Portals Logo

Documentation
Guides
Token Approvals

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.

Gasless 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.

NOTE: 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.

NOTE: 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"
    }
  }
}