ETH Price: $3,614.38 (+0.70%)

Contract

0x914f986a44AcB623A277d6Bd17368171FCbe4273
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

Token Holdings

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Bond Withdrawal213204382024-12-03 7:18:474 hrs ago1733210327IN
Hop Protocol: HOP Bridge
0 ETH0.0026127217.23366326
Bond Transfer Ro...213025912024-11-30 19:30:352 days ago1732995035IN
Hop Protocol: HOP Bridge
0 ETH0.0031874113.13982718
Bond Withdrawal212928902024-11-29 10:55:234 days ago1732877723IN
Hop Protocol: HOP Bridge
0 ETH0.001172857.73621273
Bond Transfer Ro...212589852024-11-24 17:05:358 days ago1732467935IN
Hop Protocol: HOP Bridge
0 ETH0.002329919.37262701
Send To L2212532662024-11-23 21:56:479 days ago1732399007IN
Hop Protocol: HOP Bridge
0 ETH0.001290310.21201875
Bond Transfer Ro...212529192024-11-23 20:46:479 days ago1732394807IN
Hop Protocol: HOP Bridge
0 ETH0.0026345610.86719999
Send To L2212189352024-11-19 2:57:3514 days ago1731985055IN
Hop Protocol: HOP Bridge
0 ETH0.001882159.93537358
Send To L2211886552024-11-14 21:35:3518 days ago1731620135IN
Hop Protocol: HOP Bridge
0 ETH0.0050475232.4257493
Bond Transfer Ro...211733432024-11-12 18:18:2320 days ago1731435503IN
Hop Protocol: HOP Bridge
0 ETH0.0063366327.02595151
Bond Transfer Ro...211621732024-11-11 4:52:5922 days ago1731300779IN
Hop Protocol: HOP Bridge
0 ETH0.0030684313.01633817
Settle Bonded Wi...211615832024-11-11 2:54:3522 days ago1731293675IN
Hop Protocol: HOP Bridge
0 ETH0.0010002614.1399981
Bond Transfer Ro...211612932024-11-11 1:56:2322 days ago1731290183IN
Hop Protocol: HOP Bridge
0 ETH0.002424612.7526428
Send To L2211610382024-11-11 1:04:4722 days ago1731287087IN
Hop Protocol: HOP Bridge
0 ETH0.0022469215.4209367
Bond Withdrawal211610312024-11-11 1:03:2322 days ago1731287003IN
Hop Protocol: HOP Bridge
0 ETH0.0018867714.03121054
Bond Withdrawal211610302024-11-11 1:03:1122 days ago1731286991IN
Hop Protocol: HOP Bridge
0 ETH0.0021188513.97603339
Send To L2211608032024-11-11 0:17:4722 days ago1731284267IN
Hop Protocol: HOP Bridge
0 ETH0.0030547619.6240695
Send To L2211607542024-11-11 0:07:5922 days ago1731283679IN
Hop Protocol: HOP Bridge
0 ETH0.003376623.1782013
Send To L2211607032024-11-10 23:57:4722 days ago1731283067IN
Hop Protocol: HOP Bridge
0 ETH0.0020045513.72472714
Send To L2211606962024-11-10 23:56:2322 days ago1731282983IN
Hop Protocol: HOP Bridge
0 ETH0.0025606116.44962661
Bond Transfer Ro...211561562024-11-10 8:45:3523 days ago1731228335IN
Hop Protocol: HOP Bridge
0 ETH0.0027776111.59003972
Send To L2211554582024-11-10 6:25:1123 days ago1731219911IN
Hop Protocol: HOP Bridge
0 ETH0.0024842615.95793401
Bond Withdrawal211511462024-11-09 15:59:1123 days ago1731167951IN
Hop Protocol: HOP Bridge
0 ETH0.001488149.81590414
Bond Withdrawal211476732024-11-09 4:21:3524 days ago1731126095IN
Hop Protocol: HOP Bridge
0 ETH0.000862295.68771207
Bond Withdrawal211476532024-11-09 4:17:3524 days ago1731125855IN
Hop Protocol: HOP Bridge
0 ETH0.000895855.91006612
Bond Transfer Ro...211472622024-11-09 2:59:2324 days ago1731121163IN
Hop Protocol: HOP Bridge
0 ETH0.001860617.67198208
View all transactions

View more zero value Internal Transactions in Advanced View mode

Advanced mode:
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
L1_HOP_Bridge

Compiler Version
v0.6.12+commit.27d51765

Optimization Enabled:
Yes with 50000 runs

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

pragma solidity 0.6.12;
pragma experimental ABIEncoderV2;

import "./L1_ERC20_Bridge.sol";

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

contract L1_HOP_Bridge is L1_ERC20_Bridge {

    address public migrator;

    modifier onlyMigrator () {
        require(msg.sender == migrator, "L1_HOP_BRG: Caller is not the migrator");
        _;
    }

    constructor (
        IERC20 _l1CanonicalToken,
        address[] memory bonders,
        address _governance,
        address _migrator
    )
        public
        L1_ERC20_Bridge(_l1CanonicalToken, bonders, _governance)
    {
        migrator = _migrator;
    }

    function migrateTokens(address recipient) external onlyMigrator {
        uint256 amount = l1CanonicalToken.balanceOf(address(this));
        _transferFromBridge(recipient, amount);
    }

    function setMigrator(address _newMigrator) external onlyMigrator {
        migrator = _newMigrator;
    }
}

File 2 of 12 : 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 3 of 12 : 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 4 of 12 : 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 5 of 12 : 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(uint256 => 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[destinationChainId][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[destinationChainId][transferRootId] == 0, "L1_BRG: TransferRoot already confirmed");
        require(rootCommittedAt > 0, "L1_BRG: rootCommittedAt must be greater than 0");
        transferRootCommittedAt[destinationChainId][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
     * @param destinationChainId The id of the destination chain
     */
    function challengeTransferBond(bytes32 rootHash, uint256 originalAmount, uint256 destinationChainId) external payable {
        bytes32 transferRootId = getTransferRootId(rootHash, originalAmount);
        TransferBond storage transferBond = transferBonds[transferRootId];

        require(transferRootCommittedAt[destinationChainId][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
     * @param destinationChainId The id of the destination chain
     */
    function resolveChallenge(bytes32 rootHash, uint256 originalAmount, uint256 destinationChainId) 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[destinationChainId][transferRootId] > 0) {
            // Invalid challenge

            if (transferBond.createdAt > transferRootCommittedAt[destinationChainId][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 6 of 12 : 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 7 of 12 : 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 8 of 12 : 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 9 of 12 : IMessengerWrapper.sol
// SPDX-License-Identifier: MIT

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

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

File 10 of 12 : 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 11 of 12 : 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 12 of 12 : 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",
        "devdoc",
        "userdoc",
        "metadata",
        "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"},{"internalType":"address","name":"_migrator","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"},{"internalType":"uint256","name":"destinationChainId","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":[{"internalType":"address","name":"recipient","type":"address"}],"name":"migrateTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"migrator","outputs":[{"internalType":"address","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"},{"internalType":"uint256","name":"destinationChainId","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":"address","name":"_newMigrator","type":"address"}],"name":"setMigrator","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":"uint256","name":"","type":"uint256"},{"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"}]

60a060405262015180600e55620d2f00600f556103846010553480156200002557600080fd5b5060405162004bef38038062004bef8339810160408190526200004891620001ce565b83838381818180600160008190555060005b81518110156200016957600160008383815181106200007557fe5b6020908102919091018101516001600160a01b031682528101919091526040016000205460ff1615620000c55760405162461bcd60e51b8152600401620000bc90620002c3565b60405180910390fd5b6001806000848481518110620000d757fe5b60200260200101516001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a81548160ff0219169083151502179055508181815181106200012357fe5b60200260200101516001600160a01b03167f2cec73b7434d3b91198ad1a618f63e6a0761ce281af5ec9ec76606d948d03e2360405160405180910390a26001016200005a565b5050600b80546001600160a01b03199081166001600160a01b039485161790915560609690961b6001600160601b03191660805250601180549095169516949094179092555062000338945050505050565b8051620001c8816200031f565b92915050565b60008060008060808587031215620001e4578384fd5b8451620001f1816200031f565b602086810151919550906001600160401b038082111562000210578586fd5b818801915088601f83011262000224578586fd5b81518181111562000233578687fd5b838102915062000245848301620002f8565b8181528481019084860184860187018d10156200026057898afd5b8995505b838610156200028e57620002798d82620001bb565b83526001959095019491860191860162000264565b50809850505050505050620002a78660408701620001bb565b9150620002b88660608701620001bb565b905092959194509250565b6020808252818101527f4143543a2043616e6e6f7420616464206475706c696361746520626f6e646572604082015260600190565b6040518181016001600160401b03811182821017156200031757600080fd5b604052919050565b6001600160a01b03811681146200033557600080fd5b50565b60805160601c61488a6200036560003980611a455280611ade52806125ca52806126a9525061488a6000f3fe60806040526004361061031e5760003560e01c806381707b80116101a5578063c7525dd3116100ec578063e19be15011610095578063f3f480d91161006f578063f3f480d914610895578063fa2a69a3146108aa578063fc110b67146108ca578063ffa9286c146108ea5761031e565b8063e19be15014610835578063eecd57e614610855578063ef6ebe5e146108755761031e565b8063d4448163116100c6578063d4448163146107e2578063d5ef755114610802578063deace8f5146108225761031e565b8063c7525dd314610775578063cbd1642e14610795578063ce803b4f146107b55761031e565b8063ab033ea91161014e578063b162717e11610128578063b162717e14610720578063b7a0bda614610740578063c1684711146107555761031e565b8063ab033ea9146106cd578063adc9772e146106ed578063af215f94146107005761031e565b806398c4f76d1161017f57806398c4f76d14610678578063a239f5ee1461068d578063a35962f3146106ad5761031e565b806381707b80146106185780638d8798bf14610638578063960a7afa146106585761031e565b80633a7af631116102695780635aa6e675116102125780637398d282116101ec5780637398d282146105ce578063767631d5146105ee5780637cd07e47146106035761031e565b80635aa6e675146105775780635d475fdd146105995780636cff06a7146105b95761031e565b80635325937f116102435780635325937f1461050557806357344e6f146105255780635a7e1083146105455761031e565b80633a7af631146104a35780633b8fea28146104d05780634de8c6e6146104f05761031e565b806323cf3118116102cb578063302830ab116102a5578063302830ab1461044e5780633408e4701461046e57806339ada669146104835761031e565b806323cf3118146103ee5780632b85dcc91461040e5780632e17de781461042e5761031e565b806314942024116102fc578063149420241461039b5780631bbe15ea146103bb57806323c452cd146103ce5761031e565b806304e6c2c0146103235780630f7aadb71461034557806313948c7614610365575b600080fd5b34801561032f57600080fd5b5061034361033e3660046132d8565b61090a565b005b34801561035157600080fd5b50610343610360366004613435565b6109da565b34801561037157600080fd5b506103856103803660046132d8565b610b07565b60405161039291906138f6565b60405180910390f35b3480156103a757600080fd5b506103436103b63660046136a7565b610b33565b6103436103c9366004613575565b610b79565b3480156103da57600080fd5b506103436103e93660046133fb565b610d7b565b3480156103fa57600080fd5b506103436104093660046132d8565b610e3f565b34801561041a57600080fd5b50610385610429366004613504565b610ebd565b34801561043a57600080fd5b50610343610449366004613504565b610ec5565b34801561045a57600080fd5b5061038561046936600461334e565b610f87565b34801561047a57600080fd5b50610385610fbf565b34801561048f57600080fd5b5061034361049e366004613504565b610fc3565b3480156104af57600080fd5b506104c36104be366004613504565b610fd0565b60405161039291906138eb565b3480156104dc57600080fd5b506103856104eb36600461351c565b610fe5565b3480156104fc57600080fd5b50610385611002565b34801561051157600080fd5b506103436105203660046132d8565b611008565b34801561053157600080fd5b506103856105403660046132d8565b6110d0565b34801561055157600080fd5b50610565610560366004613504565b6110f8565b6040516103929695949392919061385b565b34801561058357600080fd5b5061058c61115c565b6040516103929190613779565b3480156105a557600080fd5b506103436105b4366004613504565b611178565b3480156105c557600080fd5b506103856111a7565b3480156105da57600080fd5b506103856105e93660046135b8565b6111ad565b3480156105fa57600080fd5b506103856111ca565b34801561060f57600080fd5b5061058c6111d0565b34801561062457600080fd5b50610343610633366004613575565b6111ec565b34801561064457600080fd5b50610343610653366004613575565b611452565b34801561066457600080fd5b5061038561067336600461351c565b6116b8565b34801561068457600080fd5b506103856116eb565b34801561069957600080fd5b506103856106a8366004613504565b6116f0565b3480156106b957600080fd5b5061058c6106c8366004613504565b6116fd565b3480156106d957600080fd5b506103436106e83660046132d8565b611725565b6103436106fb36600461334e565b6117a7565b34801561070c57600080fd5b5061038561071b3660046135e7565b611884565b34801561072c57600080fd5b5061034361073b3660046132f4565b6118c6565b34801561074c57600080fd5b5061058c611a43565b34801561076157600080fd5b506103436107703660046132d8565b611a67565b34801561078157600080fd5b50610343610790366004613379565b611b73565b3480156107a157600080fd5b506103436107b036600461353d565b611cc6565b3480156107c157600080fd5b506107d56107d036600461351c565b611d89565b6040516103929190614730565b3480156107ee57600080fd5b506103436107fd3660046135b8565b611dde565b34801561080e57600080fd5b506104c361081d3660046132d8565b611e39565b61034361083036600461363f565b611e64565b34801561084157600080fd5b50610385610850366004613504565b6120d9565b34801561086157600080fd5b50610343610870366004613504565b6120ee565b34801561088157600080fd5b506103436108903660046136cb565b6120fb565b3480156108a157600080fd5b506103856122b0565b3480156108b657600080fd5b506104c36108c5366004613504565b6122b6565b3480156108d657600080fd5b506103856108e5366004613504565b6122cb565b3480156108f657600080fd5b506103856109053660046132d8565b6122dd565b610912612317565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001602081905260409091205460ff161515146109665760405162461bcd60e51b815260040161095d90613c8a565b60405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff811660008181526001602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055517f4234ba611d325b3ba434c4e1b037967b955b1274d4185ee9847b7491111a48ff9190a250565b600260005414156109fd5760405162461bcd60e51b815260040161095d90614585565b60026000908155610a1a610a0f610fbf565b8e8e8e8e8e8e611884565b9050610a6081868686808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152508d959493925088915050612350565b610a7c5760405162461bcd60e51b815260040161095d90614208565b6000610a8888886116b8565b9050610a94818e61246c565b610aa1828f8f60006124d8565b8d73ffffffffffffffffffffffffffffffffffffffff16827f9475cdbde5fc71fe2ccd413c82878ee54d061b9f74f9e2e1a03ff1178821502c8f8f604051610aea92919061374f565b60405180910390a350506001600055505050505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600360205260409020545b919050565b610b3b612317565b6000918252600d602052604090912080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b6000610b8584846116b8565b600081815260086020908152604080832086845260078352818420858552909252909120549192509015610bcb5760405162461bcd60e51b815260040161095d90614085565b6001810154610bec5760405162461bcd60e51b815260040161095d90613a03565b6000610c07600e5483600101546124ff90919063ffffffff16565b905042811015610c295760405162461bcd60e51b815260040161095d9061423f565b600382015415610c4b5760405162461bcd60e51b815260040161095d90613bd0565b4260038301556004820180547fffffffffffffffffffffffff000000000000000000000000000000000000000016331790556001820154600090610c8e90610ebd565b90506000610c9b876120d9565b8454600084815260096020908152604080832073ffffffffffffffffffffffffffffffffffffffff9094168084529390915290205491925090610cde908361252b565b600084815260096020908152604080832073ffffffffffffffffffffffffffffffffffffffff80871685529252909120919091558554610d1f911683612553565b6000610d2a896116f0565b9050610d3633826125b0565b89877fec2697dcba539a0ac947cdf1f6d0b6314c065429eca8be2435859b10209d4c278b604051610d6791906138f6565b60405180910390a350505050505050505050565b3360009081526001602052604090205460ff16610daa5760405162461bcd60e51b815260040161095d906141d1565b60026000541415610dcd5760405162461bcd60e51b815260040161095d90614585565b60026000908155610deb610ddf610fbf565b86868686600080611884565b9050610df781856125f2565b610e03818686856124d8565b506001600055610e12336122dd565b610e1b336110d0565b1015610e395760405162461bcd60e51b815260040161095d9061413f565b50505050565b60115473ffffffffffffffffffffffffffffffffffffffff163314610e765760405162461bcd60e51b815260040161095d9061429d565b601180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b613840900490565b60026000541415610ee85760405162461bcd60e51b815260040161095d90614585565b6002600055610ef73382612553565b610f01338261268f565b3373ffffffffffffffffffffffffffffffffffffffff167f85082129d87b2fe11527cb1b3b7a520aeb5aa6913f88a3d8757fe40d1db02fdd82604051610f4791906138f6565b60405180910390a26001600055610f5d336122dd565b610f66336110d0565b1015610f845760405162461bcd60e51b815260040161095d9061413f565b50565b73ffffffffffffffffffffffffffffffffffffffff821660009081526006602090815260408083208484529091529020545b92915050565b4690565b610fcb612317565b601055565b60009081526005602052604090205460ff1690565b600760209081526000928352604080842090915290825290205481565b61384081565b611010612317565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001602052604090205460ff16156110565760405162461bcd60e51b815260040161095d90613ace565b73ffffffffffffffffffffffffffffffffffffffff8116600081815260016020819052604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016909217909155517f2cec73b7434d3b91198ad1a618f63e6a0761ce281af5ec9ec76606d948d03e239190a250565b73ffffffffffffffffffffffffffffffffffffffff1660009081526002602052604090205490565b6008602052600090815260409020805460018201546002830154600384015460049094015473ffffffffffffffffffffffffffffffffffffffff93841694929391929181169074010000000000000000000000000000000000000000900460ff1686565b600b5473ffffffffffffffffffffffffffffffffffffffff1681565b611180612317565b6138408106156111a25760405162461bcd60e51b815260040161095d9061396f565b600e55565b60105481565b600960209081526000928352604080842090915290825290205481565b600f5481565b60115473ffffffffffffffffffffffffffffffffffffffff1681565b60006111f884846116b8565b600081815260086020526040902060038101549192509061122b5760405162461bcd60e51b815260040161095d906144cb565b600f54600382015461123c916124ff565b421161125a5760405162461bcd60e51b815260040161095d90614331565b600481015474010000000000000000000000000000000000000000900460ff16156112975760405162461bcd60e51b815260040161095d90613b73565b6004810180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905560006112e3856116f0565b6000858152600760209081526040808320878452909152902054909150156113be57601054600085815260076020908152604080832087845290915290205461132b916124ff565b8260010154111561136f57815461136a9073ffffffffffffffffffffffffffffffffffffffff166113658361135f896120d9565b906124ff565b6126d0565b6113b9565b60048201546113949073ffffffffffffffffffffffffffffffffffffffff16826126d0565b81546113b99073ffffffffffffffffffffffffffffffffffffffff16611365876120d9565b611411565b6113df61dead6113da60046113d485600161272d565b90612767565b61268f565b6004808301546114119173ffffffffffffffffffffffffffffffffffffffff90911690611365906113d485600761272d565b85837f4a99228a8a6d774d261be57ab0ed833bb1bae1f22bbbd3d4767b75ad03fdddf78760405161144291906138f6565b60405180910390a3505050505050565b3360009081526001602052604090205460ff166114815760405162461bcd60e51b815260040161095d906141d1565b600061148d84836116b8565b6000848152600760209081526040808320848452909152902054909150156114c75760405162461bcd60e51b815260040161095d90614085565b600081815260086020526040902060010154156114f65760405162461bcd60e51b815260040161095d90614676565b600061150142610ebd565b9050600061150e846120d9565b600083815260096020908152604080832033845290915290205490915061153590826124ff565b60008381526009602090815260408083203380855290835281842094909455805160c08101825293845242848301908152848201898152606086018581526080870186815260a088018781528b88526008909652939095209551865473ffffffffffffffffffffffffffffffffffffffff9182167fffffffffffffffffffffffff00000000000000000000000000000000000000009182161788559251600188015590516002870155935160038601559051600490940180549251151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff95909416929091169190911792909216179055611648868686612799565b857fa57b3e1f3af9eca02201028629700658608222c365064584cfe65d9630ef4f7b8560405161167891906138f6565b60405180910390a250505061168c336122dd565b611695336110d0565b10156116b35760405162461bcd60e51b815260040161095d9061413f565b505050565b600082826040516020016116cd92919061374f565b60405160208183030381529060405280519060200120905092915050565b600a81565b6000610fb982600a612767565b600c6020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b61172d612317565b73ffffffffffffffffffffffffffffffffffffffff81166117605760405162461bcd60e51b815260040161095d906145bc565b600b80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b600260005414156117ca5760405162461bcd60e51b815260040161095d90614585565b6002600090815573ffffffffffffffffffffffffffffffffffffffff831681526001602081905260409091205460ff161515146118195760405162461bcd60e51b815260040161095d90613c8a565b61182333826125b0565b61182d82826126d0565b8173ffffffffffffffffffffffffffffffffffffffff167febedb8b3c678666e7f36970bc8f57abf6d8fa2e828c0da91ea5b75bf68ed101a8260405161187391906138f6565b60405180910390a250506001600055565b6000878787878787876040516020016118a39796959493929190614751565b604051602081830303815290604052805190602001209050979650505050505050565b600061190484848080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525061293592505050565b9050600061191282846116b8565b90506000805b858110156119d65773ffffffffffffffffffffffffffffffffffffffff881660009081526006602052604081208189898581811061195257fe5b90506020020135815260200190815260200160002054905060008111156119cd5761197d83826124ff565b73ffffffffffffffffffffffffffffffffffffffff8a16600090815260066020526040812091945090818a8a868181106119b357fe5b905060200201358152602001908152602001600020819055505b50600101611918565b506119e1828261246c565b6119eb87826126d0565b828773ffffffffffffffffffffffffffffffffffffffff167f78e830d08be9d5f957414c84d685c061ecbd8467be98b42ebb64f0118b57d2ff83604051611a3291906138f6565b60405180910390a350505050505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b60115473ffffffffffffffffffffffffffffffffffffffff163314611a9e5760405162461bcd60e51b815260040161095d9061429d565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815260009073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016906370a0823190611b13903090600401613779565b60206040518083038186803b158015611b2b57600080fd5b505afa158015611b3f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b6391906135a0565b9050611b6f828261268f565b5050565b611bb787858585808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152508c959493925087915050612350565b611bd35760405162461bcd60e51b815260040161095d90614208565b6000611bdf87876116b8565b73ffffffffffffffffffffffffffffffffffffffff8a1660009081526006602090815260408083208c845290915290205490915080611c305760405162461bcd60e51b815260040161095d90613a60565b73ffffffffffffffffffffffffffffffffffffffff8a1660009081526006602090815260408083208c8452909152812055611c6b828261246c565b611c758a826126d0565b87898b73ffffffffffffffffffffffffffffffffffffffff167f84eb21b24c31b27a3bc67dde4a598aad06db6e9415cd66544492b9616996143c60405160405180910390a450505050505050505050565b611cce612317565b6000611cda84846116b8565b9050611ce461324f565b611cee8585611d89565b9050806040015160001415611d155760405162461bcd60e51b815260040161095d90613b05565b80518414611d1f57fe5b6040810151600090611d34906249d4006124ff565b905080421015611d565760405162461bcd60e51b815260040161095d90613c2d565b60208201518251600091611d6a919061252b565b9050611d76848261246c565b611d80858261268f565b50505050505050565b611d9161324f565b60046000611d9f85856116b8565b81526020019081526020016000206040518060600160405290816000820154815260200160018201548152602001600282015481525050905092915050565b611de6612317565b6000918252600c602052604090912080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909216919091179055565b73ffffffffffffffffffffffffffffffffffffffff1660009081526001602052604090205460ff1690565b6000878152600c602052604090205473ffffffffffffffffffffffffffffffffffffffff1680611ea65760405162461bcd60e51b815260040161095d90613f00565b6000888152600d602052604090205460ff1615611ed55760405162461bcd60e51b815260040161095d90613cc1565b60008611611ef55760405162461bcd60e51b815260040161095d90613912565b81861015611f155760405162461bcd60e51b815260040161095d906146d3565b611f1f33876125b0565b6060878787878787604051602401611f3c969594939291906138a3565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152602080830180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fcc29a3060000000000000000000000000000000000000000000000000000000017905260008c8152600a9091522054909150611fcc90886124ff565b60008a8152600a60205260409081902091909155517f419cb55000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169063419cb550906120309084906004016138ff565b600060405180830381600087803b15801561204a57600080fd5b505af115801561205e573d6000803e3d6000fd5b505050508373ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff168a7f0a0607688c86ec1775abcdbab7b33a3a35a6c9cde677c9be880150c231cc6b0b8a8a8a896040516120c69493929190614797565b60405180910390a4505050505050505050565b6000610fb96120e7836116f0565b83906124ff565b6120f6612317565b600f55565b6000858152600c60205260408082205490517f99178dd8000000000000000000000000000000000000000000000000000000008152879273ffffffffffffffffffffffffffffffffffffffff9092169182916399178dd89161216491339190369060040161379a565b600060405180830381600087803b15801561217e57600080fd5b505af1158015612192573d6000803e3d6000fd5b5050505060006121a287866116b8565b6000878152600760209081526040808320848452909152902054909150156121dc5760405162461bcd60e51b815260040161095d90613fcb565b600084116121fc5760405162461bcd60e51b815260040161095d90613d55565b6000868152600760209081526040808320848452825291829020869055815160808101909252604680835261224d92889290919061480f9083013960008b8152600a60205260409020549190612d52565b6000898152600a60209081526040808320939093558382526008905220600181015461227e5761227e888888612799565b87878a7ffdfb0eefa96935b8a8c0edf528e125dc6f3934fdbbfce31b38967e8ff413dccd896040516120c691906138f6565b600e5481565b600d6020526000908152604090205460ff1681565b600a6020526000908152604090205481565b6000610fb96122eb83612d7e565b73ffffffffffffffffffffffffffffffffffffffff8416600090815260036020526040902054906124ff565b600b5473ffffffffffffffffffffffffffffffffffffffff16331461234e5760405162461bcd60e51b815260040161095d906139cc565b565b60008082116123715760405162461bcd60e51b815260040161095d906140e2565b8184106123905760405162461bcd60e51b815260040161095d90613ea3565b61239982612dfc565b8351146123b85760405162461bcd60e51b815260040161095d9061438e565b8460005b845181101561245f578560011660011415612414578481815181106123dd57fe5b6020026020010151826040516020016123f792919061374f565b604051602081830303815290604052805190602001209150612453565b8185828151811061242157fe5b602002602001015160405160200161243a92919061374f565b6040516020818303038152906040528051906020012091505b600195861c95016123bc565b5090951495945050505050565b600082815260046020526040902080546124985760405162461bcd60e51b815260040161095d90613a97565b60018101546000906124aa90846124ff565b82549091508111156124ce5760405162461bcd60e51b815260040161095d90614528565b6001909101555050565b6124e184612e91565b6124ef836113da848461252b565b8015610e3957610e39338261268f565b6000828201838110156125245760405162461bcd60e51b815260040161095d90613b3c565b9392505050565b60008282111561254d5760405162461bcd60e51b815260040161095d90613d1e565b50900390565b73ffffffffffffffffffffffffffffffffffffffff821660009081526003602052604090205461258390826124ff565b73ffffffffffffffffffffffffffffffffffffffff90921660009081526003602052604090209190915550565b611b6f73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016833084612ef9565b3360009081526006602090815260408083208584529091529020541561262a5760405162461bcd60e51b815260040161095d90614411565b6126343382612553565b336000908152600660209081526040808320858452909152908190208290555182907f0c3d250c7831051e78aa6a56679e590374c7c424415ffe4aa474491def2fe705906126839084906138f6565b60405180910390a25050565b611b6f73ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168383612f9c565b73ffffffffffffffffffffffffffffffffffffffff821660009081526002602052604090205461270090826124ff565b73ffffffffffffffffffffffffffffffffffffffff90921660009081526002602052604090209190915550565b60008261273c57506000610fb9565b8282028284828161274957fe5b04146125245760405162461bcd60e51b815260040161095d90614028565b60008082116127885760405162461bcd60e51b815260040161095d90613e0f565b81838161279157fe5b049392505050565b6127a1610fbf565b8214156127b7576127b28382612fbb565b6116b3565b6000828152600a60205260409020546127d090826124ff565b6000838152600a6020908152604080832093909355600c9052205473ffffffffffffffffffffffffffffffffffffffff168061281e5760405162461bcd60e51b815260040161095d90613f00565b6060848360405160240161283392919061374f565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167ffd31c5ba00000000000000000000000000000000000000000000000000000000179052517f419cb55000000000000000000000000000000000000000000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff83169063419cb550906128fc9084906004016138ff565b600060405180830381600087803b15801561291657600080fd5b505af115801561292a573d6000803e3d6000fd5b505050505050505050565b6000808251116129575760405162461bcd60e51b815260040161095d90614619565b81516001141561297d578160008151811061296e57fe5b60200260200101519050610b2e565b612985613270565b5060408051610200810182527f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56381527f633dc4d7da7256660a892f8f1604a44b5432649cc8ec5cb3ced4c4e6ac94dd1d60208201527f890740a8eb06ce9be422cb8da5cdafc2b58c0a5e24036c578de2a433c828ff7d818301527f3b8ec09e026fdc305365dfc94e189a81b38c7597b3d941c279f042e8206e0bd86060808301919091527fecd50eee38e386bd62be9bedb990706951b65fe053bd9d8a521af753d139e2da60808301527fdefff6d330bb5403f63b14f33b578274160de3a50df4efecf0e0db73bcdd3da560a08301527f617bdd11f7c0a11f49db22f629387a12da7596f9d1704d7465177c63d88ec7d760c08301527f292c23a9aa1d8bea7e2435e555a4a60e379a5a35f3f452bae60121073fb6eead60e08301527fe1cea92ed99acdcb045a6726b2f87107e8a61620a232cf4d7d5b5766b3952e106101008301527f7ad66c0a68c72cb89e4fb4303841966e4062a76ab97451e3b9fb526a5ceb7f826101208301527fe026cc5a4aed3c22a58cbd3d2ac754c9352c5436f638042dca99034e836365166101408301527f3d04cffd8b46a874edf5cfae63077de85f849a660426697b06a829c70dd1409c6101608301527fad676aa337a485e4728a0b240d92b3ef7b3c372d06d189322bfd5f61f1e7203e6101808301527fa2fca4a49658f9fab7aa63289c91b7c7b6c832a6d0e69334ff5b0a3483d09dab6101a08301527f4ebfd9cd7bca2505f7bef59cc1c12ecc708fff26ae4af19abe852afe9e20c8626101c08301527f2def10d13dd169f550f578bda343d9717a138562e0093b380a1120789d53cf106101e0830152825183815280820184529192909190602082018180368337505085519192506000918291508180805b6001841115612d2e5750506002820460018084161460005b82811015612caa578a8160020281518110612c5157fe5b602002602001015196508a8160020260010181518110612c6d57fe5b6020026020010151955086602089015285604089015287805190602001208b8281518110612c9757fe5b6020908102919091010152600101612c3a565b508015612d0d57896001850381518110612cc057fe5b60200260200101519550878360108110612cd657fe5b602002015160001b945085602088015284604088015286805190602001208a8381518110612d0057fe5b6020026020010181815250505b80612d19576000612d1c565b60015b60ff1682019350600190920191612c22565b89600081518110612d3b57fe5b602002602001015198505050505050505050919050565b60008184841115612d765760405162461bcd60e51b815260040161095d91906138ff565b505050900390565b600080612d8a42610ebd565b9050600080613840600e5481612d9c57fe5b04905060005b81811015612df257808403600090815260096020908152604080832073ffffffffffffffffffffffffffffffffffffffff8a168452909152902054612de89084906124ff565b9250600101612da2565b5090949350505050565b6000808211612e1d5760405162461bcd60e51b815260040161095d90613f37565b8160011415612e2e57506000610b2e565b81600060805b60018110612e7c577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6001821b01811b831615612e745791821c91908101905b60011c612e34565b506001811b8414612524576001019392505050565b60008181526005602052604090205460ff1615612ec05760405162461bcd60e51b815260040161095d90613e46565b600090815260056020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055565b610e39846323b872dd60e01b858585604051602401612f1a93929190613804565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915261308f565b6116b38363a9059cbb60e01b8484604051602401612f1a929190613835565b6000612fc783836116b8565b60008181526004602052604090205490915015612ff65760405162461bcd60e51b815260040161095d90613f94565b600082116130165760405162461bcd60e51b815260040161095d90614174565b6040805160608101825283815260006020808301828152428486019081528684526004909252918490209251835590516001830155516002909101555183907fb33d2162aead99dab59e77a7a67ea025b776bf8ca8079e132afdf9b23e03bd42906130829085906138f6565b60405180910390a2505050565b60606130f1826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff1661312b9092919063ffffffff16565b8051909150156116b3578080602001905181019061310f91906134e8565b6116b35760405162461bcd60e51b815260040161095d9061446e565b606061313a8484600085613142565b949350505050565b6060824710156131645760405162461bcd60e51b815260040161095d90613db2565b61316d85613210565b6131895760405162461bcd60e51b815260040161095d906142fa565b600060608673ffffffffffffffffffffffffffffffffffffffff1685876040516131b3919061375d565b60006040518083038185875af1925050503d80600081146131f0576040519150601f19603f3d011682016040523d82523d6000602084013e6131f5565b606091505b5091509150613205828286613216565b979650505050505050565b3b151590565b60608315613225575081612524565b8251156132355782518084602001fd5b8160405162461bcd60e51b815260040161095d91906138ff565b60405180606001604052806000815260200160008152602001600081525090565b6040518061020001604052806010906020820280368337509192915050565b60008083601f8401126132a0578182fd5b50813567ffffffffffffffff8111156132b7578182fd5b60208301915083602080830285010111156132d157600080fd5b9250929050565b6000602082840312156132e9578081fd5b8135612524816147de565b60008060008060608587031215613309578283fd5b8435613314816147de565b9350602085013567ffffffffffffffff81111561332f578384fd5b61333b8782880161328f565b9598909750949560400135949350505050565b60008060408385031215613360578182fd5b823561336b816147de565b946020939093013593505050565b60008060008060008060008060e0898b031215613394578384fd5b883561339f816147de565b97506020890135965060408901359550606089013594506080890135935060a089013567ffffffffffffffff8111156133d6578384fd5b6133e28b828c0161328f565b999c989b50969995989497949560c00135949350505050565b60008060008060808587031215613410578384fd5b843561341b816147de565b966020860135965060408601359560600135945092505050565b6000806000806000806000806000806000806101608d8f031215613457578384fd5b6134618d356147de565b8c359b5060208d01359a5060408d0135995060608d0135985060808d0135975060a08d0135965060c08d0135955060e08d013594506101008d0135935067ffffffffffffffff6101208e013511156134b7578283fd5b6134c88e6101208f01358f0161328f565b81945080935050506101408d013590509295989b509295989b509295989b565b6000602082840312156134f9578081fd5b815161252481614800565b600060208284031215613515578081fd5b5035919050565b6000806040838503121561352e578182fd5b50508035926020909101359150565b600080600060608486031215613551578081fd5b8335925060208401359150604084013561356a816147de565b809150509250925092565b600080600060608486031215613589578081fd5b505081359360208301359350604090920135919050565b6000602082840312156135b1578081fd5b5051919050565b600080604083850312156135ca578182fd5b8235915060208301356135dc816147de565b809150509250929050565b600080600080600080600060e0888a031215613601578081fd5b873596506020880135613613816147de565b96999698505050506040850135946060810135946080820135945060a0820135935060c0909101359150565b600080600080600080600060e0888a031215613659578081fd5b87359650602088013561366b816147de565b955060408801359450606088013593506080880135925060a0880135613690816147de565b8092505060c0880135905092959891949750929550565b600080604083850312156136b9578182fd5b8235915060208301356135dc81614800565b600080600080600060a086880312156136e2578283fd5b505083359560208501359550604085013594606081013594506080013592509050565b6000815180845261371d8160208601602086016147b2565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b918252602082015260400190565b6000825161376f8184602087016147b2565b9190910192915050565b73ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b600073ffffffffffffffffffffffffffffffffffffffff851682526040602083015282604083015282846060840137818301606090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016010192915050565b73ffffffffffffffffffffffffffffffffffffffff9384168152919092166020820152604081019190915260600190565b73ffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b73ffffffffffffffffffffffffffffffffffffffff9687168152602081019590955260408501939093526060840191909152909216608082015290151560a082015260c00190565b73ffffffffffffffffffffffffffffffffffffffff9687168152602081019590955260408501939093526060840191909152909216608082015260a081019190915260c00190565b901515815260200190565b90815260200190565b6000602082526125246020830184613705565b60208082526027908201527f4c315f4252473a204d757374207472616e736665722061206e6f6e2d7a65726f60408201527f20616d6f756e7400000000000000000000000000000000000000000000000000606082015260800190565b6020808252603b908201527f4c315f4252473a206368616c6c656e6765506572696f64206d7573742062652060408201527f646976697369626c652062792054494d455f534c4f545f53495a450000000000606082015260800190565b6020808252601f908201527f4c315f4252473a2043616c6c6572206973206e6f7420746865206f776e657200604082015260600190565b60208082526028908201527f4c315f4252473a205472616e73666572526f6f7420686173206e6f742062656560408201527f6e20626f6e646564000000000000000000000000000000000000000000000000606082015260800190565b6020808252601e908201527f4c325f4252473a207472616e73666572496420686173206e6f20626f6e640000604082015260600190565b6020808252601c908201527f4252473a205472616e7366657220726f6f74206e6f7420666f756e6400000000604082015260600190565b6020808252601e908201527f4143543a204164647265737320697320616c726561647920626f6e6465720000604082015260600190565b6020808252601b908201527f4252473a205472616e73666572526f6f74206e6f7420666f756e640000000000604082015260600190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b60208082526025908201527f4c315f4252473a205472616e73666572526f6f7420616c72656164792072657360408201527f6f6c766564000000000000000000000000000000000000000000000000000000606082015260800190565b60208082526027908201527f4c315f4252473a205472616e73666572526f6f7420616c72656164792063686160408201527f6c6c656e67656400000000000000000000000000000000000000000000000000606082015260800190565b6020808252603b908201527f4252473a205472616e73666572526f6f742063616e6e6f74206265207265736360408201527f756564206265666f726520746865205265736375652044656c61790000000000606082015260800190565b6020808252601a908201527f4143543a2041646472657373206973206e6f7420626f6e646572000000000000604082015260600190565b60208082526028908201527f4c315f4252473a2053656e647320746f207468697320636861696e496420617260408201527f6520706175736564000000000000000000000000000000000000000000000000606082015260800190565b6020808252601e908201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604082015260600190565b6020808252602e908201527f4c315f4252473a20726f6f74436f6d6d69747465644174206d7573742062652060408201527f67726561746572207468616e2030000000000000000000000000000000000000606082015260800190565b60208082526026908201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60408201527f722063616c6c0000000000000000000000000000000000000000000000000000606082015260800190565b6020808252601a908201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604082015260600190565b6020808252602c908201527f4252473a20546865207472616e736665722068617320616c726561647920626560408201527f656e2077697468647261776e0000000000000000000000000000000000000000606082015260800190565b60208082526024908201527f4c69625f4d65726b6c65547265653a20496e646578206f7574206f6620626f7560408201527f6e64732e00000000000000000000000000000000000000000000000000000000606082015260800190565b6020808252601d908201527f4c315f4252473a20636861696e4964206e6f7420737570706f72746564000000604082015260600190565b60208082526030908201527f4c69625f4d65726b6c65547265653a2043616e6e6f7420636f6d70757465206360408201527f65696c286c6f675f3229206f6620302e00000000000000000000000000000000606082015260800190565b6020808252601e908201527f4252473a205472616e7366657220726f6f7420616c7265616479207365740000604082015260600190565b60208082526026908201527f4c315f4252473a205472616e73666572526f6f7420616c726561647920636f6e60408201527f6669726d65640000000000000000000000000000000000000000000000000000606082015260800190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f60408201527f7700000000000000000000000000000000000000000000000000000000000000606082015260800190565b6020808252602f908201527f4c315f4252473a205472616e73666572526f6f742068617320616c726561647960408201527f206265656e20636f6e6669726d65640000000000000000000000000000000000606082015260800190565b60208082526037908201527f4c69625f4d65726b6c65547265653a20546f74616c206c6561766573206d757360408201527f742062652067726561746572207468616e207a65726f2e000000000000000000606082015260800190565b6020808252818101527f4143543a204e6f7420656e6f75676820617661696c61626c6520637265646974604082015260600190565b6020808252602d908201527f4252473a2043616e6e6f7420736574205472616e73666572526f6f7420746f7460408201527f616c416d6f756e74206f66203000000000000000000000000000000000000000606082015260800190565b60208082526019908201527f4143543a2043616c6c6572206973206e6f7420626f6e64657200000000000000604082015260600190565b6020808252601b908201527f4252473a20496e76616c6964207472616e736665722070726f6f660000000000604082015260600190565b602080825260409082018190527f4c315f4252473a205472616e73666572526f6f742063616e6e6f742062652063908201527f68616c6c656e676564206166746572206368616c6c656e676520706572696f64606082015260800190565b60208082526026908201527f4c315f484f505f4252473a2043616c6c6572206973206e6f7420746865206d6960408201527f677261746f720000000000000000000000000000000000000000000000000000606082015260800190565b6020808252601d908201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604082015260600190565b60208082526026908201527f4c315f4252473a204368616c6c656e676520706572696f6420686173206e6f7460408201527f20656e6465640000000000000000000000000000000000000000000000000000606082015260800190565b6020808252604d908201527f4c69625f4d65726b6c65547265653a20546f74616c207369626c696e6773206460408201527f6f6573206e6f7420636f72726563746c7920636f72726573706f6e6420746f2060608201527f746f74616c206c65617665732e00000000000000000000000000000000000000608082015260a00190565b60208082526027908201527f4252473a205769746864726177616c2068617320616c7265616479206265656e60408201527f20626f6e64656400000000000000000000000000000000000000000000000000606082015260800190565b6020808252602a908201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60408201527f6f74207375636365656400000000000000000000000000000000000000000000606082015260800190565b6020808252602c908201527f4c315f4252473a205472616e73666572526f6f7420686173206e6f742062656560408201527f6e206368616c6c656e6765640000000000000000000000000000000000000000606082015260800190565b6020808252602a908201527f4252473a205769746864726177616c2065786365656473205472616e7366657260408201527f526f6f7420746f74616c00000000000000000000000000000000000000000000606082015260800190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b6020808252602b908201527f4c315f4252473a205f6e6577476f7665726e616e63652063616e6e6f7420626560408201527f2061646472657373283029000000000000000000000000000000000000000000606082015260800190565b60208082526034908201527f4c69625f4d65726b6c65547265653a204d7573742070726f766964652061742060408201527f6c65617374206f6e65206c65616620686173682e000000000000000000000000606082015260800190565b6020808252602c908201527f4c315f4252473a205472616e73666572526f6f742068617320616c726561647960408201527f206265656e20626f6e6465640000000000000000000000000000000000000000606082015260800190565b60208082526028908201527f4c315f4252473a2052656c61796572206665652063616e6e6f7420657863656560408201527f6420616d6f756e74000000000000000000000000000000000000000000000000606082015260800190565b81518152602080830151908201526040918201519181019190915260600190565b96875273ffffffffffffffffffffffffffffffffffffffff95909516602087015260408601939093526060850191909152608084015260a083015260c082015260e00190565b93845260208401929092526040830152606082015260800190565b60005b838110156147cd5781810151838201526020016147b5565b83811115610e395750506000910152565b73ffffffffffffffffffffffffffffffffffffffff81168114610f8457600080fd5b8015158114610f8457600080fdfe4c315f4252473a20416d6f756e74206578636565647320636861696e42616c616e63652e205468697320696e646963617465732061206c617965722d32206661696c7572652ea26469706673582212205119361c8f9a9053273deeda832fc1c9e476e45dcf2a64e49d2548672465bec964736f6c634300060c0033000000000000000000000000c5102fe9359fd9a28f877a67e36b0f050d81a3cc0000000000000000000000000000000000000000000000000000000000000080000000000000000000000000f56e305024b195383245a075737d16dbdb8487fb000000000000000000000000eea8422a08258e73c139fc32a25e10410c14bd7a00000000000000000000000000000000000000000000000000000000000000010000000000000000000000002a6303e6b99d451df3566068ebb110708335658f

Deployed Bytecode

0x60806040526004361061031e5760003560e01c806381707b80116101a5578063c7525dd3116100ec578063e19be15011610095578063f3f480d91161006f578063f3f480d914610895578063fa2a69a3146108aa578063fc110b67146108ca578063ffa9286c146108ea5761031e565b8063e19be15014610835578063eecd57e614610855578063ef6ebe5e146108755761031e565b8063d4448163116100c6578063d4448163146107e2578063d5ef755114610802578063deace8f5146108225761031e565b8063c7525dd314610775578063cbd1642e14610795578063ce803b4f146107b55761031e565b8063ab033ea91161014e578063b162717e11610128578063b162717e14610720578063b7a0bda614610740578063c1684711146107555761031e565b8063ab033ea9146106cd578063adc9772e146106ed578063af215f94146107005761031e565b806398c4f76d1161017f57806398c4f76d14610678578063a239f5ee1461068d578063a35962f3146106ad5761031e565b806381707b80146106185780638d8798bf14610638578063960a7afa146106585761031e565b80633a7af631116102695780635aa6e675116102125780637398d282116101ec5780637398d282146105ce578063767631d5146105ee5780637cd07e47146106035761031e565b80635aa6e675146105775780635d475fdd146105995780636cff06a7146105b95761031e565b80635325937f116102435780635325937f1461050557806357344e6f146105255780635a7e1083146105455761031e565b80633a7af631146104a35780633b8fea28146104d05780634de8c6e6146104f05761031e565b806323cf3118116102cb578063302830ab116102a5578063302830ab1461044e5780633408e4701461046e57806339ada669146104835761031e565b806323cf3118146103ee5780632b85dcc91461040e5780632e17de781461042e5761031e565b806314942024116102fc578063149420241461039b5780631bbe15ea146103bb57806323c452cd146103ce5761031e565b806304e6c2c0146103235780630f7aadb71461034557806313948c7614610365575b600080fd5b34801561032f57600080fd5b5061034361033e3660046132d8565b61090a565b005b34801561035157600080fd5b50610343610360366004613435565b6109da565b34801561037157600080fd5b506103856103803660046132d8565b610b07565b60405161039291906138f6565b60405180910390f35b3480156103a757600080fd5b506103436103b63660046136a7565b610b33565b6103436103c9366004613575565b610b79565b3480156103da57600080fd5b506103436103e93660046133fb565b610d7b565b3480156103fa57600080fd5b506103436104093660046132d8565b610e3f565b34801561041a57600080fd5b50610385610429366004613504565b610ebd565b34801561043a57600080fd5b50610343610449366004613504565b610ec5565b34801561045a57600080fd5b5061038561046936600461334e565b610f87565b34801561047a57600080fd5b50610385610fbf565b34801561048f57600080fd5b5061034361049e366004613504565b610fc3565b3480156104af57600080fd5b506104c36104be366004613504565b610fd0565b60405161039291906138eb565b3480156104dc57600080fd5b506103856104eb36600461351c565b610fe5565b3480156104fc57600080fd5b50610385611002565b34801561051157600080fd5b506103436105203660046132d8565b611008565b34801561053157600080fd5b506103856105403660046132d8565b6110d0565b34801561055157600080fd5b50610565610560366004613504565b6110f8565b6040516103929695949392919061385b565b34801561058357600080fd5b5061058c61115c565b6040516103929190613779565b3480156105a557600080fd5b506103436105b4366004613504565b611178565b3480156105c557600080fd5b506103856111a7565b3480156105da57600080fd5b506103856105e93660046135b8565b6111ad565b3480156105fa57600080fd5b506103856111ca565b34801561060f57600080fd5b5061058c6111d0565b34801561062457600080fd5b50610343610633366004613575565b6111ec565b34801561064457600080fd5b50610343610653366004613575565b611452565b34801561066457600080fd5b5061038561067336600461351c565b6116b8565b34801561068457600080fd5b506103856116eb565b34801561069957600080fd5b506103856106a8366004613504565b6116f0565b3480156106b957600080fd5b5061058c6106c8366004613504565b6116fd565b3480156106d957600080fd5b506103436106e83660046132d8565b611725565b6103436106fb36600461334e565b6117a7565b34801561070c57600080fd5b5061038561071b3660046135e7565b611884565b34801561072c57600080fd5b5061034361073b3660046132f4565b6118c6565b34801561074c57600080fd5b5061058c611a43565b34801561076157600080fd5b506103436107703660046132d8565b611a67565b34801561078157600080fd5b50610343610790366004613379565b611b73565b3480156107a157600080fd5b506103436107b036600461353d565b611cc6565b3480156107c157600080fd5b506107d56107d036600461351c565b611d89565b6040516103929190614730565b3480156107ee57600080fd5b506103436107fd3660046135b8565b611dde565b34801561080e57600080fd5b506104c361081d3660046132d8565b611e39565b61034361083036600461363f565b611e64565b34801561084157600080fd5b50610385610850366004613504565b6120d9565b34801561086157600080fd5b50610343610870366004613504565b6120ee565b34801561088157600080fd5b506103436108903660046136cb565b6120fb565b3480156108a157600080fd5b506103856122b0565b3480156108b657600080fd5b506104c36108c5366004613504565b6122b6565b3480156108d657600080fd5b506103856108e5366004613504565b6122cb565b3480156108f657600080fd5b506103856109053660046132d8565b6122dd565b610912612317565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001602081905260409091205460ff161515146109665760405162461bcd60e51b815260040161095d90613c8a565b60405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff811660008181526001602052604080822080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00169055517f4234ba611d325b3ba434c4e1b037967b955b1274d4185ee9847b7491111a48ff9190a250565b600260005414156109fd5760405162461bcd60e51b815260040161095d90614585565b60026000908155610a1a610a0f610fbf565b8e8e8e8e8e8e611884565b9050610a6081868686808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152508d959493925088915050612350565b610a7c5760405162461bcd60e51b815260040161095d90614208565b6000610a8888886116b8565b9050610a94818e61246c565b610aa1828f8f60006124d8565b8d73ffffffffffffffffffffffffffffffffffffffff16827f9475cdbde5fc71fe2ccd413c82878ee54d061b9f74f9e2e1a03ff1178821502c8f8f604051610aea92919061374f565b60405180910390a350506001600055505050505050505050505050565b73ffffffffffffffffffffffffffffffffffffffff81166000908152600360205260409020545b919050565b610b3b612317565b6000918252600d602052604090912080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016911515919091179055565b6000610b8584846116b8565b600081815260086020908152604080832086845260078352818420858552909252909120549192509015610bcb5760405162461bcd60e51b815260040161095d90614085565b6001810154610bec5760405162461bcd60e51b815260040161095d90613a03565b6000610c07600e5483600101546124ff90919063ffffffff16565b905042811015610c295760405162461bcd60e51b815260040161095d9061423f565b600382015415610c4b5760405162461bcd60e51b815260040161095d90613bd0565b4260038301556004820180547fffffffffffffffffffffffff000000000000000000000000000000000000000016331790556001820154600090610c8e90610ebd565b90506000610c9b876120d9565b8454600084815260096020908152604080832073ffffffffffffffffffffffffffffffffffffffff9094168084529390915290205491925090610cde908361252b565b600084815260096020908152604080832073ffffffffffffffffffffffffffffffffffffffff80871685529252909120919091558554610d1f911683612553565b6000610d2a896116f0565b9050610d3633826125b0565b89877fec2697dcba539a0ac947cdf1f6d0b6314c065429eca8be2435859b10209d4c278b604051610d6791906138f6565b60405180910390a350505050505050505050565b3360009081526001602052604090205460ff16610daa5760405162461bcd60e51b815260040161095d906141d1565b60026000541415610dcd5760405162461bcd60e51b815260040161095d90614585565b60026000908155610deb610ddf610fbf565b86868686600080611884565b9050610df781856125f2565b610e03818686856124d8565b506001600055610e12336122dd565b610e1b336110d0565b1015610e395760405162461bcd60e51b815260040161095d9061413f565b50505050565b60115473ffffffffffffffffffffffffffffffffffffffff163314610e765760405162461bcd60e51b815260040161095d9061429d565b601180547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b613840900490565b60026000541415610ee85760405162461bcd60e51b815260040161095d90614585565b6002600055610ef73382612553565b610f01338261268f565b3373ffffffffffffffffffffffffffffffffffffffff167f85082129d87b2fe11527cb1b3b7a520aeb5aa6913f88a3d8757fe40d1db02fdd82604051610f4791906138f6565b60405180910390a26001600055610f5d336122dd565b610f66336110d0565b1015610f845760405162461bcd60e51b815260040161095d9061413f565b50565b73ffffffffffffffffffffffffffffffffffffffff821660009081526006602090815260408083208484529091529020545b92915050565b4690565b610fcb612317565b601055565b60009081526005602052604090205460ff1690565b600760209081526000928352604080842090915290825290205481565b61384081565b611010612317565b73ffffffffffffffffffffffffffffffffffffffff811660009081526001602052604090205460ff16156110565760405162461bcd60e51b815260040161095d90613ace565b73ffffffffffffffffffffffffffffffffffffffff8116600081815260016020819052604080832080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0016909217909155517f2cec73b7434d3b91198ad1a618f63e6a0761ce281af5ec9ec76606d948d03e239190a250565b73ffffffffffffffffffffffffffffffffffffffff1660009081526002602052604090205490565b6008602052600090815260409020805460018201546002830154600384015460049094015473ffffffffffffffffffffffffffffffffffffffff93841694929391929181169074010000000000000000000000000000000000000000900460ff1686565b600b5473ffffffffffffffffffffffffffffffffffffffff1681565b611180612317565b6138408106156111a25760405162461bcd60e51b815260040161095d9061396f565b600e55565b60105481565b600960209081526000928352604080842090915290825290205481565b600f5481565b60115473ffffffffffffffffffffffffffffffffffffffff1681565b60006111f884846116b8565b600081815260086020526040902060038101549192509061122b5760405162461bcd60e51b815260040161095d906144cb565b600f54600382015461123c916124ff565b421161125a5760405162461bcd60e51b815260040161095d90614331565b600481015474010000000000000000000000000000000000000000900460ff16156112975760405162461bcd60e51b815260040161095d90613b73565b6004810180547fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff167401000000000000000000000000000000000000000017905560006112e3856116f0565b6000858152600760209081526040808320878452909152902054909150156113be57601054600085815260076020908152604080832087845290915290205461132b916124ff565b8260010154111561136f57815461136a9073ffffffffffffffffffffffffffffffffffffffff166113658361135f896120d9565b906124ff565b6126d0565b6113b9565b60048201546113949073ffffffffffffffffffffffffffffffffffffffff16826126d0565b81546113b99073ffffffffffffffffffffffffffffffffffffffff16611365876120d9565b611411565b6113df61dead6113da60046113d485600161272d565b90612767565b61268f565b6004808301546114119173ffffffffffffffffffffffffffffffffffffffff90911690611365906113d485600761272d565b85837f4a99228a8a6d774d261be57ab0ed833bb1bae1f22bbbd3d4767b75ad03fdddf78760405161144291906138f6565b60405180910390a3505050505050565b3360009081526001602052604090205460ff166114815760405162461bcd60e51b815260040161095d906141d1565b600061148d84836116b8565b6000848152600760209081526040808320848452909152902054909150156114c75760405162461bcd60e51b815260040161095d90614085565b600081815260086020526040902060010154156114f65760405162461bcd60e51b815260040161095d90614676565b600061150142610ebd565b9050600061150e846120d9565b600083815260096020908152604080832033845290915290205490915061153590826124ff565b60008381526009602090815260408083203380855290835281842094909455805160c08101825293845242848301908152848201898152606086018581526080870186815260a088018781528b88526008909652939095209551865473ffffffffffffffffffffffffffffffffffffffff9182167fffffffffffffffffffffffff00000000000000000000000000000000000000009182161788559251600188015590516002870155935160038601559051600490940180549251151574010000000000000000000000000000000000000000027fffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffff95909416929091169190911792909216179055611648868686612799565b857fa57b3e1f3af9eca02201028629700658608222c365064584cfe65d9630ef4f7b8560405161167891906138f6565b60405180910390a250505061168c336122dd565b611695336110d0565b10156116b35760405162461bcd60e51b815260040161095d9061413f565b505050565b600082826040516020016116cd92919061374f565b60405160208183030381529060405280519060200120905092915050565b600a81565b6000610fb982600a612767565b600c6020526000908152604090205473ffffffffffffffffffffffffffffffffffffffff1681565b61172d612317565b73ffffffffffffffffffffffffffffffffffffffff81166117605760405162461bcd60e51b815260040161095d906145bc565b600b80547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff92909216919091179055565b600260005414156117ca5760405162461bcd60e51b815260040161095d90614585565b6002600090815573ffffffffffffffffffffffffffffffffffffffff831681526001602081905260409091205460ff161515146118195760405162461bcd60e51b815260040161095d90613c8a565b61182333826125b0565b61182d82826126d0565b8173ffffffffffffffffffffffffffffffffffffffff167febedb8b3c678666e7f36970bc8f57abf6d8fa2e828c0da91ea5b75bf68ed101a8260405161187391906138f6565b60405180910390a250506001600055565b6000878787878787876040516020016118a39796959493929190614751565b604051602081830303815290604052805190602001209050979650505050505050565b600061190484848080602002602001604051908101604052809392919081815260200183836020028082843760009201919091525061293592505050565b9050600061191282846116b8565b90506000805b858110156119d65773ffffffffffffffffffffffffffffffffffffffff881660009081526006602052604081208189898581811061195257fe5b90506020020135815260200190815260200160002054905060008111156119cd5761197d83826124ff565b73ffffffffffffffffffffffffffffffffffffffff8a16600090815260066020526040812091945090818a8a868181106119b357fe5b905060200201358152602001908152602001600020819055505b50600101611918565b506119e1828261246c565b6119eb87826126d0565b828773ffffffffffffffffffffffffffffffffffffffff167f78e830d08be9d5f957414c84d685c061ecbd8467be98b42ebb64f0118b57d2ff83604051611a3291906138f6565b60405180910390a350505050505050565b7f000000000000000000000000c5102fe9359fd9a28f877a67e36b0f050d81a3cc81565b60115473ffffffffffffffffffffffffffffffffffffffff163314611a9e5760405162461bcd60e51b815260040161095d9061429d565b6040517f70a0823100000000000000000000000000000000000000000000000000000000815260009073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000c5102fe9359fd9a28f877a67e36b0f050d81a3cc16906370a0823190611b13903090600401613779565b60206040518083038186803b158015611b2b57600080fd5b505afa158015611b3f573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b6391906135a0565b9050611b6f828261268f565b5050565b611bb787858585808060200260200160405190810160405280939291908181526020018383602002808284376000920191909152508c959493925087915050612350565b611bd35760405162461bcd60e51b815260040161095d90614208565b6000611bdf87876116b8565b73ffffffffffffffffffffffffffffffffffffffff8a1660009081526006602090815260408083208c845290915290205490915080611c305760405162461bcd60e51b815260040161095d90613a60565b73ffffffffffffffffffffffffffffffffffffffff8a1660009081526006602090815260408083208c8452909152812055611c6b828261246c565b611c758a826126d0565b87898b73ffffffffffffffffffffffffffffffffffffffff167f84eb21b24c31b27a3bc67dde4a598aad06db6e9415cd66544492b9616996143c60405160405180910390a450505050505050505050565b611cce612317565b6000611cda84846116b8565b9050611ce461324f565b611cee8585611d89565b9050806040015160001415611d155760405162461bcd60e51b815260040161095d90613b05565b80518414611d1f57fe5b6040810151600090611d34906249d4006124ff565b905080421015611d565760405162461bcd60e51b815260040161095d90613c2d565b60208201518251600091611d6a919061252b565b9050611d76848261246c565b611d80858261268f565b50505050505050565b611d9161324f565b60046000611d9f85856116b8565b81526020019081526020016000206040518060600160405290816000820154815260200160018201548152602001600282015481525050905092915050565b611de6612317565b6000918252600c602052604090912080547fffffffffffffffffffffffff00000000000000000000000000000000000000001673ffffffffffffffffffffffffffffffffffffffff909216919091179055565b73ffffffffffffffffffffffffffffffffffffffff1660009081526001602052604090205460ff1690565b6000878152600c602052604090205473ffffffffffffffffffffffffffffffffffffffff1680611ea65760405162461bcd60e51b815260040161095d90613f00565b6000888152600d602052604090205460ff1615611ed55760405162461bcd60e51b815260040161095d90613cc1565b60008611611ef55760405162461bcd60e51b815260040161095d90613912565b81861015611f155760405162461bcd60e51b815260040161095d906146d3565b611f1f33876125b0565b6060878787878787604051602401611f3c969594939291906138a3565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0818403018152918152602080830180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fcc29a3060000000000000000000000000000000000000000000000000000000017905260008c8152600a9091522054909150611fcc90886124ff565b60008a8152600a60205260409081902091909155517f419cb55000000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff83169063419cb550906120309084906004016138ff565b600060405180830381600087803b15801561204a57600080fd5b505af115801561205e573d6000803e3d6000fd5b505050508373ffffffffffffffffffffffffffffffffffffffff168873ffffffffffffffffffffffffffffffffffffffff168a7f0a0607688c86ec1775abcdbab7b33a3a35a6c9cde677c9be880150c231cc6b0b8a8a8a896040516120c69493929190614797565b60405180910390a4505050505050505050565b6000610fb96120e7836116f0565b83906124ff565b6120f6612317565b600f55565b6000858152600c60205260408082205490517f99178dd8000000000000000000000000000000000000000000000000000000008152879273ffffffffffffffffffffffffffffffffffffffff9092169182916399178dd89161216491339190369060040161379a565b600060405180830381600087803b15801561217e57600080fd5b505af1158015612192573d6000803e3d6000fd5b5050505060006121a287866116b8565b6000878152600760209081526040808320848452909152902054909150156121dc5760405162461bcd60e51b815260040161095d90613fcb565b600084116121fc5760405162461bcd60e51b815260040161095d90613d55565b6000868152600760209081526040808320848452825291829020869055815160808101909252604680835261224d92889290919061480f9083013960008b8152600a60205260409020549190612d52565b6000898152600a60209081526040808320939093558382526008905220600181015461227e5761227e888888612799565b87878a7ffdfb0eefa96935b8a8c0edf528e125dc6f3934fdbbfce31b38967e8ff413dccd896040516120c691906138f6565b600e5481565b600d6020526000908152604090205460ff1681565b600a6020526000908152604090205481565b6000610fb96122eb83612d7e565b73ffffffffffffffffffffffffffffffffffffffff8416600090815260036020526040902054906124ff565b600b5473ffffffffffffffffffffffffffffffffffffffff16331461234e5760405162461bcd60e51b815260040161095d906139cc565b565b60008082116123715760405162461bcd60e51b815260040161095d906140e2565b8184106123905760405162461bcd60e51b815260040161095d90613ea3565b61239982612dfc565b8351146123b85760405162461bcd60e51b815260040161095d9061438e565b8460005b845181101561245f578560011660011415612414578481815181106123dd57fe5b6020026020010151826040516020016123f792919061374f565b604051602081830303815290604052805190602001209150612453565b8185828151811061242157fe5b602002602001015160405160200161243a92919061374f565b6040516020818303038152906040528051906020012091505b600195861c95016123bc565b5090951495945050505050565b600082815260046020526040902080546124985760405162461bcd60e51b815260040161095d90613a97565b60018101546000906124aa90846124ff565b82549091508111156124ce5760405162461bcd60e51b815260040161095d90614528565b6001909101555050565b6124e184612e91565b6124ef836113da848461252b565b8015610e3957610e39338261268f565b6000828201838110156125245760405162461bcd60e51b815260040161095d90613b3c565b9392505050565b60008282111561254d5760405162461bcd60e51b815260040161095d90613d1e565b50900390565b73ffffffffffffffffffffffffffffffffffffffff821660009081526003602052604090205461258390826124ff565b73ffffffffffffffffffffffffffffffffffffffff90921660009081526003602052604090209190915550565b611b6f73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000c5102fe9359fd9a28f877a67e36b0f050d81a3cc16833084612ef9565b3360009081526006602090815260408083208584529091529020541561262a5760405162461bcd60e51b815260040161095d90614411565b6126343382612553565b336000908152600660209081526040808320858452909152908190208290555182907f0c3d250c7831051e78aa6a56679e590374c7c424415ffe4aa474491def2fe705906126839084906138f6565b60405180910390a25050565b611b6f73ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000c5102fe9359fd9a28f877a67e36b0f050d81a3cc168383612f9c565b73ffffffffffffffffffffffffffffffffffffffff821660009081526002602052604090205461270090826124ff565b73ffffffffffffffffffffffffffffffffffffffff90921660009081526002602052604090209190915550565b60008261273c57506000610fb9565b8282028284828161274957fe5b04146125245760405162461bcd60e51b815260040161095d90614028565b60008082116127885760405162461bcd60e51b815260040161095d90613e0f565b81838161279157fe5b049392505050565b6127a1610fbf565b8214156127b7576127b28382612fbb565b6116b3565b6000828152600a60205260409020546127d090826124ff565b6000838152600a6020908152604080832093909355600c9052205473ffffffffffffffffffffffffffffffffffffffff168061281e5760405162461bcd60e51b815260040161095d90613f00565b6060848360405160240161283392919061374f565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529181526020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167ffd31c5ba00000000000000000000000000000000000000000000000000000000179052517f419cb55000000000000000000000000000000000000000000000000000000000815290915073ffffffffffffffffffffffffffffffffffffffff83169063419cb550906128fc9084906004016138ff565b600060405180830381600087803b15801561291657600080fd5b505af115801561292a573d6000803e3d6000fd5b505050505050505050565b6000808251116129575760405162461bcd60e51b815260040161095d90614619565b81516001141561297d578160008151811061296e57fe5b60200260200101519050610b2e565b612985613270565b5060408051610200810182527f290decd9548b62a8d60345a988386fc84ba6bc95484008f6362f93160ef3e56381527f633dc4d7da7256660a892f8f1604a44b5432649cc8ec5cb3ced4c4e6ac94dd1d60208201527f890740a8eb06ce9be422cb8da5cdafc2b58c0a5e24036c578de2a433c828ff7d818301527f3b8ec09e026fdc305365dfc94e189a81b38c7597b3d941c279f042e8206e0bd86060808301919091527fecd50eee38e386bd62be9bedb990706951b65fe053bd9d8a521af753d139e2da60808301527fdefff6d330bb5403f63b14f33b578274160de3a50df4efecf0e0db73bcdd3da560a08301527f617bdd11f7c0a11f49db22f629387a12da7596f9d1704d7465177c63d88ec7d760c08301527f292c23a9aa1d8bea7e2435e555a4a60e379a5a35f3f452bae60121073fb6eead60e08301527fe1cea92ed99acdcb045a6726b2f87107e8a61620a232cf4d7d5b5766b3952e106101008301527f7ad66c0a68c72cb89e4fb4303841966e4062a76ab97451e3b9fb526a5ceb7f826101208301527fe026cc5a4aed3c22a58cbd3d2ac754c9352c5436f638042dca99034e836365166101408301527f3d04cffd8b46a874edf5cfae63077de85f849a660426697b06a829c70dd1409c6101608301527fad676aa337a485e4728a0b240d92b3ef7b3c372d06d189322bfd5f61f1e7203e6101808301527fa2fca4a49658f9fab7aa63289c91b7c7b6c832a6d0e69334ff5b0a3483d09dab6101a08301527f4ebfd9cd7bca2505f7bef59cc1c12ecc708fff26ae4af19abe852afe9e20c8626101c08301527f2def10d13dd169f550f578bda343d9717a138562e0093b380a1120789d53cf106101e0830152825183815280820184529192909190602082018180368337505085519192506000918291508180805b6001841115612d2e5750506002820460018084161460005b82811015612caa578a8160020281518110612c5157fe5b602002602001015196508a8160020260010181518110612c6d57fe5b6020026020010151955086602089015285604089015287805190602001208b8281518110612c9757fe5b6020908102919091010152600101612c3a565b508015612d0d57896001850381518110612cc057fe5b60200260200101519550878360108110612cd657fe5b602002015160001b945085602088015284604088015286805190602001208a8381518110612d0057fe5b6020026020010181815250505b80612d19576000612d1c565b60015b60ff1682019350600190920191612c22565b89600081518110612d3b57fe5b602002602001015198505050505050505050919050565b60008184841115612d765760405162461bcd60e51b815260040161095d91906138ff565b505050900390565b600080612d8a42610ebd565b9050600080613840600e5481612d9c57fe5b04905060005b81811015612df257808403600090815260096020908152604080832073ffffffffffffffffffffffffffffffffffffffff8a168452909152902054612de89084906124ff565b9250600101612da2565b5090949350505050565b6000808211612e1d5760405162461bcd60e51b815260040161095d90613f37565b8160011415612e2e57506000610b2e565b81600060805b60018110612e7c577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6001821b01811b831615612e745791821c91908101905b60011c612e34565b506001811b8414612524576001019392505050565b60008181526005602052604090205460ff1615612ec05760405162461bcd60e51b815260040161095d90613e46565b600090815260056020526040902080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00166001179055565b610e39846323b872dd60e01b858585604051602401612f1a93929190613804565b604080517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08184030181529190526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167fffffffff000000000000000000000000000000000000000000000000000000009093169290921790915261308f565b6116b38363a9059cbb60e01b8484604051602401612f1a929190613835565b6000612fc783836116b8565b60008181526004602052604090205490915015612ff65760405162461bcd60e51b815260040161095d90613f94565b600082116130165760405162461bcd60e51b815260040161095d90614174565b6040805160608101825283815260006020808301828152428486019081528684526004909252918490209251835590516001830155516002909101555183907fb33d2162aead99dab59e77a7a67ea025b776bf8ca8079e132afdf9b23e03bd42906130829085906138f6565b60405180910390a2505050565b60606130f1826040518060400160405280602081526020017f5361666545524332303a206c6f772d6c6576656c2063616c6c206661696c65648152508573ffffffffffffffffffffffffffffffffffffffff1661312b9092919063ffffffff16565b8051909150156116b3578080602001905181019061310f91906134e8565b6116b35760405162461bcd60e51b815260040161095d9061446e565b606061313a8484600085613142565b949350505050565b6060824710156131645760405162461bcd60e51b815260040161095d90613db2565b61316d85613210565b6131895760405162461bcd60e51b815260040161095d906142fa565b600060608673ffffffffffffffffffffffffffffffffffffffff1685876040516131b3919061375d565b60006040518083038185875af1925050503d80600081146131f0576040519150601f19603f3d011682016040523d82523d6000602084013e6131f5565b606091505b5091509150613205828286613216565b979650505050505050565b3b151590565b60608315613225575081612524565b8251156132355782518084602001fd5b8160405162461bcd60e51b815260040161095d91906138ff565b60405180606001604052806000815260200160008152602001600081525090565b6040518061020001604052806010906020820280368337509192915050565b60008083601f8401126132a0578182fd5b50813567ffffffffffffffff8111156132b7578182fd5b60208301915083602080830285010111156132d157600080fd5b9250929050565b6000602082840312156132e9578081fd5b8135612524816147de565b60008060008060608587031215613309578283fd5b8435613314816147de565b9350602085013567ffffffffffffffff81111561332f578384fd5b61333b8782880161328f565b9598909750949560400135949350505050565b60008060408385031215613360578182fd5b823561336b816147de565b946020939093013593505050565b60008060008060008060008060e0898b031215613394578384fd5b883561339f816147de565b97506020890135965060408901359550606089013594506080890135935060a089013567ffffffffffffffff8111156133d6578384fd5b6133e28b828c0161328f565b999c989b50969995989497949560c00135949350505050565b60008060008060808587031215613410578384fd5b843561341b816147de565b966020860135965060408601359560600135945092505050565b6000806000806000806000806000806000806101608d8f031215613457578384fd5b6134618d356147de565b8c359b5060208d01359a5060408d0135995060608d0135985060808d0135975060a08d0135965060c08d0135955060e08d013594506101008d0135935067ffffffffffffffff6101208e013511156134b7578283fd5b6134c88e6101208f01358f0161328f565b81945080935050506101408d013590509295989b509295989b509295989b565b6000602082840312156134f9578081fd5b815161252481614800565b600060208284031215613515578081fd5b5035919050565b6000806040838503121561352e578182fd5b50508035926020909101359150565b600080600060608486031215613551578081fd5b8335925060208401359150604084013561356a816147de565b809150509250925092565b600080600060608486031215613589578081fd5b505081359360208301359350604090920135919050565b6000602082840312156135b1578081fd5b5051919050565b600080604083850312156135ca578182fd5b8235915060208301356135dc816147de565b809150509250929050565b600080600080600080600060e0888a031215613601578081fd5b873596506020880135613613816147de565b96999698505050506040850135946060810135946080820135945060a0820135935060c0909101359150565b600080600080600080600060e0888a031215613659578081fd5b87359650602088013561366b816147de565b955060408801359450606088013593506080880135925060a0880135613690816147de565b8092505060c0880135905092959891949750929550565b600080604083850312156136b9578182fd5b8235915060208301356135dc81614800565b600080600080600060a086880312156136e2578283fd5b505083359560208501359550604085013594606081013594506080013592509050565b6000815180845261371d8160208601602086016147b2565b601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169290920160200192915050565b918252602082015260400190565b6000825161376f8184602087016147b2565b9190910192915050565b73ffffffffffffffffffffffffffffffffffffffff91909116815260200190565b600073ffffffffffffffffffffffffffffffffffffffff851682526040602083015282604083015282846060840137818301606090810191909152601f9092017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016010192915050565b73ffffffffffffffffffffffffffffffffffffffff9384168152919092166020820152604081019190915260600190565b73ffffffffffffffffffffffffffffffffffffffff929092168252602082015260400190565b73ffffffffffffffffffffffffffffffffffffffff9687168152602081019590955260408501939093526060840191909152909216608082015290151560a082015260c00190565b73ffffffffffffffffffffffffffffffffffffffff9687168152602081019590955260408501939093526060840191909152909216608082015260a081019190915260c00190565b901515815260200190565b90815260200190565b6000602082526125246020830184613705565b60208082526027908201527f4c315f4252473a204d757374207472616e736665722061206e6f6e2d7a65726f60408201527f20616d6f756e7400000000000000000000000000000000000000000000000000606082015260800190565b6020808252603b908201527f4c315f4252473a206368616c6c656e6765506572696f64206d7573742062652060408201527f646976697369626c652062792054494d455f534c4f545f53495a450000000000606082015260800190565b6020808252601f908201527f4c315f4252473a2043616c6c6572206973206e6f7420746865206f776e657200604082015260600190565b60208082526028908201527f4c315f4252473a205472616e73666572526f6f7420686173206e6f742062656560408201527f6e20626f6e646564000000000000000000000000000000000000000000000000606082015260800190565b6020808252601e908201527f4c325f4252473a207472616e73666572496420686173206e6f20626f6e640000604082015260600190565b6020808252601c908201527f4252473a205472616e7366657220726f6f74206e6f7420666f756e6400000000604082015260600190565b6020808252601e908201527f4143543a204164647265737320697320616c726561647920626f6e6465720000604082015260600190565b6020808252601b908201527f4252473a205472616e73666572526f6f74206e6f7420666f756e640000000000604082015260600190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b60208082526025908201527f4c315f4252473a205472616e73666572526f6f7420616c72656164792072657360408201527f6f6c766564000000000000000000000000000000000000000000000000000000606082015260800190565b60208082526027908201527f4c315f4252473a205472616e73666572526f6f7420616c72656164792063686160408201527f6c6c656e67656400000000000000000000000000000000000000000000000000606082015260800190565b6020808252603b908201527f4252473a205472616e73666572526f6f742063616e6e6f74206265207265736360408201527f756564206265666f726520746865205265736375652044656c61790000000000606082015260800190565b6020808252601a908201527f4143543a2041646472657373206973206e6f7420626f6e646572000000000000604082015260600190565b60208082526028908201527f4c315f4252473a2053656e647320746f207468697320636861696e496420617260408201527f6520706175736564000000000000000000000000000000000000000000000000606082015260800190565b6020808252601e908201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604082015260600190565b6020808252602e908201527f4c315f4252473a20726f6f74436f6d6d69747465644174206d7573742062652060408201527f67726561746572207468616e2030000000000000000000000000000000000000606082015260800190565b60208082526026908201527f416464726573733a20696e73756666696369656e742062616c616e636520666f60408201527f722063616c6c0000000000000000000000000000000000000000000000000000606082015260800190565b6020808252601a908201527f536166654d6174683a206469766973696f6e206279207a65726f000000000000604082015260600190565b6020808252602c908201527f4252473a20546865207472616e736665722068617320616c726561647920626560408201527f656e2077697468647261776e0000000000000000000000000000000000000000606082015260800190565b60208082526024908201527f4c69625f4d65726b6c65547265653a20496e646578206f7574206f6620626f7560408201527f6e64732e00000000000000000000000000000000000000000000000000000000606082015260800190565b6020808252601d908201527f4c315f4252473a20636861696e4964206e6f7420737570706f72746564000000604082015260600190565b60208082526030908201527f4c69625f4d65726b6c65547265653a2043616e6e6f7420636f6d70757465206360408201527f65696c286c6f675f3229206f6620302e00000000000000000000000000000000606082015260800190565b6020808252601e908201527f4252473a205472616e7366657220726f6f7420616c7265616479207365740000604082015260600190565b60208082526026908201527f4c315f4252473a205472616e73666572526f6f7420616c726561647920636f6e60408201527f6669726d65640000000000000000000000000000000000000000000000000000606082015260800190565b60208082526021908201527f536166654d6174683a206d756c7469706c69636174696f6e206f766572666c6f60408201527f7700000000000000000000000000000000000000000000000000000000000000606082015260800190565b6020808252602f908201527f4c315f4252473a205472616e73666572526f6f742068617320616c726561647960408201527f206265656e20636f6e6669726d65640000000000000000000000000000000000606082015260800190565b60208082526037908201527f4c69625f4d65726b6c65547265653a20546f74616c206c6561766573206d757360408201527f742062652067726561746572207468616e207a65726f2e000000000000000000606082015260800190565b6020808252818101527f4143543a204e6f7420656e6f75676820617661696c61626c6520637265646974604082015260600190565b6020808252602d908201527f4252473a2043616e6e6f7420736574205472616e73666572526f6f7420746f7460408201527f616c416d6f756e74206f66203000000000000000000000000000000000000000606082015260800190565b60208082526019908201527f4143543a2043616c6c6572206973206e6f7420626f6e64657200000000000000604082015260600190565b6020808252601b908201527f4252473a20496e76616c6964207472616e736665722070726f6f660000000000604082015260600190565b602080825260409082018190527f4c315f4252473a205472616e73666572526f6f742063616e6e6f742062652063908201527f68616c6c656e676564206166746572206368616c6c656e676520706572696f64606082015260800190565b60208082526026908201527f4c315f484f505f4252473a2043616c6c6572206973206e6f7420746865206d6960408201527f677261746f720000000000000000000000000000000000000000000000000000606082015260800190565b6020808252601d908201527f416464726573733a2063616c6c20746f206e6f6e2d636f6e7472616374000000604082015260600190565b60208082526026908201527f4c315f4252473a204368616c6c656e676520706572696f6420686173206e6f7460408201527f20656e6465640000000000000000000000000000000000000000000000000000606082015260800190565b6020808252604d908201527f4c69625f4d65726b6c65547265653a20546f74616c207369626c696e6773206460408201527f6f6573206e6f7420636f72726563746c7920636f72726573706f6e6420746f2060608201527f746f74616c206c65617665732e00000000000000000000000000000000000000608082015260a00190565b60208082526027908201527f4252473a205769746864726177616c2068617320616c7265616479206265656e60408201527f20626f6e64656400000000000000000000000000000000000000000000000000606082015260800190565b6020808252602a908201527f5361666545524332303a204552433230206f7065726174696f6e20646964206e60408201527f6f74207375636365656400000000000000000000000000000000000000000000606082015260800190565b6020808252602c908201527f4c315f4252473a205472616e73666572526f6f7420686173206e6f742062656560408201527f6e206368616c6c656e6765640000000000000000000000000000000000000000606082015260800190565b6020808252602a908201527f4252473a205769746864726177616c2065786365656473205472616e7366657260408201527f526f6f7420746f74616c00000000000000000000000000000000000000000000606082015260800190565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b6020808252602b908201527f4c315f4252473a205f6e6577476f7665726e616e63652063616e6e6f7420626560408201527f2061646472657373283029000000000000000000000000000000000000000000606082015260800190565b60208082526034908201527f4c69625f4d65726b6c65547265653a204d7573742070726f766964652061742060408201527f6c65617374206f6e65206c65616620686173682e000000000000000000000000606082015260800190565b6020808252602c908201527f4c315f4252473a205472616e73666572526f6f742068617320616c726561647960408201527f206265656e20626f6e6465640000000000000000000000000000000000000000606082015260800190565b60208082526028908201527f4c315f4252473a2052656c61796572206665652063616e6e6f7420657863656560408201527f6420616d6f756e74000000000000000000000000000000000000000000000000606082015260800190565b81518152602080830151908201526040918201519181019190915260600190565b96875273ffffffffffffffffffffffffffffffffffffffff95909516602087015260408601939093526060850191909152608084015260a083015260c082015260e00190565b93845260208401929092526040830152606082015260800190565b60005b838110156147cd5781810151838201526020016147b5565b83811115610e395750506000910152565b73ffffffffffffffffffffffffffffffffffffffff81168114610f8457600080fd5b8015158114610f8457600080fdfe4c315f4252473a20416d6f756e74206578636565647320636861696e42616c616e63652e205468697320696e646963617465732061206c617965722d32206661696c7572652ea26469706673582212205119361c8f9a9053273deeda832fc1c9e476e45dcf2a64e49d2548672465bec964736f6c634300060c0033

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

000000000000000000000000c5102fe9359fd9a28f877a67e36b0f050d81a3cc0000000000000000000000000000000000000000000000000000000000000080000000000000000000000000f56e305024b195383245a075737d16dbdb8487fb000000000000000000000000eea8422a08258e73c139fc32a25e10410c14bd7a00000000000000000000000000000000000000000000000000000000000000010000000000000000000000002a6303e6b99d451df3566068ebb110708335658f

-----Decoded View---------------
Arg [0] : _l1CanonicalToken (address): 0xc5102fE9359FD9a28f877a67E36B0F050d81a3CC
Arg [1] : bonders (address[]): 0x2A6303e6b99d451Df3566068EBb110708335658f
Arg [2] : _governance (address): 0xF56e305024B195383245A075737d16dBdb8487Fb
Arg [3] : _migrator (address): 0xeeA8422a08258e73c139Fc32a25e10410c14bd7a

-----Encoded View---------------
6 Constructor Arguments found :
Arg [0] : 000000000000000000000000c5102fe9359fd9a28f877a67e36b0f050d81a3cc
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000080
Arg [2] : 000000000000000000000000f56e305024b195383245a075737d16dbdb8487fb
Arg [3] : 000000000000000000000000eea8422a08258e73c139fc32a25e10410c14bd7a
Arg [4] : 0000000000000000000000000000000000000000000000000000000000000001
Arg [5] : 0000000000000000000000002a6303e6b99d451df3566068ebb110708335658f


Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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

OVERVIEW

The Hop protocol bridge for the HOP token.

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading
[ Download: CSV Export  ]

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