Contract

0xBB3bb9D08fd0e92eBdB69ECb6a3336061417fdc7

Overview

S Balance

Sonic LogoSonic LogoSonic Logo0 S

S Value

-

Token Holdings

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Create Refuel Re...29946292025-01-08 14:44:062 hrs ago1736347446IN
0xBB3bb9D0...61417fdc7
0.2 S0.000706765.51
Create Refuel Re...29810712025-01-08 12:37:514 hrs ago1736339871IN
0xBB3bb9D0...61417fdc7
0.1 S0.000706765.51
Create Refuel Re...29686962025-01-08 10:09:017 hrs ago1736330941IN
0xBB3bb9D0...61417fdc7
169.95 S0.000672085.5
Create Refuel Re...29455132025-01-08 5:36:5111 hrs ago1736314611IN
0xBB3bb9D0...61417fdc7
189.90206106 S0.000672215.5
Create Refuel Re...28565842025-01-07 13:05:3728 hrs ago1736255137IN
0xBB3bb9D0...61417fdc7
59.5 S0.000722365.63
Create Refuel Re...28540872025-01-07 12:27:2728 hrs ago1736252847IN
0xBB3bb9D0...61417fdc7
47.93461888 S0.000672215.5
Create Refuel Re...28537982025-01-07 12:22:2829 hrs ago1736252548IN
0xBB3bb9D0...61417fdc7
4 S0.000671955.5
Create Refuel Re...28034062025-01-07 3:55:2537 hrs ago1736222125IN
0xBB3bb9D0...61417fdc7
284.65511028 S0.000134391.1
Create Refuel Re...27849442025-01-07 1:17:5040 hrs ago1736212670IN
0xBB3bb9D0...61417fdc7
30 S0.000142411.11
Create Refuel Re...27435332025-01-06 18:19:1747 hrs ago1736187557IN
0xBB3bb9D0...61417fdc7
7 S0.000142371.11
Create Refuel Re...27429492025-01-06 18:13:2147 hrs ago1736187201IN
0xBB3bb9D0...61417fdc7
68 S0.000156541.22
Create Refuel Re...14428012024-12-24 9:06:1315 days ago1735031173IN
0xBB3bb9D0...61417fdc7
1 wei0.000121661
Create Refuel Re...14427272024-12-24 9:05:2415 days ago1735031124IN
0xBB3bb9D0...61417fdc7
1 wei0.000121661
Create Refuel Re...14425532024-12-24 9:03:2315 days ago1735031003IN
0xBB3bb9D0...61417fdc7
1 wei0.000138761

Latest 14 internal transactions

Parent Transaction Hash Block From To
29946292025-01-08 14:44:062 hrs ago1736347446
0xBB3bb9D0...61417fdc7
0.2 S
29810712025-01-08 12:37:514 hrs ago1736339871
0xBB3bb9D0...61417fdc7
0.1 S
29686962025-01-08 10:09:017 hrs ago1736330941
0xBB3bb9D0...61417fdc7
169.95 S
29455132025-01-08 5:36:5111 hrs ago1736314611
0xBB3bb9D0...61417fdc7
189.90206106 S
28565842025-01-07 13:05:3728 hrs ago1736255137
0xBB3bb9D0...61417fdc7
59.5 S
28540872025-01-07 12:27:2728 hrs ago1736252847
0xBB3bb9D0...61417fdc7
47.93461888 S
28537982025-01-07 12:22:2829 hrs ago1736252548
0xBB3bb9D0...61417fdc7
4 S
28034062025-01-07 3:55:2537 hrs ago1736222125
0xBB3bb9D0...61417fdc7
284.65511028 S
27849442025-01-07 1:17:5040 hrs ago1736212670
0xBB3bb9D0...61417fdc7
30 S
27435332025-01-06 18:19:1747 hrs ago1736187557
0xBB3bb9D0...61417fdc7
7 S
27429492025-01-06 18:13:2147 hrs ago1736187201
0xBB3bb9D0...61417fdc7
68 S
14428012024-12-24 9:06:1315 days ago1735031173
0xBB3bb9D0...61417fdc7
1 wei
14427272024-12-24 9:05:2415 days ago1735031124
0xBB3bb9D0...61417fdc7
1 wei
14425532024-12-24 9:03:2315 days ago1735031003
0xBB3bb9D0...61417fdc7
1 wei
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
RefuelInbox

Compiler Version
v0.8.19+commit.7dd6d404

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion
File 1 of 18 : RefuelInbox.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.17;

import {WETH} from "solmate/src/tokens/WETH.sol";
import {ERC20, SafeTransferLib} from "solmate/src/utils/SafeTransferLib.sol";
import {Permit2HashHelper} from "../lib/Permit2HashHelper.sol";
import {RequestLib as SingleOutputRequestLib} from "../lib/SingleOutputRequestLib.sol";
import {InboxEvents} from "../common/InboxEvents.sol";
import {BasicRequest, Request as SingleOutputRequest} from "../common/SingleOutputStructs.sol";
import {Ownable} from "../utils/Ownable.sol";
import {IBungeeGateway} from "../interfaces/IBungeeGateway.sol";
import {ISingleOutputRequestImpl} from "../interfaces/ISingleOutputRequestImpl.sol";
import {IPermit2} from "permit2/src/interfaces/IPermit2.sol";
import {
    InvalidChainId,
    InvalidMsgValue,
    InvalidNonce,
    TransferFailed,
    RequestDoesNotExist,
    RequestAlreadyWithdraw
} from "../common/InboxErrors.sol";

/// @title Refuel Inbox
/// @notice Enables users to send Refuel (native token) bridging requests to Bungee Protocol auction
/// @dev To send Requests to Bungee Protocol, users are required to sign on a Request (EIP-712)
/// @dev Then submit Request + signed message to Bungee Protocol's off-chain auction service
/// @dev To enable creating orders on-chain, users can use Inboxes where request details are stored
/// @dev Request creation event is emitted which is picked up by BP's auction
/// @dev Bungee Protocol uses PERMIT-2, which uses EIP-1271 to validate stored requests on the Inbox
/// @author [email protected]
contract RefuelInbox is Ownable, InboxEvents {
    /*//////////////////////////////////////////////////////////////////////////
                                    LIBS
    //////////////////////////////////////////////////////////////////////////*/

    using SingleOutputRequestLib for SingleOutputRequest;
    using SafeTransferLib for ERC20;

    /*//////////////////////////////////////////////////////////////////////////
                                    CONSTANTS
    //////////////////////////////////////////////////////////////////////////*/

    /// @notice Permit2 contract address
    IPermit2 public immutable PERMIT2;

    /// @notice Wrapped native token address
    WETH public immutable WRAPPED_NATIVE_TOKEN;

    /// @notice bungeeGateway contract address
    IBungeeGateway public immutable BUNGEE_GATEWAY;

    /// @notice Address used to denote native tokens on Bungee Protocol
    address public constant NATIVE_TOKEN_ADDRESS = address(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE);

    /// @notice MAGIC_VALUE returned for valid signatures according to EIP-1271
    /// @dev https://eips.ethereum.org/EIPS/eip-1271
    bytes4 internal constant MAGIC_VALUE = 0x1626ba7e;

    /// @notice MAGIC_VALUE returned for valid signatures according to EIP-1271
    /// @dev https://eips.ethereum.org/EIPS/eip-1271
    bytes4 internal constant NON_MAGIC_VALUE = 0xffffffff;

    /*//////////////////////////////////////////////////////////////////////////
                                    PUBLIC STORAGE
    //////////////////////////////////////////////////////////////////////////*/

    /// @notice stores requests created by users
    mapping(uint256 nonce => ReceivedRequest receivedRequest) public requestInbox;

    /// @notice stores requests withdrawn by users post-extraction
    mapping(bytes32 typedDataHash => bool withdrawn) public withdrawnInbox;

    /*//////////////////////////////////////////////////////////////////////////
                                    STRUCTS
    //////////////////////////////////////////////////////////////////////////*/

    /// @notice Struct used to store received requests against request nonce
    /// @param ogSender sender of the request
    /// @param typedDataHash typedDataHash of the Request's hash
    struct ReceivedRequest {
        address ogSender;
        bytes32 typedDataHash;
    }

    /*//////////////////////////////////////////////////////////////////////////
                                    CONSTRUCTOR
    //////////////////////////////////////////////////////////////////////////*/

    /// @dev constructor sets immutable variables and gives infinite WETH/Wrapped Native Token approval to Permit2
    /// @param _owner owner address who'll be able to call onlyOwner methods
    /// @param _permit2 permit2 contract address
    /// @param _bungeeGateway singleOutputRequest BungeeGateway
    /// @param _wrappedNativeToken wrapped native token address
    constructor(
        address _owner,
        address _permit2,
        address _bungeeGateway,
        address payable _wrappedNativeToken
    ) Ownable(_owner) {
        PERMIT2 = IPermit2(_permit2);
        BUNGEE_GATEWAY = IBungeeGateway(_bungeeGateway);
        WRAPPED_NATIVE_TOKEN = WETH(_wrappedNativeToken);

        // Gives max Wrapped-NativeToken approval to Permit2 contract
        WRAPPED_NATIVE_TOKEN.approve(address(PERMIT2), type(uint256).max);
    }

    /*//////////////////////////////////////////////////////////////////////////
                                RECEIVE FUNCTION
    //////////////////////////////////////////////////////////////////////////*/

    /// @notice receive() function
    receive() external payable {}

    /*//////////////////////////////////////////////////////////////////////////
                                EXTERNAL FUNCTIONS
    //////////////////////////////////////////////////////////////////////////*/

    /// @notice called by the user to create a Refuel deposit request
    /// @dev Creates Refuel Request, Wraps native token, stores typedDataHash, emits Request creation event
    /// @param singleOutputRequest singleOutputRequest struct
    function createRefuelRequest(SingleOutputRequest calldata singleOutputRequest) external payable {
        // Validates Request and reverts if there are invalid details in the Request
        _checkRequestValidity(singleOutputRequest.basicReq);

        // Wraps native asset to WETH
        WRAPPED_NATIVE_TOKEN.deposit{value: msg.value}();

        // Creates RequestHash and TypedDataHash for the Request
        (bytes32 requestHash, bytes32 typedDataHash) = _createTypedDataHash(singleOutputRequest);

        // Store the hash against the nonce
        requestInbox[singleOutputRequest.basicReq.nonce] = ReceivedRequest({
            ogSender: msg.sender,
            typedDataHash: typedDataHash
        });

        // Emit event
        emit RefuelRequestCreated(requestHash, msg.sender, abi.encode(singleOutputRequest));
    }

    /// @notice called by the user to unlock/withdraw funds if Request is not fulfilled
    /// @param singleOutputRequest singleOutputRequest struct
    function withdrawFunds(SingleOutputRequest calldata singleOutputRequest) external {
        // creates requestHash and typedDataHash for the Request
        (bytes32 requestHash, bytes32 typedDataHash) = _createTypedDataHash(singleOutputRequest);

        // checks if the request was created on Inbox
        if (requestInbox[singleOutputRequest.basicReq.nonce].typedDataHash != typedDataHash)
            revert RequestDoesNotExist();

        // if nonce is valid, request hasn't been extracted and funds are unlocked to the user from Inbox
        // if invalid, request has been extracted and funds are withdrawn from BungeeGateway and sent to user
        if (_isNonceValid(singleOutputRequest.basicReq.nonce)) {
            // CASE - PRE EXTRACTION
            _withdraw(singleOutputRequest.basicReq.nonce, singleOutputRequest.basicReq.inputAmount, requestHash);

            // deletes request from storage
            delete requestInbox[singleOutputRequest.basicReq.nonce];
        } else {
            // CASE - POST EXTRACTION
            // checks if the request has already been withdrawn
            if (withdrawnInbox[typedDataHash]) revert RequestAlreadyWithdraw();

            // If Request has not been withdrawn, it withdraws it
            if (!BUNGEE_GATEWAY.withdrawnRequests(requestHash)) {
                bytes memory payload = abi.encodeWithSelector(
                    ISingleOutputRequestImpl.withdrawRequestOnOrigin.selector,
                    requestHash
                );
                BUNGEE_GATEWAY.executeSOR(payload);
            }

            _withdraw(singleOutputRequest.basicReq.nonce, singleOutputRequest.basicReq.inputAmount, requestHash);

            // Stores Withdrawn Requests
            withdrawnInbox[typedDataHash] = true;
        }
    }

    /*//////////////////////////////////////////////////////////////////////////
                                Signature Verification
    //////////////////////////////////////////////////////////////////////////*/

    /// @notice Called by PERMIT2 to verify the validity of witness data signed against the nonce for transfer
    /// @param _hash PERMIT2 typedData hash
    /// @param _signature Encoded Request Details passed from PERMIT2
    function isValidSignature(bytes32 _hash, bytes calldata _signature) external view returns (bytes4 magicValue) {
        // Decodes nonce from signature
        uint256 nonce = abi.decode(_signature, (uint256));

        // Checks if hashTypedData (_hash) from PERMIT2 does not match the order stored against nonce
        if (requestInbox[nonce].typedDataHash == _hash) {
            return MAGIC_VALUE;
        } else {
            return NON_MAGIC_VALUE;
        }
    }

    /*//////////////////////////////////////////////////////////////////////////
                                ADMIN FUNCTIONS
    //////////////////////////////////////////////////////////////////////////*/

    /// @notice admin / onlyOwner function to rescue funds in case mistakenly sent to the contract
    /// @param token address of token rescused
    /// @param to address to send rescused funds to
    /// @param amount amount to be rescued
    function rescue(address token, address to, uint256 amount) external onlyOwner {
        _sendFundsFromContract(token, to, amount);
    }

    /*//////////////////////////////////////////////////////////////////////////
                                INTERNAL FUNCTIONS
    //////////////////////////////////////////////////////////////////////////*/

    /// @dev validates request details and reverts if any of the conditions are not met
    /// @param basicRequest BasicRequest struct details
    function _checkRequestValidity(BasicRequest calldata basicRequest) internal view {
        // reverts if inputAmount does not match msg.value
        if (msg.value != basicRequest.inputAmount) revert InvalidMsgValue();

        // reverts if originChainId is not the current chainId
        if (basicRequest.originChainId != block.chainid) revert InvalidChainId();

        // reverts if the nonce has already been used
        if (requestInbox[basicRequest.nonce].typedDataHash != bytes32(0)) revert InvalidNonce();
    }

    /// @dev creates typedDataHash which is the hash the user signs on for permit2
    /// @param singleOutputRequest singleOutputRequest struct
    function _createTypedDataHash(
        SingleOutputRequest calldata singleOutputRequest
    ) internal view returns (bytes32 requestHash, bytes32 typedDataHash) {
        // Creates Request Hash
        requestHash = singleOutputRequest.hashOriginRequest();

        // Hash with witness
        bytes32 hashWithWitness = Permit2HashHelper.returnHashWithWitness(
            singleOutputRequest.basicReq.inputToken,
            singleOutputRequest.basicReq.inputAmount,
            singleOutputRequest.basicReq.nonce,
            singleOutputRequest.basicReq.deadline,
            requestHash,
            SingleOutputRequestLib.PERMIT2_ORDER_TYPE,
            singleOutputRequest.basicReq.bungeeGateway
        );

        // Typed Data Hash
        typedDataHash = Permit2HashHelper._hashTypedData(address(PERMIT2), hashWithWitness);
    }

    /// @dev withdraws / unlocks funds back to the user if a Request is not fulfilled
    /// @dev this method is called in case the request is not yet picked up by Bungee Protocol
    /// @param nonce nonce of the Request
    /// @param amount user's inputAmount that was locked and to be withdrawn
    /// @param requestHash hash of the Request
    function _withdraw(uint256 nonce, uint256 amount, bytes32 requestHash) internal {
        // unwrap native token
        WRAPPED_NATIVE_TOKEN.withdraw(amount);

        // transfers funds to user
        _sendFundsFromContract(NATIVE_TOKEN_ADDRESS, requestInbox[nonce].ogSender, amount);

        // emits event
        emit RefuelRequestWithdrawn(requestHash);
    }

    /// @dev transfers native token / ERC-20 token from the contract
    /// @param token address of token being sent
    /// @param to address the token is sent to
    /// @param amount amount being sent
    function _sendFundsFromContract(address token, address to, uint256 amount) internal {
        /// native token case
        if (token == NATIVE_TOKEN_ADDRESS) {
            (bool success, ) = to.call{value: amount, gas: 5000}("");
            if (!success) revert TransferFailed();
            return;
        }

        /// ERC20 case
        ERC20(token).safeTransfer(to, amount);
    }

    /// @notice Checks if the unordered nonce has been used on Permit2
    /// @param nonce nonce value on Permit2 whose validity is to be checked
    function _isNonceValid(uint256 nonce) internal view returns (bool) {
        (uint256 wordPos, uint256 bitPos) = _bitmapPositions(nonce);

        // fetches the nonceBitmap value from PERMIT2
        uint256 bitmap = PERMIT2.nonceBitmap(address(this), wordPos);

        uint256 bit = 1 << bitPos;
        uint256 flipped = bitmap ^ bit;

        // checks if the nonce has been used
        if (flipped & bit == 0) return false;
        return true;
    }

    /// @notice Bit shifts nonce and returns wordPos and bitPos
    /// @param nonce nonce value
    function _bitmapPositions(uint256 nonce) private pure returns (uint256 wordPos, uint256 bitPos) {
        wordPos = uint248(nonce >> 8);
        bitPos = uint8(nonce);
    }
}

File 2 of 18 : IAllowanceTransfer.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

import {IEIP712} from "./IEIP712.sol";

/// @title AllowanceTransfer
/// @notice Handles ERC20 token permissions through signature based allowance setting and ERC20 token transfers by checking allowed amounts
/// @dev Requires user's token approval on the Permit2 contract
interface IAllowanceTransfer is IEIP712 {
    /// @notice Thrown when an allowance on a token has expired.
    /// @param deadline The timestamp at which the allowed amount is no longer valid
    error AllowanceExpired(uint256 deadline);

    /// @notice Thrown when an allowance on a token has been depleted.
    /// @param amount The maximum amount allowed
    error InsufficientAllowance(uint256 amount);

    /// @notice Thrown when too many nonces are invalidated.
    error ExcessiveInvalidation();

    /// @notice Emits an event when the owner successfully invalidates an ordered nonce.
    event NonceInvalidation(
        address indexed owner,
        address indexed token,
        address indexed spender,
        uint48 newNonce,
        uint48 oldNonce
    );

    /// @notice Emits an event when the owner successfully sets permissions on a token for the spender.
    event Approval(
        address indexed owner,
        address indexed token,
        address indexed spender,
        uint160 amount,
        uint48 expiration
    );

    /// @notice Emits an event when the owner successfully sets permissions using a permit signature on a token for the spender.
    event Permit(
        address indexed owner,
        address indexed token,
        address indexed spender,
        uint160 amount,
        uint48 expiration,
        uint48 nonce
    );

    /// @notice Emits an event when the owner sets the allowance back to 0 with the lockdown function.
    event Lockdown(address indexed owner, address token, address spender);

    /// @notice The permit data for a token
    struct PermitDetails {
        // ERC20 token address
        address token;
        // the maximum amount allowed to spend
        uint160 amount;
        // timestamp at which a spender's token allowances become invalid
        uint48 expiration;
        // an incrementing value indexed per owner,token,and spender for each signature
        uint48 nonce;
    }

    /// @notice The permit message signed for a single token allownce
    struct PermitSingle {
        // the permit data for a single token alownce
        PermitDetails details;
        // address permissioned on the allowed tokens
        address spender;
        // deadline on the permit signature
        uint256 sigDeadline;
    }

    /// @notice The permit message signed for multiple token allowances
    struct PermitBatch {
        // the permit data for multiple token allowances
        PermitDetails[] details;
        // address permissioned on the allowed tokens
        address spender;
        // deadline on the permit signature
        uint256 sigDeadline;
    }

    /// @notice The saved permissions
    /// @dev This info is saved per owner, per token, per spender and all signed over in the permit message
    /// @dev Setting amount to type(uint160).max sets an unlimited approval
    struct PackedAllowance {
        // amount allowed
        uint160 amount;
        // permission expiry
        uint48 expiration;
        // an incrementing value indexed per owner,token,and spender for each signature
        uint48 nonce;
    }

    /// @notice A token spender pair.
    struct TokenSpenderPair {
        // the token the spender is approved
        address token;
        // the spender address
        address spender;
    }

    /// @notice Details for a token transfer.
    struct AllowanceTransferDetails {
        // the owner of the token
        address from;
        // the recipient of the token
        address to;
        // the amount of the token
        uint160 amount;
        // the token to be transferred
        address token;
    }

    /// @notice A mapping from owner address to token address to spender address to PackedAllowance struct, which contains details and conditions of the approval.
    /// @notice The mapping is indexed in the above order see: allowance[ownerAddress][tokenAddress][spenderAddress]
    /// @dev The packed slot holds the allowed amount, expiration at which the allowed amount is no longer valid, and current nonce thats updated on any signature based approvals.
    function allowance(
        address user,
        address token,
        address spender
    ) external view returns (uint160 amount, uint48 expiration, uint48 nonce);

    /// @notice Approves the spender to use up to amount of the specified token up until the expiration
    /// @param token The token to approve
    /// @param spender The spender address to approve
    /// @param amount The approved amount of the token
    /// @param expiration The timestamp at which the approval is no longer valid
    /// @dev The packed allowance also holds a nonce, which will stay unchanged in approve
    /// @dev Setting amount to type(uint160).max sets an unlimited approval
    function approve(
        address token,
        address spender,
        uint160 amount,
        uint48 expiration
    ) external;

    /// @notice Permit a spender to a given amount of the owners token via the owner's EIP-712 signature
    /// @dev May fail if the owner's nonce was invalidated in-flight by invalidateNonce
    /// @param owner The owner of the tokens being approved
    /// @param permitSingle Data signed over by the owner specifying the terms of approval
    /// @param signature The owner's signature over the permit data
    function permit(
        address owner,
        PermitSingle memory permitSingle,
        bytes calldata signature
    ) external;

    /// @notice Permit a spender to the signed amounts of the owners tokens via the owner's EIP-712 signature
    /// @dev May fail if the owner's nonce was invalidated in-flight by invalidateNonce
    /// @param owner The owner of the tokens being approved
    /// @param permitBatch Data signed over by the owner specifying the terms of approval
    /// @param signature The owner's signature over the permit data
    function permit(
        address owner,
        PermitBatch memory permitBatch,
        bytes calldata signature
    ) external;

    /// @notice Transfer approved tokens from one address to another
    /// @param from The address to transfer from
    /// @param to The address of the recipient
    /// @param amount The amount of the token to transfer
    /// @param token The token address to transfer
    /// @dev Requires the from address to have approved at least the desired amount
    /// of tokens to msg.sender.
    function transferFrom(
        address from,
        address to,
        uint160 amount,
        address token
    ) external;

    /// @notice Transfer approved tokens in a batch
    /// @param transferDetails Array of owners, recipients, amounts, and tokens for the transfers
    /// @dev Requires the from addresses to have approved at least the desired amount
    /// of tokens to msg.sender.
    function transferFrom(
        AllowanceTransferDetails[] calldata transferDetails
    ) external;

    /// @notice Enables performing a "lockdown" of the sender's Permit2 identity
    /// by batch revoking approvals
    /// @param approvals Array of approvals to revoke.
    function lockdown(TokenSpenderPair[] calldata approvals) external;

    /// @notice Invalidate nonces for a given (token, spender) pair
    /// @param token The token to invalidate nonces for
    /// @param spender The spender to invalidate nonces for
    /// @param newNonce The new nonce to set. Invalidates all nonces less than it.
    /// @dev Can't invalidate more than 2**16 nonces per transaction.
    function invalidateNonces(
        address token,
        address spender,
        uint48 newNonce
    ) external;
}

File 3 of 18 : IEIP712.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

interface IEIP712 {
    function DOMAIN_SEPARATOR() external view returns (bytes32);
}

File 4 of 18 : IPermit2.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {ISignatureTransfer} from "./ISignatureTransfer.sol";
import {IAllowanceTransfer} from "./IAllowanceTransfer.sol";

/// @notice Permit2 handles signature-based transfers in SignatureTransfer and allowance-based transfers in AllowanceTransfer.
/// @dev Users must approve Permit2 before calling any of the transfer functions.
interface IPermit2 is ISignatureTransfer, IAllowanceTransfer {
    // IPermit2 unifies the two interfaces so users have maximal flexibility with their approval.
}

File 5 of 18 : ISignatureTransfer.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

import {IEIP712} from "./IEIP712.sol";

/// @title SignatureTransfer
/// @notice Handles ERC20 token transfers through signature based actions
/// @dev Requires user's token approval on the Permit2 contract
interface ISignatureTransfer is IEIP712 {
    /// @notice Thrown when the requested amount for a transfer is larger than the permissioned amount
    /// @param maxAmount The maximum amount a spender can request to transfer
    error InvalidAmount(uint256 maxAmount);

    /// @notice Thrown when the number of tokens permissioned to a spender does not match the number of tokens being transferred
    /// @dev If the spender does not need to transfer the number of tokens permitted, the spender can request amount 0 to be transferred
    error LengthMismatch();

    /// @notice Emits an event when the owner successfully invalidates an unordered nonce.
    event UnorderedNonceInvalidation(
        address indexed owner,
        uint256 word,
        uint256 mask
    );

    /// @notice The token and amount details for a transfer signed in the permit transfer signature
    struct TokenPermissions {
        // ERC20 token address
        address token;
        // the maximum amount that can be spent
        uint256 amount;
    }

    /// @notice The signed permit message for a single token transfer
    struct PermitTransferFrom {
        TokenPermissions permitted;
        // a unique value for every token owner's signature to prevent signature replays
        uint256 nonce;
        // deadline on the permit signature
        uint256 deadline;
    }

    /// @notice Specifies the recipient address and amount for batched transfers.
    /// @dev Recipients and amounts correspond to the index of the signed token permissions array.
    /// @dev Reverts if the requested amount is greater than the permitted signed amount.
    struct SignatureTransferDetails {
        // recipient address
        address to;
        // spender requested amount
        uint256 requestedAmount;
    }

    /// @notice Used to reconstruct the signed permit message for multiple token transfers
    /// @dev Do not need to pass in spender address as it is required that it is msg.sender
    /// @dev Note that a user still signs over a spender address
    struct PermitBatchTransferFrom {
        // the tokens and corresponding amounts permitted for a transfer
        TokenPermissions[] permitted;
        // a unique value for every token owner's signature to prevent signature replays
        uint256 nonce;
        // deadline on the permit signature
        uint256 deadline;
    }

    /// @notice A map from token owner address and a caller specified word index to a bitmap. Used to set bits in the bitmap to prevent against signature replay protection
    /// @dev Uses unordered nonces so that permit messages do not need to be spent in a certain order
    /// @dev The mapping is indexed first by the token owner, then by an index specified in the nonce
    /// @dev It returns a uint256 bitmap
    /// @dev The index, or wordPosition is capped at type(uint248).max
    function nonceBitmap(address, uint256) external view returns (uint256);

    /// @notice Transfers a token using a signed permit message
    /// @dev Reverts if the requested amount is greater than the permitted signed amount
    /// @param permit The permit data signed over by the owner
    /// @param owner The owner of the tokens to transfer
    /// @param transferDetails The spender's requested transfer details for the permitted token
    /// @param signature The signature to verify
    function permitTransferFrom(
        PermitTransferFrom memory permit,
        SignatureTransferDetails calldata transferDetails,
        address owner,
        bytes calldata signature
    ) external;

    /// @notice Transfers a token using a signed permit message
    /// @notice Includes extra data provided by the caller to verify signature over
    /// @dev The witness type string must follow EIP712 ordering of nested structs and must include the TokenPermissions type definition
    /// @dev Reverts if the requested amount is greater than the permitted signed amount
    /// @param permit The permit data signed over by the owner
    /// @param owner The owner of the tokens to transfer
    /// @param transferDetails The spender's requested transfer details for the permitted token
    /// @param witness Extra data to include when checking the user signature
    /// @param witnessTypeString The EIP-712 type definition for remaining string stub of the typehash
    /// @param signature The signature to verify
    function permitWitnessTransferFrom(
        PermitTransferFrom memory permit,
        SignatureTransferDetails calldata transferDetails,
        address owner,
        bytes32 witness,
        string calldata witnessTypeString,
        bytes calldata signature
    ) external;

    /// @notice Transfers multiple tokens using a signed permit message
    /// @param permit The permit data signed over by the owner
    /// @param owner The owner of the tokens to transfer
    /// @param transferDetails Specifies the recipient and requested amount for the token transfer
    /// @param signature The signature to verify
    function permitTransferFrom(
        PermitBatchTransferFrom memory permit,
        SignatureTransferDetails[] calldata transferDetails,
        address owner,
        bytes calldata signature
    ) external;

    /// @notice Transfers multiple tokens using a signed permit message
    /// @dev The witness type string must follow EIP712 ordering of nested structs and must include the TokenPermissions type definition
    /// @notice Includes extra data provided by the caller to verify signature over
    /// @param permit The permit data signed over by the owner
    /// @param owner The owner of the tokens to transfer
    /// @param transferDetails Specifies the recipient and requested amount for the token transfer
    /// @param witness Extra data to include when checking the user signature
    /// @param witnessTypeString The EIP-712 type definition for remaining string stub of the typehash
    /// @param signature The signature to verify
    function permitWitnessTransferFrom(
        PermitBatchTransferFrom memory permit,
        SignatureTransferDetails[] calldata transferDetails,
        address owner,
        bytes32 witness,
        string calldata witnessTypeString,
        bytes calldata signature
    ) external;

    /// @notice Invalidates the bits specified in mask for the bitmap at the word position
    /// @dev The wordPos is maxed at type(uint248).max
    /// @param wordPos A number to index the nonceBitmap at
    /// @param mask A bitmap masked against msg.sender's current bitmap at the word position
    function invalidateUnorderedNonces(uint256 wordPos, uint256 mask) external;
}

File 6 of 18 : ERC20.sol
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;

/// @notice Modern and gas efficient ERC20 + EIP-2612 implementation.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/ERC20.sol)
/// @author Modified from Uniswap (https://github.com/Uniswap/uniswap-v2-core/blob/master/contracts/UniswapV2ERC20.sol)
/// @dev Do not manually set balances without updating totalSupply, as the sum of all user balances must not exceed it.
abstract contract ERC20 {
    /*//////////////////////////////////////////////////////////////
                                 EVENTS
    //////////////////////////////////////////////////////////////*/

    event Transfer(address indexed from, address indexed to, uint256 amount);

    event Approval(address indexed owner, address indexed spender, uint256 amount);

    /*//////////////////////////////////////////////////////////////
                            METADATA STORAGE
    //////////////////////////////////////////////////////////////*/

    string public name;

    string public symbol;

    uint8 public immutable decimals;

    /*//////////////////////////////////////////////////////////////
                              ERC20 STORAGE
    //////////////////////////////////////////////////////////////*/

    uint256 public totalSupply;

    mapping(address => uint256) public balanceOf;

    mapping(address => mapping(address => uint256)) public allowance;

    /*//////////////////////////////////////////////////////////////
                            EIP-2612 STORAGE
    //////////////////////////////////////////////////////////////*/

    uint256 internal immutable INITIAL_CHAIN_ID;

    bytes32 internal immutable INITIAL_DOMAIN_SEPARATOR;

    mapping(address => uint256) public nonces;

    /*//////////////////////////////////////////////////////////////
                               CONSTRUCTOR
    //////////////////////////////////////////////////////////////*/

    constructor(string memory _name, string memory _symbol, uint8 _decimals) {
        name = _name;
        symbol = _symbol;
        decimals = _decimals;

        INITIAL_CHAIN_ID = block.chainid;
        INITIAL_DOMAIN_SEPARATOR = computeDomainSeparator();
    }

    /*//////////////////////////////////////////////////////////////
                               ERC20 LOGIC
    //////////////////////////////////////////////////////////////*/

    function approve(address spender, uint256 amount) public virtual returns (bool) {
        allowance[msg.sender][spender] = amount;

        emit Approval(msg.sender, spender, amount);

        return true;
    }

    function transfer(address to, uint256 amount) public virtual returns (bool) {
        balanceOf[msg.sender] -= amount;

        // Cannot overflow because the sum of all user
        // balances can't exceed the max uint256 value.
        unchecked {
            balanceOf[to] += amount;
        }

        emit Transfer(msg.sender, to, amount);

        return true;
    }

    function transferFrom(address from, address to, uint256 amount) public virtual returns (bool) {
        uint256 allowed = allowance[from][msg.sender]; // Saves gas for limited approvals.

        if (allowed != type(uint256).max) allowance[from][msg.sender] = allowed - amount;

        balanceOf[from] -= amount;

        // Cannot overflow because the sum of all user
        // balances can't exceed the max uint256 value.
        unchecked {
            balanceOf[to] += amount;
        }

        emit Transfer(from, to, amount);

        return true;
    }

    /*//////////////////////////////////////////////////////////////
                             EIP-2612 LOGIC
    //////////////////////////////////////////////////////////////*/

    function permit(
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) public virtual {
        require(deadline >= block.timestamp, "PERMIT_DEADLINE_EXPIRED");

        // Unchecked because the only math done is incrementing
        // the owner's nonce which cannot realistically overflow.
        unchecked {
            address recoveredAddress = ecrecover(
                keccak256(
                    abi.encodePacked(
                        "\x19\x01",
                        DOMAIN_SEPARATOR(),
                        keccak256(
                            abi.encode(
                                keccak256(
                                    "Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"
                                ),
                                owner,
                                spender,
                                value,
                                nonces[owner]++,
                                deadline
                            )
                        )
                    )
                ),
                v,
                r,
                s
            );

            require(recoveredAddress != address(0) && recoveredAddress == owner, "INVALID_SIGNER");

            allowance[recoveredAddress][spender] = value;
        }

        emit Approval(owner, spender, value);
    }

    function DOMAIN_SEPARATOR() public view virtual returns (bytes32) {
        return block.chainid == INITIAL_CHAIN_ID ? INITIAL_DOMAIN_SEPARATOR : computeDomainSeparator();
    }

    function computeDomainSeparator() internal view virtual returns (bytes32) {
        return
            keccak256(
                abi.encode(
                    keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"),
                    keccak256(bytes(name)),
                    keccak256("1"),
                    block.chainid,
                    address(this)
                )
            );
    }

    /*//////////////////////////////////////////////////////////////
                        INTERNAL MINT/BURN LOGIC
    //////////////////////////////////////////////////////////////*/

    function _mint(address to, uint256 amount) internal virtual {
        totalSupply += amount;

        // Cannot overflow because the sum of all user
        // balances can't exceed the max uint256 value.
        unchecked {
            balanceOf[to] += amount;
        }

        emit Transfer(address(0), to, amount);
    }

    function _burn(address from, uint256 amount) internal virtual {
        balanceOf[from] -= amount;

        // Cannot underflow because a user's balance
        // will never be larger than the total supply.
        unchecked {
            totalSupply -= amount;
        }

        emit Transfer(from, address(0), amount);
    }
}

File 7 of 18 : WETH.sol
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;

import {ERC20} from "./ERC20.sol";

import {SafeTransferLib} from "../utils/SafeTransferLib.sol";

/// @notice Minimalist and modern Wrapped Ether implementation.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/tokens/WETH.sol)
/// @author Inspired by WETH9 (https://github.com/dapphub/ds-weth/blob/master/src/weth9.sol)
contract WETH is ERC20("Wrapped Ether", "WETH", 18) {
    using SafeTransferLib for address;

    event Deposit(address indexed from, uint256 amount);

    event Withdrawal(address indexed to, uint256 amount);

    function deposit() public payable virtual {
        _mint(msg.sender, msg.value);

        emit Deposit(msg.sender, msg.value);
    }

    function withdraw(uint256 amount) public virtual {
        _burn(msg.sender, amount);

        emit Withdrawal(msg.sender, amount);

        msg.sender.safeTransferETH(amount);
    }

    receive() external payable virtual {
        deposit();
    }
}

File 8 of 18 : SafeTransferLib.sol
// SPDX-License-Identifier: AGPL-3.0-only
pragma solidity >=0.8.0;

import {ERC20} from "../tokens/ERC20.sol";

/// @notice Safe ETH and ERC20 transfer library that gracefully handles missing return values.
/// @author Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/SafeTransferLib.sol)
/// @dev Use with caution! Some functions in this library knowingly create dirty bits at the destination of the free memory pointer.
/// @dev Note that none of the functions in this library check that a token has code at all! That responsibility is delegated to the caller.
library SafeTransferLib {
    /*//////////////////////////////////////////////////////////////
                             ETH OPERATIONS
    //////////////////////////////////////////////////////////////*/

    function safeTransferETH(address to, uint256 amount) internal {
        bool success;

        /// @solidity memory-safe-assembly
        assembly {
            // Transfer the ETH and store if it succeeded or not.
            success := call(gas(), to, amount, 0, 0, 0, 0)
        }

        require(success, "ETH_TRANSFER_FAILED");
    }

    /*//////////////////////////////////////////////////////////////
                            ERC20 OPERATIONS
    //////////////////////////////////////////////////////////////*/

    function safeTransferFrom(ERC20 token, address from, address to, uint256 amount) internal {
        bool success;

        /// @solidity memory-safe-assembly
        assembly {
            // Get a pointer to some free memory.
            let freeMemoryPointer := mload(0x40)

            // Write the abi-encoded calldata into memory, beginning with the function selector.
            mstore(freeMemoryPointer, 0x23b872dd00000000000000000000000000000000000000000000000000000000)
            mstore(add(freeMemoryPointer, 4), and(from, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the "from" argument.
            mstore(add(freeMemoryPointer, 36), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the "to" argument.
            mstore(add(freeMemoryPointer, 68), amount) // Append the "amount" argument. Masking not required as it's a full 32 byte type.

            success := and(
                // Set success to whether the call reverted, if not we check it either
                // returned exactly 1 (can't just be non-zero data), or had no return data.
                or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
                // We use 100 because the length of our calldata totals up like so: 4 + 32 * 3.
                // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.
                // Counterintuitively, this call must be positioned second to the or() call in the
                // surrounding and() call or else returndatasize() will be zero during the computation.
                call(gas(), token, 0, freeMemoryPointer, 100, 0, 32)
            )
        }

        require(success, "TRANSFER_FROM_FAILED");
    }

    function safeTransfer(ERC20 token, address to, uint256 amount) internal {
        bool success;

        /// @solidity memory-safe-assembly
        assembly {
            // Get a pointer to some free memory.
            let freeMemoryPointer := mload(0x40)

            // Write the abi-encoded calldata into memory, beginning with the function selector.
            mstore(freeMemoryPointer, 0xa9059cbb00000000000000000000000000000000000000000000000000000000)
            mstore(add(freeMemoryPointer, 4), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the "to" argument.
            mstore(add(freeMemoryPointer, 36), amount) // Append the "amount" argument. Masking not required as it's a full 32 byte type.

            success := and(
                // Set success to whether the call reverted, if not we check it either
                // returned exactly 1 (can't just be non-zero data), or had no return data.
                or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
                // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2.
                // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.
                // Counterintuitively, this call must be positioned second to the or() call in the
                // surrounding and() call or else returndatasize() will be zero during the computation.
                call(gas(), token, 0, freeMemoryPointer, 68, 0, 32)
            )
        }

        require(success, "TRANSFER_FAILED");
    }

    function safeApprove(ERC20 token, address to, uint256 amount) internal {
        bool success;

        /// @solidity memory-safe-assembly
        assembly {
            // Get a pointer to some free memory.
            let freeMemoryPointer := mload(0x40)

            // Write the abi-encoded calldata into memory, beginning with the function selector.
            mstore(freeMemoryPointer, 0x095ea7b300000000000000000000000000000000000000000000000000000000)
            mstore(add(freeMemoryPointer, 4), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the "to" argument.
            mstore(add(freeMemoryPointer, 36), amount) // Append the "amount" argument. Masking not required as it's a full 32 byte type.

            success := and(
                // Set success to whether the call reverted, if not we check it either
                // returned exactly 1 (can't just be non-zero data), or had no return data.
                or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
                // We use 68 because the length of our calldata totals up like so: 4 + 32 * 2.
                // We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.
                // Counterintuitively, this call must be positioned second to the or() call in the
                // surrounding and() call or else returndatasize() will be zero during the computation.
                call(gas(), token, 0, freeMemoryPointer, 68, 0, 32)
            )
        }

        require(success, "APPROVE_FAILED");
    }
}

File 9 of 18 : BungeeErrors.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

//

error MofaSignatureInvalid();
error InsufficientNativeAmount();
error InvalidMultipleNativeTokens();

error FulfilmentChainInvalid();
error RequestAlreadyFulfilled();
error RouterNotRegistered();

error TransferFailed();
error CallerNotBungeeGateway();

error NoExecutionCacheFound();
error ExecutionCacheFailed();
error SwapOutputInsufficient();

error UnsupportedDestinationChainId();

error MinOutputNotMet();

error OnlyOwner();
error OnlyNominee();

error InvalidRequest();
error FulfilmentDeadlineNotMet();
error CallerNotDelegate();

error BungeeSiblingDoesNotExist();
error InvalidMsg();

error NotDelegate();
error RequestProcessed();
error RequestNotProcessed();

error InvalidSwitchboard();
error PromisedAmountNotMet();

error MsgReceiveFailed();

error RouterAlreadyWhitelisted();
error InvalidStake();
error RouterAlreadyRegistered();

error InvalidFulfil();

error InsufficientCapacity();

error ReleaseFundsNotImplemented();

File 10 of 18 : InboxErrors.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.17;

/// @dev reverts with error when chainId does not match block.chainid
error InvalidChainId();

/// @dev reverts with error if the msg.value and Request inputAmount do not match
error InvalidMsgValue();

/// @dev reverts with error if the nonce has already been used
error InvalidNonce();

///@dev reverts with error if native / ERC-20 transfer fails
error TransferFailed();

/// @dev reverts with error if Request does not exist on the Inbox contract
error RequestDoesNotExist();

/// @dev reverts with error if Request has already been withdrawn by the user post-extraction
error RequestAlreadyWithdraw();

/// @dev reverts with error if Request has already been extracted
error RequestAlreadyFulfilled();

File 11 of 18 : InboxEvents.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

contract InboxEvents {
    /// @notice Emitted when the user creates a Request on the Refuel Inbox
    /// @param requestHash Hash of the request
    /// @param ogSender Address of the user who created the request
    /// @param request Encoded Request details
    event RefuelRequestCreated(bytes32 indexed requestHash, address ogSender, bytes request);

    /// @notice Emitted when the user withdraws a Request
    /// @param requestHash Hash of the request
    event RefuelRequestWithdrawn(bytes32 indexed requestHash);
}

contract SwapRequestInboxEvents {
    /// @notice Emitted when the user creates a Swap Request on the Refuel Inbox
    /// @param requestHash Hash of the request
    /// @param ogSender Address of the user who created the request
    /// @param request Encoded Request details
    event SwapRequestCreated(bytes32 indexed requestHash, address ogSender, bytes request);

    /// @notice Emitted when the user withdraws a Swap Request
    /// @param requestHash Hash of the request
    event SwapRequestWithdrawn(bytes32 indexed requestHash);
}

File 12 of 18 : SingleOutputStructs.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.17;

// Basic details in the request
struct BasicRequest {
    // src chain id
    uint256 originChainId;
    // dest chain id
    uint256 destinationChainId;
    // deadline of the request
    uint256 deadline;
    // nonce used for uniqueness in signature
    uint256 nonce;
    // address of the user placing the request.
    address sender;
    // address of the receiver on destination chain
    address receiver;
    // delegate address that has some rights over the request signed
    address delegate;
    // address of bungee gateway, this address will have access to pull funds from the sender.
    address bungeeGateway;
    // id of the switchboard
    uint32 switchboardId;
    // address of the input token
    address inputToken;
    // amount of the input tokens
    uint256 inputAmount;
    // output token to be received on the destination.
    address outputToken;
    // minimum amount to be receive on the destination for the output token.
    uint256 minOutputAmount;
    // native token refuel amount on the destination chain
    uint256 refuelAmount;
}

// The Request which user signs
struct Request {
    // basic details in the request.
    BasicRequest basicReq;
    // swap output token that the user is okay with swapping input token to.
    address swapOutputToken;
    // minimum swap output the user is okay with swapping the input token to.
    // Transmitter can choose or not choose to swap tokens.
    uint256 minSwapOutput;
    // any sort of metadata to be passed with the request
    bytes32 metadata;
    // fees of the affiliate if any
    bytes affiliateFees;
}

// Transmitter's origin chain execution details for a request with promisedAmounts.
struct ExtractExec {
    // User signed Request
    Request request;
    // address of the router being used for the request.
    address router;
    // promised amount for output token on the destination
    uint256 promisedAmount;
    // promised amount for native token refuel on the destination
    uint256 promisedRefuelAmount;
    // RouterPayload (router specific data) + RouterValue (value required by the router) etc etc
    bytes routerData;
    // swapPayload 0x00 if no swap is involved.
    bytes swapPayload;
    // swapRouterAddress
    address swapRouter;
    // user signature against the request
    bytes userSignature;
    // address of the beneficiary submitted by the transmitter.
    // the beneficiary will be the one receiving locked tokens when a request is settled.
    address beneficiary;
}

// Transmitter's destination chain execution details with fulfil amounts.
struct FulfilExec {
    // User Signed Request
    Request request;
    // address of the router
    address fulfilRouter;
    // amount to be sent to the receiver for output token.
    uint256 fulfilAmount;
    // amount to be sent to the receiver for native token refuel.
    uint256 refuelFulfilAmount;
    // extraPayload for router.
    bytes routerData;
    // total msg.value to be sent to fulfil native token output token
    uint256 msgValue;
}

struct ExtractedRequest {
    uint256 expiry;
    address router;
    address sender;
    address delegate;
    uint32 switchboardId;
    address token;
    address transmitter; // For stake capacity
    address beneficiary; // For Transmitter
    uint256 amount;
    uint256 promisedAmount; // For Transmitter
    uint256 promisedRefuelAmount;
    bytes affiliateFees; // For integrator
}

struct FulfilledRequest {
    uint256 fulfilledAmount;
    uint256 fulfilledRefuelAmount;
    bool processed;
}

File 13 of 18 : IBungeeGateway.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.17;

interface IBungeeGateway {
    function setWhitelistedReceiver(address receiver, uint256 destinationChainId, address router) external;

    function getWhitelistedReceiver(address router, uint256 destinationChainId) external view returns (address);

    function inboundMsgFromSwitchboard(uint8 msgId, uint32 switchboardId, bytes calldata payload) external;

    function isBungeeRouter(address router) external view returns (bool);

    function withdrawnRequests(bytes32 requestHash) external view returns (bool);

    function withdrawRequestOnOrigin(bytes32 requestHash) external;

    function executeSOR(bytes calldata data) external payable returns (bytes memory);
}

File 14 of 18 : ISingleOutputRequestImpl.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.17;

interface ISingleOutputRequestImpl {
    function withdrawRequestOnOrigin(bytes32 requestHash) external;
}

File 15 of 18 : Permit2HashHelper.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.17;

import {IPermit2} from "permit2/src/interfaces/IPermit2.sol";
import {ISignatureTransfer} from "permit2/src/interfaces/ISignatureTransfer.sol";

/// @title Permit2HashHelper
/// @notice Helper library to generate the WitnessHash used by Permit2
/// @dev We receive hashTypedData from Permit2 in isValidSignature function, used to verify the Commande details.
/// @dev This lib helps generate the witness hash which is used to create the hashTypedData
/// @dev reference : https://github.com/Uniswap/permit2/blob/cc56ad0f3439c502c246fc5cfcc3db92bb8b7219/src/libraries/PermitHash.sol#L85
/// @dev reference : https://github.com/Uniswap/permit2/blob/cc56ad0f3439c502c246fc5cfcc3db92bb8b7219/src/EIP712.sol#L38
library Permit2HashHelper {
    string public constant _PERMIT_TRANSFER_FROM_WITNESS_TYPEHASH_STUB =
        "PermitWitnessTransferFrom(TokenPermissions permitted,address spender,uint256 nonce,uint256 deadline,";

    bytes32 public constant _TOKEN_PERMISSIONS_TYPEHASH = keccak256("TokenPermissions(address token,uint256 amount)");

    function returnHashWithWitness(
        address token,
        uint256 amount,
        uint256 nonce,
        uint256 deadline,
        bytes32 commandHash,
        string memory witnessTypeString,
        address bungeeGateway
    ) internal pure returns (bytes32) {
        ISignatureTransfer.TokenPermissions memory tokenPermissions = ISignatureTransfer.TokenPermissions(
            token,
            amount
        );
        ISignatureTransfer.PermitTransferFrom memory permit = ISignatureTransfer.PermitTransferFrom(
            tokenPermissions,
            nonce,
            deadline
        );
        return hashWithWitness(permit, commandHash, witnessTypeString, bungeeGateway);
    }

    function hashWithWitness(
        ISignatureTransfer.PermitTransferFrom memory permit,
        bytes32 witness,
        string memory witnessTypeString,
        address bungeeGateway
    ) internal pure returns (bytes32) {
        bytes32 typeHash = keccak256(abi.encodePacked(_PERMIT_TRANSFER_FROM_WITNESS_TYPEHASH_STUB, witnessTypeString));

        bytes32 tokenPermissionsHash = _hashTokenPermissions(permit.permitted);
        return
            keccak256(
                abi.encode(typeHash, tokenPermissionsHash, bungeeGateway, permit.nonce, permit.deadline, witness)
            );
    }

    function _hashTokenPermissions(
        ISignatureTransfer.TokenPermissions memory permitted
    ) private pure returns (bytes32) {
        return keccak256(abi.encode(_TOKEN_PERMISSIONS_TYPEHASH, permitted));
    }

    /// @notice Creates an EIP-712 typed data hash
    function _hashTypedData(address permit2, bytes32 dataHash) internal view returns (bytes32) {
        return keccak256(abi.encodePacked("\x19\x01", IPermit2(permit2).DOMAIN_SEPARATOR(), dataHash));
    }
}

File 16 of 18 : Permit2Lib.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.17;
import {ISignatureTransfer} from "permit2/src/interfaces/ISignatureTransfer.sol";

// Library to get Permit 2 related data.
library Permit2Lib {
    string public constant TOKEN_PERMISSIONS_TYPE = "TokenPermissions(address token,uint256 amount)";

    function toPermit(
        address inputToken,
        uint256 inputAmount,
        uint256 nonce,
        uint256 deadline
    ) internal pure returns (ISignatureTransfer.PermitTransferFrom memory) {
        return
            ISignatureTransfer.PermitTransferFrom({
                permitted: ISignatureTransfer.TokenPermissions({token: inputToken, amount: inputAmount}),
                nonce: nonce,
                deadline: deadline
            });
    }

    function transferDetails(
        uint256 amount,
        address spender
    ) internal pure returns (ISignatureTransfer.SignatureTransferDetails memory) {
        return ISignatureTransfer.SignatureTransferDetails({to: spender, requestedAmount: amount});
    }
}

File 17 of 18 : SingleOutputRequestLib.sol
// SPDX-License-Identifier: GPL-3.0-only
pragma solidity ^0.8.17;

import {BasicRequest, Request, ExtractExec} from "../common/SingleOutputStructs.sol";
import {Permit2Lib} from "./Permit2Lib.sol";

/// @notice helpers for handling BasicRequest
library BasicRequestLib {
    bytes internal constant BASIC_REQUEST_TYPE =
        abi.encodePacked(
            "BasicRequest(",
            "uint256 originChainId,",
            "uint256 destinationChainId,",
            "uint256 deadline,",
            "uint256 nonce,",
            "address sender,",
            "address receiver,",
            "address delegate,",
            "address bungeeGateway,",
            "uint32 switchboardId,",
            "address inputToken,",
            "uint256 inputAmount,",
            "address outputToken,",
            "uint256 minOutputAmount,"
            "uint256 refuelAmount)"
        );
    bytes32 internal constant BASIC_REQUEST_TYPE_HASH = keccak256(BASIC_REQUEST_TYPE);

    /// @notice Hash of BasicRequest struct on the origin chain
    /// @dev enforces originChainId to be the current chainId. Resulting hash would be the same on all chains.
    /// @dev helps avoid extra checking of chainId in the contract
    /// @param basicReq BasicRequest object to be hashed
    function originHash(BasicRequest memory basicReq) internal view returns (bytes32) {
        return
            keccak256(
                abi.encodePacked(
                    BASIC_REQUEST_TYPE_HASH,
                    abi.encode(
                        block.chainid,
                        basicReq.destinationChainId,
                        basicReq.deadline,
                        basicReq.nonce,
                        basicReq.sender,
                        basicReq.receiver,
                        basicReq.delegate,
                        basicReq.bungeeGateway,
                        basicReq.switchboardId,
                        basicReq.inputToken,
                        basicReq.inputAmount,
                        basicReq.outputToken,
                        basicReq.minOutputAmount,
                        basicReq.refuelAmount
                    )
                )
            );
    }

    /// @notice Hash of BasicRequest struct on the destination chain
    /// @dev enforces destinationChain to be the current chainId. Resulting hash would be the same on all chains.
    /// @dev helps avoid extra checking of chainId in the contract
    /// @param basicReq BasicRequest object to be hashed
    function destinationHash(BasicRequest memory basicReq) internal view returns (bytes32) {
        return
            keccak256(
                abi.encodePacked(
                    BASIC_REQUEST_TYPE_HASH,
                    abi.encode(
                        basicReq.originChainId,
                        block.chainid,
                        basicReq.deadline,
                        basicReq.nonce,
                        basicReq.sender,
                        basicReq.receiver,
                        basicReq.delegate,
                        basicReq.bungeeGateway,
                        basicReq.switchboardId,
                        basicReq.inputToken,
                        basicReq.inputAmount,
                        basicReq.outputToken,
                        basicReq.minOutputAmount,
                        basicReq.refuelAmount
                    )
                )
            );
    }
}

/// @title Bungee Request Library.
/// @author bungee protocol
/// @notice This library is responsible for all the hashing related to Request object.
library RequestLib {
    using BasicRequestLib for BasicRequest;

    // Permit 2 Witness Order Type.
    string internal constant PERMIT2_ORDER_TYPE =
        string(
            abi.encodePacked(
                "Request witness)",
                abi.encodePacked(BasicRequestLib.BASIC_REQUEST_TYPE, REQUEST_TYPE),
                Permit2Lib.TOKEN_PERMISSIONS_TYPE
            )
        );

    // REQUEST TYPE encode packed
    bytes internal constant REQUEST_TYPE =
        abi.encodePacked(
            "Request(",
            "BasicRequest basicReq,",
            "address swapOutputToken,",
            "uint256 minSwapOutput,",
            "bytes32 metadata,",
            "bytes affiliateFees)"
        );

    // EXTRACT EXEC TYPE.
    bytes internal constant EXTRACT_EXEC_TYPE =
        abi.encodePacked(
            "ExtractExec(",
            "Request request,",
            "address router,",
            "uint256 promisedAmount,",
            "uint256 promisedRefuelAmount,",
            "bytes routerData,",
            "bytes swapPayload,",
            "address swapRouter,",
            "bytes userSignature,",
            "address beneficiary)"
        );

    // BUNGEE_REQUEST_TYPE
    bytes internal constant BUNGEE_REQUEST_TYPE = abi.encodePacked(REQUEST_TYPE, BasicRequestLib.BASIC_REQUEST_TYPE);

    // Keccak Hash of BUNGEE_REQUEST_TYPE
    bytes32 internal constant BUNGEE_REQUEST_TYPE_HASH = keccak256(BUNGEE_REQUEST_TYPE);

    // Exec Type.
    bytes internal constant EXEC_TYPE = abi.encodePacked(EXTRACT_EXEC_TYPE, REQUEST_TYPE);

    // Keccak Hash of Exec Type.
    bytes32 internal constant EXTRACT_EXEC_TYPE_HASH = keccak256(EXEC_TYPE);

    /// @notice Hash of request on the origin chain
    /// @param request request that is signe by the user
    function hashOriginRequest(Request memory request) internal view returns (bytes32) {
        return
            keccak256(
                abi.encode(
                    BUNGEE_REQUEST_TYPE_HASH,
                    request.basicReq.originHash(),
                    request.swapOutputToken,
                    request.minSwapOutput,
                    request.metadata,
                    keccak256(request.affiliateFees)
                )
            );
    }

    /// @notice Hash of request on the destination chain
    /// @param request request signed by the user
    function hashDestinationRequest(Request memory request) internal view returns (bytes32) {
        return
            keccak256(
                abi.encode(
                    BUNGEE_REQUEST_TYPE_HASH,
                    request.basicReq.destinationHash(),
                    request.swapOutputToken,
                    request.minSwapOutput,
                    request.metadata,
                    keccak256(request.affiliateFees)
                )
            );
    }

    /// @notice Hash of Extract Exec on the origin chain
    /// @param execution Transmitter submitted extract exec object
    function hashOriginExtractExec(ExtractExec memory execution) internal view returns (bytes32) {
        return
            keccak256(
                abi.encode(
                    EXTRACT_EXEC_TYPE_HASH,
                    hashOriginRequest(execution.request),
                    execution.router,
                    execution.promisedAmount,
                    execution.promisedRefuelAmount,
                    keccak256(execution.routerData),
                    keccak256(execution.swapPayload),
                    execution.swapRouter,
                    keccak256(execution.userSignature),
                    execution.beneficiary
                )
            );
    }

    /// @notice hash a batch of extract execs
    /// @param extractExecs batch of extract execs to be hashed
    function hashOriginBatch(ExtractExec[] memory extractExecs) internal view returns (bytes32) {
        unchecked {
            bytes32 outputHash = keccak256("BUNGEE_EXTRACT_EXEC");
            // Hash all of the extract execs present in the batch.
            for (uint256 i = 0; i < extractExecs.length; i++) {
                outputHash = keccak256(abi.encode(outputHash, hashOriginExtractExec(extractExecs[i])));
            }

            return outputHash;
        }
    }
}

File 18 of 18 : Ownable.sol
// SPDX-License-Identifier: GPL-3.0-only
pragma solidity ^0.8.17;

import {OnlyOwner, OnlyNominee} from "../common/BungeeErrors.sol";

abstract contract Ownable {
    address private _owner;
    address private _nominee;

    event OwnerNominated(address indexed nominee);
    event OwnerClaimed(address indexed claimer);

    constructor(address owner_) {
        _claimOwner(owner_);
    }

    modifier onlyOwner() {
        if (msg.sender != _owner) {
            revert OnlyOwner();
        }
        _;
    }

    function owner() public view returns (address) {
        return _owner;
    }

    function nominee() public view returns (address) {
        return _nominee;
    }

    function nominateOwner(address nominee_) external {
        if (msg.sender != _owner) {
            revert OnlyOwner();
        }
        _nominee = nominee_;
        emit OwnerNominated(_nominee);
    }

    function claimOwner() external {
        if (msg.sender != _nominee) {
            revert OnlyNominee();
        }
        _claimOwner(msg.sender);
    }

    function _claimOwner(address claimer_) internal {
        _owner = claimer_;
        _nominee = address(0);
        emit OwnerClaimed(claimer_);
    }
}

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

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"address","name":"_owner","type":"address"},{"internalType":"address","name":"_permit2","type":"address"},{"internalType":"address","name":"_bungeeGateway","type":"address"},{"internalType":"address payable","name":"_wrappedNativeToken","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"InvalidChainId","type":"error"},{"inputs":[],"name":"InvalidMsgValue","type":"error"},{"inputs":[],"name":"InvalidNonce","type":"error"},{"inputs":[],"name":"OnlyNominee","type":"error"},{"inputs":[],"name":"OnlyOwner","type":"error"},{"inputs":[],"name":"RequestAlreadyWithdraw","type":"error"},{"inputs":[],"name":"RequestDoesNotExist","type":"error"},{"inputs":[],"name":"TransferFailed","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"claimer","type":"address"}],"name":"OwnerClaimed","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"nominee","type":"address"}],"name":"OwnerNominated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"requestHash","type":"bytes32"},{"indexed":false,"internalType":"address","name":"ogSender","type":"address"},{"indexed":false,"internalType":"bytes","name":"request","type":"bytes"}],"name":"RefuelRequestCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"requestHash","type":"bytes32"}],"name":"RefuelRequestWithdrawn","type":"event"},{"inputs":[],"name":"BUNGEE_GATEWAY","outputs":[{"internalType":"contract IBungeeGateway","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"NATIVE_TOKEN_ADDRESS","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PERMIT2","outputs":[{"internalType":"contract IPermit2","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"WRAPPED_NATIVE_TOKEN","outputs":[{"internalType":"contract WETH","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"claimOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"uint256","name":"originChainId","type":"uint256"},{"internalType":"uint256","name":"destinationChainId","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"delegate","type":"address"},{"internalType":"address","name":"bungeeGateway","type":"address"},{"internalType":"uint32","name":"switchboardId","type":"uint32"},{"internalType":"address","name":"inputToken","type":"address"},{"internalType":"uint256","name":"inputAmount","type":"uint256"},{"internalType":"address","name":"outputToken","type":"address"},{"internalType":"uint256","name":"minOutputAmount","type":"uint256"},{"internalType":"uint256","name":"refuelAmount","type":"uint256"}],"internalType":"struct BasicRequest","name":"basicReq","type":"tuple"},{"internalType":"address","name":"swapOutputToken","type":"address"},{"internalType":"uint256","name":"minSwapOutput","type":"uint256"},{"internalType":"bytes32","name":"metadata","type":"bytes32"},{"internalType":"bytes","name":"affiliateFees","type":"bytes"}],"internalType":"struct Request","name":"singleOutputRequest","type":"tuple"}],"name":"createRefuelRequest","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_hash","type":"bytes32"},{"internalType":"bytes","name":"_signature","type":"bytes"}],"name":"isValidSignature","outputs":[{"internalType":"bytes4","name":"magicValue","type":"bytes4"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"nominee_","type":"address"}],"name":"nominateOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"nominee","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"nonce","type":"uint256"}],"name":"requestInbox","outputs":[{"internalType":"address","name":"ogSender","type":"address"},{"internalType":"bytes32","name":"typedDataHash","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"rescue","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"components":[{"internalType":"uint256","name":"originChainId","type":"uint256"},{"internalType":"uint256","name":"destinationChainId","type":"uint256"},{"internalType":"uint256","name":"deadline","type":"uint256"},{"internalType":"uint256","name":"nonce","type":"uint256"},{"internalType":"address","name":"sender","type":"address"},{"internalType":"address","name":"receiver","type":"address"},{"internalType":"address","name":"delegate","type":"address"},{"internalType":"address","name":"bungeeGateway","type":"address"},{"internalType":"uint32","name":"switchboardId","type":"uint32"},{"internalType":"address","name":"inputToken","type":"address"},{"internalType":"uint256","name":"inputAmount","type":"uint256"},{"internalType":"address","name":"outputToken","type":"address"},{"internalType":"uint256","name":"minOutputAmount","type":"uint256"},{"internalType":"uint256","name":"refuelAmount","type":"uint256"}],"internalType":"struct BasicRequest","name":"basicReq","type":"tuple"},{"internalType":"address","name":"swapOutputToken","type":"address"},{"internalType":"uint256","name":"minSwapOutput","type":"uint256"},{"internalType":"bytes32","name":"metadata","type":"bytes32"},{"internalType":"bytes","name":"affiliateFees","type":"bytes"}],"internalType":"struct Request","name":"singleOutputRequest","type":"tuple"}],"name":"withdrawFunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"typedDataHash","type":"bytes32"}],"name":"withdrawnInbox","outputs":[{"internalType":"bool","name":"withdrawn","type":"bool"}],"stateMutability":"view","type":"function"},{"stateMutability":"payable","type":"receive"}]

60e06040523480156200001157600080fd5b5060405162001e3438038062001e34833981016040819052620000349162000143565b836200004081620000d7565b506001600160a01b03838116608081905283821660c05290821660a081905260405163095ea7b360e01b8152600481019290925260001960248301529063095ea7b3906044016020604051808303816000875af1158015620000a6573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190620000cc9190620001ab565b5050505050620001d6565b600080546001600160a01b0383166001600160a01b0319918216811783556001805490921690915560405190917ffbe19c9b601f5ee90b44c7390f3fa2319eba01762d34ee372aeafd59b25c7f8791a250565b6001600160a01b03811681146200014057600080fd5b50565b600080600080608085870312156200015a57600080fd5b845162000167816200012a565b60208601519094506200017a816200012a565b60408601519093506200018d816200012a565b6060860151909250620001a0816200012a565b939692955090935050565b600060208284031215620001be57600080fd5b81518015158114620001cf57600080fd5b9392505050565b60805160a05160c051611c046200023060003960008181610232015281816106b1015261076d01526000818161013d015281816104ac0152610bb20152600081816101fe01528181610a9e0152610b040152611c046000f3fe6080604052600436106100e15760003560e01c806370372d851161007f5780639ef6b870116100595780639ef6b87014610285578063a4a96bee146102c5578063b19c7af914610324578063df2ebdbb1461034457600080fd5b806370372d85146102205780637692ba86146102545780638da5cb5b1461026757600080fd5b806320ff430b116100bb57806320ff430b146101955780633bd1adec146101b75780635b94db27146101cc5780636afdd850146101ec57600080fd5b80631626ba7e146100ed5780631b3f8c5e1461012b57806320f99c0a1461017757600080fd5b366100e857005b600080fd5b3480156100f957600080fd5b5061010d610108366004611097565b61036c565b6040516001600160e01b031990911681526020015b60405180910390f35b34801561013757600080fd5b5061015f7f000000000000000000000000000000000000000000000000000000000000000081565b6040516001600160a01b039091168152602001610122565b34801561018357600080fd5b506001546001600160a01b031661015f565b3480156101a157600080fd5b506101b56101b036600461112f565b6103bb565b005b3480156101c357600080fd5b506101b56103f6565b3480156101d857600080fd5b506101b56101e736600461116b565b61042c565b3480156101f857600080fd5b5061015f7f000000000000000000000000000000000000000000000000000000000000000081565b34801561022c57600080fd5b5061015f7f000000000000000000000000000000000000000000000000000000000000000081565b6101b5610262366004611186565b6104a1565b34801561027357600080fd5b506000546001600160a01b031661015f565b34801561029157600080fd5b506102b56102a03660046111c2565b60036020526000908152604090205460ff1681565b6040519015158152602001610122565b3480156102d157600080fd5b506103056102e03660046111c2565b600260205260009081526040902080546001909101546001600160a01b039091169082565b604080516001600160a01b039093168352602083019190915201610122565b34801561033057600080fd5b506101b561033f366004611186565b6105d6565b34801561035057600080fd5b5061015f73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee81565b60008061037b838501856111c2565b6000818152600260205260409020600101549091508590036103a75750630b135d3f60e11b90506103b4565b506001600160e01b031990505b9392505050565b6000546001600160a01b031633146103e657604051635fc483c560e01b815260040160405180910390fd5b6103f1838383610826565b505050565b6001546001600160a01b0316331461042157604051637c91ccdd60e01b815260040160405180910390fd5b61042a336108de565b565b6000546001600160a01b0316331461045757604051635fc483c560e01b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b0383169081179091556040517f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce2290600090a250565b6104aa81610931565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b15801561050557600080fd5b505af1158015610519573d6000803e3d6000fd5b505050505060008061052a836109af565b60408051808201825233808252602080830185815260608a0135600090815260028352859020935184546001600160a01b0319166001600160a01b0390911617845551600190930192909255915193955091935084927fb443229dacef116724612aaad43f3c264d2a8859cf87a29c6d26261c01356462926105ae91889101611265565b60408051601f19818403018152908290526105c99291611456565b60405180910390a2505050565b6000806105e2836109af565b60608501356000908152600260205260409020600101549193509150811461061d57604051637037cbb560e11b815260040160405180910390fd5b61062a6060840135610acb565b1561066b57610643606084013561014085013584610b9c565b505060600135600090815260026020526040812080546001600160a01b031916815560010155565b60008181526003602052604090205460ff161561069b57604051633adb396560e21b815260040160405180910390fd5b604051633539b96d60e11b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690636a7372da90602401602060405180830381865afa158015610700573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107249190611482565b6107f45760408051602480820185905282518083039091018152604490910182526020810180516001600160e01b031663048dc4a360e11b1790529051632a02224160e01b81527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632a022241906107aa9084906004016114a4565b6000604051808303816000875af11580156107c9573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526107f19190810190611573565b50505b610808606084013561014085013584610b9c565b6000818152600360205260409020805460ff19166001179055505050565b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b038416016108ca576000826001600160a01b03168261138890604051600060405180830381858888f193505050503d806000811461089d576040519150601f19603f3d011682016040523d82523d6000602084013e6108a2565b606091505b50509050806108c4576040516312171d8360e31b815260040160405180910390fd5b50505050565b6103f16001600160a01b0384168383610c7e565b600080546001600160a01b0383166001600160a01b0319918216811783556001805490921690915560405190917ffbe19c9b601f5ee90b44c7390f3fa2319eba01762d34ee372aeafd59b25c7f8791a250565b806101400135341461095657604051631841b4e160e01b815260040160405180910390fd5b8035461461097757604051633d23e4d160e11b815260040160405180910390fd5b6060810135600090815260026020526040902060010154156109ac57604051633ab3447f60e11b815260040160405180910390fd5b50565b6000806109c36109be84611637565b610d03565b91506000610a976109dc6101408601610120870161116b565b604080516101408801359160608901359190890135908890610a0090602001611789565b604051602081830303815290604052604051602001610a1e90611935565b60408051601f1981840301815290829052610a3c92916020016119e4565b60408051601f1981840301815260608301909152602e808352909190611b3d6020830139604051602001610a71929190611a13565b60408051601f19818403018152919052610a926101008c0160e08d0161116b565b610dec565b9050610ac37f000000000000000000000000000000000000000000000000000000000000000082610e3d565b915050915091565b60008080600884901c60ff85166040516313f80ad160e21b81523060048201526024810183905291935091506000906001600160a01b037f00000000000000000000000000000000000000000000000000000000000000001690634fe02b4490604401602060405180830381865afa158015610b4b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b6f9190611a61565b90506001821b808218808216600003610b8f575060009695505050505050565b5060019695505050505050565b604051632e1a7d4d60e01b8152600481018390527f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031690632e1a7d4d90602401600060405180830381600087803b158015610bfe57600080fd5b505af1158015610c12573d6000803e3d6000fd5b505050600084815260026020526040902054610c4e915073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee906001600160a01b031684610826565b60405181907faead1fb52e86ee68f07ea59f6916ae761c7e362eb98afe59a8f02f880d0714ca90600090a2505050565b600060405163a9059cbb60e01b81526001600160a01b0384166004820152826024820152602060006044836000895af13d15601f3d11600160005114161716915050806108c45760405162461bcd60e51b815260206004820152600f60248201526e1514905394d1915497d19052531151608a1b604482015260640160405180910390fd5b6000604051602001610d1490611935565b604051602081830303815290604052604051602001610d3290611789565b60408051601f1981840301815290829052610d5092916020016119e4565b60405160208183030381529060405280519060200120610d738360000151610edf565b836020015184604001518560600151866080015180519060200120604051602001610dcf9695949392919095865260208601949094526001600160a01b039290921660408501526060840152608083015260a082015260c00190565b604051602081830303815290604052805190602001209050919050565b6040805180820182526001600160a01b038916815260208082018990528251606081018452828152908101889052918201869052600091610e2f81878787610f89565b9a9950505050505050505050565b6000826001600160a01b0316633644e5156040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e7d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ea19190611a61565b60405161190160f01b602082015260228101919091526042810183905260620160405160208183030381529060405280519060200120905092915050565b6000604051602001610ef090611789565b604051602081830303815290604052805190602001204683602001518460400151856060015186608001518760a001518860c001518960e001518a61010001518b61012001518c61014001518d61016001518e61018001518f6101a00151604051602001610f6b9e9d9c9b9a99989796959493929190611a7a565b60408051601f1981840301815290829052610dcf9291602001611b16565b6000806040518060a0016040528060648152602001611b6b6064913984604051602001610fb79291906119e4565b6040516020818303038152906040528051906020012090506000610fde8760000151611043565b6020808901516040808b015181519384018790529083018490526001600160a01b0388166060840152608083019190915260a082015260c0810188905290915060e0016040516020818303038152906040528051906020012092505050949350505050565b60007f618358ac3db8dc274f0cd8829da7e234bd48cd73c4a740aede1adec9846d06a182604051602001610dcf92919091825280516001600160a01b03166020808401919091520151604082015260600190565b6000806000604084860312156110ac57600080fd5b83359250602084013567ffffffffffffffff808211156110cb57600080fd5b818601915086601f8301126110df57600080fd5b8135818111156110ee57600080fd5b87602082850101111561110057600080fd5b6020830194508093505050509250925092565b80356001600160a01b038116811461112a57600080fd5b919050565b60008060006060848603121561114457600080fd5b61114d84611113565b925061115b60208501611113565b9150604084013590509250925092565b60006020828403121561117d57600080fd5b6103b482611113565b60006020828403121561119857600080fd5b813567ffffffffffffffff8111156111af57600080fd5b820161024081850312156103b457600080fd5b6000602082840312156111d457600080fd5b5035919050565b803563ffffffff8116811461112a57600080fd5b6000808335601e1984360301811261120657600080fd5b830160208101925035905067ffffffffffffffff81111561122657600080fd5b80360382131561123557600080fd5b9250929050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6020815281356020820152602082013560408201526040820135606082015260608201356080820152600061129c60808401611113565b6001600160a01b03811660a0840152506112b860a08401611113565b6001600160a01b03811660c0840152506112d460c08401611113565b6001600160a01b03811660e0840152506112f060e08401611113565b610100611307818501836001600160a01b03169052565b6113128186016111db565b9150506101206113298185018363ffffffff169052565b611334818601611113565b91505061014061134e818501836001600160a01b03169052565b6101609150808501358285015250611367818501611113565b9050610180611380818501836001600160a01b03169052565b6101a091508085013582850152506101c081850135818501526113a4818601611113565b9150506101e06113be818501836001600160a01b03169052565b610200915080850135828501525061022081850135818501526113e3818601866111ef565b61024086810152925090506113fd6102608501838361123c565b95945050505050565b60005b83811015611421578181015183820152602001611409565b50506000910152565b60008151808452611442816020860160208601611406565b601f01601f19169290920160200192915050565b6001600160a01b038316815260406020820181905260009061147a9083018461142a565b949350505050565b60006020828403121561149457600080fd5b815180151581146103b457600080fd5b6020815260006103b4602083018461142a565b634e487b7160e01b600052604160045260246000fd5b60405160a0810167ffffffffffffffff811182821017156114f0576114f06114b7565b60405290565b6040516101c0810167ffffffffffffffff811182821017156114f0576114f06114b7565b604051601f8201601f1916810167ffffffffffffffff81118282101715611543576115436114b7565b604052919050565b600067ffffffffffffffff821115611565576115656114b7565b50601f01601f191660200190565b60006020828403121561158557600080fd5b815167ffffffffffffffff81111561159c57600080fd5b8201601f810184136115ad57600080fd5b80516115c06115bb8261154b565b61151a565b8181528560208385010111156115d557600080fd5b6113fd826020830160208601611406565b600082601f8301126115f757600080fd5b81356116056115bb8261154b565b81815284602083860101111561161a57600080fd5b816020850160208301376000918101602001919091529392505050565b600081360361024081121561164b57600080fd5b6116536114cd565b6101c08083121561166357600080fd5b61166b6114f6565b92508435835260208501356020840152604085013560408401526060850135606084015261169b60808601611113565b60808401526116ac60a08601611113565b60a08401526116bd60c08601611113565b60c08401526116ce60e08601611113565b60e08401526101006116e18187016111db565b908401526101206116f3868201611113565b908401526101408581013590840152610160611710818701611113565b9084015261018085810135908401526101a08086013590840152828252611738818601611113565b6020830152506101e084013560408201526102008401356060820152610220840135915067ffffffffffffffff82111561177157600080fd5b61177d368386016115e6565b60808201529392505050565b6c084c2e6d2c6a4cae2eacae6e85609b1b8152751d5a5b9d0c8d4d881bdc9a59da5b90da185a5b92590b60521b600d8201527f75696e743235362064657374696e6174696f6e436861696e49642c00000000006023820152701d5a5b9d0c8d4d88191958591b1a5b994b607a1b603e8201526d1d5a5b9d0c8d4d881b9bdb98d94b60921b604f8201526e1859191c995cdcc81cd95b99195c8b608a1b605d820152701859191c995cdcc81c9958d95a5d995c8b607a1b606c820152701859191c995cdcc819195b1959d85d194b607a1b607d820152751859191c995cdcc8189d5b99d95951d85d195dd85e4b60521b608e820152741d5a5b9d0ccc881cddda5d18da189bd85c9912590b605a1b60a4820152721859191c995cdcc81a5b9c1d5d151bdad95b8b606a1b60b9820152731d5a5b9d0c8d4d881a5b9c1d5d105b5bdd5b9d0b60621b60cc820152731859191c995cdcc81bdd5d1c1d5d151bdad95b8b60621b60e08201527f75696e74323536206d696e4f7574707574416d6f756e742c75696e743235362060f48201526c72656675656c416d6f756e742960981b6101148201526101210190565b670a4cae2eacae6e8560c31b81527510985cda58d4995c5d595cdd0818985cda58d4995c4b60521b60088201527f6164647265737320737761704f7574707574546f6b656e2c0000000000000000601e820152751d5a5b9d0c8d4d881b5a5b94ddd85c13dd5d1c1d5d0b60521b603682015270189e5d195ccccc881b595d1859185d184b607a1b604c82015273627974657320616666696c69617465466565732960601b605d82015260710190565b600083516119f6818460208801611406565b835190830190611a0a818360208801611406565b01949350505050565b6f52657175657374207769746e6573732960801b815260008351611a3e816010850160208801611406565b835190830190611a55816010840160208801611406565b01601001949350505050565b600060208284031215611a7357600080fd5b5051919050565b8e8152602081018e9052604081018d9052606081018c90526001600160a01b038b811660808301528a811660a083015289811660c0830152881660e08201526101c0810163ffffffff88166101008301526001600160a01b03871661012083015285610140830152611af86101608301866001600160a01b03169052565b6101808201939093526101a001529c9b505050505050505050505050565b82815260008251611b2e816020850160208701611406565b91909101602001939250505056fe546f6b656e5065726d697373696f6e73286164647265737320746f6b656e2c75696e7432353620616d6f756e74295065726d69745769746e6573735472616e7366657246726f6d28546f6b656e5065726d697373696f6e73207065726d69747465642c61646472657373207370656e6465722c75696e74323536206e6f6e63652c75696e7432353620646561646c696e652ca264697066735822122005b3ad66d8517182f40f902a8af73a56c10b1f141242af8396bfb41818ca2b7664736f6c63430008130033000000000000000000000000a5acba07788f16b4790fcbb09ca3b7fc8dd053a2000000000000000000000000000000000022d473030f116ddee9f6b43ac78ba3000000000000000000000000d26410401cc61a24205a01cc620a73c010fba290000000000000000000000000039e2fb66102314ce7b64ce5ce3e5183bc94ad38

Deployed Bytecode

0x6080604052600436106100e15760003560e01c806370372d851161007f5780639ef6b870116100595780639ef6b87014610285578063a4a96bee146102c5578063b19c7af914610324578063df2ebdbb1461034457600080fd5b806370372d85146102205780637692ba86146102545780638da5cb5b1461026757600080fd5b806320ff430b116100bb57806320ff430b146101955780633bd1adec146101b75780635b94db27146101cc5780636afdd850146101ec57600080fd5b80631626ba7e146100ed5780631b3f8c5e1461012b57806320f99c0a1461017757600080fd5b366100e857005b600080fd5b3480156100f957600080fd5b5061010d610108366004611097565b61036c565b6040516001600160e01b031990911681526020015b60405180910390f35b34801561013757600080fd5b5061015f7f000000000000000000000000039e2fb66102314ce7b64ce5ce3e5183bc94ad3881565b6040516001600160a01b039091168152602001610122565b34801561018357600080fd5b506001546001600160a01b031661015f565b3480156101a157600080fd5b506101b56101b036600461112f565b6103bb565b005b3480156101c357600080fd5b506101b56103f6565b3480156101d857600080fd5b506101b56101e736600461116b565b61042c565b3480156101f857600080fd5b5061015f7f000000000000000000000000000000000022d473030f116ddee9f6b43ac78ba381565b34801561022c57600080fd5b5061015f7f000000000000000000000000d26410401cc61a24205a01cc620a73c010fba29081565b6101b5610262366004611186565b6104a1565b34801561027357600080fd5b506000546001600160a01b031661015f565b34801561029157600080fd5b506102b56102a03660046111c2565b60036020526000908152604090205460ff1681565b6040519015158152602001610122565b3480156102d157600080fd5b506103056102e03660046111c2565b600260205260009081526040902080546001909101546001600160a01b039091169082565b604080516001600160a01b039093168352602083019190915201610122565b34801561033057600080fd5b506101b561033f366004611186565b6105d6565b34801561035057600080fd5b5061015f73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee81565b60008061037b838501856111c2565b6000818152600260205260409020600101549091508590036103a75750630b135d3f60e11b90506103b4565b506001600160e01b031990505b9392505050565b6000546001600160a01b031633146103e657604051635fc483c560e01b815260040160405180910390fd5b6103f1838383610826565b505050565b6001546001600160a01b0316331461042157604051637c91ccdd60e01b815260040160405180910390fd5b61042a336108de565b565b6000546001600160a01b0316331461045757604051635fc483c560e01b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b0383169081179091556040517f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce2290600090a250565b6104aa81610931565b7f000000000000000000000000039e2fb66102314ce7b64ce5ce3e5183bc94ad386001600160a01b031663d0e30db0346040518263ffffffff1660e01b81526004016000604051808303818588803b15801561050557600080fd5b505af1158015610519573d6000803e3d6000fd5b505050505060008061052a836109af565b60408051808201825233808252602080830185815260608a0135600090815260028352859020935184546001600160a01b0319166001600160a01b0390911617845551600190930192909255915193955091935084927fb443229dacef116724612aaad43f3c264d2a8859cf87a29c6d26261c01356462926105ae91889101611265565b60408051601f19818403018152908290526105c99291611456565b60405180910390a2505050565b6000806105e2836109af565b60608501356000908152600260205260409020600101549193509150811461061d57604051637037cbb560e11b815260040160405180910390fd5b61062a6060840135610acb565b1561066b57610643606084013561014085013584610b9c565b505060600135600090815260026020526040812080546001600160a01b031916815560010155565b60008181526003602052604090205460ff161561069b57604051633adb396560e21b815260040160405180910390fd5b604051633539b96d60e11b8152600481018390527f000000000000000000000000d26410401cc61a24205a01cc620a73c010fba2906001600160a01b031690636a7372da90602401602060405180830381865afa158015610700573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906107249190611482565b6107f45760408051602480820185905282518083039091018152604490910182526020810180516001600160e01b031663048dc4a360e11b1790529051632a02224160e01b81527f000000000000000000000000d26410401cc61a24205a01cc620a73c010fba2906001600160a01b031690632a022241906107aa9084906004016114a4565b6000604051808303816000875af11580156107c9573d6000803e3d6000fd5b505050506040513d6000823e601f3d908101601f191682016040526107f19190810190611573565b50505b610808606084013561014085013584610b9c565b6000818152600360205260409020805460ff19166001179055505050565b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b038416016108ca576000826001600160a01b03168261138890604051600060405180830381858888f193505050503d806000811461089d576040519150601f19603f3d011682016040523d82523d6000602084013e6108a2565b606091505b50509050806108c4576040516312171d8360e31b815260040160405180910390fd5b50505050565b6103f16001600160a01b0384168383610c7e565b600080546001600160a01b0383166001600160a01b0319918216811783556001805490921690915560405190917ffbe19c9b601f5ee90b44c7390f3fa2319eba01762d34ee372aeafd59b25c7f8791a250565b806101400135341461095657604051631841b4e160e01b815260040160405180910390fd5b8035461461097757604051633d23e4d160e11b815260040160405180910390fd5b6060810135600090815260026020526040902060010154156109ac57604051633ab3447f60e11b815260040160405180910390fd5b50565b6000806109c36109be84611637565b610d03565b91506000610a976109dc6101408601610120870161116b565b604080516101408801359160608901359190890135908890610a0090602001611789565b604051602081830303815290604052604051602001610a1e90611935565b60408051601f1981840301815290829052610a3c92916020016119e4565b60408051601f1981840301815260608301909152602e808352909190611b3d6020830139604051602001610a71929190611a13565b60408051601f19818403018152919052610a926101008c0160e08d0161116b565b610dec565b9050610ac37f000000000000000000000000000000000022d473030f116ddee9f6b43ac78ba382610e3d565b915050915091565b60008080600884901c60ff85166040516313f80ad160e21b81523060048201526024810183905291935091506000906001600160a01b037f000000000000000000000000000000000022d473030f116ddee9f6b43ac78ba31690634fe02b4490604401602060405180830381865afa158015610b4b573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b6f9190611a61565b90506001821b808218808216600003610b8f575060009695505050505050565b5060019695505050505050565b604051632e1a7d4d60e01b8152600481018390527f000000000000000000000000039e2fb66102314ce7b64ce5ce3e5183bc94ad386001600160a01b031690632e1a7d4d90602401600060405180830381600087803b158015610bfe57600080fd5b505af1158015610c12573d6000803e3d6000fd5b505050600084815260026020526040902054610c4e915073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee906001600160a01b031684610826565b60405181907faead1fb52e86ee68f07ea59f6916ae761c7e362eb98afe59a8f02f880d0714ca90600090a2505050565b600060405163a9059cbb60e01b81526001600160a01b0384166004820152826024820152602060006044836000895af13d15601f3d11600160005114161716915050806108c45760405162461bcd60e51b815260206004820152600f60248201526e1514905394d1915497d19052531151608a1b604482015260640160405180910390fd5b6000604051602001610d1490611935565b604051602081830303815290604052604051602001610d3290611789565b60408051601f1981840301815290829052610d5092916020016119e4565b60405160208183030381529060405280519060200120610d738360000151610edf565b836020015184604001518560600151866080015180519060200120604051602001610dcf9695949392919095865260208601949094526001600160a01b039290921660408501526060840152608083015260a082015260c00190565b604051602081830303815290604052805190602001209050919050565b6040805180820182526001600160a01b038916815260208082018990528251606081018452828152908101889052918201869052600091610e2f81878787610f89565b9a9950505050505050505050565b6000826001600160a01b0316633644e5156040518163ffffffff1660e01b8152600401602060405180830381865afa158015610e7d573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610ea19190611a61565b60405161190160f01b602082015260228101919091526042810183905260620160405160208183030381529060405280519060200120905092915050565b6000604051602001610ef090611789565b604051602081830303815290604052805190602001204683602001518460400151856060015186608001518760a001518860c001518960e001518a61010001518b61012001518c61014001518d61016001518e61018001518f6101a00151604051602001610f6b9e9d9c9b9a99989796959493929190611a7a565b60408051601f1981840301815290829052610dcf9291602001611b16565b6000806040518060a0016040528060648152602001611b6b6064913984604051602001610fb79291906119e4565b6040516020818303038152906040528051906020012090506000610fde8760000151611043565b6020808901516040808b015181519384018790529083018490526001600160a01b0388166060840152608083019190915260a082015260c0810188905290915060e0016040516020818303038152906040528051906020012092505050949350505050565b60007f618358ac3db8dc274f0cd8829da7e234bd48cd73c4a740aede1adec9846d06a182604051602001610dcf92919091825280516001600160a01b03166020808401919091520151604082015260600190565b6000806000604084860312156110ac57600080fd5b83359250602084013567ffffffffffffffff808211156110cb57600080fd5b818601915086601f8301126110df57600080fd5b8135818111156110ee57600080fd5b87602082850101111561110057600080fd5b6020830194508093505050509250925092565b80356001600160a01b038116811461112a57600080fd5b919050565b60008060006060848603121561114457600080fd5b61114d84611113565b925061115b60208501611113565b9150604084013590509250925092565b60006020828403121561117d57600080fd5b6103b482611113565b60006020828403121561119857600080fd5b813567ffffffffffffffff8111156111af57600080fd5b820161024081850312156103b457600080fd5b6000602082840312156111d457600080fd5b5035919050565b803563ffffffff8116811461112a57600080fd5b6000808335601e1984360301811261120657600080fd5b830160208101925035905067ffffffffffffffff81111561122657600080fd5b80360382131561123557600080fd5b9250929050565b81835281816020850137506000828201602090810191909152601f909101601f19169091010190565b6020815281356020820152602082013560408201526040820135606082015260608201356080820152600061129c60808401611113565b6001600160a01b03811660a0840152506112b860a08401611113565b6001600160a01b03811660c0840152506112d460c08401611113565b6001600160a01b03811660e0840152506112f060e08401611113565b610100611307818501836001600160a01b03169052565b6113128186016111db565b9150506101206113298185018363ffffffff169052565b611334818601611113565b91505061014061134e818501836001600160a01b03169052565b6101609150808501358285015250611367818501611113565b9050610180611380818501836001600160a01b03169052565b6101a091508085013582850152506101c081850135818501526113a4818601611113565b9150506101e06113be818501836001600160a01b03169052565b610200915080850135828501525061022081850135818501526113e3818601866111ef565b61024086810152925090506113fd6102608501838361123c565b95945050505050565b60005b83811015611421578181015183820152602001611409565b50506000910152565b60008151808452611442816020860160208601611406565b601f01601f19169290920160200192915050565b6001600160a01b038316815260406020820181905260009061147a9083018461142a565b949350505050565b60006020828403121561149457600080fd5b815180151581146103b457600080fd5b6020815260006103b4602083018461142a565b634e487b7160e01b600052604160045260246000fd5b60405160a0810167ffffffffffffffff811182821017156114f0576114f06114b7565b60405290565b6040516101c0810167ffffffffffffffff811182821017156114f0576114f06114b7565b604051601f8201601f1916810167ffffffffffffffff81118282101715611543576115436114b7565b604052919050565b600067ffffffffffffffff821115611565576115656114b7565b50601f01601f191660200190565b60006020828403121561158557600080fd5b815167ffffffffffffffff81111561159c57600080fd5b8201601f810184136115ad57600080fd5b80516115c06115bb8261154b565b61151a565b8181528560208385010111156115d557600080fd5b6113fd826020830160208601611406565b600082601f8301126115f757600080fd5b81356116056115bb8261154b565b81815284602083860101111561161a57600080fd5b816020850160208301376000918101602001919091529392505050565b600081360361024081121561164b57600080fd5b6116536114cd565b6101c08083121561166357600080fd5b61166b6114f6565b92508435835260208501356020840152604085013560408401526060850135606084015261169b60808601611113565b60808401526116ac60a08601611113565b60a08401526116bd60c08601611113565b60c08401526116ce60e08601611113565b60e08401526101006116e18187016111db565b908401526101206116f3868201611113565b908401526101408581013590840152610160611710818701611113565b9084015261018085810135908401526101a08086013590840152828252611738818601611113565b6020830152506101e084013560408201526102008401356060820152610220840135915067ffffffffffffffff82111561177157600080fd5b61177d368386016115e6565b60808201529392505050565b6c084c2e6d2c6a4cae2eacae6e85609b1b8152751d5a5b9d0c8d4d881bdc9a59da5b90da185a5b92590b60521b600d8201527f75696e743235362064657374696e6174696f6e436861696e49642c00000000006023820152701d5a5b9d0c8d4d88191958591b1a5b994b607a1b603e8201526d1d5a5b9d0c8d4d881b9bdb98d94b60921b604f8201526e1859191c995cdcc81cd95b99195c8b608a1b605d820152701859191c995cdcc81c9958d95a5d995c8b607a1b606c820152701859191c995cdcc819195b1959d85d194b607a1b607d820152751859191c995cdcc8189d5b99d95951d85d195dd85e4b60521b608e820152741d5a5b9d0ccc881cddda5d18da189bd85c9912590b605a1b60a4820152721859191c995cdcc81a5b9c1d5d151bdad95b8b606a1b60b9820152731d5a5b9d0c8d4d881a5b9c1d5d105b5bdd5b9d0b60621b60cc820152731859191c995cdcc81bdd5d1c1d5d151bdad95b8b60621b60e08201527f75696e74323536206d696e4f7574707574416d6f756e742c75696e743235362060f48201526c72656675656c416d6f756e742960981b6101148201526101210190565b670a4cae2eacae6e8560c31b81527510985cda58d4995c5d595cdd0818985cda58d4995c4b60521b60088201527f6164647265737320737761704f7574707574546f6b656e2c0000000000000000601e820152751d5a5b9d0c8d4d881b5a5b94ddd85c13dd5d1c1d5d0b60521b603682015270189e5d195ccccc881b595d1859185d184b607a1b604c82015273627974657320616666696c69617465466565732960601b605d82015260710190565b600083516119f6818460208801611406565b835190830190611a0a818360208801611406565b01949350505050565b6f52657175657374207769746e6573732960801b815260008351611a3e816010850160208801611406565b835190830190611a55816010840160208801611406565b01601001949350505050565b600060208284031215611a7357600080fd5b5051919050565b8e8152602081018e9052604081018d9052606081018c90526001600160a01b038b811660808301528a811660a083015289811660c0830152881660e08201526101c0810163ffffffff88166101008301526001600160a01b03871661012083015285610140830152611af86101608301866001600160a01b03169052565b6101808201939093526101a001529c9b505050505050505050505050565b82815260008251611b2e816020850160208701611406565b91909101602001939250505056fe546f6b656e5065726d697373696f6e73286164647265737320746f6b656e2c75696e7432353620616d6f756e74295065726d69745769746e6573735472616e7366657246726f6d28546f6b656e5065726d697373696f6e73207065726d69747465642c61646472657373207370656e6465722c75696e74323536206e6f6e63652c75696e7432353620646561646c696e652ca264697066735822122005b3ad66d8517182f40f902a8af73a56c10b1f141242af8396bfb41818ca2b7664736f6c63430008130033

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

000000000000000000000000a5acba07788f16b4790fcbb09ca3b7fc8dd053a2000000000000000000000000000000000022d473030f116ddee9f6b43ac78ba3000000000000000000000000d26410401cc61a24205a01cc620a73c010fba290000000000000000000000000039e2fb66102314ce7b64ce5ce3e5183bc94ad38

-----Decoded View---------------
Arg [0] : _owner (address): 0xa5acBA07788f16B4790FCBb09cA3b7Fc8dd053A2
Arg [1] : _permit2 (address): 0x000000000022D473030F116dDEE9F6B43aC78BA3
Arg [2] : _bungeeGateway (address): 0xD26410401cC61a24205A01CC620A73c010FBA290
Arg [3] : _wrappedNativeToken (address): 0x039e2fB66102314Ce7b64Ce5Ce3E5183bc94aD38

-----Encoded View---------------
4 Constructor Arguments found :
Arg [0] : 000000000000000000000000a5acba07788f16b4790fcbb09ca3b7fc8dd053a2
Arg [1] : 000000000000000000000000000000000022d473030f116ddee9f6b43ac78ba3
Arg [2] : 000000000000000000000000d26410401cc61a24205a01cc620a73c010fba290
Arg [3] : 000000000000000000000000039e2fb66102314ce7b64ce5ce3e5183bc94ad38


Block Transaction Gas Used Reward
view all blocks produced

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

Validator Index Block Amount
View All Withdrawals

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

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