-
-
Notifications
You must be signed in to change notification settings - Fork 812
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
fix[lang]: disallow blockhash
in pure
functions
#3157
base: master
Are you sure you want to change the base?
Changes from 26 commits
90747ef
393dfed
3d303c7
439bb78
5fadb3b
d976d3f
aa82067
cccd707
6f193e4
a0e80ad
b3e4b62
79e1674
f6f2e91
a5b1924
b754a1b
eff8438
035a91b
9410901
f6c95b2
19baa5d
a33c7a8
bf26d2e
7ae3018
c3f2bf6
3931761
1895549
9e52ecc
dad2c46
ebfe003
4709936
e2e9864
b1517b7
d9e32c7
8610908
36d6ddb
115f9c4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
@@ -900,25 +900,29 @@ def set_lucky(arg1: address, arg2: int128): | |||||||||
print("Successfully executed an external contract call state change") | ||||||||||
|
||||||||||
|
||||||||||
def test_constant_external_contract_call_cannot_change_state(): | ||||||||||
c = """ | ||||||||||
@pytest.mark.parametrize("state_modifying_decorator", ("payable", "nonpayable")) | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||
@pytest.mark.parametrize("non_modifying_decorator", ("pure", "view")) | ||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||
def test_constant_external_contract_call_cannot_change_state( | ||||||||||
state_modifying_decorator, non_modifying_decorator | ||||||||||
): | ||||||||||
c = f""" | ||||||||||
interface Foo: | ||||||||||
def set_lucky(_lucky: int128) -> int128: nonpayable | ||||||||||
def set_lucky(_lucky: int128) -> int128: {state_modifying_decorator} | ||||||||||
|
||||||||||
@external | ||||||||||
@view | ||||||||||
@{non_modifying_decorator} | ||||||||||
def set_lucky_stmt(arg1: address, arg2: int128): | ||||||||||
extcall Foo(arg1).set_lucky(arg2) | ||||||||||
""" | ||||||||||
|
||||||||||
with pytest.raises(StateAccessViolation): | ||||||||||
compile_code(c) | ||||||||||
|
||||||||||
c2 = """ | ||||||||||
c2 = f""" | ||||||||||
interface Foo: | ||||||||||
def set_lucky(_lucky: int128) -> int128: nonpayable | ||||||||||
def set_lucky(_lucky: int128) -> int128: {state_modifying_decorator} | ||||||||||
@external | ||||||||||
@view | ||||||||||
@{non_modifying_decorator} | ||||||||||
def set_lucky_expr(arg1: address, arg2: int128) -> int128: | ||||||||||
return extcall Foo(arg1).set_lucky(arg2) | ||||||||||
""" | ||||||||||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -49,12 +49,12 @@ | |
UnfoldableNode, | ||
ZeroDivisionException, | ||
) | ||
from vyper.semantics.analysis.base import Modifiability, VarInfo | ||
from vyper.semantics.analysis.base import Modifiability, StateMutability, VarInfo | ||
Check notice Code scanning / CodeQL Cyclic import Note
Import of module
vyper.semantics.analysis.base Error loading related location Loading |
||
from vyper.semantics.analysis.utils import ( | ||
get_common_types, | ||
get_exact_type_from_node, | ||
get_possible_types_from_node, | ||
validate_expected_type, | ||
Check notice Code scanning / CodeQL Cyclic import Note
Import of module
vyper.semantics.analysis.utils Error loading related location Loading |
||
) | ||
from vyper.semantics.types import ( | ||
TYPE_T, | ||
|
@@ -1061,6 +1061,26 @@ | |
|
||
kwargz = {i.arg: i.value for i in node.keywords} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. maybe get |
||
|
||
delegate_call = kwargz.get("is_delegate_call", False) | ||
charles-cooper marked this conversation as resolved.
Show resolved
Hide resolved
|
||
static_call = kwargz.get("is_static_call", False) | ||
if delegate_call and static_call: | ||
raise ArgumentException( | ||
"Call may use one of `is_delegate_call` or `is_static_call`, not both", node | ||
) | ||
|
||
value = kwargz.get("value") | ||
if (delegate_call or static_call) and value is not None: | ||
charles-cooper marked this conversation as resolved.
Show resolved
Hide resolved
|
||
raise ArgumentException("value= may not be passed for static or delegate calls!", node) | ||
|
||
fn_node = node.get_ancestor(vy_ast.FunctionDef) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. note for refactoring: ideally we should pass this in a context object There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. should I add a comment here? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. sure |
||
fn_type = fn_node._metadata["func_type"] | ||
if not static_call and not fn_type.is_mutable: | ||
raise StateAccessViolation( | ||
f"Cannot make modifying calls from {fn_type.mutability}," | ||
" use `is_static_call=True` to perform this action", | ||
node, | ||
) | ||
|
||
outsize = kwargz.get("max_outsize") | ||
if outsize is not None: | ||
outsize = outsize.get_folded_value() | ||
|
@@ -1106,20 +1126,6 @@ | |
kwargs["revert_on_failure"], | ||
) | ||
|
||
if delegate_call and static_call: | ||
raise ArgumentException( | ||
"Call may use one of `is_delegate_call` or `is_static_call`, not both" | ||
) | ||
|
||
if (delegate_call or static_call) and value.value != 0: | ||
raise ArgumentException("value= may not be passed for static or delegate calls!") | ||
|
||
if not static_call and context.is_constant(): | ||
raise StateAccessViolation( | ||
f"Cannot make modifying calls from {context.pp_constancy()}," | ||
" use `is_static_call=True` to perform this action" | ||
) | ||
|
||
if data.value == "~calldata": | ||
call_ir = ["with", "mem_ofst", "msize"] | ||
args_ofst = ["seq", ["calldatacopy", "mem_ofst", 0, "calldatasize"], "mem_ofst"] | ||
|
@@ -1249,6 +1255,7 @@ | |
_id = "blockhash" | ||
_inputs = [("block_num", UINT256_T)] | ||
_return_type = BYTES32_T | ||
mutability = StateMutability.VIEW | ||
|
||
@process_inputs | ||
def build_IR(self, expr, args, kwargs, contact): | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should I revert the changes in this file?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
probably not. do any of them fail? it increases test coverage, right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no, they pass, and probably increases test coverage. I will leave this file as it is then.