Contract 0x3666f603Cc164936C1b87e207F36BEBa4AC5f18a 4

Bridge 
 
Txn Hash Method
Block
From
To
Value
0xc1b1d9a4d9ff71bc1f137f0f45674f53b1417c723551ee7646d1b7f9bc04583aSend To L2(pending)2021-10-24 1:48:4714 hrs 49 mins ago0x499c24d259124bad7e9c610a1b223f3decfeb69e IN Hop Exchange: Bridge0 Ether(Pending)(Pending)
0xbf96be6d54e0f1f75c47fd6ab2bb95eab64e7e57e07805fae0055242a0e3c3e3Send To L2134812592021-10-24 16:29:179 mins ago0x7680407aafff43d2e9c3a4c77697e28cd0a59f57 IN  Hop Exchange: Bridge0 Ether0.008513885977 77.992414806
0xf35bc381336f912c90e06e87adfc8e9382f031c042810b67dace84d49cbac1f5Bond Withdrawal134812112021-10-24 16:19:0519 mins agoHop Protocol: Bonders IN  Hop Exchange: Bridge0 Ether0.011589295507 72.429475449
0x0995fe24424fb5b012225a2a93a09e77e576ca8f74ad43612580a823d233c984Bond Withdrawal134811712021-10-24 16:10:4727 mins agoHop Protocol: Bonders IN  Hop Exchange: Bridge0 Ether0.01054236426 65.881541434
0xf21c1022b27bbb93a63d04d8ef9653544ec67fc0d95d3913eb20bd52dbfd38faBond Withdrawal134811482021-10-24 16:07:3331 mins agoHop Protocol: Bonders IN  Hop Exchange: Bridge0 Ether0.015838404747 98.977657464
0xacde63d768bd49e296a37e5a236a132622fecbfb528ba924c4400cec22b0d055Bond Withdrawal134809672021-10-24 15:27:311 hr 11 mins agoHop Protocol: Bonders IN  Hop Exchange: Bridge0 Ether0.013839448871 86.492230835
0x76a5efe98d85c07f8777b3d4009b2d8ec9353e044fc45d827adf642983641358Bond Withdrawal134807562021-10-24 14:37:002 hrs 1 min agoHop Protocol: Bonders IN  Hop Exchange: Bridge0 Ether0.010099492408 70.671287883
0x9c980403ff4503bdacdafde1d3066d6001bbcb538c01965ac1e88820df65c800Send To L2134807232021-10-24 14:29:072 hrs 9 mins ago0x95cf065063335ab425a2f0fcc1d86550b41d002b IN  Hop Exchange: Bridge0 Ether0.006034073497 57.818129961
0x15f083a63431efe19732d1bd3ae545d1d460d3231b13ff48299484e113337081Bond Withdrawal134807132021-10-24 14:26:412 hrs 12 mins agoHop Protocol: Bonders IN  Hop Exchange: Bridge0 Ether0.009490548357 59.312961588
0x52f8437bacdde494ed98d0e6282dfae16439cffed903a68a0de88434214732ceBond Withdrawal134806492021-10-24 14:13:352 hrs 25 mins agoHop Protocol: Bonders IN  Hop Exchange: Bridge0 Ether0.013118434819 81.986118313
0xdd87e8fb335689bcaea4626a0886e92b1f7758e9ee2cfc8d6fe2ed17ea225a1bBond Withdrawal134806202021-10-24 14:05:552 hrs 32 mins agoHop Protocol: Bonders IN  Hop Exchange: Bridge0 Ether0.010342195951 64.640340707
0x50c515cd0fe937e008f7c80062938c3d5f8dd977ac047980d5d0d6b612a04beaBond Transfer Ro...134806012021-10-24 14:01:322 hrs 37 mins agoHop Protocol: Bonders IN  Hop Exchange: Bridge0 Ether0.012188338887 73.489248776
0x7cc7dd71e3edf66f38014a6d776438c9522c74b5303c6cc5e315cc8b7028c5ddBond Withdrawal134804762021-10-24 13:32:353 hrs 6 mins agoHop Protocol: Bonders IN  Hop Exchange: Bridge0 Ether0.011112780813 69.451407513
0xd3de8b05f789a332578b66e19ca0b68434c1a276d015a32b82305317fd639c84Send To L2134804752021-10-24 13:32:163 hrs 6 mins ago0xb6ba3cd9e4f8f5ba416cdce42e5058a16b2c3609 IN  Hop Exchange: Bridge0 Ether0.00818812575
0x1bd7e21c6e9e3dfb5e5bc7b1aa9a63ca903e724ab26bd012f68259938c15be3bBond Withdrawal134804652021-10-24 13:29:513 hrs 8 mins agoHop Protocol: Bonders IN  Hop Exchange: Bridge0 Ether0.010656158215 66.597658962
0xebe4d3285ff90162b4ec6878e09442400a0280341f798d0c025c3718b3c96e53Settle Bonded Wi...134804632021-10-24 13:29:273 hrs 9 mins agoHop Protocol: Bonders IN  Hop Exchange: Bridge0 Ether0.004091417408 69.802733284
0x2e2c1cbbe55e339cdda25e30f9d6b227cd1d54e7a80be78154ee2bb1a2828c63Send To L2134803772021-10-24 13:07:433 hrs 30 mins ago0xfdd7c88db10a4e099337a09b1651a7fe5124d88f IN  Hop Exchange: Bridge0 Ether0.006262194219 59.997070365
0xb895cf77ae17628f584e585e79f818ef5f2b8c1444586a1e78aadec582d49535Bond Transfer Ro...134803692021-10-24 13:05:403 hrs 33 mins agoHop Protocol: Bonders IN  Hop Exchange: Bridge0 Ether0.011623829651 63.534859697
0x2a5b6f797e80719bf2c0c2cf8a19e091a804959c70aa5eed42bc50faf1429eb7Bond Withdrawal134802892021-10-24 12:48:063 hrs 50 mins agoHop Protocol: Bonders IN  Hop Exchange: Bridge0 Ether0.007989036908 49.928984232
0x8c1ba78d8dcb3a252d9e9afdeb32303ae90bae1d8a2131385b77a2dd4ec4dbf2Send To L2134802622021-10-24 12:40:483 hrs 57 mins ago0xdd5dd4a737c0e4a9cb4579e4e39fba8e18fbba5d IN  Hop Exchange: Bridge0 Ether0.007006516563 43.504144966
0xfa69cf15ad1b615e8da7958b732bd5c6a103f618e8ed0c39de6471fb5c0ce919Send To L2134801672021-10-24 12:24:114 hrs 14 mins ago0x7c74f84ab9d211b0ad306fd793c593b744135c49 IN  Hop Exchange: Bridge0 Ether0.006417204773 61.482201426
0x24bcc0a4bcfbb247893fd1655c827f18f44c395157b5fd9488452491e62d4218Send To L2134801422021-10-24 12:19:444 hrs 18 mins ago0xddb85e692bf8cac12b3e6766ab23b8e8e29781bb IN  Hop Exchange: Bridge0 Ether0.008905901868 81.565588109
0x744751f0ceda26b366b50fdadd951e36abd94947b9edff0e293109ca95b1bff2Settle Bonded Wi...134801022021-10-24 12:08:184 hrs 30 mins agoHop Protocol: Bonders IN  Hop Exchange: Bridge0 Ether0.003746602779 61.722257937
0xd49f98df51139d780ba47639193a81a4bb8f77d22dc73987f2600049f49a680cSend To L2134800422021-10-24 11:55:374 hrs 43 mins ago0x02b63fcfd6aa1d392e1eeb7ab3b45665a3ebd18a IN  Hop Exchange: Bridge0 Ether0.00446865652 42.803633377
0x08b026034d6b89a7ee0e75108487e9590a8b82b603fc3c20efa078d9b9eb6328Send To L2134800052021-10-24 11:48:444 hrs 49 mins ago0x22193c716480e1d97e436b83b80b5b1b9446dfb5 IN  Hop Exchange: Bridge0 Ether0.007806989779 48.474361267
[ Download CSV Export 
View more zero value Internal Transactions in Advanced View mode
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
L1_ERC20_Bridge

Compiler Version
v0.6.12+commit.27d51765

Optimization Enabled:
Yes with 50000 runs

Other Settings:
default evmVersion
File 1 of 11 : L1_ERC20_Bridge.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.6.12;
pragma experimental ABIEncoderV2;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/SafeERC20.sol";
import "./L1_Bridge.sol";

/**
 * @dev A L1_Bridge that uses an ERC20 as the canonical token
 */

contract L1_ERC20_Bridge is L1_Bridge {
    using SafeERC20 for IERC20;

    IERC20 public immutable l1CanonicalToken;

    constructor (IERC20 _l1CanonicalToken, address[] memory bonders, address _governance) public L1_Bridge(bonders, _governance) {
        l1CanonicalToken = _l1CanonicalToken;
    }

    /* ========== Override Functions ========== */

    function _transferFromBridge(address recipient, uint256 amount) internal override {
        l1CanonicalToken.safeTransfer(recipient, amount);
    }

    function _transferToBridge(address from, uint256 amount) internal override {
        l1CanonicalToken.safeTransferFrom(from, address(this), amount);
    }
}

File 2 of 11 : IERC20.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

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

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

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

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

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

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

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

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

File 3 of 11 : SafeERC20.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.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 IERC20;` 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));
    }

    /**
     * @dev Deprecated. This function has issues similar to the ones found in
     * {IERC20-approve}, and its usage is discouraged.
     *
     * Whenever possible, use {safeIncreaseAllowance} and
     * {safeDecreaseAllowance} instead.
     */
    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, "SafeERC20: decreased allowance below zero");
        _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. We use {Address.functionCall} to perform this call, which verifies that
        // the target address contains contract code and also asserts for success in the low-level call.

        bytes memory returndata = address(token).functionCall(data, "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 4 of 11 : L1_Bridge.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.6.12;
pragma experimental ABIEncoderV2;

import "./Bridge.sol";
import "../interfaces/IMessengerWrapper.sol";

/**
 * @dev L1_Bridge is responsible for the bonding and challenging of TransferRoots. All TransferRoots
 * originate in the L1_Bridge through `bondTransferRoot` and are propagated up to destination L2s.
 */

abstract contract L1_Bridge is Bridge {

    struct TransferBond {
        address bonder;
        uint256 createdAt;
        uint256 totalAmount;
        uint256 challengeStartTime;
        address challenger;
        bool challengeResolved;
    }

    /* ========== State ========== */

    mapping(bytes32 => uint256) public transferRootCommittedAt;
    mapping(bytes32 => TransferBond) public transferBonds;
    mapping(uint256 => mapping(address => uint256)) public timeSlotToAmountBonded;
    mapping(uint256 => uint256) public chainBalance;

    /* ========== Config State ========== */

    address public governance;
    mapping(uint256 => IMessengerWrapper) public crossDomainMessengerWrappers;
    mapping(uint256 => bool) public isChainIdPaused;
    uint256 public challengePeriod = 1 days;
    uint256 public challengeResolutionPeriod = 10 days;
    uint256 public minTransferRootBondDelay = 15 minutes;
    
    uint256 public constant CHALLENGE_AMOUNT_DIVISOR = 10;
    uint256 public constant TIME_SLOT_SIZE = 4 hours;

    /* ========== Events ========== */

    event TransferSentToL2(
        uint256 indexed chainId,
        address indexed recipient,
        uint256 amount,
        uint256 amountOutMin,
        uint256 deadline,
        address indexed relayer,
        uint256 relayerFee
    );

    event TransferRootBonded (
        bytes32 indexed root,
        uint256 amount
    );

    event TransferRootConfirmed(
        uint256 indexed originChainId,
        uint256 indexed destinationChainId,
        bytes32 indexed rootHash,
        uint256 totalAmount
    );

    event TransferBondChallenged(
        bytes32 indexed transferRootId,
        bytes32 indexed rootHash,
        uint256 originalAmount
    );

    event ChallengeResolved(
        bytes32 indexed transferRootId,
        bytes32 indexed rootHash,
        uint256 originalAmount
    );

    /* ========== Modifiers ========== */

    modifier onlyL2Bridge(uint256 chainId) {
        IMessengerWrapper messengerWrapper = crossDomainMessengerWrappers[chainId];
        messengerWrapper.verifySender(msg.sender, msg.data);
        _;
    }

    constructor (address[] memory bonders, address _governance) public Bridge(bonders) {
        governance = _governance;
    }

    /* ========== Send Functions ========== */

    /**
     * @notice `amountOutMin` and `deadline` should be 0 when no swap is intended at the destination.
     * @notice `amount` is the total amount the user wants to send including the relayer fee
     * @dev Send tokens to a supported layer-2 to mint hToken and optionally swap the hToken in the
     * AMM at the destination.
     * @param chainId The chainId of the destination chain
     * @param recipient The address receiving funds at the destination
     * @param amount The amount being sent
     * @param amountOutMin The minimum amount received after attempting to swap in the destination
     * AMM market. 0 if no swap is intended.
     * @param deadline The deadline for swapping in the destination AMM market. 0 if no
     * swap is intended.
     * @param relayer The address of the relayer at the destination.
     * @param relayerFee The amount distributed to the relayer at the destination. This is subtracted from the `amount`.
     */
    function sendToL2(
        uint256 chainId,
        address recipient,
        uint256 amount,
        uint256 amountOutMin,
        uint256 deadline,
        address relayer,
        uint256 relayerFee
    )
        external
        payable
    {
        IMessengerWrapper messengerWrapper = crossDomainMessengerWrappers[chainId];
        require(messengerWrapper != IMessengerWrapper(0), "L1_BRG: chainId not supported");
        require(isChainIdPaused[chainId] == false, "L1_BRG: Sends to this chainId are paused");
        require(amount > 0, "L1_BRG: Must transfer a non-zero amount");
        require(amount >= relayerFee, "L1_BRG: Relayer fee cannot exceed amount");

        _transferToBridge(msg.sender, amount);

        bytes memory message = abi.encodeWithSignature(
            "distribute(address,uint256,uint256,uint256,address,uint256)",
            recipient,
            amount,
            amountOutMin,
            deadline,
            relayer,
            relayerFee
        );

        chainBalance[chainId] = chainBalance[chainId].add(amount);
        messengerWrapper.sendCrossDomainMessage(message);

        emit TransferSentToL2(
            chainId,
            recipient,
            amount,
            amountOutMin,
            deadline,
            relayer,
            relayerFee
        );
    }

    /* ========== TransferRoot Functions ========== */

    /**
     * @dev Setting a TransferRoot is a two step process.
     * @dev   1. The TransferRoot is bonded with `bondTransferRoot`. Withdrawals can now begin on L1
     * @dev      and recipient L2's
     * @dev   2. The TransferRoot is confirmed after `confirmTransferRoot` is called by the l2 bridge
     * @dev      where the TransferRoot originated.
     */

    /**
     * @dev Used by the Bonder to bond a TransferRoot and propagate it up to destination L2s
     * @param rootHash The Merkle root of the TransferRoot Merkle tree
     * @param destinationChainId The id of the destination chain
     * @param totalAmount The amount destined for the destination chain
     */
    function bondTransferRoot(
        bytes32 rootHash,
        uint256 destinationChainId,
        uint256 totalAmount
    )
        external
        onlyBonder
        requirePositiveBalance
    {
        bytes32 transferRootId = getTransferRootId(rootHash, totalAmount);
        require(transferRootCommittedAt[transferRootId] == 0, "L1_BRG: TransferRoot has already been confirmed");
        require(transferBonds[transferRootId].createdAt == 0, "L1_BRG: TransferRoot has already been bonded");

        uint256 currentTimeSlot = getTimeSlot(block.timestamp);
        uint256 bondAmount = getBondForTransferAmount(totalAmount);
        timeSlotToAmountBonded[currentTimeSlot][msg.sender] = timeSlotToAmountBonded[currentTimeSlot][msg.sender].add(bondAmount);

        transferBonds[transferRootId] = TransferBond(
            msg.sender,
            block.timestamp,
            totalAmount,
            uint256(0),
            address(0),
            false
        );

        _distributeTransferRoot(rootHash, destinationChainId, totalAmount);

        emit TransferRootBonded(rootHash, totalAmount);
    }

    /**
     * @dev Used by an L2 bridge to confirm a TransferRoot via cross-domain message. Once a TransferRoot
     * has been confirmed, any challenge against that TransferRoot can be resolved as unsuccessful.
     * @param originChainId The id of the origin chain
     * @param rootHash The Merkle root of the TransferRoot Merkle tree
     * @param destinationChainId The id of the destination chain
     * @param totalAmount The amount destined for each destination chain
     * @param rootCommittedAt The block timestamp when the TransferRoot was committed on its origin chain
     */
    function confirmTransferRoot(
        uint256 originChainId,
        bytes32 rootHash,
        uint256 destinationChainId,
        uint256 totalAmount,
        uint256 rootCommittedAt
    )
        external
        onlyL2Bridge(originChainId)
    {
        bytes32 transferRootId = getTransferRootId(rootHash, totalAmount);
        require(transferRootCommittedAt[transferRootId] == 0, "L1_BRG: TransferRoot already confirmed");
        require(rootCommittedAt > 0, "L1_BRG: rootCommittedAt must be greater than 0");
        transferRootCommittedAt[transferRootId] = rootCommittedAt;
        chainBalance[originChainId] = chainBalance[originChainId].sub(totalAmount, "L1_BRG: Amount exceeds chainBalance. This indicates a layer-2 failure.");

        // If the TransferRoot was never bonded, distribute the TransferRoot.
        TransferBond storage transferBond = transferBonds[transferRootId];
        if (transferBond.createdAt == 0) {
            _distributeTransferRoot(rootHash, destinationChainId, totalAmount);
        }

        emit TransferRootConfirmed(originChainId, destinationChainId, rootHash, totalAmount);
    }

    function _distributeTransferRoot(
        bytes32 rootHash,
        uint256 chainId,
        uint256 totalAmount
    )
        internal
    {
        // Set TransferRoot on recipient Bridge
        if (chainId == getChainId()) {
            // Set L1 TransferRoot
            _setTransferRoot(rootHash, totalAmount);
        } else {
            chainBalance[chainId] = chainBalance[chainId].add(totalAmount);

            IMessengerWrapper messengerWrapper = crossDomainMessengerWrappers[chainId];
            require(messengerWrapper != IMessengerWrapper(0), "L1_BRG: chainId not supported");

            // Set L2 TransferRoot
            bytes memory setTransferRootMessage = abi.encodeWithSignature(
                "setTransferRoot(bytes32,uint256)",
                rootHash,
                totalAmount
            );
            messengerWrapper.sendCrossDomainMessage(setTransferRootMessage);
        }
    }

    /* ========== External TransferRoot Challenges ========== */

    /**
     * @dev Challenge a TransferRoot believed to be fraudulent
     * @param rootHash The Merkle root of the TransferRoot Merkle tree
     * @param originalAmount The total amount bonded for this TransferRoot
     */
    function challengeTransferBond(bytes32 rootHash, uint256 originalAmount) external payable {
        bytes32 transferRootId = getTransferRootId(rootHash, originalAmount);
        TransferBond storage transferBond = transferBonds[transferRootId];

        require(transferRootCommittedAt[transferRootId] == 0, "L1_BRG: TransferRoot has already been confirmed");
        require(transferBond.createdAt != 0, "L1_BRG: TransferRoot has not been bonded");
        uint256 challengePeriodEnd = transferBond.createdAt.add(challengePeriod);
        require(challengePeriodEnd >= block.timestamp, "L1_BRG: TransferRoot cannot be challenged after challenge period");
        require(transferBond.challengeStartTime == 0, "L1_BRG: TransferRoot already challenged");

        transferBond.challengeStartTime = block.timestamp;
        transferBond.challenger = msg.sender;

        // Move amount from timeSlotToAmountBonded to debit
        uint256 timeSlot = getTimeSlot(transferBond.createdAt);
        uint256 bondAmount = getBondForTransferAmount(originalAmount);
        address bonder = transferBond.bonder;
        timeSlotToAmountBonded[timeSlot][bonder] = timeSlotToAmountBonded[timeSlot][bonder].sub(bondAmount);

        _addDebit(transferBond.bonder, bondAmount);

        // Get stake for challenge
        uint256 challengeStakeAmount = getChallengeAmountForTransferAmount(originalAmount);
        _transferToBridge(msg.sender, challengeStakeAmount);

        emit TransferBondChallenged(transferRootId, rootHash, originalAmount);
    }

    /**
     * @dev Resolve a challenge after the `challengeResolutionPeriod` has passed
     * @param rootHash The Merkle root of the TransferRoot Merkle tree
     * @param originalAmount The total amount originally bonded for this TransferRoot
     */
    function resolveChallenge(bytes32 rootHash, uint256 originalAmount) external {
        bytes32 transferRootId = getTransferRootId(rootHash, originalAmount);
        TransferBond storage transferBond = transferBonds[transferRootId];

        require(transferBond.challengeStartTime != 0, "L1_BRG: TransferRoot has not been challenged");
        require(block.timestamp > transferBond.challengeStartTime.add(challengeResolutionPeriod), "L1_BRG: Challenge period has not ended");
        require(transferBond.challengeResolved == false, "L1_BRG: TransferRoot already resolved");
        transferBond.challengeResolved = true;

        uint256 challengeStakeAmount = getChallengeAmountForTransferAmount(originalAmount);

        if (transferRootCommittedAt[transferRootId] > 0) {
            // Invalid challenge

            if (transferBond.createdAt > transferRootCommittedAt[transferRootId].add(minTransferRootBondDelay)) {
                // Credit the bonder back with the bond amount plus the challenger's stake
                _addCredit(transferBond.bonder, getBondForTransferAmount(originalAmount).add(challengeStakeAmount));
            } else {
                // If the TransferRoot was bonded before it was committed, the challenger and Bonder
                // get their stake back. This discourages Bonders from tricking challengers into
                // challenging a valid TransferRoots that haven't yet been committed. It also ensures
                // that Bonders are not punished if a TransferRoot is bonded too soon in error.

                // Return the challenger's stake
                _addCredit(transferBond.challenger, challengeStakeAmount);
                // Credit the bonder back with the bond amount
                _addCredit(transferBond.bonder, getBondForTransferAmount(originalAmount));
            }
        } else {
            // Valid challenge
            // Burn 25% of the challengers stake
            _transferFromBridge(address(0xdead), challengeStakeAmount.mul(1).div(4));
            // Reward challenger with the remaining 75% of their stake plus 100% of the Bonder's stake
            _addCredit(transferBond.challenger, challengeStakeAmount.mul(7).div(4));
        }

        emit ChallengeResolved(transferRootId, rootHash, originalAmount);
    }

    /* ========== Override Functions ========== */

    function _additionalDebit(address bonder) internal view override returns (uint256) {
        uint256 currentTimeSlot = getTimeSlot(block.timestamp);
        uint256 bonded = 0;

        uint256 numTimeSlots = challengePeriod / TIME_SLOT_SIZE;
        for (uint256 i = 0; i < numTimeSlots; i++) {
            bonded = bonded.add(timeSlotToAmountBonded[currentTimeSlot - i][bonder]);
        }

        return bonded;
    }

    function _requireIsGovernance() internal override {
        require(governance == msg.sender, "L1_BRG: Caller is not the owner");
    }

    /* ========== External Config Management Setters ========== */

    function setGovernance(address _newGovernance) external onlyGovernance {
        require(_newGovernance != address(0), "L1_BRG: _newGovernance cannot be address(0)");
        governance = _newGovernance;
    }

    function setCrossDomainMessengerWrapper(uint256 chainId, IMessengerWrapper _crossDomainMessengerWrapper) external onlyGovernance {
        crossDomainMessengerWrappers[chainId] = _crossDomainMessengerWrapper;
    }

    function setChainIdDepositsPaused(uint256 chainId, bool isPaused) external onlyGovernance {
        isChainIdPaused[chainId] = isPaused;
    }

    function setChallengePeriod(uint256 _challengePeriod) external onlyGovernance {
        require(_challengePeriod % TIME_SLOT_SIZE == 0, "L1_BRG: challengePeriod must be divisible by TIME_SLOT_SIZE");

        challengePeriod = _challengePeriod;
    }

    function setChallengeResolutionPeriod(uint256 _challengeResolutionPeriod) external onlyGovernance {
        challengeResolutionPeriod = _challengeResolutionPeriod;
    }

    function setMinTransferRootBondDelay(uint256 _minTransferRootBondDelay) external onlyGovernance {
        minTransferRootBondDelay = _minTransferRootBondDelay;
    }

    /* ========== Public Getters ========== */

    function getBondForTransferAmount(uint256 amount) public pure returns (uint256) {
        // Bond covers amount plus a bounty to pay a potential challenger
        return amount.add(getChallengeAmountForTransferAmount(amount));
    }

    function getChallengeAmountForTransferAmount(uint256 amount) public pure returns (uint256) {
        // Bond covers amount plus a bounty to pay a potential challenger
        return amount.div(CHALLENGE_AMOUNT_DIVISOR);
    }

    function getTimeSlot(uint256 time) public pure returns (uint256) {
        return time / TIME_SLOT_SIZE;
    }
}

File 5 of 11 : SafeMath.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

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

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

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

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

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

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

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

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

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

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

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

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

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

File 6 of 11 : Address.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.2 <0.8.0;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

File 7 of 11 : Bridge.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.6.12;
pragma experimental ABIEncoderV2;

import "./Accounting.sol";
import "../libraries/Lib_MerkleTree.sol";

/**
 * @dev Bridge extends the accounting system and encapsulates the logic that is shared by both the
 * L1 and L2 Bridges. It allows to TransferRoots to be set by parent contracts and for those
 * TransferRoots to be withdrawn against. It also allows the bonder to bond and withdraw Transfers
 * directly through `bondWithdrawal` and then settle those bonds against their TransferRoot once it
 * has been set.
 */

abstract contract Bridge is Accounting {
    using Lib_MerkleTree for bytes32;

    struct TransferRoot {
        uint256 total;
        uint256 amountWithdrawn;
        uint256 createdAt;
    }

    /* ========== Events ========== */

    event Withdrew(
        bytes32 indexed transferId,
        address indexed recipient,
        uint256 amount,
        bytes32 transferNonce
    );

    event WithdrawalBonded(
        bytes32 indexed transferId,
        uint256 amount
    );

    event WithdrawalBondSettled(
        address indexed bonder,
        bytes32 indexed transferId,
        bytes32 indexed rootHash
    );

    event MultipleWithdrawalsSettled(
        address indexed bonder,
        bytes32 indexed rootHash,
        uint256 totalBondsSettled
    );

    event TransferRootSet(
        bytes32 indexed rootHash,
        uint256 totalAmount
    );

    /* ========== State ========== */

    mapping(bytes32 => TransferRoot) private _transferRoots;
    mapping(bytes32 => bool) private _spentTransferIds;
    mapping(address => mapping(bytes32 => uint256)) private _bondedWithdrawalAmounts;

    uint256 constant RESCUE_DELAY = 8 weeks;

    constructor(address[] memory bonders) public Accounting(bonders) {}

    /* ========== Public Getters ========== */

    /**
     * @dev Get the hash that represents an individual Transfer.
     * @param chainId The id of the destination chain
     * @param recipient The address receiving the Transfer
     * @param amount The amount being transferred including the `_bonderFee`
     * @param transferNonce Used to avoid transferId collisions
     * @param bonderFee The amount paid to the address that withdraws the Transfer
     * @param amountOutMin The minimum amount received after attempting to swap in the destination
     * AMM market. 0 if no swap is intended.
     * @param deadline The deadline for swapping in the destination AMM market. 0 if no
     * swap is intended.
     */
    function getTransferId(
        uint256 chainId,
        address recipient,
        uint256 amount,
        bytes32 transferNonce,
        uint256 bonderFee,
        uint256 amountOutMin,
        uint256 deadline
    )
        public
        pure
        returns (bytes32)
    {
        return keccak256(abi.encode(
            chainId,
            recipient,
            amount,
            transferNonce,
            bonderFee,
            amountOutMin,
            deadline
        ));
    }

    /**
     * @notice getChainId can be overridden by subclasses if needed for compatibility or testing purposes.
     * @dev Get the current chainId
     * @return chainId The current chainId
     */
    function getChainId() public virtual view returns (uint256 chainId) {
        this; // Silence state mutability warning without generating any additional byte code
        assembly {
            chainId := chainid()
        }
    }

    /**
     * @dev Get the TransferRoot id for a given rootHash and totalAmount
     * @param rootHash The Merkle root of the TransferRoot
     * @param totalAmount The total of all Transfers in the TransferRoot
     * @return The calculated transferRootId
     */
    function getTransferRootId(bytes32 rootHash, uint256 totalAmount) public pure returns (bytes32) {
        return keccak256(abi.encodePacked(rootHash, totalAmount));
    }

    /**
     * @dev Get the TransferRoot for a given rootHash and totalAmount
     * @param rootHash The Merkle root of the TransferRoot
     * @param totalAmount The total of all Transfers in the TransferRoot
     * @return The TransferRoot with the calculated transferRootId
     */
    function getTransferRoot(bytes32 rootHash, uint256 totalAmount) public view returns (TransferRoot memory) {
        return _transferRoots[getTransferRootId(rootHash, totalAmount)];
    }

    /**
     * @dev Get the amount bonded for the withdrawal of a transfer
     * @param bonder The Bonder of the withdrawal
     * @param transferId The Transfer's unique identifier
     * @return The amount bonded for a Transfer withdrawal
     */
    function getBondedWithdrawalAmount(address bonder, bytes32 transferId) external view returns (uint256) {
        return _bondedWithdrawalAmounts[bonder][transferId];
    }

    /**
     * @dev Get the spent status of a transfer ID
     * @param transferId The transfer's unique identifier
     * @return True if the transferId has been spent
     */
    function isTransferIdSpent(bytes32 transferId) external view returns (bool) {
        return _spentTransferIds[transferId];
    }

    /* ========== User/Relayer External Functions ========== */

    /**
     * @notice Can be called by anyone (recipient or relayer)
     * @dev Withdraw a Transfer from its destination bridge
     * @param recipient The address receiving the Transfer
     * @param amount The amount being transferred including the `_bonderFee`
     * @param transferNonce Used to avoid transferId collisions
     * @param bonderFee The amount paid to the address that withdraws the Transfer
     * @param amountOutMin The minimum amount received after attempting to swap in the destination
     * AMM market. 0 if no swap is intended. (only used to calculate `transferId` in this function)
     * @param deadline The deadline for swapping in the destination AMM market. 0 if no
     * swap is intended. (only used to calculate `transferId` in this function)
     * @param rootHash The Merkle root of the TransferRoot
     * @param transferRootTotalAmount The total amount being transferred in a TransferRoot
     * @param transferIdTreeIndex The index of the transferId in the Merkle tree
     * @param siblings The siblings of the transferId in the Merkle tree
     * @param totalLeaves The total number of leaves in the Merkle tree
     */
    function withdraw(
        address recipient,
        uint256 amount,
        bytes32 transferNonce,
        uint256 bonderFee,
        uint256 amountOutMin,
        uint256 deadline,
        bytes32 rootHash,
        uint256 transferRootTotalAmount,
        uint256 transferIdTreeIndex,
        bytes32[] calldata siblings,
        uint256 totalLeaves
    )
        external
        nonReentrant
    {
        bytes32 transferId = getTransferId(
            getChainId(),
            recipient,
            amount,
            transferNonce,
            bonderFee,
            amountOutMin,
            deadline
        );

        require(
            rootHash.verify(
                transferId,
                transferIdTreeIndex,
                siblings,
                totalLeaves
            )
        , "BRG: Invalid transfer proof");
        bytes32 transferRootId = getTransferRootId(rootHash, transferRootTotalAmount);
        _addToAmountWithdrawn(transferRootId, amount);
        _fulfillWithdraw(transferId, recipient, amount, uint256(0));

        emit Withdrew(transferId, recipient, amount, transferNonce);
    }

    /**
     * @dev Allows the bonder to bond individual withdrawals before their TransferRoot has been committed.
     * @param recipient The address receiving the Transfer
     * @param amount The amount being transferred including the `_bonderFee`
     * @param transferNonce Used to avoid transferId collisions
     * @param bonderFee The amount paid to the address that withdraws the Transfer
     */
    function bondWithdrawal(
        address recipient,
        uint256 amount,
        bytes32 transferNonce,
        uint256 bonderFee
    )
        external
        onlyBonder
        requirePositiveBalance
        nonReentrant
    {
        bytes32 transferId = getTransferId(
            getChainId(),
            recipient,
            amount,
            transferNonce,
            bonderFee,
            0,
            0
        );

        _bondWithdrawal(transferId, amount);
        _fulfillWithdraw(transferId, recipient, amount, bonderFee);
    }

    /**
     * @dev Refunds the Bonder's stake from a bonded withdrawal and counts that withdrawal against
     * its TransferRoot.
     * @param bonder The Bonder of the withdrawal
     * @param transferId The Transfer's unique identifier
     * @param rootHash The Merkle root of the TransferRoot
     * @param transferRootTotalAmount The total amount being transferred in a TransferRoot
     * @param transferIdTreeIndex The index of the transferId in the Merkle tree
     * @param siblings The siblings of the transferId in the Merkle tree
     * @param totalLeaves The total number of leaves in the Merkle tree
     */
    function settleBondedWithdrawal(
        address bonder,
        bytes32 transferId,
        bytes32 rootHash,
        uint256 transferRootTotalAmount,
        uint256 transferIdTreeIndex,
        bytes32[] calldata siblings,
        uint256 totalLeaves
    )
        external
    {
        require(
            rootHash.verify(
                transferId,
                transferIdTreeIndex,
                siblings,
                totalLeaves
            )
        , "BRG: Invalid transfer proof");
        bytes32 transferRootId = getTransferRootId(rootHash, transferRootTotalAmount);

        uint256 amount = _bondedWithdrawalAmounts[bonder][transferId];
        require(amount > 0, "L2_BRG: transferId has no bond");

        _bondedWithdrawalAmounts[bonder][transferId] = 0;
        _addToAmountWithdrawn(transferRootId, amount);
        _addCredit(bonder, amount);

        emit WithdrawalBondSettled(bonder, transferId, rootHash);
    }

    /**
     * @dev Refunds the Bonder for all withdrawals that they bonded in a TransferRoot.
     * @param bonder The address of the Bonder being refunded
     * @param transferIds All transferIds in the TransferRoot in order
     * @param totalAmount The totalAmount of the TransferRoot
     */
    function settleBondedWithdrawals(
        address bonder,
        // transferIds _must_ be calldata or it will be mutated by Lib_MerkleTree.getMerkleRoot
        bytes32[] calldata transferIds,
        uint256 totalAmount
    )
        external
    {
        bytes32 rootHash = Lib_MerkleTree.getMerkleRoot(transferIds);
        bytes32 transferRootId = getTransferRootId(rootHash, totalAmount);

        uint256 totalBondsSettled = 0;
        for(uint256 i = 0; i < transferIds.length; i++) {
            uint256 transferBondAmount = _bondedWithdrawalAmounts[bonder][transferIds[i]];
            if (transferBondAmount > 0) {
                totalBondsSettled = totalBondsSettled.add(transferBondAmount);
                _bondedWithdrawalAmounts[bonder][transferIds[i]] = 0;
            }
        }

        _addToAmountWithdrawn(transferRootId, totalBondsSettled);
        _addCredit(bonder, totalBondsSettled);

        emit MultipleWithdrawalsSettled(bonder, rootHash, totalBondsSettled);
    }

    /* ========== External TransferRoot Rescue ========== */

    /**
     * @dev Allows governance to withdraw the remaining amount from a TransferRoot after the rescue delay has passed.
     * @param rootHash the Merkle root of the TransferRoot
     * @param originalAmount The TransferRoot's recorded total
     * @param recipient The address receiving the remaining balance
     */
    function rescueTransferRoot(bytes32 rootHash, uint256 originalAmount, address recipient) external onlyGovernance {
        bytes32 transferRootId = getTransferRootId(rootHash, originalAmount);
        TransferRoot memory transferRoot = getTransferRoot(rootHash, originalAmount);

        require(transferRoot.createdAt != 0, "BRG: TransferRoot not found");
        assert(transferRoot.total == originalAmount);
        uint256 rescueDelayEnd = transferRoot.createdAt.add(RESCUE_DELAY);
        require(block.timestamp >= rescueDelayEnd, "BRG: TransferRoot cannot be rescued before the Rescue Delay");

        uint256 remainingAmount = transferRoot.total.sub(transferRoot.amountWithdrawn);
        _addToAmountWithdrawn(transferRootId, remainingAmount);
        _transferFromBridge(recipient, remainingAmount);
    }

    /* ========== Internal Functions ========== */

    function _markTransferSpent(bytes32 transferId) internal {
        require(!_spentTransferIds[transferId], "BRG: The transfer has already been withdrawn");
        _spentTransferIds[transferId] = true;
    }

    function _addToAmountWithdrawn(bytes32 transferRootId, uint256 amount) internal {
        TransferRoot storage transferRoot = _transferRoots[transferRootId];
        require(transferRoot.total > 0, "BRG: Transfer root not found");

        uint256 newAmountWithdrawn = transferRoot.amountWithdrawn.add(amount);
        require(newAmountWithdrawn <= transferRoot.total, "BRG: Withdrawal exceeds TransferRoot total");

        transferRoot.amountWithdrawn = newAmountWithdrawn;
    }

    function _setTransferRoot(bytes32 rootHash, uint256 totalAmount) internal {
        bytes32 transferRootId = getTransferRootId(rootHash, totalAmount);
        require(_transferRoots[transferRootId].total == 0, "BRG: Transfer root already set");
        require(totalAmount > 0, "BRG: Cannot set TransferRoot totalAmount of 0");

        _transferRoots[transferRootId] = TransferRoot(totalAmount, 0, block.timestamp);

        emit TransferRootSet(rootHash, totalAmount);
    }

    function _bondWithdrawal(bytes32 transferId, uint256 amount) internal {
        require(_bondedWithdrawalAmounts[msg.sender][transferId] == 0, "BRG: Withdrawal has already been bonded");
        _addDebit(msg.sender, amount);
        _bondedWithdrawalAmounts[msg.sender][transferId] = amount;

        emit WithdrawalBonded(transferId, amount);
    }

    /* ========== Private Functions ========== */

    /// @dev Completes the Transfer, distributes the Bonder fee and marks the Transfer as spent.
    function _fulfillWithdraw(
        bytes32 transferId,
        address recipient,
        uint256 amount,
        uint256 bonderFee
    ) private {
        _markTransferSpent(transferId);
        _transferFromBridge(recipient, amount.sub(bonderFee));
        if (bonderFee > 0) {
            _transferFromBridge(msg.sender, bonderFee);
        }
    }
}

File 8 of 11 : IMessengerWrapper.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.12 <0.8.0;
pragma experimental ABIEncoderV2;

interface IMessengerWrapper {
    function sendCrossDomainMessage(bytes memory _calldata) external;
    function verifySender(address l1BridgeCaller, bytes memory _data) external;
}

File 9 of 11 : Accounting.sol
// SPDX-License-Identifier: MIT

pragma solidity 0.6.12;
pragma experimental ABIEncoderV2;

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

/**
 * @dev Accounting is an abstract contract that encapsulates the most critical logic in the Hop contracts.
 * The accounting system works by using two balances that can only increase `_credit` and `_debit`.
 * A bonder's available balance is the total credit minus the total debit. The contract exposes
 * two external functions that allows a bonder to stake and unstake and exposes two internal
 * functions to its child contracts that allow the child contract to add to the credit 
 * and debit balance. In addition, child contracts can override `_additionalDebit` to account
 * for any additional debit balance in an alternative way. Lastly, it exposes a modifier,
 * `requirePositiveBalance`, that can be used by child contracts to ensure the bonder does not
 * use more than its available stake.
 */

abstract contract Accounting is ReentrancyGuard {
    using SafeMath for uint256;

    mapping(address => bool) private _isBonder;

    mapping(address => uint256) private _credit;
    mapping(address => uint256) private _debit;

    event Stake (
        address indexed account,
        uint256 amount
    );

    event Unstake (
        address indexed account,
        uint256 amount
    );

    event BonderAdded (
        address indexed newBonder
    );

    event BonderRemoved (
        address indexed previousBonder
    );

    /* ========== Modifiers ========== */

    modifier onlyBonder {
        require(_isBonder[msg.sender], "ACT: Caller is not bonder");
        _;
    }

    modifier onlyGovernance {
        _requireIsGovernance();
        _;
    }

    /// @dev Used by parent contract to ensure that the Bonder is solvent at the end of the transaction.
    modifier requirePositiveBalance {
        _;
        require(getCredit(msg.sender) >= getDebitAndAdditionalDebit(msg.sender), "ACT: Not enough available credit");
    }

    /// @dev Sets the Bonder addresses
    constructor(address[] memory bonders) public {
        for (uint256 i = 0; i < bonders.length; i++) {
            require(_isBonder[bonders[i]] == false, "ACT: Cannot add duplicate bonder");
            _isBonder[bonders[i]] = true;
            emit BonderAdded(bonders[i]);
        }
    }

    /* ========== Virtual functions ========== */
    /**
     * @dev The following functions are overridden in L1_Bridge and L2_Bridge
     */
    function _transferFromBridge(address recipient, uint256 amount) internal virtual;
    function _transferToBridge(address from, uint256 amount) internal virtual;
    function _requireIsGovernance() internal virtual;

    /**
     * @dev This function can be optionally overridden by a parent contract to track any additional
     * debit balance in an alternative way.
     */
    function _additionalDebit(address /*bonder*/) internal view virtual returns (uint256) {
        this; // Silence state mutability warning without generating any additional byte code
        return 0;
    }

    /* ========== Public/external getters ========== */

    /**
     * @dev Check if address is a Bonder
     * @param maybeBonder The address being checked
     * @return true if address is a Bonder
     */
    function getIsBonder(address maybeBonder) public view returns (bool) {
        return _isBonder[maybeBonder];
    }

    /**
     * @dev Get the Bonder's credit balance
     * @param bonder The owner of the credit balance being checked
     * @return The credit balance for the Bonder
     */
    function getCredit(address bonder) public view returns (uint256) {
        return _credit[bonder];
    }

    /**
     * @dev Gets the debit balance tracked by `_debit` and does not include `_additionalDebit()`
     * @param bonder The owner of the debit balance being checked
     * @return The debit amount for the Bonder
     */
    function getRawDebit(address bonder) external view returns (uint256) {
        return _debit[bonder];
    }

    /**
     * @dev Get the Bonder's total debit
     * @param bonder The owner of the debit balance being checked
     * @return The Bonder's total debit balance
     */
    function getDebitAndAdditionalDebit(address bonder) public view returns (uint256) {
        return _debit[bonder].add(_additionalDebit(bonder));
    }

    /* ========== Bonder external functions ========== */

    /** 
     * @dev Allows the Bonder to deposit tokens and increase its credit balance
     * @param bonder The address being staked on
     * @param amount The amount being staked
     */
    function stake(address bonder, uint256 amount) external payable nonReentrant {
        require(_isBonder[bonder] == true, "ACT: Address is not bonder");
        _transferToBridge(msg.sender, amount);
        _addCredit(bonder, amount);

        emit Stake(bonder, amount);
    }

    /**
     * @dev Allows the caller to withdraw any available balance and add to their debit balance
     * @param amount The amount being unstaked
     */
    function unstake(uint256 amount) external requirePositiveBalance nonReentrant {
        _addDebit(msg.sender, amount);
        _transferFromBridge(msg.sender, amount);

        emit Unstake(msg.sender, amount);
    }

    /**
     * @dev Add Bonder to allowlist
     * @param bonder The address being added as a Bonder
     */
    function addBonder(address bonder) external onlyGovernance {
        require(_isBonder[bonder] == false, "ACT: Address is already bonder");
        _isBonder[bonder] = true;

        emit BonderAdded(bonder);
    }

    /**
     * @dev Remove Bonder from allowlist
     * @param bonder The address being removed as a Bonder
     */
    function removeBonder(address bonder) external onlyGovernance {
        require(_isBonder[bonder] == true, "ACT: Address is not bonder");
        _isBonder[bonder] = false;

        emit BonderRemoved(bonder);
    }

    /* ========== Internal functions ========== */

    function _addCredit(address bonder, uint256 amount) internal {
        _credit[bonder] = _credit[bonder].add(amount);
    }

    function _addDebit(address bonder, uint256 amount) internal {
        _debit[bonder] = _debit[bonder].add(amount);
    }
}

File 10 of 11 : Lib_MerkleTree.sol
// SPDX-License-Identifier: MIT
pragma solidity >0.5.0 <0.8.0;

/**
 * @title Lib_MerkleTree
 * @author River Keefer
 */
library Lib_MerkleTree {

    /**********************
     * Internal Functions *
     **********************/

    /**
     * Calculates a merkle root for a list of 32-byte leaf hashes.  WARNING: If the number
     * of leaves passed in is not a power of two, it pads out the tree with zero hashes.
     * If you do not know the original length of elements for the tree you are verifying,
     * then this may allow empty leaves past _elements.length to pass a verification check down the line.
     * Note that the _elements argument is modified, therefore it must not be used again afterwards
     * @param _elements Array of hashes from which to generate a merkle root.
     * @return Merkle root of the leaves, with zero hashes for non-powers-of-two (see above).
     */
    function getMerkleRoot(
        bytes32[] memory _elements
    )
        internal
        pure
        returns (
            bytes32
        )
    {
        require(
            _elements.length > 0,
            "Lib_MerkleTree: Must provide at least one leaf hash."
        );

        if (_elements.length == 1) {
            return _elements[0];
        }

        uint256[16] memory defaults = [
            0x290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e563,
            0x633dc4d7da7256660a892f8f1604a44b5432649cc8ec5cb3ced4c4e6ac94dd1d,
            0x890740a8eb06ce9be422cb8da5cdafc2b58c0a5e24036c578de2a433c828ff7d,
            0x3b8ec09e026fdc305365dfc94e189a81b38c7597b3d941c279f042e8206e0bd8,
            0xecd50eee38e386bd62be9bedb990706951b65fe053bd9d8a521af753d139e2da,
            0xdefff6d330bb5403f63b14f33b578274160de3a50df4efecf0e0db73bcdd3da5,
            0x617bdd11f7c0a11f49db22f629387a12da7596f9d1704d7465177c63d88ec7d7,
            0x292c23a9aa1d8bea7e2435e555a4a60e379a5a35f3f452bae60121073fb6eead,
            0xe1cea92ed99acdcb045a6726b2f87107e8a61620a232cf4d7d5b5766b3952e10,
            0x7ad66c0a68c72cb89e4fb4303841966e4062a76ab97451e3b9fb526a5ceb7f82,
            0xe026cc5a4aed3c22a58cbd3d2ac754c9352c5436f638042dca99034e83636516,
            0x3d04cffd8b46a874edf5cfae63077de85f849a660426697b06a829c70dd1409c,
            0xad676aa337a485e4728a0b240d92b3ef7b3c372d06d189322bfd5f61f1e7203e,
            0xa2fca4a49658f9fab7aa63289c91b7c7b6c832a6d0e69334ff5b0a3483d09dab,
            0x4ebfd9cd7bca2505f7bef59cc1c12ecc708fff26ae4af19abe852afe9e20c862,
            0x2def10d13dd169f550f578bda343d9717a138562e0093b380a1120789d53cf10
        ];

        // Reserve memory space for our hashes.
        bytes memory buf = new bytes(64);

        // We'll need to keep track of left and right siblings.
        bytes32 leftSibling;
        bytes32 rightSibling;

        // Number of non-empty nodes at the current depth.
        uint256 rowSize = _elements.length;

        // Current depth, counting from 0 at the leaves
        uint256 depth = 0;

        // Common sub-expressions
        uint256 halfRowSize;         // rowSize / 2
        bool rowSizeIsOdd;           // rowSize % 2 == 1

        while (rowSize > 1) {
            halfRowSize = rowSize / 2;
            rowSizeIsOdd = rowSize % 2 == 1;

            for (uint256 i = 0; i < halfRowSize; i++) {
                leftSibling  = _elements[(2 * i)    ];
                rightSibling = _elements[(2 * i) + 1];
                assembly {
                    mstore(add(buf, 32), leftSibling )
                    mstore(add(buf, 64), rightSibling)
                }

                _elements[i] = keccak256(buf);
            }

            if (rowSizeIsOdd) {
                leftSibling  = _elements[rowSize - 1];
                rightSibling = bytes32(defaults[depth]);
                assembly {
                    mstore(add(buf, 32), leftSibling)
                    mstore(add(buf, 64), rightSibling)
                }

                _elements[halfRowSize] = keccak256(buf);
            }

            rowSize = halfRowSize + (rowSizeIsOdd ? 1 : 0);
            depth++;
        }

        return _elements[0];
    }

    /**
     * Verifies a merkle branch for the given leaf hash.  Assumes the original length
     * of leaves generated is a known, correct input, and does not return true for indices
     * extending past that index (even if _siblings would be otherwise valid.)
     * @param _root The Merkle root to verify against.
     * @param _leaf The leaf hash to verify inclusion of.
     * @param _index The index in the tree of this leaf.
     * @param _siblings Array of sibline nodes in the inclusion proof, starting from depth 0 (bottom of the tree).
     * @param _totalLeaves The total number of leaves originally passed into.
     * @return Whether or not the merkle branch and leaf passes verification.
     */
    function verify(
        bytes32 _root,
        bytes32 _leaf,
        uint256 _index,
        bytes32[] memory _siblings,
        uint256 _totalLeaves
    )
        internal
        pure
        returns (
            bool
        )
    {
        require(
            _totalLeaves > 0,
            "Lib_MerkleTree: Total leaves must be greater than zero."
        );

        require(
            _index < _totalLeaves,
            "Lib_MerkleTree: Index out of bounds."
        );

        require(
            _siblings.length == _ceilLog2(_totalLeaves),
            "Lib_MerkleTree: Total siblings does not correctly correspond to total leaves."
        );

        bytes32 computedRoot = _leaf;

        for (uint256 i = 0; i < _siblings.length; i++) {
            if ((_index & 1) == 1) {
                computedRoot = keccak256(
                    abi.encodePacked(
                        _siblings[i],
                        computedRoot
                    )
                );
            } else {
                computedRoot = keccak256(
                    abi.encodePacked(
                        computedRoot,
                        _siblings[i]
                    )
                );
            }

            _index >>= 1;
        }

        return _root == computedRoot;
    }


    /*********************
     * Private Functions *
     *********************/

    /**
     * Calculates the integer ceiling of the log base 2 of an input.
     * @param _in Unsigned input to calculate the log.
     * @return ceil(log_base_2(_in))
     */
    function _ceilLog2(
        uint256 _in
    )
        private
        pure
        returns (
            uint256
        )
    {
        require(
            _in > 0,
            "Lib_MerkleTree: Cannot compute ceil(log_2) of 0."
        );

        if (_in == 1) {
            return 0;
        }

        // Find the highest set bit (will be floor(log_2)).
        // Borrowed with <3 from https://github.com/ethereum/solidity-examples
        uint256 val = _in;
        uint256 highest = 0;
        for (uint256 i = 128; i >= 1; i >>= 1) {
            if (val & (uint(1) << i) - 1 << i != 0) {
                highest += i;
                val >>= i;
            }
        }

        // Increment by one if this is not a perfect logarithm.
        if ((uint(1) << highest) != _in) {
            highest += 1;
        }

        return highest;
    }
}

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

pragma solidity >=0.6.0 <0.8.0;

/**
 * @dev Contract module that helps prevent reentrant calls to a function.
 *
 * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
 * available, which can be applied to functions to make sure there are no nested
 * (reentrant) calls to them.
 *
 * Note that because there is a single `nonReentrant` guard, functions marked as
 * `nonReentrant` may not call one another. This can be worked around by making
 * those functions `private`, and then adding `external` `nonReentrant` entry
 * points to them.
 *
 * TIP: If you would like to learn more about reentrancy and alternative ways
 * to protect against it, check out our blog post
 * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
 */
abstract contract ReentrancyGuard {
    // Booleans are more expensive than uint256 or any type that takes up a full
    // word because each write operation emits an extra SLOAD to first read the
    // slot's contents, replace the bits taken up by the boolean, and then write
    // back. This is the compiler's defense against contract upgrades and
    // pointer aliasing, and it cannot be disabled.

    // The values being non-zero value makes deployment a bit more expensive,
    // but in exchange the refund on every call to nonReentrant will be lower in
    // amount. Since refunds are capped to a percentage of the total
    // transaction's gas, it is best to keep them low in cases like this one, to
    // increase the likelihood of the full refund coming into effect.
    uint256 private constant _NOT_ENTERED = 1;
    uint256 private constant _ENTERED = 2;

    uint256 private _status;

    constructor () internal {
        _status = _NOT_ENTERED;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and make it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        // On the first call to nonReentrant, _notEntered will be true
        require(_status != _ENTERED, "ReentrancyGuard: reentrant call");

        // Any calls to nonReentrant after this point will fail
        _status = _ENTERED;

        _;

        // By storing the original value once again, a refund is triggered (see
        // https://eips.ethereum.org/EIPS/eip-2200)
        _status = _NOT_ENTERED;
    }
}

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

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"contract IERC20","name":"_l1CanonicalToken","type":"address"},{"internalType":"address[]","name":"bonders","type":"address[]"},{"internalType":"address","name":"_governance","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"newBonder","type":"address"}],"name":"BonderAdded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousBonder","type":"address"}],"name":"BonderRemoved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"transferRootId","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"rootHash","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"originalAmount","type":"uint256"}],"name":"ChallengeResolved","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"bonder","type":"address"},{"indexed":true,"internalType":"bytes32","name":"rootHash","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"totalBondsSettled","type":"uint256"}],"name":"MultipleWithdrawalsSettled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Stake","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"transferRootId","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"rootHash","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"originalAmount","type":"uint256"}],"name":"TransferBondChallenged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"root","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"TransferRootBonded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"originChainId","type":"uint256"},{"indexed":true,"internalType":"uint256","name":"destinationChainId","type":"uint256"},{"indexed":true,"internalType":"bytes32","name":"rootHash","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"totalAmount","type":"uint256"}],"name":"TransferRootConfirmed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"rootHash","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"totalAmount","type":"uint256"}],"name":"TransferRootSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"chainId","type":"uint256"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"deadline","type":"uint256"},{"indexed":true,"internalType":"address","name":"relayer","type":"address"},{"indexed":false,"internalType":"uint256","name":"relayerFee","type":"uint256"}],"name":"TransferSentToL2","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"Unstake","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"bonder","type":"address"},{"indexed":true,"internalType":"bytes32","name":"transferId","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"rootHash","type":"bytes32"}],"name":"WithdrawalBondSettled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"transferId","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"}],"name":"WithdrawalBonded","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"transferId","type":"bytes32"},{"indexed":true,"internalType":"address","name":"recipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"bytes32","name":"transferNonce","type":"bytes32"}],"name":"Withdrew","type":"event"},{"inputs":[],"name":"CHALLENGE_AMOUNT_DIVISOR","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TIME_SLOT_SIZE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"bonder","type":"address"}],"name":"addBonder","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"rootHash","type":"bytes32"},{"internalType":"uint256","name":"destinationChainId","type":"uint256"},{"internalType":"uint256","name":"totalAmount","type":"uint256"}],"name":"bondTransferRoot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes32","name":"transferNonce","type":"bytes32"},{"internalType":"uint256","name":"bonderFee","type":"uint256"}],"name":"bondWithdrawal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"chainBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"challengePeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"challengeResolutionPeriod","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"rootHash","type":"bytes32"},{"internalType":"uint256","name":"originalAmount","type":"uint256"}],"name":"challengeTransferBond","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"originChainId","type":"uint256"},{"internalType":"bytes32","name":"rootHash","type":"bytes32"},{"internalType":"uint256","name":"destinationChainId","type":"uint256"},{"internalType":"uint256","name":"totalAmount","type":"uint256"},{"internalType":"uint256","name":"rootCommittedAt","type":"uint256"}],"name":"confirmTransferRoot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"crossDomainMessengerWrappers","outputs":[{"internalType":"contract IMessengerWrapper","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"getBondForTransferAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"bonder","type":"address"},{"internalType":"bytes32","name":"transferId","type":"bytes32"}],"name":"getBondedWithdrawalAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getChainId","outputs":[{"internalType":"uint256","name":"chainId","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"getChallengeAmountForTransferAmount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"bonder","type":"address"}],"name":"getCredit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"bonder","type":"address"}],"name":"getDebitAndAdditionalDebit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"maybeBonder","type":"address"}],"name":"getIsBonder","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"bonder","type":"address"}],"name":"getRawDebit","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"time","type":"uint256"}],"name":"getTimeSlot","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"chainId","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes32","name":"transferNonce","type":"bytes32"},{"internalType":"uint256","name":"bonderFee","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"getTransferId","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"bytes32","name":"rootHash","type":"bytes32"},{"internalType":"uint256","name":"totalAmount","type":"uint256"}],"name":"getTransferRoot","outputs":[{"components":[{"internalType":"uint256","name":"total","type":"uint256"},{"internalType":"uint256","name":"amountWithdrawn","type":"uint256"},{"internalType":"uint256","name":"createdAt","type":"uint256"}],"internalType":"struct Bridge.TransferRoot","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"rootHash","type":"bytes32"},{"internalType":"uint256","name":"totalAmount","type":"uint256"}],"name":"getTransferRootId","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"governance","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"isChainIdPaused","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"transferId","type":"bytes32"}],"name":"isTransferIdSpent","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"l1CanonicalToken","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minTransferRootBondDelay","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"bonder","type":"address"}],"name":"removeBonder","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"rootHash","type":"bytes32"},{"internalType":"uint256","name":"originalAmount","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"}],"name":"rescueTransferRoot","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"rootHash","type":"bytes32"},{"internalType":"uint256","name":"originalAmount","type":"uint256"}],"name":"resolveChallenge","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"chainId","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"address","name":"relayer","type":"address"},{"internalType":"uint256","name":"relayerFee","type":"uint256"}],"name":"sendToL2","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"chainId","type":"uint256"},{"internalType":"bool","name":"isPaused","type":"bool"}],"name":"setChainIdDepositsPaused","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_challengePeriod","type":"uint256"}],"name":"setChallengePeriod","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_challengeResolutionPeriod","type":"uint256"}],"name":"setChallengeResolutionPeriod","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"chainId","type":"uint256"},{"internalType":"contract IMessengerWrapper","name":"_crossDomainMessengerWrapper","type":"address"}],"name":"setCrossDomainMessengerWrapper","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newGovernance","type":"address"}],"name":"setGovernance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_minTransferRootBondDelay","type":"uint256"}],"name":"setMinTransferRootBondDelay","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"bonder","type":"address"},{"internalType":"bytes32","name":"transferId","type":"bytes32"},{"internalType":"bytes32","name":"rootHash","type":"bytes32"},{"internalType":"uint256","name":"transferRootTotalAmount","type":"uint256"},{"internalType":"uint256","name":"transferIdTreeIndex","type":"uint256"},{"internalType":"bytes32[]","name":"siblings","type":"bytes32[]"},{"internalType":"uint256","name":"totalLeaves","type":"uint256"}],"name":"settleBondedWithdrawal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"bonder","type":"address"},{"internalType":"bytes32[]","name":"transferIds","type":"bytes32[]"},{"internalType":"uint256","name":"totalAmount","type":"uint256"}],"name":"settleBondedWithdrawals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"bonder","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"stake","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"}],"name":"timeSlotToAmountBonded","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"transferBonds","outputs":[{"internalType":"address","name":"bonder","type":"address"},{"internalType":"uint256","name":"createdAt","type":"uint256"},{"internalType":"uint256","name":"totalAmount","type":"uint256"},{"internalType":"uint256","name":"challengeStartTime","type":"uint256"},{"internalType":"address","name":"challenger","type":"address"},{"internalType":"bool","name":"challengeResolved","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"transferRootCommittedAt","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"unstake","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"bytes32","name":"transferNonce","type":"bytes32"},{"internalType":"uint256","name":"bonderFee","type":"uint256"},{"internalType":"uint256","name":"amountOutMin","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"bytes32","name":"rootHash","type":"bytes32"},{"internalType":"uint256","name":"transferRootTotalAmount","type":"uint256"},{"internalType":"uint256","name":"transferIdTreeIndex","type":"uint256"},{"internalType":"bytes32[]","name":"siblings","type":"bytes32[]"},{"internalType":"uint256","name":"totalLeaves","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60a060405262015180600e55620d2f00600f556103846010553480156200002557600080fd5b5060405162004eaa38038062004eaa8339810160408190526200004891620001b6565b81818180600160008190555060005b81518110156200016657600160008383815181106200007257fe5b6020908102919091018101516001600160a01b031682528101919091526040016000205460ff1615620000c25760405162461bcd60e51b8152600401620000b9906200028a565b60405180910390fd5b6001806000848481518110620000d457fe5b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff0219169083151502179055508181815181106200012057fe5b60200260200101516001600160a01b03167f2cec73b7434d3b91198ad1a618f63e6a0761ce281af5ec9ec76606d948d03e2360405160405180910390a260010162000057565b5050600b80546001600160a01b0319166001600160a01b0393909316929092179091555050505060601b6001600160601b0319166080526200031f565b8051620001b08162000306565b92915050565b600080600060608486031215620001cb578283fd5b8351620001d88162000306565b602085810151919450906001600160401b03811115620001f6578384fd5b8501601f8101871362000207578384fd5b80516200021e6200021882620002e6565b620002bf565b81815283810190838501858402850186018b10156200023b578788fd5b8794505b838510156200026957620002548b82620001a3565b8352600194909401939185019185016200023f565b508096505050505050620002818560408601620001a3565b90509250925092565b6020808252818101527f4143543a2043616e6e6f7420616464206475706c696361746520626f6e646572604082015260600190565b6040518181016001600160401b0381118282101715620002de57600080fd5b604052919050565b60006001600160401b03821115620002fc578081fd5b5060209081020190565b6001600160a01b03811681146200031c57600080fd5b50565b60805160601c614b63620003476000398061190e52806127d75280612b155250614b636000f3fe6080604052600436106102fd5760003560e01c8063960a7afa1161018f578063cbd1642e116100e1578063eecd57e61161008a578063fa2a69a311610064578063fa2a69a314610834578063fc110b6714610854578063ffa9286c14610874576102fd565b8063eecd57e6146107df578063ef6ebe5e146107ff578063f3f480d91461081f576102fd565b8063d5ef7551116100bb578063d5ef75511461078c578063deace8f5146107ac578063e19be150146107bf576102fd565b8063cbd1642e1461071f578063ce803b4f1461073f578063d44481631461076c576102fd565b8063adc9772e11610143578063b7a0bda61161011d578063b7a0bda6146106d7578063bacc68af146106ec578063c7525dd3146106ff576102fd565b8063adc9772e14610684578063af215f9414610697578063b162717e146106b7576102fd565b8063a239f5ee11610174578063a239f5ee14610624578063a35962f314610644578063ab033ea914610664576102fd565b8063960a7afa146105ef57806398c4f76d1461060f576102fd565b806345ca9fc9116102535780635aa6e675116101fc5780637398d282116101d65780637398d2821461059a578063767631d5146105ba5780638d8798bf146105cf576102fd565b80635aa6e675146105435780635d475fdd146105655780636cff06a714610585576102fd565b80635325937f1161022d5780635325937f146104d157806357344e6f146104f15780635a7e108314610511576102fd565b806345ca9fc91461047c5780634612f40c1461049c5780634de8c6e6146104bc576102fd565b80632b85dcc9116102b55780633408e4701161028f5780633408e4701461041a57806339ada6691461042f5780633a7af6311461044f576102fd565b80632b85dcc9146103ba5780632e17de78146103da578063302830ab146103fa576102fd565b806313948c76116102e657806313948c7614610344578063149420241461037a57806323c452cd1461039a576102fd565b806304e6c2c0146103025780630f7aadb714610324575b600080fd5b34801561030e57600080fd5b5061032261031d366004613626565b610894565b005b34801561033057600080fd5b5061032261033f366004613783565b61097e565b34801561035057600080fd5b5061036461035f366004613626565b610adf565b6040516103719190613c2c565b60405180910390f35b34801561038657600080fd5b506103226103953660046139dd565b610b0b565b3480156103a657600080fd5b506103226103b5366004613749565b610b51565b3480156103c657600080fd5b506103646103d5366004613852565b610c63565b3480156103e657600080fd5b506103226103f5366004613852565b610c6b565b34801561040657600080fd5b5061036461041536600461369c565b610d61565b34801561042657600080fd5b50610364610d99565b34801561043b57600080fd5b5061032261044a366004613852565b610d9d565b34801561045b57600080fd5b5061046f61046a366004613852565b610daa565b6040516103719190613c21565b34801561048857600080fd5b5061032261049736600461386a565b610dbf565b3480156104a857600080fd5b506103646104b7366004613852565b61105c565b3480156104c857600080fd5b5061036461106e565b3480156104dd57600080fd5b506103226104ec366004613626565b611074565b3480156104fd57600080fd5b5061036461050c366004613626565b611156565b34801561051d57600080fd5b5061053161052c366004613852565b61117e565b60405161037196959493929190613b91565b34801561054f57600080fd5b506105586111e2565b6040516103719190613aaf565b34801561057157600080fd5b50610322610580366004613852565b6111fe565b34801561059157600080fd5b50610364611247565b3480156105a657600080fd5b506103646105b53660046138ee565b61124d565b3480156105c657600080fd5b5061036461126a565b3480156105db57600080fd5b506103226105ea3660046138c3565b611270565b3480156105fb57600080fd5b5061036461060a36600461386a565b611533565b34801561061b57600080fd5b50610364611566565b34801561063057600080fd5b5061036461063f366004613852565b61156b565b34801561065057600080fd5b5061055861065f366004613852565b611578565b34801561067057600080fd5b5061032261067f366004613626565b6115a0565b61032261069236600461369c565b61163c565b3480156106a357600080fd5b506103646106b236600461391d565b61174d565b3480156106c357600080fd5b506103226106d2366004613642565b61178f565b3480156106e357600080fd5b5061055861190c565b6103226106fa36600461386a565b611930565b34801561070b57600080fd5b5061032261071a3660046136c7565b611b8e565b34801561072b57600080fd5b5061032261073a36600461388b565b611d15565b34801561074b57600080fd5b5061075f61075a36600461386a565b611e0c565b6040516103719190614a09565b34801561077857600080fd5b506103226107873660046138ee565b611e61565b34801561079857600080fd5b5061046f6107a7366004613626565b611ebc565b6103226107ba366004613975565b611ee7565b3480156107cb57600080fd5b506103646107da366004613852565b6121c4565b3480156107eb57600080fd5b506103226107fa366004613852565b6121d9565b34801561080b57600080fd5b5061032261081a366004613a01565b6121e6565b34801561082b57600080fd5b506103646123be565b34801561084057600080fd5b5061046f61084f366004613852565b6123c4565b34801561086057600080fd5b5061036461086f366004613852565b6123d9565b34801561088057600080fd5b5061036461088f366004613626565b6123eb565b61089c612425565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001602081905260409091205460ff1615151461090a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090190613fc0565b60405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff811660008181526001602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055517f4234ba611d325b3ba434c4e1b037967b955b1274d4185ee9847b7491111a48ff9190a250565b600260005414156109bb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109019061485e565b600260009081556109d86109cd610d99565b8e8e8e8e8e8e61174d565b9050610a1e81868686808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152508d959493925088915050612478565b610a54576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109019061453e565b6000610a608888611533565b9050610a6c818e6125e2565b610a79828f8f6000612682565b8d73ffffffffffffffffffffffffffffffffffffffff16827f9475cdbde5fc71fe2ccd413c82878ee54d061b9f74f9e2e1a03ff1178821502c8f8f604051610ac2929190613a85565b60405180910390a350506001600055505050505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600360205260409020545b919050565b610b13612425565b6000918252600d602052604090912080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b3360009081526001602052604090205460ff16610b9a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090190614507565b60026000541415610bd7576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109019061485e565b60026000908155610bf5610be9610d99565b8686868660008061174d565b9050610c0181856126a9565b610c0d81868685612682565b506001600055610c1c336123eb565b610c2533611156565b1015610c5d576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090190614475565b50505050565b613840900490565b60026000541415610ca8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109019061485e565b6002600055610cb73382612760565b610cc133826127bd565b3373ffffffffffffffffffffffffffffffffffffffff167f85082129d87b2fe11527cb1b3b7a520aeb5aa6913f88a3d8757fe40d1db02fdd82604051610d079190613c2c565b60405180910390a26001600055610d1d336123eb565b610d2633611156565b1015610d5e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090190614475565b50565b73ffffffffffffffffffffffffffffffffffffffff821660009081526006602090815260408083208484529091529020545b92915050565b4690565b610da5612425565b601055565b60009081526005602052604090205460ff1690565b6000610dcb8383611533565b6000818152600860205260409020600381015491925090610e18576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610901906147a4565b600f546003820154610e2991612802565b4211610e61576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109019061460a565b600481015474010000000000000000000000000000000000000000900460ff1615610eb8576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090190613ea9565b6004810180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff16740100000000000000000000000000000000000000001790556000610f048461156b565b60008481526007602052604090205490915015610fc957601054600084815260076020526040902054610f3691612802565b82600101541115610f7a578154610f759073ffffffffffffffffffffffffffffffffffffffff16610f7083610f6a886121c4565b90612802565b612848565b610fc4565b6004820154610f9f9073ffffffffffffffffffffffffffffffffffffffff1682612848565b8154610fc49073ffffffffffffffffffffffffffffffffffffffff16610f70866121c4565b61101c565b610fea61dead610fe56004610fdf8560016128a5565b906128f9565b6127bd565b60048083015461101c9173ffffffffffffffffffffffffffffffffffffffff90911690610f7090610fdf8560076128a5565b84837f4a99228a8a6d774d261be57ab0ed833bb1bae1f22bbbd3d4767b75ad03fdddf78660405161104d9190613c2c565b60405180910390a35050505050565b60076020526000908152604090205481565b61384081565b61107c612425565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001602052604090205460ff16156110dc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090190613e04565b73ffffffffffffffffffffffffffffffffffffffff8116600081815260016020819052604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016909217909155517f2cec73b7434d3b91198ad1a618f63e6a0761ce281af5ec9ec76606d948d03e239190a250565b73ffffffffffffffffffffffffffffffffffffffff1660009081526002602052604090205490565b6008602052600090815260409020805460018201546002830154600384015460049094015473ffffffffffffffffffffffffffffffffffffffff93841694929391929181169074010000000000000000000000000000000000000000900460ff1686565b600b5473ffffffffffffffffffffffffffffffffffffffff1681565b611206612425565b613840810615611242576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090190613ca5565b600e55565b60105481565b600960209081526000928352604080842090915290825290205481565b600f5481565b3360009081526001602052604090205460ff166112b9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090190614507565b60006112c58483611533565b6000818152600760205260409020549091501561130e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610901906143bb565b60008181526008602052604090206001015415611357576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109019061494f565b600061136242610c63565b9050600061136f846121c4565b60008381526009602090815260408083203384529091529020549091506113969082612802565b60008381526009602090815260408083203380855290835281842094909455805160c08101825293845242848301908152848201898152606086018581526080870186815260a088018781528b88526008909652939095209551865473ffffffffffffffffffffffffffffffffffffffff9182167fffffffffffffffffffffffff00000000000000000000000000000000000000009182161788559251600188015590516002870155935160038601559051600490940180549251151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff959094169290911691909117929092161790556114a9868686612945565b857fa57b3e1f3af9eca02201028629700658608222c365064584cfe65d9630ef4f7b856040516114d99190613c2c565b60405180910390a25050506114ed336123eb565b6114f633611156565b101561152e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090190614475565b505050565b60008282604051602001611548929190613a85565b60405160208183030381529060405280519060200120905092915050565b600a81565b6000610d9382600a6128f9565b600c6020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b6115a8612425565b73ffffffffffffffffffffffffffffffffffffffff81166115f5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090190614895565b600b80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b60026000541415611679576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109019061485e565b6002600090815573ffffffffffffffffffffffffffffffffffffffff831681526001602081905260409091205460ff161515146116e2576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090190613fc0565b6116ec3382612afb565b6116f68282612848565b8173ffffffffffffffffffffffffffffffffffffffff167febedb8b3c678666e7f36970bc8f57abf6d8fa2e828c0da91ea5b75bf68ed101a8260405161173c9190613c2c565b60405180910390a250506001600055565b60008787878787878760405160200161176c9796959493929190614a2a565b604051602081830303815290604052805190602001209050979650505050505050565b60006117cd848480806020026020016040519081016040528093929190818152602001838360200280828437600092019190915250612b3d92505050565b905060006117db8284611533565b90506000805b8581101561189f5773ffffffffffffffffffffffffffffffffffffffff881660009081526006602052604081208189898581811061181b57fe5b9050602002013581526020019081526020016000205490506000811115611896576118468382612802565b73ffffffffffffffffffffffffffffffffffffffff8a16600090815260066020526040812091945090818a8a8681811061187c57fe5b905060200201358152602001908152602001600020819055505b506001016117e1565b506118aa82826125e2565b6118b48782612848565b828773ffffffffffffffffffffffffffffffffffffffff167f78e830d08be9d5f957414c84d685c061ecbd8467be98b42ebb64f0118b57d2ff836040516118fb9190613c2c565b60405180910390a350505050505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b600061193c8383611533565b60008181526008602090815260408083206007909252909120549192509015611991576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610901906143bb565b60018101546119cc576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090190613d39565b60006119e7600e54836001015461280290919063ffffffff16565b905042811015611a23576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090190614575565b600382015415611a5f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090190613f06565b4260038301556004820180547fffffffffffffffffffffffff000000000000000000000000000000000000000016331790556001820154600090611aa290610c63565b90506000611aaf866121c4565b8454600084815260096020908152604080832073ffffffffffffffffffffffffffffffffffffffff9094168084529390915290205491925090611af29083612f74565b600084815260096020908152604080832073ffffffffffffffffffffffffffffffffffffffff80871685529252909120919091558554611b33911683612760565b6000611b3e8861156b565b9050611b4a3382612afb565b88877fec2697dcba539a0ac947cdf1f6d0b6314c065429eca8be2435859b10209d4c278a604051611b7b9190613c2c565b60405180910390a3505050505050505050565b611bd287858585808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152508c959493925087915050612478565b611c08576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109019061453e565b6000611c148787611533565b73ffffffffffffffffffffffffffffffffffffffff8a1660009081526006602090815260408083208c845290915290205490915080611c7f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090190613d96565b73ffffffffffffffffffffffffffffffffffffffff8a1660009081526006602090815260408083208c8452909152812055611cba82826125e2565b611cc48a82612848565b87898b73ffffffffffffffffffffffffffffffffffffffff167f84eb21b24c31b27a3bc67dde4a598aad06db6e9415cd66544492b9616996143c60405160405180910390a450505050505050505050565b611d1d612425565b6000611d298484611533565b9050611d3361359d565b611d3d8585611e0c565b9050806040015160001415611d7e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090190613e3b565b80518414611d8857fe5b6040810151600090611d9d906249d400612802565b905080421015611dd9576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090190613f63565b60208201518251600091611ded9190612f74565b9050611df984826125e2565b611e0385826127bd565b50505050505050565b611e1461359d565b60046000611e228585611533565b81526020019081526020016000206040518060600160405290816000820154815260200160018201548152602001600282015481525050905092915050565b611e69612425565b6000918252600c602052604090912080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909216919091179055565b73ffffffffffffffffffffffffffffffffffffffff1660009081526001602052604090205460ff1690565b6000878152600c602052604090205473ffffffffffffffffffffffffffffffffffffffff1680611f43576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090190614236565b6000888152600d602052604090205460ff1615611f8c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090190613ff7565b60008611611fc6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090190613c48565b81861015612000576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610901906149ac565b61200a3387612afb565b606087878787878760405160240161202796959493929190613bd9565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152602080830180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fcc29a3060000000000000000000000000000000000000000000000000000000017905260008c8152600a90915220549091506120b79088612802565b60008a8152600a60205260409081902091909155517f419cb55000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169063419cb5509061211b908490600401613c35565b600060405180830381600087803b15801561213557600080fd5b505af1158015612149573d6000803e3d6000fd5b505050508373ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff168a7f0a0607688c86ec1775abcdbab7b33a3a35a6c9cde677c9be880150c231cc6b0b8a8a8a896040516121b19493929190614a70565b60405180910390a4505050505050505050565b6000610d936121d28361156b565b8390612802565b6121e1612425565b600f55565b6000858152600c60205260408082205490517f99178dd8000000000000000000000000000000000000000000000000000000008152879273ffffffffffffffffffffffffffffffffffffffff9092169182916399178dd89161224f913391903690600401613ad0565b600060405180830381600087803b15801561226957600080fd5b505af115801561227d573d6000803e3d6000fd5b50505050600061228d8786611533565b600081815260076020526040902054909150156122d6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090190614301565b60008411612310576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109019061408b565b83600760008381526020019081526020016000208190555061235b85604051806080016040528060468152602001614ae86046913960008b8152600a60205260409020549190612fb6565b6000898152600a60209081526040808320939093558382526008905220600181015461238c5761238c888888612945565b87878a7ffdfb0eefa96935b8a8c0edf528e125dc6f3934fdbbfce31b38967e8ff413dccd896040516121b19190613c2c565b600e5481565b600d6020526000908152604090205460ff1681565b600a6020526000908152604090205481565b6000610d936123f983612ffc565b73ffffffffffffffffffffffffffffffffffffffff841660009081526003602052604090205490612802565b600b5473ffffffffffffffffffffffffffffffffffffffff163314612476576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090190613d02565b565b60008082116124b3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090190614418565b8184106124ec576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610901906141d9565b6124f58261307a565b83511461252e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090190614667565b8460005b84518110156125d557856001166001141561258a5784818151811061255357fe5b60200260200101518260405160200161256d929190613a85565b6040516020818303038152906040528051906020012091506125c9565b8185828151811061259757fe5b60200260200101516040516020016125b0929190613a85565b6040516020818303038152906040528051906020012091505b600195861c9501612532565b5090951495945050505050565b60008281526004602052604090208054612628576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090190613dcd565b600181015460009061263a9084612802565b8254909150811115612678576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090190614801565b6001909101555050565b61268b84613129565b61269983610fe58484612f74565b8015610c5d57610c5d33826127bd565b336000908152600660209081526040808320858452909152902054156126fb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610901906146ea565b6127053382612760565b336000908152600660209081526040808320858452909152908190208290555182907f0c3d250c7831051e78aa6a56679e590374c7c424415ffe4aa474491def2fe70590612754908490613c2c565b60405180910390a25050565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600360205260409020546127909082612802565b73ffffffffffffffffffffffffffffffffffffffff90921660009081526003602052604090209190915550565b6127fe73ffffffffffffffffffffffffffffffffffffffff7f00000000000000000000000000000000000000000000000000000000000000001683836131ab565b5050565b600082820183811015612841576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090190613e72565b9392505050565b73ffffffffffffffffffffffffffffffffffffffff82166000908152600260205260409020546128789082612802565b73ffffffffffffffffffffffffffffffffffffffff90921660009081526002602052604090209190915550565b6000826128b457506000610d93565b828202828482816128c157fe5b0414612841576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109019061435e565b6000808211612934576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090190614145565b81838161293d57fe5b049392505050565b61294d610d99565b8214156129635761295e838261324c565b61152e565b6000828152600a602052604090205461297c9082612802565b6000838152600a6020908152604080832093909355600c9052205473ffffffffffffffffffffffffffffffffffffffff16806129e4576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090190614236565b606084836040516024016129f9929190613a85565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167ffd31c5ba00000000000000000000000000000000000000000000000000000000179052517f419cb55000000000000000000000000000000000000000000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff83169063419cb55090612ac2908490600401613c35565b600060405180830381600087803b158015612adc57600080fd5b505af1158015612af0573d6000803e3d6000fd5b505050505050505050565b6127fe73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016833084613354565b600080825111612b79576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610901906148f2565b815160011415612b9f5781600081518110612b9057fe5b60200260200101519050610b06565b612ba76135be565b5060408051610200810182527f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56381527f633dc4d7da7256660a892f8f1604a44b5432649cc8ec5cb3ced4c4e6ac94dd1d60208201527f890740a8eb06ce9be422cb8da5cdafc2b58c0a5e24036c578de2a433c828ff7d818301527f3b8ec09e026fdc305365dfc94e189a81b38c7597b3d941c279f042e8206e0bd86060808301919091527fecd50eee38e386bd62be9bedb990706951b65fe053bd9d8a521af753d139e2da60808301527fdefff6d330bb5403f63b14f33b578274160de3a50df4efecf0e0db73bcdd3da560a08301527f617bdd11f7c0a11f49db22f629387a12da7596f9d1704d7465177c63d88ec7d760c08301527f292c23a9aa1d8bea7e2435e555a4a60e379a5a35f3f452bae60121073fb6eead60e08301527fe1cea92ed99acdcb045a6726b2f87107e8a61620a232cf4d7d5b5766b3952e106101008301527f7ad66c0a68c72cb89e4fb4303841966e4062a76ab97451e3b9fb526a5ceb7f826101208301527fe026cc5a4aed3c22a58cbd3d2ac754c9352c5436f638042dca99034e836365166101408301527f3d04cffd8b46a874edf5cfae63077de85f849a660426697b06a829c70dd1409c6101608301527fad676aa337a485e4728a0b240d92b3ef7b3c372d06d189322bfd5f61f1e7203e6101808301527fa2fca4a49658f9fab7aa63289c91b7c7b6c832a6d0e69334ff5b0a3483d09dab6101a08301527f4ebfd9cd7bca2505f7bef59cc1c12ecc708fff26ae4af19abe852afe9e20c8626101c08301527f2def10d13dd169f550f578bda343d9717a138562e0093b380a1120789d53cf106101e0830152825183815280820184529192909190602082018180368337505085519192506000918291508180805b6001841115612f505750506002820460018084161460005b82811015612ecc578a8160020281518110612e7357fe5b602002602001015196508a8160020260010181518110612e8f57fe5b6020026020010151955086602089015285604089015287805190602001208b8281518110612eb957fe5b6020908102919091010152600101612e5c565b508015612f2f57896001850381518110612ee257fe5b60200260200101519550878360108110612ef857fe5b602002015160001b945085602088015284604088015286805190602001208a8381518110612f2257fe5b6020026020010181815250505b80612f3b576000612f3e565b60015b60ff1682019350600190920191612e44565b89600081518110612f5d57fe5b602002602001015198505050505050505050919050565b600082821115612fb0576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090190614054565b50900390565b60008184841115612ff4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109019190613c35565b505050900390565b60008061300842610c63565b9050600080613840600e548161301a57fe5b04905060005b8181101561307057808403600090815260096020908152604080832073ffffffffffffffffffffffffffffffffffffffff8a168452909152902054613066908490612802565b9250600101613020565b5090949350505050565b60008082116130b5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109019061426d565b81600114156130c657506000610b06565b81600060805b60018110613114577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6001821b01811b83161561310c5791821c91908101905b60011c6130cc565b506001811b8414612841576001019392505050565b60008181526005602052604090205460ff1615613172576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109019061417c565b600090815260056020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055565b61152e8363a9059cbb60e01b84846040516024016131ca929190613b6b565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff0000000000000000000000000000000000000000000000000000000090931692909217909152613375565b60006132588383611533565b600081815260046020526040902054909150156132a1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610901906142ca565b600082116132db576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610901906144aa565b6040805160608101825283815260006020808301828152428486019081528684526004909252918490209251835590516001830155516002909101555183907fb33d2162aead99dab59e77a7a67ea025b776bf8ca8079e132afdf9b23e03bd4290613347908590613c2c565b60405180910390a2505050565b610c5d846323b872dd60e01b8585856040516024016131ca93929190613b3a565b60606133d7826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff1661342b9092919063ffffffff16565b80519091501561152e57808060200190518101906133f59190613836565b61152e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161090190614747565b606061343a8484600085613442565b949350505050565b60608247101561347e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610901906140e8565b61348785613544565b6134bd576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610901906145d3565b600060608673ffffffffffffffffffffffffffffffffffffffff1685876040516134e79190613a93565b60006040518083038185875af1925050503d8060008114613524576040519150601f19603f3d011682016040523d82523d6000602084013e613529565b606091505b509150915061353982828661354a565b979650505050505050565b3b151590565b60608315613559575081612841565b8251156135695782518084602001fd5b816040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016109019190613c35565b60405180606001604052806000815260200160008152602001600081525090565b6040518061020001604052806010906020820280368337509192915050565b60008083601f8401126135ee578182fd5b50813567ffffffffffffffff811115613605578182fd5b602083019150836020808302850101111561361f57600080fd5b9250929050565b600060208284031215613637578081fd5b813561284181614ab7565b60008060008060608587031215613657578283fd5b843561366281614ab7565b9350602085013567ffffffffffffffff81111561367d578384fd5b613689878288016135dd565b9598909750949560400135949350505050565b600080604083850312156136ae578182fd5b82356136b981614ab7565b946020939093013593505050565b60008060008060008060008060e0898b0312156136e2578384fd5b88356136ed81614ab7565b97506020890135965060408901359550606089013594506080890135935060a089013567ffffffffffffffff811115613724578384fd5b6137308b828c016135dd565b999c989b50969995989497949560c00135949350505050565b6000806000806080858703121561375e578384fd5b843561376981614ab7565b966020860135965060408601359560600135945092505050565b6000806000806000806000806000806000806101608d8f0312156137a5578384fd5b6137af8d35614ab7565b8c359b5060208d01359a5060408d0135995060608d0135985060808d0135975060a08d0135965060c08d0135955060e08d013594506101008d0135935067ffffffffffffffff6101208e01351115613805578283fd5b6138168e6101208f01358f016135dd565b81945080935050506101408d013590509295989b509295989b509295989b565b600060208284031215613847578081fd5b815161284181614ad9565b600060208284031215613863578081fd5b5035919050565b6000806040838503121561387c578182fd5b50508035926020909101359150565b60008060006060848603121561389f578283fd5b833592506020840135915060408401356138b881614ab7565b809150509250925092565b6000806000606084860312156138d7578081fd5b505081359360208301359350604090920135919050565b60008060408385031215613900578182fd5b82359150602083013561391281614ab7565b809150509250929050565b600080600080600080600060e0888a031215613937578081fd5b87359650602088013561394981614ab7565b96999698505050506040850135946060810135946080820135945060a0820135935060c0909101359150565b600080600080600080600060e0888a03121561398f578081fd5b8735965060208801356139a181614ab7565b955060408801359450606088013593506080880135925060a08801356139c681614ab7565b8092505060c0880135905092959891949750929550565b600080604083850312156139ef578182fd5b82359150602083013561391281614ad9565b600080600080600060a08688031215613a18578283fd5b505083359560208501359550604085013594606081013594506080013592509050565b60008151808452613a53816020860160208601614a8b565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b918252602082015260400190565b60008251613aa5818460208701614a8b565b9190910192915050565b73ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b600073ffffffffffffffffffffffffffffffffffffffff851682526040602083015282604083015282846060840137818301606090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016010192915050565b73ffffffffffffffffffffffffffffffffffffffff9384168152919092166020820152604081019190915260600190565b73ffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b73ffffffffffffffffffffffffffffffffffffffff9687168152602081019590955260408501939093526060840191909152909216608082015290151560a082015260c00190565b73ffffffffffffffffffffffffffffffffffffffff9687168152602081019590955260408501939093526060840191909152909216608082015260a081019190915260c00190565b901515815260200190565b90815260200190565b6000602082526128416020830184613a3b565b60208082526027908201527f4c315f4252473a204d757374207472616e736665722061206e6f6e2d7a65726f60408201527f20616d6f756e7400000000000000000000000000000000000000000000000000606082015260800190565b6020808252603b908201527f4c315f4252473a206368616c6c656e6765506572696f64206d7573742062652060408201527f646976697369626c652062792054494d455f534c4f545f53495a450000000000606082015260800190565b6020808252601f908201527f4c315f4252473a2043616c6c6572206973206e6f7420746865206f776e657200604082015260600190565b60208082526028908201527f4c315f4252473a205472616e73666572526f6f7420686173206e6f742062656560408201527f6e20626f6e646564000000000000000000000000000000000000000000000000606082015260800190565b6020808252601e908201527f4c325f4252473a207472616e73666572496420686173206e6f20626f6e640000604082015260600190565b6020808252601c908201527f4252473a205472616e7366657220726f6f74206e6f7420666f756e6400000000604082015260600190565b6020808252601e908201527f4143543a204164647265737320697320616c726561647920626f6e6465720000604082015260600190565b6020808252601b908201527f4252473a205472616e73666572526f6f74206e6f7420666f756e640000000000604082015260600190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b60208082526025908201527f4c315f4252473a205472616e73666572526f6f7420616c72656164792072657360408201527f6f6c766564000000000000000000000000000000000000000000000000000000606082015260800190565b60208082526027908201527f4c315f4252473a205472616e73666572526f6f7420616c72656164792063686160408201527f6c6c656e67656400000000000000000000000000000000000000000000000000606082015260800190565b6020808252603b908201527f4252473a205472616e73666572526f6f742063616e6e6f74206265207265736360408201527f756564206265666f726520746865205265736375652044656c61790000000000606082015260800190565b6020808252601a908201527f4143543a2041646472657373206973206e6f7420626f6e646572000000000000604082015260600190565b60208082526028908201527f4c315f4252473a2053656e647320746f207468697320636861696e496420617260408201527f6520706175736564000000000000000000000000000000000000000000000000606082015260800190565b6020808252601e908201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604082015260600190565b6020808252602e908201527f4c315f4252473a20726f6f74436f6d6d69747465644174206d7573742062652060408201527f67726561746572207468616e2030000000000000000000000000000000000000606082015260800190565b60208082526026908201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60408201527f722063616c6c0000000000000000000000000000000000000000000000000000606082015260800190565b6020808252601a908201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604082015260600190565b6020808252602c908201527f4252473a20546865207472616e736665722068617320616c726561647920626560408201527f656e2077697468647261776e0000000000000000000000000000000000000000606082015260800190565b60208082526024908201527f4c69625f4d65726b6c65547265653a20496e646578206f7574206f6620626f7560408201527f6e64732e00000000000000000000000000000000000000000000000000000000606082015260800190565b6020808252601d908201527f4c315f4252473a20636861696e4964206e6f7420737570706f72746564000000604082015260600190565b60208082526030908201527f4c69625f4d65726b6c65547265653a2043616e6e6f7420636f6d70757465206360408201527f65696c286c6f675f3229206f6620302e00000000000000000000000000000000606082015260800190565b6020808252601e908201527f4252473a205472616e7366657220726f6f7420616c7265616479207365740000604082015260600190565b60208082526026908201527f4c315f4252473a205472616e73666572526f6f7420616c726561647920636f6e60408201527f6669726d65640000000000000000000000000000000000000000000000000000606082015260800190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f60408201527f7700000000000000000000000000000000000000000000000000000000000000606082015260800190565b6020808252602f908201527f4c315f4252473a205472616e73666572526f6f742068617320616c726561647960408201527f206265656e20636f6e6669726d65640000000000000000000000000000000000606082015260800190565b60208082526037908201527f4c69625f4d65726b6c65547265653a20546f74616c206c6561766573206d757360408201527f742062652067726561746572207468616e207a65726f2e000000000000000000606082015260800190565b6020808252818101527f4143543a204e6f7420656e6f75676820617661696c61626c6520637265646974604082015260600190565b6020808252602d908201527f4252473a2043616e6e6f7420736574205472616e73666572526f6f7420746f7460408201527f616c416d6f756e74206f66203000000000000000000000000000000000000000606082015260800190565b60208082526019908201527f4143543a2043616c6c6572206973206e6f7420626f6e64657200000000000000604082015260600190565b6020808252601b908201527f4252473a20496e76616c6964207472616e736665722070726f6f660000000000604082015260600190565b602080825260409082018190527f4c315f4252473a205472616e73666572526f6f742063616e6e6f742062652063908201527f68616c6c656e676564206166746572206368616c6c656e676520706572696f64606082015260800190565b6020808252601d908201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604082015260600190565b60208082526026908201527f4c315f4252473a204368616c6c656e676520706572696f6420686173206e6f7460408201527f20656e6465640000000000000000000000000000000000000000000000000000606082015260800190565b6020808252604d908201527f4c69625f4d65726b6c65547265653a20546f74616c207369626c696e6773206460408201527f6f6573206e6f7420636f72726563746c7920636f72726573706f6e6420746f2060608201527f746f74616c206c65617665732e00000000000000000000000000000000000000608082015260a00190565b60208082526027908201527f4252473a205769746864726177616c2068617320616c7265616479206265656e60408201527f20626f6e64656400000000000000000000000000000000000000000000000000606082015260800190565b6020808252602a908201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60408201527f6f74207375636365656400000000000000000000000000000000000000000000606082015260800190565b6020808252602c908201527f4c315f4252473a205472616e73666572526f6f7420686173206e6f742062656560408201527f6e206368616c6c656e6765640000000000000000000000000000000000000000606082015260800190565b6020808252602a908201527f4252473a205769746864726177616c2065786365656473205472616e7366657260408201527f526f6f7420746f74616c00000000000000000000000000000000000000000000606082015260800190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b6020808252602b908201527f4c315f4252473a205f6e6577476f7665726e616e63652063616e6e6f7420626560408201527f2061646472657373283029000000000000000000000000000000000000000000606082015260800190565b60208082526034908201527f4c69625f4d65726b6c65547265653a204d7573742070726f766964652061742060408201527f6c65617374206f6e65206c65616620686173682e000000000000000000000000606082015260800190565b6020808252602c908201527f4c315f4252473a205472616e73666572526f6f742068617320616c726561647960408201527f206265656e20626f6e6465640000000000000000000000000000000000000000606082015260800190565b60208082526028908201527f4c315f4252473a2052656c61796572206665652063616e6e6f7420657863656560408201527f6420616d6f756e74000000000000000000000000000000000000000000000000606082015260800190565b81518152602080830151908201526040918201519181019190915260600190565b96875273ffffffffffffffffffffffffffffffffffffffff95909516602087015260408601939093526060850191909152608084015260a083015260c082015260e00190565b93845260208401929092526040830152606082015260800190565b60005b83811015614aa6578181015183820152602001614a8e565b83811115610c5d5750506000910152565b73ffffffffffffffffffffffffffffffffffffffff81168114610d5e57600080fd5b8015158114610d5e57600080fdfe4c315f4252473a20416d6f756e74206578636565647320636861696e42616c616e63652e205468697320696e646963617465732061206c617965722d32206661696c7572652ea26469706673582212200babe27abec15af01c62175f0c1669a66ab3b06dbe96abb0fd248de74e1039c964736f6c634300060c0033000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000000000060000000000000000000000000f56e305024b195383245a075737d16dbdb8487fb00000000000000000000000000000000000000000000000000000000000000010000000000000000000000002a6303e6b99d451df3566068ebb110708335658f

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

000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb480000000000000000000000000000000000000000000000000000000000000060000000000000000000000000f56e305024b195383245a075737d16dbdb8487fb00000000000000000000000000000000000000000000000000000000000000010000000000000000000000002a6303e6b99d451df3566068ebb110708335658f

-----Decoded View---------------
Arg [0] : _l1CanonicalToken (address): 0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48
Arg [1] : bonders (address[]): 0x2a6303e6b99d451df3566068ebb110708335658f
Arg [2] : _governance (address): 0xf56e305024b195383245a075737d16dbdb8487fb

-----Encoded View---------------
5 Constructor Arguments found :
Arg [0] : 000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000060
Arg [2] : 000000000000000000000000f56e305024b195383245a075737d16dbdb8487fb
Arg [3] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [4] : 0000000000000000000000002a6303e6b99d451df3566068ebb110708335658f


Block Transaction Difficulty Gas Used Reward
Block Uncle Number Difficulty Gas Used Reward
Loading
Loading
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.