pragma solidity ^0.4.19;
/**
* EIP-20 standard token interface, as defined at
* ttps://github.com/ethereum/EIPs/blob/master/EIPS/eip-20-token-standard.md
*/
contract Token {
function name() public constant returns (string);
function symbol() public constant returns (string);
function decimals() public constant returns (uint8);
function totalSupply() public constant returns (uint256);
function balanceOf(address _owner) public constant returns (uint256);
function transfer(address _to, uint256 _value) public returns (bool);
function transferFrom(address _from, address _to, uint256 _value)
public returns (bool);
function approve(address _spender, uint256 _value) public returns (bool);
function allowance(address _owner, address _spender)
public constant returns (uint256);
event Transfer(address indexed _from, address indexed _to, uint256 _value);
event Approval(
address indexed _owner, address indexed _spender, uint256 _value);
}
/**
* Allows one to lock EIP-20 tokens until certain time arrives.
* Copyright © 2018 by ABDK Consulting https://abdk.consulting/
* Author: Mikhail Vladimirov <mikhail.vladimirov[at]gmail.com>
*/
contract TokenTimeLock {
/**
* Create new Token Time Lock with given donation address.
*
* @param _donationAddress donation address
*/
function TokenTimeLock (address _donationAddress) public {
donationAddress = _donationAddress;
}
/**
* Lock given amount of given EIP-20 tokens until given time arrives, after
* this time allow the tokens to be transferred to given beneficiary. This
* contract should be allowed to transfer at least given amount of tokens
* from msg.sender.
*
* @param _token EIP-20 token contract managing tokens to be locked
* @param _beneficiary beneficiary to receive tokens after unlock time
* @param _amount amount of tokens to be locked
* @param _unlockTime unlock time
*
* @return time lock ID
*/
function lock (
Token _token, address _beneficiary, uint256 _amount,
uint256 _unlockTime) public returns (uint256) {
require (_amount > 0);
uint256 id = nextLockID++;
TokenTimeLockInfo storage lockInfo = locks [id];
lockInfo.token = _token;
lockInfo.beneficiary = _beneficiary;
lockInfo.amount = _amount;
lockInfo.unlockTime = _unlockTime;
Lock (id, _token, _beneficiary, _amount, _unlockTime);
require (_token.transferFrom (msg.sender, this, _amount));
return id;
}
/**
* Unlock tokens locked under time lock with given ID and transfer them to
* corresponding beneficiary.
*
* @param _id time lock ID to unlock tokens locked under
*/
function unlock (uint256 _id) public {
TokenTimeLockInfo memory lockInfo = locks [_id];
delete locks [_id];
require (lockInfo.amount > 0);
require (lockInfo.unlockTime <= block.timestamp);
Unlock (_id);
require (
lockInfo.token.transfer (
lockInfo.beneficiary, lockInfo.amount));
}
/**
* If you like this contract, you may send some ether to this address and
* it will be used to develop more useful contracts available to everyone.
*/
address public donationAddress;
/**
* Next time lock ID to be used.
*/
uint256 private nextLockID = 0;
/**
* Maps time lock ID to TokenTimeLockInfo structure encapsulating time lock
* information.
*/
mapping (uint256 => TokenTimeLockInfo) public locks;
/**
* Encapsulates information abount time lock.
*/
struct TokenTimeLockInfo {
/**
* EIP-20 token contract managing locked tokens.
*/
Token token;
/**
* Beneficiary to receive tokens once they are unlocked.
*/
address beneficiary;
/**
* Amount of locked tokens.
*/
uint256 amount;
/**
* Unlock time.
*/
uint256 unlockTime;
}
/**
* Logged when tokens were time locked.
*
* @param id time lock ID
* @param token EIP-20 token contract managing locked tokens
* @param beneficiary beneficiary to receive tokens once they are unlocked
* @param amount amount of locked tokens
* @param unlockTime unlock time
*/
event Lock (
uint256 indexed id, Token indexed token, address indexed beneficiary,
uint256 amount, uint256 unlockTime);
/**
* Logged when tokens were unlocked and sent to beneficiary.
*
* @param id time lock ID
*/
event Unlock (uint256 indexed id);
}
{
"compilationTarget": {
"TokenTimeLock.sol": "TokenTimeLock"
},
"libraries": {},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"constant":false,"inputs":[{"name":"_token","type":"address"},{"name":"_beneficiary","type":"address"},{"name":"_amount","type":"uint256"},{"name":"_unlockTime","type":"uint256"}],"name":"lock","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_id","type":"uint256"}],"name":"unlock","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"donationAddress","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"","type":"uint256"}],"name":"locks","outputs":[{"name":"token","type":"address"},{"name":"beneficiary","type":"address"},{"name":"amount","type":"uint256"},{"name":"unlockTime","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"_donationAddress","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"id","type":"uint256"},{"indexed":true,"name":"token","type":"address"},{"indexed":true,"name":"beneficiary","type":"address"},{"indexed":false,"name":"amount","type":"uint256"},{"indexed":false,"name":"unlockTime","type":"uint256"}],"name":"Lock","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"id","type":"uint256"}],"name":"Unlock","type":"event"}]