To create an upgradeable contract I have to use multiple proxies. The contract applies to Proxy A, then Proxy A applies to Proxy B. But delegatecall doesn't work in this case.
The simplified code of my contracts:
pragma solidity ^0.4.24;
contract A {
uint256 public value = 100;
function mul() public {
value *= 2;
}
}
contract B {
uint256 public value = 200;
address a;
constructor(address _a) {
a = _a;
}
function delegate() public {
a.delegatecall(bytes4(keccak256("mul()")));
}
}
contract C {
uint256 public value = 500;
address b;
constructor(address _b) {
b = _b;
}
function delegate() public {
b.delegatecall(bytes4(keccak256("delegate()")));
}
}
delegate()
function works only if it called at contract B
Thanks!
Best Answer
When, in
C
, you dob.delegatecall(
, what happens is that:B
C
And
B
andC
have the same storage layout:uint value
are located on storage slot0
.address a
andaddress b
located on storage slot1
So now you are executing
B
's code withC
's storage. And you aska.delegatecall(bytes4(keccak256("mul()")));
. What the underlying bytecode does is actually takeC
's value at storage slot1
, in effectb
, and use that asa
. So you are about todelegatecall
onB
again.And you call
mul()
onB
? There is no such function, so it does nothing. In fact, depending on your version of Solidity, this call would silently fail or not.It's working as expected :)