PP2: Contract: Arithmetic overflow (Cannot Sub) on any native LUNC transaction involving a slippage floor; affects swaps and liquidity provision #342
Labels
No labels
agent:fix_bugfix
agent:fix_conflicts
agent:fix_security
agent:gap_analysis
agent:implement
agent:implement
agent:implement
agent:open_issues
agent:ready
agent:research
agent:security_audit
agent:verify
architecture
backend
blocker:hybrid
blocker:launch
blocker:limit-orders
blocker:v2
block:log_only
block:security
bug
ci
contracts
correctness
deploy
dev
devops
docs
documentation
duplicate
e2e
enhancement
epic
feature
frontend
functional-completion
gas
good first issue
governance
help wanted
high-risk
hooks
hybrid
indexer
infra
infrastructure
integrators
invalid
launch-blocker
limit-orders
localnet
localterra
low priority
missing-implementation
needs-design
ops
performance
priority
high
priority
medium
product
qa
QA
question
ready
ready
research
scripts
security
security-hardening
smartcontracts
tech-debt
testing
ux
UX
v2
verification
wontfix
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
code/cl8y-dex-terraclassic#342
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Summary
Any on-chain transaction involving native LUNC (auto-wrapped) that computes or enforces a slippage floor fails with an arithmetic overflow:
The underflow pattern is consistent: the smaller value is always
value * 0.995(the 0.5% slippage floor of the larger value), confirming the overflow is triggered when the contract attempts a subtraction of the formslippage_floor - offer_amountor equivalent where the floor is computed as less than the reference amount.Two reproduction paths confirmed:
Path 1 -- Swap (LUNC to EMBER):
Path 2 -- Provide Liquidity (LUNC-C/EMBER pool, 1 LUNC input):
Both follow the same
N * 0.995 - Npattern. The different message indices (1 vs 3) reflect the different number of setup messages in each transaction type (swap = WrapDeposit + router send; liquidity = allowance + allowance + WrapDeposit + provide_liquidity).Reproduction steps
Swap path:
/(Swap page) on LocalTerraCannot Sub with 9950000 and 10000000Liquidity path:
/poolon LocalTerraCannot Sub with 995000 and 1000000Error detail
Cannot Sub with 9950000 and 10000000Cannot Sub with 995000 and 1000000Both values satisfy
smaller = larger * (1 - 0.005)exactly, confirming the slippage tolerance (0.5%) is the source of the subtraction operand.Expected behavior
Transactions should execute successfully. If a slippage floor is not met, the contract should return a named error (
MaxSpreadAssertion,MinReturnAssertion, etc.), not an unguarded arithmetic overflow that surfaces as a rawOverflow: Cannot Submessage.Actual behavior
The contract panics with an unsigned integer underflow. Transactions are broadcast and included in a block but wasm execution fails. The error is not user-actionable.
Possible root cause area
Code review of
smartcontracts/packages/dex-common/src/max_spread.rsandsmartcontracts/contracts/pair/src/contract.rsconfirms all guarded subtraction sites are safe:max_spread.rs:239-242: belief-price path guardsif expected_return > actual_returnbefore subtracting -- safepair/contract.rs:812-814(spot_linear_spread_over_gross): guardsif ideal_output > gross_outputbefore subtracting -- safepair/contract.rs:1110:gross_output.checked_sub(pool_commission_amount)-- commission is ~1.8% of gross, so gross > commission always; safe under normal conditionsThe values
9950000 = 10000000 * 0.995do not correspond to any commission or spread calculation. The exactchecked_subsite could not be confirmed from static analysis alone. Possible location: an intermediate amount comparison in the router's sub-message handling, or a per-hopmin_returnenforced by the pair contract on one of the intermediate hops with an incorrect value computed by the frontend for the wrapped-token input amount.Recommended next step: enable detailed wasm execution logs on localterra and capture the full stack trace including which contract and function triggered the overflow.
Impact assessment
Environment
/(Swap),/pool(Liquidity)Severity: ~"blocker:limit-orders" -- on-chain arithmetic panic blocks all native LUNC transactions; raw overflow error surfaced to user.
Related checklist items: PP-2, PP-3, PP-4, PL-6, PL-9
cc: @PlasticDigits
changed title from
PP2: Contract: Arithmetic overflow on LUNC to EMBER swap execution; `Cannot Sub with 9950000 and 10000000`toPP2: Contract: Arithmetic overflow (Cannot Sub) on any native LUNC transaction involving a slippage floor; affects swaps and liquidity provisionchanged the description
mentioned in issue #337
mentioned in commit
ee182786a0mentioned in merge request !846
MR !846 opened
Changes:
nativeTransferTax.ts+ net CW20 amounts inexecuteNativeSwap/ native-wrapPoolPageprovide.Verify
npm test -- nativeTransferTax.test.tsCannot Sub)mentioned in merge request !847
mentioned in merge request !849
mentioned in merge request !848
mentioned in commit df7f7ac974ce42d67aad4e8c41d408d6f3bed742
mentioned in commit
b511e77e6aVerification complete — #342
All acceptance and verification criteria PASS on
main(83dc192).Results
nativeTransferTax.test.tswrap-swap.spec.tsE1 e2e-tx — tx success alertwrap-pool.spec.tsE7 e2e-tx — auto-wrap provide tx succeedsMerged fix: !846 (
nativeTransferTax.ts+ post-tax CW20 amounts).Re-verify checklist
npm test -- nativeTransferTax.test.tsCannot Sub)mentioned in issue #353
mentioned in issue #559