I found this in the official solidity docs.
The values of all members of msg, including msg.sender and msg.value can change for every external function call. This includes calls to library functions.
The "can change for every external function call" is too vague for me.
Does anyone know when it does change for an external function call?
My concrete example:
pragma solidity ^0.5.10;
contract A {
function foo() external view returns(address payable) {return msg.sender;}
}
contract B is A {
address payable public msgSender;
function bar() external {
// 3 ways of doing the same thing
msgSender = A.foo(); // does this work and who will be msgSender?
msgSender = this.foo(); // does this work and who will be msgSender?
msgSender = super.foo(); // does this work and who will be msgSender?
}
}
Please take all the code as is => in the 3 notations A.foo()
this.foo()
super.foo()
I am NOT talking to another deployed contract instance. With all 3 ways I want to showcase 3 (different but same) ways of calling external functions
(inherited
ones in this case) on a contract
from inside
(internally
) that same contract
. The 3 ways basically just vary in their scope
or explicitness I believe.
Back to my main question:
Who is the msg.sender
emitted in the EmitMsgSender
event
emitted by the call
to A/this/super.foo()
in my example?
Is it contract B
's address payable
or is it the address
that sent the tx
to B.bar()
?
By the way, it would make my life easier, if it were the original caller of the B.bar()
function, and not B
's address.
Thanks for your help!
Best Answer
Here is my answer, to my own questions after testing in
Remix
:A.foo()
does not work:TypeError Member "foo" not found or not visible after argument-dependent lookup in type(contract A)
super.foo()
except it says... lookup in contract super B
Both 1) and 2) could be expected from thedocs
that only listthis.f()
as a way to callexternal
functions from inside a contract.And now to the interesting part: Edits thanks to @smarx
this.foo()
works and it returns theaddress
ofcontract B
asmsg.sender
.=> When I call an
inherited
external
function
internally
(from inside the same contract), the context DID change themsg.sender
to thederived contract
'saddress
, who forwarded themessage
to itsbase
contract
'sexternal
function
via the specialthis.function()
syntax.The
msg.sender
is NOT preserved (as could be expected from thesolidity docs
).However, the docs are still ambiguous:
This seems to imply that sometimes it does not change. So: When does it change (in my example it did) and most of all when DOES IT NOT?
EDIT: Answer from @smarx (paraphrased)