From 725253551ef9f408db328568e218f03474ceb788 Mon Sep 17 00:00:00 2001 From: Alex Beregszaszi Date: Tue, 27 Sep 2022 14:13:44 +0200 Subject: [PATCH] Improve FunctionSelector helpers --- libsolidity/analysis/PostTypeChecker.cpp | 2 +- .../analysis/PostTypeContractLevelChecker.cpp | 2 +- libsolidity/ast/AST.cpp | 4 +- libsolidity/ast/Types.cpp | 4 +- libsolidity/codegen/ArrayUtils.cpp | 2 +- libsolidity/codegen/CompilerUtils.cpp | 4 +- libsolidity/codegen/ContractCompiler.cpp | 6 +-- libsolidity/codegen/ExpressionCompiler.cpp | 2 +- libsolidity/codegen/YulUtilFunctions.cpp | 6 +-- .../codegen/ir/IRGeneratorForStatements.cpp | 10 ++-- libsolidity/interface/CompilerStack.cpp | 2 +- libsolidity/interface/GasEstimator.cpp | 3 +- libsolutil/FunctionSelector.h | 17 +++--- test/CMakeLists.txt | 1 + test/ExecutionFramework.cpp | 3 +- test/ExecutionFramework.h | 6 +-- test/contracts/Wallet.cpp | 2 +- test/libsolidity/ABIEncoderTests.cpp | 2 +- test/libsolidity/AnalysisFramework.cpp | 5 +- test/libsolidity/GasMeter.cpp | 2 +- test/libsolidity/SolidityEndToEndTest.cpp | 14 ++--- test/libsolidity/util/ContractABIUtils.cpp | 4 +- test/libsolutil/FunctionSelector.cpp | 53 +++++++++++++++++++ 23 files changed, 106 insertions(+), 50 deletions(-) create mode 100644 test/libsolutil/FunctionSelector.cpp diff --git a/libsolidity/analysis/PostTypeChecker.cpp b/libsolidity/analysis/PostTypeChecker.cpp index b5b973aa4..c8b3b5f16 100644 --- a/libsolidity/analysis/PostTypeChecker.cpp +++ b/libsolidity/analysis/PostTypeChecker.cpp @@ -411,7 +411,7 @@ struct ReservedErrorSelector: public PostTypeChecker::Checker ); else { - uint32_t selector = util::selectorFromSignature32(_error.functionType(true)->externalSignature()); + uint32_t selector = util::selectorFromSignatureU32(_error.functionType(true)->externalSignature()); if (selector == 0 || ~selector == 0) m_errorReporter.syntaxError( 2855_error, diff --git a/libsolidity/analysis/PostTypeContractLevelChecker.cpp b/libsolidity/analysis/PostTypeContractLevelChecker.cpp index 38a192c22..67d0623aa 100644 --- a/libsolidity/analysis/PostTypeContractLevelChecker.cpp +++ b/libsolidity/analysis/PostTypeContractLevelChecker.cpp @@ -52,7 +52,7 @@ bool PostTypeContractLevelChecker::check(ContractDefinition const& _contract) for (ErrorDefinition const* error: _contract.interfaceErrors()) { string signature = error->functionType(true)->externalSignature(); - uint32_t hash = util::selectorFromSignature32(signature); + uint32_t hash = util::selectorFromSignatureU32(signature); // Fail if there is a different signature for the same hash. if (!errorHashes[hash].empty() && !errorHashes[hash].count(signature)) { diff --git a/libsolidity/ast/AST.cpp b/libsolidity/ast/AST.cpp index 97167818c..8619ee6ae 100644 --- a/libsolidity/ast/AST.cpp +++ b/libsolidity/ast/AST.cpp @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -281,8 +282,7 @@ vector, FunctionTypePointer>> const& ContractDefinition: if (signaturesSeen.count(functionSignature) == 0) { signaturesSeen.insert(functionSignature); - util::FixedHash<4> hash(util::keccak256(functionSignature)); - interfaceFunctionList.emplace_back(hash, fun); + interfaceFunctionList.emplace_back(util::selectorFromSignatureH32(functionSignature), fun); } } } diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index ebe704103..9c0179eda 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -3583,12 +3583,12 @@ string FunctionType::externalSignature() const u256 FunctionType::externalIdentifier() const { - return util::selectorFromSignature32(externalSignature()); + return util::selectorFromSignatureU32(externalSignature()); } string FunctionType::externalIdentifierHex() const { - return util::FixedHash<4>(util::keccak256(externalSignature())).hex(); + return util::selectorFromSignatureH32(externalSignature()).hex(); } bool FunctionType::isPure() const diff --git a/libsolidity/codegen/ArrayUtils.cpp b/libsolidity/codegen/ArrayUtils.cpp index 9b95463ba..609ff9993 100644 --- a/libsolidity/codegen/ArrayUtils.cpp +++ b/libsolidity/codegen/ArrayUtils.cpp @@ -889,7 +889,7 @@ void ArrayUtils::popStorageArrayElement(ArrayType const& _type) const } sstore(ref, slot_value) })"); - code("panicSelector", util::selectorFromSignature("Panic(uint256)").str()); + code("panicSelector", util::selectorFromSignatureU256("Panic(uint256)").str()); code("emptyArrayPop", to_string(unsigned(util::PanicCode::EmptyArrayPop))); m_context.appendInlineAssembly(code.render(), {"ref", "slot_value", "length"}); m_context << Instruction::POP << Instruction::POP << Instruction::POP; diff --git a/libsolidity/codegen/CompilerUtils.cpp b/libsolidity/codegen/CompilerUtils.cpp index 32b1f1bba..783a7b1a4 100644 --- a/libsolidity/codegen/CompilerUtils.cpp +++ b/libsolidity/codegen/CompilerUtils.cpp @@ -95,7 +95,7 @@ void CompilerUtils::revertWithStringData(Type const& _argumentType) { solAssert(_argumentType.isImplicitlyConvertibleTo(*TypeProvider::fromElementaryTypeName("string memory"))); fetchFreeMemoryPointer(); - m_context << util::selectorFromSignature("Error(string)"); + m_context << util::selectorFromSignatureU256("Error(string)"); m_context << Instruction::DUP2 << Instruction::MSTORE; m_context << u256(4) << Instruction::ADD; // Stack: @@ -111,7 +111,7 @@ void CompilerUtils::revertWithError( ) { fetchFreeMemoryPointer(); - m_context << util::selectorFromSignature(_signature); + m_context << util::selectorFromSignatureU256(_signature); m_context << Instruction::DUP2 << Instruction::MSTORE; m_context << u256(4) << Instruction::ADD; // Stack: diff --git a/libsolidity/codegen/ContractCompiler.cpp b/libsolidity/codegen/ContractCompiler.cpp index a89dbb21b..a6e7ab2fb 100644 --- a/libsolidity/codegen/ContractCompiler.cpp +++ b/libsolidity/codegen/ContractCompiler.cpp @@ -253,7 +253,7 @@ size_t ContractCompiler::deployLibrary(ContractDefinition const& _contract) return(codepos, subSize) } )") - ("panicSelector", util::selectorFromSignature("Panic(uint256)").str()) + ("panicSelector", util::selectorFromSignatureU256("Panic(uint256)").str()) ("panicCode", "0") .render(), {"subSize", "subOffset"} @@ -1046,7 +1046,7 @@ void ContractCompiler::handleCatch(vector> const& _ca solAssert(m_context.evmVersion().supportsReturndata(), ""); // stack: - m_context << Instruction::DUP1 << util::selectorFromSignature32("Error(string)") << Instruction::EQ; + m_context << Instruction::DUP1 << util::selectorFromSignatureU32("Error(string)") << Instruction::EQ; m_context << Instruction::ISZERO; m_context.appendConditionalJumpTo(panicTag); m_context << Instruction::POP; // remove selector @@ -1078,7 +1078,7 @@ void ContractCompiler::handleCatch(vector> const& _ca solAssert(m_context.evmVersion().supportsReturndata(), ""); // stack: - m_context << util::selectorFromSignature32("Panic(uint256)") << Instruction::EQ; + m_context << util::selectorFromSignatureU32("Panic(uint256)") << Instruction::EQ; m_context << Instruction::ISZERO; m_context.appendConditionalJumpTo(fallbackTag); diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp index 3ee824447..461de5648 100644 --- a/libsolidity/codegen/ExpressionCompiler.cpp +++ b/libsolidity/codegen/ExpressionCompiler.cpp @@ -1329,7 +1329,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) // hash the signature if (auto const* stringType = dynamic_cast(selectorType)) { - m_context << util::selectorFromSignature(stringType->value()); + m_context << util::selectorFromSignatureU256(stringType->value()); dataOnStack = TypeProvider::fixedBytes(4); } else diff --git a/libsolidity/codegen/YulUtilFunctions.cpp b/libsolidity/codegen/YulUtilFunctions.cpp index b66189f05..fa5573810 100644 --- a/libsolidity/codegen/YulUtilFunctions.cpp +++ b/libsolidity/codegen/YulUtilFunctions.cpp @@ -233,7 +233,7 @@ string YulUtilFunctions::requireOrAssertFunction(bool _assert, Type const* _mess .render(); int const hashHeaderSize = 4; - u256 const errorHash = util::selectorFromSignature("Error(string)"); + u256 const errorHash = util::selectorFromSignatureU256("Error(string)"); string const encodeFunc = ABIFunctions(m_evmVersion, m_revertStrings, m_functionCollector) .tupleEncoder( @@ -4426,7 +4426,7 @@ string YulUtilFunctions::revertReasonIfDebugBody( revert(start, ) )"); templ("allocate", _allocation); - templ("sig", util::selectorFromSignature("Error(string)").str()); + templ("sig", util::selectorFromSignatureU256("Error(string)").str()); templ("length", to_string(_message.length())); size_t words = (_message.length() + 31) / 32; @@ -4454,7 +4454,7 @@ string YulUtilFunctions::panicFunction(util::PanicCode _code) } )") ("functionName", functionName) - ("selector", util::selectorFromSignature("Panic(uint256)").str()) + ("selector", util::selectorFromSignatureU256("Panic(uint256)").str()) ("code", toCompactHexWithPrefix(static_cast(_code))) .render(); }); diff --git a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp index 61ec2b144..30575930c 100644 --- a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp +++ b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp @@ -1196,7 +1196,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall) // hash the signature Type const& selectorType = type(*arguments.front()); if (auto const* stringType = dynamic_cast(&selectorType)) - selector = formatNumber(util::selectorFromSignature(stringType->value())); + selector = formatNumber(util::selectorFromSignatureU256(stringType->value())); else { // Used to reset the free memory pointer later. @@ -1785,7 +1785,7 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess) "" ); define(IRVariable{_memberAccess}) << formatNumber( - util::selectorFromSignature(functionType.externalSignature()) + util::selectorFromSignatureU256(functionType.externalSignature()) ) << "\n"; } else if (functionType.kind() == FunctionType::Kind::Event) @@ -3234,7 +3234,7 @@ void IRGeneratorForStatements::handleCatch(TryStatement const& _tryStatement) if (TryCatchClause const* errorClause = _tryStatement.errorClause()) { - appendCode() << "case " << selectorFromSignature32("Error(string)") << " {\n"; + appendCode() << "case " << selectorFromSignatureU32("Error(string)") << " {\n"; setLocation(*errorClause); string const dataVariable = m_context.newYulVariable(); appendCode() << "let " << dataVariable << " := " << m_utils.tryDecodeErrorMessageFunction() << "()\n"; @@ -3254,7 +3254,7 @@ void IRGeneratorForStatements::handleCatch(TryStatement const& _tryStatement) } if (TryCatchClause const* panicClause = _tryStatement.panicClause()) { - appendCode() << "case " << selectorFromSignature32("Panic(uint256)") << " {\n"; + appendCode() << "case " << selectorFromSignatureU32("Panic(uint256)") << " {\n"; setLocation(*panicClause); string const success = m_context.newYulVariable(); string const code = m_context.newYulVariable(); @@ -3317,7 +3317,7 @@ void IRGeneratorForStatements::revertWithError( })"); templ("pos", m_context.newYulVariable()); templ("end", m_context.newYulVariable()); - templ("hash", util::selectorFromSignature(_signature).str()); + templ("hash", util::selectorFromSignatureU256(_signature).str()); templ("allocateUnbounded", m_utils.allocateUnboundedFunction()); vector errorArgumentVars; diff --git a/libsolidity/interface/CompilerStack.cpp b/libsolidity/interface/CompilerStack.cpp index 109650130..ca700d764 100644 --- a/libsolidity/interface/CompilerStack.cpp +++ b/libsolidity/interface/CompilerStack.cpp @@ -1034,7 +1034,7 @@ Json::Value CompilerStack::interfaceSymbols(string const& _contractName) const for (ErrorDefinition const* error: contractDefinition(_contractName).interfaceErrors()) { string signature = error->functionType(true)->externalSignature(); - interfaceSymbols["errors"][signature] = util::toHex(toCompactBigEndian(util::selectorFromSignature32(signature), 4)); + interfaceSymbols["errors"][signature] = util::toHex(toCompactBigEndian(util::selectorFromSignatureU32(signature), 4)); } for (EventDefinition const* event: ranges::concat_view( diff --git a/libsolidity/interface/GasEstimator.cpp b/libsolidity/interface/GasEstimator.cpp index 8b7e79840..512f91bee 100644 --- a/libsolidity/interface/GasEstimator.cpp +++ b/libsolidity/interface/GasEstimator.cpp @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -54,7 +55,7 @@ GasEstimator::GasConsumption GasEstimator::functionalEstimation( ExpressionClasses& classes = state->expressionClasses(); using Id = ExpressionClasses::Id; using Ids = vector; - Id hashValue = classes.find(u256(util::FixedHash<4>::Arith(util::FixedHash<4>(util::keccak256(_signature))))); + Id hashValue = classes.find(u256(util::selectorFromSignatureU32(_signature))); Id calldata = classes.find(Instruction::CALLDATALOAD, Ids{classes.find(u256(0))}); if (!m_evmVersion.hasBitwiseShifting()) // div(calldataload(0), 1 << 224) equals to hashValue diff --git a/libsolutil/FunctionSelector.h b/libsolutil/FunctionSelector.h index da6feb4e0..2712f6bad 100644 --- a/libsolutil/FunctionSelector.h +++ b/libsolutil/FunctionSelector.h @@ -26,17 +26,22 @@ namespace solidity::util { -/// @returns the ABI selector for a given function signature, as a 32 bit number. -inline uint32_t selectorFromSignature32(std::string const& _signature) +/// @returns the ABI selector for a given function signature, as a FixedHash h32. +inline FixedHash<4> selectorFromSignatureH32(std::string const& _signature) { - return uint32_t(FixedHash<4>::Arith(util::FixedHash<4>(util::keccak256(_signature)))); + return FixedHash<4>(util::keccak256(_signature), FixedHash<4>::AlignLeft); +} + +/// @returns the ABI selector for a given function signature, as a 32 bit number. +inline uint32_t selectorFromSignatureU32(std::string const& _signature) +{ + return uint32_t(FixedHash<4>::Arith(selectorFromSignatureH32(_signature))); } /// @returns the ABI selector for a given function signature, as a u256 (left aligned) number. -inline u256 selectorFromSignature(std::string const& _signature) +inline u256 selectorFromSignatureU256(std::string const& _signature) { - return u256(selectorFromSignature32(_signature)) << (256 - 32); + return u256(selectorFromSignatureU32(_signature)) << (256 - 32); } - } diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index cc7a61bae..637a62a0c 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -35,6 +35,7 @@ set(libsolutil_sources libsolutil/CommonData.cpp libsolutil/CommonIO.cpp libsolutil/FixedHash.cpp + libsolutil/FunctionSelector.cpp libsolutil/IndentedWriter.cpp libsolutil/IpfsHash.cpp libsolutil/IterateReplacing.cpp diff --git a/test/ExecutionFramework.cpp b/test/ExecutionFramework.cpp index bb46f108d..be2a283f7 100644 --- a/test/ExecutionFramework.cpp +++ b/test/ExecutionFramework.cpp @@ -30,7 +30,6 @@ #include #include -#include #include @@ -123,7 +122,7 @@ bytes ExecutionFramework::panicData(util::PanicCode _code) { return m_evmVersion.supportsReturndata() ? - toCompactBigEndian(selectorFromSignature32("Panic(uint256)"), 4) + encode(u256(static_cast(_code))) : + toCompactBigEndian(selectorFromSignatureU32("Panic(uint256)"), 4) + encode(u256(static_cast(_code))) : bytes(); } diff --git a/test/ExecutionFramework.h b/test/ExecutionFramework.h index ae2ab6894..cbde0ac4e 100644 --- a/test/ExecutionFramework.h +++ b/test/ExecutionFramework.h @@ -31,8 +31,7 @@ #include -#include -#include +#include #include #include @@ -108,8 +107,7 @@ public: bytes const& callContractFunctionWithValueNoEncoding(std::string _sig, u256 const& _value, bytes const& _arguments) { - util::FixedHash<4> hash(util::keccak256(_sig)); - sendMessage(hash.asBytes() + _arguments, false, _value); + sendMessage(util::selectorFromSignatureH32(_sig).asBytes() + _arguments, false, _value); return m_output; } diff --git a/test/contracts/Wallet.cpp b/test/contracts/Wallet.cpp index 72aac4f71..63a4bfc31 100644 --- a/test/contracts/Wallet.cpp +++ b/test/contracts/Wallet.cpp @@ -591,7 +591,7 @@ BOOST_AUTO_TEST_CASE(revoke_addOwner) BOOST_REQUIRE(callContractFunction("changeRequirement(uint256)", u256(3)) == encodeArgs()); // add a new owner h160 deployer = m_sender; - h256 opHash = util::keccak256(FixedHash<4>(util::keccak256("addOwner(address)")).asBytes() + h256(0x33).asBytes()); + h256 opHash = util::keccak256(util::selectorFromSignatureH32("addOwner(address)").asBytes() + h256(0x33).asBytes()); BOOST_REQUIRE(callContractFunction("addOwner(address)", h160(0x33)) == encodeArgs()); BOOST_REQUIRE(callContractFunction("isOwner(address)", h160(0x33)) == encodeArgs(false)); m_sender = account(0); diff --git a/test/libsolidity/ABIEncoderTests.cpp b/test/libsolidity/ABIEncoderTests.cpp index 6cb524044..970bf1b3e 100644 --- a/test/libsolidity/ABIEncoderTests.cpp +++ b/test/libsolidity/ABIEncoderTests.cpp @@ -342,7 +342,7 @@ BOOST_AUTO_TEST_CASE(external_function) BOTH_ENCODERS( compileAndRun(sourceCode); callContractFunction("f(uint256)", u256(0)); - string functionIdF = asString(m_contractAddress.ref()) + asString(FixedHash<4>(keccak256("f(uint256)")).ref()); + string functionIdF = asString(m_contractAddress.ref()) + asString(util::selectorFromSignatureH32("f(uint256)").ref()); REQUIRE_LOG_DATA(encodeArgs(functionIdF, functionIdF)); ) } diff --git a/test/libsolidity/AnalysisFramework.cpp b/test/libsolidity/AnalysisFramework.cpp index 5dce2211f..7bbaaaa5d 100644 --- a/test/libsolidity/AnalysisFramework.cpp +++ b/test/libsolidity/AnalysisFramework.cpp @@ -30,7 +30,7 @@ #include -#include +#include #include @@ -170,6 +170,5 @@ FunctionTypePointer AnalysisFramework::retrieveFunctionBySignature( std::string const& _signature ) { - FixedHash<4> hash(util::keccak256(_signature)); - return _contract.interfaceFunctions()[hash]; + return _contract.interfaceFunctions()[util::selectorFromSignatureH32(_signature)]; } diff --git a/test/libsolidity/GasMeter.cpp b/test/libsolidity/GasMeter.cpp index d77462eb9..0cb81ecb6 100644 --- a/test/libsolidity/GasMeter.cpp +++ b/test/libsolidity/GasMeter.cpp @@ -78,7 +78,7 @@ public: { u256 gasUsed = 0; GasMeter::GasConsumption gas; - util::FixedHash<4> hash(util::keccak256(_sig)); + util::FixedHash<4> hash = util::selectorFromSignatureH32(_sig); for (bytes const& arguments: _argumentVariants) { sendMessage(hash.asBytes() + arguments, false, 0); diff --git a/test/libsolidity/SolidityEndToEndTest.cpp b/test/libsolidity/SolidityEndToEndTest.cpp index 7509bed3c..698f6de66 100644 --- a/test/libsolidity/SolidityEndToEndTest.cpp +++ b/test/libsolidity/SolidityEndToEndTest.cpp @@ -1627,7 +1627,7 @@ BOOST_AUTO_TEST_CASE(bytes_from_calldata_to_memory) ALSO_VIA_YUL( DISABLE_EWASM_TESTRUN(); compileAndRun(sourceCode); - bytes calldata1 = FixedHash<4>(util::keccak256("f()")).asBytes() + bytes(61, 0x22) + bytes(12, 0x12); + bytes calldata1 = util::selectorFromSignatureH32("f()").asBytes() + bytes(61, 0x22) + bytes(12, 0x12); sendMessage(calldata1, false); BOOST_CHECK(m_transactionSuccessful); BOOST_CHECK(m_output == encodeArgs(util::keccak256(bytes{'a', 'b', 'c'} + calldata1))); @@ -1872,8 +1872,8 @@ BOOST_AUTO_TEST_CASE(bytes_in_arguments) compileAndRun(sourceCode); - string innercalldata1 = asString(FixedHash<4>(util::keccak256("f(uint256,uint256)")).asBytes() + encodeArgs(8, 9)); - string innercalldata2 = asString(FixedHash<4>(util::keccak256("g(uint256)")).asBytes() + encodeArgs(3)); + string innercalldata1 = asString(util::selectorFromSignatureH32("f(uint256,uint256)").asBytes() + encodeArgs(8, 9)); + string innercalldata2 = asString(util::selectorFromSignatureH32("g(uint256)").asBytes() + encodeArgs(3)); bytes calldata = encodeArgs( 12, 32 * 4, u256(32 * 4 + 32 + (innercalldata1.length() + 31) / 32 * 32), 13, u256(innercalldata1.length()), innercalldata1, @@ -2205,8 +2205,8 @@ BOOST_AUTO_TEST_CASE(calldata_struct_function_type) )"; compileAndRun(sourceCode, 0, "C"); - bytes fn_C_g = m_contractAddress.asBytes() + FixedHash<4>(util::keccak256("g(uint256)")).asBytes() + bytes(8,0); - bytes fn_C_h = m_contractAddress.asBytes() + FixedHash<4>(util::keccak256("h(uint256)")).asBytes() + bytes(8,0); + bytes fn_C_g = m_contractAddress.asBytes() + util::selectorFromSignatureH32("g(uint256)").asBytes() + bytes(8,0); + bytes fn_C_h = m_contractAddress.asBytes() + util::selectorFromSignatureH32("h(uint256)").asBytes() + bytes(8,0); ABI_CHECK(callContractFunctionNoEncoding("f((function))", fn_C_g), encodeArgs(42 * 3)); ABI_CHECK(callContractFunctionNoEncoding("f((function))", fn_C_h), encodeArgs(23)); } @@ -3007,7 +3007,7 @@ BOOST_AUTO_TEST_CASE(receive_external_function_type) compileAndRun(sourceCode, 0, "C"); ABI_CHECK(callContractFunction( "f(function)", - m_contractAddress.asBytes() + FixedHash<4>(util::keccak256("g()")).asBytes() + bytes(32 - 4 - 20, 0) + m_contractAddress.asBytes() + util::selectorFromSignatureH32("g()").asBytes() + bytes(32 - 4 - 20, 0) ), encodeArgs(u256(7))); ) } @@ -3026,7 +3026,7 @@ BOOST_AUTO_TEST_CASE(return_external_function_type) compileAndRun(sourceCode, 0, "C"); ABI_CHECK( callContractFunction("f()"), - m_contractAddress.asBytes() + FixedHash<4>(util::keccak256("g()")).asBytes() + bytes(32 - 4 - 20, 0) + m_contractAddress.asBytes() + util::selectorFromSignatureH32("g()").asBytes() + bytes(32 - 4 - 20, 0) ); } diff --git a/test/libsolidity/util/ContractABIUtils.cpp b/test/libsolidity/util/ContractABIUtils.cpp index b94de7bec..10363551b 100644 --- a/test/libsolidity/util/ContractABIUtils.cpp +++ b/test/libsolidity/util/ContractABIUtils.cpp @@ -338,9 +338,9 @@ solidity::frontend::test::ParameterList ContractABIUtils::failureParameters(byte parameters.push_back(Parameter{bytes(), "", ABIType{ABIType::HexString, ABIType::AlignNone, 4}, FormatInfo{}}); uint64_t selector = fromBigEndian(bytes{_bytes.begin(), _bytes.begin() + 4}); - if (selector == selectorFromSignature32("Panic(uint256)")) + if (selector == selectorFromSignatureU32("Panic(uint256)")) parameters.push_back(Parameter{bytes(), "", ABIType{ABIType::Hex}, FormatInfo{}}); - else if (selector == selectorFromSignature32("Error(string)")) + else if (selector == selectorFromSignatureU32("Error(string)")) { parameters.push_back(Parameter{bytes(), "", ABIType{ABIType::Hex}, FormatInfo{}}); parameters.push_back(Parameter{bytes(), "", ABIType{ABIType::UnsignedDec}, FormatInfo{}}); diff --git a/test/libsolutil/FunctionSelector.cpp b/test/libsolutil/FunctionSelector.cpp new file mode 100644 index 000000000..2ddfe9400 --- /dev/null +++ b/test/libsolutil/FunctionSelector.cpp @@ -0,0 +1,53 @@ +/* + This file is part of solidity. + + solidity is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + solidity is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with solidity. If not, see . +*/ +/** + * Unit tests for FunctionSelector. + */ + +#include + +#include + +#include +#include + +using namespace std; + +namespace solidity::util::test +{ + +BOOST_AUTO_TEST_SUITE(FunctionSelectorTest) + +BOOST_AUTO_TEST_CASE(conversions) +{ + BOOST_CHECK_EQUAL( + util::selectorFromSignatureH32("test()"), + util::FixedHash<4>(0xf8a8fd6d) + ); + BOOST_CHECK_EQUAL( + util::selectorFromSignatureU32("test()"), + 0xf8a8fd6d + ); + BOOST_CHECK_EQUAL( + util::selectorFromSignatureU256("test()"), + u256("0xf8a8fd6d00000000000000000000000000000000000000000000000000000000") + ); +} + +BOOST_AUTO_TEST_SUITE_END() + +}