@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.
- package/.eslintrc.js +8 -0
- package/build/abi/Aave_GSM.json +751 -0
- package/build/abi/Balancer.json +257 -0
- package/build/abi/BalancerV2.json +1179 -0
- package/build/abi/RamsesV2Pool.abi.json +1554 -0
- package/build/abi/RamsesV2Quoter.abi.json +274 -0
- package/build/abi/USDM.json +807 -0
- package/build/abi/UniswapV2Router.json +397 -0
- package/build/abi/{wombat/pool.json → angle-transmuter/ChainlinkAccessControlledOffchainAggregator.json} +594 -637
- package/build/abi/angle-transmuter/ChainlinkEACAggregatorProxy.json +509 -0
- package/build/abi/curve-v1/CurveBUSDv2.abi.json +1356 -0
- package/build/abi/curve-v1/CurveTokenV1.json +305 -0
- package/build/abi/curve-v1/CurveTokenV2.json +318 -0
- package/build/abi/curve-v1/CurveV1StableNg.json +1452 -0
- package/build/abi/curve-v1/CurveV2Swap.json +700 -0
- package/build/abi/curve-v1/FactoryCryptoRegistry.json +316 -0
- package/build/abi/curve-v1/FactoryRegistry.json +508 -0
- package/build/abi/curve-v1/StableSwapAave.json +1152 -0
- package/build/abi/curve-v1/StableSwapBUSD.json +814 -0
- package/build/abi/curve-v1/StableSwapCompound.json +814 -0
- package/build/abi/curve-v1/StableSwapIDLE.json +1253 -0
- package/build/abi/curve-v1/StableSwapPax.json +865 -0
- package/build/abi/curve-v1/StableSwapSnow.json +900 -0
- package/build/abi/curve-v1/StableSwapUSDN.json +1004 -0
- package/build/abi/curve-v1/StableSwapUSDT.json +814 -0
- package/build/abi/curve-v1/StableSwapY.json +814 -0
- package/build/abi/inception/inception-ineth.json +609 -0
- package/build/abi/kyberdmm/kyber-storage.abi.json +824 -0
- package/build/abi/kyberdmm.abi.json +1148 -0
- package/build/abi/maverick-v2/MaverickV2Quoter.json +278 -0
- package/build/abi/nerve/nerve-metapool.json +790 -0
- package/build/abi/uniswap-v3/UniswapV3Quoter.abi.json +193 -0
- package/build/abi/velodrome-slipstream/VelodromeSlipstreamQuoterV2.abi.json +267 -0
- package/build/dex/aave-v1/aave-v1.js +0 -1
- package/build/dex/aave-v1/aave-v1.js.map +1 -1
- package/build/dex/balancer-v1/balancer-pools.json +33333 -0
- package/build/dex/bebop/websocket-fetcher.d.ts +35 -0
- package/build/dex/bebop/websocket-fetcher.js +87 -0
- package/build/dex/bebop/websocket-fetcher.js.map +1 -0
- package/build/dex/idle-dao/idle-dao-pool.d.ts +56 -0
- package/build/dex/idle-dao/idle-dao-pool.js +176 -0
- package/build/dex/idle-dao/idle-dao-pool.js.map +1 -0
- package/build/dex/idle-dao/idle-dao-pooling-pool.d.ts +16 -0
- package/build/dex/idle-dao/idle-dao-pooling-pool.js +57 -0
- package/build/dex/idle-dao/idle-dao-pooling-pool.js.map +1 -0
- package/build/dex/idle-dao/scripts.d.ts +9 -0
- package/build/dex/idle-dao/scripts.js +552 -0
- package/build/dex/idle-dao/scripts.js.map +1 -0
- package/build/dex/inception/inception-event-pool.d.ts +4 -4
- package/build/dex/inception/inception-event-pool.js +9 -7
- package/build/dex/inception/inception-event-pool.js.map +1 -1
- package/build/dex/inception/inception-native.d.ts +43 -0
- package/build/dex/inception/inception-native.js +131 -0
- package/build/dex/inception/inception-native.js.map +1 -0
- package/build/dex/inception/inception-pool.d.ts +18 -0
- package/build/dex/inception/inception-pool.js +32 -0
- package/build/dex/inception/inception-pool.js.map +1 -0
- package/build/dex/inception/inception-price-feed.d.ts +19 -0
- package/build/dex/inception/inception-price-feed.js +51 -0
- package/build/dex/inception/inception-price-feed.js.map +1 -0
- package/build/dex/inception/inception.d.ts +6 -6
- package/build/dex/inception/inception.js +40 -16
- package/build/dex/inception/inception.js.map +1 -1
- package/build/dex/inception/utils.d.ts +0 -1
- package/build/dex/inception/utils.js +1 -22
- package/build/dex/inception/utils.js.map +1 -1
- package/build/dex/platypus/platypus.js +3 -17
- package/build/dex/platypus/platypus.js.map +1 -1
- package/build/dex/swaap-v1/swaap-v1.js +0 -4
- package/build/dex/swaap-v1/swaap-v1.js.map +1 -1
- package/build/dex/uniswap-v2/config.js +8 -0
- package/build/dex/uniswap-v2/config.js.map +1 -1
- package/build/dex/uniswap-v3/config.js +2 -1
- package/build/dex/uniswap-v3/config.js.map +1 -1
- package/build/executor/fixtures/executor01/exchange-params/price-route-multiswap-balancerv1-curvev1-eth-usdc-gusd.json +16 -0
- package/build/executor/fixtures/executor01/exchange-params/price-route-multiswap-balancerv1-sushiv3-wbtc-eth-sushi.json +16 -0
- package/build/executor/fixtures/executor01/exchange-params/price-route-multiswap-sushiv3-curvev1-eth-usdc-gusd.json +16 -0
- package/build/executor/fixtures/executor01/exchange-params/price-route-multiswap-sushiv3-curvev1-gusd-usdc-eth.json +16 -0
- package/build/executor/fixtures/executor01/exchange-params/price-route-multiswap-sushiv3-dai-usdc-eth.json +16 -0
- package/build/executor/fixtures/executor01/exchange-params/price-route-multiswap-sushiv3-eth-usdc-dai.json +16 -0
- package/build/executor/fixtures/executor01/exchange-params/price-route-multiswap-sushiv3-usdc-eth-wbtc.json +16 -0
- package/build/executor/fixtures/executor01/exchange-params/price-route-multiswap-sushiv3-usdt-usdc-dai.json +16 -0
- package/build/executor/fixtures/executor01/exchange-params/price-route-simpleSwap-balancerv1-eth-usdc.json +9 -0
- package/build/executor/fixtures/executor01/exchange-params/price-route-simpleSwap-balancerv1-usdc-eth.json +9 -0
- package/build/executor/fixtures/executor01/exchange-params/price-route-simpleSwap-balancerv1-usdc-wbtc.json +9 -0
- package/build/executor/fixtures/executor01/exchange-params/price-route-simpleSwap-curvev1-eth-steth.json +9 -0
- package/build/executor/fixtures/executor01/exchange-params/price-route-simpleSwap-curvev1-steth-eth.json +9 -0
- package/build/executor/fixtures/executor01/exchange-params/price-route-simpleSwap-curvev1-usdc-usdt.json +9 -0
- package/build/executor/fixtures/executor01/exchange-params/price-route-simpleSwap-univ3-eth-usdc.json +9 -0
- package/build/executor/fixtures/executor01/exchange-params/price-route-simpleSwap-univ3-usdc-eth.json +9 -0
- package/build/executor/fixtures/executor01/exchange-params/price-route-simpleSwap-univ3-usdc-usdt.json +9 -0
- package/build/executor/fixtures/executor01/maybe-weth-calldata/price-route-multiswap-balancerv1-sushiv3-wbtc-eth-sushi.json +12 -0
- package/build/executor/fixtures/executor01/maybe-weth-calldata/price-route-multiswap-sushiv3-curvev1-eth-usdc-gusd.json +7 -0
- package/build/executor/fixtures/executor01/maybe-weth-calldata/price-route-multiswap-sushiv3-curvev1-gusd-usdc-eth.json +7 -0
- package/build/executor/fixtures/executor01/maybe-weth-calldata/price-route-multiswap-sushiv3-dai-usdc-eth.json +7 -0
- package/build/executor/fixtures/executor01/maybe-weth-calldata/price-route-multiswap-sushiv3-eth-usdc-dai.json +7 -0
- package/build/executor/fixtures/executor01/maybe-weth-calldata/price-route-multiswap-sushiv3-usdc-eth-wbtc.json +12 -0
- package/build/executor/fixtures/executor01/maybe-weth-calldata/price-route-simpleSwap-univ3-eth-usdc.json +7 -0
- package/build/executor/fixtures/executor01/maybe-weth-calldata/price-route-simpleSwap-univ3-usdc-eth.json +7 -0
- package/build/executor/fixtures/executor01/routes/price-route-multiswap-balancerv1-curvev1-eth-usdc-gusd.json +78 -0
- package/build/executor/fixtures/executor01/routes/price-route-multiswap-balancerv1-sushiv3-wbtc-eth-sushi.json +81 -0
- package/build/executor/fixtures/executor01/routes/price-route-multiswap-sushiv3-curvev1-eth-usdc-gusd.json +78 -0
- package/build/executor/fixtures/executor01/routes/price-route-multiswap-sushiv3-curvev1-gusd-usdc-eth.json +78 -0
- package/build/executor/fixtures/executor01/routes/price-route-multiswap-sushiv3-dai-usdc-eth.json +81 -0
- package/build/executor/fixtures/executor01/routes/price-route-multiswap-sushiv3-eth-usdc-dai.json +81 -0
- package/build/executor/fixtures/executor01/routes/price-route-multiswap-sushiv3-usdc-eth-wbtc.json +81 -0
- package/build/executor/fixtures/executor01/routes/price-route-multiswap-sushiv3-usdt-usdc-dai.json +81 -0
- package/build/executor/fixtures/executor01/routes/price-route-simpleSwap-balancerv1-eth-usdc.json +64 -0
- package/build/executor/fixtures/executor01/routes/price-route-simpleSwap-balancerv1-usdc-eth.json +85 -0
- package/build/executor/fixtures/executor01/routes/price-route-simpleSwap-balancerv1-usdc-wbtc.json +64 -0
- package/build/executor/fixtures/executor01/routes/price-route-simpleSwap-curvev1-eth-steth.json +52 -0
- package/build/executor/fixtures/executor01/routes/price-route-simpleSwap-curvev1-steth-eth.json +52 -0
- package/build/executor/fixtures/executor01/routes/price-route-simpleSwap-curvev1-usdc-usdt.json +52 -0
- package/build/executor/fixtures/executor01/routes/price-route-simpleSwap-univ3-eth-usdc.json +55 -0
- package/build/executor/fixtures/executor01/routes/price-route-simpleSwap-univ3-usdc-eth.json +55 -0
- package/build/executor/fixtures/executor01/routes/price-route-simpleSwap-univ3-usdc-usdt.json +55 -0
- package/build/executor/fixtures/executor02/exchange-params/price-route-multiSwap-balancerv1-sushiv3-univ3-bal-eth-sushi.json +23 -0
- package/build/executor/fixtures/executor02/exchange-params/price-route-multiSwap-maverickv1-sushiv3-univ3-eth-usdc-mav.json +37 -0
- package/build/executor/fixtures/executor02/exchange-params/price-route-multiSwap-univ3-sushiv3-sushi-eth-wbtc.json +23 -0
- package/build/executor/fixtures/executor02/exchange-params/price-route-multiSwap-univ3-sushiv3-wbtc-eth-sushi.json +23 -0
- package/build/executor/fixtures/executor02/exchange-params/price-route-multiswap-curvev1-univ3-dai-usdc-eth.json +51 -0
- package/build/executor/fixtures/executor02/exchange-params/price-route-multiswap-univ3-usdt-dai-eth.json +58 -0
- package/build/executor/fixtures/executor02/exchange-params/price-route-simpleSwap-sushiv3-balancerv1-eth-usdc.json +23 -0
- package/build/executor/fixtures/executor02/exchange-params/price-route-simpleSwap-sushiv3-balancerv1-usdc-eth.json +23 -0
- package/build/executor/fixtures/executor02/exchange-params/price-route-simpleSwap-sushiv3-univ3-eth-sushi.json +9 -0
- package/build/executor/fixtures/executor02/exchange-params/price-route-simpleSwap-sushiv3-univ3-sushi-eth.json +16 -0
- package/build/executor/fixtures/executor02/exchange-params/price-route-simpleSwap-univ3-curvev1-usdt-dai.json +23 -0
- package/build/executor/fixtures/executor02/maybe-weth-calldata/price-route-multiSwap-balancerv1-sushiv3-univ3-bal-eth-sushi.json +12 -0
- package/build/executor/fixtures/executor02/maybe-weth-calldata/price-route-multiSwap-maverickv1-sushiv3-univ3-eth-usdc-mav.json +7 -0
- package/build/executor/fixtures/executor02/maybe-weth-calldata/price-route-multiSwap-univ3-sushiv3-sushi-eth-wbtc.json +12 -0
- package/build/executor/fixtures/executor02/maybe-weth-calldata/price-route-multiSwap-univ3-sushiv3-wbtc-eth-sushi.json +12 -0
- package/build/executor/fixtures/executor02/maybe-weth-calldata/price-route-multiswap-curvev1-univ3-dai-usdc-eth.json +7 -0
- package/build/executor/fixtures/executor02/maybe-weth-calldata/price-route-multiswap-univ3-usdt-dai-eth.json +7 -0
- package/build/executor/fixtures/executor02/maybe-weth-calldata/price-route-simpleSwap-sushiv3-balancerv1-eth-usdc.json +7 -0
- package/build/executor/fixtures/executor02/maybe-weth-calldata/price-route-simpleSwap-sushiv3-balancerv1-usdc-eth.json +7 -0
- package/build/executor/fixtures/executor02/maybe-weth-calldata/price-route-simpleSwap-sushiv3-univ3-eth-sushi.json +7 -0
- package/build/executor/fixtures/executor02/maybe-weth-calldata/price-route-simpleSwap-sushiv3-univ3-sushi-eth.json +7 -0
- package/build/executor/fixtures/executor02/routes/price-route-multiSwap-balancerv1-sushiv3-univ3-bal-eth-sushi.json +130 -0
- package/build/executor/fixtures/executor02/routes/price-route-multiSwap-maverickv1-sushiv3-univ3-eth-usdc-mav.json +136 -0
- package/build/executor/fixtures/executor02/routes/price-route-multiSwap-univ3-sushiv3-sushi-eth-wbtc.json +100 -0
- package/build/executor/fixtures/executor02/routes/price-route-multiSwap-univ3-sushiv3-wbtc-eth-sushi.json +100 -0
- package/build/executor/fixtures/executor02/routes/price-route-multiswap-curvev1-univ3-dai-usdc-eth.json +166 -0
- package/build/executor/fixtures/executor02/routes/price-route-multiswap-univ3-usdt-dai-eth.json +190 -0
- package/build/executor/fixtures/executor02/routes/price-route-simpleSwap-sushiv3-balancerv1-eth-usdc.json +114 -0
- package/build/executor/fixtures/executor02/routes/price-route-simpleSwap-sushiv3-balancerv1-usdc-eth.json +114 -0
- package/build/executor/fixtures/executor02/routes/price-route-simpleSwap-sushiv3-univ3-eth-sushi.json +55 -0
- package/build/executor/fixtures/executor02/routes/price-route-simpleSwap-sushiv3-univ3-sushi-eth.json +73 -0
- package/build/executor/fixtures/executor02/routes/price-route-simpleSwap-univ3-curvev1-usdt-dai.json +82 -0
- package/package.json +1 -1
- package/src/dex/generic-rfq/example-api.test.ts +12 -1
- package/src/dex/generic-rfq/generic-rfq-e2e.test.ts +5 -47
- package/src/dex/generic-rfq/generic-rfq-local-e2e.test.ts +8 -22
- package/src/dex/uniswap-v2/config.ts +9 -0
- package/src/dex/uniswap-v2/uniswap-v2-e2e-avalanche.test.ts +105 -1
- package/src/dex/uniswap-v3/config.ts +2 -1
- package/tests/constants-e2e.ts +7 -53
- package/tests/{tenderly-simulation-new.test.ts → tenderly-simulation.test.ts} +2 -2
- package/tests/tenderly-simulation.ts +650 -241
- package/tests/token-storage-slots.json +166 -0
- package/tests/utils-e2e.ts +198 -712
- package/tests/v6/utils-e2e-v6.ts +60 -134
- package/.vscode/launch.json +0 -53
- package/.vscode/settings.json +0 -2
- package/.vscode/tasks.json +0 -15
- package/build/abi/uniswap-v3/AlienBaseV3Router.abi.json +0 -52
- package/build/abi/uniswap-v4/quoter.abi.json +0 -461
- package/build/abi/uniswap-v4/router.abi.json +0 -230
- package/build/abi/usual-m-smart-m/usualM.abi.json +0 -483
- package/build/dex/aave-v2/tokens-avalanche.json +0 -44
- package/build/dex/aave-v2/tokens-mainnet.json +0 -188
- package/build/dex/aave-v2/tokens-polygon.json +0 -44
- package/build/dex/bProtocol.d.ts +0 -18
- package/build/dex/bProtocol.js +0 -39
- package/build/dex/bProtocol.js.map +0 -1
- package/build/dex/balancer-v3/abi/balancerBatchRouter.d.ts +0 -729
- package/build/dex/balancer-v3/abi/balancerBatchRouter.js +0 -732
- package/build/dex/balancer-v3/abi/balancerBatchRouter.js.map +0 -1
- package/build/dex/balancer-v3/abi/balancerRouter.d.ts +0 -1406
- package/build/dex/balancer-v3/abi/balancerRouter.js +0 -1175
- package/build/dex/balancer-v3/abi/balancerRouter.js.map +0 -1
- package/build/dex/balancer-v3/abi/vaultExtension.V3.d.ts +0 -2081
- package/build/dex/balancer-v3/abi/vaultExtension.V3.js +0 -1851
- package/build/dex/balancer-v3/abi/vaultExtension.V3.js.map +0 -1
- package/build/dex/balancer-v3/balancer-v3-sepolia-pools.d.ts +0 -34
- package/build/dex/balancer-v3/balancer-v3-sepolia-pools.js +0 -406
- package/build/dex/balancer-v3/balancer-v3-sepolia-pools.js.map +0 -1
- package/build/dex/bancor.d.ts +0 -26
- package/build/dex/bancor.js +0 -58
- package/build/dex/bancor.js.map +0 -1
- package/build/dex/compound.d.ts +0 -18
- package/build/dex/compound.js +0 -46
- package/build/dex/compound.js.map +0 -1
- package/build/dex/curve-v2.d.ts +0 -58
- package/build/dex/curve-v2.js +0 -180
- package/build/dex/curve-v2.js.map +0 -1
- package/build/dex/dodo-v1.d.ts +0 -33
- package/build/dex/dodo-v1.js +0 -63
- package/build/dex/dodo-v1.js.map +0 -1
- package/build/dex/erc4626/scripts/validate-state.d.ts +0 -0
- package/build/dex/erc4626/scripts/validate-state.js +0 -146
- package/build/dex/erc4626/scripts/validate-state.js.map +0 -1
- package/build/dex/lido.d.ts +0 -19
- package/build/dex/lido.js +0 -42
- package/build/dex/lido.js.map +0 -1
- package/build/dex/maker-psm/scripts/gem.abi.json +0 -136
- package/build/dex/maker-psm/scripts/validate-state.d.ts +0 -0
- package/build/dex/maker-psm/scripts/validate-state.js +0 -185
- package/build/dex/maker-psm/scripts/validate-state.js.map +0 -1
- package/build/dex/maker-psm/scripts/vat.abi.json +0 -243
- package/build/dex/onebit.d.ts +0 -25
- package/build/dex/onebit.js +0 -42
- package/build/dex/onebit.js.map +0 -1
- package/build/dex/smoothy.d.ts +0 -26
- package/build/dex/smoothy.js +0 -48
- package/build/dex/smoothy.js.map +0 -1
- package/build/dex/solidly-v3/scripts/check-event-pool-event.d.ts +0 -1
- package/build/dex/solidly-v3/scripts/check-event-pool-event.js +0 -53
- package/build/dex/solidly-v3/scripts/check-event-pool-event.js.map +0 -1
- package/build/dex/stable-pool.d.ts +0 -28
- package/build/dex/stable-pool.js +0 -55
- package/build/dex/stable-pool.js.map +0 -1
- package/build/dex/trader-joe-v2.1/trader-joe-v2.1-new.d.ts +0 -7
- package/build/dex/trader-joe-v2.1/trader-joe-v2.1-new.js +0 -20
- package/build/dex/trader-joe-v2.1/trader-joe-v2.1-new.js.map +0 -1
- package/build/dex/trader-joe-v2.1.d.ts +0 -43
- package/build/dex/trader-joe-v2.1.js +0 -79
- package/build/dex/trader-joe-v2.1.js.map +0 -1
- package/build/dex/uniswap-v3/forks/alien-base-v3/alien-base-v3.d.ts +0 -17
- package/build/dex/uniswap-v3/forks/alien-base-v3/alien-base-v3.js +0 -64
- package/build/dex/uniswap-v3/forks/alien-base-v3/alien-base-v3.js.map +0 -1
- package/build/dex/uniswap-v3/forks/alien-v3/alien-v3.d.ts +0 -17
- package/build/dex/uniswap-v3/forks/alien-v3/alien-v3.js +0 -79
- package/build/dex/uniswap-v3/forks/alien-v3/alien-v3.js.map +0 -1
- package/build/dex/uniswap-v3/uniswap-v3-pricing.d.ts +0 -4
- package/build/dex/uniswap-v3/uniswap-v3-pricing.js +0 -43
- package/build/dex/uniswap-v3/uniswap-v3-pricing.js.map +0 -1
- package/build/dex/uniswap-v3/uniswap-v3-worker.d.ts +0 -1
- package/build/dex/uniswap-v3/uniswap-v3-worker.js +0 -10
- package/build/dex/uniswap-v3/uniswap-v3-worker.js.map +0 -1
- package/build/dex/uniswap-v4/config.d.ts +0 -3
- package/build/dex/uniswap-v4/config.js +0 -15
- package/build/dex/uniswap-v4/config.js.map +0 -1
- package/build/dex/uniswap-v4/encoder.d.ts +0 -16
- package/build/dex/uniswap-v4/encoder.js +0 -94
- package/build/dex/uniswap-v4/encoder.js.map +0 -1
- package/build/dex/uniswap-v4/types.d.ts +0 -30
- package/build/dex/uniswap-v4/types.js +0 -3
- package/build/dex/uniswap-v4/types.js.map +0 -1
- package/build/dex/uniswap-v4/uniswap-v4.d.ts +0 -38
- package/build/dex/uniswap-v4/uniswap-v4.js +0 -187
- package/build/dex/uniswap-v4/uniswap-v4.js.map +0 -1
- package/build/dex/usual/usual-m-smart-m.d.ts +0 -17
- package/build/dex/usual/usual-m-smart-m.js +0 -50
- package/build/dex/usual/usual-m-smart-m.js.map +0 -1
- package/build/dex/usual-m-smart-m/config.d.ts +0 -3
- package/build/dex/usual-m-smart-m/config.js +0 -13
- package/build/dex/usual-m-smart-m/config.js.map +0 -1
- package/build/dex/usual-m-smart-m/types.d.ts +0 -7
- package/build/dex/usual-m-smart-m/types.js +0 -3
- package/build/dex/usual-m-smart-m/types.js.map +0 -1
- package/build/dex/usual-m-smart-m/usual-m-smart-m.d.ts +0 -35
- package/build/dex/usual-m-smart-m/usual-m-smart-m.js +0 -161
- package/build/dex/usual-m-smart-m/usual-m-smart-m.js.map +0 -1
- package/build/dex/usual-m-usd0/config.d.ts +0 -3
- package/build/dex/usual-m-usd0/config.js +0 -14
- package/build/dex/usual-m-usd0/config.js.map +0 -1
- package/build/dex/usual-m-usd0/types.d.ts +0 -8
- package/build/dex/usual-m-usd0/types.js +0 -3
- package/build/dex/usual-m-usd0/types.js.map +0 -1
- package/build/dex/usual-m-usd0/usual-m-usd0.d.ts +0 -35
- package/build/dex/usual-m-usd0/usual-m-usd0.js +0 -159
- package/build/dex/usual-m-usd0/usual-m-usd0.js.map +0 -1
- package/tests/augustus-approvals.test.ts +0 -628
- package/tests/smart-tokens.ts +0 -112
- package/tests/tenderly-simulation-new.ts +0 -698
- package/tests/v6/executors.test.ts +0 -110
- package/tests/v6/price-routes/arbitrum/sell-0.1-ETH-USDC.json +0 -104
- package/tests/v6/price-routes/arbitrum/sell-1_000-ETH-DAI.json +0 -294
- package/tests/v6/price-routes/arbitrum/sell-1_000-WETH-wstETH.json +0 -121
- package/tests/v6/price-routes/arbitrum/sell-1_000_000-ARB-DAI.json +0 -270
- package/tests/v6/price-routes/arbitrum/sell-1_000_000-ARB-ETH.json +0 -326
- package/tests/v6/price-routes/arbitrum/sell-1_000_000-DAI-ARB.json +0 -434
- package/tests/v6/price-routes/arbitrum/sell-250_000-LINK-USDC.json +0 -182
- package/tests/v6/price-routes/arbitrum/sell-3_000-BAL-UNI.json +0 -154
- package/tests/v6/price-routes/avalanche/sell-100_000-WAVAX-USDC.json +0 -315
- package/tests/v6/price-routes/avalanche/sell-40-BTC-AVAX.json +0 -207
- package/tests/v6/price-routes/mainnet/buy-3200-ETH-DAI.json +0 -228
- package/tests/v6/price-routes/mainnet/sell-1-USDC-USDT.json +0 -78
- package/tests/v6/price-routes/mainnet/sell-1-WBTC-BAL.json +0 -158
- package/tests/v6/price-routes/mainnet/sell-100-tBTC-WBTC.json +0 -100
- package/tests/v6/price-routes/mainnet/sell-1000-eth-dai.json +0 -340
- package/tests/v6/price-routes/mainnet/sell-1000-wbtc-eth-uniswapv3-balancerv2.json +0 -162
- package/tests/v6/price-routes/mainnet/sell-100_000-USDC-USDT-2-univ2-pools.json +0 -86
- package/tests/v6/price-routes/mainnet/sell-10_000-ETH-USDC-balancer.json +0 -383
- package/tests/v6/price-routes/mainnet/sell-10_000-ETH-stETH.json +0 -168
- package/tests/v6/price-routes/mainnet/sell-10_000-USDC-USDT-BalancerV2.json +0 -68
- package/tests/v6/price-routes/mainnet/sell-10_000-eth-usdc-uniswapv3-balancerv2.json +0 -348
- package/tests/v6/price-routes/mainnet/sell-1_000-stETH-ETH.json +0 -100
- package/tests/v6/price-routes/mainnet/sell-50-eth-usdc.json +0 -153
- package/tests/v6/price-routes/polygon/sell-100-WBTC-MATIC-1.json +0 -571
- package/tests/v6/price-routes/polygon/sell-100-WBTC-MATIC.json +0 -559
- package/tests/v6/price-routes/polygon/sell-1_000_000-DAI-MATIC-2.json +0 -447
- package/tests/v6/price-routes/polygon/sell-1_000_000-DAI-MATIC-3.json +0 -472
- 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
|
|
8
|
-
import
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
const
|
|
12
|
-
const
|
|
13
|
-
const
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
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
|
-
|
|
36
|
-
|
|
37
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
44
|
-
|
|
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
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
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
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
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
|
-
|
|
177
|
+
TokenStorageSlotsCache.TOKEN_STORAGE_SLOTS ||= {};
|
|
178
|
+
TokenStorageSlotsCache.TOKEN_STORAGE_SLOTS[chainId] ||= {};
|
|
179
|
+
TokenStorageSlotsCache.TOKEN_STORAGE_SLOTS[chainId][token.toLowerCase()] =
|
|
180
|
+
slots;
|
|
84
181
|
|
|
85
|
-
|
|
86
|
-
return this.chainIdToChainNameMap[network];
|
|
182
|
+
void TokenStorageSlotsCache.saveTokenStorageSlots();
|
|
87
183
|
}
|
|
184
|
+
}
|
|
88
185
|
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
186
|
+
export class TenderlySimulator {
|
|
187
|
+
// public constants
|
|
188
|
+
static readonly DEFAULT_OWNER = '0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa';
|
|
189
|
+
static readonly DEFAULT_SPENDER =
|
|
190
|
+
'0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb';
|
|
94
191
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
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
|
-
|
|
102
|
-
|
|
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
|
-
|
|
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
|
-
|
|
118
|
-
|
|
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
|
-
|
|
122
|
-
|
|
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
|
-
|
|
128
|
-
|
|
237
|
+
return simulation;
|
|
238
|
+
}
|
|
129
239
|
|
|
240
|
+
public async getSimulatedTransactionDetails(
|
|
241
|
+
id: string,
|
|
242
|
+
): Promise<SimulatedTransactionDetails | null> {
|
|
130
243
|
try {
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
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
|
-
|
|
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(
|
|
169
|
-
|
|
252
|
+
console.error(e);
|
|
253
|
+
return null;
|
|
170
254
|
}
|
|
171
255
|
}
|
|
172
256
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
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
|
-
|
|
190
|
-
|
|
191
|
-
|
|
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
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
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
|
-
|
|
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
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
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
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
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
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
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
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
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
|
}
|