Starting our journey few months ago, we began with a comprehensive survey of smart contract security challenges and solutions. The reentrancy attack, arguably the most common and famous type of attack, was there from the get go. The ReentrancyGuard by OpenZeppelin has been around at least since beginning of 2017 to mitigate these kind of attacks. So we asked ourselves, how come a bug with such an easy mitigation still causes so much havoc?
Interestingly enough, we’ve noticed something even more disturbing: protocols that had already been implementing ReentrancyGuard, to some extent, are still being hacked by reentrancy!
Cream ($18.8m), Fei-Rari ($80m), BurgerSwap ($7.2m), and Orion ($3m), to name a few. All had a reentrancy guard in place, but failed to prevent the malicious reentrant call.
We scratched our heads in bewilderment and tried to triage this.
At first we thought it might be some kind of bug in the ReentrancyGuard contract, but it was not. It is a fairly simple concept and OZ made a tremendous job in refining it.
We came to the conclusion that the traditional reentrancy guard has some fundamental limitations that prevents it from providing a perfect prevention against reentrant calls:
As cyber security experts, we know that security counter measures are only as good as how it is being implemented, and this is exactly our way of thinking at SphereX.
We asked ourselves, is there a better implementation pattern for this crucial security element? Is there somehow a way for it to be incorporated in such a way that will prevent all the above problems and still be easily used?
The answer is yes!
Most of the protocols mentioned above were also using a proxy. Let’s imagine a conceptual protocol where a proxy is being used and the implementation is protected by a reentrancy guard:
In this traditional design every function in the implementation is accompanied with a nonReentrant modifier. Every implementation upgrade might break the consistency of the reentrancy check and might introduce new reentrancy bugs.
We would like to suggest a different approach. For the reentrancy guard to be incorporated in the proxy contract rather than in the implementation:
This way, we have one, non-distributed enforcement point to prevent Reentrancy!
This approach has some other cool features:
We took the liberty of implementing this. We took ReentrancyGuard and TransparentUpgradeableProxy as reference contracts and used them to do exactly that. This wasn’t without challenges (That you can read about at the bottom).
Interesting story, we decided to fully implement this during the awesome ETHDenver 2023 Hackathon. Thinking that the odds were small, we presented the project in the morning of the last day of the Hackathon, and then headed to the airport to catch a flight.
We watched the live broadcast of the closing ceremony finding out we were nominated as one of the best infrastructure projects in the Hackathon 😞
We felt like this is such a fundamental piece we have to release it for everyone to benefit, but keep in mind, this is the bare minimum. Web3 hacks are becoming more and more sophisticated and our analysis shows the current tools at hand just don’t cut it.
Some technical difficulties we were facing
Some caveats you should know before using this:
We’re releasing the reentrancy proxy for free use by the community, for a better secured Web3.0.
Here it is:
Ariel has over 12 years of software development and cybersecurity research experience. Before joining SphereX, Ariel was the co-founder and CEO of Realmode Labs, a boutique cybersecurity research firm.