Thanks so much for sharing the use case, @gitpusha! Indeed, it would seem like the issue is with the double delegate call, as you say - that’s why you are seeing calls to the zero address. Assuming a delegatecall chain from UserProxy to OzProxy to Action:
1- UserProxy delegatecalls into OzProxy
2- OzProxy loads its implementation address from storage in a special slot
3- But the current state (including storage) is that of the original UserProxy
4- The special implementation slot is empty, so the implementation address loaded is zero
5- OzProxy delegatecalls into zero
My suggestion here would be to just build a registry that points to the latest version of each Action, and not rely on OzProxies at all. This way, when a user wants to execute a given action, you just query this registry for the address of the latest version of the
action contract, and execute it.
The SDK does provide support for this: if you
oz publish your project, it will create a set of contracts that act as a registry. Whenever you make a change to your contracts (ie your
actions,) you can
oz push to upload and register the latest versions. You can even use
oz bump to track multiple versions of your actions, and
oz freeze to guarantee that a version will be unchanged.
You can then inject the
App main contract to every
UserProxy, and use
App#getImplementation to get the latest version of an
action by name.
Do you think sth like this would work?