Skip to content

Commit fe097cf

Browse files
Transpile a34185060
1 parent 73cfbce commit fe097cf

File tree

4 files changed

+48
-40
lines changed

4 files changed

+48
-40
lines changed

contracts/utils/cryptography/signers/MultiSignerERC7913WeightedUpgradeable.sol

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
// SPDX-License-Identifier: MIT
22
// OpenZeppelin Contracts (last updated v5.4.0-rc.1) (utils/cryptography/signers/MultiSignerERC7913Weighted.sol)
33

4-
pragma solidity ^0.8.27;
4+
pragma solidity ^0.8.26;
55

66
import {SafeCast} from "@openzeppelin/contracts/utils/math/SafeCast.sol";
77
import {MultiSignerERC7913Upgradeable} from "./MultiSignerERC7913Upgradeable.sol";
@@ -126,18 +126,22 @@ abstract contract MultiSignerERC7913WeightedUpgradeable is Initializable, MultiS
126126
uint256 extraWeightRemoved = 0;
127127
for (uint256 i = 0; i < signers.length; ++i) {
128128
bytes memory signer = signers[i];
129-
uint64 weight = weights[i];
130-
131129
require(isSigner(signer), MultiSignerERC7913NonexistentSigner(signer));
130+
131+
uint64 weight = weights[i];
132132
require(weight > 0, MultiSignerERC7913WeightedInvalidWeight(signer, weight));
133133

134134
unchecked {
135-
// Overflow impossible: weight values are bounded by uint64 and economic constraints
136-
extraWeightRemoved += $._extraWeights[signer];
137-
extraWeightAdded += $._extraWeights[signer] = weight - 1;
135+
uint64 oldExtraWeight = $._extraWeights[signer];
136+
uint64 newExtraWeight = weight - 1;
137+
138+
if (oldExtraWeight != newExtraWeight) {
139+
// Overflow impossible: weight values are bounded by uint64 and economic constraints
140+
extraWeightRemoved += oldExtraWeight;
141+
extraWeightAdded += $._extraWeights[signer] = newExtraWeight;
142+
emit ERC7913SignerWeightChanged(signer, weight);
143+
}
138144
}
139-
140-
emit ERC7913SignerWeightChanged(signer, weight);
141145
}
142146
unchecked {
143147
// Safe from underflow: `extraWeightRemoved` is bounded by `_totalExtraWeight` by construction

scripts/generate/templates/EnumerableSet.js

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -324,12 +324,12 @@ struct ${name} {
324324
* Returns true if the value was added to the set, that is if it was not
325325
* already present.
326326
*/
327-
function add(${name} storage self, ${value.type} memory value) internal returns (bool) {
328-
if (!contains(self, value)) {
329-
self._values.push(value);
327+
function add(${name} storage set, ${value.type} memory value) internal returns (bool) {
328+
if (!contains(set, value)) {
329+
set._values.push(value);
330330
// The value is stored at length-1, but we add 1 to all indexes
331331
// and use 0 as a sentinel value
332-
self._positions[value] = self._values.length;
332+
set._positions[value] = set._values.length;
333333
return true;
334334
} else {
335335
return false;
@@ -342,33 +342,33 @@ function add(${name} storage self, ${value.type} memory value) internal returns
342342
* Returns true if the value was removed from the set, that is if it was
343343
* present.
344344
*/
345-
function remove(${name} storage self, ${value.type} memory value) internal returns (bool) {
345+
function remove(${name} storage set, ${value.type} memory value) internal returns (bool) {
346346
// We cache the value's position to prevent multiple reads from the same storage slot
347-
uint256 position = self._positions[value];
347+
uint256 position = set._positions[value];
348348
349349
if (position != 0) {
350-
// Equivalent to contains(self, value)
350+
// Equivalent to contains(set, value)
351351
// To delete an element from the _values array in O(1), we swap the element to delete with the last one in
352352
// the array, and then remove the last element (sometimes called as 'swap and pop').
353353
// This modifies the order of the array, as noted in {at}.
354354
355355
uint256 valueIndex = position - 1;
356-
uint256 lastIndex = self._values.length - 1;
356+
uint256 lastIndex = set._values.length - 1;
357357
358358
if (valueIndex != lastIndex) {
359-
${value.type} memory lastValue = self._values[lastIndex];
359+
${value.type} memory lastValue = set._values[lastIndex];
360360
361361
// Move the lastValue to the index where the value to delete is
362-
self._values[valueIndex] = lastValue;
362+
set._values[valueIndex] = lastValue;
363363
// Update the tracked position of the lastValue (that was just moved)
364-
self._positions[lastValue] = position;
364+
set._positions[lastValue] = position;
365365
}
366366
367367
// Delete the slot where the moved value was stored
368-
self._values.pop();
368+
set._values.pop();
369369
370370
// Delete the tracked position for the deleted slot
371-
delete self._positions[value];
371+
delete set._positions[value];
372372
373373
return true;
374374
} else {
@@ -393,15 +393,15 @@ function clear(${name} storage set) internal {
393393
/**
394394
* @dev Returns true if the value is in the set. O(1).
395395
*/
396-
function contains(${name} storage self, ${value.type} memory value) internal view returns (bool) {
397-
return self._positions[value] != 0;
396+
function contains(${name} storage set, ${value.type} memory value) internal view returns (bool) {
397+
return set._positions[value] != 0;
398398
}
399399
400400
/**
401401
* @dev Returns the number of values on the set. O(1).
402402
*/
403-
function length(${name} storage self) internal view returns (uint256) {
404-
return self._values.length;
403+
function length(${name} storage set) internal view returns (uint256) {
404+
return set._values.length;
405405
}
406406
407407
/**
@@ -414,8 +414,8 @@ function length(${name} storage self) internal view returns (uint256) {
414414
*
415415
* - \`index\` must be strictly less than {length}.
416416
*/
417-
function at(${name} storage self, uint256 index) internal view returns (${value.type} memory) {
418-
return self._values[index];
417+
function at(${name} storage set, uint256 index) internal view returns (${value.type} memory) {
418+
return set._values[index];
419419
}
420420
421421
/**
@@ -426,8 +426,8 @@ function at(${name} storage self, uint256 index) internal view returns (${value.
426426
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
427427
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
428428
*/
429-
function values(${name} storage self) internal view returns (${value.type}[] memory) {
430-
return self._values;
429+
function values(${name} storage set) internal view returns (${value.type}[] memory) {
430+
return set._values;
431431
}
432432
433433
/**

test/account/AccountMultiSignerWeighted.test.js

Lines changed: 14 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,10 @@ describe('AccountMultiSignerWeighted', function () {
158158
await expect(this.mock.signerWeight(signer3)).to.eventually.equal(3); // unchanged
159159
});
160160

161+
it("no-op doesn't emit an event", async function () {
162+
await expect(this.mock.$_setSignerWeights([signer1], [1])).to.not.emit(this.mock, 'ERC7913SignerWeightChanged');
163+
});
164+
161165
it('cannot set weight to non-existent signer', async function () {
162166
// Reverts when setting weight for non-existent signer
163167
await expect(this.mock.$_setSignerWeights([signer4], [1]))
@@ -186,28 +190,28 @@ describe('AccountMultiSignerWeighted', function () {
186190
});
187191

188192
it('validates threshold is reachable when updating weights', async function () {
189-
// First, lower the weights so the sum is exactly 6 (just enough for threshold=6)
190-
await expect(this.mock.$_setSignerWeights([signer1, signer2, signer3], [1, 2, 3]))
193+
// First, lower the weights so the sum is exactly 9 (just enough for threshold=9)
194+
await expect(this.mock.$_setSignerWeights([signer1, signer2, signer3], [2, 3, 4]))
191195
.to.emit(this.mock, 'ERC7913SignerWeightChanged')
192-
.withArgs(signer1, 1)
196+
.withArgs(signer1, 2)
193197
.to.emit(this.mock, 'ERC7913SignerWeightChanged')
194-
.withArgs(signer2, 2)
198+
.withArgs(signer2, 3)
195199
.to.emit(this.mock, 'ERC7913SignerWeightChanged')
196-
.withArgs(signer3, 3);
200+
.withArgs(signer3, 4);
197201

198-
// Increase threshold to 6
199-
await expect(this.mock.$_setThreshold(6)).to.emit(this.mock, 'ERC7913ThresholdSet').withArgs(6);
202+
// Increase threshold to 9
203+
await expect(this.mock.$_setThreshold(9)).to.emit(this.mock, 'ERC7913ThresholdSet').withArgs(9);
200204

201205
// Now try to lower weights so their sum is less than the threshold
202-
await expect(this.mock.$_setSignerWeights([signer1, signer2, signer3], [1, 1, 1])).to.be.revertedWithCustomError(
206+
await expect(this.mock.$_setSignerWeights([signer1, signer2, signer3], [2, 2, 2])).to.be.revertedWithCustomError(
203207
this.mock,
204208
'MultiSignerERC7913UnreachableThreshold',
205209
);
206210

207211
// Try to increase threshold to be larger than the total weight
208-
await expect(this.mock.$_setThreshold(7))
212+
await expect(this.mock.$_setThreshold(10))
209213
.to.be.revertedWithCustomError(this.mock, 'MultiSignerERC7913UnreachableThreshold')
210-
.withArgs(6, 7);
214+
.withArgs(9, 10);
211215
});
212216

213217
it('reports default weight of 1 for signers without explicit weight', async function () {

0 commit comments

Comments
 (0)