mirror of
				https://github.com/ethereum/solidity
				synced 2023-10-03 13:03:40 +00:00 
			
		
		
		
	Merge pull request #13571 from ethereum/explicit-fixedhash
Drop implicit alignment argument from FixedHash (and improve FunctionSelector helpers)
This commit is contained in:
		
						commit
						5f8b48793c
					
				| @ -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, | ||||
|  | ||||
| @ -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)) | ||||
| 		{ | ||||
|  | ||||
| @ -27,6 +27,7 @@ | ||||
| #include <libsolidity/ast/ASTVisitor.h> | ||||
| #include <libsolidity/ast/AST_accept.h> | ||||
| #include <libsolidity/ast/TypeProvider.h> | ||||
| #include <libsolutil/FunctionSelector.h> | ||||
| #include <libsolutil/Keccak256.h> | ||||
| 
 | ||||
| #include <range/v3/view/tail.hpp> | ||||
| @ -281,8 +282,7 @@ vector<pair<util::FixedHash<4>, 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); | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| @ -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 | ||||
|  | ||||
| @ -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; | ||||
|  | ||||
| @ -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: <string data> <mem pos of encoding start>
 | ||||
| @ -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: <arguments...> <mem pos of encoding start>
 | ||||
|  | ||||
| @ -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<ASTPointer<TryCatchClause>> const& _ca | ||||
| 		solAssert(m_context.evmVersion().supportsReturndata(), ""); | ||||
| 
 | ||||
| 		// 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.appendConditionalJumpTo(panicTag); | ||||
| 		m_context << Instruction::POP; // remove selector
 | ||||
| @ -1078,7 +1078,7 @@ void ContractCompiler::handleCatch(vector<ASTPointer<TryCatchClause>> const& _ca | ||||
| 		solAssert(m_context.evmVersion().supportsReturndata(), ""); | ||||
| 
 | ||||
| 		// stack: <selector>
 | ||||
| 		m_context << util::selectorFromSignature32("Panic(uint256)") << Instruction::EQ; | ||||
| 		m_context << util::selectorFromSignatureU32("Panic(uint256)") << Instruction::EQ; | ||||
| 		m_context << Instruction::ISZERO; | ||||
| 		m_context.appendConditionalJumpTo(fallbackTag); | ||||
| 
 | ||||
|  | ||||
| @ -1329,7 +1329,7 @@ bool ExpressionCompiler::visit(FunctionCall const& _functionCall) | ||||
| 					// hash the signature
 | ||||
| 					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); | ||||
| 					} | ||||
| 					else | ||||
|  | ||||
| @ -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, <overallLength>) | ||||
| 	)"); | ||||
| 	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<unsigned>(_code))) | ||||
| 		.render(); | ||||
| 	}); | ||||
|  | ||||
| @ -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<StringLiteralType const*>(&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<string> errorArgumentVars; | ||||
|  | ||||
| @ -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( | ||||
|  | ||||
| @ -30,6 +30,7 @@ | ||||
| #include <libevmasm/ControlFlowGraph.h> | ||||
| #include <libevmasm/KnownState.h> | ||||
| #include <libevmasm/PathGasMeter.h> | ||||
| #include <libsolutil/FunctionSelector.h> | ||||
| #include <libsolutil/Keccak256.h> | ||||
| 
 | ||||
| #include <functional> | ||||
| @ -54,7 +55,7 @@ GasEstimator::GasConsumption GasEstimator::functionalEstimation( | ||||
| 		ExpressionClasses& classes = state->expressionClasses(); | ||||
| 		using Id = ExpressionClasses::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))}); | ||||
| 		if (!m_evmVersion.hasBitwiseShifting()) | ||||
| 			// div(calldataload(0), 1 << 224) equals to hashValue
 | ||||
|  | ||||
| @ -61,7 +61,7 @@ public: | ||||
| 	explicit FixedHash() { m_data.fill(0); } | ||||
| 
 | ||||
| 	/// Construct from another hash, filling with zeroes or cropping as necessary.
 | ||||
| 	template <unsigned M> explicit FixedHash(FixedHash<M> const& _h, ConstructFromHashType _t = AlignLeft) | ||||
| 	template <unsigned M> explicit FixedHash(FixedHash<M> const& _h, ConstructFromHashType _t) | ||||
| 	{ | ||||
| 		m_data.fill(0); | ||||
| 		unsigned c = std::min(M, N); | ||||
|  | ||||
| @ -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); | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| } | ||||
|  | ||||
| @ -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 | ||||
|  | ||||
| @ -255,7 +255,7 @@ evmc::result EVMHost::call(evmc_message const& _message) noexcept | ||||
| 		h160 createAddress(keccak256( | ||||
| 			bytes(begin(message.sender.bytes), end(message.sender.bytes)) + | ||||
| 			asBytes(to_string(sender.nonce++)) | ||||
| 		)); | ||||
| 		), h160::AlignLeft); | ||||
| 		message.destination = convertToEVMC(createAddress); | ||||
| 		code = evmc::bytes(message.input_data, message.input_data + message.input_size); | ||||
| 	} | ||||
| @ -266,7 +266,7 @@ evmc::result EVMHost::call(evmc_message const& _message) noexcept | ||||
| 			bytes(begin(message.sender.bytes), end(message.sender.bytes)) + | ||||
| 			bytes(begin(message.create2_salt.bytes), end(message.create2_salt.bytes)) + | ||||
| 			keccak256(bytes(message.input_data, message.input_data + message.input_size)).asBytes() | ||||
| 		)); | ||||
| 		), h160::AlignLeft); | ||||
| 		message.destination = convertToEVMC(createAddress); | ||||
| 		if (accounts.count(message.destination) && ( | ||||
| 			accounts[message.destination].nonce > 0 || | ||||
|  | ||||
| @ -30,7 +30,6 @@ | ||||
| #include <test/libsolidity/util/SoltestTypes.h> | ||||
| 
 | ||||
| #include <libsolutil/CommonIO.h> | ||||
| #include <libsolutil/FunctionSelector.h> | ||||
| 
 | ||||
| #include <liblangutil/Exceptions.h> | ||||
| 
 | ||||
| @ -123,7 +122,7 @@ bytes ExecutionFramework::panicData(util::PanicCode _code) | ||||
| { | ||||
| 	return | ||||
| 		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(); | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -31,8 +31,7 @@ | ||||
| 
 | ||||
| #include <liblangutil/EVMVersion.h> | ||||
| 
 | ||||
| #include <libsolutil/FixedHash.h> | ||||
| #include <libsolutil/Keccak256.h> | ||||
| #include <libsolutil/FunctionSelector.h> | ||||
| #include <libsolutil/ErrorCodes.h> | ||||
| 
 | ||||
| #include <functional> | ||||
| @ -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; | ||||
| 	} | ||||
| 
 | ||||
|  | ||||
| @ -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); | ||||
|  | ||||
| @ -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)); | ||||
| 	) | ||||
| } | ||||
|  | ||||
| @ -30,7 +30,7 @@ | ||||
| 
 | ||||
| #include <liblangutil/Scanner.h> | ||||
| 
 | ||||
| #include <libsolutil/Keccak256.h> | ||||
| #include <libsolutil/FunctionSelector.h> | ||||
| 
 | ||||
| #include <boost/test/unit_test.hpp> | ||||
| 
 | ||||
| @ -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)]; | ||||
| } | ||||
|  | ||||
| @ -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); | ||||
|  | ||||
| @ -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) | ||||
| 	); | ||||
| } | ||||
| 
 | ||||
|  | ||||
| @ -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<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{}}); | ||||
| 		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{}}); | ||||
|  | ||||
| @ -146,29 +146,30 @@ BOOST_AUTO_TEST_CASE(string_constructor_frombytes) | ||||
| 
 | ||||
| BOOST_AUTO_TEST_CASE(converting_constructor) | ||||
| { | ||||
| 	// Truncation
 | ||||
| 	FixedHash<8> a = FixedHash<8>(FixedHash<12>("112233445566778899001122")); | ||||
| 	// Left-aligned truncation
 | ||||
| 	FixedHash<8> a = FixedHash<8>(FixedHash<12>("112233445566778899001122"), FixedHash<8>::AlignLeft); | ||||
| 	BOOST_CHECK_EQUAL(a.size, 8); | ||||
| 	BOOST_CHECK_EQUAL(a.hex(), "1122334455667788"); | ||||
| 
 | ||||
| 	// Right-aligned truncation
 | ||||
| 	FixedHash<8> b = FixedHash<8>(FixedHash<12>("112233445566778899001122"), FixedHash<8>::AlignRight); | ||||
| 	BOOST_CHECK_EQUAL(b.size, 8); | ||||
| 	BOOST_CHECK_EQUAL(b.hex(), "5566778899001122"); | ||||
| 
 | ||||
| 	// Left-aligned extension
 | ||||
| 	FixedHash<12> b = FixedHash<12>(FixedHash<8>("1122334455667788"), FixedHash<12>::AlignLeft); | ||||
| 	BOOST_CHECK_EQUAL(b.size, 12); | ||||
| 	BOOST_CHECK_EQUAL(b.hex(), "112233445566778800000000"); | ||||
| 	FixedHash<12> c = FixedHash<12>(FixedHash<8>("1122334455667788"), FixedHash<12>::AlignLeft); | ||||
| 	BOOST_CHECK_EQUAL(c.size, 12); | ||||
| 	BOOST_CHECK_EQUAL(c.hex(), "112233445566778800000000"); | ||||
| 
 | ||||
| 	// Right-aligned extension
 | ||||
| 	FixedHash<12> c = FixedHash<12>(FixedHash<8>("1122334455667788"), FixedHash<12>::AlignRight); | ||||
| 	BOOST_CHECK_EQUAL(c.size, 12); | ||||
| 	BOOST_CHECK_EQUAL(c.hex(), "000000001122334455667788"); | ||||
| 
 | ||||
| 	// Default setting
 | ||||
| 	FixedHash<12> d = FixedHash<12>(FixedHash<8>("1122334455667788")); | ||||
| 	BOOST_CHECK_EQUAL(d, b); | ||||
| 	FixedHash<12> d = FixedHash<12>(FixedHash<8>("1122334455667788"), FixedHash<12>::AlignRight); | ||||
| 	BOOST_CHECK_EQUAL(d.size, 12); | ||||
| 	BOOST_CHECK_EQUAL(d.hex(), "000000001122334455667788"); | ||||
| 
 | ||||
| 	// FailIfDifferent setting
 | ||||
| 	// TODO: Shouldn't this throw?
 | ||||
| 	FixedHash<12> e = FixedHash<12>(FixedHash<8>("1122334455667788"), FixedHash<12>::FailIfDifferent); | ||||
| 	BOOST_CHECK_EQUAL(e, b); | ||||
| 	BOOST_CHECK_EQUAL(e, c); | ||||
| } | ||||
| 
 | ||||
| BOOST_AUTO_TEST_CASE(arith_constructor) | ||||
|  | ||||
							
								
								
									
										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() | ||||
| 
 | ||||
| } | ||||
| @ -439,7 +439,7 @@ u256 EwasmBuiltinInterpreter::evalEthBuiltin(string const& _fun, vector<uint64_t | ||||
| 	} | ||||
| 	else if (_fun == "getExternalCodeSize") | ||||
| 		// Generate "random" code length.
 | ||||
| 		return uint32_t(u256(keccak256(h256(readAddress(arg[0])))) & 0xfff); | ||||
| 		return uint32_t(u256(keccak256(h256(readAddress(arg[0]), h256::AlignLeft))) & 0xfff); | ||||
| 	else if (_fun == "getGasLeft") | ||||
| 		return 0x99; | ||||
| 	else if (_fun == "getBlockGasLimit") | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user