More Info
Private Name Tags
ContractCreator
Latest 25 from a total of 33,657 transactions
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Execute | 18732628 | 388 days ago | IN | 0 ETH | 0.0056941 | ||||
Execute | 14881066 | 942 days ago | IN | 0 ETH | 0.01712422 | ||||
Execute | 14257541 | 1040 days ago | IN | 0 ETH | 0.00667073 | ||||
Confirm Guardian... | 13819567 | 1108 days ago | IN | 0 ETH | 0.0080913 | ||||
Execute | 13813119 | 1109 days ago | IN | 0 ETH | 0.00832407 | ||||
Execute | 13813111 | 1109 days ago | IN | 0 ETH | 0.01113728 | ||||
Confirm Guardian... | 13589860 | 1145 days ago | IN | 0 ETH | 0.01790212 | ||||
Execute | 13583525 | 1146 days ago | IN | 0 ETH | 0.02390021 | ||||
Execute | 13477654 | 1162 days ago | IN | 0 ETH | 0.00938465 | ||||
Confirm Guardian... | 13404516 | 1174 days ago | IN | 0 ETH | 0.01036103 | ||||
Confirm Guardian... | 13404492 | 1174 days ago | IN | 0 ETH | 0.00468286 | ||||
Execute | 13398152 | 1175 days ago | IN | 0 ETH | 0.0099828 | ||||
Execute | 13398138 | 1175 days ago | IN | 0 ETH | 0.01134928 | ||||
Confirm Guardian... | 13223121 | 1202 days ago | IN | 0 ETH | 0.00288287 | ||||
Execute | 13216658 | 1203 days ago | IN | 0 ETH | 0.00531646 | ||||
Execute | 12491293 | 1316 days ago | IN | 0 ETH | 0.0159075 | ||||
Confirm Guardian... | 12426591 | 1326 days ago | IN | 0 ETH | 0.01185887 | ||||
Execute | 12420087 | 1327 days ago | IN | 0 ETH | 0.03760066 | ||||
Execute | 12309882 | 1344 days ago | IN | 0 ETH | 0.00644035 | ||||
Confirm Guardian... | 12302233 | 1345 days ago | IN | 0 ETH | 0.00484854 | ||||
Execute | 12295781 | 1346 days ago | IN | 0 ETH | 0.01040342 | ||||
Execute | 12291603 | 1346 days ago | IN | 0 ETH | 0.02096265 | ||||
Execute | 11919644 | 1404 days ago | IN | 0 ETH | 0.00933369 | ||||
Confirm Guardian... | 11908839 | 1405 days ago | IN | 0 ETH | 0.01094619 | ||||
Execute | 11902256 | 1406 days ago | IN | 0 ETH | 0.01669099 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Contract Name:
GuardianManager
Compiler Version
v0.4.24+commit.e67f0147
Optimization Enabled:
Yes with 999 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity)
/** *Submitted for verification at Etherscan.io on 2019-02-05 */ pragma solidity ^0.4.24; /** * @title Module * @dev Interface for a module. * A module MUST implement the addModule() method to ensure that a wallet with at least one module * can never end up in a "frozen" state. * @author Julien Niset - <[email protected]> */ interface Module { /** * @dev Inits a module for a wallet by e.g. setting some wallet specific parameters in storage. * @param _wallet The wallet. */ function init(BaseWallet _wallet) external; /** * @dev Adds a module to a wallet. * @param _wallet The target wallet. * @param _module The modules to authorise. */ function addModule(BaseWallet _wallet, Module _module) external; /** * @dev Utility method to recover any ERC20 token that was sent to the * module by mistake. * @param _token The token to recover. */ function recoverToken(address _token) external; } /** * @title BaseModule * @dev Basic module that contains some methods common to all modules. * @author Julien Niset - <[email protected]> */ contract BaseModule is Module { // The adddress of the module registry. ModuleRegistry internal registry; event ModuleCreated(bytes32 name); event ModuleInitialised(address wallet); constructor(ModuleRegistry _registry, bytes32 _name) public { registry = _registry; emit ModuleCreated(_name); } /** * @dev Throws if the sender is not the target wallet of the call. */ modifier onlyWallet(BaseWallet _wallet) { require(msg.sender == address(_wallet), "BM: caller must be wallet"); _; } /** * @dev Throws if the sender is not the owner of the target wallet or the module itself. */ modifier onlyOwner(BaseWallet _wallet) { require(msg.sender == address(this) || isOwner(_wallet, msg.sender), "BM: must be an owner for the wallet"); _; } /** * @dev Throws if the sender is not the owner of the target wallet. */ modifier strictOnlyOwner(BaseWallet _wallet) { require(isOwner(_wallet, msg.sender), "BM: msg.sender must be an owner for the wallet"); _; } /** * @dev Inits the module for a wallet by logging an event. * The method can only be called by the wallet itself. * @param _wallet The wallet. */ function init(BaseWallet _wallet) external onlyWallet(_wallet) { emit ModuleInitialised(_wallet); } /** * @dev Adds a module to a wallet. First checks that the module is registered. * @param _wallet The target wallet. * @param _module The modules to authorise. */ function addModule(BaseWallet _wallet, Module _module) external strictOnlyOwner(_wallet) { require(registry.isRegisteredModule(_module), "BM: module is not registered"); _wallet.authoriseModule(_module, true); } /** * @dev Utility method enbaling anyone to recover ERC20 token sent to the * module by mistake and transfer them to the Module Registry. * @param _token The token to recover. */ function recoverToken(address _token) external { uint total = ERC20(_token).balanceOf(address(this)); ERC20(_token).transfer(address(registry), total); } /** * @dev Helper method to check if an address is the owner of a target wallet. * @param _wallet The target wallet. * @param _addr The address. */ function isOwner(BaseWallet _wallet, address _addr) internal view returns (bool) { return _wallet.owner() == _addr; } } /** * @title RelayerModule * @dev Base module containing logic to execute transactions signed by eth-less accounts and sent by a relayer. * @author Julien Niset - <[email protected]> */ contract RelayerModule is Module { uint256 constant internal BLOCKBOUND = 10000; mapping (address => RelayerConfig) public relayer; struct RelayerConfig { uint256 nonce; mapping (bytes32 => bool) executedTx; } event TransactionExecuted(address indexed wallet, bool indexed success, bytes32 signedHash); /** * @dev Throws if the call did not go through the execute() method. */ modifier onlyExecute { require(msg.sender == address(this), "RM: must be called via execute()"); _; } /* ***************** Abstract method ************************* */ /** * @dev Gets the number of valid signatures that must be provided to execute a * specific relayed transaction. * @param _wallet The target wallet. * @param _data The data of the relayed transaction. * @return The number of required signatures. */ function getRequiredSignatures(BaseWallet _wallet, bytes _data) internal view returns (uint256); /** * @dev Validates the signatures provided with a relayed transaction. * The method MUST throw if one or more signatures are not valid. * @param _wallet The target wallet. * @param _data The data of the relayed transaction. * @param _signHash The signed hash representing the relayed transaction. * @param _signatures The signatures as a concatenated byte array. */ function validateSignatures(BaseWallet _wallet, bytes _data, bytes32 _signHash, bytes _signatures) internal view returns (bool); /* ************************************************************ */ /** * @dev Executes a relayed transaction. * @param _wallet The target wallet. * @param _data The data for the relayed transaction * @param _nonce The nonce used to prevent replay attacks. * @param _signatures The signatures as a concatenated byte array. * @param _gasPrice The gas price to use for the gas refund. * @param _gasLimit The gas limit to use for the gas refund. */ function execute( BaseWallet _wallet, bytes _data, uint256 _nonce, bytes _signatures, uint256 _gasPrice, uint256 _gasLimit ) external returns (bool success) { uint startGas = gasleft(); bytes32 signHash = getSignHash(address(this), _wallet, 0, _data, _nonce, _gasPrice, _gasLimit); require(checkAndUpdateUniqueness(_wallet, _nonce, signHash), "RM: Duplicate request"); require(verifyData(address(_wallet), _data), "RM: the wallet authorized is different then the target of the relayed data"); uint256 requiredSignatures = getRequiredSignatures(_wallet, _data); if((requiredSignatures * 65) == _signatures.length) { if(verifyRefund(_wallet, _gasLimit, _gasPrice, requiredSignatures)) { if(requiredSignatures == 0 || validateSignatures(_wallet, _data, signHash, _signatures)) { // solium-disable-next-line security/no-call-value success = address(this).call(_data); refund(_wallet, startGas - gasleft(), _gasPrice, _gasLimit, requiredSignatures, msg.sender); } } } emit TransactionExecuted(_wallet, success, signHash); } /** * @dev Gets the current nonce for a wallet. * @param _wallet The target wallet. */ function getNonce(BaseWallet _wallet) external view returns (uint256 nonce) { return relayer[_wallet].nonce; } /** * @dev Generates the signed hash of a relayed transaction according to ERC 1077. * @param _from The starting address for the relayed transaction (should be the module) * @param _to The destination address for the relayed transaction (should be the wallet) * @param _value The value for the relayed transaction * @param _data The data for the relayed transaction * @param _nonce The nonce used to prevent replay attacks. * @param _gasPrice The gas price to use for the gas refund. * @param _gasLimit The gas limit to use for the gas refund. */ function getSignHash( address _from, address _to, uint256 _value, bytes _data, uint256 _nonce, uint256 _gasPrice, uint256 _gasLimit ) internal pure returns (bytes32) { return keccak256( abi.encodePacked( "\x19Ethereum Signed Message:\n32", keccak256(abi.encodePacked(byte(0x19), byte(0), _from, _to, _value, _data, _nonce, _gasPrice, _gasLimit)) )); } /** * @dev Checks if the relayed transaction is unique. * @param _wallet The target wallet. * @param _nonce The nonce * @param _signHash The signed hash of the transaction */ function checkAndUpdateUniqueness(BaseWallet _wallet, uint256 _nonce, bytes32 _signHash) internal returns (bool) { if(relayer[_wallet].executedTx[_signHash] == true) { return false; } relayer[_wallet].executedTx[_signHash] = true; return true; } /** * @dev Checks that a nonce has the correct format and is valid. * It must be constructed as nonce = {block number}{timestamp} where each component is 16 bytes. * @param _wallet The target wallet. * @param _nonce The nonce */ function checkAndUpdateNonce(BaseWallet _wallet, uint256 _nonce) internal returns (bool) { if(_nonce <= relayer[_wallet].nonce) { return false; } uint256 nonceBlock = (_nonce & 0xffffffffffffffffffffffffffffffff00000000000000000000000000000000) >> 128; if(nonceBlock > block.number + BLOCKBOUND) { return false; } relayer[_wallet].nonce = _nonce; return true; } /** * @dev Recovers the signer at a given position from a list of concatenated signatures. * @param _signedHash The signed hash * @param _signatures The concatenated signatures. * @param _index The index of the signature to recover. */ function recoverSigner(bytes32 _signedHash, bytes _signatures, uint _index) internal pure returns (address) { uint8 v; bytes32 r; bytes32 s; // we jump 32 (0x20) as the first slot of bytes contains the length // we jump 65 (0x41) per signature // for v we load 32 bytes ending with v (the first 31 come from s) then apply a mask // solium-disable-next-line security/no-inline-assembly assembly { r := mload(add(_signatures, add(0x20,mul(0x41,_index)))) s := mload(add(_signatures, add(0x40,mul(0x41,_index)))) v := and(mload(add(_signatures, add(0x41,mul(0x41,_index)))), 0xff) } require(v == 27 || v == 28); return ecrecover(_signedHash, v, r, s); } /** * @dev Refunds the gas used to the Relayer. * For security reasons the default behavior is to not refund calls with 0 or 1 signatures. * @param _wallet The target wallet. * @param _gasUsed The gas used. * @param _gasPrice The gas price for the refund. * @param _gasLimit The gas limit for the refund. * @param _signatures The number of signatures used in the call. * @param _relayer The address of the Relayer. */ function refund(BaseWallet _wallet, uint _gasUsed, uint _gasPrice, uint _gasLimit, uint _signatures, address _relayer) internal { uint256 amount = 29292 + _gasUsed; // 21000 (transaction) + 7620 (execution of refund) + 672 to log the event + _gasUsed // only refund if gas price not null, more than 1 signatures, gas less than gasLimit if(_gasPrice > 0 && _signatures > 1 && amount <= _gasLimit) { if(_gasPrice > tx.gasprice) { amount = amount * tx.gasprice; } else { amount = amount * _gasPrice; } _wallet.invoke(_relayer, amount, ""); } } /** * @dev Returns false if the refund is expected to fail. * @param _wallet The target wallet. * @param _gasUsed The expected gas used. * @param _gasPrice The expected gas price for the refund. */ function verifyRefund(BaseWallet _wallet, uint _gasUsed, uint _gasPrice, uint _signatures) internal view returns (bool) { if(_gasPrice > 0 && _signatures > 1 && (address(_wallet).balance < _gasUsed * _gasPrice || _wallet.authorised(this) == false)) { return false; } return true; } /** * @dev Checks that the wallet address provided as the first parameter of the relayed data is the same * as the wallet passed as the input of the execute() method. @return false if the addresses are different. */ function verifyData(address _wallet, bytes _data) private pure returns (bool) { require(_data.length >= 36, "RM: Invalid dataWallet"); address dataWallet; // solium-disable-next-line security/no-inline-assembly assembly { //_data = {length:32}{sig:4}{_wallet:32}{...} dataWallet := mload(add(_data, 0x24)) } return dataWallet == _wallet; } /** * @dev Parses the data to extract the method signature. */ function functionPrefix(bytes _data) internal pure returns (bytes4 prefix) { require(_data.length >= 4, "RM: Invalid functionPrefix"); // solium-disable-next-line security/no-inline-assembly assembly { prefix := mload(add(_data, 0x20)) } } } /** * ERC20 contract interface. */ contract ERC20 { function totalSupply() public view returns (uint); function decimals() public view returns (uint); function balanceOf(address tokenOwner) public view returns (uint balance); function allowance(address tokenOwner, address spender) public view returns (uint remaining); function transfer(address to, uint tokens) public returns (bool success); function approve(address spender, uint tokens) public returns (bool success); function transferFrom(address from, address to, uint tokens) public returns (bool success); } /** * @title Owned * @dev Basic contract to define an owner. * @author Julien Niset - <[email protected]> */ contract Owned { // The owner address public owner; event OwnerChanged(address indexed _newOwner); /** * @dev Throws if the sender is not the owner. */ modifier onlyOwner { require(msg.sender == owner, "Must be owner"); _; } constructor() public { owner = msg.sender; } /** * @dev Lets the owner transfer ownership of the contract to a new owner. * @param _newOwner The new owner. */ function changeOwner(address _newOwner) external onlyOwner { require(_newOwner != address(0), "Address must not be null"); owner = _newOwner; emit OwnerChanged(_newOwner); } } /** * @title ModuleRegistry * @dev Registry of authorised modules. * Modules must be registered before they can be authorised on a wallet. * @author Julien Niset - <[email protected]> */ contract ModuleRegistry is Owned { mapping (address => Info) internal modules; mapping (address => Info) internal upgraders; event ModuleRegistered(address indexed module, bytes32 name); event ModuleDeRegistered(address module); event UpgraderRegistered(address indexed upgrader, bytes32 name); event UpgraderDeRegistered(address upgrader); struct Info { bool exists; bytes32 name; } /** * @dev Registers a module. * @param _module The module. * @param _name The unique name of the module. */ function registerModule(address _module, bytes32 _name) external onlyOwner { require(!modules[_module].exists, "MR: module already exists"); modules[_module] = Info({exists: true, name: _name}); emit ModuleRegistered(_module, _name); } /** * @dev Deregisters a module. * @param _module The module. */ function deregisterModule(address _module) external onlyOwner { require(modules[_module].exists, "MR: module does not exists"); delete modules[_module]; emit ModuleDeRegistered(_module); } /** * @dev Registers an upgrader. * @param _upgrader The upgrader. * @param _name The unique name of the upgrader. */ function registerUpgrader(address _upgrader, bytes32 _name) external onlyOwner { require(!upgraders[_upgrader].exists, "MR: upgrader already exists"); upgraders[_upgrader] = Info({exists: true, name: _name}); emit UpgraderRegistered(_upgrader, _name); } /** * @dev Deregisters an upgrader. * @param _upgrader The _upgrader. */ function deregisterUpgrader(address _upgrader) external onlyOwner { require(upgraders[_upgrader].exists, "MR: upgrader does not exists"); delete upgraders[_upgrader]; emit UpgraderDeRegistered(_upgrader); } /** * @dev Utility method enbaling the owner of the registry to claim any ERC20 token that was sent to the * registry. * @param _token The token to recover. */ function recoverToken(address _token) external onlyOwner { uint total = ERC20(_token).balanceOf(address(this)); ERC20(_token).transfer(msg.sender, total); } /** * @dev Gets the name of a module from its address. * @param _module The module address. * @return the name. */ function moduleInfo(address _module) external view returns (bytes32) { return modules[_module].name; } /** * @dev Gets the name of an upgrader from its address. * @param _upgrader The upgrader address. * @return the name. */ function upgraderInfo(address _upgrader) external view returns (bytes32) { return upgraders[_upgrader].name; } /** * @dev Checks if a module is registered. * @param _module The module address. * @return true if the module is registered. */ function isRegisteredModule(address _module) external view returns (bool) { return modules[_module].exists; } /** * @dev Checks if a list of modules are registered. * @param _modules The list of modules address. * @return true if all the modules are registered. */ function isRegisteredModule(address[] _modules) external view returns (bool) { for(uint i = 0; i < _modules.length; i++) { if (!modules[_modules[i]].exists) { return false; } } return true; } /** * @dev Checks if an upgrader is registered. * @param _upgrader The upgrader address. * @return true if the upgrader is registered. */ function isRegisteredUpgrader(address _upgrader) external view returns (bool) { return upgraders[_upgrader].exists; } } /** * @title BaseWallet * @dev Simple modular wallet that authorises modules to call its invoke() method. * Based on https://gist.github.com/Arachnid/a619d31f6d32757a4328a428286da186 by * @author Julien Niset - <[email protected]> */ contract BaseWallet { // The implementation of the proxy address public implementation; // The owner address public owner; // The authorised modules mapping (address => bool) public authorised; // The enabled static calls mapping (bytes4 => address) public enabled; // The number of modules uint public modules; event AuthorisedModule(address indexed module, bool value); event EnabledStaticCall(address indexed module, bytes4 indexed method); event Invoked(address indexed module, address indexed target, uint indexed value, bytes data); event Received(uint indexed value, address indexed sender, bytes data); event OwnerChanged(address owner); /** * @dev Throws if the sender is not an authorised module. */ modifier moduleOnly { require(authorised[msg.sender], "BW: msg.sender not an authorized module"); _; } /** * @dev Inits the wallet by setting the owner and authorising a list of modules. * @param _owner The owner. * @param _modules The modules to authorise. */ function init(address _owner, address[] _modules) external { require(owner == address(0) && modules == 0, "BW: wallet already initialised"); require(_modules.length > 0, "BW: construction requires at least 1 module"); owner = _owner; modules = _modules.length; for(uint256 i = 0; i < _modules.length; i++) { require(authorised[_modules[i]] == false, "BW: module is already added"); authorised[_modules[i]] = true; Module(_modules[i]).init(this); emit AuthorisedModule(_modules[i], true); } } /** * @dev Enables/Disables a module. * @param _module The target module. * @param _value Set to true to authorise the module. */ function authoriseModule(address _module, bool _value) external moduleOnly { if (authorised[_module] != _value) { if(_value == true) { modules += 1; authorised[_module] = true; Module(_module).init(this); } else { modules -= 1; require(modules > 0, "BW: wallet must have at least one module"); delete authorised[_module]; } emit AuthorisedModule(_module, _value); } } /** * @dev Enables a static method by specifying the target module to which the call * must be delegated. * @param _module The target module. * @param _method The static method signature. */ function enableStaticCall(address _module, bytes4 _method) external moduleOnly { require(authorised[_module], "BW: must be an authorised module for static call"); enabled[_method] = _module; emit EnabledStaticCall(_module, _method); } /** * @dev Sets a new owner for the wallet. * @param _newOwner The new owner. */ function setOwner(address _newOwner) external moduleOnly { require(_newOwner != address(0), "BW: address cannot be null"); owner = _newOwner; emit OwnerChanged(_newOwner); } /** * @dev Performs a generic transaction. * @param _target The address for the transaction. * @param _value The value of the transaction. * @param _data The data of the transaction. */ function invoke(address _target, uint _value, bytes _data) external moduleOnly { // solium-disable-next-line security/no-call-value require(_target.call.value(_value)(_data), "BW: call to target failed"); emit Invoked(msg.sender, _target, _value, _data); } /** * @dev This method makes it possible for the wallet to comply to interfaces expecting the wallet to * implement specific static methods. It delegates the static call to a target contract if the data corresponds * to an enabled method, or logs the call otherwise. */ function() public payable { if(msg.data.length > 0) { address module = enabled[msg.sig]; if(module == address(0)) { emit Received(msg.value, msg.sender, msg.data); } else { require(authorised[module], "BW: must be an authorised module for static call"); // solium-disable-next-line security/no-inline-assembly assembly { calldatacopy(0, 0, calldatasize()) let result := staticcall(gas, module, 0, calldatasize(), 0, 0) returndatacopy(0, 0, returndatasize()) switch result case 0 {revert(0, returndatasize())} default {return (0, returndatasize())} } } } } } /** * @title Storage * @dev Base contract for the storage of a wallet. * @author Julien Niset - <[email protected]> */ contract Storage { /** * @dev Throws if the caller is not an authorised module. */ modifier onlyModule(BaseWallet _wallet) { require(_wallet.authorised(msg.sender), "TS: must be an authorized module to call this method"); _; } } /** * @title GuardianStorage * @dev Contract storing the state of wallets related to guardians and lock. * The contract only defines basic setters and getters with no logic. Only modules authorised * for a wallet can modify its state. * @author Julien Niset - <[email protected]> * @author Olivier Van Den Biggelaar - <[email protected]> */ contract GuardianStorage is Storage { struct GuardianStorageConfig { // the list of guardians address[] guardians; // the info about guardians mapping (address => GuardianInfo) info; // the lock's release timestamp uint256 lock; // the module that set the last lock address locker; } struct GuardianInfo { bool exists; uint128 index; } // wallet specific storage mapping (address => GuardianStorageConfig) internal configs; // *************** External Functions ********************* // /** * @dev Lets an authorised module add a guardian to a wallet. * @param _wallet The target wallet. * @param _guardian The guardian to add. */ function addGuardian(BaseWallet _wallet, address _guardian) external onlyModule(_wallet) { GuardianStorageConfig storage config = configs[_wallet]; config.info[_guardian].exists = true; config.info[_guardian].index = uint128(config.guardians.push(_guardian) - 1); } /** * @dev Lets an authorised module revoke a guardian from a wallet. * @param _wallet The target wallet. * @param _guardian The guardian to revoke. */ function revokeGuardian(BaseWallet _wallet, address _guardian) external onlyModule(_wallet) { GuardianStorageConfig storage config = configs[_wallet]; address lastGuardian = config.guardians[config.guardians.length - 1]; if (_guardian != lastGuardian) { uint128 targetIndex = config.info[_guardian].index; config.guardians[targetIndex] = lastGuardian; config.info[lastGuardian].index = targetIndex; } config.guardians.length--; delete config.info[_guardian]; } /** * @dev Returns the number of guardians for a wallet. * @param _wallet The target wallet. * @return the number of guardians. */ function guardianCount(BaseWallet _wallet) external view returns (uint256) { return configs[_wallet].guardians.length; } /** * @dev Gets the list of guaridans for a wallet. * @param _wallet The target wallet. * @return the list of guardians. */ function getGuardians(BaseWallet _wallet) external view returns (address[]) { GuardianStorageConfig storage config = configs[_wallet]; address[] memory guardians = new address[](config.guardians.length); for (uint256 i = 0; i < config.guardians.length; i++) { guardians[i] = config.guardians[i]; } return guardians; } /** * @dev Checks if an account is a guardian for a wallet. * @param _wallet The target wallet. * @param _guardian The account. * @return true if the account is a guardian for a wallet. */ function isGuardian(BaseWallet _wallet, address _guardian) external view returns (bool) { return configs[_wallet].info[_guardian].exists; } /** * @dev Lets an authorised module set the lock for a wallet. * @param _wallet The target wallet. * @param _releaseAfter The epoch time at which the lock should automatically release. */ function setLock(BaseWallet _wallet, uint256 _releaseAfter) external onlyModule(_wallet) { configs[_wallet].lock = _releaseAfter; if(_releaseAfter != 0 && msg.sender != configs[_wallet].locker) { configs[_wallet].locker = msg.sender; } } /** * @dev Checks if the lock is set for a wallet. * @param _wallet The target wallet. * @return true if the lock is set for the wallet. */ function isLocked(BaseWallet _wallet) external view returns (bool) { return configs[_wallet].lock > now; } /** * @dev Gets the time at which the lock of a wallet will release. * @param _wallet The target wallet. * @return the time at which the lock of a wallet will release, or zero if there is no lock set. */ function getLock(BaseWallet _wallet) external view returns (uint256) { return configs[_wallet].lock; } /** * @dev Gets the address of the last module that modified the lock for a wallet. * @param _wallet The target wallet. * @return the address of the last module that modified the lock for a wallet. */ function getLocker(BaseWallet _wallet) external view returns (address) { return configs[_wallet].locker; } } library GuardianUtils { /** * @dev Checks if an address is an account guardian or an account authorised to sign on behalf of a smart-contract guardian * given a list of guardians. * @param _guardians the list of guardians * @param _guardian the address to test * @return true and the list of guardians minus the found guardian upon success, false and the original list of guardians if not found. */ function isGuardian(address[] _guardians, address _guardian) internal view returns (bool, address[]) { if(_guardians.length == 0 || _guardian == address(0)) { return (false, _guardians); } bool isFound = false; address[] memory updatedGuardians = new address[](_guardians.length - 1); uint256 index = 0; for (uint256 i = 0; i < _guardians.length; i++) { if(!isFound) { // check if _guardian is an account guardian if(_guardian == _guardians[i]) { isFound = true; continue; } // check if _guardian is the owner of a smart contract guardian if(isContract(_guardians[i]) && isGuardianOwner(_guardians[i], _guardian)) { isFound = true; continue; } } if(index < updatedGuardians.length) { updatedGuardians[index] = _guardians[i]; index++; } } return isFound ? (true, updatedGuardians) : (false, _guardians); } /** * @dev Checks if an address is a contract. * @param _addr The address. */ function isContract(address _addr) internal view returns (bool) { uint32 size; // solium-disable-next-line security/no-inline-assembly assembly { size := extcodesize(_addr) } return (size > 0); } /** * @dev Checks if an address is the owner of a guardian contract. * The method does not revert if the call to the owner() method consumes more then 5000 gas. * @param _guardian The guardian contract * @param _owner The owner to verify. */ function isGuardianOwner(address _guardian, address _owner) internal view returns (bool) { address owner = address(0); bytes4 sig = bytes4(keccak256("owner()")); // solium-disable-next-line security/no-inline-assembly assembly { let ptr := mload(0x40) mstore(ptr,sig) let result := staticcall(5000, _guardian, ptr, 0x20, ptr, 0x20) if eq(result, 1) { owner := mload(ptr) } } return owner == _owner; } } /** * @title GuardianManager * @dev Module to manage the guardians of wallets. * Guardians are accounts (EOA or contracts) that are authorized to perform specific * security operations on wallets such as toggle a safety lock, start a recovery procedure, * or confirm transactions. Addition or revokation of guardians is initiated by the owner * of a wallet and must be confirmed after a security period (e.g. 24 hours). * The list of guardians for a wallet is stored on a saparate * contract to facilitate its use by other modules. * @author Julien Niset - <[email protected]> * @author Olivier Van Den Biggelaar - <[email protected]> */ contract GuardianManager is BaseModule, RelayerModule { bytes32 constant NAME = "GuardianManager"; bytes4 constant internal CONFIRM_ADDITION_PREFIX = bytes4(keccak256("confirmGuardianAddition(address,address)")); bytes4 constant internal CONFIRM_REVOKATION_PREFIX = bytes4(keccak256("confirmGuardianRevokation(address,address)")); struct GuardianManagerConfig { // the time at which a guardian addition or revokation will be confirmable by the owner mapping (bytes32 => uint256) pending; } // the wallet specific storage mapping (address => GuardianManagerConfig) internal configs; // the address of the Guardian storage GuardianStorage public guardianStorage; // the security period uint256 public securityPeriod; // the security window uint256 public securityWindow; // *************** Events *************************** // event GuardianAdditionRequested(address indexed wallet, address indexed guardian, uint256 executeAfter); event GuardianRevokationRequested(address indexed wallet, address indexed guardian, uint256 executeAfter); event GuardianAdditionCancelled(address indexed wallet, address indexed guardian); event GuardianRevokationCancelled(address indexed wallet, address indexed guardian); event GuardianAdded(address indexed wallet, address indexed guardian); event GuardianRevoked(address indexed wallet, address indexed guardian); // *************** Modifiers ************************ // /** * @dev Throws if the wallet is not locked. */ modifier onlyWhenLocked(BaseWallet _wallet) { // solium-disable-next-line security/no-block-members require(guardianStorage.isLocked(_wallet), "GM: wallet must be locked"); _; } /** * @dev Throws if the wallet is locked. */ modifier onlyWhenUnlocked(BaseWallet _wallet) { // solium-disable-next-line security/no-block-members require(!guardianStorage.isLocked(_wallet), "GM: wallet must be unlocked"); _; } // *************** Constructor ********************** // constructor( ModuleRegistry _registry, GuardianStorage _guardianStorage, uint256 _securityPeriod, uint256 _securityWindow ) BaseModule(_registry, NAME) public { guardianStorage = _guardianStorage; securityPeriod = _securityPeriod; securityWindow = _securityWindow; } // *************** External Functions ********************* // /** * @dev Lets the owner add a guardian to its wallet. * The first guardian is added immediately. All following additions must be confirmed * by calling the confirmGuardianAddition() method. * @param _wallet The target wallet. * @param _guardian The guardian to add. */ function addGuardian(BaseWallet _wallet, address _guardian) external onlyOwner(_wallet) onlyWhenUnlocked(_wallet) { require(!isOwner(_wallet, _guardian), "GM: target guardian cannot be owner"); require(!isGuardian(_wallet, _guardian), "GM: target is already a guardian"); // Guardians must either be an EOA or a contract with an owner() // method that returns an address with a 5000 gas stipend. // Note that this test is not meant to be strict and can be bypassed by custom malicious contracts. // solium-disable-next-line security/no-low-level-calls require(_guardian.call.gas(5000)(abi.encodeWithSignature("owner()")), "GM: guardian must be EOA or implement owner()"); if(guardianStorage.guardianCount(_wallet) == 0) { guardianStorage.addGuardian(_wallet, _guardian); emit GuardianAdded(_wallet, _guardian); } else { bytes32 id = keccak256(abi.encodePacked(address(_wallet), _guardian, "addition")); GuardianManagerConfig storage config = configs[_wallet]; require( config.pending[id] == 0 || now > config.pending[id] + securityWindow, "GM: addition of target as guardian is already pending"); config.pending[id] = now + securityPeriod; emit GuardianAdditionRequested(_wallet, _guardian, now + securityPeriod); } } /** * @dev Confirms the pending addition of a guardian to a wallet. * The method must be called during the confirmation window and * can be called by anyone to enable orchestration. * @param _wallet The target wallet. * @param _guardian The guardian. */ function confirmGuardianAddition(BaseWallet _wallet, address _guardian) public onlyWhenUnlocked(_wallet) { bytes32 id = keccak256(abi.encodePacked(address(_wallet), _guardian, "addition")); GuardianManagerConfig storage config = configs[_wallet]; require(config.pending[id] > 0, "GM: no pending addition as guardian for target"); require(config.pending[id] < now, "GM: Too early to confirm guardian addition"); require(now < config.pending[id] + securityWindow, "GM: Too late to confirm guardian addition"); guardianStorage.addGuardian(_wallet, _guardian); delete config.pending[id]; emit GuardianAdded(_wallet, _guardian); } /** * @dev Lets the owner cancel a pending guardian addition. * @param _wallet The target wallet. * @param _guardian The guardian. */ function cancelGuardianAddition(BaseWallet _wallet, address _guardian) public onlyOwner(_wallet) onlyWhenUnlocked(_wallet) { bytes32 id = keccak256(abi.encodePacked(address(_wallet), _guardian, "addition")); GuardianManagerConfig storage config = configs[_wallet]; require(config.pending[id] > 0, "GM: no pending addition as guardian for target"); delete config.pending[id]; emit GuardianAdditionCancelled(_wallet, _guardian); } /** * @dev Lets the owner revoke a guardian from its wallet. * Revokation must be confirmed by calling the confirmGuardianRevokation() method. * @param _wallet The target wallet. * @param _guardian The guardian to revoke. */ function revokeGuardian(BaseWallet _wallet, address _guardian) external onlyOwner(_wallet) { require(isGuardian(_wallet, _guardian), "GM: must be an existing guardian"); bytes32 id = keccak256(abi.encodePacked(address(_wallet), _guardian, "revokation")); GuardianManagerConfig storage config = configs[_wallet]; require( config.pending[id] == 0 || now > config.pending[id] + securityWindow, "GM: revokation of target as guardian is already pending"); // TODO need to allow if confirmation window passed config.pending[id] = now + securityPeriod; emit GuardianRevokationRequested(_wallet, _guardian, now + securityPeriod); } /** * @dev Confirms the pending revokation of a guardian to a wallet. * The method must be called during the confirmation window and * can be called by anyone to enable orchestration. * @param _wallet The target wallet. * @param _guardian The guardian. */ function confirmGuardianRevokation(BaseWallet _wallet, address _guardian) public { bytes32 id = keccak256(abi.encodePacked(address(_wallet), _guardian, "revokation")); GuardianManagerConfig storage config = configs[_wallet]; require(config.pending[id] > 0, "GM: no pending guardian revokation for target"); require(config.pending[id] < now, "GM: Too early to confirm guardian revokation"); require(now < config.pending[id] + securityWindow, "GM: Too late to confirm guardian revokation"); guardianStorage.revokeGuardian(_wallet, _guardian); delete config.pending[id]; emit GuardianRevoked(_wallet, _guardian); } /** * @dev Lets the owner cancel a pending guardian revokation. * @param _wallet The target wallet. * @param _guardian The guardian. */ function cancelGuardianRevokation(BaseWallet _wallet, address _guardian) public onlyOwner(_wallet) onlyWhenUnlocked(_wallet) { bytes32 id = keccak256(abi.encodePacked(address(_wallet), _guardian, "revokation")); GuardianManagerConfig storage config = configs[_wallet]; require(config.pending[id] > 0, "GM: no pending guardian revokation for target"); delete config.pending[id]; emit GuardianRevokationCancelled(_wallet, _guardian); } /** * @dev Checks if an address is a guardian for a wallet. * @param _wallet The target wallet. * @param _guardian The address to check. * @return true if the address if a guardian for the wallet. */ function isGuardian(BaseWallet _wallet, address _guardian) public view returns (bool _isGuardian) { (_isGuardian, ) = GuardianUtils.isGuardian(guardianStorage.getGuardians(_wallet), _guardian); } /** * @dev Counts the number of active guardians for a wallet. * @param _wallet The target wallet. * @return the number of active guardians for a wallet. */ function guardianCount(BaseWallet _wallet) external view returns (uint256 _count) { return guardianStorage.guardianCount(_wallet); } /** * @dev Get the active guardians for a wallet. * @param _wallet The target wallet. * @return the active guardians for a wallet. */ function getGuardians(BaseWallet _wallet) external view returns (address[] _guardians) { return guardianStorage.getGuardians(_wallet); } // *************** Implementation of RelayerModule methods ********************* // // Overrides to use the incremental nonce and save some gas function checkAndUpdateUniqueness(BaseWallet _wallet, uint256 _nonce, bytes32 _signHash) internal returns (bool) { return checkAndUpdateNonce(_wallet, _nonce); } function validateSignatures(BaseWallet _wallet, bytes _data, bytes32 _signHash, bytes _signatures) internal view returns (bool) { address signer = recoverSigner(_signHash, _signatures, 0); return isOwner(_wallet, signer); // "GM: signer must be owner" } function getRequiredSignatures(BaseWallet _wallet, bytes _data) internal view returns (uint256) { bytes4 methodId = functionPrefix(_data); if (methodId == CONFIRM_ADDITION_PREFIX || methodId == CONFIRM_REVOKATION_PREFIX) { return 0; } return 1; } }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
[{"constant":true,"inputs":[],"name":"securityWindow","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_wallet","type":"address"}],"name":"init","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_wallet","type":"address"},{"name":"_guardian","type":"address"}],"name":"revokeGuardian","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_wallet","type":"address"},{"name":"_guardian","type":"address"}],"name":"cancelGuardianRevokation","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_wallet","type":"address"}],"name":"getNonce","outputs":[{"name":"nonce","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_wallet","type":"address"},{"name":"_guardian","type":"address"}],"name":"confirmGuardianRevokation","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_wallet","type":"address"}],"name":"guardianCount","outputs":[{"name":"_count","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_wallet","type":"address"},{"name":"_module","type":"address"}],"name":"addModule","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_wallet","type":"address"},{"name":"_guardian","type":"address"}],"name":"confirmGuardianAddition","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"securityPeriod","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_token","type":"address"}],"name":"recoverToken","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_wallet","type":"address"},{"name":"_guardian","type":"address"}],"name":"cancelGuardianAddition","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_wallet","type":"address"},{"name":"_data","type":"bytes"},{"name":"_nonce","type":"uint256"},{"name":"_signatures","type":"bytes"},{"name":"_gasPrice","type":"uint256"},{"name":"_gasLimit","type":"uint256"}],"name":"execute","outputs":[{"name":"success","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_wallet","type":"address"},{"name":"_guardian","type":"address"}],"name":"addGuardian","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"","type":"address"}],"name":"relayer","outputs":[{"name":"nonce","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_wallet","type":"address"},{"name":"_guardian","type":"address"}],"name":"isGuardian","outputs":[{"name":"_isGuardian","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"guardianStorage","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_wallet","type":"address"}],"name":"getGuardians","outputs":[{"name":"_guardians","type":"address[]"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"_registry","type":"address"},{"name":"_guardianStorage","type":"address"},{"name":"_securityPeriod","type":"uint256"},{"name":"_securityWindow","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"name":"wallet","type":"address"},{"indexed":true,"name":"guardian","type":"address"},{"indexed":false,"name":"executeAfter","type":"uint256"}],"name":"GuardianAdditionRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"wallet","type":"address"},{"indexed":true,"name":"guardian","type":"address"},{"indexed":false,"name":"executeAfter","type":"uint256"}],"name":"GuardianRevokationRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"wallet","type":"address"},{"indexed":true,"name":"guardian","type":"address"}],"name":"GuardianAdditionCancelled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"wallet","type":"address"},{"indexed":true,"name":"guardian","type":"address"}],"name":"GuardianRevokationCancelled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"wallet","type":"address"},{"indexed":true,"name":"guardian","type":"address"}],"name":"GuardianAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"wallet","type":"address"},{"indexed":true,"name":"guardian","type":"address"}],"name":"GuardianRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"wallet","type":"address"},{"indexed":true,"name":"success","type":"bool"},{"indexed":false,"name":"signedHash","type":"bytes32"}],"name":"TransactionExecuted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"name","type":"bytes32"}],"name":"ModuleCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"name":"wallet","type":"address"}],"name":"ModuleInitialised","type":"event"}]
Contract Creation Code
608060405234801561001057600080fd5b5060405160808061315183398101604081815282516020808501518386015160609096015160008054600160a060020a031916600160a060020a0386161790557f477561726469616e4d616e61676572000000000000000000000000000000000080875294519396919591949093879391927f3019c8fc80239e3dff8f781212ae2004839c2cb61d6c70acd279ac65392145df92908290030190a1505060038054600160a060020a031916600160a060020a0394909416939093179092556004556005555061306d806100e46000396000f3006080604052600436106100fa5763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416626fda3581146100ff57806319ab453c146101265780631d97d8cc146101495780632960739b146101705780632d0335ab146101975780634b3ef054146101b85780635040fb76146101df5780635a1db8c41461020057806370135f52146102275780637cc0d9061461024e5780639be65a6014610263578063a6eb069014610284578063aacaaf88146102ab578063c684521014610302578063c9b5ef8e14610329578063d4ee97341461034a578063d89784fc14610371578063f18858ab146103a2575b600080fd5b34801561010b57600080fd5b50610114610413565b60408051918252519081900360200190f35b34801561013257600080fd5b50610147600160a060020a0360043516610419565b005b34801561015557600080fd5b50610147600160a060020a03600435811690602435166104bf565b34801561017c57600080fd5b50610147600160a060020a03600435811690602435166107ab565b3480156101a357600080fd5b50610114600160a060020a0360043516610af2565b3480156101c457600080fd5b50610147600160a060020a0360043581169060243516610b0d565b3480156101eb57600080fd5b50610114600160a060020a0360043516610e9e565b34801561020c57600080fd5b50610147600160a060020a0360043581169060243516610f3b565b34801561023357600080fd5b50610147600160a060020a0360043581169060243516611141565b34801561025a57600080fd5b5061011461159a565b34801561026f57600080fd5b50610147600160a060020a03600435166115a0565b34801561029057600080fd5b50610147600160a060020a03600435811690602435166116d4565b3480156102b757600080fd5b506102ee60048035600160a060020a031690602480358082019290810135916044359160643591820191013560843560a435611a1b565b604080519115158252519081900360200190f35b34801561030e57600080fd5b50610147600160a060020a0360043581169060243516611d15565b34801561033557600080fd5b50610114600160a060020a036004351661242b565b34801561035657600080fd5b506102ee600160a060020a036004358116906024351661243d565b34801561037d57600080fd5b50610386612542565b60408051600160a060020a039092168252519081900360200190f35b3480156103ae57600080fd5b506103c3600160a060020a0360043516612551565b60408051602080825283518183015283519192839290830191858101910280838360005b838110156103ff5781810151838201526020016103e7565b505050509050019250505060405180910390f35b60055481565b8033600160a060020a0382161461047f5760408051600080516020613022833981519152815260206004820152601960248201527f424d3a2063616c6c6572206d7573742062652077616c6c657400000000000000604482015290519081900360640190fd5b60408051600160a060020a038416815290517f9fcca3f73f85397e2bf03647abf243c20b753bd54463ff3cae74de2971c112fa9181900360200190a15050565b60008083333014806104d657506104d6813361264d565b15156105575760408051600080516020613022833981519152815260206004820152602360248201527f424d3a206d75737420626520616e206f776e657220666f72207468652077616c60448201527f6c65740000000000000000000000000000000000000000000000000000000000606482015290519081900360840190fd5b610561858561243d565b15156105bc5760408051600080516020613022833981519152815260206004820181905260248201527f474d3a206d75737420626520616e206578697374696e6720677561726469616e604482015290519081900360640190fd5b60408051600160a060020a038781166c010000000000000000000000009081026020808501919091529188160260348301527f7265766f6b6174696f6e00000000000000000000000000000000000000000000604883015282518083036032018152605290920192839052815191929182918401908083835b602083106106545780518252601f199092019160209182019101610635565b51815160209384036101000a60001901801990921691161790526040805192909401829003909120600160a060020a038b166000908152600283528481208282529283905293909320549297509550501591508190506106c557506005546000848152602084905260409020540142115b15156107465760408051600080516020613022833981519152815260206004820152603760248201527f474d3a207265766f6b6174696f6e206f6620746172676574206173206775617260448201527f6469616e20697320616c72656164792070656e64696e67000000000000000000606482015290519081900360840190fd5b6004805460008581526020858152604091829020429384019055925481519201825251600160a060020a0380881693908916927f9746f6868f544595794833da53250bd19e72334733336cfd5dd6fbc5f6a6ac42929081900390910190a35050505050565b60008083333014806107c257506107c2813361264d565b15156108435760408051600080516020613022833981519152815260206004820152602360248201527f424d3a206d75737420626520616e206f776e657220666f72207468652077616c60448201527f6c65740000000000000000000000000000000000000000000000000000000000606482015290519081900360840190fd5b600354604080517f4a4fbeec000000000000000000000000000000000000000000000000000000008152600160a060020a038089166004830152915188939290921691634a4fbeec916024808201926020929091908290030181600087803b1580156108ae57600080fd5b505af11580156108c2573d6000803e3d6000fd5b505050506040513d60208110156108d857600080fd5b5051156109345760408051600080516020613022833981519152815260206004820152601b60248201527f474d3a2077616c6c6574206d75737420626520756e6c6f636b65640000000000604482015290519081900360640190fd5b60408051600160a060020a038881166c010000000000000000000000009081026020808501919091529189160260348301527f7265766f6b6174696f6e00000000000000000000000000000000000000000000604883015282518083036032018152605290920192839052815191929182918401908083835b602083106109cc5780518252601f1990920191602091820191016109ad565b51815160209384036101000a60001901801990921691161790526040805192909401829003909120600160a060020a038c166000908152600283528481208282529283905293842054909950909750919091119250610aa39150505760408051600080516020613022833981519152815260206004820152602d60248201527f474d3a206e6f2070656e64696e6720677561726469616e207265766f6b61746960448201527f6f6e20666f722074617267657400000000000000000000000000000000000000606482015290519081900360840190fd5b60008481526020849052604080822082905551600160a060020a0380881692908916917fc0b205956d5e27c296695de329b5a014584a4f51824b1725a0eefc1174d6dbd59190a3505050505050565b600160a060020a031660009081526001602052604090205490565b60008083836040516020018083600160a060020a0316600160a060020a03166c0100000000000000000000000002815260140182600160a060020a0316600160a060020a03166c01000000000000000000000000028152601401807f7265766f6b6174696f6e00000000000000000000000000000000000000000000815250600a01925050506040516020818303038152906040526040518082805190602001908083835b60208310610bd15780518252601f199092019160209182019101610bb2565b51815160209384036101000a60001901801990921691161790526040805192909401829003909120600160a060020a038a166000908152600283528481208282529283905293842054909750909550919091119250610ca89150505760408051600080516020613022833981519152815260206004820152602d60248201527f474d3a206e6f2070656e64696e6720677561726469616e207265766f6b61746960448201527f6f6e20666f722074617267657400000000000000000000000000000000000000606482015290519081900360840190fd5b6000828152602082905260409020544211610d385760408051600080516020613022833981519152815260206004820152602c60248201527f474d3a20546f6f206561726c7920746f20636f6e6669726d206775617264696160448201527f6e207265766f6b6174696f6e0000000000000000000000000000000000000000606482015290519081900360840190fd5b600554600083815260208390526040902054014210610dcc5760408051600080516020613022833981519152815260206004820152602b60248201527f474d3a20546f6f206c61746520746f20636f6e6669726d20677561726469616e60448201527f207265766f6b6174696f6e000000000000000000000000000000000000000000606482015290519081900360840190fd5b600354604080517f1d97d8cc000000000000000000000000000000000000000000000000000000008152600160a060020a038781166004830152868116602483015291519190921691631d97d8cc91604480830192600092919082900301818387803b158015610e3b57600080fd5b505af1158015610e4f573d6000803e3d6000fd5b50505060008381526020839052604080822082905551600160a060020a0380871693508716917f548f10dcba266544123ad8cf8284f25c4baa659cba25dbdf16a06ea11235de9b91a350505050565b600354604080517f5040fb76000000000000000000000000000000000000000000000000000000008152600160a060020a03848116600483015291516000939290921691635040fb769160248082019260209290919082900301818787803b158015610f0957600080fd5b505af1158015610f1d573d6000803e3d6000fd5b505050506040513d6020811015610f3357600080fd5b505192915050565b81610f46813361264d565b1515610fc75760408051600080516020613022833981519152815260206004820152602e60248201527f424d3a206d73672e73656e646572206d75737420626520616e206f776e65722060448201527f666f72207468652077616c6c6574000000000000000000000000000000000000606482015290519081900360840190fd5b60008054604080517f0bcd4ebb000000000000000000000000000000000000000000000000000000008152600160a060020a03868116600483015291519190921692630bcd4ebb92602480820193602093909283900390910190829087803b15801561103257600080fd5b505af1158015611046573d6000803e3d6000fd5b505050506040513d602081101561105c57600080fd5b505115156110b95760408051600080516020613022833981519152815260206004820152601c60248201527f424d3a206d6f64756c65206973206e6f74207265676973746572656400000000604482015290519081900360640190fd5b604080517f1f17732d000000000000000000000000000000000000000000000000000000008152600160a060020a03848116600483015260016024830152915191851691631f17732d9160448082019260009290919082900301818387803b15801561112457600080fd5b505af1158015611138573d6000803e3d6000fd5b50505050505050565b600354604080517f4a4fbeec000000000000000000000000000000000000000000000000000000008152600160a060020a038086166004830152915160009384938793911691634a4fbeec9160248082019260209290919082900301818887803b1580156111ae57600080fd5b505af11580156111c2573d6000803e3d6000fd5b505050506040513d60208110156111d857600080fd5b5051156112345760408051600080516020613022833981519152815260206004820152601b60248201527f474d3a2077616c6c6574206d75737420626520756e6c6f636b65640000000000604482015290519081900360640190fd5b60408051600160a060020a038781166c010000000000000000000000009081026020808501919091529188160260348301527f6164646974696f6e000000000000000000000000000000000000000000000000604883015282518083036030018152605090920192839052815191929182918401908083835b602083106112cc5780518252601f1990920191602091820191016112ad565b51815160209384036101000a60001901801990921691161790526040805192909401829003909120600160a060020a038b1660009081526002835284812082825292839052938420549098509096509190911192506113a39150505760408051600080516020613022833981519152815260206004820152602e60248201527f474d3a206e6f2070656e64696e67206164646974696f6e20617320677561726460448201527f69616e20666f7220746172676574000000000000000000000000000000000000606482015290519081900360840190fd5b60008381526020839052604090205442116114335760408051600080516020613022833981519152815260206004820152602a60248201527f474d3a20546f6f206561726c7920746f20636f6e6669726d206775617264696160448201527f6e206164646974696f6e00000000000000000000000000000000000000000000606482015290519081900360840190fd5b6005546000848152602084905260409020540142106114c75760408051600080516020613022833981519152815260206004820152602960248201527f474d3a20546f6f206c61746520746f20636f6e6669726d20677561726469616e60448201527f206164646974696f6e0000000000000000000000000000000000000000000000606482015290519081900360840190fd5b600354604080517fc6845210000000000000000000000000000000000000000000000000000000008152600160a060020a03888116600483015287811660248301529151919092169163c684521091604480830192600092919082900301818387803b15801561153657600080fd5b505af115801561154a573d6000803e3d6000fd5b50505060008481526020849052604080822082905551600160a060020a0380881693508816917fbc3292102fa77e083913064b282926717cdfaede4d35f553d66366c0a3da755a91a35050505050565b60045481565b604080517f70a082310000000000000000000000000000000000000000000000000000000081523060048201529051600091600160a060020a038416916370a082319160248082019260209290919082900301818787803b15801561160457600080fd5b505af1158015611618573d6000803e3d6000fd5b505050506040513d602081101561162e57600080fd5b505160008054604080517fa9059cbb000000000000000000000000000000000000000000000000000000008152600160a060020a0392831660048201526024810185905290519394509085169263a9059cbb92604480840193602093929083900390910190829087803b1580156116a457600080fd5b505af11580156116b8573d6000803e3d6000fd5b505050506040513d60208110156116ce57600080fd5b50505050565b60008083333014806116eb57506116eb813361264d565b151561176c5760408051600080516020613022833981519152815260206004820152602360248201527f424d3a206d75737420626520616e206f776e657220666f72207468652077616c60448201527f6c65740000000000000000000000000000000000000000000000000000000000606482015290519081900360840190fd5b600354604080517f4a4fbeec000000000000000000000000000000000000000000000000000000008152600160a060020a038089166004830152915188939290921691634a4fbeec916024808201926020929091908290030181600087803b1580156117d757600080fd5b505af11580156117eb573d6000803e3d6000fd5b505050506040513d602081101561180157600080fd5b50511561185d5760408051600080516020613022833981519152815260206004820152601b60248201527f474d3a2077616c6c6574206d75737420626520756e6c6f636b65640000000000604482015290519081900360640190fd5b60408051600160a060020a038881166c010000000000000000000000009081026020808501919091529189160260348301527f6164646974696f6e000000000000000000000000000000000000000000000000604883015282518083036030018152605090920192839052815191929182918401908083835b602083106118f55780518252601f1990920191602091820191016118d6565b51815160209384036101000a60001901801990921691161790526040805192909401829003909120600160a060020a038c1660009081526002835284812082825292839052938420549099509097509190911192506119cc9150505760408051600080516020613022833981519152815260206004820152602e60248201527f474d3a206e6f2070656e64696e67206164646974696f6e20617320677561726460448201527f69616e20666f7220746172676574000000000000000000000000000000000000606482015290519081900360840190fd5b60008481526020849052604080822082905551600160a060020a0380881692908916917faa13b27c23e9e3f3d5f3861a53b7a2931e019170a6a19ed64942e26a1dd5987a9190a3505050505050565b6000806000805a9250611a66308d60008e8e8080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050508d8b8b6126ed565b9150611a738c8a846128e1565b1515611ace5760408051600080516020613022833981519152815260206004820152601560248201527f524d3a204475706c696361746520726571756573740000000000000000000000604482015290519081900360640190fd5b611b088c8c8c8080601f016020809104026020016040519081016040528093929190818152602001838380828437506128f5945050505050565b1515611baf5760408051600080516020613022833981519152815260206004820152604a60248201527f524d3a207468652077616c6c657420617574686f72697a65642069732064696660448201527f666572656e74207468656e2074686520746172676574206f662074686520726560648201527f6c61796564206461746100000000000000000000000000000000000000000000608482015290519081900360a40190fd5b611be98c8c8c8080601f0160208091040260200160405190810160405280939291908181526020018383808284375061297f945050505050565b905060418102871415611cc457611c028c868884612aab565b15611cc457801580611c7d5750611c7d8c8c8c8080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050848b8b8080601f01602080910402602001604051908101604052809392919081815260200183838082843750612b7f945050505050565b15611cc45730600160a060020a03168b8b604051808383808284378201915050925050506000604051808303816000865af19150509350611cc48c5a850388888533612ba4565b60408051838152905185151591600160a060020a038f16917f6bb0b384ce772133df63560651bc8c727c53306cec1d51e2cbf8ea35fb8f2ec19181900360200190a350505098975050505050505050565b6000808333301480611d2c5750611d2c813361264d565b1515611dad5760408051600080516020613022833981519152815260206004820152602360248201527f424d3a206d75737420626520616e206f776e657220666f72207468652077616c60448201527f6c65740000000000000000000000000000000000000000000000000000000000606482015290519081900360840190fd5b600354604080517f4a4fbeec000000000000000000000000000000000000000000000000000000008152600160a060020a038089166004830152915188939290921691634a4fbeec916024808201926020929091908290030181600087803b158015611e1857600080fd5b505af1158015611e2c573d6000803e3d6000fd5b505050506040513d6020811015611e4257600080fd5b505115611e9e5760408051600080516020613022833981519152815260206004820152601b60248201527f474d3a2077616c6c6574206d75737420626520756e6c6f636b65640000000000604482015290519081900360640190fd5b611ea8868661264d565b15611f285760408051600080516020613022833981519152815260206004820152602360248201527f474d3a2074617267657420677561726469616e2063616e6e6f74206265206f7760448201527f6e65720000000000000000000000000000000000000000000000000000000000606482015290519081900360840190fd5b611f32868661243d565b15611f8c5760408051600080516020613022833981519152815260206004820181905260248201527f474d3a2074617267657420697320616c7265616479206120677561726469616e604482015290519081900360640190fd5b60408051600481526024810182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f8da5cb5b0000000000000000000000000000000000000000000000000000000017815291518151600160a060020a0389169361138893929182919080838360005b83811015612018578181015183820152602001612000565b50505050905090810190601f1680156120455780820380516001836020036101000a031916815260200191505b5091505060006040518083038160008787f19250505015156120dc5760408051600080516020613022833981519152815260206004820152602d60248201527f474d3a20677561726469616e206d75737420626520454f41206f7220696d706c60448201527f656d656e74206f776e6572282900000000000000000000000000000000000000606482015290519081900360840190fd5b600354604080517f5040fb76000000000000000000000000000000000000000000000000000000008152600160a060020a03898116600483015291519190921691635040fb769160248083019260209291908290030181600087803b15801561214457600080fd5b505af1158015612158573d6000803e3d6000fd5b505050506040513d602081101561216e57600080fd5b5051151561223a57600354604080517fc6845210000000000000000000000000000000000000000000000000000000008152600160a060020a03898116600483015288811660248301529151919092169163c684521091604480830192600092919082900301818387803b1580156121e557600080fd5b505af11580156121f9573d6000803e3d6000fd5b5050604051600160a060020a038089169350891691507fbc3292102fa77e083913064b282926717cdfaede4d35f553d66366c0a3da755a90600090a3612423565b60408051600160a060020a038881166c010000000000000000000000009081026020808501919091529189160260348301527f6164646974696f6e000000000000000000000000000000000000000000000000604883015282518083036030018152605090920192839052815191929182918401908083835b602083106122d25780518252601f1990920191602091820191016122b3565b51815160209384036101000a60001901801990921691161790526040805192909401829003909120600160a060020a038c1660009081526002835284812082825292839052939093205492985096505015915081905061234357506005546000858152602085905260409020540142115b15156123c45760408051600080516020613022833981519152815260206004820152603560248201527f474d3a206164646974696f6e206f66207461726765742061732067756172646960448201527f616e20697320616c72656164792070656e64696e670000000000000000000000606482015290519081900360840190fd5b6004805460008681526020868152604091829020429384019055925481519201825251600160a060020a0380891693908a16927fe4166e4bc55a182bd13d933553241bb3441b91d15fbc74c5c752f96965563bde929081900390910190a35b505050505050565b60016020526000908152604090205481565b600354604080517ff18858ab000000000000000000000000000000000000000000000000000000008152600160a060020a038581166004830152915160009361253a93169163f18858ab916024808301928792919082900301818387803b1580156124a757600080fd5b505af11580156124bb573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405260208110156124e457600080fd5b8101908080516401000000008111156124fc57600080fd5b8201602081018481111561250f57600080fd5b815185602082028301116401000000008211171561252c57600080fd5b505092919050505083612c73565b509392505050565b600354600160a060020a031681565b600354604080517ff18858ab000000000000000000000000000000000000000000000000000000008152600160a060020a0384811660048301529151606093929092169163f18858ab9160248082019260009290919082900301818387803b1580156125bc57600080fd5b505af11580156125d0573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405260208110156125f957600080fd5b81019080805164010000000081111561261157600080fd5b8201602081018481111561262457600080fd5b815185602082028301116401000000008211171561264157600080fd5b50909695505050505050565b600081600160a060020a031683600160a060020a0316638da5cb5b6040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b1580156126b057600080fd5b505af11580156126c4573d6000803e3d6000fd5b505050506040513d60208110156126da57600080fd5b5051600160a060020a0316149392505050565b6040517f190000000000000000000000000000000000000000000000000000000000000060208083018281526000602185018190526c01000000000000000000000000600160a060020a03808e16820260228801528c16026036860152604a85018a90528851909485938d938d938d938d938d938d938d939192606a909201918701908083835b602083106127935780518252601f199092019160209182019101612774565b6001836020036101000a03801982511681845116808217855250505050505090500184815260200183815260200182815260200199505050505050505050506040516020818303038152906040526040518082805190602001908083835b602083106128105780518252601f1990920191602091820191016127f1565b51815160209384036101000a6000190180199092169116179052604080519290940182900382207f19457468657265756d205369676e6564204d6573736167653a0a33320000000083830152603c8084019190915284518084039091018152605c9092019384905281519195509293508392850191508083835b602083106128a95780518252601f19909201916020918201910161288a565b5181516020939093036101000a600019018019909116921691909117905260405192018290039091209b9a5050505050505050505050565b60006128ed8484612dfa565b949350505050565b60008060248351101515156129595760408051600080516020613022833981519152815260206004820152601660248201527f524d3a20496e76616c6964206461746157616c6c657400000000000000000000604482015290519081900360640190fd5b6024830151905083600160a060020a031681600160a060020a03161491505b5092915050565b60008061298b83612e87565b604080517f636f6e6669726d477561726469616e4164646974696f6e28616464726573732c81527f6164647265737329000000000000000000000000000000000000000000000000602082015290519081900360280190209091507fffffffff0000000000000000000000000000000000000000000000000000000080831691161480612a935750604080517f636f6e6669726d477561726469616e5265766f6b6174696f6e2861646472657381527f732c6164647265737329000000000000000000000000000000000000000000006020820152905190819003602a0190207fffffffff000000000000000000000000000000000000000000000000000000008281169116145b15612aa15760009150612978565b5060019392505050565b60008083118015612abc5750600182115b8015612b67575082840285600160a060020a0316311080612b675750604080517fd6eb1bbf0000000000000000000000000000000000000000000000000000000081523060048201529051600160a060020a0387169163d6eb1bbf9160248083019260209291908290030181600087803b158015612b3957600080fd5b505af1158015612b4d573d6000803e3d6000fd5b505050506040513d6020811015612b6357600080fd5b5051155b15612b74575060006128ed565b506001949350505050565b600080612b8e84846000612ef2565b9050612b9a868261264d565b9695505050505050565b61726c8501600085118015612bb95750600183115b8015612bc55750838111155b15611138573a851115612bd9573a02612bdc565b84025b604080517f8f6f0332000000000000000000000000000000000000000000000000000000008152600160a060020a03848116600483015260248201849052606060448301526000606483018190529251908a1692638f6f03329260a4808201939182900301818387803b158015612c5257600080fd5b505af1158015612c66573d6000803e3d6000fd5b5050505050505050505050565b6000606060006060600080875160001480612c955750600160a060020a038716155b15612ca65760008895509550612def565b600093506001885103604051908082528060200260200182016040528015612cd8578160200160208202803883390190505b50925060009150600090505b8751811015612dd957831515612d84578781815181101515612d0257fe5b90602001906020020151600160a060020a031687600160a060020a03161415612d2e5760019350612dd1565b612d4e8882815181101515612d3f57fe5b90602001906020020151612f9f565b8015612d765750612d768882815181101515612d6657fe5b9060200190602002015188612fad565b15612d845760019350612dd1565b8251821015612dd1578781815181101515612d9b57fe5b906020019060200201518383815181101515612db357fe5b600160a060020a039092166020928302909101909101526001909101905b600101612ce4565b83612de657600088612dea565b6001835b955095505b505050509250929050565b600160a060020a03821660009081526001602052604081205481908311612e245760009150612978565b507001000000000000000000000000000000006fffffffffffffffffffffffffffffffff198316044361271001811115612e615760009150612978565b5050600160a060020a039190911660009081526001602081905260409091209190915590565b60006004825110151515612eea5760408051600080516020613022833981519152815260206004820152601a60248201527f524d3a20496e76616c69642066756e6374696f6e507265666978000000000000604482015290519081900360640190fd5b506020015190565b6041808202830160208101516040820151919092015160009260ff9190911691601b831480612f2457508260ff16601c145b1515612f2f57600080fd5b60408051600080825260208083018085528b905260ff8716838501526060830186905260808301859052925160019360a0808501949193601f19840193928390039091019190865af1158015612f89573d6000803e3d6000fd5b5050604051601f19015198975050505050505050565b6000903b63ffffffff161190565b604080517f6f776e657228290000000000000000000000000000000000000000000000000081529051908190036007018120808252600091829190602081818189611388fa600181141561300057815193505b505083600160a060020a031682600160a060020a0316149250505092915050560008c379a000000000000000000000000000000000000000000000000000000000a165627a7a7230582086448da21884a19f4cf51905c8210254a33deb89a165d6737b44c9c1a09391f50029000000000000000000000000c17d432bd8e8850fd7b32b0270f5afac65db010500000000000000000000000044da3a8051ba88eab0440db3779cab9d679ae76f0000000000000000000000000000000000000000000000000000000000015180000000000000000000000000000000000000000000000000000000000000a8c0
Deployed Bytecode
0x6080604052600436106100fa5763ffffffff7c01000000000000000000000000000000000000000000000000000000006000350416626fda3581146100ff57806319ab453c146101265780631d97d8cc146101495780632960739b146101705780632d0335ab146101975780634b3ef054146101b85780635040fb76146101df5780635a1db8c41461020057806370135f52146102275780637cc0d9061461024e5780639be65a6014610263578063a6eb069014610284578063aacaaf88146102ab578063c684521014610302578063c9b5ef8e14610329578063d4ee97341461034a578063d89784fc14610371578063f18858ab146103a2575b600080fd5b34801561010b57600080fd5b50610114610413565b60408051918252519081900360200190f35b34801561013257600080fd5b50610147600160a060020a0360043516610419565b005b34801561015557600080fd5b50610147600160a060020a03600435811690602435166104bf565b34801561017c57600080fd5b50610147600160a060020a03600435811690602435166107ab565b3480156101a357600080fd5b50610114600160a060020a0360043516610af2565b3480156101c457600080fd5b50610147600160a060020a0360043581169060243516610b0d565b3480156101eb57600080fd5b50610114600160a060020a0360043516610e9e565b34801561020c57600080fd5b50610147600160a060020a0360043581169060243516610f3b565b34801561023357600080fd5b50610147600160a060020a0360043581169060243516611141565b34801561025a57600080fd5b5061011461159a565b34801561026f57600080fd5b50610147600160a060020a03600435166115a0565b34801561029057600080fd5b50610147600160a060020a03600435811690602435166116d4565b3480156102b757600080fd5b506102ee60048035600160a060020a031690602480358082019290810135916044359160643591820191013560843560a435611a1b565b604080519115158252519081900360200190f35b34801561030e57600080fd5b50610147600160a060020a0360043581169060243516611d15565b34801561033557600080fd5b50610114600160a060020a036004351661242b565b34801561035657600080fd5b506102ee600160a060020a036004358116906024351661243d565b34801561037d57600080fd5b50610386612542565b60408051600160a060020a039092168252519081900360200190f35b3480156103ae57600080fd5b506103c3600160a060020a0360043516612551565b60408051602080825283518183015283519192839290830191858101910280838360005b838110156103ff5781810151838201526020016103e7565b505050509050019250505060405180910390f35b60055481565b8033600160a060020a0382161461047f5760408051600080516020613022833981519152815260206004820152601960248201527f424d3a2063616c6c6572206d7573742062652077616c6c657400000000000000604482015290519081900360640190fd5b60408051600160a060020a038416815290517f9fcca3f73f85397e2bf03647abf243c20b753bd54463ff3cae74de2971c112fa9181900360200190a15050565b60008083333014806104d657506104d6813361264d565b15156105575760408051600080516020613022833981519152815260206004820152602360248201527f424d3a206d75737420626520616e206f776e657220666f72207468652077616c60448201527f6c65740000000000000000000000000000000000000000000000000000000000606482015290519081900360840190fd5b610561858561243d565b15156105bc5760408051600080516020613022833981519152815260206004820181905260248201527f474d3a206d75737420626520616e206578697374696e6720677561726469616e604482015290519081900360640190fd5b60408051600160a060020a038781166c010000000000000000000000009081026020808501919091529188160260348301527f7265766f6b6174696f6e00000000000000000000000000000000000000000000604883015282518083036032018152605290920192839052815191929182918401908083835b602083106106545780518252601f199092019160209182019101610635565b51815160209384036101000a60001901801990921691161790526040805192909401829003909120600160a060020a038b166000908152600283528481208282529283905293909320549297509550501591508190506106c557506005546000848152602084905260409020540142115b15156107465760408051600080516020613022833981519152815260206004820152603760248201527f474d3a207265766f6b6174696f6e206f6620746172676574206173206775617260448201527f6469616e20697320616c72656164792070656e64696e67000000000000000000606482015290519081900360840190fd5b6004805460008581526020858152604091829020429384019055925481519201825251600160a060020a0380881693908916927f9746f6868f544595794833da53250bd19e72334733336cfd5dd6fbc5f6a6ac42929081900390910190a35050505050565b60008083333014806107c257506107c2813361264d565b15156108435760408051600080516020613022833981519152815260206004820152602360248201527f424d3a206d75737420626520616e206f776e657220666f72207468652077616c60448201527f6c65740000000000000000000000000000000000000000000000000000000000606482015290519081900360840190fd5b600354604080517f4a4fbeec000000000000000000000000000000000000000000000000000000008152600160a060020a038089166004830152915188939290921691634a4fbeec916024808201926020929091908290030181600087803b1580156108ae57600080fd5b505af11580156108c2573d6000803e3d6000fd5b505050506040513d60208110156108d857600080fd5b5051156109345760408051600080516020613022833981519152815260206004820152601b60248201527f474d3a2077616c6c6574206d75737420626520756e6c6f636b65640000000000604482015290519081900360640190fd5b60408051600160a060020a038881166c010000000000000000000000009081026020808501919091529189160260348301527f7265766f6b6174696f6e00000000000000000000000000000000000000000000604883015282518083036032018152605290920192839052815191929182918401908083835b602083106109cc5780518252601f1990920191602091820191016109ad565b51815160209384036101000a60001901801990921691161790526040805192909401829003909120600160a060020a038c166000908152600283528481208282529283905293842054909950909750919091119250610aa39150505760408051600080516020613022833981519152815260206004820152602d60248201527f474d3a206e6f2070656e64696e6720677561726469616e207265766f6b61746960448201527f6f6e20666f722074617267657400000000000000000000000000000000000000606482015290519081900360840190fd5b60008481526020849052604080822082905551600160a060020a0380881692908916917fc0b205956d5e27c296695de329b5a014584a4f51824b1725a0eefc1174d6dbd59190a3505050505050565b600160a060020a031660009081526001602052604090205490565b60008083836040516020018083600160a060020a0316600160a060020a03166c0100000000000000000000000002815260140182600160a060020a0316600160a060020a03166c01000000000000000000000000028152601401807f7265766f6b6174696f6e00000000000000000000000000000000000000000000815250600a01925050506040516020818303038152906040526040518082805190602001908083835b60208310610bd15780518252601f199092019160209182019101610bb2565b51815160209384036101000a60001901801990921691161790526040805192909401829003909120600160a060020a038a166000908152600283528481208282529283905293842054909750909550919091119250610ca89150505760408051600080516020613022833981519152815260206004820152602d60248201527f474d3a206e6f2070656e64696e6720677561726469616e207265766f6b61746960448201527f6f6e20666f722074617267657400000000000000000000000000000000000000606482015290519081900360840190fd5b6000828152602082905260409020544211610d385760408051600080516020613022833981519152815260206004820152602c60248201527f474d3a20546f6f206561726c7920746f20636f6e6669726d206775617264696160448201527f6e207265766f6b6174696f6e0000000000000000000000000000000000000000606482015290519081900360840190fd5b600554600083815260208390526040902054014210610dcc5760408051600080516020613022833981519152815260206004820152602b60248201527f474d3a20546f6f206c61746520746f20636f6e6669726d20677561726469616e60448201527f207265766f6b6174696f6e000000000000000000000000000000000000000000606482015290519081900360840190fd5b600354604080517f1d97d8cc000000000000000000000000000000000000000000000000000000008152600160a060020a038781166004830152868116602483015291519190921691631d97d8cc91604480830192600092919082900301818387803b158015610e3b57600080fd5b505af1158015610e4f573d6000803e3d6000fd5b50505060008381526020839052604080822082905551600160a060020a0380871693508716917f548f10dcba266544123ad8cf8284f25c4baa659cba25dbdf16a06ea11235de9b91a350505050565b600354604080517f5040fb76000000000000000000000000000000000000000000000000000000008152600160a060020a03848116600483015291516000939290921691635040fb769160248082019260209290919082900301818787803b158015610f0957600080fd5b505af1158015610f1d573d6000803e3d6000fd5b505050506040513d6020811015610f3357600080fd5b505192915050565b81610f46813361264d565b1515610fc75760408051600080516020613022833981519152815260206004820152602e60248201527f424d3a206d73672e73656e646572206d75737420626520616e206f776e65722060448201527f666f72207468652077616c6c6574000000000000000000000000000000000000606482015290519081900360840190fd5b60008054604080517f0bcd4ebb000000000000000000000000000000000000000000000000000000008152600160a060020a03868116600483015291519190921692630bcd4ebb92602480820193602093909283900390910190829087803b15801561103257600080fd5b505af1158015611046573d6000803e3d6000fd5b505050506040513d602081101561105c57600080fd5b505115156110b95760408051600080516020613022833981519152815260206004820152601c60248201527f424d3a206d6f64756c65206973206e6f74207265676973746572656400000000604482015290519081900360640190fd5b604080517f1f17732d000000000000000000000000000000000000000000000000000000008152600160a060020a03848116600483015260016024830152915191851691631f17732d9160448082019260009290919082900301818387803b15801561112457600080fd5b505af1158015611138573d6000803e3d6000fd5b50505050505050565b600354604080517f4a4fbeec000000000000000000000000000000000000000000000000000000008152600160a060020a038086166004830152915160009384938793911691634a4fbeec9160248082019260209290919082900301818887803b1580156111ae57600080fd5b505af11580156111c2573d6000803e3d6000fd5b505050506040513d60208110156111d857600080fd5b5051156112345760408051600080516020613022833981519152815260206004820152601b60248201527f474d3a2077616c6c6574206d75737420626520756e6c6f636b65640000000000604482015290519081900360640190fd5b60408051600160a060020a038781166c010000000000000000000000009081026020808501919091529188160260348301527f6164646974696f6e000000000000000000000000000000000000000000000000604883015282518083036030018152605090920192839052815191929182918401908083835b602083106112cc5780518252601f1990920191602091820191016112ad565b51815160209384036101000a60001901801990921691161790526040805192909401829003909120600160a060020a038b1660009081526002835284812082825292839052938420549098509096509190911192506113a39150505760408051600080516020613022833981519152815260206004820152602e60248201527f474d3a206e6f2070656e64696e67206164646974696f6e20617320677561726460448201527f69616e20666f7220746172676574000000000000000000000000000000000000606482015290519081900360840190fd5b60008381526020839052604090205442116114335760408051600080516020613022833981519152815260206004820152602a60248201527f474d3a20546f6f206561726c7920746f20636f6e6669726d206775617264696160448201527f6e206164646974696f6e00000000000000000000000000000000000000000000606482015290519081900360840190fd5b6005546000848152602084905260409020540142106114c75760408051600080516020613022833981519152815260206004820152602960248201527f474d3a20546f6f206c61746520746f20636f6e6669726d20677561726469616e60448201527f206164646974696f6e0000000000000000000000000000000000000000000000606482015290519081900360840190fd5b600354604080517fc6845210000000000000000000000000000000000000000000000000000000008152600160a060020a03888116600483015287811660248301529151919092169163c684521091604480830192600092919082900301818387803b15801561153657600080fd5b505af115801561154a573d6000803e3d6000fd5b50505060008481526020849052604080822082905551600160a060020a0380881693508816917fbc3292102fa77e083913064b282926717cdfaede4d35f553d66366c0a3da755a91a35050505050565b60045481565b604080517f70a082310000000000000000000000000000000000000000000000000000000081523060048201529051600091600160a060020a038416916370a082319160248082019260209290919082900301818787803b15801561160457600080fd5b505af1158015611618573d6000803e3d6000fd5b505050506040513d602081101561162e57600080fd5b505160008054604080517fa9059cbb000000000000000000000000000000000000000000000000000000008152600160a060020a0392831660048201526024810185905290519394509085169263a9059cbb92604480840193602093929083900390910190829087803b1580156116a457600080fd5b505af11580156116b8573d6000803e3d6000fd5b505050506040513d60208110156116ce57600080fd5b50505050565b60008083333014806116eb57506116eb813361264d565b151561176c5760408051600080516020613022833981519152815260206004820152602360248201527f424d3a206d75737420626520616e206f776e657220666f72207468652077616c60448201527f6c65740000000000000000000000000000000000000000000000000000000000606482015290519081900360840190fd5b600354604080517f4a4fbeec000000000000000000000000000000000000000000000000000000008152600160a060020a038089166004830152915188939290921691634a4fbeec916024808201926020929091908290030181600087803b1580156117d757600080fd5b505af11580156117eb573d6000803e3d6000fd5b505050506040513d602081101561180157600080fd5b50511561185d5760408051600080516020613022833981519152815260206004820152601b60248201527f474d3a2077616c6c6574206d75737420626520756e6c6f636b65640000000000604482015290519081900360640190fd5b60408051600160a060020a038881166c010000000000000000000000009081026020808501919091529189160260348301527f6164646974696f6e000000000000000000000000000000000000000000000000604883015282518083036030018152605090920192839052815191929182918401908083835b602083106118f55780518252601f1990920191602091820191016118d6565b51815160209384036101000a60001901801990921691161790526040805192909401829003909120600160a060020a038c1660009081526002835284812082825292839052938420549099509097509190911192506119cc9150505760408051600080516020613022833981519152815260206004820152602e60248201527f474d3a206e6f2070656e64696e67206164646974696f6e20617320677561726460448201527f69616e20666f7220746172676574000000000000000000000000000000000000606482015290519081900360840190fd5b60008481526020849052604080822082905551600160a060020a0380881692908916917faa13b27c23e9e3f3d5f3861a53b7a2931e019170a6a19ed64942e26a1dd5987a9190a3505050505050565b6000806000805a9250611a66308d60008e8e8080601f0160208091040260200160405190810160405280939291908181526020018383808284378201915050505050508d8b8b6126ed565b9150611a738c8a846128e1565b1515611ace5760408051600080516020613022833981519152815260206004820152601560248201527f524d3a204475706c696361746520726571756573740000000000000000000000604482015290519081900360640190fd5b611b088c8c8c8080601f016020809104026020016040519081016040528093929190818152602001838380828437506128f5945050505050565b1515611baf5760408051600080516020613022833981519152815260206004820152604a60248201527f524d3a207468652077616c6c657420617574686f72697a65642069732064696660448201527f666572656e74207468656e2074686520746172676574206f662074686520726560648201527f6c61796564206461746100000000000000000000000000000000000000000000608482015290519081900360a40190fd5b611be98c8c8c8080601f0160208091040260200160405190810160405280939291908181526020018383808284375061297f945050505050565b905060418102871415611cc457611c028c868884612aab565b15611cc457801580611c7d5750611c7d8c8c8c8080601f016020809104026020016040519081016040528093929190818152602001838380828437820191505050505050848b8b8080601f01602080910402602001604051908101604052809392919081815260200183838082843750612b7f945050505050565b15611cc45730600160a060020a03168b8b604051808383808284378201915050925050506000604051808303816000865af19150509350611cc48c5a850388888533612ba4565b60408051838152905185151591600160a060020a038f16917f6bb0b384ce772133df63560651bc8c727c53306cec1d51e2cbf8ea35fb8f2ec19181900360200190a350505098975050505050505050565b6000808333301480611d2c5750611d2c813361264d565b1515611dad5760408051600080516020613022833981519152815260206004820152602360248201527f424d3a206d75737420626520616e206f776e657220666f72207468652077616c60448201527f6c65740000000000000000000000000000000000000000000000000000000000606482015290519081900360840190fd5b600354604080517f4a4fbeec000000000000000000000000000000000000000000000000000000008152600160a060020a038089166004830152915188939290921691634a4fbeec916024808201926020929091908290030181600087803b158015611e1857600080fd5b505af1158015611e2c573d6000803e3d6000fd5b505050506040513d6020811015611e4257600080fd5b505115611e9e5760408051600080516020613022833981519152815260206004820152601b60248201527f474d3a2077616c6c6574206d75737420626520756e6c6f636b65640000000000604482015290519081900360640190fd5b611ea8868661264d565b15611f285760408051600080516020613022833981519152815260206004820152602360248201527f474d3a2074617267657420677561726469616e2063616e6e6f74206265206f7760448201527f6e65720000000000000000000000000000000000000000000000000000000000606482015290519081900360840190fd5b611f32868661243d565b15611f8c5760408051600080516020613022833981519152815260206004820181905260248201527f474d3a2074617267657420697320616c7265616479206120677561726469616e604482015290519081900360640190fd5b60408051600481526024810182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f8da5cb5b0000000000000000000000000000000000000000000000000000000017815291518151600160a060020a0389169361138893929182919080838360005b83811015612018578181015183820152602001612000565b50505050905090810190601f1680156120455780820380516001836020036101000a031916815260200191505b5091505060006040518083038160008787f19250505015156120dc5760408051600080516020613022833981519152815260206004820152602d60248201527f474d3a20677561726469616e206d75737420626520454f41206f7220696d706c60448201527f656d656e74206f776e6572282900000000000000000000000000000000000000606482015290519081900360840190fd5b600354604080517f5040fb76000000000000000000000000000000000000000000000000000000008152600160a060020a03898116600483015291519190921691635040fb769160248083019260209291908290030181600087803b15801561214457600080fd5b505af1158015612158573d6000803e3d6000fd5b505050506040513d602081101561216e57600080fd5b5051151561223a57600354604080517fc6845210000000000000000000000000000000000000000000000000000000008152600160a060020a03898116600483015288811660248301529151919092169163c684521091604480830192600092919082900301818387803b1580156121e557600080fd5b505af11580156121f9573d6000803e3d6000fd5b5050604051600160a060020a038089169350891691507fbc3292102fa77e083913064b282926717cdfaede4d35f553d66366c0a3da755a90600090a3612423565b60408051600160a060020a038881166c010000000000000000000000009081026020808501919091529189160260348301527f6164646974696f6e000000000000000000000000000000000000000000000000604883015282518083036030018152605090920192839052815191929182918401908083835b602083106122d25780518252601f1990920191602091820191016122b3565b51815160209384036101000a60001901801990921691161790526040805192909401829003909120600160a060020a038c1660009081526002835284812082825292839052939093205492985096505015915081905061234357506005546000858152602085905260409020540142115b15156123c45760408051600080516020613022833981519152815260206004820152603560248201527f474d3a206164646974696f6e206f66207461726765742061732067756172646960448201527f616e20697320616c72656164792070656e64696e670000000000000000000000606482015290519081900360840190fd5b6004805460008681526020868152604091829020429384019055925481519201825251600160a060020a0380891693908a16927fe4166e4bc55a182bd13d933553241bb3441b91d15fbc74c5c752f96965563bde929081900390910190a35b505050505050565b60016020526000908152604090205481565b600354604080517ff18858ab000000000000000000000000000000000000000000000000000000008152600160a060020a038581166004830152915160009361253a93169163f18858ab916024808301928792919082900301818387803b1580156124a757600080fd5b505af11580156124bb573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405260208110156124e457600080fd5b8101908080516401000000008111156124fc57600080fd5b8201602081018481111561250f57600080fd5b815185602082028301116401000000008211171561252c57600080fd5b505092919050505083612c73565b509392505050565b600354600160a060020a031681565b600354604080517ff18858ab000000000000000000000000000000000000000000000000000000008152600160a060020a0384811660048301529151606093929092169163f18858ab9160248082019260009290919082900301818387803b1580156125bc57600080fd5b505af11580156125d0573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405260208110156125f957600080fd5b81019080805164010000000081111561261157600080fd5b8201602081018481111561262457600080fd5b815185602082028301116401000000008211171561264157600080fd5b50909695505050505050565b600081600160a060020a031683600160a060020a0316638da5cb5b6040518163ffffffff167c0100000000000000000000000000000000000000000000000000000000028152600401602060405180830381600087803b1580156126b057600080fd5b505af11580156126c4573d6000803e3d6000fd5b505050506040513d60208110156126da57600080fd5b5051600160a060020a0316149392505050565b6040517f190000000000000000000000000000000000000000000000000000000000000060208083018281526000602185018190526c01000000000000000000000000600160a060020a03808e16820260228801528c16026036860152604a85018a90528851909485938d938d938d938d938d938d938d939192606a909201918701908083835b602083106127935780518252601f199092019160209182019101612774565b6001836020036101000a03801982511681845116808217855250505050505090500184815260200183815260200182815260200199505050505050505050506040516020818303038152906040526040518082805190602001908083835b602083106128105780518252601f1990920191602091820191016127f1565b51815160209384036101000a6000190180199092169116179052604080519290940182900382207f19457468657265756d205369676e6564204d6573736167653a0a33320000000083830152603c8084019190915284518084039091018152605c9092019384905281519195509293508392850191508083835b602083106128a95780518252601f19909201916020918201910161288a565b5181516020939093036101000a600019018019909116921691909117905260405192018290039091209b9a5050505050505050505050565b60006128ed8484612dfa565b949350505050565b60008060248351101515156129595760408051600080516020613022833981519152815260206004820152601660248201527f524d3a20496e76616c6964206461746157616c6c657400000000000000000000604482015290519081900360640190fd5b6024830151905083600160a060020a031681600160a060020a03161491505b5092915050565b60008061298b83612e87565b604080517f636f6e6669726d477561726469616e4164646974696f6e28616464726573732c81527f6164647265737329000000000000000000000000000000000000000000000000602082015290519081900360280190209091507fffffffff0000000000000000000000000000000000000000000000000000000080831691161480612a935750604080517f636f6e6669726d477561726469616e5265766f6b6174696f6e2861646472657381527f732c6164647265737329000000000000000000000000000000000000000000006020820152905190819003602a0190207fffffffff000000000000000000000000000000000000000000000000000000008281169116145b15612aa15760009150612978565b5060019392505050565b60008083118015612abc5750600182115b8015612b67575082840285600160a060020a0316311080612b675750604080517fd6eb1bbf0000000000000000000000000000000000000000000000000000000081523060048201529051600160a060020a0387169163d6eb1bbf9160248083019260209291908290030181600087803b158015612b3957600080fd5b505af1158015612b4d573d6000803e3d6000fd5b505050506040513d6020811015612b6357600080fd5b5051155b15612b74575060006128ed565b506001949350505050565b600080612b8e84846000612ef2565b9050612b9a868261264d565b9695505050505050565b61726c8501600085118015612bb95750600183115b8015612bc55750838111155b15611138573a851115612bd9573a02612bdc565b84025b604080517f8f6f0332000000000000000000000000000000000000000000000000000000008152600160a060020a03848116600483015260248201849052606060448301526000606483018190529251908a1692638f6f03329260a4808201939182900301818387803b158015612c5257600080fd5b505af1158015612c66573d6000803e3d6000fd5b5050505050505050505050565b6000606060006060600080875160001480612c955750600160a060020a038716155b15612ca65760008895509550612def565b600093506001885103604051908082528060200260200182016040528015612cd8578160200160208202803883390190505b50925060009150600090505b8751811015612dd957831515612d84578781815181101515612d0257fe5b90602001906020020151600160a060020a031687600160a060020a03161415612d2e5760019350612dd1565b612d4e8882815181101515612d3f57fe5b90602001906020020151612f9f565b8015612d765750612d768882815181101515612d6657fe5b9060200190602002015188612fad565b15612d845760019350612dd1565b8251821015612dd1578781815181101515612d9b57fe5b906020019060200201518383815181101515612db357fe5b600160a060020a039092166020928302909101909101526001909101905b600101612ce4565b83612de657600088612dea565b6001835b955095505b505050509250929050565b600160a060020a03821660009081526001602052604081205481908311612e245760009150612978565b507001000000000000000000000000000000006fffffffffffffffffffffffffffffffff198316044361271001811115612e615760009150612978565b5050600160a060020a039190911660009081526001602081905260409091209190915590565b60006004825110151515612eea5760408051600080516020613022833981519152815260206004820152601a60248201527f524d3a20496e76616c69642066756e6374696f6e507265666978000000000000604482015290519081900360640190fd5b506020015190565b6041808202830160208101516040820151919092015160009260ff9190911691601b831480612f2457508260ff16601c145b1515612f2f57600080fd5b60408051600080825260208083018085528b905260ff8716838501526060830186905260808301859052925160019360a0808501949193601f19840193928390039091019190865af1158015612f89573d6000803e3d6000fd5b5050604051601f19015198975050505050505050565b6000903b63ffffffff161190565b604080517f6f776e657228290000000000000000000000000000000000000000000000000081529051908190036007018120808252600091829190602081818189611388fa600181141561300057815193505b505083600160a060020a031682600160a060020a0316149250505092915050560008c379a000000000000000000000000000000000000000000000000000000000a165627a7a7230582086448da21884a19f4cf51905c8210254a33deb89a165d6737b44c9c1a09391f50029
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000c17d432bd8e8850fd7b32b0270f5afac65db010500000000000000000000000044da3a8051ba88eab0440db3779cab9d679ae76f0000000000000000000000000000000000000000000000000000000000015180000000000000000000000000000000000000000000000000000000000000a8c0
-----Decoded View---------------
Arg [0] : _registry (address): 0xc17D432Bd8e8850Fd7b32B0270f5AfAc65DB0105
Arg [1] : _guardianStorage (address): 0x44DA3A8051bA88EAB0440DB3779cAB9D679ae76f
Arg [2] : _securityPeriod (uint256): 86400
Arg [3] : _securityWindow (uint256): 43200
-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 000000000000000000000000c17d432bd8e8850fd7b32b0270f5afac65db0105
Arg [1] : 00000000000000000000000044da3a8051ba88eab0440db3779cab9d679ae76f
Arg [2] : 0000000000000000000000000000000000000000000000000000000000015180
Arg [3] : 000000000000000000000000000000000000000000000000000000000000a8c0
Swarm Source
bzzr://86448da21884a19f4cf51905c8210254a33deb89a165d6737b44c9c1a09391f5
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 30 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.