mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Packed Encoding: Disallow types in v2 that aren't allowed in v1
This commit is contained in:
parent
227addfcef
commit
fe2429de9f
@ -48,9 +48,9 @@ using namespace dev::solidity;
|
|||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
|
||||||
bool typeSupportedByOldABIEncoder(Type const& _type)
|
bool typeSupportedByOldABIEncoder(Type const& _type, bool _isLibraryCall)
|
||||||
{
|
{
|
||||||
if (_type.dataStoredIn(DataLocation::Storage))
|
if (_isLibraryCall && _type.dataStoredIn(DataLocation::Storage))
|
||||||
return true;
|
return true;
|
||||||
if (_type.category() == Type::Category::Struct)
|
if (_type.category() == Type::Category::Struct)
|
||||||
return false;
|
return false;
|
||||||
@ -58,7 +58,7 @@ bool typeSupportedByOldABIEncoder(Type const& _type)
|
|||||||
{
|
{
|
||||||
auto const& arrayType = dynamic_cast<ArrayType const&>(_type);
|
auto const& arrayType = dynamic_cast<ArrayType const&>(_type);
|
||||||
auto base = arrayType.baseType();
|
auto base = arrayType.baseType();
|
||||||
if (!typeSupportedByOldABIEncoder(*base) || (base->category() == Type::Category::Array && base->isDynamicallySized()))
|
if (!typeSupportedByOldABIEncoder(*base, _isLibraryCall) || (base->category() == Type::Category::Array && base->isDynamicallySized()))
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
@ -355,7 +355,7 @@ bool TypeChecker::visit(FunctionDefinition const& _function)
|
|||||||
if (
|
if (
|
||||||
_function.isPublic() &&
|
_function.isPublic() &&
|
||||||
!_function.sourceUnit().annotation().experimentalFeatures.count(ExperimentalFeature::ABIEncoderV2) &&
|
!_function.sourceUnit().annotation().experimentalFeatures.count(ExperimentalFeature::ABIEncoderV2) &&
|
||||||
!typeSupportedByOldABIEncoder(*type(var))
|
!typeSupportedByOldABIEncoder(*type(var), isLibraryFunction)
|
||||||
)
|
)
|
||||||
m_errorReporter.typeError(
|
m_errorReporter.typeError(
|
||||||
var.location(),
|
var.location(),
|
||||||
@ -475,7 +475,7 @@ bool TypeChecker::visit(VariableDeclaration const& _variable)
|
|||||||
{
|
{
|
||||||
vector<string> unsupportedTypes;
|
vector<string> unsupportedTypes;
|
||||||
for (auto const& param: getter.parameterTypes() + getter.returnParameterTypes())
|
for (auto const& param: getter.parameterTypes() + getter.returnParameterTypes())
|
||||||
if (!typeSupportedByOldABIEncoder(*param))
|
if (!typeSupportedByOldABIEncoder(*param, false /* isLibrary */))
|
||||||
unsupportedTypes.emplace_back(param->toString());
|
unsupportedTypes.emplace_back(param->toString());
|
||||||
if (!unsupportedTypes.empty())
|
if (!unsupportedTypes.empty())
|
||||||
m_errorReporter.typeError(_variable.location(),
|
m_errorReporter.typeError(_variable.location(),
|
||||||
@ -585,7 +585,7 @@ bool TypeChecker::visit(EventDefinition const& _eventDef)
|
|||||||
m_errorReporter.typeError(var->location(), "Internal or recursive type is not allowed as event parameter type.");
|
m_errorReporter.typeError(var->location(), "Internal or recursive type is not allowed as event parameter type.");
|
||||||
if (
|
if (
|
||||||
!_eventDef.sourceUnit().annotation().experimentalFeatures.count(ExperimentalFeature::ABIEncoderV2) &&
|
!_eventDef.sourceUnit().annotation().experimentalFeatures.count(ExperimentalFeature::ABIEncoderV2) &&
|
||||||
!typeSupportedByOldABIEncoder(*type(*var))
|
!typeSupportedByOldABIEncoder(*type(*var), false /* isLibrary */)
|
||||||
)
|
)
|
||||||
m_errorReporter.typeError(
|
m_errorReporter.typeError(
|
||||||
var->location(),
|
var->location(),
|
||||||
@ -1550,6 +1550,15 @@ void TypeChecker::typeCheckABIEncodeFunctions(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isPacked && !typeSupportedByOldABIEncoder(*argType, false /* isLibrary */))
|
||||||
|
{
|
||||||
|
m_errorReporter.typeError(
|
||||||
|
arguments[i]->location(),
|
||||||
|
"Type not supported in packed mode."
|
||||||
|
);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if (!argType->fullEncodingType(false, abiEncoderV2, !_functionType->padArguments()))
|
if (!argType->fullEncodingType(false, abiEncoderV2, !_functionType->padArguments()))
|
||||||
m_errorReporter.typeError(
|
m_errorReporter.typeError(
|
||||||
arguments[i]->location(),
|
arguments[i]->location(),
|
||||||
|
@ -13715,25 +13715,22 @@ BOOST_AUTO_TEST_CASE(abi_encodePackedV2_structs)
|
|||||||
s.d[0] = -7;
|
s.d[0] = -7;
|
||||||
s.d[1] = -8;
|
s.d[1] = -8;
|
||||||
}
|
}
|
||||||
function testStorage() public returns (bytes memory) {
|
function testStorage() public {
|
||||||
emit E(s);
|
emit E(s);
|
||||||
return abi.encodePacked(uint8(0x33), s, uint8(0x44));
|
|
||||||
}
|
}
|
||||||
function testMemory() public returns (bytes memory) {
|
function testMemory() public {
|
||||||
S memory m = s;
|
S memory m = s;
|
||||||
emit E(m);
|
emit E(m);
|
||||||
return abi.encodePacked(uint8(0x33), m, uint8(0x44));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)";
|
)";
|
||||||
compileAndRun(sourceCode, 0, "C");
|
compileAndRun(sourceCode, 0, "C");
|
||||||
bytes structEnc = encodeArgs(int(0x12), u256(-7), int(2), int(3), u256(-7), u256(-8));
|
bytes structEnc = encodeArgs(int(0x12), u256(-7), int(2), int(3), u256(-7), u256(-8));
|
||||||
string encoding = "\x33" + asString(structEnc) + "\x44";
|
ABI_CHECK(callContractFunction("testStorage()"), encodeArgs());
|
||||||
ABI_CHECK(callContractFunction("testStorage()"), encodeArgs(0x20, encoding.size(), encoding));
|
|
||||||
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 2);
|
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 2);
|
||||||
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("E((uint8,int16,uint8[2],int16[]))")));
|
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("E((uint8,int16,uint8[2],int16[]))")));
|
||||||
BOOST_CHECK_EQUAL(m_logs[0].topics[1], dev::keccak256(asString(structEnc)));
|
BOOST_CHECK_EQUAL(m_logs[0].topics[1], dev::keccak256(asString(structEnc)));
|
||||||
ABI_CHECK(callContractFunction("testMemory()"), encodeArgs(0x20, encoding.size(), encoding));
|
ABI_CHECK(callContractFunction("testMemory()"), encodeArgs());
|
||||||
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 2);
|
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 2);
|
||||||
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("E((uint8,int16,uint8[2],int16[]))")));
|
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("E((uint8,int16,uint8[2],int16[]))")));
|
||||||
BOOST_CHECK_EQUAL(m_logs[0].topics[1], dev::keccak256(asString(structEnc)));
|
BOOST_CHECK_EQUAL(m_logs[0].topics[1], dev::keccak256(asString(structEnc)));
|
||||||
@ -13749,7 +13746,7 @@ BOOST_AUTO_TEST_CASE(abi_encodePackedV2_nestedArray)
|
|||||||
int16 b;
|
int16 b;
|
||||||
}
|
}
|
||||||
event E(S[2][][3] indexed);
|
event E(S[2][][3] indexed);
|
||||||
function testNestedArrays() public returns (bytes memory) {
|
function testNestedArrays() public {
|
||||||
S[2][][3] memory x;
|
S[2][][3] memory x;
|
||||||
x[1] = new S[2][](2);
|
x[1] = new S[2][](2);
|
||||||
x[1][0][0].a = 1;
|
x[1][0][0].a = 1;
|
||||||
@ -13757,14 +13754,12 @@ BOOST_AUTO_TEST_CASE(abi_encodePackedV2_nestedArray)
|
|||||||
x[1][0][1].a = 3;
|
x[1][0][1].a = 3;
|
||||||
x[1][1][1].b = 4;
|
x[1][1][1].b = 4;
|
||||||
emit E(x);
|
emit E(x);
|
||||||
return abi.encodePacked(uint8(0x33), x, uint8(0x44));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)";
|
)";
|
||||||
compileAndRun(sourceCode, 0, "C");
|
compileAndRun(sourceCode, 0, "C");
|
||||||
bytes structEnc = encodeArgs(1, 2, 3, 0, 0, 0, 0, 4);
|
bytes structEnc = encodeArgs(1, 2, 3, 0, 0, 0, 0, 4);
|
||||||
string encoding = "\x33" + asString(structEnc) + "\x44";
|
ABI_CHECK(callContractFunction("testNestedArrays()"), encodeArgs());
|
||||||
ABI_CHECK(callContractFunction("testNestedArrays()"), encodeArgs(0x20, encoding.size(), encoding));
|
|
||||||
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 2);
|
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 2);
|
||||||
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("E((uint8,int16)[2][][3])")));
|
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("E((uint8,int16)[2][][3])")));
|
||||||
BOOST_CHECK_EQUAL(m_logs[0].topics[1], dev::keccak256(asString(structEnc)));
|
BOOST_CHECK_EQUAL(m_logs[0].topics[1], dev::keccak256(asString(structEnc)));
|
||||||
@ -13782,27 +13777,22 @@ BOOST_AUTO_TEST_CASE(abi_encodePackedV2_arrayOfStrings)
|
|||||||
x[0] = "abc";
|
x[0] = "abc";
|
||||||
x[1] = "0123456789012345678901234567890123456789";
|
x[1] = "0123456789012345678901234567890123456789";
|
||||||
}
|
}
|
||||||
function testStorage() public returns (bytes memory) {
|
function testStorage() public {
|
||||||
emit E(x);
|
emit E(x);
|
||||||
return abi.encodePacked(uint8(0x33), x, uint8(0x44));
|
|
||||||
}
|
}
|
||||||
function testMemory() public returns (bytes memory) {
|
function testMemory() public {
|
||||||
string[] memory y = x;
|
string[] memory y = x;
|
||||||
emit E(y);
|
emit E(y);
|
||||||
return abi.encodePacked(uint8(0x33), y, uint8(0x44));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)";
|
)";
|
||||||
compileAndRun(sourceCode, 0, "C");
|
compileAndRun(sourceCode, 0, "C");
|
||||||
bytes arrayEncoding = encodeArgs("abc", "0123456789012345678901234567890123456789");
|
bytes arrayEncoding = encodeArgs("abc", "0123456789012345678901234567890123456789");
|
||||||
// This pads to multiple of 32 bytes
|
ABI_CHECK(callContractFunction("testStorage()"), encodeArgs());
|
||||||
string encoding = "\x33" + asString(arrayEncoding) + "\x44";
|
|
||||||
BOOST_CHECK_EQUAL(encoding.size(), 2 + 32 * 3);
|
|
||||||
ABI_CHECK(callContractFunction("testStorage()"), encodeArgs(0x20, encoding.size(), encoding));
|
|
||||||
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 2);
|
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 2);
|
||||||
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("E(string[])")));
|
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("E(string[])")));
|
||||||
BOOST_CHECK_EQUAL(m_logs[0].topics[1], dev::keccak256(asString(arrayEncoding)));
|
BOOST_CHECK_EQUAL(m_logs[0].topics[1], dev::keccak256(asString(arrayEncoding)));
|
||||||
ABI_CHECK(callContractFunction("testMemory()"), encodeArgs(0x20, encoding.size(), encoding));
|
ABI_CHECK(callContractFunction("testMemory()"), encodeArgs());
|
||||||
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 2);
|
BOOST_REQUIRE_EQUAL(m_logs[0].topics.size(), 2);
|
||||||
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("E(string[])")));
|
BOOST_CHECK_EQUAL(m_logs[0].topics[0], dev::keccak256(string("E(string[])")));
|
||||||
BOOST_CHECK_EQUAL(m_logs[0].topics[1], dev::keccak256(asString(arrayEncoding)));
|
BOOST_CHECK_EQUAL(m_logs[0].topics[1], dev::keccak256(asString(arrayEncoding)));
|
||||||
|
@ -12,3 +12,5 @@ contract C {
|
|||||||
}
|
}
|
||||||
// ----
|
// ----
|
||||||
// Warning: (0-33): Experimental features are turned on. Do not use experimental features on live deployments.
|
// Warning: (0-33): Experimental features are turned on. Do not use experimental features on live deployments.
|
||||||
|
// TypeError: (191-192): Type not supported in packed mode.
|
||||||
|
// TypeError: (194-195): Type not supported in packed mode.
|
||||||
|
@ -13,5 +13,5 @@ contract C {
|
|||||||
// ----
|
// ----
|
||||||
// TypeError: (131-132): This type cannot be encoded.
|
// TypeError: (131-132): This type cannot be encoded.
|
||||||
// TypeError: (134-135): This type cannot be encoded.
|
// TypeError: (134-135): This type cannot be encoded.
|
||||||
// TypeError: (200-201): This type cannot be encoded.
|
// TypeError: (200-201): Type not supported in packed mode.
|
||||||
// TypeError: (203-204): This type cannot be encoded.
|
// TypeError: (203-204): Type not supported in packed mode.
|
||||||
|
@ -5,6 +5,10 @@ contract C {
|
|||||||
S s;
|
S s;
|
||||||
struct T { uint y; }
|
struct T { uint y; }
|
||||||
T t;
|
T t;
|
||||||
|
function e() public view {
|
||||||
|
S memory st;
|
||||||
|
abi.encodePacked(st);
|
||||||
|
}
|
||||||
function f() public view {
|
function f() public view {
|
||||||
abi.encode(s, t);
|
abi.encode(s, t);
|
||||||
}
|
}
|
||||||
@ -14,3 +18,6 @@ contract C {
|
|||||||
}
|
}
|
||||||
// ----
|
// ----
|
||||||
// Warning: (0-33): Experimental features are turned on. Do not use experimental features on live deployments.
|
// Warning: (0-33): Experimental features are turned on. Do not use experimental features on live deployments.
|
||||||
|
// TypeError: (193-195): Type not supported in packed mode.
|
||||||
|
// TypeError: (323-324): Type not supported in packed mode.
|
||||||
|
// TypeError: (326-327): Type not supported in packed mode.
|
||||||
|
@ -6,4 +6,4 @@ contract C {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ----
|
// ----
|
||||||
// TypeError: (116-117): This type cannot be encoded.
|
// TypeError: (116-117): Type not supported in packed mode.
|
||||||
|
@ -0,0 +1,13 @@
|
|||||||
|
contract C {
|
||||||
|
string[] s;
|
||||||
|
function f() public pure {
|
||||||
|
string[] memory m;
|
||||||
|
abi.encodePacked(m);
|
||||||
|
}
|
||||||
|
function g() public pure {
|
||||||
|
abi.encodePacked(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// ----
|
||||||
|
// TypeError: (112-113): Type not supported in packed mode.
|
||||||
|
// TypeError: (178-179): Type not supported in packed mode.
|
@ -9,5 +9,5 @@ contract C {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// ----
|
// ----
|
||||||
// TypeError: (156-157): This type cannot be encoded.
|
// TypeError: (156-157): Type not supported in packed mode.
|
||||||
// TypeError: (159-160): This type cannot be encoded.
|
// TypeError: (159-160): Type not supported in packed mode.
|
||||||
|
Loading…
Reference in New Issue
Block a user