Back to HomeDeployer 0x6bdd15...e1ef20 Deployment Block 6,408,967 Deployment Date Sep 27, 2018, 12:09 PM Code Size 971.0 B Gas at Deploy 359,389
Deployed September 27, 2018 (7 years ago)Block 6,408,967
This contract is not yet documented
Know something about this contract? Switch to the History tab and suggest an edit to help preserve Ethereum history.
Byzantium EraVerified Source
Key Facts
Deployment Transaction: 0x881357fe019261d7...998aedbb3c14758f
Heuristic Analysis
The following characteristics were detected through bytecode analysis and may not be accurate.
Detected Type: Unclassified
Byzantium Era
First Metropolis hard fork. Added zk-SNARK precompiles, REVERT opcode, and staticcall.
Block span: 4,370,000 — 7,279,999
October 16, 2017 — February 28, 2019
Bytecode Overview
Opcodes971
Unique Opcodes130
Jump Instructions44
Storage Operations7
Verified Source Available
This contract has verified source code on Etherscan.
Show source code (Solidity)
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);
}
}External Links
Related contracts
SmartWallet
Same deployerBancor-lineage per-user withdrawal wallet, first of 7,847 identical siblings from Sep 2018. Source verified by EthereumHistory via linked-library bytecode match.
0xfc247c...bea350September 27, 2018MetaPunk
Same eraA June 2018 ERC-721 built to represent CryptoPunks, holding none. It has minted 9,640 tokens while the punks contract it points at is not the real one.
0x0144b7...50c9dfJune 23, 2018