Transaction Hash:
Block:
3909822 at Jun-21-2017 08:55:04 PM +UTC
Transaction Fee:
0.010731075 ETH
$22.71
Gas Used:
143,081 Gas / 75 Gwei
Emitted Events:
| 5 |
Controller.LogNewWallet( receiver=0xb089d5935287047ec60cebf79d33648ff6c3dee5 )
|
Account State Difference:
| Address | Before | After | State Difference | ||
|---|---|---|---|---|---|
|
0x829BD824...93333A830
Miner
| (F2Pool Old) | 2,495.678576222769452957 Eth | 2,495.689307297769452957 Eth | 0.010731075 | |
| 0xb089D593...FF6c3dEE5 |
0 Eth
Nonce: 0
|
0 Eth
Nonce: 1
| |||
| 0xEdcE8831...94d75B3a0 | (Bittrex: Controller V1) | ||||
| 0xFBb1b73C...f520fBB98 | (Bittrex) |
156,929.692080269563440621 Eth
Nonce: 347939
|
156,929.681349194563440621 Eth
Nonce: 347940
| 0.010731075 |
Execution Trace
Controller.CALL( )
-
0xb089d5935287047ec60cebf79d33648ff6c3dee5.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);
}
}