DAT Contract Overview
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Enumerable.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
/// @title LazAI DAT Token Standard (Final Version)
/// @notice Token standard for semi-fungible AI data/model asset shares, usage rights, and on-chain revenue participation
contract DATToken is ERC721Enumerable, Ownable
{
struct ClassMetadata {
string name;
string description;
string dataURI;
}
struct DAT {
uint256 classId; // AI asset class (e.g., dataset, model, agent)
uint256 value; // Usage credit, revenue share, or computation quota
uint256 expireAt; // Optional: expiration timestamp
uint256 shareRatio; // Optional: % of future revenue this token is entitled to (in basis points)
}
string public contractMetadata;
uint8 public constant valueDecimals = 6; // USDC-style
uint256 public nextTokenId;
mapping(uint256 => DAT) public dats; // tokenId => DAT info
mapping(uint256 => ClassMetadata) public classMetadata; // classId => metadata
mapping(uint256 => uint256) public classSupply; // classId => number of minted DATs
mapping(uint256 => mapping(address => bool)) public classApprovals; // classId => operator => approved
event ClassCreated(uint256 indexed classId, string name);
event DATMinted(address indexed to, uint256 tokenId, uint256 classId, uint256 value);
event ValueTransferred(uint256 fromTokenId, uint256 toTokenId, uint256 value);
event ClassApproved(uint256 classId, address operator, bool approved);
constructor(string memory name_, string memory symbol_, string memory contractURI_) ERC721(name_, symbol_) {
contractMetadata = contractURI_;
}
// -------- Metadata --------
function contractURI() external view returns (string memory) {
return contractMetadata;
}
function classURI(uint256 classId) external view returns (string memory) {
return classMetadata[classId].dataURI;
}
// -------- Class Management --------
function createClass(
uint256 classId,
string memory name,
string memory description,
string memory dataURI
) external onlyOwner {
require(bytes(classMetadata[classId].name).length == 0, "Class exists");
classMetadata[classId] = ClassMetadata(name, description, dataURI);
emit ClassCreated(classId, name);
}
function approveForClass(uint256 classId, address operator, bool approved) external {
require(operator != msg.sender, "Self approve not needed");
classApprovals[classId][operator] = approved;
emit ClassApproved(classId, operator, approved);
}
function isApprovedForClass(uint256 classId, address operator) public view returns (bool) {
return classApprovals[classId][operator];
}
// -------- DAT Minting --------
function mintDAT(
address to,
uint256 classId,
uint256 value,
uint256 expireAt,
uint256 shareRatio // in basis points (e.g., 5000 = 50%)
) external onlyOwner returns (uint256) {
require(bytes(classMetadata[classId].name).length > 0, "Invalid class");
uint256 tokenId = ++nextTokenId;
dats[tokenId] = DAT(classId, value, expireAt, shareRatio);
_mint(to, tokenId);
classSupply[classId]++;
emit DATMinted(to, tokenId, classId, value);
return tokenId;
}
// -------- Value Transfer --------
function transferValue(
uint256 fromTokenId,
uint256 toTokenId,
uint256 value
) external {
require(_isApprovedOrOwner(msg.sender, fromTokenId), "Not authorized");
require(dats[fromTokenId].classId == dats[toTokenId].classId, "Class mismatch");
require(dats[fromTokenId].value >= value, "Insufficient value");
dats[fromTokenId].value -= value;
dats[toTokenId].value += value;
emit ValueTransferred(fromTokenId, toTokenId, value);
}
// -------- Views --------
function valueOf(uint256 tokenId) external view returns (uint256) {
return dats[tokenId].value;
}
function classOf(uint256 tokenId) external view returns (uint256) {
return dats[tokenId].classId;
}
function shareOf(uint256 tokenId) external view returns (uint256) {
return dats[tokenId].shareRatio;
}
function classCount() external view returns (uint256) {
return nextTokenId; // approximation
}
function tokenSupplyInClass(uint256 classId) external view returns (uint256) {
return classSupply[classId];
}
}
Last updated