ETH Price: $1,598.85 (+0.79%)
Gas: 20 Gwei
 

Overview

ETH Balance

0.238 ETH

Eth Value

$380.53 (@ $1,598.85/ETH)

Sponsored

Transaction Hash
Method
Block
From
To
Value
Start Standard E...162055492022-12-17 16:16:11283 days 22 hrs ago1671293771IN
OMG Network V1: Exit Game
0.014 ETH0.0055546414.3
Start Standard E...162055292022-12-17 16:12:11283 days 22 hrs ago1671293531IN
OMG Network V1: Exit Game
0.014 ETH0.0055544714.3
Start Standard E...162053872022-12-17 15:43:23283 days 23 hrs ago1671291803IN
OMG Network V1: Exit Game
0.014 ETH0.0058384314.3
Start Standard E...162053392022-12-17 15:33:47283 days 23 hrs ago1671291227IN
OMG Network V1: Exit Game
0.014 ETH0.0055544714.3
Start Standard E...162052642022-12-17 15:18:47283 days 23 hrs ago1671290327IN
OMG Network V1: Exit Game
0.014 ETH0.0058815614.3
Start Standard E...162052242022-12-17 15:10:47283 days 23 hrs ago1671289847IN
OMG Network V1: Exit Game
0.014 ETH0.0060835414.3
Start Standard E...161284652022-12-06 21:33:35294 days 17 hrs ago1670362415IN
OMG Network V1: Exit Game
0.014 ETH0.0225480553
Start Standard E...161256602022-12-06 12:09:47295 days 2 hrs ago1670328587IN
OMG Network V1: Exit Game
0.014 ETH0.0056249314.3
Start Standard E...161256582022-12-06 12:09:23295 days 2 hrs ago1670328563IN
OMG Network V1: Exit Game
0.014 ETH0.0063113814.79021333
Start Standard E...149901772022-06-19 9:58:10465 days 4 hrs ago1655632690IN
OMG Network V1: Exit Game
0.014 ETH0.0127641330
Start Standard E...145699292022-04-12 9:30:33533 days 5 hrs ago1649755833IN
OMG Network V1: Exit Game
0.014 ETH0.0115262430
Start Standard E...145615592022-04-11 1:56:50534 days 12 hrs ago1649642210IN
OMG Network V1: Exit Game
0.014 ETH0.0113262330
Start Standard E...137184812021-12-01 2:28:57665 days 12 hrs ago1638325737IN
OMG Network V1: Exit Game
0.014 ETH0.04839735126
Start Standard E...136794192021-11-24 20:50:29671 days 17 hrs ago1637787029IN
OMG Network V1: Exit Game
0.014 ETH0.05402125143
Start Standard E...132558832021-09-19 11:29:29738 days 3 hrs ago1632050969IN
OMG Network V1: Exit Game
0.014 ETH0.0115337232
Start Standard E...132493032021-09-18 11:08:46739 days 3 hrs ago1631963326IN
OMG Network V1: Exit Game
0.014 ETH0.0163329640
Start Standard E...128052392021-07-11 9:39:03808 days 5 hrs ago1625996343IN
OMG Network V1: Exit Game
0.014 ETH0.002551236
Start Standard E...127618422021-07-04 15:29:06814 days 23 hrs ago1625412546IN
OMG Network V1: Exit Game
0.014 ETH0.001725848.9
Start Standard E...127332232021-06-30 4:29:47819 days 10 hrs ago1625027387IN
OMG Network V1: Exit Game
0.014 ETH0.002335811.1
Start Standard E...127332232021-06-30 4:29:47819 days 10 hrs ago1625027387IN
OMG Network V1: Exit Game
0.014 ETH0.0047224611.1
Start Standard E...127086922021-06-26 8:49:08823 days 5 hrs ago1624697348IN
OMG Network V1: Exit Game
0.014 ETH0.0044467511.9
Start Standard E...126955782021-06-24 7:37:04825 days 7 hrs ago1624520224IN
OMG Network V1: Exit Game
0.014 ETH0.003264719
Start Standard E...126727062021-06-20 18:06:46828 days 20 hrs ago1624212406IN
OMG Network V1: Exit Game
0.014 ETH0.002126535.9
Start Standard E...125728322021-06-05 6:17:33844 days 8 hrs ago1622873853IN
OMG Network V1: Exit Game
0.014 ETH0.005809415.1
Start Standard E...125661662021-06-04 5:48:22845 days 8 hrs ago1622785702IN
OMG Network V1: Exit Game
0.014 ETH0.0057632327
View all transactions

Latest 25 internal transactions (View All)

Advanced mode:
Advanced Filter
Parent Txn Hash Block From To Value
161912582022-12-15 16:22:11285 days 22 hrs ago1671121331
OMG Network V1: Exit Game
0.014 ETH
146326122022-04-22 4:43:02523 days 10 hrs ago1650602582
OMG Network V1: Exit Game
0.014 ETH
146326122022-04-22 4:43:02523 days 10 hrs ago1650602582
OMG Network V1: Exit Game
0.014 ETH
146153542022-04-19 11:50:52526 days 2 hrs ago1650369052
OMG Network V1: Exit Game
0.014 ETH
138096232021-12-15 12:05:16651 days 2 hrs ago1639569916
OMG Network V1: Exit Game
0.014 ETH
133051342021-09-27 2:11:54730 days 12 hrs ago1632708714
OMG Network V1: Exit Game
0.014 ETH
133051342021-09-27 2:11:54730 days 12 hrs ago1632708714
OMG Network V1: Exit Game
0.014 ETH
128565922021-07-19 10:53:00800 days 3 hrs ago1626691980
OMG Network V1: Exit Game
0.014 ETH
127867082021-07-08 12:31:42811 days 2 hrs ago1625747502
OMG Network V1: Exit Game
0.014 ETH
127866742021-07-08 12:23:41811 days 2 hrs ago1625747021
OMG Network V1: Exit Game
0.014 ETH
127839282021-07-08 1:56:00811 days 12 hrs ago1625709360
OMG Network V1: Exit Game
0.014 ETH
127839282021-07-08 1:56:00811 days 12 hrs ago1625709360
OMG Network V1: Exit Game
0.014 ETH
127839282021-07-08 1:56:00811 days 12 hrs ago1625709360
OMG Network V1: Exit Game
0.014 ETH
127828012021-07-07 21:45:20811 days 17 hrs ago1625694320
OMG Network V1: Exit Game
0.014 ETH
125957832021-06-08 19:28:54840 days 19 hrs ago1623180534
OMG Network V1: Exit Game
0.014 ETH
125957832021-06-08 19:28:54840 days 19 hrs ago1623180534
OMG Network V1: Exit Game
0.014 ETH
125420052021-05-31 12:03:38849 days 2 hrs ago1622462618
OMG Network V1: Exit Game
0.014 ETH
124958832021-05-24 8:20:32856 days 6 hrs ago1621844432
OMG Network V1: Exit Game
0.014 ETH
123107222021-04-25 17:08:05884 days 21 hrs ago1619370485
OMG Network V1: Exit Game
0.014 ETH
123107162021-04-25 17:06:15884 days 21 hrs ago1619370375
OMG Network V1: Exit Game
0.014 ETH
121581542021-04-02 5:10:31908 days 9 hrs ago1617340231
OMG Network V1: Exit Game
0.014 ETH
121581542021-04-02 5:10:31908 days 9 hrs ago1617340231
OMG Network V1: Exit Game
0.014 ETH
121581542021-04-02 5:10:31908 days 9 hrs ago1617340231
OMG Network V1: Exit Game
0.014 ETH
121581542021-04-02 5:10:31908 days 9 hrs ago1617340231
OMG Network V1: Exit Game
0.014 ETH
121581542021-04-02 5:10:31908 days 9 hrs ago1617340231
OMG Network V1: Exit Game
0.014 ETH
View All Internal Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
PaymentExitGame

Compiler Version
v0.5.11+commit.c082d0b4

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion, Apache-2.0 license
File 1 of 114 : PaymentExitGame.sol
pragma solidity 0.5.11;
pragma experimental ABIEncoderV2;

import "./PaymentExitGameArgs.sol";
import "./routers/PaymentStandardExitRouter.sol";
import "./routers/PaymentInFlightExitRouter.sol";
import "../utils/ExitId.sol";
import "../registries/SpendingConditionRegistry.sol";
import "../../framework/interfaces/IExitProcessor.sol";
import "../../framework/PlasmaFramework.sol";
import "../../utils/OnlyFromAddress.sol";

/**
 * @notice The exit game contract implementation for Payment Transaction
 */
contract PaymentExitGame is IExitProcessor, OnlyFromAddress, PaymentStandardExitRouter, PaymentInFlightExitRouter {
    PlasmaFramework private plasmaFramework;

    /**
     * @dev use struct PaymentExitGameArgs to avoid stack too deep compilation error.
     */
    constructor(PaymentExitGameArgs.Args memory args)
        public
        PaymentStandardExitRouter(args)
        PaymentInFlightExitRouter(args)
    {
        plasmaFramework = args.framework;

        // makes sure that the spending condition has already renounced ownership
        require(args.spendingConditionRegistry.owner() == address(0), "Spending condition registry ownership needs to be renounced");
    }

    /**
     * @notice Callback processes exit function for the PlasmaFramework to call
     * @param exitId The exit ID
     * @param token Token (ERC20 address or address(0) for ETH) of the exiting output
     */
    function processExit(uint160 exitId, uint256, address token) external onlyFrom(address(plasmaFramework)) {
        if (ExitId.isStandardExit(exitId)) {
            PaymentStandardExitRouter.processStandardExit(exitId, token);
        } else {
            PaymentInFlightExitRouter.processInFlightExit(exitId, token);
        }
    }

    /**
     * @notice Helper function to compute the standard exit ID
     */
    function getStandardExitId(bool _isDeposit, bytes memory _txBytes, uint256 _utxoPos)
        public
        pure
        returns (uint160)
    {
        PosLib.Position memory utxoPos = PosLib.decode(_utxoPos);
        return ExitId.getStandardExitId(_isDeposit, _txBytes, utxoPos);
    }

    /**
     * @notice Helper function to compute the in-flight exit ID
     */
    function getInFlightExitId(bytes memory _txBytes)
        public
        pure
        returns (uint160)
    {
        return ExitId.getInFlightExitId(_txBytes);
    }
}

File 2 of 114 : Migrations.sol
pragma solidity >=0.4.21 <0.6.0;

contract Migrations {
  address public owner;
  uint public last_completed_migration;

  constructor() public {
    owner = msg.sender;
  }

  modifier restricted() {
    if (msg.sender == owner) _;
  }

  function setCompleted(uint completed) public restricted {
    last_completed_migration = completed;
  }

  function upgrade(address new_address) public restricted {
    Migrations upgraded = Migrations(new_address);
    upgraded.setCompleted(last_completed_migration);
  }
}

File 3 of 114 : Imports.sol
pragma solidity 0.5.11;

// Import contracts from third party Solidity libraries to make them available in tests.

import "openzeppelin-solidity/contracts/token/ERC20/ERC20Mintable.sol";

contract Import {
    // dummy empty contract to allow the compiler not always trying to re-compile this file.
}

File 4 of 114 : FailFastReentrancyGuardAttacker.sol
pragma solidity 0.5.11;
pragma experimental ABIEncoderV2;

import "../../src/utils/FailFastReentrancyGuard.sol";
import "../../src/framework/PlasmaFramework.sol";

contract FailFastReentrancyGuardAttacker is FailFastReentrancyGuard {
    PlasmaFramework private framework;

    event RemoteCallFailed();

    constructor(PlasmaFramework plasmaFramework) public {
        framework = plasmaFramework;
    }

    function guardedLocal() public nonReentrant(framework) {
        guardedLocal();
    }

    function guardedRemote() external nonReentrant(framework) {
        // solhint-disable-next-line avoid-low-level-calls
        (bool success, ) = address(this).call(abi.encodeWithSignature("guardedRemote()"));
        if (!success) {
            emit RemoteCallFailed();
        }
    }
}

File 5 of 114 : FallbackFunctionFailAttacker.sol
pragma solidity 0.5.11;
pragma experimental ABIEncoderV2;

contract FallbackFunctionFailAttacker {
    function () external payable {
        revert("fail on fallback function");
    }
}

File 6 of 114 : OutOfGasFallbackAttacker.sol
pragma solidity 0.5.11;

contract OutOfGasFallbackAttacker {
    function () external payable {
        while (true) {}
    }
}

File 7 of 114 : SpendingConditionMock.sol
pragma solidity 0.5.11;
pragma experimental ABIEncoderV2;

import "../../src/exits/interfaces/ISpendingCondition.sol";

contract SpendingConditionMock is ISpendingCondition {
    bool internal expectedResult;
    bool internal shouldRevert;
    Args internal expectedArgs;

    string constant internal REVERT_MESSAGE = "Test spending condition reverts";

    struct Args {
        bytes inputTx;
        uint256 utxoPos;
        bytes spendingTx;
        uint16 inputIndex;
        bytes witness;
    }

    /** mock what would "verify()" returns */
    function mockResult(bool result) public {
        expectedResult = result;
    }

    /** when called, the spending condition would always revert on purpose */
    function mockRevert() public {
        shouldRevert = true;
    }

    /** provide the expected args, it would check with the value called for "verify()" */
    function shouldVerifyArgumentEquals(Args memory args) public {
        expectedArgs = args;
    }

    /** override */
    function verify(
        bytes calldata inputTx,
        uint256 utxoPos,
        bytes calldata spendingTx,
        uint16 inputIndex,
        bytes calldata witness
    )
        external
        view
        returns (bool)
    {
        if (shouldRevert) {
            revert(REVERT_MESSAGE);
        }

        // only run the check when "shouldVerifyArgumentEqauals" is called
        if (expectedArgs.inputTx.length > 0) {
            require(keccak256(expectedArgs.inputTx) == keccak256(inputTx), "input tx not as expected");
            require(expectedArgs.utxoPos == utxoPos, "utxoPos not as expected");
            require(keccak256(expectedArgs.spendingTx) == keccak256(spendingTx), "spending tx not as expected");
            require(expectedArgs.inputIndex == inputIndex, "input index not as expected");
            require(keccak256(expectedArgs.witness) == keccak256(witness), "witness not as expected");
        }
        return expectedResult;
    }
}

File 8 of 114 : SpyPlasmaFrameworkForExitGame.sol
pragma solidity 0.5.11;
pragma experimental ABIEncoderV2;

import "../../src/framework/PlasmaFramework.sol";
import "../../src/utils/PosLib.sol";
import "../../src/framework/models/BlockModel.sol";

contract SpyPlasmaFrameworkForExitGame is PlasmaFramework {
    using PosLib for PosLib.Position;

    uint256 public enqueuedCount = 0;
    mapping (uint256 => BlockModel.Block) public blocks;

    event EnqueueTriggered(
        uint256 vaultId,
        address token,
        uint64 exitableAt,
        uint256 txPos,
        uint256 exitId,
        address exitProcessor
    );

    /** This spy contract set the authority and maintainer both to the caller */
    constructor(uint256 _minExitPeriod, uint256 _initialImmuneVaults, uint256 _initialImmuneExitGames)
        public
        PlasmaFramework(_minExitPeriod, _initialImmuneVaults, _initialImmuneExitGames, msg.sender, msg.sender)
    {
    }

    /** override for test */
    function enqueue(
        uint256 _vaultId,
        address _token,
        uint64 _exitableAt,
        PosLib.Position calldata _txPos,
        uint160 _exitId,
        IExitProcessor _exitProcessor
    )
        external
        returns (uint256)
    {
        enqueuedCount += 1;
        emit EnqueueTriggered(
            _vaultId,
            _token,
            _exitableAt,
            _txPos.getTxPositionForExitPriority(),
            _exitId,
            address(_exitProcessor)
        );
        return enqueuedCount;
    }

    /**
     Custom test helpers
     */
    function setBlock(uint256 _blockNum, bytes32 _root, uint256 _timestamp) external {
        blocks[_blockNum] = BlockModel.Block(_root, _timestamp);
    }

    function setOutputFinalized(bytes32 _outputId, uint160 _exitId) external {
        outputsFinalizations[_outputId] = _exitId;
    }

    /**
     * Override to remove check that block exists
     */
    function isDeposit(uint256 blockNum) public view returns (bool) {
        return blockNum % childBlockInterval != 0;
    }
}

File 9 of 114 : StateTransitionVerifierMock.sol
pragma solidity 0.5.11;
pragma experimental ABIEncoderV2;

import "../../src/exits/interfaces/IStateTransitionVerifier.sol";

contract StateTransitionVerifierMock is IStateTransitionVerifier {
    bool public expectedResult;
    bool public shouldRevert;
    Args public expectedArgs;

    struct Args {
        bytes inFlightTx;
        bytes[] inputTxs;
        uint16[] outputIndexOfInputTxs;
    }

    /** mock what "isCorrectStateTransition()" returns */
    function mockResult(bool result) public {
        expectedResult = result;
    }

    /** when called, the "isCorrectStateTransition" function reverts on purpose */
    function mockRevert() public {
        shouldRevert = true;
    }

    /** provide the expected args, it would check with the value called for "verify()" */
    function shouldVerifyArgumentEquals(Args memory args)
        public
    {
        expectedArgs = args;
    }

    function isCorrectStateTransition(
        bytes calldata inFlightTx,
        bytes[] calldata inputTxs,
        uint16[] calldata outputIndexOfInputTxs
    )
        external
        view
        returns (bool)
    {
        if (shouldRevert) {
            revert("Failing on purpose");
        }

        // only run the check when "shouldVerifyArgumentEqauals" is called
        if (expectedArgs.inFlightTx.length > 0) {
            require(keccak256(inFlightTx) == keccak256(expectedArgs.inFlightTx), "in-flight tx is not as expected");

            require(inputTxs.length == expectedArgs.inputTxs.length, "input txs array length mismatches expected data");
            for (uint i = 0; i < expectedArgs.inputTxs.length; i++) {
                require(keccak256(inputTxs[i]) == keccak256(expectedArgs.inputTxs[i]), "input tx is not as expected");
            }

            require(outputIndexOfInputTxs.length == expectedArgs.outputIndexOfInputTxs.length, "outputIndex array length mismatches expected data");
            for (uint i = 0; i < expectedArgs.outputIndexOfInputTxs.length; i++) {
                require(outputIndexOfInputTxs[i] == expectedArgs.outputIndexOfInputTxs[i], "output index of input txs is not as expected");
            }
        }

        return expectedResult;
    }
}

File 10 of 114 : SpyErc20VaultForExitGame.sol
pragma solidity 0.5.11;

import "../../../src/vaults/Erc20Vault.sol";
import "../../../src/framework/PlasmaFramework.sol";

contract SpyErc20VaultForExitGame is Erc20Vault {
    event Erc20WithdrawCalled(
        address target,
        address token,
        uint256 amount
    );

    constructor(PlasmaFramework _framework) public Erc20Vault(_framework) {}

    /** override for test */
    function withdraw(address payable _target, address _token, uint256 _amount) external {
        emit Erc20WithdrawCalled(_target, _token, _amount);
    }
}

File 11 of 114 : SpyEthVaultForExitGame.sol
pragma solidity 0.5.11;

import "../../../src/vaults/EthVault.sol";
import "../../../src/framework/PlasmaFramework.sol";

contract SpyEthVaultForExitGame is EthVault {
    uint256 public constant SAFE_GAS_STIPEND = 2300;

    event EthWithdrawCalled(
        address target,
        uint256 amount
    );

    constructor(PlasmaFramework _framework) public EthVault(_framework, SAFE_GAS_STIPEND) {}

    /** override for test */
    function withdraw(address payable _target, uint256 _amount) external {
        emit EthWithdrawCalled(_target, _amount);
    }
}

File 12 of 114 : PaymentInFlightExitModelUtilsMock.sol
pragma solidity 0.5.11;
pragma experimental ABIEncoderV2;

import "../../../src/exits/payment/PaymentInFlightExitModelUtils.sol";
import { PaymentExitDataModel as ExitModel } from "../../../src/exits/payment/PaymentExitDataModel.sol";

contract PaymentInFlightExitModelUtilsMock {

    ExitModel.InFlightExit public ife;

    constructor(uint256 exitMap, uint64 exitStartTimestamp) public {
        ife.exitMap = exitMap;
        ife.exitStartTimestamp = exitStartTimestamp;
    }

    /** Helper functions */
    function setWithdrawData(
        string memory target,
        uint16 index,
        ExitModel.WithdrawData memory data
    )
        public
    {
        if (stringEquals(target, "inputs")) {
            ife.inputs[index] = data;
        } else if (stringEquals(target, "outputs")) {
            ife.outputs[index] = data;
        } else {
            revert("target should be either inputs or outputs");
        }
    }

    function stringEquals(string memory a, string memory b) private pure returns (bool) {
        return keccak256(abi.encodePacked(a)) == keccak256(abi.encodePacked(b));
    }

    /** Wrapper functions */
    function isInputEmpty(uint16 index)
        external
        view
        returns (bool)
    {
        return PaymentInFlightExitModelUtils.isInputEmpty(ife, index);
    }

    function isOutputEmpty(uint16 index)
        external
        view
        returns (bool)
    {
        return PaymentInFlightExitModelUtils.isOutputEmpty(ife, index);
    }

    function isInputPiggybacked(uint16 index)
        external
        view
        returns (bool)
    {
        return PaymentInFlightExitModelUtils.isInputPiggybacked(ife, index);
    }

    function isOutputPiggybacked(uint16 index)
        external
        view
        returns (bool)
    {
        return PaymentInFlightExitModelUtils.isOutputPiggybacked(ife, index);
    }

    function setInputPiggybacked(uint16 index)
        external
    {
        PaymentInFlightExitModelUtils.setInputPiggybacked(ife, index);
    }

    function clearInputPiggybacked(uint16 index)
        external
    {
        PaymentInFlightExitModelUtils.clearInputPiggybacked(ife, index);
    }

    function setOutputPiggybacked(uint16 index)
        external
    {
        PaymentInFlightExitModelUtils.setOutputPiggybacked(ife, index);
    }

    function clearOutputPiggybacked(uint16 index)
        external
    {
        PaymentInFlightExitModelUtils.clearOutputPiggybacked(ife, index);
    }

    function isInFirstPhase(uint256 minExitPeriod)
        external
        view
        returns (bool)
    {
        return PaymentInFlightExitModelUtils.isInFirstPhase(ife, minExitPeriod);
    }
}

File 13 of 114 : PaymentInFlightExitRouterMock.sol
pragma solidity 0.5.11;
pragma experimental ABIEncoderV2;

import "../../../../src/exits/payment/PaymentExitDataModel.sol";
import "../../../../src/exits/payment/routers/PaymentInFlightExitRouter.sol";
import "../../../../src/exits/payment/routers/PaymentInFlightExitRouterArgs.sol";
import "../../../../src/framework/PlasmaFramework.sol";
import "../../../../src/exits/interfaces/IStateTransitionVerifier.sol";
import "../../../../src/exits/payment/PaymentInFlightExitModelUtils.sol";

import "../../../../src/utils/FailFastReentrancyGuard.sol";

contract PaymentInFlightExitRouterMock is FailFastReentrancyGuard, PaymentInFlightExitRouter {
    using PaymentInFlightExitModelUtils for PaymentExitDataModel.InFlightExit;

    PlasmaFramework public framework;

    PaymentInFlightExitRouterArgs.StartExitArgs private startIfeArgs;
    PaymentInFlightExitRouterArgs.PiggybackInFlightExitOnInputArgs private piggybackInputArgs;
    PaymentInFlightExitRouterArgs.PiggybackInFlightExitOnOutputArgs private piggybackOutputArgs;
    PaymentInFlightExitRouterArgs.ChallengeCanonicityArgs private challengeCanonicityArgs;
    PaymentInFlightExitRouterArgs.ChallengeInputSpentArgs private challengeInputSpentArgs;
    PaymentInFlightExitRouterArgs.ChallengeOutputSpent private challengeOutputSpentArgs;

    constructor(PaymentExitGameArgs.Args memory args)
        public
        PaymentInFlightExitRouter(args)
    {
        framework = args.framework;
    }

    /** override and calls processInFlightExit for test */
    function processExit(uint160 exitId, uint256, address ercContract) external {
        PaymentInFlightExitRouter.processInFlightExit(exitId, ercContract);
    }

    function setInFlightExit(uint160 exitId, PaymentExitDataModel.InFlightExit memory exit) public {
        PaymentExitDataModel.InFlightExit storage ife = inFlightExitMap.exits[exitId];
        ife.isCanonical = exit.isCanonical;
        ife.exitStartTimestamp = exit.exitStartTimestamp;
        ife.exitMap = exit.exitMap;
        ife.position = exit.position;
        ife.bondOwner = exit.bondOwner;
        ife.bondSize = exit.bondSize;
        ife.oldestCompetitorPosition = exit.oldestCompetitorPosition;

        for (uint i = 0; i < exit.inputs.length; i++) {
            ife.inputs[i] = exit.inputs[i];
        }

        for (uint i = 0; i < exit.outputs.length; i++) {
            ife.outputs[i] = exit.outputs[i];
        }
    }

    function getInFlightExitInput(uint160 exitId, uint16 inputIndex) public view returns (PaymentExitDataModel.WithdrawData memory) {
        return inFlightExitMap.exits[exitId].inputs[inputIndex];
    }

    function setInFlightExitInputPiggybacked(uint160 exitId, uint16 inputIndex) public payable {
        inFlightExitMap.exits[exitId].setInputPiggybacked(inputIndex);
    }

    function setInFlightExitOutputPiggybacked(uint160 exitId, uint16 outputIndex) public payable {
        inFlightExitMap.exits[exitId].setOutputPiggybacked(outputIndex);
    }

    function getInFlightExitOutput(uint160 exitId, uint16 outputIndex) public view returns (PaymentExitDataModel.WithdrawData memory) {
        return inFlightExitMap.exits[exitId].outputs[outputIndex];
    }

    /** calls the flagOutputFinalized function on behalf of the exit game */
    function proxyFlagOutputFinalized(bytes32 outputId, uint160 exitId) public {
        framework.flagOutputFinalized(outputId, exitId);
    }

    /**
     * This function helps test reentrant by making this function itself the first call with 'nonReentrant' protection
     * So all other PaymentExitGame functions that is protected by 'nonReentrant' too would fail as it would be considered as re-entrancy
     */
    function testNonReentrant(string memory testTarget) public nonReentrant(framework) {
        if (stringEquals(testTarget, "startInFlightExit")) {
            PaymentInFlightExitRouter.startInFlightExit(startIfeArgs);
        } else if (stringEquals(testTarget, "piggybackInFlightExitOnInput")) {
            PaymentInFlightExitRouter.piggybackInFlightExitOnInput(piggybackInputArgs);
        } else if (stringEquals(testTarget, "piggybackInFlightExitOnOutput")) {
            PaymentInFlightExitRouter.piggybackInFlightExitOnOutput(piggybackOutputArgs);
        } else if (stringEquals(testTarget, "challengeInFlightExitNotCanonical")) {
            PaymentInFlightExitRouter.challengeInFlightExitNotCanonical(challengeCanonicityArgs);
        } else if (stringEquals(testTarget, "respondToNonCanonicalChallenge")) {
            PaymentInFlightExitRouter.respondToNonCanonicalChallenge(bytes(""), 0, bytes(""));
        } else if (stringEquals(testTarget, "challengeInFlightExitInputSpent")) {
            PaymentInFlightExitRouter.challengeInFlightExitInputSpent(challengeInputSpentArgs);
        } else if (stringEquals(testTarget, "challengeInFlightExitOutputSpent")) {
            PaymentInFlightExitRouter.challengeInFlightExitOutputSpent(challengeOutputSpentArgs);
        } else if (stringEquals(testTarget, "deleteNonPiggybackedInFlightExit")) {
            PaymentInFlightExitRouter.deleteNonPiggybackedInFlightExit(uint160(0));
        }

        revert("non defined function");
    }

    /** empty function that accepts ETH to fund the contract as test setup */
    function depositFundForTest() public payable {}

    function stringEquals(string memory a, string memory b) private pure returns (bool) {
        return keccak256(abi.encodePacked(a)) == keccak256(abi.encodePacked(b));
    }
}

File 14 of 114 : PaymentStandardExitRouterMock.sol
pragma solidity 0.5.11;
pragma experimental ABIEncoderV2;

import "../../../../src/exits/payment/PaymentExitGameArgs.sol";
import "../../../../src/exits/payment/routers/PaymentStandardExitRouter.sol";
import "../../../../src/exits/payment/routers/PaymentStandardExitRouterArgs.sol";
import "../../../../src/framework/PlasmaFramework.sol";

contract PaymentStandardExitRouterMock is PaymentStandardExitRouter {
    PlasmaFramework private framework;

    PaymentStandardExitRouterArgs.StartStandardExitArgs private startStandardExitArgs;
    PaymentStandardExitRouterArgs.ChallengeStandardExitArgs private challengeStandardExitArgs;

    constructor(PaymentExitGameArgs.Args memory args)
        public
        PaymentStandardExitRouter(args)
    {
        framework = args.framework;
    }

    /** override and calls processStandardExit for test */
    function processExit(uint160 exitId, uint256, address ercContract) external {
        PaymentStandardExitRouter.processStandardExit(exitId, ercContract);
    }

    /** helper functions for testing */
    function setExit(uint160 exitId, PaymentExitDataModel.StandardExit memory exitData) public {
        PaymentStandardExitRouter.standardExitMap.exits[exitId] = exitData;
    }

    function proxyFlagOutputFinalized(bytes32 outputId, uint160 exitId) public {
        framework.flagOutputFinalized(outputId, exitId);
    }

    function depositFundForTest() public payable {}

    /**
     * This function helps test reentrant by making this function itself the first call with 'nonReentrant' protection
     * So all other PaymentExitGame functions that is protected by 'nonReentrant' too would fail as it would be considered as re-entrancy
     */
    function testNonReentrant(string memory testTarget) public nonReentrant(framework) {
        if (stringEquals(testTarget, "startStandardExit")) {
            PaymentStandardExitRouter.startStandardExit(startStandardExitArgs);
        } else if (stringEquals(testTarget, "challengeStandardExit")) {
            PaymentStandardExitRouter.challengeStandardExit(challengeStandardExitArgs);
        }
    }

    function stringEquals(string memory a, string memory b) private pure returns (bool) {
        return keccak256(abi.encodePacked(a)) == keccak256(abi.encodePacked(b));
    }
}

File 15 of 114 : ExitIdWrapper.sol
pragma solidity 0.5.11;

import "../../../src/utils/PosLib.sol";
import "../../../src/exits/utils/ExitId.sol";

contract ExitIdWrapper {
    function isStandardExit(uint160 _exitId) public pure returns (bool) {
        return ExitId.isStandardExit(_exitId);
    }

    function getStandardExitId(bool _isDeposit, bytes memory _txBytes, uint256 _utxoPos)
        public
        pure
        returns (uint160)
    {
        PosLib.Position memory utxoPos = PosLib.decode(_utxoPos);
        return ExitId.getStandardExitId(_isDeposit, _txBytes, utxoPos);
    }

    function getInFlightExitId(bytes memory _txBytes)
        public
        pure
        returns (uint160)
    {
        return ExitId.getInFlightExitId(_txBytes);
    }
}

File 16 of 114 : ExitableTimestampWrapper.sol
pragma solidity 0.5.11;

import "../../../src/exits/utils/ExitableTimestamp.sol";

contract ExitableTimestampWrapper {
    using ExitableTimestamp for ExitableTimestamp.Calculator;
    ExitableTimestamp.Calculator internal calculator;

    constructor(uint256 _minExitPeriod) public {
        calculator = ExitableTimestamp.Calculator(_minExitPeriod);
    }

    function calculateDepositTxOutputExitableTimestamp(
        uint256 _now
    )
        public
        view
        returns (uint64)
    {
        return calculator.calculateDepositTxOutputExitableTimestamp(_now);
    }

    function calculateTxExitableTimestamp(
        uint256 _now,
        uint256 _blockTimestamp
    )
        public
        view
        returns (uint64)
    {
        return calculator.calculateTxExitableTimestamp(_now, _blockTimestamp);
    }
}

File 17 of 114 : MoreVpFinalizationWrapper.sol
pragma solidity 0.5.11;
pragma experimental ABIEncoderV2;

import "../../../src/exits/utils/MoreVpFinalization.sol";

contract MoreVpFinalizationWrapper {
    function isStandardFinalized(
        PlasmaFramework framework,
        bytes memory txBytes,
        uint256 txPos,
        bytes memory inclusionProof
    )
        public
        view
        returns (bool)
    {
        return MoreVpFinalization.isStandardFinalized(
            framework,
            txBytes,
            PosLib.decode(txPos),
            inclusionProof
        );
    }

    function isProtocolFinalized(
        PlasmaFramework framework,
        bytes memory txBytes
    )
        public
        view
        returns (bool)
    {
        return MoreVpFinalization.isProtocolFinalized(
            framework,
            txBytes
        );
    }
}

File 18 of 114 : OutputIdWrapper.sol
pragma solidity 0.5.11;

import "../../../src/exits/utils/OutputId.sol";

contract OutputIdWrapper {
    function computeDepositOutputId(
        bytes memory _txBytes,
        uint8 _outputIndex,
        uint256 _utxoPosValue
    )
        public
        pure
        returns (bytes32)
    {
        return OutputId.computeDepositOutputId(_txBytes, _outputIndex, _utxoPosValue);
    }

    function computeNormalOutputId(
        bytes memory _txBytes,
        uint8 _outputIndex
    )
        public
        pure
        returns (bytes32)
    {
        return OutputId.computeNormalOutputId(_txBytes, _outputIndex);
    }
}

File 19 of 114 : BlockControllerMock.sol
pragma solidity 0.5.11;
pragma experimental ABIEncoderV2;

import "../../src/framework/BlockController.sol";

contract BlockControllerMock is BlockController {
    address private maintainer;

    constructor(
        uint256 interval,
        uint256 minExitPeriod,
        uint256 initialImmuneVaults,
        address authority
    )
        public
        BlockController(
            interval,
            minExitPeriod,
            initialImmuneVaults,
            authority
        )
    {
        maintainer = msg.sender;
    }

    /**
     * override to make it non-abstract contract
     * this mock file set the user that deploys the contract as maintainer to simplify the test.
     */
    function getMaintainer() public view returns (address) {
        return maintainer;
    }

    function setBlock(uint256 _blockNum, bytes32 _root, uint256 _timestamp) external {
        blocks[_blockNum] = BlockModel.Block(_root, _timestamp);
    }
}

File 20 of 114 : DummyExitGame.sol
pragma solidity 0.5.11;
pragma experimental ABIEncoderV2;

import "./registries/ExitGameRegistryMock.sol";
import "../../src/framework/ExitGameController.sol";
import "../../src/framework/interfaces/IExitProcessor.sol";
import "../../src/vaults/Erc20Vault.sol";
import "../../src/vaults/EthVault.sol";
import "../../src/utils/PosLib.sol";

contract DummyExitGame is IExitProcessor {
    uint256 public priorityFromEnqueue;

    ExitGameRegistryMock public exitGameRegistry;
    ExitGameController public exitGameController;
    EthVault public ethVault;
    Erc20Vault public erc20Vault;

    event ExitFinalizedFromDummyExitGame (
        uint256 indexed exitId,
        uint256 vaultId,
        address ercContract
    );

    // override ExitProcessor interface
    function processExit(uint160 exitId, uint256 vaultId, address ercContract) public {
        emit ExitFinalizedFromDummyExitGame(exitId, vaultId, ercContract);
    }

    // setter function only for test, not a real Exit Game function
    function setExitGameRegistry(address _contract) public {
        exitGameRegistry = ExitGameRegistryMock(_contract);
    }

    function checkOnlyFromNonQuarantinedExitGame() public view returns (bool) {
        return exitGameRegistry.checkOnlyFromNonQuarantinedExitGame();
    }

    // setter function only for test, not a real Exit Game function
    function setExitGameController(address _contract) public {
        exitGameController = ExitGameController(_contract);
    }

    function enqueue(uint256 vaultId, address token, uint64 exitableAt, uint256 txPos, uint160 exitId, IExitProcessor exitProcessor)
        public
    {
        priorityFromEnqueue = exitGameController.enqueue(vaultId, token, exitableAt, PosLib.decode(txPos), exitId, exitProcessor);
    }

    function proxyBatchFlagOutputsFinalized(bytes32[] memory outputIds, uint160 exitId) public {
        exitGameController.batchFlagOutputsFinalized(outputIds, exitId);
    }

    function proxyFlagOutputFinalized(bytes32 outputId, uint160 exitId) public {
        exitGameController.flagOutputFinalized(outputId, exitId);
    }

    // setter function only for test, not a real Exit Game function
    function setEthVault(EthVault vault) public {
        ethVault = vault;
    }

    function proxyEthWithdraw(address payable target, uint256 amount) public {
        ethVault.withdraw(target, amount);
    }

    // setter function only for test, not a real Exit Game function
    function setErc20Vault(Erc20Vault vault) public {
        erc20Vault = vault;
    }

    function proxyErc20Withdraw(address payable target, address token, uint256 amount) public {
        erc20Vault.withdraw(target, token, amount);
    }
}

File 21 of 114 : DummyVault.sol
pragma solidity 0.5.11;

import "./registries/VaultRegistryMock.sol";
import "../../src/framework/BlockController.sol";

contract DummyVault {
    VaultRegistryMock internal vaultRegistry;
    BlockController internal blockController;

    // setter function only for test, not a real Vault function
    function setVaultRegistry(address _contract) public {
        vaultRegistry = VaultRegistryMock(_contract);
    }

    function checkOnlyFromNonQuarantinedVault() public view returns (bool) {
        return vaultRegistry.checkOnlyFromNonQuarantinedVault();
    }

    // setter function only for test, not a real Vault function
    function setBlockController(address _contract) public {
        blockController = BlockController(_contract);
    }

    function submitDepositBlock(bytes32 _blockRoot) public {
        blockController.submitDepositBlock(_blockRoot);
    }
}

File 22 of 114 : ExitGameControllerMock.sol
pragma solidity 0.5.11;
pragma experimental ABIEncoderV2;

import "../../src/framework/ExitGameController.sol";

contract ExitGameControllerMock is ExitGameController {
    address private maintainer;

    constructor(uint256 _minExitPeriod, uint256 _initialImmuneExitGames)
        public
        ExitGameController(_minExitPeriod, _initialImmuneExitGames)
    {
        maintainer = msg.sender;
    }

    /**
     * override to make it non-abstract contract
     * this mock file set the user that deploys the contract as maintainer to simplify the test.
     */
    function getMaintainer() public view returns (address) {
        return maintainer;
    }
}

File 23 of 114 : ProtocolWrapper.sol
pragma solidity 0.5.11;

import "../../src/framework/Protocol.sol";

contract ProtocolWrapper {
    // solhint-disable-next-line func-name-mixedcase
    function MVP() public pure returns (uint8) {
        return Protocol.MVP();
    }

    // solhint-disable-next-line func-name-mixedcase
    function MORE_VP() public pure returns (uint8) {
        return Protocol.MORE_VP();
    }

    function isValidProtocol(uint8 protocol) public pure returns (bool) {
        return Protocol.isValidProtocol(protocol);
    }
}

File 24 of 114 : ReentrancyExitGame.sol
pragma solidity 0.5.11;
pragma experimental ABIEncoderV2;

import "../../src/framework/ExitGameController.sol";
import "../../src/framework/interfaces/IExitProcessor.sol";

contract ReentrancyExitGame is IExitProcessor {
    ExitGameController public exitGameController;
    uint256 public vaultId;
    address public testToken;
    uint256 public reentryMaxExitToProcess;

    constructor(ExitGameController _controller, uint256 _vaultId, address _token, uint256 _reentryMaxExitToProcess) public {
        exitGameController = _controller;
        vaultId = _vaultId;
        testToken = _token;
        reentryMaxExitToProcess = _reentryMaxExitToProcess;
    }

    // override ExitProcessor interface
    // This would call the processExits back to mimic reentracy attack
    function processExit(uint160, uint256, address) public {
        exitGameController.processExits(vaultId, testToken, 0, reentryMaxExitToProcess);
    }

    function enqueue(uint256 _vaultId, address _token, uint64 _exitableAt, uint256 _txPos, uint160 _exitId, IExitProcessor _exitProcessor)
        public
    {
        exitGameController.enqueue(_vaultId, _token, _exitableAt, PosLib.decode(_txPos), _exitId, _exitProcessor);
    }
}

File 25 of 114 : ExitGameRegistryMock.sol
pragma solidity 0.5.11;

import "../../../src/framework/registries/ExitGameRegistry.sol";

contract ExitGameRegistryMock is ExitGameRegistry {
    address private maintainer;

    constructor (uint256 _minExitPeriod, uint256 _initialImmuneExitGames)
        public
        ExitGameRegistry(_minExitPeriod, _initialImmuneExitGames)
    {
    }

    /** override to make it non-abstract contract */
    function getMaintainer() public view returns (address) {
        return maintainer;
    }

    /** test helper function */
    function setMaintainer(address maintainerToSet) public {
        maintainer = maintainerToSet;
    }

    function checkOnlyFromNonQuarantinedExitGame() public onlyFromNonQuarantinedExitGame view returns (bool) {
        return true;
    }
}

File 26 of 114 : VaultRegistryMock.sol
pragma solidity 0.5.11;

import "../../../src/framework/registries/VaultRegistry.sol";

contract VaultRegistryMock is VaultRegistry {
    address private maintainer;

    constructor (uint256 _minExitPeriod, uint256 _initialImmuneVaults)
        public
        VaultRegistry(_minExitPeriod, _initialImmuneVaults)
    {
    }

    /** override to make it non-abstract contract */
    function getMaintainer() public view returns (address) {
        return maintainer;
    }

    /** test helper function */
    function setMaintainer(address maintainerToSet) public {
        maintainer = maintainerToSet;
    }

    function checkOnlyFromNonQuarantinedVault() public onlyFromNonQuarantinedVault view returns (bool) {
        return true;
    }
}

File 27 of 114 : ExitPriorityWrapper.sol
pragma solidity 0.5.11;

import "../../../src/framework/utils/ExitPriority.sol";
import "../../../src/utils/PosLib.sol";

contract ExitPriorityWrapper {
    function computePriority(uint64 exitableAt, uint256 txPos, uint160 exitId) public pure returns (uint256) {
        return ExitPriority.computePriority(exitableAt, PosLib.decode(txPos), exitId);
    }

    function parseExitableAt(uint256 priority) public pure returns (uint64) {
        return ExitPriority.parseExitableAt(priority);
    }

    function parseExitId(uint256 priority) public pure returns (uint160) {
        return ExitPriority.parseExitId(priority);
    }
}

File 28 of 114 : PriorityQueueLoadTest.sol
pragma solidity 0.5.11;

import "../../../src/framework/utils/PriorityQueue.sol";

contract PriorityQueueLoadTest is PriorityQueue {

    /**
     * Helper function to inject heap data. It only appends batch of data to the end of array used as heap.
     * The client using this should make sure the data is in the order of an valid heap.
     */
    function setHeapData(uint256[] calldata heapList) external {
        for (uint i = 0; i < heapList.length; i++) {
            PriorityQueue.queue.heapList.push(heapList[i]);
        }
        PriorityQueue.queue.currentSize += heapList.length;
    }
}

File 29 of 114 : PriorityQueueTest.sol
pragma solidity ^0.5.0;
import "../../src/framework/utils/PriorityQueue.sol";

/**
 * @title PriorityQueue
 * @dev Min-heap priority queue implementation.
 */
contract PriorityQueueTest{

    /*
     * Events
     */

    event DelMin(uint256 val);

    /*
     *  Storage
     */

    PriorityQueue public queue;
    /*
     *  Public functions
     */

    constructor()
        public
    {
        queue = new PriorityQueue();
    }

    /**
     * @dev Inserts an element into the queue. Does not perform deduplication.
     */
    function insert(uint256 _element)
        public
    {
        queue.insert(_element);
    }

    /**
     * @dev Overrides the default implementation, by simply emitting an even on deletion, so that the result is testable.
     * @return The smallest element in the priority queue.
     */
    function delMin()
        public
        returns (uint256 value)
    {
        value = queue.delMin();
        emit DelMin(value);
    }

    /*
     * Read-only functions
     */
    /**
     * @dev Returns the top element of the heap.
     * @return The smallest element in the priority queue.
     */
    function getMin()
        public
        view
        returns (uint256)
    {
        return queue.getMin();
    }

    function currentSize()
        external
        view
        returns (uint256)
    {
        return queue.currentSize();
    }
}

File 30 of 114 : RLPTest.sol
pragma solidity ^0.5.0;

import "../../src/utils/RLPReader.sol";


/**
 * @title RLPTest
 * @dev Contract for testing RLP decoding.
 */
contract RLPTest {
    function eight(bytes memory tx_bytes)
        public
        pure
        returns (uint256, address, address)
    {
        RLPReader.RLPItem[] memory txList = RLPReader.toList(RLPReader.toRlpItem(tx_bytes));
        return (
            RLPReader.toUint(txList[5]),
            RLPReader.toAddress(txList[6]),
            RLPReader.toAddress(txList[7])
        );
    }

    function eleven(bytes memory tx_bytes)
        public
        pure
        returns (uint256, address, address, address)
    {
        RLPReader.RLPItem[] memory  txList = RLPReader.toList(RLPReader.toRlpItem(tx_bytes));
        return (
            RLPReader.toUint(txList[7]),
            RLPReader.toAddress(txList[8]),
            RLPReader.toAddress(txList[9]),
            RLPReader.toAddress(txList[10])
        );
    }
}

File 31 of 114 : FungibleTokenOutputWrapper.sol
pragma solidity 0.5.11;
pragma experimental ABIEncoderV2;

import "../../src/transactions/FungibleTokenOutputModel.sol";

contract FungibleTokenOutputWrapper {
    using RLPReader for bytes;
    using RLPReader for RLPReader.RLPItem;

    function decodeOutput(bytes memory encodedOutput)
        public
        pure
        returns (FungibleTokenOutputModel.Output memory)
    {
        GenericTransaction.Output memory genericOutput = GenericTransaction.decodeOutput(encodedOutput.toRlpItem());
        return FungibleTokenOutputModel.decodeOutput(genericOutput);
    }

    function getOutput(bytes memory transaction, uint16 outputIndex)
        public
        pure
        returns (FungibleTokenOutputModel.Output memory)
    {
        GenericTransaction.Transaction memory genericTx = GenericTransaction.decode(transaction);
        return FungibleTokenOutputModel.getOutput(genericTx, outputIndex);
    }
}

File 32 of 114 : GenericTransactionWrapper.sol
pragma solidity 0.5.11;
pragma experimental ABIEncoderV2;

import "../../src/transactions/GenericTransaction.sol";

contract GenericTransactionWrapper {

    function decode(bytes memory transaction) public pure returns (GenericTransaction.Transaction memory) {
        return GenericTransaction.decode(transaction);
    }

    function getOutput(bytes memory transaction, uint16 outputIndex) public pure returns (GenericTransaction.Output memory) {
        GenericTransaction.Transaction memory genericTx = GenericTransaction.decode(transaction);
        return GenericTransaction.getOutput(genericTx, outputIndex);
    }
}

File 33 of 114 : PaymentTransactionModelMock.sol
pragma solidity 0.5.11;
pragma experimental ABIEncoderV2;

import "../../src/transactions/PaymentTransactionModel.sol";

contract PaymentTransactionModelMock {
    using RLPReader for bytes;

    function decode(bytes memory transaction) public pure returns (PaymentTransactionModel.Transaction memory) {
        return PaymentTransactionModel.decode(transaction);
    }

    function getOutputOwner(uint256 outputType, address owner, address token, uint256 amount) public pure returns (address payable) {
        FungibleTokenOutputModel.Output memory output = FungibleTokenOutputModel.Output({
            outputType: outputType,
            outputGuard: bytes20(owner),
            token: token,
            amount: amount
        });
        return PaymentTransactionModel.getOutputOwner(output);
    }

    function getOutput(bytes memory transaction, uint16 outputIndex) public pure returns (FungibleTokenOutputModel.Output memory) {
        PaymentTransactionModel.Transaction memory decodedTx = PaymentTransactionModel.decode(transaction);
        return PaymentTransactionModel.getOutput(decodedTx, outputIndex);
    }
}

File 34 of 114 : PaymentEip712LibMock.sol
pragma solidity 0.5.11;

import "../../../src/transactions/eip712Libs/PaymentEip712Lib.sol";
import "../../../src/transactions/PaymentTransactionModel.sol";

contract PaymentEip712LibMock {
    function hashTx(address _verifyingContract, bytes memory _rlpTx)
        public
        pure
        returns (bytes32)
    {
        PaymentEip712Lib.Constants memory eip712 = PaymentEip712Lib.initConstants(_verifyingContract);
        return PaymentEip712Lib.hashTx(eip712, PaymentTransactionModel.decode(_rlpTx));
    }
}

File 35 of 114 : BitsWrapper.sol
pragma solidity 0.5.11;

import "../../src/utils/Bits.sol";

contract BitsWrapper {
    function setBit(uint _self, uint8 _index) public pure returns (uint)
    {
        return Bits.setBit(_self, _index);
    }

    function clearBit(uint _self, uint8 _index) public pure returns (uint)
    {
        return Bits.clearBit(_self, _index);
    }

    /**
     * @dev It makes sense to expose just `bitSet` to be able to test both of Bits `getBit` and `bitSet`
     */
    function bitSet(uint _self, uint8 _index) public pure returns (bool)
    {
        return Bits.bitSet(_self, _index);
    }
}

File 36 of 114 : BondSizeMock.sol
pragma solidity 0.5.11;

import "../../src/exits/utils/BondSize.sol";

contract BondSizeMock {
    using BondSize for BondSize.Params;

    BondSize.Params public bond;

    constructor (uint128 initialBondSize, uint16 lowerBoundDivisor, uint16 upperBoundMultiplier) public {
        bond = BondSize.buildParams(initialBondSize, lowerBoundDivisor, upperBoundMultiplier);
    }

    function bondSize() public view returns (uint128) {
        return bond.bondSize();
    }

    function updateBondSize(uint128 newBondSize) public {
        bond.updateBondSize(newBondSize);
    }
}

File 37 of 114 : MerkleWrapper.sol
pragma solidity 0.5.11;

import "../../src/utils/Merkle.sol";

contract MerkleWrapper {

    function checkMembership(bytes memory leaf, uint256 index, bytes32 rootHash, bytes memory proof)
        public
        pure
        returns (bool)
    {
        return Merkle.checkMembership(leaf, index, rootHash, proof);
    }
}

File 38 of 114 : OnlyWithValueMock.sol
pragma solidity 0.5.11;

import "../../src/utils/OnlyWithValue.sol";

contract OnlyWithValueMock is OnlyWithValue {
    event OnlyWithValuePassed();

    function checkOnlyWithValue(uint256 _value) public payable onlyWithValue(_value) {
        emit OnlyWithValuePassed();
    }
}

File 39 of 114 : PosLibWrapper.sol
pragma solidity 0.5.11;
pragma experimental ABIEncoderV2;

import "../../src/utils/PosLib.sol";

contract PosLibWrapper {
    using PosLib for PosLib.Position;

    function toStrictTxPos(PosLib.Position memory pos)
        public
        pure
        returns (PosLib.Position memory)
    {
        return pos.toStrictTxPos();
    }

    function getTxPositionForExitPriority(PosLib.Position memory pos)
        public
        pure
        returns (uint256)
    {
        return pos.getTxPositionForExitPriority();
    }

    function encode(PosLib.Position memory pos) public pure returns (uint256) {
        return pos.encode();
    }

    function decode(uint256 pos) public pure returns (PosLib.Position memory) {
        return PosLib.decode(pos);
    }
}

File 40 of 114 : QuarantineMock.sol
pragma solidity 0.5.11;

import "../../src/framework/utils/Quarantine.sol";

contract QuarantineMock {
    using Quarantine for Quarantine.Data;
    Quarantine.Data internal _quarantine;

    constructor(uint256 _period, uint256 _initialImmuneCount)
        public
    {
        _quarantine.quarantinePeriod = _period;
        _quarantine.immunitiesRemaining = _initialImmuneCount;
    }

    function quarantineContract(address _contractAddress) public {
        _quarantine.quarantine(_contractAddress);
    }

    function isQuarantined(address _contractAddress) public view returns (bool) {
        return _quarantine.isQuarantined(_contractAddress);
    }
}

File 41 of 114 : RLPMock.sol
pragma solidity 0.5.11;

pragma experimental ABIEncoderV2;

import "../../src/utils/RLPReader.sol";

contract RLPMock {

    using RLPReader for bytes;
    using RLPReader for RLPReader.RLPItem;

    uint8 constant internal WORD_SIZE = 32;

    function decodeBytes32(bytes memory _data) public pure returns (bytes32) {
        return _data.toRlpItem().toBytes32();
    }

    function decodeAddress(bytes memory _data) public pure returns (address) {
        return _data.toRlpItem().toAddress();
    }
    
    function decodeBytes20(bytes memory _data) public pure returns (bytes20) {
        return bytes20(_data.toRlpItem().toAddress());
    }

    function decodeBytes(bytes memory _data) public pure returns (bytes memory) {
        return toBytes(_data.toRlpItem());
    }

    function decodeUint(bytes memory _data) public pure returns (uint) {
        return _data.toRlpItem().toUint();
    }

    function decodeInt(bytes memory _data) public pure returns (int) {
        return int(_data.toRlpItem().toUint());
    }

    function decodeString(bytes memory _data) public pure returns (string memory) {
        return string(toBytes(_data.toRlpItem()));
    }

    function decodeList(bytes memory _data) public pure returns (bytes[] memory) {

        RLPReader.RLPItem[] memory items = _data.toRlpItem().toList();

        bytes[] memory result =  new bytes[](items.length);
        for (uint i = 0; i < items.length; i++) {
            result[i] = toRlpBytes(items[i]);
        }
        return result;
    }

    function toBytes(RLPReader.RLPItem memory item) internal pure returns (bytes memory) {
        require(item.len > 0, "Item length must be > 0");

        (uint256 itemLen, uint256 offset) = RLPReader.decodeLengthAndOffset(item.memPtr);
        require(itemLen == item.len, "Decoded RLP length is invalid");
        uint len = itemLen - offset;
        bytes memory result = new bytes(len);

        uint destPtr;
        // solhint-disable-next-line no-inline-assembly
        assembly {
            destPtr := add(0x20, result)
        }

        copyUnsafe(item.memPtr + offset, destPtr, len);
        return result;
    }

    function copyUnsafe(uint src, uint dest, uint len) private pure {
        if (len == 0) return;
        uint remainingLength = len;

        // copy as many word sizes as possible
        for (uint i = WORD_SIZE; len >= i; i += WORD_SIZE) {
            // solhint-disable-next-line no-inline-assembly
            assembly {
                mstore(dest, mload(src))
            }

            src += WORD_SIZE;
            dest += WORD_SIZE;
            remainingLength -= WORD_SIZE;
            require(remainingLength < len, "Remaining length not less than original length");
        }

        // left over bytes. Mask is used to remove unwanted bytes from the word
        uint mask = 256 ** (WORD_SIZE - remainingLength) - 1;

        // solhint-disable-next-line no-inline-assembly
        assembly {
            let srcpart := and(mload(src), not(mask)) // zero out src
            let destpart := and(mload(dest), mask) // retrieve the bytes
            mstore(dest, or(destpart, srcpart))
        }
    }

    function toRlpBytes(RLPReader.RLPItem memory item) internal pure returns (bytes memory) {
        bytes memory result = new bytes(item.len);
        if (result.length == 0) return result;

        uint resultPtr;
        // solhint-disable-next-line no-inline-assembly
        assembly {
            resultPtr := add(0x20, result)
        }

        copyUnsafe(item.memPtr, resultPtr, item.len);
        return result;
    }
}

File 42 of 114 : RLPMockSecurity.sol
pragma solidity 0.5.11;

pragma experimental ABIEncoderV2;

import "../../src/utils/RLPReader.sol";

contract RLPMockSecurity {

    using RLPReader for bytes;
    using RLPReader for RLPReader.RLPItem;

    function decodeBytes32(bytes memory _data) public pure returns (bytes32) {
        return bytes32(_data.toRlpItem().toUint());
    }

    function decodeBytes20(bytes memory _data) public pure returns (bytes20) {
        return bytes20(_data.toRlpItem().toAddress());
    }

    function decodeUint(bytes memory _data) public pure returns (uint) {
        return _data.toRlpItem().toUint();
    }

    function decodeList(bytes memory _data) public pure returns (RLPReader.RLPItem[] memory) {
        return _data.toRlpItem().toList();
    }
}

File 43 of 114 : SafeEthTransferMock.sol
pragma solidity 0.5.11;

import "../../src/utils/SafeEthTransfer.sol";

contract SafeEthTransferMock {
    bool public transferResult;

    function transferRevertOnError(address payable receiver, uint256 amount, uint256 gasStipend)
        public
    {
        SafeEthTransfer.transferRevertOnError(receiver, amount, gasStipend);
    }

    function transferReturnResult(address payable receiver, uint256 amount, uint256 gasStipend)
        public
    {
        transferResult = SafeEthTransfer.transferReturnResult(receiver, amount, gasStipend);
    }

    /** helper function to pre-fund the contract to test */
    function setupInitialFundToTestTransfer() external payable {}
}

File 44 of 114 : NonCompliantERC20.sol
pragma solidity 0.5.11;

import "openzeppelin-solidity/contracts/math/SafeMath.sol";

// A 'NonCompliantERC20' token is one that uses an old version of the ERC20 standard,
// as described here https://medium.com/coinmonks/missing-return-value-bug-at-least-130-tokens-affected-d67bf08521ca
// Basically, this version does not return anything from `transfer` and `transferFrom`,
// whereas most modern implementions of ERC20 return a boolean to indicate success or failure.
contract NonCompliantERC20 {
    using SafeMath for uint256;

    mapping (address => uint256) private balances;
    mapping (address => mapping (address => uint256)) private allowances;
    uint256 private totalSupply;

    constructor(uint256 _initialAmount) public {
        balances[msg.sender] = _initialAmount;
        totalSupply = _initialAmount;
    }

    function balanceOf(address _account) public view returns (uint256) {
        return balances[_account];
    }

    function transfer(address _to, uint _value) public {
        balances[msg.sender] = balances[msg.sender].sub(_value);
        balances[_to] = balances[_to].add(_value);
    }

    function transferFrom(address _from, address _to, uint _value) public {
        uint256 _allowance = allowances[_from][msg.sender];

        balances[_to] = balances[_to].add(_value);
        balances[_from] = balances[_from].sub(_value);
        allowances[_from][msg.sender] = _allowance.sub(_value);
    }

    function approve(address _spender, uint _value) public {
        allowances[msg.sender][_spender] = _value;
    }

    function allowance(address _owner, address _spender) public view returns (uint256 remaining) {
        return allowances[_owner][_spender];
    }
}

File 45 of 114 : FeeClaimOutputToPaymentTxCondition.sol
pragma solidity 0.5.11;

import "openzeppelin-solidity/contracts/cryptography/ECDSA.sol";

import "../interfaces/ISpendingCondition.sol";
import "../utils/OutputId.sol";
import "../../framework/PlasmaFramework.sol";
import "../../transactions/FungibleTokenOutputModel.sol";
import "../../transactions/GenericTransaction.sol";
import "../../transactions/PaymentTransactionModel.sol";
import "../../transactions/eip712Libs/PaymentEip712Lib.sol";
import "../../utils/PosLib.sol";

contract FeeClaimOutputToPaymentTxCondition is ISpendingCondition {
    using PaymentEip712Lib for PaymentEip712Lib.Constants;
    using PosLib for PosLib.Position;

    uint256 public feeTxType;
    uint256 public feeClaimOutputType;
    uint256 public paymentTxType;
    PaymentEip712Lib.Constants internal eip712;

    constructor(
        PlasmaFramework _framework,
        uint256 _feeTxType,
        uint256 _feeClaimOutputType,
        uint256 _paymentTxType
    )
        public
    {
        eip712 = PaymentEip712Lib.initConstants(address(_framework));
        feeTxType = _feeTxType;
        feeClaimOutputType = _feeClaimOutputType;
        paymentTxType = _paymentTxType;
    }

    /**
     * @dev This implementation checks signature for spending fee claim output. It should be signed with the owner signature.
     *      The fee claim output that is spendable follows Fungible Token Output format.
     * @param feeTxBytes Encoded fee transaction
     * @param utxoPos Position of the fee utxo
     * @param paymentTxBytes Payment transaction (in bytes) that spends the fee claim output
     * @param inputIndex Input index of the payment tx that points to the fee claim output
     * @param signature Signature of the owner of fee claiming output
     */
    function verify(
        bytes calldata feeTxBytes,
        uint256 utxoPos,
        bytes calldata paymentTxBytes,
        uint16 inputIndex,
        bytes calldata signature
    )
        external
        view
        returns (bool)
    {
        PosLib.Position memory decodedUtxoPos = PosLib.decode(utxoPos);
        require(decodedUtxoPos.outputIndex == 0, "Fee claim output must be the first output of fee tx");

        GenericTransaction.Transaction memory feeTx = GenericTransaction.decode(feeTxBytes);
        FungibleTokenOutputModel.Output memory feeClaimOutput = FungibleTokenOutputModel.getOutput(feeTx, decodedUtxoPos.outputIndex);

        require(feeTx.txType == feeTxType, "Unexpected tx type for fee transaction");
        require(feeClaimOutput.outputType == feeClaimOutputType, "Unexpected output type for fee claim output");

        PaymentTransactionModel.Transaction memory paymentTx = PaymentTransactionModel.decode(paymentTxBytes);
        require(paymentTx.txType == paymentTxType, "Unexpected tx type for payment transaction");

        require(
            paymentTx.inputs[inputIndex] == bytes32(decodedUtxoPos.encode()),
            "Payment tx points to the incorrect output UTXO position of the fee claim output"
        );

        address owner = address(feeClaimOutput.outputGuard);
        address signer = ECDSA.recover(eip712.hashTx(paymentTx), signature);
        require(signer != address(0), "Failed to recover the signer from the signature");
        require(owner == signer, "Tx is not signed correctly");

        return true;
    }
}

File 46 of 114 : FeeExitGame.sol
pragma solidity 0.5.11;

/**
* It is an empty contract by design. We only want to be able to register the tx type to the framework.
* For simplicity, a fee claiming tx does not have the ability to exit directly.
* It should be first spend to a Payment tx and then exit the fund from Payment tx.
*/
contract FeeExitGame {
}

File 47 of 114 : ISpendingCondition.sol
pragma solidity 0.5.11;

/**
 * @notice Interface of the spending condition
 * @dev For the interface design and discussion, see the following GH issue
 *      https://github.com/omisego/plasma-contracts/issues/214
 */
interface ISpendingCondition {

    /**
     * @notice Verifies the spending condition
     * @param inputTx Encoded input transaction, in bytes
     * @param utxoPos Position of the utxo
     * @param spendingTx Spending transaction, in bytes
     * @param inputIndex The input index of the spending tx that points to the output
     * @param witness The witness data of the spending condition
     */
    function verify(
        bytes calldata inputTx,
        uint256 utxoPos,
        bytes calldata spendingTx,
        uint16 inputIndex,
        bytes calldata witness
    ) external view returns (bool);
}

File 48 of 114 : IStateTransitionVerifier.sol
pragma solidity 0.5.11;
pragma experimental ABIEncoderV2;

interface IStateTransitionVerifier {

    /**
    * @notice Verifies state transition logic
    * @param txBytes The transaction that does the state transition to verify
    * @param inputTxs Input transaction to the transaction to verify
    * @param outputIndexOfInputTxs Output index of the input txs that the transaction input points to
    */
    function isCorrectStateTransition(
        bytes calldata txBytes,
        bytes[] calldata inputTxs,
        uint16[] calldata outputIndexOfInputTxs
    )
        external
        view
        returns (bool);
}

File 49 of 114 : PaymentExitDataModel.sol
pragma solidity 0.5.11;

/**
 * @notice Model library for PaymentExit
 */
library PaymentExitDataModel {
    uint8 constant public MAX_INPUT_NUM = 4;
    uint8 constant public MAX_OUTPUT_NUM = 4;

    /**
     * @dev Exit model for a standard exit
     * @param exitable Boolean that defines whether exit is possible. Used by the challenge game to flag the result.
     * @param utxoPos The UTXO position of the transaction's exiting output
     * @param outputId The output identifier, in OutputId format
     * @param exitTarget The address to which the exit withdraws funds
     * @param amount The amount of funds to withdraw with this exit
     * @param bondSize The size of the bond put up for this exit to start, and which is used to cover the cost of challenges
     */
    struct StandardExit {
        bool exitable;
        uint256 utxoPos;
        bytes32 outputId;
        address payable exitTarget;
        uint256 amount;
        uint256 bondSize;
    }

    /**
     * @dev Mapping of (exitId => StandardExit) that stores all standard exit data
     */
    struct StandardExitMap {
        mapping (uint160 => PaymentExitDataModel.StandardExit) exits;
    }

    /**
     * @dev The necessary data needed for processExit for in-flight exit inputs/outputs
     */
    struct WithdrawData {
        bytes32 outputId;
        address payable exitTarget;
        address token;
        uint256 amount;
        uint256 piggybackBondSize;
    }

    /**
     * @dev Exit model for an in-flight exit
     * @param isCanonical A boolean that defines whether the exit is canonical
     *                    A canonical exit withdraws the outputs while a non-canonical exit withdraws the  inputs
     * @param exitStartTimestamp Timestamp for the start of the exit
     * @param exitMap A bitmap that stores piggyback flags
     * @param position The position of the youngest input of the in-flight exit transaction
     * @param inputs Fixed-size array of data required to withdraw inputs (if undefined, the default value is empty)
     * @param outputs Fixed-size array of data required to withdraw outputs (if undefined, the default value is empty)
     * @param bondOwner Recipient of the bond, when the in-flight exit is processed
     * @param bondSize The size of the bond put up for this exit to start. Used to cover the cost of challenges.
     * @param oldestCompetitorPosition The position of the oldest competing transaction
     *                                 The exiting transaction is only canonical if all competing transactions are younger.
     */
    struct InFlightExit {
        // Canonicity is assumed at start, and can be challenged and set to `false` after start
        // Response to non-canonical challenge can set it back to `true`
        bool isCanonical;
        uint64 exitStartTimestamp;

        /**
         * exit map Stores piggybacks and finalized exits
         * right most 0 ~ MAX_INPUT bits is flagged when input is piggybacked
         * right most MAX_INPUT ~ MAX_INPUT + MAX_OUTPUT bits is flagged when output is piggybacked
         */
        uint256 exitMap;
        uint256 position;
        WithdrawData[MAX_INPUT_NUM] inputs;
        WithdrawData[MAX_OUTPUT_NUM] outputs;
        address payable bondOwner;
        uint256 bondSize;
        uint256 oldestCompetitorPosition;
    }

    /**
     * @dev Mapping of (exitId => InFlightExit) that stores all in-flight exit data
     */
    struct InFlightExitMap {
        mapping (uint160 => PaymentExitDataModel.InFlightExit) exits;
    }
}

File 50 of 114 : PaymentExitGameArgs.sol
pragma solidity 0.5.11;

import "../registries/SpendingConditionRegistry.sol";
import "../interfaces/IStateTransitionVerifier.sol";
import "../../framework/PlasmaFramework.sol";

library PaymentExitGameArgs {
    /**
     * @param framework The Plasma framework
     * @param ethVaultId Vault id for EthVault
     * @param erc20VaultId Vault id for the Erc20Vault
     * @param spendingConditionRegistry the spendingConditionRegistry that can provide spending condition implementation by types
     * @param stateTransitionVerifier state transition verifier predicate contract that checks the transaction correctness
     * @param supportTxType the tx type of this exit game is using
     * @param safeGasStipend a gas amount limit when transferring Eth to protect from attack with draining gas
     */
    struct Args {
        PlasmaFramework framework;
        uint256 ethVaultId;
        uint256 erc20VaultId;
        SpendingConditionRegistry spendingConditionRegistry;
        IStateTransitionVerifier stateTransitionVerifier;
        uint256 supportTxType;
        uint256 safeGasStipend;
    }
}

File 51 of 114 : PaymentInFlightExitModelUtils.sol
pragma solidity 0.5.11;
pragma experimental ABIEncoderV2;

import "../../utils/Bits.sol";
import "../../transactions/PaymentTransactionModel.sol";
import { PaymentExitDataModel as ExitModel } from "./PaymentExitDataModel.sol";

library PaymentInFlightExitModelUtils {
    using Bits for uint256;

    function isInputEmpty(ExitModel.InFlightExit memory ife, uint16 index)
        internal
        pure
        returns (bool)
    {
        require(index < PaymentTransactionModel.MAX_INPUT_NUM(), "Invalid input index");
        return isEmptyWithdrawData(ife.inputs[index]);
    }

    function isOutputEmpty(ExitModel.InFlightExit memory ife, uint16 index)
        internal
        pure
        returns (bool)
    {
        require(index < PaymentTransactionModel.MAX_OUTPUT_NUM(), "Invalid output index");
        return isEmptyWithdrawData(ife.outputs[index]);
    }

    function isInputPiggybacked(ExitModel.InFlightExit memory ife, uint16 index)
        internal
        pure
        returns (bool)
    {
        require(index < PaymentTransactionModel.MAX_INPUT_NUM(), "Invalid input index");
        return ife.exitMap.bitSet(uint8(index));
    }

    function isOutputPiggybacked(ExitModel.InFlightExit memory ife, uint16 index)
        internal
        pure
        returns (bool)
    {
        require(index < PaymentTransactionModel.MAX_OUTPUT_NUM(), "Invalid output index");
        uint8 indexInExitMap = uint8(index + PaymentTransactionModel.MAX_INPUT_NUM());
        return ife.exitMap.bitSet(indexInExitMap);
    }

    function setInputPiggybacked(ExitModel.InFlightExit storage ife, uint16 index)
        internal
    {
        require(index < PaymentTransactionModel.MAX_INPUT_NUM(), "Invalid input index");
        ife.exitMap = ife.exitMap.setBit(uint8(index));
    }

    function clearInputPiggybacked(ExitModel.InFlightExit storage ife, uint16 index)
        internal
    {
        require(index < PaymentTransactionModel.MAX_INPUT_NUM(), "Invalid input index");
        ife.exitMap = ife.exitMap.clearBit(uint8(index));
    }

    function setOutputPiggybacked(ExitModel.InFlightExit storage ife, uint16 index)
        internal
    {
        require(index < PaymentTransactionModel.MAX_OUTPUT_NUM(), "Invalid output index");
        uint8 indexInExitMap = uint8(index + PaymentTransactionModel.MAX_INPUT_NUM());
        ife.exitMap = ife.exitMap.setBit(indexInExitMap);
    }

    function clearOutputPiggybacked(ExitModel.InFlightExit storage ife, uint16 index)
        internal
    {
        require(index < PaymentTransactionModel.MAX_OUTPUT_NUM(), "Invalid output index");
        uint8 indexInExitMap = uint8(index + PaymentTransactionModel.MAX_INPUT_NUM());
        ife.exitMap = ife.exitMap.clearBit(indexInExitMap);
    }

    function isInFirstPhase(ExitModel.InFlightExit memory ife, uint256 minExitPeriod)
        internal
        view
        returns (bool)
    {
        uint256 periodTime = minExitPeriod / 2;
        return ((block.timestamp - ife.exitStartTimestamp) / periodTime) < 1;
    }

    function isEmptyWithdrawData(ExitModel.WithdrawData memory data) private pure returns (bool) {
        return data.outputId == bytes32("") &&
                data.exitTarget == address(0) &&
                data.token == address(0) &&
                data.amount == 0 &&
                data.piggybackBondSize == 0;
    }
}

File 52 of 114 : PaymentTransactionStateTransitionVerifier.sol
pragma solidity 0.5.11;
pragma experimental ABIEncoderV2;

import "../interfaces/IStateTransitionVerifier.sol";
import "../payment/PaymentExitDataModel.sol";
import "../../transactions/FungibleTokenOutputModel.sol";
import "../../transactions/PaymentTransactionModel.sol";

import "openzeppelin-solidity/contracts/math/SafeMath.sol";

/**
* @notice Verifies state transitions for payment transaction
* @dev For payment transaction to be valid, the state transition should check that the sum of the inputs is larger than the sum of the outputs
*/
contract PaymentTransactionStateTransitionVerifier {
    using SafeMath for uint256;

    /**
     * @dev For payment transaction to be valid, the state transition should check that the sum of the inputs is larger than the sum of the outputs
     */
    function isCorrectStateTransition(
        bytes calldata txBytes,
        bytes[] calldata inputTxs,
        uint16[] calldata outputIndexOfInputTxs
    )
        external
        pure
        returns (bool)
    {
        if (inputTxs.length != outputIndexOfInputTxs.length) {
            return false;
        }

        FungibleTokenOutputModel.Output[] memory inputs = new FungibleTokenOutputModel.Output[](inputTxs.length);
        for (uint i = 0; i < inputTxs.length; i++) {
            uint16 outputIndex = outputIndexOfInputTxs[i];
            FungibleTokenOutputModel.Output memory output = FungibleTokenOutputModel.getOutput(
                GenericTransaction.decode(inputTxs[i]),
                outputIndex
            );
            inputs[i] = output;
        }

        PaymentTransactionModel.Transaction memory transaction = PaymentTransactionModel.decode(txBytes);
        FungibleTokenOutputModel.Output[] memory outputs = new FungibleTokenOutputModel.Output[](transaction.outputs.length);
        for (uint i = 0; i < transaction.outputs.length; i++) {
            outputs[i] = FungibleTokenOutputModel.Output(
                    transaction.outputs[i].outputType,
                    transaction.outputs[i].outputGuard,
                    transaction.outputs[i].token,
                    transaction.outputs[i].amount
                );
        }

        return _isCorrectStateTransition(inputs, outputs);
    }

    function _isCorrectStateTransition(
        FungibleTokenOutputModel.Output[] memory inputs,
        FungibleTokenOutputModel.Output[] memory outputs
    )
        private
        pure
        returns (bool)
    {
        bool correctTransition = true;
        uint i = 0;
        while (correctTransition && i < outputs.length) {
            address token = outputs[i].token;
            FungibleTokenOutputModel.Output[] memory inputsForToken = filterWithToken(inputs, token);
            FungibleTokenOutputModel.Output[] memory outputsForToken = filterWithToken(outputs, token);

            correctTransition = isCorrectSpend(inputsForToken, outputsForToken);
            i += 1;
        }
        return correctTransition;
    }

    function filterWithToken(
        FungibleTokenOutputModel.Output[] memory outputs,
        address token
    )
        private
        pure
        returns (FungibleTokenOutputModel.Output[] memory)
    {
        // Required for calculating the size of the filtered array
        uint256 arraySize = 0;
        for (uint i = 0; i < outputs.length; ++i) {
            if (outputs[i].token == token) {
                arraySize += 1;
            }
        }

        FungibleTokenOutputModel.Output[] memory outputsWithToken = new FungibleTokenOutputModel.Output[](arraySize);
        uint j = 0;
        for (uint i = 0; i < outputs.length; ++i) {
            if (outputs[i].token == token) {
                outputsWithToken[j] = outputs[i];
                j += 1;
            }
        }

        return outputsWithToken;
    }

    function isCorrectSpend(
        FungibleTokenOutputModel.Output[] memory inputs,
        FungibleTokenOutputModel.Output[] memory outputs
    )
        internal
        pure
        returns (bool)
    {
        uint256 amountIn = sumAmounts(inputs);
        uint256 amountOut = sumAmounts(outputs);
        return amountIn >= amountOut;
    }

    function sumAmounts(FungibleTokenOutputModel.Output[] memory outputs) private pure returns (uint256) {
        uint256 amount = 0;
        for (uint i = 0; i < outputs.length; i++) {
            amount = amount.add(outputs[i].amount);
        }
        return amount;
    }
}

File 53 of 114 : PaymentChallengeIFEInputSpent.sol
pragma solidity 0.5.11;
pragma experimental ABIEncoderV2;

import "../PaymentExitDataModel.sol";
import "../PaymentInFlightExitModelUtils.sol";
import "../routers/PaymentInFlightExitRouterArgs.sol";
import "../../interfaces/ISpendingCondition.sol";
import "../../registries/SpendingConditionRegistry.sol";
import "../../utils/ExitId.sol";
import "../../utils/OutputId.sol";
import "../../utils/MoreVpFinalization.sol";
import "../../../utils/Merkle.sol";
import "../../../utils/SafeEthTransfer.sol";
import "../../../utils/PosLib.sol";
import "../../../framework/PlasmaFramework.sol";
import "../../../transactions/PaymentTransactionModel.sol";
import "../../../transactions/GenericTransaction.sol";

library PaymentChallengeIFEInputSpent {
    using PosLib for PosLib.Position;
    using PaymentInFlightExitModelUtils for PaymentExitDataModel.InFlightExit;

    struct Controller {
        PlasmaFramework framework;
        SpendingConditionRegistry spendingConditionRegistry;
        uint256 safeGasStipend;
    }

    event InFlightExitInputBlocked(
        address indexed challenger,
        bytes32 indexed txHash,
        uint16 inputIndex
    );

    /**
     * @dev Data to be passed around helper functions
     */
    struct ChallengeIFEData {
        Controller controller;
        PaymentInFlightExitRouterArgs.ChallengeInputSpentArgs args;
        PaymentExitDataModel.InFlightExit ife;
    }

    /**
     * @notice Function that builds the controller struct
     * @return Controller struct of PaymentChallengeIFEInputSpent
     */
    function buildController(
        PlasmaFramework framework,
        SpendingConditionRegistry spendingConditionRegistry,
        uint256 safeGasStipend
    )
        public
        pure
        returns (Controller memory)
    {
        return Controller({
            framework: framework,
            spendingConditionRegistry: spendingConditionRegistry,
            safeGasStipend: safeGasStipend
        });
    }

    /**
     * @notice Main logic implementation for 'challengeInFlightExitInputSpent'
     * @dev emits InFlightExitInputBlocked event on success
     * @param self The controller struct
     * @param inFlightExitMap The storage of all in-flight exit data
     * @param args Arguments of 'challengeInFlightExitInputSpent' function from client
     */
    function run(
        Controller memory self,
        PaymentExitDataModel.InFlightExitMap storage inFlightExitMap,
        PaymentInFlightExitRouterArgs.ChallengeInputSpentArgs memory args
    )
        public
    {
        require(args.senderData == keccak256(abi.encodePacked(msg.sender)), "Incorrect senderData");

        uint160 exitId = ExitId.getInFlightExitId(args.inFlightTx);
        PaymentExitDataModel.InFlightExit storage ife = inFlightExitMap.exits[exitId];

        require(ife.exitStartTimestamp != 0, "In-flight exit does not exist");
        require(ife.isInputPiggybacked(args.inFlightTxInputIndex), "The indexed input has not been piggybacked");

        require(
            keccak256(args.inFlightTx) != keccak256(args.challengingTx),
            "The challenging transaction is the same as the in-flight transaction"
        );

        ChallengeIFEData memory data = ChallengeIFEData({
            controller: self,
            args: args,
            ife: inFlightExitMap.exits[exitId]
        });

        verifySpentInputEqualsIFEInput(data);
        verifyChallengingTransactionProtocolFinalized(data);
        verifySpendingCondition(data);

        // Remove the input from the piggyback map
        ife.clearInputPiggybacked(args.inFlightTxInputIndex);

        uint256 piggybackBondSize = ife.inputs[args.inFlightTxInputIndex].piggybackBondSize;
        SafeEthTransfer.transferRevertOnError(msg.sender, piggybackBondSize, self.safeGasStipend);

        emit InFlightExitInputBlocked(msg.sender, keccak256(args.inFlightTx), args.inFlightTxInputIndex);
    }

    function verifySpentInputEqualsIFEInput(ChallengeIFEData memory data) private view {
        bytes32 ifeInputOutputId = data.ife.inputs[data.args.inFlightTxInputIndex].outputId;

        PosLib.Position memory utxoPos = PosLib.decode(data.args.inputUtxoPos);
        bytes32 challengingTxInputOutputId = data.controller.framework.isDeposit(utxoPos.blockNum)
                ? OutputId.computeDepositOutputId(data.args.inputTx, utxoPos.outputIndex, utxoPos.encode())
                : OutputId.computeNormalOutputId(data.args.inputTx, utxoPos.outputIndex);

        require(ifeInputOutputId == challengingTxInputOutputId, "Spent input is not the same as piggybacked input");
    }

    function verifyChallengingTransactionProtocolFinalized(ChallengeIFEData memory data)
        private
        view
    {
        bool isProtocolFinalized = MoreVpFinalization.isProtocolFinalized(
            data.controller.framework,
            data.args.challengingTx
        );

        // MoreVP protocol finalization would only return false only when tx does not exists.
        // Should fail already in early stages (eg. decode)
        assert(isProtocolFinalized);
    }

    function verifySpendingCondition(ChallengeIFEData memory data) private view {
        GenericTransaction.Transaction memory challengingTx = GenericTransaction.decode(data.args.challengingTx);

        GenericTransaction.Transaction memory inputTx = GenericTransaction.decode(data.args.inputTx);
        PosLib.Position memory utxoPos = PosLib.decode(data.args.inputUtxoPos);
        GenericTransaction.Output memory output = GenericTransaction.getOutput(inputTx, utxoPos.outputIndex);

        ISpendingCondition condition = data.controller.spendingConditionRegistry.spendingConditions(
            output.outputType, challengingTx.txType
        );
        require(address(condition) != address(0), "Spending condition contract not found");

        bool isSpent = condition.verify(
            data.args.inputTx,
            data.args.inputUtxoPos,
            data.args.challengingTx,
            data.args.challengingTxInputIndex,
            data.args.challengingTxWitness
        );
        require(isSpent, "Spending condition failed");
    }
}

File 54 of 114 : PaymentChallengeIFENotCanonical.sol
pragma solidity 0.5.11;
pragma experimental ABIEncoderV2;

import "../PaymentExitDataModel.sol";
import "../PaymentInFlightExitModelUtils.sol";
import "../routers/PaymentInFlightExitRouterArgs.sol";
import "../../interfaces/ISpendingCondition.sol";
import "../../registries/SpendingConditionRegistry.sol";
import "../../utils/ExitId.sol";
import "../../utils/OutputId.sol";
import "../../utils/MoreVpFinalization.sol";
import "../../../utils/PosLib.sol";
import "../../../utils/Merkle.sol";
import "../../../framework/PlasmaFramework.sol";
import "../../../transactions/PaymentTransactionModel.sol";
import "../../../transactions/GenericTransaction.sol";

library PaymentChallengeIFENotCanonical {
    using PosLib for PosLib.Position;
    using PaymentInFlightExitModelUtils for PaymentExitDataModel.InFlightExit;

    /**
     * @dev supportedTxType Allows reuse of code in different Payment Tx versions
     */
    struct Controller {
        PlasmaFramework framework;
        SpendingConditionRegistry spendingConditionRegistry;
        uint256 supportedTxType;
    }

    event InFlightExitChallenged(
        address indexed challenger,
        bytes32 indexed txHash,
        uint256 challengeTxPosition
    );

    event InFlightExitChallengeResponded(
        address indexed challenger,
        bytes32 indexed txHash,
        uint256 challengeTxPosition
    );

    /**
     * @notice Function that builds the controller struct
     * @return Controller struct of PaymentChallengeIFENotCanonical
     */
    function buildController(
        PlasmaFramework framework,
        SpendingConditionRegistry spendingConditionRegistry,
        uint256 supportedTxType
    )
        public
        pure
        returns (Controller memory)
    {
        return Controller({
            framework: framework,
            spendingConditionRegistry: spendingConditionRegistry,
            supportedTxType: supportedTxType
        });
    }

    /**
     * @notice Main logic implementation for 'challengeInFlightExitNotCanonical'
     * @dev emits InFlightExitChallenged event on success
     * @param self The controller struct
     * @param inFlightExitMap The storage of all in-flight exit data
     * @param args Arguments of 'challengeInFlightExitNotCanonical' function from client
     */
    function challenge(
        Controller memory self,
        PaymentExitDataModel.InFlightExitMap storage inFlightExitMap,
        PaymentInFlightExitRouterArgs.ChallengeCanonicityArgs memory args
    )
        public
    {
        uint160 exitId = ExitId.getInFlightExitId(args.inFlightTx);
        PaymentExitDataModel.InFlightExit storage ife = inFlightExitMap.exits[exitId];
        require(args.inFlightTxInputIndex < ife.inputs.length, "Input index out of bounds");
        require(ife.exitStartTimestamp != 0, "In-flight exit does not exist");

        require(ife.isInFirstPhase(self.framework.minExitPeriod()),
                "Canonicity challenge phase for this exit has ended");

        require(
            keccak256(args.inFlightTx) != keccak256(args.competingTx),
            "The competitor transaction is the same as transaction in-flight"
        );

        PosLib.Position memory inputUtxoPos = PosLib.decode(args.inputUtxoPos);

        bytes32 outputId;
        if (self.framework.isDeposit(inputUtxoPos.blockNum)) {
            outputId = OutputId.computeDepositOutputId(args.inputTx, inputUtxoPos.outputIndex, args.inputUtxoPos);
        } else {
            outputId = OutputId.computeNormalOutputId(args.inputTx, inputUtxoPos.outputIndex);
        }
        require(outputId == ife.inputs[args.inFlightTxInputIndex].outputId,
                "Provided inputs data does not point to the same outputId from the in-flight exit");

        GenericTransaction.Output memory output = GenericTransaction.getOutput(
            GenericTransaction.decode(args.inputTx),
            inputUtxoPos.outputIndex
        );

        ISpendingCondition condition = self.spendingConditionRegistry.spendingConditions(
            output.outputType, self.supportedTxType
        );
        require(address(condition) != address(0), "Spending condition contract not found");

        bool isSpentByCompetingTx = condition.verify(
            args.inputTx,
            args.inputUtxoPos,
            args.competingTx,
            args.competingTxInputIndex,
            args.competingTxWitness
        );
        require(isSpentByCompetingTx, "Competing input spending condition is not met");

        // Determine the position of the competing transaction
        uint256 competitorPosition = verifyCompetingTxFinalizedInThePosition(self, args);

        require(
            ife.oldestCompetitorPosition == 0 || ife.oldestCompetitorPosition > competitorPosition,
            "Competing transaction is not older than already known competitor"
        );

        ife.oldestCompetitorPosition = competitorPosition;
        ife.bondOwner = msg.sender;

        // Set a flag so that only the inputs are exitable, unless a response is received.
        ife.isCanonical = false;

        emit InFlightExitChallenged(msg.sender, keccak256(args.inFlightTx), competitorPosition);
    }

    /**
     * @notice Main logic implementation for 'respondToNonCanonicalChallenge'
     * @dev emits InFlightExitChallengeResponded event on success
     * @param self The controller struct
     * @param inFlightExitMap The storage of all in-flight exit data
     * @param inFlightTx The in-flight tx, in RLP-encoded bytes
     * @param inFlightTxPos The UTXO position of the in-flight exit. Should hardcode 0 for the outputIndex.
     * @param inFlightTxInclusionProof Inclusion proof for the in-flight tx
     */
    function respond(
        Controller memory self,
        PaymentExitDataModel.InFlightExitMap storage inFlightExitMap,
        bytes memory inFlightTx,
        uint256 inFlightTxPos,
        bytes memory inFlightTxInclusionProof
    )
        public
    {
        uint160 exitId = ExitId.getInFlightExitId(inFlightTx);
        PaymentExitDataModel.InFlightExit storage ife = inFlightExitMap.exits[exitId];
        require(ife.exitStartTimestamp != 0, "In-flight exit does not exist");
        require(inFlightTxPos > 0, "In-flight transaction position must not be 0");

        require(
            ife.oldestCompetitorPosition > inFlightTxPos,
            "In-flight transaction must be older than competitors to respond to non-canonical challenge");

        PosLib.Position memory txPos = PosLib.decode(inFlightTxPos);
        (bytes32 root, ) = self.framework.blocks(txPos.blockNum);
        require(root != bytes32(""), "Failed to get the block root hash of the tx position");

        verifyPositionOfTransactionIncludedInBlock(
            inFlightTx, txPos, root, inFlightTxInclusionProof
        );

        ife.oldestCompetitorPosition = inFlightTxPos;
        ife.isCanonical = true;
        ife.bondOwner = msg.sender;

        emit InFlightExitChallengeResponded(msg.sender, keccak256(inFlightTx), inFlightTxPos);
    }

    function verifyPositionOfTransactionIncludedInBlock(
        bytes memory txbytes,
        PosLib.Position memory txPos,
        bytes32 root,
        bytes memory inclusionProof
    )
        private
        pure
    {
        require(txPos.outputIndex == 0, "Output index of txPos has to be 0");
        require(
            Merkle.checkMembership(txbytes, txPos.txIndex, root, inclusionProof),
            "Transaction is not included in block of Plasma chain"
        );
    }

    function verifyCompetingTxFinalizedInThePosition(
        Controller memory self,
        PaymentInFlightExitRouterArgs.ChallengeCanonicityArgs memory args
    )
        private
        view
        returns (uint256)
    {
        // default to infinite low priority position
        uint256 competitorPosition = ~uint256(0);

        if (args.competingTxPos == 0) {
            bool isProtocolFinalized = MoreVpFinalization.isProtocolFinalized(
                self.framework,
                args.competingTx
            );
            // MoreVP protocol finalization would only return false only when tx does not exists.
            // Should fail already in early stages (eg. decode)
            assert(isProtocolFinalized);
        } else {
            PosLib.Position memory competingTxPos = PosLib.decode(args.competingTxPos);
            require(competingTxPos.outputIndex == 0, "OutputIndex of competingTxPos should be 0");

            bool isStandardFinalized = MoreVpFinalization.isStandardFinalized(
                self.framework,
                args.competingTx,
                competingTxPos,
                args.competingTxInclusionProof
            );
            require(isStandardFinalized, "Competing tx is not standard finalized with the given tx position");
            competitorPosition = args.competingTxPos;
        }
        return competitorPosition;
    }
}

File 55 of 114 : PaymentChallengeIFEOutputSpent.sol
pragma solidity 0.5.11;
pragma experimental ABIEncoderV2;

import "../PaymentExitDataModel.sol";
import "../PaymentInFlightExitModelUtils.sol";
import "../routers/PaymentInFlightExitRouterArgs.sol";
import "../../interfaces/ISpendingCondition.sol";
import "../../registries/SpendingConditionRegistry.sol";
import "../../utils/ExitId.sol";
import "../../utils/MoreVpFinalization.sol";
import "../../../utils/Merkle.sol";
import "../../../utils/SafeEthTransfer.sol";
import "../../../utils/PosLib.sol";
import "../../../transactions/GenericTransaction.sol";
import "../../../framework/PlasmaFramework.sol";
import "../../../transactions/PaymentTransactionModel.sol";

library PaymentChallengeIFEOutputSpent {
    using PosLib for PosLib.Position;
    using PaymentInFlightExitModelUtils for PaymentExitDataModel.InFlightExit;

    struct Controller {
        PlasmaFramework framework;
        SpendingConditionRegistry spendingConditionRegistry;
        uint256 safeGasStipend;
    }

    event InFlightExitOutputBlocked(
        address indexed challenger,
        bytes32 indexed txHash,
        uint16 outputIndex
    );

    /**
     * @notice Main logic implementation for 'challengeInFlightExitOutputSpent'
     * @dev emits InFlightExitOutputBlocked event on success
     * @param controller The controller struct
     * @param inFlightExitMap The storage of all in-flight exit data
     * @param args Arguments of 'challengeInFlightExitOutputSpent' function from client
     */
    function run(
        Controller memory controller,
        PaymentExitDataModel.InFlightExitMap storage inFlightExitMap,
        PaymentInFlightExitRouterArgs.ChallengeOutputSpent memory args
    )
        public
    {
        require(args.senderData == keccak256(abi.encodePacked(msg.sender)), "Incorrect senderData");

        uint160 exitId = ExitId.getInFlightExitId(args.inFlightTx);
        PaymentExitDataModel.InFlightExit storage ife = inFlightExitMap.exits[exitId];
        require(ife.exitStartTimestamp != 0, "In-flight exit does not exist");

        PosLib.Position memory utxoPos = PosLib.decode(args.outputUtxoPos);
        uint16 outputIndex = utxoPos.outputIndex;
        require(
            ife.isOutputPiggybacked(outputIndex),
            "Output is not piggybacked"
        );

        verifyInFlightTransactionStandardFinalized(controller, args);
        verifyChallengingTransactionProtocolFinalized(controller, args);
        verifyChallengingTransactionSpendsOutput(controller, args);

        ife.clearOutputPiggybacked(outputIndex);

        uint256 piggybackBondSize = ife.outputs[outputIndex].piggybackBondSize;
        SafeEthTransfer.transferRevertOnError(msg.sender, piggybackBondSize, controller.safeGasStipend);

        emit InFlightExitOutputBlocked(msg.sender, keccak256(args.inFlightTx), outputIndex);
    }

    function verifyInFlightTransactionStandardFinalized(
        Controller memory controller,
        PaymentInFlightExitRouterArgs.ChallengeOutputSpent memory args
    )
        private
        view
    {
        PosLib.Position memory utxoPos = PosLib.decode(args.outputUtxoPos);
        bool isStandardFinalized = MoreVpFinalization.isStandardFinalized(
            controller.framework,
            args.inFlightTx,
            utxoPos.toStrictTxPos(),
            args.inFlightTxInclusionProof
        );

        require(isStandardFinalized, "In-flight transaction must be standard finalized (included in Plasma) to be able to spend");
    }

    function verifyChallengingTransactionProtocolFinalized(
        Controller memory controller,
        PaymentInFlightExitRouterArgs.ChallengeOutputSpent memory args
    )
        private
        view
    {
        bool isProtocolFinalized = MoreVpFinalization.isProtocolFinalized(
            controller.framework,
            args.challengingTx
        );

        // MoreVP protocol finalization would only return false only when tx does not exists.
        // Should fail already in early stages (eg. decode)
        assert(isProtocolFinalized);
    }

    function verifyChallengingTransactionSpendsOutput(
        Controller memory controller,
        PaymentInFlightExitRouterArgs.ChallengeOutputSpent memory args
    )
        private
        view
    {
        PosLib.Position memory utxoPos = PosLib.decode(args.outputUtxoPos);
        GenericTransaction.Transaction memory challengingTx = GenericTransaction.decode(args.challengingTx);

        GenericTransaction.Transaction memory ifeTx = GenericTransaction.decode(args.inFlightTx);
        GenericTransaction.Output memory ifeTxOutput = GenericTransaction.getOutput(ifeTx, utxoPos.outputIndex);

        ISpendingCondition condition = controller.spendingConditionRegistry.spendingConditions(
            ifeTxOutput.outputType,
            challengingTx.txType
        );
        require(address(condition) != address(0), "Spending condition contract not found");

        bool isSpentBySpendingTx = condition.verify(
            args.inFlightTx,
            utxoPos.encode(),
            args.challengingTx,
            args.challengingTxInputIndex,
            args.challengingTxWitness
        );

        require(isSpentBySpendingTx, "Challenging transaction does not spend the output");
    }
}

File 56 of 114 : PaymentChallengeStandardExit.sol
pragma solidity 0.5.11;
pragma experimental ABIEncoderV2;

import "../PaymentExitDataModel.sol";
import "../routers/PaymentStandardExitRouterArgs.sol";
import "../../interfaces/ISpendingCondition.sol";
import "../../registries/SpendingConditionRegistry.sol";
import "../../utils/MoreVpFinalization.sol";
import "../../utils/OutputId.sol";
import "../../../vaults/EthVault.sol";
import "../../../vaults/Erc20Vault.sol";
import "../../../framework/PlasmaFramework.sol";
import "../../../framework/Protocol.sol";
import "../../../utils/SafeEthTransfer.sol";
import "../../../utils/PosLib.sol";
import "../../../transactions/PaymentTransactionModel.sol";
import "../../../transactions/GenericTransaction.sol";

library PaymentChallengeStandardExit {
    using PosLib for PosLib.Position;
    using PaymentTransactionModel for PaymentTransactionModel.Transaction;

    struct Controller {
        PlasmaFramework framework;
        SpendingConditionRegistry spendingConditionRegistry;
        uint256 safeGasStipend;
    }

    event ExitChallenged(
        uint256 indexed utxoPos
    );

    /**
     * @dev Data to be passed around helper functions
     */
    struct ChallengeStandardExitData {
        Controller controller;
        PaymentStandardExitRouterArgs.ChallengeStandardExitArgs args;
        PaymentExitDataModel.StandardExit exitData;
        uint256 challengeTxType;
    }

    /**
     * @notice Function that builds the controller struct
     * @return Controller struct of PaymentChallengeStandardExit
     */
    function buildController(
        PlasmaFramework framework,
        SpendingConditionRegistry spendingConditionRegistry,
        uint256 safeGasStipend
    )
        public
        pure
        returns (Controller memory)
    {
        return Controller({
            framework: framework,
            spendingConditionRegistry: spendingConditionRegistry,
            safeGasStipend: safeGasStipend
        });
    }

    /**
     * @notice Main logic function to challenge standard exit
     * @dev emits ExitChallenged event on success
     * @param self The controller struct
     * @param exitMap The storage of all standard exit data
     * @param args Arguments of challenge standard exit function from client
     */
    function run(
        Controller memory self,
        PaymentExitDataModel.StandardExitMap storage exitMap,
        PaymentStandardExitRouterArgs.ChallengeStandardExitArgs memory args
    )
        public
    {
        require(args.senderData == keccak256(abi.encodePacked(msg.sender)), "Incorrect senderData");

        GenericTransaction.Transaction memory challengeTx = GenericTransaction.decode(args.challengeTx);

        ChallengeStandardExitData memory data = ChallengeStandardExitData({
            controller: self,
            args: args,
            exitData: exitMap.exits[args.exitId],
            challengeTxType: challengeTx.txType
        });
        verifyChallengeExitExists(data);
        verifyChallengeTxProtocolFinalized(data);
        verifySpendingCondition(data);

        exitMap.exits[args.exitId].exitable = false;

        SafeEthTransfer.transferRevertOnError(msg.sender, data.exitData.bondSize, self.safeGasStipend);

        emit ExitChallenged(data.exitData.utxoPos);
    }

    function verifyChallengeExitExists(ChallengeStandardExitData memory data) private pure {
        require(data.exitData.exitable == true, "The exit does not exist");
    }

    function verifyChallengeTxProtocolFinalized(ChallengeStandardExitData memory data) private view {
        bool isProtocolFinalized = MoreVpFinalization.isProtocolFinalized(data.controller.framework, data.args.challengeTx);
        // MoreVP protocol finalization would only return false only when tx does not exists.
        // Should fail already in early stages (eg. decode)
        assert(isProtocolFinalized);
    }

    function verifySpendingCondition(ChallengeStandardExitData memory data) private view {
        PaymentStandardExitRouterArgs.ChallengeStandardExitArgs memory args = data.args;

        PosLib.Position memory utxoPos = PosLib.decode(data.exitData.utxoPos);
        FungibleTokenOutputModel.Output memory output = PaymentTransactionModel
            .decode(args.exitingTx)
            .getOutput(utxoPos.outputIndex);

        ISpendingCondition condition = data.controller.spendingConditionRegistry.spendingConditions(
            output.outputType, data.challengeTxType
        );
        require(address(condition) != address(0), "Spending condition contract not found");

        bytes32 outputId = data.controller.framework.isDeposit(utxoPos.blockNum)
                ? OutputId.computeDepositOutputId(args.exitingTx, utxoPos.outputIndex, utxoPos.encode())
                : OutputId.computeNormalOutputId(args.exitingTx, utxoPos.outputIndex);
        require(outputId == data.exitData.outputId, "Invalid exiting tx causing outputId mismatch");

        bool isSpentByChallengeTx = condition.verify(
            args.exitingTx,
            utxoPos.encode(),
            args.challengeTx,
            args.inputIndex,
            args.witness
        );
        require(isSpentByChallengeTx, "Spending condition failed");
    }
}

File 57 of 114 : PaymentDeleteInFlightExit.sol
pragma solidity 0.5.11;
pragma experimental ABIEncoderV2;

import "../PaymentExitDataModel.sol";
import "../PaymentInFlightExitModelUtils.sol";
import "../../../utils/SafeEthTransfer.sol";
import "../../../transactions/PaymentTransactionModel.sol";

library PaymentDeleteInFlightExit {
    using PaymentInFlightExitModelUtils for PaymentExitDataModel.InFlightExit;

    struct Controller {
        uint256 minExitPeriod;
        uint256 safeGasStipend;
    }

    event InFlightExitDeleted(
        uint160 indexed exitId
    );

    /**
     * @notice Main logic function to delete the non piggybacked in-flight exit
     * @param exitId The exitId of the standard exit
     */
    function run(
        Controller memory self,
        PaymentExitDataModel.InFlightExitMap storage exitMap,
        uint160 exitId
    )
        public
    {
        PaymentExitDataModel.InFlightExit memory ife = exitMap.exits[exitId];
        require(ife.exitStartTimestamp != 0, "In-flight exit does not exist");
        require(!ife.isInFirstPhase(self.minExitPeriod), "Cannot delete in-flight exit still in first phase");
        require(!isPiggybacked(ife), "The in-flight exit is already piggybacked");

        delete exitMap.exits[exitId];
        SafeEthTransfer.transferRevertOnError(ife.bondOwner, ife.bondSize, self.safeGasStipend);
        emit InFlightExitDeleted(exitId);
    }

    function isPiggybacked(ExitModel.InFlightExit memory ife)
        private
        pure
        returns (bool)
    {
        for (uint16 i = 0; i < PaymentTransactionModel.MAX_INPUT_NUM(); i++) {
            if (ife.isInputPiggybacked(i)) {
                return true;
            }
        }

        for (uint16 i = 0; i < PaymentTransactionModel.MAX_OUTPUT_NUM(); i++) {
            if (ife.isOutputPiggybacked(i)) {
                return true;
            }
        }

        return false;
    }
}

File 58 of 114 : PaymentPiggybackInFlightExit.sol
pragma solidity 0.5.11;
pragma experimental ABIEncoderV2;

import "../PaymentExitDataModel.sol";
import "../PaymentInFlightExitModelUtils.sol";
import "../routers/PaymentInFlightExitRouterArgs.sol";
import "../../utils/ExitableTimestamp.sol";
import "../../utils/ExitId.sol";
import "../../../framework/PlasmaFramework.sol";
import "../../../framework/interfaces/IExitProcessor.sol";
import "../../../transactions/PaymentTransactionModel.sol";
import "../../../utils/PosLib.sol";

library PaymentPiggybackInFlightExit {
    using PosLib for PosLib.Position;
    using ExitableTimestamp for ExitableTimestamp.Calculator;
    using PaymentInFlightExitModelUtils for PaymentExitDataModel.InFlightExit;

    struct Controller {
        PlasmaFramework framework;
        ExitableTimestamp.Calculator exitableTimestampCalculator;
        IExitProcessor exitProcessor;
        uint256 minExitPeriod;
        uint256 ethVaultId;
        uint256 erc20VaultId;
    }

    event InFlightExitInputPiggybacked(
        address indexed exitTarget,
        bytes32 indexed txHash,
        uint16 inputIndex
    );

    event InFlightExitOutputPiggybacked(
        address indexed exitTarget,
        bytes32 indexed txHash,
        uint16 outputIndex
    );

    /**
     * @notice Function that builds the controller struct
     * @return Controller struct of PaymentPiggybackInFlightExit
     */
    function buildController(
        PlasmaFramework framework,
        IExitProcessor exitProcessor,
        uint256 ethVaultId,
        uint256 erc20VaultId
    )
        public
        view
        returns (Controller memory)
    {
        return Controller({
            framework: framework,
            exitableTimestampCalculator: ExitableTimestamp.Calculator(framework.minExitPeriod()),
            exitProcessor: exitProcessor,
            minExitPeriod: framework.minExitPeriod(),
            ethVaultId: ethVaultId,
            erc20VaultId: erc20VaultId
        });
    }

    /**
     * @notice The main controller logic for 'piggybackInFlightExitOnInput'
     * @dev emits InFlightExitInputPiggybacked event on success
     * @param self The controller struct
     * @param inFlightExitMap The storage of all in-flight exit data
     * @param args Arguments of 'piggybackInFlightExitOnInput' function from client
     */
    function piggybackInput(
        Controller memory self,
        PaymentExitDataModel.InFlightExitMap storage inFlightExitMap,
        PaymentInFlightExitRouterArgs.PiggybackInFlightExitOnInputArgs memory args
    )
        public
    {
        uint160 exitId = ExitId.getInFlightExitId(args.inFlightTx);
        PaymentExitDataModel.InFlightExit storage exit = inFlightExitMap.exits[exitId];

        require(exit.exitStartTimestamp != 0, "No in-flight exit to piggyback on");
        require(exit.isInFirstPhase(self.minExitPeriod), "Piggyback is possible only in the first phase of the exit period");

        require(!exit.isInputEmpty(args.inputIndex), "Indexed input is empty");
        require(!exit.isInputPiggybacked(args.inputIndex), "Indexed input already piggybacked");

        PaymentExitDataModel.WithdrawData storage withdrawData = exit.inputs[args.inputIndex];

        require(withdrawData.exitTarget == msg.sender, "Can be called only by the exit target");
        withdrawData.piggybackBondSize = msg.value;

        if (isFirstPiggybackOfTheToken(exit, withdrawData.token)) {
            enqueue(self, withdrawData.token, PosLib.decode(exit.position), exitId);
        }

        exit.setInputPiggybacked(args.inputIndex);

        emit InFlightExitInputPiggybacked(msg.sender, keccak256(args.inFlightTx), args.inputIndex);
    }

    /**
     * @notice The main controller logic for 'piggybackInFlightExitOnOutput'
     * @dev emits InFlightExitOutputPiggybacked event on success
     * @param self The controller struct
     * @param inFlightExitMap The storage of all in-flight exit data
     * @param args Arguments of 'piggybackInFlightExitOnOutput' function from client
     */
    function piggybackOutput(
        Controller memory self,
        PaymentExitDataModel.InFlightExitMap storage inFlightExitMap,
        PaymentInFlightExitRouterArgs.PiggybackInFlightExitOnOutputArgs memory args
    )
        public
    {
        uint160 exitId = ExitId.getInFlightExitId(args.inFlightTx);
        PaymentExitDataModel.InFlightExit storage exit = inFlightExitMap.exits[exitId];

        require(exit.exitStartTimestamp != 0, "No in-flight exit to piggyback on");
        require(exit.isInFirstPhase(self.minExitPeriod), "Piggyback is possible only in the first phase of the exit period");

        require(!exit.isOutputEmpty(args.outputIndex), "Indexed output is empty");
        require(!exit.isOutputPiggybacked(args.outputIndex), "Indexed output already piggybacked");

        PaymentExitDataModel.WithdrawData storage withdrawData = exit.outputs[args.outputIndex];

        require(withdrawData.exitTarget == msg.sender, "Can be called only by the exit target");
        withdrawData.piggybackBondSize = msg.value;

        if (isFirstPiggybackOfTheToken(exit, withdrawData.token)) {
            enqueue(self, withdrawData.token, PosLib.decode(exit.position), exitId);
        }

        exit.setOutputPiggybacked(args.outputIndex);

        emit InFlightExitOutputPiggybacked(msg.sender, keccak256(args.inFlightTx), args.outputIndex);
    }

    function enqueue(
        Controller memory controller,
        address token,
        PosLib.Position memory utxoPos,
        uint160 exitId
    )
        private
    {
        (, uint256 blockTimestamp) = controller.framework.blocks(utxoPos.blockNum);
        require(blockTimestamp != 0, "There is no block for the exit position to enqueue");

        uint64 exitableAt = controller.exitableTimestampCalculator.calculateTxExitableTimestamp(now, blockTimestamp);

        uint256 vaultId;
        if (token == address(0)) {
            vaultId = controller.ethVaultId;
        } else {
            vaultId = controller.erc20VaultId;
        }

        controller.framework.enqueue(vaultId, token, exitableAt, utxoPos.toStrictTxPos(), exitId, controller.exitProcessor);
    }

    function isFirstPiggybackOfTheToken(ExitModel.InFlightExit memory ife, address token)
        private
        pure
        returns (bool)
    {
        for (uint i = 0; i < PaymentTransactionModel.MAX_INPUT_NUM(); i++) {
            if (ife.isInputPiggybacked(uint16(i)) && ife.inputs[i].token == token) {
                return false;
            }
        }

        for (uint i = 0; i < PaymentTransactionModel.MAX_OUTPUT_NUM(); i++) {
            if (ife.isOutputPiggybacked(uint16(i)) && ife.outputs[i].token == token) {
                return false;
            }
        }

        return true;
    }
}

File 59 of 114 : PaymentProcessInFlightExit.sol
pragma solidity 0.5.11;
pragma experimental ABIEncoderV2;

import "../PaymentExitDataModel.sol";
import "../PaymentInFlightExitModelUtils.sol";
import "../../../framework/PlasmaFramework.sol";
import "../../../transactions/PaymentTransactionModel.sol";
import "../../../utils/SafeEthTransfer.sol";
import "../../../vaults/EthVault.sol";
import "../../../vaults/Erc20Vault.sol";

library PaymentProcessInFlightExit {
    using PaymentInFlightExitModelUtils for PaymentExitDataModel.InFlightExit;

    struct Controller {
        PlasmaFramework framework;
        EthVault ethVault;
        Erc20Vault erc20Vault;
        uint256 safeGasStipend;
    }

    event InFlightExitOmitted(
        uint160 indexed exitId,
        address token
    );

    event InFlightExitOutputWithdrawn(
        uint160 indexed exitId,
        uint16 outputIndex
    );

    event InFlightExitInputWithdrawn(
        uint160 indexed exitId,
        uint16 inputIndex
    );

    event InFlightBondReturnFailed(
        address indexed receiver,
        uint256 amount
    );

    /**
     * @notice Main logic function to process in-flight exit
     * @dev emits InFlightExitOmitted event if the exit is omitted
     * @dev emits InFlightBondReturnFailed event if failed to pay out bond. Would continue to process the exit.
     * @dev emits InFlightExitInputWithdrawn event if the input of IFE is withdrawn successfully
     * @dev emits InFlightExitOutputWithdrawn event if the output of IFE is withdrawn successfully
     * @param self The controller struct
     * @param exitMap The storage of all in-flight exit data
     * @param exitId The exitId of the in-flight exit
     * @param token The ERC20 token address of the exit; uses address(0) to represent ETH
     */
    function run(
        Controller memory self,
        PaymentExitDataModel.InFlightExitMap storage exitMap,
        uint160 exitId,
        address token
    )
        public
    {
        PaymentExitDataModel.InFlightExit storage exit = exitMap.exits[exitId];

        if (exit.exitStartTimestamp == 0) {
            emit InFlightExitOmitted(exitId, token);
            return;
        }

        /* To prevent a double spend, it is needed to know if an output can be exited.
         * An output can not be exited if:
         * - it is finalized by a standard exit
         * - it is finalized by an in-flight exit as input of a non-canonical transaction
         * - it is blocked from exiting, because it is an input of a canonical transaction
         *   that exited from one of it's outputs
         * - it is finalized by an in-flight exit as an output of a canonical transaction
         * - it is an output of a transaction for which at least one of its inputs is already finalized
         *
         * Hence, Plasma Framework stores each output with an exit id that finalized it.
         * When transaction is marked as canonical but any of it's input was finalized by
         * other exit, it is not allowed to exit from the transaction's outputs.
         * In that case exit from an unspent input is possible.
         * When all inputs of a transaction that is marked as canonical are either not finalized or finalized
         * by the same exit (which means they were marked as finalized when processing the same exit for a different token),
         * only exit from outputs is possible.
         *
         * See: https://github.com/omisego/plasma-contracts/issues/102#issuecomment-495809967 for more details
         */
        if (!exit.isCanonical || isAnyInputFinalizedByOtherExit(self.framework, exit, exitId)) {
            for (uint16 i = 0; i < exit.inputs.length; i++) {
                PaymentExitDataModel.WithdrawData memory withdrawal = exit.inputs[i];

                if (shouldWithdrawInput(self, exit, withdrawal, token, i)) {
                    withdrawFromVault(self, withdrawal);
                    emit InFlightExitInputWithdrawn(exitId, i);
                }
            }

            flagOutputsWhenNonCanonical(self.framework, exit, token, exitId);
        } else {
            for (uint16 i = 0; i < exit.outputs.length; i++) {
                PaymentExitDataModel.WithdrawData memory withdrawal = exit.outputs[i];

                if (shouldWithdrawOutput(self, exit, withdrawal, token, i)) {
                    withdrawFromVault(self, withdrawal);
                    emit InFlightExitOutputWithdrawn(exitId, i);
                }
            }

            flagOutputsWhenCanonical(self.framework, exit, token, exitId);
        }

        returnInputPiggybackBonds(self, exit, token);
        returnOutputPiggybackBonds(self, exit, token);

        clearPiggybackInputFlag(exit, token);
        clearPiggybackOutputFlag(exit, token);

        if (allPiggybacksCleared(exit)) {
            bool success = SafeEthTransfer.transferReturnResult(
                exit.bondOwner, exit.bondSize, self.safeGasStipend
            );

            // we do not want to block a queue if bond return is unsuccessful
            if (!success) {
                emit InFlightBondReturnFailed(exit.bondOwner, exit.bondSize);
            }
            delete exitMap.exits[exitId];
        }
    }

    function isAnyInputFinalizedByOtherExit(
        PlasmaFramework framework,
        PaymentExitDataModel.InFlightExit memory exit,
        uint160 exitId
    )
        private
        view
        returns (bool)
    {
        uint256 nonEmptyInputIndex;
        for (uint16 i = 0; i < exit.inputs.length; i++) {
            if (!exit.isInputEmpty(i)) {
                nonEmptyInputIndex++;
            }
        }
        bytes32[] memory outputIdsOfInputs = new bytes32[](nonEmptyInputIndex);
        nonEmptyInputIndex = 0;
        for (uint16 i = 0; i < exit.inputs.length; i++) {
            if (!exit.isInputEmpty(i)) {
                outputIdsOfInputs[nonEmptyInputIndex] = exit.inputs[i].outputId;
                nonEmptyInputIndex++;
            }
        }
        return framework.isAnyInputFinalizedByOtherExit(outputIdsOfInputs, exitId);
    }

    function shouldWithdrawInput(
        Controller memory controller,
        PaymentExitDataModel.InFlightExit memory exit,
        PaymentExitDataModel.WithdrawData memory withdrawal,
        address token,
        uint16 index
    )
        private
        view
        returns (bool)
    {
        return withdrawal.token == token &&
                exit.isInputPiggybacked(index) &&
                !controller.framework.isOutputFinalized(withdrawal.outputId);
    }

    function shouldWithdrawOutput(
        Controller memory controller,
        PaymentExitDataModel.InFlightExit memory exit,
        PaymentExitDataModel.WithdrawData memory withdrawal,
        address token,
        uint16 index
    )
        private
        view
        returns (bool)
    {
        return withdrawal.token == token &&
                exit.isOutputPiggybacked(index) &&
                !controller.framework.isOutputFinalized(withdrawal.outputId);
    }

    function withdrawFromVault(
        Controller memory self,
        PaymentExitDataModel.WithdrawData memory withdrawal
    )
        private
    {
        if (withdrawal.token == address(0)) {
            self.ethVault.withdraw(withdrawal.exitTarget, withdrawal.amount);
        } else {
            self.erc20Vault.withdraw(withdrawal.exitTarget, withdrawal.token, withdrawal.amount);
        }
    }

    function flagOutputsWhenNonCanonical(
        PlasmaFramework framework,
        PaymentExitDataModel.InFlightExit memory exit,
        address token,
        uint160 exitId
    )
        private
    {
        uint256 piggybackedInputNumOfTheToken;
        for (uint16 i = 0; i < exit.inputs.length; i++) {
            if (exit.inputs[i].token == token && exit.isInputPiggybacked(i)) {
                piggybackedInputNumOfTheToken++;
            }
        }

        bytes32[] memory outputIdsToFlag = new bytes32[](piggybackedInputNumOfTheToken);
        uint indexForOutputIds = 0;
        for (uint16 i = 0; i < exit.inputs.length; i++) {
            if (exit.inputs[i].token == token && exit.isInputPiggybacked(i)) {
                outputIdsToFlag[indexForOutputIds] = exit.inputs[i].outputId;
                indexForOutputIds++;
            }
        }
        framework.batchFlagOutputsFinalized(outputIdsToFlag, exitId);
    }

    function flagOutputsWhenCanonical(
        PlasmaFramework framework,
        PaymentExitDataModel.InFlightExit memory exit,
        address token,
        uint160 exitId
    )
        private
    {
        uint256 inputNumOfTheToken;
        for (uint16 i = 0; i < exit.inputs.length; i++) {
            if (!exit.isInputEmpty(i)) {
                inputNumOfTheToken++;
            }
        }

        uint256 piggybackedOutputNumOfTheToken;
        for (uint16 i = 0; i < exit.outputs.length; i++) {
            if (exit.outputs[i].token == token && exit.isOutputPiggybacked(i)) {
                piggybackedOutputNumOfTheToken++;
            }
        }

        bytes32[] memory outputIdsToFlag = new bytes32[](inputNumOfTheToken + piggybackedOutputNumOfTheToken);
        uint indexForOutputIds = 0;
        for (uint16 i = 0; i < exit.inputs.length; i++) {
            if (!exit.isInputEmpty(i)) {
                outputIdsToFlag[indexForOutputIds] = exit.inputs[i].outputId;
                indexForOutputIds++;
            }
        }
        for (uint16 i = 0; i < exit.outputs.length; i++) {
            if (exit.outputs[i].token == token && exit.isOutputPiggybacked(i)) {
                outputIdsToFlag[indexForOutputIds] = exit.outputs[i].outputId;
                indexForOutputIds++;
            }
        }
        framework.batchFlagOutputsFinalized(outputIdsToFlag, exitId);
    }

    function returnInputPiggybackBonds(
        Controller memory self,
        PaymentExitDataModel.InFlightExit storage exit,
        address token
    )
        private
    {
        for (uint16 i = 0; i < exit.inputs.length; i++) {
            PaymentExitDataModel.WithdrawData memory withdrawal = exit.inputs[i];

            // If the input has been challenged, isInputPiggybacked() will return false
            if (token == withdrawal.token && exit.isInputPiggybacked(i)) {
                bool success = SafeEthTransfer.transferReturnResult(
                    withdrawal.exitTarget, withdrawal.piggybackBondSize, self.safeGasStipend
                );

                // we do not want to block a queue if bond return is unsuccessful
                if (!success) {
                    emit InFlightBondReturnFailed(withdrawal.exitTarget, withdrawal.piggybackBondSize);
                }
            }
        }
    }

    function returnOutputPiggybackBonds(
        Controller memory self,
        PaymentExitDataModel.InFlightExit storage exit,
        address token
    )
        private
    {
        for (uint16 i = 0; i < exit.outputs.length; i++) {
            PaymentExitDataModel.WithdrawData memory withdrawal = exit.outputs[i];

            // If the output has been challenged, isOutputPiggybacked() will return false
            if (token == withdrawal.token && exit.isOutputPiggybacked(i)) {
                bool success = SafeEthTransfer.transferReturnResult(
                    withdrawal.exitTarget, withdrawal.piggybackBondSize, self.safeGasStipend
                );

                // we do not want to block a queue if bond return is unsuccessful
                if (!success) {
                    emit InFlightBondReturnFailed(withdrawal.exitTarget, withdrawal.piggybackBondSize);
                }
            }
        }
    }

    function clearPiggybackInputFlag(
        PaymentExitDataModel.InFlightExit storage exit,
        address token
    )
        private
    {
        for (uint16 i = 0; i < exit.inputs.length; i++) {
            if (token == exit.inputs[i].token) {
                exit.clearInputPiggybacked(i);
            }
        }
    }

    function clearPiggybackOutputFlag(
        PaymentExitDataModel.InFlightExit storage exit,
        address token
    )
        private
    {
        for (uint16 i = 0; i < exit.outputs.length; i++) {
            if (token == exit.outputs[i].token) {
                exit.clearOutputPiggybacked(i);
            }
        }
    }

    function allPiggybacksCleared(PaymentExitDataModel.InFlightExit memory exit) private pure returns (bool) {
        for (uint16 i = 0; i < exit.inputs.length; i++) {
            if (exit.isInputPiggybacked(i))
                return false;
        }

        for (uint16 i = 0; i < exit.outputs.length; i++) {
            if (exit.isOutputPiggybacked(i))
                return false;
        }

        return true;
    }
}

File 60 of 114 : PaymentProcessStandardExit.sol
pragma solidity 0.5.11;
pragma experimental ABIEncoderV2;

import "../PaymentExitDataModel.sol";
import "../routers/PaymentStandardExitRouterArgs.sol";
import "../../../framework/PlasmaFramework.sol";
import "../../../utils/SafeEthTransfer.sol";
import "../../../vaults/EthVault.sol";
import "../../../vaults/Erc20Vault.sol";

library PaymentProcessStandardExit {
    struct Controller {
        PlasmaFramework framework;
        EthVault ethVault;
        Erc20Vault erc20Vault;
        uint256 safeGasStipend;
    }

    event ExitOmitted(
        uint160 indexed exitId
    );

    event ExitFinalized(
        uint160 indexed exitId
    );

    event BondReturnFailed(
        address indexed receiver,
        uint256 amount
    );

    /**
     * @notice Main logic function to process standard exit
     * @dev emits ExitOmitted event if the exit is omitted
     * @dev emits ExitFinalized event if the exit is processed and funds are withdrawn
     * @param self The controller struct
     * @param exitMap The storage of all standard exit data
     * @param exitId The exitId of the standard exit
     * @param token The ERC20 token address of the exit. Uses address(0) to represent ETH.
     */
    function run(
        Controller memory self,
        PaymentExitDataModel.StandardExitMap storage exitMap,
        uint160 exitId,
        address token
    )
        public
    {
        PaymentExitDataModel.StandardExit memory exit = exitMap.exits[exitId];

        if (!exit.exitable || self.framework.isOutputFinalized(exit.outputId)) {
            emit ExitOmitted(exitId);
            delete exitMap.exits[exitId];
            return;
        }

        self.framework.flagOutputFinalized(exit.outputId, exitId);

        // we do not want to block a queue if bond return is unsuccessful
        bool success = SafeEthTransfer.transferReturnResult(exit.exitTarget, exit.bondSize, self.safeGasStipend);
        if (!success) {
            emit BondReturnFailed(exit.exitTarget, exit.bondSize);
        }

        if (token == address(0)) {
            self.ethVault.withdraw(exit.exitTarget, exit.amount);
        } else {
            self.erc20Vault.withdraw(exit.exitTarget, token, exit.amount);
        }

        delete exitMap.exits[exitId];

        emit ExitFinalized(exitId);
    }
}

File 61 of 114 : PaymentStartInFlightExit.sol
pragma solidity 0.5.11;
pragma experimental ABIEncoderV2;

import "../PaymentExitDataModel.sol";
import "../PaymentInFlightExitModelUtils.sol";
import "../routers/PaymentInFlightExitRouterArgs.sol";
import "../../interfaces/ISpendingCondition.sol";
import "../../interfaces/IStateTransitionVerifier.sol";
import "../../registries/SpendingConditionRegistry.sol";
import "../../utils/ExitableTimestamp.sol";
import "../../utils/ExitId.sol";
import "../../utils/OutputId.sol";
import "../../utils/MoreVpFinalization.sol";
import "../../../utils/PosLib.sol";
import "../../../utils/Merkle.sol";
import "../../../framework/PlasmaFramework.sol";
import "../../../transactions/PaymentTransactionModel.sol";
import "../../../transactions/GenericTransaction.sol";

library PaymentStartInFlightExit {
    using ExitableTimestamp for ExitableTimestamp.Calculator;
    using PosLib for PosLib.Position;
    using PaymentInFlightExitModelUtils for PaymentExitDataModel.InFlightExit;
    using PaymentTransactionModel for PaymentTransactionModel.Transaction;

    /**
     * @dev supportedTxType enables code reuse in different Payment Tx versions
     */
    struct Controller {
        PlasmaFramework framework;
        ExitableTimestamp.Calculator exitTimestampCalculator;
        SpendingConditionRegistry spendingConditionRegistry;
        IStateTransitionVerifier transitionVerifier;
        uint256 supportedTxType;
    }

    event InFlightExitStarted(
        address indexed initiator,
        bytes32 indexed txHash
    );

     /**
     * @dev data to be passed around start in-flight exit helper functions
     * @param controller the Controller struct of this library
     * @param exitId ID of the exit
     * @param inFlightTxRaw In-flight transaction as bytes
     * @param inFlightTx Decoded in-flight transaction
     * @param inFlightTxHash Hash of in-flight transaction
     * @param inputTxs Input transactions as bytes
     * @param inputUtxosPos Postions of input utxos coded as integers
     * @param inputTxsInclusionProofs Merkle proofs for input transactions
     * @param inFlightTxWitnesses Witnesses for in-flight transactions
     * @param outputIds Output IDs for input transactions.
     */
    struct StartExitData {
        Controller controller;
        uint160 exitId;
        bytes inFlightTxRaw;
        PaymentTransactionModel.Transaction inFlightTx;
        bytes32 inFlightTxHash;
        bytes[] inputTxs;
        PosLib.Position[] inputUtxosPos;
        bytes[] inputTxsInclusionProofs;
        bytes[] inFlightTxWitnesses;
        bytes32[] outputIds;
    }

    /**
     * @notice Function that builds the controller struct
     * @return Controller struct of PaymentStartInFlightExit
     */
    function buildController(
        PlasmaFramework framework,
        SpendingConditionRegistry spendingConditionRegistry,
        IStateTransitionVerifier transitionVerifier,
        uint256 supportedTxType
    )
        public
        view
        returns (Controller memory)
    {
        return Controller({
            framework: framework,
            exitTimestampCalculator: ExitableTimestamp.Calculator(framework.minExitPeriod()),
            spendingConditionRegistry: spendingConditionRegistry,
            transitionVerifier: transitionVerifier,
            supportedTxType: supportedTxType
        });
    }

    /**
     * @notice Main logic function to start in-flight exit
     * @dev emits InFlightExitStarted event on success
     * @param self The controller struct
     * @param inFlightExitMap The storage of all in-flight exit data
     * @param args Arguments of start in-flight exit function from client
     */
    function run(
        Controller memory self,
        PaymentExitDataModel.InFlightExitMap storage inFlightExitMap,
        PaymentInFlightExitRouterArgs.StartExitArgs memory args
    )
        public
    {
        StartExitData memory startExitData = createStartExitData(self, args);
        verifyStart(startExitData, inFlightExitMap);
        startExit(startExitData, inFlightExitMap);
        emit InFlightExitStarted(msg.sender, startExitData.inFlightTxHash);
    }

    function createStartExitData(
        Controller memory controller,
        PaymentInFlightExitRouterArgs.StartExitArgs memory args
    )
        private
        view
        returns (StartExitData memory)
    {
        StartExitData memory exitData;
        exitData.controller = controller;
        exitData.exitId = ExitId.getInFlightExitId(args.inFlightTx);
        exitData.inFlightTxRaw = args.inFlightTx;
        exitData.inFlightTx = PaymentTransactionModel.decode(args.inFlightTx);
        exitData.inFlightTxHash = keccak256(args.inFlightTx);
        exitData.inputTxs = args.inputTxs;
        exitData.inputUtxosPos = decodeInputTxsPositions(args.inputUtxosPos);
        exitData.inputTxsInclusionProofs = args.inputTxsInclusionProofs;
        exitData.inFlightTxWitnesses = args.inFlightTxWitnesses;
        exitData.outputIds = getOutputIds(controller, exitData.inputTxs, exitData.inputUtxosPos);
        return exitData;
    }

    function decodeInputTxsPositions(uint256[] memory inputUtxosPos) private pure returns (PosLib.Position[] memory) {
        require(inputUtxosPos.length <= PaymentTransactionModel.MAX_INPUT_NUM(), "Too many transactions provided");

        PosLib.Position[] memory utxosPos = new PosLib.Position[](inputUtxosPos.length);
        for (uint i = 0; i < inputUtxosPos.length; i++) {
            utxosPos[i] = PosLib.decode(inputUtxosPos[i]);
        }
        return utxosPos;
    }

    function getOutputIds(Controller memory controller, bytes[] memory inputTxs, PosLib.Position[] memory utxoPos)
        private
        view
        returns (bytes32[] memory)
    {
        require(inputTxs.length == utxoPos.length, "Number of input transactions does not match number of provided input utxos positions");
        bytes32[] memory outputIds = new bytes32[](inputTxs.length);
        for (uint i = 0; i < inputTxs.length; i++) {
            bool isDepositTx = controller.framework.isDeposit(utxoPos[i].blockNum);
            outputIds[i] = isDepositTx
                ? OutputId.computeDepositOutputId(inputTxs[i], utxoPos[i].outputIndex, utxoPos[i].encode())
                : OutputId.computeNormalOutputId(inputTxs[i], utxoPos[i].outputIndex);
        }
        return outputIds;
    }

    function verifyStart(
        StartExitData memory exitData,
        PaymentExitDataModel.InFlightExitMap storage inFlightExitMap
    )
        private
        view
    {
        verifyExitNotStarted(exitData.exitId, inFlightExitMap);
        verifyInFlightTxType(exitData);
        verifyNumberOfInputsMatchesNumberOfInFlightTransactionInputs(exitData);
        verifyNoInputSpentMoreThanOnce(exitData.inFlightTx);
        verifyInputTransactionIsStandardFinalized(exitData);
        verifyInputsSpent(exitData);
        verifyStateTransition(exitData);
    }

    function verifyExitNotStarted(
        uint160 exitId,
        PaymentExitDataModel.InFlightExitMap storage inFlightExitMap
    )
        private
        view
    {
        PaymentExitDataModel.InFlightExit storage exit = inFlightExitMap.exits[exitId];
        require(exit.exitStartTimestamp == 0, "There is an active in-flight exit from this transaction");
    }

    function verifyInFlightTxType(StartExitData memory exitData) private pure {
        require(exitData.inFlightTx.txType == exitData.controller.supportedTxType, "Unsupported transaction type of the exit game");
    }

    function verifyNumberOfInputsMatchesNumberOfInFlightTransactionInputs(StartExitData memory exitData) private pure {
        require(exitData.inputTxs.length != 0, "In-flight transaction must have inputs");
        require(
            exitData.inputTxs.length == exitData.inFlightTx.inputs.length,
            "Number of input transactions does not match number of in-flight transaction inputs"
        );
        require(
            exitData.inputTxsInclusionProofs.length == exitData.inFlightTx.inputs.length,
            "Number of input transactions inclusion proofs does not match the number of in-flight transaction inputs"
        );
        require(
            exitData.inFlightTxWitnesses.length == exitData.inFlightTx.inputs.length,
            "Number of input transaction witnesses does not match the number of in-flight transaction inputs"
        );
    }

    function verifyNoInputSpentMoreThanOnce(PaymentTransactionModel.Transaction memory inFlightTx) private pure {
        if (inFlightTx.inputs.length > 1) {
            for (uint i = 0; i < inFlightTx.inputs.length; i++) {
                for (uint j = i + 1; j < inFlightTx.inputs.length; j++) {
                    require(inFlightTx.inputs[i] != inFlightTx.inputs[j], "In-flight transaction must have unique inputs");
                }
            }
        }
    }

    function verifyInputTransactionIsStandardFinalized(StartExitData memory exitData) private view {
        for (uint i = 0; i < exitData.inputTxs.length; i++) {
            bool isStandardFinalized = MoreVpFinalization.isStandardFinalized(
                exitData.controller.framework,
                exitData.inputTxs[i],
                exitData.inputUtxosPos[i].toStrictTxPos(),
                exitData.inputTxsInclusionProofs[i]
            );
            require(isStandardFinalized, "Input transaction is not standard finalized");
        }
    }

    function verifyInputsSpent(StartExitData memory exitData) private view {
        for (uint16 i = 0; i < exitData.inputTxs.length; i++) {
            uint16 outputIndex = exitData.inputUtxosPos[i].outputIndex;
            GenericTransaction.Output memory output = GenericTransaction.getOutput(
                GenericTransaction.decode(exitData.inputTxs[i]),
                outputIndex
            );

            ISpendingCondition condition = exitData.controller.spendingConditionRegistry.spendingConditions(
                output.outputType, exitData.controller.supportedTxType
            );

            require(address(condition) != address(0), "Spending condition contract not found");

            bool isSpentByInFlightTx = condition.verify(
                exitData.inputTxs[i],
                exitData.inputUtxosPos[i].encode(),
                exitData.inFlightTxRaw,
                i,
                exitData.inFlightTxWitnesses[i]
            );
            require(isSpentByInFlightTx, "Spending condition failed");
        }
    }

    function verifyStateTransition(StartExitData memory exitData) private view {
        uint16[] memory outputIndexForInputTxs = new uint16[](exitData.inputTxs.length);
        for (uint i = 0; i < exitData.inFlightTx.inputs.length; i++) {
            outputIndexForInputTxs[i] = exitData.inputUtxosPos[i].outputIndex;
        }

        require(
            exitData.controller.transitionVerifier.isCorrectStateTransition(exitData.inFlightTxRaw, exitData.inputTxs, outputIndexForInputTxs),
            "Invalid state transition"
        );
    }

    function startExit(
        StartExitData memory startExitData,
        PaymentExitDataModel.InFlightExitMap storage inFlightExitMap
    )
        private
    {
        PaymentExitDataModel.InFlightExit storage ife = inFlightExitMap.exits[startExitData.exitId];
        ife.isCanonical = true;
        ife.bondOwner = msg.sender;
        ife.bondSize = msg.value;
        ife.position = getYoungestInputUtxoPosition(startExitData.inputUtxosPos);
        ife.exitStartTimestamp = uint64(block.timestamp);
        setInFlightExitInputs(ife, startExitData);
        setInFlightExitOutputs(ife, startExitData);
    }

    function getYoungestInputUtxoPosition(PosLib.Position[] memory inputUtxosPos) private pure returns (uint256) {
        uint256 youngest = inputUtxosPos[0].encode();
        for (uint i = 1; i < inputUtxosPos.length; i++) {
            uint256 encodedUtxoPos = inputUtxosPos[i].encode();
            if (encodedUtxoPos > youngest) {
                youngest = encodedUtxoPos;
            }
        }
        return youngest;
    }

    function setInFlightExitInputs(
        PaymentExitDataModel.InFlightExit storage ife,
        StartExitData memory exitData
    )
        private
    {
        for (uint i = 0; i < exitData.inputTxs.length; i++) {
            uint16 outputIndex = exitData.inputUtxosPos[i].outputIndex;
            FungibleTokenOutputModel.Output memory output = FungibleTokenOutputModel.getOutput(
                GenericTransaction.decode(exitData.inputTxs[i]),
                outputIndex
            );

            ife.inputs[i].outputId = exitData.outputIds[i];
            ife.inputs[i].exitTarget = address(uint160(output.outputGuard));
            ife.inputs[i].token = output.token;
            ife.inputs[i].amount = output.amount;
        }
    }

    function setInFlightExitOutputs(
        PaymentExitDataModel.InFlightExit storage ife,
        StartExitData memory exitData
    )
        private
    {
        for (uint16 i = 0; i < exitData.inFlightTx.outputs.length; i++) {
            // deposit transaction can't be in-flight exited
            bytes32 outputId = OutputId.computeNormalOutputId(exitData.inFlightTxRaw, i);
            FungibleTokenOutputModel.Output memory output = exitData.inFlightTx.getOutput(i);

            ife.outputs[i].outputId = outputId;
            ife.outputs[i].exitTarget = address(uint160(output.outputGuard));
            ife.outputs[i].token = output.token;
            ife.outputs[i].amount = output.amount;
        }
    }
}

File 62 of 114 : PaymentStartStandardExit.sol
pragma solidity 0.5.11;
pragma experimental ABIEncoderV2;

import "../PaymentExitDataModel.sol";
import "../routers/PaymentStandardExitRouterArgs.sol";
import "../../utils/ExitableTimestamp.sol";
import "../../utils/ExitId.sol";
import "../../utils/OutputId.sol";
import "../../utils/MoreVpFinalization.sol";
import "../../../transactions/PaymentTransactionModel.sol";
import "../../../utils/PosLib.sol";
import "../../../framework/PlasmaFramework.sol";
import "../../utils/ExitableTimestamp.sol";

library PaymentStartStandardExit {
    using ExitableTimestamp for ExitableTimestamp.Calculator;
    using PosLib for PosLib.Position;
    using PaymentTransactionModel for PaymentTransactionModel.Transaction;

    struct Controller {
        IExitProcessor exitProcessor;
        PlasmaFramework framework;
        ExitableTimestamp.Calculator exitableTimestampCalculator;
        uint256 ethVaultId;
        uint256 erc20VaultId;
        uint256 supportedTxType;
    }

    /**
     * @dev Data to be passed around startStandardExit helper functions
     */
    struct StartStandardExitData {
        Controller controller;
        PaymentStandardExitRouterArgs.StartStandardExitArgs args;
        PosLib.Position utxoPos;
        PaymentTransactionModel.Transaction outputTx;
        FungibleTokenOutputModel.Output output;
        uint160 exitId;
        bool isTxDeposit;
        uint256 txBlockTimeStamp;
        bytes32 outputId;
    }

    event ExitStarted(
        address indexed owner,
        uint160 exitId
    );

    /**
     * @notice Function that builds the controller struct
     * @return Controller struct of PaymentStartStandardExit
     */
    function buildController(
        IExitProcessor exitProcessor,
        PlasmaFramework framework,
        uint256 ethVaultId,
        uint256 erc20VaultId,
        uint256 supportedTxType
    )
        public
        view
        returns (Controller memory)
    {
        return Controller({
            exitProcessor: exitProcessor,
            framework: framework,
            exitableTimestampCalculator: ExitableTimestamp.Calculator(framework.minExitPeriod()),
            ethVaultId: ethVaultId,
            erc20VaultId: erc20VaultId,
            supportedTxType: supportedTxType
        });
    }

    /**
     * @notice Main logic function to start standard exit
     * @dev emits ExitStarted event on success
     * @param self The controller struct
     * @param exitMap The storage of all standard exit data
     * @param args Arguments of start standard exit function from client
     */
    function run(
        Controller memory self,
        PaymentExitDataModel.StandardExitMap storage exitMap,
        PaymentStandardExitRouterArgs.StartStandardExitArgs memory args
    )
        public
    {
        StartStandardExitData memory data = setupStartStandardExitData(self, args);
        verifyStartStandardExitData(self, data, exitMap);
        saveStandardExitData(data, exitMap);
        enqueueStandardExit(data);

        emit ExitStarted(msg.sender, data.exitId);
    }

    function setupStartStandardExitData(
        Controller memory controller,
        PaymentStandardExitRouterArgs.StartStandardExitArgs memory args
    )
        private
        view
        returns (StartStandardExitData memory)
    {
        PosLib.Position memory utxoPos = PosLib.decode(args.utxoPos);
        PaymentTransactionModel.Transaction memory outputTx = PaymentTransactionModel.decode(args.rlpOutputTx);
        FungibleTokenOutputModel.Output memory output = outputTx.getOutput(utxoPos.outputIndex);
        bool isTxDeposit = controller.framework.isDeposit(utxoPos.blockNum);
        uint160 exitId = ExitId.getStandardExitId(isTxDeposit, args.rlpOutputTx, utxoPos);
        (, uint256 blockTimestamp) = controller.framework.blocks(utxoPos.blockNum);

        bytes32 outputId = isTxDeposit
            ? OutputId.computeDepositOutputId(args.rlpOutputTx, utxoPos.outputIndex, utxoPos.encode())
            : OutputId.computeNormalOutputId(args.rlpOutputTx, utxoPos.outputIndex);

        return StartStandardExitData({
            controller: controller,
            args: args,
            utxoPos: utxoPos,
            outputTx: outputTx,
            output: output,
            exitId: exitId,
            isTxDeposit: isTxDeposit,
            txBlockTimeStamp: blockTimestamp,
            outputId: outputId
        });
    }

    function verifyStartStandardExitData(
        Controller memory self,
        StartStandardExitData memory data,
        PaymentExitDataModel.StandardExitMap storage exitMap
    )
        private
        view
    {
        require(data.outputTx.txType == data.controller.supportedTxType, "Unsupported transaction type of the exit game");
        require(data.txBlockTimeStamp != 0, "There is no block for the position");

        require(PaymentTransactionModel.getOutputOwner(data.output) == msg.sender, "Only output owner can start an exit");

        require(isStandardFinalized(data), "The transaction must be standard finalized");
        PaymentExitDataModel.StandardExit memory exit = exitMap.exits[data.exitId];
        require(exit.amount == 0, "Exit has already started");

        require(self.framework.isOutputFinalized(data.outputId) == false, "Output is already spent");
    }

    function isStandardFinalized(StartStandardExitData memory data)
        private
        view
        returns (bool)
    {
        return MoreVpFinalization.isStandardFinalized(
            data.controller.framework,
            data.args.rlpOutputTx,
            data.utxoPos.toStrictTxPos(),
            data.args.outputTxInclusionProof
        );
    }

    function saveStandardExitData(
        StartStandardExitData memory data,
        PaymentExitDataModel.StandardExitMap storage exitMap
    )
        private
    {
        exitMap.exits[data.exitId] = PaymentExitDataModel.StandardExit({
            exitable: true,
            utxoPos: data.utxoPos.encode(),
            outputId: data.outputId,
            exitTarget: msg.sender,
            amount: data.output.amount,
            bondSize: msg.value
        });
    }

    function enqueueStandardExit(StartStandardExitData memory data) private {

        uint64 exitableAt;
        ExitableTimestamp.Calculator memory exitableTimestampCalculator = data.controller.exitableTimestampCalculator;

        if (data.isTxDeposit){
            exitableAt = exitableTimestampCalculator.calculateDepositTxOutputExitableTimestamp(block.timestamp);
        } else {
            exitableAt = exitableTimestampCalculator.calculateTxExitableTimestamp(block.timestamp, data.txBlockTimeStamp);
        }

        uint256 vaultId;
        if (data.output.token == address(0)) {
            vaultId = data.controller.ethVaultId;
        } else {
            vaultId = data.controller.erc20VaultId;
        }

        data.controller.framework.enqueue(
            vaultId, data.output.token, exitableAt, data.utxoPos.toStrictTxPos(),
            data.exitId, data.controller.exitProcessor
        );
    }
}

File 63 of 114 : PaymentInFlightExitRouter.sol
pragma solidity 0.5.11;
pragma experimental ABIEncoderV2;

import "./PaymentInFlightExitRouterArgs.sol";
import "../PaymentExitDataModel.sol";
import "../PaymentExitGameArgs.sol";
import "../controllers/PaymentStartInFlightExit.sol";
import "../controllers/PaymentPiggybackInFlightExit.sol";
import "../controllers/PaymentChallengeIFENotCanonical.sol";
import "../controllers/PaymentChallengeIFEInputSpent.sol";
import "../controllers/PaymentChallengeIFEOutputSpent.sol";
import "../controllers/PaymentDeleteInFlightExit.sol";
import "../controllers/PaymentProcessInFlightExit.sol";
import "../../registries/SpendingConditionRegistry.sol";
import "../../interfaces/IStateTransitionVerifier.sol";
import "../../utils/BondSize.sol";
import "../../../utils/FailFastReentrancyGuard.sol";
import "../../../utils/OnlyFromAddress.sol";
import "../../../utils/OnlyWithValue.sol";
import "../../../framework/PlasmaFramework.sol";
import "../../../framework/interfaces/IExitProcessor.sol";


contract PaymentInFlightExitRouter is
    IExitProcessor,
    OnlyFromAddress,
    OnlyWithValue,
    FailFastReentrancyGuard
{
    using PaymentStartInFlightExit for PaymentStartInFlightExit.Controller;
    using PaymentPiggybackInFlightExit for PaymentPiggybackInFlightExit.Controller;
    using PaymentChallengeIFENotCanonical for PaymentChallengeIFENotCanonical.Controller;
    using PaymentChallengeIFEInputSpent for PaymentChallengeIFEInputSpent.Controller;
    using PaymentChallengeIFEOutputSpent for PaymentChallengeIFEOutputSpent.Controller;
    using PaymentDeleteInFlightExit for PaymentDeleteInFlightExit.Controller;
    using PaymentProcessInFlightExit for PaymentProcessInFlightExit.Controller;
    using BondSize for BondSize.Params;

    // Initial IFE bond size = 185000 (gas cost of challenge) * 20 gwei (current fast gas price) * 10 (safety margin)
    uint128 public constant INITIAL_IFE_BOND_SIZE = 37000000000000000 wei;

    // Initial piggyback bond size = 140000 (gas cost of challenge) * 20 gwei (current fast gas price) * 10 (safety margin)
    uint128 public constant INITIAL_PB_BOND_SIZE = 28000000000000000 wei;

    // Each bond size upgrade can increase to a maximum of 200% or decrease to 50% of the current bond
    uint16 public constant BOND_LOWER_BOUND_DIVISOR = 2;
    uint16 public constant BOND_UPPER_BOUND_MULTIPLIER = 2;

    PaymentExitDataModel.InFlightExitMap internal inFlightExitMap;
    PaymentStartInFlightExit.Controller internal startInFlightExitController;
    PaymentPiggybackInFlightExit.Controller internal piggybackInFlightExitController;
    PaymentChallengeIFENotCanonical.Controller internal challengeCanonicityController;
    PaymentChallengeIFEInputSpent.Controller internal challengeInputSpentController;
    PaymentChallengeIFEOutputSpent.Controller internal challengeOutputSpentController;
    PaymentDeleteInFlightExit.Controller internal deleteNonPiggybackIFEController;
    PaymentProcessInFlightExit.Controller internal processInflightExitController;
    BondSize.Params internal startIFEBond;
    BondSize.Params internal piggybackBond;

    PlasmaFramework private framework;

    event IFEBondUpdated(uint128 bondSize);
    event PiggybackBondUpdated(uint128 bondSize);

    event InFlightExitStarted(
        address indexed initiator,
        bytes32 indexed txHash
    );

    event InFlightExitInputPiggybacked(
        address indexed exitTarget,
        bytes32 indexed txHash,
        uint16 inputIndex
    );

    event InFlightExitOmitted(
        uint160 indexed exitId,
        address token
    );

    event InFlightBondReturnFailed(
        address indexed receiver,
        uint256 amount
    );

    event InFlightExitOutputWithdrawn(
        uint160 indexed exitId,
        uint16 outputIndex
    );

    event InFlightExitInputWithdrawn(
        uint160 indexed exitId,
        uint16 inputIndex
    );

    event InFlightExitOutputPiggybacked(
        address indexed exitTarget,
        bytes32 indexed txHash,
        uint16 outputIndex
    );

    event InFlightExitChallenged(
        address indexed challenger,
        bytes32 indexed txHash,
        uint256 challengeTxPosition
    );

    event InFlightExitChallengeResponded(
        address indexed challenger,
        bytes32 indexed txHash,
        uint256 challengeTxPosition
    );

    event InFlightExitInputBlocked(
        address indexed challenger,
        bytes32 indexed txHash,
        uint16 inputIndex
    );

    event InFlightExitOutputBlocked(
        address indexed challenger,
        bytes32 indexed txHash,
        uint16 outputIndex
    );

    event InFlightExitDeleted(
        uint160 indexed exitId
    );

    constructor(PaymentExitGameArgs.Args memory args)
        public
    {
        framework = args.framework;

        EthVault ethVault = EthVault(args.framework.vaults(args.ethVaultId));
        require(address(ethVault) != address(0), "Invalid ETH vault");

        Erc20Vault erc20Vault = Erc20Vault(args.framework.vaults(args.erc20VaultId));
        require(address(erc20Vault) != address(0), "Invalid ERC20 vault");

        startInFlightExitController = PaymentStartInFlightExit.buildController(
            args.framework,
            args.spendingConditionRegistry,
            args.stateTransitionVerifier,
            args.supportTxType
        );

        piggybackInFlightExitController = PaymentPiggybackInFlightExit.buildController(
            args.framework,
            this,
            args.ethVaultId,
            args.erc20VaultId
        );

        challengeCanonicityController = PaymentChallengeIFENotCanonical.buildController(
            args.framework,
            args.spendingConditionRegistry,
            args.supportTxType
        );

        challengeInputSpentController = PaymentChallengeIFEInputSpent.buildController(
            args.framework,
            args.spendingConditionRegistry,
            args.safeGasStipend
        );

        challengeOutputSpentController = PaymentChallengeIFEOutputSpent.Controller(
            args.framework,
            args.spendingConditionRegistry,
            args.safeGasStipend
        );

        deleteNonPiggybackIFEController = PaymentDeleteInFlightExit.Controller({
            minExitPeriod: args.framework.minExitPeriod(),
            safeGasStipend: args.safeGasStipend
        });

        processInflightExitController = PaymentProcessInFlightExit.Controller({
            framework: args.framework,
            ethVault: ethVault,
            erc20Vault: erc20Vault,
            safeGasStipend: args.safeGasStipend
        });
        startIFEBond = BondSize.buildParams(INITIAL_IFE_BOND_SIZE, BOND_LOWER_BOUND_DIVISOR, BOND_UPPER_BOUND_MULTIPLIER);
        piggybackBond = BondSize.buildParams(INITIAL_PB_BOND_SIZE, BOND_LOWER_BOUND_DIVISOR, BOND_UPPER_BOUND_MULTIPLIER);
    }

    /**
     * @notice Getter functions to retrieve in-flight exit data of the PaymentExitGame
     * @param exitIds The exit IDs of the in-flight exits
     */
    function inFlightExits(uint160[] calldata exitIds) external view returns (PaymentExitDataModel.InFlightExit[] memory) {
        PaymentExitDataModel.InFlightExit[] memory exits = new PaymentExitDataModel.InFlightExit[](exitIds.length);
        for (uint i = 0; i < exitIds.length; i++) {
            uint160 exitId = exitIds[i];
            exits[i] = inFlightExitMap.exits[exitId];
        }
        return exits;
    }

    /**
     * @notice Starts withdrawal from a transaction that may be in-flight
     * @param args Input argument data to challenge (see also struct 'StartExitArgs')
     */
    function startInFlightExit(PaymentInFlightExitRouterArgs.StartExitArgs memory args)
        public
        payable
        nonReentrant(framework)
        onlyWithValue(startIFEBondSize())
    {
        startInFlightExitController.run(inFlightExitMap, args);
    }

    /**
     * @notice Piggyback on an input of an in-flight exiting tx. Processed only if the in-flight exit is non-canonical.
     * @param args Input argument data to piggyback (see also struct 'PiggybackInFlightExitOnInputArgs')
     */
    function piggybackInFlightExitOnInput(
        PaymentInFlightExitRouterArgs.PiggybackInFlightExitOnInputArgs memory args
    )
        public
        payable
        nonReentrant(framework)
        onlyWithValue(piggybackBondSize())
    {
        piggybackInFlightExitController.piggybackInput(inFlightExitMap, args);
    }

    /**
     * @notice Piggyback on an output of an in-flight exiting tx. Processed only if the in-flight exit is canonical.
     * @param args Input argument data to piggyback (see also struct 'PiggybackInFlightExitOnOutputArgs')
     */
    function piggybackInFlightExitOnOutput(
        PaymentInFlightExitRouterArgs.PiggybackInFlightExitOnOutputArgs memory args
    )
        public
        payable
        nonReentrant(framework)
        onlyWithValue(piggybackBondSize())
    {
        piggybackInFlightExitController.piggybackOutput(inFlightExitMap, args);
    }

    /**
     * @notice Challenges an in-flight exit to be non-canonical
     * @param args Input argument data to challenge (see also struct 'ChallengeCanonicityArgs')
     */
    function challengeInFlightExitNotCanonical(PaymentInFlightExitRouterArgs.ChallengeCanonicityArgs memory args)
        public
        nonReentrant(framework)
    {
        challengeCanonicityController.challenge(inFlightExitMap, args);
    }

    /**
     * @notice Respond to a non-canonical challenge by providing its position and by proving its correctness
     * @param inFlightTx The RLP-encoded in-flight transaction
     * @param inFlightTxPos The position of the in-flight exiting transaction. The output index within the position is unused and should be set to 0
     * @param inFlightTxInclusionProof Proof that the in-flight exiting transaction is included in a Plasma block
     */
    function respondToNonCanonicalChallenge(
        bytes memory inFlightTx,
        uint256 inFlightTxPos,
        bytes memory inFlightTxInclusionProof
    )
        public
        nonReentrant(framework)
    {
        challengeCanonicityController.respond(inFlightExitMap, inFlightTx, inFlightTxPos, inFlightTxInclusionProof);
    }

    /**
     * @notice Challenges an exit from in-flight transaction input
     * @param args Argument data to challenge (see also struct 'ChallengeInputSpentArgs')
     */
    function challengeInFlightExitInputSpent(PaymentInFlightExitRouterArgs.ChallengeInputSpentArgs memory args)
        public
        nonReentrant(framework)
    {
        challengeInputSpentController.run(inFlightExitMap, args);
    }

     /**
     * @notice Challenges an exit from in-flight transaction output
     * @param args Argument data to challenge (see also struct 'ChallengeOutputSpent')
     */
    function challengeInFlightExitOutputSpent(PaymentInFlightExitRouterArgs.ChallengeOutputSpent memory args)
        public
        nonReentrant(framework)
    {
        challengeOutputSpentController.run(inFlightExitMap, args);
    }

    /**
     * @notice Deletes in-flight exit if the first phase has passed and not being piggybacked
     * @dev Since IFE is enqueued during piggyback, a non-piggybacked IFE means that it will never be processed.
     *      This means that the IFE bond will never be returned.
     *      see: https://github.com/omisego/plasma-contracts/issues/440
     * @param exitId The exitId of the in-flight exit
     */
    function deleteNonPiggybackedInFlightExit(uint160 exitId) public nonReentrant(framework) {
        deleteNonPiggybackIFEController.run(inFlightExitMap, exitId);
    }

    /**
     * @notice Process in-flight exit
     * @dev This function is designed to be called in the main processExit function, thus, using internal
     * @param exitId The in-flight exit ID
     * @param token The token (in erc20 address or address(0) for ETH) of the exiting output
     */
    function processInFlightExit(uint160 exitId, address token) internal {
        processInflightExitController.run(inFlightExitMap, exitId, token);
    }

    /**
     * @notice Retrieves the in-flight exit bond size
     */
    function startIFEBondSize() public view returns (uint128) {
        return startIFEBond.bondSize();
    }

    /**
     * @notice Updates the in-flight exit bond size, taking two days to become effective.
     * @param newBondSize The new bond size
     */
    function updateStartIFEBondSize(uint128 newBondSize) public onlyFrom(framework.getMaintainer()) {
        startIFEBond.updateBondSize(newBondSize);
        emit IFEBondUpdated(newBondSize);
    }

    /**
     * @notice Retrieves the piggyback bond size
     */
    function piggybackBondSize() public view returns (uint128) {
        return piggybackBond.bondSize();
    }

    /**
     * @notice Updates the piggyback bond size, taking two days to become effective
     * @param newBondSize The new bond size
     */
    function updatePiggybackBondSize(uint128 newBondSize) public onlyFrom(framework.getMaintainer()) {
        piggybackBond.updateBondSize(newBondSize);
        emit PiggybackBondUpdated(newBondSize);
    }
}

File 64 of 114 : PaymentInFlightExitRouterArgs.sol
pragma solidity 0.5.11;

library PaymentInFlightExitRouterArgs {
    /**
    * @notice Wraps arguments for startInFlightExit.
    * @param inFlightTx RLP encoded in-flight transaction.
    * @param inputTxs Transactions that created the inputs to the in-flight transaction. In the same order as in-flight transaction inputs.
    * @param inputUtxosPos Utxos that represent in-flight transaction inputs. In the same order as input transactions.
    * @param inputTxsInclusionProofs Merkle proofs that show the input-creating transactions are valid. In the same order as input transactions.
    * @param inFlightTxWitnesses Witnesses for in-flight transaction. In the same order as input transactions.
    */
    struct StartExitArgs {
        bytes inFlightTx;
        bytes[] inputTxs;
        uint256[] inputUtxosPos;
        bytes[] inputTxsInclusionProofs;
        bytes[] inFlightTxWitnesses;
    }

    /**
    * @notice Wraps arguments for piggybacking on in-flight transaction input exit
    * @param inFlightTx RLP-encoded in-flight transaction
    * @param inputIndex Index of the input to piggyback on
    */
    struct PiggybackInFlightExitOnInputArgs {
        bytes inFlightTx;
        uint16 inputIndex;
    }

    /**
    * @notice Wraps arguments for piggybacking on in-flight transaction output exit
    * @param inFlightTx RLP-encoded in-flight transaction
    * @param outputIndex Index of the output to piggyback on
    */
    struct PiggybackInFlightExitOnOutputArgs {
        bytes inFlightTx;
        uint16 outputIndex;
    }

    /**
     * @notice Wraps arguments for challenging non-canonical in-flight exits
     * @param inputTx Transaction that created the input shared by the in-flight transaction and its competitor
     * @param inputUtxoPos Position of input utxo
     * @param inFlightTx RLP-encoded in-flight transaction
     * @param inFlightTxInputIndex Index of the shared input in the in-flight transaction
     * @param competingTx RLP-encoded competing transaction
     * @param competingTxInputIndex Index of shared input in competing transaction
     * @param competingTxPos (Optional) Position of competing transaction in the chain, if included. OutputIndex of the position should be 0.
     * @param competingTxInclusionProof (Optional) Merkle proofs showing that the competing transaction was contained in chain
     * @param competingTxWitness Witness for competing transaction
     */
    struct ChallengeCanonicityArgs {
        bytes inputTx;
        uint256 inputUtxoPos;
        bytes inFlightTx;
        uint16 inFlightTxInputIndex;
        bytes competingTx;
        uint16 competingTxInputIndex;
        uint256 competingTxPos;
        bytes competingTxInclusionProof;
        bytes competingTxWitness;
    }

    /**
     * @notice Wraps arguments for challenging in-flight exit input spent
     * @param inFlightTx RLP-encoded in-flight transaction
     * @param inFlightTxInputIndex Index of spent input
     * @param challengingTx RLP-encoded challenging transaction
     * @param challengingTxInputIndex Index of spent input in a challenging transaction
     * @param challengingTxWitness Witness for challenging transactions
     * @param inputTx RLP-encoded input transaction
     * @param inputUtxoPos UTXO position of input transaction's output
     * @param senderData A keccak256 hash of the sender's address
     */
    struct ChallengeInputSpentArgs {
        bytes inFlightTx;
        uint16 inFlightTxInputIndex;
        bytes challengingTx;
        uint16 challengingTxInputIndex;
        bytes challengingTxWitness;
        bytes inputTx;
        uint256 inputUtxoPos;
        bytes32 senderData;
    }

     /**
     * @notice Wraps arguments for challenging in-flight transaction output exit
     * @param inFlightTx RLP-encoded in-flight transaction
     * @param inFlightTxInclusionProof Proof that an in-flight transaction is included in Plasma
     * @param outputUtxoPos UTXO position of challenged output
     * @param challengingTx RLP-encoded challenging transaction
     * @param challengingTxInputIndex Input index of challenged output in a challenging transaction
     * @param challengingTxWitness Witness for challenging transaction
     * @param senderData A keccak256 hash of the sender's address
     */
    struct ChallengeOutputSpent {
        bytes inFlightTx;
        bytes inFlightTxInclusionProof;
        uint256 outputUtxoPos;
        bytes challengingTx;
        uint16 challengingTxInputIndex;
        bytes challengingTxWitness;
        bytes32 senderData;
    }
}

File 65 of 114 : PaymentStandardExitRouter.sol
pragma solidity 0.5.11;
pragma experimental ABIEncoderV2;

import "./PaymentStandardExitRouterArgs.sol";
import "../PaymentExitGameArgs.sol";
import "../PaymentExitDataModel.sol";
import "../controllers/PaymentStartStandardExit.sol";
import "../controllers/PaymentProcessStandardExit.sol";
import "../controllers/PaymentChallengeStandardExit.sol";
import "../../registries/SpendingConditionRegistry.sol";
import "../../utils/BondSize.sol";
import "../../../vaults/EthVault.sol";
import "../../../vaults/Erc20Vault.sol";
import "../../../framework/PlasmaFramework.sol";
import "../../../framework/interfaces/IExitProcessor.sol";
import "../../../utils/OnlyWithValue.sol";
import "../../../utils/OnlyFromAddress.sol";
import "../../../utils/FailFastReentrancyGuard.sol";

contract PaymentStandardExitRouter is
    IExitProcessor,
    OnlyFromAddress,
    OnlyWithValue,
    FailFastReentrancyGuard
{
    using PaymentStartStandardExit for PaymentStartStandardExit.Controller;
    using PaymentChallengeStandardExit for PaymentChallengeStandardExit.Controller;
    using PaymentProcessStandardExit for PaymentProcessStandardExit.Controller;
    using BondSize for BondSize.Params;

    // Initial bond size = 70000 (gas cost of challenge) * 20 gwei (current fast gas price) * 10 (safety margin)
    uint128 public constant INITIAL_BOND_SIZE = 14000000000000000 wei;

    // Each bond size upgrade can either at most increase to 200% or decrease to 50% of current bond
    uint16 public constant BOND_LOWER_BOUND_DIVISOR = 2;
    uint16 public constant BOND_UPPER_BOUND_MULTIPLIER = 2;

    PaymentExitDataModel.StandardExitMap internal standardExitMap;
    PaymentStartStandardExit.Controller internal startStandardExitController;
    PaymentProcessStandardExit.Controller internal processStandardExitController;
    PaymentChallengeStandardExit.Controller internal challengeStandardExitController;
    BondSize.Params internal startStandardExitBond;

    PlasmaFramework private framework;

    event StandardExitBondUpdated(uint128 bondSize);

    event ExitStarted(
        address indexed owner,
        uint160 exitId
    );

    event ExitChallenged(
        uint256 indexed utxoPos
    );

    event ExitOmitted(
        uint160 indexed exitId
    );

    event ExitFinalized(
        uint160 indexed exitId
    );

    event BondReturnFailed(
        address indexed receiver,
        uint256 amount
    );

    constructor(PaymentExitGameArgs.Args memory args)
        public
    {
        framework = args.framework;

        EthVault ethVault = EthVault(args.framework.vaults(args.ethVaultId));
        require(address(ethVault) != address(0), "Invalid ETH vault");

        Erc20Vault erc20Vault = Erc20Vault(args.framework.vaults(args.erc20VaultId));
        require(address(erc20Vault) != address(0), "Invalid ERC20 vault");

        startStandardExitController = PaymentStartStandardExit.buildController(
            this,
            args.framework,
            args.ethVaultId,
            args.erc20VaultId,
            args.supportTxType
        );

        challengeStandardExitController = PaymentChallengeStandardExit.buildController(
            args.framework,
            args.spendingConditionRegistry,
            args.safeGasStipend
        );

        processStandardExitController = PaymentProcessStandardExit.Controller(
            args.framework, ethVault, erc20Vault, args.safeGasStipend
        );

        startStandardExitBond = BondSize.buildParams(INITIAL_BOND_SIZE, BOND_LOWER_BOUND_DIVISOR, BOND_UPPER_BOUND_MULTIPLIER);
    }

    /**
     * @notice Getter retrieves standard exit data of the PaymentExitGame
     * @param exitIds Exit IDs of the standard exits
     */
    function standardExits(uint160[] calldata exitIds) external view returns (PaymentExitDataModel.StandardExit[] memory) {
        PaymentExitDataModel.StandardExit[] memory exits = new PaymentExitDataModel.StandardExit[](exitIds.length);
        for (uint i = 0; i < exitIds.length; i++){
            uint160 exitId = exitIds[i];
            exits[i] = standardExitMap.exits[exitId];
        }
        return exits;
    }

    /**
     * @notice Retrieves the standard exit bond size
     */
    function startStandardExitBondSize() public view returns (uint128) {
        return startStandardExitBond.bondSize();
    }

    /**
     * @notice Updates the standard exit bond size, taking two days to become effective
     * @param newBondSize The new bond size
     */
    function updateStartStandardExitBondSize(uint128 newBondSize) public onlyFrom(framework.getMaintainer()) {
        startStandardExitBond.updateBondSize(newBondSize);
        emit StandardExitBondUpdated(newBondSize);
    }

    /**
     * @notice Starts a standard exit of a given output, using output-age priority
     */
    function startStandardExit(
        PaymentStandardExitRouterArgs.StartStandardExitArgs memory args
    )
        public
        payable
        nonReentrant(framework)
        onlyWithValue(startStandardExitBondSize())
    {
        startStandardExitController.run(standardExitMap, args);
    }

    /**
     * @notice Challenge a standard exit by showing the exiting output was spent
     */
    function challengeStandardExit(PaymentStandardExitRouterArgs.ChallengeStandardExitArgs memory args)
        public
        nonReentrant(framework)
    {
        challengeStandardExitController.run(standardExitMap, args);
    }

    /**
     * @notice Process standard exit
     * @dev This function is designed to be called in the main processExit function, using internal
     * @param exitId The standard exit ID
     * @param token The token (in erc20 address or address(0) for ETH) of the exiting output
     */
    function processStandardExit(uint160 exitId, address token) internal {
        processStandardExitController.run(standardExitMap, exitId, token);
    }
}

File 66 of 114 : PaymentStandardExitRouterArgs.sol
pragma solidity 0.5.11;

library PaymentStandardExitRouterArgs {
    /**
     * @notice Wraps arguments for startStandardExit
     * @param utxoPos Position of the exiting output
     * @param rlpOutputTx The RLP-encoded transaction that creates the exiting output
     * @param outputTxInclusionProof A Merkle proof showing that the transaction was included
    */
    struct StartStandardExitArgs {
        uint256 utxoPos;
        bytes rlpOutputTx;
        bytes outputTxInclusionProof;
    }

    /**
     * @notice Input args data for challengeStandardExit
     * @param exitId Identifier of the standard exit to challenge
     * @param exitingTx RLP-encoded transaction that creates the exiting output
     * @param challengeTx RLP-encoded transaction that spends the exiting output
     * @param inputIndex Input of the challenging tx, corresponding to the exiting output
     * @param witness Witness data that proves the exiting output is spent
     * @param senderData A keccak256 hash of the sender's address
     */
    struct ChallengeStandardExitArgs {
        uint160 exitId;
        bytes exitingTx;
        bytes challengeTx;
        uint16 inputIndex;
        bytes witness;
        bytes32 senderData;
    }
}

File 67 of 114 : PaymentOutputToPaymentTxCondition.sol
pragma solidity 0.5.11;

import "openzeppelin-solidity/contracts/cryptography/ECDSA.sol";

import "../../interfaces/ISpendingCondition.sol";
import "../../../utils/PosLib.sol";
import "../../../transactions/PaymentTransactionModel.sol";
import "../../../transactions/eip712Libs/PaymentEip712Lib.sol";

contract PaymentOutputToPaymentTxCondition is ISpendingCondition {
    using PaymentEip712Lib for PaymentEip712Lib.Constants;
    using PosLib for PosLib.Position;
    using PaymentTransactionModel for PaymentTransactionModel.Transaction;

    uint256 internal supportInputTxType;
    uint256 internal supportSpendingTxType;
    PaymentEip712Lib.Constants internal eip712;

    /**
     * @dev This is designed to be re-useable for all versions of payment transaction, so that
     *      inputTxType and spendingTxType of the payment output is injected instead
     */
    constructor(address framework, uint256 inputTxType, uint256 spendingTxType) public {
        eip712 = PaymentEip712Lib.initConstants(framework);
        supportInputTxType = inputTxType;
        supportSpendingTxType = spendingTxType;
    }

    /**
     * @notice Verifies the spending condition
     * @param inputTxBytes Encoded input transaction, in bytes
     * @param utxoPos Position of the utxo
     * @param spendingTxBytes Spending transaction, in bytes
     * @param inputIndex Input index of the spending tx that points to the output
     * @param signature Signature of the output owner
     */
    function verify(
        bytes calldata inputTxBytes,
        uint256 utxoPos,
        bytes calldata spendingTxBytes,
        uint16 inputIndex,
        bytes calldata signature
    )
        external
        view
        returns (bool)
    {
        PaymentTransactionModel.Transaction memory inputTx = PaymentTransactionModel.decode(inputTxBytes);
        require(inputTx.txType == supportInputTxType, "Input tx is an unsupported payment tx type");

        PaymentTransactionModel.Transaction memory spendingTx = PaymentTransactionModel.decode(spendingTxBytes);
        require(spendingTx.txType == supportSpendingTxType, "The spending tx is an unsupported payment tx type");

        require(
            spendingTx.inputs[inputIndex] == bytes32(utxoPos),
            "Spending tx points to the incorrect output UTXO position"
        );

        PosLib.Position memory decodedUtxoPos = PosLib.decode(utxoPos);
        address owner = PaymentTransactionModel.getOutputOwner(inputTx.getOutput(decodedUtxoPos.outputIndex));
        address signer = ECDSA.recover(eip712.hashTx(spendingTx), signature);
        require(signer != address(0), "Failed to recover the signer from the signature");
        require(owner == signer, "Tx is not signed correctly");

        return true;
    }
}

File 68 of 114 : SpendingConditionRegistry.sol
pragma solidity 0.5.11;

import "openzeppelin-solidity/contracts/ownership/Ownable.sol";
import "openzeppelin-solidity/contracts/utils/Address.sol";

import "../interfaces/ISpendingCondition.sol";

/**
 * @title SpendingConditionRegistry
 * @notice The registry contracts of the spending condition
 * @dev This is designed to renounce ownership before injecting the registry contract to ExitGame contracts
 *      After registering all the essential condition contracts, the owner should renounce its ownership to
 *      ensure no further conditions are registered for an ExitGame contract.
 *      https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/ownership/Ownable.sol#L55
 */
contract SpendingConditionRegistry is Ownable {
    // mapping of hash(outputType, spendingTxTpye) => ISpendingCondition
    mapping(bytes32 => ISpendingCondition) internal _spendingConditions;

    function spendingConditions(uint256 outputType, uint256 spendingTxType) public view returns (ISpendingCondition) {
        bytes32 key = keccak256(abi.encode(outputType, spendingTxType));
        return _spendingConditions[key];
    }

    /**
     * @notice Register the spending condition contract
     * @param outputType The output type of the spending condition
     * @param spendingTxType Spending tx type of the spending condition
     * @param condition The spending condition contract
     */
    function registerSpendingCondition(uint256 outputType, uint256 spendingTxType, ISpendingCondition condition)
        public
        onlyOwner
    {
        require(outputType != 0, "Registration not possible with output type 0");
        require(spendingTxType != 0, "Registration not possible with spending tx type 0");
        require(Address.isContract(address(condition)), "Registration not possible with a non-contract address");

        bytes32 key = keccak256(abi.encode(outputType, spendingTxType));
        require(address(_spendingConditions[key]) == address(0), "The (output type, spending tx type) pair is already registered");

        _spendingConditions[key] = condition;
    }
}

File 69 of 114 : BondSize.sol
pragma solidity 0.5.11;

/**
 * @notice Stores an updateable bond size
 * @dev Bond design details at https://github.com/omisego/research/issues/107#issuecomment-525267486
 * @dev Security depends on the min/max value, which can be updated to compare to the current bond size, plus the waiting period
 *      Min/max value of the next bond size prevents the possibility to set bond size too low or too high, which risks breaking the system
 *      Waiting period ensures that a user does not get an unexpected bond without notice.
 */
library BondSize {
    uint64 constant public WAITING_PERIOD = 2 days;

    /**
     * @dev Struct is designed to be packed into two 32-bytes storage slots
     * @param previousBondSize The bond size prior to upgrade, which should remain the same until the waiting period completes
     * @param updatedBondSize The bond size to use once the waiting period completes
     * @param effectiveUpdateTime A timestamp for the end of the waiting period, when the updated bond size is implemented
     * @param lowerBoundDivisor The divisor that checks the lower bound for an update. Each update cannot be lower than (current bond / lowerBoundDivisor)
     * @param upperBoundMultiplier The multiplier that checks the upper bound for an update. Each update cannot be larger than (current bond * upperBoundMultiplier)
     */
    struct Params {
        uint128 previousBondSize;
        uint128 updatedBondSize;
        uint128 effectiveUpdateTime;
        uint16 lowerBoundDivisor;
        uint16 upperBoundMultiplier;
    }

    function buildParams(uint128 initialBondSize, uint16 lowerBoundDivisor, uint16 upperBoundMultiplier)
        internal
        pure
        returns (Params memory)
    {
        // Set the initial value far into the future
        uint128 initialEffectiveUpdateTime = 2 ** 63;
        return Params({
            previousBondSize: initialBondSize,
            updatedBondSize: 0,
            effectiveUpdateTime: initialEffectiveUpdateTime,
            lowerBoundDivisor: lowerBoundDivisor,
            upperBoundMultiplier: upperBoundMultiplier
        });
    }

    /**
    * @notice Updates the bond size
    * @dev The new bond size value updates once the two day waiting period completes
    * @param newBondSize The new bond size
    */
    function updateBondSize(Params storage self, uint128 newBondSize) internal {
        validateBondSize(self, newBondSize);

        if (self.updatedBondSize != 0 && now >= self.effectiveUpdateTime) {
            self.previousBondSize = self.updatedBondSize;
        }
        self.updatedBondSize = newBondSize;
        self.effectiveUpdateTime = uint64(now) + WAITING_PERIOD;
    }

    /**
    * @notice Returns the current bond size
    */
    function bondSize(Params memory self) internal view returns (uint128) {
        if (now < self.effectiveUpdateTime) {
            return self.previousBondSize;
        } else {
            return self.updatedBondSize;
        }
    }

    function validateBondSize(Params memory self, uint128 newBondSize) private view {
        uint128 currentBondSize = bondSize(self);
        require(newBondSize > 0, "Bond size cannot be zero");
        require(newBondSize >= currentBondSize / self.lowerBoundDivisor, "Bond size is too low");
        require(uint256(newBondSize) <= uint256(currentBondSize) * self.upperBoundMultiplier, "Bond size is too high");
    }
}

File 70 of 114 : ExitId.sol
pragma solidity 0.5.11;

import "../../utils/Bits.sol";
import "../../utils/PosLib.sol";

library ExitId {
    using PosLib for PosLib.Position;
    using Bits for uint160;
    using Bits for uint256;

    /**
     * @notice Checks whether exitId is a standard exit ID
     */
    function isStandardExit(uint160 _exitId) internal pure returns (bool) {
        return _exitId.getBit(151) == 0;
    }

    /**
     * @notice Given transaction bytes and UTXO position, returns its exit ID
     * @dev Computation of a deposit ID is different to any other tx because txBytes of a deposit tx can be a non-unique value
     * @notice Output index must be within range 0 - 255
     * @param _isDeposit Defines whether the tx for the exitId is a deposit tx
     * @param _txBytes Transaction bytes
     * @param _utxoPos UTXO position of the exiting output
     * @return _standardExitId Unique ID of the standard exit
     *     Anatomy of returned value, most significant bits first:
     *     8-bits - output index
     *     1-bit - in-flight flag (0 for standard exit)
     *     151-bits - hash(tx) or hash(tx|utxo) for deposit
     */
    function getStandardExitId(
        bool _isDeposit,
        bytes memory _txBytes,
        PosLib.Position memory _utxoPos
    )
        internal
        pure
        returns (uint160)
    {
        if (_isDeposit) {
            bytes32 hashData = keccak256(abi.encodePacked(_txBytes, _utxoPos.encode()));
            return _computeStandardExitId(hashData, _utxoPos.outputIndex);
        }

        return _computeStandardExitId(keccak256(_txBytes), _utxoPos.outputIndex);
    }

    /**
    * @notice Given transaction bytes, returns in-flight exit ID
    * @param _txBytes Transaction bytes
    * @return Unique in-flight exit ID
    */
    function getInFlightExitId(bytes memory _txBytes) internal pure returns (uint160) {
        return uint160((uint256(keccak256(_txBytes)) >> 105).setBit(151));
    }

    function _computeStandardExitId(bytes32 _txhash, uint16 _outputIndex)
        private
        pure
        returns (uint160)
    {
        uint256 exitId = (uint256(_txhash) >> 105) | (uint256(_outputIndex) << 152);
        uint160 croppedExitId = uint160(exitId);

        require(uint256(croppedExitId) == exitId, "ExitId overflows");

        return croppedExitId;
    }
}

File 71 of 114 : ExitableTimestamp.sol
pragma solidity 0.5.11;

import "openzeppelin-solidity/contracts/math/Math.sol";

library ExitableTimestamp {
    struct Calculator {
        uint256 minExitPeriod;
    }

    /**
     * @notice Calculates the exitable timestamp for a mined transaction
     * @dev This is the main function when asking for exitable timestamp in most cases.
     *      The only exception is to calculate the exitable timestamp for a deposit output in standard exit.
     *      Should use the function 'calculateDepositTxOutputExitableTimestamp' for that case.
     */
    function calculateTxExitableTimestamp(
        Calculator memory _calculator,
        uint256 _now,
        uint256 _blockTimestamp
    )
        internal
        pure
        returns (uint64)
    {
        return uint64(Math.max(_blockTimestamp + (_calculator.minExitPeriod * 2), _now + _calculator.minExitPeriod));
    }

    /**
     * @notice Calculates the exitable timestamp for deposit transaction output for standard exit
     * @dev This function should only be used in standard exit for calculating exitable timestamp of a deposit output.
     *      For in-fight exit, the priority of a input tx which is a deposit tx should still be using the another function 'calculateTxExitableTimestamp'.
     *      See discussion here: https://git.io/Je4N5
     *      Reason of deposit output has different exitable timestamp: https://git.io/JecCV
     */
    function calculateDepositTxOutputExitableTimestamp(
        Calculator memory _calculator,
        uint256 _now
    )
        internal
        pure
        returns (uint64)
    {
        return uint64(_now + _calculator.minExitPeriod);
    }
}

File 72 of 114 : MoreVpFinalization.sol
pragma solidity 0.5.11;
pragma experimental ABIEncoderV2;

import "../../framework/PlasmaFramework.sol";
import "../../framework/Protocol.sol";
import "../../utils/Merkle.sol";
import "../../utils/PosLib.sol";
import "../../transactions/GenericTransaction.sol";

/**
 * @notice Library to check finalization for MoreVP protocol
 * @dev This library assumes that the tx is of the GenericTransaction format
 */
library MoreVpFinalization {
    using PosLib for PosLib.Position;

    /**
    * @notice Checks whether a transaction is "standard finalized".
    *         For MoreVP, it means the transaction should be included in a plasma block.
    */
    function isStandardFinalized(
        PlasmaFramework framework,
        bytes memory txBytes,
        PosLib.Position memory txPos,
        bytes memory inclusionProof
    )
        internal
        view
        returns (bool)
    {
        require(txPos.outputIndex == 0, "Invalid transaction position");
        GenericTransaction.Transaction memory genericTx = GenericTransaction.decode(txBytes);
        uint8 protocol = framework.protocols(genericTx.txType);
        require(protocol == Protocol.MORE_VP(), "MoreVpFinalization: not a MoreVP protocol tx");

        (bytes32 root,) = framework.blocks(txPos.blockNum);
        require(root != bytes32(""), "Failed to get the root hash of the block num");

        return Merkle.checkMembership(
            txBytes, txPos.txIndex, root, inclusionProof
        );
    }

    /**
    * @notice Checks whether a transaction is "protocol finalized"
    *         For MoreVP, since it allows in-flight tx, so only checks for the existence of the transaction
    */
    function isProtocolFinalized(
        PlasmaFramework framework,
        bytes memory txBytes
    )
        internal
        view
        returns (bool)
    {
        if (txBytes.length == 0) {
            return false;
        }

        GenericTransaction.Transaction memory genericTx = GenericTransaction.decode(txBytes);
        uint8 protocol = framework.protocols(genericTx.txType);
        require(protocol == Protocol.MORE_VP(), "MoreVpFinalization: not a MoreVP protocol tx");

        return true;
    }
}

File 73 of 114 : OutputId.sol
pragma solidity 0.5.11;

library OutputId {
    /**
     * @notice Computes the output ID for a deposit tx
     * @dev Deposit tx bytes might not be unique because all inputs are empty
     *      Two deposits with the same output value would result in the same tx bytes
     *      As a result, we need to hash with utxoPos to ensure uniqueness
     * @param _txBytes Transaction bytes
     * @param _outputIndex Output index of the output
     * @param _utxoPosValue (Optional) UTXO position of the deposit output
     */
    function computeDepositOutputId(bytes memory _txBytes, uint256 _outputIndex, uint256 _utxoPosValue)
        internal
        pure
        returns(bytes32)
    {
        return keccak256(abi.encodePacked(_txBytes, _outputIndex, _utxoPosValue));
    }

    /**
     * @notice Computes the output ID for normal (non-deposit) tx
     * @dev Since txBytes for non-deposit tx is unique, directly hash the txBytes with outputIndex
     * @param _txBytes Transaction bytes
     * @param _outputIndex Output index of the output
     */
    function computeNormalOutputId(bytes memory _txBytes, uint256 _outputIndex)
        internal
        pure
        returns(bytes32)
    {
        return keccak256(abi.encodePacked(_txBytes, _outputIndex));
    }
}

File 74 of 114 : BlockController.sol
pragma solidity 0.5.11;

import "./models/BlockModel.sol";
import "./registries/VaultRegistry.sol";
import "../utils/OnlyFromAddress.sol";

/**
* @notice Controls the logic and functions for block submissions in PlasmaFramework
* @dev There are two types of blocks: child block and deposit block
*      Each child block has an interval of 'childBlockInterval'
*      The interval is preserved for deposits. Each deposit results in one deposit block.
*      For instance, a child block would be in block 1000 and the next deposit would result in block 1001.
*
*      Only the authority address can perform a block submission.
*      Details on limitations for the authority address can be found here: https://github.com/omisego/elixir-omg#managing-the-operator-address
*/
contract BlockController is OnlyFromAddress, VaultRegistry {
    address public authority;
    uint256 public childBlockInterval;
    uint256 public nextChildBlock;
    uint256 public nextDeposit;
    bool public isChildChainActivated;

    mapping (uint256 => BlockModel.Block) public blocks; // block number => Block data

    event BlockSubmitted(
        uint256 blknum
    );

    event ChildChainActivated(
        address authority
    );

    constructor(
        uint256 _interval,
        uint256 _minExitPeriod,
        uint256 _initialImmuneVaults,
        address _authority
    )
        public
        VaultRegistry(_minExitPeriod, _initialImmuneVaults)
    {
        authority = _authority;
        childBlockInterval = _interval;
        nextChildBlock = childBlockInterval;
        nextDeposit = 1;
        isChildChainActivated = false;
    }

    /**
     * @notice Activates the child chain so that child chain can start to submit child blocks to root chain
     * @notice Can only be called once by the authority.
     * @notice Sets isChildChainActivated to true and emits the ChildChainActivated event.
     * @dev This is a preserved action for authority account to start its nonce with 1.
     *      Child chain rely ethereum nonce to protect re-org: https://git.io/JecDG
     *      see discussion: https://git.io/JenaT, https://git.io/JecDO
     */
    function activateChildChain() external onlyFrom(authority) {
        require(isChildChainActivated == false, "Child chain already activated");
        isChildChainActivated = true;
        emit ChildChainActivated(authority);
    }

    /**
     * @notice Allows the authority to submit the Merkle root of a Plasma block
     * @dev emit BlockSubmitted event
     * @dev Block number jumps 'childBlockInterval' per submission
     * @dev See discussion in https://github.com/omisego/plasma-contracts/issues/233
     * @param _blockRoot Merkle root of the Plasma block
     */
    function submitBlock(bytes32 _blockRoot) external onlyFrom(authority) {
        require(isChildChainActivated == true, "Child chain has not been activated by authority address yet");
        uint256 submittedBlockNumber = nextChildBlock;

        blocks[submittedBlockNumber] = BlockModel.Block({
            root: _blockRoot,
            timestamp: block.timestamp
        });

        nextChildBlock += childBlockInterval;
        nextDeposit = 1;

        emit BlockSubmitted(submittedBlockNumber);
    }

    /**
     * @notice Submits a block for deposit
     * @dev Block number adds 1 per submission; it's possible to have at most 'childBlockInterval' deposit blocks between two child chain blocks
     * @param _blockRoot Merkle root of the Plasma block
     * @return The deposit block number
     */
    function submitDepositBlock(bytes32 _blockRoot) public onlyFromNonQuarantinedVault returns (uint256) {
        require(isChildChainActivated == true, "Child chain has not been activated by authority address yet");
        require(nextDeposit < childBlockInterval, "Exceeded limit of deposits per child block interval");

        uint256 blknum = nextDepositBlock();
        blocks[blknum] = BlockModel.Block({
            root : _blockRoot,
            timestamp : block.timestamp
        });

        nextDeposit++;
        return blknum;
    }

    function nextDepositBlock() public view returns (uint256) {
        return nextChildBlock - childBlockInterval + nextDeposit;
    }

    function isDeposit(uint256 blockNum) public view returns (bool) {
        require(blocks[blockNum].timestamp != 0, "Block does not exist");
        return blockNum % childBlockInterval != 0;
    }
}

File 75 of 114 : ExitGameController.sol
pragma solidity 0.5.11;
pragma experimental ABIEncoderV2;

import "./interfaces/IExitProcessor.sol";
import "./registries/ExitGameRegistry.sol";
import "./utils/PriorityQueue.sol";
import "./utils/ExitPriority.sol";
import "../utils/PosLib.sol";

/**
 * @notice Controls the logic and functions for ExitGame to interact with the PlasmaFramework
 *         Plasma M(ore)VP relies on exit priority to secure the user from invalid transactions
 *         The priority queue ensures the exit is processed with the exit priority
 *         For details, see the Plasma MVP spec: https://ethresear.ch/t/minimal-viable-plasma/426
 */
contract ExitGameController is ExitGameRegistry {
    // exit hashed (priority, vault id, token) => IExitProcessor
    mapping (bytes32 => IExitProcessor) public delegations;
    // hashed (vault id, token) => PriorityQueue
    mapping (bytes32 => PriorityQueue) public exitsQueues;
    // outputId => exitId
    mapping (bytes32 => uint160) public outputsFinalizations;
    bool private mutex = false;

    event ExitQueueAdded(
        uint256 vaultId,
        address token
    );

    event ProcessedExitsNum(
        uint256 processedNum,
        uint256 vaultId,
        address token
    );

    event ExitQueued(
        uint160 indexed exitId,
        uint256 priority
    );

    constructor(uint256 _minExitPeriod, uint256 _initialImmuneExitGames)
        public
        ExitGameRegistry(_minExitPeriod, _initialImmuneExitGames)
    {
    }

    /**
     * @dev Prevents reentrant calls by using a mutex.
     */
    modifier nonReentrant() {
        require(!mutex, "Reentrant call");
        mutex = true;
        _;
        assert(mutex);
        mutex = false;
    }

    /**
     * @notice Activates non reentrancy mode
     *         Guards against reentering into publicly accessible code that modifies state related to exits
     * @dev Accessible only from non quarantined exit games, uses a mutex
     */
    function activateNonReentrant() external onlyFromNonQuarantinedExitGame() {
        require(!mutex, "Reentrant call");
        mutex = true;
    }

    /**
     * @notice Deactivates non reentrancy mode
     * @dev Accessible only from non quarantined exit games, uses a mutex
     */
    function deactivateNonReentrant() external onlyFromNonQuarantinedExitGame() {
        assert(mutex);
        mutex = false;
    }

    /**
     * @notice Checks if the queue for a specified token was created
     * @param vaultId ID of the vault that handles the token
     * @param token Address of the token
     * @return bool Defines whether the queue for a token was created
     */
    function hasExitQueue(uint256 vaultId, address token) public view returns (bool) {
        bytes32 key = exitQueueKey(vaultId, token);
        return hasExitQueue(key);
    }

    /**
     * @notice Adds queue to the Plasma framework
     * @dev The queue is created as a new contract instance
     * @param vaultId ID of the vault
     * @param token Address of the token
     */
    function addExitQueue(uint256 vaultId, address token) external {
        require(vaultId != 0, "Vault ID must not be 0");
        bytes32 key = exitQueueKey(vaultId, token);
        require(!hasExitQueue(key), "Exit queue exists");
        exitsQueues[key] = new PriorityQueue();
        emit ExitQueueAdded(vaultId, token);
    }

    /**
     * @notice Enqueue exits from exit game contracts is a function that places the exit into the
     *         priority queue to enforce the priority of exit during 'processExits'
     * @dev emits ExitQueued event, which can be used to back trace the priority inside the queue
     * @dev Caller of this function should add "pragma experimental ABIEncoderV2;" on top of file
     * @dev Priority (exitableAt, txPos, exitId) must be unique per queue. Do not enqueue when the same priority is already in the queue.
     * @param vaultId Vault ID of the vault that stores exiting funds
     * @param token Token for the exit
     * @param exitableAt The earliest time a specified exit can be processed
     * @param txPos Transaction position for the exit priority. For SE it should be the exit tx, for IFE it should be the youngest input tx position.
     * @param exitId ID used by the exit processor contract to determine how to process the exit
     * @param exitProcessor The exit processor contract, called during "processExits"
     * @return A unique priority number computed for the exit
     */
    function enqueue(
        uint256 vaultId,
        address token,
        uint64 exitableAt,
        PosLib.Position calldata txPos,
        uint160 exitId,
        IExitProcessor exitProcessor
    )
        external
        onlyFromNonQuarantinedExitGame
        returns (uint256)
    {
        bytes32 key = exitQueueKey(vaultId, token);
        require(hasExitQueue(key), "The queue for the (vaultId, token) pair is not yet added to the Plasma framework");
        PriorityQueue queue = exitsQueues[key];

        uint256 priority = ExitPriority.computePriority(exitableAt, txPos, exitId);

        queue.insert(priority);

        bytes32 delegationKey = getDelegationKey(priority, vaultId, token);
        require(address(delegations[delegationKey]) == address(0), "The same priority is already enqueued");
        delegations[delegationKey] = exitProcessor;

        emit ExitQueued(exitId, priority);
        return priority;
    }

    /**
     * @notice Processes any exits that have completed the challenge period. Exits are processed according to the exit priority.
     * @dev Emits ProcessedExitsNum event
     * @param vaultId Vault ID of the vault that stores exiting funds
     * @param token The token type to process
     * @param topExitId Unique identifier for prioritizing the first exit to process. Set to zero to skip this check.
     * @param maxExitsToProcess Maximum number of exits to process
     * @return Total number of processed exits
     */
    function processExits(uint256 vaultId, address token, uint160 topExitId, uint256 maxExitsToProcess) external nonReentrant {
        bytes32 key = exitQueueKey(vaultId, token);
        require(hasExitQueue(key), "The token is not yet added to the Plasma framework");
        PriorityQueue queue = exitsQueues[key];
        require(queue.currentSize() > 0, "Exit queue is empty");

        uint256 uniquePriority = queue.getMin();
        uint160 exitId = ExitPriority.parseExitId(uniquePriority);
        require(topExitId == 0 || exitId == topExitId,
            "Top exit ID of the queue is different to the one specified");

        bytes32 delegationKey = getDelegationKey(uniquePriority, vaultId, token);
        IExitProcessor processor = delegations[delegationKey];
        uint256 processedNum = 0;

        while (processedNum < maxExitsToProcess && ExitPriority.parseExitableAt(uniquePriority) < block.timestamp) {
            delete delegations[delegationKey];
            queue.delMin();
            processedNum++;

            processor.processExit(exitId, vaultId, token);

            if (queue.currentSize() == 0) {
                break;
            }

            uniquePriority = queue.getMin();
            delegationKey = getDelegationKey(uniquePriority, vaultId, token);
            exitId = ExitPriority.parseExitId(uniquePriority);
            processor = delegations[delegationKey];
        }

        emit ProcessedExitsNum(processedNum, vaultId, token);
    }

    /**
     * @notice Checks whether any of the output with the given outputIds is already spent
     * @param _outputIds Output IDs to check
     */
    function isAnyInputFinalizedByOtherExit(bytes32[] calldata _outputIds, uint160 exitId) external view returns (bool) {
        for (uint i = 0; i < _outputIds.length; i++) {
            uint160 finalizedExitId = outputsFinalizations[_outputIds[i]];
            if (finalizedExitId != 0 && finalizedExitId != exitId) {
                return true;
            }
        }
        return false;
    }

    /**
     * @notice Batch flags already spent outputs (only not already spent)
     * @param outputIds Output IDs to flag
     */
    function batchFlagOutputsFinalized(bytes32[] calldata outputIds, uint160 exitId) external onlyFromNonQuarantinedExitGame {
        for (uint i = 0; i < outputIds.length; i++) {
            require(outputIds[i] != bytes32(""), "Should not flag with empty outputId");
            if (outputsFinalizations[outputIds[i]] == 0) {
                outputsFinalizations[outputIds[i]] = exitId;
            }
        }
    }

    /**
     * @notice Flags a single output as spent if it is not flagged already
     * @param outputId The output ID to flag as spent
     */
    function flagOutputFinalized(bytes32 outputId, uint160 exitId) external onlyFromNonQuarantinedExitGame {
        require(outputId != bytes32(""), "Should not flag with empty outputId");
        if (outputsFinalizations[outputId] == 0) {
            outputsFinalizations[outputId] = exitId;
        }
    }

     /**
     * @notice Checks whether output with a given outputId is finalized
     * @param outputId Output ID to check
     */
    function isOutputFinalized(bytes32 outputId) external view returns (bool) {
        return outputsFinalizations[outputId] != 0;
    }

    function getNextExit(uint256 vaultId, address token) external view returns (uint256) {
        bytes32 key = exitQueueKey(vaultId, token);
        return exitsQueues[key].getMin();
    }

    function exitQueueKey(uint256 vaultId, address token) private pure returns (bytes32) {
        return keccak256(abi.encodePacked(vaultId, token));
    }

    function hasExitQueue(bytes32 queueKey) private view returns (bool) {
        return address(exitsQueues[queueKey]) != address(0);
    }

    function getDelegationKey(uint256 priority, uint256 vaultId, address token) private pure returns (bytes32) {
        return keccak256(abi.encodePacked(priority, vaultId, token));
    }
}

File 76 of 114 : PlasmaFramework.sol
pragma solidity 0.5.11;
pragma experimental ABIEncoderV2;

import "./BlockController.sol";
import "./ExitGameController.sol";
import "./registries/VaultRegistry.sol";
import "./registries/ExitGameRegistry.sol";

contract PlasmaFramework is VaultRegistry, ExitGameRegistry, ExitGameController, BlockController {
    uint256 public constant CHILD_BLOCK_INTERVAL = 1000;

    /**
     * The minimum finalization period is the Plasma guarantee that all exits are safe provided the user takes action within the specified time period
     * When the child chain is rogue, user should start their exit and challenge any invalid exit within this period
     * An exit can be processed/finalized after minimum two finalization periods from its inclusion position, unless it is an exit for a deposit,
     * which would use one finalization period, instead of two
     *
     * For the Abstract Layer Design, OmiseGO also uses some multitude of this period to update its framework
     * See also ExitGameRegistry.sol, VaultRegistry.sol, and Vault.sol for more information on the update waiting time (the quarantined period)
     *
     * MVP: https://ethresear.ch/t/minimal-viable-plasma/426
     * MoreVP: https://github.com/omisego/elixir-omg/blob/master/docs/morevp.md#timeline
     * Special period for deposit: https://git.io/JecCV
     */
    uint256 public minExitPeriod;
    address private maintainer;
    string public version;

    constructor(
        uint256 _minExitPeriod,
        uint256 _initialImmuneVaults,
        uint256 _initialImmuneExitGames,
        address _authority,
        address _maintainer
    )
        public
        BlockController(CHILD_BLOCK_INTERVAL, _minExitPeriod, _initialImmuneVaults, _authority)
        ExitGameController(_minExitPeriod, _initialImmuneExitGames)
    {
        minExitPeriod = _minExitPeriod;
        maintainer = _maintainer;
    }

    function getMaintainer() public view returns (address) {
        return maintainer;
    }

    /**
     * @notice Gets the semantic version of the current deployed contracts
    */
    function getVersion() external view returns (string memory) {
        return version;
    }
    
    /**
     * @notice Sets the semantic version of the current deployed contracts
     * @param _version is semver string
     */
    function setVersion(string memory _version) public onlyFrom(getMaintainer()) {
        version = _version;
    }
}

File 77 of 114 : Protocol.sol
pragma solidity 0.5.11;

/**
 * @notice Protocols for the PlasmaFramework
 */
library Protocol {
    uint8 constant internal MVP_VALUE = 1;
    uint8 constant internal MORE_VP_VALUE = 2;

    // solhint-disable-next-line func-name-mixedcase
    function MVP() internal pure returns (uint8) {
        return MVP_VALUE;
    }

    // solhint-disable-next-line func-name-mixedcase
    function MORE_VP() internal pure returns (uint8) {
        return MORE_VP_VALUE;
    }

    function isValidProtocol(uint8 protocol) internal pure returns (bool) {
        return protocol == MVP_VALUE || protocol == MORE_VP_VALUE;
    }
}

File 78 of 114 : IExitProcessor.sol
pragma solidity 0.5.11;

/**
 * @dev An interface that allows custom logic to process exits for different requirements.
 *      This interface is used to dispatch to each custom processor when 'processExits' is called on PlasmaFramework.
 */
interface IExitProcessor {
    /**
     * @dev Function interface for processing exits.
     * @param exitId Unique ID for exit per tx type
     * @param vaultId ID of the vault that funds the exit
     * @param token Address of the token contract
     */
    function processExit(uint160 exitId, uint256 vaultId, address token) external;
}

File 79 of 114 : BlockModel.sol
pragma solidity 0.5.11;

library BlockModel {
    /**
     * @notice Block data structure that is stored in the contract
     * @param root The Merkle root block hash of the Plasma blocks
     * @param timestamp The timestamp, in seconds, when the block is saved
     */
    struct Block {
        bytes32 root;
        uint256 timestamp;
    }
}

File 80 of 114 : ExitGameRegistry.sol
pragma solidity 0.5.11;

import "openzeppelin-solidity/contracts/utils/Address.sol";

import "../Protocol.sol";
import "../utils/Quarantine.sol";
import "../../utils/OnlyFromAddress.sol";

contract ExitGameRegistry is OnlyFromAddress {
    using Quarantine for Quarantine.Data;

    mapping(uint256 => address) private _exitGames; // txType => exit game contract address
    mapping(address => uint256) private _exitGameToTxType; // exit game contract address => tx type
    mapping(uint256 => uint8) private _protocols; // tx type => protocol (MVP/MORE_VP)
    Quarantine.Data private _exitGameQuarantine;

    event ExitGameRegistered(
        uint256 txType,
        address exitGameAddress,
        uint8 protocol
    );

    /**
     * @dev It takes at least 3 * minExitPeriod before each new exit game contract is able to start protecting existing transactions
     *      see: https://github.com/omisego/plasma-contracts/issues/172
     *           https://github.com/omisego/plasma-contracts/issues/197
     */
    constructor (uint256 _minExitPeriod, uint256 _initialImmuneExitGames)
        public
    {
        _exitGameQuarantine.quarantinePeriod = 4 * _minExitPeriod;
        _exitGameQuarantine.immunitiesRemaining = _initialImmuneExitGames;
    }

    /**
     * @notice A modifier to verify that the call is from a non-quarantined exit game
     */
    modifier onlyFromNonQuarantinedExitGame() {
        require(_exitGameToTxType[msg.sender] != 0, "The call is not from a registered exit game contract");
        require(!_exitGameQuarantine.isQuarantined(msg.sender), "ExitGame is quarantined");
        _;
    }

    /**
     * @notice interface to get the 'maintainer' address.
     * @dev see discussion here: https://git.io/Je8is
     */
    function getMaintainer() public view returns (address);

    /**
     * @notice Checks whether the contract is safe to use and is not under quarantine
     * @dev Exposes information about exit games quarantine
     * @param _contract Address of the exit game contract
     * @return boolean Whether the contract is safe to use and is not under quarantine
     */
    function isExitGameSafeToUse(address _contract) public view returns (bool) {
        return _exitGameToTxType[_contract] != 0 && !_exitGameQuarantine.isQuarantined(_contract);
    }

    /**
     * @notice Registers an exit game within the PlasmaFramework. Only the maintainer can call the function.
     * @dev Emits ExitGameRegistered event to notify clients
     * @param _txType The tx type where the exit game wants to register
     * @param _contract Address of the exit game contract
     * @param _protocol The transaction protocol, either 1 for MVP or 2 for MoreVP
     */
    function registerExitGame(uint256 _txType, address _contract, uint8 _protocol) public onlyFrom(getMaintainer()) {
        require(_txType != 0, "Should not register with tx type 0");
        require(Address.isContract(_contract), "Should not register with a non-contract address");
        require(_exitGames[_txType] == address(0), "The tx type is already registered");
        require(_exitGameToTxType[_contract] == 0, "The exit game contract is already registered");
        require(Protocol.isValidProtocol(_protocol), "Invalid protocol value");

        _exitGames[_txType] = _contract;
        _exitGameToTxType[_contract] = _txType;
        _protocols[_txType] = _protocol;
        _exitGameQuarantine.quarantine(_contract);

        emit ExitGameRegistered(_txType, _contract, _protocol);
    }

    /**
     * @notice Public getter for retrieving protocol with tx type
     */
    function protocols(uint256 _txType) public view returns (uint8) {
        return _protocols[_txType];
    }

    /**
     * @notice Public getter for retrieving exit game address with tx type
     */
    function exitGames(uint256 _txType) public view returns (address) {
        return _exitGames[_txType];
    }

    /**
     * @notice Public getter for retrieving tx type with exit game address
     */
    function exitGameToTxType(address _exitGame) public view returns (uint256) {
        return _exitGameToTxType[_exitGame];
    }
}

File 81 of 114 : VaultRegistry.sol
pragma solidity 0.5.11;

import "openzeppelin-solidity/contracts/utils/Address.sol";

import "../utils/Quarantine.sol";
import "../../utils/OnlyFromAddress.sol";

contract VaultRegistry is OnlyFromAddress {
    using Quarantine for Quarantine.Data;

    mapping(uint256 => address) private _vaults; // vault id => vault address
    mapping(address => uint256) private _vaultToId; // vault address => vault id
    Quarantine.Data private _vaultQuarantine;

    event VaultRegistered(
        uint256 vaultId,
        address vaultAddress
    );

    /**
     * @dev It takes at least 2 minExitPeriod for each new vault contract to start.
     *      This is to protect deposit transactions already in mempool,
     *      and also make sure user only needs to SE within first week when invalid vault is registered.
     *      see: https://github.com/omisego/plasma-contracts/issues/412
     *           https://github.com/omisego/plasma-contracts/issues/173
     */
    constructor(uint256 _minExitPeriod, uint256 _initialImmuneVaults)
        public
    {
        _vaultQuarantine.quarantinePeriod = 2 * _minExitPeriod;
        _vaultQuarantine.immunitiesRemaining = _initialImmuneVaults;
    }

    /**
     * @notice interface to get the 'maintainer' address.
     * @dev see discussion here: https://git.io/Je8is
     */
    function getMaintainer() public view returns (address);

    /**
     * @notice A modifier to check that the call is from a non-quarantined vault
     */
    modifier onlyFromNonQuarantinedVault() {
        require(_vaultToId[msg.sender] > 0, "The call is not from a registered vault");
        require(!_vaultQuarantine.isQuarantined(msg.sender), "Vault is quarantined");
        _;
    }

    /**
     * @notice Register a vault within the PlasmaFramework. Only a maintainer can make the call.
     * @dev emits VaultRegistered event to notify clients
     * @param _vaultId The ID for the vault contract to register
     * @param _vaultAddress Address of the vault contract
     */
    function registerVault(uint256 _vaultId, address _vaultAddress) public onlyFrom(getMaintainer()) {
        require(_vaultId != 0, "Should not register with vault ID 0");
        require(Address.isContract(_vaultAddress), "Should not register with a non-contract address");
        require(_vaults[_vaultId] == address(0), "The vault ID is already registered");
        require(_vaultToId[_vaultAddress] == 0, "The vault contract is already registered");

        _vaults[_vaultId] = _vaultAddress;
        _vaultToId[_vaultAddress] = _vaultId;
        _vaultQuarantine.quarantine(_vaultAddress);

        emit VaultRegistered(_vaultId, _vaultAddress);
    }

    /**
     * @notice Public getter for retrieving vault address with vault ID
     */
    function vaults(uint256 _vaultId) public view returns (address) {
        return _vaults[_vaultId];
    }

    /**
     * @notice Public getter for retrieving vault ID with vault address
     */
    function vaultToId(address _vaultAddress) public view returns (uint256) {
        return _vaultToId[_vaultAddress];
    }
}

File 82 of 114 : ExitPriority.sol
pragma solidity 0.5.11;

import "../../utils/PosLib.sol";

library ExitPriority {

    using PosLib for PosLib.Position;

    /**
     * @dev Returns an exit priority for a given UTXO position and a unique ID.
     * The priority for Plasma M(ore)VP protocol is a combination of 'exitableAt' and 'txPos'.
     * Since 'exitableAt' only provides granularity of block, add 'txPos' to provide priority for a transaction.
     * @notice Detailed explanation on field lengths can be found at https://github.com/omisego/plasma-contracts/pull/303#discussion_r328850572
     * @param exitId Unique exit identifier
     * @return An exit priority
     *   Anatomy of returned value, most significant bits first
     *   42 bits  - timestamp in seconds (exitable_at); we can represent dates until year 141431
     *   54 bits  - blocknum * 10^5 + txindex; 54 bits represent all transactions for 85 years. Be aware that child chain block number jumps with the interval of CHILD_BLOCK_INTERVAL, which would be 1000 in production.
     *   160 bits - exit id
     */
    function computePriority(uint64 exitableAt, PosLib.Position memory txPos, uint160 exitId)
        internal
        pure
        returns (uint256)
    {
        return (uint256(exitableAt) << 214) | (txPos.getTxPositionForExitPriority() << 160) | uint256(exitId);
    }

    function parseExitableAt(uint256 priority) internal pure returns (uint64) {
        return uint64(priority >> 214);
    }

    function parseExitId(uint256 priority) internal pure returns (uint160) {
        // Exit ID uses only 160 least significant bits
        return uint160(priority);
    }
}

File 83 of 114 : PriorityQueue.sol
pragma solidity 0.5.11;

import "../../utils/OnlyFromAddress.sol";

import "openzeppelin-solidity/contracts/math/SafeMath.sol";

/**
 * @title PriorityQueue
 * @dev Min-heap priority queue implementation
 */
contract PriorityQueue is OnlyFromAddress {
    using SafeMath for uint256;

    struct Queue {
        uint256[] heapList;
        uint256 currentSize;
    }

    Queue public queue;
    address public framework;

    constructor() public {
        queue.heapList = [0];
        queue.currentSize = 0;

        // it is expected that this should be called by PlasmaFramework
        // and only PlasmaFramework contract can add things to the queue
        framework = msg.sender;
    }

    /**
     * @notice Gets num of elements in the queue
     */
    function currentSize() external view returns (uint256) {
        return queue.currentSize;
    }

    /**
     * @notice Gets all elements in the queue
     */
    function heapList() external view returns (uint256[] memory) {
        return queue.heapList;
    }

    /**
     * @notice Inserts an element into the queue by the framework
     * @dev Does not perform deduplication
     */
    function insert(uint256 _element) external onlyFrom(framework) {
        queue.heapList.push(_element);
        queue.currentSize = queue.currentSize.add(1);
        percUp(queue, queue.currentSize);
    }

    /**
     * @notice Deletes the smallest element from the queue by the framework
     * @dev Fails when queue is empty
     * @return The smallest element in the priority queue
     */
    function delMin() external onlyFrom(framework) returns (uint256) {
        require(queue.currentSize > 0, "Queue is empty");
        uint256 retVal = queue.heapList[1];
        queue.heapList[1] = queue.heapList[queue.currentSize];
        delete queue.heapList[queue.currentSize];
        queue.currentSize = queue.currentSize.sub(1);
        percDown(queue, 1);
        queue.heapList.length = queue.heapList.length.sub(1);
        return retVal;
    }

    /**
     * @notice Returns the smallest element from the queue
     * @dev Fails when queue is empty
     * @return The smallest element in the priority queue
     */
    function getMin() external view returns (uint256) {
        require(queue.currentSize > 0, "Queue is empty");
        return queue.heapList[1];
    }

    function percUp(Queue storage self, uint256 pointer) private {
        uint256 i = pointer;
        uint256 j = i;
        uint256 newVal = self.heapList[i];
        while (newVal < self.heapList[i.div(2)]) {
            self.heapList[i] = self.heapList[i.div(2)];
            i = i.div(2);
        }
        if (i != j) {
            self.heapList[i] = newVal;
        }
    }

    function percDown(Queue storage self, uint256 pointer) private {
        uint256 i = pointer;
        uint256 j = i;
        uint256 newVal = self.heapList[i];
        uint256 mc = minChild(self, i);
        while (mc <= self.currentSize && newVal > self.heapList[mc]) {
            self.heapList[i] = self.heapList[mc];
            i = mc;
            mc = minChild(self, i);
        }
        if (i != j) {
            self.heapList[i] = newVal;
        }
    }

    function minChild(Queue storage self, uint256 i) private view returns (uint256) {
        if (i.mul(2).add(1) > self.currentSize) {
            return i.mul(2);
        } else {
            if (self.heapList[i.mul(2)] < self.heapList[i.mul(2).add(1)]) {
                return i.mul(2);
            } else {
                return i.mul(2).add(1);
            }
        }
    }
}

File 84 of 114 : Quarantine.sol
pragma solidity 0.5.11;

/**
 * @notice Provides a way to quarantine (disable) contracts for a specified period of time
 * @dev The immunitiesRemaining member allows deployment to the platform with some
 * pre-verified contracts that don't get quarantined
 */
library Quarantine {
    struct Data {
        mapping(address => uint256) store;
        uint256 quarantinePeriod;
        uint256 immunitiesRemaining;
    }

    /**
     * @notice Checks whether a contract is quarantined
     */
    function isQuarantined(Data storage _self, address _contractAddress) internal view returns (bool) {
        return block.timestamp < _self.store[_contractAddress];
    }

    /**
     * @notice Places a contract into quarantine
     * @param _contractAddress The address of the contract
     */
    function quarantine(Data storage _self, address _contractAddress) internal {
        require(_contractAddress != address(0), "An empty address cannot be quarantined");
        require(_self.store[_contractAddress] == 0, "The contract is already quarantined");

        if (_self.immunitiesRemaining == 0) {
            _self.store[_contractAddress] = block.timestamp + _self.quarantinePeriod;
        } else {
            _self.immunitiesRemaining--;
        }
    }
}

File 85 of 114 : FungibleTokenOutputModel.sol
pragma solidity 0.5.11;
pragma experimental ABIEncoderV2;

import "./GenericTransaction.sol";
import "../utils/RLPReader.sol";

/**
 * @notice Data structure and its decode function for ouputs of fungible token transactions
 */
library FungibleTokenOutputModel {
    using RLPReader for RLPReader.RLPItem;

    struct Output {
        uint256 outputType;
        bytes20 outputGuard;
        address token;
        uint256 amount;
    }

    /**
     * @notice Given a GenericTransaction.Output, decodes the `data` field.
     * The data field is an RLP list that must satisfy the following conditions:
     *      - It must have 3 elements: [`outputGuard`, `token`, `amount`]
     *      - `outputGuard` is a 20 byte long array
     *      - `token` is a 20 byte long array
     *      - `amount` must be an integer value with no leading zeros. It may not be zero.
     * @param genericOutput A GenericTransaction.Output
     * @return A fully decoded FungibleTokenOutputModel.Output struct
     */
    function decodeOutput(GenericTransaction.Output memory genericOutput)
        internal
        pure
        returns (Output memory)
    {
        RLPReader.RLPItem[] memory dataList = genericOutput.data.toList();
        require(dataList.length == 3, "Output data must have 3 items");

        Output memory outputData = Output({
            outputType: genericOutput.outputType,
            outputGuard: bytes20(dataList[0].toAddress()),
            token: dataList[1].toAddress(),
            amount: dataList[2].toUint()
        });

        require(outputData.amount != 0, "Output amount must not be 0");
        require(outputData.outputGuard != bytes20(0), "Output outputGuard must not be 0");
        return outputData;
    }

    /**
    * @dev Decodes and returns the output at a specific index in the transaction
    */
    function getOutput(GenericTransaction.Transaction memory transaction, uint16 outputIndex)
        internal
        pure
        returns
        (Output memory)
    {
        require(outputIndex < transaction.outputs.length, "Output index out of bounds");
        return decodeOutput(transaction.outputs[outputIndex]);
    }
}

File 86 of 114 : GenericTransaction.sol
pragma solidity 0.5.11;

import "../utils/RLPReader.sol";

/**
 * @title GenericTransaction
 * @notice GenericTransaction is a generic transaction format that makes few assumptions about the
 * content of the transaction. A transaction must satisy the following requirements:
 * - It must be a list of 5 items: [txType, inputs, outputs, txData, metaData]
 * - `txType` must be a uint not equal to zero
 * - inputs must be a list of RLP items.
 * - outputs must be a list of `Output`s
 * - an `Output` is a list of 2 items: [outputType, data]
 * - `Output.outputType` must be a uint not equal to zero
 * - `Output.data` is an RLP item. It can be a list.
 * - no assumptions are made about `txData`. Note that `txData` can be a list.
 * - `metaData` must be 32 bytes long.
 */
library GenericTransaction {

    uint8 constant private TX_NUM_ITEMS = 5;

    using RLPReader for bytes;
    using RLPReader for RLPReader.RLPItem;

    struct Transaction {
        uint256 txType;
        RLPReader.RLPItem[] inputs;
        Output[] outputs;
        RLPReader.RLPItem txData;
        bytes32 metaData;
    }

    struct Output {
        uint256 outputType;
        RLPReader.RLPItem data;
    }

    /**
    * @dev Decodes an RLP encoded transaction into the generic format.
    */
    function decode(bytes memory transaction) internal pure returns (Transaction memory) {
        RLPReader.RLPItem[] memory rlpTx = transaction.toRlpItem().toList();
        require(rlpTx.length == TX_NUM_ITEMS, "Invalid encoding of transaction");
        uint256 txType = rlpTx[0].toUint();
        require(txType > 0, "Transaction type must not be 0");

        RLPReader.RLPItem[] memory outputList = rlpTx[2].toList();
        Output[] memory outputs = new Output[](outputList.length);
        for (uint i = 0; i < outputList.length; i++) {
            outputs[i] = decodeOutput(outputList[i]);
        }

        bytes32 metaData = rlpTx[4].toBytes32();

        return Transaction({
            txType: txType,
            inputs: rlpTx[1].toList(),
            outputs: outputs,
            txData: rlpTx[3],
            metaData: metaData
        });
    }

    /**
    * @dev Returns the output at a specific index in the transaction
    */
    function getOutput(Transaction memory transaction, uint16 outputIndex)
        internal
        pure
        returns (Output memory)
    {
        require(outputIndex < transaction.outputs.length, "Output index out of bounds");
        return transaction.outputs[outputIndex];
    }

    /**
    * @dev Decodes an RLPItem to an output
    */
    function decodeOutput(RLPReader.RLPItem memory encodedOutput)
        internal
        pure
        returns (Output memory)
    {
        RLPReader.RLPItem[] memory rlpList = encodedOutput.toList();
        require(rlpList.length == 2, "Output must have 2 items");

        Output memory output = Output({
            outputType: rlpList[0].toUint(),
            data: rlpList[1]
        });

        require(output.outputType != 0, "Output type must not be 0");
        return output;
    }
}

File 87 of 114 : PaymentTransactionModel.sol
pragma solidity 0.5.11;
pragma experimental ABIEncoderV2;

import "./FungibleTokenOutputModel.sol";
import "../utils/RLPReader.sol";

/**
 * @notice Data structure and its decode function for Payment transaction
 */
library PaymentTransactionModel {
    using RLPReader for bytes;
    using RLPReader for RLPReader.RLPItem;

    uint8 constant private _MAX_INPUT_NUM = 4;
    uint8 constant private _MAX_OUTPUT_NUM = 4;

    uint8 constant private ENCODED_LENGTH = 4;

    // solhint-disable-next-line func-name-mixedcase
    function MAX_INPUT_NUM() internal pure returns (uint8) {
        return _MAX_INPUT_NUM;
    }

    // solhint-disable-next-line func-name-mixedcase
    function MAX_OUTPUT_NUM() internal pure returns (uint8) {
        return _MAX_OUTPUT_NUM;
    }

    struct Transaction {
        uint256 txType;
        bytes32[] inputs;
        FungibleTokenOutputModel.Output[] outputs;
        uint256 txData;
        bytes32 metaData;
    }

    /**
     * @notice Decodes a encoded byte array into a PaymentTransaction
     * The following rules about the rlp-encoded transaction are enforced:
     *      - `txType` must be an integer value with no leading zeros
     *      - `inputs` is an list of 0 to 4 elements
     *      - Each `input` is a 32 byte long array
     *      - An `input` may not be all zeros
     *      - `outputs` is an list of 0 to 4 elements
     *      - Each `output` is a list of 2 elements: [`outputType`, `data`]
     *      - `output.outputType` must be an integer value with no leading zeros
     *      - See FungibleTokenOutputModel for deatils on `output.data` encoding.
     *      - An `output` may not be null; A null output is one whose amount is zero
     * @param _tx An RLP-encoded transaction
     * @return A decoded PaymentTransaction struct
     */
    function decode(bytes memory _tx) internal pure returns (PaymentTransactionModel.Transaction memory) {
        return fromGeneric(GenericTransaction.decode(_tx));
    }

    /**
     * @notice Converts a GenericTransaction to a PaymentTransaction
     * @param genericTx A GenericTransaction.Transaction struct
     * @return A PaymentTransaction.Transaction struct
     */
    function fromGeneric(GenericTransaction.Transaction memory genericTx)
        internal
        pure
        returns (PaymentTransactionModel.Transaction memory)
    {
        require(genericTx.inputs.length <= _MAX_INPUT_NUM, "Transaction inputs num exceeds limit");
        require(genericTx.outputs.length != 0, "Transaction cannot have 0 outputs");
        require(genericTx.outputs.length <= _MAX_OUTPUT_NUM, "Transaction outputs num exceeds limit");

        bytes32[] memory inputs = new bytes32[](genericTx.inputs.length);
        for (uint i = 0; i < genericTx.inputs.length; i++) {
            bytes32 input = genericTx.inputs[i].toBytes32();
            require(uint256(input) != 0, "Null input not allowed");
            inputs[i] = input;
        }

        FungibleTokenOutputModel.Output[] memory outputs = new FungibleTokenOutputModel.Output[](genericTx.outputs.length);
        for (uint i = 0; i < genericTx.outputs.length; i++) {
            outputs[i] = FungibleTokenOutputModel.decodeOutput(genericTx.outputs[i]);
        }

        // txData is unused, it must be 0
        require(genericTx.txData.toUint() == 0, "txData must be 0");

        return Transaction({
            txType: genericTx.txType,
            inputs: inputs,
            outputs: outputs,
            txData: 0,
            metaData: genericTx.metaData
        });
    }

    /**
     * @notice Retrieve the 'owner' from the output, assuming the
     *         'outputGuard' field directly holds the owner's address
     */
    function getOutputOwner(FungibleTokenOutputModel.Output memory output) internal pure returns (address payable) {
        return address(uint160(output.outputGuard));
    }

    /**
     * @notice Gets output at provided index
     *
     */
    function getOutput(Transaction memory transaction, uint16 outputIndex) internal pure returns (FungibleTokenOutputModel.Output memory) {
        require(outputIndex < transaction.outputs.length, "Output index out of bounds");
        return transaction.outputs[outputIndex];
    }
}

File 88 of 114 : PaymentEip712Lib.sol
pragma solidity 0.5.11;
pragma experimental ABIEncoderV2;

import "../PaymentTransactionModel.sol";
import "../../utils/PosLib.sol";

/**
 * @title PaymentEip712Lib
 * @notice Utilities for hashing structural data for PaymentTransaction (see EIP-712)
 *
 * @dev EIP712: https://github.com/ethereum/EIPs/blob/master/EIPS/eip-712.md
 *      We rely on the contract address to protect against replay attacks instead of using chain ID
 *      For more information, see https://github.com/omisego/plasma-contracts/issues/98#issuecomment-490792098
 */
library PaymentEip712Lib {
    using PosLib for PosLib.Position;

    bytes2 constant internal EIP191_PREFIX = "\x19\x01";

    bytes32 constant internal EIP712_DOMAIN_HASH = keccak256(
        "EIP712Domain(string name,string version,address verifyingContract,bytes32 salt)"
    );

    bytes32 constant internal TX_TYPE_HASH = keccak256(
        "Transaction(uint256 txType,Input input0,Input input1,Input input2,Input input3,Output output0,Output output1,Output output2,Output output3,uint256 txData,bytes32 metadata)Input(uint256 blknum,uint256 txindex,uint256 oindex)Output(uint256 outputType,bytes20 outputGuard,address currency,uint256 amount)"
    );

    bytes32 constant internal INPUT_TYPE_HASH = keccak256("Input(uint256 blknum,uint256 txindex,uint256 oindex)");
    bytes32 constant internal OUTPUT_TYPE_HASH = keccak256("Output(uint256 outputType,bytes20 outputGuard,address currency,uint256 amount)");
    bytes32 constant internal SALT = 0xfad5c7f626d80f9256ef01929f3beb96e058b8b4b0e3fe52d84f054c0e2a7a83;

    bytes32 constant internal EMPTY_INPUT_HASH = keccak256(abi.encode(INPUT_TYPE_HASH, 0, 0, 0));
    bytes32 constant internal EMPTY_OUTPUT_HASH = keccak256(abi.encode(OUTPUT_TYPE_HASH, 0, bytes20(0x0), address(0x0), 0));

    struct Constants {
        // solhint-disable-next-line var-name-mixedcase
        bytes32 DOMAIN_SEPARATOR;
    }

    function initConstants(address _verifyingContract) internal pure returns (Constants memory) {
        // solhint-disable-next-line var-name-mixedcase
        bytes32 DOMAIN_SEPARATOR = keccak256(abi.encode(
            EIP712_DOMAIN_HASH,
            keccak256("OMG Network"),
            keccak256("1"),
            address(_verifyingContract),
            SALT
        ));

        return Constants({
            DOMAIN_SEPARATOR: DOMAIN_SEPARATOR
        });
    }

    // The 'encode(domainSeparator, message)' of the EIP712 specification
    // See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-712.md#specification
    function hashTx(Constants memory _eip712, PaymentTransactionModel.Transaction memory _tx)
        internal
        pure
        returns (bytes32)
    {
        return keccak256(abi.encodePacked(
            EIP191_PREFIX,
            _eip712.DOMAIN_SEPARATOR,
            _hashTx(_tx)
        ));
    }

    // The 'hashStruct(message)' function of transaction
    // See https://github.com/ethereum/EIPs/blob/master/EIPS/eip-712.md#definition-of-hashstruct
    function _hashTx(PaymentTransactionModel.Transaction memory _tx)
        private
        pure
        returns (bytes32)
    {
        // Pad empty value to input array
        bytes32[] memory inputs = new bytes32[](PaymentTransactionModel.MAX_INPUT_NUM());
        for (uint i = 0; i < _tx.inputs.length; i++) {
            inputs[i] = _tx.inputs[i];
        }

        // Pad empty value to output array
        FungibleTokenOutputModel.Output[] memory outputs = new FungibleTokenOutputModel.Output[](PaymentTransactionModel.MAX_OUTPUT_NUM());
        for (uint i = 0; i < _tx.outputs.length; i++) {
            outputs[i] = _tx.outputs[i];
        }

        return keccak256(abi.encode(
            TX_TYPE_HASH,
            _tx.txType,
            _hashInput(inputs[0]),
            _hashInput(inputs[1]),
            _hashInput(inputs[2]),
            _hashInput(inputs[3]),
            _hashOutput(outputs[0]),
            _hashOutput(outputs[1]),
            _hashOutput(outputs[2]),
            _hashOutput(outputs[3]),
            _tx.txData,
            _tx.metaData
        ));
    }

    function _hashInput(bytes32 _input) private pure returns (bytes32) {
        uint256 inputUtxoValue = uint256(_input);
        if (inputUtxoValue == 0) {
            return EMPTY_INPUT_HASH;
        }

        PosLib.Position memory utxo = PosLib.decode(inputUtxoValue);
        return keccak256(abi.encode(
            INPUT_TYPE_HASH,
            utxo.blockNum,
            utxo.txIndex,
            uint256(utxo.outputIndex)
        ));
    }

    function _hashOutput(FungibleTokenOutputModel.Output memory _output)
        private
        pure
        returns (bytes32)
    {
        if (_output.amount == 0) {
            return EMPTY_OUTPUT_HASH;
        }

        return keccak256(abi.encode(
            OUTPUT_TYPE_HASH,
            _output.outputType,
            _output.outputGuard,
            _output.token,
            _output.amount
        ));
    }
}

File 89 of 114 : Bits.sol
pragma solidity 0.5.11;

/**
 * @title Bits
 * @dev Operations on individual bits of a word
 */
library Bits {
    /*
     * Storage
     */

    uint constant internal ONE = uint(1);

    /*
     * Internal functions
     */
    /**
     * @dev Sets the bit at the given '_index' in '_self' to '1'
     * @param _self Uint to modify
     * @param _index Index of the bit to set
     * @return The modified value
     */
    function setBit(uint _self, uint8 _index)
        internal
        pure
        returns (uint)
    {
        return _self | ONE << _index;
    }

    /**
     * @dev Sets the bit at the given '_index' in '_self' to '0'
     * @param _self Uint to modify
     * @param _index Index of the bit to set
     * @return The modified value
     */
    function clearBit(uint _self, uint8 _index)
        internal
        pure
        returns (uint)
    {
        return _self & ~(ONE << _index);
    }

    /**
     * @dev Returns the bit at the given '_index' in '_self'
     * @param _self Uint to check
     * @param _index Index of the bit to retrieve
     * @return The value of the bit at '_index'
     */
    function getBit(uint _self, uint8 _index)
        internal
        pure
        returns (uint8)
    {
        return uint8(_self >> _index & 1);
    }

    /**
     * @dev Checks if the bit at the given '_index' in '_self' is '1'
     * @param _self Uint to check
     * @param _index Index of the bit to check
     * @return True, if the bit is '0'; otherwise, False
     */
    function bitSet(uint _self, uint8 _index)
        internal
        pure
        returns (bool)
    {
        return getBit(_self, _index) == 1;
    }
}

File 90 of 114 : FailFastReentrancyGuard.sol
pragma solidity 0.5.11;

import "../framework/ExitGameController.sol";

/**
 * @notice Reentrancy guard that fails immediately when a reentrace occurs
 *         Works on multi-contracts level by activating and deactivating a reentrancy guard kept in plasma framework's state
 */
contract FailFastReentrancyGuard {

    /**
     * @dev Prevents reentrant calls by using a mutex.
     */
    modifier nonReentrant(ExitGameController exitGameController) {
        exitGameController.activateNonReentrant();
        _;
        exitGameController.deactivateNonReentrant();
    }
}

File 91 of 114 : Merkle.sol
pragma solidity 0.5.11;

/**
 * @title Merkle
 * @dev Library for working with Merkle trees
 */
library Merkle {
    byte private constant LEAF_SALT = 0x00;
    byte private constant NODE_SALT = 0x01;

    /**
     * @notice Checks that a leaf hash is contained in a root hash
     * @param leaf Leaf hash to verify
     * @param index Position of the leaf hash in the Merkle tree
     * @param rootHash Root of the Merkle tree
     * @param proof A Merkle proof demonstrating membership of the leaf hash
     * @return True, if the leaf hash is in the Merkle tree; otherwise, False
    */
    function checkMembership(bytes memory leaf, uint256 index, bytes32 rootHash, bytes memory proof)
        internal
        pure
        returns (bool)
    {
        require(proof.length != 0, "Merkle proof must not be empty");
        require(proof.length % 32 == 0, "Length of Merkle proof must be a multiple of 32");

        // see https://github.com/omisego/plasma-contracts/issues/546
        require(index < 2**(proof.length/32), "Index does not match the length of the proof");

        bytes32 proofElement;
        bytes32 computedHash = keccak256(abi.encodePacked(LEAF_SALT, leaf));
        uint256 j = index;
        // Note: We're skipping the first 32 bytes of `proof`, which holds the size of the dynamically sized `bytes`
        for (uint256 i = 32; i <= proof.length; i += 32) {
            // solhint-disable-next-line no-inline-assembly
            assembly {
                proofElement := mload(add(proof, i))
            }
            if (j % 2 == 0) {
                computedHash = keccak256(abi.encodePacked(NODE_SALT, computedHash, proofElement));
            } else {
                computedHash = keccak256(abi.encodePacked(NODE_SALT, proofElement, computedHash));
            }
            j = j / 2;
        }

        return computedHash == rootHash;
    }
}

File 92 of 114 : OnlyFromAddress.sol
pragma solidity 0.5.11;

contract OnlyFromAddress {

    modifier onlyFrom(address caller) {
        require(msg.sender == caller, "Caller address is unauthorized");
        _;
    }
}

File 93 of 114 : OnlyWithValue.sol
pragma solidity 0.5.11;

contract OnlyWithValue {
    modifier onlyWithValue(uint256 _value) {
        require(msg.value == _value, "Input value must match msg.value");
        _;
    }
}

File 94 of 114 : PosLib.sol
pragma solidity 0.5.11;

import "openzeppelin-solidity/contracts/math/SafeMath.sol";

/**
 * @dev UTXO position = (blknum * BLOCK_OFFSET + txIndex * TX_OFFSET + outputIndex).
 * TX position = (blknum * BLOCK_OFFSET + txIndex * TX_OFFSET)
 */
library PosLib {
    struct Position {
        uint64 blockNum;
        uint16 txIndex;
        uint16 outputIndex;
    }

    uint256 constant internal BLOCK_OFFSET = 1000000000;
    uint256 constant internal TX_OFFSET = 10000;
    
    uint256 constant internal MAX_OUTPUT_INDEX = TX_OFFSET - 1;
    // since we are using merkle tree of depth 16, max tx index size is 2^16 - 1
    uint256 constant internal MAX_TX_INDEX = 2 ** 16 - 1;
    // in ExitPriority, only 54 bits are reserved for both blockNum and txIndex
    uint256 constant internal MAX_BLOCK_NUM = ((2 ** 54 - 1) - MAX_TX_INDEX) / (BLOCK_OFFSET / TX_OFFSET);

    /**
     * @notice Returns transaction position which is an utxo position of zero index output
     * @param pos UTXO position of the output
     * @return Position of a transaction
     */
    function toStrictTxPos(Position memory pos)
        internal
        pure
        returns (Position memory)
    {
        return Position(pos.blockNum, pos.txIndex, 0);
    }

    /**
     * @notice Used for calculating exit priority
     * @param pos UTXO position for the output
     * @return Identifier of the transaction
     */
    function getTxPositionForExitPriority(Position memory pos)
        internal
        pure
        returns (uint256)
    {
        return encode(pos) / TX_OFFSET;
    }

    /**
     * @notice Encodes a position
     * @param pos Position
     * @return Position encoded as an integer
     */
    function encode(Position memory pos) internal pure returns (uint256) {
        require(pos.outputIndex <= MAX_OUTPUT_INDEX, "Invalid output index");
        require(pos.blockNum <= MAX_BLOCK_NUM, "Invalid block number");

        return pos.blockNum * BLOCK_OFFSET + pos.txIndex * TX_OFFSET + pos.outputIndex;
    }

    /**
     * @notice Decodes a position from an integer value
     * @param pos Encoded position
     * @return Position
     */
    function decode(uint256 pos) internal pure returns (Position memory) {
        uint256 blockNum = pos / BLOCK_OFFSET;
        uint256 txIndex = (pos % BLOCK_OFFSET) / TX_OFFSET;
        uint16 outputIndex = uint16(pos % TX_OFFSET);

        require(blockNum <= MAX_BLOCK_NUM, "blockNum exceeds max size allowed in PlasmaFramework");
        require(txIndex <= MAX_TX_INDEX, "txIndex exceeds the size of uint16");
        return Position(uint64(blockNum), uint16(txIndex), outputIndex);
    }
}

File 95 of 114 : RLPReader.sol
/**
 * @author Hamdi Allam [email protected]
 * @notice RLP decoding library forked from https://github.com/hamdiallam/Solidity-RLP
 * @dev Some changes that were made to the library are:
 *      - Added more test cases from https://github.com/ethereum/tests/tree/master/RLPTests
 *      - Created more custom invalid test cases
 *      - Added more checks to ensure the decoder reads within bounds of the input length
 *      - Moved utility functions necessary to run some of the tests to the RLPMock.sol
*/

pragma solidity 0.5.11;

library RLPReader {
    uint8 constant internal STRING_SHORT_START = 0x80;
    uint8 constant internal STRING_LONG_START  = 0xb8;
    uint8 constant internal LIST_SHORT_START   = 0xc0;
    uint8 constant internal LIST_LONG_START    = 0xf8;
    uint8 constant internal MAX_SHORT_LEN      = 55;
    uint8 constant internal WORD_SIZE = 32;

    struct RLPItem {
        uint256 len;
        uint256 memPtr;
    }

    /**
     * @notice Convert a dynamic bytes array into an RLPItem
     * @param item RLP encoded bytes
     * @return An RLPItem
     */
    function toRlpItem(bytes memory item) internal pure returns (RLPItem memory) {
        uint256 memPtr;

        // solhint-disable-next-line no-inline-assembly
        assembly {
            memPtr := add(item, 0x20)
        }

        return RLPItem(item.length, memPtr);
    }

    /**
    * @notice Convert a dynamic bytes array into a list of RLPItems
    * @param item RLP encoded list in bytes
    * @return A list of RLPItems
    */
    function toList(RLPItem memory item) internal pure returns (RLPItem[] memory) {
        require(isList(item), "Item is not a list");

        (uint256 listLength, uint256 offset) = decodeLengthAndOffset(item.memPtr);
        require(listLength == item.len, "Decoded RLP length for list is invalid");

        uint256 items = countEncodedItems(item);
        RLPItem[] memory result = new RLPItem[](items);

        uint256 dataMemPtr = item.memPtr + offset;
        uint256 dataLen;
        for (uint256 i = 0; i < items; i++) {
            (dataLen, ) = decodeLengthAndOffset(dataMemPtr);
            result[i] = RLPItem(dataLen, dataMemPtr);
            dataMemPtr = dataMemPtr + dataLen;
        }

        return result;
    }

    /**
    * @notice Check whether the RLPItem is either a list
    * @param item RLP encoded list in bytes
    * @return A boolean whether the RLPItem is a list
    */
    function isList(RLPItem memory item) internal pure returns (bool) {
        if (item.len == 0) return false;

        uint8 byte0;
        uint256 memPtr = item.memPtr;
        // solhint-disable-next-line no-inline-assembly
        assembly {
            byte0 := byte(0, mload(memPtr))
        }

        if (byte0 < LIST_SHORT_START)
            return false;
        return true;
    }

    /**
     * @notice Create an address from a RLPItem
     * @dev Function is not a standard RLP decoding function and it used to decode to the Solidity native address type
     * @param item RLPItem
     */
    function toAddress(RLPItem memory item) internal pure returns (address) {
        require(item.len == 21, "Item length must be 21");
        require(!isList(item), "Item must not be a list");

        (uint256 itemLen, uint256 offset) = decodeLengthAndOffset(item.memPtr);
        require(itemLen == 21, "Decoded item length must be 21");

        uint256 dataMemPtr = item.memPtr + offset;
        uint256 result;
        // solhint-disable-next-line no-inline-assembly
        assembly {
            result := mload(dataMemPtr)
            // right shift by 12 to make bytes20
            result := div(result, exp(256, 12))
        }

        return address(result);
    }

    /**
     * @notice Create a uint256 from a RLPItem. Leading zeros are invalid.
     * @dev Function is not a standard RLP decoding function and it used to decode to the Solidity native uint256 type
     * @param item RLPItem
     */
    function toUint(RLPItem memory item) internal pure returns (uint256) {
        require(item.len > 0 && item.len <= 33, "Item length must be between 1 and 33 bytes");
        require(!isList(item), "Item must not be a list");
        (uint256 itemLen, uint256 offset) = decodeLengthAndOffset(item.memPtr);
        require(itemLen == item.len, "Decoded item length must be equal to the input data length");

        uint256 dataLen = itemLen - offset;

        uint result;
        uint dataByte0;
        uint dataMemPtr = item.memPtr + offset;
        // solhint-disable-next-line no-inline-assembly
        assembly {
            result := mload(dataMemPtr)
            dataByte0 := byte(0, result)
            // shift to the correct location if necessary
            if lt(dataLen, WORD_SIZE) {
                result := div(result, exp(256, sub(WORD_SIZE, dataLen)))
            }
        }
        // Special case: scalar 0 should be encoded as 0x80 and _not_ as 0x00
        require(!(dataByte0 == 0 && offset == 0), "Scalar 0 should be encoded as 0x80");

        // Disallow leading zeros
        require(!(dataByte0 == 0 && dataLen > 1), "Leading zeros are invalid");

        return result;
    }

    /**
     * @notice Create a bytes32 from a RLPItem
    * @dev Function is not a standard RLP decoding function and it used to decode to the Solidity native bytes32 type
     * @param item RLPItem
     */
    function toBytes32(RLPItem memory item) internal pure returns (bytes32) {
        // 1 byte for the length prefix
        require(item.len == 33, "Item length must be 33");
        require(!isList(item), "Item must not be a list");

        (uint256 itemLen, uint256 offset) = decodeLengthAndOffset(item.memPtr);
        require(itemLen == 33, "Decoded item length must be 33");

        uint256 dataMemPtr = item.memPtr + offset;
        bytes32 result;
        // solhint-disable-next-line no-inline-assembly
        assembly {
            result := mload(dataMemPtr)
        }

        return result;
    }

    /**
    * @notice Counts the number of payload items inside an RLP encoded list
    * @param item RLPItem
    * @return The number of items in a inside an RLP encoded list
    */
    function countEncodedItems(RLPItem memory item) private pure returns (uint256) {
        uint256 count = 0;
        (, uint256 offset) = decodeLengthAndOffset(item.memPtr);
        uint256 currPtr = item.memPtr + offset;
        uint256 endPtr = item.memPtr + item.len;
        while (currPtr < endPtr) {
            (uint256 currLen, ) = decodeLengthAndOffset(currPtr);
            currPtr = currPtr + currLen;
            require(currPtr <= endPtr, "Invalid decoded length of RLP item found during counting items in a list");
            count++;
        }

        return count;
    }

    /**
     * @notice Decodes the RLPItem's length and offset.
     * @dev This function is dangerous. Ensure that the returned length is within bounds that memPtr points to.
     * @param memPtr Pointer to the dynamic bytes array in memory
     * @return The length of the RLPItem (including the length field) and the offset of the payload
     */
    function decodeLengthAndOffset(uint256 memPtr) internal pure returns (uint256, uint256) {
        uint256 decodedLength;
        uint256 offset;
        uint256 byte0;

        // solhint-disable-next-line no-inline-assembly
        assembly {
            byte0 := byte(0, mload(memPtr))
        }

        if (byte0 < STRING_SHORT_START) {
            // Item is a single byte
            decodedLength = 1;
            offset = 0;
        } else if (STRING_SHORT_START <= byte0 && byte0 < STRING_LONG_START) {
            // The range of the first byte is between 0x80 and 0xb7 therefore it is a short string
            // decodedLength is between 1 and 56 bytes
            decodedLength = (byte0 - STRING_SHORT_START) + 1;
            if (decodedLength == 2){
                uint256 byte1;
                // solhint-disable-next-line no-inline-assembly
                assembly {
                    byte1 := byte(0, mload(add(memPtr, 1)))
                }
                // A single byte below 0x80 must be encoded as itself.
                require(byte1 >= STRING_SHORT_START, "Invalid short string encoding");
            }
            offset = 1;
        } else if (STRING_LONG_START <= byte0 && byte0 < LIST_SHORT_START) {
            // The range of the first byte is between 0xb8 and 0xbf therefore it is a long string
            // lengthLen is between 1 and 8 bytes
            // dataLen is greater than 55 bytes
            uint256 dataLen;
            uint256 byte1;
            uint256 lengthLen;

            // solhint-disable-next-line no-inline-assembly
            assembly {
                lengthLen := sub(byte0, 0xb7) // The length of the length of the payload is encoded in the first byte.
                memPtr := add(memPtr, 1) // skip over the first byte

                // right shift to the correct position
                dataLen := div(mload(memPtr), exp(256, sub(WORD_SIZE, lengthLen)))
                decodedLength := add(dataLen, add(lengthLen, 1))
                byte1 := byte(0, mload(memPtr))
            }

            // Check that the length has no leading zeros
            require(byte1 != 0, "Invalid leading zeros in length of the length for a long string");
            // Check that the value of length > MAX_SHORT_LEN
            require(dataLen > MAX_SHORT_LEN, "Invalid length for a long string");
            // Calculate the offset
            offset = lengthLen + 1;
        } else if (LIST_SHORT_START <= byte0 && byte0 < LIST_LONG_START) {
            // The range of the first byte is between 0xc0 and 0xf7 therefore it is a short list
            // decodedLength is between 1 and 56 bytes
            decodedLength = (byte0 - LIST_SHORT_START) + 1;
            offset = 1;
        } else {
            // The range of the first byte is between 0xf8 and 0xff therefore it is a long list
            // lengthLen is between 1 and 8 bytes
            // dataLen is greater than 55 bytes
            uint256 dataLen;
            uint256 byte1;
            uint256 lengthLen;

            // solhint-disable-next-line no-inline-assembly
            assembly {
                lengthLen := sub(byte0, 0xf7) // The length of the length of the payload is encoded in the first byte.
                memPtr := add(memPtr, 1) // skip over the first byte

                // right shift to the correct position
                dataLen := div(mload(memPtr), exp(256, sub(WORD_SIZE, lengthLen)))
                decodedLength := add(dataLen, add(lengthLen, 1))
                byte1 := byte(0, mload(memPtr))
            }

            // Check that the length has no leading zeros
            require(byte1 != 0, "Invalid leading zeros in length of the length for a long list");
            // Check that the value of length > MAX_SHORT_LEN
            require(dataLen > MAX_SHORT_LEN, "Invalid length for a long list");
            // Calculate the offset
            offset = lengthLen + 1;
        }

        return (decodedLength, offset);
    }
}

File 96 of 114 : SafeEthTransfer.sol
pragma solidity 0.5.11;

/**
* @notice Utility library to safely transfer ETH
* @dev transfer is no longer the recommended way to do ETH transfer.
*      see issue: https://github.com/omisego/plasma-contracts/issues/312
*
*      This library limits the amount of gas used for external calls with value to protect against potential DOS/griefing attacks that try to use up all the gas.
*      see issue: https://github.com/omisego/plasma-contracts/issues/385
*/
library SafeEthTransfer {
    /**
     * @notice Try to transfer eth without using more gas than `gasStipend`.
     *         Reverts if it fails to transfer the ETH.
     * @param receiver the address to receive ETH
     * @param amount the amount of ETH (in wei) to transfer
     * @param gasStipend the maximum amount of gas to be used for the call
     */
    function transferRevertOnError(address payable receiver, uint256 amount, uint256 gasStipend)
        internal
    {
        bool success = transferReturnResult(receiver, amount, gasStipend);
        require(success, "SafeEthTransfer: failed to transfer ETH");
    }

    /**
     * @notice Transfer ETH without using more gas than the `gasStipend`.
     *         Returns whether the transfer call is successful or not.
     * @dev EVM will revert with "out of gas" error if there is not enough gas left for the call
     * @param receiver the address to receive ETH
     * @param amount the amount of ETH (in wei) to transfer
     * @param gasStipend the maximum amount of gas to be used during the transfer call
     * @return a flag showing the call is successful or not
     */
    function transferReturnResult(address payable receiver, uint256 amount, uint256 gasStipend)
        internal
        returns (bool)
    {
        (bool success, ) = receiver.call.gas(gasStipend).value(amount)("");
        return success;
    }
}

File 97 of 114 : Erc20Vault.sol
pragma solidity 0.5.11;

import "./Vault.sol";
import "./verifiers/IErc20DepositVerifier.sol";
import "../framework/PlasmaFramework.sol";

import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol";
import "openzeppelin-solidity/contracts/token/ERC20/SafeERC20.sol";

contract Erc20Vault is Vault {
    using SafeERC20 for IERC20;

    event Erc20Withdrawn(
        address indexed receiver,
        address indexed token,
        uint256 amount
    );

    event DepositCreated(
        address indexed depositor,
        uint256 indexed blknum,
        address indexed token,
        uint256 amount
    );

    constructor(PlasmaFramework _framework) public Vault(_framework) {}

    /**
     * @notice Deposits approved amount of ERC20 token(s) into the contract
     * Once the deposit is recognized, the owner (depositor) can transact on the OmiseGO Network
     * The approve function of the ERC20 token contract must be called before calling this function
     * for at least the amount that is deposited into the contract
     * @param depositTx RLP-encoded transaction to act as the deposit
     */
    function deposit(bytes calldata depositTx) external {
        address depositVerifier = super.getEffectiveDepositVerifier();
        require(depositVerifier != address(0), "Deposit verifier has not been set");

        (address depositor, address token, uint256 amount) = IErc20DepositVerifier(depositVerifier)
            .verify(depositTx, msg.sender, address(this));

        IERC20(token).safeTransferFrom(depositor, address(this), amount);

        uint256 blknum = super.submitDepositBlock(depositTx);

        emit DepositCreated(msg.sender, blknum, token, amount);
    }

    /**
    * @notice Withdraw ERC20 tokens that have successfully exited from the OmiseGO Network
    * @param receiver Address of the recipient
    * @param token Address of ERC20 token contract
    * @param amount Amount to transfer
    */
    function withdraw(address payable receiver, address token, uint256 amount) external onlyFromNonQuarantinedExitGame {
        IERC20(token).safeTransfer(receiver, amount);
        emit Erc20Withdrawn(receiver, token, amount);
    }
}

File 98 of 114 : EthVault.sol
pragma solidity 0.5.11;

import "./Vault.sol";
import "./verifiers/IEthDepositVerifier.sol";
import "../framework/PlasmaFramework.sol";
import "../utils/SafeEthTransfer.sol";

contract EthVault is Vault {
    event EthWithdrawn(
        address indexed receiver,
        uint256 amount
    );

    event WithdrawFailed(
        address indexed receiver,
        uint256 amount
    );

    event DepositCreated(
        address indexed depositor,
        uint256 indexed blknum,
        address indexed token,
        uint256 amount
    );

    uint256 public safeGasStipend;

    constructor(PlasmaFramework _framework, uint256 _safeGasStipend) public Vault(_framework) {
        safeGasStipend = _safeGasStipend;
    }

    /**
     * @notice Allows a user to deposit ETH into the contract
     * Once the deposit is recognized, the owner may transact on the OmiseGO Network
     * @param _depositTx RLP-encoded transaction to act as the deposit
     */
    function deposit(bytes calldata _depositTx) external payable {
        address depositVerifier = super.getEffectiveDepositVerifier();
        require(depositVerifier != address(0), "Deposit verifier has not been set");

        IEthDepositVerifier(depositVerifier).verify(_depositTx, msg.value, msg.sender);
        uint256 blknum = super.submitDepositBlock(_depositTx);

        emit DepositCreated(msg.sender, blknum, address(0), msg.value);
    }

    /**
    * @notice Withdraw ETH that has successfully exited from the OmiseGO Network
    * @dev We do not want to block exit queue if a transfer is unsuccessful, so we don't revert on transfer error.
    *      However, if there is not enough gas left for the safeGasStipend, then the EVM _will_ revert with an 'out of gas' error.
    *      If this happens, the user should retry with higher gas.
    * @param receiver Address of the recipient
    * @param amount The amount of ETH to transfer
    */
    function withdraw(address payable receiver, uint256 amount) external onlyFromNonQuarantinedExitGame {
        bool success = SafeEthTransfer.transferReturnResult(receiver, amount, safeGasStipend);
        if (success) {
            emit EthWithdrawn(receiver, amount);
        } else {
            emit WithdrawFailed(receiver, amount);
        }
    }
}

File 99 of 114 : Vault.sol
pragma solidity 0.5.11;

import "../framework/PlasmaFramework.sol";
import "../utils/OnlyFromAddress.sol";

/**
 * @notice Base contract for vault implementation
 * @dev This is the functionality to swap "deposit verifier"
 *      Setting a new deposit verifier allows an upgrade to a new deposit tx type without upgrading the vault
 */
contract Vault is OnlyFromAddress {

    byte private constant LEAF_SALT = 0x00;
    byte private constant NODE_SALT = 0x01;

    event SetDepositVerifierCalled(address nextDepositVerifier);
    PlasmaFramework internal framework;
    bytes32[16] internal zeroHashes; // Pre-computes zero hashes to be used for building merkle tree for deposit block

    /**
     * @notice Stores deposit verifier contract addresses; first contract address is effective until the
     *  `newDepositVerifierMaturityTimestamp`; second contract address becomes effective after that timestamp
    */
    address[2] public depositVerifiers;
    uint256 public newDepositVerifierMaturityTimestamp = 2 ** 255; // point far in the future

    constructor(PlasmaFramework _framework) public {
        framework = _framework;
        zeroHashes = getZeroHashes();
    }

    /**
     * @dev Pre-computes zero hashes to be used for building Merkle tree for deposit block
     */
    function getZeroHashes() private pure returns (bytes32[16] memory) {
        bytes32[16] memory hashes;
        bytes32 zeroHash = keccak256(abi.encodePacked(LEAF_SALT, uint256(0)));
        for (uint i = 0; i < 16; i++) {
            hashes[i] = zeroHash;
            zeroHash = keccak256(abi.encodePacked(NODE_SALT, zeroHash, zeroHash));
        }
        return hashes;
    }

    /**
     * @notice Checks whether the call originates from a non-quarantined exit game contract
    */
    modifier onlyFromNonQuarantinedExitGame() {
        require(
            ExitGameRegistry(framework).isExitGameSafeToUse(msg.sender),
            "Called from a non-registered or quarantined exit game contract"
        );
        _;
    }

    /**
     * @notice Sets the deposit verifier contract, which may be called only by the operator
     * @dev emit SetDepositVerifierCalled
     * @dev When one contract is already set, the next one is effective after 2 * MIN_EXIT_PERIOD.
     *      This is to protect deposit transactions already in mempool,
     *      and also make sure user only needs to SE within first week when invalid vault is registered.
     *
     *      see: https://github.com/omisego/plasma-contracts/issues/412
     *           https://github.com/omisego/plasma-contracts/issues/173
     *
     * @param _verifier Address of the verifier contract
     */
    function setDepositVerifier(address _verifier) public onlyFrom(framework.getMaintainer()) {
        require(_verifier != address(0), "Cannot set an empty address as deposit verifier");

        if (depositVerifiers[0] != address(0)) {
            depositVerifiers[0] = getEffectiveDepositVerifier();
            depositVerifiers[1] = _verifier;
            newDepositVerifierMaturityTimestamp = now + 2 * framework.minExitPeriod();
        } else {
            depositVerifiers[0] = _verifier;
        }

        emit SetDepositVerifierCalled(_verifier);
    }

    /**
     * @notice Retrieves the currently effective deposit verifier contract address
     * @return Contract address of the deposit verifier
     */
    function getEffectiveDepositVerifier() public view returns (address) {
        if (now < newDepositVerifierMaturityTimestamp) {
            return depositVerifiers[0];
        } else {
            return depositVerifiers[1];
        }
    }

    /**
     * @notice Generate and submit a deposit block root to the PlasmaFramework
     * @dev Designed to be called by the contract that inherits Vault
     */
    function submitDepositBlock(bytes memory depositTx) internal returns (uint256) {
        bytes32 root = getDepositBlockRoot(depositTx);

        uint256 depositBlkNum = framework.submitDepositBlock(root);
        return depositBlkNum;
    }

    function getDepositBlockRoot(bytes memory depositTx) private view returns (bytes32) {
        bytes32 root = keccak256(abi.encodePacked(LEAF_SALT, depositTx));
        for (uint i = 0; i < 16; i++) {
            root = keccak256(abi.encodePacked(NODE_SALT, root, zeroHashes[i]));
        }
        return root;
    }
}

File 100 of 114 : Erc20DepositVerifier.sol
pragma solidity 0.5.11;

import "openzeppelin-solidity/contracts/token/ERC20/IERC20.sol";

import "./IErc20DepositVerifier.sol";
import {PaymentTransactionModel as DepositTx} from "../../transactions/PaymentTransactionModel.sol";

/**
 * @notice Implementation of Erc20 deposit verifier using payment transaction as the deposit tx
 */
contract Erc20DepositVerifier is IErc20DepositVerifier {
    uint256 public depositTxType;
    uint256 public supportedOutputType;

    constructor(uint256 txType, uint256 outputType) public {
        depositTxType = txType;
        supportedOutputType = outputType;
    }

    /**
     * @notice Overrides the function of IErc20DepositVerifier and implements the verification logic
     *         for payment transaction
     * @dev Vault address must be approved to transfer from the sender address before doing the deposit
     * @return Verified (owner, token, amount) of the deposit ERC20 token data
     */
    function verify(bytes calldata depositTx, address sender, address vault)
        external
        view
        returns (
            address owner,
            address token,
            uint256 amount
        )
    {
        DepositTx.Transaction memory decodedTx = DepositTx.decode(depositTx);

        require(decodedTx.txType == depositTxType, "Invalid transaction type");

        require(decodedTx.inputs.length == 0, "Deposit must have no inputs");

        require(decodedTx.outputs.length == 1, "Deposit must have exactly one output");
        require(decodedTx.outputs[0].token != address(0), "Invalid output currency (ETH)");
        require(decodedTx.outputs[0].outputType == supportedOutputType, "Invalid output type");

        address depositorsAddress = DepositTx.getOutputOwner(decodedTx.outputs[0]);
        require(depositorsAddress == sender, "Depositor's address must match sender's address");

        IERC20 erc20 = IERC20(decodedTx.outputs[0].token);
        require(erc20.allowance(depositorsAddress, vault) >= decodedTx.outputs[0].amount, "Tokens have not been approved");

        return (depositorsAddress, decodedTx.outputs[0].token, decodedTx.outputs[0].amount);
    }
}

File 101 of 114 : EthDepositVerifier.sol
pragma solidity 0.5.11;

import "./IEthDepositVerifier.sol";
import {PaymentTransactionModel as DepositTx} from "../../transactions/PaymentTransactionModel.sol";

/**
 * @notice Implementation of ETH deposit verifier using payment transaction as the deposit transaction
 */
contract EthDepositVerifier is IEthDepositVerifier {
    uint256 public depositTxType;
    uint256 public supportedOutputType;

    constructor(uint256 txType, uint256 outputType) public {
        depositTxType = txType;
        supportedOutputType = outputType;
    }

    /**
     * @notice Overrides the function of IEthDepositVerifier and implements the verification logic
     *         for payment transaction
     */
    function verify(bytes calldata depositTx, uint256 amount, address sender) external view {
        DepositTx.Transaction memory decodedTx = DepositTx.decode(depositTx);

        require(decodedTx.txType == depositTxType, "Invalid transaction type");

        require(decodedTx.inputs.length == 0, "Deposit must have no inputs");

        require(decodedTx.outputs.length == 1, "Deposit must have exactly one output");
        require(decodedTx.outputs[0].amount == amount, "Deposited value must match sent amount");
        require(decodedTx.outputs[0].token == address(0), "Output requires correct currency (ETH)");
        require(decodedTx.outputs[0].outputType == supportedOutputType, "Invalid output type");

        address depositorsAddress = DepositTx.getOutputOwner(decodedTx.outputs[0]);
        require(depositorsAddress == sender, "Depositor's address must match sender's address");
    }
}

File 102 of 114 : IErc20DepositVerifier.sol
pragma solidity 0.5.11;

interface IErc20DepositVerifier {
    /**
     * @notice Verifies a deposit transaction
     * @param depositTx The deposit transaction
     * @param sender The owner of the deposit transaction
     * @param vault The address of the Erc20Vault contract
     * @return Verified (owner, token, amount) of the deposit ERC20 token data
     */
    function verify(bytes calldata depositTx, address sender, address vault)
        external
        view
        returns (address owner, address token, uint256 amount);
}

File 103 of 114 : IEthDepositVerifier.sol
pragma solidity 0.5.11;

interface IEthDepositVerifier {
    /**
     * @notice Verifies a deposit transaction
     * @param depositTx The deposit transaction
     * @param amount The amount deposited
     * @param sender The owner of the deposit transaction
     */
    function verify(bytes calldata depositTx, uint256 amount, address sender) external view;
}

File 104 of 114 : ERC20Mintable.sol
pragma solidity ^0.5.0;

import "./ERC20.sol";
import "../../access/roles/MinterRole.sol";

/**
 * @dev Extension of `ERC20` that adds a set of accounts with the `MinterRole`,
 * which have permission to mint (create) new tokens as they see fit.
 *
 * At construction, the deployer of the contract is the only minter.
 */
contract ERC20Mintable is ERC20, MinterRole {
    /**
     * @dev See `ERC20._mint`.
     *
     * Requirements:
     *
     * - the caller must have the `MinterRole`.
     */
    function mint(address account, uint256 amount) public onlyMinter returns (bool) {
        _mint(account, amount);
        return true;
    }
}

File 105 of 114 : SafeMath.sol
pragma solidity ^0.5.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, 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");
        uint256 c = a - b;

        return c;
    }

    /**
     * @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) {
        // Gas optimization: this is cheaper than requiring 'a' not being zero, but the
        // benefit is lost if 'b' is also tested.
        // See: https://github.com/OpenZeppelin/openzeppelin-solidity/pull/522
        if (a == 0) {
            return 0;
        }

        uint256 c = a * b;
        require(c / a == b, "SafeMath: multiplication overflow");

        return c;
    }

    /**
     * @dev Returns the integer division of two unsigned integers. Reverts 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) {
        // Solidity only automatically asserts when dividing by 0
        require(b > 0, "SafeMath: division by zero");
        uint256 c = a / b;
        // assert(a == b * c + a % b); // There is no case in which this doesn't hold

        return c;
    }

    /**
     * @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
     * Reverts 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;
    }
}

File 106 of 114 : ECDSA.sol
pragma solidity ^0.5.0;

/**
 * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.
 *
 * These functions can be used to verify that a message was signed by the holder
 * of the private keys of a given address.
 */
library ECDSA {
    /**
     * @dev Returns the address that signed a hashed message (`hash`) with
     * `signature`. This address can then be used for verification purposes.
     *
     * The `ecrecover` EVM opcode allows for malleable (non-unique) signatures:
     * this function rejects them by requiring the `s` value to be in the lower
     * half order, and the `v` value to be either 27 or 28.
     *
     * (.note) This call _does not revert_ if the signature is invalid, or
     * if the signer is otherwise unable to be retrieved. In those scenarios,
     * the zero address is returned.
     *
     * (.warning) `hash` _must_ be the result of a hash operation for the
     * verification to be secure: it is possible to craft signatures that
     * recover to arbitrary addresses for non-hashed data. A safe way to ensure
     * this is by receiving a hash of the original message (which may otherwise)
     * be too long), and then calling `toEthSignedMessageHash` on it.
     */
    function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
        // Check the signature length
        if (signature.length != 65) {
            return (address(0));
        }

        // Divide the signature in r, s and v variables
        bytes32 r;
        bytes32 s;
        uint8 v;

        // ecrecover takes the signature parameters, and the only way to get them
        // currently is to use assembly.
        // solhint-disable-next-line no-inline-assembly
        assembly {
            r := mload(add(signature, 0x20))
            s := mload(add(signature, 0x40))
            v := byte(0, mload(add(signature, 0x60)))
        }

        // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature
        // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines
        // the valid range for s in (281): 0 < s < secp256k1n ÷ 2 + 1, and for v in (282): v ∈ {27, 28}. Most
        // signatures from current libraries generate a unique signature with an s-value in the lower half order.
        //
        // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value
        // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or
        // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept
        // these malleable signatures as well.
        if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
            return address(0);
        }

        if (v != 27 && v != 28) {
            return address(0);
        }

        // If the signature is valid (and not malleable), return the signer address
        return ecrecover(hash, v, r, s);
    }

    /**
     * @dev Returns an Ethereum Signed Message, created from a `hash`. This
     * replicates the behavior of the
     * [`eth_sign`](https://github.com/ethereum/wiki/wiki/JSON-RPC#eth_sign)
     * JSON-RPC method.
     *
     * See `recover`.
     */
    function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32) {
        // 32 is the length in bytes of hash,
        // enforced by the type signature above
        return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n32", hash));
    }
}

File 107 of 114 : Ownable.sol
pragma solidity ^0.5.0;

/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be aplied to your functions to restrict their use to
 * the owner.
 */
contract Ownable {
    address private _owner;

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    constructor () internal {
        _owner = msg.sender;
        emit OwnershipTransferred(address(0), _owner);
    }

    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        require(isOwner(), "Ownable: caller is not the owner");
        _;
    }

    /**
     * @dev Returns true if the caller is the current owner.
     */
    function isOwner() public view returns (bool) {
        return msg.sender == _owner;
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions anymore. Can only be called by the current owner.
     *
     * > Note: Renouncing ownership will leave the contract without an owner,
     * thereby removing any functionality that is only available to the owner.
     */
    function renounceOwnership() public onlyOwner {
        emit OwnershipTransferred(_owner, address(0));
        _owner = address(0);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public onlyOwner {
        _transferOwnership(newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     */
    function _transferOwnership(address newOwner) internal {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        emit OwnershipTransferred(_owner, newOwner);
        _owner = newOwner;
    }
}

File 108 of 114 : Address.sol
pragma solidity ^0.5.0;

/**
 * @dev Collection of functions related to the address type,
 */
library Address {
    /**
     * @dev Returns true if `account` is a contract.
     *
     * This test is non-exhaustive, and there may be false-negatives: during the
     * execution of a contract's constructor, its address will be reported as
     * not containing a contract.
     *
     * > It is unsafe to assume that an address for which this function returns
     * false is an externally-owned account (EOA) and not a contract.
     */
    function isContract(address account) internal view returns (bool) {
        // This method relies in 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;
    }
}

File 109 of 114 : Math.sol
pragma solidity ^0.5.0;

/**
 * @dev Standard math utilities missing in the Solidity language.
 */
library Math {
    /**
     * @dev Returns the largest of two numbers.
     */
    function max(uint256 a, uint256 b) internal pure returns (uint256) {
        return a >= b ? a : b;
    }

    /**
     * @dev Returns the smallest of two numbers.
     */
    function min(uint256 a, uint256 b) internal pure returns (uint256) {
        return a < b ? a : b;
    }

    /**
     * @dev Returns the average of two numbers. The result is rounded towards
     * zero.
     */
    function average(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b) / 2 can overflow, so we distribute
        return (a / 2) + (b / 2) + ((a % 2 + b % 2) / 2);
    }
}

File 110 of 114 : IERC20.sol
pragma solidity ^0.5.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP. Does not include
 * the optional functions; to access them see `ERC20Detailed`.
 */
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.
     *
     * > Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an `Approval` event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

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

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

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

File 111 of 114 : SafeERC20.sol
pragma solidity ^0.5.0;

import "./IERC20.sol";
import "../../math/SafeMath.sol";
import "../../utils/Address.sol";

/**
 * @title SafeERC20
 * @dev Wrappers around ERC20 operations that throw on failure (when the token
 * contract returns false). Tokens that return no value (and instead revert or
 * throw on failure) are also supported, non-reverting calls are assumed to be
 * successful.
 * To use this library you can add a `using SafeERC20 for ERC20;` statement to your contract,
 * which allows you to call the safe operations as `token.safeTransfer(...)`, etc.
 */
library SafeERC20 {
    using SafeMath for uint256;
    using Address for address;

    function safeTransfer(IERC20 token, address to, uint256 value) internal {
        callOptionalReturn(token, abi.encodeWithSelector(token.transfer.selector, to, value));
    }

    function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal {
        callOptionalReturn(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
    }

    function safeApprove(IERC20 token, address spender, uint256 value) internal {
        // safeApprove should only be called when setting an initial allowance,
        // or when resetting it to zero. To increase and decrease it, use
        // 'safeIncreaseAllowance' and 'safeDecreaseAllowance'
        // solhint-disable-next-line max-line-length
        require((value == 0) || (token.allowance(address(this), spender) == 0),
            "SafeERC20: approve from non-zero to non-zero allowance"
        );
        callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, value));
    }

    function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal {
        uint256 newAllowance = token.allowance(address(this), spender).add(value);
        callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
    }

    function safeDecreaseAllowance(IERC20 token, address spender, uint256 value) internal {
        uint256 newAllowance = token.allowance(address(this), spender).sub(value);
        callOptionalReturn(token, abi.encodeWithSelector(token.approve.selector, spender, newAllowance));
    }

    /**
     * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement
     * on the return value: the return value is optional (but if data is returned, it must not be false).
     * @param token The token targeted by the call.
     * @param data The call data (encoded using abi.encode or one of its variants).
     */
    function callOptionalReturn(IERC20 token, bytes memory data) private {
        // We need to perform a low level call here, to bypass Solidity's return data size checking mechanism, since
        // we're implementing it ourselves.

        // A Solidity high level call has three parts:
        //  1. The target address is checked to verify it contains contract code
        //  2. The call itself is made, and success asserted
        //  3. The return value is decoded, which in turn checks the size of the returned data.
        // solhint-disable-next-line max-line-length
        require(address(token).isContract(), "SafeERC20: call to non-contract");

        // solhint-disable-next-line avoid-low-level-calls
        (bool success, bytes memory returndata) = address(token).call(data);
        require(success, "SafeERC20: low-level call failed");

        if (returndata.length > 0) { // Return data is optional
            // solhint-disable-next-line max-line-length
            require(abi.decode(returndata, (bool)), "SafeERC20: ERC20 operation did not succeed");
        }
    }
}

File 112 of 114 : ERC20.sol
pragma solidity ^0.5.0;

import "./IERC20.sol";
import "../../math/SafeMath.sol";

/**
 * @dev Implementation of the `IERC20` interface.
 *
 * This implementation is agnostic to the way tokens are created. This means
 * that a supply mechanism has to be added in a derived contract using `_mint`.
 * For a generic mechanism see `ERC20Mintable`.
 *
 * *For a detailed writeup see our guide [How to implement supply
 * mechanisms](https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226).*
 *
 * We have followed general OpenZeppelin guidelines: functions revert instead
 * of returning `false` on failure. This behavior is nonetheless conventional
 * and does not conflict with the expectations of ERC20 applications.
 *
 * Additionally, an `Approval` event is emitted on calls to `transferFrom`.
 * This allows applications to reconstruct the allowance for all accounts just
 * by listening to said events. Other implementations of the EIP may not emit
 * these events, as it isn't required by the specification.
 *
 * Finally, the non-standard `decreaseAllowance` and `increaseAllowance`
 * functions have been added to mitigate the well-known issues around setting
 * allowances. See `IERC20.approve`.
 */
contract ERC20 is IERC20 {
    using SafeMath for uint256;

    mapping (address => uint256) private _balances;

    mapping (address => mapping (address => uint256)) private _allowances;

    uint256 private _totalSupply;

    /**
     * @dev See `IERC20.totalSupply`.
     */
    function totalSupply() public view returns (uint256) {
        return _totalSupply;
    }

    /**
     * @dev See `IERC20.balanceOf`.
     */
    function balanceOf(address account) public view returns (uint256) {
        return _balances[account];
    }

    /**
     * @dev See `IERC20.transfer`.
     *
     * Requirements:
     *
     * - `recipient` cannot be the zero address.
     * - the caller must have a balance of at least `amount`.
     */
    function transfer(address recipient, uint256 amount) public returns (bool) {
        _transfer(msg.sender, recipient, amount);
        return true;
    }

    /**
     * @dev See `IERC20.allowance`.
     */
    function allowance(address owner, address spender) public view returns (uint256) {
        return _allowances[owner][spender];
    }

    /**
     * @dev See `IERC20.approve`.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function approve(address spender, uint256 value) public returns (bool) {
        _approve(msg.sender, spender, value);
        return true;
    }

    /**
     * @dev See `IERC20.transferFrom`.
     *
     * Emits an `Approval` event indicating the updated allowance. This is not
     * required by the EIP. See the note at the beginning of `ERC20`;
     *
     * Requirements:
     * - `sender` and `recipient` cannot be the zero address.
     * - `sender` must have a balance of at least `value`.
     * - the caller must have allowance for `sender`'s tokens of at least
     * `amount`.
     */
    function transferFrom(address sender, address recipient, uint256 amount) public returns (bool) {
        _transfer(sender, recipient, amount);
        _approve(sender, msg.sender, _allowances[sender][msg.sender].sub(amount));
        return true;
    }

    /**
     * @dev Atomically increases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to `approve` that can be used as a mitigation for
     * problems described in `IERC20.approve`.
     *
     * Emits an `Approval` event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function increaseAllowance(address spender, uint256 addedValue) public returns (bool) {
        _approve(msg.sender, spender, _allowances[msg.sender][spender].add(addedValue));
        return true;
    }

    /**
     * @dev Atomically decreases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to `approve` that can be used as a mitigation for
     * problems described in `IERC20.approve`.
     *
     * Emits an `Approval` event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `spender` must have allowance for the caller of at least
     * `subtractedValue`.
     */
    function decreaseAllowance(address spender, uint256 subtractedValue) public returns (bool) {
        _approve(msg.sender, spender, _allowances[msg.sender][spender].sub(subtractedValue));
        return true;
    }

    /**
     * @dev Moves tokens `amount` from `sender` to `recipient`.
     *
     * This is internal function is equivalent to `transfer`, and can be used to
     * e.g. implement automatic token fees, slashing mechanisms, etc.
     *
     * Emits a `Transfer` event.
     *
     * Requirements:
     *
     * - `sender` cannot be the zero address.
     * - `recipient` cannot be the zero address.
     * - `sender` must have a balance of at least `amount`.
     */
    function _transfer(address sender, address recipient, uint256 amount) internal {
        require(sender != address(0), "ERC20: transfer from the zero address");
        require(recipient != address(0), "ERC20: transfer to the zero address");

        _balances[sender] = _balances[sender].sub(amount);
        _balances[recipient] = _balances[recipient].add(amount);
        emit Transfer(sender, recipient, amount);
    }

    /** @dev Creates `amount` tokens and assigns them to `account`, increasing
     * the total supply.
     *
     * Emits a `Transfer` event with `from` set to the zero address.
     *
     * Requirements
     *
     * - `to` cannot be the zero address.
     */
    function _mint(address account, uint256 amount) internal {
        require(account != address(0), "ERC20: mint to the zero address");

        _totalSupply = _totalSupply.add(amount);
        _balances[account] = _balances[account].add(amount);
        emit Transfer(address(0), account, amount);
    }

     /**
     * @dev Destoys `amount` tokens from `account`, reducing the
     * total supply.
     *
     * Emits a `Transfer` event with `to` set to the zero address.
     *
     * Requirements
     *
     * - `account` cannot be the zero address.
     * - `account` must have at least `amount` tokens.
     */
    function _burn(address account, uint256 value) internal {
        require(account != address(0), "ERC20: burn from the zero address");

        _totalSupply = _totalSupply.sub(value);
        _balances[account] = _balances[account].sub(value);
        emit Transfer(account, address(0), value);
    }

    /**
     * @dev Sets `amount` as the allowance of `spender` over the `owner`s tokens.
     *
     * This is internal function is equivalent to `approve`, and can be used to
     * e.g. set automatic allowances for certain subsystems, etc.
     *
     * Emits an `Approval` event.
     *
     * Requirements:
     *
     * - `owner` cannot be the zero address.
     * - `spender` cannot be the zero address.
     */
    function _approve(address owner, address spender, uint256 value) internal {
        require(owner != address(0), "ERC20: approve from the zero address");
        require(spender != address(0), "ERC20: approve to the zero address");

        _allowances[owner][spender] = value;
        emit Approval(owner, spender, value);
    }

    /**
     * @dev Destoys `amount` tokens from `account`.`amount` is then deducted
     * from the caller's allowance.
     *
     * See `_burn` and `_approve`.
     */
    function _burnFrom(address account, uint256 amount) internal {
        _burn(account, amount);
        _approve(account, msg.sender, _allowances[account][msg.sender].sub(amount));
    }
}

File 113 of 114 : MinterRole.sol
pragma solidity ^0.5.0;

import "../Roles.sol";

contract MinterRole {
    using Roles for Roles.Role;

    event MinterAdded(address indexed account);
    event MinterRemoved(address indexed account);

    Roles.Role private _minters;

    constructor () internal {
        _addMinter(msg.sender);
    }

    modifier onlyMinter() {
        require(isMinter(msg.sender), "MinterRole: caller does not have the Minter role");
        _;
    }

    function isMinter(address account) public view returns (bool) {
        return _minters.has(account);
    }

    function addMinter(address account) public onlyMinter {
        _addMinter(account);
    }

    function renounceMinter() public {
        _removeMinter(msg.sender);
    }

    function _addMinter(address account) internal {
        _minters.add(account);
        emit MinterAdded(account);
    }

    function _removeMinter(address account) internal {
        _minters.remove(account);
        emit MinterRemoved(account);
    }
}

File 114 of 114 : Roles.sol
pragma solidity ^0.5.0;

/**
 * @title Roles
 * @dev Library for managing addresses assigned to a Role.
 */
library Roles {
    struct Role {
        mapping (address => bool) bearer;
    }

    /**
     * @dev Give an account access to this role.
     */
    function add(Role storage role, address account) internal {
        require(!has(role, account), "Roles: account already has role");
        role.bearer[account] = true;
    }

    /**
     * @dev Remove an account's access to this role.
     */
    function remove(Role storage role, address account) internal {
        require(has(role, account), "Roles: account does not have role");
        role.bearer[account] = false;
    }

    /**
     * @dev Check if an account has this role.
     * @return bool
     */
    function has(Role storage role, address account) internal view returns (bool) {
        require(account != address(0), "Roles: account is the zero address");
        return role.bearer[account];
    }
}

Settings
{
  "libraries": {
    "": {
      "PaymentStartStandardExit": "0xf38380bbf08961123960fAd630a0609906849751",
      "PaymentChallengeStandardExit": "0x24c0a84090135AD04F257C85E10db6B4A74E0738",
      "PaymentProcessStandardExit": "0x5E84DF30ce17A9AC34E5474fc37a9c2267454518",
      "PaymentStartInFlightExit": "0x081d7B167a94E7421Ea5D0016C3D01E0cFf6B557",
      "PaymentPiggybackInFlightExit": "0x5d3EE50E31293B45A7eb8B864c0B015E169AC7D8",
      "PaymentChallengeIFENotCanonical": "0x9e3108FB11cAEDA64e264B2953a0eDa81cf1a650",
      "PaymentChallengeIFEInputSpent": "0xEf6133d149460C9B79e132517934f77F1E62b23e",
      "PaymentChallengeIFEOutputSpent": "0x7A8C0D7F1e6dBe36AB3A9adE0C44a0b868bB703F",
      "PaymentDeleteInFlightExit": "0x4f05855B6dF026726037500D10D91652b5C9e784",
      "PaymentProcessInFlightExit": "0x67C3E5524dBE05B54fE08c3D4af65c273B87E630"
    }
  },
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "remappings": [],
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "abi"
      ]
    }
  }
}

Contract Security Audit

Contract ABI

[{"constant":true,"inputs":[{"internalType":"uint160[]","name":"exitIds","type":"uint160[]"}],"name":"standardExits","outputs":[{"components":[{"internalType":"bool","name":"exitable","type":"bool"},{"internalType":"uint256","name":"utxoPos","type":"uint256"},{"internalType":"bytes32","name":"outputId","type":"bytes32"},{"internalType":"address payable","name":"exitTarget","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"bondSize","type":"uint256"}],"internalType":"struct PaymentExitDataModel.StandardExit[]","name":"","type":"tuple[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"internalType":"uint128","name":"newBondSize","type":"uint128"}],"name":"updateStartStandardExitBondSize","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"components":[{"internalType":"bytes","name":"inFlightTx","type":"bytes"},{"internalType":"bytes","name":"inFlightTxInclusionProof","type":"bytes"},{"internalType":"uint256","name":"outputUtxoPos","type":"uint256"},{"internalType":"bytes","name":"challengingTx","type":"bytes"},{"internalType":"uint16","name":"challengingTxInputIndex","type":"uint16"},{"internalType":"bytes","name":"challengingTxWitness","type":"bytes"},{"internalType":"bytes32","name":"senderData","type":"bytes32"}],"internalType":"struct PaymentInFlightExitRouterArgs.ChallengeOutputSpent","name":"args","type":"tuple"}],"name":"challengeInFlightExitOutputSpent","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint128","name":"newBondSize","type":"uint128"}],"name":"updatePiggybackBondSize","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"internalType":"bytes","name":"inFlightTx","type":"bytes"},{"internalType":"uint256","name":"inFlightTxPos","type":"uint256"},{"internalType":"bytes","name":"inFlightTxInclusionProof","type":"bytes"}],"name":"respondToNonCanonicalChallenge","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"piggybackBondSize","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"components":[{"internalType":"bytes","name":"inFlightTx","type":"bytes"},{"internalType":"bytes[]","name":"inputTxs","type":"bytes[]"},{"internalType":"uint256[]","name":"inputUtxosPos","type":"uint256[]"},{"internalType":"bytes[]","name":"inputTxsInclusionProofs","type":"bytes[]"},{"internalType":"bytes[]","name":"inFlightTxWitnesses","type":"bytes[]"}],"internalType":"struct PaymentInFlightExitRouterArgs.StartExitArgs","name":"args","type":"tuple"}],"name":"startInFlightExit","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint160","name":"exitId","type":"uint160"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"token","type":"address"}],"name":"processExit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"components":[{"internalType":"uint256","name":"utxoPos","type":"uint256"},{"internalType":"bytes","name":"rlpOutputTx","type":"bytes"},{"internalType":"bytes","name":"outputTxInclusionProof","type":"bytes"}],"internalType":"struct PaymentStandardExitRouterArgs.StartStandardExitArgs","name":"args","type":"tuple"}],"name":"startStandardExit","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":true,"inputs":[],"name":"startIFEBondSize","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"INITIAL_PB_BOND_SIZE","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"bytes","name":"_txBytes","type":"bytes"}],"name":"getInFlightExitId","outputs":[{"internalType":"uint160","name":"","type":"uint160"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":true,"inputs":[],"name":"BOND_LOWER_BOUND_DIVISOR","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"BOND_UPPER_BOUND_MULTIPLIER","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"components":[{"internalType":"bytes","name":"inFlightTx","type":"bytes"},{"internalType":"uint16","name":"outputIndex","type":"uint16"}],"internalType":"struct PaymentInFlightExitRouterArgs.PiggybackInFlightExitOnOutputArgs","name":"args","type":"tuple"}],"name":"piggybackInFlightExitOnOutput","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[{"internalType":"uint128","name":"newBondSize","type":"uint128"}],"name":"updateStartIFEBondSize","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[{"internalType":"bool","name":"_isDeposit","type":"bool"},{"internalType":"bytes","name":"_txBytes","type":"bytes"},{"internalType":"uint256","name":"_utxoPos","type":"uint256"}],"name":"getStandardExitId","outputs":[{"internalType":"uint160","name":"","type":"uint160"}],"payable":false,"stateMutability":"pure","type":"function"},{"constant":false,"inputs":[{"internalType":"uint160","name":"exitId","type":"uint160"}],"name":"deleteNonPiggybackedInFlightExit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"components":[{"internalType":"bytes","name":"inFlightTx","type":"bytes"},{"internalType":"uint16","name":"inFlightTxInputIndex","type":"uint16"},{"internalType":"bytes","name":"challengingTx","type":"bytes"},{"internalType":"uint16","name":"challengingTxInputIndex","type":"uint16"},{"internalType":"bytes","name":"challengingTxWitness","type":"bytes"},{"internalType":"bytes","name":"inputTx","type":"bytes"},{"internalType":"uint256","name":"inputUtxoPos","type":"uint256"},{"internalType":"bytes32","name":"senderData","type":"bytes32"}],"internalType":"struct PaymentInFlightExitRouterArgs.ChallengeInputSpentArgs","name":"args","type":"tuple"}],"name":"challengeInFlightExitInputSpent","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"INITIAL_BOND_SIZE","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[],"name":"INITIAL_IFE_BOND_SIZE","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":true,"inputs":[{"internalType":"uint160[]","name":"exitIds","type":"uint160[]"}],"name":"inFlightExits","outputs":[{"components":[{"internalType":"bool","name":"isCanonical","type":"bool"},{"internalType":"uint64","name":"exitStartTimestamp","type":"uint64"},{"internalType":"uint256","name":"exitMap","type":"uint256"},{"internalType":"uint256","name":"position","type":"uint256"},{"components":[{"internalType":"bytes32","name":"outputId","type":"bytes32"},{"internalType":"address payable","name":"exitTarget","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"piggybackBondSize","type":"uint256"}],"internalType":"struct PaymentExitDataModel.WithdrawData[4]","name":"inputs","type":"tuple[4]"},{"components":[{"internalType":"bytes32","name":"outputId","type":"bytes32"},{"internalType":"address payable","name":"exitTarget","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"piggybackBondSize","type":"uint256"}],"internalType":"struct PaymentExitDataModel.WithdrawData[4]","name":"outputs","type":"tuple[4]"},{"internalType":"address payable","name":"bondOwner","type":"address"},{"internalType":"uint256","name":"bondSize","type":"uint256"},{"internalType":"uint256","name":"oldestCompetitorPosition","type":"uint256"}],"internalType":"struct PaymentExitDataModel.InFlightExit[]","name":"","type":"tuple[]"}],"payable":false,"stateMutability":"view","type":"function"},{"constant":false,"inputs":[{"components":[{"internalType":"uint160","name":"exitId","type":"uint160"},{"internalType":"bytes","name":"exitingTx","type":"bytes"},{"internalType":"bytes","name":"challengeTx","type":"bytes"},{"internalType":"uint16","name":"inputIndex","type":"uint16"},{"internalType":"bytes","name":"witness","type":"bytes"},{"internalType":"bytes32","name":"senderData","type":"bytes32"}],"internalType":"struct PaymentStandardExitRouterArgs.ChallengeStandardExitArgs","name":"args","type":"tuple"}],"name":"challengeStandardExit","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":false,"inputs":[{"components":[{"internalType":"bytes","name":"inFlightTx","type":"bytes"},{"internalType":"uint16","name":"inputIndex","type":"uint16"}],"internalType":"struct PaymentInFlightExitRouterArgs.PiggybackInFlightExitOnInputArgs","name":"args","type":"tuple"}],"name":"piggybackInFlightExitOnInput","outputs":[],"payable":true,"stateMutability":"payable","type":"function"},{"constant":false,"inputs":[{"components":[{"internalType":"bytes","name":"inputTx","type":"bytes"},{"internalType":"uint256","name":"inputUtxoPos","type":"uint256"},{"internalType":"bytes","name":"inFlightTx","type":"bytes"},{"internalType":"uint16","name":"inFlightTxInputIndex","type":"uint16"},{"internalType":"bytes","name":"competingTx","type":"bytes"},{"internalType":"uint16","name":"competingTxInputIndex","type":"uint16"},{"internalType":"uint256","name":"competingTxPos","type":"uint256"},{"internalType":"bytes","name":"competingTxInclusionProof","type":"bytes"},{"internalType":"bytes","name":"competingTxWitness","type":"bytes"}],"internalType":"struct PaymentInFlightExitRouterArgs.ChallengeCanonicityArgs","name":"args","type":"tuple"}],"name":"challengeInFlightExitNotCanonical","outputs":[],"payable":false,"stateMutability":"nonpayable","type":"function"},{"constant":true,"inputs":[],"name":"startStandardExitBondSize","outputs":[{"internalType":"uint128","name":"","type":"uint128"}],"payable":false,"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"contract PlasmaFramework","name":"framework","type":"address"},{"internalType":"uint256","name":"ethVaultId","type":"uint256"},{"internalType":"uint256","name":"erc20VaultId","type":"uint256"},{"internalType":"contract SpendingConditionRegistry","name":"spendingConditionRegistry","type":"address"},{"internalType":"contract IStateTransitionVerifier","name":"stateTransitionVerifier","type":"address"},{"internalType":"uint256","name":"supportTxType","type":"uint256"},{"internalType":"uint256","name":"safeGasStipend","type":"uint256"}],"internalType":"struct PaymentExitGameArgs.Args","name":"args","type":"tuple"}],"payable":false,"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint128","name":"bondSize","type":"uint128"}],"name":"IFEBondUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint128","name":"bondSize","type":"uint128"}],"name":"PiggybackBondUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"initiator","type":"address"},{"indexed":true,"internalType":"bytes32","name":"txHash","type":"bytes32"}],"name":"InFlightExitStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"exitTarget","type":"address"},{"indexed":true,"internalType":"bytes32","name":"txHash","type":"bytes32"},{"indexed":false,"internalType":"uint16","name":"inputIndex","type":"uint16"}],"name":"InFlightExitInputPiggybacked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint160","name":"exitId","type":"uint160"},{"indexed":false,"internalType":"address","name":"token","type":"address"}],"name":"InFlightExitOmitted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"InFlightBondReturnFailed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint160","name":"exitId","type":"uint160"},{"indexed":false,"internalType":"uint16","name":"outputIndex","type":"uint16"}],"name":"InFlightExitOutputWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint160","name":"exitId","type":"uint160"},{"indexed":false,"internalType":"uint16","name":"inputIndex","type":"uint16"}],"name":"InFlightExitInputWithdrawn","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"exitTarget","type":"address"},{"indexed":true,"internalType":"bytes32","name":"txHash","type":"bytes32"},{"indexed":false,"internalType":"uint16","name":"outputIndex","type":"uint16"}],"name":"InFlightExitOutputPiggybacked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"challenger","type":"address"},{"indexed":true,"internalType":"bytes32","name":"txHash","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"challengeTxPosition","type":"uint256"}],"name":"InFlightExitChallenged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"challenger","type":"address"},{"indexed":true,"internalType":"bytes32","name":"txHash","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"challengeTxPosition","type":"uint256"}],"name":"InFlightExitChallengeResponded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"challenger","type":"address"},{"indexed":true,"internalType":"bytes32","name":"txHash","type":"bytes32"},{"indexed":false,"internalType":"uint16","name":"inputIndex","type":"uint16"}],"name":"InFlightExitInputBlocked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"challenger","type":"address"},{"indexed":true,"internalType":"bytes32","name":"txHash","type":"bytes32"},{"indexed":false,"internalType":"uint16","name":"outputIndex","type":"uint16"}],"name":"InFlightExitOutputBlocked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint160","name":"exitId","type":"uint160"}],"name":"InFlightExitDeleted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint128","name":"bondSize","type":"uint128"}],"name":"StandardExitBondUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":false,"internalType":"uint160","name":"exitId","type":"uint160"}],"name":"ExitStarted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"utxoPos","type":"uint256"}],"name":"ExitChallenged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint160","name":"exitId","type":"uint160"}],"name":"ExitOmitted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint160","name":"exitId","type":"uint160"}],"name":"ExitFinalized","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"receiver","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"BondReturnFailed","type":"event"}]

60806040523480156200001157600080fd5b5060405162004f3238038062004f328339810160408190526200003491620012a2565b8051601080546001600160a01b0319166001600160a01b03909216918217905560208201516040517f8c64ea4a00000000000000000000000000000000000000000000000000000000815283928392600092638c64ea4a916200009a9160040162001589565b60206040518083038186803b158015620000b357600080fd5b505afa158015620000c8573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250620000ee919081019062001279565b90506001600160a01b0381166200013c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620001339062001553565b60405180910390fd5b815160408084015190517f8c64ea4a0000000000000000000000000000000000000000000000000000000081526000926001600160a01b031691638c64ea4a916200018b919060040162001589565b60206040518083038186803b158015620001a457600080fd5b505afa158015620001b9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250620001df919081019062001279565b90506001600160a01b03811662000224576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620001339062001565565b8251602084015160408086015160a087015191517f07a97aa900000000000000000000000000000000000000000000000000000000815273f38380bbf08961123960fad630a0609906849751946307a97aa9946200028c94309492939192916004016200145b565b60c06040518083038186803b158015620002a557600080fd5b505af4158015620002ba573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250620002e0919081019062001326565b8051600180546001600160a01b039283166001600160a01b031991821617909155602083015160028054919093169116179055604080820151516003556060808301516004908155608084015160055560a09093015160065585519086015160c087015192517f159cde2d0000000000000000000000000000000000000000000000000000000081527324c0a84090135ad04f257c85e10db6b4a74e07389463159cde2d946200039594939290910162001525565b60606040518083038186803b158015620003ae57600080fd5b505af4158015620003c3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250620003e99190810190620012c3565b8051600b80546001600160a01b03199081166001600160a01b0393841617909155602080840151600c80548416918516919091179055604093840151600d5583516080810185528751841680825287851682840181905294871695820186905260c089015160609092018290526007805485169091179055600880548416909417909355600980549092169093179055600a556200049e906631bced02db000090600290819062000eed811b6200387417901c565b8051600e80546020808501516001600160801b03199283166001600160801b03958616178516700100000000000000000000000000000000918616820217909355604080860151600f805460608901516080909901519516919096161761ffff60801b191661ffff9687169094029390931761ffff60901b191672010000000000000000000000000000000000009590921694909402179091558551603080546001600160a01b0319166001600160a01b0390921691821790559186015190517f8c64ea4a00000000000000000000000000000000000000000000000000000000815260009550919350638c64ea4a92506200059d9160040162001589565b60206040518083038186803b158015620005b657600080fd5b505afa158015620005cb573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250620005f1919081019062001279565b90506001600160a01b03811662000636576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620001339062001553565b815160408084015190517f8c64ea4a0000000000000000000000000000000000000000000000000000000081526000926001600160a01b031691638c64ea4a9162000685919060040162001589565b60206040518083038186803b1580156200069e57600080fd5b505afa158015620006b3573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250620006d9919081019062001279565b90506001600160a01b0381166200071e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620001339062001565565b82516060840151608085015160a08601516040517f91ac978000000000000000000000000000000000000000000000000000000000815273081d7b167a94e7421ea5d0016c3d01e0cff6b557946391ac978094620007839491939092600401620014f7565b60a06040518083038186803b1580156200079c57600080fd5b505af4158015620007b1573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250620007d7919081019062001305565b8051601280546001600160a01b03199081166001600160a01b0393841617909155602080840151516013556040808501516014805485169186169190911790556060850151601580549094169416939093179091556080909201516016558451918501518582015191517f32e6d869000000000000000000000000000000000000000000000000000000008152735d3ee50e31293b45a7eb8b864c0b015e169ac7d8936332e6d869936200089493919230929190600401620014b1565b60c06040518083038186803b158015620008ad57600080fd5b505af4158015620008c2573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250620008e89190810190620012e4565b8051601780546001600160a01b03199081166001600160a01b0393841617909155602083015151601855604080840151601980549093169316929092179055606080830151601a556080830151601b5560a092830151601c558551908601519286015191517f159cde2d000000000000000000000000000000000000000000000000000000008152739e3108fb11caeda64e264b2953a0eda81cf1a6509363159cde2d936200099b939260040162001525565b60606040518083038186803b158015620009b457600080fd5b505af4158015620009c9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250620009ef9190810190620012c3565b8051601d80546001600160a01b039283166001600160a01b0319918216179091556020830151601e8054919093169116179055604090810151601f558351606085015160c086015192517f159cde2d00000000000000000000000000000000000000000000000000000000815273ef6133d149460c9b79e132517934f77f1e62b23e9363159cde2d9362000a8b93909290919060040162001525565b60606040518083038186803b15801562000aa457600080fd5b505af415801562000ab9573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525062000adf9190810190620012c3565b8051602080546001600160a01b03199081166001600160a01b03938416178255818401516021805483169185169190911790556040938401516022558351606080820186528851851680835290890151851682850181905260c08a01519287018390526023805485169092179091556024805490931617909155602555825180840180855287517fd4a2b4ef00000000000000000000000000000000000000000000000000000000909152935190938493169163d4a2b4ef916044808601929190818703018186803b15801562000bb557600080fd5b505afa15801562000bca573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525062000bf0919081019062001347565b815260c0850180516020928301528251602655918101516027556040805160808101825286516001600160a01b0390811680835287821683860181905291871693830184905294516060909201829052602880546001600160a01b031990811690961790556029805486169091179055602a8054909416909117909255602b9190915562000c95906683734dd0b080009060029081906200387462000eed821b17901c565b8051602c80546020808501516001600160801b03199283166001600160801b039586161785167001000000000000000000000000000000009186168202179093556040850151602d805460608801516080909801519416919095161761ffff60801b191661ffff9586169093029290921761ffff60901b19167201000000000000000000000000000000000000949091169390930292909217905562000d5290666379da05b6000090600290819062000eed811b6200387417901c565b8051602e80546020808501516001600160801b03199283166001600160801b03958616178516700100000000000000000000000000000000918616820217909355604080860151602f80546060808a01516080909a015191909616929097169190911761ffff60801b191661ffff9788169095029490941761ffff60901b191672010000000000000000000000000000000000009690951695909502939093179091558651603180546001600160a01b0319166001600160a01b039283161790559087015183517f8da5cb5b00000000000000000000000000000000000000000000000000000000815293516000975091169450638da5cb5b9350600480840193829003018186803b15801562000e6857600080fd5b505afa15801562000e7d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525062000ea3919081019062001279565b6001600160a01b03161462000ee6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620001339062001577565b5062001622565b62000ef762000f38565b506040805160a0810182526001600160801b03949094168452600060208501526780000000000000009084015261ffff918216606084015216608082015290565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915290565b805162000f7381620015f2565b92915050565b805162000f73816200160c565b600060e0828403121562000f9957600080fd5b62000fa560e062001599565b9050600062000fb5848462000f79565b825250602062000fc8848483016200126c565b602083015250604062000fde848285016200126c565b604083015250606062000ff48482850162000f79565b60608301525060806200100a8482850162000f79565b60808301525060a062001020848285016200126c565b60a08301525060c062001036848285016200126c565b60c08301525092915050565b6000602082840312156200105557600080fd5b62001061602062001599565b905060006200107184846200126c565b82525092915050565b6000606082840312156200108d57600080fd5b62001099606062001599565b90506000620010a9848462000f79565b8252506020620010bc8484830162000f79565b6020830152506040620010d2848285016200126c565b60408301525092915050565b600060c08284031215620010f157600080fd5b620010fd60c062001599565b905060006200110d848462000f79565b8252506020620011208484830162001042565b6020830152506040620011368482850162000f79565b60408301525060606200114c848285016200126c565b606083015250608062001162848285016200126c565b60808301525060a062001178848285016200126c565b60a08301525092915050565b600060a082840312156200119757600080fd5b620011a360a062001599565b90506000620011b3848462000f79565b8252506020620011c68484830162001042565b6020830152506040620011dc8482850162000f79565b6040830152506060620011f28482850162000f79565b606083015250608062001208848285016200126c565b60808301525092915050565b600060c082840312156200122757600080fd5b6200123360c062001599565b9050600062001243848462000f79565b8252506020620012568484830162000f79565b6020830152506040620011368482850162001042565b805162000f738162001617565b6000602082840312156200128c57600080fd5b60006200129a848462000f66565b949350505050565b600060e08284031215620012b557600080fd5b60006200129a848462000f86565b600060608284031215620012d657600080fd5b60006200129a84846200107a565b600060c08284031215620012f757600080fd5b60006200129a8484620010de565b600060a082840312156200131857600080fd5b60006200129a848462001184565b600060c082840312156200133957600080fd5b60006200129a848462001214565b6000602082840312156200135a57600080fd5b60006200129a84846200126c565b6200137381620015d6565b82525050565b600062001388601183620015c0565b7f496e76616c696420455448207661756c74000000000000000000000000000000815260200192915050565b6000620013c3601383620015c0565b7f496e76616c6964204552433230207661756c7400000000000000000000000000815260200192915050565b6000620013fe603b83620015c0565b7f5370656e64696e6720636f6e646974696f6e207265676973747279206f776e6581527f7273686970206e6565647320746f2062652072656e6f756e6365640000000000602082015260400192915050565b6200137381620015ef565b60a081016200146b828862001368565b6200147a602083018762001368565b62001489604083018662001450565b62001498606083018562001450565b620014a7608083018462001450565b9695505050505050565b60808101620014c1828762001368565b620014d0602083018662001368565b620014df604083018562001450565b620014ee606083018462001450565b95945050505050565b6080810162001507828762001368565b62001516602083018662001368565b620014df604083018562001368565b6060810162001535828662001368565b62001544602083018562001368565b6200129a604083018462001450565b6020808252810162000f738162001379565b6020808252810162000f7381620013b4565b6020808252810162000f7381620013ef565b6020810162000f73828462001450565b6040518181016001600160401b0381118282101715620015b857600080fd5b604052919050565b90815260200190565b600062000f7382620015e3565b600062000f7382620015c9565b6001600160a01b031690565b90565b620015fd81620015c9565b81146200160957600080fd5b50565b620015fd81620015d6565b620015fd81620015ef565b61390080620016326000396000f3fe6080604052600436106101815760003560e01c8063a0e403b1116100d1578063c170ecf51161008a578063df2933e211610064578063df2933e214610409578063e5bc60c714610429578063e83622981461043c578063fe32a1241461045c57610181565b8063c170ecf5146103b2578063c96e7c05146103c7578063cec9e1a7146103dc57610181565b8063a0e403b1146102fd578063a4a254411461031f578063b177ba2314610332578063b22d3e1414610352578063b3c2ec7614610372578063b9a3a28e1461039257610181565b80635a5285141161013e5780637702fa17116101185780637702fa17146102a65780637e2b2efe146102bb578063839c78f9146102d0578063905d6a99146102fd57610181565b80635a52851414610260578063684963511461027357806370e014621461029357610181565b80630ca5b67614610186578063163d7bc7146101bc5780632c3bad95146101de578063315fb7da146101fe57806336660de41461021e5780633f1214cf1461023e575b600080fd5b34801561019257600080fd5b506101a66101a136600461253c565b610471565b6040516101b39190613451565b60405180910390f35b3480156101c857600080fd5b506101dc6101d73660046127f1565b610576565b005b3480156101ea57600080fd5b506101dc6101f93660046126ed565b610679565b34801561020a57600080fd5b506101dc6102193660046127f1565b6107cd565b34801561022a57600080fd5b506101dc610239366004612615565b6108bb565b34801561024a57600080fd5b50610253610a15565b6040516101b391906136f5565b6101dc61026e366004612789565b610a7a565b34801561027f57600080fd5b506101dc61028e36600461282d565b610bfe565b6101dc6102a13660046127bd565b610c56565b3480156102b257600080fd5b50610253610d78565b3480156102c757600080fd5b50610253610dd8565b3480156102dc57600080fd5b506102f06102eb3660046125e1565b610de3565b6040516101b39190613703565b34801561030957600080fd5b50610312610df6565b6040516101b39190613711565b6101dc61032d366004612755565b610dfb565b34801561033e57600080fd5b506101dc61034d3660046127f1565b610f19565b34801561035e57600080fd5b506102f061036d36600461257d565b611007565b34801561037e57600080fd5b506101dc61038d36600461280f565b611032565b34801561039e57600080fd5b506101dc6103ad3660046126b9565b6110eb565b3480156103be57600080fd5b506102536111b8565b3480156103d357600080fd5b506102536111c3565b3480156103e857600080fd5b506103fc6103f736600461253c565b6111ce565b6040516101b39190613440565b34801561041557600080fd5b506101dc610424366004612721565b6113f7565b6101dc610437366004612755565b6114c4565b34801561044857600080fd5b506101dc610457366004612685565b6115e2565b34801561046857600080fd5b506102536116af565b606080838390506040519080825280602002602001820160405280156104b157816020015b61049e611c20565b8152602001906001900390816104965790505b50905060005b8381101561056c5760008585838181106104cd57fe5b90506020020160206104e2919081019061280f565b6001600160a01b0380821660009081526020818152604091829020825160c081018452815460ff161515815260018201549281019290925260028101549282019290925260038201549092166060830152600481015460808301526005015460a082015284519192509084908490811061055857fe5b6020908102919091010152506001016104b7565b5090505b92915050565b601060009054906101000a90046001600160a01b03166001600160a01b0316634b0a72bc6040518163ffffffff1660e01b815260040160206040518083038186803b1580156105c457600080fd5b505afa1580156105d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506105fc919081019061251e565b336001600160a01b0382161461062d5760405162461bcd60e51b8152600401610624906134d2565b60405180910390fd5b61063e600e8363ffffffff61170f16565b7fd21ccbbae3d29826d53310efdc993c64e27496dd31694b292f1a120344ec37ab8260405161066d91906136f5565b60405180910390a15050565b603060009054906101000a90046001600160a01b0316806001600160a01b031663ff27b1896040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156106ca57600080fd5b505af11580156106de573d6000803e3d6000fd5b5050604080516060810182526023546001600160a01b0390811682526024541660208201526025548183015290516359cff02160e01b8152737a8c0d7f1e6dbe36ab3a9ade0c44a0b868bb703f93506359cff0219250610746919060119087906004016135b5565b60006040518083038186803b15801561075e57600080fd5b505af4158015610772573d6000803e3d6000fd5b50505050806001600160a01b0316634e0f74366040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156107b157600080fd5b505af11580156107c5573d6000803e3d6000fd5b505050505050565b603060009054906101000a90046001600160a01b03166001600160a01b0316634b0a72bc6040518163ffffffff1660e01b815260040160206040518083038186803b15801561081b57600080fd5b505afa15801561082f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610853919081019061251e565b336001600160a01b0382161461087b5760405162461bcd60e51b8152600401610624906134d2565b61088c602e8363ffffffff61170f16565b7f30ce291291dca42b8168ab211fafc36d3d4868292ed3259874ed00864432e20e8260405161066d91906136f5565b603060009054906101000a90046001600160a01b0316806001600160a01b031663ff27b1896040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561090c57600080fd5b505af1158015610920573d6000803e3d6000fd5b505060408051606081018252601d546001600160a01b039081168252601e54166020820152601f54818301529051630c27711f60e11b8152739e3108fb11caeda64e264b2953a0eda81cf1a650935063184ee23e925061098c919060119089908990899060040161352f565b60006040518083038186803b1580156109a457600080fd5b505af41580156109b8573d6000803e3d6000fd5b50505050806001600160a01b0316634e0f74366040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156109f757600080fd5b505af1158015610a0b573d6000803e3d6000fd5b5050505050505050565b6040805160a081018252602e546001600160801b038082168352600160801b9182900481166020840152602f549081169383019390935261ffff90830481166060830152600160901b9092049091166080820152600090610a75906117fd565b905090565b603060009054906101000a90046001600160a01b0316806001600160a01b031663ff27b1896040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610acb57600080fd5b505af1158015610adf573d6000803e3d6000fd5b50505050610aeb610d78565b6001600160801b0316803414610b135760405162461bcd60e51b815260040161062490613482565b6040805160a0810182526012546001600160a01b039081168252825160208181018552601354825283015260145481168284015260155416606082015260165460808201529051631ff4513b60e01b815273081d7b167a94e7421ea5d0016c3d01e0cff6b55791631ff4513b91610b929190601190889060040161369a565b60006040518083038186803b158015610baa57600080fd5b505af4158015610bbe573d6000803e3d6000fd5b5050505050806001600160a01b0316634e0f74366040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156107b157600080fd5b6031546001600160a01b0316338114610c295760405162461bcd60e51b8152600401610624906134d2565b610c3284611827565b15610c4657610c41848361184d565b610c50565b610c5084836118e9565b50505050565b601060009054906101000a90046001600160a01b0316806001600160a01b031663ff27b1896040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610ca757600080fd5b505af1158015610cbb573d6000803e3d6000fd5b50505050610cc76116af565b6001600160801b0316803414610cef5760405162461bcd60e51b815260040161062490613482565b6040805160c0810182526001546001600160a01b0390811682526002541660208083019190915282519081018352600354815281830152600480546060830152600554608083015260065460a083015291516332c812a760e11b815273f38380bbf08961123960fad630a060990684975192636590254e92610b929290916000918991016136c7565b6040805160a081018252602c546001600160801b038082168352600160801b9182900481166020840152602d549081169383019390935261ffff90830481166060830152600160901b9092049091166080820152600090610a75906117fd565b666379da05b6000081565b6000610dee82611959565b90505b919050565b600281565b603060009054906101000a90046001600160a01b0316806001600160a01b031663ff27b1896040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610e4c57600080fd5b505af1158015610e60573d6000803e3d6000fd5b50505050610e6c610a15565b6001600160801b0316803414610e945760405162461bcd60e51b815260040161062490613482565b6040805160c0810182526017546001600160a01b03908116825282516020818101855260185482528301526019541681830152601a546060820152601b546080820152601c5460a0820152905163082153e960e21b8152735d3ee50e31293b45a7eb8b864c0b015e169ac7d8916320854fa491610b9291906011908890600401613637565b603060009054906101000a90046001600160a01b03166001600160a01b0316634b0a72bc6040518163ffffffff1660e01b815260040160206040518083038186803b158015610f6757600080fd5b505afa158015610f7b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610f9f919081019061251e565b336001600160a01b03821614610fc75760405162461bcd60e51b8152600401610624906134d2565b610fd8602c8363ffffffff61170f16565b7f63ccac61f03626a0e717e96da239ff8996745b6c4ddcaffdedc88d7ef938f5ec8260405161066d91906136f5565b6000611011611c55565b61101a83611977565b9050611027858583611a0a565b9150505b9392505050565b603060009054906101000a90046001600160a01b0316806001600160a01b031663ff27b1896040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561108357600080fd5b505af1158015611097573d6000803e3d6000fd5b505060408051808201825260265481526027546020820152905163b1cf0fed60e01b8152734f05855b6df026726037500d10d91652b5c9e784935063b1cf0fed92506107469190601190879060040161360f565b603060009054906101000a90046001600160a01b0316806001600160a01b031663ff27b1896040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561113c57600080fd5b505af1158015611150573d6000803e3d6000fd5b505060408051606081018252602080546001600160a01b0390811683526021541690820152602254818301529051634bb4a4df60e11b815273ef6133d149460c9b79e132517934f77f1e62b23e935063976949be925061074691906011908790600401613502565b6631bced02db000081565b6683734dd0b0800081565b6060808383905060405190808252806020026020018201604052801561120e57816020015b6111fb611c75565b8152602001906001900390816111f35790505b50905060005b8381101561056c57600085858381811061122a57fe5b905060200201602061123f919081019061280f565b6001600160a01b0381166000908152601160209081526040808320815161012081018352815460ff81161515825261010090046001600160401b03169381019390935260018101548383015260028101546060840152815160808082019093529495509193919290840191906003840190600490835b8282101561131c576040805160a081018252600584028601805482526001808201546001600160a01b0390811660208086019190915260028401549091169484019490945260038201546060840152600490910154608083015290835290920191016112b5565b5050509082525060408051608081019091526020909101906017830160046000835b828210156113a5576040805160a081018252600584028601805482526001808201546001600160a01b03908116602080860191909152600284015490911694840194909452600382015460608401526004909101546080830152908352909201910161133e565b50505090825250602b8201546001600160a01b03166020820152602c8201546040820152602d9091015460609091015283518490849081106113e357fe5b602090810291909101015250600101611214565b601060009054906101000a90046001600160a01b0316806001600160a01b031663ff27b1896040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561144857600080fd5b505af115801561145c573d6000803e3d6000fd5b505060408051606081018252600b546001600160a01b039081168252600c54166020820152600d5481830152905163edc91d4b60e01b81527324c0a84090135ad04f257c85e10db6b4a74e0738935063edc91d4b9250610746919060009087906004016135e2565b603060009054906101000a90046001600160a01b0316806001600160a01b031663ff27b1896040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561151557600080fd5b505af1158015611529573d6000803e3d6000fd5b50505050611535610a15565b6001600160801b031680341461155d5760405162461bcd60e51b815260040161062490613482565b6040805160c0810182526017546001600160a01b03908116825282516020818101855260185482528301526019541681830152601a546060820152601b546080820152601c5460a08201529051631845801f60e11b8152735d3ee50e31293b45a7eb8b864c0b015e169ac7d89163308b003e91610b9291906011908890600401613637565b603060009054906101000a90046001600160a01b0316806001600160a01b031663ff27b1896040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561163357600080fd5b505af1158015611647573d6000803e3d6000fd5b505060408051606081018252601d546001600160a01b039081168252601e54166020820152601f54818301529051631287d7e160e31b8152739e3108fb11caeda64e264b2953a0eda81cf1a650935063943ebf08925061074691906011908790600401613588565b6040805160a081018252600e546001600160801b038082168352600160801b9182900481166020840152600f549081169383019390935261ffff90830481166060830152600160901b9092049091166080820152600090610a75906117fd565b6040805160a08101825283546001600160801b038082168352600160801b918290048116602084015260018601549081169383019390935261ffff90830481166060830152600160901b909204909116608082015261176e9082611a7a565b8154600160801b90046001600160801b03161580159061179b575060018201546001600160801b03164210155b156117c2578154600160801b81046001600160801b03166001600160801b03199091161782555b81546001600160801b03918216600160801b02911617815560010180546001600160801b0319166001600160401b03426202a3000116179055565b600081604001516001600160801b031642101561181c57508051610df1565b506020810151610df1565b60006118436001600160a01b038316609763ffffffff611b3d16565b60ff161592915050565b604080516080810182526007546001600160a01b039081168252600854811660208301526009541681830152600a54606082015290516373c97b6d60e11b8152735e84df30ce17a9ac34e5474fc37a9c22674545189163e792f6da916118bd919060009087908790600401613665565b60006040518083038186803b1580156118d557600080fd5b505af41580156107c5573d6000803e3d6000fd5b604080516080810182526028546001600160a01b03908116825260295481166020830152602a541681830152602b5460608201529051632309cb3d60e01b81527367c3e5524dbe05b54fe08c3d4af65c273b87e63091632309cb3d916118bd919060119087908790600401613665565b80516020820120600090610dee9060691c609763ffffffff611b4716565b61197f611c55565b633b9aca00808304906127109084068190049084066429f16b11c68311156119b95760405162461bcd60e51b815260040161062490613462565b61ffff8211156119db5760405162461bcd60e51b815260040161062490613472565b604080516060810182526001600160401b03909416845261ffff92831660208501529116908201529050919050565b60008315611a5d57600083611a1e84611b54565b604051602001611a2f92919061341e565b604051602081830303815290604052805190602001209050611a55818460400151611be3565b91505061102b565b611a7283805190602001208360400151611be3565b949350505050565b6000611a85836117fd565b90506000826001600160801b031611611ab05760405162461bcd60e51b8152600401610624906134b2565b826060015161ffff16816001600160801b031681611aca57fe5b046001600160801b0316826001600160801b03161015611afc5760405162461bcd60e51b8152600401610624906134c2565b826080015161ffff16816001600160801b031602826001600160801b03161115611b385760405162461bcd60e51b815260040161062490613492565b505050565b60ff161c60011690565b600160ff919091161b1790565b6000600161271003826040015161ffff161115611b835760405162461bcd60e51b8152600401610624906134a2565b81516429f16b11c66001600160401b039091161115611bb45760405162461bcd60e51b8152600401610624906134e2565b506040810151602082015182516001600160401b0316633b9aca000261ffff9182166127100201911601919050565b6000606983901c61ffff60981b609884901b1617806001600160a01b0381168114611a725760405162461bcd60e51b8152600401610624906134f2565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a081019190915290565b604080516060810182526000808252602082018190529181019190915290565b60405180610120016040528060001515815260200160006001600160401b031681526020016000815260200160008152602001611cb0611ce1565b8152602001611cbd611ce1565b815260200160006001600160a01b0316815260200160008152602001600081525090565b60405180608001604052806004905b611cf8611d0e565b815260200190600190039081611cf05790505090565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915290565b803561057081613830565b805161057081613830565b600082601f830112611d6357600080fd5b8135611d76611d7182613745565b61371f565b81815260209384019390925082018360005b83811015611db45781358601611d9e8882611e8c565b8452506020928301929190910190600101611d88565b5050505092915050565b60008083601f840112611dd057600080fd5b5081356001600160401b03811115611de757600080fd5b602083019150836020820283011115611dff57600080fd5b9250929050565b600082601f830112611e1757600080fd5b8135611e25611d7182613745565b91508181835260208401935060208101905083856020840282011115611e4a57600080fd5b60005b83811015611db45781611e608882611e81565b8452506020928301929190910190600101611e4d565b803561057081613847565b803561057081613850565b600082601f830112611e9d57600080fd5b8135611eab611d7182613765565b91508082526020830160208301858383011115611ec757600080fd5b611ed28382846137ee565b50505092915050565b60006101208284031215611eee57600080fd5b611ef961012061371f565b905081356001600160401b03811115611f1157600080fd5b611f1d84828501611e8c565b8252506020611f2e84848301611e81565b60208301525060408201356001600160401b03811115611f4d57600080fd5b611f5984828501611e8c565b6040830152506060611f6d84828501612508565b60608301525060808201356001600160401b03811115611f8c57600080fd5b611f9884828501611e8c565b60808301525060a0611fac84828501612508565b60a08301525060c0611fc084828501611e81565b60c08301525060e08201356001600160401b03811115611fdf57600080fd5b611feb84828501611e8c565b60e0830152506101008201356001600160401b0381111561200b57600080fd5b61201784828501611e8c565b6101008301525092915050565b6000610100828403121561203757600080fd5b61204261010061371f565b905081356001600160401b0381111561205a57600080fd5b61206684828501611e8c565b825250602061207784848301612508565b60208301525060408201356001600160401b0381111561209657600080fd5b6120a284828501611e8c565b60408301525060606120b684828501612508565b60608301525060808201356001600160401b038111156120d557600080fd5b6120e184828501611e8c565b60808301525060a08201356001600160401b0381111561210057600080fd5b61210c84828501611e8c565b60a08301525060c061212084828501611e81565b60c08301525060e061213484828501611e81565b60e08301525092915050565b600060e0828403121561215257600080fd5b61215c60e061371f565b905081356001600160401b0381111561217457600080fd5b61218084828501611e8c565b82525060208201356001600160401b0381111561219c57600080fd5b6121a884828501611e8c565b60208301525060406121bc84828501611e81565b60408301525060608201356001600160401b038111156121db57600080fd5b6121e784828501611e8c565b60608301525060806121fb84828501612508565b60808301525060a08201356001600160401b0381111561221a57600080fd5b61222684828501611e8c565b60a08301525060c061223a84828501611e81565b60c08301525092915050565b600060c0828403121561225857600080fd5b61226260c061371f565b905060006122708484612513565b82525060208201356001600160401b0381111561228c57600080fd5b61229884828501611e8c565b60208301525060408201356001600160401b038111156122b757600080fd5b6122c384828501611e8c565b60408301525060606122d784828501612508565b60608301525060808201356001600160401b038111156122f657600080fd5b61230284828501611e8c565b60808301525060a061231684828501611e81565b60a08301525092915050565b60006040828403121561233457600080fd5b61233e604061371f565b905081356001600160401b0381111561235657600080fd5b61236284828501611e8c565b825250602061237384848301612508565b60208301525092915050565b600060a0828403121561239157600080fd5b61239b60a061371f565b905081356001600160401b038111156123b357600080fd5b6123bf84828501611e8c565b82525060208201356001600160401b038111156123db57600080fd5b6123e784828501611d52565b60208301525060408201356001600160401b0381111561240657600080fd5b61241284828501611e06565b60408301525060608201356001600160401b0381111561243157600080fd5b61243d84828501611d52565b60608301525060808201356001600160401b0381111561245c57600080fd5b61246884828501611d52565b60808301525092915050565b60006060828403121561248657600080fd5b612490606061371f565b9050600061249e8484611e81565b82525060208201356001600160401b038111156124ba57600080fd5b6124c684828501611e8c565b60208301525060408201356001600160401b038111156124e557600080fd5b6124f184828501611e8c565b60408301525092915050565b803561057081613859565b803561057081613862565b80356105708161386b565b60006020828403121561253057600080fd5b6000611a728484611d47565b6000806020838503121561254f57600080fd5b82356001600160401b0381111561256557600080fd5b61257185828601611dbe565b92509250509250929050565b60008060006060848603121561259257600080fd5b600061259e8686611e76565b93505060208401356001600160401b038111156125ba57600080fd5b6125c686828701611e8c565b92505060406125d786828701611e81565b9150509250925092565b6000602082840312156125f357600080fd5b81356001600160401b0381111561260957600080fd5b611a7284828501611e8c565b60008060006060848603121561262a57600080fd5b83356001600160401b0381111561264057600080fd5b61264c86828701611e8c565b935050602061265d86828701611e81565b92505060408401356001600160401b0381111561267957600080fd5b6125d786828701611e8c565b60006020828403121561269757600080fd5b81356001600160401b038111156126ad57600080fd5b611a7284828501611edb565b6000602082840312156126cb57600080fd5b81356001600160401b038111156126e157600080fd5b611a7284828501612024565b6000602082840312156126ff57600080fd5b81356001600160401b0381111561271557600080fd5b611a7284828501612140565b60006020828403121561273357600080fd5b81356001600160401b0381111561274957600080fd5b611a7284828501612246565b60006020828403121561276757600080fd5b81356001600160401b0381111561277d57600080fd5b611a7284828501612322565b60006020828403121561279b57600080fd5b81356001600160401b038111156127b157600080fd5b611a728482850161237f565b6000602082840312156127cf57600080fd5b81356001600160401b038111156127e557600080fd5b611a7284828501612474565b60006020828403121561280357600080fd5b6000611a7284846124fd565b60006020828403121561282157600080fd5b6000611a728484612513565b60008060006060848603121561284257600080fd5b600061284e8686612513565b935050602061285f86828701611e81565b92505060406125d786828701611d3c565b600061102b8383612a9d565b600061288883836131b3565b50506105e00190565b600061289d838361328f565b505060c00190565b60006128b1838361339f565b505060a00190565b60006128c58383612a94565b505060200190565b6128d6816137a8565b82525050565b60006128e782613795565b6128f1818561379f565b9350836020820285016129038561378c565b8060005b8581101561293d57848403895281516129208582612870565b945061292b8361378c565b60209a909a0199925050600101612907565b5091979650505050505050565b600061295582613795565b61295f818561379f565b935061296a8361378c565b8060005b83811015612998578151612982888261287c565b975061298d8361378c565b92505060010161296e565b509495945050505050565b60006129ae82613795565b6129b8818561379f565b93506129c38361378c565b8060005b838110156129985781516129db8882612891565b97506129e68361378c565b9250506001016129c7565b6129fa81613799565b612a048184610df1565b9250612a0f82613792565b8060005b838110156107c5578151612a2787826128a5565b9650612a328361378c565b925050600101612a13565b6000612a4882613795565b612a52818561379f565b9350612a5d8361378c565b8060005b83811015612998578151612a7588826128b9565b9750612a808361378c565b925050600101612a61565b6128d6816137b3565b6128d681613792565b6000612aa882613795565b612ab2818561379f565b9350612ac28185602086016137fa565b612acb81613826565b9093019392505050565b6000612ae082613795565b612aea8185610df1565b9350612afa8185602086016137fa565b9290920192915050565b6128d6816137e3565b6000612b1a60348361379f565b7f626c6f636b4e756d2065786365656473206d61782073697a6520616c6c6f77658152736420696e20506c61736d614672616d65776f726b60601b602082015260400192915050565b6000612b7060228361379f565b7f7478496e6465782065786365656473207468652073697a65206f662075696e74815261189b60f11b602082015260400192915050565b6000612bb460208361379f565b7f496e7075742076616c7565206d757374206d61746368206d73672e76616c7565815260200192915050565b6000612bed60158361379f565b74084dedcc840e6d2f4ca40d2e640e8dede40d0d2ced605b1b815260200192915050565b6000612c1e60148361379f565b73092dcecc2d8d2c840deeae8e0eae840d2dcc8caf60631b815260200192915050565b6000612c4e60188361379f565b7f426f6e642073697a652063616e6e6f74206265207a65726f0000000000000000815260200192915050565b6000612c8760148361379f565b73426f6e642073697a6520697320746f6f206c6f7760601b815260200192915050565b6000612cb7601e8361379f565b7f43616c6c6572206164647265737320697320756e617574686f72697a65640000815260200192915050565b6000612cf060148361379f565b7324b73b30b634b210313637b1b590373ab6b132b960611b815260200192915050565b6000612d2060108361379f565b6f457869744964206f766572666c6f777360801b815260200192915050565b80516020830190610c508482612a94565b805161012080845260009190840190612d698282612a9d565b9150506020830151612d7e6020860182612a94565b5060408301518482036040860152612d968282612a9d565b9150506060830151612dab60608601826133fb565b5060808301518482036080860152612dc38282612a9d565b91505060a0830151612dd860a08601826133fb565b5060c0830151612deb60c0860182612a94565b5060e083015184820360e0860152612e038282612a9d565b915050610100830151848203610100860152612e1f8282612a9d565b95945050505050565b805161010080845260009190840190612e418282612a9d565b9150506020830151612e5660208601826133fb565b5060408301518482036040860152612e6e8282612a9d565b9150506060830151612e8360608601826133fb565b5060808301518482036080860152612e9b8282612a9d565b91505060a083015184820360a0860152612eb58282612a9d565b91505060c0830151612eca60c0860182612a94565b5060e083015161056c60e0860182612a94565b805160e080845260009190840190612ef58282612a9d565b91505060208301518482036020860152612f0f8282612a9d565b9150506040830151612f246040860182612a94565b5060608301518482036060860152612f3c8282612a9d565b9150506080830151612f5160808601826133fb565b5060a083015184820360a0860152612f698282612a9d565b91505060c083015161056c60c0860182612a94565b805160009060c0840190612f9285826133f2565b5060208301518482036020860152612faa8282612a9d565b91505060408301518482036040860152612fc48282612a9d565b9150506060830151612fd960608601826133fb565b5060808301518482036080860152612ff18282612a9d565b91505060a083015161056c60a0860182612a94565b805160608301906130178482612b04565b50602082015161302a6020850182612b04565b506040820151610c506040850182612a94565b8051604083019061304e8482612a94565b506020820151610c506020850182612a94565b805160c08301906130728482612b04565b5060208201516130856020850182612d3f565b5060408201516130986040850182612b04565b5060608201516130ab6060850182612a94565b5060808201516130be6080850182612a94565b5060a0820151610c5060a0850182612a94565b805160808301906130e28482612b04565b5060208201516130f56020850182612b04565b5060408201516131086040850182612b04565b506060820151610c506060850182612a94565b805160a083019061312c8482612b04565b50602082015161313f6020850182612d3f565b5060408201516131526040850182612b04565b5060608201516131656060850182612b04565b506080820151610c506080850182612a94565b805160c08301906131898482612b04565b50602082015161319c6020850182612b04565b5060408201516130986040850182612d3f565b9052565b80516105e08301906131c58482612a8b565b5060208201516131d86020850182613415565b5060408201516131eb6040850182612a94565b5060608201516131fe6060850182612a94565b50608082015161321160808501826129f1565b5060a08201516132256103008501826129f1565b5060c08201516132396105808501826128cd565b5060e082015161324d6105a0850182612a94565b50610100820151610c506105c0850182612a94565b805160408084526000919084019061327a8282612a9d565b915050602083015161056c60208601826133fb565b805160c08301906132a08482612a8b565b5060208201516132b36020850182612a94565b5060408201516132c66040850182612a94565b5060608201516130ab60608501826128cd565b805160a0808452600091908401906132f18282612a9d565b9150506020830151848203602086015261330b82826128dc565b915050604083015184820360408601526133258282612a3d565b9150506060830151848203606086015261333f82826128dc565b91505060808301518482036080860152612e1f82826128dc565b8051600090606084019061336d8582612a94565b50602083015184820360208601526133858282612a9d565b91505060408301518482036040860152612e1f8282612a9d565b805160a08301906133b08482612a94565b5060208201516133c360208501826128cd565b5060408201516133d660408501826128cd565b5060608201516131656060850182612a94565b6128d6816137b8565b6128d6816137cb565b6128d6816137c4565b6128d661341082613792565b613792565b6128d6816137d7565b600061342a8285612ad5565b91506134368284613404565b5060200192915050565b6020808252810161102b818461294a565b6020808252810161102b81846129a3565b60208082528101610dee81612b0d565b60208082528101610dee81612b63565b60208082528101610dee81612ba7565b60208082528101610dee81612be0565b60208082528101610dee81612c11565b60208082528101610dee81612c41565b60208082528101610dee81612c7a565b60208082528101610dee81612caa565b60208082528101610dee81612ce3565b60208082528101610dee81612d13565b60a081016135108286613006565b61351d60608301856131af565b8181036080830152612e1f8184612e28565b60e0810161353d8288613006565b61354a60608301876131af565b818103608083015261355c8186612a9d565b905061356b60a0830185612a94565b81810360c083015261357d8184612a9d565b979650505050505050565b60a081016135968286613006565b6135a360608301856131af565b8181036080830152612e1f8184612d50565b60a081016135c38286613006565b6135d060608301856131af565b8181036080830152612e1f8184612edd565b60a081016135f08286613006565b6135fd60608301856131af565b8181036080830152612e1f8184612f7e565b6080810161361d828661303d565b61362a60408301856131af565b611a7260608301846133f2565b61010081016136468286613061565b61365360c08301856131af565b81810360e0830152612e1f8184613262565b60e0810161367382876130d1565b61368060808301866131af565b61368d60a08301856133f2565b612e1f60c08301846128cd565b60e081016136a8828661311b565b6136b560a08301856131af565b81810360c0830152612e1f81846132d9565b61010081016136d68286613178565b6136e360c08301856131af565b81810360e0830152612e1f8184613359565b6020810161057082846133e9565b6020810161057082846133f2565b6020810161057082846133fb565b6040518181016001600160401b038111828210171561373d57600080fd5b604052919050565b60006001600160401b0382111561375b57600080fd5b5060209081020190565b60006001600160401b0382111561377b57600080fd5b506020601f91909101601f19160190565b60200190565b90565b5190565b50600490565b90815260200190565b6000610dee826137cb565b151590565b6001600160801b031690565b61ffff1690565b6001600160a01b031690565b6001600160401b031690565b6000610dee826137a8565b82818337506000910152565b60005b838110156138155781810151838201526020016137fd565b83811115610c505750506000910152565b601f01601f191690565b613839816137a8565b811461384457600080fd5b50565b613839816137b3565b61383981613792565b613839816137b8565b613839816137c4565b613839816137cb565b61387c611d0e565b506040805160a0810182526001600160801b03949094168452600060208501526780000000000000009084015261ffff91821660608401521660808201529056fea365627a7a723158209c00be5c05ba01aa62f0d0328e226c7eee7b07c7d18bf1f24a73b36e65a35a496c6578706572696d656e74616cf564736f6c634300050b00400000000000000000000000000d4c1222f5e839a911e2053860e45f18921d72ac00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000a5230d65bfab06d0520bc8ec18474b999e5413af000000000000000000000000890d4b9d3e20c9390845e2bf2ccdd77a5822ac23000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000008fc

Deployed Bytecode

0x6080604052600436106101815760003560e01c8063a0e403b1116100d1578063c170ecf51161008a578063df2933e211610064578063df2933e214610409578063e5bc60c714610429578063e83622981461043c578063fe32a1241461045c57610181565b8063c170ecf5146103b2578063c96e7c05146103c7578063cec9e1a7146103dc57610181565b8063a0e403b1146102fd578063a4a254411461031f578063b177ba2314610332578063b22d3e1414610352578063b3c2ec7614610372578063b9a3a28e1461039257610181565b80635a5285141161013e5780637702fa17116101185780637702fa17146102a65780637e2b2efe146102bb578063839c78f9146102d0578063905d6a99146102fd57610181565b80635a52851414610260578063684963511461027357806370e014621461029357610181565b80630ca5b67614610186578063163d7bc7146101bc5780632c3bad95146101de578063315fb7da146101fe57806336660de41461021e5780633f1214cf1461023e575b600080fd5b34801561019257600080fd5b506101a66101a136600461253c565b610471565b6040516101b39190613451565b60405180910390f35b3480156101c857600080fd5b506101dc6101d73660046127f1565b610576565b005b3480156101ea57600080fd5b506101dc6101f93660046126ed565b610679565b34801561020a57600080fd5b506101dc6102193660046127f1565b6107cd565b34801561022a57600080fd5b506101dc610239366004612615565b6108bb565b34801561024a57600080fd5b50610253610a15565b6040516101b391906136f5565b6101dc61026e366004612789565b610a7a565b34801561027f57600080fd5b506101dc61028e36600461282d565b610bfe565b6101dc6102a13660046127bd565b610c56565b3480156102b257600080fd5b50610253610d78565b3480156102c757600080fd5b50610253610dd8565b3480156102dc57600080fd5b506102f06102eb3660046125e1565b610de3565b6040516101b39190613703565b34801561030957600080fd5b50610312610df6565b6040516101b39190613711565b6101dc61032d366004612755565b610dfb565b34801561033e57600080fd5b506101dc61034d3660046127f1565b610f19565b34801561035e57600080fd5b506102f061036d36600461257d565b611007565b34801561037e57600080fd5b506101dc61038d36600461280f565b611032565b34801561039e57600080fd5b506101dc6103ad3660046126b9565b6110eb565b3480156103be57600080fd5b506102536111b8565b3480156103d357600080fd5b506102536111c3565b3480156103e857600080fd5b506103fc6103f736600461253c565b6111ce565b6040516101b39190613440565b34801561041557600080fd5b506101dc610424366004612721565b6113f7565b6101dc610437366004612755565b6114c4565b34801561044857600080fd5b506101dc610457366004612685565b6115e2565b34801561046857600080fd5b506102536116af565b606080838390506040519080825280602002602001820160405280156104b157816020015b61049e611c20565b8152602001906001900390816104965790505b50905060005b8381101561056c5760008585838181106104cd57fe5b90506020020160206104e2919081019061280f565b6001600160a01b0380821660009081526020818152604091829020825160c081018452815460ff161515815260018201549281019290925260028101549282019290925260038201549092166060830152600481015460808301526005015460a082015284519192509084908490811061055857fe5b6020908102919091010152506001016104b7565b5090505b92915050565b601060009054906101000a90046001600160a01b03166001600160a01b0316634b0a72bc6040518163ffffffff1660e01b815260040160206040518083038186803b1580156105c457600080fd5b505afa1580156105d8573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052506105fc919081019061251e565b336001600160a01b0382161461062d5760405162461bcd60e51b8152600401610624906134d2565b60405180910390fd5b61063e600e8363ffffffff61170f16565b7fd21ccbbae3d29826d53310efdc993c64e27496dd31694b292f1a120344ec37ab8260405161066d91906136f5565b60405180910390a15050565b603060009054906101000a90046001600160a01b0316806001600160a01b031663ff27b1896040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156106ca57600080fd5b505af11580156106de573d6000803e3d6000fd5b5050604080516060810182526023546001600160a01b0390811682526024541660208201526025548183015290516359cff02160e01b8152737a8c0d7f1e6dbe36ab3a9ade0c44a0b868bb703f93506359cff0219250610746919060119087906004016135b5565b60006040518083038186803b15801561075e57600080fd5b505af4158015610772573d6000803e3d6000fd5b50505050806001600160a01b0316634e0f74366040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156107b157600080fd5b505af11580156107c5573d6000803e3d6000fd5b505050505050565b603060009054906101000a90046001600160a01b03166001600160a01b0316634b0a72bc6040518163ffffffff1660e01b815260040160206040518083038186803b15801561081b57600080fd5b505afa15801561082f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610853919081019061251e565b336001600160a01b0382161461087b5760405162461bcd60e51b8152600401610624906134d2565b61088c602e8363ffffffff61170f16565b7f30ce291291dca42b8168ab211fafc36d3d4868292ed3259874ed00864432e20e8260405161066d91906136f5565b603060009054906101000a90046001600160a01b0316806001600160a01b031663ff27b1896040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561090c57600080fd5b505af1158015610920573d6000803e3d6000fd5b505060408051606081018252601d546001600160a01b039081168252601e54166020820152601f54818301529051630c27711f60e11b8152739e3108fb11caeda64e264b2953a0eda81cf1a650935063184ee23e925061098c919060119089908990899060040161352f565b60006040518083038186803b1580156109a457600080fd5b505af41580156109b8573d6000803e3d6000fd5b50505050806001600160a01b0316634e0f74366040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156109f757600080fd5b505af1158015610a0b573d6000803e3d6000fd5b5050505050505050565b6040805160a081018252602e546001600160801b038082168352600160801b9182900481166020840152602f549081169383019390935261ffff90830481166060830152600160901b9092049091166080820152600090610a75906117fd565b905090565b603060009054906101000a90046001600160a01b0316806001600160a01b031663ff27b1896040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610acb57600080fd5b505af1158015610adf573d6000803e3d6000fd5b50505050610aeb610d78565b6001600160801b0316803414610b135760405162461bcd60e51b815260040161062490613482565b6040805160a0810182526012546001600160a01b039081168252825160208181018552601354825283015260145481168284015260155416606082015260165460808201529051631ff4513b60e01b815273081d7b167a94e7421ea5d0016c3d01e0cff6b55791631ff4513b91610b929190601190889060040161369a565b60006040518083038186803b158015610baa57600080fd5b505af4158015610bbe573d6000803e3d6000fd5b5050505050806001600160a01b0316634e0f74366040518163ffffffff1660e01b8152600401600060405180830381600087803b1580156107b157600080fd5b6031546001600160a01b0316338114610c295760405162461bcd60e51b8152600401610624906134d2565b610c3284611827565b15610c4657610c41848361184d565b610c50565b610c5084836118e9565b50505050565b601060009054906101000a90046001600160a01b0316806001600160a01b031663ff27b1896040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610ca757600080fd5b505af1158015610cbb573d6000803e3d6000fd5b50505050610cc76116af565b6001600160801b0316803414610cef5760405162461bcd60e51b815260040161062490613482565b6040805160c0810182526001546001600160a01b0390811682526002541660208083019190915282519081018352600354815281830152600480546060830152600554608083015260065460a083015291516332c812a760e11b815273f38380bbf08961123960fad630a060990684975192636590254e92610b929290916000918991016136c7565b6040805160a081018252602c546001600160801b038082168352600160801b9182900481166020840152602d549081169383019390935261ffff90830481166060830152600160901b9092049091166080820152600090610a75906117fd565b666379da05b6000081565b6000610dee82611959565b90505b919050565b600281565b603060009054906101000a90046001600160a01b0316806001600160a01b031663ff27b1896040518163ffffffff1660e01b8152600401600060405180830381600087803b158015610e4c57600080fd5b505af1158015610e60573d6000803e3d6000fd5b50505050610e6c610a15565b6001600160801b0316803414610e945760405162461bcd60e51b815260040161062490613482565b6040805160c0810182526017546001600160a01b03908116825282516020818101855260185482528301526019541681830152601a546060820152601b546080820152601c5460a0820152905163082153e960e21b8152735d3ee50e31293b45a7eb8b864c0b015e169ac7d8916320854fa491610b9291906011908890600401613637565b603060009054906101000a90046001600160a01b03166001600160a01b0316634b0a72bc6040518163ffffffff1660e01b815260040160206040518083038186803b158015610f6757600080fd5b505afa158015610f7b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250610f9f919081019061251e565b336001600160a01b03821614610fc75760405162461bcd60e51b8152600401610624906134d2565b610fd8602c8363ffffffff61170f16565b7f63ccac61f03626a0e717e96da239ff8996745b6c4ddcaffdedc88d7ef938f5ec8260405161066d91906136f5565b6000611011611c55565b61101a83611977565b9050611027858583611a0a565b9150505b9392505050565b603060009054906101000a90046001600160a01b0316806001600160a01b031663ff27b1896040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561108357600080fd5b505af1158015611097573d6000803e3d6000fd5b505060408051808201825260265481526027546020820152905163b1cf0fed60e01b8152734f05855b6df026726037500d10d91652b5c9e784935063b1cf0fed92506107469190601190879060040161360f565b603060009054906101000a90046001600160a01b0316806001600160a01b031663ff27b1896040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561113c57600080fd5b505af1158015611150573d6000803e3d6000fd5b505060408051606081018252602080546001600160a01b0390811683526021541690820152602254818301529051634bb4a4df60e11b815273ef6133d149460c9b79e132517934f77f1e62b23e935063976949be925061074691906011908790600401613502565b6631bced02db000081565b6683734dd0b0800081565b6060808383905060405190808252806020026020018201604052801561120e57816020015b6111fb611c75565b8152602001906001900390816111f35790505b50905060005b8381101561056c57600085858381811061122a57fe5b905060200201602061123f919081019061280f565b6001600160a01b0381166000908152601160209081526040808320815161012081018352815460ff81161515825261010090046001600160401b03169381019390935260018101548383015260028101546060840152815160808082019093529495509193919290840191906003840190600490835b8282101561131c576040805160a081018252600584028601805482526001808201546001600160a01b0390811660208086019190915260028401549091169484019490945260038201546060840152600490910154608083015290835290920191016112b5565b5050509082525060408051608081019091526020909101906017830160046000835b828210156113a5576040805160a081018252600584028601805482526001808201546001600160a01b03908116602080860191909152600284015490911694840194909452600382015460608401526004909101546080830152908352909201910161133e565b50505090825250602b8201546001600160a01b03166020820152602c8201546040820152602d9091015460609091015283518490849081106113e357fe5b602090810291909101015250600101611214565b601060009054906101000a90046001600160a01b0316806001600160a01b031663ff27b1896040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561144857600080fd5b505af115801561145c573d6000803e3d6000fd5b505060408051606081018252600b546001600160a01b039081168252600c54166020820152600d5481830152905163edc91d4b60e01b81527324c0a84090135ad04f257c85e10db6b4a74e0738935063edc91d4b9250610746919060009087906004016135e2565b603060009054906101000a90046001600160a01b0316806001600160a01b031663ff27b1896040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561151557600080fd5b505af1158015611529573d6000803e3d6000fd5b50505050611535610a15565b6001600160801b031680341461155d5760405162461bcd60e51b815260040161062490613482565b6040805160c0810182526017546001600160a01b03908116825282516020818101855260185482528301526019541681830152601a546060820152601b546080820152601c5460a08201529051631845801f60e11b8152735d3ee50e31293b45a7eb8b864c0b015e169ac7d89163308b003e91610b9291906011908890600401613637565b603060009054906101000a90046001600160a01b0316806001600160a01b031663ff27b1896040518163ffffffff1660e01b8152600401600060405180830381600087803b15801561163357600080fd5b505af1158015611647573d6000803e3d6000fd5b505060408051606081018252601d546001600160a01b039081168252601e54166020820152601f54818301529051631287d7e160e31b8152739e3108fb11caeda64e264b2953a0eda81cf1a650935063943ebf08925061074691906011908790600401613588565b6040805160a081018252600e546001600160801b038082168352600160801b9182900481166020840152600f549081169383019390935261ffff90830481166060830152600160901b9092049091166080820152600090610a75906117fd565b6040805160a08101825283546001600160801b038082168352600160801b918290048116602084015260018601549081169383019390935261ffff90830481166060830152600160901b909204909116608082015261176e9082611a7a565b8154600160801b90046001600160801b03161580159061179b575060018201546001600160801b03164210155b156117c2578154600160801b81046001600160801b03166001600160801b03199091161782555b81546001600160801b03918216600160801b02911617815560010180546001600160801b0319166001600160401b03426202a3000116179055565b600081604001516001600160801b031642101561181c57508051610df1565b506020810151610df1565b60006118436001600160a01b038316609763ffffffff611b3d16565b60ff161592915050565b604080516080810182526007546001600160a01b039081168252600854811660208301526009541681830152600a54606082015290516373c97b6d60e11b8152735e84df30ce17a9ac34e5474fc37a9c22674545189163e792f6da916118bd919060009087908790600401613665565b60006040518083038186803b1580156118d557600080fd5b505af41580156107c5573d6000803e3d6000fd5b604080516080810182526028546001600160a01b03908116825260295481166020830152602a541681830152602b5460608201529051632309cb3d60e01b81527367c3e5524dbe05b54fe08c3d4af65c273b87e63091632309cb3d916118bd919060119087908790600401613665565b80516020820120600090610dee9060691c609763ffffffff611b4716565b61197f611c55565b633b9aca00808304906127109084068190049084066429f16b11c68311156119b95760405162461bcd60e51b815260040161062490613462565b61ffff8211156119db5760405162461bcd60e51b815260040161062490613472565b604080516060810182526001600160401b03909416845261ffff92831660208501529116908201529050919050565b60008315611a5d57600083611a1e84611b54565b604051602001611a2f92919061341e565b604051602081830303815290604052805190602001209050611a55818460400151611be3565b91505061102b565b611a7283805190602001208360400151611be3565b949350505050565b6000611a85836117fd565b90506000826001600160801b031611611ab05760405162461bcd60e51b8152600401610624906134b2565b826060015161ffff16816001600160801b031681611aca57fe5b046001600160801b0316826001600160801b03161015611afc5760405162461bcd60e51b8152600401610624906134c2565b826080015161ffff16816001600160801b031602826001600160801b03161115611b385760405162461bcd60e51b815260040161062490613492565b505050565b60ff161c60011690565b600160ff919091161b1790565b6000600161271003826040015161ffff161115611b835760405162461bcd60e51b8152600401610624906134a2565b81516429f16b11c66001600160401b039091161115611bb45760405162461bcd60e51b8152600401610624906134e2565b506040810151602082015182516001600160401b0316633b9aca000261ffff9182166127100201911601919050565b6000606983901c61ffff60981b609884901b1617806001600160a01b0381168114611a725760405162461bcd60e51b8152600401610624906134f2565b6040805160c081018252600080825260208201819052918101829052606081018290526080810182905260a081019190915290565b604080516060810182526000808252602082018190529181019190915290565b60405180610120016040528060001515815260200160006001600160401b031681526020016000815260200160008152602001611cb0611ce1565b8152602001611cbd611ce1565b815260200160006001600160a01b0316815260200160008152602001600081525090565b60405180608001604052806004905b611cf8611d0e565b815260200190600190039081611cf05790505090565b6040805160a08101825260008082526020820181905291810182905260608101829052608081019190915290565b803561057081613830565b805161057081613830565b600082601f830112611d6357600080fd5b8135611d76611d7182613745565b61371f565b81815260209384019390925082018360005b83811015611db45781358601611d9e8882611e8c565b8452506020928301929190910190600101611d88565b5050505092915050565b60008083601f840112611dd057600080fd5b5081356001600160401b03811115611de757600080fd5b602083019150836020820283011115611dff57600080fd5b9250929050565b600082601f830112611e1757600080fd5b8135611e25611d7182613745565b91508181835260208401935060208101905083856020840282011115611e4a57600080fd5b60005b83811015611db45781611e608882611e81565b8452506020928301929190910190600101611e4d565b803561057081613847565b803561057081613850565b600082601f830112611e9d57600080fd5b8135611eab611d7182613765565b91508082526020830160208301858383011115611ec757600080fd5b611ed28382846137ee565b50505092915050565b60006101208284031215611eee57600080fd5b611ef961012061371f565b905081356001600160401b03811115611f1157600080fd5b611f1d84828501611e8c565b8252506020611f2e84848301611e81565b60208301525060408201356001600160401b03811115611f4d57600080fd5b611f5984828501611e8c565b6040830152506060611f6d84828501612508565b60608301525060808201356001600160401b03811115611f8c57600080fd5b611f9884828501611e8c565b60808301525060a0611fac84828501612508565b60a08301525060c0611fc084828501611e81565b60c08301525060e08201356001600160401b03811115611fdf57600080fd5b611feb84828501611e8c565b60e0830152506101008201356001600160401b0381111561200b57600080fd5b61201784828501611e8c565b6101008301525092915050565b6000610100828403121561203757600080fd5b61204261010061371f565b905081356001600160401b0381111561205a57600080fd5b61206684828501611e8c565b825250602061207784848301612508565b60208301525060408201356001600160401b0381111561209657600080fd5b6120a284828501611e8c565b60408301525060606120b684828501612508565b60608301525060808201356001600160401b038111156120d557600080fd5b6120e184828501611e8c565b60808301525060a08201356001600160401b0381111561210057600080fd5b61210c84828501611e8c565b60a08301525060c061212084828501611e81565b60c08301525060e061213484828501611e81565b60e08301525092915050565b600060e0828403121561215257600080fd5b61215c60e061371f565b905081356001600160401b0381111561217457600080fd5b61218084828501611e8c565b82525060208201356001600160401b0381111561219c57600080fd5b6121a884828501611e8c565b60208301525060406121bc84828501611e81565b60408301525060608201356001600160401b038111156121db57600080fd5b6121e784828501611e8c565b60608301525060806121fb84828501612508565b60808301525060a08201356001600160401b0381111561221a57600080fd5b61222684828501611e8c565b60a08301525060c061223a84828501611e81565b60c08301525092915050565b600060c0828403121561225857600080fd5b61226260c061371f565b905060006122708484612513565b82525060208201356001600160401b0381111561228c57600080fd5b61229884828501611e8c565b60208301525060408201356001600160401b038111156122b757600080fd5b6122c384828501611e8c565b60408301525060606122d784828501612508565b60608301525060808201356001600160401b038111156122f657600080fd5b61230284828501611e8c565b60808301525060a061231684828501611e81565b60a08301525092915050565b60006040828403121561233457600080fd5b61233e604061371f565b905081356001600160401b0381111561235657600080fd5b61236284828501611e8c565b825250602061237384848301612508565b60208301525092915050565b600060a0828403121561239157600080fd5b61239b60a061371f565b905081356001600160401b038111156123b357600080fd5b6123bf84828501611e8c565b82525060208201356001600160401b038111156123db57600080fd5b6123e784828501611d52565b60208301525060408201356001600160401b0381111561240657600080fd5b61241284828501611e06565b60408301525060608201356001600160401b0381111561243157600080fd5b61243d84828501611d52565b60608301525060808201356001600160401b0381111561245c57600080fd5b61246884828501611d52565b60808301525092915050565b60006060828403121561248657600080fd5b612490606061371f565b9050600061249e8484611e81565b82525060208201356001600160401b038111156124ba57600080fd5b6124c684828501611e8c565b60208301525060408201356001600160401b038111156124e557600080fd5b6124f184828501611e8c565b60408301525092915050565b803561057081613859565b803561057081613862565b80356105708161386b565b60006020828403121561253057600080fd5b6000611a728484611d47565b6000806020838503121561254f57600080fd5b82356001600160401b0381111561256557600080fd5b61257185828601611dbe565b92509250509250929050565b60008060006060848603121561259257600080fd5b600061259e8686611e76565b93505060208401356001600160401b038111156125ba57600080fd5b6125c686828701611e8c565b92505060406125d786828701611e81565b9150509250925092565b6000602082840312156125f357600080fd5b81356001600160401b0381111561260957600080fd5b611a7284828501611e8c565b60008060006060848603121561262a57600080fd5b83356001600160401b0381111561264057600080fd5b61264c86828701611e8c565b935050602061265d86828701611e81565b92505060408401356001600160401b0381111561267957600080fd5b6125d786828701611e8c565b60006020828403121561269757600080fd5b81356001600160401b038111156126ad57600080fd5b611a7284828501611edb565b6000602082840312156126cb57600080fd5b81356001600160401b038111156126e157600080fd5b611a7284828501612024565b6000602082840312156126ff57600080fd5b81356001600160401b0381111561271557600080fd5b611a7284828501612140565b60006020828403121561273357600080fd5b81356001600160401b0381111561274957600080fd5b611a7284828501612246565b60006020828403121561276757600080fd5b81356001600160401b0381111561277d57600080fd5b611a7284828501612322565b60006020828403121561279b57600080fd5b81356001600160401b038111156127b157600080fd5b611a728482850161237f565b6000602082840312156127cf57600080fd5b81356001600160401b038111156127e557600080fd5b611a7284828501612474565b60006020828403121561280357600080fd5b6000611a7284846124fd565b60006020828403121561282157600080fd5b6000611a728484612513565b60008060006060848603121561284257600080fd5b600061284e8686612513565b935050602061285f86828701611e81565b92505060406125d786828701611d3c565b600061102b8383612a9d565b600061288883836131b3565b50506105e00190565b600061289d838361328f565b505060c00190565b60006128b1838361339f565b505060a00190565b60006128c58383612a94565b505060200190565b6128d6816137a8565b82525050565b60006128e782613795565b6128f1818561379f565b9350836020820285016129038561378c565b8060005b8581101561293d57848403895281516129208582612870565b945061292b8361378c565b60209a909a0199925050600101612907565b5091979650505050505050565b600061295582613795565b61295f818561379f565b935061296a8361378c565b8060005b83811015612998578151612982888261287c565b975061298d8361378c565b92505060010161296e565b509495945050505050565b60006129ae82613795565b6129b8818561379f565b93506129c38361378c565b8060005b838110156129985781516129db8882612891565b97506129e68361378c565b9250506001016129c7565b6129fa81613799565b612a048184610df1565b9250612a0f82613792565b8060005b838110156107c5578151612a2787826128a5565b9650612a328361378c565b925050600101612a13565b6000612a4882613795565b612a52818561379f565b9350612a5d8361378c565b8060005b83811015612998578151612a7588826128b9565b9750612a808361378c565b925050600101612a61565b6128d6816137b3565b6128d681613792565b6000612aa882613795565b612ab2818561379f565b9350612ac28185602086016137fa565b612acb81613826565b9093019392505050565b6000612ae082613795565b612aea8185610df1565b9350612afa8185602086016137fa565b9290920192915050565b6128d6816137e3565b6000612b1a60348361379f565b7f626c6f636b4e756d2065786365656473206d61782073697a6520616c6c6f77658152736420696e20506c61736d614672616d65776f726b60601b602082015260400192915050565b6000612b7060228361379f565b7f7478496e6465782065786365656473207468652073697a65206f662075696e74815261189b60f11b602082015260400192915050565b6000612bb460208361379f565b7f496e7075742076616c7565206d757374206d61746368206d73672e76616c7565815260200192915050565b6000612bed60158361379f565b74084dedcc840e6d2f4ca40d2e640e8dede40d0d2ced605b1b815260200192915050565b6000612c1e60148361379f565b73092dcecc2d8d2c840deeae8e0eae840d2dcc8caf60631b815260200192915050565b6000612c4e60188361379f565b7f426f6e642073697a652063616e6e6f74206265207a65726f0000000000000000815260200192915050565b6000612c8760148361379f565b73426f6e642073697a6520697320746f6f206c6f7760601b815260200192915050565b6000612cb7601e8361379f565b7f43616c6c6572206164647265737320697320756e617574686f72697a65640000815260200192915050565b6000612cf060148361379f565b7324b73b30b634b210313637b1b590373ab6b132b960611b815260200192915050565b6000612d2060108361379f565b6f457869744964206f766572666c6f777360801b815260200192915050565b80516020830190610c508482612a94565b805161012080845260009190840190612d698282612a9d565b9150506020830151612d7e6020860182612a94565b5060408301518482036040860152612d968282612a9d565b9150506060830151612dab60608601826133fb565b5060808301518482036080860152612dc38282612a9d565b91505060a0830151612dd860a08601826133fb565b5060c0830151612deb60c0860182612a94565b5060e083015184820360e0860152612e038282612a9d565b915050610100830151848203610100860152612e1f8282612a9d565b95945050505050565b805161010080845260009190840190612e418282612a9d565b9150506020830151612e5660208601826133fb565b5060408301518482036040860152612e6e8282612a9d565b9150506060830151612e8360608601826133fb565b5060808301518482036080860152612e9b8282612a9d565b91505060a083015184820360a0860152612eb58282612a9d565b91505060c0830151612eca60c0860182612a94565b5060e083015161056c60e0860182612a94565b805160e080845260009190840190612ef58282612a9d565b91505060208301518482036020860152612f0f8282612a9d565b9150506040830151612f246040860182612a94565b5060608301518482036060860152612f3c8282612a9d565b9150506080830151612f5160808601826133fb565b5060a083015184820360a0860152612f698282612a9d565b91505060c083015161056c60c0860182612a94565b805160009060c0840190612f9285826133f2565b5060208301518482036020860152612faa8282612a9d565b91505060408301518482036040860152612fc48282612a9d565b9150506060830151612fd960608601826133fb565b5060808301518482036080860152612ff18282612a9d565b91505060a083015161056c60a0860182612a94565b805160608301906130178482612b04565b50602082015161302a6020850182612b04565b506040820151610c506040850182612a94565b8051604083019061304e8482612a94565b506020820151610c506020850182612a94565b805160c08301906130728482612b04565b5060208201516130856020850182612d3f565b5060408201516130986040850182612b04565b5060608201516130ab6060850182612a94565b5060808201516130be6080850182612a94565b5060a0820151610c5060a0850182612a94565b805160808301906130e28482612b04565b5060208201516130f56020850182612b04565b5060408201516131086040850182612b04565b506060820151610c506060850182612a94565b805160a083019061312c8482612b04565b50602082015161313f6020850182612d3f565b5060408201516131526040850182612b04565b5060608201516131656060850182612b04565b506080820151610c506080850182612a94565b805160c08301906131898482612b04565b50602082015161319c6020850182612b04565b5060408201516130986040850182612d3f565b9052565b80516105e08301906131c58482612a8b565b5060208201516131d86020850182613415565b5060408201516131eb6040850182612a94565b5060608201516131fe6060850182612a94565b50608082015161321160808501826129f1565b5060a08201516132256103008501826129f1565b5060c08201516132396105808501826128cd565b5060e082015161324d6105a0850182612a94565b50610100820151610c506105c0850182612a94565b805160408084526000919084019061327a8282612a9d565b915050602083015161056c60208601826133fb565b805160c08301906132a08482612a8b565b5060208201516132b36020850182612a94565b5060408201516132c66040850182612a94565b5060608201516130ab60608501826128cd565b805160a0808452600091908401906132f18282612a9d565b9150506020830151848203602086015261330b82826128dc565b915050604083015184820360408601526133258282612a3d565b9150506060830151848203606086015261333f82826128dc565b91505060808301518482036080860152612e1f82826128dc565b8051600090606084019061336d8582612a94565b50602083015184820360208601526133858282612a9d565b91505060408301518482036040860152612e1f8282612a9d565b805160a08301906133b08482612a94565b5060208201516133c360208501826128cd565b5060408201516133d660408501826128cd565b5060608201516131656060850182612a94565b6128d6816137b8565b6128d6816137cb565b6128d6816137c4565b6128d661341082613792565b613792565b6128d6816137d7565b600061342a8285612ad5565b91506134368284613404565b5060200192915050565b6020808252810161102b818461294a565b6020808252810161102b81846129a3565b60208082528101610dee81612b0d565b60208082528101610dee81612b63565b60208082528101610dee81612ba7565b60208082528101610dee81612be0565b60208082528101610dee81612c11565b60208082528101610dee81612c41565b60208082528101610dee81612c7a565b60208082528101610dee81612caa565b60208082528101610dee81612ce3565b60208082528101610dee81612d13565b60a081016135108286613006565b61351d60608301856131af565b8181036080830152612e1f8184612e28565b60e0810161353d8288613006565b61354a60608301876131af565b818103608083015261355c8186612a9d565b905061356b60a0830185612a94565b81810360c083015261357d8184612a9d565b979650505050505050565b60a081016135968286613006565b6135a360608301856131af565b8181036080830152612e1f8184612d50565b60a081016135c38286613006565b6135d060608301856131af565b8181036080830152612e1f8184612edd565b60a081016135f08286613006565b6135fd60608301856131af565b8181036080830152612e1f8184612f7e565b6080810161361d828661303d565b61362a60408301856131af565b611a7260608301846133f2565b61010081016136468286613061565b61365360c08301856131af565b81810360e0830152612e1f8184613262565b60e0810161367382876130d1565b61368060808301866131af565b61368d60a08301856133f2565b612e1f60c08301846128cd565b60e081016136a8828661311b565b6136b560a08301856131af565b81810360c0830152612e1f81846132d9565b61010081016136d68286613178565b6136e360c08301856131af565b81810360e0830152612e1f8184613359565b6020810161057082846133e9565b6020810161057082846133f2565b6020810161057082846133fb565b6040518181016001600160401b038111828210171561373d57600080fd5b604052919050565b60006001600160401b0382111561375b57600080fd5b5060209081020190565b60006001600160401b0382111561377b57600080fd5b506020601f91909101601f19160190565b60200190565b90565b5190565b50600490565b90815260200190565b6000610dee826137cb565b151590565b6001600160801b031690565b61ffff1690565b6001600160a01b031690565b6001600160401b031690565b6000610dee826137a8565b82818337506000910152565b60005b838110156138155781810151838201526020016137fd565b83811115610c505750506000910152565b601f01601f191690565b613839816137a8565b811461384457600080fd5b50565b613839816137b3565b61383981613792565b613839816137b8565b613839816137c4565b613839816137cb565b61387c611d0e565b506040805160a0810182526001600160801b03949094168452600060208501526780000000000000009084015261ffff91821660608401521660808201529056fea365627a7a723158209c00be5c05ba01aa62f0d0328e226c7eee7b07c7d18bf1f24a73b36e65a35a496c6578706572696d656e74616cf564736f6c634300050b0040

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

0000000000000000000000000d4c1222f5e839a911e2053860e45f18921d72ac00000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002000000000000000000000000a5230d65bfab06d0520bc8ec18474b999e5413af000000000000000000000000890d4b9d3e20c9390845e2bf2ccdd77a5822ac23000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000008fc

-----Decoded View---------------
Arg [0] : args (tuple): System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput]

-----Encoded View---------------
7 Constructor Arguments found :
Arg [0] : 0000000000000000000000000d4c1222f5e839a911e2053860e45f18921d72ac
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000002
Arg [3] : 000000000000000000000000a5230d65bfab06d0520bc8ec18474b999e5413af
Arg [4] : 000000000000000000000000890d4b9d3e20c9390845e2bf2ccdd77a5822ac23
Arg [5] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [6] : 00000000000000000000000000000000000000000000000000000000000008fc


Deployed Bytecode Sourcemap

505:1863:48:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3713:419:64;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;3713:419:64;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;4484:222;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;4484:222:64;;;;;;;;:::i;:::-;;10816:231:62;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;10816:231:62;;;;;;;;:::i;12946:203::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;12946:203:62;;;;;;;;:::i;9895:332::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;9895:332:62;;;;;;;;:::i;12689:107::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;12689:107:62;;;:::i;:::-;;;;;;;;7609:264;;;;;;;;;:::i;1409:332:48:-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;1409:332:48;;;;;;;;:::i;4811:295:64:-;;;;;;;;;:::i;12162:105:62:-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;12162:105:62;;;:::i;2055:68::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;2055:68:62;;;:::i;2200:166:48:-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;2200:166:48;;;;;;;;:::i;:::-;;;;;;;;2233:51:62;;8:9:-1;5:2;;;30:1;27;20:12;5:2;2233:51:62;;;:::i;:::-;;;;;;;;8689:327;;;;;;;;;:::i;12423:195::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;12423:195:62;;;;;;;;:::i;1826:288:48:-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;1826:288:48;;;;;;;;:::i;11467:166:62:-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;11467:166:62;;;;;;;;:::i;10406:232::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;10406:232:62;;;;;;;;:::i;1296:65:64:-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;1296:65:64;;;:::i;1855:69:62:-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;1855:69:62;;;:::i;7007:420::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;7007:420:62;;;;;;;;:::i;:::-;;;;;;;;5209:226:64;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;5209:226:64;;;;;;;;:::i;8120:324:62:-;;;;;;;;;:::i;9198:240::-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;-1:-1;9198:240:62;;;;;;;;:::i;4207:123:64:-;;8:9:-1;5:2;;;30:1;27;20:12;5:2;4207:123:64;;;:::i;3713:419::-;3787:42;3841:48;3932:7;;:14;;3892:55;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;-1:-1:-1;3841:106:64;-1:-1:-1;3962:6:64;3957:147;3974:18;;;3957:147;;;4012:14;4029:7;;4037:1;4029:10;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;4064:29:64;;;:15;:29;;;;;;;;;;;;4053:40;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:8;;4012:27;;-1:-1:-1;4053:40:64;:5;;4059:1;;4053:8;;;;;;;;;;;;;;;:40;-1:-1:-1;3994:3:64;;3957:147;;;-1:-1:-1;4120:5:64;-1:-1:-1;3713:419:64;;;;;:::o;4484:222::-;4562:9;;;;;;;;;-1:-1:-1;;;;;4562:9:64;-1:-1:-1;;;;;4562:23:64;;:25;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;4562:25:64;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;4562:25:64;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;4562:25:64;;;;;;;;;109:10:91;-1:-1:-1;;;;;109:20:91;;;101:63;;;;-1:-1:-1;;;101:63:91;;;;;;;;;;;;;;;;;4599:49:64;:21;4636:11;4599:49;:36;:49;:::i;:::-;4663:36;4687:11;4663:36;;;;;;;;;;;;;;;4484:222;;:::o;10816:231:62:-;10958:9;;;;;;;;;-1:-1:-1;;;;;10958:9:62;462:18:89;-1:-1:-1;;;;;462:39:89;;:41;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;462:41:89;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;10983:34:62;;;;;;;;:30;:34;-1:-1:-1;;;;;10983:34:62;;;;;;;;;;;;;;;;;;:57;;-1:-1:-1;;;10983:57:62;;:34;;-1:-1:-1;10983:34:62;;-1:-1:-1;10983:57:62;;:34;11018:15;;11035:4;;10983:57;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;10983:57:62;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;10983:57:62;;;;524:18:89;-1:-1:-1;;;;;524:41:89;;:43;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;524:43:89;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;524:43:89;;;;10816:231:62;;:::o;12946:203::-;13016:9;;;;;;;;;-1:-1:-1;;;;;13016:9:62;-1:-1:-1;;;;;13016:23:62;;:25;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;13016:25:62;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;13016:25:62;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;13016:25:62;;;;;;;;;109:10:91;-1:-1:-1;;;;;109:20:91;;;101:63;;;;-1:-1:-1;;;101:63:91;;;;;;;;;13053:41:62;:13;13082:11;13053:41;:28;:41;:::i;:::-;13109:33;13130:11;13109:33;;;;;;;9895:332;10088:9;;;;;;;;;-1:-1:-1;;;;;10088:9:62;462:18:89;-1:-1:-1;;;;;462:39:89;;:41;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;462:41:89;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;10113:37:62;;;;;;;;:29;:37;-1:-1:-1;;;;;10113:37:62;;;;;;;;;;;;;;;;;;:107;;-1:-1:-1;;;10113:107:62;;:37;;-1:-1:-1;10113:37:62;;-1:-1:-1;10113:107:62;;:37;10151:15;;10168:10;;10180:13;;10195:24;;10113:107;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;10113:107:62;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;10113:107:62;;;;524:18:89;-1:-1:-1;;;;;524:41:89;;:43;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;524:43:89;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;524:43:89;;;;9895:332:62;;;;:::o;12689:107::-;12765:22;;;;;;;;:13;:22;-1:-1:-1;;;;;12765:22:62;;;;;-1:-1:-1;;;12765:22:62;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;12765:22:62;;;;;;;;;;12739:7;;12765:24;;:22;:24::i;:::-;12758:31;;12689:107;:::o;7609:264::-;7745:9;;;;;;;;;-1:-1:-1;;;;;7745:9:62;462:18:89;-1:-1:-1;;;;;462:39:89;;:41;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;462:41:89;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;462:41:89;;;;7778:18:62;:16;:18::i;:::-;-1:-1:-1;;;;;54:131:92;124:6;111:9;:19;103:64;;;;-1:-1:-1;;;103:64:92;;;;;;;;;7812:31:62;;;;;;;;:27;:31;-1:-1:-1;;;;;7812:31:62;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:54;;-1:-1:-1;;;7812:54:62;;:31;;;;:54;;:31;7844:15;;7861:4;;7812:31;:54;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;7812:54:62;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;7812:54:62;;;;513:1:89;524:18;-1:-1:-1;;;;;524:41:89;;:43;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;1409:332:48;1496:15;;-1:-1:-1;;;;;1496:15:48;109:10:91;:20;;101:63;;;;-1:-1:-1;;;101:63:91;;;;;;;;;1528:29:48;1550:6;1528:21;:29::i;:::-;1524:211;;;1573:60;1619:6;1627:5;1573:45;:60::i;:::-;1524:211;;;1664:60;1710:6;1718:5;1664:45;:60::i;:::-;1409:332;;;;:::o;4811:295:64:-;4969:9;;;;;;;;;-1:-1:-1;;;;;4969:9:64;462:18:89;-1:-1:-1;;;;;462:39:89;;:41;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;462:41:89;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;462:41:89;;;;5002:27:64;:25;:27::i;:::-;-1:-1:-1;;;;;54:131:92;124:6;111:9;:19;103:64;;;;-1:-1:-1;;;103:64:92;;;;;;;;;5045:31:64;;;;;;;;:27;:31;-1:-1:-1;;;;;5045:31:64;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:54;;-1:-1:-1;;;5045:54:64;;:31;;;;:54;;:31;;-1:-1:-1;;5094:4:64;;5045:54;;;12162:105:62;12237:21;;;;;;;;:12;:21;-1:-1:-1;;;;;12237:21:62;;;;;-1:-1:-1;;;12237:21:62;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;12237:21:62;;;;;;;;;;12211:7;;12237:23;;:21;:23::i;2055:68::-;2102:21;2055:68;:::o;2200:166:48:-;2295:7;2325:34;2350:8;2325:24;:34::i;:::-;2318:41;;2200:166;;;;:::o;2233:51:62:-;2283:1;2233:51;:::o;8689:327::-;8871:9;;;;;;;;;-1:-1:-1;;;;;8871:9:62;462:18:89;-1:-1:-1;;;;;462:39:89;;:41;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;462:41:89;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;462:41:89;;;;8904:19:62;:17;:19::i;:::-;-1:-1:-1;;;;;54:131:92;124:6;111:9;:19;103:64;;;;-1:-1:-1;;;103:64:92;;;;;;;;;8939:47:62;;;;;;;;:31;:47;-1:-1:-1;;;;;8939:47:62;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:70;;-1:-1:-1;;;8939:70:62;;:47;;;;:70;;:47;8987:15;;9004:4;;8939:47;:70;;;12423:195;12492:9;;;;;;;;;-1:-1:-1;;;;;12492:9:62;-1:-1:-1;;;;;12492:23:62;;:25;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;12492:25:62;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;12492:25:62;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;12492:25:62;;;;;;;;;109:10:91;-1:-1:-1;;;;;109:20:91;;;101:63;;;;-1:-1:-1;;;101:63:91;;;;;;;;;12529:40:62;:12;12557:11;12529:40;:27;:40;:::i;:::-;12584:27;12599:11;12584:27;;;;;;;1826:288:48;1956:7;1979:30;;:::i;:::-;2012:23;2026:8;2012:13;:23::i;:::-;1979:56;;2052:55;2077:10;2089:8;2099:7;2052:24;:55::i;:::-;2045:62;;;1826:288;;;;;;:::o;11467:166:62:-;11545:9;;;;;;;;;-1:-1:-1;;;;;11545:9:62;462:18:89;-1:-1:-1;;;;;462:39:89;;:41;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;462:41:89;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;11566:35:62;;;;;;;;:31;:35;;;;;;;;;:60;;-1:-1:-1;;;11566:60:62;;:35;;-1:-1:-1;11566:35:62;;-1:-1:-1;11566:60:62;;:35;11602:15;;11619:6;;11566:60;;;;10406:232;10550:9;;;;;;;;;-1:-1:-1;;;;;10550:9:62;462:18:89;-1:-1:-1;;;;;462:39:89;;:41;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;462:41:89;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;10575:33:62;;;;;;;;:29;:33;;-1:-1:-1;;;;;10575:33:62;;;;;;;;;;;;;;;;;;:56;;-1:-1:-1;;;10575:56:62;;:33;;-1:-1:-1;10575:33:62;;-1:-1:-1;10575:56:62;;:33;10609:15;;10626:4;;10575:56;;;;1296:65:64;1340:21;1296:65;:::o;1855:69:62:-;1903:21;1855:69;:::o;7007:420::-;7081:42;7135:48;7226:7;;:14;;7186:55;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;-1:-1:-1;7135:106:62;-1:-1:-1;7256:6:62;7251:148;7268:18;;;7251:148;;;7307:14;7324:7;;7332:1;7324:10;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;7359:29:62;;:21;:29;;;:15;:29;;;;;;;;7348:40;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;7348:40:62;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;7359:29;;-1:-1:-1;7348:40:62;;7359:29;;7348:40;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;7348:40:62;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;7348:40:62;;;-1:-1:-1;7348:40:62;;;;;;;;;;;;;;;;;;-1:-1:-1;7348:40:62;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;7348:40:62;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;7348:40:62;;;-1:-1:-1;7348:40:62;;;;-1:-1:-1;;;;;7348:40:62;;;;;;;;;;;;;;;;;;;;;;;:8;;:5;;7354:1;;7348:8;;;;;;;;;;;;;;;:40;-1:-1:-1;7288:3:62;;7251:148;;5209:226:64;5345:9;;;;;;;;;-1:-1:-1;;;;;5345:9:64;462:18:89;-1:-1:-1;;;;;462:39:89;;:41;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;462:41:89;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;5370:35:64;;;;;;;;:31;:35;-1:-1:-1;;;;;5370:35:64;;;;;;;;;;;;;;;;;;:58;;-1:-1:-1;;;5370:58:64;;:35;;-1:-1:-1;5370:35:64;;-1:-1:-1;5370:58:64;;:35;-1:-1:-1;;5423:4:64;;5370:58;;;;8120:324:62;8300:9;;;;;;;;;-1:-1:-1;;;;;8300:9:62;462:18:89;-1:-1:-1;;;;;462:39:89;;:41;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;462:41:89;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;462:41:89;;;;8333:19:62;:17;:19::i;:::-;-1:-1:-1;;;;;54:131:92;124:6;111:9;:19;103:64;;;;-1:-1:-1;;;103:64:92;;;;;;;;;8368:46:62;;;;;;;;:31;:46;-1:-1:-1;;;;;8368:46:62;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:69;;-1:-1:-1;;;8368:69:62;;:46;;;;:69;;:46;8415:15;;8432:4;;8368:46;:69;;;9198:240;9344:9;;;;;;;;;-1:-1:-1;;;;;9344:9:62;462:18:89;-1:-1:-1;;;;;462:39:89;;:41;;;;;;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;462:41:89;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;5:2;-1:-1;;9369:39:62;;;;;;;;:29;:39;-1:-1:-1;;;;;9369:39:62;;;;;;;;;;;;;;;;;;:62;;-1:-1:-1;;;9369:62:62;;:39;;-1:-1:-1;9369:39:62;;-1:-1:-1;9369:62:62;;:39;9409:15;;9426:4;;9369:62;;;;4207:123:64;4291:30;;;;;;;;:21;:30;-1:-1:-1;;;;;4291:30:64;;;;;-1:-1:-1;;;4291:30:64;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;4291:30:64;;;;;;;;;;4265:7;;4291:32;;:30;:32::i;2307:381:68:-;2392:35;;;;;;;;;;-1:-1:-1;;;;;2392:35:68;;;;;-1:-1:-1;;;2392:35:68;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;;2392:35:68;;;;;;;;;;;;2415:11;2392:16;:35::i;:::-;2442:20;;-1:-1:-1;;;2442:20:68;;-1:-1:-1;;;;;2442:20:68;:25;;;;:60;;-1:-1:-1;2478:24:68;;;;-1:-1:-1;;;;;2478:24:68;2471:3;:31;;2442:60;2438:135;;;2542:20;;-1:-1:-1;;;2542:20:68;;-1:-1:-1;;;;;2542:20:68;-1:-1:-1;;;;;;2518:44:68;;;;;;2438:135;2582:34;;-1:-1:-1;;;;;2582:34:68;;;-1:-1:-1;;;2582:34:68;;;;;;-1:-1:-1;2626:24:68;:55;;-1:-1:-1;;;;;;2626:55:68;-1:-1:-1;;;;;2660:3:68;598:6;2653:28;2626:55;;;;2307:381::o;2753:233::-;2814:7;2843:4;:24;;;-1:-1:-1;;;;;2837:30:68;:3;:30;2833:147;;;-1:-1:-1;2890:21:68;;2883:28;;2833:147;-1:-1:-1;2949:20:68;;;;2942:27;;281:118:69;345:4;368:19;-1:-1:-1;;;;;368:14:69;;383:3;368:19;:14;:19;:::i;:::-;:24;;;;281:118;-1:-1:-1;;281:118:69:o;5729:151:64:-;5808:33;;;;;;;;:29;:33;-1:-1:-1;;;;;5808:33:64;;;;;;;;;;;;;;;;;;;;;;;;;;:65;;-1:-1:-1;;;5808:65:64;;:33;;;;:65;;:33;-1:-1:-1;;5859:6:64;;5867:5;;5808:65;;;;;;;;;;;;;;;;8:9:-1;5:2;;;30:1;27;20:12;5:2;5808:65:64;;;;8:9:-1;5:2;;;45:16;42:1;39;24:38;77:16;74:1;67:27;11935:151:62;12014:33;;;;;;;;:29;:33;-1:-1:-1;;;;;12014:33:62;;;;;;;;;;;;;;;;;;;;;;;;;;:65;;-1:-1:-1;;;12014:65:62;;:33;;;;:65;;:33;12048:15;;12065:6;;12073:5;;12014:65;;;;1785:164:69;1901:19;;;;;;1858:7;;1892:49;;1925:3;1893:35;1937:3;1892:49;:44;:49;:::i;2150:491:93:-;2202:15;;:::i;:::-;410:10;2248:18;;;;464:5;2295:18;;;2294:32;;;;2364:15;;805:59;2399:25;;;2391:90;;;;-1:-1:-1;;;2391:90:93;;;;;;;;;666:11;2499:7;:23;;2491:70;;;;-1:-1:-1;;;2491:70:93;;;;;;;;;2578:56;;;;;;;;-1:-1:-1;;;;;2578:56:93;;;;;;;;;;;;;;;;;;;;-1:-1:-1;2150:491:93;;;:::o;1140:480:69:-;1317:7;1344:10;1340:191;;;1370:16;1416:8;1426:17;:8;:15;:17::i;:::-;1399:45;;;;;;;;;;;;;49:4:-1;39:7;30;26:21;22:32;13:7;6:49;1399:45:69;;;1389:56;;;;;;1370:75;;1466:54;1489:8;1499;:20;;;1466:22;:54::i;:::-;1459:61;;;;;1340:191;1548:65;1581:8;1571:19;;;;;;1592:8;:20;;;1548:22;:65::i;:::-;1541:72;1140:480;-1:-1:-1;;;;1140:480:69:o;2992:417:68:-;3082:23;3108:14;3117:4;3108:8;:14::i;:::-;3082:40;;3154:1;3140:11;-1:-1:-1;;;;;3140:15:68;;3132:52;;;;-1:-1:-1;;;3132:52:68;;;;;;;;;3235:4;:22;;;3217:40;;:15;-1:-1:-1;;;;;3217:40:68;;;;;;;-1:-1:-1;;;;;3202:55:68;:11;-1:-1:-1;;;;;3202:55:68;;;3194:88;;;;-1:-1:-1;;;3194:88:68;;;;;;;;;3351:4;:25;;;3324:52;;3332:15;-1:-1:-1;;;;;3324:24:68;:52;3308:11;-1:-1:-1;;;;;3300:20:68;:76;;3292:110;;;;-1:-1:-1;;;3292:110:68;;;;;;;;;2992:417;;;:::o;1134:150:88:-;1257:15;;;1275:1;1257:19;;1134:150::o;425:144::-;180:1;549:13;;;;;;541:21;;425:144::o;1698:315:93:-;1758:7;537:1;464:5;525:13;1785:3;:15;;;:35;;;;1777:68;;;;-1:-1:-1;;;1777:68:93;;;;;;;;;1863:12;;805:59;-1:-1:-1;;;;;1863:29:93;;;;;1855:62;;;;-1:-1:-1;;;1855:62:93;;;;;;;;;-1:-1:-1;1991:15:93;;;;1965:11;;;;1935:12;;-1:-1:-1;;;;;1935:27:93;410:10;1935:27;:71;1965:23;;;464:5;1965:23;1935:53;:71;;;1698:315;;;:::o;1955:373:69:-;2071:7;2132:3;2112:23;;;-1:-1:-1;;;2165:3:69;2140:28;;;;2111:58;;-1:-1:-1;;;;;2237:22:69;;:32;;2229:61;;;;-1:-1:-1;;;2229:61:69;;;;;;;;505:1863:48;;;;;;;;;-1:-1:-1;505:1863:48;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;-1:-1:-1;505:1863:48;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;;;;-1:-1:-1;;;;;505:1863:48;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;-1:-1:-1;;;;;505:1863:48;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;:::o;:::-;;;;;;;;;-1:-1:-1;505:1863:48;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;5:130:-1:-;72:20;;97:33;72:20;97:33;;142:134;220:13;;238:33;220:13;238:33;;299:685;;417:3;410:4;402:6;398:17;394:27;384:2;;435:1;432;425:12;384:2;472:6;459:20;494:81;509:65;567:6;509:65;;;494:81;;;603:21;;;647:4;635:17;;;;485:90;;-1:-1;660:14;;635:17;755:1;740:238;765:6;762:1;759:13;740:238;;;848:3;835:17;827:6;823:30;872:42;910:3;898:10;872:42;;;860:55;;-1:-1;938:4;929:14;;;;957;;;;;787:1;780:9;740:238;;;744:14;377:607;;;;;;;;1010:352;;;1140:3;1133:4;1125:6;1121:17;1117:27;1107:2;;1158:1;1155;1148:12;1107:2;-1:-1;1178:20;;-1:-1;;;;;1207:30;;1204:2;;;1250:1;1247;1240:12;1204:2;1284:4;1276:6;1272:17;1260:29;;1335:3;1327:4;1319:6;1315:17;1305:8;1301:32;1298:41;1295:2;;;1352:1;1349;1342:12;1295:2;1100:262;;;;;;1388:699;;1501:3;1494:4;1486:6;1482:17;1478:27;1468:2;;1519:1;1516;1509:12;1468:2;1556:6;1543:20;1578:76;1593:60;1646:6;1593:60;;1578:76;1569:85;;1671:5;1696:6;1689:5;1682:21;1726:4;1718:6;1714:17;1704:27;;1748:4;1743:3;1739:14;1732:21;;1801:6;1848:3;1840:4;1832:6;1828:17;1823:3;1819:27;1816:36;1813:2;;;1865:1;1862;1855:12;1813:2;1890:1;1875:206;1900:6;1897:1;1894:13;1875:206;;;1958:3;1980:37;2013:3;2001:10;1980:37;;;1968:50;;-1:-1;2041:4;2032:14;;;;2060;;;;;1922:1;1915:9;1875:206;;2095:124;2159:20;;2184:30;2159:20;2184:30;;2226:130;2293:20;;2318:33;2293:20;2318:33;;2364:432;;2461:3;2454:4;2446:6;2442:17;2438:27;2428:2;;2479:1;2476;2469:12;2428:2;2516:6;2503:20;2538:60;2553:44;2590:6;2553:44;;2538:60;2529:69;;2618:6;2611:5;2604:21;2654:4;2646:6;2642:17;2687:4;2680:5;2676:16;2722:3;2713:6;2708:3;2704:16;2701:25;2698:2;;;2739:1;2736;2729:12;2698:2;2749:41;2783:6;2778:3;2773;2749:41;;;2421:375;;;;;;;;3320:2054;;3451:5;3439:9;3434:3;3430:19;3426:31;3423:2;;;3470:1;3467;3460:12;3423:2;3488:21;3503:5;3488:21;;;3479:30;-1:-1;3562:31;;-1:-1;;;;;3602:30;;3599:2;;;3645:1;3642;3635:12;3599:2;3679:54;3729:3;3720:6;3709:9;3705:22;3679:54;;;3655:79;;-1:-1;3803:2;3836:49;3881:3;3857:22;;;3836:49;;;3829:4;3822:5;3818:16;3811:75;3755:142;3981:2;3970:9;3966:18;3953:32;-1:-1;;;;;3997:6;3994:30;3991:2;;;4037:1;4034;4027:12;3991:2;4072:54;4122:3;4113:6;4102:9;4098:22;4072:54;;;4065:4;4058:5;4054:16;4047:80;3907:231;4204:2;4237:48;4281:3;4272:6;4261:9;4257:22;4237:48;;;4230:4;4223:5;4219:16;4212:74;4148:149;4382:3;4371:9;4367:19;4354:33;-1:-1;;;;;4399:6;4396:30;4393:2;;;4439:1;4436;4429:12;4393:2;4474:54;4524:3;4515:6;4504:9;4500:22;4474:54;;;4467:4;4460:5;4456:16;4449:80;4307:233;4607:3;4641:48;4685:3;4676:6;4665:9;4661:22;4641:48;;;4634:4;4627:5;4623:16;4616:74;4550:151;4761:3;4795:49;4840:3;4831:6;4820:9;4816:22;4795:49;;;4788:4;4781:5;4777:16;4770:75;4711:145;4955:3;4944:9;4940:19;4927:33;-1:-1;;;;;4972:6;4969:30;4966:2;;;5012:1;5009;5002:12;4966:2;5047:54;5097:3;5088:6;5077:9;5073:22;5047:54;;;5040:4;5033:5;5029:16;5022:80;4866:247;5205:3;5194:9;5190:19;5177:33;-1:-1;;;;;5222:6;5219:30;5216:2;;;5262:1;5259;5252:12;5216:2;5298:54;5348:3;5339:6;5328:9;5324:22;5298:54;;;5290:5;5283;5279:17;5272:81;5123:241;3417:1957;;;;;5448:1798;;5579:5;5567:9;5562:3;5558:19;5554:31;5551:2;;;5598:1;5595;5588:12;5551:2;5616:21;5631:5;5616:21;;;5607:30;-1:-1;5693:31;;-1:-1;;;;;5733:30;;5730:2;;;5776:1;5773;5766:12;5730:2;5810:54;5860:3;5851:6;5840:9;5836:22;5810:54;;;5786:79;;-1:-1;5942:2;5975:48;6019:3;5995:22;;;5975:48;;;5968:4;5961:5;5957:16;5950:74;5886:149;6122:2;6111:9;6107:18;6094:32;-1:-1;;;;;6138:6;6135:30;6132:2;;;6178:1;6175;6168:12;6132:2;6213:54;6263:3;6254:6;6243:9;6239:22;6213:54;;;6206:4;6199:5;6195:16;6188:80;6045:234;6348:2;6381:48;6425:3;6416:6;6405:9;6401:22;6381:48;;;6374:4;6367:5;6363:16;6356:74;6289:152;6535:3;6524:9;6520:19;6507:33;-1:-1;;;;;6552:6;6549:30;6546:2;;;6592:1;6589;6582:12;6546:2;6627:54;6677:3;6668:6;6657:9;6653:22;6627:54;;;6620:4;6613:5;6609:16;6602:80;6451:242;6774:3;6763:9;6759:19;6746:33;-1:-1;;;;;6791:6;6788:30;6785:2;;;6831:1;6828;6821:12;6785:2;6866:54;6916:3;6907:6;6896:9;6892:22;6866:54;;;6859:4;6852:5;6848:16;6841:80;6703:229;6990:3;7024:49;7069:3;7060:6;7049:9;7045:22;7024:49;;;7017:4;7010:5;7006:16;6999:75;6942:143;7141:3;7175:49;7220:3;7211:6;7200:9;7196:22;7175:49;;;7168:4;7161:5;7157:16;7150:75;7095:141;5545:1701;;;;;7317:1651;;7445:4;7433:9;7428:3;7424:19;7420:30;7417:2;;;7463:1;7460;7453:12;7417:2;7481:20;7496:4;7481:20;;;7472:29;-1:-1;7557:31;;-1:-1;;;;;7597:30;;7594:2;;;7640:1;7637;7630:12;7594:2;7674:54;7724:3;7715:6;7704:9;7700:22;7674:54;;;7650:79;;-1:-1;7838:2;7823:18;;7810:32;-1:-1;;;;;7851:30;;7848:2;;;7894:1;7891;7884:12;7848:2;7929:54;7979:3;7970:6;7959:9;7955:22;7929:54;;;7922:4;7915:5;7911:16;7904:80;7750:245;8054:2;8087:49;8132:3;8123:6;8112:9;8108:22;8087:49;;;8080:4;8073:5;8069:16;8062:75;8005:143;8235:2;8224:9;8220:18;8207:32;-1:-1;;;;;8251:6;8248:30;8245:2;;;8291:1;8288;8281:12;8245:2;8326:54;8376:3;8367:6;8356:9;8352:22;8326:54;;;8319:4;8312:5;8308:16;8301:80;8158:234;8461:3;8495:48;8539:3;8530:6;8519:9;8515:22;8495:48;;;8488:4;8481:5;8477:16;8470:74;8402:153;8649:3;8638:9;8634:19;8621:33;-1:-1;;;;;8666:6;8663:30;8660:2;;;8706:1;8703;8696:12;8660:2;8741:54;8791:3;8782:6;8771:9;8767:22;8741:54;;;8734:4;8727:5;8723:16;8716:80;8565:242;8863:3;8897:49;8942:3;8933:6;8922:9;8918:22;8897:49;;;8890:4;8883:5;8879:16;8872:75;8817:141;7411:1557;;;;;9044:1364;;9177:4;9165:9;9160:3;9156:19;9152:30;9149:2;;;9195:1;9192;9185:12;9149:2;9213:20;9228:4;9213:20;;;9204:29;-1:-1;9285:1;9316:49;9361:3;9341:9;9316:49;;;9292:74;;-1:-1;9460:2;9445:18;;9432:32;-1:-1;;;;;9473:30;;9470:2;;;9516:1;9513;9506:12;9470:2;9551:54;9601:3;9592:6;9581:9;9577:22;9551:54;;;9544:4;9537:5;9533:16;9526:80;9387:230;9702:2;9691:9;9687:18;9674:32;-1:-1;;;;;9718:6;9715:30;9712:2;;;9758:1;9755;9748:12;9712:2;9793:54;9843:3;9834:6;9823:9;9819:22;9793:54;;;9786:4;9779:5;9775:16;9768:80;9627:232;9915:2;9948:48;9992:3;9983:6;9972:9;9968:22;9948:48;;;9941:4;9934:5;9930:16;9923:74;9869:139;10089:3;10078:9;10074:19;10061:33;-1:-1;;;;;10106:6;10103:30;10100:2;;;10146:1;10143;10136:12;10100:2;10181:54;10231:3;10222:6;10211:9;10207:22;10181:54;;;10174:4;10167:5;10163:16;10156:80;10018:229;10303:3;10337:49;10382:3;10373:6;10362:9;10358:22;10337:49;;;10330:4;10323:5;10319:16;10312:75;10257:141;9143:1265;;;;;10491:594;;10631:4;10619:9;10614:3;10610:19;10606:30;10603:2;;;10649:1;10646;10639:12;10603:2;10667:20;10682:4;10667:20;;;10658:29;-1:-1;10743:31;;-1:-1;;;;;10783:30;;10780:2;;;10826:1;10823;10816:12;10780:2;10860:54;10910:3;10901:6;10890:9;10886:22;10860:54;;;10836:79;;-1:-1;10982:2;11015:48;11059:3;11035:22;;;11015:48;;;11008:4;11001:5;10997:16;10990:74;10936:139;10597:488;;;;;11829:1493;;11950:4;11938:9;11933:3;11929:19;11925:30;11922:2;;;11968:1;11965;11958:12;11922:2;11986:20;12001:4;11986:20;;;11977:29;-1:-1;12062:31;;-1:-1;;;;;12102:30;;12099:2;;;12145:1;12142;12135:12;12099:2;12179:54;12229:3;12220:6;12209:9;12205:22;12179:54;;;12155:79;;-1:-1;12327:2;12312:18;;12299:32;-1:-1;;;;;12340:30;;12337:2;;;12383:1;12380;12373:12;12337:2;12418:75;12489:3;12480:6;12469:9;12465:22;12418:75;;;12411:4;12404:5;12400:16;12393:101;12255:250;12592:2;12581:9;12577:18;12564:32;-1:-1;;;;;12608:6;12605:30;12602:2;;;12648:1;12645;12638:12;12602:2;12683:70;12749:3;12740:6;12729:9;12725:22;12683:70;;;12676:4;12669:5;12665:16;12658:96;12515:250;12862:2;12851:9;12847:18;12834:32;-1:-1;;;;;12878:6;12875:30;12872:2;;;12918:1;12915;12908:12;12872:2;12953:75;13024:3;13015:6;13004:9;13000:22;12953:75;;;12946:4;12939:5;12935:16;12928:101;12775:265;13133:3;13122:9;13118:19;13105:33;-1:-1;;;;;13150:6;13147:30;13144:2;;;13190:1;13187;13180:12;13144:2;13225:75;13296:3;13287:6;13276:9;13272:22;13225:75;;;13218:4;13211:5;13207:16;13200:101;13050:262;11916:1406;;;;;13394:835;;13523:4;13511:9;13506:3;13502:19;13498:30;13495:2;;;13541:1;13538;13531:12;13495:2;13559:20;13574:4;13559:20;;;13550:29;-1:-1;13632:1;13663:49;13708:3;13688:9;13663:49;;;13639:74;;-1:-1;13809:2;13794:18;;13781:32;-1:-1;;;;;13822:30;;13819:2;;;13865:1;13862;13855:12;13819:2;13900:54;13950:3;13941:6;13930:9;13926:22;13900:54;;;13893:4;13886:5;13882:16;13875:80;13734:232;14062:2;14051:9;14047:18;14034:32;-1:-1;;;;;14078:6;14075:30;14072:2;;;14118:1;14115;14108:12;14072:2;14153:54;14203:3;14194:6;14183:9;14179:22;14153:54;;;14146:4;14139:5;14135:16;14128:80;13976:243;13489:740;;;;;14236:130;14303:20;;14328:33;14303:20;14328:33;;14373:128;14439:20;;14464:32;14439:20;14464:32;;14508:130;14575:20;;14600:33;14575:20;14600:33;;14782:263;;14897:2;14885:9;14876:7;14872:23;14868:32;14865:2;;;14913:1;14910;14903:12;14865:2;14948:1;14965:64;15021:7;15001:9;14965:64;;15052:397;;;15191:2;15179:9;15170:7;15166:23;15162:32;15159:2;;;15207:1;15204;15197:12;15159:2;15242:31;;-1:-1;;;;;15282:30;;15279:2;;;15325:1;15322;15315:12;15279:2;15353:80;15425:7;15416:6;15405:9;15401:22;15353:80;;;15343:90;;;;15221:218;15153:296;;;;;;15456:589;;;;15600:2;15588:9;15579:7;15575:23;15571:32;15568:2;;;15616:1;15613;15606:12;15568:2;15651:1;15668:50;15710:7;15690:9;15668:50;;;15658:60;;15630:94;15783:2;15772:9;15768:18;15755:32;-1:-1;;;;;15799:6;15796:30;15793:2;;;15839:1;15836;15829:12;15793:2;15859:62;15913:7;15904:6;15893:9;15889:22;15859:62;;;15849:72;;15734:193;15958:2;15976:53;16021:7;16012:6;16001:9;15997:22;15976:53;;;15966:63;;15937:98;15562:483;;;;;;16052:345;;16165:2;16153:9;16144:7;16140:23;16136:32;16133:2;;;16181:1;16178;16171:12;16133:2;16216:31;;-1:-1;;;;;16256:30;;16253:2;;;16299:1;16296;16289:12;16253:2;16319:62;16373:7;16364:6;16353:9;16349:22;16319:62;;16404:699;;;;16560:2;16548:9;16539:7;16535:23;16531:32;16528:2;;;16576:1;16573;16566:12;16528:2;16611:31;;-1:-1;;;;;16651:30;;16648:2;;;16694:1;16691;16684:12;16648:2;16714:62;16768:7;16759:6;16748:9;16744:22;16714:62;;;16704:72;;16590:192;16813:2;16831:53;16876:7;16867:6;16856:9;16852:22;16831:53;;;16821:63;;16792:98;16949:2;16938:9;16934:18;16921:32;-1:-1;;;;;16965:6;16962:30;16959:2;;;17005:1;17002;16995:12;16959:2;17025:62;17079:7;17070:6;17059:9;17055:22;17025:62;;17110:411;;17256:2;17244:9;17235:7;17231:23;17227:32;17224:2;;;17272:1;17269;17262:12;17224:2;17307:31;;-1:-1;;;;;17347:30;;17344:2;;;17390:1;17387;17380:12;17344:2;17410:95;17497:7;17488:6;17477:9;17473:22;17410:95;;17528:411;;17674:2;17662:9;17653:7;17649:23;17645:32;17642:2;;;17690:1;17687;17680:12;17642:2;17725:31;;-1:-1;;;;;17765:30;;17762:2;;;17808:1;17805;17798:12;17762:2;17828:95;17915:7;17906:6;17895:9;17891:22;17828:95;;17946:405;;18089:2;18077:9;18068:7;18064:23;18060:32;18057:2;;;18105:1;18102;18095:12;18057:2;18140:31;;-1:-1;;;;;18180:30;;18177:2;;;18223:1;18220;18213:12;18177:2;18243:92;18327:7;18318:6;18307:9;18303:22;18243:92;;18358:415;;18506:2;18494:9;18485:7;18481:23;18477:32;18474:2;;;18522:1;18519;18512:12;18474:2;18557:31;;-1:-1;;;;;18597:30;;18594:2;;;18640:1;18637;18630:12;18594:2;18660:97;18749:7;18740:6;18729:9;18725:22;18660:97;;18780:429;;18935:2;18923:9;18914:7;18910:23;18906:32;18903:2;;;18951:1;18948;18941:12;18903:2;18986:31;;-1:-1;;;;;19026:30;;19023:2;;;19069:1;19066;19059:12;19023:2;19089:104;19185:7;19176:6;19165:9;19161:22;19089:104;;19654:391;;19790:2;19778:9;19769:7;19765:23;19761:32;19758:2;;;19806:1;19803;19796:12;19758:2;19841:31;;-1:-1;;;;;19881:30;;19878:2;;;19924:1;19921;19914:12;19878:2;19944:85;20021:7;20012:6;20001:9;19997:22;19944:85;;20052:407;;20196:2;20184:9;20175:7;20171:23;20167:32;20164:2;;;20212:1;20209;20202:12;20164:2;20247:31;;-1:-1;;;;;20287:30;;20284:2;;;20330:1;20327;20320:12;20284:2;20350:93;20435:7;20426:6;20415:9;20411:22;20350:93;;20466:241;;20570:2;20558:9;20549:7;20545:23;20541:32;20538:2;;;20586:1;20583;20576:12;20538:2;20621:1;20638:53;20683:7;20663:9;20638:53;;20714:241;;20818:2;20806:9;20797:7;20793:23;20789:32;20786:2;;;20834:1;20831;20824:12;20786:2;20869:1;20886:53;20931:7;20911:9;20886:53;;20962:491;;;;21100:2;21088:9;21079:7;21075:23;21071:32;21068:2;;;21116:1;21113;21106:12;21068:2;21151:1;21168:53;21213:7;21193:9;21168:53;;;21158:63;;21130:97;21258:2;21276:53;21321:7;21312:6;21301:9;21297:22;21276:53;;;21266:63;;21237:98;21366:2;21384:53;21429:7;21420:6;21409:9;21405:22;21384:53;;21461:193;;21580:68;21644:3;21636:6;21580:68;;21663:282;;21802:102;21900:3;21892:6;21802:102;;;-1:-1;;21933:5;21924:15;;21795:150;21954:281;;22093:102;22191:3;22183:6;22093:102;;;-1:-1;;22224:4;22215:14;;22086:149;22244:281;;22383:102;22481:3;22473:6;22383:102;;;-1:-1;;22514:4;22505:14;;22376:149;22534:189;;22629:54;22679:3;22671:6;22629:54;;;-1:-1;;22712:4;22703:14;;22622:101;22731:127;22820:32;22846:5;22820:32;;;22815:3;22808:45;22802:56;;;23130:876;;23279:55;23328:5;23279:55;;;23347:89;23429:6;23424:3;23347:89;;;23340:96;;23459:3;23501:4;23493:6;23489:17;23484:3;23480:27;23528:57;23579:5;23528:57;;;23605:7;23633:1;23618:349;23643:6;23640:1;23637:13;23618:349;;;23705:9;23699:4;23695:20;23690:3;23683:33;23750:6;23744:13;23772:82;23849:4;23834:13;23772:82;;;23764:90;;23871:61;23925:6;23871:61;;;23955:4;23946:14;;;;;23861:71;-1:-1;;23665:1;23658:9;23618:349;;;-1:-1;23980:4;;23258:748;-1:-1;;;;;;;23258:748;24111:898;;24308:80;24382:5;24308:80;;;24401:112;24506:6;24501:3;24401:112;;;24394:119;;24534:82;24610:5;24534:82;;;24636:7;24664:1;24649:338;24674:6;24671:1;24668:13;24649:338;;;24741:6;24735:13;24762:115;24873:3;24858:13;24762:115;;;24755:122;;24894:86;24973:6;24894:86;;;24884:96;-1:-1;;24696:1;24689:9;24649:338;;;-1:-1;25000:3;;24287:722;-1:-1;;;;;24287:722;25114:898;;25311:80;25385:5;25311:80;;;25404:112;25509:6;25504:3;25404:112;;;25397:119;;25537:82;25613:5;25537:82;;;25639:7;25667:1;25652:338;25677:6;25674:1;25671:13;25652:338;;;25744:6;25738:13;25765:115;25876:3;25861:13;25765:115;;;25758:122;;25897:86;25976:6;25897:86;;;25887:96;-1:-1;;25699:1;25692:9;25652:338;;26119:832;26290:74;26358:5;26290:74;;;26377:100;26470:6;26465:3;26377:100;;;26370:107;;26498:76;26568:5;26498:76;;;26594:7;26622:1;26607:332;26632:6;26629:1;26626:13;26607:332;;;26699:6;26693:13;26720:115;26831:3;26816:13;26720:115;;;26713:122;;26852:80;26925:6;26852:80;;;26842:90;-1:-1;;26654:1;26647:9;26607:332;;26990:678;;27129:50;27173:5;27129:50;;;27192:84;27269:6;27264:3;27192:84;;;27185:91;;27297:52;27343:5;27297:52;;;27369:7;27397:1;27382:264;27407:6;27404:1;27401:13;27382:264;;;27474:6;27468:13;27495:71;27562:3;27547:13;27495:71;;;27488:78;;27583:56;27632:6;27583:56;;;27573:66;-1:-1;;27429:1;27422:9;27382:264;;27676:94;27743:21;27758:5;27743:21;;27777:103;27850:24;27868:5;27850:24;;28005:359;;28123:38;28155:5;28123:38;;;28173:78;28244:6;28239:3;28173:78;;;28166:85;;28256:52;28301:6;28296:3;28289:4;28282:5;28278:16;28256:52;;;28329:29;28351:6;28329:29;;;28320:39;;;;28103:261;-1:-1;;;28103:261;28371:356;;28499:38;28531:5;28499:38;;;28549:88;28630:6;28625:3;28549:88;;;28542:95;;28642:52;28687:6;28682:3;28675:4;28668:5;28664:16;28642:52;;;28706:16;;;;;28479:248;-1:-1;;28479:248;29072:164;29173:57;29224:5;29173:57;;30169:465;;30329:67;30393:2;30388:3;30329:67;;;30429:66;30409:87;;-1:-1;;;30525:2;30516:12;;30509:88;30625:2;30616:12;;30315:319;-1:-1;;30315:319;30643:465;;30803:67;30867:2;30862:3;30803:67;;;30903:66;30883:87;;-1:-1;;;30999:2;30990:12;;30983:88;31099:2;31090:12;;30789:319;-1:-1;;30789:319;31117:364;;31277:67;31341:2;31336:3;31277:67;;;31377:66;31357:87;;31472:2;31463:12;;31263:218;-1:-1;;31263:218;31490:364;;31650:67;31714:2;31709:3;31650:67;;;-1:-1;;;31730:87;;31845:2;31836:12;;31636:218;-1:-1;;31636:218;31863:364;;32023:67;32087:2;32082:3;32023:67;;;-1:-1;;;32103:87;;32218:2;32209:12;;32009:218;-1:-1;;32009:218;32236:364;;32396:67;32460:2;32455:3;32396:67;;;32496:66;32476:87;;32591:2;32582:12;;32382:218;-1:-1;;32382:218;32609:364;;32769:67;32833:2;32828:3;32769:67;;;-1:-1;;;32849:87;;32964:2;32955:12;;32755:218;-1:-1;;32755:218;32982:364;;33142:67;33206:2;33201:3;33142:67;;;33242:66;33222:87;;33337:2;33328:12;;33128:218;-1:-1;;33128:218;33355:364;;33515:67;33579:2;33574:3;33515:67;;;-1:-1;;;33595:87;;33710:2;33701:12;;33501:218;-1:-1;;33501:218;33728:364;;33888:67;33952:2;33947:3;33888:67;;;-1:-1;;;33968:87;;34083:2;34074:12;;33874:218;-1:-1;;33874:218;34181:339;34401:22;;34326:4;34317:14;;;34429:70;34321:3;34401:22;34429:70;;34658:2136;34921:22;;34851:5;34956:37;;;34658:2136;;34842:15;;;;35008:75;34842:15;34921:22;35008:75;;;35000:83;;34872:223;35176:4;35169:5;35165:16;35159:23;35188:71;35253:4;35248:3;35244:14;35230:12;35188:71;;;35105:160;35344:4;35337:5;35333:16;35327:23;35396:3;35390:4;35386:14;35379:4;35374:3;35370:14;35363:38;35416:75;35486:4;35472:12;35416:75;;;35408:83;;35275:228;35592:4;35585:5;35581:16;35575:23;35604:69;35667:4;35662:3;35658:14;35644:12;35604:69;;;35513:166;35759:4;35752:5;35748:16;35742:23;35811:3;35805:4;35801:14;35794:4;35789:3;35785:14;35778:38;35831:75;35901:4;35887:12;35831:75;;;35823:83;;35689:229;36008:4;36001:5;35997:16;35991:23;36020:69;36083:4;36078:3;36074:14;36060:12;36020:69;;;35928:167;36178:4;36171:5;36167:16;36161:23;36190:71;36255:4;36250:3;36246:14;36232:12;36190:71;;;36105:162;36361:4;36354:5;36350:16;36344:23;36413:3;36407:4;36403:14;36396:4;36391:3;36387:14;36380:38;36433:75;36503:4;36489:12;36433:75;;;36425:83;;36277:243;36607:5;36600;36596:17;36590:24;36661:3;36655:4;36651:14;36643:5;36638:3;36634:15;36627:39;36681:75;36751:4;36737:12;36681:75;;;36673:83;34824:1970;-1:-1;;;;;34824:1970;36932:1883;37198:22;;37125:5;37233:37;;;36932:1883;;37116:15;;;;37285:75;37116:15;37198:22;37285:75;;;37277:83;;37146:226;37461:4;37454:5;37450:16;37444:23;37473:69;37536:4;37531:3;37527:14;37513:12;37473:69;;;37382:166;37630:4;37623:5;37619:16;37613:23;37682:3;37676:4;37672:14;37665:4;37660:3;37656:14;37649:38;37702:75;37772:4;37758:12;37702:75;;;37694:83;;37558:231;37881:4;37874:5;37870:16;37864:23;37893:69;37956:4;37951:3;37947:14;37933:12;37893:69;;;37799:169;38057:4;38050:5;38046:16;38040:23;38109:3;38103:4;38099:14;38092:4;38087:3;38083:14;38076:38;38129:75;38199:4;38185:12;38129:75;;;38121:83;;37978:238;38292:4;38285:5;38281:16;38275:23;38344:3;38338:4;38334:14;38327:4;38322:3;38318:14;38311:38;38364:75;38434:4;38420:12;38364:75;;;38356:83;;38226:225;38532:4;38525:5;38521:16;38515:23;38544:71;38609:4;38604:3;38600:14;38586:12;38544:71;;;38461:160;38700:4;38693:5;38689:16;38683:23;38712:71;38777:4;38772:3;38768:14;38754:12;38712:71;;38947:1718;39206:22;;39134:4;39241:37;;;38947:1718;;39125:14;;;;39293:75;39125:14;39206:22;39293:75;;;39285:83;;39154:226;39473:4;39466:5;39462:16;39456:23;39525:3;39519:4;39515:14;39508:4;39503:3;39499:14;39492:38;39545:75;39615:4;39601:12;39545:75;;;39537:83;;39390:242;39714:4;39707:5;39703:16;39697:23;39726:71;39791:4;39786:3;39782:14;39768:12;39726:71;;;39642:161;39885:4;39878:5;39874:16;39868:23;39937:3;39931:4;39927:14;39920:4;39915:3;39911:14;39904:38;39957:75;40027:4;40013:12;39957:75;;;39949:83;;39813:231;40136:4;40129:5;40125:16;40119:23;40148:69;40211:4;40206:3;40202:14;40188:12;40148:69;;;40054:169;40312:4;40305:5;40301:16;40295:23;40364:3;40358:4;40354:14;40347:4;40342:3;40338:14;40331:38;40384:75;40454:4;40440:12;40384:75;;;40376:83;;40233:238;40550:4;40543:5;40539:16;40533:23;40562:71;40627:4;40622:3;40618:14;40604:12;40562:71;;40807:1440;41072:22;;40807:1440;;41004:4;40995:14;;;41100:70;40999:3;41072:22;41100:70;;;41024:152;41254:4;41247:5;41243:16;41237:23;41306:3;41300:4;41296:14;41289:4;41284:3;41280:14;41273:38;41326:75;41396:4;41382:12;41326:75;;;41318:83;;41186:227;41493:4;41486:5;41482:16;41476:23;41545:3;41539:4;41535:14;41528:4;41523:3;41519:14;41512:38;41565:75;41635:4;41621:12;41565:75;;;41557:83;;41423:229;41731:4;41724:5;41720:16;41714:23;41743:69;41806:4;41801:3;41797:14;41783:12;41743:69;;;41662:156;41894:4;41887:5;41883:16;41877:23;41946:3;41940:4;41936:14;41929:4;41924:3;41920:14;41913:38;41966:75;42036:4;42022:12;41966:75;;;41958:83;;41828:225;42132:4;42125:5;42121:16;42115:23;42144:71;42209:4;42204:3;42200:14;42186:12;42144:71;;42359:762;42587:22;;42516:4;42507:14;;;42615:95;42511:3;42587:22;42615:95;;;42536:180;42810:4;42803:5;42799:16;42793:23;42822:106;42922:4;42917:3;42913:14;42899:12;42822:106;;;42726:208;43017:4;43010:5;43006:16;43000:23;43029:71;43094:4;43089:3;43085:14;43071:12;43029:71;;45852:523;46084:22;;46009:4;46000:14;;;46112:70;46004:3;46084:22;46112:70;;;46029:159;46271:4;46264:5;46260:16;46254:23;46283:71;46348:4;46343:3;46339:14;46325:12;46283:71;;46485:1315;46713:22;;46642:4;46633:14;;;46741:95;46637:3;46713:22;46741:95;;;46662:180;46938:4;46931:5;46927:16;46921:23;46950:125;47069:4;47064:3;47060:14;47046:12;46950:125;;;46852:229;47163:4;47156:5;47152:16;47146:23;47175:95;47264:4;47259:3;47255:14;47241:12;47175:95;;;47091:185;47358:4;47351:5;47347:16;47341:23;47370:71;47435:4;47430:3;47426:14;47412:12;47370:71;;;47286:161;47526:4;47519:5;47515:16;47509:23;47538:71;47603:4;47598:3;47594:14;47580:12;47538:71;;;47457:158;47696:4;47689:5;47685:16;47679:23;47708:71;47773:4;47768:3;47764:14;47750:12;47708:71;;47906:916;48134:22;;48063:4;48054:14;;;48162:95;48058:3;48134:22;48162:95;;;48083:180;48340:4;48333:5;48329:16;48323:23;48352:89;48435:4;48430:3;48426:14;48412:12;48352:89;;;48273:174;48526:4;48519:5;48515:16;48509:23;48538:91;48623:4;48618:3;48614:14;48600:12;48538:91;;;48457:178;48718:4;48711:5;48707:16;48701:23;48730:71;48795:4;48790:3;48786:14;48772:12;48730:71;;49946:1207;50174:22;;50103:4;50094:14;;;50202:95;50098:3;50174:22;50202:95;;;50123:180;50395:4;50388:5;50384:16;50378:23;50407:125;50526:4;50521:3;50517:14;50503:12;50407:125;;;50313:225;50632:4;50625:5;50621:16;50615:23;50644:106;50744:4;50739:3;50735:14;50721:12;50644:106;;;50548:208;50843:4;50836:5;50832:16;50826:23;50855:104;50953:4;50948:3;50944:14;50930:12;50855:104;;;50766:199;51049:4;51042:5;51038:16;51032:23;51061:71;51126:4;51121:3;51117:14;51103:12;51061:71;;51255:1317;51487:22;;51412:4;51403:14;;;51515:94;51407:3;51487:22;51515:94;;;51432:183;51693:4;51686:5;51682:16;51676:23;51705:96;51795:4;51790:3;51786:14;51772:12;51705:96;;;51625:182;51903:4;51896:5;51892:16;51886:23;51915:125;52034:4;52029:3;52025:14;52011:12;51915:125;;52579:132;52688:18;;52682:29;52809:1812;53022:22;;52948:5;52939:15;;;53050:56;52943:3;53022:22;53050:56;;;52969:143;53199:4;53192:5;53188:16;53182:23;53211:61;53266:4;53261:3;53257:14;53243:12;53211:61;;;53122:156;53354:4;53347:5;53343:16;53337:23;53366:63;53423:4;53418:3;53414:14;53400:12;53366:63;;;53288:147;53512:4;53505:5;53501:16;53495:23;53524:63;53581:4;53576:3;53572:14;53558:12;53524:63;;;53445:148;53668:4;53661:5;53657:16;53651:23;53680:157;53831:4;53826:3;53822:14;53808:12;53680:157;;;53603:240;53919:4;53912:5;53908:16;53902:23;53931:158;54082:5;54077:3;54073:15;54059:12;53931:158;;;53853:242;54173:4;54166:5;54162:16;54156:23;54185:80;54258:5;54253:3;54249:15;54235:12;54185:80;;;54105:166;54348:4;54341:5;54337:16;54331:23;54360:64;54417:5;54412:3;54408:15;54394:12;54360:64;;;54281:149;54523:5;54516;54512:17;54506:24;54536:64;54593:5;54588:3;54584:15;54570:12;54536:64;;54777:649;55060:22;;54988:4;55095:37;;;54777:649;;54979:14;;;;55147:75;54979:14;55060:22;55147:75;;;55139:83;;55008:226;55313:4;55306:5;55302:16;55296:23;55325:69;55388:4;55383:3;55379:14;55365:12;55325:69;;56473:1119;56682:22;;56612:4;56603:14;;;56710:56;56607:3;56682:22;56710:56;;;56632:140;56848:4;56841:5;56837:16;56831:23;56860:63;56917:4;56912:3;56908:14;56894:12;56860:63;;;56782:147;57006:4;56999:5;56995:16;56989:23;57018:63;57075:4;57070:3;57066:14;57052:12;57018:63;;;56939:148;57166:4;57159:5;57155:16;57149:23;57178:79;57251:4;57246:3;57242:14;57228:12;57178:79;;57710:1578;57955:22;;57883:4;57990:37;;;57710:1578;;57874:14;;;;58042:75;57874:14;57955:22;58042:75;;;58034:83;;57903:226;58206:4;58199:5;58195:16;58189:23;58258:3;58252:4;58248:14;58241:4;58236:3;58232:14;58225:38;58278:117;58390:4;58376:12;58278:117;;;58270:125;;58139:268;58489:4;58482:5;58478:16;58472:23;58541:3;58535:4;58531:14;58524:4;58519:3;58515:14;58508:38;58561:107;58663:4;58649:12;58561:107;;;58553:115;;58417:263;58772:4;58765:5;58761:16;58755:23;58824:3;58818:4;58814:14;58807:4;58802:3;58798:14;58791:38;58844:117;58956:4;58942:12;58844:117;;;58836:125;;58690:283;59061:4;59054:5;59050:16;59044:23;59113:3;59107:4;59103:14;59096:4;59091:3;59087:14;59080:38;59133:117;59245:4;59231:12;59133:117;;59422:877;59680:22;;59422:877;;59611:4;59602:14;;;59708:70;59606:3;59680:22;59708:70;;;59631:153;59864:4;59857:5;59853:16;59847:23;59916:3;59910:4;59906:14;59899:4;59894:3;59890:14;59883:38;59936:75;60006:4;59992:12;59936:75;;;59928:83;;59794:229;60114:4;60107:5;60103:16;60097:23;60166:3;60160:4;60156:14;60149:4;60144:3;60140:14;60133:38;60186:75;60256:4;60242:12;60186:75;;60397:974;60606:22;;60536:4;60527:14;;;60634:62;60531:3;60606:22;60634:62;;;60556:146;60781:4;60774:5;60770:16;60764:23;60793:79;60866:4;60861:3;60857:14;60843:12;60793:79;;;60712:166;60952:4;60945:5;60941:16;60935:23;60964:63;61021:4;61016:3;61012:14;60998:12;60964:63;;;60888:145;61108:4;61101:5;61097:16;61091:23;61120:63;61177:4;61172:3;61168:14;61154:12;61120:63;;61378:113;61461:24;61479:5;61461:24;;61498:113;61581:24;61599:5;61581:24;;61864:110;61945:23;61962:5;61945:23;;62452:152;62553:45;62573:24;62591:5;62573:24;;;62553:45;;62611:100;62682:23;62699:5;62682:23;;62718:401;;62890:93;62979:3;62970:6;62890:93;;;62883:100;;62994:75;63065:3;63056:6;62994:75;;;-1:-1;63091:2;63082:12;;62871:248;-1:-1;;62871:248;63126:465;63346:2;63360:47;;;63331:18;;63421:160;63331:18;63567:6;63421:160;;63598:465;63818:2;63832:47;;;63803:18;;63893:160;63803:18;64039:6;63893:160;;64070:407;64261:2;64275:47;;;64246:18;;64336:131;64246:18;64336:131;;64484:407;64675:2;64689:47;;;64660:18;;64750:131;64660:18;64750:131;;64898:407;65089:2;65103:47;;;65074:18;;65164:131;65074:18;65164:131;;65312:407;65503:2;65517:47;;;65488:18;;65578:131;65488:18;65578:131;;65726:407;65917:2;65931:47;;;65902:18;;65992:131;65902:18;65992:131;;66140:407;66331:2;66345:47;;;66316:18;;66406:131;66316:18;66406:131;;66554:407;66745:2;66759:47;;;66730:18;;66820:131;66730:18;66820:131;;66968:407;67159:2;67173:47;;;67144:18;;67234:131;67144:18;67234:131;;67382:407;67573:2;67587:47;;;67558:18;;67648:131;67558:18;67648:131;;67796:407;67987:2;68001:47;;;67972:18;;68062:131;67972:18;68062:131;;68210:857;68562:3;68547:19;;68577:135;68551:9;68685:6;68577:135;;;68723:110;68829:2;68818:9;68814:18;68805:6;68723:110;;;68882:9;68876:4;68872:20;68866:3;68855:9;68851:19;68844:49;68907:150;69052:4;69043:6;68907:150;;69074:1049;69434:3;69419:19;;69449:135;69423:9;69557:6;69449:135;;;69595:110;69701:2;69690:9;69686:18;69677:6;69595:110;;;69754:9;69748:4;69744:20;69738:3;69727:9;69723:19;69716:49;69779:84;69858:4;69849:6;69779:84;;;69771:92;;69874:81;69950:3;69939:9;69935:19;69926:6;69874:81;;;70004:9;69998:4;69994:20;69988:3;69977:9;69973:19;69966:49;70029:84;70108:4;70099:6;70029:84;;;70021:92;69405:718;-1:-1;;;;;;;69405:718;70130:857;70482:3;70467:19;;70497:135;70471:9;70605:6;70497:135;;;70643:110;70749:2;70738:9;70734:18;70725:6;70643:110;;;70802:9;70796:4;70792:20;70786:3;70775:9;70771:19;70764:49;70827:150;70972:4;70963:6;70827:150;;70994:845;71340:3;71325:19;;71355:135;71329:9;71463:6;71355:135;;;71501:110;71607:2;71596:9;71592:18;71583:6;71501:110;;;71660:9;71654:4;71650:20;71644:3;71633:9;71629:19;71622:49;71685:144;71824:4;71815:6;71685:144;;71846:865;72202:3;72187:19;;72217:135;72191:9;72325:6;72217:135;;;72363:110;72469:2;72458:9;72454:18;72445:6;72363:110;;;72522:9;72516:4;72512:20;72506:3;72495:9;72491:19;72484:49;72547:154;72696:4;72687:6;72547:154;;72718:640;72986:3;72971:19;;73001:135;72975:9;73109:6;73001:135;;;73147:110;73253:2;73242:9;73238:18;73229:6;73147:110;;;73268:80;73344:2;73333:9;73329:18;73320:6;73268:80;;73365:894;73735:3;73720:19;;73750:135;73724:9;73858:6;73750:135;;;73896:111;74002:3;73991:9;73987:19;73978:6;73896:111;;;74056:9;74050:4;74046:20;74040:3;74029:9;74025:19;74018:49;74081:168;74244:4;74235:6;74081:168;;75171:762;75467:3;75452:19;;75482:135;75456:9;75590:6;75482:135;;;75628:111;75734:3;75723:9;75719:19;75710:6;75628:111;;;75750:81;75826:3;75815:9;75811:19;75802:6;75750:81;;;75842;75918:3;75907:9;75903:19;75894:6;75842:81;;76709:818;77041:3;77026:19;;77056:135;77030:9;77164:6;77056:135;;;77202:111;77308:3;77297:9;77293:19;77284:6;77202:111;;;77362:9;77356:4;77352:20;77346:3;77335:9;77331:19;77324:49;77387:130;77512:4;77503:6;77387:130;;77534:850;77882:3;77867:19;;77897:135;77871:9;78005:6;77897:135;;;78043:111;78149:3;78138:9;78134:19;78125:6;78043:111;;;78203:9;78197:4;78193:20;78187:3;78176:9;78172:19;78165:49;78228:146;78369:4;78360:6;78228:146;;78391:213;78509:2;78494:18;;78523:71;78498:9;78567:6;78523:71;;78611:213;78729:2;78714:18;;78743:71;78718:9;78787:6;78743:71;;78831:209;78947:2;78932:18;;78961:69;78936:9;79003:6;78961:69;;79047:256;79109:2;79103:9;79135:17;;;-1:-1;;;;;79195:34;;79231:22;;;79192:62;79189:2;;;79267:1;79264;79257:12;79189:2;79283;79276:22;79087:216;;-1:-1;79087:216;79310:305;;-1:-1;;;;;79462:6;79459:30;79456:2;;;79502:1;79499;79492:12;79456:2;-1:-1;79537:4;79525:17;;;79590:15;;79393:222;79929:317;;-1:-1;;;;;80060:6;80057:30;80054:2;;;80100:1;80097;80090:12;80054:2;-1:-1;80231:4;80167;80144:17;;;;-1:-1;;80140:33;80221:15;;79991:255;80581:152;80706:4;80697:14;;80654:79;81108:119;81214:3;81200:27;81388:138;81492:12;;81463:63;81873:129;-1:-1;81989:3;;81967:35;83046:181;83167:19;;;83216:4;83207:14;;83160:67;84684:91;;84746:24;84764:5;84746:24;;84888:85;84954:13;84947:21;;84930:43;85059:113;-1:-1;;;;;85121:46;;85104:68;85179:84;85251:6;85240:18;;85223:40;85270:121;-1:-1;;;;;85332:54;;85315:76;85477:96;-1:-1;;;;;85538:30;;85521:52;85580:161;;85679:57;85730:5;85679:57;;87504:145;87585:6;87580:3;87575;87562:30;-1:-1;87641:1;87623:16;;87616:27;87555:94;87658:268;87723:1;87730:101;87744:6;87741:1;87738:13;87730:101;;;87811:11;;;87805:18;87792:11;;;87785:39;87766:2;87759:10;87730:101;;;87846:6;87843:1;87840:13;87837:2;;;-1:-1;;87911:1;87893:16;;87886:27;87707:219;88015:97;88103:2;88083:14;-1:-1;;88079:28;;88063:49;88120:117;88189:24;88207:5;88189:24;;;88182:5;88179:35;88169:2;;88228:1;88225;88218:12;88169:2;88163:74;;88244:111;88310:21;88325:5;88310:21;;88362:117;88431:24;88449:5;88431:24;;88486:117;88555:24;88573:5;88555:24;;88610:115;88678:23;88695:5;88678:23;;88732:117;88801:24;88819:5;88801:24;;88899:74;1708:13:68;;:::i;:::-;-1:-1:-1;1851:264:68;;;;;;;;-1:-1:-1;;;;;1851:264:68;;;;;;-1:-1:-1;1851:264:68;;;;1827:7;1851:264;;;;;;;;;;;;;;;;;;1560:562::o

Swarm Source

bzzr://9c00be5c05ba01aa62f0d0328e226c7eee7b07c7d18bf1f24a73b36e65a35a49

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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

OVERVIEW

The OMG Network's exit game contract.

Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.

Validator Index Block Amount
View All Withdrawals

Txn Hash Block Value Eth2 PubKey Valid
View All Deposits
[ Download: CSV Export  ]
[ Download: CSV Export  ]

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