Problem
approve_creator (contracts/campaign-escrow/src/lib.rs:345-394) checks the campaign's status, the payout amount, max_creators, and escrow headroom — but never checks any deadline:
pub fn approve_creator(
env: Env,
business: Address,
campaign_id: CampaignId,
creator: Address,
payout_amount: i128,
) -> Result<(), Error> {
require_not_paused(&env)?;
business.require_auth();
let mut campaign = storage::get_campaign(&env, campaign_id)?;
if campaign.business != business {
return Err(Error::NotCampaignOwner);
}
if campaign.status != CampaignStatus::Funded && campaign.status != CampaignStatus::Active {
return Err(Error::InvalidStatus);
}
if payout_amount <= 0 {
return Err(Error::InvalidAmount);
}
// ... no deadline check anywhere in this function
Meanwhile submit_proof unconditionally rejects with Error::ContentDeadlinePassed once env.ledger().timestamp() > campaign.completion_deadline (lib.rs:407-409).
Concrete failure scenario
A creator applies before application_deadline. The business is slow to review and only calls approve_creator after completion_deadline has already passed — the call succeeds and commits payout_amount against the escrow balance. That creator can now never call submit_proof (the deadline is already gone), so the application is permanently stuck at Approved with no way to progress — a self-inflicted, zero-malice instance of the "committed payout can become permanently unrecoverable" problem (see the linked issue on that).
There's no adversarial actor here at all — just a business reviewing applications a little too slowly relative to its own completion_deadline, which the contract currently lets happen silently.
Expected behaviour
approve_creator should reject once there's no meaningful time left for the creator to deliver — e.g. once now >= campaign.completion_deadline (or a small configurable buffer before it). Approving with zero time left to submit serves no purpose and only manufactures a dead commitment.
Files
contracts/campaign-escrow/src/lib.rs — approve_creator
Acceptance criteria
Problem
approve_creator(contracts/campaign-escrow/src/lib.rs:345-394) checks the campaign's status, the payout amount,max_creators, and escrow headroom — but never checks any deadline:Meanwhile
submit_proofunconditionally rejects withError::ContentDeadlinePassedonceenv.ledger().timestamp() > campaign.completion_deadline(lib.rs:407-409).Concrete failure scenario
A creator applies before
application_deadline. The business is slow to review and only callsapprove_creatoraftercompletion_deadlinehas already passed — the call succeeds and commitspayout_amountagainst the escrow balance. That creator can now never callsubmit_proof(the deadline is already gone), so the application is permanently stuck atApprovedwith no way to progress — a self-inflicted, zero-malice instance of the "committed payout can become permanently unrecoverable" problem (see the linked issue on that).There's no adversarial actor here at all — just a business reviewing applications a little too slowly relative to its own
completion_deadline, which the contract currently lets happen silently.Expected behaviour
approve_creatorshould reject once there's no meaningful time left for the creator to deliver — e.g. oncenow >= campaign.completion_deadline(or a small configurable buffer before it). Approving with zero time left to submit serves no purpose and only manufactures a dead commitment.Files
contracts/campaign-escrow/src/lib.rs—approve_creatorAcceptance criteria
approve_creatorreturns an error (e.g.Error::ContentDeadlinePassed) when called at or aftercampaign.completion_deadlinecompletion_deadlinefails, instead of silently committing an undeliverable payout