ETH Price: $3,450.29 (-1.89%)
Gas: 2 Gwei

Contract

0xB0F720Baa5BD1715897d4790A59f5c7aa1377D79
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Swap Exact ETH F...193283732024-02-28 20:20:59145 days ago1709151659IN
Materia: Orchestrator
0.2 ETH0.0096654254.55973569
Remove Liquidity...189729032024-01-10 0:13:11195 days ago1704845591IN
Materia: Orchestrator
0 ETH0.0034949217.7997418
Swap Exact ETH F...187573972023-12-10 17:47:47225 days ago1702230467IN
Materia: Orchestrator
0.0005 ETH0.0200457963.11190965
Swap ETH For Exa...166689762023-02-20 9:49:59518 days ago1676886599IN
Materia: Orchestrator
0.02934291 ETH0.0043729521.67469546
Swap Exact ETH F...166072172023-02-11 18:09:59527 days ago1676138999IN
Materia: Orchestrator
0.1 ETH0.0037775719.44668798
Swap Exact Token...165747492023-02-07 5:13:47532 days ago1675746827IN
Materia: Orchestrator
0 ETH0.0077445723.15967791
Swap Exact Token...165747442023-02-07 5:12:47532 days ago1675746767IN
Materia: Orchestrator
0 ETH0.0079472223.76398371
Swap Exact ETH F...162184492022-12-19 11:29:59581 days ago1671449399IN
Materia: Orchestrator
0.03680093 ETH0.0031931612.89679509
Swap Exact ETH F...162184412022-12-19 11:28:23581 days ago1671449303IN
Materia: Orchestrator
0.01976732 ETH0.0031990612.08589007
Swap Exact ETH F...160144572022-11-20 23:18:23610 days ago1668986303IN
Materia: Orchestrator
0.5 ETH0.0019192810.83331108
Swap Exact ETH F...155399422022-09-15 15:19:23676 days ago1663255163IN
Materia: Orchestrator
0.3 ETH0.006892738.90819972
Swap Exact ETH F...155398802022-09-15 15:06:47676 days ago1663254407IN
Materia: Orchestrator
0.1 ETH0.006893838.91440295
Remove Liquidity...154137782022-08-26 6:24:59696 days ago1661495099IN
Materia: Orchestrator
0 ETH0.001760936.79859504
Remove Liquidity...139323252022-01-03 11:56:25931 days ago1641210985IN
Materia: Orchestrator
0 ETH0.0137010264.18937553
Swap Exact Token...137875582021-12-12 2:07:45954 days ago1639274865IN
Materia: Orchestrator
0 ETH0.0172086851.45967862
Swap Exact ETH F...137875052021-12-12 1:55:48954 days ago1639274148IN
Materia: Orchestrator
0.025 ETH0.0203719664.13881028
Swap Exact Token...137812602021-12-11 2:50:07955 days ago1639191007IN
Materia: Orchestrator
0 ETH0.0152662845.00207991
Swap Exact Token...136255682021-11-16 8:29:13979 days ago1637051353IN
Materia: Orchestrator
0 ETH0.04080107122
Remove Liquidity...136119702021-11-14 4:52:14982 days ago1636865534IN
Materia: Orchestrator
0 ETH0.04011373140.08345829
Swap Exact ETH F...134935492021-10-26 14:34:471000 days ago1635258887IN
Materia: Orchestrator
0.18 ETH0.04891678154.00314032
Swap Exact ETH F...134788312021-10-24 7:24:081002 days ago1635060248IN
Materia: Orchestrator
0.15 ETH0.0072168152.77340453
Swap Exact ETH F...134779782021-10-24 4:08:231003 days ago1635048503IN
Materia: Orchestrator
0.05 ETH0.0176612455.60231915
Swap Exact Token...134770112021-10-24 0:28:301003 days ago1635035310IN
Materia: Orchestrator
0 ETH0.0120416552.04523382
Swap Exact ETH F...134769502021-10-24 0:15:521003 days ago1635034552IN
Materia: Orchestrator
0.1 ETH0.0016945555
Swap Exact ETH F...134765682021-10-23 22:40:061003 days ago1635028806IN
Materia: Orchestrator
0.15 ETH0.0216420772.01182151
View all transactions

Latest 25 internal transactions (View All)

Advanced mode:
Parent Transaction Hash Block From To
193284562024-02-28 20:37:35145 days ago1709152655
Materia: Orchestrator
0.19934673 ETH
193284562024-02-28 20:37:35145 days ago1709152655
Materia: Orchestrator
0.19934673 ETH
193283732024-02-28 20:20:59145 days ago1709151659
Materia: Orchestrator
0.2 ETH
190694432024-01-23 12:42:59181 days ago1706013779
Materia: Orchestrator
0.03258203 ETH
190694432024-01-23 12:42:59181 days ago1706013779
Materia: Orchestrator
0.03258203 ETH
189869052024-01-11 23:19:47193 days ago1705015187
Materia: Orchestrator
0.41291681 ETH
189869052024-01-11 23:19:47193 days ago1705015187
Materia: Orchestrator
0.41291681 ETH
189253302024-01-03 7:24:35201 days ago1704266675
Materia: Orchestrator
0.05036216 ETH
189253302024-01-03 7:24:35201 days ago1704266675
Materia: Orchestrator
0.05036216 ETH
187573972023-12-10 17:47:47225 days ago1702230467
Materia: Orchestrator
0.0005 ETH
167678352023-03-06 7:29:35504 days ago1678087775
Materia: Orchestrator
0.05008273 ETH
167678352023-03-06 7:29:35504 days ago1678087775
Materia: Orchestrator
0.05008273 ETH
166798042023-02-21 22:19:59517 days ago1677017999
Materia: Orchestrator
0.02902787 ETH
166798042023-02-21 22:19:59517 days ago1677017999
Materia: Orchestrator
0.02902787 ETH
166689762023-02-20 9:49:59518 days ago1676886599
Materia: Orchestrator
0.00014598 ETH
166689762023-02-20 9:49:59518 days ago1676886599
Materia: Orchestrator
0.02919692 ETH
166073212023-02-11 18:30:59527 days ago1676140259
Materia: Orchestrator
0.09946462 ETH
166073212023-02-11 18:30:59527 days ago1676140259
Materia: Orchestrator
0.09946462 ETH
166072172023-02-11 18:09:59527 days ago1676138999
Materia: Orchestrator
0.1 ETH
165747492023-02-07 5:13:47532 days ago1675746827
Materia: Orchestrator
0.01905538 ETH
165747492023-02-07 5:13:47532 days ago1675746827
Materia: Orchestrator
0.01905538 ETH
165747442023-02-07 5:12:47532 days ago1675746767
Materia: Orchestrator
0.01358931 ETH
165747442023-02-07 5:12:47532 days ago1675746767
Materia: Orchestrator
0.01358931 ETH
165704972023-02-06 14:59:23532 days ago1675695563
Materia: Orchestrator
0.18372162 ETH
165704972023-02-06 14:59:23532 days ago1675695563
Materia: Orchestrator
0.18372162 ETH
View All Internal Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
MateriaOrchestrator

Compiler Version
v0.8.0+commit.c7dfd78e

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, GNU GPLv3 license

Contract Source Code (Solidity Multiple files format)

File 1 of 35: MateriaOrchestrator.sol
// SPDX-License-Identifier: GPL3

pragma solidity 0.8.0;

import './IMVDFunctionalitiesManager.sol';
import './IDoubleProxy.sol';
import './IMVDProxy.sol';

import './IMateriaOrchestrator.sol';
import './IMateriaFactory.sol';

import './IEthItemInteroperableInterface.sol';
import './IERC20WrapperV1.sol';

import './MateriaLibrary.sol';
import './TransferHelper.sol';

abstract contract Proxy {
    function _delegate(address implementation) internal virtual {
        assembly {
            calldatacopy(0, 0, calldatasize())
            let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)
            returndatacopy(0, 0, returndatasize())
            switch result
                case 0 {
                    revert(0, returndatasize())
                }
                default {
                    return(0, returndatasize())
                }
        }
    }
}

contract MateriaOrchestrator is Proxy, IMateriaOrchestrator {
    IDoubleProxy public override doubleProxy;

    address public override swapper;
    address public override liquidityAdder;
    address public override liquidityRemover;

    IMateriaFactory public override factory;
    IERC20WrapperV1 public override erc20Wrapper;
    IERC20 public override bridgeToken;
    uint256 public override ETHEREUM_OBJECT_ID;

    constructor(
        address initialFactory,
        address initialBridgeToken,
        address initialErc20Wrapper,
        address initialDoubleProxy,
        address initialLiquidityAdder,
        address initialLiquidityRemover,
        address initialSwapper
    ) {
        factory = IMateriaFactory(initialFactory);
        bridgeToken = IERC20(initialBridgeToken);
        erc20Wrapper = IERC20WrapperV1(initialErc20Wrapper);
        ETHEREUM_OBJECT_ID = uint256(keccak256(bytes('THE ETHEREUM OBJECT IT')));
        doubleProxy = IDoubleProxy(initialDoubleProxy);
        liquidityAdder = initialLiquidityAdder;
        liquidityRemover = initialLiquidityRemover;
        swapper = initialSwapper;
    }

    function setDoubleProxy(address newDoubleProxy) external override onlyDFO {
        doubleProxy = IDoubleProxy(newDoubleProxy);
    }

    function setBridgeToken(address newBridgeToken) external override onlyDFO {
        bridgeToken = IERC20(newBridgeToken);
    }

    function setErc20Wrapper(address newErc20Wrapper) external override onlyDFO {
        erc20Wrapper = IERC20WrapperV1(newErc20Wrapper);
    }

    function setFactory(address newFactory) external override onlyDFO {
        factory = IMateriaFactory(newFactory);
    }

    function setEthereumObjectId(uint256 newEthereumObjectId) external override onlyDFO {
        ETHEREUM_OBJECT_ID = newEthereumObjectId;
    }

    function setSwapper(address _swapper) external override onlyDFO {
        swapper = _swapper;
    }

    function setLiquidityAdder(address _adder) external override onlyDFO {
        liquidityAdder = _adder;
    }

    function setLiquidityRemover(address _remover) external override onlyDFO {
        liquidityRemover = _remover;
    }

    function retire(address newOrchestrator) external override onlyDFO {
        factory.transferOwnership(newOrchestrator);
    }

    function setFees(
        address token,
        uint256 materiaFee,
        uint256 swapFee
    ) external override onlyDFO {
        factory.setFees(MateriaLibrary.pairFor(address(factory), address(bridgeToken), token), materiaFee, swapFee);
    }

    function setDefaultFees(uint256 materiaFee, uint256 swapFee) external override onlyDFO {
        factory.setDefaultMateriaFee(materiaFee);
        factory.setDefaultSwapFee(swapFee);
    }

    function setFeeTo(address feeTo) external override onlyDFO {
        factory.setFeeTo(feeTo);
    }

    //better be safe than sorry
    function getCrumbs(
        address token,
        uint256 amount,
        address receiver
    ) external override onlyDFO {
        TransferHelper.safeTransfer(token, receiver, amount);
    }

    modifier onlyDFO() {
        require(IMVDFunctionalitiesManager(IMVDProxy(doubleProxy.proxy()).getMVDFunctionalitiesManagerAddress()).isAuthorizedFunctionality(msg.sender), "Unauthorized");
        _;
    }

    receive() external payable {
        require(msg.sender == address(erc20Wrapper), 'Only EthItem can send ETH to this contract');
    }

    /**
     * As ERC1155 receiver Materia Orchestrator implements onERC1155Received and onERC1155BatchReceived.
     * onERC1155Received exposes the delegate call to the Liquidity Adder, Remover Liquidity and to the Swapper contracts.
     * Calling with a callback you will be able to specify the operation needed.
     * onERC1155BatchReceived will be implemented with batch/lego operation.
     */

    function onERC1155Received(
        address,
        address,
        uint256,
        uint256,
        bytes calldata payload
    ) external override returns (bytes4) {
        (uint256 operation, ) = abi.decode(payload, (uint256, bytes));
        if (operation == 1) {
            //Adding liquidity
            _delegate(liquidityAdder);
        } else if (operation == 2 || operation == 3 || operation == 4 || operation == 5) {
            //Remove liquidity
            _delegate(swapper); //Swapping
        } else {
            revert();
        }

        return this.onERC1155Received.selector;
    }

    function onERC1155BatchReceived(
        address,
        address,
        uint256[] calldata,
        uint256[] calldata,
        bytes calldata
    ) external pure override returns (bytes4) {
        revert();
    }

    /**
     * Liquidity adding methods are exposed to call the Liquidity Adder contract via a secure channel such as the Orchestrator.
     * Both addLiquidity and addLiquidityETH methods are provided. addLiquidity can be used for ERC20 and ITEMs.
     */

    function addLiquidity(
        address token,
        uint256 tokenAmountDesired,
        uint256 bridgeAmountDesired,
        uint256 tokenAmountMin,
        uint256 bridgeAmountMin,
        address to,
        uint256 deadline
    )
        external
        override
        returns (
            uint256 amountA,
            uint256 amountB,
            uint256 liquidity
        )
    {
        _delegate(liquidityAdder);
    }

    function addLiquidityETH(
        uint256 bridgeAmountDesired,
        uint256 EthAmountMin,
        uint256 bridgeAmountMin,
        address to,
        uint256 deadline
    )
        external
        payable
        override
        returns (
            uint256 amountToken,
            uint256 amountETH,
            uint256 liquidity
        )
    {
        _delegate(liquidityAdder);
    }

    /**
     * Liquidity removing methods are exposed to call the Liquidity Remover contract via a secure channel such as the Orchestrator.
     * The following methods are provided:
     * removeLiquidity, removeLiquidityETH, removeLiquidityWithPermit and removeLiquidityETHWithPermit
     */

    function removeLiquidity(
        address token,
        uint256 liquidity,
        uint256 tokenAmountMin,
        uint256 bridgeAmountMin,
        address to,
        uint256 deadline
    ) public override {
        _delegate(liquidityRemover);
    }

    function removeLiquidityETH(
        uint256 liquidity,
        uint256 bridgeAmountMin,
        uint256 EthAmountMin,
        address to,
        uint256 deadline
    ) public override {
        _delegate(liquidityRemover);
    }

    function removeLiquidityWithPermit(
        address token,
        uint256 liquidity,
        uint256 tokenAmountMin,
        uint256 bridgeAmountMin,
        address to,
        uint256 deadline,
        bool approveMax,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) public override {
        _delegate(liquidityRemover);
    }

    function removeLiquidityETHWithPermit(
        uint256 liquidity,
        uint256 tokenAmountMin,
        uint256 bridgeAmountMin,
        address to,
        uint256 deadline,
        bool approveMax,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) public override {
        _delegate(liquidityRemover);
    }

    /**
     * Swapping methods are exposed to call the Swapper Operator contract via a secure channel such as the Orchestrator.
     * The following methods are provided:
     * swapExactTokensForTokens, swapTokensForExactTokens, swapExactETHForTokens, swapTokensForExactETH, swapExactTokensForETH and swapETHForExactTokens
     */
    function swapExactTokensForTokens(
        uint256 amountIn,
        uint256 amountOutMin,
        address[] memory path,
        address to,
        uint256 deadline
    ) public override returns (uint256[] memory amounts) {
        _delegate(swapper);
    }

    function swapTokensForExactTokens(
        uint256 amountOut,
        uint256 amountInMax,
        address[] memory path,
        address to,
        uint256 deadline
    ) public override returns (uint256[] memory amounts) {
        _delegate(swapper);
    }

    function swapExactETHForTokens(
        uint256 amountOutMin,
        address[] memory path,
        address to,
        uint256 deadline
    ) public payable override {
        _delegate(swapper);
    }

    function swapTokensForExactETH(
        uint256 amountOut,
        uint256 amountInMax,
        address[] memory path,
        address to,
        uint256 deadline
    ) public override {
        _delegate(swapper);
    }

    function swapExactTokensForETH(
        uint256 amountIn,
        uint256 amountOutMin,
        address[] memory path,
        address to,
        uint256 deadline
    ) public override {
        _delegate(swapper);
    }

    function swapETHForExactTokens(
        uint256 amountOut,
        address[] memory path,
        address to,
        uint256 deadline
    ) public payable override {
        _delegate(swapper);
    }

    /**
     * Methods are exposed for the UI to retrive useful information such as quote, getAmountOut, getAmountIn, getAmountsOut, getAmountsIn
     */
    function quote(
        uint256 amountA,
        uint256 reserveA,
        uint256 reserveB
    ) public pure override returns (uint256 amountB) {
        return MateriaLibrary.quote(amountA, reserveA, reserveB);
    }

    function getAmountOut(
        uint256 amountIn,
        uint256 reserveIn,
        uint256 reserveOut
    ) public pure override returns (uint256 amountOut) {
        return MateriaLibrary.getAmountOut(amountIn, reserveIn, reserveOut);
    }

    function getAmountIn(
        uint256 amountOut,
        uint256 reserveIn,
        uint256 reserveOut
    ) public pure override returns (uint256 amountIn) {
        return MateriaLibrary.getAmountIn(amountOut, reserveIn, reserveOut);
    }

    function getAmountsOut(uint256 amountIn, address[] memory path)
        public
        view
        override
        returns (uint256[] memory amounts)
    {
        return MateriaLibrary.getAmountsOut(address(factory), amountIn, path);
    }

    function getAmountsIn(uint256 amountOut, address[] memory path)
        public
        view
        override
        returns (uint256[] memory amounts)
    {
        return MateriaLibrary.getAmountsIn(address(factory), amountOut, path);
    }

    /**
     * isEthItem is a custom implementation to check whether a token is an ITEM or a standard ERC20.
     */

    function isEthItem(address token)
        public
        view
        override
        returns (
            address collection,
            bool ethItem,
            uint256 itemId
        )
    {
        if (token == address(0)) {
            return (address(0), false, 0);
        } else {
            try IEthItemInteroperableInterface(token).mainInterface() returns (address mainInterface) {
                return (mainInterface, true, IEthItemInteroperableInterface(token).objectId());
            } catch {
                return (address(0), false, 0);
            }
        }
    }
}

File 2 of 35: IBaseTokenData.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.8.0;

interface IBaseTokenData {
    function name() external view returns (string memory);

    function symbol() external view returns (string memory);
}

File 3 of 35: IDoubleProxy.sol
// SPDX-License-Identifier: GPL3

pragma solidity =0.8.0;

interface IDoubleProxy {
    function init(address[] calldata proxyList, address currentProxy) external;

    function proxy() external view returns (address);

    function setProxy() external;

    function isProxy(address) external view returns (bool);

    function proxiesLength() external view returns (uint256);

    function proxies(uint256 start, uint256 offset) external view returns (address[] memory);

    function proxies() external view returns (address[] memory);
}

File 4 of 35: IERC1155.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.0;

import "./IERC165.sol";

/**
 * @dev Required interface of an ERC1155 compliant contract, as defined in the
 * https://eips.ethereum.org/EIPS/eip-1155[EIP].
 *
 * _Available since v3.1._
 */
interface IERC1155 is IERC165 {
    /**
     * @dev Emitted when `value` tokens of token type `id` are transferred from `from` to `to` by `operator`.
     */
    event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);

    /**
     * @dev Equivalent to multiple {TransferSingle} events, where `operator`, `from` and `to` are the same for all
     * transfers.
     */
    event TransferBatch(address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] values);

    /**
     * @dev Emitted when `account` grants or revokes permission to `operator` to transfer their tokens, according to
     * `approved`.
     */
    event ApprovalForAll(address indexed account, address indexed operator, bool approved);

    /**
     * @dev Emitted when the URI for token type `id` changes to `value`, if it is a non-programmatic URI.
     *
     * If an {URI} event was emitted for `id`, the standard
     * https://eips.ethereum.org/EIPS/eip-1155#metadata-extensions[guarantees] that `value` will equal the value
     * returned by {IERC1155MetadataURI-uri}.
     */
    event URI(string value, uint256 indexed id);

    /**
     * @dev Returns the amount of tokens of token type `id` owned by `account`.
     *
     * Requirements:
     *
     * - `account` cannot be the zero address.
     */
    function balanceOf(address account, uint256 id) external view returns (uint256);

    /**
     * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {balanceOf}.
     *
     * Requirements:
     *
     * - `accounts` and `ids` must have the same length.
     */
    function balanceOfBatch(address[] calldata accounts, uint256[] calldata ids) external view returns (uint256[] memory);

    /**
     * @dev Grants or revokes permission to `operator` to transfer the caller's tokens, according to `approved`,
     *
     * Emits an {ApprovalForAll} event.
     *
     * Requirements:
     *
     * - `operator` cannot be the caller.
     */
    function setApprovalForAll(address operator, bool approved) external;

    /**
     * @dev Returns true if `operator` is approved to transfer ``account``'s tokens.
     *
     * See {setApprovalForAll}.
     */
    function isApprovedForAll(address account, address operator) external view returns (bool);

    /**
     * @dev Transfers `amount` tokens of token type `id` from `from` to `to`.
     *
     * Emits a {TransferSingle} event.
     *
     * Requirements:
     *
     * - `to` cannot be the zero address.
     * - If the caller is not `from`, it must be have been approved to spend ``from``'s tokens via {setApprovalForAll}.
     * - `from` must have a balance of tokens of type `id` of at least `amount`.
     * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155Received} and return the
     * acceptance magic value.
     */
    function safeTransferFrom(address from, address to, uint256 id, uint256 amount, bytes calldata data) external;

    /**
     * @dev xref:ROOT:erc1155.adoc#batch-operations[Batched] version of {safeTransferFrom}.
     *
     * Emits a {TransferBatch} event.
     *
     * Requirements:
     *
     * - `ids` and `amounts` must have the same length.
     * - If `to` refers to a smart contract, it must implement {IERC1155Receiver-onERC1155BatchReceived} and return the
     * acceptance magic value.
     */
    function safeBatchTransferFrom(address from, address to, uint256[] calldata ids, uint256[] calldata amounts, bytes calldata data) external;
}

File 5 of 35: IERC1155Receiver.sol
// SPDX-License-Identifier: MIT
pragma solidity 0.8.0;

//import "./IERC165.sol";

/**
 * _Available since v3.1._
 */
interface IERC1155Receiver {//is IERC165 {

    /**
        @dev Handles the receipt of a single ERC1155 token type. This function is
        called at the end of a `safeTransferFrom` after the balance has been updated.
        To accept the transfer, this must return
        `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))`
        (i.e. 0xf23a6e61, or its own function selector).
        @param operator The address which initiated the transfer (i.e. msg.sender)
        @param from The address which previously owned the token
        @param id The ID of the token being transferred
        @param value The amount of tokens being transferred
        @param data Additional data with no specified format
        @return `bytes4(keccak256("onERC1155Received(address,address,uint256,uint256,bytes)"))` if transfer is allowed
    */
    function onERC1155Received(
        address operator,
        address from,
        uint256 id,
        uint256 value,
        bytes calldata data
    )
        external
        returns(bytes4);

    /**
        @dev Handles the receipt of a multiple ERC1155 token types. This function
        is called at the end of a `safeBatchTransferFrom` after the balances have
        been updated. To accept the transfer(s), this must return
        `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))`
        (i.e. 0xbc197c81, or its own function selector).
        @param operator The address which initiated the batch transfer (i.e. msg.sender)
        @param from The address which previously owned the token
        @param ids An array containing ids of each token being transferred (order and length must match values array)
        @param values An array containing amounts of each token being transferred (order and length must match ids array)
        @param data Additional data with no specified format
        @return `bytes4(keccak256("onERC1155BatchReceived(address,address,uint256[],uint256[],bytes)"))` if transfer is allowed
    */
    function onERC1155BatchReceived(
        address operator,
        address from,
        uint256[] calldata ids,
        uint256[] calldata values,
        bytes calldata data
    )
        external
        returns(bytes4);
}

File 6 of 35: IERC1155Views.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.8.0;

/**
 * @title IERC1155Views - An optional utility interface to improve the ERC-1155 Standard.
 * @dev This interface introduces some additional capabilities for ERC-1155 Tokens.
 */
interface IERC1155Views {

    /**
     * @dev Returns the total supply of the given token id
     * @param objectId the id of the token whose availability you want to know 
     */
    function totalSupply(uint256 objectId) external view returns (uint256);

    /**
     * @dev Returns the name of the given token id
     * @param objectId the id of the token whose name you want to know 
     */
    function name(uint256 objectId) external view returns (string memory);

    /**
     * @dev Returns the symbol of the given token id
     * @param objectId the id of the token whose symbol you want to know 
     */
    function symbol(uint256 objectId) external view returns (string memory);

    /**
     * @dev Returns the decimals of the given token id
     * @param objectId the id of the token whose decimals you want to know 
     */
    function decimals(uint256 objectId) external view returns (uint256);

    /**
     * @dev Returns the uri of the given token id
     * @param objectId the id of the token whose uri you want to know 
     */
    function uri(uint256 objectId) external view returns (string memory);
}

File 7 of 35: IERC165.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.8.0;


/**
 * @dev Interface of the ERC165 standard, as defined in the
 * https://eips.ethereum.org/EIPS/eip-165[EIP].
 *
 * Implementers can declare support of contract interfaces, which can then be
 * queried by others ({ERC165Checker}).
 *
 * For an implementation, see {ERC165}.
 */
interface IERC165 {
    /**
     * @dev Returns true if this contract implements the interface defined by
     * `interfaceId`. See the corresponding
     * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
     * to learn more about how these ids are created.
     *
     * This function call must use less than 30 000 gas.
     */
    function supportsInterface(bytes4 interfaceId) external view returns (bool);
}

File 8 of 35: IERC20.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `recipient`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address recipient, uint256 amount) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `sender` to `recipient` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(address sender, address recipient, uint256 amount) external returns (bool);

    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);
}

File 9 of 35: IERC20Data.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.8.0;

import "./IBaseTokenData.sol";
import "./IERC20.sol";

interface IERC20Data is IBaseTokenData, IERC20 {
    function decimals() external view returns (uint256);
}

File 10 of 35: IERC20WrapperV1.sol
//SPDX-License-Identifier: MIT

pragma solidity 0.8.0;

import "./IEthItemModelBase.sol";

/**
 * @title ERC20-Based EthItem, version 1.
 * @dev All the wrapped ERC20 Tokens will be created following this Model.
 * The minting operation can be done by calling the appropriate method given in this interface.
 * The burning operation will send back the original wrapped ERC20 amount.
 * To initalize it, the original 'init(address,string,string)'
 * function of the EthItem Token Standard will be used, but the first address parameter will be the original ERC20 Source Contract to Wrap, and NOT the ERC20Model, which is always taken by the Contract who creates the Wrapper.
 */
interface IERC20WrapperV1 is IEthItemModelBase {

    /**
     * @param objectId the Object Id you want to know info about
     * @return erc20TokenAddress the wrapped ERC20 Token address corresponding to the given objectId
     */
    function source(uint256 objectId) external view returns (address erc20TokenAddress);

     /**
     * @param erc20TokenAddress the wrapped ERC20 Token address you want to know info about
     * @return objectId the id in the collection which correspondes to the given erc20TokenAddress
     */
    function object(address erc20TokenAddress) external view returns (uint256 objectId);

    /**
     * @dev Mint operation.
     * It inhibits and bypasses the original EthItem Token Standard 'mint(uint256,string)'.
     * The logic will execute a transferFrom call to the given erc20TokenAddress to transfer the chosed amount of tokens
     * @param erc20TokenAddress The token address to wrap.
     * @param amount The token amount to wrap
     *
     * @return objectId the id given by this collection to the given erc20TokenAddress. It can be brand new if it is the first time this collection is created. Otherwhise, the firstly-created objectId value will be used.
     * @return wrapperAddress The address ethItemERC20Wrapper generated after the creation of the returned objectId
     */
    function mint(address erc20TokenAddress, uint256 amount) external returns (uint256 objectId, address wrapperAddress);

    function mintETH() external payable returns (uint256 objectId, address wrapperAddress);
}

File 11 of 35: IERC721Receiver.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.8.0;

/**
 * @title ERC721 token receiver interface
 * @dev Interface for any contract that wants to support safeTransfers
 * from ERC721 asset contracts.
 */
interface IERC721Receiver {
    /**
     * @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}
     * by `operator` from `from`, this function is called.
     *
     * It must return its Solidity selector to confirm the token transfer.
     * If any other value is returned or the interface is not implemented by the recipient, the transfer will be reverted.
     *
     * The selector can be obtained in Solidity with `IERC721.onERC721Received.selector`.
     */
    function onERC721Received(address operator, address from, uint256 tokenId, bytes calldata data) external returns (bytes4);
}

File 12 of 35: IEthItemInteroperableInterface.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.8.0;

import "./IERC20.sol";
import "./IERC20Data.sol";

interface IEthItemInteroperableInterface is IERC20, IERC20Data {

    function init(uint256 id, string calldata name, string calldata symbol, uint256 decimals) external;

    function mainInterface() external view returns (address);

    function objectId() external view returns (uint256);

    function mint(address owner, uint256 amount) external;

    function burn(address owner, uint256 amount) external;

    function permitNonce(address sender) external view returns(uint256);

    function permit(address owner, address spender, uint value, uint8 v, bytes32 r, bytes32 s) external;

    function interoperableInterfaceVersion() external pure returns(uint256 ethItemInteroperableInterfaceVersion);
}

File 13 of 35: IEthItemMainInterface.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.8.0;

import "./IERC1155.sol";
import "./IERC1155Receiver.sol";
import "./IERC1155Views.sol";
import "./IEthItemInteroperableInterface.sol";
import "./IBaseTokenData.sol";

interface IEthItemMainInterface is IERC1155, IERC1155Views, IBaseTokenData {

    function init(
        address interfaceModel,
        string calldata name,
        string calldata symbol
    ) external;

    function mainInterfaceVersion() external pure returns(uint256 ethItemInteroperableVersion);

    function toInteroperableInterfaceAmount(uint256 objectId, uint256 ethItemAmount) external view returns (uint256 interoperableInterfaceAmount);

    function toMainInterfaceAmount(uint256 objectId, uint256 erc20WrapperAmount) external view returns (uint256 mainInterfaceAmount);

    function interoperableInterfaceModel() external view returns (address, uint256);

    function asInteroperable(uint256 objectId) external view returns (IEthItemInteroperableInterface);

    function emitTransferSingleEvent(address sender, address from, address to, uint256 objectId, uint256 amount) external;

    function mint(uint256 amount, string calldata partialUri)
        external
        returns (uint256, address);

    function burn(
        uint256 objectId,
        uint256 amount
    ) external;

    function burnBatch(
        uint256[] calldata objectIds,
        uint256[] calldata amounts
    ) external;

    event NewItem(uint256 indexed objectId, address indexed tokenAddress);
    event Mint(uint256 objectId, address tokenAddress, uint256 amount);
}

File 14 of 35: IEthItemModelBase.sol
//SPDX-License-Identifier: MIT

pragma solidity 0.8.0;

import "./IEthItemMainInterface.sol";

/**
 * @dev This interface contains the commonn data provided by all the EthItem models
 */
interface IEthItemModelBase is IEthItemMainInterface {

    /**
     * @dev Contract Initialization, the caller of this method should be a Contract containing the logic to provide the EthItemERC20WrapperModel to be used to create ERC20-based objectIds
     * @param name the chosen name for this NFT
     * @param symbol the chosen symbol (Ticker) for this NFT
     */
    function init(string calldata name, string calldata symbol) external;

    /**
     * @return modelVersionNumber The version number of the Model, it should be progressive
     */
    function modelVersion() external pure returns(uint256 modelVersionNumber);

    /**
     * @return factoryAddress the address of the Contract which initialized this EthItem
     */
    function factory() external view returns(address factoryAddress);
}

File 15 of 35: IEthItemOrchestrator.sol
//SPDX-License-Identifier: MIT

pragma solidity 0.8.0;

import "./IERC721Receiver.sol";
import "./IERC1155Receiver.sol";



interface IEthItemOrchestrator is IERC721Receiver, IERC1155Receiver {

    function factories() external view returns(address[] memory);

    function factory() external view returns(address);

    function setFactory(address newFactory) external;

    function knowledgeBases() external view returns(address[] memory);

    function knowledgeBase() external view returns(address);

    function setKnowledgeBase(address newKnowledgeBase) external;

    function ENSController() external view returns (address);

    function setENSController(address newEnsController) external;

    function transferENS(address receiver, bytes32 domainNode, uint256 domainId, bool reclaimFirst, bool safeTransferFrom, bytes calldata payload) external;

    /**
     * @dev GET - The DoubleProxy of the DFO linked to this Contract
     */
    function doubleProxy() external view returns (address);

    /**
     * @dev SET - The DoubleProxy of the DFO linked to this Contract
     * It can be done only through a Proposal in the Linked DFO
     * @param newDoubleProxy the new DoubleProxy address
     */
    function setDoubleProxy(address newDoubleProxy) external;

    /**
     * @dev SET - The address of the Smart Contract whose code will serve as a model for all the EthItemERC20Wrappers (please see the eth-item-token-standard for further information).
     * It can be done only through a Proposal in the Linked DFO
     */
    function setEthItemInteroperableInterfaceModel(address ethItemInteroperableInterfaceModelAddress) external;

    /**
     * @dev SET - The address of the Native EthItem model.
     * It can be done only through a Proposal in the Linked DFO
     */
    function setNativeModel(address nativeModelAddress) external;

    /**
     * @dev SET - The address of the ERC1155 NFT-Based EthItem model.
     * It can be done only through a Proposal in the Linked DFO
     */
    function setERC1155WrapperModel(address erc1155WrapperModelAddress) external;

    /**
     * @dev SET - The address of the Smart Contract whose code will serve as a model for all the Wrapped ERC20 EthItems.
     * It can be done only through a Proposal in the Linked DFO
     */
    function setERC20WrapperModel(address erc20WrapperModelAddress) external;

    /**
     * @dev SET - The address of the Smart Contract whose code will serve as a model for all the Wrapped ERC721 EthItems.
     * It can be done only through a Proposal in the Linked DFO
     */
    function setERC721WrapperModel(address erc721WrapperModelAddress) external;

    /**
     * @dev SET - The element useful to calculate the Percentage fee
     * It can be done only through a Proposal in the Linked DFO
     */
    function setMintFeePercentage(uint256 mintFeePercentageNumerator, uint256 mintFeePercentageDenominator) external;

    /**
     * @dev SET - The element useful to calculate the Percentage fee
     * It can be done only through a Proposal in the Linked DFO
     */
    function setBurnFeePercentage(uint256 burnFeePercentageNumerator, uint256 burnFeePercentageDenominator) external;

    function createNative(bytes calldata modelInitPayload, string calldata ens)
        external
        returns (address newNativeAddress, bytes memory modelInitCallResponse);

    function createERC20Wrapper(bytes calldata modelInitPayload)
        external
        returns (address newEthItemAddress, bytes memory modelInitCallResponse);
}

import "./IMVDFunctionalitiesManager.sol";
import "./IMVDProxy.sol";
import "./IDoubleProxy.sol";
import "./IStateHolder.sol";

File 16 of 35: IEthItemOrchestratorDependantElement.sol
//SPDX-License-Identifier: MIT

pragma solidity =0.8.0;

import "./IERC165.sol";

interface IEthItemOrchestratorDependantElement is IERC165 {

    /**
     * @dev GET - The DoubleProxy of the DFO linked to this Contract
     */
    function doubleProxy() external view returns (address);

    /**
     * @dev SET - The DoubleProxy of the DFO linked to this Contract
     * It can be done only by the Factory controller
     * @param newDoubleProxy the new DoubleProxy address
     */
    function setDoubleProxy(address newDoubleProxy) external;

    function isAuthorizedOrchestrator(address operator) external view returns(bool);
}

File 17 of 35: IKnowledgeBase.sol
//SPDX-License-Identifier: MIT
pragma solidity =0.8.0;

pragma solidity 0.8.0;

import "./IEthItemOrchestratorDependantElement.sol";

/**
 * @title IKnowledgeBase
 * @dev This contract represents the Factory Used to deploy all the EthItems, keeping track of them.
 */
interface IKnowledgeBase is IEthItemOrchestratorDependantElement {

    function setERC20Wrapper(address newWrapper) external;

    function erc20Wrappers() external view returns(address[] memory);

    function erc20Wrapper() external view returns(address);

    function setEthItem(address ethItem) external;

    function isEthItem(address ethItem) external view returns(bool);

    function setWrapped(address wrappedAddress, address ethItem) external;

    function wrapper(address wrappedAddress, uint256 version) external view returns (address ethItem);
}

File 18 of 35: IMateriaFactory.sol
// SPDX-License-Identifier: GPL3

interface IMateriaFactory {
    event PairCreated(address indexed token0, address indexed token1, address pair, uint256);

    function feeTo() external view returns (address);

    function getPair(address tokenA, address tokenB) external view returns (address pair);

    function allPairs(uint256) external view returns (address pair);

    function allPairsLength() external view returns (uint256);

    function createPair(address tokenA, address tokenB) external returns (address pair);

    function setFeeTo(address) external;

    function setDefaultMateriaFee(uint256) external;

    function setDefaultSwapFee(uint256) external;

    function transferOwnership(address newOwner) external;

    function setFees(
        address,
        uint256,
        uint256
    ) external;

    function owner() external view returns (address);
}

File 19 of 35: IMateriaLiquidityRemover.sol
// SPDX-License-Identifier: GPL3

pragma solidity ^0.8.0;

/*
    This interface represents a break in the symmetry and should not exist since a
    Materia Operator should be able to receive only ERC1155.
    Nevertheless for the moment che Materia liquidity pool token is not wrapped
    by the orchestrator, and for this reason it cannot be sent to the Materia
    Liquidity Remover as an ERC1155 token.
    In a future realease it may introduced the LP wrap and therefore this interface
    may become useless.
*/

interface IMateriaLiquidityRemover {
    function removeLiquidity(
        address token,
        uint256 liquidity,
        uint256 tokenAmountMin,
        uint256 bridgeAmountMin,
        uint256 deadline
    ) external returns (uint256 amountBridge, uint256 amountToken);
}

File 20 of 35: IMateriaOrchestrator.sol
// SPDX-License-Identifier: GPL3

pragma solidity 0.8.0;

import './IERC1155Receiver.sol';
import './IMateriaFactory.sol';
import './IERC20.sol';
import './IERC20WrapperV1.sol';
import './IDoubleProxy.sol';

interface IMateriaOrchestrator is IERC1155Receiver {
    function setDoubleProxy(address newDoubleProxy) external;

    function setBridgeToken(address newBridgeToken) external;

    function setErc20Wrapper(address newErc20Wrapper) external;

    function setFactory(address newFactory) external;

    function setEthereumObjectId(uint256 newEthereumObjectId) external;

    function setSwapper(address _swapper) external;

    function setLiquidityAdder(address _adder) external;

    function setLiquidityRemover(address _remover) external;

    function retire(address newOrchestrator) external;

    function setFees(
        address token,
        uint256 materiaFee,
        uint256 swapFee
    ) external;

    function setDefaultFees(uint256 materiaFee, uint256 swapFee) external;

    function setFeeTo(address feeTo) external;

    function getCrumbs(
        address token,
        uint256 amount,
        address receiver
    ) external;

    function factory() external view returns (IMateriaFactory);

    function bridgeToken() external view returns (IERC20);

    function erc20Wrapper() external view returns (IERC20WrapperV1);

    function ETHEREUM_OBJECT_ID() external view returns (uint256);

    function swapper() external view returns (address);

    function liquidityAdder() external view returns (address);

    function liquidityRemover() external view returns (address);

    function doubleProxy() external view returns (IDoubleProxy);

    //Liquidity adding

    function addLiquidity(
        address token,
        uint256 tokenAmountDesired,
        uint256 bridgeAmountDesired,
        uint256 tokenAmountMin,
        uint256 bridgeAmountMin,
        address to,
        uint256 deadline
    )
        external
        returns (
            uint256 amountA,
            uint256 amountB,
            uint256 liquidity
        );

    function addLiquidityETH(
        uint256 bridgeAmountDesired,
        uint256 EthAmountMin,
        uint256 bridgeAmountMin,
        address to,
        uint256 deadline
    )
        external
        payable
        returns (
            uint256 amountToken,
            uint256 amountETH,
            uint256 liquidity
        );

    //Liquidity removing

    function removeLiquidity(
        address token,
        uint256 liquidity,
        uint256 tokenAmountMin,
        uint256 bridgeAmountMin,
        address to,
        uint256 deadline
    ) external;

    function removeLiquidityETH(
        uint256 liquidity,
        uint256 bridgeAmountMin,
        uint256 EthAmountMin,
        address to,
        uint256 deadline
    ) external;

    function removeLiquidityWithPermit(
        address token,
        uint256 liquidity,
        uint256 tokenAmountMin,
        uint256 bridgeAmountMin,
        address to,
        uint256 deadline,
        bool approveMax,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external;

    function removeLiquidityETHWithPermit(
        uint256 liquidity,
        uint256 ethAmountMin,
        uint256 bridgeAmountMin,
        address to,
        uint256 deadline,
        bool approveMax,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external;

    //Swapping

    function swapExactTokensForTokens(
        uint256 amountIn,
        uint256 amountOutMin,
        address[] memory path,
        address to,
        uint256 deadline
    ) external returns (uint256[] memory amounts);

    function swapTokensForExactTokens(
        uint256 amountOut,
        uint256 amountInMax,
        address[] memory path,
        address to,
        uint256 deadline
    ) external returns (uint256[] memory amounts);

    function swapExactETHForTokens(
        uint256 amountOutMin,
        address[] memory path,
        address to,
        uint256 deadline
    ) external payable;

    function swapTokensForExactETH(
        uint256 amountOut,
        uint256 amountInMax,
        address[] memory path,
        address to,
        uint256 deadline
    ) external;

    function swapExactTokensForETH(
        uint256 amountIn,
        uint256 amountOutMin,
        address[] memory path,
        address to,
        uint256 deadline
    ) external;

    function swapETHForExactTokens(
        uint256 amountOut,
        address[] memory path,
        address to,
        uint256 deadline
    ) external payable;

    //Materia utilities

    function isEthItem(address token)
        external
        view
        returns (
            address collection,
            bool ethItem,
            uint256 itemId
        );

    function quote(
        uint256 amountA,
        uint256 reserveA,
        uint256 reserveB
    ) external pure returns (uint256 amountB);

    function getAmountOut(
        uint256 amountIn,
        uint256 reserveIn,
        uint256 reserveOut
    ) external pure returns (uint256 amountOut);

    function getAmountIn(
        uint256 amountOut,
        uint256 reserveIn,
        uint256 reserveOut
    ) external pure returns (uint256 amountIn);

    function getAmountsOut(uint256 amountIn, address[] memory path) external view returns (uint256[] memory amounts);

    function getAmountsIn(uint256 amountOut, address[] memory path) external view returns (uint256[] memory amounts);
}

File 21 of 35: IMateriaPair.sol
pragma solidity >=0.5.0;

interface IMateriaPair {
    event Approval(address indexed owner, address indexed spender, uint256 value);
    event Transfer(address indexed from, address indexed to, uint256 value);

    function name() external pure returns (string memory);

    function symbol() external pure returns (string memory);

    function decimals() external pure returns (uint8);

    function totalSupply() external view returns (uint256);

    function balanceOf(address owner) external view returns (uint256);

    function allowance(address owner, address spender) external view returns (uint256);

    function approve(address spender, uint256 value) external returns (bool);

    function transfer(address to, uint256 value) external returns (bool);

    function transferFrom(
        address from,
        address to,
        uint256 value
    ) external returns (bool);

    function DOMAIN_SEPARATOR() external view returns (bytes32);

    function PERMIT_TYPEHASH() external pure returns (bytes32);

    function nonces(address owner) external view returns (uint256);

    function permit(
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external;

    event Mint(address indexed sender, uint256 amount0, uint256 amount1);
    event Burn(address indexed sender, uint256 amount0, uint256 amount1, address indexed to);
    event Swap(
        address indexed sender,
        uint256 amount0In,
        uint256 amount1In,
        uint256 amount0Out,
        uint256 amount1Out,
        address indexed to
    );
    event Sync(uint112 reserve0, uint112 reserve1);

    function MINIMUM_LIQUIDITY() external pure returns (uint256);

    function factory() external view returns (address);

    function token0() external view returns (address);

    function token1() external view returns (address);

    function getReserves()
        external
        view
        returns (
            uint112 reserve0,
            uint112 reserve1,
            uint32 blockTimestampLast
        );

    function price0CumulativeLast() external view returns (uint256);

    function price1CumulativeLast() external view returns (uint256);

    function kLast() external view returns (uint256);

    function mint(address to) external returns (uint256 liquidity);

    function burn(address to) external returns (uint256 amount0, uint256 amount1);

    function swap(
        uint256 amount0Out,
        uint256 amount1Out,
        address to,
        bytes calldata data
    ) external;

    function skim(address to) external;

    function sync() external;

    function initialize(
        address,
        address,
        uint256,
        uint256
    ) external;

    function setMateriaFee(uint256 _materiaFee) external;

    function setSwapFee(uint256 _swapFee) external;

    function materiaFee() external view returns (uint256);

    function swapFee() external view returns (uint256);

    function owner() external view returns (address);

    function renounceOwnership() external;

    function transferOwnership(address newOwner) external;
}

File 22 of 35: IMVDFunctionalitiesManager.sol
// SPDX-License-Identifier: GPL3

pragma solidity =0.8.0;

interface IMVDFunctionalitiesManager {
    function getProxy() external view returns (address);

    function setProxy() external;

    function init(
        address sourceLocation,
        uint256 getMinimumBlockNumberSourceLocationId,
        address getMinimumBlockNumberFunctionalityAddress,
        uint256 getEmergencyMinimumBlockNumberSourceLocationId,
        address getEmergencyMinimumBlockNumberFunctionalityAddress,
        uint256 getEmergencySurveyStakingSourceLocationId,
        address getEmergencySurveyStakingFunctionalityAddress,
        uint256 checkVoteResultSourceLocationId,
        address checkVoteResultFunctionalityAddress
    ) external;

    function addFunctionality(
        string calldata codeName,
        address sourceLocation,
        uint256 sourceLocationId,
        address location,
        bool submitable,
        string calldata methodSignature,
        string calldata returnAbiParametersArray,
        bool isInternal,
        bool needsSender
    ) external;

    function addFunctionality(
        string calldata codeName,
        address sourceLocation,
        uint256 sourceLocationId,
        address location,
        bool submitable,
        string calldata methodSignature,
        string calldata returnAbiParametersArray,
        bool isInternal,
        bool needsSender,
        uint256 position
    ) external;

    function removeFunctionality(string calldata codeName) external returns (bool removed, uint256 position);

    function isValidFunctionality(address functionality) external view returns (bool);

    function isAuthorizedFunctionality(address functionality) external view returns (bool);

    function setCallingContext(address location) external returns (bool);

    function clearCallingContext() external;

    function getFunctionalityData(string calldata codeName)
        external
        view
        returns (
            address,
            uint256,
            string memory,
            address,
            uint256
        );

    function hasFunctionality(string calldata codeName) external view returns (bool);

    function getFunctionalitiesAmount() external view returns (uint256);

    function functionalitiesToJSON() external view returns (string memory);

    function functionalitiesToJSON(uint256 start, uint256 l) external view returns (string memory functionsJSONArray);

    function functionalityNames() external view returns (string memory);

    function functionalityNames(uint256 start, uint256 l) external view returns (string memory functionsJSONArray);

    function functionalityToJSON(string calldata codeName) external view returns (string memory);

    function preConditionCheck(
        string calldata codeName,
        bytes calldata data,
        uint8 submitable,
        address sender,
        uint256 value
    ) external view returns (address location, bytes memory payload);

    function setupFunctionality(address proposalAddress) external returns (bool);
}

File 23 of 35: IMVDProxy.sol
// SPDX-License-Identifier: GPL3

pragma solidity =0.8.0;

interface IMVDProxy {
    function init(
        address votingTokenAddress,
        address functionalityProposalManagerAddress,
        address stateHolderAddress,
        address functionalityModelsManagerAddress,
        address functionalitiesManagerAddress,
        address walletAddress,
        address doubleProxyAddress
    ) external;

    function getDelegates() external view returns (address[] memory);

    function getToken() external view returns (address);

    function getMVDFunctionalityProposalManagerAddress() external view returns (address);

    function getStateHolderAddress() external view returns (address);

    function getMVDFunctionalityModelsManagerAddress() external view returns (address);

    function getMVDFunctionalitiesManagerAddress() external view returns (address);

    function getMVDWalletAddress() external view returns (address);

    function getDoubleProxyAddress() external view returns (address);

    function setDelegate(uint256 position, address newAddress) external returns (address oldAddress);

    function changeProxy(address newAddress, bytes calldata initPayload) external;

    function isValidProposal(address proposal) external view returns (bool);

    function isAuthorizedFunctionality(address functionality) external view returns (bool);

    function newProposal(
        string calldata codeName,
        bool emergency,
        address sourceLocation,
        uint256 sourceLocationId,
        address location,
        bool submitable,
        string calldata methodSignature,
        string calldata returnParametersJSONArray,
        bool isInternal,
        bool needsSender,
        string calldata replaces
    ) external returns (address proposalAddress);

    function startProposal(address proposalAddress) external;

    function disableProposal(address proposalAddress) external;

    function transfer(
        address receiver,
        uint256 value,
        address token
    ) external;

    function transfer721(
        address receiver,
        uint256 tokenId,
        bytes calldata data,
        bool safe,
        address token
    ) external;

    function flushToWallet(
        address tokenAddress,
        bool is721,
        uint256 tokenId
    ) external;

    function setProposal() external;

    function read(string calldata codeName, bytes calldata data) external view returns (bytes memory returnData);

    function submit(string calldata codeName, bytes calldata data) external payable returns (bytes memory returnData);

    function callFromManager(address location, bytes calldata payload) external returns (bool, bytes memory);

    function emitFromManager(
        string calldata codeName,
        address proposal,
        string calldata replaced,
        address replacedSourceLocation,
        uint256 replacedSourceLocationId,
        address location,
        bool submitable,
        string calldata methodSignature,
        bool isInternal,
        bool needsSender,
        address proposalAddress
    ) external;

    function emitEvent(
        string calldata eventSignature,
        bytes calldata firstIndex,
        bytes calldata secondIndex,
        bytes calldata data
    ) external;

    event ProxyChanged(address indexed newAddress);
    event DelegateChanged(uint256 position, address indexed oldAddress, address indexed newAddress);

    event Proposal(address proposal);
    event ProposalCheck(address indexed proposal);
    event ProposalSet(address indexed proposal, bool success);
    event FunctionalitySet(
        string codeName,
        address indexed proposal,
        string replaced,
        address replacedSourceLocation,
        uint256 replacedSourceLocationId,
        address indexed replacedLocation,
        bool replacedWasSubmitable,
        string replacedMethodSignature,
        bool replacedWasInternal,
        bool replacedNeededSender,
        address indexed replacedProposal
    );

    event Event(string indexed key, bytes32 indexed firstIndex, bytes32 indexed secondIndex, bytes data);
}

File 24 of 35: IStateHolder.sol
// SPDX-License-Identifier: GPL3

pragma solidity =0.8.0;

interface IStateHolder {
    function init() external;

    function getProxy() external view returns (address);

    function setProxy() external;

    function toJSON() external view returns (string memory);

    function toJSON(uint256 start, uint256 l) external view returns (string memory);

    function getStateSize() external view returns (uint256);

    function exists(string calldata varName) external view returns (bool);

    function getDataType(string calldata varName) external view returns (string memory dataType);

    function clear(string calldata varName) external returns (string memory oldDataType, bytes memory oldVal);

    function setBytes(string calldata varName, bytes calldata val) external returns (bytes memory);

    function getBytes(string calldata varName) external view returns (bytes memory);

    function setString(string calldata varName, string calldata val) external returns (string memory);

    function getString(string calldata varName) external view returns (string memory);

    function setBool(string calldata varName, bool val) external returns (bool);

    function getBool(string calldata varName) external view returns (bool);

    function getUint256(string calldata varName) external view returns (uint256);

    function setUint256(string calldata varName, uint256 val) external returns (uint256);

    function getAddress(string calldata varName) external view returns (address);

    function setAddress(string calldata varName, address val) external returns (address);
}

File 25 of 35: IWETH.sol
// SPDX-License-Identifier: GPL3

pragma solidity >=0.5.0;

interface IWETH {
    function deposit() external payable;

    function transfer(address to, uint256 value) external returns (bool);

    function withdraw(uint256) external;
}

File 26 of 35: MateriaLibrary.sol
// SPDX-License-Identifier: GPL3

pragma solidity >=0.5.0;

import './IMateriaPair.sol';
import './IMateriaFactory.sol';

import './SafeMath.sol';

library MateriaLibrary {
    using SafeMath for uint256;

    // returns sorted token addresses, used to handle return values from pairs sorted in this order
    function sortTokens(address tokenA, address tokenB) internal pure returns (address token0, address token1) {
        require(tokenA != tokenB, 'MateriaLibrary: IDENTICAL_ADDRESSES');
        (token0, token1) = tokenA < tokenB ? (tokenA, tokenB) : (tokenB, tokenA);
        require(token0 != address(0), 'MateriaLibrary: ZERO_ADDRESS');
    }

    // calculates the CREATE2 address for a pair without making any external calls
    function pairFor(
        address factory,
        address tokenA,
        address tokenB
    ) internal pure returns (address pair) {
        (address token0, address token1) = sortTokens(tokenA, tokenB);
        pair = address(
            uint160(
                uint256(
                    keccak256(
                        abi.encodePacked(
                            hex'ff',
                            factory,
                            keccak256(abi.encodePacked(token0, token1)),
                            hex'1974917c1e01e6369c1b45f631eae6a71d24cb5108c460cc7f0b1c608b3a7c94' // init code hash
                        )
                    )
                )
            )
        );
    }

    // fetches and sorts the reserves for a pair
    function getReserves(
        address factory,
        address tokenA,
        address tokenB
    ) internal view returns (uint256 reserveA, uint256 reserveB) {
        (address token0, ) = sortTokens(tokenA, tokenB);
        (uint256 reserve0, uint256 reserve1, ) = IMateriaPair(pairFor(factory, tokenA, tokenB)).getReserves();
        (reserveA, reserveB) = tokenA == token0 ? (reserve0, reserve1) : (reserve1, reserve0);
    }

    // given some amount of an asset and pair reserves, returns an equivalent amount of the other asset
    function quote(
        uint256 amountA,
        uint256 reserveA,
        uint256 reserveB
    ) internal pure returns (uint256 amountB) {
        require(amountA > 0, 'MateriaLibrary: INSUFFICIENT_AMOUNT');
        require(reserveA > 0 && reserveB > 0, 'MateriaLibrary: INSUFFICIENT_LIQUIDITY');
        amountB = amountA.mul(reserveB) / reserveA;
    }

    // given an input amount of an asset and pair reserves, returns the maximum output amount of the other asset
    function getAmountOut(
        uint256 amountIn,
        uint256 reserveIn,
        uint256 reserveOut
    ) internal pure returns (uint256 amountOut) {
        require(amountIn > 0, 'MateriaLibrary: INSUFFICIENT_INPUT_AMOUNT');
        require(reserveIn > 0 && reserveOut > 0, 'MateriaLibrary: INSUFFICIENT_LIQUIDITY');
        uint256 amountInWithFee = amountIn.mul(997);
        uint256 numerator = amountInWithFee.mul(reserveOut);
        uint256 denominator = reserveIn.mul(1000).add(amountInWithFee);
        amountOut = numerator / denominator;
    }

    // given an output amount of an asset and pair reserves, returns a required input amount of the other asset
    function getAmountIn(
        uint256 amountOut,
        uint256 reserveIn,
        uint256 reserveOut
    ) internal pure returns (uint256 amountIn) {
        require(amountOut > 0, 'MateriaLibrary: INSUFFICIENT_OUTPUT_AMOUNT');
        require(reserveIn > 0 && reserveOut > 0, 'MateriaLibrary: INSUFFICIENT_LIQUIDITY');
        uint256 numerator = reserveIn.mul(amountOut).mul(1000);
        uint256 denominator = reserveOut.sub(amountOut).mul(997);
        amountIn = (numerator / denominator).add(1);
    }

    // performs chained getAmountOut calculations on any number of pairs
    function getAmountsOut(
        address factory,
        uint256 amountIn,
        address[] memory path
    ) internal view returns (uint256[] memory amounts) {
        require(path.length >= 2, 'MateriaLibrary: INVALID_PATH');
        amounts = new uint256[](path.length);
        amounts[0] = amountIn;
        for (uint256 i; i < path.length - 1; i++) {
            (uint256 reserveIn, uint256 reserveOut) = getReserves(factory, path[i], path[i + 1]);
            amounts[i + 1] = getAmountOut(amounts[i], reserveIn, reserveOut);
        }
    }

    // performs chained getAmountIn calculations on any number of pairs
    function getAmountsIn(
        address factory,
        uint256 amountOut,
        address[] memory path
    ) internal view returns (uint256[] memory amounts) {
        require(path.length >= 2, 'MateriaLibrary: INVALID_PATH');
        amounts = new uint256[](path.length);
        amounts[amounts.length - 1] = amountOut;
        for (uint256 i = path.length - 1; i > 0; i--) {
            (uint256 reserveIn, uint256 reserveOut) = getReserves(factory, path[i - 1], path[i]);
            amounts[i - 1] = getAmountIn(amounts[i], reserveIn, reserveOut);
        }
    }
}

File 27 of 35: MateriaLiquidityAdder.sol
// SPDX-License-Identifier: GPL3
pragma solidity 0.8.0;

import './MateriaOperator.sol';
import './IMateriaOrchestrator.sol';
import './IMateriaFactory.sol';
import './IMateriaPair.sol';
import './IERC20.sol';
import './IERC20WrapperV1.sol';

import './MateriaLibrary.sol';
import './TransferHelper.sol';

contract MateriaLiquidityAdder is MateriaOperator {
    function _addLiquidity(
        address tokenA,
        address tokenB,
        uint256 amountADesired,
        uint256 amountBDesired,
        uint256 amountAMin,
        uint256 amountBMin
    ) private returns (uint256 amountA, uint256 amountB) {
        address factory = address(IMateriaOrchestrator(address(this)).factory());

        // create the pair if it doesn't exist yet
        if (IMateriaFactory(factory).getPair(tokenA, tokenB) == address(0)) {
            IMateriaFactory(factory).createPair(tokenA, tokenB);
        }
        (uint256 reserveA, uint256 reserveB) = MateriaLibrary.getReserves(address(factory), tokenA, tokenB);
        if (reserveA == 0 && reserveB == 0) {
            (amountA, amountB) = (amountADesired, amountBDesired);
        } else {
            uint256 amountBOptimal = MateriaLibrary.quote(amountADesired, reserveA, reserveB);
            if (amountBOptimal <= amountBDesired) {
                require(amountBOptimal >= amountBMin, 'INSUFFICIENT_B_AMOUNT');
                (amountA, amountB) = (amountADesired, amountBOptimal);
            } else {
                uint256 amountAOptimal = MateriaLibrary.quote(amountBDesired, reserveB, reserveA);
                assert(amountAOptimal <= amountADesired);
                require(amountAOptimal >= amountAMin, 'INSUFFICIENT_A_AMOUNT');
                (amountA, amountB) = (amountAOptimal, amountBDesired);
            }
        }
    }

    function _doAddLiquidity(
        address token,
        address bridgeToken,
        uint256 tokenAmountDesired,
        uint256 bridgeAmountDesired,
        uint256 tokenAmountMin,
        uint256 bridgeAmountMin,
        address to
    )
        private
        returns (
            uint256 tokenAmount,
            uint256 bridgeAmount,
            uint256 liquidity
        )
    {
        (tokenAmount, bridgeAmount) = _addLiquidity(
            token,
            bridgeToken,
            tokenAmountDesired,
            bridgeAmountDesired,
            tokenAmountMin,
            bridgeAmountMin
        );

        address pair =
            MateriaLibrary.pairFor(address(IMateriaOrchestrator(address(this)).factory()), token, bridgeToken);
        TransferHelper.safeTransfer(token, pair, tokenAmount);
        TransferHelper.safeTransferFrom(bridgeToken, msg.sender, pair, bridgeAmount);
        liquidity = IMateriaPair(pair).mint(to);
    }

    function addLiquidity(
        address token,
        uint256 tokenAmountDesired,
        uint256 bridgeAmountDesired,
        uint256 tokenAmountMin,
        uint256 bridgeAmountMin,
        address to,
        uint256 deadline
    ) public ensure(deadline) {
        address erc20Wrapper = address(IMateriaOrchestrator(address(this)).erc20Wrapper());
        address interoperable;

        tokenAmountMin = _adjustAmount(token, tokenAmountMin);

        TransferHelper.safeTransferFrom(token, msg.sender, address(this), tokenAmountDesired);
        (interoperable, tokenAmountDesired) = _wrapErc20(token, tokenAmountDesired, erc20Wrapper);

        (uint256 tokenAmount, , ) =
            _doAddLiquidity(
                interoperable,
                address(IMateriaOrchestrator(address(this)).bridgeToken()),
                tokenAmountDesired,
                bridgeAmountDesired,
                tokenAmountMin,
                bridgeAmountMin,
                to
            );

        uint256 dust = tokenAmountDesired - tokenAmount;
        if (dust > 0) _unwrapErc20(IERC20WrapperV1(erc20Wrapper).object(token), token, dust, erc20Wrapper, msg.sender);
    }

    function addLiquidityETH(
        uint256 bridgeAmountDesired,
        uint256 ethAmountMin,
        uint256 bridgeAmountMin,
        address to,
        uint256 deadline
    )
        public
        payable
        ensure(deadline)
        returns (
            uint256 ethAmount,
            uint256 bridgeAmount,
            uint256 liquidity
        )
    {
        address erc20Wrapper = address(IMateriaOrchestrator(address(this)).erc20Wrapper());
        address bridgeToken = address(IMateriaOrchestrator(address(this)).bridgeToken());

        address ieth =
            address(
                IERC20WrapperV1(erc20Wrapper).asInteroperable(
                    uint256(IMateriaOrchestrator(address(this)).ETHEREUM_OBJECT_ID())
                )
            );

        (ethAmount, bridgeAmount) = _addLiquidity(
            ieth,
            bridgeToken,
            msg.value,
            bridgeAmountDesired,
            ethAmountMin,
            bridgeAmountMin
        );

        _wrapEth(ethAmount, erc20Wrapper);

        address pair =
            MateriaLibrary.pairFor(address(IMateriaOrchestrator(address(this)).factory()), ieth, bridgeToken);
        TransferHelper.safeTransfer(ieth, pair, ethAmount);
        TransferHelper.safeTransferFrom(bridgeToken, msg.sender, pair, bridgeAmount);
        liquidity = IMateriaPair(pair).mint(to);

        uint256 dust;
        if ((dust = msg.value - ethAmount) > 0) TransferHelper.safeTransferETH(msg.sender, dust);
    }

    function addLiquidityItem(
        uint256 itemId,
        uint256 value,
        address from,
        bytes memory payload
    ) private returns (uint256 itemAmount, uint256 bridgeAmount) {
        address erc20Wrapper = address(IMateriaOrchestrator(address(this)).erc20Wrapper());
        address bridgeToken = address(IMateriaOrchestrator(address(this)).bridgeToken());

        uint256 bridgeAmountDesired;
        address to;
        uint256 deadline;
        address token;

        (bridgeAmountDesired, itemAmount, bridgeAmount, to, deadline) = abi.decode(
            payload,
            (uint256, uint256, uint256, address, uint256)
        );

        _ensure(deadline);

        (itemAmount, bridgeAmount) = _addLiquidity(
            (token = address(IERC20WrapperV1(erc20Wrapper).asInteroperable(itemId))),
            bridgeToken,
            value,
            bridgeAmountDesired,
            itemAmount,
            bridgeAmount
        );

        address pair =
            MateriaLibrary.pairFor(address(IMateriaOrchestrator(address(this)).factory()), token, bridgeToken);
        TransferHelper.safeTransfer(token, pair, itemAmount);
        TransferHelper.safeTransferFrom(bridgeToken, from, pair, bridgeAmount);
        IMateriaPair(pair).mint(to);

        // value now is for the possible dust
        if ((value = value - itemAmount) > 0) TransferHelper.safeTransfer(token, from, value);
        if ((value = bridgeAmountDesired - bridgeAmount) > 0) TransferHelper.safeTransfer(bridgeToken, from, value);
    }

    function onERC1155Received(
        address,
        address from,
        uint256 id,
        uint256 value,
        bytes calldata data
    ) public override returns (bytes4) {
        uint256 operation;
        bytes memory payload;

        (operation, payload) = abi.decode(data, (uint256, bytes));

        if (operation == 1) {
            addLiquidityItem(id, value, from, payload);
        } else revert();

        return this.onERC1155Received.selector;
    }

    function onERC1155BatchReceived(
        address,
        address,
        uint256[] calldata,
        uint256[] calldata,
        bytes calldata
    ) public pure override returns (bytes4) {
        revert();
    }

    function supportsInterface(bytes4) public pure override returns (bool) {
        return false;
    }
}

File 28 of 35: MateriaLiquidityMathLibrary.sol
pragma solidity 0.8.0;

import './IMateriaPair.sol';
import './IMateriaFactory.sol';
import './SafeMath.sol';
import './Math.sol';
import './MateriaLibrary.sol';

// library containing some math for dealing with the liquidity shares of a pair, e.g. computing their exact value
// in terms of the underlying tokens
library MateriaLiquidityMathLibrary {
    using SafeMath for uint256;

    // computes the direction and magnitude of the profit-maximizing trade
    function computeProfitMaximizingTrade(
        uint256 truePriceTokenA,
        uint256 truePriceTokenB,
        uint256 reserveA,
        uint256 reserveB
    ) pure internal returns (bool aToB, uint256 amountIn) {
        aToB = SafeMath.mul(reserveA, truePriceTokenB)/reserveB < truePriceTokenA;

        uint256 invariant = reserveA.mul(reserveB);

        uint256 leftSide = Math.sqrt(
            SafeMath.mul(
                invariant.mul(1000),
                aToB ? truePriceTokenA : truePriceTokenB)/
                (aToB ? truePriceTokenB : truePriceTokenA).mul(997)
            
        );
        uint256 rightSide = (aToB ? reserveA.mul(1000) : reserveB.mul(1000)) / 997;

        if (leftSide < rightSide) return (false, 0);

        // compute the amount that must be sent to move the price to the profit-maximizing price
        amountIn = leftSide.sub(rightSide);
    }

    // gets the reserves after an arbitrage moves the price to the profit-maximizing ratio given an externally observed true price
    function getReservesAfterArbitrage(
        address factory,
        address tokenA,
        address tokenB,
        uint256 truePriceTokenA,
        uint256 truePriceTokenB
    ) view internal returns (uint256 reserveA, uint256 reserveB) {
        // first get reserves before the swap
        (reserveA, reserveB) = MateriaLibrary.getReserves(factory, tokenA, tokenB);

        require(reserveA > 0 && reserveB > 0, 'MateriaArbitrageLibrary: ZERO_PAIR_RESERVES');

        // then compute how much to swap to arb to the true price
        (bool aToB, uint256 amountIn) = computeProfitMaximizingTrade(truePriceTokenA, truePriceTokenB, reserveA, reserveB);

        if (amountIn == 0) {
            return (reserveA, reserveB);
        }

        // now affect the trade to the reserves
        if (aToB) {
            uint amountOut = MateriaLibrary.getAmountOut(amountIn, reserveA, reserveB);
            reserveA += amountIn;
            reserveB -= amountOut;
        } else {
            uint amountOut = MateriaLibrary.getAmountOut(amountIn, reserveB, reserveA);
            reserveB += amountIn;
            reserveA -= amountOut;
        }
    }

    // computes liquidity value given all the parameters of the pair
    function computeLiquidityValue(
        uint256 reservesA,
        uint256 reservesB,
        uint256 totalSupply,
        uint256 liquidityAmount,
        bool feeOn,
        uint kLast
    ) internal pure returns (uint256 tokenAAmount, uint256 tokenBAmount) {
        if (feeOn && kLast > 0) {
            uint rootK = Math.sqrt(reservesA.mul(reservesB));
            uint rootKLast = Math.sqrt(kLast);
            if (rootK > rootKLast) {
                uint numerator1 = totalSupply;
                uint numerator2 = rootK.sub(rootKLast);
                uint denominator = rootK.mul(5).add(rootKLast);
                uint feeLiquidity = SafeMath.mul(numerator1, numerator2)/ denominator;
                totalSupply = totalSupply.add(feeLiquidity);
            }
        }
        return (reservesA.mul(liquidityAmount) / totalSupply, reservesB.mul(liquidityAmount) / totalSupply);
    }

    // get all current parameters from the pair and compute value of a liquidity amount
    // **note this is subject to manipulation, e.g. sandwich attacks**. prefer passing a manipulation resistant price to
    // #getLiquidityValueAfterArbitrageToPrice
    function getLiquidityValue(
        address factory,
        address tokenA,
        address tokenB,
        uint256 liquidityAmount
    ) internal view returns (uint256 tokenAAmount, uint256 tokenBAmount) {
        (uint256 reservesA, uint256 reservesB) = MateriaLibrary.getReserves(factory, tokenA, tokenB);
        IMateriaPair pair = IMateriaPair(MateriaLibrary.pairFor(factory, tokenA, tokenB));
        bool feeOn = IMateriaFactory(factory).feeTo() != address(0);
        uint kLast = feeOn ? pair.kLast() : 0;
        uint totalSupply = pair.totalSupply();
        return computeLiquidityValue(reservesA, reservesB, totalSupply, liquidityAmount, feeOn, kLast);
    }

    // given two tokens, tokenA and tokenB, and their "true price", i.e. the observed ratio of value of token A to token B,
    // and a liquidity amount, returns the value of the liquidity in terms of tokenA and tokenB
    function getLiquidityValueAfterArbitrageToPrice(
        address factory,
        address tokenA,
        address tokenB,
        uint256 truePriceTokenA,
        uint256 truePriceTokenB,
        uint256 liquidityAmount
    ) internal view returns (
        uint256 tokenAAmount,
        uint256 tokenBAmount
    ) {
        bool feeOn = IMateriaFactory(factory).feeTo() != address(0);
        IMateriaPair pair = IMateriaPair(MateriaLibrary.pairFor(factory, tokenA, tokenB));
        uint kLast = feeOn ? pair.kLast() : 0;
        uint totalSupply = pair.totalSupply();

        // this also checks that totalSupply > 0
        require(totalSupply >= liquidityAmount && liquidityAmount > 0, 'ComputeLiquidityValue: LIQUIDITY_AMOUNT');

        (uint reservesA, uint reservesB) = getReservesAfterArbitrage(factory, tokenA, tokenB, truePriceTokenA, truePriceTokenB);

        return computeLiquidityValue(reservesA, reservesB, totalSupply, liquidityAmount, feeOn, kLast);
    }
}

File 29 of 35: MateriaLiquidityRemover.sol
// SPDX-License-Identifier: GPL3
pragma solidity 0.8.0;

import './MateriaOperator.sol';
import './IMateriaOrchestrator.sol';
import './IMateriaPair.sol';
import './IERC20.sol';
import './IERC20WrapperV1.sol';

import './MateriaLibrary.sol';

contract MateriaLiquidityRemover is MateriaOperator {
    function removeLiquidity(
        address token,
        uint256 liquidity,
        uint256 tokenAmountMin,
        uint256 bridgeAmountMin,
        address to,
        uint256 deadline
    ) public ensure(deadline) returns (uint256 amountBridge, uint256 amountToken) {
        address erc20Wrapper = address(IMateriaOrchestrator(address(this)).erc20Wrapper());
        address bridgeToken = address(IMateriaOrchestrator(address(this)).bridgeToken());
        address pair;

        {
            (bool ethItem, uint256 itemId) = _isEthItem(token, erc20Wrapper);
            token = ethItem ? token : address(IERC20WrapperV1(erc20Wrapper).asInteroperable(itemId));
            pair = MateriaLibrary.pairFor(address(IMateriaOrchestrator(address(this)).factory()), token, bridgeToken);
        }

        IMateriaPair(pair).transferFrom(msg.sender, pair, liquidity); // send liquidity to pair
        (uint256 amount0, uint256 amount1) = IMateriaPair(pair).burn(to);
        (address token0, ) = MateriaLibrary.sortTokens(token, bridgeToken);
        (amountBridge, amountToken) = token0 == address(bridgeToken) ? (amount0, amount1) : (amount1, amount0);
        require(amountBridge >= bridgeAmountMin, 'INSUFFICIENT_BRIDGE_AMOUNT');
        require(amountToken >= tokenAmountMin, 'INSUFFICIENT_TOKEN_AMOUNT');
    }

    function removeLiquidityETH(
        uint256 liquidity,
        uint256 bridgeAmountMin,
        uint256 ethAmountMin,
        address to,
        uint256 deadline
    ) public ensure(deadline) returns (uint256 amountBridge, uint256 amountEth) {
        address erc20Wrapper = address(IMateriaOrchestrator(address(this)).erc20Wrapper());
        address bridgeToken = address(IMateriaOrchestrator(address(this)).bridgeToken());
        address ieth = _tokenToInteroperable(address(0), erc20Wrapper);

        address pair =
            MateriaLibrary.pairFor(address(IMateriaOrchestrator(address(this)).factory()), ieth, bridgeToken);

        IMateriaPair(pair).transferFrom(msg.sender, pair, liquidity); // send liquidity to pair
        (uint256 amount0, uint256 amount1) = IMateriaPair(pair).burn(address(this));
        (address token0, ) = MateriaLibrary.sortTokens(ieth, address(bridgeToken));
        (amountBridge, amountEth) = token0 == address(bridgeToken) ? (amount0, amount1) : (amount1, amount0);
        require(amountBridge >= bridgeAmountMin, 'INSUFFICIENT_BRIDGE_AMOUNT');
        require(amountEth >= ethAmountMin, 'INSUFFICIENT_TOKEN_AMOUNT');
        _unwrapEth(uint256(IMateriaOrchestrator(address(this)).ETHEREUM_OBJECT_ID()), amountEth, erc20Wrapper, to);
    }

    function removeLiquidityWithPermit(
        address token,
        uint256 liquidity,
        uint256 tokenAmountMin,
        uint256 bridgeAmountMin,
        address to,
        uint256 deadline,
        bool approveMax,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external {
        address factory = address(IMateriaOrchestrator(address(this)).factory());
        address bridgeToken = address(IMateriaOrchestrator(address(this)).bridgeToken());

        address pair = MateriaLibrary.pairFor(factory, bridgeToken, token);
        uint256 value = approveMax ? type(uint256).max : liquidity;
        IMateriaPair(pair).permit(msg.sender, address(this), value, deadline, v, r, s);
        removeLiquidity(token, liquidity, tokenAmountMin, bridgeAmountMin, to, deadline);
    }

    function removeLiquidityETHWithPermit(
        uint256 liquidity,
        uint256 tokenAmountMin,
        uint256 bridgeAmountMin,
        address to,
        uint256 deadline,
        bool approveMax,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external {
        address factory = address(IMateriaOrchestrator(address(this)).factory());
        address bridgeToken = address(IMateriaOrchestrator(address(this)).bridgeToken());
        address erc20Wrapper = address(IMateriaOrchestrator(address(this)).erc20Wrapper());

        address pair = MateriaLibrary.pairFor(factory, bridgeToken, _tokenToInteroperable(address(0), erc20Wrapper));
        uint256 value = approveMax ? type(uint256).max : liquidity;
        IMateriaPair(pair).permit(msg.sender, address(this), value, deadline, v, r, s);
        removeLiquidityETH(liquidity, bridgeAmountMin, tokenAmountMin, to, deadline);
    }

    function onERC1155Received(
        address,
        address,
        uint256,
        uint256,
        bytes calldata
    ) public pure override returns (bytes4) {
        revert();
    }

    function onERC1155BatchReceived(
        address,
        address,
        uint256[] calldata,
        uint256[] calldata,
        bytes calldata
    ) public pure override returns (bytes4) {
        revert();
    }

    function supportsInterface(bytes4) public pure override returns (bool) {
        return false;
    }
}

File 30 of 35: MateriaOperator.sol
// SPDX-License-Identifier: GPL3
pragma solidity ^0.8.0;

import './IERC20.sol';
import './IMateriaOrchestrator.sol';
import './TransferHelper.sol';
import './IEthItemInteroperableInterface.sol';
import './IERC20WrapperV1.sol';

abstract contract MateriaOperator is IERC1155Receiver, IERC165 {
    modifier ensure(uint256 deadline) {
        require(deadline >= block.timestamp, 'Materia: Expired');
        _;
    }

    function _ensure(uint256 deadline) internal ensure(deadline) {}

    function _isEthItem(address token, address wrapper) internal view returns (bool ethItem, uint256 id) {
        try IEthItemInteroperableInterface(token).mainInterface() {
            ethItem = true;
        } catch {
            ethItem = false;
            id = IERC20WrapperV1(wrapper).object(token);
        }
    }

    function _wrapErc20(
        address token,
        uint256 amount,
        address wrapper
    ) internal returns (address interoperable, uint256 newAmount) {
        if (IERC20(token).allowance(address(this), wrapper) < amount) {
            IERC20(token).approve(wrapper, type(uint256).max);
        }

        (uint256 id, ) = IERC20WrapperV1(wrapper).mint(token, amount);

        newAmount = IERC20(interoperable = address(IERC20WrapperV1(wrapper).asInteroperable(id))).balanceOf(
            address(this)
        );
    }

    function _unwrapErc20(
        uint256 id,
        address tokenOut,
        uint256 amount,
        address wrapper,
        address to
    ) internal {
        IERC20WrapperV1(wrapper).burn(id, amount);
        TransferHelper.safeTransfer(tokenOut, to, IERC20(tokenOut).balanceOf(address(this)));
    }

    function _unwrapEth(
        uint256 id,
        uint256 amount,
        address wrapper,
        address to
    ) internal {
        IERC20WrapperV1(wrapper).burn(id, amount);
        TransferHelper.safeTransferETH(to, amount);
    }

    function _wrapEth(uint256 amount, address wrapper) public payable returns (address interoperable) {
        (, interoperable) = IERC20WrapperV1(wrapper).mintETH{value: amount}();
    }

    function _adjustAmount(address token, uint256 amount) internal view returns (uint256 newAmount) {
        newAmount = amount * (10**(18 - IERC20Data(token).decimals()));
    }

    function _tokenToInteroperable(address token, address wrapper) internal view returns (address interoperable) {
        if (token == address(0))
            interoperable = address(
                IERC20WrapperV1(wrapper).asInteroperable(
                    uint256(IMateriaOrchestrator(address(this)).ETHEREUM_OBJECT_ID())
                )
            );
        else {
            (, uint256 itemId) = _isEthItem(token, wrapper);
            interoperable = address(IERC20WrapperV1(wrapper).asInteroperable(itemId));
        }
    }
}

File 31 of 35: MateriaSwapper.sol
// SPDX-License-Identifier: UNLICENSED

pragma solidity 0.8.0;

import './MateriaOperator.sol';
import './IMateriaOrchestrator.sol';
import './IMateriaFactory.sol';
import './IMateriaPair.sol';
import './IERC20.sol';
import './IERC20WrapperV1.sol';
import './IEthItemMainInterface.sol';
import './MateriaLibrary.sol';
import './TransferHelper.sol';


contract MateriaSwapper is MateriaOperator {

    function _swap(address factory, uint[] memory amounts, address[] memory path, address _to) internal virtual {
        for (uint i; i < path.length - 1; i++) {
            (address input, address output) = (path[i], path[i + 1]);
            (address token0,) = MateriaLibrary.sortTokens(input, output);
            uint amountOut = amounts[i + 1];
            (uint amount0Out, uint amount1Out) = input == token0 ? (uint(0), amountOut) : (amountOut, uint(0));
            address to = i < path.length - 2 ? MateriaLibrary.pairFor(factory, output, path[i + 2]) : _to;
            IMateriaPair(MateriaLibrary.pairFor(factory, input, output)).swap(
                amount0Out, amount1Out, to, new bytes(0)
            );
        }
    }
    
 
    function swapExactTokensForTokens(
        uint amountIn,
        uint amountOutMin,
        address[] memory path,
        address to,
        uint deadline
    ) public ensure(deadline) returns (uint[] memory amounts) {
        
        address factory = address(IMateriaOrchestrator(address(this)).factory());
        address bridgeToken = address(IMateriaOrchestrator(address(this)).bridgeToken());
        address erc20Wrapper = address(IMateriaOrchestrator(address(this)).erc20Wrapper());

        TransferHelper.safeTransferFrom(path[0], msg.sender, address(this), amountIn);
        
        (path[0], amountIn) = _wrapErc20(path[0], amountIn, erc20Wrapper);
        
        bool ethItemOut;
        uint itemId;
        address tokenOut;
        
        (ethItemOut, itemId) = _isEthItem(path[path.length - 1], erc20Wrapper);
        
        if (!ethItemOut && bridgeToken != path[path.length - 1]) {
            tokenOut = path[path.length - 1];
            amountOutMin = _adjustAmount(tokenOut, amountOutMin);
            path[path.length - 1] = address(IERC20WrapperV1(erc20Wrapper).asInteroperable(itemId));
        }
        
        amounts = MateriaLibrary.getAmountsOut(factory, amountIn, path);
        require(amounts[amounts.length - 1] >= amountOutMin, 'INSUFFICIENT_OUTPUT_AMOUNT');
        
        TransferHelper.safeTransfer(
            path[0], MateriaLibrary.pairFor(factory, path[0], path[1]), amounts[0]
        );
        
        if (ethItemOut) {
            _swap(factory, amounts, path, to);
        } else {
            _swap(factory, amounts, path, address(this));
            _unwrapErc20(itemId, tokenOut, amounts[amounts.length - 1], erc20Wrapper, to);
        }
    }

    function swapTokensForExactTokens(
        uint amountOut,
        uint amountInMax,
        address[] memory path,
        address to,
        uint deadline
    ) public ensure(deadline) returns (uint[] memory amounts) {
        
        address factory = address(IMateriaOrchestrator(address(this)).factory());
        address erc20Wrapper = address(IMateriaOrchestrator(address(this)).erc20Wrapper());
        
        address tokenIn = path[0];
        path[0] = address(IERC20WrapperV1(erc20Wrapper).asInteroperable(IERC20WrapperV1(erc20Wrapper).object(path[0])));
        
        bool ethItemOut;
        uint itemId;
        (ethItemOut, itemId) = _isEthItem(path[path.length - 1], erc20Wrapper);
        address tokenOut;
        
        if (!ethItemOut && address(IMateriaOrchestrator(address(this)).bridgeToken()) != path[path.length - 1]) {
            tokenOut = path[path.length - 1];
            amountOut =  _adjustAmount(tokenOut, amountOut);
            path[path.length - 1] = address(IERC20WrapperV1(erc20Wrapper).asInteroperable(itemId));
        }

        amounts = MateriaLibrary.getAmountsIn(factory, amountOut, path);
        amounts[0] = amounts[0] / (10**(18 - IERC20Data(tokenIn).decimals())) + 1;

        require(amounts[0] <= amountInMax, 'EXCESSIVE_INPUT_AMOUNT');
        
        TransferHelper.safeTransferFrom(tokenIn, msg.sender, address(this), amounts[0]);
        
        (, amounts[0]) = _wrapErc20(tokenIn, amounts[0], erc20Wrapper);
        
        TransferHelper.safeTransfer(
            path[0], MateriaLibrary.pairFor(factory, path[0], path[1]), amounts[0]
        );
        
        if (ethItemOut) {
            _swap(factory, amounts, path, to);
        } else {
            _swap(factory, amounts, path, address(this));
            _unwrapErc20(itemId, tokenOut, amounts[amounts.length - 1], erc20Wrapper, to);
        }
    }
    
     function swapExactETHForTokens(
        uint amountOutMin,
        address[] memory path,
        address to,
        uint deadline
    ) public ensure(deadline) payable returns (uint[] memory amounts) {
        address factory = address(IMateriaOrchestrator(address(this)).factory());
        address bridgeToken = address(IMateriaOrchestrator(address(this)).bridgeToken());
        address erc20Wrapper = address(IMateriaOrchestrator(address(this)).erc20Wrapper());

        path[0] = _wrapEth(msg.value, erc20Wrapper);
        
        bool ethItemOut;
        uint itemId;
        address tokenOut;
        
        (ethItemOut, itemId) = _isEthItem(path[path.length - 1], erc20Wrapper);
        
        if (!ethItemOut && bridgeToken != path[path.length - 1]) {
            tokenOut = path[path.length - 1];
            amountOutMin = _adjustAmount(tokenOut, amountOutMin);
            path[path.length - 1] = address(IERC20WrapperV1(erc20Wrapper).asInteroperable(itemId));
        }
        
        amounts = MateriaLibrary.getAmountsOut(factory, msg.value, path);
        require(amounts[amounts.length - 1] >= amountOutMin, 'INSUFFICIENT_OUTPUT_AMOUNT');
        
        TransferHelper.safeTransfer(
            path[0], MateriaLibrary.pairFor(factory, path[0], path[1]), amounts[0]
        );
        
        if (ethItemOut) {
            _swap(factory, amounts, path, to);
        } else {
            _swap(factory, amounts, path, address(this));
            _unwrapErc20(itemId, tokenOut, amounts[amounts.length - 1], erc20Wrapper, to);
        }
    }
   
    function swapTokensForExactETH(
        uint amountOut,
        uint amountInMax,
        address[] memory path,
        address to,
        uint deadline
    ) public ensure(deadline) returns (uint[] memory amounts) {
        address factory = address(IMateriaOrchestrator(address(this)).factory());
        address erc20Wrapper = address(IMateriaOrchestrator(address(this)).erc20Wrapper());
        uint ethId = uint(IMateriaOrchestrator(address(this)).ETHEREUM_OBJECT_ID());
        
        address token = path[0];
        path[0] = address(IERC20WrapperV1(erc20Wrapper).asInteroperable(IERC20WrapperV1(erc20Wrapper).object(path[0])));
        amountOut = amountOut * (10 ** (18 - IERC20Data(path[path.length - 1]).decimals()));

        amountInMax = _adjustAmount(token, amountInMax);
        amounts = MateriaLibrary.getAmountsIn(factory, amountOut, path);
        require(amounts[0] <= amountInMax, 'INSUFFICIENT_INPUT_AMOUNT');

        TransferHelper.safeTransferFrom(token, msg.sender, address(this), amounts[0]);
        
        (path[0], amounts[0]) = _wrapErc20(token, amounts[0], erc20Wrapper);
        
        TransferHelper.safeTransfer(
            path[0], MateriaLibrary.pairFor(factory, path[0], path[1]), amounts[0]
        );
        
        _swap(factory, amounts, path, address(this));
        _unwrapEth(ethId, amounts[amounts.length - 1], erc20Wrapper, to);
    }
    
    function swapExactTokensForETH(
        uint amountIn,
        uint amountOutMin,
        address[] memory path,
        address to,
        uint deadline
    ) public ensure(deadline) returns (uint[] memory amounts) {
        address factory = address(IMateriaOrchestrator(address(this)).factory());
        address erc20Wrapper = address(IMateriaOrchestrator(address(this)).erc20Wrapper());
        uint ethId = uint(IMateriaOrchestrator(address(this)).ETHEREUM_OBJECT_ID());

        TransferHelper.safeTransferFrom(path[0], msg.sender, address(this), amountIn);
        
        (path[0], amountIn) = _wrapErc20(path[0], amountIn, erc20Wrapper);
        
        amounts = MateriaLibrary.getAmountsOut(factory, amountIn, path);
        require(amounts[amounts.length - 1] >= amountOutMin, 'INSUFFICIENT_OUTPUT_AMOUNT');
        
        TransferHelper.safeTransfer(
            path[0], MateriaLibrary.pairFor(factory, path[0], path[1]), amounts[0]
        );
        
        _swap(factory, amounts, path, address(this));
        _unwrapEth(ethId, amounts[amounts.length - 1], erc20Wrapper, to);
    }
    
    function swapETHForExactTokens(
        uint amountOut,
        address[] memory path,
        address to,
        uint deadline
    ) public payable ensure(deadline) returns (uint[] memory amounts) {
        address factory = address(IMateriaOrchestrator(address(this)).factory());
        address erc20Wrapper = address(IMateriaOrchestrator(address(this)).erc20Wrapper());
        address bridgeToken = address(IMateriaOrchestrator(address(this)).bridgeToken());
        
        bool ethItemOut;
        uint itemId;
        address tokenOut;
        
        (ethItemOut, itemId) = _isEthItem(path[path.length - 1], erc20Wrapper);
        
        if (!ethItemOut && bridgeToken != path[path.length - 1]) {
            tokenOut = path[path.length - 1];
            amountOut = _adjustAmount(tokenOut, amountOut);
            path[path.length - 1] = address(IERC20WrapperV1(erc20Wrapper).asInteroperable(itemId));
        }
        
        amounts = MateriaLibrary.getAmountsIn(factory, amountOut, path);
        require(amounts[0] <= msg.value, 'INSUFFICIENT_INPUT_AMOUNT');
        
        path[0] = _wrapEth(amounts[0], erc20Wrapper);
        
        TransferHelper.safeTransfer(
            path[0], MateriaLibrary.pairFor(factory, path[0], path[1]), amounts[0]
        );
        
        if (ethItemOut) {
            _swap(factory, amounts, path, to);
        } else {
            _swap(factory, amounts, path, address(this));
            _unwrapErc20(itemId, tokenOut, amounts[amounts.length - 1], erc20Wrapper, to);
        }
        
        if (msg.value > amounts[0])
            TransferHelper.safeTransferETH(msg.sender, msg.value - amounts[0]);
    }
    
    function swapExactItemsForTokens(
        uint amountIn,
        uint amountOutMin,
        address[] memory path,
        address to,
        uint deadline
    ) private ensure(deadline) {
        address factory = address(IMateriaOrchestrator(address(this)).factory());
        address erc20Wrapper = address(IMateriaOrchestrator(address(this)).erc20Wrapper());

        bool ethItemOut;
        uint itemId;
        address tokenOut;
        
        (ethItemOut, itemId) = _isEthItem(path[path.length - 1], erc20Wrapper);
        
        if (!ethItemOut && address(IMateriaOrchestrator(address(this)).bridgeToken()) != path[path.length - 1]) {
            tokenOut = path[path.length - 1];
            amountOutMin = _adjustAmount(tokenOut, amountOutMin);
            path[path.length - 1] = address(IERC20WrapperV1(erc20Wrapper).asInteroperable(itemId));
        }
        
        uint[] memory amounts = MateriaLibrary.getAmountsOut(factory, amountIn, path);
        require(amounts[amounts.length - 1] >= amountOutMin, 'INSUFFICIENT_OUTPUT_AMOUNT');
        
        TransferHelper.safeTransfer(
            path[0], MateriaLibrary.pairFor(factory, path[0], path[1]), amounts[0]
        );
        
        if (ethItemOut) {
            _swap(factory, amounts, path, to);
        } else {
            _swap(factory, amounts, path, address(this));
            _unwrapErc20(itemId, tokenOut, amounts[amounts.length - 1], erc20Wrapper, to);
        }
    }
    
    function swapItemsForExactTokens(
        uint amountOut,
        uint amountInMax,
        address[] memory path,
        address to,
        address from,
        uint deadline
    ) private ensure(deadline) {
        address factory = address(IMateriaOrchestrator(address(this)).factory());
        address erc20Wrapper = address(IMateriaOrchestrator(address(this)).erc20Wrapper());

        bool ethItemOut;
        uint itemId;
        address tokenOut;
        
        (ethItemOut, itemId) = _isEthItem(path[path.length - 1], erc20Wrapper);
        
        if (!ethItemOut && address(IMateriaOrchestrator(address(this)).bridgeToken()) != path[path.length - 1]) {
            tokenOut = path[path.length - 1];
            amountOut = _adjustAmount(tokenOut, amountOut);
            path[path.length - 1] = address(IERC20WrapperV1(erc20Wrapper).asInteroperable(itemId));
        }
        
        uint[] memory amounts = MateriaLibrary.getAmountsIn(factory, amountOut, path);
        require(amounts[0] <= amountInMax, 'INSUFFICIENT_INPUT_AMOUNT');
        
        {
        uint amountBack;
        if ((amountBack = amountInMax - amounts[0]) > 0)
            TransferHelper.safeTransfer(path[0], from, amountBack);
        }
        
        TransferHelper.safeTransfer(
            path[0], MateriaLibrary.pairFor(factory, path[0], path[1]), amounts[0]
        );
        
        if (ethItemOut) {
            _swap(factory, amounts, path, to);
        } else {
            _swap(factory, amounts, path, address(this));
            _unwrapErc20(itemId, tokenOut, amounts[amounts.length - 1], erc20Wrapper, to);
        }
    }
    
    function swapExactItemsForEth(
        uint amountIn,
        uint amountOutMin,
        address[] memory path,
        address to,
        uint deadline
    ) private ensure(deadline) {
        address factory = address(IMateriaOrchestrator(address(this)).factory());
        address erc20Wrapper = address(IMateriaOrchestrator(address(this)).erc20Wrapper());
        uint ethId = uint(IMateriaOrchestrator(address(this)).ETHEREUM_OBJECT_ID());

        uint[] memory amounts = MateriaLibrary.getAmountsOut(factory, amountIn, path);
        require(amounts[amounts.length - 1] >= amountOutMin, 'INSUFFICIENT_OUTPUT_AMOUNT');
        
        TransferHelper.safeTransfer(
            path[0], MateriaLibrary.pairFor(factory, path[0], path[1]), amounts[0]
        );
        
        _swap(factory, amounts, path, address(this));
        
        IERC20WrapperV1(erc20Wrapper).burn(
            ethId,
            amounts[amounts.length - 1]
        );
        
        TransferHelper.safeTransferETH(to, amounts[amounts.length - 1]);
    }
    
    function swapItemsForExactEth(
        uint amountOut,
        uint amountInMax,
        address[] memory path,
        address to,
        address from,
        uint deadline
    ) private ensure(deadline) {
        address factory = address(IMateriaOrchestrator(address(this)).factory());
        address erc20Wrapper = address(IMateriaOrchestrator(address(this)).erc20Wrapper());
        uint ethId = uint(IMateriaOrchestrator(address(this)).ETHEREUM_OBJECT_ID());

        uint[] memory amounts = MateriaLibrary.getAmountsIn(factory, amountOut, path);
        require(amounts[0] <= amountInMax, 'INSUFFICIENT_INPUT_AMOUNT');
        
        {
        uint amountBack;
        if ((amountBack = amountInMax - amounts[0]) > 0)
            TransferHelper.safeTransfer(path[0], from, amountBack);
        }
        
        TransferHelper.safeTransfer(
            path[0], MateriaLibrary.pairFor(factory, path[0], path[1]), amounts[0]
        );
        
        _swap(factory, amounts, path, address(this));
        
        IERC20WrapperV1(erc20Wrapper).burn(
            ethId,
            amounts[amounts.length - 1]
        );
        
        TransferHelper.safeTransferETH(to, amounts[amounts.length - 1]);
    }

    function onERC1155Received(
        address,
        address from,
        uint,
        uint value,
        bytes calldata data
    ) public override returns(bytes4) {
        uint operation;
        uint amount;
        address[] memory path;
        address to;
        uint deadline;
        
        { //to avoid "stack too deep"
            bytes memory payload;
            (operation, payload) = abi.decode(data, (uint, bytes));
            (amount, path, to, deadline) = abi.decode(payload, (uint, address[], address, uint));
        }
        
        if (operation == 2) swapExactItemsForTokens(value, amount, path, to, deadline);
        else if (operation == 3) swapItemsForExactTokens(amount, value, path, to, from, deadline);
        else if (operation == 4) swapExactItemsForEth(value, amount, path, to, deadline);
        else if (operation == 5) swapItemsForExactEth(amount, value, path, to, from, deadline);
        else revert();
        
        return this.onERC1155Received.selector;
    }

    function onERC1155BatchReceived(
        address,
        address,
        uint256[] calldata,
        uint256[] calldata,
        bytes calldata
    ) public override pure returns(bytes4) {
        revert();
    }
    
    function supportsInterface(
        bytes4
    ) public override pure returns (bool) {
        return false;
    }
}

File 32 of 35: Math.sol
// SPDX-License-Identifier: UNLICENSED

pragma solidity =0.8.0;

// a library for performing various math operations

library Math {
    function min(uint x, uint y) internal pure returns (uint z) {
        z = x < y ? x : y;
    }

    // babylonian method (https://en.wikipedia.org/wiki/Methods_of_computing_square_roots#Babylonian_method)
    function sqrt(uint y) internal pure returns (uint z) {
        if (y > 3) {
            z = y;
            uint x = y / 2 + 1;
            while (x < z) {
                z = x;
                x = (y / x + x) / 2;
            }
        } else if (y != 0) {
            z = 1;
        }
    }
}

File 33 of 35: SafeMath.sol
// SPDX-License-Identifier: UNLICENSED

pragma solidity 0.8.0;

// a library for performing overflow-safe math, courtesy of DappHub (https://github.com/dapphub/ds-math)

library SafeMath {
    function add(uint x, uint y) internal pure returns (uint z) {
        require((z = x + y) >= x, 'ds-math-add-overflow');
    }

    function sub(uint x, uint y) internal pure returns (uint z) {
        require((z = x - y) <= x, 'ds-math-sub-underflow');
    }

    function mul(uint x, uint y) internal pure returns (uint z) {
        require(y == 0 || (z = x * y) / y == x, 'ds-math-mul-overflow');
    }
}

File 34 of 35: TransferHelper.sol
// SPDX-License-Identifier: GPL-3.0-or-later

pragma solidity >=0.6.0;

// helper methods for interacting with ERC20 tokens and sending ETH that do not consistently return true/false
library TransferHelper {
    function safeApprove(
        address token,
        address to,
        uint256 value
    ) internal {
        // bytes4(keccak256(bytes('approve(address,uint256)')));
        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x095ea7b3, to, value));
        require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: APPROVE_FAILED');
    }

    function safeTransfer(
        address token,
        address to,
        uint256 value
    ) internal {
        // bytes4(keccak256(bytes('transfer(address,uint256)')));
        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0xa9059cbb, to, value));
        require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: TRANSFER_FAILED');
    }

    function safeTransferFrom(
        address token,
        address from,
        address to,
        uint256 value
    ) internal {
        // bytes4(keccak256(bytes('transferFrom(address,address,uint256)')));
        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(0x23b872dd, from, to, value));
        require(success && (data.length == 0 || abi.decode(data, (bool))), 'TransferHelper: TRANSFER_FROM_FAILED');
    }

    function safeTransferETH(address to, uint256 value) internal {
        (bool success, ) = to.call{value: value}(new bytes(0));
        require(success, 'TransferHelper: ETH_TRANSFER_FAILED');
    }
}

File 35 of 35: UQ112x112.sol
// SPDX-License-Identifier: UNLICENSED

pragma solidity =0.8.0;

// a library for handling binary fixed point numbers (https://en.wikipedia.org/wiki/Q_(number_format))

// range: [0, 2**112 - 1]
// resolution: 1 / 2**112

library UQ112x112 {
    uint224 constant Q112 = 2**112;

    // encode a uint112 as a UQ112x112
    function encode(uint112 y) internal pure returns (uint224 z) {
        z = uint224(y) * Q112; // never overflows
    }

    // divide a UQ112x112 by a uint112, returning a UQ112x112
    function uqdiv(uint224 x, uint112 y) internal pure returns (uint224 z) {
        z = x / uint224(y);
    }
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"initialFactory","type":"address"},{"internalType":"address","name":"initialBridgeToken","type":"address"},{"internalType":"address","name":"initialErc20Wrapper","type":"address"},{"internalType":"address","name":"initialDoubleProxy","type":"address"},{"internalType":"address","name":"initialLiquidityAdder","type":"address"},{"internalType":"address","name":"initialLiquidityRemover","type":"address"},{"internalType":"address","name":"initialSwapper","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ETHEREUM_OBJECT_ID","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"tokenAmountDesired","type":"uint256"},{"internalType":"uint256","name":"bridgeAmountDesired","type":"uint256"},{"internalType":"uint256","name":"tokenAmountMin","type":"uint256"},{"internalType":"uint256","name":"bridgeAmountMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"addLiquidity","outputs":[{"internalType":"uint256","name":"amountA","type":"uint256"},{"internalType":"uint256","name":"amountB","type":"uint256"},{"internalType":"uint256","name":"liquidity","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"bridgeAmountDesired","type":"uint256"},{"internalType":"uint256","name":"EthAmountMin","type":"uint256"},{"internalType":"uint256","name":"bridgeAmountMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"addLiquidityETH","outputs":[{"internalType":"uint256","name":"amountToken","type":"uint256"},{"internalType":"uint256","name":"amountETH","type":"uint256"},{"internalType":"uint256","name":"liquidity","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"bridgeToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"doubleProxy","outputs":[{"internalType":"contract IDoubleProxy","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"erc20Wrapper","outputs":[{"internalType":"contract IERC20WrapperV1","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"factory","outputs":[{"internalType":"contract IMateriaFactory","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"uint256","name":"reserveIn","type":"uint256"},{"internalType":"uint256","name":"reserveOut","type":"uint256"}],"name":"getAmountIn","outputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"reserveIn","type":"uint256"},{"internalType":"uint256","name":"reserveOut","type":"uint256"}],"name":"getAmountOut","outputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"}],"name":"getAmountsIn","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"}],"name":"getAmountsOut","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"receiver","type":"address"}],"name":"getCrumbs","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"isEthItem","outputs":[{"internalType":"address","name":"collection","type":"address"},{"internalType":"bool","name":"ethItem","type":"bool"},{"internalType":"uint256","name":"itemId","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"liquidityAdder","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"liquidityRemover","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"uint256[]","name":"","type":"uint256[]"},{"internalType":"bytes","name":"","type":"bytes"}],"name":"onERC1155BatchReceived","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"payload","type":"bytes"}],"name":"onERC1155Received","outputs":[{"internalType":"bytes4","name":"","type":"bytes4"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountA","type":"uint256"},{"internalType":"uint256","name":"reserveA","type":"uint256"},{"internalType":"uint256","name":"reserveB","type":"uint256"}],"name":"quote","outputs":[{"internalType":"uint256","name":"amountB","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"tokenAmountMin","type":"uint256"},{"internalType":"uint256","name":"bridgeAmountMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"removeLiquidity","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"bridgeAmountMin","type":"uint256"},{"internalType":"uint256","name":"EthAmountMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"removeLiquidityETH","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"tokenAmountMin","type":"uint256"},{"internalType":"uint256","name":"bridgeAmountMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bool","name":"approveMax","type":"bool"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"removeLiquidityETHWithPermit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"liquidity","type":"uint256"},{"internalType":"uint256","name":"tokenAmountMin","type":"uint256"},{"internalType":"uint256","name":"bridgeAmountMin","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bool","name":"approveMax","type":"bool"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"removeLiquidityWithPermit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOrchestrator","type":"address"}],"name":"retire","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newBridgeToken","type":"address"}],"name":"setBridgeToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"materiaFee","type":"uint256"},{"internalType":"uint256","name":"swapFee","type":"uint256"}],"name":"setDefaultFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newDoubleProxy","type":"address"}],"name":"setDoubleProxy","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newErc20Wrapper","type":"address"}],"name":"setErc20Wrapper","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"newEthereumObjectId","type":"uint256"}],"name":"setEthereumObjectId","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newFactory","type":"address"}],"name":"setFactory","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"feeTo","type":"address"}],"name":"setFeeTo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"materiaFee","type":"uint256"},{"internalType":"uint256","name":"swapFee","type":"uint256"}],"name":"setFees","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_adder","type":"address"}],"name":"setLiquidityAdder","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_remover","type":"address"}],"name":"setLiquidityRemover","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_swapper","type":"address"}],"name":"setSwapper","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapETHForExactTokens","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactETHForTokens","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactTokensForETH","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountIn","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapExactTokensForTokens","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"uint256","name":"amountInMax","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapTokensForExactETH","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amountOut","type":"uint256"},{"internalType":"uint256","name":"amountInMax","type":"uint256"},{"internalType":"address[]","name":"path","type":"address[]"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"swapTokensForExactTokens","outputs":[{"internalType":"uint256[]","name":"amounts","type":"uint256[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"swapper","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]

60806040523480156200001157600080fd5b506040516200397e3803806200397e83398101604081905262000034916200012c565b600480546001600160a01b03199081166001600160a01b03998a1617909155600680548216978916979097179096556005805487169588169590951790945560408051808201909152601681527f54484520455448455245554d204f424a454354204954000000000000000000006020909101527f186184b38c30620314f957b261f907a96e7bd12c377a91dcf1ef57fdea9aad3760075560008054861693871693909317909255600280548516918616919091179055600380548416918516919091179055600180549092169216919091179055620001c0565b80516001600160a01b03811681146200012757600080fd5b919050565b600080600080600080600060e0888a03121562000147578283fd5b62000152886200010f565b965062000162602089016200010f565b955062000172604089016200010f565b945062000182606089016200010f565b935062000192608089016200010f565b9250620001a260a089016200010f565b9150620001b260c089016200010f565b905092959891949750929550565b6137ae80620001d06000396000f3fe60806040526004361061024a5760003560e01c80639187aaca11610139578063be745fff116100b6578063d7565a0c1161007a578063d7565a0c1461069d578063ee1fae3c146106bd578063f23a6e61146106dd578063f46901ed146106fd578063f4734b0c1461071d578063fb3bdb411461049c57610284565b8063be745fff1461061e578063c45a015514610633578063cafd47df14610648578063cbd99d031461065d578063d06ca61f1461067d57610284565b8063ad615dec116100fd578063ad615dec1461057e578063b6ec79fe1461059e578063b9bdb4ef146105be578063bb8a88bb146105de578063bc197c81146105f157610284565b80639187aaca146104cf57806396c92f5e146104fe5780639c82f2a41461051e5780639e6371ba1461053e5780639f1840111461055e57610284565b806347883c37116101c7578063678700e01161018b578063678700e01461045c578063781cef2a1461047c5780637ff36ab51461049c57806385f8c259146104af5780638803dbee146103c357610284565b806347883c37146103e35780634a25d94a1461031f5780634eb9b5921461041257806355809f9f146104275780635bb478081461043c57610284565b80631b5f58c81161020e5780631b5f58c81461033f5780631f00ca741461036157806323ae84011461038e5780632b3297f9146103ae57806338ed1739146103c357610284565b806302af0fb514610289578063054d50d4146102a9578063104870fd146102df57806311f38472146102ff57806318cbafe51461031f57610284565b36610284576005546001600160a01b031633146102825760405162461bcd60e51b815260040161027990613576565b60405180910390fd5b005b600080fd5b34801561029557600080fd5b506102826102a4366004612ee6565b610732565b3480156102b557600080fd5b506102c96102c43660046130dd565b6108c2565b6040516102d6919061363d565b60405180910390f35b3480156102eb57600080fd5b506102826102fa366004612d8a565b6108d7565b34801561030b57600080fd5b5061028261031a366004612cf9565b6108f8565b34801561032b57600080fd5b5061028261033a366004613074565b610aff565b34801561034b57600080fd5b50610354610b1b565b6040516102d69190613276565b34801561036d57600080fd5b5061038161037c366004612f16565b610b2a565b6040516102d691906132e5565b34801561039a57600080fd5b506102826103a9366004612b44565b610b4d565b3480156103ba57600080fd5b50610354610cfa565b3480156103cf57600080fd5b506103816103de366004613074565b610d09565b3480156103ef57600080fd5b506104036103fe366004612b44565b610d2a565b6040516102d69392919061328a565b34801561041e57600080fd5b50610354610e48565b34801561043357600080fd5b50610354610e57565b34801561044857600080fd5b50610282610457366004612b44565b610e66565b34801561046857600080fd5b5061028261047736600461313f565b611013565b34801561048857600080fd5b50610282610497366004612b44565b611033565b6102826104aa366004612f5b565b6111e0565b3480156104bb57600080fd5b506102c96104ca3660046130dd565b6111fb565b3480156104db57600080fd5b506104ef6104ea366004612e1f565b611208565b6040516102d693929190613646565b34801561050a57600080fd5b50610282610519366004612d2d565b611231565b34801561052a57600080fd5b50610282610539366004612b44565b61124e565b34801561054a57600080fd5b50610282610559366004612b44565b6113fb565b34801561056a57600080fd5b50610282610579366004612b44565b6115e3565b34801561058a57600080fd5b506102c96105993660046130dd565b611790565b3480156105aa57600080fd5b506102826105b9366004612cb8565b61179d565b3480156105ca57600080fd5b506102826105d9366004613053565b611938565b6104ef6105ec366004613108565b611b81565b3480156105fd57600080fd5b5061061161060c366004612b83565b611ba8565b6040516102d69190613329565b34801561062a57600080fd5b506102c9611baf565b34801561063f57600080fd5b50610354611bb5565b34801561065457600080fd5b50610354611bc4565b34801561066957600080fd5b50610282610678366004612b44565b611bd3565b34801561068957600080fd5b50610381610698366004612f16565b611d80565b3480156106a957600080fd5b506102826106b8366004612b44565b611d9a565b3480156106c957600080fd5b506102826106d8366004613108565b611f47565b3480156106e957600080fd5b506106116106f8366004612c3e565b611f5c565b34801561070957600080fd5b50610282610718366004612b44565b611fe4565b34801561072957600080fd5b5061035461219e565b60008054906101000a90046001600160a01b03166001600160a01b031663ec5568896040518163ffffffff1660e01b815260040160206040518083038186803b15801561077e57600080fd5b505afa158015610792573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107b69190612b67565b6001600160a01b0316636701586a6040518163ffffffff1660e01b815260040160206040518083038186803b1580156107ee57600080fd5b505afa158015610802573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108269190612b67565b6001600160a01b0316633191d332336040518263ffffffff1660e01b81526004016108519190613276565b60206040518083038186803b15801561086957600080fd5b505afa15801561087d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108a19190612e87565b6108bd5760405162461bcd60e51b8152600401610279906133a4565b600755565b60006108cf8484846121ad565b949350505050565b6003546108ec906001600160a01b0316612247565b50505050505050505050565b60008054906101000a90046001600160a01b03166001600160a01b031663ec5568896040518163ffffffff1660e01b815260040160206040518083038186803b15801561094457600080fd5b505afa158015610958573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061097c9190612b67565b6001600160a01b0316636701586a6040518163ffffffff1660e01b815260040160206040518083038186803b1580156109b457600080fd5b505afa1580156109c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109ec9190612b67565b6001600160a01b0316633191d332336040518263ffffffff1660e01b8152600401610a179190613276565b60206040518083038186803b158015610a2f57600080fd5b505afa158015610a43573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a679190612e87565b610a835760405162461bcd60e51b8152600401610279906133a4565b6004546006546001600160a01b03918216916311f3847291610aa8918491168761226b565b84846040518463ffffffff1660e01b8152600401610ac8939291906132c4565b600060405180830381600087803b158015610ae257600080fd5b505af1158015610af6573d6000803e3d6000fd5b50505050505050565b600154610b14906001600160a01b0316612247565b5050505050565b6005546001600160a01b031681565b600454606090610b44906001600160a01b031684846122db565b90505b92915050565b60008054906101000a90046001600160a01b03166001600160a01b031663ec5568896040518163ffffffff1660e01b815260040160206040518083038186803b158015610b9957600080fd5b505afa158015610bad573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bd19190612b67565b6001600160a01b0316636701586a6040518163ffffffff1660e01b815260040160206040518083038186803b158015610c0957600080fd5b505afa158015610c1d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c419190612b67565b6001600160a01b0316633191d332336040518263ffffffff1660e01b8152600401610c6c9190613276565b60206040518083038186803b158015610c8457600080fd5b505afa158015610c98573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cbc9190612e87565b610cd85760405162461bcd60e51b8152600401610279906133a4565b600680546001600160a01b0319166001600160a01b0392909216919091179055565b6001546001600160a01b031681565b600154606090610d21906001600160a01b0316612247565b95945050505050565b600080806001600160a01b038416610d4a57506000915081905080610e41565b836001600160a01b0316631836b97d6040518163ffffffff1660e01b815260040160206040518083038186803b158015610d8357600080fd5b505afa925050508015610db3575060408051601f3d908101601f19168201909252610db091810190612b67565b60015b610dc557506000915081905080610e41565b806001866001600160a01b031663d4d5a06d6040518163ffffffff1660e01b815260040160206040518083038186803b158015610e0157600080fd5b505afa158015610e15573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e399190612efe565b935093509350505b9193909250565b6000546001600160a01b031681565b6002546001600160a01b031681565b60008054906101000a90046001600160a01b03166001600160a01b031663ec5568896040518163ffffffff1660e01b815260040160206040518083038186803b158015610eb257600080fd5b505afa158015610ec6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610eea9190612b67565b6001600160a01b0316636701586a6040518163ffffffff1660e01b815260040160206040518083038186803b158015610f2257600080fd5b505afa158015610f36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f5a9190612b67565b6001600160a01b0316633191d332336040518263ffffffff1660e01b8152600401610f859190613276565b60206040518083038186803b158015610f9d57600080fd5b505afa158015610fb1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fd59190612e87565b610ff15760405162461bcd60e51b8152600401610279906133a4565b600480546001600160a01b0319166001600160a01b0392909216919091179055565b600354611028906001600160a01b0316612247565b505050505050505050565b60008054906101000a90046001600160a01b03166001600160a01b031663ec5568896040518163ffffffff1660e01b815260040160206040518083038186803b15801561107f57600080fd5b505afa158015611093573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110b79190612b67565b6001600160a01b0316636701586a6040518163ffffffff1660e01b815260040160206040518083038186803b1580156110ef57600080fd5b505afa158015611103573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111279190612b67565b6001600160a01b0316633191d332336040518263ffffffff1660e01b81526004016111529190613276565b60206040518083038186803b15801561116a57600080fd5b505afa15801561117e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111a29190612e87565b6111be5760405162461bcd60e51b8152600401610279906133a4565b600380546001600160a01b0319166001600160a01b0392909216919091179055565b6001546111f5906001600160a01b0316612247565b50505050565b60006108cf848484612495565b60025460009081908190611224906001600160a01b0316612247565b9750975097945050505050565b600354611246906001600160a01b0316612247565b505050505050565b60008054906101000a90046001600160a01b03166001600160a01b031663ec5568896040518163ffffffff1660e01b815260040160206040518083038186803b15801561129a57600080fd5b505afa1580156112ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112d29190612b67565b6001600160a01b0316636701586a6040518163ffffffff1660e01b815260040160206040518083038186803b15801561130a57600080fd5b505afa15801561131e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113429190612b67565b6001600160a01b0316633191d332336040518263ffffffff1660e01b815260040161136d9190613276565b60206040518083038186803b15801561138557600080fd5b505afa158015611399573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113bd9190612e87565b6113d95760405162461bcd60e51b8152600401610279906133a4565b600180546001600160a01b0319166001600160a01b0392909216919091179055565b60008054906101000a90046001600160a01b03166001600160a01b031663ec5568896040518163ffffffff1660e01b815260040160206040518083038186803b15801561144757600080fd5b505afa15801561145b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061147f9190612b67565b6001600160a01b0316636701586a6040518163ffffffff1660e01b815260040160206040518083038186803b1580156114b757600080fd5b505afa1580156114cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114ef9190612b67565b6001600160a01b0316633191d332336040518263ffffffff1660e01b815260040161151a9190613276565b60206040518083038186803b15801561153257600080fd5b505afa158015611546573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061156a9190612e87565b6115865760405162461bcd60e51b8152600401610279906133a4565b6004805460405163f2fde38b60e01b81526001600160a01b039091169163f2fde38b916115b591859101613276565b600060405180830381600087803b1580156115cf57600080fd5b505af1158015610b14573d6000803e3d6000fd5b60008054906101000a90046001600160a01b03166001600160a01b031663ec5568896040518163ffffffff1660e01b815260040160206040518083038186803b15801561162f57600080fd5b505afa158015611643573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116679190612b67565b6001600160a01b0316636701586a6040518163ffffffff1660e01b815260040160206040518083038186803b15801561169f57600080fd5b505afa1580156116b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116d79190612b67565b6001600160a01b0316633191d332336040518263ffffffff1660e01b81526004016117029190613276565b60206040518083038186803b15801561171a57600080fd5b505afa15801561172e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117529190612e87565b61176e5760405162461bcd60e51b8152600401610279906133a4565b600280546001600160a01b0319166001600160a01b0392909216919091179055565b60006108cf848484612529565b60008054906101000a90046001600160a01b03166001600160a01b031663ec5568896040518163ffffffff1660e01b815260040160206040518083038186803b1580156117e957600080fd5b505afa1580156117fd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118219190612b67565b6001600160a01b0316636701586a6040518163ffffffff1660e01b815260040160206040518083038186803b15801561185957600080fd5b505afa15801561186d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118919190612b67565b6001600160a01b0316633191d332336040518263ffffffff1660e01b81526004016118bc9190613276565b60206040518083038186803b1580156118d457600080fd5b505afa1580156118e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061190c9190612e87565b6119285760405162461bcd60e51b8152600401610279906133a4565b61193383828461258b565b505050565b60008054906101000a90046001600160a01b03166001600160a01b031663ec5568896040518163ffffffff1660e01b815260040160206040518083038186803b15801561198457600080fd5b505afa158015611998573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119bc9190612b67565b6001600160a01b0316636701586a6040518163ffffffff1660e01b815260040160206040518083038186803b1580156119f457600080fd5b505afa158015611a08573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a2c9190612b67565b6001600160a01b0316633191d332336040518263ffffffff1660e01b8152600401611a579190613276565b60206040518083038186803b158015611a6f57600080fd5b505afa158015611a83573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611aa79190612e87565b611ac35760405162461bcd60e51b8152600401610279906133a4565b60048054604051633ca1b37360e11b81526001600160a01b039091169163794366e691611af29186910161363d565b600060405180830381600087803b158015611b0c57600080fd5b505af1158015611b20573d6000803e3d6000fd5b50506004805460405163334dc4f360e01b81526001600160a01b03909116935063334dc4f39250611b539185910161363d565b600060405180830381600087803b158015611b6d57600080fd5b505af1158015611246573d6000803e3d6000fd5b60025460009081908190611b9d906001600160a01b0316612247565b955095509592505050565b6000806000fd5b60075481565b6004546001600160a01b031681565b6003546001600160a01b031681565b60008054906101000a90046001600160a01b03166001600160a01b031663ec5568896040518163ffffffff1660e01b815260040160206040518083038186803b158015611c1f57600080fd5b505afa158015611c33573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c579190612b67565b6001600160a01b0316636701586a6040518163ffffffff1660e01b815260040160206040518083038186803b158015611c8f57600080fd5b505afa158015611ca3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cc79190612b67565b6001600160a01b0316633191d332336040518263ffffffff1660e01b8152600401611cf29190613276565b60206040518083038186803b158015611d0a57600080fd5b505afa158015611d1e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d429190612e87565b611d5e5760405162461bcd60e51b8152600401610279906133a4565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b600454606090610b44906001600160a01b03168484612671565b60008054906101000a90046001600160a01b03166001600160a01b031663ec5568896040518163ffffffff1660e01b815260040160206040518083038186803b158015611de657600080fd5b505afa158015611dfa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e1e9190612b67565b6001600160a01b0316636701586a6040518163ffffffff1660e01b815260040160206040518083038186803b158015611e5657600080fd5b505afa158015611e6a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e8e9190612b67565b6001600160a01b0316633191d332336040518263ffffffff1660e01b8152600401611eb99190613276565b60206040518083038186803b158015611ed157600080fd5b505afa158015611ee5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f099190612e87565b611f255760405162461bcd60e51b8152600401610279906133a4565b600580546001600160a01b0319166001600160a01b0392909216919091179055565b600354610b14906001600160a01b0316612247565b600080611f6b83850185612fba565b5090508060011415611f9157600254611f8c906001600160a01b0316612247565b611fd0565b8060021480611fa05750806003145b80611fab5750806004145b80611fb65750806005145b1561028457600154611f8c906001600160a01b0316612247565b5063f23a6e6160e01b979650505050505050565b60008054906101000a90046001600160a01b03166001600160a01b031663ec5568896040518163ffffffff1660e01b815260040160206040518083038186803b15801561203057600080fd5b505afa158015612044573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120689190612b67565b6001600160a01b0316636701586a6040518163ffffffff1660e01b815260040160206040518083038186803b1580156120a057600080fd5b505afa1580156120b4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120d89190612b67565b6001600160a01b0316633191d332336040518263ffffffff1660e01b81526004016121039190613276565b60206040518083038186803b15801561211b57600080fd5b505afa15801561212f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121539190612e87565b61216f5760405162461bcd60e51b8152600401610279906133a4565b6004805460405163f46901ed60e01b81526001600160a01b039091169163f46901ed916115b591859101613276565b6006546001600160a01b031681565b60008084116121ce5760405162461bcd60e51b8152600401610279906134ea565b6000831180156121de5750600082115b6121fa5760405162461bcd60e51b8152600401610279906135c0565b6000612208856103e561280b565b90506000612216828561280b565b905060006122308361222a886103e861280b565b9061284b565b905061223c818361369e565b979650505050505050565b3660008037600080366000845af43d6000803e808015612266573d6000f35b3d6000fd5b600080600061227a8585612879565b915091508582826040516020016122929291906131c0565b604051602081830303815290604052805190602001206040516020016122b9929190613220565b60408051601f1981840301815291905280516020909101209695505050505050565b60606002825110156122ff5760405162461bcd60e51b8152600401610279906134b3565b815167ffffffffffffffff81111561232757634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015612350578160200160208202803683370190505b50905082816001835161236391906136dd565b8151811061238157634e487b7160e01b600052603260045260246000fd5b60200260200101818152505060006001835161239d91906136dd565b90505b801561248d5760008061240c87866123b96001876136dd565b815181106123d757634e487b7160e01b600052603260045260246000fd5b60200260200101518786815181106123ff57634e487b7160e01b600052603260045260246000fd5b6020026020010151612903565b9150915061244284848151811061243357634e487b7160e01b600052603260045260246000fd5b60200260200101518383612495565b8461244e6001866136dd565b8151811061246c57634e487b7160e01b600052603260045260246000fd5b60200260200101818152505050508080612485906136f4565b9150506123a0565b509392505050565b60008084116124b65760405162461bcd60e51b815260040161027990613469565b6000831180156124c65750600082115b6124e25760405162461bcd60e51b8152600401610279906135c0565b60006124fa6103e86124f4868861280b565b9061280b565b9050600061250e6103e56124f486896129dc565b905061251f600161222a838561369e565b9695505050505050565b600080841161254a5760405162461bcd60e51b815260040161027990613426565b60008311801561255a5750600082115b6125765760405162461bcd60e51b8152600401610279906135c0565b82612581858461280b565b6108cf919061369e565b600080846001600160a01b031663a9059cbb85856040516024016125b09291906132ab565b6040516020818303038152906040529060e01b6020820180516001600160e01b0383818316178352505050506040516125e991906131e7565b6000604051808303816000865af19150503d8060008114612626576040519150601f19603f3d011682016040523d82523d6000602084013e61262b565b606091505b50915091508180156126555750805115806126555750808060200190518101906126559190612e87565b610b145760405162461bcd60e51b81526004016102799061336d565b60606002825110156126955760405162461bcd60e51b8152600401610279906134b3565b815167ffffffffffffffff8111156126bd57634e487b7160e01b600052604160045260246000fd5b6040519080825280602002602001820160405280156126e6578160200160208202803683370190505b509050828160008151811061270b57634e487b7160e01b600052603260045260246000fd5b60200260200101818152505060005b6001835161272891906136dd565b81101561248d5760008061278a8786858151811061275657634e487b7160e01b600052603260045260246000fd5b60200260200101518786600161276c9190613686565b815181106123ff57634e487b7160e01b600052603260045260246000fd5b915091506127c08484815181106127b157634e487b7160e01b600052603260045260246000fd5b602002602001015183836121ad565b846127cc856001613686565b815181106127ea57634e487b7160e01b600052603260045260246000fd5b602002602001018181525050505080806128039061370b565b91505061271a565b600081158061282f5750828261282181836136be565b925061282d908361369e565b145b610b475760405162461bcd60e51b8152600401610279906133ca565b6000826128588382613686565b9150811015610b475760405162461bcd60e51b8152600401610279906133f8565b600080826001600160a01b0316846001600160a01b031614156128ae5760405162461bcd60e51b815260040161027990613533565b826001600160a01b0316846001600160a01b0316106128ce5782846128d1565b83835b90925090506001600160a01b0382166128fc5760405162461bcd60e51b815260040161027990613606565b9250929050565b60008060006129128585612879565b50905060008061292388888861226b565b6001600160a01b0316630902f1ac6040518163ffffffff1660e01b815260040160606040518083038186803b15801561295b57600080fd5b505afa15801561296f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129939190612ea3565b506001600160701b031691506001600160701b03169150826001600160a01b0316876001600160a01b0316146129ca5780826129cd565b81815b90999098509650505050505050565b6000826129e983826136dd565b9150811115610b475760405162461bcd60e51b81526004016102799061333e565b600082601f830112612a1a578081fd5b8135602067ffffffffffffffff821115612a3657612a3661373c565b808202612a4482820161365c565b838152828101908684018388018501891015612a5e578687fd5b8693505b85841015612a89578035612a7581613752565b835260019390930192918401918401612a62565b50979650505050505050565b60008083601f840112612aa6578182fd5b50813567ffffffffffffffff811115612abd578182fd5b60208301915083602080830285010111156128fc57600080fd5b60008083601f840112612ae8578182fd5b50813567ffffffffffffffff811115612aff578182fd5b6020830191508360208285010111156128fc57600080fd5b80516001600160701b0381168114612b2e57600080fd5b919050565b803560ff81168114612b2e57600080fd5b600060208284031215612b55578081fd5b8135612b6081613752565b9392505050565b600060208284031215612b78578081fd5b8151612b6081613752565b60008060008060008060008060a0898b031215612b9e578384fd5b8835612ba981613752565b97506020890135612bb981613752565b9650604089013567ffffffffffffffff80821115612bd5578586fd5b612be18c838d01612a95565b909850965060608b0135915080821115612bf9578586fd5b612c058c838d01612a95565b909650945060808b0135915080821115612c1d578384fd5b50612c2a8b828c01612ad7565b999c989b5096995094979396929594505050565b60008060008060008060a08789031215612c56578182fd5b8635612c6181613752565b95506020870135612c7181613752565b94506040870135935060608701359250608087013567ffffffffffffffff811115612c9a578283fd5b612ca689828a01612ad7565b979a9699509497509295939492505050565b600080600060608486031215612ccc578283fd5b8335612cd781613752565b9250602084013591506040840135612cee81613752565b809150509250925092565b600080600060608486031215612d0d578283fd5b8335612d1881613752565b95602085013595506040909401359392505050565b60008060008060008060c08789031215612d45578182fd5b8635612d5081613752565b95506020870135945060408701359350606087013592506080870135612d7581613752565b8092505060a087013590509295509295509295565b6000806000806000806000806000806101408b8d031215612da9578384fd5b8a35612db481613752565b995060208b0135985060408b0135975060608b0135965060808b0135612dd981613752565b955060a08b0135945060c08b0135612df08161376a565b9350612dfe60e08c01612b33565b92506101008b013591506101208b013590509295989b9194979a5092959850565b600080600080600080600060e0888a031215612e39578081fd5b8735612e4481613752565b96506020880135955060408801359450606088013593506080880135925060a0880135612e7081613752565b8092505060c0880135905092959891949750929550565b600060208284031215612e98578081fd5b8151612b608161376a565b600080600060608486031215612eb7578081fd5b612ec084612b17565b9250612ece60208501612b17565b9150604084015163ffffffff81168114612cee578182fd5b600060208284031215612ef7578081fd5b5035919050565b600060208284031215612f0f578081fd5b5051919050565b60008060408385031215612f28578182fd5b82359150602083013567ffffffffffffffff811115612f45578182fd5b612f5185828601612a0a565b9150509250929050565b60008060008060808587031215612f70578182fd5b84359350602085013567ffffffffffffffff811115612f8d578283fd5b612f9987828801612a0a565b9350506040850135612faa81613752565b9396929550929360600135925050565b60008060408385031215612fcc578182fd5b8235915060208084013567ffffffffffffffff80821115612feb578384fd5b818601915086601f830112612ffe578384fd5b8135818111156130105761301061373c565b613022601f8201601f1916850161365c565b91508082528784828501011115613037578485fd5b8084840185840137810190920192909252919491935090915050565b60008060408385031215613065578182fd5b50508035926020909101359150565b600080600080600060a0868803121561308b578283fd5b8535945060208601359350604086013567ffffffffffffffff8111156130af578384fd5b6130bb88828901612a0a565b93505060608601356130cc81613752565b949793965091946080013592915050565b6000806000606084860312156130f1578081fd5b505081359360208301359350604090920135919050565b600080600080600060a0868803121561311f578283fd5b85359450602086013593506040860135925060608601356130cc81613752565b60008060008060008060008060006101208a8c03121561315d578283fd5b8935985060208a0135975060408a0135965060608a013561317d81613752565b955060808a0135945060a08a01356131948161376a565b93506131a260c08b01612b33565b925060e08a013591506101008a013590509295985092959850929598565b6bffffffffffffffffffffffff19606093841b811682529190921b16601482015260280190565b60008251815b8181101561320757602081860181015185830152016131ed565b818111156132155782828501525b509190910192915050565b6001600160f81b0319815260609290921b6bffffffffffffffffffffffff1916600183015260158201527f1974917c1e01e6369c1b45f631eae6a71d24cb5108c460cc7f0b1c608b3a7c94603582015260550190565b6001600160a01b0391909116815260200190565b6001600160a01b039390931683529015156020830152604082015260600190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b039390931683526020830191909152604082015260600190565b6020808252825182820181905260009190848201906040850190845b8181101561331d57835183529284019291840191600101613301565b50909695505050505050565b6001600160e01b031991909116815260200190565b60208082526015908201527464732d6d6174682d7375622d756e646572666c6f7760581b604082015260600190565b6020808252601f908201527f5472616e7366657248656c7065723a205452414e534645525f4641494c454400604082015260600190565b6020808252600c908201526b155b985d5d1a1bdc9a5e995960a21b604082015260600190565b60208082526014908201527364732d6d6174682d6d756c2d6f766572666c6f7760601b604082015260600190565b60208082526014908201527364732d6d6174682d6164642d6f766572666c6f7760601b604082015260600190565b60208082526023908201527f4d6174657269614c6962726172793a20494e53554646494349454e545f414d4f60408201526215539560ea1b606082015260800190565b6020808252602a908201527f4d6174657269614c6962726172793a20494e53554646494349454e545f4f555460408201526914155517d05353d5539560b21b606082015260800190565b6020808252601c908201527f4d6174657269614c6962726172793a20494e56414c49445f5041544800000000604082015260600190565b60208082526029908201527f4d6174657269614c6962726172793a20494e53554646494349454e545f494e50604082015268155517d05353d5539560ba1b606082015260800190565b60208082526023908201527f4d6174657269614c6962726172793a204944454e544943414c5f41444452455360408201526253455360e81b606082015260800190565b6020808252602a908201527f4f6e6c79204574684974656d2063616e2073656e642045544820746f207468696040820152691cc818dbdb9d1c9858dd60b21b606082015260800190565b60208082526026908201527f4d6174657269614c6962726172793a20494e53554646494349454e545f4c495160408201526555494449545960d01b606082015260800190565b6020808252601c908201527f4d6174657269614c6962726172793a205a45524f5f4144445245535300000000604082015260600190565b90815260200190565b9283526020830191909152604082015260600190565b60405181810167ffffffffffffffff8111828210171561367e5761367e61373c565b604052919050565b6000821982111561369957613699613726565b500190565b6000826136b957634e487b7160e01b81526012600452602481fd5b500490565b60008160001904831182151516156136d8576136d8613726565b500290565b6000828210156136ef576136ef613726565b500390565b60008161370357613703613726565b506000190190565b600060001982141561371f5761371f613726565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b038116811461376757600080fd5b50565b801515811461376757600080fdfea2646970667358221220b3b8ef5e113b91bb36e96a9cac93a50966aa5f577408c39530aba3b8e91db4ed64736f6c63430008000033000000000000000000000000b498a69ff7b9a73c58491d564fc6a462b259c8600000000000000000000000007c974104df9dd7fb91205ab3d66d15aff1049de8000000000000000000000000c46abe9805c54107114e04bdb30f189434cce2d30000000000000000000000002e203d0ccd2f372b6509febda9343054f146ae56000000000000000000000000a85844dd423cdb2b6bea603e1768f9587d662ab8000000000000000000000000c97587c6edac9d298a4ca2fdffe28f4f6b10d480000000000000000000000000f644dd45c854bed5924e95eb0ab68e38d5be66da

Deployed Bytecode

0x60806040526004361061024a5760003560e01c80639187aaca11610139578063be745fff116100b6578063d7565a0c1161007a578063d7565a0c1461069d578063ee1fae3c146106bd578063f23a6e61146106dd578063f46901ed146106fd578063f4734b0c1461071d578063fb3bdb411461049c57610284565b8063be745fff1461061e578063c45a015514610633578063cafd47df14610648578063cbd99d031461065d578063d06ca61f1461067d57610284565b8063ad615dec116100fd578063ad615dec1461057e578063b6ec79fe1461059e578063b9bdb4ef146105be578063bb8a88bb146105de578063bc197c81146105f157610284565b80639187aaca146104cf57806396c92f5e146104fe5780639c82f2a41461051e5780639e6371ba1461053e5780639f1840111461055e57610284565b806347883c37116101c7578063678700e01161018b578063678700e01461045c578063781cef2a1461047c5780637ff36ab51461049c57806385f8c259146104af5780638803dbee146103c357610284565b806347883c37146103e35780634a25d94a1461031f5780634eb9b5921461041257806355809f9f146104275780635bb478081461043c57610284565b80631b5f58c81161020e5780631b5f58c81461033f5780631f00ca741461036157806323ae84011461038e5780632b3297f9146103ae57806338ed1739146103c357610284565b806302af0fb514610289578063054d50d4146102a9578063104870fd146102df57806311f38472146102ff57806318cbafe51461031f57610284565b36610284576005546001600160a01b031633146102825760405162461bcd60e51b815260040161027990613576565b60405180910390fd5b005b600080fd5b34801561029557600080fd5b506102826102a4366004612ee6565b610732565b3480156102b557600080fd5b506102c96102c43660046130dd565b6108c2565b6040516102d6919061363d565b60405180910390f35b3480156102eb57600080fd5b506102826102fa366004612d8a565b6108d7565b34801561030b57600080fd5b5061028261031a366004612cf9565b6108f8565b34801561032b57600080fd5b5061028261033a366004613074565b610aff565b34801561034b57600080fd5b50610354610b1b565b6040516102d69190613276565b34801561036d57600080fd5b5061038161037c366004612f16565b610b2a565b6040516102d691906132e5565b34801561039a57600080fd5b506102826103a9366004612b44565b610b4d565b3480156103ba57600080fd5b50610354610cfa565b3480156103cf57600080fd5b506103816103de366004613074565b610d09565b3480156103ef57600080fd5b506104036103fe366004612b44565b610d2a565b6040516102d69392919061328a565b34801561041e57600080fd5b50610354610e48565b34801561043357600080fd5b50610354610e57565b34801561044857600080fd5b50610282610457366004612b44565b610e66565b34801561046857600080fd5b5061028261047736600461313f565b611013565b34801561048857600080fd5b50610282610497366004612b44565b611033565b6102826104aa366004612f5b565b6111e0565b3480156104bb57600080fd5b506102c96104ca3660046130dd565b6111fb565b3480156104db57600080fd5b506104ef6104ea366004612e1f565b611208565b6040516102d693929190613646565b34801561050a57600080fd5b50610282610519366004612d2d565b611231565b34801561052a57600080fd5b50610282610539366004612b44565b61124e565b34801561054a57600080fd5b50610282610559366004612b44565b6113fb565b34801561056a57600080fd5b50610282610579366004612b44565b6115e3565b34801561058a57600080fd5b506102c96105993660046130dd565b611790565b3480156105aa57600080fd5b506102826105b9366004612cb8565b61179d565b3480156105ca57600080fd5b506102826105d9366004613053565b611938565b6104ef6105ec366004613108565b611b81565b3480156105fd57600080fd5b5061061161060c366004612b83565b611ba8565b6040516102d69190613329565b34801561062a57600080fd5b506102c9611baf565b34801561063f57600080fd5b50610354611bb5565b34801561065457600080fd5b50610354611bc4565b34801561066957600080fd5b50610282610678366004612b44565b611bd3565b34801561068957600080fd5b50610381610698366004612f16565b611d80565b3480156106a957600080fd5b506102826106b8366004612b44565b611d9a565b3480156106c957600080fd5b506102826106d8366004613108565b611f47565b3480156106e957600080fd5b506106116106f8366004612c3e565b611f5c565b34801561070957600080fd5b50610282610718366004612b44565b611fe4565b34801561072957600080fd5b5061035461219e565b60008054906101000a90046001600160a01b03166001600160a01b031663ec5568896040518163ffffffff1660e01b815260040160206040518083038186803b15801561077e57600080fd5b505afa158015610792573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107b69190612b67565b6001600160a01b0316636701586a6040518163ffffffff1660e01b815260040160206040518083038186803b1580156107ee57600080fd5b505afa158015610802573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108269190612b67565b6001600160a01b0316633191d332336040518263ffffffff1660e01b81526004016108519190613276565b60206040518083038186803b15801561086957600080fd5b505afa15801561087d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108a19190612e87565b6108bd5760405162461bcd60e51b8152600401610279906133a4565b600755565b60006108cf8484846121ad565b949350505050565b6003546108ec906001600160a01b0316612247565b50505050505050505050565b60008054906101000a90046001600160a01b03166001600160a01b031663ec5568896040518163ffffffff1660e01b815260040160206040518083038186803b15801561094457600080fd5b505afa158015610958573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061097c9190612b67565b6001600160a01b0316636701586a6040518163ffffffff1660e01b815260040160206040518083038186803b1580156109b457600080fd5b505afa1580156109c8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906109ec9190612b67565b6001600160a01b0316633191d332336040518263ffffffff1660e01b8152600401610a179190613276565b60206040518083038186803b158015610a2f57600080fd5b505afa158015610a43573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a679190612e87565b610a835760405162461bcd60e51b8152600401610279906133a4565b6004546006546001600160a01b03918216916311f3847291610aa8918491168761226b565b84846040518463ffffffff1660e01b8152600401610ac8939291906132c4565b600060405180830381600087803b158015610ae257600080fd5b505af1158015610af6573d6000803e3d6000fd5b50505050505050565b600154610b14906001600160a01b0316612247565b5050505050565b6005546001600160a01b031681565b600454606090610b44906001600160a01b031684846122db565b90505b92915050565b60008054906101000a90046001600160a01b03166001600160a01b031663ec5568896040518163ffffffff1660e01b815260040160206040518083038186803b158015610b9957600080fd5b505afa158015610bad573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bd19190612b67565b6001600160a01b0316636701586a6040518163ffffffff1660e01b815260040160206040518083038186803b158015610c0957600080fd5b505afa158015610c1d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610c419190612b67565b6001600160a01b0316633191d332336040518263ffffffff1660e01b8152600401610c6c9190613276565b60206040518083038186803b158015610c8457600080fd5b505afa158015610c98573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610cbc9190612e87565b610cd85760405162461bcd60e51b8152600401610279906133a4565b600680546001600160a01b0319166001600160a01b0392909216919091179055565b6001546001600160a01b031681565b600154606090610d21906001600160a01b0316612247565b95945050505050565b600080806001600160a01b038416610d4a57506000915081905080610e41565b836001600160a01b0316631836b97d6040518163ffffffff1660e01b815260040160206040518083038186803b158015610d8357600080fd5b505afa925050508015610db3575060408051601f3d908101601f19168201909252610db091810190612b67565b60015b610dc557506000915081905080610e41565b806001866001600160a01b031663d4d5a06d6040518163ffffffff1660e01b815260040160206040518083038186803b158015610e0157600080fd5b505afa158015610e15573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e399190612efe565b935093509350505b9193909250565b6000546001600160a01b031681565b6002546001600160a01b031681565b60008054906101000a90046001600160a01b03166001600160a01b031663ec5568896040518163ffffffff1660e01b815260040160206040518083038186803b158015610eb257600080fd5b505afa158015610ec6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610eea9190612b67565b6001600160a01b0316636701586a6040518163ffffffff1660e01b815260040160206040518083038186803b158015610f2257600080fd5b505afa158015610f36573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610f5a9190612b67565b6001600160a01b0316633191d332336040518263ffffffff1660e01b8152600401610f859190613276565b60206040518083038186803b158015610f9d57600080fd5b505afa158015610fb1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610fd59190612e87565b610ff15760405162461bcd60e51b8152600401610279906133a4565b600480546001600160a01b0319166001600160a01b0392909216919091179055565b600354611028906001600160a01b0316612247565b505050505050505050565b60008054906101000a90046001600160a01b03166001600160a01b031663ec5568896040518163ffffffff1660e01b815260040160206040518083038186803b15801561107f57600080fd5b505afa158015611093573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906110b79190612b67565b6001600160a01b0316636701586a6040518163ffffffff1660e01b815260040160206040518083038186803b1580156110ef57600080fd5b505afa158015611103573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111279190612b67565b6001600160a01b0316633191d332336040518263ffffffff1660e01b81526004016111529190613276565b60206040518083038186803b15801561116a57600080fd5b505afa15801561117e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906111a29190612e87565b6111be5760405162461bcd60e51b8152600401610279906133a4565b600380546001600160a01b0319166001600160a01b0392909216919091179055565b6001546111f5906001600160a01b0316612247565b50505050565b60006108cf848484612495565b60025460009081908190611224906001600160a01b0316612247565b9750975097945050505050565b600354611246906001600160a01b0316612247565b505050505050565b60008054906101000a90046001600160a01b03166001600160a01b031663ec5568896040518163ffffffff1660e01b815260040160206040518083038186803b15801561129a57600080fd5b505afa1580156112ae573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906112d29190612b67565b6001600160a01b0316636701586a6040518163ffffffff1660e01b815260040160206040518083038186803b15801561130a57600080fd5b505afa15801561131e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113429190612b67565b6001600160a01b0316633191d332336040518263ffffffff1660e01b815260040161136d9190613276565b60206040518083038186803b15801561138557600080fd5b505afa158015611399573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906113bd9190612e87565b6113d95760405162461bcd60e51b8152600401610279906133a4565b600180546001600160a01b0319166001600160a01b0392909216919091179055565b60008054906101000a90046001600160a01b03166001600160a01b031663ec5568896040518163ffffffff1660e01b815260040160206040518083038186803b15801561144757600080fd5b505afa15801561145b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061147f9190612b67565b6001600160a01b0316636701586a6040518163ffffffff1660e01b815260040160206040518083038186803b1580156114b757600080fd5b505afa1580156114cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906114ef9190612b67565b6001600160a01b0316633191d332336040518263ffffffff1660e01b815260040161151a9190613276565b60206040518083038186803b15801561153257600080fd5b505afa158015611546573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061156a9190612e87565b6115865760405162461bcd60e51b8152600401610279906133a4565b6004805460405163f2fde38b60e01b81526001600160a01b039091169163f2fde38b916115b591859101613276565b600060405180830381600087803b1580156115cf57600080fd5b505af1158015610b14573d6000803e3d6000fd5b60008054906101000a90046001600160a01b03166001600160a01b031663ec5568896040518163ffffffff1660e01b815260040160206040518083038186803b15801561162f57600080fd5b505afa158015611643573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116679190612b67565b6001600160a01b0316636701586a6040518163ffffffff1660e01b815260040160206040518083038186803b15801561169f57600080fd5b505afa1580156116b3573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116d79190612b67565b6001600160a01b0316633191d332336040518263ffffffff1660e01b81526004016117029190613276565b60206040518083038186803b15801561171a57600080fd5b505afa15801561172e573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906117529190612e87565b61176e5760405162461bcd60e51b8152600401610279906133a4565b600280546001600160a01b0319166001600160a01b0392909216919091179055565b60006108cf848484612529565b60008054906101000a90046001600160a01b03166001600160a01b031663ec5568896040518163ffffffff1660e01b815260040160206040518083038186803b1580156117e957600080fd5b505afa1580156117fd573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118219190612b67565b6001600160a01b0316636701586a6040518163ffffffff1660e01b815260040160206040518083038186803b15801561185957600080fd5b505afa15801561186d573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906118919190612b67565b6001600160a01b0316633191d332336040518263ffffffff1660e01b81526004016118bc9190613276565b60206040518083038186803b1580156118d457600080fd5b505afa1580156118e8573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061190c9190612e87565b6119285760405162461bcd60e51b8152600401610279906133a4565b61193383828461258b565b505050565b60008054906101000a90046001600160a01b03166001600160a01b031663ec5568896040518163ffffffff1660e01b815260040160206040518083038186803b15801561198457600080fd5b505afa158015611998573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906119bc9190612b67565b6001600160a01b0316636701586a6040518163ffffffff1660e01b815260040160206040518083038186803b1580156119f457600080fd5b505afa158015611a08573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611a2c9190612b67565b6001600160a01b0316633191d332336040518263ffffffff1660e01b8152600401611a579190613276565b60206040518083038186803b158015611a6f57600080fd5b505afa158015611a83573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611aa79190612e87565b611ac35760405162461bcd60e51b8152600401610279906133a4565b60048054604051633ca1b37360e11b81526001600160a01b039091169163794366e691611af29186910161363d565b600060405180830381600087803b158015611b0c57600080fd5b505af1158015611b20573d6000803e3d6000fd5b50506004805460405163334dc4f360e01b81526001600160a01b03909116935063334dc4f39250611b539185910161363d565b600060405180830381600087803b158015611b6d57600080fd5b505af1158015611246573d6000803e3d6000fd5b60025460009081908190611b9d906001600160a01b0316612247565b955095509592505050565b6000806000fd5b60075481565b6004546001600160a01b031681565b6003546001600160a01b031681565b60008054906101000a90046001600160a01b03166001600160a01b031663ec5568896040518163ffffffff1660e01b815260040160206040518083038186803b158015611c1f57600080fd5b505afa158015611c33573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611c579190612b67565b6001600160a01b0316636701586a6040518163ffffffff1660e01b815260040160206040518083038186803b158015611c8f57600080fd5b505afa158015611ca3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611cc79190612b67565b6001600160a01b0316633191d332336040518263ffffffff1660e01b8152600401611cf29190613276565b60206040518083038186803b158015611d0a57600080fd5b505afa158015611d1e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611d429190612e87565b611d5e5760405162461bcd60e51b8152600401610279906133a4565b600080546001600160a01b0319166001600160a01b0392909216919091179055565b600454606090610b44906001600160a01b03168484612671565b60008054906101000a90046001600160a01b03166001600160a01b031663ec5568896040518163ffffffff1660e01b815260040160206040518083038186803b158015611de657600080fd5b505afa158015611dfa573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e1e9190612b67565b6001600160a01b0316636701586a6040518163ffffffff1660e01b815260040160206040518083038186803b158015611e5657600080fd5b505afa158015611e6a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611e8e9190612b67565b6001600160a01b0316633191d332336040518263ffffffff1660e01b8152600401611eb99190613276565b60206040518083038186803b158015611ed157600080fd5b505afa158015611ee5573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611f099190612e87565b611f255760405162461bcd60e51b8152600401610279906133a4565b600580546001600160a01b0319166001600160a01b0392909216919091179055565b600354610b14906001600160a01b0316612247565b600080611f6b83850185612fba565b5090508060011415611f9157600254611f8c906001600160a01b0316612247565b611fd0565b8060021480611fa05750806003145b80611fab5750806004145b80611fb65750806005145b1561028457600154611f8c906001600160a01b0316612247565b5063f23a6e6160e01b979650505050505050565b60008054906101000a90046001600160a01b03166001600160a01b031663ec5568896040518163ffffffff1660e01b815260040160206040518083038186803b15801561203057600080fd5b505afa158015612044573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120689190612b67565b6001600160a01b0316636701586a6040518163ffffffff1660e01b815260040160206040518083038186803b1580156120a057600080fd5b505afa1580156120b4573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906120d89190612b67565b6001600160a01b0316633191d332336040518263ffffffff1660e01b81526004016121039190613276565b60206040518083038186803b15801561211b57600080fd5b505afa15801561212f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906121539190612e87565b61216f5760405162461bcd60e51b8152600401610279906133a4565b6004805460405163f46901ed60e01b81526001600160a01b039091169163f46901ed916115b591859101613276565b6006546001600160a01b031681565b60008084116121ce5760405162461bcd60e51b8152600401610279906134ea565b6000831180156121de5750600082115b6121fa5760405162461bcd60e51b8152600401610279906135c0565b6000612208856103e561280b565b90506000612216828561280b565b905060006122308361222a886103e861280b565b9061284b565b905061223c818361369e565b979650505050505050565b3660008037600080366000845af43d6000803e808015612266573d6000f35b3d6000fd5b600080600061227a8585612879565b915091508582826040516020016122929291906131c0565b604051602081830303815290604052805190602001206040516020016122b9929190613220565b60408051601f1981840301815291905280516020909101209695505050505050565b60606002825110156122ff5760405162461bcd60e51b8152600401610279906134b3565b815167ffffffffffffffff81111561232757634e487b7160e01b600052604160045260246000fd5b604051908082528060200260200182016040528015612350578160200160208202803683370190505b50905082816001835161236391906136dd565b8151811061238157634e487b7160e01b600052603260045260246000fd5b60200260200101818152505060006001835161239d91906136dd565b90505b801561248d5760008061240c87866123b96001876136dd565b815181106123d757634e487b7160e01b600052603260045260246000fd5b60200260200101518786815181106123ff57634e487b7160e01b600052603260045260246000fd5b6020026020010151612903565b9150915061244284848151811061243357634e487b7160e01b600052603260045260246000fd5b60200260200101518383612495565b8461244e6001866136dd565b8151811061246c57634e487b7160e01b600052603260045260246000fd5b60200260200101818152505050508080612485906136f4565b9150506123a0565b509392505050565b60008084116124b65760405162461bcd60e51b815260040161027990613469565b6000831180156124c65750600082115b6124e25760405162461bcd60e51b8152600401610279906135c0565b60006124fa6103e86124f4868861280b565b9061280b565b9050600061250e6103e56124f486896129dc565b905061251f600161222a838561369e565b9695505050505050565b600080841161254a5760405162461bcd60e51b815260040161027990613426565b60008311801561255a5750600082115b6125765760405162461bcd60e51b8152600401610279906135c0565b82612581858461280b565b6108cf919061369e565b600080846001600160a01b031663a9059cbb85856040516024016125b09291906132ab565b6040516020818303038152906040529060e01b6020820180516001600160e01b0383818316178352505050506040516125e991906131e7565b6000604051808303816000865af19150503d8060008114612626576040519150601f19603f3d011682016040523d82523d6000602084013e61262b565b606091505b50915091508180156126555750805115806126555750808060200190518101906126559190612e87565b610b145760405162461bcd60e51b81526004016102799061336d565b60606002825110156126955760405162461bcd60e51b8152600401610279906134b3565b815167ffffffffffffffff8111156126bd57634e487b7160e01b600052604160045260246000fd5b6040519080825280602002602001820160405280156126e6578160200160208202803683370190505b509050828160008151811061270b57634e487b7160e01b600052603260045260246000fd5b60200260200101818152505060005b6001835161272891906136dd565b81101561248d5760008061278a8786858151811061275657634e487b7160e01b600052603260045260246000fd5b60200260200101518786600161276c9190613686565b815181106123ff57634e487b7160e01b600052603260045260246000fd5b915091506127c08484815181106127b157634e487b7160e01b600052603260045260246000fd5b602002602001015183836121ad565b846127cc856001613686565b815181106127ea57634e487b7160e01b600052603260045260246000fd5b602002602001018181525050505080806128039061370b565b91505061271a565b600081158061282f5750828261282181836136be565b925061282d908361369e565b145b610b475760405162461bcd60e51b8152600401610279906133ca565b6000826128588382613686565b9150811015610b475760405162461bcd60e51b8152600401610279906133f8565b600080826001600160a01b0316846001600160a01b031614156128ae5760405162461bcd60e51b815260040161027990613533565b826001600160a01b0316846001600160a01b0316106128ce5782846128d1565b83835b90925090506001600160a01b0382166128fc5760405162461bcd60e51b815260040161027990613606565b9250929050565b60008060006129128585612879565b50905060008061292388888861226b565b6001600160a01b0316630902f1ac6040518163ffffffff1660e01b815260040160606040518083038186803b15801561295b57600080fd5b505afa15801561296f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906129939190612ea3565b506001600160701b031691506001600160701b03169150826001600160a01b0316876001600160a01b0316146129ca5780826129cd565b81815b90999098509650505050505050565b6000826129e983826136dd565b9150811115610b475760405162461bcd60e51b81526004016102799061333e565b600082601f830112612a1a578081fd5b8135602067ffffffffffffffff821115612a3657612a3661373c565b808202612a4482820161365c565b838152828101908684018388018501891015612a5e578687fd5b8693505b85841015612a89578035612a7581613752565b835260019390930192918401918401612a62565b50979650505050505050565b60008083601f840112612aa6578182fd5b50813567ffffffffffffffff811115612abd578182fd5b60208301915083602080830285010111156128fc57600080fd5b60008083601f840112612ae8578182fd5b50813567ffffffffffffffff811115612aff578182fd5b6020830191508360208285010111156128fc57600080fd5b80516001600160701b0381168114612b2e57600080fd5b919050565b803560ff81168114612b2e57600080fd5b600060208284031215612b55578081fd5b8135612b6081613752565b9392505050565b600060208284031215612b78578081fd5b8151612b6081613752565b60008060008060008060008060a0898b031215612b9e578384fd5b8835612ba981613752565b97506020890135612bb981613752565b9650604089013567ffffffffffffffff80821115612bd5578586fd5b612be18c838d01612a95565b909850965060608b0135915080821115612bf9578586fd5b612c058c838d01612a95565b909650945060808b0135915080821115612c1d578384fd5b50612c2a8b828c01612ad7565b999c989b5096995094979396929594505050565b60008060008060008060a08789031215612c56578182fd5b8635612c6181613752565b95506020870135612c7181613752565b94506040870135935060608701359250608087013567ffffffffffffffff811115612c9a578283fd5b612ca689828a01612ad7565b979a9699509497509295939492505050565b600080600060608486031215612ccc578283fd5b8335612cd781613752565b9250602084013591506040840135612cee81613752565b809150509250925092565b600080600060608486031215612d0d578283fd5b8335612d1881613752565b95602085013595506040909401359392505050565b60008060008060008060c08789031215612d45578182fd5b8635612d5081613752565b95506020870135945060408701359350606087013592506080870135612d7581613752565b8092505060a087013590509295509295509295565b6000806000806000806000806000806101408b8d031215612da9578384fd5b8a35612db481613752565b995060208b0135985060408b0135975060608b0135965060808b0135612dd981613752565b955060a08b0135945060c08b0135612df08161376a565b9350612dfe60e08c01612b33565b92506101008b013591506101208b013590509295989b9194979a5092959850565b600080600080600080600060e0888a031215612e39578081fd5b8735612e4481613752565b96506020880135955060408801359450606088013593506080880135925060a0880135612e7081613752565b8092505060c0880135905092959891949750929550565b600060208284031215612e98578081fd5b8151612b608161376a565b600080600060608486031215612eb7578081fd5b612ec084612b17565b9250612ece60208501612b17565b9150604084015163ffffffff81168114612cee578182fd5b600060208284031215612ef7578081fd5b5035919050565b600060208284031215612f0f578081fd5b5051919050565b60008060408385031215612f28578182fd5b82359150602083013567ffffffffffffffff811115612f45578182fd5b612f5185828601612a0a565b9150509250929050565b60008060008060808587031215612f70578182fd5b84359350602085013567ffffffffffffffff811115612f8d578283fd5b612f9987828801612a0a565b9350506040850135612faa81613752565b9396929550929360600135925050565b60008060408385031215612fcc578182fd5b8235915060208084013567ffffffffffffffff80821115612feb578384fd5b818601915086601f830112612ffe578384fd5b8135818111156130105761301061373c565b613022601f8201601f1916850161365c565b91508082528784828501011115613037578485fd5b8084840185840137810190920192909252919491935090915050565b60008060408385031215613065578182fd5b50508035926020909101359150565b600080600080600060a0868803121561308b578283fd5b8535945060208601359350604086013567ffffffffffffffff8111156130af578384fd5b6130bb88828901612a0a565b93505060608601356130cc81613752565b949793965091946080013592915050565b6000806000606084860312156130f1578081fd5b505081359360208301359350604090920135919050565b600080600080600060a0868803121561311f578283fd5b85359450602086013593506040860135925060608601356130cc81613752565b60008060008060008060008060006101208a8c03121561315d578283fd5b8935985060208a0135975060408a0135965060608a013561317d81613752565b955060808a0135945060a08a01356131948161376a565b93506131a260c08b01612b33565b925060e08a013591506101008a013590509295985092959850929598565b6bffffffffffffffffffffffff19606093841b811682529190921b16601482015260280190565b60008251815b8181101561320757602081860181015185830152016131ed565b818111156132155782828501525b509190910192915050565b6001600160f81b0319815260609290921b6bffffffffffffffffffffffff1916600183015260158201527f1974917c1e01e6369c1b45f631eae6a71d24cb5108c460cc7f0b1c608b3a7c94603582015260550190565b6001600160a01b0391909116815260200190565b6001600160a01b039390931683529015156020830152604082015260600190565b6001600160a01b03929092168252602082015260400190565b6001600160a01b039390931683526020830191909152604082015260600190565b6020808252825182820181905260009190848201906040850190845b8181101561331d57835183529284019291840191600101613301565b50909695505050505050565b6001600160e01b031991909116815260200190565b60208082526015908201527464732d6d6174682d7375622d756e646572666c6f7760581b604082015260600190565b6020808252601f908201527f5472616e7366657248656c7065723a205452414e534645525f4641494c454400604082015260600190565b6020808252600c908201526b155b985d5d1a1bdc9a5e995960a21b604082015260600190565b60208082526014908201527364732d6d6174682d6d756c2d6f766572666c6f7760601b604082015260600190565b60208082526014908201527364732d6d6174682d6164642d6f766572666c6f7760601b604082015260600190565b60208082526023908201527f4d6174657269614c6962726172793a20494e53554646494349454e545f414d4f60408201526215539560ea1b606082015260800190565b6020808252602a908201527f4d6174657269614c6962726172793a20494e53554646494349454e545f4f555460408201526914155517d05353d5539560b21b606082015260800190565b6020808252601c908201527f4d6174657269614c6962726172793a20494e56414c49445f5041544800000000604082015260600190565b60208082526029908201527f4d6174657269614c6962726172793a20494e53554646494349454e545f494e50604082015268155517d05353d5539560ba1b606082015260800190565b60208082526023908201527f4d6174657269614c6962726172793a204944454e544943414c5f41444452455360408201526253455360e81b606082015260800190565b6020808252602a908201527f4f6e6c79204574684974656d2063616e2073656e642045544820746f207468696040820152691cc818dbdb9d1c9858dd60b21b606082015260800190565b60208082526026908201527f4d6174657269614c6962726172793a20494e53554646494349454e545f4c495160408201526555494449545960d01b606082015260800190565b6020808252601c908201527f4d6174657269614c6962726172793a205a45524f5f4144445245535300000000604082015260600190565b90815260200190565b9283526020830191909152604082015260600190565b60405181810167ffffffffffffffff8111828210171561367e5761367e61373c565b604052919050565b6000821982111561369957613699613726565b500190565b6000826136b957634e487b7160e01b81526012600452602481fd5b500490565b60008160001904831182151516156136d8576136d8613726565b500290565b6000828210156136ef576136ef613726565b500390565b60008161370357613703613726565b506000190190565b600060001982141561371f5761371f613726565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052604160045260246000fd5b6001600160a01b038116811461376757600080fd5b50565b801515811461376757600080fdfea2646970667358221220b3b8ef5e113b91bb36e96a9cac93a50966aa5f577408c39530aba3b8e91db4ed64736f6c63430008000033

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

000000000000000000000000b498a69ff7b9a73c58491d564fc6a462b259c8600000000000000000000000007c974104df9dd7fb91205ab3d66d15aff1049de8000000000000000000000000c46abe9805c54107114e04bdb30f189434cce2d30000000000000000000000002e203d0ccd2f372b6509febda9343054f146ae56000000000000000000000000a85844dd423cdb2b6bea603e1768f9587d662ab8000000000000000000000000c97587c6edac9d298a4ca2fdffe28f4f6b10d480000000000000000000000000f644dd45c854bed5924e95eb0ab68e38d5be66da

-----Decoded View---------------
Arg [0] : initialFactory (address): 0xB498a69fF7b9a73C58491d564Fc6a462b259c860
Arg [1] : initialBridgeToken (address): 0x7C974104DF9dd7fb91205ab3D66d15AFf1049DE8
Arg [2] : initialErc20Wrapper (address): 0xC46abE9805c54107114e04bdb30F189434ccE2d3
Arg [3] : initialDoubleProxy (address): 0x2E203D0CcD2f372b6509FeBDA9343054F146ae56
Arg [4] : initialLiquidityAdder (address): 0xA85844DD423cdB2b6beA603e1768f9587d662aB8
Arg [5] : initialLiquidityRemover (address): 0xC97587c6edaC9D298A4cA2fDFFE28f4F6b10d480
Arg [6] : initialSwapper (address): 0xF644DD45c854BeD5924E95Eb0aB68E38d5BE66da

-----Encoded View---------------
7 Constructor Arguments found :
Arg [0] : 000000000000000000000000b498a69ff7b9a73c58491d564fc6a462b259c860
Arg [1] : 0000000000000000000000007c974104df9dd7fb91205ab3d66d15aff1049de8
Arg [2] : 000000000000000000000000c46abe9805c54107114e04bdb30f189434cce2d3
Arg [3] : 0000000000000000000000002e203d0ccd2f372b6509febda9343054f146ae56
Arg [4] : 000000000000000000000000a85844dd423cdb2b6bea603e1768f9587d662ab8
Arg [5] : 000000000000000000000000c97587c6edac9d298a4ca2fdffe28f4f6b10d480
Arg [6] : 000000000000000000000000f644dd45c854bed5924e95eb0ab68e38d5be66da


Deployed Bytecode Sourcemap

894:11060:29:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;4267:12;;-1:-1:-1;;;;;4267:12:29;4245:10;:35;4237:90;;;;-1:-1:-1;;;4237:90:29;;;;;;;:::i;:::-;;;;;;;;;894:11060;;;;;2581:141;;;;;;;;;;-1:-1:-1;2581:141:29;;;;;:::i;:::-;;:::i;10252:242::-;;;;;;;;;;-1:-1:-1;10252:242:29;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;7466:342;;;;;;;;;;-1:-1:-1;7466:342:29;;;;;:::i;:::-;;:::i;3203:249::-;;;;;;;;;;-1:-1:-1;3203:249:29;;;;;:::i;:::-;;:::i;9441:221::-;;;;;;;;;;-1:-1:-1;9441:221:29;;;;;:::i;:::-;;:::i;1180:44::-;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;10995:242::-;;;;;;;;;;-1:-1:-1;10995:242:29;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;2176:127::-;;;;;;;;;;-1:-1:-1;2176:127:29;;;;;:::i;:::-;;:::i;1007:31::-;;;;;;;;;;;;;:::i;8475:259::-;;;;;;;;;;-1:-1:-1;8475:259:29;;;;;:::i;:::-;;:::i;11361:591::-;;;;;;;;;;-1:-1:-1;11361:591:29;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;:::i;960:40::-;;;;;;;;;;;;;:::i;1044:38::-;;;;;;;;;;;;;:::i;2455:120::-;;;;;;;;;;-1:-1:-1;2455:120:29;;;;;:::i;:::-;;:::i;7814:322::-;;;;;;;;;;-1:-1:-1;7814:322:29;;;;;:::i;:::-;;:::i;2948:117::-;;;;;;;;;;-1:-1:-1;2948:117:29;;;;;:::i;:::-;;:::i;9005:203::-;;;;;;:::i;:::-;;:::i;10500:241::-;;;;;;;;;;-1:-1:-1;10500:241:29;;;;;:::i;:::-;;:::i;5839:431::-;;;;;;;;;;-1:-1:-1;5839:431:29;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;:::i;6972:252::-;;;;;;;;;;-1:-1:-1;6972:252:29;;;;;:::i;:::-;;:::i;2728:99::-;;;;;;;;;;-1:-1:-1;2728:99:29;;;;;:::i;:::-;;:::i;3071:126::-;;;;;;;;;;-1:-1:-1;3071:126:29;;;;;:::i;:::-;;:::i;2833:109::-;;;;;;;;;;-1:-1:-1;2833:109:29;;;;;:::i;:::-;;:::i;10028:218::-;;;;;;;;;;-1:-1:-1;10028:218:29;;;;;:::i;:::-;;:::i;3789:193::-;;;;;;;;;;-1:-1:-1;3789:193:29;;;;;:::i;:::-;;:::i;3458:188::-;;;;;;;;;;-1:-1:-1;3458:188:29;;;;;:::i;:::-;;:::i;6276:395::-;;;;;;:::i;:::-;;:::i;5358:217::-;;;;;;;;;;-1:-1:-1;5358:217:29;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;1270:42::-;;;;;;;;;;;;;:::i;1135:39::-;;;;;;;;;;;;;:::i;1088:40::-;;;;;;;;;;;;;:::i;2037:133::-;;;;;;;;;;-1:-1:-1;2037:133:29;;;;;:::i;:::-;;:::i;10747:242::-;;;;;;;;;;-1:-1:-1;10747:242:29;;;;;:::i;:::-;;:::i;2309:140::-;;;;;;;;;;-1:-1:-1;2309:140:29;;;;;:::i;:::-;;:::i;7230:230::-;;;;;;;;;;-1:-1:-1;7230:230:29;;;;;:::i;:::-;;:::i;4743:609::-;;;;;;;;;;-1:-1:-1;4743:609:29;;;;;:::i;:::-;;:::i;3652:99::-;;;;;;;;;;-1:-1:-1;3652:99:29;;;;;:::i;:::-;;:::i;1230:34::-;;;;;;;;;;;;;:::i;2581:141::-;4062:11;;;;;;;;-1:-1:-1;;;;;4062:11:29;-1:-1:-1;;;;;4062:17:29;;:19;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;4052:66:29;;:68;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;4025:122:29;;4148:10;4025:134;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;4017:159;;;;-1:-1:-1;;;4017:159:29;;;;;;;:::i;:::-;2675:18:::1;:40:::0;2581:141::o;10252:242::-;10391:17;10427:60;10455:8;10465:9;10476:10;10427:27;:60::i;:::-;10420:67;10252:242;-1:-1:-1;;;;10252:242:29:o;7466:342::-;7784:16;;7774:27;;-1:-1:-1;;;;;7784:16:29;7774:9;:27::i;:::-;7466:342;;;;;;;;;;:::o;3203:249::-;4062:11;;;;;;;;-1:-1:-1;;;;;4062:11:29;-1:-1:-1;;;;;4062:17:29;;:19;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;4052:66:29;;:68;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;4025:122:29;;4148:10;4025:134;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;4017:159;;;;-1:-1:-1;;;4017:159:29;;;;;;;:::i;:::-;3338:7:::1;::::0;3403:11:::1;::::0;-1:-1:-1;;;;;3338:7:29;;::::1;::::0;:15:::1;::::0;3354:69:::1;::::0;3338:7;;3403:11:::1;3417:5:::0;3354:22:::1;:69::i;:::-;3425:10;3437:7;3338:107;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;;;;;3203:249:::0;;;:::o;9441:221::-;9647:7;;9637:18;;-1:-1:-1;;;;;9647:7:29;9637:9;:18::i;:::-;9441:221;;;;;:::o;1180:44::-;;;-1:-1:-1;;;;;1180:44:29;;:::o;10995:242::-;11204:7;;11121:24;;11168:62;;-1:-1:-1;;;;;11204:7:29;11214:9;11225:4;11168:27;:62::i;:::-;11161:69;;10995:242;;;;;:::o;2176:127::-;4062:11;;;;;;;;-1:-1:-1;;;;;4062:11:29;-1:-1:-1;;;;;4062:17:29;;:19;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;4052:66:29;;:68;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;4025:122:29;;4148:10;4025:134;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;4017:159;;;;-1:-1:-1;;;4017:159:29;;;;;;;:::i;:::-;2260:11:::1;:36:::0;;-1:-1:-1;;;;;;2260:36:29::1;-1:-1:-1::0;;;;;2260:36:29;;;::::1;::::0;;;::::1;::::0;;2176:127::o;1007:31::-;;;-1:-1:-1;;;;;1007:31:29;;:::o;8475:259::-;8719:7;;8673:24;;8709:18;;-1:-1:-1;;;;;8719:7:29;8709:9;:18::i;:::-;8475:259;;;;;;;:::o;11361:591::-;11470:18;;;-1:-1:-1;;;;;11571:19:29;;11567:379;;-1:-1:-1;11622:1:29;;-1:-1:-1;11622:1:29;;-1:-1:-1;11622:1:29;11606:29;;11567:379;11701:5;-1:-1:-1;;;;;11670:51:29;;:53;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;11670:53:29;;;;;;;;-1:-1:-1;;11670:53:29;;;;;;;;;;;;:::i;:::-;;;11666:270;;-1:-1:-1;11908:1:29;;-1:-1:-1;11908:1:29;;-1:-1:-1;11908:1:29;11892:29;;11666:270;11782:13;11797:4;11834:5;-1:-1:-1;;;;;11803:46:29;;:48;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;11774:78;;;;;;;11666:270;11361:591;;;;;:::o;960:40::-;;;-1:-1:-1;;;;;960:40:29;;:::o;1044:38::-;;;-1:-1:-1;;;;;1044:38:29;;:::o;2455:120::-;4062:11;;;;;;;;-1:-1:-1;;;;;4062:11:29;-1:-1:-1;;;;;4062:17:29;;:19;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;4052:66:29;;:68;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;4025:122:29;;4148:10;4025:134;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;4017:159;;;;-1:-1:-1;;;4017:159:29;;;;;;;:::i;:::-;2531:7:::1;:37:::0;;-1:-1:-1;;;;;;2531:37:29::1;-1:-1:-1::0;;;;;2531:37:29;;;::::1;::::0;;;::::1;::::0;;2455:120::o;7814:322::-;8112:16;;8102:27;;-1:-1:-1;;;;;8112:16:29;8102:9;:27::i;:::-;7814:322;;;;;;;;;:::o;2948:117::-;4062:11;;;;;;;;-1:-1:-1;;;;;4062:11:29;-1:-1:-1;;;;;4062:17:29;;:19;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;4052:66:29;;:68;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;4025:122:29;;4148:10;4025:134;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;4017:159;;;;-1:-1:-1;;;4017:159:29;;;;;;;:::i;:::-;3031:16:::1;:27:::0;;-1:-1:-1;;;;;;3031:27:29::1;-1:-1:-1::0;;;;;3031:27:29;;;::::1;::::0;;;::::1;::::0;;2948:117::o;9005:203::-;9193:7;;9183:18;;-1:-1:-1;;;;;9193:7:29;9183:9;:18::i;:::-;9005:203;;;;:::o;10500:241::-;10639:16;10674:60;10701:9;10712;10723:10;10674:26;:60::i;5839:431::-;6248:14;;6138:15;;;;;;6238:25;;-1:-1:-1;;;;;6248:14:29;6238:9;:25::i;:::-;5839:431;;;;;;;;;;;:::o;6972:252::-;7200:16;;7190:27;;-1:-1:-1;;;;;7200:16:29;7190:9;:27::i;:::-;6972:252;;;;;;:::o;2728:99::-;4062:11;;;;;;;;-1:-1:-1;;;;;4062:11:29;-1:-1:-1;;;;;4062:17:29;;:19;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;4052:66:29;;:68;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;4025:122:29;;4148:10;4025:134;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;4017:159;;;;-1:-1:-1;;;4017:159:29;;;;;;;:::i;:::-;2802:7:::1;:18:::0;;-1:-1:-1;;;;;;2802:18:29::1;-1:-1:-1::0;;;;;2802:18:29;;;::::1;::::0;;;::::1;::::0;;2728:99::o;3071:126::-;4062:11;;;;;;;;-1:-1:-1;;;;;4062:11:29;-1:-1:-1;;;;;4062:17:29;;:19;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;4052:66:29;;:68;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;4025:122:29;;4148:10;4025:134;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;4017:159;;;;-1:-1:-1;;;4017:159:29;;;;;;;:::i;:::-;3148:7:::1;::::0;;:42:::1;::::0;-1:-1:-1;;;3148:42:29;;-1:-1:-1;;;;;3148:7:29;;::::1;::::0;:25:::1;::::0;:42:::1;::::0;3174:15;;3148:42:::1;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;2833:109:::0;4062:11;;;;;;;;-1:-1:-1;;;;;4062:11:29;-1:-1:-1;;;;;4062:17:29;;:19;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;4052:66:29;;:68;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;4025:122:29;;4148:10;4025:134;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;4017:159;;;;-1:-1:-1;;;4017:159:29;;;;;;;:::i;:::-;2912:14:::1;:23:::0;;-1:-1:-1;;;;;;2912:23:29::1;-1:-1:-1::0;;;;;2912:23:29;;;::::1;::::0;;;::::1;::::0;;2833:109::o;10028:218::-;10156:15;10190:49;10211:7;10220:8;10230;10190:20;:49::i;3789:193::-;4062:11;;;;;;;;-1:-1:-1;;;;;4062:11:29;-1:-1:-1;;;;;4062:17:29;;:19;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;4052:66:29;;:68;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;4025:122:29;;4148:10;4025:134;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;4017:159;;;;-1:-1:-1;;;4017:159:29;;;;;;;:::i;:::-;3923:52:::1;3951:5;3958:8;3968:6;3923:27;:52::i;:::-;3789:193:::0;;;:::o;3458:188::-;4062:11;;;;;;;;-1:-1:-1;;;;;4062:11:29;-1:-1:-1;;;;;4062:17:29;;:19;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;4052:66:29;;:68;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;4025:122:29;;4148:10;4025:134;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;4017:159;;;;-1:-1:-1;;;4017:159:29;;;;;;;:::i;:::-;3555:7:::1;::::0;;:40:::1;::::0;-1:-1:-1;;;3555:40:29;;-1:-1:-1;;;;;3555:7:29;;::::1;::::0;:28:::1;::::0;:40:::1;::::0;3584:10;;3555:40:::1;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;;-1:-1:-1::0;;3605:7:29::1;::::0;;:34:::1;::::0;-1:-1:-1;;;3605:34:29;;-1:-1:-1;;;;;3605:7:29;;::::1;::::0;-1:-1:-1;3605:25:29::1;::::0;-1:-1:-1;3605:34:29::1;::::0;3631:7;;3605:34:::1;;:::i;:::-;;;;;;;;;;;;;;;;;;::::0;::::1;;;;;;;;;;;;::::0;::::1;;;;6276:395:::0;6649:14;;6533:19;;;;;;6639:25;;-1:-1:-1;;;;;6649:14:29;6639:9;:25::i;:::-;6276:395;;;;;;;;;:::o;5358:217::-;5542:6;5560:8;;;1270:42;;;;:::o;1135:39::-;;;-1:-1:-1;;;;;1135:39:29;;:::o;1088:40::-;;;-1:-1:-1;;;;;1088:40:29;;:::o;2037:133::-;4062:11;;;;;;;;-1:-1:-1;;;;;4062:11:29;-1:-1:-1;;;;;4062:17:29;;:19;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;4052:66:29;;:68;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;4025:122:29;;4148:10;4025:134;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;4017:159;;;;-1:-1:-1;;;4017:159:29;;;;;;;:::i;:::-;2121:11:::1;:42:::0;;-1:-1:-1;;;;;;2121:42:29::1;-1:-1:-1::0;;;;;2121:42:29;;;::::1;::::0;;;::::1;::::0;;2037:133::o;10747:242::-;10957:7;;10873:24;;10920:62;;-1:-1:-1;;;;;10957:7:29;10967:8;10977:4;10920:28;:62::i;2309:140::-;4062:11;;;;;;;;-1:-1:-1;;;;;4062:11:29;-1:-1:-1;;;;;4062:17:29;;:19;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;4052:66:29;;:68;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;4025:122:29;;4148:10;4025:134;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;4017:159;;;;-1:-1:-1;;;4017:159:29;;;;;;;:::i;:::-;2395:12:::1;:47:::0;;-1:-1:-1;;;;;;2395:47:29::1;-1:-1:-1::0;;;;;2395:47:29;;;::::1;::::0;;;::::1;::::0;;2309:140::o;7230:230::-;7436:16;;7426:27;;-1:-1:-1;;;;;7436:16:29;7426:9;:27::i;4743:609::-;4903:6;;4945:37;;;;4956:7;4945:37;:::i;:::-;4921:61;;;4996:9;5009:1;4996:14;4992:305;;;5067:14;;5057:25;;-1:-1:-1;;;;;5067:14:29;5057:9;:25::i;:::-;4992:305;;;5103:9;5116:1;5103:14;:32;;;;5121:9;5134:1;5121:14;5103:32;:50;;;;5139:9;5152:1;5139:14;5103:50;:68;;;;5157:9;5170:1;5157:14;5103:68;5099:198;;;5228:7;;5218:18;;-1:-1:-1;;;;;5228:7:29;5218:9;:18::i;5099:198::-;-1:-1:-1;;;;5314:31:29;4743:609;-1:-1:-1;;;;;;;4743:609:29:o;3652:99::-;4062:11;;;;;;;;-1:-1:-1;;;;;4062:11:29;-1:-1:-1;;;;;4062:17:29;;:19;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;4052:66:29;;:68;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;4025:122:29;;4148:10;4025:134;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;4017:159;;;;-1:-1:-1;;;4017:159:29;;;;;;;:::i;:::-;3721:7:::1;::::0;;:23:::1;::::0;-1:-1:-1;;;3721:23:29;;-1:-1:-1;;;;;3721:7:29;;::::1;::::0;:16:::1;::::0;:23:::1;::::0;3738:5;;3721:23:::1;;:::i;1230:34::-:0;;;-1:-1:-1;;;;;1230:34:29;;:::o;2516:557:24:-;2648:17;2696:1;2685:8;:12;2677:66;;;;-1:-1:-1;;;2677:66:24;;;;;;;:::i;:::-;2773:1;2761:9;:13;:31;;;;;2791:1;2778:10;:14;2761:31;2753:82;;;;-1:-1:-1;;;2753:82:24;;;;;;;:::i;:::-;2845:23;2871:17;:8;2884:3;2871:12;:17::i;:::-;2845:43;-1:-1:-1;2898:17:24;2918:31;2845:43;2938:10;2918:19;:31::i;:::-;2898:51;-1:-1:-1;2959:19:24;2981:40;3005:15;2981:19;:9;2995:4;2981:13;:19::i;:::-;:23;;:40::i;:::-;2959:62;-1:-1:-1;3043:23:24;2959:62;3043:9;:23;:::i;:::-;3031:35;2516:557;-1:-1:-1;;;;;;;2516:557:24:o;400:490:29:-;512:14;509:1;506;493:34;612:1;609;593:14;590:1;574:14;567:5;554:60;648:16;645:1;642;627:38;685:6;708:74;;;;839:16;836:1;829:27;708:74;747:16;744:1;737:27;740:708:24;859:12;884:14;900;918:26;929:6;937;918:10;:26::i;:::-;883:61;;;;1154:7;1218:6;1226;1201:32;;;;;;;;;:::i;:::-;;;;;;;;;;;;;1191:43;;;;;;1071:306;;;;;;;;;:::i;:::-;;;;-1:-1:-1;;1071:306:24;;;;;;;;;1036:363;;1071:306;1036:363;;;;;740:708;-1:-1:-1;;;;;;740:708:24:o;4407:570::-;4541:24;4600:1;4585:4;:11;:16;;4577:57;;;;-1:-1:-1;;;4577:57:24;;;;;;;:::i;:::-;4668:4;:11;4654:26;;;;;;-1:-1:-1;;;4654:26:24;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;4654:26:24;;4644:36;;4720:9;4690:7;4715:1;4698:7;:14;:18;;;;:::i;:::-;4690:27;;;;;;-1:-1:-1;;;4690:27:24;;;;;;;;;;;;;;:39;;;;;4744:9;4770:1;4756:4;:11;:15;;;;:::i;:::-;4744:27;;4739:232;4773:5;;4739:232;;4800:17;;4841:42;4853:7;4862:4;4867:5;4871:1;4867;:5;:::i;:::-;4862:11;;;;;;-1:-1:-1;;;4862:11:24;;;;;;;;;;;;;;;4875:4;4880:1;4875:7;;;;;;-1:-1:-1;;;4875:7:24;;;;;;;;;;;;;;;4841:11;:42::i;:::-;4799:84;;;;4914:46;4926:7;4934:1;4926:10;;;;;;-1:-1:-1;;;4926:10:24;;;;;;;;;;;;;;;4938:9;4949:10;4914:11;:46::i;:::-;4897:7;4905:5;4909:1;4905;:5;:::i;:::-;4897:14;;;;;;-1:-1:-1;;;4897:14:24;;;;;;;;;;;;;;:63;;;;;4739:232;;4780:3;;;;;:::i;:::-;;;;4739:232;;;;4407:570;;;;;:::o;3191:510::-;3323:16;3371:1;3359:9;:13;3351:68;;;;-1:-1:-1;;;3351:68:24;;;;;;;:::i;:::-;3449:1;3437:9;:13;:31;;;;;3467:1;3454:10;:14;3437:31;3429:82;;;;-1:-1:-1;;;3429:82:24;;;;;;;:::i;:::-;3521:17;3541:34;3570:4;3541:24;:9;3555;3541:13;:24::i;:::-;:28;;:34::i;:::-;3521:54;-1:-1:-1;3585:19:24;3607:34;3637:3;3607:25;:10;3622:9;3607:14;:25::i;:34::-;3585:56;-1:-1:-1;3662:32:24;3692:1;3663:23;3585:56;3663:9;:23;:::i;3662:32::-;3651:43;3191:510;-1:-1:-1;;;;;;3191:510:24:o;2042:355::-;2163:15;2208:1;2198:7;:11;2190:59;;;;-1:-1:-1;;;2190:59:24;;;;;;;:::i;:::-;2278:1;2267:8;:12;:28;;;;;2294:1;2283:8;:12;2267:28;2259:79;;;;-1:-1:-1;;;2259:79:24;;;;;;;:::i;:::-;2382:8;2358:21;:7;2370:8;2358:11;:21::i;:::-;:32;;;;:::i;605:390:33:-;785:12;799:17;820:5;-1:-1:-1;;;;;820:10:33;854;866:2;870:5;831:45;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;831:45:33;;;;;;;;;;;820:57;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;784:93;;;;895:7;:57;;;;-1:-1:-1;907:11:33;;:16;;:44;;;938:4;927:24;;;;;;;;;;;;:::i;:::-;887:101;;;;-1:-1:-1;;;887:101:33;;;;;;;:::i;3780:549:24:-;3914:24;3973:1;3958:4;:11;:16;;3950:57;;;;-1:-1:-1;;;3950:57:24;;;;;;;:::i;:::-;4041:4;:11;4027:26;;;;;;-1:-1:-1;;;4027:26:24;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;4027:26:24;;4017:36;;4076:8;4063:7;4071:1;4063:10;;;;;;-1:-1:-1;;;4063:10:24;;;;;;;;;;;;;;:21;;;;;4099:9;4094:229;4128:1;4114:4;:11;:15;;;;:::i;:::-;4110:1;:19;4094:229;;;4151:17;4170:18;4192:42;4204:7;4213:4;4218:1;4213:7;;;;;;-1:-1:-1;;;4213:7:24;;;;;;;;;;;;;;;4222:4;4227:1;4231;4227:5;;;;:::i;:::-;4222:11;;;;;;-1:-1:-1;;;4222:11:24;;;;;;;;4192:42;4150:84;;;;4265:47;4278:7;4286:1;4278:10;;;;;;-1:-1:-1;;;4278:10:24;;;;;;;;;;;;;;;4290:9;4301:10;4265:12;:47::i;:::-;4248:7;4256:5;:1;4260;4256:5;:::i;:::-;4248:14;;;;;;-1:-1:-1;;;4248:14:24;;;;;;;;;;;;;;:64;;;;;4094:229;;4131:3;;;;;:::i;:::-;;;;4094:229;;458:140:32;510:6;536;;;:30;;-1:-1:-1;565:1:32;560;551:5;560:1;565;551:5;:::i;:::-;547:9;-1:-1:-1;546:15:32;;547:9;546:15;:::i;:::-;:20;536:30;528:63;;;;-1:-1:-1;;;528:63:32;;;;;;;:::i;193:126::-;245:6;286:1;276:5;280:1;286;276:5;:::i;:::-;272:9;;;271:16;;263:49;;;;-1:-1:-1;;;263:49:32;;;;;;;:::i;310:341:24:-;385:14;401;445:6;-1:-1:-1;;;;;435:16:24;:6;-1:-1:-1;;;;;435:16:24;;;427:64;;;;-1:-1:-1;;;427:64:24;;;;;;;:::i;:::-;529:6;-1:-1:-1;;;;;520:15:24;:6;-1:-1:-1;;;;;520:15:24;;:53;;558:6;566;520:53;;;539:6;547;520:53;501:72;;-1:-1:-1;501:72:24;-1:-1:-1;;;;;;591:20:24;;583:61;;;;-1:-1:-1;;;583:61:24;;;;;;;:::i;:::-;310:341;;;;;:::o;1503:429::-;1626:16;1644;1673:14;1693:26;1704:6;1712;1693:10;:26::i;:::-;1672:47;;;1730:16;1748;1783:32;1791:7;1800:6;1808;1783:7;:32::i;:::-;-1:-1:-1;;;;;1770:58:24;;:60;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;1729:101;-1:-1:-1;;;;;1729:101:24;;;-1:-1:-1;;;;;1729:101:24;;;1873:6;-1:-1:-1;;;;;1863:16:24;:6;-1:-1:-1;;;;;1863:16:24;;:62;;1906:8;1916;1863:62;;;1883:8;1893;1863:62;1840:85;;;;-1:-1:-1;1503:429:24;-1:-1:-1;;;;;;;1503:429:24:o;325:127:32:-;377:6;418:1;408:5;412:1;418;408:5;:::i;:::-;404:9;;;403:16;;395:50;;;;-1:-1:-1;;;395:50:32;;;;;;;:::i;14:826:35:-;;127:3;120:4;112:6;108:17;104:27;94:2;;149:5;142;135:20;94:2;189:6;176:20;215:4;238:18;234:2;231:26;228:2;;;260:18;;:::i;:::-;307:2;303;299:11;330:27;353:2;349;345:11;330:27;:::i;:::-;391:15;;;422:12;;;;454:15;;;488;;;484:24;;481:33;-1:-1:-1;478:2:35;;;531:5;524;517:20;478:2;557:5;548:14;;571:240;585:2;582:1;579:9;571:240;;;656:3;643:17;673:33;700:5;673:33;:::i;:::-;719:18;;603:1;596:9;;;;;757:12;;;;789;;571:240;;;-1:-1:-1;829:5:35;84:756;-1:-1:-1;;;;;;;84:756:35:o;845:404::-;;;978:3;971:4;963:6;959:17;955:27;945:2;;1003:8;993;986:26;945:2;-1:-1:-1;1033:20:35;;1076:18;1065:30;;1062:2;;;1115:8;1105;1098:26;1062:2;1159:4;1151:6;1147:17;1135:29;;1222:3;1215:4;1207;1199:6;1195:17;1187:6;1183:30;1179:41;1176:50;1173:2;;;1239:1;1236;1229:12;1254:377;;;1371:3;1364:4;1356:6;1352:17;1348:27;1338:2;;1396:8;1386;1379:26;1338:2;-1:-1:-1;1426:20:35;;1469:18;1458:30;;1455:2;;;1508:8;1498;1491:26;1455:2;1552:4;1544:6;1540:17;1528:29;;1604:3;1597:4;1588:6;1580;1576:19;1572:30;1569:39;1566:2;;;1621:1;1618;1611:12;1636:190;1717:13;;-1:-1:-1;;;;;1759:42:35;;1749:53;;1739:2;;1816:1;1813;1806:12;1739:2;1698:128;;;:::o;1831:158::-;1899:20;;1959:4;1948:16;;1938:27;;1928:2;;1979:1;1976;1969:12;1994:259;;2106:2;2094:9;2085:7;2081:23;2077:32;2074:2;;;2127:6;2119;2112:22;2074:2;2171:9;2158:23;2190:33;2217:5;2190:33;:::i;:::-;2242:5;2064:189;-1:-1:-1;;;2064:189:35:o;2258:263::-;;2381:2;2369:9;2360:7;2356:23;2352:32;2349:2;;;2402:6;2394;2387:22;2349:2;2439:9;2433:16;2458:33;2485:5;2458:33;:::i;2526:1396::-;;;;;;;;;2795:3;2783:9;2774:7;2770:23;2766:33;2763:2;;;2817:6;2809;2802:22;2763:2;2861:9;2848:23;2880:33;2907:5;2880:33;:::i;:::-;2932:5;-1:-1:-1;2989:2:35;2974:18;;2961:32;3002:35;2961:32;3002:35;:::i;:::-;3056:7;-1:-1:-1;3114:2:35;3099:18;;3086:32;3137:18;3167:14;;;3164:2;;;3199:6;3191;3184:22;3164:2;3243:76;3311:7;3302:6;3291:9;3287:22;3243:76;:::i;:::-;3338:8;;-1:-1:-1;3217:102:35;-1:-1:-1;3426:2:35;3411:18;;3398:32;;-1:-1:-1;3442:16:35;;;3439:2;;;3476:6;3468;3461:22;3439:2;3520:78;3590:7;3579:8;3568:9;3564:24;3520:78;:::i;:::-;3617:8;;-1:-1:-1;3494:104:35;-1:-1:-1;3705:3:35;3690:19;;3677:33;;-1:-1:-1;3722:16:35;;;3719:2;;;3756:6;3748;3741:22;3719:2;;3800:62;3854:7;3843:8;3832:9;3828:24;3800:62;:::i;:::-;2753:1169;;;;-1:-1:-1;2753:1169:35;;-1:-1:-1;2753:1169:35;;;;;;3881:8;-1:-1:-1;;;2753:1169:35:o;3927:849::-;;;;;;;4126:3;4114:9;4105:7;4101:23;4097:33;4094:2;;;4148:6;4140;4133:22;4094:2;4192:9;4179:23;4211:33;4238:5;4211:33;:::i;:::-;4263:5;-1:-1:-1;4320:2:35;4305:18;;4292:32;4333:35;4292:32;4333:35;:::i;:::-;4387:7;-1:-1:-1;4441:2:35;4426:18;;4413:32;;-1:-1:-1;4492:2:35;4477:18;;4464:32;;-1:-1:-1;4547:3:35;4532:19;;4519:33;4575:18;4564:30;;4561:2;;;4612:6;4604;4597:22;4561:2;4656:60;4708:7;4699:6;4688:9;4684:22;4656:60;:::i;:::-;4084:692;;;;-1:-1:-1;4084:692:35;;-1:-1:-1;4084:692:35;;4735:8;;4084:692;-1:-1:-1;;;4084:692:35:o;4781:470::-;;;;4927:2;4915:9;4906:7;4902:23;4898:32;4895:2;;;4948:6;4940;4933:22;4895:2;4992:9;4979:23;5011:33;5038:5;5011:33;:::i;:::-;5063:5;-1:-1:-1;5115:2:35;5100:18;;5087:32;;-1:-1:-1;5171:2:35;5156:18;;5143:32;5184:35;5143:32;5184:35;:::i;:::-;5238:7;5228:17;;;4885:366;;;;;:::o;5256:395::-;;;;5402:2;5390:9;5381:7;5377:23;5373:32;5370:2;;;5423:6;5415;5408:22;5370:2;5467:9;5454:23;5486:33;5513:5;5486:33;:::i;:::-;5538:5;5590:2;5575:18;;5562:32;;-1:-1:-1;5641:2:35;5626:18;;;5613:32;;5360:291;-1:-1:-1;;;5360:291:35:o;5656:677::-;;;;;;;5853:3;5841:9;5832:7;5828:23;5824:33;5821:2;;;5875:6;5867;5860:22;5821:2;5919:9;5906:23;5938:33;5965:5;5938:33;:::i;:::-;5990:5;-1:-1:-1;6042:2:35;6027:18;;6014:32;;-1:-1:-1;6093:2:35;6078:18;;6065:32;;-1:-1:-1;6144:2:35;6129:18;;6116:32;;-1:-1:-1;6200:3:35;6185:19;;6172:33;6214:35;6172:33;6214:35;:::i;:::-;6268:7;6258:17;;;6322:3;6311:9;6307:19;6294:33;6284:43;;5811:522;;;;;;;;:::o;6338:1026::-;;;;;;;;;;;6598:3;6586:9;6577:7;6573:23;6569:33;6566:2;;;6620:6;6612;6605:22;6566:2;6664:9;6651:23;6683:33;6710:5;6683:33;:::i;:::-;6735:5;-1:-1:-1;6787:2:35;6772:18;;6759:32;;-1:-1:-1;6838:2:35;6823:18;;6810:32;;-1:-1:-1;6889:2:35;6874:18;;6861:32;;-1:-1:-1;6945:3:35;6930:19;;6917:33;6959:35;6917:33;6959:35;:::i;:::-;7013:7;-1:-1:-1;7067:3:35;7052:19;;7039:33;;-1:-1:-1;7124:3:35;7109:19;;7096:33;7138:32;7096:33;7138:32;:::i;:::-;7189:7;-1:-1:-1;7215:39:35;7249:3;7234:19;;7215:39;:::i;:::-;7205:49;;7301:3;7290:9;7286:19;7273:33;7263:43;;7353:3;7342:9;7338:19;7325:33;7315:43;;6556:808;;;;;;;;;;;;;:::o;7369:746::-;;;;;;;;7583:3;7571:9;7562:7;7558:23;7554:33;7551:2;;;7605:6;7597;7590:22;7551:2;7649:9;7636:23;7668:33;7695:5;7668:33;:::i;:::-;7720:5;-1:-1:-1;7772:2:35;7757:18;;7744:32;;-1:-1:-1;7823:2:35;7808:18;;7795:32;;-1:-1:-1;7874:2:35;7859:18;;7846:32;;-1:-1:-1;7925:3:35;7910:19;;7897:33;;-1:-1:-1;7982:3:35;7967:19;;7954:33;7996:35;7954:33;7996:35;:::i;:::-;8050:7;8040:17;;;8104:3;8093:9;8089:19;8076:33;8066:43;;7541:574;;;;;;;;;;:::o;8120:257::-;;8240:2;8228:9;8219:7;8215:23;8211:32;8208:2;;;8261:6;8253;8246:22;8208:2;8298:9;8292:16;8317:30;8341:5;8317:30;:::i;8382:474::-;;;;8538:2;8526:9;8517:7;8513:23;8509:32;8506:2;;;8559:6;8551;8544:22;8506:2;8587:42;8619:9;8587:42;:::i;:::-;8577:52;;8648:51;8695:2;8684:9;8680:18;8648:51;:::i;:::-;8638:61;;8742:2;8731:9;8727:18;8721:25;8786:10;8779:5;8775:22;8768:5;8765:33;8755:2;;8817:6;8809;8802:22;8861:190;;8973:2;8961:9;8952:7;8948:23;8944:32;8941:2;;;8994:6;8986;8979:22;8941:2;-1:-1:-1;9022:23:35;;8931:120;-1:-1:-1;8931:120:35:o;9056:194::-;;9179:2;9167:9;9158:7;9154:23;9150:32;9147:2;;;9200:6;9192;9185:22;9147:2;-1:-1:-1;9228:16:35;;9137:113;-1:-1:-1;9137:113:35:o;9255:442::-;;;9409:2;9397:9;9388:7;9384:23;9380:32;9377:2;;;9430:6;9422;9415:22;9377:2;9471:9;9458:23;9448:33;;9532:2;9521:9;9517:18;9504:32;9559:18;9551:6;9548:30;9545:2;;;9596:6;9588;9581:22;9545:2;9624:67;9683:7;9674:6;9663:9;9659:22;9624:67;:::i;:::-;9614:77;;;9367:330;;;;;:::o;9702:648::-;;;;;9890:3;9878:9;9869:7;9865:23;9861:33;9858:2;;;9912:6;9904;9897:22;9858:2;9953:9;9940:23;9930:33;;10014:2;10003:9;9999:18;9986:32;10041:18;10033:6;10030:30;10027:2;;;10078:6;10070;10063:22;10027:2;10106:67;10165:7;10156:6;10145:9;10141:22;10106:67;:::i;:::-;10096:77;;;10223:2;10212:9;10208:18;10195:32;10236:33;10263:5;10236:33;:::i;:::-;9848:502;;;;-1:-1:-1;10288:5:35;;10340:2;10325:18;10312:32;;-1:-1:-1;;9848:502:35:o;10355:875::-;;;10493:2;10481:9;10472:7;10468:23;10464:32;10461:2;;;10514:6;10506;10499:22;10461:2;10555:9;10542:23;10532:33;;10584:2;10637;10626:9;10622:18;10609:32;10660:18;10701:2;10693:6;10690:14;10687:2;;;10722:6;10714;10707:22;10687:2;10765:6;10754:9;10750:22;10740:32;;10810:7;10803:4;10799:2;10795:13;10791:27;10781:2;;10837:6;10829;10822:22;10781:2;10878;10865:16;10900:2;10896;10893:10;10890:2;;;10906:18;;:::i;:::-;10948:52;10990:2;10971:13;;-1:-1:-1;;10967:27:35;10963:36;;10948:52;:::i;:::-;10935:65;;11023:2;11016:5;11009:17;11063:7;11058:2;11053;11049;11045:11;11041:20;11038:33;11035:2;;;11089:6;11081;11074:22;11035:2;11149;11144;11140;11136:11;11131:2;11124:5;11120:14;11107:45;11172:14;;11168:23;;;11161:39;;;;10451:779;;11176:5;;-1:-1:-1;10451:779:35;;-1:-1:-1;;10451:779:35:o;11235:258::-;;;11364:2;11352:9;11343:7;11339:23;11335:32;11332:2;;;11385:6;11377;11370:22;11332:2;-1:-1:-1;;11413:23:35;;;11483:2;11468:18;;;11455:32;;-1:-1:-1;11322:171:35:o;11498:717::-;;;;;;11703:3;11691:9;11682:7;11678:23;11674:33;11671:2;;;11725:6;11717;11710:22;11671:2;11766:9;11753:23;11743:33;;11823:2;11812:9;11808:18;11795:32;11785:42;;11878:2;11867:9;11863:18;11850:32;11905:18;11897:6;11894:30;11891:2;;;11942:6;11934;11927:22;11891:2;11970:67;12029:7;12020:6;12009:9;12005:22;11970:67;:::i;:::-;11960:77;;;12087:2;12076:9;12072:18;12059:32;12100:33;12127:5;12100:33;:::i;:::-;11661:554;;;;-1:-1:-1;11661:554:35;;12204:3;12189:19;12176:33;;11661:554;-1:-1:-1;;11661:554:35:o;12220:326::-;;;;12366:2;12354:9;12345:7;12341:23;12337:32;12334:2;;;12387:6;12379;12372:22;12334:2;-1:-1:-1;;12415:23:35;;;12485:2;12470:18;;12457:32;;-1:-1:-1;12536:2:35;12521:18;;;12508:32;;12324:222;-1:-1:-1;12324:222:35:o;12551:533::-;;;;;;12731:3;12719:9;12710:7;12706:23;12702:33;12699:2;;;12753:6;12745;12738:22;12699:2;12794:9;12781:23;12771:33;;12851:2;12840:9;12836:18;12823:32;12813:42;;12902:2;12891:9;12887:18;12874:32;12864:42;;12956:2;12945:9;12941:18;12928:32;12969:33;12996:5;12969:33;:::i;13089:882::-;;;;;;;;;;13332:3;13320:9;13311:7;13307:23;13303:33;13300:2;;;13354:6;13346;13339:22;13300:2;13395:9;13382:23;13372:33;;13452:2;13441:9;13437:18;13424:32;13414:42;;13503:2;13492:9;13488:18;13475:32;13465:42;;13557:2;13546:9;13542:18;13529:32;13570:33;13597:5;13570:33;:::i;:::-;13622:5;-1:-1:-1;13674:3:35;13659:19;;13646:33;;-1:-1:-1;13731:3:35;13716:19;;13703:33;13745:32;13703:33;13745:32;:::i;:::-;13796:7;-1:-1:-1;13822:39:35;13856:3;13841:19;;13822:39;:::i;:::-;13812:49;;13908:3;13897:9;13893:19;13880:33;13870:43;;13960:3;13949:9;13945:19;13932:33;13922:43;;13290:681;;;;;;;;;;;:::o;13976:333::-;-1:-1:-1;;14203:2:35;14199:15;;;14195:24;;14183:37;;14254:15;;;;14250:24;14245:2;14236:12;;14229:46;14300:2;14291:12;;14123:186::o;14314:430::-;;14481:6;14475:13;14506:3;14518:129;14532:6;14529:1;14526:13;14518:129;;;14630:4;14614:14;;;14610:25;;14604:32;14591:11;;;14584:53;14547:12;14518:129;;;14665:6;14662:1;14659:13;14656:2;;;14700:3;14691:6;14686:3;14682:16;14675:29;14656:2;-1:-1:-1;14722:16:35;;;;;14451:293;-1:-1:-1;;14451:293:35:o;14749:636::-;-1:-1:-1;;;;;;15108:26:35;;15171:2;15167:15;;;;-1:-1:-1;;15163:53:35;15159:1;15150:11;;15143:74;15242:2;15233:12;;15226:28;15284:66;15279:2;15270:12;;15263:88;15376:2;15367:12;;15098:287::o;15390:203::-;-1:-1:-1;;;;;15554:32:35;;;;15536:51;;15524:2;15509:18;;15491:102::o;15598:355::-;-1:-1:-1;;;;;15812:32:35;;;;15794:51;;15888:14;;15881:22;15876:2;15861:18;;15854:50;15935:2;15920:18;;15913:34;15782:2;15767:18;;15749:204::o;15958:274::-;-1:-1:-1;;;;;16150:32:35;;;;16132:51;;16214:2;16199:18;;16192:34;16120:2;16105:18;;16087:145::o;16237:345::-;-1:-1:-1;;;;;16457:32:35;;;;16439:51;;16521:2;16506:18;;16499:34;;;;16564:2;16549:18;;16542:34;16427:2;16412:18;;16394:188::o;16587:635::-;16758:2;16810:21;;;16880:13;;16783:18;;;16902:22;;;16587:635;;16758:2;16981:15;;;;16955:2;16940:18;;;16587:635;17027:169;17041:6;17038:1;17035:13;17027:169;;;17102:13;;17090:26;;17171:15;;;;17136:12;;;;17063:1;17056:9;17027:169;;;-1:-1:-1;17213:3:35;;16738:484;-1:-1:-1;;;;;;16738:484:35:o;17227:202::-;-1:-1:-1;;;;;;17389:33:35;;;;17371:52;;17359:2;17344:18;;17326:103::o;18346:345::-;18548:2;18530:21;;;18587:2;18567:18;;;18560:30;-1:-1:-1;;;18621:2:35;18606:18;;18599:51;18682:2;18667:18;;18520:171::o;18696:355::-;18898:2;18880:21;;;18937:2;18917:18;;;18910:30;18976:33;18971:2;18956:18;;18949:61;19042:2;19027:18;;18870:181::o;19056:336::-;19258:2;19240:21;;;19297:2;19277:18;;;19270:30;-1:-1:-1;;;19331:2:35;19316:18;;19309:42;19383:2;19368:18;;19230:162::o;19397:344::-;19599:2;19581:21;;;19638:2;19618:18;;;19611:30;-1:-1:-1;;;19672:2:35;19657:18;;19650:50;19732:2;19717:18;;19571:170::o;19746:344::-;19948:2;19930:21;;;19987:2;19967:18;;;19960:30;-1:-1:-1;;;20021:2:35;20006:18;;19999:50;20081:2;20066:18;;19920:170::o;20095:399::-;20297:2;20279:21;;;20336:2;20316:18;;;20309:30;20375:34;20370:2;20355:18;;20348:62;-1:-1:-1;;;20441:2:35;20426:18;;20419:33;20484:3;20469:19;;20269:225::o;20499:406::-;20701:2;20683:21;;;20740:2;20720:18;;;20713:30;20779:34;20774:2;20759:18;;20752:62;-1:-1:-1;;;20845:2:35;20830:18;;20823:40;20895:3;20880:19;;20673:232::o;20910:352::-;21112:2;21094:21;;;21151:2;21131:18;;;21124:30;21190;21185:2;21170:18;;21163:58;21253:2;21238:18;;21084:178::o;21267:405::-;21469:2;21451:21;;;21508:2;21488:18;;;21481:30;21547:34;21542:2;21527:18;;21520:62;-1:-1:-1;;;21613:2:35;21598:18;;21591:39;21662:3;21647:19;;21441:231::o;21677:399::-;21879:2;21861:21;;;21918:2;21898:18;;;21891:30;21957:34;21952:2;21937:18;;21930:62;-1:-1:-1;;;22023:2:35;22008:18;;22001:33;22066:3;22051:19;;21851:225::o;22081:406::-;22283:2;22265:21;;;22322:2;22302:18;;;22295:30;22361:34;22356:2;22341:18;;22334:62;-1:-1:-1;;;22427:2:35;22412:18;;22405:40;22477:3;22462:19;;22255:232::o;22492:402::-;22694:2;22676:21;;;22733:2;22713:18;;;22706:30;22772:34;22767:2;22752:18;;22745:62;-1:-1:-1;;;22838:2:35;22823:18;;22816:36;22884:3;22869:19;;22666:228::o;22899:352::-;23101:2;23083:21;;;23140:2;23120:18;;;23113:30;23179;23174:2;23159:18;;23152:58;23242:2;23227:18;;23073:178::o;23256:177::-;23402:25;;;23390:2;23375:18;;23357:76::o;23438:319::-;23640:25;;;23696:2;23681:18;;23674:34;;;;23739:2;23724:18;;23717:34;23628:2;23613:18;;23595:162::o;23762:251::-;23832:2;23826:9;23862:17;;;23909:18;23894:34;;23930:22;;;23891:62;23888:2;;;23956:18;;:::i;:::-;23992:2;23985:22;23806:207;;-1:-1:-1;23806:207:35:o;24018:128::-;;24089:1;24085:6;24082:1;24079:13;24076:2;;;24095:18;;:::i;:::-;-1:-1:-1;24131:9:35;;24066:80::o;24151:217::-;;24217:1;24207:2;;-1:-1:-1;;;24242:31:35;;24296:4;24293:1;24286:15;24324:4;24249:1;24314:15;24207:2;-1:-1:-1;24353:9:35;;24197:171::o;24373:168::-;;24479:1;24475;24471:6;24467:14;24464:1;24461:21;24456:1;24449:9;24442:17;24438:45;24435:2;;;24486:18;;:::i;:::-;-1:-1:-1;24526:9:35;;24425:116::o;24546:125::-;;24614:1;24611;24608:8;24605:2;;;24619:18;;:::i;:::-;-1:-1:-1;24656:9:35;;24595:76::o;24676:136::-;;24743:5;24733:2;;24752:18;;:::i;:::-;-1:-1:-1;;;24788:18:35;;24723:89::o;24817:135::-;;-1:-1:-1;;24877:17:35;;24874:2;;;24897:18;;:::i;:::-;-1:-1:-1;24944:1:35;24933:13;;24864:88::o;24957:127::-;25018:10;25013:3;25009:20;25006:1;24999:31;25049:4;25046:1;25039:15;25073:4;25070:1;25063:15;25089:127;25150:10;25145:3;25141:20;25138:1;25131:31;25181:4;25178:1;25171:15;25205:4;25202:1;25195:15;25221:133;-1:-1:-1;;;;;25298:31:35;;25288:42;;25278:2;;25344:1;25341;25334:12;25278:2;25268:86;:::o;25359:120::-;25447:5;25440:13;25433:21;25426:5;25423:32;25413:2;;25469:1;25466;25459:12

Swarm Source

ipfs://b3b8ef5e113b91bb36e96a9cac93a50966aa5f577408c39530aba3b8e91db4ed

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  ]
[ 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.