@paraswap/dex-lib 4.1.16 → 4.1.17-arena

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (304) hide show
  1. package/.eslintrc.js +8 -0
  2. package/build/abi/Aave_GSM.json +751 -0
  3. package/build/abi/Balancer.json +257 -0
  4. package/build/abi/BalancerV2.json +1179 -0
  5. package/build/abi/RamsesV2Pool.abi.json +1554 -0
  6. package/build/abi/RamsesV2Quoter.abi.json +274 -0
  7. package/build/abi/USDM.json +807 -0
  8. package/build/abi/UniswapV2Router.json +397 -0
  9. package/build/abi/{wombat/pool.json → angle-transmuter/ChainlinkAccessControlledOffchainAggregator.json} +594 -637
  10. package/build/abi/angle-transmuter/ChainlinkEACAggregatorProxy.json +509 -0
  11. package/build/abi/curve-v1/CurveBUSDv2.abi.json +1356 -0
  12. package/build/abi/curve-v1/CurveTokenV1.json +305 -0
  13. package/build/abi/curve-v1/CurveTokenV2.json +318 -0
  14. package/build/abi/curve-v1/CurveV1StableNg.json +1452 -0
  15. package/build/abi/curve-v1/CurveV2Swap.json +700 -0
  16. package/build/abi/curve-v1/FactoryCryptoRegistry.json +316 -0
  17. package/build/abi/curve-v1/FactoryRegistry.json +508 -0
  18. package/build/abi/curve-v1/StableSwapAave.json +1152 -0
  19. package/build/abi/curve-v1/StableSwapBUSD.json +814 -0
  20. package/build/abi/curve-v1/StableSwapCompound.json +814 -0
  21. package/build/abi/curve-v1/StableSwapIDLE.json +1253 -0
  22. package/build/abi/curve-v1/StableSwapPax.json +865 -0
  23. package/build/abi/curve-v1/StableSwapSnow.json +900 -0
  24. package/build/abi/curve-v1/StableSwapUSDN.json +1004 -0
  25. package/build/abi/curve-v1/StableSwapUSDT.json +814 -0
  26. package/build/abi/curve-v1/StableSwapY.json +814 -0
  27. package/build/abi/inception/inception-ineth.json +609 -0
  28. package/build/abi/kyberdmm/kyber-storage.abi.json +824 -0
  29. package/build/abi/kyberdmm.abi.json +1148 -0
  30. package/build/abi/maverick-v2/MaverickV2Quoter.json +278 -0
  31. package/build/abi/nerve/nerve-metapool.json +790 -0
  32. package/build/abi/uniswap-v3/UniswapV3Quoter.abi.json +193 -0
  33. package/build/abi/velodrome-slipstream/VelodromeSlipstreamQuoterV2.abi.json +267 -0
  34. package/build/dex/aave-v1/aave-v1.js +0 -1
  35. package/build/dex/aave-v1/aave-v1.js.map +1 -1
  36. package/build/dex/balancer-v1/balancer-pools.json +33333 -0
  37. package/build/dex/bebop/websocket-fetcher.d.ts +35 -0
  38. package/build/dex/bebop/websocket-fetcher.js +87 -0
  39. package/build/dex/bebop/websocket-fetcher.js.map +1 -0
  40. package/build/dex/idle-dao/idle-dao-pool.d.ts +56 -0
  41. package/build/dex/idle-dao/idle-dao-pool.js +176 -0
  42. package/build/dex/idle-dao/idle-dao-pool.js.map +1 -0
  43. package/build/dex/idle-dao/idle-dao-pooling-pool.d.ts +16 -0
  44. package/build/dex/idle-dao/idle-dao-pooling-pool.js +57 -0
  45. package/build/dex/idle-dao/idle-dao-pooling-pool.js.map +1 -0
  46. package/build/dex/idle-dao/scripts.d.ts +9 -0
  47. package/build/dex/idle-dao/scripts.js +552 -0
  48. package/build/dex/idle-dao/scripts.js.map +1 -0
  49. package/build/dex/inception/inception-event-pool.d.ts +4 -4
  50. package/build/dex/inception/inception-event-pool.js +9 -7
  51. package/build/dex/inception/inception-event-pool.js.map +1 -1
  52. package/build/dex/inception/inception-native.d.ts +43 -0
  53. package/build/dex/inception/inception-native.js +131 -0
  54. package/build/dex/inception/inception-native.js.map +1 -0
  55. package/build/dex/inception/inception-pool.d.ts +18 -0
  56. package/build/dex/inception/inception-pool.js +32 -0
  57. package/build/dex/inception/inception-pool.js.map +1 -0
  58. package/build/dex/inception/inception-price-feed.d.ts +19 -0
  59. package/build/dex/inception/inception-price-feed.js +51 -0
  60. package/build/dex/inception/inception-price-feed.js.map +1 -0
  61. package/build/dex/inception/inception.d.ts +6 -6
  62. package/build/dex/inception/inception.js +40 -16
  63. package/build/dex/inception/inception.js.map +1 -1
  64. package/build/dex/inception/utils.d.ts +0 -1
  65. package/build/dex/inception/utils.js +1 -22
  66. package/build/dex/inception/utils.js.map +1 -1
  67. package/build/dex/platypus/platypus.js +3 -17
  68. package/build/dex/platypus/platypus.js.map +1 -1
  69. package/build/dex/swaap-v1/swaap-v1.js +0 -4
  70. package/build/dex/swaap-v1/swaap-v1.js.map +1 -1
  71. package/build/dex/uniswap-v2/config.js +8 -0
  72. package/build/dex/uniswap-v2/config.js.map +1 -1
  73. package/build/dex/uniswap-v3/config.js +2 -1
  74. package/build/dex/uniswap-v3/config.js.map +1 -1
  75. package/build/executor/fixtures/executor01/exchange-params/price-route-multiswap-balancerv1-curvev1-eth-usdc-gusd.json +16 -0
  76. package/build/executor/fixtures/executor01/exchange-params/price-route-multiswap-balancerv1-sushiv3-wbtc-eth-sushi.json +16 -0
  77. package/build/executor/fixtures/executor01/exchange-params/price-route-multiswap-sushiv3-curvev1-eth-usdc-gusd.json +16 -0
  78. package/build/executor/fixtures/executor01/exchange-params/price-route-multiswap-sushiv3-curvev1-gusd-usdc-eth.json +16 -0
  79. package/build/executor/fixtures/executor01/exchange-params/price-route-multiswap-sushiv3-dai-usdc-eth.json +16 -0
  80. package/build/executor/fixtures/executor01/exchange-params/price-route-multiswap-sushiv3-eth-usdc-dai.json +16 -0
  81. package/build/executor/fixtures/executor01/exchange-params/price-route-multiswap-sushiv3-usdc-eth-wbtc.json +16 -0
  82. package/build/executor/fixtures/executor01/exchange-params/price-route-multiswap-sushiv3-usdt-usdc-dai.json +16 -0
  83. package/build/executor/fixtures/executor01/exchange-params/price-route-simpleSwap-balancerv1-eth-usdc.json +9 -0
  84. package/build/executor/fixtures/executor01/exchange-params/price-route-simpleSwap-balancerv1-usdc-eth.json +9 -0
  85. package/build/executor/fixtures/executor01/exchange-params/price-route-simpleSwap-balancerv1-usdc-wbtc.json +9 -0
  86. package/build/executor/fixtures/executor01/exchange-params/price-route-simpleSwap-curvev1-eth-steth.json +9 -0
  87. package/build/executor/fixtures/executor01/exchange-params/price-route-simpleSwap-curvev1-steth-eth.json +9 -0
  88. package/build/executor/fixtures/executor01/exchange-params/price-route-simpleSwap-curvev1-usdc-usdt.json +9 -0
  89. package/build/executor/fixtures/executor01/exchange-params/price-route-simpleSwap-univ3-eth-usdc.json +9 -0
  90. package/build/executor/fixtures/executor01/exchange-params/price-route-simpleSwap-univ3-usdc-eth.json +9 -0
  91. package/build/executor/fixtures/executor01/exchange-params/price-route-simpleSwap-univ3-usdc-usdt.json +9 -0
  92. package/build/executor/fixtures/executor01/maybe-weth-calldata/price-route-multiswap-balancerv1-sushiv3-wbtc-eth-sushi.json +12 -0
  93. package/build/executor/fixtures/executor01/maybe-weth-calldata/price-route-multiswap-sushiv3-curvev1-eth-usdc-gusd.json +7 -0
  94. package/build/executor/fixtures/executor01/maybe-weth-calldata/price-route-multiswap-sushiv3-curvev1-gusd-usdc-eth.json +7 -0
  95. package/build/executor/fixtures/executor01/maybe-weth-calldata/price-route-multiswap-sushiv3-dai-usdc-eth.json +7 -0
  96. package/build/executor/fixtures/executor01/maybe-weth-calldata/price-route-multiswap-sushiv3-eth-usdc-dai.json +7 -0
  97. package/build/executor/fixtures/executor01/maybe-weth-calldata/price-route-multiswap-sushiv3-usdc-eth-wbtc.json +12 -0
  98. package/build/executor/fixtures/executor01/maybe-weth-calldata/price-route-simpleSwap-univ3-eth-usdc.json +7 -0
  99. package/build/executor/fixtures/executor01/maybe-weth-calldata/price-route-simpleSwap-univ3-usdc-eth.json +7 -0
  100. package/build/executor/fixtures/executor01/routes/price-route-multiswap-balancerv1-curvev1-eth-usdc-gusd.json +78 -0
  101. package/build/executor/fixtures/executor01/routes/price-route-multiswap-balancerv1-sushiv3-wbtc-eth-sushi.json +81 -0
  102. package/build/executor/fixtures/executor01/routes/price-route-multiswap-sushiv3-curvev1-eth-usdc-gusd.json +78 -0
  103. package/build/executor/fixtures/executor01/routes/price-route-multiswap-sushiv3-curvev1-gusd-usdc-eth.json +78 -0
  104. package/build/executor/fixtures/executor01/routes/price-route-multiswap-sushiv3-dai-usdc-eth.json +81 -0
  105. package/build/executor/fixtures/executor01/routes/price-route-multiswap-sushiv3-eth-usdc-dai.json +81 -0
  106. package/build/executor/fixtures/executor01/routes/price-route-multiswap-sushiv3-usdc-eth-wbtc.json +81 -0
  107. package/build/executor/fixtures/executor01/routes/price-route-multiswap-sushiv3-usdt-usdc-dai.json +81 -0
  108. package/build/executor/fixtures/executor01/routes/price-route-simpleSwap-balancerv1-eth-usdc.json +64 -0
  109. package/build/executor/fixtures/executor01/routes/price-route-simpleSwap-balancerv1-usdc-eth.json +85 -0
  110. package/build/executor/fixtures/executor01/routes/price-route-simpleSwap-balancerv1-usdc-wbtc.json +64 -0
  111. package/build/executor/fixtures/executor01/routes/price-route-simpleSwap-curvev1-eth-steth.json +52 -0
  112. package/build/executor/fixtures/executor01/routes/price-route-simpleSwap-curvev1-steth-eth.json +52 -0
  113. package/build/executor/fixtures/executor01/routes/price-route-simpleSwap-curvev1-usdc-usdt.json +52 -0
  114. package/build/executor/fixtures/executor01/routes/price-route-simpleSwap-univ3-eth-usdc.json +55 -0
  115. package/build/executor/fixtures/executor01/routes/price-route-simpleSwap-univ3-usdc-eth.json +55 -0
  116. package/build/executor/fixtures/executor01/routes/price-route-simpleSwap-univ3-usdc-usdt.json +55 -0
  117. package/build/executor/fixtures/executor02/exchange-params/price-route-multiSwap-balancerv1-sushiv3-univ3-bal-eth-sushi.json +23 -0
  118. package/build/executor/fixtures/executor02/exchange-params/price-route-multiSwap-maverickv1-sushiv3-univ3-eth-usdc-mav.json +37 -0
  119. package/build/executor/fixtures/executor02/exchange-params/price-route-multiSwap-univ3-sushiv3-sushi-eth-wbtc.json +23 -0
  120. package/build/executor/fixtures/executor02/exchange-params/price-route-multiSwap-univ3-sushiv3-wbtc-eth-sushi.json +23 -0
  121. package/build/executor/fixtures/executor02/exchange-params/price-route-multiswap-curvev1-univ3-dai-usdc-eth.json +51 -0
  122. package/build/executor/fixtures/executor02/exchange-params/price-route-multiswap-univ3-usdt-dai-eth.json +58 -0
  123. package/build/executor/fixtures/executor02/exchange-params/price-route-simpleSwap-sushiv3-balancerv1-eth-usdc.json +23 -0
  124. package/build/executor/fixtures/executor02/exchange-params/price-route-simpleSwap-sushiv3-balancerv1-usdc-eth.json +23 -0
  125. package/build/executor/fixtures/executor02/exchange-params/price-route-simpleSwap-sushiv3-univ3-eth-sushi.json +9 -0
  126. package/build/executor/fixtures/executor02/exchange-params/price-route-simpleSwap-sushiv3-univ3-sushi-eth.json +16 -0
  127. package/build/executor/fixtures/executor02/exchange-params/price-route-simpleSwap-univ3-curvev1-usdt-dai.json +23 -0
  128. package/build/executor/fixtures/executor02/maybe-weth-calldata/price-route-multiSwap-balancerv1-sushiv3-univ3-bal-eth-sushi.json +12 -0
  129. package/build/executor/fixtures/executor02/maybe-weth-calldata/price-route-multiSwap-maverickv1-sushiv3-univ3-eth-usdc-mav.json +7 -0
  130. package/build/executor/fixtures/executor02/maybe-weth-calldata/price-route-multiSwap-univ3-sushiv3-sushi-eth-wbtc.json +12 -0
  131. package/build/executor/fixtures/executor02/maybe-weth-calldata/price-route-multiSwap-univ3-sushiv3-wbtc-eth-sushi.json +12 -0
  132. package/build/executor/fixtures/executor02/maybe-weth-calldata/price-route-multiswap-curvev1-univ3-dai-usdc-eth.json +7 -0
  133. package/build/executor/fixtures/executor02/maybe-weth-calldata/price-route-multiswap-univ3-usdt-dai-eth.json +7 -0
  134. package/build/executor/fixtures/executor02/maybe-weth-calldata/price-route-simpleSwap-sushiv3-balancerv1-eth-usdc.json +7 -0
  135. package/build/executor/fixtures/executor02/maybe-weth-calldata/price-route-simpleSwap-sushiv3-balancerv1-usdc-eth.json +7 -0
  136. package/build/executor/fixtures/executor02/maybe-weth-calldata/price-route-simpleSwap-sushiv3-univ3-eth-sushi.json +7 -0
  137. package/build/executor/fixtures/executor02/maybe-weth-calldata/price-route-simpleSwap-sushiv3-univ3-sushi-eth.json +7 -0
  138. package/build/executor/fixtures/executor02/routes/price-route-multiSwap-balancerv1-sushiv3-univ3-bal-eth-sushi.json +130 -0
  139. package/build/executor/fixtures/executor02/routes/price-route-multiSwap-maverickv1-sushiv3-univ3-eth-usdc-mav.json +136 -0
  140. package/build/executor/fixtures/executor02/routes/price-route-multiSwap-univ3-sushiv3-sushi-eth-wbtc.json +100 -0
  141. package/build/executor/fixtures/executor02/routes/price-route-multiSwap-univ3-sushiv3-wbtc-eth-sushi.json +100 -0
  142. package/build/executor/fixtures/executor02/routes/price-route-multiswap-curvev1-univ3-dai-usdc-eth.json +166 -0
  143. package/build/executor/fixtures/executor02/routes/price-route-multiswap-univ3-usdt-dai-eth.json +190 -0
  144. package/build/executor/fixtures/executor02/routes/price-route-simpleSwap-sushiv3-balancerv1-eth-usdc.json +114 -0
  145. package/build/executor/fixtures/executor02/routes/price-route-simpleSwap-sushiv3-balancerv1-usdc-eth.json +114 -0
  146. package/build/executor/fixtures/executor02/routes/price-route-simpleSwap-sushiv3-univ3-eth-sushi.json +55 -0
  147. package/build/executor/fixtures/executor02/routes/price-route-simpleSwap-sushiv3-univ3-sushi-eth.json +73 -0
  148. package/build/executor/fixtures/executor02/routes/price-route-simpleSwap-univ3-curvev1-usdt-dai.json +82 -0
  149. package/package.json +1 -1
  150. package/src/dex/generic-rfq/example-api.test.ts +12 -1
  151. package/src/dex/generic-rfq/generic-rfq-e2e.test.ts +5 -47
  152. package/src/dex/generic-rfq/generic-rfq-local-e2e.test.ts +8 -22
  153. package/src/dex/uniswap-v2/config.ts +9 -0
  154. package/src/dex/uniswap-v2/uniswap-v2-e2e-avalanche.test.ts +105 -1
  155. package/src/dex/uniswap-v3/config.ts +2 -1
  156. package/tests/constants-e2e.ts +7 -53
  157. package/tests/{tenderly-simulation-new.test.ts → tenderly-simulation.test.ts} +2 -2
  158. package/tests/tenderly-simulation.ts +650 -241
  159. package/tests/token-storage-slots.json +166 -0
  160. package/tests/utils-e2e.ts +198 -712
  161. package/tests/v6/utils-e2e-v6.ts +60 -134
  162. package/.vscode/launch.json +0 -53
  163. package/.vscode/settings.json +0 -2
  164. package/.vscode/tasks.json +0 -15
  165. package/build/abi/uniswap-v3/AlienBaseV3Router.abi.json +0 -52
  166. package/build/abi/uniswap-v4/quoter.abi.json +0 -461
  167. package/build/abi/uniswap-v4/router.abi.json +0 -230
  168. package/build/abi/usual-m-smart-m/usualM.abi.json +0 -483
  169. package/build/dex/aave-v2/tokens-avalanche.json +0 -44
  170. package/build/dex/aave-v2/tokens-mainnet.json +0 -188
  171. package/build/dex/aave-v2/tokens-polygon.json +0 -44
  172. package/build/dex/bProtocol.d.ts +0 -18
  173. package/build/dex/bProtocol.js +0 -39
  174. package/build/dex/bProtocol.js.map +0 -1
  175. package/build/dex/balancer-v3/abi/balancerBatchRouter.d.ts +0 -729
  176. package/build/dex/balancer-v3/abi/balancerBatchRouter.js +0 -732
  177. package/build/dex/balancer-v3/abi/balancerBatchRouter.js.map +0 -1
  178. package/build/dex/balancer-v3/abi/balancerRouter.d.ts +0 -1406
  179. package/build/dex/balancer-v3/abi/balancerRouter.js +0 -1175
  180. package/build/dex/balancer-v3/abi/balancerRouter.js.map +0 -1
  181. package/build/dex/balancer-v3/abi/vaultExtension.V3.d.ts +0 -2081
  182. package/build/dex/balancer-v3/abi/vaultExtension.V3.js +0 -1851
  183. package/build/dex/balancer-v3/abi/vaultExtension.V3.js.map +0 -1
  184. package/build/dex/balancer-v3/balancer-v3-sepolia-pools.d.ts +0 -34
  185. package/build/dex/balancer-v3/balancer-v3-sepolia-pools.js +0 -406
  186. package/build/dex/balancer-v3/balancer-v3-sepolia-pools.js.map +0 -1
  187. package/build/dex/bancor.d.ts +0 -26
  188. package/build/dex/bancor.js +0 -58
  189. package/build/dex/bancor.js.map +0 -1
  190. package/build/dex/compound.d.ts +0 -18
  191. package/build/dex/compound.js +0 -46
  192. package/build/dex/compound.js.map +0 -1
  193. package/build/dex/curve-v2.d.ts +0 -58
  194. package/build/dex/curve-v2.js +0 -180
  195. package/build/dex/curve-v2.js.map +0 -1
  196. package/build/dex/dodo-v1.d.ts +0 -33
  197. package/build/dex/dodo-v1.js +0 -63
  198. package/build/dex/dodo-v1.js.map +0 -1
  199. package/build/dex/erc4626/scripts/validate-state.d.ts +0 -0
  200. package/build/dex/erc4626/scripts/validate-state.js +0 -146
  201. package/build/dex/erc4626/scripts/validate-state.js.map +0 -1
  202. package/build/dex/lido.d.ts +0 -19
  203. package/build/dex/lido.js +0 -42
  204. package/build/dex/lido.js.map +0 -1
  205. package/build/dex/maker-psm/scripts/gem.abi.json +0 -136
  206. package/build/dex/maker-psm/scripts/validate-state.d.ts +0 -0
  207. package/build/dex/maker-psm/scripts/validate-state.js +0 -185
  208. package/build/dex/maker-psm/scripts/validate-state.js.map +0 -1
  209. package/build/dex/maker-psm/scripts/vat.abi.json +0 -243
  210. package/build/dex/onebit.d.ts +0 -25
  211. package/build/dex/onebit.js +0 -42
  212. package/build/dex/onebit.js.map +0 -1
  213. package/build/dex/smoothy.d.ts +0 -26
  214. package/build/dex/smoothy.js +0 -48
  215. package/build/dex/smoothy.js.map +0 -1
  216. package/build/dex/solidly-v3/scripts/check-event-pool-event.d.ts +0 -1
  217. package/build/dex/solidly-v3/scripts/check-event-pool-event.js +0 -53
  218. package/build/dex/solidly-v3/scripts/check-event-pool-event.js.map +0 -1
  219. package/build/dex/stable-pool.d.ts +0 -28
  220. package/build/dex/stable-pool.js +0 -55
  221. package/build/dex/stable-pool.js.map +0 -1
  222. package/build/dex/trader-joe-v2.1/trader-joe-v2.1-new.d.ts +0 -7
  223. package/build/dex/trader-joe-v2.1/trader-joe-v2.1-new.js +0 -20
  224. package/build/dex/trader-joe-v2.1/trader-joe-v2.1-new.js.map +0 -1
  225. package/build/dex/trader-joe-v2.1.d.ts +0 -43
  226. package/build/dex/trader-joe-v2.1.js +0 -79
  227. package/build/dex/trader-joe-v2.1.js.map +0 -1
  228. package/build/dex/uniswap-v3/forks/alien-base-v3/alien-base-v3.d.ts +0 -17
  229. package/build/dex/uniswap-v3/forks/alien-base-v3/alien-base-v3.js +0 -64
  230. package/build/dex/uniswap-v3/forks/alien-base-v3/alien-base-v3.js.map +0 -1
  231. package/build/dex/uniswap-v3/forks/alien-v3/alien-v3.d.ts +0 -17
  232. package/build/dex/uniswap-v3/forks/alien-v3/alien-v3.js +0 -79
  233. package/build/dex/uniswap-v3/forks/alien-v3/alien-v3.js.map +0 -1
  234. package/build/dex/uniswap-v3/uniswap-v3-pricing.d.ts +0 -4
  235. package/build/dex/uniswap-v3/uniswap-v3-pricing.js +0 -43
  236. package/build/dex/uniswap-v3/uniswap-v3-pricing.js.map +0 -1
  237. package/build/dex/uniswap-v3/uniswap-v3-worker.d.ts +0 -1
  238. package/build/dex/uniswap-v3/uniswap-v3-worker.js +0 -10
  239. package/build/dex/uniswap-v3/uniswap-v3-worker.js.map +0 -1
  240. package/build/dex/uniswap-v4/config.d.ts +0 -3
  241. package/build/dex/uniswap-v4/config.js +0 -15
  242. package/build/dex/uniswap-v4/config.js.map +0 -1
  243. package/build/dex/uniswap-v4/encoder.d.ts +0 -16
  244. package/build/dex/uniswap-v4/encoder.js +0 -94
  245. package/build/dex/uniswap-v4/encoder.js.map +0 -1
  246. package/build/dex/uniswap-v4/types.d.ts +0 -30
  247. package/build/dex/uniswap-v4/types.js +0 -3
  248. package/build/dex/uniswap-v4/types.js.map +0 -1
  249. package/build/dex/uniswap-v4/uniswap-v4.d.ts +0 -38
  250. package/build/dex/uniswap-v4/uniswap-v4.js +0 -187
  251. package/build/dex/uniswap-v4/uniswap-v4.js.map +0 -1
  252. package/build/dex/usual/usual-m-smart-m.d.ts +0 -17
  253. package/build/dex/usual/usual-m-smart-m.js +0 -50
  254. package/build/dex/usual/usual-m-smart-m.js.map +0 -1
  255. package/build/dex/usual-m-smart-m/config.d.ts +0 -3
  256. package/build/dex/usual-m-smart-m/config.js +0 -13
  257. package/build/dex/usual-m-smart-m/config.js.map +0 -1
  258. package/build/dex/usual-m-smart-m/types.d.ts +0 -7
  259. package/build/dex/usual-m-smart-m/types.js +0 -3
  260. package/build/dex/usual-m-smart-m/types.js.map +0 -1
  261. package/build/dex/usual-m-smart-m/usual-m-smart-m.d.ts +0 -35
  262. package/build/dex/usual-m-smart-m/usual-m-smart-m.js +0 -161
  263. package/build/dex/usual-m-smart-m/usual-m-smart-m.js.map +0 -1
  264. package/build/dex/usual-m-usd0/config.d.ts +0 -3
  265. package/build/dex/usual-m-usd0/config.js +0 -14
  266. package/build/dex/usual-m-usd0/config.js.map +0 -1
  267. package/build/dex/usual-m-usd0/types.d.ts +0 -8
  268. package/build/dex/usual-m-usd0/types.js +0 -3
  269. package/build/dex/usual-m-usd0/types.js.map +0 -1
  270. package/build/dex/usual-m-usd0/usual-m-usd0.d.ts +0 -35
  271. package/build/dex/usual-m-usd0/usual-m-usd0.js +0 -159
  272. package/build/dex/usual-m-usd0/usual-m-usd0.js.map +0 -1
  273. package/tests/augustus-approvals.test.ts +0 -628
  274. package/tests/smart-tokens.ts +0 -112
  275. package/tests/tenderly-simulation-new.ts +0 -698
  276. package/tests/v6/executors.test.ts +0 -110
  277. package/tests/v6/price-routes/arbitrum/sell-0.1-ETH-USDC.json +0 -104
  278. package/tests/v6/price-routes/arbitrum/sell-1_000-ETH-DAI.json +0 -294
  279. package/tests/v6/price-routes/arbitrum/sell-1_000-WETH-wstETH.json +0 -121
  280. package/tests/v6/price-routes/arbitrum/sell-1_000_000-ARB-DAI.json +0 -270
  281. package/tests/v6/price-routes/arbitrum/sell-1_000_000-ARB-ETH.json +0 -326
  282. package/tests/v6/price-routes/arbitrum/sell-1_000_000-DAI-ARB.json +0 -434
  283. package/tests/v6/price-routes/arbitrum/sell-250_000-LINK-USDC.json +0 -182
  284. package/tests/v6/price-routes/arbitrum/sell-3_000-BAL-UNI.json +0 -154
  285. package/tests/v6/price-routes/avalanche/sell-100_000-WAVAX-USDC.json +0 -315
  286. package/tests/v6/price-routes/avalanche/sell-40-BTC-AVAX.json +0 -207
  287. package/tests/v6/price-routes/mainnet/buy-3200-ETH-DAI.json +0 -228
  288. package/tests/v6/price-routes/mainnet/sell-1-USDC-USDT.json +0 -78
  289. package/tests/v6/price-routes/mainnet/sell-1-WBTC-BAL.json +0 -158
  290. package/tests/v6/price-routes/mainnet/sell-100-tBTC-WBTC.json +0 -100
  291. package/tests/v6/price-routes/mainnet/sell-1000-eth-dai.json +0 -340
  292. package/tests/v6/price-routes/mainnet/sell-1000-wbtc-eth-uniswapv3-balancerv2.json +0 -162
  293. package/tests/v6/price-routes/mainnet/sell-100_000-USDC-USDT-2-univ2-pools.json +0 -86
  294. package/tests/v6/price-routes/mainnet/sell-10_000-ETH-USDC-balancer.json +0 -383
  295. package/tests/v6/price-routes/mainnet/sell-10_000-ETH-stETH.json +0 -168
  296. package/tests/v6/price-routes/mainnet/sell-10_000-USDC-USDT-BalancerV2.json +0 -68
  297. package/tests/v6/price-routes/mainnet/sell-10_000-eth-usdc-uniswapv3-balancerv2.json +0 -348
  298. package/tests/v6/price-routes/mainnet/sell-1_000-stETH-ETH.json +0 -100
  299. package/tests/v6/price-routes/mainnet/sell-50-eth-usdc.json +0 -153
  300. package/tests/v6/price-routes/polygon/sell-100-WBTC-MATIC-1.json +0 -571
  301. package/tests/v6/price-routes/polygon/sell-100-WBTC-MATIC.json +0 -559
  302. package/tests/v6/price-routes/polygon/sell-1_000_000-DAI-MATIC-2.json +0 -447
  303. package/tests/v6/price-routes/polygon/sell-1_000_000-DAI-MATIC-3.json +0 -472
  304. package/tests/v6/price-routes/polygon/sell-1_000_000-DAI-MATIC.json +0 -628
@@ -1,289 +1,698 @@
1
1
  /* eslint-disable no-console */
2
+ import 'dotenv/config';
2
3
  import axios from 'axios';
3
- import { TxObject } from '../src/types';
4
- import { StateOverrides, StateSimulateApiOverride } from './smart-tokens';
5
- import { Provider, StaticJsonRpcProvider } from '@ethersproject/providers';
6
4
  import { ethers } from 'ethers';
7
- import { Network } from '../build/constants';
8
- import { Address } from '@paraswap/core';
9
-
10
- const TENDERLY_TOKEN = process.env.TENDERLY_TOKEN;
11
- const TENDERLY_ACCOUNT_ID = process.env.TENDERLY_ACCOUNT_ID;
12
- const TENDERLY_PROJECT = process.env.TENDERLY_PROJECT;
13
- const TENDERLY_VNET_ID = process.env.TENDERLY_VNET_ID;
14
-
15
- export type SimulationResult = {
16
- success: boolean;
17
- gasUsed?: string;
18
- url?: string;
19
- transaction?: any;
20
- };
21
-
22
- export interface TransactionSimulator {
23
- vnetId: string;
24
- rpcURL: string;
25
- setup(): Promise<void>;
26
-
27
- getChainNameByChainId(network: number): string;
28
-
29
- simulate(
30
- params: TxObject,
31
- stateOverrides?: StateOverrides,
32
- ): Promise<SimulationResult>;
5
+ import * as fs from 'fs/promises';
6
+ import * as path from 'path';
7
+ import { ETHER_ADDRESS } from '../src/constants';
8
+
9
+ const TENDERLY_TOKEN = process.env.TENDERLY_TOKEN!;
10
+ const TENDERLY_ACCOUNT_ID = process.env.TENDERLY_ACCOUNT_ID!;
11
+ const TENDERLY_PROJECT = process.env.TENDERLY_PROJECT!;
12
+
13
+ interface StateObject {
14
+ // Overrides of storage slots.
15
+ // In this mapping, the key is variable storage slot,
16
+ // and the value contains the override.
17
+ storage?: Record<string, string>; // storage slot -> value
18
+ balance?: string;
19
+ nonce?: number;
20
+ // Bytecode that will override the code associated to the given account.
21
+ code?: string;
33
22
  }
23
+ export type StateOverride = Record<string, StateObject>; // contract -> storage override
34
24
 
35
- export class EstimateGasSimulation implements TransactionSimulator {
36
- vnetId: string = '0';
37
- rpcURL: string = '';
25
+ interface TokenStorageSlots {
26
+ balanceSlot: string;
27
+ allowanceSlot: string;
28
+ isVyper?: boolean;
29
+ }
30
+
31
+ interface SimulateTransactionRequest {
32
+ from: string | null;
33
+ to: string | null;
34
+ value?: string;
35
+ data: string;
36
+ chainId: number;
37
+ timestamp?: number;
38
+ blockNumber?: number;
39
+ stateOverride?: StateOverride;
40
+ }
41
+
42
+ // not fully complete
43
+ interface SimulatedTransactionCall {
44
+ hash: string;
45
+ contract_name: string;
46
+ function_name: string;
47
+ function_pc: number;
48
+ function_op: string;
49
+ function_file_index: number;
50
+ function_code_start: number;
51
+ function_line_number: number;
52
+ function_code_length: number;
53
+ absolute_position: number;
54
+ caller_pc: number;
55
+ caller_op: string;
56
+ call_type: string;
57
+ address: string;
58
+ from: string;
59
+ from_balance: string;
60
+ to: string;
61
+ to_balance: string;
62
+ value: string | null;
63
+ caller: {
64
+ address: string;
65
+ balance: string;
66
+ };
67
+ block_timestamp: string;
68
+ gas: number;
69
+ gas_used: number;
70
+ intrinsic_gas: number;
71
+ storage_address: string;
72
+ input: string;
73
+ storage_slot: string[] | undefined;
74
+ calls: SimulatedTransactionCall[] | null;
75
+ }
38
76
 
39
- constructor(private provider: Provider) {}
77
+ // not fully complete
78
+ interface Simulation {
79
+ id: string;
80
+ project_id: string;
81
+ owner_id: string;
82
+ network_id: string;
83
+ block_number: number;
84
+ transaction_index: number;
85
+ from: string;
86
+ to: string;
87
+ input: string;
88
+ gas: number;
89
+ gas_price: string;
90
+ gas_used: number;
91
+ value: string;
92
+ method: string;
93
+ status: boolean;
94
+ }
40
95
 
41
- async setup() {}
96
+ // not complete, all details include a lot more info
97
+ interface SimulatedTransactionDetails {
98
+ transaction: {
99
+ hash: string;
100
+ block_hash: string;
101
+ block_number: number;
102
+ from: string;
103
+ gas: number;
104
+ gas_price: number;
105
+ gas_fee_cap: number;
106
+ gas_tip_cap: number;
107
+ cumulative_gas_used: number;
108
+ gas_used: number;
109
+ effective_gas_price: number;
110
+ input: string;
111
+ nonce: number;
112
+ to: string;
113
+ index: number;
114
+ value: string;
115
+ access_list: null;
116
+ status: boolean;
117
+ transaction_info: {
118
+ call_trace: SimulatedTransactionCall;
119
+ };
120
+ };
121
+ }
42
122
 
43
- getChainNameByChainId(network: number) {
44
- return '';
123
+ class TokenStorageSlotsCache {
124
+ private static TOKEN_STORAGE_SLOTS: Record<
125
+ number,
126
+ Record<string, TokenStorageSlots>
127
+ > | null = null;
128
+ private static readonly TOKEN_STORAGE_SLOTS_FILEPATH = path.join(
129
+ __dirname,
130
+ 'token-storage-slots.json',
131
+ );
132
+
133
+ private static async loadTokenStorageSlots(): Promise<
134
+ Record<number, Record<string, TokenStorageSlots>>
135
+ > {
136
+ return JSON.parse(
137
+ await fs.readFile(TokenStorageSlotsCache.TOKEN_STORAGE_SLOTS_FILEPATH, {
138
+ encoding: 'utf-8',
139
+ }),
140
+ );
45
141
  }
46
142
 
47
- async simulate(
48
- params: TxObject,
49
- _: StateOverrides,
50
- ): Promise<SimulationResult> {
51
- try {
52
- const result = await this.provider.estimateGas(params);
53
- return {
54
- success: true,
55
- gasUsed: result.toNumber().toString(),
56
- };
57
- } catch (e) {
58
- console.error(`Estimate gas simulation failed:`, e);
59
- return {
60
- success: false,
61
- };
143
+ private static async saveTokenStorageSlots(): Promise<void> {
144
+ await fs.writeFile(
145
+ TokenStorageSlotsCache.TOKEN_STORAGE_SLOTS_FILEPATH,
146
+ JSON.stringify(TokenStorageSlotsCache.TOKEN_STORAGE_SLOTS, null, 2),
147
+ { encoding: 'utf-8' },
148
+ );
149
+ }
150
+
151
+ static async getTokenStorageSlots(
152
+ chainId: number,
153
+ token: string,
154
+ ): Promise<TokenStorageSlots | null> {
155
+ if (!TokenStorageSlotsCache.TOKEN_STORAGE_SLOTS) {
156
+ TokenStorageSlotsCache.TOKEN_STORAGE_SLOTS =
157
+ await TokenStorageSlotsCache.loadTokenStorageSlots();
62
158
  }
159
+
160
+ return (
161
+ TokenStorageSlotsCache.TOKEN_STORAGE_SLOTS[chainId]?.[
162
+ token.toLowerCase()
163
+ ] ?? null
164
+ );
63
165
  }
64
- }
65
166
 
66
- export class TenderlySimulation implements TransactionSimulator {
67
- vnetId: string = '';
68
- rpcURL: string = '';
69
- maxGasLimit = 80000000;
70
-
71
- private readonly chainIdToChainNameMap: { [key: number]: string } = {
72
- [Network.MAINNET]: 'mainnet',
73
- [Network.BSC]: 'bnb',
74
- [Network.POLYGON]: 'polygon',
75
- [Network.AVALANCHE]: 'avalanche-mainnet',
76
- [Network.FANTOM]: 'fantom',
77
- [Network.ARBITRUM]: 'arbitrum',
78
- [Network.OPTIMISM]: 'optimistic',
79
- [Network.GNOSIS]: 'gnosis-chain',
80
- [Network.BASE]: 'base',
81
- };
167
+ static async setTokenStorageSlots(
168
+ chainId: number,
169
+ token: string,
170
+ slots: TokenStorageSlots,
171
+ ): Promise<void> {
172
+ if (!TokenStorageSlotsCache.TOKEN_STORAGE_SLOTS) {
173
+ TokenStorageSlotsCache.TOKEN_STORAGE_SLOTS =
174
+ await TokenStorageSlotsCache.loadTokenStorageSlots();
175
+ }
82
176
 
83
- constructor(private network: number = 1) {}
177
+ TokenStorageSlotsCache.TOKEN_STORAGE_SLOTS ||= {};
178
+ TokenStorageSlotsCache.TOKEN_STORAGE_SLOTS[chainId] ||= {};
179
+ TokenStorageSlotsCache.TOKEN_STORAGE_SLOTS[chainId][token.toLowerCase()] =
180
+ slots;
84
181
 
85
- getChainNameByChainId(network: number): string {
86
- return this.chainIdToChainNameMap[network];
182
+ void TokenStorageSlotsCache.saveTokenStorageSlots();
87
183
  }
184
+ }
88
185
 
89
- async setup() {
90
- if (!TENDERLY_TOKEN)
91
- throw new Error(
92
- `TenderlySimulation_setup: TENDERLY_TOKEN not found in the env`,
93
- );
186
+ export class TenderlySimulator {
187
+ // public constants
188
+ static readonly DEFAULT_OWNER = '0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa';
189
+ static readonly DEFAULT_SPENDER =
190
+ '0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb';
94
191
 
95
- const findAdminRPC = (rpcs: { name: string; url: string }[]) => {
96
- return rpcs.find(
97
- rpc => rpc.name.toLowerCase() === 'Admin RPC'.toLowerCase(),
98
- );
192
+ // singleton
193
+ private static instance: TenderlySimulator;
194
+
195
+ private constructor() {}
196
+
197
+ public static getInstance(): TenderlySimulator {
198
+ if (!TenderlySimulator.instance) {
199
+ TenderlySimulator.instance = new TenderlySimulator();
200
+ }
201
+
202
+ return TenderlySimulator.instance;
203
+ }
204
+
205
+ public async simulateTransaction(
206
+ request: SimulateTransactionRequest,
207
+ ): Promise<Simulation> {
208
+ const data = {
209
+ network_id: request.chainId,
210
+ from: request.from,
211
+ to: request.to,
212
+ input: request.data,
213
+ value: request.value,
214
+ save: true,
215
+ save_if_fails: true,
216
+ state_objects: request.stateOverride,
99
217
  };
100
218
 
101
- if (TENDERLY_VNET_ID) {
102
- this.vnetId = TENDERLY_VNET_ID;
103
-
104
- try {
105
- let res = await axios.get(
106
- `https://api.tenderly.co/api/v1/account/${TENDERLY_ACCOUNT_ID}/project/${TENDERLY_PROJECT}/vnets/${this.vnetId}`,
107
- {
108
- timeout: 200000,
109
- headers: {
110
- 'x-access-key': TENDERLY_TOKEN,
111
- },
112
- },
113
- );
219
+ console.log('Sending transaction simulation with params:');
220
+ console.log(JSON.stringify(data, null, 2));
114
221
 
115
- const rpc = findAdminRPC(res.data.rpcs);
222
+ const response = await axios.request({
223
+ method: 'POST',
224
+ url: `https://api.tenderly.co/api/v1/account/${TENDERLY_ACCOUNT_ID}/project/${TENDERLY_PROJECT}/simulate`,
225
+ headers: {
226
+ 'X-Access-Key': TENDERLY_TOKEN,
227
+ },
228
+ data,
229
+ });
116
230
 
117
- if (!rpc) {
118
- throw new Error(`RPC url was not found for testnet: ${this.vnetId}`);
119
- }
231
+ const simulation = response.data.simulation as Simulation;
232
+ const url = `https://dashboard.tenderly.co/${TENDERLY_ACCOUNT_ID}/${TENDERLY_PROJECT}/simulator/${simulation.id}`;
120
233
 
121
- this.rpcURL = rpc.url;
122
- } catch (e) {
123
- console.error(`TenderlySimulation_setup:`, e);
124
- throw e;
125
- }
234
+ console.log('Successfully simulated a transaction:');
235
+ console.log(`Simulation URL - ${url}`);
126
236
 
127
- return;
128
- }
237
+ return simulation;
238
+ }
129
239
 
240
+ public async getSimulatedTransactionDetails(
241
+ id: string,
242
+ ): Promise<SimulatedTransactionDetails | null> {
130
243
  try {
131
- await process.nextTick(() => {}); // https://stackoverflow.com/questions/69169492/async-external-function-leaves-open-handles-jest-supertest-express
132
- let res = await axios.post(
133
- `https://api.tenderly.co/api/v1/account/${TENDERLY_ACCOUNT_ID}/project/${TENDERLY_PROJECT}/vnets`,
134
- {
135
- slug: `e2e-tests-testnetwork-${this.network.toString()}-${Date.now()}`,
136
- fork_config: {
137
- network_id: this.network,
138
- },
139
- virtual_network_config: {
140
- chain_config: {
141
- chain_id: this.network,
142
- },
143
- },
144
- sync_state_config: {
145
- enabled: false,
146
- },
147
- explorer_page_config: {
148
- enabled: true,
149
- verification_visibility: 'bytecode',
150
- },
151
- },
152
- {
153
- timeout: 200000,
154
- headers: {
155
- 'x-access-key': TENDERLY_TOKEN,
156
- },
157
- },
244
+ const { data } = await axios.post(
245
+ `https://api.tenderly.co/api/v1/account/${TENDERLY_ACCOUNT_ID}/project/${TENDERLY_PROJECT}/simulations/${id}`,
246
+ {},
247
+ { headers: { 'X-Access-Key': TENDERLY_TOKEN } },
158
248
  );
159
249
 
160
- this.vnetId = res.data.id;
161
- const rpc = findAdminRPC(res.data.rpcs);
162
- if (!rpc) {
163
- throw new Error(`RPC url was not found for testnet: ${this.vnetId}`);
164
- }
165
-
166
- this.rpcURL = rpc.url;
250
+ return data;
167
251
  } catch (e) {
168
- console.error(`TenderlySimulation_setup:`, e);
169
- throw e;
252
+ console.error(e);
253
+ return null;
170
254
  }
171
255
  }
172
256
 
173
- async simulate(params: TxObject, stateOverrides?: StateOverrides) {
174
- try {
175
- let stateOverridesParams = {};
176
-
177
- if (stateOverrides) {
178
- await process.nextTick(() => {}); // https://stackoverflow.com/questions/69169492/async-external-function-leaves-open-handles-jest-supertest-express
179
- const result = await axios.post(
180
- `https://api.tenderly.co/api/v1/account/${TENDERLY_ACCOUNT_ID}/project/${TENDERLY_PROJECT}/contracts/encode-states`,
181
- stateOverrides,
182
- {
183
- headers: {
184
- 'x-access-key': TENDERLY_TOKEN!,
185
- },
186
- },
187
- );
257
+ getSLOADCalls = (
258
+ callTrace: SimulatedTransactionCall,
259
+ ): SimulatedTransactionCall[] => {
260
+ const results: SimulatedTransactionCall[] = [];
261
+
262
+ if (callTrace.call_type === 'SLOAD') {
263
+ results.push(callTrace);
264
+ }
265
+
266
+ if (callTrace.calls) {
267
+ for (const call of callTrace.calls) {
268
+ results.push(...this.getSLOADCalls(call));
269
+ }
270
+ }
271
+
272
+ return results;
273
+ };
188
274
 
189
- stateOverridesParams = Object.keys(result.data.stateOverrides).reduce(
190
- (acc, contract) => {
191
- const _storage = result.data.stateOverrides[contract].value;
275
+ /**
276
+ *
277
+ * @param balanceOfSlot storage slot of `balanceOf` mapping
278
+ * @param owner account's address
279
+ * @param isVyper `true` if contract is written in Vyper
280
+ */
281
+ calculateAddressBalanceSlot(
282
+ balanceOfSlot: string,
283
+ owner: string,
284
+ isVyper = false,
285
+ ) {
286
+ return isVyper
287
+ ? this.calculateVyperAddressBalanceSlot(balanceOfSlot, owner)
288
+ : this.calculateSolidityAddressBalanceSlot(balanceOfSlot, owner);
289
+ }
290
+
291
+ /**
292
+ *
293
+ * @param balanceOfSlot storage slot of `balanceOf` mapping
294
+ * @param owner account's address
295
+ */
296
+ calculateSolidityAddressBalanceSlot(balanceOfSlot: string, owner: string) {
297
+ return ethers.utils.keccak256(
298
+ ethers.utils.concat([ethers.utils.hexZeroPad(owner, 32), balanceOfSlot]),
299
+ );
300
+ }
301
+
302
+ /**
303
+ *
304
+ * @param balanceOfSlot storage slot of `balanceOf` mapping
305
+ * @param owner account's address
306
+ */
307
+ calculateVyperAddressBalanceSlot(balanceOfSlot: string, owner: string) {
308
+ return ethers.utils.keccak256(
309
+ ethers.utils.concat([balanceOfSlot, ethers.utils.hexZeroPad(owner, 32)]),
310
+ );
311
+ }
192
312
 
193
- acc[contract] = {
194
- storage: _storage,
195
- };
196
- return acc;
197
- },
198
- {} as Record<Address, StateSimulateApiOverride>,
313
+ /**
314
+ *
315
+ * @param allowanceSlot storage slot of `allowance` mapping
316
+ * @param owner account's address
317
+ * @param spender spender's address
318
+ * @param isVyper `true` if contract is written in Vyper
319
+ */
320
+ calculateAddressAllowanceSlot(
321
+ allowanceSlot: string,
322
+ owner: string,
323
+ spender: string,
324
+ isVyper = false,
325
+ ) {
326
+ return isVyper
327
+ ? this.calculateVyperAddressAllowanceSlot(allowanceSlot, owner, spender)
328
+ : this.calculateSolidityAddressAllowanceSlot(
329
+ allowanceSlot,
330
+ owner,
331
+ spender,
199
332
  );
333
+ }
200
334
 
201
- await this.executeStateOverrides(stateOverridesParams);
202
- }
335
+ /**
336
+ *
337
+ * @param allowanceSlot storage slot of `allowance` mapping
338
+ * @param owner account's address
339
+ * @param spender spender's address
340
+ */
341
+ calculateSolidityAddressAllowanceSlot(
342
+ allowanceSlot: string,
343
+ owner: string,
344
+ spender: string,
345
+ ) {
346
+ const slotHash = ethers.utils.keccak256(
347
+ ethers.utils.concat([
348
+ ethers.utils.hexZeroPad(owner, 32),
349
+ ethers.utils.hexZeroPad(allowanceSlot, 32),
350
+ ]),
351
+ );
203
352
 
204
- await process.nextTick(() => {}); // https://stackoverflow.com/questions/69169492/async-external-function-leaves-open-handles-jest-supertest-express
205
- const { data } = await axios.post(
206
- `https://api.tenderly.co/api/v1/account/${TENDERLY_ACCOUNT_ID}/project/${TENDERLY_PROJECT}/vnets/${this.vnetId}/transactions`,
207
- {
208
- callArgs: {
209
- from: params.from,
210
- to: params.to,
211
- value:
212
- params.value === '0'
213
- ? '0x0'
214
- : ethers.utils.hexStripZeros(
215
- ethers.utils.hexlify(BigInt(params.value)),
216
- ),
217
- gas: ethers.utils.hexStripZeros(
218
- ethers.utils.hexlify(BigInt(this.maxGasLimit)),
219
- ),
220
- data: params.data,
221
- },
222
- blockNumber: 'pending',
223
- },
224
- {
225
- timeout: 30 * 1000,
226
- headers: {
227
- 'x-access-key': TENDERLY_TOKEN!,
228
- },
229
- },
230
- );
353
+ return ethers.utils.keccak256(
354
+ ethers.utils.concat([ethers.utils.hexZeroPad(spender, 32), slotHash]),
355
+ );
356
+ }
357
+
358
+ /**
359
+ *
360
+ * @param allowanceSlot storage slot of `allowance` mapping
361
+ * @param owner account's address
362
+ * @param spender spender's address
363
+ */
364
+ calculateVyperAddressAllowanceSlot(
365
+ allowanceSlot: string,
366
+ owner: string,
367
+ spender: string,
368
+ ) {
369
+ const slotHash = ethers.utils.keccak256(
370
+ ethers.utils.concat([
371
+ ethers.utils.hexZeroPad(allowanceSlot, 32),
372
+ ethers.utils.hexZeroPad(owner, 32),
373
+ ]),
374
+ );
375
+
376
+ return ethers.utils.keccak256(
377
+ ethers.utils.concat([slotHash, ethers.utils.hexZeroPad(spender, 32)]),
378
+ );
379
+ }
380
+
381
+ buildBalanceOfSimulationRequest(
382
+ chainId: number,
383
+ token: string,
384
+ owner: string,
385
+ ): SimulateTransactionRequest {
386
+ const iface = new ethers.utils.Interface([
387
+ 'function balanceOf(address owner) view returns (uint)',
388
+ ]);
389
+
390
+ return {
391
+ from: ethers.constants.AddressZero,
392
+ to: token,
393
+ data: iface.encodeFunctionData('balanceOf', [owner]),
394
+ chainId,
395
+ };
396
+ }
397
+
398
+ buildAllowanceSimulationRequest(
399
+ chainId: number,
400
+ token: string,
401
+ owner: string,
402
+ spender: string,
403
+ ): SimulateTransactionRequest {
404
+ const iface = new ethers.utils.Interface([
405
+ 'function allowance(address owner, address spender) view returns (uint)',
406
+ ]);
407
+
408
+ return {
409
+ from: ethers.constants.AddressZero,
410
+ to: token,
411
+ data: iface.encodeFunctionData('allowance', [owner, spender]),
412
+ chainId,
413
+ };
414
+ }
415
+
416
+ /**
417
+ * Finds the slot of the `balanceOf` mapping in given token contract's storage.
418
+ * Supports `Solidity` and `Vyper` contracts
419
+ * @param chainId token chain id
420
+ * @param token token address
421
+ */
422
+ async findTokenBalanceOfSlot(
423
+ chainId: number,
424
+ token: string,
425
+ ): Promise<{ slot: string; isVyper?: boolean }> {
426
+ const account = TenderlySimulator.DEFAULT_OWNER;
427
+
428
+ const balanceOfSimulationRequest = this.buildBalanceOfSimulationRequest(
429
+ chainId,
430
+ token,
431
+ account,
432
+ );
433
+
434
+ const { id: simulationId } = await this.simulateTransaction(
435
+ balanceOfSimulationRequest,
436
+ );
437
+
438
+ const simulationDetails = await this.getSimulatedTransactionDetails(
439
+ simulationId,
440
+ );
441
+
442
+ if (!simulationDetails) {
443
+ throw `No simulation with id ${simulationId} details found`;
444
+ }
231
445
 
232
- if (data.status === 'success') {
233
- return {
234
- success: true,
235
- gasUsed: data.gasUsed,
236
- url: `https://dashboard.tenderly.co/${TENDERLY_ACCOUNT_ID}/${TENDERLY_PROJECT}/testnet/${
237
- this.vnetId
238
- }/tx/${this.chainIdToChainNameMap[this.network]}/${data.id}`,
239
- transaction: data.input,
240
- };
241
- } else {
242
- return {
243
- success: false,
244
- url: `https://dashboard.tenderly.co/${TENDERLY_ACCOUNT_ID}/${TENDERLY_PROJECT}/testnet/${
245
- this.vnetId
246
- }/tx/${this.chainIdToChainNameMap[this.network]}/${data.id}`,
247
- error: `Simulation failed ${data.error_reason}`,
248
- };
446
+ const callTrace = simulationDetails.transaction.transaction_info.call_trace;
447
+
448
+ const sloadCalls = this.getSLOADCalls(callTrace);
449
+ // token's storage slots that were read during the `balanceOf` call
450
+ const readSlots = sloadCalls
451
+ .map(call => call.storage_slot?.[0])
452
+ .filter<string>((slot): slot is string => !!slot);
453
+
454
+ const startingPoints = [
455
+ // regular contract
456
+ 0n,
457
+ // ERC20Upgradeable
458
+ BigInt(
459
+ '0x52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace00',
460
+ ),
461
+ ];
462
+
463
+ for (const startingPoint of startingPoints) {
464
+ for (let i = startingPoint; i < startingPoint + 1_000n; i += 1n) {
465
+ const candidateSlot = ethers.utils.defaultAbiCoder.encode(
466
+ ['uint'],
467
+ [i],
468
+ );
469
+ // try solidity slot
470
+ const solitidyBalanceOfSlot = this.calculateSolidityAddressBalanceSlot(
471
+ candidateSlot,
472
+ account,
473
+ );
474
+ if (readSlots.includes(solitidyBalanceOfSlot)) {
475
+ return { slot: candidateSlot };
476
+ }
477
+ // try vyper slot
478
+ const vyperBalanceOfSlot = this.calculateVyperAddressBalanceSlot(
479
+ candidateSlot,
480
+ account,
481
+ );
482
+ if (readSlots.includes(vyperBalanceOfSlot)) {
483
+ return { slot: candidateSlot, isVyper: true };
484
+ }
249
485
  }
250
- } catch (e) {
251
- console.error('TenderlySimulation_simulate_error', e);
252
- return {
253
- success: false,
254
- };
255
486
  }
487
+
488
+ throw new Error(
489
+ `Could not find a 'balanceOf' mapping slot for token ${token} on chain ${chainId}`,
490
+ );
256
491
  }
257
492
 
258
- async executeStateOverrides(
259
- stateOverridesParams: Record<string, StateSimulateApiOverride>,
260
- ) {
261
- if (!this.rpcURL) {
262
- throw new Error(
263
- `rpcURL is not defined for testnet: ${this.vnetId} (https://dashboard.tenderly.co/${TENDERLY_ACCOUNT_ID}/${TENDERLY_PROJECT}/testnet/${this.vnetId}`,
264
- );
493
+ /**
494
+ * Finds the slot of the `allowance` mapping in given token contract's storage
495
+ * Supports `Solidity` and `Vyper` contracts
496
+ * @param chainId token chain id
497
+ * @param token token address
498
+ */
499
+ async findTokenAllowanceSlot(
500
+ chainId: number,
501
+ token: string,
502
+ ): Promise<{ slot: string; isVyper?: boolean }> {
503
+ const account = TenderlySimulator.DEFAULT_OWNER;
504
+ const spender = TenderlySimulator.DEFAULT_SPENDER;
505
+
506
+ const allowanceSimulationRequest = this.buildAllowanceSimulationRequest(
507
+ chainId,
508
+ token,
509
+ account,
510
+ spender,
511
+ );
512
+
513
+ const { id: simulationId } = await this.simulateTransaction(
514
+ allowanceSimulationRequest,
515
+ );
516
+
517
+ const simulationDetails = await this.getSimulatedTransactionDetails(
518
+ simulationId,
519
+ );
520
+
521
+ if (!simulationDetails) {
522
+ throw `No simulation with id ${simulationId} details found`;
265
523
  }
266
524
 
267
- const testNetRPC = new StaticJsonRpcProvider(this.rpcURL);
268
- await Promise.all(
269
- Object.keys(stateOverridesParams).map(async addr => {
270
- const storage = stateOverridesParams[addr].storage;
271
-
272
- await Promise.all(
273
- Object.keys(storage).map(async slot => {
274
- const txHash = await testNetRPC!.send('tenderly_setStorageAt', [
275
- addr,
276
- slot,
277
- storage[slot],
278
- ]);
279
-
280
- const transaction = await testNetRPC!.waitForTransaction(txHash);
281
- if (!transaction.status) {
282
- console.log(`Transaction failed: ${txHash}`);
283
- }
284
- }),
525
+ const callTrace = simulationDetails.transaction.transaction_info.call_trace;
526
+
527
+ const sloadCalls = this.getSLOADCalls(callTrace);
528
+ // token's storage slots that were read during the `allowance` call
529
+ const readSlots = sloadCalls
530
+ .map(call => call.storage_slot?.[0])
531
+ .filter<string>((slot): slot is string => !!slot);
532
+
533
+ const startingPoints = [
534
+ // regular contract
535
+ 0n,
536
+ // ERC20Upgradeable
537
+ BigInt(
538
+ '0x52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace00',
539
+ ),
540
+ ];
541
+
542
+ for (const init of startingPoints) {
543
+ for (let i = init; i < init + 1000n; i += 1n) {
544
+ const candidateSlot = ethers.utils.defaultAbiCoder.encode(
545
+ ['uint'],
546
+ [i],
285
547
  );
286
- }),
548
+ // try solidity
549
+ const solidityAllowanceSlot =
550
+ this.calculateSolidityAddressAllowanceSlot(
551
+ candidateSlot,
552
+ account,
553
+ spender,
554
+ );
555
+ if (readSlots.includes(solidityAllowanceSlot)) {
556
+ return { slot: candidateSlot };
557
+ }
558
+ // try vyper
559
+ const vyperAllowanceSlot = this.calculateVyperAddressAllowanceSlot(
560
+ candidateSlot,
561
+ account,
562
+ spender,
563
+ );
564
+ if (readSlots.includes(vyperAllowanceSlot)) {
565
+ return { slot: candidateSlot, isVyper: true };
566
+ }
567
+ }
568
+ }
569
+
570
+ throw new Error(
571
+ `Could not find a 'allowance' mapping slot for token ${token} on chain ${chainId}`,
572
+ );
573
+ }
574
+
575
+ /**
576
+ * Returns storage slots for the given token contract.
577
+ * @param chainId Token chain ID
578
+ * @param token Token address. Doesn't have to be normalized
579
+ */
580
+ async getTokenStorageSlots(
581
+ chainId: number,
582
+ token: string,
583
+ ): Promise<TokenStorageSlots> {
584
+ const normalizedToken = token.toLowerCase();
585
+
586
+ if (normalizedToken === ETHER_ADDRESS) {
587
+ throw new Error('Cannot provide storage slots for native token');
588
+ }
589
+
590
+ // check cache
591
+ const cachedSlots = await TokenStorageSlotsCache.getTokenStorageSlots(
592
+ chainId,
593
+ normalizedToken,
594
+ );
595
+
596
+ // return if cached
597
+ if (cachedSlots) {
598
+ return cachedSlots;
599
+ }
600
+
601
+ // find the slots
602
+ const [balanceSlot, allowanceSlot] = await Promise.all([
603
+ this.findTokenBalanceOfSlot(chainId, token),
604
+ this.findTokenAllowanceSlot(chainId, token),
605
+ ]);
606
+
607
+ // save the slots and return
608
+ const slots: TokenStorageSlots = {
609
+ balanceSlot: balanceSlot.slot,
610
+ allowanceSlot: allowanceSlot.slot,
611
+ isVyper: balanceSlot.isVyper,
612
+ };
613
+
614
+ // no need to await
615
+ void TokenStorageSlotsCache.setTokenStorageSlots(chainId, token, slots);
616
+
617
+ return slots;
618
+ }
619
+
620
+ /**
621
+ * Adds native balance override to an existing `StateOverride` object
622
+ * @param stateOverride object to add the override to
623
+ * @param account address to be given the balance
624
+ * @param amount token amount in wei
625
+ */
626
+ addBalanceOverride(
627
+ stateOverride: StateOverride,
628
+ account: string,
629
+ amount: bigint,
630
+ ): void {
631
+ // add the balance override
632
+ stateOverride[account] ||= {};
633
+ stateOverride[account].balance = amount.toString();
634
+ }
635
+
636
+ /**
637
+ * Adds token balance override to an existing `StateOverride` object
638
+ * @param stateOverride object to add the override to
639
+ * @param chainId token chain ID
640
+ * @param token token address
641
+ * @param account address to be given the balance
642
+ * @param amount token amount in wei
643
+ */
644
+ async addTokenBalanceOverride(
645
+ stateOverride: StateOverride,
646
+ chainId: number,
647
+ token: string,
648
+ account: string,
649
+ amount: bigint,
650
+ ): Promise<void> {
651
+ // get mapping slots
652
+ const tokenSlots = await this.getTokenStorageSlots(chainId, token);
653
+ // calculate balance slot
654
+ const slotToOverride = this.calculateAddressBalanceSlot(
655
+ tokenSlots.balanceSlot,
656
+ account,
657
+ tokenSlots.isVyper,
658
+ );
659
+ // add the balance override
660
+ stateOverride[token] ||= {};
661
+ stateOverride[token].storage ||= {};
662
+ stateOverride[token].storage[slotToOverride] =
663
+ ethers.utils.defaultAbiCoder.encode(['uint'], [amount]);
664
+ }
665
+
666
+ /**
667
+ * Adds token allowance override to an existing `StateOverride` object
668
+ * @param stateOverride object to add the override to
669
+ * @param chainId token chain ID
670
+ * @param token token address
671
+ * @param account owner address
672
+ * @param spender spender address
673
+ * @param amount token amount in wei
674
+ */
675
+ async addAllowanceOverride(
676
+ stateOverride: StateOverride,
677
+ chainId: number,
678
+ token: string,
679
+ account: string,
680
+ spender: string,
681
+ amount: bigint,
682
+ ): Promise<void> {
683
+ // get mapping slots
684
+ const tokenSlots = await this.getTokenStorageSlots(chainId, token);
685
+ // calculate allowance slot
686
+ const slotToOverride = this.calculateAddressAllowanceSlot(
687
+ tokenSlots.allowanceSlot,
688
+ account,
689
+ spender,
690
+ tokenSlots.isVyper,
287
691
  );
692
+ // add the allowance override
693
+ stateOverride[token] ||= {};
694
+ stateOverride[token].storage ||= {};
695
+ stateOverride[token].storage[slotToOverride] =
696
+ ethers.utils.defaultAbiCoder.encode(['uint'], [amount]);
288
697
  }
289
698
  }