Consistent addresses for upgradable contracts (#1389)

pull/1403/head
Asa Oines 2 years ago committed by GitHub
parent 4fc474ed55
commit 8f77723001
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 24
      rust/config/test/test_config.json
  2. 147
      rust/config/testnet3/testnet3_config.json
  3. 112
      solidity/contracts/isms/MultisigIsm.sol
  4. 21
      solidity/contracts/test/MysteryMath.sol
  5. 22
      solidity/contracts/test/MysteryMathV1.sol
  6. 22
      solidity/contracts/test/MysteryMathV2.sol
  7. 6
      solidity/contracts/upgrade/ProxyAdmin.sol
  8. 6
      solidity/contracts/upgrade/TransparentUpgradeableProxy.sol
  9. 98
      solidity/contracts/upgrade/UpgradeBeacon.sol
  10. 48
      solidity/contracts/upgrade/UpgradeBeaconController.sol
  11. 176
      solidity/contracts/upgrade/UpgradeBeaconProxy.sol
  12. 145
      solidity/test/isms/multisigIsm.test.ts
  13. 74
      solidity/test/lib/upgrade.ts
  14. 45
      solidity/test/upgrade.test.ts
  15. 516
      typescript/infra/config/environments/testnet3/core/verification/verification.json
  16. 8
      typescript/infra/scripts/core.ts
  17. 63
      typescript/infra/src/core/deploy.ts
  18. 6
      typescript/infra/src/scraper/deploy.ts
  19. 14
      typescript/infra/test/core.test.ts
  20. 96
      typescript/sdk/src/consts/environments/mainnet.json
  21. 54
      typescript/sdk/src/consts/environments/test.json
  22. 96
      typescript/sdk/src/consts/environments/testnet2.json
  23. 139
      typescript/sdk/src/consts/environments/testnet3.json
  24. 21
      typescript/sdk/src/core/TestCoreDeployer.ts
  25. 14
      typescript/sdk/src/core/contracts.ts
  26. 19
      typescript/sdk/src/deploy/HyperlaneAppChecker.ts
  27. 165
      typescript/sdk/src/deploy/HyperlaneDeployer.ts
  28. 15
      typescript/sdk/src/deploy/core/HyperlaneCoreChecker.ts
  29. 142
      typescript/sdk/src/deploy/core/HyperlaneCoreDeployer.ts
  30. 43
      typescript/sdk/src/deploy/proxy.ts
  31. 8
      typescript/sdk/src/index.ts
  32. 7
      typescript/sdk/src/proxy.ts

@ -5,9 +5,9 @@
"name": "test1",
"domain": "13371",
"addresses": {
"mailbox": "0xB7f8BC63BbcaD18155201308C8f3540b07f84F5e",
"interchainGasPaymaster": "0xCf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc9",
"multisigIsm": "0xDc64a140Aa3E981100a9becA4E685f962f0cF6C9"
"mailbox": "0xa513E6E4b8f2a923D98304ec87F64353C4D5C853",
"interchainGasPaymaster": "0x5FC8d32690cc91D4c39d9d3abcBD16989F875707",
"multisigIsm": "0x5FbDB2315678afecb367f032d93F642f64180aa3"
},
"rpcStyle": "ethereum",
"finalityBlocks": "0",
@ -23,9 +23,9 @@
"name": "test2",
"domain": "13372",
"addresses": {
"mailbox": "0x322813Fd9A801c5507c9de605d63CEA4f2CE6c44",
"interchainGasPaymaster": "0x0B306BF915C4d645ff596e518fAf3F9669b97016",
"multisigIsm": "0x959922bE3CAee4b8Cd9a407cc3ac1C251C2007B1"
"mailbox": "0x0B306BF915C4d645ff596e518fAf3F9669b97016",
"interchainGasPaymaster": "0x0DCd1Bf9A1b36cE34237eEaFef220932846BCD82",
"multisigIsm": "0x2279B7A0a67DB372996a5FaB50D91eAA73d2eBe6"
},
"rpcStyle": "ethereum",
"finalityBlocks": "1",
@ -34,16 +34,16 @@
"url": ""
},
"index": {
"from": "16"
"from": "13"
}
},
"test3": {
"name": "test3",
"domain": "13373",
"addresses": {
"mailbox": "0x1613beB3B2C4f22Ee086B2b38C1476A3cE7f78E8",
"interchainGasPaymaster": "0x09635F643e140090A9A8Dcd712eD6285858ceBef",
"multisigIsm": "0xc5a5C42992dECbae36851359345FE25997F5C42d"
"mailbox": "0x322813Fd9A801c5507c9de605d63CEA4f2CE6c44",
"interchainGasPaymaster": "0x59b670e9fA9D0A427751Af201D676719a970857b",
"multisigIsm": "0x959922bE3CAee4b8Cd9a407cc3ac1C251C2007B1"
},
"rpcStyle": "ethereum",
"finalityBlocks": "2",
@ -52,7 +52,7 @@
"url": ""
},
"index": {
"from": "28"
"from": "21"
}
}
},
@ -62,4 +62,4 @@
"level": "debug",
"fmt": "json"
}
}
}

@ -1,151 +1,6 @@
{
"environment": "testnet3",
"chains": {
"alfajores": {
"name": "alfajores",
"domain": "44787",
"addresses": {
"mailbox": "0x4dea8886b520450aD19e35206dDFb951fFcDFb17",
"interchainGasPaymaster": "0x974cC4516FdEE100c8f8f5338C7461DfD544a884",
"multisigIsm": "0xcF6bA9D5f6101232C065aD3462F365f0D1bD7fb4"
},
"rpcStyle": "ethereum",
"finalityBlocks": "0",
"connection": {
"type": "http",
"url": ""
},
"index": {
"from": "14863532"
}
},
"fuji": {
"name": "fuji",
"domain": "43113",
"addresses": {
"mailbox": "0x9BA855357227f62263683A275291f3a923C13903",
"interchainGasPaymaster": "0xe0a9bf21Ddee4a0B0F354b25981924A767C6183E",
"multisigIsm": "0x12Ac803eeD2707D5845e7c5E73BeDf0Dca331555"
},
"rpcStyle": "ethereum",
"finalityBlocks": "3",
"connection": {
"type": "http",
"url": ""
},
"index": {
"from": "16330615"
}
},
"mumbai": {
"name": "mumbai",
"domain": "80001",
"addresses": {
"mailbox": "0x2342eb763F3efeFE5A0BA2a21481fD5Ba7f59A90",
"interchainGasPaymaster": "0x0b8978f247fEFae77dE328706fD5895B187BCa95",
"multisigIsm": "0x4E95F7Bf8a4D963C593A25bb6A8C83942211104A"
},
"rpcStyle": "ethereum",
"finalityBlocks": "32",
"connection": {
"type": "http",
"url": ""
},
"index": {
"from": "29390033"
}
},
"bsctestnet": {
"name": "bsctestnet",
"domain": "97",
"addresses": {
"mailbox": "0x056d6CAe959B4266291d6BCB3364cdF1Bc8C9814",
"interchainGasPaymaster": "0x81bbe1D62798A9c0ca42F1a41834a6C5E659cAEd",
"multisigIsm": "0xdE0Cbd9A17A99348785DA7625cB44a24b5A337be"
},
"rpcStyle": "ethereum",
"finalityBlocks": "9",
"connection": {
"type": "http",
"url": ""
},
"index": {
"from": "25001629"
}
},
"goerli": {
"name": "goerli",
"domain": "5",
"addresses": {
"mailbox": "0x5D5F9793Bc52CfF1522cDEf7206470717d2bae29",
"interchainGasPaymaster": "0xaC47a6318AdF660ea24994617B27171e85c6b5BE",
"multisigIsm": "0x2a13C3bD245166D1C6515f15fcd1441367FAb675"
},
"rpcStyle": "ethereum",
"finalityBlocks": "2",
"connection": {
"type": "http",
"url": ""
},
"index": {
"from": "8039005"
}
},
"moonbasealpha": {
"name": "moonbasealpha",
"domain": "1287",
"addresses": {
"mailbox": "0x711166cE892CBa0Fc01FdD74cFBE73b027678e15",
"interchainGasPaymaster": "0x1fe349d93078B26C8c7350A401e2B60f100952F5",
"multisigIsm": "0xD221ffdAa65518BF56c8623e04eA0380CE1BfaE2"
},
"rpcStyle": "ethereum",
"finalityBlocks": "1",
"connection": {
"type": "http",
"url": ""
},
"index": {
"from": "3265472"
}
},
"optimismgoerli": {
"name": "optimismgoerli",
"domain": "420",
"addresses": {
"mailbox": "0xd876C01aB40e8cE42Db417fBC79c726d45504dE4",
"interchainGasPaymaster": "0x62A3fC7873AC96fFF1975663Aa41Ab9100cDe2FB",
"multisigIsm": "0xDA7f1997D52a5f442E83948F7529BceAA6e1fda2"
},
"rpcStyle": "ethereum",
"finalityBlocks": "1",
"connection": {
"type": "http",
"url": ""
},
"index": {
"from": "3055263"
}
},
"arbitrumgoerli": {
"name": "arbitrumgoerli",
"domain": "421613",
"addresses": {
"mailbox": "0x957ff8ca77Af405D620e47350327fDA24b83070b",
"interchainGasPaymaster": "0x0C16e730090cb681460516428c3b2D1BBCB1b647",
"multisigIsm": "0x890eB21B76DCB165A1807cBE279f883716eA47D4"
},
"rpcStyle": "ethereum",
"finalityBlocks": "1",
"connection": {
"type": "http",
"url": ""
},
"index": {
"from": "1941997"
}
}
},
"chains": {},
"signers": {},
"db": "db_path",
"tracing": {

@ -44,13 +44,11 @@ contract MultisigIsm is IMultisigIsm, Ownable {
* @param domain The remote domain of the validator set.
* @param validator The address of the validator.
* @param validatorCount The number of enrolled validators in the validator set.
* @param commitment A commitment to the validator set and threshold.
*/
event ValidatorEnrolled(
uint32 indexed domain,
address indexed validator,
uint256 validatorCount,
bytes32 commitment
uint256 validatorCount
);
/**
@ -58,26 +56,26 @@ contract MultisigIsm is IMultisigIsm, Ownable {
* @param domain The remote domain of the validator set.
* @param validator The address of the validator.
* @param validatorCount The number of enrolled validators in the validator set.
* @param commitment A commitment to the validator set and threshold.
*/
event ValidatorUnenrolled(
uint32 indexed domain,
address indexed validator,
uint256 validatorCount,
bytes32 commitment
uint256 validatorCount
);
/**
* @notice Emitted when the quorum threshold is set.
* @param domain The remote domain of the validator set.
* @param threshold The new quorum threshold.
*/
event ThresholdSet(uint32 indexed domain, uint8 threshold);
/**
* @notice Emitted when the validator set or threshold changes.
* @param domain The remote domain of the validator set.
* @param commitment A commitment to the validator set and threshold.
*/
event ThresholdSet(
uint32 indexed domain,
uint256 threshold,
bytes32 commitment
);
event CommitmentUpdated(uint32 domain, bytes32 commitment);
// ============ Constructor ============
@ -86,6 +84,27 @@ contract MultisigIsm is IMultisigIsm, Ownable {
// ============ External Functions ============
/**
* @notice Enrolls multiple validators into a validator set.
* @dev Reverts if `_validator` is already in the validator set.
* @param _domains The remote domains of the validator sets.
* @param _validators The validators to add to the validator sets.
* @dev _validators[i] are the validators to enroll for _domains[i].
*/
function enrollValidators(
uint32[] calldata _domains,
address[][] calldata _validators
) external onlyOwner {
require(_domains.length == _validators.length, "!length");
for (uint256 i = 0; i < _domains.length; i += 1) {
address[] calldata _domainValidators = _validators[i];
for (uint256 j = 0; j < _domainValidators.length; j += 1) {
_enrollValidator(_domains[i], _domainValidators[j]);
}
_updateCommitment(_domains[i]);
}
}
/**
* @notice Enrolls a validator into a validator set.
* @dev Reverts if `_validator` is already in the validator set.
@ -96,15 +115,8 @@ contract MultisigIsm is IMultisigIsm, Ownable {
external
onlyOwner
{
require(_validator != address(0), "zero address");
require(validatorSet[_domain].add(_validator), "already enrolled");
bytes32 _commitment = _updateCommitment(_domain);
emit ValidatorEnrolled(
_domain,
_validator,
validatorCount(_domain),
_commitment
);
_enrollValidator(_domain, _validator);
_updateCommitment(_domain);
}
/**
@ -123,28 +135,23 @@ contract MultisigIsm is IMultisigIsm, Ownable {
_validatorCount >= threshold[_domain],
"violates quorum threshold"
);
bytes32 _commitment = _updateCommitment(_domain);
emit ValidatorUnenrolled(
_domain,
_validator,
_validatorCount,
_commitment
);
_updateCommitment(_domain);
emit ValidatorUnenrolled(_domain, _validator, _validatorCount);
}
/**
* @notice Sets the quorum threshold.
* @param _domain The remote domain of the validator set.
* @param _threshold The new quorum threshold.
* @notice Sets the quorum threshold for multiple domains.
* @param _domains The remote domains of the validator sets.
* @param _thresholds The new quorum thresholds.
*/
function setThreshold(uint32 _domain, uint8 _threshold) external onlyOwner {
require(
_threshold > 0 && _threshold <= validatorCount(_domain),
"!range"
);
threshold[_domain] = _threshold;
bytes32 _commitment = _updateCommitment(_domain);
emit ThresholdSet(_domain, _threshold, _commitment);
function setThresholds(
uint32[] calldata _domains,
uint8[] calldata _thresholds
) external onlyOwner {
require(_domains.length == _thresholds.length, "!length");
for (uint256 i = 0; i < _domains.length; i += 1) {
setThreshold(_domains[i], _thresholds[i]);
}
}
/**
@ -164,6 +171,22 @@ contract MultisigIsm is IMultisigIsm, Ownable {
// ============ Public Functions ============
/**
* @notice Sets the quorum threshold.
* @param _domain The remote domain of the validator set.
* @param _threshold The new quorum threshold.
*/
function setThreshold(uint32 _domain, uint8 _threshold) public onlyOwner {
require(
_threshold > 0 && _threshold <= validatorCount(_domain),
"!range"
);
threshold[_domain] = _threshold;
emit ThresholdSet(_domain, _threshold);
_updateCommitment(_domain);
}
/**
* @notice Verifies that a quorum of the origin domain's validators signed
* a checkpoint, and verifies the merkle proof of `_message` against that
@ -207,6 +230,18 @@ contract MultisigIsm is IMultisigIsm, Ownable {
// ============ Internal Functions ============
/**
* @notice Enrolls a validator into a validator set.
* @dev Reverts if `_validator` is already in the validator set.
* @param _domain The remote domain of the validator set.
* @param _validator The validator to add to the validator set.
*/
function _enrollValidator(uint32 _domain, address _validator) internal {
require(_validator != address(0), "zero address");
require(validatorSet[_domain].add(_validator), "already enrolled");
emit ValidatorEnrolled(_domain, _validator, validatorCount(_domain));
}
/**
* @notice Updates the commitment to the validator set for `_domain`.
* @param _domain The remote domain of the validator set.
@ -219,6 +254,7 @@ contract MultisigIsm is IMultisigIsm, Ownable {
abi.encodePacked(_threshold, _validators)
);
commitment[_domain] = _commitment;
emit CommitmentUpdated(_domain, _commitment);
return _commitment;
}

@ -1,21 +0,0 @@
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;
abstract contract MysteryMath {
uint256 public stateVar;
function setState(uint256 _var) external {
stateVar = _var;
}
function getState() external view returns (uint256) {
return stateVar;
}
function doMath(uint256 a, uint256 b)
external
pure
virtual
returns (uint256 _result);
}

@ -1,22 +0,0 @@
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;
import "./MysteryMath.sol";
contract MysteryMathV1 is MysteryMath {
uint32 public immutable version;
constructor() {
version = 1;
}
function doMath(uint256 a, uint256 b)
external
pure
override
returns (uint256 _result)
{
_result = a + b;
}
}

@ -1,22 +0,0 @@
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;
import "./MysteryMath.sol";
contract MysteryMathV2 is MysteryMath {
uint32 public immutable version;
constructor() {
version = 2;
}
function doMath(uint256 a, uint256 b)
external
pure
override
returns (uint256 _result)
{
_result = a * b;
}
}

@ -0,0 +1,6 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (proxy/transparent/ProxyAdmin.sol)
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol";

@ -0,0 +1,6 @@
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (proxy/transparent/TransparentUpgradeableProxy.sol)
pragma solidity ^0.8.0;
import "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol";

@ -1,98 +0,0 @@
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;
// ============ External Imports ============
import {Address} from "@openzeppelin/contracts/utils/Address.sol";
/**
* @title UpgradeBeacon
* @notice Stores the address of an implementation contract
* and allows a controller to upgrade the implementation address
* @dev This implementation combines the gas savings of having no function selectors
* found in 0age's implementation:
* https://github.com/dharma-eng/dharma-smart-wallet/blob/master/contracts/proxies/smart-wallet/UpgradeBeaconProxyV1.sol
* With the added niceties of a safety check that each implementation is a contract
* and an Upgrade event emitted each time the implementation is changed
* found in OpenZeppelin's implementation:
* https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/proxy/beacon/BeaconProxy.sol
*/
contract UpgradeBeacon {
// ============ Immutables ============
// The controller is capable of modifying the implementation address
address private immutable controller;
// ============ Private Storage Variables ============
// The implementation address is held in storage slot zero.
address private implementation;
// ============ Events ============
// Upgrade event is emitted each time the implementation address is set
// (including deployment)
event Upgrade(address indexed implementation);
// ============ Constructor ============
/**
* @notice Validate the initial implementation and store it.
* Store the controller immutably.
* @param _initialImplementation Address of the initial implementation contract
* @param _controller Address of the controller who can upgrade the implementation
*/
constructor(address _initialImplementation, address _controller) payable {
_setImplementation(_initialImplementation);
controller = _controller;
}
// ============ External Functions ============
/**
* @notice For all callers except the controller, return the current implementation address.
* If called by the Controller, update the implementation address
* to the address passed in the calldata.
* Note: this requires inline assembly because Solidity fallback functions
* do not natively take arguments or return values.
*/
fallback() external payable {
if (msg.sender != controller) {
// if not called by the controller,
// load implementation address from storage slot zero
// and return it.
assembly {
mstore(0, sload(0))
return(0, 32)
}
} else {
// if called by the controller,
// load new implementation address from the first word of the calldata
address _newImplementation;
assembly {
_newImplementation := calldataload(0)
}
// set the new implementation
_setImplementation(_newImplementation);
}
}
// ============ Private Functions ============
/**
* @notice Perform checks on the new implementation address
* then upgrade the stored implementation.
* @param _newImplementation Address of the new implementation contract which will replace the old one
*/
function _setImplementation(address _newImplementation) private {
// Require that the new implementation is different from the current one
require(implementation != _newImplementation, "!upgrade");
// Require that the new implementation is a contract
require(
Address.isContract(_newImplementation),
"implementation !contract"
);
// set the new implementation
implementation = _newImplementation;
emit Upgrade(_newImplementation);
}
}

@ -1,48 +0,0 @@
// SPDX-License-Identifier: MIT OR Apache-2.0
pragma solidity >=0.8.0;
// ============ Internal Imports ============
import {UpgradeBeacon} from "./UpgradeBeacon.sol";
// ============ External Imports ============
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import {Address} from "@openzeppelin/contracts/utils/Address.sol";
/**
* @title UpgradeBeaconController
* @notice Set as the controller of UpgradeBeacon contract(s),
* capable of changing their stored implementation address.
* @dev This implementation is a minimal version inspired by 0age's implementation:
* https://github.com/dharma-eng/dharma-smart-wallet/blob/master/contracts/upgradeability/DharmaUpgradeBeaconController.sol
*/
contract UpgradeBeaconController is Ownable {
// ============ Events ============
event BeaconUpgraded(address indexed beacon, address implementation);
// ============ External Functions ============
/**
* @notice Modify the implementation stored in the UpgradeBeacon,
* which will upgrade the implementation used by all
* Proxy contracts using that UpgradeBeacon
* @param _beacon Address of the UpgradeBeacon which will be updated
* @param _implementation Address of the Implementation contract to upgrade the Beacon to
*/
function upgrade(address _beacon, address _implementation)
external
onlyOwner
{
// Require that the beacon is a contract
require(Address.isContract(_beacon), "beacon !contract");
// Call into beacon and supply address of new implementation to update it.
(bool _success, ) = _beacon.call(abi.encode(_implementation));
// Revert with message on failure (i.e. if the beacon is somehow incorrect).
if (!_success) {
assembly {
returndatacopy(0, 0, returndatasize())
revert(0, returndatasize())
}
}
emit BeaconUpgraded(_beacon, _implementation);
}
}

@ -1,176 +0,0 @@
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;
// ============ External Imports ============
import {Address} from "@openzeppelin/contracts/utils/Address.sol";
/**
* @title UpgradeBeaconProxy
* @notice
* Proxy contract which delegates all logic, including initialization,
* to an implementation contract.
* The implementation contract is stored within an Upgrade Beacon contract;
* the implementation contract can be changed by performing an upgrade on the Upgrade Beacon contract.
* The Upgrade Beacon contract for this Proxy is immutably specified at deployment.
* @dev This implementation combines the gas savings of keeping the UpgradeBeacon address outside of contract storage
* found in 0age's implementation:
* https://github.com/dharma-eng/dharma-smart-wallet/blob/master/contracts/proxies/smart-wallet/UpgradeBeaconProxyV1.sol
* With the added safety checks that the UpgradeBeacon and implementation are contracts at time of deployment
* found in OpenZeppelin's implementation:
* https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/proxy/beacon/BeaconProxy.sol
*/
contract UpgradeBeaconProxy {
// ============ Immutables ============
// Upgrade Beacon address is immutable (therefore not kept in contract storage)
address private immutable upgradeBeacon;
// ============ Constructor ============
/**
* @notice Validate that the Upgrade Beacon is a contract, then set its
* address immutably within this contract.
* Validate that the implementation is also a contract,
* Then call the initialization function defined at the implementation.
* The deployment will revert and pass along the
* revert reason if the initialization function reverts.
* @param _upgradeBeacon Address of the Upgrade Beacon to be stored immutably in the contract
* @param _initializationCalldata Calldata supplied when calling the initialization function
*/
constructor(address _upgradeBeacon, bytes memory _initializationCalldata)
payable
{
// Validate the Upgrade Beacon is a contract
require(Address.isContract(_upgradeBeacon), "beacon !contract");
// set the Upgrade Beacon
upgradeBeacon = _upgradeBeacon;
// Validate the implementation is a contract
address _implementation = _getImplementation(_upgradeBeacon);
require(
Address.isContract(_implementation),
"beacon implementation !contract"
);
// Call the initialization function on the implementation
if (_initializationCalldata.length > 0) {
_initialize(_implementation, _initializationCalldata);
}
}
// ============ External Functions ============
/**
* @notice Forwards all calls with data to _fallback()
* No public functions are declared on the contract, so all calls hit fallback
*/
fallback() external payable {
_fallback();
}
/**
* @notice Forwards all calls with no data to _fallback()
*/
receive() external payable {
_fallback();
}
// ============ Private Functions ============
/**
* @notice Call the initialization function on the implementation
* Used at deployment to initialize the proxy
* based on the logic for initialization defined at the implementation
* @param _implementation - Contract to which the initalization is delegated
* @param _initializationCalldata - Calldata supplied when calling the initialization function
*/
function _initialize(
address _implementation,
bytes memory _initializationCalldata
) private {
// Delegatecall into the implementation, supplying initialization calldata.
(bool _ok, ) = _implementation.delegatecall(_initializationCalldata);
// Revert and include revert data if delegatecall to implementation reverts.
if (!_ok) {
assembly {
returndatacopy(0, 0, returndatasize())
revert(0, returndatasize())
}
}
}
/**
* @notice Delegates function calls to the implementation contract returned by the Upgrade Beacon
*/
function _fallback() private {
_delegate(_getImplementation());
}
/**
* @notice Delegate function execution to the implementation contract
* @dev This is a low level function that doesn't return to its internal
* call site. It will return whatever is returned by the implementation to the
* external caller, reverting and returning the revert data if implementation
* reverts.
* @param _implementation - Address to which the function execution is delegated
*/
function _delegate(address _implementation) private {
assembly {
// Copy msg.data. We take full control of memory in this inline assembly
// block because it will not return to Solidity code. We overwrite the
// Solidity scratch pad at memory position 0.
calldatacopy(0, 0, calldatasize())
// Delegatecall to the implementation, supplying calldata and gas.
// Out and outsize are set to zero - instead, use the return buffer.
let result := delegatecall(
gas(),
_implementation,
0,
calldatasize(),
0,
0
)
// Copy the returned data from the return buffer.
returndatacopy(0, 0, returndatasize())
switch result
// Delegatecall returns 0 on error.
case 0 {
revert(0, returndatasize())
}
default {
return(0, returndatasize())
}
}
}
/**
* @notice Call the Upgrade Beacon to get the current implementation contract address
* @return _implementation Address of the current implementation.
*/
function _getImplementation()
private
view
returns (address _implementation)
{
_implementation = _getImplementation(upgradeBeacon);
}
/**
* @notice Call the Upgrade Beacon to get the current implementation contract address
* @dev _upgradeBeacon is passed as a parameter so that
* we can also use this function in the constructor,
* where we can't access immutable variables.
* @param _upgradeBeacon Address of the UpgradeBeacon storing the current implementation
* @return _implementation Address of the current implementation.
*/
function _getImplementation(address _upgradeBeacon)
private
view
returns (address _implementation)
{
// Get the current implementation address from the upgrade beacon.
(bool _ok, bytes memory _returnData) = _upgradeBeacon.staticcall("");
// Revert and pass along revert message if call to upgrade beacon reverts.
require(_ok, string(_returnData));
// Set the implementation to the address returned from the upgrade beacon.
_implementation = abi.decode(_returnData, (address));
}
}

@ -54,6 +54,61 @@ describe('MultisigIsm', async () => {
});
});
describe('#enrollValidators', () => {
let validatorAddresses: string[];
const domains = [ORIGIN_DOMAIN, DESTINATION_DOMAIN];
before(async () => {
validatorAddresses = validators.map((v) => v.address);
});
it('enrolls validators into multiple validator sets', async () => {
await multisigIsm.enrollValidators(
domains,
domains.map(() => validatorAddresses),
);
await Promise.all(
domains.map(async (domain) => {
expect(await multisigIsm.validators(domain)).to.deep.equal(
validatorAddresses,
);
}),
);
});
it('emits the ValidatorEnrolled event', async () => {
expect(
await multisigIsm.enrollValidators(
domains,
domains.map(() => validatorAddresses),
),
)
.to.emit(multisigIsm, 'ValidatorEnrolled')
.withArgs(ORIGIN_DOMAIN, validatorAddresses[0], 1);
});
it('emits the CommitmentUpdated event', async () => {
const expectedCommitment = getCommitment(0, validatorAddresses);
expect(
await multisigIsm.enrollValidators(
domains,
domains.map(() => validatorAddresses),
),
)
.to.emit(multisigIsm, 'CommitmentUpdated')
.withArgs(ORIGIN_DOMAIN, expectedCommitment);
});
it('reverts when called by a non-owner', async () => {
await expect(
multisigIsm.connect(nonOwner).enrollValidators(
domains,
domains.map(() => validatorAddresses),
),
).to.be.revertedWith('Ownable: caller is not the owner');
});
});
describe('#enrollValidator', () => {
it('enrolls a validator into the validator set', async () => {
await multisigIsm.enrollValidator(ORIGIN_DOMAIN, validators[0].address);
@ -64,12 +119,20 @@ describe('MultisigIsm', async () => {
});
it('emits the ValidatorEnrolled event', async () => {
const expectedCommitment = getCommitment(0, [validators[0].address]);
expect(
await multisigIsm.enrollValidator(ORIGIN_DOMAIN, validators[0].address),
)
.to.emit(multisigIsm, 'ValidatorEnrolled')
.withArgs(ORIGIN_DOMAIN, validators[0].address, 1, expectedCommitment);
.withArgs(ORIGIN_DOMAIN, validators[0].address, 1);
});
it('emits the CommitmentUpdated event', async () => {
const expectedCommitment = getCommitment(0, [validators[0].address]);
expect(
await multisigIsm.enrollValidator(ORIGIN_DOMAIN, validators[0].address),
)
.to.emit(multisigIsm, 'CommitmentUpdated')
.withArgs(ORIGIN_DOMAIN, expectedCommitment);
});
it('reverts if the validator is already enrolled', async () => {
@ -100,7 +163,6 @@ describe('MultisigIsm', async () => {
});
it('emits the ValidatorUnenrolled event', async () => {
const expectedCommitment = getCommitment(0, []);
expect(
await multisigIsm.unenrollValidator(
ORIGIN_DOMAIN,
@ -108,7 +170,19 @@ describe('MultisigIsm', async () => {
),
)
.to.emit(multisigIsm, 'ValidatorUnenrolled')
.withArgs(ORIGIN_DOMAIN, validators[0].address, 0, expectedCommitment);
.withArgs(ORIGIN_DOMAIN, validators[0].address, 0);
});
it('emits the CommitmentUpdated event', async () => {
const expectedCommitment = getCommitment(0, []);
expect(
await multisigIsm.unenrollValidator(
ORIGIN_DOMAIN,
validators[0].address,
),
)
.to.emit(multisigIsm, 'CommitmentUpdated')
.withArgs(ORIGIN_DOMAIN, expectedCommitment);
});
it('reverts if the resulting validator set size will be less than the quorum threshold', async () => {
@ -134,6 +208,51 @@ describe('MultisigIsm', async () => {
});
});
describe('#setThresholds', () => {
let validatorAddresses: string[];
const domains = [ORIGIN_DOMAIN, DESTINATION_DOMAIN];
const thresholds = [2, 4];
before(async () => {
validatorAddresses = validators.map((v) => v.address);
});
beforeEach(async () => {
await multisigIsm.enrollValidators(
domains,
domains.map(() => validatorAddresses),
);
});
it('sets the quorum thresholds', async () => {
await multisigIsm.setThresholds(domains, thresholds);
await Promise.all(
domains.map(async (domain, i) => {
expect(await multisigIsm.threshold(domain)).to.equal(thresholds[i]);
}),
);
});
it('emits the SetThreshold event', async () => {
expect(await multisigIsm.setThresholds(domains, thresholds))
.to.emit(multisigIsm, 'ThresholdSet')
.withArgs(ORIGIN_DOMAIN, 2);
});
it('emits the CommitmentUpdated event', async () => {
const expectedCommitment = getCommitment(2, validatorAddresses);
expect(await multisigIsm.setThresholds(domains, thresholds))
.to.emit(multisigIsm, 'CommitmentUpdated')
.withArgs(ORIGIN_DOMAIN, expectedCommitment);
});
it('reverts when called by a non-owner', async () => {
await expect(
multisigIsm.connect(nonOwner).setThresholds(domains, thresholds),
).to.be.revertedWith('Ownable: caller is not the owner');
});
});
describe('#setThreshold', () => {
beforeEach(async () => {
// Have 2 validators to allow us to have more than 1 valid
@ -149,13 +268,19 @@ describe('MultisigIsm', async () => {
});
it('emits the SetThreshold event', async () => {
expect(await multisigIsm.setThreshold(ORIGIN_DOMAIN, 2))
.to.emit(multisigIsm, 'ThresholdSet')
.withArgs(ORIGIN_DOMAIN, 2);
});
it('emits the CommitmentUpdated event', async () => {
const expectedCommitment = getCommitment(2, [
validators[0].address,
validators[1].address,
]);
expect(await multisigIsm.setThreshold(ORIGIN_DOMAIN, 2))
.to.emit(multisigIsm, 'ThresholdSet')
.withArgs(ORIGIN_DOMAIN, 2, expectedCommitment);
.to.emit(multisigIsm, 'CommitmentUpdated')
.withArgs(ORIGIN_DOMAIN, expectedCommitment);
});
it('reverts if the new quorum threshold is zero', async () => {
@ -179,10 +304,10 @@ describe('MultisigIsm', async () => {
describe('#validators', () => {
beforeEach(async () => {
// Must be done sequentially so gas estimation is correct.
for (const v of validators) {
await multisigIsm.enrollValidator(ORIGIN_DOMAIN, v.address);
}
await multisigIsm.enrollValidators(
[ORIGIN_DOMAIN],
[validators.map((v) => v.address)],
);
});
it('returns the validators', async () => {

@ -1,74 +0,0 @@
import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers';
import { expect } from 'chai';
import {
MysteryMathV1,
MysteryMathV1__factory,
MysteryMathV2,
UpgradeBeacon,
UpgradeBeaconController,
UpgradeBeaconProxy__factory,
UpgradeBeacon__factory,
} from '../../types';
export type MysteryMathUpgrade = {
proxy: MysteryMathV1 | MysteryMathV2;
beacon: UpgradeBeacon;
implementation: MysteryMathV1 | MysteryMathV2;
};
export class UpgradeTestHelpers {
a = 5;
b = 10;
stateVar = 17;
async deployMysteryMathUpgradeSetup(
signer: SignerWithAddress,
ubc: UpgradeBeaconController,
): Promise<MysteryMathUpgrade> {
// deploy implementation
const mysteryMathFactory = new MysteryMathV1__factory(signer);
const mysteryMathImplementation = await mysteryMathFactory.deploy();
// deploy and set upgrade beacon
const beaconFactory = new UpgradeBeacon__factory(signer);
const beacon = await beaconFactory.deploy(
mysteryMathImplementation.address,
ubc.address,
);
// deploy proxy
const proxyFactory = new UpgradeBeaconProxy__factory(signer);
const upgradeBeaconProxy = await proxyFactory.deploy(beacon.address, []);
// set proxy
const proxy = mysteryMathFactory.attach(upgradeBeaconProxy.address);
// Set state of proxy
await proxy.setState(this.stateVar);
return { proxy, beacon, implementation: mysteryMathImplementation };
}
async expectMysteryMathV1(mysteryMathProxy: MysteryMathV1) {
const versionResult = await mysteryMathProxy.version();
expect(versionResult).to.equal(1);
const mathResult = await mysteryMathProxy.doMath(this.a, this.b);
expect(mathResult).to.equal(this.a + this.b);
const stateResult = await mysteryMathProxy.getState();
expect(stateResult).to.equal(this.stateVar);
}
async expectMysteryMathV2(mysteryMathProxy: MysteryMathV2) {
const versionResult = await mysteryMathProxy.version();
expect(versionResult).to.equal(2);
const mathResult = await mysteryMathProxy.doMath(this.a, this.b);
expect(mathResult).to.equal(this.a * this.b);
const stateResult = await mysteryMathProxy.getState();
expect(stateResult).to.equal(this.stateVar);
}
}

@ -1,45 +0,0 @@
import { SignerWithAddress } from '@nomiclabs/hardhat-ethers/signers';
import { ethers } from 'hardhat';
import {
MysteryMathV2__factory,
UpgradeBeaconController,
UpgradeBeaconController__factory,
} from '../types';
import { MysteryMathUpgrade, UpgradeTestHelpers } from './lib/upgrade';
describe('Upgrade', async () => {
const utils = new UpgradeTestHelpers();
let signer: SignerWithAddress,
mysteryMath: MysteryMathUpgrade,
ubc: UpgradeBeaconController;
before(async () => {
// set signer
[signer] = await ethers.getSigners();
const ubcFactory = new UpgradeBeaconController__factory(signer);
ubc = await ubcFactory.deploy();
// deploy upgrade setup for mysteryMath contract
mysteryMath = await utils.deployMysteryMathUpgradeSetup(signer, ubc);
});
it('Pre-Upgrade returns values from MysteryMathV1', async () => {
await utils.expectMysteryMathV1(mysteryMath.proxy);
});
it('Upgrades without problem', async () => {
// Deploy Implementation 2
const factory = new MysteryMathV2__factory(signer);
const implementation = await factory.deploy();
// Upgrade to implementation 2
await ubc.upgrade(mysteryMath.beacon.address, implementation.address);
});
it('Post-Upgrade returns values from MysteryMathV2', async () => {
await utils.expectMysteryMathV2(mysteryMath.proxy);
});
});

@ -1,516 +0,0 @@
{
"alfajores": [
{
"name": "upgradeBeaconController",
"address": "0x7256A4D01Fc8C3DdAf6415cbb48a5a5464d1E034",
"constructorArguments": "",
"isProxy": false
},
{
"name": "interchainGasPaymaster",
"address": "0x945E59Cd57c7E6a3B62997D5876D427f198d32e2",
"constructorArguments": "",
"isProxy": false
},
{
"name": "UpgradeBeacon",
"address": "0x350068a409bF7823aeefE674a5963fA4DbbC020C",
"constructorArguments": "000000000000000000000000945e59cd57c7e6a3b62997d5876d427f198d32e20000000000000000000000007256a4d01fc8c3ddaf6415cbb48a5a5464d1e034",
"isProxy": false
},
{
"name": "UpgradeBeaconProxy",
"address": "0x974cC4516FdEE100c8f8f5338C7461DfD544a884",
"constructorArguments": "000000000000000000000000350068a409bf7823aeefe674a5963fa4dbbc020c000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000048129fc1c00000000000000000000000000000000000000000000000000000000",
"isProxy": true
},
{
"name": "multisigIsm",
"address": "0xcF6bA9D5f6101232C065aD3462F365f0D1bD7fb4",
"constructorArguments": "",
"isProxy": false
},
{
"name": "mailbox",
"address": "0x389bffa5Af799130e7D77D13FA3f1a2A7c2c6324",
"constructorArguments": "000000000000000000000000000000000000000000000000000000000000aef3",
"isProxy": false
},
{
"name": "UpgradeBeacon",
"address": "0x7eDdB0E12909D7713A99CBB1F69475F7D119938C",
"constructorArguments": "000000000000000000000000389bffa5af799130e7d77d13fa3f1a2a7c2c63240000000000000000000000007256a4d01fc8c3ddaf6415cbb48a5a5464d1e034",
"isProxy": false
},
{
"name": "UpgradeBeaconProxy",
"address": "0x4dea8886b520450aD19e35206dDFb951fFcDFb17",
"constructorArguments": "0000000000000000000000007eddb0e12909d7713a99cbb1f69475f7d119938c00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000024c4d66de8000000000000000000000000cf6ba9d5f6101232c065ad3462f365f0d1bd7fb400000000000000000000000000000000000000000000000000000000",
"isProxy": true
}
],
"fuji": [
{
"name": "upgradeBeaconController",
"address": "0xf267997ca816d5eafD2FFDcA5929448653C36fC7",
"constructorArguments": "",
"isProxy": false
},
{
"name": "interchainGasPaymaster",
"address": "0xcd5c058E7fFB990A6D98573b48a24258a9673a16",
"constructorArguments": "",
"isProxy": false
},
{
"name": "UpgradeBeacon",
"address": "0xE2BC59cdD7cf0D6C052844150Fd6D61B121c461F",
"constructorArguments": "000000000000000000000000cd5c058e7ffb990a6d98573b48a24258a9673a16000000000000000000000000f267997ca816d5eafd2ffdca5929448653c36fc7",
"isProxy": false
},
{
"name": "UpgradeBeaconProxy",
"address": "0x11Fc991B40d6CA311D3D09042F70fDD6c996Ea1B",
"constructorArguments": "000000000000000000000000e2bc59cdd7cf0d6c052844150fd6d61b121c461f000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000048129fc1c00000000000000000000000000000000000000000000000000000000",
"isProxy": true
},
{
"name": "multisigIsm",
"address": "0xd66837b425e56b36073919DA85548FBD775B57e3",
"constructorArguments": "",
"isProxy": false
},
{
"name": "upgradeBeaconController",
"address": "0x9a5BFA884D6906fbdD3645f3b68B4e17bF80A7Ac",
"constructorArguments": "",
"isProxy": false
},
{
"name": "interchainGasPaymaster",
"address": "0x628d64270FC97D8ff04DcD13Dd6Cf1dde9DfAca3",
"constructorArguments": "",
"isProxy": false
},
{
"name": "UpgradeBeacon",
"address": "0xB7619A3EBFCAf08d6b04F1557c44806D976CF065",
"constructorArguments": "000000000000000000000000628d64270fc97d8ff04dcd13dd6cf1dde9dfaca30000000000000000000000009a5bfa884d6906fbdd3645f3b68b4e17bf80a7ac",
"isProxy": false
},
{
"name": "UpgradeBeaconProxy",
"address": "0x6F113AF8732660bB826C4d8f7011b95Ab9bBd46a",
"constructorArguments": "000000000000000000000000b7619a3ebfcaf08d6b04f1557c44806d976cf065000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000048129fc1c00000000000000000000000000000000000000000000000000000000",
"isProxy": true
},
{
"name": "multisigIsm",
"address": "0xEF8db4c93F36C3e6E122F79003DE136d5BE86395",
"constructorArguments": "",
"isProxy": false
},
{
"name": "upgradeBeaconController",
"address": "0x4718377c11832850387E85AeA07Ae87684d3841b",
"constructorArguments": "",
"isProxy": false
},
{
"name": "interchainGasPaymaster",
"address": "0x7d34FE1356FAd1f69eB7dcAC8d4d970d9E965Ed4",
"constructorArguments": "",
"isProxy": false
},
{
"name": "UpgradeBeacon",
"address": "0xc0294802f9333DB063FFd26BF765FffA4Ae035ca",
"constructorArguments": "0000000000000000000000007d34fe1356fad1f69eb7dcac8d4d970d9e965ed40000000000000000000000004718377c11832850387e85aea07ae87684d3841b",
"isProxy": false
},
{
"name": "UpgradeBeaconProxy",
"address": "0x379Ae5e626b9186da3E7Acd6D75cCF3DDc907171",
"constructorArguments": "000000000000000000000000c0294802f9333db063ffd26bf765fffa4ae035ca000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000048129fc1c00000000000000000000000000000000000000000000000000000000",
"isProxy": true
},
{
"name": "multisigIsm",
"address": "0x12Ac803eeD2707D5845e7c5E73BeDf0Dca331555",
"constructorArguments": "",
"isProxy": false
},
{
"name": "upgradeBeaconController",
"address": "0xA8aa2c1237275210566FDFCE1CF27B53645c6aE1",
"constructorArguments": "",
"isProxy": false
},
{
"name": "interchainGasPaymaster",
"address": "0x9B26FBD80b3C3aAc3e66c463623FF49A08F54d99",
"constructorArguments": "",
"isProxy": false
},
{
"name": "UpgradeBeacon",
"address": "0xd02EDfAd6eBcb88b6458C436Dc7EbA59D9856beA",
"constructorArguments": "0000000000000000000000009b26fbd80b3c3aac3e66c463623ff49a08f54d99000000000000000000000000a8aa2c1237275210566fdfce1cf27b53645c6ae1",
"isProxy": false
},
{
"name": "UpgradeBeaconProxy",
"address": "0x7CE925E78047a99705ca16fE3918c79341BDe64F",
"constructorArguments": "000000000000000000000000d02edfad6ebcb88b6458c436dc7eba59d9856bea000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000048129fc1c00000000000000000000000000000000000000000000000000000000",
"isProxy": true
},
{
"name": "upgradeBeaconController",
"address": "0x9d29eA8F9e7a04871C30C9d4C4129F0Fad5ab5a0",
"constructorArguments": "",
"isProxy": false
},
{
"name": "interchainGasPaymaster",
"address": "0x041EbFaE9AD18c2f9bC248832b644c0D2256D3B9",
"constructorArguments": "",
"isProxy": false
},
{
"name": "UpgradeBeacon",
"address": "0x900567ec8701D387e62b85fb01A9E22C862779bC",
"constructorArguments": "000000000000000000000000041ebfae9ad18c2f9bc248832b644c0d2256d3b90000000000000000000000009d29ea8f9e7a04871c30c9d4c4129f0fad5ab5a0",
"isProxy": false
},
{
"name": "UpgradeBeaconProxy",
"address": "0xe0a9bf21Ddee4a0B0F354b25981924A767C6183E",
"constructorArguments": "000000000000000000000000900567ec8701d387e62b85fb01a9e22c862779bc000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000048129fc1c00000000000000000000000000000000000000000000000000000000",
"isProxy": true
},
{
"name": "mailbox",
"address": "0xc392687AA3491cb010E0216fb6Caa5Dd7Cbf60b7",
"constructorArguments": "000000000000000000000000000000000000000000000000000000000000a869",
"isProxy": false
},
{
"name": "UpgradeBeacon",
"address": "0xad442d59B0a83e51DdF4CaBD9Ee39F28852005D8",
"constructorArguments": "000000000000000000000000c392687aa3491cb010e0216fb6caa5dd7cbf60b70000000000000000000000009d29ea8f9e7a04871c30c9d4c4129f0fad5ab5a0",
"isProxy": false
},
{
"name": "UpgradeBeaconProxy",
"address": "0x9BA855357227f62263683A275291f3a923C13903",
"constructorArguments": "000000000000000000000000ad442d59b0a83e51ddf4cabd9ee39f28852005d800000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000024c4d66de800000000000000000000000012ac803eed2707d5845e7c5e73bedf0dca33155500000000000000000000000000000000000000000000000000000000",
"isProxy": true
}
],
"mumbai": [
{
"name": "upgradeBeaconController",
"address": "0x54bDe7D3b78c05b7A686cc5D1211C30483eeAC45",
"constructorArguments": "",
"isProxy": false
},
{
"name": "interchainGasPaymaster",
"address": "0x78F9D209f705D3924a1cEae86Be1d09d82DB28db",
"constructorArguments": "",
"isProxy": false
},
{
"name": "interchainGasPaymaster",
"address": "0xe04777c63989C271dBff3Af3f783B5CF84F40D0A",
"constructorArguments": "",
"isProxy": false
},
{
"name": "UpgradeBeacon",
"address": "0x1D15E801F21b5f6ca07c8933D7FE94b29438e405",
"constructorArguments": "000000000000000000000000e04777c63989c271dbff3af3f783b5cf84f40d0a00000000000000000000000054bde7d3b78c05b7a686cc5d1211c30483eeac45",
"isProxy": false
},
{
"name": "UpgradeBeaconProxy",
"address": "0x0b8978f247fEFae77dE328706fD5895B187BCa95",
"constructorArguments": "0000000000000000000000001d15e801f21b5f6ca07c8933d7fe94b29438e405000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000048129fc1c00000000000000000000000000000000000000000000000000000000",
"isProxy": true
},
{
"name": "multisigIsm",
"address": "0x4E95F7Bf8a4D963C593A25bb6A8C83942211104A",
"constructorArguments": "",
"isProxy": false
},
{
"name": "mailbox",
"address": "0x2Ad9aFb9bee28cB96C263c469612078E468A8Fe9",
"constructorArguments": "0000000000000000000000000000000000000000000000000000000000013881",
"isProxy": false
},
{
"name": "UpgradeBeacon",
"address": "0x9067ebbAf4f28dBDf97b37BC4C7F2b5bF8d54164",
"constructorArguments": "0000000000000000000000002ad9afb9bee28cb96c263c469612078e468a8fe900000000000000000000000054bde7d3b78c05b7a686cc5d1211c30483eeac45",
"isProxy": false
},
{
"name": "UpgradeBeaconProxy",
"address": "0x2342eb763F3efeFE5A0BA2a21481fD5Ba7f59A90",
"constructorArguments": "0000000000000000000000009067ebbaf4f28dbdf97b37bc4c7f2b5bf8d5416400000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000024c4d66de80000000000000000000000004e95f7bf8a4d963c593a25bb6a8c83942211104a00000000000000000000000000000000000000000000000000000000",
"isProxy": true
}
],
"bsctestnet": [
{
"name": "upgradeBeaconController",
"address": "0xb10202cA1656A74f793d50EbfcC7F8F78CAab464",
"constructorArguments": "",
"isProxy": false
},
{
"name": "interchainGasPaymaster",
"address": "0x95ADDeb18912d6e6A9FbeF8B40cE44eA8cF2566e",
"constructorArguments": "",
"isProxy": false
},
{
"name": "UpgradeBeacon",
"address": "0xA68774aCEF2D13c1894295d801Bf0FB5b402D10e",
"constructorArguments": "00000000000000000000000095addeb18912d6e6a9fbef8b40ce44ea8cf2566e000000000000000000000000b10202ca1656a74f793d50ebfcc7f8f78caab464",
"isProxy": false
},
{
"name": "UpgradeBeaconProxy",
"address": "0x81bbe1D62798A9c0ca42F1a41834a6C5E659cAEd",
"constructorArguments": "000000000000000000000000a68774acef2d13c1894295d801bf0fb5b402d10e000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000048129fc1c00000000000000000000000000000000000000000000000000000000",
"isProxy": true
},
{
"name": "multisigIsm",
"address": "0xdE0Cbd9A17A99348785DA7625cB44a24b5A337be",
"constructorArguments": "",
"isProxy": false
},
{
"name": "mailbox",
"address": "0xB99Cf0bf4500BB66469bf949e2CB58535846BD1c",
"constructorArguments": "0000000000000000000000000000000000000000000000000000000000000061",
"isProxy": false
},
{
"name": "UpgradeBeacon",
"address": "0xeCc72e8D4E3404175700DE71dfc3474eEa17a89B",
"constructorArguments": "000000000000000000000000b99cf0bf4500bb66469bf949e2cb58535846bd1c000000000000000000000000b10202ca1656a74f793d50ebfcc7f8f78caab464",
"isProxy": false
},
{
"name": "UpgradeBeaconProxy",
"address": "0x056d6CAe959B4266291d6BCB3364cdF1Bc8C9814",
"constructorArguments": "000000000000000000000000ecc72e8d4e3404175700de71dfc3474eea17a89b00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000024c4d66de8000000000000000000000000de0cbd9a17a99348785da7625cb44a24b5a337be00000000000000000000000000000000000000000000000000000000",
"isProxy": true
}
],
"goerli": [
{
"name": "upgradeBeaconController",
"address": "0xB9C0c168917aD137D0B75896ee273c3Ed2420012",
"constructorArguments": "",
"isProxy": false
},
{
"name": "interchainGasPaymaster",
"address": "0x7e3fb42377ffa28b7B649AE5319d3eB7C2128103",
"constructorArguments": "",
"isProxy": false
},
{
"name": "UpgradeBeacon",
"address": "0x3ddeA0c17578242A17042F2cCf1b09fbBE51AFC3",
"constructorArguments": "0000000000000000000000007e3fb42377ffa28b7b649ae5319d3eb7c2128103000000000000000000000000b9c0c168917ad137d0b75896ee273c3ed2420012",
"isProxy": false
},
{
"name": "UpgradeBeaconProxy",
"address": "0xaC47a6318AdF660ea24994617B27171e85c6b5BE",
"constructorArguments": "0000000000000000000000003ddea0c17578242a17042f2ccf1b09fbbe51afc3000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000048129fc1c00000000000000000000000000000000000000000000000000000000",
"isProxy": true
},
{
"name": "multisigIsm",
"address": "0x2a13C3bD245166D1C6515f15fcd1441367FAb675",
"constructorArguments": "",
"isProxy": false
},
{
"name": "mailbox",
"address": "0x7387e72A8F455A2bfb5E211B01d8B6AE2a56c60E",
"constructorArguments": "0000000000000000000000000000000000000000000000000000000000000005",
"isProxy": false
},
{
"name": "UpgradeBeacon",
"address": "0x20cC3a33C49fa13627303669edf2DcA7F1E76a50",
"constructorArguments": "0000000000000000000000007387e72a8f455a2bfb5e211b01d8b6ae2a56c60e000000000000000000000000b9c0c168917ad137d0b75896ee273c3ed2420012",
"isProxy": false
},
{
"name": "UpgradeBeaconProxy",
"address": "0x5D5F9793Bc52CfF1522cDEf7206470717d2bae29",
"constructorArguments": "00000000000000000000000020cc3a33c49fa13627303669edf2dca7f1e76a5000000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000024c4d66de80000000000000000000000002a13c3bd245166d1c6515f15fcd1441367fab67500000000000000000000000000000000000000000000000000000000",
"isProxy": true
}
],
"moonbasealpha": [
{
"name": "upgradeBeaconController",
"address": "0x0C16e730090cb681460516428c3b2D1BBCB1b647",
"constructorArguments": "",
"isProxy": false
},
{
"name": "interchainGasPaymaster",
"address": "0x890eB21B76DCB165A1807cBE279f883716eA47D4",
"constructorArguments": "",
"isProxy": false
},
{
"name": "UpgradeBeacon",
"address": "0xBA3f3A84F149842529993bc38A7b4cF8131c17c2",
"constructorArguments": "000000000000000000000000890eb21b76dcb165a1807cbe279f883716ea47d40000000000000000000000000c16e730090cb681460516428c3b2d1bbcb1b647",
"isProxy": false
},
{
"name": "UpgradeBeaconProxy",
"address": "0x1fe349d93078B26C8c7350A401e2B60f100952F5",
"constructorArguments": "000000000000000000000000ba3f3a84f149842529993bc38a7b4cf8131c17c2000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000048129fc1c00000000000000000000000000000000000000000000000000000000",
"isProxy": true
},
{
"name": "multisigIsm",
"address": "0xD221ffdAa65518BF56c8623e04eA0380CE1BfaE2",
"constructorArguments": "",
"isProxy": false
},
{
"name": "mailbox",
"address": "0x0De2F539569Fb1e2e3C1d233f7A63a18B9A17110",
"constructorArguments": "0000000000000000000000000000000000000000000000000000000000000507",
"isProxy": false
},
{
"name": "UpgradeBeacon",
"address": "0x111F4f782B47881898755Bd2F67f12876893300E",
"constructorArguments": "0000000000000000000000000de2f539569fb1e2e3c1d233f7a63a18b9a171100000000000000000000000000c16e730090cb681460516428c3b2d1bbcb1b647",
"isProxy": false
},
{
"name": "UpgradeBeaconProxy",
"address": "0x711166cE892CBa0Fc01FdD74cFBE73b027678e15",
"constructorArguments": "000000000000000000000000111f4f782b47881898755bd2f67f12876893300e00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000024c4d66de8000000000000000000000000d221ffdaa65518bf56c8623e04ea0380ce1bfae200000000000000000000000000000000000000000000000000000000",
"isProxy": true
}
],
"optimismgoerli": [
{
"name": "upgradeBeaconController",
"address": "0x69181Ea49C2F5F7904cEb7299a75620bAd0954FA",
"constructorArguments": "",
"isProxy": false
},
{
"name": "interchainGasPaymaster",
"address": "0x15846844baD5E06a98056e6c3F87C0ABB0A40d21",
"constructorArguments": "",
"isProxy": false
},
{
"name": "UpgradeBeacon",
"address": "0x5f2fFCF69c58AcA2b521690400756FAe8CC99117",
"constructorArguments": "00000000000000000000000015846844bad5e06a98056e6c3f87c0abb0a40d2100000000000000000000000069181ea49c2f5f7904ceb7299a75620bad0954fa",
"isProxy": false
},
{
"name": "UpgradeBeaconProxy",
"address": "0x62A3fC7873AC96fFF1975663Aa41Ab9100cDe2FB",
"constructorArguments": "0000000000000000000000005f2ffcf69c58aca2b521690400756fae8cc99117000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000048129fc1c00000000000000000000000000000000000000000000000000000000",
"isProxy": true
},
{
"name": "multisigIsm",
"address": "0xDA7f1997D52a5f442E83948F7529BceAA6e1fda2",
"constructorArguments": "",
"isProxy": false
},
{
"name": "mailbox",
"address": "0x14EE2f01907707Ce8d13C4F5DBC40778b5b664e0",
"constructorArguments": "00000000000000000000000000000000000000000000000000000000000001a4",
"isProxy": false
},
{
"name": "UpgradeBeacon",
"address": "0x23cD67A76c99578f77C73A306A29905D63D203b4",
"constructorArguments": "00000000000000000000000014ee2f01907707ce8d13c4f5dbc40778b5b664e000000000000000000000000069181ea49c2f5f7904ceb7299a75620bad0954fa",
"isProxy": false
},
{
"name": "UpgradeBeaconProxy",
"address": "0xd876C01aB40e8cE42Db417fBC79c726d45504dE4",
"constructorArguments": "00000000000000000000000023cd67a76c99578f77c73a306a29905d63d203b400000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000024c4d66de8000000000000000000000000da7f1997d52a5f442e83948f7529bceaa6e1fda200000000000000000000000000000000000000000000000000000000",
"isProxy": true
}
],
"arbitrumgoerli": [
{
"name": "upgradeBeaconController",
"address": "0xDA7f1997D52a5f442E83948F7529BceAA6e1fda2",
"constructorArguments": "",
"isProxy": false
},
{
"name": "interchainGasPaymaster",
"address": "0xa1C91dd4F3050DE9C4184BD8B4403A0C81D5463C",
"constructorArguments": "",
"isProxy": false
},
{
"name": "UpgradeBeacon",
"address": "0x603d9041D636CD3218888F1C6F18A4BfeDcdB7F0",
"constructorArguments": "000000000000000000000000a1c91dd4f3050de9c4184bd8b4403a0c81d5463c000000000000000000000000da7f1997d52a5f442e83948f7529bceaa6e1fda2",
"isProxy": false
},
{
"name": "UpgradeBeaconProxy",
"address": "0x0C16e730090cb681460516428c3b2D1BBCB1b647",
"constructorArguments": "000000000000000000000000603d9041d636cd3218888f1c6f18a4bfedcdb7f0000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000048129fc1c00000000000000000000000000000000000000000000000000000000",
"isProxy": true
},
{
"name": "multisigIsm",
"address": "0x890eB21B76DCB165A1807cBE279f883716eA47D4",
"constructorArguments": "",
"isProxy": false
},
{
"name": "mailbox",
"address": "0x11467b49e7BBE3090EC25aF85E172D5ed6F2DA23",
"constructorArguments": "0000000000000000000000000000000000000000000000000000000000066eed",
"isProxy": false
},
{
"name": "UpgradeBeacon",
"address": "0xC60C145f1e1904f9d6483A611BF1416697CCc1FE",
"constructorArguments": "00000000000000000000000011467b49e7bbe3090ec25af85e172d5ed6f2da23000000000000000000000000da7f1997d52a5f442e83948f7529bceaa6e1fda2",
"isProxy": false
},
{
"name": "UpgradeBeaconProxy",
"address": "0x957ff8ca77Af405D620e47350327fDA24b83070b",
"constructorArguments": "000000000000000000000000c60c145f1e1904f9d6483a611bf1416697ccc1fe00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000024c4d66de8000000000000000000000000890eb21b76dcb165a1807cbe279f883716ea47d400000000000000000000000000000000000000000000000000000000",
"isProxy": true
}
]
}

@ -19,7 +19,11 @@ async function main() {
const environment = await getEnvironment();
const config = getCoreEnvironmentConfig(environment) as any;
const multiProvider = await config.getMultiProvider();
const deployer = new HyperlaneCoreInfraDeployer(multiProvider, config.core);
const deployer = new HyperlaneCoreInfraDeployer(
multiProvider,
config.core,
environment,
);
let previousContracts = {};
previousAddressParsing: try {
@ -60,7 +64,7 @@ async function main() {
deployer.mergeWithExistingVerificationInputs(existingVerificationInputs),
);
}
deployer.writeRustConfigs(environment, getCoreRustDirectory(environment));
deployer.writeRustConfigs(getCoreRustDirectory(environment));
}
main().then(console.log).catch(console.error);

@ -1,9 +1,22 @@
import { ethers } from 'ethers';
import {
InterchainGasPaymaster,
Mailbox,
ProxyAdmin,
} from '@hyperlane-xyz/core';
import {
ChainMap,
ChainName,
CoreConfig,
HyperlaneCoreDeployer,
MultiProvider,
ProxiedContract,
TransparentProxyAddresses,
chainMetadata,
objMap,
} from '@hyperlane-xyz/sdk';
import { types } from '@hyperlane-xyz/utils';
import { DeployEnvironment, RustChainSetup, RustConfig } from '../config';
import { ConnectionType } from '../config/agent';
@ -12,9 +25,53 @@ import { writeJSON } from '../utils/utils';
export class HyperlaneCoreInfraDeployer<
Chain extends ChainName,
> extends HyperlaneCoreDeployer<Chain> {
writeRustConfigs(environment: DeployEnvironment, directory: string) {
environment: DeployEnvironment;
constructor(
multiProvider: MultiProvider<Chain>,
configMap: ChainMap<Chain, CoreConfig>,
environment: DeployEnvironment,
) {
super(multiProvider, configMap);
this.environment = environment;
}
async deployInterchainGasPaymaster<LocalChain extends Chain>(
chain: LocalChain,
proxyAdmin: ProxyAdmin,
): Promise<
ProxiedContract<InterchainGasPaymaster, TransparentProxyAddresses>
> {
const deployOpts = {
create2Salt: ethers.utils.solidityKeccak256(
['string', 'string'],
[this.environment, 'interchainGasPaymaster'],
),
};
return super.deployInterchainGasPaymaster(chain, proxyAdmin, deployOpts);
}
async deployMailbox<LocalChain extends Chain>(
chain: LocalChain,
defaultIsmAddress: types.Address,
proxyAdmin: ProxyAdmin,
): Promise<ProxiedContract<Mailbox, TransparentProxyAddresses>> {
const deployOpts = {
create2Salt: ethers.utils.solidityKeccak256(
['string', 'string'],
[this.environment, 'mailbox'],
),
};
return super.deployMailbox(
chain,
defaultIsmAddress,
proxyAdmin,
deployOpts,
);
}
writeRustConfigs(directory: string) {
const rustConfig: RustConfig<Chain> = {
environment,
environment: this.environment,
chains: {},
signers: {},
db: 'db_path',
@ -59,6 +116,6 @@ export class HyperlaneCoreInfraDeployer<
}
rustConfig.chains[chain] = chainConfig;
});
writeJSON(directory, `${environment}_config.json`, rustConfig);
writeJSON(directory, `${this.environment}_config.json`, rustConfig);
}
}

@ -22,7 +22,7 @@ export async function runScraperHelmCommand<Chain extends ChainName>(
? ` | kubectl diff -n ${agentConfig.namespace} --field-manager="Go-http-client" -f - || true`
: '';
const helmReleaseName = getScraperHelmReleaseName(agentConfig);
const helmReleaseName = getScraperHelmReleaseName();
if (action === HelmCommand.InstallOrUpgrade) {
// Delete secrets to avoid them being stale
@ -100,8 +100,6 @@ async function scraperHelmValues<Chain extends ChainName>(
return helmifyValues(valueDict);
}
function getScraperHelmReleaseName<Chain extends ChainName>(
agentConfig: AgentConfig<Chain>,
) {
function getScraperHelmReleaseName() {
return `scraper`;
}

@ -40,7 +40,11 @@ describe('core', async () => {
});
it('deploys', async () => {
deployer = new HyperlaneCoreInfraDeployer(multiProvider, coreConfig);
deployer = new HyperlaneCoreInfraDeployer(
multiProvider,
coreConfig,
environment,
);
contracts = await deployer.deploy();
});
@ -48,7 +52,7 @@ describe('core', async () => {
const base = './test/outputs/core';
writeJSON(base, 'contracts.json', serializeContracts(contracts));
writeJSON(base, 'verification.json', deployer.verificationInputs);
deployer.writeRustConfigs(environment, base);
deployer.writeRustConfigs(base);
});
it('transfers ownership', async () => {
@ -58,7 +62,11 @@ describe('core', async () => {
describe('failure modes', async () => {
beforeEach(async () => {
deployer = new HyperlaneCoreInfraDeployer(multiProvider, coreConfig);
deployer = new HyperlaneCoreInfraDeployer(
multiProvider,
coreConfig,
environment,
);
const stub = sinon.stub(deployer, 'deployContracts');
stub.withArgs('test3', sinon.match.any).rejects();
// @ts-ignore

@ -1,151 +1,135 @@
{
"avalanche": {
"upgradeBeaconController": "0x2C1FAbEcd7bFBdEBF27CcdB67baADB38b6Df90fC",
"proxyAdmin": "0x2C1FAbEcd7bFBdEBF27CcdB67baADB38b6Df90fC",
"multisigIsm": "0x8b83fefd896fAa52057798f6426E9f0B080FCCcE",
"interchainGasPaymaster": {
"kind": "UpgradeBeacon",
"kind": "Transparent",
"proxy": "0xed9a722c543883FB7e07E78F3879762DE09eA7D5",
"implementation": "0xcAf034CE568fad5B85Cfbf088FF43974C39287cC",
"beacon": "0xcf2d1D59C51a341818d23b0f6AfB7c85d668Dc77"
"implementation": "0xcAf034CE568fad5B85Cfbf088FF43974C39287cC"
},
"mailbox": {
"kind": "UpgradeBeacon",
"kind": "Transparent",
"proxy": "0x0761b0827849abbf7b0cC09CE14e1C93D87f5004",
"implementation": "0xEb9FcFDC9EfDC17c1EC5E1dc085B98485da213D6",
"beacon": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908"
"implementation": "0xEb9FcFDC9EfDC17c1EC5E1dc085B98485da213D6"
},
"interchainAccountRouter": "0xc011170d9795a7a2d065E384EAd1CA3394A7d35E",
"interchainQueryRouter": "0x6141e7E7fA2c1beB8be030B0a7DB4b8A10c7c3cd",
"create2Factory": "0xc97D8e6f57b0d64971453dDc6EB8483fec9d163a"
},
"bsc": {
"upgradeBeaconController": "0x149db7afD694722747035d5AEC7007ccb6F8f112",
"proxyAdmin": "0x149db7afD694722747035d5AEC7007ccb6F8f112",
"multisigIsm": "0x19dc38aeae620380430C200a6E990D5Af5480117",
"interchainGasPaymaster": {
"kind": "UpgradeBeacon",
"kind": "Transparent",
"proxy": "0x47bf94790241B1764fC41A35a8329A15569E121C",
"implementation": "0x4419922ca3C11F92bd11D31489932C39BAB57DA3",
"beacon": "0xc2Da384799488B4e1E773d70a83346529145085B"
"implementation": "0x4419922ca3C11F92bd11D31489932C39BAB57DA3"
},
"mailbox": {
"kind": "UpgradeBeacon",
"kind": "Transparent",
"proxy": "0xc3F23848Ed2e04C0c6d41bd7804fa8f89F940B94",
"implementation": "0xfDc940D5c148bA038505DAa5524730644527229a",
"beacon": "0x0D63128D887159d63De29497dfa45AFc7C699AE4"
"implementation": "0xfDc940D5c148bA038505DAa5524730644527229a"
},
"interchainAccountRouter": "0xc011170d9795a7a2d065E384EAd1CA3394A7d35E",
"interchainQueryRouter": "0x6141e7E7fA2c1beB8be030B0a7DB4b8A10c7c3cd",
"create2Factory": "0xc97D8e6f57b0d64971453dDc6EB8483fec9d163a"
},
"polygon": {
"upgradeBeaconController": "0x12582c7B0f43c6A667CBaA7fA8b112F7fb1E69F0",
"proxyAdmin": "0x12582c7B0f43c6A667CBaA7fA8b112F7fb1E69F0",
"multisigIsm": "0x1Ab68dC4f7b6cfcd00218D4b761b7F3b5a724555",
"interchainGasPaymaster": {
"kind": "UpgradeBeacon",
"kind": "Transparent",
"proxy": "0x60B8d195f1b2EcaC26d54b95C69E6399cFD64b53",
"implementation": "0x13E83ac41e696856B6996263501fB3225AD5E6F5",
"beacon": "0x61374178e45F65fF9D6252d017Cd580FC60B7654"
"implementation": "0x13E83ac41e696856B6996263501fB3225AD5E6F5"
},
"mailbox": {
"kind": "UpgradeBeacon",
"kind": "Transparent",
"proxy": "0x8249cD1275855F2BB20eE71f0B9fA3c9155E5FaB",
"implementation": "0x17E216fBb22dF4ef8A6640ae9Cb147C92710ac84",
"beacon": "0xe042D1fbDf59828dd16b9649Ede7abFc856F7a6c"
"implementation": "0x17E216fBb22dF4ef8A6640ae9Cb147C92710ac84"
},
"interchainAccountRouter": "0xc011170d9795a7a2d065E384EAd1CA3394A7d35E",
"interchainQueryRouter": "0x6141e7E7fA2c1beB8be030B0a7DB4b8A10c7c3cd",
"create2Factory": "0xc97D8e6f57b0d64971453dDc6EB8483fec9d163a"
},
"celo": {
"upgradeBeaconController": "0x48083C69f5a42c6B69ABbAd48AE195BD36770ee2",
"proxyAdmin": "0x48083C69f5a42c6B69ABbAd48AE195BD36770ee2",
"multisigIsm": "0x12582c7B0f43c6A667CBaA7fA8b112F7fb1E69F0",
"interchainGasPaymaster": {
"kind": "UpgradeBeacon",
"kind": "Transparent",
"proxy": "0xCDeb368Db32ecCefaf7018e152DA9120565cb572",
"implementation": "0x70EbA87Cd15616f32C736B3f3BdCfaeD0713a82B",
"beacon": "0x99fEFc1119E86Ee0153eb887cF8E8ab2d92A16e8"
"implementation": "0x70EbA87Cd15616f32C736B3f3BdCfaeD0713a82B"
},
"mailbox": {
"kind": "UpgradeBeacon",
"kind": "Transparent",
"proxy": "0xe042D1fbDf59828dd16b9649Ede7abFc856F7a6c",
"implementation": "0xFC62DeF1f08793aBf0E67f69257c6be258194F72",
"beacon": "0x17E216fBb22dF4ef8A6640ae9Cb147C92710ac84"
"implementation": "0xFC62DeF1f08793aBf0E67f69257c6be258194F72"
},
"interchainAccountRouter": "0xc011170d9795a7a2d065E384EAd1CA3394A7d35E",
"interchainQueryRouter": "0x6141e7E7fA2c1beB8be030B0a7DB4b8A10c7c3cd",
"create2Factory": "0xc97D8e6f57b0d64971453dDc6EB8483fec9d163a"
},
"arbitrum": {
"upgradeBeaconController": "0x2C1FAbEcd7bFBdEBF27CcdB67baADB38b6Df90fC",
"proxyAdmin": "0x2C1FAbEcd7bFBdEBF27CcdB67baADB38b6Df90fC",
"multisigIsm": "0x8b83fefd896fAa52057798f6426E9f0B080FCCcE",
"interchainGasPaymaster": {
"kind": "UpgradeBeacon",
"kind": "Transparent",
"proxy": "0x376aD181E8cd45eAd5403F78d5A871D08c3c4D77",
"implementation": "0x5c12ADC734699C07b095fe30B8312F1A7bbaA788",
"beacon": "0xc23BaF5Eb5848D19701BbE7f139645e6bd58a319"
"implementation": "0x5c12ADC734699C07b095fe30B8312F1A7bbaA788"
},
"mailbox": {
"kind": "UpgradeBeacon",
"kind": "Transparent",
"proxy": "0x0761b0827849abbf7b0cC09CE14e1C93D87f5004",
"implementation": "0xEb9FcFDC9EfDC17c1EC5E1dc085B98485da213D6",
"beacon": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908"
"implementation": "0xEb9FcFDC9EfDC17c1EC5E1dc085B98485da213D6"
},
"interchainAccountRouter": "0xc011170d9795a7a2d065E384EAd1CA3394A7d35E",
"interchainQueryRouter": "0x6141e7E7fA2c1beB8be030B0a7DB4b8A10c7c3cd",
"create2Factory": "0xc97D8e6f57b0d64971453dDc6EB8483fec9d163a"
},
"optimism": {
"upgradeBeaconController": "0x15ab173bDB6832f9b64276bA128659b0eD77730B",
"proxyAdmin": "0x15ab173bDB6832f9b64276bA128659b0eD77730B",
"multisigIsm": "0xd83A4F747fE80Ed98839e05079B1B7Fe037b1638",
"interchainGasPaymaster": {
"kind": "UpgradeBeacon",
"kind": "Transparent",
"proxy": "0xc5D6aCaafBCcEC6D7fD7d92F4509befce641c563",
"implementation": "0xFB9e40D811Cea562cc8a322b029eF2BDcC3ef6ed",
"beacon": "0x6119B76720CcfeB3D256EC1b91218EEfFD6756E1"
"implementation": "0xFB9e40D811Cea562cc8a322b029eF2BDcC3ef6ed"
},
"mailbox": {
"kind": "UpgradeBeacon",
"kind": "Transparent",
"proxy": "0x0be2Ae2f6D02a3e0e00ECB57D3E1fCbb7f8F38F4",
"implementation": "0x2fa5F5C96419C222cDbCeC797D696e6cE428A7A9",
"beacon": "0x182E8d7c5F1B06201b102123FC7dF0EaeB445a7B"
"implementation": "0x2fa5F5C96419C222cDbCeC797D696e6cE428A7A9"
},
"interchainAccountRouter": "0xc011170d9795a7a2d065E384EAd1CA3394A7d35E",
"interchainQueryRouter": "0x6141e7E7fA2c1beB8be030B0a7DB4b8A10c7c3cd",
"create2Factory": "0xc97D8e6f57b0d64971453dDc6EB8483fec9d163a"
},
"ethereum": {
"upgradeBeaconController": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7",
"proxyAdmin": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7",
"multisigIsm": "0xeA87ae93Fa0019a82A727bfd3eBd1cFCa8f64f1D",
"interchainGasPaymaster": {
"kind": "UpgradeBeacon",
"kind": "Transparent",
"proxy": "0x17E216fBb22dF4ef8A6640ae9Cb147C92710ac84",
"implementation": "0x1Ab68dC4f7b6cfcd00218D4b761b7F3b5a724555",
"beacon": "0xFC62DeF1f08793aBf0E67f69257c6be258194F72"
"implementation": "0x1Ab68dC4f7b6cfcd00218D4b761b7F3b5a724555"
},
"mailbox": {
"kind": "UpgradeBeacon",
"kind": "Transparent",
"proxy": "0x2f9DB5616fa3fAd1aB06cB2C906830BA63d135e3",
"implementation": "0x3a867fCfFeC2B790970eeBDC9023E75B0a172aa7",
"beacon": "0x7f50C5776722630a0024fAE05fDe8b47571D7B39"
"implementation": "0x3a867fCfFeC2B790970eeBDC9023E75B0a172aa7"
},
"interchainAccountRouter": "0xc011170d9795a7a2d065E384EAd1CA3394A7d35E",
"interchainQueryRouter": "0x6141e7E7fA2c1beB8be030B0a7DB4b8A10c7c3cd",
"create2Factory": "0xc97D8e6f57b0d64971453dDc6EB8483fec9d163a"
},
"moonbeam": {
"upgradeBeaconController": "0x2C1FAbEcd7bFBdEBF27CcdB67baADB38b6Df90fC",
"proxyAdmin": "0x2C1FAbEcd7bFBdEBF27CcdB67baADB38b6Df90fC",
"multisigIsm": "0x1052eF3419f26Bec74Ed7CEf4a4FA6812Bc09908",
"interchainGasPaymaster": {
"kind": "UpgradeBeacon",
"kind": "Transparent",
"proxy": "0xEb9FcFDC9EfDC17c1EC5E1dc085B98485da213D6",
"implementation": "0x8b83fefd896fAa52057798f6426E9f0B080FCCcE",
"beacon": "0x8F7454AC98228f3504Bb91eA3D8Adafe6406110A"
"implementation": "0x8b83fefd896fAa52057798f6426E9f0B080FCCcE"
},
"mailbox": {
"kind": "UpgradeBeacon",
"kind": "Transparent",
"proxy": "0xeA87ae93Fa0019a82A727bfd3eBd1cFCa8f64f1D",
"implementation": "0x4Ed7d626f1E96cD1C0401607Bf70D95243E3dEd1",
"beacon": "0x2f2aFaE1139Ce54feFC03593FeE8AB2aDF4a85A7"
"implementation": "0x4Ed7d626f1E96cD1C0401607Bf70D95243E3dEd1"
},
"interchainAccountRouter": "0xc011170d9795a7a2d065E384EAd1CA3394A7d35E",
"interchainQueryRouter": "0x6141e7E7fA2c1beB8be030B0a7DB4b8A10c7c3cd",

@ -1,50 +1,44 @@
{
"test1": {
"upgradeBeaconController": "0x5FbDB2315678afecb367f032d93F642f64180aa3",
"proxyAdmin": "0xCf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc9",
"interchainGasPaymaster": {
"kind": "UpgradeBeacon",
"proxy": "0xCf7Ed3AccA5a467e9e704C703E8D87F634fB0Fc9",
"implementation": "0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512",
"beacon": "0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0"
"kind": "Transparent",
"proxy": "0x5FC8d32690cc91D4c39d9d3abcBD16989F875707",
"implementation": "0xDc64a140Aa3E981100a9becA4E685f962f0cF6C9"
},
"mailbox": {
"kind": "UpgradeBeacon",
"proxy": "0xB7f8BC63BbcaD18155201308C8f3540b07f84F5e",
"implementation": "0x8A791620dd6260079BF849Dc5567aDC3F2FdC318",
"beacon": "0x610178dA211FEF7D417bC0e6FeD39F05609AD788"
"kind": "Transparent",
"proxy": "0xa513E6E4b8f2a923D98304ec87F64353C4D5C853",
"implementation": "0x0165878A594ca255338adfa4d48449f69242Eb8F"
},
"multisigIsm": "0xDc64a140Aa3E981100a9becA4E685f962f0cF6C9"
"multisigIsm": "0x5FbDB2315678afecb367f032d93F642f64180aa3"
},
"test2": {
"upgradeBeaconController": "0xA51c1fc2f0D1a1b8494Ed1FE312d7C3a78Ed91C0",
"proxyAdmin": "0xB7f8BC63BbcaD18155201308C8f3540b07f84F5e",
"interchainGasPaymaster": {
"kind": "UpgradeBeacon",
"proxy": "0x0B306BF915C4d645ff596e518fAf3F9669b97016",
"implementation": "0x0DCd1Bf9A1b36cE34237eEaFef220932846BCD82",
"beacon": "0x9A676e781A523b5d0C0e43731313A708CB607508"
"kind": "Transparent",
"proxy": "0x0DCd1Bf9A1b36cE34237eEaFef220932846BCD82",
"implementation": "0xA51c1fc2f0D1a1b8494Ed1FE312d7C3a78Ed91C0"
},
"mailbox": {
"kind": "UpgradeBeacon",
"proxy": "0x322813Fd9A801c5507c9de605d63CEA4f2CE6c44",
"implementation": "0x59b670e9fA9D0A427751Af201D676719a970857b",
"beacon": "0x4ed7c70F96B99c776995fB64377f0d4aB3B0e1C1"
"kind": "Transparent",
"proxy": "0x0B306BF915C4d645ff596e518fAf3F9669b97016",
"implementation": "0x9A676e781A523b5d0C0e43731313A708CB607508"
},
"multisigIsm": "0x959922bE3CAee4b8Cd9a407cc3ac1C251C2007B1"
"multisigIsm": "0x2279B7A0a67DB372996a5FaB50D91eAA73d2eBe6"
},
"test3": {
"upgradeBeaconController": "0xa85233C63b9Ee964Add6F2cffe00Fd84eb32338f",
"proxyAdmin": "0x3Aa5ebB10DC797CAC828524e59A333d0A371443c",
"interchainGasPaymaster": {
"kind": "UpgradeBeacon",
"proxy": "0x09635F643e140090A9A8Dcd712eD6285858ceBef",
"implementation": "0x4A679253410272dd5232B3Ff7cF5dbB88f295319",
"beacon": "0x7a2088a1bFc9d81c55368AE168C2C02570cB814F"
"kind": "Transparent",
"proxy": "0x59b670e9fA9D0A427751Af201D676719a970857b",
"implementation": "0xc6e7DF5E7b4f2A278906862b61205850344D4e7d"
},
"mailbox": {
"kind": "UpgradeBeacon",
"proxy": "0x1613beB3B2C4f22Ee086B2b38C1476A3cE7f78E8",
"implementation": "0x9E545E3C0baAB3E08CdfD552C960A1050f373042",
"beacon": "0xa82fF9aFd8f496c3d6ac40E2a0F282E47488CFc9"
"kind": "Transparent",
"proxy": "0x322813Fd9A801c5507c9de605d63CEA4f2CE6c44",
"implementation": "0x4ed7c70F96B99c776995fB64377f0d4aB3B0e1C1"
},
"multisigIsm": "0xc5a5C42992dECbae36851359345FE25997F5C42d"
"multisigIsm": "0x959922bE3CAee4b8Cd9a407cc3ac1C251C2007B1"
}
}

@ -1,151 +1,135 @@
{
"alfajores": {
"upgradeBeaconController": "0x15e07BD101dfB4e8C2D0B368AbFeE3524e541277",
"proxyAdmin": "0x15e07BD101dfB4e8C2D0B368AbFeE3524e541277",
"multisigIsm": "0xc41169650335Ad274157Ea5116Cdf227430A68a3",
"interchainGasPaymaster": {
"kind": "UpgradeBeacon",
"kind": "Transparent",
"proxy": "0x1Fb165396FB26AC4178ca4240b3724039F75EED7",
"implementation": "0x67fA6577A7558a55BFDA87118dDBbeFB34521758",
"beacon": "0xd95091C1c1A7E0e5DdD7d44568A04588e76e4dDe"
"implementation": "0x67fA6577A7558a55BFDA87118dDBbeFB34521758"
},
"mailbox": {
"kind": "UpgradeBeacon",
"kind": "Transparent",
"proxy": "0x5C7D9B5f38022dB78416D6C0132bf8c404deDe27",
"implementation": "0x9095fDae1977A5fa61877FD44f307f7aDcBF9A0d",
"beacon": "0xD3CCCbde1CCdB99313f25F8CA1A7B5C13BfD3dA2"
"implementation": "0x9095fDae1977A5fa61877FD44f307f7aDcBF9A0d"
},
"interchainAccountRouter": "0xc011170d9795a7a2d065E384EAd1CA3394A7d35E",
"interchainQueryRouter": "0x6141e7E7fA2c1beB8be030B0a7DB4b8A10c7c3cd",
"create2Factory": "0xc97D8e6f57b0d64971453dDc6EB8483fec9d163a"
},
"fuji": {
"upgradeBeaconController": "0x97Bbc6bBaFa5Ce3b2FA966c121Af63bD09e940f8",
"proxyAdmin": "0x97Bbc6bBaFa5Ce3b2FA966c121Af63bD09e940f8",
"multisigIsm": "0x33AbaF6708be03Bdf0595DA0745A7111b01dB8c7",
"interchainGasPaymaster": {
"kind": "UpgradeBeacon",
"kind": "Transparent",
"proxy": "0x4834a491f78BBF48e983F9Ce0E20D1E4DbE013D8",
"implementation": "0x5309959109F031B8459deD683d958aE3393A1786",
"beacon": "0x9CA79aDb726866c764f3D4ec6D01d5976351f50F"
"implementation": "0x5309959109F031B8459deD683d958aE3393A1786"
},
"mailbox": {
"kind": "UpgradeBeacon",
"kind": "Transparent",
"proxy": "0xc507A7c848b59469cC44A3653F8a582aa8BeC71E",
"implementation": "0x71B1BF7C99BEef0545eAFf441372cb6413d9367c",
"beacon": "0x16C20625B11E0c8187Cc1B3e4ceedc35C48D8013"
"implementation": "0x71B1BF7C99BEef0545eAFf441372cb6413d9367c"
},
"interchainAccountRouter": "0xc011170d9795a7a2d065E384EAd1CA3394A7d35E",
"interchainQueryRouter": "0x6141e7E7fA2c1beB8be030B0a7DB4b8A10c7c3cd",
"create2Factory": "0xc97D8e6f57b0d64971453dDc6EB8483fec9d163a"
},
"mumbai": {
"upgradeBeaconController": "0xC81e6D1070aFA48DA4e4f35E744CC1aE43532a10",
"proxyAdmin": "0xC81e6D1070aFA48DA4e4f35E744CC1aE43532a10",
"multisigIsm": "0xb636B2c65A75d41F0dBe98fB33eb563d245a241a",
"interchainGasPaymaster": {
"kind": "UpgradeBeacon",
"kind": "Transparent",
"proxy": "0x9A27744C249A11f68B3B56f09D280599585DFBb8",
"implementation": "0xc67b416734FDfa1c37760858aB30a18af6101383",
"beacon": "0x4F49f89b6e350B8A3BE3aB8c9Aa6bcd3179FaA02"
"implementation": "0xc67b416734FDfa1c37760858aB30a18af6101383"
},
"mailbox": {
"kind": "UpgradeBeacon",
"kind": "Transparent",
"proxy": "0xe17c37212d785760E8331D4A4395B17b34Ba8cDF",
"implementation": "0x5310F977D29ae0Cf14eC000b5dbDF9734499Be4E",
"beacon": "0xaCF0B0bA84db40cDC48235De2d6cF96540fFa5CD"
"implementation": "0x5310F977D29ae0Cf14eC000b5dbDF9734499Be4E"
},
"interchainAccountRouter": "0xc011170d9795a7a2d065E384EAd1CA3394A7d35E",
"interchainQueryRouter": "0x6141e7E7fA2c1beB8be030B0a7DB4b8A10c7c3cd",
"create2Factory": "0xc97D8e6f57b0d64971453dDc6EB8483fec9d163a"
},
"bsctestnet": {
"upgradeBeaconController": "0x638A831b4d11Be6a72AcB97d1aE79DA05Ae9B1D3",
"proxyAdmin": "0x638A831b4d11Be6a72AcB97d1aE79DA05Ae9B1D3",
"multisigIsm": "0xe403E16db1f5997bC62Dc611A8d42836364A7f01",
"interchainGasPaymaster": {
"kind": "UpgradeBeacon",
"kind": "Transparent",
"proxy": "0x155b1F1801030Ea4dF038107d3cc1b4bA496916e",
"implementation": "0x407eB16cdC073bB9cb0Da779aeb0a9246940D3B8",
"beacon": "0xC6A00ce0f86e88dD9eE45f28a79AB8FA833F01F6"
"implementation": "0x407eB16cdC073bB9cb0Da779aeb0a9246940D3B8"
},
"mailbox": {
"kind": "UpgradeBeacon",
"kind": "Transparent",
"proxy": "0xE023239c8dfc172FF008D8087E7442d3eBEd9350",
"implementation": "0x7740342863717e26E3d5B828639834ADfce8a061",
"beacon": "0xa318ffca299412ce76B7cb980850ceDB15584E7e"
"implementation": "0x7740342863717e26E3d5B828639834ADfce8a061"
},
"interchainAccountRouter": "0xc011170d9795a7a2d065E384EAd1CA3394A7d35E",
"interchainQueryRouter": "0x6141e7E7fA2c1beB8be030B0a7DB4b8A10c7c3cd",
"create2Factory": "0xc97D8e6f57b0d64971453dDc6EB8483fec9d163a"
},
"arbitrumgoerli": {
"upgradeBeaconController": "0x275aCcCa81cAD931dC6fB6E49ED233Bc99Bed4A7",
"proxyAdmin": "0x275aCcCa81cAD931dC6fB6E49ED233Bc99Bed4A7",
"multisigIsm": "0x01812D60958798695391dacF092BAc4a715B1718",
"interchainGasPaymaster": {
"kind": "UpgradeBeacon",
"kind": "Transparent",
"proxy": "0x44b764045BfDC68517e10e783E69B376cef196B2",
"implementation": "0xeb6f11189197223c656807a83B0DD374f9A6dF44",
"beacon": "0x16B710b86CAd07E6F1C531861a16F5feC29dba37"
"implementation": "0xeb6f11189197223c656807a83B0DD374f9A6dF44"
},
"mailbox": {
"kind": "UpgradeBeacon",
"kind": "Transparent",
"proxy": "0xDDcFEcF17586D08A5740B7D91735fcCE3dfe3eeD",
"implementation": "0x54148470292C24345fb828B003461a9444414517",
"beacon": "0x589C201a07c26b4725A4A829d772f24423da480B"
"implementation": "0x54148470292C24345fb828B003461a9444414517"
},
"interchainAccountRouter": "0xc011170d9795a7a2d065E384EAd1CA3394A7d35E",
"interchainQueryRouter": "0x6141e7E7fA2c1beB8be030B0a7DB4b8A10c7c3cd",
"create2Factory": "0xc97D8e6f57b0d64971453dDc6EB8483fec9d163a"
},
"optimismgoerli": {
"upgradeBeaconController": "0x275aCcCa81cAD931dC6fB6E49ED233Bc99Bed4A7",
"proxyAdmin": "0x275aCcCa81cAD931dC6fB6E49ED233Bc99Bed4A7",
"multisigIsm": "0x01812D60958798695391dacF092BAc4a715B1718",
"interchainGasPaymaster": {
"kind": "UpgradeBeacon",
"kind": "Transparent",
"proxy": "0x44b764045BfDC68517e10e783E69B376cef196B2",
"implementation": "0xeb6f11189197223c656807a83B0DD374f9A6dF44",
"beacon": "0x16B710b86CAd07E6F1C531861a16F5feC29dba37"
"implementation": "0xeb6f11189197223c656807a83B0DD374f9A6dF44"
},
"mailbox": {
"kind": "UpgradeBeacon",
"kind": "Transparent",
"proxy": "0xDDcFEcF17586D08A5740B7D91735fcCE3dfe3eeD",
"implementation": "0x54148470292C24345fb828B003461a9444414517",
"beacon": "0x589C201a07c26b4725A4A829d772f24423da480B"
"implementation": "0x54148470292C24345fb828B003461a9444414517"
},
"interchainAccountRouter": "0xc011170d9795a7a2d065E384EAd1CA3394A7d35E",
"interchainQueryRouter": "0x6141e7E7fA2c1beB8be030B0a7DB4b8A10c7c3cd",
"create2Factory": "0xc97D8e6f57b0d64971453dDc6EB8483fec9d163a"
},
"goerli": {
"upgradeBeaconController": "0x275aCcCa81cAD931dC6fB6E49ED233Bc99Bed4A7",
"proxyAdmin": "0x275aCcCa81cAD931dC6fB6E49ED233Bc99Bed4A7",
"multisigIsm": "0x01812D60958798695391dacF092BAc4a715B1718",
"interchainGasPaymaster": {
"kind": "UpgradeBeacon",
"kind": "Transparent",
"proxy": "0x44b764045BfDC68517e10e783E69B376cef196B2",
"implementation": "0xeb6f11189197223c656807a83B0DD374f9A6dF44",
"beacon": "0x16B710b86CAd07E6F1C531861a16F5feC29dba37"
"implementation": "0xeb6f11189197223c656807a83B0DD374f9A6dF44"
},
"mailbox": {
"kind": "UpgradeBeacon",
"kind": "Transparent",
"proxy": "0xDDcFEcF17586D08A5740B7D91735fcCE3dfe3eeD",
"implementation": "0x54148470292C24345fb828B003461a9444414517",
"beacon": "0x589C201a07c26b4725A4A829d772f24423da480B"
"implementation": "0x54148470292C24345fb828B003461a9444414517"
},
"interchainAccountRouter": "0xc011170d9795a7a2d065E384EAd1CA3394A7d35E",
"interchainQueryRouter": "0x6141e7E7fA2c1beB8be030B0a7DB4b8A10c7c3cd",
"create2Factory": "0xc97D8e6f57b0d64971453dDc6EB8483fec9d163a"
},
"moonbasealpha": {
"upgradeBeaconController": "0x6E7b29CB2A7617405B4d30C6f84bBD51b4Bb4be8",
"proxyAdmin": "0x6E7b29CB2A7617405B4d30C6f84bBD51b4Bb4be8",
"multisigIsm": "0xD356C996277eFb7f75Ee8bd61b31cC781A12F54f",
"interchainGasPaymaster": {
"kind": "UpgradeBeacon",
"kind": "Transparent",
"proxy": "0xeb6f11189197223c656807a83B0DD374f9A6dF44",
"implementation": "0xfc6e546510dC9d76057F1f76633FCFfC188CB213",
"beacon": "0x275aCcCa81cAD931dC6fB6E49ED233Bc99Bed4A7"
"implementation": "0xfc6e546510dC9d76057F1f76633FCFfC188CB213"
},
"mailbox": {
"kind": "UpgradeBeacon",
"kind": "Transparent",
"proxy": "0x54148470292C24345fb828B003461a9444414517",
"implementation": "0xC2E36cd6e32e194EE11f15D9273B64461A4D49A2",
"beacon": "0x6966b0E55883d49BFB24539356a2f8A673E02039"
"implementation": "0xC2E36cd6e32e194EE11f15D9273B64461A4D49A2"
},
"interchainAccountRouter": "0xc011170d9795a7a2d065E384EAd1CA3394A7d35E",
"interchainQueryRouter": "0x6141e7E7fA2c1beB8be030B0a7DB4b8A10c7c3cd",

@ -1,138 +1 @@
{
"alfajores": {
"upgradeBeaconController": "0x7256A4D01Fc8C3DdAf6415cbb48a5a5464d1E034",
"interchainGasPaymaster": {
"kind": "UpgradeBeacon",
"proxy": "0x974cC4516FdEE100c8f8f5338C7461DfD544a884",
"implementation": "0x945E59Cd57c7E6a3B62997D5876D427f198d32e2",
"beacon": "0x350068a409bF7823aeefE674a5963fA4DbbC020C"
},
"mailbox": {
"kind": "UpgradeBeacon",
"proxy": "0x4dea8886b520450aD19e35206dDFb951fFcDFb17",
"implementation": "0x389bffa5Af799130e7D77D13FA3f1a2A7c2c6324",
"beacon": "0x7eDdB0E12909D7713A99CBB1F69475F7D119938C"
},
"create2Factory": "0xc97D8e6f57b0d64971453dDc6EB8483fec9d163a",
"multisigIsm": "0xcF6bA9D5f6101232C065aD3462F365f0D1bD7fb4"
},
"fuji": {
"upgradeBeaconController": "0x9d29eA8F9e7a04871C30C9d4C4129F0Fad5ab5a0",
"interchainGasPaymaster": {
"kind": "UpgradeBeacon",
"proxy": "0xe0a9bf21Ddee4a0B0F354b25981924A767C6183E",
"implementation": "0x041EbFaE9AD18c2f9bC248832b644c0D2256D3B9",
"beacon": "0x900567ec8701D387e62b85fb01A9E22C862779bC"
},
"mailbox": {
"kind": "UpgradeBeacon",
"proxy": "0x9BA855357227f62263683A275291f3a923C13903",
"implementation": "0xc392687AA3491cb010E0216fb6Caa5Dd7Cbf60b7",
"beacon": "0xad442d59B0a83e51DdF4CaBD9Ee39F28852005D8"
},
"create2Factory": "0xc97D8e6f57b0d64971453dDc6EB8483fec9d163a",
"multisigIsm": "0x12Ac803eeD2707D5845e7c5E73BeDf0Dca331555"
},
"mumbai": {
"upgradeBeaconController": "0x54bDe7D3b78c05b7A686cc5D1211C30483eeAC45",
"interchainGasPaymaster": {
"kind": "UpgradeBeacon",
"proxy": "0x0b8978f247fEFae77dE328706fD5895B187BCa95",
"implementation": "0xe04777c63989C271dBff3Af3f783B5CF84F40D0A",
"beacon": "0x1D15E801F21b5f6ca07c8933D7FE94b29438e405"
},
"mailbox": {
"kind": "UpgradeBeacon",
"proxy": "0x2342eb763F3efeFE5A0BA2a21481fD5Ba7f59A90",
"implementation": "0x2Ad9aFb9bee28cB96C263c469612078E468A8Fe9",
"beacon": "0x9067ebbAf4f28dBDf97b37BC4C7F2b5bF8d54164"
},
"create2Factory": "0xc97D8e6f57b0d64971453dDc6EB8483fec9d163a",
"multisigIsm": "0x4E95F7Bf8a4D963C593A25bb6A8C83942211104A"
},
"bsctestnet": {
"upgradeBeaconController": "0xb10202cA1656A74f793d50EbfcC7F8F78CAab464",
"interchainGasPaymaster": {
"kind": "UpgradeBeacon",
"proxy": "0x81bbe1D62798A9c0ca42F1a41834a6C5E659cAEd",
"implementation": "0x95ADDeb18912d6e6A9FbeF8B40cE44eA8cF2566e",
"beacon": "0xA68774aCEF2D13c1894295d801Bf0FB5b402D10e"
},
"mailbox": {
"kind": "UpgradeBeacon",
"proxy": "0x056d6CAe959B4266291d6BCB3364cdF1Bc8C9814",
"implementation": "0xB99Cf0bf4500BB66469bf949e2CB58535846BD1c",
"beacon": "0xeCc72e8D4E3404175700DE71dfc3474eEa17a89B"
},
"create2Factory": "0xc97D8e6f57b0d64971453dDc6EB8483fec9d163a",
"multisigIsm": "0xdE0Cbd9A17A99348785DA7625cB44a24b5A337be"
},
"goerli": {
"upgradeBeaconController": "0xB9C0c168917aD137D0B75896ee273c3Ed2420012",
"interchainGasPaymaster": {
"kind": "UpgradeBeacon",
"proxy": "0xaC47a6318AdF660ea24994617B27171e85c6b5BE",
"implementation": "0x7e3fb42377ffa28b7B649AE5319d3eB7C2128103",
"beacon": "0x3ddeA0c17578242A17042F2cCf1b09fbBE51AFC3"
},
"mailbox": {
"kind": "UpgradeBeacon",
"proxy": "0x5D5F9793Bc52CfF1522cDEf7206470717d2bae29",
"implementation": "0x7387e72A8F455A2bfb5E211B01d8B6AE2a56c60E",
"beacon": "0x20cC3a33C49fa13627303669edf2DcA7F1E76a50"
},
"create2Factory": "0xc97D8e6f57b0d64971453dDc6EB8483fec9d163a",
"multisigIsm": "0x2a13C3bD245166D1C6515f15fcd1441367FAb675"
},
"moonbasealpha": {
"upgradeBeaconController": "0x0C16e730090cb681460516428c3b2D1BBCB1b647",
"interchainGasPaymaster": {
"kind": "UpgradeBeacon",
"proxy": "0x1fe349d93078B26C8c7350A401e2B60f100952F5",
"implementation": "0x890eB21B76DCB165A1807cBE279f883716eA47D4",
"beacon": "0xBA3f3A84F149842529993bc38A7b4cF8131c17c2"
},
"mailbox": {
"kind": "UpgradeBeacon",
"proxy": "0x711166cE892CBa0Fc01FdD74cFBE73b027678e15",
"implementation": "0x0De2F539569Fb1e2e3C1d233f7A63a18B9A17110",
"beacon": "0x111F4f782B47881898755Bd2F67f12876893300E"
},
"create2Factory": "0xc97D8e6f57b0d64971453dDc6EB8483fec9d163a",
"multisigIsm": "0xD221ffdAa65518BF56c8623e04eA0380CE1BfaE2"
},
"optimismgoerli": {
"upgradeBeaconController": "0x69181Ea49C2F5F7904cEb7299a75620bAd0954FA",
"interchainGasPaymaster": {
"kind": "UpgradeBeacon",
"proxy": "0x62A3fC7873AC96fFF1975663Aa41Ab9100cDe2FB",
"implementation": "0x15846844baD5E06a98056e6c3F87C0ABB0A40d21",
"beacon": "0x5f2fFCF69c58AcA2b521690400756FAe8CC99117"
},
"mailbox": {
"kind": "UpgradeBeacon",
"proxy": "0xd876C01aB40e8cE42Db417fBC79c726d45504dE4",
"implementation": "0x14EE2f01907707Ce8d13C4F5DBC40778b5b664e0",
"beacon": "0x23cD67A76c99578f77C73A306A29905D63D203b4"
},
"create2Factory": "0xc97D8e6f57b0d64971453dDc6EB8483fec9d163a",
"multisigIsm": "0xDA7f1997D52a5f442E83948F7529BceAA6e1fda2"
},
"arbitrumgoerli": {
"upgradeBeaconController": "0xDA7f1997D52a5f442E83948F7529BceAA6e1fda2",
"interchainGasPaymaster": {
"kind": "UpgradeBeacon",
"proxy": "0x0C16e730090cb681460516428c3b2D1BBCB1b647",
"implementation": "0xa1C91dd4F3050DE9C4184BD8B4403A0C81D5463C",
"beacon": "0x603d9041D636CD3218888F1C6F18A4BfeDcdB7F0"
},
"mailbox": {
"kind": "UpgradeBeacon",
"proxy": "0x957ff8ca77Af405D620e47350327fDA24b83070b",
"implementation": "0x11467b49e7BBE3090EC25aF85E172D5ed6F2DA23",
"beacon": "0xC60C145f1e1904f9d6483A611BF1416697CCc1FE"
},
"create2Factory": "0xc97D8e6f57b0d64971453dDc6EB8483fec9d163a",
"multisigIsm": "0x890eB21B76DCB165A1807cBE279f883716eA47D4"
}
}
{}

@ -3,16 +3,12 @@ import { ethers } from 'ethers';
import {
MultisigIsm,
TestIsm__factory,
TestMailbox,
TestMailbox__factory,
} from '@hyperlane-xyz/core';
import { types } from '@hyperlane-xyz/utils';
import { chainMetadata } from '../consts/chainMetadata';
import { HyperlaneCoreDeployer } from '../deploy/core/HyperlaneCoreDeployer';
import { CoreConfig } from '../deploy/core/types';
import { MultiProvider } from '../providers/MultiProvider';
import { BeaconProxyAddresses, ProxiedContract, ProxyKind } from '../proxy';
import { ChainMap, TestChainNames } from '../types';
import { TestCoreApp } from './TestCoreApp';
@ -67,23 +63,6 @@ export class TestCoreDeployer<
return testIsm as unknown as MultisigIsm;
}
// skip proxying
async deployMailbox<LocalChain extends TestChain>(
chain: LocalChain,
defaultIsmAddress: types.Address,
): Promise<ProxiedContract<TestMailbox, BeaconProxyAddresses>> {
const localDomain = chainMetadata[chain].id;
const mailbox = await this.deployContract(chain, 'mailbox', [localDomain]);
await mailbox.initialize(defaultIsmAddress);
return new ProxiedContract(mailbox, {
kind: ProxyKind.UpgradeBeacon,
proxy: mailbox.address,
implementation: mailbox.address,
beacon: mailbox.address,
}) as ProxiedContract<TestMailbox, BeaconProxyAddresses>;
}
async deployApp(): Promise<TestCoreApp<TestChain>> {
return new TestCoreApp(await this.deploy(), this.multiProvider);
}

@ -8,30 +8,30 @@ import {
Mailbox__factory,
MultisigIsm,
MultisigIsm__factory,
UpgradeBeaconController,
UpgradeBeaconController__factory,
ProxyAdmin,
ProxyAdmin__factory,
} from '@hyperlane-xyz/core';
import { BeaconProxyAddresses, ProxiedContract } from '../proxy';
import { ProxiedContract, TransparentProxyAddresses } from '../proxy';
type ConnectionClientContracts = {
interchainGasPaymaster: ProxiedContract<
InterchainGasPaymaster,
BeaconProxyAddresses
TransparentProxyAddresses
>;
};
export type CoreContracts = ConnectionClientContracts & {
mailbox: ProxiedContract<Mailbox, BeaconProxyAddresses>;
mailbox: ProxiedContract<Mailbox, TransparentProxyAddresses>;
multisigIsm: MultisigIsm;
upgradeBeaconController: UpgradeBeaconController;
proxyAdmin: ProxyAdmin;
};
export const coreFactories = {
interchainAccountRouter: new InterchainAccountRouter__factory(),
interchainQueryRouter: new InterchainQueryRouter__factory(),
create2Factory: new Create2Factory__factory(),
upgradeBeaconController: new UpgradeBeaconController__factory(),
proxyAdmin: new ProxyAdmin__factory(),
interchainGasPaymaster: new InterchainGasPaymaster__factory(),
multisigIsm: new MultisigIsm__factory(),
mailbox: new Mailbox__factory(),

@ -4,10 +4,10 @@ import type { types } from '@hyperlane-xyz/utils';
import { HyperlaneApp } from '../HyperlaneApp';
import { MultiProvider } from '../providers/MultiProvider';
import { BeaconProxyAddresses } from '../proxy';
import { TransparentProxyAddresses } from '../proxy';
import { ChainMap, ChainName } from '../types';
import { upgradeBeaconImplementation, upgradeBeaconViolation } from './proxy';
import { proxyAdmin, proxyImplementation, proxyViolation } from './proxy';
import { CheckerViolation, OwnerViolation, ViolationType } from './types';
export abstract class HyperlaneAppChecker<
@ -54,21 +54,26 @@ export abstract class HyperlaneAppChecker<
this.violations.push(violation);
}
async checkUpgradeBeacon(
async checkProxiedContract(
chain: Chain,
name: string,
proxiedAddress: BeaconProxyAddresses,
proxiedAddress: TransparentProxyAddresses,
proxyAdminAddress?: types.Address,
): Promise<void> {
const dc = this.multiProvider.getChainConnection(chain);
const implementation = await upgradeBeaconImplementation(
const implementation = await proxyImplementation(
dc.provider,
proxiedAddress.beacon,
proxiedAddress.proxy,
);
if (implementation !== proxiedAddress.implementation) {
this.addViolation(
upgradeBeaconViolation(chain, name, proxiedAddress, implementation),
proxyViolation(chain, name, proxiedAddress, implementation),
);
}
if (proxyAdminAddress) {
const admin = await proxyAdmin(dc.provider, proxiedAddress.proxy);
utils.assert(admin === proxyAdminAddress, 'Proxy admin mismatch');
}
}
async checkOwnership(

@ -4,10 +4,10 @@ import { ethers } from 'ethers';
import {
Create2Factory__factory,
Ownable,
UpgradeBeaconProxy__factory,
UpgradeBeacon__factory,
ProxyAdmin,
TransparentUpgradeableProxy,
TransparentUpgradeableProxy__factory,
} from '@hyperlane-xyz/core';
import type { types } from '@hyperlane-xyz/utils';
import {
HyperlaneContract,
@ -17,7 +17,11 @@ import {
serializeContracts,
} from '../contracts';
import { MultiProvider } from '../providers/MultiProvider';
import { BeaconProxyAddresses, ProxiedContract, ProxyKind } from '../proxy';
import {
ProxiedContract,
ProxyKind,
TransparentProxyAddresses,
} from '../proxy';
import { ChainMap, ChainName } from '../types';
import { objMap } from '../utils/objects';
@ -112,10 +116,12 @@ export abstract class HyperlaneDeployer<
const dc = this.multiProvider.getChainConnection(chain);
const address = await dc.signer!.getAddress();
const owner = await ownable.owner();
this.logger({ owner });
this.logger({ signer: address });
const logObj = { owner, signer: address };
if (address === owner) {
this.logger('Owner and signer are equal, proceeding', logObj);
return fn();
} else {
this.logger('Owner and signer NOT equal, skipping', logObj);
}
}
@ -123,7 +129,7 @@ export abstract class HyperlaneDeployer<
chain: Chain,
factory: F,
contractName: string,
args: Parameters<F['deploy']>,
constructorArgs: Parameters<F['deploy']>,
deployOpts?: DeployOptions,
): Promise<ReturnType<F['deploy']>> {
const cachedContract = this.deployedContracts[chain]?.[contractName];
@ -145,9 +151,6 @@ export abstract class HyperlaneDeployer<
deployOpts.create2Salt &&
(await chainConnection.provider.getCode(CREATE2FACTORY_ADDRESS)) != '0x'
) {
if (args.length > 0) {
throw new Error("Can't use CREATE2 with deployment args");
}
this.logger(`Deploying with CREATE2 factory`);
const create2Factory = Create2Factory__factory.connect(
@ -157,21 +160,28 @@ export abstract class HyperlaneDeployer<
const salt = ethers.utils.keccak256(
ethers.utils.hexlify(ethers.utils.toUtf8Bytes(deployOpts.create2Salt)),
);
const encodedConstructorArgs =
factory.interface.encodeDeploy(constructorArgs);
const bytecode = ethers.utils.hexlify(
ethers.utils.concat([factory.bytecode, encodedConstructorArgs]),
);
// TODO: Maybe recover deployed contracts?
const contractAddr = await create2Factory.deployedAddress(
factory.bytecode,
bytecode,
await signer.getAddress(),
salt,
);
const deployTx = deployOpts.initCalldata
? await create2Factory.deployAndInit(
factory.bytecode,
bytecode,
salt,
deployOpts.initCalldata,
chainConnection.overrides,
)
: await create2Factory.deploy(
factory.bytecode,
bytecode,
salt,
chainConnection.overrides,
);
@ -181,7 +191,7 @@ export abstract class HyperlaneDeployer<
name: contractName,
address: contractAddr,
isProxy: false,
constructorArguments: '',
constructorArguments: encodedConstructorArgs,
});
return factory.attach(contractAddr).connect(signer) as ReturnType<
@ -190,7 +200,7 @@ export abstract class HyperlaneDeployer<
} else {
const contract = await factory
.connect(signer)
.deploy(...args, chainConnection.overrides);
.deploy(...constructorArgs, chainConnection.overrides);
await chainConnection.handleTx(contract.deployTransaction);
@ -234,31 +244,76 @@ export abstract class HyperlaneDeployer<
protected async deployProxy<C extends ethers.Contract>(
chain: Chain,
implementation: C,
beaconAddress: string,
proxyAdmin: ProxyAdmin,
initArgs: Parameters<C['initialize']>,
): Promise<ProxiedContract<C, BeaconProxyAddresses>> {
deployOpts?: DeployOptions,
): Promise<ProxiedContract<C, TransparentProxyAddresses>> {
const initData = implementation.interface.encodeFunctionData(
'initialize',
initArgs,
);
const deployArgs: Parameters<UpgradeBeaconProxy__factory['deploy']> = [
beaconAddress,
initData,
];
const beaconProxy = await this.deployContractFromFactory(
chain,
new UpgradeBeaconProxy__factory(),
'UpgradeBeaconProxy',
deployArgs,
);
let proxy: TransparentUpgradeableProxy;
const chainConnection = this.multiProvider.getChainConnection(chain);
this.logger(`Deploying transparent upgradable proxy`);
if (
deployOpts &&
deployOpts.create2Salt &&
(await chainConnection.provider.getCode(CREATE2FACTORY_ADDRESS)) != '0x'
) {
// To get consistent addresses with Create2, we need to use
// consistent constructor arguments.
// The three constructor arguments we need to configure are:
// 1. Proxy implementation: This will start as the Create2Factory
// address, as it needs to be a contract address.
// After we've taken over as the proxy admin, we will set it
// to the proper address.
// 2. Proxy admin: This will start as the Create2Factory contract
// address. We will change this to the proper address atomically.
// 3. Initialization data: This will start as null, and we will
// initialize our proxied contract manually.
const constructorArgs: Parameters<
TransparentUpgradeableProxy__factory['deploy']
> = [CREATE2FACTORY_ADDRESS, CREATE2FACTORY_ADDRESS, '0x'];
// We set the initCallData to atomically change admin to the proxyAdmin
// contract.
const initCalldata =
new TransparentUpgradeableProxy__factory().interface.encodeFunctionData(
'changeAdmin',
[proxyAdmin.address],
);
proxy = await this.deployContractFromFactory(
chain,
new TransparentUpgradeableProxy__factory(),
'TransparentUpgradableProxy',
constructorArgs,
{ ...deployOpts, initCalldata },
);
this.logger(`Upgrading and initializing transparent upgradable proxy`);
// We now have a deployed proxy admin'd by ProxyAdmin.
// Upgrade its implementation and initialize it
await proxyAdmin.upgradeAndCall(
proxy.address,
implementation.address,
initData,
);
} else {
const constructorArgs: Parameters<
TransparentUpgradeableProxy__factory['deploy']
> = [implementation.address, proxyAdmin.address, initData];
proxy = await this.deployContractFromFactory(
chain,
new TransparentUpgradeableProxy__factory(),
'TransparentUpgradableProxy',
constructorArgs,
);
}
return new ProxiedContract<C, BeaconProxyAddresses>(
implementation.attach(beaconProxy.address) as C,
return new ProxiedContract<C, TransparentProxyAddresses>(
implementation.attach(proxy.address) as C,
{
kind: ProxyKind.UpgradeBeacon,
proxy: beaconProxy.address,
kind: ProxyKind.Transparent,
proxy: proxy.address,
implementation: implementation.address,
beacon: beaconAddress,
},
);
}
@ -276,7 +331,7 @@ export abstract class HyperlaneDeployer<
}
/**
* Deploys the UpgradeBeacon, Implementation and Proxy for a given contract
* Deploys the Implementation and Proxy for a given contract
*
*/
async deployProxiedContract<
@ -285,61 +340,35 @@ export abstract class HyperlaneDeployer<
>(
chain: Chain,
contractName: K,
deployArgs: Parameters<Factories[K]['deploy']>,
ubcAddress: types.Address,
constructorArgs: Parameters<Factories[K]['deploy']>,
proxyAdmin: ProxyAdmin,
initArgs: Parameters<C['initialize']>,
): Promise<ProxiedContract<C, BeaconProxyAddresses>> {
deployOpts?: DeployOptions,
): Promise<ProxiedContract<C, TransparentProxyAddresses>> {
const cachedProxy = this.deployedContracts[chain]?.[contractName as any];
if (cachedProxy) {
this.logger(`Recovered proxy ${contractName.toString()} on ${chain}`);
return cachedProxy as ProxiedContract<C, BeaconProxyAddresses>;
return cachedProxy as ProxiedContract<C, TransparentProxyAddresses>;
}
const implementation = await this.deployContract<K>(
chain,
contractName,
deployArgs,
constructorArgs,
deployOpts,
);
this.logger(`Proxy ${contractName.toString()} on ${chain}`);
const beaconDeployArgs: Parameters<UpgradeBeacon__factory['deploy']> = [
implementation.address,
ubcAddress,
];
const beacon = await this.deployContractFromFactory(
chain,
new UpgradeBeacon__factory(),
'UpgradeBeacon',
beaconDeployArgs,
);
const contract = await this.deployProxy(
chain,
implementation as C,
beacon.address,
proxyAdmin,
initArgs,
deployOpts,
);
this.cacheContract(chain, contractName, contract);
return contract;
}
/**
* Sets up a new proxy with the same beacon and implementation
*
*/
async duplicateProxiedContract<C extends ethers.Contract>(
chain: Chain,
proxy: ProxiedContract<C, BeaconProxyAddresses>,
initArgs: Parameters<C['initialize']>,
): Promise<ProxiedContract<C, BeaconProxyAddresses>> {
this.logger(`Duplicate Proxy on ${chain}`);
return this.deployProxy(
chain,
proxy.contract.attach(proxy.addresses.implementation) as C,
proxy.addresses.beacon,
initArgs,
);
}
mergeWithExistingVerificationInputs(
existingInputsMap: ChainMap<Chain, ContractVerificationInput[]>,
): ChainMap<Chain, ContractVerificationInput[]> {

@ -29,7 +29,6 @@ export class HyperlaneCoreChecker<
await this.checkProxiedContracts(chain);
await this.checkMailbox(chain);
await this.checkMultisigIsm(chain);
await this.checkInterchainGasPaymaster(chain);
}
async checkDomainOwnership(chain: Chain): Promise<void> {
@ -37,7 +36,7 @@ export class HyperlaneCoreChecker<
if (config.owner) {
const contracts = this.app.getContracts(chain);
const ownables = [
contracts.upgradeBeaconController,
contracts.proxyAdmin,
contracts.mailbox.contract,
contracts.multisigIsm,
];
@ -68,19 +67,17 @@ export class HyperlaneCoreChecker<
async checkProxiedContracts(chain: Chain): Promise<void> {
const contracts = this.app.getContracts(chain);
await this.checkUpgradeBeacon(
await this.checkProxiedContract(
chain,
'Mailbox',
contracts.mailbox.addresses,
contracts.proxyAdmin.address,
);
}
async checkInterchainGasPaymaster(chain: Chain): Promise<void> {
const contracts = this.app.getContracts(chain);
await this.checkUpgradeBeacon(
await this.checkProxiedContract(
chain,
'InterchainGasPaymaster',
contracts.interchainGasPaymaster.addresses,
contracts.mailbox.addresses,
contracts.proxyAdmin.address,
);
}

@ -1,7 +1,13 @@
import debug from 'debug';
import { ethers } from 'ethers';
import { Mailbox, MultisigIsm, Ownable } from '@hyperlane-xyz/core';
import {
InterchainGasPaymaster,
Mailbox,
MultisigIsm,
Ownable,
ProxyAdmin,
} from '@hyperlane-xyz/core';
import type { types } from '@hyperlane-xyz/utils';
import { chainMetadata } from '../../consts/chainMetadata';
@ -10,10 +16,10 @@ import { CoreContracts, coreFactories } from '../../core/contracts';
import { ChainNameToDomainId } from '../../domains';
import { ChainConnection } from '../../providers/ChainConnection';
import { MultiProvider } from '../../providers/MultiProvider';
import { BeaconProxyAddresses, ProxiedContract } from '../../proxy';
import { ProxiedContract, TransparentProxyAddresses } from '../../proxy';
import { ChainMap, ChainName } from '../../types';
import { objMap, promiseObjAll } from '../../utils/objects';
import { HyperlaneDeployer } from '../HyperlaneDeployer';
import { DeployOptions, HyperlaneDeployer } from '../HyperlaneDeployer';
import { CoreConfig } from './types';
@ -38,19 +44,38 @@ export class HyperlaneCoreDeployer<
this.startingBlockNumbers = objMap(configMap, () => undefined);
}
deployInterchainGasPaymaster<LocalChain extends Chain>(
chain: LocalChain,
proxyAdmin: ProxyAdmin,
deployOpts?: DeployOptions,
): Promise<
ProxiedContract<InterchainGasPaymaster, TransparentProxyAddresses>
> {
return this.deployProxiedContract(
chain,
'interchainGasPaymaster',
[],
proxyAdmin,
[],
deployOpts,
);
}
async deployMailbox<LocalChain extends Chain>(
chain: LocalChain,
defaultIsmAddress: types.Address,
ubcAddress: types.Address,
): Promise<ProxiedContract<Mailbox, BeaconProxyAddresses>> {
proxyAdmin: ProxyAdmin,
deployOpts?: DeployOptions,
): Promise<ProxiedContract<Mailbox, TransparentProxyAddresses>> {
const domain = chainMetadata[chain].id;
const mailbox = await this.deployProxiedContract(
chain,
'mailbox',
[domain],
ubcAddress,
proxyAdmin,
[defaultIsmAddress],
deployOpts,
);
return mailbox;
}
@ -66,39 +91,58 @@ export class HyperlaneCoreDeployer<
.multiProvider.remoteChains(chain);
await super.runIfOwner(chain, multisigIsm, async () => {
// TODO: Remove extraneous validators
for (const remote of remotes) {
const multisigIsmConfig = this.configMap[remote].multisigIsm;
const domain = ChainNameToDomainId[remote];
await Promise.all(
multisigIsmConfig.validators.map(async (validator) => {
const isValidator = await multisigIsm.isEnrolled(domain, validator);
if (!isValidator) {
this.logger(
`Enrolling ${validator} as ${remote} validator on ${chain}`,
);
await chainConnection.handleTx(
multisigIsm.enrollValidator(
domain,
validator,
chainConnection.overrides,
),
);
}
}),
const remoteDomains = remotes.map((chain) => ChainNameToDomainId[chain]);
const actualValidators = await Promise.all(
remoteDomains.map((id) => multisigIsm.validators(id)),
);
const expectedValidators = remotes.map(
(chain) => this.configMap[chain].multisigIsm.validators,
);
const validatorsToEnroll = expectedValidators.map((validators, i) =>
validators.filter(
(validator) =>
!actualValidators[i].includes(ethers.utils.getAddress(validator)),
),
);
const chainsToEnrollValidators = remotes.filter(
(_, i) => validatorsToEnroll[i].length > 0,
);
if (chainsToEnrollValidators.length > 0) {
this.logger(
`Enroll ${chainsToEnrollValidators} validators on ${chain}`,
);
await chainConnection.handleTx(
multisigIsm.enrollValidators(
chainsToEnrollValidators.map((c) => ChainNameToDomainId[c]),
validatorsToEnroll.filter((validators) => validators.length > 0),
chainConnection.overrides,
),
);
}
const actualThresholds = await Promise.all(
remoteDomains.map((id) => multisigIsm.threshold(id)),
);
const expectedThresholds = remotes.map(
(chain) => this.configMap[chain].multisigIsm.threshold,
);
const chainsToSetThreshold = remotes.filter(
(_, i) => actualThresholds[i] !== expectedThresholds[i],
);
if (chainsToSetThreshold.length > 0) {
this.logger(
`Set remote (${chainsToSetThreshold}) thresholds on ${chain}`,
);
const threshold = await multisigIsm.threshold(domain);
if (threshold !== multisigIsmConfig.threshold) {
this.logger(
`Setting ${remote} threshold to ${multisigIsmConfig.threshold} on ${chain}`,
);
await chainConnection.handleTx(
multisigIsm.setThreshold(
domain,
multisigIsmConfig.threshold,
chainConnection.overrides,
await chainConnection.handleTx(
multisigIsm.setThresholds(
chainsToSetThreshold.map((c) => ChainNameToDomainId[c]),
chainsToSetThreshold.map(
(c) => this.configMap[c].multisigIsm.threshold,
),
);
}
chainConnection.overrides,
),
);
}
});
@ -118,31 +162,21 @@ export class HyperlaneCoreDeployer<
const provider = dc.provider!;
const startingBlockNumber = await provider.getBlockNumber();
this.startingBlockNumbers[chain] = startingBlockNumber;
const multisigIsm = await this.deployMultisigIsm(chain);
const upgradeBeaconController = await this.deployContract(
chain,
'upgradeBeaconController',
[],
);
const interchainGasPaymaster = await this.deployProxiedContract(
const proxyAdmin = await this.deployContract(chain, 'proxyAdmin', []);
const interchainGasPaymaster = await this.deployInterchainGasPaymaster(
chain,
'interchainGasPaymaster',
[],
upgradeBeaconController.address,
[],
proxyAdmin,
);
const multisigIsm = await this.deployMultisigIsm(chain);
const mailbox = await this.deployMailbox(
chain,
multisigIsm.address,
upgradeBeaconController.address,
proxyAdmin,
);
return {
upgradeBeaconController,
proxyAdmin,
interchainGasPaymaster,
mailbox,
multisigIsm,
@ -173,7 +207,7 @@ export class HyperlaneCoreDeployer<
const ownables: Ownable[] = [
coreContracts.mailbox.contract,
coreContracts.multisigIsm,
coreContracts.upgradeBeaconController,
coreContracts.proxyAdmin,
];
return Promise.all(
ownables.map((ownable) =>

@ -2,44 +2,59 @@ import { ethers } from 'ethers';
import type { types } from '@hyperlane-xyz/utils';
import { BeaconProxyAddresses } from '../proxy';
import { TransparentProxyAddresses } from '../proxy';
import { ChainName } from '../types';
import { CheckerViolation } from './types';
export interface UpgradeBeaconViolation extends CheckerViolation {
type: BeaconProxyAddresses['kind'];
export interface ProxyViolation extends CheckerViolation {
type: TransparentProxyAddresses['kind'];
data: {
proxiedAddress: BeaconProxyAddresses;
proxyAddresses: TransparentProxyAddresses;
name: string;
};
actual: string;
expected: string;
}
export async function upgradeBeaconImplementation(
export async function proxyImplementation(
provider: ethers.providers.Provider,
beacon: types.Address,
proxy: types.Address,
): Promise<types.Address> {
// TODO: This should check the correct upgrade beacon controller
const storageValue = await provider.getStorageAt(beacon, 0);
// Hardcoded storage slot for implementation per EIP-1967
const storageValue = await provider.getStorageAt(
proxy,
'0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc',
);
return ethers.utils.getAddress(storageValue.slice(26));
}
export function upgradeBeaconViolation<Chain extends ChainName>(
export async function proxyAdmin(
provider: ethers.providers.Provider,
proxy: types.Address,
): Promise<types.Address> {
// Hardcoded storage slot for admin per EIP-1967
const storageValue = await provider.getStorageAt(
proxy,
'0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103',
);
return ethers.utils.getAddress(storageValue.slice(26));
}
export function proxyViolation<Chain extends ChainName>(
chain: Chain,
name: string,
proxiedAddress: BeaconProxyAddresses,
proxyAddresses: TransparentProxyAddresses,
actual: types.Address,
): UpgradeBeaconViolation {
): ProxyViolation {
return {
chain,
type: proxiedAddress.kind,
type: proxyAddresses.kind,
actual,
expected: proxiedAddress.implementation,
expected: proxyAddresses.implementation,
data: {
name,
proxiedAddress,
proxyAddresses,
},
};
}

@ -46,7 +46,11 @@ export {
TSContract,
} from './events';
export { BeaconProxyAddresses, ProxiedContract, ProxyAddresses } from './proxy';
export {
TransparentProxyAddresses,
ProxiedContract,
ProxyAddresses,
} from './proxy';
export { Router, RouterContracts, RouterFactories } from './router';
@ -99,7 +103,7 @@ export {
MultisigIsmViolationType,
} from './deploy/core/types';
export { HyperlaneDeployer } from './deploy/HyperlaneDeployer';
export { UpgradeBeaconViolation } from './deploy/proxy';
export { ProxyViolation } from './deploy/proxy';
export { HyperlaneRouterDeployer } from './deploy/router/HyperlaneRouterDeployer';
export { HyperlaneRouterChecker } from './deploy/router/HyperlaneRouterChecker';
export {

@ -5,7 +5,7 @@ import type { types } from '@hyperlane-xyz/utils';
import { Connection } from './types';
export enum ProxyKind {
UpgradeBeacon = 'UpgradeBeacon',
Transparent = 'Transparent',
}
export interface ProxyAddresses<Kind extends ProxyKind> {
@ -27,10 +27,7 @@ export function isProxyAddresses(
);
}
export interface BeaconProxyAddresses
extends ProxyAddresses<ProxyKind.UpgradeBeacon> {
beacon: types.Address;
}
export type TransparentProxyAddresses = ProxyAddresses<ProxyKind.Transparent>;
export class ProxiedContract<
C extends Contract,

Loading…
Cancel
Save