PRBProxy is a forwarding proxy that allows for the composition of Ethereum transactions on behalf of the contract owner, acting as a smart wallet that enables multiple contract calls within a single transaction. In Ethereum, externally owned accounts (EOAs) do not have this functionality because they cannot perform delegate calls.
Some key features of PRBProxy include:
DELEGATECALL
.Overall, PRBProxy is a powerful tool for transaction composition, providing numerous features and benefits not available through EOAs:
The concept of a forwarding proxy has gained popularity thanks to DappHub, the developer team behind the decentralized stablecoin DAI. DappHub created DSProxy, a widely used tool that allows for the execution of multiple contract calls in a single transaction. Major DeFi players like Maker, Balancer, and DeFi Saver all rely on DSProxy.
However, as the Ethereum ecosystem has evolved since DSProxy's launch in 2017, the tool has become outdated. With significant improvements to the Solidity compiler and new EVM OPCODES, as well as the introduction of more user-friendly development environments like Foundry, it was time for an update.
Enter PRBProxy, the modern successor to DSProxy; a "DSProxy 2.0", if you will. It improves upon DSProxy in several ways:
DELEGATECALL
.Using CREATE2 eliminates the risk of a chain reorg overriding the proxy contract owner, making PRBProxy a more secure alternative to DSProxy. With DSProxy, users must wait for several blocks to be mined before assuming the contract is secure. However, PRBProxy eliminates this risk entirely, making it possible to safely send funds to the proxy before it is deployed.
PRBProxyRegistry is deployed on 10+ chains at 0x584009E9eDe26e212182c9745F5c000191296a78. A sortable, searchable list of all available chains can be found at https://prbproxy.com/deployments. To request a deployment to a new chain, please open a GitHub issue. You can speed up the process by sending funds to cover the deploy cost to the deployer account: 0x3Afb8fEDaC6429E2165E84CC43EeA7e42e6440fF.
The ABIs can be found on https://prbproxy.com/abi, where they can be downloaded or copied to the clipboard in various formats, including:
Alternatively, you can:
cast interface 0x584009E9eDe26e212182c9745F5c000191296a78
This is the recommended approach.
Install PRBProxy using your favorite package manager, e.g., with Bun:
bun add @prb/proxy
Then, if you are using Foundry, you need to add this to your remappings.txt
file:
@prb/proxy/=node_modules/@prb/proxy/
This installation method is not recommended, but it is available for those who prefer it.
First, install the submodule using Forge:
forge install --no-commit PaulRBerg/prb-proxy@release-v4
Your .gitmodules
file should now contain the following entry:
[submodule "lib/prb-proxy"]
branch = "release-v4"
path = "lib/prb-proxy"
url = "https://github.com/PaulRBerg/prb-proxy"
Finally, add this to your remappings.txt
file:
@prb/proxy/=lib/prb-proxy/
Proxies are deployed via PRBProxyRegistry. There are multiple deploy functions available:
Function | Description |
---|---|
deploy |
Deploy a proxy for msg.sender |
deployFor |
Deploy a proxy for the provided owner |
deployAndExecute |
Deploy a proxy for msg.sender , and delegate calls to the provided target |
deployAndInstallPlugin |
Deploy a proxy for msg.sender , and installs the provided plugin |
deployAndExecuteAndInstall |
Deploy a proxy for msg.sender , delegate calls to the provided target, and installs the provided plugin |
Once the proxy is deployed, you can start interacting with target contracts by calling the execute
function on the proxy by passing the ABI-encoding
function signatures and data.
For the avoidance of doubt, PRBProxy is not an upgradeable proxy[^1]. It is a "forwarding" proxy whose sole purpose is to delegate calls to target and plugin contracts.
Both PRBProxyRegistry and PRBProxy are immutable contracts. Their source code cannot be changed once deployed.
See this repository's wiki page for guidance on how to write targets and plugins.
Integrating PRBProxy into a front-end app would work something like this:
getProxy
function on the registry to determine if the user already has a proxy.execute
function.However, this is just scratching the surface. For more examples of how to use PRBProxy in a frontend environment, check out the Frontends wiki. Additionally, Maker's developer guide, [Working with DSProxy][dsproxy-guide], provides an in-depth exploration of the proxy concept that can also help you understand how to use PRBProxy. Just be sure to keep in mind the differences outlined throughout this document.
While I have strict standards for code quality and test coverage, and the code has been audited by third-party security researchers, using PRBProxy may not be entirely risk-free.
Please be aware that this software is experimental and is provided on an "as is" and "as available" basis. I do not offer any warranties, and I cannot be held responsible for any direct or indirect loss resulting from the continued use of this codebase.
If you discover any bugs or security issues, please report them via Telegram.
This project is licensed under MIT.
[dsproxy-guide]: https://github.com/makerdao/developerguides/blob/9ded1b68228e6cd70885f1326349c6bf087b9573/devtools/working-with-dsproxy/working-with-dsproxy.md
[^1]: The term "proxy" can refer to different concepts in Ethereum, most notably upgradeable proxies, a design popularized by OpenZeppelin that enables contract owners to upgrade the contract's logic. It's critical to note that PRBProxy does not fall under this category of upgradeable proxies.