diff --git a/libsolidity/ast/Types.cpp b/libsolidity/ast/Types.cpp index 56a41b5f0..cfaf91ce1 100644 --- a/libsolidity/ast/Types.cpp +++ b/libsolidity/ast/Types.cpp @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -3591,7 +3592,7 @@ string FunctionType::externalSignature() const u256 FunctionType::externalIdentifier() const { - return util::FixedHash<4>::Arith(util::FixedHash<4>(util::keccak256(externalSignature()))); + return util::selectorFromSignature32(externalSignature()); } string FunctionType::externalIdentifierHex() const diff --git a/libsolidity/codegen/CompilerUtils.cpp b/libsolidity/codegen/CompilerUtils.cpp index dfc7cd233..f9be04c6e 100644 --- a/libsolidity/codegen/CompilerUtils.cpp +++ b/libsolidity/codegen/CompilerUtils.cpp @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -93,7 +94,7 @@ void CompilerUtils::revertWithStringData(Type const& _argumentType) { solAssert(_argumentType.isImplicitlyConvertibleTo(*TypeProvider::fromElementaryTypeName("string memory")), ""); fetchFreeMemoryPointer(); - m_context << (u256(util::FixedHash<4>::Arith(util::FixedHash<4>(util::keccak256("Error(string)")))) << (256 - 32)); + m_context << util::selectorFromSignature("Error(string)"); m_context << Instruction::DUP2 << Instruction::MSTORE; m_context << u256(4) << Instruction::ADD; // Stack: @@ -916,7 +917,7 @@ void CompilerUtils::convertType( { unsigned const numBytes = dynamic_cast(_targetType).numBytes(); solAssert(data.size() <= 32, ""); - m_context << (h256::Arith(h256(data, h256::AlignLeft)) & (~(u256(-1) >> (8 * numBytes)))); + m_context << (u256(h256(data, h256::AlignLeft)) & (~(u256(-1) >> (8 * numBytes)))); } else if (targetTypeCategory == Type::Category::Array) { @@ -1421,7 +1422,7 @@ void CompilerUtils::storeStringData(bytesConstRef _data) { for (unsigned i = 0; i < _data.size(); i += 32) { - m_context << h256::Arith(h256(_data.cropped(i), h256::AlignLeft)); + m_context << u256(h256(_data.cropped(i), h256::AlignLeft)); storeInMemoryDynamic(*TypeProvider::uint256()); } m_context << Instruction::POP; diff --git a/libsolidity/codegen/ContractCompiler.cpp b/libsolidity/codegen/ContractCompiler.cpp index f69999e1f..f76613095 100644 --- a/libsolidity/codegen/ContractCompiler.cpp +++ b/libsolidity/codegen/ContractCompiler.cpp @@ -953,8 +953,6 @@ void ContractCompiler::handleCatch(vector> const& _ca ); solAssert(m_context.evmVersion().supportsReturndata(), ""); - string errorHash = FixedHash<4>(util::keccak256("Error(string)")).hex(); - // Try to decode the error message. // If this fails, leaves 0 on the stack, otherwise the pointer to the data string. m_context.callYulFunction(m_context.utilFunctions().tryDecodeErrorMessageFunction(), 0, 1); diff --git a/libsolidity/codegen/ExpressionCompiler.cpp b/libsolidity/codegen/ExpressionCompiler.cpp index 99c09c14b..e4fd66ac9 100644 --- a/libsolidity/codegen/ExpressionCompiler.cpp +++ b/libsolidity/codegen/ExpressionCompiler.cpp @@ -33,6 +33,7 @@ #include #include +#include #include #include @@ -1187,8 +1188,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) // hash the signature if (auto const* stringType = dynamic_cast(selectorType)) { - FixedHash<4> hash(keccak256(stringType->value())); - m_context << (u256(FixedHash<4>::Arith(hash)) << (256 - 32)); + m_context << util::selectorFromSignature(stringType->value()); dataOnStack = TypeProvider::fixedBytes(4); } else diff --git a/libsolidity/codegen/YulUtilFunctions.cpp b/libsolidity/codegen/YulUtilFunctions.cpp index 4d7125b8d..eb7479f12 100644 --- a/libsolidity/codegen/YulUtilFunctions.cpp +++ b/libsolidity/codegen/YulUtilFunctions.cpp @@ -26,6 +26,7 @@ #include #include +#include #include #include @@ -126,11 +127,7 @@ string YulUtilFunctions::requireOrAssertFunction(bool _assert, Type const* _mess .render(); int const hashHeaderSize = 4; - int const byteSize = 8; - u256 const errorHash = - u256(FixedHash::Arith( - FixedHash(keccak256("Error(string)")) - )) << (256 - hashHeaderSize * byteSize); + u256 const errorHash = util::selectorFromSignature("Error(string)"); string const encodeFunc = ABIFunctions(m_evmVersion, m_revertStrings, m_functionCollector) .tupleEncoder( @@ -3192,7 +3189,7 @@ string YulUtilFunctions::revertReasonIfDebug(RevertStrings revertStrings, string revert(0, add(reasonPos, )) })"); - templ("sig", (u256(util::FixedHash<4>::Arith(util::FixedHash<4>(util::keccak256("Error(string)")))) << (256 - 32)).str()); + templ("sig", util::selectorFromSignature("Error(string)").str()); templ("length", to_string(_message.length())); size_t words = (_message.length() + 31) / 32; diff --git a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp index 9e8c0816b..790bc4642 100644 --- a/libsolidity/codegen/ir/IRGeneratorForStatements.cpp +++ b/libsolidity/codegen/ir/IRGeneratorForStatements.cpp @@ -43,6 +43,7 @@ #include #include #include +#include #include #include @@ -1037,10 +1038,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall) // hash the signature Type const& selectorType = type(*arguments.front()); if (auto const* stringType = dynamic_cast(&selectorType)) - { - FixedHash<4> hash(keccak256(stringType->value())); - selector = formatNumber(u256(FixedHash<4>::Arith(hash)) << (256 - 32)); - } + selector = formatNumber(util::selectorFromSignature(stringType->value())); else { // Used to reset the free memory pointer later. @@ -1157,10 +1155,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall) })"); templ("pos", m_context.newYulVariable()); templ("end", m_context.newYulVariable()); - templ( - "hash", - (u256(util::FixedHash<4>::Arith(util::FixedHash<4>(util::keccak256("Error(string)")))) << (256 - 32)).str() - ); + templ("hash", util::selectorFromSignature("Error(string)").str()); templ("allocateTemporary", m_utils.allocationTemporaryMemoryFunction()); templ( "argumentVars", diff --git a/libsolutil/CMakeLists.txt b/libsolutil/CMakeLists.txt index 390950ab9..a83eb734c 100644 --- a/libsolutil/CMakeLists.txt +++ b/libsolutil/CMakeLists.txt @@ -10,6 +10,7 @@ set(sources Exceptions.cpp Exceptions.h FixedHash.h + FunctionSelector.h IndentedWriter.cpp IndentedWriter.h InvertibleMap.h diff --git a/libsolutil/FunctionSelector.h b/libsolutil/FunctionSelector.h new file mode 100644 index 000000000..da6feb4e0 --- /dev/null +++ b/libsolutil/FunctionSelector.h @@ -0,0 +1,42 @@ +/* + 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 . +*/ +// SPDX-License-Identifier: GPL-3.0 + +#pragma once + +#include +#include + +#include + +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) +{ + return uint32_t(FixedHash<4>::Arith(util::FixedHash<4>(util::keccak256(_signature)))); +} + +/// @returns the ABI selector for a given function signature, as a u256 (left aligned) number. +inline u256 selectorFromSignature(std::string const& _signature) +{ + return u256(selectorFromSignature32(_signature)) << (256 - 32); +} + + +}