ETH Price: $2,074.80 (+4.19%)

Contract

0xDBE5c009095169D3de4a8D1C70E319fE647A3DBf
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Token Holdings

More Info

Private Name Tags

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Initialize154131482022-08-26 4:00:051312 days ago1661486405IN
0xDBE5c009...E647A3DBf
0 ETH0.0002217410.25967801

View more zero value Internal Transactions in Advanced View mode

Advanced mode:
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:
RollupUserFacet

Compiler Version
v0.6.11+commit.5ef660b1

Optimization Enabled:
Yes with 100 runs

Other Settings:
default evmVersion
File 1 of 34 : RollupUser.sol
// SPDX-License-Identifier: Apache-2.0

pragma solidity ^0.6.11;

import "../Rollup.sol";
import "./IRollupFacets.sol";
import { NitroReadyMagicNums } from "../../bridge/NitroMigratorUtil.sol";

abstract contract AbsRollupUserFacet is RollupBase, IRollupUser {
    function initialize(address _stakeToken) public virtual override;

    modifier onlyValidator() {
        require(isValidator[msg.sender], "NOT_VALIDATOR");
        _;
    }

    /**
     * @notice Reject the next unresolved node
     * @param stakerAddress Example staker staked on sibling, used to prove a node is on an unconfirmable branch and can be rejected
     */
    function rejectNextNode(address stakerAddress) external onlyValidator whenNotPaused {
        requireUnresolvedExists();
        uint256 latestConfirmedNodeNum = latestConfirmed();
        uint256 firstUnresolvedNodeNum = firstUnresolvedNode();
        INode firstUnresolvedNode_ = getNode(firstUnresolvedNodeNum);

        if (firstUnresolvedNode_.prev() == latestConfirmedNodeNum) {
            /**If the first unresolved node is a child of the latest confirmed node, to prove it can be rejected, we show:
             * a) Its deadline has expired
             * b) *Some* staker is staked on a sibling

             * The following three checks are sufficient to prove b:
            */

            // 1.  StakerAddress is indeed a staker
            require(isStaked(stakerAddress), "NOT_STAKED");

            // 2. Staker's latest staked node hasn't been resolved; this proves that staker's latest staked node can't be a parent of firstUnresolvedNode
            requireUnresolved(latestStakedNode(stakerAddress));

            // 3. staker isn't staked on first unresolved node; this proves staker's latest staked can't be a child of firstUnresolvedNode (recall staking on node requires staking on all of its parents)
            require(!firstUnresolvedNode_.stakers(stakerAddress), "STAKED_ON_TARGET");
            // If a staker is staked on a node that is neither a child nor a parent of firstUnresolvedNode, it must be a sibling, QED

            // Verify the block's deadline has passed
            firstUnresolvedNode_.requirePastDeadline();

            getNode(latestConfirmedNodeNum).requirePastChildConfirmDeadline();

            removeOldZombies(0);

            // Verify that no staker is staked on this node
            require(
                firstUnresolvedNode_.stakerCount() == countStakedZombies(firstUnresolvedNode_),
                "HAS_STAKERS"
            );
        }
        // Simpler case: if the first unreseolved node doesn't point to the last confirmed node, another branch was confirmed and can simply reject it outright
        _rejectNextNode();
        rollupEventBridge.nodeRejected(firstUnresolvedNodeNum);

        emit NodeRejected(firstUnresolvedNodeNum);
    }

    /**
     * @notice Confirm the next unresolved node
     * @param beforeSendAcc Accumulator of the AVM sends from the beginning of time up to the end of the previous confirmed node
     * @param sendsData Concatenated data of the sends included in the confirmed node
     * @param sendLengths Lengths of the included sends
     * @param afterSendCount Total number of AVM sends emitted from the beginning of time after this node is confirmed
     * @param afterLogAcc Accumulator of the AVM logs from the beginning of time up to the end of this node
     * @param afterLogCount Total number of AVM logs emitted from the beginning of time after this node is confirmed
     */
    function confirmNextNode(
        bytes32 beforeSendAcc,
        bytes calldata sendsData,
        uint256[] calldata sendLengths,
        uint256 afterSendCount,
        bytes32 afterLogAcc,
        uint256 afterLogCount
    ) external onlyValidator whenInShutdownModeOrNotPaused {
        requireUnresolvedExists();

        // There is at least one non-zombie staker
        require(stakerCount() > 0, "NO_STAKERS");

        INode node = getNode(firstUnresolvedNode());

        // Verify the block's deadline has passed
        node.requirePastDeadline();
        getNode(latestConfirmed()).requirePastChildConfirmDeadline();

        // Check that prev is latest confirmed
        require(node.prev() == latestConfirmed(), "INVALID_PREV");

        removeOldZombies(0);

        // All non-zombie stakers are staked on this node
        require(
            node.stakerCount() == stakerCount().add(countStakedZombies(node)),
            "NOT_ALL_STAKED"
        );

        confirmNextNode(
            beforeSendAcc,
            sendsData,
            sendLengths,
            afterSendCount,
            afterLogAcc,
            afterLogCount,
            outbox,
            rollupEventBridge
        );
    }

    /**
     * @notice Create a new stake
     * @param depositAmount The amount of either eth or tokens staked
     */
    function _newStake(uint256 depositAmount) internal onlyValidator whenNotPaused {
        // Verify that sender is not already a staker
        require(!isStaked(msg.sender), "ALREADY_STAKED");
        require(!isZombie(msg.sender), "STAKER_IS_ZOMBIE");
        require(depositAmount >= currentRequiredStake(), "NOT_ENOUGH_STAKE");

        createNewStake(msg.sender, depositAmount);

        rollupEventBridge.stakeCreated(msg.sender, latestConfirmed());
    }

    /**
     * @notice Move stake onto existing child node
     * @param nodeNum Index of the node to move stake to. This must by a child of the node the staker is currently staked on
     * @param nodeHash Node hash of nodeNum (protects against reorgs)
     */
    function stakeOnExistingNode(uint256 nodeNum, bytes32 nodeHash)
        external
        onlyValidator
        whenNotPaused
    {
        require(isStaked(msg.sender), "NOT_STAKED");

        require(getNodeHash(nodeNum) == nodeHash, "NODE_REORG");
        require(
            nodeNum >= firstUnresolvedNode() && nodeNum <= latestNodeCreated(),
            "NODE_NUM_OUT_OF_RANGE"
        );
        INode node = getNode(nodeNum);
        require(latestStakedNode(msg.sender) == node.prev(), "NOT_STAKED_PREV");
        stakeOnNode(msg.sender, nodeNum, confirmPeriodBlocks);
    }

    /**
     * @notice Create a new node and move stake onto it
     * @param expectedNodeHash The hash of the node being created (protects against reorgs)
     * @param assertionBytes32Fields Assertion data for creating
     * @param assertionIntFields Assertion data for creating
     * @param beforeProposedBlock Block number at previous assertion
     * @param beforeInboxMaxCount Inbox count at previous assertion
     * @param sequencerBatchProof Proof data for ensuring expected state of inbox (used in Nodehash to protect against reorgs)
     */
    function stakeOnNewNode(
        bytes32 expectedNodeHash,
        bytes32[3][2] calldata assertionBytes32Fields,
        uint256[4][2] calldata assertionIntFields,
        uint256 beforeProposedBlock,
        uint256 beforeInboxMaxCount,
        bytes calldata sequencerBatchProof
    ) external onlyValidator whenNotPaused {
        require(isStaked(msg.sender), "NOT_STAKED");

        RollupLib.Assertion memory assertion = RollupLib.decodeAssertion(
            assertionBytes32Fields,
            assertionIntFields,
            beforeProposedBlock,
            beforeInboxMaxCount,
            sequencerBridge.messageCount()
        );

        {
            uint256 timeSinceLastNode = block.number.sub(assertion.beforeState.proposedBlock);
            // Verify that assertion meets the minimum Delta time requirement
            require(timeSinceLastNode >= minimumAssertionPeriod, "TIME_DELTA");

            uint256 gasUsed = RollupLib.assertionGasUsed(assertion);
            // Minimum size requirements: each assertion must satisfy either
            require(
                // Consumes at least all inbox messages put into L1 inbox before your prev node’s L1 blocknum
                assertion.afterState.inboxCount >= assertion.beforeState.inboxMaxCount ||
                    // Consumes AvmGas >=100% of speed limit for time since your prev node (based on difference in L1 blocknum)
                    gasUsed >= timeSinceLastNode.mul(avmGasSpeedLimitPerBlock) ||
                    assertion.afterState.sendCount.sub(assertion.beforeState.sendCount) ==
                    MAX_SEND_COUNT,
                "TOO_SMALL"
            );

            // Don't allow an assertion to include more than the maxiumum number of sends
            require(
                assertion.afterState.sendCount.sub(assertion.beforeState.sendCount) <=
                    MAX_SEND_COUNT,
                "TOO_MANY_SENDS"
            );

            // Don't allow an assertion to use above a maximum amount of gas
            require(gasUsed <= timeSinceLastNode.mul(avmGasSpeedLimitPerBlock).mul(4), "TOO_LARGE");
        }
        createNewNode(
            assertion,
            assertionBytes32Fields,
            assertionIntFields,
            sequencerBatchProof,
            CreateNodeDataFrame({
                avmGasSpeedLimitPerBlock: avmGasSpeedLimitPerBlock,
                confirmPeriodBlocks: confirmPeriodBlocks,
                prevNode: latestStakedNode(msg.sender), // Ensure staker is staked on the previous node
                sequencerInbox: sequencerBridge,
                rollupEventBridge: rollupEventBridge,
                nodeFactory: nodeFactory
            }),
            expectedNodeHash
        );

        stakeOnNode(msg.sender, latestNodeCreated(), confirmPeriodBlocks);
    }

    /**
     * @notice Refund a staker that is currently staked on or before the latest confirmed node
     * @dev Since a staker is initially placed in the latest confirmed node, if they don't move it
     * a griefer can remove their stake. It is recomended to batch together the txs to place a stake
     * and move it to the desired node.
     * @param stakerAddress Address of the staker whose stake is refunded
     */
    function returnOldDeposit(address stakerAddress)
        external
        override
        onlyValidator
        whenInShutdownModeOrNotPaused
    {
        require(latestStakedNode(stakerAddress) <= latestConfirmed(), "TOO_RECENT");
        requireUnchallengedStaker(stakerAddress);
        withdrawStaker(stakerAddress);
    }

    /**
     * @notice Increase the amount staked for the given staker
     * @param stakerAddress Address of the staker whose stake is increased
     * @param depositAmount The amount of either eth or tokens deposited
     */
    function _addToDeposit(address stakerAddress, uint256 depositAmount)
        internal
        onlyValidator
        whenNotPaused
    {
        requireUnchallengedStaker(stakerAddress);
        increaseStakeBy(stakerAddress, depositAmount);
    }

    /**
     * @notice Reduce the amount staked for the sender (difference between initial amount staked and target is creditted back to the sender).
     * @param target Target amount of stake for the staker. If this is below the current minimum, it will be set to minimum instead
     */
    function reduceDeposit(uint256 target) external onlyValidator whenNotPaused {
        requireUnchallengedStaker(msg.sender);
        uint256 currentRequired = currentRequiredStake();
        if (target < currentRequired) {
            target = currentRequired;
        }
        reduceStakeTo(msg.sender, target);
    }

    /**
     * @notice Start a challenge between the given stakers over the node created by the first staker assuming that the two are staked on conflicting nodes. N.B.: challenge creator does not necessarily need to be one of the two asserters.
     * @param stakers Stakers engaged in the challenge. The first staker should be staked on the first node
     * @param nodeNums Nodes of the stakers engaged in the challenge. The first node should be the earliest and is the one challenged
     * @param executionHashes Challenge related data for the two nodes
     * @param proposedTimes Times that the two nodes were proposed
     * @param maxMessageCounts Total number of messages consumed by the two nodes
     */
    function createChallenge(
        address payable[2] calldata stakers,
        uint256[2] calldata nodeNums,
        bytes32[2] calldata executionHashes,
        uint256[2] calldata proposedTimes,
        uint256[2] calldata maxMessageCounts
    ) external onlyValidator whenNotPaused {
        require(nodeNums[0] < nodeNums[1], "WRONG_ORDER");
        require(nodeNums[1] <= latestNodeCreated(), "NOT_PROPOSED");
        require(latestConfirmed() < nodeNums[0], "ALREADY_CONFIRMED");

        INode node1 = getNode(nodeNums[0]);
        INode node2 = getNode(nodeNums[1]);

        // ensure nodes staked on the same parent (and thus in conflict)
        require(node1.prev() == node2.prev(), "DIFF_PREV");

        // ensure both stakers aren't currently in challenge
        requireUnchallengedStaker(stakers[0]);
        requireUnchallengedStaker(stakers[1]);

        require(node1.stakers(stakers[0]), "STAKER1_NOT_STAKED");
        require(node2.stakers(stakers[1]), "STAKER2_NOT_STAKED");

        // Check param data against challenge hash
        require(
            node1.challengeHash() ==
                RollupLib.challengeRootHash(
                    executionHashes[0],
                    proposedTimes[0],
                    maxMessageCounts[0]
                ),
            "CHAL_HASH1"
        );

        require(
            node2.challengeHash() ==
                RollupLib.challengeRootHash(
                    executionHashes[1],
                    proposedTimes[1],
                    maxMessageCounts[1]
                ),
            "CHAL_HASH2"
        );

        // Calculate upper limit for allowed node proposal time:
        uint256 commonEndTime = getNode(node1.prev()).firstChildBlock().add( // Dispute start: dispute timer for a node starts when its first child is created
            node1.deadlineBlock().sub(proposedTimes[0]).add(extraChallengeTimeBlocks) // add dispute window to dispute start time
        );
        if (commonEndTime < proposedTimes[1]) {
            // The 2nd node was created too late; loses challenge automatically.
            completeChallengeImpl(stakers[0], stakers[1]);
            return;
        }
        // Start a challenge between staker1 and staker2. Staker1 will defend the correctness of node1, and staker2 will challenge it.
        address challengeAddress = challengeFactory.createChallenge(
            address(this),
            executionHashes[0],
            maxMessageCounts[0],
            stakers[0],
            stakers[1],
            commonEndTime.sub(proposedTimes[0]),
            commonEndTime.sub(proposedTimes[1]),
            sequencerBridge,
            delayedBridge
        ); // trusted external call

        challengeStarted(stakers[0], stakers[1], challengeAddress);

        emit RollupChallengeStarted(challengeAddress, stakers[0], stakers[1], nodeNums[0]);
    }

    /**
     * @notice Inform the rollup that the challenge between the given stakers is completed
     * @param winningStaker Address of the winning staker
     * @param losingStaker Address of the losing staker
     */
    function completeChallenge(address winningStaker, address losingStaker)
        external
        override
        whenNotPaused
    {
        // Only the challenge contract can call this to declare the winner and loser
        require(msg.sender == inChallenge(winningStaker, losingStaker), "WRONG_SENDER");

        completeChallengeImpl(winningStaker, losingStaker);
    }

    function completeChallengeImpl(address winningStaker, address losingStaker) private {
        uint256 remainingLoserStake = amountStaked(losingStaker);
        uint256 winnerStake = amountStaked(winningStaker);
        if (remainingLoserStake > winnerStake) {
            // If loser has a higher stake than the winner, refund the difference
            remainingLoserStake = remainingLoserStake.sub(reduceStakeTo(losingStaker, winnerStake));
        }

        // Reward the winner with half the remaining stake
        uint256 amountWon = remainingLoserStake / 2;
        increaseStakeBy(winningStaker, amountWon);
        remainingLoserStake = remainingLoserStake.sub(amountWon);
        clearChallenge(winningStaker);
        // Credit the other half to the owner address
        increaseWithdrawableFunds(owner, remainingLoserStake);
        // Turning loser into zombie renders the loser's remaining stake inaccessible
        turnIntoZombie(losingStaker);
    }

    /**
     * @notice Remove the given zombie from nodes it is staked on, moving backwords from the latest node it is staked on
     * @param zombieNum Index of the zombie to remove
     * @param maxNodes Maximum number of nodes to remove the zombie from (to limit the cost of this transaction)
     */
    function removeZombie(uint256 zombieNum, uint256 maxNodes)
        external
        onlyValidator
        whenNotPaused
    {
        require(zombieNum <= zombieCount(), "NO_SUCH_ZOMBIE");
        address zombieStakerAddress = zombieAddress(zombieNum);
        uint256 latestNodeStaked = zombieLatestStakedNode(zombieNum);
        uint256 nodesRemoved = 0;
        uint256 firstUnresolved = firstUnresolvedNode();
        while (latestNodeStaked >= firstUnresolved && nodesRemoved < maxNodes) {
            INode node = getNode(latestNodeStaked);
            node.removeStaker(zombieStakerAddress);
            latestNodeStaked = node.prev();
            nodesRemoved++;
        }
        if (latestNodeStaked < firstUnresolved) {
            removeZombie(zombieNum);
        } else {
            zombieUpdateLatestStakedNode(zombieNum, latestNodeStaked);
        }
    }

    /**
     * @notice Remove any zombies whose latest stake is earlier than the first unresolved node
     * @param startIndex Index in the zombie list to start removing zombies from (to limit the cost of this transaction)
     */
    function removeOldZombies(uint256 startIndex)
        public
        onlyValidator
        whenInShutdownModeOrNotPaused
    {
        uint256 currentZombieCount = zombieCount();
        uint256 firstUnresolved = firstUnresolvedNode();
        for (uint256 i = startIndex; i < currentZombieCount; i++) {
            while (zombieLatestStakedNode(i) < firstUnresolved) {
                removeZombie(i);
                currentZombieCount--;
                if (i >= currentZombieCount) {
                    return;
                }
            }
        }
    }

    /**
     * @notice Calculate the current amount of funds required to place a new stake in the rollup
     * @dev If the stake requirement get's too high, this function may start reverting due to overflow, but
     * that only blocks operations that should be blocked anyway
     * @return The current minimum stake requirement
     */
    function currentRequiredStake(
        uint256 _blockNumber,
        uint256 _firstUnresolvedNodeNum,
        uint256 _latestCreatedNode
    ) internal view returns (uint256) {
        // If there are no unresolved nodes, then you can use the base stake
        if (_firstUnresolvedNodeNum - 1 == _latestCreatedNode) {
            return baseStake;
        }
        uint256 firstUnresolvedDeadline = getNode(_firstUnresolvedNodeNum).deadlineBlock();
        if (_blockNumber < firstUnresolvedDeadline) {
            return baseStake;
        }
        uint24[10] memory numerators = [
            1,
            122971,
            128977,
            80017,
            207329,
            114243,
            314252,
            129988,
            224562,
            162163
        ];
        uint24[10] memory denominators = [
            1,
            114736,
            112281,
            64994,
            157126,
            80782,
            207329,
            80017,
            128977,
            86901
        ];
        uint256 firstUnresolvedAge = _blockNumber.sub(firstUnresolvedDeadline);
        uint256 periodsPassed = firstUnresolvedAge.mul(10).div(confirmPeriodBlocks);
        // Overflow check
        if (periodsPassed.div(10) >= 255) {
            return type(uint256).max;
        }
        uint256 baseMultiplier = 2**periodsPassed.div(10);
        uint256 withNumerator = baseMultiplier * numerators[periodsPassed % 10];
        // Overflow check
        if (withNumerator / baseMultiplier != numerators[periodsPassed % 10]) {
            return type(uint256).max;
        }
        uint256 multiplier = withNumerator.div(denominators[periodsPassed % 10]);
        if (multiplier == 0) {
            multiplier = 1;
        }
        uint256 fullStake = baseStake * multiplier;
        // Overflow check
        if (fullStake / baseStake != multiplier) {
            return type(uint256).max;
        }
        return fullStake;
    }

    /**
     * @notice Calculate the current amount of funds required to place a new stake in the rollup
     * @dev If the stake requirement get's too high, this function may start reverting due to overflow, but
     * that only blocks operations that should be blocked anyway
     * @return The current minimum stake requirement
     */
    function requiredStake(
        uint256 blockNumber,
        uint256 firstUnresolvedNodeNum,
        uint256 latestCreatedNode
    ) external view returns (uint256) {
        return currentRequiredStake(blockNumber, firstUnresolvedNodeNum, latestCreatedNode);
    }

    function currentRequiredStake() public view returns (uint256) {
        uint256 firstUnresolvedNodeNum = firstUnresolvedNode();

        return currentRequiredStake(block.number, firstUnresolvedNodeNum, latestNodeCreated());
    }

    /**
     * @notice Calculate the number of zombies staked on the given node
     *
     * @dev This function could be uncallable if there are too many zombies. However,
     * removeZombie and removeOldZombies can be used to remove any zombies that exist
     * so that this will then be callable
     *
     * @param node The node on which to count staked zombies
     * @return The number of zombies staked on the node
     */
    function countStakedZombies(INode node) public view override returns (uint256) {
        uint256 currentZombieCount = zombieCount();
        uint256 stakedZombieCount = 0;
        for (uint256 i = 0; i < currentZombieCount; i++) {
            if (node.stakers(zombieAddress(i))) {
                stakedZombieCount++;
            }
        }
        return stakedZombieCount;
    }

    /**
     * @notice Verify that there are some number of nodes still unresolved
     */
    function requireUnresolvedExists() public view override {
        uint256 firstUnresolved = firstUnresolvedNode();
        require(
            firstUnresolved > latestConfirmed() && firstUnresolved <= latestNodeCreated(),
            "NO_UNRESOLVED"
        );
    }

    function requireUnresolved(uint256 nodeNum) public view override {
        require(nodeNum >= firstUnresolvedNode(), "ALREADY_DECIDED");
        require(nodeNum <= latestNodeCreated(), "DOESNT_EXIST");
    }

    /**
     * @notice Verify that the given address is staked and not actively in a challenge
     * @param stakerAddress Address to check
     */
    function requireUnchallengedStaker(address stakerAddress) private view {
        require(isStaked(stakerAddress), "NOT_STAKED");
        require(currentChallenge(stakerAddress) == address(0), "IN_CHAL");
    }

    function isNitroReady() external pure returns (uint256) {
        return NitroReadyMagicNums.ROLLUP_USER;
    }

    function withdrawStakerFunds(address payable destination) external virtual returns (uint256);
}

contract RollupUserFacet is AbsRollupUserFacet {
    function initialize(address _stakeToken) public override {
        require(_stakeToken == address(0), "NO_TOKEN_ALLOWED");
        // stakeToken = _stakeToken;
    }

    /**
     * @notice Create a new stake
     * @dev It is recomended to call stakeOnExistingNode after creating a new stake
     * so that a griefer doesn't remove your stake by immediately calling returnOldDeposit
     */
    function newStake() external payable onlyValidator whenNotPaused {
        _newStake(msg.value);
    }

    /**
     * @notice Increase the amount staked eth for the given staker
     * @param stakerAddress Address of the staker whose stake is increased
     */
    function addToDeposit(address stakerAddress) external payable onlyValidator whenNotPaused {
        _addToDeposit(stakerAddress, msg.value);
    }

    /**
     * @notice Withdraw uncomitted funds owned by sender from the rollup chain
     * @param destination Address to transfer the withdrawn funds to
     */
    function withdrawStakerFunds(address payable destination)
        external
        override
        onlyValidator
        whenInShutdownModeOrNotPaused
        returns (uint256)
    {
        uint256 amount = withdrawFunds(msg.sender);
        // This is safe because it occurs after all checks and effects
        destination.transfer(amount);
        return amount;
    }
}

contract ERC20RollupUserFacet is AbsRollupUserFacet {
    function initialize(address _stakeToken) public override {
        require(_stakeToken != address(0), "NEED_STAKE_TOKEN");
        require(stakeToken == address(0), "ALREADY_INIT");
        stakeToken = _stakeToken;
    }

    /**
     * @notice Create a new stake
     * @dev It is recomended to call stakeOnExistingNode after creating a new stake
     * so that a griefer doesn't remove your stake by immediately calling returnOldDeposit
     * @param tokenAmount the amount of tokens staked
     */
    function newStake(uint256 tokenAmount) external onlyValidator whenNotPaused {
        _newStake(tokenAmount);
        require(
            IERC20(stakeToken).transferFrom(msg.sender, address(this), tokenAmount),
            "TRANSFER_FAIL"
        );
    }

    /**
     * @notice Increase the amount staked tokens for the given staker
     * @param stakerAddress Address of the staker whose stake is increased
     * @param tokenAmount the amount of tokens staked
     */
    function addToDeposit(address stakerAddress, uint256 tokenAmount)
        external
        onlyValidator
        whenNotPaused
    {
        _addToDeposit(stakerAddress, tokenAmount);
        require(
            IERC20(stakeToken).transferFrom(msg.sender, address(this), tokenAmount),
            "TRANSFER_FAIL"
        );
    }

    /**
     * @notice Withdraw uncomitted funds owned by sender from the rollup chain
     * @param destination Address to transfer the withdrawn funds to
     */
    function withdrawStakerFunds(address payable destination)
        external
        override
        onlyValidator
        whenInShutdownModeOrNotPaused
        returns (uint256)
    {
        uint256 amount = withdrawFunds(msg.sender);
        // This is safe because it occurs after all checks and effects
        require(IERC20(stakeToken).transfer(destination, amount), "TRANSFER_FAILED");
        return amount;
    }
}

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

import "@openzeppelin/contracts/utils/Pausable.sol";
import "@openzeppelin/contracts/proxy/Proxy.sol";
import "@openzeppelin/contracts/utils/Address.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";

import "./RollupEventBridge.sol";
import "./RollupCore.sol";
import "./RollupLib.sol";
import "./INode.sol";
import "./INodeFactory.sol";

import "../challenge/IChallenge.sol";
import "../challenge/IChallengeFactory.sol";

import "../bridge/interfaces/IBridge.sol";
import "../bridge/interfaces/IOutbox.sol";
import "../bridge/Messages.sol";

import "../libraries/ProxyUtil.sol";
import "../libraries/Cloneable.sol";
import "./facets/IRollupFacets.sol";

abstract contract RollupBase is Cloneable, RollupCore, Pausable {
    // Rollup Config
    uint256 public confirmPeriodBlocks;
    uint256 public extraChallengeTimeBlocks;
    uint256 public avmGasSpeedLimitPerBlock;
    uint256 public baseStake;

    // Bridge is an IInbox and IOutbox
    IBridge public delayedBridge;
    ISequencerInbox public sequencerBridge;
    IOutbox public outbox;
    RollupEventBridge public rollupEventBridge;
    IChallengeFactory public challengeFactory;
    INodeFactory public nodeFactory;
    address public owner;
    address public stakeToken;
    uint256 public minimumAssertionPeriod;

    uint256 public STORAGE_GAP_1;
    uint256 public STORAGE_GAP_2;
    uint256 public challengeExecutionBisectionDegree;

    address[] internal facets;

    mapping(address => bool) isValidator;

    /// @dev indicates the block which the rollup starts the shutdown for nitro mode
    uint256 public shutdownForNitroBlock;

    /// @dev indicates if rollup is in shutdown for nitro mode
    function shutdownForNitroMode() public view returns (bool) {
        return block.number >= shutdownForNitroBlock;
    }

    /// @dev allows a function to be executed either if contract is either in `shutdownForNitroMode` or not paused
    modifier whenInShutdownModeOrNotPaused() {
        if (!shutdownForNitroMode()) {
            require(!paused(), "Pausable: paused");
        }
        _;
    }

    /// @notice DEPRECATED -- this method is deprecated but still mantained for backward compatibility
    /// @dev this actually returns the avmGasSpeedLimitPerBlock
    /// @return this actually returns the avmGasSpeedLimitPerBlock
    function arbGasSpeedLimitPerBlock() external view returns (uint256) {
        return avmGasSpeedLimitPerBlock;
    }
}

contract Rollup is Proxy, RollupBase {
    using Address for address;

    constructor(uint256 _confirmPeriodBlocks) public Cloneable() Pausable() {
        // constructor is used so logic contract can't be init'ed
        confirmPeriodBlocks = _confirmPeriodBlocks;
        require(isInit(), "CONSTRUCTOR_NOT_INIT");
    }

    function isInit() internal view returns (bool) {
        return confirmPeriodBlocks != 0;
    }

    // _rollupParams = [ confirmPeriodBlocks, extraChallengeTimeBlocks, avmGasSpeedLimitPerBlock, baseStake ]
    // connectedContracts = [delayedBridge, sequencerInbox, outbox, rollupEventBridge, challengeFactory, nodeFactory]
    function initialize(
        bytes32 _machineHash,
        uint256[4] calldata _rollupParams,
        address _stakeToken,
        address _owner,
        bytes calldata _extraConfig,
        address[6] calldata connectedContracts,
        address[2] calldata _facets,
        uint256[2] calldata sequencerInboxParams
    ) public {
        require(!isInit(), "ALREADY_INIT");

        // calls initialize method in user facet
        require(_facets[0].isContract(), "FACET_0_NOT_CONTRACT");
        require(_facets[1].isContract(), "FACET_1_NOT_CONTRACT");
        (bool success, ) = _facets[1].delegatecall(
            abi.encodeWithSelector(IRollupUser.initialize.selector, _stakeToken)
        );
        require(success, "FAIL_INIT_FACET");

        delayedBridge = IBridge(connectedContracts[0]);
        sequencerBridge = ISequencerInbox(connectedContracts[1]);
        outbox = IOutbox(connectedContracts[2]);
        delayedBridge.setOutbox(connectedContracts[2], true);
        rollupEventBridge = RollupEventBridge(connectedContracts[3]);
        delayedBridge.setInbox(connectedContracts[3], true);

        rollupEventBridge.rollupInitialized(
            _rollupParams[0],
            _rollupParams[2],
            _owner,
            _extraConfig
        );

        challengeFactory = IChallengeFactory(connectedContracts[4]);
        nodeFactory = INodeFactory(connectedContracts[5]);

        INode node = createInitialNode(_machineHash);
        initializeCore(node);

        confirmPeriodBlocks = _rollupParams[0];
        extraChallengeTimeBlocks = _rollupParams[1];
        avmGasSpeedLimitPerBlock = _rollupParams[2];
        baseStake = _rollupParams[3];
        owner = _owner;
        // A little over 15 minutes
        minimumAssertionPeriod = 75;
        challengeExecutionBisectionDegree = 400;

        sequencerBridge.setMaxDelay(sequencerInboxParams[0], sequencerInboxParams[1]);

        // facets[0] == admin, facets[1] == user
        facets = _facets;

        shutdownForNitroBlock = type(uint256).max;

        emit RollupCreated(_machineHash);
        require(isInit(), "INITIALIZE_NOT_INIT");
    }

    function postUpgradeInit() external {
        // it is assumed the rollup contract is behind a Proxy controlled by a proxy admin
        // this function can only be called by the proxy admin contract
        address proxyAdmin = ProxyUtil.getProxyAdmin();
        require(msg.sender == proxyAdmin, "NOT_FROM_ADMIN");

        shutdownForNitroBlock = type(uint256).max;
    }

    function createInitialNode(bytes32 _machineHash) private returns (INode) {
        bytes32 state = RollupLib.stateHash(
            RollupLib.ExecutionState(
                0, // total gas used
                _machineHash,
                0, // inbox count
                0, // send count
                0, // log count
                0, // send acc
                0, // log acc
                block.number, // block proposed
                1 // Initialization message already in inbox
            )
        );
        return
            INode(
                nodeFactory.createNode(
                    state,
                    0, // challenge hash (not challengeable)
                    0, // confirm data
                    0, // prev node
                    block.number // deadline block (not challengeable)
                )
            );
    }

    /**
     * This contract uses a dispatch pattern from EIP-2535: Diamonds
     * together with Open Zeppelin's proxy
     */

    function getFacets() external view returns (address, address) {
        return (getAdminFacet(), getUserFacet());
    }

    function getAdminFacet() public view returns (address) {
        return facets[0];
    }

    function getUserFacet() public view returns (address) {
        return facets[1];
    }

    /**
     * @dev This is a virtual function that should be overriden so it returns the address to which the fallback function
     * and {_fallback} should delegate.
     */
    function _implementation() internal view virtual override returns (address) {
        require(msg.data.length >= 4, "NO_FUNC_SIG");
        address rollupOwner = owner;
        // if there is an owner and it is the sender, delegate to admin facet
        address target = rollupOwner != address(0) && rollupOwner == msg.sender
            ? getAdminFacet()
            : getUserFacet();
        require(target.isContract(), "TARGET_NOT_CONTRACT");
        return target;
    }
}

File 3 of 34 : IRollupFacets.sol
// 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.
 */

// solhint-disable-next-line compiler-version
pragma solidity >=0.6.9 <0.9.0;

import "../INode.sol";
import "../../bridge/interfaces/IOutbox.sol";

interface IRollupUser {
    function initialize(address _stakeToken) external;

    function completeChallenge(address winningStaker, address losingStaker) external;

    function returnOldDeposit(address stakerAddress) external;

    function requireUnresolved(uint256 nodeNum) external view;

    function requireUnresolvedExists() external view;

    function countStakedZombies(INode node) external view returns (uint256);
}

interface IRollupAdmin {
    event OwnerFunctionCalled(uint256 indexed id);

    /**
     * @notice Add a contract authorized to put messages into this rollup's inbox
     * @param _outbox Outbox contract to add
     */
    function setOutbox(IOutbox _outbox) external;

    /**
     * @notice Disable an old outbox from interacting with the bridge
     * @param _outbox Outbox contract to remove
     */
    function removeOldOutbox(address _outbox) external;

    /**
     * @notice Enable or disable an inbox contract
     * @param _inbox Inbox contract to add or remove
     * @param _enabled New status of inbox
     */
    function setInbox(address _inbox, bool _enabled) external;

    /**
     * @notice Pause interaction with the rollup contract
     */
    function pause() external;

    /**
     * @notice Resume interaction with the rollup contract
     */
    function resume() external;

    /**
     * @notice Set the addresses of rollup logic facets called
     * @param newAdminFacet address of logic that owner of rollup calls
     * @param newUserFacet ddress of logic that user of rollup calls
     */
    function setFacets(address newAdminFacet, address newUserFacet) external;

    /**
     * @notice Set the addresses of the validator whitelist
     * @dev It is expected that both arrays are same length, and validator at
     * position i corresponds to the value at position i
     * @param _validator addresses to set in the whitelist
     * @param _val value to set in the whitelist for corresponding address
     */
    function setValidator(address[] memory _validator, bool[] memory _val) external;

    /**
     * @notice Set a new owner address for the rollup
     * @param newOwner address of new rollup owner
     */
    function setOwner(address newOwner) external;

    /**
     * @notice Set minimum assertion period for the rollup
     * @param newPeriod new minimum period for assertions
     */
    function setMinimumAssertionPeriod(uint256 newPeriod) external;

    /**
     * @notice Set number of blocks until a node is considered confirmed
     * @param newConfirmPeriod new number of blocks until a node is confirmed
     */
    function setConfirmPeriodBlocks(uint256 newConfirmPeriod) external;

    /**
     * @notice Set number of extra blocks after a challenge
     * @param newExtraTimeBlocks new number of blocks
     */
    function setExtraChallengeTimeBlocks(uint256 newExtraTimeBlocks) external;

    /**
     * @notice Set speed limit per block
     * @param newAvmGasSpeedLimitPerBlock maximum avmgas to be used per block
     */
    function setAvmGasSpeedLimitPerBlock(uint256 newAvmGasSpeedLimitPerBlock) external;

    /**
     * @notice Set base stake required for an assertion
     * @param newBaseStake maximum avmgas to be used per block
     */
    function setBaseStake(uint256 newBaseStake) external;

    /**
     * @notice Set the token used for stake, where address(0) == eth
     * @dev Before changing the base stake token, you might need to change the
     * implementation of the Rollup User facet!
     * @param newStakeToken address of token used for staking
     */
    function setStakeToken(address newStakeToken) external;

    /**
     * @notice Set max delay for sequencer inbox
     * @param newSequencerInboxMaxDelayBlocks max number of blocks
     * @param newSequencerInboxMaxDelaySeconds max number of seconds
     */
    function setSequencerInboxMaxDelay(
        uint256 newSequencerInboxMaxDelayBlocks,
        uint256 newSequencerInboxMaxDelaySeconds
    ) external;

    /**
     * @notice Set execution bisection degree
     * @param newChallengeExecutionBisectionDegree execution bisection degree
     */
    function setChallengeExecutionBisectionDegree(uint256 newChallengeExecutionBisectionDegree)
        external;

    /**
     * @notice Updates a whitelist address for its consumers
     * @dev setting the newWhitelist to address(0) disables it for consumers
     * @param whitelist old whitelist to be deprecated
     * @param newWhitelist new whitelist to be used
     * @param targets whitelist consumers to be triggered
     */
    function updateWhitelistConsumers(
        address whitelist,
        address newWhitelist,
        address[] memory targets
    ) external;

    /**
     * @notice Updates a whitelist's entries
     * @dev user at position i will be assigned value i
     * @param whitelist whitelist to be updated
     * @param user users to be updated in the whitelist
     * @param val if user is or not allowed in the whitelist
     */
    function setWhitelistEntries(
        address whitelist,
        address[] memory user,
        bool[] memory val
    ) external;

    /**
     * @notice Updates whether an address is a sequencer at the sequencer inbox
     * @param newSequencer address to be modified
     * @param isSequencer whether this address should be authorized as a sequencer
     */
    function setIsSequencer(address newSequencer, bool isSequencer) external;

    /**
     * @notice Upgrades the implementation of a beacon controlled by the rollup
     * @param beacon address of beacon to be upgraded
     * @param newImplementation new address of implementation
     */
    function upgradeBeacon(address beacon, address newImplementation) external;

    function forceResolveChallenge(address[] memory stackerA, address[] memory stackerB) external;

    function forceRefundStaker(address[] memory stacker) external;

    function forceCreateNode(
        bytes32 expectedNodeHash,
        bytes32[3][2] calldata assertionBytes32Fields,
        uint256[4][2] calldata assertionIntFields,
        bytes calldata sequencerBatchProof,
        uint256 beforeProposedBlock,
        uint256 beforeInboxMaxCount,
        uint256 prevNode
    ) external;

    function forceConfirmNode(
        uint256 nodeNum,
        bytes32 beforeSendAcc,
        bytes calldata sendsData,
        uint256[] calldata sendLengths,
        uint256 afterSendCount,
        bytes32 afterLogAcc,
        uint256 afterLogCount
    ) external;
}

interface INitroRollupCore {
    function inbox() external view returns (address);

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

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

pragma experimental ABIEncoderV2;

import "./interfaces/IInbox.sol";
import "@arbitrum/nitro-contracts/src/bridge/IBridge.sol" as INitroBridge;
import "@arbitrum/nitro-contracts/src/bridge/IInbox.sol" as INitroInbox;

interface INitroRollup {
    struct GlobalState {
        bytes32[2] bytes32Vals;
        uint64[2] u64Vals;
    }

    enum MachineStatus {
        RUNNING,
        FINISHED,
        ERRORED,
        TOO_FAR
    }

    struct ExecutionState {
        GlobalState globalState;
        MachineStatus machineStatus;
    }
    struct NitroRollupAssertion {
        ExecutionState beforeState;
        ExecutionState afterState;
        uint64 numBlocks;
    }

    function bridge() external view returns (INitroBridge.IBridge);

    function inbox() external view returns (INitroInbox.IInbox);

    function setInbox(IInbox newInbox) external;

    function setOwner(address newOwner) external;

    function paused() external view returns (bool);

    function pause() external;

    function resume() external;

    function latestNodeCreated() external returns (uint64);

    function createNitroMigrationGenesis(NitroRollupAssertion calldata assertion) external;
}

interface IArbOwner {
    function addChainOwner(address newOwner) external;
}

/// @dev lib used since file level consts aren't available in this solc version
library NitroReadyMagicNums {
    uint256 constant ROLLUP_USER = 0xa4b1;
    uint256 constant ROLLUP_ADMIN = 0xa4b2;
    uint256 constant NODE_BEACON = 0xa4b3;
    uint256 constant OUTBOX = 0xa4b4;
    uint256 constant BRIDGE = 0xa4b5;
    uint256 constant DELAYED_INBOX = 0xa4b6;
    uint256 constant SEQ_INBOX = 0xa4b7;
}

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

import "./Context.sol";

/**
 * @dev Contract module which allows children to implement an emergency stop
 * mechanism that can be triggered by an authorized account.
 *
 * This module is used through inheritance. It will make available the
 * modifiers `whenNotPaused` and `whenPaused`, which can be applied to
 * the functions of your contract. Note that they will not be pausable by
 * simply including this module, only once the modifiers are put in place.
 */
abstract contract Pausable is Context {
    /**
     * @dev Emitted when the pause is triggered by `account`.
     */
    event Paused(address account);

    /**
     * @dev Emitted when the pause is lifted by `account`.
     */
    event Unpaused(address account);

    bool private _paused;

    /**
     * @dev Initializes the contract in unpaused state.
     */
    constructor () internal {
        _paused = false;
    }

    /**
     * @dev Returns true if the contract is paused, and false otherwise.
     */
    function paused() public view virtual returns (bool) {
        return _paused;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is not paused.
     *
     * Requirements:
     *
     * - The contract must not be paused.
     */
    modifier whenNotPaused() {
        require(!paused(), "Pausable: paused");
        _;
    }

    /**
     * @dev Modifier to make a function callable only when the contract is paused.
     *
     * Requirements:
     *
     * - The contract must be paused.
     */
    modifier whenPaused() {
        require(paused(), "Pausable: not paused");
        _;
    }

    /**
     * @dev Triggers stopped state.
     *
     * Requirements:
     *
     * - The contract must not be paused.
     */
    function _pause() internal virtual whenNotPaused {
        _paused = true;
        emit Paused(_msgSender());
    }

    /**
     * @dev Returns to normal state.
     *
     * Requirements:
     *
     * - The contract must be paused.
     */
    function _unpause() internal virtual whenPaused {
        _paused = false;
        emit Unpaused(_msgSender());
    }
}

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

/**
 * @dev This abstract contract provides a fallback function that delegates all calls to another contract using the EVM
 * instruction `delegatecall`. We refer to the second contract as the _implementation_ behind the proxy, and it has to
 * be specified by overriding the virtual {_implementation} function.
 *
 * Additionally, delegation to the implementation can be triggered manually through the {_fallback} function, or to a
 * different contract through the {_delegate} function.
 *
 * The success and return data of the delegated call will be returned back to the caller of the proxy.
 */
abstract contract Proxy {
    /**
     * @dev Delegates the current call to `implementation`.
     *
     * This function does not return to its internall call site, it will return directly to the external caller.
     */
    function _delegate(address implementation) internal virtual {
        // solhint-disable-next-line no-inline-assembly
        assembly {
            // Copy msg.data. We take full control of memory in this inline assembly
            // block because it will not return to Solidity code. We overwrite the
            // Solidity scratch pad at memory position 0.
            calldatacopy(0, 0, calldatasize())

            // Call the implementation.
            // out and outsize are 0 because we don't know the size yet.
            let result := delegatecall(gas(), implementation, 0, calldatasize(), 0, 0)

            // Copy the returned data.
            returndatacopy(0, 0, returndatasize())

            switch result
            // delegatecall returns 0 on error.
            case 0 { revert(0, returndatasize()) }
            default { return(0, returndatasize()) }
        }
    }

    /**
     * @dev This is a virtual function that should be overriden so it returns the address to which the fallback function
     * and {_fallback} should delegate.
     */
    function _implementation() internal view virtual returns (address);

    /**
     * @dev Delegates the current call to the address returned by `_implementation()`.
     *
     * This function does not return to its internall call site, it will return directly to the external caller.
     */
    function _fallback() internal virtual {
        _beforeFallback();
        _delegate(_implementation());
    }

    /**
     * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if no other
     * function in the contract matches the call data.
     */
    fallback () external payable virtual {
        _fallback();
    }

    /**
     * @dev Fallback function that delegates calls to the address returned by `_implementation()`. Will run if call data
     * is empty.
     */
    receive () external payable virtual {
        _fallback();
    }

    /**
     * @dev Hook that is called before falling back to the implementation. Can happen as part of a manual `_fallback`
     * call, or as part of the Solidity `fallback` or `receive` functions.
     *
     * If overriden should call `super._beforeFallback()`.
     */
    function _beforeFallback() internal virtual {
    }
}

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.2 <0.8.0;

/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * [IMPORTANT]
     * ====
     * It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     *
     * Among others, `isContract` will return false for the following
     * types of addresses:
     *
     *  - an externally-owned account
     *  - a contract in construction
     *  - an address where a contract will be created
     *  - an address where a contract lived, but was destroyed
     * ====
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies on extcodesize, which returns 0 for contracts in
        // construction, since the code is only stored at the end of the
        // constructor execution.

        uint256 size;
        // solhint-disable-next-line no-inline-assembly
        assembly { size := extcodesize(account) }
        return size > 0;
    }

    /**
     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
     * `recipient`, forwarding all available gas and reverting on errors.
     *
     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
     * of certain opcodes, possibly making contracts go over the 2300 gas limit
     * imposed by `transfer`, making them unable to receive funds via
     * `transfer`. {sendValue} removes this limitation.
     *
     * https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
     *
     * IMPORTANT: because control is transferred to `recipient`, care must be
     * taken to not create reentrancy vulnerabilities. Consider using
     * {ReentrancyGuard} or the
     * https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        require(address(this).balance >= amount, "Address: insufficient balance");

        // solhint-disable-next-line avoid-low-level-calls, avoid-call-value
        (bool success, ) = recipient.call{ value: amount }("");
        require(success, "Address: unable to send value, recipient may have reverted");
    }

    /**
     * @dev Performs a Solidity function call using a low level `call`. A
     * plain`call` is an unsafe replacement for a function call: use this
     * function instead.
     *
     * If `target` reverts with a revert reason, it is bubbled up by this
     * function (like regular Solidity function calls).
     *
     * Returns the raw returned data. To convert to the expected return value,
     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
     *
     * Requirements:
     *
     * - `target` must be a contract.
     * - calling `target` with `data` must not revert.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
      return functionCall(target, data, "Address: low-level call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
     * `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but also transferring `value` wei to `target`.
     *
     * Requirements:
     *
     * - the calling contract must have an ETH balance of at least `value`.
     * - the called Solidity function must be `payable`.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
        return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
    }

    /**
     * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
     * with `errorMessage` as a fallback revert reason when `target` reverts.
     *
     * _Available since v3.1._
     */
    function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) {
        require(address(this).balance >= value, "Address: insufficient balance for call");
        require(isContract(target), "Address: call to non-contract");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.call{ value: value }(data);
        return _verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
        return functionStaticCall(target, data, "Address: low-level static call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a static call.
     *
     * _Available since v3.3._
     */
    function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) {
        require(isContract(target), "Address: static call to non-contract");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.staticcall(data);
        return _verifyCallResult(success, returndata, errorMessage);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionDelegateCall(target, data, "Address: low-level delegate call failed");
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
     * but performing a delegate call.
     *
     * _Available since v3.4._
     */
    function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
        require(isContract(target), "Address: delegate call to non-contract");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = target.delegatecall(data);
        return _verifyCallResult(success, returndata, errorMessage);
    }

    function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {
        if (success) {
            return returndata;
        } else {
            // Look for revert reason and bubble it up if present
            if (returndata.length > 0) {
                // The easiest way to bubble the revert reason is using memory via assembly

                // solhint-disable-next-line no-inline-assembly
                assembly {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert(errorMessage);
            }
        }
    }
}

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

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

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

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

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

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

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

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

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

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

import "./Rollup.sol";
import "./facets/IRollupFacets.sol";

import "../bridge/interfaces/IBridge.sol";
import "../bridge/interfaces/IMessageProvider.sol";
import "./INode.sol";
import "../libraries/Cloneable.sol";

contract RollupEventBridge is IMessageProvider, Cloneable {
    uint8 internal constant INITIALIZATION_MSG_TYPE = 11;
    uint8 internal constant ROLLUP_PROTOCOL_EVENT_TYPE = 8;

    uint8 internal constant CREATE_NODE_EVENT = 0;
    uint8 internal constant CONFIRM_NODE_EVENT = 1;
    uint8 internal constant REJECT_NODE_EVENT = 2;
    uint8 internal constant STAKE_CREATED_EVENT = 3;

    IBridge bridge;
    address rollup;

    modifier onlyRollup() {
        require(msg.sender == rollup, "ONLY_ROLLUP");
        _;
    }

    function initialize(address _bridge, address _rollup) external {
        require(rollup == address(0), "ALREADY_INIT");
        bridge = IBridge(_bridge);
        rollup = _rollup;
    }

    function rollupInitialized(
        uint256 confirmPeriodBlocks,
        uint256 avmGasSpeedLimitPerBlock,
        address owner,
        bytes calldata extraConfig
    ) external onlyRollup {
        bytes memory initMsg = abi.encodePacked(
            keccak256("ChallengePeriodEthBlocks"),
            confirmPeriodBlocks,
            keccak256("SpeedLimitPerSecond"),
            avmGasSpeedLimitPerBlock / 100, // convert avm gas to arbgas
            keccak256("ChainOwner"),
            uint256(uint160(bytes20(owner))),
            extraConfig
        );
        uint256 num = bridge.deliverMessageToInbox(
            INITIALIZATION_MSG_TYPE,
            address(0),
            keccak256(initMsg)
        );
        emit InboxMessageDelivered(num, initMsg);
    }

    function nodeCreated(
        uint256 nodeNum,
        uint256 prev,
        uint256 deadline,
        address asserter
    ) external onlyRollup {
        deliverToBridge(
            abi.encodePacked(
                CREATE_NODE_EVENT,
                nodeNum,
                prev,
                block.number,
                deadline,
                uint256(uint160(bytes20(asserter)))
            )
        );
    }

    function nodeConfirmed(uint256 nodeNum) external onlyRollup {
        deliverToBridge(abi.encodePacked(CONFIRM_NODE_EVENT, nodeNum));
    }

    function nodeRejected(uint256 nodeNum) external onlyRollup {
        deliverToBridge(abi.encodePacked(REJECT_NODE_EVENT, nodeNum));
    }

    function stakeCreated(address staker, uint256 nodeNum) external onlyRollup {
        deliverToBridge(
            abi.encodePacked(
                STAKE_CREATED_EVENT,
                uint256(uint160(bytes20(staker))),
                nodeNum,
                block.number
            )
        );
    }

    function deliverToBridge(bytes memory message) private {
        emit InboxMessageDelivered(
            bridge.deliverMessageToInbox(
                ROLLUP_PROTOCOL_EVENT_TYPE,
                msg.sender,
                keccak256(message)
            ),
            message
        );
    }
}

File 10 of 34 : RollupCore.sol
// 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;

import "./INode.sol";
import "./IRollupCore.sol";
import "./RollupLib.sol";
import "./INodeFactory.sol";
import "./RollupEventBridge.sol";
import "../bridge/interfaces/ISequencerInbox.sol";

import "@openzeppelin/contracts/math/SafeMath.sol";

contract RollupCore is IRollupCore {
    using SafeMath for uint256;

    // Stakers become Zombies after losing a challenge
    struct Zombie {
        address stakerAddress;
        uint256 latestStakedNode;
    }

    struct Staker {
        uint256 index;
        uint256 latestStakedNode;
        uint256 amountStaked;
        // currentChallenge is 0 if staker is not in a challenge
        address currentChallenge;
        bool isStaked;
    }

    uint256 private _latestConfirmed;
    uint256 private _firstUnresolvedNode;
    uint256 private _latestNodeCreated;
    uint256 private _lastStakeBlock;
    mapping(uint256 => INode) private _nodes;
    mapping(uint256 => bytes32) private _nodeHashes;

    address payable[] private _stakerList;
    mapping(address => Staker) public override _stakerMap;

    Zombie[] private _zombies;

    mapping(address => uint256) private _withdrawableFunds;

    /**
     * @notice Get the address of the Node contract for the given node
     * @param nodeNum Index of the node
     * @return Address of the Node contract
     */
    function getNode(uint256 nodeNum) public view override returns (INode) {
        return _nodes[nodeNum];
    }

    /**
     * @notice Get the address of the staker at the given index
     * @param stakerNum Index of the staker
     * @return Address of the staker
     */
    function getStakerAddress(uint256 stakerNum) public view override returns (address) {
        return _stakerList[stakerNum];
    }

    /**
     * @notice Check whether the given staker is staked
     * @param staker Staker address to check
     * @return True or False for whether the staker was staked
     */
    function isStaked(address staker) public view override returns (bool) {
        return _stakerMap[staker].isStaked;
    }

    /**
     * @notice Get the latest staked node of the given staker
     * @param staker Staker address to lookup
     * @return Latest node staked of the staker
     */
    function latestStakedNode(address staker) public view override returns (uint256) {
        return _stakerMap[staker].latestStakedNode;
    }

    /**
     * @notice Get the current challenge of the given staker
     * @param staker Staker address to lookup
     * @return Current challenge of the staker
     */
    function currentChallenge(address staker) public view override returns (address) {
        return _stakerMap[staker].currentChallenge;
    }

    /**
     * @notice Get the amount staked of the given staker
     * @param staker Staker address to lookup
     * @return Amount staked of the staker
     */
    function amountStaked(address staker) public view override returns (uint256) {
        return _stakerMap[staker].amountStaked;
    }

    /**
     * @notice Get the original staker address of the zombie at the given index
     * @param zombieNum Index of the zombie to lookup
     * @return Original staker address of the zombie
     */
    function zombieAddress(uint256 zombieNum) public view override returns (address) {
        return _zombies[zombieNum].stakerAddress;
    }

    /**
     * @notice Get Latest node that the given zombie at the given index is staked on
     * @param zombieNum Index of the zombie to lookup
     * @return Latest node that the given zombie is staked on
     */
    function zombieLatestStakedNode(uint256 zombieNum) public view override returns (uint256) {
        return _zombies[zombieNum].latestStakedNode;
    }

    /// @return Current number of un-removed zombies
    function zombieCount() public view override returns (uint256) {
        return _zombies.length;
    }

    function isZombie(address staker) public view override returns (bool) {
        for (uint256 i = 0; i < _zombies.length; i++) {
            if (staker == _zombies[i].stakerAddress) {
                return true;
            }
        }
        return false;
    }

    /**
     * @notice Get the amount of funds withdrawable by the given address
     * @param owner Address to check the funds of
     * @return Amount of funds withdrawable by owner
     */
    function withdrawableFunds(address owner) external view override returns (uint256) {
        return _withdrawableFunds[owner];
    }

    /**
     * @return Index of the first unresolved node
     * @dev If all nodes have been resolved, this will be latestNodeCreated + 1
     */
    function firstUnresolvedNode() public view override returns (uint256) {
        return _firstUnresolvedNode;
    }

    /// @return Index of the latest confirmed node
    function latestConfirmed() public view override returns (uint256) {
        return _latestConfirmed;
    }

    /// @return Index of the latest rollup node created
    function latestNodeCreated() public view override returns (uint256) {
        return _latestNodeCreated;
    }

    /// @return Ethereum block that the most recent stake was created
    function lastStakeBlock() external view override returns (uint256) {
        return _lastStakeBlock;
    }

    /// @return Number of active stakers currently staked
    function stakerCount() public view override returns (uint256) {
        return _stakerList.length;
    }

    /**
     * @notice Initialize the core with an initial node
     * @param initialNode Initial node to start the chain with
     */
    function initializeCore(INode initialNode) internal {
        _nodes[0] = initialNode;
        _firstUnresolvedNode = 1;
    }

    /**
     * @notice React to a new node being created by storing it an incrementing the latest node counter
     * @param node Node that was newly created
     * @param nodeHash The hash of said node
     */
    function nodeCreated(INode node, bytes32 nodeHash) internal {
        _latestNodeCreated++;
        _nodes[_latestNodeCreated] = node;
        _nodeHashes[_latestNodeCreated] = nodeHash;
    }

    /// @return Node hash as of this node number
    function getNodeHash(uint256 index) public view override returns (bytes32) {
        return _nodeHashes[index];
    }

    /// @notice Reject the next unresolved node
    function _rejectNextNode() internal {
        destroyNode(_firstUnresolvedNode);
        _firstUnresolvedNode++;
    }

    /// @notice Confirm the next unresolved node
    function confirmNextNode(
        bytes32 beforeSendAcc,
        bytes calldata sendsData,
        uint256[] calldata sendLengths,
        uint256 afterSendCount,
        bytes32 afterLogAcc,
        uint256 afterLogCount,
        IOutbox outbox,
        RollupEventBridge rollupEventBridge
    ) internal {
        confirmNode(
            _firstUnresolvedNode,
            beforeSendAcc,
            sendsData,
            sendLengths,
            afterSendCount,
            afterLogAcc,
            afterLogCount,
            outbox,
            rollupEventBridge
        );
    }

    function confirmNode(
        uint256 nodeNum,
        bytes32 beforeSendAcc,
        bytes calldata sendsData,
        uint256[] calldata sendLengths,
        uint256 afterSendCount,
        bytes32 afterLogAcc,
        uint256 afterLogCount,
        IOutbox outbox,
        RollupEventBridge rollupEventBridge
    ) internal {
        bytes32 afterSendAcc = RollupLib.feedAccumulator(sendsData, sendLengths, beforeSendAcc);

        INode node = getNode(nodeNum);
        // Authenticate data against node's confirm data pre-image
        require(
            node.confirmData() ==
                RollupLib.confirmHash(
                    beforeSendAcc,
                    afterSendAcc,
                    afterLogAcc,
                    afterSendCount,
                    afterLogCount
                ),
            "CONFIRM_DATA"
        );

        // trusted external call to outbox
        outbox.processOutgoingMessages(sendsData, sendLengths);

        destroyNode(_latestConfirmed);
        _latestConfirmed = nodeNum;
        _firstUnresolvedNode = nodeNum + 1;

        rollupEventBridge.nodeConfirmed(nodeNum);
        emit NodeConfirmed(nodeNum, afterSendAcc, afterSendCount, afterLogAcc, afterLogCount);
    }

    /**
     * @notice Create a new stake at latest confirmed node
     * @param stakerAddress Address of the new staker
     * @param depositAmount Stake amount of the new staker
     */
    function createNewStake(address payable stakerAddress, uint256 depositAmount) internal {
        uint256 stakerIndex = _stakerList.length;
        _stakerList.push(stakerAddress);
        _stakerMap[stakerAddress] = Staker(
            stakerIndex,
            _latestConfirmed,
            depositAmount,
            address(0), // new staker is not in challenge
            true
        );
        _lastStakeBlock = block.number;
        emit UserStakeUpdated(stakerAddress, 0, depositAmount);
    }

    /**
     * @notice Check to see whether the two stakers are in the same challenge
     * @param stakerAddress1 Address of the first staker
     * @param stakerAddress2 Address of the second staker
     * @return Address of the challenge that the two stakers are in
     */
    function inChallenge(address stakerAddress1, address stakerAddress2)
        internal
        view
        returns (address)
    {
        Staker storage staker1 = _stakerMap[stakerAddress1];
        Staker storage staker2 = _stakerMap[stakerAddress2];
        address challenge = staker1.currentChallenge;
        require(challenge != address(0), "NO_CHAL");
        require(challenge == staker2.currentChallenge, "DIFF_IN_CHAL");
        return challenge;
    }

    /**
     * @notice Make the given staker as not being in a challenge
     * @param stakerAddress Address of the staker to remove from a challenge
     */
    function clearChallenge(address stakerAddress) internal {
        Staker storage staker = _stakerMap[stakerAddress];
        staker.currentChallenge = address(0);
    }

    /**
     * @notice Mark both the given stakers as engaged in the challenge
     * @param staker1 Address of the first staker
     * @param staker2 Address of the second staker
     * @param challenge Address of the challenge both stakers are now in
     */
    function challengeStarted(
        address staker1,
        address staker2,
        address challenge
    ) internal {
        _stakerMap[staker1].currentChallenge = challenge;
        _stakerMap[staker2].currentChallenge = challenge;
    }

    /**
     * @notice Add to the stake of the given staker by the given amount
     * @param stakerAddress Address of the staker to increase the stake of
     * @param amountAdded Amount of stake to add to the staker
     */
    function increaseStakeBy(address stakerAddress, uint256 amountAdded) internal {
        Staker storage staker = _stakerMap[stakerAddress];
        uint256 initialStaked = staker.amountStaked;
        uint256 finalStaked = initialStaked.add(amountAdded);
        staker.amountStaked = finalStaked;
        emit UserStakeUpdated(stakerAddress, initialStaked, finalStaked);
    }

    /**
     * @notice Reduce the stake of the given staker to the given target
     * @param stakerAddress Address of the staker to reduce the stake of
     * @param target Amount of stake to leave with the staker
     * @return Amount of value released from the stake
     */
    function reduceStakeTo(address stakerAddress, uint256 target) internal returns (uint256) {
        Staker storage staker = _stakerMap[stakerAddress];
        uint256 current = staker.amountStaked;
        require(target <= current, "TOO_LITTLE_STAKE");
        uint256 amountWithdrawn = current.sub(target);
        staker.amountStaked = target;
        increaseWithdrawableFunds(stakerAddress, amountWithdrawn);
        emit UserStakeUpdated(stakerAddress, current, target);
        return amountWithdrawn;
    }

    /**
     * @notice Remove the given staker and turn them into a zombie
     * @param stakerAddress Address of the staker to remove
     */
    function turnIntoZombie(address stakerAddress) internal {
        Staker storage staker = _stakerMap[stakerAddress];
        _zombies.push(Zombie(stakerAddress, staker.latestStakedNode));
        deleteStaker(stakerAddress);
    }

    /**
     * @notice Update the latest staked node of the zombie at the given index
     * @param zombieNum Index of the zombie to move
     * @param latest New latest node the zombie is staked on
     */
    function zombieUpdateLatestStakedNode(uint256 zombieNum, uint256 latest) internal {
        _zombies[zombieNum].latestStakedNode = latest;
    }

    /**
     * @notice Remove the zombie at the given index
     * @param zombieNum Index of the zombie to remove
     */
    function removeZombie(uint256 zombieNum) internal {
        _zombies[zombieNum] = _zombies[_zombies.length - 1];
        _zombies.pop();
    }

    /**
     * @notice Remove the given staker and return their stake
     * @param stakerAddress Address of the staker withdrawing their stake
     */
    function withdrawStaker(address stakerAddress) internal {
        Staker storage staker = _stakerMap[stakerAddress];
        uint256 initialStaked = staker.amountStaked;
        increaseWithdrawableFunds(stakerAddress, initialStaked);
        deleteStaker(stakerAddress);
        emit UserStakeUpdated(stakerAddress, initialStaked, 0);
    }

    /**
     * @notice Advance the given staker to the given node
     * @param stakerAddress Address of the staker adding their stake
     * @param nodeNum Index of the node to stake on
     */
    function stakeOnNode(
        address stakerAddress,
        uint256 nodeNum,
        uint256 confirmPeriodBlocks
    ) internal {
        Staker storage staker = _stakerMap[stakerAddress];
        INode node = _nodes[nodeNum];
        uint256 newStakerCount = node.addStaker(stakerAddress);
        staker.latestStakedNode = nodeNum;
        if (newStakerCount == 1) {
            INode parent = _nodes[node.prev()];
            parent.newChildConfirmDeadline(block.number.add(confirmPeriodBlocks));
        }
    }

    /**
     * @notice Clear the withdrawable funds for the given address
     * @param owner Address of the account to remove funds from
     * @return Amount of funds removed from account
     */
    function withdrawFunds(address owner) internal returns (uint256) {
        uint256 amount = _withdrawableFunds[owner];
        _withdrawableFunds[owner] = 0;
        emit UserWithdrawableFundsUpdated(owner, amount, 0);
        return amount;
    }

    /**
     * @notice Increase the withdrawable funds for the given address
     * @param owner Address of the account to add withdrawable funds to
     */
    function increaseWithdrawableFunds(address owner, uint256 amount) internal {
        uint256 initialWithdrawable = _withdrawableFunds[owner];
        uint256 finalWithdrawable = initialWithdrawable.add(amount);
        _withdrawableFunds[owner] = finalWithdrawable;
        emit UserWithdrawableFundsUpdated(owner, initialWithdrawable, finalWithdrawable);
    }

    /**
     * @notice Remove the given staker
     * @param stakerAddress Address of the staker to remove
     */
    function deleteStaker(address stakerAddress) private {
        Staker storage staker = _stakerMap[stakerAddress];
        uint256 stakerIndex = staker.index;
        _stakerList[stakerIndex] = _stakerList[_stakerList.length - 1];
        _stakerMap[_stakerList[stakerIndex]].index = stakerIndex;
        _stakerList.pop();
        delete _stakerMap[stakerAddress];
    }

    /**
     * @notice Destroy the given node and clear out its address
     * @param nodeNum Index of the node to remove
     */
    function destroyNode(uint256 nodeNum) internal {
        _nodes[nodeNum].destroy();
        _nodes[nodeNum] = INode(0);
    }

    function nodeDeadline(
        uint256 avmGasSpeedLimitPerBlock,
        uint256 gasUsed,
        uint256 confirmPeriodBlocks,
        INode prevNode
    ) internal view returns (uint256 deadlineBlock) {
        // Set deadline rounding up to the nearest block
        uint256 checkTime = gasUsed.add(avmGasSpeedLimitPerBlock.sub(1)).div(
            avmGasSpeedLimitPerBlock
        );

        deadlineBlock = max(block.number.add(confirmPeriodBlocks), prevNode.deadlineBlock()).add(
            checkTime
        );

        uint256 olderSibling = prevNode.latestChildNumber();
        if (olderSibling != 0) {
            deadlineBlock = max(deadlineBlock, getNode(olderSibling).deadlineBlock());
        }
        return deadlineBlock;
    }

    function max(uint256 a, uint256 b) internal pure returns (uint256) {
        return a > b ? a : b;
    }

    struct StakeOnNewNodeFrame {
        uint256 currentInboxSize;
        INode node;
        bytes32 executionHash;
        INode prevNode;
        bytes32 lastHash;
        bool hasSibling;
        uint256 deadlineBlock;
        uint256 gasUsed;
        uint256 sequencerBatchEnd;
        bytes32 sequencerBatchAcc;
    }

    struct CreateNodeDataFrame {
        uint256 prevNode;
        uint256 confirmPeriodBlocks;
        uint256 avmGasSpeedLimitPerBlock;
        ISequencerInbox sequencerInbox;
        RollupEventBridge rollupEventBridge;
        INodeFactory nodeFactory;
    }

    uint8 internal constant MAX_SEND_COUNT = 100;

    function createNewNode(
        RollupLib.Assertion memory assertion,
        bytes32[3][2] calldata assertionBytes32Fields,
        uint256[4][2] calldata assertionIntFields,
        bytes calldata sequencerBatchProof,
        CreateNodeDataFrame memory inputDataFrame,
        bytes32 expectedNodeHash
    ) internal returns (bytes32 newNodeHash) {
        StakeOnNewNodeFrame memory memoryFrame;
        {
            // validate data
            memoryFrame.gasUsed = RollupLib.assertionGasUsed(assertion);
            memoryFrame.prevNode = getNode(inputDataFrame.prevNode);
            memoryFrame.currentInboxSize = inputDataFrame.sequencerInbox.messageCount();

            // Make sure the previous state is correct against the node being built on
            require(
                RollupLib.stateHash(assertion.beforeState) == memoryFrame.prevNode.stateHash(),
                "PREV_STATE_HASH"
            );

            // Ensure that the assertion doesn't read past the end of the current inbox
            require(
                assertion.afterState.inboxCount <= memoryFrame.currentInboxSize,
                "INBOX_PAST_END"
            );
            // Insure inbox tip after assertion is included in a sequencer-inbox batch and return inbox acc; this gives replay protection against the state of the inbox
            (memoryFrame.sequencerBatchEnd, memoryFrame.sequencerBatchAcc) = inputDataFrame
                .sequencerInbox
                .proveInboxContainsMessage(sequencerBatchProof, assertion.afterState.inboxCount);
        }

        {
            memoryFrame.executionHash = RollupLib.executionHash(assertion);

            memoryFrame.deadlineBlock = nodeDeadline(
                inputDataFrame.avmGasSpeedLimitPerBlock,
                memoryFrame.gasUsed,
                inputDataFrame.confirmPeriodBlocks,
                memoryFrame.prevNode
            );

            memoryFrame.hasSibling = memoryFrame.prevNode.latestChildNumber() > 0;
            // here we don't use ternacy operator to remain compatible with slither
            if (memoryFrame.hasSibling) {
                memoryFrame.lastHash = getNodeHash(memoryFrame.prevNode.latestChildNumber());
            } else {
                memoryFrame.lastHash = getNodeHash(inputDataFrame.prevNode);
            }

            memoryFrame.node = INode(
                inputDataFrame.nodeFactory.createNode(
                    RollupLib.stateHash(assertion.afterState),
                    RollupLib.challengeRoot(assertion, memoryFrame.executionHash, block.number),
                    RollupLib.confirmHash(assertion),
                    inputDataFrame.prevNode,
                    memoryFrame.deadlineBlock
                )
            );
        }

        {
            uint256 nodeNum = latestNodeCreated() + 1;
            memoryFrame.prevNode.childCreated(nodeNum);

            newNodeHash = RollupLib.nodeHash(
                memoryFrame.hasSibling,
                memoryFrame.lastHash,
                memoryFrame.executionHash,
                memoryFrame.sequencerBatchAcc
            );
            require(newNodeHash == expectedNodeHash, "UNEXPECTED_NODE_HASH");

            nodeCreated(memoryFrame.node, newNodeHash);
            inputDataFrame.rollupEventBridge.nodeCreated(
                nodeNum,
                inputDataFrame.prevNode,
                memoryFrame.deadlineBlock,
                msg.sender
            );
        }

        emit NodeCreated(
            latestNodeCreated(),
            getNodeHash(inputDataFrame.prevNode),
            newNodeHash,
            memoryFrame.executionHash,
            memoryFrame.currentInboxSize,
            memoryFrame.sequencerBatchEnd,
            memoryFrame.sequencerBatchAcc,
            assertionBytes32Fields,
            assertionIntFields
        );

        return newNodeHash;
    }
}

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

import "../challenge/ChallengeLib.sol";
import "./INode.sol";

import "@openzeppelin/contracts/math/SafeMath.sol";

library RollupLib {
    using SafeMath for uint256;

    struct Config {
        bytes32 machineHash;
        uint256 confirmPeriodBlocks;
        uint256 extraChallengeTimeBlocks;
        uint256 avmGasSpeedLimitPerBlock;
        uint256 baseStake;
        address stakeToken;
        address owner;
        address sequencer;
        uint256 sequencerDelayBlocks;
        uint256 sequencerDelaySeconds;
        bytes extraConfig;
    }

    struct ExecutionState {
        uint256 gasUsed;
        bytes32 machineHash;
        uint256 inboxCount;
        uint256 sendCount;
        uint256 logCount;
        bytes32 sendAcc;
        bytes32 logAcc;
        uint256 proposedBlock;
        uint256 inboxMaxCount;
    }

    function stateHash(ExecutionState memory execState) internal pure returns (bytes32) {
        return
            keccak256(
                abi.encodePacked(
                    execState.gasUsed,
                    execState.machineHash,
                    execState.inboxCount,
                    execState.sendCount,
                    execState.logCount,
                    execState.sendAcc,
                    execState.logAcc,
                    execState.proposedBlock,
                    execState.inboxMaxCount
                )
            );
    }

    struct Assertion {
        ExecutionState beforeState;
        ExecutionState afterState;
    }

    function decodeExecutionState(
        bytes32[3] memory bytes32Fields,
        uint256[4] memory intFields,
        uint256 proposedBlock,
        uint256 inboxMaxCount
    ) internal pure returns (ExecutionState memory) {
        return
            ExecutionState(
                intFields[0],
                bytes32Fields[0],
                intFields[1],
                intFields[2],
                intFields[3],
                bytes32Fields[1],
                bytes32Fields[2],
                proposedBlock,
                inboxMaxCount
            );
    }

    function decodeAssertion(
        bytes32[3][2] memory bytes32Fields,
        uint256[4][2] memory intFields,
        uint256 beforeProposedBlock,
        uint256 beforeInboxMaxCount,
        uint256 inboxMaxCount
    ) internal view returns (Assertion memory) {
        return
            Assertion(
                decodeExecutionState(
                    bytes32Fields[0],
                    intFields[0],
                    beforeProposedBlock,
                    beforeInboxMaxCount
                ),
                decodeExecutionState(bytes32Fields[1], intFields[1], block.number, inboxMaxCount)
            );
    }

    function executionStateChallengeHash(ExecutionState memory state)
        internal
        pure
        returns (bytes32)
    {
        return
            ChallengeLib.assertionHash(
                state.gasUsed,
                ChallengeLib.assertionRestHash(
                    state.inboxCount,
                    state.machineHash,
                    state.sendAcc,
                    state.sendCount,
                    state.logAcc,
                    state.logCount
                )
            );
    }

    function executionHash(Assertion memory assertion) internal pure returns (bytes32) {
        return
            ChallengeLib.bisectionChunkHash(
                assertion.beforeState.gasUsed,
                assertion.afterState.gasUsed - assertion.beforeState.gasUsed,
                RollupLib.executionStateChallengeHash(assertion.beforeState),
                RollupLib.executionStateChallengeHash(assertion.afterState)
            );
    }

    function assertionGasUsed(RollupLib.Assertion memory assertion)
        internal
        pure
        returns (uint256)
    {
        return assertion.afterState.gasUsed.sub(assertion.beforeState.gasUsed);
    }

    function challengeRoot(
        Assertion memory assertion,
        bytes32 assertionExecHash,
        uint256 blockProposed
    ) internal pure returns (bytes32) {
        return challengeRootHash(assertionExecHash, blockProposed, assertion.afterState.inboxCount);
    }

    function challengeRootHash(
        bytes32 execution,
        uint256 proposedTime,
        uint256 maxMessageCount
    ) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked(execution, proposedTime, maxMessageCount));
    }

    function confirmHash(Assertion memory assertion) internal pure returns (bytes32) {
        return
            confirmHash(
                assertion.beforeState.sendAcc,
                assertion.afterState.sendAcc,
                assertion.afterState.logAcc,
                assertion.afterState.sendCount,
                assertion.afterState.logCount
            );
    }

    function confirmHash(
        bytes32 beforeSendAcc,
        bytes32 afterSendAcc,
        bytes32 afterLogAcc,
        uint256 afterSendCount,
        uint256 afterLogCount
    ) internal pure returns (bytes32) {
        return
            keccak256(
                abi.encodePacked(
                    beforeSendAcc,
                    afterSendAcc,
                    afterSendCount,
                    afterLogAcc,
                    afterLogCount
                )
            );
    }

    function feedAccumulator(
        bytes memory messageData,
        uint256[] memory messageLengths,
        bytes32 beforeAcc
    ) internal pure returns (bytes32) {
        uint256 offset = 0;
        uint256 messageCount = messageLengths.length;
        uint256 dataLength = messageData.length;
        bytes32 messageAcc = beforeAcc;
        for (uint256 i = 0; i < messageCount; i++) {
            uint256 messageLength = messageLengths[i];
            require(offset + messageLength <= dataLength, "DATA_OVERRUN");
            bytes32 messageHash;
            assembly {
                messageHash := keccak256(add(messageData, add(offset, 32)), messageLength)
            }
            messageAcc = keccak256(abi.encodePacked(messageAcc, messageHash));
            offset += messageLength;
        }
        require(offset == dataLength, "DATA_LENGTH");
        return messageAcc;
    }

    function nodeHash(
        bool hasSibling,
        bytes32 lastHash,
        bytes32 assertionExecHash,
        bytes32 inboxAcc
    ) internal pure returns (bytes32) {
        uint8 hasSiblingInt = hasSibling ? 1 : 0;
        return keccak256(abi.encodePacked(hasSiblingInt, lastHash, assertionExecHash, inboxAcc));
    }
}

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

// solhint-disable-next-line compiler-version
pragma solidity >=0.6.9 <0.9.0;

interface INode {
    function initialize(
        address _rollup,
        bytes32 _stateHash,
        bytes32 _challengeHash,
        bytes32 _confirmData,
        uint256 _prev,
        uint256 _deadlineBlock
    ) external;

    function destroy() external;

    function addStaker(address staker) external returns (uint256);

    function removeStaker(address staker) external;

    function childCreated(uint256) external;

    function newChildConfirmDeadline(uint256 deadline) external;

    function stateHash() external view returns (bytes32);

    function challengeHash() external view returns (bytes32);

    function confirmData() external view returns (bytes32);

    function prev() external view returns (uint256);

    function deadlineBlock() external view returns (uint256);

    function noChildConfirmedBeforeBlock() external view returns (uint256);

    function stakerCount() external view returns (uint256);

    function stakers(address staker) external view returns (bool);

    function firstChildBlock() external view returns (uint256);

    function latestChildNumber() external view returns (uint256);

    function requirePastDeadline() external view;

    function requirePastChildConfirmDeadline() external view;

    function isNitroReady() external pure 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.
 */

// solhint-disable-next-line compiler-version
pragma solidity >=0.6.9 <0.9.0;

interface INodeFactory {
    function createNode(
        bytes32 _stateHash,
        bytes32 _challengeHash,
        bytes32 _confirmData,
        uint256 _prev,
        uint256 _deadlineBlock
    ) external returns (address);

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

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

// solhint-disable-next-line compiler-version
pragma solidity >=0.6.9 <0.9.0;

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

interface IChallenge {
    function initializeChallenge(
        IOneStepProof[] calldata _executors,
        address _resultReceiver,
        bytes32 _executionHash,
        uint256 _maxMessageCount,
        address _asserter,
        address _challenger,
        uint256 _asserterTimeLeft,
        uint256 _challengerTimeLeft,
        ISequencerInbox _sequencerBridge,
        IBridge _delayedBridge
    ) external;

    function currentResponderTimeLeft() external view returns (uint256);

    function lastMoveBlock() external view returns (uint256);

    function timeout() external;

    function asserter() external view returns (address);

    function challenger() external view returns (address);

    function clearChallenge() external;
}

File 15 of 34 : IChallengeFactory.sol
// 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.
 */

// solhint-disable-next-line compiler-version
pragma solidity >=0.6.9 <0.9.0;

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

interface IChallengeFactory {
    function createChallenge(
        address _resultReceiver,
        bytes32 _executionHash,
        uint256 _maxMessageCount,
        address _asserter,
        address _challenger,
        uint256 _asserterTimeLeft,
        uint256 _challengerTimeLeft,
        ISequencerInbox _sequencerBridge,
        IBridge _delayedBridge
    ) external returns (address);
}

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

// solhint-disable-next-line compiler-version
pragma solidity >=0.6.9 <0.9.0;

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);

    function isNitroReady() 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.
 */

// solhint-disable-next-line compiler-version
pragma solidity >=0.6.9 <0.9.0;

import "./IBridge.sol";

interface IOutbox {
    event OutboxEntryCreated(
        uint256 indexed batchNum,
        uint256 outboxEntryIndex,
        bytes32 outputRoot,
        uint256 numInBatch
    );
    event OutBoxTransactionExecuted(
        address indexed destAddr,
        address indexed l2Sender,
        uint256 indexed outboxEntryIndex,
        uint256 transactionIndex
    );

    function l2ToL1Sender() external view returns (address);

    function l2ToL1Block() external view returns (uint256);

    function l2ToL1EthBlock() external view returns (uint256);

    function l2ToL1Timestamp() external view returns (uint256);

    function l2ToL1BatchNum() external view returns (uint256);

    function l2ToL1OutputId() external view returns (bytes32);

    function processOutgoingMessages(bytes calldata sendsData, uint256[] calldata sendLengths)
        external;

    function outboxEntryExists(uint256 batchNum) external view returns (bool);

    function setBridge(IBridge newBridge) external;

    function isNitroReady() external pure returns (uint256);
}

// 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 Messages {
    function messageHash(
        uint8 kind,
        address sender,
        uint256 blockNumber,
        uint256 timestamp,
        uint256 inboxSeqNum,
        uint256 gasPriceL1,
        bytes32 messageDataHash
    ) internal pure returns (bytes32) {
        return
            keccak256(
                abi.encodePacked(
                    kind,
                    sender,
                    blockNumber,
                    timestamp,
                    inboxSeqNum,
                    gasPriceL1,
                    messageDataHash
                )
            );
    }

    function addMessageToInbox(bytes32 inbox, bytes32 message) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked(inbox, message));
    }
}

File 19 of 34 : ProxyUtil.sol
// 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;

library ProxyUtil {
    function getProxyAdmin() internal view returns (address admin) {
        // https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v3.4.0/contracts/proxy/TransparentUpgradeableProxy.sol#L48
        // Storage slot with the admin of the proxy contract.
        // This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is
        bytes32 slot = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;
        assembly {
            admin := sload(slot)
        }
    }
}

// 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 "./ICloneable.sol";

contract Cloneable is ICloneable {
    string private constant NOT_CLONE = "NOT_CLONE";

    bool private isMasterCopy;

    constructor() public {
        isMasterCopy = true;
    }

    function isMaster() external view override returns (bool) {
        return isMasterCopy;
    }

    function safeSelfDestruct(address payable dest) internal {
        require(!isMasterCopy, NOT_CLONE);
        selfdestruct(dest);
    }
}

// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

/*
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with GSN meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address payable) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes memory) {
        this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
        return msg.data;
    }
}

File 22 of 34 : IMessageProvider.sol
// 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.
 */

// solhint-disable-next-line compiler-version
pragma solidity >=0.6.9 <0.9.0;

interface IMessageProvider {
    event InboxMessageDelivered(uint256 indexed messageNum, bytes data);

    event InboxMessageDeliveredFromOrigin(uint256 indexed messageNum);
}

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

// solhint-disable-next-line compiler-version
pragma solidity >=0.6.9 <0.9.0;

import "./INode.sol";

interface IRollupCore {
    function _stakerMap(address stakerAddress)
        external
        view
        returns (
            uint256,
            uint256,
            uint256,
            address,
            bool
        );

    event RollupCreated(bytes32 machineHash);

    event NodeCreated(
        uint256 indexed nodeNum,
        bytes32 indexed parentNodeHash,
        bytes32 nodeHash,
        bytes32 executionHash,
        uint256 inboxMaxCount,
        uint256 afterInboxBatchEndCount,
        bytes32 afterInboxBatchAcc,
        bytes32[3][2] assertionBytes32Fields,
        uint256[4][2] assertionIntFields
    );

    event NodeConfirmed(
        uint256 indexed nodeNum,
        bytes32 afterSendAcc,
        uint256 afterSendCount,
        bytes32 afterLogAcc,
        uint256 afterLogCount
    );

    event NodeRejected(uint256 indexed nodeNum);

    event RollupChallengeStarted(
        address indexed challengeContract,
        address asserter,
        address challenger,
        uint256 challengedNode
    );

    event UserStakeUpdated(address indexed user, uint256 initialBalance, uint256 finalBalance);

    event UserWithdrawableFundsUpdated(
        address indexed user,
        uint256 initialBalance,
        uint256 finalBalance
    );

    function getNode(uint256 nodeNum) external view returns (INode);

    /**
     * @notice Get the address of the staker at the given index
     * @param stakerNum Index of the staker
     * @return Address of the staker
     */
    function getStakerAddress(uint256 stakerNum) external view returns (address);

    /**
     * @notice Check whether the given staker is staked
     * @param staker Staker address to check
     * @return True or False for whether the staker was staked
     */
    function isStaked(address staker) external view returns (bool);

    /**
     * @notice Get the latest staked node of the given staker
     * @param staker Staker address to lookup
     * @return Latest node staked of the staker
     */
    function latestStakedNode(address staker) external view returns (uint256);

    /**
     * @notice Get the current challenge of the given staker
     * @param staker Staker address to lookup
     * @return Current challenge of the staker
     */
    function currentChallenge(address staker) external view returns (address);

    /**
     * @notice Get the amount staked of the given staker
     * @param staker Staker address to lookup
     * @return Amount staked of the staker
     */
    function amountStaked(address staker) external view returns (uint256);

    /**
     * @notice Get the original staker address of the zombie at the given index
     * @param zombieNum Index of the zombie to lookup
     * @return Original staker address of the zombie
     */
    function zombieAddress(uint256 zombieNum) external view returns (address);

    /**
     * @notice Get Latest node that the given zombie at the given index is staked on
     * @param zombieNum Index of the zombie to lookup
     * @return Latest node that the given zombie is staked on
     */
    function zombieLatestStakedNode(uint256 zombieNum) external view returns (uint256);

    /// @return Current number of un-removed zombies
    function zombieCount() external view returns (uint256);

    function isZombie(address staker) external view returns (bool);

    /**
     * @notice Get the amount of funds withdrawable by the given address
     * @param owner Address to check the funds of
     * @return Amount of funds withdrawable by owner
     */
    function withdrawableFunds(address owner) external view returns (uint256);

    /**
     * @return Index of the first unresolved node
     * @dev If all nodes have been resolved, this will be latestNodeCreated + 1
     */
    function firstUnresolvedNode() external view returns (uint256);

    /// @return Index of the latest confirmed node
    function latestConfirmed() external view returns (uint256);

    /// @return Index of the latest rollup node created
    function latestNodeCreated() external view returns (uint256);

    /// @return Ethereum block that the most recent stake was created
    function lastStakeBlock() external view returns (uint256);

    /// @return Number of active stakers currently staked
    function stakerCount() external view returns (uint256);

    /// @return Node hash as of this node number
    function getNodeHash(uint256 index) external view returns (bytes32);
}

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

// solhint-disable-next-line compiler-version
pragma solidity >=0.6.9 <0.9.0;

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);
    event ShutdownForNitroSet(bool shutdown);

    /// @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: MIT

pragma solidity >=0.6.0 <0.8.0;

/**
 * @dev Wrappers over Solidity's arithmetic operations with added overflow
 * checks.
 *
 * Arithmetic operations in Solidity wrap on overflow. This can easily result
 * in bugs, because programmers usually assume that an overflow raises an
 * error, which is the standard behavior in high level programming languages.
 * `SafeMath` restores this intuition by reverting the transaction when an
 * operation overflows.
 *
 * Using this library instead of the unchecked operations eliminates an entire
 * class of bugs, so it's recommended to use it always.
 */
library SafeMath {
    /**
     * @dev Returns the addition of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        uint256 c = a + b;
        if (c < a) return (false, 0);
        return (true, c);
    }

    /**
     * @dev Returns the substraction of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        if (b > a) return (false, 0);
        return (true, a - b);
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, with an overflow flag.
     *
     * _Available since v3.4._
     */
    function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
        // benefit is lost if 'b' is also tested.
        // See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
        if (a == 0) return (true, 0);
        uint256 c = a * b;
        if (c / a != b) return (false, 0);
        return (true, c);
    }

    /**
     * @dev Returns the division of two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        if (b == 0) return (false, 0);
        return (true, a / b);
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
     *
     * _Available since v3.4._
     */
    function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
        if (b == 0) return (false, 0);
        return (true, a % b);
    }

    /**
     * @dev Returns the addition of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `+` operator.
     *
     * Requirements:
     *
     * - Addition cannot overflow.
     */
    function add(uint256 a, uint256 b) internal pure returns (uint256) {
        uint256 c = a + b;
        require(c >= a, "SafeMath: addition overflow");
        return c;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting on
     * overflow (when the result is negative).
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b <= a, "SafeMath: subtraction overflow");
        return a - b;
    }

    /**
     * @dev Returns the multiplication of two unsigned integers, reverting on
     * overflow.
     *
     * Counterpart to Solidity's `*` operator.
     *
     * Requirements:
     *
     * - Multiplication cannot overflow.
     */
    function mul(uint256 a, uint256 b) internal pure returns (uint256) {
        if (a == 0) return 0;
        uint256 c = a * b;
        require(c / a == b, "SafeMath: multiplication overflow");
        return c;
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting on
     * division by zero. The result is rounded towards zero.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b > 0, "SafeMath: division by zero");
        return a / b;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting when dividing by zero.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b) internal pure returns (uint256) {
        require(b > 0, "SafeMath: modulo by zero");
        return a % b;
    }

    /**
     * @dev Returns the subtraction of two unsigned integers, reverting with custom message on
     * overflow (when the result is negative).
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {trySub}.
     *
     * Counterpart to Solidity's `-` operator.
     *
     * Requirements:
     *
     * - Subtraction cannot overflow.
     */
    function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b <= a, errorMessage);
        return a - b;
    }

    /**
     * @dev Returns the integer division of two unsigned integers, reverting with custom message on
     * division by zero. The result is rounded towards zero.
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {tryDiv}.
     *
     * Counterpart to Solidity's `/` operator. Note: this function uses a
     * `revert` opcode (which leaves remaining gas untouched) while Solidity
     * uses an invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b > 0, errorMessage);
        return a / b;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * reverting with custom message when dividing by zero.
     *
     * CAUTION: This function is deprecated because it requires allocating memory for the error
     * message unnecessarily. For custom revert reasons use {tryMod}.
     *
     * Counterpart to Solidity's `%` operator. This function uses a `revert`
     * opcode (which leaves remaining gas untouched) while Solidity uses an
     * invalid opcode to revert (consuming all remaining gas).
     *
     * Requirements:
     *
     * - The divisor cannot be zero.
     */
    function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
        require(b > 0, errorMessage);
        return a % b;
    }
}

// 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 "../libraries/MerkleLib.sol";
import "@openzeppelin/contracts/math/SafeMath.sol";

library ChallengeLib {
    using SafeMath for uint256;

    function firstSegmentSize(uint256 totalCount, uint256 bisectionCount)
        internal
        pure
        returns (uint256)
    {
        return totalCount / bisectionCount + (totalCount % bisectionCount);
    }

    function otherSegmentSize(uint256 totalCount, uint256 bisectionCount)
        internal
        pure
        returns (uint256)
    {
        return totalCount / bisectionCount;
    }

    function bisectionChunkHash(
        uint256 _segmentStart,
        uint256 _segmentLength,
        bytes32 _startHash,
        bytes32 _endHash
    ) internal pure returns (bytes32) {
        return keccak256(abi.encodePacked(_segmentStart, _segmentLength, _startHash, _endHash));
    }

    function assertionHash(uint256 _avmGasUsed, bytes32 _restHash) internal pure returns (bytes32) {
        // Note: make sure this doesn't return Challenge.UNREACHABLE_ASSERTION (currently 0)
        return keccak256(abi.encodePacked(_avmGasUsed, _restHash));
    }

    function assertionRestHash(
        uint256 _totalMessagesRead,
        bytes32 _machineState,
        bytes32 _sendAcc,
        uint256 _sendCount,
        bytes32 _logAcc,
        uint256 _logCount
    ) internal pure returns (bytes32) {
        return
            keccak256(
                abi.encodePacked(
                    _totalMessagesRead,
                    _machineState,
                    _sendAcc,
                    _sendCount,
                    _logAcc,
                    _logCount
                )
            );
    }

    function updatedBisectionRoot(
        bytes32[] memory _chainHashes,
        uint256 _challengedSegmentStart,
        uint256 _challengedSegmentLength
    ) internal pure returns (bytes32) {
        uint256 bisectionCount = _chainHashes.length - 1;
        bytes32[] memory hashes = new bytes32[](bisectionCount);
        uint256 chunkSize = ChallengeLib.firstSegmentSize(_challengedSegmentLength, bisectionCount);
        uint256 segmentStart = _challengedSegmentStart;
        hashes[0] = ChallengeLib.bisectionChunkHash(
            segmentStart,
            chunkSize,
            _chainHashes[0],
            _chainHashes[1]
        );
        segmentStart = segmentStart.add(chunkSize);
        chunkSize = ChallengeLib.otherSegmentSize(_challengedSegmentLength, bisectionCount);
        for (uint256 i = 1; i < bisectionCount; i++) {
            hashes[i] = ChallengeLib.bisectionChunkHash(
                segmentStart,
                chunkSize,
                _chainHashes[i],
                _chainHashes[i + 1]
            );
            segmentStart = segmentStart.add(chunkSize);
        }
        return MerkleLib.generateRoot(hashes);
    }

    function verifySegmentProof(
        bytes32 challengeState,
        bytes32 item,
        bytes32[] calldata _merkleNodes,
        uint256 _merkleRoute
    ) internal pure returns (bool) {
        return challengeState == MerkleLib.calculateRoot(_merkleNodes, _merkleRoute, item);
    }
}

// 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 MerkleLib {
    function generateRoot(bytes32[] memory _hashes) internal pure returns (bytes32) {
        bytes32[] memory prevLayer = _hashes;
        while (prevLayer.length > 1) {
            bytes32[] memory nextLayer = new bytes32[]((prevLayer.length + 1) / 2);
            for (uint256 i = 0; i < nextLayer.length; i++) {
                if (2 * i + 1 < prevLayer.length) {
                    nextLayer[i] = keccak256(
                        abi.encodePacked(prevLayer[2 * i], prevLayer[2 * i + 1])
                    );
                } else {
                    nextLayer[i] = prevLayer[2 * i];
                }
            }
            prevLayer = nextLayer;
        }
        return prevLayer[0];
    }

    function calculateRoot(
        bytes32[] memory nodes,
        uint256 route,
        bytes32 item
    ) internal pure returns (bytes32) {
        uint256 proofItems = nodes.length;
        require(proofItems <= 256);
        bytes32 h = item;
        for (uint256 i = 0; i < proofItems; i++) {
            if (route % 2 == 0) {
                h = keccak256(abi.encodePacked(nodes[i], h));
            } else {
                h = keccak256(abi.encodePacked(h, nodes[i]));
            }
            route /= 2;
        }
        return h;
    }
}

File 28 of 34 : ICloneable.sol
// 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.
 */

// solhint-disable-next-line compiler-version
pragma solidity >=0.6.9 <0.9.0;

interface ICloneable {
    function isMaster() external view returns (bool);
}

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

// solhint-disable-next-line compiler-version
pragma solidity >=0.6.9 <0.9.0;

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

// solhint-disable-next-line compiler-version
pragma solidity >=0.6.9 <0.9.0;

import "./IBridge.sol";
import "./IMessageProvider.sol";

interface IInbox is IMessageProvider {
    function sendL2Message(bytes calldata messageData) external returns (uint256);

    function sendUnsignedTransaction(
        uint256 maxGas,
        uint256 gasPriceBid,
        uint256 nonce,
        address destAddr,
        uint256 amount,
        bytes calldata data
    ) external returns (uint256);

    function sendContractTransaction(
        uint256 maxGas,
        uint256 gasPriceBid,
        address destAddr,
        uint256 amount,
        bytes calldata data
    ) external returns (uint256);

    function sendL1FundedUnsignedTransaction(
        uint256 maxGas,
        uint256 gasPriceBid,
        uint256 nonce,
        address destAddr,
        bytes calldata data
    ) external payable returns (uint256);

    function sendL1FundedContractTransaction(
        uint256 maxGas,
        uint256 gasPriceBid,
        address destAddr,
        bytes calldata data
    ) external payable returns (uint256);

    function createRetryableTicket(
        address destAddr,
        uint256 arbTxCallValue,
        uint256 maxSubmissionCost,
        address submissionRefundAddress,
        address valueRefundAddress,
        uint256 maxGas,
        uint256 gasPriceBid,
        bytes calldata data
    ) external payable returns (uint256);

    function unsafeCreateRetryableTicket(
        address destAddr,
        uint256 arbTxCallValue,
        uint256 maxSubmissionCost,
        address submissionRefundAddress,
        address valueRefundAddress,
        uint256 maxGas,
        uint256 gasPriceBid,
        bytes calldata data
    ) external payable returns (uint256);

    function depositEth(uint256 maxSubmissionCost) external payable returns (uint256);

    function bridge() external view returns (IBridge);

    function pauseCreateRetryables() external;

    function unpauseCreateRetryables() external;

    function startRewriteAddress() external;

    function stopRewriteAddress() external;
}

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

// solhint-disable-next-line compiler-version
pragma solidity >=0.6.9 <0.9.0;

import "./IOwnable.sol";

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

    event BridgeCallTriggered(
        address indexed outbox,
        address indexed to,
        uint256 value,
        bytes data
    );

    event InboxToggle(address indexed inbox, bool enabled);

    event OutboxToggle(address indexed outbox, bool enabled);

    event SequencerInboxUpdated(address newSequencerInbox);

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

    function enqueueSequencerMessage(bytes32 dataHash, uint256 afterDelayedMessagesRead)
        external
        returns (
            uint256 seqMessageIndex,
            bytes32 beforeAcc,
            bytes32 delayedAcc,
            bytes32 acc
        );

    function submitBatchSpendingReport(address batchPoster, bytes32 dataHash)
        external
        returns (uint256 msgNum);

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

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

    function setOutbox(address inbox, bool enabled) external;

    function setSequencerInbox(address _sequencerInbox) external;

    // View functions

    function sequencerInbox() external view returns (address);

    function activeOutbox() external view returns (address);

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

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

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

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

    function delayedMessageCount() external view returns (uint256);

    function sequencerMessageCount() external view returns (uint256);

    function rollup() external view returns (IOwnable);

    function acceptFundsFromOldBridge() external payable;
}

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

// solhint-disable-next-line compiler-version
pragma solidity >=0.6.9 <0.9.0;

import "./IBridge.sol";
import "./IDelayedMessageProvider.sol";

interface IInbox is IDelayedMessageProvider {
    function sendL2Message(bytes calldata messageData) external returns (uint256);

    function sendUnsignedTransaction(
        uint256 gasLimit,
        uint256 maxFeePerGas,
        uint256 nonce,
        address to,
        uint256 value,
        bytes calldata data
    ) external returns (uint256);

    function sendContractTransaction(
        uint256 gasLimit,
        uint256 maxFeePerGas,
        address to,
        uint256 value,
        bytes calldata data
    ) external returns (uint256);

    function sendL1FundedUnsignedTransaction(
        uint256 gasLimit,
        uint256 maxFeePerGas,
        uint256 nonce,
        address to,
        bytes calldata data
    ) external payable returns (uint256);

    function sendL1FundedContractTransaction(
        uint256 gasLimit,
        uint256 maxFeePerGas,
        address to,
        bytes calldata data
    ) external payable returns (uint256);

    /// @dev Gas limit and maxFeePerGas should not be set to 1 as that is used to trigger the RetryableData error
    function createRetryableTicket(
        address to,
        uint256 arbTxCallValue,
        uint256 maxSubmissionCost,
        address submissionRefundAddress,
        address valueRefundAddress,
        uint256 gasLimit,
        uint256 maxFeePerGas,
        bytes calldata data
    ) external payable returns (uint256);

    /// @dev Gas limit and maxFeePerGas should not be set to 1 as that is used to trigger the RetryableData error
    function unsafeCreateRetryableTicket(
        address to,
        uint256 arbTxCallValue,
        uint256 maxSubmissionCost,
        address submissionRefundAddress,
        address valueRefundAddress,
        uint256 gasLimit,
        uint256 maxFeePerGas,
        bytes calldata data
    ) external payable returns (uint256);

    function depositEth() external payable returns (uint256);

    /// @notice deprecated in favour of depositEth with no parameters
    function depositEth(uint256 maxSubmissionCost) external payable returns (uint256);

    function bridge() external view returns (IBridge);

    function postUpgradeInit(IBridge _bridge) external;
}

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

// solhint-disable-next-line compiler-version
pragma solidity >=0.4.21 <0.9.0;

interface IOwnable {
    function owner() external view returns (address);
}

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

// solhint-disable-next-line compiler-version
pragma solidity >=0.6.9 <0.9.0;

interface IDelayedMessageProvider {
    /// @dev event emitted when a inbox message is added to the Bridge's delayed accumulator
    event InboxMessageDelivered(uint256 indexed messageNum, bytes data);

    /// @dev event emitted when a inbox message is added to the Bridge's delayed accumulator
    /// same as InboxMessageDelivered but the batch data is available in tx.input
    event InboxMessageDeliveredFromOrigin(uint256 indexed messageNum);
}

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

Contract Security Audit

Contract ABI

API
[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"nodeNum","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"afterSendAcc","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"afterSendCount","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"afterLogAcc","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"afterLogCount","type":"uint256"}],"name":"NodeConfirmed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"nodeNum","type":"uint256"},{"indexed":true,"internalType":"bytes32","name":"parentNodeHash","type":"bytes32"},{"indexed":false,"internalType":"bytes32","name":"nodeHash","type":"bytes32"},{"indexed":false,"internalType":"bytes32","name":"executionHash","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"inboxMaxCount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"afterInboxBatchEndCount","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"afterInboxBatchAcc","type":"bytes32"},{"indexed":false,"internalType":"bytes32[3][2]","name":"assertionBytes32Fields","type":"bytes32[3][2]"},{"indexed":false,"internalType":"uint256[4][2]","name":"assertionIntFields","type":"uint256[4][2]"}],"name":"NodeCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"nodeNum","type":"uint256"}],"name":"NodeRejected","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"challengeContract","type":"address"},{"indexed":false,"internalType":"address","name":"asserter","type":"address"},{"indexed":false,"internalType":"address","name":"challenger","type":"address"},{"indexed":false,"internalType":"uint256","name":"challengedNode","type":"uint256"}],"name":"RollupChallengeStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"machineHash","type":"bytes32"}],"name":"RollupCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"initialBalance","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"finalBalance","type":"uint256"}],"name":"UserStakeUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"user","type":"address"},{"indexed":false,"internalType":"uint256","name":"initialBalance","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"finalBalance","type":"uint256"}],"name":"UserWithdrawableFundsUpdated","type":"event"},{"inputs":[],"name":"STORAGE_GAP_1","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"STORAGE_GAP_2","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"_stakerMap","outputs":[{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"uint256","name":"latestStakedNode","type":"uint256"},{"internalType":"uint256","name":"amountStaked","type":"uint256"},{"internalType":"address","name":"currentChallenge","type":"address"},{"internalType":"bool","name":"isStaked","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"stakerAddress","type":"address"}],"name":"addToDeposit","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"staker","type":"address"}],"name":"amountStaked","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"arbGasSpeedLimitPerBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"avmGasSpeedLimitPerBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"baseStake","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"challengeExecutionBisectionDegree","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"challengeFactory","outputs":[{"internalType":"contract IChallengeFactory","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"winningStaker","type":"address"},{"internalType":"address","name":"losingStaker","type":"address"}],"name":"completeChallenge","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"beforeSendAcc","type":"bytes32"},{"internalType":"bytes","name":"sendsData","type":"bytes"},{"internalType":"uint256[]","name":"sendLengths","type":"uint256[]"},{"internalType":"uint256","name":"afterSendCount","type":"uint256"},{"internalType":"bytes32","name":"afterLogAcc","type":"bytes32"},{"internalType":"uint256","name":"afterLogCount","type":"uint256"}],"name":"confirmNextNode","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"confirmPeriodBlocks","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"contract INode","name":"node","type":"address"}],"name":"countStakedZombies","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address payable[2]","name":"stakers","type":"address[2]"},{"internalType":"uint256[2]","name":"nodeNums","type":"uint256[2]"},{"internalType":"bytes32[2]","name":"executionHashes","type":"bytes32[2]"},{"internalType":"uint256[2]","name":"proposedTimes","type":"uint256[2]"},{"internalType":"uint256[2]","name":"maxMessageCounts","type":"uint256[2]"}],"name":"createChallenge","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"staker","type":"address"}],"name":"currentChallenge","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"currentRequiredStake","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"delayedBridge","outputs":[{"internalType":"contract IBridge","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"extraChallengeTimeBlocks","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"firstUnresolvedNode","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"nodeNum","type":"uint256"}],"name":"getNode","outputs":[{"internalType":"contract INode","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getNodeHash","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"stakerNum","type":"uint256"}],"name":"getStakerAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_stakeToken","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"isMaster","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isNitroReady","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"staker","type":"address"}],"name":"isStaked","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"staker","type":"address"}],"name":"isZombie","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"lastStakeBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"latestConfirmed","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"latestNodeCreated","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"staker","type":"address"}],"name":"latestStakedNode","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minimumAssertionPeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"newStake","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"nodeFactory","outputs":[{"internalType":"contract INodeFactory","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"outbox","outputs":[{"internalType":"contract IOutbox","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"paused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"target","type":"uint256"}],"name":"reduceDeposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"stakerAddress","type":"address"}],"name":"rejectNextNode","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"startIndex","type":"uint256"}],"name":"removeOldZombies","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"zombieNum","type":"uint256"},{"internalType":"uint256","name":"maxNodes","type":"uint256"}],"name":"removeZombie","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"nodeNum","type":"uint256"}],"name":"requireUnresolved","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[],"name":"requireUnresolvedExists","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"blockNumber","type":"uint256"},{"internalType":"uint256","name":"firstUnresolvedNodeNum","type":"uint256"},{"internalType":"uint256","name":"latestCreatedNode","type":"uint256"}],"name":"requiredStake","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"stakerAddress","type":"address"}],"name":"returnOldDeposit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"rollupEventBridge","outputs":[{"internalType":"contract RollupEventBridge","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"sequencerBridge","outputs":[{"internalType":"contract ISequencerInbox","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"shutdownForNitroBlock","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"shutdownForNitroMode","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"nodeNum","type":"uint256"},{"internalType":"bytes32","name":"nodeHash","type":"bytes32"}],"name":"stakeOnExistingNode","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"expectedNodeHash","type":"bytes32"},{"internalType":"bytes32[3][2]","name":"assertionBytes32Fields","type":"bytes32[3][2]"},{"internalType":"uint256[4][2]","name":"assertionIntFields","type":"uint256[4][2]"},{"internalType":"uint256","name":"beforeProposedBlock","type":"uint256"},{"internalType":"uint256","name":"beforeInboxMaxCount","type":"uint256"},{"internalType":"bytes","name":"sequencerBatchProof","type":"bytes"}],"name":"stakeOnNewNode","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"stakeToken","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"stakerCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address payable","name":"destination","type":"address"}],"name":"withdrawStakerFunds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"withdrawableFunds","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"zombieNum","type":"uint256"}],"name":"zombieAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"zombieCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"zombieNum","type":"uint256"}],"name":"zombieLatestStakedNode","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"}]

608060405234801561001057600080fd5b506000805460ff19908116600117909155600b805490911690556154d5806100396000396000f3fe60806040526004361061030c5760003560e01c80637427be511161019c578063d01e6602116100e2578063e8bd492211610090578063e8bd492214610a22578063edfd03ed14610a8b578063ef40a67014610ab5578063f31d863f14610ae8578063f33e1fac14610bc6578063f51de41b14610bf0578063f8d1f19414610c05578063fa7803e614610c2f5761030c565b8063d01e66021461097a578063d735e21d146109a4578063d7445bc8146109b9578063d93fe9c4146109ce578063dc72a33b146109e3578063dff69787146109f8578063e4781e1014610a0d5761030c565b806381fbc98a1161014a57806381fbc98a146108785780638640ce5f146108ab5780638da5cb5b146108c057806391c657e8146108d55780639e8a713f14610908578063a8929e0b1461091d578063c4d66de814610932578063ce11e6ab146109655761030c565b80637427be51146107ac57806376e7e23b146107df578063771b2f97146107f45780637ba9534a146108095780637e2d21551461081e5780637f4320ce1461084e5780637f60abbb146108635761030c565b80634f0f4aa91161026157806362a82d7d1161020f57806362a82d7d1461069257806363721d6b146106bc57806365f7f80d146106d157806367425daf146106e657806369fd251c146106fb5780636b94c33b1461072e5780636f791d29146107615780636f7d0026146107765761030c565b80634f0f4aa9146105d957806351ed6a30146106035780635c975abb146106185780635dbaf68b1461062d5780635e8ef106146106425780635f576db6146106575780636177fd181461065f5761030c565b80633e96576e116102be5780633e96576e1461044e5780633fe3862714610481578063414f23fe1461051e57806345c5b2c71461054e57806345e38b6414610574578063488ed1a9146105895780634d26732d146105c45761030c565b806304a28064146103115780631e83d30f146103565780632b2af0ab146103825780632e7acfa6146103ac5780632f30cabd146103c1578063313a04fa146103f45780633e55c0c71461041d575b600080fd5b34801561031d57600080fd5b506103446004803603602081101561033457600080fd5b50356001600160a01b0316610c6a565b60408051918252519081900360200190f35b34801561036257600080fd5b506103806004803603602081101561037957600080fd5b5035610d2b565b005b34801561038e57600080fd5b50610380600480360360208110156103a557600080fd5b5035610df7565b3480156103b857600080fd5b50610344610e93565b3480156103cd57600080fd5b50610344600480360360208110156103e457600080fd5b50356001600160a01b0316610e99565b34801561040057600080fd5b50610409610eb4565b604080519115158252519081900360200190f35b34801561042957600080fd5b50610432610ebd565b604080516001600160a01b039092168252519081900360200190f35b34801561045a57600080fd5b506103446004803603602081101561047157600080fd5b50356001600160a01b0316610ecc565b34801561048d57600080fd5b5061038060048036036102408110156104a557600080fd5b813591602081019160e08201916101e08101359161020082013591908101906102408101610220820135600160201b8111156104e057600080fd5b8201836020820111156104f257600080fd5b803590602001918460018302840111600160201b8311171561051357600080fd5b509092509050610eea565b34801561052a57600080fd5b506103806004803603604081101561054157600080fd5b508035906020013561135e565b6103806004803603602081101561056457600080fd5b50356001600160a01b03166115bd565b34801561058057600080fd5b50610344611663565b34801561059557600080fd5b5061038060048036036101408110156105ad57600080fd5b50604081016080820160c083016101008401611669565b3480156105d057600080fd5b50610344611f92565b3480156105e557600080fd5b50610432600480360360208110156105fc57600080fd5b5035611fb7565b34801561060f57600080fd5b50610432611fd2565b34801561062457600080fd5b50610409611fe1565b34801561063957600080fd5b50610432611fea565b34801561064e57600080fd5b50610344611ff9565b610380611fff565b34801561066b57600080fd5b506104096004803603602081101561068257600080fd5b50356001600160a01b03166120a6565b34801561069e57600080fd5b50610432600480360360208110156106b557600080fd5b50356120ce565b3480156106c857600080fd5b506103446120f8565b3480156106dd57600080fd5b506103446120fe565b3480156106f257600080fd5b50610380612104565b34801561070757600080fd5b506104326004803603602081101561071e57600080fd5b50356001600160a01b031661216e565b34801561073a57600080fd5b506103806004803603602081101561075157600080fd5b50356001600160a01b031661218f565b34801561076d57600080fd5b506104096125e3565b34801561078257600080fd5b506103446004803603606081101561079957600080fd5b50803590602081013590604001356125ec565b3480156107b857600080fd5b50610380600480360360208110156107cf57600080fd5b50356001600160a01b0316612603565b3480156107eb57600080fd5b5061034461270e565b34801561080057600080fd5b50610344612714565b34801561081557600080fd5b5061034461271a565b34801561082a57600080fd5b506103806004803603604081101561084157600080fd5b5080359060200135612720565b34801561085a57600080fd5b5061034461295d565b34801561086f57600080fd5b50610344612963565b34801561088457600080fd5b506103446004803603602081101561089b57600080fd5b50356001600160a01b0316612969565b3480156108b757600080fd5b50610344612a5c565b3480156108cc57600080fd5b50610432612a62565b3480156108e157600080fd5b50610409600480360360208110156108f857600080fd5b50356001600160a01b0316612a71565b34801561091457600080fd5b50610432612acb565b34801561092957600080fd5b50610344612ada565b34801561093e57600080fd5b506103806004803603602081101561095557600080fd5b50356001600160a01b0316612ae0565b34801561097157600080fd5b50610432612b2f565b34801561098657600080fd5b506104326004803603602081101561099d57600080fd5b5035612b3e565b3480156109b057600080fd5b50610344612b6d565b3480156109c557600080fd5b50610344612b73565b3480156109da57600080fd5b50610432612b79565b3480156109ef57600080fd5b50610344612b88565b348015610a0457600080fd5b50610344612b8e565b348015610a1957600080fd5b50610344612b94565b348015610a2e57600080fd5b50610a5560048036036020811015610a4557600080fd5b50356001600160a01b0316612b9a565b604080519586526020860194909452848401929092526001600160a01b0316606084015215156080830152519081900360a00190f35b348015610a9757600080fd5b5061038060048036036020811015610aae57600080fd5b5035612bd6565b348015610ac157600080fd5b5061034460048036036020811015610ad857600080fd5b50356001600160a01b0316612ce3565b348015610af457600080fd5b50610380600480360360c0811015610b0b57600080fd5b81359190810190604081016020820135600160201b811115610b2c57600080fd5b820183602082011115610b3e57600080fd5b803590602001918460018302840111600160201b83111715610b5f57600080fd5b919390929091602081019035600160201b811115610b7c57600080fd5b820183602082011115610b8e57600080fd5b803590602001918460208302840111600160201b83111715610baf57600080fd5b919350915080359060208101359060400135612d01565b348015610bd257600080fd5b5061034460048036036020811015610be957600080fd5b5035613065565b348015610bfc57600080fd5b5061043261308d565b348015610c1157600080fd5b5061034460048036036020811015610c2857600080fd5b503561309c565b348015610c3b57600080fd5b5061038060048036036040811015610c5257600080fd5b506001600160a01b03813581169160200135166130ae565b600080610c756120f8565b90506000805b82811015610d2157846001600160a01b0316639168ae72610c9b83612b3e565b6040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b158015610ce157600080fd5b505afa158015610cf5573d6000803e3d6000fd5b505050506040513d6020811015610d0b57600080fd5b505115610d19576001909101905b600101610c7b565b509150505b919050565b336000908152601d602052604090205460ff16610d7f576040805162461bcd60e51b815260206004820152600d60248201526c2727aa2fab20a624a220aa27a960991b604482015290519081900360640190fd5b610d87611fe1565b15610dc7576040805162461bcd60e51b81526020600482015260106024820152600080516020615480833981519152604482015290519081900360640190fd5b610dd033613162565b6000610dda611f92565b905080821015610de8578091505b610df233836131f9565b505050565b610dff612b6d565b811015610e45576040805162461bcd60e51b815260206004820152600f60248201526e1053149150511657d11150d2511151608a1b604482015290519081900360640190fd5b610e4d61271a565b811115610e90576040805162461bcd60e51b815260206004820152600c60248201526b1113d154d39517d1561254d560a21b604482015290519081900360640190fd5b50565b600c5481565b6001600160a01b03166000908152600a602052604090205490565b601e5443101590565b6011546001600160a01b031681565b6001600160a01b031660009081526008602052604090206001015490565b336000908152601d602052604090205460ff16610f3e576040805162461bcd60e51b815260206004820152600d60248201526c2727aa2fab20a624a220aa27a960991b604482015290519081900360640190fd5b610f46611fe1565b15610f86576040805162461bcd60e51b81526020600482015260106024820152600080516020615480833981519152604482015290519081900360640190fd5b610f8f336120a6565b610fcd576040805162461bcd60e51b815260206004820152600a6024820152691393d517d4d51052d15160b21b604482015290519081900360640190fd5b610fd5615351565b60408051808201909152611108908860026000835b8282101561102b5760408051606081810190925290808402860190600390839083908082843760009201919091525050508152600190910190602001610fea565b505060408051808201909152915089905060026000835b828210156110835760408051608081810190925290808402860190600490839083908082843760009201919091525050508152600190910190602001611042565b505050508787601160009054906101000a90046001600160a01b03166001600160a01b0316633dbcc8d16040518163ffffffff1660e01b815260040160206040518083038186803b1580156110d757600080fd5b505afa1580156110eb573d6000803e3d6000fd5b505050506040513d602081101561110157600080fd5b50516132bf565b805160e0015190915060009061112590439063ffffffff61330d16565b905060185481101561116b576040805162461bcd60e51b815260206004820152600a60248201526954494d455f44454c544160b01b604482015290519081900360640190fd5b60006111768361336a565b9050826000015161010001518360200151604001511015806111ab5750600e546111a790839063ffffffff61338616565b8110155b806111d7575082516060908101516020850151909101516064916111d5919063ffffffff61330d16565b145b611214576040805162461bcd60e51b81526020600482015260096024820152681513d3d7d4d350531360ba1b604482015290519081900360640190fd5b8251606090810151602085015190910151606491611238919063ffffffff61330d16565b111561127c576040805162461bcd60e51b815260206004820152600e60248201526d544f4f5f4d414e595f53454e445360901b604482015290519081900360640190fd5b6112a26004611296600e548561338690919063ffffffff16565b9063ffffffff61338616565b8111156112e2576040805162461bcd60e51b8152602060048201526009602482015268544f4f5f4c4152474560b81b604482015290519081900360640190fd5b505061133f81888886866040518060c0016040528061130033610ecc565b8152600c546020820152600e5460408201526011546001600160a01b039081166060830152601354811660808301526015541660a0909101528e6133df565b506113543361134c61271a565b600c54613a99565b5050505050505050565b336000908152601d602052604090205460ff166113b2576040805162461bcd60e51b815260206004820152600d60248201526c2727aa2fab20a624a220aa27a960991b604482015290519081900360640190fd5b6113ba611fe1565b156113fa576040805162461bcd60e51b81526020600482015260106024820152600080516020615480833981519152604482015290519081900360640190fd5b611403336120a6565b611441576040805162461bcd60e51b815260206004820152600a6024820152691393d517d4d51052d15160b21b604482015290519081900360640190fd5b8061144b8361309c565b1461148a576040805162461bcd60e51b815260206004820152600a6024820152694e4f44455f52454f524760b01b604482015290519081900360640190fd5b611492612b6d565b82101580156114a857506114a461271a565b8211155b6114f1576040805162461bcd60e51b81526020600482015260156024820152744e4f44455f4e554d5f4f55545f4f465f52414e474560581b604482015290519081900360640190fd5b60006114fc83611fb7565b9050806001600160a01b031663479c92546040518163ffffffff1660e01b815260040160206040518083038186803b15801561153757600080fd5b505afa15801561154b573d6000803e3d6000fd5b505050506040513d602081101561156157600080fd5b505161156c33610ecc565b146115b0576040805162461bcd60e51b815260206004820152600f60248201526e2727aa2fa9aa20a5a2a22fa82922ab60891b604482015290519081900360640190fd5b610df23384600c54613a99565b336000908152601d602052604090205460ff16611611576040805162461bcd60e51b815260206004820152600d60248201526c2727aa2fab20a624a220aa27a960991b604482015290519081900360640190fd5b611619611fe1565b15611659576040805162461bcd60e51b81526020600482015260106024820152600080516020615480833981519152604482015290519081900360640190fd5b610e908134613c32565b60185481565b336000908152601d602052604090205460ff166116bd576040805162461bcd60e51b815260206004820152600d60248201526c2727aa2fab20a624a220aa27a960991b604482015290519081900360640190fd5b6116c5611fe1565b15611705576040805162461bcd60e51b81526020600482015260106024820152600080516020615480833981519152604482015290519081900360640190fd5b602084013584351061174c576040805162461bcd60e51b815260206004820152600b60248201526a2ba927a723afa7a92222a960a91b604482015290519081900360640190fd5b61175461271a565b6020850135111561179b576040805162461bcd60e51b815260206004820152600c60248201526b1393d517d41493d413d4d15160a21b604482015290519081900360640190fd5b83356117a56120fe565b106117eb576040805162461bcd60e51b81526020600482015260116024820152701053149150511657d0d3d3919254935151607a1b604482015290519081900360640190fd5b60006117fd85825b6020020135611fb7565b9050600061180c8660016117f3565b9050806001600160a01b031663479c92546040518163ffffffff1660e01b815260040160206040518083038186803b15801561184757600080fd5b505afa15801561185b573d6000803e3d6000fd5b505050506040513d602081101561187157600080fd5b5051604080516311e7249560e21b815290516001600160a01b0385169163479c9254916004808301926020929190829003018186803b1580156118b357600080fd5b505afa1580156118c7573d6000803e3d6000fd5b505050506040513d60208110156118dd57600080fd5b50511461191d576040805162461bcd60e51b81526020600482015260096024820152682224a3232fa82922ab60b91b604482015290519081900360640190fd5b6119378760005b60200201356001600160a01b0316613162565b611942876001611924565b604080516348b4573960e11b81526001600160a01b03893581166004830152915191841691639168ae7291602480820192602092909190829003018186803b15801561198d57600080fd5b505afa1580156119a1573d6000803e3d6000fd5b505050506040513d60208110156119b757600080fd5b50516119ff576040805162461bcd60e51b815260206004820152601260248201527114d51052d1548c57d393d517d4d51052d15160721b604482015290519081900360640190fd5b604080516348b4573960e11b81526001600160a01b0360208a81013582166004840152925190841692639168ae729260248082019391829003018186803b158015611a4957600080fd5b505afa158015611a5d573d6000803e3d6000fd5b505050506040513d6020811015611a7357600080fd5b5051611abb576040805162461bcd60e51b815260206004820152601260248201527114d51052d1548c97d393d517d4d51052d15160721b604482015290519081900360640190fd5b611ad0853585358560005b6020020135613ce1565b826001600160a01b0316635b8b22806040518163ffffffff1660e01b815260040160206040518083038186803b158015611b0957600080fd5b505afa158015611b1d573d6000803e3d6000fd5b505050506040513d6020811015611b3357600080fd5b505114611b74576040805162461bcd60e51b815260206004820152600a6024820152694348414c5f484153483160b01b604482015290519081900360640190fd5b611b8960208087013590860135856001611ac6565b816001600160a01b0316635b8b22806040518163ffffffff1660e01b815260040160206040518083038186803b158015611bc257600080fd5b505afa158015611bd6573d6000803e3d6000fd5b505050506040513d6020811015611bec57600080fd5b505114611c2d576040805162461bcd60e51b815260206004820152600a60248201526921a420a62fa420a9a41960b11b604482015290519081900360640190fd5b6000611da7611cca600d54611cbe88600060028110611c4857fe5b6020020135876001600160a01b0316632edfb42a6040518163ffffffff1660e01b815260040160206040518083038186803b158015611c8657600080fd5b505afa158015611c9a573d6000803e3d6000fd5b505050506040513d6020811015611cb057600080fd5b50519063ffffffff61330d16565b9063ffffffff613d1816565b611d37856001600160a01b031663479c92546040518163ffffffff1660e01b815260040160206040518083038186803b158015611d0657600080fd5b505afa158015611d1a573d6000803e3d6000fd5b505050506040513d6020811015611d3057600080fd5b5051611fb7565b6001600160a01b031663d7ff5e356040518163ffffffff1660e01b815260040160206040518083038186803b158015611d6f57600080fd5b505afa158015611d83573d6000803e3d6000fd5b505050506040513d6020811015611d9957600080fd5b50519063ffffffff613d1816565b90506020850135811015611de157611dd96001600160a01b0389351689600160200201356001600160a01b0316613d72565b505050611f8b565b6014546000906001600160a01b0390811690638ecaab119030908a35908935908e35168e600160200201356001600160a01b0316611e398d600060028110611e2557fe5b60200201358a61330d90919063ffffffff16565b611e538e600160200201358b61330d90919063ffffffff16565b601154601054604080516001600160e01b031960e08d901b1681526001600160a01b039a8b166004820152602481019990995260448901979097529488166064880152928716608487015260a486019190915260c4850152841660e484015290921661010482015290516101248083019260209291908290030181600087803b158015611edf57600080fd5b505af1158015611ef3573d6000803e3d6000fd5b505050506040513d6020811015611f0957600080fd5b50519050611f326001600160a01b038a35168a600160200201356001600160a01b031683613df9565b604080516001600160a01b038b35811682526020808d01358216908301528a35828401529151918316917fa5256d19d4ddaf646f4b5c1861b8d4c08238e6356b8ae36dcc49ac67fda758799181900360600190a2505050505b5050505050565b600080611f9d612b6d565b9050611fb14382611fac61271a565b613e43565b91505090565b6000908152600560205260409020546001600160a01b031690565b6017546001600160a01b031681565b600b5460ff1690565b6014546001600160a01b031681565b600e5490565b336000908152601d602052604090205460ff16612053576040805162461bcd60e51b815260206004820152600d60248201526c2727aa2fab20a624a220aa27a960991b604482015290519081900360640190fd5b61205b611fe1565b1561209b576040805162461bcd60e51b81526020600482015260106024820152600080516020615480833981519152604482015290519081900360640190fd5b6120a4346140fa565b565b6001600160a01b0316600090815260086020526040902060030154600160a01b900460ff1690565b6000600782815481106120dd57fe5b6000918252602090912001546001600160a01b031692915050565b60095490565b60015490565b600061210e612b6d565b90506121186120fe565b8111801561212d575061212961271a565b8111155b610e90576040805162461bcd60e51b815260206004820152600d60248201526c1393d7d553949154d3d3159151609a1b604482015290519081900360640190fd5b6001600160a01b039081166000908152600860205260409020600301541690565b336000908152601d602052604090205460ff166121e3576040805162461bcd60e51b815260206004820152600d60248201526c2727aa2fab20a624a220aa27a960991b604482015290519081900360640190fd5b6121eb611fe1565b1561222b576040805162461bcd60e51b81526020600482015260106024820152600080516020615480833981519152604482015290519081900360640190fd5b612233612104565b600061223d6120fe565b90506000612249612b6d565b9050600061225682611fb7565b905082816001600160a01b031663479c92546040518163ffffffff1660e01b815260040160206040518083038186803b15801561229257600080fd5b505afa1580156122a6573d6000803e3d6000fd5b505050506040513d60208110156122bc57600080fd5b50511415612545576122cd846120a6565b61230b576040805162461bcd60e51b815260206004820152600a6024820152691393d517d4d51052d15160b21b604482015290519081900360640190fd5b61231c61231785610ecc565b610df7565b806001600160a01b0316639168ae72856040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b15801561237257600080fd5b505afa158015612386573d6000803e3d6000fd5b505050506040513d602081101561239c57600080fd5b5051156123e3576040805162461bcd60e51b815260206004820152601060248201526f14d51052d15117d3d397d5105491d15560821b604482015290519081900360640190fd5b806001600160a01b03166388d221c66040518163ffffffff1660e01b815260040160006040518083038186803b15801561241c57600080fd5b505afa158015612430573d6000803e3d6000fd5b5050505061243d83611fb7565b6001600160a01b0316633aa192746040518163ffffffff1660e01b815260040160006040518083038186803b15801561247557600080fd5b505afa158015612489573d6000803e3d6000fd5b505050506124976000612bd6565b6124a081610c6a565b816001600160a01b031663dff697876040518163ffffffff1660e01b815260040160206040518083038186803b1580156124d957600080fd5b505afa1580156124ed573d6000803e3d6000fd5b505050506040513d602081101561250357600080fd5b505114612545576040805162461bcd60e51b815260206004820152600b60248201526a4841535f5354414b45525360a81b604482015290519081900360640190fd5b61254d614306565b60135460408051630c2a09ad60e21b81526004810185905290516001600160a01b03909216916330a826b49160248082019260009290919082900301818387803b15801561259a57600080fd5b505af11580156125ae573d6000803e3d6000fd5b50506040518492507f9f7eee12f08e41a1d1a617e76576aa2d6a1e06dbdd72d817e62b6e8dfdebe2a39150600090a250505050565b60005460ff1690565b60006125f9848484613e43565b90505b9392505050565b336000908152601d602052604090205460ff16612657576040805162461bcd60e51b815260206004820152600d60248201526c2727aa2fab20a624a220aa27a960991b604482015290519081900360640190fd5b61265f610eb4565b6126ab5761266b611fe1565b156126ab576040805162461bcd60e51b81526020600482015260106024820152600080516020615480833981519152604482015290519081900360640190fd5b6126b36120fe565b6126bc82610ecc565b11156126fc576040805162461bcd60e51b815260206004820152600a6024820152691513d3d7d49150d1539560b21b604482015290519081900360640190fd5b61270581613162565b610e908161431c565b600f5481565b600d5481565b60035490565b336000908152601d602052604090205460ff16612774576040805162461bcd60e51b815260206004820152600d60248201526c2727aa2fab20a624a220aa27a960991b604482015290519081900360640190fd5b61277c611fe1565b156127bc576040805162461bcd60e51b81526020600482015260106024820152600080516020615480833981519152604482015290519081900360640190fd5b6127c46120f8565b821115612809576040805162461bcd60e51b815260206004820152600e60248201526d4e4f5f535543485f5a4f4d42494560901b604482015290519081900360640190fd5b600061281483612b3e565b9050600061282184613065565b905060008061282e612b6d565b90505b80831015801561284057508482105b1561293557600061285084611fb7565b9050806001600160a01b03166396a9fdc0866040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b03168152602001915050600060405180830381600087803b1580156128aa57600080fd5b505af11580156128be573d6000803e3d6000fd5b50505050806001600160a01b031663479c92546040518163ffffffff1660e01b815260040160206040518083038186803b1580156128fb57600080fd5b505afa15801561290f573d6000803e3d6000fd5b505050506040513d602081101561292557600080fd5b5051935050600190910190612831565b8083101561294b5761294686614382565b612955565b612955868461441e565b505050505050565b601a5481565b601e5481565b336000908152601d602052604081205460ff166129bd576040805162461bcd60e51b815260206004820152600d60248201526c2727aa2fab20a624a220aa27a960991b604482015290519081900360640190fd5b6129c5610eb4565b612a11576129d1611fe1565b15612a11576040805162461bcd60e51b81526020600482015260106024820152600080516020615480833981519152604482015290519081900360640190fd5b6000612a1c33614445565b6040519091506001600160a01b0384169082156108fc029083906000818181858888f19350505050158015612a55573d6000803e3d6000fd5b5092915050565b60045490565b6016546001600160a01b031681565b6000805b600954811015612ac25760098181548110612a8c57fe5b60009182526020909120600290910201546001600160a01b0384811691161415612aba576001915050610d26565b600101612a75565b50600092915050565b6013546001600160a01b031681565b61a4b190565b6001600160a01b03811615610e90576040805162461bcd60e51b815260206004820152601060248201526f1393d7d513d2d15397d0531313d5d15160821b604482015290519081900360640190fd5b6012546001600160a01b031681565b600060098281548110612b4d57fe5b60009182526020909120600290910201546001600160a01b031692915050565b60025490565b600e5481565b6015546001600160a01b031681565b601b5481565b60075490565b60195481565b6008602052600090815260409020805460018201546002830154600390930154919290916001600160a01b03811690600160a01b900460ff1685565b336000908152601d602052604090205460ff16612c2a576040805162461bcd60e51b815260206004820152600d60248201526c2727aa2fab20a624a220aa27a960991b604482015290519081900360640190fd5b612c32610eb4565b612c7e57612c3e611fe1565b15612c7e576040805162461bcd60e51b81526020600482015260106024820152600080516020615480833981519152604482015290519081900360640190fd5b6000612c886120f8565b90506000612c94612b6d565b9050825b82811015612cdd575b81612cab82613065565b1015612cd557612cba81614382565b60001990920191828110612cd057505050610e90565b612ca1565b600101612c98565b50505050565b6001600160a01b031660009081526008602052604090206002015490565b336000908152601d602052604090205460ff16612d55576040805162461bcd60e51b815260206004820152600d60248201526c2727aa2fab20a624a220aa27a960991b604482015290519081900360640190fd5b612d5d610eb4565b612da957612d69611fe1565b15612da9576040805162461bcd60e51b81526020600482015260106024820152600080516020615480833981519152604482015290519081900360640190fd5b612db1612104565b6000612dbb612b8e565b11612dfa576040805162461bcd60e51b815260206004820152600a6024820152694e4f5f5354414b45525360b01b604482015290519081900360640190fd5b6000612e0c612e07612b6d565b611fb7565b9050806001600160a01b03166388d221c66040518163ffffffff1660e01b815260040160006040518083038186803b158015612e4757600080fd5b505afa158015612e5b573d6000803e3d6000fd5b50505050612e6a612e076120fe565b6001600160a01b0316633aa192746040518163ffffffff1660e01b815260040160006040518083038186803b158015612ea257600080fd5b505afa158015612eb6573d6000803e3d6000fd5b50505050612ec26120fe565b816001600160a01b031663479c92546040518163ffffffff1660e01b815260040160206040518083038186803b158015612efb57600080fd5b505afa158015612f0f573d6000803e3d6000fd5b505050506040513d6020811015612f2557600080fd5b505114612f68576040805162461bcd60e51b815260206004820152600c60248201526b24a72b20a624a22fa82922ab60a11b604482015290519081900360640190fd5b612f726000612bd6565b612f86612f7e82610c6a565b611cbe612b8e565b816001600160a01b031663dff697876040518163ffffffff1660e01b815260040160206040518083038186803b158015612fbf57600080fd5b505afa158015612fd3573d6000803e3d6000fd5b505050506040513d6020811015612fe957600080fd5b50511461302e576040805162461bcd60e51b815260206004820152600e60248201526d1393d517d0531317d4d51052d15160921b604482015290519081900360640190fd5b60125460135461305a918b918b918b918b918b918b918b918b916001600160a01b0390811691166144a8565b505050505050505050565b60006009828154811061307457fe5b9060005260206000209060020201600101549050919050565b6010546001600160a01b031681565b60009081526006602052604090205490565b6130b6611fe1565b156130f6576040805162461bcd60e51b81526020600482015260106024820152600080516020615480833981519152604482015290519081900360640190fd5b61310082826144c9565b6001600160a01b0316336001600160a01b031614613154576040805162461bcd60e51b815260206004820152600c60248201526b2ba927a723afa9a2a72222a960a11b604482015290519081900360640190fd5b61315e8282613d72565b5050565b61316b816120a6565b6131a9576040805162461bcd60e51b815260206004820152600a6024820152691393d517d4d51052d15160b21b604482015290519081900360640190fd5b60006131b48261216e565b6001600160a01b031614610e90576040805162461bcd60e51b8152602060048201526007602482015266125397d0d2105360ca1b604482015290519081900360640190fd5b6001600160a01b038216600090815260086020526040812060028101548084111561325e576040805162461bcd60e51b815260206004820152601060248201526f544f4f5f4c4954544c455f5354414b4560801b604482015290519081900360640190fd5b6000613270828663ffffffff61330d16565b600284018690559050613283868261458f565b604080518381526020810187905281516001600160a01b0389169260008051602061543f833981519152928290030190a2925050505b92915050565b6132c7615351565b604080518082019091528651865182916132e291888861461a565b815260200161330188600160200201518860016020020151438761461a565b90529695505050505050565b600082821115613364576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b8051516020820151516000916132b9919063ffffffff61330d16565b600082613395575060006132b9565b828202828482816133a257fe5b04146125fc5760405162461bcd60e51b815260040180806020018281038252602181526020018061545f6021913960400191505060405180910390fd5b60006133e9615376565b6133f28961336a565b60e0820152835161340290611fb7565b81606001906001600160a01b031690816001600160a01b03168152505083606001516001600160a01b0316633dbcc8d16040518163ffffffff1660e01b815260040160206040518083038186803b15801561345c57600080fd5b505afa158015613470573d6000803e3d6000fd5b505050506040513d602081101561348657600080fd5b5051815260608101516040805163380ed4c760e11b815290516001600160a01b039092169163701da98e91600480820192602092909190829003018186803b1580156134d157600080fd5b505afa1580156134e5573d6000803e3d6000fd5b505050506040513d60208110156134fb57600080fd5b50518951613508906146b8565b1461354c576040805162461bcd60e51b815260206004820152600f60248201526e0a0a48aacbea6a882a88abe9082a69608b1b604482015290519081900360640190fd5b805160208a015160400151111561359b576040805162461bcd60e51b815260206004820152600e60248201526d12539093d617d41054d517d1539160921b604482015290519081900360640190fd5b83606001516001600160a01b031663dc1b7b1f87878c60200151604001516040518463ffffffff1660e01b815260040180806020018381526020018281038252858582818152602001925080828437600081840152601f19601f820116905080830192505050945050505050604080518083038186803b15801561361e57600080fd5b505afa158015613632573d6000803e3d6000fd5b505050506040513d604081101561364857600080fd5b5080516020909101516101208301526101008201526136668961474d565b81604001818152505061368b84604001518260e001518660200151846060015161477e565b8160c0018181525050600081606001516001600160a01b031663f0dd77ff6040518163ffffffff1660e01b815260040160206040518083038186803b1580156136d357600080fd5b505afa1580156136e7573d6000803e3d6000fd5b505050506040513d60208110156136fd57600080fd5b50511160a08201819052156137875761377d81606001516001600160a01b031663f0dd77ff6040518163ffffffff1660e01b815260040160206040518083038186803b15801561374c57600080fd5b505afa158015613760573d6000803e3d6000fd5b505050506040513d602081101561377657600080fd5b505161309c565b6080820152613798565b83516137929061309c565b60808201525b8360a001516001600160a01b031663d45ab2b56137b88b602001516146b8565b6137c78c8560400151436148ec565b6137d08d614901565b88600001518660c001516040518663ffffffff1660e01b81526004018086815260200185815260200184815260200183815260200182815260200195505050505050602060405180830381600087803b15801561382c57600080fd5b505af1158015613840573d6000803e3d6000fd5b505050506040513d602081101561385657600080fd5b50516001600160a01b03166020820152600061387061271a565b600101905081606001516001600160a01b0316631bc09d0a826040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b1580156138bf57600080fd5b505af11580156138d3573d6000803e3d6000fd5b505050506138f48260a0015183608001518460400151856101200151614931565b9250838314613941576040805162461bcd60e51b81526020600482015260146024820152730aa9c8ab0a08a86a88a88be9c9e888abe9082a6960631b604482015290519081900360640190fd5b61394f826020015184614998565b6080850151855160c084015160408051638b8ca19960e01b81526004810186905260248101939093526044830191909152336064830152516001600160a01b0390921691638b8ca1999160848082019260009290919082900301818387803b1580156139ba57600080fd5b505af11580156139ce573d6000803e3d6000fd5b50505050506139e0846000015161309c565b6139e861271a565b7f8016306209aff73e79f274cf38a41928996f746e2953111902e1f55be1713a5484846040015185600001518661010001518761012001518f8f6040518088815260200187815260200186815260200185815260200184815260200183600260600280828437600083820152601f01601f191690910190508261010080828437600083820152604051601f909101601f1916909201829003995090975050505050505050a350979650505050505050565b6001600160a01b0380841660008181526008602090815260408083208784526005835281842054825163123334b760e11b815260048101969096529151909591909116938492632466696e9260248084019382900301818787803b158015613b0057600080fd5b505af1158015613b14573d6000803e3d6000fd5b505050506040513d6020811015613b2a57600080fd5b5051600180850187905590915081141561295557600060056000846001600160a01b031663479c92546040518163ffffffff1660e01b815260040160206040518083038186803b158015613b7d57600080fd5b505afa158015613b91573d6000803e3d6000fd5b505050506040513d6020811015613ba757600080fd5b505181526020810191909152604001600020546001600160a01b0316905080636971dfe5613bdb438863ffffffff613d1816565b6040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b158015613c1157600080fd5b505af1158015613c25573d6000803e3d6000fd5b5050505050505050505050565b336000908152601d602052604090205460ff16613c86576040805162461bcd60e51b815260206004820152600d60248201526c2727aa2fab20a624a220aa27a960991b604482015290519081900360640190fd5b613c8e611fe1565b15613cce576040805162461bcd60e51b81526020600482015260106024820152600080516020615480833981519152604482015290519081900360640190fd5b613cd782613162565b61315e82826149e2565b6040805160208082019590955280820193909352606080840192909252805180840390920182526080909201909152805191012090565b6000828201838110156125fc576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6000613d7d82612ce3565b90506000613d8a84612ce3565b905080821115613db157613dae613da184836131f9565b839063ffffffff61330d16565b91505b60028204613dbf85826149e2565b613dcf838263ffffffff61330d16565b9250613dda85614a56565b601654613df0906001600160a01b03168461458f565b611f8b84614a80565b6001600160a01b03928316600090815260086020526040808220600390810180549487166001600160a01b0319958616811790915594909516825290209092018054909216179055565b600081600184031415613e595750600f546125fc565b6000613e6484611fb7565b6001600160a01b0316632edfb42a6040518163ffffffff1660e01b815260040160206040518083038186803b158015613e9c57600080fd5b505afa158015613eb0573d6000803e3d6000fd5b505050506040513d6020811015613ec657600080fd5b5051905080851015613edc575050600f546125fc565b613ee46153ca565b506040805161014081018252600181526201e05b60208201526201f7d191810191909152620138916060820152620329e160808201526201be4360a08201526204cb8c60c08201526201fbc460e082015262036d3261010082015262027973610120820152613f516153ca565b506040805161014081018252600181526201c03060208201526201b6999181019190915261fde26060820152620265c6608082015262013b8e60a0820152620329e160c08201526201389160e08201526201f7d1610100820152620153756101208201526000613fc7888563ffffffff61330d16565b90506000613ff1600c54613fe5600a8561338690919063ffffffff16565b9063ffffffff614b3016565b905060ff61400682600a63ffffffff614b3016565b1061401a57600019955050505050506125fc565b600061402d82600a63ffffffff614b3016565b60020a9050600085600a8406600a811061404357fe5b602002015162ffffff168202905085600a8406600a811061406057fe5b602002015162ffffff1682828161407357fe5b041461408a576000199750505050505050506125fc565b60006140b586600a8606600a811061409e57fe5b6020020151839062ffffff1663ffffffff614b3016565b9050806140c0575060015b600f5480820290829082816140d157fe5b04146140ea5760001999505050505050505050506125fc565b9c9b505050505050505050505050565b336000908152601d602052604090205460ff1661414e576040805162461bcd60e51b815260206004820152600d60248201526c2727aa2fab20a624a220aa27a960991b604482015290519081900360640190fd5b614156611fe1565b15614196576040805162461bcd60e51b81526020600482015260106024820152600080516020615480833981519152604482015290519081900360640190fd5b61419f336120a6565b156141e2576040805162461bcd60e51b815260206004820152600e60248201526d1053149150511657d4d51052d15160921b604482015290519081900360640190fd5b6141eb33612a71565b15614230576040805162461bcd60e51b815260206004820152601060248201526f5354414b45525f49535f5a4f4d42494560801b604482015290519081900360640190fd5b614238611f92565b81101561427f576040805162461bcd60e51b815260206004820152601060248201526f4e4f545f454e4f5547485f5354414b4560801b604482015290519081900360640190fd5b6142893382614b97565b6013546001600160a01b031663f03c04a5336142a36120fe565b6040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050600060405180830381600087803b1580156142f257600080fd5b505af1158015611f8b573d6000803e3d6000fd5b614311600254614c90565b600280546001019055565b6001600160a01b03811660009081526008602052604090206002810154614343838261458f565b61434c83614d12565b604080518281526000602082015281516001600160a01b0386169260008051602061543f833981519152928290030190a2505050565b60098054600019810190811061439457fe5b9060005260206000209060020201600982815481106143af57fe5b60009182526020909120825460029092020180546001600160a01b0319166001600160a01b0390921691909117815560019182015491015560098054806143f257fe5b60008281526020812060026000199093019283020180546001600160a01b031916815560010155905550565b806009838154811061442c57fe5b9060005260206000209060020201600101819055505050565b6001600160a01b0381166000818152600a60209081526040808320805490849055815181815292830184905281519394909390927fa740af14c56e4e04a617b1de1eb20de73270decbaaead14f142aabf3038e5ae292908290030190a292915050565b6144bd6002548b8b8b8b8b8b8b8b8b8b614e38565b50505050505050505050565b6001600160a01b03808316600090815260086020526040808220848416835290822060038201549293919290911680614533576040805162461bcd60e51b81526020600482015260076024820152661393d7d0d2105360ca1b604482015290519081900360640190fd5b60038201546001600160a01b03828116911614614586576040805162461bcd60e51b815260206004820152600c60248201526b1112519197d25397d0d2105360a21b604482015290519081900360640190fd5b95945050505050565b6001600160a01b0382166000908152600a6020526040812054906145b9828463ffffffff613d1816565b6001600160a01b0385166000818152600a60209081526040918290208490558151868152908101849052815193945091927fa740af14c56e4e04a617b1de1eb20de73270decbaaead14f142aabf3038e5ae29281900390910190a250505050565b6146226153e9565b60408051610120810182528551815286516020820152908101856001602002015181526020018560026004811061465557fe5b602002015181526020018560036004811061466c57fe5b602002015181526020018660016003811061468357fe5b602002015181526020018660026003811061469a57fe5b60200201518152602001848152602001838152509050949350505050565b6000816000015182602001518360400151846060015185608001518660a001518760c001518860e00151896101000151604051602001808a81526020018981526020018881526020018781526020018681526020018581526020018481526020018381526020018281526020019950505050505050505050604051602081830303815290604052805190602001209050919050565b805180516020830151516000926132b992918290039061476c90615109565b6147798660200151615109565b61513e565b6000806147a686613fe561479982600163ffffffff61330d16565b889063ffffffff613d1816565b905061482981611cbe6147bf438863ffffffff613d1816565b866001600160a01b0316632edfb42a6040518163ffffffff1660e01b815260040160206040518083038186803b1580156147f857600080fd5b505afa15801561480c573d6000803e3d6000fd5b505050506040513d602081101561482257600080fd5b505161517c565b91506000836001600160a01b031663f0dd77ff6040518163ffffffff1660e01b815260040160206040518083038186803b15801561486657600080fd5b505afa15801561487a573d6000803e3d6000fd5b505050506040513d602081101561489057600080fd5b5051905080156148e2576148df836148a783611fb7565b6001600160a01b0316632edfb42a6040518163ffffffff1660e01b815260040160206040518083038186803b1580156147f857600080fd5b92505b5050949350505050565b60006125f98383866020015160400151613ce1565b805160a09081015160208301519182015160c083015160608401516080909401516000946132b994939291615192565b60008085614940576000614943565b60015b905080858585604051602001808560ff1660ff1660f81b815260010184815260200183815260200182815260200194505050505060405160208183030381529060405280519060200120915050949350505050565b60038054600101808255600090815260056020908152604080832080546001600160a01b0319166001600160a01b0397909716969096179095559154815260069091529190912055565b6001600160a01b038216600090815260086020526040812060028101549091614a11828563ffffffff613d1816565b60028401819055604080518481526020810183905281519293506001600160a01b0388169260008051602061543f833981519152929181900390910190a25050505050565b6001600160a01b0316600090815260086020526040902060030180546001600160a01b0319169055565b6001600160a01b0381811660008181526008602090815260408083208151808301909252938152600180850154928201928352600980549182018155909352517f6e1540171b6c0c960b71a7020d9f60077f6af931a8bbf590da0223dacf75c7af600290930292830180546001600160a01b031916919095161790935591517f6e1540171b6c0c960b71a7020d9f60077f6af931a8bbf590da0223dacf75c7b09092019190915561315e82614d12565b6000808211614b86576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b818381614b8f57fe5b049392505050565b6007805460018082019092557fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c688810180546001600160a01b038087166001600160a01b031992831681179093556040805160a081018252858152865460208281019182528284018a8152600060608501818152608086018c81528a8352600885528783209651875594519b86019b909b559051600285015598516003909301805492511515600160a01b0260ff60a01b199490961692909616919091179190911692909217909255436004558151948552840185905280519293919260008051602061543f8339815191529281900390910190a2505050565b60008181526005602052604080822054815163083197ef60e41b815291516001600160a01b03909116926383197ef0926004808201939182900301818387803b158015614cdc57600080fd5b505af1158015614cf0573d6000803e3d6000fd5b50505060009182525060056020526040902080546001600160a01b0319169055565b6001600160a01b03811660009081526008602052604090208054600780546000198101908110614d3e57fe5b600091825260209091200154600780546001600160a01b039092169183908110614d6457fe5b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550806008600060078481548110614da457fe5b60009182526020808320909101546001600160a01b031683528201929092526040019020556007805480614dd457fe5b60008281526020808220830160001990810180546001600160a01b03191690559092019092556001600160a01b03949094168152600890935250506040812081815560018101829055600281019190915560030180546001600160a81b0319169055565b6000614eb98a8a8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020808e0282810182019093528d82529093508d92508c918291850190849080828437600081840152601f19601f820116905080830192505050505050508d6151d9565b90506000614ec68d611fb7565b9050614ed58c83888a89615192565b816001600160a01b03166397bdc5106040518163ffffffff1660e01b815260040160206040518083038186803b158015614f0e57600080fd5b505afa158015614f22573d6000803e3d6000fd5b505050506040513d6020811015614f3857600080fd5b505114614f7b576040805162461bcd60e51b815260206004820152600c60248201526b434f4e4649524d5f4441544160a01b604482015290519081900360640190fd5b836001600160a01b0316630c7268478c8c8c8c6040518563ffffffff1660e01b81526004018080602001806020018381038352878782818152602001925080828437600083820152601f01601f19169091018481038352858152602090810191508690860280828437600081840152601f19601f8201169050808301925050509650505050505050600060405180830381600087803b15801561501d57600080fd5b505af1158015615031573d6000803e3d6000fd5b50505050615040600154614c90565b60018d81558d01600255604080516316b9109b60e01b8152600481018f905290516001600160a01b038516916316b9109b91602480830192600092919082900301818387803b15801561509257600080fd5b505af11580156150a6573d6000803e3d6000fd5b505050508c7f2400bd6e429cfcd98fe43a75bbbe4702c59c99d636100690130cc1ebb611c5a2838989896040518085815260200184815260200183815260200182815260200194505050505060405180910390a250505050505050505050505050565b60006132b98260000151615139846040015185602001518660a0015187606001518860c0015189608001516152da565b615325565b604080516020808201969096528082019490945260608401929092526080808401919091528151808403909101815260a09092019052805191012090565b600081831161518b57816125fc565b5090919050565b60408051602080820197909752808201959095526060850192909252608084019290925260a0808401929092528051808403909201825260c0909201909152805191012090565b81518351600091829184835b8381101561528c5760008882815181106151fb57fe5b6020026020010151905083818701111561524b576040805162461bcd60e51b815260206004820152600c60248201526b2220aa20afa7ab22a9292aa760a11b604482015290519081900360640190fd5b6020868b01810182902060408051808401969096528581019190915280518086038201815260609095019052835193019290922091909401936001016151e5565b508184146152cf576040805162461bcd60e51b815260206004820152600b60248201526a08882a882be988a9c8ea8960ab1b604482015290519081900360640190fd5b979650505050505050565b60408051602080820198909852808201969096526060860194909452608085019290925260a084015260c0808401919091528151808403909101815260e09092019052805191012090565b604080516020808201949094528082019290925280518083038201815260609092019052805191012090565b60405180604001604052806153646153e9565b81526020016153716153e9565b905290565b6040805161014081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081019190915290565b604051806101400160405280600a906020820280368337509192915050565b604051806101200160405280600081526020016000801916815260200160008152602001600081526020016000815260200160008019168152602001600080191681526020016000815260200160008152509056feebd093d389ab57f3566918d2c379a2b4d9539e8eb95efad9d5e465457833fde6536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f775061757361626c653a2070617573656400000000000000000000000000000000a26469706673582212208c3d38675521346566e8f28939516bbd5f14bb6d5eb606cf9443f07198e6875464736f6c634300060b0033

Deployed Bytecode

0x60806040526004361061030c5760003560e01c80637427be511161019c578063d01e6602116100e2578063e8bd492211610090578063e8bd492214610a22578063edfd03ed14610a8b578063ef40a67014610ab5578063f31d863f14610ae8578063f33e1fac14610bc6578063f51de41b14610bf0578063f8d1f19414610c05578063fa7803e614610c2f5761030c565b8063d01e66021461097a578063d735e21d146109a4578063d7445bc8146109b9578063d93fe9c4146109ce578063dc72a33b146109e3578063dff69787146109f8578063e4781e1014610a0d5761030c565b806381fbc98a1161014a57806381fbc98a146108785780638640ce5f146108ab5780638da5cb5b146108c057806391c657e8146108d55780639e8a713f14610908578063a8929e0b1461091d578063c4d66de814610932578063ce11e6ab146109655761030c565b80637427be51146107ac57806376e7e23b146107df578063771b2f97146107f45780637ba9534a146108095780637e2d21551461081e5780637f4320ce1461084e5780637f60abbb146108635761030c565b80634f0f4aa91161026157806362a82d7d1161020f57806362a82d7d1461069257806363721d6b146106bc57806365f7f80d146106d157806367425daf146106e657806369fd251c146106fb5780636b94c33b1461072e5780636f791d29146107615780636f7d0026146107765761030c565b80634f0f4aa9146105d957806351ed6a30146106035780635c975abb146106185780635dbaf68b1461062d5780635e8ef106146106425780635f576db6146106575780636177fd181461065f5761030c565b80633e96576e116102be5780633e96576e1461044e5780633fe3862714610481578063414f23fe1461051e57806345c5b2c71461054e57806345e38b6414610574578063488ed1a9146105895780634d26732d146105c45761030c565b806304a28064146103115780631e83d30f146103565780632b2af0ab146103825780632e7acfa6146103ac5780632f30cabd146103c1578063313a04fa146103f45780633e55c0c71461041d575b600080fd5b34801561031d57600080fd5b506103446004803603602081101561033457600080fd5b50356001600160a01b0316610c6a565b60408051918252519081900360200190f35b34801561036257600080fd5b506103806004803603602081101561037957600080fd5b5035610d2b565b005b34801561038e57600080fd5b50610380600480360360208110156103a557600080fd5b5035610df7565b3480156103b857600080fd5b50610344610e93565b3480156103cd57600080fd5b50610344600480360360208110156103e457600080fd5b50356001600160a01b0316610e99565b34801561040057600080fd5b50610409610eb4565b604080519115158252519081900360200190f35b34801561042957600080fd5b50610432610ebd565b604080516001600160a01b039092168252519081900360200190f35b34801561045a57600080fd5b506103446004803603602081101561047157600080fd5b50356001600160a01b0316610ecc565b34801561048d57600080fd5b5061038060048036036102408110156104a557600080fd5b813591602081019160e08201916101e08101359161020082013591908101906102408101610220820135600160201b8111156104e057600080fd5b8201836020820111156104f257600080fd5b803590602001918460018302840111600160201b8311171561051357600080fd5b509092509050610eea565b34801561052a57600080fd5b506103806004803603604081101561054157600080fd5b508035906020013561135e565b6103806004803603602081101561056457600080fd5b50356001600160a01b03166115bd565b34801561058057600080fd5b50610344611663565b34801561059557600080fd5b5061038060048036036101408110156105ad57600080fd5b50604081016080820160c083016101008401611669565b3480156105d057600080fd5b50610344611f92565b3480156105e557600080fd5b50610432600480360360208110156105fc57600080fd5b5035611fb7565b34801561060f57600080fd5b50610432611fd2565b34801561062457600080fd5b50610409611fe1565b34801561063957600080fd5b50610432611fea565b34801561064e57600080fd5b50610344611ff9565b610380611fff565b34801561066b57600080fd5b506104096004803603602081101561068257600080fd5b50356001600160a01b03166120a6565b34801561069e57600080fd5b50610432600480360360208110156106b557600080fd5b50356120ce565b3480156106c857600080fd5b506103446120f8565b3480156106dd57600080fd5b506103446120fe565b3480156106f257600080fd5b50610380612104565b34801561070757600080fd5b506104326004803603602081101561071e57600080fd5b50356001600160a01b031661216e565b34801561073a57600080fd5b506103806004803603602081101561075157600080fd5b50356001600160a01b031661218f565b34801561076d57600080fd5b506104096125e3565b34801561078257600080fd5b506103446004803603606081101561079957600080fd5b50803590602081013590604001356125ec565b3480156107b857600080fd5b50610380600480360360208110156107cf57600080fd5b50356001600160a01b0316612603565b3480156107eb57600080fd5b5061034461270e565b34801561080057600080fd5b50610344612714565b34801561081557600080fd5b5061034461271a565b34801561082a57600080fd5b506103806004803603604081101561084157600080fd5b5080359060200135612720565b34801561085a57600080fd5b5061034461295d565b34801561086f57600080fd5b50610344612963565b34801561088457600080fd5b506103446004803603602081101561089b57600080fd5b50356001600160a01b0316612969565b3480156108b757600080fd5b50610344612a5c565b3480156108cc57600080fd5b50610432612a62565b3480156108e157600080fd5b50610409600480360360208110156108f857600080fd5b50356001600160a01b0316612a71565b34801561091457600080fd5b50610432612acb565b34801561092957600080fd5b50610344612ada565b34801561093e57600080fd5b506103806004803603602081101561095557600080fd5b50356001600160a01b0316612ae0565b34801561097157600080fd5b50610432612b2f565b34801561098657600080fd5b506104326004803603602081101561099d57600080fd5b5035612b3e565b3480156109b057600080fd5b50610344612b6d565b3480156109c557600080fd5b50610344612b73565b3480156109da57600080fd5b50610432612b79565b3480156109ef57600080fd5b50610344612b88565b348015610a0457600080fd5b50610344612b8e565b348015610a1957600080fd5b50610344612b94565b348015610a2e57600080fd5b50610a5560048036036020811015610a4557600080fd5b50356001600160a01b0316612b9a565b604080519586526020860194909452848401929092526001600160a01b0316606084015215156080830152519081900360a00190f35b348015610a9757600080fd5b5061038060048036036020811015610aae57600080fd5b5035612bd6565b348015610ac157600080fd5b5061034460048036036020811015610ad857600080fd5b50356001600160a01b0316612ce3565b348015610af457600080fd5b50610380600480360360c0811015610b0b57600080fd5b81359190810190604081016020820135600160201b811115610b2c57600080fd5b820183602082011115610b3e57600080fd5b803590602001918460018302840111600160201b83111715610b5f57600080fd5b919390929091602081019035600160201b811115610b7c57600080fd5b820183602082011115610b8e57600080fd5b803590602001918460208302840111600160201b83111715610baf57600080fd5b919350915080359060208101359060400135612d01565b348015610bd257600080fd5b5061034460048036036020811015610be957600080fd5b5035613065565b348015610bfc57600080fd5b5061043261308d565b348015610c1157600080fd5b5061034460048036036020811015610c2857600080fd5b503561309c565b348015610c3b57600080fd5b5061038060048036036040811015610c5257600080fd5b506001600160a01b03813581169160200135166130ae565b600080610c756120f8565b90506000805b82811015610d2157846001600160a01b0316639168ae72610c9b83612b3e565b6040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b158015610ce157600080fd5b505afa158015610cf5573d6000803e3d6000fd5b505050506040513d6020811015610d0b57600080fd5b505115610d19576001909101905b600101610c7b565b509150505b919050565b336000908152601d602052604090205460ff16610d7f576040805162461bcd60e51b815260206004820152600d60248201526c2727aa2fab20a624a220aa27a960991b604482015290519081900360640190fd5b610d87611fe1565b15610dc7576040805162461bcd60e51b81526020600482015260106024820152600080516020615480833981519152604482015290519081900360640190fd5b610dd033613162565b6000610dda611f92565b905080821015610de8578091505b610df233836131f9565b505050565b610dff612b6d565b811015610e45576040805162461bcd60e51b815260206004820152600f60248201526e1053149150511657d11150d2511151608a1b604482015290519081900360640190fd5b610e4d61271a565b811115610e90576040805162461bcd60e51b815260206004820152600c60248201526b1113d154d39517d1561254d560a21b604482015290519081900360640190fd5b50565b600c5481565b6001600160a01b03166000908152600a602052604090205490565b601e5443101590565b6011546001600160a01b031681565b6001600160a01b031660009081526008602052604090206001015490565b336000908152601d602052604090205460ff16610f3e576040805162461bcd60e51b815260206004820152600d60248201526c2727aa2fab20a624a220aa27a960991b604482015290519081900360640190fd5b610f46611fe1565b15610f86576040805162461bcd60e51b81526020600482015260106024820152600080516020615480833981519152604482015290519081900360640190fd5b610f8f336120a6565b610fcd576040805162461bcd60e51b815260206004820152600a6024820152691393d517d4d51052d15160b21b604482015290519081900360640190fd5b610fd5615351565b60408051808201909152611108908860026000835b8282101561102b5760408051606081810190925290808402860190600390839083908082843760009201919091525050508152600190910190602001610fea565b505060408051808201909152915089905060026000835b828210156110835760408051608081810190925290808402860190600490839083908082843760009201919091525050508152600190910190602001611042565b505050508787601160009054906101000a90046001600160a01b03166001600160a01b0316633dbcc8d16040518163ffffffff1660e01b815260040160206040518083038186803b1580156110d757600080fd5b505afa1580156110eb573d6000803e3d6000fd5b505050506040513d602081101561110157600080fd5b50516132bf565b805160e0015190915060009061112590439063ffffffff61330d16565b905060185481101561116b576040805162461bcd60e51b815260206004820152600a60248201526954494d455f44454c544160b01b604482015290519081900360640190fd5b60006111768361336a565b9050826000015161010001518360200151604001511015806111ab5750600e546111a790839063ffffffff61338616565b8110155b806111d7575082516060908101516020850151909101516064916111d5919063ffffffff61330d16565b145b611214576040805162461bcd60e51b81526020600482015260096024820152681513d3d7d4d350531360ba1b604482015290519081900360640190fd5b8251606090810151602085015190910151606491611238919063ffffffff61330d16565b111561127c576040805162461bcd60e51b815260206004820152600e60248201526d544f4f5f4d414e595f53454e445360901b604482015290519081900360640190fd5b6112a26004611296600e548561338690919063ffffffff16565b9063ffffffff61338616565b8111156112e2576040805162461bcd60e51b8152602060048201526009602482015268544f4f5f4c4152474560b81b604482015290519081900360640190fd5b505061133f81888886866040518060c0016040528061130033610ecc565b8152600c546020820152600e5460408201526011546001600160a01b039081166060830152601354811660808301526015541660a0909101528e6133df565b506113543361134c61271a565b600c54613a99565b5050505050505050565b336000908152601d602052604090205460ff166113b2576040805162461bcd60e51b815260206004820152600d60248201526c2727aa2fab20a624a220aa27a960991b604482015290519081900360640190fd5b6113ba611fe1565b156113fa576040805162461bcd60e51b81526020600482015260106024820152600080516020615480833981519152604482015290519081900360640190fd5b611403336120a6565b611441576040805162461bcd60e51b815260206004820152600a6024820152691393d517d4d51052d15160b21b604482015290519081900360640190fd5b8061144b8361309c565b1461148a576040805162461bcd60e51b815260206004820152600a6024820152694e4f44455f52454f524760b01b604482015290519081900360640190fd5b611492612b6d565b82101580156114a857506114a461271a565b8211155b6114f1576040805162461bcd60e51b81526020600482015260156024820152744e4f44455f4e554d5f4f55545f4f465f52414e474560581b604482015290519081900360640190fd5b60006114fc83611fb7565b9050806001600160a01b031663479c92546040518163ffffffff1660e01b815260040160206040518083038186803b15801561153757600080fd5b505afa15801561154b573d6000803e3d6000fd5b505050506040513d602081101561156157600080fd5b505161156c33610ecc565b146115b0576040805162461bcd60e51b815260206004820152600f60248201526e2727aa2fa9aa20a5a2a22fa82922ab60891b604482015290519081900360640190fd5b610df23384600c54613a99565b336000908152601d602052604090205460ff16611611576040805162461bcd60e51b815260206004820152600d60248201526c2727aa2fab20a624a220aa27a960991b604482015290519081900360640190fd5b611619611fe1565b15611659576040805162461bcd60e51b81526020600482015260106024820152600080516020615480833981519152604482015290519081900360640190fd5b610e908134613c32565b60185481565b336000908152601d602052604090205460ff166116bd576040805162461bcd60e51b815260206004820152600d60248201526c2727aa2fab20a624a220aa27a960991b604482015290519081900360640190fd5b6116c5611fe1565b15611705576040805162461bcd60e51b81526020600482015260106024820152600080516020615480833981519152604482015290519081900360640190fd5b602084013584351061174c576040805162461bcd60e51b815260206004820152600b60248201526a2ba927a723afa7a92222a960a91b604482015290519081900360640190fd5b61175461271a565b6020850135111561179b576040805162461bcd60e51b815260206004820152600c60248201526b1393d517d41493d413d4d15160a21b604482015290519081900360640190fd5b83356117a56120fe565b106117eb576040805162461bcd60e51b81526020600482015260116024820152701053149150511657d0d3d3919254935151607a1b604482015290519081900360640190fd5b60006117fd85825b6020020135611fb7565b9050600061180c8660016117f3565b9050806001600160a01b031663479c92546040518163ffffffff1660e01b815260040160206040518083038186803b15801561184757600080fd5b505afa15801561185b573d6000803e3d6000fd5b505050506040513d602081101561187157600080fd5b5051604080516311e7249560e21b815290516001600160a01b0385169163479c9254916004808301926020929190829003018186803b1580156118b357600080fd5b505afa1580156118c7573d6000803e3d6000fd5b505050506040513d60208110156118dd57600080fd5b50511461191d576040805162461bcd60e51b81526020600482015260096024820152682224a3232fa82922ab60b91b604482015290519081900360640190fd5b6119378760005b60200201356001600160a01b0316613162565b611942876001611924565b604080516348b4573960e11b81526001600160a01b03893581166004830152915191841691639168ae7291602480820192602092909190829003018186803b15801561198d57600080fd5b505afa1580156119a1573d6000803e3d6000fd5b505050506040513d60208110156119b757600080fd5b50516119ff576040805162461bcd60e51b815260206004820152601260248201527114d51052d1548c57d393d517d4d51052d15160721b604482015290519081900360640190fd5b604080516348b4573960e11b81526001600160a01b0360208a81013582166004840152925190841692639168ae729260248082019391829003018186803b158015611a4957600080fd5b505afa158015611a5d573d6000803e3d6000fd5b505050506040513d6020811015611a7357600080fd5b5051611abb576040805162461bcd60e51b815260206004820152601260248201527114d51052d1548c97d393d517d4d51052d15160721b604482015290519081900360640190fd5b611ad0853585358560005b6020020135613ce1565b826001600160a01b0316635b8b22806040518163ffffffff1660e01b815260040160206040518083038186803b158015611b0957600080fd5b505afa158015611b1d573d6000803e3d6000fd5b505050506040513d6020811015611b3357600080fd5b505114611b74576040805162461bcd60e51b815260206004820152600a6024820152694348414c5f484153483160b01b604482015290519081900360640190fd5b611b8960208087013590860135856001611ac6565b816001600160a01b0316635b8b22806040518163ffffffff1660e01b815260040160206040518083038186803b158015611bc257600080fd5b505afa158015611bd6573d6000803e3d6000fd5b505050506040513d6020811015611bec57600080fd5b505114611c2d576040805162461bcd60e51b815260206004820152600a60248201526921a420a62fa420a9a41960b11b604482015290519081900360640190fd5b6000611da7611cca600d54611cbe88600060028110611c4857fe5b6020020135876001600160a01b0316632edfb42a6040518163ffffffff1660e01b815260040160206040518083038186803b158015611c8657600080fd5b505afa158015611c9a573d6000803e3d6000fd5b505050506040513d6020811015611cb057600080fd5b50519063ffffffff61330d16565b9063ffffffff613d1816565b611d37856001600160a01b031663479c92546040518163ffffffff1660e01b815260040160206040518083038186803b158015611d0657600080fd5b505afa158015611d1a573d6000803e3d6000fd5b505050506040513d6020811015611d3057600080fd5b5051611fb7565b6001600160a01b031663d7ff5e356040518163ffffffff1660e01b815260040160206040518083038186803b158015611d6f57600080fd5b505afa158015611d83573d6000803e3d6000fd5b505050506040513d6020811015611d9957600080fd5b50519063ffffffff613d1816565b90506020850135811015611de157611dd96001600160a01b0389351689600160200201356001600160a01b0316613d72565b505050611f8b565b6014546000906001600160a01b0390811690638ecaab119030908a35908935908e35168e600160200201356001600160a01b0316611e398d600060028110611e2557fe5b60200201358a61330d90919063ffffffff16565b611e538e600160200201358b61330d90919063ffffffff16565b601154601054604080516001600160e01b031960e08d901b1681526001600160a01b039a8b166004820152602481019990995260448901979097529488166064880152928716608487015260a486019190915260c4850152841660e484015290921661010482015290516101248083019260209291908290030181600087803b158015611edf57600080fd5b505af1158015611ef3573d6000803e3d6000fd5b505050506040513d6020811015611f0957600080fd5b50519050611f326001600160a01b038a35168a600160200201356001600160a01b031683613df9565b604080516001600160a01b038b35811682526020808d01358216908301528a35828401529151918316917fa5256d19d4ddaf646f4b5c1861b8d4c08238e6356b8ae36dcc49ac67fda758799181900360600190a2505050505b5050505050565b600080611f9d612b6d565b9050611fb14382611fac61271a565b613e43565b91505090565b6000908152600560205260409020546001600160a01b031690565b6017546001600160a01b031681565b600b5460ff1690565b6014546001600160a01b031681565b600e5490565b336000908152601d602052604090205460ff16612053576040805162461bcd60e51b815260206004820152600d60248201526c2727aa2fab20a624a220aa27a960991b604482015290519081900360640190fd5b61205b611fe1565b1561209b576040805162461bcd60e51b81526020600482015260106024820152600080516020615480833981519152604482015290519081900360640190fd5b6120a4346140fa565b565b6001600160a01b0316600090815260086020526040902060030154600160a01b900460ff1690565b6000600782815481106120dd57fe5b6000918252602090912001546001600160a01b031692915050565b60095490565b60015490565b600061210e612b6d565b90506121186120fe565b8111801561212d575061212961271a565b8111155b610e90576040805162461bcd60e51b815260206004820152600d60248201526c1393d7d553949154d3d3159151609a1b604482015290519081900360640190fd5b6001600160a01b039081166000908152600860205260409020600301541690565b336000908152601d602052604090205460ff166121e3576040805162461bcd60e51b815260206004820152600d60248201526c2727aa2fab20a624a220aa27a960991b604482015290519081900360640190fd5b6121eb611fe1565b1561222b576040805162461bcd60e51b81526020600482015260106024820152600080516020615480833981519152604482015290519081900360640190fd5b612233612104565b600061223d6120fe565b90506000612249612b6d565b9050600061225682611fb7565b905082816001600160a01b031663479c92546040518163ffffffff1660e01b815260040160206040518083038186803b15801561229257600080fd5b505afa1580156122a6573d6000803e3d6000fd5b505050506040513d60208110156122bc57600080fd5b50511415612545576122cd846120a6565b61230b576040805162461bcd60e51b815260206004820152600a6024820152691393d517d4d51052d15160b21b604482015290519081900360640190fd5b61231c61231785610ecc565b610df7565b806001600160a01b0316639168ae72856040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b0316815260200191505060206040518083038186803b15801561237257600080fd5b505afa158015612386573d6000803e3d6000fd5b505050506040513d602081101561239c57600080fd5b5051156123e3576040805162461bcd60e51b815260206004820152601060248201526f14d51052d15117d3d397d5105491d15560821b604482015290519081900360640190fd5b806001600160a01b03166388d221c66040518163ffffffff1660e01b815260040160006040518083038186803b15801561241c57600080fd5b505afa158015612430573d6000803e3d6000fd5b5050505061243d83611fb7565b6001600160a01b0316633aa192746040518163ffffffff1660e01b815260040160006040518083038186803b15801561247557600080fd5b505afa158015612489573d6000803e3d6000fd5b505050506124976000612bd6565b6124a081610c6a565b816001600160a01b031663dff697876040518163ffffffff1660e01b815260040160206040518083038186803b1580156124d957600080fd5b505afa1580156124ed573d6000803e3d6000fd5b505050506040513d602081101561250357600080fd5b505114612545576040805162461bcd60e51b815260206004820152600b60248201526a4841535f5354414b45525360a81b604482015290519081900360640190fd5b61254d614306565b60135460408051630c2a09ad60e21b81526004810185905290516001600160a01b03909216916330a826b49160248082019260009290919082900301818387803b15801561259a57600080fd5b505af11580156125ae573d6000803e3d6000fd5b50506040518492507f9f7eee12f08e41a1d1a617e76576aa2d6a1e06dbdd72d817e62b6e8dfdebe2a39150600090a250505050565b60005460ff1690565b60006125f9848484613e43565b90505b9392505050565b336000908152601d602052604090205460ff16612657576040805162461bcd60e51b815260206004820152600d60248201526c2727aa2fab20a624a220aa27a960991b604482015290519081900360640190fd5b61265f610eb4565b6126ab5761266b611fe1565b156126ab576040805162461bcd60e51b81526020600482015260106024820152600080516020615480833981519152604482015290519081900360640190fd5b6126b36120fe565b6126bc82610ecc565b11156126fc576040805162461bcd60e51b815260206004820152600a6024820152691513d3d7d49150d1539560b21b604482015290519081900360640190fd5b61270581613162565b610e908161431c565b600f5481565b600d5481565b60035490565b336000908152601d602052604090205460ff16612774576040805162461bcd60e51b815260206004820152600d60248201526c2727aa2fab20a624a220aa27a960991b604482015290519081900360640190fd5b61277c611fe1565b156127bc576040805162461bcd60e51b81526020600482015260106024820152600080516020615480833981519152604482015290519081900360640190fd5b6127c46120f8565b821115612809576040805162461bcd60e51b815260206004820152600e60248201526d4e4f5f535543485f5a4f4d42494560901b604482015290519081900360640190fd5b600061281483612b3e565b9050600061282184613065565b905060008061282e612b6d565b90505b80831015801561284057508482105b1561293557600061285084611fb7565b9050806001600160a01b03166396a9fdc0866040518263ffffffff1660e01b815260040180826001600160a01b03166001600160a01b03168152602001915050600060405180830381600087803b1580156128aa57600080fd5b505af11580156128be573d6000803e3d6000fd5b50505050806001600160a01b031663479c92546040518163ffffffff1660e01b815260040160206040518083038186803b1580156128fb57600080fd5b505afa15801561290f573d6000803e3d6000fd5b505050506040513d602081101561292557600080fd5b5051935050600190910190612831565b8083101561294b5761294686614382565b612955565b612955868461441e565b505050505050565b601a5481565b601e5481565b336000908152601d602052604081205460ff166129bd576040805162461bcd60e51b815260206004820152600d60248201526c2727aa2fab20a624a220aa27a960991b604482015290519081900360640190fd5b6129c5610eb4565b612a11576129d1611fe1565b15612a11576040805162461bcd60e51b81526020600482015260106024820152600080516020615480833981519152604482015290519081900360640190fd5b6000612a1c33614445565b6040519091506001600160a01b0384169082156108fc029083906000818181858888f19350505050158015612a55573d6000803e3d6000fd5b5092915050565b60045490565b6016546001600160a01b031681565b6000805b600954811015612ac25760098181548110612a8c57fe5b60009182526020909120600290910201546001600160a01b0384811691161415612aba576001915050610d26565b600101612a75565b50600092915050565b6013546001600160a01b031681565b61a4b190565b6001600160a01b03811615610e90576040805162461bcd60e51b815260206004820152601060248201526f1393d7d513d2d15397d0531313d5d15160821b604482015290519081900360640190fd5b6012546001600160a01b031681565b600060098281548110612b4d57fe5b60009182526020909120600290910201546001600160a01b031692915050565b60025490565b600e5481565b6015546001600160a01b031681565b601b5481565b60075490565b60195481565b6008602052600090815260409020805460018201546002830154600390930154919290916001600160a01b03811690600160a01b900460ff1685565b336000908152601d602052604090205460ff16612c2a576040805162461bcd60e51b815260206004820152600d60248201526c2727aa2fab20a624a220aa27a960991b604482015290519081900360640190fd5b612c32610eb4565b612c7e57612c3e611fe1565b15612c7e576040805162461bcd60e51b81526020600482015260106024820152600080516020615480833981519152604482015290519081900360640190fd5b6000612c886120f8565b90506000612c94612b6d565b9050825b82811015612cdd575b81612cab82613065565b1015612cd557612cba81614382565b60001990920191828110612cd057505050610e90565b612ca1565b600101612c98565b50505050565b6001600160a01b031660009081526008602052604090206002015490565b336000908152601d602052604090205460ff16612d55576040805162461bcd60e51b815260206004820152600d60248201526c2727aa2fab20a624a220aa27a960991b604482015290519081900360640190fd5b612d5d610eb4565b612da957612d69611fe1565b15612da9576040805162461bcd60e51b81526020600482015260106024820152600080516020615480833981519152604482015290519081900360640190fd5b612db1612104565b6000612dbb612b8e565b11612dfa576040805162461bcd60e51b815260206004820152600a6024820152694e4f5f5354414b45525360b01b604482015290519081900360640190fd5b6000612e0c612e07612b6d565b611fb7565b9050806001600160a01b03166388d221c66040518163ffffffff1660e01b815260040160006040518083038186803b158015612e4757600080fd5b505afa158015612e5b573d6000803e3d6000fd5b50505050612e6a612e076120fe565b6001600160a01b0316633aa192746040518163ffffffff1660e01b815260040160006040518083038186803b158015612ea257600080fd5b505afa158015612eb6573d6000803e3d6000fd5b50505050612ec26120fe565b816001600160a01b031663479c92546040518163ffffffff1660e01b815260040160206040518083038186803b158015612efb57600080fd5b505afa158015612f0f573d6000803e3d6000fd5b505050506040513d6020811015612f2557600080fd5b505114612f68576040805162461bcd60e51b815260206004820152600c60248201526b24a72b20a624a22fa82922ab60a11b604482015290519081900360640190fd5b612f726000612bd6565b612f86612f7e82610c6a565b611cbe612b8e565b816001600160a01b031663dff697876040518163ffffffff1660e01b815260040160206040518083038186803b158015612fbf57600080fd5b505afa158015612fd3573d6000803e3d6000fd5b505050506040513d6020811015612fe957600080fd5b50511461302e576040805162461bcd60e51b815260206004820152600e60248201526d1393d517d0531317d4d51052d15160921b604482015290519081900360640190fd5b60125460135461305a918b918b918b918b918b918b918b918b916001600160a01b0390811691166144a8565b505050505050505050565b60006009828154811061307457fe5b9060005260206000209060020201600101549050919050565b6010546001600160a01b031681565b60009081526006602052604090205490565b6130b6611fe1565b156130f6576040805162461bcd60e51b81526020600482015260106024820152600080516020615480833981519152604482015290519081900360640190fd5b61310082826144c9565b6001600160a01b0316336001600160a01b031614613154576040805162461bcd60e51b815260206004820152600c60248201526b2ba927a723afa9a2a72222a960a11b604482015290519081900360640190fd5b61315e8282613d72565b5050565b61316b816120a6565b6131a9576040805162461bcd60e51b815260206004820152600a6024820152691393d517d4d51052d15160b21b604482015290519081900360640190fd5b60006131b48261216e565b6001600160a01b031614610e90576040805162461bcd60e51b8152602060048201526007602482015266125397d0d2105360ca1b604482015290519081900360640190fd5b6001600160a01b038216600090815260086020526040812060028101548084111561325e576040805162461bcd60e51b815260206004820152601060248201526f544f4f5f4c4954544c455f5354414b4560801b604482015290519081900360640190fd5b6000613270828663ffffffff61330d16565b600284018690559050613283868261458f565b604080518381526020810187905281516001600160a01b0389169260008051602061543f833981519152928290030190a2925050505b92915050565b6132c7615351565b604080518082019091528651865182916132e291888861461a565b815260200161330188600160200201518860016020020151438761461a565b90529695505050505050565b600082821115613364576040805162461bcd60e51b815260206004820152601e60248201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604482015290519081900360640190fd5b50900390565b8051516020820151516000916132b9919063ffffffff61330d16565b600082613395575060006132b9565b828202828482816133a257fe5b04146125fc5760405162461bcd60e51b815260040180806020018281038252602181526020018061545f6021913960400191505060405180910390fd5b60006133e9615376565b6133f28961336a565b60e0820152835161340290611fb7565b81606001906001600160a01b031690816001600160a01b03168152505083606001516001600160a01b0316633dbcc8d16040518163ffffffff1660e01b815260040160206040518083038186803b15801561345c57600080fd5b505afa158015613470573d6000803e3d6000fd5b505050506040513d602081101561348657600080fd5b5051815260608101516040805163380ed4c760e11b815290516001600160a01b039092169163701da98e91600480820192602092909190829003018186803b1580156134d157600080fd5b505afa1580156134e5573d6000803e3d6000fd5b505050506040513d60208110156134fb57600080fd5b50518951613508906146b8565b1461354c576040805162461bcd60e51b815260206004820152600f60248201526e0a0a48aacbea6a882a88abe9082a69608b1b604482015290519081900360640190fd5b805160208a015160400151111561359b576040805162461bcd60e51b815260206004820152600e60248201526d12539093d617d41054d517d1539160921b604482015290519081900360640190fd5b83606001516001600160a01b031663dc1b7b1f87878c60200151604001516040518463ffffffff1660e01b815260040180806020018381526020018281038252858582818152602001925080828437600081840152601f19601f820116905080830192505050945050505050604080518083038186803b15801561361e57600080fd5b505afa158015613632573d6000803e3d6000fd5b505050506040513d604081101561364857600080fd5b5080516020909101516101208301526101008201526136668961474d565b81604001818152505061368b84604001518260e001518660200151846060015161477e565b8160c0018181525050600081606001516001600160a01b031663f0dd77ff6040518163ffffffff1660e01b815260040160206040518083038186803b1580156136d357600080fd5b505afa1580156136e7573d6000803e3d6000fd5b505050506040513d60208110156136fd57600080fd5b50511160a08201819052156137875761377d81606001516001600160a01b031663f0dd77ff6040518163ffffffff1660e01b815260040160206040518083038186803b15801561374c57600080fd5b505afa158015613760573d6000803e3d6000fd5b505050506040513d602081101561377657600080fd5b505161309c565b6080820152613798565b83516137929061309c565b60808201525b8360a001516001600160a01b031663d45ab2b56137b88b602001516146b8565b6137c78c8560400151436148ec565b6137d08d614901565b88600001518660c001516040518663ffffffff1660e01b81526004018086815260200185815260200184815260200183815260200182815260200195505050505050602060405180830381600087803b15801561382c57600080fd5b505af1158015613840573d6000803e3d6000fd5b505050506040513d602081101561385657600080fd5b50516001600160a01b03166020820152600061387061271a565b600101905081606001516001600160a01b0316631bc09d0a826040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b1580156138bf57600080fd5b505af11580156138d3573d6000803e3d6000fd5b505050506138f48260a0015183608001518460400151856101200151614931565b9250838314613941576040805162461bcd60e51b81526020600482015260146024820152730aa9c8ab0a08a86a88a88be9c9e888abe9082a6960631b604482015290519081900360640190fd5b61394f826020015184614998565b6080850151855160c084015160408051638b8ca19960e01b81526004810186905260248101939093526044830191909152336064830152516001600160a01b0390921691638b8ca1999160848082019260009290919082900301818387803b1580156139ba57600080fd5b505af11580156139ce573d6000803e3d6000fd5b50505050506139e0846000015161309c565b6139e861271a565b7f8016306209aff73e79f274cf38a41928996f746e2953111902e1f55be1713a5484846040015185600001518661010001518761012001518f8f6040518088815260200187815260200186815260200185815260200184815260200183600260600280828437600083820152601f01601f191690910190508261010080828437600083820152604051601f909101601f1916909201829003995090975050505050505050a350979650505050505050565b6001600160a01b0380841660008181526008602090815260408083208784526005835281842054825163123334b760e11b815260048101969096529151909591909116938492632466696e9260248084019382900301818787803b158015613b0057600080fd5b505af1158015613b14573d6000803e3d6000fd5b505050506040513d6020811015613b2a57600080fd5b5051600180850187905590915081141561295557600060056000846001600160a01b031663479c92546040518163ffffffff1660e01b815260040160206040518083038186803b158015613b7d57600080fd5b505afa158015613b91573d6000803e3d6000fd5b505050506040513d6020811015613ba757600080fd5b505181526020810191909152604001600020546001600160a01b0316905080636971dfe5613bdb438863ffffffff613d1816565b6040518263ffffffff1660e01b815260040180828152602001915050600060405180830381600087803b158015613c1157600080fd5b505af1158015613c25573d6000803e3d6000fd5b5050505050505050505050565b336000908152601d602052604090205460ff16613c86576040805162461bcd60e51b815260206004820152600d60248201526c2727aa2fab20a624a220aa27a960991b604482015290519081900360640190fd5b613c8e611fe1565b15613cce576040805162461bcd60e51b81526020600482015260106024820152600080516020615480833981519152604482015290519081900360640190fd5b613cd782613162565b61315e82826149e2565b6040805160208082019590955280820193909352606080840192909252805180840390920182526080909201909152805191012090565b6000828201838110156125fc576040805162461bcd60e51b815260206004820152601b60248201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604482015290519081900360640190fd5b6000613d7d82612ce3565b90506000613d8a84612ce3565b905080821115613db157613dae613da184836131f9565b839063ffffffff61330d16565b91505b60028204613dbf85826149e2565b613dcf838263ffffffff61330d16565b9250613dda85614a56565b601654613df0906001600160a01b03168461458f565b611f8b84614a80565b6001600160a01b03928316600090815260086020526040808220600390810180549487166001600160a01b0319958616811790915594909516825290209092018054909216179055565b600081600184031415613e595750600f546125fc565b6000613e6484611fb7565b6001600160a01b0316632edfb42a6040518163ffffffff1660e01b815260040160206040518083038186803b158015613e9c57600080fd5b505afa158015613eb0573d6000803e3d6000fd5b505050506040513d6020811015613ec657600080fd5b5051905080851015613edc575050600f546125fc565b613ee46153ca565b506040805161014081018252600181526201e05b60208201526201f7d191810191909152620138916060820152620329e160808201526201be4360a08201526204cb8c60c08201526201fbc460e082015262036d3261010082015262027973610120820152613f516153ca565b506040805161014081018252600181526201c03060208201526201b6999181019190915261fde26060820152620265c6608082015262013b8e60a0820152620329e160c08201526201389160e08201526201f7d1610100820152620153756101208201526000613fc7888563ffffffff61330d16565b90506000613ff1600c54613fe5600a8561338690919063ffffffff16565b9063ffffffff614b3016565b905060ff61400682600a63ffffffff614b3016565b1061401a57600019955050505050506125fc565b600061402d82600a63ffffffff614b3016565b60020a9050600085600a8406600a811061404357fe5b602002015162ffffff168202905085600a8406600a811061406057fe5b602002015162ffffff1682828161407357fe5b041461408a576000199750505050505050506125fc565b60006140b586600a8606600a811061409e57fe5b6020020151839062ffffff1663ffffffff614b3016565b9050806140c0575060015b600f5480820290829082816140d157fe5b04146140ea5760001999505050505050505050506125fc565b9c9b505050505050505050505050565b336000908152601d602052604090205460ff1661414e576040805162461bcd60e51b815260206004820152600d60248201526c2727aa2fab20a624a220aa27a960991b604482015290519081900360640190fd5b614156611fe1565b15614196576040805162461bcd60e51b81526020600482015260106024820152600080516020615480833981519152604482015290519081900360640190fd5b61419f336120a6565b156141e2576040805162461bcd60e51b815260206004820152600e60248201526d1053149150511657d4d51052d15160921b604482015290519081900360640190fd5b6141eb33612a71565b15614230576040805162461bcd60e51b815260206004820152601060248201526f5354414b45525f49535f5a4f4d42494560801b604482015290519081900360640190fd5b614238611f92565b81101561427f576040805162461bcd60e51b815260206004820152601060248201526f4e4f545f454e4f5547485f5354414b4560801b604482015290519081900360640190fd5b6142893382614b97565b6013546001600160a01b031663f03c04a5336142a36120fe565b6040518363ffffffff1660e01b815260040180836001600160a01b03166001600160a01b0316815260200182815260200192505050600060405180830381600087803b1580156142f257600080fd5b505af1158015611f8b573d6000803e3d6000fd5b614311600254614c90565b600280546001019055565b6001600160a01b03811660009081526008602052604090206002810154614343838261458f565b61434c83614d12565b604080518281526000602082015281516001600160a01b0386169260008051602061543f833981519152928290030190a2505050565b60098054600019810190811061439457fe5b9060005260206000209060020201600982815481106143af57fe5b60009182526020909120825460029092020180546001600160a01b0319166001600160a01b0390921691909117815560019182015491015560098054806143f257fe5b60008281526020812060026000199093019283020180546001600160a01b031916815560010155905550565b806009838154811061442c57fe5b9060005260206000209060020201600101819055505050565b6001600160a01b0381166000818152600a60209081526040808320805490849055815181815292830184905281519394909390927fa740af14c56e4e04a617b1de1eb20de73270decbaaead14f142aabf3038e5ae292908290030190a292915050565b6144bd6002548b8b8b8b8b8b8b8b8b8b614e38565b50505050505050505050565b6001600160a01b03808316600090815260086020526040808220848416835290822060038201549293919290911680614533576040805162461bcd60e51b81526020600482015260076024820152661393d7d0d2105360ca1b604482015290519081900360640190fd5b60038201546001600160a01b03828116911614614586576040805162461bcd60e51b815260206004820152600c60248201526b1112519197d25397d0d2105360a21b604482015290519081900360640190fd5b95945050505050565b6001600160a01b0382166000908152600a6020526040812054906145b9828463ffffffff613d1816565b6001600160a01b0385166000818152600a60209081526040918290208490558151868152908101849052815193945091927fa740af14c56e4e04a617b1de1eb20de73270decbaaead14f142aabf3038e5ae29281900390910190a250505050565b6146226153e9565b60408051610120810182528551815286516020820152908101856001602002015181526020018560026004811061465557fe5b602002015181526020018560036004811061466c57fe5b602002015181526020018660016003811061468357fe5b602002015181526020018660026003811061469a57fe5b60200201518152602001848152602001838152509050949350505050565b6000816000015182602001518360400151846060015185608001518660a001518760c001518860e00151896101000151604051602001808a81526020018981526020018881526020018781526020018681526020018581526020018481526020018381526020018281526020019950505050505050505050604051602081830303815290604052805190602001209050919050565b805180516020830151516000926132b992918290039061476c90615109565b6147798660200151615109565b61513e565b6000806147a686613fe561479982600163ffffffff61330d16565b889063ffffffff613d1816565b905061482981611cbe6147bf438863ffffffff613d1816565b866001600160a01b0316632edfb42a6040518163ffffffff1660e01b815260040160206040518083038186803b1580156147f857600080fd5b505afa15801561480c573d6000803e3d6000fd5b505050506040513d602081101561482257600080fd5b505161517c565b91506000836001600160a01b031663f0dd77ff6040518163ffffffff1660e01b815260040160206040518083038186803b15801561486657600080fd5b505afa15801561487a573d6000803e3d6000fd5b505050506040513d602081101561489057600080fd5b5051905080156148e2576148df836148a783611fb7565b6001600160a01b0316632edfb42a6040518163ffffffff1660e01b815260040160206040518083038186803b1580156147f857600080fd5b92505b5050949350505050565b60006125f98383866020015160400151613ce1565b805160a09081015160208301519182015160c083015160608401516080909401516000946132b994939291615192565b60008085614940576000614943565b60015b905080858585604051602001808560ff1660ff1660f81b815260010184815260200183815260200182815260200194505050505060405160208183030381529060405280519060200120915050949350505050565b60038054600101808255600090815260056020908152604080832080546001600160a01b0319166001600160a01b0397909716969096179095559154815260069091529190912055565b6001600160a01b038216600090815260086020526040812060028101549091614a11828563ffffffff613d1816565b60028401819055604080518481526020810183905281519293506001600160a01b0388169260008051602061543f833981519152929181900390910190a25050505050565b6001600160a01b0316600090815260086020526040902060030180546001600160a01b0319169055565b6001600160a01b0381811660008181526008602090815260408083208151808301909252938152600180850154928201928352600980549182018155909352517f6e1540171b6c0c960b71a7020d9f60077f6af931a8bbf590da0223dacf75c7af600290930292830180546001600160a01b031916919095161790935591517f6e1540171b6c0c960b71a7020d9f60077f6af931a8bbf590da0223dacf75c7b09092019190915561315e82614d12565b6000808211614b86576040805162461bcd60e51b815260206004820152601a60248201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604482015290519081900360640190fd5b818381614b8f57fe5b049392505050565b6007805460018082019092557fa66cc928b5edb82af9bd49922954155ab7b0942694bea4ce44661d9a8736c688810180546001600160a01b038087166001600160a01b031992831681179093556040805160a081018252858152865460208281019182528284018a8152600060608501818152608086018c81528a8352600885528783209651875594519b86019b909b559051600285015598516003909301805492511515600160a01b0260ff60a01b199490961692909616919091179190911692909217909255436004558151948552840185905280519293919260008051602061543f8339815191529281900390910190a2505050565b60008181526005602052604080822054815163083197ef60e41b815291516001600160a01b03909116926383197ef0926004808201939182900301818387803b158015614cdc57600080fd5b505af1158015614cf0573d6000803e3d6000fd5b50505060009182525060056020526040902080546001600160a01b0319169055565b6001600160a01b03811660009081526008602052604090208054600780546000198101908110614d3e57fe5b600091825260209091200154600780546001600160a01b039092169183908110614d6457fe5b9060005260206000200160006101000a8154816001600160a01b0302191690836001600160a01b03160217905550806008600060078481548110614da457fe5b60009182526020808320909101546001600160a01b031683528201929092526040019020556007805480614dd457fe5b60008281526020808220830160001990810180546001600160a01b03191690559092019092556001600160a01b03949094168152600890935250506040812081815560018101829055600281019190915560030180546001600160a81b0319169055565b6000614eb98a8a8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525050604080516020808e0282810182019093528d82529093508d92508c918291850190849080828437600081840152601f19601f820116905080830192505050505050508d6151d9565b90506000614ec68d611fb7565b9050614ed58c83888a89615192565b816001600160a01b03166397bdc5106040518163ffffffff1660e01b815260040160206040518083038186803b158015614f0e57600080fd5b505afa158015614f22573d6000803e3d6000fd5b505050506040513d6020811015614f3857600080fd5b505114614f7b576040805162461bcd60e51b815260206004820152600c60248201526b434f4e4649524d5f4441544160a01b604482015290519081900360640190fd5b836001600160a01b0316630c7268478c8c8c8c6040518563ffffffff1660e01b81526004018080602001806020018381038352878782818152602001925080828437600083820152601f01601f19169091018481038352858152602090810191508690860280828437600081840152601f19601f8201169050808301925050509650505050505050600060405180830381600087803b15801561501d57600080fd5b505af1158015615031573d6000803e3d6000fd5b50505050615040600154614c90565b60018d81558d01600255604080516316b9109b60e01b8152600481018f905290516001600160a01b038516916316b9109b91602480830192600092919082900301818387803b15801561509257600080fd5b505af11580156150a6573d6000803e3d6000fd5b505050508c7f2400bd6e429cfcd98fe43a75bbbe4702c59c99d636100690130cc1ebb611c5a2838989896040518085815260200184815260200183815260200182815260200194505050505060405180910390a250505050505050505050505050565b60006132b98260000151615139846040015185602001518660a0015187606001518860c0015189608001516152da565b615325565b604080516020808201969096528082019490945260608401929092526080808401919091528151808403909101815260a09092019052805191012090565b600081831161518b57816125fc565b5090919050565b60408051602080820197909752808201959095526060850192909252608084019290925260a0808401929092528051808403909201825260c0909201909152805191012090565b81518351600091829184835b8381101561528c5760008882815181106151fb57fe5b6020026020010151905083818701111561524b576040805162461bcd60e51b815260206004820152600c60248201526b2220aa20afa7ab22a9292aa760a11b604482015290519081900360640190fd5b6020868b01810182902060408051808401969096528581019190915280518086038201815260609095019052835193019290922091909401936001016151e5565b508184146152cf576040805162461bcd60e51b815260206004820152600b60248201526a08882a882be988a9c8ea8960ab1b604482015290519081900360640190fd5b979650505050505050565b60408051602080820198909852808201969096526060860194909452608085019290925260a084015260c0808401919091528151808403909101815260e09092019052805191012090565b604080516020808201949094528082019290925280518083038201815260609092019052805191012090565b60405180604001604052806153646153e9565b81526020016153716153e9565b905290565b6040805161014081018252600080825260208201819052918101829052606081018290526080810182905260a0810182905260c0810182905260e08101829052610100810182905261012081019190915290565b604051806101400160405280600a906020820280368337509192915050565b604051806101200160405280600081526020016000801916815260200160008152602001600081526020016000815260200160008019168152602001600080191681526020016000815260200160008152509056feebd093d389ab57f3566918d2c379a2b4d9539e8eb95efad9d5e465457833fde6536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f775061757361626c653a2070617573656400000000000000000000000000000000a26469706673582212208c3d38675521346566e8f28939516bbd5f14bb6d5eb606cf9443f07198e6875464736f6c634300060b0033

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export  ]

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