Skip to content

feat(events): decouple management authority from funder via per-event manager#23

Open
0xdevcollins wants to merge 2 commits into
testnetfrom
feat/event-manager-authority
Open

feat(events): decouple management authority from funder via per-event manager#23
0xdevcollins wants to merge 2 commits into
testnetfrom
feat/event-manager-authority

Conversation

@0xdevcollins

@0xdevcollins 0xdevcollins commented Jun 8, 2026

Copy link
Copy Markdown
Collaborator

What

Splits the events contract's single owner (funder and management authority) into a funder (owner) and an optional per-event manager. When set, the manager authorizes select_winners + cancel; otherwise it falls back to the owner, so legacy events are unchanged.

Why

Previously the wallet that funded an event was the only one that could operate it: if a member funded a hackathon from a personal or burner wallet, another privileged org member could not publish winners or cancel, because the contract's require_auth was bound to that wallet. Pointing the manager at the org's canonical wallet (signed custodially by the backend) lets any privileged member operate the event regardless of funding source.

Changes

  • DataKey::EventManager(u64) side-map. No EventRecord layout change, so no migration; legacy events fall back to owner-managed.
  • resolve_manager(event_id, owner) + the four management auths (select_winners, start_cancel, process_cancel_batch, finalize_cancel) now use it.
  • create_event records an optional manager; CreateEventParams.manager: Option<Address>.
  • set_manager (gated by the current manager, so it is rotatable) + get_manager.
  • Tests + regenerated snapshots (per the repo's snapshot convention).

Tests

cargo test -p boundless-events -> 79 passed (76 existing unchanged + 3 new: default-falls-back-to-owner, override-recorded, rotation, managed select_winners). Release WASM builds clean.

Deploy

Deployed fresh to testnet with a single-key admin at CATWJ3QXKJBS6UM7WHHNOJCAHWKMAKKRH7E4B4BYHDZ7UNMB4HUPJT2Y (USDC registered, profile contract repointed, backend BOUNDLESS_EVENTS_CONTRACT_ADDRESS updated). Storage is additive and legacy events stay owner-managed, so no migrate step is required.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Per-event management delegation: assignable managers can authorize select/cancel flows; public set/get manager APIs added.
    • Self-service profile bootstrap: users can create their own profile via a new public bootstrap endpoint.
  • Tests

    • Added/updated unit and cross-contract tests and regenerated many snapshots to reflect manager/profile flows.
  • Chores

    • Added optional testnet build feature to speed local upgrades; deploy scripts updated accordingly.

… manager

Add an optional per-event manager (the address that authorizes
select_winners + cancel) so the funding source (owner) can differ from
the operating identity. An org can fund from any wallet, a treasury
wallet, or an external/burner key while keeping management bound to its
canonical wallet, so any privileged member can operate the event.

- New DataKey::EventManager(u64) side-map. No EventRecord layout change,
  so no migration; legacy events fall back to owner-managed.
- create_event records an optional manager; select_winners + all three
  cancel phases now require resolve_manager(...).require_auth() instead
  of event.owner.require_auth().
- New set_manager (gated by the current manager, so an org can rotate its
  operating wallet) + get_manager reads.
- CreateEventParams gains manager: Option<Address>.
- Tests: default-falls-back-to-owner, override-recorded, rotation, and a
  managed event selecting winners. Snapshots regenerated.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jun 8, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Per-event manager support was added to the events contract. Event creation can store a manager override, new APIs read and update it, and cancel/winner-selection authorization now uses the resolved manager instead of always the owner. Tests and snapshots were updated for the new event parameter and authority flow.

Changes

Event manager override

Layer / File(s) Summary
Types, storage, and create_event
contracts/events/src/types.rs, contracts/events/src/storage.rs, contracts/events/src/event_ops.rs
CreateEventParams gains manager, storage adds EventManager, and create_event persists the override when provided.
Manager resolution and public API
contracts/events/src/event_ops.rs, contracts/events/src/lib.rs
resolve_manager selects manager-or-owner, and set_manager/get_manager are exported through the contract API.
Lifecycle authorization changes
contracts/events/src/event_ops.rs
start_cancel, process_cancel_batch, finalize_cancel, and select_winners require the resolved manager authority.
Tests and snapshots
contracts/events/src/tests/*, contracts/events/test_snapshots/tests/*
Test inputs add explicit manager values or None, and snapshot fixtures are refreshed for the new argument and authorization data.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Poem

🐰 I hopped through fields of manager light,
and nibbled auth rules left and right.
A tiny override I left in store,
so owners and managers share the floor.
Thump-thump — now contracts purr, secure and bright.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/event-manager-authority

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
contracts/events/src/tests/cross_contract.rs (1)

1210-1247: ⚡ Quick win

Strengthen manager auth tests to assert the signer identity, not only success paths.

These tests currently pass under global auth mocking even if authority accidentally remains owner. Please assert required auths (or negative path) so regressions in manager gating are caught.

Suggested test hardening pattern
#[test]
fn manager_override_can_select_winners() {
    let ctx = setup();
    let manager = Address::generate(&ctx.env);
    let bounty_id = create_bounty_with_manager(&ctx, &manager);

    let op_apply = BytesN::random(&ctx.env);
    ctx.events.apply_to_bounty(&bounty_id, &ctx.applicant, &op_apply);

    let winners = soroban_sdk::vec![ ... ];
    let op_select = BytesN::random(&ctx.env);
    ctx.events.select_winners(&bounty_id, &winners, &op_select);

+   let auths = ctx.env.auths();
+   let manager_required = auths.iter().any(|(addr, _)| *addr == manager);
+   let owner_required = auths.iter().any(|(addr, _)| *addr == ctx.owner);
+   assert!(manager_required, "select_winners must require manager auth");
+   assert!(!owner_required, "owner auth should not gate managed events");
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@contracts/events/src/tests/cross_contract.rs` around lines 1210 - 1247,
Update the manager auth tests to explicitly assert signer identity: in
manager_can_be_rotated and manager_override_can_select_winners use
Address::generate to create manager and manager2, call
ctx.events.set_manager(&id, &manager2) then assert the old manager cannot
perform manager-only actions (e.g., expect ctx.events.select_winners or whatever
manager-only entrypoint to fail when invoked with the original manager) and that
the new manager (manager2) can successfully perform the same action; use
ctx.events.apply_to_bounty / ctx.events.select_winners / ctx.events.get_event to
verify failure for the wrong signer and success for the correct signer so the
test fails if manager gating reverts to owner or global auth mocking hides
regressions.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@contracts/events/src/storage.rs`:
- Around line 218-225: The EventManager override can silently expire because
only DataKey::EventManager(id) is refreshed in
get_event_manager/set_event_manager while normal event activity only refreshes
DataKey::Event(id); update the code so touch_event_persistent (and/or the event
accessors get_event/set_event) also refreshes the corresponding
DataKey::EventManager(id) TTL when an event is accessed/updated: when
touch_event_persistent(env, &DataKey::Event(id)) is called, check
env.storage().persistent().get(&DataKey::EventManager(id)) and call
touch_event_persistent(env, &DataKey::EventManager(id)) (or reuse the existing
touch logic) so resolve_manager continues to see the delegated manager while the
event is active. Ensure you reference and update get_event, set_event,
touch_event_persistent, and DataKey::EventManager accordingly.

---

Nitpick comments:
In `@contracts/events/src/tests/cross_contract.rs`:
- Around line 1210-1247: Update the manager auth tests to explicitly assert
signer identity: in manager_can_be_rotated and
manager_override_can_select_winners use Address::generate to create manager and
manager2, call ctx.events.set_manager(&id, &manager2) then assert the old
manager cannot perform manager-only actions (e.g., expect
ctx.events.select_winners or whatever manager-only entrypoint to fail when
invoked with the original manager) and that the new manager (manager2) can
successfully perform the same action; use ctx.events.apply_to_bounty /
ctx.events.select_winners / ctx.events.get_event to verify failure for the wrong
signer and success for the correct signer so the test fails if manager gating
reverts to owner or global auth mocking hides regressions.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 90fbb4b4-967e-4b4b-8298-1a7b01a5bd92

📥 Commits

Reviewing files that changed from the base of the PR and between d3a32bd and 8e3dc2b.

📒 Files selected for processing (75)
  • contracts/events/src/event_ops.rs
  • contracts/events/src/lib.rs
  • contracts/events/src/storage.rs
  • contracts/events/src/tests/contributions.rs
  • contracts/events/src/tests/cross_contract.rs
  • contracts/events/src/tests/crowdfunding.rs
  • contracts/events/src/types.rs
  • contracts/events/test_snapshots/tests/admin/apply_upgrade_after_expiry_reverts.1.json
  • contracts/events/test_snapshots/tests/admin/apply_upgrade_before_timelock_reverts.1.json
  • contracts/events/test_snapshots/tests/admin/cancel_pending_upgrade_clears_proposal.1.json
  • contracts/events/test_snapshots/tests/admin/propose_upgrade_records_pending_and_emits.1.json
  • contracts/events/test_snapshots/tests/contributions/add_funds_paged_storage_round_trip.1.json
  • contracts/events/test_snapshots/tests/contributions/add_funds_to_cancelled_event_reverts.1.json
  • contracts/events/test_snapshots/tests/contributions/anyone_can_top_up_an_active_event.1.json
  • contracts/events/test_snapshots/tests/contributions/below_minimum_contribution_reverts.1.json
  • contracts/events/test_snapshots/tests/contributions/cancel_at_boundary_pays_partners_full_no_owner_residual.1.json
  • contracts/events/test_snapshots/tests/contributions/cancel_clears_contributor_amounts_so_replay_state_is_clean.1.json
  • contracts/events/test_snapshots/tests/contributions/cancel_with_no_contributors_refunds_owner_in_full.1.json
  • contracts/events/test_snapshots/tests/contributions/cancel_with_owner_top_up_keeps_owner_residual_correct.1.json
  • contracts/events/test_snapshots/tests/contributions/cancel_with_partner_pool_refunds_partners_then_owner_residual.1.json
  • contracts/events/test_snapshots/tests/contributions/multiple_top_ups_from_same_contributor_aggregate_and_dont_duplicate_list.1.json
  • contracts/events/test_snapshots/tests/contributions/owner_top_up_grows_escrow_without_recording_contribution_entry.1.json
  • contracts/events/test_snapshots/tests/contributions/paged_cancel_owner_only_settles_inside_start.1.json
  • contracts/events/test_snapshots/tests/contributions/paged_cancel_processes_in_batches.1.json
  • contracts/events/test_snapshots/tests/contributions/replayed_add_funds_reverts.1.json
  • contracts/events/test_snapshots/tests/contributions/zero_or_negative_contribution_reverts.1.json
  • contracts/events/test_snapshots/tests/cross_contract/add_funds_uses_event_override_not_global.1.json
  • contracts/events/test_snapshots/tests/cross_contract/apply_charges_credits_via_profile.1.json
  • contracts/events/test_snapshots/tests/cross_contract/bounty_submit_requires_prior_application.1.json
  • contracts/events/test_snapshots/tests/cross_contract/bounty_submit_succeeds_after_apply.1.json
  • contracts/events/test_snapshots/tests/cross_contract/cancel_after_select_winners_refunds_only_remaining.1.json
  • contracts/events/test_snapshots/tests/cross_contract/cancel_already_cancelled_reverts.1.json
  • contracts/events/test_snapshots/tests/cross_contract/cancel_refunds_remaining_escrow_to_owner.1.json
  • contracts/events/test_snapshots/tests/cross_contract/claim_milestone_final_milestone_marks_event_completed.1.json
  • contracts/events/test_snapshots/tests/cross_contract/claim_milestone_idempotent_per_recipient_and_milestone.1.json
  • contracts/events/test_snapshots/tests/cross_contract/claim_milestone_invalid_milestone_index_reverts.1.json
  • contracts/events/test_snapshots/tests/cross_contract/claim_milestone_pays_per_milestone_amount.1.json
  • contracts/events/test_snapshots/tests/cross_contract/claim_milestone_rejects_non_grant_events.1.json
  • contracts/events/test_snapshots/tests/cross_contract/create_event_charges_override_rate_when_provided.1.json
  • contracts/events/test_snapshots/tests/cross_contract/create_event_omitted_override_falls_back_to_global_default.1.json
  • contracts/events/test_snapshots/tests/cross_contract/create_event_with_waiver_charges_no_fee.1.json
  • contracts/events/test_snapshots/tests/cross_contract/duplicate_apply_reverts.1.json
  • contracts/events/test_snapshots/tests/cross_contract/grant_last_milestone_sweeps_rounding_residue.1.json
  • contracts/events/test_snapshots/tests/cross_contract/hackathon_submit_creates_anchor_without_prior_apply.1.json
  • contracts/events/test_snapshots/tests/cross_contract/insufficient_credits_reverts.1.json
  • contracts/events/test_snapshots/tests/cross_contract/manager_can_be_rotated.1.json
  • contracts/events/test_snapshots/tests/cross_contract/manager_defaults_to_owner_and_override_is_recorded.1.json
  • contracts/events/test_snapshots/tests/cross_contract/manager_override_can_select_winners.1.json
  • contracts/events/test_snapshots/tests/cross_contract/replayed_apply_reverts_idempotently.1.json
  • contracts/events/test_snapshots/tests/cross_contract/resubmit_preserves_original_submitted_at_and_updates_uri.1.json
  • contracts/events/test_snapshots/tests/cross_contract/select_winners_handles_multi_recipient_distribution.1.json
  • contracts/events/test_snapshots/tests/cross_contract/select_winners_pays_against_remaining_escrow_including_top_ups.1.json
  • contracts/events/test_snapshots/tests/cross_contract/select_winners_pays_recipient_and_bumps_profile.1.json
  • contracts/events/test_snapshots/tests/cross_contract/select_winners_rejects_duplicate_position.1.json
  • contracts/events/test_snapshots/tests/cross_contract/select_winners_rejects_second_call_winners_already_selected.1.json
  • contracts/events/test_snapshots/tests/cross_contract/select_winners_replayed_reverts.1.json
  • contracts/events/test_snapshots/tests/cross_contract/select_winners_requires_position_in_distribution.1.json
  • contracts/events/test_snapshots/tests/cross_contract/submit_replayed_reverts.1.json
  • contracts/events/test_snapshots/tests/cross_contract/withdraw_refunds_half_credits.1.json
  • contracts/events/test_snapshots/tests/cross_contract/withdraw_submission_removes_anchor.1.json
  • contracts/events/test_snapshots/tests/cross_contract/withdraw_submission_without_submission_reverts.1.json
  • contracts/events/test_snapshots/tests/crowdfunding/builder_top_up_does_not_appear_in_contributor_list.1.json
  • contracts/events/test_snapshots/tests/crowdfunding/cancel_after_partial_claim_pro_rates_remaining.1.json
  • contracts/events/test_snapshots/tests/crowdfunding/cancel_refunds_all_partners_no_owner_residual.1.json
  • contracts/events/test_snapshots/tests/crowdfunding/cancel_with_no_contributions_just_marks_cancelled.1.json
  • contracts/events/test_snapshots/tests/crowdfunding/claim_milestone_last_drains_dust_remainder.1.json
  • contracts/events/test_snapshots/tests/crowdfunding/claim_milestone_out_of_range_reverts.1.json
  • contracts/events/test_snapshots/tests/crowdfunding/claim_milestone_replay_reverts.1.json
  • contracts/events/test_snapshots/tests/crowdfunding/claim_milestone_splits_evenly_across_remaining.1.json
  • contracts/events/test_snapshots/tests/crowdfunding/claim_milestone_with_empty_escrow_reverts.1.json
  • contracts/events/test_snapshots/tests/crowdfunding/community_top_ups_raise_escrow_from_zero.1.json
  • contracts/events/test_snapshots/tests/crowdfunding/create_with_zero_owner_deposit_and_auto_registered_winner.1.json
  • contracts/events/test_snapshots/tests/crowdfunding/crowdfunding_claim_milestone_requires_admin_auth.1.json
  • contracts/events/test_snapshots/tests/crowdfunding/select_winners_on_crowdfunding_reverts.1.json
  • contracts/events/test_snapshots/tests/crowdfunding/submit_on_crowdfunding_reverts.1.json

Comment on lines +218 to +225
pub fn get_event_manager(env: &Env, id: u64) -> Option<Address> {
let key = DataKey::EventManager(id);
let m: Option<Address> = env.storage().persistent().get(&key);
if m.is_some() {
touch_event_persistent(env, &key);
}
m
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

# Verify EventManager TTL refresh points and authority fallback path.
rg -n "EventManager|get_event_manager|set_event_manager|touch_event_persistent|resolve_manager|get_event\\(|set_event\\(" \
  contracts/events/src/storage.rs contracts/events/src/event_ops.rs

Repository: boundlessfi/boundless-contract

Length of output: 7208


🏁 Script executed:

#!/bin/bash
set -euo pipefail

sed -n '1,120p' contracts/events/src/storage.rs
echo "----"
sed -n '180,260p' contracts/events/src/storage.rs
echo "----"
sed -n '40,110p' contracts/events/src/event_ops.rs
echo "----"
sed -n '140,220p' contracts/events/src/event_ops.rs
echo "----"
sed -n '300,360p' contracts/events/src/event_ops.rs
echo "----"
sed -n '780,860p' contracts/events/src/event_ops.rs

Repository: boundlessfi/boundless-contract

Length of output: 17659


🏁 Script executed:

#!/bin/bash
set -euo pipefail

rg -n "resolve_manager\\(" contracts/events/src/event_ops.rs
echo "----"
rg -n "get_event_manager\\(|set_event_manager\\(" contracts/events/src
echo "----"
rg -n "storage::get_event\\(|storage::set_event\\(" contracts/events/src/event_ops.rs

Repository: boundlessfi/boundless-contract

Length of output: 2942


🏁 Script executed:

#!/bin/bash
set -euo pipefail

sed -n '280,360p' contracts/events/src/event_ops.rs
echo "----"
sed -n '380,440p' contracts/events/src/event_ops.rs
echo "----"
sed -n '440,520p' contracts/events/src/event_ops.rs
echo "----"
sed -n '600,660p' contracts/events/src/event_ops.rs

Repository: boundlessfi/boundless-contract

Length of output: 10842


Manager override can expire independently and silently revert authority to owner

DataKey::EventManager(event_id) TTL is only refreshed in get_event_manager/set_event_manager, while normal event activity refreshes only DataKey::Event(event_id) via get_event/set_event. If the manager entry expires while the event stays alive, resolve_manager() falls back to event.owner, so subsequent require_auth in cancel/winner flows will accept the owner instead of the delegated manager.

Suggested fix
pub fn get_event(env: &Env, id: u64) -> Option<EventRecord> {
    let key = DataKey::Event(id);
    let rec: Option<EventRecord> = env.storage().persistent().get(&key);
    if rec.is_some() {
        touch_event_persistent(env, &key);
+       // Keep side-map authority key alive whenever the event itself is alive.
+       let _ = get_event_manager(env, id);
    }
    rec
}

pub fn set_event(env: &Env, id: u64, record: &EventRecord) {
    let key = DataKey::Event(id);
    env.storage().persistent().set(&key, record);
    touch_event_persistent(env, &key);
+   // Keep side-map authority key aligned with event TTL if present.
+   let _ = get_event_manager(env, id);
}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@contracts/events/src/storage.rs` around lines 218 - 225, The EventManager
override can silently expire because only DataKey::EventManager(id) is refreshed
in get_event_manager/set_event_manager while normal event activity only
refreshes DataKey::Event(id); update the code so touch_event_persistent (and/or
the event accessors get_event/set_event) also refreshes the corresponding
DataKey::EventManager(id) TTL when an event is accessed/updated: when
touch_event_persistent(env, &DataKey::Event(id)) is called, check
env.storage().persistent().get(&DataKey::EventManager(id)) and call
touch_event_persistent(env, &DataKey::EventManager(id)) (or reuse the existing
touch logic) so resolve_manager continues to see the delegated manager while the
event is active. Ensure you reference and update get_event, set_event,
touch_event_persistent, and DataKey::EventManager accordingly.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
deploy_and_upgrade.sh (2)

37-40: ⚠️ Potential issue | 🟠 Major | ⚡ Quick win

Fix positional-arg parsing before using NETWORK for feature gating.

NETWORK is read from $4, but for non-propose-upgrade actions the usage places network in arg 3. That makes network selection (and the new testnet feature branch) incorrect.

Suggested patch
 ACTION=${1:-"status"}
 CONTRACT_KIND=${2:-"events"}
-NETWORK=${4:-"testnet"}
-SOURCE_ACCOUNT=${5:-"alice"}
+
+if [ "$ACTION" = "propose-upgrade" ]; then
+    NETWORK=${4:-"testnet"}
+    SOURCE_ACCOUNT=${5:-"alice"}
+else
+    NETWORK=${3:-"testnet"}
+    SOURCE_ACCOUNT=${4:-"alice"}
+fi

Also applies to: 73-77


149-151: ⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

Timelock status output is inaccurate for profile on testnet.

For testnet profile builds (--features testnet), upgrade timelock is 0, but the script always prints ~1 day.

Suggested patch
-    echo "The timelock is ~1 day at 5s/ledger (17_280 ledgers)."
+    if [ "$CONTRACT_KIND" = "profile" ] && [ "$NETWORK" = "testnet" ]; then
+        echo "Timelock is 0 ledgers for testnet profile builds (--features testnet)."
+    else
+        echo "The timelock is ~1 day at 5s/ledger (17_280 ledgers)."
+    fi
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@deploy_and_upgrade.sh` around lines 149 - 151, The script always prints "The
timelock is ~1 day at 5s/ledger (17_280 ledgers)." even when building for
testnet where the timelock is 0; update deploy_and_upgrade.sh to detect the
testnet profile (e.g., check the PROFILE variable or FEATURES/testnet flag used
by the script) and conditionally print the appropriate message: if profile ==
"testnet" emit a line saying the timelock is 0 (or omit the ~1 day lines),
otherwise keep the existing "~1 day" echo lines; locate the three echo
statements ("The timelock is ~1 day...", "Run 'apply-upgrade'...", "Run
'status'...") and wrap them in the profile conditional so testnet output
reflects timelock=0.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Outside diff comments:
In `@deploy_and_upgrade.sh`:
- Around line 149-151: The script always prints "The timelock is ~1 day at
5s/ledger (17_280 ledgers)." even when building for testnet where the timelock
is 0; update deploy_and_upgrade.sh to detect the testnet profile (e.g., check
the PROFILE variable or FEATURES/testnet flag used by the script) and
conditionally print the appropriate message: if profile == "testnet" emit a line
saying the timelock is 0 (or omit the ~1 day lines), otherwise keep the existing
"~1 day" echo lines; locate the three echo statements ("The timelock is ~1
day...", "Run 'apply-upgrade'...", "Run 'status'...") and wrap them in the
profile conditional so testnet output reflects timelock=0.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: f3d8852f-bfe3-4d19-997e-75502e8887da

📥 Commits

Reviewing files that changed from the base of the PR and between 8e3dc2b and e3da6d6.

📒 Files selected for processing (85)
  • contracts/events/Cargo.toml
  • contracts/events/src/admin.rs
  • contracts/events/test_snapshots/tests/admin/apply_upgrade_after_expiry_reverts.1.json
  • contracts/events/test_snapshots/tests/admin/apply_upgrade_before_timelock_reverts.1.json
  • contracts/events/test_snapshots/tests/admin/cancel_pending_upgrade_clears_proposal.1.json
  • contracts/events/test_snapshots/tests/admin/propose_upgrade_records_pending_and_emits.1.json
  • contracts/events/test_snapshots/tests/contributions/add_funds_paged_storage_round_trip.1.json
  • contracts/events/test_snapshots/tests/contributions/add_funds_to_cancelled_event_reverts.1.json
  • contracts/events/test_snapshots/tests/contributions/anyone_can_top_up_an_active_event.1.json
  • contracts/events/test_snapshots/tests/contributions/below_minimum_contribution_reverts.1.json
  • contracts/events/test_snapshots/tests/contributions/cancel_at_boundary_pays_partners_full_no_owner_residual.1.json
  • contracts/events/test_snapshots/tests/contributions/cancel_clears_contributor_amounts_so_replay_state_is_clean.1.json
  • contracts/events/test_snapshots/tests/contributions/cancel_with_no_contributors_refunds_owner_in_full.1.json
  • contracts/events/test_snapshots/tests/contributions/cancel_with_owner_top_up_keeps_owner_residual_correct.1.json
  • contracts/events/test_snapshots/tests/contributions/cancel_with_partner_pool_refunds_partners_then_owner_residual.1.json
  • contracts/events/test_snapshots/tests/contributions/multiple_top_ups_from_same_contributor_aggregate_and_dont_duplicate_list.1.json
  • contracts/events/test_snapshots/tests/contributions/owner_top_up_grows_escrow_without_recording_contribution_entry.1.json
  • contracts/events/test_snapshots/tests/contributions/paged_cancel_owner_only_settles_inside_start.1.json
  • contracts/events/test_snapshots/tests/contributions/paged_cancel_processes_in_batches.1.json
  • contracts/events/test_snapshots/tests/contributions/replayed_add_funds_reverts.1.json
  • contracts/events/test_snapshots/tests/contributions/zero_or_negative_contribution_reverts.1.json
  • contracts/events/test_snapshots/tests/cross_contract/add_funds_uses_event_override_not_global.1.json
  • contracts/events/test_snapshots/tests/cross_contract/apply_charges_credits_via_profile.1.json
  • contracts/events/test_snapshots/tests/cross_contract/bounty_submit_requires_prior_application.1.json
  • contracts/events/test_snapshots/tests/cross_contract/bounty_submit_succeeds_after_apply.1.json
  • contracts/events/test_snapshots/tests/cross_contract/cancel_after_select_winners_refunds_only_remaining.1.json
  • contracts/events/test_snapshots/tests/cross_contract/cancel_already_cancelled_reverts.1.json
  • contracts/events/test_snapshots/tests/cross_contract/cancel_refunds_remaining_escrow_to_owner.1.json
  • contracts/events/test_snapshots/tests/cross_contract/claim_milestone_final_milestone_marks_event_completed.1.json
  • contracts/events/test_snapshots/tests/cross_contract/claim_milestone_idempotent_per_recipient_and_milestone.1.json
  • contracts/events/test_snapshots/tests/cross_contract/claim_milestone_invalid_milestone_index_reverts.1.json
  • contracts/events/test_snapshots/tests/cross_contract/claim_milestone_pays_per_milestone_amount.1.json
  • contracts/events/test_snapshots/tests/cross_contract/claim_milestone_rejects_non_grant_events.1.json
  • contracts/events/test_snapshots/tests/cross_contract/create_event_charges_override_rate_when_provided.1.json
  • contracts/events/test_snapshots/tests/cross_contract/create_event_omitted_override_falls_back_to_global_default.1.json
  • contracts/events/test_snapshots/tests/cross_contract/create_event_with_waiver_charges_no_fee.1.json
  • contracts/events/test_snapshots/tests/cross_contract/duplicate_apply_reverts.1.json
  • contracts/events/test_snapshots/tests/cross_contract/grant_last_milestone_sweeps_rounding_residue.1.json
  • contracts/events/test_snapshots/tests/cross_contract/hackathon_submit_creates_anchor_without_prior_apply.1.json
  • contracts/events/test_snapshots/tests/cross_contract/insufficient_credits_reverts.1.json
  • contracts/events/test_snapshots/tests/cross_contract/manager_can_be_rotated.1.json
  • contracts/events/test_snapshots/tests/cross_contract/manager_defaults_to_owner_and_override_is_recorded.1.json
  • contracts/events/test_snapshots/tests/cross_contract/manager_override_can_select_winners.1.json
  • contracts/events/test_snapshots/tests/cross_contract/replayed_apply_reverts_idempotently.1.json
  • contracts/events/test_snapshots/tests/cross_contract/resubmit_preserves_original_submitted_at_and_updates_uri.1.json
  • contracts/events/test_snapshots/tests/cross_contract/select_winners_handles_multi_recipient_distribution.1.json
  • contracts/events/test_snapshots/tests/cross_contract/select_winners_pays_against_remaining_escrow_including_top_ups.1.json
  • contracts/events/test_snapshots/tests/cross_contract/select_winners_pays_recipient_and_bumps_profile.1.json
  • contracts/events/test_snapshots/tests/cross_contract/select_winners_rejects_duplicate_position.1.json
  • contracts/events/test_snapshots/tests/cross_contract/select_winners_rejects_second_call_winners_already_selected.1.json
  • contracts/events/test_snapshots/tests/cross_contract/select_winners_replayed_reverts.1.json
  • contracts/events/test_snapshots/tests/cross_contract/select_winners_requires_position_in_distribution.1.json
  • contracts/events/test_snapshots/tests/cross_contract/submit_replayed_reverts.1.json
  • contracts/events/test_snapshots/tests/cross_contract/withdraw_refunds_half_credits.1.json
  • contracts/events/test_snapshots/tests/cross_contract/withdraw_submission_removes_anchor.1.json
  • contracts/events/test_snapshots/tests/cross_contract/withdraw_submission_without_submission_reverts.1.json
  • contracts/events/test_snapshots/tests/crowdfunding/builder_top_up_does_not_appear_in_contributor_list.1.json
  • contracts/events/test_snapshots/tests/crowdfunding/cancel_after_partial_claim_pro_rates_remaining.1.json
  • contracts/events/test_snapshots/tests/crowdfunding/cancel_refunds_all_partners_no_owner_residual.1.json
  • contracts/events/test_snapshots/tests/crowdfunding/cancel_with_no_contributions_just_marks_cancelled.1.json
  • contracts/events/test_snapshots/tests/crowdfunding/claim_milestone_last_drains_dust_remainder.1.json
  • contracts/events/test_snapshots/tests/crowdfunding/claim_milestone_out_of_range_reverts.1.json
  • contracts/events/test_snapshots/tests/crowdfunding/claim_milestone_replay_reverts.1.json
  • contracts/events/test_snapshots/tests/crowdfunding/claim_milestone_splits_evenly_across_remaining.1.json
  • contracts/events/test_snapshots/tests/crowdfunding/claim_milestone_with_empty_escrow_reverts.1.json
  • contracts/events/test_snapshots/tests/crowdfunding/community_top_ups_raise_escrow_from_zero.1.json
  • contracts/events/test_snapshots/tests/crowdfunding/create_with_zero_owner_deposit_and_auto_registered_winner.1.json
  • contracts/events/test_snapshots/tests/crowdfunding/crowdfunding_claim_milestone_requires_admin_auth.1.json
  • contracts/events/test_snapshots/tests/crowdfunding/select_winners_on_crowdfunding_reverts.1.json
  • contracts/events/test_snapshots/tests/crowdfunding/submit_on_crowdfunding_reverts.1.json
  • contracts/profile/Cargo.toml
  • contracts/profile/src/admin.rs
  • contracts/profile/src/credits.rs
  • contracts/profile/src/lib.rs
  • contracts/profile/src/tests/bootstrap.rs
  • contracts/profile/src/tests/mod.rs
  • contracts/profile/test_snapshots/tests/admin/apply_upgrade_after_expiry_reverts_profile.1.json
  • contracts/profile/test_snapshots/tests/admin/apply_upgrade_before_timelock_reverts_profile.1.json
  • contracts/profile/test_snapshots/tests/admin/propose_upgrade_records_pending.1.json
  • contracts/profile/test_snapshots/tests/bootstrap/bootstrap_self_creates_profile_for_caller.1.json
  • contracts/profile/test_snapshots/tests/bootstrap/bootstrap_self_demands_the_callers_own_auth_not_admin.1.json
  • contracts/profile/test_snapshots/tests/bootstrap/bootstrap_self_is_idempotent_for_existing_profile.1.json
  • contracts/profile/test_snapshots/tests/bootstrap/bootstrap_self_rejects_a_replayed_op_id.1.json
  • deploy_and_upgrade.sh
  • scripts/deploy/deploy.sh
✅ Files skipped from review due to trivial changes (38)
  • contracts/profile/test_snapshots/tests/bootstrap/bootstrap_self_rejects_a_replayed_op_id.1.json
  • contracts/events/test_snapshots/tests/admin/propose_upgrade_records_pending_and_emits.1.json
  • contracts/profile/test_snapshots/tests/bootstrap/bootstrap_self_is_idempotent_for_existing_profile.1.json
  • contracts/profile/test_snapshots/tests/admin/apply_upgrade_before_timelock_reverts_profile.1.json
  • contracts/events/test_snapshots/tests/admin/cancel_pending_upgrade_clears_proposal.1.json
  • contracts/profile/test_snapshots/tests/admin/apply_upgrade_after_expiry_reverts_profile.1.json
  • contracts/profile/test_snapshots/tests/admin/propose_upgrade_records_pending.1.json
  • contracts/events/test_snapshots/tests/cross_contract/manager_defaults_to_owner_and_override_is_recorded.1.json
  • contracts/events/test_snapshots/tests/admin/apply_upgrade_after_expiry_reverts.1.json
  • contracts/events/test_snapshots/tests/cross_contract/withdraw_refunds_half_credits.1.json
  • contracts/events/test_snapshots/tests/admin/apply_upgrade_before_timelock_reverts.1.json
  • contracts/events/test_snapshots/tests/contributions/zero_or_negative_contribution_reverts.1.json
  • contracts/profile/test_snapshots/tests/bootstrap/bootstrap_self_demands_the_callers_own_auth_not_admin.1.json
  • contracts/events/test_snapshots/tests/cross_contract/select_winners_pays_recipient_and_bumps_profile.1.json
  • contracts/events/test_snapshots/tests/crowdfunding/select_winners_on_crowdfunding_reverts.1.json
  • contracts/events/test_snapshots/tests/cross_contract/apply_charges_credits_via_profile.1.json
  • contracts/events/test_snapshots/tests/cross_contract/select_winners_requires_position_in_distribution.1.json
  • contracts/events/test_snapshots/tests/cross_contract/select_winners_rejects_second_call_winners_already_selected.1.json
  • contracts/events/test_snapshots/tests/contributions/paged_cancel_owner_only_settles_inside_start.1.json
  • contracts/events/test_snapshots/tests/crowdfunding/cancel_refunds_all_partners_no_owner_residual.1.json
  • contracts/events/test_snapshots/tests/contributions/cancel_clears_contributor_amounts_so_replay_state_is_clean.1.json
  • contracts/events/test_snapshots/tests/contributions/replayed_add_funds_reverts.1.json
  • contracts/events/test_snapshots/tests/cross_contract/add_funds_uses_event_override_not_global.1.json
  • contracts/events/test_snapshots/tests/cross_contract/submit_replayed_reverts.1.json
  • contracts/events/test_snapshots/tests/cross_contract/select_winners_handles_multi_recipient_distribution.1.json
  • contracts/events/test_snapshots/tests/cross_contract/manager_override_can_select_winners.1.json
  • contracts/events/test_snapshots/tests/crowdfunding/claim_milestone_splits_evenly_across_remaining.1.json
  • contracts/events/test_snapshots/tests/cross_contract/withdraw_submission_removes_anchor.1.json
  • contracts/events/test_snapshots/tests/contributions/multiple_top_ups_from_same_contributor_aggregate_and_dont_duplicate_list.1.json
  • contracts/events/test_snapshots/tests/contributions/cancel_with_owner_top_up_keeps_owner_residual_correct.1.json
  • contracts/events/test_snapshots/tests/cross_contract/bounty_submit_succeeds_after_apply.1.json
  • contracts/events/test_snapshots/tests/crowdfunding/cancel_with_no_contributions_just_marks_cancelled.1.json
  • contracts/events/test_snapshots/tests/contributions/below_minimum_contribution_reverts.1.json
  • contracts/events/test_snapshots/tests/cross_contract/claim_milestone_final_milestone_marks_event_completed.1.json
  • contracts/events/test_snapshots/tests/contributions/cancel_with_partner_pool_refunds_partners_then_owner_residual.1.json
  • contracts/events/test_snapshots/tests/crowdfunding/claim_milestone_out_of_range_reverts.1.json
  • contracts/events/test_snapshots/tests/cross_contract/duplicate_apply_reverts.1.json
  • contracts/events/test_snapshots/tests/contributions/owner_top_up_grows_escrow_without_recording_contribution_entry.1.json
🚧 Files skipped from review as they are similar to previous changes (33)
  • contracts/events/test_snapshots/tests/cross_contract/select_winners_rejects_duplicate_position.1.json
  • contracts/events/test_snapshots/tests/cross_contract/create_event_with_waiver_charges_no_fee.1.json
  • contracts/events/test_snapshots/tests/cross_contract/replayed_apply_reverts_idempotently.1.json
  • contracts/events/test_snapshots/tests/cross_contract/cancel_already_cancelled_reverts.1.json
  • contracts/events/test_snapshots/tests/crowdfunding/create_with_zero_owner_deposit_and_auto_registered_winner.1.json
  • contracts/events/test_snapshots/tests/cross_contract/withdraw_submission_without_submission_reverts.1.json
  • contracts/events/test_snapshots/tests/crowdfunding/claim_milestone_with_empty_escrow_reverts.1.json
  • contracts/events/test_snapshots/tests/cross_contract/manager_can_be_rotated.1.json
  • contracts/events/test_snapshots/tests/crowdfunding/submit_on_crowdfunding_reverts.1.json
  • contracts/events/test_snapshots/tests/crowdfunding/crowdfunding_claim_milestone_requires_admin_auth.1.json
  • contracts/events/test_snapshots/tests/contributions/add_funds_to_cancelled_event_reverts.1.json
  • contracts/events/test_snapshots/tests/cross_contract/cancel_refunds_remaining_escrow_to_owner.1.json
  • contracts/events/test_snapshots/tests/cross_contract/resubmit_preserves_original_submitted_at_and_updates_uri.1.json
  • contracts/events/test_snapshots/tests/crowdfunding/builder_top_up_does_not_appear_in_contributor_list.1.json
  • contracts/events/test_snapshots/tests/cross_contract/bounty_submit_requires_prior_application.1.json
  • contracts/events/test_snapshots/tests/contributions/cancel_with_no_contributors_refunds_owner_in_full.1.json
  • contracts/events/test_snapshots/tests/cross_contract/create_event_charges_override_rate_when_provided.1.json
  • contracts/events/test_snapshots/tests/cross_contract/create_event_omitted_override_falls_back_to_global_default.1.json
  • contracts/events/test_snapshots/tests/contributions/add_funds_paged_storage_round_trip.1.json
  • contracts/events/test_snapshots/tests/cross_contract/insufficient_credits_reverts.1.json
  • contracts/events/test_snapshots/tests/contributions/paged_cancel_processes_in_batches.1.json
  • contracts/events/test_snapshots/tests/cross_contract/hackathon_submit_creates_anchor_without_prior_apply.1.json
  • contracts/events/test_snapshots/tests/crowdfunding/claim_milestone_replay_reverts.1.json
  • contracts/events/test_snapshots/tests/cross_contract/claim_milestone_invalid_milestone_index_reverts.1.json
  • contracts/events/test_snapshots/tests/contributions/anyone_can_top_up_an_active_event.1.json
  • contracts/events/test_snapshots/tests/cross_contract/select_winners_replayed_reverts.1.json
  • contracts/events/test_snapshots/tests/crowdfunding/community_top_ups_raise_escrow_from_zero.1.json
  • contracts/events/test_snapshots/tests/cross_contract/grant_last_milestone_sweeps_rounding_residue.1.json
  • contracts/events/test_snapshots/tests/crowdfunding/claim_milestone_last_drains_dust_remainder.1.json
  • contracts/events/test_snapshots/tests/cross_contract/claim_milestone_idempotent_per_recipient_and_milestone.1.json
  • contracts/events/test_snapshots/tests/cross_contract/select_winners_pays_against_remaining_escrow_including_top_ups.1.json
  • contracts/events/test_snapshots/tests/cross_contract/cancel_after_select_winners_refunds_only_remaining.1.json
  • contracts/events/test_snapshots/tests/contributions/cancel_at_boundary_pays_partners_full_no_owner_residual.1.json

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant