Throw if contract creation fails.

This commit is contained in:
chriseth 2016-07-11 15:04:33 +02:00
parent e3e4d84f33
commit 2a560b798b
3 changed files with 67 additions and 0 deletions

View File

@ -106,6 +106,43 @@ of unused parameters (especially return parameters) can be omitted.
}
}
.. index:: ! new, contracts;creating
.. _creating-contracts:
Creating Contracts via new
==========================
A contract can create a new contract using the ``new`` keyword. The full
code of the contract to be created has to be known and thus recursive
creation-dependencies are now possible.
::
contract D {
uint x;
function D(uint a) {
x = a;
}
}
contract C {
D d = new D(4); // will be executed as part of C's constructor
function createD(uint arg) {
D newD = new D(arg);
}
function createAndEndowD(uint arg, uint amount) {
// Send ether along with the creation
D newD = (new D).value(amount)(arg);
}
}
As seen in the example, it is possible to forward Ether to the creation,
but it is not possible to limit the amount of gas. If the creation fails
(due to out-of-stack, not enough balance or other problems), an exception
is thrown.
Order of Evaluation of Expressions
==================================

View File

@ -533,6 +533,9 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
else
m_context << u256(0);
m_context << Instruction::CREATE;
// Check if zero (out of stack or not enough balance).
m_context << Instruction::DUP1 << Instruction::ISZERO;
m_context.appendConditionalJumpTo(m_context.errorTag());
if (function.valueSet())
m_context << swapInstruction(1) << Instruction::POP;
break;

View File

@ -6839,6 +6839,33 @@ BOOST_AUTO_TEST_CASE(skip_dynamic_types_for_structs)
BOOST_CHECK(callContractFunction("g()") == encodeArgs(u256(2), u256(6)));
}
BOOST_AUTO_TEST_CASE(failed_create)
{
char const* sourceCode = R"(
contract D { }
contract C {
uint public x;
function f(uint amount) returns (address) {
x++;
return (new D).value(amount)();
}
function stack(uint depth) returns (address) {
if (depth < 1024)
return this.stack(depth - 1);
else
return f(0);
}
}
)";
compileAndRun(sourceCode, 20, "C");
BOOST_CHECK(callContractFunction("f(uint256)", 20) != encodeArgs(u256(0)));
BOOST_CHECK(callContractFunction("x()") == encodeArgs(u256(1)));
BOOST_CHECK(callContractFunction("f(uint256)", 20) == encodeArgs());
BOOST_CHECK(callContractFunction("x()") == encodeArgs(u256(1)));
BOOST_CHECK(callContractFunction("stack(uint256)", 1023) == encodeArgs());
BOOST_CHECK(callContractFunction("x()") == encodeArgs(u256(1)));
}
BOOST_AUTO_TEST_CASE(create_dynamic_array_with_zero_length)
{
char const* sourceCode = R"(