Contracts
Reference for every contract in dataprism-protocol. For deployed addresses, see
Deployments.
Token (DPC)
Token.sol, the protocol's ERC-20 token (name = "DataPrism Token", symbol = "DPC",
decimals = 18). It is consumed (burned) on data operations to pay protocol fees.
Role-based access:
- Minters: addresses authorized to mint, with a configurable min/max range per minter.
- Burners: addresses authorized to burn from another account (e.g.
DataPrism). - Operators: addresses authorized to
transferFromwithout an allowance (e.g.DataPrism).
Key functions:
| Function | Description |
|---|---|
transfer / approve / transferFrom | Standard ERC-20 (operators bypass allowance). |
permit(owner, spender, value, deadline, v, r, s) | EIP-2612 gasless approval. |
mint(amount) / mintTo(to, amount) | Mint (active minters only). |
burn(account, amount) / burnFrom(account, amount) | Burn (active burners only). |
configureMinter / configureBurner / configureOperator | Admin role configuration. |
transferOwnership / acceptOwnership | Two-step ownership transfer. |
Events: Transfer, Approval, OwnershipTransferStarted, OwnershipTransferred.
FeeController
FeeController.sol, centralizes pricing. Each action has a default fee in DPC; custom fees
can be negotiated per address (DataPrismCloud pays 1000 DPC / 1 USDC to create a prism,
100 DPC / 0.1 USDC per data operation, and 0 on other prism operations).
getProtocolFee(caller, action) → custom fee if configured, otherwise default feeAction constants are keccak256 of the action name. Default fees at deployment:
| Action | Default fee |
|---|---|
CREATE_PRISM | 1 DPC |
FUND_PRISM | 0 DPC |
TRANSFER_PRISM | 0 DPC |
DELETE_PRISM | 0 DPC |
ADD_DATA | 1 DPC |
MODIFY_DATA | 1 DPC |
DELETE_DATA | 1 DPC |
BUY_TOKENS | 0% (no fee) |
SELL_TOKENS | 1% (100 bps) |
Admin functions: setDefaultProtocolFee, setCustomProtocolFee, removeCustomProtocolFee,
setTreasury, plus two-step ownership.
DataPrism
DataPrism.sol, the raw storage layer. Prisms are identified by bytes32 IDs. Each prism
has an owner, a DPC tokens balance, and a mapping of dataId → (bytes payload, uint256 timestamp).
Only the owner can write, modify, or delete; tokens are deducted on every operation.
Prism lifecycle: createPrism, createPrisms, fundPrism, fundPrisms,
transferPrism, transferPrisms, deletePrism, deletePrisms.
Single data ops: writeData, modifyData, deleteData.
Batch data ops: writeDataTo, modifyDataIn, deleteDataFrom (one prism);
writeDataAcross, modifyDataAcross, deleteDataAcross (multiple prisms).
Views: getPrism, getPrismOwner, getPrismTokens, prismExists, getData,
getDataFrom, getDataAcross, dataExists, getDataTimestamp.
Events: PrismCreated, PrismFunded, PrismTransferred, PrismDeleted, DataWritten,
DataUpdated, DataDeleted.
DataPrismCloud
DataPrismCloud.sol, the application layer. It maps bytes16 cloud IDs to the underlying
bytes32 storage IDs and adds:
- Cloud IDs (
bytes16): the first 16 bytes of the prism ID; cheaper in calldata. - Writers: per-prism delegated write access with optional expiration.
- Two-step transfers:
transferPrism→acceptTransfer. - On-chain enumeration: prisms per user, dataIds per prism, writers per prism.
- Internal token balance: DPC managed at the cloud layer.
Prism management: createPrism, createPrismWithPermit, createPrismWithData,
createPrismWithDataAndPermit, fundPrism, fundPrismWithPermit, transferPrism,
acceptTransfer, deletePrism.
The createPrismWithData variants create a prism and write an initial batch of entries
(dataIds / payloads) in a single atomic transaction, equivalent to createPrism
followed by batchWriteData but with one signature and one nonce increment; fundAmount must
cover the creation fee plus the per-entry data fees. The *AndPermit form additionally bundles
an EIP-2612 permit so a funded, populated prism is created with no separate
approve.
The *WithPermit variants bundle an EIP-2612 permit on the DPC token
into the same call, so a funded prism is created (or topped up) in a single
transaction with no separate approve. They run
token.permit(msg.sender, address(this), amount, deadline, v, r, s), the cloud is
not a token operator, so pulling DPC needs an allowance, and then the normal
createPrism / fundPrism logic. With amount == 0 the permit is skipped.
Writer management: addWriter, updateWriterExpiration, removeWriter.
Data ops: writeData, modifyData, deleteData, batchWriteData, batchModifyData,
batchDeleteData.
Meta-transaction callbacks (only callable by the Forwarder): the *As variants -
createPrismAs, createPrismWithDataAs, fundPrismAs, transferPrismAs, acceptTransferAs,
deletePrismAs, writeDataAs, modifyDataAs, deleteDataAs, batchWriteDataAs,
batchModifyDataAs, batchDeleteDataAs.
Views: getPrismOwner, getPrismPendingOwner, getPrismTokens, getProtocolId,
getUserPrismCount, getUserPrismByIndex, getDataCount, getDataKeyByIndex,
getWritersCount, getWriterByIndex, getWriterExpiration, DOMAIN_SEPARATOR.
The Forwarder is wired in post-deployment via setForwardContract.
DataPrismCloudForwarder
DataPrismCloudForwarder.sol, EIP-712 meta-transaction relayer. Users sign off-chain and a
relayer submits on their behalf in exchange for a relayerFee.
Meta-transaction flow
1. User signs EIP-712 (verifyingContract = DataPrismCloud address)
2. Relayer calls Forwarder.writeDataFor(...)
3. Forwarder verifies the signature and the priority window
4. Forwarder calls DataPrismCloud.writeDataAs(...)
5. DataPrismCloud executes and transfers relayerFee to the Forwarder
6. Forwarder credits the relayer's voucher balancePriority window (anti-frontrunning)
After a request is created, only official relayers can submit it during the first
priorityWindow seconds. After that window, any relayer may relay it.
Relayer economics
- Official relayer: receives 100% of
relayerFee. - Non-official relayer: receives
relayerShareBps% (default 7000 = 70%); the remainder goes toprotocolTreasury. - Fees accumulate as vouchers, claimed via
claimVouchers().
*For dispatch functions
| Function | Description |
|---|---|
createPrismFor | Create a prism on behalf of the signer (optional relayerFundAmount). Carries an EIP-2612 PermitParams and runs token.permit(...) before createPrismAs, so funding needs no prior approve. |
createPrismWithDataFor | Create a prism and write an initial batch (dataIds / payloads) on behalf of the signer, in a single atomic transaction. Carries a PermitParams and calls createPrismWithDataAs; fundAmount must cover the creation fee plus the per-entry data fees. |
fundPrismFor | Fund a prism (also bundles a permit for the DPC pull). |
transferPrismFor | Initiate a prism ownership transfer. |
acceptTransferFor | Accept a pending transfer. |
deletePrismFor | Delete a prism. |
writeDataFor | Write a new data entry. |
modifyDataFor | Update an existing data entry. |
deleteDataFor | Delete a data entry. |
batchWriteDataFor | Write multiple entries into one prism. |
batchModifyDataFor | Update multiple entries in one prism. |
batchDeleteDataFor | Delete multiple entries from one prism. |
batchMultiUserWriteData | Write entries for multiple users in a single transaction. |
Admin/relayer management: claimVouchers, setOfficialRelayer, setProtocolTreasury,
setPriorityWindow, setRelayerShareBps.
Batch operations (BatchWriteData, BatchModifyData, BatchDeleteData) sign over
pre-computed dataIdsHash and payloadsHash. The combined create-and-write path
(createPrismWithDataFor) uses a dedicated typehash
CreatePrismWithData(uint256 fundAmount,bytes32 salt,bytes32 dataIdsHash,bytes32 payloadsHash,uint256 relayerFee,uint256 timestamp,uint256 nonce),
where dataIdsHash and payloadsHash follow the same convention as BatchWriteData. Security:
nonce replay protection, s-value malleability check, and ERC-1271 smart-contract signer support.
Exchange
Exchange.sol, converts external ERC-20 tokens to/from DPC, with optional yield strategies.
Each accepted token has a TokenConfig { bool active; uint256 rate; } where rate is DPC
wei per payment-token wei (1 USDC = 1000 DPC → rate = 1000 × 10^12, since USDC has 6 decimals
and DPC has 18).
| Function | Description |
|---|---|
buyTokens(paymentToken, paymentAmount, minTokensOut) | Swap external token → DPC (mints DPC). |
sellTokens(paymentToken, dpcAmount, minTokenOut) | Swap DPC → external token (burns DPC). |
setTokenConfig(token, active, rate) | Admin: accept a token and set its rate. |
setTokenStrategy(token, strategy) | Admin: route reserves through a yield strategy. |
harvestYield(token) | Admin: harvest yield from the strategy. |
recoverToken(token, amount) | Admin: recover stuck tokens. |
A protocol fee (in basis points) is deducted on both buy and sell, sent to
feeController.treasury(). Events: TokensBought, TokensSold, TokenConfigUpdated,
TokenStrategySet.
MorphoStrategy
MorphoStrategy.sol, an optional yield strategy that routes Exchange reserves into
Morpho Blue supply markets. Only the authorized exchange can call
deposit, withdraw, and withdrawAll; the admin configures markets via setMarket and
claims surplus yield via harvest.
Factory
scripts/Factory.sol, a CREATE2 factory for deterministic deployments. deploy(salt, initCode)
deploys and verifies the predicted address; getAddress(initCodeHash, salt) and
initHash(initCode) help compute addresses ahead of time.

