Summary
file_dispute performs two token transfers (filing fee and claim amount) before the Dispute record is created and stored:
// ❌ Both interactions before any Effect
token_client.transfer(&claimant, &env.current_contract_address(), &fee);
token_client.transfer(&claimant, &env.current_contract_address(), &claim_amount);
// Dispute record created much later
env.storage().persistent().set(&_ttl_key, &dispute);
If any operation between the second transfer and the set panics, funds are locked in the contract with no dispute record. A re-entrant callback from either transfer finds no dispute state to inspect.
Fix
Create and persist the dispute record before any token transfers:
// 1. Build dispute struct
// 2. env.storage().persistent().set(&_ttl_key, &dispute);
// 3. env.storage().instance().set(&DataKey::DisputeCounter, &dispute_id);
// 4. THEN: token_client.transfer for fee
// 5. THEN: token_client.transfer for claim_amount
Summary
file_disputeperforms two token transfers (filing fee and claim amount) before theDisputerecord is created and stored:If any operation between the second transfer and the
setpanics, funds are locked in the contract with no dispute record. A re-entrant callback from either transfer finds no dispute state to inspect.Fix
Create and persist the dispute record before any token transfers: