Chain · Base 8453Token · USDC 0x8335…2913Contract · MoltEscrowV2Snapshot fee · 500 bps

When the worker is a machine, the interesting question is not whether a “smart contract holds the money safely.” It is which address can call which function, what state bits flip, and which funds move on which event. The notes below are pinned to the verified MoltEscrowV2 source on Base, read-only eth_call observations captured on September 9, 2026 at 20:46 UTC, and one funded deposit transaction for a 1.5 USDC job.

This page is a laboratory explainer. It is not a wallet, not a payout tool, and not a substitute for reading the job record or the contract. Neomorphic does not operate MoltJobs escrow.

§ 01Custody

Who holds the funds.

Funds sit in the escrow contract itself after deposit. The immutable USDC token is Base native USDC at 0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913. The escrow implementation is MoltEscrowV2 at 0x3a57faee4EE95444506a6E290261D4C37b3060Be (Sourcify exact match, verified 2026-08-02). At that observation, platformFeeBps() returned 500 (5%). MAX_PLATFORM_FEE_BPS is 1000. BPS_DIVISOR is 10000. DISPUTE_WINDOW is 7 days (604800 seconds) as a public constant — and is not referenced by any function body in the verified source.

RoleAddress / controlWhat it can do on-chain
Escrow contract0x3a57…060BeHolds net USDC per jobId; accumulates platformFees.
Poster (depositor)msg.sender of depositCreates the escrow row; alone may call dispute(jobId).
Owner / backend relayerOwnable.owner() — snapshot read 0xc66c…aeb7dassignAgent, release, refund, resolveDispute, withdrawFees, fee updates.
Agent walletSet later by assignAgentReceives USDC only when release or a dispute split pays job.agent. No machine-side withdraw from escrow.

API surface that mirrors the same economics: poster PATCH /jobs/:id/approve is documented as releasing escrow; POST /jobs/:id/release-escrow is a manual release; cancel/dispute paths are documented on the public REST reference. Those HTTP verbs are not the on-chain selectors — the owner key must still call release / refund / resolveDispute.

§ 02Selectors

What event triggers each move.

01

deposit(bytes32 jobId, uint256 amount)

Anyone who can transferFrom USDC. Pulls gross amount, stores net amount - fee, bumps platformFees by the fee, emits Deposited(jobId, poster, netAmount, platformFee). Rejects duplicate jobId.

02

assignAgent(bytes32 jobId, address agent)

onlyOwner. Sets job.agent and agentAssigned. Required before release or poster dispute.

03

release(bytes32 jobId)

onlyOwner. Requires assigned, not released/refunded/disputed. Transfers job.amount (net) to the agent. Platform fee stays in platformFees until withdrawFees.

04

refund(bytes32 jobId)

onlyOwner. Returns job.amount + job.platformFee to the poster and decrements platformFees. Allowed even if a dispute flag was never set; blocked after release.

05

dispute(bytes32 jobId) / resolveDispute(jobId, posterBps, agentBps)

Poster opens dispute after assignment. Owner resolves with a 10000-bps split of the net amount; dust remainder accrues to platformFees. DISPUTE_WINDOW is not enforced in these bodies.

Marketplace copy states a flat 5% fee with 95% to the agent on approval, settlement in USDC on Base, and that disputes or no-approval follow timeout/resolution rules surfaced on the job record. The contract is the sharper instrument: fee is computed at deposit time; agent never pulls; owner is the release/refund choke point.

§ 03Worked example

One real 1.5 USDC deposit.

Job public record 5d7388ca-a5b1-4e48-b4eb-0cd25891472d (budget 1.5 USDC, paymentProvider: ON_CHAIN_USDC, chainId 8453) cites escrow tx 0x734c792c2c3d1a69a6965cb7fb1023d699f5d980a85fdd99e5dc1ec2d2a34483.

ObservationValue
Calldata selector0x1de26e16 = deposit(bytes32,uint256)
jobId (bytes32)0x03a2f87d51db84c3a80d4e9a721400607380b57bb2f39b0fc13338ec97036b02
Gross amount1 500 000 base units = 1.5 USDC
USDC Transfer1.5 USDC from poster 0xc66c…aeb7d → escrow
Deposited eventnet 1.425 USDC · fee 0.075 USDC (5%)
Block51034005 · depositTime 1788857357 (2026-09-08 08:49:17 UTC)
Captured escrows(jobId)agent zero · agentAssigned false · released/refunded/disputed false · amount 1.425 · fee 0.075

Status at the captured observation: Snapshot: funded, unassigned — the deposit receipt and captured escrow row showed funds inside the contract while the marketplace job showed OPEN with agentId: null. That gap is normal for bid-budget listings; it is also how capital sits idle.

§ 04Failure modes

Six ways machine escrow goes wrong.

1. Stranded escrow

Deposit succeeds; no agent is ever assigned; owner never refunds. Net USDC and the recorded fee remain in contract storage. The example was funded and unassigned at capture, but that alone does not prove abandonment or permanent stranding. It illustrates an intermediate state that becomes problematic only if the responsible owner never assigns or refunds it.

2. Owner-key dependency / stale signer

release, refund, assignAgent, and resolveDispute are onlyOwner. If the relayer key is lost, rotated without ownership transfer, or nonce-stuck, marketplace “approve” HTTP success can diverge from on-chain settlement until a new owner can act.

3. Unused DISPUTE_WINDOW

The constant is 7 days and readable on-chain, but dispute / resolveDispute do not check it. Operators or agents who assume an automatic time gate from the constant name will mis-model risk.

4. RPC lying about receipts

A client that trusts a single RPC’s eth_getTransactionReceipt without cross-checking block hash / confirmatory peers can accept a forged or reorged receipt. Prefer comparing receipt logs (USDC Transfer + Deposited) against an independent Base endpoint before treating escrow as funded.

5. Chain reorg of the deposit

A shallow confirmation can unwind deposit. Marketplace job rows that mark funded: true from a single receipt can temporarily disagree with canonical chain state after a reorg.

6. Proof-hold / abandonment off-chain

Custom jobs carry proofHoldHours (720 on the sampled listings) and API cancel/dispute paths. Those timers belong to off-chain product logic; this source review does not prove how or whether the service enforces them. The contract will not auto-refund when a human abandons review; someone must still call refund or resolve a dispute.

§ 05Sources

Primary endpoints used for this note.

Contract-state snapshot: 2026-09-09T20:46:15Z. The example is historical, not a continuously updated status display. Re-read the current job and chain state before relying on a row.