This document describes the three new features implemented in the ChainSettle smart contract.
Allows the buyer and supplier to jointly agree to replace the arbiter on an active shipment. This handles situations where the original arbiter becomes unavailable or has a conflict of interest.
New Storage Key:
ArbiterRotation(String) // Stores pending rotation proposalNew Struct:
pub struct ArbiterRotationProposal {
pub new_arbiter: Address,
pub buyer_agreed: bool,
pub supplier_agreed: bool,
}propose_arbiter_rotation(caller, shipment_id, new_arbiter)
- Caller: Any buyer or the supplier
- Behavior:
- Validates the shipment is active
- Validates caller is a buyer or supplier
- Creates or updates a rotation proposal in temporary storage
- When both buyer and supplier agree on the same
new_arbiter, the rotation is applied immediately - Emits
arbiter_rotation_proposedevent when proposal is made - Emits
arbiter_rotatedevent when rotation is finalized
- Mutual Consent: Both parties must explicitly agree on the same new arbiter
- Atomic Application: Rotation happens immediately when consensus is reached
- Temporary Storage: Proposals are stored temporarily and cleared once applied
- No Disputes Required: Can be done at any time during active shipment
- Buyer calls
propose_arbiter_rotation(shipment_id, new_arbiter_address) - Supplier calls
propose_arbiter_rotation(shipment_id, new_arbiter_address)with same address - Arbiter is automatically rotated; both parties notified via events
Allows buyers to configure a penalty that is automatically deducted from supplier payment when proof arrives late. The penalty is calculated per ledger of delay and returned to the buyer.
New Shipment Fields:
pub late_penalty_bps_per_ledger: u32, // Basis points penalty per ledger of delayNew ShipmentOptions Field:
pub late_penalty_bps_per_ledger: u32, // Set during shipment creationNew Milestone Field:
pub proof_submitted_ledger: Option<u32>, // Ledger when proof was submittedWhen a milestone is confirmed:
delay_ledgers = current_ledger - proof_submitted_ledger
penalty = (payment * late_penalty_bps_per_ledger * delay_ledgers) / 10_000
net_payment = payment - penalty
During confirm_milestone:
- Calculates delay from
proof_submitted_ledgerto current ledger - Deducts penalty from supplier payment
- Returns penalty to primary buyer
- Penalty is only applied if
late_penalty_bps_per_ledger > 0
During claim_auto_confirmation:
- Same penalty calculation applies
- Ensures consistent penalty treatment
- Per-Ledger Calculation: Penalty scales with delay duration
- Automatic Deduction: No manual intervention required
- Buyer Refund: Penalty is returned to primary buyer
- Holdback Compatible: Works with payment holdback periods
- Zero Default: Set to 0 to disable (backward compatible)
- Shipment total: 1,000 tokens
- Milestone payment: 25% = 250 tokens
- Late penalty: 100 bps per ledger (1% per ledger)
- Delay: 5 ledgers
- Penalty: (250 _ 100 _ 5) / 10,000 = 12.5 tokens
- Supplier receives: 237.5 tokens
- Buyer receives: 12.5 tokens (refund)
Automatically confirms milestones after a configurable inactivity timeout. This protects suppliers from buyer ghost-abandonment by ensuring payment is released even if the buyer never acts.
New Shipment Fields:
pub auto_confirm_ledgers: u32, // Ledgers after proof submission before auto-confirmationNew ShipmentOptions Field:
pub auto_confirm_ledgers: u32, // Set during shipment creationNew Milestone Field:
pub proof_submitted_ledger: Option<u32>, // Ledger when proof was submittedAuto-Confirmation Window:
auto_confirm_ledger = proof_submitted_ledger + auto_confirm_ledgers
When current_ledger >= auto_confirm_ledger:
- Milestone is considered auto-confirmed
- Manual confirmation is blocked
- Disputes are blocked
claim_auto_confirmationcan be called
During confirm_milestone:
- Checks if auto-confirmation window has passed
- If passed, rejects with error directing to
claim_auto_confirmation - If not passed, proceeds with normal confirmation
During raise_dispute:
- Checks if auto-confirmation window has passed
- If passed, rejects dispute (window closed)
- If not passed, allows dispute
claim_auto_confirmation(shipment_id, milestone_index)
- Caller: Anyone (permissionless)
- Behavior:
- Validates milestone is in
ProofSubmittedstatus - Validates auto-confirmation window has expired
- Applies late-delivery penalty if configured
- Transfers net payment to supplier
- Returns penalty to buyer if applicable
- Marks milestone as
Confirmed - Completes shipment if all milestones done
- Emits
auto_confirmation_claimedevent
- Validates milestone is in
- Permissionless: Anyone can trigger auto-confirmation
- Supplier Protection: Ensures payment release after timeout
- Penalty Integration: Late penalties still apply
- Holdback Compatible: Works with payment holdback periods
- Zero Default: Set to 0 to disable (backward compatible)
- Dispute Window: Disputes must be raised before auto-confirmation
- Supplier submits proof at ledger 1000
- Shipment configured with
auto_confirm_ledgers = 100 - Auto-confirmation available at ledger 1100
- If buyer hasn't confirmed by ledger 1100, anyone can call
claim_auto_confirmation - Payment is released to supplier automatically
- All new fields default to 0 (disabled)
- Existing shipments continue to work unchanged
- No migration required
All three features work together seamlessly:
// Example: Shipment with all features enabled
ShipmentOptions {
response_deadline: 1000,
penalty_bps: 500,
milestone_mode: MilestoneMode::Parallel,
holdback_ledgers: 50,
dispute_cooldown_ledgers: 100,
late_penalty_bps_per_ledger: 100, // 1% per ledger
auto_confirm_ledgers: 200, // 200 ledgers timeout
}Arbiter Rotation:
arbiter_rotation_proposed(shipment_id, new_arbiter)arbiter_rotated(shipment_id, new_arbiter)
Late-Delivery Penalty:
- Included in
milestone_confirmedevent:(milestone_index, payment, fee_amount, penalty_deducted) - Included in
auto_confirmation_claimedevent:(milestone_index, payment, fee_amount, penalty_deducted)
Auto-Confirmation:
auto_confirmation_claimed(shipment_id, (milestone_index, payment, fee_amount, penalty_deducted))
All existing tests pass with the new features. The test suite validates:
- Milestone creation with new fields
- ShipmentOptions with new parameters
- Backward compatibility (zero defaults)
- Integration with existing features
Run tests with:
cargo test --libAll 53 tests pass successfully.
- Arbiter Rotation: Requires mutual consent; no unilateral changes possible
- Late Penalties: Calculated deterministically; no rounding errors
- Auto-Confirmation: Permissionless but time-locked; cannot be triggered early
- Penalty Refunds: Returned to primary buyer; no loss of funds
- Dispute Window: Enforced before auto-confirmation; disputes take precedence
Potential improvements for future versions:
- Configurable penalty recipient (not just primary buyer)
- Milestone-specific auto-confirmation windows
- Penalty caps (maximum deduction)
- Arbiter rotation with cooldown period
- Penalty escalation (increasing over time)