Transaction Hash:
Block:
6843094 at Dec-07-2018 02:26:40 PM +UTC
Transaction Fee:
0.0010751419 ETH
$2.25
Gas Used:
250,033 Gas / 4.3 Gwei
Emitted Events:
Account State Difference:
| Address | Before | After | State Difference | ||
|---|---|---|---|---|---|
| 0x1a80BDC2...e1b251886 |
2.3062748247169083 Eth
Nonce: 19117
|
2.3051996828169083 Eth
Nonce: 19118
| 0.0010751419 | ||
| 0x27695E09...4c39e9eb9 | |||||
|
0xEA674fdD...16B898ec8
Miner
| (Ethermine) | 916.692727871384735431 Eth | 916.693803013284735431 Eth | 0.0010751419 |
Execution Trace
CSToken.calculateDividends( limit=10 )
calculateDividends[CSToken (ln:213)]
safeAdd[CSToken (ln:217)]_addDividendsForAddress[CSToken (ln:224)]safeAdd[CSToken (ln:245)]Transfer[CSToken (ln:246)]Issuance[CSToken (ln:247)]safeAdd[CSToken (ln:248)]safeAdd[CSToken (ln:251)]safeAdd[CSToken (ln:253)]
pragma solidity ^0.4.2;
contract owned {
address public owner;
function owned() {
owner = msg.sender;
}
function changeOwner(address newOwner) onlyOwner {
owner = newOwner;
}
modifier onlyOwner {
require(msg.sender == owner);
_;
}
}
contract tokenRecipient {function receiveApproval(address _from, uint256 _value, address _token, bytes _extraData);}
contract Utils {
/**
constructor
*/
function Utils() {
}
// validates an address - currently only checks that it isn't null
modifier validAddress(address _address) {
require(_address != 0x0);
_;
}
// verifies that the address is different than this contract address
modifier notThis(address _address) {
require(_address != address(this));
_;
}
// Overflow protected math functions
/**
@dev returns the sum of _x and _y, asserts if the calculation overflows
@param _x value 1
@param _y value 2
@return sum
*/
function safeAdd(uint256 _x, uint256 _y) internal returns (uint256) {
uint256 z = _x + _y;
assert(z >= _x);
return z;
}
/**
@dev returns the difference of _x minus _y, asserts if the subtraction results in a negative number
@param _x minuend
@param _y subtrahend
@return difference
*/
function safeSub(uint256 _x, uint256 _y) internal returns (uint256) {
assert(_x >= _y);
return _x - _y;
}
}
contract CSToken is owned, Utils {
struct Dividend {uint256 time; uint256 tenThousandth; uint256 countComplete;}
/* Public variables of the token */
string public standard = 'Token 0.1';
string public name = 'KickCoin';
string public symbol = 'KICK';
uint8 public decimals = 8;
uint256 _totalSupply = 0;
/* Is allowed to burn tokens */
bool public allowManuallyBurnTokens = true;
/* This creates an array with all balances */
mapping (address => uint256) balances;
mapping (address => mapping (uint256 => uint256)) public agingBalanceOf;
uint[] agingTimes;
Dividend[] dividends;
mapping (address => mapping (address => uint256)) allowed;
/* This generates a public event on the blockchain that will notify clients */
event Transfer(address indexed from, address indexed to, uint256 value);
event AgingTransfer(address indexed from, address indexed to, uint256 value, uint256 agingTime);
event Approval(address indexed _owner, address indexed _spender, uint256 _value);
// triggered when the total supply is increased
event Issuance(uint256 _amount);
// triggered when the total supply is decreased
event Destruction(uint256 _amount);
// This notifies clients about the amount burnt
event Burn(address indexed from, uint256 value);
address[] public addressByIndex;
mapping (address => bool) addressAddedToIndex;
mapping (address => uint) agingTimesForPools;
uint16 currentDividendIndex = 1;
mapping (address => uint) calculatedDividendsIndex;
bool public transfersEnabled = true;
event NewSmartToken(address _token);
/* Initializes contract with initial supply tokens to the creator of the contract */
function CSToken() {
owner = msg.sender;
// So that the index starts with 1
dividends.push(Dividend(0, 0, 0));
// 31.10.2017 09:00:00
dividends.push(Dividend(1509440400, 30, 0));
// 30.11.2017 09:00:00
dividends.push(Dividend(1512032400, 20, 0));
// 31.12.2017 09:00:00
dividends.push(Dividend(1514710800, 10, 0));
// 31.01.2018 09:00:00
dividends.push(Dividend(1517389200, 5, 0));
// 28.02.2018 09:00:00
dividends.push(Dividend(1519808400, 10, 0));
// 31.03.2018 09:00:00
dividends.push(Dividend(1522486800, 20, 0));
// 30.04.2018 09:00:00
dividends.push(Dividend(1525078800, 30, 0));
// 31.05.2018 09:00:00
dividends.push(Dividend(1527757200, 50, 0));
// 30.06.2018 09:00:00
dividends.push(Dividend(1530349200, 30, 0));
// 31.07.2018 09:00:00
dividends.push(Dividend(1533027600, 20, 0));
// 31.08.2018 09:00:00
dividends.push(Dividend(1535706000, 10, 0));
// 30.09.2018 09:00:00
dividends.push(Dividend(1538298000, 5, 0));
// 31.10.2018 09:00:00
dividends.push(Dividend(1540976400, 10, 0));
// 30.11.2018 09:00:00
dividends.push(Dividend(1543568400, 20, 0));
// 31.12.2018 09:00:00
dividends.push(Dividend(1546246800, 30, 0));
// 31.01.2019 09:00:00
dividends.push(Dividend(1548925200, 60, 0));
// 28.02.2019 09:00:00
dividends.push(Dividend(1551344400, 30, 0));
// 31.03.2019 09:00:00
dividends.push(Dividend(1554022800, 20, 0));
// 30.04.2019 09:00:00
dividends.push(Dividend(1556614800, 10, 0));
// 31.05.2019 09:00:00
dividends.push(Dividend(1559307600, 20, 0));
// 30.06.2019 09:00:00
dividends.push(Dividend(1561885200, 30, 0));
// 31.07.2019 09:00:00
dividends.push(Dividend(1564563600, 20, 0));
// 31.08.2019 09:00:00
dividends.push(Dividend(1567242000, 10, 0));
// 30.09.2019 09:00:00
dividends.push(Dividend(1569834000, 5, 0));
NewSmartToken(address(this));
}
modifier transfersAllowed {
assert(transfersEnabled);
_;
}
function totalSupply() constant returns (uint256 totalSupply) {
totalSupply = _totalSupply;
}
function balanceOf(address _owner) constant returns (uint256 balance) {
return balances[_owner];
}
function allowance(address _owner, address _spender) constant returns (uint256 remaining) {
return allowed[_owner][_spender];
}
bool allAgingTimesHasBeenAdded = false;
function addAgingTime(uint256 time) onlyOwner {
require(!allAgingTimesHasBeenAdded);
agingTimes.push(time);
}
function allAgingTimesAdded() onlyOwner {
allAgingTimesHasBeenAdded = true;
}
function calculateDividends(uint256 limit) {
require(now >= dividends[currentDividendIndex].time);
require(limit > 0);
limit = safeAdd(dividends[currentDividendIndex].countComplete, limit);
if (limit > addressByIndex.length) {
limit = addressByIndex.length;
}
for (uint256 i = dividends[currentDividendIndex].countComplete; i < limit; i++) {
_addDividendsForAddress(addressByIndex[i]);
}
if (limit == addressByIndex.length) {
currentDividendIndex++;
}
else {
dividends[currentDividendIndex].countComplete = limit;
}
}
/* User can himself receive dividends without waiting for a global accruals */
function receiveDividends() public {
require(now >= dividends[currentDividendIndex].time);
assert(_addDividendsForAddress(msg.sender));
}
function _addDividendsForAddress(address _address) internal returns (bool success) {
// skip calculating dividends, if already calculated for this address
if (calculatedDividendsIndex[_address] >= currentDividendIndex) return false;
uint256 add = balances[_address] * dividends[currentDividendIndex].tenThousandth / 1000;
balances[_address] = safeAdd(balances[_address], add);
Transfer(this, _address, add);
Issuance(add);
_totalSupply = safeAdd(_totalSupply, add);
if (agingBalanceOf[_address][0] > 0) {
agingBalanceOf[_address][0] = safeAdd(agingBalanceOf[_address][0], agingBalanceOf[_address][0] * dividends[currentDividendIndex].tenThousandth / 1000);
for (uint256 k = 0; k < agingTimes.length; k++) {
agingBalanceOf[_address][agingTimes[k]] = safeAdd(agingBalanceOf[_address][agingTimes[k]], agingBalanceOf[_address][agingTimes[k]] * dividends[currentDividendIndex].tenThousandth / 1000);
}
}
calculatedDividendsIndex[_address] = currentDividendIndex;
return true;
}
/* Send coins */
function transfer(address _to, uint256 _value) transfersAllowed returns (bool success) {
_checkMyAging(msg.sender);
if (currentDividendIndex < dividends.length && now >= dividends[currentDividendIndex].time) {
_addDividendsForAddress(msg.sender);
_addDividendsForAddress(_to);
}
require(accountBalance(msg.sender) >= _value);
// Subtract from the sender
balances[msg.sender] = safeSub(balances[msg.sender], _value);
if (agingTimesForPools[msg.sender] > 0 && agingTimesForPools[msg.sender] > now) {
_addToAging(msg.sender, _to, agingTimesForPools[msg.sender], _value);
}
balances[_to] = safeAdd(balances[_to], _value);
_addIndex(_to);
Transfer(msg.sender, _to, _value);
return true;
}
function mintToken(address target, uint256 mintedAmount, uint256 agingTime) onlyOwner {
if (agingTime > now) {
_addToAging(owner, target, agingTime, mintedAmount);
}
balances[target] = safeAdd(balances[target], mintedAmount);
_totalSupply = safeAdd(_totalSupply, mintedAmount);
Issuance(mintedAmount);
_addIndex(target);
Transfer(this, target, mintedAmount);
}
function _addIndex(address _address) internal {
if (!addressAddedToIndex[_address]) {
addressAddedToIndex[_address] = true;
addressByIndex.push(_address);
}
}
function _addToAging(address from, address target, uint256 agingTime, uint256 amount) internal {
agingBalanceOf[target][0] = safeAdd(agingBalanceOf[target][0], amount);
agingBalanceOf[target][agingTime] = safeAdd(agingBalanceOf[target][agingTime], amount);
AgingTransfer(from, target, amount, agingTime);
}
/* Allow another contract to spend some tokens in your behalf */
function approve(address _spender, uint256 _value) returns (bool success) {
allowed[msg.sender][_spender] = _value;
Approval(msg.sender, _spender, _value);
return true;
}
/* Approve and then communicate the approved contract in a single tx */
function approveAndCall(address _spender, uint256 _value, bytes _extraData) returns (bool success) {
tokenRecipient spender = tokenRecipient(_spender);
if (approve(_spender, _value)) {
spender.receiveApproval(msg.sender, _value, this, _extraData);
return true;
}
}
/* A contract attempts to get the coins */
function transferFrom(address _from, address _to, uint256 _value) transfersAllowed returns (bool success) {
_checkMyAging(_from);
if (currentDividendIndex < dividends.length && now >= dividends[currentDividendIndex].time) {
_addDividendsForAddress(_from);
_addDividendsForAddress(_to);
}
// Check if the sender has enough
require(accountBalance(_from) >= _value);
// Check allowed
require(_value <= allowed[_from][msg.sender]);
// Subtract from the sender
balances[_from] = safeSub(balances[_from], _value);
// Add the same to the recipient
balances[_to] = safeAdd(balances[_to], _value);
allowed[_from][msg.sender] = safeSub(allowed[_from][msg.sender], _value);
if (agingTimesForPools[_from] > 0 && agingTimesForPools[_from] > now) {
_addToAging(_from, _to, agingTimesForPools[_from], _value);
}
_addIndex(_to);
Transfer(_from, _to, _value);
return true;
}
/* This unnamed function is called whenever someone tries to send ether to it */
function() {
revert();
// Prevents accidental sending of ether
}
function _checkMyAging(address sender) internal {
if (agingBalanceOf[sender][0] == 0) return;
for (uint256 k = 0; k < agingTimes.length; k++) {
if (agingTimes[k] < now) {
agingBalanceOf[sender][0] = safeSub(agingBalanceOf[sender][0], agingBalanceOf[sender][agingTimes[k]]);
agingBalanceOf[sender][agingTimes[k]] = 0;
}
}
}
function addAgingTimesForPool(address poolAddress, uint256 agingTime) onlyOwner {
agingTimesForPools[poolAddress] = agingTime;
}
function countAddresses() constant returns (uint256 length) {
return addressByIndex.length;
}
function accountBalance(address _address) constant returns (uint256 balance) {
return safeSub(balances[_address], agingBalanceOf[_address][0]);
}
function disableTransfers(bool _disable) public onlyOwner {
transfersEnabled = !_disable;
}
function issue(address _to, uint256 _amount) public onlyOwner validAddress(_to) notThis(_to) {
_totalSupply = safeAdd(_totalSupply, _amount);
balances[_to] = safeAdd(balances[_to], _amount);
_addIndex(_to);
Issuance(_amount);
Transfer(this, _to, _amount);
}
/**
* Destroy tokens
* Remove `_value` tokens from the system irreversibly
* @param _value the amount of money to burn
*/
function burn(uint256 _value) returns (bool success) {
destroy(msg.sender, _value);
Burn(msg.sender, _value);
return true;
}
/**
* Destroy tokens
* Remove `_amount` tokens from the system irreversibly
* @param _from the address from which tokens will be burnt
* @param _amount the amount of money to burn
*/
function destroy(address _from, uint256 _amount) public {
_checkMyAging(_from);
// validate input
require((msg.sender == _from && allowManuallyBurnTokens) || msg.sender == owner);
require(accountBalance(_from) >= _amount);
balances[_from] = safeSub(balances[_from], _amount);
_totalSupply = safeSub(_totalSupply, _amount);
Transfer(_from, this, _amount);
Destruction(_amount);
}
function disableManuallyBurnTokens(bool _disable) public onlyOwner {
allowManuallyBurnTokens = !_disable;
}
}