How to retrieve the logic address of a Minimal Proxy?

Hi, based on this answer, I am using the minimal proxy pattern with create2. This part is working just fine. I’d really like to be able to extract out the logic address of that minimal proxy, using Solidity, and I’m not sure how to go about it.

:computer: Environment

Using hardhat, and solidity 0.6.12

:memo:Details

Using create2 + minimal proxy, we have a setup that allows us to create many instances of a given contract. Then elsewhere, a separate contract of ours re-creates the create2 address and verifies it against msg.sender, to ensure that the caller is a genuine contract that we created in our factories (and it saves us from having to store all the addresses we created). That part all works well.

The thing is, we may later upgrade the original contract, which would change the “reference implementation” that the minimal proxy uses, and therefore change it’s contract code, and hence the generated create2 address. So instead of using our config to get the reference implementation, we wanted to pull out the address from the minimal proxy itself. But I think this would require calling some assembly such as mload on the minimal proxy address. This leads me to have two questions…

  1. Can I call assembly on another random contract? Or how can I access arbitrary storage slots on another contract?
  2. If I could do this, where is the logic address stored exactly on the minimal proxy?

I was looking at this, which gave me a decent idea of where it is within the bytecode, and then I think I could turn the bytes back into an address from there. But I’m more stuck on the first part, of how do I even try to reach into a minimal proxy from within Solidity?

Any help would be appreciated. Thanks!

PS: If this isn’t possible, a potentially workable alternative is to store all the reference implementations we ever use, and cycle through them when checking validity, though that seems lame. The other solution is to simply store all the addresses we create, but that could mean a lot of extra storage, and would kind of defeat the purpose of why we went with create2.

Hi @blakewest. It should be possible to do this. I’ll give the rough idea. You can retrieve the code of another contract through address(addr).code. This will be a bytes array in memory from which you can easily retrieve a slice, you would be using the indices that correspond to the address that is filled in when a minimal proxy is created. Then you can use abi.decode to convert it to an address.

Let us know if you can get it to work!

So, it turned out that using address(addr).code is a Solidity 0.8 feature. We’re on 0.6.12, and ended up determining that the cost of upgrading was not worth it just for this. We decided to use a simple mapping of all the instances of the contract that we’ve created. This will add a bit of storage cost on deployment, but we realized it won’t actually change the costs of later verifications, since we were going to have to read the logic contract address anyway. Which is no different from reading an address out of a mapping.

Thanks so much for your help though!

address(addr).code is just syntax for the extcodecopy opcode, which you can use in Solidity 0.6.

Glad you worked it out though.