Ethereum: Creating a Nested Function Call with createProxyWithNonce
When working with the Safe Proxy Factory on Ethereum, deploying a new Gnosis Safe can be a complex process. One common problem arises when trying to create a proxy for a single contract or function using the createProxyWithNonce
method.
In this article, we will dive into the specifics of how to use the createProxyWithNonce
method with nested functions and nonces.
Problem: Nested Function Calls
Let’s consider an example of deploying a simple Gnosis Safe that uses two contracts:
SafeContract
: This contract provides basic security features such as adding users to a whitelist.
MyContract
: This is the main contract that we want to proxy and implements our own logic.
To deploy both contracts via the Safe Proxy Factory using createProxyWithNonce
, we would need to create nested function calls:
contract MySafe {
function myFunction() internally returns () {
// Here's the custom logic...
}
}
SafeContract is SafeProxyFactory {
function safeFunction() public nonces[0] {
return myFunction();
}
function createProxyWithNonce(
_singleton,
initializer,
saltNonce
) internal override returns (MySafe) {
MySafe proxy = new MySafe(address(_singleton));
// Initialize the proxy with some data...
return proxy;
}
}
As you can see, we are creating nested function calls: createProxyWithNonce
is called recursively within another function. This approach has several problems:
- Nested function calls are not allowed: Recursive function calls are not supported in Solidity.
- Nonces are only valid for the first call: Since
createProxyWithNonce
creates a new instance ofMySafe
, we lose all nonces from the previous call. To fix this, we need to explicitly pass in the nonces.
Solution: Explicitly passing nonces
To solve the above problems, we can modify our approach as follows:
contract MySafe {
function myFunction() internally returns () {
// Here's the custom logic...
}
}
contract SafeContract is SafeProxyFactory {
function createProxyWithNonce(
_singleton,
initializer,
saltNonce
) public nonces[0] {
return new MySafe(address(_singleton));
}
function getProxy() internal view returns (MySafe) {
// Returns a proxy instance
}
}
In this modified approach:
- We pass
nonce[0]
to thecreateProxyWithNonce
method, which gets the nonce value for the first call.
- We also define a separate
getProxy()
function that returns a proxy instance. This allows us to return a proxy instance without having to rely on nonces.
Conclusion
To create nested function calls using createProxyWithNonce
, you must explicitly pass the nonces, either as a parameter or using an internal view property. This avoids recursive function calls and ensures that your contract is initialized correctly.
When deploying Gnosis Safe via Safe Proxy Factory, follow these guidelines when creating nested function calls:
- Pass the nonce explicitly in
createProxyWithNonce
methods.
- Use internal view properties to get proxy instances.