sla-escrow-api 0.2.8

SLA-Escrow: Service Level Agreement Enforcer for AI Agents
Documentation
//! Shared on-chain and SDK defaults for sla-escrow (grouped by concern).

use const_crypto::ed25519;
use solana_program::{pubkey, pubkey::Pubkey};

// =============================================================================
// Authority
// =============================================================================

/// Account allowed to invoke [`Initialize`](crate::instruction::EscrowInstruction::Initialize).
pub const INITIALIZER_ADDRESS: Pubkey = pubkey!("4ALL9EAVHpv7ioJF95ktDLtrHUEJezPuFxTFFMy3fpSy");

// =============================================================================
// Fees, oracle tip cap, and `open_escrow` amount defaults (USDC-style 6 decimals)
// =============================================================================

/// Basis points denominator (1 bp = 0.01%).
pub const BASIS_POINTS_DENOMINATOR: u128 = 10_000;

/// Default bank protocol fee at `Initialize` when not overridden.
pub const DEFAULT_FEE_BPS: u16 = 100; // 1%

/// Program-enforced cap on protocol `fee_bps` (used by `Initialize`,
/// `OpenEscrow`, `UpdateEscrowSettings`). 10% ceiling.
pub const MAX_FEE_BASIS_POINTS: u16 = 1_000;

/// Cap on per-escrow oracle tip (`oracle_fee_bps`).
pub const MAX_ORACLE_FEE_BPS: u16 = 500;

/// Default minimum protocol fee at release (raw units); `max(bps_fee, min_fee_amount)`.
pub const DEFAULT_MIN_FEE_RAW_USDC_DECIMALS_6: u64 = 100_000;

/// Default minimum payment (raw) for `open_escrow` USDC-style defaults; must exceed min fee above.
pub const DEFAULT_MIN_PAYMENT_RAW_USDC_DECIMALS_6: u64 = 1_000_000;

// =============================================================================
// Global `Config`: defaults at `Initialize`
// =============================================================================

/// Default `Config::closure_delay_seconds` (post-settlement retention before `close-payment`).
pub const CLOSURE_DELAY_RELEASE_REFUND: i64 = 7 * 24 * 60 * 60; // 7 days

/// Default `Config::refund_cooldown_seconds` (spacing for buyer-initiated refunds).
/// Shorter than legacy 48h — tuned for agentic / high-throughput flows; raise via `update-config` if needed.
pub const DEFAULT_REFUND_COOLDOWN_SECONDS: i64 = 24 * 60 * 60; // 24 hours

/// Default `Config::delivery_cutoff_seconds` (oracle evaluation window before expiry).
pub const DEFAULT_DELIVERY_CUTOFF_SECONDS: i64 = 300; // 5 minutes

// =============================================================================
// Global `Config`: bounds for `UpdateConfig` (validator in `update_config.rs`)
// =============================================================================

/// Minimum allowed `closure_delay_seconds` (agent-friendly floor).
pub const MIN_CLOSURE_DELAY_SECONDS: i64 = 5 * 60; // 5 minutes

/// Maximum allowed `closure_delay_seconds`.
pub const MAX_CLOSURE_DELAY_SECONDS: i64 = 30 * 24 * 60 * 60; // 30 days

/// When refund cooldown is enabled (`> 0`), minimum allowed value.
pub const MIN_REFUND_COOLDOWN_WHEN_ENABLED_SECONDS: i64 = 60 * 60; // 1 hour

/// Maximum allowed refund cooldown.
pub const MAX_REFUND_COOLDOWN_SECONDS: i64 = 7 * 24 * 60 * 60; // 7 days

/// Maximum allowed `delivery_cutoff_seconds`.
pub const MAX_DELIVERY_CUTOFF_SECONDS: i64 = 24 * 60 * 60; // 1 day

// =============================================================================
// Payment TTL (`FundPayment`, `ExtendPaymentTTL`)
// =============================================================================

/// Program-enforced minimum TTL for a funded payment.
pub const MIN_TTL_SECONDS: i64 = 60; // 1 minute

/// Default TTL when using `fund-payment` without `--ttl-seconds` (CLI and integrators).
pub const DEFAULT_TTL_SECONDS: i64 = 24 * 60 * 60; // 86400 s = 24 hours

/// Program-enforced maximum TTL from funding time.
pub const MAX_TTL_SECONDS: i64 = 30 * 24 * 60 * 60; // 30 days

// =============================================================================
// Payment state bytes
// =============================================================================

pub const PAYMENT_STATE_FUNDED: u8 = 0; // Account created and funded atomically
pub const PAYMENT_STATE_RELEASED: u8 = 1; // Released to seller (normal flow)
pub const PAYMENT_STATE_REFUNDED: u8 = 2; // Refunded to buyer (normal flow)

// =============================================================================
// PDA seeds
// =============================================================================

/// Seed for the bank PDA.
pub const BANK: &[u8] = b"bank";

/// Seed for the config PDA.
pub const CONFIG: &[u8] = b"config";

/// Seed for per-mint escrow PDAs.
pub const ESCROW: &[u8] = b"escrow";

/// Seed for native SOL liquidity storage (SOL escrows).
pub const SOL_STORAGE: &[u8] = b"sol_storage";

/// Seed for payment PDAs.
pub const PAYMENT: &[u8] = b"payment";

/// Seed for the authority transfer proposal PDA.
pub const AUTHORITY_TRANSFER: &[u8] = b"authority_transfer";

// =============================================================================
// Authority transfer timelock (compile-time immutable — cannot be shortened by
// a compromised bank authority; only changeable via program upgrade)
// =============================================================================

// Mandatory delay before a proposed authority transfer can be accepted (in seconds).
// Production value: 2 days (48 hours = 2 * 24 * 60 * 60)
// pub const AUTHORITY_TRANSFER_DELAY_SECONDS: i64 = 172_800;

/// Mandatory delay between an `UpdateAuthority` proposal and `AcceptAuthority`
/// (seconds). Compile-time constant — cannot be shortened by a compromised
/// bank authority; only changeable via program upgrade. Devnet: 180 s.
pub const AUTHORITY_TRANSFER_DELAY_SECONDS: i64 = 180;

// =============================================================================
// Well-known token mints (mainnet-style symbols; devnet may use other mints)
// =============================================================================

pub const MARS_MINT_ADDRESS: Pubkey = pubkey!("7RAV5UPRTzxn46kLeA8MiJsdNy9VKc5fip8FWEgTpTHh");
pub const USDC_MINT_ADDRESS: Pubkey = pubkey!("EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v");
pub const USDT_MINT_ADDRESS: Pubkey = pubkey!("Es9vMFrzaCERmJfrF4H2FYD4KCoNkY11McCe8BenwNYB");
pub const WSOL_MINT_ADDRESS: Pubkey = pubkey!("So11111111111111111111111111111111111111112");
pub const MIRACLE_MINT_ADDRESS: Pubkey = pubkey!("Mirab4SFVff6sCuK48PPnSUj7PNpDDrBWY6FkJmuifG");
pub const TESTCOIN_MINT_ADDRESS: Pubkey = pubkey!("2gNCDGj8Xi9Zs7LNQTPWf4pfZvAM7UHusY4xhKNYg6W6");

/// SPL Token-2022 program id.
pub const TOKEN_2022_PROGRAM_ID: Pubkey = pubkey!("TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb");

// =============================================================================
// Derived addresses for this program id (compile-time; off-chain convenience)
// =============================================================================

const PROGRAM_ID: [u8; 32] = unsafe { *(&crate::id() as *const Pubkey as *const [u8; 32]) };

/// Bank PDA for [`crate::ID`].
pub const BANK_ADDRESS: Pubkey =
    Pubkey::new_from_array(ed25519::derive_program_address(&[BANK], &PROGRAM_ID).0);

/// Config PDA for [`crate::ID`].
pub const CONFIG_ADDRESS: Pubkey =
    Pubkey::new_from_array(ed25519::derive_program_address(&[CONFIG], &PROGRAM_ID).0);

/// Precomputed escrow-related PDAs for this program id (integrator convenience).
///
/// These are **compile-time constants** in the API crate only—they are **not** stored in the
/// on-chain program account data and do **not** increase Solana program deployment size or rent.
pub const MARS_ESCROW_ADDRESS: Pubkey = Pubkey::new_from_array(
    ed25519::derive_program_address(
        &[
            ESCROW,
            unsafe { &*(&MARS_MINT_ADDRESS as *const Pubkey as *const [u8; 32]) },
            unsafe { &*(&BANK_ADDRESS as *const Pubkey as *const [u8; 32]) },
        ],
        &PROGRAM_ID,
    )
    .0,
);
pub const MARS_ESCROW_BUMP: u8 = ed25519::derive_program_address(
    &[
        ESCROW,
        unsafe { &*(&MARS_MINT_ADDRESS as *const Pubkey as *const [u8; 32]) },
        unsafe { &*(&BANK_ADDRESS as *const Pubkey as *const [u8; 32]) },
    ],
    &PROGRAM_ID,
)
.1;
pub const MARS_ESCROW_TOKENS_ADDRESS: Pubkey = Pubkey::new_from_array(
    ed25519::derive_program_address(
        &[
            unsafe { &*(&MARS_ESCROW_ADDRESS as *const Pubkey as *const [u8; 32]) },
            unsafe { &*(&spl_token::id() as *const Pubkey as *const [u8; 32]) },
            unsafe { &*(&MARS_MINT_ADDRESS as *const Pubkey as *const [u8; 32]) },
        ],
        unsafe { &*(&spl_associated_token_account::id() as *const Pubkey as *const [u8; 32]) },
    )
    .0,
);

pub const MIRACLE_ESCROW_ADDRESS: Pubkey = Pubkey::new_from_array(
    ed25519::derive_program_address(
        &[
            ESCROW,
            unsafe { &*(&MIRACLE_MINT_ADDRESS as *const Pubkey as *const [u8; 32]) },
            unsafe { &*(&BANK_ADDRESS as *const Pubkey as *const [u8; 32]) },
        ],
        &PROGRAM_ID,
    )
    .0,
);
pub const MIRACLE_ESCROW_BUMP: u8 = ed25519::derive_program_address(
    &[
        ESCROW,
        unsafe { &*(&MIRACLE_MINT_ADDRESS as *const Pubkey as *const [u8; 32]) },
        unsafe { &*(&BANK_ADDRESS as *const Pubkey as *const [u8; 32]) },
    ],
    &PROGRAM_ID,
)
.1;
pub const MIRACLE_ESCROW_TOKENS_ADDRESS: Pubkey = Pubkey::new_from_array(
    ed25519::derive_program_address(
        &[
            unsafe { &*(&MIRACLE_ESCROW_ADDRESS as *const Pubkey as *const [u8; 32]) },
            unsafe { &*(&spl_token::id() as *const Pubkey as *const [u8; 32]) },
            unsafe { &*(&MIRACLE_MINT_ADDRESS as *const Pubkey as *const [u8; 32]) },
        ],
        unsafe { &*(&spl_associated_token_account::id() as *const Pubkey as *const [u8; 32]) },
    )
    .0,
);

pub const USDC_ESCROW_ADDRESS: Pubkey = Pubkey::new_from_array(
    ed25519::derive_program_address(
        &[
            ESCROW,
            unsafe { &*(&USDC_MINT_ADDRESS as *const Pubkey as *const [u8; 32]) },
            unsafe { &*(&BANK_ADDRESS as *const Pubkey as *const [u8; 32]) },
        ],
        &PROGRAM_ID,
    )
    .0,
);
pub const USDC_ESCROW_BUMP: u8 = ed25519::derive_program_address(
    &[
        ESCROW,
        unsafe { &*(&USDC_MINT_ADDRESS as *const Pubkey as *const [u8; 32]) },
        unsafe { &*(&BANK_ADDRESS as *const Pubkey as *const [u8; 32]) },
    ],
    &PROGRAM_ID,
)
.1;
pub const USDC_ESCROW_TOKENS_ADDRESS: Pubkey = Pubkey::new_from_array(
    ed25519::derive_program_address(
        &[
            unsafe { &*(&USDC_ESCROW_ADDRESS as *const Pubkey as *const [u8; 32]) },
            unsafe { &*(&spl_token::id() as *const Pubkey as *const [u8; 32]) },
            unsafe { &*(&USDC_MINT_ADDRESS as *const Pubkey as *const [u8; 32]) },
        ],
        unsafe { &*(&spl_associated_token_account::id() as *const Pubkey as *const [u8; 32]) },
    )
    .0,
);

pub const USDT_ESCROW_ADDRESS: Pubkey = Pubkey::new_from_array(
    ed25519::derive_program_address(
        &[
            ESCROW,
            unsafe { &*(&USDT_MINT_ADDRESS as *const Pubkey as *const [u8; 32]) },
            unsafe { &*(&BANK_ADDRESS as *const Pubkey as *const [u8; 32]) },
        ],
        &PROGRAM_ID,
    )
    .0,
);
pub const USDT_ESCROW_BUMP: u8 = ed25519::derive_program_address(
    &[
        ESCROW,
        unsafe { &*(&USDT_MINT_ADDRESS as *const Pubkey as *const [u8; 32]) },
        unsafe { &*(&BANK_ADDRESS as *const Pubkey as *const [u8; 32]) },
    ],
    &PROGRAM_ID,
)
.1;
pub const USDT_ESCROW_TOKENS_ADDRESS: Pubkey = Pubkey::new_from_array(
    ed25519::derive_program_address(
        &[
            unsafe { &*(&USDT_ESCROW_ADDRESS as *const Pubkey as *const [u8; 32]) },
            unsafe { &*(&spl_token::id() as *const Pubkey as *const [u8; 32]) },
            unsafe { &*(&USDT_MINT_ADDRESS as *const Pubkey as *const [u8; 32]) },
        ],
        unsafe { &*(&spl_associated_token_account::id() as *const Pubkey as *const [u8; 32]) },
    )
    .0,
);

pub const WSOL_ESCROW_ADDRESS: Pubkey = Pubkey::new_from_array(
    ed25519::derive_program_address(
        &[
            ESCROW,
            unsafe { &*(&WSOL_MINT_ADDRESS as *const Pubkey as *const [u8; 32]) },
            unsafe { &*(&BANK_ADDRESS as *const Pubkey as *const [u8; 32]) },
        ],
        &PROGRAM_ID,
    )
    .0,
);
pub const WSOL_ESCROW_BUMP: u8 = ed25519::derive_program_address(
    &[
        ESCROW,
        unsafe { &*(&WSOL_MINT_ADDRESS as *const Pubkey as *const [u8; 32]) },
        unsafe { &*(&BANK_ADDRESS as *const Pubkey as *const [u8; 32]) },
    ],
    &PROGRAM_ID,
)
.1;
pub const WSOL_ESCROW_TOKENS_ADDRESS: Pubkey = Pubkey::new_from_array(
    ed25519::derive_program_address(
        &[
            unsafe { &*(&WSOL_ESCROW_ADDRESS as *const Pubkey as *const [u8; 32]) },
            unsafe { &*(&spl_token::id() as *const Pubkey as *const [u8; 32]) },
            unsafe { &*(&WSOL_MINT_ADDRESS as *const Pubkey as *const [u8; 32]) },
        ],
        unsafe { &*(&spl_associated_token_account::id() as *const Pubkey as *const [u8; 32]) },
    )
    .0,
);
pub const TESTCOIN_ESCROW_ADDRESS: Pubkey = Pubkey::new_from_array(
    ed25519::derive_program_address(
        &[
            ESCROW,
            unsafe { &*(&TESTCOIN_MINT_ADDRESS as *const Pubkey as *const [u8; 32]) },
            unsafe { &*(&BANK_ADDRESS as *const Pubkey as *const [u8; 32]) },
        ],
        &PROGRAM_ID,
    )
    .0,
);
pub const TESTCOIN_ESCROW_BUMP: u8 = ed25519::derive_program_address(
    &[
        ESCROW,
        unsafe { &*(&TESTCOIN_MINT_ADDRESS as *const Pubkey as *const [u8; 32]) },
        unsafe { &*(&BANK_ADDRESS as *const Pubkey as *const [u8; 32]) },
    ],
    &PROGRAM_ID,
)
.1;
pub const TESTCOIN_ESCROW_TOKENS_ADDRESS: Pubkey = Pubkey::new_from_array(
    ed25519::derive_program_address(
        &[
            unsafe { &*(&TESTCOIN_ESCROW_ADDRESS as *const Pubkey as *const [u8; 32]) },
            unsafe { &*(&spl_token::id() as *const Pubkey as *const [u8; 32]) },
            unsafe { &*(&TESTCOIN_MINT_ADDRESS as *const Pubkey as *const [u8; 32]) },
        ],
        unsafe { &*(&spl_associated_token_account::id() as *const Pubkey as *const [u8; 32]) },
    )
    .0,
);