Skip to content

Commit e62cd31

Browse files
committed
Refactor ERC404NullOwnerCappedUpgradeable contract by removing IERC404 interface and DoubleEndedQueue library. Simplified function overrides for ERC20 and ERC721 operations, enhancing clarity and maintainability. Updated storage accessor and error handling for improved functionality.
1 parent e9175b8 commit e62cd31

File tree

3 files changed

+34
-401
lines changed

3 files changed

+34
-401
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)