Xswap Smart Order Router
This repository contains routing logic for the Xswap V3 protocol.
It searches for the most efficient way to swap token A for token B, considering splitting swaps across multiple routes and gas costs.
Testing
Unit Tests
First make sure you have run npm install
and npm run build
.
npm run test
Integration Tests
Make sure the .env
file is configured to connect to mainnet and other chains. See the CLI section below for more details.
npm run integ-test
Tenderly Simulations
Quotes can be simulated on Tenderly
Ensure you set the following environment variables:
process.env.TENDERLY_BASE_URL!,
process.env.TENDERLY_USER!,
process.env.TENDERLY_PROJECT!,
process.env.TENDERLY_ACCESS_KEY!,
CLI
The package can be run as a CLI for testing purposes.
First create a .env
file in the root of the project and configure:
JSON_RPC_PROVIDER = '<JSON_RPC_PROVIDER>'
To run on chains other than mainnet set up a connection by specifying the environment variable
JSON_RPC_PROVIDER_ROPSTEN = '<JSON_RPC_PROVIDER>'
JSON_RPC_PROVIDER_RINKEBY = '<JSON_RPC_PROVIDER>'
JSON_RPC_PROVIDER_GORLI = '<JSON_RPC_PROVIDER>'
JSON_RPC_PROVIDER_KOVAN = '<JSON_RPC_PROVIDER>'
JSON_RPC_PROVIDER_OPTIMISM = '<JSON_RPC_PROVIDER>'
JSON_RPC_PROVIDER_OPTIMISM_GOERLI = '<JSON_RPC_PROVIDER>'
JSON_RPC_PROVIDER_OPTIMISTIC_KOVAN = '<JSON_RPC_PROVIDER>'
JSON_RPC_PROVIDER_ARBITRUM_ONE = '<JSON_RPC_PROVIDER>'
JSON_RPC_PROVIDER_ARBITRUM_RINKEBY = '<JSON_RPC_PROVIDER>'
JSON_RPC_PROVIDER_ARBITRUM_GOERLI = '<JSON_RPC_PROVIDER>'
JSON_RPC_PROVIDER_POLYGON = '<JSON_RPC_PROVIDER>'
JSON_RPC_PROVIDER_POLYGON_MUMBAI = '<JSON_RPC_PROVIDER>'
JSON_RPC_PROVIDER_CELO = '<JSON_RPC_PROVIDER>'
JSON_RPC_PROVIDER_CELO_ALFAJORES = '<JSON_RPC_PROVIDER>'
JSON_RPC_PROVIDER_BSC = '<JSON_RPC_PROVIDER>'
Then from the root directory you can execute the CLI.
Examples
Some examples to use for manual CLI testing.
Mainnet
./bin/cli quote --tokenIn 0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48 --tokenOut 0x1f9840a85d5af5bf1d1762f925bdaddc4201f984 --amount 1000 --exactIn --recipient 0xAb5801a7D398351b8bE11C439e05C5B3259aeC9B --protocols v2,v3
Best Route:
100.00% = USDC -- 0.3% --> UNI
Raw Quote Out:
35.72
Gas Adjusted Quote Out:
34.03
Gas Used Quote Token: 1.691772
Gas Used USD: 47.592951
Calldata: 0x414bf389000000000000...
Value: 0x00
blockNumber: "13088815"
estimatedGasUsed: "113000"
gasPriceWei: "130000000000"
./bin/cli quote-to-ratio --token0 0xa0b86991c6218b36c1d19d4a2e9eb0ce3606eb48 --token1 0xdac17f958d2ee523a2206206994597c13d831ec7 --feeAmount 3000 --recipient 0xAb5801a7D398351b8bE11C439e05C5B3259aeC9B --token0Balance 1000 --token1Balance 2000 --tickLower -120 --tickUpper 120
Best Route:
100.00% = USDT -- 0.05% --> USDC
Raw Quote Exact In:
392.68
Gas Adjusted Quote In}:
346.13
Gas Used Quote Token: 46.550010
Gas Used USD: 46.342899
Calldata: 0x414bf389000000000000000000000000dac17f958d2ee523a2206206994597c13d831ec7000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb4800000000000000000000000000000000000000000000000000000000000001f4000000000000000000000000ab5801a7d398351b8be11c439e05c5b3259aec9b000000000000000000000000000000000000000000000000000000000000006400000000000000000000000000000000000000000000000000000000176a736c000000000000000000000000000000000000000000000000000000001764f8650000000000000000000000000000000000000000000000000000000000000000
Value: 0x00
blockNumber: "13239188"
estimatedGasUsed: "113000"
gasPriceWei: "116690684398"
./bin/cli quote --tokenIn 0x0391D2021f89DC339F60Fff84546EA23E337750f --tokenOut 0x4d224452801ACEd8B2F0aebE155379bb5D594381 --amount 10000 --exactIn --recipient 0xAb5801a7D398351b8bE11C439e05C5B3259aeC9B --protocols v2,v3,mixed
Best Route:
[V2 + V3] 100.00% = BOND -- [0x6591c4BcD6D7A1eb4E537DA8B78676C1576Ba244] --> USDC -- 0.3% [0xB07Fe2F407F971125D4EB1977f8aCEe8846C7324] --> APE
Raw Quote Exact In:
10437.85
Gas Adjusted Quote In:
10433.83
Gas Used Quote Token: 4.018625
Gas Used USD: 29.669402
Calldata: 0x5ae401dc0000000000000000000000000000000000000000000000000000000000000064000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000016000000000000000000000000000000000000000000000000000000000000000e4472b43f300000000000000000000000000000000000000000000021e19e0c9bab240000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000020000000000000000000000000391d2021f89dc339f60fff84546ea23e337750f000000000000000000000000a0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000104b858183f00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000080000000000000000000000000ab5801a7d398351b8be11c439e05c5b3259aec9b00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002358df5b3b4459a3f5b000000000000000000000000000000000000000000000000000000000000002ba0b86991c6218b36c1d19d4a2e9eb0ce3606eb48000bb84d224452801aced8b2f0aebe155379bb5d59438100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
Value: 0x00
blockNumber: "15303839"
estimatedGasUsed: "434000"
gasPriceWei: "38218865879"
Total ticks crossed: 7
XDC Mainnet
XSP
./bin/cli quote --tokenIn 0x36726235dAdbdb4658D33E62a249dCA7c4B2bC68 --tokenOut 0xD4B5f10D61916Bd6E0860144a91Ac658dE8a1437 --amount 1000 --exactIn --minSplits 1 --protocols v2,v3,mixed --router alpha --chainId 50
SRX - USDT
./bin/cli quote --tokenIn 0x5d5f074837f5d4618b3916ba74de1bf9662a3fed --tokenOut 0xD4B5f10D61916Bd6E0860144a91Ac658dE8a1437 --amount 1000 --exactIn --minSplits 1 --protocols v2 --router alpha --chainId 50
SRX - WXDC
./bin/cli quote --tokenIn 0x5d5f074837f5d4618b3916ba74de1bf9662a3fed --tokenOut 0x951857744785e80e2de051c32ee7b25f9c458c42 --amount 1000 --exactIn --minSplits 1 --protocols v2,v3,mixed --router alpha --chainId 50
Adding a new Chain
The main components to complete are:
- Deploy contracts on chain, add the pools to subgraph
- Populate v3 providers in
src/providers/v3/subgraph-provider
andsrc/providers/v3/static-subgraph-provider
- Populate chainId and addresses in
src/util/chains.ts
andsrc/util/addresses.ts
- Populate token providers in
src/providers/caching-token-provider
andsrc/providers/token-provider.ts
- Populate gas constants in
src/routers/alpha-router/gas-models/*
- Populate bases in
src/routers/legacy-router/bases.ts
- Populate
test/integ/routers/alpha-router/alpha-router.integration.test.ts
andsrc/providers/v2/static-subgraph-provider.ts
- Populate
src/routers/alpha-router/*
- Add a log to
/CHANGELOG.md
- Run
npm run integ-test
successfully
Troubleshooting
ProviderGasLimit errors
The package sends many large multicall requests to nodes. You must ensure that your node provider's eth_call
gas limit is high enough to succesfully process the RPC calls.
By default each eth_call
will consume up to:
- 132,000,000 gas on Optimism
- 120,000,000 gas on Arbitrum
- 50,000,000 gas on Celo
- 150,000,000 gas on every other network (Mainnet, Goerli, etc.)
These parameters should work on Infura and Alchemy by default.
This total amount of gas each eth_call
can consume is equal to the multicallChunk
config value multiplied by the gasLimitPerCall
config value. If you are using a node provider with a lower gas limit per eth_call
you will need to override the default V3QuoteProvider
with an instance that lowers the multicallChunk
and gasLimitPerCall
parameters such that the multiplication is below your node providers limit. Lowering these values will cause each multicall to consume less gas. See here for examples of how to set these values. Note some providers have different limits per chain.
If you are running your own node, we recommend you configure start your node with a higher gas limit per call. For example, on Geth you can use the command line argument --rpc.gascap 150000000
to raise the limit to 150m, which is enough to run the default configuration of this package.
If you are using Hardhat mainnet forking, you should add blockGasLimit: 150_000_000
to your Hardhat config to use the default package configuration.
TODO
- Check default gas limit for XDC
- add v2 against
node version 15