Transaction Hash:
Block:
3910361 at Jun-21-2017 11:31:24 PM +UTC
Transaction Fee:
0.010731075 ETH
$21.51
Gas Used:
143,081 Gas / 75 Gwei
Emitted Events:
| 13 |
Controller.LogNewWallet( receiver=0x890fb297ce204fbdf78a2e384a30d613f80c7267 )
|
Account State Difference:
| Address | Before | After | State Difference | ||
|---|---|---|---|---|---|
|
0x2a65Aca4...135398226
Miner
| (DwarfPool) | 10,046.185940433026299163 Eth | 10,046.196671508026299163 Eth | 0.010731075 | |
| 0x890FB297...3F80C7267 |
0 Eth
Nonce: 0
|
0 Eth
Nonce: 1
| |||
| 0xEdcE8831...94d75B3a0 | (Bittrex: Controller V1) | ||||
| 0xFBb1b73C...f520fBB98 | (Bittrex) |
163,438.188493022113725403 Eth
Nonce: 349986
|
163,438.177761947113725403 Eth
Nonce: 349987
| 0.010731075 |
Execution Trace
Controller.CALL( )
-
0x890fb297ce204fbdf78a2e384a30d613f80c7267.60606040( )
pragma solidity ^0.4.4;
//copyright 2017 NewAlchemy
//Written by Dennis Peterson
contract AbstractSweeper {
//abstract:
function sweep(address token, uint amount) returns (bool);
//concrete:
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) {return 0;}
function transfer(address a, uint val) returns (bool) {return false;}
}
contract DefaultSweeper is AbstractSweeper {
function DefaultSweeper(address controller)
AbstractSweeper(controller) {}
function sweep(address _token, uint _amount)
canSweep
returns (bool) {
Token token = Token(_token);
uint amount = _amount;
if (amount > token.balanceOf(this)) {
return false;
}
address destination = controller.destination();
// Because sweep is called with delegatecall, this typically
// comes from the UserWallet.
bool success = token.transfer(destination, amount);
if (success) {
controller.logSweep(this, _token, _amount);
}
return success;
}
}
contract UserWallet {
AbstractSweeperList c;
function UserWallet(address _sweeperlist) {
c = AbstractSweeperList(_sweeperlist);
}
function sweep(address _token, uint _amount)
returns (bool) {
return c.sweeperOf(_token).delegatecall(msg.data);
}
}
contract AbstractSweeperList {
function sweeperOf(address _token) returns (address);
}
contract Controller is AbstractSweeperList {
address public owner;
address public authorizedCaller;
//destination defaults to same as owner
//but is separate to allow never exposing cold storage
address public destination;
bool public halted;
event LogNewWallet(address receiver);
event LogSweep(address from, address 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);
}
//assuming halt because caller is compromised
//so let caller stop for speed, only owner can restart
function halt() onlyAdmins {
halted = true;
}
function start() onlyOwner {
halted = false;
}
//***********
//SweeperList
//***********
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 token, uint amount) {
LogSweep(from, token, amount);
}
}