Skip to content

Feat(soroban/permissions): add delegate status getter#166

Open
B3rnard601 wants to merge 4 commits into
DelegoLabs:mainfrom
B3rnard601:feat-(Soroban/Permissions)-Add-Delegate-Status-Getter
Open

Feat(soroban/permissions): add delegate status getter#166
B3rnard601 wants to merge 4 commits into
DelegoLabs:mainfrom
B3rnard601:feat-(Soroban/Permissions)-Add-Delegate-Status-Getter

Conversation

@B3rnard601

@B3rnard601 B3rnard601 commented Jun 25, 2026

Copy link
Copy Markdown

Summary

Type of change

  • Bug fix
  • New feature
  • Breaking change
  • Documentation

Test plan

  • pnpm typecheck
  • pnpm test
  • Manual testing (describe):

Checklist

  • Follows project code conventions
  • TODOs reference issues where applicable
  • No secrets or credentials committed

closes #100

Summary by CodeRabbit

  • New Features

    • Added a read-only delegate status check that reports whether a delegate can spend, including remaining allowance and a block reason (inactive, revoked, expired, paused, or exhausted).
  • Bug Fixes

    • Added validations rejecting non-positive amounts and negative grant limits.
    • Improved spendability/allowance decrease checks to prevent over-decreasing beyond granted remaining allowance.
    • Strengthened authorization and made allowance execution safely handle missing permission records and low resulting limits.
  • Tests

    • Added an integration test for over-decreasing allowance beyond total allowance.
    • Expanded delegate-status tests to cover active, missing, revoked, expired, exhausted, and paused states.

@coderabbitai

coderabbitai Bot commented Jun 25, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The permissions contract adds a paused status, a delegate status view, stricter allowance checks, and owner authentication for allowance decreases. Tests were updated for the new status reporting and allowance behavior.

Changes

Permissions lifecycle and status reporting

Layer / File(s) Summary
State model and grant validation
contracts/permissions/src/lib.rs, contracts/permissions/src/test.rs
PermissionStatus adds Paused, DelegateStatusView is introduced, grant rejects negative limits, and the whitelist grant calls use the updated argument order.
Delegate status and spend checks
contracts/permissions/src/lib.rs, contracts/permissions/src/test.rs
can_spend rejects non-positive amounts, get_delegate_status returns active, missing, revoked, expired, exhausted, and paused states, and tests cover the new delegate-status view.
Allowance decrease validation
contracts/permissions/src/lib.rs, contracts/permissions/src/integration_tests.rs
decrease_allowance rejects non-positive and over-limit amounts, with an integration test covering the over-limit panic.
Decrease execution auth and recovery
contracts/permissions/src/lib.rs
execute_decrease_allowance now requires owner authentication first and clears pending decrements when the permission record is missing or would underflow.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related issues

  • DelegoLabs/Delego issue 35 — Adds Paused state handling and paused-status reporting/tests, which matches the pause-related changes here.
  • DelegoLabs/Delego issue 100 — Introduces DelegateStatusView and get_delegate_status for delegate spendability reporting.

Possibly related PRs

  • DelegoLabs/Delego#76 — Touches contracts/permissions/src/lib.rs around spendability checks and grant/test call shapes that overlap with this PR.
  • DelegoLabs/Delego#74 — Covers the allowance-decrease flow that this PR tightens with extra validation and owner auth.

Poem

A bunny peeks at the status tree,
Paused, revoked, or spent by decree.
With hops so neat and checks so fine,
The allowance paths now read just right. 🐰

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning The PR also changes grant validation, can_spend, decrease_allowance, and execute_decrease_allowance behavior beyond the delegate-status getter scope. Split the allowance and auth behavior changes into a separate PR, and keep this one focused on the delegate status getter and its tests.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title is concise and accurately summarizes the main change: adding a delegate status getter.
Linked Issues check ✅ Passed The PR implements DelegateStatusView/get_delegate_status and covers the requested states with tests.
Docstring Coverage ✅ Passed Docstring coverage is 86.67% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@B3rnard601 B3rnard601 changed the title Feat (soroban/permissions) add delegate status getter Feat(soroban/permissions): add delegate status getter Jun 25, 2026

@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: 3

🤖 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/permissions/src/lib.rs`:
- Around line 117-119: The permission grant validation currently treats zero
per-tx limits as valid, which can make a delegation appear active even though it
can never authorize any spend. Update the validation and active-state logic in
the relevant grant construction and evaluation paths (including the branch
around limit_total/limit_per_tx and the corresponding code near can_spend) so
that limit_per_tx must be greater than zero, or otherwise ensure active is false
when no positive spend amount is possible. Apply the same fix in both matching
locations referenced by the existing grant logic.
- Around line 344-348: The pending decrease flow in the permission update path
allows queued decrements to become stuck because `decrease_permission` only
checks `record.limit_total` and does not reserve allowance during the delay.
Update the logic around `decrease_permission` and the execution check in the
permission apply path so a queued decrement cannot later fail when `new_limit <
record.spent`; instead, validate or account for the current spent amount at
queue time, and ensure any rejected or invalid pending decrement is cleared so
it does not block future decreases.
- Around line 280-286: The `get_delegate_status` API currently unwraps the
storage lookup for `DataKey::Permission`, which panics when no delegation
exists. Update `get_delegate_status` to handle the missing `PermissionRecord`
case the same way `can_spend` does by returning an inactive `DelegateStatusView`
with the appropriate reason instead of aborting. Keep the existing behavior for
present records, and use the
`get_delegate_status`/`PermissionRecord`/`DelegateStatusView` flow to locate the
change.
🪄 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 Plus

Run ID: bb486ce1-f610-4bb2-8c5c-d311e2671ab9

📥 Commits

Reviewing files that changed from the base of the PR and between b3d63c6 and cb0b9e0.

📒 Files selected for processing (3)
  • contracts/permissions/src/integration_tests.rs
  • contracts/permissions/src/lib.rs
  • contracts/permissions/src/test.rs

Comment thread contracts/permissions/src/lib.rs
Comment thread contracts/permissions/src/lib.rs Outdated
Comment thread contracts/permissions/src/lib.rs

@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

🤖 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/permissions/src/lib.rs`:
- Around line 201-214: The delegate status logic is using the raw allowance
state and does not reflect pending decrements, so update get_delegate_status
(and the shared delegate status path it uses in the affected range) to subtract
the PendingDecrement amount just like can_spend does. Use the existing
PendingDecrement key lookup and effective remaining calculation so the returned
status reports the adjusted remaining value and marks the delegate inactive when
the effective allowance is exhausted.
🪄 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 Plus

Run ID: 6b7c4b11-3a69-4785-bd1d-1c1e81d475c6

📥 Commits

Reviewing files that changed from the base of the PR and between 270f45f and 275cfe7.

📒 Files selected for processing (2)
  • contracts/permissions/src/lib.rs
  • contracts/permissions/src/test.rs
🚧 Files skipped from review as they are similar to previous changes (1)
  • contracts/permissions/src/test.rs

Comment on lines +201 to +214
let pend_key = DataKey::PendingDecrement(owner.clone(), delegate.clone());
let pending_amount = match env.storage().persistent().get::<DataKey, PendingAllowanceDecrement>(&pend_key) {
Some(p) => p.amount,
None => 0,
};

let remaining = record.limit_total - record.spent;
if amount > remaining {
let effective_remaining = if remaining > pending_amount {
remaining - pending_amount
} else {
0
};

if amount > effective_remaining {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Account for pending decrements in delegate status.

can_spend reserves pending_amount, but get_delegate_status ignores it. If a pending decrease equals the remaining allowance, every positive spend is rejected while the status still returns active: true and the raw remaining.

Proposed fix
-        let key = DataKey::Permission(owner, delegate);
+        let key = DataKey::Permission(owner.clone(), delegate.clone());
         let record: PermissionRecord = match env.storage().persistent().get(&key) {
             Some(r) => r,
             None => {
                 return DelegateStatusView {
                     active: false,
@@
-        let remaining = if record.spent >= record.limit_total {
+        let raw_remaining = if record.spent >= record.limit_total {
             0
         } else {
             record.limit_total - record.spent
         };
+
+        let pend_key = DataKey::PendingDecrement(owner.clone(), delegate.clone());
+        let pending_amount = match env.storage().persistent().get::<DataKey, PendingAllowanceDecrement>(&pend_key) {
+            Some(p) => p.amount,
+            None => 0,
+        };
+
+        let remaining = if raw_remaining > pending_amount {
+            raw_remaining - pending_amount
+        } else {
+            0
+        };
@@
-        if record.spent >= record.limit_total {
+        if remaining == 0 {
             return DelegateStatusView {
                 active: false,
                 reason: symbol_short!("exhausted"),
                 remaining,

Also applies to: 309-359

🤖 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/permissions/src/lib.rs` around lines 201 - 214, The delegate status
logic is using the raw allowance state and does not reflect pending decrements,
so update get_delegate_status (and the shared delegate status path it uses in
the affected range) to subtract the PendingDecrement amount just like can_spend
does. Use the existing PendingDecrement key lookup and effective remaining
calculation so the returned status reports the adjusted remaining value and
marks the delegate inactive when the effective allowance is exhausted.

@ScriptedBro

Copy link
Copy Markdown
Contributor

Resolve conflicts

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.

[Soroban/Permissions] Add Delegate Status Getter

2 participants