[KMS-ETH]- Fixed increasing lock

pull/195/head^2
szotov 2018-01-02 18:14:50 +03:00
parent 41906af98a
commit fb116beef0
3 changed files with 92 additions and 159 deletions

View File

@ -85,19 +85,14 @@ contract Escrow is Miner, Ownable {
* @param _periods Amount of periods during which tokens will be locked
**/
function lock(uint256 _value, uint256 _periods) returns (bool success) {
// TODO add checking min reward
require(_value != 0 || _periods != 0);
var lockedTokens = getLockedTokens(msg.sender);
Test(lockedTokens);
// if (!allTokensMinted()) {
// lockedTokens = info.lockedValue;
// }
var info = tokenInfo[msg.sender];
require(_value <= token.balanceOf(address(this)) &&
_value <= info.value.sub(lockedTokens));
// Checks if tokens are not locked or lock can be increased
// TODO add checking amount of reward
// require(lockedTokens == 0 ||
// info.releaseBlock >= block.number);
if (lockedTokens == 0) {
info.lockedValue = _value;
info.releasePeriod = block.number.div(blocksPerPeriod).add(_periods).add(1);
@ -105,10 +100,10 @@ contract Escrow is Miner, Ownable {
info.lockedValue = info.lockedValue.add(_value);
info.releasePeriod = info.releasePeriod.add(_periods);
}
confirmActivity();
confirmActivity(info.lockedValue);
return true;
}
event Test(uint v);
/**
* @notice Withdraw available amount of tokens back to owner
@ -168,58 +163,6 @@ contract Escrow is Miner, Ownable {
var currentPeriod = block.number.div(blocksPerPeriod);
var info = tokenInfo[_owner];
var numberConfirmedPeriods = info.numberConfirmedPeriods;
// if (numberConfirmedPeriods > 0 &&
// info.confirmedPeriods[numberConfirmedPeriods - 1].period == currentPeriod) {
// return info.confirmedPeriods[numberConfirmedPeriods - 1].lockedValue;
// }
// if (numberConfirmedPeriods > 1 &&
// info.confirmedPeriods[numberConfirmedPeriods - 2].period == currentPeriod) {
// return info.confirmedPeriods[numberConfirmedPeriods - 2].lockedValue;
// }
//
// return info.lockedValue;
//
// if (newNumberConfirmedPeriods > 0 ) {
// if (info.confirmedPeriods[0].period == previousPeriod + 1) {
// info.lockedValue = info.confirmedPeriods[i].lockedValue;
// } else if (info.lockedValue != lockedValue) {
// info.lockedValue = lockedValue;
// }
// } else {
// if (calculateLockedTokens(msg.sender) == 0) {
// info.lockedValue = 0;
// } else if (info.lockedValue != lockedValue) {
// info.lockedValue = lockedValue;
// }
// }
// 1. Найти currentPeriod == period
// 2. Нет текущего, но есть предыдущий период и есть будущие периоды, то значение предыдущего
// 3. Нет текущего, но есть предыдущий период и нет будущих периодов, то расчет следующего периода (если == 0, то 0)
// 4. Есть ли есть остальыне (т.е. будущие) периоды, то текущее значение
// 5. Нет периодов, то расчет следующего периода (если == 0, то 0)
// 1. определить позицию текущего периода или меньше текущего
// 2. получаем newNumberConfirmedPeriods и lockedValue
// if (newNumberConfirmedPeriods > 0 &&
// info.confirmedPeriods[0].period == previousPeriod + 1) {
// return info.confirmedPeriods[0].lockedValue;
// } else if (newNumberConfirmedPeriods == 0 &&
// calculateLockedTokens(msg.sender) == 0) {
// return 0;
// }
// if (info.lockedValue != lockedValue) {
// return lockedValue;
// }
// return info.lockedValue;
// 1. Если есть currentPeriod, то вернуть его
// 2. Нет текущего, но есть предыдущий период и есть будущие периоды, то значение предыдущего
// 3. Нет текущего, но есть предыдущий период и нет будущих периодов, то расчет следующего периода (если == 0, то 0)
// 4. Есть ли есть остальыне (т.е. будущие) периоды, то текущее значение
// 5. Нет периодов, то расчет следующего периода (если == 0, то 0)
// no confirmed periods, so current period may be release period
if (numberConfirmedPeriods == 0) {
@ -242,42 +185,11 @@ contract Escrow is Miner, Ownable {
}
}
// checks if owner can mine more tokens (before or after release period)
if (calculateLockedTokens(_owner) == 0) {
if (calculateLockedTokens(_owner, lockedValue) == 0) {
return 0;
} else {
return lockedValue;
}
// if (newNumberConfirmedPeriods > 0 &&
// info.confirmedPeriods[0].period == previousPeriod + 1) {
// return info.confirmedPeriods[0].lockedValue;
// } else if (newNumberConfirmedPeriods == 0 &&
// calculateLockedTokens(msg.sender) == 0) {
// return 0;
// }
// if (info.lockedValue != lockedValue) {
// return lockedValue;
// }
// return info.lockedValue;
// if (newNumberConfirmedPeriods > 0 &&
// info.confirmedPeriods[0].period == previousPeriod + 1) {
// info.lockedValue = info.confirmedPeriods[i].lockedValue;
// } else if (newNumberConfirmedPeriods > 0 &&
// info.lockedValue != lockedValue) {
// info.lockedValue = lockedValue;
// } else if (newNumberConfirmedPeriods == 0 &&
// calculateLockedTokens(msg.sender) == 0) {
// info.lockedValue = 0;
// } else if (newNumberConfirmedPeriods == 0 &&
// info.lockedValue != lockedValue) {
// info.lockedValue = lockedValue;
// }
}
/**
@ -293,8 +205,9 @@ contract Escrow is Miner, Ownable {
/**
* @notice Calculate locked tokens value for owner in next period
* @param _owner Tokens owner
* @param _currentLockedToken Current locked tokens
**/
function calculateLockedTokens(address _owner)
function calculateLockedTokens(address _owner, uint256 _currentLockedToken)
public constant returns (uint256)
{
var nextPeriod = block.number.div(blocksPerPeriod) + 1;
@ -302,10 +215,51 @@ contract Escrow is Miner, Ownable {
if (info.releasePeriod <= nextPeriod) {
return 0;
} else {
return info.lockedValue;
return _currentLockedToken;
}
}
/**
* @notice Calculate locked tokens value for owner in next period
* @param _owner Tokens owner
**/
function calculateLockedTokens(address _owner)
public constant returns (uint256)
{
return calculateLockedTokens(_owner, getLockedTokens(_owner));
}
/**
* @notice Confirm activity for future period
* @param _lockedValue Locked tokens in future period
**/
function confirmActivity(uint256 _lockedValue) internal {
require(_lockedValue > 0);
var info = tokenInfo[msg.sender];
var nextPeriod = block.number.div(blocksPerPeriod) + 1;
if (info.numberConfirmedPeriods > 0 &&
info.confirmedPeriods[info.numberConfirmedPeriods - 1].period == nextPeriod) {
var confirmedPeriod = info.confirmedPeriods[info.numberConfirmedPeriods - 1];
lockedPerPeriod[nextPeriod].totalLockedValue = lockedPerPeriod[nextPeriod].totalLockedValue
.add(_lockedValue.sub(confirmedPeriod.lockedValue));
confirmedPeriod.lockedValue = _lockedValue;
return;
}
require(info.numberConfirmedPeriods < MAX_PERIODS);
lockedPerPeriod[nextPeriod].totalLockedValue =
lockedPerPeriod[nextPeriod].totalLockedValue.add(_lockedValue);
lockedPerPeriod[nextPeriod].numberOwnersToBeRewarded++;
if (info.numberConfirmedPeriods < info.confirmedPeriods.length) {
info.confirmedPeriods[info.numberConfirmedPeriods].period = nextPeriod;
info.confirmedPeriods[info.numberConfirmedPeriods].lockedValue = _lockedValue;
} else {
info.confirmedPeriods.push(ConfirmedPeriodInfo(nextPeriod, _lockedValue));
}
info.numberConfirmedPeriods++;
}
/**
* @notice Confirm activity for future period
**/
@ -318,18 +272,7 @@ contract Escrow is Miner, Ownable {
}
var lockedTokens = calculateLockedTokens(msg.sender);
require(lockedTokens > 0);
require(info.numberConfirmedPeriods < MAX_PERIODS);
lockedPerPeriod[nextPeriod].totalLockedValue += lockedTokens;
lockedPerPeriod[nextPeriod].numberOwnersToBeRewarded++;
if (info.numberConfirmedPeriods < info.confirmedPeriods.length) {
info.confirmedPeriods[info.numberConfirmedPeriods].period = nextPeriod;
info.confirmedPeriods[info.numberConfirmedPeriods].lockedValue = lockedTokens;
} else {
info.confirmedPeriods.push(ConfirmedPeriodInfo(nextPeriod, lockedTokens));
}
info.numberConfirmedPeriods++;
confirmActivity(lockedTokens);
}
/**

View File

@ -28,20 +28,6 @@ contract Miner {
miningCoefficient = _miningCoefficient;
}
// /**
// * @dev Check reward.
// * @param _lockedBlocks The amount of blocks during which tokens were locked.
// * @return Reward is empty or not
// **/
// // TODO complete
// function isEmptyReward(uint256 _lockedBlocks)
// constant returns (bool)
// {
// return token.totalSupply() == token.futureSupply() ||
// (token.futureSupply().mul(_lockedBlocks).div(miningCoefficient) -
// token.totalSupply().mul(_lockedBlocks).div(miningCoefficient)) == 0;
// }
/**
* @notice Function to mint tokens for sender
* @param _to The address that will receive the minted tokens.

View File

@ -58,7 +58,7 @@ def test_escrow(web3, chain, token, escrow):
assert 0 == escrow.call().getLockedTokens(alice)
# Ursula can't lock too low value
# TODO uncomment
# TODO uncomment after completing logic
# with pytest.raises(TransactionFailed):
# tx = escrow.transact({'from': ursula}).deposit(1000, 10)
# chain.wait.for_receipt(tx)
@ -69,7 +69,7 @@ def test_escrow(web3, chain, token, escrow):
assert 1000 == token.call().balanceOf(escrow.address)
assert 9000 == token.call().balanceOf(ursula)
assert 1000 == escrow.call().getLockedTokens(ursula)
tx = escrow.transact({'from': alice}).deposit(500, 4)
tx = escrow.transact({'from': alice}).deposit(500, 6)
chain.wait.for_receipt(tx)
assert 500 == escrow.call().getLockedTokens(alice)
assert 1500 == token.call().balanceOf(escrow.address)
@ -81,25 +81,6 @@ def test_escrow(web3, chain, token, escrow):
assert 500 == escrow.call().getLockedTokens(alice)
assert 1500 == escrow.call().getAllLockedTokens()
# # Ursula asks for refund
# tx = escrow.transact({'from': ursula}).withdraw(500)
# chain.wait.for_receipt(tx)
# # and it works
# assert token.call().balanceOf(escrow.address) == 1500
# assert token.call().balanceOf(ursula) == 9000
# # Ursula and Alice lock some tokens for 100 and 200 blocks
# tx = escrow.transact({'from': ursula}).lock(1000, 100)
# chain.wait.for_receipt(tx)
# assert escrow.call().getLockedTokens(ursula) == 1000
# assert escrow.call().getLockedTokens(alice) == 0
# assert escrow.call().getAllLockedTokens() == 1000
# tx = escrow.transact({'from': alice}).lock(500, 200)
# chain.wait.for_receipt(tx)
# assert escrow.call().getLockedTokens(ursula) == 1000
# assert escrow.call().getLockedTokens(alice) == 500
# assert escrow.call().getAllLockedTokens() == 1500
# Ursula's withdrawal attempt won't succeed
with pytest.raises(TransactionFailed):
tx = escrow.transact({'from': ursula}).withdraw(100)
@ -107,34 +88,56 @@ def test_escrow(web3, chain, token, escrow):
assert 1500 == token.call().balanceOf(escrow.address)
assert 9000 == token.call().balanceOf(ursula)
# Ursula can deposit more tokens
tx = escrow.transact({'from': alice}).confirmActivity()
chain.wait.for_receipt(tx)
tx = escrow.transact({'from': ursula}).deposit(500, 0)
chain.wait.for_receipt(tx)
assert 2000 == token.call().balanceOf(escrow.address)
assert 8500 == token.call().balanceOf(ursula)
# Wait 50 blocks and checks locking
chain.wait.for_block(web3.eth.blockNumber + 50)
assert 1500 == escrow.call().getLockedTokens(ursula)
# Wait 100 blocks
chain.wait.for_block(web3.eth.blockNumber + 100)
chain.wait.for_block(web3.eth.blockNumber + 50)
assert 0 == escrow.call().getLockedTokens(ursula)
# And Ursula can withdraw some tokens
tx = escrow.transact({'from': ursula}).withdraw(100)
chain.wait.for_receipt(tx)
assert 1400 == token.call().balanceOf(escrow.address)
assert 9100 == token.call().balanceOf(ursula)
assert 1900 == token.call().balanceOf(escrow.address)
assert 8600 == token.call().balanceOf(ursula)
# But Ursula can't withdraw all without mining for locked value
with pytest.raises(TransactionFailed):
tx = escrow.transact({'from': ursula}).withdrawAll()
chain.wait.for_receipt(tx)
# Ursula can't deposit more tokens without mining for already locked value
with pytest.raises(TransactionFailed):
tx = escrow.transact({'from': ursula}).deposit(1000, 0)
chain.wait.for_receipt(tx)
assert 1400 == token.call().balanceOf(escrow.address)
# And can't lock some of them
# TODO check logic
# with pytest.raises(TransactionFailed):
# tx = escrow.transact({'from': ursula}).lock(500, 100)
# chain.wait.for_receipt(tx)
# Ursula can deposit more tokens
tx = escrow.transact({'from': ursula}).deposit(500, 0)
chain.wait.for_receipt(tx)
assert 2400 == token.call().balanceOf(escrow.address)
# Locked tokens will be updated in next period
assert 1500 == escrow.call().getLockedTokens(ursula)
# assert 1000 == escrow.call().getLockedTokens(ursula, web3.eth.blockNumber + 50)
# assert 0 == escrow.call().getLockedTokens(ursula, web3.eth.blockNumber + 100)
chain.wait.for_block(web3.eth.blockNumber + 50)
assert 500 == escrow.call().getLockedTokens(ursula)
# And can increase lock
tx = escrow.transact({'from': ursula}).lock(500, 2)
chain.wait.for_receipt(tx)
assert 500 == escrow.call().getLockedTokens(ursula)
# assert 1500 == escrow.call().getLockedTokens(ursula, web3.eth.blockNumber + 50)
# assert 0 == escrow.call().getLockedTokens(ursula, web3.eth.blockNumber + 200)
chain.wait.for_block(web3.eth.blockNumber + 50)
assert 1000 == escrow.call().getLockedTokens(ursula)
# Alice can't deposit too low value (less then rate)
# TODO check logic
# TODO uncomment after completing logic
# with pytest.raises(TransactionFailed):
# tx = escrow.transact({'from': ursula}).deposit(100, 100)
# chain.wait.for_receipt(tx)
@ -143,10 +146,11 @@ def test_escrow(web3, chain, token, escrow):
tx = escrow.transact({'from': alice}).deposit(500, 0)
chain.wait.for_receipt(tx)
assert 500 == escrow.call().getLockedTokens(alice)
chain.wait.for_block(web3.eth.blockNumber + 50)
assert 1000 == escrow.call().getLockedTokens(alice)
# TODO complete method
# assert escrow.call().getLockedTokens(alice, web3.eth.blockNumber + 100) == 0
chain.wait.for_block(web3.eth.blockNumber + 50)
assert 1000 == escrow.call().getLockedTokens(alice)
# And increases locked blocks
tx = escrow.transact({'from': alice}).lock(0, 2)
chain.wait.for_receipt(tx)