Transform FIX asset descriptors into verifiable onchain commitments
A comprehensive toolkit for converting FIX (Financial Information eXchange) protocol asset descriptors into SBE (Simple Binary Encoding) payloads and Merkle commitments for blockchain verification.
- π FIX Message Parsing - Robust parsing of FIX protocol asset descriptors
- π SBE Encoding - Simple Binary Encoding (SBE) for efficient onchain storage
- π³ Merkle Tree Generation - Efficient tree construction with cryptographic proofs
- βοΈ Onchain Verification - Smart contracts for decentralized proof verification
- π Web Interface - Interactive UI for testing and deployment
- π Wallet Integration - MetaMask support for blockchain interactions
fix-descriptor/
βββ packages/
β βββ fixdescriptorkit-typescript/ # Core TypeScript library
βββ apps/
β βββ web/ # Next.js web application
βββ contracts/ # Solidity smart contracts
βββ sbe-lambda-encoder/ # AWS Lambda SBE encoder service
βββ DEPLOYMENT.md # Deployment guide
- TypeScript - Type-safe development
- fixparser - FIX protocol message parsing
- cbor-x - Canonical CBOR encoding/decoding
- viem - Ethereum blockchain interactions
- vitest - Fast unit testing
- Next.js 15 - Full-stack React framework
- App Router - Modern routing and serverless functions
- Tailwind CSS - Utility-first styling
- MetaMask - Web3 wallet integration
- Solidity - Smart contract development
- Foundry - Ethereum development framework
- OpenZeppelin - Security-audited contract libraries
- Node.js 18+ and npm
- Foundry for smart contract development
- MetaMask browser extension
# Clone the repository (with submodules for OpenZeppelin)
git clone --recurse-submodules https://github.com/NethermindEth/fix-descriptor.git
cd fix-descriptor
# If you already cloned without submodules, run:
# git submodule update --init --recursive
# Install dependencies
npm install
# Build the TypeScript library
npm run build
# Start the development server
npm run devVisit http://localhost:3000 to see the application.
import {
parseFixDescriptor,
buildCanonicalTree,
encodeCanonicalCBOR,
enumerateLeaves,
computeRoot,
generateProof
} from 'fixdescriptorkit-typescript';
// Parse FIX message
const fixMessage = "8=FIX.4.4|9=0000|35=d|55=ACME|48=US000000AA11|167=CORP|15=USD|10=000";
const tree = parseFixDescriptor(fixMessage);
// Generate canonical CBOR
const canonical = buildCanonicalTree(tree);
const cbor = encodeCanonicalCBOR(canonical);
// Create Merkle commitment
const leaves = enumerateLeaves(canonical);
const root = computeRoot(leaves);
// Generate proof for specific field (e.g., Currency field at path [15])
const proof = generateProof(leaves, [15]);
console.log('Merkle Root:', root);
console.log('Proof:', proof);Easy Integration with FixDescriptorLib: Add FIX descriptor support to any token in just 3 steps using the library pattern.
import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/access/Ownable.sol";
import "./IFixDescriptor.sol";
import "./FixDescriptorLib.sol";
contract MyBondToken is ERC20, Ownable, IFixDescriptor {
using FixDescriptorLib for FixDescriptorLib.Storage;
// Step 1: Add storage slot
FixDescriptorLib.Storage private _fixDescriptor;
constructor() ERC20("MyBond", "BOND") Ownable(msg.sender) {}
// Step 2: Add setter with your access control
function setFixDescriptor(FixDescriptor calldata descriptor) external onlyOwner {
_fixDescriptor.setDescriptor(descriptor);
}
// Step 3: Forward IFixDescriptor calls to library
function getFixDescriptor() external view returns (FixDescriptor memory) {
return _fixDescriptor.getDescriptor();
}
function getFixRoot() external view returns (bytes32) {
return _fixDescriptor.getRoot();
}
function verifyField(
bytes calldata pathCBOR,
bytes calldata value,
bytes32[] calldata proof,
bool[] calldata directions
) external view returns (bool) {
return _fixDescriptor.verifyFieldProof(pathCBOR, value, proof, directions);
}
}Works with Upgradeable Contracts Too!
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
}Benefits:
- β Easy Integration - Just 3 steps, ~10 lines of code
- β Works Everywhere - Any token standard, any upgrade pattern
- β No Central Registry - Fully decentralized, embedded in asset contracts
- β All Logic Included - SSTORE2, Merkle proofs, SBE reading handled by library
- β Flexible Access Control - Use Ownable, AccessControl, or custom logic
π Complete Integration Guide
# Set your FIXParser license key
export FIXPARSER_LICENSE_KEY="your-license-key"
# Run tests
npm testIf tests reference OpenZeppelin contracts, ensure submodules are initialized:
git submodule update --init --recursivecd contracts
forge testcd contracts
# Deploy asset token contracts
forge script script/DeployAssetToken.s.sol --rpc-url https://ethereum-sepolia-rpc.publicnode.com --broadcast --verify
# Or deploy your own custom asset contract implementing IFixDescriptorSee DEPLOYMENT.md for detailed Vercel deployment instructions.
The SBE Lambda Encoder is an AWS Lambda function that encodes/decodes FIX messages using Simple Binary Encoding (SBE) with runtime code generation.
cd sbe-lambda-encoder
# First-time deployment (interactive)
sam build
sam deploy --guided
# Subsequent updates
sam build
sam deploySee sbe-lambda-encoder/README.md for complete deployment instructions, usage examples, and troubleshooting.
If you use GitHub Actions, enable submodule checkout:
- uses: actions/checkout@v4
with:
submodules: recursivegraph TD
A[FIX Message] --> B[Parse & Validate]
B --> C[Canonical Tree]
C --> D[SBE Encoding]
D --> E[Merkle Tree]
E --> F[Onchain Storage]
F --> G[Verification]
- Parser - Converts FIX messages to structured trees
- Canonicalizer - Normalizes data for deterministic encoding
- SBE Encoder - Creates compact binary representations using Simple Binary Encoding
- Merkle Engine - Generates cryptographic commitments and proofs
- Asset Contracts - ERC20/ERC721 tokens with embedded descriptors
- Verification Library - Onchain Merkle proof verification
Parses a FIX message string into a structured descriptor tree.
Converts a descriptor tree into canonical form for consistent encoding.
Encodes canonical data into deterministic CBOR format.
Computes the Merkle root hash from enumerated leaves.
Generates a cryptographic proof for a specific field path.
Asset contracts implementing IFixDescriptor provide:
getFixDescriptor()- Returns the complete descriptor struct withfixSBEPtrandfixSBELenfieldsgetFixRoot()- Returns the Merkle root commitmentverifyField(pathCBOR, value, proof, directions)- Verifies a field against the commitment
verify(root, pathCBOR, value, proof, directions)- Core verification function
- Sepolia Testnet (Chain ID: 11155111)
The repository includes example implementations:
AssetTokenERC20- ERC20 token with embedded FIX descriptorAssetTokenERC721- ERC721 NFT with embedded FIX descriptorDataContractFactory- SSTORE2 pattern for SBE data storageFixMerkleVerifier- Library for proof verification
Deploy your own asset contracts implementing IFixDescriptor to use this system.
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
- Follow TypeScript best practices
- Add tests for new functionality
- Update documentation as needed
- Ensure all tests pass before submitting
This project is licensed under the ISC License - see the LICENSE file for details.
Comprehensive documentation for smart contracts is available in contracts/docs/:
- π Getting Started - Setup, build, and test instructions
- π Gas Analysis - Merkle proof verification gas costs
- β Merkle Verifier Guide - Proof-based verification (6k-8.5k gas, recommended)
- π Documentation Index - Complete documentation overview
Key Finding: Merkle proof verification is 2-10x more gas efficient than direct field parsing. Use Merkle for production deployments. The system uses SBE (Simple Binary Encoding) for onchain storage.
- Web Specification - Complete technical specification (interactive)
- DEPLOYMENT.md - Deployment guide
- Live Demo: https://fixdescriptor.vercel.app
- FIX Protocol: https://www.fixtrading.org/
- Foundry: https://getfoundry.sh/
- OpenZeppelin: https://openzeppelin.com/
- FIX Trading Community for the FIX protocol specification
- OpenZeppelin for secure smart contract libraries
- Foundry for the excellent Ethereum development toolkit
For questions, issues, or contributions:
- π Issues: GitHub Issues
- π¬ Discussions: GitHub Discussions
Built with β€οΈ for the financial technology community
