Merge pull request #1702 from ethereum/assertError

Change effect of assert to invalid opcode.
This commit is contained in:
Yoichi Hirai 2017-03-03 18:25:50 +01:00 committed by GitHub
commit cfbbd89daf
5 changed files with 25 additions and 27 deletions

View File

@ -399,7 +399,6 @@ Currently, Solidity automatically generates a runtime exception in the following
While a user-provided exception is generated in the following situations: While a user-provided exception is generated in the following situations:
#. Calling ``throw``. #. Calling ``throw``.
#. The condition of ``assert(condition)`` is not met.
Internally, Solidity performs a revert operation (instruction ``0xfd``) when a user-provided exception is thrown. In contrast, it performs an invalid operation Internally, Solidity performs a revert operation (instruction ``0xfd``) when a user-provided exception is thrown. In contrast, it performs an invalid operation
(instruction ``0xfe``) if a runtime exception is encountered. In both cases, this causes (instruction ``0xfe``) if a runtime exception is encountered. In both cases, this causes

View File

@ -435,7 +435,7 @@ The following is the order of precedence for operators, listed in order of evalu
| *16* | Comma operator | ``,`` | | *16* | Comma operator | ``,`` |
+------------+-------------------------------------+--------------------------------------------+ +------------+-------------------------------------+--------------------------------------------+
.. index:: block, coinbase, difficulty, number, block;number, timestamp, block;timestamp, msg, data, gas, sender, value, now, gas price, origin, assert, revert, keccak256, ripemd160, sha256, ecrecover, addmod, mulmod, cryptography, this, super, selfdestruct, balance, send .. index:: block, coinbase, difficulty, number, block;number, timestamp, block;timestamp, msg, data, gas, sender, value, now, gas price, origin, revert, keccak256, ripemd160, sha256, ecrecover, addmod, mulmod, cryptography, this, super, selfdestruct, balance, send
Global Variables Global Variables
================ ================
@ -461,7 +461,6 @@ Global Variables
- ``ecrecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) returns (address)``: recover address associated with the public key from elliptic curve signature, return zero on error - ``ecrecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) returns (address)``: recover address associated with the public key from elliptic curve signature, return zero on error
- ``addmod(uint x, uint y, uint k) returns (uint)``: compute ``(x + y) % k`` where the addition is performed with arbitrary precision and does not wrap around at ``2**256`` - ``addmod(uint x, uint y, uint k) returns (uint)``: compute ``(x + y) % k`` where the addition is performed with arbitrary precision and does not wrap around at ``2**256``
- ``mulmod(uint x, uint y, uint k) returns (uint)``: compute ``(x * y) % k`` where the multiplication is performed with arbitrary precision and does not wrap around at ``2**256`` - ``mulmod(uint x, uint y, uint k) returns (uint)``: compute ``(x * y) % k`` where the multiplication is performed with arbitrary precision and does not wrap around at ``2**256``
- ``assert(bool condition)``: throws if the condition is false
- ``this`` (current contract's type): the current contract, explicitly convertible to ``address`` - ``this`` (current contract's type): the current contract, explicitly convertible to ``address``
- ``super``: the contract one level higher in the inheritance hierarchy - ``super``: the contract one level higher in the inheritance hierarchy
- ``selfdestruct(address recipient)``: destroy the current contract, sending its funds to the given address - ``selfdestruct(address recipient)``: destroy the current contract, sending its funds to the given address

View File

@ -66,8 +66,9 @@ m_magicVariables(vector<shared_ptr<MagicVariableDeclaration const>>{make_shared<
make_shared<FunctionType>(strings{"bytes32", "uint8", "bytes32", "bytes32"}, strings{"address"}, FunctionType::Location::ECRecover)), make_shared<FunctionType>(strings{"bytes32", "uint8", "bytes32", "bytes32"}, strings{"address"}, FunctionType::Location::ECRecover)),
make_shared<MagicVariableDeclaration>("ripemd160", make_shared<MagicVariableDeclaration>("ripemd160",
make_shared<FunctionType>(strings(), strings{"bytes20"}, FunctionType::Location::RIPEMD160, true)), make_shared<FunctionType>(strings(), strings{"bytes20"}, FunctionType::Location::RIPEMD160, true)),
make_shared<MagicVariableDeclaration>("assert", // Disabled until decision about semantics of assert is made.
make_shared<FunctionType>(strings{"bool"}, strings{}, FunctionType::Location::Assert)), // make_shared<MagicVariableDeclaration>("assert",
// make_shared<FunctionType>(strings{"bool"}, strings{}, FunctionType::Location::Assert)),
make_shared<MagicVariableDeclaration>("revert", make_shared<MagicVariableDeclaration>("revert",
make_shared<FunctionType>(strings(), strings(), FunctionType::Location::Revert))}) make_shared<FunctionType>(strings(), strings(), FunctionType::Location::Revert))})
{ {

View File

@ -885,9 +885,8 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
// jump if condition was met // jump if condition was met
m_context << Instruction::ISZERO << Instruction::ISZERO; m_context << Instruction::ISZERO << Instruction::ISZERO;
auto success = m_context.appendConditionalJump(); auto success = m_context.appendConditionalJump();
// condition was not met, abort // condition was not met, flag an error
m_context << u256(0) << u256(0); m_context << Instruction::INVALID;
m_context << Instruction::REVERT;
// the success branch // the success branch
m_context << success; m_context << success;
break; break;

View File

@ -9119,24 +9119,24 @@ BOOST_AUTO_TEST_CASE(invalid_instruction)
BOOST_CHECK(callContractFunction("f()") == encodeArgs()); BOOST_CHECK(callContractFunction("f()") == encodeArgs());
} }
BOOST_AUTO_TEST_CASE(assert) //BOOST_AUTO_TEST_CASE(assert)
{ //{
char const* sourceCode = R"( // char const* sourceCode = R"(
contract C { // contract C {
function f() { // function f() {
assert(false); // assert(false);
} // }
function g(bool val) returns (bool) { // function g(bool val) returns (bool) {
assert(val == true); // assert(val == true);
return true; // return true;
} // }
} // }
)"; // )";
compileAndRun(sourceCode, 0, "C"); // compileAndRun(sourceCode, 0, "C");
BOOST_CHECK(callContractFunction("f()") == encodeArgs()); // BOOST_CHECK(callContractFunction("f()") == encodeArgs());
BOOST_CHECK(callContractFunction("g(bool)", false) == encodeArgs()); // BOOST_CHECK(callContractFunction("g(bool)", false) == encodeArgs());
BOOST_CHECK(callContractFunction("g(bool)", true) == encodeArgs(true)); // BOOST_CHECK(callContractFunction("g(bool)", true) == encodeArgs(true));
} //}
BOOST_AUTO_TEST_CASE(revert) BOOST_AUTO_TEST_CASE(revert)
{ {