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 = (
|
dispatched_upgradeable_deployer_classes = (
|
||||||
|
StakingEscrowDeployer,
|
||||||
PolicyManagerDeployer,
|
PolicyManagerDeployer,
|
||||||
AdjudicatorDeployer,
|
AdjudicatorDeployer,
|
||||||
StakingEscrowDeployer,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
upgradeable_deployer_classes = (
|
upgradeable_deployer_classes = (
|
||||||
|
|
|
@ -227,11 +227,8 @@ class StakingEscrowAgent(EthereumContractAgent):
|
||||||
contract_name: str = STAKING_ESCROW_CONTRACT_NAME
|
contract_name: str = STAKING_ESCROW_CONTRACT_NAME
|
||||||
_proxy_name: str = DISPATCHER_CONTRACT_NAME
|
_proxy_name: str = DISPATCHER_CONTRACT_NAME
|
||||||
_excluded_interfaces = (
|
_excluded_interfaces = (
|
||||||
'setPolicyManager',
|
|
||||||
'verifyState',
|
'verifyState',
|
||||||
'finishUpgrade',
|
'finishUpgrade'
|
||||||
'setAdjudicator',
|
|
||||||
'setWorkLock'
|
|
||||||
)
|
)
|
||||||
|
|
||||||
DEFAULT_PAGINATION_SIZE: int = 30 # TODO: Use dynamic pagination size (see #1424)
|
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"
|
STAKING_INTERFACE_ROUTER_CONTRACT_NAME = "StakingInterfaceRouter"
|
||||||
NUCYPHER_TOKEN_CONTRACT_NAME = 'NuCypherToken'
|
NUCYPHER_TOKEN_CONTRACT_NAME = 'NuCypherToken'
|
||||||
STAKING_ESCROW_CONTRACT_NAME = 'StakingEscrow'
|
STAKING_ESCROW_CONTRACT_NAME = 'StakingEscrow'
|
||||||
|
STAKING_ESCROW_STUB_CONTRACT_NAME = 'StakingEscrowStub'
|
||||||
POLICY_MANAGER_CONTRACT_NAME = 'PolicyManager'
|
POLICY_MANAGER_CONTRACT_NAME = 'PolicyManager'
|
||||||
STAKING_INTERFACE_CONTRACT_NAME = 'StakingInterface'
|
STAKING_INTERFACE_CONTRACT_NAME = 'StakingInterface'
|
||||||
PREALLOCATION_ESCROW_CONTRACT_NAME = 'PreallocationEscrow'
|
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 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 eth_typing.evm import ChecksumAddress
|
||||||
from typing import Dict, List, Tuple
|
from typing import Dict, List, Tuple
|
||||||
from web3 import Web3
|
from web3 import Web3
|
||||||
|
@ -505,15 +505,13 @@ class StakingEscrowDeployer(BaseContractDeployer, UpgradeableContractMixin, Owna
|
||||||
|
|
||||||
agency = StakingEscrowAgent
|
agency = StakingEscrowAgent
|
||||||
contract_name = agency.contract_name
|
contract_name = agency.contract_name
|
||||||
|
contract_name_stub = "StakingEscrowStub"
|
||||||
|
|
||||||
can_be_idle = True
|
can_be_idle = True
|
||||||
preparation_steps = ('contract_deployment',
|
init_steps = ('stub_deployment', 'dispatcher_deployment')
|
||||||
'dispatcher_deployment',
|
preparation_steps = ('contract_deployment', 'dispatcher_retarget')
|
||||||
'set_on_policy_manager',
|
|
||||||
'set_on_adjudicator')
|
|
||||||
worklock_preparation_step = ('set_on_worklock',)
|
|
||||||
activation_steps = ('approve_reward_transfer', 'initialize')
|
activation_steps = ('approve_reward_transfer', 'initialize')
|
||||||
deployment_steps = preparation_steps + worklock_preparation_step + activation_steps
|
deployment_steps = preparation_steps + activation_steps
|
||||||
_proxy_deployer = DispatcherDeployer
|
_proxy_deployer = DispatcherDeployer
|
||||||
|
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
|
@ -528,18 +526,48 @@ class StakingEscrowDeployer(BaseContractDeployer, UpgradeableContractMixin, Owna
|
||||||
worklock_contract_name = WorklockDeployer.contract_name
|
worklock_contract_name = WorklockDeployer.contract_name
|
||||||
self.token_contract = self.blockchain.get_contract_by_name(registry=self.registry,
|
self.token_contract = self.blockchain.get_contract_by_name(registry=self.registry,
|
||||||
contract_name=token_contract_name)
|
contract_name=token_contract_name)
|
||||||
self.policy_manager = self.blockchain.get_contract_by_name(registry=self.registry,
|
try:
|
||||||
contract_name=policy_manager_contract_name,
|
self.policy_manager = self.blockchain.get_contract_by_name(registry=self.registry,
|
||||||
proxy_name=policy_manager_proxy_name)
|
contract_name=policy_manager_contract_name,
|
||||||
self.adjudicator = self.blockchain.get_contract_by_name(registry=self.registry,
|
proxy_name=policy_manager_proxy_name)
|
||||||
contract_name=adjudicator_contract_name,
|
except self.registry.UnknownContract:
|
||||||
proxy_name=adjudicator_proxy_name)
|
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:
|
try:
|
||||||
self.worklock = self.blockchain.get_contract_by_name(registry=self.registry,
|
self.worklock = self.blockchain.get_contract_by_name(registry=self.registry,
|
||||||
contract_name=worklock_contract_name)
|
contract_name=worklock_contract_name)
|
||||||
except self.registry.UnknownContract:
|
except self.registry.UnknownContract:
|
||||||
self.worklock = None
|
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):
|
def _deploy_essential(self, contract_version: str, gas_limit: int = None, confirmations: int = 0, **overrides):
|
||||||
args = self.economics.staking_deployment_parameters
|
args = self.economics.staking_deployment_parameters
|
||||||
constructor_kwargs = {
|
constructor_kwargs = {
|
||||||
|
@ -557,7 +585,7 @@ class StakingEscrowDeployer(BaseContractDeployer, UpgradeableContractMixin, Owna
|
||||||
}
|
}
|
||||||
constructor_kwargs.update(overrides)
|
constructor_kwargs.update(overrides)
|
||||||
constructor_kwargs = {k: v for k, v in constructor_kwargs.items() if v is not None}
|
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,
|
constructor_kwargs.update({"_token": self.token_contract.address,
|
||||||
"_policyManager": self.policy_manager.address,
|
"_policyManager": self.policy_manager.address,
|
||||||
"_adjudicator": self.adjudicator.address,
|
"_adjudicator": self.adjudicator.address,
|
||||||
|
@ -575,7 +603,7 @@ class StakingEscrowDeployer(BaseContractDeployer, UpgradeableContractMixin, Owna
|
||||||
return the_escrow_contract, deploy_receipt
|
return the_escrow_contract, deploy_receipt
|
||||||
|
|
||||||
def deploy(self,
|
def deploy(self,
|
||||||
deployment_mode=FULL,
|
deployment_mode=INIT,
|
||||||
gas_limit: int = None,
|
gas_limit: int = None,
|
||||||
progress=None,
|
progress=None,
|
||||||
contract_version: str = "latest",
|
contract_version: str = "latest",
|
||||||
|
@ -597,7 +625,7 @@ class StakingEscrowDeployer(BaseContractDeployer, UpgradeableContractMixin, Owna
|
||||||
Returns transaction receipts in a dict.
|
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 ValueError(f"Invalid deployment mode ({deployment_mode})")
|
||||||
|
|
||||||
# Raise if not all-systems-go
|
# Raise if not all-systems-go
|
||||||
|
@ -608,32 +636,60 @@ class StakingEscrowDeployer(BaseContractDeployer, UpgradeableContractMixin, Owna
|
||||||
if gas_limit:
|
if gas_limit:
|
||||||
origin_args.update({'gas': gas_limit}) # TODO: Gas Management - #842
|
origin_args.update({'gas': gas_limit}) # TODO: Gas Management - #842
|
||||||
|
|
||||||
# 1 - Deploy #
|
if deployment_mode is INIT:
|
||||||
if emitter:
|
# 1 - Deploy Stub
|
||||||
emitter.message(f"\nNext Transaction: {self.contract_name} Contract Creation", color='blue', bold=True)
|
if emitter:
|
||||||
the_escrow_contract, deploy_receipt = self._deploy_essential(contract_version=contract_version,
|
emitter.message(f"\nNext Transaction: {self.contract_name_stub} Contract Creation", color='blue', bold=True)
|
||||||
gas_limit=gas_limit,
|
the_escrow_contract, deploy_receipt = self._deploy_stub(gas_limit=gas_limit,
|
||||||
confirmations=confirmations,
|
confirmations=confirmations,
|
||||||
**overrides)
|
**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.
|
# This is the end of bare deployment.
|
||||||
if deployment_mode is BARE:
|
if deployment_mode is BARE:
|
||||||
self._contract = the_escrow_contract
|
self._contract = the_escrow_contract
|
||||||
receipts = self._finish_bare_deployment(deployment_receipt=deploy_receipt, progress=progress)
|
receipts = self._finish_bare_deployment(deployment_receipt=deploy_receipt, progress=progress)
|
||||||
return receipts
|
return receipts
|
||||||
|
|
||||||
if progress:
|
if progress:
|
||||||
progress.update(1)
|
progress.update(1)
|
||||||
|
|
||||||
# 2 - Deploy the dispatcher used for updating this contract #
|
if deployment_mode is INIT:
|
||||||
if emitter:
|
# 2 - Deploy the dispatcher used for updating this contract #
|
||||||
emitter.message(f"\nNext Transaction: {DispatcherDeployer.contract_name} Contract Creation for {self.contract_name}", color='blue', bold=True)
|
if emitter:
|
||||||
dispatcher_deployer = DispatcherDeployer(registry=self.registry,
|
emitter.message(f"\nNext Transaction: {DispatcherDeployer.contract_name} "
|
||||||
target_contract=the_escrow_contract,
|
f"Contract Creation for {self.contract_name}",
|
||||||
deployer_address=self.deployer_address)
|
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:
|
if progress:
|
||||||
progress.update(1)
|
progress.update(1)
|
||||||
|
|
||||||
|
@ -645,57 +701,17 @@ class StakingEscrowDeployer(BaseContractDeployer, UpgradeableContractMixin, Owna
|
||||||
wrapped_escrow_contract = self.blockchain._wrap_contract(dispatcher_contract,
|
wrapped_escrow_contract = self.blockchain._wrap_contract(dispatcher_contract,
|
||||||
target_contract=the_escrow_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
|
# Switch the contract for the wrapped one
|
||||||
self._contract = wrapped_escrow_contract
|
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
|
# 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
|
# This is the end of deployment without activation: the contract is now idle, waiting for activation
|
||||||
return preparation_receipts
|
return preparation_receipts
|
||||||
else: # deployment_mode is FULL
|
else: # deployment_mode is FULL
|
||||||
|
@ -788,24 +804,21 @@ class PolicyManagerDeployer(BaseContractDeployer, UpgradeableContractMixin, Owna
|
||||||
contract_name=staking_contract_name,
|
contract_name=staking_contract_name,
|
||||||
proxy_name=proxy_name)
|
proxy_name=proxy_name)
|
||||||
except self.registry.UnknownContract:
|
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]:
|
def check_deployment_readiness(self, *args, **kwargs) -> Tuple[bool, list]:
|
||||||
policy_manager_deployment_rules = []
|
staking_escrow_owner = self.staking_contract.functions.owner().call()
|
||||||
if self.staking_contract is not None:
|
policy_manager_deployment_rules = [
|
||||||
staking_escrow_owner = self.staking_contract.functions.owner().call()
|
(self.deployer_address == staking_escrow_owner,
|
||||||
policy_manager_deployment_rules.append(
|
f'{self.contract_name} must be deployed by the owner of {STAKING_ESCROW_CONTRACT_NAME} ({staking_escrow_owner})')
|
||||||
(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)
|
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:
|
def _deploy_essential(self, contract_version: str, gas_limit: int = None, confirmations: int = 0) -> tuple:
|
||||||
escrow_address = self.staking_contract.address if self.staking_contract is not None else NULL_ADDRESS
|
constructor_kwargs = {"_escrow": self.staking_contract.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})
|
|
||||||
policy_manager_contract, deploy_receipt = self.blockchain.deploy_contract(self.deployer_address,
|
policy_manager_contract, deploy_receipt = self.blockchain.deploy_contract(self.deployer_address,
|
||||||
self.registry,
|
self.registry,
|
||||||
self.contract_name,
|
self.contract_name,
|
||||||
|
@ -823,7 +836,6 @@ class PolicyManagerDeployer(BaseContractDeployer, UpgradeableContractMixin, Owna
|
||||||
ignore_deployed: bool = False,
|
ignore_deployed: bool = False,
|
||||||
confirmations: int = 0,
|
confirmations: int = 0,
|
||||||
emitter=None,
|
emitter=None,
|
||||||
**overrides,
|
|
||||||
) -> Dict[str, dict]:
|
) -> Dict[str, dict]:
|
||||||
|
|
||||||
if deployment_mode not in (BARE, IDLE, FULL):
|
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)
|
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,
|
policy_manager_contract, deploy_receipt = self._deploy_essential(contract_version=contract_version,
|
||||||
gas_limit=gas_limit,
|
gas_limit=gas_limit,
|
||||||
confirmations=confirmations,
|
confirmations=confirmations)
|
||||||
**overrides)
|
|
||||||
|
|
||||||
# This is the end of bare deployment.
|
# This is the end of bare deployment.
|
||||||
if deployment_mode is BARE:
|
if deployment_mode is BARE:
|
||||||
|
@ -929,9 +940,15 @@ class StakingInterfaceDeployer(BaseContractDeployer, UpgradeableContractMixin, O
|
||||||
|
|
||||||
staking_contract_name = StakingEscrowDeployer.contract_name
|
staking_contract_name = StakingEscrowDeployer.contract_name
|
||||||
staking_proxy_name = StakingEscrowDeployer._proxy_deployer.contract_name
|
staking_proxy_name = StakingEscrowDeployer._proxy_deployer.contract_name
|
||||||
self.staking_contract = self.blockchain.get_contract_by_name(registry=self.registry,
|
try:
|
||||||
contract_name=staking_contract_name,
|
self.staking_contract = self.blockchain.get_contract_by_name(registry=self.registry,
|
||||||
proxy_name=staking_proxy_name)
|
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_contract_name = PolicyManagerDeployer.contract_name
|
||||||
policy_proxy_name = PolicyManagerDeployer._proxy_deployer.contract_name
|
policy_proxy_name = PolicyManagerDeployer._proxy_deployer.contract_name
|
||||||
|
@ -1140,16 +1157,17 @@ class AdjudicatorDeployer(BaseContractDeployer, UpgradeableContractMixin, Ownabl
|
||||||
contract_name=staking_contract_name,
|
contract_name=staking_contract_name,
|
||||||
proxy_name=proxy_name)
|
proxy_name=proxy_name)
|
||||||
except self.registry.UnknownContract:
|
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]:
|
def check_deployment_readiness(self, *args, **kwargs) -> Tuple[bool, list]:
|
||||||
adjudicator_deployment_rules = []
|
staking_escrow_owner = self.staking_contract.functions.owner().call()
|
||||||
if self.staking_contract is not None:
|
adjudicator_deployment_rules = [
|
||||||
staking_escrow_owner = self.staking_contract.functions.owner().call()
|
(self.deployer_address == staking_escrow_owner,
|
||||||
adjudicator_deployment_rules.append(
|
f'{self.contract_name} must be deployed by the owner of {STAKING_ESCROW_CONTRACT_NAME} ({staking_escrow_owner})')
|
||||||
(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)
|
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):
|
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.update(overrides)
|
||||||
constructor_kwargs = {k: v for k, v in constructor_kwargs.items() if v is not None}
|
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
|
# 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": self.staking_contract.address})
|
||||||
constructor_kwargs.update({"_escrow": escrow_address})
|
|
||||||
adjudicator_contract, deploy_receipt = self.blockchain.deploy_contract(self.deployer_address,
|
adjudicator_contract, deploy_receipt = self.blockchain.deploy_contract(self.deployer_address,
|
||||||
self.registry,
|
self.registry,
|
||||||
self.contract_name,
|
self.contract_name,
|
||||||
|
@ -1249,11 +1266,26 @@ class WorklockDeployer(BaseContractDeployer):
|
||||||
def __init__(self, *args, **kwargs):
|
def __init__(self, *args, **kwargs):
|
||||||
|
|
||||||
super().__init__(*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):
|
def _deploy_essential(self, gas_limit: int = None, confirmations: int = 0):
|
||||||
# Deploy
|
# Deploy
|
||||||
constructor_args = (self.token_agent.contract_address,
|
constructor_args = (self.token_contract.address,
|
||||||
|
self.staking_contract.address,
|
||||||
*self.economics.worklock_deployment_parameters)
|
*self.economics.worklock_deployment_parameters)
|
||||||
|
|
||||||
worklock_contract, receipt = self.blockchain.deploy_contract(self.deployer_address,
|
worklock_contract, receipt = self.blockchain.deploy_contract(self.deployer_address,
|
||||||
|
@ -1278,11 +1310,7 @@ class WorklockDeployer(BaseContractDeployer):
|
||||||
if deployment_mode != FULL:
|
if deployment_mode != FULL:
|
||||||
raise self.ContractDeploymentError(f"{self.contract_name} cannot be deployed in {deployment_mode} mode")
|
raise self.ContractDeploymentError(f"{self.contract_name} cannot be deployed in {deployment_mode} mode")
|
||||||
|
|
||||||
# staking_escrow_rule = [
|
self.check_deployment_readiness(ignore_deployed=ignore_deployed)
|
||||||
# (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)
|
|
||||||
|
|
||||||
# Essential
|
# Essential
|
||||||
if emitter:
|
if emitter:
|
||||||
|
|
|
@ -13,7 +13,7 @@ import "zeppelin/math/Math.sol";
|
||||||
/**
|
/**
|
||||||
* @title Adjudicator
|
* @title Adjudicator
|
||||||
* @notice Supervises stakers' behavior and punishes when something's wrong.
|
* @notice Supervises stakers' behavior and punishes when something's wrong.
|
||||||
* @dev |v2.2.1|
|
* @dev |v2.1.2|
|
||||||
*/
|
*/
|
||||||
contract Adjudicator is Upgradeable {
|
contract Adjudicator is Upgradeable {
|
||||||
|
|
||||||
|
@ -35,6 +35,7 @@ contract Adjudicator is Upgradeable {
|
||||||
bytes32 constant RESERVED_CAPSULE_AND_CFRAG_BYTES = bytes32(0);
|
bytes32 constant RESERVED_CAPSULE_AND_CFRAG_BYTES = bytes32(0);
|
||||||
address constant RESERVED_ADDRESS = address(0);
|
address constant RESERVED_ADDRESS = address(0);
|
||||||
|
|
||||||
|
StakingEscrow public immutable escrow;
|
||||||
SignatureVerifier.HashAlgorithm public immutable hashAlgorithm;
|
SignatureVerifier.HashAlgorithm public immutable hashAlgorithm;
|
||||||
uint256 public immutable basePenalty;
|
uint256 public immutable basePenalty;
|
||||||
uint256 public immutable penaltyHistoryCoefficient;
|
uint256 public immutable penaltyHistoryCoefficient;
|
||||||
|
@ -43,10 +44,9 @@ contract Adjudicator is Upgradeable {
|
||||||
|
|
||||||
mapping (address => uint256) public penaltyHistory;
|
mapping (address => uint256) public penaltyHistory;
|
||||||
mapping (bytes32 => bool) public evaluatedCFrags;
|
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 _hashAlgorithm Hashing algorithm
|
||||||
* @param _basePenalty Base for the penalty calculation
|
* @param _basePenalty Base for the penalty calculation
|
||||||
* @param _penaltyHistoryCoefficient Coefficient for calculating the penalty depending on the history
|
* @param _penaltyHistoryCoefficient Coefficient for calculating the penalty depending on the history
|
||||||
|
@ -62,8 +62,7 @@ contract Adjudicator is Upgradeable {
|
||||||
uint256 _rewardCoefficient
|
uint256 _rewardCoefficient
|
||||||
) {
|
) {
|
||||||
// Sanity checks.
|
// Sanity checks.
|
||||||
require(// This contract has an escrow if it's not the null address.
|
require(_escrow.secondsPerPeriod() > 0 && // This contract has an escrow, and it's not the null address.
|
||||||
(address(_escrow) == address(0) || _escrow.secondsPerPeriod() > 0) &&
|
|
||||||
// The reward and penalty coefficients are set.
|
// The reward and penalty coefficients are set.
|
||||||
_percentagePenaltyCoefficient != 0 &&
|
_percentagePenaltyCoefficient != 0 &&
|
||||||
_rewardCoefficient != 0);
|
_rewardCoefficient != 0);
|
||||||
|
@ -75,17 +74,6 @@ contract Adjudicator is Upgradeable {
|
||||||
rewardCoefficient = _rewardCoefficient;
|
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
|
* @notice Submit proof that a worker created wrong CFrag
|
||||||
* @param _capsuleBytes Serialized capsule
|
* @param _capsuleBytes Serialized capsule
|
||||||
|
@ -203,7 +191,6 @@ contract Adjudicator is Upgradeable {
|
||||||
/// @dev the `onlyWhileUpgrading` modifier works through a call to the parent `verifyState`
|
/// @dev the `onlyWhileUpgrading` modifier works through a call to the parent `verifyState`
|
||||||
function verifyState(address _testTarget) public override virtual {
|
function verifyState(address _testTarget) public override virtual {
|
||||||
super.verifyState(_testTarget);
|
super.verifyState(_testTarget);
|
||||||
require(address(delegateGet(_testTarget, this.escrow.selector)) == address(escrow));
|
|
||||||
bytes32 evaluationCFragHash = SignatureVerifier.hash(
|
bytes32 evaluationCFragHash = SignatureVerifier.hash(
|
||||||
abi.encodePacked(RESERVED_CAPSULE_AND_CFRAG_BYTES), SignatureVerifier.HashAlgorithm.SHA256);
|
abi.encodePacked(RESERVED_CAPSULE_AND_CFRAG_BYTES), SignatureVerifier.HashAlgorithm.SHA256);
|
||||||
require(delegateGet(_testTarget, this.evaluatedCFrags.selector, evaluationCFragHash) ==
|
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`
|
/// @dev the `onlyWhileUpgrading` modifier works through a call to the parent `finishUpgrade`
|
||||||
function finishUpgrade(address _target) public override virtual {
|
function finishUpgrade(address _target) public override virtual {
|
||||||
super.finishUpgrade(_target);
|
super.finishUpgrade(_target);
|
||||||
StakingEscrow escrowAddress = Adjudicator(_target).escrow();
|
|
||||||
if (address(escrowAddress) != address(0)) {
|
|
||||||
escrow = escrowAddress;
|
|
||||||
}
|
|
||||||
// preparation for the verifyState method
|
// preparation for the verifyState method
|
||||||
bytes32 evaluationCFragHash = SignatureVerifier.hash(
|
bytes32 evaluationCFragHash = SignatureVerifier.hash(
|
||||||
abi.encodePacked(RESERVED_CAPSULE_AND_CFRAG_BYTES), SignatureVerifier.HashAlgorithm.SHA256);
|
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
|
* @title PolicyManager
|
||||||
* @notice Contract holds policy data and locks accrued policy fees
|
* @notice Contract holds policy data and locks accrued policy fees
|
||||||
* @dev |v6.2.1|
|
* @dev |v6.1.3|
|
||||||
*/
|
*/
|
||||||
contract PolicyManager is Upgradeable {
|
contract PolicyManager is Upgradeable {
|
||||||
using SafeERC20 for NuCypherToken;
|
using SafeERC20 for NuCypherToken;
|
||||||
|
@ -108,37 +108,25 @@ contract PolicyManager is Upgradeable {
|
||||||
// controlled overflow to get max int256
|
// controlled overflow to get max int256
|
||||||
int256 public constant DEFAULT_FEE_DELTA = int256((uint256(0) - 1) >> 1);
|
int256 public constant DEFAULT_FEE_DELTA = int256((uint256(0) - 1) >> 1);
|
||||||
|
|
||||||
|
StakingEscrow public immutable escrow;
|
||||||
uint32 public immutable secondsPerPeriod;
|
uint32 public immutable secondsPerPeriod;
|
||||||
|
|
||||||
mapping (bytes16 => Policy) public policies;
|
mapping (bytes16 => Policy) public policies;
|
||||||
mapping (address => NodeInfo) public nodes;
|
mapping (address => NodeInfo) public nodes;
|
||||||
Range public feeRateRange;
|
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 _escrow Escrow contract
|
||||||
* @param _secondsPerPeriod Seconds per period from StakingEscrow contract
|
|
||||||
*/
|
*/
|
||||||
constructor(StakingEscrow _escrow, uint32 _secondsPerPeriod) {
|
constructor(StakingEscrow _escrow) {
|
||||||
uint32 localSecondsPerPeriod = address(_escrow) != address(0) ? _escrow.secondsPerPeriod() : _secondsPerPeriod;
|
// if the input address is not the StakingEscrow then calling `secondsPerPeriod` will throw error
|
||||||
|
uint32 localSecondsPerPeriod = _escrow.secondsPerPeriod();
|
||||||
require(localSecondsPerPeriod > 0);
|
require(localSecondsPerPeriod > 0);
|
||||||
secondsPerPeriod = localSecondsPerPeriod;
|
secondsPerPeriod = localSecondsPerPeriod;
|
||||||
escrow = _escrow;
|
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
|
* @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`
|
/// @dev the `onlyWhileUpgrading` modifier works through a call to the parent `verifyState`
|
||||||
function verifyState(address _testTarget) public override virtual {
|
function verifyState(address _testTarget) public override virtual {
|
||||||
super.verifyState(_testTarget);
|
super.verifyState(_testTarget);
|
||||||
require(address(delegateGet(_testTarget, this.escrow.selector)) == address(escrow));
|
|
||||||
Range memory rangeToCheck = delegateGetFeeRateRange(_testTarget);
|
Range memory rangeToCheck = delegateGetFeeRateRange(_testTarget);
|
||||||
require(feeRateRange.min == rangeToCheck.min &&
|
require(feeRateRange.min == rangeToCheck.min &&
|
||||||
feeRateRange.defaultValue == rangeToCheck.defaultValue &&
|
feeRateRange.defaultValue == rangeToCheck.defaultValue &&
|
||||||
|
@ -770,10 +757,6 @@ contract PolicyManager is Upgradeable {
|
||||||
/// @dev the `onlyWhileUpgrading` modifier works through a call to the parent `finishUpgrade`
|
/// @dev the `onlyWhileUpgrading` modifier works through a call to the parent `finishUpgrade`
|
||||||
function finishUpgrade(address _target) public override virtual {
|
function finishUpgrade(address _target) public override virtual {
|
||||||
super.finishUpgrade(_target);
|
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)
|
// Create fake Policy and NodeInfo to use them in verifyState(address)
|
||||||
Policy storage policy = policies[RESERVED_POLICY_ID];
|
Policy storage policy = policies[RESERVED_POLICY_ID];
|
||||||
policy.sponsor = msg.sender;
|
policy.sponsor = msg.sender;
|
||||||
|
|
|
@ -41,6 +41,58 @@ interface WorkLockInterface {
|
||||||
function token() external view returns (NuCypherToken);
|
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
|
* @title StakingEscrow
|
||||||
|
@ -156,6 +208,9 @@ contract StakingEscrow is Issuer, IERC900History {
|
||||||
/**
|
/**
|
||||||
* @notice Constructor sets address of token contract and coefficients for minting
|
* @notice Constructor sets address of token contract and coefficients for minting
|
||||||
* @param _token Token contract
|
* @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 _hoursPerPeriod Size of period in hours
|
||||||
* @param _issuanceDecayCoefficient (d) Coefficient which modifies the rate at which the maximum issuance decays,
|
* @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.
|
* 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 _minAllowableLockedTokens Min amount of tokens that can be locked
|
||||||
* @param _maxAllowableLockedTokens Max 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 _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(
|
constructor(
|
||||||
NuCypherToken _token,
|
NuCypherToken _token,
|
||||||
|
PolicyManagerInterface _policyManager,
|
||||||
|
AdjudicatorInterface _adjudicator,
|
||||||
|
WorkLockInterface _workLock,
|
||||||
uint32 _hoursPerPeriod,
|
uint32 _hoursPerPeriod,
|
||||||
uint256 _issuanceDecayCoefficient,
|
uint256 _issuanceDecayCoefficient,
|
||||||
uint256 _lockDurationCoefficient1,
|
uint256 _lockDurationCoefficient1,
|
||||||
|
@ -195,10 +250,7 @@ contract StakingEscrow is Issuer, IERC900History {
|
||||||
uint16 _minLockedPeriods,
|
uint16 _minLockedPeriods,
|
||||||
uint256 _minAllowableLockedTokens,
|
uint256 _minAllowableLockedTokens,
|
||||||
uint256 _maxAllowableLockedTokens,
|
uint256 _maxAllowableLockedTokens,
|
||||||
uint16 _minWorkerPeriods,
|
uint16 _minWorkerPeriods
|
||||||
PolicyManagerInterface _policyManager,
|
|
||||||
AdjudicatorInterface _adjudicator,
|
|
||||||
WorkLockInterface _workLock
|
|
||||||
)
|
)
|
||||||
Issuer(
|
Issuer(
|
||||||
_token,
|
_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------------------------
|
//------------------------Main getters------------------------
|
||||||
/**
|
/**
|
||||||
* @notice Get all tokens belonging to the staker
|
* @notice Get all tokens belonging to the staker
|
||||||
|
|
|
@ -43,6 +43,7 @@ contract WorkLock is Ownable {
|
||||||
uint256 private constant MAX_ETH_SUPPLY = 2e10 ether;
|
uint256 private constant MAX_ETH_SUPPLY = 2e10 ether;
|
||||||
|
|
||||||
NuCypherToken public immutable token;
|
NuCypherToken public immutable token;
|
||||||
|
StakingEscrow public immutable escrow;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @dev WorkLock calculations:
|
* @dev WorkLock calculations:
|
||||||
|
@ -56,6 +57,9 @@ contract WorkLock is Ownable {
|
||||||
uint256 public immutable boostingRefund;
|
uint256 public immutable boostingRefund;
|
||||||
uint256 public immutable minAllowedBid;
|
uint256 public immutable minAllowedBid;
|
||||||
uint16 public immutable stakingPeriods;
|
uint16 public immutable stakingPeriods;
|
||||||
|
// copy from the escrow contract
|
||||||
|
uint256 public immutable maxAllowableLockedTokens;
|
||||||
|
uint256 public immutable minAllowableLockedTokens;
|
||||||
|
|
||||||
uint256 public tokenSupply;
|
uint256 public tokenSupply;
|
||||||
uint256 public startBidDate;
|
uint256 public startBidDate;
|
||||||
|
@ -70,11 +74,6 @@ contract WorkLock is Ownable {
|
||||||
// if value == bidders.length then WorkLock is fully checked
|
// if value == bidders.length then WorkLock is fully checked
|
||||||
uint256 public nextBidderToCheck;
|
uint256 public nextBidderToCheck;
|
||||||
|
|
||||||
StakingEscrow public escrow;
|
|
||||||
// copy from the escrow contract
|
|
||||||
uint256 public maxAllowableLockedTokens;
|
|
||||||
uint256 public minAllowableLockedTokens;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev Checks timestamp regarding cancellation window
|
* @dev Checks timestamp regarding cancellation window
|
||||||
*/
|
*/
|
||||||
|
@ -87,6 +86,7 @@ contract WorkLock is Ownable {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param _token Token contract
|
* @param _token Token contract
|
||||||
|
* @param _escrow Escrow contract
|
||||||
* @param _startBidDate Timestamp when bidding starts
|
* @param _startBidDate Timestamp when bidding starts
|
||||||
* @param _endBidDate Timestamp when bidding will end
|
* @param _endBidDate Timestamp when bidding will end
|
||||||
* @param _endCancellationDate Timestamp when cancellation will ends
|
* @param _endCancellationDate Timestamp when cancellation will ends
|
||||||
|
@ -96,6 +96,7 @@ contract WorkLock is Ownable {
|
||||||
*/
|
*/
|
||||||
constructor(
|
constructor(
|
||||||
NuCypherToken _token,
|
NuCypherToken _token,
|
||||||
|
StakingEscrow _escrow,
|
||||||
uint256 _startBidDate,
|
uint256 _startBidDate,
|
||||||
uint256 _endBidDate,
|
uint256 _endBidDate,
|
||||||
uint256 _endCancellationDate,
|
uint256 _endCancellationDate,
|
||||||
|
@ -105,38 +106,27 @@ contract WorkLock is Ownable {
|
||||||
) {
|
) {
|
||||||
uint256 totalSupply = _token.totalSupply();
|
uint256 totalSupply = _token.totalSupply();
|
||||||
require(totalSupply > 0 && // token contract is deployed and accessible
|
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 > _startBidDate && // bidding period lasts some time
|
||||||
_endBidDate > block.timestamp && // there is time to make a bid
|
_endBidDate > block.timestamp && // there is time to make a bid
|
||||||
_endCancellationDate >= _endBidDate && // cancellation window includes bidding
|
_endCancellationDate >= _endBidDate && // cancellation window includes bidding
|
||||||
_minAllowedBid > 0 && // min allowed bid was set
|
_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()`,
|
// worst case for `ethToWork()` and `workToETH()`,
|
||||||
// when ethSupply == MAX_ETH_SUPPLY and tokenSupply == totalSupply
|
// when ethSupply == MAX_ETH_SUPPLY and tokenSupply == totalSupply
|
||||||
require(MAX_ETH_SUPPLY * totalSupply * SLOWING_REFUND / MAX_ETH_SUPPLY / totalSupply == SLOWING_REFUND &&
|
require(MAX_ETH_SUPPLY * totalSupply * SLOWING_REFUND / MAX_ETH_SUPPLY / totalSupply == SLOWING_REFUND &&
|
||||||
MAX_ETH_SUPPLY * totalSupply * _boostingRefund / MAX_ETH_SUPPLY / totalSupply == _boostingRefund);
|
MAX_ETH_SUPPLY * totalSupply * _boostingRefund / MAX_ETH_SUPPLY / totalSupply == _boostingRefund);
|
||||||
|
|
||||||
token = _token;
|
token = _token;
|
||||||
|
escrow = _escrow;
|
||||||
startBidDate = _startBidDate;
|
startBidDate = _startBidDate;
|
||||||
endBidDate = _endBidDate;
|
endBidDate = _endBidDate;
|
||||||
endCancellationDate = _endCancellationDate;
|
endCancellationDate = _endCancellationDate;
|
||||||
boostingRefund = _boostingRefund;
|
boostingRefund = _boostingRefund;
|
||||||
stakingPeriods = _stakingPeriods;
|
stakingPeriods = _stakingPeriods;
|
||||||
minAllowedBid = _minAllowedBid;
|
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();
|
maxAllowableLockedTokens = _escrow.maxAllowableLockedTokens();
|
||||||
minAllowableLockedTokens = _escrow.minAllowableLockedTokens();
|
minAllowableLockedTokens = _escrow.minAllowableLockedTokens();
|
||||||
}
|
}
|
||||||
|
|
|
@ -454,8 +454,9 @@ def rollback(general_config, actor_options):
|
||||||
@option_confirmations
|
@option_confirmations
|
||||||
@click.option('--mode',
|
@click.option('--mode',
|
||||||
help="Deploy a contract following all steps ('full'), up to idle status ('idle'), "
|
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'",
|
"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'
|
default='full'
|
||||||
)
|
)
|
||||||
@click.option('--activate', help="Activate a contract that is in idle mode", is_flag=True)
|
@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
|
import pytest
|
||||||
|
|
||||||
from nucypher.blockchain.eth.deployers import (AdjudicatorDeployer, NucypherTokenDeployer, PolicyManagerDeployer,
|
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")
|
@pytest.fixture(scope="module")
|
||||||
|
@ -29,20 +30,16 @@ def token_deployer(testerchain, test_registry):
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope="module")
|
@pytest.fixture(scope="module")
|
||||||
def worklock_deployer(token_deployer,
|
def staking_escrow_stub_deployer(testerchain, token_deployer, test_registry):
|
||||||
testerchain,
|
|
||||||
test_registry,
|
|
||||||
token_economics):
|
|
||||||
token_deployer.deploy()
|
token_deployer.deploy()
|
||||||
worklock_deployer = WorklockDeployer(registry=test_registry,
|
staking_escrow_deployer = StakingEscrowDeployer(registry=test_registry,
|
||||||
economics=token_economics,
|
deployer_address=testerchain.etherbase_account)
|
||||||
deployer_address=testerchain.etherbase_account)
|
return staking_escrow_deployer
|
||||||
return worklock_deployer
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope="module")
|
@pytest.fixture(scope="module")
|
||||||
def policy_manager_deployer(worklock_deployer, testerchain, test_registry):
|
def policy_manager_deployer(staking_escrow_stub_deployer, testerchain, test_registry):
|
||||||
worklock_deployer.deploy()
|
staking_escrow_stub_deployer.deploy(deployment_mode=INIT)
|
||||||
policy_manager_deployer = PolicyManagerDeployer(registry=test_registry,
|
policy_manager_deployer = PolicyManagerDeployer(registry=test_registry,
|
||||||
deployer_address=testerchain.etherbase_account)
|
deployer_address=testerchain.etherbase_account)
|
||||||
return policy_manager_deployer
|
return policy_manager_deployer
|
||||||
|
@ -66,7 +63,6 @@ def staking_escrow_deployer(testerchain, adjudicator_deployer, test_registry):
|
||||||
|
|
||||||
@pytest.fixture(scope="module")
|
@pytest.fixture(scope="module")
|
||||||
def staking_interface_deployer(staking_escrow_deployer, testerchain, test_registry):
|
def staking_interface_deployer(staking_escrow_deployer, testerchain, test_registry):
|
||||||
staking_escrow_deployer.deploy()
|
|
||||||
staking_interface_deployer = StakingInterfaceDeployer(registry=test_registry,
|
staking_interface_deployer = StakingInterfaceDeployer(registry=test_registry,
|
||||||
deployer_address=testerchain.etherbase_account)
|
deployer_address=testerchain.etherbase_account)
|
||||||
return staking_interface_deployer
|
return staking_interface_deployer
|
||||||
|
|
|
@ -35,6 +35,11 @@ def test_adjudicator_deployer(testerchain,
|
||||||
token_deployer = NucypherTokenDeployer(deployer_address=origin, registry=test_registry)
|
token_deployer = NucypherTokenDeployer(deployer_address=origin, registry=test_registry)
|
||||||
token_deployer.deploy()
|
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)
|
deployer = AdjudicatorDeployer(deployer_address=origin, registry=test_registry)
|
||||||
deployment_receipts = deployer.deploy(progress=deployment_progress)
|
deployment_receipts = deployer.deploy(progress=deployment_progress)
|
||||||
|
|
||||||
|
@ -48,6 +53,8 @@ def test_adjudicator_deployer(testerchain,
|
||||||
adjudicator_agent = deployer.make_agent()
|
adjudicator_agent = deployer.make_agent()
|
||||||
|
|
||||||
# Check default Adjudicator deployment parameters
|
# 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.hash_algorithm == token_economics.hash_algorithm
|
||||||
assert adjudicator_agent.base_penalty == token_economics.base_penalty
|
assert adjudicator_agent.base_penalty == token_economics.base_penalty
|
||||||
assert adjudicator_agent.penalty_history_coefficient == token_economics.penalty_history_coefficient
|
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()
|
another_token_agent = token_deployer.make_agent()
|
||||||
assert another_token_agent.contract_address == token_deployer.contract_address == token_agent.contract_address
|
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
|
# Policy Manager
|
||||||
#
|
#
|
||||||
|
|
|
@ -51,6 +51,23 @@ def test_deploy_ethereum_contracts(testerchain,
|
||||||
assert len(another_token_agent.contract_address) == 42
|
assert len(another_token_agent.contract_address) == 42
|
||||||
assert another_token_agent.contract_address == token_deployer.contract_address == token_agent.contract_address
|
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
|
# Policy Manager
|
||||||
#
|
#
|
||||||
|
@ -76,6 +93,7 @@ def test_deploy_ethereum_contracts(testerchain,
|
||||||
assert len(another_policy_agent.contract_address) == 42
|
assert len(another_policy_agent.contract_address) == 42
|
||||||
assert another_policy_agent.contract_address == policy_manager_deployer.contract_address == policy_agent.contract_address
|
assert another_policy_agent.contract_address == policy_manager_deployer.contract_address == policy_agent.contract_address
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Adjudicator
|
# Adjudicator
|
||||||
#
|
#
|
||||||
|
@ -101,12 +119,6 @@ def test_deploy_ethereum_contracts(testerchain,
|
||||||
assert len(another_adjudicator_agent.contract_address) == 42
|
assert len(another_adjudicator_agent.contract_address) == 42
|
||||||
assert another_adjudicator_agent.contract_address == adjudicator_deployer.contract_address == adjudicator_agent.contract_address
|
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
|
# StakingEscrow
|
||||||
#
|
#
|
||||||
staking_escrow_deployer = StakingEscrowDeployer(
|
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 staking_escrow_deployer.contract_address is constants.CONTRACT_NOT_DEPLOYED
|
||||||
assert not staking_escrow_deployer.is_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 staking_escrow_deployer.is_deployed()
|
||||||
assert len(staking_escrow_deployer.contract_address) == 42
|
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()
|
another_staking_agent = staking_escrow_deployer.make_agent()
|
||||||
assert len(another_staking_agent.contract_address) == 42
|
assert len(another_staking_agent.contract_address) == 42
|
||||||
assert another_staking_agent.contract_address == staking_escrow_deployer.contract_address == staking_agent.contract_address
|
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
|
You should have received a copy of the GNU Affero General Public License
|
||||||
along with nucypher. If not, see <https://www.gnu.org/licenses/>.
|
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.agents import ContractAgency, PolicyManagerAgent, StakingEscrowAgent
|
||||||
from nucypher.blockchain.eth.constants import POLICY_MANAGER_CONTRACT_NAME
|
from nucypher.blockchain.eth.constants import POLICY_MANAGER_CONTRACT_NAME
|
||||||
from nucypher.blockchain.eth.deployers import (DispatcherDeployer, PolicyManagerDeployer)
|
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
|
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:
|
for step_title in steps:
|
||||||
assert deployment_receipts[step_title]['status'] == 1
|
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):
|
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
|
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):
|
def test_policy_manager_has_dispatcher(policy_manager_deployer, testerchain, test_registry):
|
||||||
|
|
||||||
# Let's get the "bare" PolicyManager contract (i.e., unwrapped, no dispatcher)
|
# 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
|
import pytest
|
||||||
|
from constant_sorrow import constants
|
||||||
|
|
||||||
from nucypher.blockchain.eth.deployers import (AdjudicatorDeployer, NucypherTokenDeployer, PolicyManagerDeployer,
|
from nucypher.blockchain.eth.deployers import (AdjudicatorDeployer, NucypherTokenDeployer, PolicyManagerDeployer,
|
||||||
PreallocationEscrowDeployer, StakingEscrowDeployer,
|
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 = NucypherTokenDeployer(deployer_address=origin, registry=test_registry)
|
||||||
token_deployer.deploy()
|
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 = PolicyManagerDeployer(deployer_address=origin, registry=test_registry)
|
||||||
policy_manager_deployer.deploy()
|
policy_manager_deployer.deploy()
|
||||||
|
|
||||||
|
@ -44,7 +48,7 @@ def test_staking_interface_deployer(testerchain, deployment_progress, test_regis
|
||||||
adjudicator_deployer.deploy()
|
adjudicator_deployer.deploy()
|
||||||
|
|
||||||
staking_escrow_deployer = StakingEscrowDeployer(deployer_address=origin, registry=test_registry)
|
staking_escrow_deployer = StakingEscrowDeployer(deployer_address=origin, registry=test_registry)
|
||||||
staking_escrow_deployer.deploy()
|
staking_escrow_deployer.deploy(deployment_mode=constants.FULL)
|
||||||
|
|
||||||
#
|
#
|
||||||
# Test
|
# 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
|
You should have received a copy of the GNU Affero General Public License
|
||||||
along with nucypher. If not, see <https://www.gnu.org/licenses/>.
|
along with nucypher. If not, see <https://www.gnu.org/licenses/>.
|
||||||
"""
|
"""
|
||||||
|
from constant_sorrow import constants
|
||||||
|
|
||||||
from constant_sorrow.constants import BARE
|
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):
|
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
|
# 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:
|
for step in staking_escrow_deployer.deployment_steps:
|
||||||
assert deployment_receipts[step]['status'] == 1
|
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
|
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,
|
def test_worklock_deployment(worklock_deployer,
|
||||||
|
baseline_deployment,
|
||||||
|
staking_escrow_stub_deployer,
|
||||||
deployment_progress,
|
deployment_progress,
|
||||||
test_registry,
|
test_registry,
|
||||||
testerchain):
|
testerchain):
|
||||||
|
@ -41,6 +59,10 @@ def test_worklock_deployment(worklock_deployer,
|
||||||
for step_title in steps:
|
for step_title in steps:
|
||||||
assert deployment_receipts[step_title]['status'] == 1
|
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):
|
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
|
# 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:
|
with open(registry_filepath, 'r') as file:
|
||||||
raw_registry_data = file.read()
|
raw_registry_data = file.read()
|
||||||
registry_data = json.loads(raw_registry_data)
|
registry_data = json.loads(raw_registry_data)
|
||||||
|
|
|
@ -30,7 +30,7 @@ from nucypher.blockchain.eth.constants import (
|
||||||
DISPATCHER_CONTRACT_NAME,
|
DISPATCHER_CONTRACT_NAME,
|
||||||
NUCYPHER_TOKEN_CONTRACT_NAME,
|
NUCYPHER_TOKEN_CONTRACT_NAME,
|
||||||
POLICY_MANAGER_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.deployers import StakingEscrowDeployer, StakingInterfaceDeployer
|
||||||
from nucypher.blockchain.eth.registry import InMemoryContractRegistry, LocalContractRegistry
|
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]
|
deployed_contracts = [NUCYPHER_TOKEN_CONTRACT_NAME]
|
||||||
assert list(new_registry.enrolled_names) == deployed_contracts
|
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',
|
command = ('contracts',
|
||||||
'--contract-name', POLICY_MANAGER_CONTRACT_NAME,
|
'--contract-name', POLICY_MANAGER_CONTRACT_NAME,
|
||||||
'--provider', TEST_PROVIDER_URI,
|
'--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])
|
deployed_contracts.extend([POLICY_MANAGER_CONTRACT_NAME, DISPATCHER_CONTRACT_NAME])
|
||||||
assert list(new_registry.enrolled_names) == deployed_contracts
|
assert list(new_registry.enrolled_names) == deployed_contracts
|
||||||
|
|
||||||
# 3. Deploy Adjudicator
|
# 4. Deploy Adjudicator
|
||||||
command = ('contracts',
|
command = ('contracts',
|
||||||
'--contract-name', ADJUDICATOR_CONTRACT_NAME,
|
'--contract-name', ADJUDICATOR_CONTRACT_NAME,
|
||||||
'--provider', TEST_PROVIDER_URI,
|
'--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])
|
deployed_contracts.extend([ADJUDICATOR_CONTRACT_NAME, DISPATCHER_CONTRACT_NAME])
|
||||||
assert list(new_registry.enrolled_names) == deployed_contracts
|
assert list(new_registry.enrolled_names) == deployed_contracts
|
||||||
|
|
||||||
# 4. Deploy StakingEscrow in IDLE mode
|
# 5. Deploy StakingEscrow in IDLE mode
|
||||||
command = ('contracts',
|
command = ('contracts',
|
||||||
'--contract-name', STAKING_ESCROW_CONTRACT_NAME,
|
'--contract-name', STAKING_ESCROW_CONTRACT_NAME,
|
||||||
'--mode', 'idle',
|
'--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)
|
result = click_runner.invoke(deploy, command, input=user_input, catch_exceptions=False)
|
||||||
assert result.exit_code == 0
|
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
|
assert list(new_registry.enrolled_names) == deployed_contracts
|
||||||
|
|
||||||
# 5. Activate StakingEscrow
|
# 6. Activate StakingEscrow
|
||||||
command = ('contracts',
|
command = ('contracts',
|
||||||
'--contract-name', STAKING_ESCROW_CONTRACT_NAME,
|
'--contract-name', STAKING_ESCROW_CONTRACT_NAME,
|
||||||
'--activate',
|
'--activate',
|
||||||
|
|
|
@ -12,7 +12,8 @@ import "contracts/StakingEscrow.sol";
|
||||||
*/
|
*/
|
||||||
contract PolicyManagerBad is PolicyManager {
|
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) {}
|
function getNodeFeeDelta(address, uint16) public view override returns (int256) {}
|
||||||
|
|
||||||
|
@ -26,7 +27,8 @@ contract PolicyManagerV2Mock is PolicyManager {
|
||||||
|
|
||||||
uint256 public valueToCheck;
|
uint256 public valueToCheck;
|
||||||
|
|
||||||
constructor(StakingEscrow _escrow, uint32 _secondsPerPeriod) PolicyManager(_escrow, _secondsPerPeriod) {}
|
constructor(StakingEscrow _escrow) PolicyManager(_escrow) {
|
||||||
|
}
|
||||||
|
|
||||||
function setValueToCheck(uint256 _valueToCheck) public {
|
function setValueToCheck(uint256 _valueToCheck) public {
|
||||||
valueToCheck = _valueToCheck;
|
valueToCheck = _valueToCheck;
|
||||||
|
@ -142,7 +144,8 @@ contract StakingEscrowForPolicyMock {
|
||||||
*/
|
*/
|
||||||
contract ExtendedPolicyManager is PolicyManager {
|
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 {
|
function setNodeFeeDelta(address _node, uint16 _period, int256 _value) external {
|
||||||
NodeInfo storage node = nodes[_node];
|
NodeInfo storage node = nodes[_node];
|
||||||
|
|
|
@ -14,6 +14,9 @@ contract EnhancedStakingEscrow is StakingEscrow {
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
NuCypherToken _token,
|
NuCypherToken _token,
|
||||||
|
PolicyManagerInterface _policyManager,
|
||||||
|
AdjudicatorInterface _adjudicator,
|
||||||
|
WorkLockInterface _workLock,
|
||||||
uint32 _hoursPerPeriod,
|
uint32 _hoursPerPeriod,
|
||||||
uint256 _issuanceDecayCoefficient,
|
uint256 _issuanceDecayCoefficient,
|
||||||
uint256 _lockDurationCoefficient1,
|
uint256 _lockDurationCoefficient1,
|
||||||
|
@ -24,13 +27,13 @@ contract EnhancedStakingEscrow is StakingEscrow {
|
||||||
uint16 _minLockedPeriods,
|
uint16 _minLockedPeriods,
|
||||||
uint256 _minAllowableLockedTokens,
|
uint256 _minAllowableLockedTokens,
|
||||||
uint256 _maxAllowableLockedTokens,
|
uint256 _maxAllowableLockedTokens,
|
||||||
uint16 _minWorkerPeriods,
|
uint16 _minWorkerPeriods
|
||||||
PolicyManagerInterface _policyManager,
|
|
||||||
AdjudicatorInterface _adjudicator,
|
|
||||||
WorkLockInterface _workLock
|
|
||||||
)
|
)
|
||||||
StakingEscrow(
|
StakingEscrow(
|
||||||
_token,
|
_token,
|
||||||
|
_policyManager,
|
||||||
|
_adjudicator,
|
||||||
|
_workLock,
|
||||||
_hoursPerPeriod,
|
_hoursPerPeriod,
|
||||||
_issuanceDecayCoefficient,
|
_issuanceDecayCoefficient,
|
||||||
_lockDurationCoefficient1,
|
_lockDurationCoefficient1,
|
||||||
|
@ -41,10 +44,7 @@ contract EnhancedStakingEscrow is StakingEscrow {
|
||||||
_minLockedPeriods,
|
_minLockedPeriods,
|
||||||
_minAllowableLockedTokens,
|
_minAllowableLockedTokens,
|
||||||
_maxAllowableLockedTokens,
|
_maxAllowableLockedTokens,
|
||||||
_minWorkerPeriods,
|
_minWorkerPeriods
|
||||||
_policyManager,
|
|
||||||
_adjudicator,
|
|
||||||
_workLock
|
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -74,6 +74,9 @@ contract StakingEscrowBad is StakingEscrow {
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
NuCypherToken _token,
|
NuCypherToken _token,
|
||||||
|
PolicyManagerInterface _policyManager,
|
||||||
|
AdjudicatorInterface _adjudicator,
|
||||||
|
WorkLockInterface _workLock,
|
||||||
uint32 _hoursPerPeriod,
|
uint32 _hoursPerPeriod,
|
||||||
uint256 _issuanceDecayCoefficient,
|
uint256 _issuanceDecayCoefficient,
|
||||||
uint256 _lockDurationCoefficient1,
|
uint256 _lockDurationCoefficient1,
|
||||||
|
@ -84,13 +87,13 @@ contract StakingEscrowBad is StakingEscrow {
|
||||||
uint16 _minLockedPeriods,
|
uint16 _minLockedPeriods,
|
||||||
uint256 _minAllowableLockedTokens,
|
uint256 _minAllowableLockedTokens,
|
||||||
uint256 _maxAllowableLockedTokens,
|
uint256 _maxAllowableLockedTokens,
|
||||||
uint16 _minWorkerPeriods,
|
uint16 _minWorkerPeriods
|
||||||
PolicyManagerInterface _policyManager,
|
|
||||||
AdjudicatorInterface _adjudicator,
|
|
||||||
WorkLockInterface _workLock
|
|
||||||
)
|
)
|
||||||
StakingEscrow(
|
StakingEscrow(
|
||||||
_token,
|
_token,
|
||||||
|
_policyManager,
|
||||||
|
_adjudicator,
|
||||||
|
_workLock,
|
||||||
_hoursPerPeriod,
|
_hoursPerPeriod,
|
||||||
_issuanceDecayCoefficient,
|
_issuanceDecayCoefficient,
|
||||||
_lockDurationCoefficient1,
|
_lockDurationCoefficient1,
|
||||||
|
@ -101,10 +104,7 @@ contract StakingEscrowBad is StakingEscrow {
|
||||||
_minLockedPeriods,
|
_minLockedPeriods,
|
||||||
_minAllowableLockedTokens,
|
_minAllowableLockedTokens,
|
||||||
_maxAllowableLockedTokens,
|
_maxAllowableLockedTokens,
|
||||||
_minWorkerPeriods,
|
_minWorkerPeriods
|
||||||
_policyManager,
|
|
||||||
_adjudicator,
|
|
||||||
_workLock
|
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
@ -123,6 +123,9 @@ contract StakingEscrowV2Mock is StakingEscrow {
|
||||||
|
|
||||||
constructor(
|
constructor(
|
||||||
NuCypherToken _token,
|
NuCypherToken _token,
|
||||||
|
PolicyManagerInterface _policyManager,
|
||||||
|
AdjudicatorInterface _adjudicator,
|
||||||
|
WorkLockInterface _workLock,
|
||||||
uint32 _hoursPerPeriod,
|
uint32 _hoursPerPeriod,
|
||||||
uint256 _issuanceDecayCoefficient,
|
uint256 _issuanceDecayCoefficient,
|
||||||
uint256 _lockDurationCoefficient1,
|
uint256 _lockDurationCoefficient1,
|
||||||
|
@ -134,13 +137,13 @@ contract StakingEscrowV2Mock is StakingEscrow {
|
||||||
uint256 _minAllowableLockedTokens,
|
uint256 _minAllowableLockedTokens,
|
||||||
uint256 _maxAllowableLockedTokens,
|
uint256 _maxAllowableLockedTokens,
|
||||||
uint16 _minWorkerPeriods,
|
uint16 _minWorkerPeriods,
|
||||||
PolicyManagerInterface _policyManager,
|
|
||||||
AdjudicatorInterface _adjudicator,
|
|
||||||
WorkLockInterface _workLock,
|
|
||||||
uint256 _valueToCheck
|
uint256 _valueToCheck
|
||||||
)
|
)
|
||||||
StakingEscrow(
|
StakingEscrow(
|
||||||
_token,
|
_token,
|
||||||
|
_policyManager,
|
||||||
|
_adjudicator,
|
||||||
|
_workLock,
|
||||||
_hoursPerPeriod,
|
_hoursPerPeriod,
|
||||||
_issuanceDecayCoefficient,
|
_issuanceDecayCoefficient,
|
||||||
_lockDurationCoefficient1,
|
_lockDurationCoefficient1,
|
||||||
|
@ -151,10 +154,7 @@ contract StakingEscrowV2Mock is StakingEscrow {
|
||||||
_minLockedPeriods,
|
_minLockedPeriods,
|
||||||
_minAllowableLockedTokens,
|
_minAllowableLockedTokens,
|
||||||
_maxAllowableLockedTokens,
|
_maxAllowableLockedTokens,
|
||||||
_minWorkerPeriods,
|
_minWorkerPeriods
|
||||||
_policyManager,
|
|
||||||
_adjudicator,
|
|
||||||
_workLock
|
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
valueToCheck = _valueToCheck;
|
valueToCheck = _valueToCheck;
|
||||||
|
|
|
@ -70,8 +70,20 @@ def token(token_economics, deploy_contract):
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope='module')
|
@pytest.fixture(scope='module')
|
||||||
def policy_manager_bare(testerchain, token_economics, deploy_contract):
|
def escrow_dispatcher(testerchain, token, token_economics, deploy_contract):
|
||||||
contract, _ = deploy_contract('PolicyManager', NULL_ADDRESS, token_economics.seconds_per_period)
|
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
|
return contract
|
||||||
|
|
||||||
|
|
||||||
|
@ -89,14 +101,15 @@ def policy_manager(testerchain, policy_manager_bare, policy_manager_dispatcher):
|
||||||
abi=policy_manager_bare.abi,
|
abi=policy_manager_bare.abi,
|
||||||
address=policy_manager_dispatcher.address,
|
address=policy_manager_dispatcher.address,
|
||||||
ContractFactoryClass=Contract)
|
ContractFactoryClass=Contract)
|
||||||
|
|
||||||
return contract
|
return contract
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope='module')
|
@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(
|
contract, _ = deploy_contract(
|
||||||
'Adjudicator',
|
'Adjudicator',
|
||||||
NULL_ADDRESS,
|
escrow_dispatcher.address,
|
||||||
*token_economics.slashing_deployment_parameters)
|
*token_economics.slashing_deployment_parameters)
|
||||||
return contract
|
return contract
|
||||||
|
|
||||||
|
@ -114,11 +127,12 @@ def adjudicator(testerchain, adjudicator_bare, adjudicator_dispatcher):
|
||||||
abi=adjudicator_bare.abi,
|
abi=adjudicator_bare.abi,
|
||||||
address=adjudicator_dispatcher.address,
|
address=adjudicator_dispatcher.address,
|
||||||
ContractFactoryClass=Contract)
|
ContractFactoryClass=Contract)
|
||||||
|
|
||||||
return contract
|
return contract
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope='module')
|
@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
|
# Creator deploys the worklock using test values
|
||||||
now = testerchain.w3.eth.getBlock('latest').timestamp
|
now = testerchain.w3.eth.getBlock('latest').timestamp
|
||||||
start_bid_date = ((now + 3600) // 3600 + 1) * 3600 # beginning of the next hour plus 1 hour
|
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, _ = deploy_contract(
|
||||||
contract_name='WorkLock',
|
contract_name='WorkLock',
|
||||||
_token=token.address,
|
_token=token.address,
|
||||||
|
_escrow=escrow_dispatcher.address,
|
||||||
_startBidDate=start_bid_date,
|
_startBidDate=start_bid_date,
|
||||||
_endBidDate=end_bid_date,
|
_endBidDate=end_bid_date,
|
||||||
_endCancellationDate=end_cancellation_date,
|
_endCancellationDate=end_cancellation_date,
|
||||||
|
@ -137,44 +152,42 @@ def worklock(testerchain, token, token_economics, deploy_contract):
|
||||||
_stakingPeriods=staking_periods,
|
_stakingPeriods=staking_periods,
|
||||||
_minAllowedBid=min_allowed_bid
|
_minAllowedBid=min_allowed_bid
|
||||||
)
|
)
|
||||||
|
|
||||||
return contract
|
return contract
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope='module')
|
@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
|
# Creator deploys the escrow
|
||||||
contract, _ = deploy_contract(
|
contract, _ = deploy_contract(
|
||||||
'EnhancedStakingEscrow',
|
'EnhancedStakingEscrow',
|
||||||
token.address,
|
token.address,
|
||||||
*token_economics.staking_deployment_parameters,
|
|
||||||
policy_manager.address,
|
policy_manager.address,
|
||||||
adjudicator.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
|
return contract
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope='module')
|
@pytest.fixture(scope='module')
|
||||||
def escrow_dispatcher(testerchain, escrow_bare, deploy_contract):
|
def escrow(testerchain, escrow_bare, escrow_dispatcher):
|
||||||
dispatcher, _ = deploy_contract('Dispatcher', escrow_bare.address)
|
|
||||||
return dispatcher
|
|
||||||
|
|
||||||
|
|
||||||
@pytest.fixture(scope='module')
|
|
||||||
def escrow(testerchain, escrow_bare, policy_manager, adjudicator, worklock, escrow_dispatcher):
|
|
||||||
# Wrap dispatcher contract
|
# Wrap dispatcher contract
|
||||||
contract = testerchain.client.get_contract(
|
contract = testerchain.client.get_contract(
|
||||||
abi=escrow_bare.abi,
|
abi=escrow_bare.abi,
|
||||||
address=escrow_dispatcher.address,
|
address=escrow_dispatcher.address,
|
||||||
ContractFactoryClass=Contract)
|
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
|
return contract
|
||||||
|
|
||||||
|
|
||||||
|
@ -903,8 +916,8 @@ def test_upgrading_and_rollback(testerchain,
|
||||||
policy_manager_dispatcher,
|
policy_manager_dispatcher,
|
||||||
staking_interface_router,
|
staking_interface_router,
|
||||||
multisig,
|
multisig,
|
||||||
worklock,
|
|
||||||
adjudicator,
|
adjudicator,
|
||||||
|
worklock,
|
||||||
deploy_contract):
|
deploy_contract):
|
||||||
creator, staker1, staker2, staker3, staker4, alice1, alice2, *contracts_owners =\
|
creator, staker1, staker2, staker3, staker4, alice1, alice2, *contracts_owners =\
|
||||||
testerchain.client.accounts
|
testerchain.client.accounts
|
||||||
|
@ -917,12 +930,12 @@ def test_upgrading_and_rollback(testerchain,
|
||||||
escrow_v2, _ = deploy_contract(
|
escrow_v2, _ = deploy_contract(
|
||||||
'StakingEscrow',
|
'StakingEscrow',
|
||||||
token.address,
|
token.address,
|
||||||
*token_economics.staking_deployment_parameters,
|
|
||||||
policy_manager.address,
|
policy_manager.address,
|
||||||
adjudicator.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
|
# Staker and Alice can't upgrade contracts, only owner can
|
||||||
with pytest.raises((TransactionFailed, ValueError)):
|
with pytest.raises((TransactionFailed, ValueError)):
|
||||||
tx = escrow_dispatcher.functions.upgrade(escrow_v2.address).transact({'from': alice1})
|
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, client, bad_node, node1, node2, node3, *everyone_else = testerchain.client.accounts
|
||||||
|
|
||||||
# Creator deploys the policy manager
|
# Creator deploys the policy manager
|
||||||
contract, _ = deploy_contract('PolicyManager', escrow.address, 0)
|
contract, _ = deploy_contract('PolicyManager', escrow.address)
|
||||||
|
|
||||||
# Give client some ether
|
# Give client some ether
|
||||||
tx = testerchain.client.send_transaction(
|
tx = testerchain.client.send_transaction(
|
||||||
|
|
|
@ -522,18 +522,18 @@ def test_upgrading(testerchain, deploy_contract):
|
||||||
|
|
||||||
# Only escrow contract is allowed in PolicyManager constructor
|
# Only escrow contract is allowed in PolicyManager constructor
|
||||||
with pytest.raises((TransactionFailed, ValueError)):
|
with pytest.raises((TransactionFailed, ValueError)):
|
||||||
deploy_contract('PolicyManager', creator, 0)
|
deploy_contract('PolicyManager', creator)
|
||||||
|
|
||||||
# Deploy contracts
|
# Deploy contracts
|
||||||
escrow1, _ = deploy_contract('StakingEscrowForPolicyMock', 1)
|
escrow1, _ = deploy_contract('StakingEscrowForPolicyMock', 1)
|
||||||
escrow2, _ = deploy_contract('StakingEscrowForPolicyMock', 1)
|
escrow2, _ = deploy_contract('StakingEscrowForPolicyMock', 1)
|
||||||
address1 = escrow1.address
|
address1 = escrow1.address
|
||||||
address2 = escrow2.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)
|
dispatcher, _ = deploy_contract('Dispatcher', contract_library_v1.address)
|
||||||
|
|
||||||
# Deploy second version of the contract
|
# 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(
|
contract = testerchain.client.get_contract(
|
||||||
abi=contract_library_v2.abi,
|
abi=contract_library_v2.abi,
|
||||||
address=dispatcher.address,
|
address=dispatcher.address,
|
||||||
|
@ -562,7 +562,7 @@ def test_upgrading(testerchain, deploy_contract):
|
||||||
assert 3 == contract.functions.valueToCheck().call()
|
assert 3 == contract.functions.valueToCheck().call()
|
||||||
|
|
||||||
# Can't upgrade to the previous version or to the bad version
|
# 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)):
|
with pytest.raises((TransactionFailed, ValueError)):
|
||||||
tx = dispatcher.functions.upgrade(contract_library_v1.address).transact({'from': creator})
|
tx = dispatcher.functions.upgrade(contract_library_v1.address).transact({'from': creator})
|
||||||
testerchain.wait_for_receipt(tx)
|
testerchain.wait_for_receipt(tx)
|
||||||
|
@ -616,7 +616,7 @@ def test_handling_wrong_state(testerchain, deploy_contract):
|
||||||
|
|
||||||
# Prepare enhanced version of contract
|
# Prepare enhanced version of contract
|
||||||
escrow, _ = deploy_contract('StakingEscrowForPolicyMock', 1)
|
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})
|
tx = escrow.functions.setPolicyManager(policy_manager.address).transact({'from': creator})
|
||||||
testerchain.wait_for_receipt(tx)
|
testerchain.wait_for_receipt(tx)
|
||||||
|
|
||||||
|
|
|
@ -84,11 +84,12 @@ def escrow_contract(testerchain,
|
||||||
deploy_parameters[5] = 0
|
deploy_parameters[5] = 0
|
||||||
deploy_parameters[6] = 0
|
deploy_parameters[6] = 0
|
||||||
|
|
||||||
deploy_parameters.append(policy_manager.address)
|
contract, _ = deploy_contract('EnhancedStakingEscrow',
|
||||||
deploy_parameters.append(adjudicator.address)
|
token.address,
|
||||||
deploy_parameters.append(worklock.address)
|
policy_manager.address,
|
||||||
|
adjudicator.address,
|
||||||
contract, _ = deploy_contract('EnhancedStakingEscrow', token.address, *deploy_parameters)
|
worklock.address,
|
||||||
|
*deploy_parameters)
|
||||||
|
|
||||||
if request.param:
|
if request.param:
|
||||||
dispatcher, _ = deploy_contract('Dispatcher', contract.address)
|
dispatcher, _ = deploy_contract('Dispatcher', contract.address)
|
||||||
|
|
|
@ -45,10 +45,10 @@ def test_upgrading(testerchain, token, token_economics, deploy_contract):
|
||||||
contract_library_v1, _ = deploy_contract(
|
contract_library_v1, _ = deploy_contract(
|
||||||
'StakingEscrow',
|
'StakingEscrow',
|
||||||
token.address,
|
token.address,
|
||||||
*token_economics.staking_deployment_parameters,
|
|
||||||
policy_manager.address,
|
policy_manager.address,
|
||||||
adjudicator.address,
|
adjudicator.address,
|
||||||
worklock.address
|
worklock.address,
|
||||||
|
*token_economics.staking_deployment_parameters
|
||||||
)
|
)
|
||||||
dispatcher, _ = deploy_contract('Dispatcher', contract_library_v1.address)
|
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, _ = deploy_contract(
|
||||||
contract_name='WorkLock',
|
contract_name='WorkLock',
|
||||||
_token=token.address,
|
_token=token.address,
|
||||||
|
_escrow=escrow.address,
|
||||||
_startBidDate=start_bid_date,
|
_startBidDate=start_bid_date,
|
||||||
_endBidDate=end_bid_date,
|
_endBidDate=end_bid_date,
|
||||||
_endCancellationDate=end_cancellation_date,
|
_endCancellationDate=end_cancellation_date,
|
||||||
|
@ -67,9 +68,6 @@ def worklock_factory(testerchain, token, escrow, token_economics, deploy_contrac
|
||||||
_minAllowedBid=MIN_ALLOWED_BID
|
_minAllowedBid=MIN_ALLOWED_BID
|
||||||
)
|
)
|
||||||
|
|
||||||
tx = contract.functions.setStakingEscrow(escrow.address).transact()
|
|
||||||
testerchain.wait_for_receipt(tx)
|
|
||||||
|
|
||||||
if supply > 0:
|
if supply > 0:
|
||||||
tx = token.functions.approve(contract.address, supply).transact()
|
tx = token.functions.approve(contract.address, supply).transact()
|
||||||
testerchain.wait_for_receipt(tx)
|
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
|
# Set gas only for one check
|
||||||
tx = worklock.functions.verifyBiddingCorrectness(gas_to_save_state)\
|
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)
|
testerchain.wait_for_receipt(tx)
|
||||||
assert worklock.functions.nextBidderToCheck().call() == 1
|
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
|
# But can verify only one of them
|
||||||
assert worklock.functions.nextBidderToCheck().call() == 0
|
assert worklock.functions.nextBidderToCheck().call() == 0
|
||||||
tx = worklock.functions.verifyBiddingCorrectness(gas_to_save_state)\
|
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)
|
testerchain.wait_for_receipt(tx)
|
||||||
assert worklock.functions.nextBidderToCheck().call() == 1
|
assert worklock.functions.nextBidderToCheck().call() == 1
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,7 @@ import os
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
|
||||||
import requests
|
import requests
|
||||||
|
from constant_sorrow import constants
|
||||||
from web3.exceptions import ValidationError
|
from web3.exceptions import ValidationError
|
||||||
|
|
||||||
from nucypher.blockchain.eth.deployers import AdjudicatorDeployer, BaseContractDeployer, NucypherTokenDeployer, \
|
from nucypher.blockchain.eth.deployers import AdjudicatorDeployer, BaseContractDeployer, NucypherTokenDeployer, \
|
||||||
|
@ -83,27 +84,43 @@ CONSTRUCTOR_OVERRIDES = {
|
||||||
"_firstPhaseMaxIssuance": None,
|
"_firstPhaseMaxIssuance": None,
|
||||||
"_miningCoefficient": 2,
|
"_miningCoefficient": 2,
|
||||||
"_lockedPeriodsCoefficient": 1,
|
"_lockedPeriodsCoefficient": 1,
|
||||||
"_rewardedPeriods": 1},
|
"_rewardedPeriods": 1}
|
||||||
"v5.6.1": {"_isTestContract": True}
|
}
|
||||||
},
|
}
|
||||||
PolicyManagerDeployer.contract_name: {"v6.2.1": {"_secondsPerPeriod": None}}
|
|
||||||
|
FORCE_SKIP = {
|
||||||
|
StakingEscrowDeployer.contract_name: ["v5.6.1"]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def deploy_earliest_contract(blockchain_interface: BlockchainDeployerInterface,
|
def deploy_base_contract(blockchain_interface: BlockchainDeployerInterface,
|
||||||
deployer: BaseContractDeployer):
|
deployer: BaseContractDeployer,
|
||||||
|
skipt_test: bool):
|
||||||
contract_name = deployer.contract_name
|
contract_name = deployer.contract_name
|
||||||
latest_version, _data = blockchain_interface.find_raw_contract_data(contract_name, "latest")
|
latest_version, _data = blockchain_interface.find_raw_contract_data(contract_name, "latest")
|
||||||
try:
|
try:
|
||||||
overrides = CONSTRUCTOR_OVERRIDES[contract_name][latest_version]
|
overrides = CONSTRUCTOR_OVERRIDES[contract_name][latest_version]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
overrides = dict()
|
overrides = dict()
|
||||||
|
|
||||||
|
version = "latest" if skipt_test else "earliest"
|
||||||
try:
|
try:
|
||||||
deployer.deploy(contract_version="earliest", **overrides)
|
deployer.deploy(contract_version=version, deployment_mode=constants.FULL, **overrides)
|
||||||
except ValidationError:
|
except ValidationError:
|
||||||
pass # Skip errors related to initialization
|
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):
|
def test_upgradeability(temp_dir_path):
|
||||||
# Prepare remote source for compilation
|
# Prepare remote source for compilation
|
||||||
download_github_dir(GITHUB_SOURCE_LINK, temp_dir_path)
|
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)
|
economics = make_token_economics(blockchain_interface)
|
||||||
|
|
||||||
# Check contracts with multiple versions
|
# Check contracts with multiple versions
|
||||||
raw_contracts = blockchain_interface._raw_contract_cache
|
|
||||||
contract_name = AdjudicatorDeployer.contract_name
|
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
|
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
|
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
|
return
|
||||||
|
|
||||||
# Prepare master version of contracts and upgrade to the latest
|
# Prepare master version of contracts and upgrade to the latest
|
||||||
|
@ -145,36 +161,42 @@ def test_upgradeability(temp_dir_path):
|
||||||
economics=economics)
|
economics=economics)
|
||||||
token_deployer.deploy()
|
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,
|
policy_manager_deployer = PolicyManagerDeployer(registry=registry,
|
||||||
deployer_address=origin,
|
deployer_address=origin,
|
||||||
economics=economics)
|
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,
|
adjudicator_deployer = AdjudicatorDeployer(registry=registry,
|
||||||
deployer_address=origin,
|
deployer_address=origin,
|
||||||
economics=economics)
|
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,
|
if skip_staking_escrow_test:
|
||||||
deployer_address=origin,
|
worklock_deployer = WorklockDeployer(registry=registry,
|
||||||
economics=economics)
|
deployer_address=origin,
|
||||||
worklock_deployer.deploy()
|
economics=economics)
|
||||||
|
worklock_deployer.deploy()
|
||||||
|
|
||||||
staking_escrow_deployer = StakingEscrowDeployer(registry=registry,
|
staking_escrow_deployer = StakingEscrowDeployer(registry=registry,
|
||||||
deployer_address=origin,
|
deployer_address=origin,
|
||||||
economics=economics)
|
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:
|
if not skip_staking_escrow_test:
|
||||||
policy_manager_deployer.upgrade(contract_version="latest", confirmations=0)
|
|
||||||
|
|
||||||
if test_adjudicator:
|
|
||||||
adjudicator_deployer.upgrade(contract_version="latest", confirmations=0)
|
|
||||||
|
|
||||||
if test_staking_escrow:
|
|
||||||
# TODO prepare at least one staker before calling upgrade
|
# TODO prepare at least one staker before calling upgrade
|
||||||
staking_escrow_deployer.upgrade(contract_version="latest", confirmations=0)
|
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:
|
finally:
|
||||||
# Unregister interface # TODO: Move to method?
|
# Unregister interface # TODO: Move to method?
|
||||||
with contextlib.suppress(KeyError):
|
with contextlib.suppress(KeyError):
|
||||||
|
|
|
@ -108,6 +108,7 @@ from tests.utils.ursula import (
|
||||||
MOCK_KNOWN_URSULAS_CACHE,
|
MOCK_KNOWN_URSULAS_CACHE,
|
||||||
_mock_ursula_reencrypts
|
_mock_ursula_reencrypts
|
||||||
)
|
)
|
||||||
|
from constant_sorrow.constants import (FULL, INIT)
|
||||||
|
|
||||||
test_logger = Logger("test-logger")
|
test_logger = Logger("test-logger")
|
||||||
|
|
||||||
|
@ -555,6 +556,11 @@ def _make_agency(testerchain,
|
||||||
registry=test_registry)
|
registry=test_registry)
|
||||||
token_deployer.deploy()
|
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,
|
policy_manager_deployer = PolicyManagerDeployer(deployer_address=origin,
|
||||||
economics=token_economics,
|
economics=token_economics,
|
||||||
registry=test_registry)
|
registry=test_registry)
|
||||||
|
@ -565,6 +571,11 @@ def _make_agency(testerchain,
|
||||||
registry=test_registry)
|
registry=test_registry)
|
||||||
adjudicator_deployer.deploy()
|
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,
|
worklock_deployer = WorklockDeployer(deployer_address=origin,
|
||||||
economics=token_economics,
|
economics=token_economics,
|
||||||
registry=test_registry)
|
registry=test_registry)
|
||||||
|
@ -573,12 +584,7 @@ def _make_agency(testerchain,
|
||||||
staking_escrow_deployer = StakingEscrowDeployer(deployer_address=origin,
|
staking_escrow_deployer = StakingEscrowDeployer(deployer_address=origin,
|
||||||
economics=token_economics,
|
economics=token_economics,
|
||||||
registry=test_registry)
|
registry=test_registry)
|
||||||
staking_escrow_deployer.deploy()
|
staking_escrow_deployer.deploy(deployment_mode=FULL)
|
||||||
|
|
||||||
staking_interface_deployer = StakingInterfaceDeployer(deployer_address=origin,
|
|
||||||
economics=token_economics,
|
|
||||||
registry=test_registry)
|
|
||||||
staking_interface_deployer.deploy()
|
|
||||||
|
|
||||||
token_agent = token_deployer.make_agent() # 1 Token
|
token_agent = token_deployer.make_agent() # 1 Token
|
||||||
staking_agent = staking_escrow_deployer.make_agent() # 2 Staking Escrow
|
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.economics import BaseEconomics, StandardTokenEconomics
|
||||||
from nucypher.blockchain.eth.actors import ContractAdministrator
|
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.interfaces import BlockchainDeployerInterface, BlockchainInterfaceFactory
|
||||||
from nucypher.blockchain.eth.registry import InMemoryContractRegistry, BaseContractRegistry
|
from nucypher.blockchain.eth.registry import InMemoryContractRegistry, BaseContractRegistry
|
||||||
from nucypher.blockchain.eth.sol.compile.constants import TEST_SOLIDITY_SOURCE_ROOT, SOLIDITY_SOURCE_ROOT
|
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,
|
NUMBER_OF_URSULAS_IN_BLOCKCHAIN_TESTS,
|
||||||
PYEVM_DEV_URI
|
PYEVM_DEV_URI
|
||||||
)
|
)
|
||||||
|
from constant_sorrow.constants import (INIT)
|
||||||
|
|
||||||
|
|
||||||
def token_airdrop(token_agent, amount: NU, origin: str, addresses: List[str]):
|
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
|
gas_limit = None # TODO: Gas management - #842
|
||||||
for deployer_class in admin.primary_deployer_classes:
|
for deployer_class in admin.primary_deployer_classes:
|
||||||
if deployer_class in ContractAdministrator.standard_deployer_classes:
|
if deployer_class is StakingEscrowDeployer:
|
||||||
admin.deploy_contract(contract_name=deployer_class.contract_name, gas_limit=gas_limit)
|
admin.deploy_contract(contract_name=deployer_class.contract_name,
|
||||||
|
gas_limit=gas_limit,
|
||||||
|
deployment_mode=INIT)
|
||||||
else:
|
else:
|
||||||
admin.deploy_contract(contract_name=deployer_class.contract_name, gas_limit=gas_limit)
|
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
|
return testerchain, registry
|
||||||
|
|
||||||
@property
|
@property
|
||||||
|
|
Loading…
Reference in New Issue