diff options
author | chriseth <chris@ethereum.org> | 2018-04-13 03:01:08 +0800 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-04-13 03:01:08 +0800 |
commit | 7054defdd6c202d0943c11cb87ac2748b9bdc62b (patch) | |
tree | 8a69eb34b9089b689d5f467b8cb56b4a74ad04b8 /test/libsolidity | |
parent | 44416d1ac65b2cfae4bb15d39bc84b1a78211baa (diff) | |
parent | 966367305ad511900bedfd9af08114a0b1307399 (diff) | |
download | dexon-solidity-7054defdd6c202d0943c11cb87ac2748b9bdc62b.tar.gz dexon-solidity-7054defdd6c202d0943c11cb87ac2748b9bdc62b.tar.zst dexon-solidity-7054defdd6c202d0943c11cb87ac2748b9bdc62b.zip |
Merge pull request #3364 from ethereum/revertWithReason
Revert with reason
Diffstat (limited to 'test/libsolidity')
-rw-r--r-- | test/libsolidity/Assembly.cpp | 21 | ||||
-rw-r--r-- | test/libsolidity/JSONCompiler.cpp | 8 | ||||
-rw-r--r-- | test/libsolidity/SolidityCompiler.cpp | 4 | ||||
-rw-r--r-- | test/libsolidity/SolidityEndToEndTest.cpp | 208 | ||||
-rw-r--r-- | test/libsolidity/SolidityNameAndTypeResolution.cpp | 22 | ||||
-rw-r--r-- | test/libsolidity/StandardCompiler.cpp | 19 |
6 files changed, 260 insertions, 22 deletions
diff --git a/test/libsolidity/Assembly.cpp b/test/libsolidity/Assembly.cpp index 5519ae0d..77ca363a 100644 --- a/test/libsolidity/Assembly.cpp +++ b/test/libsolidity/Assembly.cpp @@ -157,14 +157,23 @@ BOOST_AUTO_TEST_CASE(location_test) } } )"; - shared_ptr<string const> n = make_shared<string>(""); AssemblyItems items = compileContract(sourceCode); vector<SourceLocation> locations = - vector<SourceLocation>(24, SourceLocation(2, 75, n)) + - vector<SourceLocation>(32, SourceLocation(20, 72, n)) + - vector<SourceLocation>{SourceLocation(42, 51, n), SourceLocation(65, 67, n)} + - vector<SourceLocation>(2, SourceLocation(58, 67, n)) + - vector<SourceLocation>(2, SourceLocation(20, 72, n)); + vector<SourceLocation>(24, SourceLocation(2, 75, make_shared<string>(""))) + + vector<SourceLocation>(2, SourceLocation(20, 72, make_shared<string>(""))) + + vector<SourceLocation>(1, SourceLocation(8, 17, make_shared<string>("--CODEGEN--"))) + + vector<SourceLocation>(3, SourceLocation(5, 7, make_shared<string>("--CODEGEN--"))) + + vector<SourceLocation>(1, SourceLocation(30, 31, make_shared<string>("--CODEGEN--"))) + + vector<SourceLocation>(1, SourceLocation(27, 28, make_shared<string>("--CODEGEN--"))) + + vector<SourceLocation>(1, SourceLocation(20, 32, make_shared<string>("--CODEGEN--"))) + + vector<SourceLocation>(1, SourceLocation(5, 7, make_shared<string>("--CODEGEN--"))) + + vector<SourceLocation>(24, SourceLocation(20, 72, make_shared<string>(""))) + + vector<SourceLocation>(1, SourceLocation(42, 51, make_shared<string>(""))) + + vector<SourceLocation>(1, SourceLocation(65, 67, make_shared<string>(""))) + + vector<SourceLocation>(2, SourceLocation(58, 67, make_shared<string>(""))) + + vector<SourceLocation>(2, SourceLocation(20, 72, make_shared<string>(""))); + + checkAssemblyLocations(items, locations); } diff --git a/test/libsolidity/JSONCompiler.cpp b/test/libsolidity/JSONCompiler.cpp index cdcc22a6..2b3df3a7 100644 --- a/test/libsolidity/JSONCompiler.cpp +++ b/test/libsolidity/JSONCompiler.cpp @@ -111,7 +111,7 @@ BOOST_AUTO_TEST_CASE(basic_compilation) BOOST_CHECK(contract["bytecode"].isString()); BOOST_CHECK_EQUAL( dev::test::bytecodeSansMetadata(contract["bytecode"].asString()), - "60806040523415600e57600080fd5b603580601b6000396000f3006080604052600080fd00" + "6080604052348015600f57600080fd5b50603580601d6000396000f3006080604052600080fd00" ); BOOST_CHECK(contract["runtimeBytecode"].isString()); BOOST_CHECK_EQUAL( @@ -122,7 +122,7 @@ BOOST_AUTO_TEST_CASE(basic_compilation) BOOST_CHECK(contract["gasEstimates"].isObject()); BOOST_CHECK_EQUAL( dev::jsonCompactPrint(contract["gasEstimates"]), - "{\"creation\":[61,10600],\"external\":{},\"internal\":{}}" + "{\"creation\":[66,10600],\"external\":{},\"internal\":{}}" ); BOOST_CHECK(contract["metadata"].isString()); BOOST_CHECK(dev::test::isValidMetadata(contract["metadata"].asString())); @@ -153,7 +153,7 @@ BOOST_AUTO_TEST_CASE(single_compilation) BOOST_CHECK(contract["bytecode"].isString()); BOOST_CHECK_EQUAL( dev::test::bytecodeSansMetadata(contract["bytecode"].asString()), - "60806040523415600e57600080fd5b603580601b6000396000f3006080604052600080fd00" + "6080604052348015600f57600080fd5b50603580601d6000396000f3006080604052600080fd00" ); BOOST_CHECK(contract["runtimeBytecode"].isString()); BOOST_CHECK_EQUAL( @@ -164,7 +164,7 @@ BOOST_AUTO_TEST_CASE(single_compilation) BOOST_CHECK(contract["gasEstimates"].isObject()); BOOST_CHECK_EQUAL( dev::jsonCompactPrint(contract["gasEstimates"]), - "{\"creation\":[61,10600],\"external\":{},\"internal\":{}}" + "{\"creation\":[66,10600],\"external\":{},\"internal\":{}}" ); BOOST_CHECK(contract["metadata"].isString()); BOOST_CHECK(dev::test::isValidMetadata(contract["metadata"].asString())); diff --git a/test/libsolidity/SolidityCompiler.cpp b/test/libsolidity/SolidityCompiler.cpp index e87ab603..90540f3e 100644 --- a/test/libsolidity/SolidityCompiler.cpp +++ b/test/libsolidity/SolidityCompiler.cpp @@ -47,8 +47,8 @@ BOOST_AUTO_TEST_CASE(does_not_include_creation_time_only_internal_functions) BOOST_REQUIRE_MESSAGE(m_compiler.compile(), "Compiling contract failed"); bytes const& creationBytecode = m_compiler.object("C").bytecode; bytes const& runtimeBytecode = m_compiler.runtimeObject("C").bytecode; - BOOST_CHECK(creationBytecode.size() >= 120); - BOOST_CHECK(creationBytecode.size() <= 150); + BOOST_CHECK(creationBytecode.size() >= 130); + BOOST_CHECK(creationBytecode.size() <= 160); BOOST_CHECK(runtimeBytecode.size() >= 50); BOOST_CHECK(runtimeBytecode.size() <= 70); } diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index 037afb92..cbeca215 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -10458,6 +10458,214 @@ BOOST_AUTO_TEST_CASE(revert) ABI_CHECK(callContractFunction("a()"), encodeArgs(u256(42))); } +BOOST_AUTO_TEST_CASE(revert_with_cause) +{ + char const* sourceCode = R"( + contract D { + function f() public { + revert("test123"); + } + function g() public { + revert("test1234567890123456789012345678901234567890"); + } + } + contract C { + D d = new D(); + function forward(address target, bytes data) internal returns (bool success, bytes retval) { + uint retsize; + assembly { + success := call(not(0), target, 0, add(data, 0x20), mload(data), 0, 0) + retsize := returndatasize() + } + retval = new bytes(retsize); + assembly { + returndatacopy(add(retval, 0x20), 0, returndatasize()) + } + } + function f() public returns (bool, bytes) { + return forward(address(d), msg.data); + } + function g() public returns (bool, bytes) { + return forward(address(d), msg.data); + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + bool const haveReturndata = dev::test::Options::get().evmVersion().supportsReturndata(); + bytes const errorSignature = bytes{0x08, 0xc3, 0x79, 0xa0}; + ABI_CHECK(callContractFunction("f()"), haveReturndata ? encodeArgs(0, 0x40, 0x64) + errorSignature + encodeArgs(0x20, 7, "test123") + bytes(28, 0) : bytes()); + ABI_CHECK(callContractFunction("g()"), haveReturndata ? encodeArgs(0, 0x40, 0x84) + errorSignature + encodeArgs(0x20, 44, "test1234567890123456789012345678901234567890") + bytes(28, 0): bytes()); +} + +BOOST_AUTO_TEST_CASE(require_with_message) +{ + char const* sourceCode = R"( + contract D { + bool flag = false; + string storageError = "abc"; + function f(uint x) public { + require(x > 7, "failed"); + } + function g() public { + // As a side-effect of internalFun, the flag will be set to true + // (even if the condition is true), + // but it will only throw in the next evaluation. + bool flagCopy = flag; + require(flagCopy == false, internalFun()); + } + function internalFun() returns (string) { + flag = true; + return "only on second run"; + } + function h() public { + require(false, storageError); + } + } + contract C { + D d = new D(); + function forward(address target, bytes data) internal returns (bool success, bytes retval) { + uint retsize; + assembly { + success := call(not(0), target, 0, add(data, 0x20), mload(data), 0, 0) + retsize := returndatasize() + } + retval = new bytes(retsize); + assembly { + returndatacopy(add(retval, 0x20), 0, returndatasize()) + } + } + function f(uint x) public returns (bool, bytes) { + return forward(address(d), msg.data); + } + function g() public returns (bool, bytes) { + return forward(address(d), msg.data); + } + function h() public returns (bool, bytes) { + return forward(address(d), msg.data); + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + bool const haveReturndata = dev::test::Options::get().evmVersion().supportsReturndata(); + bytes const errorSignature = bytes{0x08, 0xc3, 0x79, 0xa0}; + ABI_CHECK(callContractFunction("f(uint256)", 8), haveReturndata ? encodeArgs(1, 0x40, 0) : bytes()); + ABI_CHECK(callContractFunction("f(uint256)", 5), haveReturndata ? encodeArgs(0, 0x40, 0x64) + errorSignature + encodeArgs(0x20, 6, "failed") + bytes(28, 0) : bytes()); + ABI_CHECK(callContractFunction("g()"), haveReturndata ? encodeArgs(1, 0x40, 0) : bytes()); + ABI_CHECK(callContractFunction("g()"), haveReturndata ? encodeArgs(0, 0x40, 0x64) + errorSignature + encodeArgs(0x20, 18, "only on second run") + bytes(28, 0) : bytes()); + ABI_CHECK(callContractFunction("h()"), haveReturndata ? encodeArgs(0, 0x40, 0x64) + errorSignature + encodeArgs(0x20, 3, "abc") + bytes(28, 0): bytes()); +} + +BOOST_AUTO_TEST_CASE(bubble_up_error_messages) +{ + char const* sourceCode = R"( + contract D { + function f() public { + revert("message"); + } + function g() public { + this.f(); + } + } + contract C { + D d = new D(); + function forward(address target, bytes data) internal returns (bool success, bytes retval) { + uint retsize; + assembly { + success := call(not(0), target, 0, add(data, 0x20), mload(data), 0, 0) + retsize := returndatasize() + } + retval = new bytes(retsize); + assembly { + returndatacopy(add(retval, 0x20), 0, returndatasize()) + } + } + function f() public returns (bool, bytes) { + return forward(address(d), msg.data); + } + function g() public returns (bool, bytes) { + return forward(address(d), msg.data); + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + bool const haveReturndata = dev::test::Options::get().evmVersion().supportsReturndata(); + bytes const errorSignature = bytes{0x08, 0xc3, 0x79, 0xa0}; + ABI_CHECK(callContractFunction("f()"), haveReturndata ? encodeArgs(0, 0x40, 0x64) + errorSignature + encodeArgs(0x20, 7, "message") + bytes(28, 0) : bytes()); + ABI_CHECK(callContractFunction("g()"), haveReturndata ? encodeArgs(0, 0x40, 0x64) + errorSignature + encodeArgs(0x20, 7, "message") + bytes(28, 0) : bytes()); +} + +BOOST_AUTO_TEST_CASE(bubble_up_error_messages_through_transfer) +{ + char const* sourceCode = R"( + contract D { + function() public payable { + revert("message"); + } + function f() public { + this.transfer(0); + } + } + contract C { + D d = new D(); + function forward(address target, bytes data) internal returns (bool success, bytes retval) { + uint retsize; + assembly { + success := call(not(0), target, 0, add(data, 0x20), mload(data), 0, 0) + retsize := returndatasize() + } + retval = new bytes(retsize); + assembly { + returndatacopy(add(retval, 0x20), 0, returndatasize()) + } + } + function f() public returns (bool, bytes) { + return forward(address(d), msg.data); + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + bool const haveReturndata = dev::test::Options::get().evmVersion().supportsReturndata(); + bytes const errorSignature = bytes{0x08, 0xc3, 0x79, 0xa0}; + ABI_CHECK(callContractFunction("f()"), haveReturndata ? encodeArgs(0, 0x40, 0x64) + errorSignature + encodeArgs(0x20, 7, "message") + bytes(28, 0) : bytes()); +} + +BOOST_AUTO_TEST_CASE(bubble_up_error_messages_through_create) +{ + char const* sourceCode = R"( + contract E { + function E() { + revert("message"); + } + } + contract D { + function f() public { + var x = new E(); + } + } + contract C { + D d = new D(); + function forward(address target, bytes data) internal returns (bool success, bytes retval) { + uint retsize; + assembly { + success := call(not(0), target, 0, add(data, 0x20), mload(data), 0, 0) + retsize := returndatasize() + } + retval = new bytes(retsize); + assembly { + returndatacopy(add(retval, 0x20), 0, returndatasize()) + } + } + function f() public returns (bool, bytes) { + return forward(address(d), msg.data); + } + } + )"; + compileAndRun(sourceCode, 0, "C"); + bool const haveReturndata = dev::test::Options::get().evmVersion().supportsReturndata(); + bytes const errorSignature = bytes{0x08, 0xc3, 0x79, 0xa0}; + ABI_CHECK(callContractFunction("f()"), haveReturndata ? encodeArgs(0, 0x40, 0x64) + errorSignature + encodeArgs(0x20, 7, "message") + bytes(28, 0) : bytes()); +} + BOOST_AUTO_TEST_CASE(negative_stack_height) { // This code was causing negative stack height during code generation diff --git a/test/libsolidity/SolidityNameAndTypeResolution.cpp b/test/libsolidity/SolidityNameAndTypeResolution.cpp index 6a33cbbd..d438a9dc 100644 --- a/test/libsolidity/SolidityNameAndTypeResolution.cpp +++ b/test/libsolidity/SolidityNameAndTypeResolution.cpp @@ -5987,14 +5987,30 @@ BOOST_AUTO_TEST_CASE(bare_revert) } } )"; - CHECK_WARNING(text, "Statement has no effect."); + CHECK_ERROR(text, TypeError, "No matching declaration found"); +} + +BOOST_AUTO_TEST_CASE(revert_with_reason) +{ + char const* text = R"( + contract C { + function f(uint x) pure public { + if (x > 7) + revert("abc"); + else + revert(); + } + } + )"; + CHECK_SUCCESS_NO_WARNINGS(text); } BOOST_AUTO_TEST_CASE(bare_others) { CHECK_WARNING("contract C { function f() pure public { selfdestruct; } }", "Statement has no effect."); CHECK_WARNING("contract C { function f() pure public { assert; } }", "Statement has no effect."); - CHECK_WARNING("contract C { function f() pure public { require; } }", "Statement has no effect."); + // This is different because it does have overloads. + CHECK_ERROR("contract C { function f() pure public { require; } }", TypeError, "No matching declaration found after variable lookup."); CHECK_WARNING("contract C { function f() pure public { suicide; } }", "Statement has no effect."); } @@ -6493,7 +6509,7 @@ BOOST_AUTO_TEST_CASE(does_not_error_transfer_regular_function) CHECK_SUCCESS_NO_WARNINGS(text); } -BOOST_AUTO_TEST_CASE(returndatacopy_as_variable) +BOOST_AUTO_TEST_CASE(returndatasize_as_variable) { char const* text = R"( contract c { function f() public { uint returndatasize; assembly { returndatasize }}} diff --git a/test/libsolidity/StandardCompiler.cpp b/test/libsolidity/StandardCompiler.cpp index b285a2a0..74bf01b2 100644 --- a/test/libsolidity/StandardCompiler.cpp +++ b/test/libsolidity/StandardCompiler.cpp @@ -261,19 +261,24 @@ BOOST_AUTO_TEST_CASE(basic_compilation) BOOST_CHECK(contract["evm"]["bytecode"]["object"].isString()); BOOST_CHECK_EQUAL( dev::test::bytecodeSansMetadata(contract["evm"]["bytecode"]["object"].asString()), - "60806040523415600e57600080fd5b603580601b6000396000f3006080604052600080fd00" + "6080604052348015600f57600080fd5b50603580601d6000396000f3006080604052600080fd00" ); BOOST_CHECK(contract["evm"]["assembly"].isString()); BOOST_CHECK(contract["evm"]["assembly"].asString().find( - " /* \"fileA\":0:14 contract A { } */\n mstore(0x40, 0x80)\n jumpi(tag_1, iszero(callvalue))\n" - " 0x0\n dup1\n revert\ntag_1:\n dataSize(sub_0)\n dup1\n dataOffset(sub_0)\n 0x0\n codecopy\n 0x0\n" - " return\nstop\n\nsub_0: assembly {\n /* \"fileA\":0:14 contract A { } */\n" - " mstore(0x40, 0x80)\n 0x0\n dup1\n revert\n\n" - " auxdata: 0xa165627a7a7230582") == 0); + " /* \"fileA\":0:14 contract A { } */\n mstore(0x40, 0x80)\n " + "callvalue\n /* \"--CODEGEN--\":8:17 */\n dup1\n " + "/* \"--CODEGEN--\":5:7 */\n iszero\n tag_1\n jumpi\n " + "/* \"--CODEGEN--\":30:31 */\n 0x0\n /* \"--CODEGEN--\":27:28 */\n " + "dup1\n /* \"--CODEGEN--\":20:32 */\n revert\n /* \"--CODEGEN--\":5:7 */\n" + "tag_1:\n /* \"fileA\":0:14 contract A { } */\n pop\n dataSize(sub_0)\n dup1\n " + "dataOffset(sub_0)\n 0x0\n codecopy\n 0x0\n return\nstop\n\nsub_0: assembly {\n " + "/* \"fileA\":0:14 contract A { } */\n mstore(0x40, 0x80)\n 0x0\n " + "dup1\n revert\n\n auxdata: 0xa165627a7a72305820" + ) == 0); BOOST_CHECK(contract["evm"]["gasEstimates"].isObject()); BOOST_CHECK_EQUAL( dev::jsonCompactPrint(contract["evm"]["gasEstimates"]), - "{\"creation\":{\"codeDepositCost\":\"10600\",\"executionCost\":\"61\",\"totalCost\":\"10661\"}}" + "{\"creation\":{\"codeDepositCost\":\"10600\",\"executionCost\":\"66\",\"totalCost\":\"10666\"}}" ); BOOST_CHECK(contract["metadata"].isString()); BOOST_CHECK(dev::test::isValidMetadata(contract["metadata"].asString())); |