From 16610f6565aecd1fe1d4ef09d03c3a619d34b9fe Mon Sep 17 00:00:00 2001 From: derekpierre Date: Thu, 22 Aug 2024 16:52:11 -0400 Subject: [PATCH 1/6] Add ability for the deployer to not prompt user for deployments. --- deployment/params.py | 61 ++++++++++++++++++++++++++------------------ 1 file changed, 36 insertions(+), 25 deletions(-) diff --git a/deployment/params.py b/deployment/params.py index abcc99fd8..0b5bbc263 100644 --- a/deployment/params.py +++ b/deployment/params.py @@ -1,6 +1,6 @@ import typing from abc import ABC, abstractmethod -from collections import namedtuple, OrderedDict +from collections import OrderedDict, namedtuple from pathlib import Path from typing import Any, List @@ -480,7 +480,11 @@ class Transactor: Represents an ape account plus validated/annotated transaction execution. """ - def __init__(self, account: typing.Optional[AccountAPI] = None): + def __init__(self, account: typing.Optional[AccountAPI] = None, force: bool = False): + if force and not account: + raise ValueError("'force' can only be used if 'account' is provided") + + self._force = force if account is None: self._account = select_account() else: @@ -502,13 +506,17 @@ def transact(self, method: ContractTransactionHandler, *args) -> ReceiptAPI: else: message = f"{base_message} with no arguments" print(message) - _continue() - result = method(*args, sender=self._account, - # FIXME: Manual gas fees - #199 - # max_priority_fee="3 gwei", - # max_fee="120 gwei" - ) + if not self._force: + _continue() + + result = method( + *args, + sender=self._account, + # FIXME: Manual gas fees - #199 + # max_priority_fee="3 gwei", + # max_fee="120 gwei" + ) return result @@ -526,7 +534,10 @@ def __init__( path: Path, verify: bool, account: typing.Optional[AccountAPI] = None, + force: bool = False, ): + super().__init__(account, force) + check_plugins() self.path = path self.config = config @@ -539,10 +550,13 @@ def __init__( _Constants = namedtuple("_Constants", list(constants)) self.constants = _Constants(**constants) - super().__init__(account) self._set_account(self._account) self.verify = verify - self._confirm_start() + self._print_deployment_info() + + if not self._force: + # Confirms the start of the deployment. + _continue() @classmethod def from_yaml(cls, filepath: Path, *args, **kwargs) -> "Deployer": @@ -583,16 +597,19 @@ def _deploy_contract( self, container: ContractContainer, resolved_params: OrderedDict ) -> ContractInstance: contract_name = container.contract_type.name - _confirm_resolution(resolved_params, contract_name) + if not self._force: + _confirm_resolution(resolved_params, contract_name) deployment_params = [container, *resolved_params.values()] kwargs = self._get_kwargs() deployer_account = self.get_account() - return deployer_account.deploy(*deployment_params, - # FIXME: Manual gas fees - #199 - # max_priority_fee="3 gwei", - # max_fee="120 gwei", - **kwargs) + return deployer_account.deploy( + *deployment_params, + # FIXME: Manual gas fees - #199 + # max_priority_fee="3 gwei", + # max_fee="120 gwei", + **kwargs, + ) def _deploy_proxy( self, @@ -615,12 +632,8 @@ def _deploy_proxy( ) return contract_type_container.at(proxy_contract.address) - def upgrade(self, container: ContractContainer, proxy_address, data=b'') -> ContractInstance: - - admin_slot = chain.provider.get_storage_at( - address=proxy_address, - slot=EIP1967_ADMIN_SLOT - ) + def upgrade(self, container: ContractContainer, proxy_address, data=b"") -> ContractInstance: + admin_slot = chain.provider.get_storage_at(address=proxy_address, slot=EIP1967_ADMIN_SLOT) if admin_slot == EMPTY_BYTES32: raise ValueError( @@ -651,8 +664,7 @@ def finalize(self, deployments: List[ContractInstance]) -> None: if self.verify: verify_contracts(contracts=deployments) - def _confirm_start(self) -> None: - """Confirms the start of the deployment.""" + def _print_deployment_info(self): print( f"Account: {self.get_account().address}", f"Config: {self.path}", @@ -664,4 +676,3 @@ def _confirm_start(self) -> None: f"Gas Price: {networks.provider.gas_price}", sep="\n", ) - _continue() From 9099e3327054844b3d1bffdb05d7f8f9fb152a3d Mon Sep 17 00:00:00 2001 From: derekpierre Date: Thu, 22 Aug 2024 16:53:51 -0400 Subject: [PATCH 2/6] Add deployment script to use for CI tests in order to test deployments. --- deployment/constructor_params/ci/child.yml | 33 ++++++++++++++++++ scripts/ci/deploy_child.py | 39 ++++++++++++++++++++++ 2 files changed, 72 insertions(+) create mode 100644 deployment/constructor_params/ci/child.yml create mode 100644 scripts/ci/deploy_child.py diff --git a/deployment/constructor_params/ci/child.yml b/deployment/constructor_params/ci/child.yml new file mode 100644 index 000000000..40c80af0b --- /dev/null +++ b/deployment/constructor_params/ci/child.yml @@ -0,0 +1,33 @@ +deployment: + name: ci-child + chain_id: 1337 + +artifacts: + dir: ./deployment/artifacts/ + filename: ci.json + +constants: + ONE_HOUR_IN_SECONDS: 3600 + FORTY_THOUSAND_TOKENS_IN_WEI_UNITS: 40000000000000000000000 + TEN_MILLION_TOKENS_IN_WEI_UNITS: 10000000000000000000000000 # https://www.youtube.com/watch?v=EJR1H5tf5wE + MAX_DKG_SIZE: 4 + +contracts: + - MockPolygonChild + - TACoChildApplication: + proxy: + constructor: + _rootApplication: $MockPolygonChild + _minimumAuthorization: $FORTY_THOUSAND_TOKENS_IN_WEI_UNITS + - LynxRitualToken: + constructor: + _totalSupplyOfTokens: $TEN_MILLION_TOKENS_IN_WEI_UNITS + - Coordinator: + proxy: + constructor: + _data: $encode:initialize,$ONE_HOUR_IN_SECONDS,$MAX_DKG_SIZE,$deployer + constructor: + _application: $TACoChildApplication + - GlobalAllowList: + constructor: + _coordinator: $Coordinator diff --git a/scripts/ci/deploy_child.py b/scripts/ci/deploy_child.py new file mode 100644 index 000000000..9d76b026c --- /dev/null +++ b/scripts/ci/deploy_child.py @@ -0,0 +1,39 @@ +#!/usr/bin/python3 +from ape import accounts, networks, project + +from deployment.constants import CONSTRUCTOR_PARAMS_DIR +from deployment.params import Deployer + +VERIFY = False +CONSTRUCTOR_PARAMS_FILEPATH = CONSTRUCTOR_PARAMS_DIR / "ci" / "child.yml" + + +def main(): + with networks.ethereum.local.use_provider("test"): + test_account = accounts.test_accounts[0] + + deployer = Deployer.from_yaml( + filepath=CONSTRUCTOR_PARAMS_FILEPATH, verify=VERIFY, account=test_account, force=True + ) + + mock_polygon_child = deployer.deploy(project.MockPolygonChild) + + taco_child_application = deployer.deploy(project.TACoChildApplication) + + deployer.transact(mock_polygon_child.setChildApplication, taco_child_application.address) + + ritual_token = deployer.deploy(project.LynxRitualToken) + + coordinator = deployer.deploy(project.Coordinator) + + global_allow_list = deployer.deploy(project.GlobalAllowList) + + deployments = [ + mock_polygon_child, + taco_child_application, + ritual_token, + coordinator, + global_allow_list, + ] + + deployer.finalize(deployments=deployments) From 067d7d46005b1c71e817cc21b54dc9acc14b37e4 Mon Sep 17 00:00:00 2001 From: derekpierre Date: Thu, 22 Aug 2024 16:56:43 -0400 Subject: [PATCH 3/6] Add step to CI to test deployment of contracts, and to list contracts in registries for each domain. --- .github/workflows/main.yaml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml index f965aed8e..225e7b1fd 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/main.yaml @@ -43,6 +43,15 @@ jobs: - name: Run Ape Tests run: ape test + - name: Run Deployment Test + run: ape run ci deploy_child + + - name: Run Registry Scripts to list contracts + run: | + ape run list_contracts --domain lynx + ape run list_contracts --domain tapir + ape run list_contracts --domain mainnet + - name: Build npm package run: npm run build From d9810590e9844330bb1cceb9339a688aac84e1aa Mon Sep 17 00:00:00 2001 From: derekpierre Date: Thu, 22 Aug 2024 19:44:41 -0400 Subject: [PATCH 4/6] Update pip install so that script files can properly reference deployment yml path within github action. --- .github/workflows/main.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/main.yaml b/.github/workflows/main.yaml index 225e7b1fd..35fb7b2b1 100644 --- a/.github/workflows/main.yaml +++ b/.github/workflows/main.yaml @@ -38,7 +38,7 @@ jobs: with: cache: "pip" python-version: "3.11" - - run: pip install . -r requirements.txt + - run: pip install -e . -r requirements.txt - name: Run Ape Tests run: ape test From a7ce192dfa9785f21ad1d24678f044685181cf21 Mon Sep 17 00:00:00 2001 From: derekpierre Date: Fri, 23 Aug 2024 07:42:44 -0400 Subject: [PATCH 5/6] Rename 'force' to 'non_interactive' for clarity. --- deployment/params.py | 18 +++++++++--------- scripts/ci/deploy_child.py | 5 ++++- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/deployment/params.py b/deployment/params.py index 0b5bbc263..53826e26f 100644 --- a/deployment/params.py +++ b/deployment/params.py @@ -480,11 +480,11 @@ class Transactor: Represents an ape account plus validated/annotated transaction execution. """ - def __init__(self, account: typing.Optional[AccountAPI] = None, force: bool = False): - if force and not account: - raise ValueError("'force' can only be used if 'account' is provided") + def __init__(self, account: typing.Optional[AccountAPI] = None, non_interactive: bool = False): + if non_interactive and not account: + raise ValueError("'non_interactive' can only be used if an account is provided") - self._force = force + self._non_interactive = non_interactive if account is None: self._account = select_account() else: @@ -507,7 +507,7 @@ def transact(self, method: ContractTransactionHandler, *args) -> ReceiptAPI: message = f"{base_message} with no arguments" print(message) - if not self._force: + if not self._non_interactive: _continue() result = method( @@ -534,9 +534,9 @@ def __init__( path: Path, verify: bool, account: typing.Optional[AccountAPI] = None, - force: bool = False, + non_interactive: bool = False, ): - super().__init__(account, force) + super().__init__(account, non_interactive) check_plugins() self.path = path @@ -554,7 +554,7 @@ def __init__( self.verify = verify self._print_deployment_info() - if not self._force: + if not self._non_interactive: # Confirms the start of the deployment. _continue() @@ -597,7 +597,7 @@ def _deploy_contract( self, container: ContractContainer, resolved_params: OrderedDict ) -> ContractInstance: contract_name = container.contract_type.name - if not self._force: + if not self._non_interactive: _confirm_resolution(resolved_params, contract_name) deployment_params = [container, *resolved_params.values()] kwargs = self._get_kwargs() diff --git a/scripts/ci/deploy_child.py b/scripts/ci/deploy_child.py index 9d76b026c..89cd2cadb 100644 --- a/scripts/ci/deploy_child.py +++ b/scripts/ci/deploy_child.py @@ -13,7 +13,10 @@ def main(): test_account = accounts.test_accounts[0] deployer = Deployer.from_yaml( - filepath=CONSTRUCTOR_PARAMS_FILEPATH, verify=VERIFY, account=test_account, force=True + filepath=CONSTRUCTOR_PARAMS_FILEPATH, + verify=VERIFY, + account=test_account, + non_interactive=True, ) mock_polygon_child = deployer.deploy(project.MockPolygonChild) From c24f375bbf6bbd5e4d42c241189790a0f901d175 Mon Sep 17 00:00:00 2001 From: derekpierre Date: Fri, 23 Aug 2024 07:43:14 -0400 Subject: [PATCH 6/6] Delete generated registry at the end of the script - allows for local execution without always having to manually delete the file. --- scripts/ci/deploy_child.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/scripts/ci/deploy_child.py b/scripts/ci/deploy_child.py index 89cd2cadb..ab5c7ff8b 100644 --- a/scripts/ci/deploy_child.py +++ b/scripts/ci/deploy_child.py @@ -40,3 +40,6 @@ def main(): ] deployer.finalize(deployments=deployments) + + # remove registry file now that task is complete + deployer.registry_filepath.unlink()