[KMS-ETH]- Updated policy manager contract

pull/195/head^2
szotov 2018-01-27 16:05:19 +03:00
parent 0e625a6550
commit 8beffcbaa7
6 changed files with 411 additions and 97 deletions

View File

@ -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;
}
}

View File

@ -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;

View File

@ -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);
}
}

View File

@ -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;
}

View File

@ -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()

View File

@ -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)