Skip links

Core Components of the Oracle State Machine

TL;DR

Oraclizer’s state synchronization architecture consists of five core components: Polygon CDK-based L3 zkRollup infrastructure, zkVerify integrated verification engine, Base L2 bridge connection, Oracle State Synchronizer (OSS), and RWA Registry contracts. Each component performs a specialized role, working together to enable the entire system to complete state synchronization. Particularly, the modular architecture of Polygon CDK and verification optimization through Horizen Labs’ zkVerify have made bidirectional real-time state synchronization economically viable—something impossible with traditional oracle systems.


In our previous articles, we explored the concept and theoretical foundations of the oracle state machine. Now it’s time to dive deeper into the specifics. We’ll examine which technical components are necessary to implement complete state synchronization, and how they interact to overcome the limitations of existing oracles.

What we’re covering today isn’t just a list of technical specifications. We want to share the development team’s genuine experiences regarding why each component was necessary, what problems it was designed to solve, and what challenges we faced during implementation.

Architecture Design Philosophy: A Modular Approach

The biggest dilemma we faced when designing Oraclizer was: “Should we solve everything with a single system, or approach it with a combination of specialized components?”

After analyzing the limitations demonstrated by existing monolithic oracle systems, we became convinced that a modular architecture was the answer. We designed each component to be optimized for a specific function, while collectively performing as a perfect state synchronization orchestra.

The reason for choosing this approach is simple. State synchronization is an incredibly complex and multifaceted problem. Data transmission, verification, storage, consensus, bridging—if we tried to handle all these processes with a single component, we couldn’t properly optimize any of them.

Core Component 1: Polygon CDK-based L3 zkRollup Infrastructure

Why We Chose Polygon CDK

The L3 zkRollup infrastructure that forms the foundation of Oraclizer is built on Polygon’s Chain Development Kit (CDK). This choice involved deep technical considerations.

Initially, we considered developing our own rollup solution. However, we determined that leveraging proven infrastructure would be wiser to focus on our core functionality of state synchronization. Polygon CDK was the optimal choice for the following reasons:

// Polygon CDK modular structure example
contract OraclizerL3 {
    using PolygonCDK for zkEVM;
    using zkVerify for ProofVerification;

    struct StateTransition {
        bytes32 previousStateRoot;
        bytes32 newStateRoot;
        bytes proof;
        uint256 timestamp;
    }

    mapping(bytes32 => StateTransition) public transitions;

    function submitStateTransition(
        bytes32 _newStateRoot,
        bytes calldata _proof
    ) external onlySequencer {
        // Process state transition in CDK's zkEVM environment
        require(zkVerify.verifyProof(_proof), "Invalid proof");

        transitions[_newStateRoot] = StateTransition({
            previousStateRoot: currentStateRoot,
            newStateRoot: _newStateRoot,
            proof: _proof,
            timestamp: block.timestamp
        });

        // Propagate finality to Base L2
        bridgeToBase(_newStateRoot);
    }
}

Polygon CDK’s support for multiple execution environments was particularly important. Between CDK OP Stack and CDK Erigon, we chose CDK Erigon because its custom gas token support and detailed configuration options were essential for oracle state synchronization.

zkRollup vs Validium: Our Choice

CDK supports three modes: zkRollup, Validium, and Sovereign. Oraclizer is designed to dynamically switch between zkRollup and Validium depending on the situation:

  • Critical financial transactions: zkRollup mode to store all data on-chain
  • Large-volume state updates: Validium mode to optimize data availability costs

Core Component 2: zkVerify Integrated Verification Engine

Strategic Partnership with Horizen Labs

zkVerify is one of the most innovative parts of the Oraclizer architecture. This modular ZK proof verification network developed by Horizen Labs is the key technology enabling our 93% gas cost reduction goal.

The cost of directly verifying ZK proofs on existing L1s is substantial. Horizen Labs’ research shows that Ethereum’s zk-rollups alone spent $47 million on proof verification throughout 2023.

// zkVerify integration code example
class ZKVerifyManager {
    private zkVerifyEndpoint: string;
    private proofQueue: ProofSubmission[];

    async submitProofForVerification(
        proof: ZKProof,
        publicInputs: PublicInputs
    ): Promise {
        // Submit proof to zkVerify network
        const submission = await this.zkVerifyClient.submitProof({
            proof: proof.serialize(),
            publicInputs: publicInputs.serialize(),
            provingSystem: 'Groth16' // or Plonky2, RISC0, etc.
        });

        // Achieve 91% cost reduction
        const estimatedL1Cost = await this.estimateL1VerificationCost(proof);
        const zkVerifyCost = submission.verificationCost;

        console.log(`Cost reduction: ${
            ((estimatedL1Cost - zkVerifyCost) / estimatedL1Cost * 100).toFixed(1)
        }%`);

        return this.waitForVerification(submission.id);
    }

    private async handleBatchVerification(): Promise {
        // Process multiple proofs in batches for additional cost savings
        const batchSize = 50;
        const batches = this.chunkArray(this.proofQueue, batchSize);

        for (const batch of batches) {
            await this.zkVerifyClient.submitBatch(batch);
        }
    }
}

Support for Multiple Proof Systems

The power of zkVerify lies in its support for various proof systems. Oraclizer utilizes the following proof systems as appropriate for different situations:

  • Groth16: When compact proof size is needed
  • Plonky2: When fast proof generation is important
  • RISC0: When general computation proofs are required
  • UltraPlonk: Optimized for complex circuits

Core Component 3: Base L2 Bridge Connection

Strategic Integration with Coinbase Base

The connection with Base L2 serves as a crucial bridge allowing Oraclizer to interoperate with the entire Ethereum ecosystem. Base is an OP Stack-based L2 developed by Coinbase, with a verified user base of over 100 million, which we expect to play an important role in Oraclizer’s mass adoption.

// Base L2 bridge interface
interface IBaseBridge {
    struct StateCommitment {
        bytes32 oraclizerStateRoot;
        uint256 blockNumber;
        bytes proof;
    }

    function commitState(
        StateCommitment calldata commitment
    ) external;

    function verifyStateInclusion(
        bytes32 stateRoot,
        bytes calldata proof
    ) external view returns (bool);
}

contract OraclizerBaseBridge is IBaseBridge {
    using OPStack for CrossChainMessage;

    mapping(bytes32 => bool) public verifiedStates;

    function commitState(
        StateCommitment calldata commitment
    ) external override onlyOraclizerL3 {
        // State commit through OP Stack messaging
        bytes memory message = abi.encode(
            commitment.oraclizerStateRoot,
            commitment.blockNumber
        );

        // Send message to Base L2
        IL2CrossDomainMessenger(BASE_MESSENGER).sendMessage(
            address(this),
            message,
            uint32(200000) // gas limit
        );

        verifiedStates[commitment.oraclizerStateRoot] = true;

        emit StateCommitted(
            commitment.oraclizerStateRoot,
            commitment.blockNumber
        );
    }
}

Ultimate Finality to Ethereum L1

The process of ultimate finality reaching Ethereum L1 via Base L2 is as follows:

  1. State update on L3 → Proof verification with zkVerify
  2. State commitment to Base L2 → Using the OP Stack messaging system
  3. Finality to Ethereum L1 → Through Base’s periodic state root submissions

Through this multi-layered structure, Oraclizer can inherit Ethereum’s security while significantly improving cost efficiency.

Core Component 4: Oracle State Synchronizer (OSS)

The Brain of State Synchronization

The Oracle State Synchronizer (OSS) acts as the brain of Oraclizer. It takes on the central role of detecting, verifying, and synchronizing all state changes.

The most important function of OSS is ensuring cross-chain state consistency. When oracle requests come in simultaneously from multiple blockchains, preventing duplicate processing for the same asset is crucial.

# OSS core logic (Python pseudocode)
class OracleStateSynchronizer:
    def __init__(self):
        self.state_locks = {}  # Locks by asset
        self.pending_updates = Queue()
        self.confirmed_states = StateTree()

    async def process_oracle_request(self, request: OracleRequest) -> bool:
        asset_id = request.asset_id

        # 1. Check preemptive lock
        if asset_id in self.state_locks:
            logger.info(f"Asset {asset_id} is locked, queuing request")
            return await self.queue_request(request)

        # 2. Lock asset
        self.state_locks[asset_id] = {
            'locked_at': time.now(),
            'request_id': request.id,
            'chain_id': request.source_chain
        }

        try:
            # 3. Execute state change
            result = await self.execute_state_change(request)

            # 4. Generate and verify proof with zkVerify
            proof = await self.generate_state_proof(result)
            verification = await self.zkverify_client.verify(proof)

            if verification.is_valid:
                # 5. Update state tree
                self.confirmed_states.update(asset_id, result.new_state)

                # 6. Cross-chain propagation
                await self.broadcast_state_update(result)

                return True
            else:
                await self.rollback_state_change(request)
                return False

        finally:
            # 7. Release lock
            del self.state_locks[asset_id]

    async def execute_state_change(self, request: OracleRequest) -> StateChangeResult:
        """Actual state change logic"""
        current_state = await self.get_current_state(request.asset_id)

        # Regulatory compliance verification
        compliance_check = await self.verify_compliance(request, current_state)
        if not compliance_check.is_compliant:
            raise ComplianceError(compliance_check.reason)

        # Execute state transition
        new_state = await self.apply_state_transition(
            current_state,
            request.transition_data
        )

        return StateChangeResult(
            asset_id=request.asset_id,
            previous_state=current_state,
            new_state=new_state,
            timestamp=time.now()
        )

Collaboration with D-quencer

OSS works closely with the D-quencer (Decentralized Sequencer). When D-quencer determines the transaction order, OSS processes state updates accordingly.

Collaboration with Active Asserters elected through VRF based on BLS signatures is particularly important:

// D-quencer and OSS interface
interface IDquencerOSSInterface {
    struct SequencedUpdate {
        bytes32 updateHash;
        uint256 sequence;
        address asserter;
        bytes signature;
    }

    function processSequencedUpdate(
        SequencedUpdate calldata update
    ) external returns (bool success);

    function requestStateRollback(
        bytes32 updateHash,
        string calldata reason
    ) external;
}

Core Component 5: RWA Registry Contract

Single Source of Truth

The RWA Registry serves as the Single Source of Truth (SST) managing the on-chain state of all real-world assets. This contract is deployed on Oraclizer L3 and acts as the reference point for all state synchronization.

// RWA Registry contract core section
contract RWARegistry {
    using SafeMath for uint256;

    struct Asset {
        bytes32 assetId;
        address owner;  // Pseudonymous address based on OCID
        uint256 value;
        AssetType assetType;
        LockStatus lockStatus;
        uint256 lastUpdated;
        bytes32 metadataHash;
    }

    enum AssetType { BOND, STOCK, REAL_ESTATE, COMMODITY, GAME_ITEM }
    enum LockStatus { UNLOCKED, TEMP_LOCKED, PERM_LOCKED, REGULATORY_LOCKED }

    mapping(bytes32 => Asset) public assets;
    mapping(bytes32 => bool) public oracleContracts; // Active oracle contracts
    mapping(address => bytes32[]) public userAssets;

    event AssetStateChanged(
        bytes32 indexed assetId,
        address indexed owner,
        uint256 newValue,
        LockStatus newStatus
    );

    event OracleContractInitiated(
        bytes32 indexed assetId,
        address indexed requester,
        bytes32 contractId
    );

    modifier onlyOSS() {
        require(msg.sender == ossAddress, "Only OSS can update");
        _;
    }

    function updateAssetState(
        bytes32 assetId,
        uint256 newValue,
        LockStatus newStatus,
        bytes calldata proof
    ) external onlyOSS {
        Asset storage asset = assets[assetId];
        require(asset.assetId != 0, "Asset does not exist");

        // Verification before state update
        require(verifyStateTransition(asset, newValue, newStatus, proof), 
                "Invalid state transition");

        // Prevent double spending
        require(!oracleContracts[assetId] || newStatus == LockStatus.UNLOCKED,
                "Asset is locked in oracle contract");

        asset.value = newValue;
        asset.lockStatus = newStatus;
        asset.lastUpdated = block.timestamp;

        emit AssetStateChanged(assetId, asset.owner, newValue, newStatus);
    }

    function initiateOracleContract(
        bytes32 assetId,
        address requester
    ) external onlyOSS returns (bytes32 contractId) {
        require(assets[assetId].lockStatus == LockStatus.UNLOCKED,
                "Asset is not available");

        contractId = keccak256(abi.encodePacked(
            assetId,
            requester,
            block.timestamp,
            block.number
        ));

        // Lock asset
        assets[assetId].lockStatus = LockStatus.TEMP_LOCKED;
        oracleContracts[assetId] = true;

        emit OracleContractInitiated(assetId, requester, contractId);
    }
}

Cross-chain Access Interface

The RWA Registry provides standardized interfaces for access from various blockchains:

// Cross-chain bridge interface
interface IRWARegistryBridge {
    function queryAssetState(
        bytes32 assetId
    ) external view returns (
        address owner,
        uint256 value,
        AssetType assetType,
        LockStatus lockStatus
    );

    function requestOracleContract(
        bytes32 assetId,
        bytes calldata contractData
    ) external payable returns (bytes32 requestId);
}

Component Interactions: A Real Operation Scenario

Let’s examine how these five core components work together through a real scenario.

Scenario: Using Tokenized Treasury Bonds as DeFi Collateral

  1. A lending protocol on Arbitrum wants to use tokenized US Treasury bonds as collateral
  2. OSS detects the request and checks the status of the treasury bond in the RWA Registry
  3. Asset locking: The Registry changes the status of the bond to TEMP_LOCKED
  4. State change proof: Generate a ZK proof for the lock state change
  5. zkVerify verification: The generated proof is verified on the zkVerify network
  6. Cross-chain propagation: Send state update to Arbitrum via Base L2
  7. Loan execution: Arbitrum verifies the collateral and executes the loan
  8. State finalization: Final state commitment from Base to Ethereum L1

Performance Optimization and Challenges in Development

Gas Efficiency Achievement Process

Reaching our goal of 93% gas cost reduction involved numerous trials and errors. The initial prototype only achieved about 60% reduction, but we reached our target through the following optimizations:

// Gas optimization example: Batch processing
class BatchProcessor {
    private batchSize = 100;
    private pendingUpdates: StateUpdate[] = [];

    async optimizeBatch(updates: StateUpdate[]): Promise {
        // 1. Group similar state updates
        const groupedUpdates = this.groupSimilarUpdates(updates);

        // 2. Compress into Merkle batch
        const merkleRoot = this.buildMerkleTree(groupedUpdates);

        // 3. Batch verification in zkVerify
        const batchProof = await this.generateBatchProof(merkleRoot);

        return {
            root: merkleRoot,
            proof: batchProof,
            gasEstimate: this.estimateGasCost(batchProof)
        };
    }

    private groupSimilarUpdates(updates: StateUpdate[]): UpdateGroup[] {
        // Group by identical asset types and similar value ranges
        return updates.reduce((groups, update) => {
            const key = `${update.assetType}-${Math.floor(update.value / 1000)}`;
            if (!groups[key]) groups[key] = [];
            groups[key].push(update);
            return groups;
        }, {} as Record);
    }
}

Latency Minimization

For real-time state synchronization, we needed to minimize communication delays between components. We introduced predictive proof generation to address bottlenecks, particularly in communication with the zkVerify network:

class PredictiveProofGenerator:
    def __init__(self):
        self.proof_cache = LRUCache(maxsize=1000)
        self.pattern_analyzer = StatePatternAnalyzer()

    async def generate_proof_predictively(self, state_change: StateChange):
        # Predict next states through pattern analysis
        predicted_states = self.pattern_analyzer.predict_next_states(
            state_change.asset_id,
            state_change.current_state
        )

        # Pre-generate proofs for likely states
        for predicted_state in predicted_states[:3]:  # Only top 3
            future_proof = await self.pre_generate_proof(
                state_change.current_state,
                predicted_state
            )
            self.proof_cache.set(
                self.generate_cache_key(state_change.asset_id, predicted_state),
                future_proof
            )

Security Considerations and Audit Results

The security of each component directly impacts the reliability of the entire system. Permission management between RWA Registry and OSS was particularly important:

// Multi-signature based permission management
contract SecurityManager {
    using ECDSA for bytes32;

    struct MultiSigConfig {
        address[] signers;
        uint256 threshold;
        uint256 nonce;
    }

    mapping(bytes32 => MultiSigConfig) public configs;

    function executeWithMultiSig(
        bytes32 configId,
        bytes calldata data,
        bytes[] calldata signatures
    ) external {
        MultiSigConfig storage config = configs[configId];
        require(signatures.length >= config.threshold, "Insufficient signatures");

        bytes32 hash = keccak256(abi.encodePacked(
            data,
            config.nonce++
        )).toEthSignedMessageHash();

        uint256 validSigs = 0;
        for (uint i = 0; i < signatures.length; i++) {
            address signer = hash.recover(signatures[i]);
            if (isValidSigner(configId, signer)) {
                validSigs++;
            }
        }

        require(validSigs >= config.threshold, "Invalid signatures");

        // Execute only when verified
        (bool success, ) = address(this).call(data);
        require(success, "Execution failed");
    }
}

In this article, we’ve examined the five core components that constitute the oracle state machine. You’ve seen how each plays a specialized role while collaboratively working toward the common goal of complete state synchronization.

In our next article, we’ll explore in more detail how these components operate in actual RWA tokenization scenarios through specific use cases.

References

[1]. Polygon Labs. (2024). Polygon CDK Documentation. https://docs.polygon.technology/cdk/

[2]. Horizen Labs. (2024). zkVerify: Modular ZK Proof Verification Network. https://zkverify.io/

[3]. Coinbase. (2024). Base: An Ethereum L2 by Coinbase. https://base.org/

[4]. Optimism Collective. (2024). OP Stack Documentation. https://stack.optimism.io/

[5]. Ethereum Foundation. (2024). Layer 2 Scaling Solutions. https://ethereum.org/en/layer-2/

Read Next