pragma solidity ^0.4.22;
// ----------------------------------------------------------------------------
// ERC Token Standard #20 Interface
// https://github.com/ethereum/EIPs/blob/master/EIPS/eip-20-token-standard.md
// ----------------------------------------------------------------------------
contract ERC20Interface {
function balanceOf(address tokenOwner) public constant returns (uint balance);
function allowance(address _owner, address _spender) public constant returns (uint remaining);
function transfer(address to, uint tokens) public returns (bool success);
function approve(address spender, uint tokens) public returns (bool success);
function transferFrom(address from, address to, uint256 _value) public returns (bool);
event Approval(address indexed tokenOwner, address indexed spender, uint tokens);
}
// ----------------------------------------------------------------------------
// ERC Token Standard #223 Interface
// https://github.com/Dexaran/ERC223-token-standard/token/ERC223/ERC223_interface.sol
// ----------------------------------------------------------------------------
contract ERC223Interface {
uint public totalSupply;
function transfer(address to, uint value, bytes data) public returns (bool success);
event Transfer(address indexed from, address indexed to, uint value, bytes data);
}
/**
* @title Owned
* @dev To verify ownership
*/
contract owned {
address public owner;
function owned() public {
owner = msg.sender;
}
modifier onlyOwner {
require(msg.sender == owner);
_;
}
}
/**
* As part of the ERC223 standard we need to call the fallback of the token
*/
contract ContractReceiver {
struct TKN {
address sender;
uint value;
bytes data;
bytes4 sig;
}
function tokenFallback(address _from, uint _value, bytes _data) public pure {
TKN memory tkn;
tkn.sender = _from;
tkn.value = _value;
tkn.data = _data;
uint32 u = uint32(_data[3]) + (uint32(_data[2]) << 8) + (uint32(_data[1]) << 16) + (uint32(_data[0]) << 24);
tkn.sig = bytes4(u);
/* tkn variable is analogue of msg variable of Ether transaction
* tkn.sender is person who initiated this token transaction (analogue of msg.sender)
* tkn.value the number of tokens that were sent (analogue of msg.value)
* tkn.data is data of token transaction (analogue of msg.data)
* tkn.sig is 4 bytes signature of function
* if data of token transaction is a function execution
*/
}
}
/**
* @title SafeMath
* @dev Math operations with safety checks that throw on error
*/
library SafeMath {
function mul(uint a, uint b) internal pure returns (uint) {
uint c = a * b;
assert(a == 0 || c / a == b);
return c;
}
function div(uint a, uint b) internal pure returns (uint) {
// assert(b > 0); // Solidity automatically throws when dividing by 0
uint c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
return c;
}
function sub(uint a, uint b) internal pure returns (uint) {
assert(b <= a);
return a - b;
}
function add(uint a, uint b) internal pure returns (uint) {
uint c = a + b;
assert(c >= a);
return c;
}
}
contract TimeVaultInterface is ERC20Interface, ERC223Interface {
function timeVault(address who) public constant returns (uint);
function getNow() public constant returns (uint);
function transferByOwner(address to, uint _value, uint timevault) public returns (bool);
}
/**
* All meta information for the Token must be defined here so that it can be accessed from both sides of proxy
*/
contract ELTTokenType {
uint public decimals;
uint public totalSupply;
mapping(address => uint) balances;
mapping(address => uint) timevault;
mapping(address => mapping(address => uint)) allowed;
// Token release switch
bool public released;
// The date before the release must be finalized (a unix timestamp)
uint public globalTimeVault;
event Transfer(address indexed from, address indexed to, uint tokens);
}
contract ERC20Token is ERC20Interface, ERC223Interface, ELTTokenType {
using SafeMath for uint;
function transfer(address _to, uint _value) public returns (bool success) {
bytes memory empty;
return transfer(_to, _value, empty);
}
// Function that is called when a user or another contract wants to transfer funds .
function transfer(address _to, uint _value, bytes _data) public returns (bool success) {
if (isContract(_to)) {
return transferToContract(_to, _value, _data, false);
}
else {
return transferToAddress(_to, _value, _data, false);
}
}
/**
* @dev Approve the passed address to spend the specified amount of tokens on behalf of msg.sender.
*
*/
function approve(address _spender, uint _value) public returns (bool) {
allowed[msg.sender][_spender] = _value;
emit Approval(msg.sender, _spender, _value);
return true;
}
/**
* @dev Function to check the amount of tokens that an owner allowed to a spender.
* @param _owner address The address which owns the funds.
* @param _spender address The address which will spend the funds.
* @return A uint specifying the amount of tokens still available for the spender.
*/
function allowance(address _owner, address _spender) public constant returns (uint remaining) {
return allowed[_owner][_spender];
}
/**
* @dev Gets the balance of the specified address.
* @param _owner The address to query the the balance of.
* @return An uint representing the amount owned by the passed address.
*/
function balanceOf(address _owner) public constant returns (uint balance) {
return balances[_owner];
}
function isContract(address _addr) private view returns (bool is_contract) {
uint length;
assembly
{
//retrieve the size of the code on target address, this needs assembly
length := extcodesize(_addr)
}
return (length > 0);
}
//function that is called when transaction target is an address
function transferToAddress(address _to, uint _value, bytes _data, bool withAllowance) private returns (bool success) {
transferIfRequirementsMet(msg.sender, _to, _value, withAllowance);
emit Transfer(msg.sender, _to, _value, _data);
return true;
}
//function that is called when transaction target is a contract
function transferToContract(address _to, uint _value, bytes _data, bool withAllowance) private returns (bool success) {
transferIfRequirementsMet(msg.sender, _to, _value, withAllowance);
ContractReceiver receiver = ContractReceiver(_to);
receiver.tokenFallback(msg.sender, _value, _data);
emit Transfer(msg.sender, _to, _value, _data);
return true;
}
// Function to verify that all the requirements to transfer are satisfied
// The destination is not the null address
// The tokens have been released for sale
// The sender's tokens are not locked in a timevault
function checkTransferRequirements(address _to, uint _value) private view {
require(_to != address(0));
require(released == true);
require(now > globalTimeVault);
if (timevault[msg.sender] != 0)
{
require(now > timevault[msg.sender]);
}
require(balanceOf(msg.sender) >= _value);
}
// Do the transfer if the requirements are met
function transferIfRequirementsMet(address _from, address _to, uint _value, bool withAllowances) private {
checkTransferRequirements(_to, _value);
if ( withAllowances)
{
require (_value <= allowed[_from][msg.sender]);
}
balances[_from] = balances[msg.sender].sub(_value);
balances[_to] = balances[_to].add(_value);
}
// Transfer from one address to another taking into account ERC223 condition to verify that the to address is a contract or not
function transferFrom(address from, address to, uint value) public returns (bool) {
bytes memory empty;
if (isContract(to)) {
return transferToContract(to, value, empty, true);
}
else {
return transferToAddress(to, value, empty, true);
}
allowed[from][msg.sender] = allowed[from][msg.sender].sub(value);
return true;
}
}
contract TimeVaultToken is owned, TimeVaultInterface, ERC20Token {
function transferByOwner(address to, uint value, uint earliestReTransferTime) onlyOwner public returns (bool) {
transfer(to, value);
timevault[to] = earliestReTransferTime;
return true;
}
function timeVault(address owner) public constant returns (uint earliestTransferTime) {
return timevault[owner];
}
function getNow() public constant returns (uint blockchainTimeNow) {
return now;
}
}
contract StandardToken is TimeVaultToken {
/**
* approve should be called when allowed[_spender] == 0. To increment
* allowed value is better to use this function to avoid 2 calls (and wait until
* the first transaction is mined)
* From MonolithDAO Token.sol
*/
function increaseApproval(address _spender, uint _addedValue) public returns (bool success) {
allowed[msg.sender][_spender] = allowed[msg.sender][_spender].add(_addedValue);
emit Approval(msg.sender, _spender, allowed[msg.sender][_spender]);
return true;
}
function decreaseApproval(address _spender, uint _subtractedValue) public returns (bool success) {
uint oldValue = allowed[msg.sender][_spender];
if (_subtractedValue > oldValue) {
allowed[msg.sender][_spender] = 0;
} else {
allowed[msg.sender][_spender] = oldValue.sub(_subtractedValue);
}
emit Approval(msg.sender, _spender, allowed[msg.sender][_spender]);
return true;
}
}
contract StandardTokenExt is StandardToken {
/* Interface declaration */
function isToken() public pure returns (bool weAre) {
return true;
}
}
contract OwnershipTransferrable is TimeVaultToken {
event OwnershipTransferred(address indexed _from, address indexed _to);
function transferOwnership(address newOwner) onlyOwner public {
transferByOwner(newOwner, balanceOf(newOwner), 0);
owner = newOwner;
emit OwnershipTransferred(msg.sender, newOwner);
}
}
contract VersionedToken is owned {
address public upgradableContractAddress;
/**
* Constructor:
* initialVersion - the address of the initial version of the implementation for the contract
*
* Note that this implementation must be visible to the relay contact even though it will not be a subclass
* do this by importing the main contract that implements it. If the code is not visible it will not
* always be accessible through the delegatecall() function. And even if it is, it will take an unlimited amount
* of gas to process the call.
*
* In our case this it is ELTTokenImpl.sol
* e.g.
* import "ELTToken.sol"
*
* Please note: IMPORTANT
* do not implement any function called "update()" otherwise it will break the Versioning system
*/
function VersionedToken(address initialImplementation) public {
upgradableContractAddress = initialImplementation;
}
/**
* update
* Call to upgrade the implementation version of this constract
* newVersion: this is the address of the new implementation for the contract
*/
function upgradeToken(address newImplementation) onlyOwner public {
upgradableContractAddress = newImplementation;
}
/**
* This is the fallback function that is called whenever a contract is called but can't find the called function.
* In this case we delegate the call to the implementing contract ELTTokenImpl
*
* Instead of using delegatecall() in Solidity we use the assembly because it allows us to return values to the caller
*/
function() public {
address upgradableContractMem = upgradableContractAddress;
bytes memory functionCall = msg.data;
assembly {
// Load the first 32 bytes of the functionCall bytes array which represents the size of the bytes array
let functionCallSize := mload(functionCall)
// Calculate functionCallDataAddress which starts at the second 32 byte block in the functionCall bytes array
let functionCallDataAddress := add(functionCall, 0x20)
// delegatecall(gasAllowed, callAddress, inMemAddress, inSizeBytes, outMemAddress, outSizeBytes) returns/pushes to stack (1 on success, 0 on failure)
let functionCallResult := delegatecall(gas, upgradableContractMem, functionCallDataAddress, functionCallSize, 0, 0)
let freeMemAddress := mload(0x40)
switch functionCallResult
case 0 {
// revert(fromMemAddress, sizeInBytes) ends execution and returns value
revert(freeMemAddress, 0)
}
default {
// returndatacopy(toMemAddress, fromMemAddress, sizeInBytes)
returndatacopy(freeMemAddress, 0x0, returndatasize)
// return(fromMemAddress, sizeInBytes)
return (freeMemAddress, returndatasize)
}
}
}
}
contract ELTToken is VersionedToken, ELTTokenType {
string public name;
string public symbol;
function ELTToken(address _tokenOwner, string _tokenName, string _tokenSymbol, uint _totalSupply, uint _decimals, uint _globalTimeVaultOpeningTime, address _initialImplementation) VersionedToken(_initialImplementation) public {
name = _tokenName;
symbol = _tokenSymbol;
decimals = _decimals;
totalSupply = _totalSupply * 10 ** uint(decimals);
// Allocate initial balance to the owner
balances[_tokenOwner] = totalSupply;
emit Transfer(address(0), owner, totalSupply);
globalTimeVault = _globalTimeVaultOpeningTime;
released = false;
}
}
contract ELTTokenImpl is StandardTokenExt {
/** Name and symbol were updated. */
event UpdatedTokenInformation(string newName, string newSymbol);
string public name;
string public symbol;
bool private adminReturnStatus ;
/**
* One way function to perform the final token release.
*/
function releaseTokenTransfer(bool _value) onlyOwner public {
released = _value;
}
function setGlobalTimeVault(uint _globalTimeVaultOpeningTime) onlyOwner public {
globalTimeVault = _globalTimeVaultOpeningTime;
}
function admin(string functionName, string p1, string p2, string p3) onlyOwner public returns (bool result) {
// Use parameters to remove warning
adminReturnStatus = (bytes(functionName).length + bytes(p1).length + bytes(p2).length + bytes(p3).length) != 0;
return adminReturnStatus ;
}
/**
* Owner can update token information here.
*
* It is often useful to conceal the actual token association, until
* the token operations, like central issuance or reissuance have been completed.
* In this case the initial token can be supplied with empty name and symbol information.
*
* This function allows the token owner to rename the token after the operations
* have been completed and then point the audience to use the token contract.
*/
function setTokenInformation(string _tokenName, string _tokenSymbol) onlyOwner public {
name = _tokenName;
symbol = _tokenSymbol;
emit UpdatedTokenInformation(name, symbol);
}
}
{
"compilationTarget": {
"ELTToken.sol": "ELTToken"
},
"evmVersion": "byzantium",
"libraries": {},
"optimizer": {
"enabled": false,
"runs": 0
},
"remappings": []
}
[{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"globalTimeVault","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"newImplementation","type":"address"}],"name":"upgradeToken","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"owner","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"symbol","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"released","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"upgradableContractAddress","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"_tokenOwner","type":"address"},{"name":"_tokenName","type":"string"},{"name":"_tokenSymbol","type":"string"},{"name":"_totalSupply","type":"uint256"},{"name":"_decimals","type":"uint256"},{"name":"_globalTimeVaultOpeningTime","type":"uint256"},{"name":"_initialImplementation","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"payable":false,"stateMutability":"nonpayable","type":"fallback"},{"anonymous":false,"inputs":[{"indexed":true,"name":"from","type":"address"},{"indexed":true,"name":"to","type":"address"},{"indexed":false,"name":"tokens","type":"uint256"}],"name":"Transfer","type":"event"}]