Deprecates TestEconomics; Adds worklock supply and funding management - Extracts statistical methods to worklock agent.

pull/1550/head
Kieran Prasch 2020-01-12 13:57:09 -08:00 committed by Kieran R. Prasch
parent b2bf0f487d
commit 355d7ff887
9 changed files with 192 additions and 208 deletions

View File

@ -207,12 +207,28 @@ class BaseEconomics:
@property
def worklock_deployment_parameters(self):
"""
0 token - Token contract
1 escrow - Escrow contract
2 router - Router contract
...
3 startBidDate - Timestamp when bidding starts
4 endBidDate - Timestamp when bidding will end
5 boostingRefund - Coefficient to boost refund ETH
6 lockingDuration - Duration of tokens locking
"""
deployment_parameters = [self.bidding_start_date,
self.bidding_end_date,
self.worklock_boosting_refund_rate,
self.worklock_commitment_duration]
return tuple(map(int, deployment_parameters))
@property
def bidding_duration(self) -> int:
"""Returns the total bidding window duration in seconds."""
return self.bidding_end_date - self.bidding_start_date
class StandardTokenEconomics(BaseEconomics):
"""
@ -335,68 +351,6 @@ class StandardTokenEconomics(BaseEconomics):
return self.cumulative_rewards_at_period(period) - self.cumulative_rewards_at_period(period-1)
class TestEconomics(StandardTokenEconomics):
# TODO: Move to fixture as instance of base economics
nickname = 'test-economics'
description = f'Identical to {StandardTokenEconomics.nickname} with Instant-start one-hour worklock.'
__default_worklock_boosting_refund_rate = 200
__default_worklock_supply = NotImplemented
def __init__(self,
worklock_boosting_refund_rate: int = __default_worklock_boosting_refund_rate,
worklock_supply: int = __default_worklock_supply,
*args, **kwargs):
#
# Injected
#
super().__init__(worklock_boosting_refund_rate=worklock_boosting_refund_rate,
worklock_supply=worklock_supply,
*args, **kwargs)
#
# Calculated
#
self.worklock_supply = self.maximum_allowed_locked
@property
def worklock_deployment_parameters(self):
"""
0 token - Token contract
1 escrow - Escrow contract
2 router - Router contract
...
3 startBidDate - Timestamp when bidding starts
4 endBidDate - Timestamp when bidding will end
5 boostingRefund - Coefficient to boost refund ETH
6 lockingDuration - Duration of tokens locking
"""
from nucypher.blockchain.eth.interfaces import BlockchainInterfaceFactory
# from nucypher.utilities.sandbox.constants import TEST_PROVIDER_URI
# Get current blocktime
blockchain = BlockchainInterfaceFactory.get_interface()
now = blockchain.w3.eth.getBlock(block_identifier='latest').timestamp
# Calculate instant start time
one_hour_in_seconds = (60 * 60)
start_date = now
self.bidding_start_date = start_date
self.bidding_end_date = start_date + one_hour_in_seconds
self.worklock_commitment_duration = 2 * self.minimum_locked_periods
deployment_parameters = [self.bidding_start_date,
self.bidding_end_date,
self.worklock_boosting_refund_rate,
self.worklock_commitment_duration]
return tuple(map(int, deployment_parameters))
class EconomicsFactory:
# TODO: Enforce singleton
@ -424,7 +378,7 @@ class EconomicsFactory:
# Token
total_supply = token_agent.contract.functions.totalSupply().call()
reward_supply = staking_agent.contract.functions.getReservedReward().call()
# it's not real initial_supply value because used current reward instead of initial
# Not the "real" initial_supply value because used current reward instead of initial reward
initial_supply = total_supply - reward_supply
# Staking Escrow
@ -437,14 +391,12 @@ class EconomicsFactory:
# Worklock
worklock_parameters = worklock_agent.worklock_parameters()
worklock_supply = worklock_agent.total_supply()
# Aggregate (order-sensitive)
economics_parameters = (initial_supply,
total_supply,
*staking_parameters,
*slashing_parameters,
worklock_supply,
*worklock_parameters)
economics = BaseEconomics(*economics_parameters)

View File

@ -16,10 +16,10 @@ along with nucypher. If not, see <https://www.gnu.org/licenses/>.
"""
import math
import random
from typing import Generator, List, Tuple, Union
import math
from constant_sorrow.constants import NO_CONTRACT_AVAILABLE
from eth_utils.address import to_checksum_address
from twisted.logger import Logger
@ -39,7 +39,6 @@ from nucypher.blockchain.eth.constants import (
from nucypher.blockchain.eth.decorators import validate_checksum_address
from nucypher.blockchain.eth.interfaces import BlockchainInterface, BlockchainInterfaceFactory
from nucypher.blockchain.eth.registry import AllocationRegistry, BaseContractRegistry, IndividualAllocationRegistry
from nucypher.blockchain.eth.sol.compile import SolidityCompiler
from nucypher.blockchain.eth.utils import epoch_to_period
from nucypher.crypto.api import sha256_digest
@ -614,6 +613,10 @@ class StakingEscrowAgent(EthereumContractAgent):
result = missing_confirmations
return result
def get_completed_work(self, allocation_address: str):
total_completed_work = self.contract.functions.getCompletedWork(allocation_address).call()
return total_completed_work
class PolicyManagerAgent(EthereumContractAgent):
@ -955,20 +958,6 @@ class WorkLockAgent(EthereumContractAgent):
registry_contract_name = "WorkLock"
def fund(self, sender_address: str, supply) -> dict:
"""Convenience method for funding the contract."""
supply = supply.to_nunits()
token_agent = ContractAgency.get_agent(NucypherTokenAgent, registry=self.registry)
approve_function = token_agent.contract.functions.approve(self.contract_address, supply)
approve_receipt = self.blockchain.send_transaction(contract_function=approve_function,
sender_address=sender_address)
funding_function = self.contract.functions.tokenDeposit(supply)
funding_receipt = self.blockchain.send_transaction(contract_function=funding_function,
sender_address=sender_address)
return funding_receipt
def bid(self, value: int, sender_address: str) -> dict:
"""
Bid for NU tokens with ETH.
@ -984,48 +973,40 @@ class WorkLockAgent(EthereumContractAgent):
return current_bid
def get_allocation_from_bidder(self, bidder_address: str) -> str:
preallocation_address = self.contract.functions.workInfo(bidder_address).call()[2]
return preallocation_address
def get_token_supply(self) -> int: # TODO: Needs better name
supply = self.contract.functions.tokenSupply().call()
return supply
def cancel_bid(self, sender_address: str) -> dict:
"""
Cancel bid and refund deposited ETH.
"""
contract_function = self.contract.functions.cancelBid()
receipt = self.blockchain.send_transaction(contract_function=contract_function,
sender_address=sender_address)
return receipt
def _make_preallocation_registry(self, bidder_address: str) -> IndividualAllocationRegistry:
preallocation_address = self.get_allocation_from_bidder(bidder_address=bidder_address)
compiler = SolidityCompiler()
# compiler.install_compiler()
compiled_contracts = compiler.compile()
all_contracts = compiled_contracts[PreallocationEscrowAgent.registry_contract_name]
contract = all_contracts[0] # There is only one version
allocation_registry = IndividualAllocationRegistry(beneficiary_address=bidder_address,
contract_address=preallocation_address,
contract_abi=contract.abi)
return allocation_registry
allocation_address = self.contract.functions.workInfo(bidder_address).call()[2]
return allocation_address
def get_bidder_from_allocation(self, allocation_address: str) -> str:
bidder = self.contract.functions.depositors(allocation_address).call()
return bidder
@property
def lot_value(self) -> int:
"""
Total number of tokens than can be bid for and awarded in allocation contracts;
or the number of NU tokens deposited before the bidding windows begins via tokenDeposit().
"""
supply = self.contract.functions.tokenSupply().call()
return supply
def cancel_bid(self, bidder_address: str) -> dict:
"""
Cancel bid and refund deposited ETH.
"""
contract_function = self.contract.functions.cancelBid()
receipt = self.blockchain.send_transaction(contract_function=contract_function,
sender_address=bidder_address)
return receipt
def _make_allocation_registry(self, bidder_address: str) -> IndividualAllocationRegistry:
preallocation_address = self.get_allocation_from_bidder(bidder_address=bidder_address)
allocation_registry = IndividualAllocationRegistry(beneficiary_address=bidder_address,
contract_address=preallocation_address)
return allocation_registry
def available_refund(self, bidder_address: str = None, allocation_address: str = None) -> int:
# TODO: move up one layer
# TODO: make decorator
if bidder_address and allocation_address:
raise ValueError("Pass bidder address or allocation address, got both.")
if bidder_address:
allocation_address = self.get_allocation_from_bidder(bidder_address=bidder_address)
else:
@ -1033,22 +1014,22 @@ class WorkLockAgent(EthereumContractAgent):
staking_agent = ContractAgency.get_agent(StakingEscrowAgent, registry=self.registry)
# TODO: Move to agent method
total_completed_work = staking_agent.contracts.functions.getCompletedWork(allocation_address)
# Calculate
total_completed_work = staking_agent.get_completed_work(allocation_address=allocation_address)
refunded_work = self.contract.functions.workInfo(bidder_address).call()[1]
completed_work = total_completed_work - refunded_work
refund_eth = self.contract.functions.workToETH(completed_work).call()
return refund_eth
def claim(self, sender_address: str) -> dict:
def claim(self, bidder_address: str) -> dict:
"""
Claim tokens - will be deposited and locked as stake in the StakingEscrow contract.
This function produces a new deployment or PreAllocationEscrow for the claimee.
"""
contract_function = self.contract.functions.claim()
receipt = self.blockchain.send_transaction(contract_function=contract_function,
sender_address=sender_address)
sender_address=bidder_address)
return receipt
@ -1062,27 +1043,54 @@ class WorkLockAgent(EthereumContractAgent):
sender_address=sender_address)
return receipt
def refund(self, sender_address: str, allocation_address: str) -> dict:
def refund(self, beneficiary_address: str, allocation_address: str = None) -> dict:
"""
Refund ETH for completed work.
Refund ETH for completed work to the beneficiary address (must be the owner of the allocation).
"""
if not allocation_address:
allocation_address = self.get_allocation_from_bidder(bidder_address=beneficiary_address)
if allocation_address == BlockchainInterface.NULL_ADDRESS:
raise ValueError(f"Unable to locate allocation for {beneficiary_address}")
contract_function = self.contract.functions.refund(allocation_address)
receipt = self.blockchain.send_transaction(contract_function=contract_function, sender_address=sender_address)
receipt = self.blockchain.send_transaction(contract_function=contract_function,
sender_address=beneficiary_address)
return receipt
def get_remaining_work(self, allocation_address: str) -> int:
def get_remaining_work(self, bidder_address: str = None, allocation_address: str = None) -> int:
"""
Get remaining work periods until full refund for the target address.
"""
if bidder_address and allocation_address:
raise ValueError("Pass bidder address or allocation address, got both.")
if bidder_address:
allocation_address = self.get_allocation_from_bidder(bidder_address=bidder_address)
result = self.contract.functions.getRemainingWork(allocation_address).call()
return result
def get_eth_supply(self):
supply = self.blockchain.w3.client.get_balance(self.contract_address)
return supply
def get_refund_rate(self):
f = self.contract.functions
refund_rate = self.get_deposit_rate() * f.SLOWING_REFUND().call() / f.boostingRefund().call()
return refund_rate
def get_deposit_rate(self):
deposit_rate = self.lot_value / self.get_eth_supply()
return deposit_rate
def get_unclaimed_tokens(self):
tokens = self.contract.functions.unclaimedTokens().call()
return tokens
def worklock_parameters(self) -> Tuple:
parameter_signatures = (
'tokenSupply',
'startBidDate',
'endBidDate',
'boostingRefund',
'lockingDuration'
'lockingDuration',
)
def _call_function_by_name(name: str):

View File

@ -94,7 +94,7 @@ class BaseContractDeployer:
@property
def contract_address(self) -> str:
if self._contract is CONTRACT_NOT_DEPLOYED:
raise self.ContractNotDeployed
raise self.ContractNotDeployed(self.contract_name)
address = self._contract.address # type: str
return address
@ -173,7 +173,7 @@ class BaseContractDeployer:
raise self.ContractDeploymentError(message)
return True
def deploy(self, gas_limit: int, progress, **overrides) -> dict:
def deploy(self, gas_limit: int = None, progress: int = None, **overrides) -> dict:
"""
Provides for the setup, deployment, and initialization of ethereum smart contracts.
Emits the configured blockchain network transactions for single contract instance publication.
@ -933,7 +933,6 @@ class PreallocationEscrowDeployer(BaseContractDeployer, UpgradeableContractMixin
contract_abi=self.contract.abi)
def deploy(self,
initial_deployment: bool = True,
gas_limit: int = None,
use_sidekick: bool = False,
progress=None) -> dict:
@ -1069,7 +1068,7 @@ class WorklockDeployer(BaseContractDeployer):
agency = WorkLockAgent
contract_name = agency.registry_contract_name
deployment_steps = ('contract_deployment', 'bond_escrow')
deployment_steps = ('contract_deployment', 'bond_escrow', 'fund_worklock')
_upgradeable = False
__proxy_deployer = NotImplemented
@ -1082,7 +1081,10 @@ class WorklockDeployer(BaseContractDeployer):
self.interface_agent = ContractAgency.get_agent(PreallocationEscrowAgent.StakingInterfaceAgent,
registry=self.registry)
def deploy(self, initial_deployment: bool = True, gas_limit: int = None, progress=None) -> Dict[str, dict]:
def deploy(self,
gas_limit: int = None,
progress: int = None,
fund_now: bool = True) -> Dict[str, dict]:
self.check_deployment_readiness()
interface_router = self.blockchain.get_proxy_contract(registry=self.registry,
@ -1099,17 +1101,41 @@ class WorklockDeployer(BaseContractDeployer):
self.contract_name,
*constructor_args,
gas_limit=gas_limit)
self._contract = worklock_contract
if progress:
progress.update(1)
bonding_function = self.staking_agent.contract.functions.setWorkLock(worklock_contract.address)
bonding_receipt = self.blockchain.send_transaction(sender_address=self.deployer_address,
contract_function=bonding_function)
if progress:
progress.update(1)
funding_receipt = self.fund(sender_address=self.deployer_address)
if progress:
progress.update(1)
# Gather the transaction hashes
self.deployment_transactions = {'contract_deployment': deploy_txhash, 'bond_escrow': bonding_receipt}
self._contract = worklock_contract
self.deployment_transactions = {'contract_deployment': deploy_txhash,
'bond_escrow': bonding_receipt,
'fund_worklock': funding_receipt}
return self.deployment_transactions
def fund(self, sender_address: str) -> dict:
"""
Convenience method for funding the contract and establishing the
total worklock lot value to be auctioned.
"""
supply = self.economics.worklock_supply.to_nunits()
token_agent = ContractAgency.get_agent(NucypherTokenAgent, registry=self.registry)
approve_function = token_agent.contract.functions.approve(self.contract_address, supply)
approve_receipt = self.blockchain.send_transaction(contract_function=approve_function,
sender_address=sender_address)
funding_function = self.contract.functions.tokenDeposit(supply)
funding_receipt = self.blockchain.send_transaction(contract_function=funding_function,
sender_address=sender_address)
return funding_receipt

View File

@ -729,13 +729,6 @@ def echo_solidity_version(ctx, param, value):
def paint_worklock_status(emitter, registry: BaseContractRegistry):
"""
# TODO: move some of these to agent?
* depositRate = tokenSupply / ethSupply
* claimedTokens = depositedETH * depositRate
* refundRate = depositRate * SLOWING_REFUND / boostingRefund
* refundETH = completedWork / refundRate
"""
from maya import MayaDT
WORKLOCK_AGENT = ContractAgency.get_agent(WorkLockAgent, registry=registry)
blockchain = WORKLOCK_AGENT.blockchain
@ -763,16 +756,28 @@ Time Remaining .... {remaining}
Economics
======================================================
Boosting Refund .... {WORKLOCK_AGENT.contract.functions.boostingRefund().call()}
Boosting Refund .... {WORKLOCK_AGENT.contract.functions.boostingRefund().call()}
Slowing Refund .... {WORKLOCK_AGENT.contract.functions.slowingRefund().call()}
Refund Rate ....... {WORKLOCK_AGENT.get_refund_rate()}
Deposit Rate ...... {WORKLOCK_AGENT.get_deposit_rate()}
Total Bids ......... {blockchain.client.get_balance(WORKLOCK_AGENT.contract_address)}
Unclaimed Tokens ... {WORKLOCK_AGENT.contract.functions.unclaimedTokens().call()}
Claimed Tokens ..... {WORKLOCK_AGENT.get_claimed_tokens()}
Unclaimed Tokens ... {WORKLOCK_AGENT.get_unclaimed_tokens()}
"""
emitter.message(payload)
return
def paint_worklock_participant_status(emitter):
message = f"""
Allocations
=====================================================
"""
emitter.message(message)
return
def paint_worklock_participant_notice(emitter, bidder_address, registry):
worklock_agent = ContractAgency.get_agent(WorkLockAgent, registry=registry)

View File

@ -24,7 +24,6 @@ from nucypher.blockchain.eth.interfaces import BlockchainInterfaceFactory
from nucypher.blockchain.eth.registry import InMemoryContractRegistry, LocalContractRegistry
from nucypher.characters.banners import WORKLOCK_BANNER
from nucypher.cli.actions import select_client_account
from nucypher.cli.config import nucypher_click_config
from nucypher.cli.painting import paint_receipt_summary, paint_worklock_status, paint_worklock_participant_notice
from nucypher.cli.types import EIP55_CHECKSUM_ADDRESS, WEI, EXISTING_READABLE_FILE

View File

@ -14,6 +14,8 @@ GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with nucypher. If not, see <https://www.gnu.org/licenses/>.
"""
import requests
import socket

View File

@ -3,12 +3,7 @@ import rlp
from eth_tester.exceptions import TransactionFailed
from eth_utils import to_canonical_address, keccak, to_checksum_address
from nucypher.blockchain.eth.agents import WorkLockAgent, ContractAgency, NucypherTokenAgent
from nucypher.blockchain.eth.token import NU
from nucypher.crypto.powers import TransactingPower
from nucypher.utilities.sandbox.constants import INSECURE_DEVELOPMENT_PASSWORD
DEPOSIT_RATE = 100
from nucypher.blockchain.eth.agents import WorkLockAgent, ContractAgency
def next_address(testerchain, worklock):
@ -25,101 +20,78 @@ def test_create_worklock_agent(testerchain, test_registry, agency, token_economi
assert agent == same_agent
def test_funding_worklock_contract(testerchain, agency, test_registry, token_economics):
transacting_power = TransactingPower(account=testerchain.etherbase_account, password=INSECURE_DEVELOPMENT_PASSWORD)
transacting_power.activate()
worklock_agent = ContractAgency.get_agent(WorkLockAgent, registry=test_registry)
# WorkLock contract is unfunded.
token_agent = ContractAgency.get_agent(NucypherTokenAgent, registry=test_registry)
assert token_agent.get_balance(worklock_agent.contract_address) == 0
# Funding account has enough tokens to fund the contract.
worklock_supply = NU.from_nunits(2 * token_economics.maximum_allowed_locked - 1)
assert token_agent.get_balance(testerchain.etherbase_account) > token_economics.maximum_allowed_locked
# Fund.
receipt = worklock_agent.fund(sender_address=testerchain.etherbase_account,
supply=worklock_supply)
assert receipt['status'] == 1
def test_bidding(testerchain, agency, token_economics, test_registry):
maximum_deposit_eth = token_economics.maximum_allowed_locked // DEPOSIT_RATE
minimum_deposit_eth = token_economics.minimum_allowed_locked // DEPOSIT_RATE
big_bid = token_economics.maximum_allowed_locked // 100
small_bid = token_economics.minimum_allowed_locked // 100
agent = ContractAgency.get_agent(WorkLockAgent, registry=test_registry)
# Round 1
for multiplier, bidder in enumerate(testerchain.unassigned_accounts[:3], start=1):
bid = minimum_deposit_eth * multiplier
bid = big_bid * multiplier
receipt = agent.bid(sender_address=bidder, value=bid)
assert receipt['status'] == 1
# Round 2
for multiplier, bidder in enumerate(testerchain.unassigned_accounts[:3], start=1):
bid = (minimum_deposit_eth * 2) * multiplier
bid = (small_bid * 2) * multiplier
receipt = agent.bid(sender_address=bidder, value=bid)
assert receipt['status'] == 1
big_bidder = testerchain.unassigned_accounts[-1]
bid_wei = maximum_deposit_eth - 1
receipt = agent.bid(sender_address=big_bidder, value=bid_wei)
assert receipt['status'] == 1
def test_get_bid(testerchain, agency, token_economics, test_registry):
bidder = testerchain.unassigned_accounts[-1]
big_bid = token_economics.maximum_allowed_locked // 10
big_bidder = testerchain.unassigned_accounts[-1]
agent = ContractAgency.get_agent(WorkLockAgent, registry=test_registry)
bid = agent.get_bid(bidder)
assert bid == 39999999999999999999999
receipt = agent.bid(sender_address=big_bidder, value=big_bid)
assert receipt['status'] == 1
bid = agent.get_bid(big_bidder)
assert bid == big_bid
def test_cancel_bid(testerchain, agency, token_economics, test_registry):
bidder = testerchain.unassigned_accounts[0]
bidder = testerchain.unassigned_accounts[1]
agent = ContractAgency.get_agent(WorkLockAgent, registry=test_registry)
receipt = agent.cancel_bid(bidder)
assert receipt['status'] == 1
# Can't cancel twice in a row
# Can't cancel a bid twice in a row
with pytest.raises((TransactionFailed, ValueError)):
_receipt = agent.cancel_bid(bidder)
def test_get_remaining_work_before_bidding_ends(testerchain, agency, token_economics, test_registry):
agent = ContractAgency.get_agent(WorkLockAgent, registry=test_registry)
preallocation_address = next_address(testerchain, agent.contract)
remaining = agent.get_remaining_work(allocation_address=preallocation_address)
bidder = testerchain.unassigned_accounts[0]
remaining = agent.get_remaining_work(bidder_address=bidder)
assert remaining == 0
def test_early_claim(testerchain, agency, token_economics, test_registry):
agent = ContractAgency.get_agent(WorkLockAgent, registry=test_registry)
bidder = testerchain.unassigned_accounts[-1]
bidder = testerchain.unassigned_accounts[0]
with pytest.raises(TransactionFailed):
receipt = agent.claim(sender_address=bidder)
receipt = agent.claim(bidder_address=bidder)
assert receipt
def test_refund_before_bidding_ends(testerchain, agency, token_economics, test_registry):
agent = ContractAgency.get_agent(WorkLockAgent, registry=test_registry)
bidder = testerchain.unassigned_accounts[-1]
allocation_address = next_address(testerchain, agent.contract)
with pytest.raises(TransactionFailed):
_receipt = agent.refund(sender_address=bidder, allocation_address=allocation_address)
def test_successful_claim(testerchain, agency, token_economics, test_registry):
# Wait exactly 1 hour + 1 second
testerchain.time_travel(seconds=(60*60)+1)
# Wait until the bidding window closes...
testerchain.time_travel(seconds=token_economics.bidding_duration+1)
agent = ContractAgency.get_agent(WorkLockAgent, registry=test_registry)
bidder = testerchain.unassigned_accounts[-1]
receipt = agent.claim(sender_address=bidder)
bidder = testerchain.unassigned_accounts[0]
receipt = agent.claim(bidder_address=bidder)
assert receipt
# Cant claim more than once
with pytest.raises(TransactionFailed):
_receipt = agent.claim(sender_address=bidder)
_receipt = agent.claim(bidder_address=bidder)
def test_lookup_bidders_and_allocations(testerchain, agency, token_economics, test_registry):
bidder = testerchain.unassigned_accounts[0]
agent = ContractAgency.get_agent(WorkLockAgent, registry=test_registry)
allocation_address = agent.get_allocation_from_bidder(bidder)
recovered_bidder = agent.get_bidder_from_allocation(allocation_address)
assert recovered_bidder == bidder

View File

@ -19,11 +19,12 @@ along with nucypher. If not, see <https://www.gnu.org/licenses/>.
import pytest
from eth_utils import keccak
from nucypher.blockchain.eth.agents import WorkLockAgent, ContractAgency
from nucypher.blockchain.eth.agents import WorkLockAgent, ContractAgency, NucypherTokenAgent
from nucypher.blockchain.eth.constants import WORKLOCK_CONTRACT_NAME
from nucypher.blockchain.eth.deployers import WorklockDeployer, StakingInterfaceDeployer, AdjudicatorDeployer
from nucypher.crypto.powers import TransactingPower
from nucypher.utilities.sandbox.constants import STAKING_ESCROW_DEPLOYMENT_SECRET, INSECURE_DEPLOYMENT_SECRET_HASH, \
POLICY_MANAGER_DEPLOYMENT_SECRET
POLICY_MANAGER_DEPLOYMENT_SECRET, INSECURE_DEVELOPMENT_PASSWORD
@pytest.fixture(scope="module")
@ -54,7 +55,7 @@ def test_worklock_deployment(worklock_deployer, staking_escrow_deployer, deploym
# deployment steps must match expected number of steps
steps = worklock_deployer.deployment_steps
assert deployment_progress.num_steps == len(steps) == len(deployment_receipts) == 2
assert deployment_progress.num_steps == len(steps) == len(deployment_receipts) == 3
# Ensure every step is successful
for step_title in steps:

View File

@ -33,7 +33,7 @@ from umbral.keys import UmbralPrivateKey
from umbral.signing import Signer
from web3 import Web3
from nucypher.blockchain.economics import TestEconomics
from nucypher.blockchain.economics import StandardTokenEconomics
from nucypher.blockchain.eth.actors import Staker, StakeHolder
from nucypher.blockchain.eth.agents import NucypherTokenAgent
from nucypher.blockchain.eth.clients import NuCypherGethDevProcess
@ -44,7 +44,7 @@ from nucypher.blockchain.eth.deployers import (NucypherTokenDeployer,
AdjudicatorDeployer,
StakingInterfaceDeployer,
WorklockDeployer
)
)
from nucypher.blockchain.eth.interfaces import BlockchainInterfaceFactory
from nucypher.blockchain.eth.networks import NetworksInventory
from nucypher.blockchain.eth.registry import (
@ -385,9 +385,28 @@ def federated_ursulas(ursula_federated_test_config):
# Blockchain
#
@pytest.fixture(scope='session')
def token_economics():
economics = TestEconomics()
@pytest.fixture(scope='module')
def token_economics(testerchain):
# Get current blocktime
blockchain = BlockchainInterfaceFactory.get_interface()
now = blockchain.w3.eth.getBlock(block_identifier='latest').timestamp
# Calculate instant start time
one_hour_in_seconds = (60 * 60)
start_date = now
bidding_start_date = start_date
# Ends in one hour
bidding_end_date = start_date + one_hour_in_seconds
economics = StandardTokenEconomics(
worklock_boosting_refund_rate=200,
worklock_commitment_duration=60, # Periods
worklock_supply=NU.from_nunits(1_000_000),
bidding_start_date=bidding_start_date,
bidding_end_date=bidding_end_date
)
return economics