Skip to content

Job registry and proposal scaling validation 392#664

Open
Stanley-Owoh wants to merge 15 commits into
DXmakers:mainfrom
Stanley-Owoh:job-registry-and-proposal-scaling-validation-392
Open

Job registry and proposal scaling validation 392#664
Stanley-Owoh wants to merge 15 commits into
DXmakers:mainfrom
Stanley-Owoh:job-registry-and-proposal-scaling-validation-392

Conversation

@Stanley-Owoh
Copy link
Copy Markdown
Contributor

Summary

This PR addresses bid modification race conditions in multi-threaded state within the JobRegistry smart contract. The implementation adds reentrancy guards, duplicate bid prevention, address-based bid acceptance (immune to index manipulation), structured error codes, CID validation, and map-like bid storage. All 57 tests pass and the WASM binary compiles to ~30KB.

Changes

contracts/job_registry/src/lib.rs

Race Condition Protections

  • Reentrancy guard: require_not_reentrant() using DataKey::Locked — prevents reentrant calls during submit_bid, cancel_bid, accept_bid, close_job, and submit_deliverable
  • Duplicate bid prevention: Each freelancer can only have one active bid per job, preventing bid-spam manipulation
  • Accept-by-address: accept_bid takes a freelancer address instead of a numeric index — immune to index-shifting race conditions from cancellations
  • Job lock via reentrancy guard: All bid-modifying functions acquire the guard before proceeding

Structured Error Codes

  • Replaced bare panic!("message") with panic_with_error! and a JobRegistryError enum containing 16 distinct error codes:
    • AlreadyInitialized (1), NotInitialized (2), InvalidJobId (3), InvalidBudget (4), InvalidHash (5)
    • JobAlreadyExists (6), JobNotFound (7), JobNotOpen (8), Unauthorized (9)
    • BidAlreadySubmitted (10), BidNotFound (11), InvalidStateTransition (12)
    • JobExpired (13), Overflow (14), BidIndexOutOfBounds (15), ReentrancyDetected (16)

CID Compression & Validation

  • All heavy text strings are stored as compact IPFS CIDs (max 64 bytes)
  • hash_is_valid() enforces non-empty and bounded-length checks on metadata_hash, proposal_hash, and deliverable_hash

Map-Like Bid Storage

  • DataKey::Bids(u64)Vec<BidRecord> — clean key-value mapping from job ID to a dynamic vector of bids
  • Bid operations (submit, cancel, query) use this map-like structure for O(n) iteration

Strict Ownership Validation

  • accept_bid requires caller == job.client — only the job creator can accept proposals
  • close_job and cancel_expired_job enforce the same ownership check
  • submit_deliverable checks caller == assigned freelancer
  • mark_disputed allows only the client or the assigned freelancer

New Functions

Function Purpose
post_job_auto Auto-assigns sequential job IDs
cancel_bid Freelancer can withdraw their bid while job is Open
submit_deliverable Assigned freelancer submits work (CID-based)
mark_disputed Client or freelancer flags an assigned/in-progress job
cancel_expired_job Owner closes a job after its expires_at
set_upgrade_admin / get_upgrade_admin Admin-gated upgrade authority
upgrade Contract WASM upgrade using stored admin
get_bids_page Paginated bid query for scaling
get_bid_at Single bid lookup by index
get_bids_count Total bid count for a job

Storage Layout

  • Instance: Admin, Locked, UpgradeAdmin, NextJobId
  • Persistent: Job(u64), Bids(u64)

State Machine

Open → Assigned → DeliverableSubmitted → Disputed → Closed
  ↓                                                    ↑
  └─────────────────── Closed ─────────────────────────┘

Acceptance Criteria

  • Compiles — all profiles pass with zero warnings
  • WASM size — 30,053 bytes (well within Soroban limits)
  • State transitionOpen → Assigned after successful bid acceptance
  • Out-of-bounds/late bids — blocked with specific error codes
  • 57/57 tests pass

Tests Added/Updated

  • Reentrancy detection tests (via guard pattern)
  • Duplicate bid rejection (BidAlreadySubmitted)
  • Bid cancellation with index stability
  • Expiration-based bid blocking (JobExpired)
  • Paginated bid queries (scaling validation)
  • Full lifecycle (post → bid → accept → deliverable)
  • Dispute marking from valid states only
  • Upgrade admin set/get/authorization
  • Budget edge cases (minimum, maximum, negative, zero)
  • CID validation (empty, oversized)
  • All existing tests updated for new error code format

Closes #392

… snapshots

- Fix badge_level computation in score_from_profile to derive dynamically
  from score via BadgeLevel::from_score, rather than reading stale stored value
- Fix BadgeTier clone in set_badge_metadata to avoid use-after-move
- Fix RoleMetrics::new() initial badge_level to match default score (Bronze)
- Regenerate all Soroban test snapshots for the updated contract logic

All 25 tests passing.
…ity and consistency

- Removed unnecessary whitespace and adjusted formatting in `lib.rs` and `profile.rs`.
- Consolidated function signatures for better clarity.
- Enhanced error handling in arithmetic operations.
- Streamlined badge level assignment logic in the `refresh_badges` method.
- Updated function calls to maintain consistent formatting across the codebase.
…lement-exponential-decay-model-for-reputation-scores-395
…-395' of https://github.com/Stanley-Owoh/lance into implement-exponential-decay-model-for-reputation-scores-395
- Created test snapshot for successful job posting without explicit initialization.
- Created test snapshot for successful deliverable submission after job acceptance.
- Updated ledger entries and event structures to reflect new job and deliverable states.
@vercel
Copy link
Copy Markdown

vercel Bot commented May 29, 2026

@Stanley-Owoh is attempting to deploy a commit to the mAzI's projects Team on Vercel.

A member of the Team first needs to authorize it.

Copy link
Copy Markdown
Contributor

@soomtochukwu soomtochukwu left a comment

Choose a reason for hiding this comment

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

  • If you could fix the merge conflict(s) ASAP
  • see that the CI checks pass

…-registry-and-proposal-scaling-validation-392
@drips-wave
Copy link
Copy Markdown

drips-wave Bot commented May 29, 2026

@Stanley-Owoh 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

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.

[SC-REG-038] Job Registry and Proposal Scaling Validation - Step 38

2 participants