From 9acec99c312241e93b8da6b2cb7e42abe02bebaa Mon Sep 17 00:00:00 2001 From: Leonardo Alt Date: Tue, 19 Mar 2019 16:51:33 +0100 Subject: [PATCH 1/2] Issue error for callvalue in nonpayable function --- Changelog.md | 1 + libsolidity/analysis/ViewPureChecker.cpp | 8 +++++--- .../memberLookup/msg_value_modifier_view.sol | 2 +- ...ns_msg_value_in_non_payable_public_function.sol | 2 +- .../callvalue_nonpayable_assembly_fallback.sol | 11 +++++++++++ .../callvalue_nonpayable_assembly_function.sol | 10 ++++++++++ ...value_nonpayable_assembly_function_modifier.sol | 14 ++++++++++++++ .../callvalue_payable_assembly_fallback.sol | 9 +++++++++ .../callvalue_payable_assembly_function.sol | 8 ++++++++ ...allvalue_payable_assembly_function_modifier.sol | 12 ++++++++++++ .../viewPureChecker/msg_value_modifier_view.sol | 2 +- 11 files changed, 73 insertions(+), 6 deletions(-) create mode 100644 test/libsolidity/syntaxTests/viewPureChecker/callvalue_nonpayable_assembly_fallback.sol create mode 100644 test/libsolidity/syntaxTests/viewPureChecker/callvalue_nonpayable_assembly_function.sol create mode 100644 test/libsolidity/syntaxTests/viewPureChecker/callvalue_nonpayable_assembly_function_modifier.sol create mode 100644 test/libsolidity/syntaxTests/viewPureChecker/callvalue_payable_assembly_fallback.sol create mode 100644 test/libsolidity/syntaxTests/viewPureChecker/callvalue_payable_assembly_function.sol create mode 100644 test/libsolidity/syntaxTests/viewPureChecker/callvalue_payable_assembly_function_modifier.sol diff --git a/Changelog.md b/Changelog.md index 7e422b8e7..26995cf73 100644 --- a/Changelog.md +++ b/Changelog.md @@ -4,6 +4,7 @@ Language Features: Compiler Features: + * Inline Assembly: Issue error when using ``callvalue()`` inside nonpayable function (in the same way that ``msg.value`` already does). * Yul Optimizer: Enable stack allocation optimization by default if yul optimizer is active (disable in yulDetails). diff --git a/libsolidity/analysis/ViewPureChecker.cpp b/libsolidity/analysis/ViewPureChecker.cpp index 0ece09f16..70b907b5b 100644 --- a/libsolidity/analysis/ViewPureChecker.cpp +++ b/libsolidity/analysis/ViewPureChecker.cpp @@ -112,6 +112,8 @@ private: { if (eth::SemanticInformation::invalidInViewFunctions(_instruction)) m_reportMutability(StateMutability::NonPayable, _location); + else if (_instruction == Instruction::CALLVALUE) + m_reportMutability(StateMutability::Payable, _location); else if (eth::SemanticInformation::invalidInPureFunctions(_instruction)) m_reportMutability(StateMutability::View, _location); } @@ -270,13 +272,13 @@ void ViewPureChecker::reportMutability( if (_nestedLocation) m_errorReporter.typeError( _location, - SecondarySourceLocation().append("\"msg.value\" appears here inside the modifier.", *_nestedLocation), - "This modifier uses \"msg.value\" and thus the function has to be payable or internal." + SecondarySourceLocation().append("\"msg.value\" or \"callvalue()\" appear here inside the modifier.", *_nestedLocation), + "This modifier uses \"msg.value\" or \"callvalue()\" and thus the function has to be payable or internal." ); else m_errorReporter.typeError( _location, - "\"msg.value\" can only be used in payable public functions. Make the function " + "\"msg.value\" and \"callvalue()\" can only be used in payable public functions. Make the function " "\"payable\" or use an internal function to avoid this error." ); m_errors = true; diff --git a/test/libsolidity/syntaxTests/memberLookup/msg_value_modifier_view.sol b/test/libsolidity/syntaxTests/memberLookup/msg_value_modifier_view.sol index 8430c5c3e..abfc1eb87 100644 --- a/test/libsolidity/syntaxTests/memberLookup/msg_value_modifier_view.sol +++ b/test/libsolidity/syntaxTests/memberLookup/msg_value_modifier_view.sol @@ -3,4 +3,4 @@ contract C { function f() costs(1 ether) public view {} } // ---- -// TypeError: (101-115): This modifier uses "msg.value" and thus the function has to be payable or internal. +// TypeError: (101-115): This modifier uses "msg.value" or "callvalue()" and thus the function has to be payable or internal. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/397_warns_msg_value_in_non_payable_public_function.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/397_warns_msg_value_in_non_payable_public_function.sol index c56ad25f9..6797857af 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/397_warns_msg_value_in_non_payable_public_function.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/397_warns_msg_value_in_non_payable_public_function.sol @@ -4,4 +4,4 @@ contract C { } } // ---- -// TypeError: (52-61): "msg.value" can only be used in payable public functions. Make the function "payable" or use an internal function to avoid this error. +// TypeError: (52-61): "msg.value" and "callvalue()" can only be used in payable public functions. Make the function "payable" or use an internal function to avoid this error. diff --git a/test/libsolidity/syntaxTests/viewPureChecker/callvalue_nonpayable_assembly_fallback.sol b/test/libsolidity/syntaxTests/viewPureChecker/callvalue_nonpayable_assembly_fallback.sol new file mode 100644 index 000000000..d019110e4 --- /dev/null +++ b/test/libsolidity/syntaxTests/viewPureChecker/callvalue_nonpayable_assembly_fallback.sol @@ -0,0 +1,11 @@ +contract C +{ + function () external { + uint x; + assembly { + x := callvalue() + } + } +} +// ---- +// TypeError: (92-103): "msg.value" and "callvalue()" can only be used in payable public functions. Make the function "payable" or use an internal function to avoid this error. diff --git a/test/libsolidity/syntaxTests/viewPureChecker/callvalue_nonpayable_assembly_function.sol b/test/libsolidity/syntaxTests/viewPureChecker/callvalue_nonpayable_assembly_function.sol new file mode 100644 index 000000000..edc413e2d --- /dev/null +++ b/test/libsolidity/syntaxTests/viewPureChecker/callvalue_nonpayable_assembly_function.sol @@ -0,0 +1,10 @@ +contract C +{ + function f(uint x) public { + assembly { + x := callvalue() + } + } +} +// ---- +// TypeError: (81-92): "msg.value" and "callvalue()" can only be used in payable public functions. Make the function "payable" or use an internal function to avoid this error. diff --git a/test/libsolidity/syntaxTests/viewPureChecker/callvalue_nonpayable_assembly_function_modifier.sol b/test/libsolidity/syntaxTests/viewPureChecker/callvalue_nonpayable_assembly_function_modifier.sol new file mode 100644 index 000000000..916b0d2db --- /dev/null +++ b/test/libsolidity/syntaxTests/viewPureChecker/callvalue_nonpayable_assembly_function_modifier.sol @@ -0,0 +1,14 @@ +contract C +{ + modifier m { + uint x; + assembly { + x := callvalue() + } + _; + } + function f() m public { + } +} +// ---- +// TypeError: (99-100): This modifier uses "msg.value" or "callvalue()" and thus the function has to be payable or internal. diff --git a/test/libsolidity/syntaxTests/viewPureChecker/callvalue_payable_assembly_fallback.sol b/test/libsolidity/syntaxTests/viewPureChecker/callvalue_payable_assembly_fallback.sol new file mode 100644 index 000000000..7e87fd0fc --- /dev/null +++ b/test/libsolidity/syntaxTests/viewPureChecker/callvalue_payable_assembly_fallback.sol @@ -0,0 +1,9 @@ +contract C +{ + function () external payable { + uint x; + assembly { + x := callvalue() + } + } +} diff --git a/test/libsolidity/syntaxTests/viewPureChecker/callvalue_payable_assembly_function.sol b/test/libsolidity/syntaxTests/viewPureChecker/callvalue_payable_assembly_function.sol new file mode 100644 index 000000000..77dee8bda --- /dev/null +++ b/test/libsolidity/syntaxTests/viewPureChecker/callvalue_payable_assembly_function.sol @@ -0,0 +1,8 @@ +contract C +{ + function f(uint x) public payable { + assembly { + x := callvalue() + } + } +} diff --git a/test/libsolidity/syntaxTests/viewPureChecker/callvalue_payable_assembly_function_modifier.sol b/test/libsolidity/syntaxTests/viewPureChecker/callvalue_payable_assembly_function_modifier.sol new file mode 100644 index 000000000..9938fadd8 --- /dev/null +++ b/test/libsolidity/syntaxTests/viewPureChecker/callvalue_payable_assembly_function_modifier.sol @@ -0,0 +1,12 @@ +contract C +{ + modifier m { + uint x; + assembly { + x := callvalue() + } + _; + } + function f() m public payable { + } +} diff --git a/test/libsolidity/syntaxTests/viewPureChecker/msg_value_modifier_view.sol b/test/libsolidity/syntaxTests/viewPureChecker/msg_value_modifier_view.sol index 613b01980..8c0df6e9a 100644 --- a/test/libsolidity/syntaxTests/viewPureChecker/msg_value_modifier_view.sol +++ b/test/libsolidity/syntaxTests/viewPureChecker/msg_value_modifier_view.sol @@ -3,4 +3,4 @@ contract C { function f() m(1 ether, msg.value) public view {} } // ---- -// TypeError: (118-127): "msg.value" can only be used in payable public functions. Make the function "payable" or use an internal function to avoid this error. +// TypeError: (118-127): "msg.value" and "callvalue()" can only be used in payable public functions. Make the function "payable" or use an internal function to avoid this error. From 0386d39942aff46b60ed774f5941253841194a96 Mon Sep 17 00:00:00 2001 From: Leonardo Alt Date: Tue, 19 Mar 2019 20:45:20 +0100 Subject: [PATCH 2/2] Add test with internal function --- ...allvalue_nonpayable_assembly_function_internal.sol | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 test/libsolidity/syntaxTests/viewPureChecker/callvalue_nonpayable_assembly_function_internal.sol diff --git a/test/libsolidity/syntaxTests/viewPureChecker/callvalue_nonpayable_assembly_function_internal.sol b/test/libsolidity/syntaxTests/viewPureChecker/callvalue_nonpayable_assembly_function_internal.sol new file mode 100644 index 000000000..63014543e --- /dev/null +++ b/test/libsolidity/syntaxTests/viewPureChecker/callvalue_nonpayable_assembly_function_internal.sol @@ -0,0 +1,11 @@ +contract C +{ + function f() internal returns (uint x) { + assembly { + x := callvalue() + } + } + function g() public returns (uint) { + return f(); + } +}