Transaction Hash:
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 | ||
---|---|---|---|---|---|
0x5A0b54D5...D3E029c4c
Miner
| (Spark Pool) | 4.286389542438442801 Eth | 4.288287116358442801 Eth | 0.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
|
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); } }