Allow to withdraw excess NU from PreallocationEscrow if there's enough stake

pull/1480/head
David Núñez 2019-11-16 14:43:06 +01:00
parent dfc5b987b2
commit 91e73b1410
3 changed files with 27 additions and 4 deletions

View File

@ -94,7 +94,7 @@ contract PolicyManager is Upgradeable {
* @param _escrow Escrow contract
**/
constructor(StakingEscrow _escrow) public {
// if the input address is not the StakingEscrow than calling `secondsPerPeriod` will throw error
// if the input address is not the StakingEscrow then calling `secondsPerPeriod` will throw error
secondsPerPeriod = _escrow.secondsPerPeriod();
require(secondsPerPeriod > 0);
escrow = _escrow;

View File

@ -279,6 +279,7 @@ contract StakingEscrow is Issuer {
/**
* @notice Get the value of locked tokens for a staker in a future period
* @dev This function is used by PreallocationEscrow so its signature can't be updated.
* @param _staker Staker
* @param _periods Amount of periods that will be added to the current period
**/

View File

@ -8,6 +8,13 @@ import "zeppelin/utils/Address.sol";
import "contracts/NuCypherToken.sol";
import "contracts/staking_contracts/AbstractStakingContract.sol";
/**
* @notice StakingEscrow interface
**/
contract StakingEscrowInterface {
function getLockedTokens(address _staker, uint16 _periods) public view returns (uint256);
function secondsPerPeriod() public view returns (uint32);
}
/**
* @notice Contract holds tokens for vesting.
@ -25,15 +32,19 @@ contract PreallocationEscrow is AbstractStakingContract, Ownable {
NuCypherToken public token;
uint256 public lockedValue;
uint256 public endLockTimestamp;
StakingEscrowInterface public stakingEscrow;
/**
* @param _router Interface router contract address
* @param _token Token contract
**/
constructor(StakingInterfaceRouter _router, NuCypherToken _token) public AbstractStakingContract(_router) {
// check that the input address is contract
constructor(StakingInterfaceRouter _router, NuCypherToken _token, StakingEscrowInterface _stakingEscrow) public AbstractStakingContract(_router) {
// check that the input addresses are contract
require(_token.totalSupply() > 0);
require(_stakingEscrow.secondsPerPeriod() > 0);
token = _token;
stakingEscrow = _stakingEscrow;
}
/**
@ -64,7 +75,18 @@ contract PreallocationEscrow is AbstractStakingContract, Ownable {
* @param _value Amount of token to withdraw
**/
function withdrawTokens(uint256 _value) public onlyOwner {
require(token.balanceOf(address(this)).sub(getLockedTokens()) >= _value);
uint256 balance = token.balanceOf(address(this));
uint32 secondsPerPeriod = stakingEscrow.secondsPerPeriod();
uint16 currentPeriod = uint16(block.timestamp / secondsPerPeriod);
uint16 endLockPeriod = uint16(endLockTimestamp / secondsPerPeriod);
if (currentPeriod <= endLockPeriod) {
uint256 stakedTokens = stakingEscrow.getLockedTokens(address(this), endLockPeriod - currentPeriod);
uint256 lockedTokens = getLockedTokens();
if (lockedTokens > stakedTokens) {
balance = balance.sub(lockedTokens - stakedTokens);
}
}
require(balance >= _value);
token.safeTransfer(msg.sender, _value);
emit TokensWithdrawn(msg.sender, _value);
}