Merge pull request #6473 from ethereum/libeventhash-6435

Fix external ABI type name for contracts
This commit is contained in:
chriseth 2019-04-18 12:53:34 +02:00 committed by GitHub
commit fb302c1c4f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 115 additions and 24 deletions

View File

@ -25,6 +25,8 @@ Compiler Features:
Bugfixes:
* SMTChecker: Implement Boolean short-circuiting.
* SMTChecker: SSA control-flow did not take into account state variables that were modified inside inlined functions that were called inside branches.
* Type System: Use correct type name for contracts in event parameters when used in
libraries. This affected code generation.
* Yul: Properly register functions and disallow shadowing between function variables and variables in the outside scope.

View File

@ -1,4 +1,12 @@
[
{
"name": "IncorrectEventSignatureInLibraries",
"summary": "Contract types used in events in libraries cause an incorrect event signature hash",
"description": "Instead of using the type `address` in the hashed signature, the actual contract name was used, leading to a wrong hash in the logs.",
"introduced": "0.3.0",
"fixed": "0.5.8",
"severity": "very low"
},
{
"name": "ABIEncoderV2PackedStorage",
"summary": "Storage structs and arrays with types shorter than 32 bytes can cause data corruption if encoded directly from storage using the experimental ABIEncoderV2.",

View File

@ -211,6 +211,7 @@
},
"0.3.0": {
"bugs": [
"IncorrectEventSignatureInLibraries",
"ExpExponentCleanup",
"NestedArrayFunctionCallDecoder",
"ZeroFunctionSelector",
@ -231,6 +232,7 @@
},
"0.3.1": {
"bugs": [
"IncorrectEventSignatureInLibraries",
"ExpExponentCleanup",
"NestedArrayFunctionCallDecoder",
"ZeroFunctionSelector",
@ -250,6 +252,7 @@
},
"0.3.2": {
"bugs": [
"IncorrectEventSignatureInLibraries",
"ExpExponentCleanup",
"NestedArrayFunctionCallDecoder",
"ZeroFunctionSelector",
@ -269,6 +272,7 @@
},
"0.3.3": {
"bugs": [
"IncorrectEventSignatureInLibraries",
"ExpExponentCleanup",
"NestedArrayFunctionCallDecoder",
"ZeroFunctionSelector",
@ -287,6 +291,7 @@
},
"0.3.4": {
"bugs": [
"IncorrectEventSignatureInLibraries",
"ExpExponentCleanup",
"NestedArrayFunctionCallDecoder",
"ZeroFunctionSelector",
@ -305,6 +310,7 @@
},
"0.3.5": {
"bugs": [
"IncorrectEventSignatureInLibraries",
"ExpExponentCleanup",
"NestedArrayFunctionCallDecoder",
"ZeroFunctionSelector",
@ -323,6 +329,7 @@
},
"0.3.6": {
"bugs": [
"IncorrectEventSignatureInLibraries",
"ExpExponentCleanup",
"NestedArrayFunctionCallDecoder",
"ZeroFunctionSelector",
@ -339,6 +346,7 @@
},
"0.4.0": {
"bugs": [
"IncorrectEventSignatureInLibraries",
"ExpExponentCleanup",
"NestedArrayFunctionCallDecoder",
"ZeroFunctionSelector",
@ -355,6 +363,7 @@
},
"0.4.1": {
"bugs": [
"IncorrectEventSignatureInLibraries",
"ExpExponentCleanup",
"NestedArrayFunctionCallDecoder",
"ZeroFunctionSelector",
@ -371,6 +380,7 @@
},
"0.4.10": {
"bugs": [
"IncorrectEventSignatureInLibraries",
"ExpExponentCleanup",
"NestedArrayFunctionCallDecoder",
"ZeroFunctionSelector",
@ -383,6 +393,7 @@
},
"0.4.11": {
"bugs": [
"IncorrectEventSignatureInLibraries",
"ExpExponentCleanup",
"NestedArrayFunctionCallDecoder",
"ZeroFunctionSelector",
@ -394,6 +405,7 @@
},
"0.4.12": {
"bugs": [
"IncorrectEventSignatureInLibraries",
"ExpExponentCleanup",
"NestedArrayFunctionCallDecoder",
"ZeroFunctionSelector",
@ -404,6 +416,7 @@
},
"0.4.13": {
"bugs": [
"IncorrectEventSignatureInLibraries",
"ExpExponentCleanup",
"NestedArrayFunctionCallDecoder",
"ZeroFunctionSelector",
@ -414,6 +427,7 @@
},
"0.4.14": {
"bugs": [
"IncorrectEventSignatureInLibraries",
"ExpExponentCleanup",
"NestedArrayFunctionCallDecoder",
"ZeroFunctionSelector",
@ -423,6 +437,7 @@
},
"0.4.15": {
"bugs": [
"IncorrectEventSignatureInLibraries",
"ExpExponentCleanup",
"NestedArrayFunctionCallDecoder",
"ZeroFunctionSelector"
@ -431,6 +446,7 @@
},
"0.4.16": {
"bugs": [
"IncorrectEventSignatureInLibraries",
"ExpExponentCleanup",
"NestedArrayFunctionCallDecoder",
"ZeroFunctionSelector"
@ -439,6 +455,7 @@
},
"0.4.17": {
"bugs": [
"IncorrectEventSignatureInLibraries",
"ExpExponentCleanup",
"EventStructWrongData",
"NestedArrayFunctionCallDecoder",
@ -448,6 +465,7 @@
},
"0.4.18": {
"bugs": [
"IncorrectEventSignatureInLibraries",
"ExpExponentCleanup",
"EventStructWrongData",
"NestedArrayFunctionCallDecoder"
@ -456,6 +474,7 @@
},
"0.4.19": {
"bugs": [
"IncorrectEventSignatureInLibraries",
"ABIEncoderV2PackedStorage",
"ExpExponentCleanup",
"EventStructWrongData",
@ -465,6 +484,7 @@
},
"0.4.2": {
"bugs": [
"IncorrectEventSignatureInLibraries",
"ExpExponentCleanup",
"NestedArrayFunctionCallDecoder",
"ZeroFunctionSelector",
@ -480,6 +500,7 @@
},
"0.4.20": {
"bugs": [
"IncorrectEventSignatureInLibraries",
"ABIEncoderV2PackedStorage",
"ExpExponentCleanup",
"EventStructWrongData",
@ -489,6 +510,7 @@
},
"0.4.21": {
"bugs": [
"IncorrectEventSignatureInLibraries",
"ABIEncoderV2PackedStorage",
"ExpExponentCleanup",
"EventStructWrongData",
@ -498,6 +520,7 @@
},
"0.4.22": {
"bugs": [
"IncorrectEventSignatureInLibraries",
"ABIEncoderV2PackedStorage",
"ExpExponentCleanup",
"EventStructWrongData",
@ -507,6 +530,7 @@
},
"0.4.23": {
"bugs": [
"IncorrectEventSignatureInLibraries",
"ABIEncoderV2PackedStorage",
"ExpExponentCleanup",
"EventStructWrongData"
@ -515,6 +539,7 @@
},
"0.4.24": {
"bugs": [
"IncorrectEventSignatureInLibraries",
"ABIEncoderV2PackedStorage",
"ExpExponentCleanup",
"EventStructWrongData"
@ -523,12 +548,14 @@
},
"0.4.25": {
"bugs": [
"IncorrectEventSignatureInLibraries",
"ABIEncoderV2PackedStorage"
],
"released": "2018-09-12"
},
"0.4.3": {
"bugs": [
"IncorrectEventSignatureInLibraries",
"ExpExponentCleanup",
"NestedArrayFunctionCallDecoder",
"ZeroFunctionSelector",
@ -543,6 +570,7 @@
},
"0.4.4": {
"bugs": [
"IncorrectEventSignatureInLibraries",
"ExpExponentCleanup",
"NestedArrayFunctionCallDecoder",
"ZeroFunctionSelector",
@ -556,6 +584,7 @@
},
"0.4.5": {
"bugs": [
"IncorrectEventSignatureInLibraries",
"ExpExponentCleanup",
"NestedArrayFunctionCallDecoder",
"ZeroFunctionSelector",
@ -570,6 +599,7 @@
},
"0.4.6": {
"bugs": [
"IncorrectEventSignatureInLibraries",
"ExpExponentCleanup",
"NestedArrayFunctionCallDecoder",
"ZeroFunctionSelector",
@ -583,6 +613,7 @@
},
"0.4.7": {
"bugs": [
"IncorrectEventSignatureInLibraries",
"ExpExponentCleanup",
"NestedArrayFunctionCallDecoder",
"ZeroFunctionSelector",
@ -595,6 +626,7 @@
},
"0.4.8": {
"bugs": [
"IncorrectEventSignatureInLibraries",
"ExpExponentCleanup",
"NestedArrayFunctionCallDecoder",
"ZeroFunctionSelector",
@ -607,6 +639,7 @@
},
"0.4.9": {
"bugs": [
"IncorrectEventSignatureInLibraries",
"ExpExponentCleanup",
"NestedArrayFunctionCallDecoder",
"ZeroFunctionSelector",
@ -619,36 +652,42 @@
},
"0.5.0": {
"bugs": [
"IncorrectEventSignatureInLibraries",
"ABIEncoderV2PackedStorage"
],
"released": "2018-11-13"
},
"0.5.1": {
"bugs": [
"IncorrectEventSignatureInLibraries",
"ABIEncoderV2PackedStorage"
],
"released": "2018-12-03"
},
"0.5.2": {
"bugs": [
"IncorrectEventSignatureInLibraries",
"ABIEncoderV2PackedStorage"
],
"released": "2018-12-19"
},
"0.5.3": {
"bugs": [
"IncorrectEventSignatureInLibraries",
"ABIEncoderV2PackedStorage"
],
"released": "2019-01-22"
},
"0.5.4": {
"bugs": [
"IncorrectEventSignatureInLibraries",
"ABIEncoderV2PackedStorage"
],
"released": "2019-02-12"
},
"0.5.5": {
"bugs": [
"IncorrectEventSignatureInLibraries",
"ABIEncoderV2PackedStorage",
"IncorrectByteInstructionOptimization",
"DoubleShiftSizeOverflow"
@ -657,13 +696,16 @@
},
"0.5.6": {
"bugs": [
"IncorrectEventSignatureInLibraries",
"ABIEncoderV2PackedStorage",
"IncorrectByteInstructionOptimization"
],
"released": "2019-03-13"
},
"0.5.7": {
"bugs": [],
"bugs": [
"IncorrectEventSignatureInLibraries"
],
"released": "2019-03-26"
}
}

View File

@ -148,6 +148,21 @@ bool fitsIntoBits(bigint const& _value, unsigned _bits, bool _signed)
));
}
Result<TypePointers> transformParametersToExternal(TypePointers const& _parameters, bool _inLibrary)
{
TypePointers transformed;
for (auto const& type: _parameters)
{
if (TypePointer ext = type->interfaceType(_inLibrary).get())
transformed.push_back(ext);
else
return Result<TypePointers>::err("Parameter should have external type.");
}
return transformed;
}
}
void Type::clearCache() const
@ -2840,27 +2855,22 @@ FunctionTypePointer FunctionType::interfaceFunctionType() const
{
// Note that m_declaration might also be a state variable!
solAssert(m_declaration, "Declaration needed to determine interface function type.");
bool isLibraryFunction = dynamic_cast<ContractDefinition const&>(*m_declaration->scope()).isLibrary();
bool isLibraryFunction = kind() != Kind::Event && dynamic_cast<ContractDefinition const&>(*m_declaration->scope()).isLibrary();
TypePointers paramTypes;
TypePointers retParamTypes;
Result<TypePointers> paramTypes =
transformParametersToExternal(m_parameterTypes, isLibraryFunction);
if (!paramTypes.message().empty())
return FunctionTypePointer();
Result<TypePointers> retParamTypes =
transformParametersToExternal(m_returnParameterTypes, isLibraryFunction);
if (!retParamTypes.message().empty())
return FunctionTypePointer();
for (auto type: m_parameterTypes)
{
if (auto ext = type->interfaceType(isLibraryFunction).get())
paramTypes.push_back(ext);
else
return FunctionTypePointer();
}
for (auto type: m_returnParameterTypes)
{
if (auto ext = type->interfaceType(isLibraryFunction).get())
retParamTypes.push_back(ext);
else
return FunctionTypePointer();
}
auto variable = dynamic_cast<VariableDeclaration const*>(m_declaration);
if (variable && retParamTypes.empty())
if (variable && retParamTypes.get().empty())
return FunctionTypePointer();
return TypeProvider::function(
@ -3075,13 +3085,15 @@ string FunctionType::externalSignature() const
// "inLibrary" is only relevant if this is not an event.
bool const inLibrary = kind() != Kind::Event && dynamic_cast<ContractDefinition const&>(*m_declaration->scope()).isLibrary();
FunctionTypePointer external = interfaceFunctionType();
solAssert(!!external, "External function type requested.");
auto parameterTypes = external->parameterTypes();
auto typeStrings = parameterTypes | boost::adaptors::transformed([&](TypePointer _t) -> string
auto extParams = transformParametersToExternal(m_parameterTypes, inLibrary);
solAssert(extParams.message().empty(), extParams.message());
auto typeStrings = extParams.get() | boost::adaptors::transformed([&](TypePointer _t) -> string
{
solAssert(_t, "Parameter should have external type.");
string typeName = _t->signatureInExternalFunction(inLibrary);
if (inLibrary && _t->dataStoredIn(DataLocation::Storage))
typeName += " storage";
return typeName;

View File

@ -15607,6 +15607,33 @@ BOOST_AUTO_TEST_CASE(contract_name)
ABI_CHECK(callContractFunction("constantNameAccessor()"), argsLong);
}
BOOST_AUTO_TEST_CASE(event_wrong_abi_name)
{
char const* sourceCode = R"(
library ClientReceipt {
event Deposit(Test indexed _from, bytes32 indexed _id, uint _value);
function deposit(bytes32 _id) public {
Test a;
emit Deposit(a, _id, msg.value);
}
}
contract Test {
function f() public {
ClientReceipt.deposit("123");
}
}
)";
compileAndRun(sourceCode, 0, "ClientReceipt", bytes());
compileAndRun(sourceCode, 0, "Test", bytes(), map<string, Address>{{"ClientReceipt", m_contractAddress}});
u256 value(18);
u256 id(0x1234);
callContractFunction("f()");
BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 3);
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("Deposit(address,bytes32,uint256)")));
}
BOOST_AUTO_TEST_SUITE_END()