Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions intent_settlement/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,17 @@ const PROTOCOL_FEE_BPS: i128 = 5; // 0.05%
/// closes.
const BID_WINDOW: u64 = 120; // 2 minutes

// Upper sanity bound for src_amount and min_dst_amount.
//
// Largest realistic token amounts use 18-decimal ETH units.
// 1e12 tokens × 1e18 units/token = 1e30, well within i128 range (~1.7e38),
// but downstream arithmetic (fee = amount * 5 / 10_000) multiplies first and
// then divides. To guarantee `amount * PROTOCOL_FEE_BPS` never overflows i128,
// the bound is i128::MAX / PROTOCOL_FEE_BPS ≈ 3.4e37. We choose a round,
// economically implausible threshold: 10^30 (one trillion 18-decimal tokens).
// That is a comfortable safety margin while rejecting only fat-fingered inputs.
pub const MAX_AMOUNT: i128 = 1_000_000_000_000_000_000_000_000_000_000i128; // 10^30

// Soroban archives ledger entries that go too long without being touched.
// Persistent Intent/Solver records get their TTL bumped on every write so
// they don't need to be manually restored before later calls can read them.
Expand Down Expand Up @@ -784,6 +795,10 @@ impl IntentSettlement {
panic_with_error!(&env, Error::ZeroAmount);
}

if src_amount > MAX_AMOUNT || min_dst_amount > MAX_AMOUNT {
panic_with_error!(&env, Error::AmountTooLarge);
}

if Self::is_dst_allowlist_enabled(env.clone())
&& !Self::is_dst_token_allowed(env.clone(), dst_token.clone())
{
Expand Down