Last week Uniswap introduced Permit2 that is a game-changer and the new chapter for all future dapps.
It this article I’m going to discuss a really contradictory topic which is the EIP2612’s security and how the central smart-contract called “Permit2” can affect many web3 users in the near future. Some says that this new concept will change the DeFi world by improving the UX by making the gas much cheaper and lowering the amount of interactions with the dapp. However, I’m going to show you the dark side of how those seemingly harmless EIP2612 signatures could be the opportunity for hackers to steal ERC20 tokens by fabricating these signatures with combination of Permit2 interactions.
Today’s topics are:
- What is EIP2612 signature?
- The initial version of Permit in ERC20 tokens, scam explanation, the implementation of this scam and the demo
- The second version of Permit, the phishing opportunity, the source code of the scam and the demo
- How to secure yourself from the phishing
Feel free to jump to any part you want. Let’s begin exposing Permits!
Disclaimer: This article and the GitHub repo is created ONLY FOR EDUCATIONAL PURPOSES.
What is EIP2612 ?
This is the extension of the EIP712 and is has a couple of tweaks that makes it the ERC20-centric. Simply saying, it improves the interaction with ERC20 tokens. The most powerful feature is the ability to pay for the gas fee with ERC20 tokens, rather than solely relying on ETH.
So, EIP2612 signature was created to become the main part for all dapps which use the “Permit” for the functionality. It becomes a kind of a relayer between the user and the dapp. As a typical EIP712, it is a signature window that has some kind of a message inside and it needs to be signed with the private key to approve the fact of confirmation of the data in the message box. After the signature, a data (proof) is generated. This proof can be used in smart-contract’s methods to execute some logic on behalf of the address that signed the executable data.
More details on EIP2612 you can find here (click). The screenshots of that signature will be further.
Permit1
If you want to swap your ERC20 tokens on some DEX, you need to have ETH on of your wallet in order to pay for the gas for the approval of your tokens to a DEX’s smart-contract. The problem is that sometimes user don’t have enough ETH for paying for the gas, or the cost of the gas for the approval transaction could be really high sometimes.
The solution for that is the additional functionality for the ERC20 structure. These kind of functionality should be really cheap in gas cost, be quicker than the approve() method and have the same level of security. Also, it should allow users to trigger these functionality without paying for the gas. These kind of extension for ERC20s is called the “Permit”.
Because of the Permit logic inside ERC20 structure, you can approve your tokens with a nice-looking EIP2612 signature. No more straightforward approvals!
For instance, on Uniswap, when you want to swap your USDC tokens, you need to give a permission to the Uniswap’s SwapRouter smart-contract. Here is the screenshot of the window you see. It is a EIP2612 signature.
In the above’s signature, I’m approving 15 USDC to the Uniswap’s SwapRouter02 smart-contract with some short-term deadline.
Briefly saying, this signature enormously improves the user experience! That’s why many popular ERC20 tokens are integrated the “Permit” functionality inside their smart-contracts.
Here’s the list (click) of all ERC20 tokens that have implemented Permit logic. You can find there some popular tokens like USDC or DAI.
However, besides the good side of that concept there’s also a bad side. There is a way to replicate this EIP2612 signature in order to get user’s permission to execute any code that they signed in the message box.
This is my implementation for the fake Permit signature:
In order to understand how the scam on the video works, let’s pretend that we are hackers and we want to create a scamming website to steal ERC20 tokens from others.
We are going to start from the permit() function that can be found in ERC20 token with Permit extension. Let’s take a look at this function.
We can see some interesting parameters there. For instance, the owner and the spender parameters. So, permit() allows to manually specify who is the owner of ERC20 token and who is going to have a permission to spend them.
The v, r and s parameters is the signature itself. Our “fake” EIP2612 signature window should have a body message that says that victim approves all of his token’s amount to the spender (us). By getting the victim’s signature from our hand-made EIP2612 window and splitting it into three components (v, r, s), we can reuse them for the permit() method.
For the next step we need to have any wallet to execute the transaction. Just by calling token’s permit() method and passing the data and the signature components (v, r, s) that we got from the signed data, we can easily send this transaction and pay for the gas ourselves.
After the transaction is mined, we are going to have the permission to spend victim’s tokens. The next step will be stealing these tokens by simply calling transferFrom() method.
That’s it, we successfully stole ERC20 tokens with only one nice-looking signature that victim signed.
The code for that scam, as well as for Permit2 you can find here (click).
Permit2
The initial approach for adding the “Permit” functionality to the ERC20 tokens is really good and working solution. Although, there is a problem that not every ERC20 token confirms the “Permit”. Due to this, there is two potential ways to bring this convenient approach in the space. The first one is to upgrade all the existing ERC20 tokens with “Permit” methods and include these methods into default ERC20 standard. There are A LOT of ERC20 tokens that already deployed to the network and changing the standard could turn out to be really bad idea.
The second solution is to develop a central smart-contract that is going to play a role of an intermediate between the tokens owners and dapps. This approach is the win-win because the web3 users can approve the tokens that they want to use in dapps to this central smart-contract and that’s it! After the approval, all the future interactions with dapps that also connected to this central smart-contract are going to be absolutely gasslees and really smooth.
That’s exactly what Uniswap did (click). They created this central smart-contract and called it “Permit2”.
However, the bad part is that this smart-contract has so much power, so hackers can access this power and use it for bad things. Let’s imagine that we are hackers one more time and try to implement the scam for stealing peoples tokens by interacting with Permit2 smart-contract.
This is what I created (video below). You can see familiar EIP2612 signature and what’s going on after it we going to deep dive further.
I surely say that this smart-contract is really powerful! There is a lot of various functions there and my solution is not very complex, I think the future scammers will create something more quick and reliable.
Let’s deep dive to understand how I replicated the signature and successfully stole ERC20 token from my another wallet.
In order to steal the tokens from the victim, we need to be sure that his tokens are approved to the Permit2 smart-contract. In the future adoption it won’t be a case, but right know, for testing purposes, I created a button that is calling the approve() method, and gives the permission for tokens to the Permit2 smart-contract.
After we 100% sure that the token we want to steal is approved to the Permit2, let’s think of a way to steal this token. Like in a previous part, the first thing that we need to do is to approve the victim’s token to our wallet. After the approval, transfer this token to us.
Let’s take a look at a method permit() from the Permit2 smart-contract:
This method is laying inside the AllowanceTransfer part and it gives the permission for the specific token and to the specific spender that needs to be manually entered into the PermitSingle struct.
The PermitSingle looks like this. And actually, there’s is another struct inside it called PermitDetails:
So the final message the victim have to sign in the “fake” EIP2612 signature looks like this:
After victim signs this message, we are getting the signature. That’s pretty much it. We have the PermitSignle data and the signature (the generated value from that data signed by the victim’s private key). Using these information, we can easily call permit() method in Permit2 smart-contract that you saw above. After calling this method, the smart-contract gives us the permission to spend the victim’s token.
When we have the permission, we need to transfer victim’s token to our address. In order to do it, we have to call another function called transferFrom():
This is really simple! Let’s just pass the parameters inside the transferFrom() and execute it. Yeaaa! We successfully stole the token!
The code of this scam you can find in my github repo (click)
How to protect yourself from getting scammed
In this part of the article let’s discuss how to protect yourself from getting scammed by bad people who not believe in new decentralized internet and trying to get rich from the honest people like us.
There is a several browser extensions out there that shows what is going on under the hood after you signing a message. I heard that @stelolabs created a neat extension. Another resource is of course the @RevokeCash, this is the most powerful tool out there. I also heard that they recently created an extension too. This is not the ad btw, just my recommendation.
Don’t ever trust anyone who offers you a help to revoke approvals or secure your wallet from scams. There’s a high chance that they are also scammers who want to get some data from you, like your private key. So be aware of this!
Conclusion
I can clearly see the new pattern towards we are moving right now, these central smart-contracts that becoming intermediates between two parties is a really workable and accurate solution. However, I think that the current state of crypto is not fully allows moving to this pattern.
For instance, this vulnerability of forking signature windows is really similar to the recent Opensea’s fake Seaport signature scam that lead to approximately $1 mill in lost.
BTW, the next article is going to be about Seaport Scam with the code examples, as you love, so subscribe to my twitter to not miss it!
Saying that web3 space is not ready yet, I mean the fact that there are many new users who don’t understand the technical part of how everything works here, those kind of people are the ones who buying expensive NFTs and then go to the random websites and signing random stuff there. And after they lose all of their assets, they are starting to complain that the whole idea of web3 is a scam. These people are still living in web2, they used to the phishing websites that wants to get so many data from you: username, password etc. On the other hand, web3 allows you to interact with the website only by one signature! One click!
This is only the beginning! I want you to be aware of the potential scams they are going to show up in the coming year. So stay safe!
Useful links
GitHub with my code for this article: All the code is on GITHUB Don’t hesitate leaving a star 🥹🤙
Follow me on twitter: @romanrakhlin
Top comments (0)