From d2db362c88601a512d9d3e05df2e773feace9a5b Mon Sep 17 00:00:00 2001 From: Obiajulu-gif Date: Thu, 23 Apr 2026 14:55:43 -0700 Subject: [PATCH 1/2] feat(contracts): implement comprehensive logging and docs for JobRegistry::post_job --- contracts/job_registry/src/lib.rs | 11 +++++++++-- docs/contracts/job_registry.md | 28 ++++++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 2 deletions(-) diff --git a/contracts/job_registry/src/lib.rs b/contracts/job_registry/src/lib.rs index ebade485..e2e51717 100644 --- a/contracts/job_registry/src/lib.rs +++ b/contracts/job_registry/src/lib.rs @@ -1,8 +1,8 @@ #![no_std] use soroban_sdk::{ - contract, contracterror, contractimpl, contracttype, panic_with_error, symbol_short, Address, - Bytes, Env, Vec, + contract, contracterror, contractimpl, contracttype, log, panic_with_error, symbol_short, + Address, Bytes, Env, Vec, }; const MAX_HASH_LEN: u32 = 96; @@ -80,6 +80,7 @@ impl JobRegistryContract { env.storage().instance().set(&DataKey::Admin, &admin); env.storage().instance().set(&DataKey::NextJobId, &1u64); + log!(&env, "JobRegistry initialized with admin: {}", admin); env.events().publish((symbol_short!("init"),), admin); } @@ -114,6 +115,7 @@ impl JobRegistryContract { env.storage().instance().set(&DataKey::NextJobId, &updated); } + log!(&env, "post_job: id {} client {} budget {}", job_id, client, budget); env.events() .publish((symbol_short!("jobpost"), job_id), (client, budget)); } @@ -133,6 +135,7 @@ impl JobRegistryContract { .unwrap_or_else(|| panic_with_error!(&env, JobRegistryError::Overflow)); env.storage().instance().set(&DataKey::NextJobId, &next); + log!(&env, "post_job_auto: id {} client {} budget {}", job_id, client, budget); env.events() .publish((symbol_short!("jobauto"), job_id), (client, budget)); @@ -175,6 +178,7 @@ impl JobRegistryContract { }); env.storage().persistent().set(&bids_key, &bids); + log!(&env, "submit_bid: id {} freelancer {}", job_id, freelancer); env.events() .publish((symbol_short!("bid"), job_id), freelancer); } @@ -219,6 +223,7 @@ impl JobRegistryContract { job.status = JobStatus::InProgress; env.storage().persistent().set(&key, &job); + log!(&env, "accept_bid: id {} client {} freelancer {}", job_id, client, freelancer); env.events() .publish((symbol_short!("accept"), job_id), freelancer); } @@ -249,6 +254,7 @@ impl JobRegistryContract { .persistent() .set(&DataKey::Deliverable(job_id), &hash); + log!(&env, "submit_deliverable: id {} freelancer {}", job_id, freelancer); env.events() .publish((symbol_short!("deliver"), job_id), freelancer); } @@ -273,6 +279,7 @@ impl JobRegistryContract { job.status = JobStatus::Disputed; env.storage().persistent().set(&key, &job); + log!(&env, "mark_disputed: id {}", job_id); env.events().publish((symbol_short!("dispute"), job_id), ()); } diff --git a/docs/contracts/job_registry.md b/docs/contracts/job_registry.md index 70ec4c0e..72d3c409 100644 --- a/docs/contracts/job_registry.md +++ b/docs/contracts/job_registry.md @@ -4,6 +4,34 @@ The `JobRegistry` contract manages job postings, bid submissions, bid acceptance, deliverable submission, and dispute status updates for the Lance protocol. +## `post_job` and `post_job_auto` + +### Purpose + +These functions allow a client to post a new job to the Lance protocol, making it available for freelancers to bid on. `post_job` allows the client to explicitly define the job ID, while `post_job_auto` automatically assigns the next available sequential ID. + +### Behavior + +- Authenticates the caller with `client.require_auth()`. +- Validates inputs: checks for invalid (zero) budget, validates the deliverable IPFS hash size, and checks for zero job ID. +- Stores the job data (`client`, `metadata_hash`, `budget_stroops`, `status = Open`) in persistent storage. +- Automatically increments the internal `NextJobId` counter. +- Emits a `jobpost` (or `jobauto`) event for on-chain tracking and off-chain indexing. + +### Errors + +These functions use `JobRegistryError` to return structured error information: + +- `InvalidJobId` (3): job ID cannot be zero. +- `InvalidBudget` (4): budget must be greater than zero. +- `InvalidHash` (5): metadata hash must not be empty or exceed maximum length. +- `JobAlreadyExists` (6): the explicitly requested job ID is already taken. +- `Overflow` (14): the next job ID counter overflowed. + +### Security + +These functions perform strict validation on inputs to prevent issues like overflow and garbage data (e.g. invalid IPFS hashes). All inputs are bounded, ensuring minimal on-chain footprint and deterministic behavior. + ## `accept_bid` ### Purpose From cac706ab2256c86022b08160ca0beb82b096885d Mon Sep 17 00:00:00 2001 From: Obiajulu-gif Date: Thu, 23 Apr 2026 15:36:37 -0700 Subject: [PATCH 2/2] style(contracts): apply cargo fmt fixes to JobRegistry logs --- contracts/job_registry/src/lib.rs | 31 +++++++++++++++++++++++++++---- 1 file changed, 27 insertions(+), 4 deletions(-) diff --git a/contracts/job_registry/src/lib.rs b/contracts/job_registry/src/lib.rs index e2e51717..7b0e1f36 100644 --- a/contracts/job_registry/src/lib.rs +++ b/contracts/job_registry/src/lib.rs @@ -115,7 +115,13 @@ impl JobRegistryContract { env.storage().instance().set(&DataKey::NextJobId, &updated); } - log!(&env, "post_job: id {} client {} budget {}", job_id, client, budget); + log!( + &env, + "post_job: id {} client {} budget {}", + job_id, + client, + budget + ); env.events() .publish((symbol_short!("jobpost"), job_id), (client, budget)); } @@ -135,7 +141,13 @@ impl JobRegistryContract { .unwrap_or_else(|| panic_with_error!(&env, JobRegistryError::Overflow)); env.storage().instance().set(&DataKey::NextJobId, &next); - log!(&env, "post_job_auto: id {} client {} budget {}", job_id, client, budget); + log!( + &env, + "post_job_auto: id {} client {} budget {}", + job_id, + client, + budget + ); env.events() .publish((symbol_short!("jobauto"), job_id), (client, budget)); @@ -223,7 +235,13 @@ impl JobRegistryContract { job.status = JobStatus::InProgress; env.storage().persistent().set(&key, &job); - log!(&env, "accept_bid: id {} client {} freelancer {}", job_id, client, freelancer); + log!( + &env, + "accept_bid: id {} client {} freelancer {}", + job_id, + client, + freelancer + ); env.events() .publish((symbol_short!("accept"), job_id), freelancer); } @@ -254,7 +272,12 @@ impl JobRegistryContract { .persistent() .set(&DataKey::Deliverable(job_id), &hash); - log!(&env, "submit_deliverable: id {} freelancer {}", job_id, freelancer); + log!( + &env, + "submit_deliverable: id {} freelancer {}", + job_id, + freelancer + ); env.events() .publish((symbol_short!("deliver"), job_id), freelancer); }