diff --git a/contracts/risk_registry/src/lib.rs b/contracts/risk_registry/src/lib.rs index a19af71..8cd81a5 100644 --- a/contracts/risk_registry/src/lib.rs +++ b/contracts/risk_registry/src/lib.rs @@ -2019,6 +2019,99 @@ mod tests { .is_ok()); } + // ── add_verifier re-registration guard ─────────────────────────────────── + + #[test] + fn test_add_verifier_rejects_already_active_verifier() { + // Re-registering an active verifier must fail — previously this silently + // overwrote VerifierStake (stranding funds) and reset VerifierReputation. + let (env, admin, _, staking_token, client) = setup(); + let verifier = Address::generate(&env); + mint_stake(&env, &staking_token, &verifier, 2_000_000i128); + client.add_verifier(&admin, &verifier, &1_000_000i128); + let result = client.try_add_verifier(&admin, &verifier, &500_000i128); + assert!(result.is_err()); + // Stake unchanged at original amount — no funds stranded + assert_eq!(client.get_verifier_stake(&verifier), 1_000_000i128); + assert!(client.is_verifier(&verifier)); + } + + #[test] + fn test_regression_fund_stranding_prevented() { + // Regression: second add_verifier with a lower amount must no longer + // silently overwrite VerifierStake, stranding the difference on-chain. + let (env, admin, _, staking_token, client) = setup(); + let verifier = Address::generate(&env); + mint_stake(&env, &staking_token, &verifier, 2_000_000i128); + client.add_verifier(&admin, &verifier, &1_000_000i128); + assert_eq!(client.get_verifier_stake(&verifier), 1_000_000i128); + // Attempt re-register with a lower stake — must be rejected + assert!(client.try_add_verifier(&admin, &verifier, &500_000i128).is_err()); + // Tracked stake is still 1_000_000, not silently reduced to 500_000 + assert_eq!(client.get_verifier_stake(&verifier), 1_000_000i128); + } + + #[test] + fn test_regression_reputation_reset_prevented() { + // Regression: second add_verifier must not reset VerifierReputation to 100, + // laundering slashing history recorded via record_default. + let (env, admin, _, staking_token, client) = setup(); + let verifier = Address::generate(&env); + let sme = Address::generate(&env); + mint_stake(&env, &staking_token, &verifier, 2_000_000i128); + client.add_verifier(&admin, &verifier, &1_000_000i128); + client.register_sme(&verifier, &sme, &40u32, &true); + client.record_default(&admin, &sme); + let rep_after_slash = client.get_verifier_reputation(&verifier); + assert!(rep_after_slash < 100, "reputation should have been reduced"); + // Attempt re-register — rejected, reputation preserved + let _ = client.try_add_verifier(&admin, &verifier, &1_000_000i128); + assert_eq!(client.get_verifier_reputation(&verifier), rep_after_slash); + } + + #[test] + fn test_top_up_stake_increases_stake_additively() { + // top_up_stake must ADD to existing tracked stake, not overwrite it. + let (env, admin, _, staking_token, client) = setup(); + let verifier = Address::generate(&env); + mint_stake(&env, &staking_token, &verifier, 3_000_000i128); + client.add_verifier(&admin, &verifier, &1_000_000i128); + assert_eq!(client.get_verifier_stake(&verifier), 1_000_000i128); + client.top_up_stake(&admin, &verifier, &500_000i128); + assert_eq!(client.get_verifier_stake(&verifier), 1_500_000i128); + } + + #[test] + fn test_top_up_stake_preserves_reputation() { + // top_up_stake must leave VerifierReputation untouched. + let (env, admin, _, staking_token, client) = setup(); + let verifier = Address::generate(&env); + let sme = Address::generate(&env); + mint_stake(&env, &staking_token, &verifier, 3_000_000i128); + client.add_verifier(&admin, &verifier, &1_000_000i128); + client.register_sme(&verifier, &sme, &40u32, &true); + client.record_default(&admin, &sme); + let rep = client.get_verifier_reputation(&verifier); + assert!(rep < 100); + client.top_up_stake(&admin, &verifier, &500_000i128); + assert_eq!(client.get_verifier_reputation(&verifier), rep); + } + + #[test] + fn test_top_up_stake_requires_active_verifier() { + let (env, admin, _, staking_token, client) = setup(); + let stranger = Address::generate(&env); + mint_stake(&env, &staking_token, &stranger, 1_000_000i128); + assert!(client.try_top_up_stake(&admin, &stranger, &500_000i128).is_err()); + } + + #[test] + fn test_top_up_stake_rejects_zero_amount() { + let (env, admin, _, staking_token, client) = setup(); + let verifier = Address::generate(&env); + mint_stake(&env, &staking_token, &verifier, 1_000_000i128); + client.add_verifier(&admin, &verifier, &1_000_000i128); + assert!(client.try_top_up_stake(&admin, &verifier, &0i128).is_err()); // ── set_credit_limit (require_non_negative_amount guard) ───────────────── #[test]