mirror of
https://github.com/ethereum/solidity
synced 2023-10-03 13:03:40 +00:00
Explain mappings example, and add link to further details
Updates from review Changes from review Nested example Update docs/types/mapping-types.rst Co-Authored-By: chriseth <chris@ethereum.org> Changes from review Bring example inline with ERC20 Clarify what maps where Use OZ contract example Update docs/types/mapping-types.rst Co-Authored-By: chriseth <chris@ethereum.org> update code example
This commit is contained in:
parent
aa8de4404e
commit
0c51dcc967
@ -4,7 +4,8 @@
|
|||||||
Mapping Types
|
Mapping Types
|
||||||
=============
|
=============
|
||||||
|
|
||||||
You declare mapping types with the syntax ``mapping(_KeyType => _ValueType)``.
|
Mapping types use the syntax ``mapping(_KeyType => _ValueType)`` and variables
|
||||||
|
are declared as a mapping type using the syntax ``mapping (_KeyType => _ValueType) _VariableModifiers _VariableName``.
|
||||||
The ``_KeyType`` can be any elementary type. This means it can be any of
|
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
|
the built-in value types plus ``bytes`` and ``string``. User-defined
|
||||||
or complex types like contract types, enums, mappings, structs and any array type
|
or complex types like contract types, enums, mappings, structs and any array type
|
||||||
@ -27,11 +28,16 @@ They cannot be used as parameters or return parameters
|
|||||||
of contract functions that are publicly visible.
|
of contract functions that are publicly visible.
|
||||||
|
|
||||||
You can mark state variables of mapping type as ``public`` and Solidity creates a
|
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
|
:ref:`getter <visibility-and-getters>` for you. The ``_KeyType`` becomes a parameter for the getter.
|
||||||
parameter for the getter. If ``_ValueType`` is a value type or a struct,
|
If ``_ValueType`` is a value type or a struct, the getter returns ``_ValueType``.
|
||||||
the getter returns ``_ValueType``.
|
|
||||||
If ``_ValueType`` is an array or a mapping, the getter has one parameter for
|
If ``_ValueType`` is an array or a mapping, the getter has one parameter for
|
||||||
each ``_KeyType``, recursively. For example with a mapping:
|
each ``_KeyType``, recursively.
|
||||||
|
|
||||||
|
In the example below, the ``MappingExample`` contract defines a public ``balances``
|
||||||
|
mapping, with the key type an ``address``, and a value type a ``uint``, mapping
|
||||||
|
an Ethereum address to an unsigned integer value. As ``uint`` is a value type, the getter
|
||||||
|
returns a value that matches the type, which you can see in the ``MappingUser``
|
||||||
|
contract that returns the value at the specified address.
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
@ -53,6 +59,52 @@ each ``_KeyType``, recursively. For example with a mapping:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
The example below is a simplified version of an `ERC20 token <https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/ERC20.sol>`_.
|
||||||
|
``_allowances`` is an example of a mapping type inside another mapping type.
|
||||||
|
The example below uses ``_allowances`` to record the amount someone else is allowed to withdraw from your account.
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
pragma solidity >=0.4.0 <0.7.0;
|
||||||
|
|
||||||
|
contract MappingExample {
|
||||||
|
|
||||||
|
mapping (address => uint256) private _balances;
|
||||||
|
mapping (address => mapping (address => uint256)) private _allowances;
|
||||||
|
|
||||||
|
event Transfer(address indexed from, address indexed to, uint256 value);
|
||||||
|
event Approval(address indexed owner, address indexed spender, uint256 value);
|
||||||
|
|
||||||
|
function allowance(address owner, address spender) public view returns (uint256) {
|
||||||
|
return _allowances[owner][spender];
|
||||||
|
}
|
||||||
|
|
||||||
|
function transferFrom(address sender, address recipient, uint256 amount) public returns (bool) {
|
||||||
|
_transfer(sender, recipient, amount);
|
||||||
|
approve(sender, msg.sender, amount);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function approve(address owner, address spender, uint256 amount) public returns (bool) {
|
||||||
|
require(owner != address(0), "ERC20: approve from the zero address");
|
||||||
|
require(spender != address(0), "ERC20: approve to the zero address");
|
||||||
|
|
||||||
|
_allowances[owner][spender] = amount;
|
||||||
|
emit Approval(owner, spender, amount);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function _transfer(address sender, address recipient, uint256 amount) internal {
|
||||||
|
require(sender != address(0), "ERC20: transfer from the zero address");
|
||||||
|
require(recipient != address(0), "ERC20: transfer to the zero address");
|
||||||
|
|
||||||
|
_balances[sender] -= amount;
|
||||||
|
_balances[recipient] += amount;
|
||||||
|
emit Transfer(sender, recipient, amount);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
.. index:: !iterable mappings
|
.. index:: !iterable mappings
|
||||||
.. _iterable-mappings:
|
.. _iterable-mappings:
|
||||||
|
|
||||||
|
@ -17,7 +17,7 @@ equivalent to ``a = 0``, but it can also be used on arrays, where it assigns a d
|
|||||||
array of length zero or a static array of the same length with all elements set to their
|
array of length zero or a static array of the same length with all elements set to their
|
||||||
initial value. ``delete a[x]`` deletes the item at index ``x`` of the array and leaves
|
initial value. ``delete a[x]`` deletes the item at index ``x`` of the array and leaves
|
||||||
all other elements and the length of the array untouched. This especially means that it leaves
|
all other elements and the length of the array untouched. This especially means that it leaves
|
||||||
a gap in the array. If you plan to remove items, a mapping is probably a better choice.
|
a gap in the array. If you plan to remove items, a :ref:`mapping <mapping-types>` is probably a better choice.
|
||||||
|
|
||||||
For structs, it assigns a struct with all members reset. In other words, the value of ``a`` after ``delete a`` is the same as if ``a`` would be declared without assignment, with the following caveat:
|
For structs, it assigns a struct with all members reset. In other words, the value of ``a`` after ``delete a`` is the same as if ``a`` would be declared without assignment, with the following caveat:
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user