Key Takeaway:
- Protocol was exploited on 27 March 2022, and tokens worth $2 Million Stolen.
The Event
On March 27th, 2022, at 1:41 AM UTC, the Revest Protocol was victimized by an exploit. In the exploit, approximately $2 million in tokens (specifically BLOCKS, ECO, and RENA) were stolen from our Ethereum-based token vault.
According to their Revest Protocol Exploit Recovery Plan those who have not been directly affected by this exploit, their tokens are safe. RVST and RVST-LP stakes are unaffected, and Revest deployments on Fantom, Polygon, AVAX, and Syscoin are safe.
According to Revest, the first of these thefts involved 352,836 RenaSwap tokens worth $120,000 at the time of the theft. These tokens, the only ones that have not been cashed out, remain in the hacker’s wallet. Following this first attack, the hacker stole 715,000,000 BLOCKS DAO tokens, which he illegally sold for $1.7 million in stolen Ether. This resulted in a 76% drop in BLOCKS DAO’s price and the theft of over 500 Ethereum from their Liquidity Pool.
The hacker eventually targeted EcoFi and stole $7,700,000 ECO tokens, totaling $100,000. During this attack, smaller amounts of ConstitutionDAO and LUKSO were also stolen, netting an additional $10-$12K.
Following these thefts, the attacker swapped all tokens except RENA for Ether and transferred their looted funds to TornadoCash. Revest contacted the DEXes used for the swaps, but they do not keep IP logs and are unable to assist further. It is extremely unlikely that the stolen funds can be recovered directly from the criminal involved.
How did the Exploit happen?
The hacker began the exploit by creating an address-locked FNFT with a zero amount of the desired asset and a quantity of two FNFTs. This was normal and expected system behavior, which resulted in the creation of fnftId=1036. Because the FNFT was locked to the hacker’s address, they were able to withdraw tokens from all associated FNFTs immediately rather than having to wait a period of time. The hacker then called mintAddressLock (Revest.sol entry point) a second time within the same transaction (these multiple creation calls enabled by the hacker’s use of a custom-built attack contract).
This time, the exploiter choose to mint 7.7M copies of the desired FNFT again, with a depositAmount of zero tokens and again designated in the targeted asset. Once again, their attack contract was chosen as the recipient of the newly minted FNFT, which was assigned ID=1037. This is where a “reentrancy” (Reentrancy targets the original function, whereas this exploit went after a secondary function) was carried out.
The FNFTHandler contract has a design flaw that was overlooked during Revest’s audits and peer reviews: it increments the fnftsCreated variable after the mint operation is called, rather than before. This variable is in charge of all calls to “getNextID()” in FNFTHandler, which ensures that the next ID used is not one that has already been used to store an existing FNFT.
The exploiter was able to discover one such use despite the fact that such flaws are few and far between. The onERC1155 signal was activated when the mint() function was called during the second call. The received callback was sent to the attack contract, which used it to call “depositAdditionalToFNFT” within Revest.sol.
This call targeted ID=1036, 1 ERC-20 token, and a quantity of 1 out of a supply of 2. DepositAdditionalToFNFT assumed that it needed to create a new series, so it called “getNextId”, because the fnftsCreated variable had not been incremented at this point in the process, this returned ID=1037, which already had a supply of 7.7M and a depositAmount of tokens of zero.
However, because there was no checking in the function to see if a FNFT config already existed, this was able to modify the config to contain a depositAmount of 1 ERC-20 of the targeted asset, rather than zero. When all of the functions finished their work, the attacker was left with a FNFT with ID=1037, supply 7.7M, and depositAmount=1 token. They then immediately withdrew all 7.7M FNFTs, draining the vault of the targeted asset.