mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Add abi.decode(bytes data, (...))
This commit is contained in:
@@ -13195,6 +13195,203 @@ BOOST_AUTO_TEST_CASE(senders_balance)
|
||||
BOOST_CHECK(callContractFunction("f()") == encodeArgs(u256(27)));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(abi_decode_trivial)
|
||||
{
|
||||
char const* sourceCode = R"(
|
||||
contract C {
|
||||
function f(bytes memory data) public pure returns (uint) {
|
||||
return abi.decode(data, (uint));
|
||||
}
|
||||
}
|
||||
)";
|
||||
compileAndRun(sourceCode);
|
||||
ABI_CHECK(callContractFunction("f(bytes)", 0x20, 0x20, 33), encodeArgs(u256(33)));
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(abi_encode_decode_simple)
|
||||
{
|
||||
char const* sourceCode = R"XX(
|
||||
contract C {
|
||||
function f() public pure returns (uint, bytes memory) {
|
||||
bytes memory arg = "abcdefg";
|
||||
return abi.decode(abi.encode(uint(33), arg), (uint, bytes));
|
||||
}
|
||||
}
|
||||
)XX";
|
||||
compileAndRun(sourceCode);
|
||||
ABI_CHECK(
|
||||
callContractFunction("f()"),
|
||||
encodeArgs(33, 0x40, 7, "abcdefg")
|
||||
);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(abi_decode_simple)
|
||||
{
|
||||
char const* sourceCode = R"(
|
||||
contract C {
|
||||
function f(bytes memory data) public pure returns (uint, bytes memory) {
|
||||
return abi.decode(data, (uint, bytes));
|
||||
}
|
||||
}
|
||||
)";
|
||||
compileAndRun(sourceCode);
|
||||
ABI_CHECK(
|
||||
callContractFunction("f(bytes)", 0x20, 0x20 * 4, 33, 0x40, 7, "abcdefg"),
|
||||
encodeArgs(33, 0x40, 7, "abcdefg")
|
||||
);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(abi_decode_v2)
|
||||
{
|
||||
char const* sourceCode = R"(
|
||||
pragma experimental ABIEncoderV2;
|
||||
contract C {
|
||||
struct S { uint a; uint[] b; }
|
||||
function f() public pure returns (S memory) {
|
||||
S memory s;
|
||||
s.a = 8;
|
||||
s.b = new uint[](3);
|
||||
s.b[0] = 9;
|
||||
s.b[1] = 10;
|
||||
s.b[2] = 11;
|
||||
return abi.decode(abi.encode(s), (S));
|
||||
}
|
||||
}
|
||||
)";
|
||||
compileAndRun(sourceCode);
|
||||
ABI_CHECK(
|
||||
callContractFunction("f()"),
|
||||
encodeArgs(0x20, 8, 0x40, 3, 9, 10, 11)
|
||||
);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(abi_decode_simple_storage)
|
||||
{
|
||||
char const* sourceCode = R"(
|
||||
contract C {
|
||||
bytes data;
|
||||
function f(bytes memory _data) public returns (uint, bytes memory) {
|
||||
data = _data;
|
||||
return abi.decode(data, (uint, bytes));
|
||||
}
|
||||
}
|
||||
)";
|
||||
compileAndRun(sourceCode);
|
||||
ABI_CHECK(
|
||||
callContractFunction("f(bytes)", 0x20, 0x20 * 4, 33, 0x40, 7, "abcdefg"),
|
||||
encodeArgs(33, 0x40, 7, "abcdefg")
|
||||
);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(abi_decode_v2_storage)
|
||||
{
|
||||
char const* sourceCode = R"(
|
||||
pragma experimental ABIEncoderV2;
|
||||
contract C {
|
||||
bytes data;
|
||||
struct S { uint a; uint[] b; }
|
||||
function f() public returns (S memory) {
|
||||
S memory s;
|
||||
s.a = 8;
|
||||
s.b = new uint[](3);
|
||||
s.b[0] = 9;
|
||||
s.b[1] = 10;
|
||||
s.b[2] = 11;
|
||||
data = abi.encode(s);
|
||||
return abi.decode(data, (S));
|
||||
}
|
||||
}
|
||||
)";
|
||||
compileAndRun(sourceCode);
|
||||
ABI_CHECK(
|
||||
callContractFunction("f()"),
|
||||
encodeArgs(0x20, 8, 0x40, 3, 9, 10, 11)
|
||||
);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(abi_decode_calldata)
|
||||
{
|
||||
char const* sourceCode = R"(
|
||||
contract C {
|
||||
function f(bytes calldata data) external pure returns (uint, bytes memory r) {
|
||||
return abi.decode(data, (uint, bytes));
|
||||
}
|
||||
}
|
||||
)";
|
||||
compileAndRun(sourceCode);
|
||||
ABI_CHECK(
|
||||
callContractFunction("f(bytes)", 0x20, 0x20 * 4, 33, 0x40, 7, "abcdefg"),
|
||||
encodeArgs(33, 0x40, 7, "abcdefg")
|
||||
);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(abi_decode_v2_calldata)
|
||||
{
|
||||
char const* sourceCode = R"(
|
||||
pragma experimental ABIEncoderV2;
|
||||
contract C {
|
||||
struct S { uint a; uint[] b; }
|
||||
function f(bytes calldata data) external pure returns (S memory) {
|
||||
return abi.decode(data, (S));
|
||||
}
|
||||
}
|
||||
)";
|
||||
compileAndRun(sourceCode);
|
||||
ABI_CHECK(
|
||||
callContractFunction("f(bytes)", 0x20, 0x20 * 7, 0x20, 33, 0x40, 3, 10, 11, 12),
|
||||
encodeArgs(0x20, 33, 0x40, 3, 10, 11, 12)
|
||||
);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(abi_decode_static_array)
|
||||
{
|
||||
char const* sourceCode = R"(
|
||||
contract C {
|
||||
function f(bytes calldata data) external pure returns (uint[2][3] memory) {
|
||||
return abi.decode(data, (uint[2][3]));
|
||||
}
|
||||
}
|
||||
)";
|
||||
compileAndRun(sourceCode);
|
||||
ABI_CHECK(
|
||||
callContractFunction("f(bytes)", 0x20, 6 * 0x20, 1, 2, 3, 4, 5, 6),
|
||||
encodeArgs(1, 2, 3, 4, 5, 6)
|
||||
);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(abi_decode_static_array_v2)
|
||||
{
|
||||
char const* sourceCode = R"(
|
||||
pragma experimental ABIEncoderV2;
|
||||
contract C {
|
||||
function f(bytes calldata data) external pure returns (uint[2][3] memory) {
|
||||
return abi.decode(data, (uint[2][3]));
|
||||
}
|
||||
}
|
||||
)";
|
||||
compileAndRun(sourceCode);
|
||||
ABI_CHECK(
|
||||
callContractFunction("f(bytes)", 0x20, 6 * 0x20, 1, 2, 3, 4, 5, 6),
|
||||
encodeArgs(1, 2, 3, 4, 5, 6)
|
||||
);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(abi_decode_dynamic_array)
|
||||
{
|
||||
char const* sourceCode = R"(
|
||||
contract C {
|
||||
function f(bytes calldata data) external pure returns (uint[] memory) {
|
||||
return abi.decode(data, (uint[]));
|
||||
}
|
||||
}
|
||||
)";
|
||||
compileAndRun(sourceCode);
|
||||
ABI_CHECK(
|
||||
callContractFunction("f(bytes)", 0x20, 6 * 0x20, 0x20, 4, 3, 4, 5, 6),
|
||||
encodeArgs(0x20, 4, 3, 4, 5, 6)
|
||||
);
|
||||
}
|
||||
|
||||
BOOST_AUTO_TEST_CASE(write_storage_external)
|
||||
{
|
||||
char const* sourceCode = R"(
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
// This restriction might be lifted in the future
|
||||
contract C {
|
||||
function f() public pure {
|
||||
abi.decode("abc", (bytes calldata));
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// ParserError: (121-129): Expected ',' but got 'calldata'
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
contract C {
|
||||
function f() public pure {
|
||||
abi.decode();
|
||||
abi.decode(msg.data);
|
||||
abi.decode(msg.data, uint, uint);
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// TypeError: (46-58): This function takes two arguments, but 0 were provided.
|
||||
// TypeError: (64-84): This function takes two arguments, but 1 were provided.
|
||||
// TypeError: (90-122): This function takes two arguments, but 3 were provided.
|
||||
// TypeError: (111-115): The second argument to "abi.decode" has to be a tuple of types.
|
||||
@@ -0,0 +1,7 @@
|
||||
contract C {
|
||||
function f() public pure {
|
||||
abi.decode("abc", (bytes memory, uint[][2] memory));
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// ParserError: (71-77): Expected ',' but got 'memory'
|
||||
@@ -0,0 +1,10 @@
|
||||
pragma experimental "ABIEncoderV2";
|
||||
|
||||
contract C {
|
||||
struct S { uint x; uint[] b; }
|
||||
function f() public pure returns (S memory, bytes memory, uint[][2] memory) {
|
||||
return abi.decode("abc", (S, bytes, uint[][2]));
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// Warning: (0-35): Experimental features are turned on. Do not use experimental features on live deployments.
|
||||
@@ -0,0 +1,11 @@
|
||||
contract C {
|
||||
function f() public pure {
|
||||
abi.decode("abc", uint);
|
||||
abi.decode("abc", this);
|
||||
abi.decode("abc", f());
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// TypeError: (64-68): The second argument to "abi.decode" has to be a tuple of types.
|
||||
// TypeError: (93-97): The second argument to "abi.decode" has to be a tuple of types.
|
||||
// TypeError: (122-125): The second argument to "abi.decode" has to be a tuple of types.
|
||||
@@ -0,0 +1,5 @@
|
||||
contract C {
|
||||
function f() public pure returns (uint, bytes32, C) {
|
||||
return abi.decode("abc", (uint, bytes32, C));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
contract C {
|
||||
function f() public pure returns (uint) {
|
||||
return abi.decode("abc", (uint));
|
||||
}
|
||||
}
|
||||
// ----
|
||||
@@ -0,0 +1,8 @@
|
||||
// This restriction might be lifted in the future
|
||||
contract C {
|
||||
function f() {
|
||||
abi.decode("abc", (bytes storage));
|
||||
}
|
||||
}
|
||||
// ----
|
||||
// ParserError: (109-116): Expected ',' but got 'storage'
|
||||
Reference in New Issue
Block a user