Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 37 additions & 6 deletions soroban-contracts/contracts/vault_factory/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,10 @@ impl VaultFactory {
// ─────────────────────────────────────────────────────────────────

/// Create a minimal single-RWA vault.
///
/// Uses a default of 7 share decimals (SEP-41 convention). For USDC-aligned
/// assets (6 decimal tokens), use `create_single_rwa_vault_full` and specify
/// `share_decimals: 6u32`.
pub fn create_single_rwa_vault(
e: &Env,
caller: Address,
Expand All @@ -119,24 +123,31 @@ impl VaultFactory {
asset,
name,
symbol,
7u32, // share_decimals: SEP-41 convention (7 decimals)
rwa_name,
rwa_symbol,
rwa_document_uri,
zero_str, // category
0u32, // expected_apy
maturity_date,
0u64, // funding_deadline (0 = no deadline)
0i128, // funding_target
0i128, // min_deposit
0i128, // max_deposit_per_user
200u32, // early_redemption_fee_bps (2 %)
0u64, // funding_deadline (0 = no deadline)
0i128, // funding_target
0i128, // min_deposit
0i128, // max_deposit_per_user
200u32, // early_redemption_fee_bps (2 %)
)
}

/// Create a fully parameterised single-RWA vault.
///
/// Parameters are passed as a `CreateVaultParams` struct to stay within
/// Soroban's 10-argument limit per contract function.
///
/// **Note:** `share_decimals` is required in `CreateVaultParams`. Common values:
/// - `6u32` for USDC/USDT-aligned assets
/// - `7u32` for SEP-41 convention (default recommendation)
/// - `8u32` for BTC-pegged tokens
/// - `18u32` for ETH/ERC-20 compatibility
Comment on lines +146 to +150
Copy link

Copilot AI Mar 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PR description states "no breaking changes", but adding a required share_decimals field to CreateVaultParams/BatchVaultParams changes the XDR shape of arguments for create_single_rwa_vault_full / create_single_rwa_vault_batch / batch_create_vaults. Existing off-chain callers will need to update their generated bindings / param construction. Please either (a) update the PR description/release notes to reflect the breaking API change, or (b) preserve backward compatibility by keeping the old entrypoints/types and adding new ones that include share_decimals (or making the field optional with an explicit default).

Copilot uses AI. Check for mistakes.
pub fn create_single_rwa_vault_full(
e: &Env,
caller: Address,
Expand All @@ -151,6 +162,7 @@ impl VaultFactory {
params.asset,
params.name,
params.symbol,
params.share_decimals,
params.rwa_name,
params.rwa_symbol,
params.rwa_document_uri,
Expand All @@ -169,6 +181,12 @@ impl VaultFactory {
///
/// Parameters are passed as a `CreateVaultParams` struct to stay within
/// Soroban's 10-argument limit per contract function.
///
/// **Note:** `share_decimals` is required in `CreateVaultParams`. Common values:
/// - `6u32` for USDC/USDT-aligned assets
/// - `7u32` for SEP-41 convention (default recommendation)
/// - `8u32` for BTC-pegged tokens
/// - `18u32` for ETH/ERC-20 compatibility
pub fn create_single_rwa_vault_batch(
e: &Env,
caller: Address,
Expand All @@ -183,6 +201,7 @@ impl VaultFactory {
params.asset,
params.name,
params.symbol,
params.share_decimals,
params.rwa_name,
params.rwa_symbol,
params.rwa_document_uri,
Expand All @@ -201,6 +220,9 @@ impl VaultFactory {
///
/// The batch size is capped at `MAX_BATCH_SIZE` (10) to prevent gas
/// exhaustion from unbounded contract deployments.
///
/// **Note:** Each vault in the batch uses its own `share_decimals` value
/// from the corresponding `BatchVaultParams`.
pub fn batch_create_vaults(
e: &Env,
caller: Address,
Expand All @@ -222,6 +244,7 @@ impl VaultFactory {
p.asset,
p.name,
p.symbol,
p.share_decimals,
p.rwa_name,
p.rwa_symbol,
p.rwa_document_uri,
Expand Down Expand Up @@ -511,6 +534,7 @@ impl VaultFactory {
asset: Address,
name: String,
symbol: String,
share_decimals: u32,
rwa_name: String,
rwa_symbol: String,
rwa_document_uri: String,
Expand Down Expand Up @@ -571,11 +595,18 @@ impl VaultFactory {

// Build the InitParams struct for the vault constructor.
// Using a struct keeps us under Soroban's 10-arg limit per function.
//
// Note: share_decimals is passed from the caller. The relationship between
// share_decimals and asset_decimals affects the share/asset ratio calculation:
// - For USDC-aligned assets (6 decimals): use share_decimals = 6
// - For SEP-41 convention (7 decimals): use share_decimals = 7
// - For BTC-pegged tokens (8 decimals): use share_decimals = 8
// - For ETH/ERC-20 compatibility (18 decimals): use share_decimals = 18
let init_params = SingleRwaVaultInitParams {
asset: vault_asset.clone(),
share_name: name.clone(),
share_symbol: symbol.clone(),
share_decimals: 6u32, // USDC convention
share_decimals,
admin: admin.clone(),
zkme_verifier: zkme.clone(),
cooperator: coop.clone(),
Expand Down
2 changes: 2 additions & 0 deletions soroban-contracts/contracts/vault_factory/src/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,7 @@ fn test_create_single_rwa_vault_full() {
asset: asset.clone(),
name: String::from_str(&e, "Full Vault"),
symbol: String::from_str(&e, "FV"),
share_decimals: 7u32, // SEP-41 convention
rwa_name: String::from_str(&e, "Private Credit"),
rwa_symbol: String::from_str(&e, "PC"),
rwa_document_uri: String::from_str(&e, "https://doc.com"),
Expand Down Expand Up @@ -93,6 +94,7 @@ fn test_batch_create_vaults() {
asset: asset.clone(),
name: String::from_str(&e, "Vault"),
symbol: String::from_str(&e, "V"),
share_decimals: 7u32, // SEP-41 convention
rwa_name: String::from_str(&e, "RWA"),
rwa_symbol: String::from_str(&e, "R"),
rwa_document_uri: String::from_str(&e, "uri"),
Expand Down
2 changes: 2 additions & 0 deletions soroban-contracts/contracts/vault_factory/src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -436,6 +436,7 @@ fn test_batch_create_vaults_exceeds_limit() {
asset: asset.clone(),
name: String::from_str(&e, "V"),
symbol: String::from_str(&e, "V"),
share_decimals: 7u32, // SEP-41 convention
rwa_name: String::from_str(&e, "RWA"),
rwa_symbol: String::from_str(&e, "R"),
rwa_document_uri: String::from_str(&e, "https://example.com"),
Expand Down Expand Up @@ -470,6 +471,7 @@ fn test_batch_create_vaults_at_limit_ok() {
asset: asset.clone(),
name: String::from_str(&e, "V"),
symbol: String::from_str(&e, "V"),
share_decimals: 7u32, // SEP-41 convention
rwa_name: String::from_str(&e, "RWA"),
rwa_symbol: String::from_str(&e, "R"),
rwa_document_uri: String::from_str(&e, "https://example.com"),
Expand Down
14 changes: 14 additions & 0 deletions soroban-contracts/contracts/vault_factory/src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,26 @@ pub struct SingleRwaVaultInitParams {
}

/// Parameters for batch vault creation (mirrors BatchVaultParams in Solidity).
///
/// # Share Decimals
/// `share_decimals` determines the decimal precision of the vault's share token.
/// This is independent of the underlying asset's decimals. Common conventions:
/// - 6: USDC convention (matching USDC/USDT)
/// - 7: SEP-41 convention (Stellar ecosystem standard for asset-anchored tokens)
/// - 8: BTC-pegged tokens convention
/// - 18: ETH/ERC-20 convention (for compatibility with ETH-based systems)
///
/// The share/asset ratio is calculated based on these decimals, so using the
/// wrong value will result in incorrect share pricing.
#[contracttype]
#[derive(Clone, Debug)]
pub struct BatchVaultParams {
pub asset: Address,
pub name: String,
pub symbol: String,
/// Number of decimal places for the vault's share token.
/// Default: 7u32 (SEP-41 convention). Set to 6u32 for USDC-aligned assets.
Copy link

Copilot AI Mar 26, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The docstring says share_decimals has a "Default: 7u32" but BatchVaultParams/CreateVaultParams require the caller to always provide this field (there is no on-chain default applied when deserializing the struct). Please reword this to avoid implying an automatic default (e.g., "recommended" or "factory simple create uses 7u32").

Suggested change
/// Default: 7u32 (SEP-41 convention). Set to 6u32 for USDC-aligned assets.
/// Recommended: 7u32 (SEP-41 convention, used by the factory's simple
/// creation flows). Set to 6u32 for USDC-aligned assets, or another value
/// as appropriate for the asset.

Copilot uses AI. Check for mistakes.
pub share_decimals: u32,
pub rwa_name: String,
pub rwa_symbol: String,
pub rwa_document_uri: String,
Expand Down
Loading