ETH Price: $2,427.44 (-1.32%)

Transaction Decoder

Block:
9039266 at Dec-02-2019 05:33:40 PM +UTC
Transaction Fee:
0.00189757392 ETH $4.61
Gas Used:
359,389 Gas / 5.28 Gwei

Account State Difference:

  Address   Before After State Difference Code
(Spark Pool)
4.286389542438442801 Eth4.288287116358442801 Eth0.00189757392
0x6bDd15d2...cF7E1Ef20
1.945670328999731323 Eth
Nonce: 9770
1.943772755079731323 Eth
Nonce: 9771
0.00189757392
0x8814Ef83...4AF85b106
0 Eth
Nonce: 0
0 Eth
Nonce: 1
From: 0 To: 9490744359835591335685194031242098318086894947643761222607283797392076464181437770819392204415944127781119593210848853154207386388928868994105922290686738497311113706381655156697950662444168365077802504063109965874897217191432756434607980605508972017764350370594248864261037727223209987533587369402261431525187434428345291799784572118434682154889261945336991645710209773719767614151842666298071388892252792143863915024024796501754278210299949195608766118893351150902463268671986339446558698692133618279224776859297807582642485832089978143002233863741796809744897238291035926373795626739692525536381028560960849374440712481071182508889353289029720956398521804825926197733505604553164837438553136871642641537702191469346398309553369249807773018269623642597407700528675438243006804563705047334481175461157872105175922001212076652641331937172206687797674915102779544461051729592252297713784813136506262320833615042470562735026824584435164255194544041475150541235450031416457277886794730305434612462278815208342055032854064741055423725585062182426545948137513948308849875705606416323357460313589217975738625298276311832854349780508037111379377426637190189684427930868416206963932600639007742592126116665899713691413031499409475167474451407915715832610226042448503943578153374411302013043448488438933926347776692638006076894499810850044557686822365978000706386394951333602945020247504946931429005716149866152214164251294948099534502026777670948006545413818295064164194690762189161025811525711652528579246154883200178769369437172619825379296899831405388588241861731263289446461041011664122183315669992542136611215409995172547154289470116007001316430387822351148340019621728669739648944635829585245687548583603001130720364147453838549434485666532119450741681263025478720644789816256581906432851734422727470165111175056838370793743196380369533908024482316942331505364534910173823628942960225269707625585505840106356019975172336078307073856545000658195520952459198791037323056636203009515655398446090493332618407100624213209758646936008036597070324868087146127799823175404237506401247963599751472191282653764634662470555669501272848722349968859645737767310467811071883571052474484834246346266412790278545749044631580440993683851137491391365834518085770773906967552812488906849334154863030136345048046403928822042325423838887261560531827420921266217

Execution Trace

SmartWallet.60806040( )
  • 0x74ba8c8f53809bd3baa0c243350cb989f6c9dc3c.5b73e840( )
    pragma solidity ^0.4.24;
    
    contract IERC20Token {
        // these functions aren't abstract since the compiler emits automatically generated getter functions as external
        function name() public constant returns (string) {}
        function symbol() public constant returns (string) {}
        function decimals() public constant returns (uint8) {}
        function totalSupply() public constant returns (uint256) {}
        function balanceOf(address _owner) public constant returns (uint256) { _owner; }
        function allowance(address _owner, address _spender) public constant returns (uint256) { _owner; _spender; }
    
        function transfer(address _to, uint256 _value) public returns (bool success);
        function transferFrom(address _from, address _to, uint256 _value) public returns (bool success);
        function approve(address _spender, uint256 _value) public returns (bool success);
    }
    
    contract Ownable {
        address public owner;
        address public newOwner;
    
        event OwnerUpdate(address _prevOwner, address _newOwner);
    
        /*
            @dev constructor
        */
        constructor (address _owner) public {
            owner = _owner;
        }
    
        /*
            @dev allows execution by the owner only
        */
        modifier ownerOnly {
            require(msg.sender == owner);
            _;
        }
    
        /*
            @dev allows transferring the contract ownership
            the new owner still needs to accept the transfer
            can only be called by the contract owner
    
            @param _newOwner    new contract owner
        */
        function transferOwnership(address _newOwner) public ownerOnly {
            require(_newOwner != owner);
            newOwner = _newOwner;
        }
    
        /*
            @dev used by a new owner to accept an ownership transfer
        */
        function acceptOwnership() public {
            require(msg.sender == newOwner);
            emit OwnerUpdate(owner, newOwner);
            owner = newOwner;
            newOwner = address(0);
        }
    }
    
    contract Utils {
        /*
            @dev constructor
        */
        constructor() public {
        }
    
        /*
            @dev verifies that an amount is greater than zero
        */
        modifier greaterThanZero(uint256 _amount) {
            require(_amount > 0);
            _;
        }
    
        /*
            @dev validates an address - currently only checks that it isn't null
        */
        modifier validAddress(address _address) {
            require(_address != 0x0);
            _;
        }
    
        /*
            @dev verifies that the address is different than this contract address
        */
        modifier notThis(address _address) {
            require(_address != address(this));
            _;
        }
    
        /*
            @dev verifies that the string is not empty
        */
        modifier notEmpty(string _str) {
            require(bytes(_str).length > 0);
            _;
        }
    
        // Overflow protected math functions
    
        /*
            @dev returns the sum of _x and _y, asserts if the calculation overflows
    
            @param _x   value 1
            @param _y   value 2
    
            @return sum
        */
        function safeAdd(uint256 _x, uint256 _y) internal pure returns (uint256) {
            uint256 z = _x + _y;
            assert(z >= _x);
            return z;
        }
    
        /*
            @dev returns the difference of _x minus _y, asserts if the subtraction results in a negative number
    
            @param _x   minuend
            @param _y   subtrahend
    
            @return difference
        */
        function safeSub(uint256 _x, uint256 _y) internal pure returns (uint256) {
            require(_x >= _y);
            return _x - _y;
        }
    
        /*
            @dev returns the product of multiplying _x by _y, asserts if the calculation overflows
    
            @param _x   factor 1
            @param _y   factor 2
    
            @return product
        */
        function safeMul(uint256 _x, uint256 _y) internal pure returns (uint256) {
            uint256 z = _x * _y;
            assert(_x == 0 || z / _x == _y);
            return z;
        }
    }
    
    contract WithdrawalConfigurations is Ownable, Utils {
        
        /*
         *  Members
         */
    
        uint public      minWithdrawalCoolingPeriod;
        uint constant    maxWithdrawalCoolingPeriod = 12 * 1 weeks; // = 14515200 seconds
        uint public      withdrawalCoolingPeriod;
       
        /*
         *  Events
         */
        event WithdrawalRequested(address _sender, address _smartWallet);
        event SetWithdrawalCoolingPeriod(uint _withdrawalCoolingPeriod);
    
        /*
            @dev constructor
    
            @param _withdrawalCoolingPeriod       The cooling period 
            @param _minWithdrawalCoolingPeriod    The minimum time from withdraw request to allow performing it
    
        */
        constructor (uint _withdrawalCoolingPeriod, uint _minWithdrawalCoolingPeriod) 
            Ownable(msg.sender)
            public
            {
                require(_withdrawalCoolingPeriod <= maxWithdrawalCoolingPeriod &&
                        _withdrawalCoolingPeriod >= _minWithdrawalCoolingPeriod);
                require(_minWithdrawalCoolingPeriod >= 0);
    
                minWithdrawalCoolingPeriod = _minWithdrawalCoolingPeriod;
                withdrawalCoolingPeriod = _withdrawalCoolingPeriod;
           }
    
        /*
            @dev Get the withdrawalCoolingPeriod parameter value. 
       
         */
        function getWithdrawalCoolingPeriod() external view returns(uint) {
            return withdrawalCoolingPeriod;
        }
    
        /*
            @dev Set the withdrawalCoolingPeriod parameter value. 
    
            @param _withdrawalCoolingPeriod   Cooling period in seconds
         */
        function setWithdrawalCoolingPeriod(uint _withdrawalCoolingPeriod)
            ownerOnly()
            public
            {
                require (_withdrawalCoolingPeriod <= maxWithdrawalCoolingPeriod &&
                         _withdrawalCoolingPeriod >= minWithdrawalCoolingPeriod);
                withdrawalCoolingPeriod = _withdrawalCoolingPeriod;
                emit SetWithdrawalCoolingPeriod(_withdrawalCoolingPeriod);
        }
    
        /*
            @dev Fire the WithdrawalRequested event. 
    
            @param _sender          The user account, activating this request
            @param _smartWallet     The smart wallet that the request was called upon   
         */
        function emitWithrawalRequestEvent(address _sender, address _smartWallet) 
            public
            {
                emit WithdrawalRequested(_sender, _smartWallet);
        }
    }
    
    library SmartWalletLib {
    
        /*
         *  Structs
         */ 
        struct Wallet {
            address operatorAccount;
            address userWithdrawalAccount;
            address feesAccount;
            uint    withdrawAllowedAt; // In seconds
        }
    
        /*
         *  Members
         */
        string constant VERSION = "1.1";
        address constant withdrawalConfigurationsContract = 0xDdD336eAad17F1D40cc81997Fb956608f00639FF; 
        
        /*
         *  Modifiers
         */
        modifier validAddress(address _address) {
            require(_address != 0x0);
            _;
        }
    
        modifier addressNotSet(address _address) {
            require(_address == 0);
            _;
        }
    
        modifier operatorOnly(address _operatorAccount) {
            require(msg.sender == _operatorAccount);
            _;
        }
    
        modifier userWithdrawalAccountOnly(Wallet storage _self) {
            require(msg.sender == _self.userWithdrawalAccount);
            _;
        }
    
        /*
         *  Events
         */
        event TransferToUserWithdrawalAccount(address _token, address _userWithdrawalAccount, uint _amount, address _feesToken, address _feesAccount, uint _fee);
        event SetUserWithdrawalAccount(address _userWithdrawalAccount);
        event PerformUserWithdraw(address _token, address _userWithdrawalAccount, uint _amount);
        
        /*
            @dev Initialize the wallet with the operator and backupAccount address
            
            @param _self                        Wallet storage
            @param _operator                    The operator account
            @param _feesAccount                 The account to transfer fees to
        */
        function initWallet(Wallet storage _self, address _operator, address _feesAccount) 
                public
                validAddress(_operator)
                validAddress(_feesAccount)
                {
            
                    _self.operatorAccount = _operator;
                    _self.feesAccount = _feesAccount;
        }
    
        /*
            @dev Setting the account of the user to send funds to. 
            
            @param _self                        Wallet storage
            @param _userWithdrawalAccount       The user account to withdraw funds to
        */
        function setUserWithdrawalAccount(Wallet storage _self, address _userWithdrawalAccount) 
                public
                operatorOnly(_self.operatorAccount)
                validAddress(_userWithdrawalAccount)
                addressNotSet(_self.userWithdrawalAccount)
                {
            
                    _self.userWithdrawalAccount = _userWithdrawalAccount;
                    emit SetUserWithdrawalAccount(_userWithdrawalAccount);
        }
        
        /*
            @dev Withdraw funds to the user account. 
    
            @param _self                Wallet storage
            @param _token               The ERC20 token the owner withdraws from 
            @param _amount              Amount to transfer  
            @param _fee                 Fee to transfer   
        */
        function transferToUserWithdrawalAccount(Wallet storage _self, IERC20Token _token, uint _amount, IERC20Token _feesToken, uint _fee) 
                public 
                operatorOnly(_self.operatorAccount)
                validAddress(_self.userWithdrawalAccount)
                {
    
                    if (_fee > 0) {        
                        _feesToken.transfer(_self.feesAccount, _fee); 
                    }       
                    
                    _token.transfer(_self.userWithdrawalAccount, _amount);
                    emit TransferToUserWithdrawalAccount(_token, _self.userWithdrawalAccount, _amount,  _feesToken, _self.feesAccount, _fee);   
            
        }
    
        /*
            @dev returns the sum of _x and _y, asserts if the calculation overflows
    
            @param _x   value 1
            @param _y   value 2
    
            @return sum
        */
        function safeAdd(uint256 _x, uint256 _y) internal pure returns (uint256) {
            uint256 z = _x + _y;
            assert(z >= _x);
            return z;
        }
        
        /*
            @dev user request withdraw. 
    
            @param _self                Wallet storage
            @param _token               The ERC20 token the owner withdraws from 
            
        */
        function requestWithdraw(Wallet storage _self) 
            public 
            userWithdrawalAccountOnly(_self)
            {
                
                WithdrawalConfigurations withdrawalConfigurations = WithdrawalConfigurations(withdrawalConfigurationsContract);
                
                _self.withdrawAllowedAt = safeAdd(now, withdrawalConfigurations.getWithdrawalCoolingPeriod());
    
                withdrawalConfigurations.emitWithrawalRequestEvent(msg.sender, address(this));
        }
    
        /*
            @dev user perform withdraw. 
    
            @param _self                Wallet storage
            @param _token               The ERC20 token the owner withdraws from 
            
        */
        function performUserWithdraw(Wallet storage _self, IERC20Token _token)
            public
            userWithdrawalAccountOnly(_self)
            {
                require(_self.withdrawAllowedAt != 0 &&
                        _self.withdrawAllowedAt <= now );
    
                uint userBalance = _token.balanceOf(this);
                _token.transfer(_self.userWithdrawalAccount, userBalance);
                emit PerformUserWithdraw(_token, _self.userWithdrawalAccount, userBalance);   
            }
    
    }
    
    contract SmartWallet {
    
        /*
         *  Members
         */
        using SmartWalletLib for SmartWalletLib.Wallet;
        SmartWalletLib.Wallet public wallet;
           
       // Wallet public wallet;
        /*
         *  Events
         */
        event TransferToUserWithdrawalAccount(address _token, address _userWithdrawalAccount, uint _amount, address _feesToken, address _feesAccount, uint _fee);
        event SetUserWithdrawalAccount(address _userWithdrawalAccount);
        event PerformUserWithdraw(address _token, address _userWithdrawalAccount, uint _amount);
         
        /*
            @dev constructor
    
            @param _backupAccount       A default operator's account to send funds to, in cases where the user account is
                                        unavailable or lost
            @param _operator            The contract operator address
            @param _feesAccount         The account to transfer fees to 
    
        */
        constructor (address _operator, address _feesAccount) public {
            wallet.initWallet(_operator, _feesAccount);
        }
    
        /*
            @dev Setting the account of the user to send funds to. 
            
            @param _userWithdrawalAccount       The user account to withdraw funds to
            
        */
        function setUserWithdrawalAccount(address _userWithdrawalAccount) public {
            wallet.setUserWithdrawalAccount(_userWithdrawalAccount);
        }
    
        /*
            @dev Withdraw funds to the user account. 
    
    
            @param _token               The ERC20 token the owner withdraws from 
            @param _amount              Amount to transfer    
        */
        function transferToUserWithdrawalAccount(IERC20Token _token, uint _amount, IERC20Token _feesToken, uint _fee) public {
            wallet.transferToUserWithdrawalAccount(_token, _amount, _feesToken, _fee);
        }
    
        /*
            @dev Allows the user to request a withdraw of his/her placements
            
            @param _token               The ERC20 token the user wishes to withdraw from 
        */
        function requestWithdraw() public {
            wallet.requestWithdraw();
        }
    
        /*
            @dev Allows the user to perform the requestWithdraw operation
            
            @param _token               The ERC20 token the user withdraws from 
        */
        function performUserWithdraw(IERC20Token _token) public {
            wallet.performUserWithdraw(_token);
        }
    }