From 0a396410e660d94c63a665dd59b18b4ec6820998 Mon Sep 17 00:00:00 2001 From: "Kieran R. Prasch" Date: Thu, 30 Jan 2020 12:14:00 -0800 Subject: [PATCH] Respond to more RFCs in PR #1550 --- nucypher/blockchain/eth/actors.py | 12 ++++++++- nucypher/blockchain/eth/agents.py | 4 +-- nucypher/blockchain/eth/deployers.py | 40 ++++++++++++++++------------ nucypher/characters/lawful.py | 4 +-- 4 files changed, 38 insertions(+), 22 deletions(-) diff --git a/nucypher/blockchain/eth/actors.py b/nucypher/blockchain/eth/actors.py index 8f5b18b91..80d105eaf 100644 --- a/nucypher/blockchain/eth/actors.py +++ b/nucypher/blockchain/eth/actors.py @@ -793,6 +793,9 @@ class Staker(NucypherTokenActor): # Value if entire_balance and amount: raise ValueError("Specify an amount or entire balance, not both") + elif not entire_balance and not amount: + raise ValueError("Specify an amount or entire balance, got neither") + if entire_balance: amount = self.token_balance if not self.token_balance >= amount: @@ -1391,6 +1394,7 @@ class Bidder(NucypherTokenActor): super().__init__(checksum_address=checksum_address, *args, **kwargs) self.worklock_agent = ContractAgency.get_agent(WorkLockAgent, registry=self.registry) self.staking_agent = ContractAgency.get_agent(StakingEscrowAgent, registry=self.registry) + self.economics = EconomicsFactory.get_economics(registry=self.registry) def _ensure_bidding_is_open(self): highest_block = self.worklock_agent.blockchain.w3.eth.getBlock('latest') @@ -1417,6 +1421,12 @@ class Bidder(NucypherTokenActor): def place_bid(self, value: int) -> dict: # wei_bid = Web3.toWei(value, 'wei') # TODO: Consider default denomination on this layer self._ensure_bidding_is_open() + + # Ensure the bid is at least large enough for min. stake + minimum = self.economics.minimum_allowed_locked + if value < minimum: + raise ValueError(f"Bid amount must be at least {NU.from_nunits(minimum)}") + receipt = self.worklock_agent.bid(checksum_address=self.checksum_address, value=value) return receipt @@ -1463,7 +1473,7 @@ class Bidder(NucypherTokenActor): # @property - def current_bid(self, denomination: str = None) -> float: + def current_bid(self, denomination: str = None) -> int: bid = self.worklock_agent.get_bid(checksum_address=self.checksum_address) ether_bid = Web3.toWei(bid, denomination or 'wei') # TODO: Consider default denomination on this layer return ether_bid diff --git a/nucypher/blockchain/eth/agents.py b/nucypher/blockchain/eth/agents.py index 21aa8581c..8d4321f67 100644 --- a/nucypher/blockchain/eth/agents.py +++ b/nucypher/blockchain/eth/agents.py @@ -1035,8 +1035,8 @@ class WorkLockAgent(EthereumContractAgent): @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(). + Total number of tokens than can be bid for and awarded in or the number of NU + tokens deposited before the bidding windows begins via tokenDeposit(). """ supply = self.contract.functions.tokenSupply().call() return supply diff --git a/nucypher/blockchain/eth/deployers.py b/nucypher/blockchain/eth/deployers.py index ae18ddae1..373a76538 100644 --- a/nucypher/blockchain/eth/deployers.py +++ b/nucypher/blockchain/eth/deployers.py @@ -23,7 +23,7 @@ from constant_sorrow.constants import CONTRACT_NOT_DEPLOYED, NO_DEPLOYER_CONFIGU from web3 import Web3 from web3.contract import Contract -from nucypher.blockchain.economics import StandardTokenEconomics +from nucypher.blockchain.economics import StandardTokenEconomics, BaseEconomics from nucypher.blockchain.eth.agents import ( EthereumContractAgent, StakingEscrowAgent, @@ -68,7 +68,7 @@ class BaseContractDeployer: def __init__(self, registry: BaseContractRegistry, - economics: StandardTokenEconomics = None, + economics: BaseEconomics = None, deployer_address: str = None): # @@ -90,7 +90,7 @@ class BaseContractDeployer: self.__economics = economics or StandardTokenEconomics() @property - def economics(self) -> StandardTokenEconomics: + def economics(self) -> BaseEconomics: """Read-only access for economics instance.""" return self.__economics @@ -1075,7 +1075,7 @@ class WorklockDeployer(BaseContractDeployer): agency = WorkLockAgent contract_name = agency.registry_contract_name - deployment_steps = ('contract_deployment', 'bond_escrow', 'fund_worklock') + deployment_steps = ('contract_deployment', 'bond_escrow', 'approve_funding', 'fund_worklock') _upgradeable = False def __init__(self, *args, **kwargs): @@ -1099,7 +1099,7 @@ class WorklockDeployer(BaseContractDeployer): self._contract = worklock_contract return worklock_contract, receipt - def deploy(self, gas_limit: int = None, progress: int = None) -> Dict[str, dict]: + def deploy(self, gas_limit: int = None, progress=None) -> Dict[str, dict]: self.check_deployment_readiness() # Essential @@ -1115,17 +1115,16 @@ class WorklockDeployer(BaseContractDeployer): progress.update(1) # Funding - funding_receipt = self.fund(sender_address=self.deployer_address) - if progress: - progress.update(1) + approve_receipt, funding_receipt = self.fund(sender_address=self.deployer_address, progress=progress) # Gather the transaction hashes - self.deployment_transactions = dict(zip(self.deployment_steps, (deployment_receipt, - bonding_receipt, - funding_receipt))) - return self.deployment_transactions + self.deployment_receipts = dict(zip(self.deployment_steps, (deployment_receipt, + bonding_receipt, + approve_receipt, + funding_receipt))) + return self.deployment_receipts - def fund(self, sender_address: str) -> dict: + def fund(self, sender_address: str, progress=None) -> Tuple[dict, dict]: """ Convenience method for funding the contract and establishing the total worklock lot value to be auctioned. @@ -1137,10 +1136,17 @@ class WorklockDeployer(BaseContractDeployer): approve_receipt = self.blockchain.send_transaction(contract_function=approve_function, sender_address=sender_address) + if progress: + progress.update(1) + funding_function = self.contract.functions.tokenDeposit(supply) funding_receipt = self.blockchain.send_transaction(contract_function=funding_function, sender_address=sender_address) - return funding_receipt + + if progress: + progress.update(1) + + return approve_receipt, funding_receipt class SeederDeployer(BaseContractDeployer, OwnableContractMixin): @@ -1150,7 +1156,7 @@ class SeederDeployer(BaseContractDeployer, OwnableContractMixin): deployment_steps = ('contract_deployment', ) _upgradeable = False - MAX_SEEDS = 10 # TODO: Move to economics? + MAX_SEEDS = 10 # TODO: Move to economics? def deploy(self, gas_limit: int = None, progress: int = None, **overrides) -> dict: self.check_deployment_readiness() @@ -1163,5 +1169,5 @@ class SeederDeployer(BaseContractDeployer, OwnableContractMixin): self._contract = seeder_contract if progress: progress.update(1) - receipts = {self.deployment_steps[0]: receipt} - return receipts + self.deployment_receipts.update({self.deployment_steps[0]: receipt}) + return self.deployment_receipts diff --git a/nucypher/characters/lawful.py b/nucypher/characters/lawful.py index ca4785d62..8df1942fe 100644 --- a/nucypher/characters/lawful.py +++ b/nucypher/characters/lawful.py @@ -800,8 +800,8 @@ class Ursula(Teacher, Character, Worker): # Blockchain decentralized_identity_evidence: bytes = constants.NOT_SIGNED, - checksum_address: str = None, # TODO: Rename to Staker address - worker_address: str = None, + checksum_address: str = None, + worker_address: str = None, # TODO: deprecate, and rename to "checksum_address" work_tracker: WorkTracker = None, start_working_now: bool = True, client_password: str = None,