ETH Price: $2,089.78 (-2.86%)

Transaction Decoder

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:

225 CSToken.Transfer( from=[Receiver] CSToken, to=0x383708982B7E3Cd2F51E386586b303C7B42a823F, value=0 )
226 CSToken.Issuance( _amount=0 )
227 CSToken.Transfer( from=[Receiver] CSToken, to=0xc84737EB7fD886F8CeDc50C8322189A72848e0F8, value=7215525377 )
228 CSToken.Issuance( _amount=7215525377 )
229 CSToken.Transfer( from=[Receiver] CSToken, to=0x9ce94E5E2E328c58E469Fd65991d55c86DFAf03B, value=62655706120 )
230 CSToken.Issuance( _amount=62655706120 )
231 CSToken.Transfer( from=[Receiver] CSToken, to=0xceb8aba51AB881B563E59a644f3aC3be690D5970, value=0 )
232 CSToken.Issuance( _amount=0 )
233 CSToken.Transfer( from=[Receiver] CSToken, to=0xb4Aa44C5F908523699a361543866c12BC86DD1dD, value=19100957171 )
234 CSToken.Issuance( _amount=19100957171 )
235 CSToken.Transfer( from=[Receiver] CSToken, to=0xb407d213016F38cDE11FB21261C005a5C24641CE, value=0 )
236 CSToken.Issuance( _amount=0 )
237 CSToken.Transfer( from=[Receiver] CSToken, to=0xfA01af5cb2030DcdBD90a1629d166CE8B15D97FA, value=0 )
238 CSToken.Issuance( _amount=0 )
239 CSToken.Transfer( from=[Receiver] CSToken, to=0x2d25A6e7a5DCB342E60D1dE180b0f745d1cE5E63, value=148387114 )
240 CSToken.Issuance( _amount=148387114 )
241 CSToken.Transfer( from=[Receiver] CSToken, to=0x909D96A771e0F570ca9e243Aa443F9BE8A9Dd9d2, value=7602370431 )
242 CSToken.Issuance( _amount=7602370431 )
243 CSToken.Transfer( from=[Receiver] CSToken, to=0x66F3C954a097bbA1f71D77A7807DbA588a975fEd, value=0 )
244 CSToken.Issuance( _amount=0 )

Account State Difference:

  Address   Before After State Difference Code
0x1a80BDC2...e1b251886
2.3062748247169083 Eth
Nonce: 19117
2.3051996828169083 Eth
Nonce: 19118
0.0010751419
0x27695E09...4c39e9eb9
(Ethermine)
916.692727871384735431 Eth916.693803013284735431 Eth0.0010751419

Execution Trace

CSToken.calculateDividends( limit=10 )
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;
	}
}