Developer Guide
Smart Contracts
DataPolicy.sol — the on-chain authority for policy enforcement, escrow management, and royalty settlement.
Smart Contracts
LICEN's on-chain logic lives in a single contract: DataPolicy.sol, deployed on the 0G Galileo Testnet.
Deployed Address
| Contract | Network | Address |
|---|---|---|
DataPolicy | 0G Galileo Testnet (Chain ID: 16602) | 0x565ab137D5D18B7Aa32783C7D1a8dc29d83687E7 |
Network Details
| Parameter | Value |
|---|---|
| Network Name | 0G Galileo Testnet |
| RPC URL | https://evmrpc-testnet.0g.ai |
| Chain ID | 16602 |
| Currency | 0G (native) |
| Block Explorer | https://chainscan-galileo.0g.ai |
On-Chain Data Model
The Policy Struct
This struct is the owner's enforceable usage policy. Purpose restrictions are only one field inside a larger control model that also governs pricing, volume, repeat access, and session lifetime.
struct Policy {
bytes32 datasetRoot; // Merkle root of encrypted dataset on 0G Storage
address owner; // Royalty recipient
bytes32 manifestHash; // Hash of off-chain policy manifest (integrity anchor)
uint256 royaltyPerEpoch; // Cost per training epoch (in native 0G, wei units)
uint32 maxEpochsPerRun; // Max epochs per single training session
uint32 maxRunsPerRequester;// Lifetime session cap per researcher wallet
uint64 accessTtlSeconds; // Session validity window after AccessGranted
uint64 policyExpiry; // Unix timestamp — no new requests after this
bool active; // Publisher can pause/unpause
}The Job Struct
struct Job {
bytes32 datasetRoot; // Dataset being trained on
address requester; // Researcher who paid
address provider; // = backendWallet (the Orchestrator)
bytes32 purposeId; // Declared use case (keccak256 of purpose string)
uint32 requestedEpochs;// Epochs the researcher paid for
uint256 escrowAmount; // 0G wei locked
uint64 requestTime; // Unix timestamp of request
JobState state; // None|Requested|Granted|Running|Completed|Failed|TimedOut|Refunded
bytes32 termsHash; // Must match manifestHash at request time
}Key Functions
Publisher
// Register a dataset and its policy on-chain
function registerDataset(
bytes32 datasetRoot,
bytes32 manifestHash,
uint256 royaltyPerEpoch,
uint32 maxEpochsPerRun,
uint32 maxRunsPerRequester,
uint64 accessTtlSeconds,
uint64 policyExpiry,
bytes32[] calldata allowedPurposeIds
) external;Researcher
// Lock escrow and request access — emits AccessGranted
function requestAccess(
bytes32 datasetRoot,
bytes32 purposeId,
uint32 requestedEpochs,
bytes32 termsHash
) external payable;
// msg.value must equal royaltyPerEpoch * requestedEpochsAt request time, the contract checks the researcher's requested access against the owner's policy envelope: price, requested epochs, repeat-request caps, access duration, expiry, and allowed purpose IDs.
Orchestrator (backendWallet only)
// Mark job as Running
function startJob(bytes32 jobId) external;
// Settle royalties and mark Completed
function confirmTrainingComplete(
bytes32 jobId,
uint32 actualEpochs,
bytes32 resultHash,
bytes32 attestationRef
) external;
// Trigger researcher refund
function markJobFailed(bytes32 jobId, string calldata reason) external;Key Events
event DatasetRegistered(bytes32 indexed datasetRoot, address indexed owner, bytes32 manifestHash);
event AccessGranted(bytes32 indexed jobId, bytes32 indexed datasetRoot, address indexed requester, uint32 epochs);
event JobStarted(bytes32 indexed jobId);
event TrainingCompleted(bytes32 indexed jobId, uint32 actualEpochs, bytes32 resultHash);
event JobFailed(bytes32 indexed jobId, string reason);Development
Contracts are built with Foundry.
# Run test suite
cd packages/contracts
forge test
# Deploy to 0G Testnet
source .env
forge script script/DeployDataPolicy.s.sol \
--rpc-url $OG_EVM_RPC_URL \
--broadcast