diff --git a/Changelog.md b/Changelog.md index 98a1dc275..5b276b114 100644 --- a/Changelog.md +++ b/Changelog.md @@ -11,6 +11,7 @@ Compiler Features: Bugfixes: * Type Checker: Fix internal compiler error when calling `.push()` for a storage array with a nested mapping. + * Type Checker: Add missing checks for calls using types incompatible with ABIEncoderV1 in modules where ABIEncoderV2 is not enabled. ### 0.7.2 (2020-09-28) diff --git a/libsolidity/analysis/TypeChecker.cpp b/libsolidity/analysis/TypeChecker.cpp index eb2e81743..d8eef6119 100644 --- a/libsolidity/analysis/TypeChecker.cpp +++ b/libsolidity/analysis/TypeChecker.cpp @@ -2178,6 +2178,52 @@ void TypeChecker::typeCheckFunctionGeneralChecks( m_errorReporter.typeError(errorId, paramArgMap[i]->location(), description); } } + + TypePointers const& returnParameterTypes = _functionType->returnParameterTypes(); + bool isLibraryCall = (_functionType->kind() == FunctionType::Kind::DelegateCall); + bool callRequiresABIEncoding = + // ABIEncode/ABIDecode calls not included because they should have been already validated + // at this point and they have variadic arguments so they need special handling. + _functionType->kind() == FunctionType::Kind::DelegateCall || + _functionType->kind() == FunctionType::Kind::External || + _functionType->kind() == FunctionType::Kind::Creation || + _functionType->kind() == FunctionType::Kind::Event; + + if (callRequiresABIEncoding && !experimentalFeatureActive(ExperimentalFeature::ABIEncoderV2)) + { + solAssert(!isVariadic, ""); + solAssert(parameterTypes.size() == arguments.size(), ""); + solAssert(!_functionType->isBareCall(), ""); + solAssert(*_functionCall.annotation().kind == FunctionCallKind::FunctionCall, ""); + + for (size_t i = 0; i < parameterTypes.size(); ++i) + { + solAssert(parameterTypes[i], ""); + + if (!typeSupportedByOldABIEncoder(*parameterTypes[i], isLibraryCall)) + m_errorReporter.typeError( + 2443_error, + paramArgMap[i]->location(), + "The type of this parameter, " + parameterTypes[i]->toString(true) + ", " + "is only supported in ABIEncoderV2. " + "Use \"pragma experimental ABIEncoderV2;\" to enable the feature." + ); + } + + for (size_t i = 0; i < returnParameterTypes.size(); ++i) + { + solAssert(returnParameterTypes[i], ""); + + if (!typeSupportedByOldABIEncoder(*returnParameterTypes[i], isLibraryCall)) + m_errorReporter.typeError( + 2428_error, + _functionCall.location(), + "The type of return parameter " + toString(i + 1) + ", " + returnParameterTypes[i]->toString(true) + ", " + "is only supported in ABIEncoderV2. " + "Use \"pragma experimental ABIEncoderV2;\" to enable the feature." + ); + } + } } bool TypeChecker::visit(FunctionCall const& _functionCall) diff --git a/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v1_library_function_accepting_storage_struct.sol b/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v1_library_function_accepting_storage_struct.sol new file mode 100644 index 000000000..63f7af68a --- /dev/null +++ b/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v1_library_function_accepting_storage_struct.sol @@ -0,0 +1,21 @@ +==== Source: A ==== +pragma experimental ABIEncoderV2; + +library L { + struct Item { + uint x; + } + + function set(Item storage _item) external view {} +} +==== Source: B ==== +import "A"; + +contract Test { + L.Item item; + + function foo() public view { + L.set(item); + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v2_constructor_accepting_struct.sol b/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v2_constructor_accepting_struct.sol new file mode 100644 index 000000000..17dfee2c3 --- /dev/null +++ b/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v2_constructor_accepting_struct.sol @@ -0,0 +1,20 @@ +==== Source: A ==== +pragma experimental ABIEncoderV2; + +contract C { + struct Item { + uint x; + } + + constructor(Item memory _item) {} +} +==== Source: B ==== +import "A"; + +contract Test { + function foo() public { + new C(C.Item(5)); + } +} +// ---- +// TypeError 2443: (B:71-80): The type of this parameter, struct C.Item, is only supported in ABIEncoderV2. Use "pragma experimental ABIEncoderV2;" to enable the feature. diff --git a/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v2_contract_function_accepting_struct_via_named_argument.sol b/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v2_contract_function_accepting_struct_via_named_argument.sol new file mode 100644 index 000000000..bf8663071 --- /dev/null +++ b/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v2_contract_function_accepting_struct_via_named_argument.sol @@ -0,0 +1,20 @@ +==== Source: A ==== +pragma experimental ABIEncoderV2; + +contract C { + struct Item { + uint x; + } + + function set(uint _x, string memory _y, Item memory _item, bool _z) external view {} +} +==== Source: B ==== +import "A"; + +contract Test { + function foo() public view { + C(0x00).set({_item: C.Item(50), _z: false, _y: "abc", _x: 30}); + } +} +// ---- +// TypeError 2443: (B:90-100): The type of this parameter, struct C.Item, is only supported in ABIEncoderV2. Use "pragma experimental ABIEncoderV2;" to enable the feature. diff --git a/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v2_contract_function_pointer_accepting_struct.sol b/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v2_contract_function_pointer_accepting_struct.sol new file mode 100644 index 000000000..db6180ff6 --- /dev/null +++ b/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v2_contract_function_pointer_accepting_struct.sol @@ -0,0 +1,22 @@ +==== Source: A ==== +pragma experimental ABIEncoderV2; + +contract C { + struct Item { + uint x; + } + + function get(Item memory _item) external {} +} +==== Source: B ==== +import "A"; + +contract Test { + function foo() public { + C c = new C(); + function(C.Item memory) external ptr = c.get; + ptr(C.Item(5)); + } +} +// ---- +// TypeError 2443: (B:146-155): The type of this parameter, struct C.Item, is only supported in ABIEncoderV2. Use "pragma experimental ABIEncoderV2;" to enable the feature. diff --git a/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v2_contract_function_returning_dynamic_string_array.sol b/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v2_contract_function_returning_dynamic_string_array.sol new file mode 100644 index 000000000..11cdbaefb --- /dev/null +++ b/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v2_contract_function_returning_dynamic_string_array.sol @@ -0,0 +1,16 @@ +==== Source: A ==== +pragma experimental ABIEncoderV2; + +contract C { + function f() external view returns (string[] memory) {} +} +==== Source: B ==== +import "A"; + +contract D { + function g() public view { + C(0x00).f(); + } +} +// ---- +// TypeError 2428: (B:65-76): The type of return parameter 1, string[], is only supported in ABIEncoderV2. Use "pragma experimental ABIEncoderV2;" to enable the feature. diff --git a/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v2_contract_function_returning_struct.sol b/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v2_contract_function_returning_struct.sol new file mode 100644 index 000000000..123073cb0 --- /dev/null +++ b/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v2_contract_function_returning_struct.sol @@ -0,0 +1,20 @@ +==== Source: A ==== +pragma experimental ABIEncoderV2; + +contract C { + struct Item { + uint x; + } + + function get() external view returns(Item memory) {} +} +==== Source: B ==== +import "A"; + +contract Test { + function foo() public view { + C(0x00).get(); + } +} +// ---- +// TypeError 2428: (B:70-83): The type of return parameter 1, struct C.Item, is only supported in ABIEncoderV2. Use "pragma experimental ABIEncoderV2;" to enable the feature. diff --git a/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v2_contract_function_returning_struct_with_dynamic_array.sol b/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v2_contract_function_returning_struct_with_dynamic_array.sol new file mode 100644 index 000000000..35faaaf15 --- /dev/null +++ b/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v2_contract_function_returning_struct_with_dynamic_array.sol @@ -0,0 +1,20 @@ +==== Source: A ==== +pragma experimental ABIEncoderV2; + +contract C { + struct Item { + uint[] y; + } + + function get() external view returns(Item memory) {} +} +==== Source: B ==== +import "A"; + +contract Test { + function foo() public view { + C(0x00).get(); + } +} +// ---- +// TypeError 2428: (B:70-83): The type of return parameter 1, struct C.Item, is only supported in ABIEncoderV2. Use "pragma experimental ABIEncoderV2;" to enable the feature. diff --git a/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v2_event_accepting_struct.sol b/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v2_event_accepting_struct.sol new file mode 100644 index 000000000..4a02a2fa1 --- /dev/null +++ b/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v2_event_accepting_struct.sol @@ -0,0 +1,19 @@ +==== Source: A ==== +pragma experimental ABIEncoderV2; + +library L { + struct Item { + uint x; + } + event E(Item _value); +} +==== Source: B ==== +import "A"; + +contract Test { + function foo() public { + emit L.E(L.Item(42)); + } +} +// ---- +// TypeError 2443: (B:74-84): The type of this parameter, struct L.Item, is only supported in ABIEncoderV2. Use "pragma experimental ABIEncoderV2;" to enable the feature. diff --git a/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v2_library_function_accepting_storage_struct.sol b/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v2_library_function_accepting_storage_struct.sol new file mode 100644 index 000000000..46b350118 --- /dev/null +++ b/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v2_library_function_accepting_storage_struct.sol @@ -0,0 +1,21 @@ +==== Source: A ==== +pragma experimental ABIEncoderV2; + +library L { + struct Item { + uint x; + } + + function get(Item storage _item) external view {} +} +==== Source: B ==== +import "A"; + +contract Test { + L.Item item; + + function foo() public view { + L.get(item); + } +} +// ---- diff --git a/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v2_library_function_returning_struct.sol b/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v2_library_function_returning_struct.sol new file mode 100644 index 000000000..983ce189f --- /dev/null +++ b/test/libsolidity/syntaxTests/abiEncoder/v1_call_to_v2_library_function_returning_struct.sol @@ -0,0 +1,20 @@ +==== Source: A ==== +pragma experimental ABIEncoderV2; + +library L { + struct Item { + uint x; + } + + function get() external view returns(Item memory) {} +} +==== Source: B ==== +import "A"; + +contract Test { + function foo() public view { + L.get(); + } +} +// ---- +// TypeError 2428: (B:70-77): The type of return parameter 1, struct L.Item, is only supported in ABIEncoderV2. Use "pragma experimental ABIEncoderV2;" to enable the feature. diff --git a/test/libsolidity/syntaxTests/abiEncoder/v2_accessing_returned_dynamic_array_with_returndata_support.sol b/test/libsolidity/syntaxTests/abiEncoder/v2_accessing_returned_dynamic_array_with_returndata_support.sol new file mode 100644 index 000000000..27f55764e --- /dev/null +++ b/test/libsolidity/syntaxTests/abiEncoder/v2_accessing_returned_dynamic_array_with_returndata_support.sol @@ -0,0 +1,13 @@ +pragma experimental ABIEncoderV2; + +contract C { + function get() public view returns (uint[][] memory) {} + + function test() public view returns (bool) { + uint[][] memory x = this.get(); + } +} +// ==== +// EVMVersion: >=byzantium +// ---- +// Warning 2072: (166-183): Unused local variable. diff --git a/test/libsolidity/syntaxTests/abiEncoder/v2_accessing_returned_dynamic_array_without_returndata_support.sol b/test/libsolidity/syntaxTests/abiEncoder/v2_accessing_returned_dynamic_array_without_returndata_support.sol new file mode 100644 index 000000000..eb1b9bb9d --- /dev/null +++ b/test/libsolidity/syntaxTests/abiEncoder/v2_accessing_returned_dynamic_array_without_returndata_support.sol @@ -0,0 +1,13 @@ +pragma experimental ABIEncoderV2; + +contract C { + function get() public view returns (uint[][] memory) {} + + function test() public view returns (bool) { + uint[][] memory x = this.get(); + } +} +// ==== +// EVMVersion: