feat: inputSettlerBond#164
Conversation
|
Note
|
| Cohort / File(s) | Summary |
|---|---|
Input Settlement Bond Contract src/input/bond/InputSettlerBond.sol |
New comprehensive contract implementing dual-mode input settlement: bonded flow (direct transfer to solver with solver signature), escrow flow (deposit via multiple authorization methods), with claim, refund, and finalize operations; includes order status tracking, solver authorization via EIP-712, time-based validation (TIME_TO_FILL), and bond interaction via SolverBondVault. |
Solver Bond Vault Contract src/input/bond/SolverBondVault.sol |
New contract managing per-solver, per-token bond accounting with BondState struct tracking available and locked amounts; implements deposit, withdrawal, locking/unlocking, penalization/slashing flows; supports multiple input transfer mechanisms (direct, Permit2, ERC-3009) via internal helper functions; validates tokens and amounts. |
Input Settler Bond Interface src/interfaces/IInputSettlerBond.sol |
New interface defining eight external function signatures: overloaded open/openFor variants, claim, finalise, refund, and orderIdentifier view function; establishes contract API for input settlement operations. |
Sequence Diagrams
sequenceDiagram
autonumber
actor User
participant ISB as InputSettlerBond
participant SBV as SolverBondVault
participant Token as ERC20 Token
actor Solver
rect rgb(200, 220, 255)
note over User,Token: Bonded Settlement Flow
User->>ISB: open(order, solver, solverSignature)
ISB->>ISB: Validate solver signature (EIP-712)
ISB->>SBV: Check solver bonds available
ISB->>Token: Transfer inputs to solver
ISB->>SBV: Lock solver bonds
ISB->>ISB: Record OrderStatus.Open, solver, timestamp
ISB-->>User: Emit Open event
ISB-->>Solver: Emit Claimed event (implicit)
end
rect rgb(220, 255, 220)
note over User,Token: Finalization Path (On-time)
Solver->>ISB: finalise(order, solveParams)
ISB->>ISB: Validate order status & timing
ISB->>SBV: Unlock solver bonds
ISB->>ISB: Update OrderStatus.Finalised
ISB-->>Solver: Emit Finalised event
end
rect rgb(255, 220, 220)
note over User,Token: Refund Path (Late/Default)
User->>ISB: refund(order)
ISB->>ISB: Validate order status
alt Order in Open state
ISB->>Token: Return inputs to user
else Order in Claimed state
ISB->>SBV: Slash solver bonds (basis points)
ISB->>Token: Transfer slashed amount to user
end
ISB->>ISB: Update OrderStatus.Refunded
ISB-->>User: Emit Refunded event
end
sequenceDiagram
autonumber
actor User
participant ISB as InputSettlerBond
participant SBV as SolverBondVault
participant Token as ERC20 Token
actor Sponsor
actor Solver
rect rgb(200, 220, 255)
note over User,Solver: Escrow Settlement Flow
User->>ISB: openFor(order, sponsor, signature) <br/> [or open(order)]
ISB->>ISB: Validate sponsor signature (if applicable)
ISB->>Token: Transfer inputs into contract escrow
ISB->>ISB: Record OrderStatus.Open, no solver yet
ISB-->>User: Emit Open event
end
rect rgb(220, 255, 220)
note over User,Solver: Solver Assignment (Optional variant)
Sponsor->>ISB: openFor(order, sponsor, sig, solver, solverSig)
ISB->>ISB: Validate both signatures
ISB->>ISB: Store solver & timestamp
ISB-->>Sponsor: Update orderSolver mapping
end
rect rgb(255, 240, 200)
note over User,Solver: Claim Phase
Sponsor->>ISB: claim(order)
ISB->>ISB: Validate order Open status
ISB->>Token: Transfer escrowed inputs to claimer
ISB->>ISB: Update OrderStatus.Claimed, record solver/timestamp
ISB-->>Sponsor: Emit Claimed event
end
rect rgb(255, 220, 220)
note over User,Solver: Post-Claim Outcomes
alt On-time finalization
Solver->>ISB: finalise(order, solveParams)
ISB->>ISB: Validate timing & status
ISB->>ISB: Update OrderStatus.Finalised
ISB-->>Solver: Emit Finalised event
else Late/refund request
User->>ISB: refund(order)
ISB->>ISB: Validate OrderStatus.Claimed
ISB->>SBV: Slash solver bonds (if solver assigned)
ISB->>Token: Transfer penalty or return to user
ISB->>ISB: Update OrderStatus.Refunded
ISB-->>User: Emit Refunded event
end
end
Estimated code review effort
🎯 4 (Complex) | ⏱️ ~60 minutes
Poem
🐰 With bonds of trust and vaults so deep,
We settle orders, promises to keep,
Through escrow paths and solver's care,
With EIP-712 signatures to spare—
No reentrancy shall pass this year! 🔐
Pre-merge checks and finishing touches
✅ Passed checks (3 passed)
| Check name | Status | Explanation |
|---|---|---|
| Title check | ✅ Passed | The title 'feat: inputSettlerBond' is clear and specific, directly referencing the main component added in this PR. |
| Docstring Coverage | ✅ Passed | No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check. |
| Description check | ✅ Passed | PR description includes a clear overview of the inputSettlerBond contract, relates to issue #51, and completes the third-party integration checklist with all items marked. |
✨ Finishing touches
- 📝 Generate docstrings
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.
Comment @coderabbitai help to get the list of available commands and usage tips.
There was a problem hiding this comment.
Actionable comments posted: 1
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
src/input/bond/InputSettlerBond.sol (1)
545-563: Potential issue:_transferInputsusessafeTransferFromeven for self-transfers.Unlike
_lockBondsAndTransfer(lines 234-236) which handles thesender == address(this)case withsafeTransfer,_transferInputsalways usessafeTransferFrom. When called withsender = address(this)(as in escrow refunds at line 470), this may fail for tokens that don't allow self-transfers without approval.🔎 Proposed fix
function _transferInputs( address sender, address to, uint256[2][] calldata inputs ) internal { uint256 inputsLength = inputs.length; for (uint256 i = 0; i < inputsLength; ++i) { uint256[2] calldata input = inputs[i]; address token = input[0].validatedCleanAddress(); uint256 amount = input[1]; _validateZeroAmount(amount); _validateToken(token); - IERC20(token).safeTransferFrom(sender, to, amount); + if (sender == address(this)) + IERC20(token).safeTransfer(to, amount); + else IERC20(token).safeTransferFrom(sender, to, amount); } }
🧹 Nitpick comments (3)
src/input/bond/SolverBondVault.sol (1)
338-345: Consider handlingreceiveWithAuthorizationreturn value explicitly.The low-level
callis used to attempt ERC-3009 authorization, with a silent fallback to the multi-signature path on failure. While this works, consider logging or differentiating the failure reason to aid debugging. The current behavior is functional but could mask unexpected token contract issues.src/input/bond/InputSettlerBond.sol (2)
372-396: Consider adding fillDeadline validation in claim.The
claimfunction doesn't validate thatorder.fillDeadlinehasn't passed. While this may be intentional (allowing late claims before expiry), a solver claiming afterfillDeadlinewill likely face slashing during finalization. Consider whether early rejection would improve UX.
495-495: Minor: Consider documenting TIME_TO_FILL bounds.While overflow at
os.timestamp + TIME_TO_FILLis practically impossible with realistic timestamps, documenting expected bounds forTIME_TO_FILL(e.g., "expected to be hours or days, not years") would clarify the design intent.
📜 Review details
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
src/input/bond/InputSettlerBond.solsrc/input/bond/SolverBondVault.solsrc/interfaces/IInputSettlerBond.sol
🔇 Additional comments (16)
src/input/bond/SolverBondVault.sol (8)
126-130: LGTM!Constructor validation is correct - ensures
slashBasisPointscannot exceed 100% (10,000 BPS).
139-154: LGTM!Good use of balance-before/after pattern to properly handle fee-on-transfer tokens. The validation and accounting are correct.
161-173: LGTM!Proper checks-effects-interactions pattern with correct balance validation.
426-464: LGTM!The unlock-then-slash logic correctly adds the locked amount back to available balance before calculating the slash. The use of
Math.minensures the slash cannot exceed available funds, preventing underflow.
472-498: LGTM!Full penalization correctly transfers locked bonds directly to the recipient, bypassing the available balance. The accounting properly decrements only
lockedAmount.
506-543: LGTM!The penalize-and-slash logic correctly separates the full lock penalty from the additional slash on available balance. The combined transfer is efficient.
626-678: LGTM!Clean separation of transfer-only logic from the lock-and-transfer variant. The fallback pattern is consistent with the locking version.
687-692: LGTM!Correct use of
Math.mulDivwith default floor rounding, appropriate for penalty calculations.src/interfaces/IInputSettlerBond.sol (1)
10-45: LGTM!Interface correctly declares all public entry points matching the implementation. The overloads for
openandopenForproperly distinguish bonded vs escrow modes.src/input/bond/InputSettlerBond.sol (7)
119-127: LGTM!Constructor properly initializes EIP712 domain and SolverBondVault. The immutable
TIME_TO_FILLis set correctly.
170-203: LGTM!Proper state machine with effective reentrancy protection via the status check pattern. The order of operations (set status → external call → verify status) is correct.
205-225: LGTM!Escrow mode correctly deposits tokens to the contract and uses the same reentrancy protection pattern.
242-305: LGTM!Clean multi-path authorization handling with proper validation. The signature type dispatch correctly routes to appropriate transfer methods.
405-424: LGTM!Proper delegation to validation and finalization logic. The status check ensures only claimed orders can be finalized.
432-458: LGTM!Refund correctly differentiates between claimed (penalize solver) and deposited (return escrow) states. The expiry check ensures premature refunds are blocked.
530-548: LGTM!EIP712-compliant solver consent verification using
SignatureCheckerfor smart contract wallet compatibility. The minimal typehash is sufficient since EIP712 domain provides contract-specific binding.
Description
This PR aims to implement a new inputSettler contract. Unlike the Escrow model, the solver initiates the claim process by depositing a certain amount of bond after filling. If no one disputes, the order becomes final. A claim can be disputed by depositing a bond into the contract. In this case, the order is completed with the oracle result.
Related Issues
#51
Third-Party Integration Checklist
foundry.tomlsrc/oracles/[oracle-type]/external/[protocol-name]/Additional Notes
The overall structure is still in the conceptual stage. It would be great to discuss the contract's flows. Currently, there is a fixed waiting period called DISPUTE_WAITING_TIME, but this may not be enough for all oracles or it may be too long. That's why it needs to be a different structure.