Approvals are an integral part of ERC20 and other token standards which is commonly found in almost all tradable tokens on the Ethereum , Binance Smart Chain , Polygon and many more EVM based blockchains.
Approvals are commonly used by Decentralized application’s smart contracts to get an approval to spend the user’s tokens on their behalf, which is crucial for some applications like Decentralized Exchanges but is often misused by some Applications and even used in malicious phishing attacks which are aimed at unsuspected users and tricks them into providing approvals to a malicious smart contract which then can be used to steal the user’s funds.
To understand how approvals work and why they are needed we need to start from the basics:
What is the ERC20 Standard?
The ERC-20 introduces a standard for Fungible Tokens, in other words, they have a property that makes each Token be exactly the same (in type and value) of another Token. For example, an ERC-20 Token acts just like the ETH, meaning that 1 Token is and will always be equal to all the other Tokens.
The ERC20 Standard defines a set of properties and functionalities which each compatible token must have to qualify as an ERC20 Token. The standard functions that the code must contain are:
function name() public view returns (string)
function symbol() public view returns (string)
function decimals() public view returns (uint8)
function totalSupply() public view returns (uint256)
function balanceOf(address _owner) public view returns (uint256 balance)
function transfer(address _to, uint256 _value) public returns (bool success)
function transferFrom(address _from, address _to, uint256 _value) public returns (bool success)
function approve(address _spender, uint256 _value) public returns (bool success)
function allowance(address _owner, address _spender) public view returns (uint256 remaining)
You can pick up any of your favorite fungible token and you will find these functions in the code always. Some Decentralized applications and Websites requires conformation to the ERC20 standard to be usable with the Application. Most AMM based Decentralized Exchanges require the coin to be ERC20 compliant to be able to traded.
Over the time the standard has been modified by other EVM chains like Binance Smart Chain , Tron and more to create their own standards like BEP20, TRC20 , but they are built upon the Base ERC20 Standard.
You can read more about ERC20 at : https://ethereum.org/en/developers/docs/standards/tokens/erc-20/
Transfer Problem:
Usually when you send any ERC20 Token from your wallet to another wallet , your wallet calls the “function transfer(address _to, uint256 _value) public returns (bool success)” from the underlying contract code to facilitate the transfer of tokens from your wallet to another wallet. Usually in such transaction only one contract operation is performed which is the function “transfer”. This transfer is mostly restricted and tokens can only be transferred by the transaction sender and only when the sender directly interacts with the token contract.
But in the case of most Dapp’s the transfer process needs to be completed along with several other Dapp specific operations in a single transaction, this is acheived by the user calling a function in the Dapp’s Smart Contract Code.
As the user interacts with the Dapp’s Smart Contract rather than directly interacting with the Token’s Smart Contract due to this the transfer function cannot be called by the Dapp’s Contract to transfer tokens from the user’s address to another address due to the sender restriction which is inplace to protect the user’s funds.
This is where approvals and transferfrom functions come through to enable Dapp’s to function securely and more efficiently.
function transferFrom(address _from, address _to, uint256 _value) public returns (bool success)
function approve(address _spender, uint256 _value) public returns (bool success)
function allowance(address _owner, address _spender) public view returns (uint256 remaining)
The Approve function allows a user to approve a value of tokens to a Spender to allow the Spender to spend the tokens on behalf of the User.
The Allowance function can be used to view the current Allowance of a Spender for a particular User.
The TransferFrom Function allows the Approved funds to be spent by the Spender.
The standard flow that almost all Dapp’s follow when you try any operation which requires a transfer of some tokens from your account to the Dapp’s Smart Contract (For example a Swap on Uniswap/Pancakeswap etc) is:
- Checking Allowance for the Dapp’s Smart Contract
- If Allowance is not present or is less than the transfer amount , send an approval of unlimited value for the Dapp’s Smart Contract. (Nowadays Approvals can be done with Signatures with any actual transaction as well for smart contracts supporting EIP-2612)
3. Call the Dapp’s Contract , which uses the TransferFrom function to transfer out the funds from the user’s wallet to Dapp’s Contract.
This is the standard flow followed by almost all Dapp’s to make sure smooth flow for the users , the initial unlimited alows Dapp’s to only ask for approvals once , also helps user’s save transaction fees on multiple approvals.
This approach is widely used but has been debated over time in the Defi community as this approval approach is being used by user’s without proper knowledge and concequences of their actions and are being used by malicious actors to lure unsuspecting users to approve amounts to malcious contracts to steal the funds.
Case Study:
Recently one of our lead developers (Lets call him Mr. Dev) received a message from one of their friends (Lets call him Mr. A) who is certainly new to Blockchain and have started investing in Defi for few months now. Mr. A had an issue where the tokens (Worth around $25,000 USD) which he bought recently through an Decentralized AMM Exchange suddenly vanished from their account , he tried to find any transaction sent from his account to view where the coins went but was unable to do so. So Mr. A asked for Mr. Dev’s help to find where the tokens went.
On initial inspection of the accounts activity on sites like BSCScan shows no transaction going through the Mr. A’s wallet , but on a closer look on the Bep20 Token Transfer section , there seems to be a transaction where another address used TransferFrom functionality to transfer the tokens out of Mr. A’s wallet to their own Wallet.
As Mr. Dev saw a transaction with TransferFrom function being called , Mr. Dev knew there must be an approval transaction from Mr. A’s account to allow the attacker to steal Mr. A’s funds. On closed inspection Mr. Dev found that the approval transaction was sent almost 1 month before the actual funds were stolen. On further inspection it was found that Mr. A fell into a Pancakeswap Phishing Attack, where Mr. A unsuspectingly approved the tokens to be spent by the attacker thinking the site asking for approval was Pancakeswap.
Over the course of our investigation we found that nowadays these types of attacks are happening almost too frequently and due to the anonymous nature , the attackers are almost never caught.
The only way to protect oneself from such attacks is to use Defi Apps with precaution and being Aware of each and every step.
How to Protect from such attacks:
- Understand each action has consequences: Reviewing each action you do in your wallet throughly is important as even the smallest ones can lead to loss of funds.
- Check Approval Amounts and Spenders and all transaction’s contract addresses: Check all details before providing any approval to any smart contract , Many wallets like Metamask , show all the specific details required for you to verify the transaction. You should check the spender contract on block explorers like bscscan , etherscan etc to verify the contracts ownership and code , most explorers have strict rules regarding the data they show regarding any contract address thus it is easier to verify if a contract you are interacting with is the one you want to interact with. Most Dapp’s provide their Contract Addresses publically as well so that users can be sure that they are interacting with the correct contracts. Most wallets allow adding these contracts addresses in Address books which would remove the need for verification for each transaction.
- Use multiple wallets: In an ideal situation it is always better to use atleast 2 different wallets , ideally one of the wallets should be a cold wallet which is not usually connected directly to the internet and another is a standard wallet which you use for any interactions with any Defi Application. Usually cold wallet’s are not readily available to everyone, but in that case 2 seperate addresses should still be used to keep the funds safe. Only one wallet should be used to interact with different applications and only required funds should remain in the this wallet. All other funds which are currently not used should remain in the second wallet which is never connected to any Application and only transactions for the second wallet should be sending/receving tokens/coins with the primary wallet. This ends up adding a bit of transaction cost but in the long run allows you to keep your funds safe.
Conclusion:
Defi is the new way for the world to take control of their freedom and finances but everyone should be aware of the dangers of not using the technology as intended and not being careful of the actions they perform on the blockchain , as the blockchain technology is immutable so are the actions performed. Thus once an action is confirmed on chain there is no going back. The best way to tackle all these issues is to be informed and also inform others of the pros , cons , best practices to follow to have a safe and profitable Defi Experience.
This article marks the start of Afraswap’s Educational Effort aimed to allow users to make informed decisions while interacting with blockchain. We will be publishing these posts regularly in the future and aim to contribute to make Blockchain a better place for everyone.