Skip to content

Latest commit

 

History

History
 
 

README.md

Smart Contract Reference Guide

Complete reference documentation for the Invoice Liquidity Network (ILN) smart contracts. These documents provide developers with all function signatures, parameters, return values, error conditions, and examples needed to integrate with ILN.


Contract Overview

The ILN system consists of three main smart contracts deployed on Stellar:

Contract Purpose Language
Invoice Liquidity Core escrow, invoices, funding Rust (Soroban)
Governance Proposals, voting, delegation Rust (Soroban)
Reputation Bonus Reputation scoring, discount bonuses Rust (Soroban)

Quick Reference by Use Case

I want to...

Submit an invoice for funding

  • Read: Invoice Contract
  • Function: submit_invoice(freelancer, payer, amount, due_date, discount_rate, token)
  • Example: Freelancer creates invoice, LPs can fund it

Fund an invoice (as an LP)

  • Read: Invoice Contract
  • Function: fund_invoice(funder, invoice_id, fund_amount, require_oracle_verification?)
  • Example: LP contributes capital to earn discount rate

Query my invoices

  • Read: Invoice Contract
  • Function: list_invoices_by_submitter(submitter, page, page_size)
  • Example: Get paginated list of submitted invoices

Check my reputation score

  • Read: Invoice Contract
  • Function: get_reputation(address)
  • Example: Payer views reputation & payment history

Vote on a governance proposal

  • Read: Governance Contract
  • Function: cast_vote(voter, proposal_id, support)
  • Example: Token holder votes for/against parameter change

Create a governance proposal

  • Read: Governance Contract
  • Function: create_proposal(proposer, action_type, description_hash, proposed_value)
  • Example: Propose fee rate update

Delegate voting power

  • Read: Governance Contract
  • Function: delegate_votes(delegator, delegate)
  • Example: Delegate voting power to trusted party

Contracts by Function Category

Invoice Lifecycle

Submission & Modification

Funding

Settlement & Default

Disputes & Appeals

Query


Reputation & Scoring

Reputation Query

LP Analytics

Reputation Contracts


Governance & Administration

Proposals

Voting

Delegation

Admin

Configuration

Multi-Sig


Data Structures

Core Types

Invoice

  • Reference
  • All invoice data: parties, amounts, dates, status
  • Includes optional auction fields, LP whitelist, reputation snapshot

ReputationProfile

  • Reference
  • Score, counters (submitted/paid/defaulted), activity timestamp

LPStats

  • Reference
  • Aggregated portfolio metrics: total_funded, total_earned, active positions, average yield

GovernanceProposal

  • Reference
  • Proposal id, proposer, action, votes, status, timelock info

ProposalAction

  • Reference
  • Variants: UpdateFeeRate, AddToken, RemoveToken, UpdateMaxDiscountRate

ProposalStatus

  • Reference
  • Active, Passed, Rejected, Executed, Vetoed

Event Schema

Invoice Events

  • InvoiceSubmitted - Invoice created
  • InvoiceFunded - Successfully funded (individual funding)
  • InvoicePartiallyPaid - Partial payment recorded
  • InvoicePaid - Fully settled
  • InvoiceDefaulted - Unpaid past due date
  • InvoiceExpired - Never funded, due date passed
  • InvoiceCancelled - Submitter cancelled
  • InvoiceUpdated - Terms modified
  • InvoiceTransferred - Transferred to new recipient
  • InvoiceTokenChanged - Payment token changed
  • InvoiceDisputed - Payer contested
  • InvoiceAppealed - Appeal filed against default
  • DefaultAppealed - Appeal filed
  • AppealResolved - Appeal decision rendered

Auction Events

  • AuctionStarted - Dutch auction created
  • AuctionFunded - Funding during auction with effective rate

Reputation Events

  • ReputationUpdated - Score changed
  • PayerReputationDecayed - Time-based decay applied

Governance Events

  • ProposalCreated - Proposal submitted
  • VoteCast - Vote recorded
  • VotesDelegated - Delegation created
  • VotesUndelegated - Delegation revoked
  • ProposalExecuted - Proposal action executed
  • ProposalVetoed - Admin blocked proposal

Admin Events

  • AdminChanged - New admin set
  • TokenAdded - Token approved
  • TokenRemoved - Token disabled
  • ParameterUpdated - Config changed
  • ContractPaused / ContractUnpaused - Pause state toggled
  • ContractUpgraded - WASM upgraded

Error Codes Reference

Common Errors

  • Unauthorized - Caller not authorized
  • ContractPaused - Contract in emergency pause state

Invoice Errors (full list)

  • InvoiceNotFound - Invalid invoice ID
  • AlreadyFunded - Invoice fully funded
  • NotFunded - Invoice not yet funded
  • InvalidDueDate - Date outside valid range
  • PayerReputationTooLow - Payer below minimum score
  • LPNotWhitelisted - LP not in allowed list

Governance Errors (full list)

  • ProposalNotFound - Invalid proposal ID
  • VotingEnded - Voting period closed
  • AlreadyVoted - Voter already voted
  • QuorumNotReached - Insufficient participation
  • DelegationCyclePrevented - Would create delegation loop

Integration Patterns

SDK Usage

TypeScript SDK client examples:

import { ILNClient } from '@iln/sdk';

const client = new ILNClient({
  rpc: 'https://soroban-testnet.stellar.org',
  invoiceContractId: 'CD3TE3IAHM...',
});

// Submit invoice
const invoiceId = await client.submitInvoice({
  freelancer: freelancerAddress,
  payer: payerAddress,
  amount: BigInt('10000000'),
  dueDate: futureTimestamp,
  discountRate: 300,
  token: usdcAddress,
});

// Fund invoice
await client.fundInvoice({
  funder: lpAddress,
  invoiceId: invoiceId,
  fundAmount: BigInt('5000000'),
});

See: Integration Guide

Event Listening

Listen to contract events:

// Listen for InvoicePaid events
const subscription = client.on('InvoicePaid', (event) => {
  console.log('Invoice paid:', event.invoice_id);
  console.log('LP earned:', event.lp_earned);
});

See: Event Documentation

Governance Workflow

Typical governance proposal flow:

  1. Propose: Create proposal via governance contract
  2. Vote: Members vote during 3-day period
  3. Execute: After voting ends + timelock, execute proposal
  4. Effect: Proposal action executes on ILN contract

See: Governance Contract - Workflow Example


Architecture Diagram

┌─────────────────────────────────────────────────┐
│         Stellar Blockchain (Soroban)            │
├─────────────────────────────────────────────────┤
│                                                 │
│  ┌──────────────────────────────────────────┐  │
│  │  Invoice Liquidity Contract              │  │
│  │  • Invoice lifecycle                    │  │
│  │  • Funding & settlement                 │  │
│  │  • Disputes & appeals                   │  │
│  │  • Reputation scoring                   │  │
│  │  • Batch operations                     │  │
│  └──────────┬──────────────────────────────┘  │
│             │ executes via governance         │
│             ▼                                  │
│  ┌──────────────────────────────────────────┐  │
│  │  Governance Contract                    │  │
│  │  • Proposal creation & voting           │  │
│  │  • Vote delegation (transitive)         │  │
│  │  • Timelock & execution                 │  │
│  │  • Admin veto (optional)                │  │
│  └──────────────────────────────────────────┘  │
│             ▲                                  │
│             │ updates config                  │
│             │                                  │
│  ┌──────────────────────────────────────────┐  │
│  │  Reputation Bonus Contract              │  │
│  │  • Reputation calculation               │  │
│  │  • Discount bonus computation           │  │
│  │  • Lifecycle hooks (submit/paid/default)│  │
│  └──────────────────────────────────────────┘  │
│                                                 │
│  + Tokens (USDC, XLM, EURC SACs)               │
│  + Optional: Price Oracle, Distribution Hooks  │
│                                                 │
└─────────────────────────────────────────────────┘
         │
         │ Web3 SDK
         ▼
┌─────────────────────────────────┐
│  Frontend / Backend Integration │
│  • Mobile app                   │
│  • Web dashboard                │
│  • API server                   │
│  • Notification service         │
└─────────────────────────────────┘

Testnet Deployment

Component Address Notes
Invoice Contract CD3TE3IAHM737P236XZL2OYU275ZKD6MN7YH7PYYAXYIGEH55OPEWYJC Core contract
USDC CBIELTK6YBZJU5UP2WWQEUCYKLPU6AUNZ2BQ4WWFEIE3USCIHMXQDAMA Test USDC
RPC https://soroban-testnet.stellar.org Stellar test network

Next Steps

  1. Read the appropriate contract reference based on your use case:

  2. Follow the Integration Guide to set up SDK and start coding:

  3. Monitor events for real-time updates:

  4. Review examples in the repository:


Support & Resources


Glossary

  • Invoice - A billing claim from freelancer to payer
  • LP (Liquidity Provider) - Provides capital to fund invoices
  • Funder - Alternative term for LP in context of specific invoice
  • Discount Rate - LP yield in basis points (bps)
  • Reputation Score - Account's reliability metric (0-100+)
  • Stroops - Smallest unit (10^-7 USDC)
  • Quorum - Minimum participation for governance (bps of total supply)
  • Timelock - Delay before proposal execution (ledgers)
  • Delegation - Transfer of voting power to another account
  • Default - Unpaid invoice after due date
  • Appeal - Payer contest of default marking
  • Dispute - Payer contest before settlement

TypeScript Type Alignment (packages/shared)

The drift problem

packages/shared/src/types.ts is the foundation every TypeScript consumer builds on. Before the audit in July 2026, the hand-maintained types had drifted significantly from the deployed contract. The table below records every finding so future auditors can verify the fix and catch new drift early.

Drift found and fixed (July 2026 audit)

InvoiceStatus (was InvoiceState)

Value Was present Notes
Pending
PartiallyFunded ❌ missing Added
Funded
Paid
Defaulted
Appealed ❌ missing Added
Disputed ❌ missing Added
Expired ❌ missing Added
Cancelled ❌ missing Added

InvoiceState kept as a deprecated alias for backward compatibility.

Invoice struct

Field Was present Fix
id, freelancer, payer, amount, dueDate, discountRate, status, funder, fundedAt
token ❌ missing Added — payment token address (USDC/XLM/EURC)
amountFunded ❌ missing Added — cumulative LP capital deployed
amountPaid ❌ missing Added — cumulative payer payments
submitterReputation ❌ missing Added — freelancer score snapshot at submission
referralCode ❌ missing Added — Uint8Array | null (BytesN<32>)
allowedLps ❌ missing Added — LP whitelist (string[] | null)
isAuction ❌ missing Added
auctionStartRate ❌ missing Added
auctionMinRate ❌ missing Added
auctionRateDecayPerHour ❌ missing Added
auctionStartedAt ❌ missing Added

ReputationScore

Field Was present Fix
address, score
updatedAt ❌ wrong name Renamed to lastActivityLedger (maps to last_activity_ledger u64)
invoicesSubmitted ❌ missing Added (invoices_submitted u64)
invoicesPaid ❌ missing Added (invoices_paid u64)
invoicesDefaulted ❌ missing Added (invoices_defaulted u64)

ProposalStatus

Value Was present Fix
Active
Draft ❌ phantom Removed — proposals go straight to Active
Succeeded ❌ wrong name Renamed to Passed
Defeated ❌ wrong name Renamed to Rejected
Executed
Cancelled ❌ phantom Removed — only invoice statuses include Cancelled
Vetoed ❌ missing Added

GovernanceProposal

Field Was present Fix
id, proposer, status, createdAt, votingEndsAt
title ❌ phantom Removed — not on-chain; proposals use description_hash
description ❌ phantom Removed — same reason
abstainVotes ❌ phantom Removed — contract only has votes_for / votes_against
executedAt ❌ wrong semantics Replaced with etaLedger (eta_ledger u32 — timelock ledger, not timestamp)
forVotes / againstVotes Renamed to votesFor / votesAgainst to match camelCase convention
descriptionHash ❌ missing Added (description_hash BytesN<32>)
actionType ❌ missing Added (action_type ProposalAction)
proposedValue ❌ missing Added (proposed_value i128)

ContractStats

Field Was present Fix
totalInvoices, totalVolume
totalYield ❌ phantom Removed — not in get_contract_stats() return value
defaultRate ❌ phantom Removed — not in get_contract_stats() return value
totalFunded ❌ missing Added (total_funded u64)
totalPaid ❌ missing Added (total_paid u64)

LPStats

Field Was present Fix
deployed ❌ wrong name Renamed to totalFunded (total_funded i128)
yield ❌ wrong name + reserved keyword Renamed to totalEarned (total_earned i128)
invoiceCount ❌ ambiguous Replaced by explicit activePositions + totalPositions
defaultRate ❌ phantom Removed — not in LPStats struct
activePositions ❌ missing Added (active_positions u64)
totalPositions ❌ missing Added (total_positions u64)
avgYieldBps ❌ missing Added (avg_yield_bps u32)

Events

Old type name Issue Fix
InvoiceCreatedEvent ("InvoiceCreated") Contract emits "InvoiceSubmitted" New canonical InvoiceSubmittedEvent; old name kept as deprecated alias
InvoiceRepaidEvent ("InvoiceRepaid") Contract emits "InvoicePaid" New canonical InvoicePaidEvent; old name kept as deprecated alias
GovernanceProposalVotedEvent ("ProposalVoted") Contract emits "VoteCast" New canonical VoteCastEvent; old name kept; weight: bigint field added
TokenListedEvent / TokenDelistedEvent Contract emits "TokenAdded" / "TokenRemoved" New canonical events; old names kept as deprecated aliases
InvoiceFundedEvent Missing amountFunded, effectiveYieldBps, status Fields added
ContractStatsUpdatedEvent / LPStatsUpdatedEvent Not emitted by contract Retained but documented as client-side synthetic events

Automated type generation

Manually maintaining packages/shared/src/types.ts is the root cause of every drift finding above. The correct long-term fix is to derive types directly from the contract's machine-readable Soroban spec.

How it works

stellar contract build         # compiles Rust → WASM
    ↓
stellar contract info          # extracts XDR spec → spec.json
    ↓
scripts/generate-shared-types.mts   # spec.json → types.ts
    ↓
packages/shared/src/types.ts   # committed, never hand-edited

Generating the spec

# From repo root (requires Stellar CLI and initialized contract submodule)
cd backend
stellar contract build
stellar contract info \
  --wasm target/wasm32v1-none/release/*.wasm \
  --output-format json > target/spec.json
cd ..

Running the generator

# Generate types.ts from an existing spec.json
pnpm generate:shared-types

# Dry-run — print to stdout without writing
node --import tsx/esm scripts/generate-shared-types.mts \
  --spec backend/target/spec.json \
  --dry-run

The generator is scaffolded at scripts/generate-shared-types.mts. It reads the UdtStructV0, UdtEnumV0, and UdtUnionV0 entries from spec.json and emits camelCase TypeScript interfaces and union types with inline comments pointing back to the contract field names and types.

CI enforcement

Once backend/target/spec.json is committed (or generated as a CI artifact), add this step to ci.yml alongside the existing sdk-types-sync job:

- name: Regenerate shared types
  run: pnpm generate:shared-types

- name: Check if shared types drifted
  run: |
    if ! git diff --exit-code packages/shared/src/types.ts; then
      echo "❌ Shared types are out of sync with the contract spec."
      echo "Run: pnpm generate:shared-types"
      exit 1
    fi

Current status

The generator is scaffolded and the pnpm generate:shared-types script is wired in package.json. It cannot run automatically in CI yet because backend/target/spec.json is not committed — the contract submodule must be initialized and built first. Until then, types.ts is manually maintained and must be audited against docs/contracts/ on every contract change.


Last Updated: July 2026 Contract Version: v1.0 Documentation Version: 1.0