From 0d05a3ce35a802ac879a6d0e756630f8b5e97e94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20N=C3=BA=C3=B1ez?= Date: Tue, 25 Jul 2023 13:40:51 +0200 Subject: [PATCH 1/8] FxBaseChildTunnel can't emit events on _processMessageFromRoot callback See https://github.com/0xPolygon/fx-portal/blob/296ac8d41579f98d3a4dfb6d41737fae272a30ba/contracts/tunnel/FxBaseChildTunnel.sol#L58 --- contracts/xchain/PolygonChild.sol | 3 --- 1 file changed, 3 deletions(-) diff --git a/contracts/xchain/PolygonChild.sol b/contracts/xchain/PolygonChild.sol index 53415186..0a0fa040 100644 --- a/contracts/xchain/PolygonChild.sol +++ b/contracts/xchain/PolygonChild.sol @@ -5,8 +5,6 @@ import "@fx-portal/contracts/tunnel/FxBaseChildTunnel.sol"; import "@openzeppelin/contracts/access/Ownable.sol"; contract PolygonChild is FxBaseChildTunnel, Ownable { - event MessageReceived(address indexed sender, bytes data); - address public stakeInfoAddress; constructor(address _fxChild) FxBaseChildTunnel(_fxChild) {} @@ -16,7 +14,6 @@ contract PolygonChild is FxBaseChildTunnel, Ownable { address sender, bytes memory data ) internal override validateSender(sender) { - emit MessageReceived(sender, data); // solhint-disable-next-line avoid-low-level-calls stakeInfoAddress.call(data); } From 38870ed8c946864b6bc6eea27310301baa434c3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20N=C3=BA=C3=B1ez?= Date: Tue, 25 Jul 2023 16:29:58 +0200 Subject: [PATCH 2/8] FxPortal Deployment info: FxRoot, FxChild, CheckpointManager For both Ethereum Mainnet - Polygon Mainnet and Ethereum Goerli - Polygon Mumbai. See https://wiki.polygon.technology/docs/pos/design/bridge/l1-l2-communication/state-transfer/#prerequisites --- ape-config.yaml | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/ape-config.yaml b/ape-config.yaml index 9727fd79..985f129d 100644 --- a/ape-config.yaml +++ b/ape-config.yaml @@ -36,12 +36,15 @@ deployments: mainnet: - contract_type: DAI address: '0x8f3Cf7ad23Cd3CaDbD9735AFf958023239c6A063' + - contract_type: fx_child + address: '0x8397259c983751DAf40400790063935a11afa28a' mumbai: - contract_type: DAI address: '0x001B3B4d0F3714Ca98ba10F6042DaEbF0B1B7b6F' - contract_type: StakeInfo address: '0xC1379866Fb0c100DCBFAb7b470009C4827D47DD8' - - fx_child: '0xCf73231F28B7331BBe3124B907840A94851f9f11' + - contract_type: fx_child + address: '0xCf73231F28B7331BBe3124B907840A94851f9f11' - verify: False ethereum: local: @@ -83,6 +86,10 @@ deployments: max_dkg_size: 8 pre_application: '0x685b8Fd02aB87d8FfFff7346cB101A5cE4185bf3' verify: True + - contract_type: fx_root + address: '0x3d1d3E34f7fB6D26245E6640E1c50710eFFf15bA' + - contract_type: checkpoint_manager + address: '0x2890bA17EfE978480615e330ecB65333b880928e' mumbai: - stake_info_contract: '0xC1379866Fb0c100DCBFAb7b470009C4827D47DD8' max_dkg_size: 16 @@ -98,6 +105,10 @@ deployments: pre_min_authorization: 40000000000000000000000 pre_min_operator_seconds: 86400 # one day in seconds verify: True + - contract_type: fx_root + address: '0xfe5e5D361b2ad62c541bAb87C45a0B9B018389a2' + - contract_type: checkpoint_manager + address: '0x86e4dc95c7fbdbf52e33d563bbdb00823894c287' test: From e54455beeb830840d1c4acc3a4024a8adff2a054 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20N=C3=BA=C3=B1ez?= Date: Tue, 25 Jul 2023 16:33:59 +0200 Subject: [PATCH 3/8] Set FxChildTunnel on PolygonRoot constructor Instead of setting the child tunnel with setFxChildTunnel(), which could be prone to front-running. --- contracts/xchain/PolygonRoot.sol | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/contracts/xchain/PolygonRoot.sol b/contracts/xchain/PolygonRoot.sol index 71def5e6..7c393e76 100644 --- a/contracts/xchain/PolygonRoot.sol +++ b/contracts/xchain/PolygonRoot.sol @@ -11,10 +11,12 @@ contract PolygonRoot is FxBaseRootTunnel, IUpdatableStakeInfo { constructor( address _checkpointManager, address _fxRoot, - address _source + address _source, + address _fxChildTunnel ) FxBaseRootTunnel(_checkpointManager, _fxRoot) { require(_source != address(0), "Wrong input parameters"); source = _source; + fxChildTunnel = _fxChildTunnel; } /** From f2953e716e94a32cdb76ba291f400df3fe666f70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20N=C3=BA=C3=B1ez?= Date: Tue, 25 Jul 2023 16:35:48 +0200 Subject: [PATCH 4/8] Grant DEFAULT_ADMIN_ROLE on StakeInfo to the deployer This way they can grant/revoke updaters, which is useful for testnets, and the admin can revoke themselves if the updaters list is considered final. --- contracts/contracts/coordination/StakeInfo.sol | 1 + 1 file changed, 1 insertion(+) diff --git a/contracts/contracts/coordination/StakeInfo.sol b/contracts/contracts/coordination/StakeInfo.sol index 250f3895..b4872f1a 100644 --- a/contracts/contracts/coordination/StakeInfo.sol +++ b/contracts/contracts/coordination/StakeInfo.sol @@ -20,6 +20,7 @@ contract StakeInfo is AccessControl, IUpdatableStakeInfo, IAccessControlApplicat } constructor(address[] memory updaters) { + _grantRole(DEFAULT_ADMIN_ROLE, msg.sender); for (uint256 i = 0; i < updaters.length; i++) { _grantRole(UPDATE_ROLE, updaters[i]); } From 9551852c0b4f03f295dabf64ff75696d0ed3888f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20N=C3=BA=C3=B1ez?= Date: Tue, 25 Jul 2023 17:09:36 +0200 Subject: [PATCH 5/8] Adapt xchain deployment script to new changes --- scripts/deploy_xchain_test.py | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/scripts/deploy_xchain_test.py b/scripts/deploy_xchain_test.py index 06cc59b8..83521571 100644 --- a/scripts/deploy_xchain_test.py +++ b/scripts/deploy_xchain_test.py @@ -1,15 +1,16 @@ from ape import accounts, config, networks, project -def deploy_eth_contracts(deployer): +def deploy_eth_contracts(deployer, source, child_address): # Connect to the Ethereum network with networks.ethereum.goerli.use_provider("infura"): DEPLOYMENTS_CONFIG = config.get_config("deployments")["ethereum"]["goerli"][0] - # Deploy the FxStateRootTunnel contract polygon_root = project.PolygonRoot.deploy( DEPLOYMENTS_CONFIG.get("checkpoint_manager"), DEPLOYMENTS_CONFIG.get("fx_root"), + source, + child_address, sender=deployer, publish=DEPLOYMENTS_CONFIG.get("verify"), ) @@ -22,32 +23,29 @@ def deploy_polygon_contracts(deployer): with networks.polygon.mumbai.use_provider("infura"): DEPLOYMENTS_CONFIG = config.get_config("deployments")["polygon"]["mumbai"][0] - # Deploy the FxStateChildTunnel contract - polygon_child = project.PolygonChild.deploy( - DEPLOYMENTS_CONFIG.get("fx_child"), + stake_info = project.StakeInfo.deploy( + [deployer.address, polygon_child.address], sender=deployer, publish=DEPLOYMENTS_CONFIG.get("verify"), ) - stake_info = project.StakeInfo.deploy( - [deployer.address, polygon_child.address], + + polygon_child = project.PolygonChild.deploy( + DEPLOYMENTS_CONFIG.get("fx_child"), + stake_info.address, sender=deployer, publish=DEPLOYMENTS_CONFIG.get("verify"), ) - return polygon_child, stake_info + return polygon_child, stake_info -def main(account_id=None): +# TODO: Figure out better way to retrieve the TACo app contract address +def main(taco_app, account_id=None): deployer = accounts.load("TGoerli") with accounts.use_sender(deployer): - root = deploy_eth_contracts(deployer) - child, stake_info = deploy_polygon_contracts(deployer) + child, _ = deploy_polygon_contracts(deployer) + root = deploy_eth_contracts(deployer, child.address, taco_app) # Set the root contract address in the child contract with networks.polygon.mumbai.use_provider("infura"): child.setFxRootTunnel(root.address) - child.setStakeInfoAddress(stake_info.address) - - # Set the child contract address in the root contract - with networks.ethereum.goerli.use_provider("infura"): - root.setFxChildTunnel(child.address) From ff108c7bf7f8a1409ee2348f2fdcc788dbd330f4 Mon Sep 17 00:00:00 2001 From: James Campbell Date: Tue, 1 Aug 2023 18:18:22 +0200 Subject: [PATCH 6/8] Improve logging of check_xchain script --- scripts/check_xchain.py | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/scripts/check_xchain.py b/scripts/check_xchain.py index 0b1ea5a3..06124cd1 100644 --- a/scripts/check_xchain.py +++ b/scripts/check_xchain.py @@ -1,20 +1,30 @@ import time -from ape import networks, project +from ape import accounts, networks, project def main(): + deployer = accounts.load("TGoerli") print("*******") print("WARNING: This script will take 40 mins to run to allow messages to sync from L1 to L2") print("*******") with networks.ethereum.goerli.use_provider("infura"): - root = project.PolygonRoot.at("0xdc90A337DF9561705EB85B92391ab8F55d114D53") + root = project.PolygonRoot.at("0x55D1E362b81FDC6BaA359630bf3Ffa5900F66777") root.updateOperator( "0x3B42d26E19FF860bC4dEbB920DD8caA53F93c600", "0x3B42d26E19FF860bC4dEbB920DD8caA53F93c600", + sender=deployer, ) - time.sleep(60 * 40) - with networks.polygon.mumbai.use_provider("infura"): - stake_info = project.StakeInfo.at("0x40D0107ACa3503CB345E4117a9F92E8220EEEb3C") - print(stake_info.operatorToProvider("0xAe87D865F3A507185656aD0ef52a8E0B9f3d58f8")) - print(stake_info.operatorToProvider("0x3B42d26E19FF860bC4dEbB920DD8caA53F93c600")) + # check every 5 minutes + print("Now: {}".format(time.time())) + for i in range(12): + time.sleep(60 * i * 5) + print("Now: {}".format(time.time())) + with networks.polygon.mumbai.use_provider("infura"): + stake_info = project.StakeInfo.at("0x96e7dBa88f79e5CCAEBf0c7678539F6C0d719c99") + print( + stake_info.stakingProviderFromOperator("0xAe87D865F3A507185656aD0ef52a8E0B9f3d58f8") + ) + print( + stake_info.stakingProviderFromOperator("0x3B42d26E19FF860bC4dEbB920DD8caA53F93c600") + ) From 1dfe46f162e7d3c5ce0ee3c1e76dda56a7c798d6 Mon Sep 17 00:00:00 2001 From: James Campbell Date: Tue, 1 Aug 2023 18:18:43 +0200 Subject: [PATCH 7/8] Fix bugs and improve config handling for deploying xchain scripts --- scripts/deploy_xchain_test.py | 79 +++++++++++++++++++++++++---------- 1 file changed, 57 insertions(+), 22 deletions(-) diff --git a/scripts/deploy_xchain_test.py b/scripts/deploy_xchain_test.py index 83521571..610b5b1a 100644 --- a/scripts/deploy_xchain_test.py +++ b/scripts/deploy_xchain_test.py @@ -1,51 +1,86 @@ +import click from ape import accounts, config, networks, project +from ape.cli import NetworkBoundCommand, account_option -def deploy_eth_contracts(deployer, source, child_address): - # Connect to the Ethereum network - with networks.ethereum.goerli.use_provider("infura"): - DEPLOYMENTS_CONFIG = config.get_config("deployments")["ethereum"]["goerli"][0] +def convert_config(config): + result = {} + for item in config: + if "contract_type" in item: + result[item["contract_type"]] = item["address"] + else: + result.update(item) + return result + +def deploy_eth_contracts(deployer, source, child_address, config, eth_network): + # Connect to the Ethereum network + with eth_network.use_provider("infura"): polygon_root = project.PolygonRoot.deploy( - DEPLOYMENTS_CONFIG.get("checkpoint_manager"), - DEPLOYMENTS_CONFIG.get("fx_root"), + config["checkpoint_manager"], + config["fx_root"], source, child_address, sender=deployer, - publish=DEPLOYMENTS_CONFIG.get("verify"), + publish=False, ) return polygon_root -def deploy_polygon_contracts(deployer): +def deploy_polygon_contracts(deployer, config, poly_network): # Connect to the Polygon network - with networks.polygon.mumbai.use_provider("infura"): - DEPLOYMENTS_CONFIG = config.get_config("deployments")["polygon"]["mumbai"][0] - + with poly_network.use_provider("infura"): stake_info = project.StakeInfo.deploy( - [deployer.address, polygon_child.address], + [deployer.address], sender=deployer, - publish=DEPLOYMENTS_CONFIG.get("verify"), + publish=False, ) polygon_child = project.PolygonChild.deploy( - DEPLOYMENTS_CONFIG.get("fx_child"), + config["fx_child"], stake_info.address, sender=deployer, - publish=DEPLOYMENTS_CONFIG.get("verify"), + publish=False, ) - return polygon_child, stake_info -# TODO: Figure out better way to retrieve the TACo app contract address -def main(taco_app, account_id=None): - deployer = accounts.load("TGoerli") + +# TODO: Figure out better way to retrieve the TACo app contract address +@click.command(cls=NetworkBoundCommand) +@click.option("--network_type", type=click.Choice(["mainnet", "testnet"])) +@account_option() +def cli(network_type, account): + deployer = account + if network_type == "mainnet": + eth_config = config.get_config("deployments")["ethereum"]["mainnet"] + poly_config = config.get_config("deployments")["polygon"]["mainnet"] + eth_network = networks.ethereum.mainnet + poly_network = networks.polygon.mainnet + elif network_type == "testnet": + eth_config = config.get_config("deployments")["ethereum"]["goerli"] + poly_config = config.get_config("deployments")["polygon"]["mumbai"] + eth_network = networks.ethereum.goerli + poly_network = networks.polygon.mumbai + + print("Deployer: {}".format(deployer)) + print("ETH CONFIG: {}".format(eth_config)) + print("POLYGON CONFIG: {}".format(poly_config)) + with accounts.use_sender(deployer): - child, _ = deploy_polygon_contracts(deployer) - root = deploy_eth_contracts(deployer, child.address, taco_app) + child, stake_info = deploy_polygon_contracts( + deployer, convert_config(poly_config), poly_network + ) + root = deploy_eth_contracts( + deployer, deployer.address, child.address, convert_config(eth_config), eth_network + ) # Set the root contract address in the child contract - with networks.polygon.mumbai.use_provider("infura"): + with poly_network.use_provider("infura"): child.setFxRootTunnel(root.address) + stake_info.addUpdaters([child.address]) + + print("CHILD: {}".format(child.address)) + print("STAKE INFO: {}".format(stake_info.address)) + print("ROOT: {}".format(root.address)) From a0acacd28ba66d2b36ee5b2630464363e0231990 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20N=C3=BA=C3=B1ez?= Date: Tue, 29 Aug 2023 13:19:28 +0200 Subject: [PATCH 8/8] New coordinator deployment script Based on the FlatRateFeeModel script --- ape-config.yaml | 1 - scripts/deploy_coordinator_with_fee_model.py | 77 ++++++++++++++++++++ 2 files changed, 77 insertions(+), 1 deletion(-) create mode 100644 scripts/deploy_coordinator_with_fee_model.py diff --git a/ape-config.yaml b/ape-config.yaml index 985f129d..1ffd5886 100644 --- a/ape-config.yaml +++ b/ape-config.yaml @@ -45,7 +45,6 @@ deployments: address: '0xC1379866Fb0c100DCBFAb7b470009C4827D47DD8' - contract_type: fx_child address: '0xCf73231F28B7331BBe3124B907840A94851f9f11' - - verify: False ethereum: local: - nu_token_supply: 1_000_000_000 diff --git a/scripts/deploy_coordinator_with_fee_model.py b/scripts/deploy_coordinator_with_fee_model.py new file mode 100644 index 00000000..5489d036 --- /dev/null +++ b/scripts/deploy_coordinator_with_fee_model.py @@ -0,0 +1,77 @@ +#!/usr/bin/python3 + +import os + +from ape import config, project, networks +from ape.cli import account_option, network_option, NetworkBoundCommand +from ape.utils import ZERO_ADDRESS + +from ape_etherscan.utils import API_KEY_ENV_KEY_MAP + +import click + + +@click.command(cls=NetworkBoundCommand) +@network_option() +@account_option() +@click.option('--currency', default=ZERO_ADDRESS) +@click.option('--rate', default=None) +@click.option('--timeout', default=None) +@click.option('--admin', default=None) +@click.option('--max_size', default=None) +@click.option('--verify/--no-verify', default=True) +def cli(network, account, currency, rate, timeout, admin, max_size, verify): + + deployer = account + click.echo(f"Deployer: {deployer}") + + if rate and currency == ZERO_ADDRESS: + raise ValueError("ERC20 contract address needed for currency") + + # Network + ecosystem_name = networks.provider.network.ecosystem.name + network_name = networks.provider.network.name + provider_name = networks.provider.name + click.echo(f"You are connected to network '{ecosystem_name}:{network_name}:{provider_name}'.") + + # TODO: Move this to a common deployment utilities module + # Validate Etherscan verification parameters. + # This import fails if called before the click network options are evaluated + from scripts.utils import LOCAL_BLOCKCHAIN_ENVIRONMENTS + is_public_deployment = network_name not in LOCAL_BLOCKCHAIN_ENVIRONMENTS + if not is_public_deployment: + verify = False + elif verify: + env_var_key = API_KEY_ENV_KEY_MAP.get(ecosystem_name) + api_key = os.environ.get(env_var_key) + print(api_key) + if not api_key: + raise ValueError(f"{env_var_key} is not set") + + # Use deployment information for currency, if possible + try: + deployments = config.deployments[ecosystem_name][network_name] + except KeyError: + pass # TODO: Further validate currency address? + else: + print(deployments) + try: + currency = next(d for d in deployments if d["contract_type"] == currency)["address"] + except StopIteration: + pass + + try: + stakes = next(d for d in deployments if d["contract_type"] == "StakeInfo")["address"] + except StopIteration: + raise ValueError("StakeInfo deployment needed") + + # Parameter defaults + admin = admin or deployer + rate = rate or 1 + timeout = timeout or 60*60 + max_size = max_size or 64 + + params = (stakes, timeout, max_size, admin, currency, rate) + print("Deployment parameters:", params) + return project.Coordinator.deploy(*params, sender=deployer, publish=verify) + \ No newline at end of file