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

feat: v2 evm contracts deploy scripts #293

Merged
merged 66 commits into from
Aug 7, 2024
Merged
Show file tree
Hide file tree
Changes from 65 commits
Commits
Show all changes
66 commits
Select commit Hold shift + click to select a range
5b5cc4b
access control for erc20 custody new
skosito Jul 23, 2024
f1cf789
cleanup erc20 custody new events and errors
skosito Jul 23, 2024
8b9669e
access control for gateway evm
skosito Jul 23, 2024
1851b89
move connector events to interface
skosito Jul 23, 2024
ba0f25f
add tss address to connector and fix uniswap integration test
skosito Jul 23, 2024
3f4990c
tests for tss sender in connector
skosito Jul 23, 2024
a686f66
remove access control todos from zevm contracts
skosito Jul 23, 2024
58160e8
generate
skosito Jul 23, 2024
0f8ab79
missing access control
skosito Jul 23, 2024
72e1200
init v2 folder
skosito Jul 24, 2024
8fafcbd
use npm
skosito Jul 24, 2024
99aaebb
moving files
skosito Jul 24, 2024
8e5b78f
moving files
skosito Jul 24, 2024
2964b06
move upgrade test
skosito Jul 24, 2024
3eac2ca
connector tests
skosito Jul 24, 2024
c0dbd8c
wip
skosito Jul 24, 2024
394e7c5
forge fmt
skosito Jul 24, 2024
09be45c
move echidna
skosito Jul 24, 2024
6672b9e
using submodule for forge-std
skosito Jul 24, 2024
2ea0a59
forge install: openzeppelin-contracts-upgradeable
skosito Jul 24, 2024
a8ec2b1
use submodules
skosito Jul 24, 2024
3a57e9d
move existing to v1 folder
skosito Jul 26, 2024
a3bf3f2
Merge branch 'main' into v1-v2-split
skosito Jul 29, 2024
731aa1e
yarn generate for v1
skosito Jul 29, 2024
3d6a870
cleanup
skosito Jul 29, 2024
3d736e5
conflicts
skosito Jul 29, 2024
0ec2a72
try to fix build action
skosito Jul 29, 2024
b334516
fixing v1 actions
skosito Jul 29, 2024
307a455
fix test v1
skosito Jul 29, 2024
d00c832
add paths to v1 actions
skosito Jul 29, 2024
b8db384
forge fmt
skosito Jul 29, 2024
56ef158
add test v2 and cleanup v1 actions
skosito Jul 29, 2024
9a7dd16
fix
skosito Jul 29, 2024
28af3e6
fix
skosito Jul 29, 2024
dd4cbeb
remove build v1 action and rename test actions steps
skosito Jul 29, 2024
2a01ed1
feat: port localnet to v2 (#269)
skosito Jul 29, 2024
4c013a2
readme and test fixes
skosito Jul 29, 2024
f401c98
lint v2
skosito Jul 29, 2024
8af5d05
enable coverage and slither on v2
skosito Jul 29, 2024
545201b
remove broadcast folder
skosito Jul 29, 2024
5231707
fix PR comments
skosito Jul 30, 2024
f4c1c7d
merge main
skosito Jul 30, 2024
640e67d
refactor: v2 bindings (#270)
skosito Jul 30, 2024
6835971
refactor: remove new suffix from v2 contracts (#272)
skosito Jul 31, 2024
5f2ea3c
feat: add missing access control (#277)
skosito Aug 1, 2024
ad2f4d9
modify zrc20
skosito Aug 1, 2024
a7897cd
generate
skosito Aug 1, 2024
48bf0de
add unit tests for zrc20
skosito Aug 1, 2024
b5a5576
generate
skosito Aug 1, 2024
a06e946
generate
skosito Aug 1, 2024
5a3892e
PR comment
skosito Aug 2, 2024
38081fb
Merge branch 'main' into zrc-20-fixes
skosito Aug 2, 2024
ca92f50
generate
skosito Aug 2, 2024
a1ec678
add poc for create2 gatewayevm deployment
skosito Aug 2, 2024
acc628e
renaming
skosito Aug 2, 2024
5b84119
add script to test upgrade
skosito Aug 2, 2024
98e0483
Merge branch 'main' into createx-poc
skosito Aug 5, 2024
a5d2ac4
PR comments
skosito Aug 5, 2024
f9ef655
add issue to todos
skosito Aug 5, 2024
19cc73b
Merge branch 'main' into createx-poc
skosito Aug 6, 2024
4808595
add scripts to deploy evm protocol contracts
skosito Aug 6, 2024
85a9acd
Merge branch 'main' into evm-deploy-scripts
skosito Aug 6, 2024
47cb6b5
update readme
skosito Aug 6, 2024
0e0a18a
update gitignore for broadcast
skosito Aug 6, 2024
c84d4d7
fix comments
skosito Aug 6, 2024
0e192af
pr comments
skosito Aug 7, 2024
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
2 changes: 1 addition & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -37,4 +37,4 @@ crytic-export

out
cache_forge
broadcast
v2/broadcast/*/31337
8 changes: 8 additions & 0 deletions v2/.env.sample
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# This is sample on how .env should look like. Values given here are illustration and are expected if run with anvil locally and first private key.
# evm
TSS_ADDRESS=0x70997970C51812dc3A010C7d01b50e0d17dc79C8
GATEWAY_ADMIN_ADDRESS_EVM=0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266
ERC20_CUSTODY_ADMIN_ADDRESS_EVM=0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266
ZETA_CONNECTOR_ADMIN_ADDRESS_EVM=0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266
GATEWAY_PROXY_EVM=0x9f21B726FCb84D8e92cdC678772590dce5347D0B
ZETA_ERC20_EVM=0x42928581Ba60cD97B65D873151dc063F3D0619f8
28 changes: 28 additions & 0 deletions v2/scripts/deploy/deterministic/DeployERC20Custody.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.26;

import "forge-std/Script.sol";
import "src/evm/ERC20Custody.sol";

contract DeployERC20Custody is Script {
function run() external {
address payable tss = payable(vm.envAddress("TSS_ADDRESS"));
address admin = vm.envAddress("ERC20_CUSTODY_ADMIN_ADDRESS_EVM");
address gateway = vm.envAddress("GATEWAY_PROXY_EVM");

bytes32 salt = keccak256("ERC20Custody");
fbac marked this conversation as resolved.
Show resolved Hide resolved

vm.startBroadcast();

ERC20Custody custody = new ERC20Custody{salt: salt}(gateway, tss, admin);
skosito marked this conversation as resolved.
Show resolved Hide resolved

address expectedAddr = vm.computeCreate2Address(
salt,
hashInitCode(type(ERC20Custody).creationCode, abi.encode(gateway, tss, admin))
);

require(expectedAddr == address(custody), "erc20 custody address doesn't match expected address");

vm.stopBroadcast();
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Consider adding error handling and logging.

Adding error handling and logging can help in debugging and monitoring the deployment process.

function run() external {
    address payable tss = payable(vm.envAddress("TSS_ADDRESS"));
    address admin = vm.envAddress("ERC20_CUSTODY_ADMIN_ADDRESS_EVM");
    address gateway = vm.envAddress("GATEWAY_PROXY_EVM");

    bytes32 salt = keccak256("ERC20Custody");

    vm.startBroadcast();

    ERC20Custody custody;
    try new ERC20Custody{salt: salt}(gateway, tss, admin) returns (ERC20Custody _custody) {
        custody = _custody;
    } catch {
        revert("Failed to deploy ERC20Custody contract");
    }

    address expectedAddr = vm.computeCreate2Address(
        salt,
        hashInitCode(type(ERC20Custody).creationCode, abi.encode(gateway, tss, admin))
    );

    require(expectedAddr == address(custody), "erc20 custody address doesn't match expected address");

    vm.stopBroadcast();
}
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
address payable tss = payable(vm.envAddress("TSS_ADDRESS"));
address admin = vm.envAddress("ERC20_CUSTODY_ADMIN_ADDRESS_EVM");
address gateway = vm.envAddress("GATEWAY_PROXY_EVM");
bytes32 salt = keccak256("ERC20Custody");
vm.startBroadcast();
ERC20Custody custody = new ERC20Custody{salt: salt}(gateway, tss, admin);
address expectedAddr = vm.computeCreate2Address(
salt,
hashInitCode(type(ERC20Custody).creationCode, abi.encode(gateway, tss, admin))
);
require(expectedAddr == address(custody), "erc20 custody address doesn't match expected address");
vm.stopBroadcast();
}
address payable tss = payable(vm.envAddress("TSS_ADDRESS"));
address admin = vm.envAddress("ERC20_CUSTODY_ADMIN_ADDRESS_EVM");
address gateway = vm.envAddress("GATEWAY_PROXY_EVM");
bytes32 salt = keccak256("ERC20Custody");
vm.startBroadcast();
ERC20Custody custody;
try new ERC20Custody{salt: salt}(gateway, tss, admin) returns (ERC20Custody _custody) {
custody = _custody;
} catch {
revert("Failed to deploy ERC20Custody contract");
}
address expectedAddr = vm.computeCreate2Address(
salt,
hashInitCode(type(ERC20Custody).creationCode, abi.encode(gateway, tss, admin))
);
require(expectedAddr == address(custody), "erc20 custody address doesn't match expected address");
vm.stopBroadcast();

}
24 changes: 8 additions & 16 deletions v2/scripts/deploy/deterministic/DeployGatewayEVM.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,29 +6,21 @@ import "src/evm/GatewayEVM.sol";
import "test/utils/TestERC20.sol";
import { ERC1967Proxy } from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol";

contract DeployGatewayEVMCreate2 is Script {
contract DeployGatewayEVM 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 payable tss = payable(vm.envAddress("TSS_ADDRESS"));
address admin = vm.envAddress("GATEWAY_ADMIN_ADDRESS_EVM");
address zeta = vm.envAddress("ZETA_ERC20_EVM");

address expectedImplAddress;
address expectedProxyAddress;

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

vm.startBroadcast(deployer);
bytes32 implSalt = keccak256("GatewayEVM");
bytes32 proxySalt = keccak256("GatewayEVMProxy");

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

expectedImplAddress = computeCreate2Address(
expectedImplAddress = vm.computeCreate2Address(
implSalt,
hashInitCode(type(GatewayEVM).creationCode)
);
Expand Down
25 changes: 25 additions & 0 deletions v2/scripts/deploy/deterministic/DeployTestERC20.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.26;

import "forge-std/Script.sol";
import "test/utils/TestERC20.sol";

// This is just to deploy test erc20 tokens for testing deployments
contract DeployTestERC20 is Script {
function run() external {
bytes32 erc20Salt = keccak256("TestERC20");

vm.startBroadcast();

TestERC20 zeta = new TestERC20{salt: erc20Salt}("zeta", "ZETA");
skosito marked this conversation as resolved.
Show resolved Hide resolved

address expectedAddr = vm.computeCreate2Address(
erc20Salt,
hashInitCode(type(TestERC20).creationCode, abi.encode("zeta", "ZETA"))
);

require(expectedAddr == address(zeta), "zeta address doesn't match expected address");

vm.stopBroadcast();
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Consider adding error handling and logging.

Adding error handling and logging can help in debugging and monitoring the deployment process.

function run() external {
    bytes32 erc20Salt = keccak256("TestERC20");

    vm.startBroadcast();

    TestERC20 zeta;
    try new TestERC20{salt: erc20Salt}("zeta", "ZETA") returns (TestERC20 _zeta) {
        zeta = _zeta;
    } catch {
        revert("Failed to deploy TestERC20 contract");
    }

    address expectedAddr = vm.computeCreate2Address(
        erc20Salt,
        hashInitCode(type(TestERC20).creationCode, abi.encode("zeta", "ZETA"))
    );

    require(expectedAddr == address(zeta), "zeta address doesn't match expected address");

    vm.stopBroadcast();
}
Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
function run() external {
bytes32 erc20Salt = keccak256("TestERC20");
vm.startBroadcast();
TestERC20 zeta = new TestERC20{salt: erc20Salt}("zeta", "ZETA");
address expectedAddr = vm.computeCreate2Address(
erc20Salt,
hashInitCode(type(TestERC20).creationCode, abi.encode("zeta", "ZETA"))
);
require(expectedAddr == address(zeta), "zeta address doesn't match expected address");
vm.stopBroadcast();
}
function run() external {
bytes32 erc20Salt = keccak256("TestERC20");
vm.startBroadcast();
TestERC20 zeta;
try new TestERC20{salt: erc20Salt}("zeta", "ZETA") returns (TestERC20 _zeta) {
zeta = _zeta;
} catch {
revert("Failed to deploy TestERC20 contract");
}
address expectedAddr = vm.computeCreate2Address(
erc20Salt,
hashInitCode(type(TestERC20).creationCode, abi.encode("zeta", "ZETA"))
);
require(expectedAddr == address(zeta), "zeta address doesn't match expected address");
vm.stopBroadcast();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.26;

import "forge-std/Script.sol";
import "src/evm/ZetaConnectorNonNative.sol";

contract DeployZetaConnectorNonNative is Script {
function run() external {
address payable tss = payable(vm.envAddress("TSS_ADDRESS"));
address admin = vm.envAddress("ZETA_CONNECTOR_ADMIN_ADDRESS_EVM");
address gateway = vm.envAddress("GATEWAY_PROXY_EVM");
address zeta = vm.envAddress("ZETA_ERC20_EVM");

bytes32 salt = keccak256("ZetaConnectorNonNative");

vm.startBroadcast();

ZetaConnectorNonNative connector = new ZetaConnectorNonNative{salt: salt}(gateway, zeta, tss, admin);
skosito marked this conversation as resolved.
Show resolved Hide resolved

address expectedAddr = vm.computeCreate2Address(
salt,
hashInitCode(type(ZetaConnectorNonNative).creationCode, abi.encode(gateway, zeta, tss, admin))
);

require(expectedAddr == address(connector), "zeta connector non native address doesn't match expected address");

vm.stopBroadcast();
}
}
8 changes: 1 addition & 7 deletions v2/scripts/deploy/deterministic/UpgradeGatewayEVM.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,7 @@ 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));
address proxy = vm.envAddress("GATEWAY_EVM_PROXY");

GatewayEVM prevImpl = GatewayEVM(proxy);

Expand Down
13 changes: 11 additions & 2 deletions v2/scripts/deploy/deterministic/readme.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
## Deterministic GatewayEVM deployments
## Deterministic deployments

`DeployGatewayEVMCreate2` script uses create2 with Foundry (https://book.getfoundry.sh/tutorials/create2-tutorial) to perform deterministic deployment of `GatewayEVM` contracts.
Note: `.env` file should be set up and updated during deployments according to expected env variables in scripts, check `.env.sample` for example on how it should look like.
Currently, `.env.sample` is set with test env variables that can be used to test scripts locally with `anvil` using first account private key.

`DeployGatewayEVM` 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:
Expand All @@ -9,9 +12,15 @@ Since UUPS proxy is used for `GatewayEVM` contract, both implementation and `ERC
- adding a salt to deployment
- basic assertions to verify that deployed address is same as expected

Remaining deployment script work in similar way as `GatewayEVM` but much simpler because there is no proxy.

`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

To execute deployment script, following format is needed:

```
forge script scripts/deploy/deterministic/<Script>.s.sol --rpc-url <RPC_URL> --private-key <PRIVATE_KEY> --broadcast
```
Loading