Skip to content

Funding Proof

The Funding Proof demonstrates that a user has sufficient balance to cover a transaction without revealing the actual balance.

When creating a shielded intent, the user commits to an input amount but doesn’t reveal it. The Funding Proof proves:

“I have at least X tokens” without revealing “I have exactly Y tokens”

InputVisibilityDescription
commitment_hashPublicHash of the amount commitment
minimum_amountPublicRequired minimum balance
actual_balancePrivateUser’s true balance
blinding_factorPrivateCommitment randomness
  1. Balance Sufficiency: actual_balance >= minimum_amount
  2. Commitment Correctness: Pedersen(actual_balance, blinding) = commitment
use dep::std::hash::pedersen_hash;
fn main(
// Public inputs
commitment_hash: pub Field,
minimum_amount: pub u64,
// Private inputs (witness)
actual_balance: u64,
blinding_factor: Field,
) {
// Constraint 1: Sufficient balance
assert(actual_balance >= minimum_amount);
// Constraint 2: Commitment validity
let computed_commitment = pedersen_hash([
actual_balance as Field,
blinding_factor
]);
assert(computed_commitment == commitment_hash);
}
1. User has balance: 1000 tokens
2. User wants to send: 500 tokens
3. User creates commitment: C = Pedersen(500, random_blinding)
4. User generates proof:
- Public: hash(C), min=500
- Private: balance=1000, blinding=random
5. Verifier confirms: "User has at least 500 tokens"
PropertyGuarantee
SoundnessCannot prove false balance
Zero-knowledgeActual balance not revealed
BindingCannot change committed amount
import { MockProofProvider, FundingProofParams } from '@sip-protocol/sdk'
const proofProvider = new MockProofProvider()
const params: FundingProofParams = {
commitmentHash: '0x...',
minimumAmount: 500n,
actualBalance: 1000n,
blindingFactor: '0x...'
}
const result = await proofProvider.generateFundingProof(params)
if (result.valid) {
console.log('Proof:', result.proof)
}
interface FundingProof {
proof: HexString // ZK proof bytes
publicInputs: {
commitmentHash: Field
minimumAmount: u64
}
framework: 'noir' | 'mock'
timestamp: number
}

Solvers verify the funding proof before accepting an intent:

const isValid = await proofProvider.verifyProof(
fundingProof,
[commitmentHash, minimumAmount]
)
if (!isValid) {
throw new Error('Invalid funding proof')
}
CaseHandling
Balance = MinimumValid (equality allowed)
Balance < MinimumProof generation fails
Zero balanceProof fails unless min=0
OverflowConstrained by field size
MetricMockNoir (estimated)
Proof generation<1ms2-3s
Proof size64 bytes~200 bytes
Verification<1ms~10ms