What other constants depend on the current call like msg.sender?
I recently noticed that msg.sender
isn't always the original caller's address (see here). It's the address of the current call. So if foo()
calls bar()
, then msg.sender
in bar()
will be the address of the contract containing foo()
.
My questions are:
- Are there any other constants that depend on the current call? Full list: https://solidity.readthedocs.io/en/latest/units-and-global-variables.html#special-variables-and-functions
- What's the best way to get the original sender's address?
contract-design contract-invocation constant
add a comment |
I recently noticed that msg.sender
isn't always the original caller's address (see here). It's the address of the current call. So if foo()
calls bar()
, then msg.sender
in bar()
will be the address of the contract containing foo()
.
My questions are:
- Are there any other constants that depend on the current call? Full list: https://solidity.readthedocs.io/en/latest/units-and-global-variables.html#special-variables-and-functions
- What's the best way to get the original sender's address?
contract-design contract-invocation constant
add a comment |
I recently noticed that msg.sender
isn't always the original caller's address (see here). It's the address of the current call. So if foo()
calls bar()
, then msg.sender
in bar()
will be the address of the contract containing foo()
.
My questions are:
- Are there any other constants that depend on the current call? Full list: https://solidity.readthedocs.io/en/latest/units-and-global-variables.html#special-variables-and-functions
- What's the best way to get the original sender's address?
contract-design contract-invocation constant
I recently noticed that msg.sender
isn't always the original caller's address (see here). It's the address of the current call. So if foo()
calls bar()
, then msg.sender
in bar()
will be the address of the contract containing foo()
.
My questions are:
- Are there any other constants that depend on the current call? Full list: https://solidity.readthedocs.io/en/latest/units-and-global-variables.html#special-variables-and-functions
- What's the best way to get the original sender's address?
contract-design contract-invocation constant
contract-design contract-invocation constant
edited Jan 24 at 19:10
Rob Hitchens B9lab
27.2k64480
27.2k64480
asked Jan 24 at 17:53
Justin HarrisJustin Harris
1165
1165
add a comment |
add a comment |
3 Answers
3
active
oldest
votes
msg.data
, msg.sender
, msg.sig
, and msg.value
will depend on the current call.
tx.origin
is the original sender of the transaction (EOA = Externally Owned Account).
Note that the msg.*
variables are only changed if you have
this.fn()
or
someOtherContractRef.fn()
Internal calls within the contract (without this.
) will not change msg.*
variables.
add a comment |
Adding to @ivicaa's and @Lauri's answer.
What's the best way to get the original sender's address?
tx.origin
is a security concern and not recommended. Relying on it also ensures that contracts cannot be clients of your contract since a contract can never be the tx.origin. This limitation seriously constrains your dapp since it includes multi-signature wallet contracts and since there are usually desirable use-cases where the "user" could be another contract.
It's not a simple issue. This thread may shed some light on the considerations: https://github.com/ethereum/solidity/issues/683
tx.origin
is almost never useful. This is the most subjective point, but I have yet to come across a use of tx.origin that seemed legitimate to me. I welcome counter-examples, but I've written dozens or hundreds of smart contracts without needing it, and I have never heard of anyone else needing it either.
Instead, pass the msg.sender
into functions that are concerned with the transaction signer. This implies that the called contract trusts the sending contract to tell the truth. The called contract should not naively listen to anything, but rather trust only whitelisted contracts that form part of your system.
function somethingOnBehalfOfSomeoneElse(address user) public onlyTrustedContracts {...
Hope it helps.
That's very helpful. How about doing stuff like:modifier onlyOwner() { require(msg.sender == owner || tx.origin == owner, "Sender is not the owner."); _; }
? Could that be a problem too?
– Justin Harris
Jan 28 at 16:25
My understanding istx.origin
can be overwritten by a determined adversary so I've learned to just disregard it and carry on as though it doesn't exist. I would call the example function withotherContact.somethingOnBehalfOfSomeoneElse(msg.sender)
so my contract relies exclusively on values I believe are trustworthy.
– Rob Hitchens B9lab
Jan 28 at 17:00
add a comment |
All of the msg
constants depend on the currenct scope (contract). Their value remains the same in the same contract (even in different functions) but if you call another contract the values change accordingly.
You can see them here in action:
pragma solidity ^0.5.0;
contract A {
event Data(bytes a);
event Sig(bytes4 a);
event Val(uint a);
function a() public payable {
emit Data(msg.data);
emit Sig(msg.sig);
emit Val(msg.value);
b();
B b = new B();
b.c();
}
function b() public payable {
emit Data(msg.data);
emit Sig(msg.sig);
emit Val(msg.value);
}
}
contract B {
event Data(bytes a);
event Sig(bytes4 a);
event Val(uint a);
function c() public payable {
emit Data(msg.data);
emit Sig(msg.sig);
emit Val(msg.value);
}
}
As for the original sender, you can simply use tx.origin
. Note that this is very rarely used as using it may ruin functionality of some proxy contracts etc.
Thanks your answer is very good too but I accepted the other because it gave some details about the use ofthis
.
– Justin Harris
Jan 24 at 19:06
add a comment |
Your Answer
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "642"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fethereum.stackexchange.com%2fquestions%2f66082%2fwhat-other-constants-depend-on-the-current-call-like-msg-sender%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
msg.data
, msg.sender
, msg.sig
, and msg.value
will depend on the current call.
tx.origin
is the original sender of the transaction (EOA = Externally Owned Account).
Note that the msg.*
variables are only changed if you have
this.fn()
or
someOtherContractRef.fn()
Internal calls within the contract (without this.
) will not change msg.*
variables.
add a comment |
msg.data
, msg.sender
, msg.sig
, and msg.value
will depend on the current call.
tx.origin
is the original sender of the transaction (EOA = Externally Owned Account).
Note that the msg.*
variables are only changed if you have
this.fn()
or
someOtherContractRef.fn()
Internal calls within the contract (without this.
) will not change msg.*
variables.
add a comment |
msg.data
, msg.sender
, msg.sig
, and msg.value
will depend on the current call.
tx.origin
is the original sender of the transaction (EOA = Externally Owned Account).
Note that the msg.*
variables are only changed if you have
this.fn()
or
someOtherContractRef.fn()
Internal calls within the contract (without this.
) will not change msg.*
variables.
msg.data
, msg.sender
, msg.sig
, and msg.value
will depend on the current call.
tx.origin
is the original sender of the transaction (EOA = Externally Owned Account).
Note that the msg.*
variables are only changed if you have
this.fn()
or
someOtherContractRef.fn()
Internal calls within the contract (without this.
) will not change msg.*
variables.
edited Jan 24 at 19:10
answered Jan 24 at 18:49
ivicaaivicaa
5,3281937
5,3281937
add a comment |
add a comment |
Adding to @ivicaa's and @Lauri's answer.
What's the best way to get the original sender's address?
tx.origin
is a security concern and not recommended. Relying on it also ensures that contracts cannot be clients of your contract since a contract can never be the tx.origin. This limitation seriously constrains your dapp since it includes multi-signature wallet contracts and since there are usually desirable use-cases where the "user" could be another contract.
It's not a simple issue. This thread may shed some light on the considerations: https://github.com/ethereum/solidity/issues/683
tx.origin
is almost never useful. This is the most subjective point, but I have yet to come across a use of tx.origin that seemed legitimate to me. I welcome counter-examples, but I've written dozens or hundreds of smart contracts without needing it, and I have never heard of anyone else needing it either.
Instead, pass the msg.sender
into functions that are concerned with the transaction signer. This implies that the called contract trusts the sending contract to tell the truth. The called contract should not naively listen to anything, but rather trust only whitelisted contracts that form part of your system.
function somethingOnBehalfOfSomeoneElse(address user) public onlyTrustedContracts {...
Hope it helps.
That's very helpful. How about doing stuff like:modifier onlyOwner() { require(msg.sender == owner || tx.origin == owner, "Sender is not the owner."); _; }
? Could that be a problem too?
– Justin Harris
Jan 28 at 16:25
My understanding istx.origin
can be overwritten by a determined adversary so I've learned to just disregard it and carry on as though it doesn't exist. I would call the example function withotherContact.somethingOnBehalfOfSomeoneElse(msg.sender)
so my contract relies exclusively on values I believe are trustworthy.
– Rob Hitchens B9lab
Jan 28 at 17:00
add a comment |
Adding to @ivicaa's and @Lauri's answer.
What's the best way to get the original sender's address?
tx.origin
is a security concern and not recommended. Relying on it also ensures that contracts cannot be clients of your contract since a contract can never be the tx.origin. This limitation seriously constrains your dapp since it includes multi-signature wallet contracts and since there are usually desirable use-cases where the "user" could be another contract.
It's not a simple issue. This thread may shed some light on the considerations: https://github.com/ethereum/solidity/issues/683
tx.origin
is almost never useful. This is the most subjective point, but I have yet to come across a use of tx.origin that seemed legitimate to me. I welcome counter-examples, but I've written dozens or hundreds of smart contracts without needing it, and I have never heard of anyone else needing it either.
Instead, pass the msg.sender
into functions that are concerned with the transaction signer. This implies that the called contract trusts the sending contract to tell the truth. The called contract should not naively listen to anything, but rather trust only whitelisted contracts that form part of your system.
function somethingOnBehalfOfSomeoneElse(address user) public onlyTrustedContracts {...
Hope it helps.
That's very helpful. How about doing stuff like:modifier onlyOwner() { require(msg.sender == owner || tx.origin == owner, "Sender is not the owner."); _; }
? Could that be a problem too?
– Justin Harris
Jan 28 at 16:25
My understanding istx.origin
can be overwritten by a determined adversary so I've learned to just disregard it and carry on as though it doesn't exist. I would call the example function withotherContact.somethingOnBehalfOfSomeoneElse(msg.sender)
so my contract relies exclusively on values I believe are trustworthy.
– Rob Hitchens B9lab
Jan 28 at 17:00
add a comment |
Adding to @ivicaa's and @Lauri's answer.
What's the best way to get the original sender's address?
tx.origin
is a security concern and not recommended. Relying on it also ensures that contracts cannot be clients of your contract since a contract can never be the tx.origin. This limitation seriously constrains your dapp since it includes multi-signature wallet contracts and since there are usually desirable use-cases where the "user" could be another contract.
It's not a simple issue. This thread may shed some light on the considerations: https://github.com/ethereum/solidity/issues/683
tx.origin
is almost never useful. This is the most subjective point, but I have yet to come across a use of tx.origin that seemed legitimate to me. I welcome counter-examples, but I've written dozens or hundreds of smart contracts without needing it, and I have never heard of anyone else needing it either.
Instead, pass the msg.sender
into functions that are concerned with the transaction signer. This implies that the called contract trusts the sending contract to tell the truth. The called contract should not naively listen to anything, but rather trust only whitelisted contracts that form part of your system.
function somethingOnBehalfOfSomeoneElse(address user) public onlyTrustedContracts {...
Hope it helps.
Adding to @ivicaa's and @Lauri's answer.
What's the best way to get the original sender's address?
tx.origin
is a security concern and not recommended. Relying on it also ensures that contracts cannot be clients of your contract since a contract can never be the tx.origin. This limitation seriously constrains your dapp since it includes multi-signature wallet contracts and since there are usually desirable use-cases where the "user" could be another contract.
It's not a simple issue. This thread may shed some light on the considerations: https://github.com/ethereum/solidity/issues/683
tx.origin
is almost never useful. This is the most subjective point, but I have yet to come across a use of tx.origin that seemed legitimate to me. I welcome counter-examples, but I've written dozens or hundreds of smart contracts without needing it, and I have never heard of anyone else needing it either.
Instead, pass the msg.sender
into functions that are concerned with the transaction signer. This implies that the called contract trusts the sending contract to tell the truth. The called contract should not naively listen to anything, but rather trust only whitelisted contracts that form part of your system.
function somethingOnBehalfOfSomeoneElse(address user) public onlyTrustedContracts {...
Hope it helps.
answered Jan 24 at 19:11
Rob Hitchens B9labRob Hitchens B9lab
27.2k64480
27.2k64480
That's very helpful. How about doing stuff like:modifier onlyOwner() { require(msg.sender == owner || tx.origin == owner, "Sender is not the owner."); _; }
? Could that be a problem too?
– Justin Harris
Jan 28 at 16:25
My understanding istx.origin
can be overwritten by a determined adversary so I've learned to just disregard it and carry on as though it doesn't exist. I would call the example function withotherContact.somethingOnBehalfOfSomeoneElse(msg.sender)
so my contract relies exclusively on values I believe are trustworthy.
– Rob Hitchens B9lab
Jan 28 at 17:00
add a comment |
That's very helpful. How about doing stuff like:modifier onlyOwner() { require(msg.sender == owner || tx.origin == owner, "Sender is not the owner."); _; }
? Could that be a problem too?
– Justin Harris
Jan 28 at 16:25
My understanding istx.origin
can be overwritten by a determined adversary so I've learned to just disregard it and carry on as though it doesn't exist. I would call the example function withotherContact.somethingOnBehalfOfSomeoneElse(msg.sender)
so my contract relies exclusively on values I believe are trustworthy.
– Rob Hitchens B9lab
Jan 28 at 17:00
That's very helpful. How about doing stuff like:
modifier onlyOwner() { require(msg.sender == owner || tx.origin == owner, "Sender is not the owner."); _; }
? Could that be a problem too?– Justin Harris
Jan 28 at 16:25
That's very helpful. How about doing stuff like:
modifier onlyOwner() { require(msg.sender == owner || tx.origin == owner, "Sender is not the owner."); _; }
? Could that be a problem too?– Justin Harris
Jan 28 at 16:25
My understanding is
tx.origin
can be overwritten by a determined adversary so I've learned to just disregard it and carry on as though it doesn't exist. I would call the example function with otherContact.somethingOnBehalfOfSomeoneElse(msg.sender)
so my contract relies exclusively on values I believe are trustworthy.– Rob Hitchens B9lab
Jan 28 at 17:00
My understanding is
tx.origin
can be overwritten by a determined adversary so I've learned to just disregard it and carry on as though it doesn't exist. I would call the example function with otherContact.somethingOnBehalfOfSomeoneElse(msg.sender)
so my contract relies exclusively on values I believe are trustworthy.– Rob Hitchens B9lab
Jan 28 at 17:00
add a comment |
All of the msg
constants depend on the currenct scope (contract). Their value remains the same in the same contract (even in different functions) but if you call another contract the values change accordingly.
You can see them here in action:
pragma solidity ^0.5.0;
contract A {
event Data(bytes a);
event Sig(bytes4 a);
event Val(uint a);
function a() public payable {
emit Data(msg.data);
emit Sig(msg.sig);
emit Val(msg.value);
b();
B b = new B();
b.c();
}
function b() public payable {
emit Data(msg.data);
emit Sig(msg.sig);
emit Val(msg.value);
}
}
contract B {
event Data(bytes a);
event Sig(bytes4 a);
event Val(uint a);
function c() public payable {
emit Data(msg.data);
emit Sig(msg.sig);
emit Val(msg.value);
}
}
As for the original sender, you can simply use tx.origin
. Note that this is very rarely used as using it may ruin functionality of some proxy contracts etc.
Thanks your answer is very good too but I accepted the other because it gave some details about the use ofthis
.
– Justin Harris
Jan 24 at 19:06
add a comment |
All of the msg
constants depend on the currenct scope (contract). Their value remains the same in the same contract (even in different functions) but if you call another contract the values change accordingly.
You can see them here in action:
pragma solidity ^0.5.0;
contract A {
event Data(bytes a);
event Sig(bytes4 a);
event Val(uint a);
function a() public payable {
emit Data(msg.data);
emit Sig(msg.sig);
emit Val(msg.value);
b();
B b = new B();
b.c();
}
function b() public payable {
emit Data(msg.data);
emit Sig(msg.sig);
emit Val(msg.value);
}
}
contract B {
event Data(bytes a);
event Sig(bytes4 a);
event Val(uint a);
function c() public payable {
emit Data(msg.data);
emit Sig(msg.sig);
emit Val(msg.value);
}
}
As for the original sender, you can simply use tx.origin
. Note that this is very rarely used as using it may ruin functionality of some proxy contracts etc.
Thanks your answer is very good too but I accepted the other because it gave some details about the use ofthis
.
– Justin Harris
Jan 24 at 19:06
add a comment |
All of the msg
constants depend on the currenct scope (contract). Their value remains the same in the same contract (even in different functions) but if you call another contract the values change accordingly.
You can see them here in action:
pragma solidity ^0.5.0;
contract A {
event Data(bytes a);
event Sig(bytes4 a);
event Val(uint a);
function a() public payable {
emit Data(msg.data);
emit Sig(msg.sig);
emit Val(msg.value);
b();
B b = new B();
b.c();
}
function b() public payable {
emit Data(msg.data);
emit Sig(msg.sig);
emit Val(msg.value);
}
}
contract B {
event Data(bytes a);
event Sig(bytes4 a);
event Val(uint a);
function c() public payable {
emit Data(msg.data);
emit Sig(msg.sig);
emit Val(msg.value);
}
}
As for the original sender, you can simply use tx.origin
. Note that this is very rarely used as using it may ruin functionality of some proxy contracts etc.
All of the msg
constants depend on the currenct scope (contract). Their value remains the same in the same contract (even in different functions) but if you call another contract the values change accordingly.
You can see them here in action:
pragma solidity ^0.5.0;
contract A {
event Data(bytes a);
event Sig(bytes4 a);
event Val(uint a);
function a() public payable {
emit Data(msg.data);
emit Sig(msg.sig);
emit Val(msg.value);
b();
B b = new B();
b.c();
}
function b() public payable {
emit Data(msg.data);
emit Sig(msg.sig);
emit Val(msg.value);
}
}
contract B {
event Data(bytes a);
event Sig(bytes4 a);
event Val(uint a);
function c() public payable {
emit Data(msg.data);
emit Sig(msg.sig);
emit Val(msg.value);
}
}
As for the original sender, you can simply use tx.origin
. Note that this is very rarely used as using it may ruin functionality of some proxy contracts etc.
answered Jan 24 at 18:52
Lauri PeltonenLauri Peltonen
5,0492424
5,0492424
Thanks your answer is very good too but I accepted the other because it gave some details about the use ofthis
.
– Justin Harris
Jan 24 at 19:06
add a comment |
Thanks your answer is very good too but I accepted the other because it gave some details about the use ofthis
.
– Justin Harris
Jan 24 at 19:06
Thanks your answer is very good too but I accepted the other because it gave some details about the use of
this
.– Justin Harris
Jan 24 at 19:06
Thanks your answer is very good too but I accepted the other because it gave some details about the use of
this
.– Justin Harris
Jan 24 at 19:06
add a comment |
Thanks for contributing an answer to Ethereum Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fethereum.stackexchange.com%2fquestions%2f66082%2fwhat-other-constants-depend-on-the-current-call-like-msg-sender%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown