@dpa-oss/dpa 1.0.0

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.
@@ -0,0 +1,81 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity ^0.8.20;
3
+
4
+ import "../DPA.sol";
5
+
6
+ /**
7
+ * @title AssetDPA
8
+ * @dev Example implementation of the abstract DPA contract
9
+ * Demonstrates how to define a custom struct and decode content
10
+ */
11
+ contract AssetDPA is DPA {
12
+ /// @notice Asset type enumeration
13
+ enum AssetType {
14
+ Enum1,
15
+ Enum2
16
+ }
17
+
18
+ /// @notice Asset content structure
19
+ struct AssetContent {
20
+ uint256 amount;
21
+ AssetType assetType;
22
+ }
23
+
24
+ // ============ Events ============
25
+
26
+ /// @notice Emitted when asset content is decoded (for indexing)
27
+ event AssetContentStored(
28
+ uint256 indexed tokenId,
29
+ uint256 amount,
30
+ AssetType assetType
31
+ );
32
+
33
+ // ============ Constructor ============
34
+
35
+ /**
36
+ * @param orchestrator_ Initial orchestrator address
37
+ */
38
+ constructor(
39
+ address orchestrator_
40
+ ) DPA("Asset DPA", "ASSET-DPA", orchestrator_) {}
41
+
42
+ // ============ View Functions ============
43
+
44
+ /**
45
+ * @notice Decodes and returns the asset content for a token
46
+ * @param tokenId Token to query
47
+ * @return content The decoded AssetContent struct
48
+ */
49
+ function getAssetContent(
50
+ uint256 tokenId
51
+ ) external view returns (AssetContent memory content) {
52
+ bytes memory rawContent = this.tokenContent(tokenId);
53
+ content = abi.decode(rawContent, (AssetContent));
54
+ }
55
+
56
+ // ============ Internal Functions ============
57
+
58
+ /**
59
+ * @dev Validates that content can be decoded as AssetContent
60
+ * @param content The encoded content to validate
61
+ */
62
+ function _validateContent(bytes calldata content) internal pure override {
63
+ // Attempt to decode - will revert if invalid
64
+ abi.decode(content, (AssetContent));
65
+ }
66
+
67
+ // ============ Helper Functions ============
68
+
69
+ /**
70
+ * @notice Helper to encode AssetContent for minting
71
+ * @param amount The amount value
72
+ * @param assetType The asset type
73
+ * @return Encoded bytes
74
+ */
75
+ function encodeAssetContent(
76
+ uint256 amount,
77
+ AssetType assetType
78
+ ) external pure returns (bytes memory) {
79
+ return abi.encode(AssetContent({amount: amount, assetType: assetType}));
80
+ }
81
+ }
@@ -0,0 +1,50 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity ^0.8.20;
3
+
4
+ /**
5
+ * @title Errors
6
+ * @dev Unified error codes for DPA ecosystem
7
+ */
8
+ library Errors {
9
+ /// @dev Caller is not the orchestrator
10
+ error NotOrchestrator();
11
+
12
+ /// @dev Token does not exist
13
+ error InvalidTokenId();
14
+
15
+ /// @dev Revision chain violation
16
+ error InvalidRevision();
17
+
18
+ /// @dev Batch minting error
19
+ error BatchMintFailed();
20
+
21
+ /// @dev Arrays length mismatch
22
+ error ArrayLengthMismatch();
23
+
24
+ /// @dev Zero address provided
25
+ error ZeroAddress();
26
+
27
+ /// @dev Attempted to revise a token that is not the latest version
28
+ error NotLatestVersion();
29
+
30
+ /// @dev Link name already exists for this token
31
+ error DuplicateLinkName();
32
+
33
+ /// @dev Link name not found for this token
34
+ error LinkNotFound();
35
+
36
+ /// @dev Link name cannot be empty
37
+ error EmptyLinkName();
38
+
39
+ /// @dev Address is not a contract
40
+ error NotAContract();
41
+
42
+ /// @dev Cannot link to self
43
+ error SelfLink();
44
+
45
+ /// @dev Token burning is disabled
46
+ error BurnDisabled();
47
+
48
+ /// @dev Linked contract does not implement IDPA interface
49
+ error NotADPAContract();
50
+ }
@@ -0,0 +1,112 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity ^0.8.20;
3
+
4
+ import "./Types.sol";
5
+ import "@openzeppelin/contracts/utils/introspection/IERC165.sol";
6
+
7
+ /**
8
+ * @title IDPA
9
+ * @dev Interface for Digital Public Asset contracts
10
+ * Defines the standard functions for DPA implementations
11
+ * Extends IERC165 for interface detection
12
+ */
13
+ interface IDPA is IERC165 {
14
+ // ============ Admin Functions ============
15
+
16
+ /// @notice Returns the current orchestrator address
17
+ function orchestrator() external view returns (address);
18
+
19
+ /// @notice Updates the orchestrator address (owner only)
20
+ function setOrchestrator(address newOrchestrator) external;
21
+
22
+ /// @notice Pauses all minting and revision operations (owner only)
23
+ function pause() external;
24
+
25
+ /// @notice Unpauses all minting and revision operations (owner only)
26
+ function unpause() external;
27
+
28
+ // ============ Minting Functions ============
29
+
30
+ /// @notice Mints a single token with URI and content
31
+ function mint(
32
+ address to,
33
+ string calldata uri,
34
+ bytes calldata content
35
+ ) external returns (uint256 tokenId);
36
+
37
+ /// @notice Mints a single token with explicit owner specification
38
+ function mintWithOwner(
39
+ address to,
40
+ address owner_,
41
+ string calldata uri,
42
+ bytes calldata content
43
+ ) external returns (uint256 tokenId);
44
+
45
+ /// @notice Batch mints tokens with URIs and contents
46
+ function batchMint(
47
+ address to,
48
+ string[] calldata uris,
49
+ bytes[] calldata contents
50
+ ) external returns (uint256 startTokenId);
51
+
52
+ // ============ Revision Functions ============
53
+
54
+ /// @notice Creates a new revision of an existing token (protocol-enforced)
55
+ /// @param parentTokenId The token being revised (must be latest version)
56
+ /// @param uri New token URI
57
+ /// @param content New encoded content
58
+ /// @param reason Human-readable reason for revision
59
+ /// @return newTokenId The newly minted revision token
60
+ function revise(
61
+ uint256 parentTokenId,
62
+ string calldata uri,
63
+ bytes calldata content,
64
+ string calldata reason
65
+ ) external returns (uint256 newTokenId);
66
+
67
+ // ============ Query Functions ============
68
+
69
+ /// @notice Returns the token URI
70
+ function tokenURI(uint256 tokenId) external view returns (string memory);
71
+
72
+ /// @notice Returns the raw encoded content for a token
73
+ function tokenContent(uint256 tokenId) external view returns (bytes memory);
74
+
75
+ /// @notice Returns the revision record for a token
76
+ function getRevisionRecord(
77
+ uint256 tokenId
78
+ ) external view returns (Types.RevisionRecord memory);
79
+
80
+ /// @notice Returns the full revision chain from origin to the given token
81
+ function getRevisionChain(
82
+ uint256 tokenId
83
+ ) external view returns (uint256[] memory chain);
84
+
85
+ /// @notice Returns the latest version in a revision chain
86
+ function getLatestVersion(
87
+ uint256 originTokenId
88
+ ) external view returns (uint256 latestTokenId);
89
+
90
+ /// @notice Returns the child token of a given token (0 if none)
91
+ function getChildToken(
92
+ uint256 tokenId
93
+ ) external view returns (uint256 childTokenId);
94
+
95
+ /// @notice Returns the total count of unique digital public assets
96
+ function getTotalAssets() external view returns (uint256 total);
97
+
98
+ /// @notice Checks if a token is the latest version in its chain
99
+ function isLatestVersion(
100
+ uint256 tokenId
101
+ ) external view returns (bool isLatest);
102
+
103
+ /// @notice Returns the origin token ID for any token in a revision chain
104
+ function getOriginToken(
105
+ uint256 tokenId
106
+ ) external view returns (uint256 originTokenId);
107
+
108
+ /// @notice Returns the version number of a token
109
+ function getVersion(
110
+ uint256 tokenId
111
+ ) external view returns (uint256 version);
112
+ }
@@ -0,0 +1,18 @@
1
+ // SPDX-License-Identifier: MIT
2
+ pragma solidity ^0.8.20;
3
+
4
+ /**
5
+ * @title Types
6
+ * @dev Shared types for DPA ecosystem
7
+ */
8
+ library Types {
9
+ /// @dev Record of a revision in the linked list
10
+ struct RevisionRecord {
11
+ uint256 previousTokenId; // Parent revision (0 if origin)
12
+ uint256 originTokenId; // Root of the revision chain
13
+ uint256 version; // Version number (1 for origin, increments on each revision)
14
+ bytes32 reasonHash; // Keccak256 hash of reason (full reason in event)
15
+ uint256 timestamp; // When created
16
+ address actor; // Who created this
17
+ }
18
+ }
@@ -0,0 +1,23 @@
1
+ import { HardhatUserConfig } from "hardhat/config";
2
+ import "@nomicfoundation/hardhat-toolbox";
3
+ import "hardhat-gas-reporter";
4
+
5
+ const config: HardhatUserConfig = {
6
+ solidity: {
7
+ version: "0.8.20",
8
+ settings: {
9
+ optimizer: {
10
+ enabled: true,
11
+ runs: 200,
12
+ },
13
+ },
14
+ },
15
+ gasReporter: {
16
+ enabled: true,
17
+ currency: "USD",
18
+ outputFile: "gas-report.txt",
19
+ noColors: true,
20
+ },
21
+ };
22
+
23
+ export default config;
package/package.json ADDED
@@ -0,0 +1,24 @@
1
+ {
2
+ "name": "@dpa-oss/dpa",
3
+ "version": "1.0.0",
4
+ "scripts": {
5
+ "compile": "hardhat compile",
6
+ "test": "hardhat test",
7
+ "clean": "hardhat clean"
8
+ },
9
+ "keywords": [],
10
+ "author": "Jason Cruz",
11
+ "license": "ISC",
12
+ "description": "DPA (Digital Public Asset) Smart Contracts",
13
+ "devDependencies": {
14
+ "@nomicfoundation/hardhat-toolbox": "^4.0.0",
15
+ "@types/node": "^20.0.0",
16
+ "hardhat": "^2.22.0",
17
+ "hardhat-gas-reporter": "^2.3.0",
18
+ "typescript": "^5.0.0"
19
+ },
20
+ "dependencies": {
21
+ "@openzeppelin/contracts": "^5.0.0",
22
+ "erc721a": "^4.3.0"
23
+ }
24
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,15 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2020",
4
+ "module": "commonjs",
5
+ "strict": true,
6
+ "esModuleInterop": true,
7
+ "skipLibCheck": true,
8
+ "forceConsistentCasingInFileNames": true,
9
+ "resolveJsonModule": true,
10
+ "declaration": true,
11
+ "outDir": "./dist"
12
+ },
13
+ "include": ["./scripts", "./test", "./hardhat.config.ts"],
14
+ "files": ["./hardhat.config.ts"]
15
+ }