Fix StakingEscrowDeployer + fix tests, update PREApplicationDeployer + add tests

pull/2861/head
vzotova 2022-02-03 18:32:03 +03:00 committed by Kieran Prasch
parent ee2a5190e6
commit 1c90a5be8a
5 changed files with 164 additions and 43 deletions

View File

@ -49,6 +49,7 @@ from nucypher.blockchain.eth.interfaces import (
VersionedContract,
)
from nucypher.blockchain.eth.registry import BaseContractRegistry
from nucypher.blockchain.eth.token import NU
from nucypher.crypto.powers import TransactingPower
@ -399,6 +400,8 @@ class NucypherTokenDeployer(BaseContractDeployer):
_upgradeable = False
_ownable = False
TOTAL_SUPPLY = NU(1_000_000_000, 'NU').to_units()
def deploy(self,
transacting_power: TransactingPower,
gas_limit: int = None,
@ -424,7 +427,7 @@ class NucypherTokenDeployer(BaseContractDeployer):
emitter.message("\nNext Transaction: Token Contract Creation", color='blue', bold=True)
# WARNING: Order-sensitive!
constructor_kwargs = {"_totalSupplyOfTokens": self.economics.erc20_total_supply}
constructor_kwargs = {"_totalSupplyOfTokens": self.TOTAL_SUPPLY}
constructor_kwargs.update(overrides)
constructor_kwargs = {k: v for k, v in constructor_kwargs.items() if v is not None}
contract, deployment_receipt = self.blockchain.deploy_contract(transacting_power,
@ -541,15 +544,17 @@ class StakingEscrowDeployer(BaseContractDeployer, UpgradeableContractMixin, Owna
deployment_steps = preparation_steps
_proxy_deployer = DispatcherDeployer
def __init__(self, *args, **kwargs):
STUB_MIN_ALLOWED_TOKENS = NU(15_000, 'NU').to_units()
STUB_MAX_ALLOWED_TOKENS = NU(30_000_000, 'NU').to_units()
def __init__(self, staking_interface: ChecksumAddress = None, *args, **kwargs):
super().__init__(*args, **kwargs)
self.__dispatcher_contract = None
token_contract_name = NucypherTokenDeployer.contract_name
self.token_contract = self.blockchain.get_contract_by_name(registry=self.registry,
contract_name=token_contract_name)
self.policy_manager = self._get_contract(deployer_class=PolicyManagerDeployer)
self.adjudicator = self._get_contract(deployer_class=AdjudicatorDeployer)
self.threshold_staking_address = staking_interface
self.worklock = self._get_contract(deployer_class=WorklockDeployer)
def _get_contract(self, deployer_class) -> VersionedContract:
@ -571,8 +576,8 @@ class StakingEscrowDeployer(BaseContractDeployer, UpgradeableContractMixin, Owna
confirmations: int = 0,
**overrides):
constructor_kwargs = {
"_minAllowableLockedTokens": self.economics.min_authorization,
"_maxAllowableLockedTokens": self.economics.maximum_allowed_locked
"_minAllowableLockedTokens": self.STUB_MIN_ALLOWED_TOKENS,
"_maxAllowableLockedTokens": self.STUB_MAX_ALLOWED_TOKENS
}
constructor_kwargs.update(overrides)
constructor_kwargs = {k: v for k, v in constructor_kwargs.items() if v is not None}
@ -596,11 +601,11 @@ class StakingEscrowDeployer(BaseContractDeployer, UpgradeableContractMixin, Owna
confirmations: int = 0,
**overrides):
constructor_kwargs = {}
constructor_kwargs.update({"_token": self.token_contract.address,
"_workLock": self.worklock.address if self.worklock is not None else NULL_ADDRESS,
"_tStaking": self.threshold_staking_address})
constructor_kwargs.update(overrides)
constructor_kwargs = {k: v for k, v in constructor_kwargs.items() if v is not None}
# Force use of the contract addresses from the registry
constructor_kwargs.update({"_token": self.token_contract.address,
"_workLock": self.worklock.address if self.worklock is not None else NULL_ADDRESS})
the_escrow_contract, deploy_receipt = self.blockchain.deploy_contract(
transacting_power,
self.registry,
@ -726,6 +731,7 @@ class StakingEscrowDeployer(BaseContractDeployer, UpgradeableContractMixin, Owna
return preparation_receipts
# TODO delete me
class PolicyManagerDeployer(BaseContractDeployer, UpgradeableContractMixin, OwnableContractMixin):
"""
Depends on StakingEscrow and NucypherTokenAgent
@ -922,7 +928,7 @@ class StakingInterfaceDeployer(BaseContractDeployer, UpgradeableContractMixin, O
# _ownable = False # TODO: This contract is not truly ownable but we need the logic of the mixin to execute
def __init__(self, *args, **kwargs):
def __init__(self, staking_interface: ChecksumAddress, *args, **kwargs):
super().__init__(*args, **kwargs)
token_contract_name = NucypherTokenDeployer.contract_name
@ -954,6 +960,8 @@ class StakingInterfaceDeployer(BaseContractDeployer, UpgradeableContractMixin, O
except BaseContractRegistry.UnknownContract:
self.worklock_contract = None
self.threshold_staking_interface = staking_interface
def _deploy_essential(self,
transacting_power: TransactingPower,
contract_version: str,
@ -964,7 +972,8 @@ class StakingInterfaceDeployer(BaseContractDeployer, UpgradeableContractMixin, O
constructor_args = (self.token_contract.address,
self.staking_contract.address,
self.policy_contract.address,
worklock_address)
worklock_address,
self.threshold_staking_interface)
contract, deployment_receipt = self.blockchain.deploy_contract(transacting_power,
self.registry,
@ -990,7 +999,7 @@ class StakingInterfaceDeployer(BaseContractDeployer, UpgradeableContractMixin, O
This is meant to be called only once per general deployment.
"""
if deployment_mode not in (BARE, IDLE, FULL):
if deployment_mode not in (BARE, FULL):
raise ValueError(f"Invalid deployment mode ({deployment_mode})")
self.check_deployment_readiness(deployer_address=transacting_power.account,
@ -1168,6 +1177,28 @@ class PREApplicationDeployer(BaseContractDeployer):
super().__init__(*args, **kwargs)
self.threshold_staking_interface = staking_interface
def _deploy_essential(self,
transacting_power: TransactingPower,
gas_limit: int = None,
confirmations: int = 0,
**overrides):
constructor_kwargs = {}
constructor_kwargs.update({"_minAuthorization": self.economics.min_authorization,
"_minOperatorSeconds": self.economics.min_operator_seconds,
"_tStaking": self.threshold_staking_interface})
constructor_kwargs.update(overrides)
constructor_kwargs = {k: v for k, v in constructor_kwargs.items() if v is not None}
the_escrow_contract, deploy_receipt = self.blockchain.deploy_contract(
transacting_power,
self.registry,
self.contract_name,
gas_limit=gas_limit,
confirmations=confirmations,
**constructor_kwargs
)
return the_escrow_contract, deploy_receipt
def deploy(self,
transacting_power: TransactingPower,
gas_limit: int = None,
@ -1178,25 +1209,27 @@ class PREApplicationDeployer(BaseContractDeployer):
emitter=None,
**overrides):
constructor_args = (
self.threshold_staking_interface,
*self.economics.pre_application_deployment_parameters
)
if deployment_mode != FULL:
raise self.ContractDeploymentError(f"{self.contract_name} cannot be deployed in {deployment_mode} mode")
self.check_deployment_readiness(deployer_address=transacting_power.account,
ignore_deployed=ignore_deployed)
contract, receipt = self._deploy_essential(transacting_power=transacting_power,
gas_limit=gas_limit,
confirmations=confirmations,
**overrides)
# Update the progress bar
if progress:
progress.update(1)
contract, receipt = self.blockchain.deploy_contract(
transacting_power,
self.registry,
self.contract_name,
*constructor_args,
gas_limit=gas_limit,
confirmations=confirmations,
# **overrides # TODO: Support CLI deployment params
)
self._contract = contract
self.deployment_receipts = dict(zip(self.deployment_steps, (receipt, )))
return self.deployment_receipts
# TODO: delete me
class WorklockDeployer(BaseContractDeployer):
agency = WorkLockAgent

View File

@ -51,15 +51,21 @@ def staking_escrow_stub_deployer(testerchain, token_deployer, test_registry, tra
@pytest.fixture(scope="module")
def staking_escrow_deployer(testerchain, staking_escrow_stub_deployer, test_registry, transacting_power):
def staking_escrow_deployer(testerchain,
staking_escrow_stub_deployer,
threshold_staking,
test_registry,
transacting_power):
staking_escrow_stub_deployer.deploy(deployment_mode=INIT, transacting_power=transacting_power)
staking_escrow_deployer = StakingEscrowDeployer(registry=test_registry)
staking_escrow_deployer = StakingEscrowDeployer(staking_interface=threshold_staking.address,
registry=test_registry)
return staking_escrow_deployer
@pytest.fixture(scope="module")
def staking_interface_deployer(staking_escrow_deployer, testerchain, test_registry):
staking_interface_deployer = StakingInterfaceDeployer(registry=test_registry)
def staking_interface_deployer(staking_escrow_deployer, testerchain, test_registry, threshold_staking):
staking_interface_deployer = StakingInterfaceDeployer(staking_interface=threshold_staking.address,
registry=test_registry)
return staking_interface_deployer

View File

@ -0,0 +1,78 @@
"""
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.agents import WorkLockAgent, PREApplicationAgent
from nucypher.blockchain.eth.constants import PRE_APPLICATION_CONTRACT_NAME
from nucypher.blockchain.eth.deployers import PREApplicationDeployer
@pytest.fixture(scope="module")
def pre_application_deployer(testerchain,
test_registry,
application_economics,
threshold_staking):
pre_application_deployer = PREApplicationDeployer(staking_interface=threshold_staking.address,
registry=test_registry,
economics=application_economics)
return pre_application_deployer
def test_pre_application_deployment(pre_application_deployer,
deployment_progress,
test_registry,
testerchain,
transacting_power,
threshold_staking):
# Deploy
assert pre_application_deployer.contract_name == PRE_APPLICATION_CONTRACT_NAME
deployment_receipts = pre_application_deployer.deploy(progress=deployment_progress,
transacting_power=transacting_power) # < ---- DEPLOY
# deployment steps must match expected number of steps
steps = pre_application_deployer.deployment_steps
assert deployment_progress.num_steps == len(steps) == len(deployment_receipts) == 1
# Ensure every step is successful
for step_title in steps:
assert deployment_receipts[step_title]['status'] == 1
# Ensure the correct staking escrow address is set
threshold_staking_address = pre_application_deployer.contract.functions.tStaking().call()
assert threshold_staking.address == threshold_staking_address
def test_make_agent(pre_application_deployer, test_registry):
agent = pre_application_deployer.make_agent()
another_application_agent = PREApplicationAgent(registry=test_registry)
assert agent == another_application_agent # __eq__
# Compare the contract address for equality
assert agent.contract_address == another_application_agent.contract_address
def test_deployment_parameters(pre_application_deployer, test_registry, application_economics):
# Ensure restoration of deployment parameters
agent = pre_application_deployer.make_agent()
assert agent.get_min_authorization() == application_economics.min_authorization
assert agent.get_min_operator_seconds() == application_economics.min_operator_seconds

View File

@ -23,7 +23,6 @@ from nucypher.blockchain.eth.agents import ContractAgency, StakingEscrowAgent
from nucypher.blockchain.eth.deployers import (DispatcherDeployer, StakingEscrowDeployer)
@pytest.mark.skip()
def test_staking_escrow_deployment(staking_escrow_deployer, deployment_progress, transacting_power):
deployment_receipts = staking_escrow_deployer.deploy(progress=deployment_progress,
deployment_mode=constants.FULL,
@ -36,7 +35,6 @@ def test_staking_escrow_deployment(staking_escrow_deployer, deployment_progress,
assert deployment_receipts[step]['status'] == 1
@pytest.mark.skip()
def test_make_agent(staking_escrow_deployer, test_registry):
# Create a StakingEscrowAgent instance
staking_agent = staking_escrow_deployer.make_agent()
@ -49,7 +47,6 @@ def test_make_agent(staking_escrow_deployer, test_registry):
assert staking_agent.contract_address == same_staking_agent.contract_address
@pytest.mark.skip()
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)
@ -68,20 +65,20 @@ def test_staking_escrow_has_dispatcher(staking_escrow_deployer, testerchain, tes
assert target == existing_bare_contract.address
@pytest.mark.skip()
def test_upgrade(testerchain, test_registry, application_economics, transacting_power):
def test_upgrade(testerchain, test_registry, application_economics, transacting_power, threshold_staking):
deployer = StakingEscrowDeployer(registry=test_registry, economics=application_economics)
deployer = StakingEscrowDeployer(staking_interface=threshold_staking.address,
registry=test_registry,
economics=application_economics)
receipts = deployer.upgrade(ignore_deployed=True, confirmations=0, transacting_power=transacting_power)
for title, receipt in receipts.items():
assert receipt['status'] == 1
@pytest.mark.skip()
def test_rollback(testerchain, test_registry, transacting_power):
def test_rollback(testerchain, test_registry, transacting_power, threshold_staking):
deployer = StakingEscrowDeployer(registry=test_registry)
deployer = StakingEscrowDeployer(staking_interface=threshold_staking.address, registry=test_registry)
staking_agent = ContractAgency.get_agent(StakingEscrowAgent, registry=test_registry)
current_target = staking_agent.contract.functions.target().call()
@ -105,9 +102,14 @@ def test_rollback(testerchain, test_registry, transacting_power):
assert new_target == old_target
@pytest.mark.skip()
def test_deploy_bare_upgradeable_contract_deployment(testerchain, test_registry, application_economics, transacting_power):
deployer = StakingEscrowDeployer(registry=test_registry, economics=application_economics)
def test_deploy_bare_upgradeable_contract_deployment(testerchain,
test_registry,
application_economics,
transacting_power,
threshold_staking):
deployer = StakingEscrowDeployer(staking_interface=threshold_staking.address,
registry=test_registry,
economics=application_economics)
enrolled_names = list(test_registry.enrolled_names)
old_number_of_enrollments = enrolled_names.count(StakingEscrowDeployer.contract_name)
@ -128,7 +130,6 @@ def test_deploy_bare_upgradeable_contract_deployment(testerchain, test_registry,
assert new_number_of_proxy_enrollments == old_number_of_proxy_enrollments
@pytest.mark.skip()
def test_deployer_version_management(testerchain, test_registry, application_economics):
deployer = StakingEscrowDeployer(registry=test_registry, economics=application_economics)
@ -141,7 +142,6 @@ def test_deployer_version_management(testerchain, test_registry, application_eco
assert untargeted_deployment.address != latest_targeted_deployment.address
@pytest.mark.skip()
def test_manual_proxy_retargeting(testerchain, test_registry, application_economics, transacting_power):
deployer = StakingEscrowDeployer(registry=test_registry, economics=application_economics)

View File

@ -42,6 +42,10 @@ contract ThresholdStakingForPREApplicationMock {
preApplication = _preApplication;
}
function stakedNu(address) external view returns (uint256) {
return 0;
}
function setRoles(
address _stakingProvider,
address _owner,