diff --git a/contracts/job_registry/src/lib.rs b/contracts/job_registry/src/lib.rs index ebade485..7b0e1f36 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,13 @@ 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 +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 + ); env.events() .publish((symbol_short!("jobauto"), job_id), (client, budget)); @@ -175,6 +190,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 +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 + ); env.events() .publish((symbol_short!("accept"), job_id), freelancer); } @@ -249,6 +272,12 @@ 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 +302,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