The future of smart contract development is composability.
TL;DR https://epm.wtf
Last year I was experimenting with keeping NFT metadata entirely on-chain when I hit the 24kb EVM smart contract size limit. This limitation led me to try various workarounds like deploying libraries and additional contracts that call each other. It was messy to maintain and a nightmare to iterate on the contract code.
Searching for a better way, I stumbled on the (EIP-2535) Diamond Proxy Pattern, created by Nick Mudge, which changed everything. Upgradability, infinite contract size, shared contracts. My mind was blown. ๐คฏ
Since then, I've used the Diamond Pattern in all my smart contracts. Along the way I've developed a bunch of command line scripts to swap out functions ("diamond cuts") and automate some of the more tedious parts of iterating on and testing contracts. But it still felt clunky. And that's why I developed EPM.
The Vision ๐
With a few clicks on a webpage, combine smart contracts created by other people (or myself) into my own contract. Maximize re-usability, minimize attack surface, and DRY.
Features ๐ก
With EPM you can deploy a Diamond Proxy, attach facets to it, and then get even more granular by toggling functions on or off!
See it for yourself: https://epm.wtf/manage?address=0xcf169E3D03e46df50f609Ac3b49B66f453E5b6fc&chainId=137
Note: You wonโt be able to edit anything since you donโt own the contract.
Generate Code
Another area of development I found tedious was generating Typescript types for my contracts. With EPM you can download the combined types or ABI (all facet ABIs concatenated) with a click. Just for good measure, there's also a code example of integrating into a React app.
Bundles
Combine facets, toggle functions, and save that configuration for easy deployment by you or someone else!
Other Uses
EPM supports uploading and deployment of any smart contract. That means you can also use it for non-diamond contracts.
Use Cases
Inheritance By Overriding Functions
I've been experimenting with a sort of inheritance between contracts by having a base contract that implements a function, say handleSaleDistribution(...)
, and a second contract that implements the same function. I turn the function off in the base contract and on in the second contract. Then, from the base contract I can still call the method.
These don't have to both be contracts written by you. It could be that BaseFacet
was uploaded to EPM by someone else. You just need to create OverrideFacet
with a single function.
The catch with using this pattern is that it requires you to call the function a little differently in the base contract:
BaseFacet.sol
OverrideFacet.sol
Contract Administration
A simpler use case would be keeping an NFT mint off until a contract admin manually flips the switch on by enabling the corresponding function on the Diamond.
Shared Business Logic
It may already be obvious, but it's worth reiterating that Diamond Facets can be shared by multiple Diamond Proxies! This reduces the amount of duplicate code that needs to be deployed and by extension lowers deployment costs.
Nick Mudge just wrote about this
Related Projects
I'm part of Meem, a group of amazing people working to define the relationships between assets and humans with smart contracts. One of our other projects is Clubs which provides tools for online communities.
Behind the scenes, Clubs is using EPM and the Meem API to manage contracts and upgrades. That means you can start with a Clubs contract and customize it with EPM to suit your needs. For more info read how to Customize your Clubs Contract with EPM.
EPM Documentation ๐
The most up to date information about EPM, Meem, and Clubs.
Considerations ๐ค
Careless upgrades that use Diamond Storage can cause data corruption in the data stored in the contract (๐คฆโโ๏ธ speaking from experience here). It's important to understand exactly how storage works and follow best practices to prevent issues.
Next Steps ๐
Itโs still early and there's a bunch of improvements that can be made to EPM. Just a few that come to mind are...
Design / UX updates (in progress)
Support more constructor data types when deploying contracts
Verified contracts / creators
Show audits
Links to source code
Better "my contracts" contract management / searching
Facet compatibility info / warnings
Ensure upgrades do not destroy data
Decentralized data source
Currently Meem maintains the database for EPM but ideally it would live in a decentralized database or shared data storage like IPFS
Have an idea? Want to help develop EPM? Let's chat!
Links
Get in touch
Twitter: @kengoldfarb
Email: hello@kengoldfarb.com
Github: kengoldfarb
Farcaster: @kencodes