Skip to content

Commit 870e2e1

Browse files
committed
Refactor ERC404NullOwnerCappedUpgradeable contract by removing unused interfaces and dependencies
- Deleted the `IERC404` interface and the `DoubleEndedQueue` library, simplifying the contract structure. - Updated function signatures to remove references to the deleted interface, ensuring compliance with ERC20 and ERC721 standards. - Streamlined the contract by eliminating unnecessary state variables and constants, enhancing readability and maintainability. - Adjusted event emissions and error handling to align with the new implementation.
1 parent e9175b8 commit 870e2e1

File tree

4 files changed

+283
-404
lines changed

4 files changed

+283
-404
lines changed

contracts/src/ERC404NullOwnerCappedUpgradeable.sol

Lines changed: 34 additions & 126 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,10 @@ pragma solidity 0.8.24;
33

44
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
55
import {IERC20Metadata} from "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
6-
import {IERC721Receiver} from "@openzeppelin/contracts/interfaces/IERC721Receiver.sol";
76
import {ContextUpgradeable} from "@openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol";
87
import {IERC20Errors} from "@openzeppelin/contracts/interfaces/draft-IERC6093.sol";
98
import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
109
import {IERC165} from "@openzeppelin/contracts/interfaces/IERC165.sol";
11-
import "./interfaces/IERC404.sol";
12-
import "./lib/DoubleEndedQueue.sol";
1310

1411
/// @title ERC404NullOwnerCappedUpgradeable
1512
/// @notice Hybrid ERC20/ERC721 implementation with null owner support, supply cap, and upgradeability
@@ -20,11 +17,8 @@ abstract contract ERC404NullOwnerCappedUpgradeable is
2017
IERC165,
2118
IERC20,
2219
IERC20Metadata,
23-
IERC20Errors,
24-
IERC404
20+
IERC20Errors
2521
{
26-
using DoubleEndedQueue for DoubleEndedQueue.Uint256Deque;
27-
2822
struct TokenData {
2923
address owner; // current owner (can be address(0) for null-owner)
3024
uint88 index; // position in owned[owner] array
@@ -43,44 +37,26 @@ abstract contract ERC404NullOwnerCappedUpgradeable is
4337
uint256 totalSupply;
4438
uint256 cap;
4539

46-
// === ERC404 NFT State ===
47-
DoubleEndedQueue.Uint256Deque storedERC721Ids;
4840
mapping(address => uint256[]) owned;
4941
mapping(uint256 => TokenData) tokens;
5042
mapping(uint256 => address) getApproved;
5143
mapping(address => mapping(address => bool)) isApprovedForAll;
52-
mapping(address => bool) erc721TransferExempt;
5344
uint256 minted; // Number of NFTs minted
5445
uint256 units; // Units for NFT minting (e.g., 1000 * 10^18)
55-
uint256 initialChainId;
56-
bytes32 initialDomainSeparator;
57-
mapping(address => uint256) nonces;
5846

5947
// === Metadata ===
6048
string name;
6149
string symbol;
6250
}
63-
64-
// =============================================================
65-
// CONSTANTS
66-
// =============================================================
67-
68-
/// @dev Unique storage slot for EIP-7201 namespaced storage
69-
/// keccak256(abi.encode(uint256(keccak256("ethscriptions.storage.ERC404NullOwnerCapped")) - 1)) & ~bytes32(uint256(0xff))
70-
bytes32 private constant STORAGE_LOCATION = 0x8a0c9d8e5f7b3a2c1d4e6f8a9b7c5d3e2f1a4b6c8d9e7f5a3b2c1d4e6f8a9b00;
71-
51+
7252
// =============================================================
7353
// EVENTS
7454
// =============================================================
7555

7656
// ERC20 Events are inherited from IERC20 (Transfer, Approval)
7757

7858
// ERC721 Events (using different names to avoid conflicts with ERC20)
79-
// event Transfer(address indexed from, address indexed to, uint256 value);
80-
event ERC20Transfer(address indexed from, address indexed to, uint256 value);
8159
event ERC721Transfer(address indexed from, address indexed to, uint256 indexed id);
82-
event ERC721Approval(address indexed owner, address indexed spender, uint256 indexed id);
83-
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
8460

8561
// =============================================================
8662
// CUSTOM ERRORS
@@ -91,14 +67,22 @@ abstract contract ERC404NullOwnerCappedUpgradeable is
9167
error ERC20InvalidCap(uint256 cap);
9268
error InvalidUnits(uint256 units);
9369
error NotImplemented();
70+
error NotFound();
71+
error InvalidTokenId();
72+
error AlreadyExists();
73+
error InvalidRecipient();
74+
error Unauthorized();
75+
error OwnedIndexOverflow();
9476

9577
// =============================================================
9678
// STORAGE ACCESSOR
9779
// =============================================================
9880

9981
function _getS() internal pure returns (TokenStorage storage $) {
82+
bytes32 slot = keccak256("ethscriptions.storage.ERC404NullOwnerCapped");
83+
10084
assembly {
101-
$.slot := STORAGE_LOCATION
85+
$.slot := slot
10286
}
10387
}
10488

@@ -132,38 +116,36 @@ abstract contract ERC404NullOwnerCappedUpgradeable is
132116
$.symbol = symbol_;
133117
$.cap = cap_;
134118
$.units = units_;
135-
$.initialChainId = block.chainid;
136-
$.initialDomainSeparator = _computeDomainSeparator();
137119
}
138120

139121
// =============================================================
140122
// ERC20 METADATA VIEWS
141123
// =============================================================
142124

143-
function name() public view virtual override(IERC404, IERC20Metadata) returns (string memory) {
125+
function name() public view virtual override(IERC20Metadata) returns (string memory) {
144126
TokenStorage storage $ = _getS();
145127
return $.name;
146128
}
147129

148-
function symbol() public view virtual override(IERC404, IERC20Metadata) returns (string memory) {
130+
function symbol() public view virtual override(IERC20Metadata) returns (string memory) {
149131
TokenStorage storage $ = _getS();
150132
return $.symbol;
151133
}
152134

153-
function decimals() public pure override(IERC404, IERC20Metadata) returns (uint8) {
135+
function decimals() public pure override(IERC20Metadata) returns (uint8) {
154136
return 18;
155137
}
156138

157139
// =============================================================
158140
// ERC20 VIEWS
159141
// =============================================================
160142

161-
function totalSupply() public view virtual override(IERC404, IERC20) returns (uint256) {
143+
function totalSupply() public view virtual override returns (uint256) {
162144
TokenStorage storage $ = _getS();
163145
return $.totalSupply;
164146
}
165147

166-
function balanceOf(address account) public view virtual override(IERC404, IERC20) returns (uint256) {
148+
function balanceOf(address account) public view virtual override returns (uint256) {
167149
TokenStorage storage $ = _getS();
168150
return $.balances[account];
169151
}
@@ -179,7 +161,7 @@ abstract contract ERC404NullOwnerCappedUpgradeable is
179161
return t.owner == owner_ ? 1 : 0;
180162
}
181163

182-
function allowance(address owner, address spender) public view virtual override(IERC404, IERC20) returns (uint256) {
164+
function allowance(address owner, address spender) public view virtual override returns (uint256) {
183165
TokenStorage storage $ = _getS();
184166
return $.allowances[owner][spender];
185167
}
@@ -196,17 +178,17 @@ abstract contract ERC404NullOwnerCappedUpgradeable is
196178
// ERC721 VIEWS
197179
// =============================================================
198180

199-
function erc721TotalSupply() public view virtual override(IERC404) returns (uint256) {
181+
function erc721TotalSupply() public view virtual returns (uint256) {
200182
TokenStorage storage $ = _getS();
201183
return $.minted;
202184
}
203185

204-
function erc721BalanceOf(address owner_) public view virtual override(IERC404) returns (uint256) {
186+
function erc721BalanceOf(address owner_) public view virtual returns (uint256) {
205187
TokenStorage storage $ = _getS();
206188
return $.owned[owner_].length;
207189
}
208190

209-
function ownerOf(uint256 id_) public view virtual override(IERC404) returns (address) {
191+
function ownerOf(uint256 id_) public view virtual returns (address) {
210192
_validateTokenId(id_);
211193
TokenStorage storage $ = _getS();
212194
TokenData storage t = $.tokens[id_];
@@ -216,7 +198,7 @@ abstract contract ERC404NullOwnerCappedUpgradeable is
216198
return t.owner;
217199
}
218200

219-
function owned(address owner_) public view virtual override(IERC404) returns (uint256[] memory) {
201+
function owned(address owner_) public view virtual returns (uint256[] memory) {
220202
TokenStorage storage $ = _getS();
221203
return $.owned[owner_];
222204
}
@@ -229,42 +211,11 @@ abstract contract ERC404NullOwnerCappedUpgradeable is
229211
return $.getApproved[id_];
230212
}
231213

232-
function isApprovedForAll(address owner_, address operator_) public view virtual override(IERC404) returns (bool) {
214+
function isApprovedForAll(address owner_, address operator_) public view virtual returns (bool) {
233215
TokenStorage storage $ = _getS();
234216
return $.isApprovedForAll[owner_][operator_];
235217
}
236218

237-
function erc721TransferExempt(address account_) public view virtual override returns (bool) {
238-
TokenStorage storage $ = _getS();
239-
return $.erc721TransferExempt[account_];
240-
}
241-
242-
// =============================================================
243-
// QUEUE VIEWS
244-
// =============================================================
245-
246-
function getERC721QueueLength() public view virtual override returns (uint256) {
247-
TokenStorage storage $ = _getS();
248-
return $.storedERC721Ids.length();
249-
}
250-
251-
function getERC721TokensInQueue(
252-
uint256 start_,
253-
uint256 count_
254-
) public view virtual override returns (uint256[] memory) {
255-
TokenStorage storage $ = _getS();
256-
uint256[] memory tokensInQueue = new uint256[](count_);
257-
258-
for (uint256 i = start_; i < start_ + count_;) {
259-
tokensInQueue[i - start_] = $.storedERC721Ids.at(i);
260-
unchecked {
261-
++i;
262-
}
263-
}
264-
265-
return tokensInQueue;
266-
}
267-
268219
// =============================================================
269220
// OTHER VIEWS
270221
// =============================================================
@@ -285,57 +236,53 @@ abstract contract ERC404NullOwnerCappedUpgradeable is
285236
}
286237

287238
/// @notice tokenURI must be implemented by child contract
288-
function tokenURI(uint256 id_) public view virtual override(IERC404) returns (string memory);
239+
function tokenURI(uint256 id_) public view virtual returns (string memory);
289240

290241
// =============================================================
291242
// ERC20 OPERATIONS
292243
// =============================================================
293244

294-
function transfer(address, uint256) public pure virtual override(IERC404, IERC20) returns (bool) {
245+
function transfer(address, uint256) public pure virtual override returns (bool) {
295246
revert NotImplemented();
296247
}
297248

298-
function approve(address, uint256) public pure virtual override(IERC404, IERC20) returns (bool) {
249+
function approve(address, uint256) public pure virtual override returns (bool) {
299250
revert NotImplemented();
300251
}
301252

302-
function transferFrom(address, address, uint256) public pure virtual override(IERC404, IERC20) returns (bool) {
253+
function transferFrom(address, address, uint256) public pure virtual override returns (bool) {
303254
revert NotImplemented();
304255
}
305256

306-
function erc20Approve(address, uint256) public pure virtual override returns (bool) {
257+
function erc20Approve(address, uint256) public pure virtual returns (bool) {
307258
revert NotImplemented();
308259
}
309260

310-
function erc20TransferFrom(address, address, uint256) public pure virtual override returns (bool) {
261+
function erc20TransferFrom(address, address, uint256) public pure virtual returns (bool) {
311262
revert NotImplemented();
312263
}
313264

314265
// =============================================================
315266
// ERC721 OPERATIONS
316267
// =============================================================
317268

318-
function erc721Approve(address, uint256) public pure virtual override {
269+
function erc721Approve(address, uint256) public pure virtual {
319270
revert NotImplemented();
320271
}
321272

322-
function erc721TransferFrom(address, address, uint256) public pure virtual override {
273+
function erc721TransferFrom(address, address, uint256) public pure virtual {
323274
revert NotImplemented();
324275
}
325276

326-
function setApprovalForAll(address, bool) public pure virtual override {
277+
function setApprovalForAll(address, bool) public pure virtual {
327278
revert NotImplemented();
328279
}
329280

330-
function safeTransferFrom(address, address, uint256) public pure virtual override {
281+
function safeTransferFrom(address, address, uint256) public pure virtual {
331282
revert NotImplemented();
332283
}
333284

334-
function safeTransferFrom(address, address, uint256, bytes memory) public pure virtual override {
335-
revert NotImplemented();
336-
}
337-
338-
function setSelfERC721TransferExempt(bool) public pure virtual override {
285+
function safeTransferFrom(address, address, uint256, bytes memory) public pure virtual {
339286
revert NotImplemented();
340287
}
341288

@@ -367,7 +314,6 @@ abstract contract ERC404NullOwnerCappedUpgradeable is
367314
}
368315

369316
emit Transfer(from_, to_, value_);
370-
// emit ERC20Transfer(from_, to_, value_);
371317
}
372318

373319
/// @notice Transfer an ERC721 token
@@ -454,44 +400,6 @@ abstract contract ERC404NullOwnerCappedUpgradeable is
454400
return
455401
interfaceId == type(IERC165).interfaceId ||
456402
interfaceId == type(IERC20).interfaceId ||
457-
interfaceId == type(IERC20Metadata).interfaceId ||
458-
interfaceId == type(IERC404).interfaceId;
459-
}
460-
461-
/// @notice Internal function to compute domain separator for EIP-2612 permits
462-
function _computeDomainSeparator() internal view virtual returns (bytes32) {
463-
return
464-
keccak256(
465-
abi.encode(
466-
keccak256(
467-
"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"
468-
),
469-
keccak256(bytes(name())),
470-
keccak256("1"),
471-
block.chainid,
472-
address(this)
473-
)
474-
);
475-
}
476-
477-
function permit(
478-
address owner_,
479-
address spender_,
480-
uint256 value_,
481-
uint256 deadline_,
482-
uint8 v_,
483-
bytes32 r_,
484-
bytes32 s_
485-
) public virtual {
486-
revert NotImplemented();
487-
}
488-
489-
/// @notice EIP-2612 domain separator
490-
function DOMAIN_SEPARATOR() public view virtual returns (bytes32) {
491-
TokenStorage storage $ = _getS();
492-
return
493-
block.chainid == $.initialChainId
494-
? $.initialDomainSeparator
495-
: _computeDomainSeparator();
403+
interfaceId == type(IERC20Metadata).interfaceId;
496404
}
497405
}

0 commit comments

Comments
 (0)