Skip to content

Commit 92eb157

Browse files
authored
feat(events): stop enforcing the submission deadline on-chain (#99)
The submission deadline was enforced by the contract (reject apply/submit/ withdraw_submission after it, require+future-check at create), but it gates nothing the contract is responsible for: - no money path reads it (since #61 the payout/refund liveness is anchored to select-time via PRIZE_CLAIM_WINDOW_SECS, not the deadline); - winners are the manager's discretion — select_winners never consults submissions, so a late submission row is inert; - permissionless-submit storage abuse is bounded by the #86 count cap, not the deadline. Meanwhile the deadline is immutable on-chain (no set/extend entrypoint), so the contract could not support the extensions organizers do routinely. A submission window — with its extensions, grace periods, and cutoffs — is a backend/product concern; the chain keeps only custody, the count cap, and discretionary winner selection. Remove the enforcement: - delete the deadline checks in submit / withdraw_submission / bounty apply and the create-time DeadlineMustBeFuture check; - drop the required-deadline check from hackathon/crowdfunding validate_create. Keep EventRecord.deadline as advisory metadata (still stored, emitted at create, backend-owned) — no storage-layout change, no ABI break. The now-dead DeadlineRequired/DeadlinePassed/DeadlineMustBeFuture variants are retired, freeing 3 slots against the 50-case error-enum cap. Removed the 5 tests that asserted the deleted behavior. 220 events + 66 profile green; make build OK (events 55,742 B); fmt clean.
1 parent eed33cf commit 92eb157

8 files changed

Lines changed: 5 additions & 130 deletions

File tree

contracts/events/src/bounty.rs

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ pub fn apply(
2828
admin::require_not_paused(env)?;
2929

3030
let event = storage::get_event(env, bounty_id).ok_or(Error::EventNotFound)?;
31-
require_active_bounty(env, &event)?;
31+
require_active_bounty(&event)?;
3232

3333
applicant.require_auth();
3434
idempotency::require_unseen(env, &applicant, &op_id)?;
@@ -61,7 +61,7 @@ pub fn withdraw_application(
6161
admin::require_not_paused(env)?;
6262

6363
let event = storage::get_event(env, bounty_id).ok_or(Error::EventNotFound)?;
64-
require_active_bounty(env, &event)?;
64+
require_active_bounty(&event)?;
6565

6666
applicant.require_auth();
6767
idempotency::require_unseen(env, &applicant, &op_id)?;
@@ -85,17 +85,12 @@ pub fn withdraw_application(
8585
// ============================================================
8686
// HELPERS
8787
// ============================================================
88-
fn require_active_bounty(env: &Env, event: &EventRecord) -> Result<(), Error> {
88+
fn require_active_bounty(event: &EventRecord) -> Result<(), Error> {
8989
if !matches!(event.pillar, Pillar::Bounty) {
9090
return Err(Error::InvalidPillar);
9191
}
9292
if !matches!(event.status, EventStatus::Active) {
9393
return Err(Error::EventNotActive);
9494
}
95-
if let Some(deadline) = event.deadline {
96-
if deadline <= env.ledger().timestamp() {
97-
return Err(Error::DeadlinePassed);
98-
}
99-
}
10095
Ok(())
10196
}

contracts/events/src/crowdfunding.rs

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,6 @@ pub fn validate_create(_env: &Env, record: &EventRecord, _owner: &Address) -> Re
1111
_ => return Err(Error::InvalidReleaseKind),
1212
}
1313

14-
if record.deadline.is_none() {
15-
return Err(Error::DeadlineRequired);
16-
}
17-
1814
if record.winner_distribution.len() != 1 {
1915
return Err(Error::InvalidDistribution);
2016
}

contracts/events/src/errors.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,8 @@ pub enum Error {
2929
InvalidReleaseKind = 33,
3030
InvalidDistribution = 34,
3131
InvalidBudget = 35,
32-
DeadlineRequired = 36,
33-
DeadlinePassed = 37,
34-
DeadlineMustBeFuture = 38,
32+
// 36-38 retired: deadline enforcement removed (submission windows are an
33+
// off-chain/backend concern; the contract no longer gates on deadline).
3534
TitleTooLong = 39,
3635

3736
ApplicantAlreadyApplied = 40,

contracts/events/src/event_ops.rs

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -81,12 +81,6 @@ pub fn create_event(env: &Env, params: CreateEventParams, op_id: BytesN<32>) ->
8181
return Err(Error::DistributionMismatch);
8282
}
8383

84-
if let Some(deadline) = params.deadline {
85-
if deadline <= env.ledger().timestamp() {
86-
return Err(Error::DeadlineMustBeFuture);
87-
}
88-
}
89-
9084
if let Some(bps) = params.fee_bps_override {
9185
if bps > MAX_FEE_BPS {
9286
return Err(Error::InvalidFeeBps);
@@ -544,11 +538,6 @@ pub fn submit(
544538
if matches!(event.pillar, Pillar::Crowdfunding) {
545539
return Err(Error::InvalidPillar);
546540
}
547-
if let Some(deadline) = event.deadline {
548-
if deadline <= env.ledger().timestamp() {
549-
return Err(Error::DeadlinePassed);
550-
}
551-
}
552541

553542
applicant.require_auth();
554543
idempotency::require_unseen(env, &applicant, &op_id)?;
@@ -612,11 +601,6 @@ pub fn withdraw_submission(
612601
if !matches!(event.status, EventStatus::Active) {
613602
return Err(Error::EventNotActive);
614603
}
615-
if let Some(deadline) = event.deadline {
616-
if deadline <= env.ledger().timestamp() {
617-
return Err(Error::DeadlinePassed);
618-
}
619-
}
620604

621605
applicant.require_auth();
622606
idempotency::require_unseen(env, &applicant, &op_id)?;

contracts/events/src/hackathon.rs

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,5 @@ pub fn validate_create(_env: &Env, record: &EventRecord, _owner: &Address) -> Re
99
if !matches!(record.release_kind, ReleaseKind::Single) {
1010
return Err(Error::InvalidReleaseKind);
1111
}
12-
if record.deadline.is_none() {
13-
return Err(Error::DeadlineRequired);
14-
}
1512
Ok(())
1613
}

contracts/events/src/tests/bounty_pillar.rs

Lines changed: 0 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -280,24 +280,6 @@ fn apply_on_completed_event_reverts() {
280280
assert_eq!(err, Error::EventNotActive);
281281
}
282282

283-
#[test]
284-
fn apply_after_deadline_reverts() {
285-
let ctx = setup();
286-
let deadline = ctx.env.ledger().timestamp() + 100;
287-
let bounty_id = create_bounty_with_deadline(&ctx, deadline);
288-
289-
ctx.env.ledger().with_mut(|li| {
290-
li.timestamp = deadline;
291-
});
292-
293-
let op_id = BytesN::random(&ctx.env);
294-
let err = expect_op_err(
295-
ctx.events
296-
.try_apply_to_bounty(&bounty_id, &ctx.applicant, &op_id),
297-
);
298-
assert_eq!(err, Error::DeadlinePassed);
299-
}
300-
301283
#[test]
302284
fn apply_when_paused_reverts() {
303285
let ctx = setup();

contracts/events/src/tests/crowdfunding.rs

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -158,27 +158,6 @@ fn create_rejects_single_release_kind() {
158158
assert!(res.is_err(), "single release must be rejected");
159159
}
160160

161-
#[test]
162-
fn create_rejects_missing_deadline() {
163-
let ctx = setup();
164-
let params = CreateEventParams {
165-
pillar: Pillar::Crowdfunding,
166-
owner: ctx.builder.clone(),
167-
token: ctx.token_addr.clone(),
168-
total_budget: FUNDING_GOAL,
169-
release_kind: ReleaseKind::Multi(3),
170-
content_uri: String::from_str(&ctx.env, "uri"),
171-
title: String::from_str(&ctx.env, "Bad CF"),
172-
deadline: None,
173-
winner_distribution: single_dist_100_at_1(&ctx.env),
174-
fee_bps_override: None,
175-
manager: None,
176-
};
177-
let op = BytesN::random(&ctx.env);
178-
let res = ctx.events.try_create_event(&params, &op);
179-
assert!(res.is_err());
180-
}
181-
182161
#[test]
183162
fn create_rejects_distribution_with_multiple_positions() {
184163
let ctx = setup();

contracts/events/src/tests/hackathon_pillar.rs

Lines changed: 0 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -172,48 +172,6 @@ fn create_rejects_multi_release_kind() {
172172
assert!(res.is_err(), "hackathon must use Single release");
173173
}
174174

175-
#[test]
176-
fn create_rejects_missing_deadline() {
177-
let ctx = setup();
178-
let params = CreateEventParams {
179-
pillar: Pillar::Hackathon,
180-
owner: ctx.owner.clone(),
181-
token: ctx.token_addr.clone(),
182-
total_budget: TOTAL_BUDGET,
183-
release_kind: ReleaseKind::Single,
184-
content_uri: String::from_str(&ctx.env, "uri"),
185-
title: String::from_str(&ctx.env, "Hackathon"),
186-
deadline: None,
187-
winner_distribution: single_winner_dist(&ctx.env),
188-
fee_bps_override: None,
189-
manager: None,
190-
};
191-
let op = BytesN::random(&ctx.env);
192-
let res = ctx.events.try_create_event(&params, &op);
193-
assert!(res.is_err(), "hackathon requires a submission deadline");
194-
}
195-
196-
#[test]
197-
fn create_rejects_past_deadline() {
198-
let ctx = setup();
199-
let params = CreateEventParams {
200-
pillar: Pillar::Hackathon,
201-
owner: ctx.owner.clone(),
202-
token: ctx.token_addr.clone(),
203-
total_budget: TOTAL_BUDGET,
204-
release_kind: ReleaseKind::Single,
205-
content_uri: String::from_str(&ctx.env, "uri"),
206-
title: String::from_str(&ctx.env, "Hackathon"),
207-
deadline: Some(ctx.env.ledger().timestamp()),
208-
winner_distribution: single_winner_dist(&ctx.env),
209-
fee_bps_override: None,
210-
manager: None,
211-
};
212-
let op = BytesN::random(&ctx.env);
213-
let res = ctx.events.try_create_event(&params, &op);
214-
assert!(res.is_err(), "deadline must be in the future");
215-
}
216-
217175
// ============================================================
218176
// submit (open submission model)
219177
// ============================================================
@@ -252,21 +210,6 @@ fn resubmit_keeps_original_timestamp_and_updates_uri() {
252210
assert_eq!(second.submitted_at, first_time);
253211
}
254212

255-
#[test]
256-
fn submit_after_deadline_reverts() {
257-
let ctx = setup();
258-
let id = create_hackathon(&ctx);
259-
260-
ctx.env.ledger().with_mut(|li| {
261-
li.timestamp += 2 * 86_400;
262-
});
263-
264-
let uri = String::from_str(&ctx.env, "ipfs://Qm.../late.json");
265-
let op = BytesN::random(&ctx.env);
266-
let res = ctx.events.try_submit(&id, &ctx.applicant, &uri, &op);
267-
assert!(res.is_err(), "submission after the deadline must revert");
268-
}
269-
270213
#[test]
271214
fn submit_replayed_op_reverts() {
272215
let ctx = setup();

0 commit comments

Comments
 (0)