Skip to content

Instantly share code, notes, and snippets.

@goastoman
Last active June 22, 2018 12:22
Show Gist options
  • Save goastoman/3993b9aad652bc354d885638639dfedc to your computer and use it in GitHub Desktop.
Save goastoman/3993b9aad652bc354d885638639dfedc to your computer and use it in GitHub Desktop.
MultipleTokenTimelock.sol
pragma solidity 0.4.24;
import "openzeppelin-solidity/contracts/token/ERC20/ERC20.sol";
import "openzeppelin-solidity/contracts/token/ERC20/SafeERC20.sol";
contract MultipleTokenTimelock {
// SafeERC20 contains safe methods which throw instead of returning false.
using SafeERC20 for ERC20;
ERC20 public token;
event Locked(address beneficiary, uint256 amount, uint256 releaseTime);
event Released(address beneficiary, uint256 amount, uint256 releaseTime);
struct Lock {
uint256 amount; // amount which is locked (or was locked)
uint256 releaseTime; // when lock expires
}
mapping(address => Lock[]) public locks;
constructor(address _token) public {
token = ERC20(_token);
}
/**
* @dev transfer tokens for a specified address locking the amount until release time.
* @param _to The address to transfer to.
* @param _amount The amount to be transferred.
* @param _releaseTime When lock expires.
*/
function transferWithLock(address _to, uint256 _amount, uint256 _releaseTime) public returns (bool success) {
if (_amount > 0) {
Lock memory newLock = Lock(_amount, _releaseTime);
locks[_to].push(newLock);
token.safeTransferFrom(msg.sender, address(this), _amount);
emit Locked(_to, _amount, _releaseTime);
success = true;
}
}
/**
* @dev transfer tokens for specified addresses locking the specified amounts until release time.
* @param _addrs The addresses to transfer to.
* @param _amounts The corresponding amounts to be transferred.
* @param _releaseTime When locks expire.
*/
function batchTransferWithLock(address[] _addrs, uint256[] _amounts, uint256 _releaseTime) public {
require(_addrs.length == _amounts.length);
for (uint256 i = 0; i < _addrs.length; i++) {
// Intentionally ignoring the result of transferWithLock.
transferWithLock(_addrs[i], _amounts[i], _releaseTime);
}
}
/**
* @dev releases lock by index with past releaseTime for a beneficiary.
* Can be used to prevent DoS if releaseAllLocks fails due to out-of-gas when there are too many locks
* or fails for any other reason.
* Anyone can call this method.
* @param _beneficiary For whom the tokens will be released.
* @param _lockIndex Lock index.
*/
function releaseLockByIndex(address _beneficiary, uint256 _lockIndex) public returns (bool success) {
Lock storage lock = locks[_beneficiary][_lockIndex];
uint256 amount = lock.amount;
uint256 releaseTime = lock.releaseTime;
if (amount > 0 && now >= releaseTime) {
// clearing this lock to prevent double spend and get gas refund
lock.amount = 0;
lock.releaseTime = 0;
// Token contract is trusted as it is controlled by the owner,
// no need to worry about the re-entrancy attack.
token.safeTransfer(_beneficiary, amount);
emit Released(_beneficiary, amount, releaseTime);
success = true;
}
}
/**
* @dev releases all locks with past releaseTime for a beneficiary
* Anyone can call this method.
* @param _beneficiary For whom the tokens will be released.
*/
function releaseAllLocks(address _beneficiary) public {
for (uint256 i = 0; i < locks[_beneficiary].length; i++) {
// Intentionally ignoring the result of releaseLockByIndex.
releaseLockByIndex(_beneficiary, i);
}
}
/**
* @dev Returns the number of locks for the specified beneficiary.
* @param _beneficiary Beneficiary of the locks
*/
function lockCount(address _beneficiary) public view returns (uint256) {
return locks[_beneficiary].length;
}
}
pragma solidity 0.4.24;
import "openzeppelin-solidity/contracts/token/ERC20/DetailedERC20.sol";
import "openzeppelin-solidity/contracts/token/ERC20/BurnableToken.sol";
/**
* @title Token
*/
contract Token is BurnableToken, DetailedERC20 {
/**
* @dev Constructor that gives msg.sender all of existing tokens.
*/
constructor(
string _name,
string _symbol,
uint8 _decimals,
uint256 _initialSupply
) DetailedERC20(_name, _symbol, _decimals) public
{
totalSupply_ = _initialSupply;
balances[msg.sender] = _initialSupply;
emit Transfer(0x0, msg.sender, _initialSupply);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment