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
12 changes: 12 additions & 0 deletions contracts/claims-processor/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2133,6 +2133,18 @@ impl ClaimsProcessor {
Self::claim_payout(env, claim_id)
}

/// Claim payout with explicit recipient verification (issue #718).
/// Rejects any attempt to redirect payout away from the claimant.
pub fn claim_payout_to(env: Env, claim_id: u128, recipient: Address) -> i128 {
let claim: Claim = env.storage().persistent()
.get(&StorageKey::Claim(claim_id))
.unwrap_or_else(|| panic_with_error!(&env, Error::ClaimNotFound));
if recipient != claim.claimant {
panic_with_error!(&env, Error::Unauthorized);
}
Self::claim_payout(env, claim_id)
}

/// Claim the payout for an approved claim after the payout delay has elapsed.
///
/// When a payout delay is configured, approved claims enter Paid/PartiallyPaid
Expand Down
8 changes: 8 additions & 0 deletions contracts/governance-dao/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1401,6 +1401,9 @@ impl GovernanceDao {
if proposal.status == ProposalStatus::Cancelled {
panic_with_error!(&env, Error::AlreadyCancelled);
}
if proposal.status == ProposalStatus::Expired {
panic_with_error!(&env, Error::ExecutionDeadlineExpired);
}
if proposal.status != ProposalStatus::Passed {
panic_with_error!(&env, Error::ProposalNotPassed);
}
Expand Down Expand Up @@ -1460,6 +1463,11 @@ impl GovernanceDao {
);
}

/// Execute proposal alias (issue #720), checking deadline and expiration.
pub fn execute_proposal(env: Env, proposal_id: u64) {
Self::execute(env, proposal_id);
}

/// Return the execution audit trail record for an executed proposal.
pub fn get_execution_audit(env: Env, proposal_id: u64) -> ExecutionAuditRecord {
env.storage()
Expand Down
5 changes: 5 additions & 0 deletions contracts/policy-engine/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -991,6 +991,11 @@ impl PolicyEngine {
.and_then(|v| v.checked_div(365))
.and_then(|v| v.checked_div(10_000))
.unwrap_or_else(|| panic_with_error!(env, Error::CoverageOutOfRange));

// SECURITY FIX (issue #719): Reject zero or negative premium amounts to prevent free coverage
if required_premium <= 0 {
panic_with_error!(env, Error::ZeroPremiumRate);
}

// SECURITY FIX: reject payment if token does not match the product's expected token
if payment_token != &product.expected_token {
Expand Down
8 changes: 8 additions & 0 deletions contracts/risk-pool/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -797,6 +797,14 @@ impl RiskPool {
/// Transfer `shares` from `from` address to `to` address.
/// Returns the proportional USDC deposit amount transferred.
///
/// Transfer LP shares between providers, validating amount is strictly positive (issue #717).
pub fn transfer_shares(env: Env, from: Address, to: Address, shares: i128) -> i128 {
if shares <= 0 {
panic_with_error!(&env, Error::ZeroAmount);
}
Self::transfer_position(env, from, to, shares)
}

/// The admin cannot be the receiving side either (issue #568) —
/// otherwise `transfer_position` is a one-transaction way around the
/// `deposit` restriction and the separation of duties it exists for.
Expand Down
Loading