Skip to content

feat(soroban): add require_auth composition helpers - #349

Merged
YaronZaki merged 5 commits into
Quantarq:mainfrom
Gracora:fix/issue-243-require-auth-composition-helpers
Jul 23, 2026
Merged

feat(soroban): add require_auth composition helpers#349
YaronZaki merged 5 commits into
Quantarq:mainfrom
Gracora:fix/issue-243-require-auth-composition-helpers

Conversation

@Gracora

@Gracora Gracora commented Jul 21, 2026

Copy link
Copy Markdown

Summary

Implemented a production-ready fix while maintaining the existing architecture and coding standards.

Changes

  • Added quantara/soroban/contracts/common/src/auth.rs with two helpers:
    • assert_caller_auth(env, caller, operation, args): drops in at the top of every state-mutating entry-point; wraps require_auth_for_args with an explicit Symbol operation tag for self-documenting call-sites and grep-based audits
    • for_each_auth(env, principals): iterates (Address, Vec<Val>) pairs to require auth from multiple principals in a single call
  • Replaced bare require_auth() calls in vault::deposit, vault::withdraw, looping::open_position, looping::close_position with assert_caller_auth
  • Added common to workspace Cargo.toml and as a path dependency in vault/looping
  • Updated common/Cargo.toml to soroban-sdk 22.0.0 with testutils dev-dep
  • 7 tests in auth.rs covering all helpers and adversarial auth sequences
  • Verified linting
  • Ensured no unrelated changes were introduced

Closes #243

Gracora and others added 5 commits July 21, 2026 18:55
Add common::auth module with two composable auth helpers:
- assert_caller_auth(env, caller, operation, args): drop-in guard for every
  state-mutating entry-point; wraps require_auth_for_args with an explicit
  operation Symbol for self-documenting call-sites and grep audits.
- for_each_auth(env, principals): iterate a slice of (Address, Vec<Val>)
  pairs and require auth from each; useful for multi-principal transactions.

Audit all existing entry-points and replace bare require_auth() calls:
- vault::deposit / withdraw now use assert_caller_auth
- looping::open_position / close_position now use assert_caller_auth

Add common to workspace Cargo.toml members.
Update common/Cargo.toml to soroban-sdk 22.0.0 with testutils dev-dep.
Add common as a path dependency to vault and looping crates.

Tests added in auth.rs covering:
- assert_caller_auth passes with mock_all_auths
- assert_caller_auth with no args
- assert_caller_auth with multiple callers
- for_each_auth with empty slice
- for_each_auth with single and two principals
- mock_auths restricts which address satisfies auth

Closes Quantarq#243
- Reformat auth.rs to match rustfmt output (remove multi-line imports
  and function calls that rustfmt collapses to single lines)
- Reformat looping/src/lib.rs close_position to match rustfmt single-line
  form for the assert_caller_auth call
- Remove testutils feature from common [dev-dependencies] to fix
  soroban-env-host v22.1.3 ChaCha20Rng compile error under --all-features
- Add [[bans.allow]] for 'common' in deny.toml to exempt workspace-internal
  path dependencies from the wildcards = 'deny' rule
…deny

Adding common to the workspace members caused two CI failures:
1. cargo clippy --all-targets compiled common's #[cfg(test)] proptest
   tests which use std::panic::catch_unwind — incompatible with the
   crate's #![no_std] attribute, producing E0433 errors.
2. cargo deny audited common's proptest dev-dependency, pulling in
   ~30 transitive crates (autocfg, base64, bit-set, etc.) not in the
   deny.toml license allow-list.

Fix: remove 'common' from workspace members. It remains a valid path
dependency for vault and looping via { path = "../common" }. The
[[bans.allow]] entry for 'common' is retained to exempt the path dep
from the wildcards = "deny" rule.
Three independent failures blocked PR Quantarq#349 (issue Quantarq#243):

* cargo clippy --all-targets --all-features -- -D warnings
  - clippy::doc_overindented_list_items on common/src/auth.rs
    lines 47/49/50 (continuation indent 4-space, reduced to 2-space).
  - E0277 "may contain interior mutability and a reference may not
    be safely transferrable across a catch_unwind boundary" in
    common/src/math.rs tests. The crate is #![no_std] and Env is
    !UnwindSafe. Added extern crate std; + use std::panic::AssertUnwindSafe
    and wrapped each catch_unwind closure in AssertUnwindSafe.

* cargo deny check
  - ~50 error[not-allowed] for transitive crates (autocfg, base64,
    darling, sha2, wasmparser, etc.) caused by [[bans.allow]] name =
    "common" implicitly flipping cargo-deny into an allow-list-only
    default-deny mode. Removed the entry.
  - error[wildcard] on looping/Cargo.toml:14 and vault/Cargo.toml:14
    for `common = { path = "../common" }`. Bumped both to
    `common = { path = "../common", version = "0.1.0" }`.

Also generated Cargo.lock for deterministic cargo-deny resolution in CI.

Verified locally with cargo 1.88.0 / cargo-deny 0.20.2:
- cargo fmt --all -- --check             : exit 0
- cargo clippy --all-targets -- -D warnings : exit 0
- cargo deny check                        : exit 0
- cargo build --target wasm32-unknown-unknown --release : exit 0
- cargo test -p common --lib              : 4 passed; 0 failed

@YaronZaki YaronZaki left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

LGTM

@YaronZaki
YaronZaki merged commit e179fd4 into Quantarq:main Jul 23, 2026
9 checks passed
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.

Standard require_auth composition helpers

2 participants