Transaction Hash:
Block:
5117572 at Feb-19-2018 08:20:38 AM +UTC
Transaction Fee:
0.00265209 ETH
$5.31
Gas Used:
88,403 Gas / 30 Gwei
Account State Difference:
| Address | Before | After | State Difference | ||
|---|---|---|---|---|---|
| 0x89e9062B...997dC4ccf | |||||
| 0xC1D5E361...A2fb30F0b |
0.47 Eth
Nonce: 0
|
0.00734791 Eth
Nonce: 1
| 0.46265209 | ||
| 0xe3954999...2541E9b18 | 408.213585293896480095 Eth | 408.673585293896480095 Eth | 0.46 | ||
|
0xEA674fdD...16B898ec8
Miner
| (Ethermine) | 2,767.19405843950893969 Eth | 2,767.19671052950893969 Eth | 0.00265209 |
Execution Trace
ETH 0.46
SimpleTGE.CALL( )
- ETH 0.46
0xe39549998782169d1e91587a0d2e8652541e9b18.CALL( )
[SimpleTGE (ln:196)]
contributeWithoutVesting[SimpleTGE (ln:197)]
pragma solidity ^0.4.17;
/**
* @title SafeMath
* @dev Math operations with safety checks that throw on error
*/
library SafeMath {
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
uint256 c = a * b;
assert(c / a == b);
return c;
}
function div(uint256 a, uint256 b) internal pure returns (uint256) {
// assert(b > 0); // Solidity automatically throws when dividing by 0
uint256 c = a / b;
// assert(a == b * c + a % b); // There is no case in which this doesn't hold
return c;
}
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
assert(b <= a);
return a - b;
}
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
assert(c >= a);
return c;
}
}
/**
* @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;
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @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);
_;
}
/**
* @dev Allows the current owner to transfer control of the contract to a newOwner.
* @param newOwner The address to transfer ownership to.
*/
function transferOwnership(address newOwner) public onlyOwner {
require(newOwner != address(0));
OwnershipTransferred(owner, newOwner);
owner = newOwner;
}
}
contract SimpleTGE is Ownable {
using SafeMath for uint256;
// start and end timestamps (both inclusive) when sale is open
uint256 public publicTGEStartBlockTimeStamp;
uint256 public publicTGEEndBlockTimeStamp;
// address where funds are collected
address public fundsWallet;
// amount of raised money in wei
uint256 public weiRaised;
// sale cap in wei
uint256 public totalCapInWei;
// individual cap in wei
uint256 public individualCapInWei;
// how long the TRS subscription is open after the TGE.
uint256 public TRSOffset = 5 days;
mapping (address => bool) public whitelist;
address[] public contributors;
struct Contribution {
bool hasVested;
uint256 weiContributed;
}
mapping (address => Contribution) public contributions;
modifier whilePublicTGEIsActive() {
require(block.timestamp >= publicTGEStartBlockTimeStamp && block.timestamp <= publicTGEEndBlockTimeStamp);
_;
}
modifier isWhitelisted() {
require(whitelist[msg.sender]);
_;
}
function blacklistAddresses(address[] addrs) external onlyOwner returns(bool) {
require(addrs.length <= 100);
for (uint i = 0; i < addrs.length; i++) {
require(addrs[i] != address(0));
whitelist[addrs[i]] = false;
}
return true;
}
function whitelistAddresses(address[] addrs) external onlyOwner returns(bool) {
require(addrs.length <= 100);
for (uint i = 0; i < addrs.length; i++) {
require(addrs[i] != address(0));
whitelist[addrs[i]] = true;
}
return true;
}
/**
* @dev Transfer all Ether held by the contract to the address specified by owner.
*/
function reclaimEther(address _beneficiary) external onlyOwner {
_beneficiary.transfer(this.balance);
}
function SimpleTGE (
address _fundsWallet,
uint256 _publicTGEStartBlockTimeStamp,
uint256 _publicTGEEndBlockTimeStamp,
uint256 _individualCapInWei,
uint256 _totalCapInWei
) public
{
require(_publicTGEStartBlockTimeStamp >= block.timestamp);
require(_publicTGEEndBlockTimeStamp > _publicTGEStartBlockTimeStamp);
require(_fundsWallet != address(0));
require(_individualCapInWei > 0);
require(_individualCapInWei <= _totalCapInWei);
require(_totalCapInWei > 0);
fundsWallet = _fundsWallet;
publicTGEStartBlockTimeStamp = _publicTGEStartBlockTimeStamp;
publicTGEEndBlockTimeStamp = _publicTGEEndBlockTimeStamp;
individualCapInWei = _individualCapInWei;
totalCapInWei = _totalCapInWei;
}
// allows changing the individual cap.
function changeIndividualCapInWei(uint256 _individualCapInWei) onlyOwner external returns(bool) {
require(_individualCapInWei > 0);
require(_individualCapInWei < totalCapInWei);
individualCapInWei = _individualCapInWei;
return true;
}
// low level token purchase function
function contribute(bool _vestingDecision) internal {
// validations
require(msg.sender != address(0));
require(msg.value != 0);
require(weiRaised.add(msg.value) <= totalCapInWei);
require(contributions[msg.sender].weiContributed.add(msg.value) <= individualCapInWei);
// if we have not received any WEI from this address until now, then we add this address to contributors list.
if (contributions[msg.sender].weiContributed == 0) {
contributors.push(msg.sender);
}
contributions[msg.sender].weiContributed = contributions[msg.sender].weiContributed.add(msg.value);
weiRaised = weiRaised.add(msg.value);
contributions[msg.sender].hasVested = _vestingDecision;
fundsWallet.transfer(msg.value);
}
function contributeAndVest() external whilePublicTGEIsActive isWhitelisted payable {
contribute(true);
}
function contributeWithoutVesting() public whilePublicTGEIsActive isWhitelisted payable {
contribute(false);
}
// fallback function can be used to buy tokens
function () external payable {
contributeWithoutVesting();
}
// Vesting logic
// The following cases are checked for _beneficiary's actions:
function vest(bool _vestingDecision) external isWhitelisted returns(bool) {
bool existingDecision = contributions[msg.sender].hasVested;
require(existingDecision != _vestingDecision);
require(block.timestamp >= publicTGEStartBlockTimeStamp);
require(contributions[msg.sender].weiContributed > 0);
// Ensure vesting cannot be done once TRS starts
if (block.timestamp > publicTGEEndBlockTimeStamp) {
require(block.timestamp.sub(publicTGEEndBlockTimeStamp) <= TRSOffset);
}
contributions[msg.sender].hasVested = _vestingDecision;
return true;
}
}