Transaction Hash:
Block:
6561663 at Oct-22-2018 09:15:26 AM +UTC
Transaction Fee:
0.00229785 ETH
$5.01
Gas Used:
45,957 Gas / 50 Gwei
Emitted Events:
| 17 |
GnosisToken.Transfer( from=[Receiver] 0xe4a46d2222f4c97d0ed65d15e464bb38a34a0c78, to=[Sender] 0xfbb1b73c4f0bda4f67dca266ce6ef42f520fbb98, value=11155352250000000000 )
|
| 18 |
Controller.LogSweep( from=[Receiver] 0xe4a46d2222f4c97d0ed65d15e464bb38a34a0c78, to=[Sender] 0xfbb1b73c4f0bda4f67dca266ce6ef42f520fbb98, token=GnosisToken, amount=11155352250000000000 )
|
Account State Difference:
| Address | Before | After | State Difference | ||
|---|---|---|---|---|---|
| 0x6810e776...8e5386b96 | |||||
|
0xEA674fdD...16B898ec8
Miner
| (Ethermine) | 1,028.082421790706771928 Eth | 1,028.084719640706771928 Eth | 0.00229785 | |
| 0xFBb1b73C...f520fBB98 | (Bittrex) |
964,370.722728023530389355 Eth
Nonce: 6706405
|
964,370.720430173530389355 Eth
Nonce: 6706406
| 0.00229785 |
Execution Trace
0xe4a46d2222f4c97d0ed65d15e464bb38a34a0c78.6ea056a9( )
-
Controller.sweeperOf( _token=0x6810e776880C02933D47DB1b9fc05908e5386b96 ) => ( 0xb2233FCEC42c588Ee71A594d9A25AA695345426c ) DefaultSweeper.sweep( _token=0x6810e776880C02933D47DB1b9fc05908e5386b96, _amount=11155352250000000000 ) => ( True )-
Controller.CALL( ) -
Controller.CALL( ) -
Controller.CALL( ) -
Controller.CALL( ) -
GnosisToken.balanceOf( _owner=0xE4a46d2222f4c97D0ED65D15e464BB38A34A0c78 ) => ( 11155352250000000000 )
-
GnosisToken.transfer( _to=0xFBb1b73C4f0BDa4f67dcA266ce6Ef42f520fBB98, _value=11155352250000000000 ) => ( True )
-
Controller.logSweep( from=0xE4a46d2222f4c97D0ED65D15e464BB38A34A0c78, to=0xFBb1b73C4f0BDa4f67dcA266ce6Ef42f520fBB98, token=0x6810e776880C02933D47DB1b9fc05908e5386b96, amount=11155352250000000000 )
-
File 1 of 3: GnosisToken
File 2 of 3: Controller
File 3 of 3: DefaultSweeper
pragma solidity 0.4.10;
/// @title Abstract token contract - Functions to be implemented by token contracts.
contract Token {
function transfer(address to, uint256 value) returns (bool success);
function transferFrom(address from, address to, uint256 value) returns (bool success);
function approve(address spender, uint256 value) returns (bool success);
// This is not an abstract function, because solc won't recognize generated getter functions for public variables as functions.
function totalSupply() constant returns (uint256 supply) {}
function balanceOf(address owner) constant returns (uint256 balance);
function allowance(address owner, address spender) constant returns (uint256 remaining);
event Transfer(address indexed from, address indexed to, uint256 value);
event Approval(address indexed owner, address indexed spender, uint256 value);
}
/// @title Standard token contract - Standard token interface implementation.
contract StandardToken is Token {
/*
* Data structures
*/
mapping (address => uint256) balances;
mapping (address => mapping (address => uint256)) allowed;
uint256 public totalSupply;
/*
* Public functions
*/
/// @dev Transfers sender's tokens to a given address. Returns success.
/// @param _to Address of token receiver.
/// @param _value Number of tokens to transfer.
/// @return Returns success of function call.
function transfer(address _to, uint256 _value)
public
returns (bool)
{
if (balances[msg.sender] < _value) {
// Balance too low
throw;
}
balances[msg.sender] -= _value;
balances[_to] += _value;
Transfer(msg.sender, _to, _value);
return true;
}
/// @dev Allows allowed third party to transfer tokens from one address to another. Returns success.
/// @param _from Address from where tokens are withdrawn.
/// @param _to Address to where tokens are sent.
/// @param _value Number of tokens to transfer.
/// @return Returns success of function call.
function transferFrom(address _from, address _to, uint256 _value)
public
returns (bool)
{
if (balances[_from] < _value || allowed[_from][msg.sender] < _value) {
// Balance or allowance too low
throw;
}
balances[_to] += _value;
balances[_from] -= _value;
allowed[_from][msg.sender] -= _value;
Transfer(_from, _to, _value);
return true;
}
/// @dev Sets approved amount of tokens for spender. Returns success.
/// @param _spender Address of allowed account.
/// @param _value Number of approved tokens.
/// @return Returns success of function call.
function approve(address _spender, uint256 _value)
public
returns (bool)
{
allowed[msg.sender][_spender] = _value;
Approval(msg.sender, _spender, _value);
return true;
}
/*
* Read functions
*/
/// @dev Returns number of allowed tokens for given address.
/// @param _owner Address of token owner.
/// @param _spender Address of token spender.
/// @return Returns remaining allowance for spender.
function allowance(address _owner, address _spender)
constant
public
returns (uint256)
{
return allowed[_owner][_spender];
}
/// @dev Returns number of tokens owned by given address.
/// @param _owner Address of token owner.
/// @return Returns balance of owner.
function balanceOf(address _owner)
constant
public
returns (uint256)
{
return balances[_owner];
}
}
/// @title Gnosis token contract
/// @author Stefan George - <stefan.george@consensys.net>
contract GnosisToken is StandardToken {
/*
* Token meta data
*/
string constant public name = "Gnosis Token";
string constant public symbol = "GNO";
uint8 constant public decimals = 18;
/*
* Public functions
*/
/// @dev Contract constructor function sets dutch auction contract address and assigns all tokens to dutch auction.
/// @param dutchAuction Address of dutch auction contract.
/// @param owners Array of addresses receiving preassigned tokens.
/// @param tokens Array of preassigned token amounts.
function GnosisToken(address dutchAuction, address[] owners, uint[] tokens)
public
{
if (dutchAuction == 0)
// Address should not be null.
throw;
totalSupply = 10000000 * 10**18;
balances[dutchAuction] = 9000000 * 10**18;
Transfer(0, dutchAuction, balances[dutchAuction]);
uint assignedTokens = balances[dutchAuction];
for (uint i=0; i<owners.length; i++) {
if (owners[i] == 0)
// Address should not be null.
throw;
balances[owners[i]] += tokens[i];
Transfer(0, owners[i], tokens[i]);
assignedTokens += tokens[i];
}
if (assignedTokens != totalSupply)
throw;
}
}File 2 of 3: Controller
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);
}
}File 3 of 3: DefaultSweeper
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);
}
}