Approval Vulnerabilities¶
Approvals are a fundamental component of tokens on Ethereum. They allow users to grant permission to third-party addresses, be it externally owned accounts (EOAs) or other smart contracts, to move funds on their behalf. This feature has benefited many systems, including NFT marketplaces and DeFi applications. These platforms often employ approvals to automate the transfer of funds. This could be when a trade is completed or funds must be moved based on specific business logic conditions.
Unlimited Approvals¶
A prevalent misstep among smart contract developers is requiring unlimited approvals for certain assets. This is usually justified by the system’s lack of knowledge of the necessary amount at a given time. This implies the following problem: Once granted, approvals can be invoked anytime. If a malicious party were to compromise the smart contract system, they could exploit these approvals, leading to a complete drain of all previously approved assets for the affected address.
Approval Frontrunning¶
Another issue is the susceptibility of the approval system to frontrunning. When a user submits multiple approve
calls, they inadvertently open a window of opportunity for malicious actors. To illustrate:
- Using the
approve
function, a user allows a smart contract system to transferx
of their ERC20 tokens. - Later, they opt to modify the allowance to
y
and thus send anotherapprove
request. - In the meantime, before the user-given transaction gets included, an attacker initiates the
transferFrom
function to removex
tokens from the user’s wallet. - If the attacker’s transaction is processed first, followed by the user's new
approve
transaction, the malicious actor can move an additionaly
tokens. - The aggregate unauthorized transfer would amount to
x+y
tokens.
This vulnerability arises because the ERC20's _approve
function directly sets the spender’s allowance.
1 2 3 4 5 6 7 8 9 10 11 12 |
|
Meanwhile, the _spendAllowance
function only verifies the current allowance against the amount specified in the transferFrom
call. It lacks a mechanism to track funds transferred before the latest approve
request.
1 2 3 4 5 6 7 8 9 10 11 |
|
Security Best Practices for Approvals¶
One straightforward countermeasure against frontrunning is to modify how the allowance is managed. Rather than arbitrarily increasing or decreasing allowances by setting new values with direct approve
calls, it’s best practice to call the safeIncreaseAllowance
and safeDecreaseAllowance
functions, as defined in OpenZeppelin's SafeERC20 implementation. These functions internally call the target's approve
function but offer an additional parameter specifying the value difference.
Another notable threat, although not a direct, smart contract vulnerability, is "approval phishing." In scenarios where a frontend is exposed to content injection attacks or other manipulations, attackers can modify the underlying code to divert approvals not to the intended smart contract address but to their own, hijacking the process.
Developers should employ an allowance system that limits the number of tokens an approval can move to only the immediately necessary amount. Implementing two-step transfers and locking periods can limit the impact of malicious actions, although this might reduce user-friendliness. For users, a good habit is periodically assessing given approvals and revoking outdated or unnecessary ones. There are platforms like https://revoke.cash/ that can help in this regard.