From f4cb57fc3b95dc40697402d9a9b1d8b5bed15ddd Mon Sep 17 00:00:00 2001 From: haoyang9804 Date: Fri, 18 Oct 2024 22:20:54 +0100 Subject: [PATCH 01/12] enrich document with using getter function over state struct instance --- docs/contracts/visibility-and-getters.rst | 29 +++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/docs/contracts/visibility-and-getters.rst b/docs/contracts/visibility-and-getters.rst index 5bf46dea551b..331e7654ea45 100644 --- a/docs/contracts/visibility-and-getters.rst +++ b/docs/contracts/visibility-and-getters.rst @@ -189,6 +189,35 @@ to write a function, for example: Now you can use ``getArray()`` to retrieve the entire array, instead of ``myArray(i)``, which returns a single element per call. +When you have a public state variable of a struct type, calling the +getter function will return either a tuple containing the struct's members +(if there are multiple members) or just a single member +(if the struct has only one member). For example: + +.. code-block:: solidity + + // SPDX-License-Identifier: GPL-3.0 + pragma solidity >=0.4.0 <0.9.0; + + contract structExample { + struct simpleStruct { + bool b; + } + struct compleStruct { + uint a; + bool b; + } + simpleStruct public ss; + compleStruct public cs; + function f() public view { + bool b1 = this.ss(); + (uint a, bool b2) = this.cs(); + } + } + +``this.ss()``'s return type is bool, while ``this.cs()``'s return type is +a tuple of uint and bool. + The next example is more complex: .. code-block:: solidity From 81b8a67d61b03958169826084a4ac52a0e593289 Mon Sep 17 00:00:00 2001 From: haoyang9804 Date: Fri, 18 Oct 2024 23:00:11 +0100 Subject: [PATCH 02/12] fix errors in the doc --- docs/contracts/visibility-and-getters.rst | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/docs/contracts/visibility-and-getters.rst b/docs/contracts/visibility-and-getters.rst index 331e7654ea45..6cc5af4dd216 100644 --- a/docs/contracts/visibility-and-getters.rst +++ b/docs/contracts/visibility-and-getters.rst @@ -191,7 +191,7 @@ Now you can use ``getArray()`` to retrieve the entire array, instead of When you have a public state variable of a struct type, calling the getter function will return either a tuple containing the struct's members -(if there are multiple members) or just a single member +(if there are multiple members) or just a single member (if the struct has only one member). For example: .. code-block:: solidity @@ -200,22 +200,34 @@ getter function will return either a tuple containing the struct's members pragma solidity >=0.4.0 <0.9.0; contract structExample { + // Struct Definition with single member struct simpleStruct { bool b; } + + // Struct Definition with multiple members struct compleStruct { uint a; bool b; } + + // public state variables simpleStruct public ss; compleStruct public cs; - function f() public view { - bool b1 = this.ss(); - (uint a, bool b2) = this.cs(); + + // Getter function generated by the compiler + /* + function ss() public view returns (bool) { + return ss.b; } + function cs() public view returns (uint, bool) { + return (cs.a, cs.b); + } + */ + } -``this.ss()``'s return type is bool, while ``this.cs()``'s return type is +``this.ss()``'s return type is bool, while ``this.cs()``'s return type is a tuple of uint and bool. The next example is more complex: From 464cb001366c81970b908b7d9d1c700f1bf69b75 Mon Sep 17 00:00:00 2001 From: haoyang9804 Date: Fri, 18 Oct 2024 23:03:42 +0100 Subject: [PATCH 03/12] remove Trailing whitespace --- docs/contracts/visibility-and-getters.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/contracts/visibility-and-getters.rst b/docs/contracts/visibility-and-getters.rst index 6cc5af4dd216..f25eba92fbed 100644 --- a/docs/contracts/visibility-and-getters.rst +++ b/docs/contracts/visibility-and-getters.rst @@ -214,7 +214,7 @@ getter function will return either a tuple containing the struct's members // public state variables simpleStruct public ss; compleStruct public cs; - + // Getter function generated by the compiler /* function ss() public view returns (bool) { From 0251f9eda6faa71f81ec12496def333530ffd4da Mon Sep 17 00:00:00 2001 From: haoyang9804 Date: Mon, 21 Oct 2024 13:44:17 +0100 Subject: [PATCH 04/12] Refine doc based on suggestions --- docs/contracts/visibility-and-getters.rst | 28 +++++++++++------------ 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/docs/contracts/visibility-and-getters.rst b/docs/contracts/visibility-and-getters.rst index f25eba92fbed..e67883ac0b6d 100644 --- a/docs/contracts/visibility-and-getters.rst +++ b/docs/contracts/visibility-and-getters.rst @@ -189,45 +189,45 @@ to write a function, for example: Now you can use ``getArray()`` to retrieve the entire array, instead of ``myArray(i)``, which returns a single element per call. -When you have a public state variable of a struct type, calling the -getter function will return either a tuple containing the struct's members -(if there are multiple members) or just a single member -(if the struct has only one member). For example: +When you have a public state variable of a struct type, calling the compiler +generated getter function will return either a tuple containing the struct's members +(if there are multiple members) or just a single member +(if the struct has only one member). For example: .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.4.0 <0.9.0; - contract structExample { + contract StructExample { // Struct Definition with single member - struct simpleStruct { + struct SimpleStruct { bool b; } // Struct Definition with multiple members - struct compleStruct { + struct ComplexStruct { uint a; bool b; } // public state variables - simpleStruct public ss; - compleStruct public cs; + SimpleStruct public simpleStruct; + ComplexStruct public complexStruct; // Getter function generated by the compiler /* - function ss() public view returns (bool) { - return ss.b; + function simpleStruct() public view returns (bool) { + return simpleStruct.b; } - function cs() public view returns (uint, bool) { - return (cs.a, cs.b); + function complexStruct() public view returns (uint, bool) { + return (complexStruct.a, complexStruct.b); } */ } -``this.ss()``'s return type is bool, while ``this.cs()``'s return type is +``this.simpleStruct()``'s return type is bool, while ``this.complexStruct()``'s return type is a tuple of uint and bool. The next example is more complex: From f02c816b6d7ea155b9e440b94824083657d63904 Mon Sep 17 00:00:00 2001 From: haoyang9804 Date: Mon, 21 Oct 2024 13:51:11 +0100 Subject: [PATCH 05/12] refine the doc --- docs/contracts/visibility-and-getters.rst | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/docs/contracts/visibility-and-getters.rst b/docs/contracts/visibility-and-getters.rst index e67883ac0b6d..725d9af9830a 100644 --- a/docs/contracts/visibility-and-getters.rst +++ b/docs/contracts/visibility-and-getters.rst @@ -189,10 +189,13 @@ to write a function, for example: Now you can use ``getArray()`` to retrieve the entire array, instead of ``myArray(i)``, which returns a single element per call. -When you have a public state variable of a struct type, calling the compiler -generated getter function will return either a tuple containing the struct's members -(if there are multiple members) or just a single member -(if the struct has only one member). For example: +When you declare a public state variable of a struct type, +the generated getter function does not return the struct as a single object in memory. +Instead, due to historical design choices and early limitations in the ABI encoding of structs, +the getter function returns the individual members of the struct as separate elements within a tuple. +If the struct contains multiple members, the getter function returns a tuple with each member as a +distinct element. Conversely, if the struct has only one member, the getter function simply returns +that member directly instead of wrapping it in a tuple. For example: .. code-block:: solidity From f043514b2a5aac24db3938271a588eefa277557d Mon Sep 17 00:00:00 2001 From: haoyang9804 Date: Mon, 21 Oct 2024 18:24:52 +0100 Subject: [PATCH 06/12] merge array example and struct example. Remove mapping. --- docs/contracts/visibility-and-getters.rst | 72 +++++------------------ 1 file changed, 14 insertions(+), 58 deletions(-) diff --git a/docs/contracts/visibility-and-getters.rst b/docs/contracts/visibility-and-getters.rst index 725d9af9830a..98d37dc1e511 100644 --- a/docs/contracts/visibility-and-getters.rst +++ b/docs/contracts/visibility-and-getters.rst @@ -157,12 +157,21 @@ it evaluates to a state variable. If it is accessed externally } } +Getter functions do not always return the entire state variable, +arrays and structs are two exceptions. + If you have a ``public`` state variable of array type, then you can only retrieve single elements of the array via the generated getter function. This mechanism -exists to avoid high gas costs when returning an entire array. You can use -arguments to specify which individual element to return, for example -``myArray(0)``. If you want to return an entire array in one call, then you need -to write a function, for example: +exists to avoid high gas costs when returning an entire array. +When you declare a public state variable of a struct type, +the generated getter function does not return the struct as a single object in memory. +Instead, due to historical design choices and early limitations in the ABI encoding of structs, +the getter function returns the individual members of the struct as separate elements within a tuple. +If the struct contains multiple members, the getter function returns a tuple with each member as a +distinct element. Conversely, if the struct has only one member, the getter function simply returns +that member directly instead of wrapping it in a tuple. + +Below is an example to include the above two cases. .. code-block:: solidity @@ -186,22 +195,6 @@ to write a function, for example: } } -Now you can use ``getArray()`` to retrieve the entire array, instead of -``myArray(i)``, which returns a single element per call. - -When you declare a public state variable of a struct type, -the generated getter function does not return the struct as a single object in memory. -Instead, due to historical design choices and early limitations in the ABI encoding of structs, -the getter function returns the individual members of the struct as separate elements within a tuple. -If the struct contains multiple members, the getter function returns a tuple with each member as a -distinct element. Conversely, if the struct has only one member, the getter function simply returns -that member directly instead of wrapping it in a tuple. For example: - -.. code-block:: solidity - - // SPDX-License-Identifier: GPL-3.0 - pragma solidity >=0.4.0 <0.9.0; - contract StructExample { // Struct Definition with single member struct SimpleStruct { @@ -228,41 +221,4 @@ that member directly instead of wrapping it in a tuple. For example: } */ - } - -``this.simpleStruct()``'s return type is bool, while ``this.complexStruct()``'s return type is -a tuple of uint and bool. - -The next example is more complex: - -.. code-block:: solidity - - // SPDX-License-Identifier: GPL-3.0 - pragma solidity >=0.4.0 <0.9.0; - - contract Complex { - struct Data { - uint a; - bytes3 b; - mapping(uint => uint) map; - uint[3] c; - uint[] d; - bytes e; - } - mapping(uint => mapping(bool => Data[])) public data; - } - -It generates a function of the following form. The mapping and arrays (with the -exception of byte arrays) in the struct are omitted because there is no good way -to select individual struct members or provide a key for the mapping: - -.. code-block:: solidity - - function data(uint arg1, bool arg2, uint arg3) - public - returns (uint a, bytes3 b, bytes memory e) - { - a = data[arg1][arg2][arg3].a; - b = data[arg1][arg2][arg3].b; - e = data[arg1][arg2][arg3].e; - } + } \ No newline at end of file From c2ce59b140b6a10e4cebdc8fb593134ea102b02e Mon Sep 17 00:00:00 2001 From: haoyang9804 Date: Tue, 22 Oct 2024 13:31:31 +0100 Subject: [PATCH 07/12] Document a special workaround for calldata arrays and struct instances --- docs/types/reference-types.rst | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/docs/types/reference-types.rst b/docs/types/reference-types.rst index 4a053d51beea..6c7d70056384 100644 --- a/docs/types/reference-types.rst +++ b/docs/types/reference-types.rst @@ -37,6 +37,12 @@ non-persistent area where function arguments are stored, and behaves mostly like data location can also be returned from functions, but it is not possible to allocate such types. +.. note:: + Arrays and structs with ``calldata`` data location declared in a function body must be assigned before + use. Arrays and structs with ``calldata`` data location as the returned parameters of a function + must be assigned before returning. This rule is enforced by the compiler to allow complex initialization patterns. + A workaround is assign the variable to itself after declaration. + .. note:: Prior to version 0.6.9 data location for reference-type arguments was limited to ``calldata`` in external functions, ``memory`` in public functions and either From d6010a2478a2bcaa57faa5f8e66874ca037e49ce Mon Sep 17 00:00:00 2001 From: haoyang9804 Date: Tue, 22 Oct 2024 13:35:14 +0100 Subject: [PATCH 08/12] reset the incorrect commit --- docs/types/reference-types.rst | 6 ------ 1 file changed, 6 deletions(-) diff --git a/docs/types/reference-types.rst b/docs/types/reference-types.rst index 6c7d70056384..4a053d51beea 100644 --- a/docs/types/reference-types.rst +++ b/docs/types/reference-types.rst @@ -37,12 +37,6 @@ non-persistent area where function arguments are stored, and behaves mostly like data location can also be returned from functions, but it is not possible to allocate such types. -.. note:: - Arrays and structs with ``calldata`` data location declared in a function body must be assigned before - use. Arrays and structs with ``calldata`` data location as the returned parameters of a function - must be assigned before returning. This rule is enforced by the compiler to allow complex initialization patterns. - A workaround is assign the variable to itself after declaration. - .. note:: Prior to version 0.6.9 data location for reference-type arguments was limited to ``calldata`` in external functions, ``memory`` in public functions and either From e1dd47932e1c98f5acfe0a8a0fb542fc47dc9680 Mon Sep 17 00:00:00 2001 From: haoyang9804 Date: Fri, 25 Oct 2024 22:59:43 +0100 Subject: [PATCH 09/12] refine the doc --- docs/contracts/visibility-and-getters.rst | 27 ++++++++++------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/docs/contracts/visibility-and-getters.rst b/docs/contracts/visibility-and-getters.rst index 98d37dc1e511..e7a857427989 100644 --- a/docs/contracts/visibility-and-getters.rst +++ b/docs/contracts/visibility-and-getters.rst @@ -157,28 +157,27 @@ it evaluates to a state variable. If it is accessed externally } } -Getter functions do not always return the entire state variable, -arrays and structs are two exceptions. +When considering arrays and structs, the getter functions do not return +the entire state variable, but a tuple of one or more elements. If you have a ``public`` state variable of array type, then you can only retrieve single elements of the array via the generated getter function. This mechanism exists to avoid high gas costs when returning an entire array. -When you declare a public state variable of a struct type, -the generated getter function does not return the struct as a single object in memory. -Instead, due to historical design choices and early limitations in the ABI encoding of structs, -the getter function returns the individual members of the struct as separate elements within a tuple. -If the struct contains multiple members, the getter function returns a tuple with each member as a -distinct element. Conversely, if the struct has only one member, the getter function simply returns -that member directly instead of wrapping it in a tuple. -Below is an example to include the above two cases. +When you declare a public state variable of a struct type, the generated getter function +returns specific member of the struct as separate elements within a tuple, +rather than the struct as a single object in memory. +The members returned appear in the order they are declared in the struct, provided they +are not omitted. Array-type members within the struct are excluded from the returned tuple. +Additionally, if the struct consists solely of array-type members, no getter function will be generated + .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 pragma solidity >=0.4.16 <0.9.0; - contract arrayExample { + contract ArrayExample { // public state variable uint[] public myArray; @@ -198,13 +197,14 @@ Below is an example to include the above two cases. contract StructExample { // Struct Definition with single member struct SimpleStruct { - bool b; + int[2] arr; } // Struct Definition with multiple members struct ComplexStruct { uint a; bool b; + int[2] arr; } // public state variables @@ -213,9 +213,6 @@ Below is an example to include the above two cases. // Getter function generated by the compiler /* - function simpleStruct() public view returns (bool) { - return simpleStruct.b; - } function complexStruct() public view returns (uint, bool) { return (complexStruct.a, complexStruct.b); } From abe09347dc521ac0bfbcec9a704e8d6dc80c5113 Mon Sep 17 00:00:00 2001 From: haoyang9804 Date: Sat, 26 Oct 2024 13:56:04 +0100 Subject: [PATCH 10/12] Fix errors in the code example --- docs/contracts/visibility-and-getters.rst | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/contracts/visibility-and-getters.rst b/docs/contracts/visibility-and-getters.rst index e7a857427989..c2bc44bc24da 100644 --- a/docs/contracts/visibility-and-getters.rst +++ b/docs/contracts/visibility-and-getters.rst @@ -157,7 +157,7 @@ it evaluates to a state variable. If it is accessed externally } } -When considering arrays and structs, the getter functions do not return +When considering arrays and structs, the getter functions do not return the entire state variable, but a tuple of one or more elements. If you have a ``public`` state variable of array type, then you can only retrieve @@ -208,7 +208,7 @@ Additionally, if the struct consists solely of array-type members, no getter fun } // public state variables - SimpleStruct public simpleStruct; + // SimpleStruct omits all its members, therefore its public instance is disallowed ComplexStruct public complexStruct; // Getter function generated by the compiler From 5d4fe822b75d582b20b6109ece96f2829aef9a07 Mon Sep 17 00:00:00 2001 From: haoyang9804 Date: Wed, 30 Oct 2024 11:18:26 +0000 Subject: [PATCH 11/12] refine the doc --- docs/contracts/visibility-and-getters.rst | 66 +++++++++++++++++------ 1 file changed, 51 insertions(+), 15 deletions(-) diff --git a/docs/contracts/visibility-and-getters.rst b/docs/contracts/visibility-and-getters.rst index c2bc44bc24da..a2b2ea6c1d50 100644 --- a/docs/contracts/visibility-and-getters.rst +++ b/docs/contracts/visibility-and-getters.rst @@ -157,21 +157,13 @@ it evaluates to a state variable. If it is accessed externally } } -When considering arrays and structs, the getter functions do not return -the entire state variable, but a tuple of one or more elements. +When considering arrays, mapping, and structs, the getter functions do not return +the entire state variable. If you have a ``public`` state variable of array type, then you can only retrieve single elements of the array via the generated getter function. This mechanism exists to avoid high gas costs when returning an entire array. -When you declare a public state variable of a struct type, the generated getter function -returns specific member of the struct as separate elements within a tuple, -rather than the struct as a single object in memory. -The members returned appear in the order they are declared in the struct, provided they -are not omitted. Array-type members within the struct are excluded from the returned tuple. -Additionally, if the struct consists solely of array-type members, no getter function will be generated - - .. code-block:: solidity // SPDX-License-Identifier: GPL-3.0 @@ -194,28 +186,72 @@ Additionally, if the struct consists solely of array-type members, no getter fun } } +If you have a ``public`` state variable of mapping type. The getter function +returns the value associated with the key passed as an argument. + +.. code-block:: solidity + + // SPDX-License-Identifier: GPL-3.0 + pragma solidity >=0.4.16 <0.9.0; + + contract MappingExample { + // public state variable + mapping(uint => uint) public myMap; + + // Getter function generated by the compiler + /* + function myMap(uint i) public view returns (uint) { + return myMap[i]; + } + */ + } + +When you declare a public state variable of a struct type, the generated getter function +returns specific member of the struct as separate elements within a tuple, +rather than the struct as a single object in memory. +The members returned appear in the order they are declared in the struct, provided they +are not omitted. Array members and mapping members within the struct are excluded from the returned tuple. +Additionally, if the struct consists solely of array members and mapping members, no getter function will be generated. + +.. code-block:: solidity + + // SPDX-License-Identifier: GPL-3.0 + pragma solidity >=0.4.16 <0.9.0; + contract StructExample { // Struct Definition with single member struct SimpleStruct { int[2] arr; + mapping(uint => uint) map; } // Struct Definition with multiple members struct ComplexStruct { uint a; - bool b; - int[2] arr; + bytes3 b; + mapping(uint => uint) map; + uint[3] c; + uint[] d; + bytes e; } // public state variables // SimpleStruct omits all its members, therefore its public instance is disallowed ComplexStruct public complexStruct; + mapping(uint => mapping(bool => ComplexStruct[])) public map; // Getter function generated by the compiler /* - function complexStruct() public view returns (uint, bool) { - return (complexStruct.a, complexStruct.b); + function complexStruct() public view returns (uint, bytes3, bytes memory) { + return (complexStruct.a, complexStruct.b, complexStruct.e); + } + function map(uint arg1, bool arg2, uint arg3) + public + returns (uint a, bytes3 b, bytes memory e) + { + a = map[arg1][arg2][arg3].a; + b = map[arg1][arg2][arg3].b; + e = map[arg1][arg2][arg3].e; } */ - } \ No newline at end of file From 6173e007369bf755b943e7879cd257e459489f34 Mon Sep 17 00:00:00 2001 From: Haoyang Ma Date: Mon, 2 Dec 2024 11:47:41 +0000 Subject: [PATCH 12/12] update --- docs/contracts/visibility-and-getters.rst | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/docs/contracts/visibility-and-getters.rst b/docs/contracts/visibility-and-getters.rst index a2b2ea6c1d50..bef5c644a5cb 100644 --- a/docs/contracts/visibility-and-getters.rst +++ b/docs/contracts/visibility-and-getters.rst @@ -207,11 +207,13 @@ returns the value associated with the key passed as an argument. } When you declare a public state variable of a struct type, the generated getter function -returns specific member of the struct as separate elements within a tuple, +returns each member of the struct as separate elements within a tuple, rather than the struct as a single object in memory. The members returned appear in the order they are declared in the struct, provided they -are not omitted. Array members and mapping members within the struct are excluded from the returned tuple. -Additionally, if the struct consists solely of array members and mapping members, no getter function will be generated. +are not omitted. The mapping and arrays (with the exception of byte arrays) +in the struct are omitted because there is no good way to +select individual array members or provide a key for the mapping +Additionally, if all struct members are omitted, no getter function will be generated. .. code-block:: solidity