Transaction Hash:
Block:
5815888 at Jun-19-2018 09:02:23 AM +UTC
Transaction Fee:
0.00086496 ETH
$1.94
Gas Used:
21,624 Gas / 40 Gwei
Account State Difference:
Address | Before | After | State Difference | ||
---|---|---|---|---|---|
0x43876E4e...55A3F3413 |
2.750546310191150307 Eth
Nonce: 163
|
2.749681350191150307 Eth
Nonce: 164
| 0.00086496 | ||
0xEA674fdD...16B898ec8
Miner
| (Ethermine) | 558.995191668995349374 Eth | 558.996056628995349374 Eth | 0.00086496 |
Execution Trace
ETH 1
PublicSale.CALL( )
[PublicSale (ln:187)]
collect[PublicSale (ln:188)]
whitelist[PublicSale (ln:258)]
add[PublicSale (ln:260)]
getPurchaseAmount[PublicSale (ln:268)]
add[PublicSale (ln:270)]
add[PublicSale (ln:273)]
transfer[PublicSale (ln:275)]
safeTransfer[PublicSale (ln:276)]
mul[PublicSale (ln:276)]
Purchase[PublicSale (ln:278)]
mul[PublicSale (ln:278)]
pragma solidity ^0.4.24; library SafeMath { /** * @dev Multiplies two numbers, throws on overflow. */ function mul(uint256 a, uint256 b) internal pure returns (uint256 c) { // Gas optimization: this is cheaper than asserting 'a' not being zero, but the // benefit is lost if 'b' is also tested. // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522 if (a == 0) { return 0; } c = a * b; assert(c / a == b); return c; } /** * @dev Integer division of two numbers, truncating the quotient. */ 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 a / b; } /** * @dev Subtracts two numbers, throws on overflow (i.e. if subtrahend is greater than minuend). */ function sub(uint256 a, uint256 b) internal pure returns (uint256) { assert(b <= a); return a - b; } /** * @dev Adds two numbers, throws on overflow. */ function add(uint256 a, uint256 b) internal pure returns (uint256 c) { c = a + b; assert(c >= a); return c; } } contract Ownable { address public owner; event OwnershipRenounced(address indexed previousOwner); event OwnershipTransferred( address indexed previousOwner, address indexed newOwner ); /** * @dev The Ownable constructor sets the original `owner` of the contract to the sender * account. */ constructor() 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 relinquish control of the contract. */ function renounceOwnership() public onlyOwner { emit OwnershipRenounced(owner); owner = address(0); } /** * @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 { _transferOwnership(_newOwner); } /** * @dev Transfers control of the contract to a newOwner. * @param _newOwner The address to transfer ownership to. */ function _transferOwnership(address _newOwner) internal { require(_newOwner != address(0)); emit OwnershipTransferred(owner, _newOwner); owner = _newOwner; } } contract Pausable is Ownable { event Pause(); event Unpause(); bool public paused = false; /** * @dev Modifier to make a function callable only when the contract is not paused. */ modifier whenNotPaused() { require(!paused); _; } /** * @dev Modifier to make a function callable only when the contract is paused. */ modifier whenPaused() { require(paused); _; } /** * @dev called by the owner to pause, triggers stopped state */ function pause() onlyOwner whenNotPaused public { paused = true; emit Pause(); } /** * @dev called by the owner to unpause, returns to normal state */ function unpause() onlyOwner whenPaused public { paused = false; emit Unpause(); } } contract PublicSale is Pausable { using SafeMath for uint256; using SafeERC20 for ERC20; uint256 public maxgas; uint256 public maxcap; // sale hardcap uint256 public exceed; // indivisual hardcap uint256 public minimum; // indivisual softcap uint256 public rate; // exchange rate bool public ignited = false; // is sale started? uint256 public weiRaised = 0; // check sale status address public wallet; // wallet for withdrawal Whitelist public List; // whitelist ERC20 public Token; // token constructor ( uint256 _maxcap, uint256 _exceed, uint256 _minimum, uint256 _rate, uint256 _maxgas, address _wallet, address _whitelist, address _token ) public { require(_wallet != address(0)); require(_whitelist != address(0)); require(_token != address(0)); maxcap = _maxcap; exceed = _exceed; minimum = _minimum; rate = _rate; maxgas = _maxgas; wallet = _wallet; Token = ERC20(_token); List = Whitelist(_whitelist); } /* fallback function */ function () external payable { collect(); } // address event Change(address addr, string name); event ChangeMaxGas(uint256 gas); function setMaxGas(uint256 gas) external onlyOwner { require(gas > 0); maxgas = gas; emit ChangeMaxGas(gas); } function setWhitelist(address whitelist) external onlyOwner { require(whitelist != address(0)); List = Whitelist(whitelist); emit Change(whitelist, "whitelist"); } function setWallet(address newWallet) external onlyOwner { require(newWallet != address(0)); wallet = newWallet; emit Change(newWallet, "wallet"); } // sale controller event Ignite(); event Extinguish(); function ignite() external onlyOwner { ignited = true; emit Ignite(); } function extinguish() external onlyOwner { ignited = false; emit Extinguish(); } // collect eth event Purchase(address indexed buyer, uint256 purchased, uint256 refund, uint256 tokens); mapping (address => uint256) public buyers; function collect() public payable whenNotPaused { address buyer = msg.sender; uint256 amount = msg.value; require(ignited); require(List.whitelist(buyer)); require(buyer != address(0)); require(buyers[buyer].add(amount) >= minimum); require(buyers[buyer] < exceed); require(weiRaised < maxcap); require(tx.gasprice <= maxgas); uint256 purchase; uint256 refund; (purchase, refund) = getPurchaseAmount(buyer, amount); weiRaised = weiRaised.add(purchase); if(weiRaised >= maxcap) ignited = false; buyers[buyer] = buyers[buyer].add(purchase); buyer.transfer(refund); Token.safeTransfer(buyer, purchase.mul(rate)); emit Purchase(buyer, purchase, refund, purchase.mul(rate)); } // util functions for collect function getPurchaseAmount(address _buyer, uint256 _amount) private view returns (uint256, uint256) { uint256 d1 = maxcap.sub(weiRaised); uint256 d2 = exceed.sub(buyers[_buyer]); uint256 d = (d1 > d2) ? d2 : d1; return (_amount > d) ? (d, _amount.sub(d)) : (_amount, 0); } // finalize bool public finalized = false; function finalize() external onlyOwner whenNotPaused { require(!finalized); withdrawEther(); withdrawToken(); finalized = true; } // withdraw event WithdrawToken(address indexed from, uint256 amount); event WithdrawEther(address indexed from, uint256 amount); function withdrawToken() public onlyOwner whenNotPaused { require(!ignited); Token.safeTransfer(wallet, Token.balanceOf(address(this))); emit WithdrawToken(wallet, Token.balanceOf(address(this))); } function withdrawEther() public onlyOwner whenNotPaused { require(!ignited); wallet.transfer(address(this).balance); emit WithdrawEther(wallet, address(this).balance); } } contract RBAC { using Roles for Roles.Role; mapping (string => Roles.Role) private roles; event RoleAdded(address addr, string roleName); event RoleRemoved(address addr, string roleName); /** * @dev reverts if addr does not have role * @param addr address * @param roleName the name of the role * // reverts */ function checkRole(address addr, string roleName) view public { roles[roleName].check(addr); } /** * @dev determine if addr has role * @param addr address * @param roleName the name of the role * @return bool */ function hasRole(address addr, string roleName) view public returns (bool) { return roles[roleName].has(addr); } /** * @dev add a role to an address * @param addr address * @param roleName the name of the role */ function addRole(address addr, string roleName) internal { roles[roleName].add(addr); emit RoleAdded(addr, roleName); } /** * @dev remove a role from an address * @param addr address * @param roleName the name of the role */ function removeRole(address addr, string roleName) internal { roles[roleName].remove(addr); emit RoleRemoved(addr, roleName); } /** * @dev modifier to scope access to a single role (uses msg.sender as addr) * @param roleName the name of the role * // reverts */ modifier onlyRole(string roleName) { checkRole(msg.sender, roleName); _; } /** * @dev modifier to scope access to a set of roles (uses msg.sender as addr) * @param roleNames the names of the roles to scope access to * // reverts * * @TODO - when solidity supports dynamic arrays as arguments to modifiers, provide this * see: https://github.com/ethereum/solidity/issues/2467 */ // modifier onlyRoles(string[] roleNames) { // bool hasAnyRole = false; // for (uint8 i = 0; i < roleNames.length; i++) { // if (hasRole(msg.sender, roleNames[i])) { // hasAnyRole = true; // break; // } // } // require(hasAnyRole); // _; // } } contract Whitelist is Ownable, RBAC { event WhitelistedAddressAdded(address addr); event WhitelistedAddressRemoved(address addr); string public constant ROLE_WHITELISTED = "whitelist"; /** * @dev Throws if called by any account that's not whitelisted. */ modifier onlyWhitelisted() { checkRole(msg.sender, ROLE_WHITELISTED); _; } /** * @dev add an address to the whitelist * @param addr address * @return true if the address was added to the whitelist, false if the address was already in the whitelist */ function addAddressToWhitelist(address addr) onlyOwner public { addRole(addr, ROLE_WHITELISTED); emit WhitelistedAddressAdded(addr); } /** * @dev getter to determine if address is in whitelist */ function whitelist(address addr) public view returns (bool) { return hasRole(addr, ROLE_WHITELISTED); } /** * @dev add addresses to the whitelist * @param addrs addresses * @return true if at least one address was added to the whitelist, * false if all addresses were already in the whitelist */ function addAddressesToWhitelist(address[] addrs) onlyOwner public { for (uint256 i = 0; i < addrs.length; i++) { addAddressToWhitelist(addrs[i]); } } /** * @dev remove an address from the whitelist * @param addr address * @return true if the address was removed from the whitelist, * false if the address wasn't in the whitelist in the first place */ function removeAddressFromWhitelist(address addr) onlyOwner public { removeRole(addr, ROLE_WHITELISTED); emit WhitelistedAddressRemoved(addr); } /** * @dev remove addresses from the whitelist * @param addrs addresses * @return true if at least one address was removed from the whitelist, * false if all addresses weren't in the whitelist in the first place */ function removeAddressesFromWhitelist(address[] addrs) onlyOwner public { for (uint256 i = 0; i < addrs.length; i++) { removeAddressFromWhitelist(addrs[i]); } } } library Roles { struct Role { mapping (address => bool) bearer; } /** * @dev give an address access to this role */ function add(Role storage role, address addr) internal { role.bearer[addr] = true; } /** * @dev remove an address' access to this role */ function remove(Role storage role, address addr) internal { role.bearer[addr] = false; } /** * @dev check if an address has this role * // reverts */ function check(Role storage role, address addr) view internal { require(has(role, addr)); } /** * @dev check if an address has this role * @return bool */ function has(Role storage role, address addr) view internal returns (bool) { return role.bearer[addr]; } } contract ERC20Basic { function totalSupply() public view returns (uint256); function balanceOf(address who) public view returns (uint256); function transfer(address to, uint256 value) public returns (bool); event Transfer(address indexed from, address indexed to, uint256 value); } contract ERC20 is ERC20Basic { function allowance(address owner, address spender) public view returns (uint256); function transferFrom(address from, address to, uint256 value) public returns (bool); function approve(address spender, uint256 value) public returns (bool); event Approval( address indexed owner, address indexed spender, uint256 value ); } library SafeERC20 { function safeTransfer(ERC20Basic token, address to, uint256 value) internal { require(token.transfer(to, value)); } function safeTransferFrom( ERC20 token, address from, address to, uint256 value ) internal { require(token.transferFrom(from, to, value)); } function safeApprove(ERC20 token, address spender, uint256 value) internal { require(token.approve(spender, value)); } }