Skip to content

Fix CRITICAL admin bootstrap & MEDIUM delegation cap - #308

Merged
dultimateade merged 2 commits into
dultimateade:mainfrom
jc1788-byte:fix/security-admin-bootstrap-delegation-cap
Oct 17, 2026
Merged

dultimateade merged 2 commits into
dultimateade:mainfrom
jc1788-byte:fix/security-admin-bootstrap-delegation-cap

Conversation

@jc1788-byte

@jc1788-byte jc1788-byte commented Oct 17, 2026 •

Copy link
Copy Markdown
Contributor

Summary

CRITICAL: markets contract admin bootstrap allows any caller

  • Problem: is_admin_internal() returned true when no admin was stored, allowing any caller to front-run deployment and call pause_markets, transfer_ownership, add_admin on a fresh deployment.
  • Fix: Added initialize(env, admin) entrypoint that atomically stores DataKey::Admin and DataKey::Initialized. is_admin_internal() now returns false when admin is unset. All admin entrypoints (pause_markets, unpause_markets, transfer_ownership, add_admin) are gated by assert_is_admin(). Added get_admin and is_paused read-only entrypoints.
  • Also fixed: proptest error variant mismatch (AdminActionTimelocked → AdminCooldownActive) that was failing CI.

MEDIUM: predictify-hybrid delegation voting power uncapped

  • Problem: delegation.rs did not exist; set_delegate/unset_delegate entrypoints were referenced in the event catalog but had no implementation, meaning delegated voting power was uncapped.
  • Fix: Created contracts/predictify-hybrid/src/delegation.rs with DelegationManager implementing set_delegate/unset_delegate. Enforces a 10% cap on delegated voting power per address (MAX_DELEGATION_BPS=1000 of BPS_DENOMINATOR=10000). Cap is checked at delegation time; excess rejected with DelegationCapExceeded. Added DelegationCapExceeded=676 error variant and updated the err_stability snapshot (120→121 variants).

What was tested

  • markets contract: 17 tests pass (14 new auth boundary + 2 cooldown + 1 proptest)
    • initialize sets admin, rejects re-init, requires auth
    • pause_markets/unpause_markets require admin, attacker rejected
    • transfer_ownership admin-only, self-transfer rejected
    • add_admin admin-only, self rejected
    • Critical: admin unset → all admin entrypoints reject attacker
    • Read-only entrypoints require no auth
  • predictify-hybrid delegation: 13 unit tests in delegation.rs covering basic delegation, cap enforcement at boundary, multiple delegators, re-delegation, self-delegation rejection, zero stake rejection, unset without active delegation, and cap calculation

Note

The predictify-hybrid contract has 23 pre-existing compile errors (missing module files: analytics, audit, governance, versioning, etc., and an unclosed delimiter in disputes.rs). These are unrelated to this PR. The new delegation.rs module produces zero compile errors itself, and the markets contract builds and tests cleanly.

closes #283
closes #270
closes #271
closes #284

CRITICAL (markets): Admin bootstrap allowed any caller when admin was
unset. Added initialize() entrypoint that atomically stores admin and
initialized flag. is_admin_internal() now returns false when no admin is
stored (was true). Added pause_markets, unpause_markets, transfer_ownership,
add_admin entrypoints all gated by assert_is_admin(). Added get_admin and
is_paused read-only entrypoints. Fixed proptest error variant mismatch
(AdminCooldownActive vs AdminActionTimelocked).

MEDIUM (predictify-hybrid): Created delegation.rs with DelegationManager
implementing set_delegate/unset_delegate. Enforces 10% cap on delegated
voting power per address (MAX_DELEGATION_BPS=1000 of BPS_DENOMINATOR=10000).
Cap checked at delegation time; excess rejected with DelegationCapExceeded.
Added DelegationCapExceeded=676 error variant and updated err_stability
snapshot (120→121 variants).

Tests: 14 auth boundary tests for markets (initialize, pause/unpause,
transfer_ownership, add_admin, admin-unset rejection, read-only). 13 unit
tests in delegation.rs (basic delegation, cap boundary, multiple delegators,
re-delegation, self-delegation rejection, zero stake, unset, cap calc).
@drips-wave

drips-wave Bot commented Oct 17, 2026

Copy link
Copy Markdown

@jc1788-byte Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits.

You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀

Learn more about application limits

@dultimateade
dultimateade merged commit ae16817 into dultimateade:main Oct 17, 2026
0 of 3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment