Skip to content

Commit

Permalink
All contracts behind proxies
Browse files Browse the repository at this point in the history
  • Loading branch information
Benjimmutable committed Oct 31, 2023
1 parent 59a4140 commit ba6b401
Show file tree
Hide file tree
Showing 13 changed files with 177 additions and 112 deletions.
2 changes: 1 addition & 1 deletion axelar-local-dev/chain-config/local.json
Original file line number Diff line number Diff line change
Expand Up @@ -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": [
Expand Down
2 changes: 1 addition & 1 deletion axelar-local-dev/chain-config/local.template.json
Original file line number Diff line number Diff line change
Expand Up @@ -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": [
Expand Down
47 changes: 30 additions & 17 deletions deploy.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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

Expand Down
17 changes: 8 additions & 9 deletions script/DeployChildContracts.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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),
""
);
Expand All @@ -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),
Expand All @@ -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));
Expand Down
38 changes: 27 additions & 11 deletions script/DeployRootContracts.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand All @@ -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");

/**
Expand All @@ -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")) {
Expand All @@ -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));
}
}
3 changes: 0 additions & 3 deletions script/InitializeChildContracts.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,5 @@ contract InitializeChildContracts is Script {
childAxelarBridgeAdaptor.initialize(address(childERC20Bridge));

vm.stopBroadcast();

console2.log("DINGDING");
console2.log(childAxelarBridgeAdaptor.rootBridgeAdaptor());
}
}
78 changes: 57 additions & 21 deletions script/InitializeRootContracts.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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());
}
}
10 changes: 10 additions & 0 deletions src/child/ChildAxelarBridgeAdaptor.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
Loading

0 comments on commit ba6b401

Please sign in to comment.