mirror of https://github.com/nucypher/nucypher.git
[KMS-ETH]- Updated policy manager contract
parent
0e625a6550
commit
8beffcbaa7
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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()
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue