Skip to content

Commit 6d9e981

Browse files
committed
fix: decouple profile calls from payout in claim_prize and claim_milestone
1 parent a413d23 commit 6d9e981

2 files changed

Lines changed: 31 additions & 28 deletions

File tree

contracts/events/src/event_ops.rs

Lines changed: 16 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -764,23 +764,10 @@ pub fn claim_prize(
764764
return Err(Error::InsufficientEscrow);
765765
}
766766

767-
// Release token from escrow.
767+
// Release token from escrow — critical path, must succeed.
768768
escrow::release(env, &event.token, &recipient, amount);
769769
event.remaining_escrow = event.remaining_escrow.saturating_sub(amount);
770770

771-
// Cross-contract profile mutations. Each call gets a unique child op_id.
772-
let profile = profile_client::client(env);
773-
let reason_win = Symbol::new(env, "win");
774-
775-
let bootstrap_op = idempotency::derive_child(env, &op_id, tag::BOOTSTRAP);
776-
profile.bootstrap(&recipient, &bootstrap_op);
777-
778-
let rep_op = idempotency::derive_child(env, &op_id, tag::BUMP_REP);
779-
profile.bump_reputation(&recipient, &reputation_bump, &reason_win, &rep_op);
780-
781-
let earnings_op = idempotency::derive_child(env, &op_id, tag::REGISTER_EARNINGS);
782-
profile.register_earnings(&recipient, &event.token, &amount, &earnings_op);
783-
784771
// Mark prize claimed (prevents replay for this recipient + position).
785772
storage::mark_prize_claimed(env, event_id, &recipient, position);
786773

@@ -807,12 +794,26 @@ pub fn claim_prize(
807794

808795
evt::PrizeClaimed {
809796
event_id,
810-
recipient,
797+
recipient: recipient.clone(),
811798
position,
812799
amount,
813800
}
814801
.publish(env);
815802

803+
// Best-effort profile side effects — payout is already finalised so a
804+
// profile-contract failure must not block the claim.
805+
let profile = profile_client::client(env);
806+
let reason_win = Symbol::new(env, "win");
807+
808+
let bootstrap_op = idempotency::derive_child(env, &op_id, tag::BOOTSTRAP);
809+
let _ = profile.try_bootstrap(&recipient, &bootstrap_op);
810+
811+
let rep_op = idempotency::derive_child(env, &op_id, tag::BUMP_REP);
812+
let _ = profile.try_bump_reputation(&recipient, &reputation_bump, &reason_win, &rep_op);
813+
814+
let earnings_op = idempotency::derive_child(env, &op_id, tag::REGISTER_EARNINGS);
815+
let _ = profile.try_register_earnings(&recipient, &event.token, &amount, &earnings_op);
816+
816817
idempotency::mark_seen(env, &op_id);
817818
Ok(())
818819
}

contracts/events/src/grant.rs

Lines changed: 15 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -121,18 +121,6 @@ pub fn claim_milestone(
121121
storage::set_crowdfunding_milestones_claimed(env, event_id, claimed.saturating_add(1));
122122
}
123123

124-
let profile = profile_client::client(env);
125-
let reason = Symbol::new(env, "milestone");
126-
127-
let bootstrap_op = idempotency::derive_child(env, &op_id, tag::BOOTSTRAP);
128-
profile.bootstrap(&recipient, &bootstrap_op);
129-
130-
let rep_op = idempotency::derive_child(env, &op_id, tag::BUMP_REP);
131-
profile.bump_reputation(&recipient, &reputation_bump, &reason, &rep_op);
132-
133-
let earnings_op = idempotency::derive_child(env, &op_id, tag::REGISTER_EARNINGS);
134-
profile.register_earnings(&recipient, &event.token, &amount, &earnings_op);
135-
136124
storage::append_winner(
137125
env,
138126
event_id,
@@ -153,12 +141,26 @@ pub fn claim_milestone(
153141

154142
evt::MilestoneClaimed {
155143
event_id,
156-
recipient,
144+
recipient: recipient.clone(),
157145
milestone,
158146
amount,
159147
}
160148
.publish(env);
161149

150+
// Best-effort profile side effects — payout is already finalised so a
151+
// profile-contract failure must not block the claim.
152+
let profile = profile_client::client(env);
153+
let reason = Symbol::new(env, "milestone");
154+
155+
let bootstrap_op = idempotency::derive_child(env, &op_id, tag::BOOTSTRAP);
156+
let _ = profile.try_bootstrap(&recipient, &bootstrap_op);
157+
158+
let rep_op = idempotency::derive_child(env, &op_id, tag::BUMP_REP);
159+
let _ = profile.try_bump_reputation(&recipient, &reputation_bump, &reason, &rep_op);
160+
161+
let earnings_op = idempotency::derive_child(env, &op_id, tag::REGISTER_EARNINGS);
162+
let _ = profile.try_register_earnings(&recipient, &event.token, &amount, &earnings_op);
163+
162164
idempotency::mark_seen(env, &op_id);
163165
Ok(())
164166
}

0 commit comments

Comments
 (0)