Defi Scams — Rug pull Analysis: Wallstreetswap.finance
Disclaimer: This article only aims to provide basic knowledge to the smart contract fraudulent schemes and prevent scams to grow and hurt the Defi community. This is NOT financial advice.
Introduction
Wallstreetswap.finance is another typical Defi protocol that allows you to swap, stake, and farm tokens. At first glance, nothing too out of the ordinary and looks very trustable because it has been audited (but deleted after rugged), has convincing and well-written documentation, and has the most crucial thing, the timelock contract.
The Audit problem
In the audit pdf file, it states that TechRate performs an audit of “smart contracts” but only shows one file — the “Pool” contract.
But in reality, Since the main Github repo is already gone and the pdf file contains nothing about the contract information, We really can’t determine whether the auditor audited the actual backdoored contact or not.
The Rug Pull
At around 11:30 AM UTC, February 15, 2021, Wallstreetswap.finance suddenly close its website and began the rug pull.
When the website has been closed, I thought that it will be another developer dump. Then we’ll have to manually unstake and remove the liquidity, and get our tokens back eventually. But that's not the case for this time.
In the LP token contract (for now on I’ll use BNB/BUSD for example), you can clearly see that the reserve, the actual balance of BNB and BUSD in the contract, is 0.
We can recheck this by going to the BNB contract and use the balanceOf
function to query back the LP contract’s balance. And it resulted in 0.
** Some of the pools reserve fund is not updated because the sync
function hasn't been called, So it has to be manually checked **
Then in the Contract owner wallet, we’ll call him Culprit “C” from now on, we can see various transactions being executed by him, transferring the LPs token to his wallet and swapping all of it to BNB on PCS, then transfer all of the 220370 BNB (Approx 5m$) to an unknown wallet.
After that, the funds are split up and vanish into Binance hub, where we can’t track it anymore.
Now we know that our funds are actually stolen this time. It's time to trace back to the root cause.
Tracing Back To The Root
Transfering token
We’ll start our progress by answering the question “How the duck can C withdraw our token!?”.
Looking into this transaction emitted log, C called some function that emits Transfer
, moving the token from src
address to dst
address with wad
value. In this case, from 0x3c8 address, our BNB/BUSD contract, to 0xa75, C address, with the value of 1834.95 Ether. (The wad is in Wei unit)
Then we seek the function that emits Transfer
in the BNB contract.
The only function that emits Transfer
istransferFrom
. Which is the line we can figure out what’s going on. The complicated thing is, how can he executed this function without being reverted? According to the if-statement in line 58, he NEEDS to have the allowance to transfer the token. So we know for sure he somehow got his hand on the LP contract allowance.
Liquidity Pool Contract (LP Contract)
Let me explain how adding liquidity normally works
- Execute the add liquidity function with the desired token and let the contract transfer your tokens to the contract balance
- The contract then mints you that LP token pairs that can be used in staking
- You lose both actual tokens, then you gain the corresponding LP token back
This means both of the tokens that you use to create LP token are not yours anymore and is now owned by the contract instead. Most of the time it’ll be fine, but not for this contract.
From the clue we have, we’ll skim the LP contract for abnormality about Approval
first.
We found something interesting.
What the duck is that sufficient check? Why would you approve _factory
with an unlimited amount? (uint(-1)
is maximum unsigned integer)
Something sketchy is going on.
The comment says //Called once by the factory at time of deployment
so we look for this function that ran when you created the LP contract. The contract that deploys this is WallStreetSwapFactory.
WallStreetSwapFactory, The Culprit
In WallStreetSwapFactory contract, line 396, createPair
is the function we are looking for. Now let’s take a closer look at it..
The thing looks fine until we reached line 406. The pair initialize with _factory
address of feeToSetter
. It means feeToSetter
address will have unlimited token approval in that pair. Then what’s the feeToSetter
? We’ll check it by querying feeToSetter()
Look familiar right? That’s the C address!
This explains why he can use transferFrom
function without it being reverted.
C, The contract owner, actually has access to everyone’s LP token the entire time!
Conclusion
The contract owner puts a backdoor code in the LP creation contract so he can have unlimited token approval to every LP pairs he created. Then he rugged, transferring every token from the LP pair contract to his own address, then bridged through Binance. This resulted in 5m$ TVL fraud.
That’s all for now. Remember to ape in responsibly and your funds will be SAFU, stay safe my fellow degens.
Feedback is always appreciated.