Resources

People often ask me "How did you learn how to hack?" The answer: by reading. This page is a collection of the blog posts and other articles that I have accumulated over the years of my journey. Enjoy!

yAcademy Proxies Research - 1145

yAcademyPosted 2 Years Ago
  • The article dives into the different proxy patterns and the security issues that can arise from this. First, there is the simple proxy. This makes a delegateCall to the implementation code. The delegateCall is used in order for the proxy to have the storage of the contract be decoupled from the code. The original proxy did not have the ability to upgrade though.
  • Obviously, we want to be able to upgrade the implementation address. This is done by storing the implementation address within the proxy contract and have an admin function to update it. An Initializeable Proxy is a proxy that can be initialized. This is necessary because the constructor will only run on deployment. So, if we set a new implementation, we need a way to initialize or update the state of new variables.
  • The patterns above have a few problems though. The proxy has an issue with storage collisions if a user is not careful. To account for this, EIP-1967 was created for unstructured storage. This stores the implementation address at a nearly random slot within the contract to ensure that collisions don't occur.
  • The second problem is function clashing when the proxy and implementation share a function selector. In the Transparent Proxy pattern, the admin of the contract hits a special section of code only meant for admins while the rest of the users hit the normal fallback code.
  • In all of the cases before, the upgrading was happening within the proxy contract. The Universal Upgradeable Proxy Standard (UUPS) flips this on its head. The upgrading functionality is in the implementation contract instead. This allows for editing the upgrade functionality, which can be a good thing.
  • The Beacon Proxy pattern is useful when there are a large amount of proxy contracts are needed. If the implementation address changed, then all of the proxies would need to change as well. Instead of the proxy->implementation flow, this pattern adds in a third contract. The flow is now proxy->beacon->implementation.
  • Diamond Proxy has a list of implementation contracts that point to different contracts depending on the function being called. This allows for smart contracts larger than the official size. However, this does have the limitation of storage being quite weird across the different contracts.
  • The Metamorphic contract is weird in that it doesn't have a proxy for updating. Instead, it calls selfdestruct then redeploys the contract to the same address. Honestly, this pattern makes the most sense to me for user engagement.
  • This is a really good article on the types of proxy contracts. I felt like they explained the pros, cons and gave example implementations on the way.