mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Merge pull request #4820 from ethereum/disallow_indexed_ref_v2
Disallow indexed reference types in events when using ABIEncoderV2
This commit is contained in:
commit
c164f80ba6
@ -108,6 +108,7 @@ Bugfixes:
|
|||||||
* Type Checker: Fix crashes in erroneous tuple assignments in which the type of the right hand side cannot be determined.
|
* Type Checker: Fix crashes in erroneous tuple assignments in which the type of the right hand side cannot be determined.
|
||||||
* Type Checker: Fix freeze for negative fixed-point literals very close to ``0``, such as ``-1e-100``.
|
* Type Checker: Fix freeze for negative fixed-point literals very close to ``0``, such as ``-1e-100``.
|
||||||
* Type Checker: Report error when using structs in events without experimental ABIEncoderV2. This used to crash or log the wrong values.
|
* Type Checker: Report error when using structs in events without experimental ABIEncoderV2. This used to crash or log the wrong values.
|
||||||
|
* Type Checker: Report error when using indexed structs in events with experimental ABIEncoderV2. This used to log wrong values.
|
||||||
* Type System: Allow arbitrary exponents for literals with a mantissa of zero.
|
* Type System: Allow arbitrary exponents for literals with a mantissa of zero.
|
||||||
|
|
||||||
### 0.4.24 (2018-05-16)
|
### 0.4.24 (2018-05-16)
|
||||||
|
@ -1,4 +1,12 @@
|
|||||||
[
|
[
|
||||||
|
{
|
||||||
|
"name": "EventStructWrongData",
|
||||||
|
"summary": "Using structs in events logged wrong data.",
|
||||||
|
"description": "If a struct is used in an event, the address of the struct is logged instead of the actual data.",
|
||||||
|
"introduced": "0.4.17",
|
||||||
|
"fixed": "0.5.0",
|
||||||
|
"severity": "very low"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "NestedArrayFunctionCallDecoder",
|
"name": "NestedArrayFunctionCallDecoder",
|
||||||
"summary": "Calling functions that return multi-dimensional fixed-size arrays can result in memory corruption.",
|
"summary": "Calling functions that return multi-dimensional fixed-size arrays can result in memory corruption.",
|
||||||
|
@ -412,6 +412,7 @@
|
|||||||
},
|
},
|
||||||
"0.4.17": {
|
"0.4.17": {
|
||||||
"bugs": [
|
"bugs": [
|
||||||
|
"EventStructWrongData",
|
||||||
"NestedArrayFunctionCallDecoder",
|
"NestedArrayFunctionCallDecoder",
|
||||||
"ZeroFunctionSelector"
|
"ZeroFunctionSelector"
|
||||||
],
|
],
|
||||||
@ -419,12 +420,14 @@
|
|||||||
},
|
},
|
||||||
"0.4.18": {
|
"0.4.18": {
|
||||||
"bugs": [
|
"bugs": [
|
||||||
|
"EventStructWrongData",
|
||||||
"NestedArrayFunctionCallDecoder"
|
"NestedArrayFunctionCallDecoder"
|
||||||
],
|
],
|
||||||
"released": "2017-10-18"
|
"released": "2017-10-18"
|
||||||
},
|
},
|
||||||
"0.4.19": {
|
"0.4.19": {
|
||||||
"bugs": [
|
"bugs": [
|
||||||
|
"EventStructWrongData",
|
||||||
"NestedArrayFunctionCallDecoder"
|
"NestedArrayFunctionCallDecoder"
|
||||||
],
|
],
|
||||||
"released": "2017-11-30"
|
"released": "2017-11-30"
|
||||||
@ -445,28 +448,35 @@
|
|||||||
},
|
},
|
||||||
"0.4.20": {
|
"0.4.20": {
|
||||||
"bugs": [
|
"bugs": [
|
||||||
|
"EventStructWrongData",
|
||||||
"NestedArrayFunctionCallDecoder"
|
"NestedArrayFunctionCallDecoder"
|
||||||
],
|
],
|
||||||
"released": "2018-02-14"
|
"released": "2018-02-14"
|
||||||
},
|
},
|
||||||
"0.4.21": {
|
"0.4.21": {
|
||||||
"bugs": [
|
"bugs": [
|
||||||
|
"EventStructWrongData",
|
||||||
"NestedArrayFunctionCallDecoder"
|
"NestedArrayFunctionCallDecoder"
|
||||||
],
|
],
|
||||||
"released": "2018-03-07"
|
"released": "2018-03-07"
|
||||||
},
|
},
|
||||||
"0.4.22": {
|
"0.4.22": {
|
||||||
"bugs": [
|
"bugs": [
|
||||||
|
"EventStructWrongData",
|
||||||
"OneOfTwoConstructorsSkipped"
|
"OneOfTwoConstructorsSkipped"
|
||||||
],
|
],
|
||||||
"released": "2018-04-16"
|
"released": "2018-04-16"
|
||||||
},
|
},
|
||||||
"0.4.23": {
|
"0.4.23": {
|
||||||
"bugs": [],
|
"bugs": [
|
||||||
|
"EventStructWrongData"
|
||||||
|
],
|
||||||
"released": "2018-04-19"
|
"released": "2018-04-19"
|
||||||
},
|
},
|
||||||
"0.4.24": {
|
"0.4.24": {
|
||||||
"bugs": [],
|
"bugs": [
|
||||||
|
"EventStructWrongData"
|
||||||
|
],
|
||||||
"released": "2018-05-16"
|
"released": "2018-05-16"
|
||||||
},
|
},
|
||||||
"0.4.3": {
|
"0.4.3": {
|
||||||
|
@ -895,7 +895,17 @@ bool TypeChecker::visit(EventDefinition const& _eventDef)
|
|||||||
for (ASTPointer<VariableDeclaration> const& var: _eventDef.parameters())
|
for (ASTPointer<VariableDeclaration> const& var: _eventDef.parameters())
|
||||||
{
|
{
|
||||||
if (var->isIndexed())
|
if (var->isIndexed())
|
||||||
|
{
|
||||||
numIndexed++;
|
numIndexed++;
|
||||||
|
if (
|
||||||
|
_eventDef.sourceUnit().annotation().experimentalFeatures.count(ExperimentalFeature::ABIEncoderV2) &&
|
||||||
|
dynamic_cast<ReferenceType const*>(type(*var).get())
|
||||||
|
)
|
||||||
|
m_errorReporter.typeError(
|
||||||
|
var->location(),
|
||||||
|
"Indexed reference types cannot yet be used with ABIEncoderV2."
|
||||||
|
);
|
||||||
|
}
|
||||||
if (!type(*var)->canLiveOutsideStorage())
|
if (!type(*var)->canLiveOutsideStorage())
|
||||||
m_errorReporter.typeError(var->location(), "Type is required to live outside storage.");
|
m_errorReporter.typeError(var->location(), "Type is required to live outside storage.");
|
||||||
if (!type(*var)->interfaceType(false))
|
if (!type(*var)->interfaceType(false))
|
||||||
|
@ -3937,6 +3937,209 @@ BOOST_AUTO_TEST_CASE(event_really_really_lots_of_data_from_storage)
|
|||||||
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("Deposit(uint256,bytes,uint256)")));
|
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("Deposit(uint256,bytes,uint256)")));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(event_struct_memory_v2)
|
||||||
|
{
|
||||||
|
char const* sourceCode = R"(
|
||||||
|
pragma experimental ABIEncoderV2;
|
||||||
|
contract C {
|
||||||
|
struct S { uint a; }
|
||||||
|
event E(S);
|
||||||
|
function createEvent(uint x) public {
|
||||||
|
emit E(S(x));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
compileAndRun(sourceCode);
|
||||||
|
u256 x(42);
|
||||||
|
callContractFunction("createEvent(uint256)", x);
|
||||||
|
BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
|
||||||
|
BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
|
||||||
|
BOOST_CHECK(m_logs[0].data == encodeArgs(x));
|
||||||
|
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1);
|
||||||
|
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("E((uint256))")));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(event_struct_storage_v2)
|
||||||
|
{
|
||||||
|
char const* sourceCode = R"(
|
||||||
|
pragma experimental ABIEncoderV2;
|
||||||
|
contract C {
|
||||||
|
struct S { uint a; }
|
||||||
|
event E(S);
|
||||||
|
S s;
|
||||||
|
function createEvent(uint x) public {
|
||||||
|
s.a = x;
|
||||||
|
emit E(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
compileAndRun(sourceCode);
|
||||||
|
u256 x(42);
|
||||||
|
callContractFunction("createEvent(uint256)", x);
|
||||||
|
BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
|
||||||
|
BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
|
||||||
|
BOOST_CHECK(m_logs[0].data == encodeArgs(x));
|
||||||
|
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1);
|
||||||
|
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("E((uint256))")));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(event_dynamic_array_memory)
|
||||||
|
{
|
||||||
|
char const* sourceCode = R"(
|
||||||
|
contract C {
|
||||||
|
event E(uint[]);
|
||||||
|
function createEvent(uint x) public {
|
||||||
|
uint[] memory arr = new uint[](3);
|
||||||
|
arr[0] = x;
|
||||||
|
arr[1] = x + 1;
|
||||||
|
arr[2] = x + 2;
|
||||||
|
emit E(arr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
compileAndRun(sourceCode);
|
||||||
|
u256 x(42);
|
||||||
|
callContractFunction("createEvent(uint256)", x);
|
||||||
|
BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
|
||||||
|
BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
|
||||||
|
BOOST_CHECK(m_logs[0].data == encodeArgs(0x20, 3, x, x + 1, x + 2));
|
||||||
|
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1);
|
||||||
|
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("E(uint256[])")));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(event_dynamic_array_memory_v2)
|
||||||
|
{
|
||||||
|
char const* sourceCode = R"(
|
||||||
|
pragma experimental ABIEncoderV2;
|
||||||
|
contract C {
|
||||||
|
event E(uint[]);
|
||||||
|
function createEvent(uint x) public {
|
||||||
|
uint[] memory arr = new uint[](3);
|
||||||
|
arr[0] = x;
|
||||||
|
arr[1] = x + 1;
|
||||||
|
arr[2] = x + 2;
|
||||||
|
emit E(arr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
compileAndRun(sourceCode);
|
||||||
|
u256 x(42);
|
||||||
|
callContractFunction("createEvent(uint256)", x);
|
||||||
|
BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
|
||||||
|
BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
|
||||||
|
BOOST_CHECK(m_logs[0].data == encodeArgs(0x20, 3, x, x + 1, x + 2));
|
||||||
|
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1);
|
||||||
|
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("E(uint256[])")));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(event_dynamic_nested_array_memory_v2)
|
||||||
|
{
|
||||||
|
char const* sourceCode = R"(
|
||||||
|
pragma experimental ABIEncoderV2;
|
||||||
|
contract C {
|
||||||
|
event E(uint[][]);
|
||||||
|
function createEvent(uint x) public {
|
||||||
|
uint[][] memory arr = new uint[][](2);
|
||||||
|
arr[0] = new uint[](2);
|
||||||
|
arr[1] = new uint[](2);
|
||||||
|
arr[0][0] = x;
|
||||||
|
arr[0][1] = x + 1;
|
||||||
|
arr[1][0] = x + 2;
|
||||||
|
arr[1][1] = x + 3;
|
||||||
|
emit E(arr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
compileAndRun(sourceCode);
|
||||||
|
u256 x(42);
|
||||||
|
callContractFunction("createEvent(uint256)", x);
|
||||||
|
BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
|
||||||
|
BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
|
||||||
|
BOOST_CHECK(m_logs[0].data == encodeArgs(0x20, 2, 0x40, 0xa0, 2, x, x + 1, 2, x + 2, x + 3));
|
||||||
|
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1);
|
||||||
|
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("E(uint256[][])")));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(event_dynamic_array_storage)
|
||||||
|
{
|
||||||
|
char const* sourceCode = R"(
|
||||||
|
contract C {
|
||||||
|
event E(uint[]);
|
||||||
|
uint[] arr;
|
||||||
|
function createEvent(uint x) public {
|
||||||
|
arr.length = 3;
|
||||||
|
arr[0] = x;
|
||||||
|
arr[1] = x + 1;
|
||||||
|
arr[2] = x + 2;
|
||||||
|
emit E(arr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
compileAndRun(sourceCode);
|
||||||
|
u256 x(42);
|
||||||
|
callContractFunction("createEvent(uint256)", x);
|
||||||
|
BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
|
||||||
|
BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
|
||||||
|
BOOST_CHECK(m_logs[0].data == encodeArgs(0x20, 3, x, x + 1, x + 2));
|
||||||
|
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1);
|
||||||
|
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("E(uint256[])")));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(event_dynamic_array_storage_v2)
|
||||||
|
{
|
||||||
|
char const* sourceCode = R"(
|
||||||
|
pragma experimental ABIEncoderV2;
|
||||||
|
contract C {
|
||||||
|
event E(uint[]);
|
||||||
|
uint[] arr;
|
||||||
|
function createEvent(uint x) public {
|
||||||
|
arr.length = 3;
|
||||||
|
arr[0] = x;
|
||||||
|
arr[1] = x + 1;
|
||||||
|
arr[2] = x + 2;
|
||||||
|
emit E(arr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
compileAndRun(sourceCode);
|
||||||
|
u256 x(42);
|
||||||
|
callContractFunction("createEvent(uint256)", x);
|
||||||
|
BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
|
||||||
|
BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
|
||||||
|
BOOST_CHECK(m_logs[0].data == encodeArgs(0x20, 3, x, x + 1, x + 2));
|
||||||
|
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1);
|
||||||
|
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("E(uint256[])")));
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_AUTO_TEST_CASE(event_dynamic_nested_array_storage_v2)
|
||||||
|
{
|
||||||
|
char const* sourceCode = R"(
|
||||||
|
pragma experimental ABIEncoderV2;
|
||||||
|
contract C {
|
||||||
|
event E(uint[][]);
|
||||||
|
uint[][] arr;
|
||||||
|
function createEvent(uint x) public {
|
||||||
|
arr.length = 2;
|
||||||
|
arr[0].length = 2;
|
||||||
|
arr[1].length = 2;
|
||||||
|
arr[0][0] = x;
|
||||||
|
arr[0][1] = x + 1;
|
||||||
|
arr[1][0] = x + 2;
|
||||||
|
arr[1][1] = x + 3;
|
||||||
|
emit E(arr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
compileAndRun(sourceCode);
|
||||||
|
u256 x(42);
|
||||||
|
callContractFunction("createEvent(uint256)", x);
|
||||||
|
BOOST_REQUIRE_EQUAL(m_logs.size(), 1);
|
||||||
|
BOOST_CHECK_EQUAL(m_logs[0].address, m_contractAddress);
|
||||||
|
BOOST_CHECK(m_logs[0].data == encodeArgs(0x20, 2, 0x40, 0xa0, 2, x, x + 1, 2, x + 2, x + 3));
|
||||||
|
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 1);
|
||||||
|
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("E(uint256[][])")));
|
||||||
|
}
|
||||||
|
|
||||||
BOOST_AUTO_TEST_CASE(event_indexed_string)
|
BOOST_AUTO_TEST_CASE(event_indexed_string)
|
||||||
{
|
{
|
||||||
char const* sourceCode = R"(
|
char const* sourceCode = R"(
|
||||||
|
@ -0,0 +1,7 @@
|
|||||||
|
pragma experimental ABIEncoderV2;
|
||||||
|
contract c {
|
||||||
|
event E(uint[] indexed);
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// Warning: (0-33): Experimental features are turned on. Do not use experimental features on live deployments.
|
||||||
|
// TypeError: (59-65): Indexed reference types cannot yet be used with ABIEncoderV2.
|
6
test/libsolidity/syntaxTests/events/event_array_v2.sol
Normal file
6
test/libsolidity/syntaxTests/events/event_array_v2.sol
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
pragma experimental ABIEncoderV2;
|
||||||
|
contract c {
|
||||||
|
event E(uint[]);
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// Warning: (0-33): Experimental features are turned on. Do not use experimental features on live deployments.
|
@ -0,0 +1,7 @@
|
|||||||
|
pragma experimental ABIEncoderV2;
|
||||||
|
contract c {
|
||||||
|
event E(uint[][] indexed);
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// Warning: (0-33): Experimental features are turned on. Do not use experimental features on live deployments.
|
||||||
|
// TypeError: (59-67): Indexed reference types cannot yet be used with ABIEncoderV2.
|
@ -0,0 +1,6 @@
|
|||||||
|
pragma experimental ABIEncoderV2;
|
||||||
|
contract c {
|
||||||
|
event E(uint[][]);
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// Warning: (0-33): Experimental features are turned on. Do not use experimental features on live deployments.
|
@ -0,0 +1,8 @@
|
|||||||
|
pragma experimental ABIEncoderV2;
|
||||||
|
contract c {
|
||||||
|
struct S { uint a ; }
|
||||||
|
event E(S indexed);
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// Warning: (0-33): Experimental features are turned on. Do not use experimental features on live deployments.
|
||||||
|
// TypeError: (85-86): Indexed reference types cannot yet be used with ABIEncoderV2.
|
7
test/libsolidity/syntaxTests/events/event_struct_v2.sol
Normal file
7
test/libsolidity/syntaxTests/events/event_struct_v2.sol
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
pragma experimental ABIEncoderV2;
|
||||||
|
contract c {
|
||||||
|
struct S { uint a ; }
|
||||||
|
event E(S);
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// Warning: (0-33): Experimental features are turned on. Do not use experimental features on live deployments.
|
Loading…
Reference in New Issue
Block a user