mirror of https://github.com/nucypher/nucypher.git
Update tests to new TACo nucypher contracts
This commit is aimed to update test to the following changes on nucypher-contracts repo: - Update SimplePREApplication with TACoApplication - Replace ThresholdStakingForPREApplicationMock contract with ThresholdStakingForTACoApplicationMock - Use the new Coordinator contract - Add the deployment of StakeInfo contract The use of these new contracts made necessary the following changes: - Add the deployment of a new Token for ritual fees: RitualToken. This contract has been added as local deployment. - Add the deployment of local contract ConditionNFT Additionally, this commit updates the key character for arguments in ape-config.yaml. From '::variable::' to <variable>, which results in a more legible code. Finally, this commit solves some linting and formatting issues. Co-authored-by: LunarBytes <kieran@nucypher.com>pull/3213/head
parent
5bdb6a8709
commit
fe75f75998
|
@ -38,8 +38,8 @@ from nucypher.blockchain.eth.constants import (
|
|||
ETH_ADDRESS_BYTE_LENGTH,
|
||||
NUCYPHER_TOKEN_CONTRACT_NAME,
|
||||
NULL_ADDRESS,
|
||||
PRE_APPLICATION_CONTRACT_NAME,
|
||||
SUBSCRIPTION_MANAGER_CONTRACT_NAME,
|
||||
TACO_APPLICATION_CONTRACT_NAME,
|
||||
)
|
||||
from nucypher.blockchain.eth.decorators import contract_api
|
||||
from nucypher.blockchain.eth.interfaces import BlockchainInterfaceFactory
|
||||
|
@ -384,7 +384,7 @@ class AdjudicatorAgent(EthereumContractAgent):
|
|||
|
||||
class PREApplicationAgent(EthereumContractAgent):
|
||||
|
||||
contract_name: str = PRE_APPLICATION_CONTRACT_NAME
|
||||
contract_name: str = TACO_APPLICATION_CONTRACT_NAME
|
||||
|
||||
DEFAULT_PROVIDERS_PAGINATION_SIZE_LIGHT_NODE = int(os.environ.get(NUCYPHER_ENVVAR_STAKING_PROVIDERS_PAGINATION_SIZE_LIGHT_NODE, default=30))
|
||||
DEFAULT_PROVIDERS_PAGINATION_SIZE = int(os.environ.get(NUCYPHER_ENVVAR_STAKING_PROVIDERS_PAGINATION_SIZE, default=1000))
|
||||
|
@ -843,7 +843,7 @@ class ContractAgency:
|
|||
if name == NUCYPHER_TOKEN_CONTRACT_NAME:
|
||||
# TODO: Perhaps rename NucypherTokenAgent
|
||||
name = "NucypherToken"
|
||||
if name == PRE_APPLICATION_CONTRACT_NAME:
|
||||
if name == TACO_APPLICATION_CONTRACT_NAME:
|
||||
name = "PREApplication" # TODO not needed once full PRE Application is used
|
||||
agent_name = f"{name}Agent"
|
||||
return agent_name
|
||||
|
|
|
@ -4,20 +4,20 @@
|
|||
# Contract Names
|
||||
#
|
||||
|
||||
DISPATCHER_CONTRACT_NAME = 'Dispatcher'
|
||||
NUCYPHER_TOKEN_CONTRACT_NAME = 'NuCypherToken'
|
||||
STAKING_ESCROW_CONTRACT_NAME = 'StakingEscrow'
|
||||
STAKING_ESCROW_STUB_CONTRACT_NAME = 'StakingEscrowStub'
|
||||
ADJUDICATOR_CONTRACT_NAME = 'Adjudicator'
|
||||
PRE_APPLICATION_CONTRACT_NAME = 'SimplePREApplication' # TODO: Use the real PREApplication
|
||||
SUBSCRIPTION_MANAGER_CONTRACT_NAME = 'SubscriptionManager'
|
||||
DISPATCHER_CONTRACT_NAME = "Dispatcher"
|
||||
NUCYPHER_TOKEN_CONTRACT_NAME = "NuCypherToken"
|
||||
STAKING_ESCROW_CONTRACT_NAME = "StakingEscrow"
|
||||
STAKING_ESCROW_STUB_CONTRACT_NAME = "StakingEscrowStub"
|
||||
ADJUDICATOR_CONTRACT_NAME = "Adjudicator"
|
||||
TACO_APPLICATION_CONTRACT_NAME = "TACoApplication" # TODO: Use the real PREApplication
|
||||
SUBSCRIPTION_MANAGER_CONTRACT_NAME = "SubscriptionManager"
|
||||
|
||||
NUCYPHER_CONTRACT_NAMES = (
|
||||
NUCYPHER_TOKEN_CONTRACT_NAME,
|
||||
STAKING_ESCROW_CONTRACT_NAME,
|
||||
ADJUDICATOR_CONTRACT_NAME,
|
||||
DISPATCHER_CONTRACT_NAME,
|
||||
PRE_APPLICATION_CONTRACT_NAME,
|
||||
TACO_APPLICATION_CONTRACT_NAME,
|
||||
SUBSCRIPTION_MANAGER_CONTRACT_NAME
|
||||
)
|
||||
|
||||
|
|
|
@ -20,19 +20,35 @@ solidity:
|
|||
deployments:
|
||||
ethereum:
|
||||
local:
|
||||
- contract_type: RitualToken
|
||||
address: '0x1e59ce931B4CFea3fe4B875411e280e173cB7A9C' # test account at index 0
|
||||
total_supply: 1000000000000000000000000000
|
||||
- contract_type: TToken
|
||||
address: '0x1e59ce931B4CFea3fe4B875411e280e173cB7A9C' # test account at index 0
|
||||
total_supply: 1000000000000000000000000000
|
||||
- contract_type: NuCypherToken
|
||||
address: '0x1e59ce931B4CFea3fe4B875411e280e173cB7A9C' # test account at index 0
|
||||
nu_token_supply: 1_000_000_000
|
||||
- contract_type: SimplePREApplication
|
||||
- contract_type: StakeInfo
|
||||
address: '0x1e59ce931B4CFea3fe4B875411e280e173cB7A9C' # test account at index 0
|
||||
threshold_staking: '::ThresholdStakingForPREApplicationMock.address::'
|
||||
updaters:
|
||||
- <address.0>
|
||||
- contract_type: TACoApplication
|
||||
address: '0x1e59ce931B4CFea3fe4B875411e280e173cB7A9C' # test account at index 0
|
||||
t_token: <TToken.address>
|
||||
threshold_staking: <ThresholdStakingForTACoApplicationMock.address>
|
||||
pre_min_authorization: 40000000000000000000000
|
||||
pre_min_operator_seconds: 86400 # one day in seconds
|
||||
reward_duration: 604800
|
||||
deauthorization_duration: 5184000
|
||||
- contract_type: Coordinator
|
||||
address: '0x1e59ce931B4CFea3fe4B875411e280e173cB7A9C' # test account at index 0
|
||||
app: '::SimplePREApplication.address::'
|
||||
stake_info: <StakeInfo.address>
|
||||
ritual_timeout: 3600
|
||||
max_dkg_size: 8
|
||||
admin: <address.0>
|
||||
currency: <RitualToken.address>
|
||||
app: <TACoApplication.address>
|
||||
|
||||
test:
|
||||
mnemonic: test test test test test test test test test test test junk
|
||||
|
|
|
@ -67,11 +67,11 @@ def erc20_evm_condition_balanceof(testerchain, test_registry):
|
|||
|
||||
|
||||
@pytest.fixture
|
||||
def erc721_contract(accounts, project, test_registry):
|
||||
def erc721_contract(accounts, project):
|
||||
account = accounts[0]
|
||||
|
||||
# deploy contract
|
||||
deployed_contract = account.deploy(project.ConditionNFT)
|
||||
deployed_contract = project.ConditionNFT
|
||||
|
||||
# mint nft with token id = 1
|
||||
deployed_contract.mint(account.address, 1, sender=account)
|
||||
|
|
|
@ -65,6 +65,11 @@ def mock_multichain_configuration(module_mocker, testerchain):
|
|||
|
||||
|
||||
@pytest.fixture(scope='session', autouse=True)
|
||||
def test_contracts(project):
|
||||
return project.contracts
|
||||
|
||||
|
||||
@pytest.fixture(scope="session", autouse=True)
|
||||
def nucypher_contracts(project):
|
||||
nucypher_contracts_dependency_api = project.dependencies["nucypher-contracts"]
|
||||
# simply use first entry - could be from github ('main') or local ('local')
|
||||
|
@ -74,9 +79,11 @@ def nucypher_contracts(project):
|
|||
|
||||
|
||||
@pytest.fixture(scope='module', autouse=True)
|
||||
def deploy_contracts(nucypher_contracts, accounts):
|
||||
def deploy_contracts(nucypher_contracts, test_contracts, accounts):
|
||||
deployments = ape_deploy_contracts(
|
||||
nucypher_contracts=nucypher_contracts, accounts=accounts
|
||||
nucypher_contracts=nucypher_contracts,
|
||||
test_contracts=test_contracts,
|
||||
accounts=accounts,
|
||||
)
|
||||
return deployments
|
||||
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
pragma solidity ^0.8.0;
|
||||
|
||||
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
|
||||
|
||||
/**
|
||||
* @notice Contract for testing the application contract
|
||||
*/
|
||||
contract RitualToken is ERC20("RitualToken", "RT") {
|
||||
constructor(uint256 _totalSupplyOfTokens) {
|
||||
_mint(msg.sender, _totalSupplyOfTokens);
|
||||
}
|
||||
}
|
|
@ -17,7 +17,11 @@ from nucypher.config.constants import (
|
|||
#
|
||||
|
||||
|
||||
MOCK_STAKING_CONTRACT_NAME = 'ThresholdStakingForPREApplicationMock'
|
||||
MOCK_STAKING_CONTRACT_NAME = "ThresholdStakingForTACoApplicationMock"
|
||||
RITUAL_TOKEN = "RitualToken"
|
||||
T_TOKEN = "TToken"
|
||||
STAKE_INFO = "StakeInfo"
|
||||
CONDITION_NFT = "ConditionNFT"
|
||||
|
||||
#
|
||||
# Ursula
|
||||
|
|
|
@ -1,10 +1,14 @@
|
|||
import json
|
||||
from copy import deepcopy
|
||||
from pathlib import Path
|
||||
from typing import Any, Dict, Tuple
|
||||
from typing import Dict, List, Tuple, Union
|
||||
|
||||
from ape import config as ape_config
|
||||
from ape import project
|
||||
from ape.api import AccountAPI, DependencyAPI
|
||||
from ape.contracts.base import ContractInstance
|
||||
from ape_test.accounts import TestAccount
|
||||
from eth_typing import ChecksumAddress
|
||||
from eth_utils import to_checksum_address
|
||||
|
||||
from nucypher.blockchain.eth.agents import (
|
||||
|
@ -14,46 +18,120 @@ from nucypher.blockchain.eth.agents import (
|
|||
SubscriptionManagerAgent,
|
||||
)
|
||||
from nucypher.blockchain.eth.registry import InMemoryContractRegistry
|
||||
from tests.constants import MOCK_STAKING_CONTRACT_NAME
|
||||
from tests.constants import (
|
||||
CONDITION_NFT,
|
||||
MOCK_STAKING_CONTRACT_NAME,
|
||||
RITUAL_TOKEN,
|
||||
STAKE_INFO,
|
||||
T_TOKEN,
|
||||
)
|
||||
|
||||
# order sensitive
|
||||
_CONTRACTS_TO_DEPLOY_ON_TESTERCHAIN = (
|
||||
RITUAL_TOKEN,
|
||||
T_TOKEN,
|
||||
NucypherTokenAgent.contract_name,
|
||||
STAKE_INFO,
|
||||
MOCK_STAKING_CONTRACT_NAME,
|
||||
PREApplicationAgent.contract_name,
|
||||
SubscriptionManagerAgent.contract_name,
|
||||
CoordinatorAgent.contract_name,
|
||||
CONDITION_NFT,
|
||||
)
|
||||
|
||||
VARIABLE_PREFIX_SYMBOL = "<"
|
||||
VARIABLE_SUFIX_SYMBOL = ">"
|
||||
|
||||
def get_ape_project_build_path(project) -> Path:
|
||||
build_path = Path(project.path) / '.build'
|
||||
return build_path
|
||||
|
||||
|
||||
def _is_variable(param: Union[str, int, List[Union[str, int]]]) -> bool:
|
||||
"""Check if param is a ape-config variable"""
|
||||
return isinstance(param, str) and (
|
||||
param.startswith(VARIABLE_PREFIX_SYMBOL)
|
||||
and param.endswith(VARIABLE_SUFIX_SYMBOL)
|
||||
)
|
||||
|
||||
|
||||
def _resolve_variable(
|
||||
param: str,
|
||||
contract_name: str,
|
||||
deployments: Dict[str, ContractInstance],
|
||||
accounts: List[TestAccount],
|
||||
) -> Union[ChecksumAddress, str, int]:
|
||||
"""Resolve a ape-config variable to a literal"""
|
||||
dependency_expression = param.strip(VARIABLE_PREFIX_SYMBOL).strip(
|
||||
VARIABLE_SUFIX_SYMBOL
|
||||
)
|
||||
dependency_name, attribute_name = dependency_expression.split(".")
|
||||
if dependency_name == "address":
|
||||
try:
|
||||
account = accounts[int(attribute_name)]
|
||||
except ValueError:
|
||||
raise ValueError(
|
||||
f"Ape account must be accessed by an index; got '{attribute_name}'."
|
||||
)
|
||||
address = ChecksumAddress(account.address)
|
||||
return address
|
||||
try:
|
||||
param = getattr(deployments[dependency_name], attribute_name)
|
||||
except KeyError:
|
||||
raise ValueError(f"Contract {contract_name} not found in deployments")
|
||||
except AttributeError:
|
||||
raise ValueError(f"Attribute {attribute_name} not found in {dependency_name}")
|
||||
return param
|
||||
|
||||
|
||||
def process_deployment_params(
|
||||
contract_name, params, deployments, symbol: str = "::"
|
||||
) -> Dict[str, Any]:
|
||||
contract_name: str,
|
||||
params: Dict[str, Union[str, int, list]],
|
||||
deployments: Dict[str, ContractInstance],
|
||||
accounts: List[TestAccount],
|
||||
) -> Dict[str, Union[ChecksumAddress, str, int]]:
|
||||
"""Process deployment params for a contract."""
|
||||
processed_params = dict()
|
||||
for k, v in params.items():
|
||||
if isinstance(v, str) and (v.startswith(symbol) and v.endswith(symbol)):
|
||||
dependency_expression = v.strip(symbol)
|
||||
dependency_name, attribute_name = dependency_expression.split(".")
|
||||
try:
|
||||
v = getattr(deployments[dependency_name], attribute_name)
|
||||
except KeyError:
|
||||
raise ValueError(f"Contract {contract_name} not found in deployments")
|
||||
except AttributeError:
|
||||
raise ValueError(
|
||||
f"Attribute {attribute_name} not found in {dependency_name}"
|
||||
)
|
||||
processed_params[k] = v
|
||||
for param_name, param_value in params.items():
|
||||
if _is_variable(param_value):
|
||||
param_value = _resolve_variable(
|
||||
param=param_value,
|
||||
contract_name=contract_name,
|
||||
deployments=deployments,
|
||||
accounts=accounts,
|
||||
)
|
||||
processed_params[param_name] = param_value
|
||||
continue
|
||||
|
||||
elif isinstance(param_value, list):
|
||||
value_list = list()
|
||||
for param in param_value:
|
||||
if _is_variable(param):
|
||||
param = _resolve_variable(
|
||||
param=param,
|
||||
contract_name=contract_name,
|
||||
deployments=deployments,
|
||||
accounts=accounts,
|
||||
)
|
||||
|
||||
value_list.append(param)
|
||||
|
||||
processed_params[param_name] = value_list
|
||||
continue
|
||||
|
||||
else:
|
||||
# this parameter is a literal
|
||||
processed_params[param_name] = param_value
|
||||
continue
|
||||
|
||||
return processed_params
|
||||
|
||||
|
||||
def get_deployment_params(
|
||||
contract_name, config, accounts, deployments
|
||||
contract_name: str,
|
||||
config: Dict[str, Union[str, list]],
|
||||
accounts: List[TestAccount],
|
||||
deployments: Dict[str, ContractInstance],
|
||||
) -> Tuple[Dict, AccountAPI]:
|
||||
"""
|
||||
Get deployment params for a contract.
|
||||
|
@ -64,14 +142,23 @@ def get_deployment_params(
|
|||
deployer_address = accounts[params.pop("address")]
|
||||
name = params.pop("contract_type")
|
||||
if name == contract_name:
|
||||
params = process_deployment_params(contract_name, params, deployments)
|
||||
params = process_deployment_params(
|
||||
contract_name=contract_name,
|
||||
params=params,
|
||||
deployments=deployments,
|
||||
accounts=accounts,
|
||||
)
|
||||
return params, deployer_address
|
||||
else:
|
||||
# there are no deployment params for this contract; default to account at index 0
|
||||
return dict(), accounts[0]
|
||||
|
||||
|
||||
def deploy_contracts(nucypher_contracts: DependencyAPI, accounts):
|
||||
def deploy_contracts(
|
||||
nucypher_contracts: DependencyAPI,
|
||||
test_contracts: DependencyAPI,
|
||||
accounts: List[TestAccount],
|
||||
):
|
||||
"""Deploy contracts o via ape's API for testing."""
|
||||
config = ape_config.get_config("deployments")["ethereum"]["local"]
|
||||
deployments = dict()
|
||||
|
@ -79,13 +166,20 @@ def deploy_contracts(nucypher_contracts: DependencyAPI, accounts):
|
|||
params, deployer_account = get_deployment_params(
|
||||
name, deployments=deployments, config=config, accounts=accounts
|
||||
)
|
||||
dependency_contract = getattr(nucypher_contracts, name)
|
||||
deployed_contract = deployer_account.deploy(dependency_contract, *params.values())
|
||||
try:
|
||||
# this contract is a dependency
|
||||
contract = getattr(nucypher_contracts, name)
|
||||
except AttributeError:
|
||||
# this contract is local to this project
|
||||
contract = getattr(project, name)
|
||||
deployed_contract = deployer_account.deploy(contract, *params.values())
|
||||
deployments[name] = deployed_contract
|
||||
return deployments
|
||||
|
||||
|
||||
def registry_from_ape_deployments(nucypher_contracts: DependencyAPI, deployments: Dict) -> InMemoryContractRegistry:
|
||||
def registry_from_ape_deployments(
|
||||
nucypher_contracts: DependencyAPI, deployments: Dict[str, ContractInstance]
|
||||
) -> InMemoryContractRegistry:
|
||||
"""Creates a registry from ape deployments."""
|
||||
|
||||
# Get the raw abi from the cached manifest
|
||||
|
|
Loading…
Reference in New Issue