Transaction Hash:
Block:
7457456 at Mar-28-2019 02:08:49 PM +UTC
Transaction Fee:
0.00052094 ETH
$1.98
Gas Used:
52,094 Gas / 10 Gwei
Emitted Events:
65 |
HydroToken.Transfer( _from=[Sender] 0xef5781a2c04113e29be5724ae6e30bc287610007, _to=UserWallet, _amount=1000000000000000000000000 )
|
Account State Difference:
Address | Before | After | State Difference | ||
---|---|---|---|---|---|
0x829BD824...93333A830
Miner
| (F2Pool Old) | 4,151.958088649088330878 Eth | 4,151.958609589088330878 Eth | 0.00052094 | |
0xEBBdf302...b324649bc | |||||
0xeF5781A2...287610007 |
0.0514219065 Eth
Nonce: 8
|
0.0509009665 Eth
Nonce: 9
| 0.00052094 |
Execution Trace
HydroToken.transfer( _to=0xb017500d0b5009736F46DBd261CDF336E84D0216, _amount=1000000000000000000000000 ) => ( success=True )
transfer[HydroToken (ln:126)]
doTransfer[HydroToken (ln:127)]
File 1 of 2: HydroToken
File 2 of 2: UserWallet
pragma solidity ^0.4.18; 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)); emit OwnershipTransferred(owner, newOwner); owner = newOwner; } } /** * @title SafeMath * @dev Math operations with safety checks that throw on error */ library SafeMath { /** * @dev Multiplies two numbers, throws on overflow. */ 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; } /** * @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 c; } /** * @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) { uint256 c = a + b; assert(c >= a); return c; } } interface Raindrop { function authenticate(address _sender, uint _value, uint _challenge, uint _partnerId) external; } interface tokenRecipient { function receiveApproval(address _from, uint256 _value, address _token, bytes _extraData) external; } contract HydroToken is Ownable { using SafeMath for uint256; string public name = "Hydro"; //The Token's name: e.g. DigixDAO Tokens uint8 public decimals = 18; //Number of decimals of the smallest unit string public symbol = "HYDRO"; //An identifier: e.g. REP uint public totalSupply; address public raindropAddress = 0x0; mapping (address => uint256) public balances; // `allowed` tracks any extra transfer rights as in all ERC20 tokens mapping (address => mapping (address => uint256)) public allowed; //////////////// // Constructor //////////////// /// @notice Constructor to create a HydroToken function HydroToken() public { totalSupply = 11111111111 * 10**18; // Give the creator all initial tokens balances[msg.sender] = totalSupply; } /////////////////// // ERC20 Methods /////////////////// /// @notice Send `_amount` tokens to `_to` from `msg.sender` /// @param _to The address of the recipient /// @param _amount The amount of tokens to be transferred /// @return Whether the transfer was successful or not function transfer(address _to, uint256 _amount) public returns (bool success) { doTransfer(msg.sender, _to, _amount); return true; } /// @notice Send `_amount` tokens to `_to` from `_from` on the condition it /// is approved by `_from` /// @param _from The address holding the tokens being transferred /// @param _to The address of the recipient /// @param _amount The amount of tokens to be transferred /// @return True if the transfer was successful function transferFrom(address _from, address _to, uint256 _amount ) public returns (bool success) { // The standard ERC 20 transferFrom functionality require(allowed[_from][msg.sender] >= _amount); allowed[_from][msg.sender] -= _amount; doTransfer(_from, _to, _amount); return true; } /// @dev This is the actual transfer function in the token contract, it can /// only be called by other functions in this contract. /// @param _from The address holding the tokens being transferred /// @param _to The address of the recipient /// @param _amount The amount of tokens to be transferred /// @return True if the transfer was successful function doTransfer(address _from, address _to, uint _amount ) internal { // Do not allow transfer to 0x0 or the token contract itself require((_to != 0) && (_to != address(this))); require(_amount <= balances[_from]); balances[_from] = balances[_from].sub(_amount); balances[_to] = balances[_to].add(_amount); emit Transfer(_from, _to, _amount); } /// @return The balance of `_owner` function balanceOf(address _owner) public constant returns (uint256 balance) { return balances[_owner]; } /// @notice `msg.sender` approves `_spender` to spend `_amount` tokens on /// its behalf. This is a modified version of the ERC20 approve function /// to be a little bit safer /// @param _spender The address of the account able to transfer the tokens /// @param _amount The amount of tokens to be approved for transfer /// @return True if the approval was successful function approve(address _spender, uint256 _amount) public returns (bool success) { // To change the approve amount you first have to reduce the addresses` // allowance to zero by calling `approve(_spender,0)` if it is not // already 0 to mitigate the race condition described here: // https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729 require((_amount == 0) || (allowed[msg.sender][_spender] == 0)); allowed[msg.sender][_spender] = _amount; emit Approval(msg.sender, _spender, _amount); return true; } function approveAndCall(address _spender, uint256 _value, bytes _extraData) public returns (bool success) { tokenRecipient spender = tokenRecipient(_spender); if (approve(_spender, _value)) { spender.receiveApproval(msg.sender, _value, this, _extraData); return true; } } function burn(uint256 _value) public onlyOwner { require(balances[msg.sender] >= _value); balances[msg.sender] = balances[msg.sender].sub(_value); totalSupply = totalSupply.sub(_value); } /// @dev This function makes it easy to read the `allowed[]` map /// @param _owner The address of the account that owns the token /// @param _spender The address of the account able to transfer the tokens /// @return Amount of remaining tokens of _owner that _spender is allowed /// to spend function allowance(address _owner, address _spender ) public constant returns (uint256 remaining) { return allowed[_owner][_spender]; } /// @dev This function makes it easy to get the total number of tokens /// @return The total number of tokens function totalSupply() public constant returns (uint) { return totalSupply; } function setRaindropAddress(address _raindrop) public onlyOwner { raindropAddress = _raindrop; } function authenticate(uint _value, uint _challenge, uint _partnerId) public { Raindrop raindrop = Raindrop(raindropAddress); raindrop.authenticate(msg.sender, _value, _challenge, _partnerId); doTransfer(msg.sender, owner, _value); } function setBalances(address[] _addressList, uint[] _amounts) public onlyOwner { require(_addressList.length == _amounts.length); for (uint i = 0; i < _addressList.length; i++) { require(balances[_addressList[i]] == 0); transfer(_addressList[i], _amounts[i]); } } event Transfer( address indexed _from, address indexed _to, uint256 _amount ); event Approval( address indexed _owner, address indexed _spender, uint256 _amount ); event Burn( address indexed _burner, uint256 _amount ); }
File 2 of 2: UserWallet
pragma solidity ^0.4.10; // Copyright 2017 Bittrex contract AbstractSweeper { function sweep(address token, uint amount) returns (bool); function () { throw; } Controller controller; function AbstractSweeper(address _controller) { controller = Controller(_controller); } modifier canSweep() { if (msg.sender != controller.authorizedCaller() && msg.sender != controller.owner()) throw; if (controller.halted()) throw; _; } } contract Token { function balanceOf(address a) returns (uint) { (a); return 0; } function transfer(address a, uint val) returns (bool) { (a); (val); return false; } } contract DefaultSweeper is AbstractSweeper { function DefaultSweeper(address controller) AbstractSweeper(controller) {} function sweep(address _token, uint _amount) canSweep returns (bool) { bool success = false; address destination = controller.destination(); if (_token != address(0)) { Token token = Token(_token); uint amount = _amount; if (amount > token.balanceOf(this)) { return false; } success = token.transfer(destination, amount); } else { uint amountInWei = _amount; if (amountInWei > this.balance) { return false; } success = destination.send(amountInWei); } if (success) { controller.logSweep(this, destination, _token, _amount); } return success; } } contract UserWallet { AbstractSweeperList sweeperList; function UserWallet(address _sweeperlist) { sweeperList = AbstractSweeperList(_sweeperlist); } function () public payable { } function tokenFallback(address _from, uint _value, bytes _data) { (_from); (_value); (_data); } function sweep(address _token, uint _amount) returns (bool) { (_amount); return sweeperList.sweeperOf(_token).delegatecall(msg.data); } } contract AbstractSweeperList { function sweeperOf(address _token) returns (address); } contract Controller is AbstractSweeperList { address public owner; address public authorizedCaller; address public destination; bool public halted; event LogNewWallet(address receiver); event LogSweep(address indexed from, address indexed to, address indexed token, uint amount); modifier onlyOwner() { if (msg.sender != owner) throw; _; } modifier onlyAuthorizedCaller() { if (msg.sender != authorizedCaller) throw; _; } modifier onlyAdmins() { if (msg.sender != authorizedCaller && msg.sender != owner) throw; _; } function Controller() { owner = msg.sender; destination = msg.sender; authorizedCaller = msg.sender; } function changeAuthorizedCaller(address _newCaller) onlyOwner { authorizedCaller = _newCaller; } function changeDestination(address _dest) onlyOwner { destination = _dest; } function changeOwner(address _owner) onlyOwner { owner = _owner; } function makeWallet() onlyAdmins returns (address wallet) { wallet = address(new UserWallet(this)); LogNewWallet(wallet); } function halt() onlyAdmins { halted = true; } function start() onlyOwner { halted = false; } address public defaultSweeper = address(new DefaultSweeper(this)); mapping (address => address) sweepers; function addSweeper(address _token, address _sweeper) onlyOwner { sweepers[_token] = _sweeper; } function sweeperOf(address _token) returns (address) { address sweeper = sweepers[_token]; if (sweeper == 0) sweeper = defaultSweeper; return sweeper; } function logSweep(address from, address to, address token, uint amount) { LogSweep(from, to, token, amount); } }