-
Notifications
You must be signed in to change notification settings - Fork 6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[DOCS] Add clarifications to mapping type #7100
Conversation
docs/types/mapping-types.rst
Outdated
|
||
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 integer value to an Ethereum address. As ``uint`` is a value type, the getter |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Mapping an address to an unsigned integer.
3d1bc27
to
9d73c76
Compare
@chriseth I understand your last comment, and I understand the principles, but as this was the content that was already there, I'm struggling slightly to explain it better. The pseudo syntax refers to the earlier paragraph, and I am hoping that the example (and explanation) help explain it… |
9d73c76
to
87dbebf
Compare
docs/types/mapping-types.rst
Outdated
@@ -4,7 +4,7 @@ | |||
Mapping Types | |||
============= | |||
|
|||
You declare mapping types with the syntax ``mapping(_KeyType => _ValueType)``. | |||
You declare mapping types with the syntax ``mapping(_KeyType => _ValueType) _VariableModifiers _VariableName``. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is how you declare a variable of mapping type, not how you declare a mapping type.
Maybe declare
is also the wrong word, use
may be better.
docs/types/mapping-types.rst
Outdated
: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``. | ||
:ref:`getter <visibility-and-getters>` for you. The ``_KeyType`` is the parameter for the getter. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please keep "becomes a", because it may not be the only parameter.
87dbebf
to
2871985
Compare
Changes made |
@@ -4,7 +4,8 @@ | |||
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``. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's probably not too useful to keep this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I still do not think it is useful to keep this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Which bit? It was here already, and from the conversations I've had around, people are really confused by the mapping syntax, so I'd love to try and be as explicit and clear as possible. Any suggestions to keep that clarity but express it differently?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it would be better to give an example how to declare a specific variable instead of just adding random placeholders whose meaning is not explained.
2871985
to
076f0dc
Compare
point to remember are that the mapping inside the mapping is not a return variable, | ||
but the variable inside it is. | ||
|
||
:: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
looks good!
docs/types/mapping-types.rst
Outdated
@@ -52,6 +58,34 @@ each ``_KeyType``, recursively. For example with a mapping: | |||
} | |||
} | |||
|
|||
The example below uses a mapping type inside another mapping type. The important | |||
point to remember are that the mapping inside the mapping is not a return variable, | |||
but the variable inside it is. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"value" instead of 'variable' for both?
docs/types/mapping-types.rst
Outdated
function f() public returns (bool) { | ||
MappingExample m = new MappingExample(); | ||
m.transfer(address(this),address(this)); | ||
return m.validBalances(address(this),address(this)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
return m.validBalances(address(this),address(this)); | |
return m.validBalances(address(this), address(this)); |
docs/types/mapping-types.rst
Outdated
pragma solidity >=0.4.0 <0.7.0; | ||
|
||
contract MappingExample { | ||
mapping(address => mapping(address => bool)) public validBalances; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doesn't erc20 use something like allowances
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It does, but I'm not sure what you mean? This isn't really an ERC20 implementation, and the data structure here is different too.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, it's exactly the same - and I think it would be a good example: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/token/ERC20/ERC20.sol#L36
@chriseth Made changes, i think I corrected another code error too. |
Tests are failing. |
8f2d068
to
6ea5578
Compare
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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Isn't it mapping the address to the uint?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think that is what I was trying to say, but I'll make it clearer.
|
||
pragma solidity >=0.4.0 <0.7.0; | ||
|
||
contract MappingExample { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you think a full credit / allowance example would be too long?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@chriseth Possibly, but how much do you think the full example relates to mappings and how they work? Or maybe a reduced example of what you suggest that highlights those aspects? I assume based on the Zeppelin link from above?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you can use the following functions and also slim them down a little:
- approve
- transferFrom
- allowances
967a3e1
to
08e26b4
Compare
docs/types/mapping-types.rst
Outdated
@@ -52,6 +58,34 @@ each ``_KeyType``, recursively. For example with a mapping: | |||
} | |||
} | |||
|
|||
The example below uses a mapping type inside another mapping type. The important | |||
point to remember are that the mapping inside the mapping is not the return value, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That should be The important point to remember is
not are
... but also: "the return value" of what? I'm not sure I understand the purpose of this sentence :-).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Corrected that. The point is to clarify that the returned value isn't the mapping inside the mapping, but the value inside the nested mapping. That's what I understood from you anyway?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When you're talking about "the returned value", you have to say what you are talking about that returns something - the index access of the outer mapping? The index access of the outer mapping in fact does return "the mapping inside the mapping" - only the second index access yields the value contained in the inner mapping...
contract C {
mapping(address => mapping(address => bool)) public allowances;
function f(address X, address Y) public view {
mapping(address => bool) storage allowancesForX = allowances[X]; // first index access is a mapping
bool allowanceForXandY = allowances[X][Y]; // two index accesses give the contained value
bool allowanceForXandY2 = allowancesForX[Y]; // which is the same as accessing the contained mapping at Y
assert(allowanceForXandY == allowanceForXandY2);
}
}
docs/types/mapping-types.rst
Outdated
|
||
function transferFrom(address sender, address recipient, uint256 amount) public returns (bool) { | ||
_transfer(sender, recipient, amount); | ||
_approve(sender, msg.sender, amount); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why do you call approve here? It should rather check that the allowance is large enough.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@chriseth This came from the Zeppelin code…
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But it does something else now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Needs to rebased since the failing test was fixed with #7419.
a391523
to
ddc9282
Compare
@erak Rebased, squashed |
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`` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"of that type" (how does a value match a type?)
docs/types/mapping-types.rst
Outdated
emit Transfer(sender, recipient, amount); | ||
} | ||
|
||
function _approve(address owner, address spender, uint256 amount) internal { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it is better to combine this function with approve
and handle the approval reduction in transferFrom manually.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is what you're asking for…
ddc9282
to
5884d78
Compare
5884d78
to
87367b4
Compare
Updates from review Changes from review Nested example Update docs/types/mapping-types.rst Co-Authored-By: chriseth <[email protected]> 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 <[email protected]> update code example
87367b4
to
0c51dcc
Compare
Rebased. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Still not sure about some details, but better to merge this.
Description
Closes #6303 by adding some description around the code example, and adding a link to the type when mentioned in other places.
Checklist