Back to Blog

Metamask improves token approval UX

Metamask makes ongoing changes to the way in which the wallet works, providing more insight to users so they can make informed choices. This article looks at the latest updates.

MetaMask Token Approvals banner

Metamask has the unenviable task of creating an intuitive and safe user experience for users with a wide range of previous experience and understanding.

One of Metamask’s recent updates to the UI/UX aims to better educate users about what happens during a transaction's approval process.

When transacting on the blockchain, you are first required to approve the smart contract executing the task can access the token within your wallet.

[@portabletext/react] Unknown block type "youtube", specify a component for it in the `components.types` prop

The two general approaches

  1. Approve the contract has infinite access to a token
  2. Approve the contract has access to a limited amount of the token
    a. This can be just the amount for the current transaction
    b. This can be the total amount of the token you currently hold

When you build interfaces for users, you make decisions about the approval amount you are requesting, which was previously passed directly to Metamask as part of the approval process and had no way to specify the amounts.

With the recent update from Metamask, you are now prompted to add a specific Custom spending cap. This allows you to limit the amount of token you are giving the contract permission to use.

Spending Cap warning on Metamast popup.

There are three options to choose from

  1. Enter your own number
  2. Click “Use default” — this will include the amount that the website is requesting (usually an infinite amount)
  3. Click “Max” — this adds in the amount of that token currently held in your wallet.

Let’s say we were selling 1 ETH token to USDC as part of this transaction. If you specify 1 as the Custom spending cap and then want to sell another 1 ETH tomorrow, you will need to go through and approve the transaction again for another amount because you will have reached the previous spending cap.

If you held 3.5 ETH in your wallet and chose the “Max” option, you could sell 1ETH today and 2.5ETH at another time. If you received another 0.5 ETH (taking your total from 2.5ETH up to 3ETH), then you would still only be able to sell 2.5ETH before having to approve a new spending cap, because you already spent 1 ETH of the previous 3.5ETH cap.

If you chose default and the contract had an infinite spending cap, you would never need to approve the contract ever again. However, if there was a smart contract bug, the exploiter could access all of the ETH in your wallet at any point (at least until you revoked the approval).

How does NFTX approach approvals

NFTX applies an infinite approval for tokens as most of our users are frequently buying and selling NFTs, adding liquidity, claiming fees and exiting positions back to NFTs.

Let’s look at an example of unstaking some inventory tokens into NFTs.


I’m claiming 4 NFTs from the vault, and I select “Approve” the transaction


The approval options show me the number of xUBAYC in my wallet 3.340279120946411997 xUBAYC

If I click “Use default”, the Custom spending cap becomes 115792089237316195423570985008687907853269984665640564039457.584007913129639935 which is the largest number that can be added and essentially means infinite approval. This means you will never have to approve this contract to interact with the vault for the xUBAYC token again.

If I click on “Max”, the custom spending cap becomes my current balance of the xUBAYC holding. If I increase my holding at a later date and want to utilise more than I approved, I will need to go back through the same approval process again.


Once you’ve chosen your custom spending cap, you can then Approve the access or click Edit to change your cap.


import { DocumentIcon } from "@heroicons/react/24/outline"
import { defineField, defineType } from "sanity"

export default defineType({
    name: 'post',
    title: "Post",
    type: 'document',
    icon: DocumentIcon,
    fields: [
        defineField({
            name: 'title',
            title: 'Title',
            description: 'This field is the title of your post.',
            type: 'string',
            validation: (rule) => rule.required(),
        }),
        defineField({
            name: 'datePublished',
            title: 'Date Published',
            description: 'The date this was published, mainly used for migrating old content',
            type: 'datetime',
            validation: (rule) => rule.required(),
        }),
        defineField({
            name: 'featureImage',
            title: 'Feature Image',
            type: 'image',
          }),
        defineField({
            name: 'slug',
            title: 'Slug',
            type: 'slug',
            options: {
                source: 'title',
                maxLength: 96,
            }
        }),
        defineField({
                name: 'content',
                title: 'Content',
                type: 'array',
                of: [
                    { type: 'block'},
                    { type: 'image'},
                    { type: 'code'},
            ],
         }),
         defineField({
            name: 'postType',
            title: 'Type of Post',
            description: 'This will define where in the site the post will appear. Guides, blog, tutorials etc',
            type: 'array',
            of: [{type: 'string'}],
            options: {
                list: [
                  { title: 'Guide', value: 'guide'},
                  { title: 'Blog', value: 'blog'},
                  { title: 'Tutorial', value: 'tutorial'},
                  { title: 'News & Industry', value: 'newsIndustry'},
                  { title: 'Change Log', value: 'changeLog'},
                ],
              },
        }),
         defineField({
            name: 'metadata',
            type: 'baseMetadata'
         })
    ],
    preview: {
        select: {
            title: 'title',
        },
        prepare({ title}) {
            return {
                subtitle: 'Home',
                title,
            }
        }
    }
})

What you decide the best option is for you is up to you. Only approving the exact amount each time is the safest approach, but you will need to pay a fee to approve every time you use the contract. Approving an infinite amount means you never have to approve again for that contract/token, but you’re more at risk for any potential hacks.

How can I see my previous token approvals on my wallet?

If you’re worried about what you have approved in the past https://revoke.cash/ is a great website to see your approvals and revoke them if you are not comfortable with the token/nft access.

If you have any questions about how NFTX works, please let us know at https://twitter.com/nftx_ or https://discord.gg/nftx

Loading...