ETH Price: $1,805.62 (+14.00%)

Contract

0xeaCb816dF64027f3CA536735efA6835cda70D785

Overview

ETH Balance

0 ETH

ETH Value

$0.00

Token Holdings

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Rescue1333505852025-03-18 12:12:2735 days ago1742299947IN
0xeaCb816d...cda70D785
0 ETH0.0000000187440.0002523
Nominate Owner1287647152024-12-02 8:30:07141 days ago1733128207IN
0xeaCb816d...cda70D785
0 ETH0.000000423290.00100089
Rescue1287646852024-12-02 8:29:07141 days ago1733128147IN
0xeaCb816d...cda70D785
0 ETH0.0000004149270.00100087
Rescue1261711642024-10-03 7:38:25201 days ago1727941105IN
0xeaCb816d...cda70D785
0 ETH0.0000000683040.00035591
Nominate Owner1260949052024-10-01 13:16:27203 days ago1727788587IN
0xeaCb816d...cda70D785
0 ETH0.000000149110.00031377

Latest 25 internal transactions (View All)

Advanced mode:
Parent Transaction Hash Block From To
1331329692025-03-13 11:18:3540 days ago1741864715
0xeaCb816d...cda70D785
0.000573452749564 ETH
1331329692025-03-13 11:18:3540 days ago1741864715
0xeaCb816d...cda70D785
0.000573452749564 ETH
1331259782025-03-13 7:25:3340 days ago1741850733
0xeaCb816d...cda70D785
0.000774182977421 ETH
1331259782025-03-13 7:25:3340 days ago1741850733
0xeaCb816d...cda70D785
0.000774182977421 ETH
1331234552025-03-13 6:01:2740 days ago1741845687
0xeaCb816d...cda70D785
0.000806277853446 ETH
1331234552025-03-13 6:01:2740 days ago1741845687
0xeaCb816d...cda70D785
0.000806277853446 ETH
1331223242025-03-13 5:23:4540 days ago1741843425
0xeaCb816d...cda70D785
0.000585943003951 ETH
1331223242025-03-13 5:23:4540 days ago1741843425
0xeaCb816d...cda70D785
0.000585943003951 ETH
1331211332025-03-13 4:44:0341 days ago1741841043
0xeaCb816d...cda70D785
0.000593121230278 ETH
1331211332025-03-13 4:44:0341 days ago1741841043
0xeaCb816d...cda70D785
0.000593121230278 ETH
1331209542025-03-13 4:38:0541 days ago1741840685
0xeaCb816d...cda70D785
0.000589763066663 ETH
1331209542025-03-13 4:38:0541 days ago1741840685
0xeaCb816d...cda70D785
0.000589763066663 ETH
1331197022025-03-13 3:56:2141 days ago1741838181
0xeaCb816d...cda70D785
0.000584627389004 ETH
1331197022025-03-13 3:56:2141 days ago1741838181
0xeaCb816d...cda70D785
0.000584627389004 ETH
1331176932025-03-13 2:49:2341 days ago1741834163
0xeaCb816d...cda70D785
0.000584035249277 ETH
1331176932025-03-13 2:49:2341 days ago1741834163
0xeaCb816d...cda70D785
0.000584035249277 ETH
1331165352025-03-13 2:10:4741 days ago1741831847
0xeaCb816d...cda70D785
0.000585494678509 ETH
1331165352025-03-13 2:10:4741 days ago1741831847
0xeaCb816d...cda70D785
0.000585494678509 ETH
1331089292025-03-12 21:57:1541 days ago1741816635
0xeaCb816d...cda70D785
0.00057635864998 ETH
1331089292025-03-12 21:57:1541 days ago1741816635
0xeaCb816d...cda70D785
0.00057635864998 ETH
1331083652025-03-12 21:38:2741 days ago1741815507
0xeaCb816d...cda70D785
0.000580530013735 ETH
1331083652025-03-12 21:38:2741 days ago1741815507
0xeaCb816d...cda70D785
0.000580530013735 ETH
1330995982025-03-12 16:46:1341 days ago1741797973
0xeaCb816d...cda70D785
0.000479328940658 ETH
1330995982025-03-12 16:46:1341 days ago1741797973
0xeaCb816d...cda70D785
0.000479328940658 ETH
1330978182025-03-12 15:46:5341 days ago1741794413
0xeaCb816d...cda70D785
0.001628977152091 ETH
View All Internal Transactions

Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
RFQRouter

Compiler Version
v0.8.19+commit.7dd6d404

Optimization Enabled:
Yes with 200 runs

Other Settings:
default evmVersion
File 1 of 14 : RFQRouterSingleOutput.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.17;
import {BaseRouter} from "./BaseRouterSingleOutput.sol";
import {FulfilExec, ExtractExec} from "../common/SingleOutputStructs.sol";
import {BungeeEvents} from "../common/BungeeEvents.sol";
import {Ownable} from "../utils/Ownable.sol";
import {IFeeCollector} from "../interfaces/IFeeCollector.sol";
import {InsufficientNativeAmount} from "../common/BungeeErrors.sol";

// Follows IRouter
contract RFQRouter is BaseRouter, BungeeEvents, Ownable {
    constructor(address _bungeeGateway, address _owner) Ownable(_owner) BaseRouter(_bungeeGateway) {}

    // execute the function
    function _execute(
        uint256 amount,
        address inputToken,
        bytes32 requestHash,
        uint256 expiry,
        address receiverContract,
        ExtractExec calldata exec
    ) internal override {
        // Do nothing, not needed.
    }

    // Called by Bungee on the destination chain to fulfil requests
    function _fulfil(bytes32 requestHash, FulfilExec calldata fulfilExec, address transmitter) internal override {
        // Transfer fulfilAmount from transmitter to user
        bool isNativeToken = fulfilExec.request.basicReq.outputToken == NATIVE_TOKEN_ADDRESS;

        // check msg.value against refuel / native token amount amount
        uint256 totalNativeTokenAmount = isNativeToken
            ? fulfilExec.fulfilAmount + fulfilExec.refuelFulfilAmount
            : fulfilExec.refuelFulfilAmount;
        if (totalNativeTokenAmount > msg.value) revert InsufficientNativeAmount();

        // Send the tokens in the exec to the receiver.
        if (isNativeToken) {
            // send total native token if outputToken is native token
            _sendFundsFromContract(NATIVE_TOKEN_ADDRESS, totalNativeTokenAmount, fulfilExec.request.basicReq.receiver);
        } else {
            // send outputToken to receiver
            _sendFundsToReceiver({
                token: fulfilExec.request.basicReq.outputToken,
                from: transmitter,
                amount: fulfilExec.fulfilAmount, // pass fulfilAmount since we're preventing native tokens in outputToken
                to: fulfilExec.request.basicReq.receiver
            });

            // Send refuel amount to the receiver.
            _sendFundsFromContract({
                token: NATIVE_TOKEN_ADDRESS,
                amount: fulfilExec.refuelFulfilAmount,
                to: fulfilExec.request.basicReq.receiver
            });
        }
    }

    /// @dev can only be called by BungeeGateways
    function _releaseFunds(address token, uint256 amount, address recipient) internal override {
        // Send the tokens in the exec to the receiver.
        _sendFundsFromContract(token, amount, recipient);
    }

    function _collectFee(
        address token,
        uint256 amount,
        address feeTaker,
        address feeCollector,
        bytes32 requestHash
    ) internal override {
        _sendFundsFromContract(token, amount, feeCollector);
        IFeeCollector(feeCollector).registerFee(feeTaker, amount, token, requestHash);
    }

    /**
     * @notice send funds to the provided address if stuck, can be called only by owner.
     * @param token address of the token
     * @param amount hash of the command.
     * @param to address, funds will be transferred to this address.
     */
    function rescue(address token, address to, uint256 amount) external onlyOwner {
        _sendFundsFromContract(token, amount, to);
    }

    receive() external payable {}
}

File 2 of 14 : 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 3 of 14 : 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 4 of 14 : 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();

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

contract BungeeEvents {
    /// @notice Emitted when a request is extracted
    /// @param requestHash hash of the request
    /// @param transmitter address of the transmitter
    /// @param execution encoded execution data
    event RequestExtracted(bytes32 indexed requestHash, uint8 implId, address transmitter, bytes execution);

    /// @notice Emitted when a request is fulfilled
    /// @param requestHash hash of the request
    /// @param fulfiller address of the fulfiller
    /// @param execution encoded execution data
    event RequestFulfilled(bytes32 indexed requestHash, uint8 implId, address fulfiller, bytes execution);

    // emitted on the source once settlement completes
    /// @param requestHash hash of the request
    event RequestSettled(bytes32 indexed requestHash);

    // emitted on the destination once settlement completes
    event RequestsSettledOnDestination(
        bytes32[] requestHashes,
        uint8 implId,
        address transmitter,
        uint256 outboundFees
    );

    /// @notice Emitted on the originChain when a request is withdrawn beyond fulfilment deadline
    /// @param requestHash hash of the request
    /// @param token token being withdrawn
    /// @param amount amount being withdrawn
    /// @param to address of the recipient
    event WithdrawOnOrigin(bytes32 indexed requestHash, address token, uint256 amount, address to);

    /// @notice Emitted on the destinationChain when a request is withdrawn if transmitter fails to fulfil
    /// @param requestHash hash of the request
    /// @param token token being withdrawn
    /// @param amount amount being withdrawn
    /// @param to address of the recipient
    event WithdrawOnDestination(bytes32 indexed requestHash, address token, uint256 amount, address to);
}

File 6 of 14 : 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 7 of 14 : IBaseRouter.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.17;

interface IBaseRouter {
    function releaseFunds(address token, uint256 amount, address recipient) external;
}

File 8 of 14 : IBaseRouterSingleOutput.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.17;
import {IBaseRouter} from "./IBaseRouter.sol";
import {FulfilExec, ExtractExec, Request} from "../common/SingleOutputStructs.sol";

interface IBaseRouterSingleOutput is IBaseRouter {
    function execute(
        uint256 amount,
        address inputToken,
        bytes32 requestHash,
        uint256 expiry,
        address receiverContract,
        address feeCollector,
        ExtractExec memory exec
    ) external;

    function fulfil(bytes32 requestHash, FulfilExec calldata fulfilExec, address transmitter) external payable;

    function withdrawRequestOnDestination(Request calldata request, bytes calldata withdrawRequestData) external;
}

File 9 of 14 : 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 10 of 14 : IFeeCollector.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.17;

interface IFeeCollector {
    function registerFee(address feeTaker, uint256 feeAmount, address feeToken) external;
    function registerFee(address feeTaker, uint256 feeAmount, address feeToken, bytes32 requestHash) external;
    function settleFee(bytes32 requestHash) external;
    function refundFee(bytes32 requestHash, address to) external;
}

File 11 of 14 : AffiliateFeesLib.sol
// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.17;

import {ERC20, SafeTransferLib} from "solmate/src/utils/SafeTransferLib.sol";
import {BytesLib} from "./BytesLib.sol";

/// @notice helpers for AffiliateFees struct
library AffiliateFeesLib {
    /// @notice SafeTransferLib - library for safe and optimized operations on ERC20 tokens
    using SafeTransferLib for ERC20;

    /// @notice error when affiliate fee length is wrong
    error WrongAffiliateFeeLength();

    /// @notice event emitted when affiliate fee is deducted
    event AffiliateFeeDeducted(address feeToken, address feeTakerAddress, uint256 feeAmount);

    // Precision used for affiliate fee calculation
    uint256 internal constant PRECISION = 10000000000000000;

    /**
     * @dev calculates & transfers fee to feeTakerAddress
     * @param bridgingAmount amount to be bridged
     * @param affiliateFees packed bytes containing feeTakerAddress and feeInBps
     *                      ensure the affiliateFees is packed as follows:
     *                      address feeTakerAddress (20 bytes) + uint48 feeInBps (6 bytes) = 26 bytes
     * @return bridgingAmount after deducting affiliate fees
     */
    function getAffiliateFees(
        uint256 bridgingAmount,
        bytes memory affiliateFees
    ) internal pure returns (uint256, uint256, address) {
        address feeTakerAddress;
        uint256 feeAmount = 0;
        if (affiliateFees.length > 0) {
            uint48 feeInBps;

            if (affiliateFees.length != 26) revert WrongAffiliateFeeLength();

            feeInBps = BytesLib.toUint48(affiliateFees, 20);
            feeTakerAddress = BytesLib.toAddress(affiliateFees, 0);

            if (feeInBps > 0) {
                // calculate fee
                feeAmount = ((bridgingAmount * feeInBps) / PRECISION);
                bridgingAmount -= feeAmount;
            }
        }

        return (bridgingAmount, feeAmount, feeTakerAddress);
    }

    function getAmountAfterFee(uint256 bridgingAmount, bytes memory affiliateFees) internal pure returns (uint256) {
        address feeTakerAddress;
        uint256 feeAmount = 0;
        if (affiliateFees.length > 0) {
            uint48 feeInBps;

            if (affiliateFees.length != 26) revert WrongAffiliateFeeLength();

            feeInBps = BytesLib.toUint48(affiliateFees, 20);
            feeTakerAddress = BytesLib.toAddress(affiliateFees, 0);

            if (feeInBps > 0) {
                // calculate fee
                feeAmount = ((bridgingAmount * feeInBps) / PRECISION);
                bridgingAmount -= feeAmount;
            }
        }

        return (bridgingAmount);
    }
}

File 12 of 14 : BytesLib.sol
// SPDX-License-Identifier: Unlicense
/*
 * @title Solidity Bytes Arrays Utils
 * @author Gonçalo Sá <[email protected]>
 *
 * @dev Bytes tightly packed arrays utility library for ethereum contracts written in Solidity.
 *      The library lets you concatenate, slice and type cast bytes arrays both in memory and storage.
 */
pragma solidity >=0.8.4 <0.9.0;

library BytesLib {
    function concat(bytes memory _preBytes, bytes memory _postBytes) internal pure returns (bytes memory) {
        bytes memory tempBytes;

        assembly {
            // Get a location of some free memory and store it in tempBytes as
            // Solidity does for memory variables.
            tempBytes := mload(0x40)

            // Store the length of the first bytes array at the beginning of
            // the memory for tempBytes.
            let length := mload(_preBytes)
            mstore(tempBytes, length)

            // Maintain a memory counter for the current write location in the
            // temp bytes array by adding the 32 bytes for the array length to
            // the starting location.
            let mc := add(tempBytes, 0x20)
            // Stop copying when the memory counter reaches the length of the
            // first bytes array.
            let end := add(mc, length)

            for {
                // Initialize a copy counter to the start of the _preBytes data,
                // 32 bytes into its memory.
                let cc := add(_preBytes, 0x20)
            } lt(mc, end) {
                // Increase both counters by 32 bytes each iteration.
                mc := add(mc, 0x20)
                cc := add(cc, 0x20)
            } {
                // Write the _preBytes data into the tempBytes memory 32 bytes
                // at a time.
                mstore(mc, mload(cc))
            }

            // Add the length of _postBytes to the current length of tempBytes
            // and store it as the new length in the first 32 bytes of the
            // tempBytes memory.
            length := mload(_postBytes)
            mstore(tempBytes, add(length, mload(tempBytes)))

            // Move the memory counter back from a multiple of 0x20 to the
            // actual end of the _preBytes data.
            mc := end
            // Stop copying when the memory counter reaches the new combined
            // length of the arrays.
            end := add(mc, length)

            for {
                let cc := add(_postBytes, 0x20)
            } lt(mc, end) {
                mc := add(mc, 0x20)
                cc := add(cc, 0x20)
            } {
                mstore(mc, mload(cc))
            }

            // Update the free-memory pointer by padding our last write location
            // to 32 bytes: add 31 bytes to the end of tempBytes to move to the
            // next 32 byte block, then round down to the nearest multiple of
            // 32. If the sum of the length of the two arrays is zero then add
            // one before rounding down to leave a blank 32 bytes (the length block with 0).
            mstore(
                0x40,
                and(
                    add(add(end, iszero(add(length, mload(_preBytes)))), 31),
                    not(31) // Round down to the nearest 32 bytes.
                )
            )
        }

        return tempBytes;
    }

    function concatStorage(bytes storage _preBytes, bytes memory _postBytes) internal {
        assembly {
            // Read the first 32 bytes of _preBytes storage, which is the length
            // of the array. (We don't need to use the offset into the slot
            // because arrays use the entire slot.)
            let fslot := sload(_preBytes.slot)
            // Arrays of 31 bytes or less have an even value in their slot,
            // while longer arrays have an odd value. The actual length is
            // the slot divided by two for odd values, and the lowest order
            // byte divided by two for even values.
            // If the slot is even, bitwise and the slot with 255 and divide by
            // two to get the length. If the slot is odd, bitwise and the slot
            // with -1 and divide by two.
            let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2)
            let mlength := mload(_postBytes)
            let newlength := add(slength, mlength)
            // slength can contain both the length and contents of the array
            // if length < 32 bytes so let's prepare for that
            // v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage
            switch add(lt(slength, 32), lt(newlength, 32))
            case 2 {
                // Since the new array still fits in the slot, we just need to
                // update the contents of the slot.
                // uint256(bytes_storage) = uint256(bytes_storage) + uint256(bytes_memory) + new_length
                sstore(
                    _preBytes.slot,
                    // all the modifications to the slot are inside this
                    // next block
                    add(
                        // we can just add to the slot contents because the
                        // bytes we want to change are the LSBs
                        fslot,
                        add(
                            mul(
                                div(
                                    // load the bytes from memory
                                    mload(add(_postBytes, 0x20)),
                                    // zero all bytes to the right
                                    exp(0x100, sub(32, mlength))
                                ),
                                // and now shift left the number of bytes to
                                // leave space for the length in the slot
                                exp(0x100, sub(32, newlength))
                            ),
                            // increase length by the double of the memory
                            // bytes length
                            mul(mlength, 2)
                        )
                    )
                )
            }
            case 1 {
                // The stored value fits in the slot, but the combined value
                // will exceed it.
                // get the keccak hash to get the contents of the array
                mstore(0x0, _preBytes.slot)
                let sc := add(keccak256(0x0, 0x20), div(slength, 32))

                // save new length
                sstore(_preBytes.slot, add(mul(newlength, 2), 1))

                // The contents of the _postBytes array start 32 bytes into
                // the structure. Our first read should obtain the `submod`
                // bytes that can fit into the unused space in the last word
                // of the stored array. To get this, we read 32 bytes starting
                // from `submod`, so the data we read overlaps with the array
                // contents by `submod` bytes. Masking the lowest-order
                // `submod` bytes allows us to add that value directly to the
                // stored value.

                let submod := sub(32, slength)
                let mc := add(_postBytes, submod)
                let end := add(_postBytes, mlength)
                let mask := sub(exp(0x100, submod), 1)

                sstore(
                    sc,
                    add(
                        and(fslot, 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00),
                        and(mload(mc), mask)
                    )
                )

                for {
                    mc := add(mc, 0x20)
                    sc := add(sc, 1)
                } lt(mc, end) {
                    sc := add(sc, 1)
                    mc := add(mc, 0x20)
                } {
                    sstore(sc, mload(mc))
                }

                mask := exp(0x100, sub(mc, end))

                sstore(sc, mul(div(mload(mc), mask), mask))
            }
            default {
                // get the keccak hash to get the contents of the array
                mstore(0x0, _preBytes.slot)
                // Start copying to the last used word of the stored array.
                let sc := add(keccak256(0x0, 0x20), div(slength, 32))

                // save new length
                sstore(_preBytes.slot, add(mul(newlength, 2), 1))

                // Copy over the first `submod` bytes of the new data as in
                // case 1 above.
                let slengthmod := mod(slength, 32)
                let mlengthmod := mod(mlength, 32)
                let submod := sub(32, slengthmod)
                let mc := add(_postBytes, submod)
                let end := add(_postBytes, mlength)
                let mask := sub(exp(0x100, submod), 1)

                sstore(sc, add(sload(sc), and(mload(mc), mask)))

                for {
                    sc := add(sc, 1)
                    mc := add(mc, 0x20)
                } lt(mc, end) {
                    sc := add(sc, 1)
                    mc := add(mc, 0x20)
                } {
                    sstore(sc, mload(mc))
                }

                mask := exp(0x100, sub(mc, end))

                sstore(sc, mul(div(mload(mc), mask), mask))
            }
        }
    }

    function slice(bytes memory _bytes, uint256 _start, uint256 _length) internal pure returns (bytes memory) {
        require(_length + 31 >= _length, "slice_overflow");
        require(_bytes.length >= _start + _length, "slice_outOfBounds");

        bytes memory tempBytes;

        assembly {
            switch iszero(_length)
            case 0 {
                // Get a location of some free memory and store it in tempBytes as
                // Solidity does for memory variables.
                tempBytes := mload(0x40)

                // The first word of the slice result is potentially a partial
                // word read from the original array. To read it, we calculate
                // the length of that partial word and start copying that many
                // bytes into the array. The first word we copy will start with
                // data we don't care about, but the last `lengthmod` bytes will
                // land at the beginning of the contents of the new array. When
                // we're done copying, we overwrite the full first word with
                // the actual length of the slice.
                let lengthmod := and(_length, 31)

                // The multiplication in the next line is necessary
                // because when slicing multiples of 32 bytes (lengthmod == 0)
                // the following copy loop was copying the origin's length
                // and then ending prematurely not copying everything it should.
                let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod)))
                let end := add(mc, _length)

                for {
                    // The multiplication in the next line has the same exact purpose
                    // as the one above.
                    let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start)
                } lt(mc, end) {
                    mc := add(mc, 0x20)
                    cc := add(cc, 0x20)
                } {
                    mstore(mc, mload(cc))
                }

                mstore(tempBytes, _length)

                //update free-memory pointer
                //allocating the array padded to 32 bytes like the compiler does now
                mstore(0x40, and(add(mc, 31), not(31)))
            }
            //if we want a zero-length slice let's just return a zero-length array
            default {
                tempBytes := mload(0x40)
                //zero out the 32 bytes slice we are about to return
                //we need to do it because Solidity does not garbage collect
                mstore(tempBytes, 0)

                mstore(0x40, add(tempBytes, 0x20))
            }
        }

        return tempBytes;
    }

    function toAddress(bytes memory _bytes, uint256 _start) internal pure returns (address) {
        require(_bytes.length >= _start + 20, "toAddress_outOfBounds");
        address tempAddress;

        assembly {
            tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000)
        }

        return tempAddress;
    }

    function toUint8(bytes memory _bytes, uint256 _start) internal pure returns (uint8) {
        require(_bytes.length >= _start + 1, "toUint8_outOfBounds");
        uint8 tempUint;

        assembly {
            tempUint := mload(add(add(_bytes, 0x1), _start))
        }

        return tempUint;
    }

    function toUint16(bytes memory _bytes, uint256 _start) internal pure returns (uint16) {
        require(_bytes.length >= _start + 2, "toUint16_outOfBounds");
        uint16 tempUint;

        assembly {
            tempUint := mload(add(add(_bytes, 0x2), _start))
        }

        return tempUint;
    }

    function toUint32(bytes memory _bytes, uint256 _start) internal pure returns (uint32) {
        require(_bytes.length >= _start + 4, "toUint32_outOfBounds");
        uint32 tempUint;

        assembly {
            tempUint := mload(add(add(_bytes, 0x4), _start))
        }

        return tempUint;
    }

    function toUint48(bytes memory _bytes, uint256 _start) internal pure returns (uint48) {
        require(_bytes.length >= _start + 6, "toUint48_outOfBounds");
        uint48 tempUint;

        assembly {
            tempUint := mload(add(add(_bytes, 0x6), _start))
        }

        return tempUint;
    }

    function toUint64(bytes memory _bytes, uint256 _start) internal pure returns (uint64) {
        require(_bytes.length >= _start + 8, "toUint64_outOfBounds");
        uint64 tempUint;

        assembly {
            tempUint := mload(add(add(_bytes, 0x8), _start))
        }

        return tempUint;
    }

    function toUint96(bytes memory _bytes, uint256 _start) internal pure returns (uint96) {
        require(_bytes.length >= _start + 12, "toUint96_outOfBounds");
        uint96 tempUint;

        assembly {
            tempUint := mload(add(add(_bytes, 0xc), _start))
        }

        return tempUint;
    }

    function toUint128(bytes memory _bytes, uint256 _start) internal pure returns (uint128) {
        require(_bytes.length >= _start + 16, "toUint128_outOfBounds");
        uint128 tempUint;

        assembly {
            tempUint := mload(add(add(_bytes, 0x10), _start))
        }

        return tempUint;
    }

    function toUint256(bytes memory _bytes, uint256 _start) internal pure returns (uint256) {
        require(_bytes.length >= _start + 32, "toUint256_outOfBounds");
        uint256 tempUint;

        assembly {
            tempUint := mload(add(add(_bytes, 0x20), _start))
        }

        return tempUint;
    }

    function toBytes32(bytes memory _bytes, uint256 _start) internal pure returns (bytes32) {
        require(_bytes.length >= _start + 32, "toBytes32_outOfBounds");
        bytes32 tempBytes32;

        assembly {
            tempBytes32 := mload(add(add(_bytes, 0x20), _start))
        }

        return tempBytes32;
    }

    function equal(bytes memory _preBytes, bytes memory _postBytes) internal pure returns (bool) {
        bool success = true;

        assembly {
            let length := mload(_preBytes)

            // if lengths don't match the arrays are not equal
            switch eq(length, mload(_postBytes))
            case 1 {
                // cb is a circuit breaker in the for loop since there's
                //  no said feature for inline assembly loops
                // cb = 1 - don't breaker
                // cb = 0 - break
                let cb := 1

                let mc := add(_preBytes, 0x20)
                let end := add(mc, length)

                for {
                    let cc := add(_postBytes, 0x20)
                    // the next line is the loop condition:
                    // while(uint256(mc < end) + cb == 2)
                } eq(add(lt(mc, end), cb), 2) {
                    mc := add(mc, 0x20)
                    cc := add(cc, 0x20)
                } {
                    // if any of these checks fails then arrays are not equal
                    if iszero(eq(mload(mc), mload(cc))) {
                        // unsuccess:
                        success := 0
                        cb := 0
                    }
                }
            }
            default {
                // unsuccess:
                success := 0
            }
        }

        return success;
    }

    function equal_nonAligned(bytes memory _preBytes, bytes memory _postBytes) internal pure returns (bool) {
        bool success = true;

        assembly {
            let length := mload(_preBytes)

            // if lengths don't match the arrays are not equal
            switch eq(length, mload(_postBytes))
            case 1 {
                // cb is a circuit breaker in the for loop since there's
                //  no said feature for inline assembly loops
                // cb = 1 - don't breaker
                // cb = 0 - break
                let cb := 1

                let endMinusWord := add(_preBytes, length)
                let mc := add(_preBytes, 0x20)
                let cc := add(_postBytes, 0x20)

                for {
                    // the next line is the loop condition:
                    // while(uint256(mc < endWord) + cb == 2)
                } eq(add(lt(mc, endMinusWord), cb), 2) {
                    mc := add(mc, 0x20)
                    cc := add(cc, 0x20)
                } {
                    // if any of these checks fails then arrays are not equal
                    if iszero(eq(mload(mc), mload(cc))) {
                        // unsuccess:
                        success := 0
                        cb := 0
                    }
                }

                // Only if still successful
                // For <1 word tail bytes
                if gt(success, 0) {
                    // Get the remainder of length/32
                    // length % 32 = AND(length, 32 - 1)
                    let numTailBytes := and(length, 0x1f)
                    let mcRem := mload(mc)
                    let ccRem := mload(cc)
                    for {
                        let i := 0
                        // the next line is the loop condition:
                        // while(uint256(i < numTailBytes) + cb == 2)
                    } eq(add(lt(i, numTailBytes), cb), 2) {
                        i := add(i, 1)
                    } {
                        if iszero(eq(byte(i, mcRem), byte(i, ccRem))) {
                            // unsuccess:
                            success := 0
                            cb := 0
                        }
                    }
                }
            }
            default {
                // unsuccess:
                success := 0
            }
        }

        return success;
    }

    function equalStorage(bytes storage _preBytes, bytes memory _postBytes) internal view returns (bool) {
        bool success = true;

        assembly {
            // we know _preBytes_offset is 0
            let fslot := sload(_preBytes.slot)
            // Decode the length of the stored array like in concatStorage().
            let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2)
            let mlength := mload(_postBytes)

            // if lengths don't match the arrays are not equal
            switch eq(slength, mlength)
            case 1 {
                // slength can contain both the length and contents of the array
                // if length < 32 bytes so let's prepare for that
                // v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage
                if iszero(iszero(slength)) {
                    switch lt(slength, 32)
                    case 1 {
                        // blank the last byte which is the length
                        fslot := mul(div(fslot, 0x100), 0x100)

                        if iszero(eq(fslot, mload(add(_postBytes, 0x20)))) {
                            // unsuccess:
                            success := 0
                        }
                    }
                    default {
                        // cb is a circuit breaker in the for loop since there's
                        //  no said feature for inline assembly loops
                        // cb = 1 - don't breaker
                        // cb = 0 - break
                        let cb := 1

                        // get the keccak hash to get the contents of the array
                        mstore(0x0, _preBytes.slot)
                        let sc := keccak256(0x0, 0x20)

                        let mc := add(_postBytes, 0x20)
                        let end := add(mc, mlength)

                        // the next line is the loop condition:
                        // while(uint256(mc < end) + cb == 2)
                        for {

                        } eq(add(lt(mc, end), cb), 2) {
                            sc := add(sc, 1)
                            mc := add(mc, 0x20)
                        } {
                            if iszero(eq(sload(sc), mload(mc))) {
                                // unsuccess:
                                success := 0
                                cb := 0
                            }
                        }
                    }
                }
            }
            default {
                // unsuccess:
                success := 0
            }
        }

        return success;
    }
}

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

import {Request, FulfilExec, ExtractExec} from "../common/SingleOutputStructs.sol";
import {IBaseRouter} from "../interfaces/IBaseRouterSingleOutput.sol";
import {IBungeeGateway} from "../interfaces/IBungeeGateway.sol";
import {TransferFailed} from "../common/BungeeErrors.sol";
import {ERC20} from "solmate/src/tokens/ERC20.sol";
import {SafeTransferLib} from "solmate/src/utils/SafeTransferLib.sol";
import {CallerNotBungeeGateway} from "../common/BungeeErrors.sol";
import {AffiliateFeesLib} from "../lib/AffiliateFeesLib.sol";

// Abstract Contract implemented by Routers
abstract contract BaseRouter is IBaseRouter {
    using SafeTransferLib for ERC20;

    // BungeeGateway Contract
    IBungeeGateway public immutable BUNGEE_GATEWAY;

    /// @notice address to identify the native token
    address public constant NATIVE_TOKEN_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;

    /// @dev id used to identify single output implementation
    uint8 public constant SINGLE_OUTPUT_IMPL_ID = 1;

    constructor(address _bungeeGateway) {
        BUNGEE_GATEWAY = IBungeeGateway(_bungeeGateway);
    }

    /// @dev can only be called by BungeeGateway
    function execute(
        uint256 amount,
        address inputToken,
        bytes32 requestHash,
        uint256 expiry,
        address receiverContract,
        address feeCollector,
        ExtractExec calldata exec
    ) external {
        // Should only be called by Bungee contract
        if (msg.sender != address(BUNGEE_GATEWAY)) revert CallerNotBungeeGateway();

        // Check if fee is supposed to be deducted
        (uint256 bridgeAmount, uint256 feeAmount, address feeTaker) = AffiliateFeesLib.getAffiliateFees(
            amount,
            exec.request.affiliateFees
        );

        if (feeAmount > 0) {
            _collectFee(inputToken, feeAmount, feeTaker, feeCollector, requestHash);
        }
        _execute(bridgeAmount, inputToken, requestHash, expiry, receiverContract, exec);
    }

    /// @dev can only be called by BungeeGateway
    function fulfil(bytes32 requestHash, FulfilExec calldata fulfilExec, address transmitter) external payable {
        // Should only be called by Bungee contract
        if (msg.sender != address(BUNGEE_GATEWAY)) revert CallerNotBungeeGateway();

        _fulfil(requestHash, fulfilExec, transmitter);
    }

    function withdrawRequestOnDestination(Request calldata request, bytes calldata withdrawRequestData) external {
        // Should only be called by Bungee contract
        if (msg.sender != address(BUNGEE_GATEWAY)) revert CallerNotBungeeGateway();

        _withdrawRequestOnDestination(request, withdrawRequestData);
    }

    /// @dev can only be called by BungeeGateways
    function releaseFunds(address token, uint256 amount, address recipient) external {
        // Should only be called by Bungee contract
        if (msg.sender != address(BUNGEE_GATEWAY)) revert CallerNotBungeeGateway();
        // Send the tokens in the exec to the receiver.
        _releaseFunds(token, amount, recipient);
    }

    /// @dev internal function for fulfil that every router needs to implement
    function _fulfil(bytes32 requestHash, FulfilExec calldata fulfilExec, address transmitter) internal virtual {}

    /// @dev internal function for executing the route every router needs to implement
    function _execute(
        uint256 amount,
        address inputToken,
        bytes32 requestHash,
        uint256 expiry,
        address receiverContract,
        ExtractExec calldata exec
    ) internal virtual {}

    /// @dev can only be called by BungeeGateways
    function _releaseFunds(address token, uint256 amount, address recipient) internal virtual {}

    function _collectFee(
        address token,
        uint256 amount,
        address feeTaker,
        address feeCollector,
        bytes32 requestHash
    ) internal virtual {}

    function _withdrawRequestOnDestination(
        Request calldata request,
        bytes calldata withdrawRequestData
    ) internal virtual {}

    /**
     * @dev send funds from an address to the provided address.
     * @param token address of the token
     * @param from atomic execution.
     * @param amount hash of the command.
     * @param to address, funds will be transferred to this address.
     */
    function _sendFundsToReceiver(address token, address from, uint256 amount, address to) 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).safeTransferFrom(from, to, amount);
    }

    /**
     * @dev send funds to the provided address.
     * @param token address of the token
     * @param amount hash of the command.
     * @param to address, funds will be transferred to this address.
     */
    function _sendFundsFromContract(address token, uint256 amount, address to) 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);
    }
}

File 14 of 14 : 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

API
[{"inputs":[{"internalType":"address","name":"_bungeeGateway","type":"address"},{"internalType":"address","name":"_owner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"CallerNotBungeeGateway","type":"error"},{"inputs":[],"name":"InsufficientNativeAmount","type":"error"},{"inputs":[],"name":"OnlyNominee","type":"error"},{"inputs":[],"name":"OnlyOwner","type":"error"},{"inputs":[],"name":"TransferFailed","type":"error"},{"inputs":[],"name":"WrongAffiliateFeeLength","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":"uint8","name":"implId","type":"uint8"},{"indexed":false,"internalType":"address","name":"transmitter","type":"address"},{"indexed":false,"internalType":"bytes","name":"execution","type":"bytes"}],"name":"RequestExtracted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"requestHash","type":"bytes32"},{"indexed":false,"internalType":"uint8","name":"implId","type":"uint8"},{"indexed":false,"internalType":"address","name":"fulfiller","type":"address"},{"indexed":false,"internalType":"bytes","name":"execution","type":"bytes"}],"name":"RequestFulfilled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"requestHash","type":"bytes32"}],"name":"RequestSettled","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32[]","name":"requestHashes","type":"bytes32[]"},{"indexed":false,"internalType":"uint8","name":"implId","type":"uint8"},{"indexed":false,"internalType":"address","name":"transmitter","type":"address"},{"indexed":false,"internalType":"uint256","name":"outboundFees","type":"uint256"}],"name":"RequestsSettledOnDestination","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"requestHash","type":"bytes32"},{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"to","type":"address"}],"name":"WithdrawOnDestination","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"requestHash","type":"bytes32"},{"indexed":false,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"uint256","name":"amount","type":"uint256"},{"indexed":false,"internalType":"address","name":"to","type":"address"}],"name":"WithdrawOnOrigin","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":"SINGLE_OUTPUT_IMPL_ID","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"claimOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"inputToken","type":"address"},{"internalType":"bytes32","name":"requestHash","type":"bytes32"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"address","name":"receiverContract","type":"address"},{"internalType":"address","name":"feeCollector","type":"address"},{"components":[{"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":"request","type":"tuple"},{"internalType":"address","name":"router","type":"address"},{"internalType":"uint256","name":"promisedAmount","type":"uint256"},{"internalType":"uint256","name":"promisedRefuelAmount","type":"uint256"},{"internalType":"bytes","name":"routerData","type":"bytes"},{"internalType":"bytes","name":"swapPayload","type":"bytes"},{"internalType":"address","name":"swapRouter","type":"address"},{"internalType":"bytes","name":"userSignature","type":"bytes"},{"internalType":"address","name":"beneficiary","type":"address"}],"internalType":"struct ExtractExec","name":"exec","type":"tuple"}],"name":"execute","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"requestHash","type":"bytes32"},{"components":[{"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":"request","type":"tuple"},{"internalType":"address","name":"fulfilRouter","type":"address"},{"internalType":"uint256","name":"fulfilAmount","type":"uint256"},{"internalType":"uint256","name":"refuelFulfilAmount","type":"uint256"},{"internalType":"bytes","name":"routerData","type":"bytes"},{"internalType":"uint256","name":"msgValue","type":"uint256"}],"internalType":"struct FulfilExec","name":"fulfilExec","type":"tuple"},{"internalType":"address","name":"transmitter","type":"address"}],"name":"fulfil","outputs":[],"stateMutability":"payable","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":"address","name":"token","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"address","name":"recipient","type":"address"}],"name":"releaseFunds","outputs":[],"stateMutability":"nonpayable","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":"request","type":"tuple"},{"internalType":"bytes","name":"withdrawRequestData","type":"bytes"}],"name":"withdrawRequestOnDestination","outputs":[],"stateMutability":"nonpayable","type":"function"},{"stateMutability":"payable","type":"receive"}]

60a060405234801561001057600080fd5b50604051610f83380380610f8383398101604081905261002f916100bd565b6001600160a01b038216608052806100468161004e565b5050506100f0565b600080546001600160a01b0383166001600160a01b0319918216811783556001805490921690915560405190917ffbe19c9b601f5ee90b44c7390f3fa2319eba01762d34ee372aeafd59b25c7f8791a250565b80516001600160a01b03811681146100b857600080fd5b919050565b600080604083850312156100d057600080fd5b6100d9836100a1565b91506100e7602084016100a1565b90509250929050565b608051610e5c610127600039600081816101de015281816102d50152818161039f0152818161045d01526104b10152610e5c6000f3fe6080604052600436106100ab5760003560e01c80635b94db27116100645780635b94db271461018c57806362524dd7146101ac57806370372d85146101cc5780638da5cb5b14610200578063da2de3441461021e578063df2ebdbb1461023157600080fd5b806320f99c0a146100b757806320ff430b146100ee5780633bd1adec146101105780633cbc7eaa146101255780633ed33c7f1461014c5780634eae20e21461016c57600080fd5b366100b257005b600080fd5b3480156100c357600080fd5b506001546001600160a01b03165b6040516001600160a01b0390911681526020015b60405180910390f35b3480156100fa57600080fd5b5061010e610109366004610b21565b610259565b005b34801561011c57600080fd5b5061010e610294565b34801561013157600080fd5b5061013a600181565b60405160ff90911681526020016100e5565b34801561015857600080fd5b5061010e610167366004610b5d565b6102ca565b34801561017857600080fd5b5061010e610187366004610bf1565b610394565b34801561019857600080fd5b5061010e6101a7366004610c91565b6103dd565b3480156101b857600080fd5b5061010e6101c7366004610cb3565b610452565b3480156101d857600080fd5b506100d17f000000000000000000000000000000000000000000000000000000000000000081565b34801561020c57600080fd5b506000546001600160a01b03166100d1565b61010e61022c366004610cef565b6104a6565b34801561023d57600080fd5b506100d173eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee81565b6000546001600160a01b0316331461028457604051635fc483c560e01b815260040160405180910390fd5b61028f8382846104fa565b505050565b6001546001600160a01b031633146102bf57604051637c91ccdd60e01b815260040160405180910390fd5b6102c8336105b2565b565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461031357604051634556123760e01b815260040160405180910390fd5b6000808061036e8a6103258680610d42565b61033490610220810190610d63565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061060592505050565b91945092509050811561038857610388898383888c6106a2565b50505050505050505050565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461028f57604051634556123760e01b815260040160405180910390fd5b6000546001600160a01b0316331461040857604051635fc483c560e01b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b0383169081179091556040517f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce2290600090a250565b336001600160a01b037f0000000000000000000000000000000000000000000000000000000000000000161461049b57604051634556123760e01b815260040160405180910390fd5b61028f838383610725565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146104ef57604051634556123760e01b815260040160405180910390fd5b61028f838383610730565b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b0384160161059e576000816001600160a01b03168361138890604051600060405180830381858888f193505050503d8060008114610571576040519150601f19603f3d011682016040523d82523d6000602084013e610576565b606091505b5050905080610598576040516312171d8360e31b815260040160405180910390fd5b50505050565b61028f6001600160a01b038416828461086e565b600080546001600160a01b0383166001600160a01b0319918216811783556001805490921690915560405190917ffbe19c9b601f5ee90b44c7390f3fa2319eba01762d34ee372aeafd59b25c7f8791a250565b600080600080600080865111156106975760008651601a1461063a57604051634115207f60e01b815260040160405180910390fd5b6106458760146108f4565b9050610652876000610957565b925065ffffffffffff81161561069557662386f26fc1000061067c65ffffffffffff83168a610dc7565b6106869190610dde565b91506106928289610e00565b97505b505b959690945092505050565b6106ad8585846104fa565b60405163eacedbf160e01b81526001600160a01b0384811660048301526024820186905286811660448301526064820183905283169063eacedbf190608401600060405180830381600087803b15801561070657600080fd5b505af115801561071a573d6000803e3d6000fd5b505050505050505050565b61028f8383836104fa565b600073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee6107518480610d42565b6107649061018081019061016001610c91565b6001600160a01b0316149050600081610781578360600135610793565b61079360608501356040860135610e13565b9050348111156107b657604051637bf261fb60e01b815260040160405180910390fd5b81156107fa576107f573eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee826107df8780610d42565b6107f09060c081019060a001610c91565b6104fa565b610867565b6108406108078580610d42565b61081a9061018081019061016001610c91565b84604087013561082a8880610d42565b61083b9060c081019060a001610c91565b6109bc565b61086773eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee60608601356107df8780610d42565b5050505050565b600060405163a9059cbb60e01b81526001600160a01b0384166004820152826024820152602060006044836000895af13d15601f3d11600160005114161716915050806105985760405162461bcd60e51b815260206004820152600f60248201526e1514905394d1915497d19052531151608a1b60448201526064015b60405180910390fd5b6000610901826006610e13565b835110156109485760405162461bcd60e51b8152602060048201526014602482015273746f55696e7434385f6f75744f66426f756e647360601b60448201526064016108eb565b50818101600601515b92915050565b6000610964826014610e13565b835110156109ac5760405162461bcd60e51b8152602060048201526015602482015274746f416464726573735f6f75744f66426f756e647360581b60448201526064016108eb565b500160200151600160601b900490565b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b03851601610a60576000816001600160a01b03168361138890604051600060405180830381858888f193505050503d8060008114610a33576040519150601f19603f3d011682016040523d82523d6000602084013e610a38565b606091505b5050905080610a5a576040516312171d8360e31b815260040160405180910390fd5b50610598565b6105986001600160a01b03851684838560006040516323b872dd60e01b81526001600160a01b03851660048201526001600160a01b03841660248201528260448201526020600060648360008a5af13d15601f3d11600160005114161716915050806108675760405162461bcd60e51b81526020600482015260146024820152731514905394d1915497d19493d357d1905253115160621b60448201526064016108eb565b80356001600160a01b0381168114610b1c57600080fd5b919050565b600080600060608486031215610b3657600080fd5b610b3f84610b05565b9250610b4d60208501610b05565b9150604084013590509250925092565b600080600080600080600060e0888a031215610b7857600080fd5b87359650610b8860208901610b05565b95506040880135945060608801359350610ba460808901610b05565b9250610bb260a08901610b05565b915060c088013567ffffffffffffffff811115610bce57600080fd5b8801610120818b031215610be157600080fd5b8091505092959891949750929550565b600080600060408486031215610c0657600080fd5b833567ffffffffffffffff80821115610c1e57600080fd5b908501906102408288031215610c3357600080fd5b90935060208501359080821115610c4957600080fd5b818601915086601f830112610c5d57600080fd5b813581811115610c6c57600080fd5b876020828501011115610c7e57600080fd5b6020830194508093505050509250925092565b600060208284031215610ca357600080fd5b610cac82610b05565b9392505050565b600080600060608486031215610cc857600080fd5b610cd184610b05565b925060208401359150610ce660408501610b05565b90509250925092565b600080600060608486031215610d0457600080fd5b83359250602084013567ffffffffffffffff811115610d2257600080fd5b840160c08187031215610d3457600080fd5b9150610ce660408501610b05565b6000823561023e19833603018112610d5957600080fd5b9190910192915050565b6000808335601e19843603018112610d7a57600080fd5b83018035915067ffffffffffffffff821115610d9557600080fd5b602001915036819003821315610daa57600080fd5b9250929050565b634e487b7160e01b600052601160045260246000fd5b808202811582820484141761095157610951610db1565b600082610dfb57634e487b7160e01b600052601260045260246000fd5b500490565b8181038181111561095157610951610db1565b8082018082111561095157610951610db156fea26469706673582212200655634b96606d6a0560508e9e5c02b2750e0cedfc09d1c069895d21062a763564736f6c634300081300330000000000000000000000009c366293ba7e893ce184d75794330d674e4d17c2000000000000000000000000daee4d2156de6fe6f7d50ca047136d758f96a6f0

Deployed Bytecode

0x6080604052600436106100ab5760003560e01c80635b94db27116100645780635b94db271461018c57806362524dd7146101ac57806370372d85146101cc5780638da5cb5b14610200578063da2de3441461021e578063df2ebdbb1461023157600080fd5b806320f99c0a146100b757806320ff430b146100ee5780633bd1adec146101105780633cbc7eaa146101255780633ed33c7f1461014c5780634eae20e21461016c57600080fd5b366100b257005b600080fd5b3480156100c357600080fd5b506001546001600160a01b03165b6040516001600160a01b0390911681526020015b60405180910390f35b3480156100fa57600080fd5b5061010e610109366004610b21565b610259565b005b34801561011c57600080fd5b5061010e610294565b34801561013157600080fd5b5061013a600181565b60405160ff90911681526020016100e5565b34801561015857600080fd5b5061010e610167366004610b5d565b6102ca565b34801561017857600080fd5b5061010e610187366004610bf1565b610394565b34801561019857600080fd5b5061010e6101a7366004610c91565b6103dd565b3480156101b857600080fd5b5061010e6101c7366004610cb3565b610452565b3480156101d857600080fd5b506100d17f0000000000000000000000009c366293ba7e893ce184d75794330d674e4d17c281565b34801561020c57600080fd5b506000546001600160a01b03166100d1565b61010e61022c366004610cef565b6104a6565b34801561023d57600080fd5b506100d173eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee81565b6000546001600160a01b0316331461028457604051635fc483c560e01b815260040160405180910390fd5b61028f8382846104fa565b505050565b6001546001600160a01b031633146102bf57604051637c91ccdd60e01b815260040160405180910390fd5b6102c8336105b2565b565b336001600160a01b037f0000000000000000000000009c366293ba7e893ce184d75794330d674e4d17c2161461031357604051634556123760e01b815260040160405180910390fd5b6000808061036e8a6103258680610d42565b61033490610220810190610d63565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201919091525061060592505050565b91945092509050811561038857610388898383888c6106a2565b50505050505050505050565b336001600160a01b037f0000000000000000000000009c366293ba7e893ce184d75794330d674e4d17c2161461028f57604051634556123760e01b815260040160405180910390fd5b6000546001600160a01b0316331461040857604051635fc483c560e01b815260040160405180910390fd5b600180546001600160a01b0319166001600160a01b0383169081179091556040517f906a1c6bd7e3091ea86693dd029a831c19049ce77f1dce2ce0bab1cacbabce2290600090a250565b336001600160a01b037f0000000000000000000000009c366293ba7e893ce184d75794330d674e4d17c2161461049b57604051634556123760e01b815260040160405180910390fd5b61028f838383610725565b336001600160a01b037f0000000000000000000000009c366293ba7e893ce184d75794330d674e4d17c216146104ef57604051634556123760e01b815260040160405180910390fd5b61028f838383610730565b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b0384160161059e576000816001600160a01b03168361138890604051600060405180830381858888f193505050503d8060008114610571576040519150601f19603f3d011682016040523d82523d6000602084013e610576565b606091505b5050905080610598576040516312171d8360e31b815260040160405180910390fd5b50505050565b61028f6001600160a01b038416828461086e565b600080546001600160a01b0383166001600160a01b0319918216811783556001805490921690915560405190917ffbe19c9b601f5ee90b44c7390f3fa2319eba01762d34ee372aeafd59b25c7f8791a250565b600080600080600080865111156106975760008651601a1461063a57604051634115207f60e01b815260040160405180910390fd5b6106458760146108f4565b9050610652876000610957565b925065ffffffffffff81161561069557662386f26fc1000061067c65ffffffffffff83168a610dc7565b6106869190610dde565b91506106928289610e00565b97505b505b959690945092505050565b6106ad8585846104fa565b60405163eacedbf160e01b81526001600160a01b0384811660048301526024820186905286811660448301526064820183905283169063eacedbf190608401600060405180830381600087803b15801561070657600080fd5b505af115801561071a573d6000803e3d6000fd5b505050505050505050565b61028f8383836104fa565b600073eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee6107518480610d42565b6107649061018081019061016001610c91565b6001600160a01b0316149050600081610781578360600135610793565b61079360608501356040860135610e13565b9050348111156107b657604051637bf261fb60e01b815260040160405180910390fd5b81156107fa576107f573eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee826107df8780610d42565b6107f09060c081019060a001610c91565b6104fa565b610867565b6108406108078580610d42565b61081a9061018081019061016001610c91565b84604087013561082a8880610d42565b61083b9060c081019060a001610c91565b6109bc565b61086773eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee60608601356107df8780610d42565b5050505050565b600060405163a9059cbb60e01b81526001600160a01b0384166004820152826024820152602060006044836000895af13d15601f3d11600160005114161716915050806105985760405162461bcd60e51b815260206004820152600f60248201526e1514905394d1915497d19052531151608a1b60448201526064015b60405180910390fd5b6000610901826006610e13565b835110156109485760405162461bcd60e51b8152602060048201526014602482015273746f55696e7434385f6f75744f66426f756e647360601b60448201526064016108eb565b50818101600601515b92915050565b6000610964826014610e13565b835110156109ac5760405162461bcd60e51b8152602060048201526015602482015274746f416464726573735f6f75744f66426f756e647360581b60448201526064016108eb565b500160200151600160601b900490565b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeed196001600160a01b03851601610a60576000816001600160a01b03168361138890604051600060405180830381858888f193505050503d8060008114610a33576040519150601f19603f3d011682016040523d82523d6000602084013e610a38565b606091505b5050905080610a5a576040516312171d8360e31b815260040160405180910390fd5b50610598565b6105986001600160a01b03851684838560006040516323b872dd60e01b81526001600160a01b03851660048201526001600160a01b03841660248201528260448201526020600060648360008a5af13d15601f3d11600160005114161716915050806108675760405162461bcd60e51b81526020600482015260146024820152731514905394d1915497d19493d357d1905253115160621b60448201526064016108eb565b80356001600160a01b0381168114610b1c57600080fd5b919050565b600080600060608486031215610b3657600080fd5b610b3f84610b05565b9250610b4d60208501610b05565b9150604084013590509250925092565b600080600080600080600060e0888a031215610b7857600080fd5b87359650610b8860208901610b05565b95506040880135945060608801359350610ba460808901610b05565b9250610bb260a08901610b05565b915060c088013567ffffffffffffffff811115610bce57600080fd5b8801610120818b031215610be157600080fd5b8091505092959891949750929550565b600080600060408486031215610c0657600080fd5b833567ffffffffffffffff80821115610c1e57600080fd5b908501906102408288031215610c3357600080fd5b90935060208501359080821115610c4957600080fd5b818601915086601f830112610c5d57600080fd5b813581811115610c6c57600080fd5b876020828501011115610c7e57600080fd5b6020830194508093505050509250925092565b600060208284031215610ca357600080fd5b610cac82610b05565b9392505050565b600080600060608486031215610cc857600080fd5b610cd184610b05565b925060208401359150610ce660408501610b05565b90509250925092565b600080600060608486031215610d0457600080fd5b83359250602084013567ffffffffffffffff811115610d2257600080fd5b840160c08187031215610d3457600080fd5b9150610ce660408501610b05565b6000823561023e19833603018112610d5957600080fd5b9190910192915050565b6000808335601e19843603018112610d7a57600080fd5b83018035915067ffffffffffffffff821115610d9557600080fd5b602001915036819003821315610daa57600080fd5b9250929050565b634e487b7160e01b600052601160045260246000fd5b808202811582820484141761095157610951610db1565b600082610dfb57634e487b7160e01b600052601260045260246000fd5b500490565b8181038181111561095157610951610db1565b8082018082111561095157610951610db156fea26469706673582212200655634b96606d6a0560508e9e5c02b2750e0cedfc09d1c069895d21062a763564736f6c63430008130033

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

0000000000000000000000009c366293ba7e893ce184d75794330d674e4d17c2000000000000000000000000daee4d2156de6fe6f7d50ca047136d758f96a6f0

-----Decoded View---------------
Arg [0] : _bungeeGateway (address): 0x9c366293ba7e893cE184d75794330d674E4D17c2
Arg [1] : _owner (address): 0xDaeE4D2156DE6fe6f7D50cA047136D758f96A6f0

-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 0000000000000000000000009c366293ba7e893ce184d75794330d674e4d17c2
Arg [1] : 000000000000000000000000daee4d2156de6fe6f7d50ca047136d758f96a6f0


Block Transaction Difficulty 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.