diff --git a/Changelog.md b/Changelog.md index 3bfda8d62..43fdf1199 100644 --- a/Changelog.md +++ b/Changelog.md @@ -3,6 +3,7 @@ Breaking Changes: * Assembler: The artificial ASSIGNIMMUTABLE opcode and the corresponding builtin in the "EVM with object access" dialect of Yul take the base offset of the code to modify as additional argument. * Code Generator: All arithmetic is checked by default. These checks can be disabled using ``unchecked { ... }``. + * General: Remove global functions ``log0``, ``log1``, ``log2``, ``log3`` and ``log4``. * Type System: Unary negation can only be used on signed integers, not on unsigned integers. * Type System: Disallow explicit conversions from negative literals and literals larger than ``type(uint160).max`` to ``address`` type. * Parser: Exponentiation is right associative. ``a**b**c`` is parsed as ``a**(b**c)``. diff --git a/docs/080-breaking-changes.rst b/docs/080-breaking-changes.rst index ac1d377f5..cbfb6a565 100644 --- a/docs/080-breaking-changes.rst +++ b/docs/080-breaking-changes.rst @@ -17,3 +17,10 @@ and it does something else afterwards. * Explicit conversions from negative literals and literals larger than ``type(uint160).max`` to ``address`` are now disallowed. * Exponentiation is right associative, i.e., the expression ``a**b**c`` is parsed as ``a**(b**c)``. Before 0.8.0, it was parsed as ``(a**b)**c``. + +Syntactic Only Changes +====================== + +* The global functions ``log0``, ``log1``, ``log2``, ``log3`` and ``log4`` have been removed. + +These are low-level functions that were largely unused. Their behaviour can be accessed from inline assembly. \ No newline at end of file diff --git a/docs/contracts/events.rst b/docs/contracts/events.rst index 55b16da91..d40b34f62 100644 --- a/docs/contracts/events.rst +++ b/docs/contracts/events.rst @@ -126,37 +126,6 @@ The output of the above looks like the following (trimmed): } } -.. index:: ! log - -Low-Level Interface to Logs -=========================== - -It is also possible to access the low-level interface to the logging -mechanism via the functions ``log0``, ``log1``, ``log2``, ``log3`` and ``log4``. -Each function ``logi`` takes ``i + 1`` parameter of type ``bytes32``, where the first -argument will be used for the data part of the log and the others -as topics. The event call above can be performed in the same way as - -:: - - // SPDX-License-Identifier: GPL-3.0 - pragma solidity >=0.4.10 <0.9.0; - - contract C { - function f() public payable { - uint256 _id = 0x420042; - log3( - bytes32(msg.value), - bytes32(0x50cb9fe53daa9737b786ab3646f04d0150dc50ef4e75f59509d83667ad5adb20), - bytes32(uint256(msg.sender)), - bytes32(_id) - ); - } - } - -where the long hexadecimal number is equal to -``keccak256("Deposit(address,bytes32,uint256)")``, the signature of the event. - Additional Resources for Understanding Events ============================================== diff --git a/libsolidity/analysis/GlobalContext.cpp b/libsolidity/analysis/GlobalContext.cpp index dee7e8220..2bf893675 100644 --- a/libsolidity/analysis/GlobalContext.cpp +++ b/libsolidity/analysis/GlobalContext.cpp @@ -45,11 +45,6 @@ int magicVariableToID(std::string const& _name) else if (_name == "ecrecover") return -6; else if (_name == "gasleft") return -7; else if (_name == "keccak256") return -8; - else if (_name == "log0") return -10; - else if (_name == "log1") return -11; - else if (_name == "log2") return -12; - else if (_name == "log3") return -13; - else if (_name == "log4") return -14; else if (_name == "msg") return -15; else if (_name == "mulmod") return -16; else if (_name == "now") return -17; @@ -83,11 +78,6 @@ inline vector> constructMagicVariable magicVarDecl("ecrecover", TypeProvider::function(strings{"bytes32", "uint8", "bytes32", "bytes32"}, strings{"address"}, FunctionType::Kind::ECRecover, false, StateMutability::Pure)), magicVarDecl("gasleft", TypeProvider::function(strings(), strings{"uint256"}, FunctionType::Kind::GasLeft, false, StateMutability::View)), magicVarDecl("keccak256", TypeProvider::function(strings{"bytes memory"}, strings{"bytes32"}, FunctionType::Kind::KECCAK256, false, StateMutability::Pure)), - magicVarDecl("log0", TypeProvider::function(strings{"bytes32"}, strings{}, FunctionType::Kind::Log0)), - magicVarDecl("log1", TypeProvider::function(strings{"bytes32", "bytes32"}, strings{}, FunctionType::Kind::Log1)), - magicVarDecl("log2", TypeProvider::function(strings{"bytes32", "bytes32", "bytes32"}, strings{}, FunctionType::Kind::Log2)), - magicVarDecl("log3", TypeProvider::function(strings{"bytes32", "bytes32", "bytes32", "bytes32"}, strings{}, FunctionType::Kind::Log3)), - magicVarDecl("log4", TypeProvider::function(strings{"bytes32", "bytes32", "bytes32", "bytes32", "bytes32"}, strings{}, FunctionType::Kind::Log4)), magicVarDecl("msg", TypeProvider::magic(MagicType::Kind::Message)), magicVarDecl("mulmod", TypeProvider::function(strings{"uint256", "uint256", "uint256"}, strings{"uint256"}, FunctionType::Kind::MulMod, false, StateMutability::Pure)), magicVarDecl("now", TypeProvider::uint256()), diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index 704a4a26b..2a18d8a4b 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -3044,11 +3044,6 @@ string FunctionType::richIdentifier() const case Kind::ECRecover: id += "ecrecover"; break; case Kind::SHA256: id += "sha256"; break; case Kind::RIPEMD160: id += "ripemd160"; break; - case Kind::Log0: id += "log0"; break; - case Kind::Log1: id += "log1"; break; - case Kind::Log2: id += "log2"; break; - case Kind::Log3: id += "log3"; break; - case Kind::Log4: id += "log4"; break; case Kind::GasLeft: id += "gasleft"; break; case Kind::Event: id += "event"; break; case Kind::SetGas: id += "setgas"; break; diff --git a/libsolidity/ast/Types.h b/libsolidity/ast/Types.h index 66df9b249..707a69253 100644 --- a/libsolidity/ast/Types.h +++ b/libsolidity/ast/Types.h @@ -1138,11 +1138,6 @@ public: ECRecover, ///< CALL to special contract for ecrecover SHA256, ///< CALL to special contract for sha256 RIPEMD160, ///< CALL to special contract for ripemd160 - Log0, - Log1, - Log2, - Log3, - Log4, Event, ///< syntactic sugar for LOG* SetGas, ///< modify the default gas value for the function call SetValue, ///< modify the default value transfer for the function call diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp index 7303f1429..781871a13 100644 --- a/libsolidity/codegen/ExpressionCompiler.cpp +++ b/libsolidity/codegen/ExpressionCompiler.cpp @@ -851,26 +851,6 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) } break; } - case FunctionType::Kind::Log0: - case FunctionType::Kind::Log1: - case FunctionType::Kind::Log2: - case FunctionType::Kind::Log3: - case FunctionType::Kind::Log4: - { - unsigned logNumber = static_cast(function.kind()) - static_cast(FunctionType::Kind::Log0); - for (unsigned arg = logNumber; arg > 0; --arg) - acceptAndConvert(*arguments[arg], *function.parameterTypes()[arg], true); - arguments.front()->accept(*this); - utils().fetchFreeMemoryPointer(); - solAssert(function.parameterTypes().front()->isValueType(), ""); - utils().packedEncode( - {arguments.front()->annotation().type}, - {function.parameterTypes().front()} - ); - utils().toSizeAfterFreeMemoryPointer(); - m_context << logInstruction(logNumber); - break; - } case FunctionType::Kind::Event: { _functionCall.expression().accept(*this); @@ -1415,11 +1395,6 @@ bool ExpressionCompiler::visit(MemberAccess const& _memberAccess) case FunctionType::Kind::BareDelegateCall: case FunctionType::Kind::BareStaticCall: case FunctionType::Kind::Transfer: - case FunctionType::Kind::Log0: - case FunctionType::Kind::Log1: - case FunctionType::Kind::Log2: - case FunctionType::Kind::Log3: - case FunctionType::Kind::Log4: case FunctionType::Kind::ECRecover: case FunctionType::Kind::SHA256: case FunctionType::Kind::RIPEMD160: diff --git a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp index 6102b8603..cc95efd60 100644 --- a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp +++ b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp @@ -1329,34 +1329,6 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall) define(_functionCall) << functions[functionType->kind()] << "(" << args << ")\n"; break; } - case FunctionType::Kind::Log0: - case FunctionType::Kind::Log1: - case FunctionType::Kind::Log2: - case FunctionType::Kind::Log3: - case FunctionType::Kind::Log4: - { - unsigned logNumber = static_cast(functionType->kind()) - static_cast(FunctionType::Kind::Log0); - solAssert(arguments.size() == logNumber + 1, ""); - ABIFunctions abi(m_context.evmVersion(), m_context.revertStrings(), m_context.functionCollector()); - string indexedArgs; - for (unsigned arg = 0; arg < logNumber; ++arg) - indexedArgs += ", " + expressionAsType(*arguments[arg + 1], *(parameterTypes[arg + 1])); - Whiskers templ(R"({ - let := - let := (, ) - (, sub(, ) ) - })"); - templ("pos", m_context.newYulVariable()); - templ("end", m_context.newYulVariable()); - templ("freeMemory", freeMemory()); - templ("encode", abi.tupleEncoder({arguments.front()->annotation().type}, {parameterTypes.front()})); - templ("nonIndexedArgs", IRVariable(*arguments.front()).commaSeparatedList()); - templ("log", "log" + to_string(logNumber)); - templ("indexedArgs", indexedArgs); - m_code << templ.render(); - - break; - } case FunctionType::Kind::Creation: { solAssert(!functionType->gasSet(), "Gas limit set for contract creation."); @@ -1854,11 +1826,6 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess) case FunctionType::Kind::BareDelegateCall: case FunctionType::Kind::BareStaticCall: case FunctionType::Kind::Transfer: - case FunctionType::Kind::Log0: - case FunctionType::Kind::Log1: - case FunctionType::Kind::Log2: - case FunctionType::Kind::Log3: - case FunctionType::Kind::Log4: case FunctionType::Kind::ECRecover: case FunctionType::Kind::SHA256: case FunctionType::Kind::RIPEMD160: diff --git a/libsolidity/formal/SMTEncoder.cpp b/libsolidity/formal/SMTEncoder.cpp index ab31d658d..3d867776a 100644 --- a/libsolidity/formal/SMTEncoder.cpp +++ b/libsolidity/formal/SMTEncoder.cpp @@ -662,13 +662,8 @@ void SMTEncoder::endVisit(FunctionCall const& _funCall) case FunctionType::Kind::ArrayPop: arrayPop(_funCall); break; - case FunctionType::Kind::Log0: - case FunctionType::Kind::Log1: - case FunctionType::Kind::Log2: - case FunctionType::Kind::Log3: - case FunctionType::Kind::Log4: case FunctionType::Kind::Event: - // These can be safely ignored. + // This can be safely ignored. break; case FunctionType::Kind::ObjectCreation: visitObjectCreation(_funCall); diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index a2a3d58ff..49267e753 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -1177,139 +1177,6 @@ BOOST_AUTO_TEST_CASE(uncalled_blockhash) ) } -BOOST_AUTO_TEST_CASE(log0) -{ - char const* sourceCode = R"( - contract test { - function a() public { - log0(bytes32(uint256(1))); - } - } - )"; - ALSO_VIA_YUL( - DISABLE_EWASM_TESTRUN() - - compileAndRun(sourceCode); - callContractFunction("a()"); - BOOST_REQUIRE_EQUAL(numLogs(), 1); - BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress); - BOOST_CHECK_EQUAL(h256(logData(0)), h256(u256(1))); - BOOST_CHECK_EQUAL(numLogTopics(0), 0); - ) -} - -BOOST_AUTO_TEST_CASE(log1) -{ - char const* sourceCode = R"( - contract test { - function a() public { - log1(bytes32(uint256(1)), bytes32(uint256(2))); - } - } - )"; - ALSO_VIA_YUL( - DISABLE_EWASM_TESTRUN() - - compileAndRun(sourceCode); - callContractFunction("a()"); - BOOST_REQUIRE_EQUAL(numLogs(), 1); - BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress); - BOOST_CHECK_EQUAL(h256(logData(0)), h256(u256(1))); - BOOST_REQUIRE_EQUAL(numLogTopics(0), 1); - BOOST_CHECK_EQUAL(logTopic(0, 0), h256(u256(2))); - ) -} - -BOOST_AUTO_TEST_CASE(log2) -{ - char const* sourceCode = R"( - contract test { - function a() public { - log2(bytes32(uint256(1)), bytes32(uint256(2)), bytes32(uint256(3))); - } - } - )"; - ALSO_VIA_YUL( - DISABLE_EWASM_TESTRUN() - - compileAndRun(sourceCode); - callContractFunction("a()"); - BOOST_REQUIRE_EQUAL(numLogs(), 1); - BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress); - BOOST_CHECK_EQUAL(h256(logData(0)), h256(u256(1))); - BOOST_REQUIRE_EQUAL(numLogTopics(0), 2); - for (unsigned i = 0; i < 2; ++i) - BOOST_CHECK_EQUAL(logTopic(0, i), h256(u256(i + 2))); - ) -} - -BOOST_AUTO_TEST_CASE(log3) -{ - char const* sourceCode = R"( - contract test { - function a() public { - log3(bytes32(uint256(1)), bytes32(uint256(2)), bytes32(uint256(3)), bytes32(uint256(4))); - } - } - )"; - ALSO_VIA_YUL( - DISABLE_EWASM_TESTRUN() - - compileAndRun(sourceCode); - callContractFunction("a()"); - BOOST_REQUIRE_EQUAL(numLogs(), 1); - BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress); - BOOST_CHECK_EQUAL(h256(logData(0)), h256(u256(1))); - BOOST_REQUIRE_EQUAL(numLogTopics(0), 3); - for (unsigned i = 0; i < 3; ++i) - BOOST_CHECK_EQUAL(logTopic(0, i), h256(u256(i + 2))); - ) -} - -BOOST_AUTO_TEST_CASE(log4) -{ - char const* sourceCode = R"( - contract test { - function a() public { - log4(bytes32(uint256(1)), bytes32(uint256(2)), bytes32(uint256(3)), bytes32(uint256(4)), bytes32(uint256(5))); - } - } - )"; - ALSO_VIA_YUL( - DISABLE_EWASM_TESTRUN() - - compileAndRun(sourceCode); - callContractFunction("a()"); - BOOST_REQUIRE_EQUAL(numLogs(), 1); - BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress); - BOOST_CHECK_EQUAL(h256(logData(0)), h256(u256(1))); - BOOST_REQUIRE_EQUAL(numLogTopics(0), 4); - for (unsigned i = 0; i < 4; ++i) - BOOST_CHECK_EQUAL(logTopic(0, i), h256(u256(i + 2))); - ) -} - -BOOST_AUTO_TEST_CASE(log_in_constructor) -{ - char const* sourceCode = R"( - contract test { - constructor() { - log1(bytes32(uint256(1)), bytes32(uint256(2))); - } - } - )"; - ALSO_VIA_YUL( - DISABLE_EWASM_TESTRUN() - - compileAndRun(sourceCode); - BOOST_REQUIRE_EQUAL(numLogs(), 1); - BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress); - BOOST_CHECK_EQUAL(h256(logData(0)), h256(u256(1))); - BOOST_REQUIRE_EQUAL(numLogTopics(0), 1); - BOOST_CHECK_EQUAL(logTopic(0, 0), h256(u256(2))); - ) -} - BOOST_AUTO_TEST_CASE(selfdestruct) { char const* sourceCode = R"( @@ -1883,7 +1750,12 @@ BOOST_AUTO_TEST_CASE(event) function deposit(bytes32 _id, bool _manually) public payable { if (_manually) { bytes32 s = 0x19dacbf83c5de6658e14cbf7bcae5c15eca2eedecf1c66fbca928e4d351bea0f; - log3(bytes32(msg.value), s, bytes32(uint256(msg.sender)), _id); + uint value = msg.value; + address sender = msg.sender; + assembly { + mstore(0, value) + log3(0, 0x20, s, sender, _id) + } } else { emit Deposit(msg.sender, _id, msg.value); } @@ -1937,6 +1809,31 @@ BOOST_AUTO_TEST_CASE(event_emit) ) } +BOOST_AUTO_TEST_CASE(event_constructor) +{ + char const* sourceCode = R"( + contract ClientReceipt { + event Deposit(address indexed _from, bytes32 indexed _id, uint _value); + constructor() { + emit Deposit(msg.sender, bytes32("abc"), 7); + } + } + )"; + ALSO_VIA_YUL( + DISABLE_EWASM_TESTRUN() + + compileAndRun(sourceCode); + BOOST_REQUIRE_EQUAL(numLogs(), 1); + BOOST_CHECK_EQUAL(logAddress(0), m_contractAddress); + BOOST_CHECK_EQUAL(h256(logData(0)), h256(u256(7))); + BOOST_REQUIRE_EQUAL(numLogTopics(0), 3); + BOOST_CHECK_EQUAL(logTopic(0, 0), util::keccak256(string("Deposit(address,bytes32,uint256)"))); + BOOST_CHECK_EQUAL(logTopic(0, 1), h256(m_sender, h256::AlignRight)); + BOOST_CHECK_EQUAL(logTopic(0, 2), h256(string{"abc"}, h256::FromBinary, h256::AlignLeft)); + ) +} + + BOOST_AUTO_TEST_CASE(event_no_arguments) { char const* sourceCode = R"( diff --git a/test/libsolidity/smtCheckerTests/special/log.sol b/test/libsolidity/smtCheckerTests/special/log.sol deleted file mode 100644 index 4dcdfc868..000000000 --- a/test/libsolidity/smtCheckerTests/special/log.sol +++ /dev/null @@ -1,40 +0,0 @@ -pragma experimental SMTChecker; - -contract C { - function f() external { - bytes32 t1 = bytes32(uint256(0x1234)); - log0(t1); - log1(t1, t1); - log2(t1, t1, t1); - log3(t1, t1, t1, t1); - log4(t1, t1, t1, t1, t1); - } - function g_data() pure internal returns (bytes32) { - assert(true); - return bytes32(uint256(0x5678)); - } - function g() external { - // To test that the function call is actually visited. - log0(g_data()); - log1(g_data(), g_data()); - log2(g_data(), g_data(), g_data()); - log3(g_data(), g_data(), g_data(), g_data()); - log4(g_data(), g_data(), g_data(), g_data(), g_data()); - } - bool x = true; - function h_data() view internal returns (bytes32) { - assert(x); - } - function h() external { - // To test that the function call is actually visited. - x = false; - log0(h_data()); - log1(h_data(), h_data()); - log2(h_data(), h_data(), h_data()); - log3(h_data(), h_data(), h_data(), h_data()); - log4(h_data(), h_data(), h_data(), h_data(), h_data()); - } -} -// ---- -// Warning 6321: (655-662): Unnamed return variable can remain unassigned. Add an explicit return with value to all non-reverting code paths or name the variable. -// Warning 6328: (668-677): CHC: Assertion violation happens here. diff --git a/test/libsolidity/syntaxTests/globalFunctions/log_deprecate.sol b/test/libsolidity/syntaxTests/globalFunctions/log_deprecate.sol new file mode 100644 index 000000000..4418c6198 --- /dev/null +++ b/test/libsolidity/syntaxTests/globalFunctions/log_deprecate.sol @@ -0,0 +1,15 @@ +contract C { + function f() public { + log0; + log1; + log2; + log3; + log4; + } +} +// ---- +// DeclarationError 7576: (38-42): Undeclared identifier. +// DeclarationError 7576: (46-50): Undeclared identifier. +// DeclarationError 7576: (54-58): Undeclared identifier. +// DeclarationError 7576: (62-66): Undeclared identifier. +// DeclarationError 7576: (70-74): Undeclared identifier. diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/141_multiple_scopes_suggestions.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/141_multiple_scopes_suggestions.sol index e71f3bd17..db870e19c 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/141_multiple_scopes_suggestions.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/141_multiple_scopes_suggestions.sol @@ -6,4 +6,4 @@ contract c { } } // ---- -// DeclarationError 7576: (101-105): Undeclared identifier. Did you mean "log8", "log9", "log0", "log1", "log2", "log3" or "log4"? +// DeclarationError 7576: (101-105): Undeclared identifier. Did you mean "log8" or "log9"? diff --git a/test/libsolidity/syntaxTests/nameAndTypeResolution/582_improve_name_suggestion_four_letters.sol b/test/libsolidity/syntaxTests/nameAndTypeResolution/582_improve_name_suggestion_four_letters.sol index e8deef519..4da28a5e9 100644 --- a/test/libsolidity/syntaxTests/nameAndTypeResolution/582_improve_name_suggestion_four_letters.sol +++ b/test/libsolidity/syntaxTests/nameAndTypeResolution/582_improve_name_suggestion_four_letters.sol @@ -12,6 +12,6 @@ contract c { // DeclarationError 7576: (52-53): Undeclared identifier. // DeclarationError 7576: (56-60): Undeclared identifier. Did you mean "long"? // DeclarationError 7576: (70-71): Undeclared identifier. -// DeclarationError 7576: (74-78): Undeclared identifier. Did you mean "long", "log0", "log1", "log2", "log3" or "log4"? +// DeclarationError 7576: (74-78): Undeclared identifier. Did you mean "long"? // DeclarationError 7576: (88-89): Undeclared identifier. // DeclarationError 7576: (92-96): Undeclared identifier. Did you mean "long"? diff --git a/test/libsolidity/syntaxTests/specialFunctions/types_with_unspecified_encoding_special_types.sol b/test/libsolidity/syntaxTests/specialFunctions/types_with_unspecified_encoding_special_types.sol index 214ed8a54..e83498b6c 100644 --- a/test/libsolidity/syntaxTests/specialFunctions/types_with_unspecified_encoding_special_types.sol +++ b/test/libsolidity/syntaxTests/specialFunctions/types_with_unspecified_encoding_special_types.sol @@ -1,13 +1,13 @@ contract C { function f() public pure { (bool a,) = address(this).call(abi.encode(address(this).delegatecall, super)); - (a,) = address(this).delegatecall(abi.encode(log0, tx, mulmod)); + (a,) = address(this).delegatecall(abi.encode(block, tx, mulmod)); a; } } // ---- // TypeError 2056: (94-120): This type cannot be encoded. // TypeError 2056: (122-127): This type cannot be encoded. -// TypeError 2056: (184-188): This type cannot be encoded. -// TypeError 2056: (190-192): This type cannot be encoded. -// TypeError 2056: (194-200): This type cannot be encoded. +// TypeError 2056: (184-189): This type cannot be encoded. +// TypeError 2056: (191-193): This type cannot be encoded. +// TypeError 2056: (195-201): This type cannot be encoded.