Skip to main content

Build requests onchain

Building requests onchain involves creating a IBungeeInbox.Request with all required parameters, including deadline, nonce, and token specifications. The request is then submitted through the createRequest function.

Creating a Request

Step 1: Generate Request Parameters

Establish the timing and uniqueness parameters for your request:

uint256 currentTimestamp = block.timestamp;
uint256 deadline = currentTimestamp + 600; // 10 minutes deadline
uint256 nonce = uint256(
uint32(
bytes4(
keccak256(
abi.encodePacked(
currentTimestamp,
block.number,
block.prevrandao,
msg.sender,
inputAmount,
chainSlug_,
gasleft()
)
)
)
)
);

The nonce generation combines multiple blockchain parameters to ensure uniqueness and prevent repeated numbers.

Step 2: Build the Basic Request

Create the basic request structure with chain identifiers, token details, and execution parameters:

IBungeeInbox.BasicRequest memory basicReq = IBungeeInbox.BasicRequest({
originChainId: request[user].inputChainSlug,
destinationChainId: request[user].outputChainSlug,
deadline: deadline,
nonce: nonce,
sender: sourceBungeeInboxAddress,
receiver: request[user].monitorAddress,
delegate: request[user].monitorAddress,
bungeeGateway: sourceBungeeGatewayAddress,
switchboardId: 1, // Fixed value for standard operations
inputToken: request[user].inputTokenAddress,
inputAmount: request[user].inputAmount,
outputToken: request[user].outputTokenAddress,
minOutputAmount: request[user].minSwapOutput,
refuelAmount: 0 // Add refuel amount if native token transfer needed
});

Step 3: Complete the Request Structure

Build the full request with additional parameters for swap execution and metadata:

IBungeeInbox.Request memory request = IBungeeInbox.Request({
basicReq: basicReq,
swapOutputToken: request[user].outputTokenAddress,
minSwapOutput: minSwapOutput,
metadata: hex"0000000000000000000000000000000000000000000000000000000000042069", // Fixed metadata
affiliateFees: "", // Add affiliate fee structure if needed
minDestGas: 0,
destinationPayload: "", // Add destination payload encoding if needed
exclusiveTransmitter: address(0) // Add specific transmitter if needed
});

Detailed explanation of all parameters of both structures may be seen in the IBungeeInbox structure definition. Also, validate all inputs before creating requests to prevent invalid submissions.

Submitting the Request

Once your request structure is complete, submit it through the BungeeInbox contract on the source chain:

IBungeeInbox(bungeeInboxAddress).createRequest(request);

Helper Libraries

The utility libraries below are for request handling and validation. These libraries include EIP-712 compliant hashing functions and request verification tools that ensure proper request formatting and security.

Simple utilities for building and verifying BungeeInbox cross-chain request payloads
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.22;

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

/// @title Basic Request Library
/// @notice Provides helpers for handling and hashing BasicRequest structs
/// @dev Contains EIP-712 type hash and origin hash logic for BasicRequest
library BasicRequestLib {
/// @dev EIP-712 type definition for BasicRequest struct
bytes internal constant BASIC_REQUEST_TYPE = abi.encodePacked(
"BasicRequest(",
"uint256 originChainId,",
"uint256 destinationChainId,",
"uint256 deadline,",
"uint256 nonce,",
"address sender,",
"address receiver,",
"address delegate,",
"address bungeeGateway,",
"uint32 switchboardId,",
"address inputToken,",
"uint256 inputAmount,",
"address outputToken,",
"uint256 minOutputAmount,",
"uint256 refuelAmount)"
);
/// @dev Keccak256 hash of the BASIC_REQUEST_TYPE
bytes32 internal constant BASIC_REQUEST_TYPE_HASH = keccak256(BASIC_REQUEST_TYPE);

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

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

/// @dev EIP-712 type definition for Request struct
bytes internal constant REQUEST_TYPE = abi.encodePacked(
"Request(",
"BasicRequest basicReq,",
"address swapOutputToken,",
"uint256 minSwapOutput,",
"bytes32 metadata,",
"bytes affiliateFees,",
"uint256 minDestGas,",
"bytes destinationPayload,",
"address exclusiveTransmitter)"
);

/// @dev EIP-712 type definition for Bungee Request, including BasicRequest
bytes internal constant BUNGEE_REQUEST_TYPE = abi.encodePacked(REQUEST_TYPE, BasicRequestLib.BASIC_REQUEST_TYPE);

/// @dev Keccak256 hash of the BUNGEE_REQUEST_TYPE
bytes32 internal constant BUNGEE_REQUEST_TYPE_HASH = keccak256(BUNGEE_REQUEST_TYPE);

/**
* @notice Creates a deterministic hash for a complete swap request
* @dev Generates an EIP-712 compliant hash that uniquely identifies a swap request
* This hash is used for request tracking, validation, and preventing replay attacks
* @param request The complete swap request structure containing all swap parameters
* @return bytes32 The deterministic hash of the swap request
*/
function createSORHash(IBungeeInbox.Request memory request) internal view returns (bytes32) {
return keccak256(
abi.encode(
BUNGEE_REQUEST_TYPE_HASH,
request.basicReq.originHash(),
request.swapOutputToken,
request.minSwapOutput,
request.metadata,
keccak256(request.affiliateFees),
request.minDestGas,
keccak256(request.destinationPayload),
request.exclusiveTransmitter
)
);
}
}
Simple IBungeeInbox interface for structuring and submitting cross-chain requests
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.22;

/// @title Bungee Inbox Interface
/// @notice Interface for submitting and handling Bungee cross-chain requests
/// @dev Defines the structure and function for Bungee Inbox requests
interface IBungeeInbox {
/// @notice Basic details in the request
/// @dev Contains all the fundamental parameters required for a Bungee request
struct BasicRequest {
/// @notice Source chain ID
uint256 originChainId;
/// @notice Destination chain ID
uint256 destinationChainId;
/// @notice Deadline of the request
uint256 deadline;
/// @notice Nonce used for uniqueness in signature
uint256 nonce;
/// @notice Address of the user placing the request
address sender;
/// @notice Address of the receiver on destination chain
address receiver;
/// @notice Delegate address that has some rights over the request signed (e.g., cancellation)
address delegate;
/// @notice Address of bungee gateway, this address will have access to pull funds from the sender
address bungeeGateway;
/// @notice ID of the switchboard for settlement
uint32 switchboardId;
/// @notice Address of the input token
address inputToken;
/// @notice Amount of the input token
uint256 inputAmount;
/// @notice Output token to be received on the destination
address outputToken;
/// @notice Minimum amount of output token to be received on the destination
uint256 minOutputAmount;
/// @notice Native token refuel amount on the destination chain
uint256 refuelAmount;
}

/// @notice The Request which user signs
/// @dev Contains all parameters for a complete Bungee request, including swap and execution details
struct Request {
/// @notice Basic details in the request
BasicRequest basicReq;
/// @notice Swap output token that the user is permitting to swap input token to
address swapOutputToken;
/// @notice Minimum swap output the user is okay with swapping the input token to
/// @dev Transmitter can choose or not choose to swap tokens
uint256 minSwapOutput;
/// @notice Any sort of metadata to be passed with the request
bytes32 metadata;
/// @notice Fees of the affiliate if any
bytes affiliateFees;
/// @notice Minimum destination gas limit to execute calldata on destination
/// @dev Only to be used when execution is required on destination
uint256 minDestGas;
/// @notice Calldata to be executed on the destination
/// @dev Calldata can only be executed on the receiver in the request
bytes destinationPayload;
/// @notice Address of the only transmitter that is permitted to execute the request
/// @dev If the transmitter is not set, anyone can execute the request. This validation would be done off-chain by the auction house
address exclusiveTransmitter;
}

/// @notice Creates a new Bungee request
/// @dev Accepts a complete Request struct and processes it. May require a payment depending on the request.
/// @param singleOutputRequest The complete request structure containing all parameters
function createRequest(Request calldata singleOutputRequest) external payable;
}