diff --git a/contracts/src/Gateway.sol b/contracts/src/Gateway.sol index 59fbdd7507..685627fe34 100644 --- a/contracts/src/Gateway.sol +++ b/contracts/src/Gateway.sol @@ -617,10 +617,33 @@ contract Gateway is IGateway, IInitializable, IUpgradable { address rescueOperator; } - /// @dev Initialize storage in the gateway - /// NOTE: This is not externally accessible as this function selector is overshadowed in the proxy + /// Initialize storage within the `GatewayProxy` contract using this initializer. + /// + /// This initializer cannot be called externally via the proxy as the function selector + /// is overshadowed in the proxy. + /// + /// This implementation is only intended to initialize storage for initial deployments + /// of the `GatewayProxy` contract to transient or long-lived testnets. + /// + /// The `GatewayProxy` deployed to Ethereum mainnet already has its storage initialized. + /// When its logic contract needs to upgraded, a new logic contract should be developed + /// that inherits from this base `Gateway` contract. Particularly, the `initialize` function + /// must be overriden to ensure selective initialization of storage fields relevant + /// to the upgrade. + /// + /// ```solidity + /// contract Gateway202508 is Gateway { + /// function initialize(bytes calldata data) external override { + /// if (ERC1967.load() == address(0)) { + /// revert Unauthorized(); + /// } + /// # Initialization routines here... + /// } + /// } + /// ``` + /// function initialize(bytes calldata data) external virtual { - // Prevent initialization of storage in implementation contract + // Ensure that arbitrary users cannot initialize storage in this logic contract. if (ERC1967.load() == address(0)) { revert Unauthorized(); } diff --git a/contracts/src/upgrades/rococo/RococoGatewayV2.sol b/contracts/src/upgrades/Gateway202410.sol similarity index 57% rename from contracts/src/upgrades/rococo/RococoGatewayV2.sol rename to contracts/src/upgrades/Gateway202410.sol index 746cc3cd1a..d049fa825a 100644 --- a/contracts/src/upgrades/rococo/RococoGatewayV2.sol +++ b/contracts/src/upgrades/Gateway202410.sol @@ -2,14 +2,11 @@ // SPDX-FileCopyrightText: 2023 Snowfork pragma solidity 0.8.25; -import "../../Gateway.sol"; +import "../Gateway.sol"; -import {UD60x18, convert} from "prb/math/src/UD60x18.sol"; -import {PricingStorage} from "../../storage/PricingStorage.sol"; - -contract RococoGatewayV2 is Gateway { +// New `Gateway` logic contract for the `GatewayProxy` deployed on mainnet +contract Gateway202410 is Gateway { constructor( - address recoveryOperator, address beefyClient, address agentExecutor, ParaID bridgeHubParaID, @@ -27,14 +24,11 @@ contract RococoGatewayV2 is Gateway { ) {} - function initialize(bytes memory data) external override { - // Prevent initialization of storage in implementation contract + // Override parent initializer to prevent re-initialization of storage. + function initialize(bytes memory) external view override { + // Ensure that arbitrary users cannot initialize storage in this logic contract. if (ERC1967.load() == address(0)) { revert Unauthorized(); } - - PricingStorage.Layout storage pricing = PricingStorage.layout(); - - pricing.multiplier = abi.decode(data, (UD60x18)); } } diff --git a/contracts/src/upgrades/polkadot/GatewayPNA.sol b/contracts/src/upgrades/polkadot/GatewayPNA.sol deleted file mode 100644 index e219667576..0000000000 --- a/contracts/src/upgrades/polkadot/GatewayPNA.sol +++ /dev/null @@ -1,27 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 -// SPDX-FileCopyrightText: 2023 Snowfork -pragma solidity 0.8.25; - -import "../../Gateway.sol"; - -contract GatewayPNA is Gateway { - constructor( - address beefyClient, - address agentExecutor, - ParaID bridgeHubParaID, - bytes32 bridgeHubAgentID, - uint8 foreignTokenDecimals, - uint128 destinationMaxTransferFee - ) - Gateway( - beefyClient, - agentExecutor, - bridgeHubParaID, - bridgeHubAgentID, - foreignTokenDecimals, - destinationMaxTransferFee - ) - {} - - function initialize(bytes memory) external override {} -} diff --git a/contracts/test/ForkUpgrade.t.sol b/contracts/test/ForkUpgrade.t.sol index 5bbd0e8d9c..5b1a6069dd 100644 --- a/contracts/test/ForkUpgrade.t.sol +++ b/contracts/test/ForkUpgrade.t.sol @@ -7,7 +7,7 @@ import {console} from "forge-std/console.sol"; import {IUpgradable} from "../src/interfaces/IUpgradable.sol"; import {IGateway} from "../src/interfaces/IGateway.sol"; import {Gateway} from "../src/Gateway.sol"; -import {GatewayPNA} from "../src/upgrades/polkadot/GatewayPNA.sol"; +import {Gateway202410} from "../src/upgrades/Gateway202410.sol"; import {AgentExecutor} from "../src/AgentExecutor.sol"; import {UpgradeParams, SetOperatingModeParams, OperatingMode, RegisterForeignTokenParams} from "../src/Params.sol"; import {ChannelID, ParaID, OperatingMode, TokenInfo} from "../src/Types.sol"; @@ -27,8 +27,8 @@ contract ForkUpgradeTest is Test { function forkUpgrade() public { AgentExecutor executor = new AgentExecutor(); - GatewayPNA newLogic = - new GatewayPNA(BeefyClient, address(executor), ParaID.wrap(1002), BridgeHubAgent, 10, 20000000000); + Gateway202410 newLogic = + new Gateway202410(BeefyClient, address(executor), ParaID.wrap(1002), BridgeHubAgent, 10, 20000000000); UpgradeParams memory params = UpgradeParams({impl: address(newLogic), implCodeHash: address(newLogic).codehash, initParams: bytes("")}); @@ -54,7 +54,7 @@ contract ForkUpgradeTest is Test { vm.expectEmit(true, true, false, false); emit IGateway.ForeignTokenRegistered(dotId, address(0x0)); - GatewayPNA(GatewayProxy).registerForeignToken(abi.encode(params)); + Gateway202410(GatewayProxy).registerForeignToken(abi.encode(params)); assert(IGateway(GatewayProxy).isTokenRegistered(0x70D9d338A6b17957B16836a90192BD8CDAe0b53d)); assertEq(IGateway(GatewayProxy).queryForeignTokenID(0x70D9d338A6b17957B16836a90192BD8CDAe0b53d), dotId); }