Skip to content

Commit 8e05a5b

Browse files
authored
Merge pull request #10 from Haroldwonder/docs/natspec-libs
docs: add NatSpec documentation for ERC20 and ERC721 libraries
2 parents 14bccf3 + afb3334 commit 8e05a5b

File tree

3 files changed

+176
-68
lines changed

3 files changed

+176
-68
lines changed

src/ERC20/ERC20/libraries/LibERC20.sol

Lines changed: 49 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,38 +1,69 @@
11
// SPDX-License-Identifier: MIT
22
pragma solidity >=0.8.30;
33

4+
/// @title LibERC20 — ERC-20 Library
5+
/// @notice Provides internal functions and storage layout for ERC-20 token logic.
6+
/// @dev Uses ERC-8042 for storage location standardization and ERC-6093 for error conventions.
47
library LibERC20 {
58

6-
// ERC-6093: Custom errors for ERC-20
9+
10+
/// @notice Thrown when a sender attempts to transfer or burn more tokens than their balance.
11+
/// @param _sender The address attempting the transfer or burn.
12+
/// @param _balance The sender's current balance.
13+
/// @param _needed The amount required to complete the operation.
714
error ERC20InsufficientBalance(address _sender, uint256 _balance, uint256 _needed);
15+
16+
/// @notice Thrown when the sender address is invalid (e.g., zero address).
17+
/// @param _sender The invalid sender address.
818
error ERC20InvalidSender(address _sender);
19+
20+
/// @notice Thrown when the receiver address is invalid (e.g., zero address).
21+
/// @param _receiver The invalid receiver address.
922
error ERC20InvalidReceiver(address _receiver);
23+
24+
/// @notice Thrown when a spender tries to spend more than their allowance.
25+
/// @param _spender The address attempting to spend.
26+
/// @param _allowance The current allowance.
27+
/// @param _needed The required amount to complete the transfer.
1028
error ERC20InsufficientAllowance(address _spender, uint256 _allowance, uint256 _needed);
29+
1130

31+
/// @notice Emitted when tokens are transferred between addresses.
32+
/// @param _from The address tokens are transferred from.
33+
/// @param _to The address tokens are transferred to.
34+
/// @param _value The amount of tokens transferred.
1235
event Transfer(address indexed _from, address indexed _to, uint256 _value);
13-
14-
// Struct storage position defined by keccak256 hash
15-
// of diamond storage identifier
36+
37+
38+
/// @notice Storage slot identifier, defined using keccak256 hash of the library diamond storage identifier.
1639
bytes32 constant STORAGE_POSITION = keccak256("compose.erc20");
1740

18-
// Storage defined using the ERC-8042 standard
19-
// @custom:storage-location erc8042:compose.erc20
41+
/// @notice ERC-20 storage layout using the ERC-8042 standard.
42+
/// @custom:storage-location erc8042:compose.erc20
2043
struct ERC20Storage {
2144
string name;
2245
string symbol;
2346
uint8 decimals;
2447
uint256 totalSupply;
2548
mapping(address owner => uint256 balance) balanceOf;
26-
mapping(address owner => mapping(address spender => uint256 allowance)) allowances;
49+
mapping(address owner => mapping(address spender => uint256 allowance)) allowances;
2750
}
2851

52+
53+
/// @notice Returns a pointer to the ERC-20 storage struct.
54+
/// @dev Uses inline assembly to bind the storage struct to the fixed storage position.
55+
/// @return s The ERC-20 storage struct.
2956
function getStorage() internal pure returns (ERC20Storage storage s) {
3057
bytes32 position = STORAGE_POSITION;
3158
assembly {
3259
s.slot := position
3360
}
34-
}
61+
}
3562

63+
/// @notice Mints new tokens to a specified address.
64+
/// @dev Increases both total supply and the recipient’s balance.
65+
/// @param _account The address receiving the newly minted tokens.
66+
/// @param _value The number of tokens to mint.
3667
function mint(address _account, uint256 _value) internal {
3768
ERC20Storage storage s = getStorage();
3869
if (_account == address(0)) {
@@ -45,6 +76,10 @@ library LibERC20 {
4576
emit Transfer(address(0), _account, _value);
4677
}
4778

79+
/// @notice Burns tokens from a specified address.
80+
/// @dev Decreases both total supply and the sender’s balance.
81+
/// @param _account The address whose tokens will be burned.
82+
/// @param _value The number of tokens to burn.
4883
function burn(address _account, uint256 _value) internal {
4984
ERC20Storage storage s = getStorage();
5085
if (_account == address(0)) {
@@ -61,6 +96,11 @@ library LibERC20 {
6196
emit Transfer(_account, address(0), _value);
6297
}
6398

99+
/// @notice Transfers tokens from one address to another using an allowance.
100+
/// @dev Deducts the spender’s allowance and updates balances.
101+
/// @param _from The address to send tokens from.
102+
/// @param _to The address to send tokens to.
103+
/// @param _value The number of tokens to transfer.
64104
function transferFrom(address _from, address _to, uint256 _value) internal {
65105
ERC20Storage storage s = getStorage();
66106
if (_from == address(0)) {
@@ -84,6 +124,4 @@ library LibERC20 {
84124
}
85125
emit Transfer(_from, _to, _value);
86126
}
87-
88-
89-
}
127+
}
Lines changed: 53 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,42 +1,74 @@
11
// SPDX-License-Identifier: MIT
22
pragma solidity >=0.8.30;
33

4+
/// @title ERC-721 Library for Compose
5+
/// @notice Provides internal logic for ERC-721 token management using diamond storage.
6+
/// @dev Implements minting, burning, and transferring of ERC-721 tokens without dependencies.
7+
/// Uses ERC-8042-compliant storage definition and includes ERC-6093 standard custom errors.
48
library LibERC721 {
59

6-
// ERC-6093: Custom errors for ERC-721
7-
error ERC721NonexistentToken(uint256 _tokenId);
10+
/// @notice Thrown when attempting to interact with a non-existent token.
11+
/// @param _tokenId The ID of the token that does not exist.
12+
error ERC721NonexistentToken(uint256 _tokenId);
13+
14+
/// @notice Thrown when the sender is not the owner of the token.
15+
/// @param _sender The address attempting the operation.
16+
/// @param _tokenId The ID of the token being transferred.
17+
/// @param _owner The actual owner of the token.
818
error ERC721IncorrectOwner(address _sender, uint256 _tokenId, address _owner);
19+
20+
/// @notice Thrown when the sender address is invalid (e.g., zero address).
21+
/// @param _sender The invalid sender address.
922
error ERC721InvalidSender(address _sender);
23+
24+
/// @notice Thrown when the receiver address is invalid (e.g., zero address).
25+
/// @param _receiver The invalid receiver address.
1026
error ERC721InvalidReceiver(address _receiver);
27+
28+
/// @notice Thrown when an operator lacks sufficient approval to manage a token.
29+
/// @param _operator The address attempting the unauthorized operation.
30+
/// @param _tokenId The ID of the token involved.
1131
error ERC721InsufficientApproval(address _operator, uint256 _tokenId);
1232

33+
/// @notice Emitted when ownership of a token changes, including minting and burning.
34+
/// @param _from The address transferring the token, or zero for minting.
35+
/// @param _to The address receiving the token, or zero for burning.
36+
/// @param _tokenId The ID of the token being transferred.
1337
event Transfer(address indexed _from, address indexed _to, uint256 indexed _tokenId);
14-
15-
// Struct storage position defined by keccak256 hash
16-
// of diamond storage identifier
38+
39+
/// @dev Storage position constant defined via keccak256 hash of diamond storage identifier.
1740
bytes32 constant STORAGE_POSITION = keccak256("compose.erc721");
1841

19-
// Storage defined using the ERC-8042 standard
20-
// @custom:storage-location erc8042:compose.erc721
42+
/// @custom:storage-location erc8042:compose.erc721
43+
/// @notice Storage layout for ERC-721 token management.
44+
/// @dev Defines ownership, balances, approvals, and operator mappings per ERC-721 standard.
2145
struct ERC721Storage {
2246
string name;
23-
string symbol;
47+
string symbol;
2448
mapping(uint256 tokenId => address owner) ownerOf;
2549
mapping(address owner => uint256 balance) balanceOf;
2650
mapping(uint256 tokenId => address approved) approved;
27-
mapping(address owner => mapping(address operator => bool approved)) isApprovedForAll;
51+
mapping(address owner => mapping(address operator => bool approved)) isApprovedForAll;
2852
}
2953

54+
/// @notice Returns the ERC-721 storage struct from its predefined slot.
55+
/// @dev Uses inline assembly to access diamond storage location.
56+
/// @return s The storage reference for ERC-721 state variables.
3057
function getStorage() internal pure returns (ERC721Storage storage s) {
3158
bytes32 position = STORAGE_POSITION;
3259
assembly {
3360
s.slot := position
3461
}
3562
}
3663

64+
/// @notice Transfers ownership of a token ID from one address to another.
65+
/// @dev Validates ownership, approval, and receiver address before updating state.
66+
/// @param _from The current owner of the token.
67+
/// @param _to The address that will receive the token.
68+
/// @param _tokenId The ID of the token being transferred.
3769
function transferFrom(address _from, address _to, uint256 _tokenId) internal {
3870
ERC721Storage storage s = getStorage();
39-
if (_to == address(0)) {
71+
if (_to == address(0)) {
4072
revert ERC721InvalidReceiver(address(0));
4173
}
4274
address owner = s.ownerOf[_tokenId];
@@ -45,9 +77,9 @@ library LibERC721 {
4577
}
4678
if (owner != _from) {
4779
revert ERC721IncorrectOwner(_from, _tokenId, owner);
48-
}
80+
}
4981
if (msg.sender != _from) {
50-
if(!s.isApprovedForAll[_from][msg.sender] && msg.sender != s.approved[_tokenId]) {
82+
if (!s.isApprovedForAll[_from][msg.sender] && msg.sender != s.approved[_tokenId]) {
5183
revert ERC721InsufficientApproval(msg.sender, _tokenId);
5284
}
5385
}
@@ -56,10 +88,14 @@ library LibERC721 {
5688
s.balanceOf[_from]--;
5789
s.balanceOf[_to]++;
5890
}
59-
s.ownerOf[_tokenId] = _to;
91+
s.ownerOf[_tokenId] = _to;
6092
emit Transfer(_from, _to, _tokenId);
6193
}
6294

95+
/// @notice Mints a new ERC-721 token to the specified address.
96+
/// @dev Reverts if the receiver address is zero or if the token already exists.
97+
/// @param _to The address that will own the newly minted token.
98+
/// @param _tokenId The ID of the token to mint.
6399
function mint(address _to, uint256 _tokenId) internal {
64100
ERC721Storage storage s = getStorage();
65101
if (_to == address(0)) {
@@ -75,6 +111,9 @@ library LibERC721 {
75111
emit Transfer(address(0), _to, _tokenId);
76112
}
77113

114+
/// @notice Burns (destroys) a specific ERC-721 token.
115+
/// @dev Reverts if the token does not exist. Clears ownership and approval.
116+
/// @param _tokenId The ID of the token to burn.
78117
function burn(uint256 _tokenId) internal {
79118
ERC721Storage storage s = getStorage();
80119
address owner = s.ownerOf[_tokenId];
@@ -88,7 +127,4 @@ library LibERC721 {
88127
}
89128
emit Transfer(owner, address(0), _tokenId);
90129
}
91-
92-
93-
94-
}
130+
}

0 commit comments

Comments
 (0)