@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.
- package/README.md +378 -0
- package/contracts/DPA.sol +740 -0
- package/contracts/examples/AssetDPA.sol +81 -0
- package/contracts/shared/Errors.sol +50 -0
- package/contracts/shared/IDPA.sol +112 -0
- package/contracts/shared/Types.sol +18 -0
- package/hardhat.config.ts +23 -0
- package/package.json +24 -0
- package/tsconfig.json +15 -0
|
@@ -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
|
+
}
|