RustFund

First Flight #36
Beginner FriendlyRust
100 EXP
View results
Submission Details
Severity: low
Invalid

Lack of Refund Event Emission (Omission + Transparency Issue)

[L-1] Lack of Refund Event Emission (Omission + Transparency Issue)

Description:

The original refund function does not emit an event to log refund transactions. This omission means there’s no on-chain notification of refund activity, forcing external systems (e.g., indexers, user interfaces) to rely solely on scanning account state changes to detect refunds.

Impact:

The absence of an event reduces transparency and complicates off-chain monitoring, debugging, and auditing. Users and external tools cannot easily track refund activity without additional effort, potentially undermining trust in the program and increasing operational overhead. While it doesn’t directly affect on-chain functionality or lead to fund loss, it’s a significant usability and design flaw for a crowdfunding program like rustfund.

Proof of Concept:

pub fn refund(ctx: Context<FundRefund>) -> Result<()> {
let amount = ctx.accounts.contribution.amount;
if ctx.accounts.fund.deadline != 0 && ctx.accounts.fund.deadline > Clock::get().unwrap().unix_timestamp.try_into().unwrap() {
return Err(ErrorCode::DeadlineNotReached.into());
}
**ctx.accounts.fund.to_account_info().try_borrow_mut_lamports()? =
ctx.accounts.fund.to_account_info().lamports()
.checked_sub(amount)
.ok_or(ProgramError::InsufficientFunds)?;
**ctx.accounts.contributor.to_account_info().try_borrow_mut_lamports()? =
ctx.accounts.contributor.to_account_info().lamports()
.checked_add(amount)
.ok_or(ErrorCode::CalculationOverflow)?;
ctx.accounts.contribution.amount = 0;
// Missing: No event emitted here to log the refund (e.g., RefundEvent with fund, contributor, amount)
Ok(())
}

Recommended Mitigation:
Add an event emission to log refund details:

pub fn refund(ctx: Context<FundRefund>) -> Result<()> {
let fund = &mut ctx.accounts.fund;
let contribution = &mut ctx.accounts.contribution;
let contributor = &mut ctx.accounts.contributor;
if fund.deadline != 0 && (fund.deadline as i64) > Clock::get()?.unix_timestamp {
return Err(ErrorCode::DeadlineNotReached.into());
}
let amount = contribution.amount;
contribution.amount = 0;
**fund.to_account_info().try_borrow_mut_lamports()? =
fund.to_account_info().lamports()
.checked_sub(amount)
.ok_or(ProgramError::InsufficientFunds)?;
**contributor.to_account_info().try_borrow_mut_lamports()? =
contributor.to_account_info().lamports()
.checked_add(amount)
.ok_or(ErrorCode::CalculationOverflow)?;
+ // Emit event for transparency
+ emit!(RefundEvent {
+ fund: fund.key(),
+ contributor: contributor.key(),
+ amount,
+ });
Ok(())
}
+#[event]
+pub struct RefundEvent {
+ pub fund: Pubkey,
+ pub contributor: Pubkey,
+ pub amount: u64,
+}
Updates

Appeal created

bube Lead Judge 2 months ago
Submission Judgement Published
Invalidated
Reason: Non-acceptable severity

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.