@fixdescriptorkit/contracts
v1.0.0
Published
ERC-FIX Solidity contracts for embedding FIX Protocol descriptors in tokens
Maintainers
Readme
FixDescriptorKit Smart Contracts
Solidity contracts for onchain storage and verification of FIX asset descriptors
A suite of Ethereum smart contracts that enable embedding FIX descriptors directly in token contracts (ERC20, ERC721) with gas-efficient storage (SSTORE2) and cryptographic verification (Merkle proofs).
🎯 Purpose
These smart contracts implement the onchain component of the FIX Descriptor specification:
- Embedded Architecture - Descriptors stored directly in asset contracts (not registries)
- SSTORE2 Storage - Gas-efficient CBOR storage in contract bytecode
- Merkle Verification - Prove any field without revealing full descriptor
- Token Integration - Works with ERC20, ERC721, and custom token standards
- Standard Interface -
IFixDescriptorfor interoperability
📁 Contract Structure
contracts/src/
├── IFixDescriptor.sol # Standard interface
├── FixDescriptorLib.sol # Core library for easy integration
├── FixMerkleVerifier.sol # Merkle proof verification library
├── DataContractFactory.sol # SSTORE2 deployment utility
├── AssetTokenERC20.sol # Example ERC20 with embedded descriptor
├── AssetTokenERC721.sol # Example ERC721 with embedded descriptor
├── AssetTokenFactory.sol # Factory for deploying asset tokens
└── examples/
├── BondDescriptorReader.sol # Advanced usage example
├── AssetTokenERC20Upgradeable.sol # Upgradeable ERC20 example
└── AssetTokenERC721Upgradeable.sol # Upgradeable ERC721 example⚡ Easy Integration
Adding FIX descriptor support to your token takes just 3 steps using FixDescriptorLib:
// 1. Import library
import "./FixDescriptorLib.sol";
import "./IFixDescriptor.sol";
contract MyToken is ERC20, IFixDescriptor {
using FixDescriptorLib for FixDescriptorLib.Storage;
// 2. Add storage slot
FixDescriptorLib.Storage private _fixDescriptor;
// 3. Forward interface calls
function getFixDescriptor() external view returns (FixDescriptor memory) {
return _fixDescriptor.getDescriptor();
}
function getFixRoot() external view returns (bytes32) {
return _fixDescriptor.getRoot();
}
function verifyField(...) external view returns (bool) {
return _fixDescriptor.verifyFieldProof(...);
}
function getHumanReadableDescriptor() external view returns (string memory) {
return _fixDescriptor.getHumanReadable();
}
}✅ Works with any token standard (ERC20, ERC721, ERC1155, custom)
✅ Works with any upgrade pattern (UUPS, Transparent, Beacon, or none)
✅ All complex logic (SSTORE2, Merkle proofs, CBOR parsing) handled by library
🔑 Core Contracts
FixDescriptorLib.sol
The easiest way to add FIX descriptor support - a comprehensive library that handles all the complexity:
- Storage struct pattern for maximum flexibility
- SSTORE2 reading with assembly optimization
- Merkle proof verification
- Human-readable CBOR parsing
- Works with upgradeable and non-upgradeable contracts
IFixDescriptor.sol
The standard interface that all asset contracts with FIX descriptors should implement.
interface IFixDescriptor {
struct FixDescriptor {
uint16 fixMajor; // FIX version major (e.g., 4)
uint16 fixMinor; // FIX version minor (e.g., 4)
bytes32 dictHash; // FIX dictionary hash
bytes32 fixRoot; // Merkle root commitment
address fixCBORPtr; // SSTORE2 address of CBOR data
uint32 fixCBORLen; // CBOR byte length
string fixURI; // Optional URI for off-chain mirror
}
function getFixDescriptor() external view returns (FixDescriptor memory);
function getFixRoot() external view returns (bytes32);
function verifyField(
bytes calldata pathCBOR,
bytes calldata value,
bytes32[] calldata proof,
bool[] calldata directions
) external view returns (bool);
event FixDescriptorSet(
bytes32 indexed fixRoot,
bytes32 indexed dictHash,
address fixCBORPtr,
uint32 fixCBORLen
);
}FixMerkleVerifier.sol
Library for verifying Merkle proofs. Gas cost: ~30-40k gas (typical depth 4-6).
DataContractFactory.sol
Factory for deploying CBOR data using SSTORE2 pattern (3-4x cheaper than storage slots).
AssetTokenERC20.sol & AssetTokenERC721.sol
Example token implementations with embedded FIX descriptors.
AssetTokenFactory.sol
Factory for deploying new asset tokens with descriptors.
🚀 Getting Started
Prerequisites
- Foundry installed
- OpenZeppelin contracts (via git submodules)
Installation
cd contracts
# Initialize OpenZeppelin submodules
git submodule update --init --recursive
# Build contracts
forge build
# Run tests
forge test📖 Usage Examples
Basic ERC20 Token
import "./FixDescriptorLib.sol";
contract MyBondToken is ERC20, Ownable, IFixDescriptor {
using FixDescriptorLib for FixDescriptorLib.Storage;
FixDescriptorLib.Storage private _fixDescriptor;
constructor() ERC20("MyBond", "BOND") Ownable(msg.sender) {}
function setFixDescriptor(FixDescriptor calldata descriptor) external onlyOwner {
_fixDescriptor.setDescriptor(descriptor);
}
function getFixDescriptor() external view returns (FixDescriptor memory) {
return _fixDescriptor.getDescriptor();
}
// ... other IFixDescriptor functions
}Upgradeable ERC20 Token
import "./FixDescriptorLib.sol";
contract MyUpgradeableBond is
ERC20Upgradeable,
OwnableUpgradeable,
UUPSUpgradeable,
IFixDescriptor
{
using FixDescriptorLib for FixDescriptorLib.Storage;
FixDescriptorLib.Storage private _fixDescriptor;
function initialize() public initializer {
__ERC20_init("MyBond", "BOND");
__Ownable_init(msg.sender);
__UUPSUpgradeable_init();
}
// ... same forwarding functions
uint256[49] private __gap; // Reserve storage for upgrades
}Factory Deployment
// Deploy CBOR data via SSTORE2
DataContractFactory dataFactory = new DataContractFactory();
address cborPtr = dataFactory.deployData(cborBytes);
// Create descriptor
IFixDescriptor.FixDescriptor memory descriptor = IFixDescriptor.FixDescriptor({
fixMajor: 4,
fixMinor: 4,
dictHash: keccak256(fixDictionaryBytes),
fixRoot: merkleRoot,
fixCBORPtr: cborPtr,
fixCBORLen: uint32(cborBytes.length),
fixURI: "ipfs://..."
});
// Deploy token
AssetTokenFactory factory = new AssetTokenFactory();
address token = factory.deployERC20(
"US Treasury Bond 2030",
"USTB30",
1000000 ether,
descriptor
);🚀 Deployment
# Deploy to Sepolia Testnet
forge script script/DeployAssetToken.s.sol \
--rpc-url https://ethereum-sepolia-rpc.publicnode.com \
--private-key $PRIVATE_KEY \
--broadcast \
--verify📚 Documentation
- Integration Guide: INTEGRATION_GUIDE.md - Comprehensive guide for adding FIX descriptors to your contracts
- Main Repository: FixDescriptorKit
- Technical Spec: Web Specification
- TypeScript Library: packages/fixdescriptorkit-typescript
- Web App: apps/web
💡 Why Use FixDescriptorLib?
| Feature | Library Pattern | Abstract Contract | Manual Implementation | |---------|----------------|-------------------|----------------------| | Code to write | ~10 lines | ~50 lines | ~150 lines | | Upgradeable support | ✅ Any pattern | ⚠️ Separate version | ❌ Complex | | Gas efficiency | ✅ Optimal | ⚠️ Delegatecall overhead | ✅ Optimal | | Maintenance | ✅ Single library | ⚠️ Multiple versions | ❌ Manual updates | | Flexibility | ✅ Works everywhere | ⚠️ Inheritance limits | ✅ Full control |
Recommendation: Use FixDescriptorLib for the best developer experience and maximum flexibility.
🔧 Foundry Commands
forge build # Build contracts
forge test # Run tests
forge test --gas-report # Gas report
forge fmt # Format code📄 License
ISC License
