PP2- Gas: Swap of CW20-to-native swaps underestimate gas; unwrap sub-message overhead not included in gas limit calculation #343
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#343
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
Swapping a CW20 token to LUNC (native output) fails after Keplr approval with:
The gas limit computed by the frontend is insufficient for the full execution path. For CW20-to-native swaps, the router appends an extra unwrap sub-message after the final hop -- a CW20 send to the wrap-mapper contract, which then issues a bank send of native coins to the recipient. This extra sub-message is not counted in the gas estimate.
Observed for: EMBER (CW20) to LUNC (native).
Reproduction steps
/(Swap page) on LocalTerraExpected behavior
The gas estimate should cover all sub-messages in the execution path, including the unwrap sub-message appended by the router when the output token is native. The swap should execute and confirm successfully.
Actual behavior
The gas limit is computed from hop count only. The unwrap sub-message adds overhead that exceeds the safety margin, causing the transaction to run out of gas after broadcast.
Verified root cause (code read and confirmed)
frontend-dapp/src/services/terraclassic/terraGas.ts:156-177--getGasLimitForTxhandles the CW20sendmessage:gasLimitForSwapOperationsMsg(terraGas.ts:93-100) callsgasLimitForExecuteSwapOperations(hops), wherehops = operations.length. This formula is:For a 1-hop swap this yields 840,000. For a 2-hop swap: 1,670,000.
Neither
gasLimitForSwapOperationsMsgnorgetGasLimitForTxinspects theunwrap_outputflag in the hook message. Whenunwrap_output: trueis set (CW20-to-native output swap), the router's finalreply_swap_hop(router/src/contract.rs:365-382) appends a CW20 send to the wrap-mapper, which then executes a bank send of native LUNC. This extra sub-message execution is not covered by the hop-count formula and pushes the total gas above the limit.The
UNWRAP_GAS_LIMIT = 400000constant exists inconstants.ts:27and is used for direct unwrap transactions, but is never added to the swap gas estimate whenunwrap_outputis true.Impact assessment
Environment
/(Swap)Severity: ~gas gas underestimation causes CW20-to-native swap failure on every submission; retry without code change will fail with the same estimate.
Related checklist items: PP-2, PP-3, PP-4
cc: @PlasticDigits
mentioned in merge request !843
mentioned in issue #337
mentioned in commit
09e0849441mentioned in merge request !845
MR !845 opened (stacked on !844)
Changes:
UNWRAP_GAS_LIMITadded whenunwrap_output: truein gas limit math.Verify
npm test -- transactions.test.ts(unwrap gas test)mentioned in merge request !847
mentioned in merge request !849
mentioned in merge request !846
mentioned in merge request !848
mentioned in merge request !844
mentioned in commit
8f2971ae3amentioned in commit
f7f56610c4Verification complete — #343
All acceptance and verification criteria PASS on
main(83dc192).Results
transactions.test.tsunwrap gasnpm test -- transactions.test.ts -t unwrapUNWRAP_GAS_LIMITin gas mathterraGas.tsadds limit whenunwrap_output:trueAlso verified EMBER→USTC native-output path via
wrap-swap.spec.tsE2e-tx (same unwrap sub-message).Merged fix: !845.
Re-verify checklist
npm test -- transactions.test.ts -t unwrapmentioned in issue #353
mentioned in issue #587
marked as related to #587
mentioned in issue #599
marked as related to #599
mentioned in issue #690