mirror of https://github.com/nucypher/nucypher.git
[KMS-ETH]- Fixed increasing lock
parent
41906af98a
commit
fb116beef0
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue