mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
commit
79f9a04236
@ -447,6 +447,12 @@ In particular, the following operations will consume more gas than the stipend p
|
|||||||
|
|
||||||
Please ensure you test your fallback function thoroughly to ensure the execution cost is less than 2300 gas before deploying a contract.
|
Please ensure you test your fallback function thoroughly to ensure the execution cost is less than 2300 gas before deploying a contract.
|
||||||
|
|
||||||
|
.. warning::
|
||||||
|
Contracts that receive Ether but do not define a fallback function
|
||||||
|
throw an exception, sending back the Ether (this was different
|
||||||
|
before Solidity v0.4.0). So if you want your contract to receive Ether,
|
||||||
|
you have to implement a fallback function.
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
contract Test {
|
contract Test {
|
||||||
|
@ -103,7 +103,9 @@ and stall those. Please be explicit about such cases in the documentation of you
|
|||||||
Sending and Receiving Ether
|
Sending and Receiving Ether
|
||||||
===========================
|
===========================
|
||||||
|
|
||||||
- If a contract receives Ether (without a function being called), the fallback function is executed. The contract can only rely
|
- If a contract receives Ether (without a function being called), the fallback function is executed.
|
||||||
|
If it does not have a fallback function, the Ether will be rejected (by throwing an exception).
|
||||||
|
During the execution of the fallback function, the contract can only rely
|
||||||
on the "gas stipend" (2300 gas) being available to it at that time. This stipend is not enough to access storage in any way.
|
on the "gas stipend" (2300 gas) being available to it at that time. This stipend is not enough to access storage in any way.
|
||||||
To be sure that your contract can receive Ether in that way, check the gas requirements of the fallback function
|
To be sure that your contract can receive Ether in that way, check the gas requirements of the fallback function
|
||||||
(for example in the "details" section in browser-solidity).
|
(for example in the "details" section in browser-solidity).
|
||||||
|
@ -92,6 +92,8 @@ bool TypeChecker::visit(ContractDefinition const& _contract)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
fallbackFunction = function;
|
fallbackFunction = function;
|
||||||
|
if (_contract.isLibrary())
|
||||||
|
typeError(fallbackFunction->location(), "Libraries cannot have fallback functions.");
|
||||||
if (!fallbackFunction->parameters().empty())
|
if (!fallbackFunction->parameters().empty())
|
||||||
typeError(fallbackFunction->parameterList().location(), "Fallback function cannot take parameters.");
|
typeError(fallbackFunction->parameterList().location(), "Fallback function cannot take parameters.");
|
||||||
if (!fallbackFunction->returnParameters().empty())
|
if (!fallbackFunction->returnParameters().empty())
|
||||||
|
@ -247,11 +247,8 @@ void ContractCompiler::appendFunctionSelector(ContractDefinition const& _contrac
|
|||||||
m_context << returnTag;
|
m_context << returnTag;
|
||||||
appendReturnValuePacker(FunctionType(*fallback).returnParameterTypes(), _contract.isLibrary());
|
appendReturnValuePacker(FunctionType(*fallback).returnParameterTypes(), _contract.isLibrary());
|
||||||
}
|
}
|
||||||
else if (_contract.isLibrary())
|
|
||||||
// Reject invalid library calls and ether sent to a library.
|
|
||||||
m_context.appendJumpTo(m_context.errorTag());
|
|
||||||
else
|
else
|
||||||
m_context << Instruction::STOP; // function not found
|
m_context.appendJumpTo(m_context.errorTag());
|
||||||
|
|
||||||
for (auto const& it: interfaceFunctions)
|
for (auto const& it: interfaceFunctions)
|
||||||
{
|
{
|
||||||
|
@ -114,7 +114,7 @@ BOOST_AUTO_TEST_CASE(location_test)
|
|||||||
shared_ptr<string const> n = make_shared<string>("source");
|
shared_ptr<string const> n = make_shared<string>("source");
|
||||||
AssemblyItems items = compileContract(sourceCode);
|
AssemblyItems items = compileContract(sourceCode);
|
||||||
vector<SourceLocation> locations =
|
vector<SourceLocation> locations =
|
||||||
vector<SourceLocation>(17, SourceLocation(2, 75, n)) +
|
vector<SourceLocation>(18, SourceLocation(2, 75, n)) +
|
||||||
vector<SourceLocation>(28, SourceLocation(20, 72, n)) +
|
vector<SourceLocation>(28, SourceLocation(20, 72, n)) +
|
||||||
vector<SourceLocation>{SourceLocation(42, 51, n), SourceLocation(65, 67, n)} +
|
vector<SourceLocation>{SourceLocation(42, 51, n), SourceLocation(65, 67, n)} +
|
||||||
vector<SourceLocation>(4, SourceLocation(58, 67, n)) +
|
vector<SourceLocation>(4, SourceLocation(58, 67, n)) +
|
||||||
|
@ -2053,6 +2053,7 @@ BOOST_AUTO_TEST_CASE(contracts_as_addresses)
|
|||||||
{
|
{
|
||||||
char const* sourceCode = R"(
|
char const* sourceCode = R"(
|
||||||
contract helper {
|
contract helper {
|
||||||
|
function() { } // can receive ether
|
||||||
}
|
}
|
||||||
contract test {
|
contract test {
|
||||||
helper h;
|
helper h;
|
||||||
@ -2540,6 +2541,19 @@ BOOST_AUTO_TEST_CASE(inherited_fallback_function)
|
|||||||
BOOST_CHECK(callContractFunction("getData()") == encodeArgs(1));
|
BOOST_CHECK(callContractFunction("getData()") == encodeArgs(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(default_fallback_throws)
|
||||||
|
{
|
||||||
|
char const* sourceCode = R"(
|
||||||
|
contract A {
|
||||||
|
function f() returns (bool) {
|
||||||
|
return this.call();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
compileAndRun(sourceCode);
|
||||||
|
BOOST_CHECK(callContractFunction("f()") == encodeArgs(0));
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(event)
|
BOOST_AUTO_TEST_CASE(event)
|
||||||
{
|
{
|
||||||
char const* sourceCode = R"(
|
char const* sourceCode = R"(
|
||||||
@ -5943,6 +5957,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 () {}
|
||||||
}
|
}
|
||||||
)";
|
)";
|
||||||
compileAndRun(sourceCode, 0, "lib");
|
compileAndRun(sourceCode, 0, "lib");
|
||||||
|
@ -1102,6 +1102,16 @@ BOOST_AUTO_TEST_CASE(fallback_function_with_arguments)
|
|||||||
BOOST_CHECK(expectError(text) == Error::Type::TypeError);
|
BOOST_CHECK(expectError(text) == Error::Type::TypeError);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(fallback_function_in_library)
|
||||||
|
{
|
||||||
|
char const* text = R"(
|
||||||
|
library C {
|
||||||
|
function() {}
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
BOOST_CHECK(expectError(text) == Error::Type::TypeError);
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(fallback_function_with_return_parameters)
|
BOOST_AUTO_TEST_CASE(fallback_function_with_return_parameters)
|
||||||
{
|
{
|
||||||
char const* text = R"(
|
char const* text = R"(
|
||||||
|
Loading…
Reference in New Issue
Block a user