5

I have read EIP-1967 and i have study how work proxy contracts.

There is something i do not understand in EIP-1967.

Here is what i have understood:

  • Logic contract's storage variables are stored in proxy contract's memory.
  • Proxy contract contains his own storage variables
  • We can have a big problem if a logic contract variable has the same address than a proxy contract variable address.
  • For this reason, proxy contract variables are stored at 3 specific addresses (we have only 3 storage variables in proxy contract)
  • The goal of this EIP is to specify 3 addresses and to say to all compilers and EVM they should NEVER store a variable at this addresses.

In my opinion, people who wrote this EIP can choose any address. The important thing is that everyone agrees with this address choice (compilers, evm, ...). They choose this Addresses:

0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc (obtained as bytes32(uint256(keccak256('eip1967.proxy.implementation')) - 1))

0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50 (obtained as bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1))

0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103 (obtained as bytes32(uint256(keccak256('eip1967.proxy.admin')) - 1))

That's fine but i am wondering something: Why did they put a -1 in the address calcuation ?

The EIP says:

Furthermore, a -1 offset is added so the preimage of the hash cannot be known, further reducing the chances of a possible attack

I do not understand how this -1 offset can reduce any chance of possible attack... The hash is known by everybody. Can anyone explain which kind of attack is protected by this -1 ?

I have looked at an openzepplin implementation (TransparentUpgradeableProxy.sol) and here is what i saw:

bytes32 private constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;

constructor(...)
{
     assert(_ADMIN_SLOT == bytes32(uint256(keccak256("eip1967.proxy.admin")) - 1));
     ...
}

My question is: How this assertion can be false ? What is the goal of this assertion in the constructor ?

Thanks a lot

1
  • If you do not get an answer here, a good place to ask is forum.openzeppelin.org where maybe you can reach out some of the spec writers Jul 3 at 19:50
0

I do not understand how this -1 offset can reduce any chance of possible attack... The hash is known by everybody. Can anyone explain which kind of attack is protected by this -1 ?

It's an interesting question, and it has to do with the difference between a 'collision attack' and a 'preimage attack' when it comes to the risk of trying to maliciously create a scenario where there is a slot collision.

You can see a discussion of the logic leading to the -1 here:

https://github.com/ethereum/EIPs/pull/1967#issuecomment-489276813

That -1 comes from a suggestion by wjmelements, when he commented here:

I challenge the idea that 0x7050c9e0f4ca769c69bd3a8ef740bc37934f8e2c036e5a723fd8ee048ed3f8c3 is the best storage location. It has a known keccak preimage, unlike nearby 0x7050c9e0f4ca769c69bd3a8ef740bc37934f8e2c036e5a723fd8ee048ed3f8c2. It is harder to engineer an attack without a known preimage.

(notice that the only difference between those two addresses is the trailing 3 vs 2.)

response was

Good point. We chose a hash with such a preimage so that we knew that it would not collide with anything allocated by the Solidity or Vyper compilers (they both store mapping values in a preimage that starts with the slot number where the mapping is declared), but picking an entirely random value could be a good idea as well. Curious to see what others think about this!

As for your closing question,

How this assertion can be false ? What is the goal of this assertion in the constructor ?

use of assert() (as opposed to require()) indicates that this should never fail. I can only imagine this being necessary to make sure you didn't accidentally do something incorrect with inheritance, for example. The idea is, "verify this very important detail before continuing with deployment to mainnet--and if somehow this critical thing is wrong, abort."

0

In the case where you accidently overwrote _ADMIN_SLOT with something else, then the deployment of your contract would fail rather than succeed silently.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.