Token Approvals
Summary
Token approvals are needed prior to using Portals that use Basic or LP tokens as input (i.e. the inputToken
). You can determine whether or not the sender
has already granted approval to the Portal contract by calling the approval endpoint. You should always check the approval status of the sender
before calling the Portal endpoint to assemble a transaction if the inputToken
is not a Native token.
Gas-free approvals (Permit)
The Portals API also supports gas-free approvals via EIP-2612. The approval endpoint will automatically detect if the inputToken
supports Permit and return a permit
object containing the approval message to be signed by the sender. Gasless approvals via Permit are optional - the API will return return both an unsigned approval transaction and a Permit message if the inputToken
supports Permit.
Endpoints
GET v2/approval
This endpoint returns a response that may contain an unsigned approval transaction and a permit message if the sender
needs to grant approval, in addition to a context object describing the approval state.
The context object includes a shouldApprove
property whose value is a boolean. If true, the response will include an unsigned approval transaction that must be submitted by the sender
prior to using Portals. In addition, if the inputToken
supports permit, a permit
object will be included in the response containing the approval message to be signed by the sender
.
If using gasless approvals, the permit signature should be retained and submitted with the Portal transaction as described here
Example
Approved state
If sender
has already granted an allowance to the target
(i.e. Portals Router), the approve
object will be undefined and the shouldApprove
and canPermit
booleans will be false. In addition, the allowance
property will indicate the current approval amount that has been granted which will be greater than or equal to the approvalAmount
.
{
"context": {
"network": "ethereum",
"allowance": "28215061",
"approvalAmount": "28215061",
"shouldApprove": false,
"canPermit": false,
"spender": "0xbf5a7f3629fb325e2a8453d595ab103465f75e62",
"target": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"
}
}
Non-Approved State
If sender
has not yet granted an allowance to the target
(i.e. Portals Router), the approve
object will be populated with an unsigned approval transaction and the shouldApprove
boolean will be true. In addition, if the inputToken
supports permit, the canPermit
boolean will be true and the permit
object will be populated with the approval message to be signed by the sender
.
The approve
object is a valid unsigned EVM transaction object that can be submitted to a node after being signed by sender
with their wallet. The permit
object is an EIP-712 message that can be signed by the sender
and submitted with the Portal transaction.
The allowance
property may be non-zero but less than approvalAmount
due to previous interactions with the target
. You should only rely on shouldApprove
to determine whether or not an approval is needed.
{
"context": {
"network": "ethereum",
"allowance": "28215061",
"approvalAmount": "1000000000",
"shouldApprove": true,
"canPermit": true,
"spender": "0xbf5a7f3629fb325e2a8453d595ab103465f75e62",
"target": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48"
},
"approve": {
"data": "0x095ea7b3000000000000000000000000bf5a7f3629fb325e2a8453d595ab103465f75e62000000000000000000000000000000000000000000000000000000003b9aca00",
"to": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
"from": "0x4689cff824d63117f9c4c42f3ec0001676f00d25",
"gasLimit": "43040"
},
"permit": {
"types": {
"Permit": [
{
"name": "owner",
"type": "address"
},
{
"name": "spender",
"type": "address"
},
{
"name": "value",
"type": "uint256"
},
{
"name": "nonce",
"type": "uint256"
},
{
"name": "deadline",
"type": "uint256"
}
]
},
"domain": {
"verifyingContract": "0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48",
"chainId": 1,
"name": "USD Coin",
"version": "2"
},
"value": {
"owner": "0x4689cff824d63117f9c4c42f3ec0001676f00d25",
"spender": "0xbf5a7f3629fb325e2a8453d595ab103465f75e62",
"value": "1000000000",
"nonce": "1",
"deadline": "18446744073709551615"
}
}
}