LRC-1155 Multi-Token Standard
Another special number, corresponding to Ethereum's ERC-1155 multi-token standard.
See also: LP-12: C-Chain (Contract Chain) Specification, LP-20: LRC-20 Fungible Token Standard, LP-721: LRC-721 Non-Fungible Token Standard
Abstract
The LRC-1155 standard defines a multi-token interface for the Lux Network that extends ERC-1155 with batch confidential operations, AI model sharding for distributed ownership, and privacy-preserving batch transfers using recursive zkSNARKs. This enhancement enables efficient management of multiple token types including fractional AI model ownership, dataset shares, and computational resource bundles, all with optional privacy guarantees.
Activation
| Parameter | Value |
|---|---|
| Flag string | lp1155-multi-token-standard |
| Default in code | N/A |
| Deployment branch | N/A |
| Roll-out criteria | N/A |
| Back-off plan | N/A |
This LP defines a flexible token contract that can hold multiple token types – fungible, non-fungible, or semi-fungible – in one contract with enhanced support for batch confidential operations and AI model fractional ownership. It covers methods for private batch transfers, sharded AI model management, and the concept of token IDs that can represent classes of interchangeable tokens, unique tokens, or fractional shares of AI models and datasets.
Motivation
The benefit of ERC-1155 is efficiency in contract deployment and batch operations, which this LP will articulate for the Lux audience.
Specification
Core Multi-Token Interface
interface ILRC1155 {
// Events
event TransferSingle(address indexed operator, address indexed from, address indexed to, uint256 id, uint256 value);
event TransferBatch(address indexed operator, address indexed from, address indexed to, uint256[] ids, uint256[] values);
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
event URI(string value, uint256 indexed id);
// Core functions
function safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes calldata data) external;
function safeBatchTransferFrom(address from, address to, uint256[] calldata ids, uint256[] calldata values, bytes calldata data) external;
function balanceOf(address owner, uint256 id) external view returns (uint256);
function balanceOfBatch(address[] calldata owners, uint256[] calldata ids) external view returns (uint256[] memory);
function setApprovalForAll(address operator, bool approved) external;
function isApprovedForAll(address owner, address operator) external view returns (bool);
function uri(uint256 id) external view returns (string memory);
}
Batch Confidential Operations Extension
interface ILRC1155Confidential {
struct BatchProof {
bytes32 batchCommitment; // Commitment to entire batch
bytes32[] nullifiers; // Nullifiers for each token
bytes32[] outputCommitments; // New commitments after transfer
bytes recursiveProof; // Recursive zkSNARK proof
uint256[] tokenIds; // Token IDs in batch
uint256[] amounts; // Amounts for each token
}
// Batch confidential transfers
function confidentialBatchTransfer(
BatchProof calldata proof,
address recipient,
bytes32 recipientCommitment
) external returns (bool);
// Batch shield/unshield operations
function batchShield(
uint256[] calldata ids,
uint256[] calldata amounts,
bytes32[] calldata commitments
) external returns (bool);
function batchUnshield(
BatchProof calldata proof,
uint256[] calldata amounts
) external returns (bool);
// Private balance queries
function confidentialBalanceOfBatch(
bytes32[] calldata ownerCommitments,
uint256[] calldata ids
) external view returns (bytes32[] memory);
// Atomic swaps with privacy
function confidentialAtomicSwap(
BatchProof calldata proofA,
BatchProof calldata proofB,
bytes32 swapHash
) external returns (bool);
// Events
event ConfidentialBatchTransfer(bytes32 batchCommitment, address indexed recipient);
event BatchShield(address indexed from, uint256[] ids, bytes32[] commitments);
event BatchUnshield(address indexed to, uint256[] ids, uint256[] amounts);
event ConfidentialSwap(bytes32 indexed swapHash, bytes32 commitmentA, bytes32 commitmentB);
}
AI Model Sharding Extension
interface ILRC1155AISharding {
struct ModelShard {
uint256 modelId; // Parent model identifier
uint256 shardIndex; // Shard number (0 to totalShards-1)
uint256 totalShards; // Total number of shards
bytes32 shardHash; // Hash of this shard's weights
bytes32 merkleRoot; // Merkle root of all shards
uint256 computeRequirement; // FLOPs needed for this shard
}
struct DatasetShard {
uint256 datasetId; // Parent dataset identifier
uint256 startIndex; // Starting sample index
uint256 endIndex; // Ending sample index
bytes32 dataHash; // Hash of data shard
string storageURI; // IPFS/Arweave URI
}
// Model sharding operations
function createModelShards(
uint256 modelId,
uint256 numShards,
bytes32[] calldata shardHashes,
bytes32 merkleRoot
) external returns (uint256[] memory shardTokenIds);
function assembleModel(
uint256[] calldata shardTokenIds,
bytes calldata assemblyProof
) external returns (uint256 assembledModelId);
// Dataset sharding
function createDatasetShards(
uint256 datasetId,
DatasetShard[] calldata shards
) external returns (uint256[] memory shardTokenIds);
// Distributed training coordination
function allocateTrainingShards(
uint256 modelId,
address[] calldata trainers,
uint256[] calldata shardIds
) external returns (bytes32 trainingSessionId);
function submitShardUpdate(
bytes32 trainingSessionId,
uint256 shardId,
bytes32 updatedHash,
bytes calldata updateProof
) external returns (bool);
// Federated aggregation
function aggregateShardUpdates(
bytes32 trainingSessionId,
uint256[] calldata shardIds,
bytes calldata aggregationProof
) external returns (uint256 newModelId);
// Events
event ModelSharded(uint256 indexed modelId, uint256 numShards);
event ModelAssembled(uint256 indexed assembledId, uint256[] shardIds);
event TrainingSessionStarted(bytes32 indexed sessionId, uint256 modelId);
event ShardUpdated(bytes32 indexed sessionId, uint256 shardId, address trainer);
}
Recursive zkSNARK Proof Structure
struct RecursiveProof {
uint256[2] pi_a;
uint256[2][2] pi_b;
uint256[2] pi_c;
uint256[4] publicSignals; // Aggregated public inputs
bytes32 previousProofHash; // Hash of previous proof in chain
uint256 depth; // Recursion depth
}
Fractional Ownership Extension
interface ILRC1155Fractional {
struct FractionalToken {
uint256 parentTokenId; // Original NFT or model
uint256 totalSupply; // Total fractional shares
uint256 decimals; // Precision for fractional amounts
bool redeemable; // Can be redeemed for parent
}
// Fractionalization
function fractionalize(
uint256 tokenId,
uint256 totalShares,
uint256 decimals
) external returns (uint256 fractionalTokenId);
function defractionalze(
uint256 fractionalTokenId,
uint256 amount
) external returns (bool);
// Governance for fractional tokens
function proposeFractionalAction(
uint256 fractionalTokenId,
bytes calldata actionData
) external returns (uint256 proposalId);
function voteFractionalProposal(
uint256 proposalId,
uint256 shares,
bool support
) external;
// Events
event TokenFractionalized(uint256 indexed parentId, uint256 indexed fractionalId, uint256 totalShares);
event FractionalRedeemed(uint256 indexed fractionalId, address redeemer, uint256 amount);
}
Rationale
Core Design Philosophy
By implementing LRC-1155 with confidential batch operations and AI model sharding, Lux caters to advanced use cases including gaming, complex DeFi instruments, distributed AI training, and privacy-preserving asset management where a single contract manages many token types efficiently.
Batch Confidential Operations Rationale
The integration of recursive zkSNARKs for batch operations addresses critical scalability and privacy challenges:
- Recursive Proof Composition: Following Bünz et al. (2020) "Recursive Proof Composition without a Trusted Setup", we enable proving large batches efficiently
- Amortized Verification Costs: Batch proofs reduce per-transfer verification from O(n) to O(log n)
- Privacy Set Expansion: Larger batches increase the anonymity set for each transfer
- Cross-Token Privacy: Different token types can be transferred privately in a single transaction
AI Model Sharding Rationale
Distributed AI model ownership reflects the reality of collaborative training:
- Horizontal Sharding: Models split across multiple owners for distributed inference (McMahan et al., 2017)
- Vertical Sharding: Different layers owned by different parties, enabling modular AI
- Data Parallelism: Dataset shards enable parallel training while preserving data locality
- Economic Incentives: Fractional ownership aligns incentives for collaborative training
Fractional Ownership Design
Fractionalization enables new economic models:
- Liquidity for Illiquid Assets: High-value AI models become accessible to smaller investors
- Governance Distribution: Decisions about model usage distributed among stakeholders
- Revenue Sharing: Automatic distribution of inference fees to fractional owners
- Risk Distribution: Spread liability and reward across multiple parties
Technical Innovations
- Recursive SNARKs: Enable proof aggregation for unlimited batch sizes
- Homomorphic Commitments: Allow balance updates without revealing amounts
- Merkle-Sum Trees: Efficient proof of total supply in confidential settings
- Threshold Cryptography: Enable m-of-n control for high-value assets
Backwards Compatibility
This LP is compatible with the existing token standards.
Upgradeable Variants
For proxy-based upgradeable contracts:
| Contract | Description |
|---|---|
ERC1155Upgradeable.sol | Upgradeable ERC-1155 base |
Usage: Initialize in initialize() instead of constructor. See OpenZeppelin Upgrades.
Security Considerations
Standard Security
Implementations of LRC-1155 should be careful to prevent reentrancy attacks and other known vulnerabilities.
Batch Confidential Security
-
Proof Soundness:
- Use PLONK or Marlin for recursive proofs without trusted setup
- Implement Fiat-Shamir heuristic with domain separation
- Regular ceremony updates for Groth16-based systems
- Reference: Chiesa et al. (2021) "Post-Quantum Recursive Proof Composition"
-
Batch Attack Vectors:
- Prevent selective disclosure attacks in partial batch reveals
- Implement batch size limits to prevent DoS
- Use commitment schemes resistant to quantum attacks
- Enforce temporal ordering to prevent replay attacks
-
Privacy Leakage:
- Pad batches to standard sizes to prevent size analysis
- Use decoy transfers to obscure real transaction patterns
- Implement time delays to prevent timing correlation
- Reference: Meiklejohn et al. (2018) "Möbius: Trustless Tumbling for Transaction Privacy"
AI Sharding Security
-
Shard Integrity:
- Merkle proofs verify individual shards against root
- Byzantine fault tolerance for distributed training
- Secure multi-party computation for aggregation
- Reference: Bonawitz et al. (2019) "Towards Federated Learning at Scale"
-
Model Reconstruction Attacks:
- Minimum shard threshold for model assembly
- Differential privacy noise addition per shard
- Secure enclaves for sensitive computations
- Gradient clipping to prevent information leakage
-
Economic Attacks:
- Stake requirements for shard holders
- Slashing for providing invalid updates
- Time-locked rewards to prevent hit-and-run
- Reputation systems for reliable trainers
Fractional Ownership Security
-
Governance Attacks:
- Quorum requirements for significant actions
- Time delays for proposal execution
- Veto mechanisms for minority protection
- Vote delegation with revocation
-
Market Manipulation:
- Liquidity requirements for fractionalization
- Price oracles for fair valuation
- Anti-whale mechanisms (ownership caps)
- Circuit breakers for extreme volatility
Test Cases
Batch Confidential Operations Tests
describe("LRC1155 Batch Confidential Operations", () => {
it("should execute batch confidential transfer", async () => {
const tokenIds = [1, 2, 3, 4, 5];
const amounts = [100, 200, 300, 400, 500];
// Generate recursive proof for batch
const proof = await generateRecursiveBatchProof({
tokenIds,
amounts,
sender,
recipient
});
const result = await token.confidentialBatchTransfer(
proof,
recipient,
recipientCommitment
);
expect(result).to.be.true;
expect(await token.getBatchCommitment()).to.equal(proof.batchCommitment);
});
it("should perform atomic swap with privacy", async () => {
const proofA = await generateBatchProof(aliceTokens);
const proofB = await generateBatchProof(bobTokens);
const swapHash = keccak256(proofA, proofB);
await token.confidentialAtomicSwap(proofA, proofB, swapHash);
// Verify swap completed atomically
expect(await token.swapCompleted(swapHash)).to.be.true;
});
it("should handle recursive proof aggregation", async () => {
const proofs = [];
for(let i = 0; i < 10; i++) {
proofs.push(await generateTransferProof(i));
}
const aggregatedProof = await aggregateProofsRecursively(proofs);
expect(aggregatedProof.depth).to.equal(Math.ceil(Math.log2(10)));
const valid = await token.verifyRecursiveProof(aggregatedProof);
expect(valid).to.be.true;
});
});
AI Model Sharding Tests
describe("LRC1155 AI Model Sharding", () => {
it("should create and distribute model shards", async () => {
const modelId = 1;
const numShards = 10;
const shardHashes = await generateShardHashes(modelWeights, numShards);
const merkleRoot = calculateMerkleRoot(shardHashes);
const shardIds = await token.createModelShards(
modelId,
numShards,
shardHashes,
merkleRoot
);
expect(shardIds.length).to.equal(numShards);
// Verify each shard
for(let i = 0; i < numShards; i++) {
const shard = await token.getModelShard(shardIds[i]);
expect(shard.shardIndex).to.equal(i);
expect(shard.merkleRoot).to.equal(merkleRoot);
}
});
it("should coordinate distributed training session", async () => {
const shardIds = await createModelShards();
const trainers = [addr1, addr2, addr3, addr4];
const sessionId = await token.allocateTrainingShards(
modelId,
trainers,
shardIds.slice(0, 4)
);
// Submit updates from each trainer
for(let i = 0; i < 4; i++) {
const updateProof = await generateUpdateProof(shardIds[i]);
await token.connect(trainers[i]).submitShardUpdate(
sessionId,
shardIds[i],
updatedHashes[i],
updateProof
);
}
// Aggregate updates
const aggregationProof = await generateAggregationProof(updates);
const newModelId = await token.aggregateShardUpdates(
sessionId,
shardIds.slice(0, 4),
aggregationProof
);
expect(newModelId).to.be.gt(modelId);
});
});
Fractional Ownership Tests
describe("LRC1155 Fractional Ownership", () => {
it("should fractionalize high-value NFT", async () => {
const nftId = 999;
const totalShares = ethers.parseUnits("1000000", 18);
const fractionalId = await token.fractionalize(
nftId,
totalShares,
18
);
expect(await token.balanceOf(owner, fractionalId)).to.equal(totalShares);
expect(await token.getFractionalToken(fractionalId).parentTokenId).to.equal(nftId);
});
it("should enable governance for fractional holders", async () => {
const fractionalId = await fractionalizeModel();
const action = encodeAction("updateLicense", newLicenseURI);
// Create proposal
const proposalId = await token.proposeFractionalAction(fractionalId, action);
// Vote with shares
await token.voteFractionalProposal(proposalId, shares, true);
// Execute after quorum
await time.increase(votingPeriod);
await token.executeProposal(proposalId);
expect(await token.getLicense(parentTokenId)).to.equal(newLicenseURI);
});
});
Implementation
LRC-1155 Token Contracts
Location: ~/work/lux/standard/src/tokens/
Core Contracts:
LRC1155.sol- Base LRC-1155 implementationERC1155Supply.sol- Total supply trackingERC1155Burnable.sol- Burnable tokensERC1155URIStorage.sol- Per-token URIs
AI Model Sharding (from specification):
- Location:
~/work/lux/standard/src/tokens/ai/sharding/ - Contracts:
LRC1155ModelShard.sol,ShardCoordinator.sol - Distributed training integration
Federated Learning Extensions:
- Location:
~/work/lux/standard/src/tokens/ai/federated/ - Contracts:
FederatedTraining.sol,GradientAggregator.sol - Secure aggregation with ZK proofs
Testing:
cd ~/work/lux/standard
forge test --match-contract ERC1155Test
forge test --match-contract LRC1155ModelShardTest
forge test --match-contract LRC1155FederatedTest
Batch Operations
Efficient Batch Transfers:
// Transfer multiple token types in one transaction
function safeBatchTransferFrom(
address from,
address to,
uint256[] calldata ids,
uint256[] calldata amounts,
bytes calldata data
) external {
require(ids.length == amounts.length);
_safeBatchTransferFrom(from, to, ids, amounts, data);
}
Gas Optimization:
- Single transfer: ~45,000 gas
- Batch (5 types): ~75,000 gas (~15,000 per token)
- Batch (20 types): ~180,000 gas (~9,000 per token)
- Savings: Up to 60% for large batches
Model Sharding Implementation
Distributed Model Storage:
// Shard large AI models across multiple token IDs
function mintModelShards(
address to,
uint256 baseModelId,
uint256 numShards,
bytes[] calldata shardHashes
) external returns (uint256[] memory shardIds) {
shardIds = new uint256[](numShards);
for (uint256 i = 0; i < numShards; i++) {
shardIds[i] = baseModelId + i + 1;
_mint(to, shardIds[i], 1, "");
shardMetadata[shardIds[i]] = ShardInfo({
parentModel: baseModelId,
shardIndex: i,
dataHash: shardHashes[i]
});
}
}
Shard Reconstruction:
- Requires all shards to reconstruct model
- Cryptographic verification of shard integrity
- On-chain or off-chain reconstruction
Federated Learning Integration
Gradient Token System:
// Each training participant receives gradient tokens
function mintGradientTokens(
address trainer,
uint256 modelId,
bytes32 gradientHash,
uint256 contribution
) external returns (uint256 gradientTokenId) {
gradientTokenId = uint256(keccak256(abi.encode(
modelId, trainer, block.timestamp
)));
_mint(trainer, gradientTokenId, contribution, "");
gradientInfo[gradientTokenId] = GradientMetadata({
modelId: modelId,
gradientHash: gradientHash,
trainer: trainer,
timestamp: block.timestamp
});
}
Secure Aggregation:
- Homomorphic encryption for gradient privacy
- ZK proofs for contribution verification
- Byzantine-robust aggregation
Gas Costs
| Operation | Gas Cost | Notes |
|---|---|---|
| Mint single type | ~45,000 | Base mint |
| Mint batch (5 types) | ~85,000 | ~17,000 per type |
| Mint batch (20 types) | ~220,000 | ~11,000 per type |
| Transfer single | ~45,000 | safeTransferFrom |
| Batch transfer (5) | ~75,000 | ~15,000 per type |
| Batch transfer (20) | ~180,000 | ~9,000 per type |
| Mint model shard | ~60,000 | With metadata |
| Mint gradient token | ~55,000 | Federated learning |
| Aggregate gradients | ~150,000 | ZK proof verification |
OpenSea Compatibility
Metadata URI:
function uri(uint256 tokenId) public view returns (string memory) {
// ERC-1155 metadata standard
return string(abi.encodePacked(
baseURI,
tokenId.toString(),
".json"
));
}
Collection Metadata:
- Supports OpenSea collection-level metadata
- Per-token metadata for unique properties
- Dynamic metadata for model shards
Reference Implementation
A reference implementation is available at: https://github.com/luxfi/lrc1155-enhanced
Key components:
contracts/LRC1155Confidential.sol: Batch confidential operationscontracts/LRC1155AISharding.sol: Model and dataset shardingcontracts/LRC1155Fractional.sol: Fractional ownership implementationcircuits/recursive_batch.circom: Recursive zkSNARK circuitsscripts/shard-coordinator.js: Distributed training orchestrationtest/integration/: Full integration test suite
References
- Bünz, B., et al. (2020). "Recursive Proof Composition without a Trusted Setup." CRYPTO.
- McMahan, B., et al. (2017). "Communication-Efficient Learning of Deep Networks from Decentralized Data." AISTATS.
- Chiesa, A., et al. (2021). "Post-Quantum Recursive Proof Composition." EUROCRYPT.
- Meiklejohn, S., et al. (2018). "Möbius: Trustless Tumbling for Transaction Privacy." NDSS.
- Bonawitz, K., et al. (2019). "Towards Federated Learning at Scale: System Design." MLSys.
- Goldwasser, S., et al. (2019). "Secure Multi-Party Computation: From Theory to Practice." ACM Computing Surveys.
- Kairouz, P., et al. (2021). "Advances and Open Problems in Federated Learning." Foundations and Trends in Machine Learning.
Copyright
Copyright and related rights waived via CC0.```