Proxy contracts and msg.sender

proxies
design

#1

Hi everyone. A question about Proxy contracts.
I have a contract A that makes calls to contract B, and B accepts only calls from A.

Now i want to add a proxy contract to A in order to make it upgradeable. All user transactions will be made to Proxy-A and delegated to Logic-A.

The address in msg.sender when contract B is reached, will be Proxy-A or Logic-A?


#2

Hey @AlexanderPoschenried! Good question :smile:

So, most proxy contract tend to use delegateCall meaning the msg.sender is maintained thoughout the transasction. So if I have a proxy to a contract, through using delegateCall the msg.sender stays as the original sender, not the proxy. This still works if its a proxy => proxy => logic.

Does that answer your question? :slightly_smiling_face:


#3

Thanks. But in my case the way is Proxy (A) => Logic (A) => Logic (B).
Logic(A) calls Logic (B) through a normal call, not a delegate call.

So i assume there the msg.sender changes from Proxy A address to Logic A address. Right?


#4

Oh, my bad.

Yes, if delegateCall is not used then msg.sender changes to the actual contract that called it.


#5

Hey @AlexanderPoschenried! If I understand correctly, then contract B will see ProxyA as msg.sender when it receives the call. Let’s say you have the following scenario:

contract A {
  B b;
  function callB() public {
    b.run();
  }
}

contract B {
  event Called(address caller);
  function run() {
    emit Called(msg.sender);
  }
}

Let’s say you deploy logic contracts A and B, and set up a proxy for A (called ProxyA, as you say). Then, when you call ProxyA.callB(), the event emitted in that transaction will be Called(ProxyA).

This is because delegatecall preserves the entire context except for the code, so any calls made from LogicA, if they were originated from ProxyA, will actually be advertised as having ProxyA for msg.sender.

Let me know if this is clear!


#6

@spalladino very clear, that example was very usefull.

Thanks both of you.