From b9c854662adeec63d850cdb903238f6ca555fb34 Mon Sep 17 00:00:00 2001 From: Vectorized Date: Wed, 25 Dec 2024 07:15:22 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=91=B7=E2=80=8D=E2=99=82=EF=B8=8F=20Bette?= =?UTF-8?q?r=20docs=20gen=20(#1256)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/accounts/erc1271.md | 2 +- docs/accounts/erc4337.md | 11 ++++---- docs/accounts/erc4337factory.md | 10 ++++++- docs/accounts/erc6551.md | 8 +++--- docs/accounts/erc6551proxy.md | 11 ++++++++ docs/accounts/erc7821.md | 2 +- docs/accounts/timelock.md | 27 ++++++++++++++++--- docs/auth/ownableroles.md | 2 +- docs/tokens/erc1155.md | 2 +- docs/tokens/erc20.md | 2 +- docs/tokens/erc20votes.md | 2 +- docs/tokens/erc4626.md | 2 +- docs/tokens/erc6909.md | 2 +- docs/tokens/erc721.md | 4 +-- docs/tokens/weth.md | 2 +- docs/utils/datetimelib.md | 22 ++++++++-------- docs/utils/deploylesspredeployqueryer.md | 9 +++++++ docs/utils/erc1967factoryconstants.md | 8 +++--- docs/utils/libzip.md | 3 ++- docs/utils/lifebuoy.md | 33 +++++++++++++++++++++++- docs/utils/upgradeablebeacon.md | 14 ++++++++++ docs/utils/uupsupgradeable.md | 3 +-- prep/gen-docs.js | 25 ++++++++++++++++-- 23 files changed, 160 insertions(+), 46 deletions(-) diff --git a/docs/accounts/erc1271.md b/docs/accounts/erc1271.md index a68fb2163..57308ae67 100644 --- a/docs/accounts/erc1271.md +++ b/docs/accounts/erc1271.md @@ -7,7 +7,7 @@ ERC1271 mixin with nested EIP-712 approach. Inherits: -- `utils/EIP712.sol` +- [`utils/EIP712.sol`](utils/eip712.md) diff --git a/docs/accounts/erc4337.md b/docs/accounts/erc4337.md index 114930edc..6c512f0ce 100644 --- a/docs/accounts/erc4337.md +++ b/docs/accounts/erc4337.md @@ -7,8 +7,7 @@ Simple ERC4337 account implementation. 1. Deploy the ERC4337 as an implementation contract, and verify it on Etherscan. 2. Create a factory that uses `LibClone.deployERC1967` or -`LibClone.deployDeterministicERC1967` to clone the implementation. -See: `ERC4337Factory.sol`. +`LibClone.deployDeterministicERC1967` to clone the implementation. See: [`ERC4337Factory.sol`](accounts/erc4337factory.md). Note: @@ -22,10 +21,10 @@ implementation, please do get one or more security reviews before deployment. Inherits: -- `auth/Ownable.sol` -- `utils/UUPSUpgradeable.sol` -- `accounts/Receiver.sol` -- `accounts/ERC1271.sol` +- [`auth/Ownable.sol`](auth/ownable.md) +- [`utils/UUPSUpgradeable.sol`](utils/uupsupgradeable.md) +- [`accounts/Receiver.sol`](accounts/receiver.md) +- [`accounts/ERC1271.sol`](accounts/erc1271.md) diff --git a/docs/accounts/erc4337factory.md b/docs/accounts/erc4337factory.md index b6f5f9ca2..21c4de34f 100644 --- a/docs/accounts/erc4337factory.md +++ b/docs/accounts/erc4337factory.md @@ -3,7 +3,15 @@ Simple ERC4337 account factory implementation. - +Note: + +- Unlike the ERC1967Factory, this factory does NOT store any admin info on the factory itself. +The deployed ERC4337 accounts are minimal ERC1967 proxies to an ERC4337 implementation. +The proxy bytecode does NOT contain any upgrading logic. +- This factory does NOT contain any logic for upgrading the ERC4337 accounts. +Upgrading must be done via UUPS logic on the accounts themselves. +- The ERC4337 standard expects the factory to use deterministic deployment. +As such, this factory does not include any non-deterministic deployment methods. diff --git a/docs/accounts/erc6551.md b/docs/accounts/erc6551.md index a7d6f0dee..e7656017b 100644 --- a/docs/accounts/erc6551.md +++ b/docs/accounts/erc6551.md @@ -29,14 +29,14 @@ Recent updates to the account abstraction validation scope rules For an opinionated implementation, see https://github.com/tokenbound/contracts. If you want to add it yourself, you'll just need to add in the user operation validation functionality (and use ERC6551's execution functionality). -- Please refer to the official [ERC6551](https://github.com/erc6551/reference) reference +- Please refer to the official [ERC6551](https://github.com/erc6551/reference) reference for latest updates on the ERC6551 standard, as well as canonical registry information. Inherits: -- `utils/UUPSUpgradeable.sol` -- `accounts/Receiver.sol` -- `accounts/ERC1271.sol` +- [`utils/UUPSUpgradeable.sol`](utils/uupsupgradeable.md) +- [`accounts/Receiver.sol`](accounts/receiver.md) +- [`accounts/ERC1271.sol`](accounts/erc1271.md) diff --git a/docs/accounts/erc6551proxy.md b/docs/accounts/erc6551proxy.md index ffed2e170..d155dad2b 100644 --- a/docs/accounts/erc6551proxy.md +++ b/docs/accounts/erc6551proxy.md @@ -3,7 +3,18 @@ Relay proxy for upgradeable ERC6551 accounts. +Note: +This relay proxy is required for upgradeable ERC6551 accounts. + +ERC6551 clone -> ERC6551Proxy (relay) -> ERC6551 account implementation. + +This relay proxy also allows for correctly revealing the +"Read as Proxy" and "Write as Proxy" tabs on Etherscan. + +After using the registry to deploy a ERC6551 clone pointing to this relay proxy, +users must send 0 ETH to the clone before clicking on "Is this a proxy?" on Etherscan. +Verification of this relay proxy on Etherscan is optional. diff --git a/docs/accounts/erc7821.md b/docs/accounts/erc7821.md index a085a3612..70f9dcffe 100644 --- a/docs/accounts/erc7821.md +++ b/docs/accounts/erc7821.md @@ -7,7 +7,7 @@ Minimal batch executor mixin. Inherits: -- `accounts/Receiver.sol` +- [`accounts/Receiver.sol`](accounts/receiver.md) diff --git a/docs/accounts/timelock.md b/docs/accounts/timelock.md index 48fff2a33..0d53d94cb 100644 --- a/docs/accounts/timelock.md +++ b/docs/accounts/timelock.md @@ -3,12 +3,33 @@ Simple timelock. - +Note: + +- This implementation only supports ERC7821 style execution. +- This implementation uses EnumerableRoles for better auditability. +- This implementation uses custom errors with arguments for easier debugging. +- `executionData` can be encoded in three different ways: + 1. `abi.encode(calls)`. + 2. `abi.encode(calls, abi.encode(predecessor))`. + 3. `abi.encode(calls, abi.encode(predecessor, salt))`. +- Where `calls` is of type `(address,uint256,bytes)[]`, and +`predecessor` is the id of the proposal that is required to be already executed. +- If `predecessor` is `bytes32(0)`, it will be ignored (treated as if not required). +- The optional `salt` allows for multiple proposals representing the same payload. +- The proposal id is given by: +`keccak256(abi.encode(mode, keccak256(executionData)))`. + +Supported modes: +- `bytes32(0x01000000000000000000...)`: does not support optional `opData`. +- `bytes32(0x01000000000078210001...)`: supports optional `opData`. +Where `opData` is `abi.encode(predecessor)` or `abi.encode(predecessor, salt)`, +and `...` is the remaining 22 bytes which can be anything. For ease of mind, just use: +`0x0100000000007821000100000000000000000000000000000000000000000000`. Inherits: -- `accounts/ERC7821.sol` -- `auth/EnumerableRoles.sol` +- [`accounts/ERC7821.sol`](accounts/erc7821.md) +- [`auth/EnumerableRoles.sol`](auth/enumerableroles.md) diff --git a/docs/auth/ownableroles.md b/docs/auth/ownableroles.md index 6f7f74e17..e45efc8c6 100644 --- a/docs/auth/ownableroles.md +++ b/docs/auth/ownableroles.md @@ -14,7 +14,7 @@ the nomenclature for the 2-step ownership handover may be unique to this codebas Inherits: -- `auth/Ownable.sol` +- [`auth/Ownable.sol`](auth/ownable.md) diff --git a/docs/tokens/erc1155.md b/docs/tokens/erc1155.md index b125ec516..65361887b 100644 --- a/docs/tokens/erc1155.md +++ b/docs/tokens/erc1155.md @@ -13,7 +13,7 @@ to copy memory internally. If you are overriding: - Make sure all variables written to storage are properly cleaned -// (e.g. the bool value for `isApprovedForAll` MUST be either 1 or 0 under the hood). +(e.g. the bool value for `isApprovedForAll` MUST be either 1 or 0 under the hood). - Check that the overridden function is actually used in the function you want to change the behavior of. Much of the code has been manually inlined for performance. diff --git a/docs/tokens/erc20.md b/docs/tokens/erc20.md index 44a446dc9..91ecb60f9 100644 --- a/docs/tokens/erc20.md +++ b/docs/tokens/erc20.md @@ -12,7 +12,7 @@ Please add any checks with overrides if desired. - The `permit` function uses the ecrecover precompile (0x1). If you are overriding: -- NEVER violate the ERC20 invariant: +- NEVER violate the ERC20 invariant: the total sum of all balances must be equal to `totalSupply()`. - Check that the overridden function is actually used in the function you want to change the behavior of. Much of the code has been manually inlined for performance. diff --git a/docs/tokens/erc20votes.md b/docs/tokens/erc20votes.md index f7c1d4eb2..0b16aecff 100644 --- a/docs/tokens/erc20votes.md +++ b/docs/tokens/erc20votes.md @@ -7,7 +7,7 @@ ERC20 with votes based on ERC5805 and ERC6372. Inherits: -- `tokens/ERC20.sol` +- [`tokens/ERC20.sol`](tokens/erc20.md) diff --git a/docs/tokens/erc4626.md b/docs/tokens/erc4626.md index a1238ea15..217a325cb 100644 --- a/docs/tokens/erc4626.md +++ b/docs/tokens/erc4626.md @@ -7,7 +7,7 @@ Simple ERC4626 tokenized Vault implementation. Inherits: -- `tokens/ERC20.sol` +- [`tokens/ERC20.sol`](tokens/erc20.md) diff --git a/docs/tokens/erc6909.md b/docs/tokens/erc6909.md index 95e64cb4e..5fc70a604 100644 --- a/docs/tokens/erc6909.md +++ b/docs/tokens/erc6909.md @@ -12,7 +12,7 @@ Please add any checks with overrides if desired. If you are overriding: - Make sure all variables written to storage are properly cleaned -// (e.g. the bool value for `isOperator` MUST be either 1 or 0 under the hood). +(e.g. the bool value for `isOperator` MUST be either 1 or 0 under the hood). - Check that the overridden function is actually used in the function you want to change the behavior of. Much of the code has been manually inlined for performance. diff --git a/docs/tokens/erc721.md b/docs/tokens/erc721.md index c103ca99b..01f98eea9 100644 --- a/docs/tokens/erc721.md +++ b/docs/tokens/erc721.md @@ -13,11 +13,11 @@ Please add any checks with overrides if desired. to copy memory internally. If you are overriding: -- NEVER violate the ERC721 invariant: +- NEVER violate the ERC721 invariant: the balance of an owner MUST always be equal to their number of ownership slots. The transfer functions do not have an underflow guard for user token balances. - Make sure all variables written to storage are properly cleaned -// (e.g. the bool value for `isApprovedForAll` MUST be either 1 or 0 under the hood). +(e.g. the bool value for `isApprovedForAll` MUST be either 1 or 0 under the hood). - Check that the overridden function is actually used in the function you want to change the behavior of. Much of the code has been manually inlined for performance. diff --git a/docs/tokens/weth.md b/docs/tokens/weth.md index aa90f33a1..d1fd2bc17 100644 --- a/docs/tokens/weth.md +++ b/docs/tokens/weth.md @@ -7,7 +7,7 @@ Simple Wrapped Ether implementation. Inherits: -- `tokens/ERC20.sol` +- [`tokens/ERC20.sol`](tokens/erc20.md) diff --git a/docs/utils/datetimelib.md b/docs/utils/datetimelib.md index 476f7dbab..57ee3fff7 100644 --- a/docs/utils/datetimelib.md +++ b/docs/utils/datetimelib.md @@ -4,17 +4,17 @@ Library for date time operations. Conventions: ---------------------------------------------------------------------+ -Unit | Range | Notes | ---------------------------------------------------------------------| -timestamp | 0..0x1e18549868c76ff | Unix timestamp. | -epochDay | 0..0x16d3e098039 | Days since 1970-01-01. | -year | 1970..0xffffffff | Gregorian calendar year. | -month | 1..12 | Gregorian calendar month. | -day | 1..31 | Gregorian calendar day of month. | -weekday | 1..7 | The day of the week (1-indexed). | ---------------------------------------------------------------------+ -All timestamps of days are rounded down to 00:00:00 UTC. + +| Unit | Range | Notes | +| -- | -- | -- | +| timestamp | 0..0x1e18549868c76ff | Unix timestamp. | +| epochDay | 0..0x16d3e098039 | Days since 1970-01-01. | +| year | 1970..0xffffffff | Gregorian calendar year. | +| month | 1..12 | Gregorian calendar month. | +| day | 1..31 | Gregorian calendar day of month. | +| weekday | 1..7 | The day of the week (1-indexed). | + +All timestamps of days are rounded down to 00:00:00 UTC. diff --git a/docs/utils/deploylesspredeployqueryer.md b/docs/utils/deploylesspredeployqueryer.md index 473516650..746148d65 100644 --- a/docs/utils/deploylesspredeployqueryer.md +++ b/docs/utils/deploylesspredeployqueryer.md @@ -3,7 +3,16 @@ Deployless queryer for predeploys. +This contract is not meant to ever actually be deployed, +only mock deployed and used via a static `eth_call`. +Creation code (hex-encoded): +`3860b63d393d516020805190606051833b15607e575b5059926040908285528351938460051b9459523d604087015260005b858103603e578680590390f35b6000828683820101510138908688820151910147875af115607457603f19875903018482890101523d59523d6000593e84016031565b3d6000803e3d6000fd5b816000828193519083479101906040515af11560ad5783815114601f3d111660155763d1f6b81290526004601cfd5b3d81803e3d90fdfe` +See: https://gist.github.com/Vectorized/f77fce00a03dfa99aee526d2a77fd2aa + +May be useful for generating ERC-6492 compliant signatures. +Inspired by Ambire's DeploylessUniversalSigValidator +(https://github.com/AmbireTech/signature-validator/blob/main/contracts/DeploylessUniversalSigValidator.sol) diff --git a/docs/utils/erc1967factoryconstants.md b/docs/utils/erc1967factoryconstants.md index 983c02e9c..b9f9a0b4f 100644 --- a/docs/utils/erc1967factoryconstants.md +++ b/docs/utils/erc1967factoryconstants.md @@ -16,12 +16,12 @@ please refer to 0age's ImmutableCreate2Factory deployment instructions at: https://github.com/ProjectOpenSea/seaport/blob/main/docs/Deployment.md Contract verification: -- Source code: +- Source code: https://github.com/Vectorized/solady/blob/5212e50fef1f2ff1b1b5e03a5d276a0d23c02713/src/utils/ERC1967Factory.sol (The EXACT source code is required. Use the file at the commit instead of the latest copy.) -- Optimization Enabled: Yes with 1000000 runs -- Compiler Version: v0.8.19+commit.7dd6d404 -- Other Settings: default evmVersion, MIT license +- Optimization Enabled: Yes with 1000000 runs +- Compiler Version: v0.8.19+commit.7dd6d404 +- Other Settings: default evmVersion, MIT license diff --git a/docs/utils/libzip.md b/docs/utils/libzip.md index 773f92042..caa9bc685 100644 --- a/docs/utils/libzip.md +++ b/docs/utils/libzip.md @@ -5,7 +5,8 @@ Library for compressing and decompressing bytes. Note: -The accompanying solady.js +The accompanying solady.js library includes implementations of +FastLZ and calldata operations for convenience. diff --git a/docs/utils/lifebuoy.md b/docs/utils/lifebuoy.md index 854000156..f32a46945 100644 --- a/docs/utils/lifebuoy.md +++ b/docs/utils/lifebuoy.md @@ -3,7 +3,38 @@ Class that allows for rescue of ETH, ERC20, ERC721 tokens. - +This contract is created to mitigate the following disasters: + +- Careless user sends tokens to the wrong chain or wrong contract. +- Careless dev deploys a contract without a withdraw function in attempt to rescue +careless user's tokens, due to deployment nonce mismatch caused by +script misfire / misconfiguration. +- Careless dev forgets to add a withdraw function to a NFT sale contract. + +Note: + +if you are deploying via a untrusted `tx.origin`, +you MUST override `_lifebuoyDefaultDeployer` to return a trusted address. + +For best safety: +- For non-escrow contracts, inherit Lifebuoy as much as possible, +and leave it unlocked. +- For escrow contracts, lock access as tight as possible, +as soon as possible. Or simply don't inherit Lifebuoy. Escrow: Your contract is designed to hold ETH, ERC20s, ERC721s +(e.g. liquidity pools). + +All rescue and rescue authorization functions require either: +- Caller is the deployer +AND the contract is not a proxy +AND `rescueLocked() & _LIFEBUOY_DEPLOYER_ACCESS_LOCK == 0`. +- Caller is `owner()` +AND `rescueLocked() & _LIFEBUOY_OWNER_ACCESS_LOCK == 0`. + +The choice of using bit flags to represent locked statuses is for +efficiency, flexibility, convenience. + +This contract is optimized with a priority on minimal bytecode size, +as the methods are not intended to be called often. diff --git a/docs/utils/upgradeablebeacon.md b/docs/utils/upgradeablebeacon.md index 5f9692375..cac53665d 100644 --- a/docs/utils/upgradeablebeacon.md +++ b/docs/utils/upgradeablebeacon.md @@ -3,7 +3,21 @@ Upgradeable beacon for ERC1967 beacon proxies. +Note: +- The implementation is intended to be used with ERC1967 beacon proxies. See: `LibClone.deployERC1967BeaconProxy` and related functions. +- For gas efficiency, the ownership functionality is baked into this contract. + +Optimized creation code (hex-encoded): +`60406101c73d393d5160205180821760a01c3d3d3e803b1560875781684343a0dc92ed22dbfc558068911c5a209f08d5ec5e557fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b3d38a23d7f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e03d38a3610132806100953d393df35b636d3e283b3d526004601cfdfe3d3560e01c635c60da1b14610120573d3560e01c80638da5cb5b1461010e5780633659cfe61460021b8163f2fde38b1460011b179063715018a6141780153d3d3e684343a0dc92ed22dbfc805490813303610101573d9260068116610089575b508290557f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e03d38a3005b925060048035938460a01c60243610173d3d3e146100ba5782156100ad573861005f565b637448fbae3d526004601cfd5b82803b156100f4578068911c5a209f08d5ec5e557fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b3d38a2005b636d3e283b3d526004601cfd5b6382b429003d526004601cfd5b684343a0dc92ed22dbfc543d5260203df35b68911c5a209f08d5ec5e543d5260203df3`. +See: https://gist.github.com/Vectorized/365bd7f6e9a848010f00adb9e50a2516 + +To get the initialization code: +`abi.encodePacked(creationCode, abi.encode(initialOwner, initialImplementation))` + +This optimized bytecode is compiled via Yul and is not verifiable via Etherscan +at the time of writing. For best gas efficiency, deploy the Yul version. +The Solidity version is provided as an interface / reference. diff --git a/docs/utils/uupsupgradeable.md b/docs/utils/uupsupgradeable.md index 2fd6ce428..a654df703 100644 --- a/docs/utils/uupsupgradeable.md +++ b/docs/utils/uupsupgradeable.md @@ -5,8 +5,7 @@ UUPS proxy mixin. Note: -- This implementation is intended to be used with ERC1967 proxies. -See: `LibClone.deployERC1967` and related functions. +- This implementation is intended to be used with ERC1967 proxies. See: `LibClone.deployERC1967` and related functions. - This implementation is NOT compatible with legacy OpenZeppelin proxies which do not store the implementation at `_ERC1967_IMPLEMENTATION_SLOT`. diff --git a/prep/gen-docs.js b/prep/gen-docs.js index c992bd371..d8b6e7d88 100644 --- a/prep/gen-docs.js +++ b/prep/gen-docs.js @@ -140,16 +140,26 @@ async function main() { }; const getTopIntro = s => coalesce( - s.match(/\/\/\/\s+@notice\s+[\s\S]+?(?:\/\/\/\s?@author\s+[\s\S]+?\n|\/\/\/\s+\([\s\S]+?\)\n)+([\s\S]*?)(?:library|(?:abstract\s+?)contract)\s[\s\S]+?\{/), + s.match(/\/\/\/\s+@notice\s+[\s\S]+?(?:\/\/\/\s?@author\s+[\s\S]+?\n|\/\/\/\s+\([\s\S]+?\)\n)+([\s\S]*?)(?:library|abstract\s+contract|contract)\s[^.]+\{/), m => normalizeNewlines(strip( m[1].replace('\n\n', '\n\n\n').split('\n') .map(l => l - .replace(/^\/\/\/\s*/, '') + .replace(/(\d\d)\:(\d\d)\:/g, '$1:$2:') + .replace(/^\/{2,3}\s{2,3}([1-9][0-9]*?)\.\s/, ' $1. ') + .replace(/^\/{2,3}\s*/, '') + .replace(/^(-\s+[\s\S]{1,64})\:/, '$1:') .replace(/^@dev\s?([\s\S]+?)\:/, '$1:\n\n') .replace(/^Note\:/, 'Note:\n\n') .replace(/^[\s\S]{1,64}\:/, m => has(m, 'http') ? m : '' + m + '') ).join('\n') + .replace(/\.\n\([\s\S]+?)\:\<\/b\>/, '. $1:') .replace(/@dev\s/g, '') + .replace(/\-{32,}\s?\+\s*?([\s\S]+)\-{32,}\s?\+/g, (m0, m1) => { + const lines = strip(m1.replace(/\-+\s*$/g, '')).split('\n'); + const n = Math.max.apply(null, lines.map(l => l.split('|').map(strip).filter(c => c.length).length)); + const h = '|' + Array(n + 1).join(' -- |'); + return '\n\n' + lines.map(l => l.match(/\-{32,}\s?\|/) ? h : '| ' + l).join('\n') + '\n\n'; + }) )) ); @@ -224,6 +234,17 @@ async function main() { }); if (docSrcPaths.length) { + docSrcPaths.forEach(p => { + writeSync( + getDocPath(p), + readSync(getDocPath(p)) + .replace(/((?:See\:)?\s)`([A-Za-z0-9\/]+?\.sol)`/ig, (m0, m1, m2) => { + if (!m0.match(/^See\:/i) && !m2.match(/\.sol$/i)) return m0; + let l = docSrcPaths.filter(q => has(q, getTitle(m2))); + return l.length ? m1 + '[`' + m2 + '`](' + getDocSubPath(l[0]) + ')' : m0; + }) + ); + }); const sidebarDocPath = path.join('docs', 'sidebar.md'); writeSync( sidebarDocPath,