From 8beffcbaa7a684772978ade058ae89f5c8f71fdb Mon Sep 17 00:00:00 2001 From: szotov Date: Sat, 27 Jan 2018 16:05:19 +0300 Subject: [PATCH] [KMS-ETH]- Updated policy manager contract --- nkms_eth/project/contracts/Escrow.sol | 123 +++++++++---- nkms_eth/project/contracts/Miner.sol | 2 + nkms_eth/project/contracts/PolicyManager.sol | 169 ++++++++++++----- nkms_eth/project/contracts/lib/LinkedList.sol | 13 +- scripts/estimate_gas_tester.py | 172 ++++++++++++++++++ tests/contracts/test_escrow.py | 29 +-- 6 files changed, 411 insertions(+), 97 deletions(-) create mode 100644 scripts/estimate_gas_tester.py diff --git a/nkms_eth/project/contracts/Escrow.sol b/nkms_eth/project/contracts/Escrow.sol index 257762093..10a998c0f 100644 --- a/nkms_eth/project/contracts/Escrow.sol +++ b/nkms_eth/project/contracts/Escrow.sol @@ -8,6 +8,7 @@ import "./lib/AdditionalMath.sol"; import "./lib/LinkedList.sol"; import "./Miner.sol"; import "./NuCypherKMSToken.sol"; +import "./PolicyManager.sol"; /** @@ -24,6 +25,11 @@ contract Escrow is Miner, Ownable { uint256 lockedValue; } + struct Downtime { + uint256 startPeriod; + uint256 endPeriod; + } + struct TokenInfo { uint256 value; uint256 decimals; @@ -31,23 +37,23 @@ contract Escrow is Miner, Ownable { bool release; uint256 maxReleasePeriods; uint256 releaseRate; + // periods that confirmed but not yet mined ConfirmedPeriodInfo[] confirmedPeriods; uint256 numberConfirmedPeriods; + // downtime + uint256 lastActivePeriod; + Downtime[] downtime; } - struct PeriodInfo { - uint256 totalLockedValue; - uint256 numberOwnersToBeRewarded; - } - - uint256 constant MAX_PERIODS = 100; + uint256 constant MAX_PERIODS = 10; uint256 constant MAX_OWNERS = 50000; mapping (address => TokenInfo) public tokenInfo; LinkedList.Data tokenOwners; - mapping (uint256 => PeriodInfo) public lockedPerPeriod; + mapping (uint256 => uint256) public lockedPerPeriod; uint256 public minReleasePeriods; + PolicyManager policyManager; /** * @notice The Escrow constructor sets address of token contract and coefficients for mining @@ -123,7 +129,7 @@ contract Escrow is Miner, Ownable { function getAllLockedTokens() public constant returns (uint256) { - return lockedPerPeriod[getCurrentPeriod()].totalLockedValue; + return lockedPerPeriod[getCurrentPeriod()]; } /** @@ -202,11 +208,12 @@ contract Escrow is Miner, Ownable { **/ function deposit(uint256 _value, uint256 _periods) public { require(_value != 0); + var info = tokenInfo[msg.sender]; if (!tokenOwners.valueExists(msg.sender)) { require(tokenOwners.sizeOf() < MAX_OWNERS); tokenOwners.push(msg.sender, true); + info.lastActivePeriod = getCurrentPeriod(); } - var info = tokenInfo[msg.sender]; info.value = info.value.add(_value); token.safeTransferFrom(msg.sender, address(this), _value); lock(_value, _periods); @@ -281,23 +288,24 @@ contract Escrow is Miner, Ownable { token.safeTransfer(msg.sender, value); } - /** - * @notice Terminate contract and refund to owners - * @dev The called token contracts could try to re-enter this contract. - Only supply token contracts you trust. - **/ - function destroy() onlyOwner public { - // Transfer tokens to owners - var current = tokenOwners.step(0x0, true); - while (current != 0x0) { - token.safeTransfer(current, tokenInfo[current].value); - current = tokenOwners.step(current, true); - } - token.safeTransfer(owner, token.balanceOf(address(this))); - - // Transfer Eth to owner and terminate contract - selfdestruct(owner); - } + // TODO change to upgrade +// /** +// * @notice Terminate contract and refund to owners +// * @dev The called token contracts could try to re-enter this contract. +// Only supply token contracts you trust. +// **/ +// function destroy() onlyOwner public { +// // Transfer tokens to owners +// var current = tokenOwners.step(0x0, true); +// while (current != 0x0) { +// token.safeTransfer(current, tokenInfo[current].value); +// current = tokenOwners.step(current, true); +// } +// token.safeTransfer(owner, token.balanceOf(address(this))); +// +// // Transfer Eth to owner and terminate contract +// selfdestruct(owner); +// } /** * @notice Confirm activity for future period @@ -312,16 +320,15 @@ contract Escrow is Miner, Ownable { if (numberConfirmedPeriods > 0 && info.confirmedPeriods[numberConfirmedPeriods - 1].period == nextPeriod) { var confirmedPeriod = info.confirmedPeriods[numberConfirmedPeriods - 1]; - lockedPerPeriod[nextPeriod].totalLockedValue = lockedPerPeriod[nextPeriod].totalLockedValue + lockedPerPeriod[nextPeriod] = lockedPerPeriod[nextPeriod] .add(_lockedValue.sub(confirmedPeriod.lockedValue)); confirmedPeriod.lockedValue = _lockedValue; return; } require(numberConfirmedPeriods < MAX_PERIODS); - lockedPerPeriod[nextPeriod].totalLockedValue = - lockedPerPeriod[nextPeriod].totalLockedValue.add(_lockedValue); - lockedPerPeriod[nextPeriod].numberOwnersToBeRewarded++; + lockedPerPeriod[nextPeriod] = lockedPerPeriod[nextPeriod] + .add(_lockedValue); if (numberConfirmedPeriods < info.confirmedPeriods.length) { info.confirmedPeriods[numberConfirmedPeriods].period = nextPeriod; info.confirmedPeriods[numberConfirmedPeriods].lockedValue = _lockedValue; @@ -329,6 +336,12 @@ contract Escrow is Miner, Ownable { info.confirmedPeriods.push(ConfirmedPeriodInfo(nextPeriod, _lockedValue)); } info.numberConfirmedPeriods++; + + var currentPeriod = nextPeriod - 1; + if (info.lastActivePeriod < currentPeriod) { + info.downtime.push(Downtime(info.lastActivePeriod + 1, currentPeriod)); + } + info.lastActivePeriod = nextPeriod; } /** @@ -381,13 +394,12 @@ contract Escrow is Miner, Ownable { msg.sender, previousPeriod, lockedValue, - lockedPerPeriod[period].totalLockedValue, + lockedPerPeriod[period], allLockedPeriods, decimals); - if (lockedPerPeriod[period].numberOwnersToBeRewarded > 1) { - lockedPerPeriod[period].numberOwnersToBeRewarded--; - } else { - delete lockedPerPeriod[period]; + // TODO remove + if (address(policyManager) != 0x0) { + policyManager.updateReward(msg.sender, previousPeriod); } } info.decimals = decimals; @@ -421,7 +433,7 @@ contract Escrow is Miner, Ownable { | |----->| **/ function findCumSum(address _start, uint256 _delta, uint256 _periods) - public constant returns (address stop, uint256 shift) + external constant returns (address stop, uint256 shift) { require(_periods > 0); var currentPeriod = getCurrentPeriod(); @@ -465,4 +477,43 @@ contract Escrow is Miner, Ownable { } } } + + /** + * @notice Set policy manager address + **/ + function setPolicyManager(PolicyManager _policyManager) onlyOwner { + require(_policyManager.escrow() == address(this)); + policyManager = _policyManager; + } + + /** + * @dev Get info about downtime periods + * @param _owner Tokens owner + * @param _index Index in array of downtime periods + **/ + function getDowntimePeriods(address _owner, uint256 _index) + public constant returns (uint256 startPeriod, uint256 endPeriod) + { + var period = tokenInfo[msg.sender].downtime[_index]; + startPeriod = period.startPeriod; + endPeriod = period.endPeriod; + } + + /** + * @dev Get size of downtime periods array + **/ + function getDowntimePeriodsLength(address _owner) + public constant returns (uint256) + { + return tokenInfo[msg.sender].downtime.length; + } + + /** + * @dev Get last active period + **/ + function getLastActivePeriod(address _owner) + public constant returns (uint256) + { + return tokenInfo[msg.sender].lastActivePeriod; + } } diff --git a/nkms_eth/project/contracts/Miner.sol b/nkms_eth/project/contracts/Miner.sol index dd7632423..a3a52d0ee 100644 --- a/nkms_eth/project/contracts/Miner.sol +++ b/nkms_eth/project/contracts/Miner.sol @@ -67,6 +67,7 @@ contract Miner { * @param _decimals The amount of locked tokens and blocks in decimals. * @return Amount of minted tokens. */ + // TODO decimals function mint( address _to, uint256 _period, @@ -78,6 +79,7 @@ contract Miner { internal returns (uint256 amount, uint256 decimals) { // TODO end of mining before calculation + // FIXME execution for first owner is more expensive if (_period > lastMintedPeriod) { lastTotalSupply = token.totalSupply(); lastMintedPeriod = _period; diff --git a/nkms_eth/project/contracts/PolicyManager.sol b/nkms_eth/project/contracts/PolicyManager.sol index 72168612a..41cb56909 100644 --- a/nkms_eth/project/contracts/PolicyManager.sol +++ b/nkms_eth/project/contracts/PolicyManager.sol @@ -3,6 +3,7 @@ pragma solidity ^0.4.0; import "./zeppelin/token/SafeERC20.sol"; import "./zeppelin/math/SafeMath.sol"; +import "./zeppelin/math/Math.sol"; import "./Escrow.sol"; import "./NuCypherKMSToken.sol"; @@ -14,21 +15,30 @@ contract PolicyManager { using SafeERC20 for NuCypherKMSToken; using SafeMath for uint256; - enum PolicyState { Pending, Active } +// enum PolicyState { Pending, Active } +// enum PolicyType { Periods } struct Policy { address client; address node; - uint256 fee; -// uint256 lockedFee; - PolicyState state; - uint256 numberOfPeriods; +// PolicyState state; + + // policy for activity periods + uint256 rate; + uint256 startPeriod; uint256 lastPeriod; + uint256 indexOfDowntimePeriods; } - NuCypherKMSToken token; - Escrow escrow; - mapping (bytes20 => Policy) policies; + struct NodeInfo { + mapping (uint256 => uint256) rewardByPeriod; + uint256 reward; + } + + NuCypherKMSToken public token; + Escrow public escrow; + mapping (bytes20 => Policy) public policies; + mapping (address => NodeInfo) public nodes; // mapping (address => byte20[]) nodePolicies; // mapping (address => byte20[]) clientPolicies; @@ -50,74 +60,149 @@ contract PolicyManager { * @notice Create policy by client * @dev Generate policy id before creation * @param _policyId Policy id - * @param _fee Amount of node reward + * @param _feeByPeriod Amount of node reward by period * @param _node Node that will handle policy * @param _numberOfPeriods Duration of the policy in periods **/ function createPolicy( bytes20 _policyId, - uint256 _fee, + uint256 _feeByPeriod, address _node, uint256 _numberOfPeriods ) public { require( - policies[_policyId].fee == 0 && - _fee != 0 && + policies[_policyId].rate == 0 && + _feeByPeriod != 0 && _numberOfPeriods != 0 && escrow.getLockedTokens(_node) != 0 ); - token.safeTransferFrom(msg.sender, address(this), _fee); + token.safeTransferFrom( + msg.sender, address(this), _feeByPeriod.mul(_numberOfPeriods)); var policy = policies[_policyId]; policy.client = msg.sender; policy.node = _node; - policy.fee = _fee; -// policy.lockedFee = _fee; - policy.state = PolicyState.Pending; - policy.numberOfPeriods = _numberOfPeriods; +// policy.state = PolicyState.Pending; + var currentPeriod = escrow.getCurrentPeriod(); + policy.startPeriod = currentPeriod.add(1); + policy.lastPeriod = currentPeriod.add(_numberOfPeriods); + policy.rate = _feeByPeriod; + + var node = nodes[_node]; + for (uint256 i = policy.startPeriod; i <= policy.lastPeriod; i++) { + node.rewardByPeriod[i] = node.rewardByPeriod[i].add(_feeByPeriod); + } + policy.indexOfDowntimePeriods = escrow.getDowntimePeriodsLength(_node); + } + +// /** +// * @notice Confirm policy by node +// * @param _policyId Policy id +// **/ +// function confirmPolicy(bytes20 _policyId) public { +// var policy = policies[_policyId]; +// require(policy.state == PolicyState.Pending && +// policy.node == msg.sender); +// policy.state = PolicyState.Active; +// } + + /** + * @notice Update node reward + * @param _node Node address + * @param _period Processed period + **/ + function updateReward(address _node, uint256 _period) external { + require(msg.sender == address(escrow)); + var node = nodes[_node]; + node.reward = node.reward.add(node.rewardByPeriod[_period]); + delete node.rewardByPeriod[_period]; } /** - * @notice Revoke policy by client (all states) or node (only Pending state) + * @notice Withdraw fee by node + **/ + function withdraw() public { + var node = nodes[msg.sender]; + var reward = node.reward; + require(reward != 0); + node.reward = 0; + token.safeTransfer(msg.sender, reward); + } + + /** + * @notice Revoke policy by client * @param _policyId Policy id **/ - function revokePolicy(bytes20 _policyId) public { + function revokePolicy(bytes20 _policyId) public { var policy = policies[_policyId]; - require(policy.state == PolicyState.Pending && - policy.client == msg.sender); - var fee = policy.fee; - var client = policy.client; + require(policy.client == msg.sender); + var refund = calculateRefund(policy); + var node = nodes[policy.node]; + for (var i = policy.startPeriod; i <= policy.lastPeriod; i++) { + node.rewardByPeriod[i] = node.rewardByPeriod[i].sub(policy.rate); + refund = refund.add(policy.rate); + } delete policies[_policyId]; - token.safeTransfer(client, fee); + token.safeTransfer(msg.sender, refund); } /** - * @notice Confirm policy by node + * @notice Refund part of fee by client * @param _policyId Policy id **/ - function confirmPolicy(bytes20 _policyId) public { + function refund(bytes20 _policyId) public { var policy = policies[_policyId]; - require(policy.state == PolicyState.Pending && - policy.node == msg.sender); - policy.state = PolicyState.Active; - policy.lastPeriod = escrow.getCurrentPeriod() - .add(policy.numberOfPeriods); +// require(policy.state == PolicyState.Active && +// msg.sender == policy.client); + require(msg.sender == policy.client); + + var refund = calculateRefund(policy); + if (policy.startPeriod > policy.lastPeriod) { + delete policies[_policyId]; + } + if (refund > 0) { + token.safeTransfer(policy.client, refund); + } } /** - * @notice Finish policy and withdraw fee by node - * @param _policyId Policy id + * @notice Calculate amount of refund + * @param policy Policy **/ - function finishPolicy(bytes20 _policyId) public { - var policy = policies[_policyId]; - require(policy.state == PolicyState.Active && - policy.node == msg.sender && - escrow.getCurrentPeriod() > policy.lastPeriod); - var fee = policy.fee; - var node = policy.client; - delete policies[_policyId]; - token.safeTransfer(node, fee); + function calculateRefund(Policy policy) internal returns (uint256) { + var currentPeriod = escrow.getCurrentPeriod(); + var maxPeriod = Math.min256(currentPeriod, policy.lastPeriod); + var minPeriod = policy.startPeriod; + var max = maxPeriod; + var activePeriods = maxPeriod.add(1).sub(minPeriod); + var length = escrow.getDowntimePeriodsLength(policy.node); + // TODO complete + for (var i = policy.indexOfDowntimePeriods; i < length; i++) { + var (startPeriod, endPeriod) = escrow.getDowntimePeriods(policy.node, i); + if (startPeriod > maxPeriod) { + break; + } else if (endPeriod < minPeriod) { + continue; + } + max = Math.min256(maxPeriod, endPeriod); + var min = Math.max256(minPeriod, startPeriod); + // TODO safe math + activePeriods -= max - min + 1; + if (maxPeriod <= endPeriod) { + break; + } + } + policy.indexOfDowntimePeriods = i; + var lastActivePeriod = escrow.getLastActivePeriod(policy.node); + if (i == length && lastActivePeriod < maxPeriod) { + min = Math.max256(minPeriod, lastActivePeriod); + // TODO safe math + activePeriods -= max - min + 1; + } + policy.startPeriod = max.add(1); + + return policy.rate.mul(activePeriods); } } diff --git a/nkms_eth/project/contracts/lib/LinkedList.sol b/nkms_eth/project/contracts/lib/LinkedList.sol index 4f49ea31e..d5e515f17 100644 --- a/nkms_eth/project/contracts/lib/LinkedList.sol +++ b/nkms_eth/project/contracts/lib/LinkedList.sol @@ -14,6 +14,7 @@ library LinkedList { struct Data { mapping (address => mapping (bool => address)) data; + uint256 count; } /// @notice Return existential state of a list. @@ -29,12 +30,7 @@ library LinkedList { function sizeOf(Data storage self) internal constant returns (uint result) { - var current = step(self, HEAD, NEXT); - while (current != HEAD) { - current = step(self, current, NEXT); - result++; - } - return; + return self.count; } /** @@ -42,8 +38,7 @@ library LinkedList { * @param value Value to search for **/ function valueExists(Data storage self, address value) - internal - constant returns (bool) + internal constant returns (bool) { if (self.data[value][PREV] == HEAD && self.data[value][NEXT] == HEAD) { if (self.data[HEAD][NEXT] == value) { @@ -95,6 +90,7 @@ library LinkedList { address to = self.data[from][direction]; createLinks(self, from, value, direction); createLinks(self, value, to, direction); + self.count++; } /// @notice Remove value from the list. @@ -108,6 +104,7 @@ library LinkedList { createLinks(self, self.data[value][PREV], self.data[value][NEXT], NEXT); delete self.data[value][PREV]; delete self.data[value][NEXT]; + self.count--; return value; } diff --git a/scripts/estimate_gas_tester.py b/scripts/estimate_gas_tester.py new file mode 100644 index 000000000..957d89122 --- /dev/null +++ b/scripts/estimate_gas_tester.py @@ -0,0 +1,172 @@ +"""Deploy contracts in tester. + +A simple Python script to deploy contracts and then estimate gas for different methods. +""" +from nkms_eth.blockchain import project + + +def wait_time(chain, wait_hours): + web3 = chain.web3 + step = 50 + end_timestamp = web3.eth.getBlock(web3.eth.blockNumber).timestamp + wait_hours * 60 * 60 + while web3.eth.getBlock(web3.eth.blockNumber).timestamp < end_timestamp: + chain.wait.for_block(web3.eth.blockNumber + step) + + +def main(): + + proj = project() + + chain_name = "tester" + print("Make sure {} chain is running, you can connect to it, or you'll get timeout".format(chain_name)) + + with proj.get_chain(chain_name) as chain: + web3 = chain.web3 + print("Web3 providers are", web3.providers) + creator = web3.eth.accounts[0] + ursula1 = web3.eth.accounts[1] + ursula2 = web3.eth.accounts[2] + ursula3 = web3.eth.accounts[3] + + # Create an ERC20 token + token, _ = chain.provider.get_or_deploy_contract( + 'NuCypherKMSToken', deploy_args=[10 ** 9, 2 * 10 ** 9], + deploy_transaction={'from': creator}) + + # Creator deploys the escrow + escrow, _ = chain.provider.get_or_deploy_contract( + 'Escrow', deploy_args=[token.address, 1, 4 * 2 * 10 ** 7, 4, 4, 1], + deploy_transaction={'from': creator}) + + # Creator deploys the policy manager + policy_manager, _ = chain.provider.get_or_deploy_contract( + 'PolicyManager', deploy_args=[token.address, escrow.address], + deploy_transaction={'from': creator}) + tx = escrow.transact({'from': creator}).setPolicyManager(policy_manager.address) + chain.wait.for_receipt(tx) + + print("Estimate gas:") + + # Give rights for mining + print("Giving rights for mining = " + + str(token.estimateGas({'from': creator}).addMiner(escrow.address))) + tx = token.transact({'from': creator}).addMiner(escrow.address) + chain.wait.for_receipt(tx) + + # Give Ursula and Alice some coins + print("Transfer tokens = " + + str(token.estimateGas({'from': creator}).transfer(ursula1, 10000))) + tx = token.transact({'from': creator}).transfer(ursula1, 10000) + chain.wait.for_receipt(tx) + tx = token.transact({'from': creator}).transfer(ursula2, 10000) + chain.wait.for_receipt(tx) + tx = token.transact({'from': creator}).transfer(ursula3, 10000) + chain.wait.for_receipt(tx) + + # Ursula and Alice give Escrow rights to transfer + print("Approving transfer = " + + str(token.estimateGas({'from': ursula1}).approve(escrow.address, 1000))) + tx = token.transact({'from': ursula1}).approve(escrow.address, 1000) + chain.wait.for_receipt(tx) + tx = token.transact({'from': ursula2}).approve(escrow.address, 500) + chain.wait.for_receipt(tx) + tx = token.transact({'from': ursula3}).approve(escrow.address, 500) + chain.wait.for_receipt(tx) + + # Ursula and Alice transfer some tokens to the escrow and lock them + print("First deposit tokens = " + + str(escrow.estimateGas({'from': ursula1}).deposit(1000, 1))) + tx = escrow.transact({'from': ursula1}).deposit(1000, 1) + chain.wait.for_receipt(tx) + print("Second deposit tokens = " + + str(escrow.estimateGas({'from': ursula2}).deposit(500, 1))) + tx = escrow.transact({'from': ursula2}).deposit(500, 1) + chain.wait.for_receipt(tx) + print("Third deposit tokens = " + + str(escrow.estimateGas({'from': ursula3}).deposit(500, 1))) + tx = escrow.transact({'from': ursula3}).deposit(500, 1) + chain.wait.for_receipt(tx) + + # Wait 1 period and confirm activity + wait_time(chain, 1) + print("First confirm activity = " + + str(escrow.estimateGas({'from': ursula1}).confirmActivity())) + tx = escrow.transact({'from': ursula1}).confirmActivity() + chain.wait.for_receipt(tx) + print("Second confirm activity = " + + str(escrow.estimateGas({'from': ursula2}).confirmActivity())) + tx = escrow.transact({'from': ursula2}).confirmActivity() + chain.wait.for_receipt(tx) + print("Third confirm activity = " + + str(escrow.estimateGas({'from': ursula3}).confirmActivity())) + tx = escrow.transact({'from': ursula3}).confirmActivity() + chain.wait.for_receipt(tx) + + # Wait 1 period and mint tokens + wait_time(chain, 1) + print("First mining = " + + str(escrow.estimateGas({'from': ursula1}).mint())) + tx = escrow.transact({'from': ursula1}).mint() + chain.wait.for_receipt(tx) + print("Second mining = " + + str(escrow.estimateGas({'from': ursula2}).mint())) + tx = escrow.transact({'from': ursula2}).mint() + chain.wait.for_receipt(tx) + print("Third/last mining = " + + str(escrow.estimateGas({'from': ursula3}).mint())) + tx = escrow.transact({'from': ursula3}).mint() + chain.wait.for_receipt(tx) + + # Wait 1 period and get locked tokens + print("Getting locked tokens = " + + str(escrow.estimateGas().getLockedTokens(ursula1))) + print("Calculating locked tokens = " + + str(escrow.estimateGas().calculateLockedTokens(ursula1, 1))) + + # Switch to unlock and lock tokens again + print("First switch = " + + str(escrow.estimateGas({'from': ursula1}).switchLock())) + tx = escrow.transact({'from': ursula1}).switchLock() + chain.wait.for_receipt(tx) + print("Second switch = " + + str(escrow.estimateGas({'from': ursula2}).switchLock())) + tx = escrow.transact({'from': ursula2}).switchLock() + chain.wait.for_receipt(tx) + print("Third switch = " + + str(escrow.estimateGas({'from': ursula3}).switchLock())) + tx = escrow.transact({'from': ursula3}).switchLock() + chain.wait.for_receipt(tx) + + print("First locking tokens = " + + str(escrow.estimateGas({'from': ursula1}).lock(1, 0))) + tx = escrow.transact({'from': ursula1}).lock(1, 0) + chain.wait.for_receipt(tx) + print("Second locking tokens = " + + str(escrow.estimateGas({'from': ursula2}).lock(1, 0))) + tx = escrow.transact({'from': ursula2}).lock(1, 0) + chain.wait.for_receipt(tx) + print("Third locking tokens = " + + str(escrow.estimateGas({'from': ursula3}).lock(1, 0))) + tx = escrow.transact({'from': ursula3}).lock(1, 0) + chain.wait.for_receipt(tx) + + # Wait 1 period and withdraw tokens + wait_time(chain, 1) + print("First withdraw = " + + str(escrow.estimateGas({'from': ursula1}).withdraw(1))) + tx = escrow.transact({'from': ursula1}).withdraw(1) + chain.wait.for_receipt(tx) + print("Second withdraw = " + + str(escrow.estimateGas({'from': ursula2}).withdraw(1))) + tx = escrow.transact({'from': ursula2}).withdraw(1) + chain.wait.for_receipt(tx) + print("Third withdraw = " + + str(escrow.estimateGas({'from': ursula3}).withdraw(1))) + tx = escrow.transact({'from': ursula3}).withdraw(1) + chain.wait.for_receipt(tx) + + print("All done!") + + +if __name__ == "__main__": + main() diff --git a/tests/contracts/test_escrow.py b/tests/contracts/test_escrow.py index 8fbed2963..9318d044d 100644 --- a/tests/contracts/test_escrow.py +++ b/tests/contracts/test_escrow.py @@ -203,17 +203,17 @@ def test_escrow(web3, chain, token, escrow): assert 100 == escrow.call().calculateLockedTokens(alice, 2) assert 0 == escrow.call().calculateLockedTokens(alice, 3) - # Ursula can't destroy contract - with pytest.raises(TransactionFailed): - tx = escrow.transact({'from': ursula}).destroy() - chain.wait.for_receipt(tx) - - # Destroy contract from creator and refund all to Ursula and Alice - tx = escrow.transact({'from': creator}).destroy() - chain.wait.for_receipt(tx) - assert 0 == token.call().balanceOf(escrow.address) - assert 10000 == token.call().balanceOf(ursula) - assert 10000 == token.call().balanceOf(alice) + # # Ursula can't destroy contract + # with pytest.raises(TransactionFailed): + # tx = escrow.transact({'from': ursula}).destroy() + # chain.wait.for_receipt(tx) + # + # # Destroy contract from creator and refund all to Ursula and Alice + # tx = escrow.transact({'from': creator}).destroy() + # chain.wait.for_receipt(tx) + # assert 0 == token.call().balanceOf(escrow.address) + # assert 10000 == token.call().balanceOf(ursula) + # assert 10000 == token.call().balanceOf(alice) def test_locked_distribution(web3, chain, token, escrow): @@ -283,6 +283,13 @@ def test_mining(web3, chain, token, escrow): ursula = web3.eth.accounts[1] alice = web3.eth.accounts[2] + # TODO test setPolicyManager + policy_manager, _ = chain.provider.get_or_deploy_contract( + 'PolicyManager', deploy_args=[token.address, escrow.address], + deploy_transaction={'from': creator}) + tx = escrow.transact({'from': creator}).setPolicyManager(policy_manager.address) + chain.wait.for_receipt(tx) + # Give Ursula and Alice some coins tx = token.transact({'from': creator}).transfer(ursula, 10000) chain.wait.for_receipt(tx)