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
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
functions match the given function identifier (or if no data was supplied at
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,
// because the fallback function does not have the `payable`
// modifier.
function() public { x = 1; }
function() external { x = 1; }
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
// to get it back.
contract Sink {
function() public payable { }
function() external payable { }
}
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;
}
function() public {
function() external {
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
// ...
function() external {
...
}
// Private functions
// ...
@ -318,10 +322,6 @@ No::
...
}
function() public {
...
}
// Internal functions
// ...
}
@ -374,13 +374,13 @@ Don't include a whitespace in the fallback function:
Yes::
function() public {
function() external {
...
}
No::
function () public {
function () external {
...
}

View File

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

View File

@ -275,7 +275,7 @@ contract ico is safeMath {
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.
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.
*/
function() payable {
function() external payable {
if (claimed) {
throw;
}

View File

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

View File

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

View File

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

View File

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

View File

@ -109,7 +109,7 @@ BOOST_AUTO_TEST_CASE(simple_alias)
{
CompilerStack c;
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());
BOOST_CHECK(c.compile());
}

View File

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

View File

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

View File

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

View File

@ -1,5 +1,5 @@
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 {
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 {
uint x;
function() public { x = 2; }
function() public { x = 3; }
function() external { x = 2; }
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 {
uint x;
function() public { x = 1; }
function() external { x = 1; }
}
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 {
function();
function f();
function() external;
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 {
event A();
function f();
function g();
function();
function f() external;
function g() external;
function() external;
}
contract C is I {
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.
contract A {
function() public {}
function() external {}
}
contract B {
A a;
function() public {
function() external {
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.
// TypeError: (209-219): Value transfer to a contract without a payable fallback function.
// 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: (213-223): Value transfer to a contract without a payable fallback function.

View File

@ -6,10 +6,10 @@ contract A {}
contract B {
A a;
function() public {
function() external {
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.
// TypeError: (190-200): Value transfer to a contract without a payable fallback function.
// 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: (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.
contract A {
function() public {}
function() external {}
}
contract B {
A a;
function() public {
function() external {
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.
// TypeError: (220-226): Value transfer to a contract without a payable fallback function.
// 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: (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.
contract A {
function() payable public {}
function() payable external {}
}
contract B {
A a;
function() public {
function() external {
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 {
A a;
function() public {
function() external {
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 {
function() { }
function() external { }
}
// ----
// Warning: (17-31): No visibility specified. Defaulting to "public".

View File

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