A token approval lets a specific spender transfer a specified amount of one token from an owner on one network. It is separate from the swap itself. Limit the amount to the intended task, verify the token and spender contracts, and confirm revocation on-chain when access is no longer needed. Revoking an allowance cannot undo transfers that already succeeded.
Record the permission that the contract actually stores
An approval screen may show a familiar app name, but the useful record is the exact permission behind it: network, owner, token contract, spender address and amount. The same token symbol on another network or at another contract address is a different asset record. A router upgrade can introduce a different spender even when the website looks unchanged.
Under the ERC-20 standard, approve(spender, amount) establishes an allowance, and allowance(owner, spender) reports remaining permission. The approved spender can use the token's transfer mechanism repeatedly within that amount. A later approval replaces the value; it does not automatically add to it.
Approval grants authority without itself performing the intended swap. It does not encode the desired output token, minimum received, recipient or trading strategy. Those belong to the execution call. Review the swap deadline and slippage controls separately: a correct allowance cannot establish that the eventual trade has acceptable terms.
For a direct ERC-20 approval, the transaction calls the token contract, while the spender is an argument inside that call. Checking only the wallet's transaction destination can therefore miss the address receiving authority. Decode both fields before signing.
Keep these fields in a non-secret operations record:
| Field | What to record | Mistake it helps reveal |
|---|---|---|
| Network and owner | Chain identifier and account holding the tokens | Checking a different account or chain |
| Token | Full contract address and verified display units | Approving a token with a familiar symbol but different contract |
| Spender | Full address, purpose and source used to verify it | Approving a substituted or obsolete contract |
| Allowance | Raw integer and displayed token amount | Confusing base units with whole tokens |
| Evidence | Transaction hash, read block and current allowance | Treating an old wallet screen as current state |
For centralized-exchange automation, API-key permissions describe another authorization system. Deleting an exchange key does not change an ERC-20 allowance stored on-chain.
A finite allowance bounds one permission
A small allowance reduces the amount this permission can move if the spender is malicious or becomes exploitable. It does not make an unverified spender trustworthy. For a conventional token with no other transfer restrictions, the immediately transferable amount through this allowance is bounded by the smaller of the owner's balance and the remaining allowance.
That is a narrow accounting bound, not an estimate of total wallet risk. Other spenders may have approvals for the same token; other tokens have separate permissions. A bot holding signing keys may also have authority beyond any single allowance.
An empty token balance does not erase a remaining permission. Later deposits can become accessible while that permission is still active. Treat an approval inventory as relevant even when its present balance column is zero.
“Unlimited” commonly means an extremely large integer. In OpenZeppelin Contracts 5.x ERC20, the maximum uint256 value is treated as an infinite approval and is not reduced by transferFrom. This is documented implementation behavior, not a universal rule for every token.
The base ERC-20 approval interface supplies no expiry field. If a token or permission framework adds an expiry, verify that specific mechanism. A bot's schedule ending at midnight does not, by itself, expire its token allowance.
Follow an approval through a failed swap and a successful one
Consider a hypothetical bot holding 3,000 units of token Q, which uses six decimals. It needs a finite allowance of 600 Q for a verified spender. Assume conventional decrementing allowance behavior, no transfer fees or rebasing, and separate approval and swap transactions. Ignore the output token and gas here so the input-token ledger remains clear.
The approval amount in base units is 600 × 10⁶ = 600,000,000. This unit conversion matters: entering 600 as a raw integer would authorize only 0.0006 Q under the stated decimals.
| Confirmed step | Q balance | Spender's Q allowance | What changed |
|---|---|---|---|
| Starting state | 3,000 | 0 | No permission yet |
| Approve 600 Q | 3,000 | 600 | Authority changes; tokens stay with owner |
| Entire swap transaction reverts | 3,000 | 600 | Earlier separate approval remains |
| New swap spends 250 Q successfully | 2,750 | 350 | Both balance and finite allowance fall by 250 |
| Owner receives another 500 Q | 3,250 | 350 | Deposit increases balance, not allowance |
| Revoke by setting allowance to zero | 3,250 | 0 | Future spending through this allowance stops |
The balance reconciles as 3,000 − 250 + 500 = 3,250 Q. The residual permission after the successful swap is 600 − 250 = 350 Q. Revocation changes that permission to zero; it does not return the 250 Q already spent.
EIP-140 specifies that REVERT rolls back state changes within the reverted execution. In this example, that rollback cannot reach into the earlier successful approval transaction. If approval and swap were instead inside the same fully reverted transaction, their state outcome would differ. Record the actual transaction boundaries.
The table also assumes the whole swap transaction reverts. A composed execution that catches a failed subcall needs a closer inspection of which actions actually completed. A wallet's general failure message is insufficient evidence about all permissions.
Keep network fees in a separate ledger. The failed-swap gas worksheet explains why an unsuccessful exchange can still produce a fee even when token balances roll back.
Revocation has to become effective before it protects anything
Disconnecting a website and revoking a token approval are distinct actions, as MetaMask's allowance guidance explains. Closing the page or stopping a bot does not rewrite the token contract's stored allowance.
A submitted revoke transaction is also different from an effective state change. Ethereum's transaction lifecycle separates broadcast and pending transactions from inclusion and later finality. Use a confirmation policy appropriate to the network, then read the allowance again at an identified block.
Suppose the ledger's remaining 350 Q is spent before the revoke takes effect. After the 500 Q deposit, that alternative outcome leaves 3,250 − 350 = 2,900 Q. A later successful revoke cannot retrieve the 350 Q. This is an alternative ordering scenario, not another step in the main table.
When access is no longer intended, stop the bot's issuance of new instructions, identify pending transactions, and revoke the exact token/spender permission through a verified interface. Preserve the receipt and final allowance read. A failed revocation leaves the permission unresolved.
If compromise is suspected, do not wait for a complete root-cause report before containing known access. Also distinguish an unsafe spender from a compromised wallet signing key: changing one allowance does not remove someone else's ability to sign as the owner.
Changing a limit and retrying are new state decisions
Replacing one nonzero allowance with another creates an ordering problem. In a hypothetical example, a spender uses an existing 600 Q permission before an update to 200 Q executes. After the update, it may still use the new 200 Q: 800 Q in total rather than the intended reduced limit.
ERC-20's specification recommends a user-interface sequence that resets the allowance to zero before setting another nonzero value. That does not stop spending while the zeroing transaction is pending. Confirm the zero state, reconcile any intervening transfers and decide whether a new grant is still appropriate before reauthorizing. ERC-20 approval guidance.
Token compatibility introduces another failure case. OpenZeppelin's SafeERC20 documentation describes forceApprove for tokens requiring a zero reset before a nonzero approval, with USDT as its example. Its wrappers also handle false or absent return values. A bot integration must verify actual token behavior rather than treating a returned transaction hash as proof of permission.
When an approval request times out, first inspect its receipt and current allowance. Blindly issuing another approval can overwrite a changed state. The API retry and backoff guide develops the broader distinction between repeating a read and repeating a mutation with an uncertain outcome.
Signed permits require a second inventory
An approval can begin with a signature instead of an owner-sent approval transaction. ERC-2612 defines a permit containing an owner, spender, value, nonce and deadline. Anyone can submit a valid permit, which sets the allowance and advances the permit nonce.
Its deadline is checked against the block timestamp when the permit executes, with equality allowed. Broadcasting before expiry is insufficient if execution occurs afterward. It does not make the resulting ordinary allowance expire at that time. A signature review must therefore include both the permission amount and the period during which someone can activate it.
There is a further consequence of the specification: an ordinary approve(spender, 0) does not itself consume an unused permit nonce. A still-valid signed permit could subsequently restore an allowance. Treat that as a separate authorization to reconcile; use the token's documented nonce or cancellation mechanism where available. Other permit frameworks can have different revocation rules.
Do not classify every signature request as a harmless login because no gas is charged at signing time. Retain the non-secret typed fields and status needed to understand what was authorized, while keeping the usable signature itself out of logs and support messages.
Close the loop with observable checks
Before enabling a bot to use an allowance, validate a small task and record the evidence:
- Verify the chain, owner, token and spender addresses from authoritative deployment information. An address label is a reading aid, not independent verification.
- Decode the requested amount into token units. Compare it with the intended input budget and identify any permission that persists afterward.
- Read the allowance before sending a change. Track the approval and swap as separate states if they are separate transactions.
- After execution, reconcile token transfers, balance, remaining allowance and fees. Include failed attempts in that review.
- When retiring access, verify the successful revoke and resulting zero allowance. Review outstanding signed authorizations separately.
The useful completion record is specific: this owner, on this network, has this remaining permission for this token and spender at this block. Keep that record alongside the swap result. It makes a future restart an explicit authorization decision instead of an assumption that yesterday's approval must still be appropriate.
