Contract 0xdc350d09f71c48c5D22fBE2741e4d6A03970E192

 
 
Txn Hash
Method
Block
From
To
Value
0x2b29a961f98801516f988c43c68b700bd66dc336ab4d6d2df98891acd7d4f459Finalize Recover...161338382022-12-07 15:52:231 day 21 hrs agoArgent: Relayer 3 IN  0xdc350d09f71c48c5d22fbe2741e4d6a03970e1920 Ether0.00088841 18.45973261
0xb94298554556e095657c6430cb087ce36a6e232485c81fe615fd300505f8cfbeExecute161231582022-12-06 3:47:113 days 9 hrs agoArgent: Relayer 3 IN  0xdc350d09f71c48c5d22fbe2741e4d6a03970e1920 Ether0.0018924911.853
0xdb311f94445999bc85b75206f8fb70d60767b76633d5b7badb5763e187003170Finalize Recover...161207912022-12-05 19:52:233 days 17 hrs agoArgent: Relayer 3 IN  0xdc350d09f71c48c5d22fbe2741e4d6a03970e1920 Ether0.00063256 13.14364215
0x9a20e72e13629962958e64681770f28ee21daf189ec6f3039e3c9dbe82251a56Execute161100482022-12-04 7:46:475 days 5 hrs agoArgent: Relayer 3 IN  0xdc350d09f71c48c5d22fbe2741e4d6a03970e1920 Ether0.001492810.711
0xf57a4d3ef28e28492b5112ce6c76f02c3205e2c3d050c8b9e311b0ec98bf952cFinalize Recover...160972112022-12-02 12:45:597 days 47 mins agoArgent: Relayer 3 IN  0xdc350d09f71c48c5d22fbe2741e4d6a03970e1920 Ether0.00051699 10.74235383
0xb1beeebe8d75f0f65c375f6310b012c3bbd73b4dfa82a276b634051c55bbbcb9Execute160864532022-12-01 0:44:478 days 12 hrs agoArgent: Relayer 3 IN  0xdc350d09f71c48c5d22fbe2741e4d6a03970e1920 Ether0.0017582111.012
0x829a76bc72033293bb7571046f9bc3bdcd28285a064652f49b0af3db25b6e0fdFinalize Recover...160707982022-11-28 20:12:5910 days 17 hrs agoArgent: Relayer 3 IN  0xdc350d09f71c48c5d22fbe2741e4d6a03970e1920 Ether0.00056581 11.75727368
0xc99cd422ed0fe94679f87ff0d8beb0eb55608e5715b0085ceef563be35e6375eExecute160600462022-11-27 8:11:4712 days 5 hrs agoArgent: Relayer 3 IN  0xdc350d09f71c48c5d22fbe2741e4d6a03970e1920 Ether0.001281238.983
0x2d25531a13d8d8d1637f7c180050a237da8d567bc44a8c1a7937ea46ca3c1f10Finalize Recover...160563352022-11-26 19:46:1112 days 17 hrs agoArgent: Relayer 3 IN  0xdc350d09f71c48c5d22fbe2741e4d6a03970e1920 Ether0.00052266 10.86334574
0x278bd7b30b8ba639786e4e7910b201ac4be66c0af46894bfa197d378420067b5Execute160455822022-11-25 7:42:5914 days 5 hrs agoArgent: Relayer 3 IN  0xdc350d09f71c48c5d22fbe2741e4d6a03970e1920 Ether0.0016132710.762
0x6f7c3d39d0742bde4d5ba343e8213df50085fdbe00788998fb31df43dab5a663Finalize Recover...160143402022-11-20 22:54:3518 days 14 hrs agoArgent: Relayer 3 IN  0xdc350d09f71c48c5d22fbe2741e4d6a03970e1920 Ether0.00051932 10.79067553
0x6141eeea3a454b1623b3c2cbb0a9e2f4dc184e3e3a9a6ad355e31ad5e63a6d3fFinalize Recover...160109162022-11-20 11:25:4719 days 2 hrs agoArgent: Relayer 3 IN  0xdc350d09f71c48c5d22fbe2741e4d6a03970e1920 Ether0.00051898 10.78372905
0x5efbc8e4c7c54915d0c0bd8acd05ee4248da40386e6aed288623e51bd5d99d6eExecute160035722022-11-19 10:50:1120 days 2 hrs agoArgent: Relayer 3 IN  0xdc350d09f71c48c5d22fbe2741e4d6a03970e1920 Ether0.0018066511.099
0x52dc24c4ea65c4e8d528658e26cc40b5dd57746449497e4cc928faf4b0a62675Execute160001592022-11-18 23:23:4720 days 14 hrs agoArgent: Relayer 3 IN  0xdc350d09f71c48c5d22fbe2741e4d6a03970e1920 Ether0.0018482711.576
0x79067676bed1449d77b64bc572215fbb4b102711a689a8c47af630e18a55c9ecFinalize Recover...159727412022-11-15 3:26:3524 days 10 hrs agoArgent: Relayer 3 IN  0xdc350d09f71c48c5d22fbe2741e4d6a03970e1920 Ether0.00376732 78.282
0xd9acfd632870bfba0e6e345e0d6d66bd2134a2251e915809c4e7829c513f70e3Execute159619752022-11-13 15:23:5925 days 22 hrs agoArgent: Relayer 3 IN  0xdc350d09f71c48c5d22fbe2741e4d6a03970e1920 Ether0.0026816118.27
0x3d9b480d1eb5a8c400653ffa28e644d228fb4862f6e81cd7db22cbf9840bd73aFinalize Recover...158982472022-11-04 17:48:3534 days 19 hrs agoArgent: Relayer 3 IN  0xdc350d09f71c48c5d22fbe2741e4d6a03970e1920 Ether0.00122612 25.48428475
0x3bfc5e9cfad125d5bca161f3eb18397baadbc3a1aa8a7acabd9faaec16a8b1d8Execute158874892022-11-03 5:44:3536 days 7 hrs agoArgent: Relayer 3 IN  0xdc350d09f71c48c5d22fbe2741e4d6a03970e1920 Ether0.0021029913.168
0x97808b6bcb851e920517a001c18f7197201aed92c7020ca8ab8731a82df761c1Finalize Recover...158859942022-11-03 0:44:3536 days 12 hrs agoArgent: Relayer 3 IN  0xdc350d09f71c48c5d22fbe2741e4d6a03970e1920 Ether0.00061656 12.81169517
0x53fbfae5ede41d70e87896b96d737a6194459e7a066f782844787b53c330f572Execute158752262022-11-01 12:38:1138 days 55 mins agoArgent: Relayer 3 IN  0xdc350d09f71c48c5d22fbe2741e4d6a03970e1920 Ether0.0016445811.205
0xe6239bd6ec0654428009436c9df546fdc8268c6a16c65586dae2cb740645201bFinalize Recover...158334152022-10-26 16:22:4743 days 21 hrs agoArgent: Relayer 3 IN  0xdc350d09f71c48c5d22fbe2741e4d6a03970e1920 Ether0.00119883 24.90989134
0x32b932fb41f4a7a518be80dddfa3f0737f00918390388c03a6e111706c6aca27Finalize Recover...158243952022-10-25 10:07:1145 days 3 hrs agoArgent: Relayer 3 IN  0xdc350d09f71c48c5d22fbe2741e4d6a03970e1920 Ether0.00052413 10.89075189
0x504938eb845f62c8ba6408191361c33b44adaa11f5482d4dcf1ac5f566f30af0Execute158226632022-10-25 4:19:1145 days 9 hrs agoArgent: Relayer 3 IN  0xdc350d09f71c48c5d22fbe2741e4d6a03970e1920 Ether0.0018485410.504
0x88c1ca6f942a8ecfed03689bf2ab651568bca75549ce64679f11f8c5ffa27a37Execute158136732022-10-23 22:03:4746 days 15 hrs agoArgent: Relayer 5 IN  0xdc350d09f71c48c5d22fbe2741e4d6a03970e1920 Ether0.0031508322.10385778
0xfd1a784a0361d9e70d029d3908bd6547b090ff8f110858aca15df6c9d3c19686Execute158085942022-10-23 5:03:1147 days 8 hrs agoArgent: Relayer 8 IN  0xdc350d09f71c48c5d22fbe2741e4d6a03970e1920 Ether0.0010570511.892
[ Download CSV Export 
View more zero value Internal Transactions in Advanced View mode
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
RecoveryManager

Compiler Version
v0.5.4+commit.9549d8ff

Optimization Enabled:
Yes with 999 runs

Other Settings:
default evmVersion, GNU GPLv3 license

Contract Source Code (Solidity)

/**
 *Submitted for verification at Etherscan.io on 2020-06-19
*/

pragma solidity ^0.5.4;

// Copyright (C) 2018  Argent Labs Ltd. <https://argent.xyz>

// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.


/**
 * @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;
}// Copyright (C) 2018  Argent Labs Ltd. <https://argent.xyz>

// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.


/**
 * @title BaseWallet
 * @dev Simple modular wallet that authorises modules to call its invoke() method.
 * @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[] calldata _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);
        }
        if (address(this).balance > 0) {
            emit Received(address(this).balance, address(0), "");
        }
    }

    /**
     * @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) {
            emit AuthorisedModule(_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];
            }
        }
    }

    /**
    * @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 calldata _data) external moduleOnly returns (bytes memory _result) {
        bool success;
        // solium-disable-next-line security/no-call-value
        (success, _result) = _target.call.value(_value)(_data);
        if (!success) {
            // solium-disable-next-line security/no-inline-assembly
            assembly {
                returndatacopy(0, 0, returndatasize)
                revert(0, returndatasize)
            }
        }
        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() external 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())}
                }
            }
        }
    }
}// Copyright (C) 2018  Argent Labs Ltd. <https://argent.xyz>

// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.



/**
 * @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);
    }
}

/**
 * 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);
}// Copyright (C) 2018  Argent Labs Ltd. <https://argent.xyz>

// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.



/**
 * @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 exist");
        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 exist");
        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[] calldata _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;
    }
}// Copyright (C) 2018  Argent Labs Ltd. <https://argent.xyz>

// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.


/**
 * @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");
        _;
    }
}// Copyright (C) 2018  Argent Labs Ltd. <https://argent.xyz>

// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.


interface IGuardianStorage{

    /**
     * @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;

    /**
     * @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;

    /**
     * @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);
}// Copyright (C) 2018  Argent Labs Ltd. <https://argent.xyz>

// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.




/**
 * @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 IGuardianStorage, 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[address(_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[address(_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[address(_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[] memory) {
        GuardianStorageConfig storage config = configs[address(_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[address(_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[address(_wallet)].lock = _releaseAfter;
        if (_releaseAfter != 0 && msg.sender != configs[address(_wallet)].locker) {
            configs[address(_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[address(_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[address(_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[address(_wallet)].locker;
    }
}/* The MIT License (MIT)

Copyright (c) 2016 Smart Contract Solutions, Inc.

Permission is hereby granted, free of charge, to any person obtaining
a copy of this software and associated documentation files (the
"Software"), to deal in the Software without restriction, including
without limitation the rights to use, copy, modify, merge, publish,
distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to
the following conditions:

The above copyright notice and this permission notice shall be included
in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */



/**
 * @title SafeMath
 * @dev Math operations with safety checks that throw on error
 */
library SafeMath {

    /**
    * @dev Multiplies two numbers, reverts on overflow.
    */
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
        // benefit is lost if 'b' is also tested.
        // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522
        if (a == 0) {
            return 0;
        }

        uint256 c = a * b;
        require(c / a == b);

        return c;
    }

    /**
    * @dev Integer division of two numbers truncating the quotient, reverts on division by zero.
    */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b > 0); // Solidity only automatically asserts when dividing by 0
        uint256 c = a / b;
        // assert(a == b * c + a % b); // There is no case in which this doesn't hold

        return c;
    }

    /**
    * @dev Subtracts two numbers, reverts on overflow (i.e. if subtrahend is greater than minuend).
    */
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b <= a);
        uint256 c = a - b;

        return c;
    }

    /**
    * @dev Adds two numbers, reverts on overflow.
    */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a);

        return c;
    }

    /**
    * @dev Divides two numbers and returns the remainder (unsigned integer modulo),
    * reverts when dividing by zero.
    */
    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b != 0);
        return a % b;
    }

    /**
    * @dev Returns ceil(a / b).
    */
    function ceil(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a / b;
        if(a % b == 0) {
            return c;
        }
        else {
            return c + 1;
        }
    }

    // from DSMath - operations on fixed precision floats

    uint256 constant WAD = 10 ** 18;
    uint256 constant RAY = 10 ** 27;

    function wmul(uint256 x, uint256 y) internal pure returns (uint256 z) {
        z = add(mul(x, y), WAD / 2) / WAD;
    }
    function rmul(uint256 x, uint256 y) internal pure returns (uint256 z) {
        z = add(mul(x, y), RAY / 2) / RAY;
    }
    function wdiv(uint256 x, uint256 y) internal pure returns (uint256 z) {
        z = add(mul(x, WAD), y / 2) / y;
    }
    function rdiv(uint256 x, uint256 y) internal pure returns (uint256 z) {
        z = add(mul(x, RAY), y / 2) / y;
    }
}
// Copyright (C) 2018  Argent Labs Ltd. <https://argent.xyz>

// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.







/**
 * @title BaseModule
 * @dev Basic module that contains some methods common to all modules.
 * @author Julien Niset - <[email protected]>
 */
contract BaseModule is Module {

    // Empty calldata
    bytes constant internal EMPTY_BYTES = "";

    // The adddress of the module registry.
    ModuleRegistry internal registry;
    // The address of the Guardian storage
    GuardianStorage internal guardianStorage;

    /**
     * @dev Throws if the wallet is locked.
     */
    modifier onlyWhenUnlocked(BaseWallet _wallet) {
        // solium-disable-next-line security/no-block-members
        require(!guardianStorage.isLocked(_wallet), "BM: wallet must be unlocked");
        _;
    }

    event ModuleCreated(bytes32 name);
    event ModuleInitialised(address wallet);

    constructor(ModuleRegistry _registry, GuardianStorage _guardianStorage, bytes32 _name) public {
        registry = _registry;
        guardianStorage = _guardianStorage;
        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 onlyWalletOwner(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 strictOnlyWalletOwner(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) public onlyWallet(_wallet) {
        emit ModuleInitialised(address(_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 strictOnlyWalletOwner(_wallet) {
        require(registry.isRegisteredModule(address(_module)), "BM: module is not registered");
        _wallet.authoriseModule(address(_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;
    }

    /**
     * @dev Helper method to invoke a wallet.
     * @param _wallet The target wallet.
     * @param _to The target address for the transaction.
     * @param _value The value of the transaction.
     * @param _data The data of the transaction.
     */
    function invokeWallet(address _wallet, address _to, uint256 _value, bytes memory _data) internal returns (bytes memory _res) {
        bool success;
        // solium-disable-next-line security/no-call-value
        (success, _res) = _wallet.call(abi.encodeWithSignature("invoke(address,uint256,bytes)", _to, _value, _data));
        if (success && _res.length > 0) { //_res is empty if _wallet is an "old" BaseWallet that can't return output values
            (_res) = abi.decode(_res, (bytes));
        } else if (_res.length > 0) {
            // solium-disable-next-line security/no-inline-assembly
            assembly {
                returndatacopy(0, 0, returndatasize)
                revert(0, returndatasize)
            }
        } else if (!success) {
            revert("BM: wallet invoke reverted");
        }
    }
}// Copyright (C) 2018  Argent Labs Ltd. <https://argent.xyz>

// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.



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[] memory _guardians, address _guardian) internal view returns (bool, address[] memory) {
        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;
    }
}
// Copyright (C) 2018  Argent Labs Ltd. <https://argent.xyz>

// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.




/**
 * @title RelayerModuleV2
 * @dev Base module containing logic to execute transactions signed by eth-less accounts and sent by a relayer.
 * RelayerModuleV2 should ultimately replace RelayerModule and be subclassed by all modules.
 * It is currently only subclassed by RecoveryManager and ApprovedTransfer.
 * @author Julien Niset <[email protected]>, Olivier VDB <[email protected]>
 */
contract RelayerModuleV2 is BaseModule {

    uint256 constant internal BLOCKBOUND = 10000;

    mapping (address => RelayerConfig) public relayer;

    struct RelayerConfig {
        uint256 nonce;
        mapping (bytes32 => bool) executedTx;
    }

    enum OwnerSignature {
        Required,
        Optional,
        Disallowed
    }

    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 methods ************************* */

    /**
    * @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 memory _data) public view returns (uint256);

    /**
    * @dev Validates the signatures provided with a relayed transaction.
    * The method MUST return false 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.
    * @return A boolean indicating whether the signatures are valid.
    */
    function validateSignatures(
        BaseWallet _wallet,
        bytes memory _data,
        bytes32 _signHash,
        bytes memory _signatures
    )
        internal view returns (bool);

    /* ***************** External methods ************************* */

    /**
    * @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 calldata _data,
        uint256 _nonce,
        bytes calldata _signatures,
        uint256 _gasPrice,
        uint256 _gasLimit
    )
        external
        returns (bool success)
    {
        uint startGas = gasleft();
        bytes32 signHash = getSignHash(address(this), address(_wallet), 0, _data, _nonce, _gasPrice, _gasLimit);
        require(checkAndUpdateUniqueness(_wallet, _nonce, signHash), "RM: Duplicate request");
        require(verifyData(address(_wallet), _data), "RM: Target of _data != _wallet");
        uint256 requiredSignatures = getRequiredSignatures(_wallet, _data);
        require(requiredSignatures * 65 == _signatures.length, "RM: Wrong number of signatures");
        require(requiredSignatures == 0 || validateSignatures(_wallet, _data, signHash, _signatures), "RM: Invalid signatures");
        // The correctness of the refund is checked on the next line using an `if` instead of a `require`
        // in order to prevent a failing refund from being replayable in the future.
        if (verifyRefund(_wallet, _gasLimit, _gasPrice, requiredSignatures)) {
            // solium-disable-next-line security/no-call-value
            (success,) = address(this).call(_data);
            refund(_wallet, startGas - gasleft(), _gasPrice, _gasLimit, requiredSignatures, msg.sender);
        }
        emit TransactionExecuted(address(_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[address(_wallet)].nonce;
    }

    /* ***************** Internal & Private methods ************************* */

    /**
    * @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 memory _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[address(_wallet)].executedTx[_signHash] == true) {
            return false;
        }
        relayer[address(_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[address(_wallet)].nonce) {
            return false;
        }
        uint256 nonceBlock = (_nonce & 0xffffffffffffffffffffffffffffffff00000000000000000000000000000000) >> 128;
        if (nonceBlock > block.number + BLOCKBOUND) {
            return false;
        }
        relayer[address(_wallet)].nonce = _nonce;
        return true;
    }

    /**
    * @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 _signHash The signed hash representing the relayed transaction.
    * @param _signatures The signatures as a concatenated byte array.
    * @param _option An enum indicating whether the owner is required, optional or disallowed.
    */
    function validateSignatures(
        BaseWallet _wallet,
        bytes32 _signHash,
        bytes memory _signatures,
        OwnerSignature _option
    )
        internal view returns (bool)
    {
        address lastSigner = address(0);
        address[] memory guardians;
        if (_option != OwnerSignature.Required || _signatures.length > 65) {
            guardians = guardianStorage.getGuardians(_wallet); // guardians are only read if they may be needed
        }
        bool isGuardian;

        for (uint8 i = 0; i < _signatures.length / 65; i++) {
            address signer = recoverSigner(_signHash, _signatures, i);

            if (i == 0) {
                if (_option == OwnerSignature.Required) {
                    // First signer must be owner
                    if (isOwner(_wallet, signer)) {
                        continue;
                    }
                    return false;
                } else if (_option == OwnerSignature.Optional) {
                    // First signer can be owner
                    if (isOwner(_wallet, signer)) {
                        continue;
                    }
                }
            }
            if (signer <= lastSigner) {
                return false; // Signers must be different
            }
            lastSigner = signer;
            (isGuardian, guardians) = GuardianUtils.isGuardian(guardians, signer);
            if (!isGuardian) {
                return false;
            }
        }
        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 memory _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); // solium-disable-line error-reason
        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;
            }
            invokeWallet(address(_wallet), _relayer, amount, EMPTY_BYTES);
        }
    }

    /**
    * @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(address(this)) == false)) {
            return false;
        }
        return true;
    }

    /**
    * @dev Parses the data to extract the method signature.
    */
    function functionPrefix(bytes memory _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))
        }
    }

   /**
    * @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 memory _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;
    }
}// Copyright (C) 2018  Argent Labs Ltd. <https://argent.xyz>

// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.

// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.

// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.





/**
 * @title RecoveryManager
 * @dev Module to manage the recovery of a wallet owner.
 * Recovery is executed by a consensus of the wallet's guardians and takes
 * 24 hours before it can be finalized. Once finalised the ownership of the wallet
 * is transfered to a new address.
 * @author Julien Niset - <[email protected]>
 * @author Olivier Van Den Biggelaar - <[email protected]>
 */
contract RecoveryManager is BaseModule, RelayerModuleV2 {

    bytes32 constant NAME = "RecoveryManager";

    bytes4 constant internal EXECUTE_RECOVERY_PREFIX = bytes4(keccak256("executeRecovery(address,address)"));
    bytes4 constant internal FINALIZE_RECOVERY_PREFIX = bytes4(keccak256("finalizeRecovery(address)"));
    bytes4 constant internal CANCEL_RECOVERY_PREFIX = bytes4(keccak256("cancelRecovery(address)"));
    bytes4 constant internal TRANSFER_OWNERSHIP_PREFIX = bytes4(keccak256("transferOwnership(address,address)"));

    struct RecoveryConfig {
        address recovery;
        uint64 executeAfter;
        uint32 guardianCount;
    }

    // Wallet specific storage
    mapping (address => RecoveryConfig) internal recoveryConfigs;

    // Recovery period
    uint256 public recoveryPeriod;
    // Lock period
    uint256 public lockPeriod;
    // Security period used for (non-recovery) ownership transfer
    uint256 public securityPeriod;
    // Security window used for (non-recovery) ownership transfer
    uint256 public securityWindow;
    // Location of the Guardian storage
    GuardianStorage public guardianStorage;

    // *************** Events *************************** //

    event RecoveryExecuted(address indexed wallet, address indexed _recovery, uint64 executeAfter);
    event RecoveryFinalized(address indexed wallet, address indexed _recovery);
    event RecoveryCanceled(address indexed wallet, address indexed _recovery);
    event OwnershipTransfered(address indexed wallet, address indexed _newOwner);

    // *************** Modifiers ************************ //

    /**
     * @dev Throws if there is no ongoing recovery procedure.
     */
    modifier onlyWhenRecovery(BaseWallet _wallet) {
        require(recoveryConfigs[address(_wallet)].executeAfter > 0, "RM: there must be an ongoing recovery");
        _;
    }

    /**
     * @dev Throws if there is an ongoing recovery procedure.
     */
    modifier notWhenRecovery(BaseWallet _wallet) {
        require(recoveryConfigs[address(_wallet)].executeAfter == 0, "RM: there cannot be an ongoing recovery");
        _;
    }

    // *************** Constructor ************************ //

    constructor(
        ModuleRegistry _registry,
        GuardianStorage _guardianStorage,
        uint256 _recoveryPeriod,
        uint256 _lockPeriod,
        uint256 _securityPeriod,
        uint256 _securityWindow
    )
        BaseModule(_registry, _guardianStorage, NAME)
        public
    {
        require(_lockPeriod >= _recoveryPeriod && _recoveryPeriod >= _securityPeriod + _securityWindow, "RM: insecure security periods");
        guardianStorage = _guardianStorage;
        recoveryPeriod = _recoveryPeriod;
        lockPeriod = _lockPeriod;
        securityPeriod = _securityPeriod;
        securityWindow = _securityWindow;
    }

    // *************** External functions ************************ //

    /**
     * @dev Lets the guardians start the execution of the recovery procedure.
     * Once triggered the recovery is pending for the security period before it can
     * be finalised.
     * Must be confirmed by N guardians, where N = ((Nb Guardian + 1) / 2).
     * @param _wallet The target wallet.
     * @param _recovery The address to which ownership should be transferred.
     */
    function executeRecovery(BaseWallet _wallet, address _recovery) external onlyExecute notWhenRecovery(_wallet) {
        require(_recovery != address(0), "RM: recovery address cannot be null");
        RecoveryConfig storage config = recoveryConfigs[address(_wallet)];
        config.recovery = _recovery;
        config.executeAfter = uint64(now + recoveryPeriod);
        config.guardianCount = uint32(guardianStorage.guardianCount(_wallet));
        guardianStorage.setLock(_wallet, now + lockPeriod);
        emit RecoveryExecuted(address(_wallet), _recovery, config.executeAfter);
    }

    /**
     * @dev Finalizes an ongoing recovery procedure if the security period is over.
     * The method is public and callable by anyone to enable orchestration.
     * @param _wallet The target wallet.
     */
    function finalizeRecovery(BaseWallet _wallet) external onlyWhenRecovery(_wallet) {
        RecoveryConfig storage config = recoveryConfigs[address(_wallet)];
        require(uint64(now) > config.executeAfter, "RM: the recovery period is not over yet");
        _wallet.setOwner(config.recovery);
        emit RecoveryFinalized(address(_wallet), config.recovery);
        guardianStorage.setLock(_wallet, 0);
        delete recoveryConfigs[address(_wallet)];
    }

    /**
     * @dev Lets the owner cancel an ongoing recovery procedure.
     * Must be confirmed by N guardians, where N = ((Nb Guardian + 1) / 2) - 1.
     * @param _wallet The target wallet.
     */
    function cancelRecovery(BaseWallet _wallet) external onlyExecute onlyWhenRecovery(_wallet) {
        RecoveryConfig storage config = recoveryConfigs[address(_wallet)];
        emit RecoveryCanceled(address(_wallet), config.recovery);
        guardianStorage.setLock(_wallet, 0);
        delete recoveryConfigs[address(_wallet)];
    }

    /**
     * @dev Lets the owner start the execution of the ownership transfer procedure.
     * Once triggered the ownership transfer is pending for the security period before it can
     * be finalised.
     * @param _wallet The target wallet.
     * @param _newOwner The address to which ownership should be transferred.
     */
    function transferOwnership(BaseWallet _wallet, address _newOwner) external onlyExecute onlyWhenUnlocked(_wallet) {
        require(_newOwner != address(0), "RM: new owner address cannot be null");
        _wallet.setOwner(_newOwner);

        emit OwnershipTransfered(address(_wallet), _newOwner);
    }

    /**
    * @dev Gets the details of the ongoing recovery procedure if any.
    * @param _wallet The target wallet.
    */
    function getRecovery(BaseWallet _wallet) public view returns(address _address, uint64 _executeAfter, uint32 _guardianCount) {
        RecoveryConfig storage config = recoveryConfigs[address(_wallet)];
        return (config.recovery, config.executeAfter, config.guardianCount);
    }

    // *************** Implementation of RelayerModule methods ********************* //

    function validateSignatures(
        BaseWallet _wallet,
        bytes memory _data,
        bytes32 _signHash,
        bytes memory _signatures
    )
        internal view returns (bool)
    {
        bytes4 functionSignature = functionPrefix(_data);
        if (functionSignature == TRANSFER_OWNERSHIP_PREFIX) {
            return validateSignatures(_wallet, _signHash, _signatures, OwnerSignature.Required);
        } else if (functionSignature == EXECUTE_RECOVERY_PREFIX) {
            return validateSignatures(_wallet, _signHash, _signatures, OwnerSignature.Disallowed);
        } else if (functionSignature == CANCEL_RECOVERY_PREFIX) {
            return validateSignatures(_wallet, _signHash, _signatures, OwnerSignature.Optional);
        }
    }

    function getRequiredSignatures(BaseWallet _wallet, bytes memory _data) public view returns (uint256) {
        bytes4 methodId = functionPrefix(_data);
        if (methodId == EXECUTE_RECOVERY_PREFIX) {
            uint walletGuardians = guardianStorage.guardianCount(_wallet);
            require(walletGuardians > 0, "RM: no guardians set on wallet");
            return SafeMath.ceil(walletGuardians, 2);
        }
        if (methodId == FINALIZE_RECOVERY_PREFIX) {
            return 0;
        }
        if (methodId == CANCEL_RECOVERY_PREFIX) {
            return SafeMath.ceil(recoveryConfigs[address(_wallet)].guardianCount + 1, 2);
        }
        if (methodId == TRANSFER_OWNERSHIP_PREFIX) {
            uint majorityGuardians = SafeMath.ceil(guardianStorage.guardianCount(_wallet), 2);
            return SafeMath.add(majorityGuardians, 1);
        }
        revert("RM: unknown method");
    }
}

Contract Security Audit

Contract ABI

[{"constant":true,"inputs":[],"name":"securityWindow","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"recoveryPeriod","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":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":"finalizeRecovery","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_wallet","type":"address"},{"name":"_data","type":"bytes"}],"name":"getRequiredSignatures","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"lockPeriod","outputs":[{"name":"","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":"_newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"securityPeriod","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"name":"_wallet","type":"address"}],"name":"getRecovery","outputs":[{"name":"_address","type":"address"},{"name":"_executeAfter","type":"uint64"},{"name":"_guardianCount","type":"uint32"}],"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":"_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":"_recovery","type":"address"}],"name":"executeRecovery","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_wallet","type":"address"}],"name":"cancelRecovery","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":"guardianStorage","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"name":"_registry","type":"address"},{"name":"_guardianStorage","type":"address"},{"name":"_recoveryPeriod","type":"uint256"},{"name":"_lockPeriod","type":"uint256"},{"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":"_recovery","type":"address"},{"indexed":false,"name":"executeAfter","type":"uint64"}],"name":"RecoveryExecuted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"wallet","type":"address"},{"indexed":true,"name":"_recovery","type":"address"}],"name":"RecoveryFinalized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"wallet","type":"address"},{"indexed":true,"name":"_recovery","type":"address"}],"name":"RecoveryCanceled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"wallet","type":"address"},{"indexed":true,"name":"_newOwner","type":"address"}],"name":"OwnershipTransfered","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"}]

608060405234801561001057600080fd5b5060405160c080612b1e833981018060405260c081101561003057600080fd5b5080516020808301516040808501516060860151608087015160a09097015160008054600160a060020a03808a16600160a060020a031992831617909255600180549288169290911691909117905583517f5265636f766572794d616e6167657200000000000000000000000000000000008082529451979895979396929594919389938993927f3019c8fc80239e3dff8f781212ae2004839c2cb61d6c70acd279ac65392145df929081900390910190a15050508383101580156100f757508082018410155b151561016457604080517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601d60248201527f524d3a20696e73656375726520736563757269747920706572696f6473000000604482015290519081900360640190fd5b60088054600160a060020a031916600160a060020a0396909616959095179094556004929092556005556006556007555061297a806101a46000396000f3fe608060405234801561001057600080fd5b5060043610610137576000357c0100000000000000000000000000000000000000000000000000000000900480636d435421116100cf578063aacaaf881161009e578063c90db44711610083578063c90db44714610495578063c9b5ef8e146104bb578063d89784fc146104e157610137565b8063aacaaf8814610377578063b0ba4da01461046757610137565b80636d435421146102be5780637cc0d906146102ec5780639769c3fe146102f45780639be65a601461035157610137565b8063315a7af31161010b578063315a7af3146101ac5780633b73d67f146101d25780633fd8b02f146102885780635a1db8c41461029057610137565b80626fda351461013c57806316c3e22f1461015657806319ab453c1461015e5780632d0335ab14610186575b600080fd5b610144610505565b60408051918252519081900360200190f35b61014461050b565b6101846004803603602081101561017457600080fd5b5035600160a060020a0316610511565b005b6101446004803603602081101561019c57600080fd5b5035600160a060020a03166105b7565b610184600480360360208110156101c257600080fd5b5035600160a060020a03166105d2565b610144600480360360408110156101e857600080fd5b600160a060020a03823516919081019060408101602082013564010000000081111561021357600080fd5b82018360208201111561022557600080fd5b8035906020019184600183028401116401000000008311171561024757600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550610835945050505050565b610144610c22565b610184600480360360408110156102a657600080fd5b50600160a060020a0381358116916020013516610c28565b610184600480360360408110156102d457600080fd5b50600160a060020a0381358116916020013516610ded565b610144611050565b61031a6004803603602081101561030a57600080fd5b5035600160a060020a0316611056565b60408051600160a060020a03909416845267ffffffffffffffff909216602084015263ffffffff1682820152519081900360600190f35b6101846004803603602081101561036757600080fd5b5035600160a060020a03166110c0565b610453600480360360c081101561038d57600080fd5b600160a060020a0382351691908101906040810160208201356401000000008111156103b857600080fd5b8201836020820111156103ca57600080fd5b803590602001918460018302840111640100000000831117156103ec57600080fd5b9193909282359260408101906020013564010000000081111561040e57600080fd5b82018360208201111561042057600080fd5b8035906020019184600183028401116401000000008311171561044257600080fd5b9193509150803590602001356111f3565b604080519115158252519081900360200190f35b6101846004803603604081101561047d57600080fd5b50600160a060020a038135811691602001351661159b565b610184600480360360208110156104ab57600080fd5b5035600160a060020a031661192d565b610144600480360360208110156104d157600080fd5b5035600160a060020a0316611ac0565b6104e9611ad2565b60408051600160a060020a039092168252519081900360200190f35b60075481565b60045481565b8033600160a060020a0382161461057757604080516000805160206128c1833981519152815260206004820152601960248201527f424d3a2063616c6c6572206d7573742062652077616c6c657400000000000000604482015290519081900360640190fd5b60408051600160a060020a038416815290517f9fcca3f73f85397e2bf03647abf243c20b753bd54463ff3cae74de2971c112fa9181900360200190a15050565b600160a060020a031660009081526002602052604090205490565b600160a060020a03811660009081526003602052604081205482917401000000000000000000000000000000000000000090910467ffffffffffffffff1611610654576040516000805160206128c1833981519152815260040180806020018281038252602581526020018061287a6025913960400191505060405180910390fd5b600160a060020a0382166000908152600360205260409020805467ffffffffffffffff74010000000000000000000000000000000000000000909104811642909116116106da576040516000805160206128c183398151915281526004018080602001828103825260278152602001806128536027913960400191505060405180910390fd5b8054604080517f13af4035000000000000000000000000000000000000000000000000000000008152600160a060020a0392831660048201529051918516916313af40359160248082019260009290919082900301818387803b15801561074057600080fd5b505af1158015610754573d6000803e3d6000fd5b50508254604051600160a060020a03918216935090861691507fd8667de85dae2d56d76e700d16de53d21ac2ce4d5549cb0bf51c55fdc37f0bc190600090a3600854604080517fb0fc29e6000000000000000000000000000000000000000000000000000000008152600160a060020a038681166004830152600060248301819052925193169263b0fc29e69260448084019391929182900301818387803b1580156107ff57600080fd5b505af1158015610813573d6000803e3d6000fd5b505050600160a060020a03909316600090815260036020526040812055505050565b60008061084183611ae1565b604080517f657865637574655265636f7665727928616464726573732c6164647265737329815290519081900360200190209091507bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19808316911614156109a857600854604080517f5040fb76000000000000000000000000000000000000000000000000000000008152600160a060020a03878116600483015291516000939290921691635040fb7691602480820192602092909190829003018186803b15801561090957600080fd5b505afa15801561091d573d6000803e3d6000fd5b505050506040513d602081101561093357600080fd5b505190506000811161099457604080516000805160206128c1833981519152815260206004820152601e60248201527f524d3a206e6f20677561726469616e7320736574206f6e2077616c6c65740000604482015290519081900360640190fd5b61099f816002611b4c565b92505050610c1c565b604080517f66696e616c697a655265636f7665727928616464726573732900000000000000815290519081900360190190207bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1982811691161415610a0d576000915050610c1c565b604080517f63616e63656c5265636f76657279286164647265737329000000000000000000815290519081900360170190207bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1982811691161415610ac057600160a060020a038416600090815260036020526040902054610ab890600163ffffffff7c0100000000000000000000000000000000000000000000000000000000909204821601166002611b4c565b915050610c1c565b60405180602261289f8239602201905060405180910390207bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161415610bc757600854604080517f5040fb76000000000000000000000000000000000000000000000000000000008152600160a060020a0387811660048301529151600093610bba931691635040fb76916024808301926020929190829003018186803b158015610b8757600080fd5b505afa158015610b9b573d6000803e3d6000fd5b505050506040513d6020811015610bb157600080fd5b50516002611b4c565b905061099f816001611b80565b604080516000805160206128c1833981519152815260206004820152601260248201527f524d3a20756e6b6e6f776e206d6574686f640000000000000000000000000000604482015290519081900360640190fd5b92915050565b60055481565b81610c338133611b99565b1515610c78576040516000805160206128c1833981519152815260040180806020018281038252602e815260200180612825602e913960400191505060405180910390fd5b600054604080517f0bcd4ebb000000000000000000000000000000000000000000000000000000008152600160a060020a03858116600483015291519190921691630bcd4ebb916024808301926020929190829003018186803b158015610cde57600080fd5b505afa158015610cf2573d6000803e3d6000fd5b505050506040513d6020811015610d0857600080fd5b50511515610d6557604080516000805160206128c1833981519152815260206004820152601c60248201527f424d3a206d6f64756c65206973206e6f74207265676973746572656400000000604482015290519081900360640190fd5b604080517f1f17732d000000000000000000000000000000000000000000000000000000008152600160a060020a03848116600483015260016024830152915191851691631f17732d9160448082019260009290919082900301818387803b158015610dd057600080fd5b505af1158015610de4573d6000803e3d6000fd5b50505050505050565b333014610e4957604080516000805160206128c1833981519152815260206004820181905260248201527f524d3a206d7573742062652063616c6c65642076696120657865637574652829604482015290519081900360640190fd5b600154604080517f4a4fbeec000000000000000000000000000000000000000000000000000000008152600160a060020a038086166004830152915185939290921691634a4fbeec91602480820192602092909190829003018186803b158015610eb257600080fd5b505afa158015610ec6573d6000803e3d6000fd5b505050506040513d6020811015610edc57600080fd5b505115610f3857604080516000805160206128c1833981519152815260206004820152601b60248201527f424d3a2077616c6c6574206d75737420626520756e6c6f636b65640000000000604482015290519081900360640190fd5b600160a060020a0382161515610f87576040516000805160206128c183398151915281526004018080602001828103825260248152602001806128e16024913960400191505060405180910390fd5b82600160a060020a03166313af4035836040518263ffffffff167c01000000000000000000000000000000000000000000000000000000000281526004018082600160a060020a0316600160a060020a03168152602001915050600060405180830381600087803b158015610ffb57600080fd5b505af115801561100f573d6000803e3d6000fd5b5050604051600160a060020a038086169350861691507f0d18b5fd22306e373229b9439188228edca81207d1667f604daf6cef8aa3ee6790600090a3505050565b60065481565b600160a060020a039081166000908152600360205260409020549081169174010000000000000000000000000000000000000000820467ffffffffffffffff16917c0100000000000000000000000000000000000000000000000000000000900463ffffffff1690565b604080517f70a082310000000000000000000000000000000000000000000000000000000081523060048201529051600091600160a060020a038416916370a0823191602480820192602092909190829003018186803b15801561112357600080fd5b505afa158015611137573d6000803e3d6000fd5b505050506040513d602081101561114d57600080fd5b505160008054604080517fa9059cbb000000000000000000000000000000000000000000000000000000008152600160a060020a0392831660048201526024810185905290519394509085169263a9059cbb92604480840193602093929083900390910190829087803b1580156111c357600080fd5b505af11580156111d7573d6000803e3d6000fd5b505050506040513d60208110156111ed57600080fd5b50505050565b6000805a90506000611243308c60008d8d8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508f92508c91508b9050611c37565b90506112508b8983611d7a565b15156112ab57604080516000805160206128c1833981519152815260206004820152601560248201527f524d3a204475706c696361746520726571756573740000000000000000000000604482015290519081900360640190fd5b6112eb8b8b8b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250611def92505050565b151561134657604080516000805160206128c1833981519152815260206004820152601e60248201527f524d3a20546172676574206f66205f6461746120213d205f77616c6c65740000604482015290519081900360640190fd5b60006113888c8c8c8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061083592505050565b90506041810287146113e957604080516000805160206128c1833981519152815260206004820152601e60248201527f524d3a2057726f6e67206e756d626572206f66207369676e6174757265730000604482015290519081900360640190fd5b80158061146757506114678c8c8c8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8f018190048102820181019092528d815288935091508d908d9081908401838280828437600092019190915250611e6892505050565b15156114c257604080516000805160206128c1833981519152815260206004820152601660248201527f524d3a20496e76616c6964207369676e61747572657300000000000000000000604482015290519081900360640190fd5b6114ce8c868884611fc3565b1561154a5730600160a060020a03168b8b604051808383808284376040519201945060009350909150508083038183865af19150503d806000811461152f576040519150601f19603f3d011682016040523d82523d6000602084013e611534565b606091505b50508094505061154a8c5a850388888533612095565b60408051838152905185151591600160a060020a038f16917f6bb0b384ce772133df63560651bc8c727c53306cec1d51e2cbf8ea35fb8f2ec19181900360200190a350505098975050505050505050565b3330146115f757604080516000805160206128c1833981519152815260206004820181905260248201527f524d3a206d7573742062652063616c6c65642076696120657865637574652829604482015290519081900360640190fd5b600160a060020a038216600090815260036020526040902054829074010000000000000000000000000000000000000000900467ffffffffffffffff1615611678576040516000805160206128c183398151915281526004018080602001828103825260278152602001806129056027913960400191505060405180910390fd5b600160a060020a03821615156116c7576040516000805160206128c1833981519152815260040180806020018281038252602381526020018061292c6023913960400191505060405180910390fd5b600160a060020a0380841660008181526003602090815260409182902080548786167fffffffffffffffffffffffff0000000000000000000000000000000000000000909116178082556004805467ffffffffffffffff429091011674010000000000000000000000000000000000000000027fffffffff0000000000000000ffffffffffffffffffffffffffffffffffffffff90921691909117825560085484517f5040fb7600000000000000000000000000000000000000000000000000000000815291820195909552925190949390931692635040fb76926024808201939291829003018186803b1580156117be57600080fd5b505afa1580156117d2573d6000803e3d6000fd5b505050506040513d60208110156117e857600080fd5b5051815463ffffffff9091167c0100000000000000000000000000000000000000000000000000000000027bffffffffffffffffffffffffffffffffffffffffffffffffffffffff909116178155600854600554604080517fb0fc29e6000000000000000000000000000000000000000000000000000000008152600160a060020a0388811660048301524290930160248201529051919092169163b0fc29e691604480830192600092919082900301818387803b1580156118a957600080fd5b505af11580156118bd573d6000803e3d6000fd5b50508254604080517401000000000000000000000000000000000000000090920467ffffffffffffffff16825251600160a060020a038781169450881692507f5f59bfd9baba55ae30bb440923cbbe30987d50e12a4e9134ffac3fd9afc3526d916020908290030190a350505050565b33301461198957604080516000805160206128c1833981519152815260206004820181905260248201527f524d3a206d7573742062652063616c6c65642076696120657865637574652829604482015290519081900360640190fd5b600160a060020a03811660009081526003602052604081205482917401000000000000000000000000000000000000000090910467ffffffffffffffff1611611a0b576040516000805160206128c1833981519152815260040180806020018281038252602581526020018061287a6025913960400191505060405180910390fd5b600160a060020a038083166000818152600360205260408082208054915190949190911692917fc45926607303da71dbeffd2ed5c6b00f581982586b697655d19ae4c4d558f25991a3600854604080517fb0fc29e6000000000000000000000000000000000000000000000000000000008152600160a060020a038681166004830152600060248301819052925193169263b0fc29e69260448084019391929182900301818387803b1580156107ff57600080fd5b60026020526000908152604090205481565b600854600160a060020a031681565b60006004825110151515611b4457604080516000805160206128c1833981519152815260206004820152601a60248201527f524d3a20496e76616c69642066756e6374696f6e507265666978000000000000604482015290519081900360640190fd5b506020015190565b6000808284811515611b5a57fe5b0490508284811515611b6857fe5b061515611b76579050610c1c565b6001019050610c1c565b600082820183811015611b9257600080fd5b9392505050565b600081600160a060020a031683600160a060020a0316638da5cb5b6040518163ffffffff167c010000000000000000000000000000000000000000000000000000000002815260040160206040518083038186803b158015611bfa57600080fd5b505afa158015611c0e573d6000803e3d6000fd5b505050506040513d6020811015611c2457600080fd5b5051600160a060020a0316149392505050565b6040517f190000000000000000000000000000000000000000000000000000000000000060208083018281526000602185018190526c01000000000000000000000000600160a060020a03808e16820260228801528c16026036860152604a85018a90528851909485938d938d938d938d938d938d938d939192606a909201918701908083835b60208310611cdd5780518252601f199092019160209182019101611cbe565b51815160209384036101000a600019018019909216911617905292019586525084810193909352506040808401919091528051808403820181526060840182528051908301207f19457468657265756d205369676e6564204d6573736167653a0a3332000000006080850152609c808501919091528151808503909101815260bc909301905281519101209e9d5050505050505050505050505050565b600160a060020a0383166000908152600260209081526040808320848452600190810190925282205460ff1615151415611db657506000611b92565b50600160a060020a0392909216600090815260026020908152604080832094835260019485019091529020805460ff1916831790555090565b60006024825110151515611e5257604080516000805160206128c1833981519152815260206004820152601660248201527f524d3a20496e76616c6964206461746157616c6c657400000000000000000000604482015290519081900360640190fd5b5060240151600160a060020a0391821691161490565b600080611e7485611ae1565b9050604051808061289f60229139602201905060405180910390207bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916817bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19161415611ee957611ee186858560006120f3565b915050611fbb565b604080517f657865637574655265636f7665727928616464726573732c6164647265737329815290519081900360200190207bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1982811691161415611f5157611ee186858560026120f3565b604080517f63616e63656c5265636f76657279286164647265737329000000000000000000815290519081900360170190207bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1982811691161415611fb957611ee186858560016120f3565b505b949350505050565b60008083118015611fd45750600182115b801561207d575082840285600160a060020a031631108061207d5750604080517fd6eb1bbf0000000000000000000000000000000000000000000000000000000081523060048201529051600160a060020a0387169163d6eb1bbf916024808301926020929190829003018186803b15801561204f57600080fd5b505afa158015612063573d6000803e3d6000fd5b505050506040513d602081101561207957600080fd5b5051155b1561208a57506000611fbb565b506001949350505050565b61726c85016000851180156120aa5750600183115b80156120b65750838111155b15610de4573a8511156120ca573a026120cd565b84025b6120e987838360206040519081016040528060008152506122fc565b5050505050505050565b60008060608184600281111561210557fe5b141580612113575060418551115b1561220c57600154604080517ff18858ab000000000000000000000000000000000000000000000000000000008152600160a060020a038a811660048301529151919092169163f18858ab916024808301926000929190829003018186803b15801561217e57600080fd5b505afa158015612192573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f1916820160405260208110156121bb57600080fd5b8101908080516401000000008111156121d357600080fd5b820160208101848111156121e657600080fd5b815185602082028301116401000000008211171561220357600080fd5b50909450505050505b6000805b8651604190048160ff1610156122ed57600061223089898460ff1661257b565b905060ff8216151561229c57600087600281111561224a57fe5b14156122735761225a8a82611b99565b1561226557506122e5565b600095505050505050611fbb565b600187600281111561228157fe5b141561229c576122918a82611b99565b1561229c57506122e5565b600160a060020a03808616908216116122bd57600095505050505050611fbb565b8094506122ca8482612625565b945092508215156122e357600095505050505050611fbb565b505b600101612210565b50600198975050505050505050565b6060600085600160a060020a03168585856040516024018084600160a060020a0316600160a060020a0316815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b8381101561236b578181015183820152602001612353565b50505050905090810190601f1680156123985780820380516001836020036101000a031916815260200191505b5060408051601f198184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f8f6f033200000000000000000000000000000000000000000000000000000000178152905182519297509550859450925090508083835b602083106124245780518252601f199092019160209182019101612405565b6001836020036101000a0380198251168184511680821785525050505050509050019150506000604051808303816000865af19150503d8060008114612486576040519150601f19603f3d011682016040523d82523d6000602084013e61248b565b606091505b509250905080801561249e575060008251115b1561250b578180602001905160208110156124b857600080fd5b8101908080516401000000008111156124d057600080fd5b820160208101848111156124e357600080fd5b81516401000000008111828201871017156124fd57600080fd5b50909550611fb99350505050565b60008251111561251f573d6000803e3d6000fd5b801515611fb957604080516000805160206128c1833981519152815260206004820152601a60248201527f424d3a2077616c6c657420696e766f6b65207265766572746564000000000000604482015290519081900360640190fd5b6041808202830160208101516040820151919092015160009260ff9190911691601b8314806125ad57508260ff16601c145b15156125b857600080fd5b604080516000815260208082018084528a905260ff8616828401526060820185905260808201849052915160019260a0808401939192601f1981019281900390910190855afa15801561260f573d6000803e3d6000fd5b5050604051601f19015198975050505050505050565b600060608351600014806126405750600160a060020a038316155b156126505750600090508261279b565b600080905060606001865103604051908082528060200260200182016040528015612685578160200160208202803883390190505b5090506000805b87518110156127815783151561272c5787818151811015156126aa57fe5b90602001906020020151600160a060020a031687600160a060020a031614156126d65760019350612779565b6126f688828151811015156126e757fe5b906020019060200201516127a2565b801561271e575061271e888281518110151561270e57fe5b90602001906020020151886127b0565b1561272c5760019350612779565b825182101561277957878181518110151561274357fe5b90602001906020020151838381518110151561275b57fe5b600160a060020a039092166020928302909101909101526001909101905b60010161268c565b508261278f57600087612793565b6001825b945094505050505b9250929050565b6000903b63ffffffff161190565b604080517f6f776e657228290000000000000000000000000000000000000000000000000081529051908190036007018120808252600091829190602081818189611388fa600181141561280357815193505b505083600160a060020a031682600160a060020a031614925050509291505056fe424d3a206d73672e73656e646572206d75737420626520616e206f776e657220666f72207468652077616c6c6574524d3a20746865207265636f7665727920706572696f64206973206e6f74206f76657220796574524d3a207468657265206d75737420626520616e206f6e676f696e67207265636f766572797472616e736665724f776e65727368697028616464726573732c616464726573732908c379a000000000000000000000000000000000000000000000000000000000524d3a206e6577206f776e657220616464726573732063616e6e6f74206265206e756c6c524d3a2074686572652063616e6e6f7420626520616e206f6e676f696e67207265636f76657279524d3a207265636f7665727920616464726573732063616e6e6f74206265206e756c6ca165627a7a72305820848907040818e3346c3e6c43f000ac1b896832fc10bd65e67c18fda3fff5b9a00029000000000000000000000000c17d432bd8e8850fd7b32b0270f5afac65db010500000000000000000000000044da3a8051ba88eab0440db3779cab9d679ae76f000000000000000000000000000000000000000000000000000000000001fa4000000000000000000000000000000000000000000000000000000000000697800000000000000000000000000000000000000000000000000000000000015180000000000000000000000000000000000000000000000000000000000000a8c0

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

000000000000000000000000c17d432bd8e8850fd7b32b0270f5afac65db010500000000000000000000000044da3a8051ba88eab0440db3779cab9d679ae76f000000000000000000000000000000000000000000000000000000000001fa4000000000000000000000000000000000000000000000000000000000000697800000000000000000000000000000000000000000000000000000000000015180000000000000000000000000000000000000000000000000000000000000a8c0

-----Decoded View---------------
Arg [0] : _registry (address): 0xc17D432Bd8e8850Fd7b32B0270f5AfAc65DB0105
Arg [1] : _guardianStorage (address): 0x44DA3A8051bA88EAB0440DB3779cAB9D679ae76f
Arg [2] : _recoveryPeriod (uint256): 129600
Arg [3] : _lockPeriod (uint256): 432000
Arg [4] : _securityPeriod (uint256): 86400
Arg [5] : _securityWindow (uint256): 43200

-----Encoded View---------------
6 Constructor Arguments found :
Arg [0] : 000000000000000000000000c17d432bd8e8850fd7b32b0270f5afac65db0105
Arg [1] : 00000000000000000000000044da3a8051ba88eab0440db3779cab9d679ae76f
Arg [2] : 000000000000000000000000000000000000000000000000000000000001fa40
Arg [3] : 0000000000000000000000000000000000000000000000000000000000069780
Arg [4] : 0000000000000000000000000000000000000000000000000000000000015180
Arg [5] : 000000000000000000000000000000000000000000000000000000000000a8c0


Deployed ByteCode Sourcemap

50844:8140:0:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;50844:8140:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;51902:29;;;:::i;:::-;;;;;;;;;;;;;;;;51644;;;:::i;30063:120::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;30063:120:0;-1:-1:-1;;;;;30063:120:0;;:::i;:::-;;41074:133;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;41074:133:0;-1:-1:-1;;;;;41074:133:0;;:::i;55073:470::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;55073:470:0;-1:-1:-1;;;;;55073:470:0;;:::i;58055:926::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;58055:926:0;;;;;;;;;;;;;;;21:11:-1;5:28;;2:2;;;46:1;43;36:12;2:2;58055:926:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;58055:926:0;;;;;;100:9:-1;95:1;81:12;77:20;67:8;63:35;60:50;39:11;25:12;22:29;11:107;8:2;;;131:1;128;121:12;8:2;58055:926:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;58055:926:0;;-1:-1:-1;58055:926:0;;-1:-1:-1;;;;;58055:926:0:i;51700:25::-;;;:::i;30384:258::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;30384:258:0;;;;;;;;;;:::i;56446:308::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;56446:308:0;;;;;;;;;;:::i;51799:29::-;;;:::i;56891:286::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;56891:286:0;-1:-1:-1;;;;;56891:286:0;;:::i;:::-;;;;-1:-1:-1;;;;;56891:286:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;30855:176;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;30855:176:0;-1:-1:-1;;;;;30855:176:0;;:::i;39474:1485::-;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;-1:-1;;;;;39474:1485:0;;;;;;;;;;;;;;;21:11:-1;5:28;;2:2;;;46:1;43;36:12;2:2;39474:1485:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;39474:1485:0;;;;;;100:9:-1;95:1;81:12;77:20;67:8;63:35;60:50;39:11;25:12;22:29;11:107;8:2;;;131:1;128;121:12;8:2;39474:1485:0;;;;;;;;;;;;;;21:11:-1;5:28;;2:2;;;46:1;43;36:12;2:2;39474:1485:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;39474:1485:0;;;;;;100:9:-1;95:1;81:12;77:20;67:8;63:35;60:50;39:11;25:12;22:29;11:107;8:2;;;131:1;128;121:12;8:2;39474:1485:0;;-1:-1:-1;39474:1485:0;-1:-1:-1;39474:1485:0;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;54245:598;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;54245:598:0;;;;;;;;;;:::i;55758:339::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;55758:339:0;-1:-1:-1;;;;;55758:339:0;;:::i;37239:49::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;37239:49:0;-1:-1:-1;;;;;37239:49:0;;:::i;51979:38::-;;;:::i;:::-;;;;-1:-1:-1;;;;;51979:38:0;;;;;;;;;;;;;;51902:29;;;;:::o;51644:::-;;;;:::o;30063:120::-;30115:7;29227:10;-1:-1:-1;;;;;29227:30:0;;;29219:68;;;;;-1:-1:-1;;;;;;;;;;;29219:68:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;30140:35;;;-1:-1:-1;;;;;30140:35:0;;;;;;;;;;;;;;;30063:120;;:::o;41074:133::-;-1:-1:-1;;;;;41168:25:0;41135:13;41168:25;;;:7;:25;;;;;:31;;41074:133::o;55073:470::-;-1:-1:-1;;;;;52647:33:0;;52696:1;52647:33;;;:15;:33;;;;;:46;:33;;:46;;;;;;:50;52639:100;;;;-1:-1:-1;;;;;;;;;;;52639:100:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;55197:33:0;;55165:29;55197:33;;;:15;:33;;;;;55263:19;;;;;;;;;55256:3;55249:33;;;;55241:85;;;;-1:-1:-1;;;;;;;;;;;55241:85:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;55354:15;;55337:33;;;;;;-1:-1:-1;;;;;55354:15:0;;;55337:33;;;;;;:16;;;;;;:33;;;;;55354:15;;55337:33;;;;;;;;55354:15;55337:16;:33;;;5:2:-1;;;;30:1;27;20:12;5:2;55337:33:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;55422:15:0;;55386:52;;-1:-1:-1;;;;;55422:15:0;;;;-1:-1:-1;55386:52:0;;;;-1:-1:-1;55386:52:0;;55422:15;;55386:52;55449:15;;:35;;;;;;-1:-1:-1;;;;;55449:35:0;;;;;;;:15;:35;;;;;;;;:15;;;:23;;:35;;;;;:15;;:35;;;;;;:15;;:35;;;5:2:-1;;;;30:1;27;20:12;5:2;55449:35:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;;;;;;;55502:33:0;;;;;;;:15;:33;;;;;55495:40;-1:-1:-1;;;55073:470:0:o;58055:926::-;58147:7;58167:15;58185:21;58200:5;58185:14;:21::i;:::-;51017:45;;;;;;;;;;;;;;;;58167:39;;-1:-1:-1;;;58221:35:0;;;;;;58217:261;;;58296:15;;:38;;;;;;-1:-1:-1;;;;;58296:38:0;;;;;;;;;58273:20;;58296:15;;;;;:29;;:38;;;;;;;;;;;;;;;:15;:38;;;5:2:-1;;;;30:1;27;20:12;5:2;58296:38:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;58296:38:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;58296:38:0;;-1:-1:-1;58375:1:0;58357:19;;58349:62;;;;;-1:-1:-1;;;;;;;;;;;58349:62:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;58433:33;58447:15;58464:1;58433:13;:33::i;:::-;58426:40;;;;;;58217:261;51129:38;;;;;;;;;;;;;;;;-1:-1:-1;;58492:36:0;;;;;;58488:77;;;58552:1;58545:8;;;;;58488:77;51232:36;;;;;;;;;;;;;;;;-1:-1:-1;;58579:34:0;;;;;;58575:143;;;-1:-1:-1;;;;;58651:33:0;;;;;;:15;:33;;;;;:47;58637:69;;58701:1;58651:47;;;;;;;:51;58637:69;58704:1;58637:13;:69::i;:::-;58630:76;;;;;58575:143;51336:47;;;;;;;;;;;;;;;;;;58732:37;;;:8;:37;;;;58728:207;;;58825:15;;:38;;;;;;-1:-1:-1;;;;;58825:38:0;;;;;;;;;58786:22;;58811:56;;58825:15;;:29;;:38;;;;;;;;;;;;;;:15;:38;;;5:2:-1;;;;30:1;27;20:12;5:2;58825:38:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;58825:38:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;58825:38:0;58865:1;58811:13;:56::i;:::-;58786:81;;58889:34;58902:17;58921:1;58889:12;:34::i;58728:207::-;58945:28;;;-1:-1:-1;;;;;;;;;;;58945:28:0;;;;;;;;;;;;;;;;;;;;;;;;;;;58055:926;;;;;:::o;51700:25::-;;;;:::o;30384:258::-;30470:7;29779:28;29787:7;29796:10;29779:7;:28::i;:::-;29771:87;;;;;;-1:-1:-1;;;;;;;;;;;29771:87:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30498:8;;:45;;;;;;-1:-1:-1;;;;;30498:45:0;;;;;;;;;:8;;;;;:27;;:45;;;;;;;;;;;;;;:8;:45;;;5:2:-1;;;;30:1;27;20:12;5:2;30498:45:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;30498:45:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;30498:45:0;30490:86;;;;;;;-1:-1:-1;;;;;;;;;;;30490:86:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;30587:47;;;;;;-1:-1:-1;;;;;30587:47:0;;;;;;;30629:4;30587:47;;;;;;:23;;;;;;:47;;;;;-1:-1:-1;;30587:47:0;;;;;;;;-1:-1:-1;30587:23:0;:47;;;5:2:-1;;;;30:1;27;20:12;5:2;30587:47:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;30587:47:0;;;;30384:258;;;:::o;56446:308::-;37730:10;37752:4;37730:27;37722:72;;;;;-1:-1:-1;;;;;;;;;;;37722:72:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;28675:15;;:33;;;;;;-1:-1:-1;;;;;28675:33:0;;;;;;;;;56550:7;;28675:15;;;;;:24;;:33;;;;;;;;;;;;;;;:15;:33;;;5:2:-1;;;;30:1;27;20:12;5:2;28675:33:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;28675:33:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;28675:33:0;28674:34;28666:74;;;;;-1:-1:-1;;;;;;;;;;;28666:74:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;56578:23:0;;;;56570:72;;;;-1:-1:-1;;;;;;;;;;;56570:72:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;56653:7;-1:-1:-1;;;;;56653:16:0;;56670:9;56653:27;;;;;;;;;;;;;-1:-1:-1;;;;;56653:27:0;-1:-1:-1;;;;;56653:27:0;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;56653:27:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;56698:48:0;;-1:-1:-1;;;;;56698:48:0;;;;-1:-1:-1;56698:48:0;;;-1:-1:-1;56698:48:0;;;;;37805:1;56446:308;;:::o;51799:29::-;;;;:::o;56891:286::-;-1:-1:-1;;;;;57058:33:0;;;56952:16;57058:33;;;:15;:33;;;;;57110:15;;;;;57127:19;;;;;;57148:20;;;;;;56891:286::o;30855:176::-;30926:38;;;;;;30958:4;30926:38;;;;;;30913:10;;-1:-1:-1;;;;;30926:23:0;;;;;:38;;;;;;;;;;;;;;;:23;:38;;;5:2:-1;;;;30:1;27;20:12;5:2;30926:38:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;30926:38:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;30926:38:0;31006:8;;;30975:48;;;;;;-1:-1:-1;;;;;31006:8:0;;;30975:48;;;;;;;;;;;;30926:38;;-1:-1:-1;30975:22:0;;;;;;:48;;;;;30926:38;;30975:48;;;;;;;;;;;:22;:48;;;5:2:-1;;;;30:1;27;20:12;5:2;30975:48:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;30975:48:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;30855:176:0:o;39474:1485::-;39712:12;39742:13;39758:9;39742:25;;39778:16;39797:84;39817:4;39832:7;39842:1;39845:5;;39797:84;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;39852:6:0;;-1:-1:-1;39860:9:0;;-1:-1:-1;39871:9:0;;-1:-1:-1;39797:11:0;:84::i;:::-;39778:103;;39900:51;39925:7;39934:6;39942:8;39900:24;:51::i;:::-;39892:85;;;;;;;-1:-1:-1;;;;;;;;;;;39892:85:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;39996:35;40015:7;40025:5;;39996:35;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;39996:10:0;;-1:-1:-1;;;39996:35:0:i;:::-;39988:78;;;;;;;-1:-1:-1;;;;;;;;;;;39988:78:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;40077:26;40106:37;40128:7;40137:5;;40106:37;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;40106:21:0;;-1:-1:-1;;;40106:37:0:i;:::-;40077:66;-1:-1:-1;40183:2:0;40162:23;;:45;;40154:88;;;;;-1:-1:-1;;;;;;;;;;;40154:88:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;40261:23;;;:84;;;40288:57;40307:7;40316:5;;40288:57;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;;40288:57:0;;;;137:4:-1;40288:57:0;;;;;;;;;;;;;;;;;40323:8;;-1:-1:-1;40288:57:0;-1:-1:-1;40333:11:0;;;;;;40288:57;;40333:11;;;;40288:57;1:33:-1;99:1;81:16;;74:27;;;;-1:-1;40288:18:0;;-1:-1:-1;;;40288:57:0:i;:::-;40253:119;;;;;;;-1:-1:-1;;;;;;;;;;;40253:119:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;40580:63;40593:7;40602:9;40613;40624:18;40580:12;:63::i;:::-;40576:304;;;40745:4;-1:-1:-1;;;;;40737:18:0;40756:5;;40737:25;;;;;30:3:-1;22:6;14;1:33;40737:25:0;;45:16:-1;;;-1:-1;40737:25:0;;-1:-1:-1;40737:25:0;;-1:-1:-1;;40737:25:0;;;;;;;;;;;;14:1:-1;21;16:31;;;;75:4;69:11;64:16;;144:4;140:9;133:4;115:16;111:27;107:43;104:1;100:51;94:4;87:65;169:16;166:1;159:27;225:16;222:1;215:4;212:1;208:12;193:49;7:242;;16:31;36:4;31:9;;7:242;;40724:38:0;;;;;40777:91;40784:7;40804:9;40793:8;:20;40815:9;40826;40837:18;40857:10;40777:6;:91::i;:::-;40895:56;;;;;;;;;;;;-1:-1:-1;;;;;40895:56:0;;;;;;;;;;;;39474:1485;;;;;;;;;;;;;:::o;54245:598::-;37730:10;37752:4;37730:27;37722:72;;;;;-1:-1:-1;;;;;;;;;;;37722:72:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;52912:33:0;;;;;;:15;:33;;;;;:46;:33;;:46;;;;;:51;52904:103;;;;-1:-1:-1;;;;;;;;;;;52904:103:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;54374:23:0;;;;54366:71;;;;-1:-1:-1;;;;;;;;;;;54366:71:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;54480:33:0;;;54448:29;54480:33;;;:15;:33;;;;;;;;;54524:27;;;;;;;;;;;;;54597:14;;;54562:50;54591:3;:20;;;54562:50;;;;;;;;;;;;;54653:15;;:38;;;;;;;;;;;;;;54480:33;;54653:15;;;;;:29;;:38;;;;;54480:33;54653:38;;;;;;:15;:38;;;5:2:-1;;;;30:1;27;20:12;5:2;54653:38:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;54653:38:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;54653:38:0;54623:69;;;;;;;;;;;;;;;54703:15;;54742:10;;54703:50;;;;;;-1:-1:-1;;;;;54703:50:0;;;;;;;54736:3;:16;;;54703:50;;;;;;:15;;;;;:23;;:50;;;;;54623:20;;54703:50;;;;;;;54623:20;54703:15;:50;;;5:2:-1;;;;30:1;27;20:12;5:2;54703:50:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;54815:19:0;;54769:66;;;54815:19;;;;;;54769:66;;;-1:-1:-1;;;;;54769:66:0;;;;-1:-1:-1;54769:66:0;;;-1:-1:-1;54769:66:0;;;;;;;;;;53018:1;37805;54245:598;;:::o;55758:339::-;37730:10;37752:4;37730:27;37722:72;;;;;-1:-1:-1;;;;;;;;;;;37722:72:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;52647:33:0;;52696:1;52647:33;;;:15;:33;;;;;:46;:33;;:46;;;;;;:50;52639:100;;;;-1:-1:-1;;;;;;;;;;;52639:100:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;55892:33:0;;;55860:29;55892:33;;;:15;:33;;;;;;55976:15;;55941:51;;55892:33;;55976:15;;;;;55892:33;55941:51;;;56003:15;;:35;;;;;;-1:-1:-1;;;;;56003:35:0;;;;;;;:15;:35;;;;;;;;:15;;;:23;;:35;;;;;:15;;:35;;;;;;:15;;:35;;;5:2:-1;;;;30:1;27;20:12;37239:49:0;;;;;;;;;;;;;:::o;51979:38::-;;;-1:-1:-1;;;;;51979:38:0;;:::o;48737:300::-;48804:13;48854:1;48838:5;:12;:17;;48830:56;;;;;;;-1:-1:-1;;;;;;;;;;;48830:56:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;49013:4:0;49002:16;48996:23;;48971:59::o;26441:218::-;26500:7;26520:9;26536:1;26532;:5;;;;;;;;26520:17;;26555:1;26551;:5;;;;;;;;:10;26548:104;;;26585:1;-1:-1:-1;26578:8:0;;26548:104;26639:1;26635:5;;-1:-1:-1;26628:12:0;;25961:150;26019:7;26051:5;;;26075:6;;;;26067:15;;;;;;26102:1;25961:150;-1:-1:-1;;;25961:150:0:o;31216:131::-;31291:4;31334:5;-1:-1:-1;;;;;31315:24:0;:7;-1:-1:-1;;;;;31315:13:0;;:15;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;31315:15:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;31315:15:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;31315:15:0;-1:-1:-1;;;;;31315:24:0;;;31216:131;-1:-1:-1;;;31216:131:0:o;41896:528::-;42309:94;;42326:10;42309:94;;;;;;;42155:7;42309:94;;;;;;;-1:-1:-1;;;;;42309:94:0;;;;;;;;;;;;;;;;;;;;;;;;42155:7;;;;42347:5;;42354:3;;42359:6;;42367:5;;42374:6;;42382:9;;42393;;42309:94;;;;;;;;;;;;;36:153:-1;66:2;58:11;;36:153;;176:10;;164:23;;-1:-1;;139:12;;;;98:2;89:12;;;;114;36:153;;;299:10;344;;263:2;259:12;;;254:3;250:22;-1:-1;;246:30;311:9;;295:26;;;340:21;;377:20;365:33;;42309:94:0;;;;;-1:-1:-1;42309:94:0;;;;;;;-1:-1:-1;42309:94:0;;;;;;;;;;26:21:-1;;;22:32;;6:49;;42309:94:0;;;;;42299:105;;;;;;42211:204;;;;;;;;;;;;;;;26:21:-1;;;22:32;;;6:49;;42211:204:0;;;;;;42187:229;;;;;;41896:528;-1:-1:-1;;;;;;;;;;;;;;41896:528:0:o;42637:318::-;-1:-1:-1;;;;;42765:25:0;;42744:4;42765:25;;;:7;:25;;;;;;;;:47;;;:36;;;;:47;;;;;;;;:55;;;42761:100;;;-1:-1:-1;42844:5:0;42837:12;;42761:100;-1:-1:-1;;;;;;42871:25:0;;;;;;;;:7;:25;;;;;;;;:47;;;42921:4;42871:36;;;:47;;;;;:54;;-1:-1:-1;;42871:54:0;;;;;-1:-1:-1;42921:4:0;42637:318::o;49285:431::-;49364:4;49405:2;49389:5;:12;:18;;49381:53;;;;;;;-1:-1:-1;;;;;;;;;;;49381:53:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;49653:4:0;49642:16;49636:23;-1:-1:-1;;;;;49687:21:0;;;;;;;49285:431::o;57276:771::-;57464:4;57486:24;57513:21;57528:5;57513:14;:21::i;:::-;57486:48;;51336:47;;;;;;;;;;;;;;;;;;;57549:46;;;:17;:46;;;;57545:495;;;57619:76;57638:7;57647:9;57658:11;57671:23;57619:18;:76::i;:::-;57612:83;;;;;57545:495;51017:45;;;;;;;;;;;;;;;;-1:-1:-1;;57717:44:0;;;;;;57713:327;;;57785:78;57804:7;57813:9;57824:11;57837:25;57785:18;:78::i;57713:327::-;51232:36;;;;;;;;;;;;;;;;-1:-1:-1;;57885:43:0;;;;;;57881:159;;;57952:76;57971:7;57980:9;57991:11;58004:23;57952:18;:76::i;57881:159::-;57276:771;;;;;;;;:::o;48289:362::-;48403:4;48436:1;48424:9;:13;:45;;;;;48468:1;48454:11;:15;48424:45;:157;;;;;48525:9;48514:8;:20;48495:7;-1:-1:-1;;;;;48487:24:0;;:47;:93;;;-1:-1:-1;48538:33:0;;;;;;48565:4;48538:33;;;;;;-1:-1:-1;;;;;48538:18:0;;;;;:33;;;;;;;;;;;;;;:18;:33;;;5:2:-1;;;;30:1;27;20:12;5:2;48538:33:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;48538:33:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;48538:33:0;:42;48487:93;48420:202;;;-1:-1:-1;48605:5:0;48598:12;;48420:202;-1:-1:-1;48639:4:0;48289:362;;;;;;:::o;47284:769::-;47515:5;:16;;47498:14;47726:13;;:32;;;;;47757:1;47743:11;:15;47726:32;:55;;;;;47772:9;47762:6;:19;;47726:55;47722:324;;;47814:11;47802:9;:23;47798:161;;;47864:11;47855:20;47798:161;;;47925:18;;47798:161;47973:61;47994:7;48004:8;48014:6;48022:11;;;;;;;;;;;;;47973:12;:61::i;:::-;;47284:769;;;;;;;:::o;44152:1546::-;44344:4;;44408:26;44344:4;44449:7;:34;;;;;;;;;;:61;;;;44508:2;44487:11;:18;:23;44449:61;44445:192;;;44539:15;;:37;;;;;;-1:-1:-1;;;;;44539:37:0;;;;;;;;;:15;;;;;:28;;:37;;;;;:15;;:37;;;;;;;:15;:37;;;5:2:-1;;;;30:1;27;20:12;5:2;44539:37:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;44539:37:0;;;;;;39:16:-1;36:1;17:17;2:54;101:4;44539:37:0;80:15:-1;;;-1:-1;;76:31;65:43;;120:4;113:20;13:2;5:11;;2:2;;;29:1;26;19:12;2:2;44539:37:0;;;;;;19:11:-1;14:3;11:20;8:2;;;44:1;41;34:12;8:2;62:21;;123:4;114:14;;138:31;;;135:2;;;182:1;179;172:12;135:2;219:3;213:10;331:9;325:2;311:12;307:21;289:16;285:44;282:59;261:11;247:12;244:29;233:116;230:2;;;362:1;359;352:12;230:2;-1:-1;44539:37:0;;-1:-1:-1;;;;;44445:192:0;44647:15;;44675:994;44697:18;;44718:2;;44697:23;44693:1;:27;;;44675:994;;;44742:14;44759:40;44773:9;44784:11;44797:1;44759:40;;:13;:40::i;:::-;44742:57;-1:-1:-1;44820:6:0;;;;44816:530;;;44862:23;44851:7;:34;;;;;;;;;44847:484;;;44965:24;44973:7;44982:6;44965:7;:24::i;:::-;44961:89;;;45018:8;;;44961:89;45079:5;45072:12;;;;;;;;;44847:484;45125:23;45114:7;:34;;;;;;;;;45110:221;;;45227:24;45235:7;45244:6;45227:7;:24::i;:::-;45223:89;;;45280:8;;;45223:89;-1:-1:-1;;;;;45364:20:0;;;;;;;45360:102;;45412:5;45405:12;;;;;;;;;45360:102;45489:6;45476:19;;45536:43;45561:9;45572:6;45536:24;:43::i;:::-;45510:69;-1:-1:-1;45510:69:0;-1:-1:-1;45598:11:0;;45594:64;;;45637:5;45630:12;;;;;;;;;45594:64;44675:994;;44722:3;;44675:994;;;-1:-1:-1;45686:4:0;;44152:1546;-1:-1:-1;;;;;;;;44152:1546:0:o;31623:847::-;31729:17;31759:12;31860:7;-1:-1:-1;;;;;31860:12:0;31930:3;31935:6;31943:5;31873:76;;;;;;-1:-1:-1;;;;;31873:76:0;-1:-1:-1;;;;;31873:76:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;23:1:-1;8:100;33:3;30:1;27:10;8:100;;;90:11;;;84:18;71:11;;;64:39;52:2;45:10;8:100;;;12:14;31873:76:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;31873:76:0;;;-1:-1:-1;;26:21;;;22:32;6:49;;31873:76:0;;;49:4:-1;25:18;;61:17;;31873:76:0;182:15:-1;31873:76:0;179:29:-1;160:49;;31860:90:0;;;;31873:76;;-1:-1:-1;31860:90:0;-1:-1:-1;31860:90:0;;-1:-1:-1;25:18;-1:-1;31860:90:0;-1:-1:-1;31860:90:0;;25:18:-1;36:153;66:2;58:11;;36:153;;176:10;;164:23;;-1:-1;;139:12;;;;98:2;89:12;;;;114;36:153;;;274:1;267:3;263:2;259:12;254:3;250:22;246:30;315:4;311:9;305:3;299:10;295:26;356:4;350:3;344:10;340:21;389:7;380;377:20;372:3;365:33;3:399;;;31860:90:0;;;;;;;;;;;;;;;;;;;;;;;;14:1:-1;21;16:31;;;;75:4;69:11;64:16;;144:4;140:9;133:4;115:16;111:27;107:43;104:1;100:51;94:4;87:65;169:16;166:1;159:27;225:16;222:1;215:4;212:1;208:12;193:49;7:242;;16:31;36:4;31:9;;7:242;-1:-1;31842:108:0;-1:-1:-1;31842:108:0;-1:-1:-1;31842:108:0;31965:26;;;;;31990:1;31976:4;:11;:15;31965:26;31961:502;;;32110:4;32099:25;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;32099:25:0;;;;;;19:11:-1;14:3;11:20;8:2;;;44:1;41;34:12;8:2;62:21;;123:4;114:14;;138:31;;;135:2;;;182:1;179;172:12;135:2;213:10;;261:11;244:29;;285:43;;;282:58;-1:-1;233:115;230:2;;;361:1;358;351:12;230:2;-1:-1;32099:25:0;;-1:-1:-1;31961:502:0;;-1:-1:-1;;;;31961:502:0;;32160:1;32146:4;:11;:15;32142:321;;;32296:14;32293:1;32290;32275:36;32339:14;32336:1;32329:25;32256:113;32391:7;32390:8;32386:77;;;32415:36;;;-1:-1:-1;;;;;;;;;;;32415:36:0;;;;;;;;;;;;;;;;;;;;;;;;;;;45972:836;46501:4;46497:16;;;46471:44;;46492:4;46471:44;;46465:51;46562:4;46541:44;;46535:51;46615:44;;;;46609:51;46078:7;;46662:4;46605:62;;;;;46701:2;46696:7;;;:18;;;46707:1;:7;;46712:2;46707:7;46696:18;46688:27;;;;;;;;46769:31;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;46769:31:0;;;;;;;;;;;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;46769:31:0;;-1:-1:-1;;46769:31:0;;;45972:836;-1:-1:-1;;;;;;;;45972:836:0:o;33638:1185::-;33729:4;33735:16;33768:10;:17;33789:1;33768:22;:49;;;-1:-1:-1;;;;;;33794:23:0;;;33768:49;33764:108;;;-1:-1:-1;33842:5:0;;-1:-1:-1;33849:10:0;33834:26;;33764:108;33882:12;33897:5;33882:20;;33913:33;33983:1;33963:10;:17;:21;33949:36;;;;;;;;;;;;;;;;;;;;;;29:2:-1;21:6;17:15;117:4;105:10;97:6;88:34;136:17;;-1:-1;33949:36:0;-1:-1:-1;33913:72:0;-1:-1:-1;33996:13:0;;34024:718;34048:10;:17;34044:1;:21;34024:718;;;34092:7;34091:8;34087:493;;;34199:10;34210:1;34199:13;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;34186:26:0;:9;-1:-1:-1;;;;;34186:26:0;;34182:120;;;34247:4;34237:14;;34274:8;;34182:120;34405:25;34416:10;34427:1;34416:13;;;;;;;;;;;;;;;;;;34405:10;:25::i;:::-;:70;;;;;34434:41;34450:10;34461:1;34450:13;;;;;;;;;;;;;;;;;;34465:9;34434:15;:41::i;:::-;34401:164;;;34510:4;34500:14;;34537:8;;34401:164;34606:16;:23;34598:5;:31;34594:137;;;34676:10;34687:1;34676:13;;;;;;;;;;;;;;;;;;34650:16;34667:5;34650:23;;;;;;;;;;-1:-1:-1;;;;;34650:39:0;;;:23;;;;;;;;;;:39;34708:7;;;;;34594:137;34067:3;;34024:718;;;;34759:7;:56;;34797:5;34804:10;34759:56;;;34770:4;34776:16;34759:56;34752:63;;;;;;;33638:1185;;;;;;:::o;34928:258::-;34986:4;35122:18;;35169:8;;;;34928:258::o;35466:541::-;35623:20;;;;;;;;;;;;;;;;35780:15;;;35549:4;;;;35623:20;35867:4;35623:20;35867:4;35623:20;35840:9;35834:4;35823:49;35900:1;35892:6;35889:13;35886:2;;;35937:3;35931:10;35922:19;;35886:2;35729:238;;35993:6;-1:-1:-1;;;;;35984:15:0;:5;-1:-1:-1;;;;;35984:15:0;;35977:22;;;;35466:541;;;;:::o

Swarm Source

bzzr://848907040818e3346c3e6c43f000ac1b896832fc10bd65e67c18fda3fff5b9a0
Block Transaction Difficulty Gas Used Reward
Block Uncle Number Difficulty Gas Used Reward
Loading
Loading
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.

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.