@dpa-oss/dpa 1.0.0 → 1.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/contracts/DPA.sol +58 -24
- package/package.json +1 -1
package/contracts/DPA.sol
CHANGED
|
@@ -26,8 +26,8 @@ abstract contract DPA is ERC721A, Ownable, Pausable, ReentrancyGuard {
|
|
|
26
26
|
/// @notice The orchestrator address (only this address can mint/revise)
|
|
27
27
|
address public orchestrator;
|
|
28
28
|
|
|
29
|
-
/// @dev Token ID -> Token
|
|
30
|
-
mapping(uint256 => string) private
|
|
29
|
+
/// @dev Token ID -> Token CID (Content Identifier)
|
|
30
|
+
mapping(uint256 => string) private _tokenCIDs;
|
|
31
31
|
|
|
32
32
|
/// @dev Token ID -> Token content (encoded bytes, decoded by implementers)
|
|
33
33
|
mapping(uint256 => bytes) private _tokenContents;
|
|
@@ -47,10 +47,13 @@ abstract contract DPA is ERC721A, Ownable, Pausable, ReentrancyGuard {
|
|
|
47
47
|
/// @dev Counter for total unique digital public assets (origin tokens only)
|
|
48
48
|
uint256 private _totalAssets;
|
|
49
49
|
|
|
50
|
+
/// @dev Base URI for token metadata (used when individual URI is not set)
|
|
51
|
+
string private _baseTokenURI;
|
|
52
|
+
|
|
50
53
|
// ============ Events ============
|
|
51
54
|
|
|
52
55
|
/// @notice Emitted when a new token is minted
|
|
53
|
-
event TokenMinted(uint256 indexed tokenId, address indexed to, string
|
|
56
|
+
event TokenMinted(uint256 indexed tokenId, address indexed to, string cid);
|
|
54
57
|
|
|
55
58
|
/// @notice Emitted when tokens are batch minted
|
|
56
59
|
event BatchMinted(
|
|
@@ -73,6 +76,9 @@ abstract contract DPA is ERC721A, Ownable, Pausable, ReentrancyGuard {
|
|
|
73
76
|
address indexed newOrchestrator
|
|
74
77
|
);
|
|
75
78
|
|
|
79
|
+
/// @notice Emitted when base URI is updated
|
|
80
|
+
event BaseURIUpdated(string previousURI, string newURI);
|
|
81
|
+
|
|
76
82
|
/// @notice Emitted when a DPA contract is linked to a token
|
|
77
83
|
event DPALinked(
|
|
78
84
|
uint256 indexed tokenId,
|
|
@@ -156,18 +162,36 @@ abstract contract DPA is ERC721A, Ownable, Pausable, ReentrancyGuard {
|
|
|
156
162
|
_unpause();
|
|
157
163
|
}
|
|
158
164
|
|
|
165
|
+
/**
|
|
166
|
+
* @notice Sets the base URI for token metadata
|
|
167
|
+
* @param baseURI_ New base URI (can be empty to disable)
|
|
168
|
+
*/
|
|
169
|
+
function setBaseURI(string calldata baseURI_) external onlyOwner {
|
|
170
|
+
string memory previous = _baseTokenURI;
|
|
171
|
+
_baseTokenURI = baseURI_;
|
|
172
|
+
emit BaseURIUpdated(previous, baseURI_);
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* @notice Returns the current base URI
|
|
177
|
+
* @return The base URI string
|
|
178
|
+
*/
|
|
179
|
+
function baseURI() external view returns (string memory) {
|
|
180
|
+
return _baseTokenURI;
|
|
181
|
+
}
|
|
182
|
+
|
|
159
183
|
// ============ Minting Functions ============
|
|
160
184
|
|
|
161
185
|
/**
|
|
162
|
-
* @notice Mints a single token with
|
|
186
|
+
* @notice Mints a single token with CID and content
|
|
163
187
|
* @param to Recipient address
|
|
164
|
-
* @param
|
|
188
|
+
* @param cid Token CID (metadata CID)
|
|
165
189
|
* @param content Encoded content data (decoded by derived contract)
|
|
166
190
|
* @return tokenId The minted token ID
|
|
167
191
|
*/
|
|
168
192
|
function mint(
|
|
169
193
|
address to,
|
|
170
|
-
string calldata
|
|
194
|
+
string calldata cid,
|
|
171
195
|
bytes calldata content
|
|
172
196
|
)
|
|
173
197
|
external
|
|
@@ -184,8 +208,8 @@ abstract contract DPA is ERC721A, Ownable, Pausable, ReentrancyGuard {
|
|
|
184
208
|
// Mint the token
|
|
185
209
|
_mint(to, 1);
|
|
186
210
|
|
|
187
|
-
// Store
|
|
188
|
-
|
|
211
|
+
// Store CID and content
|
|
212
|
+
_tokenCIDs[tokenId] = cid;
|
|
189
213
|
_tokenContents[tokenId] = content;
|
|
190
214
|
|
|
191
215
|
// Create initial revision record (no parent, version 1)
|
|
@@ -201,21 +225,21 @@ abstract contract DPA is ERC721A, Ownable, Pausable, ReentrancyGuard {
|
|
|
201
225
|
// Increment total unique assets counter
|
|
202
226
|
_totalAssets++;
|
|
203
227
|
|
|
204
|
-
emit TokenMinted(tokenId, to,
|
|
228
|
+
emit TokenMinted(tokenId, to, cid);
|
|
205
229
|
}
|
|
206
230
|
|
|
207
231
|
/**
|
|
208
232
|
* @notice Mints a single token with explicit owner specification
|
|
209
233
|
* @param to Recipient address
|
|
210
234
|
* @param owner_ Token owner for record
|
|
211
|
-
* @param
|
|
235
|
+
* @param cid Token CID (metadata CID)
|
|
212
236
|
* @param content Encoded content data
|
|
213
237
|
* @return tokenId The minted token ID
|
|
214
238
|
*/
|
|
215
239
|
function mintWithOwner(
|
|
216
240
|
address to,
|
|
217
241
|
address owner_,
|
|
218
|
-
string calldata
|
|
242
|
+
string calldata cid,
|
|
219
243
|
bytes calldata content
|
|
220
244
|
)
|
|
221
245
|
external
|
|
@@ -229,7 +253,7 @@ abstract contract DPA is ERC721A, Ownable, Pausable, ReentrancyGuard {
|
|
|
229
253
|
_validateContent(content);
|
|
230
254
|
_mint(to, 1);
|
|
231
255
|
|
|
232
|
-
|
|
256
|
+
_tokenCIDs[tokenId] = cid;
|
|
233
257
|
_tokenContents[tokenId] = content;
|
|
234
258
|
|
|
235
259
|
_revisions[tokenId] = Types.RevisionRecord({
|
|
@@ -244,19 +268,19 @@ abstract contract DPA is ERC721A, Ownable, Pausable, ReentrancyGuard {
|
|
|
244
268
|
// Increment total unique assets counter
|
|
245
269
|
_totalAssets++;
|
|
246
270
|
|
|
247
|
-
emit TokenMinted(tokenId, to,
|
|
271
|
+
emit TokenMinted(tokenId, to, cid);
|
|
248
272
|
}
|
|
249
273
|
|
|
250
274
|
/**
|
|
251
275
|
* @notice Batch mints tokens with URIs and contents
|
|
252
276
|
* @param to Recipient address (same for all tokens in batch)
|
|
253
|
-
* @param
|
|
277
|
+
* @param cids Array of token CIDs
|
|
254
278
|
* @param contents Array of encoded content data
|
|
255
279
|
* @return startTokenId The first token ID in the batch
|
|
256
280
|
*/
|
|
257
281
|
function batchMint(
|
|
258
282
|
address to,
|
|
259
|
-
string[] calldata
|
|
283
|
+
string[] calldata cids,
|
|
260
284
|
bytes[] calldata contents
|
|
261
285
|
)
|
|
262
286
|
external
|
|
@@ -265,7 +289,7 @@ abstract contract DPA is ERC721A, Ownable, Pausable, ReentrancyGuard {
|
|
|
265
289
|
nonReentrant
|
|
266
290
|
returns (uint256 startTokenId)
|
|
267
291
|
{
|
|
268
|
-
uint256 quantity =
|
|
292
|
+
uint256 quantity = cids.length;
|
|
269
293
|
|
|
270
294
|
if (quantity != contents.length) {
|
|
271
295
|
revert Errors.ArrayLengthMismatch();
|
|
@@ -287,7 +311,7 @@ abstract contract DPA is ERC721A, Ownable, Pausable, ReentrancyGuard {
|
|
|
287
311
|
// Store URIs, contents, and create revision records
|
|
288
312
|
for (uint256 i = 0; i < quantity; i++) {
|
|
289
313
|
uint256 tokenId = startTokenId + i;
|
|
290
|
-
|
|
314
|
+
_tokenCIDs[tokenId] = cids[i];
|
|
291
315
|
_tokenContents[tokenId] = contents[i];
|
|
292
316
|
|
|
293
317
|
_revisions[tokenId] = Types.RevisionRecord({
|
|
@@ -299,7 +323,7 @@ abstract contract DPA is ERC721A, Ownable, Pausable, ReentrancyGuard {
|
|
|
299
323
|
actor: msg.sender
|
|
300
324
|
});
|
|
301
325
|
|
|
302
|
-
emit TokenMinted(tokenId, to,
|
|
326
|
+
emit TokenMinted(tokenId, to, cids[i]);
|
|
303
327
|
}
|
|
304
328
|
|
|
305
329
|
// Increment total unique assets counter by batch size
|
|
@@ -313,14 +337,14 @@ abstract contract DPA is ERC721A, Ownable, Pausable, ReentrancyGuard {
|
|
|
313
337
|
/**
|
|
314
338
|
* @notice Creates a new revision of an existing token (protocol-enforced)
|
|
315
339
|
* @param parentTokenId The token being revised (must be latest version)
|
|
316
|
-
* @param
|
|
340
|
+
* @param cid New token CID
|
|
317
341
|
* @param content New encoded content
|
|
318
342
|
* @param reason Human-readable reason (stored as hash, emitted in full)
|
|
319
343
|
* @return newTokenId The newly minted revision token
|
|
320
344
|
*/
|
|
321
345
|
function revise(
|
|
322
346
|
uint256 parentTokenId,
|
|
323
|
-
string calldata
|
|
347
|
+
string calldata cid,
|
|
324
348
|
bytes calldata content,
|
|
325
349
|
string calldata reason
|
|
326
350
|
)
|
|
@@ -330,7 +354,7 @@ abstract contract DPA is ERC721A, Ownable, Pausable, ReentrancyGuard {
|
|
|
330
354
|
nonReentrant
|
|
331
355
|
returns (uint256 newTokenId)
|
|
332
356
|
{
|
|
333
|
-
newTokenId = _revise(parentTokenId,
|
|
357
|
+
newTokenId = _revise(parentTokenId, cid, content, reason);
|
|
334
358
|
}
|
|
335
359
|
|
|
336
360
|
/**
|
|
@@ -338,7 +362,7 @@ abstract contract DPA is ERC721A, Ownable, Pausable, ReentrancyGuard {
|
|
|
338
362
|
*/
|
|
339
363
|
function _revise(
|
|
340
364
|
uint256 parentTokenId,
|
|
341
|
-
string calldata
|
|
365
|
+
string calldata cid,
|
|
342
366
|
bytes calldata content,
|
|
343
367
|
string calldata reason
|
|
344
368
|
) internal onlyLatestVersion(parentTokenId) returns (uint256 newTokenId) {
|
|
@@ -353,7 +377,7 @@ abstract contract DPA is ERC721A, Ownable, Pausable, ReentrancyGuard {
|
|
|
353
377
|
_mint(parentOwner, 1);
|
|
354
378
|
|
|
355
379
|
// Store new token data
|
|
356
|
-
|
|
380
|
+
_tokenCIDs[newTokenId] = cid;
|
|
357
381
|
_tokenContents[newTokenId] = content;
|
|
358
382
|
|
|
359
383
|
// Find origin token (root of chain)
|
|
@@ -394,7 +418,17 @@ abstract contract DPA is ERC721A, Ownable, Pausable, ReentrancyGuard {
|
|
|
394
418
|
if (!_exists(tokenId)) {
|
|
395
419
|
revert Errors.InvalidTokenId();
|
|
396
420
|
}
|
|
397
|
-
|
|
421
|
+
|
|
422
|
+
string memory _tokenCID = _tokenCIDs[tokenId];
|
|
423
|
+
string memory base = _baseTokenURI;
|
|
424
|
+
|
|
425
|
+
// If base URI is set, concatenate with token path/CID
|
|
426
|
+
if (bytes(base).length > 0 && bytes(_tokenCID).length > 0) {
|
|
427
|
+
return string(abi.encodePacked(base, _tokenCID));
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
// Return token CID as-is (full URI or path)
|
|
431
|
+
return _tokenCID;
|
|
398
432
|
}
|
|
399
433
|
|
|
400
434
|
/**
|