Skip to content

Commit

Permalink
feat: create2 gatewayevm deployment and upgrade poc (#282)
Browse files Browse the repository at this point in the history
  • Loading branch information
skosito authored Aug 6, 2024
1 parent 94516b3 commit 8389089
Show file tree
Hide file tree
Showing 3 changed files with 114 additions and 0 deletions.
63 changes: 63 additions & 0 deletions v2/scripts/deploy/deterministic/DeployGatewayEVM.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.26;

import "forge-std/Script.sol";
import "src/evm/GatewayEVM.sol";
import "test/utils/TestERC20.sol";
import { ERC1967Proxy } from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";

contract DeployGatewayEVMCreate2 is Script {
function run() external {
// TODO (https://github.com/zeta-chain/protocol-contracts/issues/251): should be passed as arg
string memory mnemonic = "test test test test test test test test test test test junk";
uint256 privateKey = vm.deriveKey(mnemonic, 0);
address deployer = vm.rememberKey(privateKey);

// TODO (https://github.com/zeta-chain/protocol-contracts/issues/251): should be passed as arg
address payable tss = payable(vm.envOr("TSS_ADDRESS", address(0x123)));
address admin = vm.envOr("ADMIN_ADDRESS", deployer);

address expectedImplAddress;
address expectedProxyAddress;

bytes32 implSalt = bytes32(uint256(10));
bytes32 proxySalt = bytes32(uint256(11));

vm.startBroadcast(deployer);

// TODO (https://github.com/zeta-chain/protocol-contracts/issues/251): should be passed as arg
TestERC20 zeta = new TestERC20("zeta", "ZETA");

expectedImplAddress = computeCreate2Address(
implSalt,
hashInitCode(type(GatewayEVM).creationCode)
);

GatewayEVM gatewayImpl = new GatewayEVM{salt: implSalt}();
require(expectedImplAddress == address(gatewayImpl), "impl address doesn't match expected address");

expectedProxyAddress = vm.computeCreate2Address(
proxySalt,
hashInitCode(
type(ERC1967Proxy).creationCode,
abi.encode(
address(gatewayImpl),
abi.encodeWithSelector(GatewayEVM.initialize.selector, tss, address(zeta), admin)
)
)
);

ERC1967Proxy gatewayProxy = new ERC1967Proxy{salt: proxySalt}(
address(gatewayImpl),
abi.encodeWithSelector(GatewayEVM.initialize.selector, tss, address(zeta), admin)
);

require(expectedProxyAddress == address(gatewayProxy), "proxy address doesn't match expected address");

GatewayEVM gateway = GatewayEVM(address(gatewayProxy));
require(gateway.tssAddress() == tss, "tss not set");
require(gateway.zetaToken() == address(zeta), "zeta token not set");

vm.stopBroadcast();
}
}
34 changes: 34 additions & 0 deletions v2/scripts/deploy/deterministic/UpgradeGatewayEVM.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.26;

import "forge-std/Script.sol";
import "src/evm/GatewayEVM.sol";
import "test/utils/GatewayEVMUpgradeTest.sol";
import "test/utils/TestERC20.sol";
import { ERC1967Proxy } from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";
import { Upgrades } from "openzeppelin-foundry-upgrades/Upgrades.sol";

contract UpgradeGatewayEVM is Script {
function run() external {
// TODO (https://github.com/zeta-chain/protocol-contracts/issues/251): should be passed as arg
string memory mnemonic = "test test test test test test test test test test test junk";
uint256 privateKey = vm.deriveKey(mnemonic, 0);
address deployer = vm.rememberKey(privateKey);

// TODO (https://github.com/zeta-chain/protocol-contracts/issues/251): should be passed as arg
address proxy = vm.envOr("PROXY_ADDRESS", address(0xA7806c719bd377F15bA6CaDf2F94Afb7FfA66256));

GatewayEVM prevImpl = GatewayEVM(proxy);

vm.startBroadcast(deployer);

Upgrades.upgradeProxy(proxy, "GatewayEVMUpgradeTest.sol", "");

GatewayEVM newImpl = GatewayEVM(proxy);

require(prevImpl.tssAddress() == newImpl.tssAddress(), "tss addr changed");
require(prevImpl.zetaToken() == newImpl.zetaToken(), "zeta token addr changed");

vm.stopBroadcast();
}
}
17 changes: 17 additions & 0 deletions v2/scripts/deploy/deterministic/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
## Deterministic GatewayEVM deployments

`DeployGatewayEVMCreate2` script uses create2 with Foundry (https://book.getfoundry.sh/tutorials/create2-tutorial) to perform deterministic deployment of `GatewayEVM` contracts.
This ensures that on every EVM chain `GatewayEVM` contract will be on same address.

Since UUPS proxy is used for `GatewayEVM` contract, both implementation and `ERC1967Proxy` are deployed using above technique:

- calculate expected address
- adding a salt to deployment
- basic assertions to verify that deployed address is same as expected

`UpgradeGatewayEVM` script uses OpenZeppelin's Foundry Upgrades plugin (https://github.com/OpenZeppelin/openzeppelin-foundry-upgrades), to upgrade `GatewayEVM`:

- deploy new implementation (doesn't need to be deterministic since proxy address doesn't change)
- use plugin to upgrade proxy


0 comments on commit 8389089

Please sign in to comment.