From 8c42957409f1a96bb61c09c093c4d21d59dec67c Mon Sep 17 00:00:00 2001 From: Danny Daniil Date: Tue, 22 Nov 2022 10:14:39 -0500 Subject: [PATCH] fix: readme for adding new projects (#496) * initial take * new readme * update read me * rearange guides * add overview instructions * remove unused readme * checklist table * pollish table * question marks * delete versioned docs * aux fixes * point on doc name/id * slashes on paths --- CONTRIBUTING.md | 1 + README.md | 88 +++++-- .../version-V3/permit2/_category_.json | 6 - versioned_docs/version-V3/permit2/overview.md | 20 -- .../permit2/reference/_category_.json | 6 - .../permit2/reference/allowance-transfer.md | 171 ------------ .../permit2/reference/signature-transfer.md | 245 ------------------ 7 files changed, 73 insertions(+), 464 deletions(-) delete mode 100644 versioned_docs/version-V3/permit2/_category_.json delete mode 100644 versioned_docs/version-V3/permit2/overview.md delete mode 100644 versioned_docs/version-V3/permit2/reference/_category_.json delete mode 100644 versioned_docs/version-V3/permit2/reference/allowance-transfer.md delete mode 100644 versioned_docs/version-V3/permit2/reference/signature-transfer.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index cbed3fb172..16f51c1055 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,5 +1,6 @@ # Contribution Guidelines + Thanks for giving a little extra love to our docs site! Below are some basic guidelines to follow to get your PR merged :) ## Creating a Pull Request diff --git a/README.md b/README.md index 8bf47ef07d..232f749c99 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,78 @@ -# Website +# Uniswap Documentation + +This web application contains all documentation for Uniswap products. It is built using [Docusaurus 2](https://v2.docusaurus.io/), a modern static website generator. + + +# Project Layout + +### Uniswap documentation is broken down into four sections: +- Concepts - General Uniswap information or concepts useful for using Uniswap products, such as *Liquidity* and *Fees* +- Contracts - Uniswap smart contracts such as the V3 Contracts or *Permit2* +- SDKs - Uniswap integrations such as the *v3-sdk* and the *Swap Widget* +- APIs - The Uniswap APIs such the *Subgraph API* + +### Each item in a section should include the following: +- *Overview* +- *Guides* +- *Technical Reference* + +## Adding Documentation + +### Overview +A product overview should address points such as: + +- What are the high level components of the product? +- What what is the high level functionality the product offers? +- Where does the source code of the product live? +- Where does the code artifact live (eg *npm*) and how does someone integrate with it? + +A good example is the [V3 Smart Contracts](./docs/contracts/v3/overview.md). + +### Guides +Guides should ensure users can easily integrate with the product by including the following parts: +- An introduction that gives the developer the required context and a summary of what the guide will cover and result in. +- A walk-through of the provided example code. The guide should not directly include large blocks of code, but should instead reference/link to this code as needed, including snippets sparingly when required. +- An output or end state that users can test against. + +A good example is the [V3 SDK Guides](./docs/sdk/v3/guides/01-quick-start.md). + +### Technical References +This should contain the technical reference for the exported interfaces. A good example is the [V3 Smart Contracts](./docs/contracts/v3/reference/overview.md). -This website is built using [Docusaurus 2](https://v2.docusaurus.io/), a modern static website generator. # Contributing to Uniswap Docs -Contributing to the docs site is a great way to get involved in the dev community and help other devs along the way! Check out our guidelines [here](https://github.com/Uniswap/uniswap-docs/blob/main/CONTRIBUTING.md). +## Guidelines +Contributing to the docs site is a great way to get involved in the dev community and help other developers along the way! Check out our guidelines [here](./CONTRIBUTING.md). + +## Checklist for adding a new product + +- Did I pick the right section for the product? +- Did I create the product folder? +- Did I introduce any new concepts? If so add under */concepts/* +- Did I include an Overview of the product under *//overview* ? +- Did I include Guides of the product under *//guides* ? +- Did I include Technical Reference of the product under *//reference* ? +- Did I give a descriptive name/id to each document? This is important because that shows up in the URL +- Did I open a PR using the the [contributing](./CONTRIBUTING.md) guidelines? + +## Checklist example + +Let's walk through an example by considering the *Permit2* smart contract: +- Did I pick the right section for the product? + - In this case, [contracts](./docs/contracts/) +- Did I create the product folder? + - In this case, [yes](./docs/contracts/permit2/) +- Did I introduce any new concepts? + - No +- Did I include an Overview of the product under */contracts/permit2/overview* ? + - Yes, I did add them [here](./docs/contracts/permit2/overview.md) +- Did I include Guides of the product under *contracts/permit2/guides* ? + - No, they should be added [here](./docs/contracts/permit2/guides) +- Did I include Technical Reference of the product under *contracts/permit2/reference* ? + - Yes I added them [here](./docs/contracts/permit2/reference) +- Did I open a PR using the the [Contributing](./CONTRIBUTING.md) guidelines? + - Yes # How to generate markdown files from solidity Natspec comments @@ -37,10 +105,6 @@ Edit config.json file with - install jq : `brew install jq` run `docker run -it --env-file=.env -e "CONFIG=$(cat ./config.json | jq -r tostring)" algolia/docsearch-scraper` -# How to add a new page - -Create a markdown file in its respective versioned docs, or versioned SDK, directory. - ## Installation ```console @@ -67,12 +131,4 @@ yarn docusaurus clear yarn build ``` -This command generates static content into the `build` directory and can be served using any static contents hosting service. - -## Deployment - -```console -GIT_USER= USE_SSH=true yarn deploy -``` - -If you are using GitHub pages for hosting, this command is a convenient way to build the website and push to the `gh-pages` branch. +This command generates static content into the `build` directory and can be served using any static contents hosting service. \ No newline at end of file diff --git a/versioned_docs/version-V3/permit2/_category_.json b/versioned_docs/version-V3/permit2/_category_.json deleted file mode 100644 index 61e30a009e..0000000000 --- a/versioned_docs/version-V3/permit2/_category_.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "label": "Permit2", - "position": 5, - "collapsed": false - } - \ No newline at end of file diff --git a/versioned_docs/version-V3/permit2/overview.md b/versioned_docs/version-V3/permit2/overview.md deleted file mode 100644 index 6c57a27ab2..0000000000 --- a/versioned_docs/version-V3/permit2/overview.md +++ /dev/null @@ -1,20 +0,0 @@ ---- -id: overview -title: Overview -sidebar_position: 1 ---- - -[`Permit2`](https://github.com/Uniswap/permit2) is a unification of 2 contracts, [`SignatureTransfer`](./reference/signature-transfer.md) and [`AllowanceTransfer`](./reference/signature-transfer.md). The `SignatureTransfer` contract handles all signature-based transfers, meaning that an allowance on the token is bypassed and permissions to the spender only last for the duration of the transaction that the one-time signature is spent. The `AllowanceTransfer` contract handles setting allowances on tokens, giving permissions to spenders on a specified amount for a specified duration of time. Any transfers that then happen through the `AllowanceTransfer` contract will only succeed if the proper permissions have been set. - -## Approving Permit2 - -Before integrating contracts can request users’ tokens through Permit2, users must approve the Permit2 contract through the specific token contract by calling something like: - -```solidity -USDC.approve(permit2Address, totalAmount); -``` - -To get the maximal benefits from Permit2, users should do a max approval on the contract where: -```solidity -totalAmount = type(uint256).max; -``` \ No newline at end of file diff --git a/versioned_docs/version-V3/permit2/reference/_category_.json b/versioned_docs/version-V3/permit2/reference/_category_.json deleted file mode 100644 index 2710b6a63a..0000000000 --- a/versioned_docs/version-V3/permit2/reference/_category_.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "label": "Technical Reference", - "position": 2, - "collapsed": false - } - \ No newline at end of file diff --git a/versioned_docs/version-V3/permit2/reference/allowance-transfer.md b/versioned_docs/version-V3/permit2/reference/allowance-transfer.md deleted file mode 100644 index 4b20fe217e..0000000000 --- a/versioned_docs/version-V3/permit2/reference/allowance-transfer.md +++ /dev/null @@ -1,171 +0,0 @@ ---- -id: allowance-transfer -title: AllowanceTransfer -sidebar_position: 2 ---- - -> [**Source Code**](https://github.com/Uniswap/permit2/blob/main/src/AllowanceTransfer.sol) - -## Overview - -The main entry points on this contract are: - -- `approve` - - Use approve when you do not want to set token permissions through signature validation. -- `permit` - - Use permit when you do want to set token permissions through signature validation. -- `transferFrom` - - Use transferFrom when you want to transfer a token and have the necessary permissions to do so. - -## Functions - -### `approve` - -**Function Signature** - -```solidity -function approve(address token, address spender, uint160 amount, uint48 expiration) external -``` - -**Parameters** - -- token - the token address to approve -- spender - the spender address to approve -- amount - the approved amount of the token, `type(uint160).max` is treated as an unlimited allowance -- expiration - the timestamp at which the approval is no longer valid, passing in `0` will expire the permissions at `block.timestamp` - -### Single `permit` - -**Function Signature** - -```solidity -function permit(address owner, PermitSingle memory permitSingle, bytes calldata signature) external; -``` - -**Parameters** - -- owner - the address of the token’s owner -- permitSingle - constructed with the following: - -```solidity -struct PermitSingle { - // the permit data for a single token allowance - PermitDetails details; - // address permissioned on the allowed tokens - address spender; - // deadline on the permit signature - uint256 sigDeadline; - } - -struct PermitDetails { - // ERC20 token address - address token; - // the maximum amount allowed to spend - uint160 amount; - // timestamp at which a spender's token allowances become invalid - uint48 expiration; - // an incrementing value indexed per owner,token,and spender for each signature - uint48 nonce; - } -``` - -- signature - the signature over the permit data. Supports EOA signatures, compact signatures defined by [EIP-2098](https://eips.ethereum.org/EIPS/eip-2098), and contract signatures defined by [EIP-1271](https://eips.ethereum.org/EIPS/eip-1271) - -### Batched `permit` - -**Function Signature** - -```solidity -function permit(address owner, PermitBatch memory permitBatch, bytes calldata signature) external; -``` - -**Parameters** - -- owner - the address of the token’s owner -- permitBatch - constructed with the following: - -```solidity -struct PermitBatch { - // the permit data for multiple token allowances - PermitDetails[] details; - // address permissioned on the allowed tokens - address spender; - // deadline on the permit signature - uint256 sigDeadline; - } -struct PermitDetails { - // ERC20 token address - address token; - // the maximum amount allowed to spend - uint160 amount; - // timestamp at which a spender's token allowances become invalid - uint48 expiration; - // an incrementing value indexed per owner,token,and spender for each signature - uint48 nonce; - } -``` - -- signature - the signature over the permit data. Supports EOA signatures, compact signatures defined by [EIP-2098](https://eips.ethereum.org/EIPS/eip-2098), and contract signatures defined by [EIP-1271](https://eips.ethereum.org/EIPS/eip-1271) - -### Single `transferFrom` - -**Function Signature** - -```solidity -function transferFrom(address from, address to, uint160 amount, address token) external; -``` - -**Parameters** - -- from - the address to transfer the token from -- to - the address of the recipient -- amount - the amount of the token to transfer, the maximum amount is `type(uint160).max` -- token - the address of the token to be transferred - -### Batched `transferFrom` - -**Function Signature** - -```solidity -function transferFrom(AllowanceTransferDetails[] calldata transferDetails) external; -``` - -**Parameters** - -- transferDetails - constructed with the following - -```solidity -struct AllowanceTransferDetails { - // the owner of the token - address from; - // the recipient of the token - address to; - // the amount of the token - uint160 amount; - // the token to be transferred - address token; - } -``` - -## Nonce Schema - -The nonces used to protect against replay attacks of signatures are similar to standard incrementing nonces. However, we pack nonces with an allowed amount, and an allowed duration. This means that nonces are incremented *per owner*, *per token*, and *per spender.* Which further implies that you could sign two different permits at the same time with the same nonces and they *won’t* cancel each other out so long as the token or spender differ. - -The mapping nonces are packed in is defined as follows: - -```solidity -mapping(address => mapping(address => mapping(address => PackedAllowance))) public allowance; -``` - -and indexed as follows: - -```solidity -PackedAllowance allowanceInformation = allowance[ownerAddress][tokenAddress][spenderAddress]; -uint48 nonce = allowanceInformation.nonce; -``` - -## Security Considerations - -Similar to the security considerations outlined in SignatureTransfer, integrating contracts need to perform valid safety checks on the caller and pass in correct addresses for the `from` argument in any transfer calls. - -All amounts on the `AllowanceTransfer` contract are of type `uint160` so make sure integrating contracts safely downcast if they have to. See how Permit2Lib downcasts safely. \ No newline at end of file diff --git a/versioned_docs/version-V3/permit2/reference/signature-transfer.md b/versioned_docs/version-V3/permit2/reference/signature-transfer.md deleted file mode 100644 index 4279ade651..0000000000 --- a/versioned_docs/version-V3/permit2/reference/signature-transfer.md +++ /dev/null @@ -1,245 +0,0 @@ ---- -id: signature-transfer -title: SignatureTransfer -sidebar_position: 1 ---- - -> [**Source Code**](https://github.com/Uniswap/permit2/blob/main/src/SignatureTransfer.sol) - -## Overview - -The main entry points on this contract are: - -- `permitTransferFrom` - - Use permitTransferFrom when you want to transfer a token from an owner through signature validation. -- `permitWitnessTransferFrom` - - Use permitWitnessTransferFrom when you want to transfer a token from an owner through signature validation, but you would also like to validate other data. Any other data you wish to be validated can be passed through with the `witness` param. - -Each of these functions is overloaded with a batched version that allows users to transfer multiple tokens with 1 transaction. - -## Functions - -### Single `permitTransferFrom` - -Use the `permitTransferFrom` to transfer just one token. - -**Function signature** - -```solidity -function permitTransferFrom( - PermitTransferFrom memory permit, - SignatureTransferDetails calldata transferDetails, - address owner, - bytes calldata signature - ) external -``` - -**Parameters** - -- permit - Construct `PermitTransferFrom` struct with the following: - -```solidity -struct PermitTransferFrom { - TokenPermissions permitted; - // a unique value for every token owner's signature to prevent signature replays - uint256 nonce; - // deadline on the permit signature - uint256 deadline; - } - -struct TokenPermissions { - // ERC20 token address - address token; - // the maximum amount that can be spent - uint256 amount; - } -``` - -- transferDetails - information about recipient and amount - -```solidity -struct SignatureTransferDetails { - // recipient address - address to; - // spender requested amount - uint256 requestedAmount; - }PermitBatchTransferFrom memory permit, - SignatureTransferDetails[] calldata transferDetails, - address owner, - bytes calldata signature - ) external -``` - -- owner - the signer of the permit message and owner of the tokens -- signature - the signature over the permit data. Supports EOA signatures, compact signatures defined by [EIP-2098](https://eips.ethereum.org/EIPS/eip-2098), and contract signatures defined by [EIP-1271](https://eips.ethereum.org/EIPS/eip-1271) - -### Batched `permitTransferFrom` - -Use `permitTransferFrom` with the batched parameters when you want to transfer multiple tokens from an owner. - -**Function Signature** - -```solidity -function permitTransferFrom( - PermitBatchTransferFrom memory permit, - SignatureTransferDetails[] calldata transferDetails, - address owner, - bytes calldata signature - ) external -``` - -**Parameters** - -- permit - Construct `PermitBatchTransferFrom` with the following: - -```solidity -struct PermitBatchTransferFrom { - // the tokens and corresponding amounts permitted for a transfer - TokenPermissions[] permitted; - // a unique value for every token owner's signature to prevent signature replays - uint256 nonce; - // deadline on the permit signature - uint256 deadline; - } - -struct TokenPermissions { - // ERC20 token address - address token; - // the maximum amount that can be spent - uint256 amount; - } -``` - -- transferDetails - parameterized by the spender with information about the token transfer. - - The length of the `SignatureTransferDetails` array must equal the length of the `TokenPermissions` array passed in with `PermitBatchTransferFrom` struct. The token to be transferred specified in the `TokenPermissions` array should match the index of the `SignatureTransferDetails` array. - - Note that if a spender is permitted to a token but does not need to transfer that token, they can specify that the `requestedAmount` is 0 so that the transfer is skipped. -- owner - the signer of the permit message and owner of the tokens - -```solidity -struct SignatureTransferDetails { - // recipient address - address to; - // spender requested amount - uint256 requestedAmount; - } -``` - -- signature - the signature over the permit data. Supports EOA signatures, compact signatures defined by [EIP-2098](https://eips.ethereum.org/EIPS/eip-2098), and contract signatures defined by [EIP-1271](https://eips.ethereum.org/EIPS/eip-1271) - -### Single `permitWitnessTransferFrom` - -**Function Signature** - -```solidity -function permitWitnessTransferFrom( - PermitTransferFrom memory permit, - SignatureTransferDetails calldata transferDetails, - address owner, - bytes32 witness, - string calldata witnessTypeString, - bytes calldata signature - ) external -``` - -**Parameters** - -- permit - constructed with the same type as defined above in the single permitTransferFrom case -- transferDetails constructed with same type as defined above in the single permitTransferFrom case -- owner - the signer of the permit message and owner of the tokens -- witness - arbitrary data passed through that was signed by the user. Is used to reconstruct the signature. Pass through this data if you want the permit signature recovery also to validate other data. -- witnessTypeString - a string that defines the typed data that the witness was hashed from. It must also include the `TokenPermissions` struct and comply with [EIP-712](https://eips.ethereum.org/EIPS/eip-712) struct ordering. See an example below. -- signature - the signature over the permit data. Supports EOA signatures, compact signatures defined by [EIP-2098](https://eips.ethereum.org/EIPS/eip-2098), and contract signatures defined by [EIP-1271](https://eips.ethereum.org/EIPS/eip-1271) - -### Batch `permitWitnessTransferFrom` - -**Function Signature** - -```solidity -function permitWitnessTransferFrom( - PermitBatchTransferFrom memory permit, - SignatureTransferDetails[] calldata transferDetails, - address owner, - bytes32 witness, - string calldata witnessTypeString, - bytes calldata signature - ) external -``` - -**Parameters** - -- permit - constructed with the same type in the batched case of `permitTransferFrom` -- transferDetails - constructed with the same type in the batched case of `permitTransferFrom` -- owner - the signer of the permit message and owner of the tokens -- witness - arbitrary data passed through that was signed by the user. Is used to reconstruct the signature. Pass through this data if you want the permit signature recovery to also validate other data. -- witnessTypeString - a string that defines the typed data that the witness was hashed from. It must also include the `TokenPermissions` struct and comply with [EIP-712](https://eips.ethereum.org/EIPS/eip-712) struct ordering. See an example below. -- signature - the signature over the permit data. Supports EOA signatures, compact signatures defined by [EIP-2098](https://eips.ethereum.org/EIPS/eip-2098), and contract signatures defined by [EIP-1271](https://eips.ethereum.org/EIPS/eip-1271) - -**Example `permitWitnessTransferFrom` parameters** - -If an integrating contract would also like the signer to verify information about a trade, an integrating contract may ask the signer to also sign an `ExampleTrade` object that we define below: - -```solidity -struct ExampleTrade { - address exampleTokenAddress; - uint256 exampleMinimumAmountOut; -} -``` - -Following EIP-721, the typehash for the data would be defined by: - -```solidity -bytes32 _EXAMPLE_TRADE_TYPEHASH = keccak256('ExampleTrade(address exampleTokenAddress,uint256 exampleMinimumAmountOut)'); -``` - -The `witness` that should be passed along with the permit message should be: - -```solidity - bytes32 witness = keccak256( - abi.encode(_EXAMPLE_TRADE_TYPEHASH, exampleTrade.exampleTokenAddress, exampleTrade.exampleMinimumAmountOut)); -``` - -And the `witnessTypeString` to be passed in should be: - -```solidity -string constant witnessTypeString = "ExampleTrade witness)ExampleTrade(address exampleTokenAddress,uint256 exampleMinimumAmountOut)TokenPermissions(address token,uint256 amount)" -``` - -It’s important to note that when hashing multiple typed structs, the ordering of the structs in the type string matters. Referencing EIP-721: - -> If the struct type references other struct types (and these in turn reference even more struct types), then the set of referenced struct types is collected, sorted by name and appended to the encoding. An example encoding is `Transaction(Person from,Person to,Asset tx)Asset(address token,uint256 amount)Person(address wallet,string name)` -> - -## Nonce Schema - -Instead of using incrementing nonces, we introduce non-monotonic, or unordered nonces with a `nonceBitmap`. - -The `nonceBitmap` maps an owner's address to a uint248 value, which we will call `wordPos` which is the index of the desired bitmap. There are 2**248 possible indices and this 2**248 possible bitmaps where each bitmap holds 256 bits. A bit must be flipped on to prevent replays of users’ signatures. Bits that are dirtied may not be used again. - -```solidity -// nonceBitmap[ownerAddress][wordPosition] retrieves a uint256 bitmap -mapping(address => mapping(uint248 => uint256)) public nonceBitmap; -``` - -Users will sign a `uint256 nonce` value where the first 248 bits correspond to the word position of the bitmap to dirty and the last 8 bits correspond to the actual bit position being flipped on. - -```solidity -uint248 wordPos = uint248(nonce >> 8); -uint8 bitPos = uint8(nonce); -``` - -```solidity -uint256 bitmap = nonceBitmap[wordPos][bitPos] -``` - -## Security Considerations - -An integrating contract must check that tokens are released by a triggering call from the signer, or that the signer meant for their signature to be released by someone else. - - - -Universal Router protects against this by checking that the `msg.sender` from inside the routing contract is the supposed spender by passing `msg.sender` in as the `owner` param in any permit calls and by passing in `msg.sender` as the `from` param in any transfer calls. \ No newline at end of file