CallWithSyncFeeERC2771
Transactions with on-chain payments and ERC2771 authentication support
Last updated
Transactions with on-chain payments and ERC2771 authentication support
Last updated
If you plan to use ERC-2771 with a multicall
method or any other method using delegateCall()
Please read carefully the section
If you are using @gelatonetwork/relay-sdk
v3 or contracts from the package @gelatonetwork/relay-context
v2 please follow this to migrate to the new versions.
After reading this page:
You'll know how to use the callWithSyncFeeERC2771
SDK method, using the payment method.
You'll see some code which will help you send a relay request within minutes.
You'll learn how to pay for transactions using the provided values for fee
, feeToken
and feeCollector
.
Please proceed to our page and read it thoroughly before advancing with your implementation. It is crucial to understand all potential security risks and measures to mitigate them.
The callWithSyncFeeERC2771
method uses the payment method with support.
When using callWithSyncFeeERC2771
relay method the target contract assumes responsibility for transferring the fee to Gelato's fee collector during transaction execution. For this, the target contract needs to know:
fee
: the transfer amount
feeToken
: the token to be transferred
feeCollector
: the destination address for the fee
This modular design ensures a smooth integration with Gelato's fee handling mechanisms, providing a flexible and user-friendly approach to managing transaction fees within your dApps.
maxFee
for Your TransactioncallWithSyncFeeERC2771
This method initiates the signing of ERC2771 requests with the provided BrowserProvider
or Wallet
. Once the signature is obtained, the request is forwarded to Gelato.
signerOrProvider
: a valid provider connected to RPC or a signer.
getSignatureDataERC2771
This method starts the signing process for ERC2771 requests using the given BrowserProvider
or Signer
. After capturing the signature, it returns both the signature and the message. This collected data can then be used with the callWithSyncFeeERC2771WithSignature
method to send the request to Gelato.
signerOrProvider
: a valid provider connected to RPC or a signer.
struct
: EIP-712 message data.
signature
: EIP-712 signature.
getDataToSignERC2771
This method provides the message data intended for external signing along with the EIP-712 typed data. After obtaining the signature, the request can be dispatched using the callWithSyncFeeERC2771WithSignature
method.
signerOrProvider
(optional): A provider needed in a sequential flow to obtain the nonce from the smart contract. If you're providing the nonce within your request or if you're using the concurrent flow, this parameter isn't necessary.
struct
: EIP-712 message data.
typedData
: EIP-712 typed data.
This method sends pre-signed requests to Gelato.
struct
: EIP-712 message data returned from the signing methods.
syncFeeParams:
the feetoken
and isRelayContext
params.
signature:
EIP-712 signature returned after signing the request.
gasLimit
: the gas limit of the relay call. This effectively sets an upper price limit for the relay call.
If you are using your own custom gas limit, please add a 150k gas buffer on top of the expected gas usage for the transaction. This is for the Gelato Relay execution overhead, and adding this buffer reduces your chance of the task cancelling before it is executed on-chain.
If your contract has any hardcoded requirements about gas usage, please always explicitly pass the gasLimit
to the SDK/API, as Gelato will not know what hardcoded gas expectations your contract has. Otherwise, your relay requests might not be executable.
retries
: the number of retries that Gelato should attempt before discarding this relay call. This can be useful if the state of the target
contract is not fully known and such reverts can not be definitively avoided.
As of today, we support two distinct ways of sending callWithSyncFeeERC2771
requests:
Sequentially: This approach ensures that each request is ordered and validated against the nonce
stored on-chain. You have two options in this method:
Fetch the current nonce
value from the smart contract yourself and include it with your request.
Allow the relay-sdk to fetch the nonce
value for you when handling your relay request.
Concurrently: This method enables you to send multiple transactions simultaneously. Replay protection is achieved using a hash-based salt
mechanism. Again, you have two options:
Provide your own salt
value.
Allow the relay-sdk to generate a unique salt
value for you when processing your relay request.
By default callWithSyncFeeERC2771
requests are using the sequential method.
chainId
: the chain ID of the chain where the target
smart contract is deployed.
target
: the address of the target smart contract.
data
: encoded payload data (usually a function selector plus the required arguments) used to call the required target
address.
user
: the address of the user's EOA.
userDeadline
: optional, the amount of time in seconds that a user is willing for the relay call to be active in the relay backend before it is dismissed.
This way the user knows that if the transaction is not sent within a certain timeframe, it will expire. Without this, an adversary could pick up the transaction in the mempool and send it later. This could transfer money, or change state at a point in time which would be highly undesirable to the user.
isRelayContext
: an optional boolean (default: true
) denoting what data you would prefer appended to the end of the calldata.
isConcurrent
: false (default), optional, represents that the users' requests are validated based on a nonce, which enforces them to be processed sequentially.
userNonce
: optional, this nonce, akin to Ethereum nonces, is stored in a local mapping on the relay contracts. It serves to enforce the nonce ordering of relay calls if the user requires sequential processing. If this parameter is omitted, the relay-sdk will automatically query the current value on-chain.
isConcurrent
: true, indicates that the users' requests are validated based on a unique salt, allowing them to be processed concurrently. Replay protection is still ensured by permitting each salt value to be used only once.
userSalt
: optional, this is a bytes32 hash that is used for replay protection. If the salt is not provided then relay-sdk would generate a unique value based on a random seed and a timestamp.
GelatoRelayContextERC2771
)Once we have imported the GelatoRelay
class, when using ERC2771
methods, we must initialize it with the appropriate trustedForwarder
.
The possible configurations are:
Fortunately, Gelato provides some useful tools within the :
By inheriting the contract in your target contract, you have the ability to transfer the fee through one of two straightforward methods: _transferRelayFee()
or _transferRelayFeeCapped(uint256 maxFee)
. In either case, the inherited contract takes care of decoding the fee
, feeToken
, and feeCollector
behind the scenes.
The Gelato Relay backend simplifies the process by automatically calculating the fee for you, using Gelato's Fee Oracle to perform the calculations in the background.
Alternatively, you may choose to inherit the contract. With this approach, Gelato decodes only the feeCollector
. You must provide the fee
and feeToken
on-chain, either by hardcoding them (which is not recommended) or embedding them within the payload to be executed. The suggested way to handle this is to calculate the fee with .
Setting a maximum fee, or maxFee
, for your transactions is strongly advised. This practice enables you to ensure that transaction costs remain below a specific limit. The method _transferRelayFeeCapped(uint256 maxFee)
in the contract provides a convenient way to set the maxFee
easily.
If you are utilizing the contract, the recommended way to pass the maxFee
is by calculating the fee with , which is accessible in the . The getEstimatedFee()
method is provided to facilitate this calculation.
request
: The of the request intended for sending.
options
: an object for specifying .
apiKey
: an optional API key that links your request to your Gelato Relay account. As this call pertains to the payment method, transaction costs won't be deducted from your 1Balance account. By using the API key, you can benefit from increased rate limits of your Gelato Relay account.
taskId
: a unique task ID which can be used for .
request
: The of the request intended for sending.
type
: CallWithSyncFee
for a flow or ConcurrentCallWithSyncFee
for a flow.
request
: The of the request intended for sending.
type
: CallWithSyncFee
for a flow or ConcurrentCallWithSyncFee for a flow.
options
: an object for specifying .
apiKey
: an optional API key that links your request to your Gelato Relay account. As this call pertains to the payment method, transaction costs won't be deducted from your 1Balance account. By using the API key, you can benefit from increased rate limits of your Gelato Relay account.
taskId
: a unique task ID which can be used for .
feeToken
: the address of the token that is to be used for payment. Please visit for the full list of supported payment tokens per network.
If set to true
(default), Gelato Relay will append the feeCollector
address, the feeToken
address, and the uint256 fee
to the calldata. In this case your target contract should inherit from the contract.
If set to false
, Gelato Relay will only append the feeCollector
address to the calldata. In this case your target contract should inherit from the contract.
We will need to go to the and check the network and the contract addresses to identify the trustedForwarder
associated with our method.
In the example below, we are using the method callWithSyncFeeERC2771
on Sepolia, the trustedForwarder
associated is 0xb539068872230f20456CF38EC52EF2f91AF4AE49
. We will initialize GelatoRelay
with the following config: