-
Notifications
You must be signed in to change notification settings - Fork 398
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
### Description Some chains like zkSync do not support eip1167 (minimal/meta) proxies. This PR adds an alternative storage based multisig and aggregation ISM for use on these chains. ### Drive-by changes Simplify CLI multisig interactive config builder. Remove stale multisig config. ### Related issues None ### Backward compatibility Yes, relayer already supports this module type ### Testing Contract unit tests Manual CLI tests ![Screenshot 2024-10-02 at 4 05 08 PM](https://github.com/user-attachments/assets/c7fec896-ea7c-4fd9-a313-463168e66a82)
- Loading branch information
Showing
23 changed files
with
549 additions
and
155 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
--- | ||
'@hyperlane-xyz/cli': minor | ||
'@hyperlane-xyz/sdk': minor | ||
'@hyperlane-xyz/core': minor | ||
--- | ||
|
||
Add storage based multisig ISM types |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
// SPDX-License-Identifier: MIT OR Apache-2.0 | ||
pragma solidity >=0.8.0; | ||
|
||
interface IThresholdAddressFactory { | ||
function deploy( | ||
address[] calldata _values, | ||
uint8 _threshold | ||
) external returns (address); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
89 changes: 89 additions & 0 deletions
89
solidity/contracts/isms/aggregation/StorageAggregationIsm.sol
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
// SPDX-License-Identifier: MIT OR Apache-2.0 | ||
pragma solidity >=0.8.0; | ||
|
||
// ============ Internal Imports ============ | ||
import {AbstractAggregationIsm} from "./AbstractAggregationIsm.sol"; | ||
import {IInterchainSecurityModule} from "../../interfaces/IInterchainSecurityModule.sol"; | ||
import {IThresholdAddressFactory} from "../../interfaces/IThresholdAddressFactory.sol"; | ||
import {MinimalProxy} from "../../libs/MinimalProxy.sol"; | ||
import {PackageVersioned} from "../../PackageVersioned.sol"; | ||
|
||
// ============ External Imports ============ | ||
import {Ownable2StepUpgradeable} from "@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol"; | ||
|
||
contract StorageAggregationIsm is | ||
AbstractAggregationIsm, | ||
Ownable2StepUpgradeable | ||
{ | ||
address[] public modules; | ||
uint8 public threshold; | ||
|
||
event ModulesAndThresholdSet(address[] modules, uint8 threshold); | ||
|
||
constructor( | ||
address[] memory _modules, | ||
uint8 _threshold | ||
) Ownable2StepUpgradeable() { | ||
modules = _modules; | ||
threshold = _threshold; | ||
_disableInitializers(); | ||
} | ||
|
||
function initialize( | ||
address _owner, | ||
address[] memory _modules, | ||
uint8 _threshold | ||
) external initializer { | ||
__Ownable2Step_init(); | ||
setModulesAndThreshold(_modules, _threshold); | ||
_transferOwnership(_owner); | ||
} | ||
|
||
function setModulesAndThreshold( | ||
address[] memory _modules, | ||
uint8 _threshold | ||
) public onlyOwner { | ||
require( | ||
0 < _threshold && _threshold <= _modules.length, | ||
"Invalid threshold" | ||
); | ||
modules = _modules; | ||
threshold = _threshold; | ||
emit ModulesAndThresholdSet(_modules, _threshold); | ||
} | ||
|
||
function modulesAndThreshold( | ||
bytes calldata /* _message */ | ||
) public view override returns (address[] memory, uint8) { | ||
return (modules, threshold); | ||
} | ||
} | ||
|
||
contract StorageAggregationIsmFactory is | ||
IThresholdAddressFactory, | ||
PackageVersioned | ||
{ | ||
address public immutable implementation; | ||
|
||
constructor() { | ||
implementation = address( | ||
new StorageAggregationIsm(new address[](1), 1) | ||
); | ||
} | ||
|
||
/** | ||
* @notice Emitted when a multisig module is deployed | ||
* @param module The deployed ISM | ||
*/ | ||
event ModuleDeployed(address module); | ||
|
||
// ============ External Functions ============ | ||
function deploy( | ||
address[] calldata _modules, | ||
uint8 _threshold | ||
) external returns (address ism) { | ||
ism = MinimalProxy.create(implementation); | ||
emit ModuleDeployed(ism); | ||
StorageAggregationIsm(ism).initialize(msg.sender, _modules, _threshold); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
143 changes: 143 additions & 0 deletions
143
solidity/contracts/isms/multisig/StorageMultisigIsm.sol
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,143 @@ | ||
// SPDX-License-Identifier: MIT OR Apache-2.0 | ||
pragma solidity >=0.8.0; | ||
|
||
// ============ Internal Imports ============ | ||
import {AbstractMultisigIsm} from "./AbstractMultisigIsm.sol"; | ||
import {AbstractMerkleRootMultisigIsm} from "./AbstractMerkleRootMultisigIsm.sol"; | ||
import {AbstractMessageIdMultisigIsm} from "./AbstractMessageIdMultisigIsm.sol"; | ||
import {IInterchainSecurityModule} from "../../interfaces/IInterchainSecurityModule.sol"; | ||
import {IThresholdAddressFactory} from "../../interfaces/IThresholdAddressFactory.sol"; | ||
import {MinimalProxy} from "../../libs/MinimalProxy.sol"; | ||
import {PackageVersioned} from "../../PackageVersioned.sol"; | ||
|
||
// ============ External Imports ============ | ||
import {Ownable2StepUpgradeable} from "@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol"; | ||
|
||
abstract contract AbstractStorageMultisigIsm is | ||
AbstractMultisigIsm, | ||
Ownable2StepUpgradeable | ||
{ | ||
address[] public validators; | ||
uint8 public threshold; | ||
|
||
event ValidatorsAndThresholdSet(address[] validators, uint8 threshold); | ||
|
||
constructor( | ||
address[] memory _validators, | ||
uint8 _threshold | ||
) Ownable2StepUpgradeable() { | ||
validators = _validators; | ||
threshold = _threshold; | ||
_disableInitializers(); | ||
} | ||
|
||
function initialize( | ||
address _owner, | ||
address[] memory _validators, | ||
uint8 _threshold | ||
) external initializer { | ||
__Ownable2Step_init(); | ||
setValidatorsAndThreshold(_validators, _threshold); | ||
_transferOwnership(_owner); | ||
} | ||
|
||
function setValidatorsAndThreshold( | ||
address[] memory _validators, | ||
uint8 _threshold | ||
) public onlyOwner { | ||
require( | ||
0 < _threshold && _threshold <= _validators.length, | ||
"Invalid threshold" | ||
); | ||
validators = _validators; | ||
threshold = _threshold; | ||
emit ValidatorsAndThresholdSet(_validators, _threshold); | ||
} | ||
|
||
function validatorsAndThreshold( | ||
bytes calldata /* _message */ | ||
) public view override returns (address[] memory, uint8) { | ||
return (validators, threshold); | ||
} | ||
} | ||
|
||
contract StorageMerkleRootMultisigIsm is | ||
AbstractMerkleRootMultisigIsm, | ||
AbstractStorageMultisigIsm | ||
{ | ||
uint8 public constant moduleType = | ||
uint8(IInterchainSecurityModule.Types.MERKLE_ROOT_MULTISIG); | ||
|
||
constructor( | ||
address[] memory _validators, | ||
uint8 _threshold | ||
) AbstractStorageMultisigIsm(_validators, _threshold) {} | ||
} | ||
|
||
contract StorageMessageIdMultisigIsm is | ||
AbstractMessageIdMultisigIsm, | ||
AbstractStorageMultisigIsm | ||
{ | ||
uint8 public constant moduleType = | ||
uint8(IInterchainSecurityModule.Types.MESSAGE_ID_MULTISIG); | ||
|
||
constructor( | ||
address[] memory _validators, | ||
uint8 _threshold | ||
) AbstractStorageMultisigIsm(_validators, _threshold) {} | ||
} | ||
|
||
abstract contract StorageMultisigIsmFactory is | ||
IThresholdAddressFactory, | ||
PackageVersioned | ||
{ | ||
/** | ||
* @notice Emitted when a multisig module is deployed | ||
* @param module The deployed ISM | ||
*/ | ||
event ModuleDeployed(address module); | ||
|
||
// ============ External Functions ============ | ||
function deploy( | ||
address[] calldata _validators, | ||
uint8 _threshold | ||
) external returns (address ism) { | ||
ism = MinimalProxy.create(implementation()); | ||
emit ModuleDeployed(ism); | ||
AbstractStorageMultisigIsm(ism).initialize( | ||
msg.sender, | ||
_validators, | ||
_threshold | ||
); | ||
} | ||
|
||
function implementation() public view virtual returns (address); | ||
} | ||
|
||
contract StorageMerkleRootMultisigIsmFactory is StorageMultisigIsmFactory { | ||
address internal immutable _implementation; | ||
|
||
constructor() { | ||
_implementation = address( | ||
new StorageMerkleRootMultisigIsm(new address[](0), 0) | ||
); | ||
} | ||
|
||
function implementation() public view override returns (address) { | ||
return _implementation; | ||
} | ||
} | ||
|
||
contract StorageMessageIdMultisigIsmFactory is StorageMultisigIsmFactory { | ||
address internal immutable _implementation; | ||
|
||
constructor() { | ||
_implementation = address( | ||
new StorageMessageIdMultisigIsm(new address[](0), 0) | ||
); | ||
} | ||
|
||
function implementation() public view override returns (address) { | ||
return _implementation; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.