More Info
Private Name Tags
ContractCreator
Latest 5 from a total of 5 transactions
Latest 25 internal transactions (View All)
Advanced mode:
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
133132969 | 40 days ago | 0.000573452749564 ETH | ||||
133132969 | 40 days ago | 0.000573452749564 ETH | ||||
133125978 | 40 days ago | 0.000774182977421 ETH | ||||
133125978 | 40 days ago | 0.000774182977421 ETH | ||||
133123455 | 40 days ago | 0.000806277853446 ETH | ||||
133123455 | 40 days ago | 0.000806277853446 ETH | ||||
133122324 | 40 days ago | 0.000585943003951 ETH | ||||
133122324 | 40 days ago | 0.000585943003951 ETH | ||||
133121133 | 41 days ago | 0.000593121230278 ETH | ||||
133121133 | 41 days ago | 0.000593121230278 ETH | ||||
133120954 | 41 days ago | 0.000589763066663 ETH | ||||
133120954 | 41 days ago | 0.000589763066663 ETH | ||||
133119702 | 41 days ago | 0.000584627389004 ETH | ||||
133119702 | 41 days ago | 0.000584627389004 ETH | ||||
133117693 | 41 days ago | 0.000584035249277 ETH | ||||
133117693 | 41 days ago | 0.000584035249277 ETH | ||||
133116535 | 41 days ago | 0.000585494678509 ETH | ||||
133116535 | 41 days ago | 0.000585494678509 ETH | ||||
133108929 | 41 days ago | 0.00057635864998 ETH | ||||
133108929 | 41 days ago | 0.00057635864998 ETH | ||||
133108365 | 41 days ago | 0.000580530013735 ETH | ||||
133108365 | 41 days ago | 0.000580530013735 ETH | ||||
133099598 | 41 days ago | 0.000479328940658 ETH | ||||
133099598 | 41 days ago | 0.000479328940658 ETH | ||||
133097818 | 41 days ago | 0.001628977152091 ETH |
Loading...
Loading
Contract Name:
RFQRouter
Compiler Version
v0.8.19+commit.7dd6d404
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// 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 {} }
// 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); } }
// 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"); } }
// 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();
// 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); }
// 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; }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.17; interface IBaseRouter { function releaseFunds(address token, uint256 amount, address recipient) external; }
// 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; }
// 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); }
// 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; }
// 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); } }
// 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; } }
// 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); } }
// 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_); } }
{ "optimizer": { "enabled": true, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "devdoc", "userdoc", "metadata", "abi" ] } }, "libraries": {} }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
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"}]
Contract Creation Code
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
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 34 Chains
Chain | Token | Portfolio % | Price | Amount | Value |
---|
Loading...
Loading
Loading...
Loading
[ 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.