false
false

Contract Address Details

0xa115146782b7143fadb3065d86eacb54c169d092

Contract Name
ArbMulticall2
Creator
0x88888a–872063 at 0x34193b–06a734
Balance
0 ETH ( )
Tokens
Fetching tokens...
Transactions
0 Transactions
Transfers
0 Transfers
Gas Used
Fetching gas used...
Last Balance Update
77818605
Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
Contract name:
ArbMulticall2




Optimization enabled
true
Compiler version
v0.8.7+commit.e28d00a7




Optimization runs
100
Verified at
2023-08-24T12:54:51.254000Z

contracts/rpc-utils/MulticallV2.sol

// SPDX-License-Identifier: MIT
// solhint-disable-next-line compiler-version
pragma solidity >=0.5.0;
pragma experimental ABIEncoderV2;

import "@arbitrum/nitro-contracts/src/precompiles/ArbSys.sol";

// implementation from https://github.com/makerdao/multicall/blob/1e1b44362640820bef92d0ccf5eeee25d9b41474/src/Multicall2.sol MIT License

/// @title Multicall2 - Aggregate results from multiple read-only function calls
/// @author Michael Elliot <[email protected]>
/// @author Joshua Levine <[email protected]>
/// @author Nick Johnson <[email protected]>

contract Multicall2 {
    struct Call {
        address target;
        bytes callData;
    }
    struct Result {
        bool success;
        bytes returnData;
    }

    function aggregate(Call[] memory calls)
        public
        returns (uint256 blockNumber, bytes[] memory returnData)
    {
        blockNumber = block.number;
        returnData = new bytes[](calls.length);
        for (uint256 i = 0; i < calls.length; i++) {
            (bool success, bytes memory ret) = calls[i].target.call(calls[i].callData);
            require(success, "Multicall aggregate: call failed");
            returnData[i] = ret;
        }
    }

    function blockAndAggregate(Call[] memory calls)
        public
        returns (
            uint256 blockNumber,
            bytes32 blockHash,
            Result[] memory returnData
        )
    {
        (blockNumber, blockHash, returnData) = tryBlockAndAggregate(true, calls);
    }

    function getBlockHash(uint256 blockNumber) public view returns (bytes32 blockHash) {
        blockHash = blockhash(blockNumber);
    }

    function getBlockNumber() public view returns (uint256 blockNumber) {
        blockNumber = block.number;
    }

    function getCurrentBlockCoinbase() public view returns (address coinbase) {
        coinbase = block.coinbase;
    }

    function getCurrentBlockDifficulty() public view returns (uint256 difficulty) {
        difficulty = block.difficulty;
    }

    function getCurrentBlockGasLimit() public view returns (uint256 gaslimit) {
        gaslimit = block.gaslimit;
    }

    function getCurrentBlockTimestamp() public view returns (uint256 timestamp) {
        timestamp = block.timestamp;
    }

    function getEthBalance(address addr) public view returns (uint256 balance) {
        balance = addr.balance;
    }

    function getLastBlockHash() public view returns (bytes32 blockHash) {
        blockHash = blockhash(block.number - 1);
    }

    function tryAggregateGasRation(bool requireSuccess, Call[] memory calls)
        public
        returns (Result[] memory returnData)
    {
        returnData = new Result[](calls.length);
        uint256 gasPerCall = gasleft() / calls.length;
        for (uint256 i = 0; i < calls.length; i++) {
            (bool success, bytes memory ret) = calls[i].target.call{
                gas: gasleft() > gasPerCall ? gasPerCall : gasleft()
            }(calls[i].callData);

            if (requireSuccess) {
                require(success, "Multicall2 aggregate: call failed");
            }

            returnData[i] = Result(success, ret);
        }
    }

    function tryAggregate(bool requireSuccess, Call[] memory calls)
        public
        returns (Result[] memory returnData)
    {
        returnData = new Result[](calls.length);
        for (uint256 i = 0; i < calls.length; i++) {
            (bool success, bytes memory ret) = calls[i].target.call(calls[i].callData);

            if (requireSuccess) {
                require(success, "Multicall2 aggregate: call failed");
            }

            returnData[i] = Result(success, ret);
        }
    }

    function tryBlockAndAggregate(bool requireSuccess, Call[] memory calls)
        public
        returns (
            uint256 blockNumber,
            bytes32 blockHash,
            Result[] memory returnData
        )
    {
        blockNumber = block.number;
        blockHash = blockhash(block.number);
        returnData = tryAggregate(requireSuccess, calls);
    }
}

/// @title Arbitrum Multicall2 - Multicall2 contracts with L1 and L2 block numbers
contract ArbMulticall2 {
    struct Call {
        address target;
        bytes callData;
    }
    struct Result {
        bool success;
        bytes returnData;
    }

    function aggregate(Call[] memory calls)
        public
        returns (uint256 blockNumber, bytes[] memory returnData)
    {
        blockNumber = ArbSys(address(100)).arbBlockNumber();
        returnData = new bytes[](calls.length);
        for (uint256 i = 0; i < calls.length; i++) {
            (bool success, bytes memory ret) = calls[i].target.call(calls[i].callData);
            require(success, "Multicall aggregate: call failed");
            returnData[i] = ret;
        }
    }

    function blockAndAggregate(Call[] memory calls)
        public
        returns (
            uint256 blockNumber,
            bytes32 blockHash,
            Result[] memory returnData
        )
    {
        (blockNumber, blockHash, returnData) = tryBlockAndAggregate(true, calls);
    }

    function getBlockHash(uint256 blockNumber) public view returns (bytes32 blockHash) {
        blockHash = blockhash(blockNumber);
    }

    function getBlockNumber() public view returns (uint256 blockNumber) {
        blockNumber = ArbSys(address(100)).arbBlockNumber();
    }

    function getL1BlockNumber() public view returns (uint256 l1BlockNumber) {
        l1BlockNumber = block.number;
    }

    function getCurrentBlockCoinbase() public view returns (address coinbase) {
        coinbase = block.coinbase;
    }

    function getCurrentBlockDifficulty() public view returns (uint256 difficulty) {
        difficulty = block.difficulty;
    }

    function getCurrentBlockGasLimit() public view returns (uint256 gaslimit) {
        gaslimit = block.gaslimit;
    }

    function getCurrentBlockTimestamp() public view returns (uint256 timestamp) {
        timestamp = block.timestamp;
    }

    function getEthBalance(address addr) public view returns (uint256 balance) {
        balance = addr.balance;
    }

    function getLastBlockHash() public view returns (bytes32 blockHash) {
        blockHash = blockhash(block.number - 1);
    }

    function tryAggregateGasRation(bool requireSuccess, Call[] memory calls)
        public
        returns (Result[] memory returnData)
    {
        returnData = new Result[](calls.length);
        uint256 gasPerCall = gasleft() / calls.length;
        for (uint256 i = 0; i < calls.length; i++) {
            (bool success, bytes memory ret) = calls[i].target.call{
                gas: gasleft() > gasPerCall ? gasPerCall : gasleft()
            }(calls[i].callData);

            if (requireSuccess) {
                require(success, "Multicall2 aggregate: call failed");
            }

            returnData[i] = Result(success, ret);
        }
    }

    function tryAggregate(bool requireSuccess, Call[] memory calls)
        public
        returns (Result[] memory returnData)
    {
        returnData = new Result[](calls.length);
        for (uint256 i = 0; i < calls.length; i++) {
            (bool success, bytes memory ret) = calls[i].target.call(calls[i].callData);

            if (requireSuccess) {
                require(success, "Multicall2 aggregate: call failed");
            }

            returnData[i] = Result(success, ret);
        }
    }

    function tryBlockAndAggregate(bool requireSuccess, Call[] memory calls)
        public
        returns (
            uint256 blockNumber,
            bytes32 blockHash,
            Result[] memory returnData
        )
    {
        blockNumber = ArbSys(address(100)).arbBlockNumber();
        blockHash = blockhash(block.number);
        returnData = tryAggregate(requireSuccess, calls);
    }
}
        

@arbitrum/nitro-contracts/src/precompiles/ArbSys.sol

// Copyright 2021-2022, Offchain Labs, Inc.
// For license information, see https://github.com/nitro/blob/master/LICENSE
// SPDX-License-Identifier: BUSL-1.1

pragma solidity >=0.4.21 <0.9.0;

/**
 * @title System level functionality
 * @notice For use by contracts to interact with core L2-specific functionality.
 * Precompiled contract that exists in every Arbitrum chain at address(100), 0x0000000000000000000000000000000000000064.
 */
interface ArbSys {
    /**
     * @notice Get Arbitrum block number (distinct from L1 block number; Arbitrum genesis block has block number 0)
     * @return block number as int
     */
    function arbBlockNumber() external view returns (uint256);

    /**
     * @notice Get Arbitrum block hash (reverts unless currentBlockNum-256 <= arbBlockNum < currentBlockNum)
     * @return block hash
     */
    function arbBlockHash(uint256 arbBlockNum) external view returns (bytes32);

    /**
     * @notice Gets the rollup's unique chain identifier
     * @return Chain identifier as int
     */
    function arbChainID() external view returns (uint256);

    /**
     * @notice Get internal version number identifying an ArbOS build
     * @return version number as int
     */
    function arbOSVersion() external view returns (uint256);

    /**
     * @notice Returns 0 since Nitro has no concept of storage gas
     * @return uint 0
     */
    function getStorageGasAvailable() external view returns (uint256);

    /**
     * @notice check if current call is top level (meaning it was triggered by an EoA or a L1 contract)
     * @return true if current execution frame is not a call by another L2 contract
     */
    function isTopLevelCall() external view returns (bool);

    /**
     * @notice map L1 sender contract address to its L2 alias
     * @param sender sender address
     * @param unused argument no longer used
     * @return aliased sender address
     */
    function mapL1SenderContractAddressToL2Alias(address sender, address unused)
        external
        pure
        returns (address);

    /**
     * @notice check if the caller (of this caller of this) is an aliased L1 contract address
     * @return true iff the caller's address is an alias for an L1 contract address
     */
    function wasMyCallersAddressAliased() external view returns (bool);

    /**
     * @notice return the address of the caller (of this caller of this), without applying L1 contract address aliasing
     * @return address of the caller's caller, without applying L1 contract address aliasing
     */
    function myCallersAddressWithoutAliasing() external view returns (address);

    /**
     * @notice Send given amount of Eth to dest from sender.
     * This is a convenience function, which is equivalent to calling sendTxToL1 with empty data.
     * @param destination recipient address on L1
     * @return unique identifier for this L2-to-L1 transaction.
     */
    function withdrawEth(address destination) external payable returns (uint256);

    /**
     * @notice Send a transaction to L1
     * @param destination recipient address on L1
     * @param data (optional) calldata for L1 contract call
     * @return a unique identifier for this L2-to-L1 transaction.
     */
    function sendTxToL1(address destination, bytes calldata data)
        external
        payable
        returns (uint256);

    /**
     * @notice Get send Merkle tree state
     * @return size number of sends in the history
     * @return root root hash of the send history
     * @return partials hashes of partial subtrees in the send history tree
     */
    function sendMerkleTreeState()
        external
        view
        returns (
            uint256 size,
            bytes32 root,
            bytes32[] memory partials
        );

    /**
     * @notice creates a send txn from L2 to L1
     * @param position = (level << 192) + leaf = (0 << 192) + leaf = leaf
     */
    event L2ToL1Tx(
        address caller,
        address indexed destination,
        uint256 indexed hash,
        uint256 indexed position,
        uint256 arbBlockNum,
        uint256 ethBlockNum,
        uint256 timestamp,
        uint256 callvalue,
        bytes data
    );

    /// @dev DEPRECATED in favour of the new L2ToL1Tx event above after the nitro upgrade
    event L2ToL1Transaction(
        address caller,
        address indexed destination,
        uint256 indexed uniqueId,
        uint256 indexed batchNumber,
        uint256 indexInBatch,
        uint256 arbBlockNum,
        uint256 ethBlockNum,
        uint256 timestamp,
        uint256 callvalue,
        bytes data
    );

    /**
     * @notice logs a merkle branch for proof sythesis
     * @param reserved an index meant only to align the 4th index with L2ToL1Transaction's 4th event
     * @param hash the merkle hash
     * @param position = (level << 192) + leaf
     */
    event SendMerkleUpdate(
        uint256 indexed reserved,
        bytes32 indexed hash,
        uint256 indexed position
    );
}
          

Contract ABI

[{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"uint256","name":"blockNumber","internalType":"uint256"},{"type":"bytes[]","name":"returnData","internalType":"bytes[]"}],"name":"aggregate","inputs":[{"type":"tuple[]","name":"calls","internalType":"struct ArbMulticall2.Call[]","components":[{"type":"address","name":"target","internalType":"address"},{"type":"bytes","name":"callData","internalType":"bytes"}]}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"uint256","name":"blockNumber","internalType":"uint256"},{"type":"bytes32","name":"blockHash","internalType":"bytes32"},{"type":"tuple[]","name":"returnData","internalType":"struct ArbMulticall2.Result[]","components":[{"type":"bool","name":"success","internalType":"bool"},{"type":"bytes","name":"returnData","internalType":"bytes"}]}],"name":"blockAndAggregate","inputs":[{"type":"tuple[]","name":"calls","internalType":"struct ArbMulticall2.Call[]","components":[{"type":"address","name":"target","internalType":"address"},{"type":"bytes","name":"callData","internalType":"bytes"}]}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32","name":"blockHash","internalType":"bytes32"}],"name":"getBlockHash","inputs":[{"type":"uint256","name":"blockNumber","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"blockNumber","internalType":"uint256"}],"name":"getBlockNumber","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"coinbase","internalType":"address"}],"name":"getCurrentBlockCoinbase","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"difficulty","internalType":"uint256"}],"name":"getCurrentBlockDifficulty","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"gaslimit","internalType":"uint256"}],"name":"getCurrentBlockGasLimit","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"timestamp","internalType":"uint256"}],"name":"getCurrentBlockTimestamp","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"balance","internalType":"uint256"}],"name":"getEthBalance","inputs":[{"type":"address","name":"addr","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"l1BlockNumber","internalType":"uint256"}],"name":"getL1BlockNumber","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32","name":"blockHash","internalType":"bytes32"}],"name":"getLastBlockHash","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"tuple[]","name":"returnData","internalType":"struct ArbMulticall2.Result[]","components":[{"type":"bool","name":"success","internalType":"bool"},{"type":"bytes","name":"returnData","internalType":"bytes"}]}],"name":"tryAggregate","inputs":[{"type":"bool","name":"requireSuccess","internalType":"bool"},{"type":"tuple[]","name":"calls","internalType":"struct ArbMulticall2.Call[]","components":[{"type":"address","name":"target","internalType":"address"},{"type":"bytes","name":"callData","internalType":"bytes"}]}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"tuple[]","name":"returnData","internalType":"struct ArbMulticall2.Result[]","components":[{"type":"bool","name":"success","internalType":"bool"},{"type":"bytes","name":"returnData","internalType":"bytes"}]}],"name":"tryAggregateGasRation","inputs":[{"type":"bool","name":"requireSuccess","internalType":"bool"},{"type":"tuple[]","name":"calls","internalType":"struct ArbMulticall2.Call[]","components":[{"type":"address","name":"target","internalType":"address"},{"type":"bytes","name":"callData","internalType":"bytes"}]}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"uint256","name":"blockNumber","internalType":"uint256"},{"type":"bytes32","name":"blockHash","internalType":"bytes32"},{"type":"tuple[]","name":"returnData","internalType":"struct ArbMulticall2.Result[]","components":[{"type":"bool","name":"success","internalType":"bool"},{"type":"bytes","name":"returnData","internalType":"bytes"}]}],"name":"tryBlockAndAggregate","inputs":[{"type":"bool","name":"requireSuccess","internalType":"bool"},{"type":"tuple[]","name":"calls","internalType":"struct ArbMulticall2.Call[]","components":[{"type":"address","name":"target","internalType":"address"},{"type":"bytes","name":"callData","internalType":"bytes"}]}]}]
              

Contract Creation Code

0x608060405234801561001057600080fd5b50610d47806100206000396000f3fe608060405234801561001057600080fd5b50600436106100ca5760003560e01c806372425d9d1161007c57806372425d9d1461017257806386d516e814610178578063a8b0574e1461017e578063b9b3efe91461018c578063bce38bd714610192578063c3077fa9146101a5578063ee82ac5e146101b857600080fd5b80630f28c97d146100cf578063252dba42146100e457806327e86d6e146101055780632935cd901461010d578063399542e91461012d57806342cbb15c1461014f5780634d2301cc14610157575b600080fd5b425b6040519081526020015b60405180910390f35b6100f76100f2366004610995565b6101ca565b6040516100db929190610b61565b6100d16103c4565b61012061011b3660046109d1565b6103d7565b6040516100db9190610b0d565b61014061013b3660046109d1565b610578565b6040516100db93929190610bcb565b6100d1610608565b6100d1610165366004610973565b6001600160a01b03163190565b446100d1565b456100d1565b6040514181526020016100db565b436100d1565b6101206101a03660046109d1565b610681565b6101406101b3366004610995565b610800565b6100d16101c6366004610a25565b4090565b6000606060646001600160a01b031663a3b1b31d6040518163ffffffff1660e01b815260040160206040518083038186803b15801561020857600080fd5b505afa15801561021c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102409190610a3e565b915082516001600160401b0381111561025b5761025b610cfb565b60405190808252806020026020018201604052801561028e57816020015b60608152602001906001900390816102795790505b50905060005b83518110156103be576000808583815181106102b2576102b2610ce5565b6020026020010151600001516001600160a01b03168684815181106102d9576102d9610ce5565b6020026020010151602001516040516102f29190610af1565b6000604051808303816000865af19150503d806000811461032f576040519150601f19603f3d011682016040523d82523d6000602084013e610334565b606091505b50915091508161038b5760405162461bcd60e51b815260206004820181905260248201527f4d756c746963616c6c206167677265676174653a2063616c6c206661696c656460448201526064015b60405180910390fd5b8084848151811061039e5761039e610ce5565b6020026020010181905250505080806103b690610cb4565b915050610294565b50915091565b60006103d1600143610c6d565b40905090565b606081516001600160401b038111156103f2576103f2610cfb565b60405190808252806020026020018201604052801561043857816020015b6040805180820190915260008152606060208201528152602001906001900390816104105790505b509050600082515a61044a9190610c4b565b905060005b83518110156105705760008085838151811061046d5761046d610ce5565b6020026020010151600001516001600160a01b0316845a1161048f575a610491565b845b8785815181106104a3576104a3610ce5565b6020026020010151602001516040516104bc9190610af1565b60006040518083038160008787f1925050503d80600081146104fa576040519150601f19603f3d011682016040523d82523d6000602084013e6104ff565b606091505b5091509150861561052757816105275760405162461bcd60e51b815260040161038290610b20565b604051806040016040528083151581526020018281525085848151811061055057610550610ce5565b60200260200101819052505050808061056890610cb4565b91505061044f565b505092915050565b600080606060646001600160a01b031663a3b1b31d6040518163ffffffff1660e01b815260040160206040518083038186803b1580156105b757600080fd5b505afa1580156105cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ef9190610a3e565b9250434091506105ff8585610681565b90509250925092565b600060646001600160a01b031663a3b1b31d6040518163ffffffff1660e01b815260040160206040518083038186803b15801561064457600080fd5b505afa158015610658573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061067c9190610a3e565b905090565b606081516001600160401b0381111561069c5761069c610cfb565b6040519080825280602002602001820160405280156106e257816020015b6040805180820190915260008152606060208201528152602001906001900390816106ba5790505b50905060005b82518110156107f95760008084838151811061070657610706610ce5565b6020026020010151600001516001600160a01b031685848151811061072d5761072d610ce5565b6020026020010151602001516040516107469190610af1565b6000604051808303816000865af19150503d8060008114610783576040519150601f19603f3d011682016040523d82523d6000602084013e610788565b606091505b509150915085156107b057816107b05760405162461bcd60e51b815260040161038290610b20565b60405180604001604052808315158152602001828152508484815181106107d9576107d9610ce5565b6020026020010181905250505080806107f190610cb4565b9150506106e8565b5092915050565b6000806060610810600185610578565b9196909550909350915050565b80356001600160a01b038116811461083457600080fd5b919050565b600082601f83011261084a57600080fd5b813560206001600160401b038083111561086657610866610cfb565b8260051b610875838201610c1b565b8481528381019087850183890186018a101561089057600080fd5b600093505b86841015610966578035858111156108ac57600080fd5b89016040601f19828d0381018213156108c457600080fd5b6108cc610bf3565b6108d78a850161081d565b815282840135898111156108ea57600080fd5b8085019450508d603f8501126108ff57600080fd5b898401358981111561091357610913610cfb565b6109238b84601f84011601610c1b565b92508083528e8482870101111561093957600080fd5b808486018c85013760009083018b0152808a01919091528552505060019390930192918501918501610895565b5098975050505050505050565b60006020828403121561098557600080fd5b61098e8261081d565b9392505050565b6000602082840312156109a757600080fd5b81356001600160401b038111156109bd57600080fd5b6109c984828501610839565b949350505050565b600080604083850312156109e457600080fd5b823580151581146109f457600080fd5b915060208301356001600160401b03811115610a0f57600080fd5b610a1b85828601610839565b9150509250929050565b600060208284031215610a3757600080fd5b5035919050565b600060208284031215610a5057600080fd5b5051919050565b600082825180855260208086019550808260051b84010181860160005b84811015610ab857858303601f1901895281518051151584528401516040858501819052610aa481860183610ac5565b9a86019a9450505090830190600101610a74565b5090979650505050505050565b60008151808452610add816020860160208601610c84565b601f01601f19169290920160200192915050565b60008251610b03818460208701610c84565b9190910192915050565b60208152600061098e6020830184610a57565b60208082526021908201527f4d756c746963616c6c32206167677265676174653a2063616c6c206661696c656040820152601960fa1b606082015260800190565b600060408201848352602060408185015281855180845260608601915060608160051b870101935082870160005b82811015610bbd57605f19888703018452610bab868351610ac5565b95509284019290840190600101610b8f565b509398975050505050505050565b838152826020820152606060408201526000610bea6060830184610a57565b95945050505050565b604080519081016001600160401b0381118282101715610c1557610c15610cfb565b60405290565b604051601f8201601f191681016001600160401b0381118282101715610c4357610c43610cfb565b604052919050565b600082610c6857634e487b7160e01b600052601260045260246000fd5b500490565b600082821015610c7f57610c7f610ccf565b500390565b60005b83811015610c9f578181015183820152602001610c87565b83811115610cae576000848401525b50505050565b6000600019821415610cc857610cc8610ccf565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fdfea2646970667358221220ff49a8e6f7a224e3243c7eafac222d5d23d57879b0b2686d413724f2445009bb64736f6c63430008070033

Deployed ByteCode

0x608060405234801561001057600080fd5b50600436106100ca5760003560e01c806372425d9d1161007c57806372425d9d1461017257806386d516e814610178578063a8b0574e1461017e578063b9b3efe91461018c578063bce38bd714610192578063c3077fa9146101a5578063ee82ac5e146101b857600080fd5b80630f28c97d146100cf578063252dba42146100e457806327e86d6e146101055780632935cd901461010d578063399542e91461012d57806342cbb15c1461014f5780634d2301cc14610157575b600080fd5b425b6040519081526020015b60405180910390f35b6100f76100f2366004610995565b6101ca565b6040516100db929190610b61565b6100d16103c4565b61012061011b3660046109d1565b6103d7565b6040516100db9190610b0d565b61014061013b3660046109d1565b610578565b6040516100db93929190610bcb565b6100d1610608565b6100d1610165366004610973565b6001600160a01b03163190565b446100d1565b456100d1565b6040514181526020016100db565b436100d1565b6101206101a03660046109d1565b610681565b6101406101b3366004610995565b610800565b6100d16101c6366004610a25565b4090565b6000606060646001600160a01b031663a3b1b31d6040518163ffffffff1660e01b815260040160206040518083038186803b15801561020857600080fd5b505afa15801561021c573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906102409190610a3e565b915082516001600160401b0381111561025b5761025b610cfb565b60405190808252806020026020018201604052801561028e57816020015b60608152602001906001900390816102795790505b50905060005b83518110156103be576000808583815181106102b2576102b2610ce5565b6020026020010151600001516001600160a01b03168684815181106102d9576102d9610ce5565b6020026020010151602001516040516102f29190610af1565b6000604051808303816000865af19150503d806000811461032f576040519150601f19603f3d011682016040523d82523d6000602084013e610334565b606091505b50915091508161038b5760405162461bcd60e51b815260206004820181905260248201527f4d756c746963616c6c206167677265676174653a2063616c6c206661696c656460448201526064015b60405180910390fd5b8084848151811061039e5761039e610ce5565b6020026020010181905250505080806103b690610cb4565b915050610294565b50915091565b60006103d1600143610c6d565b40905090565b606081516001600160401b038111156103f2576103f2610cfb565b60405190808252806020026020018201604052801561043857816020015b6040805180820190915260008152606060208201528152602001906001900390816104105790505b509050600082515a61044a9190610c4b565b905060005b83518110156105705760008085838151811061046d5761046d610ce5565b6020026020010151600001516001600160a01b0316845a1161048f575a610491565b845b8785815181106104a3576104a3610ce5565b6020026020010151602001516040516104bc9190610af1565b60006040518083038160008787f1925050503d80600081146104fa576040519150601f19603f3d011682016040523d82523d6000602084013e6104ff565b606091505b5091509150861561052757816105275760405162461bcd60e51b815260040161038290610b20565b604051806040016040528083151581526020018281525085848151811061055057610550610ce5565b60200260200101819052505050808061056890610cb4565b91505061044f565b505092915050565b600080606060646001600160a01b031663a3b1b31d6040518163ffffffff1660e01b815260040160206040518083038186803b1580156105b757600080fd5b505afa1580156105cb573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ef9190610a3e565b9250434091506105ff8585610681565b90509250925092565b600060646001600160a01b031663a3b1b31d6040518163ffffffff1660e01b815260040160206040518083038186803b15801561064457600080fd5b505afa158015610658573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061067c9190610a3e565b905090565b606081516001600160401b0381111561069c5761069c610cfb565b6040519080825280602002602001820160405280156106e257816020015b6040805180820190915260008152606060208201528152602001906001900390816106ba5790505b50905060005b82518110156107f95760008084838151811061070657610706610ce5565b6020026020010151600001516001600160a01b031685848151811061072d5761072d610ce5565b6020026020010151602001516040516107469190610af1565b6000604051808303816000865af19150503d8060008114610783576040519150601f19603f3d011682016040523d82523d6000602084013e610788565b606091505b509150915085156107b057816107b05760405162461bcd60e51b815260040161038290610b20565b60405180604001604052808315158152602001828152508484815181106107d9576107d9610ce5565b6020026020010181905250505080806107f190610cb4565b9150506106e8565b5092915050565b6000806060610810600185610578565b9196909550909350915050565b80356001600160a01b038116811461083457600080fd5b919050565b600082601f83011261084a57600080fd5b813560206001600160401b038083111561086657610866610cfb565b8260051b610875838201610c1b565b8481528381019087850183890186018a101561089057600080fd5b600093505b86841015610966578035858111156108ac57600080fd5b89016040601f19828d0381018213156108c457600080fd5b6108cc610bf3565b6108d78a850161081d565b815282840135898111156108ea57600080fd5b8085019450508d603f8501126108ff57600080fd5b898401358981111561091357610913610cfb565b6109238b84601f84011601610c1b565b92508083528e8482870101111561093957600080fd5b808486018c85013760009083018b0152808a01919091528552505060019390930192918501918501610895565b5098975050505050505050565b60006020828403121561098557600080fd5b61098e8261081d565b9392505050565b6000602082840312156109a757600080fd5b81356001600160401b038111156109bd57600080fd5b6109c984828501610839565b949350505050565b600080604083850312156109e457600080fd5b823580151581146109f457600080fd5b915060208301356001600160401b03811115610a0f57600080fd5b610a1b85828601610839565b9150509250929050565b600060208284031215610a3757600080fd5b5035919050565b600060208284031215610a5057600080fd5b5051919050565b600082825180855260208086019550808260051b84010181860160005b84811015610ab857858303601f1901895281518051151584528401516040858501819052610aa481860183610ac5565b9a86019a9450505090830190600101610a74565b5090979650505050505050565b60008151808452610add816020860160208601610c84565b601f01601f19169290920160200192915050565b60008251610b03818460208701610c84565b9190910192915050565b60208152600061098e6020830184610a57565b60208082526021908201527f4d756c746963616c6c32206167677265676174653a2063616c6c206661696c656040820152601960fa1b606082015260800190565b600060408201848352602060408185015281855180845260608601915060608160051b870101935082870160005b82811015610bbd57605f19888703018452610bab868351610ac5565b95509284019290840190600101610b8f565b509398975050505050505050565b838152826020820152606060408201526000610bea6060830184610a57565b95945050505050565b604080519081016001600160401b0381118282101715610c1557610c15610cfb565b60405290565b604051601f8201601f191681016001600160401b0381118282101715610c4357610c43610cfb565b604052919050565b600082610c6857634e487b7160e01b600052601260045260246000fd5b500490565b600082821015610c7f57610c7f610ccf565b500390565b60005b83811015610c9f578181015183820152602001610c87565b83811115610cae576000848401525b50505050565b6000600019821415610cc857610cc8610ccf565b5060010190565b634e487b7160e01b600052601160045260246000fd5b634e487b7160e01b600052603260045260246000fd5b634e487b7160e01b600052604160045260246000fdfea2646970667358221220ff49a8e6f7a224e3243c7eafac222d5d23d57879b0b2686d413724f2445009bb64736f6c63430008070033