Skip to content

(Medium) ORG-E1.3 namespace error codes + rename vendor-registry Error enum #142

Description

@EmeditWeb

Summary

Every contract's error codes are dense, low, and mutually colliding: all six enums start at 1 — NotAdmin = 1 (contracts/creditline-contract/src/errors.rs:8, contracts/liquidity-pool-contract/src/errors.rs:7, contracts/reputation-contract/src/errors.rs:8, contracts/vouching-contract/src/errors.rs:3 via NotInitialized = 1), AlreadyInitialized = 1 (contracts/parameters-contract/src/errors.rs:7, contracts/vendor-registry-contract/src/errors.rs:7) — so the integer 1 means "NotAdmin" in creditline, "AlreadyInitialized" in parameters, "NotInitialized" in vouching, and "AlreadyInitialized" again in vendor-registry, with no way for a reader, log, or client to attribute a bare code to its contract. Variant names collide too: NotAdmin appears in five enums, NotInitialized in all six, Overflow in all six, Underflow in all six, ReentrancyDetected in all six. On top of that the vendor-registry type is named the bare pub enum Error (contracts/vendor-registry-contract/src/errors.rs:6), aliased to VendorRegistryError only at the re-export (contracts/vendor-registry-contract/src/lib.rs:17) while internal code still writes Error::… (contracts/vendor-registry-contract/src/lib.rs:33,43,61,67,71), and contractimport!-generated clients surface the raw enum name. A code-number collision makes cross-contract failures ambiguous exactly where try-calls swallow foreign errors (contracts/vouching-contract/src/lib.rs:205,225,238; contracts/creditline-contract/src/lib.rs:355,663,1177).

Why these together: both workstreams are faces of one property — one error integer decoded anywhere unambiguously identifies its contract and variant, and the enum that encodes vendor-registry failures carries its contract's name instead of the bare, collision-prone Error. Namespaced ranges without a renamed vendor enum still leave the one bare Error in the workspace; a rename without ranges still lets 1 mean four different things.

Labels

area: contracts type: refactor priority: medium


Workstream 1 — Assign per-contract code ranges

Objective

Give each contract a disjoint band of error codes so a single integer identifies both the contract and the variant, without changing any variant's local meaning.

Problem

All six enums begin at 1 and run densely (creditline 1-33, liquidity-pool 1-19, parameters 1-19, reputation 1-11, vouching 1-13, vendor-registry 1-13), so codes overlap completely across contracts. Cross-contract clients decode foreign errors by value; with ranges unassigned, 1 from vouching and 1 from creditline are indistinguishable in a shared log or in the try_invoke_contract error path (vouching-contract/src/lib.rs:205,225,238; creditline-contract/src/lib.rs:663,1177).

Scope

  • contracts/creditline-contract/src/errors.rs (edit — rebase codes into its band)
  • contracts/liquidity-pool-contract/src/errors.rs (edit)
  • contracts/parameters-contract/src/errors.rs (edit)
  • contracts/reputation-contract/src/errors.rs (edit)
  • contracts/vouching-contract/src/errors.rs (edit)
  • contracts/vendor-registry-contract/src/errors.rs (edit)
  • context/progress-tracker.md (edit — record the reserved bands)

Implementation

  1. Reserve 100-wide bands by contract, in workspace-member order (Cargo.toml:members): creditline 100-199, reputation 200-299, parameters 300-399, vendor-registry 400-499, liquidity-pool 500-599, vouching 600-699. Base offset knob per contract: ERROR_BASE (constant, default = the band start) so codes read 100 + local.
  2. Rewrite each Variant = n to n = base + local keeping current local order and gaps reserved for growth; keep #[repr(u32)] (errors.rs line 6 of each) unchanged so the wire type stays u32.
  3. Because codes are ABI-visible, treat this as a breaking code change: bump nothing publicly until the catalog regeneration lands; add a context/progress-tracker.md note recording each band so future contracts extend rather than reuse.
  4. Add a workspace test (one per contract or a shared errors_bands test) asserting every variant's code falls inside its contract's reserved band and that no two bands overlap.

Acceptance Criteria

  • Every variant in all six enums has a code inside its contract's reserved 100-band; no band overlaps another.
  • A test iterating all six enums fails if any code lands outside its band (mock: move ParametersError::NotAdmin to 101 → test fails).
  • #[repr(u32)] and variant order semantics are preserved; only numeric values change.

Testing

  • Unit: per-contract band-membership test asserting min(types) >= base && max(types) < base + 100.
  • Integration: an errors_bands integration test across the workspace asserting the six bands are disjoint.

Workstream 2 — Rename the bare Error enum to VendorRegistryError

Objective

Replace the workspace's only bare Error enum with a contract-named type everywhere it is referenced, so the enum name itself is unambiguous.

Problem

contracts/vendor-registry-contract/src/errors.rs:6 declares pub enum Error; the crate re-exports it under an alias (pub use errors::Error as VendorRegistryError; at vendor-registry-contract/src/lib.rs:17) while importing the bare name for internal use (use errors::Error; at :12) and calling Error::AlreadyInitialized etc. throughout (:33,43,61,67,71,95,104,118). A use ...::Error in any consumer silently shadows the prelude/host Error, and contractimport! exposes the generated client's error type under the bare name.

Scope

  • contracts/vendor-registry-contract/src/errors.rs (edit — rename Error → VendorRegistryError)
  • contracts/vendor-registry-contract/src/lib.rs (edit — drop the alias dance, use the new name)
  • contracts/vendor-registry-contract/src/tests.rs (edit — update references)
  • contracts/vendor-registry-contract/src/storage.rs, events.rs, access.rs (edit — any Error:: references)

Implementation

  1. Rename the enum declaration to pub enum VendorRegistryError.
  2. Replace all Error:: references across the crate with VendorRegistryError::; remove the use errors::Error; import (lib.rs:12) and the pub use errors::Error as VendorRegistryError; alias (:17) in favour of a single pub use errors::VendorRegistryError;.
  3. Grep gate: contracts/vendor-registry-contract/src must contain zero occurrences of a bare Error:: or use ...::Error; after the change; add it to the PR checklist.

Acceptance Criteria

  • grep -rn "\bError\b" contracts/vendor-registry-contract/src | grep -v VendorRegistryError returns nothing.
  • The crate re-exports exactly one error type named VendorRegistryError.
  • All vendor-registry tests pass unchanged in assertion content.

Testing

  • Unit: existing vendor-registry test suite (contracts/vendor-registry-contract/src/tests.rs, 26 tests) compiles and passes against the renamed enum.
  • Integration: cargo clippy --workspace --all-targets --locked -- -D warnings is clean (no leftover bare Error).

Shared acceptance criteria (whole epic)

  • cargo fmt --all --check, cargo clippy --workspace --all-targets --locked -- -D warnings, cargo build --locked --target wasm32-unknown-unknown --release, and cargo test --locked all exit 0; test count does not drop.
  • Code values are documented in context/progress-tracker.md (bands) and flow into the generated docs/ERROR_CODES.md.
  • No public function is renamed; only the error enum's name and code values change; #[repr(u32)] preserved.
  • No secrets; no changes outside the six errors.rs files and their referencing call sites.

Security & compatibility considerations

  • Error codes are ABI-visible and appear in try_* return payloads (vouching-contract/src/lib.rs:205,225,238, creditline-contract/src/lib.rs:663,1177); renaming the codes is a coordinated, breaking change — land it together with the catalog regeneration so clients and docs move at once.
  • Band reservation must be recorded so a later contract cannot be assigned an overlapping range.
  • contractimport!-generated clients for these WASMs must be rebuilt in CI (contracts-ci.yml builds the dependency WASMs before creditline) so the renamed/rebanded types propagate.

References

  • contracts/creditline-contract/src/errors.rs:7-41 — 33-variant CreditLineError; NotAdmin = 1 at :8.
  • contracts/liquidity-pool-contract/src/errors.rs:6-26 — 19-variant LiquidityPoolError; NotAdmin = 1 at :7.
  • contracts/parameters-contract/src/errors.rs:6-26 — 19-variant ParametersError; AlreadyInitialized = 1 at :7.
  • contracts/reputation-contract/src/errors.rs:7-19 — 11-variant ReputationError; NotAdmin = 1 at :8.
  • contracts/vouching-contract/src/errors.rs:6-20 — 13-variant VouchingError; NotInitialized = 1 at :7.
  • contracts/vendor-registry-contract/src/errors.rs:6-20 — 13-variant bare Error.
  • contracts/vendor-registry-contract/src/lib.rs:6,12,17,33,43,61,67,71,95,104,118 — alias/import/Error:: call sites.
  • contracts/vouching-contract/src/lib.rs:205,225,238 — cross-contract try-calls surfacing foreign errors.
  • contracts/creditline-contract/src/lib.rs:355,663,1177 — creditline try-calls to vendor-registry/reputation.
  • Cargo.toml:members — contract order that fixes band assignment.
  • context/progress-tracker.md — place to record reserved bands.
  • contracts/creditline-contract/src/lib.rs:9,14-19 — contractimport! clients that expose raw enum names.
  • Feeds the generated error reference; the per-contract error-model documentation work fills each band's rows.

If you're solving this with AI

In scope: the six contracts/*-contract/src/errors.rs files and the call sites that reference their variants (lib.rs, storage.rs, events.rs, access.rs, tests.rs within those crates), plus context/progress-tracker.md — only.
Out of scope: other repos; changing variant names (only the vendor-registry enum name and the numeric codes change); adding/removing variants; renaming public contract functions; new dependencies; reformatting untouched files.
Must: follow the repo PR template exactly; keep CI green for real (build + fmt + clippy + tests); add the band-membership and disjointness tests; a regression test that FAILS if a code escapes its band; reference this issue (Closes #<n>); no secrets.

Contribution requirements: Follow the repo PR template exactly — https://github.com/StepFi-app/StepFi-Contracts/blob/main/.github/pull_request_template.md. Reference this issue in your PR. CI must pass green (build + fmt + clippy + tests). No secrets; no out-of-scope changes.

Activity

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

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions