pragma solidity ^0.4.16;
/**
* @title Ownable
* @dev The Ownable contract has an owner address, and provides basic authorization control
* functions, this simplifies the implementation of "user permissions".
*/
contract Ownable {
address public owner;
/**
* @dev The Ownable constructor sets the original `owner` of the contract to the sender
* account.
*/
function Ownable() public {
owner = msg.sender;
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
require(msg.sender == owner);
_;
}
}
/**
* @title TenTimesToken
* @dev An ERC20 token which doubles the balance each 2 million blocks.
*/
contract TenTimesToken is Ownable {
uint256 public totalSupply;
mapping(address => uint256) startBalances;
mapping(address => mapping(address => uint256)) allowed;
mapping(address => uint256) startBlocks;
string public constant name = "Ten Times";
string public constant symbol = "TENT";
uint32 public constant decimals = 10;
function TenTimesToken() public {
totalSupply = 1000000 * 10**uint256(decimals);
startBalances[owner] = totalSupply;
startBlocks[owner] = block.number;
Transfer(address(0), owner, totalSupply);
}
/**
* @dev Computes `k * (1+1/q) ^ N`, with precision `p`. The higher
* the precision, the higher the gas cost. It should be
* something around the log of `n`. When `p == n`, the
* precision is absolute (sans possible integer overflows). <edit: NOT true, see comments>
* Much smaller values are sufficient to get a great approximation.
* from https://ethereum.stackexchange.com/questions/10425/is-there-any-efficient-way-to-compute-the-exponentiation-of-a-fraction-and-an-in
*/
function fracExp(uint256 k, uint256 q, uint256 n, uint256 p) pure public returns (uint256) {
uint256 s = 0;
uint256 N = 1;
uint256 B = 1;
for (uint256 i = 0; i < p; ++i) {
s += k * N / B / (q**i);
N = N * (n-i);
B = B * (i+1);
}
return s;
}
/**
* @dev Computes the compound interest for an account since the block stored in startBlock
* about factor 10 for 2 million blocks.
*/
function compoundInterest(address tokenOwner) view public returns (uint256) {
require(startBlocks[tokenOwner] > 0);
uint256 start = startBlocks[tokenOwner];
uint256 current = block.number;
uint256 blockCount = current - start;
uint256 balance = startBalances[tokenOwner];
return fracExp(balance, 867598, blockCount, 8) - balance;
}
/**
* @dev Get the token balance for account 'tokenOwner'
*/
function balanceOf(address tokenOwner) public constant returns (uint256 balance) {
return startBalances[tokenOwner] + compoundInterest(tokenOwner);
}
/**
* @dev Add the compound interest to the startBalance, update the start block,
* and update totalSupply
*/
function updateBalance(address tokenOwner) private {
if (startBlocks[tokenOwner] == 0) {
startBlocks[tokenOwner] = block.number;
}
uint256 ci = compoundInterest(tokenOwner);
startBalances[tokenOwner] = startBalances[tokenOwner] + ci;
totalSupply = totalSupply + ci;
startBlocks[tokenOwner] = block.number;
}
/**
* @dev Transfer the balance from token owner's account to `to` account
* - Owner's account must have sufficient balance to transfer
* - 0 value transfers are allowed
*/
function transfer(address to, uint256 tokens) public returns (bool) {
updateBalance(msg.sender);
updateBalance(to);
require(tokens <= startBalances[msg.sender]);
startBalances[msg.sender] = startBalances[msg.sender] - tokens;
startBalances[to] = startBalances[to] + tokens;
Transfer(msg.sender, to, tokens);
return true;
}
/**
* @dev Transfer `tokens` from the `from` account to the `to` account
*
* The calling account must already have sufficient tokens approve(...)-d
* for spending from the `from` account and
* - From account must have sufficient balance to transfer
* - Spender must have sufficient allowance to transfer
* - 0 value transfers are allowed
*/
function transferFrom(address from, address to, uint256 tokens) public returns (bool) {
updateBalance(from);
updateBalance(to);
require(tokens <= startBalances[from]);
startBalances[from] = startBalances[from] - tokens;
allowed[from][msg.sender] = allowed[from][msg.sender] - tokens;
startBalances[to] = startBalances[to] + tokens;
Transfer(from, to, tokens);
return true;
}
/**
* @dev Allow `spender` to withdraw from your account, multiple times, up to the 'tokens' amount.
* If this function is called again it overwrites the current allowance with 'tokens'.
*/
function approve(address spender, uint256 tokens) public returns (bool) {
allowed[msg.sender][spender] = tokens;
Approval(msg.sender, spender, tokens);
return true;
}
function allowance(address tokenOwner, address spender) public constant returns (uint256 remaining) {
return allowed[tokenOwner][spender];
}
event Transfer(address indexed from, address indexed to, uint256 tokens);
event Approval(address indexed owner, address indexed spender, uint256 tokens);
}
{
"compilationTarget": {
"TenTimesToken.sol": "TenTimesToken"
},
"libraries": {},
"optimizer": {
"enabled": false,
"runs": 200
},
"remappings": []
}
[{"constant":true,"inputs":[],"name":"name","outputs":[{"name":"","type":"string"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"spender","type":"address"},{"name":"tokens","type":"uint256"}],"name":"approve","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"totalSupply","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"from","type":"address"},{"name":"to","type":"address"},{"name":"tokens","type":"uint256"}],"name":"transferFrom","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"decimals","outputs":[{"name":"","type":"uint32"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"tokenOwner","type":"address"}],"name":"balanceOf","outputs":[{"name":"balance","type":"uint256"}],"payable":false,"stateMutability":"view","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":false,"inputs":[{"name":"to","type":"address"},{"name":"tokens","type":"uint256"}],"name":"transfer","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"tokenOwner","type":"address"}],"name":"compoundInterest","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"k","type":"uint256"},{"name":"q","type":"uint256"},{"name":"n","type":"uint256"},{"name":"p","type":"uint256"}],"name":"fracExp","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[{"name":"tokenOwner","type":"address"},{"name":"spender","type":"address"}],"name":"allowance","outputs":[{"name":"remaining","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"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"},{"anonymous":false,"inputs":[{"indexed":true,"name":"owner","type":"address"},{"indexed":true,"name":"spender","type":"address"},{"indexed":false,"name":"tokens","type":"uint256"}],"name":"Approval","type":"event"}]