MultiSignerERC7913WeightedUpgradeable
Inherits: Initializable, MultiSignerERC7913Upgradeable
*Extension of {MultiSignerERC7913} that supports weighted signatures. This contract allows assigning different weights to each signer, enabling more flexible governance schemes. For example, some signers could have higher weight than others, allowing for weighted voting or prioritized authorization. Example of usage:
contract MyWeightedMultiSignerAccount is Account, MultiSignerERC7913Weighted, Initializable {
function initialize(bytes[] memory signers, uint64[] memory weights, uint64 threshold) public initializer {
_addSigners(signers);
_setSignerWeights(signers, weights);
_setThreshold(threshold);
}
function addSigners(bytes[] memory signers) public onlyEntryPointOrSelf {
_addSigners(signers);
}
function removeSigners(bytes[] memory signers) public onlyEntryPointOrSelf {
_removeSigners(signers);
}
function setThreshold(uint64 threshold) public onlyEntryPointOrSelf {
_setThreshold(threshold);
}
function setSignerWeights(bytes[] memory signers, uint64[] memory weights) public onlyEntryPointOrSelf {
_setSignerWeights(signers, weights);
}
}
IMPORTANT: When setting a threshold value, ensure it matches the scale used for signer weights. For example, if signers have weights like 1, 2, or 3, then a threshold of 4 would require at least two signers (e.g., one with weight 1 and one with weight 3). See {signerWeight}.*
State Variables
MultiSignerERC7913WeightedStorageLocation
bytes32 private constant MultiSignerERC7913WeightedStorageLocation =
0x5ec62f110612a7ff5e720b9a2f4970583e308ad11d9cde77cb7db3ea251b1f00;
Functions
_getMultiSignerERC7913WeightedStorage
function _getMultiSignerERC7913WeightedStorage() private pure returns (MultiSignerERC7913WeightedStorage storage $);
__MultiSignerERC7913Weighted_init
function __MultiSignerERC7913Weighted_init(bytes[] memory signers_, uint64[] memory weights_, uint64 threshold_)
internal
onlyInitializing;
__MultiSignerERC7913Weighted_init_unchained
function __MultiSignerERC7913Weighted_init_unchained(
bytes[] memory signers_,
uint64[] memory weights_,
uint64 threshold_
) internal onlyInitializing;
signerWeight
Gets the weight of a signer. Returns 0 if the signer is not authorized.
function signerWeight(bytes memory signer) public view virtual returns (uint64);
totalWeight
Gets the total weight of all signers.
function totalWeight() public view virtual returns (uint64);
_setSignerWeights
Sets weights for multiple signers at once. Internal version without access control.
Requirements:
signers
and weights
arrays must have the same length. Reverts with MultiSignerERC7913WeightedMismatchedLength on mismatch.
Each signer must exist in the set of authorized signers. Otherwise reverts with {MultiSignerERC7913NonexistentSigner}
Each weight must be greater than 0. Otherwise reverts with {MultiSignerERC7913WeightedInvalidWeight}
See {_validateReachableThreshold} for the threshold validation.
Emits {ERC7913SignerWeightChanged} for each signer.
function _setSignerWeights(bytes[] memory signers, uint64[] memory weights) internal virtual;
_addSigners
See MultiSignerERC7913-_addSigners.
In cases where {totalWeight} is almost type(uint64).max
(due to a large _totalExtraWeight
), adding new
signers could cause the {totalWeight} computation to overflow. Adding a {totalWeight} calls after the new
signers are added ensures no such overflow happens.
function _addSigners(bytes[] memory newSigners) internal virtual override;
_removeSigners
See MultiSignerERC7913-_removeSigners. Just like {_addSigners}, this function does not emit {ERC7913SignerWeightChanged} events. The {ERC7913SignerRemoved} event emitted by {MultiSignerERC7913-_removeSigners} is enough to track weights here.
function _removeSigners(bytes[] memory signers) internal virtual override;
_validateReachableThreshold
Sets the threshold for the multisignature operation. Internal version without access control.
Requirements:
The totalWeight must be >=
the {threshold}. Otherwise reverts with {MultiSignerERC7913UnreachableThreshold}
NOTE: This function intentionally does not call super._validateReachableThreshold
because the base implementation
assumes each signer has a weight of 1, which is a subset of this weighted implementation. Consider that multiple
implementations of this function may exist in the contract, so important side effects may be missed
depending on the linearization order.
function _validateReachableThreshold() internal view virtual override;
_validateThreshold
Validates that the total weight of signers meets the threshold requirement.
NOTE: This function intentionally does not call super._validateThreshold
because the base implementation
assumes each signer has a weight of 1, which is a subset of this weighted implementation. Consider that multiple
implementations of this function may exist in the contract, so important side effects may be missed
depending on the linearization order.
function _validateThreshold(bytes[] memory signers) internal view virtual override returns (bool);
Events
ERC7913SignerWeightChanged
Emitted when a signer's weight is changed. NOTE: Not emitted in _addSigners or {_removeSigners}. Indexers must rely on {ERC7913SignerAdded} and {ERC7913SignerRemoved} to index a default weight of 1. See {signerWeight}.
event ERC7913SignerWeightChanged(bytes indexed signer, uint64 weight);
Errors
MultiSignerERC7913WeightedInvalidWeight
Thrown when a signer's weight is invalid.
error MultiSignerERC7913WeightedInvalidWeight(bytes signer, uint64 weight);
MultiSignerERC7913WeightedMismatchedLength
Thrown when the arrays lengths don't match. See _setSignerWeights.
error MultiSignerERC7913WeightedMismatchedLength();
Structs
MultiSignerERC7913WeightedStorage
Note: storage-location: erc7201:openzeppelin.storage.MultiSignerERC7913Weighted
struct MultiSignerERC7913WeightedStorage {
uint64 _totalExtraWeight;
mapping(bytes signer => uint64) _extraWeights;
}