[KMS-ETH]- Changed locking logic, Miner contract prepared for new parameter

pull/195/head^2
szotov 2018-01-12 19:52:17 +03:00
parent 14c0cb99a0
commit 1e8ee747bf
15 changed files with 338 additions and 278 deletions

View File

@ -4,7 +4,7 @@ from nkms_eth import blockchain
from nkms_eth import token
ESCROW_NAME = 'Escrow'
MINING_COEFF = [10 ** 9, 50, 1]
MINING_COEFF = [10 ** 9, 50, 1, 1, 1]
NULL_ADDR = '0x' + '0' * 40

View File

@ -4,6 +4,7 @@ pragma solidity ^0.4.8;
import "./zeppelin/token/SafeERC20.sol";
import "./zeppelin/ownership/Ownable.sol";
import "./zeppelin/math/Math.sol";
import "./lib/AdditionalMath.sol";
import "./lib/LinkedList.sol";
import "./Miner.sol";
import "./NuCypherKMSToken.sol";
@ -16,6 +17,7 @@ Each client that lock his tokens will receive some compensation
contract Escrow is Miner, Ownable {
using LinkedList for LinkedList.Data;
using SafeERC20 for NuCypherKMSToken;
using AdditionalMath for uint256;
struct ConfirmedPeriodInfo {
uint256 period;
@ -26,8 +28,8 @@ contract Escrow is Miner, Ownable {
uint256 value;
uint256 decimals;
uint256 lockedValue;
// last period before the tokens begin to unlock
uint256 releasePeriod;
bool release;
uint256 maxReleasePeriods;
uint256 releaseRate;
ConfirmedPeriodInfo[] confirmedPeriods;
uint256 numberConfirmedPeriods;
@ -55,14 +57,18 @@ contract Escrow is Miner, Ownable {
* @param _miningCoefficient Mining coefficient
* @param _blocksPerPeriod Size of one period in blocks
* @param _minReleasePeriods Min amount of periods during which tokens will be released
* @param _lockedBlocksCoefficient Locked blocks coefficient
* @param _awardedPeriods Max periods that will be additionally awarded
**/
function Escrow(
NuCypherKMSToken _token,
uint256 _miningCoefficient,
uint256 _blocksPerPeriod,
uint256 _minReleasePeriods
uint256 _minReleasePeriods,
uint256 _lockedBlocksCoefficient,
uint256 _awardedPeriods
)
Miner(_token, _miningCoefficient)
Miner(_token, _miningCoefficient, _lockedBlocksCoefficient, _awardedPeriods * _blocksPerPeriod)
{
require(_blocksPerPeriod != 0 && _minReleasePeriods != 0);
token = _token;
@ -102,7 +108,7 @@ contract Escrow is Miner, Ownable {
}
}
// checks if owner can mine more tokens (before or after release period)
if (calculateLockedTokens(_owner, currentPeriod, lockedValue, 1) == 0) {
if (calculateLockedTokens(_owner, false, lockedValue, 1) == 0) {
return 0;
} else {
return lockedValue;
@ -122,25 +128,22 @@ contract Escrow is Miner, Ownable {
/**
* @notice Calculate locked tokens value for owner in next period
* @param _owner Tokens owner
* @param _period Current or future period number
* @param _forceRelease Force unlocking period calculation
* @param _lockedTokens Locked tokens in specified period
* @param _periods Number of periods after _period that need to calculate
* @param _periods Number of periods that need to calculate
* @return Calculated locked tokens in next period
**/
function calculateLockedTokens(
address _owner,
uint256 _period,
bool _forceRelease,
uint256 _lockedTokens,
uint256 _periods
)
internal constant returns (uint256)
{
var nextPeriod = _period.add(_periods);
var info = tokenInfo[_owner];
var releasePeriod = info.releasePeriod;
if (releasePeriod != 0 && releasePeriod < nextPeriod) {
var period = Math.max256(_period, releasePeriod);
var unlockedTokens = nextPeriod.sub(period).mul(info.releaseRate);
if ((_forceRelease || info.release) && _periods != 0) {
var unlockedTokens = _periods.mul(info.releaseRate);
return unlockedTokens <= _lockedTokens ? _lockedTokens.sub(unlockedTokens) : 0;
} else {
return _lockedTokens;
@ -172,15 +175,31 @@ contract Escrow is Miner, Ownable {
}
var periods = nextPeriod.sub(period);
return calculateLockedTokens(_owner, period, lockedTokens, periods);
return calculateLockedTokens(_owner, false, lockedTokens, periods);
}
/**
* @notice Calculate locked periods for owner from start period
* @param _owner Tokens owner
* @param _lockedTokens Locked tokens in start period
* @return Calculated locked periods
**/
function calculateLockedPeriods(
address _owner,
uint256 _lockedTokens
)
internal constant returns (uint256)
{
var info = tokenInfo[_owner];
return _lockedTokens.div(info.releaseRate);
}
/**
* @notice Deposit tokens
* @param _value Amount of token to deposit
* @param _periods Amount of periods during which tokens will be locked
* @param _periods Amount of periods during which tokens will be unlocked
**/
function deposit(uint256 _value, uint256 _periods) {
function deposit(uint256 _value, uint256 _periods) public {
require(_value != 0);
if (!tokenOwners.valueExists(msg.sender)) {
require(tokenOwners.sizeOf() < MAX_OWNERS);
@ -195,9 +214,9 @@ contract Escrow is Miner, Ownable {
/**
* @notice Lock some tokens or increase lock
* @param _value Amount of tokens which should lock
* @param _periods Amount of periods during which tokens will be locked
* @param _periods Amount of periods during which tokens will be unlocked
**/
function lock(uint256 _value, uint256 _periods) {
function lock(uint256 _value, uint256 _periods) public {
// TODO add checking min _value
require(_value != 0 || _periods != 0);
@ -209,27 +228,38 @@ contract Escrow is Miner, Ownable {
var currentPeriod = block.number.div(blocksPerPeriod);
if (lockedTokens == 0) {
info.lockedValue = _value;
info.releasePeriod = currentPeriod.add(_periods);
info.releaseRate = _value.div(minReleasePeriods);
info.maxReleasePeriods = Math.max256(_periods, minReleasePeriods);
info.releaseRate = Math.max256(_value.divCeil(info.maxReleasePeriods), 1);
info.release = false;
} else {
info.lockedValue = lockedTokens.add(_value);
var period = Math.max256(info.releasePeriod, currentPeriod);
info.releasePeriod = period.add(_periods);
info.maxReleasePeriods = info.maxReleasePeriods.add(_periods);
info.releaseRate = Math.max256(
info.releaseRate, info.lockedValue.div(minReleasePeriods));
info.lockedValue.divCeil(info.maxReleasePeriods), info.releaseRate);
}
confirmActivity(info.lockedValue);
}
/**
* @notice Switch lock
**/
function switchLock() public {
var info = tokenInfo[msg.sender];
info.release = !info.release;
}
/**
* @notice Withdraw available amount of tokens back to owner
* @param _value Amount of token to withdraw
**/
function withdraw(uint256 _value) {
function withdraw(uint256 _value) public {
var info = tokenInfo[msg.sender];
// TODO optimize
var lockedTokens = Math.max256(calculateLockedTokens(msg.sender, 1),
getLockedTokens(msg.sender));
require(_value <= token.balanceOf(address(this)) &&
_value <= info.value.sub(getLockedTokens(msg.sender)));
_value <= info.value.sub(lockedTokens));
info.value -= _value;
token.safeTransfer(msg.sender, _value);
}
@ -237,7 +267,7 @@ contract Escrow is Miner, Ownable {
/**
* @notice Withdraw all amount of tokens back to owner (only if no locked)
**/
function withdrawAll() {
function withdrawAll() public {
// TODO extract modifier
require(tokenOwners.valueExists(msg.sender));
var info = tokenInfo[msg.sender];
@ -314,7 +344,7 @@ contract Escrow is Miner, Ownable {
var currentPeriod = nextPeriod - 1;
var lockedTokens = calculateLockedTokens(
msg.sender, currentPeriod, getLockedTokens(msg.sender), 1);
msg.sender, false, getLockedTokens(msg.sender), 1);
confirmActivity(lockedTokens);
}
@ -327,9 +357,15 @@ contract Escrow is Miner, Ownable {
var numberPeriodsForMinting = info.numberConfirmedPeriods;
require(numberPeriodsForMinting > 0 &&
info.confirmedPeriods[0].period <= previousPeriod);
var currentLockedValue = getLockedTokens(msg.sender);
var currentLockedValue = getLockedTokens(msg.sender);
var allLockedBlocks = calculateLockedPeriods(
msg.sender,
info.confirmedPeriods[numberPeriodsForMinting - 1].lockedValue)
.add(numberPeriodsForMinting)
.mul(blocksPerPeriod);
var decimals = info.decimals;
if (info.confirmedPeriods[numberPeriodsForMinting - 1].period > previousPeriod) {
numberPeriodsForMinting--;
}
@ -345,7 +381,9 @@ contract Escrow is Miner, Ownable {
lockedValue,
lockedPerPeriod[period].totalLockedValue,
blocksPerPeriod,
allLockedBlocks,
decimals);
allLockedBlocks = allLockedBlocks.sub(blocksPerPeriod);
if (lockedPerPeriod[period].numberOwnersToBeRewarded > 1) {
lockedPerPeriod[period].numberOwnersToBeRewarded--;
} else {
@ -402,14 +440,14 @@ contract Escrow is Miner, Ownable {
info.confirmedPeriods[numberConfirmedPeriods - 1].period == currentPeriod) {
var lockedTokens = calculateLockedTokens(
current,
currentPeriod,
true,
info.confirmedPeriods[numberConfirmedPeriods - 1].lockedValue,
_periods);
} else if (numberConfirmedPeriods > 1 &&
info.confirmedPeriods[numberConfirmedPeriods - 2].period == currentPeriod) {
lockedTokens = calculateLockedTokens(
current,
currentPeriod + 1,
true,
info.confirmedPeriods[numberConfirmedPeriods - 1].lockedValue,
_periods - 1);
} else {

View File

@ -2,7 +2,6 @@ pragma solidity ^0.4.0;
import "./MineableToken.sol";
import "./lib/ExponentMath.sol";
import "./zeppelin/math/SafeMath.sol";
@ -14,18 +13,33 @@ contract Miner {
MineableToken token;
uint256 public miningCoefficient;
uint256 public lockedBlocksCoefficient;
uint256 public awardedLockedBlocks;
/**
* @notice The Miner constructor sets address of token contract and coefficients for mining
* @dev Formula for mining
(futureSupply - currentSupply) * (lockedBlocks * lockedValue / totalLockedValue / k)
(futureSupply - currentSupply) * (lockedBlocks * lockedValue / totalLockedValue) * (k1 + allLockedBlocks) / k2
if allLockedBlocks > awardedLockedBlocks then allLockedBlocks = awardedLockedBlocks
* @param _token Token contract
* @param _miningCoefficient Mining coefficient (k)
* @param _miningCoefficient Mining coefficient (k2)
* @param _lockedBlocksCoefficient Locked blocks coefficient (k1)
* @param _awardedLockedBlocks Max blocks that will be additionally awarded
**/
function Miner(MineableToken _token, uint256 _miningCoefficient) {
require(address(_token) != 0x0 && _miningCoefficient != 0);
function Miner(
MineableToken _token,
uint256 _miningCoefficient,
uint256 _lockedBlocksCoefficient,
uint256 _awardedLockedBlocks
) {
require(address(_token) != 0x0 &&
_miningCoefficient != 0 &&
_lockedBlocksCoefficient != 0 &&
_awardedLockedBlocks != 0);
token = _token;
miningCoefficient = _miningCoefficient;
lockedBlocksCoefficient = _lockedBlocksCoefficient;
awardedLockedBlocks = _awardedLockedBlocks;
}
/**
@ -33,7 +47,8 @@ contract Miner {
* @param _to The address that will receive the minted tokens.
* @param _lockedValue The amount of tokens that were locked by user.
* @param _totalLockedValue The amount of tokens that were locked by all users.
* @param _lockedBlocks The amount of blocks during which tokens were locked.
* @param _currentLockedBlocks The current amount of blocks during which tokens were locked.
* @param _allLockedBlocks The max amount of blocks during which tokens were locked.
* @param _decimals The amount of locked tokens and blocks in decimals.
* @return Amount of minted tokens.
*/
@ -41,16 +56,27 @@ contract Miner {
address _to,
uint256 _lockedValue,
uint256 _totalLockedValue,
uint256 _lockedBlocks,
uint256 _currentLockedBlocks,
uint256 _allLockedBlocks,
uint256 _decimals
)
internal returns (uint256 amount, uint256 decimals)
{
//futureSupply * lockedBlocks * lockedValue / (totalLockedValue * k) -
//currentSupply * lockedBlocks * lockedValue / (totalLockedValue * k)
uint256 denominator = _totalLockedValue.mul(miningCoefficient);
uint256 maxValue = token.futureSupply().mul(_lockedBlocks).mul(_lockedValue).div(denominator);
uint256 value = token.totalSupply().mul(_lockedBlocks).mul(_lockedValue).div(denominator);
//futureSupply * currentLockedBlocks * lockedValue * (k1 + allLockedBlocks) / (totalLockedValue * k2) -
//currentSupply * currentLockedBlocks * lockedValue * (k1 + allLockedBlocks) / (totalLockedValue * k2)
var allLockedBlocks = (_allLockedBlocks <= awardedLockedBlocks ?
_allLockedBlocks : awardedLockedBlocks).add(lockedBlocksCoefficient);
var denominator = _totalLockedValue.mul(miningCoefficient);
var maxValue = token.futureSupply()
.mul(_currentLockedBlocks)
.mul(_lockedValue)
// .mul(allLockedBlocks)
.div(denominator);
var value = token.totalSupply()
.mul(_currentLockedBlocks)
.mul(_lockedValue)
// .mul(allLockedBlocks)
.div(denominator);
amount = maxValue.sub(value);
token.mint(_to, amount);
}

View File

@ -6,6 +6,7 @@ import "./zeppelin/token/SafeERC20.sol";
import "./zeppelin/math/SafeMath.sol";
import "./zeppelin/math/Math.sol";
import "./zeppelin/ownership/Ownable.sol";
import "./lib/AdditionalMath.sol";
/**
@ -14,6 +15,7 @@ import "./zeppelin/ownership/Ownable.sol";
contract Wallet is Ownable {
using SafeERC20 for NuCypherKMSToken;
using SafeMath for uint256;
using AdditionalMath for uint256;
struct PeriodInfo {
uint256 period;
@ -21,15 +23,16 @@ contract Wallet is Ownable {
}
address public manager;
// TODO maybe get from manager
NuCypherKMSToken public token;
uint256 public blocksPerPeriod;
uint256 public minReleasePeriods;
uint256 public lockedValue;
uint256 public decimals;
// last period before the tokens begin to unlock
uint256 releasePeriod;
uint256 releaseRate;
bool public release;
uint256 public maxReleasePeriods;
uint256 public releaseRate;
PeriodInfo[] public confirmedPeriods;
uint256 public numberConfirmedPeriods;
@ -86,7 +89,7 @@ contract Wallet is Ownable {
}
}
// checks if owner can mine more tokens (before or after release period)
if (calculateLockedTokens(period, lockedValueToCheck, 1) == 0) {
if (calculateLockedTokens(false, lockedValueToCheck, 1) == 0) {
return 0;
} else {
return lockedValueToCheck;
@ -94,23 +97,21 @@ contract Wallet is Ownable {
}
/**
* @notice Calculate locked tokens value in next period
* @param _period Current or future period number
* @notice Calculate locked tokens value for owner in next period
* @param _forceRelease Force unlocking period calculation
* @param _lockedTokens Locked tokens in specified period
* @param _periods Number of periods after _period that need to calculate
* @param _periods Number of periods that need to calculate
* @return Calculated locked tokens in next period
**/
function calculateLockedTokens(
uint256 _period,
bool _forceRelease,
uint256 _lockedTokens,
uint256 _periods
)
public constant returns (uint256)
{
var nextPeriod = _period.add(_periods);
if (releasePeriod != 0 && releasePeriod < nextPeriod) {
var period = Math.max256(_period, releasePeriod);
var unlockedTokens = nextPeriod.sub(period).mul(releaseRate);
if ((_forceRelease || release) && _periods != 0) {
var unlockedTokens = _periods.mul(releaseRate);
return unlockedTokens <= _lockedTokens ? _lockedTokens.sub(unlockedTokens) : 0;
} else {
return _lockedTokens;
@ -139,7 +140,18 @@ contract Wallet is Ownable {
}
var periods = nextPeriod.sub(period);
return calculateLockedTokens(period, lockedTokens, periods);
return calculateLockedTokens(false, lockedTokens, periods);
}
/**
* @notice Calculate locked periods from start period
* @param _lockedTokens Locked tokens in start period
* @return Calculated locked periods
**/
function calculateLockedPeriods(uint256 _lockedTokens)
public constant returns (uint256)
{
return _lockedTokens.div(releaseRate);
}
/**
@ -156,14 +168,14 @@ contract Wallet is Ownable {
var currentPeriod = block.number.div(blocksPerPeriod);
if (lockedTokens == 0) {
lockedValue = _value;
releasePeriod = currentPeriod.add(_periods);
releaseRate = _value.div(minReleasePeriods);
maxReleasePeriods = Math.max256(_periods, minReleasePeriods);
releaseRate = Math.max256(_value.divCeil(maxReleasePeriods), 1);
release = false;
} else {
lockedValue = lockedTokens.add(_value);
var period = Math.max256(releasePeriod, currentPeriod);
releasePeriod = period.add(_periods);
maxReleasePeriods = maxReleasePeriods.add(_periods);
releaseRate = Math.max256(
releaseRate, lockedValue.div(minReleasePeriods));
lockedValue.divCeil(maxReleasePeriods), releaseRate);
}
}
@ -171,16 +183,26 @@ contract Wallet is Ownable {
* @notice Sets locked tokens
* @param _value Amount of tokens which should lock
**/
function updateLock(uint256 _value) onlyManager public {
function updateLockedTokens(uint256 _value) onlyManager public {
lockedValue = _value;
}
/**
* @notice Switch lock
**/
function switchLock() onlyOwner public {
release = !release;
}
/**
* @notice Withdraw available amount of tokens back to owner
* @param _value Amount of token to withdraw
**/
function withdraw(uint256 _value) onlyOwner public {
require(_value <= token.balanceOf(address(this)).sub(getLockedTokens()));
// TODO optimize
var lockedTokens = Math.max256(calculateLockedTokens(1),
getLockedTokens());
require(_value <= token.balanceOf(address(this)).sub(lockedTokens));
token.safeTransfer(msg.sender, _value);
}

View File

@ -39,14 +39,18 @@ contract WalletManager is Miner, Ownable {
* @param _miningCoefficient Mining coefficient
* @param _blocksPerPeriod Size of one period in blocks
* @param _minReleasePeriods Min amount of periods during which tokens will be released
* @param _lockedBlocksCoefficient Locked blocks coefficient
* @param _awardedPeriods Max periods that will be additionally awarded
**/
function WalletManager(
NuCypherKMSToken _token,
uint256 _miningCoefficient,
uint256 _blocksPerPeriod,
uint256 _minReleasePeriods
uint256 _minReleasePeriods,
uint256 _lockedBlocksCoefficient,
uint256 _awardedPeriods
)
Miner(_token, _miningCoefficient)
Miner(_token, _miningCoefficient, _lockedBlocksCoefficient, _awardedPeriods * _blocksPerPeriod)
{
require(_blocksPerPeriod != 0 && _minReleasePeriods != 0);
token = _token;
@ -66,7 +70,7 @@ contract WalletManager is Miner, Ownable {
* @notice Create wallet for user
* @return Address of created wallet
**/
function createWallet() returns (address) {
function createWallet() public returns (address) {
require(!walletOwners.valueExists(msg.sender) &&
walletOwners.sizeOf() < MAX_OWNERS);
Wallet wallet = new Wallet(token, blocksPerPeriod, minReleasePeriods);
@ -156,7 +160,7 @@ contract WalletManager is Miner, Ownable {
var currentPeriod = nextPeriod - 1;
var lockedTokens = wallet.calculateLockedTokens(
currentPeriod, wallet.getLockedTokens(), 1);
false, wallet.getLockedTokens(), 1);
confirmActivity(lockedTokens);
}
@ -164,14 +168,18 @@ contract WalletManager is Miner, Ownable {
* @notice Mint tokens for sender for previous periods if he locked his tokens and confirmed activity
**/
function mint() walletExists external {
var previousPeriod = block.number / blocksPerPeriod - 1;
var previousPeriod = block.number.div(blocksPerPeriod).sub(1);
var wallet = wallets[msg.sender];
var numberPeriodsForMinting = wallet.numberConfirmedPeriods();
require(numberPeriodsForMinting > 0 &&
wallet.getConfirmedPeriod(0) <= previousPeriod);
var currentLockedValue = wallet.getLockedTokens();
var allLockedBlocks = wallet.calculateLockedPeriods(
wallet.getConfirmedPeriodValue(numberPeriodsForMinting - 1))
.add(numberPeriodsForMinting)
.mul(blocksPerPeriod);
var decimals = wallet.decimals();
if (wallet.getConfirmedPeriod(numberPeriodsForMinting - 1) > previousPeriod) {
numberPeriodsForMinting--;
}
@ -186,7 +194,9 @@ contract WalletManager is Miner, Ownable {
lockedValue,
lockedPerPeriod[period].totalLockedValue,
blocksPerPeriod,
allLockedBlocks,
decimals);
allLockedBlocks = allLockedBlocks.sub(blocksPerPeriod);
if (lockedPerPeriod[period].numberOwnersToBeRewarded > 1) {
lockedPerPeriod[period].numberOwnersToBeRewarded--;
} else {
@ -197,7 +207,7 @@ contract WalletManager is Miner, Ownable {
wallet.deleteConfirmedPeriods(numberPeriodsForMinting);
// Update lockedValue for current period
wallet.updateLock(currentLockedValue);
wallet.updateLockedTokens(currentLockedValue);
}
/**
@ -237,13 +247,13 @@ contract WalletManager is Miner, Ownable {
if (numberConfirmedPeriods > 0 &&
wallet.getConfirmedPeriod(numberConfirmedPeriods - 1) == currentPeriod) {
var lockedTokens = wallet.calculateLockedTokens(
currentPeriod,
true,
wallet.getConfirmedPeriodValue(numberConfirmedPeriods - 1),
_periods);
} else if (numberConfirmedPeriods > 1 &&
wallet.getConfirmedPeriod(numberConfirmedPeriods - 2) == currentPeriod) {
lockedTokens = wallet.calculateLockedTokens(
currentPeriod + 1,
true,
wallet.getConfirmedPeriodValue(numberConfirmedPeriods - 1),
_periods - 1);
} else {

View File

@ -0,0 +1,21 @@
pragma solidity ^0.4.11;
import "../zeppelin/math/SafeMath.sol";
/**
* @notice Additional math operations
**/
library AdditionalMath {
using SafeMath for uint256;
/**
* @notice Division and ceil
**/
function divCeil(uint256 a, uint256 b)
public constant returns (uint256) {
return (a.add(b) - 1) / b;
}
}

View File

@ -1,65 +0,0 @@
pragma solidity ^0.4.11;
/**
* @notice Math operations for calculating exponent
**/
library ExponentMath {
/**
* @notice Calculate k*e^(x/rate)
* @param x Point on the curve
* @param k Coefficient used for increase precision
* @param rate Curve growing rate
* @param iterations Calculate iterations. The higher the value,
the greater the accuracy and the higher the cost
* @return k*e^(x/rate)
**/
function exp(
uint256 x,
uint256 k,
uint256 rate,
uint64 iterations
)
internal constant returns (uint256)
{
require(iterations != 0);
uint256 result = k + k * x / rate;
uint256 factorial = 1;
for (uint i = 2; i <= iterations; i++) {
factorial *= i;
uint256 value = k * (x ** i) / (factorial * (rate ** i));
if (value == 0) {
break;
}
result += value;
}
return result;
}
/**
* @notice Calculate maxValue*(1-1/e^(x/rate))
* @param x Point on the curve
* @param maxValue Max value
* @param rate Curve growing rate
* @param multiplicator Coefficient used for increase precision.
Low values lead to low accuracy, but high value can cause overflow
* @param iterations Calculate iterations. The higher the value,
the greater the accuracy and the higher the cost
* @return maxValue*(1-1/e^(x/rate))
**/
function exponentialFunction(
uint256 x,
uint256 maxValue,
uint256 rate,
uint256 multiplicator,
uint64 iterations
)
internal constant returns (uint256)
{
return (multiplicator * maxValue -
maxValue * multiplicator ** 2 / exp(x, multiplicator, rate, iterations)) /
multiplicator;
}
}

View File

@ -21,6 +21,8 @@ def lock(amount: int, locktime: int, address: str = None):
chain.wait.for_receipt(tx, timeout=blockchain.TIMEOUT)
tx = escrow.transact({'from': address}).deposit(amount, locktime)
chain.wait.for_receipt(tx, timeout=blockchain.TIMEOUT)
tx = escrow.transact({'from': address}).switchLock()
chain.wait.for_receipt(tx, timeout=blockchain.TIMEOUT)
def mine(address: str = None):

View File

@ -12,9 +12,11 @@ contract MinerTest is Miner {
function MinerTest(
MineableToken _token,
uint256 _miningCoefficient
uint256 _miningCoefficient,
uint256 _lockedBlocksCoefficient,
uint256 _awardedLockedBlocks
)
Miner(_token, _miningCoefficient)
Miner(_token, _miningCoefficient, _lockedBlocksCoefficient, _awardedLockedBlocks)
{
}
@ -23,11 +25,18 @@ contract MinerTest is Miner {
uint256 _lockedValue,
uint256 _totalLockedValue,
uint256 _lockedBlocks,
uint256 _allLockedBlocks,
uint256 _decimals
)
public returns (uint256 amount, uint256 decimals)
{
return mint(_to, _lockedValue, _totalLockedValue, _lockedBlocks, _decimals);
return mint(
_to,
_lockedValue,
_totalLockedValue,
_lockedBlocks,
_allLockedBlocks,
_decimals);
}
}

View File

@ -1,41 +0,0 @@
pragma solidity ^0.4.11;
import "contracts/lib/ExponentMath.sol";
/**
* @dev Contract for testing ExponentMath library
**/
contract ExponentMathTest {
/**
* @dev maxValue*(1-1/e^(x/rate))
**/
function exponentialFunction(
uint256 x,
uint256 maxValue,
uint256 rate,
uint256 multiplicator,
uint64 iterations
)
constant returns (uint256)
{
return ExponentMath.exponentialFunction(x, maxValue, rate, multiplicator, iterations);
}
/**
* @dev k*e^(x/rate)
**/
function exp(
uint256 x,
uint256 k,
uint256 rate,
uint64 iterations
)
constant returns (uint256)
{
return ExponentMath.exp(x, k, rate, iterations);
}
}

View File

@ -17,7 +17,7 @@ def escrow(web3, chain, token):
creator = web3.eth.accounts[0]
# Creator deploys the escrow
escrow, _ = chain.provider.get_or_deploy_contract(
'Escrow', deploy_args=[token.address, 10 ** 9, 50, 2],
'Escrow', deploy_args=[token.address, 10 ** 9, 50, 2, 1, 1],
deploy_transaction={'from': creator})
return escrow
@ -50,7 +50,7 @@ def test_escrow(web3, chain, token, escrow):
# And can't lock because nothing to lock
with pytest.raises(TransactionFailed):
tx = escrow.transact({'from': ursula}).lock(500, 100)
tx = escrow.transact({'from': ursula}).lock(500, 2)
chain.wait.for_receipt(tx)
# Check that nothing is locked
@ -64,21 +64,25 @@ def test_escrow(web3, chain, token, escrow):
# chain.wait.for_receipt(tx)
# Ursula and Alice transfer some tokens to the escrow and lock them
tx = escrow.transact({'from': ursula}).deposit(1000, 2)
tx = escrow.transact({'from': ursula}).deposit(1000, 1)
chain.wait.for_receipt(tx)
assert 1000 == token.call().balanceOf(escrow.address)
assert 9000 == token.call().balanceOf(ursula)
assert 1000 == escrow.call().getLockedTokens(ursula)
assert 500 == escrow.call().calculateLockedTokens(ursula, 3)
assert 0 == escrow.call().calculateLockedTokens(ursula, 4)
tx = escrow.transact({'from': alice}).deposit(500, 6)
assert 1000 == escrow.call().calculateLockedTokens(ursula, 1)
assert 1000 == escrow.call().calculateLockedTokens(ursula, 2)
tx = escrow.transact({'from': ursula}).switchLock()
chain.wait.for_receipt(tx)
assert 500 == escrow.call().calculateLockedTokens(ursula, 2)
tx = escrow.transact({'from': ursula}).switchLock()
chain.wait.for_receipt(tx)
assert 1000 == escrow.call().calculateLockedTokens(ursula, 2)
tx = escrow.transact({'from': alice}).deposit(500, 2)
chain.wait.for_receipt(tx)
assert 1500 == token.call().balanceOf(escrow.address)
assert 9500 == token.call().balanceOf(alice)
assert 500 == escrow.call().getLockedTokens(alice)
assert 500 == escrow.call().calculateLockedTokens(alice, 6)
assert 250 == escrow.call().calculateLockedTokens(alice, 7)
assert 0 == escrow.call().calculateLockedTokens(alice, 8)
assert 500 == escrow.call().calculateLockedTokens(alice, 1)
# Checks locked tokens in next period
chain.wait.for_block(web3.eth.blockNumber + 50)
@ -100,6 +104,10 @@ def test_escrow(web3, chain, token, escrow):
chain.wait.for_receipt(tx)
assert 2000 == token.call().balanceOf(escrow.address)
assert 8500 == token.call().balanceOf(ursula)
# Ursula starts unlocking
tx = escrow.transact({'from': ursula}).switchLock()
chain.wait.for_receipt(tx)
assert 750 == escrow.call().calculateLockedTokens(ursula, 2)
# Wait 50 blocks and checks locking
@ -134,6 +142,9 @@ def test_escrow(web3, chain, token, escrow):
# Release rate will be updated too because of end of previous locking
assert 750 == escrow.call().getLockedTokens(ursula)
assert 600 == escrow.call().calculateLockedTokens(ursula, 1)
assert 600 == escrow.call().calculateLockedTokens(ursula, 2)
tx = escrow.transact({'from': ursula}).switchLock()
chain.wait.for_receipt(tx)
assert 300 == escrow.call().calculateLockedTokens(ursula, 2)
assert 0 == escrow.call().calculateLockedTokens(ursula, 3)
chain.wait.for_block(web3.eth.blockNumber + 50)
@ -146,8 +157,8 @@ def test_escrow(web3, chain, token, escrow):
chain.wait.for_receipt(tx)
assert 600 == escrow.call().getLockedTokens(ursula)
assert 800 == escrow.call().calculateLockedTokens(ursula, 1)
assert 800 == escrow.call().calculateLockedTokens(ursula, 2)
assert 400 == escrow.call().calculateLockedTokens(ursula, 3)
assert 500 == escrow.call().calculateLockedTokens(ursula, 2)
assert 200 == escrow.call().calculateLockedTokens(ursula, 3)
assert 0 == escrow.call().calculateLockedTokens(ursula, 4)
chain.wait.for_block(web3.eth.blockNumber + 50)
assert 800 == escrow.call().getLockedTokens(ursula)
@ -158,9 +169,11 @@ def test_escrow(web3, chain, token, escrow):
# tx = escrow.transact({'from': ursula}).deposit(100, 100)
# chain.wait.for_receipt(tx)
# Alice increases lock by deposit more tokens
# Alice starts unlocking and increases lock by deposit more tokens
tx = escrow.transact({'from': alice}).deposit(500, 0)
chain.wait.for_receipt(tx)
tx = escrow.transact({'from': alice}).switchLock()
chain.wait.for_receipt(tx)
assert 500 == escrow.call().getLockedTokens(alice)
assert 1000 == escrow.call().calculateLockedTokens(alice, 1)
assert 500 == escrow.call().calculateLockedTokens(alice, 2)
@ -173,16 +186,14 @@ def test_escrow(web3, chain, token, escrow):
chain.wait.for_receipt(tx)
assert 1000 == escrow.call().getLockedTokens(alice)
assert 500 == escrow.call().calculateLockedTokens(alice, 1)
assert 500 == escrow.call().calculateLockedTokens(alice, 2)
assert 0 == escrow.call().calculateLockedTokens(alice, 3)
assert 0 == escrow.call().calculateLockedTokens(alice, 2)
# Alice increases lock by small amount of tokens
tx = escrow.transact({'from': alice}).deposit(100, 0)
chain.wait.for_receipt(tx)
assert 600 == escrow.call().calculateLockedTokens(alice, 1)
assert 600 == escrow.call().calculateLockedTokens(alice, 2)
assert 100 == escrow.call().calculateLockedTokens(alice, 3)
assert 0 == escrow.call().calculateLockedTokens(alice, 4)
assert 100 == escrow.call().calculateLockedTokens(alice, 2)
assert 0 == escrow.call().calculateLockedTokens(alice, 3)
# Ursula can't destroy contract
with pytest.raises(TransactionFailed):
@ -228,6 +239,11 @@ def test_locked_distribution(web3, chain, token, escrow):
n_locked = escrow.call().getAllLockedTokens()
assert n_locked > 0
# And confirm activity
for miner in miners:
tx = escrow.transact({'from': miner}).confirmActivity()
chain.wait.for_receipt(tx)
address_stop, shift = escrow.call().findCumSum(NULL_ADDR, n_locked // 3, 1)
assert miners[0].lower() == address_stop.lower()
assert n_locked // 3 == shift
@ -241,7 +257,10 @@ def test_locked_distribution(web3, chain, token, escrow):
assert miners[2].lower() == address_stop.lower()
assert 1 == shift
address_stop, shift = escrow.call().findCumSum(NULL_ADDR, 1, 12)
address_stop, shift = escrow.call().findCumSum(NULL_ADDR, 1, 10)
assert NULL_ADDR != address_stop.lower()
assert 0 != shift
address_stop, shift = escrow.call().findCumSum(NULL_ADDR, 1, 11)
assert NULL_ADDR == address_stop.lower()
assert 0 == shift
@ -271,15 +290,15 @@ def test_mining(web3, chain, token, escrow):
chain.wait.for_receipt(tx)
# Ursula and Alice give Escrow rights to transfer
tx = token.transact({'from': ursula}).approve(escrow.address, 1000)
tx = token.transact({'from': ursula}).approve(escrow.address, 2000)
chain.wait.for_receipt(tx)
tx = token.transact({'from': alice}).approve(escrow.address, 500)
chain.wait.for_receipt(tx)
# Ursula and Alice transfer some tokens to the escrow and lock them
tx = escrow.transact({'from': ursula}).deposit(1000, 2)
tx = escrow.transact({'from': ursula}).deposit(1000, 1)
chain.wait.for_receipt(tx)
tx = escrow.transact({'from': alice}).deposit(500, 4)
tx = escrow.transact({'from': alice}).deposit(500, 2)
chain.wait.for_receipt(tx)
# Using locked tokens starts from next period
@ -292,7 +311,7 @@ def test_mining(web3, chain, token, escrow):
# Ursula can't use method from Miner contract
with pytest.raises(TypeError):
tx = escrow.transact({'from': ursula}).mint(ursula, 1000, 1000, 1000, 1000)
tx = escrow.transact({'from': ursula}).mint(ursula, 1, 1, 1, 1, 1)
chain.wait.for_receipt(tx)
# Only Ursula confirm next period
@ -316,6 +335,8 @@ def test_mining(web3, chain, token, escrow):
assert 9517 == token.call().balanceOf(alice)
# Only Ursula confirm activity for next period
tx = escrow.transact({'from': ursula}).switchLock()
chain.wait.for_receipt(tx)
tx = escrow.transact({'from': ursula}).confirmActivity()
chain.wait.for_receipt(tx)
@ -342,7 +363,9 @@ def test_mining(web3, chain, token, escrow):
assert 9133 == token.call().balanceOf(ursula)
assert 9517 == token.call().balanceOf(alice)
# Alice confirm 2 periods and mint tokens
# Alice confirm next period and mint tokens
tx = escrow.transact({'from': alice}).switchLock()
chain.wait.for_receipt(tx)
tx = escrow.transact({'from': alice}).confirmActivity()
chain.wait.for_receipt(tx)
chain.wait.for_block(web3.eth.blockNumber + 100)
@ -363,29 +386,33 @@ def test_mining(web3, chain, token, escrow):
# Ursula can lock some tokens again
tx = escrow.transact({'from': ursula}).lock(500, 4)
chain.wait.for_receipt(tx)
tx = escrow.transact({'from': ursula}).switchLock()
chain.wait.for_receipt(tx)
assert 500 == escrow.call().getLockedTokens(ursula)
assert 500 == escrow.call().calculateLockedTokens(ursula, 2)
assert 250 == escrow.call().calculateLockedTokens(ursula, 5)
assert 0 == escrow.call().calculateLockedTokens(ursula, 6)
assert 500 == escrow.call().calculateLockedTokens(ursula, 1)
assert 375 == escrow.call().calculateLockedTokens(ursula, 2)
assert 250 == escrow.call().calculateLockedTokens(ursula, 3)
assert 0 == escrow.call().calculateLockedTokens(ursula, 5)
# And can increase lock
tx = escrow.transact({'from': ursula}).lock(100, 0)
chain.wait.for_receipt(tx)
assert 600 == escrow.call().getLockedTokens(ursula)
assert 600 == escrow.call().calculateLockedTokens(ursula, 2)
assert 300 == escrow.call().calculateLockedTokens(ursula, 5)
assert 0 == escrow.call().calculateLockedTokens(ursula, 6)
assert 600 == escrow.call().calculateLockedTokens(ursula, 1)
assert 450 == escrow.call().calculateLockedTokens(ursula, 2)
assert 0 == escrow.call().calculateLockedTokens(ursula, 5)
tx = escrow.transact({'from': ursula}).lock(0, 2)
chain.wait.for_receipt(tx)
assert 600 == escrow.call().getLockedTokens(ursula)
assert 600 == escrow.call().calculateLockedTokens(ursula, 5)
assert 300 == escrow.call().calculateLockedTokens(ursula, 7)
assert 0 == escrow.call().calculateLockedTokens(ursula, 9)
tx = escrow.transact({'from': ursula}).lock(100, 1)
assert 600 == escrow.call().calculateLockedTokens(ursula, 1)
assert 450 == escrow.call().calculateLockedTokens(ursula, 2)
assert 0 == escrow.call().calculateLockedTokens(ursula, 5)
tx = escrow.transact({'from': ursula}).deposit(800, 1)
chain.wait.for_receipt(tx)
assert 700 == escrow.call().getLockedTokens(ursula)
assert 700 == escrow.call().calculateLockedTokens(ursula, 6)
assert 350 == escrow.call().calculateLockedTokens(ursula, 8)
assert 0 == escrow.call().calculateLockedTokens(ursula, 9)
assert 1400 == escrow.call().getLockedTokens(ursula)
assert 1400 == escrow.call().calculateLockedTokens(ursula, 1)
assert 1000 == escrow.call().calculateLockedTokens(ursula, 3)
assert 400 == escrow.call().calculateLockedTokens(ursula, 6)
assert 0 == escrow.call().calculateLockedTokens(ursula, 8)
# Alice can withdraw all
tx = escrow.transact({'from': alice}).withdrawAll()

View File

@ -17,7 +17,7 @@ def wallet_manager(web3, chain, token):
creator = web3.eth.accounts[0]
# Creator deploys the wallet manager
wallet_manager_contract, _ = chain.provider.get_or_deploy_contract(
'WalletManager', deploy_args=[token.address, 10 ** 9, 50, 2],
'WalletManager', deploy_args=[token.address, 10 ** 9, 50, 2, 1, 1],
deploy_transaction={'from': creator, 'gas': 4000000})
return wallet_manager_contract
@ -56,7 +56,7 @@ def test_escrow(web3, chain, token, wallet_manager):
# And can't set lock using wallet
with pytest.raises(TransactionFailed):
tx = ursula_wallet.transact({'from': ursula}).updateLock(1)
tx = ursula_wallet.transact({'from': ursula}).updateLockedTokens(1)
chain.wait.for_receipt(tx)
# Ursula and Alice transfer some money to wallets
@ -90,10 +90,21 @@ def test_escrow(web3, chain, token, wallet_manager):
# chain.wait.for_receipt(tx)
# Ursula and Alice lock some tokens for 100 and 200 blocks
tx = wallet_manager.transact({'from': ursula}).lock(1000, 2)
tx = wallet_manager.transact({'from': ursula}).lock(1000, 1)
chain.wait.for_receipt(tx)
tx = wallet_manager.transact({'from': alice}).lock(500, 6)
tx = wallet_manager.transact({'from': alice}).lock(500, 2)
chain.wait.for_receipt(tx)
assert 1000 == ursula_wallet.call().getLockedTokens()
assert 1000 == ursula_wallet.call().calculateLockedTokens(1)
assert 1000 == ursula_wallet.call().calculateLockedTokens(2)
tx = ursula_wallet.transact({'from': ursula}).switchLock()
chain.wait.for_receipt(tx)
assert 500 == ursula_wallet.call().calculateLockedTokens(2)
tx = ursula_wallet.transact({'from': ursula}).switchLock()
chain.wait.for_receipt(tx)
assert 1000 == ursula_wallet.call().calculateLockedTokens(2)
assert 500 == alice_wallet.call().getLockedTokens()
assert 500 == alice_wallet.call().calculateLockedTokens(1)
# Checks locked tokens in next period
chain.wait.for_block(web3.eth.blockNumber + 50)
@ -121,7 +132,10 @@ def test_escrow(web3, chain, token, wallet_manager):
# Wait 50 blocks and checks locking
chain.wait.for_block(web3.eth.blockNumber + 50)
assert 1500 == ursula_wallet.call().getLockedTokens()
assert 750 == ursula_wallet.call().calculateLockedTokens(web3.eth.blockNumber // 50, 1500, 1)
# Ursula starts unlocking
tx = ursula_wallet.transact({'from': ursula}).switchLock()
chain.wait.for_receipt(tx)
assert 750 == ursula_wallet.call().calculateLockedTokens(1)
assert 0 == ursula_wallet.call().calculateLockedTokens(2)
@ -159,6 +173,9 @@ def test_escrow(web3, chain, token, wallet_manager):
# Locked tokens will be updated in next period
assert 750 == ursula_wallet.call().getLockedTokens()
assert 600 == ursula_wallet.call().calculateLockedTokens(1)
assert 600 == ursula_wallet.call().calculateLockedTokens(2)
tx = ursula_wallet.transact({'from': ursula}).switchLock()
chain.wait.for_receipt(tx)
assert 300 == ursula_wallet.call().calculateLockedTokens(2)
assert 0 == ursula_wallet.call().calculateLockedTokens(3)
chain.wait.for_block(web3.eth.blockNumber + 50)
@ -171,8 +188,8 @@ def test_escrow(web3, chain, token, wallet_manager):
chain.wait.for_receipt(tx)
assert 600 == ursula_wallet.call().getLockedTokens()
assert 800 == ursula_wallet.call().calculateLockedTokens(1)
assert 800 == ursula_wallet.call().calculateLockedTokens(2)
assert 400 == ursula_wallet.call().calculateLockedTokens(3)
assert 500 == ursula_wallet.call().calculateLockedTokens(2)
assert 200 == ursula_wallet.call().calculateLockedTokens(3)
assert 0 == ursula_wallet.call().calculateLockedTokens(4)
chain.wait.for_block(web3.eth.blockNumber + 50)
assert 800 == ursula_wallet.call().getLockedTokens()
@ -188,6 +205,8 @@ def test_escrow(web3, chain, token, wallet_manager):
chain.wait.for_receipt(tx)
tx = wallet_manager.transact({'from': alice}).lock(500, 0)
chain.wait.for_receipt(tx)
tx = alice_wallet.transact({'from': alice}).switchLock()
chain.wait.for_receipt(tx)
assert 500 == alice_wallet.call().getLockedTokens()
assert 1000 == alice_wallet.call().calculateLockedTokens(1)
assert 500 == alice_wallet.call().calculateLockedTokens(2)
@ -200,16 +219,14 @@ def test_escrow(web3, chain, token, wallet_manager):
chain.wait.for_receipt(tx)
assert 1000 == alice_wallet.call().getLockedTokens()
assert 500 == alice_wallet.call().calculateLockedTokens(1)
assert 500 == alice_wallet.call().calculateLockedTokens(2)
assert 0 == alice_wallet.call().calculateLockedTokens(3)
assert 0 == alice_wallet.call().calculateLockedTokens(2)
# Alice increases lock by small amount of tokens
tx = wallet_manager.transact({'from': alice}).lock(100, 0)
chain.wait.for_receipt(tx)
assert 600 == alice_wallet.call().calculateLockedTokens(1)
assert 600 == alice_wallet.call().calculateLockedTokens(2)
assert 100 == alice_wallet.call().calculateLockedTokens(3)
assert 0 == alice_wallet.call().calculateLockedTokens(4)
assert 100 == alice_wallet.call().calculateLockedTokens(2)
assert 0 == alice_wallet.call().calculateLockedTokens(3)
# Ursula can't destroy contract
with pytest.raises(TransactionFailed):
@ -259,6 +276,11 @@ def test_locked_distribution(web3, chain, token, wallet_manager):
n_locked = wallet_manager.call().getAllLockedTokens()
assert n_locked > 0
# And confirm activity
for miner in miners:
tx = wallet_manager.transact({'from': miner}).confirmActivity()
chain.wait.for_receipt(tx)
address_stop, shift = wallet_manager.call().findCumSum(NULL_ADDR, n_locked // 3, 1)
assert miners[0].lower() == address_stop.lower()
assert n_locked // 3 == shift
@ -272,7 +294,10 @@ def test_locked_distribution(web3, chain, token, wallet_manager):
assert miners[2].lower() == address_stop.lower()
assert 1 == shift
address_stop, shift = wallet_manager.call().findCumSum(NULL_ADDR, 1, 12)
address_stop, shift = wallet_manager.call().findCumSum(NULL_ADDR, 1, 10)
assert NULL_ADDR != address_stop.lower()
assert 0 != shift
address_stop, shift = wallet_manager.call().findCumSum(NULL_ADDR, 1, 11)
assert NULL_ADDR == address_stop.lower()
assert 0 == shift
@ -318,10 +343,10 @@ def test_mining(web3, chain, token, wallet_manager):
tx = wallet_manager.transact({'from': ursula}).mint()
chain.wait.for_receipt(tx)
# Ursula and Alice lock some tokens for 100 and 200 blocks
tx = wallet_manager.transact({'from': ursula}).lock(1000, 2)
# Ursula and Alice lock some tokens
tx = wallet_manager.transact({'from': ursula}).lock(1000, 1)
chain.wait.for_receipt(tx)
tx = wallet_manager.transact({'from': alice}).lock(500, 4)
tx = wallet_manager.transact({'from': alice}).lock(500, 2)
chain.wait.for_receipt(tx)
# Using locked tokens starts from next period
@ -329,7 +354,7 @@ def test_mining(web3, chain, token, wallet_manager):
# Ursula can't use method from Miner contract
with pytest.raises(TypeError):
tx = wallet_manager.transact({'from': ursula}).mint(ursula, 1000, 1000, 1000, 1000)
tx = wallet_manager.transact({'from': ursula}).mint(ursula, 1, 1, 1, 1, 1)
chain.wait.for_receipt(tx)
# Only Ursula confirm next period
@ -353,6 +378,8 @@ def test_mining(web3, chain, token, wallet_manager):
assert 517 == token.call().balanceOf(alice_wallet.address)
# Only Ursula confirm activity for next period
tx = ursula_wallet.transact({'from': ursula}).switchLock()
chain.wait.for_receipt(tx)
tx = wallet_manager.transact({'from': ursula}).confirmActivity()
chain.wait.for_receipt(tx)
@ -379,7 +406,9 @@ def test_mining(web3, chain, token, wallet_manager):
assert 1133 == token.call().balanceOf(ursula_wallet.address)
assert 517 == token.call().balanceOf(alice_wallet.address)
# Alice confirm 2 periods and mint tokens
# Alice confirm next period and mint tokens
tx = alice_wallet.transact({'from': alice}).switchLock()
chain.wait.for_receipt(tx)
tx = wallet_manager.transact({'from': alice}).confirmActivity()
chain.wait.for_receipt(tx)
chain.wait.for_block(web3.eth.blockNumber + 100)
@ -408,29 +437,35 @@ def test_mining(web3, chain, token, wallet_manager):
# Ursula can lock some tokens again
tx = wallet_manager.transact({'from': ursula}).lock(500, 4)
chain.wait.for_receipt(tx)
tx = ursula_wallet.transact({'from': ursula}).switchLock()
chain.wait.for_receipt(tx)
assert 500 == ursula_wallet.call().getLockedTokens()
assert 500 == ursula_wallet.call().calculateLockedTokens(2)
assert 250 == ursula_wallet.call().calculateLockedTokens(5)
assert 0 == ursula_wallet.call().calculateLockedTokens(6)
assert 500 == ursula_wallet.call().calculateLockedTokens(1)
assert 375 == ursula_wallet.call().calculateLockedTokens(2)
assert 250 == ursula_wallet.call().calculateLockedTokens(3)
assert 0 == ursula_wallet.call().calculateLockedTokens(5)
# And can increase lock
tx = wallet_manager.transact({'from': ursula}).lock(100, 0)
chain.wait.for_receipt(tx)
assert 600 == ursula_wallet.call().getLockedTokens()
assert 600 == ursula_wallet.call().calculateLockedTokens(2)
assert 300 == ursula_wallet.call().calculateLockedTokens(5)
assert 0 == ursula_wallet.call().calculateLockedTokens(6)
assert 600 == ursula_wallet.call().calculateLockedTokens(1)
assert 450 == ursula_wallet.call().calculateLockedTokens(2)
assert 0 == ursula_wallet.call().calculateLockedTokens(5)
tx = wallet_manager.transact({'from': ursula}).lock(0, 2)
chain.wait.for_receipt(tx)
assert 600 == ursula_wallet.call().getLockedTokens()
assert 600 == ursula_wallet.call().calculateLockedTokens(5)
assert 300 == ursula_wallet.call().calculateLockedTokens(7)
assert 0 == ursula_wallet.call().calculateLockedTokens(8)
tx = wallet_manager.transact({'from': ursula}).lock(100, 1)
assert 600 == ursula_wallet.call().calculateLockedTokens(1)
assert 450 == ursula_wallet.call().calculateLockedTokens(2)
assert 0 == ursula_wallet.call().calculateLockedTokens(5)
tx = token.transact({'from': ursula}).transfer(ursula_wallet.address, 800)
chain.wait.for_receipt(tx)
assert 700 == ursula_wallet.call().getLockedTokens()
assert 700 == ursula_wallet.call().calculateLockedTokens(6)
assert 350 == ursula_wallet.call().calculateLockedTokens(8)
assert 0 == ursula_wallet.call().calculateLockedTokens(9)
tx = wallet_manager.transact({'from': ursula}).lock(800, 1)
chain.wait.for_receipt(tx)
assert 1400 == ursula_wallet.call().getLockedTokens()
assert 1400 == ursula_wallet.call().calculateLockedTokens(1)
assert 1000 == ursula_wallet.call().calculateLockedTokens(3)
assert 400 == ursula_wallet.call().calculateLockedTokens(6)
assert 0 == ursula_wallet.call().calculateLockedTokens(8)
# Alice can withdraw all
# TODO complete method

View File

@ -1,24 +0,0 @@
import math
def test_math(chain):
"""
These are tests for math library
"""
math_contract, _ = chain.provider.get_or_deploy_contract('ExponentMathTest')
assert int(math.exp(2)) == int(math_contract.call().exp(2, 100, 1, 30) / 100)
assert int(math.exp(2.5)) == int(math_contract.call().exp(25, 100, 10, 30) / 100)
assert int(math.exp(10)) == int(math_contract.call().exp(10, 100, 1, 30) / 100)
assert int(1000 * (1 - math.exp(-2))) == \
math_contract.call().exponentialFunction(2, 1000, 1, 200, 30)
assert int(1000 * (1 - math.exp(-2.5))) == \
math_contract.call().exponentialFunction(25, 1000, 10, 200, 30)
assert int(10 ** 9 * (1 - math.exp(-0.0000001))) == \
math_contract.call().exponentialFunction(10, 10 ** 9, 10 ** 8, 10 ** 8, 30)
# assert int(10 ** 9 * (1 - math.exp(-0.00000001))) == \
# math_contract.call().exponentialFunction(1, 10 ** 9, 10 ** 8, 10 ** 8, 30)
# assert int(10 ** 9 * (1 - math.exp(-10))) == \
# math_contract.call().exponentialFunction(10 ** 9, 10 ** 9, 10 ** 8, 10 ** 8, 30)

View File

@ -18,7 +18,7 @@ def test_miner(web3, chain, token):
# Creator deploys the miner
miner, _ = chain.provider.get_or_deploy_contract(
'MinerTest', deploy_args=[token.address, 10 ** 41],
'MinerTest', deploy_args=[token.address, 10 ** 41, 1, 1],
deploy_transaction={'from': creator})
# Give rights for mining
@ -40,13 +40,13 @@ def test_miner(web3, chain, token):
# assert miner.call().lastMintedPoint() == 0
# Mint some tokens
tx = miner.transact().testMint(ursula, 1000, 2000, 100, 0)
tx = miner.transact().testMint(ursula, 1000, 2000, 100, 0, 0)
chain.wait.for_receipt(tx)
assert 10 == token.call().balanceOf(ursula)
assert 10 ** 30 + 10 == token.call().totalSupply()
# Mint more tokens
tx = miner.transact().testMint(ursula, 500, 500, 200, 0)
tx = miner.transact().testMint(ursula, 500, 500, 200, 0, 0)
chain.wait.for_receipt(tx)
assert 50 == token.call().balanceOf(ursula)
assert 10 ** 30 + 50 == token.call().totalSupply()

View File

@ -55,7 +55,7 @@ def test_mine_withdraw(chain):
# Create a random set of miners (we have 9 in total)
for u in chain.web3.eth.accounts[1:]:
ursula.lock((10 + random.randrange(9000)) * M, 2, u)
ursula.lock((10 + random.randrange(9000)) * M, 1, u)
chain.wait.for_block(chain.web3.eth.blockNumber + 100)