Free 30-min Web3 Consultation
Book Consultation
Smart Contract Security Audits
View Audit Services
Custom DeFi Protocol Development
Explore DeFi
Full-Stack Web3 dApp Development
View App Services
Free 30-min Web3 Consultation
Book Consultation
Smart Contract Security Audits
View Audit Services
Custom DeFi Protocol Development
Explore DeFi
Full-Stack Web3 dApp Development
View App Services
Free 30-min Web3 Consultation
Book Consultation
Smart Contract Security Audits
View Audit Services
Custom DeFi Protocol Development
Explore DeFi
Full-Stack Web3 dApp Development
View App Services
Free 30-min Web3 Consultation
Book Consultation
Smart Contract Security Audits
View Audit Services
Custom DeFi Protocol Development
Explore DeFi
Full-Stack Web3 dApp Development
View App Services
LABS
Guides

Setting Up a Confidential Smart Contract Framework for Supply Agreements

A developer tutorial for building supply agreements where contract logic and state remain private between parties, using frameworks like Aztec, Secret, or Polygon Nightfall.
Chainscore © 2026
introduction
PRACTICAL GUIDE

Setting Up a Confidential Smart Contract Framework for Supply Agreements

This guide walks through implementing a confidential smart contract system for supply chain agreements using the Oasis Sapphire EVM and the OpenZeppelin Governor framework.

Confidential smart contracts are essential for supply chains where contract terms—such as pricing, rebates, and penalties—must remain private between counterparties while execution remains verifiable on-chain. Unlike public contracts, they use Trusted Execution Environments (TEEs) or secure enclaves to process encrypted data. For this setup, we'll use the Oasis Sapphire network, an EVM-compatible, confidential ParaTime. Its key feature is the ability to perform computations on encrypted data using the @oasisprotocol/sapphire-paratime library, ensuring inputs, outputs, and state remain confidential unless explicitly revealed.

To begin, initialize a Hardhat project and install the necessary dependencies. You'll need the Oasis Sapphire Hardhat plugin and OpenZeppelin contracts for governance. Your hardhat.config.js must be configured for the Sapphire testnet. The core of a confidential agreement is a contract that stores encrypted terms. We can create a ConfidentialSupplyAgreement.sol that uses Sapphire's encrypt and decrypt precompiles. Critical terms like unitPrice and penaltyRate are stored as encrypted bytes and can only be decrypted by the contract logic itself or authorized parties with the correct key.

Here is a basic structure for the confidential agreement contract:

solidity
import "@oasisprotocol/sapphire-contracts/contracts/Sapphire.sol";
contract ConfidentialSupplyAgreement {
    bytes private encryptedTerms;
    address public buyer;
    address public supplier;
    constructor(address _buyer, address _supplier, bytes memory _terms) {
        buyer = _buyer;
        supplier = _supplier;
        encryptedTerms = Sapphire.encrypt(_terms, bytes32(0)); // Encrypt with network key
    }
    function calculatePayment(uint256 deliveredUnits) public view returns (uint256) {
        require(msg.sender == buyer || msg.sender == supplier, "Unauthorized");
        bytes memory terms = Sapphire.decrypt(encryptedTerms);
        // Decode terms and perform confidential calculation
        // Return payment amount
    }
}

This contract encrypts the terms on deployment. The calculatePayment function decrypts them within the secure enclave to compute a result, which is then returned as a public output.

Managing upgrades and amendments to such sensitive agreements requires a secure governance mechanism. Integrate OpenZeppelin Governor to allow the buyer and supplier to vote on proposal to change encrypted terms. Proposals should themselves contain the new encrypted terms data. The Governor contract, which is public, will call a function on the confidential agreement that only executes the update if the proposal succeeds. This separation ensures the governance process is transparent, while the commercial data remains entirely private within the execution of the confidential contract.

For off-chain components, you need a client script to format and encrypt the initial agreement terms. Use the @oasisprotocol/sapphire-paratime npm package in a Node.js script. The workflow is: 1) Define terms as a JSON object, 2) Serialize it to bytes, 3) Encrypt it using the Sapphire.encrypt method with the appropriate keying mechanism (like the runtime's public key for on-chain encryption). This encrypted payload is what you pass to the contract constructor. Only the contract, running inside the TEE, can decrypt it.

Testing and deploying this framework requires the Oasis Sapphire testnet (available via the Oasis Dashboard). Use Hardhat scripts to deploy your Governor and confidential agreement contracts. Key considerations include managing gas costs for confidential computations, which are higher, and ensuring all sensitive logic is contained within functions that call Sapphire.decrypt. Always audit the public interface of your contract to ensure no confidential data is inadvertently logged or emitted in events. This setup provides a verifiable, automated, and private execution layer for complex supply chain agreements.

prerequisites
GETTING STARTED

Prerequisites and Setup

This guide outlines the essential tools and foundational knowledge required to build a confidential smart contract framework for supply chain agreements using zero-knowledge cryptography.

Before writing any code, you must establish a development environment capable of handling zero-knowledge circuits and confidential state. This requires installing Node.js (v18+) and a package manager like npm or yarn. You will also need a basic understanding of TypeScript/JavaScript for writing application logic and interacting with the blockchain. For the cryptographic heavy lifting, we will use the snarkjs library and a ZK-friendly language like Circom for circuit design. Ensure your system has sufficient memory (8GB+ RAM recommended) as ZK proof generation can be computationally intensive.

The core of a confidential framework is the zero-knowledge circuit. You will design this circuit in Circom to validate business logic—such as verifying a shipment's arrival meets contractual terms—without revealing the underlying data. Start by installing the Circom compiler from the official repository. You will also need a trusted setup ceremony to generate the proving and verification keys for your circuit, a critical step for security. For testing, frameworks like Hardhat or Foundry are essential, as they allow you to deploy and interact with your verifier contract on a local Ethereum Virtual Machine (EVM) network.

Finally, you need a blockchain environment for deployment. While you can start with a local Hardhat Network or Anvil, you should plan for testnets that support the necessary precompiles for ZK verification, such as Sepolia or Polygon zkEVM testnet. Your smart contract will primarily consist of a verifier (generated from your circuit) and a state management contract that stores encrypted commitments. Have a wallet like MetaMask configured and ensure you have test ETH for your chosen network. With these components installed, you are ready to proceed to circuit design and contract development.

key-concepts-text
CORE CONCEPTS: ZERO-KNOWLEDGE AND TRUSTED EXECUTION

Setting Up a Confidential Smart Contract Framework for Supply Agreements

This guide explains how to build a confidential smart contract system for supply chain agreements using zero-knowledge proofs and trusted execution environments.

Confidential supply agreements require verifying sensitive business logic—like pricing tiers, volume discounts, and delivery schedules—without revealing the underlying data to competitors or unauthorized parties. Traditional smart contracts on public blockchains like Ethereum expose all state and logic, which is unsuitable for B2B contracts. To solve this, developers combine zero-knowledge proofs (ZKPs) and Trusted Execution Environments (TEEs). ZKPs, implemented with frameworks like zk-SNARKs (via Circom or Halo2) or zk-STARKs, allow one party to prove a statement is true without revealing the inputs. TEEs, such as Intel SGX or AMD SEV, create secure, isolated enclaves for private computation.

The technical architecture involves an off-chain component for confidential computation and an on-chain verifier. For a volume discount agreement, the supplier's off-chain client would generate a ZKP (e.g., using the gnark library) that proves an invoice total is correct according to a hidden pricing schedule, given a public order quantity. This proof is then submitted to a verifier smart contract. Alternatively, a TEE-based oracle (like Oraichain or a custom Intel SGX enclave) can compute the final price within a secure environment and attest to its correctness before posting the result on-chain. The choice between ZKP and TEE depends on the trade-off between computational overhead and trust assumptions.

To implement a basic ZKP verifier for a supply agreement, you would first define the circuit logic. Using the Circom language, you could create a circuit that constrains the output price based on secret tiered pricing parameters and a public quantity. After compiling the circuit and generating a proving key, your off-chain application (e.g., a Node.js service) uses these to generate proofs for each transaction. The corresponding Solidity verifier contract, generated by snarkjs, can then be deployed to a chain like Ethereum or Polygon zkEVM. The on-chain contract only needs the proof and public inputs to verify the computation's validity in a single, gas-efficient transaction.

For TEE-based confidentiality, you would develop a Rust application using the Fortanix EDP SDK for Intel SGX. This application, running inside an enclave, would take encrypted inputs (order details), decrypt them using a sealed key, execute the pricing logic, sign the output with the enclave's attestation, and return an encrypted result. A blockchain relayer or oracle network would then forward this attested result to the smart contract. The contract verifies the attestation signature against a known list of authorized enclave keys (like Intel's root certificate) before accepting the price data. This model is used by projects like Phala Network for confidential smart contracts.

Key security considerations include the trusted setup for ZKPs, which requires a secure multi-party ceremony for circuits like Groth16, and the hardware trust in TEEs, which relies on the manufacturer's security guarantees and proper remote attestation. For production, integrate with existing privacy-focused L2s such as Aztec Network for ZK-rollups or use a TEE-based parachain on Polkadot. Always audit both the circuit/logic and the surrounding application code, and consider using standardized frameworks like ZKPS from the EEA to ensure interoperability and security in your confidential supply chain framework.

FRAMEWORK SELECTION

Comparing Confidential Smart Contract Frameworks

Key technical and operational differences between leading frameworks for building confidential supply chain agreements.

Feature / MetricOasis SapphireSecret NetworkPhala Network

Confidentiality Model

Trusted Execution Environment (TEE)

Trusted Execution Environment (TEE)

Trusted Execution Environment (TEE)

Consensus Layer

Paratime on Oasis Network

Cosmos SDK with Tendermint

Substrate with Nominated Proof-of-Stake

Programming Language

Solidity, Rust

Rust (CosmWasm)

Rust (Phat Contract)

Gas Fees for Confidential Compute

$0.01 - $0.10 per tx

$0.05 - $0.20 per tx

$0.001 - $0.03 per tx

Confidential State Storage

Cross-Chain Messaging (IBC)

Time to Finality

< 6 seconds

~6 seconds

~12 seconds

EVM Compatibility

TECHNICAL GUIDE

Implementation by Platform

Using Aztec for Private Agreements

Aztec Network is a ZK-rollup on Ethereum designed for confidential smart contracts. It uses zero-knowledge proofs to hide transaction amounts and participant identities on-chain.

Key Components for Supply Agreements:

  • Aztec.nr Framework: A Noir-based language for writing private logic.
  • Private State Variables: Data is encrypted and stored in private data trees.
  • L2 <> L1 Communication: Use the Portal Bridge for asset transfers and the rollup processor for proof verification.

Implementation Steps:

  1. Write your contract logic in Aztec.nr, defining private functions for sensitive terms like unit_price and delivery_date.
  2. Compile to an ACIR circuit and generate a proving/verification key.
  3. Deploy the contract to the Aztec Sandbox for testing.
  4. Integrate the Aztec.js SDK into your dApp frontend to create private transactions.

Considerations:

  • Gas costs are primarily for proof verification on L1.
  • Currently supports confidential ERC20 transfers and custom private logic.
  • The sequencer is currently centralized, with decentralization on the roadmap.
contract-design
SMART CONTRACT FRAMEWORK

Designing the Confidential Supply Agreement

This guide details the architecture for a confidential smart contract that automates and secures supply chain agreements using zero-knowledge proofs and private computation.

A confidential supply agreement smart contract must manage sensitive commercial data—such as pricing, volumes, and quality metrics—while enabling verifiable execution of contractual terms. Unlike public DeFi contracts, this requires a framework that separates public state logic from private business logic. The core architecture typically involves a public verification contract on a mainnet like Ethereum, which holds commitments to private data, and an off-chain privacy layer (e.g., Aztec Network, Polygon Nightfall, or a custom ZK-rollup) where the actual computation on encrypted inputs occurs. This separation ensures that only the cryptographic proofs of correct execution are published on-chain, keeping the underlying data confidential between the transacting parties.

The contract's state variables are designed to reflect the agreement's lifecycle without exposing details. Public variables might include a unique agreementId, the hashed identities of the supplier and buyer, a status enum (e.g., Active, Fulfilled, Disputed), and a cryptographic commitment (like a Merkle root or a Pedersen commitment) representing the current state of private terms. Critical private terms, stored and computed off-chain, include the unitPrice, orderQuantity, deliverySchedule, and qualitySpecifications. A state transition, such as confirming a shipment, requires the involved party to generate a zero-knowledge proof (ZKP) demonstrating they possess valid private data that satisfies the contract's rules, which is then verified by the public contract.

Implementing the logic requires defining the precise conditions for state updates. For a shipment confirmation, the private computation would validate that the deliveredQuantity and qualityHash match the order terms, and that the current timestamp is within the agreed window. Using a ZK-SNARK circuit library like circom or halo2, you would construct a circuit that takes private inputs (the actual data and a secret) and public inputs (the new state commitment). The circuit outputs a proof that, when verified on-chain, updates the public commitment without revealing the inputs. Here is a conceptual structure for the core verification function in Solidity:

solidity
function verifyShipment(
    bytes32 newStateCommitment,
    bytes calldata zkProof
) external onlyCounterparty {
    require(verifyZKProof(newStateCommitment, zkProof), "Invalid proof");
    stateCommitment = newStateCommitment;
    emit StateUpdated(msg.sender, newStateCommitment);
}

Key design considerations include oracle integration for external verification and dispute resolution. While ZKPs guarantee computational correctness, they cannot verify real-world events. A trusted oracle (like Chainlink) may be needed to confidentially attest to a shipment's arrival or a quality audit result, providing a signed data feed that serves as a private input to the ZK circuit. For disputes, the framework should include a challenge period and a fallback to a secure multi-party computation (MPC) or trusted execution environment (TEE)-based arbitration protocol, where a third party can decrypt and evaluate the private state under specific, auditable conditions without making it permanently public.

Finally, developers must address key management and user experience. Each party will need a client-side wallet capable of generating and managing private data, computing ZK proofs locally (or via a service like Ingo), and submitting transactions. Frameworks like Aztec.js or ZK-Kit provide SDKs for this interaction layer. The end-to-end flow ensures that a supply agreement's commercial sensitivity is preserved while leveraging blockchain's trustless automation, creating a foundation for private enterprise DeFi and compliant digital asset tracking.

IMPLEMENTATION PATTERNS

Code Examples: Core Contract Functions

Public Verification Interface

This Solidity interface defines the functions that will be deployed on a public L1/L2 (like Ethereum or Arbitrum) to interact with off-chain confidential computation. The core function verifies a ZK-SNARK proof.

solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;

interface IConfidentialSupplyVerifier {
    /// @notice Public state of the agreement
    struct AgreementPublicState {
        address supplier;
        address buyer;
        uint256 totalValue;
        bool isFulfilled;
        bytes32 publicStateRoot; // Merkle root of public commitments
    }

    /// @notice Verifies a proof for a confidential supply agreement clause.
    /// @param agreementId The unique identifier for the supply agreement.
    /// @param proof The zk-SNARK proof bytes (e.g., Groth16 proof).
    /// @param publicInputs Array of public inputs used in the proof verification.
    /// @return isValid True if the proof is valid, triggering state update.
    function verifyDeliveryProof(
        bytes32 agreementId,
        bytes calldata proof,
        uint256[] calldata publicInputs
    ) external returns (bool isValid);

    /// @notice Allows parties to submit an encrypted data commitment.
    /// @param agreementId The agreement identifier.
    /// @param commitmentHash The hash of the encrypted terms (e.g., hash(encrypted_price, encrypted_quantity)).
    function submitDataCommitment(bytes32 agreementId, bytes32 commitmentHash) external;

    // View function to check public state
    function getAgreementState(bytes32 agreementId) external view returns (AgreementPublicState memory);
}

The actual confidential logic (e.g., calculatePenalty) runs off-chain using a ZK circuit or inside a TEE, with only the proof and necessary public outputs sent to this verifier.

testing-deployment
GUIDE

Testing and Deploying to a Privacy Network

This guide details the process of developing, testing, and deploying a confidential smart contract for supply chain agreements using the Aztec Network.

Confidential smart contracts enable selective data visibility, a critical feature for supply agreements where parties need to prove compliance without revealing sensitive commercial terms. Unlike public blockchains, privacy networks like Aztec use zero-knowledge proofs (ZKPs) to encrypt state. For a supply agreement, this allows you to programmatically verify that a shipment quantity matches a purchase order, or that a payment is due, while keeping the exact price and item details private between the involved parties. The contract logic is public, but its data is not.

To begin, you'll set up a development environment. Install the Aztec Sandbox, a local development network, and the Aztec.nr framework. Initialize a new project using aztec-nargo new and examine the contract structure. A supply agreement contract typically includes private functions to agree_on_terms(price, quantity) visible only to the buyer and seller, and public functions like confirm_delivery() that can trigger escrow release. Use the PrivateContext and PublicContext to manage state visibility. Write your business logic in Noir, a ZK-friendly language similar to Rust.

Testing is paramount. Use the Aztec testing framework to simulate parties. You'll write integration tests that create private notes for the buyer and seller, execute the agreement function, and assert the expected private state transitions without revealing values. For example, a test can verify that after agree_on_terms, the seller's note is destroyed and a new conditional payment note is created, all within a shielded pool. Run tests with aztec test. Debugging requires inspecting transaction traces and note commitments, not raw data.

Before deploying to a testnet like Aztec's Sepolia rollup, compile your contract with aztec compile. This generates an artifact containing the contract's bytecode and a verification key for its ZK circuits. Deployment is done via the aztec deploy command, which publishes the contract's public functions to the L1 rollup contract and initializes any public state. The private functions and their initial encrypted notes are set up in a subsequent private initialization call. Fund your wallet with test ETH on Sepolia to cover gas fees for the public deployment step.

After deployment, interact with your contract using the Aztec.js client library. Create a Contract instance and use wallet.send() methods. To invoke a private function like submit_shipment_proof, the client will locally generate a ZK proof demonstrating valid state transition, then send only that proof to the network. Monitor transactions using a block explorer like Aztec's Explorer, which shows public function calls and encrypted note hashes. For ongoing development, consider using a CI pipeline to run your test suite against a forked sandbox to ensure reliability.

CONFIDENTIAL SMART CONTRACTS

Common Issues and Troubleshooting

Addressing frequent challenges and developer questions when implementing privacy-preserving supply chain agreements using frameworks like Aztec, Aleo, or Polygon Miden.

Proof verification errors are the most common failure point in ZK-based confidential contracts. This typically indicates a mismatch between the public inputs provided to the verifier and the ones committed to in the zero-knowledge proof.

Common causes include:

  • Public Input Mismatch: The publicInputs array sent with the transaction does not match the order or values hashed into the proof. Frameworks like Aztec require precise ordering.
  • Contract State Drift: The note's state (e.g., nullifier) you're trying to spend may have already been nullified in a previous block, making the historical state root in your proof invalid.
  • Incorrect Function Selector: Calling a private function with the wrong method ID or calling a public function that expects private inputs.

Debugging steps:

  1. Use the framework's local sandbox (e.g., Aztec's aztec-sandbox) to re-simulate the transaction and inspect the generated proof's public inputs.
  2. Double-check that all nullifiers are computed correctly and correspond to notes you own.
  3. Ensure the contract address and function selector in your transaction call are correct.
CONFIDENTIAL SMART CONTRACTS

Frequently Asked Questions

Common technical questions and troubleshooting for developers implementing confidential supply chain agreements using frameworks like Aztec, ZK-Rollups, and FHE.

A confidential smart contract is a program that executes on a blockchain while keeping its internal state, inputs, and sometimes logic hidden from public view. This is achieved through cryptographic techniques like zero-knowledge proofs (ZKPs) or fully homomorphic encryption (FHE).

Key differences from standard contracts:

  • State Privacy: On Ethereum, all contract storage is public. Confidential frameworks encrypt this data.
  • Transaction Privacy: Amounts, participant identities, and specific terms can be hidden.
  • Computational Overhead: Generating ZKPs or performing FHE operations adds significant gas costs and latency.
  • Prover/Verifier Model: Transactions often require generating a proof off-chain (prover) that is verified on-chain, unlike standard contract execution.

Frameworks like Aztec Network and Aleo use ZKPs, while projects like Fhenix and Inco Network are exploring FHE for on-chain confidentiality.

conclusion
IMPLEMENTATION SUMMARY

Conclusion and Next Steps

You have now configured a confidential smart contract framework for supply chain agreements using zero-knowledge proofs and private state.

This guide walked through implementing a confidential supply agreement using Aztec Network's Noir language and Aztec.nr framework. You created a private SupplyAgreement contract that keeps order quantities, pricing, and delivery schedules confidential on-chain, visible only to the transacting parties. The core mechanism uses a SharedImmutable storage variable, initialized via a private constructor, to establish a secret shared state between a manufacturer and a supplier. This ensures sensitive commercial terms are not exposed to competitors or other network participants.

The next logical step is to expand the contract's functionality. Consider adding verifiable delivery attestations where the supplier can privately submit a proof of shipment, or implementing confidential penalty clauses that automatically deduct from a bonded escrow for late deliveries without revealing the penalty amount publicly. You could also integrate with Chainlink Functions to fetch private oracle data, such as encrypted market prices, to trigger conditional payments within the agreement.

To deploy this into a production environment, you must rigorously test the circuit logic. Use the Noir playground to write comprehensive unit tests for your main function, covering edge cases in order validation and payment calculation. For the contract layer, write integration tests using the Aztec.js library within a sandbox environment to simulate private transactions between multiple parties. Audit the zk-SNARK circuit for potential arithmetic overflows or constraints that could leak information.

Explore other privacy-preserving architectures for comparison. Polygon Miden uses a different STARK-based virtual machine for confidential assets, while Espresso Systems leverages configurable data availability committees. The choice between a validium (data off-chain) like Aztec and a zk-rollup (data on-chain) often hinges on your application's specific trade-off between cost, throughput, and security assumptions regarding data availability.

Finally, engage with the developer communities for ongoing support. The Aztec Discord is active for technical questions. Review the Noir documentation for advanced circuit patterns and the Aztec.nr book for contract development details. By building on this foundation, you can create sophisticated, compliant DeFi and enterprise applications that require transactional privacy.

How to Build Confidential Smart Contracts for Supply Agreements | ChainScore Guides