From ba6b4012c5f1a663eecfe79dbfa899fb5cfaa1d3 Mon Sep 17 00:00:00 2001 From: Benjamin Patch Date: Wed, 1 Nov 2023 09:56:44 +1100 Subject: [PATCH] All contracts behind proxies --- axelar-local-dev/chain-config/local.json | 2 +- .../chain-config/local.template.json | 2 +- deploy.sh | 47 +++++++---- script/DeployChildContracts.s.sol | 17 ++-- script/DeployRootContracts.s.sol | 38 ++++++--- script/InitializeChildContracts.s.sol | 3 - script/InitializeRootContracts.s.sol | 78 ++++++++++++++----- src/child/ChildAxelarBridgeAdaptor.sol | 10 +++ src/root/RootAxelarBridgeAdaptor.sol | 45 ++++++----- .../integration/child/ChildAxelarBridge.t.sol | 3 +- .../unit/child/ChildAxelarBridgeAdaptor.t.sol | 3 +- test/unit/root/RootAxelarBridgeAdaptor.t.sol | 32 +++----- test/utils.t.sol | 9 +-- 13 files changed, 177 insertions(+), 112 deletions(-) diff --git a/axelar-local-dev/chain-config/local.json b/axelar-local-dev/chain-config/local.json index 017e00b5..9a04303f 100644 --- a/axelar-local-dev/chain-config/local.json +++ b/axelar-local-dev/chain-config/local.json @@ -16,7 +16,7 @@ "function mapToken(address rootToken) external payable returns (address)", "function deposit(address rootToken, uint256 amount) external payable" ], - "address": "0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0" + "address": "0x5FC8d32690cc91D4c39d9d3abcBD16989F875707" }, "usdc": { "abi": [ diff --git a/axelar-local-dev/chain-config/local.template.json b/axelar-local-dev/chain-config/local.template.json index 017e00b5..9a04303f 100644 --- a/axelar-local-dev/chain-config/local.template.json +++ b/axelar-local-dev/chain-config/local.template.json @@ -16,7 +16,7 @@ "function mapToken(address rootToken) external payable returns (address)", "function deposit(address rootToken, uint256 amount) external payable" ], - "address": "0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0" + "address": "0x5FC8d32690cc91D4c39d9d3abcBD16989F875707" }, "usdc": { "abi": [ diff --git a/deploy.sh b/deploy.sh index 5a6f399c..c67aee21 100755 --- a/deploy.sh +++ b/deploy.sh @@ -17,45 +17,52 @@ function main() { forge script script/DeployRootContracts.s.sol:DeployRootContracts --broadcast forge script script/DeployChildContracts.s.sol:DeployChildContracts --broadcast - echo "sleepy boy" - sleep 5 - root_filename="broadcast/DeployRootContracts.s.sol/$ROOT_CHAIN_ID/run-latest.json" child_filename="broadcast/DeployChildContracts.s.sol/$CHILD_CHAIN_ID/run-latest.json" # Extract smart contract addresses from deployments JSON - root_erc20_bridge=$( get_deployed_contract "$root_filename" "RootERC20Bridge" ) - root_bridge_adaptor=$( get_deployed_contract "$root_filename" "RootAxelarBridgeAdaptor" ) + root_proxies=$( get_deployed_contract "$root_filename" "TransparentUpgradeableProxy" ) + root_erc20_bridge_implementation=$( get_deployed_contract "$root_filename" "RootERC20Bridge" ) + root_bridge_adaptor_implementation=$( get_deployed_contract "$root_filename" "RootAxelarBridgeAdaptor" ) root_chain_child_token_template=$( get_deployed_contract "$root_filename" "ChildERC20" ) + root_proxy_admin=$( get_deployed_contract "$root_filename" "ProxyAdmin" ) if [ "$ENVIRONMENT" = "local" ]; then root_weth_contract=$( get_deployed_contract "$root_filename" "WETH" ) export ROOT_WETH_ADDRESS=$root_weth_contract fi + child_proxies=$( get_deployed_contract "$child_filename" "TransparentUpgradeableProxy" ) child_erc20_bridge_implementation=$( get_deployed_contract "$child_filename" "ChildERC20Bridge" ) - proxies=$( get_deployed_contract "$child_filename" "TransparentUpgradeableProxy" ) child_bridge_adaptor_implementation=$( get_deployed_contract "$child_filename" "ChildAxelarBridgeAdaptor" ) child_chain_child_token_template=$( get_deployed_contract "$child_filename" "ChildERC20" ) + child_proxy_admin=$( get_deployed_contract "$child_filename" "ProxyAdmin" ) - echo "Proxies: $proxies" - + # In the TransparentUpgradeableProxy contract, you have to query the storage slot directly. implementation_storage_slot="0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc" while IFS= read -r proxy_address; do - echo "... $proxy_address ..." implementation_slot_value=$(cast storage --rpc-url "$CHILD_RPC_URL" "$proxy_address" "$implementation_storage_slot") implementation_address=$(cast parse-bytes32-address "$implementation_slot_value") - echo "logic: $implementation_address" if [ "$implementation_address" = "$child_erc20_bridge_implementation" ]; then child_erc20_bridge_proxy=$proxy_address elif [ "$implementation_address" = "$child_bridge_adaptor_implementation" ]; then child_bridge_adaptor_proxy=$proxy_address fi - done <<< "$proxies" + done <<< "$child_proxies" + + while IFS= read -r proxy_address; do + implementation_slot_value=$(cast storage --rpc-url "$ROOT_RPC_URL" "$proxy_address" "$implementation_storage_slot") + implementation_address=$(cast parse-bytes32-address "$implementation_slot_value") + if [ "$implementation_address" = "$root_erc20_bridge_implementation" ]; then + root_erc20_bridge_proxy=$proxy_address + elif [ "$implementation_address" = "$root_bridge_adaptor_implementation" ]; then + root_bridge_adaptor_proxy=$proxy_address + fi + done <<< "$root_proxies" - export ROOT_ERC20_BRIDGE=$root_erc20_bridge - export ROOT_BRIDGE_ADAPTOR=$root_bridge_adaptor + export ROOT_ERC20_BRIDGE=$root_erc20_bridge_proxy + export ROOT_BRIDGE_ADAPTOR=$root_bridge_adaptor_proxy export ROOTCHAIN_CHILD_TOKEN_TEMPLATE=$root_chain_child_token_template export CHILD_BRIDGE_ADAPTOR=$child_bridge_adaptor_proxy @@ -68,12 +75,18 @@ function main() { # Write JSON file with contract addresses echo "{ \"root_chain_id\": \"$ROOT_CHAIN_ID\", - \"root_bridge\": \"$root_erc20_bridge\", - \"root_bridge_adaptor\": \"$root_bridge_adaptor\", + \"root_proxy_admin_address\": \"$root_proxy_admin\", + \"root_bridge_proxy_address\": \"$root_erc20_bridge_proxy\", + \"root_bridge_implementation_address\": \"$root_erc20_bridge_implementation\", + \"root_bridge_adaptor_proxy_address\": \"$root_bridge_adaptor_proxy\", + \"root_bridge_adaptor_implementation_address\": \"$root_bridge_adaptor_implementation\", \"root_chain_child_token_template\": \"$root_chain_child_token_template\", \"child_chain_id\": \"$CHILD_CHAIN_ID\", - \"child_bridge_address\": \"$child_erc20_bridge_proxy\", - \"child_bridge_adaptor\": \"$child_bridge_adaptor_proxy\", + \"child_proxy_admin_address\": \"$child_proxy_admin\", + \"child_bridge_proxy_address\": \"$child_erc20_bridge_proxy\", + \"child_bridge_implementation_address\": \"$child_erc20_bridge_implementation\", + \"child_bridge_proxy_adaptor\": \"$child_bridge_adaptor_proxy\", + \"child_bridge_adaptor_implementation_address\": \"$child_bridge_adaptor_implementation\", \"child_chain_child_token_template\": \"$child_chain_child_token_template\" }" | jq . > addresses.json diff --git a/script/DeployChildContracts.s.sol b/script/DeployChildContracts.s.sol index 10ec8711..a8d1f7c0 100644 --- a/script/DeployChildContracts.s.sol +++ b/script/DeployChildContracts.s.sol @@ -28,11 +28,11 @@ contract DeployChildContracts is Script { ChildERC20 childTokenTemplate = new ChildERC20(); childTokenTemplate.initialize(address(123), "TEMPLATE", "TPT", 18); - ChildERC20Bridge childBridgeImplementation = new ChildERC20Bridge(); - childBridgeImplementation.initialize(address(1), "0x123", address(1), "root", address(1)); + ChildERC20Bridge childERC20BridgeImplementation = new ChildERC20Bridge(); + childERC20BridgeImplementation.initialize(address(1), "0x123", address(1), "root", address(1)); - TransparentUpgradeableProxy childBridgeProxy = new TransparentUpgradeableProxy( - address(childBridgeImplementation), + TransparentUpgradeableProxy childERC20BridgeProxy = new TransparentUpgradeableProxy( + address(childERC20BridgeImplementation), address(proxyAdmin), "" ); @@ -41,7 +41,6 @@ contract DeployChildContracts is Script { childGateway ); - // TODO confirm that we want the same proxyAdmin for both TransparentUpgradeableProxy childBridgeAdaptorProxy = new TransparentUpgradeableProxy( address(childBridgeAdaptorImplementation), address(proxyAdmin), @@ -51,11 +50,11 @@ contract DeployChildContracts is Script { WIMX wrappedIMX = new WIMX(); vm.stopBroadcast(); - console2.log(ChildAxelarBridgeAdaptor(address(childBridgeAdaptorProxy)).rootBridgeAdaptor()); - console2.log(childGateway); - console2.log("====ADDRESSES===="); - console2.log("Child ERC20 Bridge: %s", address(childBridgeProxy)); + console2.log("====CHILD ADDRESSES===="); + console2.log("ProxyAdmin: %", address(proxyAdmin)); + console2.log("Child ERC20 Bridge Proxy: %s", address(childERC20BridgeProxy)); + console2.log("Child ERC20 Bridge Implementation: %s", address(childERC20BridgeImplementation)); console2.log("Child Axelar Bridge Adaptor Proxy: %s", address(childBridgeAdaptorProxy)); console2.log("Child Axelar Bridge Adaptor Implementation: %s", address(childBridgeAdaptorImplementation)); console2.log("childTokenTemplate: %s", address(childTokenTemplate)); diff --git a/script/DeployRootContracts.s.sol b/script/DeployRootContracts.s.sol index 0c3d4102..a1f49fce 100644 --- a/script/DeployRootContracts.s.sol +++ b/script/DeployRootContracts.s.sol @@ -3,6 +3,9 @@ pragma solidity ^0.8.21; import {Script, console2} from "forge-std/Script.sol"; +import {ProxyAdmin} from "@openzeppelin/contracts/proxy/transparent/ProxyAdmin.sol"; +import {TransparentUpgradeableProxy} from "@openzeppelin/contracts/proxy/transparent/TransparentUpgradeableProxy.sol"; + import {ChildERC20} from "../src/child/ChildERC20.sol"; import {RootERC20Bridge} from "../src/root/RootERC20Bridge.sol"; import {RootAxelarBridgeAdaptor} from "../src/root/RootAxelarBridgeAdaptor.sol"; @@ -17,9 +20,6 @@ contract DeployRootContracts is Script { function run() public { uint256 rootPrivateKey = vm.envUint("ROOT_PRIVATE_KEY"); string memory rootRpcUrl = vm.envString("ROOT_RPC_URL"); - address rootGateway = vm.envAddress("ROOT_GATEWAY_ADDRESS"); - address rootGasService = vm.envAddress("ROOT_GAS_SERVICE_ADDRESS"); - string memory childChainName = vm.envString("CHILD_CHAIN_NAME"); string memory deployEnvironment = vm.envString("ENVIRONMENT"); /** @@ -28,17 +28,30 @@ contract DeployRootContracts is Script { vm.createSelectFork(rootRpcUrl); vm.startBroadcast(rootPrivateKey); + ProxyAdmin proxyAdmin = new ProxyAdmin(); + // The ChildERC20 deployment on the root chain. ChildERC20 rootChainChildTokenTemplate = new ChildERC20(); rootChainChildTokenTemplate.initialize(address(123), "TEMPLATE", "TPT", 18); - RootERC20Bridge rootERC20Bridge = new RootERC20Bridge(); + RootERC20Bridge rootERC20BridgeImplementation = new RootERC20Bridge(); + rootERC20BridgeImplementation.initialize(address(1), address(1), "filler", address(1), address(1), address(1)); + TransparentUpgradeableProxy rootERC20BridgeProxy = new TransparentUpgradeableProxy( + address(rootERC20BridgeImplementation), + address(proxyAdmin), + "" + ); - RootAxelarBridgeAdaptor rootBridgeAdaptor = new RootAxelarBridgeAdaptor( - address(rootERC20Bridge), // root bridge - childChainName, // child chain name - rootGateway, // axelar gateway - rootGasService // axelar gas service + // TODO add dummy initialize of implementation contracts! + + RootAxelarBridgeAdaptor rootBridgeAdaptorImplementation = new RootAxelarBridgeAdaptor(); + rootBridgeAdaptorImplementation.initialize( + address(rootERC20BridgeImplementation), "Filler", address(1), address(1) + ); + TransparentUpgradeableProxy rootBridgeAdaptorProxy = new TransparentUpgradeableProxy( + address(rootBridgeAdaptorImplementation), + address(proxyAdmin), + "" ); if (Strings.equal(deployEnvironment, "local")) { @@ -48,8 +61,11 @@ contract DeployRootContracts is Script { vm.stopBroadcast(); console2.log("====ROOT ADDRESSES===="); - console2.log("Root ERC20 Bridge: %s", address(rootERC20Bridge)); - console2.log("Root Axelar Bridge Adaptor: %s", address(rootBridgeAdaptor)); + console2.log("ProxyAdmin: %", address(proxyAdmin)); + console2.log("Root ERC20 Bridge Proxy: %s", address(rootERC20BridgeProxy)); + console2.log("Root ERC20 Bridge Implementation: %s", address(rootERC20BridgeImplementation)); + console2.log("Root Axelar Bridge Adaptor Proxy: %s", address(rootBridgeAdaptorProxy)); + console2.log("Root Axelar Bridge Adaptor Implementation: %s", address(rootBridgeAdaptorImplementation)); console2.log("ROOT CHAIN childTokenTemplate: %s", address(rootChainChildTokenTemplate)); } } diff --git a/script/InitializeChildContracts.s.sol b/script/InitializeChildContracts.s.sol index 84fa4c37..ec29a6cd 100644 --- a/script/InitializeChildContracts.s.sol +++ b/script/InitializeChildContracts.s.sol @@ -38,8 +38,5 @@ contract InitializeChildContracts is Script { childAxelarBridgeAdaptor.initialize(address(childERC20Bridge)); vm.stopBroadcast(); - - console2.log("DINGDING"); - console2.log(childAxelarBridgeAdaptor.rootBridgeAdaptor()); } } diff --git a/script/InitializeRootContracts.s.sol b/script/InitializeRootContracts.s.sol index 2a8d43e1..e0c869a3 100644 --- a/script/InitializeRootContracts.s.sol +++ b/script/InitializeRootContracts.s.sol @@ -13,39 +13,75 @@ import {Utils} from "./Utils.sol"; // TODO update private key usage to be more secure: https://book.getfoundry.sh/reference/forge/forge-script#wallet-options---raw +struct InitializeRootContractsParams { + RootERC20Bridge rootERC20Bridge; + RootAxelarBridgeAdaptor rootBridgeAdaptor; + address rootChainChildTokenTemplate; + address childBridgeAdaptor; + address childERC20Bridge; + string rootRpcUrl; + uint256 rootPrivateKey; + address rootIMXToken; + address rootWETHToken; + string childChainName; + address rootGateway; + address rootGasService; +} + contract InitializeRootContracts is Script { function run() public { - RootERC20Bridge rootERC20Bridge = RootERC20Bridge(payable(vm.envAddress("ROOT_ERC20_BRIDGE"))); - RootAxelarBridgeAdaptor rootBridgeAdaptor = RootAxelarBridgeAdaptor(vm.envAddress("ROOT_BRIDGE_ADAPTOR")); - address rootChainChildTokenTemplate = vm.envAddress("ROOTCHAIN_CHILD_TOKEN_TEMPLATE"); - address childBridgeAdaptor = vm.envAddress("CHILD_BRIDGE_ADAPTOR"); - address childERC20Bridge = vm.envAddress("CHILD_ERC20_BRIDGE"); - string memory rootRpcUrl = vm.envString("ROOT_RPC_URL"); - uint256 rootPrivateKey = vm.envUint("ROOT_PRIVATE_KEY"); - address rootIMXToken = vm.envAddress("ROOT_IMX_ADDRESS"); - address rootWETHToken = vm.envAddress("ROOT_WETH_ADDRESS"); - - string[] memory checksumInputs = Utils.getChecksumInputs(childBridgeAdaptor); + InitializeRootContractsParams memory params = InitializeRootContractsParams({ + rootERC20Bridge: RootERC20Bridge(payable(vm.envAddress("ROOT_ERC20_BRIDGE"))), + rootBridgeAdaptor: RootAxelarBridgeAdaptor(vm.envAddress("ROOT_BRIDGE_ADAPTOR")), + rootChainChildTokenTemplate: vm.envAddress("ROOTCHAIN_CHILD_TOKEN_TEMPLATE"), + childBridgeAdaptor: vm.envAddress("CHILD_BRIDGE_ADAPTOR"), + childERC20Bridge: vm.envAddress("CHILD_ERC20_BRIDGE"), + rootRpcUrl: vm.envString("ROOT_RPC_URL"), + rootPrivateKey: vm.envUint("ROOT_PRIVATE_KEY"), + rootIMXToken: vm.envAddress("ROOT_IMX_ADDRESS"), + rootWETHToken: vm.envAddress("ROOT_WETH_ADDRESS"), + childChainName: vm.envString("CHILD_CHAIN_NAME"), + rootGateway: vm.envAddress("ROOT_GATEWAY_ADDRESS"), + rootGasService: vm.envAddress("ROOT_GAS_SERVICE_ADDRESS") + }); + // RootERC20Bridge rootERC20Bridge = RootERC20Bridge(payable(vm.envAddress("ROOT_ERC20_BRIDGE"))); + // RootAxelarBridgeAdaptor rootBridgeAdaptor = RootAxelarBridgeAdaptor(vm.envAddress("ROOT_BRIDGE_ADAPTOR")); + // address rootChainChildTokenTemplate = vm.envAddress("ROOTCHAIN_CHILD_TOKEN_TEMPLATE"); + // address childBridgeAdaptor = vm.envAddress("CHILD_BRIDGE_ADAPTOR"); + // address childERC20Bridge = vm.envAddress("CHILD_ERC20_BRIDGE"); + // string memory rootRpcUrl = vm.envString("ROOT_RPC_URL"); + // uint256 rootPrivateKey = vm.envUint("ROOT_PRIVATE_KEY"); + // address rootIMXToken = vm.envAddress("ROOT_IMX_ADDRESS"); + // address rootWETHToken = vm.envAddress("ROOT_WETH_ADDRESS"); + // string memory childChainName = vm.envString("CHILD_CHAIN_NAME"); + // address rootGateway = vm.envAddress("ROOT_GATEWAY_ADDRESS"); + // address rootGasService = vm.envAddress("ROOT_GAS_SERVICE_ADDRESS"); + + string[] memory checksumInputs = Utils.getChecksumInputs(params.childBridgeAdaptor); bytes memory checksumOutput = vm.ffi(checksumInputs); string memory childBridgeAdaptorChecksum = string(Utils.removeZeroByteValues(checksumOutput)); /** * INITIALIZE ROOT CHAIN CONTRACTS */ - vm.createSelectFork(rootRpcUrl); - vm.startBroadcast(rootPrivateKey); + vm.createSelectFork(params.rootRpcUrl); + vm.startBroadcast(params.rootPrivateKey); - rootERC20Bridge.initialize( - address(rootBridgeAdaptor), - childERC20Bridge, + params.rootERC20Bridge.initialize( + address(params.rootBridgeAdaptor), + params.childERC20Bridge, childBridgeAdaptorChecksum, - rootChainChildTokenTemplate, - rootIMXToken, - rootWETHToken + params.rootChainChildTokenTemplate, + params.rootIMXToken, + params.rootWETHToken ); - rootBridgeAdaptor.setChildBridgeAdaptor(); + params.rootBridgeAdaptor.initialize( + address(params.rootERC20Bridge), // root bridge + params.childChainName, // child chain name + params.rootGateway, // axelar gateway + params.rootGasService // axelar gas service + ); vm.stopBroadcast(); - console2.log(rootERC20Bridge.childBridgeAdaptor()); } } diff --git a/src/child/ChildAxelarBridgeAdaptor.sol b/src/child/ChildAxelarBridgeAdaptor.sol index ae79be87..4408bb77 100644 --- a/src/child/ChildAxelarBridgeAdaptor.sol +++ b/src/child/ChildAxelarBridgeAdaptor.sol @@ -27,6 +27,16 @@ contract ChildAxelarBridgeAdaptor is AxelarExecutable, Initializable, IChildAxel rootBridgeAdaptor = childBridge.rootERC20BridgeAdaptor(); } + // TODO tests for this + // TODO does this need to be permissioned? + /** + * @notice Sets the root bridge adaptor address. + * @dev Always sets it to whatever the rootERC20BridgeAdaptor of the bridge contract is. + */ + function setRootBridgeAdaptor() external { + rootBridgeAdaptor = childBridge.rootERC20BridgeAdaptor(); + } + /** * @dev This function is called by the parent `AxelarExecutable` contract to execute the payload. * @custom:assumes `sourceAddress_` is a 20 byte address. diff --git a/src/root/RootAxelarBridgeAdaptor.sol b/src/root/RootAxelarBridgeAdaptor.sol index 25873923..0f881643 100644 --- a/src/root/RootAxelarBridgeAdaptor.sol +++ b/src/root/RootAxelarBridgeAdaptor.sol @@ -1,6 +1,7 @@ // SPDX-License-Identifier: Apache 2.0 pragma solidity ^0.8.21; +import {Initializable} from "@openzeppelin/contracts/proxy/utils/Initializable.sol"; import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import {IERC20Metadata} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol"; import {Strings} from "@openzeppelin/contracts/utils/Strings.sol"; @@ -20,22 +21,29 @@ import {IRootERC20Bridge} from "../interfaces/root/IRootERC20Bridge.sol"; * @dev This is not an upgradeable contract, because it is trivial to deploy a new one if needed. */ contract RootAxelarBridgeAdaptor is + Initializable, IRootERC20BridgeAdaptor, IRootAxelarBridgeAdaptorEvents, IRootAxelarBridgeAdaptorErrors { using SafeERC20 for IERC20Metadata; - address public immutable ROOT_BRIDGE; + address public rootBridge; string public childBridgeAdaptor; /// @dev childChain could be immutable, but as of writing this Solidity does not support immutable strings. /// see: https://ethereum.stackexchange.com/questions/127622/typeerror-immutable-variables-cannot-have-a-non-value-type string public childChain; - IAxelarGateway public immutable AXELAR_GATEWAY; - IAxelarGasService public immutable GAS_SERVICE; + IAxelarGateway public axelarGateway; + IAxelarGasService public gasService; mapping(uint256 => string) public chainIdToChainName; - constructor(address _rootBridge, string memory _childChain, address _axelarGateway, address _gasService) { + /** + * @dev Always sets it to whatever the childBridgeAdaptor of the bridge contract is. + */ + function initialize(address _rootBridge, string memory _childChain, address _axelarGateway, address _gasService) + public + initializer + { if (_rootBridge == address(0) || _axelarGateway == address(0) || _gasService == address(0)) { revert ZeroAddresses(); } @@ -43,10 +51,19 @@ contract RootAxelarBridgeAdaptor is if (bytes(_childChain).length == 0) { revert InvalidChildChain(); } - ROOT_BRIDGE = _rootBridge; + rootBridge = _rootBridge; childChain = _childChain; - AXELAR_GATEWAY = IAxelarGateway(_axelarGateway); - GAS_SERVICE = IAxelarGasService(_gasService); + axelarGateway = IAxelarGateway(_axelarGateway); + gasService = IAxelarGasService(_gasService); + childBridgeAdaptor = IRootERC20Bridge(rootBridge).childBridgeAdaptor(); + } + + /** + * @notice Sets the child bridge adaptor address. + * @dev Always sets it to whatever the childBridgeAdaptor of the bridge contract is. + */ + function setChildBridgeAdaptor() external { + childBridgeAdaptor = IRootERC20Bridge(rootBridge).childBridgeAdaptor(); } /** @@ -57,7 +74,7 @@ contract RootAxelarBridgeAdaptor is if (msg.value == 0) { revert NoGas(); } - if (msg.sender != ROOT_BRIDGE) { + if (msg.sender != rootBridge) { revert CallerNotBridge(); } @@ -66,19 +83,11 @@ contract RootAxelarBridgeAdaptor is string memory _childChain = childChain; // TODO For `sender` (first param), should likely be refundRecipient (and in which case refundRecipient should be renamed to sender and used as refund recipient) - GAS_SERVICE.payNativeGasForContractCall{value: msg.value}( + gasService.payNativeGasForContractCall{value: msg.value}( address(this), _childChain, _childBridgeAdaptor, payload, refundRecipient ); - AXELAR_GATEWAY.callContract(_childChain, _childBridgeAdaptor, payload); + axelarGateway.callContract(_childChain, _childBridgeAdaptor, payload); emit MapTokenAxelarMessage(_childChain, _childBridgeAdaptor, payload); } - - /** - * @notice Sets the child bridge adaptor address. - * @dev Always sets it to whatever the childBridgeAdaptor of the bridge contract is. - */ - function setChildBridgeAdaptor() external { - childBridgeAdaptor = IRootERC20Bridge(ROOT_BRIDGE).childBridgeAdaptor(); - } } diff --git a/test/integration/child/ChildAxelarBridge.t.sol b/test/integration/child/ChildAxelarBridge.t.sol index ab1d8689..94517692 100644 --- a/test/integration/child/ChildAxelarBridge.t.sol +++ b/test/integration/child/ChildAxelarBridge.t.sol @@ -32,8 +32,7 @@ contract ChildERC20BridgeIntegrationTest is Test, IChildERC20BridgeEvents, IChil childERC20Bridge = new ChildERC20Bridge(); mockChildAxelarGateway = new MockChildAxelarGateway(); - childAxelarBridgeAdaptor = - new ChildAxelarBridgeAdaptor(address(mockChildAxelarGateway)); + childAxelarBridgeAdaptor = new ChildAxelarBridgeAdaptor(address(mockChildAxelarGateway)); childERC20Bridge.initialize( address(childAxelarBridgeAdaptor), diff --git a/test/unit/child/ChildAxelarBridgeAdaptor.t.sol b/test/unit/child/ChildAxelarBridgeAdaptor.t.sol index fd5783fb..18e324a1 100644 --- a/test/unit/child/ChildAxelarBridgeAdaptor.t.sol +++ b/test/unit/child/ChildAxelarBridgeAdaptor.t.sol @@ -19,8 +19,7 @@ contract ChildAxelarBridgeAdaptorUnitTest is Test, IChildAxelarBridgeAdaptorErro function setUp() public { mockChildERC20Bridge = new MockChildERC20Bridge(); mockChildAxelarGateway = new MockChildAxelarGateway(); - childAxelarBridgeAdaptor = - new ChildAxelarBridgeAdaptor(address(mockChildAxelarGateway)); + childAxelarBridgeAdaptor = new ChildAxelarBridgeAdaptor(address(mockChildAxelarGateway)); childAxelarBridgeAdaptor.initialize(address(mockChildERC20Bridge)); } diff --git a/test/unit/root/RootAxelarBridgeAdaptor.t.sol b/test/unit/root/RootAxelarBridgeAdaptor.t.sol index f1fc3ee0..c93c70d0 100644 --- a/test/unit/root/RootAxelarBridgeAdaptor.t.sol +++ b/test/unit/root/RootAxelarBridgeAdaptor.t.sol @@ -33,42 +33,32 @@ contract RootAxelarBridgeAdaptorTest is Test, IRootAxelarBridgeAdaptorEvents, IR stubRootBridge = new StubRootBridge(); childBridgeAdaptor = stubRootBridge.childBridgeAdaptor(); - axelarAdaptor = new RootAxelarBridgeAdaptor( - address(stubRootBridge), - CHILD_CHAIN_NAME, - address(mockAxelarGateway), - address(axelarGasService) + axelarAdaptor = new RootAxelarBridgeAdaptor(); + axelarAdaptor.initialize( + address(stubRootBridge), CHILD_CHAIN_NAME, address(mockAxelarGateway), address(axelarGasService) ); axelarAdaptor.setChildBridgeAdaptor(); vm.deal(address(stubRootBridge), 99999999999); } function test_Constructor() public { - assertEq(axelarAdaptor.ROOT_BRIDGE(), address(stubRootBridge), "rootBridge not set"); + assertEq(axelarAdaptor.rootBridge(), address(stubRootBridge), "rootBridge not set"); assertEq(axelarAdaptor.childBridgeAdaptor(), childBridgeAdaptor, "childBridgeAdaptor not set"); assertEq(axelarAdaptor.childChain(), CHILD_CHAIN_NAME, "childChain not set"); - assertEq(address(axelarAdaptor.AXELAR_GATEWAY()), address(mockAxelarGateway), "axelarGateway not set"); - assertEq(address(axelarAdaptor.GAS_SERVICE()), address(axelarGasService), "axelarGasService not set"); + assertEq(address(axelarAdaptor.axelarGateway()), address(mockAxelarGateway), "axelarGateway not set"); + assertEq(address(axelarAdaptor.gasService()), address(axelarGasService), "axelarGasService not set"); } - function test_RevertWhen_ConstructorGivenZeroAddress() public { + function test_RevertWhen_InitializerGivenZeroAddress() public { + RootAxelarBridgeAdaptor newAdaptor = new RootAxelarBridgeAdaptor(); vm.expectRevert(ZeroAddresses.selector); - new RootAxelarBridgeAdaptor( - address(0), - CHILD_CHAIN_NAME, - address(mockAxelarGateway), - address(axelarGasService) - ); + newAdaptor.initialize(address(0), CHILD_CHAIN_NAME, address(mockAxelarGateway), address(axelarGasService)); } function test_RevertWhen_ConstructorGivenEmptyChildChainName() public { + RootAxelarBridgeAdaptor newAdaptor = new RootAxelarBridgeAdaptor(); vm.expectRevert(InvalidChildChain.selector); - new RootAxelarBridgeAdaptor( - address(this), - "", - address(mockAxelarGateway), - address(axelarGasService) - ); + newAdaptor.initialize(address(this), "", address(mockAxelarGateway), address(axelarGasService)); } /// @dev For this unit test we just want to make sure the correct functions are called on the Axelar Gateway and Gas Service. diff --git a/test/utils.t.sol b/test/utils.t.sol index 9a53896a..48c309d8 100644 --- a/test/utils.t.sol +++ b/test/utils.t.sol @@ -47,11 +47,9 @@ contract Utils is Test { mockAxelarGateway = new MockAxelarGateway(); axelarGasService = new MockAxelarGasService(); - axelarAdaptor = new RootAxelarBridgeAdaptor( - address(rootBridge), - childBridgeName, - address(mockAxelarGateway), - address(axelarGasService) + axelarAdaptor = new RootAxelarBridgeAdaptor(); + axelarAdaptor.initialize( + address(rootBridge), childBridgeName, address(mockAxelarGateway), address(axelarGasService) ); rootBridge.initialize( @@ -62,7 +60,6 @@ contract Utils is Test { imxTokenAddress, wethTokenAddress ); - axelarAdaptor.setChildBridgeAdaptor(); } function setupDeposit(