From ac06ee11e57f0dd5ccf4db4c449b51c1dfec5f03 Mon Sep 17 00:00:00 2001 From: Alistair Singh Date: Tue, 27 Feb 2024 10:08:15 +0200 Subject: [PATCH] make initializer revert with error --- contracts/src/DeployGatewayLogic.sol | 33 ++++++++++++++ contracts/src/Gateway.sol | 64 ++++++++++++++-------------- contracts/test/Gateway.t.sol | 39 ++++++++++++----- 3 files changed, 95 insertions(+), 41 deletions(-) create mode 100644 contracts/src/DeployGatewayLogic.sol diff --git a/contracts/src/DeployGatewayLogic.sol b/contracts/src/DeployGatewayLogic.sol new file mode 100644 index 0000000000..9d10f4448a --- /dev/null +++ b/contracts/src/DeployGatewayLogic.sol @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: Apache-2.0 +// SPDX-FileCopyrightText: 2023 Snowfork +pragma solidity 0.8.23; + +import {AgentExecutor} from "./AgentExecutor.sol"; +import {Gateway} from "./Gateway.sol"; +import {ParaID} from "./Types.sol"; +import {Script} from "forge-std/Script.sol"; +import {stdJson} from "forge-std/StdJson.sol"; + +contract DeployGateway is Script { + using stdJson for string; + + function setUp() public {} + + function run() public { + uint256 privateKey = vm.envUint("PRIVATE_KEY"); + address deployer = vm.rememberKey(privateKey); + vm.startBroadcast(deployer); + + address beefyClient = vm.envAddress("BEEFY_CLIENT_CONTRACT_ADDRESS"); + + ParaID bridgeHubParaID = ParaID.wrap(uint32(vm.envUint("BRIDGE_HUB_PARAID"))); + bytes32 bridgeHubAgentID = vm.envBytes32("BRIDGE_HUB_AGENT_ID"); + + uint8 foreignTokenDecimals = uint8(vm.envUint("FOREIGN_TOKEN_DECIMALS")); + + AgentExecutor executor = new AgentExecutor(); + new Gateway(address(beefyClient), address(executor), bridgeHubParaID, bridgeHubAgentID, foreignTokenDecimals); + + vm.stopBroadcast(); + } +} diff --git a/contracts/src/Gateway.sol b/contracts/src/Gateway.sol index 430155d5f0..60f5d8c32b 100644 --- a/contracts/src/Gateway.sol +++ b/contracts/src/Gateway.sol @@ -86,6 +86,7 @@ contract Gateway is IGateway, IInitializable { error InvalidAgentExecutionPayload(); error InvalidCodeHash(); error InvalidConstructorParams(); + error AlreadyInitialized(); // handler functions are privileged modifier onlySelf() { @@ -578,47 +579,48 @@ contract Gateway is IGateway, IInitializable { revert Unauthorized(); } + Config memory config = abi.decode(data, (Config)); + CoreStorage.Layout storage core = CoreStorage.layout(); - // Check if initialized and run initialization once. - if (core.channels[PRIMARY_GOVERNANCE_CHANNEL_ID].agent == address(0)) { - Config memory config = abi.decode(data, (Config)); + if (core.channels[PRIMARY_GOVERNANCE_CHANNEL_ID].agent != address(0)) { + revert AlreadyInitialized(); + } - core.mode = config.mode; + core.mode = config.mode; - // Initialize agent for BridgeHub - address bridgeHubAgent = address(new Agent(BRIDGE_HUB_AGENT_ID)); - core.agents[BRIDGE_HUB_AGENT_ID] = bridgeHubAgent; + // Initialize agent for BridgeHub + address bridgeHubAgent = address(new Agent(BRIDGE_HUB_AGENT_ID)); + core.agents[BRIDGE_HUB_AGENT_ID] = bridgeHubAgent; - // Initialize channel for primary governance track - core.channels[PRIMARY_GOVERNANCE_CHANNEL_ID] = - Channel({mode: OperatingMode.Normal, agent: bridgeHubAgent, inboundNonce: 0, outboundNonce: 0}); + // Initialize channel for primary governance track + core.channels[PRIMARY_GOVERNANCE_CHANNEL_ID] = + Channel({mode: OperatingMode.Normal, agent: bridgeHubAgent, inboundNonce: 0, outboundNonce: 0}); - // Initialize channel for secondary governance track - core.channels[SECONDARY_GOVERNANCE_CHANNEL_ID] = - Channel({mode: OperatingMode.Normal, agent: bridgeHubAgent, inboundNonce: 0, outboundNonce: 0}); + // Initialize channel for secondary governance track + core.channels[SECONDARY_GOVERNANCE_CHANNEL_ID] = + Channel({mode: OperatingMode.Normal, agent: bridgeHubAgent, inboundNonce: 0, outboundNonce: 0}); - // Initialize agent for for AssetHub - address assetHubAgent = address(new Agent(config.assetHubAgentID)); - core.agents[config.assetHubAgentID] = assetHubAgent; + // Initialize agent for for AssetHub + address assetHubAgent = address(new Agent(config.assetHubAgentID)); + core.agents[config.assetHubAgentID] = assetHubAgent; - // Initialize channel for AssetHub - core.channels[config.assetHubParaID.into()] = - Channel({mode: OperatingMode.Normal, agent: assetHubAgent, inboundNonce: 0, outboundNonce: 0}); + // Initialize channel for AssetHub + core.channels[config.assetHubParaID.into()] = + Channel({mode: OperatingMode.Normal, agent: assetHubAgent, inboundNonce: 0, outboundNonce: 0}); - // Initialize pricing storage - PricingStorage.Layout storage pricing = PricingStorage.layout(); - pricing.exchangeRate = config.exchangeRate; - pricing.deliveryCost = config.deliveryCost; + // Initialize pricing storage + PricingStorage.Layout storage pricing = PricingStorage.layout(); + pricing.exchangeRate = config.exchangeRate; + pricing.deliveryCost = config.deliveryCost; - // Initialize assets storage - AssetsStorage.Layout storage assets = AssetsStorage.layout(); + // Initialize assets storage + AssetsStorage.Layout storage assets = AssetsStorage.layout(); - assets.assetHubParaID = config.assetHubParaID; - assets.assetHubAgent = assetHubAgent; - assets.registerTokenFee = config.registerTokenFee; - assets.assetHubCreateAssetFee = config.assetHubCreateAssetFee; - assets.assetHubReserveTransferFee = config.assetHubReserveTransferFee; - } + assets.assetHubParaID = config.assetHubParaID; + assets.assetHubAgent = assetHubAgent; + assets.registerTokenFee = config.registerTokenFee; + assets.assetHubCreateAssetFee = config.assetHubCreateAssetFee; + assets.assetHubReserveTransferFee = config.assetHubReserveTransferFee; } } diff --git a/contracts/test/Gateway.t.sol b/contracts/test/Gateway.t.sol index f8ef933783..73a6e5fda2 100644 --- a/contracts/test/Gateway.t.sol +++ b/contracts/test/Gateway.t.sol @@ -483,16 +483,7 @@ contract GatewayTest is Test { assertEq(GatewayV2(address(gateway)).getValue(), 42); } - function testInitializerRunsOnlyOnce() public { - bytes32 agentID = keccak256("123"); - - testSetPricingParameters(); - uint256 fee = IGateway(address(gateway)).quoteRegisterTokenFee(); - assertEq(fee, 10000000000000000); - - testCreateAgent(); - assertNotEq(GatewayMock(address(gateway)).agentOf(agentID), address(0)); - + function testUgradeInitializerRunsOnlyOnce() public { // Upgrade to this current logic contract AgentExecutor executor = new AgentExecutor(); GatewayMock currentLogic = @@ -508,12 +499,40 @@ contract GatewayTest is Test { assetHubReserveTransferFee: sendTokenFee, exchangeRate: exchangeRate }); + UpgradeParams memory params = UpgradeParams({ impl: address(currentLogic), implCodeHash: address(currentLogic).codehash, initParams: abi.encode(config) }); + vm.expectRevert(Gateway.AlreadyInitialized.selector); + // Expect the gateway to emit `Upgraded` + GatewayMock(address(gateway)).upgradePublic(abi.encode(params)); + } + + function testUpgradeSkipsInitializerIfNoneProvided() public { + bytes32 agentID = keccak256("123"); + + testSetPricingParameters(); + uint256 fee = IGateway(address(gateway)).quoteRegisterTokenFee(); + assertEq(fee, 10000000000000000); + + testCreateAgent(); + assertNotEq(GatewayMock(address(gateway)).agentOf(agentID), address(0)); + + // Upgrade to this current logic contract + AgentExecutor executor = new AgentExecutor(); + GatewayMock currentLogic = + new GatewayMock(address(0), address(executor), bridgeHubParaID, bridgeHubAgentID, foreignTokenDecimals); + + bytes memory initParams; // empty + UpgradeParams memory params = UpgradeParams({ + impl: address(currentLogic), + implCodeHash: address(currentLogic).codehash, + initParams: initParams + }); + // Expect the gateway to emit `Upgraded` GatewayMock(address(gateway)).upgradePublic(abi.encode(params));