Revest Protocol Exploit Recovery Plan
On March 27th, 2022, at 1:41 AM UTC, the Revest Protocol suffered an exploit in which roughly $2M worth of tokens (namely BLOCKS, ECO, and RENA) were stolen from our Ethereum-based token vault. As the team behind the creation of the Revest Protocol we are absolutely crushed that this has happened on our watch and we want to begin by assuring the impacted communities that we are doing everything in our power to make this right. This will not be an instant process but rest assured that we will not abandon you. This was a highly sophisticated attack on a vulnerability that went unnoticed during our Solidity.Finance audit as well as the multiple peer-reviews to which we subjected our code. We cannot retrieve what has been lost, but we pledge to continually do what is in our power to make this right.
To those who are not directly impacted by this exploit: your tokens are safe. All staked RVST and RVST-LPs are unaffected and Revest deployments on Fantom, Polygon, AVAX, and Syscoin are secure. Shortly after the attack began, we took swift actions to prevent the further loss of funds amidst the ongoing attack, and successfully prevented the theft of all staked RVST and RVST LP tokens. This required both freezing transfers of the RVST token and soft-locking the creation and withdrawal of FNFTs on all chains for which Revest stores value. Our team’s decisive action allowed us to ensure the rest of the attacks failed, mitigating further damage and preventing another series of malicious transactions only 70 seconds later.
As referenced above, our emergency response measures, specifically the freezing of transfers, was executed to save over 2 million additional dollars worth of RVST tokens. Secondarily, this allowed the team an environment in which to implement a fix for the underlying root cause while avoiding further losses. The Revest Protocol will be returned to full functionality as soon as possible, and we are working with additional security engineers to ensure that our patches will stop further efforts to exploit Revest ethereum based contracts.
Importantly, services which do not utilize the Revest Token Vault for their value storage but do utilize Revest’s FNFTs (such as our integration with Liquid Driver) are unaffected by this exploit and were never at risk. These services include our integration with Liquid Driver, our ERC-721 locker system, and our token swap-loan in partnership with The Poktopus.
We are so incredibly grateful to those who have assisted us with the difficult process of understanding the threat, neutralizing it, and developing the fixes necessary for ongoing function. This unfortunate event has not altered Revest’s core commitment to our mission: we remain more committed than ever to bringing FNFTs into the public eye and our future success will be all the more sound for having endured this crucible.
The remainder of this article will address the following:
- A full breakdown of all parties directly impacted
- A timeline of events from the exploit’s start through the team’s response
- Impact analysis for Revest on all other integrated chains
- Our proposed steps for addressing users and protocols impacted by this event
- Our plan for short-term and long term risk mitigation within our own systems
- How we will strengthen Revest and ensure we are at the forefront of security moving forward
Impact Statement of Lost Tokens
On March 27th, between 1:41 AM UTC and 2:22 AM UTC, roughly $2M worth of tokens were stolen from the Revest Protocol Token Vault. The first of these thefts were of 352,836 RenaSwap tokens worth $120,000 at the time of theft — these tokens remain in the hacker’s wallet, the only such tokens that have not been cashed out. Following this first attack, the hacker moved on to stealing 715,000,000 BLOCKS DAO tokens, the illegal sale of which resulted in $1.7M of stolen Ether for the hacker. For BLOCKS DAO, this resulted in the reduction of their price by at least 76% and the theft of over 500 Ethereum from their Liquidity Pool. The hacker finally targeted EcoFi with the theft of 7,700,000 ECO tokens, resulting in the theft of $100,000. Smaller amounts of ConstitutionDAO and LUKSO were also stolen during this attack, netting roughly an additional $10-$12K.
Following these thefts, the attacker swapped all tokens but RENA for Ether and transferred their ill-gotten funds to TornadoCash, a crypto-anonymizer that makes it impossible to trace where the stolen Ether has been taken. Revest has contacted the DEXes utilized for the swaps, but they do not keep IP logs and are unable to provide further assistance. It is exceedingly unlikely that direct recovery of the stolen funds from the criminal involved will be possible.
Timeline of Events
A detailed timeline of events has been set out to assist in understanding how this exploit was possible and to explain, with full transparency, the process by which the team responded to this emergency.
Mechanism Behind the Exploit
While some publications have already accurately identified the cause of the exploit, some have unfortunately (and likely unknowingly) distributed misinformation about its cause and the necessary solutions to prevent such an event from occurring again. To the end of offering information on the sophistication of the attack and the means by which it may be prevented in the future, we have included a summary of our findings.
The Revest Solidity stack is a complex piece of software. Revest.sol serves as the entry point for all transactions — from there, token locks are managed by LockManager.sol, token storage is handled by TokenVault.sol, and FNFT minting and burning is managed by FNFTHandler.sol, our ERC-1155 implementation. Several things are prerequisite to understand how an attack like this can occur: first off, when an ERC-1155 is transferred to an address, a callback to that address is implicitly sent “onERC1155Received” — for cases where a contract lives at the address having an ERC-1155 transferred to it, this allows the contract to execute arbitrary code when an ERC-1155 is sent to it. Next, within the context of Revest, there are three principal numbers that define an FNFT series. The first is the depositAmount, which represents how many ERC-20s a given FNFT is worth per FNFT. The next is the quantity or supply of ERC-1155s within that series: if a given series has a supply/quantity of 10 and a depositAmount of 5, it means that there are 10 identical FNFTs within that series, each worth 5 ERC-20 tokens, for a total of 50 ERC-20 tokens within that given series. Finally, the fnftId is an integer that acts as the identifier for a given series. All FNFTs with ID=7 will be identical to one another and are interchangeable with each other. Each one can be redeemed for depositAmount of the underlying ERC-20 token. The following graphic demonstrates a quantity/supply of 8 FNFTs with a depositAmount of 200 ERC-20s per FNFT.
To cultivate a further understanding of the Revest systems, we allow tokens containing a depositAmount of zero with real underlying ERC-20s to be created. This is both for consistency with the modular design offered by our OutputReceiver system and for allowing people to utilize FNFTs for collecting donations. This ties into the system we have in place for allowing additional deposits to any given FNFT, intended to allow for increasing the value of an underlying asset stored within an FNFT. The method that implements this, depositAdditionalToFNFT, accepts three parameters:
- fnftId to identify the relevant series
- Amount of tokens to deposit to the desired series per FNFT
- Quantity of FNFTs which should have additional deposits made to them
If the quantity of FNFTs chosen to have additional deposits made into them is less than the quantity of FNFTs the user owns, an additional FNFT series will be created at the next available ID. The FNFTs from the original series will be burned out of the users wallet in the desired quantity, and minted into their wallet from the new series, also in the desired quantity. The amount of tokens for that new series is then written into the FNFT configs stored in TokenVault.
So how did this happen?
The exploit began with the hacker creating an address-locked FNFT containing a zero amount of the desired asset and a quantity of 2 FNFTs. This was normal and expected behavior for the system, and in the linked example resulted in the creation of fnftId=1036. That the FNFT was locked to the hacker’s address enabled them to immediately withdraw tokens from all associated FNFTs, rather than having to wait a period of time. Within the same transaction (these multiple creation calls enabled by the hacker’s use of a custom-built attack-contract), the hacker then called mintAddressLock (Revest.sol entry point) a second time. This time, they 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 selected as the recipient of the minted FNFT, which was given ID=1037. This is where what could be termed a “reentrancy” (though strictly speaking, reentrancy targets the original function, while this exploit went after a secondary function) was performed.
The FNFTHandler contract suffers from a design flaw that went unnoticed during Revest’s audits and peer reviews: it increments the fnftsCreated variable after the mint operation has been called, rather than before. This variable is responsible for all calls to “getNextID()” in FNFTHandler, which is responsible for ensuring that the next ID used is not one which has already been utilized for storing an existing FNFT.
The uses of such a flaw are few and far between, but unfortunately, the exploiter was able to discover one-such use. When the mint() function was called during the second call, the onERC1155Received callback was sent to the attack-contract, which utilized that callback function to call “depositAdditionalToFNFT” within Revest.sol. This call targeted ID=1036, an amount of 1 ERC-20 token, and a quantity of 1 on a supply of 2. This resulted in depositAdditionalToFNFT believing that it needed to create a new series, which led to it making a call to “getNextId” — since 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 zero depositAmount of tokens. However, as there was no checking if an FNFT config already existed in the function, this was able to modify the config to contain a depositAmount of 1 ERC-20 of the targeted asset, rather than zero. Once the functions had all concluded their work, the attacker was left with an FNFT of ID=1037, with supply 7.7M, and depositAmount=1 token. They then withdrew all 7.7M FNFTs immediately, draining the vault of the targeted asset.
Alert and Response
The Revest Team was informed of this ongoing exploit at 2:24 UTC from the BLOCKS DAO development team. We immediately began operations to soft-lock the Revest Protocol contracts and limit any further damage. Our contracts on Ethereum follow industry-standard practices for systems containing large amounts of value and utilize a multisig for governance — this presented an initial stumbling block for the team, as only 2 of the necessary 4 parties were immediately able to sign a transaction to soft-lock the Revest Protocol. The Polygon system has hitherto not seen volume commensurate with full multisig governance — this proved useful in allowing our team to quickly soft-lock the Protocol on Polygon, making it the first Revest Protocol deployment to be secured. This was accomplished at 2:47 UTC by setting the Revest Address Registry’s pointer to Revest.sol to the burn address — all Revest contracts that handle value have a modifier within them called “onlyRevestController” on methods that are only supposed to be called by the Revest.sol contract. By setting this to the burn address, we were able to disable all interactions with TokenVault.sol, locking it out from interacting with the rest of the blockchain pending a security patch.
With concerns about the security of funds still locked in the Revest Token Vault on Ethereum at the forefront of the team’s mind, the decision was made to pause transfers of the RVST token at 3:13 UTC pending the remaining final signature needed on the multisig to soft-lock the Revest Protocol on Ethereum. This was done through special privileges delegated to a member of the team expressly for use in emergency circumstances such as these. At 3:14 UTC, exactly 70 seconds later, the hacker attempted to utilize Uniswap to contribute liquidity to the RVST-ETH pair — the pause on token transfers functioned as intended, and the hacker was unable to acquire the RVST-ETH LP tokens needed for targeting the RVST Liquidity Pool tokens stored within the Revest Token Vault. From Etherscan, we can see that 99.45% of RVST-ETH LP tokens are locked within the Revest Token Vault — if not for this 70 seconds of lead-time, the hacker would have been able to drain the entire RVST-ETH pair of liquidity, and the RVST token would have ceased to have any value. Pausing token transfers successfully prevented the loss of an additional 362.2 ETH ($1.15M). Despite multiple follow-up attempts, the hacker was unable to gain access to any RVST or RVST-ETH LP tokens.
The Revest team successfully soft-locked the Fantom contracts through the Fantom multisig at 3:44 UTC. Following that, the final Ethereum governor needed to soft-lock the Ethereum contracts was located and signed the necessary transaction to soft-lock the Ethereum contracts at 3:58 UTC. The AVAX contracts, a similar low-volume utilization scenario to the Polygon contracts, were successfully soft-locked at 5:17 UTC. The Syscoin contracts do not currently contain any value and were soft-locked by disabling frontend access.
During and following the immediate emergency response, the Revest Team formed an emergency response group comprising both core team members, members of the multisig, and Solidity experts Doublesharp, Jeffrey from BeethovenX, and Justin Bebis of the Bytemasons. We are incredibly grateful to them for their contributions during this response and the investigation that immediately followed the conclusion of active DevOps. A full investigation of the root cause of the problem continued until roughly 6:00 UTC, at which point a preliminary statement was issued and the team got some rest.
Early Takeaways
While it is far too early in the recovery process to know everything that we will ultimately take away from this terrible experience, there are a few lessons to be learned that can be put into immediate action:
- The Revest circuit-breaker system worked — that we were able to pause token transfers on RVST prevented the total draining of the RVST-ETH pool.
- More fallback methods of communications between the Revest governors will be one of our highest priorities moving forward. The Revest Gnosis governance system experienced a significant failure in communication that could have easily led to further losses of funds.
- One audit is never enough. There is no such thing as too many audits. More audits will be commissioned.
- Ongoing penetration testing is crucial. The formal establishment of improved QA systems within the Revest Team will be pursued.
- Better alert systems are needed. We were not made aware of this attack until well into its progress. Granted, the attack was clearly designed to target the protocol on Saturday night Eastern time / late night UTC. With better alert systems, we would have had more time to react quickly and stop events like these before they start.
Impact on Other Chains
While the Revest team chose to disable the Revest Protocol on all deployed chains, only tokens on Ethereum were impacted by this exploit. Tokens utilizing non-Revest-based token storage methods, such as the recently-launched xLQDR integration, do not utilize Revest’s contracts for value storage — rather, they utilize smart wallets and the xLQDR contract for value storage. These systems were never at risk from the vector utilized in this exploit.
Plan of Redress for Impacted Parties
The Revest Team feels a great deal of sympathy and grief over the loss of funds for those impacted by the failure of our system. While the Revest Protocol is a custodian-less system that exists as public infrastructure on blockchains where it is deployed, as the designers of this system, we are horrified to see the personal losses that those who put their faith in our work have suffered as a result of the criminal conduct of societal dregs.
While we do not possess the funds needed for meaningful financial recompense, and are not covered by any DeFi insurance provider, we promise to do everything within our power to make things as right as they can possibly be made. We do not yet know what form these actions will take and must speak to the development teams of each impacted protocol on a case-by-case basis to best determine a path forwards for all impacted individuals: this will be developed in the coming days, and we hope to have more specifics to share with you in the near future.Rest assured that you and your pain are not being overlooked, and that you will forever have a place in our community. We will assist in whatever capacity we are able.
Short-Term Damage Mitigation Strategy
The Revest Protocol will not allow this security flaw to be the defining moment of our story. With that in mind, we are setting out on the road to recovery immediately. For today and the immediate future, our goal is to patch the security vulnerability that enabled this exploit, reverse the soft-lock on Revest contracts across all chains, and unpause the transfers of RVST tokens. For immediate deployment, we are preparing a new version of Revest.sol with the universal use of reentrancy guard pending additional audits. Additionally, this upgraded contract will contain security features to prevent the overwriting of existing FNFT configs by methods such as split and depositAdditional. This patch will be subjected to rigorous peer-review prior to deployment, and sent in for an instantaneous audit by Solidity Finance, who currently possess the best understanding by auditors of our codebase. Once this patch has been judged secure by respected third parties and deployed, the contracts will be restored to functionality and the Revest token will be unfrozen. Our timeline for this is between Mar 27, 2022 and Mar 28, 2022.
Following this deployment and reactivation, we will move to more intermediate-term steps, which will include the replacement of all existing FNFTHandler with upgraded versions that do not suffer from the checks-effects-interactions violation which was utilized in this attack. We believe proper reentrancy guards and null-checkers will invalidate all potential vectors for further exploitation, but we are not going to take any chances. This is a more invasive procedure and will require us to spend a significant amount of Ethereum re-minting all FNFTs to their respective holders. However, we believe that is a necessary step in reestablishing trust with our community and those impacted by this exploit.
The recently-launched Revest Fee Engine will resume revenue generation following the reactivation of all relevant contracts.
Long-Term Risk Management Strategy
We are not satisfied with the status-quo. It is clear to us that multiple internal failures led to a situation where an exploit of this level was possible to execute against our system. To address this moving forwards:
- Our team will be commissioning multiple additional audits of the Revest Protocol codebase via multiple audit firms. As security industry leaders both TrailOfBits and OpenZeppelin audits are our desire, and welcome any assistance in contracting them for the highest security assurances that we can provide.
- We will be forming an internal group to investigate the feasibility of offering automated insurance on token storage within our system and investigating which reputable protocols are in a position to provide us with such a solution.
- We will be adjusting our internal design patterns to emphasize further decentralization within our value-storage architecture. Our solution with LQDR utilizes smart wallets in a manner that makes centralized attacks far more difficult to pull off — we want to explore how this solution can be applied for our Token Vault system.
- We will be seeking out workshops from Solidity experts on internal best-practices and how to implement ongoing penetration testing of our own systems.
- We will be exploring hiring a consultant to instruct our team on internal best-practices for IT security. Though off-chain security failures played no role in this exploit, we feel that by better instilling a culture of caution and cybersecurity awareness in our team we can better be prepared to avoid similar situations in the future.
- We will be improving the connectivity of our Gnosis Multisig governors group and designing similar functionality into the Revest DAO as we move into a fully decentralized organization. Better communication and more avenues of contact will be formally implemented into all current and future Revest governance systems.
- Circuit breakers will be implemented for the protocol in a way that allows one individual to throw a “switch” to disable all transactions but requires multiple sign-offs to re-enable them.
- We will be implementing automated alerts for large-value movements out of TokenVault. Had such systems existed, due to the Gnosis disconnectivity, it is unlikely that anything more could have been done, but the latency between this exploit occurring and the team being made aware should be reduced. We will be seeking automated alert systems for high-volume token movement.
Closing Statement
To our users and protocol partners,
Words cannot properly express the depth of my sorrow, the crush of remorse and shock that I feel over this. For nearly a year now, I have dedicated my time, my passion, and my energy to the creation of this protocol. From a small dream in the mind of a man who had spent years trying to cram round pegs into square holes, Revest has grown from a crazy idea into the next frontier in DeFi development. I have felt so proud the past few weeks, hearing the name FNFT mentioned all across crypto-Twitter; people have finally begun to “get it” — and now, this. The hopes and dreams of everyone involved in the monumental effort that went into bringing Revest from the drawing board onto the blockchain, battered, bloodied, and bruised by the actions of a lowly thief. People who believed in my dream, who believed in the people I brought in to make it a reality, suffering. It feels like a bad dream — a part of me simply wants to run away from it all. However, that isn’t an option. For everyone who put their trust in our creation, there has to be some semblance of justice. We can’t stop now, nor are we going to.
I promise you that however long it takes, we will make this right. I do not know how long it will take, nor what paths we will travel together, but the Revest Protocol and the Revest Team aren’t going to stop building. NFTs weren’t meant for art, they are so clearly meant to be used in finance, that to stop now would be a disservice to those who have just now lost so much. We can and will move beyond this crucible as burned and scarred as heat and pressure can make men, but all the stronger for the pain of enduring it. The success we find through our creativity we’ll share with those who’ve suffered from this — we are not going to leave our friends and partners behind. The Revest Team is not going anywhere — nor am I.
Rob Montgomery
Founder and CEO
Revest Finance
Post-Script
We would like to extend a special thanks to Doublesharp, Crypto_Clay, Justin Bebis, Jeffrey from Beethoven X, FTMAlerts, Jinx, and several other community contributors, and/or developers, who assisted in the emergency response and management of this crisis. Your friendship and the support that you offered us through this storm are enduring testaments to the strength of your character, and we are honored to know you.
Thank you,
The Revest Team