mirror of https://github.com/nucypher/nucypher.git
New deployment order: StakingEscrow dispatcher, then PolicyManager+Dispatcher -> Adjudicator+Dispatcher -> WorkLock and only after this StakingEscrow itself
parent
9815440464
commit
61d8dc1ec0
|
@ -179,9 +179,9 @@ class ContractAdministrator(NucypherTokenActor):
|
|||
)
|
||||
|
||||
dispatched_upgradeable_deployer_classes = (
|
||||
StakingEscrowDeployer,
|
||||
PolicyManagerDeployer,
|
||||
AdjudicatorDeployer,
|
||||
StakingEscrowDeployer,
|
||||
)
|
||||
|
||||
upgradeable_deployer_classes = (
|
||||
|
|
|
@ -227,11 +227,8 @@ class StakingEscrowAgent(EthereumContractAgent):
|
|||
contract_name: str = STAKING_ESCROW_CONTRACT_NAME
|
||||
_proxy_name: str = DISPATCHER_CONTRACT_NAME
|
||||
_excluded_interfaces = (
|
||||
'setPolicyManager',
|
||||
'verifyState',
|
||||
'finishUpgrade',
|
||||
'setAdjudicator',
|
||||
'setWorkLock'
|
||||
'finishUpgrade'
|
||||
)
|
||||
|
||||
DEFAULT_PAGINATION_SIZE: int = 30 # TODO: Use dynamic pagination size (see #1424)
|
||||
|
|
|
@ -23,6 +23,7 @@ DISPATCHER_CONTRACT_NAME = 'Dispatcher'
|
|||
STAKING_INTERFACE_ROUTER_CONTRACT_NAME = "StakingInterfaceRouter"
|
||||
NUCYPHER_TOKEN_CONTRACT_NAME = 'NuCypherToken'
|
||||
STAKING_ESCROW_CONTRACT_NAME = 'StakingEscrow'
|
||||
STAKING_ESCROW_STUB_CONTRACT_NAME = 'StakingEscrowStub'
|
||||
POLICY_MANAGER_CONTRACT_NAME = 'PolicyManager'
|
||||
STAKING_INTERFACE_CONTRACT_NAME = 'StakingInterface'
|
||||
PREALLOCATION_ESCROW_CONTRACT_NAME = 'PreallocationEscrow'
|
||||
|
|
|
@ -18,7 +18,7 @@ along with nucypher. If not, see <https://www.gnu.org/licenses/>.
|
|||
|
||||
from collections import OrderedDict
|
||||
|
||||
from constant_sorrow.constants import (BARE, CONTRACT_NOT_DEPLOYED, FULL, IDLE, NO_BENEFICIARY, NO_DEPLOYER_CONFIGURED)
|
||||
from constant_sorrow.constants import (BARE, CONTRACT_NOT_DEPLOYED, FULL, IDLE, INIT, NO_BENEFICIARY, NO_DEPLOYER_CONFIGURED)
|
||||
from eth_typing.evm import ChecksumAddress
|
||||
from typing import Dict, List, Tuple
|
||||
from web3 import Web3
|
||||
|
@ -505,15 +505,13 @@ class StakingEscrowDeployer(BaseContractDeployer, UpgradeableContractMixin, Owna
|
|||
|
||||
agency = StakingEscrowAgent
|
||||
contract_name = agency.contract_name
|
||||
contract_name_stub = "StakingEscrowStub"
|
||||
|
||||
can_be_idle = True
|
||||
preparation_steps = ('contract_deployment',
|
||||
'dispatcher_deployment',
|
||||
'set_on_policy_manager',
|
||||
'set_on_adjudicator')
|
||||
worklock_preparation_step = ('set_on_worklock',)
|
||||
init_steps = ('stub_deployment', 'dispatcher_deployment')
|
||||
preparation_steps = ('contract_deployment', 'dispatcher_retarget')
|
||||
activation_steps = ('approve_reward_transfer', 'initialize')
|
||||
deployment_steps = preparation_steps + worklock_preparation_step + activation_steps
|
||||
deployment_steps = preparation_steps + activation_steps
|
||||
_proxy_deployer = DispatcherDeployer
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
|
@ -528,18 +526,48 @@ class StakingEscrowDeployer(BaseContractDeployer, UpgradeableContractMixin, Owna
|
|||
worklock_contract_name = WorklockDeployer.contract_name
|
||||
self.token_contract = self.blockchain.get_contract_by_name(registry=self.registry,
|
||||
contract_name=token_contract_name)
|
||||
self.policy_manager = self.blockchain.get_contract_by_name(registry=self.registry,
|
||||
contract_name=policy_manager_contract_name,
|
||||
proxy_name=policy_manager_proxy_name)
|
||||
self.adjudicator = self.blockchain.get_contract_by_name(registry=self.registry,
|
||||
contract_name=adjudicator_contract_name,
|
||||
proxy_name=adjudicator_proxy_name)
|
||||
try:
|
||||
self.policy_manager = self.blockchain.get_contract_by_name(registry=self.registry,
|
||||
contract_name=policy_manager_contract_name,
|
||||
proxy_name=policy_manager_proxy_name)
|
||||
except self.registry.UnknownContract:
|
||||
self.policy_manager = None
|
||||
|
||||
try:
|
||||
self.adjudicator = self.blockchain.get_contract_by_name(registry=self.registry,
|
||||
contract_name=adjudicator_contract_name,
|
||||
proxy_name=adjudicator_proxy_name)
|
||||
except self.registry.UnknownContract:
|
||||
self.adjudicator = None
|
||||
|
||||
try:
|
||||
self.worklock = self.blockchain.get_contract_by_name(registry=self.registry,
|
||||
contract_name=worklock_contract_name)
|
||||
except self.registry.UnknownContract:
|
||||
self.worklock = None
|
||||
|
||||
def _deploy_stub(self, gas_limit: int = None, confirmations: int = 0, **overrides):
|
||||
constructor_kwargs = {
|
||||
"_hoursPerPeriod": self.economics.hours_per_period,
|
||||
"_minLockedPeriods": self.economics.minimum_locked_periods,
|
||||
"_minAllowableLockedTokens": self.economics.minimum_allowed_locked,
|
||||
"_maxAllowableLockedTokens": self.economics.maximum_allowed_locked
|
||||
}
|
||||
constructor_kwargs.update(overrides)
|
||||
constructor_kwargs = {k: v for k, v in constructor_kwargs.items() if v is not None}
|
||||
# Force use of the token address from the registry
|
||||
constructor_kwargs.update({"_token": self.token_contract.address})
|
||||
the_escrow_contract, deploy_receipt = self.blockchain.deploy_contract(
|
||||
self.deployer_address,
|
||||
self.registry,
|
||||
self.contract_name_stub,
|
||||
gas_limit=gas_limit,
|
||||
confirmations=confirmations,
|
||||
**constructor_kwargs
|
||||
)
|
||||
|
||||
return the_escrow_contract, deploy_receipt
|
||||
|
||||
def _deploy_essential(self, contract_version: str, gas_limit: int = None, confirmations: int = 0, **overrides):
|
||||
args = self.economics.staking_deployment_parameters
|
||||
constructor_kwargs = {
|
||||
|
@ -557,7 +585,7 @@ class StakingEscrowDeployer(BaseContractDeployer, UpgradeableContractMixin, Owna
|
|||
}
|
||||
constructor_kwargs.update(overrides)
|
||||
constructor_kwargs = {k: v for k, v in constructor_kwargs.items() if v is not None}
|
||||
# Force use of the token address from the registry
|
||||
# Force use of the contract addresses from the registry
|
||||
constructor_kwargs.update({"_token": self.token_contract.address,
|
||||
"_policyManager": self.policy_manager.address,
|
||||
"_adjudicator": self.adjudicator.address,
|
||||
|
@ -575,7 +603,7 @@ class StakingEscrowDeployer(BaseContractDeployer, UpgradeableContractMixin, Owna
|
|||
return the_escrow_contract, deploy_receipt
|
||||
|
||||
def deploy(self,
|
||||
deployment_mode=FULL,
|
||||
deployment_mode=INIT,
|
||||
gas_limit: int = None,
|
||||
progress=None,
|
||||
contract_version: str = "latest",
|
||||
|
@ -597,7 +625,7 @@ class StakingEscrowDeployer(BaseContractDeployer, UpgradeableContractMixin, Owna
|
|||
Returns transaction receipts in a dict.
|
||||
"""
|
||||
|
||||
if deployment_mode not in (BARE, IDLE, FULL):
|
||||
if deployment_mode not in (BARE, IDLE, INIT, FULL):
|
||||
raise ValueError(f"Invalid deployment mode ({deployment_mode})")
|
||||
|
||||
# Raise if not all-systems-go
|
||||
|
@ -608,32 +636,60 @@ class StakingEscrowDeployer(BaseContractDeployer, UpgradeableContractMixin, Owna
|
|||
if gas_limit:
|
||||
origin_args.update({'gas': gas_limit}) # TODO: Gas Management - #842
|
||||
|
||||
# 1 - Deploy #
|
||||
if emitter:
|
||||
emitter.message(f"\nNext Transaction: {self.contract_name} Contract Creation", color='blue', bold=True)
|
||||
the_escrow_contract, deploy_receipt = self._deploy_essential(contract_version=contract_version,
|
||||
gas_limit=gas_limit,
|
||||
confirmations=confirmations,
|
||||
**overrides)
|
||||
if deployment_mode is INIT:
|
||||
# 1 - Deploy Stub
|
||||
if emitter:
|
||||
emitter.message(f"\nNext Transaction: {self.contract_name_stub} Contract Creation", color='blue', bold=True)
|
||||
the_escrow_contract, deploy_receipt = self._deploy_stub(gas_limit=gas_limit,
|
||||
confirmations=confirmations,
|
||||
**overrides)
|
||||
else:
|
||||
# 1 - Deploy StakingEscrow
|
||||
if emitter:
|
||||
emitter.message(f"\nNext Transaction: {self.contract_name} Contract Creation", color='blue', bold=True)
|
||||
the_escrow_contract, deploy_receipt = self._deploy_essential(contract_version=contract_version,
|
||||
gas_limit=gas_limit,
|
||||
confirmations=confirmations,
|
||||
**overrides)
|
||||
|
||||
# This is the end of bare deployment.
|
||||
if deployment_mode is BARE:
|
||||
self._contract = the_escrow_contract
|
||||
receipts = self._finish_bare_deployment(deployment_receipt=deploy_receipt, progress=progress)
|
||||
return receipts
|
||||
# This is the end of bare deployment.
|
||||
if deployment_mode is BARE:
|
||||
self._contract = the_escrow_contract
|
||||
receipts = self._finish_bare_deployment(deployment_receipt=deploy_receipt, progress=progress)
|
||||
return receipts
|
||||
|
||||
if progress:
|
||||
progress.update(1)
|
||||
|
||||
# 2 - Deploy the dispatcher used for updating this contract #
|
||||
if emitter:
|
||||
emitter.message(f"\nNext Transaction: {DispatcherDeployer.contract_name} Contract Creation for {self.contract_name}", color='blue', bold=True)
|
||||
dispatcher_deployer = DispatcherDeployer(registry=self.registry,
|
||||
target_contract=the_escrow_contract,
|
||||
deployer_address=self.deployer_address)
|
||||
if deployment_mode is INIT:
|
||||
# 2 - Deploy the dispatcher used for updating this contract #
|
||||
if emitter:
|
||||
emitter.message(f"\nNext Transaction: {DispatcherDeployer.contract_name} "
|
||||
f"Contract Creation for {self.contract_name}",
|
||||
color='blue', bold=True)
|
||||
dispatcher_deployer = DispatcherDeployer(registry=self.registry,
|
||||
target_contract=the_escrow_contract,
|
||||
deployer_address=self.deployer_address)
|
||||
|
||||
dispatcher_receipts = dispatcher_deployer.deploy(gas_limit=gas_limit, confirmations=confirmations)
|
||||
dispatcher_deploy_receipt = dispatcher_receipts[dispatcher_deployer.deployment_steps[0]]
|
||||
else:
|
||||
# 2 - Upgrade dispatcher to the real contract
|
||||
if emitter:
|
||||
emitter.message(f"\nNext Transaction: {DispatcherDeployer.contract_name} "
|
||||
f"Contract Upgrade for {self.contract_name}",
|
||||
color='blue', bold=True)
|
||||
the_stub_contract = self.blockchain.get_contract_by_name(registry=self.registry,
|
||||
contract_name=self.contract_name_stub)
|
||||
dispatcher_deployer = DispatcherDeployer(registry=self.registry,
|
||||
target_contract=the_stub_contract,
|
||||
deployer_address=self.deployer_address,
|
||||
bare=True)
|
||||
|
||||
dispatcher_retarget_receipt = dispatcher_deployer.retarget(new_target=the_escrow_contract.address,
|
||||
gas_limit=gas_limit,
|
||||
confirmations=confirmations)
|
||||
|
||||
dispatcher_receipts = dispatcher_deployer.deploy(gas_limit=gas_limit, confirmations=confirmations)
|
||||
dispatcher_deploy_receipt = dispatcher_receipts[dispatcher_deployer.deployment_steps[0]]
|
||||
if progress:
|
||||
progress.update(1)
|
||||
|
||||
|
@ -645,57 +701,17 @@ class StakingEscrowDeployer(BaseContractDeployer, UpgradeableContractMixin, Owna
|
|||
wrapped_escrow_contract = self.blockchain._wrap_contract(dispatcher_contract,
|
||||
target_contract=the_escrow_contract)
|
||||
|
||||
# Configure the PolicyManager, Adjudicator, WorkLock contracts by setting the StakingEscrow
|
||||
tx_args = {}
|
||||
if gas_limit:
|
||||
tx_args.update({'gas': gas_limit}) # TODO: #842
|
||||
|
||||
if emitter:
|
||||
emitter.message(f"\nNext Transaction: Set StakingEscrow on {self.policy_manager.address}", color='blue', bold=True)
|
||||
set_on_policy_manager_function = self.policy_manager.functions.setStakingEscrow(wrapped_escrow_contract.address)
|
||||
set_on_policy_manager_receipt = self.blockchain.send_transaction(contract_function=set_on_policy_manager_function,
|
||||
sender_address=self.deployer_address,
|
||||
confirmations=confirmations,
|
||||
payload=tx_args)
|
||||
if progress:
|
||||
progress.update(1)
|
||||
|
||||
if emitter:
|
||||
emitter.message(f"\nNext Transaction: Set StakingEscrow on {self.adjudicator.address}", color='blue', bold=True)
|
||||
set_on_adjudicator_function = self.adjudicator.functions.setStakingEscrow(wrapped_escrow_contract.address)
|
||||
set_on_adjudicator_receipt = self.blockchain.send_transaction(contract_function=set_on_adjudicator_function,
|
||||
sender_address=self.deployer_address,
|
||||
confirmations=confirmations,
|
||||
payload=tx_args)
|
||||
if progress:
|
||||
progress.update(1)
|
||||
|
||||
preparation_receipts = dict(zip(self.preparation_steps,
|
||||
(deploy_receipt,
|
||||
dispatcher_deploy_receipt,
|
||||
set_on_policy_manager_receipt,
|
||||
set_on_adjudicator_receipt)))
|
||||
self.deployment_receipts = preparation_receipts
|
||||
|
||||
if self.worklock is not None:
|
||||
if emitter:
|
||||
emitter.message(f"\nNext Transaction: Set StakingEscrow on {self.worklock.address}", color='blue', bold=True)
|
||||
set_on_worklock_function = self.worklock.functions.setStakingEscrow(wrapped_escrow_contract.address)
|
||||
set_on_worklock_receipt = self.blockchain.send_transaction(contract_function=set_on_worklock_function,
|
||||
sender_address=self.deployer_address,
|
||||
confirmations=confirmations,
|
||||
payload=tx_args)
|
||||
receipts = dict(zip(self.worklock_preparation_step, (set_on_worklock_receipt,)))
|
||||
self.deployment_receipts.update(receipts)
|
||||
|
||||
if progress:
|
||||
progress.update(1)
|
||||
|
||||
# Switch the contract for the wrapped one
|
||||
self._contract = wrapped_escrow_contract
|
||||
|
||||
if deployment_mode is INIT:
|
||||
preparation_receipts = dict(zip(self.init_steps, (deploy_receipt, dispatcher_deploy_receipt)))
|
||||
else:
|
||||
preparation_receipts = dict(zip(self.preparation_steps, (deploy_receipt, dispatcher_retarget_receipt)))
|
||||
self.deployment_receipts = preparation_receipts
|
||||
|
||||
# 3 & 4 - Activation
|
||||
if deployment_mode is IDLE:
|
||||
if deployment_mode is IDLE or deployment_mode is 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
|
||||
|
@ -788,24 +804,21 @@ class PolicyManagerDeployer(BaseContractDeployer, UpgradeableContractMixin, Owna
|
|||
contract_name=staking_contract_name,
|
||||
proxy_name=proxy_name)
|
||||
except self.registry.UnknownContract:
|
||||
self.staking_contract = None
|
||||
staking_contract_name = StakingEscrowDeployer.contract_name_stub
|
||||
self.staking_contract = self.blockchain.get_contract_by_name(registry=self.registry,
|
||||
contract_name=staking_contract_name,
|
||||
proxy_name=proxy_name)
|
||||
|
||||
def check_deployment_readiness(self, *args, **kwargs) -> Tuple[bool, list]:
|
||||
policy_manager_deployment_rules = []
|
||||
if self.staking_contract is not None:
|
||||
staking_escrow_owner = self.staking_contract.functions.owner().call()
|
||||
policy_manager_deployment_rules.append(
|
||||
(self.deployer_address == staking_escrow_owner,
|
||||
f'{self.contract_name} must be deployed by the owner of {STAKING_ESCROW_CONTRACT_NAME} ({staking_escrow_owner})')
|
||||
)
|
||||
staking_escrow_owner = self.staking_contract.functions.owner().call()
|
||||
policy_manager_deployment_rules = [
|
||||
(self.deployer_address == staking_escrow_owner,
|
||||
f'{self.contract_name} must be deployed by the owner of {STAKING_ESCROW_CONTRACT_NAME} ({staking_escrow_owner})')
|
||||
]
|
||||
return super().check_deployment_readiness(additional_rules=policy_manager_deployment_rules, *args, **kwargs)
|
||||
|
||||
def _deploy_essential(self, contract_version: str, gas_limit: int = None, confirmations: int = 0, **overrides) -> tuple:
|
||||
escrow_address = self.staking_contract.address if self.staking_contract is not None else NULL_ADDRESS
|
||||
constructor_kwargs = {"_secondsPerPeriod": self.economics.seconds_per_period}
|
||||
constructor_kwargs.update(overrides)
|
||||
constructor_kwargs = {k: v for k, v in constructor_kwargs.items() if v is not None}
|
||||
constructor_kwargs.update({"_escrow": escrow_address})
|
||||
def _deploy_essential(self, contract_version: str, gas_limit: int = None, confirmations: int = 0) -> tuple:
|
||||
constructor_kwargs = {"_escrow": self.staking_contract.address}
|
||||
policy_manager_contract, deploy_receipt = self.blockchain.deploy_contract(self.deployer_address,
|
||||
self.registry,
|
||||
self.contract_name,
|
||||
|
@ -823,7 +836,6 @@ class PolicyManagerDeployer(BaseContractDeployer, UpgradeableContractMixin, Owna
|
|||
ignore_deployed: bool = False,
|
||||
confirmations: int = 0,
|
||||
emitter=None,
|
||||
**overrides,
|
||||
) -> Dict[str, dict]:
|
||||
|
||||
if deployment_mode not in (BARE, IDLE, FULL):
|
||||
|
@ -836,8 +848,7 @@ class PolicyManagerDeployer(BaseContractDeployer, UpgradeableContractMixin, Owna
|
|||
emitter.message(f"\nNext Transaction: {self.contract_name} Contract Creation", color='blue', bold=True)
|
||||
policy_manager_contract, deploy_receipt = self._deploy_essential(contract_version=contract_version,
|
||||
gas_limit=gas_limit,
|
||||
confirmations=confirmations,
|
||||
**overrides)
|
||||
confirmations=confirmations)
|
||||
|
||||
# This is the end of bare deployment.
|
||||
if deployment_mode is BARE:
|
||||
|
@ -929,9 +940,15 @@ class StakingInterfaceDeployer(BaseContractDeployer, UpgradeableContractMixin, O
|
|||
|
||||
staking_contract_name = StakingEscrowDeployer.contract_name
|
||||
staking_proxy_name = StakingEscrowDeployer._proxy_deployer.contract_name
|
||||
self.staking_contract = self.blockchain.get_contract_by_name(registry=self.registry,
|
||||
contract_name=staking_contract_name,
|
||||
proxy_name=staking_proxy_name)
|
||||
try:
|
||||
self.staking_contract = self.blockchain.get_contract_by_name(registry=self.registry,
|
||||
contract_name=staking_contract_name,
|
||||
proxy_name=staking_proxy_name)
|
||||
except self.registry.UnknownContract:
|
||||
staking_contract_name = StakingEscrowDeployer.contract_name_stub
|
||||
self.staking_contract = self.blockchain.get_contract_by_name(registry=self.registry,
|
||||
contract_name=staking_contract_name,
|
||||
proxy_name=staking_proxy_name)
|
||||
|
||||
policy_contract_name = PolicyManagerDeployer.contract_name
|
||||
policy_proxy_name = PolicyManagerDeployer._proxy_deployer.contract_name
|
||||
|
@ -1140,16 +1157,17 @@ class AdjudicatorDeployer(BaseContractDeployer, UpgradeableContractMixin, Ownabl
|
|||
contract_name=staking_contract_name,
|
||||
proxy_name=proxy_name)
|
||||
except self.registry.UnknownContract:
|
||||
self.staking_contract = None
|
||||
staking_contract_name = StakingEscrowDeployer.contract_name_stub
|
||||
self.staking_contract = self.blockchain.get_contract_by_name(registry=self.registry,
|
||||
contract_name=staking_contract_name,
|
||||
proxy_name=proxy_name)
|
||||
|
||||
def check_deployment_readiness(self, *args, **kwargs) -> Tuple[bool, list]:
|
||||
adjudicator_deployment_rules = []
|
||||
if self.staking_contract is not None:
|
||||
staking_escrow_owner = self.staking_contract.functions.owner().call()
|
||||
adjudicator_deployment_rules.append(
|
||||
(self.deployer_address == staking_escrow_owner,
|
||||
f'{self.contract_name} must be deployed by the owner of {STAKING_ESCROW_CONTRACT_NAME} ({staking_escrow_owner})')
|
||||
)
|
||||
staking_escrow_owner = self.staking_contract.functions.owner().call()
|
||||
adjudicator_deployment_rules = [
|
||||
(self.deployer_address == staking_escrow_owner,
|
||||
f'{self.contract_name} must be deployed by the owner of {STAKING_ESCROW_CONTRACT_NAME} ({staking_escrow_owner})')
|
||||
]
|
||||
return super().check_deployment_readiness(additional_rules=adjudicator_deployment_rules, *args, **kwargs)
|
||||
|
||||
def _deploy_essential(self, contract_version: str, gas_limit: int = None, confirmations: int = 0, **overrides):
|
||||
|
@ -1164,8 +1182,7 @@ class AdjudicatorDeployer(BaseContractDeployer, UpgradeableContractMixin, Ownabl
|
|||
constructor_kwargs.update(overrides)
|
||||
constructor_kwargs = {k: v for k, v in constructor_kwargs.items() if v is not None}
|
||||
# Force use of the escrow address from the registry
|
||||
escrow_address = self.staking_contract.address if self.staking_contract is not None else NULL_ADDRESS
|
||||
constructor_kwargs.update({"_escrow": escrow_address})
|
||||
constructor_kwargs.update({"_escrow": self.staking_contract.address})
|
||||
adjudicator_contract, deploy_receipt = self.blockchain.deploy_contract(self.deployer_address,
|
||||
self.registry,
|
||||
self.contract_name,
|
||||
|
@ -1249,11 +1266,26 @@ class WorklockDeployer(BaseContractDeployer):
|
|||
def __init__(self, *args, **kwargs):
|
||||
|
||||
super().__init__(*args, **kwargs)
|
||||
self.token_agent = ContractAgency.get_agent(NucypherTokenAgent, registry=self.registry) # type: NucypherTokenAgent
|
||||
token_contract_name = NucypherTokenDeployer.contract_name
|
||||
self.token_contract = self.blockchain.get_contract_by_name(registry=self.registry,
|
||||
contract_name=token_contract_name)
|
||||
|
||||
staking_contract_name = StakingEscrowDeployer.contract_name
|
||||
proxy_name = StakingEscrowDeployer._proxy_deployer.contract_name
|
||||
try:
|
||||
self.staking_contract = self.blockchain.get_contract_by_name(registry=self.registry,
|
||||
contract_name=staking_contract_name,
|
||||
proxy_name=proxy_name)
|
||||
except self.registry.UnknownContract:
|
||||
staking_contract_name = StakingEscrowDeployer.contract_name_stub
|
||||
self.staking_contract = self.blockchain.get_contract_by_name(registry=self.registry,
|
||||
contract_name=staking_contract_name,
|
||||
proxy_name=proxy_name)
|
||||
|
||||
def _deploy_essential(self, gas_limit: int = None, confirmations: int = 0):
|
||||
# Deploy
|
||||
constructor_args = (self.token_agent.contract_address,
|
||||
constructor_args = (self.token_contract.address,
|
||||
self.staking_contract.address,
|
||||
*self.economics.worklock_deployment_parameters)
|
||||
|
||||
worklock_contract, receipt = self.blockchain.deploy_contract(self.deployer_address,
|
||||
|
@ -1278,11 +1310,7 @@ class WorklockDeployer(BaseContractDeployer):
|
|||
if deployment_mode != FULL:
|
||||
raise self.ContractDeploymentError(f"{self.contract_name} cannot be deployed in {deployment_mode} mode")
|
||||
|
||||
# staking_escrow_rule = [
|
||||
# (self.staking_agent.worklock == NULL_ADDRESS,
|
||||
# f"StakingEscrow already has a WorkLock reference ({self.staking_agent.worklock})")
|
||||
# ]
|
||||
self.check_deployment_readiness(ignore_deployed=ignore_deployed)#, additional_rules=staking_escrow_rule)
|
||||
self.check_deployment_readiness(ignore_deployed=ignore_deployed)
|
||||
|
||||
# Essential
|
||||
if emitter:
|
||||
|
|
|
@ -13,7 +13,7 @@ import "zeppelin/math/Math.sol";
|
|||
/**
|
||||
* @title Adjudicator
|
||||
* @notice Supervises stakers' behavior and punishes when something's wrong.
|
||||
* @dev |v2.2.1|
|
||||
* @dev |v2.1.2|
|
||||
*/
|
||||
contract Adjudicator is Upgradeable {
|
||||
|
||||
|
@ -35,6 +35,7 @@ contract Adjudicator is Upgradeable {
|
|||
bytes32 constant RESERVED_CAPSULE_AND_CFRAG_BYTES = bytes32(0);
|
||||
address constant RESERVED_ADDRESS = address(0);
|
||||
|
||||
StakingEscrow public immutable escrow;
|
||||
SignatureVerifier.HashAlgorithm public immutable hashAlgorithm;
|
||||
uint256 public immutable basePenalty;
|
||||
uint256 public immutable penaltyHistoryCoefficient;
|
||||
|
@ -43,10 +44,9 @@ contract Adjudicator is Upgradeable {
|
|||
|
||||
mapping (address => uint256) public penaltyHistory;
|
||||
mapping (bytes32 => bool) public evaluatedCFrags;
|
||||
StakingEscrow public escrow;
|
||||
|
||||
/**
|
||||
* @param _escrow Escrow contract. Zero address if not yet deployed
|
||||
* @param _escrow Escrow contract
|
||||
* @param _hashAlgorithm Hashing algorithm
|
||||
* @param _basePenalty Base for the penalty calculation
|
||||
* @param _penaltyHistoryCoefficient Coefficient for calculating the penalty depending on the history
|
||||
|
@ -62,8 +62,7 @@ contract Adjudicator is Upgradeable {
|
|||
uint256 _rewardCoefficient
|
||||
) {
|
||||
// Sanity checks.
|
||||
require(// This contract has an escrow if it's not the null address.
|
||||
(address(_escrow) == address(0) || _escrow.secondsPerPeriod() > 0) &&
|
||||
require(_escrow.secondsPerPeriod() > 0 && // This contract has an escrow, and it's not the null address.
|
||||
// The reward and penalty coefficients are set.
|
||||
_percentagePenaltyCoefficient != 0 &&
|
||||
_rewardCoefficient != 0);
|
||||
|
@ -75,17 +74,6 @@ contract Adjudicator is Upgradeable {
|
|||
rewardCoefficient = _rewardCoefficient;
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Sets address of the escrow contract
|
||||
* @param _escrow Escrow contract
|
||||
*/
|
||||
function setStakingEscrow(StakingEscrow _escrow) external onlyOwner {
|
||||
// StakingEscrow can be set only once
|
||||
require(address(escrow) == address(0));
|
||||
require(_escrow.secondsPerPeriod() > 0); // This contract has an escrow, and it's not the null address.
|
||||
escrow = _escrow;
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Submit proof that a worker created wrong CFrag
|
||||
* @param _capsuleBytes Serialized capsule
|
||||
|
@ -203,7 +191,6 @@ contract Adjudicator is Upgradeable {
|
|||
/// @dev the `onlyWhileUpgrading` modifier works through a call to the parent `verifyState`
|
||||
function verifyState(address _testTarget) public override virtual {
|
||||
super.verifyState(_testTarget);
|
||||
require(address(delegateGet(_testTarget, this.escrow.selector)) == address(escrow));
|
||||
bytes32 evaluationCFragHash = SignatureVerifier.hash(
|
||||
abi.encodePacked(RESERVED_CAPSULE_AND_CFRAG_BYTES), SignatureVerifier.HashAlgorithm.SHA256);
|
||||
require(delegateGet(_testTarget, this.evaluatedCFrags.selector, evaluationCFragHash) ==
|
||||
|
@ -215,10 +202,6 @@ contract Adjudicator is Upgradeable {
|
|||
/// @dev the `onlyWhileUpgrading` modifier works through a call to the parent `finishUpgrade`
|
||||
function finishUpgrade(address _target) public override virtual {
|
||||
super.finishUpgrade(_target);
|
||||
StakingEscrow escrowAddress = Adjudicator(_target).escrow();
|
||||
if (address(escrowAddress) != address(0)) {
|
||||
escrow = escrowAddress;
|
||||
}
|
||||
// preparation for the verifyState method
|
||||
bytes32 evaluationCFragHash = SignatureVerifier.hash(
|
||||
abi.encodePacked(RESERVED_CAPSULE_AND_CFRAG_BYTES), SignatureVerifier.HashAlgorithm.SHA256);
|
||||
|
|
|
@ -1,555 +0,0 @@
|
|||
// SPDX-License-Identifier: AGPL-3.0-or-later
|
||||
|
||||
pragma solidity ^0.7.0;
|
||||
|
||||
|
||||
import "zeppelin/math/SafeMath.sol";
|
||||
import "zeppelin/token/ERC20/SafeERC20.sol";
|
||||
import "zeppelin/utils/Address.sol";
|
||||
import "zeppelin/ownership/Ownable.sol";
|
||||
import "contracts/NuCypherToken.sol";
|
||||
import "contracts/StakingEscrow.sol";
|
||||
import "contracts/lib/AdditionalMath.sol";
|
||||
|
||||
|
||||
/**
|
||||
* @notice The WorkLock distribution contract
|
||||
*/
|
||||
contract WorkLock is Ownable {
|
||||
using SafeERC20 for NuCypherToken;
|
||||
using SafeMath for uint256;
|
||||
using AdditionalMath for uint256;
|
||||
using Address for address payable;
|
||||
using Address for address;
|
||||
|
||||
event Deposited(address indexed sender, uint256 value);
|
||||
event Bid(address indexed sender, uint256 depositedETH);
|
||||
event Claimed(address indexed sender, uint256 claimedTokens);
|
||||
event Refund(address indexed sender, uint256 refundETH, uint256 completedWork);
|
||||
event Canceled(address indexed sender, uint256 value);
|
||||
event BiddersChecked(address indexed sender, uint256 startIndex, uint256 endIndex);
|
||||
event ForceRefund(address indexed sender, address indexed bidder, uint256 refundETH);
|
||||
event CompensationWithdrawn(address indexed sender, uint256 value);
|
||||
event Shutdown(address indexed sender);
|
||||
|
||||
struct WorkInfo {
|
||||
uint256 depositedETH;
|
||||
uint256 completedWork;
|
||||
bool claimed;
|
||||
uint128 index;
|
||||
}
|
||||
|
||||
uint16 public constant SLOWING_REFUND = 100;
|
||||
uint256 private constant MAX_ETH_SUPPLY = 2e10 ether;
|
||||
|
||||
NuCypherToken public immutable token;
|
||||
StakingEscrow public immutable escrow;
|
||||
|
||||
/*
|
||||
* @dev WorkLock calculations:
|
||||
* bid = minBid + bonusETHPart
|
||||
* bonusTokenSupply = tokenSupply - bidders.length * minAllowableLockedTokens
|
||||
* bonusDepositRate = bonusTokenSupply / bonusETHSupply
|
||||
* claimedTokens = minAllowableLockedTokens + bonusETHPart * bonusDepositRate
|
||||
* bonusRefundRate = bonusDepositRate * SLOWING_REFUND / boostingRefund
|
||||
* refundETH = completedWork / refundRate
|
||||
*/
|
||||
uint256 public immutable boostingRefund;
|
||||
uint256 public immutable minAllowedBid;
|
||||
uint16 public immutable stakingPeriods;
|
||||
// copy from the escrow contract
|
||||
uint256 public immutable maxAllowableLockedTokens;
|
||||
uint256 public immutable minAllowableLockedTokens;
|
||||
|
||||
uint256 public tokenSupply;
|
||||
uint256 public startBidDate;
|
||||
uint256 public endBidDate;
|
||||
uint256 public endCancellationDate;
|
||||
|
||||
uint256 public bonusETHSupply;
|
||||
mapping(address => WorkInfo) public workInfo;
|
||||
mapping(address => uint256) public compensation;
|
||||
|
||||
address[] public bidders;
|
||||
// if value == bidders.length then WorkLock is fully checked
|
||||
uint256 public nextBidderToCheck;
|
||||
|
||||
/**
|
||||
* @dev Checks timestamp regarding cancellation window
|
||||
*/
|
||||
modifier afterCancellationWindow()
|
||||
{
|
||||
require(block.timestamp >= endCancellationDate,
|
||||
"Operation is allowed when cancellation phase is over");
|
||||
_;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param _token Token contract
|
||||
* @param _escrow Escrow contract
|
||||
* @param _startBidDate Timestamp when bidding starts
|
||||
* @param _endBidDate Timestamp when bidding will end
|
||||
* @param _endCancellationDate Timestamp when cancellation will ends
|
||||
* @param _boostingRefund Coefficient to boost refund ETH
|
||||
* @param _stakingPeriods Amount of periods during which tokens will be locked after claiming
|
||||
* @param _minAllowedBid Minimum allowed ETH amount for bidding
|
||||
*/
|
||||
constructor(
|
||||
NuCypherToken _token,
|
||||
StakingEscrow _escrow,
|
||||
uint256 _startBidDate,
|
||||
uint256 _endBidDate,
|
||||
uint256 _endCancellationDate,
|
||||
uint256 _boostingRefund,
|
||||
uint16 _stakingPeriods,
|
||||
uint256 _minAllowedBid
|
||||
) {
|
||||
uint256 totalSupply = _token.totalSupply();
|
||||
require(totalSupply > 0 && // token contract is deployed and accessible
|
||||
_escrow.secondsPerPeriod() > 0 && // escrow contract is deployed and accessible
|
||||
_escrow.token() == _token && // same token address for worklock and escrow
|
||||
_endBidDate > _startBidDate && // bidding period lasts some time
|
||||
_endBidDate > block.timestamp && // there is time to make a bid
|
||||
_endCancellationDate >= _endBidDate && // cancellation window includes bidding
|
||||
_minAllowedBid > 0 && // min allowed bid was set
|
||||
_boostingRefund > 0 && // boosting coefficient was set
|
||||
_stakingPeriods >= _escrow.minLockedPeriods()); // staking duration is consistent with escrow contract
|
||||
// worst case for `ethToWork()` and `workToETH()`,
|
||||
// when ethSupply == MAX_ETH_SUPPLY and tokenSupply == totalSupply
|
||||
require(MAX_ETH_SUPPLY * totalSupply * SLOWING_REFUND / MAX_ETH_SUPPLY / totalSupply == SLOWING_REFUND &&
|
||||
MAX_ETH_SUPPLY * totalSupply * _boostingRefund / MAX_ETH_SUPPLY / totalSupply == _boostingRefund);
|
||||
|
||||
token = _token;
|
||||
escrow = _escrow;
|
||||
startBidDate = _startBidDate;
|
||||
endBidDate = _endBidDate;
|
||||
endCancellationDate = _endCancellationDate;
|
||||
boostingRefund = _boostingRefund;
|
||||
stakingPeriods = _stakingPeriods;
|
||||
minAllowedBid = _minAllowedBid;
|
||||
maxAllowableLockedTokens = _escrow.maxAllowableLockedTokens();
|
||||
minAllowableLockedTokens = _escrow.minAllowableLockedTokens();
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Deposit tokens to contract
|
||||
* @param _value Amount of tokens to transfer
|
||||
*/
|
||||
function tokenDeposit(uint256 _value) external {
|
||||
require(block.timestamp < endBidDate, "Can't deposit more tokens after end of bidding");
|
||||
token.safeTransferFrom(msg.sender, address(this), _value);
|
||||
tokenSupply += _value;
|
||||
emit Deposited(msg.sender, _value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Calculate amount of tokens that will be get for specified amount of ETH
|
||||
* @dev This value will be fixed only after end of bidding
|
||||
*/
|
||||
function ethToTokens(uint256 _ethAmount) public view returns (uint256) {
|
||||
if (_ethAmount < minAllowedBid) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// when all participants bid with the same minimum amount of eth
|
||||
if (bonusETHSupply == 0) {
|
||||
return tokenSupply / bidders.length;
|
||||
}
|
||||
|
||||
uint256 bonusETH = _ethAmount - minAllowedBid;
|
||||
uint256 bonusTokenSupply = tokenSupply - bidders.length * minAllowableLockedTokens;
|
||||
return minAllowableLockedTokens + bonusETH.mul(bonusTokenSupply).div(bonusETHSupply);
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Calculate amount of work that need to be done to refund specified amount of ETH
|
||||
*/
|
||||
function ethToWork(uint256 _ethAmount, uint256 _tokenSupply, uint256 _ethSupply)
|
||||
internal view returns (uint256)
|
||||
{
|
||||
return _ethAmount.mul(_tokenSupply).mul(SLOWING_REFUND).divCeil(_ethSupply.mul(boostingRefund));
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Calculate amount of work that need to be done to refund specified amount of ETH
|
||||
* @dev This value will be fixed only after end of bidding
|
||||
* @param _ethToReclaim Specified sum of ETH staker wishes to reclaim following completion of work
|
||||
* @param _restOfDepositedETH Remaining ETH in staker's deposit once ethToReclaim sum has been subtracted
|
||||
* @dev _ethToReclaim + _restOfDepositedETH = depositedETH
|
||||
*/
|
||||
function ethToWork(uint256 _ethToReclaim, uint256 _restOfDepositedETH) internal view returns (uint256) {
|
||||
|
||||
uint256 baseETHSupply = bidders.length * minAllowedBid;
|
||||
// when all participants bid with the same minimum amount of eth
|
||||
if (bonusETHSupply == 0) {
|
||||
return ethToWork(_ethToReclaim, tokenSupply, baseETHSupply);
|
||||
}
|
||||
|
||||
uint256 baseETH = 0;
|
||||
uint256 bonusETH = 0;
|
||||
|
||||
// If the staker's total remaining deposit (including the specified sum of ETH to reclaim)
|
||||
// is lower than the minimum bid size,
|
||||
// then only the base part is used to calculate the work required to reclaim ETH
|
||||
if (_ethToReclaim + _restOfDepositedETH <= minAllowedBid) {
|
||||
baseETH = _ethToReclaim;
|
||||
|
||||
// If the staker's remaining deposit (not including the specified sum of ETH to reclaim)
|
||||
// is still greater than the minimum bid size,
|
||||
// then only the bonus part is used to calculate the work required to reclaim ETH
|
||||
} else if (_restOfDepositedETH >= minAllowedBid) {
|
||||
bonusETH = _ethToReclaim;
|
||||
|
||||
// If the staker's remaining deposit (not including the specified sum of ETH to reclaim)
|
||||
// is lower than the minimum bid size,
|
||||
// then both the base and bonus parts must be used to calculate the work required to reclaim ETH
|
||||
} else {
|
||||
bonusETH = _ethToReclaim + _restOfDepositedETH - minAllowedBid;
|
||||
baseETH = _ethToReclaim - bonusETH;
|
||||
}
|
||||
|
||||
uint256 baseTokenSupply = bidders.length * minAllowableLockedTokens;
|
||||
uint256 work = 0;
|
||||
if (baseETH > 0) {
|
||||
work = ethToWork(baseETH, baseTokenSupply, baseETHSupply);
|
||||
}
|
||||
|
||||
if (bonusETH > 0) {
|
||||
uint256 bonusTokenSupply = tokenSupply - baseTokenSupply;
|
||||
work += ethToWork(bonusETH, bonusTokenSupply, bonusETHSupply);
|
||||
}
|
||||
|
||||
return work;
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Calculate amount of work that need to be done to refund specified amount of ETH
|
||||
* @dev This value will be fixed only after end of bidding
|
||||
*/
|
||||
function ethToWork(uint256 _ethAmount) public view returns (uint256) {
|
||||
return ethToWork(_ethAmount, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Calculate amount of ETH that will be refund for completing specified amount of work
|
||||
*/
|
||||
function workToETH(uint256 _completedWork, uint256 _ethSupply, uint256 _tokenSupply)
|
||||
internal view returns (uint256)
|
||||
{
|
||||
return _completedWork.mul(_ethSupply).mul(boostingRefund).div(_tokenSupply.mul(SLOWING_REFUND));
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Calculate amount of ETH that will be refund for completing specified amount of work
|
||||
* @dev This value will be fixed only after end of bidding
|
||||
*/
|
||||
function workToETH(uint256 _completedWork, uint256 _depositedETH) public view returns (uint256) {
|
||||
uint256 baseETHSupply = bidders.length * minAllowedBid;
|
||||
// when all participants bid with the same minimum amount of eth
|
||||
if (bonusETHSupply == 0) {
|
||||
return workToETH(_completedWork, baseETHSupply, tokenSupply);
|
||||
}
|
||||
|
||||
uint256 bonusWork = 0;
|
||||
uint256 bonusETH = 0;
|
||||
uint256 baseTokenSupply = bidders.length * minAllowableLockedTokens;
|
||||
|
||||
if (_depositedETH > minAllowedBid) {
|
||||
bonusETH = _depositedETH - minAllowedBid;
|
||||
uint256 bonusTokenSupply = tokenSupply - baseTokenSupply;
|
||||
bonusWork = ethToWork(bonusETH, bonusTokenSupply, bonusETHSupply);
|
||||
|
||||
if (_completedWork <= bonusWork) {
|
||||
return workToETH(_completedWork, bonusETHSupply, bonusTokenSupply);
|
||||
}
|
||||
}
|
||||
|
||||
_completedWork -= bonusWork;
|
||||
return bonusETH + workToETH(_completedWork, baseETHSupply, baseTokenSupply);
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Get remaining work to full refund
|
||||
*/
|
||||
function getRemainingWork(address _bidder) external view returns (uint256) {
|
||||
WorkInfo storage info = workInfo[_bidder];
|
||||
uint256 completedWork = escrow.getCompletedWork(_bidder).sub(info.completedWork);
|
||||
uint256 remainingWork = ethToWork(info.depositedETH);
|
||||
if (remainingWork <= completedWork) {
|
||||
return 0;
|
||||
}
|
||||
return remainingWork - completedWork;
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Get length of bidders array
|
||||
*/
|
||||
function getBiddersLength() external view returns (uint256) {
|
||||
return bidders.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Bid for tokens by transferring ETH
|
||||
*/
|
||||
function bid() external payable {
|
||||
require(block.timestamp >= startBidDate, "Bidding is not open yet");
|
||||
require(block.timestamp < endBidDate, "Bidding is already finished");
|
||||
WorkInfo storage info = workInfo[msg.sender];
|
||||
|
||||
// first bid
|
||||
if (info.depositedETH == 0) {
|
||||
require(msg.value >= minAllowedBid, "Bid must be at least minimum");
|
||||
require(bidders.length < tokenSupply / minAllowableLockedTokens, "Not enough tokens for more bidders");
|
||||
info.index = uint128(bidders.length);
|
||||
bidders.push(msg.sender);
|
||||
bonusETHSupply = bonusETHSupply.add(msg.value - minAllowedBid);
|
||||
} else {
|
||||
bonusETHSupply = bonusETHSupply.add(msg.value);
|
||||
}
|
||||
|
||||
info.depositedETH = info.depositedETH.add(msg.value);
|
||||
emit Bid(msg.sender, msg.value);
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Cancel bid and refund deposited ETH
|
||||
*/
|
||||
function cancelBid() external {
|
||||
require(block.timestamp < endCancellationDate,
|
||||
"Cancellation allowed only during cancellation window");
|
||||
WorkInfo storage info = workInfo[msg.sender];
|
||||
require(info.depositedETH > 0, "No bid to cancel");
|
||||
require(!info.claimed, "Tokens are already claimed");
|
||||
uint256 refundETH = info.depositedETH;
|
||||
info.depositedETH = 0;
|
||||
|
||||
// remove from bidders array, move last bidder to the empty place
|
||||
uint256 lastIndex = bidders.length - 1;
|
||||
if (info.index != lastIndex) {
|
||||
address lastBidder = bidders[lastIndex];
|
||||
bidders[info.index] = lastBidder;
|
||||
workInfo[lastBidder].index = info.index;
|
||||
}
|
||||
bidders.pop();
|
||||
|
||||
if (refundETH > minAllowedBid) {
|
||||
bonusETHSupply = bonusETHSupply.sub(refundETH - minAllowedBid);
|
||||
}
|
||||
msg.sender.sendValue(refundETH);
|
||||
emit Canceled(msg.sender, refundETH);
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Cancels distribution, makes possible to retrieve all bids and owner gets all tokens
|
||||
*/
|
||||
function shutdown() external onlyOwner {
|
||||
require(!isClaimingAvailable(), "Claiming has already been enabled");
|
||||
internalShutdown();
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Cancels distribution, makes possible to retrieve all bids and owner gets all tokens
|
||||
*/
|
||||
function internalShutdown() internal {
|
||||
startBidDate = 0;
|
||||
endBidDate = 0;
|
||||
endCancellationDate = uint256(0) - 1; // "infinite" cancellation window
|
||||
token.safeTransfer(owner(), tokenSupply);
|
||||
emit Shutdown(msg.sender);
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Make force refund to bidders who can get tokens more than maximum allowed
|
||||
* @param _biddersForRefund Sorted list of unique bidders. Only bidders who must receive a refund
|
||||
*/
|
||||
function forceRefund(address payable[] calldata _biddersForRefund) external afterCancellationWindow {
|
||||
require(nextBidderToCheck != bidders.length, "Bidders have already been checked");
|
||||
|
||||
uint256 length = _biddersForRefund.length;
|
||||
require(length > 0, "Must be at least one bidder for a refund");
|
||||
|
||||
uint256 minNumberOfBidders = tokenSupply.divCeil(maxAllowableLockedTokens);
|
||||
if (bidders.length < minNumberOfBidders) {
|
||||
internalShutdown();
|
||||
return;
|
||||
}
|
||||
|
||||
address previousBidder = _biddersForRefund[0];
|
||||
uint256 minBid = workInfo[previousBidder].depositedETH;
|
||||
uint256 maxBid = minBid;
|
||||
|
||||
// get minimum and maximum bids
|
||||
for (uint256 i = 1; i < length; i++) {
|
||||
address bidder = _biddersForRefund[i];
|
||||
uint256 depositedETH = workInfo[bidder].depositedETH;
|
||||
require(bidder > previousBidder && depositedETH > 0, "Addresses must be an array of unique bidders");
|
||||
if (minBid > depositedETH) {
|
||||
minBid = depositedETH;
|
||||
} else if (maxBid < depositedETH) {
|
||||
maxBid = depositedETH;
|
||||
}
|
||||
previousBidder = bidder;
|
||||
}
|
||||
|
||||
uint256[] memory refunds = new uint256[](length);
|
||||
// first step - align at a minimum bid
|
||||
if (minBid != maxBid) {
|
||||
for (uint256 i = 0; i < length; i++) {
|
||||
address bidder = _biddersForRefund[i];
|
||||
WorkInfo storage info = workInfo[bidder];
|
||||
if (info.depositedETH > minBid) {
|
||||
refunds[i] = info.depositedETH - minBid;
|
||||
info.depositedETH = minBid;
|
||||
bonusETHSupply -= refunds[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
require(ethToTokens(minBid) > maxAllowableLockedTokens,
|
||||
"At least one of bidders has allowable bid");
|
||||
|
||||
// final bids adjustment (only for bonus part)
|
||||
// (min_whale_bid * token_supply - max_stake * eth_supply) / (token_supply - max_stake * n_whales)
|
||||
uint256 maxBonusTokens = maxAllowableLockedTokens - minAllowableLockedTokens;
|
||||
uint256 minBonusETH = minBid - minAllowedBid;
|
||||
uint256 bonusTokenSupply = tokenSupply - bidders.length * minAllowableLockedTokens;
|
||||
uint256 refundETH = minBonusETH.mul(bonusTokenSupply)
|
||||
.sub(maxBonusTokens.mul(bonusETHSupply))
|
||||
.divCeil(bonusTokenSupply - maxBonusTokens.mul(length));
|
||||
uint256 resultBid = minBid.sub(refundETH);
|
||||
bonusETHSupply -= length * refundETH;
|
||||
for (uint256 i = 0; i < length; i++) {
|
||||
address bidder = _biddersForRefund[i];
|
||||
WorkInfo storage info = workInfo[bidder];
|
||||
refunds[i] += refundETH;
|
||||
info.depositedETH = resultBid;
|
||||
}
|
||||
|
||||
// reset verification
|
||||
nextBidderToCheck = 0;
|
||||
|
||||
// save a refund
|
||||
for (uint256 i = 0; i < length; i++) {
|
||||
address bidder = _biddersForRefund[i];
|
||||
compensation[bidder] += refunds[i];
|
||||
emit ForceRefund(msg.sender, bidder, refunds[i]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Withdraw compensation after force refund
|
||||
*/
|
||||
function withdrawCompensation() external {
|
||||
uint256 refund = compensation[msg.sender];
|
||||
require(refund > 0, "There is no compensation");
|
||||
compensation[msg.sender] = 0;
|
||||
msg.sender.sendValue(refund);
|
||||
emit CompensationWithdrawn(msg.sender, refund);
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Check that the claimed tokens are within `maxAllowableLockedTokens` for all participants,
|
||||
* starting from the last point `nextBidderToCheck`
|
||||
* @dev Method stops working when the remaining gas is less than `_gasToSaveState`
|
||||
* and saves the state in `nextBidderToCheck`.
|
||||
* If all bidders have been checked then `nextBidderToCheck` will be equal to the length of the bidders array
|
||||
*/
|
||||
function verifyBiddingCorrectness(uint256 _gasToSaveState) external afterCancellationWindow returns (uint256) {
|
||||
require(nextBidderToCheck != bidders.length, "Bidders have already been checked");
|
||||
|
||||
// all participants bid with the same minimum amount of eth
|
||||
uint256 index = nextBidderToCheck;
|
||||
if (bonusETHSupply == 0) {
|
||||
require(tokenSupply / bidders.length <= maxAllowableLockedTokens, "Not enough bidders");
|
||||
index = bidders.length;
|
||||
}
|
||||
|
||||
uint256 maxBonusTokens = maxAllowableLockedTokens - minAllowableLockedTokens;
|
||||
uint256 bonusTokenSupply = tokenSupply - bidders.length * minAllowableLockedTokens;
|
||||
uint256 maxBidFromMaxStake = minAllowedBid + maxBonusTokens.mul(bonusETHSupply).div(bonusTokenSupply);
|
||||
|
||||
|
||||
while (index < bidders.length && gasleft() > _gasToSaveState) {
|
||||
address bidder = bidders[index];
|
||||
require(workInfo[bidder].depositedETH <= maxBidFromMaxStake, "Bid is greater than max allowable bid");
|
||||
index++;
|
||||
}
|
||||
|
||||
if (index != nextBidderToCheck) {
|
||||
emit BiddersChecked(msg.sender, nextBidderToCheck, index);
|
||||
nextBidderToCheck = index;
|
||||
}
|
||||
return nextBidderToCheck;
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Checks if claiming available
|
||||
*/
|
||||
function isClaimingAvailable() public view returns (bool) {
|
||||
return block.timestamp >= endCancellationDate &&
|
||||
nextBidderToCheck == bidders.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Claimed tokens will be deposited and locked as stake in the StakingEscrow contract.
|
||||
*/
|
||||
function claim() external returns (uint256 claimedTokens) {
|
||||
require(isClaimingAvailable(), "Claiming has not been enabled yet");
|
||||
WorkInfo storage info = workInfo[msg.sender];
|
||||
require(!info.claimed, "Tokens are already claimed");
|
||||
claimedTokens = ethToTokens(info.depositedETH);
|
||||
require(claimedTokens > 0, "Nothing to claim");
|
||||
|
||||
info.claimed = true;
|
||||
token.approve(address(escrow), claimedTokens);
|
||||
escrow.depositFromWorkLock(msg.sender, claimedTokens, stakingPeriods);
|
||||
info.completedWork = escrow.setWorkMeasurement(msg.sender, true);
|
||||
emit Claimed(msg.sender, claimedTokens);
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Get available refund for bidder
|
||||
*/
|
||||
function getAvailableRefund(address _bidder) public view returns (uint256) {
|
||||
WorkInfo storage info = workInfo[_bidder];
|
||||
// nothing to refund
|
||||
if (info.depositedETH == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint256 currentWork = escrow.getCompletedWork(_bidder);
|
||||
uint256 completedWork = currentWork.sub(info.completedWork);
|
||||
// no work that has been completed since last refund
|
||||
if (completedWork == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint256 refundETH = workToETH(completedWork, info.depositedETH);
|
||||
if (refundETH > info.depositedETH) {
|
||||
refundETH = info.depositedETH;
|
||||
}
|
||||
return refundETH;
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Refund ETH for the completed work
|
||||
*/
|
||||
function refund() external returns (uint256 refundETH) {
|
||||
WorkInfo storage info = workInfo[msg.sender];
|
||||
require(info.claimed, "Tokens must be claimed before refund");
|
||||
refundETH = getAvailableRefund(msg.sender);
|
||||
require(refundETH > 0, "Nothing to refund: there is no ETH to refund or no completed work");
|
||||
|
||||
if (refundETH == info.depositedETH) {
|
||||
escrow.setWorkMeasurement(msg.sender, false);
|
||||
}
|
||||
info.depositedETH = info.depositedETH.sub(refundETH);
|
||||
// convert refund back to work to eliminate potential rounding errors
|
||||
uint256 completedWork = ethToWork(refundETH, info.depositedETH);
|
||||
|
||||
info.completedWork = info.completedWork.add(completedWork);
|
||||
emit Refund(msg.sender, refundETH, completedWork);
|
||||
msg.sender.sendValue(refundETH);
|
||||
}
|
||||
}
|
|
@ -17,7 +17,7 @@ import "contracts/proxy/Upgradeable.sol";
|
|||
/**
|
||||
* @title PolicyManager
|
||||
* @notice Contract holds policy data and locks accrued policy fees
|
||||
* @dev |v6.2.1|
|
||||
* @dev |v6.1.3|
|
||||
*/
|
||||
contract PolicyManager is Upgradeable {
|
||||
using SafeERC20 for NuCypherToken;
|
||||
|
@ -108,37 +108,25 @@ contract PolicyManager is Upgradeable {
|
|||
// controlled overflow to get max int256
|
||||
int256 public constant DEFAULT_FEE_DELTA = int256((uint256(0) - 1) >> 1);
|
||||
|
||||
StakingEscrow public immutable escrow;
|
||||
uint32 public immutable secondsPerPeriod;
|
||||
|
||||
mapping (bytes16 => Policy) public policies;
|
||||
mapping (address => NodeInfo) public nodes;
|
||||
Range public feeRateRange;
|
||||
StakingEscrow public escrow;
|
||||
|
||||
/**
|
||||
* @notice Constructor sets either address of the escrow contract or seconds per period directly
|
||||
* @notice Constructor sets address of the escrow contract
|
||||
* @param _escrow Escrow contract
|
||||
* @param _secondsPerPeriod Seconds per period from StakingEscrow contract
|
||||
*/
|
||||
constructor(StakingEscrow _escrow, uint32 _secondsPerPeriod) {
|
||||
uint32 localSecondsPerPeriod = address(_escrow) != address(0) ? _escrow.secondsPerPeriod() : _secondsPerPeriod;
|
||||
constructor(StakingEscrow _escrow) {
|
||||
// if the input address is not the StakingEscrow then calling `secondsPerPeriod` will throw error
|
||||
uint32 localSecondsPerPeriod = _escrow.secondsPerPeriod();
|
||||
require(localSecondsPerPeriod > 0);
|
||||
secondsPerPeriod = localSecondsPerPeriod;
|
||||
escrow = _escrow;
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Sets address of the escrow contract
|
||||
* @param _escrow Escrow contract
|
||||
*/
|
||||
function setStakingEscrow(StakingEscrow _escrow) external onlyOwner {
|
||||
// StakingEscrow can be set only once
|
||||
require(address(escrow) == address(0));
|
||||
// if the input address is not the StakingEscrow then calling `secondsPerPeriod` will throw error
|
||||
require(secondsPerPeriod == _escrow.secondsPerPeriod());
|
||||
escrow = _escrow;
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Checks that sender is the StakingEscrow contract
|
||||
*/
|
||||
|
@ -731,7 +719,6 @@ contract PolicyManager is Upgradeable {
|
|||
/// @dev the `onlyWhileUpgrading` modifier works through a call to the parent `verifyState`
|
||||
function verifyState(address _testTarget) public override virtual {
|
||||
super.verifyState(_testTarget);
|
||||
require(address(delegateGet(_testTarget, this.escrow.selector)) == address(escrow));
|
||||
Range memory rangeToCheck = delegateGetFeeRateRange(_testTarget);
|
||||
require(feeRateRange.min == rangeToCheck.min &&
|
||||
feeRateRange.defaultValue == rangeToCheck.defaultValue &&
|
||||
|
@ -770,10 +757,6 @@ contract PolicyManager is Upgradeable {
|
|||
/// @dev the `onlyWhileUpgrading` modifier works through a call to the parent `finishUpgrade`
|
||||
function finishUpgrade(address _target) public override virtual {
|
||||
super.finishUpgrade(_target);
|
||||
StakingEscrow escrowAddress = PolicyManager(_target).escrow();
|
||||
if (address(escrowAddress) != address(0)) {
|
||||
escrow = escrowAddress;
|
||||
}
|
||||
// Create fake Policy and NodeInfo to use them in verifyState(address)
|
||||
Policy storage policy = policies[RESERVED_POLICY_ID];
|
||||
policy.sponsor = msg.sender;
|
||||
|
|
|
@ -41,6 +41,58 @@ interface WorkLockInterface {
|
|||
function token() external view returns (NuCypherToken);
|
||||
}
|
||||
|
||||
/**
|
||||
* @title StakingEscrowStub
|
||||
* @notice Stub is used to deploy main StakingEscrow after all other contract and make some variables immutable
|
||||
*/
|
||||
contract StakingEscrowStub is Upgradeable {
|
||||
using AdditionalMath for uint32;
|
||||
|
||||
NuCypherToken public immutable token;
|
||||
uint32 public immutable secondsPerPeriod;
|
||||
uint16 public immutable minLockedPeriods;
|
||||
uint256 public immutable minAllowableLockedTokens;
|
||||
uint256 public immutable maxAllowableLockedTokens;
|
||||
|
||||
/**
|
||||
* @notice Predefines some variables for use when deploying other contracts
|
||||
* @param _token Token contract
|
||||
* @param _minLockedPeriods Min amount of periods during which tokens can be locked
|
||||
* @param _minAllowableLockedTokens Min amount of tokens that can be locked
|
||||
* @param _maxAllowableLockedTokens Max amount of tokens that can be locked
|
||||
*/
|
||||
constructor(
|
||||
NuCypherToken _token,
|
||||
uint32 _hoursPerPeriod,
|
||||
uint16 _minLockedPeriods,
|
||||
uint256 _minAllowableLockedTokens,
|
||||
uint256 _maxAllowableLockedTokens
|
||||
) {
|
||||
require(_token.totalSupply() > 0 &&
|
||||
_hoursPerPeriod != 0 &&
|
||||
_minLockedPeriods > 1 &&
|
||||
_maxAllowableLockedTokens != 0);
|
||||
|
||||
token = _token;
|
||||
secondsPerPeriod = _hoursPerPeriod.mul32(1 hours);
|
||||
minLockedPeriods = _minLockedPeriods;
|
||||
minAllowableLockedTokens = _minAllowableLockedTokens;
|
||||
maxAllowableLockedTokens = _maxAllowableLockedTokens;
|
||||
}
|
||||
|
||||
/// @dev the `onlyWhileUpgrading` modifier works through a call to the parent `verifyState`
|
||||
function verifyState(address _testTarget) public override virtual {
|
||||
super.verifyState(_testTarget);
|
||||
|
||||
// we have to use real values even though this is a stub
|
||||
require(address(delegateGet(_testTarget, this.token.selector)) == address(token));
|
||||
require(uint32(delegateGet(_testTarget, this.secondsPerPeriod.selector)) == secondsPerPeriod);
|
||||
require(uint16(delegateGet(_testTarget, this.minLockedPeriods.selector)) == minLockedPeriods);
|
||||
require(delegateGet(_testTarget, this.minAllowableLockedTokens.selector) == minAllowableLockedTokens);
|
||||
require(delegateGet(_testTarget, this.maxAllowableLockedTokens.selector) == maxAllowableLockedTokens);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @title StakingEscrow
|
||||
|
@ -156,6 +208,9 @@ contract StakingEscrow is Issuer, IERC900History {
|
|||
/**
|
||||
* @notice Constructor sets address of token contract and coefficients for minting
|
||||
* @param _token Token contract
|
||||
* @param _policyManager Policy Manager contract
|
||||
* @param _adjudicator Adjudicator contract
|
||||
* @param _workLock WorkLock contract. Zero address if there is no WorkLock
|
||||
* @param _hoursPerPeriod Size of period in hours
|
||||
* @param _issuanceDecayCoefficient (d) Coefficient which modifies the rate at which the maximum issuance decays,
|
||||
* only applicable to Phase 2. d = 365 * half-life / LOG2 where default half-life = 2.
|
||||
|
@ -179,12 +234,12 @@ contract StakingEscrow is Issuer, IERC900History {
|
|||
* @param _minAllowableLockedTokens Min amount of tokens that can be locked
|
||||
* @param _maxAllowableLockedTokens Max amount of tokens that can be locked
|
||||
* @param _minWorkerPeriods Min amount of periods while a worker can't be changed
|
||||
* @param _policyManager Policy Manager contract
|
||||
* @param _adjudicator Adjudicator contract
|
||||
* @param _workLock WorkLock contract. Zero address if there is no WorkLock
|
||||
*/
|
||||
constructor(
|
||||
NuCypherToken _token,
|
||||
PolicyManagerInterface _policyManager,
|
||||
AdjudicatorInterface _adjudicator,
|
||||
WorkLockInterface _workLock,
|
||||
uint32 _hoursPerPeriod,
|
||||
uint256 _issuanceDecayCoefficient,
|
||||
uint256 _lockDurationCoefficient1,
|
||||
|
@ -195,10 +250,7 @@ contract StakingEscrow is Issuer, IERC900History {
|
|||
uint16 _minLockedPeriods,
|
||||
uint256 _minAllowableLockedTokens,
|
||||
uint256 _maxAllowableLockedTokens,
|
||||
uint16 _minWorkerPeriods,
|
||||
PolicyManagerInterface _policyManager,
|
||||
AdjudicatorInterface _adjudicator,
|
||||
WorkLockInterface _workLock
|
||||
uint16 _minWorkerPeriods
|
||||
)
|
||||
Issuer(
|
||||
_token,
|
||||
|
@ -236,32 +288,6 @@ contract StakingEscrow is Issuer, IERC900History {
|
|||
_;
|
||||
}
|
||||
|
||||
//------------------------Initialization------------------------
|
||||
/**
|
||||
* @notice Set policy manager, worklock and adjudicator addresses
|
||||
*/
|
||||
// function setContracts(
|
||||
// PolicyManagerInterface _policyManager,
|
||||
// AdjudicatorInterface _adjudicator,
|
||||
// WorkLockInterface _workLock
|
||||
// )
|
||||
// external onlyOwner
|
||||
// {
|
||||
// // Policy manager can be set only once
|
||||
// require(address(policyManager) == address(0) &&
|
||||
// address(adjudicator) == address(0) &&
|
||||
// address(workLock) == address(0)
|
||||
// );
|
||||
// // This escrow must be the escrow for the new policy manager
|
||||
// require(_policyManager.escrow() == address(this) &&
|
||||
// _adjudicator.escrow() == address(this) &&
|
||||
// (address(_workLock) == address(0) || _workLock.escrow() == address(this))
|
||||
// );
|
||||
// policyManager = _policyManager;
|
||||
// adjudicator = _adjudicator;
|
||||
// workLock = _workLock;
|
||||
// }
|
||||
|
||||
//------------------------Main getters------------------------
|
||||
/**
|
||||
* @notice Get all tokens belonging to the staker
|
||||
|
|
|
@ -43,6 +43,7 @@ contract WorkLock is Ownable {
|
|||
uint256 private constant MAX_ETH_SUPPLY = 2e10 ether;
|
||||
|
||||
NuCypherToken public immutable token;
|
||||
StakingEscrow public immutable escrow;
|
||||
|
||||
/*
|
||||
* @dev WorkLock calculations:
|
||||
|
@ -56,6 +57,9 @@ contract WorkLock is Ownable {
|
|||
uint256 public immutable boostingRefund;
|
||||
uint256 public immutable minAllowedBid;
|
||||
uint16 public immutable stakingPeriods;
|
||||
// copy from the escrow contract
|
||||
uint256 public immutable maxAllowableLockedTokens;
|
||||
uint256 public immutable minAllowableLockedTokens;
|
||||
|
||||
uint256 public tokenSupply;
|
||||
uint256 public startBidDate;
|
||||
|
@ -70,11 +74,6 @@ contract WorkLock is Ownable {
|
|||
// if value == bidders.length then WorkLock is fully checked
|
||||
uint256 public nextBidderToCheck;
|
||||
|
||||
StakingEscrow public escrow;
|
||||
// copy from the escrow contract
|
||||
uint256 public maxAllowableLockedTokens;
|
||||
uint256 public minAllowableLockedTokens;
|
||||
|
||||
/**
|
||||
* @dev Checks timestamp regarding cancellation window
|
||||
*/
|
||||
|
@ -87,6 +86,7 @@ contract WorkLock is Ownable {
|
|||
|
||||
/**
|
||||
* @param _token Token contract
|
||||
* @param _escrow Escrow contract
|
||||
* @param _startBidDate Timestamp when bidding starts
|
||||
* @param _endBidDate Timestamp when bidding will end
|
||||
* @param _endCancellationDate Timestamp when cancellation will ends
|
||||
|
@ -96,6 +96,7 @@ contract WorkLock is Ownable {
|
|||
*/
|
||||
constructor(
|
||||
NuCypherToken _token,
|
||||
StakingEscrow _escrow,
|
||||
uint256 _startBidDate,
|
||||
uint256 _endBidDate,
|
||||
uint256 _endCancellationDate,
|
||||
|
@ -105,38 +106,27 @@ contract WorkLock is Ownable {
|
|||
) {
|
||||
uint256 totalSupply = _token.totalSupply();
|
||||
require(totalSupply > 0 && // token contract is deployed and accessible
|
||||
_stakingPeriods > 0 && // staking periods was set
|
||||
_escrow.secondsPerPeriod() > 0 && // escrow contract is deployed and accessible
|
||||
_escrow.token() == _token && // same token address for worklock and escrow
|
||||
_endBidDate > _startBidDate && // bidding period lasts some time
|
||||
_endBidDate > block.timestamp && // there is time to make a bid
|
||||
_endCancellationDate >= _endBidDate && // cancellation window includes bidding
|
||||
_minAllowedBid > 0 && // min allowed bid was set
|
||||
_boostingRefund > 0); // boosting coefficient was set
|
||||
_boostingRefund > 0 && // boosting coefficient was set
|
||||
_stakingPeriods >= _escrow.minLockedPeriods()); // staking duration is consistent with escrow contract
|
||||
// worst case for `ethToWork()` and `workToETH()`,
|
||||
// when ethSupply == MAX_ETH_SUPPLY and tokenSupply == totalSupply
|
||||
require(MAX_ETH_SUPPLY * totalSupply * SLOWING_REFUND / MAX_ETH_SUPPLY / totalSupply == SLOWING_REFUND &&
|
||||
MAX_ETH_SUPPLY * totalSupply * _boostingRefund / MAX_ETH_SUPPLY / totalSupply == _boostingRefund);
|
||||
|
||||
token = _token;
|
||||
escrow = _escrow;
|
||||
startBidDate = _startBidDate;
|
||||
endBidDate = _endBidDate;
|
||||
endCancellationDate = _endCancellationDate;
|
||||
boostingRefund = _boostingRefund;
|
||||
stakingPeriods = _stakingPeriods;
|
||||
minAllowedBid = _minAllowedBid;
|
||||
}
|
||||
|
||||
/**
|
||||
* @notice Sets address of the escrow contract
|
||||
* @param _escrow Escrow contract
|
||||
*/
|
||||
function setStakingEscrow(StakingEscrow _escrow) external onlyOwner {
|
||||
// StakingEscrow can be set only once
|
||||
require(address(escrow) == address(0));
|
||||
require(_escrow.secondsPerPeriod() > 0 && // escrow contract is deployed and accessible
|
||||
_escrow.token() == token && // same token address for worklock and escrow
|
||||
stakingPeriods >= _escrow.minLockedPeriods() // staking duration is consistent with escrow contract
|
||||
);
|
||||
escrow = _escrow;
|
||||
maxAllowableLockedTokens = _escrow.maxAllowableLockedTokens();
|
||||
minAllowableLockedTokens = _escrow.minAllowableLockedTokens();
|
||||
}
|
||||
|
|
|
@ -454,8 +454,9 @@ def rollback(general_config, actor_options):
|
|||
@option_confirmations
|
||||
@click.option('--mode',
|
||||
help="Deploy a contract following all steps ('full'), up to idle status ('idle'), "
|
||||
"just initialization step ('init', only for StakingEscrow) "
|
||||
"or just the bare contract ('bare'). Defaults to 'full'",
|
||||
type=click.Choice(['full', 'idle', 'bare'], case_sensitive=False),
|
||||
type=click.Choice(['full', 'idle', 'bare', 'init'], case_sensitive=False),
|
||||
default='full'
|
||||
)
|
||||
@click.option('--activate', help="Activate a contract that is in idle mode", is_flag=True)
|
||||
|
|
|
@ -18,7 +18,8 @@ along with nucypher. If not, see <https://www.gnu.org/licenses/>.
|
|||
import pytest
|
||||
|
||||
from nucypher.blockchain.eth.deployers import (AdjudicatorDeployer, NucypherTokenDeployer, PolicyManagerDeployer,
|
||||
StakingEscrowDeployer, StakingInterfaceDeployer, WorklockDeployer)
|
||||
StakingEscrowDeployer, StakingInterfaceDeployer)
|
||||
from constant_sorrow.constants import (FULL, INIT)
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
|
@ -29,20 +30,16 @@ def token_deployer(testerchain, test_registry):
|
|||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def worklock_deployer(token_deployer,
|
||||
testerchain,
|
||||
test_registry,
|
||||
token_economics):
|
||||
def staking_escrow_stub_deployer(testerchain, token_deployer, test_registry):
|
||||
token_deployer.deploy()
|
||||
worklock_deployer = WorklockDeployer(registry=test_registry,
|
||||
economics=token_economics,
|
||||
deployer_address=testerchain.etherbase_account)
|
||||
return worklock_deployer
|
||||
staking_escrow_deployer = StakingEscrowDeployer(registry=test_registry,
|
||||
deployer_address=testerchain.etherbase_account)
|
||||
return staking_escrow_deployer
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def policy_manager_deployer(worklock_deployer, testerchain, test_registry):
|
||||
worklock_deployer.deploy()
|
||||
def policy_manager_deployer(staking_escrow_stub_deployer, testerchain, test_registry):
|
||||
staking_escrow_stub_deployer.deploy(deployment_mode=INIT)
|
||||
policy_manager_deployer = PolicyManagerDeployer(registry=test_registry,
|
||||
deployer_address=testerchain.etherbase_account)
|
||||
return policy_manager_deployer
|
||||
|
@ -66,7 +63,6 @@ def staking_escrow_deployer(testerchain, adjudicator_deployer, test_registry):
|
|||
|
||||
@pytest.fixture(scope="module")
|
||||
def staking_interface_deployer(staking_escrow_deployer, testerchain, test_registry):
|
||||
staking_escrow_deployer.deploy()
|
||||
staking_interface_deployer = StakingInterfaceDeployer(registry=test_registry,
|
||||
deployer_address=testerchain.etherbase_account)
|
||||
return staking_interface_deployer
|
||||
|
|
|
@ -35,6 +35,11 @@ def test_adjudicator_deployer(testerchain,
|
|||
token_deployer = NucypherTokenDeployer(deployer_address=origin, registry=test_registry)
|
||||
token_deployer.deploy()
|
||||
|
||||
staking_escrow_deployer = StakingEscrowDeployer(deployer_address=origin, registry=test_registry)
|
||||
|
||||
staking_escrow_deployer.deploy()
|
||||
staking_agent = staking_escrow_deployer.make_agent() # 2 Staker Escrow
|
||||
|
||||
deployer = AdjudicatorDeployer(deployer_address=origin, registry=test_registry)
|
||||
deployment_receipts = deployer.deploy(progress=deployment_progress)
|
||||
|
||||
|
@ -48,6 +53,8 @@ def test_adjudicator_deployer(testerchain,
|
|||
adjudicator_agent = deployer.make_agent()
|
||||
|
||||
# Check default Adjudicator deployment parameters
|
||||
assert staking_escrow_deployer.deployer_address != staking_agent.contract_address
|
||||
assert adjudicator_agent.staking_escrow_contract == staking_agent.contract_address
|
||||
assert adjudicator_agent.hash_algorithm == token_economics.hash_algorithm
|
||||
assert adjudicator_agent.base_penalty == token_economics.base_penalty
|
||||
assert adjudicator_agent.penalty_history_coefficient == token_economics.penalty_history_coefficient
|
||||
|
|
|
@ -50,6 +50,20 @@ def test_deploy_idle_network(testerchain, deployment_progress, test_registry):
|
|||
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, deployer_address=origin)
|
||||
assert staking_escrow_deployer.deployer_address == origin
|
||||
|
||||
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)
|
||||
assert not staking_escrow_deployer.is_deployed()
|
||||
|
||||
#
|
||||
# Policy Manager
|
||||
#
|
||||
|
|
|
@ -51,6 +51,23 @@ def test_deploy_ethereum_contracts(testerchain,
|
|||
assert len(another_token_agent.contract_address) == 42
|
||||
assert another_token_agent.contract_address == token_deployer.contract_address == token_agent.contract_address
|
||||
|
||||
#
|
||||
# StakingEscrowStub
|
||||
#
|
||||
staking_escrow_deployer = StakingEscrowDeployer(
|
||||
registry=test_registry,
|
||||
deployer_address=origin)
|
||||
assert staking_escrow_deployer.deployer_address == origin
|
||||
|
||||
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)
|
||||
assert not staking_escrow_deployer.is_deployed()
|
||||
assert len(staking_escrow_deployer.contract_address) == 42
|
||||
|
||||
|
||||
#
|
||||
# Policy Manager
|
||||
#
|
||||
|
@ -76,6 +93,7 @@ def test_deploy_ethereum_contracts(testerchain,
|
|||
assert len(another_policy_agent.contract_address) == 42
|
||||
assert another_policy_agent.contract_address == policy_manager_deployer.contract_address == policy_agent.contract_address
|
||||
|
||||
|
||||
#
|
||||
# Adjudicator
|
||||
#
|
||||
|
@ -101,12 +119,6 @@ def test_deploy_ethereum_contracts(testerchain,
|
|||
assert len(another_adjudicator_agent.contract_address) == 42
|
||||
assert another_adjudicator_agent.contract_address == adjudicator_deployer.contract_address == adjudicator_agent.contract_address
|
||||
|
||||
# overall deployment steps must match aggregated individual expected number of steps
|
||||
all_deployment_transactions = token_deployer.deployment_steps + policy_manager_deployer.deployment_steps + \
|
||||
adjudicator_deployer.deployment_steps
|
||||
assert deployment_progress.num_steps == len(all_deployment_transactions)
|
||||
|
||||
#
|
||||
# StakingEscrow
|
||||
#
|
||||
staking_escrow_deployer = StakingEscrowDeployer(
|
||||
|
@ -118,7 +130,7 @@ def test_deploy_ethereum_contracts(testerchain,
|
|||
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)
|
||||
staking_escrow_deployer.deploy(progress=deployment_progress, deployment_mode=constants.FULL)
|
||||
assert staking_escrow_deployer.is_deployed()
|
||||
assert len(staking_escrow_deployer.contract_address) == 42
|
||||
|
||||
|
@ -129,3 +141,9 @@ def test_deploy_ethereum_contracts(testerchain,
|
|||
another_staking_agent = staking_escrow_deployer.make_agent()
|
||||
assert len(another_staking_agent.contract_address) == 42
|
||||
assert another_staking_agent.contract_address == staking_escrow_deployer.contract_address == staking_agent.contract_address
|
||||
|
||||
# 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
|
||||
assert deployment_progress.num_steps == len(all_deployment_transactions) #
|
||||
|
|
|
@ -14,13 +14,14 @@ 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/>.
|
||||
"""
|
||||
from constant_sorrow import constants
|
||||
|
||||
from nucypher.blockchain.eth.agents import ContractAgency, PolicyManagerAgent, StakingEscrowAgent
|
||||
from nucypher.blockchain.eth.constants import POLICY_MANAGER_CONTRACT_NAME
|
||||
from nucypher.blockchain.eth.deployers import (DispatcherDeployer, PolicyManagerDeployer)
|
||||
|
||||
|
||||
def test_policy_manager_deployment(policy_manager_deployer, deployment_progress):
|
||||
def test_policy_manager_deployment(policy_manager_deployer, staking_escrow_stub_deployer, deployment_progress):
|
||||
|
||||
assert policy_manager_deployer.contract_name == POLICY_MANAGER_CONTRACT_NAME
|
||||
|
||||
|
@ -33,6 +34,9 @@ def test_policy_manager_deployment(policy_manager_deployer, deployment_progress)
|
|||
for step_title in steps:
|
||||
assert deployment_receipts[step_title]['status'] == 1
|
||||
|
||||
staking_escrow_address = policy_manager_deployer.contract.functions.escrow().call()
|
||||
assert staking_escrow_stub_deployer.contract_address == staking_escrow_address
|
||||
|
||||
|
||||
def test_make_agent(policy_manager_deployer, test_registry):
|
||||
|
||||
|
@ -47,11 +51,6 @@ def test_make_agent(policy_manager_deployer, test_registry):
|
|||
assert policy_agent.contract_address == some_policy_agent.contract_address
|
||||
|
||||
|
||||
def test_deployment_parameters(policy_manager_deployer, token_economics):
|
||||
seconds_per_period = token_economics.seconds_per_period
|
||||
assert seconds_per_period == policy_manager_deployer.contract.functions.secondsPerPeriod().call()
|
||||
|
||||
|
||||
def test_policy_manager_has_dispatcher(policy_manager_deployer, testerchain, test_registry):
|
||||
|
||||
# Let's get the "bare" PolicyManager contract (i.e., unwrapped, no dispatcher)
|
||||
|
|
|
@ -17,6 +17,7 @@ along with nucypher. If not, see <https://www.gnu.org/licenses/>.
|
|||
|
||||
|
||||
import pytest
|
||||
from constant_sorrow import constants
|
||||
|
||||
from nucypher.blockchain.eth.deployers import (AdjudicatorDeployer, NucypherTokenDeployer, PolicyManagerDeployer,
|
||||
PreallocationEscrowDeployer, StakingEscrowDeployer,
|
||||
|
@ -37,6 +38,9 @@ def test_staking_interface_deployer(testerchain, deployment_progress, test_regis
|
|||
token_deployer = NucypherTokenDeployer(deployer_address=origin, registry=test_registry)
|
||||
token_deployer.deploy()
|
||||
|
||||
staking_escrow_deployer = StakingEscrowDeployer(deployer_address=origin, registry=test_registry)
|
||||
staking_escrow_deployer.deploy()
|
||||
|
||||
policy_manager_deployer = PolicyManagerDeployer(deployer_address=origin, registry=test_registry)
|
||||
policy_manager_deployer.deploy()
|
||||
|
||||
|
@ -44,7 +48,7 @@ def test_staking_interface_deployer(testerchain, deployment_progress, test_regis
|
|||
adjudicator_deployer.deploy()
|
||||
|
||||
staking_escrow_deployer = StakingEscrowDeployer(deployer_address=origin, registry=test_registry)
|
||||
staking_escrow_deployer.deploy()
|
||||
staking_escrow_deployer.deploy(deployment_mode=constants.FULL)
|
||||
|
||||
#
|
||||
# Test
|
||||
|
|
|
@ -14,6 +14,7 @@ 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/>.
|
||||
"""
|
||||
from constant_sorrow import constants
|
||||
|
||||
from constant_sorrow.constants import BARE
|
||||
|
||||
|
@ -22,10 +23,10 @@ from nucypher.blockchain.eth.deployers import (DispatcherDeployer, StakingEscrow
|
|||
|
||||
|
||||
def test_staking_escrow_deployment(staking_escrow_deployer, deployment_progress):
|
||||
deployment_receipts = staking_escrow_deployer.deploy(progress=deployment_progress)
|
||||
deployment_receipts = staking_escrow_deployer.deploy(progress=deployment_progress, deployment_mode=constants.FULL)
|
||||
|
||||
# deployment steps must match expected number of steps
|
||||
assert deployment_progress.num_steps == len(staking_escrow_deployer.deployment_steps) == len(deployment_receipts) == 7
|
||||
assert deployment_progress.num_steps == len(staking_escrow_deployer.deployment_steps) == len(deployment_receipts) == 4
|
||||
|
||||
for step in staking_escrow_deployer.deployment_steps:
|
||||
assert deployment_receipts[step]['status'] == 1
|
||||
|
|
|
@ -24,7 +24,25 @@ from nucypher.blockchain.eth.constants import WORKLOCK_CONTRACT_NAME
|
|||
from nucypher.blockchain.eth.deployers import WorklockDeployer
|
||||
|
||||
|
||||
@pytest.fixture(scope='module')
|
||||
def baseline_deployment(adjudicator_deployer):
|
||||
adjudicator_deployer.deploy()
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def worklock_deployer(baseline_deployment,
|
||||
testerchain,
|
||||
test_registry,
|
||||
token_economics):
|
||||
worklock_deployer = WorklockDeployer(registry=test_registry,
|
||||
economics=token_economics,
|
||||
deployer_address=testerchain.etherbase_account)
|
||||
return worklock_deployer
|
||||
|
||||
|
||||
def test_worklock_deployment(worklock_deployer,
|
||||
baseline_deployment,
|
||||
staking_escrow_stub_deployer,
|
||||
deployment_progress,
|
||||
test_registry,
|
||||
testerchain):
|
||||
|
@ -41,6 +59,10 @@ def test_worklock_deployment(worklock_deployer,
|
|||
for step_title in steps:
|
||||
assert deployment_receipts[step_title]['status'] == 1
|
||||
|
||||
# Ensure the correct staking escrow address is set
|
||||
staking_escrow_address = worklock_deployer.contract.functions.escrow().call()
|
||||
assert staking_escrow_stub_deployer.contract_address == staking_escrow_address
|
||||
|
||||
|
||||
def test_make_agent(worklock_deployer, test_registry):
|
||||
|
||||
|
|
|
@ -93,7 +93,7 @@ def test_upgrade_contracts(click_runner, test_registry_source_manager, test_regi
|
|||
#
|
||||
|
||||
# Check the existing state of the registry before the meat and potatoes
|
||||
expected_enrollments = 10
|
||||
expected_enrollments = 11
|
||||
with open(registry_filepath, 'r') as file:
|
||||
raw_registry_data = file.read()
|
||||
registry_data = json.loads(raw_registry_data)
|
||||
|
|
|
@ -30,7 +30,7 @@ from nucypher.blockchain.eth.constants import (
|
|||
DISPATCHER_CONTRACT_NAME,
|
||||
NUCYPHER_TOKEN_CONTRACT_NAME,
|
||||
POLICY_MANAGER_CONTRACT_NAME,
|
||||
STAKING_ESCROW_CONTRACT_NAME
|
||||
STAKING_ESCROW_CONTRACT_NAME, STAKING_ESCROW_STUB_CONTRACT_NAME
|
||||
)
|
||||
from nucypher.blockchain.eth.deployers import StakingEscrowDeployer, StakingInterfaceDeployer
|
||||
from nucypher.blockchain.eth.registry import InMemoryContractRegistry, LocalContractRegistry
|
||||
|
@ -286,7 +286,21 @@ def test_manual_deployment_of_idle_network(click_runner):
|
|||
deployed_contracts = [NUCYPHER_TOKEN_CONTRACT_NAME]
|
||||
assert list(new_registry.enrolled_names) == deployed_contracts
|
||||
|
||||
# 2. Deploy PolicyManager
|
||||
# 2. Deploy StakingEscrow in INIT mode
|
||||
command = ('contracts',
|
||||
'--contract-name', STAKING_ESCROW_CONTRACT_NAME,
|
||||
'--mode', 'init',
|
||||
'--provider', TEST_PROVIDER_URI,
|
||||
'--network', TEMPORARY_DOMAIN,
|
||||
'--registry-infile', ALTERNATE_REGISTRY_FILEPATH_2)
|
||||
|
||||
result = click_runner.invoke(deploy, command, input=user_input, catch_exceptions=False)
|
||||
assert result.exit_code == 0
|
||||
|
||||
deployed_contracts.extend([STAKING_ESCROW_STUB_CONTRACT_NAME, DISPATCHER_CONTRACT_NAME])
|
||||
assert list(new_registry.enrolled_names) == deployed_contracts
|
||||
|
||||
# 3. Deploy PolicyManager
|
||||
command = ('contracts',
|
||||
'--contract-name', POLICY_MANAGER_CONTRACT_NAME,
|
||||
'--provider', TEST_PROVIDER_URI,
|
||||
|
@ -299,7 +313,7 @@ def test_manual_deployment_of_idle_network(click_runner):
|
|||
deployed_contracts.extend([POLICY_MANAGER_CONTRACT_NAME, DISPATCHER_CONTRACT_NAME])
|
||||
assert list(new_registry.enrolled_names) == deployed_contracts
|
||||
|
||||
# 3. Deploy Adjudicator
|
||||
# 4. Deploy Adjudicator
|
||||
command = ('contracts',
|
||||
'--contract-name', ADJUDICATOR_CONTRACT_NAME,
|
||||
'--provider', TEST_PROVIDER_URI,
|
||||
|
@ -312,7 +326,7 @@ def test_manual_deployment_of_idle_network(click_runner):
|
|||
deployed_contracts.extend([ADJUDICATOR_CONTRACT_NAME, DISPATCHER_CONTRACT_NAME])
|
||||
assert list(new_registry.enrolled_names) == deployed_contracts
|
||||
|
||||
# 4. Deploy StakingEscrow in IDLE mode
|
||||
# 5. Deploy StakingEscrow in IDLE mode
|
||||
command = ('contracts',
|
||||
'--contract-name', STAKING_ESCROW_CONTRACT_NAME,
|
||||
'--mode', 'idle',
|
||||
|
@ -323,10 +337,10 @@ def test_manual_deployment_of_idle_network(click_runner):
|
|||
result = click_runner.invoke(deploy, command, input=user_input, catch_exceptions=False)
|
||||
assert result.exit_code == 0
|
||||
|
||||
deployed_contracts.extend([STAKING_ESCROW_CONTRACT_NAME, DISPATCHER_CONTRACT_NAME])
|
||||
deployed_contracts.extend([STAKING_ESCROW_CONTRACT_NAME])
|
||||
assert list(new_registry.enrolled_names) == deployed_contracts
|
||||
|
||||
# 5. Activate StakingEscrow
|
||||
# 6. Activate StakingEscrow
|
||||
command = ('contracts',
|
||||
'--contract-name', STAKING_ESCROW_CONTRACT_NAME,
|
||||
'--activate',
|
||||
|
|
|
@ -12,7 +12,8 @@ import "contracts/StakingEscrow.sol";
|
|||
*/
|
||||
contract PolicyManagerBad is PolicyManager {
|
||||
|
||||
constructor(StakingEscrow _escrow, uint32 _secondsPerPeriod) PolicyManager(_escrow, _secondsPerPeriod) {}
|
||||
constructor(StakingEscrow _escrow) PolicyManager(_escrow) {
|
||||
}
|
||||
|
||||
function getNodeFeeDelta(address, uint16) public view override returns (int256) {}
|
||||
|
||||
|
@ -26,7 +27,8 @@ contract PolicyManagerV2Mock is PolicyManager {
|
|||
|
||||
uint256 public valueToCheck;
|
||||
|
||||
constructor(StakingEscrow _escrow, uint32 _secondsPerPeriod) PolicyManager(_escrow, _secondsPerPeriod) {}
|
||||
constructor(StakingEscrow _escrow) PolicyManager(_escrow) {
|
||||
}
|
||||
|
||||
function setValueToCheck(uint256 _valueToCheck) public {
|
||||
valueToCheck = _valueToCheck;
|
||||
|
@ -142,7 +144,8 @@ contract StakingEscrowForPolicyMock {
|
|||
*/
|
||||
contract ExtendedPolicyManager is PolicyManager {
|
||||
|
||||
constructor(StakingEscrow _escrow, uint32 _secondsPerPeriod) PolicyManager(_escrow, _secondsPerPeriod) {}
|
||||
constructor(StakingEscrow _escrow) PolicyManager(_escrow) {
|
||||
}
|
||||
|
||||
function setNodeFeeDelta(address _node, uint16 _period, int256 _value) external {
|
||||
NodeInfo storage node = nodes[_node];
|
||||
|
|
|
@ -14,6 +14,9 @@ contract EnhancedStakingEscrow is StakingEscrow {
|
|||
|
||||
constructor(
|
||||
NuCypherToken _token,
|
||||
PolicyManagerInterface _policyManager,
|
||||
AdjudicatorInterface _adjudicator,
|
||||
WorkLockInterface _workLock,
|
||||
uint32 _hoursPerPeriod,
|
||||
uint256 _issuanceDecayCoefficient,
|
||||
uint256 _lockDurationCoefficient1,
|
||||
|
@ -24,13 +27,13 @@ contract EnhancedStakingEscrow is StakingEscrow {
|
|||
uint16 _minLockedPeriods,
|
||||
uint256 _minAllowableLockedTokens,
|
||||
uint256 _maxAllowableLockedTokens,
|
||||
uint16 _minWorkerPeriods,
|
||||
PolicyManagerInterface _policyManager,
|
||||
AdjudicatorInterface _adjudicator,
|
||||
WorkLockInterface _workLock
|
||||
uint16 _minWorkerPeriods
|
||||
)
|
||||
StakingEscrow(
|
||||
_token,
|
||||
_policyManager,
|
||||
_adjudicator,
|
||||
_workLock,
|
||||
_hoursPerPeriod,
|
||||
_issuanceDecayCoefficient,
|
||||
_lockDurationCoefficient1,
|
||||
|
@ -41,10 +44,7 @@ contract EnhancedStakingEscrow is StakingEscrow {
|
|||
_minLockedPeriods,
|
||||
_minAllowableLockedTokens,
|
||||
_maxAllowableLockedTokens,
|
||||
_minWorkerPeriods,
|
||||
_policyManager,
|
||||
_adjudicator,
|
||||
_workLock
|
||||
_minWorkerPeriods
|
||||
)
|
||||
{
|
||||
}
|
||||
|
@ -74,6 +74,9 @@ contract StakingEscrowBad is StakingEscrow {
|
|||
|
||||
constructor(
|
||||
NuCypherToken _token,
|
||||
PolicyManagerInterface _policyManager,
|
||||
AdjudicatorInterface _adjudicator,
|
||||
WorkLockInterface _workLock,
|
||||
uint32 _hoursPerPeriod,
|
||||
uint256 _issuanceDecayCoefficient,
|
||||
uint256 _lockDurationCoefficient1,
|
||||
|
@ -84,13 +87,13 @@ contract StakingEscrowBad is StakingEscrow {
|
|||
uint16 _minLockedPeriods,
|
||||
uint256 _minAllowableLockedTokens,
|
||||
uint256 _maxAllowableLockedTokens,
|
||||
uint16 _minWorkerPeriods,
|
||||
PolicyManagerInterface _policyManager,
|
||||
AdjudicatorInterface _adjudicator,
|
||||
WorkLockInterface _workLock
|
||||
uint16 _minWorkerPeriods
|
||||
)
|
||||
StakingEscrow(
|
||||
_token,
|
||||
_policyManager,
|
||||
_adjudicator,
|
||||
_workLock,
|
||||
_hoursPerPeriod,
|
||||
_issuanceDecayCoefficient,
|
||||
_lockDurationCoefficient1,
|
||||
|
@ -101,10 +104,7 @@ contract StakingEscrowBad is StakingEscrow {
|
|||
_minLockedPeriods,
|
||||
_minAllowableLockedTokens,
|
||||
_maxAllowableLockedTokens,
|
||||
_minWorkerPeriods,
|
||||
_policyManager,
|
||||
_adjudicator,
|
||||
_workLock
|
||||
_minWorkerPeriods
|
||||
)
|
||||
{
|
||||
}
|
||||
|
@ -123,6 +123,9 @@ contract StakingEscrowV2Mock is StakingEscrow {
|
|||
|
||||
constructor(
|
||||
NuCypherToken _token,
|
||||
PolicyManagerInterface _policyManager,
|
||||
AdjudicatorInterface _adjudicator,
|
||||
WorkLockInterface _workLock,
|
||||
uint32 _hoursPerPeriod,
|
||||
uint256 _issuanceDecayCoefficient,
|
||||
uint256 _lockDurationCoefficient1,
|
||||
|
@ -134,13 +137,13 @@ contract StakingEscrowV2Mock is StakingEscrow {
|
|||
uint256 _minAllowableLockedTokens,
|
||||
uint256 _maxAllowableLockedTokens,
|
||||
uint16 _minWorkerPeriods,
|
||||
PolicyManagerInterface _policyManager,
|
||||
AdjudicatorInterface _adjudicator,
|
||||
WorkLockInterface _workLock,
|
||||
uint256 _valueToCheck
|
||||
)
|
||||
StakingEscrow(
|
||||
_token,
|
||||
_policyManager,
|
||||
_adjudicator,
|
||||
_workLock,
|
||||
_hoursPerPeriod,
|
||||
_issuanceDecayCoefficient,
|
||||
_lockDurationCoefficient1,
|
||||
|
@ -151,10 +154,7 @@ contract StakingEscrowV2Mock is StakingEscrow {
|
|||
_minLockedPeriods,
|
||||
_minAllowableLockedTokens,
|
||||
_maxAllowableLockedTokens,
|
||||
_minWorkerPeriods,
|
||||
_policyManager,
|
||||
_adjudicator,
|
||||
_workLock
|
||||
_minWorkerPeriods
|
||||
)
|
||||
{
|
||||
valueToCheck = _valueToCheck;
|
||||
|
|
|
@ -70,8 +70,20 @@ def token(token_economics, deploy_contract):
|
|||
|
||||
|
||||
@pytest.fixture(scope='module')
|
||||
def policy_manager_bare(testerchain, token_economics, deploy_contract):
|
||||
contract, _ = deploy_contract('PolicyManager', NULL_ADDRESS, token_economics.seconds_per_period)
|
||||
def escrow_dispatcher(testerchain, token, token_economics, deploy_contract):
|
||||
escrow_stub, _ = deploy_contract('StakingEscrowStub',
|
||||
token.address,
|
||||
token_economics.hours_per_period,
|
||||
token_economics.minimum_locked_periods,
|
||||
token_economics.minimum_allowed_locked,
|
||||
token_economics.maximum_allowed_locked)
|
||||
dispatcher, _ = deploy_contract('Dispatcher', escrow_stub.address)
|
||||
return dispatcher
|
||||
|
||||
|
||||
@pytest.fixture(scope='module')
|
||||
def policy_manager_bare(testerchain, escrow_dispatcher, deploy_contract):
|
||||
contract, _ = deploy_contract('PolicyManager', escrow_dispatcher.address)
|
||||
return contract
|
||||
|
||||
|
||||
|
@ -89,14 +101,15 @@ def policy_manager(testerchain, policy_manager_bare, policy_manager_dispatcher):
|
|||
abi=policy_manager_bare.abi,
|
||||
address=policy_manager_dispatcher.address,
|
||||
ContractFactoryClass=Contract)
|
||||
|
||||
return contract
|
||||
|
||||
|
||||
@pytest.fixture(scope='module')
|
||||
def adjudicator_bare(testerchain, token_economics, deploy_contract):
|
||||
def adjudicator_bare(testerchain, token_economics, escrow_dispatcher, deploy_contract):
|
||||
contract, _ = deploy_contract(
|
||||
'Adjudicator',
|
||||
NULL_ADDRESS,
|
||||
escrow_dispatcher.address,
|
||||
*token_economics.slashing_deployment_parameters)
|
||||
return contract
|
||||
|
||||
|
@ -114,11 +127,12 @@ def adjudicator(testerchain, adjudicator_bare, adjudicator_dispatcher):
|
|||
abi=adjudicator_bare.abi,
|
||||
address=adjudicator_dispatcher.address,
|
||||
ContractFactoryClass=Contract)
|
||||
|
||||
return contract
|
||||
|
||||
|
||||
@pytest.fixture(scope='module')
|
||||
def worklock(testerchain, token, token_economics, deploy_contract):
|
||||
def worklock(testerchain, token, escrow_dispatcher, token_economics, deploy_contract):
|
||||
# Creator deploys the worklock using test values
|
||||
now = testerchain.w3.eth.getBlock('latest').timestamp
|
||||
start_bid_date = ((now + 3600) // 3600 + 1) * 3600 # beginning of the next hour plus 1 hour
|
||||
|
@ -130,6 +144,7 @@ def worklock(testerchain, token, token_economics, deploy_contract):
|
|||
contract, _ = deploy_contract(
|
||||
contract_name='WorkLock',
|
||||
_token=token.address,
|
||||
_escrow=escrow_dispatcher.address,
|
||||
_startBidDate=start_bid_date,
|
||||
_endBidDate=end_bid_date,
|
||||
_endCancellationDate=end_cancellation_date,
|
||||
|
@ -137,44 +152,42 @@ def worklock(testerchain, token, token_economics, deploy_contract):
|
|||
_stakingPeriods=staking_periods,
|
||||
_minAllowedBid=min_allowed_bid
|
||||
)
|
||||
|
||||
return contract
|
||||
|
||||
|
||||
@pytest.fixture(scope='module')
|
||||
def escrow_bare(testerchain, token, token_economics, policy_manager, adjudicator, worklock, deploy_contract):
|
||||
def escrow_bare(testerchain,
|
||||
token,
|
||||
policy_manager,
|
||||
adjudicator,
|
||||
worklock,
|
||||
token_economics,
|
||||
escrow_dispatcher,
|
||||
deploy_contract):
|
||||
# Creator deploys the escrow
|
||||
contract, _ = deploy_contract(
|
||||
'EnhancedStakingEscrow',
|
||||
token.address,
|
||||
*token_economics.staking_deployment_parameters,
|
||||
policy_manager.address,
|
||||
adjudicator.address,
|
||||
worklock.address
|
||||
worklock.address,
|
||||
*token_economics.staking_deployment_parameters
|
||||
)
|
||||
|
||||
tx = escrow_dispatcher.functions.upgrade(contract.address).transact()
|
||||
testerchain.wait_for_receipt(tx)
|
||||
|
||||
return contract
|
||||
|
||||
|
||||
@pytest.fixture(scope='module')
|
||||
def escrow_dispatcher(testerchain, escrow_bare, deploy_contract):
|
||||
dispatcher, _ = deploy_contract('Dispatcher', escrow_bare.address)
|
||||
return dispatcher
|
||||
|
||||
|
||||
@pytest.fixture(scope='module')
|
||||
def escrow(testerchain, escrow_bare, policy_manager, adjudicator, worklock, escrow_dispatcher):
|
||||
def escrow(testerchain, escrow_bare, escrow_dispatcher):
|
||||
# Wrap dispatcher contract
|
||||
contract = testerchain.client.get_contract(
|
||||
abi=escrow_bare.abi,
|
||||
address=escrow_dispatcher.address,
|
||||
ContractFactoryClass=Contract)
|
||||
|
||||
tx = policy_manager.functions.setStakingEscrow(contract.address).transact()
|
||||
testerchain.wait_for_receipt(tx)
|
||||
tx = adjudicator.functions.setStakingEscrow(contract.address).transact()
|
||||
testerchain.wait_for_receipt(tx)
|
||||
tx = worklock.functions.setStakingEscrow(contract.address).transact()
|
||||
testerchain.wait_for_receipt(tx)
|
||||
|
||||
return contract
|
||||
|
||||
|
||||
|
@ -903,8 +916,8 @@ def test_upgrading_and_rollback(testerchain,
|
|||
policy_manager_dispatcher,
|
||||
staking_interface_router,
|
||||
multisig,
|
||||
worklock,
|
||||
adjudicator,
|
||||
worklock,
|
||||
deploy_contract):
|
||||
creator, staker1, staker2, staker3, staker4, alice1, alice2, *contracts_owners =\
|
||||
testerchain.client.accounts
|
||||
|
@ -917,12 +930,12 @@ def test_upgrading_and_rollback(testerchain,
|
|||
escrow_v2, _ = deploy_contract(
|
||||
'StakingEscrow',
|
||||
token.address,
|
||||
*token_economics.staking_deployment_parameters,
|
||||
policy_manager.address,
|
||||
adjudicator.address,
|
||||
worklock.address
|
||||
worklock.address,
|
||||
*token_economics.staking_deployment_parameters
|
||||
)
|
||||
policy_manager_v2, _ = deploy_contract('PolicyManager', escrow.address, 0)
|
||||
policy_manager_v2, _ = deploy_contract('PolicyManager', escrow.address)
|
||||
# Staker and Alice can't upgrade contracts, only owner can
|
||||
with pytest.raises((TransactionFailed, ValueError)):
|
||||
tx = escrow_dispatcher.functions.upgrade(escrow_v2.address).transact({'from': alice1})
|
||||
|
|
|
@ -32,7 +32,7 @@ def policy_manager(testerchain, escrow, request, deploy_contract):
|
|||
creator, client, bad_node, node1, node2, node3, *everyone_else = testerchain.client.accounts
|
||||
|
||||
# Creator deploys the policy manager
|
||||
contract, _ = deploy_contract('PolicyManager', escrow.address, 0)
|
||||
contract, _ = deploy_contract('PolicyManager', escrow.address)
|
||||
|
||||
# Give client some ether
|
||||
tx = testerchain.client.send_transaction(
|
||||
|
|
|
@ -522,18 +522,18 @@ def test_upgrading(testerchain, deploy_contract):
|
|||
|
||||
# Only escrow contract is allowed in PolicyManager constructor
|
||||
with pytest.raises((TransactionFailed, ValueError)):
|
||||
deploy_contract('PolicyManager', creator, 0)
|
||||
deploy_contract('PolicyManager', creator)
|
||||
|
||||
# Deploy contracts
|
||||
escrow1, _ = deploy_contract('StakingEscrowForPolicyMock', 1)
|
||||
escrow2, _ = deploy_contract('StakingEscrowForPolicyMock', 1)
|
||||
address1 = escrow1.address
|
||||
address2 = escrow2.address
|
||||
contract_library_v1, _ = deploy_contract('PolicyManager', address1, 0)
|
||||
contract_library_v1, _ = deploy_contract('PolicyManager', address1)
|
||||
dispatcher, _ = deploy_contract('Dispatcher', contract_library_v1.address)
|
||||
|
||||
# Deploy second version of the contract
|
||||
contract_library_v2, _ = deploy_contract('PolicyManagerV2Mock', address2, 0)
|
||||
contract_library_v2, _ = deploy_contract('PolicyManagerV2Mock', address2)
|
||||
contract = testerchain.client.get_contract(
|
||||
abi=contract_library_v2.abi,
|
||||
address=dispatcher.address,
|
||||
|
@ -562,7 +562,7 @@ def test_upgrading(testerchain, deploy_contract):
|
|||
assert 3 == contract.functions.valueToCheck().call()
|
||||
|
||||
# Can't upgrade to the previous version or to the bad version
|
||||
contract_library_bad, _ = deploy_contract('PolicyManagerBad', address2, 0)
|
||||
contract_library_bad, _ = deploy_contract('PolicyManagerBad', address2)
|
||||
with pytest.raises((TransactionFailed, ValueError)):
|
||||
tx = dispatcher.functions.upgrade(contract_library_v1.address).transact({'from': creator})
|
||||
testerchain.wait_for_receipt(tx)
|
||||
|
@ -616,7 +616,7 @@ def test_handling_wrong_state(testerchain, deploy_contract):
|
|||
|
||||
# Prepare enhanced version of contract
|
||||
escrow, _ = deploy_contract('StakingEscrowForPolicyMock', 1)
|
||||
policy_manager, _ = deploy_contract('ExtendedPolicyManager', escrow.address, 0)
|
||||
policy_manager, _ = deploy_contract('ExtendedPolicyManager', escrow.address)
|
||||
tx = escrow.functions.setPolicyManager(policy_manager.address).transact({'from': creator})
|
||||
testerchain.wait_for_receipt(tx)
|
||||
|
||||
|
|
|
@ -84,11 +84,12 @@ def escrow_contract(testerchain,
|
|||
deploy_parameters[5] = 0
|
||||
deploy_parameters[6] = 0
|
||||
|
||||
deploy_parameters.append(policy_manager.address)
|
||||
deploy_parameters.append(adjudicator.address)
|
||||
deploy_parameters.append(worklock.address)
|
||||
|
||||
contract, _ = deploy_contract('EnhancedStakingEscrow', token.address, *deploy_parameters)
|
||||
contract, _ = deploy_contract('EnhancedStakingEscrow',
|
||||
token.address,
|
||||
policy_manager.address,
|
||||
adjudicator.address,
|
||||
worklock.address,
|
||||
*deploy_parameters)
|
||||
|
||||
if request.param:
|
||||
dispatcher, _ = deploy_contract('Dispatcher', contract.address)
|
||||
|
|
|
@ -45,10 +45,10 @@ def test_upgrading(testerchain, token, token_economics, deploy_contract):
|
|||
contract_library_v1, _ = deploy_contract(
|
||||
'StakingEscrow',
|
||||
token.address,
|
||||
*token_economics.staking_deployment_parameters,
|
||||
policy_manager.address,
|
||||
adjudicator.address,
|
||||
worklock.address
|
||||
worklock.address,
|
||||
*token_economics.staking_deployment_parameters
|
||||
)
|
||||
dispatcher, _ = deploy_contract('Dispatcher', contract_library_v1.address)
|
||||
|
||||
|
|
|
@ -59,6 +59,7 @@ def worklock_factory(testerchain, token, escrow, token_economics, deploy_contrac
|
|||
contract, _ = deploy_contract(
|
||||
contract_name='WorkLock',
|
||||
_token=token.address,
|
||||
_escrow=escrow.address,
|
||||
_startBidDate=start_bid_date,
|
||||
_endBidDate=end_bid_date,
|
||||
_endCancellationDate=end_cancellation_date,
|
||||
|
@ -67,9 +68,6 @@ def worklock_factory(testerchain, token, escrow, token_economics, deploy_contrac
|
|||
_minAllowedBid=MIN_ALLOWED_BID
|
||||
)
|
||||
|
||||
tx = contract.functions.setStakingEscrow(escrow.address).transact()
|
||||
testerchain.wait_for_receipt(tx)
|
||||
|
||||
if supply > 0:
|
||||
tx = token.functions.approve(contract.address, supply).transact()
|
||||
testerchain.wait_for_receipt(tx)
|
||||
|
@ -863,7 +861,7 @@ def test_verifying_correctness(testerchain, token_economics, escrow, deploy_cont
|
|||
|
||||
# Set gas only for one check
|
||||
tx = worklock.functions.verifyBiddingCorrectness(gas_to_save_state)\
|
||||
.transact({'gas': gas_to_save_state + 32000, 'gas_price': 0})
|
||||
.transact({'gas': gas_to_save_state + 30000, 'gas_price': 0})
|
||||
testerchain.wait_for_receipt(tx)
|
||||
assert worklock.functions.nextBidderToCheck().call() == 1
|
||||
|
||||
|
@ -1053,7 +1051,7 @@ def test_force_refund(testerchain, token_economics, deploy_contract, worklock_fa
|
|||
# But can verify only one of them
|
||||
assert worklock.functions.nextBidderToCheck().call() == 0
|
||||
tx = worklock.functions.verifyBiddingCorrectness(gas_to_save_state)\
|
||||
.transact({'gas': gas_to_save_state + 32000, 'gas_price': 0})
|
||||
.transact({'gas': gas_to_save_state + 30000, 'gas_price': 0})
|
||||
testerchain.wait_for_receipt(tx)
|
||||
assert worklock.functions.nextBidderToCheck().call() == 1
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ import os
|
|||
from pathlib import Path
|
||||
|
||||
import requests
|
||||
from constant_sorrow import constants
|
||||
from web3.exceptions import ValidationError
|
||||
|
||||
from nucypher.blockchain.eth.deployers import AdjudicatorDeployer, BaseContractDeployer, NucypherTokenDeployer, \
|
||||
|
@ -83,27 +84,43 @@ CONSTRUCTOR_OVERRIDES = {
|
|||
"_firstPhaseMaxIssuance": None,
|
||||
"_miningCoefficient": 2,
|
||||
"_lockedPeriodsCoefficient": 1,
|
||||
"_rewardedPeriods": 1},
|
||||
"v5.6.1": {"_isTestContract": True}
|
||||
},
|
||||
PolicyManagerDeployer.contract_name: {"v6.2.1": {"_secondsPerPeriod": None}}
|
||||
"_rewardedPeriods": 1}
|
||||
}
|
||||
}
|
||||
|
||||
FORCE_SKIP = {
|
||||
StakingEscrowDeployer.contract_name: ["v5.6.1"]
|
||||
}
|
||||
|
||||
|
||||
def deploy_earliest_contract(blockchain_interface: BlockchainDeployerInterface,
|
||||
deployer: BaseContractDeployer):
|
||||
def deploy_base_contract(blockchain_interface: BlockchainDeployerInterface,
|
||||
deployer: BaseContractDeployer,
|
||||
skipt_test: bool):
|
||||
contract_name = deployer.contract_name
|
||||
latest_version, _data = blockchain_interface.find_raw_contract_data(contract_name, "latest")
|
||||
try:
|
||||
overrides = CONSTRUCTOR_OVERRIDES[contract_name][latest_version]
|
||||
except KeyError:
|
||||
overrides = dict()
|
||||
|
||||
version = "latest" if skipt_test else "earliest"
|
||||
try:
|
||||
deployer.deploy(contract_version="earliest", **overrides)
|
||||
deployer.deploy(contract_version=version, deployment_mode=constants.FULL, **overrides)
|
||||
except ValidationError:
|
||||
pass # Skip errors related to initialization
|
||||
|
||||
|
||||
def skip_test(blockchain_interface: BlockchainDeployerInterface, contract_name: str):
|
||||
latest_version, _data = blockchain_interface.find_raw_contract_data(contract_name, "latest")
|
||||
raw_contracts = blockchain_interface._raw_contract_cache
|
||||
try:
|
||||
force_skip = latest_version in FORCE_SKIP[contract_name]
|
||||
except KeyError:
|
||||
force_skip = False
|
||||
|
||||
return force_skip or len(raw_contracts[contract_name]) == 1
|
||||
|
||||
|
||||
def test_upgradeability(temp_dir_path):
|
||||
# Prepare remote source for compilation
|
||||
download_github_dir(GITHUB_SOURCE_LINK, temp_dir_path)
|
||||
|
@ -126,15 +143,14 @@ def test_upgradeability(temp_dir_path):
|
|||
economics = make_token_economics(blockchain_interface)
|
||||
|
||||
# Check contracts with multiple versions
|
||||
raw_contracts = blockchain_interface._raw_contract_cache
|
||||
contract_name = AdjudicatorDeployer.contract_name
|
||||
test_adjudicator = len(raw_contracts[contract_name]) > 1
|
||||
skip_adjudicator_test = skip_test(blockchain_interface, contract_name)
|
||||
contract_name = StakingEscrowDeployer.contract_name
|
||||
test_staking_escrow = len(raw_contracts[contract_name]) > 1
|
||||
skip_staking_escrow_test = skip_test(blockchain_interface, contract_name)
|
||||
contract_name = PolicyManagerDeployer.contract_name
|
||||
test_policy_manager = len(raw_contracts[contract_name]) > 1
|
||||
skip_policy_manager_test = skip_test(blockchain_interface, contract_name)
|
||||
|
||||
if not test_adjudicator and not test_staking_escrow and not test_policy_manager:
|
||||
if not skip_adjudicator_test and not skip_staking_escrow_test and not skip_policy_manager_test:
|
||||
return
|
||||
|
||||
# Prepare master version of contracts and upgrade to the latest
|
||||
|
@ -145,36 +161,42 @@ def test_upgradeability(temp_dir_path):
|
|||
economics=economics)
|
||||
token_deployer.deploy()
|
||||
|
||||
staking_escrow_deployer = StakingEscrowDeployer(registry=registry,
|
||||
deployer_address=origin,
|
||||
economics=economics)
|
||||
staking_escrow_deployer.deploy(deployment_mode=constants.INIT)
|
||||
|
||||
policy_manager_deployer = PolicyManagerDeployer(registry=registry,
|
||||
deployer_address=origin,
|
||||
economics=economics)
|
||||
deploy_earliest_contract(blockchain_interface, policy_manager_deployer)
|
||||
deploy_base_contract(blockchain_interface, policy_manager_deployer, skipt_test=skip_policy_manager_test)
|
||||
|
||||
adjudicator_deployer = AdjudicatorDeployer(registry=registry,
|
||||
deployer_address=origin,
|
||||
economics=economics)
|
||||
deploy_earliest_contract(blockchain_interface, adjudicator_deployer)
|
||||
deploy_base_contract(blockchain_interface, adjudicator_deployer, skipt_test=skip_adjudicator_test)
|
||||
|
||||
worklock_deployer = WorklockDeployer(registry=registry,
|
||||
deployer_address=origin,
|
||||
economics=economics)
|
||||
worklock_deployer.deploy()
|
||||
if skip_staking_escrow_test:
|
||||
worklock_deployer = WorklockDeployer(registry=registry,
|
||||
deployer_address=origin,
|
||||
economics=economics)
|
||||
worklock_deployer.deploy()
|
||||
|
||||
staking_escrow_deployer = StakingEscrowDeployer(registry=registry,
|
||||
deployer_address=origin,
|
||||
economics=economics)
|
||||
deploy_earliest_contract(blockchain_interface, staking_escrow_deployer)
|
||||
deploy_base_contract(blockchain_interface, staking_escrow_deployer, skipt_test=skip_staking_escrow_test)
|
||||
|
||||
if test_policy_manager:
|
||||
policy_manager_deployer.upgrade(contract_version="latest", confirmations=0)
|
||||
|
||||
if test_adjudicator:
|
||||
adjudicator_deployer.upgrade(contract_version="latest", confirmations=0)
|
||||
|
||||
if test_staking_escrow:
|
||||
if not skip_staking_escrow_test:
|
||||
# TODO prepare at least one staker before calling upgrade
|
||||
staking_escrow_deployer.upgrade(contract_version="latest", confirmations=0)
|
||||
|
||||
if not skip_policy_manager_test:
|
||||
policy_manager_deployer.upgrade(contract_version="latest", confirmations=0)
|
||||
|
||||
if not skip_adjudicator_test:
|
||||
adjudicator_deployer.upgrade(contract_version="latest", confirmations=0)
|
||||
|
||||
finally:
|
||||
# Unregister interface # TODO: Move to method?
|
||||
with contextlib.suppress(KeyError):
|
||||
|
|
|
@ -108,6 +108,7 @@ from tests.utils.ursula import (
|
|||
MOCK_KNOWN_URSULAS_CACHE,
|
||||
_mock_ursula_reencrypts
|
||||
)
|
||||
from constant_sorrow.constants import (FULL, INIT)
|
||||
|
||||
test_logger = Logger("test-logger")
|
||||
|
||||
|
@ -555,6 +556,11 @@ def _make_agency(testerchain,
|
|||
registry=test_registry)
|
||||
token_deployer.deploy()
|
||||
|
||||
staking_escrow_deployer = StakingEscrowDeployer(deployer_address=origin,
|
||||
economics=token_economics,
|
||||
registry=test_registry)
|
||||
staking_escrow_deployer.deploy(deployment_mode=INIT)
|
||||
|
||||
policy_manager_deployer = PolicyManagerDeployer(deployer_address=origin,
|
||||
economics=token_economics,
|
||||
registry=test_registry)
|
||||
|
@ -565,6 +571,11 @@ def _make_agency(testerchain,
|
|||
registry=test_registry)
|
||||
adjudicator_deployer.deploy()
|
||||
|
||||
staking_interface_deployer = StakingInterfaceDeployer(deployer_address=origin,
|
||||
economics=token_economics,
|
||||
registry=test_registry)
|
||||
staking_interface_deployer.deploy()
|
||||
|
||||
worklock_deployer = WorklockDeployer(deployer_address=origin,
|
||||
economics=token_economics,
|
||||
registry=test_registry)
|
||||
|
@ -573,12 +584,7 @@ def _make_agency(testerchain,
|
|||
staking_escrow_deployer = StakingEscrowDeployer(deployer_address=origin,
|
||||
economics=token_economics,
|
||||
registry=test_registry)
|
||||
staking_escrow_deployer.deploy()
|
||||
|
||||
staking_interface_deployer = StakingInterfaceDeployer(deployer_address=origin,
|
||||
economics=token_economics,
|
||||
registry=test_registry)
|
||||
staking_interface_deployer.deploy()
|
||||
staking_escrow_deployer.deploy(deployment_mode=FULL)
|
||||
|
||||
token_agent = token_deployer.make_agent() # 1 Token
|
||||
staking_agent = staking_escrow_deployer.make_agent() # 2 Staking Escrow
|
||||
|
|
|
@ -26,6 +26,7 @@ from web3 import Web3
|
|||
|
||||
from nucypher.blockchain.economics import BaseEconomics, StandardTokenEconomics
|
||||
from nucypher.blockchain.eth.actors import ContractAdministrator
|
||||
from nucypher.blockchain.eth.deployers import StakingEscrowDeployer
|
||||
from nucypher.blockchain.eth.interfaces import BlockchainDeployerInterface, BlockchainInterfaceFactory
|
||||
from nucypher.blockchain.eth.registry import InMemoryContractRegistry, BaseContractRegistry
|
||||
from nucypher.blockchain.eth.sol.compile.constants import TEST_SOLIDITY_SOURCE_ROOT, SOLIDITY_SOURCE_ROOT
|
||||
|
@ -43,6 +44,7 @@ from tests.constants import (
|
|||
NUMBER_OF_URSULAS_IN_BLOCKCHAIN_TESTS,
|
||||
PYEVM_DEV_URI
|
||||
)
|
||||
from constant_sorrow.constants import (INIT)
|
||||
|
||||
|
||||
def token_airdrop(token_agent, amount: NU, origin: str, addresses: List[str]):
|
||||
|
@ -231,10 +233,13 @@ class TesterBlockchain(BlockchainDeployerInterface):
|
|||
|
||||
gas_limit = None # TODO: Gas management - #842
|
||||
for deployer_class in admin.primary_deployer_classes:
|
||||
if deployer_class in ContractAdministrator.standard_deployer_classes:
|
||||
admin.deploy_contract(contract_name=deployer_class.contract_name, gas_limit=gas_limit)
|
||||
if deployer_class is StakingEscrowDeployer:
|
||||
admin.deploy_contract(contract_name=deployer_class.contract_name,
|
||||
gas_limit=gas_limit,
|
||||
deployment_mode=INIT)
|
||||
else:
|
||||
admin.deploy_contract(contract_name=deployer_class.contract_name, gas_limit=gas_limit)
|
||||
admin.deploy_contract(contract_name=StakingEscrowDeployer.contract_name, gas_limit=gas_limit)
|
||||
return testerchain, registry
|
||||
|
||||
@property
|
||||
|
|
Loading…
Reference in New Issue