diff --git a/contracts/AddressResolver.sol b/contracts/AddressResolver.sol index b8820060..43460cc3 100644 --- a/contracts/AddressResolver.sol +++ b/contracts/AddressResolver.sol @@ -28,6 +28,7 @@ contract AddressResolver is OwnableTwoStep, IAddressResolver, Initializable { address[] internal _promises; uint256 public asyncPromiseCounter; + uint64 public version; // contracts to gateway map mapping(address => address) public override contractsToGateways; @@ -48,7 +49,8 @@ contract AddressResolver is OwnableTwoStep, IAddressResolver, Initializable { /// @notice Initializer to replace constructor for upgradeable contracts /// @param owner_ The address of the contract owner - function initialize(address owner_) public reinitializer(1) { + function initialize(address owner_, uint64 version_) public reinitializer(version_) { + version = version_; _claimOwner(owner_); forwarderImplementation = address(new Forwarder()); @@ -98,7 +100,8 @@ contract AddressResolver is OwnableTwoStep, IAddressResolver, Initializable { Forwarder.initialize.selector, chainSlug_, chainContractAddress_, - address(this) + address(this), + version ); salt = keccak256(constructorArgs); } @@ -111,7 +114,8 @@ contract AddressResolver is OwnableTwoStep, IAddressResolver, Initializable { AsyncPromise.initialize.selector, invoker_, msg.sender, - address(this) + address(this), + version ); salt = keccak256(abi.encodePacked(constructorArgs, asyncPromiseCounter)); diff --git a/contracts/AsyncPromise.sol b/contracts/AsyncPromise.sol index a3f45114..3c84131a 100644 --- a/contracts/AsyncPromise.sol +++ b/contracts/AsyncPromise.sol @@ -59,7 +59,7 @@ contract AsyncPromise is IPromise, Initializable, AddressResolverUtil { address invoker_, address forwarder_, address addressResolver_ - ) public reinitializer(1) { + ) public initializer { _setAddressResolver(addressResolver_); localInvoker = invoker_; forwarder = forwarder_; diff --git a/contracts/Forwarder.sol b/contracts/Forwarder.sol index d1993af0..43e4656e 100644 --- a/contracts/Forwarder.sol +++ b/contracts/Forwarder.sol @@ -23,6 +23,7 @@ contract Forwarder is IForwarder, Initializable { /// @notice caches the latest async promise address for the last call address public latestAsyncPromise; + uint64 public version; constructor() { _disableInitializers(); // disable for implementation @@ -36,7 +37,7 @@ contract Forwarder is IForwarder, Initializable { uint32 chainSlug_, address onChainAddress_, address addressResolver_ - ) public reinitializer(1) { + ) public initializer { chainSlug = chainSlug_; onChainAddress = onChainAddress_; addressResolver = addressResolver_; diff --git a/contracts/apps/payload-delivery/app-gateway/AuctionManager.sol b/contracts/apps/payload-delivery/app-gateway/AuctionManager.sol index 484e0add..d72bf380 100644 --- a/contracts/apps/payload-delivery/app-gateway/AuctionManager.sol +++ b/contracts/apps/payload-delivery/app-gateway/AuctionManager.sol @@ -21,6 +21,7 @@ contract AuctionManager is AddressResolverUtil, OwnableTwoStep, IAuctionManager, mapping(bytes32 => bool) public override auctionStarted; uint256 public auctionEndDelaySeconds; + uint64 public version; /// @notice Error thrown when trying to start or bid a closed auction error AuctionClosed(); @@ -46,10 +47,12 @@ contract AuctionManager is AddressResolverUtil, OwnableTwoStep, IAuctionManager, uint256 auctionEndDelaySeconds_, address addressResolver_, SignatureVerifier signatureVerifier_, - address owner_ - ) public reinitializer(1) { + address owner_, + uint64 version_ + ) public reinitializer(version_) { _setAddressResolver(addressResolver_); _claimOwner(owner_); + version = version_; vmChainSlug = vmChainSlug_; signatureVerifier = signatureVerifier_; auctionEndDelaySeconds = auctionEndDelaySeconds_; diff --git a/contracts/apps/payload-delivery/app-gateway/DeliveryHelper.sol b/contracts/apps/payload-delivery/app-gateway/DeliveryHelper.sol index 59e44cf9..a8151dca 100644 --- a/contracts/apps/payload-delivery/app-gateway/DeliveryHelper.sol +++ b/contracts/apps/payload-delivery/app-gateway/DeliveryHelper.sol @@ -11,6 +11,7 @@ import "solady/utils/Initializable.sol"; contract DeliveryHelper is BatchAsync, OwnableTwoStep, Initializable { event CallBackReverted(bytes32 asyncId_, bytes32 payloadId_); + uint64 public version; constructor() { _disableInitializers(); // disable for implementation @@ -24,9 +25,11 @@ contract DeliveryHelper is BatchAsync, OwnableTwoStep, Initializable { address addressResolver_, address feesManager_, address owner_, - uint256 bidTimeout_ - ) public reinitializer(1) { + uint256 bidTimeout_, + uint64 version_ + ) public reinitializer(version_) { _setAddressResolver(addressResolver_); + version = version_; feesManager = feesManager_; bidTimeout = bidTimeout_; _claimOwner(owner_); diff --git a/contracts/apps/payload-delivery/app-gateway/FeesManager.sol b/contracts/apps/payload-delivery/app-gateway/FeesManager.sol index 193730e2..46037e00 100644 --- a/contracts/apps/payload-delivery/app-gateway/FeesManager.sol +++ b/contracts/apps/payload-delivery/app-gateway/FeesManager.sol @@ -16,6 +16,7 @@ import "solady/utils/Initializable.sol"; contract FeesManager is IFeesManager, AddressResolverUtil, OwnableTwoStep, Initializable { uint256 public feesCounter; mapping(uint32 => uint256) public feeCollectionGasLimit; + uint64 public version; /// @notice Struct containing fee amounts and status struct TokenBalance { @@ -99,7 +100,12 @@ contract FeesManager is IFeesManager, AddressResolverUtil, OwnableTwoStep, Initi /// @notice Initializer function to replace constructor /// @param addressResolver_ The address of the address resolver /// @param owner_ The address of the owner - function initialize(address addressResolver_, address owner_) public reinitializer(1) { + function initialize( + address addressResolver_, + address owner_, + uint64 version_ + ) public reinitializer(version_) { + version = version_; _setAddressResolver(addressResolver_); _claimOwner(owner_); } diff --git a/contracts/socket/utils/SignatureVerifier.sol b/contracts/socket/utils/SignatureVerifier.sol index 1ed682c0..6391bd13 100644 --- a/contracts/socket/utils/SignatureVerifier.sol +++ b/contracts/socket/utils/SignatureVerifier.sol @@ -14,6 +14,8 @@ import "solady/utils/Initializable.sol"; * @dev This contract is modular component in socket to support different signing algorithms. */ contract SignatureVerifier is ISignatureVerifier, AccessControl, Initializable { + uint64 public version; + /* * @dev Error thrown when signature length is invalid */ @@ -23,7 +25,8 @@ contract SignatureVerifier is ISignatureVerifier, AccessControl, Initializable { * @notice initializes and grants RESCUE_ROLE to owner. * @param owner_ The address of the owner of the contract. */ - function initialize(address owner_) public reinitializer(1) { + function initialize(address owner_, uint64 version_) public reinitializer(version_) { + version = version_; _claimOwner(owner_); _grantRole(RESCUE_ROLE, owner_); } diff --git a/contracts/watcherPrecompile/WatcherPrecompile.sol b/contracts/watcherPrecompile/WatcherPrecompile.sol index 263b87c6..32d8054f 100644 --- a/contracts/watcherPrecompile/WatcherPrecompile.sol +++ b/contracts/watcherPrecompile/WatcherPrecompile.sol @@ -37,6 +37,8 @@ contract WatcherPrecompile is WatcherPrecompileConfig, Initializable { /// @dev callId => bool mapping(bytes32 => bool) public appGatewayCalled; + uint64 public version; + /// @notice Error thrown when an invalid chain slug is provided error InvalidChainSlug(); /// @notice Error thrown when an invalid app gateway reaches a plug @@ -97,10 +99,12 @@ contract WatcherPrecompile is WatcherPrecompileConfig, Initializable { function initialize( address owner_, address addressResolver_, - uint256 maxLimit_ - ) public reinitializer(1) { + uint256 maxLimit_, + uint64 version_ + ) public reinitializer(version_) { _setAddressResolver(addressResolver_); _claimOwner(owner_); + version = version_; maxTimeoutDelayInSeconds = 24 * 60 * 60; // 24 hours LIMIT_DECIMALS = 18; diff --git a/deployments/dev_addresses.json b/deployments/dev_addresses.json index e9b64f59..04d10cda 100644 --- a/deployments/dev_addresses.json +++ b/deployments/dev_addresses.json @@ -1,38 +1,38 @@ { "421614": { - "SignatureVerifier": "0x5e5CF700c97BC8B3F6215D98E65f85D4A44d7D06", - "Hasher": "0x6A8e801B3299FeB96D0607A01a62Db8A9239Bdc0", - "Socket": "0xa09217Cfc47F399C382E982778f6128685e13aD4", - "SocketBatcher": "0x80568677f2B092bd974657FE47Fc8531bfE5DBDC", - "FastSwitchboard": "0x5aA84ffE5eCCB5263d1AE6aEd5682EAb39Bc7036", - "FeesPlug": "0x63d3F60Db6a7Eb2fa730F850dA247C73aD162656", - "ContractFactoryPlug": "0x87cC19AedD434ebD3B74FfdC073CAeC7dC1E92EA", - "startBlock": 123791225 + "ContractFactoryPlug": "0xE86EdC6457Bf25434b6D23AdbE2F8D3D975e67FC", + "FastSwitchboard": "0xFF0A8a7BBB3a1C7Fb64318B1f3Cff50c52530370", + "FeesPlug": "0x78aE0a397Bb16d08956F040f97182fdcC19200DD", + "Hasher": "0x491B2365BB79520F0f4884e6e022287683671245", + "SignatureVerifier": "0x99DC5Cb4DadbDF09cc46E7F6e0B514094e928f9a", + "Socket": "0x82dC1E9882CDCB071B1940503585E9E6be527511", + "SocketBatcher": "0x75111143CbfdE7F8C5e558ad78AB4141ED3DbE6b", + "startBlock": 124608724 }, "7625382": { - "SignatureVerifierImpl": "0xCd44A8068117d888fb44Eb4fDe49bc9B7085189E", - "AddressResolverImpl": "0xBCF275473fdECEf5AFe22D1c771Cb79317be58dB", - "ERC1967Factory": "0xaAF245274e877795B01671602a753AafAc459297", - "SignatureVerifier": "0x2eF8A7768c42342927B9e41E468CC2984835DC58", - "AddressResolver": "0xF2bb0cA7Eab6a2c4ed64793959Ac4401159D5D13", - "WatcherPrecompileImpl": "0x345c85aCc495E6FeDCf52987BDc0636A12F8AEd7", - "WatcherPrecompile": "0x376AdA81749a64e9C2439025f475D1a7E004fcC1", - "FeesManagerImpl": "0x3Ee25f844976888B29A921443b34374d9eCC466d", - "FeesManager": "0x4D29076a0590909F3Bda7f85466cd8Ee291A1247", - "DeliveryHelperImpl": "0xAEE7D460fD1d8c4be069443a65187BC50A0BA89A", - "DeliveryHelper": "0xc0560207cBDBc5301E8343C51f8A7da339596969", - "AuctionManagerImpl": "0x6B94BfF71631f21166946e80967774F3f45e9A0b", - "AuctionManager": "0xE5A00A99C5C8E40d1C6Ec817bc808d71b1d4369b", - "startBlock": 5424 + "AddressResolver": "0x83b9f8829870989c233eD457FEBf5E2852F6f7e6", + "AddressResolverImpl": "0xE6C9cf66F57f6aF78585235E36E94007020e3746", + "AuctionManager": "0xE285dA5E0Af241148196045a8D0c554e9dCfdc5B", + "AuctionManagerImpl": "0xb888e3a8F9cC8F0281796958B01862427417b0Ea", + "DeliveryHelper": "0x96DD7A17d8BB599365d437ab0F34d7505187F9E8", + "DeliveryHelperImpl": "0x5bA4C527883F7D9e12d71Da5Cd170f26eCF2F901", + "ERC1967Factory": "0x494660a4bDcafC43a5522B98117D678654c6D3d5", + "FeesManager": "0x1B0d860ffC6D42Bc0Bd6C4b5bCe39F6694392AF5", + "FeesManagerImpl": "0x731f609cae8C9B6862B4c1D43dE29d4759f878F8", + "SignatureVerifier": "0x050433b2288F24FE6d87D3081343038D3BfBe39E", + "SignatureVerifierImpl": "0x70BA68CbDFc530E1AD62d9aFAf43a40B87D0730b", + "startBlock": 5488, + "WatcherPrecompile": "0xB588980Af36d5b718eBd4FCe3170Ee5Dd04A57D8", + "WatcherPrecompileImpl": "0x32D3c608405b9b037A574550a40477F8Ea1f8B5B" }, "11155420": { - "SignatureVerifier": "0x36AC527afA283c95EA7dD11c8E93225d9F139028", - "Hasher": "0xd36C1Dcb65CB09b7fCFABf153D7cdd42312C782E", - "Socket": "0xB0e1D8536ed769860f344Cf795f2B4fAaa41F0C8", - "SocketBatcher": "0x5fef21aD7Dc13CB1b7Cb9EAD404e3EA38d153348", - "FastSwitchboard": "0x688cf2744cd66F00E34f8BbAd15C8fb2438D62be", - "FeesPlug": "0xc13eb89675c12efF5faf5bE9B4773F9ed9192107", - "ContractFactoryPlug": "0x0E0F673C9b34d08b99407F1947A10Fe73aa17928", - "startBlock": 23870487 + "ContractFactoryPlug": "0x6EF9c18c1A69417625f4Cb3c634124a71025C3A9", + "FastSwitchboard": "0x1E407363aec8952bff0ff35A596997d11b32f9c4", + "FeesPlug": "0x70B9067056b533A4e780C5E64228C60defFbC558", + "Hasher": "0xb34DB19C7FAeECf14B3D0336C6E34f7dc1336968", + "SignatureVerifier": "0xF86B89B5c689c170BfD2734254228D6d2db5a672", + "Socket": "0xfBa932AaE9Ae2777aEC77832FC0C2D9059C8E905", + "SocketBatcher": "0xdd7b56968a3505D1A10181F2880cAA65a89E4750", + "startBlock": 23996336 } } diff --git a/deployments/dev_addresses_geth.json b/deployments/dev_addresses_geth.json new file mode 100644 index 00000000..9498b9b1 --- /dev/null +++ b/deployments/dev_addresses_geth.json @@ -0,0 +1,38 @@ +{ + "421614": { + "ContractFactoryPlug": "0x1dc20d27F06876cA74ee4e2E9a4724f06a4a5E54", + "FastSwitchboard": "0xaFFfaD81e6DDE509Bd83Ab2024225b2FF537BeA7", + "FeesPlug": "0xb2B779ab8FC851bCE986d25B2824933B0Cd101d9", + "Hasher": "0x49f24A72e738Fe86263Aa26696370972e049498B", + "SignatureVerifier": "0xb6d39d1dB2cB14043182a008EfFC079A9C578208", + "Socket": "0x9B06e2Dae351ed8B1112C036e5c306E8fBe4C9c5", + "SocketBatcher": "0xd627BFe7d2fCAC1147c996a6F2CAaB2E1e1bD344", + "startBlock": 124035386 + }, + "7625382": { + "AddressResolver": "0x1287D33646d763Ff8237Aa7BE7d92Fc918c66589", + "AddressResolverImpl": "0x8662FC08dEC7c61Dd3432fAF45a5bC024BB60B00", + "AuctionManager": "0xE3806Bc41FEAFCAA2480E702fF02dA14F767bF0F", + "AuctionManagerImpl": "0x4C68058509d754Cc0dE474eBC20aE94e4787E704", + "DeliveryHelper": "0x4D8Fb6e8a5294ed0644f462b5723ee228ecf9958", + "DeliveryHelperImpl": "0x3c9f5172feb0dDfC06176cE67B566EFbb01CCe98", + "ERC1967Factory": "0xbBfb525ADc6eC38Ef0D4b807d327c2Dd1C286de1", + "FeesManager": "0x886682a69D6c0240EB850cc2e42c5B4B74449e82", + "FeesManagerImpl": "0xF4D3BDe438416938217d4624c82AEbEb46CeD371", + "SignatureVerifier": "0x366Dea9AC69fb9D45b6756587D2fE9B4c14197F6", + "SignatureVerifierImpl": "0x3cf47Ad0F040dFF1208E649C8f8e23e6B5A08916", + "startBlock": 18, + "WatcherPrecompile": "0xaCf94Cd4A7e70304F5CA6294CDAe3CBe78Ea6A86", + "WatcherPrecompileImpl": "0x8F18fC10a8b40b548C6F04Fb252481c783A9ace0" + }, + "11155420": { + "ContractFactoryPlug": "0x0EE19F0D0e34Cdd2eb4F61E24DC837b0b7c34e69", + "FastSwitchboard": "0x70bfB36F8b8de7763F1D52d954225ae88F6Ed595", + "FeesPlug": "0x7F5D263572469Fdf1875Cd858D557B45e9FC7f23", + "Hasher": "0xe37D675646A6FEEC3E41A0FF9535E0E716f5cD89", + "SignatureVerifier": "0x0452225B52Ef6134499232CbBEDF05fD8cc38530", + "Socket": "0x0BAAD473580c9F7Ca8b2758759aF3ce5E3154bC6", + "SocketBatcher": "0xCf731f35EFd775F692fe24e650e75Fd64bBaD810", + "startBlock": 23911773 + } +} diff --git a/deployments/dev_verification.json b/deployments/dev_verification.json index ac69d1ce..2c945377 100644 --- a/deployments/dev_verification.json +++ b/deployments/dev_verification.json @@ -1,196 +1,48 @@ { - "421614": [ - [ - "0x87cC19AedD434ebD3B74FfdC073CAeC7dC1E92EA", - "ContractFactoryPlug", - "contracts/apps/payload-delivery/ContractFactoryPlug.sol", - [ - "0xa09217Cfc47F399C382E982778f6128685e13aD4", - "0x3339Cf48f1F9cf31b6F8c2664d144c7444eBBB18" - ] - ], - [ - "0x63d3F60Db6a7Eb2fa730F850dA247C73aD162656", - "FeesPlug", - "contracts/apps/payload-delivery/FeesPlug.sol", - [ - "0xa09217Cfc47F399C382E982778f6128685e13aD4", - "0x3339Cf48f1F9cf31b6F8c2664d144c7444eBBB18" - ] - ], - [ - "0x5aA84ffE5eCCB5263d1AE6aEd5682EAb39Bc7036", - "FastSwitchboard", - "contracts/socket/switchboard/FastSwitchboard.sol", - [ - 421614, - "0xa09217Cfc47F399C382E982778f6128685e13aD4", - "0x5e5CF700c97BC8B3F6215D98E65f85D4A44d7D06", - "0x3339Cf48f1F9cf31b6F8c2664d144c7444eBBB18" - ] - ], - [ - "0x80568677f2B092bd974657FE47Fc8531bfE5DBDC", - "SocketBatcher", - "contracts/socket/SocketBatcher.sol", - [ - "0x3339Cf48f1F9cf31b6F8c2664d144c7444eBBB18", - "0xa09217Cfc47F399C382E982778f6128685e13aD4" - ] - ], - [ - "0xa09217Cfc47F399C382E982778f6128685e13aD4", - "Socket", - "contracts/socket/Socket.sol", - [ - 421614, - "0x6A8e801B3299FeB96D0607A01a62Db8A9239Bdc0", - "0x5e5CF700c97BC8B3F6215D98E65f85D4A44d7D06", - "0x3339Cf48f1F9cf31b6F8c2664d144c7444eBBB18", - "OFF_CHAIN_VM" - ] - ], - [ - "0x6A8e801B3299FeB96D0607A01a62Db8A9239Bdc0", - "Hasher", - "contracts/socket/utils/Hasher.sol", - [ - "0x3339Cf48f1F9cf31b6F8c2664d144c7444eBBB18" - ] - ], - [ - "0x5e5CF700c97BC8B3F6215D98E65f85D4A44d7D06", - "SignatureVerifier", - "contracts/socket/utils/SignatureVerifier.sol", - [] - ], - [ - "0xBB4Bca54f566fc04b7A7489fF00265a1cE38b929", - "SignatureVerifier", - "contracts/socket/utils/SignatureVerifier.sol", - [] - ] - ], + "421614": [], "7625382": [ [ - "0x6B94BfF71631f21166946e80967774F3f45e9A0b", + "0xb888e3a8F9cC8F0281796958B01862427417b0Ea", "AuctionManager", "contracts/apps/payload-delivery/app-gateway/AuctionManager.sol", [] ], [ - "0xAEE7D460fD1d8c4be069443a65187BC50A0BA89A", + "0x5bA4C527883F7D9e12d71Da5Cd170f26eCF2F901", "DeliveryHelper", "contracts/apps/payload-delivery/app-gateway/DeliveryHelper.sol", [] ], [ - "0x3Ee25f844976888B29A921443b34374d9eCC466d", + "0x731f609cae8C9B6862B4c1D43dE29d4759f878F8", "FeesManager", "contracts/apps/payload-delivery/app-gateway/FeesManager.sol", [] ], [ - "0x345c85aCc495E6FeDCf52987BDc0636A12F8AEd7", + "0x32D3c608405b9b037A574550a40477F8Ea1f8B5B", "WatcherPrecompile", "contracts/watcherPrecompile/WatcherPrecompile.sol", [] ], [ - "0xaAF245274e877795B01671602a753AafAc459297", - "ERC1967Factory", - "lib/solady/src/utils/ERC1967Factory.sol", - [] - ], - [ - "0x8AAE7259Fd08cb555076A384bc228c8B20BcC4a7", - "ERC1967Factory", - "lib/solady/src/utils/ERC1967Factory.sol", - [] - ], - [ - "0xBCF275473fdECEf5AFe22D1c771Cb79317be58dB", + "0xE6C9cf66F57f6aF78585235E36E94007020e3746", "AddressResolver", "contracts/AddressResolver.sol", [] ], [ - "0xCd44A8068117d888fb44Eb4fDe49bc9B7085189E", + "0x70BA68CbDFc530E1AD62d9aFAf43a40B87D0730b", "SignatureVerifier", "contracts/socket/utils/SignatureVerifier.sol", [] ], [ - "0xa93B1119677f02445DAb5034841FC6C937340900", + "0x494660a4bDcafC43a5522B98117D678654c6D3d5", "ERC1967Factory", "lib/solady/src/utils/ERC1967Factory.sol", [] ] ], - "11155420": [ - [ - "0x0E0F673C9b34d08b99407F1947A10Fe73aa17928", - "ContractFactoryPlug", - "contracts/apps/payload-delivery/ContractFactoryPlug.sol", - [ - "0xB0e1D8536ed769860f344Cf795f2B4fAaa41F0C8", - "0x3339Cf48f1F9cf31b6F8c2664d144c7444eBBB18" - ] - ], - [ - "0xc13eb89675c12efF5faf5bE9B4773F9ed9192107", - "FeesPlug", - "contracts/apps/payload-delivery/FeesPlug.sol", - [ - "0xB0e1D8536ed769860f344Cf795f2B4fAaa41F0C8", - "0x3339Cf48f1F9cf31b6F8c2664d144c7444eBBB18" - ] - ], - [ - "0x688cf2744cd66F00E34f8BbAd15C8fb2438D62be", - "FastSwitchboard", - "contracts/socket/switchboard/FastSwitchboard.sol", - [ - 11155420, - "0xB0e1D8536ed769860f344Cf795f2B4fAaa41F0C8", - "0x36AC527afA283c95EA7dD11c8E93225d9F139028", - "0x3339Cf48f1F9cf31b6F8c2664d144c7444eBBB18" - ] - ], - [ - "0x5fef21aD7Dc13CB1b7Cb9EAD404e3EA38d153348", - "SocketBatcher", - "contracts/socket/SocketBatcher.sol", - [ - "0x3339Cf48f1F9cf31b6F8c2664d144c7444eBBB18", - "0xB0e1D8536ed769860f344Cf795f2B4fAaa41F0C8" - ] - ], - [ - "0xB0e1D8536ed769860f344Cf795f2B4fAaa41F0C8", - "Socket", - "contracts/socket/Socket.sol", - [ - 11155420, - "0xd36C1Dcb65CB09b7fCFABf153D7cdd42312C782E", - "0x36AC527afA283c95EA7dD11c8E93225d9F139028", - "0x3339Cf48f1F9cf31b6F8c2664d144c7444eBBB18", - "OFF_CHAIN_VM" - ] - ], - [ - "0xd36C1Dcb65CB09b7fCFABf153D7cdd42312C782E", - "Hasher", - "contracts/socket/utils/Hasher.sol", - [ - "0x3339Cf48f1F9cf31b6F8c2664d144c7444eBBB18" - ] - ], - [ - "0x36AC527afA283c95EA7dD11c8E93225d9F139028", - "SignatureVerifier", - "contracts/socket/utils/SignatureVerifier.sol", - [] - ] - ] + "11155420": [] } diff --git a/hardhat-scripts/constants/constants.ts b/hardhat-scripts/constants/constants.ts index b908f2ea..df871a12 100644 --- a/hardhat-scripts/constants/constants.ts +++ b/hardhat-scripts/constants/constants.ts @@ -14,3 +14,4 @@ export const BASE_SEPOLIA_CHAIN_ID = 84532; export const EVMX_CHAIN_ID = 7625382; export const MAX_LIMIT = 100; export const BID_TIMEOUT = 1000; +export const VERSION = 1; diff --git a/hardhat-scripts/constants/overrides.ts b/hardhat-scripts/constants/overrides.ts index 63159ee8..f79babc2 100644 --- a/hardhat-scripts/constants/overrides.ts +++ b/hardhat-scripts/constants/overrides.ts @@ -27,9 +27,9 @@ export const chainOverrides: { // gasPrice: 212_000_000_000, }, [EVMX_CHAIN_ID as ChainSlug]: { - // type: 1, - gasLimit: 1_000_000_000, - // gasPrice: 212_000_000_000, + type: 0, + // gasLimit: 1_000_000_000, + gasPrice: 0, }, }; diff --git a/hardhat-scripts/deploy/1.deploy.ts b/hardhat-scripts/deploy/1.deploy.ts index 44cfbb34..e2ed176f 100644 --- a/hardhat-scripts/deploy/1.deploy.ts +++ b/hardhat-scripts/deploy/1.deploy.ts @@ -13,7 +13,12 @@ import { getProviderFromChainSlug } from "../constants"; import { ethers } from "hardhat"; import dev_addresses from "../../deployments/dev_addresses.json"; import { auctionEndDelaySeconds, chains } from "./config"; -import { MAX_LIMIT, EVMX_CHAIN_ID, BID_TIMEOUT } from "../constants/constants"; +import { + MAX_LIMIT, + EVMX_CHAIN_ID, + BID_TIMEOUT, + VERSION, +} from "../constants/constants"; import { CORE_CONTRACTS, OffChainVMCoreContracts } from "../../src"; let offChainVMOwner: string; @@ -61,11 +66,12 @@ const main = async () => { ); deployUtils.addresses[contractName] = signatureVerifier.address; - await updateContractSettings( + await initializeSigVerifier( signatureVerifier, "owner", "initialize", socketOwner, + [socketOwner, VERSION], deployUtils.signer ); @@ -213,7 +219,7 @@ const deployWatcherVMContracts = async () => { deployUtils = await deployContractWithProxy( OffChainVMCoreContracts.SignatureVerifier, `contracts/socket/utils/SignatureVerifier.sol`, - [offChainVMOwner], + [offChainVMOwner, VERSION], proxyFactory, deployUtils ); @@ -221,7 +227,7 @@ const deployWatcherVMContracts = async () => { deployUtils = await deployContractWithProxy( OffChainVMCoreContracts.AddressResolver, `contracts/AddressResolver.sol`, - [offChainVMOwner], + [offChainVMOwner, VERSION], proxyFactory, deployUtils ); @@ -234,7 +240,7 @@ const deployWatcherVMContracts = async () => { deployUtils = await deployContractWithProxy( OffChainVMCoreContracts.WatcherPrecompile, `contracts/watcherPrecompile/WatcherPrecompile.sol`, - [offChainVMOwner, addressResolver.address, MAX_LIMIT], + [offChainVMOwner, addressResolver.address, MAX_LIMIT, VERSION], proxyFactory, deployUtils ); @@ -242,7 +248,7 @@ const deployWatcherVMContracts = async () => { deployUtils = await deployContractWithProxy( OffChainVMCoreContracts.FeesManager, `contracts/apps/payload-delivery/app-gateway/FeesManager.sol`, - [addressResolver.address, offChainVMOwner], + [addressResolver.address, offChainVMOwner, VERSION], proxyFactory, deployUtils ); @@ -257,6 +263,7 @@ const deployWatcherVMContracts = async () => { feesManagerAddress, offChainVMOwner, BID_TIMEOUT, + VERSION, ], proxyFactory, deployUtils @@ -271,6 +278,7 @@ const deployWatcherVMContracts = async () => { addressResolver.address, deployUtils.addresses[OffChainVMCoreContracts.SignatureVerifier], offChainVMOwner, + VERSION, ], proxyFactory, deployUtils @@ -322,6 +330,28 @@ const deployWatcherVMContracts = async () => { } }; +async function initializeSigVerifier( + contract: Contract, + getterMethod: string, + setterMethod: string, + requiredAddress: string, + initParams: any[], + signer: Signer +) { + const currentValue = await contract.connect(signer)[getterMethod](); + + if (currentValue.toLowerCase() !== requiredAddress.toLowerCase()) { + console.log({ + setterMethod, + current: currentValue, + required: requiredAddress, + }); + const tx = await contract.connect(signer)[setterMethod](...initParams); + console.log(`Setting ${getterMethod} for ${contract.address} to`, tx.hash); + await tx.wait(); + } +} + async function updateContractSettings( contract: Contract, getterMethod: string, @@ -368,6 +398,7 @@ const deployContractWithProxy = async ( deployUtils ); deployUtils.addresses[keyName] = implementation.address; + if (deployUtils.addresses[contractName] !== undefined) return deployUtils; // Create initialization data const initializeFn = implementation.interface.getFunction("initialize"); @@ -375,18 +406,14 @@ const deployContractWithProxy = async ( initializeFn, initParams ); - if (deployUtils.addresses[contractName] !== undefined) return deployUtils; // Deploy transparent proxy - const tx = await proxyFactory.connect(deployUtils.signer).deployAndCall( - implementation.address, - offChainVMOwner, - initData - ); + const tx = await proxyFactory + .connect(deployUtils.signer) + .deployAndCall(implementation.address, offChainVMOwner, initData); const receipt = await tx.wait(); - const proxyAddress = receipt.events?.find( - (e) => e.event === "Deployed" - )?.args?.proxy; + const proxyAddress = receipt.events?.find((e) => e.event === "Deployed")?.args + ?.proxy; deployUtils.addresses[contractName] = proxyAddress; return deployUtils; diff --git a/hardhat-scripts/deploy/3.upgradeManagers.ts b/hardhat-scripts/deploy/3.upgradeManagers.ts index 23371d40..5589b2fb 100644 --- a/hardhat-scripts/deploy/3.upgradeManagers.ts +++ b/hardhat-scripts/deploy/3.upgradeManagers.ts @@ -62,9 +62,7 @@ export const main = async () => { }; async function setSwitchboard(sbAddress, chain, addresses) { - const providerInstance = getProviderFromChainSlug( - EVMX_CHAIN_ID as ChainSlug - ); + const providerInstance = getProviderFromChainSlug(EVMX_CHAIN_ID as ChainSlug); const signer: Wallet = new ethers.Wallet( process.env.WATCHER_PRIVATE_KEY as string, providerInstance diff --git a/hardhat-scripts/deploy/4.connect.ts b/hardhat-scripts/deploy/4.connect.ts index e66da43c..5ac20c3e 100644 --- a/hardhat-scripts/deploy/4.connect.ts +++ b/hardhat-scripts/deploy/4.connect.ts @@ -25,9 +25,7 @@ export const getAppGateway = (plug: string, addresses: DeploymentAddresses) => { OffChainVMCoreContracts.DeliveryHelper ]; case CORE_CONTRACTS.FeesPlug: - return addresses?.[EVMX_CHAIN_ID]?.[ - OffChainVMCoreContracts.FeesManager - ]; + return addresses?.[EVMX_CHAIN_ID]?.[OffChainVMCoreContracts.FeesManager]; default: throw new Error(`Unknown plug: ${plug}`); } diff --git a/hardhat-scripts/deploy/5.upload.ts b/hardhat-scripts/deploy/5.upload.ts index 00be4c95..b174760c 100644 --- a/hardhat-scripts/deploy/5.upload.ts +++ b/hardhat-scripts/deploy/5.upload.ts @@ -2,10 +2,7 @@ import fs from "fs"; import path from "path"; import { S3Client, PutObjectCommand } from "@aws-sdk/client-s3"; import { config as dotenvConfig } from "dotenv"; -import { - BASE_SEPOLIA_CHAIN_ID, - EVMX_CHAIN_ID, -} from "../constants/constants"; +import { BASE_SEPOLIA_CHAIN_ID, EVMX_CHAIN_ID } from "../constants/constants"; import { ChainSlug } from "@socket.tech/dl-core"; // import applicationGateway from "../../artifacts/abi/SuperTokenApp.json"; diff --git a/hardhat-scripts/deploy/6.setupEnv.ts b/hardhat-scripts/deploy/6.setupEnv.ts index 92e52dda..93396386 100644 --- a/hardhat-scripts/deploy/6.setupEnv.ts +++ b/hardhat-scripts/deploy/6.setupEnv.ts @@ -33,7 +33,9 @@ const updatedLines = lines.map((line) => { dev_addresses[ChainSlug.ARBITRUM_SEPOLIA]["FastSwitchboard"] }`; } else if (line.startsWith("ARBITRUM_FEES_PLUG=")) { - return `ARBITRUM_FEES_PLUG=${dev_addresses[ChainSlug.ARBITRUM_SEPOLIA]["FeesPlug"]}`; + return `ARBITRUM_FEES_PLUG=${ + dev_addresses[ChainSlug.ARBITRUM_SEPOLIA]["FeesPlug"] + }`; } return line; // Return the line unchanged if it doesn't match any of the above }); diff --git a/hardhat-scripts/deploy/migrate-proxies.ts b/hardhat-scripts/deploy/migrate-proxies.ts deleted file mode 100644 index 3c31c7d3..00000000 --- a/hardhat-scripts/deploy/migrate-proxies.ts +++ /dev/null @@ -1,95 +0,0 @@ -import { ethers, upgrades } from "hardhat"; -import * as fs from "fs"; -import * as path from "path"; -import { EVMX_CHAIN_ID } from "../constants/constants"; - -const upgradeableContracts = [ - "SignatureVerifier", - "AddressResolver", - "WatcherPrecompile", - "FeesManager", - "DeliveryHelper", - "AuctionManager", -]; - -async function main() { - // Read addresses from JSON file - const addressesPath = path.join( - __dirname, - "../../deployments/dev_addresses.json" - ); - const addresses = JSON.parse(fs.readFileSync(addressesPath, "utf8")); - - if (!addresses[EVMX_CHAIN_ID]) { - throw new Error(`No addresses found for chain ID ${EVMX_CHAIN_ID}`); - } - - // Loop through each upgradeable contract - for (const contractName of upgradeableContracts) { - console.log(`\nProcessing ${contractName}...`); - - // Get the new implementation contract factory - const NewImplementation = await ethers.getContractFactory(contractName); - - // Get proxy address from JSON - const PROXY_ADDRESS = addresses[EVMX_CHAIN_ID][contractName]; - if (!PROXY_ADDRESS) { - console.log(`Contract address not found for ${contractName}`); - continue; - } - - try { - // Try to get current implementation address - const currentImplAddress = - await upgrades.erc1967.getImplementationAddress(PROXY_ADDRESS); - console.log( - `Current implementation address for ${contractName}: ${currentImplAddress}` - ); - - // Get the implementation address from JSON - const newImplementation = - addresses[EVMX_CHAIN_ID][`${contractName}Impl`]; - if (!newImplementation) { - console.log(`No implementation address found for ${contractName}`); - continue; - } - - if ( - currentImplAddress.toLowerCase() === newImplementation.toLowerCase() - ) { - console.log("Implementation is already up to date"); - continue; - } - - // Upgrade the proxy to point to the new implementation - console.log("Upgrading proxy..."); - const upgraded = await upgrades.upgradeProxy( - PROXY_ADDRESS, - NewImplementation - ); - await upgraded.deployed(); - - console.log("Proxy upgraded successfully"); - - // Verify the new implementation address - const updatedImplAddress = - await upgrades.erc1967.getImplementationAddress(PROXY_ADDRESS); - console.log("Updated implementation address:", updatedImplAddress); - } catch (error) { - if (error.message.includes("doesn't look like an ERC 1967 proxy")) { - console.log( - `${contractName} at ${PROXY_ADDRESS} is not a proxy contract, skipping...` - ); - continue; - } - throw error; - } - } -} - -main() - .then(() => process.exit(0)) - .catch((error) => { - console.error(error); - process.exit(1); - }); diff --git a/hardhat-scripts/deploy/migration/migrate-proxies.ts b/hardhat-scripts/deploy/migration/migrate-proxies.ts new file mode 100644 index 00000000..7a44eca4 --- /dev/null +++ b/hardhat-scripts/deploy/migration/migrate-proxies.ts @@ -0,0 +1,203 @@ +import { ethers } from "hardhat"; +import { Contract, utils, Wallet } from "ethers"; +import * as fs from "fs"; +import * as path from "path"; +import { EVMX_CHAIN_ID, VERSION } from "../../constants/constants"; +import { getProviderFromChainSlug } from "../../constants"; +import { ChainSlug } from "@socket.tech/dl-core"; + +// Implementation slot from ERC1967 +const IMPLEMENTATION_SLOT = + "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc"; + +const upgradeableContracts = [ + "SignatureVerifier", + "AddressResolver", + "WatcherPrecompile", + "FeesManager", + "DeliveryHelper", + "AuctionManager", +]; + +async function getImplementationAddress(proxyAddress: string): Promise { + const customProvider = new ethers.providers.JsonRpcProvider( + process.env.EVMX_RPC as string + ); + + // Fallback to standard storage slot for other proxy types + const implHex = await customProvider.getStorageAt( + proxyAddress, + IMPLEMENTATION_SLOT + ); + + return utils.getAddress("0x" + implHex.slice(-40)); +} + +async function main() { + // @ts-ignore - Hardhat Runtime Environment will be injected by hardhat + + // Read addresses from JSON file + const addressesPath = path.join( + __dirname, + "../../../deployments/dev_addresses.json" + ); + const addresses = JSON.parse(fs.readFileSync(addressesPath, "utf8")); + + if (!addresses[EVMX_CHAIN_ID]) { + throw new Error(`No addresses found for chain ID ${EVMX_CHAIN_ID}`); + } + + const providerInstance = getProviderFromChainSlug(EVMX_CHAIN_ID as ChainSlug); + const signer: Wallet = new ethers.Wallet( + process.env.WATCHER_PRIVATE_KEY as string, + providerInstance + ); + + // Get the proxy factory + let proxyFactory = await ethers.getContractAt( + "ERC1967Factory", + addresses[EVMX_CHAIN_ID].ERC1967Factory + ); + proxyFactory = proxyFactory.connect(signer); + + // Loop through each upgradeable contract + for (const contractName of upgradeableContracts) { + console.log(`\nProcessing ${contractName}...`); + + const PROXY_ADDRESS = addresses[EVMX_CHAIN_ID][contractName]; + if (!PROXY_ADDRESS) { + console.log(`Contract address not found for ${contractName}`); + continue; + } + + try { + // Get current implementation + const currentImplAddress = await getImplementationAddress(PROXY_ADDRESS); + console.log( + `Current implementation for ${contractName}: ${currentImplAddress}` + ); + + // Get new implementation address + const newImplementation = addresses[EVMX_CHAIN_ID][`${contractName}Impl`]; + if (!newImplementation) { + console.log(`No implementation address found for ${contractName}`); + continue; + } + + // Get contract instance for state verification + let contract = await ethers.getContractAt(contractName, PROXY_ADDRESS); + contract = contract.connect(signer); + + let version; + try { + version = await contract.version(); + console.log("Version on contract before upgrade:", version); + } catch (error) { + console.log("version variable not found"); + } + + if (contractName === "AddressResolver") + await verifyBeaconImplementation(contract, signer); + + if ( + currentImplAddress.toLowerCase() === newImplementation.toLowerCase() + ) { + console.log("Implementation is already up to date"); + continue; + } + + // Upgrade proxy + console.log("Upgrading proxy..."); + + const initializeFn = contract.interface.getFunction("initialize"); + const initData = contract.interface.encodeFunctionData(initializeFn, [ + VERSION, + ]); + + const tx = await proxyFactory.upgradeAndCall( + PROXY_ADDRESS, + newImplementation, + initData + ); + console.log("tx", tx.hash); + await tx.wait(); + + // Verify upgrade + const updatedImplAddress = await getImplementationAddress(PROXY_ADDRESS); + console.log("New implementation:", updatedImplAddress); + + if ( + updatedImplAddress.toLowerCase() !== newImplementation.toLowerCase() + ) { + throw new Error( + "Upgrade verification failed - implementation mismatch" + ); + } + + version = await contract.version(); + console.log("Version on contract after upgrade:", version); + + if (contractName === "AddressResolver") { + await verifyBeaconImplementation(contract, signer); + } + + console.log("Upgrade successful and verified"); + } catch (error) { + console.error(`Error upgrading ${contractName}:`, error); + process.exit(1); + } + } +} + +async function verifyBeaconImplementation(contract: Contract, signer: Wallet) { + console.log("Verifying beacon implementations..."); + const forwarderBeaconAddress = await contract.forwarderBeacon(); + const forwarderImplementationAddress = + await contract.forwarderImplementation(); + const asyncPromiseBeaconAddress = await contract.asyncPromiseBeacon(); + const asyncPromiseImplementationAddress = + await contract.asyncPromiseImplementation(); + + const upgradeableBeaconAbi = [ + "function implementation() view returns (address)", + ]; + + const forwarderBeacon = new ethers.Contract( + forwarderBeaconAddress, + upgradeableBeaconAbi + ); + const asyncPromiseBeacon = new ethers.Contract( + asyncPromiseBeaconAddress, + upgradeableBeaconAbi + ); + + // Verify forwarder beacon implementation + const forwarderBeaconImplementation = await forwarderBeacon + .connect(signer) + .implementation(); + if ( + forwarderBeaconImplementation.toLowerCase() !== + forwarderImplementationAddress.toLowerCase() + ) { + throw new Error("Forwarder beacon implementation mismatch"); + } + + // Verify async promise beacon implementation + const asyncPromiseBeaconImplementation = await asyncPromiseBeacon + .connect(signer) + .implementation(); + if ( + asyncPromiseBeaconImplementation.toLowerCase() !== + asyncPromiseImplementationAddress.toLowerCase() + ) { + throw new Error("Async promise beacon implementation mismatch"); + } +} +// We recommend this pattern to be able to use async/await everywhere +// and properly handle errors. +main() + .then(() => process.exit(0)) + .catch((error) => { + console.error(error); + process.exit(1); + }); diff --git a/hardhat-scripts/deploy/utils/utils.ts b/hardhat-scripts/deploy/utils/utils.ts index d952e5c6..6ddbb529 100644 --- a/hardhat-scripts/deploy/utils/utils.ts +++ b/hardhat-scripts/deploy/utils/utils.ts @@ -306,7 +306,7 @@ export const getAddresses = async ( return deploymentAddresses[chainSlug]; }; -export const createObj = function( +export const createObj = function ( obj: ChainSocketAddresses, keys: string[], value: any diff --git a/hardhat-scripts/deploy/verify.ts b/hardhat-scripts/deploy/verify.ts index b43a67d5..d9c54417 100644 --- a/hardhat-scripts/deploy/verify.ts +++ b/hardhat-scripts/deploy/verify.ts @@ -8,10 +8,7 @@ import { } from "@socket.tech/dl-core"; import path from "path"; import fs from "fs"; -import { - BASE_SEPOLIA_CHAIN_ID, - EVMX_CHAIN_ID, -} from "../constants/constants"; +import { BASE_SEPOLIA_CHAIN_ID, EVMX_CHAIN_ID } from "../constants/constants"; export type VerifyParams = { [chain in HardhatChainName]?: VerifyArgs[]; diff --git a/hardhat.config.ts b/hardhat.config.ts index 02f369b9..7bd01929 100644 --- a/hardhat.config.ts +++ b/hardhat.config.ts @@ -133,8 +133,8 @@ const config: HardhatUserConfig = { network: "offChainVM", chainId: EVMX_CHAIN_ID, urls: { - apiURL: "https://explorer-socket-composer-testnet.t.conduit.xyz/api", - browserURL: "https://explorer-socket-composer-testnet.t.conduit.xyz", + apiURL: "", + browserURL: "", }, }, ], @@ -162,6 +162,7 @@ const config: HardhatUserConfig = { solidity: { version: "0.8.22", settings: { + evmVersion: "paris", optimizer: { enabled: true, runs: 999999, diff --git a/package.json b/package.json index 04c54997..c7668da8 100644 --- a/package.json +++ b/package.json @@ -9,7 +9,7 @@ "publishConfig": { "access": "public" }, - "version": "1.0.8", + "version": "1.0.9", "description": "socket protocol", "scripts": { "build": "hardhat export-abi && tsc --project lib.tsconfig.json", @@ -25,7 +25,6 @@ "devDependencies": { "@nomiclabs/hardhat-ethers": "2.2.3", "@nomicfoundation/hardhat-verify": "^2.0.12", - "@openzeppelin/hardhat-upgrades": "1.22.1", "@socket.tech/dl-core": "^2.35.0", "@typechain/ethers-v5": "^10.0.0", "@typechain/hardhat": "6.0.0", diff --git a/remappings.txt b/remappings.txt index ab585aad..1cf3bb7d 100644 --- a/remappings.txt +++ b/remappings.txt @@ -1,5 +1,4 @@ ds-test/=lib/forge-std/lib/ds-test/src/ forge-std/=lib/forge-std/src/ solmate/=lib/solmate/src/ -openzeppelin-contracts/=lib/openzeppelin-contracts/ solady/=lib/solady/src/ \ No newline at end of file diff --git a/test/DeliveryHelper.t.sol b/test/DeliveryHelper.t.sol index 5532d35f..e3ba294b 100644 --- a/test/DeliveryHelper.t.sol +++ b/test/DeliveryHelper.t.sol @@ -49,7 +49,8 @@ contract DeliveryHelperTest is SetupTest { bytes memory feesManagerData = abi.encodeWithSelector( FeesManager.initialize.selector, address(addressResolver), - owner + owner, + version ); vm.expectEmit(true, true, true, false); @@ -65,7 +66,8 @@ contract DeliveryHelperTest is SetupTest { address(addressResolver), address(feesManagerProxy), owner, - bidTimeout + bidTimeout, + version ); vm.expectEmit(true, true, true, false); @@ -82,7 +84,8 @@ contract DeliveryHelperTest is SetupTest { auctionEndDelaySeconds, address(addressResolver), signatureVerifier, - owner + owner, + version ); vm.expectEmit(true, true, true, false); emit Initialized(1); diff --git a/test/Migration.t.sol b/test/Migration.t.sol index 1b495f40..394b3a5b 100644 --- a/test/Migration.t.sol +++ b/test/Migration.t.sol @@ -5,16 +5,26 @@ import "./SetupTest.t.sol"; import "../contracts/socket/utils/SignatureVerifier.sol"; import "../contracts/AddressResolver.sol"; import "../contracts/watcherPrecompile/WatcherPrecompile.sol"; +import "../contracts/Forwarder.sol"; +import "../contracts/AsyncPromise.sol"; import "./MockWatcherPrecompileImpl.sol"; contract MigrationTest is SetupTest { // ERC1967Factory emits this event with both proxy and implementation addresses event Upgraded(address indexed proxy, address indexed implementation); + event ImplementationUpdated(string contractName, address newImplementation); // ERC1967 implementation slot bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; + // Beacon implementation slot + uint256 internal constant _BEACON_IMPLEMENTATION_SLOT = 0x911c5a209f08d5ec5e; + + // Beacon slot in ERC1967 + bytes32 internal constant _BEACON_SLOT = + 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50; + // Error selector for Unauthorized error bytes4 internal constant UNAUTHORIZED_SELECTOR = 0x82b42900; // bytes4(keccak256("Unauthorized()")) @@ -27,6 +37,16 @@ contract MigrationTest is SetupTest { return address(uint160(uint256(value))); } + function getBeaconImplementation(address beacon) internal view returns (address) { + bytes32 value = vm.load(beacon, bytes32(_BEACON_IMPLEMENTATION_SLOT)); + return address(uint160(uint256(value))); + } + + function getBeacon(address proxy) internal view returns (address) { + bytes32 value = vm.load(proxy, _BEACON_SLOT); + return address(uint160(uint256(value))); + } + function testSignatureVerifierUpgrade() public { // Deploy new implementation SignatureVerifier newImpl = new SignatureVerifier(); @@ -156,4 +176,116 @@ contract MigrationTest is SetupTest { "Implementation should not have changed" ); } + + function testForwarderBeaconUpgrade() public { + // Deploy new implementation + Forwarder newImpl = new Forwarder(); + + // Get current implementation from beacon + address oldImpl = getBeaconImplementation(address(addressResolver.forwarderBeacon())); + + // Upgrade beacon to new implementation + vm.startPrank(watcherEOA); + vm.expectEmit(true, true, true, true, address(addressResolver)); + emit ImplementationUpdated("Forwarder", address(newImpl)); + addressResolver.setForwarderImplementation(address(newImpl)); + vm.stopPrank(); + + // Verify upgrade was successful + address newImplAddr = getBeaconImplementation(address(addressResolver.forwarderBeacon())); + assertNotEq(oldImpl, newImplAddr, "Implementation should have changed"); + assertEq(newImplAddr, address(newImpl), "New implementation not set correctly"); + + // Deploy a new forwarder and verify it uses the correct beacon + address newForwarder = addressResolver.getOrDeployForwarderContract( + address(this), + address(0x123), + 1 + ); + address beacon = getBeacon(newForwarder); + assertEq( + beacon, + address(addressResolver.forwarderBeacon()), + "Beacon address not set correctly" + ); + + // Get implementation from beacon and verify it matches + address implFromBeacon = getBeaconImplementation(beacon); + assertEq( + implFromBeacon, + address(newImpl), + "Beacon implementation should match new implementation" + ); + } + + function testAsyncPromiseBeaconUpgrade() public { + // Deploy new implementation + AsyncPromise newImpl = new AsyncPromise(); + + // Get current implementation from beacon + address oldImpl = getBeaconImplementation(address(addressResolver.asyncPromiseBeacon())); + + // Upgrade beacon to new implementation + vm.startPrank(watcherEOA); + vm.expectEmit(true, true, true, true, address(addressResolver)); + emit ImplementationUpdated("AsyncPromise", address(newImpl)); + addressResolver.setAsyncPromiseImplementation(address(newImpl)); + vm.stopPrank(); + + // Verify upgrade was successful + address newImplAddr = getBeaconImplementation( + address(addressResolver.asyncPromiseBeacon()) + ); + assertNotEq(oldImpl, newImplAddr, "Implementation should have changed"); + assertEq(newImplAddr, address(newImpl), "New implementation not set correctly"); + + // Deploy a new async promise and verify it uses the correct beacon + address newPromise = addressResolver.deployAsyncPromiseContract(address(this)); + address beacon = getBeacon(newPromise); + assertEq( + beacon, + address(addressResolver.asyncPromiseBeacon()), + "Beacon address not set correctly" + ); + + // Get implementation from beacon and verify it matches + address implFromBeacon = getBeaconImplementation(beacon); + assertEq( + implFromBeacon, + address(newImpl), + "Beacon implementation should match new implementation" + ); + } + + function testUnauthorizedBeaconUpgrade() public { + // Deploy new implementations + Forwarder newForwarderImpl = new Forwarder(); + AsyncPromise newAsyncPromiseImpl = new AsyncPromise(); + + // Try to upgrade from unauthorized account + address unauthorizedUser = address(0xBEEF); + + vm.startPrank(unauthorizedUser); + // Try upgrading forwarder beacon + vm.expectRevert(abi.encodeWithSignature("OnlyOwner()")); + addressResolver.setForwarderImplementation(address(newForwarderImpl)); + + // Try upgrading async promise beacon + vm.expectRevert(abi.encodeWithSignature("OnlyOwner()")); + addressResolver.setAsyncPromiseImplementation(address(newAsyncPromiseImpl)); + + vm.stopPrank(); + + // Verify implementations were not changed + assertNotEq( + getBeaconImplementation(address(addressResolver.forwarderBeacon())), + address(newForwarderImpl), + "Forwarder implementation should not have changed" + ); + assertNotEq( + getBeaconImplementation(address(addressResolver.asyncPromiseBeacon())), + address(newAsyncPromiseImpl), + "AsyncPromise implementation should not have changed" + ); + } } diff --git a/test/MockWatcherPrecompileImpl.sol b/test/MockWatcherPrecompileImpl.sol index feddf807..86ad1243 100644 --- a/test/MockWatcherPrecompileImpl.sol +++ b/test/MockWatcherPrecompileImpl.sol @@ -18,8 +18,7 @@ contract MockWatcherPrecompileImpl is WatcherPrecompile { // limit per day maxLimit = maxLimit_ * 10 ** LIMIT_DECIMALS; - // limit per second + // limit per second ratePerSecond = maxLimit / (24 * 60 * 60); } } - diff --git a/test/SetupTest.t.sol b/test/SetupTest.t.sol index 99f0c851..f4f55018 100644 --- a/test/SetupTest.t.sol +++ b/test/SetupTest.t.sol @@ -43,6 +43,7 @@ contract SetupTest is Test { uint256 public maxLimit = 1000; bytes public asyncPromiseBytecode = type(AsyncPromise).creationCode; + uint64 public version = 1; struct SocketContracts { uint32 chainSlug; @@ -69,7 +70,7 @@ contract SetupTest is Test { function deploySocket(uint32 chainSlug_) internal returns (SocketContracts memory) { SignatureVerifier verifier = new SignatureVerifier(); - verifier.initialize(owner); + verifier.initialize(owner, version); Hasher hasher = new Hasher(owner); Socket socket = new Socket(chainSlug_, address(hasher), address(verifier), owner, "test"); @@ -112,7 +113,8 @@ contract SetupTest is Test { // Deploy and initialize proxies bytes memory signatureVerifierData = abi.encodeWithSelector( SignatureVerifier.initialize.selector, - owner + owner, + version ); vm.expectEmit(true, true, true, false); @@ -125,7 +127,8 @@ contract SetupTest is Test { bytes memory addressResolverData = abi.encodeWithSelector( AddressResolver.initialize.selector, - watcherEOA + watcherEOA, + version ); vm.expectEmit(true, true, true, false); emit Initialized(1); @@ -139,7 +142,8 @@ contract SetupTest is Test { WatcherPrecompile.initialize.selector, watcherEOA, address(addressResolverProxy), - maxLimit + maxLimit, + version ); vm.expectEmit(true, true, true, false); emit Initialized(1); diff --git a/yarn.lock b/yarn.lock index 1bc37561..0a85c6fe 100644 --- a/yarn.lock +++ b/yarn.lock @@ -602,11 +602,6 @@ "@smithy/types" "^3.5.0" tslib "^2.6.2" -"@bytecodealliance/preview2-shim@0.17.0": - version "0.17.0" - resolved "https://registry.yarnpkg.com/@bytecodealliance/preview2-shim/-/preview2-shim-0.17.0.tgz#9bc1cadbb9f86c446c6f579d3431c08a06a6672e" - integrity sha512-JorcEwe4ud0x5BS/Ar2aQWOQoFzjq/7jcnxYXCvSMh0oRm0dQXzOA+hqLDBnOMks1LLBA7dmiLLsEBl09Yd6iQ== - "@cspotcode/source-map-support@^0.8.0": version "0.8.1" resolved "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz" @@ -1487,13 +1482,6 @@ table "^6.8.0" undici "^5.14.0" -"@nomicfoundation/slang@^0.18.3": - version "0.18.3" - resolved "https://registry.yarnpkg.com/@nomicfoundation/slang/-/slang-0.18.3.tgz#976b6c3820081cebf050afbea434038aac9313cc" - integrity sha512-YqAWgckqbHM0/CZxi9Nlf4hjk9wUNLC9ngWCWBiqMxPIZmzsVKYuChdlrfeBPQyvQQBoOhbx+7C1005kLVQDZQ== - dependencies: - "@bytecodealliance/preview2-shim" "0.17.0" - "@nomicfoundation/solidity-analyzer-darwin-arm64@0.1.2": version "0.1.2" resolved "https://registry.npmjs.org/@nomicfoundation/solidity-analyzer-darwin-arm64/-/solidity-analyzer-darwin-arm64-0.1.2.tgz" @@ -1547,32 +1535,6 @@ resolved "https://registry.yarnpkg.com/@nomiclabs/hardhat-ethers/-/hardhat-ethers-2.2.3.tgz#b41053e360c31a32c2640c9a45ee981a7e603fe0" integrity sha512-YhzPdzb612X591FOe68q+qXVXGG2ANZRvDo0RRUtimev85rCrAlv/TLMEZw5c+kq9AbzocLTVX/h2jVIFPL9Xg== -"@openzeppelin/hardhat-upgrades@1.22.1": - version "1.22.1" - resolved "https://registry.yarnpkg.com/@openzeppelin/hardhat-upgrades/-/hardhat-upgrades-1.22.1.tgz#93e2b3f870c57b00a1ae8a330a2cdd9c2d634eb8" - integrity sha512-MdoitCTLl4zwMU8MeE/bCj+7JMWBEvd38XqJkw36PkJrXlbv6FedDVCPoumMAhpmtymm0nTwTYYklYG+L6WiiQ== - dependencies: - "@openzeppelin/upgrades-core" "^1.20.0" - chalk "^4.1.0" - debug "^4.1.1" - proper-lockfile "^4.1.1" - -"@openzeppelin/upgrades-core@^1.20.0": - version "1.42.1" - resolved "https://registry.yarnpkg.com/@openzeppelin/upgrades-core/-/upgrades-core-1.42.1.tgz#a2784e8d9c09f4a79b7e5cbb11933062ad709835" - integrity sha512-8qnz2XfQrco8R8u9NjV+KiSLrVn7DnWFd+3BuhTUjhVy0bzCSu2SMKCVpZLtXbxf4f2dpz8jYPQYRa6s23PhLA== - dependencies: - "@nomicfoundation/slang" "^0.18.3" - cbor "^10.0.0" - chalk "^4.1.0" - compare-versions "^6.0.0" - debug "^4.1.1" - ethereumjs-util "^7.0.3" - minimatch "^9.0.5" - minimist "^1.2.7" - proper-lockfile "^4.1.1" - solidity-ast "^0.4.51" - "@scure/base@~1.1.0": version "1.1.9" resolved "https://registry.npmjs.org/@scure/base/-/base-1.1.9.tgz" @@ -2485,7 +2447,7 @@ bn.js@^4.11.0, bn.js@^4.11.8, bn.js@^4.11.9: resolved "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz" integrity sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA== -bn.js@^5.1.2, bn.js@^5.2.0, bn.js@^5.2.1: +bn.js@^5.2.0, bn.js@^5.2.1: version "5.2.1" resolved "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz" integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ== @@ -2609,13 +2571,6 @@ catering@^2.1.0, catering@^2.1.1: resolved "https://registry.npmjs.org/catering/-/catering-2.1.1.tgz" integrity sha512-K7Qy8O9p76sL3/3m7/zLKbRkyOlSZAgzEaLhyj2mXS8PsCud2Eo4hAb8aLtZqHh0QGqLcb9dlJSu6lHRVENm1w== -cbor@^10.0.0: - version "10.0.3" - resolved "https://registry.yarnpkg.com/cbor/-/cbor-10.0.3.tgz#202d79cd696f408700af51b0c9771577048a860e" - integrity sha512-72Jnj81xMsqepqdcSdf2+fflz/UDsThOHy5hj2MW5F5xzHL8Oa0KQ6I6V9CwVUPxg5pf+W9xp6W2KilaRXWWtw== - dependencies: - nofilter "^3.0.2" - cbor@^8.1.0: version "8.1.0" resolved "https://registry.npmjs.org/cbor/-/cbor-8.1.0.tgz" @@ -2763,11 +2718,6 @@ commander@3.0.2: resolved "https://registry.npmjs.org/commander/-/commander-3.0.2.tgz" integrity sha512-Gar0ASD4BDyKC4hl4DwHqDrmvjoxWKZigVnAbn5H1owvm4CxCPdb0HQDehwNYMJpla5+M2tPmPARzhtYuwpHow== -compare-versions@^6.0.0: - version "6.1.1" - resolved "https://registry.yarnpkg.com/compare-versions/-/compare-versions-6.1.1.tgz#7af3cc1099ba37d244b3145a9af5201b629148a9" - integrity sha512-4hm4VPpIecmlg59CHXnRDnqGplJFrbLG4aFEl5vl6cK1u76ws3LLvX7ikFnTDl5vo39sjWD6AaDPYodJp/NNHg== - concat-map@0.0.1: version "0.0.1" resolved "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz" @@ -3023,17 +2973,6 @@ ethereumjs-util@^6.0.0, ethereumjs-util@^6.2.1: ethjs-util "0.1.6" rlp "^2.2.3" -ethereumjs-util@^7.0.3: - version "7.1.5" - resolved "https://registry.yarnpkg.com/ethereumjs-util/-/ethereumjs-util-7.1.5.tgz#9ecf04861e4fbbeed7465ece5f23317ad1129181" - integrity sha512-SDl5kKrQAudFBUe5OJM9Ac6WmMyYmXX/6sTmLZ3ffG2eY6ZIGBes3pEDxNN6V72WyOw4CPD5RomKdsa8DAAwLg== - dependencies: - "@types/bn.js" "^5.1.0" - bn.js "^5.1.2" - create-hash "^1.1.2" - ethereum-cryptography "^0.1.3" - rlp "^2.2.4" - ethers@5.6.6: version "5.6.6" resolved "https://registry.npmjs.org/ethers/-/ethers-5.6.6.tgz" @@ -3338,7 +3277,7 @@ gopd@^1.0.1: dependencies: get-intrinsic "^1.1.3" -graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9, graceful-fs@^4.2.0, graceful-fs@^4.2.4: +graceful-fs@^4.1.2, graceful-fs@^4.1.6, graceful-fs@^4.1.9, graceful-fs@^4.2.0: version "4.2.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== @@ -3895,14 +3834,7 @@ minimatch@^5.0.1, minimatch@^5.1.6: dependencies: brace-expansion "^2.0.1" -minimatch@^9.0.5: - version "9.0.5" - resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.5.tgz#d74f9dd6b57d83d8e98cfb82133b03978bc929e5" - integrity sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow== - dependencies: - brace-expansion "^2.0.1" - -minimist@^1.2.0, minimist@^1.2.6, minimist@^1.2.7: +minimist@^1.2.0, minimist@^1.2.6: version "1.2.8" resolved "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz" integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== @@ -3986,7 +3918,7 @@ node-gyp-build@^4.2.0, node-gyp-build@^4.3.0: resolved "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.2.tgz" integrity sha512-IRUxE4BVsHWXkV/SFOut4qTlagw2aM8T5/vnTsmrHJvVoKueJHRc/JaFND7QDDc61kLYUJ6qlZM3sqTSyx2dTw== -nofilter@^3.0.2, nofilter@^3.1.0: +nofilter@^3.1.0: version "3.1.0" resolved "https://registry.npmjs.org/nofilter/-/nofilter-3.1.0.tgz" integrity sha512-l2NNj07e9afPnhAhvgVrCD/oy2Ai1yfLpuo3EpiO1jFTsB4sFz6oIfAfSZyQzVpkZQ9xS8ZS5g1jCBgq4Hwo0g== @@ -4158,15 +4090,6 @@ prompts@^2.4.2: kleur "^3.0.3" sisteransi "^1.0.5" -proper-lockfile@^4.1.1: - version "4.1.2" - resolved "https://registry.yarnpkg.com/proper-lockfile/-/proper-lockfile-4.1.2.tgz#c8b9de2af6b2f1601067f98e01ac66baa223141f" - integrity sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA== - dependencies: - graceful-fs "^4.2.4" - retry "^0.12.0" - signal-exit "^3.0.2" - proxy-from-env@^1.1.0: version "1.1.0" resolved "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz" @@ -4262,11 +4185,6 @@ resolve@1.17.0: dependencies: path-parse "^1.0.6" -retry@^0.12.0: - version "0.12.0" - resolved "https://registry.yarnpkg.com/retry/-/retry-0.12.0.tgz#1b42a6266a21f07421d1b0b54b7dc167b01c013b" - integrity sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow== - rimraf@^2.2.8, rimraf@^2.6.2: version "2.7.1" resolved "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz" @@ -4282,7 +4200,7 @@ ripemd160@^2.0.0, ripemd160@^2.0.1: hash-base "^3.0.0" inherits "^2.0.1" -rlp@^2.2.3, rlp@^2.2.4: +rlp@^2.2.3: version "2.2.7" resolved "https://registry.yarnpkg.com/rlp/-/rlp-2.2.7.tgz#33f31c4afac81124ac4b283e2bd4d9720b30beaf" integrity sha512-d5gdPmgQ0Z+AklL2NVXr/IoSjNZFfTVvQWzL/AM2AOcSzYP2xjlb0AC8YyCLc41MSNf6P6QVtjgPdmVtzb+4lQ== @@ -4409,11 +4327,6 @@ side-channel@^1.0.6: get-intrinsic "^1.2.4" object-inspect "^1.13.1" -signal-exit@^3.0.2: - version "3.0.7" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" - integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== - sisteransi@^1.0.5: version "1.0.5" resolved "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz" @@ -4443,11 +4356,6 @@ solc@0.7.3: semver "^5.5.0" tmp "0.0.33" -solidity-ast@^0.4.51: - version "0.4.59" - resolved "https://registry.yarnpkg.com/solidity-ast/-/solidity-ast-0.4.59.tgz#290a2815aef70a61092591ab3e991da080ae5931" - integrity sha512-I+CX0wrYUN9jDfYtcgWSe+OAowaXy8/1YQy7NS4ni5IBDmIYBq7ZzaP/7QqouLjzZapmQtvGLqCaYgoUWqBo5g== - source-map-support@^0.5.13: version "0.5.21" resolved "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz"