Skip to content
Merged
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
98 changes: 82 additions & 16 deletions contracts/pool/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,72 @@ impl PoolContract {
Self::usdc(&env)
}

/// Returns the admin address for the pool.
///
/// # Arguments
/// * `env` - The Soroban environment.
///
/// # Auth
/// No authorization is required.
///
/// # Panics
/// * Panics if the contract has not been initialized (missing `Admin`).
///
/// # Returns
/// * `Address` - The admin address.
///
/// # Example
/// ```ignore
/// let admin = client.get_admin();
/// ```
pub fn get_admin(env: Env) -> Address {
Self::admin(&env).expect("pool is not initialized: admin missing")
}

/// Returns the invoice contract address configured for the pool.
///
/// # Arguments
/// * `env` - The Soroban environment.
///
/// # Auth
/// No authorization is required.
///
/// # Panics
/// * Panics if the contract has not been initialized (missing `InvoiceContract`).
///
/// # Returns
/// * `Address` - The invoice contract address.
///
/// # Example
/// ```ignore
/// let invoice = client.get_invoice_contract();
/// ```
pub fn get_invoice_contract(env: Env) -> Address {
Self::invoice_contract(&env).expect("pool is not initialized: invoice contract missing")
}

/// Returns the escrow contract address configured for the pool.
///
/// # Arguments
/// * `env` - The Soroban environment.
///
/// # Auth
/// No authorization is required.
///
/// # Panics
/// * Panics if the contract has not been initialized (missing `EscrowContract`).
///
/// # Returns
/// * `Address` - The escrow contract address.
///
/// # Example
/// ```ignore
/// let escrow = client.get_escrow_contract();
/// ```
pub fn get_escrow_contract(env: Env) -> Address {
Self::escrow_contract(&env).expect("pool is not initialized: escrow contract missing")
}

/// Deposits USDC from an LP and issues pool shares.
///
/// # Arguments
Expand Down Expand Up @@ -449,7 +515,8 @@ impl PoolContract {
/// ```
pub fn fund_invoice(env: Env, invoice_id: BytesN<32>) -> bool {
Self::require_initialized(&env);
let invoice_contract = Self::invoice_contract(&env);
let invoice_contract = Self::invoice_contract(&env)
.expect("pool is not initialized: invoice contract missing");

let mut args = Vec::new(&env);
args.push_back(invoice_id.clone().into_val(&env));
Expand Down Expand Up @@ -561,7 +628,8 @@ impl PoolContract {
.extend_ttl(&funded_key, TTL_THRESHOLD, TTL_EXTEND_TO);

// --- Interactions: cross-contract calls after pool state is committed.
let escrow_contract = Self::escrow_contract(&env);
let escrow_contract =
Self::escrow_contract(&env).expect("pool is not initialized: escrow contract missing");

let mut args = Vec::new(&env);
args.push_back(invoice_id.clone().into_val(&env));
Expand Down Expand Up @@ -610,7 +678,8 @@ impl PoolContract {
/// client.receive_repayment(&invoice_id, 1_050);
/// ```
pub fn receive_repayment(env: Env, invoice_id: BytesN<32>, amount: u128) -> bool {
let invoice_contract = Self::invoice_contract(&env);
let invoice_contract = Self::invoice_contract(&env)
.expect("pool is not initialized: invoice contract missing");
invoice_contract.require_auth();

let funded_key = DataKey::FundedInvoice(invoice_id.clone());
Expand Down Expand Up @@ -704,7 +773,8 @@ impl PoolContract {
refund: u128,
buyer: Address,
) -> bool {
let invoice_contract = Self::invoice_contract(&env);
let invoice_contract = Self::invoice_contract(&env)
.expect("pool is not initialized: invoice contract missing");
invoice_contract.require_auth();

let funded_key = DataKey::FundedInvoice(invoice_id.clone());
Expand Down Expand Up @@ -802,7 +872,8 @@ impl PoolContract {
/// client.handle_default(&invoice_id);
/// ```
pub fn handle_default(env: Env, invoice_id: BytesN<32>) -> bool {
let invoice_contract = Self::invoice_contract(&env);
let invoice_contract = Self::invoice_contract(&env)
.expect("pool is not initialized: invoice contract missing");
invoice_contract.require_auth();

let funded_key = DataKey::FundedInvoice(invoice_id.clone());
Expand All @@ -811,7 +882,8 @@ impl PoolContract {
}
let funded_amount: u128 = env.storage().persistent().get(&funded_key).unwrap();

let escrow_contract = Self::escrow_contract(&env);
let escrow_contract =
Self::escrow_contract(&env).expect("pool is not initialized: escrow contract missing");
let pool_address = env.current_contract_address();
let mut args = Vec::new(&env);
args.push_back(invoice_id.clone().into_val(&env));
Expand Down Expand Up @@ -1062,18 +1134,12 @@ impl PoolContract {
env.storage().instance().get(&DataKey::Admin)
}

fn invoice_contract(env: &Env) -> Address {
env.storage()
.instance()
.get(&DataKey::InvoiceContract)
.expect("pool is not initialized: invoice contract missing")
fn invoice_contract(env: &Env) -> Option<Address> {
env.storage().instance().get(&DataKey::InvoiceContract)
}

fn escrow_contract(env: &Env) -> Address {
env.storage()
.instance()
.get(&DataKey::EscrowContract)
.expect("pool is not initialized: escrow contract missing")
fn escrow_contract(env: &Env) -> Option<Address> {
env.storage().instance().get(&DataKey::EscrowContract)
}

fn usdc(env: &Env) -> Address {
Expand Down
50 changes: 50 additions & 0 deletions contracts/pool/src/test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3072,3 +3072,53 @@ fn test_fund_invoice_prevents_double_funding_via_funded_key_check() {
let result = te.pool.try_fund_invoice(&invoice_id);
assert!(result.is_err());
}

// ============== PUBLIC GETTER TESTS (issue #578) ==============

#[test]
fn test_get_admin_returns_correct_address() {
let te = setup();
assert_eq!(te.pool.get_admin(), te.admin);
}

#[test]
fn test_get_invoice_contract_returns_correct_address() {
let te = setup();
assert_eq!(te.pool.get_invoice_contract(), te.invoice.address);
}

#[test]
fn test_get_escrow_contract_returns_correct_address() {
let te = setup();
assert_eq!(te.pool.get_escrow_contract(), te.escrow_id);
}

#[test]
#[should_panic(expected = "pool is not initialized: admin missing")]
fn test_get_admin_panics_when_uninitialized() {
let env = Env::default();
env.mock_all_auths();
let pool_id = env.register_contract(None, PoolContract);
let pool = PoolContractClient::new(&env, &pool_id);
let _ = pool.get_admin();
}

#[test]
#[should_panic(expected = "pool is not initialized: invoice contract missing")]
fn test_get_invoice_contract_panics_when_uninitialized() {
let env = Env::default();
env.mock_all_auths();
let pool_id = env.register_contract(None, PoolContract);
let pool = PoolContractClient::new(&env, &pool_id);
let _ = pool.get_invoice_contract();
}

#[test]
#[should_panic(expected = "pool is not initialized: escrow contract missing")]
fn test_get_escrow_contract_panics_when_uninitialized() {
let env = Env::default();
env.mock_all_auths();
let pool_id = env.register_contract(None, PoolContract);
let pool = PoolContractClient::new(&env, &pool_id);
let _ = pool.get_escrow_contract();
}