{"_id":"@aborean/universal-router","name":"@aborean/universal-router","dist-tags":{"latest":"1.6.0"},"versions":{"1.6.0":{"name":"@aborean/universal-router","description":"Smart contracts for Universal Router","license":"GPL-2.0-or-later","publishConfig":{"access":"public"},"version":"1.6.0","keywords":["uniswap","router","universal router","swap router"],"repository":{"type":"git","url":"git+https://github.com/Uniswap/universal-router.git"},"engines":{"node":">=14"},"dependencies":{"@aborean/v2-core":"1.0.1","@aborean/v3-core":"1.0.0","@openzeppelin/contracts":"4.7.0"},"devDependencies":{"@nomicfoundation/hardhat-chai-matchers":"1.0.4","@nomiclabs/hardhat-ethers":"^2.2.2","@typechain/ethers-v5":"^4.0.0","@types/chai":"^4.2.6","@types/mocha":"^5.2.7","@aborean/router-sdk":"^1.3.0","@aborean/sdk-core":"^3.0.1","@uniswap/snapshot-gas-cost":"^1.0.0","@aborean/v2-sdk":"^3.0.1","@uniswap/v3-sdk":"^3.8.3","bignumber.js":"^9.0.0","chai":"^4.3.4","ethers":"^5.7.2","hardhat":"2.12.2","hardhat-typechain":"^0.3.5","mocha-chai-jest-snapshot":"^1.1.0","prettier":"^2.0.5","prettier-plugin-solidity":"^1.0.0-alpha.59","ts-generator":"^0.1.1","ts-node":"^8.5.4","typechain":"^4.0.0","typescript":"^3.7.3"},"scripts":{"compile":"hardhat compile","test":"hardhat test","test:gas":"UPDATE_SNAPSHOT=1 yarn test --grep gas","test:all":"UPDATE_SNAPSHOT=1 yarn test","presymlink":"rm -rf ./solmate && rm -rf ./permit2","symlink":"ln -s ./lib/solmate ./solmate && ln -s ./lib/permit2 ./permit2","prettier:fix":"prettier --write '**/*.ts' && prettier --write '**/*.json'","lint:fix":"yarn prettier:fix && forge fmt","prettier":"prettier --check '**/*.ts' && forge fmt --check"},"_id":"@aborean/universal-router@1.6.0","gitHead":"41183d6eb154f0ab0e74a0e911a5ef9ea51fc4bd","bugs":{"url":"https://github.com/Uniswap/universal-router/issues"},"homepage":"https://github.com/Uniswap/universal-router#readme","_nodeVersion":"18.20.8","_npmVersion":"10.8.2","dist":{"integrity":"sha512-sGLrJc6jjsMKZz6y8CTNZQLjC3JTT0QCnsRMUiGy9C9Dwd0YtfabRqxnFjtpGjow4pLgqX0u4gSyfaaDpO+EAQ==","shasum":"89e29fe2916dd683b086a557506081dbc34fcdc1","tarball":"https://registry.npmjs.org/@aborean/universal-router/-/universal-router-1.6.0.tgz","fileCount":157,"unpackedSize":1118148,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEQCIHHrjgViVfVQahd2N9WM3ClR76xaaWC5tMHBqUsEjsgwAiBDybNsuGqrHqsbN50QP33m1xfhLmnVyvOGjVJw2T48fA=="}]},"_npmUser":{"name":"cryptoaaron","email":"aaron@bombmoney.com"},"directories":{},"maintainers":[{"name":"cryptoaaron","email":"aaron@bombmoney.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/universal-router_1.6.0_1754750510717_0.6950557035561702"},"_hasShrinkwrap":false}},"time":{"created":"2025-08-09T14:41:50.622Z","1.6.0":"2025-08-09T14:41:50.991Z","modified":"2025-08-09T14:41:51.247Z"},"maintainers":[{"name":"cryptoaaron","email":"aaron@bombmoney.com"}],"description":"Smart contracts for Universal Router","homepage":"https://github.com/Uniswap/universal-router#readme","keywords":["uniswap","router","universal router","swap router"],"repository":{"type":"git","url":"git+https://github.com/Uniswap/universal-router.git"},"bugs":{"url":"https://github.com/Uniswap/universal-router/issues"},"license":"GPL-2.0-or-later","readme":"# Universal Router\n\nPlease read the [Contributions](https://github.com/Uniswap/universal-router#contributions) section before submitting a Pull Request.\n\nTo see the commit of the smart contracts that was used in the latest deployment, see branch `deployed-commit`. To see the addresses of this latest deployment on each network, see folder `deploy-addresses`.\n\n## High-Level Overview\n\nThe Universal Router is a ERC20 and NFT swap router that allows users greater flexibility when performing trades across multiple token types.\n\nOur flexible command style allows us to provide users with:\n\n- Splitting and interleaving of Uniswap trades\n- Purchases of NFTs across 8 marketplaces\n- Partial fills of trades\n- Wrapping and Unwrapping of ETH\n- Time-bound, signature controlled token approvals using [Permit2](https://github.com/Uniswap/permit2)\n\nTransactions are encoded using a string of commands, allowing users to have maximum flexibility over what they want to perform. With all of these features available in a single transaction, the possibilities available to users are endless\n\n## Contract Overview\n\nThe Universal Router codebase consists of the `UniversalRouter` contract, and all of its dependencies. The purpose of the `UniversalRouter` is to allow users to unify Uniswap ERC20 swaps (on V2 and V3) with NFT purchases across 8 marketplaces, in a single transaction.\n\n`UniversalRouter` integrates with [Permit2](https://github.com/Uniswap/permit2), to enable users to have more safety, flexibility, and control over their ERC20 token approvals.\n\n### UniversalRouter command encoding\n\nCalls to `UniversalRouter.execute`, the entrypoint to the contracts, provide 2 main parameters:\n\n- `bytes commands`: A bytes string. Each individual byte represents 1 command that the transaction will execute.\n- `bytes[] inputs`: An array of bytes strings. Each element in the array is the encoded parameters for a command.\n\n`commands[i]` is the command that will use `inputs[i]` as its encoded input parameters.\n\nThrough function overloading there is also an optional third parameter for the `execute` function:\n\n- `uint256 deadline`: The timestamp deadline by which this transaction must be executed. Transactions executed after this specified deadline will revert.\n\n#### How the command byte is structured\n\nEach command is a `bytes1` containing the following 8 bits:\n\n```\n 0 1 2 3 4 5 6 7\n┌─┬─┬───────────┐\n│f│r|  command  │\n└─┴─┴───────────┘\n```\n\n- `f` is a single bit flag, that signals whether or not the command should be allowed to revert. If `f` is `false`, and the command reverts, then the entire transaction will revert. If `f` is `true` and the command reverts then the transaction will continue, allowing us to achieve partial fills. If using this flag, be careful to include further commands that will remove any funds that could be left unused in the `UniversalRouter` contract.\n\n- `r` is one bit of reserved space. This will allow us to increase the space used for commands, or add new flags in future.\n\n- `command` is a 6 bit unique identifier for the command that should be carried out. The values of these commands can be found within Commands.sol, or can be viewed in the table below.\n\n```\n   ┌──────┬───────────────────────────────┐\n   │ 0x00 │  V3_SWAP_EXACT_IN             │\n   ├──────┼───────────────────────────────┤\n   │ 0x01 │  V3_SWAP_EXACT_OUT            │\n   ├──────┼───────────────────────────────┤\n   │ 0x02 │  PERMIT2_TRANSFER_FROM        │\n   ├──────┼───────────────────────────────┤\n   │ 0x03 │  PERMIT2_PERMIT_BATCH         │\n   ├──────┼───────────────────────────────┤\n   │ 0x04 │  SWEEP                        │\n   ├──────┼───────────────────────────────┤\n   │ 0x05 │  TRANSFER                     │\n   ├──────┼───────────────────────────────┤\n   │ 0x06 │  PAY_PORTION                  │\n   ├──────┼───────────────────────────────┤\n   │ 0x07 │  -------                      │\n   ├──────┼───────────────────────────────┤\n   │ 0x08 │  V2_SWAP_EXACT_IN             │\n   ├──────┼───────────────────────────────┤\n   │ 0x09 │  V2_SWAP_EXACT_OUT            │\n   ├──────┼───────────────────────────────┤\n   │ 0x0a │  PERMIT2_PERMIT               │\n   ├──────┼───────────────────────────────┤\n   │ 0x0b │  WRAP_ETH                     │\n   ├──────┼───────────────────────────────┤\n   │ 0x0c │  UNWRAP_WETH                  │\n   ├──────┼───────────────────────────────┤\n   │ 0x0d │  PERMIT2_TRANSFER_FROM_BATCH  │\n   ├──────┼───────────────────────────────┤\n   │ 0x0e │  -------                      │\n   ├──────┼───────────────────────────────┤\n   │ 0x0f │  -------                      │\n   ├──────┼───────────────────────────────┤\n   │ 0x10 │  SEAPORT_V1_5                 │\n   ├──────┼───────────────────────────────┤\n   │ 0x11 │  LOOKS_RARE_721               │\n   ├──────┼───────────────────────────────┤\n   │ 0x12 │  NFTX                         │\n   ├──────┼───────────────────────────────┤\n   │ 0x13 │  CRYPTOPUNKS                  │\n   ├──────┼───────────────────────────────┤\n   │ 0x14 │  LOOKS_RARE_1155              │\n   ├──────┼───────────────────────────────┤\n   │ 0x15 │  OWNER_CHECK_721              │\n   ├──────┼───────────────────────────────┤\n   │ 0x16 │  OWNER_CHECK_1155             │\n   ├──────┼───────────────────────────────┤\n   │ 0x17 │  SWEEP_ERC721                 │\n   ├──────┼───────────────────────────────┤\n   │ 0x18 │  X2Y2_721                     │\n   ├──────┼───────────────────────────────┤\n   │ 0x19 │  SUDOSWAP                     │\n   ├──────┼───────────────────────────────┤\n   │ 0x1a │  NFT20                        │\n   ├──────┼───────────────────────────────┤\n   │ 0x1b │  X2Y2_1155                    │\n   ├──────┼───────────────────────────────┤\n   │ 0x1c │  FOUNDATION                   │\n   ├──────┼───────────────────────────────┤\n   │ 0x1d │  SWEEP_ERC1155                │\n   ├──────┼───────────────────────────────┤\n   │ 0x1e │  ELEMENT_MARKET               │\n   ├──────┼───────────────────────────────┤\n   │ 0x1f │  -------                      │\n   ├──────┼───────────────────────────────┤\n   │ 0x20 │  SEAPORT_V1_4                 │\n   ├──────┼───────────────────────────────┤\n   │ 0x21 │  EXECUTE_SUB_PLAN             │\n   ├──────┼───────────────────────────────┤\n   │ 0x22 │  APPROVE_ERC20                │\n   ├──────┼───────────────────────────────┤\n   │ 0x23-│  -------                      │\n   │ 0x3f │                               │\n   └──────┴───────────────────────────────┘\n```\n\nNote that some of the commands in the middle of the series are unused. These gaps allowed us to create gas-efficiencies when selecting which command to execute.\n\n#### How the input bytes are structures\n\nEach input bytes string is merely the abi encoding of a set of parameters. Depending on the command chosen, the input bytes string will be different. For example:\n\nThe inputs for `V3_SWAP_EXACT_IN` is the encoding of 5 parameters:\n\n- `address` The recipient of the output of the trade\n- `uint256` The amount of input tokens for the trade\n- `uint256` The minimum amount of output tokens the user wants\n- `bytes` The UniswapV3 path you want to trade along\n- `bool` A flag for whether the input funds should come from the caller (through Permit2) or whether the funds are already in the UniversalRouter\n\nWhereas in contrast `CRYPTOPUNKS` has just 3 parameters encoded:\n\n- `uint256` The ID of the punk you wish to purchase\n- `address` The recipient of the punk\n- `uint256` The amount of ETH to pay for the punk\n\nEncoding parameters in a bytes string in this way gives us maximum flexiblity to be able to support many commands which require different datatypes in a gas-efficient way.\n\nFor a more detailed breakdown of which parameters you should provide for each command take a look at the `Dispatcher.dispatch` function, or alternatively at the `ABI_DEFINITION` mapping in `planner.ts`.\n\nDeveloper documentation to give a detailed explanation of the inputs for every command will be coming soon!\n\n## Usage\n\n### To Compile and Run Tests\n\n1. Clone the repository with all submodules\n\nClone the repository with:\n```\ngit clone --recurse-submodules https://github.com/Uniswap/universal-router.git\n```\n\n2. Create `.env` file with api key\n\n```\nINFURA_API_KEY='xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx'\n```\n\n3. Run yarn commands to compile and test\n\n### To Run Hardhat Tests\n\n```console\nyarn install\nyarn symlink\nyarn compile\nyarn test\n```\n\nIf you run into an issue on `yarn compile` where it cannot find the dependencies in the lib folder try to clone all the submodules with:\n```\ngit submodule update --init --recursive\n```\n\n#### To Update Hardhat Gas Snapshots\n\n```console\nyarn test:gas\n```\n\n### To Run Forge Tests\n\n```console\nforge install\nforge build\nforge test\n```\n## Integrating\n\n1. Install the latest version of `@uniswap/universal-router` package.\n2. Add git submodules for contracts that aren't a node package. Make sure there's an empty `.gitmodules` file. Then run:\n    ```bash\n      git submodule add https://github.com/transmissions11/solmate\n      git submodule add https://github.com/Uniswap/permit2\n    ```\n3. You should now be able to import contracts from universal-router and compile.\n\n## Contributions\nBefore you submit your PR, run all of the following and commit the changes:\n```bash\n# make sure all tests pass this will also update gas snapshots\nyarn test:all\n\n# lint code\nyarn prettier:fix\n```\n\nIf you are only concerned with investigating gas diffs, you can run this command to only run gas tests\n```bash\nyarn test:gas\n```\n\n### To Deploy\n\nFill out parameters in `script/deployParameters/Deploy<network>.s.sol`\n\n```console\nforge script --broadcast \\\n--rpc-url <RPC-URL> \\\n--private-key <PRIVATE_KEY> \\\n--sig 'run()' \\\nscript/deployParameters/Deploy<network>.s.sol:Deploy<network>\n```\n\n### To Deploy and Verify\n\n```console\nforge script --broadcast \\\n--rpc-url <RPC-URL> \\\n--private-key <PRIVATE-KEY> \\\n--sig 'run()' \\\nscript/deployParameters/Deploy<network>.s.sol:Deploy<network> \\\n--etherscan-api-key <ETHERSCAN-API-KEY> \\\n--verify\n```\n\n#### To Deploy Permit2 Alongside UniversalRouter\n\nFill out parameters in `scripts/deployParameters/<network>.json`\n\n```console\nforge script --broadcast \\\n--rpc-url <RPC-URL> \\\n--private-key <PRIVATE_KEY> \\\n--sig 'runAndDeployPermit2(string)' \\\nscript/deployParameters/DeployUniversalRouter.s.sol:DeployUniversalRouter \\\n<pathToJSON>\n```\n","readmeFilename":"README.md","_rev":"1-2b30807a5b47b065e563071ff8ee45a8"}