aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--docs/frequently-asked-questions.rst17
-rw-r--r--docs/types.rst187
-rw-r--r--docs/types/conversion.rst127
-rw-r--r--docs/types/mapping-types.rst58
4 files changed, 187 insertions, 202 deletions
diff --git a/docs/frequently-asked-questions.rst b/docs/frequently-asked-questions.rst
index 8d7caefe..20c01e5c 100644
--- a/docs/frequently-asked-questions.rst
+++ b/docs/frequently-asked-questions.rst
@@ -85,23 +85,6 @@ The key point is that the calling contract needs to know about the function it i
See `ping.sol <https://github.com/fivedogit/solidity-baby-steps/blob/master/contracts/45_ping.sol>`_
and `pong.sol <https://github.com/fivedogit/solidity-baby-steps/blob/master/contracts/45_pong.sol>`_.
-How do you create 2-dimensional arrays?
-=======================================
-
-See `2D_array.sol <https://github.com/fivedogit/solidity-baby-steps/blob/master/contracts/55_2D_array.sol>`_.
-
-Note that filling a 10x10 square of ``uint8`` + contract creation took more than ``800,000``
-gas at the time of this writing. 17x17 took ``2,000,000`` gas. With the limit at
-3.14 million... well, there’s a pretty low ceiling for what you can create right
-now.
-
-Note that merely "creating" the array is free, the costs are in filling it.
-
-Note2: Optimizing storage access can pull the gas costs down considerably, because
-32 ``uint8`` values can be stored in a single slot. The problem is that these optimizations
-currently do not work across loops and also have a problem with bounds checking.
-You might get much better results in the future, though.
-
How do I initialize a contract with only a specific amount of wei?
==================================================================
diff --git a/docs/types.rst b/docs/types.rst
index ea45b7d7..b9c06f6c 100644
--- a/docs/types.rst
+++ b/docs/types.rst
@@ -22,191 +22,8 @@ tuple with a second `bool` value denoting success.
.. include:: types/reference-types.rst
-.. index:: !mapping
-.. _mapping-types:
-
-Mapping Types
-=============
-
-You declare mapping types with the syntax ``mapping(_KeyType => _ValueType)``.
-The ``_KeyType`` can be any elementary type. This means it can be any of
-the built-in value types plus ``bytes`` and ``string``. User-defined
-or complex types like contract types, enums, mappings, structs and any array type
-apart from ``bytes`` and ``string`` are not allowed.
-``_ValueType`` can be any type, including mappings.
-
-You can think of mappings as `hash tables <https://en.wikipedia.org/wiki/Hash_table>`_, which are virtually initialised
-such that every possible key exists and is mapped to a value whose
-byte-representation is all zeros, a type's :ref:`default value <default-value>`. The similarity ends there, the key data is not stored in a
-mapping, only its ``keccak256`` hash is used to look up the value.
-
-Because of this, mappings do not have a length or a concept of a key or
-value being set.
-
-Mappings can only have a data location of ``storage`` and thus
-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.
-
-You can mark 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. If ``_ValueType`` is a value type or a struct,
-the getter returns ``_ValueType``.
-If ``_ValueType`` is an array or a mapping, the getter has one parameter for
-each ``_KeyType``, recursively. For example with a mapping:
-
-::
-
- pragma solidity >=0.4.0 <0.6.0;
-
- contract MappingExample {
- mapping(address => uint) public balances;
-
- function update(uint newBalance) public {
- balances[msg.sender] = newBalance;
- }
- }
-
- contract MappingUser {
- function f() public returns (uint) {
- MappingExample m = new MappingExample();
- m.update(100);
- return m.balances(address(this));
- }
- }
-
-
-.. note::
- Mappings are not iterable, but it is possible to implement a data structure
- on top of them. For an example, see `iterable mapping <https://github.com/ethereum/dapp-bin/blob/master/library/iterable_mapping.sol>`_.
+.. include:: types/mapping-types.rst
.. include:: types/operators.rst
-.. index:: ! type;conversion, ! cast
-
-.. _types-conversion-elementary-types:
-
-Conversions between Elementary Types
-====================================
-
-Implicit Conversions
---------------------
-
-If an operator is applied to different types, the compiler tries to
-implicitly convert one of the operands to the type of the other (the same is
-true for assignments). In general, an implicit conversion between value-types
-is possible if it
-makes sense semantically and no information is lost: ``uint8`` is convertible to
-``uint16`` and ``int128`` to ``int256``, but ``int8`` is not convertible to ``uint256``
-(because ``uint256`` cannot hold e.g. ``-1``).
-
-For more details, please consult the sections about the types themselves.
-
-Explicit Conversions
---------------------
-
-If the compiler does not allow implicit conversion but you know what you are
-doing, an explicit type conversion is sometimes possible. Note that this may
-give you some unexpected behaviour and allows you to bypass some security
-features of the compiler, so be sure to test that the
-result is what you want! Take the following example where you are converting
-a negative ``int8`` to a ``uint``:
-
-::
-
- int8 y = -3;
- uint x = uint(y);
-
-At the end of this code snippet, ``x`` will have the value ``0xfffff..fd`` (64 hex
-characters), which is -3 in the two's complement representation of 256 bits.
-
-If an integer is explicitly converted to a smaller type, higher-order bits are
-cut off::
-
- uint32 a = 0x12345678;
- uint16 b = uint16(a); // b will be 0x5678 now
-
-If an integer is explicitly converted to a larger type, it is padded on the left (i.e. at the higher order end).
-The result of the conversion will compare equal to the original integer::
-
- uint16 a = 0x1234;
- uint32 b = uint32(a); // b will be 0x00001234 now
- assert(a == b);
-
-Fixed-size bytes types behave differently during conversions. They can be thought of as
-sequences of individual bytes and converting to a smaller type will cut off the
-sequence::
-
- bytes2 a = 0x1234;
- bytes1 b = bytes1(a); // b will be 0x12
-
-If a fixed-size bytes type is explicitly converted to a larger type, it is padded on
-the right. Accessing the byte at a fixed index will result in the same value before and
-after the conversion (if the index is still in range)::
-
- bytes2 a = 0x1234;
- bytes4 b = bytes4(a); // b will be 0x12340000
- assert(a[0] == b[0]);
- assert(a[1] == b[1]);
-
-Since integers and fixed-size byte arrays behave differently when truncating or
-padding, explicit conversions between integers and fixed-size byte arrays are only allowed,
-if both have the same size. If you want to convert between integers and fixed-size byte arrays of
-different size, you have to use intermediate conversions that make the desired truncation and padding
-rules explicit::
-
- bytes2 a = 0x1234;
- uint32 b = uint16(a); // b will be 0x00001234
- uint32 c = uint32(bytes4(a)); // c will be 0x12340000
- uint8 d = uint8(uint16(a)); // d will be 0x34
- uint8 e = uint8(bytes1(a)); // e will be 0x12
-
-.. _types-conversion-literals:
-
-Conversions between Literals and Elementary Types
-=================================================
-
-Integer Types
--------------
-
-Decimal and hexadecimal number literals can be implicitly converted to any integer type
-that is large enough to represent it without truncation::
-
- uint8 a = 12; // fine
- uint32 b = 1234; // fine
- uint16 c = 0x123456; // fails, since it would have to truncate to 0x3456
-
-Fixed-Size Byte Arrays
-----------------------
-
-Decimal number literals cannot be implicitly converted to fixed-size byte arrays. Hexadecimal
-number literals can be, but only if the number of hex digits exactly fits the size of the bytes
-type. As an exception both decimal and hexadecimal literals which have a value of zero can be
-converted to any fixed-size bytes type::
-
- bytes2 a = 54321; // not allowed
- bytes2 b = 0x12; // not allowed
- bytes2 c = 0x123; // not allowed
- bytes2 d = 0x1234; // fine
- bytes2 e = 0x0012; // fine
- bytes4 f = 0; // fine
- bytes4 g = 0x0; // fine
-
-String literals and hex string literals can be implicitly converted to fixed-size byte arrays,
-if their number of characters matches the size of the bytes type::
-
- bytes2 a = hex"1234"; // fine
- bytes2 b = "xy"; // fine
- bytes2 c = hex"12"; // not allowed
- bytes2 d = hex"123"; // not allowed
- bytes2 e = "x"; // not allowed
- bytes2 f = "xyz"; // not allowed
-
-Addresses
----------
-
-As described in :ref:`address_literals`, hex literals of the correct size that pass the checksum
-test are of ``address`` type. No other literals can be implicitly converted to the ``address`` type.
-
-Explicit conversions from ``bytes20`` or any integer type to ``address`` result in ``address payable``.
+.. include:: types/conversion.rst \ No newline at end of file
diff --git a/docs/types/conversion.rst b/docs/types/conversion.rst
new file mode 100644
index 00000000..5a9f84c0
--- /dev/null
+++ b/docs/types/conversion.rst
@@ -0,0 +1,127 @@
+.. index:: ! type;conversion, ! cast
+
+.. _types-conversion-elementary-types:
+
+Conversions between Elementary Types
+====================================
+
+Implicit Conversions
+--------------------
+
+If an operator is applied to different types, the compiler tries to
+implicitly convert one of the operands to the type of the other (the same is
+true for assignments). In general, an implicit conversion between value-types
+is possible if it
+makes sense semantically and no information is lost: ``uint8`` is convertible to
+``uint16`` and ``int128`` to ``int256``, but ``int8`` is not convertible to ``uint256``
+(because ``uint256`` cannot hold e.g. ``-1``).
+
+For more details, please consult the sections about the types themselves.
+
+Explicit Conversions
+--------------------
+
+If the compiler does not allow implicit conversion but you know what you are
+doing, an explicit type conversion is sometimes possible. Note that this may
+give you some unexpected behaviour and allows you to bypass some security
+features of the compiler, so be sure to test that the
+result is what you want! Take the following example where you are converting
+a negative ``int8`` to a ``uint``:
+
+::
+
+ int8 y = -3;
+ uint x = uint(y);
+
+At the end of this code snippet, ``x`` will have the value ``0xfffff..fd`` (64 hex
+characters), which is -3 in the two's complement representation of 256 bits.
+
+If an integer is explicitly converted to a smaller type, higher-order bits are
+cut off::
+
+ uint32 a = 0x12345678;
+ uint16 b = uint16(a); // b will be 0x5678 now
+
+If an integer is explicitly converted to a larger type, it is padded on the left (i.e. at the higher order end).
+The result of the conversion will compare equal to the original integer::
+
+ uint16 a = 0x1234;
+ uint32 b = uint32(a); // b will be 0x00001234 now
+ assert(a == b);
+
+Fixed-size bytes types behave differently during conversions. They can be thought of as
+sequences of individual bytes and converting to a smaller type will cut off the
+sequence::
+
+ bytes2 a = 0x1234;
+ bytes1 b = bytes1(a); // b will be 0x12
+
+If a fixed-size bytes type is explicitly converted to a larger type, it is padded on
+the right. Accessing the byte at a fixed index will result in the same value before and
+after the conversion (if the index is still in range)::
+
+ bytes2 a = 0x1234;
+ bytes4 b = bytes4(a); // b will be 0x12340000
+ assert(a[0] == b[0]);
+ assert(a[1] == b[1]);
+
+Since integers and fixed-size byte arrays behave differently when truncating or
+padding, explicit conversions between integers and fixed-size byte arrays are only allowed,
+if both have the same size. If you want to convert between integers and fixed-size byte arrays of
+different size, you have to use intermediate conversions that make the desired truncation and padding
+rules explicit::
+
+ bytes2 a = 0x1234;
+ uint32 b = uint16(a); // b will be 0x00001234
+ uint32 c = uint32(bytes4(a)); // c will be 0x12340000
+ uint8 d = uint8(uint16(a)); // d will be 0x34
+ uint8 e = uint8(bytes1(a)); // e will be 0x12
+
+.. _types-conversion-literals:
+
+Conversions between Literals and Elementary Types
+=================================================
+
+Integer Types
+-------------
+
+Decimal and hexadecimal number literals can be implicitly converted to any integer type
+that is large enough to represent it without truncation::
+
+ uint8 a = 12; // fine
+ uint32 b = 1234; // fine
+ uint16 c = 0x123456; // fails, since it would have to truncate to 0x3456
+
+Fixed-Size Byte Arrays
+----------------------
+
+Decimal number literals cannot be implicitly converted to fixed-size byte arrays. Hexadecimal
+number literals can be, but only if the number of hex digits exactly fits the size of the bytes
+type. As an exception both decimal and hexadecimal literals which have a value of zero can be
+converted to any fixed-size bytes type::
+
+ bytes2 a = 54321; // not allowed
+ bytes2 b = 0x12; // not allowed
+ bytes2 c = 0x123; // not allowed
+ bytes2 d = 0x1234; // fine
+ bytes2 e = 0x0012; // fine
+ bytes4 f = 0; // fine
+ bytes4 g = 0x0; // fine
+
+String literals and hex string literals can be implicitly converted to fixed-size byte arrays,
+if their number of characters matches the size of the bytes type::
+
+ bytes2 a = hex"1234"; // fine
+ bytes2 b = "xy"; // fine
+ bytes2 c = hex"12"; // not allowed
+ bytes2 d = hex"123"; // not allowed
+ bytes2 e = "x"; // not allowed
+ bytes2 f = "xyz"; // not allowed
+
+Addresses
+---------
+
+As described in :ref:`address_literals`, hex literals of the correct size that pass the checksum
+test are of ``address`` type. No other literals can be implicitly converted to the ``address`` type.
+
+Explicit conversions from ``bytes20`` or any integer type to ``address`` result in ``address payable``.
diff --git a/docs/types/mapping-types.rst b/docs/types/mapping-types.rst
new file mode 100644
index 00000000..935ed6b4
--- /dev/null
+++ b/docs/types/mapping-types.rst
@@ -0,0 +1,58 @@
+.. index:: !mapping
+.. _mapping-types:
+
+Mapping Types
+=============
+
+You declare mapping types with the syntax ``mapping(_KeyType => _ValueType)``.
+The ``_KeyType`` can be any elementary type. This means it can be any of
+the built-in value types plus ``bytes`` and ``string``. User-defined
+or complex types like contract types, enums, mappings, structs and any array type
+apart from ``bytes`` and ``string`` are not allowed.
+``_ValueType`` can be any type, including mappings.
+
+You can think of mappings as `hash tables <https://en.wikipedia.org/wiki/Hash_table>`_, which are virtually initialised
+such that every possible key exists and is mapped to a value whose
+byte-representation is all zeros, a type's :ref:`default value <default-value>`. The similarity ends there, the key data is not stored in a
+mapping, only its ``keccak256`` hash is used to look up the value.
+
+Because of this, mappings do not have a length or a concept of a key or
+value being set.
+
+Mappings can only have a data location of ``storage`` and thus
+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.
+
+You can mark 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. If ``_ValueType`` is a value type or a struct,
+the getter returns ``_ValueType``.
+If ``_ValueType`` is an array or a mapping, the getter has one parameter for
+each ``_KeyType``, recursively. For example with a mapping:
+
+::
+
+ pragma solidity >=0.4.0 <0.6.0;
+
+ contract MappingExample {
+ mapping(address => uint) public balances;
+
+ function update(uint newBalance) public {
+ balances[msg.sender] = newBalance;
+ }
+ }
+
+ contract MappingUser {
+ function f() public returns (uint) {
+ MappingExample m = new MappingExample();
+ m.update(100);
+ return m.balances(address(this));
+ }
+ }
+
+
+.. note::
+ Mappings are not iterable, but it is possible to implement a data structure
+ on top of them. For an example, see `iterable mapping <https://github.com/ethereum/dapp-bin/blob/master/library/iterable_mapping.sol>`_.