mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Improve FunctionSelector helpers
This commit is contained in:
parent
311b2054af
commit
725253551e
@ -411,7 +411,7 @@ struct ReservedErrorSelector: public PostTypeChecker::Checker
|
|||||||
);
|
);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
uint32_t selector = util::selectorFromSignature32(_error.functionType(true)->externalSignature());
|
uint32_t selector = util::selectorFromSignatureU32(_error.functionType(true)->externalSignature());
|
||||||
if (selector == 0 || ~selector == 0)
|
if (selector == 0 || ~selector == 0)
|
||||||
m_errorReporter.syntaxError(
|
m_errorReporter.syntaxError(
|
||||||
2855_error,
|
2855_error,
|
||||||
|
@ -52,7 +52,7 @@ bool PostTypeContractLevelChecker::check(ContractDefinition const& _contract)
|
|||||||
for (ErrorDefinition const* error: _contract.interfaceErrors())
|
for (ErrorDefinition const* error: _contract.interfaceErrors())
|
||||||
{
|
{
|
||||||
string signature = error->functionType(true)->externalSignature();
|
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.
|
// Fail if there is a different signature for the same hash.
|
||||||
if (!errorHashes[hash].empty() && !errorHashes[hash].count(signature))
|
if (!errorHashes[hash].empty() && !errorHashes[hash].count(signature))
|
||||||
{
|
{
|
||||||
|
@ -27,6 +27,7 @@
|
|||||||
#include <libsolidity/ast/ASTVisitor.h>
|
#include <libsolidity/ast/ASTVisitor.h>
|
||||||
#include <libsolidity/ast/AST_accept.h>
|
#include <libsolidity/ast/AST_accept.h>
|
||||||
#include <libsolidity/ast/TypeProvider.h>
|
#include <libsolidity/ast/TypeProvider.h>
|
||||||
|
#include <libsolutil/FunctionSelector.h>
|
||||||
#include <libsolutil/Keccak256.h>
|
#include <libsolutil/Keccak256.h>
|
||||||
|
|
||||||
#include <range/v3/view/tail.hpp>
|
#include <range/v3/view/tail.hpp>
|
||||||
@ -281,8 +282,7 @@ vector<pair<util::FixedHash<4>, FunctionTypePointer>> const& ContractDefinition:
|
|||||||
if (signaturesSeen.count(functionSignature) == 0)
|
if (signaturesSeen.count(functionSignature) == 0)
|
||||||
{
|
{
|
||||||
signaturesSeen.insert(functionSignature);
|
signaturesSeen.insert(functionSignature);
|
||||||
util::FixedHash<4> hash(util::keccak256(functionSignature));
|
interfaceFunctionList.emplace_back(util::selectorFromSignatureH32(functionSignature), fun);
|
||||||
interfaceFunctionList.emplace_back(hash, fun);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3583,12 +3583,12 @@ string FunctionType::externalSignature() const
|
|||||||
|
|
||||||
u256 FunctionType::externalIdentifier() const
|
u256 FunctionType::externalIdentifier() const
|
||||||
{
|
{
|
||||||
return util::selectorFromSignature32(externalSignature());
|
return util::selectorFromSignatureU32(externalSignature());
|
||||||
}
|
}
|
||||||
|
|
||||||
string FunctionType::externalIdentifierHex() const
|
string FunctionType::externalIdentifierHex() const
|
||||||
{
|
{
|
||||||
return util::FixedHash<4>(util::keccak256(externalSignature())).hex();
|
return util::selectorFromSignatureH32(externalSignature()).hex();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool FunctionType::isPure() const
|
bool FunctionType::isPure() const
|
||||||
|
@ -889,7 +889,7 @@ void ArrayUtils::popStorageArrayElement(ArrayType const& _type) const
|
|||||||
}
|
}
|
||||||
sstore(ref, slot_value)
|
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)));
|
code("emptyArrayPop", to_string(unsigned(util::PanicCode::EmptyArrayPop)));
|
||||||
m_context.appendInlineAssembly(code.render(), {"ref", "slot_value", "length"});
|
m_context.appendInlineAssembly(code.render(), {"ref", "slot_value", "length"});
|
||||||
m_context << Instruction::POP << Instruction::POP << Instruction::POP;
|
m_context << Instruction::POP << Instruction::POP << Instruction::POP;
|
||||||
|
@ -95,7 +95,7 @@ void CompilerUtils::revertWithStringData(Type const& _argumentType)
|
|||||||
{
|
{
|
||||||
solAssert(_argumentType.isImplicitlyConvertibleTo(*TypeProvider::fromElementaryTypeName("string memory")));
|
solAssert(_argumentType.isImplicitlyConvertibleTo(*TypeProvider::fromElementaryTypeName("string memory")));
|
||||||
fetchFreeMemoryPointer();
|
fetchFreeMemoryPointer();
|
||||||
m_context << util::selectorFromSignature("Error(string)");
|
m_context << util::selectorFromSignatureU256("Error(string)");
|
||||||
m_context << Instruction::DUP2 << Instruction::MSTORE;
|
m_context << Instruction::DUP2 << Instruction::MSTORE;
|
||||||
m_context << u256(4) << Instruction::ADD;
|
m_context << u256(4) << Instruction::ADD;
|
||||||
// Stack: <string data> <mem pos of encoding start>
|
// Stack: <string data> <mem pos of encoding start>
|
||||||
@ -111,7 +111,7 @@ void CompilerUtils::revertWithError(
|
|||||||
)
|
)
|
||||||
{
|
{
|
||||||
fetchFreeMemoryPointer();
|
fetchFreeMemoryPointer();
|
||||||
m_context << util::selectorFromSignature(_signature);
|
m_context << util::selectorFromSignatureU256(_signature);
|
||||||
m_context << Instruction::DUP2 << Instruction::MSTORE;
|
m_context << Instruction::DUP2 << Instruction::MSTORE;
|
||||||
m_context << u256(4) << Instruction::ADD;
|
m_context << u256(4) << Instruction::ADD;
|
||||||
// Stack: <arguments...> <mem pos of encoding start>
|
// Stack: <arguments...> <mem pos of encoding start>
|
||||||
|
@ -253,7 +253,7 @@ size_t ContractCompiler::deployLibrary(ContractDefinition const& _contract)
|
|||||||
return(codepos, subSize)
|
return(codepos, subSize)
|
||||||
}
|
}
|
||||||
)")
|
)")
|
||||||
("panicSelector", util::selectorFromSignature("Panic(uint256)").str())
|
("panicSelector", util::selectorFromSignatureU256("Panic(uint256)").str())
|
||||||
("panicCode", "0")
|
("panicCode", "0")
|
||||||
.render(),
|
.render(),
|
||||||
{"subSize", "subOffset"}
|
{"subSize", "subOffset"}
|
||||||
@ -1046,7 +1046,7 @@ void ContractCompiler::handleCatch(vector<ASTPointer<TryCatchClause>> const& _ca
|
|||||||
solAssert(m_context.evmVersion().supportsReturndata(), "");
|
solAssert(m_context.evmVersion().supportsReturndata(), "");
|
||||||
|
|
||||||
// stack: <selector>
|
// stack: <selector>
|
||||||
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 << Instruction::ISZERO;
|
||||||
m_context.appendConditionalJumpTo(panicTag);
|
m_context.appendConditionalJumpTo(panicTag);
|
||||||
m_context << Instruction::POP; // remove selector
|
m_context << Instruction::POP; // remove selector
|
||||||
@ -1078,7 +1078,7 @@ void ContractCompiler::handleCatch(vector<ASTPointer<TryCatchClause>> const& _ca
|
|||||||
solAssert(m_context.evmVersion().supportsReturndata(), "");
|
solAssert(m_context.evmVersion().supportsReturndata(), "");
|
||||||
|
|
||||||
// stack: <selector>
|
// stack: <selector>
|
||||||
m_context << util::selectorFromSignature32("Panic(uint256)") << Instruction::EQ;
|
m_context << util::selectorFromSignatureU32("Panic(uint256)") << Instruction::EQ;
|
||||||
m_context << Instruction::ISZERO;
|
m_context << Instruction::ISZERO;
|
||||||
m_context.appendConditionalJumpTo(fallbackTag);
|
m_context.appendConditionalJumpTo(fallbackTag);
|
||||||
|
|
||||||
|
@ -1329,7 +1329,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall)
|
|||||||
// hash the signature
|
// hash the signature
|
||||||
if (auto const* stringType = dynamic_cast<StringLiteralType const*>(selectorType))
|
if (auto const* stringType = dynamic_cast<StringLiteralType const*>(selectorType))
|
||||||
{
|
{
|
||||||
m_context << util::selectorFromSignature(stringType->value());
|
m_context << util::selectorFromSignatureU256(stringType->value());
|
||||||
dataOnStack = TypeProvider::fixedBytes(4);
|
dataOnStack = TypeProvider::fixedBytes(4);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -233,7 +233,7 @@ string YulUtilFunctions::requireOrAssertFunction(bool _assert, Type const* _mess
|
|||||||
.render();
|
.render();
|
||||||
|
|
||||||
int const hashHeaderSize = 4;
|
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)
|
string const encodeFunc = ABIFunctions(m_evmVersion, m_revertStrings, m_functionCollector)
|
||||||
.tupleEncoder(
|
.tupleEncoder(
|
||||||
@ -4426,7 +4426,7 @@ string YulUtilFunctions::revertReasonIfDebugBody(
|
|||||||
revert(start, <overallLength>)
|
revert(start, <overallLength>)
|
||||||
)");
|
)");
|
||||||
templ("allocate", _allocation);
|
templ("allocate", _allocation);
|
||||||
templ("sig", util::selectorFromSignature("Error(string)").str());
|
templ("sig", util::selectorFromSignatureU256("Error(string)").str());
|
||||||
templ("length", to_string(_message.length()));
|
templ("length", to_string(_message.length()));
|
||||||
|
|
||||||
size_t words = (_message.length() + 31) / 32;
|
size_t words = (_message.length() + 31) / 32;
|
||||||
@ -4454,7 +4454,7 @@ string YulUtilFunctions::panicFunction(util::PanicCode _code)
|
|||||||
}
|
}
|
||||||
)")
|
)")
|
||||||
("functionName", functionName)
|
("functionName", functionName)
|
||||||
("selector", util::selectorFromSignature("Panic(uint256)").str())
|
("selector", util::selectorFromSignatureU256("Panic(uint256)").str())
|
||||||
("code", toCompactHexWithPrefix(static_cast<unsigned>(_code)))
|
("code", toCompactHexWithPrefix(static_cast<unsigned>(_code)))
|
||||||
.render();
|
.render();
|
||||||
});
|
});
|
||||||
|
@ -1196,7 +1196,7 @@ void IRGeneratorForStatements::endVisit(FunctionCall const& _functionCall)
|
|||||||
// hash the signature
|
// hash the signature
|
||||||
Type const& selectorType = type(*arguments.front());
|
Type const& selectorType = type(*arguments.front());
|
||||||
if (auto const* stringType = dynamic_cast<StringLiteralType const*>(&selectorType))
|
if (auto const* stringType = dynamic_cast<StringLiteralType const*>(&selectorType))
|
||||||
selector = formatNumber(util::selectorFromSignature(stringType->value()));
|
selector = formatNumber(util::selectorFromSignatureU256(stringType->value()));
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Used to reset the free memory pointer later.
|
// Used to reset the free memory pointer later.
|
||||||
@ -1785,7 +1785,7 @@ void IRGeneratorForStatements::endVisit(MemberAccess const& _memberAccess)
|
|||||||
""
|
""
|
||||||
);
|
);
|
||||||
define(IRVariable{_memberAccess}) << formatNumber(
|
define(IRVariable{_memberAccess}) << formatNumber(
|
||||||
util::selectorFromSignature(functionType.externalSignature())
|
util::selectorFromSignatureU256(functionType.externalSignature())
|
||||||
) << "\n";
|
) << "\n";
|
||||||
}
|
}
|
||||||
else if (functionType.kind() == FunctionType::Kind::Event)
|
else if (functionType.kind() == FunctionType::Kind::Event)
|
||||||
@ -3234,7 +3234,7 @@ void IRGeneratorForStatements::handleCatch(TryStatement const& _tryStatement)
|
|||||||
|
|
||||||
if (TryCatchClause const* errorClause = _tryStatement.errorClause())
|
if (TryCatchClause const* errorClause = _tryStatement.errorClause())
|
||||||
{
|
{
|
||||||
appendCode() << "case " << selectorFromSignature32("Error(string)") << " {\n";
|
appendCode() << "case " << selectorFromSignatureU32("Error(string)") << " {\n";
|
||||||
setLocation(*errorClause);
|
setLocation(*errorClause);
|
||||||
string const dataVariable = m_context.newYulVariable();
|
string const dataVariable = m_context.newYulVariable();
|
||||||
appendCode() << "let " << dataVariable << " := " << m_utils.tryDecodeErrorMessageFunction() << "()\n";
|
appendCode() << "let " << dataVariable << " := " << m_utils.tryDecodeErrorMessageFunction() << "()\n";
|
||||||
@ -3254,7 +3254,7 @@ void IRGeneratorForStatements::handleCatch(TryStatement const& _tryStatement)
|
|||||||
}
|
}
|
||||||
if (TryCatchClause const* panicClause = _tryStatement.panicClause())
|
if (TryCatchClause const* panicClause = _tryStatement.panicClause())
|
||||||
{
|
{
|
||||||
appendCode() << "case " << selectorFromSignature32("Panic(uint256)") << " {\n";
|
appendCode() << "case " << selectorFromSignatureU32("Panic(uint256)") << " {\n";
|
||||||
setLocation(*panicClause);
|
setLocation(*panicClause);
|
||||||
string const success = m_context.newYulVariable();
|
string const success = m_context.newYulVariable();
|
||||||
string const code = m_context.newYulVariable();
|
string const code = m_context.newYulVariable();
|
||||||
@ -3317,7 +3317,7 @@ void IRGeneratorForStatements::revertWithError(
|
|||||||
})");
|
})");
|
||||||
templ("pos", m_context.newYulVariable());
|
templ("pos", m_context.newYulVariable());
|
||||||
templ("end", 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());
|
templ("allocateUnbounded", m_utils.allocateUnboundedFunction());
|
||||||
|
|
||||||
vector<string> errorArgumentVars;
|
vector<string> errorArgumentVars;
|
||||||
|
@ -1034,7 +1034,7 @@ Json::Value CompilerStack::interfaceSymbols(string const& _contractName) const
|
|||||||
for (ErrorDefinition const* error: contractDefinition(_contractName).interfaceErrors())
|
for (ErrorDefinition const* error: contractDefinition(_contractName).interfaceErrors())
|
||||||
{
|
{
|
||||||
string signature = error->functionType(true)->externalSignature();
|
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(
|
for (EventDefinition const* event: ranges::concat_view(
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
#include <libevmasm/ControlFlowGraph.h>
|
#include <libevmasm/ControlFlowGraph.h>
|
||||||
#include <libevmasm/KnownState.h>
|
#include <libevmasm/KnownState.h>
|
||||||
#include <libevmasm/PathGasMeter.h>
|
#include <libevmasm/PathGasMeter.h>
|
||||||
|
#include <libsolutil/FunctionSelector.h>
|
||||||
#include <libsolutil/Keccak256.h>
|
#include <libsolutil/Keccak256.h>
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
@ -54,7 +55,7 @@ GasEstimator::GasConsumption GasEstimator::functionalEstimation(
|
|||||||
ExpressionClasses& classes = state->expressionClasses();
|
ExpressionClasses& classes = state->expressionClasses();
|
||||||
using Id = ExpressionClasses::Id;
|
using Id = ExpressionClasses::Id;
|
||||||
using Ids = vector<Id>;
|
using Ids = vector<Id>;
|
||||||
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))});
|
Id calldata = classes.find(Instruction::CALLDATALOAD, Ids{classes.find(u256(0))});
|
||||||
if (!m_evmVersion.hasBitwiseShifting())
|
if (!m_evmVersion.hasBitwiseShifting())
|
||||||
// div(calldataload(0), 1 << 224) equals to hashValue
|
// div(calldataload(0), 1 << 224) equals to hashValue
|
||||||
|
@ -26,17 +26,22 @@
|
|||||||
namespace solidity::util
|
namespace solidity::util
|
||||||
{
|
{
|
||||||
|
|
||||||
/// @returns the ABI selector for a given function signature, as a 32 bit number.
|
/// @returns the ABI selector for a given function signature, as a FixedHash h32.
|
||||||
inline uint32_t selectorFromSignature32(std::string const& _signature)
|
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.
|
/// @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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,7 @@ set(libsolutil_sources
|
|||||||
libsolutil/CommonData.cpp
|
libsolutil/CommonData.cpp
|
||||||
libsolutil/CommonIO.cpp
|
libsolutil/CommonIO.cpp
|
||||||
libsolutil/FixedHash.cpp
|
libsolutil/FixedHash.cpp
|
||||||
|
libsolutil/FunctionSelector.cpp
|
||||||
libsolutil/IndentedWriter.cpp
|
libsolutil/IndentedWriter.cpp
|
||||||
libsolutil/IpfsHash.cpp
|
libsolutil/IpfsHash.cpp
|
||||||
libsolutil/IterateReplacing.cpp
|
libsolutil/IterateReplacing.cpp
|
||||||
|
@ -30,7 +30,6 @@
|
|||||||
#include <test/libsolidity/util/SoltestTypes.h>
|
#include <test/libsolidity/util/SoltestTypes.h>
|
||||||
|
|
||||||
#include <libsolutil/CommonIO.h>
|
#include <libsolutil/CommonIO.h>
|
||||||
#include <libsolutil/FunctionSelector.h>
|
|
||||||
|
|
||||||
#include <liblangutil/Exceptions.h>
|
#include <liblangutil/Exceptions.h>
|
||||||
|
|
||||||
@ -123,7 +122,7 @@ bytes ExecutionFramework::panicData(util::PanicCode _code)
|
|||||||
{
|
{
|
||||||
return
|
return
|
||||||
m_evmVersion.supportsReturndata() ?
|
m_evmVersion.supportsReturndata() ?
|
||||||
toCompactBigEndian(selectorFromSignature32("Panic(uint256)"), 4) + encode(u256(static_cast<unsigned>(_code))) :
|
toCompactBigEndian(selectorFromSignatureU32("Panic(uint256)"), 4) + encode(u256(static_cast<unsigned>(_code))) :
|
||||||
bytes();
|
bytes();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -31,8 +31,7 @@
|
|||||||
|
|
||||||
#include <liblangutil/EVMVersion.h>
|
#include <liblangutil/EVMVersion.h>
|
||||||
|
|
||||||
#include <libsolutil/FixedHash.h>
|
#include <libsolutil/FunctionSelector.h>
|
||||||
#include <libsolutil/Keccak256.h>
|
|
||||||
#include <libsolutil/ErrorCodes.h>
|
#include <libsolutil/ErrorCodes.h>
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
@ -108,8 +107,7 @@ public:
|
|||||||
|
|
||||||
bytes const& callContractFunctionWithValueNoEncoding(std::string _sig, u256 const& _value, bytes const& _arguments)
|
bytes const& callContractFunctionWithValueNoEncoding(std::string _sig, u256 const& _value, bytes const& _arguments)
|
||||||
{
|
{
|
||||||
util::FixedHash<4> hash(util::keccak256(_sig));
|
sendMessage(util::selectorFromSignatureH32(_sig).asBytes() + _arguments, false, _value);
|
||||||
sendMessage(hash.asBytes() + _arguments, false, _value);
|
|
||||||
return m_output;
|
return m_output;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -591,7 +591,7 @@ BOOST_AUTO_TEST_CASE(revoke_addOwner)
|
|||||||
BOOST_REQUIRE(callContractFunction("changeRequirement(uint256)", u256(3)) == encodeArgs());
|
BOOST_REQUIRE(callContractFunction("changeRequirement(uint256)", u256(3)) == encodeArgs());
|
||||||
// add a new owner
|
// add a new owner
|
||||||
h160 deployer = m_sender;
|
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("addOwner(address)", h160(0x33)) == encodeArgs());
|
||||||
BOOST_REQUIRE(callContractFunction("isOwner(address)", h160(0x33)) == encodeArgs(false));
|
BOOST_REQUIRE(callContractFunction("isOwner(address)", h160(0x33)) == encodeArgs(false));
|
||||||
m_sender = account(0);
|
m_sender = account(0);
|
||||||
|
@ -342,7 +342,7 @@ BOOST_AUTO_TEST_CASE(external_function)
|
|||||||
BOTH_ENCODERS(
|
BOTH_ENCODERS(
|
||||||
compileAndRun(sourceCode);
|
compileAndRun(sourceCode);
|
||||||
callContractFunction("f(uint256)", u256(0));
|
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));
|
REQUIRE_LOG_DATA(encodeArgs(functionIdF, functionIdF));
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,7 @@
|
|||||||
|
|
||||||
#include <liblangutil/Scanner.h>
|
#include <liblangutil/Scanner.h>
|
||||||
|
|
||||||
#include <libsolutil/Keccak256.h>
|
#include <libsolutil/FunctionSelector.h>
|
||||||
|
|
||||||
#include <boost/test/unit_test.hpp>
|
#include <boost/test/unit_test.hpp>
|
||||||
|
|
||||||
@ -170,6 +170,5 @@ FunctionTypePointer AnalysisFramework::retrieveFunctionBySignature(
|
|||||||
std::string const& _signature
|
std::string const& _signature
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
FixedHash<4> hash(util::keccak256(_signature));
|
return _contract.interfaceFunctions()[util::selectorFromSignatureH32(_signature)];
|
||||||
return _contract.interfaceFunctions()[hash];
|
|
||||||
}
|
}
|
||||||
|
@ -78,7 +78,7 @@ public:
|
|||||||
{
|
{
|
||||||
u256 gasUsed = 0;
|
u256 gasUsed = 0;
|
||||||
GasMeter::GasConsumption gas;
|
GasMeter::GasConsumption gas;
|
||||||
util::FixedHash<4> hash(util::keccak256(_sig));
|
util::FixedHash<4> hash = util::selectorFromSignatureH32(_sig);
|
||||||
for (bytes const& arguments: _argumentVariants)
|
for (bytes const& arguments: _argumentVariants)
|
||||||
{
|
{
|
||||||
sendMessage(hash.asBytes() + arguments, false, 0);
|
sendMessage(hash.asBytes() + arguments, false, 0);
|
||||||
|
@ -1627,7 +1627,7 @@ BOOST_AUTO_TEST_CASE(bytes_from_calldata_to_memory)
|
|||||||
ALSO_VIA_YUL(
|
ALSO_VIA_YUL(
|
||||||
DISABLE_EWASM_TESTRUN();
|
DISABLE_EWASM_TESTRUN();
|
||||||
compileAndRun(sourceCode);
|
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);
|
sendMessage(calldata1, false);
|
||||||
BOOST_CHECK(m_transactionSuccessful);
|
BOOST_CHECK(m_transactionSuccessful);
|
||||||
BOOST_CHECK(m_output == encodeArgs(util::keccak256(bytes{'a', 'b', 'c'} + calldata1)));
|
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);
|
compileAndRun(sourceCode);
|
||||||
|
|
||||||
string innercalldata1 = asString(FixedHash<4>(util::keccak256("f(uint256,uint256)")).asBytes() + encodeArgs(8, 9));
|
string innercalldata1 = asString(util::selectorFromSignatureH32("f(uint256,uint256)").asBytes() + encodeArgs(8, 9));
|
||||||
string innercalldata2 = asString(FixedHash<4>(util::keccak256("g(uint256)")).asBytes() + encodeArgs(3));
|
string innercalldata2 = asString(util::selectorFromSignatureH32("g(uint256)").asBytes() + encodeArgs(3));
|
||||||
bytes calldata = encodeArgs(
|
bytes calldata = encodeArgs(
|
||||||
12, 32 * 4, u256(32 * 4 + 32 + (innercalldata1.length() + 31) / 32 * 32), 13,
|
12, 32 * 4, u256(32 * 4 + 32 + (innercalldata1.length() + 31) / 32 * 32), 13,
|
||||||
u256(innercalldata1.length()), innercalldata1,
|
u256(innercalldata1.length()), innercalldata1,
|
||||||
@ -2205,8 +2205,8 @@ BOOST_AUTO_TEST_CASE(calldata_struct_function_type)
|
|||||||
)";
|
)";
|
||||||
compileAndRun(sourceCode, 0, "C");
|
compileAndRun(sourceCode, 0, "C");
|
||||||
|
|
||||||
bytes fn_C_g = m_contractAddress.asBytes() + FixedHash<4>(util::keccak256("g(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() + FixedHash<4>(util::keccak256("h(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_g), encodeArgs(42 * 3));
|
||||||
ABI_CHECK(callContractFunctionNoEncoding("f((function))", fn_C_h), encodeArgs(23));
|
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");
|
compileAndRun(sourceCode, 0, "C");
|
||||||
ABI_CHECK(callContractFunction(
|
ABI_CHECK(callContractFunction(
|
||||||
"f(function)",
|
"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)));
|
), encodeArgs(u256(7)));
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@ -3026,7 +3026,7 @@ BOOST_AUTO_TEST_CASE(return_external_function_type)
|
|||||||
compileAndRun(sourceCode, 0, "C");
|
compileAndRun(sourceCode, 0, "C");
|
||||||
ABI_CHECK(
|
ABI_CHECK(
|
||||||
callContractFunction("f()"),
|
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)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -338,9 +338,9 @@ solidity::frontend::test::ParameterList ContractABIUtils::failureParameters(byte
|
|||||||
parameters.push_back(Parameter{bytes(), "", ABIType{ABIType::HexString, ABIType::AlignNone, 4}, FormatInfo{}});
|
parameters.push_back(Parameter{bytes(), "", ABIType{ABIType::HexString, ABIType::AlignNone, 4}, FormatInfo{}});
|
||||||
|
|
||||||
uint64_t selector = fromBigEndian<uint64_t>(bytes{_bytes.begin(), _bytes.begin() + 4});
|
uint64_t selector = fromBigEndian<uint64_t>(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{}});
|
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::Hex}, FormatInfo{}});
|
||||||
parameters.push_back(Parameter{bytes(), "", ABIType{ABIType::UnsignedDec}, FormatInfo{}});
|
parameters.push_back(Parameter{bytes(), "", ABIType{ABIType::UnsignedDec}, FormatInfo{}});
|
||||||
|
53
test/libsolutil/FunctionSelector.cpp
Normal file
53
test/libsolutil/FunctionSelector.cpp
Normal file
@ -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 <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
* Unit tests for FunctionSelector.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <libsolutil/FunctionSelector.h>
|
||||||
|
|
||||||
|
#include <boost/test/unit_test.hpp>
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <sstream>
|
||||||
|
|
||||||
|
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()
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user