ETH Price: $3,355.91 (-0.87%)

Contract

0xFF5A7299ff6f0fbAad9b38906b77d08c0FBdc9A7
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Token Holdings

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Execute187326282023-12-07 6:27:35388 days ago1701930455IN
0xFF5A7299...c0FBdc9A7
0 ETH0.005694135.798
Execute148810662022-05-31 21:36:18942 days ago1654032978IN
0xFF5A7299...c0FBdc9A7
0 ETH0.01712422107.6575324
Execute142575412022-02-22 18:42:461040 days ago1645555366IN
0xFF5A7299...c0FBdc9A7
0 ETH0.0066707392
Confirm Guardian...138195672021-12-17 1:03:171108 days ago1639702997IN
0xFF5A7299...c0FBdc9A7
0 ETH0.008091384
Execute138131192021-12-16 0:58:301109 days ago1639616310IN
0xFF5A7299...c0FBdc9A7
0 ETH0.0083240779.83118844
Execute138131112021-12-16 0:56:431109 days ago1639616203IN
0xFF5A7299...c0FBdc9A7
0 ETH0.0111372870.026
Confirm Guardian...135898602021-11-10 17:37:481145 days ago1636565868IN
0xFF5A7299...c0FBdc9A7
0 ETH0.01790212186
Execute135835252021-11-09 17:36:111146 days ago1636479371IN
0xFF5A7299...c0FBdc9A7
0 ETH0.02390021218
Execute134776542021-10-24 2:54:511162 days ago1635044091IN
0xFF5A7299...c0FBdc9A7
0 ETH0.0093846559
Confirm Guardian...134045162021-10-12 15:46:041174 days ago1634053564IN
0xFF5A7299...c0FBdc9A7
0 ETH0.0103610391.347
Confirm Guardian...134044922021-10-12 15:40:261174 days ago1634053226IN
0xFF5A7299...c0FBdc9A7
0 ETH0.0046828691
Execute133981522021-10-11 15:40:471175 days ago1633966847IN
0xFF5A7299...c0FBdc9A7
0 ETH0.009982895.728
Execute133981382021-10-11 15:38:581175 days ago1633966738IN
0xFF5A7299...c0FBdc9A7
0 ETH0.01134928125.455
Confirm Guardian...132231212021-09-14 9:55:261202 days ago1631613326IN
0xFF5A7299...c0FBdc9A7
0 ETH0.0028828747.551
Execute132166582021-09-13 9:51:161203 days ago1631526676IN
0xFF5A7299...c0FBdc9A7
0 ETH0.0053164655
Execute124912932021-05-23 15:10:231316 days ago1621782623IN
0xFF5A7299...c0FBdc9A7
0 ETH0.0159075100.034
Confirm Guardian...124265912021-05-13 14:36:491326 days ago1620916609IN
0xFF5A7299...c0FBdc9A7
0 ETH0.01185887137.817
Execute124200872021-05-12 14:24:331327 days ago1620829473IN
0xFF5A7299...c0FBdc9A7
0 ETH0.03760066303.263
Execute123098822021-04-25 14:00:411344 days ago1619359241IN
0xFF5A7299...c0FBdc9A7
0 ETH0.0064403540.5
Confirm Guardian...123022332021-04-24 9:56:081345 days ago1619258168IN
0xFF5A7299...c0FBdc9A7
0 ETH0.0048485456.347
Execute122957812021-04-23 9:53:151346 days ago1619171595IN
0xFF5A7299...c0FBdc9A7
0 ETH0.0104034285.8
Execute122916032021-04-22 18:25:001346 days ago1619115900IN
0xFF5A7299...c0FBdc9A7
0 ETH0.02096265132
Execute119196442021-02-24 11:46:101404 days ago1614167170IN
0xFF5A7299...c0FBdc9A7
0 ETH0.00933369110.001
Confirm Guardian...119088392021-02-22 19:53:301405 days ago1614023610IN
0xFF5A7299...c0FBdc9A7
0 ETH0.01094619138.867
Execute119022562021-02-21 19:45:021406 days ago1613936702IN
0xFF5A7299...c0FBdc9A7
0 ETH0.01669099148
View all transactions

View more zero value Internal Transactions in Advanced View mode

Advanced mode:
Loading...
Loading

Contract Source Code Verified (Exact Match)

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

Contract ABI

[{"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"}]

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

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
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.