Some fixes for deployers and tests

pull/2861/head
vzotova 2021-11-20 19:17:28 +03:00 committed by Kieran Prasch
parent ff2802c399
commit dccc76418a
8 changed files with 9 additions and 520 deletions

View File

@ -536,8 +536,7 @@ class StakingEscrowDeployer(BaseContractDeployer, UpgradeableContractMixin, Owna
can_be_idle = True
init_steps = ('stub_deployment', 'dispatcher_deployment')
preparation_steps = ('contract_deployment', 'dispatcher_retarget')
activation_steps = ('approve_reward_transfer', 'initialize')
deployment_steps = preparation_steps + activation_steps
deployment_steps = preparation_steps
_proxy_deployer = DispatcherDeployer
def __init__(self, *args, **kwargs):
@ -636,7 +635,7 @@ class StakingEscrowDeployer(BaseContractDeployer, UpgradeableContractMixin, Owna
Returns transaction receipts in a dict.
"""
if deployment_mode not in (BARE, IDLE, INIT, FULL):
if deployment_mode not in (BARE, INIT, FULL):
raise ValueError(f"Invalid deployment mode ({deployment_mode})")
# Raise if not all-systems-go
@ -722,86 +721,7 @@ class StakingEscrowDeployer(BaseContractDeployer, UpgradeableContractMixin, Owna
preparation_receipts = dict(zip(self.preparation_steps, (deploy_receipt, dispatcher_retarget_receipt)))
self.deployment_receipts = preparation_receipts
# 3 & 4 - Activation
if deployment_mode in (IDLE, INIT):
# This is the end of deployment without activation: the contract is now idle, waiting for activation
return preparation_receipts
else: # deployment_mode is FULL
activation_receipts = self.activate(transacting_power=transacting_power,
gas_limit=gas_limit,
progress=progress,
confirmations=confirmations,
emitter=emitter)
self.deployment_receipts.update(activation_receipts)
return self.deployment_receipts
def activate(self,
transacting_power: TransactingPower,
gas_limit: int = None,
progress=None,
emitter=None,
confirmations: int = 0):
self._contract = self._get_deployed_contract()
if not self.ready_to_activate:
raise self.ContractDeploymentError(f"This StakingEscrow ({self._contract.address}) cannot be activated")
origin_args = {}
if gas_limit:
origin_args.update({'gas': gas_limit}) # TODO: #842 - Gas Management
# 3 - Approve transferring the reward supply tokens to StakingEscrow #
if emitter:
emitter.message(f"\nNext Transaction: Approve Transfer to {self.contract_name}", color='blue', bold=True)
approve_reward_function = self.token_contract.functions.approve(self._contract.address,
self.economics.erc20_reward_supply)
# TODO: Confirmations / Successful Transaction Indicator / Events ?? - #1193, #1194
approve_reward_receipt = self.blockchain.send_transaction(contract_function=approve_reward_function,
transacting_power=transacting_power,
confirmations=confirmations,
payload=origin_args)
if progress:
progress.update(1)
# 4 - Initialize the StakingEscrow contract
if emitter:
emitter.message(f"\nNext Transaction: {self.contract_name} Initialization", color='blue', bold=True)
deployer_address = transacting_power.account
init_function = self._contract.functions.initialize(self.economics.erc20_reward_supply, deployer_address)
init_receipt = self.blockchain.send_transaction(contract_function=init_function,
transacting_power=transacting_power,
confirmations=confirmations,
payload=origin_args)
if progress:
progress.update(1)
activation_receipts = dict(zip(self.activation_steps, (approve_reward_receipt, init_receipt)))
return activation_receipts
@property
def ready_to_activate(self) -> bool:
try:
deployed_contract = self._get_deployed_contract()
except self.blockchain.UnknownContract:
return False
# TODO: Consider looking for absence of Initialized event - see #1193
# This mimics initialization pre-condition in Issuer (StakingEscrow's base contract)
current_minting_period = deployed_contract.functions.currentMintingPeriod().call()
return current_minting_period == 0
@property
def is_active(self) -> bool:
try:
deployed_contract = self._get_deployed_contract()
except self.blockchain.UnknownContract:
return False
# TODO: Consider looking for Initialized event - see #1193
# This mimics isInitialized() modifier in Issuer (StakingEscrow's base contract)
current_minting_period = deployed_contract.functions.currentMintingPeriod().call()
return current_minting_period != 0
return preparation_receipts
class PolicyManagerDeployer(BaseContractDeployer, UpgradeableContractMixin, OwnableContractMixin):

View File

@ -51,22 +51,8 @@ def staking_escrow_stub_deployer(testerchain, token_deployer, test_registry, tra
@pytest.fixture(scope="module")
def policy_manager_deployer(staking_escrow_stub_deployer, testerchain, test_registry, transacting_power):
def staking_escrow_deployer(testerchain, staking_escrow_stub_deployer, test_registry, transacting_power):
staking_escrow_stub_deployer.deploy(deployment_mode=INIT, transacting_power=transacting_power)
policy_manager_deployer = PolicyManagerDeployer(registry=test_registry)
return policy_manager_deployer
@pytest.fixture(scope="module")
def adjudicator_deployer(policy_manager_deployer, testerchain, test_registry, transacting_power):
policy_manager_deployer.deploy(transacting_power=transacting_power)
adjudicator_deployer = AdjudicatorDeployer(registry=test_registry)
return adjudicator_deployer
@pytest.fixture(scope="module")
def staking_escrow_deployer(testerchain, adjudicator_deployer, test_registry, transacting_power):
adjudicator_deployer.deploy(transacting_power=transacting_power)
staking_escrow_deployer = StakingEscrowDeployer(registry=test_registry)
return staking_escrow_deployer

View File

@ -1,167 +0,0 @@
"""
This file is part of nucypher.
nucypher is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
nucypher is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with nucypher. If not, see <https://www.gnu.org/licenses/>.
"""
import pytest
from constant_sorrow import constants
from eth_tester.exceptions import TransactionFailed
from nucypher.config.constants import TEMPORARY_DOMAIN
from nucypher.blockchain.eth.signers.software import Web3Signer
from nucypher.blockchain.eth.actors import Staker
from nucypher.blockchain.eth.agents import ContractAgency, NucypherTokenAgent, StakingEscrowAgent
from nucypher.blockchain.eth.deployers import (AdjudicatorDeployer, BaseContractDeployer, NucypherTokenDeployer,
PolicyManagerDeployer, StakingEscrowDeployer)
from nucypher.crypto.powers import TransactingPower
from tests.utils.blockchain import token_airdrop
from tests.constants import DEVELOPMENT_TOKEN_AIRDROP_AMOUNT, INSECURE_DEVELOPMENT_PASSWORD
def test_deploy_idle_network(testerchain, deployment_progress, test_registry):
origin, *everybody_else = testerchain.client.accounts
#
# Nucypher Token
#
token_deployer = NucypherTokenDeployer(registry=test_registry)
tpower = TransactingPower(account=origin, signer=Web3Signer(testerchain.client))
with pytest.raises(BaseContractDeployer.ContractDeploymentError):
assert token_deployer.contract_address is constants.CONTRACT_NOT_DEPLOYED
assert not token_deployer.is_deployed()
token_deployer.deploy(progress=deployment_progress, transacting_power=tpower)
assert token_deployer.is_deployed()
token_agent = NucypherTokenAgent(registry=test_registry)
assert token_agent.contract_address == token_deployer.contract_address
another_token_agent = token_deployer.make_agent()
assert another_token_agent.contract_address == token_deployer.contract_address == token_agent.contract_address
#
# StakingEscrow - in INIT mode, i.e. stub for StakingEscrow
#
staking_escrow_deployer = StakingEscrowDeployer(registry=test_registry)
with pytest.raises(BaseContractDeployer.ContractDeploymentError):
assert staking_escrow_deployer.contract_address is constants.CONTRACT_NOT_DEPLOYED
assert not staking_escrow_deployer.is_deployed()
staking_escrow_deployer.deploy(progress=deployment_progress,
deployment_mode=constants.INIT,
transacting_power=tpower)
assert not staking_escrow_deployer.is_deployed()
#
# Policy Manager
#
policy_manager_deployer = PolicyManagerDeployer(registry=test_registry)
with pytest.raises(BaseContractDeployer.ContractDeploymentError):
assert policy_manager_deployer.contract_address is constants.CONTRACT_NOT_DEPLOYED
assert not policy_manager_deployer.is_deployed()
policy_manager_deployer.deploy(progress=deployment_progress, transacting_power=tpower)
assert policy_manager_deployer.is_deployed()
policy_agent = policy_manager_deployer.make_agent()
assert policy_agent.contract_address == policy_manager_deployer.contract_address
#
# Adjudicator
#
adjudicator_deployer = AdjudicatorDeployer(registry=test_registry)
with pytest.raises(BaseContractDeployer.ContractDeploymentError):
assert adjudicator_deployer.contract_address is constants.CONTRACT_NOT_DEPLOYED
assert not adjudicator_deployer.is_deployed()
adjudicator_deployer.deploy(progress=deployment_progress, transacting_power=tpower)
assert adjudicator_deployer.is_deployed()
adjudicator_agent = adjudicator_deployer.make_agent()
assert adjudicator_agent.contract_address == adjudicator_deployer.contract_address
#
# StakingEscrow - in IDLE mode, i.e. without activation steps (approve_funding and initialize)
#
staking_escrow_deployer = StakingEscrowDeployer(registry=test_registry)
with pytest.raises(BaseContractDeployer.ContractDeploymentError):
assert staking_escrow_deployer.contract_address is constants.CONTRACT_NOT_DEPLOYED
assert not staking_escrow_deployer.is_deployed()
staking_escrow_deployer.deploy(progress=deployment_progress,
deployment_mode=constants.IDLE,
transacting_power=tpower)
assert staking_escrow_deployer.is_deployed()
staking_agent = ContractAgency.get_agent(StakingEscrowAgent, registry=test_registry)
assert staking_agent.contract_address == staking_escrow_deployer.contract_address
# The contract has no tokens yet
assert token_agent.get_balance(staking_agent.contract_address) == 0
def test_stake_in_idle_network(testerchain, token_economics, test_registry):
# Let's fund a staker first
token_agent = NucypherTokenAgent(registry=test_registry)
tpower = TransactingPower(account=testerchain.etherbase_account, signer=Web3Signer(testerchain.client))
token_airdrop(transacting_power=tpower,
addresses=testerchain.stakers_accounts,
token_agent=token_agent,
amount=DEVELOPMENT_TOKEN_AIRDROP_AMOUNT)
account = testerchain.stakers_accounts[0]
tpower = TransactingPower(account=account, signer=Web3Signer(testerchain.client))
staker = Staker(transacting_power=tpower,
domain=TEMPORARY_DOMAIN,
registry=test_registry)
# Since StakingEscrow hasn't been activated yet, deposit should work but making a commitment must fail
amount = token_economics.minimum_allowed_locked
periods = token_economics.minimum_locked_periods
staker.initialize_stake(amount=amount, lock_periods=periods)
staker.bond_worker(account)
with pytest.raises((TransactionFailed, ValueError)):
staker.staking_agent.commit_to_next_period(transacting_power=tpower)
def test_activate_network(testerchain, token_economics, test_registry):
staking_escrow_deployer = StakingEscrowDeployer(registry=test_registry)
tpower = TransactingPower(account=testerchain.etherbase_account,
signer=Web3Signer(testerchain.client))
# Let's check we're in the position of activating StakingEscrow
assert staking_escrow_deployer.is_deployed()
assert not staking_escrow_deployer.is_active
assert staking_escrow_deployer.ready_to_activate
# OK, let's do it!
receipts = staking_escrow_deployer.activate(transacting_power=tpower)
for tx in receipts:
assert receipts[tx]['status'] == 1
# Yay!
assert staking_escrow_deployer.is_active
# Trying to activate now must fail
assert not staking_escrow_deployer.ready_to_activate
with pytest.raises(StakingEscrowDeployer.ContractDeploymentError):
staking_escrow_deployer.activate(transacting_power=tpower)

View File

@ -1,120 +0,0 @@
"""
This file is part of nucypher.
nucypher is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
nucypher is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with nucypher. If not, see <https://www.gnu.org/licenses/>.
"""
import pytest
from constant_sorrow import constants
from constant_sorrow.constants import BARE
from nucypher.blockchain.economics import StandardTokenEconomics
from nucypher.blockchain.eth.agents import ContractAgency, StakingEscrowAgent, PolicyManagerAgent
from nucypher.blockchain.eth.deployers import (StakingEscrowDeployer, PolicyManagerDeployer)
@pytest.fixture(scope="module")
def new_token_economics(token_economics):
economics = StandardTokenEconomics(genesis_hours_per_period=token_economics.hours_per_period,
hours_per_period=2 * token_economics.hours_per_period)
return economics
@pytest.fixture(scope='module')
def baseline_deployment(staking_escrow_deployer, transacting_power):
staking_escrow_deployer.deploy(deployment_mode=constants.FULL, transacting_power=transacting_power)
@pytest.fixture(scope='module')
def new_staking_escrow_deployer(testerchain, test_registry, new_token_economics):
staking_escrow_deployer = StakingEscrowDeployer(registry=test_registry,
economics=new_token_economics)
return staking_escrow_deployer
@pytest.fixture(scope='module')
def new_policy_manager_deployer(testerchain, test_registry, new_token_economics):
policy_manager_deployer = PolicyManagerDeployer(registry=test_registry,
economics=new_token_economics)
return policy_manager_deployer
def test_staking_escrow_preparation(testerchain,
transacting_power,
baseline_deployment,
token_economics,
test_registry,
new_staking_escrow_deployer):
new_staking_escrow_deployer.deploy(deployment_mode=constants.BARE,
ignore_deployed=True,
transacting_power=transacting_power)
# Data is still old, because there is no upgrade yet
staking_agent = ContractAgency.get_agent(StakingEscrowAgent, registry=test_registry)
assert staking_agent.contract.functions.secondsPerPeriod().call() == token_economics.seconds_per_period
assert staking_agent.contract.functions.genesisSecondsPerPeriod().call() == token_economics.genesis_seconds_per_period
def test_policy_manager_preparation(testerchain,
transacting_power,
token_economics,
test_registry,
new_policy_manager_deployer):
new_policy_manager_deployer.deploy(deployment_mode=constants.BARE,
ignore_deployed=True,
transacting_power=transacting_power)
# Data is still old, because there is no upgrade yet
policy_manager_agent = ContractAgency.get_agent(PolicyManagerAgent, registry=test_registry)
assert policy_manager_agent.contract.functions.secondsPerPeriod().call() == token_economics.seconds_per_period
assert policy_manager_agent.contract.functions.genesisSecondsPerPeriod().call() == token_economics.genesis_seconds_per_period
def test_staking_escrow_migration_upgrade(testerchain,
transacting_power,
test_registry,
new_token_economics,
new_staking_escrow_deployer):
latest_staking_escrow = testerchain.get_contract_by_name(registry=test_registry,
contract_name=new_staking_escrow_deployer.contract_name,
enrollment_version='latest')
new_staking_escrow_deployer.retarget(target_address=latest_staking_escrow.address,
confirmations=0,
transacting_power=transacting_power)
# Now data must be new
staking_agent = ContractAgency.get_agent(StakingEscrowAgent, registry=test_registry)
assert staking_agent.contract.functions.secondsPerPeriod().call() == new_token_economics.seconds_per_period
assert staking_agent.contract.functions.genesisSecondsPerPeriod().call() == new_token_economics.genesis_seconds_per_period
def test_policy_manager_migration_upgrade(testerchain,
transacting_power,
test_registry,
new_token_economics,
new_policy_manager_deployer):
latest_policy_manager = testerchain.get_contract_by_name(registry=test_registry,
contract_name=new_policy_manager_deployer.contract_name,
enrollment_version='latest')
new_policy_manager_deployer.retarget(target_address=latest_policy_manager.address,
confirmations=0,
transacting_power=transacting_power)
# Now data must be new
policy_manager_agent = ContractAgency.get_agent(PolicyManagerAgent, registry=test_registry)
assert policy_manager_agent.contract.functions.secondsPerPeriod().call() == new_token_economics.seconds_per_period
assert policy_manager_agent.contract.functions.genesisSecondsPerPeriod().call() == new_token_economics.genesis_seconds_per_period

View File

@ -78,50 +78,6 @@ def test_deploy_ethereum_contracts(testerchain,
assert not staking_escrow_deployer.is_deployed()
assert len(staking_escrow_deployer.contract_address) == 42
#
# Policy Manager
#
policy_manager_deployer = PolicyManagerDeployer(registry=test_registry)
with pytest.raises(BaseContractDeployer.ContractDeploymentError):
assert policy_manager_deployer.contract_address is constants.CONTRACT_NOT_DEPLOYED
assert not policy_manager_deployer.is_deployed()
policy_manager_deployer.deploy(progress=deployment_progress, transacting_power=tpower)
assert policy_manager_deployer.is_deployed()
assert len(policy_manager_deployer.contract_address) == 42
policy_agent = policy_manager_deployer.make_agent()
assert len(policy_agent.contract_address) == 42
assert policy_agent.contract_address == policy_manager_deployer.contract_address
another_policy_agent = policy_manager_deployer.make_agent()
assert len(another_policy_agent.contract_address) == 42
assert another_policy_agent.contract_address == policy_manager_deployer.contract_address == policy_agent.contract_address
#
# Adjudicator
#
adjudicator_deployer = AdjudicatorDeployer(registry=test_registry)
with pytest.raises(BaseContractDeployer.ContractDeploymentError):
assert adjudicator_deployer.contract_address is constants.CONTRACT_NOT_DEPLOYED
assert not adjudicator_deployer.is_deployed()
adjudicator_deployer.deploy(progress=deployment_progress, transacting_power=tpower)
assert adjudicator_deployer.is_deployed()
assert len(adjudicator_deployer.contract_address) == 42
adjudicator_agent = adjudicator_deployer.make_agent()
assert len(adjudicator_agent.contract_address) == 42
assert adjudicator_agent.contract_address == adjudicator_deployer.contract_address
another_adjudicator_agent = AdjudicatorAgent(registry=test_registry)
assert len(another_adjudicator_agent.contract_address) == 42
assert another_adjudicator_agent.contract_address == adjudicator_deployer.contract_address == adjudicator_agent.contract_address
# StakingEscrow
staking_escrow_deployer = StakingEscrowDeployer(registry=test_registry)
@ -145,6 +101,5 @@ def test_deploy_ethereum_contracts(testerchain,
# overall deployment steps must match aggregated individual expected number of steps
all_deployment_transactions = token_deployer.deployment_steps + staking_escrow_deployer.init_steps + \
staking_escrow_deployer.deployment_steps + \
policy_manager_deployer.deployment_steps + adjudicator_deployer.deployment_steps
staking_escrow_deployer.deployment_steps
assert deployment_progress.num_steps == len(all_deployment_transactions)

View File

@ -1,70 +0,0 @@
"""
This file is part of nucypher.
nucypher is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
nucypher is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with nucypher. If not, see <https://www.gnu.org/licenses/>.
"""
import pytest
from nucypher.blockchain.eth.signers.software import Web3Signer
from nucypher.crypto.powers import TransactingPower
from nucypher.blockchain.eth.agents import MultiSigAgent
from nucypher.blockchain.eth.constants import NULL_ADDRESS
from nucypher.blockchain.eth.deployers import MultiSigDeployer
def test_multisig_deployer_and_agent(testerchain,
deployment_progress,
test_registry):
origin = testerchain.etherbase_account
tpower = TransactingPower(account=origin, signer=Web3Signer(testerchain.client))
multisig_deployer = MultiSigDeployer(registry=test_registry)
# Can't have a threshold of 0
with pytest.raises(ValueError):
owners = testerchain.unassigned_accounts[0:3]
_ = multisig_deployer.deploy(threshold=0, owners=owners, transacting_power=tpower)
# Can't have no owners
with pytest.raises(ValueError):
_ = multisig_deployer.deploy(threshold=1, owners=[], transacting_power=tpower)
# Can't have the zero address as an owner
with pytest.raises(ValueError):
owners = testerchain.unassigned_accounts[0:3] + [NULL_ADDRESS]
_ = multisig_deployer.deploy(threshold=1, owners=owners, transacting_power=tpower)
# Can't have repeated owners
with pytest.raises(ValueError):
owners = testerchain.unassigned_accounts[0] * 3
_ = multisig_deployer.deploy(threshold=1, owners=owners, transacting_power=tpower)
# At last, sane initialization arguments for the MultiSig
threshold = 2
owners = testerchain.unassigned_accounts[0:3]
receipts = multisig_deployer.deploy(threshold=threshold, owners=owners, transacting_power=tpower)
for step in multisig_deployer.deployment_steps:
assert receipts[step]['status'] == 1
multisig_agent = multisig_deployer.make_agent() # type: MultiSigAgent
assert multisig_agent.nonce == 0
assert multisig_agent.threshold == threshold
assert multisig_agent.number_of_owners == len(owners)
for i, owner in enumerate(owners):
assert multisig_agent.get_owner(i) == owner
assert multisig_agent.is_owner(owner)
assert multisig_agent.owners == tuple(owners)

View File

@ -30,7 +30,7 @@ def test_staking_escrow_deployment(staking_escrow_deployer, deployment_progress,
transacting_power=transacting_power)
# deployment steps must match expected number of steps
assert deployment_progress.num_steps == len(staking_escrow_deployer.deployment_steps) == len(deployment_receipts) == 4
assert deployment_progress.num_steps == len(staking_escrow_deployer.deployment_steps) == len(deployment_receipts) == 2
for step in staking_escrow_deployer.deployment_steps:
assert deployment_receipts[step]['status'] == 1
@ -48,22 +48,6 @@ def test_make_agent(staking_escrow_deployer, test_registry):
assert staking_agent.contract_address == same_staking_agent.contract_address
def test_deployment_parameters(staking_escrow_deployer,
token_deployer,
token_economics,
test_registry):
token_address = staking_escrow_deployer.contract.functions.token().call()
assert token_deployer.contract_address == token_address
staking_agent = ContractAgency.get_agent(StakingEscrowAgent, registry=test_registry)
params = staking_agent.staking_parameters()
assert token_economics.staking_deployment_parameters[3:] == params[3:]
assert token_economics.staking_deployment_parameters[2] == params[2] // params[4]
assert token_economics.staking_deployment_parameters[0]*60*60 == params[0] # FIXME: Do we really want this?
assert token_economics.staking_deployment_parameters[1]*60*60 == params[1]
def test_staking_escrow_has_dispatcher(staking_escrow_deployer, testerchain, test_registry, transacting_power):
# Let's get the "bare" StakingEscrow contract (i.e., unwrapped, no dispatcher)

View File

@ -18,6 +18,7 @@ along with nucypher. If not, see <https://www.gnu.org/licenses/>.
import pytest
from constant_sorrow import constants
from nucypher.blockchain.economics import EconomicsFactory, BaseEconomics
from nucypher.blockchain.eth.agents import WorkLockAgent
from nucypher.blockchain.eth.constants import WORKLOCK_CONTRACT_NAME
@ -25,8 +26,8 @@ from nucypher.blockchain.eth.deployers import WorklockDeployer
@pytest.fixture(scope='module')
def baseline_deployment(adjudicator_deployer, transacting_power):
adjudicator_deployer.deploy(transacting_power=transacting_power)
def baseline_deployment(staking_escrow_stub_deployer, transacting_power):
staking_escrow_stub_deployer.deploy(deployment_mode=constants.INIT, transacting_power=transacting_power)
@pytest.fixture(scope="module")