Do you know a simple signature in Metamask can drain your wallet?
A very experienced user (top 10 by Degen Score) lost almost 500k USDC in an exploit today.
You could be next...
A short thread how it happened and how you can avoid such exploits in future.
It was a quiet afternoon when Joe (name changed) noticed 469k USDC left his wallet.
It wasn't a simple transfer, which meant an attacker apparently didn't have access to Joe's wallet.
It was a malicious contract that drained all USDC from his address...
Here we need to pause the story to explain some technicalities.
USDC token is a contract on Ethereum. It has many functions which define how we interact with USDC and what can be done with it.
Let's focus on two functions:
When you move USDC (or other ERC20s) between wallets, you use transfer function.
It moves tokens from the caller (the address that calls the function) to other address.
To maliciously use transfer on your behalf, someone would have to get control over your wallet.
When you interact with contracts, they use transferFrom to move your tokens. They can take up to the allowance amount which you set in approve function.
If you allow a contract to spend infinite amount of USDC, it can take it all.
Back to the Joe's story...
The aforementioned contract interaction that drained Joe's USDC was indeed transferFrom function.
But transferFrom would only work if Joe had approved the contract to spend his USDC.
And Joe was 100% convinced he didn't approve anything...
Wait a moment...
DeBank history clearly shows infinite USDC approval for the malicious contract 10 minutes before the exploit...
Did Joe actually approve it?
Yes. But also no. Not directly.
Etherscan discloses that infinite approval wasn't approve function called by Joe himself.
It was permit function called by other address and it granted the malicious contract the approval to spend all Joe's USDC.
WTF? How can others approve contracts on your behalf?
Permit function was introduced to improve user experience on Ethereum.
It allows a user to modify approval amounts without submitting a transaction. A signature is sufficient.
With your signature anyone can call permit function and update your allowance for a spender.
You can see permit in action when you use 1inch dApp.
If you want to sell USDC, you don't have to approve it first.
All you need is to sign a message.
This signature grants 1inch the permission to spend all your USDC. 1inch won't do it but a malicious contract could.
Joe must have accidentally signed such a message on a malicious website.
Unfortunately, this time he used a hot wallet and signing was just one innocent-looking click.
With a hardware wallet, there would be a second-thought moment while signing a message on the external device.
With Joe's signature a malicious actor submitted a transaction with permit function.
It gave the malicious contract the permission to spend all USDC from Joe's wallet.
Then transferFrom function was called and the malicious contract drained the funds.