Fallback function has to be external: backwards-compatible changes.

This commit is contained in:
chriseth 2018-06-28 18:08:45 +02:00
parent 4268062985
commit eeef82b2d7
43 changed files with 123 additions and 105 deletions

View File

@ -543,7 +543,7 @@ Fallback Function
================= =================
A contract can have exactly one unnamed function. This function cannot have A contract can have exactly one unnamed function. This function cannot have
arguments and cannot return anything. arguments, cannot return anything and has to have ``external`` visibility.
It is executed on a call to the contract if none of the other It is executed on a call to the contract if none of the other
functions match the given function identifier (or if no data was supplied at functions match the given function identifier (or if no data was supplied at
all). all).
@ -591,7 +591,7 @@ Like any function, the fallback function can execute complex operations as long
// Sending Ether to this contract will cause an exception, // Sending Ether to this contract will cause an exception,
// because the fallback function does not have the `payable` // because the fallback function does not have the `payable`
// modifier. // modifier.
function() public { x = 1; } function() external { x = 1; }
uint x; uint x;
} }
@ -599,7 +599,7 @@ Like any function, the fallback function can execute complex operations as long
// This contract keeps all Ether sent to it with no way // This contract keeps all Ether sent to it with no way
// to get it back. // to get it back.
contract Sink { contract Sink {
function() public payable { } function() external payable { }
} }
contract Caller { contract Caller {

View File

@ -213,7 +213,7 @@ Now someone tricks you into sending ether to the address of this attack wallet:
owner = msg.sender; owner = msg.sender;
} }
function() public { function() external {
TxUserWallet(msg.sender).transferTo(owner, msg.sender.balance); TxUserWallet(msg.sender).transferTo(owner, msg.sender.balance);
} }
} }

View File

@ -278,7 +278,7 @@ Yes::
... ...
} }
function() public { function() external {
... ...
} }
@ -308,6 +308,10 @@ No::
// External functions // External functions
// ... // ...
function() external {
...
}
// Private functions // Private functions
// ... // ...
@ -318,10 +322,6 @@ No::
... ...
} }
function() public {
...
}
// Internal functions // Internal functions
// ... // ...
} }
@ -374,13 +374,13 @@ Don't include a whitespace in the fallback function:
Yes:: Yes::
function() public { function() external {
... ...
} }
No:: No::
function () public { function () external {
... ...
} }

View File

@ -90,6 +90,7 @@ contract MultiSigWallet {
/// @dev Fallback function allows to deposit ether. /// @dev Fallback function allows to deposit ether.
function() function()
external
payable payable
{ {
if (msg.value > 0) if (msg.value > 0)

View File

@ -275,7 +275,7 @@ contract ico is safeMath {
require( msg.sender.send(_val) ); require( msg.sender.send(_val) );
} }
function () payable { function () external payable {
/* /*
Callback function. Simply calls the buy function as a beneficiary and there is no affilate address. Callback function. Simply calls the buy function as a beneficiary and there is no affilate address.
If they call the contract without any function then this process will be taken place. If they call the contract without any function then this process will be taken place.

View File

@ -18,7 +18,7 @@ contract Bounty is PullPayment, Destructible {
/** /**
* @dev Fallback function allowing the contract to recieve funds, if they haven't already been claimed. * @dev Fallback function allowing the contract to recieve funds, if they haven't already been claimed.
*/ */
function() payable { function() external payable {
if (claimed) { if (claimed) {
throw; throw;
} }

View File

@ -39,7 +39,7 @@ contract MultisigWallet is Multisig, Shareable, DayLimit {
/** /**
* @dev Fallback function, receives value and emits a deposit event. * @dev Fallback function, receives value and emits a deposit event.
*/ */
function() payable { function() external payable {
// just being sent some cash? // just being sent some cash?
if (msg.value > 0) if (msg.value > 0)
emit Deposit(msg.sender, msg.value); emit Deposit(msg.sender, msg.value);

View File

@ -61,7 +61,7 @@ contract Crowdsale {
// fallback function can be used to buy tokens // fallback function can be used to buy tokens
function () payable { function () external payable {
buyTokens(msg.sender); buyTokens(msg.sender);
} }

View File

@ -379,7 +379,7 @@ contract Wallet is multisig, multiowned, daylimit {
} }
// gets called when no other function matches // gets called when no other function matches
function() payable { function() external payable {
// just being sent some cash? // just being sent some cash?
if (msg.value > 0) if (msg.value > 0)
emit Deposit(msg.sender, msg.value); emit Deposit(msg.sender, msg.value);

View File

@ -301,7 +301,7 @@ BOOST_AUTO_TEST_CASE(regular_functions_exclude_fallback)
char const* sourceCode = R"( char const* sourceCode = R"(
contract A { contract A {
uint public x; uint public x;
function() { x = 2; } function() external { x = 2; }
} }
)"; )";
testCreationTimeGas(sourceCode); testCreationTimeGas(sourceCode);

View File

@ -109,7 +109,7 @@ BOOST_AUTO_TEST_CASE(simple_alias)
{ {
CompilerStack c; CompilerStack c;
c.addSource("a", "contract A {} pragma solidity >=0.0;"); c.addSource("a", "contract A {} pragma solidity >=0.0;");
c.addSource("dir/a/b/c", "import \"../../.././a\" as x; contract B is x.A { function() { x.A r = x.A(20); } } pragma solidity >=0.0;"); c.addSource("dir/a/b/c", "import \"../../.././a\" as x; contract B is x.A { function() external { x.A r = x.A(20); } } pragma solidity >=0.0;");
c.setEVMVersion(dev::test::Options::get().evmVersion()); c.setEVMVersion(dev::test::Options::get().evmVersion());
BOOST_CHECK(c.compile()); BOOST_CHECK(c.compile());
} }

View File

@ -843,7 +843,7 @@ BOOST_AUTO_TEST_CASE(include_fallback_function)
{ {
char const* sourceCode = R"( char const* sourceCode = R"(
contract test { contract test {
function() {} function() external {}
} }
)"; )";
@ -897,7 +897,7 @@ BOOST_AUTO_TEST_CASE(payable_fallback_function)
{ {
char const* sourceCode = R"( char const* sourceCode = R"(
contract test { contract test {
function () payable {} function () external payable {}
} }
)"; )";

View File

@ -1812,7 +1812,7 @@ BOOST_AUTO_TEST_CASE(transfer_ether)
} }
contract C { contract C {
function () payable { function () external payable {
throw; throw;
} }
} }
@ -2506,7 +2506,7 @@ BOOST_AUTO_TEST_CASE(contracts_as_addresses)
{ {
char const* sourceCode = R"( char const* sourceCode = R"(
contract helper { contract helper {
function() payable { } // can receive ether function() external payable { } // can receive ether
} }
contract test { contract test {
helper h; helper h;
@ -3054,7 +3054,7 @@ BOOST_AUTO_TEST_CASE(fallback_function)
char const* sourceCode = R"( char const* sourceCode = R"(
contract A { contract A {
uint data; uint data;
function() { data = 1; } function() external { data = 1; }
function getData() returns (uint r) { return data; } function getData() returns (uint r) { return data; }
} }
)"; )";
@ -3069,7 +3069,7 @@ BOOST_AUTO_TEST_CASE(inherited_fallback_function)
char const* sourceCode = R"( char const* sourceCode = R"(
contract A { contract A {
uint data; uint data;
function() { data = 1; } function() external { data = 1; }
function getData() returns (uint r) { return data; } function getData() returns (uint r) { return data; }
} }
contract B is A {} contract B is A {}
@ -3100,7 +3100,7 @@ BOOST_AUTO_TEST_CASE(short_data_calls_fallback)
uint public x; uint public x;
// Signature is d88e0b00 // Signature is d88e0b00
function fow() { x = 3; } function fow() { x = 3; }
function () { x = 2; } function () external { x = 2; }
} }
)"; )";
compileAndRun(sourceCode); compileAndRun(sourceCode);
@ -3802,11 +3802,11 @@ BOOST_AUTO_TEST_CASE(call_forward_bytes)
contract receiver { contract receiver {
uint public received; uint public received;
function receive(uint x) { received += x + 1; } function receive(uint x) { received += x + 1; }
function() { received = 0x80; } function() external { received = 0x80; }
} }
contract sender { contract sender {
function sender() { rec = new receiver(); } function sender() { rec = new receiver(); }
function() { savedData = msg.data; } function() external { savedData = msg.data; }
function forward() returns (bool) { !rec.call(savedData); return true; } function forward() returns (bool) { !rec.call(savedData); return true; }
function clear() returns (bool) { delete savedData; return true; } function clear() returns (bool) { delete savedData; return true; }
function val() returns (uint) { return rec.received(); } function val() returns (uint) { return rec.received(); }
@ -3830,7 +3830,7 @@ BOOST_AUTO_TEST_CASE(call_forward_bytes_length)
char const* sourceCode = R"( char const* sourceCode = R"(
contract receiver { contract receiver {
uint public calledLength; uint public calledLength;
function() { calledLength = msg.data.length; } function() external { calledLength = msg.data.length; }
} }
contract sender { contract sender {
receiver rec; receiver rec;
@ -3872,11 +3872,11 @@ BOOST_AUTO_TEST_CASE(copying_bytes_multiassign)
contract receiver { contract receiver {
uint public received; uint public received;
function receive(uint x) { received += x + 1; } function receive(uint x) { received += x + 1; }
function() { received = 0x80; } function() external { received = 0x80; }
} }
contract sender { contract sender {
function sender() { rec = new receiver(); } function sender() { rec = new receiver(); }
function() { savedData1 = savedData2 = msg.data; } function() external { savedData1 = savedData2 = msg.data; }
function forward(bool selector) returns (bool) { function forward(bool selector) returns (bool) {
if (selector) { rec.call(savedData1); delete savedData1; } if (selector) { rec.call(savedData1); delete savedData1; }
else { rec.call(savedData2); delete savedData2; } else { rec.call(savedData2); delete savedData2; }
@ -3903,7 +3903,7 @@ BOOST_AUTO_TEST_CASE(delete_removes_bytes_data)
{ {
char const* sourceCode = R"( char const* sourceCode = R"(
contract c { contract c {
function() { data = msg.data; } function() external { data = msg.data; }
function del() returns (bool) { delete data; return true; } function del() returns (bool) { delete data; return true; }
bytes data; bytes data;
} }
@ -3920,7 +3920,7 @@ BOOST_AUTO_TEST_CASE(copy_from_calldata_removes_bytes_data)
char const* sourceCode = R"( char const* sourceCode = R"(
contract c { contract c {
function set() returns (bool) { data = msg.data; return true; } function set() returns (bool) { data = msg.data; return true; }
function() { data = msg.data; } function() external { data = msg.data; }
bytes data; bytes data;
} }
)"; )";
@ -6265,7 +6265,7 @@ BOOST_AUTO_TEST_CASE(failing_send)
char const* sourceCode = R"( char const* sourceCode = R"(
contract Helper { contract Helper {
uint[] data; uint[] data;
function () { function () external {
data[9]; // trigger exception data[9]; // trigger exception
} }
} }
@ -6289,7 +6289,7 @@ BOOST_AUTO_TEST_CASE(send_zero_ether)
// (it previously did not because the gas stipend was not provided by the EVM) // (it previously did not because the gas stipend was not provided by the EVM)
char const* sourceCode = R"( char const* sourceCode = R"(
contract Receiver { contract Receiver {
function () payable { function () external payable {
} }
} }
contract Main { contract Main {
@ -7805,7 +7805,7 @@ BOOST_AUTO_TEST_CASE(reject_ether_sent_to_library)
function f(address x) returns (bool) { function f(address x) returns (bool) {
return x.send(1); return x.send(1);
} }
function () payable {} function () external payable {}
} }
)"; )";
compileAndRun(sourceCode, 0, "lib"); compileAndRun(sourceCode, 0, "lib");
@ -9335,7 +9335,7 @@ BOOST_AUTO_TEST_CASE(mutex)
else else
return fund.withdrawUnprotected(10); return fund.withdrawUnprotected(10);
} }
function() payable { function() external payable {
callDepth++; callDepth++;
if (callDepth < 4) if (callDepth < 4)
attackInternal(); attackInternal();
@ -9461,7 +9461,7 @@ BOOST_AUTO_TEST_CASE(payable_function)
function f() payable returns (uint) { function f() payable returns (uint) {
return msg.value; return msg.value;
} }
function() payable { function() external payable {
a = msg.value + 1; a = msg.value + 1;
} }
} }
@ -9500,7 +9500,7 @@ BOOST_AUTO_TEST_CASE(non_payable_throw)
function f() returns (uint) { function f() returns (uint) {
return msg.value; return msg.value;
} }
function() { function() external {
a = msg.value + 1; a = msg.value + 1;
} }
} }
@ -11189,7 +11189,7 @@ BOOST_AUTO_TEST_CASE(bubble_up_error_messages_through_transfer)
{ {
char const* sourceCode = R"( char const* sourceCode = R"(
contract D { contract D {
function() public payable { function() external payable {
revert("message"); revert("message");
} }
function f() public { function f() public {
@ -11340,7 +11340,7 @@ BOOST_AUTO_TEST_CASE(interface_contract)
interface I { interface I {
event A(); event A();
function f() returns (bool); function f() returns (bool);
function() payable; function() external payable;
} }
contract A is I { contract A is I {
@ -11352,7 +11352,7 @@ BOOST_AUTO_TEST_CASE(interface_contract)
return true; return true;
} }
function() payable { function() external payable {
} }
} }

View File

@ -0,0 +1,6 @@
contract C {
// Check that visibility is also enforced for the fallback function.
function() {}
}
// ----
// Warning: (90-103): No visibility specified. Defaulting to "public".

View File

@ -1,6 +1,6 @@
contract C { contract C {
uint x; uint x;
function() pure { x = 2; } function() external pure { x = 2; }
} }
// ---- // ----
// TypeError: (29-55): Fallback function must be payable or non-payable, but is "pure". // TypeError: (29-64): Fallback function must be payable or non-payable, but is "pure".

View File

@ -1,6 +1,6 @@
contract C { contract C {
uint x; uint x;
function() view { x = 2; } function() external view { x = 2; }
} }
// ---- // ----
// TypeError: (29-55): Fallback function must be payable or non-payable, but is "view". // TypeError: (29-64): Fallback function must be payable or non-payable, but is "view".

View File

@ -1,4 +1,4 @@
contract C { contract C {
uint x; uint x;
function() public { x = 2; } function() external { x = 2; }
} }

View File

@ -1,6 +1,6 @@
contract C { contract C {
uint x; uint x;
function(uint a) public { x = 2; } function(uint a) external { x = 2; }
} }
// ---- // ----
// TypeError: (37-45): Fallback function cannot take parameters. // TypeError: (37-45): Fallback function cannot take parameters.

View File

@ -1,5 +1,5 @@
library C { library C {
function() public {} function() external {}
} }
// ---- // ----
// TypeError: (16-36): Libraries cannot have fallback functions. // TypeError: (16-38): Libraries cannot have fallback functions.

View File

@ -1,5 +1,5 @@
contract C { contract C {
function() public returns (uint) { } function() external returns (uint) { }
} }
// ---- // ----
// TypeError: (43-49): Fallback function cannot return values. // TypeError: (45-51): Fallback function cannot return values.

View File

@ -1,7 +1,7 @@
contract C { contract C {
uint x; uint x;
function() public { x = 2; } function() external { x = 2; }
function() public { x = 3; } function() external { x = 3; }
} }
// ---- // ----
// DeclarationError: (62-90): Only one fallback function is allowed. // DeclarationError: (64-94): Only one fallback function is allowed.

View File

@ -1,7 +1,7 @@
contract A { contract A {
uint x; uint x;
function() public { x = 1; } function() external { x = 1; }
} }
contract C is A { contract C is A {
function() public { x = 2; } function() external { x = 2; }
} }

View File

@ -1,3 +1,3 @@
contract test { function() public { uint x = 1; uint y = 2; x || y; } } contract test { function() external { uint x = 1; uint y = 2; x || y; } }
// ---- // ----
// TypeError: (60-66): Operator || not compatible with types uint256 and uint256 // TypeError: (62-68): Operator || not compatible with types uint256 and uint256

View File

@ -1,3 +1,3 @@
contract test { function() public { uint x = 1; uint y = 2; x && y; } } contract test { function() external { uint x = 1; uint y = 2; x && y; } }
// ---- // ----
// TypeError: (60-66): Operator && not compatible with types uint256 and uint256 // TypeError: (62-68): Operator && not compatible with types uint256 and uint256

View File

@ -1,3 +1,3 @@
contract test { function() public { uint x = 1; !x; } } contract test { function() external { uint x = 1; !x; } }
// ---- // ----
// TypeError: (48-50): Unary operator ! cannot be applied to type uint256 // TypeError: (50-52): Unary operator ! cannot be applied to type uint256

View File

@ -1,3 +1,3 @@
contract test { function() public { uint x = 3; int y = -4; x ** y; } } contract test { function() external { uint x = 3; int y = -4; x ** y; } }
// ---- // ----
// TypeError: (60-66): Operator ** not compatible with types uint256 and int256 // TypeError: (62-68): Operator ** not compatible with types uint256 and int256

View File

@ -1,3 +1,3 @@
contract test { function() public { uint x = 3; int y = -4; y ** x; } } contract test { function() external { uint x = 3; int y = -4; y ** x; } }
// ---- // ----
// TypeError: (60-66): Operator ** not compatible with types int256 and uint256 // TypeError: (62-68): Operator ** not compatible with types int256 and uint256

View File

@ -1,3 +1,3 @@
contract test { function() public { int x = -3; int y = -4; x ** y; } } contract test { function() external { int x = -3; int y = -4; x ** y; } }
// ---- // ----
// TypeError: (60-66): Operator ** not compatible with types int256 and int256 // TypeError: (62-68): Operator ** not compatible with types int256 and int256

View File

@ -1,3 +1,3 @@
contract test { bytes a; bytes b; function() public { a == b; } } contract test { bytes a; bytes b; function() external { a == b; } }
// ---- // ----
// TypeError: (54-60): Operator == not compatible with types bytes storage ref and bytes storage ref // TypeError: (56-62): Operator == not compatible with types bytes storage ref and bytes storage ref

View File

@ -1,3 +1,10 @@
contract test { struct s {uint a;} s x; s y; function() public { x == y; } } contract test {
struct s {uint a;}
s x;
s y;
function() external {
x == y;
}
}
// ---- // ----
// TypeError: (65-71): Operator == not compatible with types struct test.s storage ref and struct test.s storage ref // TypeError: (79-85): Operator == not compatible with types struct test.s storage ref and struct test.s storage ref

View File

@ -1,9 +1,5 @@
interface I { interface I {
function(); function() external;
function f(); function f() external;
} }
// ---- // ----
// Warning: (18-29): Functions in interfaces should be declared external.
// Warning: (34-47): Functions in interfaces should be declared external.
// Warning: (18-29): No visibility specified. Defaulting to "public". In interfaces it defaults to external.
// Warning: (34-47): No visibility specified. Defaulting to "public". In interfaces it defaults to external.

View File

@ -1,17 +1,11 @@
interface I { interface I {
event A(); event A();
function f(); function f() external;
function g(); function g() external;
function(); function() external;
} }
contract C is I { contract C is I {
function f() public { function f() public {
} }
} }
// ---- // ----
// Warning: (33-46): Functions in interfaces should be declared external.
// Warning: (51-64): Functions in interfaces should be declared external.
// Warning: (69-80): Functions in interfaces should be declared external.
// Warning: (33-46): No visibility specified. Defaulting to "public". In interfaces it defaults to external.
// Warning: (51-64): No visibility specified. Defaulting to "public". In interfaces it defaults to external.
// Warning: (69-80): No visibility specified. Defaulting to "public". In interfaces it defaults to external.

View File

@ -2,16 +2,16 @@
// because A's fallback function is not payable. // because A's fallback function is not payable.
contract A { contract A {
function() public {} function() external {}
} }
contract B { contract B {
A a; A a;
function() public { function() external {
a.transfer(100); a.transfer(100);
} }
} }
// ---- // ----
// Warning: (209-219): Using contract member "transfer" inherited from the address type is deprecated. Convert the contract to "address" type to access the member, for example use "address(contract).transfer" instead. // Warning: (213-223): Using contract member "transfer" inherited from the address type is deprecated. Convert the contract to "address" type to access the member, for example use "address(contract).transfer" instead.
// TypeError: (209-219): Value transfer to a contract without a payable fallback function. // TypeError: (213-223): Value transfer to a contract without a payable fallback function.

View File

@ -6,10 +6,10 @@ contract A {}
contract B { contract B {
A a; A a;
function() public { function() external {
a.transfer(100); a.transfer(100);
} }
} }
// ---- // ----
// Warning: (190-200): Using contract member "transfer" inherited from the address type is deprecated. Convert the contract to "address" type to access the member, for example use "address(contract).transfer" instead. // Warning: (192-202): Using contract member "transfer" inherited from the address type is deprecated. Convert the contract to "address" type to access the member, for example use "address(contract).transfer" instead.
// TypeError: (190-200): Value transfer to a contract without a payable fallback function. // TypeError: (192-202): Value transfer to a contract without a payable fallback function.

View File

@ -2,16 +2,16 @@
// because A does not have a payable fallback function. // because A does not have a payable fallback function.
contract A { contract A {
function() public {} function() external {}
} }
contract B { contract B {
A a; A a;
function() public { function() external {
require(a.send(100)); require(a.send(100));
} }
} }
// ---- // ----
// Warning: (220-226): Using contract member "send" inherited from the address type is deprecated. Convert the contract to "address" type to access the member, for example use "address(contract).send" instead. // Warning: (224-230): Using contract member "send" inherited from the address type is deprecated. Convert the contract to "address" type to access the member, for example use "address(contract).send" instead.
// TypeError: (220-226): Value transfer to a contract without a payable fallback function. // TypeError: (224-230): Value transfer to a contract without a payable fallback function.

View File

@ -2,15 +2,15 @@
// because A does not have a payable fallback function. // because A does not have a payable fallback function.
contract A { contract A {
function() payable public {} function() payable external {}
} }
contract B { contract B {
A a; A a;
function() public { function() external {
a.transfer(100); a.transfer(100);
} }
} }
// ---- // ----
// Warning: (224-234): Using contract member "transfer" inherited from the address type is deprecated. Convert the contract to "address" type to access the member, for example use "address(contract).transfer" instead. // Warning: (228-238): Using contract member "transfer" inherited from the address type is deprecated. Convert the contract to "address" type to access the member, for example use "address(contract).transfer" instead.

View File

@ -5,7 +5,7 @@ contract A {
contract B { contract B {
A a; A a;
function() public { function() external {
a.transfer(); a.transfer();
} }
} }

View File

@ -0,0 +1,3 @@
contract C {
function () external { }
}

View File

@ -0,0 +1,4 @@
contract C {
function () internal { }
}
// ----

View File

@ -0,0 +1,4 @@
contract C {
function () private { }
}
// ----

View File

@ -0,0 +1,4 @@
contract C {
function () public { }
}
// ----

View File

@ -1,5 +1,4 @@
contract c { contract c {
function() { } function() external { }
} }
// ---- // ----
// Warning: (17-31): No visibility specified. Defaulting to "public".

View File

@ -14,5 +14,5 @@ contract C {
assert(true); assert(true);
x; y; z; x; y; z;
} }
function() payable public {} function() payable external {}
} }