Tests, Docs and Changelog

This commit is contained in:
Harikrishnan Mulackal
2020-06-30 16:53:41 +05:30
parent d41eaeba56
commit eeadb5a6b5
48 changed files with 215 additions and 124 deletions
+2
View File
@@ -8,6 +8,8 @@ Breaking changes:
* Parser: NatSpec comments on variables are only allowed for public state variables.
* Type Checker: Disallow shifts by signed types.
* Type Checker: Exponentiation and shifts of literals by non-literals will always use ``uint256`` or ``int256`` as a type.
* Type Checker: Disallow structs and arrays in memory or calldata if they contain nested mappings.
* Type Checker: Disallow assignments to state variables that contain nested mappings.
Language Features:
* Yul: Disallow EVM instruction `pc()`.
+1
View File
@@ -26,6 +26,7 @@ are allowed for state variables, as storage reference types
in functions, or as parameters for library functions.
They cannot be used as parameters or return parameters
of contract functions that are publicly visible.
These restrictions are also true for arrays and structs that contain mappings.
You can mark state variables of mapping type as ``public`` and Solidity creates a
:ref:`getter <visibility-and-getters>` for you. The ``_KeyType`` becomes a parameter for the getter.
+5 -6
View File
@@ -488,12 +488,11 @@ shown in the following example:
function newCampaign(address payable beneficiary, uint goal) public returns (uint campaignID) {
campaignID = numCampaigns++; // campaignID is return variable
// Creates new struct in memory and copies it to storage.
// We leave out the mapping type, because it is not valid in memory.
// If structs are copied (even from storage to storage),
// types that are not valid outside of storage (ex. mappings and array of mappings)
// are always omitted, because they cannot be enumerated.
campaigns[campaignID] = Campaign(beneficiary, goal, 0, 0);
// We cannot use "campaigns[campaignID] = Campaign(beneficiary, goal, 0, 0)"
// because the RHS creates a memory-struct "Campaign" that contains a mapping.
Campaign storage c = campaigns[campaignID];
c.beneficiary = beneficiary;
c.fundingGoal = goal;
}
function contribute(uint campaignID) public payable {
+5 -6
View File
@@ -3465,12 +3465,12 @@ BOOST_AUTO_TEST_CASE(array_copy_calldata_storage)
ABI_CHECK(callContractFunction("retrieve()"), encodeArgs(9, 28, 9, 28, 4, 3, 32));
}
BOOST_AUTO_TEST_CASE(array_copy_including_mapping)
BOOST_AUTO_TEST_CASE(array_copy_including_array)
{
char const* sourceCode = R"(
contract c {
mapping(uint=>uint)[90][] large;
mapping(uint=>uint)[3][] small;
uint[3][90][] large;
uint[3][3][] small;
function test() public returns (uint r) {
for (uint i = 0; i < 7; i++) {
large.push();
@@ -3505,9 +3505,8 @@ BOOST_AUTO_TEST_CASE(array_copy_including_mapping)
}
)";
compileAndRun(sourceCode);
ABI_CHECK(callContractFunction("test()"), encodeArgs(0x02000200));
// storage is not empty because we cannot delete the mappings
BOOST_CHECK(!storageEmpty(m_contractAddress));
ABI_CHECK(callContractFunction("test()"), encodeArgs(0x02000202));
BOOST_CHECK(storageEmpty(m_contractAddress));
ABI_CHECK(callContractFunction("clear()"), encodeArgs(0, 0));
BOOST_CHECK(storageEmpty(m_contractAddress));
}
@@ -1,50 +0,0 @@
contract Test {
struct A {
mapping(uint=>uint) m;
}
struct B {
mapping(uint=>uint) m;
uint x;
}
struct C {
mapping(uint=>uint)[] ma;
}
struct D {
A[] a;
}
A storageA;
B storageB;
C storageC;
D storageD;
constructor() public {
storageA.m[1] = 2;
storageB.m[3] = 4;
storageB.x = 5;
for (uint i = 0; i < 6; i++)
storageC.ma.push();
for (uint i = 0; i < 7; i++)
storageD.a.push();
}
function run() public returns (uint, uint, uint, uint, uint, uint) {
A memory memoryA = A();
B memory memoryB = B(42);
C memory memoryC = C();
D memory memoryD1 = D(new A[](999));
D memory memoryD2 = storageD;
storageA = memoryA;
storageB = memoryB;
storageC = memoryC;
// the following line does not compile because unimplemented
// storageD = memoryD1;
return (
storageA.m[1],
storageB.x,
memoryB.x,
storageC.ma.length,
memoryD1.a.length,
memoryD2.a.length
);
}
}
// ----
// run() -> 2, 42, 42, 6, 999, 7
@@ -1,24 +0,0 @@
contract Test {
struct S {
uint8 a;
mapping(uint256 => uint256) b;
uint8 c;
}
S s;
function f() public returns (uint256) {
S memory x;
if (x.a != 0 || x.c != 0) return 1;
x.a = 4;
x.c = 5;
s = x;
if (s.a != 4 || s.c != 5) return 2;
x = S(2, 3);
if (x.a != 2 || x.c != 3) return 3;
x = s;
if (s.a != 4 || s.c != 5) return 4;
}
}
// ----
// f() -> 0
@@ -5,7 +5,6 @@ contract c {
}
struct Struct {
uint256 a;
mapping(uint256 => Struct) b;
Nested nested;
uint256 c;
}
@@ -0,0 +1,8 @@
pragma experimental ABIEncoderV2;
contract Test {
function f(mapping(uint => uint)[] memory x) public pure {}
}
// ----
// TypeError 4103: (66-98): Types containing (nested) mappings can only be parameters or return variables of internal or library functions.
// TypeError 4061: (66-98): Type mapping(uint256 => uint256)[] is only valid in storage because it contains a (nested) mapping.
@@ -0,0 +1,6 @@
pragma experimental ABIEncoderV2;
library L {
function f(mapping(uint => uint)[2] memory a) external pure returns (mapping(uint => uint)[2] memory) {}
}
// ----
// TypeError 4061: (61-94): Type mapping(uint256 => uint256)[2] is only valid in storage because it contains a (nested) mapping.
@@ -5,7 +5,6 @@ contract C {
struct S { uint256 [ ] [ 0.425781 ether ] s1 ;
uint [ 2 ** 0xFF ] [ 2 ** 0x42 ] s2 ;
X s3 ;
mapping ( uint => address payable ) c ;
uint [ 9 hours ** 16 ] d ;
string s ;
}
@@ -14,4 +13,4 @@ contract C {
}
}
// ----
// TypeError 1534: (530-540): Type too large for memory.
// TypeError 1534: (474-484): Type too large for memory.
@@ -11,3 +11,4 @@ contract Test {
}
// ----
// DeclarationError 2333: (157-198): Identifier already declared.
// TypeError 4061: (268-300): Type struct Test.RecursiveStruct[1] is only valid in storage because it contains a (nested) mapping.
@@ -4,4 +4,4 @@ library L {
}
}
// ----
// TypeError 9214: (108-109): Mappings cannot be assigned to.
// TypeError 9214: (108-109): Types in storage containing (nested) mappings cannot be assigned to.
@@ -9,4 +9,4 @@ contract Test {
}
}
// ----
// TypeError 4994: (208-218): Member "b1" is not available in struct Test.S1 memory outside of storage.
// TypeError 4061: (161-172): Type struct Test.S2 is only valid in storage because it contains a (nested) mapping.
@@ -3,8 +3,7 @@ contract Test {
S s;
function f() public {
S memory x;
x.b[1];
}
}
// ----
// TypeError 4994: (118-121): Member "b" is not available in struct Test.S memory outside of storage.
// TypeError 4061: (104-114): Type struct Test.S is only valid in storage because it contains a (nested) mapping.
@@ -9,3 +9,4 @@ contract test {
}
}
// ----
// TypeError 9214: (152-156): Types in storage containing (nested) mappings cannot be assigned to.
@@ -0,0 +1,9 @@
pragma experimental ABIEncoderV2;
contract C {
struct S { mapping(uint => uint) a; }
function f(S memory) public {}
}
// ----
// TypeError 4103: (105-113): Types containing (nested) mappings can only be parameters or return variables of internal or library functions.
// TypeError 4061: (105-113): Type struct C.S is only valid in storage because it contains a (nested) mapping.
@@ -5,4 +5,5 @@ contract C {
function f(S memory) public {}
}
// ----
// TypeError 4103: (105-113): Only libraries are allowed to use the mapping type in public or external functions.
// TypeError 4103: (105-113): Types containing (nested) mappings can only be parameters or return variables of internal or library functions.
// TypeError 4061: (105-113): Type struct C.S is only valid in storage because it contains a (nested) mapping.
@@ -0,0 +1,10 @@
pragma experimental ABIEncoderV2;
contract C {
struct T { mapping(uint => uint) a; }
struct S { T[][2] b; }
function f(S memory) public {}
}
// ----
// TypeError 4103: (132-140): Types containing (nested) mappings can only be parameters or return variables of internal or library functions.
// TypeError 4061: (132-140): Type struct C.S is only valid in storage because it contains a (nested) mapping.
@@ -6,4 +6,5 @@ contract C {
function f(S memory) public {}
}
// ----
// TypeError 4103: (132-140): Only libraries are allowed to use the mapping type in public or external functions.
// TypeError 4103: (132-140): Types containing (nested) mappings can only be parameters or return variables of internal or library functions.
// TypeError 4061: (132-140): Type struct C.S is only valid in storage because it contains a (nested) mapping.
@@ -4,4 +4,4 @@ contract C {
}
}
// ----
// TypeError 1164: (94-117): Type cannot live outside storage.
// TypeError 1164: (94-117): Array containing a (nested) mapping cannot be constructed in memory.
@@ -2,6 +2,6 @@ contract c {
event e(uint indexed a, mapping(uint => uint) indexed b, bool indexed c, uint indexed d, uint indexed e) anonymous;
}
// ----
// TypeError 3448: (41-72): Type is required to live outside storage.
// TypeError 3448: (41-72): Type containing a (nested) mapping is not allowed as event parameter type.
// TypeError 3417: (41-72): Internal or recursive type is not allowed as event parameter type.
// TypeError 8598: (17-132): More than 4 indexed arguments for anonymous event.
@@ -6,4 +6,4 @@ contract C {
}
}
// ----
// TypeError 9755: (117-126): Wrong argument count for struct constructor: 1 arguments given but expected 2. Members that have to be skipped in memory: c
// TypeError 9515: (117-126): Struct containing a (nested) mapping cannot be constructed.
@@ -0,0 +1,15 @@
pragma experimental ABIEncoderV2;
contract test {
struct S {
T t;
}
struct T {
mapping (uint => uint) k;
}
function f(S calldata b) external {
}
}
// ----
// TypeError 4103: (155-167): Types containing (nested) mappings can only be parameters or return variables of internal or library functions.
// TypeError 4061: (155-167): Type struct test.S is only valid in storage because it contains a (nested) mapping.
@@ -1,3 +1,5 @@
pragma experimental ABIEncoderV2;
contract Test {
struct MyStructName {
address addr;
@@ -7,4 +9,4 @@ contract Test {
function f(MyStructName memory s) public {}
}
// ----
// TypeError 4103: (112-133): Recursive type not allowed for public or external contract functions.
// TypeError 4103: (147-168): Recursive type not allowed for public or external contract functions.
@@ -1,7 +1,9 @@
pragma experimental ABIEncoderV2;
contract C {
struct S { uint a; S[] sub; }
function f() public pure returns (uint, S memory) {
}
}
// ----
// TypeError 4103: (91-99): Recursive type not allowed for public or external contract functions.
// TypeError 4103: (126-134): Recursive type not allowed for public or external contract functions.
@@ -1,7 +1,9 @@
pragma experimental ABIEncoderV2;
contract C {
struct S { uint a; S[2][] sub; }
function f() public pure returns (uint, S memory) {
}
}
// ----
// TypeError 4103: (94-102): Recursive type not allowed for public or external contract functions.
// TypeError 4103: (129-137): Recursive type not allowed for public or external contract functions.
@@ -1,3 +1,5 @@
pragma experimental ABIEncoderV2;
contract C {
struct S { uint a; S[][][] sub; }
struct T { S s; }
@@ -5,4 +7,4 @@ contract C {
}
}
// ----
// TypeError 4103: (119-129): Recursive type not allowed for public or external contract functions.
// TypeError 4103: (154-164): Recursive type not allowed for public or external contract functions.
@@ -7,4 +7,4 @@ contract D {
}
}
// ----
// TypeError 9214: (160-161): Mappings cannot be assigned to.
// TypeError 9214: (160-161): Types in storage containing (nested) mappings cannot be assigned to.
@@ -20,8 +20,18 @@ contract G {
uint x = 1;
mapping (uint => uint) b = x;
}
contract H {
struct S {mapping (uint => uint) a;}
S x;
S y = x;
S z = z;
}
// ----
// TypeError 6280: (17-67): Mappings cannot be assigned to.
// TypeError 6280: (120-148): Mappings cannot be assigned to.
// TypeError 9214: (263-264): Mappings cannot be assigned to.
// TypeError 6280: (312-340): Mappings cannot be assigned to.
// TypeError 6280: (17-67): Types in storage containing (nested) mappings cannot be assigned to.
// TypeError 6280: (120-148): Types in storage containing (nested) mappings cannot be assigned to.
// TypeError 9214: (263-264): Types in storage containing (nested) mappings cannot be assigned to.
// TypeError 6280: (312-340): Types in storage containing (nested) mappings cannot be assigned to.
// TypeError 6280: (407-414): Types in storage containing (nested) mappings cannot be assigned to.
// TypeError 6280: (417-424): Types in storage containing (nested) mappings cannot be assigned to.
@@ -8,7 +8,7 @@ contract test {
}
}
// ----
// TypeError 9214: (126-129): Mappings cannot be assigned to.
// TypeError 9214: (144-147): Mappings cannot be assigned to.
// TypeError 9214: (163-166): Mappings cannot be assigned to.
// TypeError 9214: (168-171): Mappings cannot be assigned to.
// TypeError 9214: (126-129): Types in storage containing (nested) mappings cannot be assigned to.
// TypeError 9214: (144-147): Types in storage containing (nested) mappings cannot be assigned to.
// TypeError 9214: (163-166): Types in storage containing (nested) mappings cannot be assigned to.
// TypeError 9214: (168-171): Types in storage containing (nested) mappings cannot be assigned to.
@@ -11,7 +11,7 @@ contract test {
}
}
// ----
// TypeError 9214: (172-180): Mappings cannot be assigned to.
// TypeError 9214: (195-203): Mappings cannot be assigned to.
// TypeError 9214: (219-227): Mappings cannot be assigned to.
// TypeError 9214: (229-237): Mappings cannot be assigned to.
// TypeError 9214: (172-180): Types in storage containing (nested) mappings cannot be assigned to.
// TypeError 9214: (195-203): Types in storage containing (nested) mappings cannot be assigned to.
// TypeError 9214: (219-227): Types in storage containing (nested) mappings cannot be assigned to.
// TypeError 9214: (229-237): Types in storage containing (nested) mappings cannot be assigned to.
@@ -0,0 +1,6 @@
contract test {
function f(mapping(uint => uint)[2] memory b) internal {
}
}
// ----
// TypeError 4061: (31-64): Type mapping(uint256 => uint256)[2] is only valid in storage because it contains a (nested) mapping.
@@ -0,0 +1,13 @@
library Set {
struct Data { mapping(uint => bool) flags; }
function insert(Data storage self, uint value)
public
returns (bool)
{
if (self.flags[value])
return false; // already there
self.flags[value] = true;
return true;
}
}
@@ -3,4 +3,3 @@ library L {
}
}
// ----
// TypeError 3312: (27-58): Type is required to live outside storage.
@@ -3,4 +3,3 @@ library L {
}
}
// ----
// TypeError 3312: (27-58): Type is required to live outside storage.
@@ -0,0 +1,7 @@
pragma experimental ABIEncoderV2;
library L {
struct S { mapping(uint => uint) m; }
function f(S memory a) external pure returns (S memory) {}
}
// ----
// TypeError 4061: (103-113): Type struct L.S is only valid in storage because it contains a (nested) mapping.
@@ -0,0 +1,6 @@
library Test {
struct Nested { mapping(uint => uint)[2][] a; uint y; }
struct X { Nested n; }
function f(X storage x) external {}
}
// ----
@@ -2,5 +2,5 @@ contract c {
function f1(mapping(uint => uint)[] calldata) pure external {}
}
// ----
// TypeError 3312: (29-61): Type is required to live outside storage.
// TypeError 4103: (29-61): Only libraries are allowed to use the mapping type in public or external functions.
// TypeError 4103: (29-61): Types containing (nested) mappings can only be parameters or return variables of internal or library functions.
// TypeError 4061: (29-61): Type mapping(uint256 => uint256)[] is only valid in storage because it contains a (nested) mapping.
@@ -2,5 +2,5 @@ contract c {
function f1(mapping(uint => uint) calldata) pure external returns (mapping(uint => uint) memory) {}
}
// ----
// TypeError 3442: (29-59): Mapping types can only have a data location of "storage" and thus only be parameters or return variables for internal or library functions.
// TypeError 3442: (84-112): Mapping types can only have a data location of "storage" and thus only be parameters or return variables for internal or library functions.
// TypeError 4103: (29-59): Types containing (nested) mappings can only be parameters or return variables of internal or library functions.
// TypeError 4061: (29-59): Type mapping(uint256 => uint256) is only valid in storage because it contains a (nested) mapping.
@@ -3,4 +3,4 @@ contract c {
function f5(mapping(uint => uint) memory) pure internal {}
}
// ----
// TypeError 5380: (93-121): Mapping types can only have a data location of "storage".
// TypeError 4061: (93-121): Type mapping(uint256 => uint256) is only valid in storage because it contains a (nested) mapping.
@@ -2,4 +2,5 @@ contract c {
function f3(mapping(uint => uint) memory) view public {}
}
// ----
// TypeError 3442: (29-57): Mapping types can only have a data location of "storage" and thus only be parameters or return variables for internal or library functions.
// TypeError 4103: (29-57): Types containing (nested) mappings can only be parameters or return variables of internal or library functions.
// TypeError 4061: (29-57): Type mapping(uint256 => uint256) is only valid in storage because it contains a (nested) mapping.
@@ -0,0 +1,12 @@
pragma experimental ABIEncoderV2;
contract test {
struct S {
mapping (uint => uint) s;
}
function f(S calldata b) external {
}
}
// ----
// TypeError 4103: (121-133): Types containing (nested) mappings can only be parameters or return variables of internal or library functions.
// TypeError 4061: (121-133): Type struct test.S is only valid in storage because it contains a (nested) mapping.
@@ -3,4 +3,5 @@ contract C {
}
}
// ----
// TypeError 3442: (51-79): Mapping types can only have a data location of "storage" and thus only be parameters or return variables for internal or library functions.
// TypeError 4103: (51-79): Types containing (nested) mappings can only be parameters or return variables of internal or library functions.
// TypeError 4061: (51-79): Type mapping(uint256 => uint256) is only valid in storage because it contains a (nested) mapping.
@@ -0,0 +1,8 @@
pragma experimental ABIEncoderV2;
contract C {
struct S { mapping(uint => uint) a; }
function f(S memory) public {}
}
// ----
// TypeError 4103: (104-112): Types containing (nested) mappings can only be parameters or return variables of internal or library functions.
// TypeError 4061: (104-112): Type struct C.S is only valid in storage because it contains a (nested) mapping.
@@ -0,0 +1,10 @@
pragma experimental ABIEncoderV2;
contract C {
struct S { mapping(uint => uint) a; }
struct T { S s; }
struct U { T t; }
function f(U memory) public {}
}
// ----
// TypeError 4103: (148-156): Types containing (nested) mappings can only be parameters or return variables of internal or library functions.
// TypeError 4061: (148-156): Type struct C.U is only valid in storage because it contains a (nested) mapping.
@@ -0,0 +1,20 @@
contract Test {
struct S {
T[] t;
}
struct T {
U[] u;
}
struct U {
S[] s;
mapping (uint => S) map;
}
function f() public {
S memory s;
}
}
// ----
// TypeError 4061: (143-153): Type struct Test.S is only valid in storage because it contains a (nested) mapping.
@@ -0,0 +1,15 @@
contract Test {
struct S {
uint8 a;
mapping(uint256 => uint256) b;
uint8 c;
}
S s;
function f() public returns (uint256) {
S memory x;
}
}
// ----
// TypeError 4061: (172-182): Type struct Test.S is only valid in storage because it contains a (nested) mapping.