ETH Price: $1,972.33 (+0.13%)
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

More Info

Private Name Tags

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To

There are no matching entries

Please try again later

Advanced mode:
Parent Transaction Hash Method Block
From
To
View All Internal Transactions
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
OneStepProof2

Compiler Version
v0.6.11+commit.5ef660b1

Optimization Enabled:
Yes with 100 runs

Other Settings:
default evmVersion
// SPDX-License-Identifier: Apache-2.0

/*
 * Copyright 2019-2020, Offchain Labs, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/*

Structure of the extra proofs passed to operations accessing buffers (d, array of words):
 * d_0: 32 bytes header, includes the locations of other proofs as the first 5 bytes b_0 ... b_1
 * The words d[b_0..b_1]: merkle proof for first access, first element is the leaf that is accessed
 * The words d[b_1..b_2]: normalization proof for the case the buffer shrinks
 * The words d[b_2..b_3]: merkle proof for second access
 * The words d[b_4..b_5]: normalization proof for second access

Structure of merkle proofs:
 * first element is the leaf
 * other elements are the adjacent subtrees
 * the location in the tree is known from the argument passed to opcodes
 * if the access is outside the tree, the merkle proof is needed to confirm the size of the tree, and is the accessed location mod the original size of the tree

Structure of normalization proof:
 * needed if the tree shrinks
 * has three words
 * height of the tree (minus one)
 * left subtree hash
 * right subtree hash
 * if the height of the tree is 0, the left subtree hash is the single leaf of the tree instead
 * right subtree hash is checked that it's not zero, this ensures that the resulting tree is of minimal height

*/

pragma solidity ^0.6.11;

import "./IOneStepProof.sol";
import "./OneStepProofCommon.sol";
import "./Value.sol";
import "./Machine.sol";

// Originally forked from https://github.com/leapdao/solEVM-enforcer/tree/master

contract OneStepProof2 is OneStepProofCommon {
    /* solhint-disable no-inline-assembly */

    function makeZeros() internal pure returns (bytes32[] memory) {
        bytes32[] memory zeros = new bytes32[](64);
        zeros[0] = keccak1(0);
        for (uint256 i = 1; i < 64; i++) {
            zeros[i] = keccak2(zeros[i - 1], zeros[i - 1]);
        }
        return zeros;
    }

    function keccak1(bytes32 b) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked(b));
    }

    function keccak2(bytes32 a, bytes32 b) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked(a, b));
    }

    // hashes are normalized
    function get(
        bytes32 buf,
        uint256 loc,
        bytes32[] memory proof
    ) internal pure returns (bytes32) {
        // empty tree is full of zeros
        if (proof.length == 0) {
            require(buf == keccak1(bytes32(0)), "expected empty buffer");
            return 0;
        }
        bytes32 acc = keccak1(proof[0]);
        for (uint256 i = 1; i < proof.length; i++) {
            if (loc & 1 == 1) acc = keccak2(proof[i], acc);
            else acc = keccak2(acc, proof[i]);
            loc = loc >> 1;
        }
        require(acc == buf, "expected correct root");
        // maybe it is a zero outside the actual tree
        if (loc > 0) return 0;
        return proof[0];
    }

    function checkSize(
        bytes32 buf,
        uint256 loc,
        bytes32[] memory proof
    ) internal pure returns (bool) {
        // empty tree is full of zeros
        if (proof.length == 0) {
            require(buf == keccak1(bytes32(0)), "expected empty buffer");
            return true;
        }
        bytes32 acc = keccak1(proof[0]);
        bool check = true;
        bytes32[] memory zeros = makeZeros();
        for (uint256 i = 1; i < proof.length; i++) {
            if (loc & 1 == 1) acc = keccak2(proof[i], acc);
            else {
                acc = keccak2(acc, proof[i]);
                check = check && proof[i] == zeros[i - 1];
            }
            loc = loc >> 1;
        }
        require(acc == buf, "expected correct root");
        // maybe it is a zero outside the actual tree
        if (loc > 0) return true;
        return check;
    }

    function calcHeight(uint256 loc) internal pure returns (uint256) {
        if (loc == 0) return 1;
        else return 1 + calcHeight(loc >> 1);
    }

    function set(
        bytes32 buf,
        uint256 loc,
        bytes32 v,
        bytes32[] memory proof,
        uint256 nh,
        bytes32 normal1,
        bytes32 normal2
    ) internal pure returns (bytes32) {
        // three possibilities, the tree depth stays same, it becomes lower or it's extended
        bytes32 acc = keccak1(v);
        // check that the proof matches original
        get(buf, loc, proof);
        bytes32[] memory zeros = makeZeros();
        // extended
        if (loc >= (1 << (proof.length - 1))) {
            if (v == 0) return buf;
            uint256 height = calcHeight(loc);
            // build the left branch
            for (uint256 i = proof.length; i < height - 1; i++) {
                buf = keccak2(buf, zeros[i - 1]);
            }
            for (uint256 i = 1; i < height - 1; i++) {
                if (loc & 1 == 1) acc = keccak2(zeros[i - 1], acc);
                else acc = keccak2(acc, zeros[i - 1]);
                loc = loc >> 1;
            }
            return keccak2(buf, acc);
        }
        for (uint256 i = 1; i < proof.length; i++) {
            bytes32 a = loc & 1 == 1 ? proof[i] : acc;
            bytes32 b = loc & 1 == 1 ? acc : proof[i];
            acc = keccak2(a, b);
            loc = loc >> 1;
        }
        if (v != bytes32(0)) return acc;
        bytes32 res;
        if (nh == 0) {
            // Here we specify the leaf hash directly, since we're at height 0
            // There's no need for the leaf to be non-zero
            res = normal1;
        } else {
            // Since this is a branch, prove that its right side isn't 0,
            // as that wouldn't be normalized
            require(normal2 != zeros[nh], "right subtree cannot be zero");
            res = keccak2(normal1, normal2);
        }
        bytes32 acc2 = res;
        for (uint256 i = nh; i < proof.length - 1; i++) {
            acc2 = keccak2(acc2, zeros[i]);
        }
        require(acc2 == acc, "expected match");
        return res;
    }

    function getByte(bytes32 word, uint256 num) internal pure returns (uint256) {
        return (uint256(word) >> ((31 - num) * 8)) & 0xff;
    }

    function setByte(
        bytes32 word,
        uint256 num,
        uint256 b
    ) internal pure returns (bytes32) {
        bytes memory arr = bytes32ToArray(word);
        arr[num] = bytes1(uint8(b));
        return bytes32(bytes32FromArray(arr));
    }

    function setByte(
        bytes32 word,
        uint256 num,
        bytes1 b
    ) internal pure returns (bytes32) {
        bytes memory arr = bytes32ToArray(word);
        arr[num] = b;
        return bytes32(bytes32FromArray(arr));
    }

    function decode(
        bytes memory arr,
        bytes1 _start,
        bytes1 _end
    ) internal pure returns (bytes32[] memory) {
        uint256 len = uint256(uint8(_end) - uint8(_start));
        uint256 start = uint256(uint8(_start));
        bytes32[] memory res = new bytes32[](len);
        for (uint256 i = 0; i < len; i++) {
            res[i] = bytes32(bytes32FromArray(arr, (start + i) * 32));
        }
        return res;
    }

    struct BufferProof {
        bytes32[] proof1;
        bytes32[] nproof1;
        bytes32[] proof2;
        bytes32[] nproof2;
    }

    function decodeProof(bytes memory proof) internal pure returns (BufferProof memory) {
        bytes32[] memory proof1 = decode(proof, proof[0], proof[1]);
        bytes32[] memory nproof1 = decode(proof, proof[1], proof[2]);
        bytes32[] memory proof2 = decode(proof, proof[2], proof[3]);
        bytes32[] memory nproof2 = decode(proof, proof[3], proof[4]);
        return BufferProof(proof1, nproof1, proof2, nproof2);
    }

    function bytes32FromArray(bytes memory arr) internal pure returns (uint256) {
        uint256 res = 0;
        for (uint256 i = 0; i < arr.length; i++) {
            res = res << 8;
            res = res | uint256(uint8(arr[i]));
        }
        return res;
    }

    function bytes32FromArray(bytes memory arr, uint256 offset) internal pure returns (uint256) {
        uint256 res = 0;
        for (uint256 i = 0; i < 32; i++) {
            res = res << 8;
            res = res | uint256(uint8(arr[offset + i]));
        }
        return res;
    }

    function bytes32ToArray(bytes32 b) internal pure returns (bytes memory) {
        uint256 acc = uint256(b);
        bytes memory res = new bytes(32);
        for (uint256 i = 0; i < 32; i++) {
            res[31 - i] = bytes1(uint8(acc));
            acc = acc >> 8;
        }
        return res;
    }

    function getBuffer8(
        bytes32 buf,
        uint256 offset,
        BufferProof memory proof
    ) internal pure returns (uint256) {
        return getByte(get(buf, offset / 32, proof.proof1), offset % 32);
    }

    function checkBufferSize(
        bytes32 buf,
        uint256 offset,
        BufferProof memory proof
    ) internal pure returns (bool) {
        bytes32 w = get(buf, offset / 32, proof.proof1);
        for (uint256 i = offset % 32; i < 32; i++) {
            if (getByte(w, i) != 0) return false;
        }
        return checkSize(buf, offset / 32, proof.proof1);
    }

    function getBuffer64(
        bytes32 buf,
        uint256 offset,
        BufferProof memory proof
    ) internal pure returns (uint256) {
        bytes memory res = new bytes(8);
        bytes32 word = get(buf, offset / 32, proof.proof1);
        if ((offset % 32) + 8 > 32) {
            bytes32 word2 = get(buf, offset / 32 + 1, proof.proof2);
            for (uint256 i = 0; i < 8 - ((offset % 32) + 8 - 32); i++) {
                res[i] = bytes1(uint8(getByte(word, (offset % 32) + i)));
            }
            for (uint256 i = 8 - ((offset % 32) + 8 - 32); i < 8; i++) {
                res[i] = bytes1(uint8(getByte(word2, (offset + i) % 32)));
            }
        } else {
            for (uint256 i = 0; i < 8; i++) {
                res[i] = bytes1(uint8(getByte(word, (offset % 32) + i)));
            }
        }
        return bytes32FromArray(res);
    }

    function getBuffer256(
        bytes32 buf,
        uint256 offset,
        BufferProof memory proof
    ) internal pure returns (uint256) {
        bytes memory res = new bytes(32);
        bytes32 word = get(buf, offset / 32, proof.proof1);
        if ((offset % 32) + 32 > 32) {
            bytes32 word2 = get(buf, offset / 32 + 1, proof.proof2);
            for (uint256 i = 0; i < 32 - ((offset % 32) + 32 - 32); i++) {
                res[i] = bytes1(uint8(getByte(word, (offset % 32) + i)));
            }
            for (uint256 i = 32 - ((offset % 32) + 32 - 32); i < 32; i++) {
                res[i] = bytes1(uint8(getByte(word2, (offset + i) % 32)));
            }
        } else {
            for (uint256 i = 0; i < 32; i++) {
                res[i] = bytes1(uint8(getByte(word, (offset % 32) + i)));
            }
        }
        return bytes32FromArray(res);
    }

    function set(
        bytes32 buf,
        uint256 loc,
        bytes32 v,
        bytes32[] memory proof,
        bytes32[] memory nproof
    ) internal pure returns (bytes32) {
        require(nproof.length == 3, "BAD_NORMALIZATION_PROOF");
        return set(buf, loc, v, proof, uint256(nproof[0]), nproof[1], nproof[2]);
    }

    function setBuffer8(
        bytes32 buf,
        uint256 offset,
        uint256 b,
        BufferProof memory proof
    ) internal pure returns (bytes32) {
        bytes32 word = get(buf, offset / 32, proof.proof1);
        bytes32 nword = setByte(word, offset % 32, b);
        bytes32 res = set(buf, offset / 32, nword, proof.proof1, proof.nproof1);
        return res;
    }

    function setBuffer64(
        bytes32 buf,
        uint256 offset,
        uint256 val,
        BufferProof memory proof
    ) internal pure returns (bytes32) {
        bytes memory arr = bytes32ToArray(bytes32(val));
        bytes32 nword = get(buf, offset / 32, proof.proof1);
        if ((offset % 32) + 8 > 32) {
            for (uint256 i = 0; i < 8 - ((offset % 32) + 8 - 32); i++) {
                nword = setByte(nword, (offset + i) % 32, arr[i + 24]);
            }
            buf = set(buf, offset / 32, nword, proof.proof1, proof.nproof1);
            bytes32 nword2 = get(buf, offset / 32 + 1, proof.proof2);
            for (uint256 i = 8 - ((offset % 32) + 8 - 32); i < 8; i++) {
                nword2 = setByte(nword2, (offset + i) % 32, arr[i + 24]);
            }
            buf = set(buf, offset / 32 + 1, nword2, proof.proof2, proof.nproof2);
        } else {
            for (uint256 i = 0; i < 8; i++) {
                nword = setByte(nword, (offset % 32) + i, arr[i + 24]);
            }
            buf = set(buf, offset / 32, nword, proof.proof1, proof.nproof1);
        }
        return buf;
    }

    function parseProof(bytes memory proof)
        public
        pure
        returns (
            bytes32[] memory,
            bytes32[] memory,
            bytes32[] memory,
            bytes32[] memory
        )
    {
        BufferProof memory p = decodeProof(proof);
        return (p.proof1, p.nproof1, p.proof2, p.nproof2);
    }

    function setBuffer256(
        bytes32 buf,
        uint256 offset,
        uint256 val,
        BufferProof memory proof
    ) internal pure returns (bytes32) {
        bytes memory arr = bytes32ToArray(bytes32(val));
        bytes32 nword = get(buf, offset / 32, proof.proof1);
        if ((offset % 32) + 32 > 32) {
            for (uint256 i = 0; i < 32 - ((offset % 32) + 32 - 32); i++) {
                nword = setByte(nword, (offset % 32) + i, arr[i]);
            }
            buf = set(buf, offset / 32, nword, proof.proof1, proof.nproof1);
            bytes32 nword2 = get(buf, offset / 32 + 1, proof.proof2);
            for (uint256 i = 32 - ((offset % 32) + 32 - 32); i < 32; i++) {
                nword2 = setByte(nword2, (offset + i) % 32, arr[i]);
            }
            buf = set(buf, offset / 32 + 1, nword2, proof.proof2, proof.nproof2);
        } else {
            for (uint256 i = 0; i < 32; i++) {
                nword = setByte(nword, (offset % 32) + i, arr[i]);
            }
            buf = set(buf, offset / 32, nword, proof.proof1, proof.nproof1);
        }
        return buf;
    }

    function executeSendInsn(AssertionContext memory context) internal pure {
        Value.Data memory val2 = popVal(context.stack);
        Value.Data memory val1 = popVal(context.stack);
        if (!val2.isInt64() || !val1.isBuffer()) {
            handleOpcodeError(context);
            return;
        }
        if (val2.intVal > SEND_SIZE_LIMIT || val2.intVal == 0) {
            handleOpcodeError(context);
            return;
        }

        if (context.offset == context.proof.length) {
            // If we didn't pass the message data, the buffer must have been longer than the length param passed
            require(
                !checkBufferSize(val1.bufferHash, val2.intVal, decodeProof(context.bufProof)),
                "BUF_LENGTH"
            );
            handleOpcodeError(context);
            return;
        }

        // We've passed more data in the proof which is the data of the send because it isn't too long
        uint256 dataStart = context.offset;
        uint256 dataLength = val2.intVal;
        bytes memory proof = context.proof;
        bytes32 bufferHash = Hashing.bytesToBufferHash(proof, dataStart, dataLength);
        require(val1.hash() == bufferHash, "WRONG_SEND");

        bytes32 dataHash;
        assembly {
            dataHash := keccak256(add(add(proof, 32), dataStart), dataLength)
        }

        context.sendAcc = keccak256(abi.encodePacked(context.sendAcc, dataHash));
    }

    function executeGetBuffer8(AssertionContext memory context) internal pure {
        Value.Data memory val2 = popVal(context.stack);
        Value.Data memory val1 = popVal(context.stack);
        if (!val2.isInt64() || !val1.isBuffer()) {
            handleOpcodeError(context);
            return;
        }
        if (val2.intVal >= 1 << 64) {
            handleOpcodeError(context);
            return;
        }
        uint256 res = getBuffer8(val1.bufferHash, val2.intVal, decodeProof(context.bufProof));
        pushVal(context.stack, Value.newInt(res));
    }

    function executeGetBuffer64(AssertionContext memory context) internal pure {
        Value.Data memory val2 = popVal(context.stack);
        Value.Data memory val1 = popVal(context.stack);
        if (!val2.isInt64() || !val1.isBuffer()) {
            handleOpcodeError(context);
            return;
        }
        if (val2.intVal >= (1 << 64) - 7) {
            handleOpcodeError(context);
            return;
        }
        uint256 res = getBuffer64(val1.bufferHash, val2.intVal, decodeProof(context.bufProof));
        pushVal(context.stack, Value.newInt(res));
    }

    function executeGetBuffer256(AssertionContext memory context) internal pure {
        Value.Data memory val2 = popVal(context.stack);
        Value.Data memory val1 = popVal(context.stack);
        if (!val2.isInt64() || !val1.isBuffer()) {
            handleOpcodeError(context);
            return;
        }
        if (val2.intVal >= (1 << 64) - 31) {
            handleOpcodeError(context);
            return;
        }
        uint256 res = getBuffer256(val1.bufferHash, val2.intVal, decodeProof(context.bufProof));
        pushVal(context.stack, Value.newInt(res));
    }

    function executeSetBuffer8(AssertionContext memory context) internal pure {
        Value.Data memory val2 = popVal(context.stack);
        Value.Data memory val3 = popVal(context.stack);
        Value.Data memory val1 = popVal(context.stack);
        if (!val2.isInt64() || !val3.isInt() || !val1.isBuffer()) {
            handleOpcodeError(context);
            return;
        }
        if (val2.intVal >= 1 << 64 || val3.intVal >= 1 << 8) {
            handleOpcodeError(context);
            return;
        }
        bytes32 res =
            setBuffer8(val1.bufferHash, val2.intVal, val3.intVal, decodeProof(context.bufProof));
        pushVal(context.stack, Value.newBuffer(res));
    }

    function executeSetBuffer64(AssertionContext memory context) internal pure {
        Value.Data memory val2 = popVal(context.stack);
        Value.Data memory val3 = popVal(context.stack);
        Value.Data memory val1 = popVal(context.stack);
        if (!val2.isInt64() || !val3.isInt() || !val1.isBuffer()) {
            handleOpcodeError(context);
            return;
        }
        if (val2.intVal >= (1 << 64) - 7 || val3.intVal >= 1 << 64) {
            handleOpcodeError(context);
            return;
        }
        bytes32 res =
            setBuffer64(val1.bufferHash, val2.intVal, val3.intVal, decodeProof(context.bufProof));
        pushVal(context.stack, Value.newBuffer(res));
    }

    function executeSetBuffer256(AssertionContext memory context) internal pure {
        Value.Data memory val2 = popVal(context.stack);
        Value.Data memory val3 = popVal(context.stack);
        Value.Data memory val1 = popVal(context.stack);
        if (!val2.isInt64() || !val3.isInt() || !val1.isBuffer()) {
            handleOpcodeError(context);
            return;
        }
        if (val2.intVal >= (1 << 64) - 31) {
            handleOpcodeError(context);
            return;
        }
        bytes32 res =
            setBuffer256(val1.bufferHash, val2.intVal, val3.intVal, decodeProof(context.bufProof));
        pushVal(context.stack, Value.newBuffer(res));
    }

    function opInfo(uint256 opCode)
        internal
        pure
        override
        returns (
            uint256, // stack pops
            uint256, // auxstack pops
            uint64, // gas used
            function(AssertionContext memory) internal view // impl
        )
    {
        if (opCode == OP_GETBUFFER8) {
            return (2, 0, 10, executeGetBuffer8);
        } else if (opCode == OP_GETBUFFER64) {
            return (2, 0, 10, executeGetBuffer64);
        } else if (opCode == OP_GETBUFFER256) {
            return (2, 0, 10, executeGetBuffer256);
        } else if (opCode == OP_SETBUFFER8) {
            return (3, 0, 100, executeSetBuffer8);
        } else if (opCode == OP_SETBUFFER64) {
            return (3, 0, 100, executeSetBuffer64);
        } else if (opCode == OP_SETBUFFER256) {
            return (3, 0, 100, executeSetBuffer256);
        } else if (opCode == OP_SEND) {
            return (2, 0, 100, executeSendInsn);
        } else {
            revert("use another contract to handle other opcodes");
        }
    }
}

// SPDX-License-Identifier: Apache-2.0

/*
 * Copyright 2020, Offchain Labs, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

pragma solidity ^0.6.11;

import "../bridge/interfaces/IBridge.sol";
import "../bridge/interfaces/ISequencerInbox.sol";

interface IOneStepProof {
    // Bridges is sequencer bridge then delayed bridge
    function executeStep(
        address[2] calldata bridges,
        uint256 initialMessagesRead,
        bytes32[2] calldata accs,
        bytes calldata proof,
        bytes calldata bproof
    )
        external
        view
        returns (
            uint64 gas,
            uint256 afterMessagesRead,
            bytes32[4] memory fields
        );

    function executeStepDebug(
        address[2] calldata bridges,
        uint256 initialMessagesRead,
        bytes32[2] calldata accs,
        bytes calldata proof,
        bytes calldata bproof
    ) external view returns (string memory startMachine, string memory afterMachine);
}

// SPDX-License-Identifier: Apache-2.0

/*
 * Copyright 2019-2020, Offchain Labs, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

pragma solidity ^0.6.11;

import "./IOneStepProof.sol";
import "./Value.sol";
import "./Machine.sol";
import "../bridge/interfaces/IBridge.sol";
import "../bridge/interfaces/ISequencerInbox.sol";

abstract contract OneStepProofCommon is IOneStepProof {
    using Machine for Machine.Data;
    using Hashing for Value.Data;
    using Value for Value.Data;

    uint256 internal constant MAX_UINT256 = ((1 << 128) + 1) * ((1 << 128) - 1);

    uint64 internal constant ERROR_GAS_COST = 5;

    string internal constant BAD_IMM_TYP = "BAD_IMM_TYP";
    string internal constant NO_IMM = "NO_IMM";
    string internal constant STACK_MISSING = "STACK_MISSING";
    string internal constant AUX_MISSING = "AUX_MISSING";
    string internal constant STACK_MANY = "STACK_MANY";
    string internal constant AUX_MANY = "AUX_MANY";
    string internal constant INBOX_VAL = "INBOX_VAL";
    // Stop and arithmetic ops
    uint8 internal constant OP_ADD = 0x01;
    uint8 internal constant OP_MUL = 0x02;
    uint8 internal constant OP_SUB = 0x03;
    uint8 internal constant OP_DIV = 0x04;
    uint8 internal constant OP_SDIV = 0x05;
    uint8 internal constant OP_MOD = 0x06;
    uint8 internal constant OP_SMOD = 0x07;
    uint8 internal constant OP_ADDMOD = 0x08;
    uint8 internal constant OP_MULMOD = 0x09;
    uint8 internal constant OP_EXP = 0x0a;
    uint8 internal constant OP_SIGNEXTEND = 0x0b;

    // Comparison & bitwise logic
    uint8 internal constant OP_LT = 0x10;
    uint8 internal constant OP_GT = 0x11;
    uint8 internal constant OP_SLT = 0x12;
    uint8 internal constant OP_SGT = 0x13;
    uint8 internal constant OP_EQ = 0x14;
    uint8 internal constant OP_ISZERO = 0x15;
    uint8 internal constant OP_AND = 0x16;
    uint8 internal constant OP_OR = 0x17;
    uint8 internal constant OP_XOR = 0x18;
    uint8 internal constant OP_NOT = 0x19;
    uint8 internal constant OP_BYTE = 0x1a;
    uint8 internal constant OP_SHL = 0x1b;
    uint8 internal constant OP_SHR = 0x1c;
    uint8 internal constant OP_SAR = 0x1d;

    // SHA3
    uint8 internal constant OP_HASH = 0x20;
    uint8 internal constant OP_TYPE = 0x21;
    uint8 internal constant OP_ETHHASH2 = 0x22;
    uint8 internal constant OP_KECCAK_F = 0x23;
    uint8 internal constant OP_SHA256_F = 0x24;

    // Stack, Memory, Storage and Flow Operations
    uint8 internal constant OP_POP = 0x30;
    uint8 internal constant OP_SPUSH = 0x31;
    uint8 internal constant OP_RPUSH = 0x32;
    uint8 internal constant OP_RSET = 0x33;
    uint8 internal constant OP_JUMP = 0x34;
    uint8 internal constant OP_CJUMP = 0x35;
    uint8 internal constant OP_STACKEMPTY = 0x36;
    uint8 internal constant OP_PCPUSH = 0x37;
    uint8 internal constant OP_AUXPUSH = 0x38;
    uint8 internal constant OP_AUXPOP = 0x39;
    uint8 internal constant OP_AUXSTACKEMPTY = 0x3a;
    uint8 internal constant OP_NOP = 0x3b;
    uint8 internal constant OP_ERRPUSH = 0x3c;
    uint8 internal constant OP_ERRSET = 0x3d;

    // Duplication and Exchange operations
    uint8 internal constant OP_DUP0 = 0x40;
    uint8 internal constant OP_DUP1 = 0x41;
    uint8 internal constant OP_DUP2 = 0x42;
    uint8 internal constant OP_SWAP1 = 0x43;
    uint8 internal constant OP_SWAP2 = 0x44;

    // Tuple operations
    uint8 internal constant OP_TGET = 0x50;
    uint8 internal constant OP_TSET = 0x51;
    uint8 internal constant OP_TLEN = 0x52;
    uint8 internal constant OP_XGET = 0x53;
    uint8 internal constant OP_XSET = 0x54;

    // Logging operations
    uint8 internal constant OP_BREAKPOINT = 0x60;
    uint8 internal constant OP_LOG = 0x61;

    // System operations
    uint8 internal constant OP_SEND = 0x70;
    // OP_INBOX_PEEK has been removed
    uint8 internal constant OP_INBOX = 0x72;
    uint8 internal constant OP_ERROR = 0x73;
    uint8 internal constant OP_STOP = 0x74;
    uint8 internal constant OP_SETGAS = 0x75;
    uint8 internal constant OP_PUSHGAS = 0x76;
    uint8 internal constant OP_ERR_CODE_POINT = 0x77;
    uint8 internal constant OP_PUSH_INSN = 0x78;
    uint8 internal constant OP_PUSH_INSN_IMM = 0x79;
    // uint8 private constant OP_OPEN_INSN = 0x7a;
    uint8 internal constant OP_SIDELOAD = 0x7b;

    uint8 internal constant OP_ECRECOVER = 0x80;
    uint8 internal constant OP_ECADD = 0x81;
    uint8 internal constant OP_ECMUL = 0x82;
    uint8 internal constant OP_ECPAIRING = 0x83;

    uint8 internal constant OP_DEBUGPRINT = 0x90;

    // Buffer operations
    uint8 internal constant OP_NEWBUFFER = 0xa0;
    uint8 internal constant OP_GETBUFFER8 = 0xa1;
    uint8 internal constant OP_GETBUFFER64 = 0xa2;
    uint8 internal constant OP_GETBUFFER256 = 0xa3;
    uint8 internal constant OP_SETBUFFER8 = 0xa4;
    uint8 internal constant OP_SETBUFFER64 = 0xa5;
    uint8 internal constant OP_SETBUFFER256 = 0xa6;

    uint8 internal constant CODE_POINT_TYPECODE = 1;
    bytes32 internal constant CODE_POINT_ERROR =
        keccak256(abi.encodePacked(CODE_POINT_TYPECODE, uint8(0), bytes32(0)));

    uint256 internal constant SEND_SIZE_LIMIT = 10000;

    // accs is [sendAcc, logAcc]
    function executeStep(
        address[2] calldata bridges,
        uint256 initialMessagesRead,
        bytes32[2] calldata accs,
        bytes calldata proof,
        bytes calldata bproof
    )
        external
        view
        override
        returns (
            uint64 gas,
            uint256 afterMessagesRead,
            bytes32[4] memory fields
        )
    {
        AssertionContext memory context =
            initializeExecutionContext(initialMessagesRead, accs, proof, bproof, bridges);

        executeOp(context);

        return returnContext(context);
    }

    function executeStepDebug(
        address[2] calldata bridges,
        uint256 initialMessagesRead,
        bytes32[2] calldata accs,
        bytes calldata proof,
        bytes calldata bproof
    ) external view override returns (string memory startMachine, string memory afterMachine) {
        AssertionContext memory context =
            initializeExecutionContext(initialMessagesRead, accs, proof, bproof, bridges);

        executeOp(context);
        startMachine = Machine.toString(context.startMachine);
        afterMachine = Machine.toString(context.afterMachine);
    }

    // fields
    // startMachineHash,
    // endMachineHash,
    // afterInboxAcc,
    // afterMessagesHash,
    // afterLogsHash

    function returnContext(AssertionContext memory context)
        internal
        pure
        returns (
            uint64 gas,
            uint256 afterMessagesRead,
            bytes32[4] memory fields
        )
    {
        return (
            context.gas,
            context.totalMessagesRead,
            [
                Machine.hash(context.startMachine),
                Machine.hash(context.afterMachine),
                context.sendAcc,
                context.logAcc
            ]
        );
    }

    struct ValueStack {
        uint256 length;
        Value.Data[] values;
    }

    function popVal(ValueStack memory stack) internal pure returns (Value.Data memory) {
        Value.Data memory val = stack.values[stack.length - 1];
        stack.length--;
        return val;
    }

    function pushVal(ValueStack memory stack, Value.Data memory val) internal pure {
        stack.values[stack.length] = val;
        stack.length++;
    }

    struct AssertionContext {
        ISequencerInbox sequencerBridge;
        IBridge delayedBridge;
        Machine.Data startMachine;
        Machine.Data afterMachine;
        uint256 totalMessagesRead;
        bytes32 sendAcc;
        bytes32 logAcc;
        uint64 gas;
        ValueStack stack;
        ValueStack auxstack;
        bool hadImmediate;
        uint8 opcode;
        bytes proof;
        uint256 offset;
        // merkle proofs for buffer
        bytes bufProof;
        bool errorOccurred;
    }

    function handleError(AssertionContext memory context) internal pure {
        context.errorOccurred = true;
    }

    function deductGas(AssertionContext memory context, uint64 amount)
        internal
        pure
        returns (bool)
    {
        if (context.afterMachine.avmGasRemaining < amount) {
            // ERROR + GAS_SET
            context.gas += ERROR_GAS_COST;
            context.afterMachine.avmGasRemaining = MAX_UINT256;
            return true;
        } else {
            context.gas += amount;
            context.afterMachine.avmGasRemaining -= amount;
            return false;
        }
    }

    function handleOpcodeError(AssertionContext memory context) internal pure {
        handleError(context);
    }

    function initializeExecutionContext(
        uint256 initialMessagesRead,
        bytes32[2] calldata accs,
        bytes memory proof,
        bytes memory bproof,
        address[2] calldata bridges
    ) internal pure returns (AssertionContext memory) {
        uint8 opCode = uint8(proof[0]);
        uint8 stackCount = uint8(proof[1]);
        uint8 auxstackCount = uint8(proof[2]);
        uint256 offset = 3;

        // Leave some extra space for values pushed on the stack in the proofs
        Value.Data[] memory stackVals = new Value.Data[](stackCount + 4);
        Value.Data[] memory auxstackVals = new Value.Data[](auxstackCount + 4);
        for (uint256 i = 0; i < stackCount; i++) {
            (offset, stackVals[i]) = Marshaling.deserialize(proof, offset);
        }
        for (uint256 i = 0; i < auxstackCount; i++) {
            (offset, auxstackVals[i]) = Marshaling.deserialize(proof, offset);
        }
        Machine.Data memory mach;
        (offset, mach) = Machine.deserializeMachine(proof, offset);

        uint8 immediate = uint8(proof[offset]);
        offset += 1;

        AssertionContext memory context;
        context.sequencerBridge = ISequencerInbox(bridges[0]);
        context.delayedBridge = IBridge(bridges[1]);
        context.startMachine = mach;
        context.afterMachine = mach.clone();
        context.totalMessagesRead = initialMessagesRead;
        context.sendAcc = accs[0];
        context.logAcc = accs[1];
        context.gas = 0;
        context.stack = ValueStack(stackCount, stackVals);
        context.auxstack = ValueStack(auxstackCount, auxstackVals);
        context.hadImmediate = immediate == 1;
        context.opcode = opCode;
        context.proof = proof;
        context.bufProof = bproof;
        context.errorOccurred = false;
        context.offset = offset;

        require(immediate == 0 || immediate == 1, BAD_IMM_TYP);
        Value.Data memory cp;
        if (immediate == 0) {
            cp = Value.newCodePoint(uint8(opCode), context.startMachine.instructionStackHash);
        } else {
            // If we have an immediate, there must be at least one stack value
            require(stackVals.length > 0, NO_IMM);
            cp = Value.newCodePoint(
                uint8(opCode),
                context.startMachine.instructionStackHash,
                stackVals[stackCount - 1]
            );
        }
        context.startMachine.instructionStackHash = cp.hash();

        // Add the stack and auxstack values to the start machine
        uint256 i = 0;
        for (i = 0; i < stackCount - immediate; i++) {
            context.startMachine.addDataStackValue(stackVals[i]);
        }
        for (i = 0; i < auxstackCount; i++) {
            context.startMachine.addAuxStackValue(auxstackVals[i]);
        }

        return context;
    }

    function executeOp(AssertionContext memory context) internal view {
        (
            uint256 dataPopCount,
            uint256 auxPopCount,
            uint64 gasCost,
            function(AssertionContext memory) internal view impl
        ) = opInfo(context.opcode);

        // Require the prover to submit the minimal number of stack items
        require(
            ((dataPopCount > 0 || !context.hadImmediate) && context.stack.length <= dataPopCount) ||
                (context.hadImmediate && dataPopCount == 0 && context.stack.length == 1),
            STACK_MANY
        );
        require(context.auxstack.length <= auxPopCount, AUX_MANY);

        // Update end machine gas remaining before running opcode
        if (context.stack.length < dataPopCount) {
            // If we have insufficient values, reject the proof unless the stack has been fully exhausted
            require(
                context.afterMachine.dataStack.hash() == Value.newEmptyTuple().hash(),
                STACK_MISSING
            );
            deductGas(context, ERROR_GAS_COST);
            // If the stack is empty, the instruction underflowed so we have hit an error
            handleError(context);
        } else if (context.auxstack.length < auxPopCount) {
            // If we have insufficient values, reject the proof unless the auxstack has been fully exhausted
            require(
                context.afterMachine.auxStack.hash() == Value.newEmptyTuple().hash(),
                AUX_MISSING
            );
            deductGas(context, ERROR_GAS_COST);
            // If the auxstack is empty, the instruction underflowed so we have hit an error
            handleError(context);
        } else if (deductGas(context, gasCost)) {
            handleError(context);
        } else {
            impl(context);
        }

        if (context.errorOccurred) {
            if (context.afterMachine.errHandlerHash == CODE_POINT_ERROR) {
                context.afterMachine.setErrorStop();
            } else {
                // Clear error
                context.errorOccurred = false;
                context.afterMachine.instructionStackHash = context.afterMachine.errHandlerHash;

                if (!(context.hadImmediate && dataPopCount == 0)) {
                    context.stack.length = 0;
                }
                context.auxstack.length = 0;
            }
        }

        // Add the stack and auxstack values to the start machine
        uint256 i = 0;

        for (i = 0; i < context.stack.length; i++) {
            context.afterMachine.addDataStackValue(context.stack.values[i]);
        }

        for (i = 0; i < context.auxstack.length; i++) {
            context.afterMachine.addAuxStackValue(context.auxstack.values[i]);
        }
    }

    function opInfo(uint256 opCode)
        internal
        pure
        virtual
        returns (
            uint256, // stack pops
            uint256, // auxstack pops
            uint64, // gas used
            function(AssertionContext memory) internal view // impl
        );
}

// SPDX-License-Identifier: Apache-2.0

/*
 * Copyright 2019-2021, Offchain Labs, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

pragma solidity ^0.6.11;

library Value {
    uint8 internal constant INT_TYPECODE = 0;
    uint8 internal constant CODE_POINT_TYPECODE = 1;
    uint8 internal constant HASH_PRE_IMAGE_TYPECODE = 2;
    uint8 internal constant TUPLE_TYPECODE = 3;
    uint8 internal constant BUFFER_TYPECODE = TUPLE_TYPECODE + 9;
    // All values received from clients will have type codes less than the VALUE_TYPE_COUNT
    uint8 internal constant VALUE_TYPE_COUNT = TUPLE_TYPECODE + 10;

    // The following types do not show up in the marshalled format and is
    // only used for internal tracking purposes
    uint8 internal constant HASH_ONLY = 100;

    struct CodePoint {
        uint8 opcode;
        bytes32 nextCodePoint;
        Data[] immediate;
    }

    struct Data {
        uint256 intVal;
        CodePoint cpVal;
        Data[] tupleVal;
        bytes32 bufferHash;
        uint8 typeCode;
        uint256 size;
    }

    function tupleTypeCode() internal pure returns (uint8) {
        return TUPLE_TYPECODE;
    }

    function tuplePreImageTypeCode() internal pure returns (uint8) {
        return HASH_PRE_IMAGE_TYPECODE;
    }

    function intTypeCode() internal pure returns (uint8) {
        return INT_TYPECODE;
    }

    function bufferTypeCode() internal pure returns (uint8) {
        return BUFFER_TYPECODE;
    }

    function codePointTypeCode() internal pure returns (uint8) {
        return CODE_POINT_TYPECODE;
    }

    function valueTypeCode() internal pure returns (uint8) {
        return VALUE_TYPE_COUNT;
    }

    function hashOnlyTypeCode() internal pure returns (uint8) {
        return HASH_ONLY;
    }

    function isValidTupleSize(uint256 size) internal pure returns (bool) {
        return size <= 8;
    }

    function typeCodeVal(Data memory val) internal pure returns (Data memory) {
        if (val.typeCode == 2) {
            // Map HashPreImage to Tuple
            return newInt(TUPLE_TYPECODE);
        }
        return newInt(val.typeCode);
    }

    function valLength(Data memory val) internal pure returns (uint8) {
        if (val.typeCode == TUPLE_TYPECODE) {
            return uint8(val.tupleVal.length);
        } else {
            return 1;
        }
    }

    function isInt(Data memory val) internal pure returns (bool) {
        return val.typeCode == INT_TYPECODE;
    }

    function isInt64(Data memory val) internal pure returns (bool) {
        return val.typeCode == INT_TYPECODE && val.intVal < (1 << 64);
    }

    function isCodePoint(Data memory val) internal pure returns (bool) {
        return val.typeCode == CODE_POINT_TYPECODE;
    }

    function isTuple(Data memory val) internal pure returns (bool) {
        return val.typeCode == TUPLE_TYPECODE;
    }

    function isBuffer(Data memory val) internal pure returns (bool) {
        return val.typeCode == BUFFER_TYPECODE;
    }

    function newEmptyTuple() internal pure returns (Data memory) {
        return newTuple(new Data[](0));
    }

    function newBoolean(bool val) internal pure returns (Data memory) {
        if (val) {
            return newInt(1);
        } else {
            return newInt(0);
        }
    }

    function newInt(uint256 _val) internal pure returns (Data memory) {
        return
            Data(_val, CodePoint(0, 0, new Data[](0)), new Data[](0), 0, INT_TYPECODE, uint256(1));
    }

    function newHashedValue(bytes32 valueHash, uint256 valueSize)
        internal
        pure
        returns (Data memory)
    {
        return
            Data(
                uint256(valueHash),
                CodePoint(0, 0, new Data[](0)),
                new Data[](0),
                0,
                HASH_ONLY,
                valueSize
            );
    }

    function newTuple(Data[] memory _val) internal pure returns (Data memory) {
        require(isValidTupleSize(_val.length), "Tuple must have valid size");
        uint256 size = 1;

        for (uint256 i = 0; i < _val.length; i++) {
            size += _val[i].size;
        }

        return Data(0, CodePoint(0, 0, new Data[](0)), _val, 0, TUPLE_TYPECODE, size);
    }

    function newTuplePreImage(bytes32 preImageHash, uint256 size)
        internal
        pure
        returns (Data memory)
    {
        return
            Data(
                uint256(preImageHash),
                CodePoint(0, 0, new Data[](0)),
                new Data[](0),
                0,
                HASH_PRE_IMAGE_TYPECODE,
                size
            );
    }

    function newCodePoint(uint8 opCode, bytes32 nextHash) internal pure returns (Data memory) {
        return newCodePoint(CodePoint(opCode, nextHash, new Data[](0)));
    }

    function newCodePoint(
        uint8 opCode,
        bytes32 nextHash,
        Data memory immediate
    ) internal pure returns (Data memory) {
        Data[] memory imm = new Data[](1);
        imm[0] = immediate;
        return newCodePoint(CodePoint(opCode, nextHash, imm));
    }

    function newCodePoint(CodePoint memory _val) private pure returns (Data memory) {
        return Data(0, _val, new Data[](0), 0, CODE_POINT_TYPECODE, uint256(1));
    }

    function newBuffer(bytes32 bufHash) internal pure returns (Data memory) {
        return
            Data(
                uint256(0),
                CodePoint(0, 0, new Data[](0)),
                new Data[](0),
                bufHash,
                BUFFER_TYPECODE,
                uint256(1)
            );
    }
}

// SPDX-License-Identifier: Apache-2.0

/*
 * Copyright 2019-2021, Offchain Labs, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

pragma solidity ^0.6.11;

import "./Marshaling.sol";

import "../libraries/DebugPrint.sol";

library Machine {
    using Hashing for Value.Data;

    // Make sure these don't conflict with Challenge.MACHINE_UNREACHABLE (currently 100)
    uint256 internal constant MACHINE_EXTENSIVE = 0;
    uint256 internal constant MACHINE_ERRORSTOP = 1;
    uint256 internal constant MACHINE_HALT = 2;

    function addStackVal(Value.Data memory stackValHash, Value.Data memory valHash)
        internal
        pure
        returns (Value.Data memory)
    {
        Value.Data[] memory vals = new Value.Data[](2);
        vals[0] = valHash;
        vals[1] = stackValHash;

        return Hashing.getTuplePreImage(vals);
    }

    struct Data {
        bytes32 instructionStackHash;
        Value.Data dataStack;
        Value.Data auxStack;
        Value.Data registerVal;
        Value.Data staticVal;
        uint256 avmGasRemaining;
        bytes32 errHandlerHash;
        uint256 status;
    }

    function toString(Data memory machine) internal pure returns (string memory) {
        return
            string(
                abi.encodePacked(
                    "Machine(",
                    DebugPrint.bytes32string(machine.instructionStackHash),
                    ", \n",
                    DebugPrint.bytes32string(machine.dataStack.hash()),
                    ", \n",
                    DebugPrint.bytes32string(machine.auxStack.hash()),
                    ", \n",
                    DebugPrint.bytes32string(machine.registerVal.hash()),
                    ", \n",
                    DebugPrint.bytes32string(machine.staticVal.hash()),
                    ", \n",
                    DebugPrint.uint2str(machine.avmGasRemaining),
                    ", \n",
                    DebugPrint.bytes32string(machine.errHandlerHash),
                    ")\n"
                )
            );
    }

    function setErrorStop(Data memory machine) internal pure {
        machine.status = MACHINE_ERRORSTOP;
    }

    function setHalt(Data memory machine) internal pure {
        machine.status = MACHINE_HALT;
    }

    function addDataStackValue(Data memory machine, Value.Data memory val) internal pure {
        machine.dataStack = addStackVal(machine.dataStack, val);
    }

    function addAuxStackValue(Data memory machine, Value.Data memory val) internal pure {
        machine.auxStack = addStackVal(machine.auxStack, val);
    }

    function hash(Data memory machine) internal pure returns (bytes32) {
        if (machine.status == MACHINE_HALT) {
            return bytes32(uint256(0));
        } else if (machine.status == MACHINE_ERRORSTOP) {
            return bytes32(uint256(1));
        } else {
            return
                keccak256(
                    abi.encodePacked(
                        machine.instructionStackHash,
                        machine.dataStack.hash(),
                        machine.auxStack.hash(),
                        machine.registerVal.hash(),
                        machine.staticVal.hash(),
                        machine.avmGasRemaining,
                        machine.errHandlerHash
                    )
                );
        }
    }

    function clone(Data memory machine) internal pure returns (Data memory) {
        return
            Data(
                machine.instructionStackHash,
                machine.dataStack,
                machine.auxStack,
                machine.registerVal,
                machine.staticVal,
                machine.avmGasRemaining,
                machine.errHandlerHash,
                machine.status
            );
    }

    function deserializeMachine(bytes memory data, uint256 offset)
        internal
        pure
        returns (
            uint256, // offset
            Data memory // machine
        )
    {
        Data memory m;
        m.status = MACHINE_EXTENSIVE;
        uint256 instructionStack;
        uint256 errHandler;
        (offset, instructionStack) = Marshaling.deserializeInt(data, offset);

        (offset, m.dataStack) = Marshaling.deserializeHashPreImage(data, offset);
        (offset, m.auxStack) = Marshaling.deserializeHashPreImage(data, offset);
        (offset, m.registerVal) = Marshaling.deserialize(data, offset);
        (offset, m.staticVal) = Marshaling.deserialize(data, offset);
        (offset, m.avmGasRemaining) = Marshaling.deserializeInt(data, offset);
        (offset, errHandler) = Marshaling.deserializeInt(data, offset);

        m.instructionStackHash = bytes32(instructionStack);
        m.errHandlerHash = bytes32(errHandler);
        return (offset, m);
    }
}

// SPDX-License-Identifier: Apache-2.0

/*
 * Copyright 2021, Offchain Labs, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

pragma solidity ^0.6.11;

interface IBridge {
    event MessageDelivered(
        uint256 indexed messageIndex,
        bytes32 indexed beforeInboxAcc,
        address inbox,
        uint8 kind,
        address sender,
        bytes32 messageDataHash
    );

    event BridgeCallTriggered(
        address indexed outbox,
        address indexed destAddr,
        uint256 amount,
        bytes data
    );

    event InboxToggle(address indexed inbox, bool enabled);

    event OutboxToggle(address indexed outbox, bool enabled);

    function deliverMessageToInbox(
        uint8 kind,
        address sender,
        bytes32 messageDataHash
    ) external payable returns (uint256);

    function executeCall(
        address destAddr,
        uint256 amount,
        bytes calldata data
    ) external returns (bool success, bytes memory returnData);

    // These are only callable by the admin
    function setInbox(address inbox, bool enabled) external;

    function setOutbox(address inbox, bool enabled) external;

    // View functions

    function activeOutbox() external view returns (address);

    function allowedInboxes(address inbox) external view returns (bool);

    function allowedOutboxes(address outbox) external view returns (bool);

    function inboxAccs(uint256 index) external view returns (bytes32);

    function messageCount() external view returns (uint256);
}

// SPDX-License-Identifier: Apache-2.0

/*
 * Copyright 2021, Offchain Labs, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

pragma solidity ^0.6.11;

interface ISequencerInbox {
    event SequencerBatchDelivered(
        uint256 indexed firstMessageNum,
        bytes32 indexed beforeAcc,
        uint256 newMessageCount,
        bytes32 afterAcc,
        bytes transactions,
        uint256[] lengths,
        uint256[] sectionsMetadata,
        uint256 seqBatchIndex,
        address sequencer
    );

    event SequencerBatchDeliveredFromOrigin(
        uint256 indexed firstMessageNum,
        bytes32 indexed beforeAcc,
        uint256 newMessageCount,
        bytes32 afterAcc,
        uint256 seqBatchIndex
    );

    event DelayedInboxForced(
        uint256 indexed firstMessageNum,
        bytes32 indexed beforeAcc,
        uint256 newMessageCount,
        uint256 totalDelayedMessagesRead,
        bytes32[2] afterAccAndDelayed,
        uint256 seqBatchIndex
    );

    /// @notice DEPRECATED - look at IsSequencerUpdated for new updates
    // event SequencerAddressUpdated(address newAddress);

    event IsSequencerUpdated(address addr, bool isSequencer);
    event MaxDelayUpdated(uint256 newMaxDelayBlocks, uint256 newMaxDelaySeconds);

    /// @notice DEPRECATED - look at MaxDelayUpdated for new updates
    // event MaxDelayBlocksUpdated(uint256 newValue);
    /// @notice DEPRECATED - look at MaxDelayUpdated for new updates
    // event MaxDelaySecondsUpdated(uint256 newValue);

    function setMaxDelay(uint256 newMaxDelayBlocks, uint256 newMaxDelaySeconds) external;

    function setIsSequencer(address addr, bool isSequencer) external;

    function messageCount() external view returns (uint256);

    function maxDelayBlocks() external view returns (uint256);

    function maxDelaySeconds() external view returns (uint256);

    function inboxAccs(uint256 index) external view returns (bytes32);

    function getInboxAccsLength() external view returns (uint256);

    function proveInboxContainsMessage(bytes calldata proof, uint256 inboxCount)
        external
        view
        returns (uint256, bytes32);

    /// @notice DEPRECATED - use isSequencer instead
    function sequencer() external view returns (address);

    function isSequencer(address seq) external view returns (bool);
}

// SPDX-License-Identifier: Apache-2.0

/*
 * Copyright 2019-2021, Offchain Labs, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

pragma solidity ^0.6.11;

import "./Value.sol";
import "./Hashing.sol";

import "../libraries/BytesLib.sol";

library Marshaling {
    using BytesLib for bytes;
    using Value for Value.Data;

    function deserializeHashPreImage(bytes memory data, uint256 startOffset)
        internal
        pure
        returns (uint256 offset, Value.Data memory value)
    {
        require(data.length >= startOffset && data.length - startOffset >= 64, "too short");
        bytes32 hashData;
        uint256 size;
        (offset, hashData) = extractBytes32(data, startOffset);
        (offset, size) = deserializeInt(data, offset);
        return (offset, Value.newTuplePreImage(hashData, size));
    }

    function deserializeInt(bytes memory data, uint256 startOffset)
        internal
        pure
        returns (
            uint256, // offset
            uint256 // val
        )
    {
        require(data.length >= startOffset && data.length - startOffset >= 32, "too short");
        return (startOffset + 32, data.toUint(startOffset));
    }

    function deserializeBytes32(bytes memory data, uint256 startOffset)
        internal
        pure
        returns (
            uint256, // offset
            bytes32 // val
        )
    {
        require(data.length >= startOffset && data.length - startOffset >= 32, "too short");
        return (startOffset + 32, data.toBytes32(startOffset));
    }

    function deserializeCodePoint(bytes memory data, uint256 startOffset)
        internal
        pure
        returns (
            uint256, // offset
            Value.Data memory // val
        )
    {
        uint256 offset = startOffset;
        uint8 immediateType;
        uint8 opCode;
        Value.Data memory immediate;
        bytes32 nextHash;

        (offset, immediateType) = extractUint8(data, offset);
        (offset, opCode) = extractUint8(data, offset);
        if (immediateType == 1) {
            (offset, immediate) = deserialize(data, offset);
        }
        (offset, nextHash) = extractBytes32(data, offset);
        if (immediateType == 1) {
            return (offset, Value.newCodePoint(opCode, nextHash, immediate));
        }
        return (offset, Value.newCodePoint(opCode, nextHash));
    }

    function deserializeTuple(
        uint8 memberCount,
        bytes memory data,
        uint256 startOffset
    )
        internal
        pure
        returns (
            uint256, // offset
            Value.Data[] memory // val
        )
    {
        uint256 offset = startOffset;
        Value.Data[] memory members = new Value.Data[](memberCount);
        for (uint8 i = 0; i < memberCount; i++) {
            (offset, members[i]) = deserialize(data, offset);
        }
        return (offset, members);
    }

    function deserialize(bytes memory data, uint256 startOffset)
        internal
        pure
        returns (
            uint256, // offset
            Value.Data memory // val
        )
    {
        require(startOffset < data.length, "invalid offset");
        (uint256 offset, uint8 valType) = extractUint8(data, startOffset);
        if (valType == Value.intTypeCode()) {
            uint256 intVal;
            (offset, intVal) = deserializeInt(data, offset);
            return (offset, Value.newInt(intVal));
        } else if (valType == Value.codePointTypeCode()) {
            return deserializeCodePoint(data, offset);
        } else if (valType == Value.bufferTypeCode()) {
            bytes32 hashVal;
            (offset, hashVal) = deserializeBytes32(data, offset);
            return (offset, Value.newBuffer(hashVal));
        } else if (valType == Value.tuplePreImageTypeCode()) {
            return deserializeHashPreImage(data, offset);
        } else if (valType >= Value.tupleTypeCode() && valType < Value.valueTypeCode()) {
            uint8 tupLength = uint8(valType - Value.tupleTypeCode());
            Value.Data[] memory tupleVal;
            (offset, tupleVal) = deserializeTuple(tupLength, data, offset);
            return (offset, Value.newTuple(tupleVal));
        }
        require(false, "invalid typecode");
    }

    function extractUint8(bytes memory data, uint256 startOffset)
        private
        pure
        returns (
            uint256, // offset
            uint8 // val
        )
    {
        return (startOffset + 1, uint8(data[startOffset]));
    }

    function extractBytes32(bytes memory data, uint256 startOffset)
        private
        pure
        returns (
            uint256, // offset
            bytes32 // val
        )
    {
        return (startOffset + 32, data.toBytes32(startOffset));
    }
}

// SPDX-License-Identifier: Apache-2.0

/*
 * Copyright 2019, Offchain Labs, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

pragma solidity ^0.6.11;

library DebugPrint {
    function char(bytes1 b) private pure returns (bytes1 c) {
        if (uint8(b) < 10) {
            return bytes1(uint8(b) + 0x30);
        } else {
            return bytes1(uint8(b) + 0x57);
        }
    }

    function bytes32string(bytes32 b32) internal pure returns (string memory out) {
        bytes memory s = new bytes(64);

        for (uint256 i = 0; i < 32; i++) {
            bytes1 b = bytes1(b32[i]);
            bytes1 hi = bytes1(uint8(b) / 16);
            bytes1 lo = bytes1(uint8(b) - 16 * uint8(hi));
            s[i * 2] = char(hi);
            s[i * 2 + 1] = char(lo);
        }

        out = string(s);
    }

    // Taken from https://github.com/oraclize/ethereum-api/blob/master/oraclizeAPI_0.5.sol
    function uint2str(uint256 _iParam) internal pure returns (string memory _uintAsString) {
        uint256 _i = _iParam;
        if (_i == 0) {
            return "0";
        }
        uint256 j = _i;
        uint256 len;
        while (j != 0) {
            len++;
            j /= 10;
        }
        bytes memory bstr = new bytes(len);
        uint256 k = len - 1;
        while (_i != 0) {
            bstr[k--] = bytes1(uint8(48 + (_i % 10)));
            _i /= 10;
        }
        return string(bstr);
    }
}

// SPDX-License-Identifier: Apache-2.0

/*
 * Copyright 2019-2020, Offchain Labs, Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

pragma solidity ^0.6.11;

import "./Value.sol";

library Hashing {
    using Hashing for Value.Data;
    using Value for Value.CodePoint;

    function keccak1(bytes32 b) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked(b));
    }

    function keccak2(bytes32 a, bytes32 b) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked(a, b));
    }

    function bytes32FromArray(
        bytes memory arr,
        uint256 offset,
        uint256 arrLength
    ) internal pure returns (uint256) {
        uint256 res = 0;
        for (uint256 i = 0; i < 32; i++) {
            res = res << 8;
            bytes1 b = arrLength > offset + i ? arr[offset + i] : bytes1(0);
            res = res | uint256(uint8(b));
        }
        return res;
    }

    /*
     * !! Note that dataLength must be a power of two !!
     *
     * If you have an arbitrary data length, you can round it up with roundUpToPow2.
     * The boolean return value tells if the data segment data[startOffset..startOffset+dataLength] only included zeroes.
     * If pack is true, the returned value is the merkle hash where trailing zeroes are ignored, that is,
     *   if h is the smallest height for which all data[startOffset+2**h..] are zero, merkle hash of data[startOffset..startOffset+2**h] is returned.
     * If all elements in the data segment are zero (and pack is true), keccak1(bytes32(0)) is returned.
     */
    function merkleRoot(
        bytes memory data,
        uint256 rawDataLength,
        uint256 startOffset,
        uint256 dataLength,
        bool pack
    ) internal pure returns (bytes32, bool) {
        if (dataLength <= 32) {
            if (startOffset >= rawDataLength) {
                return (keccak1(bytes32(0)), true);
            }
            bytes32 res = keccak1(bytes32(bytes32FromArray(data, startOffset, rawDataLength)));
            return (res, res == keccak1(bytes32(0)));
        }
        (bytes32 h2, bool zero2) =
            merkleRoot(data, rawDataLength, startOffset + dataLength / 2, dataLength / 2, false);
        if (zero2 && pack) {
            return merkleRoot(data, rawDataLength, startOffset, dataLength / 2, pack);
        }
        (bytes32 h1, bool zero1) =
            merkleRoot(data, rawDataLength, startOffset, dataLength / 2, false);
        return (keccak2(h1, h2), zero1 && zero2);
    }

    function roundUpToPow2(uint256 len) internal pure returns (uint256) {
        if (len <= 1) return 1;
        else return 2 * roundUpToPow2((len + 1) / 2);
    }

    function bytesToBufferHash(
        bytes memory buf,
        uint256 startOffset,
        uint256 length
    ) internal pure returns (bytes32) {
        (bytes32 mhash, ) =
            merkleRoot(buf, startOffset + length, startOffset, roundUpToPow2(length), true);
        return keccak2(bytes32(uint256(123)), mhash);
    }

    function hashInt(uint256 val) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked(val));
    }

    function hashCodePoint(Value.CodePoint memory cp) internal pure returns (bytes32) {
        assert(cp.immediate.length < 2);
        if (cp.immediate.length == 0) {
            return
                keccak256(abi.encodePacked(Value.codePointTypeCode(), cp.opcode, cp.nextCodePoint));
        }
        return
            keccak256(
                abi.encodePacked(
                    Value.codePointTypeCode(),
                    cp.opcode,
                    cp.immediate[0].hash(),
                    cp.nextCodePoint
                )
            );
    }

    function hashTuplePreImage(bytes32 innerHash, uint256 valueSize)
        internal
        pure
        returns (bytes32)
    {
        return keccak256(abi.encodePacked(uint8(Value.tupleTypeCode()), innerHash, valueSize));
    }

    function hash(Value.Data memory val) internal pure returns (bytes32) {
        if (val.typeCode == Value.intTypeCode()) {
            return hashInt(val.intVal);
        } else if (val.typeCode == Value.codePointTypeCode()) {
            return hashCodePoint(val.cpVal);
        } else if (val.typeCode == Value.tuplePreImageTypeCode()) {
            return hashTuplePreImage(bytes32(val.intVal), val.size);
        } else if (val.typeCode == Value.tupleTypeCode()) {
            Value.Data memory preImage = getTuplePreImage(val.tupleVal);
            return preImage.hash();
        } else if (val.typeCode == Value.hashOnlyTypeCode()) {
            return bytes32(val.intVal);
        } else if (val.typeCode == Value.bufferTypeCode()) {
            return keccak256(abi.encodePacked(uint256(123), val.bufferHash));
        } else {
            require(false, "Invalid type code");
        }
    }

    function getTuplePreImage(Value.Data[] memory vals) internal pure returns (Value.Data memory) {
        require(vals.length <= 8, "Invalid tuple length");
        bytes32[] memory hashes = new bytes32[](vals.length);
        uint256 hashCount = hashes.length;
        uint256 size = 1;
        for (uint256 i = 0; i < hashCount; i++) {
            hashes[i] = vals[i].hash();
            size += vals[i].size;
        }
        bytes32 firstHash = keccak256(abi.encodePacked(uint8(hashes.length), hashes));
        return Value.newTuplePreImage(firstHash, size);
    }
}

// SPDX-License-Identifier: MIT

/*
 * @title Solidity Bytes Arrays Utils
 * @author Gonçalo Sá <goncalo.sa@consensys.net>
 *
 * @dev Bytes tightly packed arrays utility library for ethereum contracts written in Solidity.
 *      The library lets you concatenate, slice and type cast bytes arrays both in memory and storage.
 */

pragma solidity ^0.6.11;

/* solhint-disable no-inline-assembly */
library BytesLib {
    function toAddress(bytes memory _bytes, uint256 _start) internal pure returns (address) {
        require(_bytes.length >= (_start + 20), "Read out of bounds");
        address tempAddress;

        assembly {
            tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000)
        }

        return tempAddress;
    }

    function toUint8(bytes memory _bytes, uint256 _start) internal pure returns (uint8) {
        require(_bytes.length >= (_start + 1), "Read out of bounds");
        uint8 tempUint;

        assembly {
            tempUint := mload(add(add(_bytes, 0x1), _start))
        }

        return tempUint;
    }

    function toUint(bytes memory _bytes, uint256 _start) internal pure returns (uint256) {
        require(_bytes.length >= (_start + 32), "Read out of bounds");
        uint256 tempUint;

        assembly {
            tempUint := mload(add(add(_bytes, 0x20), _start))
        }

        return tempUint;
    }

    function toBytes32(bytes memory _bytes, uint256 _start) internal pure returns (bytes32) {
        require(_bytes.length >= (_start + 32), "Read out of bounds");
        bytes32 tempBytes32;

        assembly {
            tempBytes32 := mload(add(add(_bytes, 0x20), _start))
        }

        return tempBytes32;
    }
}
/* solhint-enable no-inline-assembly */

Settings
{
  "optimizer": {
    "enabled": true,
    "runs": 100
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "abi"
      ]
    }
  },
  "metadata": {
    "useLiteralContent": true
  },
  "libraries": {}
}

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"address[2]","name":"bridges","type":"address[2]"},{"internalType":"uint256","name":"initialMessagesRead","type":"uint256"},{"internalType":"bytes32[2]","name":"accs","type":"bytes32[2]"},{"internalType":"bytes","name":"proof","type":"bytes"},{"internalType":"bytes","name":"bproof","type":"bytes"}],"name":"executeStep","outputs":[{"internalType":"uint64","name":"gas","type":"uint64"},{"internalType":"uint256","name":"afterMessagesRead","type":"uint256"},{"internalType":"bytes32[4]","name":"fields","type":"bytes32[4]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[2]","name":"bridges","type":"address[2]"},{"internalType":"uint256","name":"initialMessagesRead","type":"uint256"},{"internalType":"bytes32[2]","name":"accs","type":"bytes32[2]"},{"internalType":"bytes","name":"proof","type":"bytes"},{"internalType":"bytes","name":"bproof","type":"bytes"}],"name":"executeStepDebug","outputs":[{"internalType":"string","name":"startMachine","type":"string"},{"internalType":"string","name":"afterMachine","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"proof","type":"bytes"}],"name":"parseProof","outputs":[{"internalType":"bytes32[]","name":"","type":"bytes32[]"},{"internalType":"bytes32[]","name":"","type":"bytes32[]"},{"internalType":"bytes32[]","name":"","type":"bytes32[]"},{"internalType":"bytes32[]","name":"","type":"bytes32[]"}],"stateMutability":"pure","type":"function"}]

608060405234801561001057600080fd5b506140e3806100206000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c806347dda1d614610046578063793deea314610162578063eba67f6e14610329575b600080fd5b610112600480360360e081101561005c57600080fd5b604082013590606083019083018360c0810160a0820135600160201b81111561008457600080fd5b82018360208201111561009657600080fd5b803590602001918460018302840111600160201b831117156100b757600080fd5b919390929091602081019035600160201b8111156100d457600080fd5b8201836020820111156100e657600080fd5b803590602001918460018302840111600160201b8311171561010757600080fd5b5090925090506104d3565b604080516001600160401b03851681526020810184905290810182608080838360005b8381101561014d578181015183820152602001610135565b50505050905001935050505060405180910390f35b6102066004803603602081101561017857600080fd5b810190602081018135600160201b81111561019257600080fd5b8201836020820111156101a457600080fd5b803590602001918460018302840111600160201b831117156101c557600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550610592945050505050565b6040518080602001806020018060200180602001858103855289818151815260200191508051906020019060200280838360005b8381101561025257818101518382015260200161023a565b50505050905001858103845288818151815260200191508051906020019060200280838360005b83811015610291578181015183820152602001610279565b50505050905001858103835287818151815260200191508051906020019060200280838360005b838110156102d05781810151838201526020016102b8565b50505050905001858103825286818151815260200191508051906020019060200280838360005b8381101561030f5781810151838201526020016102f7565b505050509050019850505050505050505060405180910390f35b6103f5600480360360e081101561033f57600080fd5b604082013590606083019083018360c0810160a0820135600160201b81111561036757600080fd5b82018360208201111561037957600080fd5b803590602001918460018302840111600160201b8311171561039a57600080fd5b919390929091602081019035600160201b8111156103b757600080fd5b8201836020820111156103c957600080fd5b803590602001918460018302840111600160201b831117156103ea57600080fd5b5090925090506105ce565b604051808060200180602001838103835285818151815260200191508051906020019080838360005b8381101561043657818101518382015260200161041e565b50505050905090810190601f1680156104635780820380516001836020036101000a031916815260200191505b50838103825284518152845160209182019186019080838360005b8381101561049657818101518382015260200161047e565b50505050905090810190601f1680156104c35780820380516001836020036101000a031916815260200191505b5094505050505060405180910390f35b6000806104de613ed3565b6104e6613ef1565b61056a8a8a8a8a8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8e018190048102820181019092528c815292508c91508b9081908401838280828437600081840152601f19601f820116905080830192505050505050508f610693565b905061057581610b4a565b61057e81610f60565b935093509350509750975097945050505050565b6060806060806105a0613f83565b6105a986610fc3565b80516020820151604083015160609093015191975095509093509150505b9193509193565b6060806105d9613ef1565b61065d898989898080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8d018190048102820181019092528b815292508b91508a9081908401838280828437600081840152601f19601f820116905080830192505050505050508e610693565b905061066881610b4a565b61067581604001516110bb565b925061068481606001516110bb565b91505097509795505050505050565b61069b613ef1565b6000846000815181106106aa57fe5b602001015160f81c60f81b60f81c90506000856001815181106106c957fe5b602001015160f81c60f81b60f81c90506000866002815181106106e857fe5b016020015160f81c9050600360606004840160ff166001600160401b038111801561071257600080fd5b5060405190808252806020026020018201604052801561074c57816020015b610739613fab565b8152602001906001900390816107315790505b50905060608360040160ff166001600160401b038111801561076d57600080fd5b506040519080825280602002602001820160405280156107a757816020015b610794613fab565b81526020019060019003908161078c5790505b50905060005b8560ff168110156107e3576107c28b856113c4565b8483815181106107ce57fe5b602090810291909101015293506001016107ad565b5060005b8460ff1681101561081d576107fc8b856113c4565b83838151811061080857fe5b602090810291909101015293506001016107e7565b50610826613fe8565b6108308b85611586565b809250819550505060008b858151811061084657fe5b01602001516001959095019460f81c905061085f613ef1565b6001600160a01b038b35811682526020808d0135909116908201526040810183905261088a83611626565b6060820152608081018f90528d3560a08201526020808f013560c0830152600060e0830181905260408051808201825260ff8c811682528185018a905261010086019190915281518083019092528a8116825292810187905261012084015283821660018114610140850152918b1661016084015261018083018f90526101c083018e90526101e08301526101a08201879052158061092c57508160ff166001145b6040518060400160405280600b81526020016a04241445f494d4d5f5459560ac1b815250906109d95760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561099e578181015183820152602001610986565b50505050905090810190601f1680156109cb5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b506109e2613fab565b60ff8316610a03576109fc8a83604001516000015161168f565b9050610aa3565b6000865111604051806040016040528060068152602001654e4f5f494d4d60d01b81525090610a735760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561099e578181015183820152602001610986565b50610aa08a8360400151600001518860018d0360ff1681518110610a9357fe5b60200260200101516116f3565b90505b610aac81611779565b60408301515260005b838a0360ff16811015610af457610aec878281518110610ad157fe5b602002602001015184604001516118e690919063ffffffff16565b600101610ab5565b5060005b8860ff16811015610b3557610b2d868281518110610b1257fe5b6020026020010151846040015161190090919063ffffffff16565b600101610af8565b50909f9e505050505050505050505050505050565b6000806000614046610b6385610160015160ff1661191a565b93509350935093506000841180610b7d5750846101400151155b8015610b8f5750610100850151518410155b80610bb757508461014001518015610ba5575083155b8015610bb75750610100850151516001145b6040518060400160405280600a815260200169535441434b5f4d414e5960b01b81525090610c265760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561099e578181015183820152602001610986565b50610120850151516040805180820190915260088152674155585f4d414e5960c01b602082015290841015610c9c5760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561099e578181015183820152602001610986565b5061010085015151841115610d5a57610cbb610cb6611a2a565b611779565b610ccc866060015160200151611779565b146040518060400160405280600d81526020016c535441434b5f4d495353494e4760981b81525090610d3f5760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561099e578181015183820152602001610986565b50610d4b856005611a71565b50610d5585611ae6565b610e1a565b61012085015151831115610df557610d73610cb6611a2a565b610d84866060015160400151611779565b146040518060400160405280600b81526020016a4155585f4d495353494e4760a81b81525090610d3f5760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561099e578181015183820152602001610986565b610dff8583611a71565b15610e0d57610d5585611ae6565b610e1a858263ffffffff16565b846101e0015115610ebf5760408051600160f81b6020808301919091526000602183018190526022808401919091528351808403909101815260429092019092528051910120606086015160c001511415610e8157610e7c8560600151611af1565b610ebf565b60006101e0860152606085015160c081015190526101408501518015610ea5575083155b610eb457610100850151600090525b610120850151600090525b60005b61010086015151811015610f0b57610f03866101000151602001518281518110610ee857fe5b602002602001015187606001516118e690919063ffffffff16565b600101610ec2565b5060005b61012086015151811015610f5857610f50866101200151602001518281518110610f3557fe5b6020026020010151876060015161190090919063ffffffff16565b600101610f0f565b505050505050565b600080610f6b613ed3565b8360e0015184608001516040518060800160405280610f8d8860400151611afb565b8152602001610f9f8860600151611afb565b81526020018760a0015181526020018760c001518152509250925092509193909250565b610fcb613f83565b606061100a8384600081518110610fde57fe5b602001015160f81c60f81b85600181518110610ff657fe5b01602001516001600160f81b031916611bbf565b90506060611037848560018151811061101f57fe5b602001015160f81c60f81b86600281518110610ff657fe5b90506060611064858660028151811061104c57fe5b602001015160f81c60f81b87600381518110610ff657fe5b90506060611091868760038151811061107957fe5b602001015160f81c60f81b88600481518110610ff657fe5b6040805160808101825295865260208601949094529284019190915250606082015290505b919050565b60606110ca8260000151611c5c565b6110df6110da8460200151611779565b611c5c565b6110ef6110da8560400151611779565b6110ff6110da8660600151611779565b61110f6110da8760800151611779565b61111c8760a00151611d2b565b6111298860c00151611c5c565b60405160200180806709ac2c6d0d2dcca560c31b81525060080188805190602001908083835b6020831061116e5780518252601f19909201916020918201910161114f565b51815160209384036101000a60001901801990921691161790526216100560e91b9190930190815289516003909101928a0191508083835b602083106111c55780518252601f1990920191602091820191016111a6565b51815160209384036101000a60001901801990921691161790526216100560e91b919093019081528851600390910192890191508083835b6020831061121c5780518252601f1990920191602091820191016111fd565b51815160209384036101000a60001901801990921691161790526216100560e91b919093019081528751600390910192880191508083835b602083106112735780518252601f199092019160209182019101611254565b51815160209384036101000a60001901801990921691161790526216100560e91b919093019081528651600390910192870191508083835b602083106112ca5780518252601f1990920191602091820191016112ab565b51815160209384036101000a60001901801990921691161790526216100560e91b919093019081528551600390910192860191508083835b602083106113215780518252601f199092019160209182019101611302565b51815160209384036101000a60001901801990921691161790526216100560e91b919093019081528451600390910192850191508083835b602083106113785780518252601f199092019160209182019101611359565b5181516020939093036101000a600019018019909116921691909117905261148560f11b92019182525060408051808303601d19018152600290920190529a9950505050505050505050565b60006113ce613fab565b83518310611414576040805162461bcd60e51b815260206004820152600e60248201526d1a5b9d985b1a59081bd9999cd95d60921b604482015290519081900360640190fd5b6000806114218686611e05565b9150915061142d611e2c565b60ff168160ff1614156114615760006114468784611e31565b90935090508261145582611ea5565b9450945050505061157f565b611469611f65565b60ff168160ff16141561148b576114808683611f6a565b93509350505061157f565b61149361200c565b60ff168160ff1614156114bb5760006114ac8784611e31565b90935090508261145582612011565b6114c36120fd565b60ff168160ff1614156114da576114808683612102565b6114e2612197565b60ff168160ff161015801561150357506114fa61219c565b60ff168160ff16105b1561153f576000611512612197565b8203905060606115238289866121a1565b90945090508361153282612249565b955095505050505061157f565b6040805162461bcd60e51b815260206004820152601060248201526f696e76616c69642074797065636f646560801b604482015290519081900360640190fd5b9250929050565b6000611590613fe8565b611598613fe8565b600060e08201819052806115ac8787611e31565b90965091506115bb8787612102565b602085015295506115cc8787612102565b604085015295506115dd87876113c4565b606085015295506115ee87876113c4565b608085015295506115ff8787611e31565b60a085015295506116108787611e31565b92845260c0840192909252509590945092505050565b61162e613fe8565b60405180610100016040528083600001518152602001836020015181526020018360400151815260200183606001518152602001836080015181526020018360a0015181526020018360c0015181526020018360e001518152509050919050565b611697613fab565b6040805160608101825260ff8516815260208082018590528251600080825291810184526116ea938301916116e2565b6116cf613fab565b8152602001906001900390816116c75790505b50905261238a565b90505b92915050565b6116fb613fab565b604080516001808252818301909252606091816020015b61171a613fab565b815260200190600190039081611712579050509050828160008151811061173d57fe5b602002602001018190525061176e60405180606001604052808760ff1681526020018681526020018381525061238a565b9150505b9392505050565b6000611783611e2c565b60ff16826080015160ff1614156117a657815161179f9061241a565b90506110b6565b6117ae611f65565b60ff16826080015160ff1614156117cc5761179f826020015161243e565b6117d46120fd565b60ff16826080015160ff1614156117f657815160a083015161179f919061253b565b6117fe612197565b60ff16826080015160ff16141561183757611817613fab565b611824836040015161258c565b905061182f81611779565b9150506110b6565b61183f612704565b60ff16826080015160ff161415611858575080516110b6565b61186061200c565b60ff16826080015160ff1614156118a5575060608082015160408051607b602080830191909152818301939093528151808203830181529301905281519101206110b6565b6040805162461bcd60e51b8152602060048201526011602482015270496e76616c6964207479706520636f646560781b604482015290519081900360640190fd5b6118f4826020015182612709565b82602001819052505050565b61190e826040015182612709565b82604001819052505050565b6000808061404660a185141561193f57506002925060009150600a90506127876105c7565b60a285141561195d57506002925060009150600a905061283e6105c7565b60a385141561197b57506002925060009150600a90506128d26105c7565b60a485141561199957506003925060009150606490506129666105c7565b60a58514156119b75750600392506000915060649050612a576105c7565b60a68514156119d55750600392506000915060649050612b2b6105c7565b60708514156119f35750600292506000915060649050612bed6105c7565b60405162461bcd60e51b815260040180806020018281038252602c815260200180614082602c913960400191505060405180910390fd5b611a32613fab565b60408051600080825260208201909252611a6c91611a66565b611a53613fab565b815260200190600190039081611a4b5790505b50612249565b905090565b6000816001600160401b0316836060015160a001511015611ab6575060e0820180516005016001600160401b03169052606082015160001960a09091015260016116ed565b5060e0820180516001600160401b039083018116909152606083015160a0018051918316909103905260006116ed565b60016101e090910152565b600160e090910152565b600060028260e001511415611b12575060006110b6565b60018260e001511415611b27575060016110b6565b81516020830151611b3790611779565b611b448460400151611779565b611b518560600151611779565b611b5e8660800151611779565b8660a001518760c00151604051602001808881526020018781526020018681526020018581526020018481526020018381526020018281526020019750505050505050506040516020818303038152906040528051906020012090506110b6565b606060f883811c9083901c81900360ff169082826001600160401b0381118015611be857600080fd5b50604051908082528060200260200182016040528015611c12578160200160208202803683370190505b50905060005b83811015611c5157611c2f88828501602002612d89565b60001b828281518110611c3e57fe5b6020908102919091010152600101611c18565b509695505050505050565b60408051818152606081810183529182919060208201818036833701905050905060005b6020811015611d24576000848260208110611c9757fe5b1a60f881811b9250601080830480831b9360ff9091169091029003901b611cbd82612dc9565b858560020281518110611ccc57fe5b60200101906001600160f81b031916908160001a905350611cec81612dc9565b858560020260010181518110611cfe57fe5b60200101906001600160f81b031916908160001a9053505060019092019150611c809050565b5092915050565b60608180611d525750506040805180820190915260018152600360fc1b60208201526110b6565b8060005b8115611d6a57600101600a82049150611d56565b6060816001600160401b0381118015611d8257600080fd5b506040519080825280601f01601f191660200182016040528015611dad576020820181803683370190505b50905060001982015b8415611dfb57600a850660300160f81b82828060019003935081518110611dd957fe5b60200101906001600160f81b031916908160001a905350600a85049450611db6565b5095945050505050565b60008082600101848481518110611e1857fe5b016020015190925060f81c90509250929050565b600090565b60008082845110158015611e49575060208385510310155b611e86576040805162461bcd60e51b81526020600482015260096024820152681d1bdbc81cda1bdc9d60ba1b604482015290519081900360640190fd5b60208301611e9a858563ffffffff612dfa16565b915091509250929050565b611ead613fab565b6040805160c0810182528381528151606081018352600080825260208083018290528451828152808201865293949085019390830191611f03565b611ef0613fab565b815260200190600190039081611ee85790505b50905281526020016000604051908082528060200260200182016040528015611f4657816020015b611f33613fab565b815260200190600190039081611f2b5790505b5081526000602082018190526040820152600160609091015292915050565b600190565b6000611f74613fab565b82600080611f80613fab565b6000611f8c8986611e05565b9095509350611f9b8986611e05565b9095509250600160ff85161415611fbc57611fb689866113c4565b90955091505b611fc68986612e53565b9095509050600160ff85161415611ff15784611fe38483856116f3565b96509650505050505061157f565b84611ffc848361168f565b9650965050505050509250929050565b600c90565b612019613fab565b6040518060c00160405280600081526020016040518060600160405280600060ff1681526020016000801b815260200160006001600160401b038111801561206057600080fd5b5060405190808252806020026020018201604052801561209a57816020015b612087613fab565b81526020019060019003908161207f5790505b509052815260200160006040519080825280602002602001820160405280156120dd57816020015b6120ca613fab565b8152602001906001900390816120c25790505b50815260208101849052600c604082015260016060909101529050919050565b600290565b600061210c613fab565b82845110158015612121575060408385510310155b61215e576040805162461bcd60e51b81526020600482015260096024820152681d1bdbc81cda1bdc9d60ba1b604482015290519081900360640190fd5b60008061216b8686612e53565b909450915061217a8685611e31565b90945090508361218a8383612e6a565b9350935050509250929050565b600390565b600d90565b60006060828160ff87166001600160401b03811180156121c057600080fd5b506040519080825280602002602001820160405280156121fa57816020015b6121e7613fab565b8152602001906001900390816121df5790505b50905060005b8760ff168160ff16101561223c5761221887846113c4565b838360ff168151811061222757fe5b60209081029190910101529250600101612200565b5090969095509350505050565b612251613fab565b61225b8251612f29565b6122ac576040805162461bcd60e51b815260206004820152601a60248201527f5475706c65206d75737420686176652076616c69642073697a65000000000000604482015290519081900360640190fd5b600160005b83518110156122e3578381815181106122c657fe5b602002602001015160a001518201915080806001019150506122b1565b506040518060c00160405280600081526020016040518060600160405280600060ff1681526020016000801b815260200160006001600160401b038111801561232b57600080fd5b5060405190808252806020026020018201604052801561236557816020015b612352613fab565b81526020019060019003908161234a5790505b5090528152602081019490945260006040850152600360608501526080909301525090565b612392613fab565b6040518060c001604052806000815260200183815260200160006001600160401b03811180156123c157600080fd5b506040519080825280602002602001820160405280156123fb57816020015b6123e8613fab565b8152602001906001900390816123e05790505b5081526000602082015260016040820181905260609091015292915050565b60408051602080820193909352815180820384018152908201909152805191012090565b600060028260400151511061244f57fe5b6040820151516124b457612461611f65565b8251602080850151604080516001600160f81b031960f896871b8116828601529490951b9093166021850152602280850191909152825180850390910181526042909301909152815191012090506110b6565b6124bc611f65565b82600001516124e284604001516000815181106124d557fe5b6020026020010151611779565b8460200151604051602001808560ff1660ff1660f81b81526001018460ff1660ff1660f81b8152600101838152602001828152602001945050505050604051602081830303815290604052805190602001209050919050565b6000612545612197565b8383604051602001808460ff1660ff1660f81b8152600101838152602001828152602001935050505060405160208183030381529060405280519060200120905092915050565b612594613fab565b6008825111156125e2576040805162461bcd60e51b8152602060048201526014602482015273092dcecc2d8d2c840e8eae0d8ca40d8cadccee8d60631b604482015290519081900360640190fd5b606082516001600160401b03811180156125fb57600080fd5b50604051908082528060200260200182016040528015612625578160200160208202803683370190505b508051909150600160005b82811015612688576126478682815181106124d557fe5b84828151811061265357fe5b60200260200101818152505085818151811061266b57fe5b602002602001015160a00151820191508080600101915050612630565b506000835184604051602001808360ff1660ff1660f81b8152600101828051906020019060200280838360005b838110156126cd5781810151838201526020016126b5565b50505050905001925050506040516020818303038152906040528051906020012090506126fa8183612e6a565b9695505050505050565b606490565b612711613fab565b6040805160028082526060828101909352816020015b61272f613fab565b815260200190600190039081612727579050509050828160008151811061275257fe5b6020026020010181905250838160018151811061276b57fe5b602002602001018190525061277f8161258c565b949350505050565b61278f613fab565b61279d826101000151612f30565b90506127a7613fab565b6127b5836101000151612f30565b90506127c082612f72565b15806127d257506127d081612f90565b155b156127e7576127e083612f9d565b505061283b565b8151600160401b116127fc576127e083612f9d565b600061281e82606001518460000151612819876101c00151610fc3565b612fa6565b905061283784610100015161283283611ea5565b612fc8565b5050505b50565b612846613fab565b612854826101000151612f30565b905061285e613fab565b61286c836101000151612f30565b905061287782612f72565b1580612889575061288781612f90565b155b15612897576127e083612f9d565b815167fffffffffffffff9116128b0576127e083612f9d565b600061281e826060015184600001516128cd876101c00151610fc3565b612ff2565b6128da613fab565b6128e8826101000151612f30565b90506128f2613fab565b612900836101000151612f30565b905061290b82612f72565b158061291d575061291b81612f90565b155b1561292b576127e083612f9d565b815167ffffffffffffffe111612944576127e083612f9d565b600061281e82606001518460000151612961876101c00151610fc3565b613152565b61296e613fab565b61297c826101000151612f30565b9050612986613fab565b612994836101000151612f30565b905061299e613fab565b6129ac846101000151612f30565b90506129b783612f72565b15806129c957506129c782613286565b155b806129da57506129d881612f90565b155b156129f0576129e884612f9d565b50505061283b565b8251600160401b111580612a075750815161010011155b15612a15576129e884612f9d565b6000612a3c826060015185600001518560000151612a37896101c00151610fc3565b613291565b9050612a5085610100015161283283612011565b5050505050565b612a5f613fab565b612a6d826101000151612f30565b9050612a77613fab565b612a85836101000151612f30565b9050612a8f613fab565b612a9d846101000151612f30565b9050612aa883612f72565b1580612aba5750612ab882613286565b155b80612acb5750612ac981612f90565b155b15612ad9576129e884612f9d565b825167fffffffffffffff9111580612af657508151600160401b11155b15612b04576129e884612f9d565b6000612a3c826060015185600001518560000151612b26896101c00151610fc3565b6132da565b612b33613fab565b612b41826101000151612f30565b9050612b4b613fab565b612b59836101000151612f30565b9050612b63613fab565b612b71846101000151612f30565b9050612b7c83612f72565b1580612b8e5750612b8c82613286565b155b80612b9f5750612b9d81612f90565b155b15612bad576129e884612f9d565b825167ffffffffffffffe111612bc6576129e884612f9d565b6000612a3c826060015185600001518560000151612be8896101c00151610fc3565b613423565b612bf5613fab565b612c03826101000151612f30565b9050612c0d613fab565b612c1b836101000151612f30565b9050612c2682612f72565b1580612c385750612c3681612f90565b155b15612c46576127e083612f9d565b81516127101080612c5657508151155b15612c64576127e083612f9d565b82610180015151836101a001511415612cdf57612c9781606001518360000151612c92866101c00151610fc3565b6134f5565b15612cd6576040805162461bcd60e51b815260206004820152600a602482015269084aa8cbe988a9c8ea8960b31b604482015290519081900360640190fd5b6127e083612f9d565b6101a083015182516101808501516000612cfa828585613549565b905080612d0686611779565b14612d45576040805162461bcd60e51b815260206004820152600a60248201526915d493d391d7d4d1539160b21b604482015290519081900360640190fd5b5090910160209081019190912060a0850180516040805180860192909252818101939093528251808203840181526060909101909252815191909201209052505050565b600080805b6020811015612dc157600882901b91508481850181518110612dac57fe5b016020015160f81c9190911790600101612d8e565b509392505050565b6000600a60f883901c1015612de9578160f81c60300160f81b90506110b6565b8160f81c60570160f81b90506110b6565b60008160200183511015612e4a576040805162461bcd60e51b815260206004820152601260248201527152656164206f7574206f6620626f756e647360701b604482015290519081900360640190fd5b50016020015190565b60008060208301611e9a858563ffffffff612dfa16565b612e72613fab565b6040805160c0810182528481528151606081018352600080825260208083018290528451828152808201865293949085019390830191612ec8565b612eb5613fab565b815260200190600190039081612ead5790505b50905281526020016000604051908082528060200260200182016040528015612f0b57816020015b612ef8613fab565b815260200190600190039081612ef05790505b50815260006020820152600260408201526060019290925250919050565b6008101590565b612f38613fab565b612f40613fab565b8260200151600184600001510381518110612f5757fe5b60209081029190910101518351600019018452915050919050565b608081015160009060ff161580156116ed57505051600160401b1190565b6080015160ff16600c1490565b61283b81611ae6565b600061277f612fbe856020865b048560000151613572565b6020855b066136e0565b808260200151836000015181518110612fdd57fe5b60209081029190910101525080516001019052565b60408051600880825281830190925260009160609190602082018180368337019050509050600061302c866020875b048660000151613572565b905060208086066008011115613100576000613054876020885b046001018760400151613572565b905060005b6018601f8816600803018110156130a85761307a838260208a5b06016136e0565b60f81b84828151811061308957fe5b60200101906001600160f81b031916908160001a905350600101613059565b506018601f8716600803015b60088110156130f9576130cb826020898401612fc2565b60f81b8482815181106130da57fe5b60200101906001600160f81b031916908160001a9053506001016130b4565b5050613149565b60005b6008811015613147576131198282602089613073565b60f81b83828151811061312857fe5b60200101906001600160f81b031916908160001a905350600101613103565b505b6126fa826136ed565b60408051602080825281830190925260009160609190602082018180368337019050509050600061318586602087613021565b90506020808606602001111561323f5760006131a387602088613046565b905060005b601f87166020038110156131f1576131c3838260208a613073565b60f81b8482815181106131d257fe5b60200101906001600160f81b031916908160001a9053506001016131a8565b50601f86166020035b60208110156130f957613211826020898401612fc2565b60f81b84828151811061322057fe5b60200101906001600160f81b031916908160001a9053506001016131fa565b60005b6020811015613147576132588282602089613073565b60f81b83828151811061326757fe5b60200101906001600160f81b031916908160001a905350600101613242565b6080015160ff161590565b6000806132a086602087612fb3565b905060006132b2826020880687613723565b905060006132ce88602089048488600001518960200151613762565b98975050505050505050565b600060606132e784613802565b905060006132f787602088613021565b9050602080870660080111156133d95760005b6018601f881660080301811015613352576133488260208984010685846018018151811061333457fe5b01602001516001600160f81b03191661386c565b915060010161330a565b5061336c876020885b048387600001518860200151613762565b9650600061337c88602089613046565b90506018601f8816600803015b60088110156133b5576133ab8260208a84010686846018018151811061333457fe5b9150600101613389565b506133d188602089046001018388604001518960600151613762565b975050613418565b60005b6008811015613408576133fe828260208a060185846018018151811061333457fe5b91506001016133dc565b506134158760208861335b565b96505b509495945050505050565b6000606061343084613802565b9050600061344087602088613021565b9050602080870660200111156134d25760005b601f871660200381101561348257613478828260208a5b060185848151811061333457fe5b9150600101613453565b5061348f8760208861335b565b9650600061349f88602089613046565b9050601f87166020035b60208110156133b5576134c88260208a84010686848151811061333457fe5b91506001016134a9565b60005b6020811015613408576134eb828260208a61346a565b91506001016134d5565b60008061350485602086612fb3565b9050601f84165b60208110156135365761351e82826136e0565b1561352e57600092505050611772565b60010161350b565b5061176e85602086048560000151613888565b600080613564858486018661355d87613a04565b6001613a2f565b50905061176e607b82613b07565b60008151600014156135db57613588600061241a565b84146135d3576040805162461bcd60e51b815260206004820152601560248201527432bc3832b1ba32b21032b6b83a3c90313ab33332b960591b604482015290519081900360640190fd5b506000611772565b60006135fa836000815181106135ed57fe5b602002602001015161241a565b905060015b83518110156136645784600116600114156136385761363184828151811061362357fe5b602002602001015183613b07565b9150613658565b6136558285838151811061364857fe5b6020026020010151613b07565b91505b600194851c94016135ff565b508481146136b1576040805162461bcd60e51b8152602060048201526015602482015274195e1c1958dd19590818dbdc9c9958dd081c9bdbdd605a1b604482015290519081900360640190fd5b83156136c1575060009050611772565b826000815181106136ce57fe5b60200260200101519150509392505050565b601f036008021c60ff1690565b600080805b8351811015611d2457600882901b915083818151811061370e57fe5b016020015160f81c91909117906001016136f2565b6000606061373085613802565b90508260f81b81858151811061374257fe5b60200101906001600160f81b031916908160001a90535061176e816136ed565b600081516003146137b4576040805162461bcd60e51b81526020600482015260176024820152762120a22fa727a926a0a624ad20aa24a7a72fa82927a7a360491b604482015290519081900360640190fd5b6126fa86868686866000815181106137c857fe5b602002602001015160001c876001815181106137e057fe5b6020026020010151886002815181106137f557fe5b6020026020010151613b33565b6040805160208082528183019092526060918391839160208201818036833701905050905060005b6020811015612dc1578260f81b8282601f038151811061384657fe5b60200101906001600160f81b031916908160001a90535060089290921c9160010161382a565b6000606061387985613802565b90508281858151811061374257fe5b60008151600014156138f15761389e600061241a565b84146138e9576040805162461bcd60e51b815260206004820152601560248201527432bc3832b1ba32b21032b6b83a3c90313ab33332b960591b604482015290519081900360640190fd5b506001611772565b6000613903836000815181106135ed57fe5b905060016060613911613dad565b905060015b85518110156139a557866001166001141561394f5761394886828151811061393a57fe5b602002602001015185613b07565b9350613999565b61395f8487838151811061364857fe5b9350828015613996575081600182038151811061397857fe5b602002602001015186828151811061398c57fe5b6020026020010151145b92505b600196871c9601613916565b508683146139f2576040805162461bcd60e51b8152602060048201526015602482015274195e1c1958dd19590818dbdc9c9958dd081c9bdbdd605a1b604482015290519081900360640190fd5b8515611dfb5760019350505050611772565b600060018211613a16575060016110b6565b613a2560026001840104613a04565b60020290506110b6565b60008060208411613a8357858510613a5657613a4b600061241a565b600191509150613afd565b6000613a6b613a6689888a613e4e565b61241a565b905080613a78600061241a565b909350149050613afd565b600080613a9d8989600289048a0160028a5b046000613a2f565b91509150808015613aab5750845b15613acb57613ac089898960028a0489613a2f565b935093505050613afd565b600080613adc8b8b8b60028c613a95565b91509150613aea8285613b07565b818015613af45750835b95509550505050505b9550959350505050565b604080516020808201949094528082019290925280518083038201815260609092019052805191012090565b600080613b3f8761241a565b9050613b4c898988613572565b506060613b57613dad565b905060018751036001901b8910613c1b5787613b77578992505050613da2565b6000613b828a613ead565b88519091505b60018203811015613bb057613ba68c84600184038151811061364857fe5b9b50600101613b88565b5060015b60018203811015613c06578a60011660011415613be457613bdd83600183038151811061393a57fe5b9350613bfa565b613bf78484600184038151811061364857fe5b93505b60019a8b1c9a01613bb4565b50613c118b84613b07565b9350505050613da2565b60015b8751811015613c9b5760008a600116600114613c3a5783613c4f565b888281518110613c4657fe5b60200260200101515b905060008b600116600114613c7757898381518110613c6a57fe5b6020026020010151613c79565b845b9050613c858282613b07565b60019c8d1c9c909550929092019150613c1e9050565b508715613caa57509050613da2565b600086613cb8575084613d2d565b818781518110613cc457fe5b6020026020010151851415613d20576040805162461bcd60e51b815260206004820152601c60248201527f726967687420737562747265652063616e6e6f74206265207a65726f00000000604482015290519081900360640190fd5b613d2a8686613b07565b90505b80875b60018a5103811015613d5657613d4c8285838151811061364857fe5b9150600101613d30565b50838114613d9c576040805162461bcd60e51b815260206004820152600e60248201526d0caf0e0cac6e8cac840dac2e8c6d60931b604482015290519081900360640190fd5b50925050505b979650505050505050565b60408051818152610820810182526060918291906020820161080080368337019050509050613ddc600061241a565b81600081518110613de957fe5b602090810291909101015260015b6040811015613e4857613e29826001830381518110613e1257fe5b602002602001015183600184038151811061364857fe5b828281518110613e3557fe5b6020908102919091010152600101613df7565b50905090565b600080805b6020811015613ea457600882901b915060008186018511613e75576000613e93565b8682870181518110613e8357fe5b01602001516001600160f81b0319165b60f81c929092179150600101613e53565b50949350505050565b600081613ebc575060016110b6565b613ec9600183901c613ead565b60010190506110b6565b60405180608001604052806004906020820280368337509192915050565b604080516102008101825260008082526020820152908101613f11613fe8565b8152602001613f1e613fe8565b81526000602082018190526040820181905260608201819052608082015260a001613f47614048565b8152602001613f54614048565b81526000602082018190526040820181905260608083018190526080830182905260a083015260c09091015290565b6040518060800160405280606081526020016060815260200160608152602001606081525090565b6040518060c0016040528060008152602001613fc5614062565b815260606020820181905260006040830181905290820181905260809091015290565b6040805161010081019091526000815260208101614004613fab565b8152602001614011613fab565b815260200161401e613fab565b815260200161402b613fab565b81526000602082018190526040820181905260609091015290565bfe5b604051806040016040528060008152602001606081525090565b604080516060808201835260008083526020830152918101919091529056fe75736520616e6f7468657220636f6e747261637420746f2068616e646c65206f74686572206f70636f646573a2646970667358221220d2b0dc1d0995b28b667486ef43a27a69bfb3453af6b9ad2b4746dbebd18b35d964736f6c634300060b0033

Deployed Bytecode

0x608060405234801561001057600080fd5b50600436106100415760003560e01c806347dda1d614610046578063793deea314610162578063eba67f6e14610329575b600080fd5b610112600480360360e081101561005c57600080fd5b604082013590606083019083018360c0810160a0820135600160201b81111561008457600080fd5b82018360208201111561009657600080fd5b803590602001918460018302840111600160201b831117156100b757600080fd5b919390929091602081019035600160201b8111156100d457600080fd5b8201836020820111156100e657600080fd5b803590602001918460018302840111600160201b8311171561010757600080fd5b5090925090506104d3565b604080516001600160401b03851681526020810184905290810182608080838360005b8381101561014d578181015183820152602001610135565b50505050905001935050505060405180910390f35b6102066004803603602081101561017857600080fd5b810190602081018135600160201b81111561019257600080fd5b8201836020820111156101a457600080fd5b803590602001918460018302840111600160201b831117156101c557600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550610592945050505050565b6040518080602001806020018060200180602001858103855289818151815260200191508051906020019060200280838360005b8381101561025257818101518382015260200161023a565b50505050905001858103845288818151815260200191508051906020019060200280838360005b83811015610291578181015183820152602001610279565b50505050905001858103835287818151815260200191508051906020019060200280838360005b838110156102d05781810151838201526020016102b8565b50505050905001858103825286818151815260200191508051906020019060200280838360005b8381101561030f5781810151838201526020016102f7565b505050509050019850505050505050505060405180910390f35b6103f5600480360360e081101561033f57600080fd5b604082013590606083019083018360c0810160a0820135600160201b81111561036757600080fd5b82018360208201111561037957600080fd5b803590602001918460018302840111600160201b8311171561039a57600080fd5b919390929091602081019035600160201b8111156103b757600080fd5b8201836020820111156103c957600080fd5b803590602001918460018302840111600160201b831117156103ea57600080fd5b5090925090506105ce565b604051808060200180602001838103835285818151815260200191508051906020019080838360005b8381101561043657818101518382015260200161041e565b50505050905090810190601f1680156104635780820380516001836020036101000a031916815260200191505b50838103825284518152845160209182019186019080838360005b8381101561049657818101518382015260200161047e565b50505050905090810190601f1680156104c35780820380516001836020036101000a031916815260200191505b5094505050505060405180910390f35b6000806104de613ed3565b6104e6613ef1565b61056a8a8a8a8a8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8e018190048102820181019092528c815292508c91508b9081908401838280828437600081840152601f19601f820116905080830192505050505050508f610693565b905061057581610b4a565b61057e81610f60565b935093509350509750975097945050505050565b6060806060806105a0613f83565b6105a986610fc3565b80516020820151604083015160609093015191975095509093509150505b9193509193565b6060806105d9613ef1565b61065d898989898080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020601f8d018190048102820181019092528b815292508b91508a9081908401838280828437600081840152601f19601f820116905080830192505050505050508e610693565b905061066881610b4a565b61067581604001516110bb565b925061068481606001516110bb565b91505097509795505050505050565b61069b613ef1565b6000846000815181106106aa57fe5b602001015160f81c60f81b60f81c90506000856001815181106106c957fe5b602001015160f81c60f81b60f81c90506000866002815181106106e857fe5b016020015160f81c9050600360606004840160ff166001600160401b038111801561071257600080fd5b5060405190808252806020026020018201604052801561074c57816020015b610739613fab565b8152602001906001900390816107315790505b50905060608360040160ff166001600160401b038111801561076d57600080fd5b506040519080825280602002602001820160405280156107a757816020015b610794613fab565b81526020019060019003908161078c5790505b50905060005b8560ff168110156107e3576107c28b856113c4565b8483815181106107ce57fe5b602090810291909101015293506001016107ad565b5060005b8460ff1681101561081d576107fc8b856113c4565b83838151811061080857fe5b602090810291909101015293506001016107e7565b50610826613fe8565b6108308b85611586565b809250819550505060008b858151811061084657fe5b01602001516001959095019460f81c905061085f613ef1565b6001600160a01b038b35811682526020808d0135909116908201526040810183905261088a83611626565b6060820152608081018f90528d3560a08201526020808f013560c0830152600060e0830181905260408051808201825260ff8c811682528185018a905261010086019190915281518083019092528a8116825292810187905261012084015283821660018114610140850152918b1661016084015261018083018f90526101c083018e90526101e08301526101a08201879052158061092c57508160ff166001145b6040518060400160405280600b81526020016a04241445f494d4d5f5459560ac1b815250906109d95760405162461bcd60e51b81526004018080602001828103825283818151815260200191508051906020019080838360005b8381101561099e578181015183820152602001610986565b50505050905090810190601f1680156109cb5780820380516001836020036101000a031916815260200191505b509250505060405180910390fd5b506109e2613fab565b60ff8316610a03576109fc8a83604001516000015161168f565b9050610aa3565b6000865111604051806040016040528060068152602001654e4f5f494d4d60d01b81525090610a735760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561099e578181015183820152602001610986565b50610aa08a8360400151600001518860018d0360ff1681518110610a9357fe5b60200260200101516116f3565b90505b610aac81611779565b60408301515260005b838a0360ff16811015610af457610aec878281518110610ad157fe5b602002602001015184604001516118e690919063ffffffff16565b600101610ab5565b5060005b8860ff16811015610b3557610b2d868281518110610b1257fe5b6020026020010151846040015161190090919063ffffffff16565b600101610af8565b50909f9e505050505050505050505050505050565b6000806000614046610b6385610160015160ff1661191a565b93509350935093506000841180610b7d5750846101400151155b8015610b8f5750610100850151518410155b80610bb757508461014001518015610ba5575083155b8015610bb75750610100850151516001145b6040518060400160405280600a815260200169535441434b5f4d414e5960b01b81525090610c265760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561099e578181015183820152602001610986565b50610120850151516040805180820190915260088152674155585f4d414e5960c01b602082015290841015610c9c5760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561099e578181015183820152602001610986565b5061010085015151841115610d5a57610cbb610cb6611a2a565b611779565b610ccc866060015160200151611779565b146040518060400160405280600d81526020016c535441434b5f4d495353494e4760981b81525090610d3f5760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561099e578181015183820152602001610986565b50610d4b856005611a71565b50610d5585611ae6565b610e1a565b61012085015151831115610df557610d73610cb6611a2a565b610d84866060015160400151611779565b146040518060400160405280600b81526020016a4155585f4d495353494e4760a81b81525090610d3f5760405162461bcd60e51b815260206004820181815283516024840152835190928392604490910191908501908083836000831561099e578181015183820152602001610986565b610dff8583611a71565b15610e0d57610d5585611ae6565b610e1a858263ffffffff16565b846101e0015115610ebf5760408051600160f81b6020808301919091526000602183018190526022808401919091528351808403909101815260429092019092528051910120606086015160c001511415610e8157610e7c8560600151611af1565b610ebf565b60006101e0860152606085015160c081015190526101408501518015610ea5575083155b610eb457610100850151600090525b610120850151600090525b60005b61010086015151811015610f0b57610f03866101000151602001518281518110610ee857fe5b602002602001015187606001516118e690919063ffffffff16565b600101610ec2565b5060005b61012086015151811015610f5857610f50866101200151602001518281518110610f3557fe5b6020026020010151876060015161190090919063ffffffff16565b600101610f0f565b505050505050565b600080610f6b613ed3565b8360e0015184608001516040518060800160405280610f8d8860400151611afb565b8152602001610f9f8860600151611afb565b81526020018760a0015181526020018760c001518152509250925092509193909250565b610fcb613f83565b606061100a8384600081518110610fde57fe5b602001015160f81c60f81b85600181518110610ff657fe5b01602001516001600160f81b031916611bbf565b90506060611037848560018151811061101f57fe5b602001015160f81c60f81b86600281518110610ff657fe5b90506060611064858660028151811061104c57fe5b602001015160f81c60f81b87600381518110610ff657fe5b90506060611091868760038151811061107957fe5b602001015160f81c60f81b88600481518110610ff657fe5b6040805160808101825295865260208601949094529284019190915250606082015290505b919050565b60606110ca8260000151611c5c565b6110df6110da8460200151611779565b611c5c565b6110ef6110da8560400151611779565b6110ff6110da8660600151611779565b61110f6110da8760800151611779565b61111c8760a00151611d2b565b6111298860c00151611c5c565b60405160200180806709ac2c6d0d2dcca560c31b81525060080188805190602001908083835b6020831061116e5780518252601f19909201916020918201910161114f565b51815160209384036101000a60001901801990921691161790526216100560e91b9190930190815289516003909101928a0191508083835b602083106111c55780518252601f1990920191602091820191016111a6565b51815160209384036101000a60001901801990921691161790526216100560e91b919093019081528851600390910192890191508083835b6020831061121c5780518252601f1990920191602091820191016111fd565b51815160209384036101000a60001901801990921691161790526216100560e91b919093019081528751600390910192880191508083835b602083106112735780518252601f199092019160209182019101611254565b51815160209384036101000a60001901801990921691161790526216100560e91b919093019081528651600390910192870191508083835b602083106112ca5780518252601f1990920191602091820191016112ab565b51815160209384036101000a60001901801990921691161790526216100560e91b919093019081528551600390910192860191508083835b602083106113215780518252601f199092019160209182019101611302565b51815160209384036101000a60001901801990921691161790526216100560e91b919093019081528451600390910192850191508083835b602083106113785780518252601f199092019160209182019101611359565b5181516020939093036101000a600019018019909116921691909117905261148560f11b92019182525060408051808303601d19018152600290920190529a9950505050505050505050565b60006113ce613fab565b83518310611414576040805162461bcd60e51b815260206004820152600e60248201526d1a5b9d985b1a59081bd9999cd95d60921b604482015290519081900360640190fd5b6000806114218686611e05565b9150915061142d611e2c565b60ff168160ff1614156114615760006114468784611e31565b90935090508261145582611ea5565b9450945050505061157f565b611469611f65565b60ff168160ff16141561148b576114808683611f6a565b93509350505061157f565b61149361200c565b60ff168160ff1614156114bb5760006114ac8784611e31565b90935090508261145582612011565b6114c36120fd565b60ff168160ff1614156114da576114808683612102565b6114e2612197565b60ff168160ff161015801561150357506114fa61219c565b60ff168160ff16105b1561153f576000611512612197565b8203905060606115238289866121a1565b90945090508361153282612249565b955095505050505061157f565b6040805162461bcd60e51b815260206004820152601060248201526f696e76616c69642074797065636f646560801b604482015290519081900360640190fd5b9250929050565b6000611590613fe8565b611598613fe8565b600060e08201819052806115ac8787611e31565b90965091506115bb8787612102565b602085015295506115cc8787612102565b604085015295506115dd87876113c4565b606085015295506115ee87876113c4565b608085015295506115ff8787611e31565b60a085015295506116108787611e31565b92845260c0840192909252509590945092505050565b61162e613fe8565b60405180610100016040528083600001518152602001836020015181526020018360400151815260200183606001518152602001836080015181526020018360a0015181526020018360c0015181526020018360e001518152509050919050565b611697613fab565b6040805160608101825260ff8516815260208082018590528251600080825291810184526116ea938301916116e2565b6116cf613fab565b8152602001906001900390816116c75790505b50905261238a565b90505b92915050565b6116fb613fab565b604080516001808252818301909252606091816020015b61171a613fab565b815260200190600190039081611712579050509050828160008151811061173d57fe5b602002602001018190525061176e60405180606001604052808760ff1681526020018681526020018381525061238a565b9150505b9392505050565b6000611783611e2c565b60ff16826080015160ff1614156117a657815161179f9061241a565b90506110b6565b6117ae611f65565b60ff16826080015160ff1614156117cc5761179f826020015161243e565b6117d46120fd565b60ff16826080015160ff1614156117f657815160a083015161179f919061253b565b6117fe612197565b60ff16826080015160ff16141561183757611817613fab565b611824836040015161258c565b905061182f81611779565b9150506110b6565b61183f612704565b60ff16826080015160ff161415611858575080516110b6565b61186061200c565b60ff16826080015160ff1614156118a5575060608082015160408051607b602080830191909152818301939093528151808203830181529301905281519101206110b6565b6040805162461bcd60e51b8152602060048201526011602482015270496e76616c6964207479706520636f646560781b604482015290519081900360640190fd5b6118f4826020015182612709565b82602001819052505050565b61190e826040015182612709565b82604001819052505050565b6000808061404660a185141561193f57506002925060009150600a90506127876105c7565b60a285141561195d57506002925060009150600a905061283e6105c7565b60a385141561197b57506002925060009150600a90506128d26105c7565b60a485141561199957506003925060009150606490506129666105c7565b60a58514156119b75750600392506000915060649050612a576105c7565b60a68514156119d55750600392506000915060649050612b2b6105c7565b60708514156119f35750600292506000915060649050612bed6105c7565b60405162461bcd60e51b815260040180806020018281038252602c815260200180614082602c913960400191505060405180910390fd5b611a32613fab565b60408051600080825260208201909252611a6c91611a66565b611a53613fab565b815260200190600190039081611a4b5790505b50612249565b905090565b6000816001600160401b0316836060015160a001511015611ab6575060e0820180516005016001600160401b03169052606082015160001960a09091015260016116ed565b5060e0820180516001600160401b039083018116909152606083015160a0018051918316909103905260006116ed565b60016101e090910152565b600160e090910152565b600060028260e001511415611b12575060006110b6565b60018260e001511415611b27575060016110b6565b81516020830151611b3790611779565b611b448460400151611779565b611b518560600151611779565b611b5e8660800151611779565b8660a001518760c00151604051602001808881526020018781526020018681526020018581526020018481526020018381526020018281526020019750505050505050506040516020818303038152906040528051906020012090506110b6565b606060f883811c9083901c81900360ff169082826001600160401b0381118015611be857600080fd5b50604051908082528060200260200182016040528015611c12578160200160208202803683370190505b50905060005b83811015611c5157611c2f88828501602002612d89565b60001b828281518110611c3e57fe5b6020908102919091010152600101611c18565b509695505050505050565b60408051818152606081810183529182919060208201818036833701905050905060005b6020811015611d24576000848260208110611c9757fe5b1a60f881811b9250601080830480831b9360ff9091169091029003901b611cbd82612dc9565b858560020281518110611ccc57fe5b60200101906001600160f81b031916908160001a905350611cec81612dc9565b858560020260010181518110611cfe57fe5b60200101906001600160f81b031916908160001a9053505060019092019150611c809050565b5092915050565b60608180611d525750506040805180820190915260018152600360fc1b60208201526110b6565b8060005b8115611d6a57600101600a82049150611d56565b6060816001600160401b0381118015611d8257600080fd5b506040519080825280601f01601f191660200182016040528015611dad576020820181803683370190505b50905060001982015b8415611dfb57600a850660300160f81b82828060019003935081518110611dd957fe5b60200101906001600160f81b031916908160001a905350600a85049450611db6565b5095945050505050565b60008082600101848481518110611e1857fe5b016020015190925060f81c90509250929050565b600090565b60008082845110158015611e49575060208385510310155b611e86576040805162461bcd60e51b81526020600482015260096024820152681d1bdbc81cda1bdc9d60ba1b604482015290519081900360640190fd5b60208301611e9a858563ffffffff612dfa16565b915091509250929050565b611ead613fab565b6040805160c0810182528381528151606081018352600080825260208083018290528451828152808201865293949085019390830191611f03565b611ef0613fab565b815260200190600190039081611ee85790505b50905281526020016000604051908082528060200260200182016040528015611f4657816020015b611f33613fab565b815260200190600190039081611f2b5790505b5081526000602082018190526040820152600160609091015292915050565b600190565b6000611f74613fab565b82600080611f80613fab565b6000611f8c8986611e05565b9095509350611f9b8986611e05565b9095509250600160ff85161415611fbc57611fb689866113c4565b90955091505b611fc68986612e53565b9095509050600160ff85161415611ff15784611fe38483856116f3565b96509650505050505061157f565b84611ffc848361168f565b9650965050505050509250929050565b600c90565b612019613fab565b6040518060c00160405280600081526020016040518060600160405280600060ff1681526020016000801b815260200160006001600160401b038111801561206057600080fd5b5060405190808252806020026020018201604052801561209a57816020015b612087613fab565b81526020019060019003908161207f5790505b509052815260200160006040519080825280602002602001820160405280156120dd57816020015b6120ca613fab565b8152602001906001900390816120c25790505b50815260208101849052600c604082015260016060909101529050919050565b600290565b600061210c613fab565b82845110158015612121575060408385510310155b61215e576040805162461bcd60e51b81526020600482015260096024820152681d1bdbc81cda1bdc9d60ba1b604482015290519081900360640190fd5b60008061216b8686612e53565b909450915061217a8685611e31565b90945090508361218a8383612e6a565b9350935050509250929050565b600390565b600d90565b60006060828160ff87166001600160401b03811180156121c057600080fd5b506040519080825280602002602001820160405280156121fa57816020015b6121e7613fab565b8152602001906001900390816121df5790505b50905060005b8760ff168160ff16101561223c5761221887846113c4565b838360ff168151811061222757fe5b60209081029190910101529250600101612200565b5090969095509350505050565b612251613fab565b61225b8251612f29565b6122ac576040805162461bcd60e51b815260206004820152601a60248201527f5475706c65206d75737420686176652076616c69642073697a65000000000000604482015290519081900360640190fd5b600160005b83518110156122e3578381815181106122c657fe5b602002602001015160a001518201915080806001019150506122b1565b506040518060c00160405280600081526020016040518060600160405280600060ff1681526020016000801b815260200160006001600160401b038111801561232b57600080fd5b5060405190808252806020026020018201604052801561236557816020015b612352613fab565b81526020019060019003908161234a5790505b5090528152602081019490945260006040850152600360608501526080909301525090565b612392613fab565b6040518060c001604052806000815260200183815260200160006001600160401b03811180156123c157600080fd5b506040519080825280602002602001820160405280156123fb57816020015b6123e8613fab565b8152602001906001900390816123e05790505b5081526000602082015260016040820181905260609091015292915050565b60408051602080820193909352815180820384018152908201909152805191012090565b600060028260400151511061244f57fe5b6040820151516124b457612461611f65565b8251602080850151604080516001600160f81b031960f896871b8116828601529490951b9093166021850152602280850191909152825180850390910181526042909301909152815191012090506110b6565b6124bc611f65565b82600001516124e284604001516000815181106124d557fe5b6020026020010151611779565b8460200151604051602001808560ff1660ff1660f81b81526001018460ff1660ff1660f81b8152600101838152602001828152602001945050505050604051602081830303815290604052805190602001209050919050565b6000612545612197565b8383604051602001808460ff1660ff1660f81b8152600101838152602001828152602001935050505060405160208183030381529060405280519060200120905092915050565b612594613fab565b6008825111156125e2576040805162461bcd60e51b8152602060048201526014602482015273092dcecc2d8d2c840e8eae0d8ca40d8cadccee8d60631b604482015290519081900360640190fd5b606082516001600160401b03811180156125fb57600080fd5b50604051908082528060200260200182016040528015612625578160200160208202803683370190505b508051909150600160005b82811015612688576126478682815181106124d557fe5b84828151811061265357fe5b60200260200101818152505085818151811061266b57fe5b602002602001015160a00151820191508080600101915050612630565b506000835184604051602001808360ff1660ff1660f81b8152600101828051906020019060200280838360005b838110156126cd5781810151838201526020016126b5565b50505050905001925050506040516020818303038152906040528051906020012090506126fa8183612e6a565b9695505050505050565b606490565b612711613fab565b6040805160028082526060828101909352816020015b61272f613fab565b815260200190600190039081612727579050509050828160008151811061275257fe5b6020026020010181905250838160018151811061276b57fe5b602002602001018190525061277f8161258c565b949350505050565b61278f613fab565b61279d826101000151612f30565b90506127a7613fab565b6127b5836101000151612f30565b90506127c082612f72565b15806127d257506127d081612f90565b155b156127e7576127e083612f9d565b505061283b565b8151600160401b116127fc576127e083612f9d565b600061281e82606001518460000151612819876101c00151610fc3565b612fa6565b905061283784610100015161283283611ea5565b612fc8565b5050505b50565b612846613fab565b612854826101000151612f30565b905061285e613fab565b61286c836101000151612f30565b905061287782612f72565b1580612889575061288781612f90565b155b15612897576127e083612f9d565b815167fffffffffffffff9116128b0576127e083612f9d565b600061281e826060015184600001516128cd876101c00151610fc3565b612ff2565b6128da613fab565b6128e8826101000151612f30565b90506128f2613fab565b612900836101000151612f30565b905061290b82612f72565b158061291d575061291b81612f90565b155b1561292b576127e083612f9d565b815167ffffffffffffffe111612944576127e083612f9d565b600061281e82606001518460000151612961876101c00151610fc3565b613152565b61296e613fab565b61297c826101000151612f30565b9050612986613fab565b612994836101000151612f30565b905061299e613fab565b6129ac846101000151612f30565b90506129b783612f72565b15806129c957506129c782613286565b155b806129da57506129d881612f90565b155b156129f0576129e884612f9d565b50505061283b565b8251600160401b111580612a075750815161010011155b15612a15576129e884612f9d565b6000612a3c826060015185600001518560000151612a37896101c00151610fc3565b613291565b9050612a5085610100015161283283612011565b5050505050565b612a5f613fab565b612a6d826101000151612f30565b9050612a77613fab565b612a85836101000151612f30565b9050612a8f613fab565b612a9d846101000151612f30565b9050612aa883612f72565b1580612aba5750612ab882613286565b155b80612acb5750612ac981612f90565b155b15612ad9576129e884612f9d565b825167fffffffffffffff9111580612af657508151600160401b11155b15612b04576129e884612f9d565b6000612a3c826060015185600001518560000151612b26896101c00151610fc3565b6132da565b612b33613fab565b612b41826101000151612f30565b9050612b4b613fab565b612b59836101000151612f30565b9050612b63613fab565b612b71846101000151612f30565b9050612b7c83612f72565b1580612b8e5750612b8c82613286565b155b80612b9f5750612b9d81612f90565b155b15612bad576129e884612f9d565b825167ffffffffffffffe111612bc6576129e884612f9d565b6000612a3c826060015185600001518560000151612be8896101c00151610fc3565b613423565b612bf5613fab565b612c03826101000151612f30565b9050612c0d613fab565b612c1b836101000151612f30565b9050612c2682612f72565b1580612c385750612c3681612f90565b155b15612c46576127e083612f9d565b81516127101080612c5657508151155b15612c64576127e083612f9d565b82610180015151836101a001511415612cdf57612c9781606001518360000151612c92866101c00151610fc3565b6134f5565b15612cd6576040805162461bcd60e51b815260206004820152600a602482015269084aa8cbe988a9c8ea8960b31b604482015290519081900360640190fd5b6127e083612f9d565b6101a083015182516101808501516000612cfa828585613549565b905080612d0686611779565b14612d45576040805162461bcd60e51b815260206004820152600a60248201526915d493d391d7d4d1539160b21b604482015290519081900360640190fd5b5090910160209081019190912060a0850180516040805180860192909252818101939093528251808203840181526060909101909252815191909201209052505050565b600080805b6020811015612dc157600882901b91508481850181518110612dac57fe5b016020015160f81c9190911790600101612d8e565b509392505050565b6000600a60f883901c1015612de9578160f81c60300160f81b90506110b6565b8160f81c60570160f81b90506110b6565b60008160200183511015612e4a576040805162461bcd60e51b815260206004820152601260248201527152656164206f7574206f6620626f756e647360701b604482015290519081900360640190fd5b50016020015190565b60008060208301611e9a858563ffffffff612dfa16565b612e72613fab565b6040805160c0810182528481528151606081018352600080825260208083018290528451828152808201865293949085019390830191612ec8565b612eb5613fab565b815260200190600190039081612ead5790505b50905281526020016000604051908082528060200260200182016040528015612f0b57816020015b612ef8613fab565b815260200190600190039081612ef05790505b50815260006020820152600260408201526060019290925250919050565b6008101590565b612f38613fab565b612f40613fab565b8260200151600184600001510381518110612f5757fe5b60209081029190910101518351600019018452915050919050565b608081015160009060ff161580156116ed57505051600160401b1190565b6080015160ff16600c1490565b61283b81611ae6565b600061277f612fbe856020865b048560000151613572565b6020855b066136e0565b808260200151836000015181518110612fdd57fe5b60209081029190910101525080516001019052565b60408051600880825281830190925260009160609190602082018180368337019050509050600061302c866020875b048660000151613572565b905060208086066008011115613100576000613054876020885b046001018760400151613572565b905060005b6018601f8816600803018110156130a85761307a838260208a5b06016136e0565b60f81b84828151811061308957fe5b60200101906001600160f81b031916908160001a905350600101613059565b506018601f8716600803015b60088110156130f9576130cb826020898401612fc2565b60f81b8482815181106130da57fe5b60200101906001600160f81b031916908160001a9053506001016130b4565b5050613149565b60005b6008811015613147576131198282602089613073565b60f81b83828151811061312857fe5b60200101906001600160f81b031916908160001a905350600101613103565b505b6126fa826136ed565b60408051602080825281830190925260009160609190602082018180368337019050509050600061318586602087613021565b90506020808606602001111561323f5760006131a387602088613046565b905060005b601f87166020038110156131f1576131c3838260208a613073565b60f81b8482815181106131d257fe5b60200101906001600160f81b031916908160001a9053506001016131a8565b50601f86166020035b60208110156130f957613211826020898401612fc2565b60f81b84828151811061322057fe5b60200101906001600160f81b031916908160001a9053506001016131fa565b60005b6020811015613147576132588282602089613073565b60f81b83828151811061326757fe5b60200101906001600160f81b031916908160001a905350600101613242565b6080015160ff161590565b6000806132a086602087612fb3565b905060006132b2826020880687613723565b905060006132ce88602089048488600001518960200151613762565b98975050505050505050565b600060606132e784613802565b905060006132f787602088613021565b9050602080870660080111156133d95760005b6018601f881660080301811015613352576133488260208984010685846018018151811061333457fe5b01602001516001600160f81b03191661386c565b915060010161330a565b5061336c876020885b048387600001518860200151613762565b9650600061337c88602089613046565b90506018601f8816600803015b60088110156133b5576133ab8260208a84010686846018018151811061333457fe5b9150600101613389565b506133d188602089046001018388604001518960600151613762565b975050613418565b60005b6008811015613408576133fe828260208a060185846018018151811061333457fe5b91506001016133dc565b506134158760208861335b565b96505b509495945050505050565b6000606061343084613802565b9050600061344087602088613021565b9050602080870660200111156134d25760005b601f871660200381101561348257613478828260208a5b060185848151811061333457fe5b9150600101613453565b5061348f8760208861335b565b9650600061349f88602089613046565b9050601f87166020035b60208110156133b5576134c88260208a84010686848151811061333457fe5b91506001016134a9565b60005b6020811015613408576134eb828260208a61346a565b91506001016134d5565b60008061350485602086612fb3565b9050601f84165b60208110156135365761351e82826136e0565b1561352e57600092505050611772565b60010161350b565b5061176e85602086048560000151613888565b600080613564858486018661355d87613a04565b6001613a2f565b50905061176e607b82613b07565b60008151600014156135db57613588600061241a565b84146135d3576040805162461bcd60e51b815260206004820152601560248201527432bc3832b1ba32b21032b6b83a3c90313ab33332b960591b604482015290519081900360640190fd5b506000611772565b60006135fa836000815181106135ed57fe5b602002602001015161241a565b905060015b83518110156136645784600116600114156136385761363184828151811061362357fe5b602002602001015183613b07565b9150613658565b6136558285838151811061364857fe5b6020026020010151613b07565b91505b600194851c94016135ff565b508481146136b1576040805162461bcd60e51b8152602060048201526015602482015274195e1c1958dd19590818dbdc9c9958dd081c9bdbdd605a1b604482015290519081900360640190fd5b83156136c1575060009050611772565b826000815181106136ce57fe5b60200260200101519150509392505050565b601f036008021c60ff1690565b600080805b8351811015611d2457600882901b915083818151811061370e57fe5b016020015160f81c91909117906001016136f2565b6000606061373085613802565b90508260f81b81858151811061374257fe5b60200101906001600160f81b031916908160001a90535061176e816136ed565b600081516003146137b4576040805162461bcd60e51b81526020600482015260176024820152762120a22fa727a926a0a624ad20aa24a7a72fa82927a7a360491b604482015290519081900360640190fd5b6126fa86868686866000815181106137c857fe5b602002602001015160001c876001815181106137e057fe5b6020026020010151886002815181106137f557fe5b6020026020010151613b33565b6040805160208082528183019092526060918391839160208201818036833701905050905060005b6020811015612dc1578260f81b8282601f038151811061384657fe5b60200101906001600160f81b031916908160001a90535060089290921c9160010161382a565b6000606061387985613802565b90508281858151811061374257fe5b60008151600014156138f15761389e600061241a565b84146138e9576040805162461bcd60e51b815260206004820152601560248201527432bc3832b1ba32b21032b6b83a3c90313ab33332b960591b604482015290519081900360640190fd5b506001611772565b6000613903836000815181106135ed57fe5b905060016060613911613dad565b905060015b85518110156139a557866001166001141561394f5761394886828151811061393a57fe5b602002602001015185613b07565b9350613999565b61395f8487838151811061364857fe5b9350828015613996575081600182038151811061397857fe5b602002602001015186828151811061398c57fe5b6020026020010151145b92505b600196871c9601613916565b508683146139f2576040805162461bcd60e51b8152602060048201526015602482015274195e1c1958dd19590818dbdc9c9958dd081c9bdbdd605a1b604482015290519081900360640190fd5b8515611dfb5760019350505050611772565b600060018211613a16575060016110b6565b613a2560026001840104613a04565b60020290506110b6565b60008060208411613a8357858510613a5657613a4b600061241a565b600191509150613afd565b6000613a6b613a6689888a613e4e565b61241a565b905080613a78600061241a565b909350149050613afd565b600080613a9d8989600289048a0160028a5b046000613a2f565b91509150808015613aab5750845b15613acb57613ac089898960028a0489613a2f565b935093505050613afd565b600080613adc8b8b8b60028c613a95565b91509150613aea8285613b07565b818015613af45750835b95509550505050505b9550959350505050565b604080516020808201949094528082019290925280518083038201815260609092019052805191012090565b600080613b3f8761241a565b9050613b4c898988613572565b506060613b57613dad565b905060018751036001901b8910613c1b5787613b77578992505050613da2565b6000613b828a613ead565b88519091505b60018203811015613bb057613ba68c84600184038151811061364857fe5b9b50600101613b88565b5060015b60018203811015613c06578a60011660011415613be457613bdd83600183038151811061393a57fe5b9350613bfa565b613bf78484600184038151811061364857fe5b93505b60019a8b1c9a01613bb4565b50613c118b84613b07565b9350505050613da2565b60015b8751811015613c9b5760008a600116600114613c3a5783613c4f565b888281518110613c4657fe5b60200260200101515b905060008b600116600114613c7757898381518110613c6a57fe5b6020026020010151613c79565b845b9050613c858282613b07565b60019c8d1c9c909550929092019150613c1e9050565b508715613caa57509050613da2565b600086613cb8575084613d2d565b818781518110613cc457fe5b6020026020010151851415613d20576040805162461bcd60e51b815260206004820152601c60248201527f726967687420737562747265652063616e6e6f74206265207a65726f00000000604482015290519081900360640190fd5b613d2a8686613b07565b90505b80875b60018a5103811015613d5657613d4c8285838151811061364857fe5b9150600101613d30565b50838114613d9c576040805162461bcd60e51b815260206004820152600e60248201526d0caf0e0cac6e8cac840dac2e8c6d60931b604482015290519081900360640190fd5b50925050505b979650505050505050565b60408051818152610820810182526060918291906020820161080080368337019050509050613ddc600061241a565b81600081518110613de957fe5b602090810291909101015260015b6040811015613e4857613e29826001830381518110613e1257fe5b602002602001015183600184038151811061364857fe5b828281518110613e3557fe5b6020908102919091010152600101613df7565b50905090565b600080805b6020811015613ea457600882901b915060008186018511613e75576000613e93565b8682870181518110613e8357fe5b01602001516001600160f81b0319165b60f81c929092179150600101613e53565b50949350505050565b600081613ebc575060016110b6565b613ec9600183901c613ead565b60010190506110b6565b60405180608001604052806004906020820280368337509192915050565b604080516102008101825260008082526020820152908101613f11613fe8565b8152602001613f1e613fe8565b81526000602082018190526040820181905260608201819052608082015260a001613f47614048565b8152602001613f54614048565b81526000602082018190526040820181905260608083018190526080830182905260a083015260c09091015290565b6040518060800160405280606081526020016060815260200160608152602001606081525090565b6040518060c0016040528060008152602001613fc5614062565b815260606020820181905260006040830181905290820181905260809091015290565b6040805161010081019091526000815260208101614004613fab565b8152602001614011613fab565b815260200161401e613fab565b815260200161402b613fab565b81526000602082018190526040820181905260609091015290565bfe5b604051806040016040528060008152602001606081525090565b604080516060808201835260008083526020830152918101919091529056fe75736520616e6f7468657220636f6e747261637420746f2068616e646c65206f74686572206f70636f646573a2646970667358221220d2b0dc1d0995b28b667486ef43a27a69bfb3453af6b9ad2b4746dbebd18b35d964736f6c634300060b0033

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

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.