Skip to content

Commit

Permalink
Fix bugs from bounty (#29)
Browse files Browse the repository at this point in the history
  • Loading branch information
robsecord authored Feb 11, 2021
1 parent 70445b8 commit f4fb60e
Show file tree
Hide file tree
Showing 6 changed files with 136 additions and 28 deletions.
3 changes: 2 additions & 1 deletion Error Codes.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ Codes:
E-100 - [--Unused--]
E-101 - PAUSED
E-102 - NOT_OWNER, transfer of token that is not own
E-103 - NOT_OWNER_OR_ADMIN
E-103 - NOT_OWNER_OR_ADMIN, NOT FUNDER
E-104 - NOT_TOKEN_CREATOR, NOT_CREATOR
E-105 - INVALID_OPERATOR, NOT_TOKEN_OPERATOR, NOT_OWNER_OR_OPERATOR, transfer caller is not owner nor approved, approve caller is not owner nor approved for all
E-106 - CANNOT_BE_SELF
Expand Down Expand Up @@ -87,3 +87,4 @@ Codes:
E-428 - token type not found
E-429 - minting restricted to limited amount
E-430 - only 1 lepton per NFT allowed
E-431 - portion already claimed
3 changes: 2 additions & 1 deletion contracts/interfaces/IIonTimelock.sol
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,8 @@ interface IIonTimelock {
function addPortions(uint256[] memory amounts, uint256[] memory releaseTimes) external returns (bool);
function nextReleaseTime() external view returns (uint256 releaseTime);
function nextReleaseAmount() external view returns (uint256 releaseAmount);
function release() external returns (uint256 amount);
function release(uint256 numPortions, uint256 indexOffset) external returns (uint256 amount);
function releasePortion(uint256 portionIndex) external returns (uint256 amount);

event PortionsAdded(uint256[] amounts, uint256[] releaseTimes);
event PortionReleased(uint256 amounts, uint256 releaseTime);
Expand Down
68 changes: 61 additions & 7 deletions contracts/tokens/IonTimelock.sol
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ contract IonTimelock is IIonTimelock {
using SafeERC20 for IERC20;

IERC20 public token;
address public funder;
address public receiver;
Portion[] public portions;

Expand All @@ -41,11 +42,13 @@ contract IonTimelock is IIonTimelock {
| Initialization |
|__________________________________*/

constructor (address _receiver, address _token) public {
constructor (address _funder, address _receiver, address _token) public {
require(_funder != address(0x0), "IonTimelock:E-403");
require(_receiver != address(0x0), "IonTimelock:E-403");
require(_token != address(0x0), "IonTimelock:E-403");

token = IERC20(_token);
funder = _funder;
receiver = _receiver;
}

Expand All @@ -54,7 +57,13 @@ contract IonTimelock is IIonTimelock {
| Public |
|__________________________________*/

function addPortions(uint256[] memory amounts, uint256[] memory releaseTimes) public override returns (bool) {
function addPortions(uint256[] memory amounts, uint256[] memory releaseTimes)
external
virtual
override
returns (bool)
{
require(msg.sender == funder, "IonTimelock:E-103");
require(amounts.length == releaseTimes.length, "IonTimelock:E-202");

uint256 totalAmount;
Expand Down Expand Up @@ -84,7 +93,13 @@ contract IonTimelock is IIonTimelock {
/**
* @return releaseTime The time when the next portion of tokens will be released.
*/
function nextReleaseTime() public view override returns (uint256 releaseTime) {
function nextReleaseTime()
external
view
virtual
override
returns (uint256 releaseTime)
{
uint256 portionCount = portions.length;
for (uint i = 0; i < portionCount; i++) {
// solhint-disable-next-line not-rely-on-time
Expand All @@ -98,7 +113,13 @@ contract IonTimelock is IIonTimelock {
/**
* @return releaseAmount The next amount that will be released.
*/
function nextReleaseAmount() public view override returns (uint256 releaseAmount) {
function nextReleaseAmount()
external
view
virtual
override
returns (uint256 releaseAmount)
{
uint256 portionCount = portions.length;
for (uint i = 0; i < portionCount; i++) {
// solhint-disable-next-line not-rely-on-time
Expand All @@ -112,9 +133,16 @@ contract IonTimelock is IIonTimelock {
/**
* @notice Transfers tokens held by timelock to the receiver.
*/
function release() public override returns (uint256 amount) {
uint256 portionCount = portions.length;
for (uint i = 0; i < portionCount; i++) {
function release(uint256 numPortions, uint256 indexOffset)
external
virtual
override
returns (uint256 amount)
{
require(numPortions <= portions.length, "IonTimelock:E-201");

uint256 portionCount = numPortions > 0 ? numPortions : portions.length;
for (uint i = indexOffset; i < portionCount; i++) {
// solhint-disable-next-line not-rely-on-time
if (!portions[i].claimed && portions[i].releaseTime <= block.timestamp) {
amount = amount.add(portions[i].amount);
Expand All @@ -128,4 +156,30 @@ contract IonTimelock is IIonTimelock {
require(amount <= amountAvailable, "IonTimelock:E-411");
token.safeTransfer(receiver, amount);
}

/**
* @notice Transfers tokens held by timelock to the receiver.
*/
function releasePortion(uint256 portionIndex)
external
virtual
override
returns (uint256 amount)
{
require(portionIndex >= 0 && portionIndex < portions.length, "IonTimelock:E-201");

Portion memory _portion = portions[portionIndex];
require(!_portion.claimed, "IonTimelock:E-431");
// solhint-disable-next-line not-rely-on-time
require(_portion.releaseTime <= block.timestamp, "IonTimelock:E-302");

amount = _portion.amount;
portions[portionIndex].claimed = true;

uint256 amountAvailable = token.balanceOf(address(this));
require(amount <= amountAvailable, "IonTimelock:E-411");
token.safeTransfer(receiver, amount);

emit PortionReleased(_portion.amount, _portion.releaseTime);
}
}
Loading

0 comments on commit f4fb60e

Please sign in to comment.