ETH Price: $3,345.65 (-1.55%)

Contract

0x963F86DA34Cf2CE619d4B8e5cE96577943f95B6b
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Token Holdings

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Execute103479142020-06-27 12:39:171644 days ago1593261557IN
0x963F86DA...943f95B6b
0 ETH0.0034594843.75
Execute103411472020-06-26 11:34:501645 days ago1593171290IN
0x963F86DA...943f95B6b
0 ETH0.0073589243.75
Execute103076722020-06-21 7:15:201651 days ago1592723720IN
0x963F86DA...943f95B6b
0 ETH0.0040225931.25
Execute103076662020-06-21 7:13:051651 days ago1592723585IN
0x963F86DA...943f95B6b
0 ETH0.0052558431.25
Execute102984022020-06-19 20:40:591652 days ago1592599259IN
0x963F86DA...943f95B6b
0 ETH0.0091819128.75
Execute102943422020-06-19 5:44:221653 days ago1592545462IN
0x963F86DA...943f95B6b
0 ETH0.0069384141.25
Execute102943392020-06-19 5:43:511653 days ago1592545431IN
0x963F86DA...943f95B6b
0 ETH0.0053063541.25
Execute102561602020-06-13 8:05:041659 days ago1592035504IN
0x963F86DA...943f95B6b
0 ETH0.0051801530.8
Execute102492292020-06-12 6:24:331660 days ago1591943073IN
0x963F86DA...943f95B6b
0 ETH0.0057347634.1
Execute102460642020-06-11 18:39:051660 days ago1591900745IN
0x963F86DA...943f95B6b
0 ETH0.0096196157.2
Execute102460582020-06-11 18:37:101660 days ago1591900630IN
0x963F86DA...943f95B6b
0 ETH0.0096212657.2
Execute102408702020-06-10 23:18:511661 days ago1591831131IN
0x963F86DA...943f95B6b
0 ETH0.0051803130.8
Execute102359482020-06-10 5:02:221662 days ago1591765342IN
0x963F86DA...943f95B6b
0 ETH0.0068454140.7
Execute102335812020-06-09 20:07:111662 days ago1591733231IN
0x963F86DA...943f95B6b
0 ETH0.0055501733
Execute102296892020-06-09 5:34:491663 days ago1591680889IN
0x963F86DA...943f95B6b
0 ETH0.0105392433
Execute102294442020-06-09 4:41:231663 days ago1591677683IN
0x963F86DA...943f95B6b
0 ETH0.0089986637.4
Execute102294362020-06-09 4:38:171663 days ago1591677497IN
0x963F86DA...943f95B6b
0 ETH0.0119444737.4
Execute102294072020-06-09 4:31:581663 days ago1591677118IN
0x963F86DA...943f95B6b
0 ETH0.0119444737.4
Execute102293802020-06-09 4:25:341663 days ago1591676734IN
0x963F86DA...943f95B6b
0 ETH0.0126466139.6
Execute102284282020-06-09 0:49:581663 days ago1591663798IN
0x963F86DA...943f95B6b
0 ETH0.0119451137.4
Execute102123742020-06-06 13:13:411665 days ago1591449221IN
0x963F86DA...943f95B6b
0 ETH0.0070302141.8
Execute102108582020-06-06 7:32:581666 days ago1591428778IN
0x963F86DA...943f95B6b
0 ETH0.0036814728.6
Execute102108442020-06-06 7:30:371666 days ago1591428637IN
0x963F86DA...943f95B6b
0 ETH0.0048102928.6
Execute102108302020-06-06 7:27:451666 days ago1591428465IN
0x963F86DA...943f95B6b
0 ETH0.004995329.7
Execute102108252020-06-06 7:26:381666 days ago1591428398IN
0x963F86DA...943f95B6b
0 ETH0.0046651229.7
View all transactions

View more zero value Internal Transactions in Advanced View mode

Advanced mode:
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
MakerManager

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 2019-12-02
*/

/**
 *Submitted for verification at Etherscan.io on 2019-12-02
*/

pragma solidity ^0.5.4;

/**
 * ERC20 contract interface.
 */
contract ERC20 {
    function totalSupply() public view returns (uint);
    function decimals() public view returns (uint);
    function balanceOf(address tokenOwner) public view returns (uint balance);
    function allowance(address tokenOwner, address spender) public view returns (uint remaining);
    function transfer(address to, uint tokens) public returns (bool success);
    function approve(address spender, uint tokens) public returns (bool success);
    function transferFrom(address from, address to, uint tokens) public returns (bool success);
}

/**
 * @title 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 {
    function init(BaseWallet _wallet) external;
    function addModule(BaseWallet _wallet, Module _module) external;
    function recoverToken(address _token) external;
}

/**
 * @title BaseWallet
 * @dev Simple modular wallet that authorises modules to call its invoke() method.
 * Based on https://gist.github.com/Arachnid/a619d31f6d32757a4328a428286da186 by 
 * @author Julien Niset - <[email protected]>
 */
contract BaseWallet {
    address public implementation;
    address public owner;
    mapping (address => bool) public authorised;
    mapping (bytes4 => address) public enabled;
    uint public modules;
    function init(address _owner, address[] calldata _modules) external;
    function authoriseModule(address _module, bool _value) external;
    function enableStaticCall(address _module, bytes4 _method) external;
    function setOwner(address _newOwner) external;
    function invoke(address _target, uint _value, bytes calldata _data) external;
    function() external payable;
}

/**
 * @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 {
    function registerModule(address _module, bytes32 _name) external;
    function deregisterModule(address _module) external;
    function registerUpgrader(address _upgrader, bytes32 _name) external;
    function deregisterUpgrader(address _upgrader) external;
    function recoverToken(address _token) external;
    function moduleInfo(address _module) external view returns (bytes32);
    function upgraderInfo(address _upgrader) external view returns (bytes32);
    function isRegisteredModule(address _module) external view returns (bool);
    function isRegisteredModule(address[] calldata _modules) external view returns (bool);
    function isRegisteredUpgrader(address _upgrader) external view returns (bool);
}

/**
 * @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 {
    function addGuardian(BaseWallet _wallet, address _guardian) external;
    function revokeGuardian(BaseWallet _wallet, address _guardian) external;
    function guardianCount(BaseWallet _wallet) external view returns (uint256);
    function getGuardians(BaseWallet _wallet) external view returns (address[] memory);
    function isGuardian(BaseWallet _wallet, address _guardian) external view returns (bool);
    function setLock(BaseWallet _wallet, uint256 _releaseAfter) external;
    function isLocked(BaseWallet _wallet) external view returns (bool);
    function getLock(BaseWallet _wallet) external view returns (uint256);
    function getLocker(BaseWallet _wallet) external view returns (address);
}

// Interface to MakerDAO's Tub contract, used to manage CDPs
contract IMakerCdp {
    IDSValue  public pep; // MKR price feed
    IMakerVox public vox; // DAI price feed

    function sai() external view returns (address);  // DAI
    function skr() external view returns (address);  // PETH
    function gem() external view returns (address);  // WETH
    function gov() external view returns (address);  // MKR

    function lad(bytes32 cup) external view returns (address);
    function ink(bytes32 cup) external view returns (uint);
    function tab(bytes32 cup) external returns (uint);
    function rap(bytes32 cup) external returns (uint);

    function tag() public view returns (uint wad);
    function mat() public view returns (uint ray);
    function per() public view returns (uint ray);
    function safe(bytes32 cup) external returns (bool);
    function ask(uint wad) public view returns (uint);
    function bid(uint wad) public view returns (uint);

    function open() external returns (bytes32 cup);
    function join(uint wad) external; // Join PETH
    function exit(uint wad) external; // Exit PETH
    function give(bytes32 cup, address guy) external;
    function lock(bytes32 cup, uint wad) external;
    function free(bytes32 cup, uint wad) external;
    function draw(bytes32 cup, uint wad) external;
    function wipe(bytes32 cup, uint wad) external;
    function shut(bytes32 cup) external;
    function bite(bytes32 cup) external;
}

interface IMakerVox {
    function par() external returns (uint);
}

interface IDSValue {
    function peek() external view returns (bytes32, bool);
    function read() external view returns (bytes32);
    function poke(bytes32 wut) external;
    function void() external;
} 

interface UniswapFactory {
    function getExchange(address _token) external view returns(address);
}

interface UniswapExchange {
    function getEthToTokenOutputPrice(uint256 _tokens_bought) external view returns (uint256);
    function getEthToTokenInputPrice(uint256 _eth_sold) external view returns (uint256);
    function getTokenToEthOutputPrice(uint256 _eth_bought) external view returns (uint256);
    function getTokenToEthInputPrice(uint256 _tokens_sold) external view returns (uint256);
}

/**
 * @title Interface for a contract that can loan tokens to a wallet.
 * @author Julien Niset - <[email protected]>
 */
interface Loan {

    event LoanOpened(address indexed _wallet, bytes32 indexed _loanId, address _collateral, uint256 _collateralAmount, address _debtToken, uint256 _debtAmount);
    event LoanClosed(address indexed _wallet, bytes32 indexed _loanId);
    event CollateralAdded(address indexed _wallet, bytes32 indexed _loanId, address _collateral, uint256 _collateralAmount);
    event CollateralRemoved(address indexed _wallet, bytes32 indexed _loanId, address _collateral, uint256 _collateralAmount);
    event DebtAdded(address indexed _wallet, bytes32 indexed _loanId, address _debtToken, uint256 _debtAmount);
    event DebtRemoved(address indexed _wallet, bytes32 indexed _loanId, address _debtToken, uint256 _debtAmount);

    /**
     * @dev Opens a collateralized loan.
     * @param _wallet The target wallet.
     * @param _collateral The token used as a collateral.
     * @param _collateralAmount The amount of collateral token provided.
     * @param _debtToken The token borrowed.
     * @param _debtAmount The amount of tokens borrowed.
     * @return (optional) An ID for the loan when the provider enables users to create multiple distinct loans.
     */
    function openLoan(
        BaseWallet _wallet, 
        address _collateral, 
        uint256 _collateralAmount, 
        address _debtToken, 
        uint256 _debtAmount
    ) 
        external 
        returns (bytes32 _loanId);

    /**
     * @dev Closes a collateralized loan by repaying all debts (plus interest) and redeeming all collateral (plus interest).
     * @param _wallet The target wallet.
     * @param _loanId The ID of the loan if any, 0 otherwise.
     */
    function closeLoan(
        BaseWallet _wallet, 
        bytes32 _loanId
    ) 
        external;

    /**
     * @dev Adds collateral to a loan identified by its ID.
     * @param _wallet The target wallet.
     * @param _loanId The ID of the loan if any, 0 otherwise.
     * @param _collateral The token used as a collateral.
     * @param _collateralAmount The amount of collateral to add.
     */
    function addCollateral(
        BaseWallet _wallet, 
        bytes32 _loanId, 
        address _collateral, 
        uint256 _collateralAmount
    ) 
        external;

    /**
     * @dev Removes collateral from a loan identified by its ID.
     * @param _wallet The target wallet.
     * @param _loanId The ID of the loan if any, 0 otherwise.
     * @param _collateral The token used as a collateral.
     * @param _collateralAmount The amount of collateral to remove.
     */
    function removeCollateral(
        BaseWallet _wallet, 
        bytes32 _loanId, 
        address _collateral, 
        uint256 _collateralAmount
    ) 
        external;

    /**
     * @dev Increases the debt by borrowing more token from a loan identified by its ID.
     * @param _wallet The target wallet.
     * @param _loanId The ID of the loan if any, 0 otherwise.
     * @param _debtToken The token borrowed.
     * @param _debtAmount The amount of token to borrow.
     */
    function addDebt(
        BaseWallet _wallet, 
        bytes32 _loanId, 
        address _debtToken, 
        uint256 _debtAmount
    ) 
        external;

    /**
     * @dev Decreases the debt by repaying some token from a loan identified by its ID.
     * @param _wallet The target wallet.
     * @param _loanId The ID of the loan if any, 0 otherwise.
     * @param _debtToken The token to repay.
     * @param _debtAmount The amount of token to repay.
     */
    function removeDebt(
        BaseWallet _wallet, 
        bytes32 _loanId, 
        address _debtToken, 
        uint256 _debtAmount
    ) 
        external;

    /**
     * @dev Gets information about a loan identified by its ID.
     * @param _wallet The target wallet.
     * @param _loanId The ID of the loan if any, 0 otherwise.
     * @return a status [0: no loan, 1: loan is safe, 2: loan is unsafe and can be liquidated, 3: unable to provide info]
     * and a value (in ETH) representing the value that could still be borrowed when status = 1; or the value of the collateral 
     * that should be added to avoid liquidation when status = 2.     
     */
    function getLoan(
        BaseWallet _wallet, 
        bytes32 _loanId
    ) 
        external 
        view 
        returns (uint8 _status, uint256 _ethValue);
}

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

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

    // The adddress of the module registry.
    ModuleRegistry internal registry;

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

    constructor(ModuleRegistry _registry, bytes32 _name) public {
        registry = _registry;
        emit ModuleCreated(_name);
    }

    /**
     * @dev Throws if the sender is not the target wallet of the call.
     */
    modifier onlyWallet(BaseWallet _wallet) {
        require(msg.sender == address(_wallet), "BM: caller must be wallet");
        _;
    }

    /**
     * @dev Throws if the sender is not the owner of the target wallet or the module itself.
     */
    modifier 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) external 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;
    }
}

/**
 * @title RelayerModule
 * @dev Base module containing logic to execute transactions signed by eth-less accounts and sent by a relayer. 
 * @author Julien Niset - <[email protected]>
 */
contract RelayerModule is Module {

    uint256 constant internal BLOCKBOUND = 10000;

    mapping (address => RelayerConfig) public relayer; 

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

    event TransactionExecuted(address indexed wallet, bool indexed success, bytes32 signedHash);

    /**
     * @dev Throws if the call did not go through the execute() method.
     */
    modifier onlyExecute {
        require(msg.sender == address(this), "RM: must be called via execute()");
        _;
    }

    /* ***************** Abstract method ************************* */

    /**
    * @dev Gets the number of valid signatures that must be provided to execute a
    * specific relayed transaction.
    * @param _wallet The target wallet.
    * @param _data The data of the relayed transaction.
    * @return The number of required signatures.
    */
    function getRequiredSignatures(BaseWallet _wallet, bytes memory _data) internal view returns (uint256);

    /**
    * @dev Validates the signatures provided with a relayed transaction.
    * The method MUST throw if one or more signatures are not valid.
    * @param _wallet The target wallet.
    * @param _data The data of the relayed transaction.
    * @param _signHash The signed hash representing the relayed transaction.
    * @param _signatures The signatures as a concatenated byte array.
    */
    function validateSignatures(BaseWallet _wallet, bytes memory _data, bytes32 _signHash, bytes memory _signatures) internal view returns (bool);

    /* ************************************************************ */

    /**
    * @dev Executes a relayed transaction.
    * @param _wallet The target wallet.
    * @param _data The data for the relayed transaction
    * @param _nonce The nonce used to prevent replay attacks.
    * @param _signatures The signatures as a concatenated byte array.
    * @param _gasPrice The gas price to use for the gas refund.
    * @param _gasLimit The gas limit to use for the gas refund.
    */
    function execute(
        BaseWallet _wallet,
        bytes 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: the wallet authorized is different then the target of the relayed data");
        uint256 requiredSignatures = getRequiredSignatures(_wallet, _data);
        if((requiredSignatures * 65) == _signatures.length) {
            if(verifyRefund(_wallet, _gasLimit, _gasPrice, requiredSignatures)) {
                if(requiredSignatures == 0 || validateSignatures(_wallet, _data, signHash, _signatures)) {
                    // solium-disable-next-line security/no-call-value
                    (success,) = address(this).call(_data);
                    refund(_wallet, startGas - gasleft(), _gasPrice, _gasLimit, requiredSignatures, msg.sender);
                }
            }
        }
        emit TransactionExecuted(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;
    }

    /**
    * @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 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); 
        return ecrecover(_signedHash, v, r, s);
    }

    /**
    * @dev Refunds the gas used to the Relayer. 
    * For security reasons the default behavior is to not refund calls with 0 or 1 signatures. 
    * @param _wallet The target wallet.
    * @param _gasUsed The gas used.
    * @param _gasPrice The gas price for the refund.
    * @param _gasLimit The gas limit for the refund.
    * @param _signatures The number of signatures used in the call.
    * @param _relayer The address of the Relayer.
    */
    function refund(BaseWallet _wallet, uint _gasUsed, uint _gasPrice, uint _gasLimit, uint _signatures, address _relayer) internal {
        uint256 amount = 29292 + _gasUsed; // 21000 (transaction) + 7620 (execution of refund) + 672 to log the event + _gasUsed
        // only refund if gas price not null, more than 1 signatures, gas less than gasLimit
        if(_gasPrice > 0 && _signatures > 1 && amount <= _gasLimit) {
            if(_gasPrice > tx.gasprice) {
                amount = amount * tx.gasprice;
            }
            else {
                amount = amount * _gasPrice;
            }
            _wallet.invoke(_relayer, amount, "");
        }
    }

    /**
    * @dev Returns false if the refund is expected to fail.
    * @param _wallet The target wallet.
    * @param _gasUsed The expected gas used.
    * @param _gasPrice The expected gas price for the refund.
    */
    function verifyRefund(BaseWallet _wallet, uint _gasUsed, uint _gasPrice, uint _signatures) internal view returns (bool) {
        if(_gasPrice > 0 
            && _signatures > 1 
            && (address(_wallet).balance < _gasUsed * _gasPrice || _wallet.authorised(address(this)) == false)) {
            return false;
        }
        return true;
    }

    /**
    * @dev Checks that the wallet address provided as the first parameter of the relayed data is the same
    * as the wallet passed as the input of the execute() method. 
    @return false if the addresses are different.
    */
    function verifyData(address _wallet, bytes 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;
    }

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

/**
 * @title OnlyOwnerModule
 * @dev Module that extends BaseModule and RelayerModule for modules where the execute() method
 * must be called with one signature frm the owner.
 * @author Julien Niset - <[email protected]>
 */
contract OnlyOwnerModule is BaseModule, RelayerModule {

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

    // Overrides to use the incremental nonce and save some gas
    function checkAndUpdateUniqueness(BaseWallet _wallet, uint256 _nonce, bytes32 _signHash) internal returns (bool) {
        return checkAndUpdateNonce(_wallet, _nonce);
    }

    function validateSignatures(BaseWallet _wallet, bytes memory _data, bytes32 _signHash, bytes memory _signatures) internal view returns (bool) {
        address signer = recoverSigner(_signHash, _signatures, 0);
        return isOwner(_wallet, signer); // "OOM: signer must be owner"
    }

    function getRequiredSignatures(BaseWallet _wallet, bytes memory _data) internal view returns (uint256) {
        return 1;
    }
}

/**
 * @title MakerManager
 * @dev Module to borrow tokens with MakerDAO
 * @author Olivier VDB - <[email protected]>, Julien Niset - <[email protected]>
 */
contract MakerManager is Loan, BaseModule, RelayerModule, OnlyOwnerModule {

    bytes32 constant NAME = "MakerManager";

    // The Guardian storage 
    GuardianStorage public guardianStorage;
    // The Maker Tub contract
    IMakerCdp public makerCdp;
    // The Uniswap Factory contract
    UniswapFactory public uniswapFactory;

    // Mock token address for ETH
    address constant internal ETH_TOKEN_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;

    // Method signatures to reduce gas cost at depoyment
    bytes4 constant internal CDP_DRAW = bytes4(keccak256("draw(bytes32,uint256)"));
    bytes4 constant internal CDP_WIPE = bytes4(keccak256("wipe(bytes32,uint256)"));
    bytes4 constant internal CDP_SHUT = bytes4(keccak256("shut(bytes32)"));
    bytes4 constant internal CDP_JOIN = bytes4(keccak256("join(uint256)"));
    bytes4 constant internal CDP_LOCK = bytes4(keccak256("lock(bytes32,uint256)"));
    bytes4 constant internal CDP_FREE = bytes4(keccak256("free(bytes32,uint256)"));
    bytes4 constant internal CDP_EXIT = bytes4(keccak256("exit(uint256)"));
    bytes4 constant internal WETH_DEPOSIT = bytes4(keccak256("deposit()"));
    bytes4 constant internal WETH_WITHDRAW = bytes4(keccak256("withdraw(uint256)"));
    bytes4 constant internal ERC20_APPROVE = bytes4(keccak256("approve(address,uint256)"));
    bytes4 constant internal ETH_TOKEN_SWAP_OUTPUT = bytes4(keccak256("ethToTokenSwapOutput(uint256,uint256)"));
    bytes4 constant internal ETH_TOKEN_SWAP_INPUT = bytes4(keccak256("ethToTokenSwapInput(uint256,uint256)"));
    bytes4 constant internal TOKEN_ETH_SWAP_INPUT = bytes4(keccak256("tokenToEthSwapInput(uint256,uint256,uint256)"));

    using SafeMath for uint256;

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

    constructor(
        ModuleRegistry _registry,
        GuardianStorage _guardianStorage,
        IMakerCdp _makerCdp,
        UniswapFactory _uniswapFactory
    )
        BaseModule(_registry, NAME)
        public
    {
        guardianStorage = _guardianStorage;
        makerCdp = _makerCdp;
        uniswapFactory = _uniswapFactory;
    }

    /* ********************************** Implementation of Loan ************************************* */

   /**
     * @dev Opens a collateralized loan.
     * @param _wallet The target wallet.
     * @param _collateral The token used as a collateral (must be 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE).
     * @param _collateralAmount The amount of collateral token provided.
     * @param _debtToken The token borrowed (must be the address of the DAI contract).
     * @param _debtAmount The amount of tokens borrowed.
     * @return The ID of the created CDP.
     */
    function openLoan(
        BaseWallet _wallet, 
        address _collateral, 
        uint256 _collateralAmount, 
        address _debtToken, 
        uint256 _debtAmount
    ) 
        external 
        onlyWalletOwner(_wallet)
        onlyWhenUnlocked(_wallet)
        returns (bytes32 _loanId)
    {
        require(_collateral == ETH_TOKEN_ADDRESS, "Maker: collateral must be ETH");
        require(_debtToken == makerCdp.sai(), "Maker: debt token must be DAI");
        _loanId = openCdp(_wallet, _collateralAmount, _debtAmount, makerCdp);
        emit LoanOpened(address(_wallet), _loanId, _collateral, _collateralAmount, _debtToken, _debtAmount);
    }

    /**
     * @dev Closes a collateralized loan by repaying all debts (plus interest) and redeeming all collateral (plus interest).
     * @param _wallet The target wallet.
     * @param _loanId The ID of the target CDP.
     */
    function closeLoan(
        BaseWallet _wallet, 
        bytes32 _loanId
    ) 
        external
        onlyWalletOwner(_wallet)
        onlyWhenUnlocked(_wallet)
    {
        closeCdp(_wallet, _loanId, makerCdp, uniswapFactory);
        emit LoanClosed(address(_wallet), _loanId);
    }

    /**
     * @dev Adds collateral to a loan identified by its ID.
     * @param _wallet The target wallet.
     * @param _loanId The ID of the target CDP.
     * @param _collateral The token used as a collateral (must be 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE).
     * @param _collateralAmount The amount of collateral to add.
     */
    function addCollateral(
        BaseWallet _wallet, 
        bytes32 _loanId, 
        address _collateral, 
        uint256 _collateralAmount
    ) 
        external
        onlyWalletOwner(_wallet)
        onlyWhenUnlocked(_wallet)
    {
        require(_collateral == ETH_TOKEN_ADDRESS, "Maker: collateral must be ETH");
        addCollateral(_wallet, _loanId, _collateralAmount, makerCdp);
        emit CollateralAdded(address(_wallet), _loanId, _collateral, _collateralAmount);
    }

    /**
     * @dev Removes collateral from a loan identified by its ID.
     * @param _wallet The target wallet.
     * @param _loanId The ID of the target CDP.
     * @param _collateral The token used as a collateral (must be 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE).
     * @param _collateralAmount The amount of collateral to remove.
     */
    function removeCollateral(
        BaseWallet _wallet, 
        bytes32 _loanId, 
        address _collateral, 
        uint256 _collateralAmount
    ) 
        external 
        onlyWalletOwner(_wallet)
        onlyWhenUnlocked(_wallet)
    {
        require(_collateral == ETH_TOKEN_ADDRESS, "Maker: collateral must be ETH");
        removeCollateral(_wallet, _loanId, _collateralAmount, makerCdp);
        emit CollateralRemoved(address(_wallet), _loanId, _collateral, _collateralAmount);
    }

    /**
     * @dev Increases the debt by borrowing more token from a loan identified by its ID.
     * @param _wallet The target wallet.
     * @param _loanId The ID of the target CDP.
     * @param _debtToken The token borrowed (must be the address of the DAI contract).
     * @param _debtAmount The amount of token to borrow.
     */
    function addDebt(
        BaseWallet _wallet,
        bytes32 _loanId,
        address _debtToken,
        uint256 _debtAmount
    )
        external
        onlyWalletOwner(_wallet)
        onlyWhenUnlocked(_wallet)
    {
        require(_debtToken == makerCdp.sai(), "Maker: debt token must be DAI");
        addDebt(_wallet, _loanId, _debtAmount, makerCdp);
        emit DebtAdded(address(_wallet), _loanId, _debtToken, _debtAmount);
    }

    /**
     * @dev Decreases the debt by repaying some token from a loan identified by its ID.
     * @param _wallet The target wallet.
     * @param _loanId The ID of the target CDP.
     * @param _debtToken The token to repay (must be the address of the DAI contract).
     * @param _debtAmount The amount of token to repay.
     */
    function removeDebt(
        BaseWallet _wallet,
        bytes32 _loanId,
        address _debtToken,
        uint256 _debtAmount
    )
        external
        onlyWalletOwner(_wallet)
        onlyWhenUnlocked(_wallet)
    {
        require(_debtToken == makerCdp.sai(), "Maker: debt token must be DAI");
        removeDebt(_wallet, _loanId, _debtAmount, makerCdp, uniswapFactory);
        emit DebtRemoved(address(_wallet), _loanId, _debtToken, _debtAmount);
    }

    /**
     * @dev Gets information about a loan identified by its ID.
     * @param _wallet The target wallet.
     * @param _loanId The ID of the target CDP.
     * @return a status [0: no loan, 1: loan is safe, 2: loan is unsafe and can be liquidated, 3: loan exists but we are unable to provide info] 
     * and a value (in ETH) representing the value that could still be borrowed when status = 1; or the value of the collateral that should be added to 
     * avoid liquidation when status = 2.      
     */
    function getLoan(
        BaseWallet _wallet, 
        bytes32 _loanId
    ) 
        external 
        view 
        returns (uint8 _status, uint256 _ethValue)
    {
        if(exists(_loanId, makerCdp)) {
            return (3,0);
        }
        return (0,0);
    }

    /* *********************************** Maker wrappers ************************************* */

    /* CDP actions */

    /**
     * @dev Lets the owner of a wallet open a new CDP. The owner must have enough ether 
     * in their wallet. The required amount of ether will be automatically converted to 
     * PETH and used as collateral in the CDP.
     * @param _wallet The target wallet
     * @param _pethCollateral The amount of PETH to lock as collateral in the CDP.
     * @param _daiDebt The amount of DAI to draw from the CDP
     * @param _makerCdp The Maker CDP contract
     * @return The id of the created CDP.
     */
    function openCdp(
        BaseWallet _wallet, 
        uint256 _pethCollateral, 
        uint256 _daiDebt,
        IMakerCdp _makerCdp
    ) 
        internal 
        returns (bytes32 _cup)
    {
        // Open CDP (CDP owner will be module)
        _cup = _makerCdp.open();
        // Transfer CDP ownership to wallet
        _makerCdp.give(_cup, address(_wallet));
        // Convert ETH to PETH & lock PETH into CDP
        lockETH(_wallet, _cup, _pethCollateral, _makerCdp);
        // Draw DAI from CDP
        if(_daiDebt > 0) {
            invokeWallet(_wallet, address(_makerCdp), 0, abi.encodeWithSelector(CDP_DRAW, _cup, _daiDebt));
        }
    }

    /**
     * @dev Lets the owner of a CDP add more collateral to their CDP. The owner must have enough ether 
     * in their wallet. The required amount of ether will be automatically converted to 
     * PETH and locked in the CDP.
     * @param _wallet The target wallet
     * @param _cup The id of the CDP.
     * @param _amount The amount of additional PETH to lock as collateral in the CDP.
     * @param _makerCdp The Maker CDP contract
     */
    function addCollateral(
        BaseWallet _wallet, 
        bytes32 _cup,
        uint256 _amount,
        IMakerCdp _makerCdp
    ) 
        internal
    {
        // _wallet must be owner of CDP
        require(address(_wallet) == _makerCdp.lad(_cup), "CM: not CDP owner");
        // convert ETH to PETH & lock PETH into CDP
        lockETH(_wallet, _cup, _amount, _makerCdp);  
    }

    /**
     * @dev Lets the owner of a CDP remove some collateral from their CDP
     * @param _wallet The target wallet
     * @param _cup The id of the CDP.
     * @param _amount The amount of PETH to remove from the CDP.
     * @param _makerCdp The Maker CDP contract
     */
    function removeCollateral(
        BaseWallet _wallet, 
        bytes32 _cup,
        uint256 _amount,
        IMakerCdp _makerCdp
    ) 
        internal
    {
        // unlock PETH from CDP & convert PETH to ETH
        freeETH(_wallet, _cup, _amount, _makerCdp);
    }

    /**
     * @dev Lets the owner of a CDP draw more DAI from their CDP.
     * @param _wallet The target wallet
     * @param _cup The id of the CDP.
     * @param _amount The amount of additional DAI to draw from the CDP.
     * @param _makerCdp The Maker CDP contract
     */
    function addDebt(
        BaseWallet _wallet, 
        bytes32 _cup,
        uint256 _amount,
        IMakerCdp _makerCdp
    ) 
        internal
    {
        // draw DAI from CDP
        invokeWallet(_wallet, address(_makerCdp), 0, abi.encodeWithSelector(CDP_DRAW, _cup, _amount));
    }

    /**
     * @dev Lets the owner of a CDP partially repay their debt. The repayment is made up of 
     * the outstanding DAI debt (including the stability fee if non-zero) plus the MKR governance fee.
     * The method will use the user's MKR tokens in priority and will, if needed, convert the required 
     * amount of ETH to cover for any missing MKR tokens.
     * @param _wallet The target wallet
     * @param _cup The id of the CDP.
     * @param _amount The amount of DAI debt to repay.
     * @param _makerCdp The Maker CDP contract
     * @param _uniswapFactory The Uniswap Factory contract.
     */
    function removeDebt(
        BaseWallet _wallet, 
        bytes32 _cup,
        uint256 _amount,
        IMakerCdp _makerCdp,
        UniswapFactory _uniswapFactory
    ) 
        internal
    {
        // _wallet must be owner of CDP
        require(address(_wallet) == _makerCdp.lad(_cup), "CM: not CDP owner");
        // get governance fee in MKR
        uint256 mkrFee = governanceFeeInMKR(_cup, _amount, _makerCdp);
        // get MKR balance
        address mkrToken = _makerCdp.gov();
        uint256 mkrBalance = ERC20(mkrToken).balanceOf(address(_wallet));
        if (mkrBalance < mkrFee) {
            // Not enough MKR => Convert some ETH into MKR with Uniswap
            address mkrUniswap = _uniswapFactory.getExchange(mkrToken);
            uint256 etherValueOfMKR = UniswapExchange(mkrUniswap).getEthToTokenOutputPrice(mkrFee - mkrBalance);
            invokeWallet(_wallet, mkrUniswap, etherValueOfMKR, abi.encodeWithSelector(ETH_TOKEN_SWAP_OUTPUT, mkrFee - mkrBalance, block.timestamp));
        }
        
        // get DAI balance
        address daiToken =_makerCdp.sai();
        uint256 daiBalance = ERC20(daiToken).balanceOf(address(_wallet));
        if (daiBalance < _amount) {
            // Not enough DAI => Convert some ETH into DAI with Uniswap
            address daiUniswap = _uniswapFactory.getExchange(daiToken);
            uint256 etherValueOfDAI = UniswapExchange(daiUniswap).getEthToTokenOutputPrice(_amount - daiBalance);
            invokeWallet(_wallet, daiUniswap, etherValueOfDAI, abi.encodeWithSelector(ETH_TOKEN_SWAP_OUTPUT, _amount - daiBalance, block.timestamp));
        }

        // Approve DAI to let wipe() repay the DAI debt
        invokeWallet(_wallet, daiToken, 0, abi.encodeWithSelector(ERC20_APPROVE, address(_makerCdp), _amount));
        // Approve MKR to let wipe() pay the MKR governance fee
        invokeWallet(_wallet, mkrToken, 0, abi.encodeWithSelector(ERC20_APPROVE, address(_makerCdp), mkrFee));
        // repay DAI debt and MKR governance fee
        invokeWallet(_wallet, address(_makerCdp), 0, abi.encodeWithSelector(CDP_WIPE, _cup, _amount));
    }

    /**
     * @dev Lets the owner of a CDP close their CDP. The method will 1) repay all debt 
     * and governance fee, 2) free all collateral, and 3) delete the CDP.
     * @param _wallet The target wallet
     * @param _cup The id of the CDP.
     * @param _makerCdp The Maker CDP contract
     * @param _uniswapFactory The Uniswap Factory contract.
     */
    function closeCdp(
        BaseWallet _wallet,
        bytes32 _cup,
        IMakerCdp _makerCdp,
        UniswapFactory _uniswapFactory
    ) 
        internal
    {
        // repay all debt (in DAI) + stability fee (in DAI) + governance fee (in MKR)
        uint debt = daiDebt(_cup, _makerCdp);
        if(debt > 0) removeDebt(_wallet, _cup, debt, _makerCdp, _uniswapFactory);
        // free all ETH collateral
        uint collateral = pethCollateral(_cup, _makerCdp);
        if(collateral > 0) removeCollateral(_wallet, _cup, collateral, _makerCdp);
        // shut the CDP
        invokeWallet(_wallet, address(_makerCdp), 0, abi.encodeWithSelector(CDP_SHUT, _cup));
    }

    /* Convenience methods */

    /**
     * @dev Returns the amount of PETH collateral locked in a CDP.
     * @param _cup The id of the CDP.
     * @param _makerCdp The Maker CDP contract
     * @return the amount of PETH locked in the CDP.
     */
    function pethCollateral(bytes32 _cup, IMakerCdp _makerCdp) public view returns (uint256) { 
        return _makerCdp.ink(_cup);
    }

    /**
     * @dev Returns the amount of DAI debt (including the stability fee if non-zero) drawn from a CDP.
     * @param _cup The id of the CDP.
     * @param _makerCdp The Maker CDP contract
     * @return the amount of DAI drawn from the CDP.
     */
    function daiDebt(bytes32 _cup, IMakerCdp _makerCdp) public returns (uint256) { 
        return _makerCdp.tab(_cup);
    }

    /**
     * @dev Indicates whether a CDP is above the liquidation ratio.
     * @param _cup The id of the CDP.
     * @param _makerCdp The Maker CDP contract
     * @return false if the CDP is in danger of being liquidated.
     */
    function isSafe(bytes32 _cup, IMakerCdp _makerCdp) public returns (bool) { 
        return _makerCdp.safe(_cup);
    }

    /**
     * @dev Checks if a CDP exists.
     * @param _cup The id of the CDP.
     * @param _makerCdp The Maker CDP contract
     * @return true if the CDP exists, false otherwise.
     */
    function exists(bytes32 _cup, IMakerCdp _makerCdp) public view returns (bool) { 
        return _makerCdp.lad(_cup) != address(0);
    }

    /**
     * @dev Max amount of DAI that can still be drawn from a CDP while keeping it above the liquidation ratio. 
     * @param _cup The id of the CDP.
     * @param _makerCdp The Maker CDP contract
     * @return the amount of DAI that can still be drawn from a CDP while keeping it above the liquidation ratio. 
     */
    function maxDaiDrawable(bytes32 _cup, IMakerCdp _makerCdp) public returns (uint256) {
        uint256 maxTab = _makerCdp.ink(_cup).rmul(_makerCdp.tag()).rdiv(_makerCdp.vox().par()).rdiv(_makerCdp.mat());
        return maxTab.sub(_makerCdp.tab(_cup));
    }

    /**
     * @dev Min amount of collateral that needs to be added to a CDP to bring it above the liquidation ratio. 
     * @param _cup The id of the CDP.
     * @param _makerCdp The Maker CDP contract
     * @return the amount of collateral that needs to be added to a CDP to bring it above the liquidation ratio.
     */
    function minCollateralRequired(bytes32 _cup, IMakerCdp _makerCdp) public returns (uint256) {
        uint256 minInk = _makerCdp.tab(_cup).rmul(_makerCdp.mat()).rmul(_makerCdp.vox().par()).rdiv(_makerCdp.tag());
        return minInk.sub(_makerCdp.ink(_cup));
    }

    /**
     * @dev Returns the governance fee in MKR.
     * @param _cup The id of the CDP.
     * @param _daiRefund The amount of DAI debt being repaid.
     * @param _makerCdp The Maker CDP contract
     * @return the governance fee in MKR
     */
    function governanceFeeInMKR(bytes32 _cup, uint256 _daiRefund, IMakerCdp _makerCdp) public returns (uint256 _fee) { 
        uint debt = daiDebt(_cup, _makerCdp);
        if (debt == 0) return 0;
        uint256 feeInDAI = _daiRefund.rmul(_makerCdp.rap(_cup).rdiv(debt));
        (bytes32 daiPerMKR, bool ok) = _makerCdp.pep().peek();
        if (ok && daiPerMKR != 0) _fee = feeInDAI.wdiv(uint(daiPerMKR));
    }

    /**
     * @dev Returns the total MKR governance fee to be paid before this CDP can be closed.
     * @param _cup The id of the CDP.
     * @param _makerCdp The Maker CDP contract
     * @return the total governance fee in MKR
     */
    function totalGovernanceFeeInMKR(bytes32 _cup, IMakerCdp _makerCdp) external returns (uint256 _fee) { 
        return governanceFeeInMKR(_cup, daiDebt(_cup, _makerCdp), _makerCdp);
    }

    /**
     * @dev Minimum amount of PETH that must be locked in a CDP for it to be deemed "safe"
     * @param _cup The id of the CDP.
     * @param _makerCdp The Maker CDP contract
     * @return The minimum amount of PETH to lock in the CDP
     */
    function minRequiredCollateral(bytes32 _cup, IMakerCdp _makerCdp) public returns (uint256 _minCollateral) { 
        _minCollateral = daiDebt(_cup, _makerCdp)    // DAI debt
            .rmul(_makerCdp.vox().par())         // x ~1 USD/DAI 
            .rmul(_makerCdp.mat())               // x 1.5
            .rmul(1010000000000000000000000000) // x (1+1%) cushion
            .rdiv(_makerCdp.tag());              // ÷ ~170 USD/PETH
    }

    /* *********************************** Utilities ************************************* */

    /**
     * @dev Converts a user's ETH into PETH and locks the PETH in a CDP
     * @param _wallet The target wallet
     * @param _cup The id of the CDP.
     * @param _pethAmount The amount of PETH to buy and lock
     * @param _makerCdp The Maker CDP contract
     */
    function lockETH(
        BaseWallet _wallet, 
        bytes32 _cup,
        uint256 _pethAmount,
        IMakerCdp _makerCdp
    ) 
        internal 
    {
        // 1. Convert ETH to PETH
        address wethToken = _makerCdp.gem();
        // Get WETH/PETH rate
        uint ethAmount = _makerCdp.ask(_pethAmount);
        // ETH to WETH
        invokeWallet(_wallet, wethToken, ethAmount, abi.encodeWithSelector(WETH_DEPOSIT));
        // Approve WETH
        invokeWallet(_wallet, wethToken, 0, abi.encodeWithSelector(ERC20_APPROVE, address(_makerCdp), ethAmount));
        // WETH to PETH
        invokeWallet(_wallet, address(_makerCdp), 0, abi.encodeWithSelector(CDP_JOIN, _pethAmount));

        // 2. Lock PETH into CDP
        address pethToken = _makerCdp.skr();
        // Approve PETH
        invokeWallet(_wallet, pethToken, 0, abi.encodeWithSelector(ERC20_APPROVE, address(_makerCdp), _pethAmount));
        // lock PETH into CDP
        invokeWallet(_wallet, address(_makerCdp), 0, abi.encodeWithSelector(CDP_LOCK, _cup, _pethAmount));
    }

    /**
     * @dev Unlocks PETH from a user's CDP and converts it back to ETH
     * @param _wallet The target wallet
     * @param _cup The id of the CDP.
     * @param _pethAmount The amount of PETH to unlock and sell
     * @param _makerCdp The Maker CDP contract
     */
    function freeETH(
        BaseWallet _wallet, 
        bytes32 _cup,
        uint256 _pethAmount,
        IMakerCdp _makerCdp
    ) 
        internal 
    {
        // 1. Unlock PETH

        // Unlock PETH from CDP
        invokeWallet(_wallet, address(_makerCdp), 0, abi.encodeWithSelector(CDP_FREE, _cup, _pethAmount));

        // 2. Convert PETH to ETH
        address wethToken = _makerCdp.gem();
        address pethToken = _makerCdp.skr();
        // Approve PETH
        invokeWallet(_wallet, pethToken, 0, abi.encodeWithSelector(ERC20_APPROVE, address(_makerCdp), _pethAmount));
        // PETH to WETH
        invokeWallet(_wallet, address(_makerCdp), 0, abi.encodeWithSelector(CDP_EXIT, _pethAmount));
        // Get WETH/PETH rate
        uint ethAmount = _makerCdp.bid(_pethAmount);
        // WETH to ETH
        invokeWallet(_wallet, wethToken, 0, abi.encodeWithSelector(WETH_WITHDRAW, ethAmount));
    }

    /**
     * @dev Conversion rate between DAI and MKR
     * @param _makerCdp The Maker CDP contract
     * @return The amount of DAI per MKR
     */
    function daiPerMkr(IMakerCdp _makerCdp) internal view returns (uint256 _daiPerMKR) {
        (bytes32 daiPerMKR_, bool ok) = _makerCdp.pep().peek();
        require(ok && daiPerMKR_ != 0, "LM: invalid DAI/MKR rate");
        _daiPerMKR = uint256(daiPerMKR_);
    }

    /**
     * @dev Utility method to invoke a wallet
     * @param _wallet The wallet to invoke.
     * @param _to The target address.
     * @param _value The value.
     * @param _data The data.
     */
    function invokeWallet(BaseWallet _wallet, address _to, uint256 _value, bytes memory _data) internal {
        _wallet.invoke(_to, _value, _data);
    }
}

Contract Security Audit

Contract ABI

[{"constant":false,"inputs":[{"name":"_cup","type":"bytes32"},{"name":"_makerCdp","type":"address"}],"name":"isSafe","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_cup","type":"bytes32"},{"name":"_makerCdp","type":"address"}],"name":"daiDebt","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_cup","type":"bytes32"},{"name":"_makerCdp","type":"address"}],"name":"totalGovernanceFeeInMKR","outputs":[{"name":"_fee","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","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":"_cup","type":"bytes32"},{"name":"_makerCdp","type":"address"}],"name":"minCollateralRequired","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_wallet","type":"address"},{"name":"_module","type":"address"}],"name":"addModule","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_cup","type":"bytes32"},{"name":"_makerCdp","type":"address"}],"name":"pethCollateral","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_cup","type":"bytes32"},{"name":"_makerCdp","type":"address"}],"name":"minRequiredCollateral","outputs":[{"name":"_minCollateral","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_wallet","type":"address"},{"name":"_loanId","type":"bytes32"}],"name":"getLoan","outputs":[{"name":"_status","type":"uint8"},{"name":"_ethValue","type":"uint256"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_cup","type":"bytes32"},{"name":"_daiRefund","type":"uint256"},{"name":"_makerCdp","type":"address"}],"name":"governanceFeeInMKR","outputs":[{"name":"_fee","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_wallet","type":"address"},{"name":"_loanId","type":"bytes32"},{"name":"_debtToken","type":"address"},{"name":"_debtAmount","type":"uint256"}],"name":"addDebt","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"uniswapFactory","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"makerCdp","outputs":[{"name":"","type":"address"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_token","type":"address"}],"name":"recoverToken","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"name":"_cup","type":"bytes32"},{"name":"_makerCdp","type":"address"}],"name":"exists","outputs":[{"name":"","type":"bool"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"name":"_cup","type":"bytes32"},{"name":"_makerCdp","type":"address"}],"name":"maxDaiDrawable","outputs":[{"name":"","type":"uint256"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_wallet","type":"address"},{"name":"_loanId","type":"bytes32"}],"name":"closeLoan","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":"_loanId","type":"bytes32"},{"name":"_collateral","type":"address"},{"name":"_collateralAmount","type":"uint256"}],"name":"removeCollateral","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_wallet","type":"address"},{"name":"_collateral","type":"address"},{"name":"_collateralAmount","type":"uint256"},{"name":"_debtToken","type":"address"},{"name":"_debtAmount","type":"uint256"}],"name":"openLoan","outputs":[{"name":"_loanId","type":"bytes32"}],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"name":"_wallet","type":"address"},{"name":"_loanId","type":"bytes32"},{"name":"_collateral","type":"address"},{"name":"_collateralAmount","type":"uint256"}],"name":"addCollateral","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"},{"constant":false,"inputs":[{"name":"_wallet","type":"address"},{"name":"_loanId","type":"bytes32"},{"name":"_debtToken","type":"address"},{"name":"_debtAmount","type":"uint256"}],"name":"removeDebt","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"inputs":[{"name":"_registry","type":"address"},{"name":"_guardianStorage","type":"address"},{"name":"_makerCdp","type":"address"},{"name":"_uniswapFactory","type":"address"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"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"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_wallet","type":"address"},{"indexed":true,"name":"_loanId","type":"bytes32"},{"indexed":false,"name":"_collateral","type":"address"},{"indexed":false,"name":"_collateralAmount","type":"uint256"},{"indexed":false,"name":"_debtToken","type":"address"},{"indexed":false,"name":"_debtAmount","type":"uint256"}],"name":"LoanOpened","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_wallet","type":"address"},{"indexed":true,"name":"_loanId","type":"bytes32"}],"name":"LoanClosed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_wallet","type":"address"},{"indexed":true,"name":"_loanId","type":"bytes32"},{"indexed":false,"name":"_collateral","type":"address"},{"indexed":false,"name":"_collateralAmount","type":"uint256"}],"name":"CollateralAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_wallet","type":"address"},{"indexed":true,"name":"_loanId","type":"bytes32"},{"indexed":false,"name":"_collateral","type":"address"},{"indexed":false,"name":"_collateralAmount","type":"uint256"}],"name":"CollateralRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_wallet","type":"address"},{"indexed":true,"name":"_loanId","type":"bytes32"},{"indexed":false,"name":"_debtToken","type":"address"},{"indexed":false,"name":"_debtAmount","type":"uint256"}],"name":"DebtAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"name":"_wallet","type":"address"},{"indexed":true,"name":"_loanId","type":"bytes32"},{"indexed":false,"name":"_debtToken","type":"address"},{"indexed":false,"name":"_debtAmount","type":"uint256"}],"name":"DebtRemoved","type":"event"}]

608060405234801561001057600080fd5b506040516080806200454e8339810180604052608081101561003157600080fd5b50805160208083015160408085015160609095015160008054600160a060020a031916600160a060020a03871617905581517f4d616b65724d616e616765720000000000000000000000000000000000000000808252925195969395939491938793927f3019c8fc80239e3dff8f781212ae2004839c2cb61d6c70acd279ac65392145df928290030190a1505060028054600160a060020a03948516600160a060020a03199182161790915560038054938516938216939093179092556004805491909316911617905550614442806200010c6000396000f3fe608060405234801561001057600080fd5b50600436106101a65760003560e060020a900480638bdb2afa116100f2578063aacaaf881161009b578063b352d4af11610075578063b352d4af1461063a578063c9b5ef8e14610674578063d89784fc1461069a578063e8ca0ca3146106a2576101a6565b8063aacaaf88146104e0578063ac5f8d51146105bc578063b02c808d146105f6576101a6565b8063a4a2850c116100cc578063a4a2850c1461045c578063a8b3dad114610488578063a90cf0af146104b4576101a6565b80638bdb2afa1461040a578063953b4e851461042e5780639be65a6014610436576101a6565b80635a1db8c41161015457806381c44b5c1161012e57806381c44b5c1461035557806383c5b0251461039e57806385a13f38146103d0576101a6565b80635a1db8c4146102cf5780635dc0409a146102fd5780637cea5aff14610329576101a6565b806319ab453c1161018557806319ab453c146102555780632d0335ab1461027d5780632d4a7221146102a3576101a6565b8062895232146101ab5780630a40f3ef146101eb5780630f1d5c9814610229575b600080fd5b6101d7600480360360408110156101c157600080fd5b5080359060200135600160a060020a03166106dc565b604080519115158252519081900360200190f35b6102176004803603604081101561020157600080fd5b5080359060200135600160a060020a031661075c565b60408051918252519081900360200190f35b6102176004803603604081101561023f57600080fd5b5080359060200135600160a060020a03166107a7565b61027b6004803603602081101561026b57600080fd5b5035600160a060020a03166107c4565b005b6102176004803603602081101561029357600080fd5b5035600160a060020a031661086a565b610217600480360360408110156102b957600080fd5b5080359060200135600160a060020a0316610885565b61027b600480360360408110156102e557600080fd5b50600160a060020a0381358116916020013516610bcf565b6102176004803603604081101561031357600080fd5b5080359060200135600160a060020a0316610d94565b6102176004803603604081101561033f57600080fd5b5080359060200135600160a060020a0316610df1565b6103816004803603604081101561036b57600080fd5b50600160a060020a038135169060200135611017565b6040805160ff909316835260208301919091528051918290030190f35b610217600480360360608110156103b457600080fd5b5080359060208101359060400135600160a060020a0316611052565b61027b600480360360808110156103e657600080fd5b50600160a060020a0381358116916020810135916040820135169060600135611235565b6104126114b7565b60408051600160a060020a039092168252519081900360200190f35b6104126114c6565b61027b6004803603602081101561044c57600080fd5b5035600160a060020a03166114d5565b6101d76004803603604081101561047257600080fd5b5080359060200135600160a060020a0316611608565b6102176004803603604081101561049e57600080fd5b5080359060200135600160a060020a0316611699565b61027b600480360360408110156104ca57600080fd5b50600160a060020a03813516906020013561197a565b6101d7600480360360c08110156104f657600080fd5b600160a060020a03823516919081019060408101602082013564010000000081111561052157600080fd5b82018360208201111561053357600080fd5b8035906020019184600183028401116401000000008311171561055557600080fd5b9193909282359260408101906020013564010000000081111561057757600080fd5b82018360208201111561058957600080fd5b803590602001918460018302840111640100000000831117156105ab57600080fd5b919350915080359060200135611b08565b61027b600480360360808110156105d257600080fd5b50600160a060020a0381358116916020810135916040820135169060600135611df0565b610217600480360360a081101561060c57600080fd5b50600160a060020a038135811691602081013582169160408201359160608101359091169060800135612007565b61027b6004803603608081101561065057600080fd5b50600160a060020a0381358116916020810135916040820135169060600135612319565b6102176004803603602081101561068a57600080fd5b5035600160a060020a0316612530565b610412612542565b61027b600480360360808110156106b857600080fd5b50600160a060020a0381358116916020810135916040820135169060600135612551565b600081600160a060020a031663e95823ad846040518263ffffffff1660e060020a02815260040180828152602001915050602060405180830381600087803b15801561072757600080fd5b505af115801561073b573d6000803e3d6000fd5b505050506040513d602081101561075157600080fd5b505190505b92915050565b600081600160a060020a031663f7c8d634846040518263ffffffff1660e060020a02815260040180828152602001915050602060405180830381600087803b15801561072757600080fd5b60006107bd836107b7858561075c565b84611052565b9392505050565b8033600160a060020a0382161461082a57604080516000805160206143b4833981519152815260206004820152601960248201527f424d3a2063616c6c6572206d7573742062652077616c6c657400000000000000604482015290519081900360640190fd5b60408051600160a060020a038416815290517f9fcca3f73f85397e2bf03647abf243c20b753bd54463ff3cae74de2971c112fa9181900360200190a15050565b600160a060020a031660009081526001602052604090205490565b600080610b4283600160a060020a03166351f910666040518163ffffffff1660e060020a02815260040160206040518083038186803b1580156108c757600080fd5b505afa1580156108db573d6000803e3d6000fd5b505050506040513d60208110156108f157600080fd5b5051604080517f67550a350000000000000000000000000000000000000000000000000000000081529051610b3691600160a060020a038816916367550a3591600480820192602092909190829003018186803b15801561095157600080fd5b505afa158015610965573d6000803e3d6000fd5b505050506040513d602081101561097b57600080fd5b5051604080517f495d32cb0000000000000000000000000000000000000000000000000000000081529051600160a060020a039092169163495d32cb916004808201926020929091908290030181600087803b1580156109da57600080fd5b505af11580156109ee573d6000803e3d6000fd5b505050506040513d6020811015610a0457600080fd5b5051604080517fab0783da0000000000000000000000000000000000000000000000000000000081529051610b2a91600160a060020a038a169163ab0783da91600480820192602092909190829003018186803b158015610a6457600080fd5b505afa158015610a78573d6000803e3d6000fd5b505050506040513d6020811015610a8e57600080fd5b5051604080517ff7c8d634000000000000000000000000000000000000000000000000000000008152600481018c90529051600160a060020a038b169163f7c8d6349160248083019260209291908290030181600087803b158015610af257600080fd5b505af1158015610b06573d6000803e3d6000fd5b505050506040513d6020811015610b1c57600080fd5b50519063ffffffff6127da16565b9063ffffffff6127da16565b9063ffffffff61281d16565b9050610bc783600160a060020a0316631f3634ed866040518263ffffffff1660e060020a0281526004018082815260200191505060206040518083038186803b158015610b8e57600080fd5b505afa158015610ba2573d6000803e3d6000fd5b505050506040513d6020811015610bb857600080fd5b5051829063ffffffff61284116565b949350505050565b81610bda8133612856565b1515610c1f576040516000805160206143b4833981519152815260040180806020018281038252602e81526020018061431c602e913960400191505060405180910390fd5b600054604080517f0bcd4ebb000000000000000000000000000000000000000000000000000000008152600160a060020a03858116600483015291519190921691630bcd4ebb916024808301926020929190829003018186803b158015610c8557600080fd5b505afa158015610c99573d6000803e3d6000fd5b505050506040513d6020811015610caf57600080fd5b50511515610d0c57604080516000805160206143b4833981519152815260206004820152601c60248201527f424d3a206d6f64756c65206973206e6f74207265676973746572656400000000604482015290519081900360640190fd5b604080517f1f17732d000000000000000000000000000000000000000000000000000000008152600160a060020a03848116600483015260016024830152915191851691631f17732d9160448082019260009290919082900301818387803b158015610d7757600080fd5b505af1158015610d8b573d6000803e3d6000fd5b50505050505050565b600081600160a060020a0316631f3634ed846040518263ffffffff1660e060020a0281526004018082815260200191505060206040518083038186803b158015610ddd57600080fd5b505afa15801561073b573d6000803e3d6000fd5b60006107bd82600160a060020a03166351f910666040518163ffffffff1660e060020a02815260040160206040518083038186803b158015610e3257600080fd5b505afa158015610e46573d6000803e3d6000fd5b505050506040513d6020811015610e5c57600080fd5b5051604080517fab0783da0000000000000000000000000000000000000000000000000000000081529051610b36916b034373d1b5e481853200000091610b2a91600160a060020a0389169163ab0783da91600480820192602092909190829003018186803b158015610ece57600080fd5b505afa158015610ee2573d6000803e3d6000fd5b505050506040513d6020811015610ef857600080fd5b5051604080517f67550a350000000000000000000000000000000000000000000000000000000081529051610b2a91600160a060020a038b16916367550a3591600480820192602092909190829003018186803b158015610f5857600080fd5b505afa158015610f6c573d6000803e3d6000fd5b505050506040513d6020811015610f8257600080fd5b5051604080517f495d32cb0000000000000000000000000000000000000000000000000000000081529051600160a060020a039092169163495d32cb916004808201926020929091908290030181600087803b158015610fe157600080fd5b505af1158015610ff5573d6000803e3d6000fd5b505050506040513d602081101561100b57600080fd5b5051610b2a8b8b61075c565b6003546000908190611033908490600160a060020a0316611608565b15611044575060039050600061104b565b5060009050805b9250929050565b60008061105f858461075c565b90508015156110725760009150506107bd565b60006111096110fc8386600160a060020a0316636f78ee0d8a6040518263ffffffff1660e060020a02815260040180828152602001915050602060405180830381600087803b1580156110c457600080fd5b505af11580156110d8573d6000803e3d6000fd5b505050506040513d60208110156110ee57600080fd5b50519063ffffffff61281d16565b869063ffffffff6127da16565b905060008085600160a060020a031663ace237f56040518163ffffffff1660e060020a02815260040160206040518083038186803b15801561114a57600080fd5b505afa15801561115e573d6000803e3d6000fd5b505050506040513d602081101561117457600080fd5b5051604080517f59e02dd70000000000000000000000000000000000000000000000000000000081528151600160a060020a03909316926359e02dd792600480840193919291829003018186803b1580156111ce57600080fd5b505afa1580156111e2573d6000803e3d6000fd5b505050506040513d60408110156111f857600080fd5b508051602090910151909250905080801561121257508115155b1561122a57611227838363ffffffff6128db16565b94505b505050509392505050565b833330148061124957506112498133612856565b151561128e576040516000805160206143b483398151915281526004018080602001828103825260238152602001806143d46023913960400191505060405180910390fd5b600254604080517f4a4fbeec000000000000000000000000000000000000000000000000000000008152600160a060020a038089166004830152915188939290921691634a4fbeec91602480820192602092909190829003018186803b1580156112f757600080fd5b505afa15801561130b573d6000803e3d6000fd5b505050506040513d602081101561132157600080fd5b505115611367576040516000805160206143b4833981519152815260040180806020018281038252602581526020018061436f6025913960400191505060405180910390fd5b600360009054906101000a9004600160a060020a0316600160a060020a0316639166cba46040518163ffffffff1660e060020a02815260040160206040518083038186803b1580156113b857600080fd5b505afa1580156113cc573d6000803e3d6000fd5b505050506040513d60208110156113e257600080fd5b5051600160a060020a0385811691161461144b57604080516000805160206143b4833981519152815260206004820152601d60248201527f4d616b65723a206465627420746f6b656e206d75737420626520444149000000604482015290519081900360640190fd5b60035461146690879087908690600160a060020a03166128f3565b60408051600160a060020a0386811682526020820186905282518893918a16927ff6669d5e7ff92997c22e9fe3b54f53ed18448cf5fdccb3eb1dc5004798fbb41492908290030190a3505050505050565b600454600160a060020a031681565b600354600160a060020a031681565b604080517f70a082310000000000000000000000000000000000000000000000000000000081523060048201529051600091600160a060020a038416916370a0823191602480820192602092909190829003018186803b15801561153857600080fd5b505afa15801561154c573d6000803e3d6000fd5b505050506040513d602081101561156257600080fd5b505160008054604080517fa9059cbb000000000000000000000000000000000000000000000000000000008152600160a060020a0392831660048201526024810185905290519394509085169263a9059cbb92604480840193602093929083900390910190829087803b1580156115d857600080fd5b505af11580156115ec573d6000803e3d6000fd5b505050506040513d602081101561160257600080fd5b50505050565b600080600160a060020a031682600160a060020a031663de5f5517856040518263ffffffff1660e060020a0281526004018082815260200191505060206040518083038186803b15801561165b57600080fd5b505afa15801561166f573d6000803e3d6000fd5b505050506040513d602081101561168557600080fd5b5051600160a060020a031614159392505050565b60008061191883600160a060020a031663ab0783da6040518163ffffffff1660e060020a02815260040160206040518083038186803b1580156116db57600080fd5b505afa1580156116ef573d6000803e3d6000fd5b505050506040513d602081101561170557600080fd5b5051604080517f67550a350000000000000000000000000000000000000000000000000000000081529051610b3691600160a060020a038816916367550a3591600480820192602092909190829003018186803b15801561176557600080fd5b505afa158015611779573d6000803e3d6000fd5b505050506040513d602081101561178f57600080fd5b5051604080517f495d32cb0000000000000000000000000000000000000000000000000000000081529051600160a060020a039092169163495d32cb916004808201926020929091908290030181600087803b1580156117ee57600080fd5b505af1158015611802573d6000803e3d6000fd5b505050506040513d602081101561181857600080fd5b5051604080517f51f910660000000000000000000000000000000000000000000000000000000081529051610b3691600160a060020a038a16916351f9106691600480820192602092909190829003018186803b15801561187857600080fd5b505afa15801561188c573d6000803e3d6000fd5b505050506040513d60208110156118a257600080fd5b5051604080517f1f3634ed000000000000000000000000000000000000000000000000000000008152600481018c90529051600160a060020a038b1691631f3634ed916024808301926020929190829003018186803b15801561190457600080fd5b505afa158015610b06573d6000803e3d6000fd5b9050610bc783600160a060020a031663f7c8d634866040518263ffffffff1660e060020a02815260040180828152602001915050602060405180830381600087803b15801561196657600080fd5b505af1158015610ba2573d6000803e3d6000fd5b813330148061198e575061198e8133612856565b15156119d3576040516000805160206143b483398151915281526004018080602001828103825260238152602001806143d46023913960400191505060405180910390fd5b600254604080517f4a4fbeec000000000000000000000000000000000000000000000000000000008152600160a060020a038087166004830152915186939290921691634a4fbeec91602480820192602092909190829003018186803b158015611a3c57600080fd5b505afa158015611a50573d6000803e3d6000fd5b505050506040513d6020811015611a6657600080fd5b505115611aac576040516000805160206143b4833981519152815260040180806020018281038252602581526020018061436f6025913960400191505060405180910390fd5b600354600454611acc9186918691600160a060020a039081169116612985565b6040518390600160a060020a038616907f07e4a0c6f06275f83bcf78e5a10eb7f5515574d593bce993377961f4133b951c90600090a350505050565b6000805a90506000611b58308c60008d8d8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508f92508c91508b9050612a5f565b9050611b658b8983612ba2565b1515611bc057604080516000805160206143b4833981519152815260206004820152601560248201527f524d3a204475706c696361746520726571756573740000000000000000000000604482015290519081900360640190fd5b611c008b8b8b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612bae92505050565b1515611c45576040516000805160206143b4833981519152815260040180806020018281038252604a8152602001806142d2604a913960600191505060405180910390fd5b6000611c878c8c8c8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612c2792505050565b905060418102871415611d9f57611ca08c868884612c2f565b15611d9f57801580611d235750611d238c8c8c8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8f018190048102820181019092528d815288935091508d908d9081908401838280828437600092019190915250612d0192505050565b15611d9f5730600160a060020a03168b8b604051808383808284376040519201945060009350909150508083038183865af19150503d8060008114611d84576040519150601f19603f3d011682016040523d82523d6000602084013e611d89565b606091505b505080945050611d9f8c5a850388888533612d26565b60408051838152905185151591600160a060020a038f16917f6bb0b384ce772133df63560651bc8c727c53306cec1d51e2cbf8ea35fb8f2ec19181900360200190a350505098975050505050505050565b8333301480611e045750611e048133612856565b1515611e49576040516000805160206143b483398151915281526004018080602001828103825260238152602001806143d46023913960400191505060405180910390fd5b600254604080517f4a4fbeec000000000000000000000000000000000000000000000000000000008152600160a060020a038089166004830152915188939290921691634a4fbeec91602480820192602092909190829003018186803b158015611eb257600080fd5b505afa158015611ec6573d6000803e3d6000fd5b505050506040513d6020811015611edc57600080fd5b505115611f22576040516000805160206143b4833981519152815260040180806020018281038252602581526020018061436f6025913960400191505060405180910390fd5b600160a060020a03841673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611f9b57604080516000805160206143b4833981519152815260206004820152601d60248201527f4d616b65723a20636f6c6c61746572616c206d75737420626520455448000000604482015290519081900360640190fd5b600354611fb690879087908690600160a060020a0316612df5565b60408051600160a060020a0386811682526020820186905282518893918a16927ff1dec7a92ef063b16d2098bb05803ed604936a7ff30f0d245fe881baf96e8e6b92908290030190a3505050505050565b6000853330148061201d575061201d8133612856565b1515612062576040516000805160206143b483398151915281526004018080602001828103825260238152602001806143d46023913960400191505060405180910390fd5b600254604080517f4a4fbeec000000000000000000000000000000000000000000000000000000008152600160a060020a03808b16600483015291518a939290921691634a4fbeec91602480820192602092909190829003018186803b1580156120cb57600080fd5b505afa1580156120df573d6000803e3d6000fd5b505050506040513d60208110156120f557600080fd5b50511561213b576040516000805160206143b4833981519152815260040180806020018281038252602581526020018061436f6025913960400191505060405180910390fd5b600160a060020a03871673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee146121b457604080516000805160206143b4833981519152815260206004820152601d60248201527f4d616b65723a20636f6c6c61746572616c206d75737420626520455448000000604482015290519081900360640190fd5b600360009054906101000a9004600160a060020a0316600160a060020a0316639166cba46040518163ffffffff1660e060020a02815260040160206040518083038186803b15801561220557600080fd5b505afa158015612219573d6000803e3d6000fd5b505050506040513d602081101561222f57600080fd5b5051600160a060020a0386811691161461229857604080516000805160206143b4833981519152815260206004820152601d60248201527f4d616b65723a206465627420746f6b656e206d75737420626520444149000000604482015290519081900360640190fd5b6003546122b390899088908790600160a060020a0316612e01565b60408051600160a060020a038a81168252602082018a9052888116828401526060820188905291519295508592918b16917ff9d7e11fb5d8d1e0a4be344a6a6adfb912161747edf926fb283150d07c39c1089181900360800190a3505095945050505050565b833330148061232d575061232d8133612856565b1515612372576040516000805160206143b483398151915281526004018080602001828103825260238152602001806143d46023913960400191505060405180910390fd5b600254604080517f4a4fbeec000000000000000000000000000000000000000000000000000000008152600160a060020a038089166004830152915188939290921691634a4fbeec91602480820192602092909190829003018186803b1580156123db57600080fd5b505afa1580156123ef573d6000803e3d6000fd5b505050506040513d602081101561240557600080fd5b50511561244b576040516000805160206143b4833981519152815260040180806020018281038252602581526020018061436f6025913960400191505060405180910390fd5b600160a060020a03841673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee146124c457604080516000805160206143b4833981519152815260206004820152601d60248201527f4d616b65723a20636f6c6c61746572616c206d75737420626520455448000000604482015290519081900360640190fd5b6003546124df90879087908690600160a060020a0316612f9a565b60408051600160a060020a0386811682526020820186905282518893918a16927fdd016248708c391ccb5c72f9258127c75b9b291ac1479513fe4f331c3489013792908290030190a3505050505050565b60016020526000908152604090205481565b600254600160a060020a031681565b833330148061256557506125658133612856565b15156125aa576040516000805160206143b483398151915281526004018080602001828103825260238152602001806143d46023913960400191505060405180910390fd5b600254604080517f4a4fbeec000000000000000000000000000000000000000000000000000000008152600160a060020a038089166004830152915188939290921691634a4fbeec91602480820192602092909190829003018186803b15801561261357600080fd5b505afa158015612627573d6000803e3d6000fd5b505050506040513d602081101561263d57600080fd5b505115612683576040516000805160206143b4833981519152815260040180806020018281038252602581526020018061436f6025913960400191505060405180910390fd5b600360009054906101000a9004600160a060020a0316600160a060020a0316639166cba46040518163ffffffff1660e060020a02815260040160206040518083038186803b1580156126d457600080fd5b505afa1580156126e8573d6000803e3d6000fd5b505050506040513d60208110156126fe57600080fd5b5051600160a060020a0385811691161461276757604080516000805160206143b4833981519152815260206004820152601d60248201527f4d616b65723a206465627420746f6b656e206d75737420626520444149000000604482015290519081900360640190fd5b60035460045461278991889188918791600160a060020a039182169116613080565b60408051600160a060020a0386811682526020820186905282518893918a16927fbfa42ea7d37497e6a09441fadba47d64b610b6b1183d895dd0a42507973430bf92908290030190a3505050505050565b60006b033b2e3c9fd0803ce800000061280c6127f6858561388b565b60026b033b2e3c9fd0803ce80000005b046138b6565b81151561281557fe5b049392505050565b60008161280c612839856b033b2e3c9fd0803ce800000061388b565b600285612806565b60008282111561285057600080fd5b50900390565b600081600160a060020a031683600160a060020a0316638da5cb5b6040518163ffffffff1660e060020a02815260040160206040518083038186803b15801561289e57600080fd5b505afa1580156128b2573d6000803e3d6000fd5b505050506040513d60208110156128c857600080fd5b5051600160a060020a0316149392505050565b60008161280c61283985670de0b6b3a764000061388b565b604080517f6472617728627974657333322c75696e74323536290000000000000000000000815281519081900360150181206024820186905260448083018690528351808403909101815260649092019092526020810180516000805160206143f7833981519152166000805160206143948339815191529093169290921790915261160290859083906000906138c8565b6000612991848461075c565b905060008111156129a9576129a98585838686613080565b60006129b58585610d94565b905060008111156129cc576129cc86868387612df5565b604080517f73687574286279746573333229000000000000000000000000000000000000008152815190819003600d01812060248083018990528351808403909101815260449092019092526020810180516000805160206143f78339815191521660008051602061439483398151915290931692909217909152612a5790879086906000906138c8565b505050505050565b6040517f190000000000000000000000000000000000000000000000000000000000000060208083018281526000602185018190526c01000000000000000000000000600160a060020a03808e16820260228801528c16026036860152604a85018a90528851909485938d938d938d938d938d938d938d939192606a909201918701908083835b60208310612b055780518252601f199092019160209182019101612ae6565b51815160209384036101000a600019018019909216911617905292019586525084810193909352506040808401919091528051808403820181526060840182528051908301207f19457468657265756d205369676e6564204d6573736167653a0a3332000000006080850152609c808501919091528151808503909101815260bc909301905281519101209e9d5050505050505050505050505050565b6000610bc784846139b3565b60006024825110151515612c1157604080516000805160206143b4833981519152815260206004820152601660248201527f524d3a20496e76616c6964206461746157616c6c657400000000000000000000604482015290519081900360640190fd5b5060240151600160a060020a0391821691161490565b600192915050565b60008083118015612c405750600182115b8015612ce9575082840285600160a060020a0316311080612ce95750604080517fd6eb1bbf0000000000000000000000000000000000000000000000000000000081523060048201529051600160a060020a0387169163d6eb1bbf916024808301926020929190829003018186803b158015612cbb57600080fd5b505afa158015612ccf573d6000803e3d6000fd5b505050506040513d6020811015612ce557600080fd5b5051155b15612cf657506000610bc7565b506001949350505050565b600080612d1084846000613a3d565b9050612d1c8682612856565b9695505050505050565b61726c8501600085118015612d3b5750600183115b8015612d475750838111155b15610d8b573a851115612d5b573a02612d5e565b84025b604080517f8f6f0332000000000000000000000000000000000000000000000000000000008152600160a060020a03848116600483015260248201849052606060448301526000606483018190529251908a1692638f6f03329260a4808201939182900301818387803b158015612dd457600080fd5b505af1158015612de8573d6000803e3d6000fd5b5050505050505050505050565b61160284848484613ae7565b600081600160a060020a031663fcfff16f6040518163ffffffff1660e060020a028152600401602060405180830381600087803b158015612e4157600080fd5b505af1158015612e55573d6000803e3d6000fd5b505050506040513d6020811015612e6b57600080fd5b5051604080517fbaa8529c00000000000000000000000000000000000000000000000000000000815260048101839052600160a060020a03888116602483015291519293509084169163baa8529c9160448082019260009290919082900301818387803b158015612edb57600080fd5b505af1158015612eef573d6000803e3d6000fd5b50505050612eff85828685613e99565b6000831115610bc757604080517f6472617728627974657333322c75696e74323536290000000000000000000000815281519081900360150181206024820184905260448083018790528351808403909101815260649092019092526020810180516000805160206143f78339815191521660008051602061439483398151915290931692909217909152610bc790869084906000906138c8565b80600160a060020a031663de5f5517846040518263ffffffff1660e060020a0281526004018082815260200191505060206040518083038186803b158015612fe157600080fd5b505afa158015612ff5573d6000803e3d6000fd5b505050506040513d602081101561300b57600080fd5b5051600160a060020a0385811691161461307457604080516000805160206143b4833981519152815260206004820152601160248201527f434d3a206e6f7420434450206f776e6572000000000000000000000000000000604482015290519081900360640190fd5b61160284848484613e99565b81600160a060020a031663de5f5517856040518263ffffffff1660e060020a0281526004018082815260200191505060206040518083038186803b1580156130c757600080fd5b505afa1580156130db573d6000803e3d6000fd5b505050506040513d60208110156130f157600080fd5b5051600160a060020a0386811691161461315a57604080516000805160206143b4833981519152815260206004820152601160248201527f434d3a206e6f7420434450206f776e6572000000000000000000000000000000604482015290519081900360640190fd5b6000613167858585611052565b9050600083600160a060020a03166312d43a516040518163ffffffff1660e060020a02815260040160206040518083038186803b1580156131a757600080fd5b505afa1580156131bb573d6000803e3d6000fd5b505050506040513d60208110156131d157600080fd5b5051604080517f70a08231000000000000000000000000000000000000000000000000000000008152600160a060020a038a811660048301529151929350600092918416916370a0823191602480820192602092909190829003018186803b15801561323c57600080fd5b505afa158015613250573d6000803e3d6000fd5b505050506040513d602081101561326657600080fd5b505190508281101561340d57600084600160a060020a03166306f2bf62846040518263ffffffff1660e060020a0281526004018082600160a060020a0316600160a060020a0316815260200191505060206040518083038186803b1580156132cd57600080fd5b505afa1580156132e1573d6000803e3d6000fd5b505050506040513d60208110156132f757600080fd5b5051604080517f59e9486200000000000000000000000000000000000000000000000000000000815284870360048201529051919250600091600160a060020a038416916359e94862916024808301926020929190829003018186803b15801561336057600080fd5b505afa158015613374573d6000803e3d6000fd5b505050506040513d602081101561338a57600080fd5b505160405190915061340a908b908490849080602561434a8239604080519182900360250182208a8d036024840152426044808501919091528251808503909101815260649093019091526020820180516000805160206143f78339815191521660008051602061439483398151915290921691909117905290506138c8565b50505b600085600160a060020a0316639166cba46040518163ffffffff1660e060020a02815260040160206040518083038186803b15801561344b57600080fd5b505afa15801561345f573d6000803e3d6000fd5b505050506040513d602081101561347557600080fd5b5051604080517f70a08231000000000000000000000000000000000000000000000000000000008152600160a060020a038c811660048301529151929350600092918416916370a0823191602480820192602092909190829003018186803b1580156134e057600080fd5b505afa1580156134f4573d6000803e3d6000fd5b505050506040513d602081101561350a57600080fd5b50519050878110156136b957600086600160a060020a03166306f2bf62846040518263ffffffff1660e060020a0281526004018082600160a060020a0316600160a060020a0316815260200191505060206040518083038186803b15801561357157600080fd5b505afa158015613585573d6000803e3d6000fd5b505050506040513d602081101561359b57600080fd5b5051604080517f59e94862000000000000000000000000000000000000000000000000000000008152848c0360048201529051919250600091600160a060020a038416916359e94862916024808301926020929190829003018186803b15801561360457600080fd5b505afa158015613618573d6000803e3d6000fd5b505050506040513d602081101561362e57600080fd5b50516040519091506136b6908d908490849080602561434a823960250190506040518091039020878f03426040516024018083815260200182815260200192505050604051602081830303815290604052906000805160206143f783398151915219166020820180516000805160206143f783398151915283818316178352505050506138c8565b50505b604080517f617070726f766528616464726573732c75696e7432353629000000000000000081528151908190036018018120600160a060020a038a16602483015260448083018c90528351808403909101815260649092019092526020810180516000805160206143f78339815191521660008051602061439483398151915290931692909217909152613753908b9084906000906138c8565b604080517f617070726f766528616464726573732c75696e7432353629000000000000000081528151908190036018018120600160a060020a038a16602483015260448083018990528351808403909101815260649092019092526020810180516000805160206143f783398151915216600080516020614394833981519152909316929092179091526137ed908b9086906000906138c8565b604080517f7769706528627974657333322c75696e7432353629000000000000000000000081528151908190036015018120602482018c905260448083018c90528351808403909101815260649092019092526020810180516000805160206143f7833981519152166000805160206143948339815191529093169290921790915261387f908b9089906000906138c8565b50505050505050505050565b600082151561389c57506000610756565b8282028284828115156138ab57fe5b04146107bd57600080fd5b6000828201838110156107bd57600080fd5b83600160a060020a0316638f6f03328484846040518463ffffffff1660e060020a0281526004018084600160a060020a0316600160a060020a0316815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b8381101561394757818101518382015260200161392f565b50505050905090810190601f1680156139745780820380516001836020036101000a031916815260200191505b50945050505050600060405180830381600087803b15801561399557600080fd5b505af11580156139a9573d6000803e3d6000fd5b5050505050505050565b600160a060020a03821660009081526001602052604081205482116139da57506000610756565b7001000000000000000000000000000000006fffffffffffffffffffffffffffffffff198316044361271001811115613a17576000915050610756565b5050600160a060020a038216600090815260016020819052604090912082905592915050565b6041808202830160208101516040820151919092015160009260ff9190911691601b831480613a6f57508260ff16601c145b1515613a7a57600080fd5b604080516000815260208082018084528a905260ff8616828401526060820185905260808201849052915160019260a0808401939192601f1981019281900390910190855afa158015613ad1573d6000803e3d6000fd5b5050604051601f19015198975050505050505050565b604080517f6672656528627974657333322c75696e74323536290000000000000000000000815281519081900360150181206024820186905260448083018690528351808403909101815260649092019092526020810180516000805160206143f78339815191521660008051602061439483398151915290931692909217909152613b7990859083906000906138c8565b600081600160a060020a0316637bd2bea76040518163ffffffff1660e060020a02815260040160206040518083038186803b158015613bb757600080fd5b505afa158015613bcb573d6000803e3d6000fd5b505050506040513d6020811015613be157600080fd5b5051604080517f0f8a771e0000000000000000000000000000000000000000000000000000000081529051919250600091600160a060020a03851691630f8a771e916004808301926020929190829003018186803b158015613c4257600080fd5b505afa158015613c56573d6000803e3d6000fd5b505050506040513d6020811015613c6c57600080fd5b5051604080517f617070726f766528616464726573732c75696e7432353629000000000000000081528151908190036018018120600160a060020a038716602483015260448083018990528351808403909101815260649092019092526020810180516000805160206143f78339815191521660008051602061439483398151915290931692909217909152909150613d0b90879083906000906138c8565b604080517f657869742875696e7432353629000000000000000000000000000000000000008152815190819003600d01812060248083018890528351808403909101815260449092019092526020810180516000805160206143f78339815191521660008051602061439483398151915290931692909217909152613d9690879085906000906138c8565b600083600160a060020a031663454a2ab3866040518263ffffffff1660e060020a0281526004018082815260200191505060206040518083038186803b158015613ddf57600080fd5b505afa158015613df3573d6000803e3d6000fd5b505050506040513d6020811015613e0957600080fd5b5051604080517f77697468647261772875696e74323536290000000000000000000000000000008152815190819003601101812060248083018590528351808403909101815260449092019092526020810180516000805160206143f78339815191521660008051602061439483398151915290931692909217909152909150610d8b90889085906000906138c8565b600081600160a060020a0316637bd2bea76040518163ffffffff1660e060020a02815260040160206040518083038186803b158015613ed757600080fd5b505afa158015613eeb573d6000803e3d6000fd5b505050506040513d6020811015613f0157600080fd5b5051604080517fe47e7e66000000000000000000000000000000000000000000000000000000008152600481018690529051919250600091600160a060020a0385169163e47e7e66916024808301926020929190829003018186803b158015613f6957600080fd5b505afa158015613f7d573d6000803e3d6000fd5b505050506040513d6020811015613f9357600080fd5b5051604080517f6465706f736974282900000000000000000000000000000000000000000000008152815190819003600901812060048252602482019092526020810180516000805160206143f78339815191521660008051602061439483398151915290931692909217909152909150614013908790849084906138c8565b604080517f617070726f766528616464726573732c75696e7432353629000000000000000081528151908190036018018120600160a060020a038616602483015260448083018590528351808403909101815260649092019092526020810180516000805160206143f783398151915216600080516020614394833981519152909316929092179091526140ad90879084906000906138c8565b604080517f6a6f696e2875696e7432353629000000000000000000000000000000000000008152815190819003600d01812060248083018890528351808403909101815260449092019092526020810180516000805160206143f7833981519152166000805160206143948339815191529093169290921790915261413890879085906000906138c8565b600083600160a060020a0316630f8a771e6040518163ffffffff1660e060020a02815260040160206040518083038186803b15801561417657600080fd5b505afa15801561418a573d6000803e3d6000fd5b505050506040513d60208110156141a057600080fd5b5051604080517f617070726f766528616464726573732c75696e7432353629000000000000000081528151908190036018018120600160a060020a038816602483015260448083018a90528351808403909101815260649092019092526020810180516000805160206143f7833981519152166000805160206143948339815191529093169290921790915290915061423f90889083906000906138c8565b604080517f6c6f636b28627974657333322c75696e74323536290000000000000000000000815281519081900360150181206024820189905260448083018990528351808403909101815260649092019092526020810180516000805160206143f78339815191521660008051602061439483398151915290931692909217909152610d8b90889086906000906138c856fe524d3a207468652077616c6c657420617574686f72697a656420697320646966666572656e74207468656e2074686520746172676574206f66207468652072656c617965642064617461424d3a206d73672e73656e646572206d75737420626520616e206f776e657220666f72207468652077616c6c6574657468546f546f6b656e537761704f75747075742875696e743235362c75696e74323536294d616b65724d616e616765723a2077616c6c6574206d75737420626520756e6c6f636b6564ffffffff0000000000000000000000000000000000000000000000000000000008c379a000000000000000000000000000000000000000000000000000000000424d3a206d75737420626520616e206f776e657220666f72207468652077616c6c657400000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffa165627a7a723058203bf4bedfff4a0e165cdef420704ae6d0f63199fb310cca443144b76dcd0d02720029000000000000000000000000c17d432bd8e8850fd7b32b0270f5afac65db010500000000000000000000000044da3a8051ba88eab0440db3779cab9d679ae76f000000000000000000000000448a5065aebb8e423f0896e6c5d525c040f59af3000000000000000000000000c0a47dfe034b400b47bdad5fecda2621de6c4d95

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106101a65760003560e060020a900480638bdb2afa116100f2578063aacaaf881161009b578063b352d4af11610075578063b352d4af1461063a578063c9b5ef8e14610674578063d89784fc1461069a578063e8ca0ca3146106a2576101a6565b8063aacaaf88146104e0578063ac5f8d51146105bc578063b02c808d146105f6576101a6565b8063a4a2850c116100cc578063a4a2850c1461045c578063a8b3dad114610488578063a90cf0af146104b4576101a6565b80638bdb2afa1461040a578063953b4e851461042e5780639be65a6014610436576101a6565b80635a1db8c41161015457806381c44b5c1161012e57806381c44b5c1461035557806383c5b0251461039e57806385a13f38146103d0576101a6565b80635a1db8c4146102cf5780635dc0409a146102fd5780637cea5aff14610329576101a6565b806319ab453c1161018557806319ab453c146102555780632d0335ab1461027d5780632d4a7221146102a3576101a6565b8062895232146101ab5780630a40f3ef146101eb5780630f1d5c9814610229575b600080fd5b6101d7600480360360408110156101c157600080fd5b5080359060200135600160a060020a03166106dc565b604080519115158252519081900360200190f35b6102176004803603604081101561020157600080fd5b5080359060200135600160a060020a031661075c565b60408051918252519081900360200190f35b6102176004803603604081101561023f57600080fd5b5080359060200135600160a060020a03166107a7565b61027b6004803603602081101561026b57600080fd5b5035600160a060020a03166107c4565b005b6102176004803603602081101561029357600080fd5b5035600160a060020a031661086a565b610217600480360360408110156102b957600080fd5b5080359060200135600160a060020a0316610885565b61027b600480360360408110156102e557600080fd5b50600160a060020a0381358116916020013516610bcf565b6102176004803603604081101561031357600080fd5b5080359060200135600160a060020a0316610d94565b6102176004803603604081101561033f57600080fd5b5080359060200135600160a060020a0316610df1565b6103816004803603604081101561036b57600080fd5b50600160a060020a038135169060200135611017565b6040805160ff909316835260208301919091528051918290030190f35b610217600480360360608110156103b457600080fd5b5080359060208101359060400135600160a060020a0316611052565b61027b600480360360808110156103e657600080fd5b50600160a060020a0381358116916020810135916040820135169060600135611235565b6104126114b7565b60408051600160a060020a039092168252519081900360200190f35b6104126114c6565b61027b6004803603602081101561044c57600080fd5b5035600160a060020a03166114d5565b6101d76004803603604081101561047257600080fd5b5080359060200135600160a060020a0316611608565b6102176004803603604081101561049e57600080fd5b5080359060200135600160a060020a0316611699565b61027b600480360360408110156104ca57600080fd5b50600160a060020a03813516906020013561197a565b6101d7600480360360c08110156104f657600080fd5b600160a060020a03823516919081019060408101602082013564010000000081111561052157600080fd5b82018360208201111561053357600080fd5b8035906020019184600183028401116401000000008311171561055557600080fd5b9193909282359260408101906020013564010000000081111561057757600080fd5b82018360208201111561058957600080fd5b803590602001918460018302840111640100000000831117156105ab57600080fd5b919350915080359060200135611b08565b61027b600480360360808110156105d257600080fd5b50600160a060020a0381358116916020810135916040820135169060600135611df0565b610217600480360360a081101561060c57600080fd5b50600160a060020a038135811691602081013582169160408201359160608101359091169060800135612007565b61027b6004803603608081101561065057600080fd5b50600160a060020a0381358116916020810135916040820135169060600135612319565b6102176004803603602081101561068a57600080fd5b5035600160a060020a0316612530565b610412612542565b61027b600480360360808110156106b857600080fd5b50600160a060020a0381358116916020810135916040820135169060600135612551565b600081600160a060020a031663e95823ad846040518263ffffffff1660e060020a02815260040180828152602001915050602060405180830381600087803b15801561072757600080fd5b505af115801561073b573d6000803e3d6000fd5b505050506040513d602081101561075157600080fd5b505190505b92915050565b600081600160a060020a031663f7c8d634846040518263ffffffff1660e060020a02815260040180828152602001915050602060405180830381600087803b15801561072757600080fd5b60006107bd836107b7858561075c565b84611052565b9392505050565b8033600160a060020a0382161461082a57604080516000805160206143b4833981519152815260206004820152601960248201527f424d3a2063616c6c6572206d7573742062652077616c6c657400000000000000604482015290519081900360640190fd5b60408051600160a060020a038416815290517f9fcca3f73f85397e2bf03647abf243c20b753bd54463ff3cae74de2971c112fa9181900360200190a15050565b600160a060020a031660009081526001602052604090205490565b600080610b4283600160a060020a03166351f910666040518163ffffffff1660e060020a02815260040160206040518083038186803b1580156108c757600080fd5b505afa1580156108db573d6000803e3d6000fd5b505050506040513d60208110156108f157600080fd5b5051604080517f67550a350000000000000000000000000000000000000000000000000000000081529051610b3691600160a060020a038816916367550a3591600480820192602092909190829003018186803b15801561095157600080fd5b505afa158015610965573d6000803e3d6000fd5b505050506040513d602081101561097b57600080fd5b5051604080517f495d32cb0000000000000000000000000000000000000000000000000000000081529051600160a060020a039092169163495d32cb916004808201926020929091908290030181600087803b1580156109da57600080fd5b505af11580156109ee573d6000803e3d6000fd5b505050506040513d6020811015610a0457600080fd5b5051604080517fab0783da0000000000000000000000000000000000000000000000000000000081529051610b2a91600160a060020a038a169163ab0783da91600480820192602092909190829003018186803b158015610a6457600080fd5b505afa158015610a78573d6000803e3d6000fd5b505050506040513d6020811015610a8e57600080fd5b5051604080517ff7c8d634000000000000000000000000000000000000000000000000000000008152600481018c90529051600160a060020a038b169163f7c8d6349160248083019260209291908290030181600087803b158015610af257600080fd5b505af1158015610b06573d6000803e3d6000fd5b505050506040513d6020811015610b1c57600080fd5b50519063ffffffff6127da16565b9063ffffffff6127da16565b9063ffffffff61281d16565b9050610bc783600160a060020a0316631f3634ed866040518263ffffffff1660e060020a0281526004018082815260200191505060206040518083038186803b158015610b8e57600080fd5b505afa158015610ba2573d6000803e3d6000fd5b505050506040513d6020811015610bb857600080fd5b5051829063ffffffff61284116565b949350505050565b81610bda8133612856565b1515610c1f576040516000805160206143b4833981519152815260040180806020018281038252602e81526020018061431c602e913960400191505060405180910390fd5b600054604080517f0bcd4ebb000000000000000000000000000000000000000000000000000000008152600160a060020a03858116600483015291519190921691630bcd4ebb916024808301926020929190829003018186803b158015610c8557600080fd5b505afa158015610c99573d6000803e3d6000fd5b505050506040513d6020811015610caf57600080fd5b50511515610d0c57604080516000805160206143b4833981519152815260206004820152601c60248201527f424d3a206d6f64756c65206973206e6f74207265676973746572656400000000604482015290519081900360640190fd5b604080517f1f17732d000000000000000000000000000000000000000000000000000000008152600160a060020a03848116600483015260016024830152915191851691631f17732d9160448082019260009290919082900301818387803b158015610d7757600080fd5b505af1158015610d8b573d6000803e3d6000fd5b50505050505050565b600081600160a060020a0316631f3634ed846040518263ffffffff1660e060020a0281526004018082815260200191505060206040518083038186803b158015610ddd57600080fd5b505afa15801561073b573d6000803e3d6000fd5b60006107bd82600160a060020a03166351f910666040518163ffffffff1660e060020a02815260040160206040518083038186803b158015610e3257600080fd5b505afa158015610e46573d6000803e3d6000fd5b505050506040513d6020811015610e5c57600080fd5b5051604080517fab0783da0000000000000000000000000000000000000000000000000000000081529051610b36916b034373d1b5e481853200000091610b2a91600160a060020a0389169163ab0783da91600480820192602092909190829003018186803b158015610ece57600080fd5b505afa158015610ee2573d6000803e3d6000fd5b505050506040513d6020811015610ef857600080fd5b5051604080517f67550a350000000000000000000000000000000000000000000000000000000081529051610b2a91600160a060020a038b16916367550a3591600480820192602092909190829003018186803b158015610f5857600080fd5b505afa158015610f6c573d6000803e3d6000fd5b505050506040513d6020811015610f8257600080fd5b5051604080517f495d32cb0000000000000000000000000000000000000000000000000000000081529051600160a060020a039092169163495d32cb916004808201926020929091908290030181600087803b158015610fe157600080fd5b505af1158015610ff5573d6000803e3d6000fd5b505050506040513d602081101561100b57600080fd5b5051610b2a8b8b61075c565b6003546000908190611033908490600160a060020a0316611608565b15611044575060039050600061104b565b5060009050805b9250929050565b60008061105f858461075c565b90508015156110725760009150506107bd565b60006111096110fc8386600160a060020a0316636f78ee0d8a6040518263ffffffff1660e060020a02815260040180828152602001915050602060405180830381600087803b1580156110c457600080fd5b505af11580156110d8573d6000803e3d6000fd5b505050506040513d60208110156110ee57600080fd5b50519063ffffffff61281d16565b869063ffffffff6127da16565b905060008085600160a060020a031663ace237f56040518163ffffffff1660e060020a02815260040160206040518083038186803b15801561114a57600080fd5b505afa15801561115e573d6000803e3d6000fd5b505050506040513d602081101561117457600080fd5b5051604080517f59e02dd70000000000000000000000000000000000000000000000000000000081528151600160a060020a03909316926359e02dd792600480840193919291829003018186803b1580156111ce57600080fd5b505afa1580156111e2573d6000803e3d6000fd5b505050506040513d60408110156111f857600080fd5b508051602090910151909250905080801561121257508115155b1561122a57611227838363ffffffff6128db16565b94505b505050509392505050565b833330148061124957506112498133612856565b151561128e576040516000805160206143b483398151915281526004018080602001828103825260238152602001806143d46023913960400191505060405180910390fd5b600254604080517f4a4fbeec000000000000000000000000000000000000000000000000000000008152600160a060020a038089166004830152915188939290921691634a4fbeec91602480820192602092909190829003018186803b1580156112f757600080fd5b505afa15801561130b573d6000803e3d6000fd5b505050506040513d602081101561132157600080fd5b505115611367576040516000805160206143b4833981519152815260040180806020018281038252602581526020018061436f6025913960400191505060405180910390fd5b600360009054906101000a9004600160a060020a0316600160a060020a0316639166cba46040518163ffffffff1660e060020a02815260040160206040518083038186803b1580156113b857600080fd5b505afa1580156113cc573d6000803e3d6000fd5b505050506040513d60208110156113e257600080fd5b5051600160a060020a0385811691161461144b57604080516000805160206143b4833981519152815260206004820152601d60248201527f4d616b65723a206465627420746f6b656e206d75737420626520444149000000604482015290519081900360640190fd5b60035461146690879087908690600160a060020a03166128f3565b60408051600160a060020a0386811682526020820186905282518893918a16927ff6669d5e7ff92997c22e9fe3b54f53ed18448cf5fdccb3eb1dc5004798fbb41492908290030190a3505050505050565b600454600160a060020a031681565b600354600160a060020a031681565b604080517f70a082310000000000000000000000000000000000000000000000000000000081523060048201529051600091600160a060020a038416916370a0823191602480820192602092909190829003018186803b15801561153857600080fd5b505afa15801561154c573d6000803e3d6000fd5b505050506040513d602081101561156257600080fd5b505160008054604080517fa9059cbb000000000000000000000000000000000000000000000000000000008152600160a060020a0392831660048201526024810185905290519394509085169263a9059cbb92604480840193602093929083900390910190829087803b1580156115d857600080fd5b505af11580156115ec573d6000803e3d6000fd5b505050506040513d602081101561160257600080fd5b50505050565b600080600160a060020a031682600160a060020a031663de5f5517856040518263ffffffff1660e060020a0281526004018082815260200191505060206040518083038186803b15801561165b57600080fd5b505afa15801561166f573d6000803e3d6000fd5b505050506040513d602081101561168557600080fd5b5051600160a060020a031614159392505050565b60008061191883600160a060020a031663ab0783da6040518163ffffffff1660e060020a02815260040160206040518083038186803b1580156116db57600080fd5b505afa1580156116ef573d6000803e3d6000fd5b505050506040513d602081101561170557600080fd5b5051604080517f67550a350000000000000000000000000000000000000000000000000000000081529051610b3691600160a060020a038816916367550a3591600480820192602092909190829003018186803b15801561176557600080fd5b505afa158015611779573d6000803e3d6000fd5b505050506040513d602081101561178f57600080fd5b5051604080517f495d32cb0000000000000000000000000000000000000000000000000000000081529051600160a060020a039092169163495d32cb916004808201926020929091908290030181600087803b1580156117ee57600080fd5b505af1158015611802573d6000803e3d6000fd5b505050506040513d602081101561181857600080fd5b5051604080517f51f910660000000000000000000000000000000000000000000000000000000081529051610b3691600160a060020a038a16916351f9106691600480820192602092909190829003018186803b15801561187857600080fd5b505afa15801561188c573d6000803e3d6000fd5b505050506040513d60208110156118a257600080fd5b5051604080517f1f3634ed000000000000000000000000000000000000000000000000000000008152600481018c90529051600160a060020a038b1691631f3634ed916024808301926020929190829003018186803b15801561190457600080fd5b505afa158015610b06573d6000803e3d6000fd5b9050610bc783600160a060020a031663f7c8d634866040518263ffffffff1660e060020a02815260040180828152602001915050602060405180830381600087803b15801561196657600080fd5b505af1158015610ba2573d6000803e3d6000fd5b813330148061198e575061198e8133612856565b15156119d3576040516000805160206143b483398151915281526004018080602001828103825260238152602001806143d46023913960400191505060405180910390fd5b600254604080517f4a4fbeec000000000000000000000000000000000000000000000000000000008152600160a060020a038087166004830152915186939290921691634a4fbeec91602480820192602092909190829003018186803b158015611a3c57600080fd5b505afa158015611a50573d6000803e3d6000fd5b505050506040513d6020811015611a6657600080fd5b505115611aac576040516000805160206143b4833981519152815260040180806020018281038252602581526020018061436f6025913960400191505060405180910390fd5b600354600454611acc9186918691600160a060020a039081169116612985565b6040518390600160a060020a038616907f07e4a0c6f06275f83bcf78e5a10eb7f5515574d593bce993377961f4133b951c90600090a350505050565b6000805a90506000611b58308c60008d8d8080601f0160208091040260200160405190810160405280939291908181526020018383808284376000920191909152508f92508c91508b9050612a5f565b9050611b658b8983612ba2565b1515611bc057604080516000805160206143b4833981519152815260206004820152601560248201527f524d3a204475706c696361746520726571756573740000000000000000000000604482015290519081900360640190fd5b611c008b8b8b8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612bae92505050565b1515611c45576040516000805160206143b4833981519152815260040180806020018281038252604a8152602001806142d2604a913960600191505060405180910390fd5b6000611c878c8c8c8080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250612c2792505050565b905060418102871415611d9f57611ca08c868884612c2f565b15611d9f57801580611d235750611d238c8c8c8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8f018190048102820181019092528d815288935091508d908d9081908401838280828437600092019190915250612d0192505050565b15611d9f5730600160a060020a03168b8b604051808383808284376040519201945060009350909150508083038183865af19150503d8060008114611d84576040519150601f19603f3d011682016040523d82523d6000602084013e611d89565b606091505b505080945050611d9f8c5a850388888533612d26565b60408051838152905185151591600160a060020a038f16917f6bb0b384ce772133df63560651bc8c727c53306cec1d51e2cbf8ea35fb8f2ec19181900360200190a350505098975050505050505050565b8333301480611e045750611e048133612856565b1515611e49576040516000805160206143b483398151915281526004018080602001828103825260238152602001806143d46023913960400191505060405180910390fd5b600254604080517f4a4fbeec000000000000000000000000000000000000000000000000000000008152600160a060020a038089166004830152915188939290921691634a4fbeec91602480820192602092909190829003018186803b158015611eb257600080fd5b505afa158015611ec6573d6000803e3d6000fd5b505050506040513d6020811015611edc57600080fd5b505115611f22576040516000805160206143b4833981519152815260040180806020018281038252602581526020018061436f6025913960400191505060405180910390fd5b600160a060020a03841673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee14611f9b57604080516000805160206143b4833981519152815260206004820152601d60248201527f4d616b65723a20636f6c6c61746572616c206d75737420626520455448000000604482015290519081900360640190fd5b600354611fb690879087908690600160a060020a0316612df5565b60408051600160a060020a0386811682526020820186905282518893918a16927ff1dec7a92ef063b16d2098bb05803ed604936a7ff30f0d245fe881baf96e8e6b92908290030190a3505050505050565b6000853330148061201d575061201d8133612856565b1515612062576040516000805160206143b483398151915281526004018080602001828103825260238152602001806143d46023913960400191505060405180910390fd5b600254604080517f4a4fbeec000000000000000000000000000000000000000000000000000000008152600160a060020a03808b16600483015291518a939290921691634a4fbeec91602480820192602092909190829003018186803b1580156120cb57600080fd5b505afa1580156120df573d6000803e3d6000fd5b505050506040513d60208110156120f557600080fd5b50511561213b576040516000805160206143b4833981519152815260040180806020018281038252602581526020018061436f6025913960400191505060405180910390fd5b600160a060020a03871673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee146121b457604080516000805160206143b4833981519152815260206004820152601d60248201527f4d616b65723a20636f6c6c61746572616c206d75737420626520455448000000604482015290519081900360640190fd5b600360009054906101000a9004600160a060020a0316600160a060020a0316639166cba46040518163ffffffff1660e060020a02815260040160206040518083038186803b15801561220557600080fd5b505afa158015612219573d6000803e3d6000fd5b505050506040513d602081101561222f57600080fd5b5051600160a060020a0386811691161461229857604080516000805160206143b4833981519152815260206004820152601d60248201527f4d616b65723a206465627420746f6b656e206d75737420626520444149000000604482015290519081900360640190fd5b6003546122b390899088908790600160a060020a0316612e01565b60408051600160a060020a038a81168252602082018a9052888116828401526060820188905291519295508592918b16917ff9d7e11fb5d8d1e0a4be344a6a6adfb912161747edf926fb283150d07c39c1089181900360800190a3505095945050505050565b833330148061232d575061232d8133612856565b1515612372576040516000805160206143b483398151915281526004018080602001828103825260238152602001806143d46023913960400191505060405180910390fd5b600254604080517f4a4fbeec000000000000000000000000000000000000000000000000000000008152600160a060020a038089166004830152915188939290921691634a4fbeec91602480820192602092909190829003018186803b1580156123db57600080fd5b505afa1580156123ef573d6000803e3d6000fd5b505050506040513d602081101561240557600080fd5b50511561244b576040516000805160206143b4833981519152815260040180806020018281038252602581526020018061436f6025913960400191505060405180910390fd5b600160a060020a03841673eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee146124c457604080516000805160206143b4833981519152815260206004820152601d60248201527f4d616b65723a20636f6c6c61746572616c206d75737420626520455448000000604482015290519081900360640190fd5b6003546124df90879087908690600160a060020a0316612f9a565b60408051600160a060020a0386811682526020820186905282518893918a16927fdd016248708c391ccb5c72f9258127c75b9b291ac1479513fe4f331c3489013792908290030190a3505050505050565b60016020526000908152604090205481565b600254600160a060020a031681565b833330148061256557506125658133612856565b15156125aa576040516000805160206143b483398151915281526004018080602001828103825260238152602001806143d46023913960400191505060405180910390fd5b600254604080517f4a4fbeec000000000000000000000000000000000000000000000000000000008152600160a060020a038089166004830152915188939290921691634a4fbeec91602480820192602092909190829003018186803b15801561261357600080fd5b505afa158015612627573d6000803e3d6000fd5b505050506040513d602081101561263d57600080fd5b505115612683576040516000805160206143b4833981519152815260040180806020018281038252602581526020018061436f6025913960400191505060405180910390fd5b600360009054906101000a9004600160a060020a0316600160a060020a0316639166cba46040518163ffffffff1660e060020a02815260040160206040518083038186803b1580156126d457600080fd5b505afa1580156126e8573d6000803e3d6000fd5b505050506040513d60208110156126fe57600080fd5b5051600160a060020a0385811691161461276757604080516000805160206143b4833981519152815260206004820152601d60248201527f4d616b65723a206465627420746f6b656e206d75737420626520444149000000604482015290519081900360640190fd5b60035460045461278991889188918791600160a060020a039182169116613080565b60408051600160a060020a0386811682526020820186905282518893918a16927fbfa42ea7d37497e6a09441fadba47d64b610b6b1183d895dd0a42507973430bf92908290030190a3505050505050565b60006b033b2e3c9fd0803ce800000061280c6127f6858561388b565b60026b033b2e3c9fd0803ce80000005b046138b6565b81151561281557fe5b049392505050565b60008161280c612839856b033b2e3c9fd0803ce800000061388b565b600285612806565b60008282111561285057600080fd5b50900390565b600081600160a060020a031683600160a060020a0316638da5cb5b6040518163ffffffff1660e060020a02815260040160206040518083038186803b15801561289e57600080fd5b505afa1580156128b2573d6000803e3d6000fd5b505050506040513d60208110156128c857600080fd5b5051600160a060020a0316149392505050565b60008161280c61283985670de0b6b3a764000061388b565b604080517f6472617728627974657333322c75696e74323536290000000000000000000000815281519081900360150181206024820186905260448083018690528351808403909101815260649092019092526020810180516000805160206143f7833981519152166000805160206143948339815191529093169290921790915261160290859083906000906138c8565b6000612991848461075c565b905060008111156129a9576129a98585838686613080565b60006129b58585610d94565b905060008111156129cc576129cc86868387612df5565b604080517f73687574286279746573333229000000000000000000000000000000000000008152815190819003600d01812060248083018990528351808403909101815260449092019092526020810180516000805160206143f78339815191521660008051602061439483398151915290931692909217909152612a5790879086906000906138c8565b505050505050565b6040517f190000000000000000000000000000000000000000000000000000000000000060208083018281526000602185018190526c01000000000000000000000000600160a060020a03808e16820260228801528c16026036860152604a85018a90528851909485938d938d938d938d938d938d938d939192606a909201918701908083835b60208310612b055780518252601f199092019160209182019101612ae6565b51815160209384036101000a600019018019909216911617905292019586525084810193909352506040808401919091528051808403820181526060840182528051908301207f19457468657265756d205369676e6564204d6573736167653a0a3332000000006080850152609c808501919091528151808503909101815260bc909301905281519101209e9d5050505050505050505050505050565b6000610bc784846139b3565b60006024825110151515612c1157604080516000805160206143b4833981519152815260206004820152601660248201527f524d3a20496e76616c6964206461746157616c6c657400000000000000000000604482015290519081900360640190fd5b5060240151600160a060020a0391821691161490565b600192915050565b60008083118015612c405750600182115b8015612ce9575082840285600160a060020a0316311080612ce95750604080517fd6eb1bbf0000000000000000000000000000000000000000000000000000000081523060048201529051600160a060020a0387169163d6eb1bbf916024808301926020929190829003018186803b158015612cbb57600080fd5b505afa158015612ccf573d6000803e3d6000fd5b505050506040513d6020811015612ce557600080fd5b5051155b15612cf657506000610bc7565b506001949350505050565b600080612d1084846000613a3d565b9050612d1c8682612856565b9695505050505050565b61726c8501600085118015612d3b5750600183115b8015612d475750838111155b15610d8b573a851115612d5b573a02612d5e565b84025b604080517f8f6f0332000000000000000000000000000000000000000000000000000000008152600160a060020a03848116600483015260248201849052606060448301526000606483018190529251908a1692638f6f03329260a4808201939182900301818387803b158015612dd457600080fd5b505af1158015612de8573d6000803e3d6000fd5b5050505050505050505050565b61160284848484613ae7565b600081600160a060020a031663fcfff16f6040518163ffffffff1660e060020a028152600401602060405180830381600087803b158015612e4157600080fd5b505af1158015612e55573d6000803e3d6000fd5b505050506040513d6020811015612e6b57600080fd5b5051604080517fbaa8529c00000000000000000000000000000000000000000000000000000000815260048101839052600160a060020a03888116602483015291519293509084169163baa8529c9160448082019260009290919082900301818387803b158015612edb57600080fd5b505af1158015612eef573d6000803e3d6000fd5b50505050612eff85828685613e99565b6000831115610bc757604080517f6472617728627974657333322c75696e74323536290000000000000000000000815281519081900360150181206024820184905260448083018790528351808403909101815260649092019092526020810180516000805160206143f78339815191521660008051602061439483398151915290931692909217909152610bc790869084906000906138c8565b80600160a060020a031663de5f5517846040518263ffffffff1660e060020a0281526004018082815260200191505060206040518083038186803b158015612fe157600080fd5b505afa158015612ff5573d6000803e3d6000fd5b505050506040513d602081101561300b57600080fd5b5051600160a060020a0385811691161461307457604080516000805160206143b4833981519152815260206004820152601160248201527f434d3a206e6f7420434450206f776e6572000000000000000000000000000000604482015290519081900360640190fd5b61160284848484613e99565b81600160a060020a031663de5f5517856040518263ffffffff1660e060020a0281526004018082815260200191505060206040518083038186803b1580156130c757600080fd5b505afa1580156130db573d6000803e3d6000fd5b505050506040513d60208110156130f157600080fd5b5051600160a060020a0386811691161461315a57604080516000805160206143b4833981519152815260206004820152601160248201527f434d3a206e6f7420434450206f776e6572000000000000000000000000000000604482015290519081900360640190fd5b6000613167858585611052565b9050600083600160a060020a03166312d43a516040518163ffffffff1660e060020a02815260040160206040518083038186803b1580156131a757600080fd5b505afa1580156131bb573d6000803e3d6000fd5b505050506040513d60208110156131d157600080fd5b5051604080517f70a08231000000000000000000000000000000000000000000000000000000008152600160a060020a038a811660048301529151929350600092918416916370a0823191602480820192602092909190829003018186803b15801561323c57600080fd5b505afa158015613250573d6000803e3d6000fd5b505050506040513d602081101561326657600080fd5b505190508281101561340d57600084600160a060020a03166306f2bf62846040518263ffffffff1660e060020a0281526004018082600160a060020a0316600160a060020a0316815260200191505060206040518083038186803b1580156132cd57600080fd5b505afa1580156132e1573d6000803e3d6000fd5b505050506040513d60208110156132f757600080fd5b5051604080517f59e9486200000000000000000000000000000000000000000000000000000000815284870360048201529051919250600091600160a060020a038416916359e94862916024808301926020929190829003018186803b15801561336057600080fd5b505afa158015613374573d6000803e3d6000fd5b505050506040513d602081101561338a57600080fd5b505160405190915061340a908b908490849080602561434a8239604080519182900360250182208a8d036024840152426044808501919091528251808503909101815260649093019091526020820180516000805160206143f78339815191521660008051602061439483398151915290921691909117905290506138c8565b50505b600085600160a060020a0316639166cba46040518163ffffffff1660e060020a02815260040160206040518083038186803b15801561344b57600080fd5b505afa15801561345f573d6000803e3d6000fd5b505050506040513d602081101561347557600080fd5b5051604080517f70a08231000000000000000000000000000000000000000000000000000000008152600160a060020a038c811660048301529151929350600092918416916370a0823191602480820192602092909190829003018186803b1580156134e057600080fd5b505afa1580156134f4573d6000803e3d6000fd5b505050506040513d602081101561350a57600080fd5b50519050878110156136b957600086600160a060020a03166306f2bf62846040518263ffffffff1660e060020a0281526004018082600160a060020a0316600160a060020a0316815260200191505060206040518083038186803b15801561357157600080fd5b505afa158015613585573d6000803e3d6000fd5b505050506040513d602081101561359b57600080fd5b5051604080517f59e94862000000000000000000000000000000000000000000000000000000008152848c0360048201529051919250600091600160a060020a038416916359e94862916024808301926020929190829003018186803b15801561360457600080fd5b505afa158015613618573d6000803e3d6000fd5b505050506040513d602081101561362e57600080fd5b50516040519091506136b6908d908490849080602561434a823960250190506040518091039020878f03426040516024018083815260200182815260200192505050604051602081830303815290604052906000805160206143f783398151915219166020820180516000805160206143f783398151915283818316178352505050506138c8565b50505b604080517f617070726f766528616464726573732c75696e7432353629000000000000000081528151908190036018018120600160a060020a038a16602483015260448083018c90528351808403909101815260649092019092526020810180516000805160206143f78339815191521660008051602061439483398151915290931692909217909152613753908b9084906000906138c8565b604080517f617070726f766528616464726573732c75696e7432353629000000000000000081528151908190036018018120600160a060020a038a16602483015260448083018990528351808403909101815260649092019092526020810180516000805160206143f783398151915216600080516020614394833981519152909316929092179091526137ed908b9086906000906138c8565b604080517f7769706528627974657333322c75696e7432353629000000000000000000000081528151908190036015018120602482018c905260448083018c90528351808403909101815260649092019092526020810180516000805160206143f7833981519152166000805160206143948339815191529093169290921790915261387f908b9089906000906138c8565b50505050505050505050565b600082151561389c57506000610756565b8282028284828115156138ab57fe5b04146107bd57600080fd5b6000828201838110156107bd57600080fd5b83600160a060020a0316638f6f03328484846040518463ffffffff1660e060020a0281526004018084600160a060020a0316600160a060020a0316815260200183815260200180602001828103825283818151815260200191508051906020019080838360005b8381101561394757818101518382015260200161392f565b50505050905090810190601f1680156139745780820380516001836020036101000a031916815260200191505b50945050505050600060405180830381600087803b15801561399557600080fd5b505af11580156139a9573d6000803e3d6000fd5b5050505050505050565b600160a060020a03821660009081526001602052604081205482116139da57506000610756565b7001000000000000000000000000000000006fffffffffffffffffffffffffffffffff198316044361271001811115613a17576000915050610756565b5050600160a060020a038216600090815260016020819052604090912082905592915050565b6041808202830160208101516040820151919092015160009260ff9190911691601b831480613a6f57508260ff16601c145b1515613a7a57600080fd5b604080516000815260208082018084528a905260ff8616828401526060820185905260808201849052915160019260a0808401939192601f1981019281900390910190855afa158015613ad1573d6000803e3d6000fd5b5050604051601f19015198975050505050505050565b604080517f6672656528627974657333322c75696e74323536290000000000000000000000815281519081900360150181206024820186905260448083018690528351808403909101815260649092019092526020810180516000805160206143f78339815191521660008051602061439483398151915290931692909217909152613b7990859083906000906138c8565b600081600160a060020a0316637bd2bea76040518163ffffffff1660e060020a02815260040160206040518083038186803b158015613bb757600080fd5b505afa158015613bcb573d6000803e3d6000fd5b505050506040513d6020811015613be157600080fd5b5051604080517f0f8a771e0000000000000000000000000000000000000000000000000000000081529051919250600091600160a060020a03851691630f8a771e916004808301926020929190829003018186803b158015613c4257600080fd5b505afa158015613c56573d6000803e3d6000fd5b505050506040513d6020811015613c6c57600080fd5b5051604080517f617070726f766528616464726573732c75696e7432353629000000000000000081528151908190036018018120600160a060020a038716602483015260448083018990528351808403909101815260649092019092526020810180516000805160206143f78339815191521660008051602061439483398151915290931692909217909152909150613d0b90879083906000906138c8565b604080517f657869742875696e7432353629000000000000000000000000000000000000008152815190819003600d01812060248083018890528351808403909101815260449092019092526020810180516000805160206143f78339815191521660008051602061439483398151915290931692909217909152613d9690879085906000906138c8565b600083600160a060020a031663454a2ab3866040518263ffffffff1660e060020a0281526004018082815260200191505060206040518083038186803b158015613ddf57600080fd5b505afa158015613df3573d6000803e3d6000fd5b505050506040513d6020811015613e0957600080fd5b5051604080517f77697468647261772875696e74323536290000000000000000000000000000008152815190819003601101812060248083018590528351808403909101815260449092019092526020810180516000805160206143f78339815191521660008051602061439483398151915290931692909217909152909150610d8b90889085906000906138c8565b600081600160a060020a0316637bd2bea76040518163ffffffff1660e060020a02815260040160206040518083038186803b158015613ed757600080fd5b505afa158015613eeb573d6000803e3d6000fd5b505050506040513d6020811015613f0157600080fd5b5051604080517fe47e7e66000000000000000000000000000000000000000000000000000000008152600481018690529051919250600091600160a060020a0385169163e47e7e66916024808301926020929190829003018186803b158015613f6957600080fd5b505afa158015613f7d573d6000803e3d6000fd5b505050506040513d6020811015613f9357600080fd5b5051604080517f6465706f736974282900000000000000000000000000000000000000000000008152815190819003600901812060048252602482019092526020810180516000805160206143f78339815191521660008051602061439483398151915290931692909217909152909150614013908790849084906138c8565b604080517f617070726f766528616464726573732c75696e7432353629000000000000000081528151908190036018018120600160a060020a038616602483015260448083018590528351808403909101815260649092019092526020810180516000805160206143f783398151915216600080516020614394833981519152909316929092179091526140ad90879084906000906138c8565b604080517f6a6f696e2875696e7432353629000000000000000000000000000000000000008152815190819003600d01812060248083018890528351808403909101815260449092019092526020810180516000805160206143f7833981519152166000805160206143948339815191529093169290921790915261413890879085906000906138c8565b600083600160a060020a0316630f8a771e6040518163ffffffff1660e060020a02815260040160206040518083038186803b15801561417657600080fd5b505afa15801561418a573d6000803e3d6000fd5b505050506040513d60208110156141a057600080fd5b5051604080517f617070726f766528616464726573732c75696e7432353629000000000000000081528151908190036018018120600160a060020a038816602483015260448083018a90528351808403909101815260649092019092526020810180516000805160206143f7833981519152166000805160206143948339815191529093169290921790915290915061423f90889083906000906138c8565b604080517f6c6f636b28627974657333322c75696e74323536290000000000000000000000815281519081900360150181206024820189905260448083018990528351808403909101815260649092019092526020810180516000805160206143f78339815191521660008051602061439483398151915290931692909217909152610d8b90889086906000906138c856fe524d3a207468652077616c6c657420617574686f72697a656420697320646966666572656e74207468656e2074686520746172676574206f66207468652072656c617965642064617461424d3a206d73672e73656e646572206d75737420626520616e206f776e657220666f72207468652077616c6c6574657468546f546f6b656e537761704f75747075742875696e743235362c75696e74323536294d616b65724d616e616765723a2077616c6c6574206d75737420626520756e6c6f636b6564ffffffff0000000000000000000000000000000000000000000000000000000008c379a000000000000000000000000000000000000000000000000000000000424d3a206d75737420626520616e206f776e657220666f72207468652077616c6c657400000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffa165627a7a723058203bf4bedfff4a0e165cdef420704ae6d0f63199fb310cca443144b76dcd0d02720029

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

000000000000000000000000c17d432bd8e8850fd7b32b0270f5afac65db010500000000000000000000000044da3a8051ba88eab0440db3779cab9d679ae76f000000000000000000000000448a5065aebb8e423f0896e6c5d525c040f59af3000000000000000000000000c0a47dfe034b400b47bdad5fecda2621de6c4d95

-----Decoded View---------------
Arg [0] : _registry (address): 0xc17D432Bd8e8850Fd7b32B0270f5AfAc65DB0105
Arg [1] : _guardianStorage (address): 0x44DA3A8051bA88EAB0440DB3779cAB9D679ae76f
Arg [2] : _makerCdp (address): 0x448a5065aeBB8E423F0896E6c5D525C040f59af3
Arg [3] : _uniswapFactory (address): 0xc0a47dFe034B400B47bDaD5FecDa2621de6c4d95

-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 000000000000000000000000c17d432bd8e8850fd7b32b0270f5afac65db0105
Arg [1] : 00000000000000000000000044da3a8051ba88eab0440db3779cab9d679ae76f
Arg [2] : 000000000000000000000000448a5065aebb8e423f0896e6c5d525c040f59af3
Arg [3] : 000000000000000000000000c0a47dfe034b400b47bdad5fecda2621de6c4d95


Deployed Bytecode Sourcemap

27936:23719:0:-;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;27936:23719:0;;;;;;;;-1:-1:-1;;;27936:23719:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;44629:120;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;44629:120:0;;;;;;-1:-1:-1;;;;;44629:120:0;;:::i;:::-;;;;;;;;;;;;;;;;;;44257:123;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;44257:123:0;;;;;;-1:-1:-1;;;;;44257:123:0;;:::i;:::-;;;;;;;;;;;;;;;;47239:188;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;47239:188:0;;;;;;-1:-1:-1;;;;;47239:188:0;;:::i;15188:122::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;15188:122:0;-1:-1:-1;;;;;15188:122:0;;:::i;:::-;;20244:133;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;20244:133:0;-1:-1:-1;;;;;20244:133:0;;:::i;46035:267::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;46035:267:0;;;;;;-1:-1:-1;;;;;46035:267:0;;:::i;15511:258::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;15511:258:0;;;;;;;;;;:::i;43851:135::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;43851:135:0;;;;;;-1:-1:-1;;;;;43851:135:0;;:::i;47694:446::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;47694:446:0;;;;;;-1:-1:-1;;;;;47694:446:0;;:::i;36045:282::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;36045:282:0;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;46568:418;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;46568:418:0;;;;;;;;;;;-1:-1:-1;;;;;46568:418:0;;:::i;34228:455::-;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;-1:-1;;;;;;34228:455:0;;;;;;;;;;;;;;;;;;;;:::i;28241:36::-;;;:::i;:::-;;;;-1:-1:-1;;;;;28241:36:0;;;;;;;;;;;;;;28172:25;;;:::i;15983:176::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;15983:176:0;-1:-1:-1;;;;;15983:176:0;;:::i;44956:138::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;44956:138:0;;;;;;-1:-1:-1;;;;;44956:138:0;;:::i;45436:260::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;45436:260:0;;;;;;-1:-1:-1;;;;;45436:260:0;;:::i;31845:299::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;;;31845:299:0;;;;;;;;:::i;18786:1343::-;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;-1:-1;;;;;18786:1343:0;;;;;;;;;;;;;;;21:11:-1;5:28;;2:2;;;46:1;43;36:12;2:2;18786:1343:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;18786:1343: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;18786:1343:0;;;;;;;;;;;;;;21:11:-1;5:28;;2:2;;;46:1;43;36:12;2:2;18786:1343:0;;35:9:-1;28:4;12:14;8:25;5:40;2:2;;;58:1;55;48:12;2:2;18786:1343: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;18786:1343:0;;-1:-1:-1;18786:1343:0;-1:-1:-1;18786:1343:0;;;;;;;:::i;33365:510::-;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;-1:-1;;;;;;33365:510:0;;;;;;;;;;;;;;;;;;;;:::i;30927:675::-;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;-1:-1;;;;;;30927:675:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;32500:501::-;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;-1:-1;;;;;;32500:501:0;;;;;;;;;;;;;;;;;;;;:::i;16772:49::-;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;16772:49:0;-1:-1:-1;;;;;16772:49:0;;:::i;28096:38::-;;;:::i;35034:479::-;;;;;;13:3:-1;8;5:12;2:2;;;30:1;27;20:12;2:2;-1:-1;;;;;;35034:479:0;;;;;;;;;;;;;;;;;;;;:::i;44629:120::-;44696:4;44721:9;-1:-1:-1;;;;;44721:14:0;;44736:4;44721:20;;;;;-1:-1:-1;;;44721:20:0;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;44721:20:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;44721:20:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;44721:20:0;;-1:-1:-1;44629:120:0;;;;;:::o;44257:123::-;44325:7;44353:9;-1:-1:-1;;;;;44353:13:0;;44367:4;44353:19;;;;;-1:-1:-1;;;44353:19:0;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;47239:188:0;47325:12;47358:61;47377:4;47383:24;47391:4;47397:9;47383:7;:24::i;:::-;47409:9;47358:18;:61::i;:::-;47351:68;47239:188;-1:-1:-1;;;47239:188:0:o;15188:122::-;15242:7;14352:10;-1:-1:-1;;;;;14352:30:0;;;14344:68;;;;;-1:-1:-1;;;;;;;;;;;14344:68:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;15267:35;;;-1:-1:-1;;;;;15267:35:0;;;;;;;;;;;;;;;15188:122;;:::o;20244:133::-;-1:-1:-1;;;;;20338:25:0;20305:13;20338:25;;;:7;:25;;;;;:31;;20244:133::o;46035:267::-;46117:7;46137:14;46154:91;46229:9;-1:-1:-1;;;;;46229:13:0;;:15;;;;;-1:-1:-1;;;46229:15:0;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;46229:15:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;46229:15:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;46229:15:0;46201;;;;;;;;46154:69;;-1:-1:-1;;;;;46201:13:0;;;;;:15;;;;;46229;;46201;;;;;;;;:13;:15;;;5:2:-1;;;;30:1;27;20:12;5:2;46201:15:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;46201:15:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;46201:15:0;:21;;;;;;;;-1:-1:-1;;;;;46201:19:0;;;;;;:21;;;;;:15;;:21;;;;;;;;;:19;:21;;;5:2:-1;;;;30:1;27;20:12;5:2;46201:21:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;46201:21:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;46201:21:0;46179:15;;;;;;;;46154:41;;-1:-1:-1;;;;;46179:13:0;;;;;:15;;;;;46201:21;;46179:15;;;;;;;;:13;:15;;;5:2:-1;;;;30:1;27;20:12;5:2;46179:15:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;46179:15:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;46179:15:0;46154:19;;;;;;;;;;;;;;-1:-1:-1;;;;;46154:13:0;;;;;:19;;;;;46179:15;;46154:19;;;;;;;-1:-1:-1;46154:13:0;:19;;;5:2:-1;;;;30:1;27;20:12;5:2;46154:19:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;46154:19:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;46154:19:0;;:41;:24;:41;:::i;:::-;:46;:69;:46;:69;:::i;:::-;:74;:91;:74;:91;:::i;:::-;46137:108;;46263:31;46274:9;-1:-1:-1;;;;;46274:13:0;;46288:4;46274:19;;;;;-1:-1:-1;;;46274:19:0;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;46274:19:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;46274:19:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;46274:19:0;46263:6;;:31;:10;:31;:::i;:::-;46256:38;46035:267;-1:-1:-1;;;;46035:267:0:o;15511:258::-;15597:7;14904:28;14912:7;14921:10;14904:7;:28::i;:::-;14896:87;;;;;;-1:-1:-1;;;;;;;;;;;14896:87:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;15625:8;;:45;;;;;;-1:-1:-1;;;;;15625:45:0;;;;;;;;;:8;;;;;:27;;:45;;;;;;;;;;;;;;:8;:45;;;5:2:-1;;;;30:1;27;20:12;5:2;15625:45:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;15625:45:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;15625:45:0;15617:86;;;;;;;-1:-1:-1;;;;;;;;;;;15617:86:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;15714:47;;;;;;-1:-1:-1;;;;;15714:47:0;;;;;;;15756:4;15714:47;;;;;;:23;;;;;;:47;;;;;-1:-1:-1;;15714:47:0;;;;;;;;-1:-1:-1;15714:23:0;:47;;;5:2:-1;;;;30:1;27;20:12;5:2;15714:47:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;15714:47:0;;;;15511:258;;;:::o;43851:135::-;43931:7;43959:9;-1:-1:-1;;;;;43959:13:0;;43973:4;43959:19;;;;;-1:-1:-1;;;43959:19:0;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;43959:19:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;47694:446:0;47776:22;47829:270;48083:9;-1:-1:-1;;;;;48083:13:0;;:15;;;;;-1:-1:-1;;;48083:15:0;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;48083:15:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;48083:15:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;48083:15:0;47955;;;;;;;;47829:214;;48014:28;;47829:142;;-1:-1:-1;;;;;47955:13:0;;;;;:15;;;;;48083;;47955;;;;;;;;:13;:15;;;5:2:-1;;;;30:1;27;20:12;5:2;47955:15:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;47955:15:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;47955:15:0;47888;;;;;;;;47829:81;;-1:-1:-1;;;;;47888:13:0;;;;;:15;;;;;47955;;47888;;;;;;;;:13;:15;;;5:2:-1;;;;30:1;27;20:12;5:2;47888:15:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;47888:15:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;47888:15:0;:21;;;;;;;;-1:-1:-1;;;;;47888:19:0;;;;;;:21;;;;;:15;;:21;;;;;;;;;:19;:21;;;5:2:-1;;;;30:1;27;20:12;5:2;47888:21:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;47888:21:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;47888:21:0;47829:24;47837:4;47843:9;47829:7;:24::i;36045:282::-;36247:8;;36178:13;;;;36231:25;;36238:7;;-1:-1:-1;;;;;36247:8:0;36231:6;:25::i;:::-;36228:69;;;-1:-1:-1;36281:1:0;;-1:-1:-1;36283:1:0;36273:12;;36228:69;-1:-1:-1;36315:1:0;;-1:-1:-1;36315:1:0;36045:282;;;;;;:::o;46568:418::-;46667:12;46693:9;46705:24;46713:4;46719:9;46705:7;:24::i;:::-;46693:36;-1:-1:-1;46744:9:0;;46740:23;;;46762:1;46755:8;;;;;46740:23;46774:16;46793:47;46809:30;46834:4;46809:9;-1:-1:-1;;;;;46809:13:0;;46823:4;46809:19;;;;;-1:-1:-1;;;46809:19:0;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;46809:19:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;46809:19:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;46809:19:0;;:30;:24;:30;:::i;:::-;46793:10;;:47;:15;:47;:::i;:::-;46774:66;;46852:17;46871:7;46882:9;-1:-1:-1;;;;;46882:13:0;;:15;;;;;-1:-1:-1;;;46882:15:0;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;46882:15:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;46882:15:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;46882:15:0;:22;;;;;;;;-1:-1:-1;;;;;46882:20:0;;;;;;:22;;;;;;;;;;;;;:20;:22;;;5:2:-1;;;;30:1;27;20:12;5:2;46882:22:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;46882:22:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;46882:22:0;;;;;;;;;-1:-1:-1;46882:22:0;-1:-1:-1;46882:22:0;46919:20;;;;-1:-1:-1;46925:14:0;;;46919:20;46915:63;;;46948:30;:8;46967:9;46948:30;:13;:30;:::i;:::-;46941:37;;46915:63;46568:418;;;;;;;;;:::o;34228:455::-;34409:7;14616:10;14638:4;14616:27;;:59;;;14647:28;14655:7;14664:10;14647:7;:28::i;:::-;14608:107;;;;;;-1:-1:-1;;;;;;;;;;;14608:107:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;29878:15;;:33;;;;;;-1:-1:-1;;;;;29878:33:0;;;;;;;;;34444:7;;29878:15;;;;;:24;;:33;;;;;;;;;;;;;;;:15;:33;;;5:2:-1;;;;30:1;27;20:12;5:2;29878:33:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;29878:33:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;29878:33:0;29877:34;29869:84;;;;-1:-1:-1;;;;;;;;;;;29869:84:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;34491:8;;;;;;;;;-1:-1:-1;;;;;34491:8:0;-1:-1:-1;;;;;34491:12:0;;:14;;;;;-1:-1:-1;;;34491:14:0;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;34491:14:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;34491:14:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;34491:14:0;-1:-1:-1;;;;;34477:28:0;;;;;;34469:70;;;;;-1:-1:-1;;;;;;;;;;;34469:70:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;34589:8;;34550:48;;34558:7;;34567;;34576:11;;-1:-1:-1;;;;;34589:8:0;34550:7;:48::i;:::-;34614:61;;;-1:-1:-1;;;;;34614:61:0;;;;;;;;;;;;;34642:7;;34614:61;;;;;;;;;;;;;14726:1;34228:455;;;;;:::o;28241:36::-;;;-1:-1:-1;;;;;28241:36:0;;:::o;28172:25::-;;;-1:-1:-1;;;;;28172:25:0;;:::o;15983:176::-;16054:38;;;;;;16086:4;16054:38;;;;;;16041:10;;-1:-1:-1;;;;;16054:23:0;;;;;:38;;;;;;;;;;;;;;;:23;:38;;;5:2:-1;;;;30:1;27;20:12;5:2;16054:38:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;16054:38:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;16054:38:0;16134:8;;;16103:48;;;;;;-1:-1:-1;;;;;16134:8:0;;;16103:48;;;;;;;;;;;;16054:38;;-1:-1:-1;16103:22:0;;;;;;:48;;;;;16054:38;;16103:48;;;;;;;;;;;:22;:48;;;5:2:-1;;;;30:1;27;20:12;5:2;16103:48:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;16103:48:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;;;;15983:176:0:o;44956:138::-;45028:4;45084:1;-1:-1:-1;;;;;45053:33:0;:9;-1:-1:-1;;;;;45053:13:0;;45067:4;45053:19;;;;;-1:-1:-1;;;45053:19:0;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;45053:19:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;45053:19:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;45053:19:0;-1:-1:-1;;;;;45053:33:0;;;;44956:138;-1:-1:-1;;;44956:138:0:o;45436:260::-;45511:7;45531:14;45548:91;45623:9;-1:-1:-1;;;;;45623:13:0;;:15;;;;;-1:-1:-1;;;45623:15:0;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;45623:15:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;45623:15:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;45623:15:0;45595;;;;;;;;45548:69;;-1:-1:-1;;;;;45595:13:0;;;;;:15;;;;;45623;;45595;;;;;;;;:13;:15;;;5:2:-1;;;;30:1;27;20:12;5:2;45595:15:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;45595:15:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;45595:15:0;:21;;;;;;;;-1:-1:-1;;;;;45595:19:0;;;;;;:21;;;;;:15;;:21;;;;;;;;;:19;:21;;;5:2:-1;;;;30:1;27;20:12;5:2;45595:21:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;45595:21:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;45595:21:0;45573:15;;;;;;;;45548:41;;-1:-1:-1;;;;;45573:13:0;;;;;:15;;;;;45595:21;;45573:15;;;;;;;;:13;:15;;;5:2:-1;;;;30:1;27;20:12;5:2;45573:15:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;45573:15:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;45573:15:0;45548:19;;;;;;;;;;;;;;-1:-1:-1;;;;;45548:13:0;;;;;:19;;;;;45573:15;;45548:19;;;;;;;:13;:19;;;5:2:-1;;;;30:1;27;20:12;5:2;45548:19:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;45548:91:0;45531:108;;45657:31;45668:9;-1:-1:-1;;;;;45668:13:0;;45682:4;45668:19;;;;;-1:-1:-1;;;45668:19:0;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;45668:19:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;31845:299:0;31971:7;14616:10;14638:4;14616:27;;:59;;;14647:28;14655:7;14664:10;14647:7;:28::i;:::-;14608:107;;;;;;-1:-1:-1;;;;;;;;;;;14608:107:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;29878:15;;:33;;;;;;-1:-1:-1;;;;;29878:33:0;;;;;;;;;32006:7;;29878:15;;;;;:24;;:33;;;;;;;;;;;;;;;:15;:33;;;5:2:-1;;;;30:1;27;20:12;5:2;29878:33:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;29878:33:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;29878:33:0;29877:34;29869:84;;;;-1:-1:-1;;;;;;;;;;;29869:84:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;32058:8;;32068:14;;32031:52;;32040:7;;32049;;-1:-1:-1;;;;;32058:8:0;;;;32068:14;32031:8;:52::i;:::-;32099:37;;32128:7;;-1:-1:-1;;;;;32099:37:0;;;;;;;;14726:1;31845:299;;;:::o;18786:1343::-;19027:12;19057:13;19073:9;19057:25;;19093:16;19112:84;19132:4;19147:7;19157:1;19160:5;;19112:84;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;19167:6:0;;-1:-1:-1;19175:9:0;;-1:-1:-1;19186:9:0;;-1:-1:-1;19112:11:0;:84::i;:::-;19093:103;;19215:51;19240:7;19249:6;19257:8;19215:24;:51::i;:::-;19207:85;;;;;;;-1:-1:-1;;;;;;;;;;;19207:85:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;19311:35;19330:7;19340:5;;19311:35;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;19311:10:0;;-1:-1:-1;;;19311:35:0:i;:::-;19303:122;;;;;;-1:-1:-1;;;;;;;;;;;19303:122:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;19436:26;19465:37;19487:7;19496:5;;19465:37;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;19465:21:0;;-1:-1:-1;;;19465:37:0:i;:::-;19436:66;-1:-1:-1;19538:2:0;19517:23;;19516:47;;19513:536;;;19583:63;19596:7;19605:9;19616;19627:18;19583:12;:63::i;:::-;19580:458;;;19670:23;;;:84;;;19697:57;19716:7;19725:5;;19697:57;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;30:3:-1;22:6;14;1:33;99:1;81:16;;74:27;;;;-1:-1;;19697:57:0;;;;137:4:-1;19697:57:0;;;;;;;;;;;;;;;;;19732:8;;-1:-1:-1;19697:57:0;-1:-1:-1;19742:11:0;;;;;;19697:57;;19742:11;;;;19697:57;1:33:-1;99:1;81:16;;74:27;;;;-1:-1;19697:18:0;;-1:-1:-1;;;19697:57:0:i;:::-;19667:356;;;19872:4;-1:-1:-1;;;;;19864:18:0;19883:5;;19864:25;;;;;30:3:-1;22:6;14;1:33;19864:25:0;;45:16:-1;;;-1:-1;19864:25:0;;-1:-1:-1;19864:25:0;;-1:-1:-1;;19864: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;;19851:38:0;;;;;19912:91;19919:7;19939:9;19928:8;:20;19950:9;19961;19972:18;19992:10;19912:6;:91::i;:::-;20064:56;;;;;;;;;;;;-1:-1:-1;;;;;20064:56:0;;;;;;;;;;;;18786:1343;;;;;;;;;;;;;:::o;33365:510::-;33567:7;14616:10;14638:4;14616:27;;:59;;;14647:28;14655:7;14664:10;14647:7;:28::i;:::-;14608:107;;;;;;-1:-1:-1;;;;;;;;;;;14608:107:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;29878:15;;:33;;;;;;-1:-1:-1;;;;;29878:33:0;;;;;;;;;33602:7;;29878:15;;;;;:24;;:33;;;;;;;;;;;;;;;:15;:33;;;5:2:-1;;;;30:1;27;20:12;5:2;29878:33:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;29878:33:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;29878:33:0;29877:34;29869:84;;;;-1:-1:-1;;;;;;;;;;;29869:84:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;33635:32:0;;28367:42;33635:32;33627:74;;;;;-1:-1:-1;;;;;;;;;;;33627:74:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;33766:8;;33712:63;;33729:7;;33738;;33747:17;;-1:-1:-1;;;;;33766:8:0;33712:16;:63::i;:::-;33791:76;;;-1:-1:-1;;;;;33791:76:0;;;;;;;;;;;;;33827:7;;33791:76;;;;;;;;;;;;;14726:1;33365:510;;;;;:::o;30927:675::-;31217:15;31155:7;14616:10;14638:4;14616:27;;:59;;;14647:28;14655:7;14664:10;14647:7;:28::i;:::-;14608:107;;;;;;-1:-1:-1;;;;;;;;;;;14608:107:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;29878:15;;:33;;;;;;-1:-1:-1;;;;;29878:33:0;;;;;;;;;31190:7;;29878:15;;;;;:24;;:33;;;;;;;;;;;;;;;:15;:33;;;5:2:-1;;;;30:1;27;20:12;5:2;29878:33:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;29878:33:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;29878:33:0;29877:34;29869:84;;;;-1:-1:-1;;;;;;;;;;;29869:84:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;31258:32:0;;28367:42;31258:32;31250:74;;;;;-1:-1:-1;;;;;;;;;;;31250:74:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;31357:8;;;;;;;;;-1:-1:-1;;;;;31357:8:0;-1:-1:-1;;;;;31357:12:0;;:14;;;;;-1:-1:-1;;;31357:14:0;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;31357:14:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;31357:14:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;31357:14:0;-1:-1:-1;;;;;31343:28:0;;;;;;31335:70;;;;;-1:-1:-1;;;;;;;;;;;31335:70:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;31475:8;;31426:58;;31434:7;;31443:17;;31462:11;;-1:-1:-1;;;;;31475:8:0;31426:7;:58::i;:::-;31500:94;;;-1:-1:-1;;;;;31500:94:0;;;;;;;;;;;;;;;;;;;;;;;;;;31416:68;;-1:-1:-1;31416:68:0;;31500:94;;;;;;;;;;;;;14726:1;30927:675;;;;;;;;:::o;32500:501::-;32698:7;14616:10;14638:4;14616:27;;:59;;;14647:28;14655:7;14664:10;14647:7;:28::i;:::-;14608:107;;;;;;-1:-1:-1;;;;;;;;;;;14608:107:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;29878:15;;:33;;;;;;-1:-1:-1;;;;;29878:33:0;;;;;;;;;32733:7;;29878:15;;;;;:24;;:33;;;;;;;;;;;;;;;:15;:33;;;5:2:-1;;;;30:1;27;20:12;5:2;29878:33:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;29878:33:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;29878:33:0;29877:34;29869:84;;;;-1:-1:-1;;;;;;;;;;;29869:84:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;32766:32:0;;28367:42;32766:32;32758:74;;;;;-1:-1:-1;;;;;;;;;;;32758:74:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;32894:8;;32843:60;;32857:7;;32866;;32875:17;;-1:-1:-1;;;;;32894:8:0;32843:13;:60::i;:::-;32919:74;;;-1:-1:-1;;;;;32919:74:0;;;;;;;;;;;;;32953:7;;32919:74;;;;;;;;;;;;;14726:1;32500:501;;;;;:::o;16772:49::-;;;;;;;;;;;;;:::o;28096:38::-;;;-1:-1:-1;;;;;28096:38:0;;:::o;35034:479::-;35218:7;14616:10;14638:4;14616:27;;:59;;;14647:28;14655:7;14664:10;14647:7;:28::i;:::-;14608:107;;;;;;-1:-1:-1;;;;;;;;;;;14608:107:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;29878:15;;:33;;;;;;-1:-1:-1;;;;;29878:33:0;;;;;;;;;35253:7;;29878:15;;;;;:24;;:33;;;;;;;;;;;;;;;:15;:33;;;5:2:-1;;;;30:1;27;20:12;5:2;29878:33:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;29878:33:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;29878:33:0;29877:34;29869:84;;;;-1:-1:-1;;;;;;;;;;;29869:84:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;35300:8;;;;;;;;;-1:-1:-1;;;;;35300:8:0;-1:-1:-1;;;;;35300:12:0;;:14;;;;;-1:-1:-1;;;35300:14:0;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;35300:14:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;35300:14:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;35300:14:0;-1:-1:-1;;;;;35286:28:0;;;;;;35278:70;;;;;-1:-1:-1;;;;;;;;;;;35278:70:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;35401:8;;35411:14;;35359:67;;35370:7;;35379;;35388:11;;-1:-1:-1;;;;;35401:8:0;;;;35411:14;35359:10;:67::i;:::-;35442:63;;;-1:-1:-1;;;;;35442:63:0;;;;;;;;;;;;;35472:7;;35442:63;;;;;;;;;;;;;14726:1;35034:479;;;;;:::o;13316:122::-;13375:9;13171:8;13401:23;13405:9;13409:1;13412;13405:3;:9::i;:::-;13422:1;13171:8;13416:7;;13401:3;:23::i;:::-;:29;;;;;;;;;13316:122;-1:-1:-1;;;13316:122:0:o;13570:120::-;13629:9;13681:1;13655:23;13659:11;13663:1;13171:8;13659:3;:11::i;:::-;13676:1;13672;:5;;12117:150;12175:7;12203:6;;;;12195:15;;;;;;-1:-1:-1;12233:5:0;;;12117:150::o;16344:131::-;16419:4;16462:5;-1:-1:-1;;;;;16443:24:0;:7;-1:-1:-1;;;;;16443:13:0;;:15;;;;;-1:-1:-1;;;16443:15:0;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;16443:15:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;16443:15:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;16443:15:0;-1:-1:-1;;;;;16443:24:0;;;16344:131;-1:-1:-1;;;16344:131:0:o;13444:120::-;13503:9;13555:1;13529:23;13533:11;13537:1;13133:8;13533:3;:11::i;39410:299::-;28519:34;;;;;;;;;;;;;;;;39653:47;;;;;;;;;;;;;;;26:21:-1;;;22:32;;;6:49;;39653:47:0;;;;;;;;25:18:-1;;61:17;;-1:-1;;;;;;;;;;;182:15;-1:-1;;;;;;;;;;;39653:47:0;;;179:29:-1;;;;160:49;;;39608:93:0;;39621:7;;39638:9;;39650:1;;39608:12;:93::i;42886:697::-;43156:9;43168:24;43176:4;43182:9;43168:7;:24::i;:::-;43156:36;;43213:1;43206:4;:8;43203:72;;;43216:59;43227:7;43236:4;43242;43248:9;43259:15;43216:10;:59::i;:::-;43322:15;43340:31;43355:4;43361:9;43340:14;:31::i;:::-;43322:49;;43398:1;43385:10;:14;43382:73;;;43401:54;43418:7;43427:4;43433:10;43445:9;43401:16;:54::i;:::-;28689:26;;;;;;;;;;;;;;;;43536:38;;;;;;;;;26:21:-1;;;22:32;;;6:49;;43536:38:0;;;;;;;;25:18:-1;;61:17;;-1:-1;;;;;;;;;;;182:15;-1:-1;;;;;;;;;;;43536:38:0;;;179:29:-1;;;;160:49;;;43491:84:0;;43504:7;;43521:9;;43533:1;;43491:12;:84::i;:::-;42886:697;;;;;;:::o;20982:534::-;21401:94;;21418:10;21401:94;;;;;;;21246:7;21401:94;;;;;;;-1:-1:-1;;;;;21401:94:0;;;;;;;;;;;;;;;;;;;;;;;;21246:7;;;;21439:5;;21446:3;;21451:6;;21459:5;;21466:6;;21474:9;;21485;;21401: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;;21401:94:0;;;;;-1:-1:-1;21401:94:0;;;;;;;-1:-1:-1;21401:94:0;;;;;;;;;;26:21:-1;;;22:32;;6:49;;21401:94:0;;;;;21391:105;;;;;;21303:204;;;;;;;;;;;;;;;26:21:-1;;;22:32;;;6:49;;21303:204:0;;;;;;21279:229;;;;;;20982:534;-1:-1:-1;;;;;;;;;;;;;;20982:534:0:o;27153:175::-;27260:4;27284:36;27304:7;27313:6;27284:19;:36::i;25876:431::-;25955:4;25996:2;25980:5;:12;:18;;25972:53;;;;;;;-1:-1:-1;;;;;;;;;;;25972:53:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;26244:4:0;26233:16;26227:23;-1:-1:-1;;;;;26278:21:0;;;;;;;25876:431::o;27635:130::-;27756:1;27635:130;;;;:::o;25263:363::-;25377:4;25409:1;25397:9;:13;:46;;;;;25442:1;25428:11;:15;25397:46;:159;;;;;25500:9;25489:8;:20;25470:7;-1:-1:-1;;;;;25462:24:0;;:47;:93;;;-1:-1:-1;25513:33:0;;;;;;25540:4;25513:33;;;;;;-1:-1:-1;;;;;25513:18:0;;;;;:33;;;;;;;;;;;;;;:18;:33;;;5:2:-1;;;;30:1;27;20:12;5:2;25513:33:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;25513:33:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;25513:33:0;:42;25462:93;25394:203;;;-1:-1:-1;25580:5:0;25573:12;;25394:203;-1:-1:-1;25614:4:0;25263:363;;;;;;:::o;27336:291::-;27472:4;27489:14;27506:40;27520:9;27531:11;27544:1;27506:13;:40::i;:::-;27489:57;;27564:24;27572:7;27581:6;27564:7;:24::i;:::-;27557:31;27336:291;-1:-1:-1;;;;;;27336:291:0:o;24347:680::-;24503:5;:16;;24486:14;24713:13;;:32;;;;;24744:1;24730:11;:15;24713:32;:55;;;;;24759:9;24749:6;:19;;24713:55;24710:310;;;24800:11;24788:9;:23;24785:173;;;24850:11;24841:20;24785:173;;;24924:18;;24785:173;24972:36;;;;;;-1:-1:-1;;;;;24972:36:0;;;;;;;;;;;;;;;;;;-1:-1:-1;24972:36:0;;;;;;;;:14;;;;;;:36;;;;;;;;;;;-1:-1:-1;24972:14:0;:36;;;5:2:-1;;;;30:1;27;20:12;5:2;24972:36:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;24972:36:0;;;;24347:680;;;;;;;:::o;38833:282::-;39065:42;39073:7;39082:4;39088:7;39097:9;39065:7;:42::i;36987:679::-;37171:12;37256:9;-1:-1:-1;;;;;37256:14:0;;:16;;;;;-1:-1:-1;;;37256:16:0;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;37256:16:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;37256:16:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;37256:16:0;37328:38;;;;;;;;;;;;-1:-1:-1;;;;;37328:38:0;;;;;;;;;37256:16;;-1:-1:-1;37328:14:0;;;;;;:38;;;;;-1:-1:-1;;37328:38:0;;;;;;;;-1:-1:-1;37328:14:0;:38;;;5:2:-1;;;;30:1;27;20:12;5:2;37328:38:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;37328:38:0;;;;37430:50;37438:7;37447:4;37453:15;37470:9;37430:7;:50::i;:::-;37535:1;37524:8;:12;37521:138;;;28519:34;;;;;;;;;;;;;;;;37598:48;;;;;;;;;;;;;;;26:21:-1;;;22:32;;;6:49;;37598:48:0;;;;;;;;25:18:-1;;61:17;;-1:-1;;;;;;;;;;;182:15;-1:-1;;;;;;;;;;;37598:48:0;;;179:29:-1;;;;160:49;;;37553:94:0;;37566:7;;37583:9;;37595:1;;37553:12;:94::i;38138:400::-;38381:9;-1:-1:-1;;;;;38381:13:0;;38395:4;38381:19;;;;;-1:-1:-1;;;38381:19:0;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;38381:19:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;38381:19:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;38381:19:0;-1:-1:-1;;;;;38361:39:0;;;;;;38353:69;;;;;-1:-1:-1;;;;;;;;;;;38353:69:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;38486:42;38494:7;38503:4;38509:7;38518:9;38486:7;:42::i;40342:2165::-;40623:9;-1:-1:-1;;;;;40623:13:0;;40637:4;40623:19;;;;;-1:-1:-1;;;40623:19:0;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;40623:19:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;40623:19:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;40623:19:0;-1:-1:-1;;;;;40603:39:0;;;;;;40595:69;;;;;-1:-1:-1;;;;;;;;;;;40595:69:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;40713:14;40730:44;40749:4;40755:7;40764:9;40730:18;:44::i;:::-;40713:61;;40813:16;40832:9;-1:-1:-1;;;;;40832:13:0;;:15;;;;;-1:-1:-1;;;40832:15:0;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;40832:15:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;40832:15:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;40832:15:0;40879:43;;;;;;-1:-1:-1;;;;;40879:43:0;;;;;;;;;40832:15;;-1:-1:-1;40858:18:0;;40879:25;;;;;;:43;;;;;40832:15;;40879:43;;;;;;;;:25;:43;;;5:2:-1;;;;30:1;27;20:12;5:2;40879:43:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;40879:43:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;40879:43:0;;-1:-1:-1;40937:19:0;;;40933:447;;;41046:18;41067:15;-1:-1:-1;;;;;41067:27:0;;41095:8;41067:37;;;;;-1:-1:-1;;;41067:37:0;;;;;;;-1:-1:-1;;;;;41067:37:0;-1:-1:-1;;;;;41067:37:0;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;41067:37:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;41067:37:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;41067:37:0;41145:73;;;;;;41198:19;;;41145:73;;;;;;41067:37;;-1:-1:-1;41119:23:0;;-1:-1:-1;;;;;41145:52:0;;;;;:73;;;;;41067:37;;41145:73;;;;;;;:52;:73;;;5:2:-1;;;;30:1;27;20:12;5:2;41145:73:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;41145:73:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;41145:73:0;29359:50;;41145:73;;-1:-1:-1;41233:135:0;;41246:7;;41255:10;;41145:73;;29359:50;;;;;;;;;;;;;;;;41330:19;;;41284:83;;;;41351:15;41284:83;;;;;;;;;;26:21:-1;;;22:32;;;6:49;;41284:83:0;;;;;;;;25:18:-1;;61:17;;-1:-1;;;;;;;;;;;182:15;-1:-1;;;;;;;;;;;41284:83:0;;;179:29:-1;;;;160:49;;41284:83:0;-1:-1:-1;41233:12:0;:135::i;:::-;40933:447;;;41428:16;41446:9;-1:-1:-1;;;;;41446:13:0;;:15;;;;;-1:-1:-1;;;41446:15:0;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;41446:15:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;41446:15:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;41446:15:0;41493:43;;;;;;-1:-1:-1;;;;;41493:43:0;;;;;;;;;41446:15;;-1:-1:-1;41472:18:0;;41493:25;;;;;;:43;;;;;41446:15;;41493:43;;;;;;;;:25;:43;;;5:2:-1;;;;30:1;27;20:12;5:2;41493:43:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;41493:43:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;41493:43:0;;-1:-1:-1;41551:20:0;;;41547:450;;;41661:18;41682:15;-1:-1:-1;;;;;41682:27:0;;41710:8;41682:37;;;;;-1:-1:-1;;;41682:37:0;;;;;;;-1:-1:-1;;;;;41682:37:0;-1:-1:-1;;;;;41682:37:0;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;41682:37:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;41682:37:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;41682:37:0;41760:74;;;;;;41813:20;;;41760:74;;;;;;41682:37;;-1:-1:-1;41734:23:0;;-1:-1:-1;;;;;41760:52:0;;;;;:74;;;;;41682:37;;41760:74;;;;;;;:52;:74;;;5:2:-1;;;;30:1;27;20:12;5:2;41760:74:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;41760:74:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;41760:74:0;29359:50;;41760:74;;-1:-1:-1;41849:136:0;;41862:7;;41871:10;;41760:74;;29359:50;;;;;;;;;;;;;;;;41956:10;41946:7;:20;41968:15;41900:84;;;;;;;;;;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;41900:84:0;;;;-1:-1:-1;;;;;;;;;;;41900:84:0;;38:4:-1;29:7;25:18;67:10;61:17;-1:-1;;;;;;;;;;;199:8;192:4;186;182:15;179:29;167:10;160:49;0:215;;;41900:84:0;41849:12;:136::i;:::-;41547:450;;;29258:37;;;;;;;;;;;;;;;;-1:-1:-1;;;;;42101:66:0;;;;;;;;;;;;;;;26:21:-1;;;22:32;;;6:49;;42101:66:0;;;;;;;;25:18:-1;;61:17;;-1:-1;;;;;;;;;;;182:15;-1:-1;;;;;;;;;;;42101:66:0;;;179:29:-1;;;;160:49;;;42066:102:0;;42079:7;;42088:8;;42098:1;;42066:12;:102::i;:::-;29258:37;;;;;;;;;;;;;;;;-1:-1:-1;;;;;42279:65:0;;;;;;;;;;;;;;;26:21:-1;;;22:32;;;6:49;;42279:65:0;;;;;;;;25:18:-1;;61:17;;-1:-1;;;;;;;;;;;182:15;-1:-1;;;;;;;;;;;42279:65:0;;;179:29:-1;;;;160:49;;;42244:101:0;;42257:7;;42266:8;;42276:1;;42244:12;:101::i;:::-;28604:34;;;;;;;;;;;;;;;;42451:47;;;;;;;;;;;;;;;26:21:-1;;;22:32;;;6:49;;42451:47:0;;;;;;;;25:18:-1;;61:17;;-1:-1;;;;;;;;;;;182:15;-1:-1;;;;;;;;;;;42451:47:0;;;179:29:-1;;;;160:49;;;42406:93:0;;42419:7;;42436:9;;42448:1;;42406:12;:93::i;:::-;40342:2165;;;;;;;;;;:::o;11141:433::-;11199:7;11443:6;;11439:47;;;-1:-1:-1;11473:1:0;11466:8;;11439:47;11510:5;;;11514:1;11510;:5;11534;;;;;;;;:10;11526:19;;;;;12343:150;12401:7;12433:5;;;12457:6;;;;12449:15;;;;;51499:153;51610:7;-1:-1:-1;;;;;51610:14:0;;51625:3;51630:6;51638:5;51610:34;;;;;-1:-1:-1;;;51610:34:0;;;;;;;-1:-1:-1;;;;;51610:34:0;-1:-1:-1;;;;;51610:34: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;51610:34:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;51610:34:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;51610:34:0;;;;51499:153;;;;:::o;22314:480::-;-1:-1:-1;;;;;22427:25:0;;22397:4;22427:25;;;:7;:25;;;;;:31;22417:41;;22414:85;;-1:-1:-1;22482:5:0;22475:12;;22414:85;45:20:-1;-1:-1;;22534:75:0;;25:41:-1;22644:12:0;16758:5;22644:25;22631:38;;22628:82;;;22693:5;22686:12;;;;;22628:82;-1:-1:-1;;;;;;;22720:25:0;;;;;;:7;:25;;;;;;;;:40;;;22314:480;;;;:::o;23068:801::-;23597:4;23593:16;;;23567:44;;23588:4;23567:44;;23561:51;23658:4;23637:44;;23631:51;23711:44;;;;23705:51;23174:7;;23758:4;23701:62;;;;;23797:2;23792:7;;;:18;;;23803:1;:7;;23808:2;23803:7;23792:18;23784:27;;;;;;;;23830:31;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;23830:31:0;;;;;;;;;;;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;23830:31:0;;-1:-1:-1;;23830:31:0;;;23068:801;-1:-1:-1;;;;;;;;23068:801:0:o;49901:944::-;28928:34;;;;;;;;;;;;;;;;50181:51;;;;;;;;;;;;;;;26:21:-1;;;22:32;;;6:49;;50181:51:0;;;;;;;;25:18:-1;;61:17;;-1:-1;;;;;;;;;;;182:15;-1:-1;;;;;;;;;;;50181:51:0;;;179:29:-1;;;;160:49;;;50136:97:0;;50149:7;;50166:9;;50178:1;;50136:12;:97::i;:::-;50281:17;50301:9;-1:-1:-1;;;;;50301:13:0;;:15;;;;;-1:-1:-1;;;50301:15:0;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;50301:15:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;50301:15:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;50301:15:0;50347;;;;;;;;50301;;-1:-1:-1;50327:17:0;;-1:-1:-1;;;;;50347:13:0;;;;;:15;;;;;50301;;50347;;;;;;;:13;:15;;;5:2:-1;;;;30:1;27;20:12;5:2;50347:15:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;50347:15:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;50347:15:0;29258:37;;;;;;;;;;;;;;;;-1:-1:-1;;;;;50434:70:0;;;;;;;;;;;;;;;26:21:-1;;;22:32;;;6:49;;50434:70:0;;;;;;;50347:15;25:18:-1;;61:17;;-1:-1;;;;;;;;;;;182:15;-1:-1;;;;;;;;;;;50434:70:0;;;179:29:-1;;;;160:49;;;50347:15:0;;-1:-1:-1;50398:107:0;;50411:7;;50347:15;;50431:1;;50398:12;:107::i;:::-;29013:26;;;;;;;;;;;;;;;;50586:45;;;;;;;;;26:21:-1;;;22:32;;;6:49;;50586:45:0;;;;;;;;25:18:-1;;61:17;;-1:-1;;;;;;;;;;;182:15;-1:-1;;;;;;;;;;;50586:45:0;;;179:29:-1;;;;160:49;;;50541:91:0;;50554:7;;50571:9;;50583:1;;50541:12;:91::i;:::-;50674:14;50691:9;-1:-1:-1;;;;;50691:13:0;;50705:11;50691:26;;;;;-1:-1:-1;;;50691:26:0;;;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;50691:26:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;50691:26:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;50691:26:0;29172:30;;;;;;;;;;;;;;;;50788:48;;;;;;;;;26:21:-1;;;22:32;;;6:49;;50788:48:0;;;;;;;50691:26;25:18:-1;;61:17;;-1:-1;;;;;;;;;;;182:15;-1:-1;;;;;;;;;;;50788:48:0;;;179:29:-1;;;;160:49;;;50691:26:0;;-1:-1:-1;50752:85:0;;50765:7;;50774:9;;50785:1;;50752:12;:85::i;48526:1084::-;48734:17;48754:9;-1:-1:-1;;;;;48754:13:0;;:15;;;;;-1:-1:-1;;;48754:15:0;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;48754:15:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;48754:15:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;48754:15:0;48828:26;;;;;;;;;;;;;;48754:15;;-1:-1:-1;48811:14:0;;-1:-1:-1;;;;;48828:13:0;;;;;:26;;;;;48754:15;;48828:26;;;;;;;:13;:26;;;5:2:-1;;;;30:1;27;20:12;5:2;48828:26:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;48828:26:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;48828:26:0;29094:22;;;;;;;;;;;;;;;;22:32:-1;6:49;;48933:36:0;;;;;;48828:26;25:18:-1;;61:17;;-1:-1;;;;;;;;;;;182:15;-1:-1;;;;;;;;;;;48933:36:0;;;179:29:-1;;;;160:49;;;48828:26:0;;-1:-1:-1;48889:81:0;;48902:7;;48911:9;;48828:26;;48889:12;:81::i;:::-;29258:37;;;;;;;;;;;;;;;;-1:-1:-1;;;;;49042:68:0;;;;;;;;;;;;;;;26:21:-1;;;22:32;;;6:49;;49042:68:0;;;;;;;;25:18:-1;;61:17;;-1:-1;;;;;;;;;;;182:15;-1:-1;;;;;;;;;;;49042:68:0;;;179:29:-1;;;;160:49;;;49006:105:0;;49019:7;;49028:9;;49039:1;;49006:12;:105::i;:::-;28766:26;;;;;;;;;;;;;;;;49192:45;;;;;;;;;26:21:-1;;;22:32;;;6:49;;49192:45:0;;;;;;;;25:18:-1;;61:17;;-1:-1;;;;;;;;;;;182:15;-1:-1;;;;;;;;;;;49192:45:0;;;179:29:-1;;;;160:49;;;49147:91:0;;49160:7;;49177:9;;49189:1;;49147:12;:91::i;:::-;49285:17;49305:9;-1:-1:-1;;;;;49305:13:0;;:15;;;;;-1:-1:-1;;;49305:15:0;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;49305:15:0;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;49305:15:0;;;;;;;13:2:-1;8:3;5:11;2:2;;;29:1;26;19:12;2:2;-1:-1;49305:15:0;29258:37;;;;;;;;;;;;;;;;-1:-1:-1;;;;;49392:70:0;;;;;;;;;;;;;;;26:21:-1;;;22:32;;;6:49;;49392:70:0;;;;;;;49305:15;25:18:-1;;61:17;;-1:-1;;;;;;;;;;;182:15;-1:-1;;;;;;;;;;;49392:70:0;;;179:29:-1;;;;160:49;;;49305:15:0;;-1:-1:-1;49356:107:0;;49369:7;;49305:15;;49389:1;;49356:12;:107::i;:::-;28843:34;;;;;;;;;;;;;;;;49550:51;;;;;;;;;;;;;;;26:21:-1;;;22:32;;;6:49;;49550:51:0;;;;;;;;25:18:-1;;61:17;;-1:-1;;;;;;;;;;;182:15;-1:-1;;;;;;;;;;;49550:51:0;;;179:29:-1;;;;160:49;;;49505:97:0;;49518:7;;49535:9;;49547:1;;49505:12;:97::i

Swarm Source

bzzr://3bf4bedfff4a0e165cdef420704ae6d0f63199fb310cca443144b76dcd0d0272

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading
[ Download: CSV Export  ]

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.