Skip to content
Merged
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
96 changes: 54 additions & 42 deletions contracts/forge-vesting/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -555,8 +555,6 @@ impl ForgeVesting {
})
}

pub fn get_config(env: Env) -> Result<VestingConfig, VestingError> {
env.storage()
/// Return the full vesting configuration set at initialization.
///
/// Exposes all fields of [`VestingConfig`] including token, beneficiary, admin,
Expand Down Expand Up @@ -758,7 +756,6 @@ impl ForgeVesting {
// ── Tests ─────────────────────────────────────────────────────────────────────

#[cfg(test)]
mod test {
mod tests {
extern crate std;

Expand Down Expand Up @@ -965,40 +962,21 @@ mod tests {

#[test]
fn test_double_cancel_fails() {
let (env, contract_id, token, beneficiary, admin) = setup_with_token();
let (env, contract_id, token_id, beneficiary, admin) = setup_with_token();
let client = ForgeVestingClient::new(&env, &contract_id);
client.initialize(&token_id, &beneficiary, &admin, &1_000_000, &100, &1000);
client.cancel();
let result = client.try_cancel();
assert_eq!(result, Err(Ok(VestingError::Cancelled)));
}

#[test]
fn test_get_vesting_schedule_fails_when_not_initialized() {
let (env, contract_id, _, _, _) = setup();
let client = ForgeVestingClient::new(&env, &contract_id);
let result = client.try_get_vesting_schedule();
assert_eq!(result, Err(Ok(VestingError::NotInitialized)));
}

#[test]
fn test_claim_after_cancel_fails() {
let (env, contract_id, token, beneficiary, admin) = setup_with_token();
fn test_schedule_and_status_provide_full_ui_info_without_get_config() {
// get_vesting_schedule() + get_status() together expose everything a UI
// needs: token, beneficiary, amounts, timing, claimable — without
// leaking the admin address or internal cancellation flag.
let (env, contract_id, token, beneficiary, admin) = setup();
let client = ForgeVestingClient::new(&env, &contract_id);
client.initialize(&token, &beneficiary, &admin, &1_000_000, &100, &1000);

// Advance past cliff
env.ledger().with_mut(|l| l.timestamp += 500);

let schedule = client.get_vesting_schedule();
assert_eq!(schedule.token, token);
assert_eq!(schedule.beneficiary, beneficiary);
assert_eq!(schedule.total_amount, 1_000_000);
assert_eq!(schedule.cliff_seconds, 100);
assert_eq!(schedule.duration_seconds, 1000);

let status = client.get_status();
assert!(status.cliff_reached);
assert!(status.claimable > 0);
assert_eq!(status.claimed, 0);
assert!(!status.fully_vested);
}

#[test]
Expand Down Expand Up @@ -1164,17 +1142,6 @@ mod tests {
assert_eq!(result, Err(Ok(VestingError::Cancelled)));
}

#[test]
fn test_claim_after_cancel_fails() {
let (env, contract_id, token_id, beneficiary, admin) = setup_with_token();
let client = ForgeVestingClient::new(&env, &contract_id);
client.initialize(&token_id, &beneficiary, &admin, &1_000_000, &100, &1000);
client.cancel();
env.ledger().with_mut(|l| l.timestamp += 200);
let result = client.try_claim();
assert_eq!(result, Err(Ok(VestingError::Cancelled)));
}

#[test]
fn test_fully_vested_after_duration() {
let (env, contract_id, token, beneficiary, admin) = setup();
Expand Down Expand Up @@ -2495,4 +2462,49 @@ mod tests {

assert_eq!(first + second, TOTAL);
}

/// unpause() must return VestingError::NotPaused when the schedule is not paused.
///
/// Verifies the correct error variant is returned so callers can distinguish
/// "not paused" from "not initialized" (CommonError::NotInitialized).
#[test]
fn test_unpause_when_not_paused_returns_not_paused() {
let (env, contract_id, token, beneficiary, admin) = setup();
let client = ForgeVestingClient::new(&env, &contract_id);
client.initialize(&token, &beneficiary, &admin, &1_000_000, &100, &1000);

// Schedule is active (not paused) — unpause must fail with NotPaused
let result = client.try_unpause();
assert_eq!(result, Err(Ok(VestingError::NotPaused)));
}

/// cancel_and_claim() must return VestingError::Paused when the schedule is paused.
///
/// Verifies the correct error variant is returned — Paused is a state condition,
/// not an authorization failure (CommonError::Unauthorized).
#[test]
fn test_cancel_and_claim_while_paused_returns_paused() {
let (env, contract_id, token, beneficiary, admin) = setup();
let client = ForgeVestingClient::new(&env, &contract_id);
client.initialize(&token, &beneficiary, &admin, &1_000_000, &100, &1000);
client.pause();

let result = client.try_cancel_and_claim();
assert_eq!(result, Err(Ok(VestingError::Paused)));
}

/// pause() must return VestingError::Paused when the schedule is already paused.
///
/// Verifies the correct error variant is returned for the already-paused case.
#[test]
fn test_pause_when_already_paused_returns_paused() {
let (env, contract_id, token, beneficiary, admin) = setup();
let client = ForgeVestingClient::new(&env, &contract_id);
client.initialize(&token, &beneficiary, &admin, &1_000_000, &100, &1000);
client.pause();

// Second pause must fail with Paused, not Unauthorized
let result = client.try_pause();
assert_eq!(result, Err(Ok(VestingError::Paused)));
}
}
Loading