diff --git a/nucypher/blockchain/eth/sol/source/contracts/Issuer.sol b/nucypher/blockchain/eth/sol/source/contracts/Issuer.sol index 7fd2f7a5f..11248cbda 100644 --- a/nucypher/blockchain/eth/sol/source/contracts/Issuer.sol +++ b/nucypher/blockchain/eth/sol/source/contracts/Issuer.sol @@ -6,6 +6,7 @@ import "zeppelin/math/SafeMath.sol"; import "zeppelin/math/Math.sol"; import "contracts/proxy/Upgradeable.sol"; import "contracts/lib/AdditionalMath.sol"; +import "zeppelin/token/ERC20/SafeERC20.sol"; /** @@ -13,9 +14,11 @@ import "contracts/lib/AdditionalMath.sol"; * @dev |v1.1.2| */ contract Issuer is Upgradeable { + using SafeERC20 for NuCypherToken; using SafeMath for uint256; using AdditionalMath for uint32; + event Burnt(address indexed sender, uint256 value); /// Issuer is initialized with a reserved reward event Initialized(uint256 reservedReward); @@ -97,14 +100,14 @@ contract Issuer is Upgradeable { /** * @notice Initialize reserved tokens for reward */ - function initialize() public onlyOwner { + function initialize(uint256 _reservedReward) public onlyOwner { require(currentSupply1 == 0); + token.safeTransferFrom(msg.sender, address(this), _reservedReward); currentMintingPeriod = getCurrentPeriod(); - uint256 reservedReward = token.balanceOf(address(this)); - uint256 currentTotalSupply = totalSupply - reservedReward; + uint256 currentTotalSupply = totalSupply - _reservedReward; currentSupply1 = currentTotalSupply; currentSupply2 = currentTotalSupply; - emit Initialized(reservedReward); + emit Initialized(_reservedReward); } /** @@ -169,6 +172,16 @@ contract Issuer is Upgradeable { currentSupply2 = currentSupply2 - _amount; } + /** + * @notice Burn sender's tokens. Amount of tokens will be returned for future minting + * @param _value Amount to burn + */ + function burn(uint256 _value) public { + token.safeTransferFrom(msg.sender, address(this), _value); + unMint(_value); + emit Burnt(msg.sender, _value); + } + /** * @notice Returns the number of tokens that can be mined */ diff --git a/nucypher/blockchain/eth/sol/source/contracts/StakingEscrow.sol b/nucypher/blockchain/eth/sol/source/contracts/StakingEscrow.sol index 2b51b9e72..90a1eb524 100644 --- a/nucypher/blockchain/eth/sol/source/contracts/StakingEscrow.sol +++ b/nucypher/blockchain/eth/sol/source/contracts/StakingEscrow.sol @@ -1,7 +1,6 @@ pragma solidity ^0.5.3; -import "zeppelin/token/ERC20/SafeERC20.sol"; import "contracts/Issuer.sol"; @@ -37,7 +36,6 @@ contract WorkLockInterface { * @dev |v1.4.1| */ contract StakingEscrow is Issuer { - using SafeERC20 for NuCypherToken; using AdditionalMath for uint256; using AdditionalMath for uint16; diff --git a/nucypher/blockchain/eth/sol/source/contracts/WorkLock.sol b/nucypher/blockchain/eth/sol/source/contracts/WorkLock.sol index 43e290265..9df9173e2 100644 --- a/nucypher/blockchain/eth/sol/source/contracts/WorkLock.sol +++ b/nucypher/blockchain/eth/sol/source/contracts/WorkLock.sol @@ -3,6 +3,7 @@ pragma solidity ^0.5.3; import "zeppelin/math/SafeMath.sol"; import "zeppelin/utils/Address.sol"; +import "zeppelin/token/ERC20/SafeERC20.sol"; import "contracts/NuCypherToken.sol"; import "contracts/StakingEscrow.sol"; @@ -11,12 +12,15 @@ import "contracts/StakingEscrow.sol"; * @notice The WorkLock distribution contract */ contract WorkLock { + using SafeERC20 for NuCypherToken; using SafeMath for uint256; using Address for address payable; + event Deposited(address indexed sender, uint256 value); event Bid(address indexed staker, uint256 depositedETH, uint256 claimedTokens); event Claimed(address indexed staker, uint256 claimedTokens); event Refund(address indexed staker, uint256 refundETH, uint256 completedWork); + event Burn(address indexed sender, uint256 value); struct WorkInfo { uint256 depositedETH; @@ -34,7 +38,7 @@ contract WorkLock { uint256 public refundRate; uint256 public minAllowableLockedTokens; uint256 public maxAllowableLockedTokens; - uint256 public allClaimedTokens; + uint256 public remainingTokens; uint16 public lockedPeriods; mapping(address => WorkInfo) public workInfo; @@ -76,6 +80,16 @@ contract WorkLock { lockedPeriods = _lockedPeriods; } + /** + * @notice Deposit tokens to contract + * @param _value Amount of tokens to transfer + **/ + function deposit(uint256 _value) public { + token.safeTransferFrom(msg.sender, address(this), _value); + remainingTokens += _value; + emit Deposited(msg.sender, _value); + } + /** * @notice Bid for tokens by transferring ETH */ @@ -88,9 +102,7 @@ contract WorkLock { require(claimedTokens >= minAllowableLockedTokens && claimedTokens <= maxAllowableLockedTokens, "Claimed tokens must be within the allowed limits"); newClaimedTokens = msg.value.mul(depositRate); - allClaimedTokens = allClaimedTokens.add(newClaimedTokens); - require(allClaimedTokens <= token.balanceOf(address(this)), - "Not enough tokens in the contract"); + remainingTokens = remainingTokens.sub(newClaimedTokens); emit Bid(msg.sender, msg.value, newClaimedTokens); } @@ -146,4 +158,15 @@ contract WorkLock { return remainingWork.sub(completedWork); } + /** + * @notice Burn unclaimed tokens + **/ + function burnRemaining() public { + require(block.timestamp >= endBidDate, "Burning tokens allowed when bidding is over"); + require(remainingTokens > 0, "There are no tokens that can be burned"); + token.approve(address(escrow), remainingTokens); + escrow.burn(remainingTokens); + emit Burn(msg.sender, remainingTokens); + } + }