Problem Statement / Feature Objective
The settlement contract converts resource token balances to the settlement currency using the current oracle exchange rate at the time of finalize_settlement(). Because the conversion happens as a single atomic swap without any slippage tolerance check, even a 1-basis-point adverse price movement between oracle read and execution causes the user to receive fewer settlement tokens than expected. In volatile market conditions, the deviation can exceed 5%, causing significant value loss for users. The contract needs a user-defined min_expected_amount parameter and a protocol-enforced MAX_SLIPPAGE_BPS (basis points) bound that rejects settlement if the converted amount deviates beyond tolerance.
Technical Invariants & Bounds
Slippage is computed as: slippage_bps = (expected_amount - actual_amount) * 10000 / expected_amount, where both amounts are i128 fixed-point with 7 decimal places. MAX_SLIPPAGE_BPS must be a protocol constant in range [1, 500] (0.01% to 5%). User can optionally set a tighter min_expected_amount parameter. The oracle rate R is an i128 with 7 decimals. The settlement amount S = volume * R / 1e7 where volume is also i128. The conversion must use checked_mul and checked_div to prevent overflow. The max settlement volume per call is MAX_VOLUME = 1_000_000 * 1e7 (1M tokens). Max conversion amount is MAX_VOLUME * MAX_RATE / 1e7 where MAX_RATE = 1_000_000 * 1e7. The product MAX_VOLUME * MAX_RATE = 1e12 * 1e7 = 1e19 which fits in i128 (~1.7e38). The total operation cost increase is ~15,000 instructions (two additional multiplications, one comparison).
Codebase Navigation Guide
Settlement conversion logic: contracts/settlement/src/lib.rs — finalize_settlement() around line 142 calls convert_to_settlement_currency() at line 178 in contracts/settlement/src/conversion.rs. Oracle rate fetching: contracts/settlement/src/rate_application.rs — get_rate() at line 42. The settlement function signature is in contracts/settlement/src/interface.rs or directly annotated with #[contractimpl]. User-facing parameter structures are in contracts/settlement/src/types.rs. The SettlementArgs struct likely contains token_address, volume, recipient. Current test cases in contracts/settlement/src/test.rs do not test slippage scenarios.
Implementation Blueprint
Step 1: Add min_expected_amount: Option<i128> to the SettlementArgs struct in contracts/settlement/src/types.rs. Step 2: Add MAX_SLIPPAGE_BPS: u32 = 100 (1%) to contracts/settlement/src/constants.rs. Step 3: In conversion.rs, before executing conversion, compute expected_amount = volume * oracle_rate / 1e7. After conversion, compute actual_amount. Reject if (expected_amount - actual_amount) * 10000 / expected_amount > MAX_SLIPPAGE_BPS OR if actual_amount < min_expected_amount (if user provided). Step 4: Emit a SlippageProtectionTriggered event when rejection occurs. Step 5: Update function signature to return Result<SettlementResult, SettlementError> where SettlementError includes SlippageExceeded variant. Step 6: Add 4 test cases: (a) zero slippage succeeds, (b) slippage within tolerance succeeds, (c) slippage exceeds tolerance fails, (d) user min_expected_amount higher than actual fails. Step 7: Run cargo test --package settlement.
Problem Statement / Feature Objective
The settlement contract converts resource token balances to the settlement currency using the current oracle exchange rate at the time of
finalize_settlement(). Because the conversion happens as a single atomic swap without any slippage tolerance check, even a 1-basis-point adverse price movement between oracle read and execution causes the user to receive fewer settlement tokens than expected. In volatile market conditions, the deviation can exceed 5%, causing significant value loss for users. The contract needs a user-definedmin_expected_amountparameter and a protocol-enforcedMAX_SLIPPAGE_BPS(basis points) bound that rejects settlement if the converted amount deviates beyond tolerance.Technical Invariants & Bounds
Slippage is computed as:
slippage_bps = (expected_amount - actual_amount) * 10000 / expected_amount, where both amounts are i128 fixed-point with 7 decimal places.MAX_SLIPPAGE_BPSmust be a protocol constant in range[1, 500](0.01% to 5%). User can optionally set a tightermin_expected_amountparameter. The oracle rateRis an i128 with 7 decimals. The settlement amountS = volume * R / 1e7where volume is also i128. The conversion must usechecked_mulandchecked_divto prevent overflow. The max settlement volume per call isMAX_VOLUME = 1_000_000 * 1e7(1M tokens). Max conversion amount isMAX_VOLUME * MAX_RATE / 1e7whereMAX_RATE = 1_000_000 * 1e7. The productMAX_VOLUME * MAX_RATE = 1e12 * 1e7 = 1e19which fits in i128 (~1.7e38). The total operation cost increase is ~15,000 instructions (two additional multiplications, one comparison).Codebase Navigation Guide
Settlement conversion logic:
contracts/settlement/src/lib.rs—finalize_settlement()around line 142 callsconvert_to_settlement_currency()at line 178 incontracts/settlement/src/conversion.rs. Oracle rate fetching:contracts/settlement/src/rate_application.rs—get_rate()at line 42. The settlement function signature is incontracts/settlement/src/interface.rsor directly annotated with#[contractimpl]. User-facing parameter structures are incontracts/settlement/src/types.rs. TheSettlementArgsstruct likely containstoken_address,volume,recipient. Current test cases incontracts/settlement/src/test.rsdo not test slippage scenarios.Implementation Blueprint
Step 1: Add
min_expected_amount: Option<i128>to theSettlementArgsstruct incontracts/settlement/src/types.rs. Step 2: AddMAX_SLIPPAGE_BPS: u32 = 100(1%) tocontracts/settlement/src/constants.rs. Step 3: Inconversion.rs, before executing conversion, computeexpected_amount = volume * oracle_rate / 1e7. After conversion, computeactual_amount. Reject if(expected_amount - actual_amount) * 10000 / expected_amount > MAX_SLIPPAGE_BPSOR ifactual_amount < min_expected_amount(if user provided). Step 4: Emit aSlippageProtectionTriggeredevent when rejection occurs. Step 5: Update function signature to returnResult<SettlementResult, SettlementError>whereSettlementErrorincludesSlippageExceededvariant. Step 6: Add 4 test cases: (a) zero slippage succeeds, (b) slippage within tolerance succeeds, (c) slippage exceeds tolerance fails, (d) usermin_expected_amounthigher than actual fails. Step 7: Runcargo test --package settlement.