get_amount_out panics with "attempt to divide by zero" on pools where one coin has near-zero balance relative to others. On-chain Vyper get_dy returns 0 in these cases (does not revert). Our code should return None or Some(0) instead of panicking.
Affected variants: TwoCryptoV1, TriCryptoNG (likely all CryptoSwap variants)
Reproduction: Block 24669924, mainnet. Call get_amount_out swapping into the coin with minimal balance.
| Pool |
Variant |
Balances |
Decimals |
0x50d71c7a2c53c501ac33c008c841dc55f3ce7077 |
TriCryptoNG |
[38518681, 7864, 7855682963687623] |
[6, 6, 18] |
0xc01728062fa40733035c30478b01e262024f0725 |
TriCryptoNG |
[52881283198033024486, 8712574380815, 1] |
[18, 18, 8] |
0x7e96ae239b9328acb57af401d1f2b6cf5b4ab8de |
TwoCryptoV1 |
[2017835, 190799953082319952471] |
[6, 18] |
0x96a3f551c99797998dc33e2d816d567db61ee1c2 |
TwoCryptoV1 |
[59376375893353131, 2618865] |
[18, 6] |
0x50f3752289e1456bfa505afd37b241bca23e685d |
TwoCryptoV1 |
[19561767653800219526730, 10692895] |
[18, 8] |
Root cause: Newton solver or fee formula divides by a value proportional to the output coin balance, which approaches 0 during simulation of a large swap.
get_amount_outpanics with "attempt to divide by zero" on pools where one coin has near-zero balance relative to others. On-chain Vyperget_dyreturns 0 in these cases (does not revert). Our code should returnNoneorSome(0)instead of panicking.Affected variants: TwoCryptoV1, TriCryptoNG (likely all CryptoSwap variants)
Reproduction: Block 24669924, mainnet. Call
get_amount_outswapping into the coin with minimal balance.0x50d71c7a2c53c501ac33c008c841dc55f3ce70770xc01728062fa40733035c30478b01e262024f07250x7e96ae239b9328acb57af401d1f2b6cf5b4ab8de0x96a3f551c99797998dc33e2d816d567db61ee1c20x50f3752289e1456bfa505afd37b241bca23e685dRoot cause: Newton solver or fee formula divides by a value proportional to the output coin balance, which approaches 0 during simulation of a large swap.