Contract Architecture

Garden uses Hashed Time Lock Contracts (HTLCs) to implement atomic swap functionality on Starknet. The contract manages the lifecycle of a swap through four main operations with enhanced signature support and flexible initiation methods:

Core Functions

Initiate

The initiate function creates a new HTLC by locking ERC20 tokens in the contract. Starknet provides three flexible initiation methods:

Basic Initiation:

fn initiate(
    ref self: ContractState,
    redeemer: ContractAddress,
    timelock: u128,
    amount: u256,
    secret_hash: [u32; 8],
)

Initiation on Behalf:

fn initiate_on_behalf(
    ref self: ContractState,
    initiator: ContractAddress,
    redeemer: ContractAddress,
    timelock: u128,
    amount: u256,
    secret_hash: [u32; 8],
)

Signature-Based Initiation:

fn initiate_with_signature(
    ref self: ContractState,
    initiator: ContractAddress,
    redeemer: ContractAddress,
    timelock: u128,
    amount: u256,
    secret_hash: [u32; 8],
    signature: Array<felt252>,
)

Uses SNIP-12 signatures for off-chain authorization, enabling gasless transactions where authorized third parties can initiate swaps on behalf of users.

Redeem

The redeem function allows the redeemer to claim the locked tokens by providing the secret that hashes to the stored secret hash.

fn redeem(
    ref self: ContractState, 
    order_id: felt252, 
    secret: Array<u32>
) -> Result<()>

The secret must hash to the exact value stored during initiation using SHA-256. Once revealed, this secret enables the counterparty to claim funds on the other chain. No signature required - anyone can execute if they know the secret.

Refund

The refund function allows the initiator to reclaim their tokens after the timelock has expired and the redeemer has not claimed the funds.

fn refund(
    ref self: ContractState,
    order_id: felt252
)

Uses block number-based timing similar to Ethereum, providing predictable settlement windows based on Starknet’s consistent block production.

Instant Refund

The instant refund function provides a way for the redeemer to consent to canceling the swap before the timelock expires using SNIP-12 signatures.

fn instant_refund(
    ref self: ContractState,
    order_id: felt252,
    signature: Array<felt252>
)

Requires the redeemer’s SNIP-12 signature to prevent unauthorized instant refunds. This ensures mutual consent before the settlement window expires.

Starknet-Specific Features

Order State Management

The contract uses a Cairo struct to store swap state with efficient storage patterns:

#[derive(Drop, Serde, starknet::Store, Debug)]
pub struct Order {
    is_fulfilled: bool,
    initiator: ContractAddress,
    redeemer: ContractAddress,
    initiated_at: u128,
    timelock: u128,
    amount: u256,
}

Poseidon-Based Order IDs

Starknet uses the Poseidon hash function for generating unique order identifiers:

fn generate_order_id(
    self: @ContractState,
    chain_id: felt252,
    secret_hash: [u32; 8],
    initiator_address: felt252,
) -> felt252 {
    let mut state = PoseidonTrait::new();
    state = state.update(chain_id);
    state = state.update_with(secret_hash);
    state = state.update(initiator_address);
    state.finalize()
}

Poseidon hashing is optimized for zero-knowledge proofs and provides efficient computation on Starknet while ensuring order uniqueness.

SNIP-12 Signature Validation

The contract implements SNIP-12 (Starknet Improvement Proposal 12) for secure off-chain message signing:

let is_valid = ISRC6Dispatcher { contract_address: initiator }
    .is_valid_signature(message_hash, signature);
let is_valid_signature = is_valid == starknet::VALIDATED || is_valid == 1;
assert!(is_valid_signature, "HTLC: invalid initiator signature");

Event Logging

The contract emits events for each state transition to enable efficient off-chain monitoring:

#[event]
#[derive(Drop, starknet::Event)]
pub enum Event {
    Initiated: Initiated,
    Redeemed: Redeemed,
    Refunded: Refunded,
}

#[derive(Drop, starknet::Event)]
pub struct Initiated {
    order_id: felt252,
    secret_hash: [u32; 8],
    amount: u256,
}

ERC20 Token Integration

Unlike native currency swaps, Starknet HTLC works with ERC20 tokens:

#[storage]
struct Storage {
    pub token: IERC20Dispatcher,
    pub orders: Map::<felt252, Order>,
}

The contract uses OpenZeppelin’s ERC20 interface for secure token transfers with proper allowance and balance checks.

Cairo Language Features

The contract leverages Cairo’s safety features and storage optimizations:

  • Storage Maps: Efficient key-value storage for orders
  • Contract Address Types: Type-safe address handling
  • Felt252: Native field element type for hashes and identifiers
  • Array Types: Dynamic arrays for signatures and secrets

Gas Optimization

Starknet’s unique fee model enables several optimizations:

fn safe_params(
    self: @ContractState, 
    redeemer: ContractAddress, 
    timelock: u128, 
    amount: u256,
) {
    assert!(redeemer.is_non_zero(), "HTLC: zero address redeemer");
    assert!(timelock > 0, "HTLC: zero timelock");
    assert!(amount > 0, "HTLC: zero amount");
}

Parameter validation is grouped into a single function to optimize for Starknet’s execution model while maintaining security.