I am setting up a scope of work for auditors. I am using OpenZeppelin SDK 2.5.0 contracts, namely Proxy and ERC-20. I am looking to see what parts of the codebase have already gone through different audits.
Do you know any well-known and audited open source projects out there using the Zeppelin Proxy pattern?
Have there been any recently released tokens with Zeppelin token code and audits?
Also I want to look into other projects regarding their deployment practices, as manual deployment with a command line oz tool is somewhat cumbersome, when everything else is automated. But I have good ideas on this one.
We’ve reviewed lots of projects that use those two patterns. For the proxy pattern, we have two simple recommendations:
Don’t use it. It adds unnecessary complexity to most projects when the much simpler contract migration pattern would do. Proxy upgrades require manipulation of low-level Solidity, are filled with “footguns”, and have so many things that we have empirically seen go wrong. You can find our detailed review of each upgrade strategy on our blog.
If you have to use it, review its use with Slither. Slither, our static analysis framework for Ethereum smart contracts, includes the most extensive set of checks available for reviewing proxy upgrade code. We’ve been able to catalog 17 specific failure conditions for proxy upgrades and build checks for them into the slither-check-upgradeability utility. You can also use https://crytic.io to check many of these issues via a simple, Github-integrated web application.
Feel free to reach out if you have other questions. We’re on a Slack, Empire Hacking, in the #ethereum and #crytic channels.
Can you point me to an example implementation of ERC-20 token that supports upgradeable code, but does not use delegatecall? I prefer my toes staying inside my shoes.
I reviewed your blog posts and found them insightful. I have ok understanding own EVM internals and Solidity, so I understand the risks using delegatecall. That is why I am asking to see if there are other projects out there using it as well, so I can go and study. OpenZeppelin proxy pattern is attractive, because it avoids a lot of pitfalls that Slither upgrade check lists.
The problem with fixing to a certain Solidity compiler is a downside, but affordable one.
Among the first projects that launched using our proxy patterns, I can recall CENTRE (USDC), which is an ERC20 that is currently holding almost 700M USD (proxy code here). Another coin using our proxies is Paxos (token here), for a value of about 250M USD, and they were audited by three different firms, Trail of Bits among them!
Decentraland has also used our upgrade patterns for the marketplace and districts, which were audited here. More recently, PoolTogether also uses our upgrade patterns, and was audited both by us and Quantstamp. I understand that AZTECalso uses our proxies, same as Unlock Protocol, and SablierHQ. I'm sure I'm missing other high profile projects, but these are the ones that come to mind now.
Now, as Dan mentions, upgrades do introduce an additional complexity, but from what we've seen in most cases the benefits definitely surpass the hassles. Also, any "manipulaton of low-level Solidity" (I'm assuming Dan refers to assembly here) is isolated in the proxies themselves, and has been very carefully reviewed and audited, as well as widely used in production.
We have rolled out patterns such as unstructured storage or transparent proxies to ensure that it's extremely difficult to shoot yourself in the foot, unless you explicitly try to do so. And if you are using our CLI, we have embedded all necessary checks to make sure that an upgrade is safe - though we always strongly encourage to test them.
FWIW, I'm not a fan of the data separation pattern for upgrades. It produces very awkward code, it makes it impossible to reuse existing libraries, it's extremely easy to screw up just by forgetting an onlyOwner modifier in any of the functions in the storage contract, and is much more expensive in terms of gas as it requires an additional CALL for every read or write operation.
Last, I'm sad to see that the Trail of Bits post is still promoting FUD on our proxies, by touting an alleged vulnerability found on our implementation. The fact is that the post picks on an unreleased implementation of the proxies which was under development in our labs repository (a space dedicated to exchange ideas), and was not present in the released version. And not to mention that, if this had been an actual vulnerability, we would have appreciated a responsible disclosure privately first, instead of finding out via a public post.