-
-
Notifications
You must be signed in to change notification settings - Fork 810
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
VIP: Restrict usage of msg
fields in public functions
#1199
Comments
An alternative to this proposal would be to only allow access to these variables in |
Tentative conclusion from gitter the other day was to disallow self calls to public functions entirely |
Calls to self if functions are public, will be prohibited. |
What about the following pattern for public => public calls in the same contract? contract FooBar:
def foo() -> uint256: constant
@public
def foo() -> uint256:
return 42
@public
def bar() -> uint256:
return FooBar(self).foo() Currently this code compiles, but calls to To me it feels much more explicit than simply using |
Calls to |
@CharlesCooper do we know why this reverts ? 🤔 |
# Line 8
[if,
[eq, [mload, 0], '4273672062' <bar()>],
[seq,
[assert, [iszero, callvalue]],
# Line 10
[mstore,
0,
[mload,
[seq,
[assert, [extcodesize, address]],
# probably this test:
[assert, [xor, address, address]],
[assert, [staticcall, gas, address, [seq, [mstore, 320, 3264763256], 348], 4, 416, 32]],
0,
416]]],
[seq_unchecked, pass, [return, 0, 32]],
# Line 8
stop]], |
@charles-cooper @jacqueswww Looking at where that LLL is generated makes it a bit more clear that it's specifically preventing an "external" call to the current address: https://github.com/ethereum/vyper/blob/76afcb1f599704b748b16272924149a472623a74/vyper/parser/external_call.py#L70 There may be a good reason to prevent that, but I can't think of one off the top of my head. Anyone have any ideas? It's also not clear from the commit history why that LLL is part of the output. |
Actually, here's the original commit that introduced that restriction: 9220715 |
Actually, I may as well ping @DavidKnott here to see if he has any recollection of why this was introduced. |
There used to be confusion as to the value of `msg.*` when we implemented internal functions as call-to-self, so we disabled `msg.*` in internal functions in #1199. However, since then internal functions are implemented just using JUMPs, so the EVM execution context doesn't change. In other words, msg.sender is the same no matter if it's used in an internal or external function, so we can lift this restriction. fix #2631
Simple Summary
Disallow using the
msg
context in public functions which are called internally.Abstract
This is kind of a follow-up to the discussion in #901. The currently implemented behavior is to disallow
msg.sender
in private functions, forcing the caller to pass it as an explicit function argument. The behavior proposed here is to extend this restriction to public functions which are called internally, and also to extend it to the entiremsg
context. If a user really wants to call an internal@public
function which accesses themsg
context, they are forced to refactor the function to passmsg.sender
explicitly (and optionally change it to@private
).Motivation
msg.sender
can have different values depending on if the function call is generated from an external caller or an internal caller. For instance,In this example,
call1
andcall4
return the address of the caller, butcall3
returns the address of this contract. This goes against Vyper's principle of auditability since extra context needs to be reasoned about when reading code. This proposal would force the above implementation ofcall1
to be changed to passmsg.sender
as an argument, mimickingcall2
.Additionally, the current behavior is an extra point of confusion for users coming from Solidity because Vyper's
@public
is more analogous to Solidity'sexternal
keyword than Solidity'spublic
keyword (Solidity has a fine-grained distinction betweenpublic
andexternal
-public
uses a jump which does not change themsg
context, whileexternal
uses a message call).Specification
In addition to disallowing
msg.sender
in private functions, additionally disallow anymsg
values (off the top of my head:msg.sender
,msg.value
, proposedmsg.data
) in internal calls to public functions by raising an exception.Backwards Compatibility
msg.sender
and friends are no longer allowed in public functions which are called internally.Copyright
Copyright and related rights waived via CC0
The text was updated successfully, but these errors were encountered: