Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Smr 1910 rbac #23

Merged
merged 25 commits into from
Nov 13, 2023
Merged
Show file tree
Hide file tree
Changes from 24 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 14 additions & 6 deletions .env.sample
Original file line number Diff line number Diff line change
@@ -1,15 +1,23 @@
ROOT_ADMIN_ADDRESS=
ROOT_PAUSER_ADDRESS=
ROOT_UNPAUSER_ADDRESS=
ROOT_RPC_URL=
CHILD_RPC_URL=
ROOT_CHAIN_ID=
CHILD_CHAIN_ID=
ROOT_PRIVATE_KEY=
CHILD_PRIVATE_KEY=
ROOT_GATEWAY_ADDRESS=
CHILD_GATEWAY_ADDRESS=
ROOT_GAS_SERVICE_ADDRESS=
CHILD_GAS_SERVICE_ADDRESS=
ROOT_CHAIN_NAME=
CHILD_CHAIN_NAME=
ROOT_IMX_ADDRESS=
ROOT_WETH_ADDRESS=
INITIAL_IMX_CUMULATIVE_DEPOSIT_LIMIT= # 0 for unlimited

CHILD_ADMIN_ADDRESS=
CHILD_PAUSER_ADDRESS=
CHILD_UNPAUSER_ADDRESS=
CHILD_RPC_URL=
CHILD_CHAIN_ID=
CHILD_PRIVATE_KEY=
CHILD_GATEWAY_ADDRESS=
CHILD_GAS_SERVICE_ADDRESS=
CHILD_CHAIN_NAME=
ENVIRONMENT=
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ yarn run execute evm/call-contract local Ethereum Polygon map
5. (OPTIONAL) Check the token mapping has been populated using `cast`
```shell
source .env
cast call --rpc-url $CHILD_RPC_URL "0x9fE46736679d2D9a65F0992F2272dE9f3c7fa6e0" "rootTokenToChildToken(address)(address)" "0x38Aa1Cb12E5263eC0c6e9febC25B01116D346CD4"
cast call --rpc-url $CHILD_RPC_URL "0x5FC8d32690cc91D4c39d9d3abcBD16989F875707" "rootTokenToChildToken(address)(address)" "0x38Aa1Cb12E5263eC0c6e9febC25B01116D346CD4"
```

6. Run the script that will send a `DEPOSIT` message
Expand All @@ -172,6 +172,6 @@ yarn run execute evm/call-contract local Ethereum Polygon deposit
7. (OPTIONAL) Check the tokens have been deposited using `cast`
```shell
source .env
cast call --rpc-url $CHILD_RPC_URL "0x3b39f73D7De57Ed2Fe85C0F30374D839dc625b93" "balanceOf(address)(uint256)" "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266"
cast call --rpc-url $CHILD_RPC_URL "0xa03647137120b00cae83751A82280A67df027F04" "balanceOf(address)(uint256)" "0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266"
```
(Note: This assumes your address is the one associated with the above-specified private key)
1 change: 1 addition & 0 deletions foundry.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,5 +2,6 @@
src = "src"
out = "out"
libs = ["lib"]
solc-version = "0.8.19"

# See more config options https://github.com/foundry-rs/foundry/blob/master/crates/config/README.md#all-options
14 changes: 11 additions & 3 deletions script/DeployChildContracts.s.sol
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
// SPDX-License-Identifier: Apache 2.0
pragma solidity ^0.8.21;
pragma solidity 0.8.19;

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 {ChildERC20Bridge} from "../src/child/ChildERC20Bridge.sol";
import {ChildERC20Bridge, IChildERC20Bridge} from "../src/child/ChildERC20Bridge.sol";
import {ChildAxelarBridgeAdaptor} from "../src/child/ChildAxelarBridgeAdaptor.sol";
import {ChildERC20} from "../src/child/ChildERC20.sol";
import {WIMX} from "../src/child/WIMX.sol";
Expand All @@ -27,8 +27,16 @@ contract DeployChildContracts is Script {
ChildERC20 childTokenTemplate = new ChildERC20();
childTokenTemplate.initialize(address(123), "TEMPLATE", "TPT", 18);

IChildERC20Bridge.InitializationRoles memory roles = IChildERC20Bridge.InitializationRoles({
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not a blocker but in general better to avoid the precompile addresses for things

defaultAdmin: address(0x1111),
pauser: address(0x2222),
unpauser: address(0x3333),
variableManager: address(0x4444),
adaptorManager: address(0x5555)
});

ChildERC20Bridge childERC20BridgeImplementation = new ChildERC20Bridge();
childERC20BridgeImplementation.initialize(address(1), "0x123", address(1), "root", address(1));
childERC20BridgeImplementation.initialize(roles, address(1), "0x123", address(1), "root", address(1));

TransparentUpgradeableProxy childERC20BridgeProxy = new TransparentUpgradeableProxy(
address(childERC20BridgeImplementation),
Expand Down
9 changes: 6 additions & 3 deletions script/DeployRootContracts.s.sol
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
// SPDX-License-Identifier: Apache 2.0
pragma solidity ^0.8.21;
pragma solidity 0.8.19;

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 {RootERC20Bridge, IRootERC20Bridge} from "../src/root/RootERC20Bridge.sol";
import {RootAxelarBridgeAdaptor} from "../src/root/RootAxelarBridgeAdaptor.sol";
import {ChildERC20Bridge} from "../src/child/ChildERC20Bridge.sol";
import {ChildAxelarBridgeAdaptor} from "../src/child/ChildAxelarBridgeAdaptor.sol";
Expand Down Expand Up @@ -35,9 +35,12 @@ contract DeployRootContracts is Script {
ChildERC20 rootChainChildTokenTemplate = new ChildERC20();
rootChainChildTokenTemplate.initialize(address(123), "TEMPLATE", "TPT", 18);

IRootERC20Bridge.InitializationRoles memory fillerRoles =
IRootERC20Bridge.InitializationRoles(address(1), address(1), address(1), address(1), address(1));

RootERC20Bridge rootERC20BridgeImplementation = new RootERC20Bridge();
rootERC20BridgeImplementation.initialize(
address(1), address(1), "filler", address(1), address(1), address(1), "filler_child_name", 1
fillerRoles, address(1), address(1), "filler", address(1), address(1), address(1), "filler_child_name", 1
);
TransparentUpgradeableProxy rootERC20BridgeProxy = new TransparentUpgradeableProxy(
address(rootERC20BridgeImplementation),
Expand Down
70 changes: 52 additions & 18 deletions script/InitializeChildContracts.s.sol
Original file line number Diff line number Diff line change
@@ -1,42 +1,76 @@
// SPDX-License-Identifier: Apache 2.0
pragma solidity ^0.8.21;
pragma solidity 0.8.19;

import {Script, console2} from "forge-std/Script.sol";

import {ChildERC20Bridge} from "../src/child/ChildERC20Bridge.sol";
import {ChildERC20Bridge, IChildERC20Bridge} from "../src/child/ChildERC20Bridge.sol";
import {ChildAxelarBridgeAdaptor} from "../src/child/ChildAxelarBridgeAdaptor.sol";
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 InitializeChildContractsParams {
address childAdminAddress;
address childPauserAddress;
address childUnpauserAddress;
ChildERC20Bridge childERC20Bridge;
ChildAxelarBridgeAdaptor childAxelarBridgeAdaptor;
address childTokenTemplate;
address rootERC20BridgeAdaptor;
string rootChainName;
address rootIMXToken;
string childRpcUrl;
uint256 deployerPrivateKey;
address childGasService;
}

contract InitializeChildContracts is Script {
function run() public {
uint256 deployerPrivateKey = vm.envUint("CHILD_PRIVATE_KEY");
ChildERC20Bridge childERC20Bridge = ChildERC20Bridge(vm.envAddress("CHILD_ERC20_BRIDGE"));
ChildAxelarBridgeAdaptor childAxelarBridgeAdaptor =
ChildAxelarBridgeAdaptor(vm.envAddress("CHILD_BRIDGE_ADAPTOR"));
address childTokenTemplate = vm.envAddress("CHILDCHAIN_CHILD_TOKEN_TEMPLATE");
address rootERC20BridgeAdaptor = vm.envAddress("ROOT_BRIDGE_ADAPTOR");
string memory childRpcUrl = vm.envString("CHILD_RPC_URL");
string memory rootChainName = vm.envString("ROOT_CHAIN_NAME");
address rootIMXToken = vm.envAddress("ROOT_IMX_ADDRESS");
address childGasService = vm.envAddress("CHILD_GAS_SERVICE_ADDRESS"); // Not yet used.
InitializeChildContractsParams memory params = InitializeChildContractsParams({
childAdminAddress: vm.envAddress("CHILD_ADMIN_ADDRESS"),
childPauserAddress: vm.envAddress("CHILD_PAUSER_ADDRESS"),
childUnpauserAddress: vm.envAddress("CHILD_UNPAUSER_ADDRESS"),
childERC20Bridge: ChildERC20Bridge(vm.envAddress("CHILD_ERC20_BRIDGE")),
childAxelarBridgeAdaptor: ChildAxelarBridgeAdaptor(vm.envAddress("CHILD_BRIDGE_ADAPTOR")),
childTokenTemplate: vm.envAddress("CHILDCHAIN_CHILD_TOKEN_TEMPLATE"),
rootERC20BridgeAdaptor: vm.envAddress("ROOT_BRIDGE_ADAPTOR"),
rootChainName: vm.envString("ROOT_CHAIN_NAME"),
rootIMXToken: vm.envAddress("ROOT_IMX_ADDRESS"),
childRpcUrl: vm.envString("CHILD_RPC_URL"),
deployerPrivateKey: vm.envUint("CHILD_PRIVATE_KEY"),
childGasService: vm.envAddress("CHILD_GAS_SERVICE_ADDRESS")
});

/**
* INITIALIZE CHILD CONTRACTS
*/
string[] memory checksumInputs = Utils.getChecksumInputs(rootERC20BridgeAdaptor);
string[] memory checksumInputs = Utils.getChecksumInputs(params.rootERC20BridgeAdaptor);
bytes memory checksumOutput = vm.ffi(checksumInputs);
string memory rootBridgeAdaptorString = string(Utils.removeZeroByteValues(checksumOutput));

vm.createSelectFork(childRpcUrl);
vm.startBroadcast(deployerPrivateKey);
vm.createSelectFork(params.childRpcUrl);
vm.startBroadcast(params.deployerPrivateKey);

childERC20Bridge.initialize(
address(childAxelarBridgeAdaptor), rootBridgeAdaptorString, childTokenTemplate, rootChainName, rootIMXToken
// TODO update
IChildERC20Bridge.InitializationRoles memory roles = IChildERC20Bridge.InitializationRoles({
defaultAdmin: params.childAdminAddress,
pauser: params.childPauserAddress,
unpauser: params.childUnpauserAddress,
variableManager: params.childAdminAddress,
adaptorManager: params.childAdminAddress
Comment on lines +59 to +60
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't look right. The variable manager and adaptor manager is same as the childAdmin?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The script isn't looking good and looks pretty outdated, so worth creating a ticket to update the script in a separate PR.

});
params.childERC20Bridge.initialize(
roles,
address(params.childAxelarBridgeAdaptor),
rootBridgeAdaptorString,
params.childTokenTemplate,
params.rootChainName,
params.rootIMXToken
);

childAxelarBridgeAdaptor.initialize(rootChainName, address(childERC20Bridge), childGasService);
params.childAxelarBridgeAdaptor.initialize(
params.rootChainName, address(params.childERC20Bridge), params.childGasService
);

vm.stopBroadcast();
}
Expand Down
21 changes: 19 additions & 2 deletions script/InitializeRootContracts.s.sol
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
// SPDX-License-Identifier: Apache 2.0
pragma solidity ^0.8.21;
pragma solidity 0.8.19;

import {Script, console2} from "forge-std/Script.sol";

import {ChildERC20} from "../src/child/ChildERC20.sol";
import {RootERC20Bridge} from "../src/root/RootERC20Bridge.sol";
import {RootERC20Bridge, IRootERC20Bridge} from "../src/root/RootERC20Bridge.sol";
import {RootAxelarBridgeAdaptor} from "../src/root/RootAxelarBridgeAdaptor.sol";
import {ChildERC20Bridge} from "../src/child/ChildERC20Bridge.sol";
import {ChildAxelarBridgeAdaptor} from "../src/child/ChildAxelarBridgeAdaptor.sol";
Expand All @@ -14,6 +14,9 @@ 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 {
address rootAdminAddress;
address rootPauserAddress;
address rootUnpauserAddress;
RootERC20Bridge rootERC20Bridge;
RootAxelarBridgeAdaptor rootBridgeAdaptor;
address rootChainChildTokenTemplate;
Expand All @@ -31,6 +34,9 @@ struct InitializeRootContractsParams {
contract InitializeRootContracts is Script {
function run() public {
InitializeRootContractsParams memory params = InitializeRootContractsParams({
rootAdminAddress: vm.envAddress("ROOT_ADMIN_ADDRESS"),
rootPauserAddress: vm.envAddress("ROOT_PAUSER_ADDRESS"),
rootUnpauserAddress: vm.envAddress("ROOT_UNPAUSER_ADDRESS"),
rootERC20Bridge: RootERC20Bridge(payable(vm.envAddress("ROOT_ERC20_BRIDGE"))),
rootBridgeAdaptor: RootAxelarBridgeAdaptor(vm.envAddress("ROOT_BRIDGE_ADAPTOR")),
rootChainChildTokenTemplate: vm.envAddress("ROOTCHAIN_CHILD_TOKEN_TEMPLATE"),
Expand All @@ -54,7 +60,18 @@ contract InitializeRootContracts is Script {
vm.createSelectFork(params.rootRpcUrl);
vm.startBroadcast(params.rootPrivateKey);

// TODO add pauser, unpauser roles. variable manager and Adaptor manager will be privileged transaction multisg

IRootERC20Bridge.InitializationRoles memory roles = IRootERC20Bridge.InitializationRoles({
defaultAdmin: params.rootAdminAddress,
pauser: params.rootPauserAddress,
unpauser: params.rootUnpauserAddress,
variableManager: params.rootAdminAddress,
adaptorManager: params.rootAdminAddress
Comment on lines +69 to +70
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here, is it intended that the variableManager and adaptorManager is the rootAdmin?

});

params.rootERC20Bridge.initialize(
roles,
address(params.rootBridgeAdaptor),
params.childERC20Bridge,
childBridgeAdaptorChecksum,
Expand Down
2 changes: 1 addition & 1 deletion script/Utils.sol
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: Apache 2.0
pragma solidity ^0.8.21;
pragma solidity 0.8.19;

import {AddressToString} from "@axelar-gmp-sdk-solidity/contracts/libs/AddressString.sol";

Expand Down
2 changes: 1 addition & 1 deletion src/child/ChildAxelarBridgeAdaptor.sol
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: Apache 2.0
pragma solidity ^0.8.21;
pragma solidity 0.8.19;

import {AxelarExecutable} from "@axelar-gmp-sdk-solidity/contracts/executable/AxelarExecutable.sol";
import {IAxelarGasService} from "@axelar-cgp-solidity/contracts/interfaces/IAxelarGasService.sol";
Expand Down
2 changes: 1 addition & 1 deletion src/child/ChildERC20.sol
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: Apache 2.0
// Adapted from OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/ERC20.sol)
pragma solidity ^0.8.21;
pragma solidity 0.8.19;

import "@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol";
import "../lib/EIP712MetaTransaction.sol";
Expand Down
42 changes: 34 additions & 8 deletions src/child/ChildERC20Bridge.sol
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
// SPDX-License-Identifier: Apache 2.0
pragma solidity ^0.8.21;
pragma solidity 0.8.19;

import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
import {AccessControlUpgradeable} from "@openzeppelin/contracts-upgradeable/access/AccessControlUpgradeable.sol";
import {Clones} from "@openzeppelin/contracts/proxy/Clones.sol";
import {Strings} from "@openzeppelin/contracts/utils/Strings.sol";
import {Address} from "@openzeppelin/contracts/utils/Address.sol";
import {Ownable2Step} from "@openzeppelin/contracts/access/Ownable2Step.sol";
import {
IChildERC20BridgeEvents,
IChildERC20BridgeErrors,
Expand All @@ -25,8 +24,7 @@ import {IChildERC20} from "../interfaces/child/IChildERC20.sol";
* @dev Any checks or logic that is specific to the underlying messaging protocol should be done in the bridge adaptor.
*/
contract ChildERC20Bridge is
Ownable2Step,
Initializable,
AccessControlUpgradeable, // AccessControlUpgradeable inherits Initializable
IChildERC20BridgeErrors,
IChildERC20Bridge,
IChildERC20BridgeEvents
Expand All @@ -36,6 +34,14 @@ contract ChildERC20Bridge is
/// @dev leave this as the first param for the integration tests
mapping(address => address) public rootTokenToChildToken;

/**
* ROLES
*/
bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE");
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see these same roles are also defined in RootERC20Bridge.sol. Possibly worth moving to another contract for DRY, consistency, less error-prone and for prosperity reasons when we support bridging of other assets?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, not just this. The root and child bridge share a lot of common constants, errors, etc, so it would be nice to create an issue and do that all in a separate PR.

bytes32 public constant UNPAUSER_ROLE = keccak256("UNPAUSER_ROLE");
bytes32 public constant VARIABLE_MANAGER_ROLE = keccak256("VARIABLE_MANAGER_ROLE");
bytes32 public constant ADAPTOR_MANAGER_ROLE = keccak256("ADAPTOR_MANAGER_ROLE");

bytes32 public constant MAP_TOKEN_SIG = keccak256("MAP_TOKEN");
bytes32 public constant DEPOSIT_SIG = keccak256("DEPOSIT");
bytes32 public constant WITHDRAW_SIG = keccak256("WITHDRAW");
Expand All @@ -56,7 +62,8 @@ contract ChildERC20Bridge is
address public childETHToken;

/**
* @notice Initilization function for RootERC20Bridge.
* @notice Initialization function for ChildERC20Bridge.
* @param newRoles Struct containing addresses of roles.
* @param newBridgeAdaptor Address of StateSender to send deposit information to.
* @param newRootERC20BridgeAdaptor Stringified address of root ERC20 bridge adaptor to communicate with.
* @param newChildTokenTemplate Address of child token template to clone.
Expand All @@ -65,13 +72,18 @@ contract ChildERC20Bridge is
* @dev Can only be called once.
*/
function initialize(
InitializationRoles memory newRoles,
address newBridgeAdaptor,
string memory newRootERC20BridgeAdaptor,
address newChildTokenTemplate,
string memory newRootChain,
address newRootIMXToken
) public initializer {
if (newBridgeAdaptor == address(0) || newChildTokenTemplate == address(0) || newRootIMXToken == address(0)) {
if (
newBridgeAdaptor == address(0) || newChildTokenTemplate == address(0) || newRootIMXToken == address(0)
|| newRoles.defaultAdmin == address(0) || newRoles.pauser == address(0) || newRoles.unpauser == address(0)
|| newRoles.variableManager == address(0) || newRoles.adaptorManager == address(0)
) {
revert ZeroAddress();
}

Expand All @@ -83,6 +95,14 @@ contract ChildERC20Bridge is
revert InvalidRootChain();
}

__AccessControl_init();

_grantRole(DEFAULT_ADMIN_ROLE, newRoles.defaultAdmin);
_grantRole(PAUSER_ROLE, newRoles.pauser);
_grantRole(UNPAUSER_ROLE, newRoles.unpauser);
_grantRole(VARIABLE_MANAGER_ROLE, newRoles.variableManager);
_grantRole(ADAPTOR_MANAGER_ROLE, newRoles.adaptorManager);

Copy link
Contributor

@rzmahmood rzmahmood Nov 8, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Best practice to call initializer of inherited contracts, i.e.

__AccessControl_init()

In this case its empty, so not critical but its good to get the habit

rootERC20BridgeAdaptor = newRootERC20BridgeAdaptor;
childTokenTemplate = newChildTokenTemplate;
bridgeAdaptor = IChildERC20BridgeAdaptor(newBridgeAdaptor);
Expand Down Expand Up @@ -281,7 +301,13 @@ contract ChildERC20Bridge is
}
}

function updateBridgeAdaptor(address newBridgeAdaptor) external override onlyOwner {
/**
* @inheritdoc IChildERC20Bridge
*/
function updateBridgeAdaptor(address newBridgeAdaptor) external override {
if (!(hasRole(ADAPTOR_MANAGER_ROLE, msg.sender))) {
revert NotVariableManager(msg.sender);
}
if (newBridgeAdaptor == address(0)) {
revert ZeroAddress();
}
Expand Down
2 changes: 1 addition & 1 deletion src/child/WIMX.sol
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: GPL-3.0
pragma solidity ^0.8.21;
pragma solidity 0.8.19;

import {IWIMX} from "../interfaces/child/IWIMX.sol";
import {Address} from "@openzeppelin/contracts/utils/Address.sol";
Expand Down
2 changes: 1 addition & 1 deletion src/interfaces/child/IChildAxelarBridgeAdaptor.sol
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: Apache 2.0
pragma solidity ^0.8.21;
pragma solidity 0.8.19;

interface IChildAxelarBridgeAdaptorErrors {
/// @notice Error when a zero address is given when not valid.
Expand Down
Loading