Merge pull request #6320 from ethereum/callvalue_nonpayable

Inline Assembly: Issue error for callvalue in nonpayable function
This commit is contained in:
chriseth 2019-03-20 10:07:09 +01:00 committed by GitHub
commit 4d89fc1644
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 84 additions and 6 deletions

View File

@ -4,6 +4,7 @@ Language Features:
Compiler 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). * Yul Optimizer: Enable stack allocation optimization by default if yul optimizer is active (disable in yulDetails).

View File

@ -112,6 +112,8 @@ private:
{ {
if (eth::SemanticInformation::invalidInViewFunctions(_instruction)) if (eth::SemanticInformation::invalidInViewFunctions(_instruction))
m_reportMutability(StateMutability::NonPayable, _location); m_reportMutability(StateMutability::NonPayable, _location);
else if (_instruction == Instruction::CALLVALUE)
m_reportMutability(StateMutability::Payable, _location);
else if (eth::SemanticInformation::invalidInPureFunctions(_instruction)) else if (eth::SemanticInformation::invalidInPureFunctions(_instruction))
m_reportMutability(StateMutability::View, _location); m_reportMutability(StateMutability::View, _location);
} }
@ -270,13 +272,13 @@ void ViewPureChecker::reportMutability(
if (_nestedLocation) if (_nestedLocation)
m_errorReporter.typeError( m_errorReporter.typeError(
_location, _location,
SecondarySourceLocation().append("\"msg.value\" appears here inside the modifier.", *_nestedLocation), SecondarySourceLocation().append("\"msg.value\" or \"callvalue()\" appear here inside the modifier.", *_nestedLocation),
"This modifier uses \"msg.value\" and thus the function has to be payable or internal." "This modifier uses \"msg.value\" or \"callvalue()\" and thus the function has to be payable or internal."
); );
else else
m_errorReporter.typeError( m_errorReporter.typeError(
_location, _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." "\"payable\" or use an internal function to avoid this error."
); );
m_errors = true; m_errors = true;

View File

@ -3,4 +3,4 @@ contract C {
function f() costs(1 ether) public view {} 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.

View File

@ -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.

View File

@ -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.

View File

@ -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.

View File

@ -0,0 +1,11 @@
contract C
{
function f() internal returns (uint x) {
assembly {
x := callvalue()
}
}
function g() public returns (uint) {
return f();
}
}

View File

@ -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.

View File

@ -0,0 +1,9 @@
contract C
{
function () external payable {
uint x;
assembly {
x := callvalue()
}
}
}

View File

@ -0,0 +1,8 @@
contract C
{
function f(uint x) public payable {
assembly {
x := callvalue()
}
}
}

View File

@ -0,0 +1,12 @@
contract C
{
modifier m {
uint x;
assembly {
x := callvalue()
}
_;
}
function f() m public payable {
}
}

View File

@ -3,4 +3,4 @@ contract C {
function f() m(1 ether, msg.value) public view {} 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.