diff --git a/ape-config.yaml b/ape-config.yaml index 9727fd79..1ffd5886 100644 --- a/ape-config.yaml +++ b/ape-config.yaml @@ -36,13 +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' - - verify: False + - contract_type: fx_child + address: '0xCf73231F28B7331BBe3124B907840A94851f9f11' ethereum: local: - nu_token_supply: 1_000_000_000 @@ -83,6 +85,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 +104,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: 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]); } 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); } 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; } /** 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") + ) 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 diff --git a/scripts/deploy_xchain_test.py b/scripts/deploy_xchain_test.py index 06cc59b8..610b5b1a 100644 --- a/scripts/deploy_xchain_test.py +++ b/scripts/deploy_xchain_test.py @@ -1,53 +1,86 @@ +import click from ape import accounts, config, networks, project +from ape.cli import NetworkBoundCommand, account_option -def deploy_eth_contracts(deployer): - # 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 + - # Deploy the FxStateRootTunnel contract +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] - - # Deploy the FxStateChildTunnel contract - polygon_child = project.PolygonChild.deploy( - DEPLOYMENTS_CONFIG.get("fx_child"), + with poly_network.use_provider("infura"): + stake_info = project.StakeInfo.deploy( + [deployer.address], sender=deployer, - publish=DEPLOYMENTS_CONFIG.get("verify"), + publish=False, ) - stake_info = project.StakeInfo.deploy( - [deployer.address, polygon_child.address], + + polygon_child = project.PolygonChild.deploy( + config["fx_child"], + stake_info.address, sender=deployer, - publish=DEPLOYMENTS_CONFIG.get("verify"), + publish=False, ) return polygon_child, stake_info -def main(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): - root = deploy_eth_contracts(deployer) - child, stake_info = deploy_polygon_contracts(deployer) + 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) - child.setStakeInfoAddress(stake_info.address) + stake_info.addUpdaters([child.address]) - # Set the child contract address in the root contract - with networks.ethereum.goerli.use_provider("infura"): - root.setFxChildTunnel(child.address) + print("CHILD: {}".format(child.address)) + print("STAKE INFO: {}".format(stake_info.address)) + print("ROOT: {}".format(root.address))