From 2d85958413d4b4beae0088c90cd1e7f9f4876d37 Mon Sep 17 00:00:00 2001 From: Vectorized Date: Wed, 25 Dec 2024 00:19:42 +0800 Subject: [PATCH] =?UTF-8?q?=F0=9F=93=9D=20Documentation=20(#659)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: melancholicxxx <118432717+melancholicxxx@users.noreply.github.com> Co-authored-by: 0xlgtm --- README.md | 8 + docs/.nojekyll | 0 docs/accounts/erc1271.md | 172 +++ docs/accounts/erc4337.md | 375 +++++ docs/accounts/erc4337factory.md | 53 + docs/accounts/erc6551.md | 303 ++++ docs/accounts/erc6551proxy.md | 32 + docs/accounts/erc7821.md | 135 ++ docs/accounts/liberc6551.md | 167 +++ docs/accounts/liberc7579.md | 269 ++++ docs/accounts/receiver.md | 74 + docs/accounts/timelock.md | 263 ++++ docs/assets/css/prism-theme.css | 149 ++ docs/assets/fontello/LICENSE.txt | 21 + docs/assets/fontello/README.txt | 75 + docs/assets/fontello/css/fontello.css | 61 + docs/assets/fontello/font/fontello.eot | Bin 0 -> 7404 bytes docs/assets/fontello/font/fontello.svg | 20 + docs/assets/fontello/font/fontello.ttf | Bin 0 -> 7236 bytes docs/assets/fontello/font/fontello.woff | Bin 0 -> 4316 bytes docs/assets/fontello/font/fontello.woff2 | Bin 0 -> 3576 bytes docs/assets/img/favicon.png | Bin 0 -> 1833 bytes docs/assets/img/preview.png | Bin 0 -> 11624 bytes docs/auth/enumerableroles.md | 244 +++ docs/auth/ownable.md | 209 +++ docs/auth/ownableroles.md | 219 +++ docs/auth/timedroles.md | 226 +++ docs/index.html | 359 +++++ docs/overview.md | 35 + docs/sidebar.md | 84 ++ docs/tokens/erc1155.md | 434 ++++++ docs/tokens/erc20.md | 347 +++++ docs/tokens/erc20votes.md | 240 +++ docs/tokens/erc2981.md | 110 ++ docs/tokens/erc4626.md | 482 ++++++ docs/tokens/erc6909.md | 262 ++++ docs/tokens/erc721.md | 570 +++++++ docs/tokens/weth.md | 67 + docs/utils/base64.md | 71 + docs/utils/create3.md | 83 ++ docs/utils/datetimelib.md | 467 ++++++ docs/utils/deploylesspredeployqueryer.md | 20 + docs/utils/dynamicarraylib.md | 977 ++++++++++++ docs/utils/dynamicbufferlib.md | 1723 ++++++++++++++++++++++ docs/utils/ecdsa.md | 248 ++++ docs/utils/efficienthashlib.md | 689 +++++++++ docs/utils/eip712.md | 86 ++ docs/utils/enumerablemaplib.md | 915 ++++++++++++ docs/utils/enumerablesetlib.md | 413 ++++++ docs/utils/erc1967factory.md | 243 +++ docs/utils/erc1967factoryconstants.md | 70 + docs/utils/fixedpointmathlib.md | 823 +++++++++++ docs/utils/gasburnerlib.md | 41 + docs/utils/initializable.md | 112 ++ docs/utils/jsonparserlib.md | 351 +++++ docs/utils/libbit.md | 137 ++ docs/utils/libbitmap.md | 135 ++ docs/utils/libbytes.md | 390 +++++ docs/utils/libcall.md | 139 ++ docs/utils/libclone.md | 1706 +++++++++++++++++++++ docs/utils/libmap.md | 314 ++++ docs/utils/libprng.md | 325 ++++ docs/utils/librlp.md | 212 +++ docs/utils/libsort.md | 521 +++++++ docs/utils/libstring.md | 819 ++++++++++ docs/utils/libtransient.md | 745 ++++++++++ docs/utils/libzip.md | 91 ++ docs/utils/lifebuoy.md | 262 ++++ docs/utils/merkleprooflib.md | 102 ++ docs/utils/metadatareaderlib.md | 181 +++ docs/utils/minheaplib.md | 249 ++++ docs/utils/multicallable.md | 75 + docs/utils/p256.md | 114 ++ docs/utils/redblacktreelib.md | 266 ++++ docs/utils/reentrancyguard.md | 38 + docs/utils/reentrancyguardtransient.md | 54 + docs/utils/safecastlib.md | 786 ++++++++++ docs/utils/safetransferlib.md | 382 +++++ docs/utils/signaturecheckerlib.md | 231 +++ docs/utils/sstore2.md | 162 ++ docs/utils/upgradeablebeacon.md | 160 ++ docs/utils/uupsupgradeable.md | 78 + docs/utils/webauthn.md | 187 +++ prep/common.js | 34 +- prep/gen-docs.js | 248 ++++ 85 files changed, 22538 insertions(+), 2 deletions(-) create mode 100644 docs/.nojekyll create mode 100644 docs/accounts/erc1271.md create mode 100644 docs/accounts/erc4337.md create mode 100644 docs/accounts/erc4337factory.md create mode 100644 docs/accounts/erc6551.md create mode 100644 docs/accounts/erc6551proxy.md create mode 100644 docs/accounts/erc7821.md create mode 100644 docs/accounts/liberc6551.md create mode 100644 docs/accounts/liberc7579.md create mode 100644 docs/accounts/receiver.md create mode 100644 docs/accounts/timelock.md create mode 100644 docs/assets/css/prism-theme.css create mode 100755 docs/assets/fontello/LICENSE.txt create mode 100755 docs/assets/fontello/README.txt create mode 100755 docs/assets/fontello/css/fontello.css create mode 100755 docs/assets/fontello/font/fontello.eot create mode 100755 docs/assets/fontello/font/fontello.svg create mode 100755 docs/assets/fontello/font/fontello.ttf create mode 100755 docs/assets/fontello/font/fontello.woff create mode 100755 docs/assets/fontello/font/fontello.woff2 create mode 100644 docs/assets/img/favicon.png create mode 100644 docs/assets/img/preview.png create mode 100644 docs/auth/enumerableroles.md create mode 100644 docs/auth/ownable.md create mode 100644 docs/auth/ownableroles.md create mode 100644 docs/auth/timedroles.md create mode 100644 docs/index.html create mode 100644 docs/overview.md create mode 100644 docs/sidebar.md create mode 100644 docs/tokens/erc1155.md create mode 100644 docs/tokens/erc20.md create mode 100644 docs/tokens/erc20votes.md create mode 100644 docs/tokens/erc2981.md create mode 100644 docs/tokens/erc4626.md create mode 100644 docs/tokens/erc6909.md create mode 100644 docs/tokens/erc721.md create mode 100644 docs/tokens/weth.md create mode 100644 docs/utils/base64.md create mode 100644 docs/utils/create3.md create mode 100644 docs/utils/datetimelib.md create mode 100644 docs/utils/deploylesspredeployqueryer.md create mode 100644 docs/utils/dynamicarraylib.md create mode 100644 docs/utils/dynamicbufferlib.md create mode 100644 docs/utils/ecdsa.md create mode 100644 docs/utils/efficienthashlib.md create mode 100644 docs/utils/eip712.md create mode 100644 docs/utils/enumerablemaplib.md create mode 100644 docs/utils/enumerablesetlib.md create mode 100644 docs/utils/erc1967factory.md create mode 100644 docs/utils/erc1967factoryconstants.md create mode 100644 docs/utils/fixedpointmathlib.md create mode 100644 docs/utils/gasburnerlib.md create mode 100644 docs/utils/initializable.md create mode 100644 docs/utils/jsonparserlib.md create mode 100644 docs/utils/libbit.md create mode 100644 docs/utils/libbitmap.md create mode 100644 docs/utils/libbytes.md create mode 100644 docs/utils/libcall.md create mode 100644 docs/utils/libclone.md create mode 100644 docs/utils/libmap.md create mode 100644 docs/utils/libprng.md create mode 100644 docs/utils/librlp.md create mode 100644 docs/utils/libsort.md create mode 100644 docs/utils/libstring.md create mode 100644 docs/utils/libtransient.md create mode 100644 docs/utils/libzip.md create mode 100644 docs/utils/lifebuoy.md create mode 100644 docs/utils/merkleprooflib.md create mode 100644 docs/utils/metadatareaderlib.md create mode 100644 docs/utils/minheaplib.md create mode 100644 docs/utils/multicallable.md create mode 100644 docs/utils/p256.md create mode 100644 docs/utils/redblacktreelib.md create mode 100644 docs/utils/reentrancyguard.md create mode 100644 docs/utils/reentrancyguardtransient.md create mode 100644 docs/utils/safecastlib.md create mode 100644 docs/utils/safetransferlib.md create mode 100644 docs/utils/signaturecheckerlib.md create mode 100644 docs/utils/sstore2.md create mode 100644 docs/utils/upgradeablebeacon.md create mode 100644 docs/utils/uupsupgradeable.md create mode 100644 docs/utils/webauthn.md create mode 100644 prep/gen-docs.js diff --git a/README.md b/README.md index ce7e0150a..7b4575eed 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,7 @@ [![NPM][npm-shield]][npm-url] [![CI][ci-shield]][ci-url] [![Solidity][solidity-shield]][solidity-ci-url] +[![Docs][docs-shield]][docs-url] Gas optimized Solidity snippets. @@ -22,6 +23,10 @@ To install with [**Hardhat**](https://github.com/nomiclabs/hardhat): npm install solady ``` +## Documentation + +https://vectorized.github.io/solady + ## Contracts The Solidity smart contracts are located in the `src` directory. @@ -158,3 +163,6 @@ This repository is inspired by or directly modified from many sources, primarily [solidity-shield]: https://img.shields.io/badge/solidity-%3E=0.8.4%20%3C=0.8.28-aa6746 [solidity-ci-url]: https://github.com/Vectorized/solady/actions/workflows/ci-all-via-ir.yml + +[docs-shield]: https://img.shields.io/badge/docs-%F0%9F%93%84-blue +[docs-url]: https://vectorized.github.io/solady diff --git a/docs/.nojekyll b/docs/.nojekyll new file mode 100644 index 000000000..e69de29bb diff --git a/docs/accounts/erc1271.md b/docs/accounts/erc1271.md new file mode 100644 index 000000000..a68fb2163 --- /dev/null +++ b/docs/accounts/erc1271.md @@ -0,0 +1,172 @@ +# ERC1271 + +ERC1271 mixin with nested EIP-712 approach. + + + + +Inherits: + +- `utils/EIP712.sol` + + + + +## Constants + +### _PERSONAL_SIGN_TYPEHASH + +```solidity +bytes32 internal constant _PERSONAL_SIGN_TYPEHASH = + 0x983e65e5148e570cd828ead231ee759a8d7958721a768f93bc4483ba005c32de +``` + +`keccak256("PersonalSign(bytes prefixed)")`. + +## ERC1271 Operations + +### isValidSignature(bytes32,bytes) + +```solidity +function isValidSignature(bytes32 hash, bytes calldata signature) + public + view + virtual + returns (bytes4 result) +``` + +Validates the signature with ERC1271 return, +so that this account can also be used as a signer. + +### _erc1271IsValidSignatureNowCalldata(bytes32,bytes) + +```solidity +function _erc1271IsValidSignatureNowCalldata( + bytes32 hash, + bytes calldata signature +) internal view virtual returns (bool) +``` + +Returns whether the `hash` and `signature` are valid. +Override if you need non-ECDSA logic. + +### _erc1271UnwrapSignature(bytes) + +```solidity +function _erc1271UnwrapSignature(bytes calldata signature) + internal + view + virtual + returns (bytes calldata result) +``` + +Unwraps and returns the signature. + +### _erc1271IsValidSignature(bytes32,bytes) + +```solidity +function _erc1271IsValidSignature(bytes32 hash, bytes calldata signature) + internal + view + virtual + returns (bool) +``` + +Returns whether the `signature` is valid for the `hash. + +### _erc1271IsValidSignatureViaSafeCaller(bytes32,bytes) + +```solidity +function _erc1271IsValidSignatureViaSafeCaller( + bytes32 hash, + bytes calldata signature +) internal view virtual returns (bool result) +``` + +Performs the signature validation without nested EIP-712 if the caller is +a safe caller. A safe caller must include the address of this account in the hash. + +### _erc1271IsValidSignatureViaNestedEIP712(bytes32,bytes) + +```solidity +function _erc1271IsValidSignatureViaNestedEIP712( + bytes32 hash, + bytes calldata signature +) internal view virtual returns (bool result) +``` + +ERC1271 signature validation (Nested EIP-712 workflow). +This uses ECDSA recovery by default (see: `_erc1271IsValidSignatureNowCalldata`). +It also uses a nested EIP-712 approach to prevent signature replays when a single EOA +owns multiple smart contract accounts, +while still enabling wallet UIs (e.g. Metamask) to show the EIP-712 values. +Crafted for phishing resistance, efficiency, flexibility. +__________________________________________________________________________________________ +Glossary: +- `APP_DOMAIN_SEPARATOR`: The domain separator of the `hash` passed in by the application. + Provided by the front end. Intended to be the domain separator of the contract + that will call `isValidSignature` on this account. +- `ACCOUNT_DOMAIN_SEPARATOR`: The domain separator of this account. + See: `EIP712._domainSeparator()`. +__________________________________________________________________________________________ +For the `TypedDataSign` workflow, the final hash will be: +```solidity +keccak256(\x19\x01 ‖ APP_DOMAIN_SEPARATOR ‖ + hashStruct(TypedDataSign({ + contents: hashStruct(originalStruct), + name: keccak256(bytes(eip712Domain().name)), + version: keccak256(bytes(eip712Domain().version)), + chainId: eip712Domain().chainId, + verifyingContract: eip712Domain().verifyingContract, + salt: eip712Domain().salt + })) +) +``` +where `‖` denotes the concatenation operator for bytes. +The order of the fields is important: `contents` comes before `name`. +The signature will be `r ‖ s ‖ v ‖ APP_DOMAIN_SEPARATOR ‖ +contents ‖ contentsDescription ‖ uint16(contentsDescription.length)`, +where: +- `contents` is the bytes32 struct hash of the original struct. +- `contentsDescription` can be either: +a) `contentsType` (implicit mode) + where `contentsType` starts with `contentsName`. +b) `contentsType ‖ contentsName` (explicit mode) + where `contentsType` may not necessarily start with `contentsName`. +The `APP_DOMAIN_SEPARATOR` and `contents` will be used to verify if `hash` is indeed correct. +__________________________________________________________________________________________ +For the `PersonalSign` workflow, the final hash will be: +```solidity +keccak256(\x19\x01 ‖ ACCOUNT_DOMAIN_SEPARATOR ‖ + hashStruct(PersonalSign({ + prefixed: keccak256(bytes(\x19Ethereum Signed Message:\n ‖ + base10(bytes(someString).length) ‖ someString)) + })) +) +``` +where `‖` denotes the concatenation operator for bytes. +The `PersonalSign` type hash will be `keccak256("PersonalSign(bytes prefixed)")`. +The signature will be `r ‖ s ‖ v`. +__________________________________________________________________________________________ +For demo and typescript code, see: +- https://github.com/junomonster/nested-eip-712 +- https://github.com/frangio/eip712-wrapper-for-eip1271 +Their nomenclature may differ from ours, although the high-level idea is similar. +Of course, if you have control over the codebase of the wallet client(s) too, +you can choose a more minimalistic signature scheme like +`keccak256(abi.encode(address(this), hash))` instead of all these acrobatics. +All these are just for widespread out-of-the-box compatibility with other wallet clients. +We want to create bazaars, not walled castles. +And we'll use push the Turing Completeness of the EVM to the limits to do so. + +### _erc1271IsValidSignatureViaRPC(bytes32,bytes) + +```solidity +function _erc1271IsValidSignatureViaRPC( + bytes32 hash, + bytes calldata signature +) internal view virtual returns (bool result) +``` + +Performs the signature validation without nested EIP-712 to allow for easy sign ins. +This function must always return false or revert if called on-chain. \ No newline at end of file diff --git a/docs/accounts/erc4337.md b/docs/accounts/erc4337.md new file mode 100644 index 000000000..114930edc --- /dev/null +++ b/docs/accounts/erc4337.md @@ -0,0 +1,375 @@ +# ERC4337 + +Simple ERC4337 account implementation. + + +Recommended usage: + +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`. + +Note: + +ERC4337 is a very complicated standard with many potential gotchas. +Also, it is subject to change and has not been finalized +(so accounts are encouraged to be upgradeable). +Usually, ERC4337 account implementations are developed by companies with ample funds +for security reviews. This implementation is intended to serve as a base reference +for smart account developers working in such companies. If you are using this +implementation, please do get one or more security reviews before deployment. + +Inherits: + +- `auth/Ownable.sol` +- `utils/UUPSUpgradeable.sol` +- `accounts/Receiver.sol` +- `accounts/ERC1271.sol` + + + + +## Structs + +### PackedUserOperation + +```solidity +struct PackedUserOperation { + address sender; + uint256 nonce; + bytes initCode; // Factory address and `factoryData` (or empty). + bytes callData; + bytes32 accountGasLimits; // `verificationGas` (16 bytes) and `callGas` (16 bytes). + uint256 preVerificationGas; + bytes32 gasFees; // `maxPriorityFee` (16 bytes) and `maxFeePerGas` (16 bytes). + bytes paymasterAndData; // Paymaster fields (or empty). + bytes signature; +} +``` + +The packed ERC4337 user operation (userOp) struct. + +### Call + +```solidity +struct Call { + address target; + uint256 value; + bytes data; +} +``` + +Call struct for the `executeBatch` function. + +## Constructor + +### _disableERC4337ImplementationInitializer() + +```solidity +function _disableERC4337ImplementationInitializer() internal virtual +``` + +Automatically initializes the owner for the implementation. This blocks someone +from initializing the implementation and doing a delegatecall to SELFDESTRUCT. +Proxies to the implementation will still be able to initialize as per normal. + +## Initializer + +### initialize(address) + +```solidity +function initialize(address newOwner) public payable virtual +``` + +Initializes the account with the owner. Can only be called once. + +## Entry Point + +### entryPoint() + +```solidity +function entryPoint() public view virtual returns (address) +``` + +Returns the canonical ERC4337 EntryPoint contract (0.7). +Override this function to return a different EntryPoint. + +## Validation Operations + +### validateUserOp(PackedUserOperation,bytes32,uint256) + +```solidity +function validateUserOp( + PackedUserOperation calldata userOp, + bytes32 userOpHash, + uint256 missingAccountFunds +) + external + payable + virtual + onlyEntryPoint + payPrefund(missingAccountFunds) + returns (uint256 validationData) +``` + +Validates the signature and nonce. +The EntryPoint will make the call to the recipient only if +this validation call returns successfully. +Signature failure should be reported by returning 1 (see: `_validateSignature`). +This allows making a "simulation call" without a valid signature. +Other failures (e.g. nonce mismatch, or invalid signature format) +should still revert to signal failure. + +### _validateSignature(PackedUserOperation,bytes32) + +```solidity +function _validateSignature( + PackedUserOperation calldata userOp, + bytes32 userOpHash +) internal virtual returns (uint256 validationData) +``` + +Validate `userOp.signature` for the `userOpHash`. + +### _validateNonce(uint256) + +```solidity +function _validateNonce(uint256 nonce) internal virtual +``` + +Override to validate the nonce of the userOp. +This method may validate the nonce requirement of this account. +e.g. +To limit the nonce to use sequenced userOps only (no "out of order" userOps): + `require(nonce < type(uint64).max)` +For a hypothetical account that *requires* the nonce to be out-of-order: + `require(nonce & type(uint64).max == 0)` +The actual nonce uniqueness is managed by the EntryPoint, and thus no other +action is needed by the account itself. + +### payPrefund(uint256) + +```solidity +modifier payPrefund(uint256 missingAccountFunds) virtual +``` + +Sends to the EntryPoint (i.e. `msg.sender`) the missing funds for this transaction. +Subclass MAY override this modifier for better funds management. +(e.g. send to the EntryPoint more than the minimum required, so that in future transactions +it will not be required to send again) +`missingAccountFunds` is the minimum value this modifier should send the EntryPoint, +which MAY be zero, in case there is enough deposit, or the userOp has a paymaster. + +### onlyEntryPoint() + +```solidity +modifier onlyEntryPoint() virtual +``` + +Requires that the caller is the EntryPoint. + +## Execution Operations + +### execute(address,uint256,bytes) + +```solidity +function execute(address target, uint256 value, bytes calldata data) + public + payable + virtual + onlyEntryPointOrOwner + returns (bytes memory result) +``` + +Execute a call from this account. + +### executeBatch(Call[]) + +```solidity +function executeBatch(Call[] calldata calls) + public + payable + virtual + onlyEntryPointOrOwner + returns (bytes[] memory results) +``` + +Execute a sequence of calls from this account. + +### delegateExecute(address,bytes) + +```solidity +function delegateExecute(address delegate, bytes calldata data) + public + payable + virtual + onlyEntryPointOrOwner + delegateExecuteGuard + returns (bytes memory result) +``` + +Execute a delegatecall with `delegate` on this account. + +### delegateExecuteGuard() + +```solidity +modifier delegateExecuteGuard() virtual +``` + +Ensures that the owner and implementation slots' values aren't changed. +You can override this modifier to ensure the sanctity of other storage slots too. + +### onlyEntryPointOrOwner() + +```solidity +modifier onlyEntryPointOrOwner() virtual +``` + +Requires that the caller is the EntryPoint, the owner, or the account itself. + +## Direct Storage Operations + +### storageLoad(bytes32) + +```solidity +function storageLoad(bytes32 storageSlot) + public + view + virtual + returns (bytes32 result) +``` + +Returns the raw storage value at `storageSlot`. + +### storageStore(bytes32,bytes32) + +```solidity +function storageStore(bytes32 storageSlot, bytes32 storageValue) + public + payable + virtual + onlyEntryPointOrOwner + storageStoreGuard(storageSlot) +``` + +Writes the raw storage value at `storageSlot`. + +### storageStoreGuard(bytes32) + +```solidity +modifier storageStoreGuard(bytes32 storageSlot) virtual +``` + +Ensures that the `storageSlot` is prohibited for direct storage writes. +You can override this modifier to ensure the sanctity of other storage slots too. + +## Deposit Operations + +### getDeposit() + +```solidity +function getDeposit() public view virtual returns (uint256 result) +``` + +Returns the account's balance on the EntryPoint. + +### addDeposit() + +```solidity +function addDeposit() public payable virtual +``` + +Deposit more funds for this account in the EntryPoint. + +### withdrawDepositTo(address,uint256) + +```solidity +function withdrawDepositTo(address to, uint256 amount) + public + payable + virtual + onlyOwner +``` + +Withdraw ETH from the account's deposit on the EntryPoint. + +## Overrides + +### _checkOwner() + +```solidity +function _checkOwner() internal view virtual override(Ownable) +``` + +Requires that the caller is the owner or the account itself. +This override affects the `onlyOwner` modifier. + +### _guardInitializeOwner() + +```solidity +function _guardInitializeOwner() + internal + pure + virtual + override(Ownable) + returns (bool) +``` + +To prevent double-initialization (reuses the owner storage slot for efficiency). + +### _erc1271Signer() + +```solidity +function _erc1271Signer() + internal + view + virtual + override(ERC1271) + returns (address) +``` + +Uses the `owner` as the ERC1271 signer. + +### _erc1271CallerIsSafe() + +```solidity +function _erc1271CallerIsSafe() + internal + view + virtual + override(ERC1271) + returns (bool) +``` + +Allow the entry point to skip the ERC7739 nested typed data workflow. +This is safe as the entry point already includes the smart account in the user op digest. + +### _authorizeUpgrade(address) + +```solidity +function _authorizeUpgrade(address) + internal + virtual + override(UUPSUpgradeable) + onlyOwner +``` + +To ensure that only the owner or the account itself can upgrade the implementation. + +### _useLibZipCdFallback() + +```solidity +function _useLibZipCdFallback() internal view virtual returns (bool) +``` + +If you don't need to use `LibZip.cdFallback`, override this function to return false. + +### fallback() + +```solidity +fallback() external payable virtual override(Receiver) receiverFallback +``` + +Handle token callbacks. If no token callback is triggered, +use `LibZip.cdFallback` for generalized calldata decompression. \ No newline at end of file diff --git a/docs/accounts/erc4337factory.md b/docs/accounts/erc4337factory.md new file mode 100644 index 000000000..b6f5f9ca2 --- /dev/null +++ b/docs/accounts/erc4337factory.md @@ -0,0 +1,53 @@ +# ERC4337Factory + +Simple ERC4337 account factory implementation. + + + + + + + + +## Immutables + +### implementation + +```solidity +address public immutable implementation +``` + +Address of the ERC4337 implementation. + +## Deploy Functions + +### createAccount(address,bytes32) + +```solidity +function createAccount(address owner, bytes32 salt) + public + payable + virtual + returns (address) +``` + +Deploys an ERC4337 account with `salt` and returns its deterministic address. +If the account is already deployed, it will simply return its address. +Any `msg.value` will simply be forwarded to the account, regardless. + +### getAddress(bytes32) + +```solidity +function getAddress(bytes32 salt) public view virtual returns (address) +``` + +Returns the deterministic address of the account created via `createAccount`. + +### initCodeHash() + +```solidity +function initCodeHash() public view virtual returns (bytes32) +``` + +Returns the initialization code hash of the ERC4337 account (a minimal ERC1967 proxy). +Used for mining vanity addresses with create2crunch. \ No newline at end of file diff --git a/docs/accounts/erc6551.md b/docs/accounts/erc6551.md new file mode 100644 index 000000000..a7d6f0dee --- /dev/null +++ b/docs/accounts/erc6551.md @@ -0,0 +1,303 @@ +# ERC6551 + +Simple ERC6551 account implementation. + + +Recommended usage (regular): + +1. Deploy the ERC6551 as an implementation contract, and verify it on Etherscan. +2. Use the canonical ERC6551Registry to deploy a clone to the ERC6551 implementation. +The UUPSUpgradeable functions will simply become no-ops. + +Recommended usage (upgradeable): +1. Deploy the ERC6551 as an implementation contract, and verify it on Etherscan. +2. Deploy the ERC6551Proxy pointing to the implementation. +This relay proxy is required, but Etherscan verification of it is optional. +3. Use the canonical ERC6551Registry to deploy a clone to the ERC6551Proxy. +If you want to reveal the "Read as Proxy" and "Write as Proxy" tabs on Etherscan, +send 0 ETH to the clone to initialize its ERC1967 implementation slot, +the click on "Is this a proxy?" on the clone's page on Etherscan. + +Note: + +- This implementation does NOT include ERC4337 functionality. +This is intentional, because the canonical ERC4337 entry point may still change and we +don't want to encourage upgradeability by default for ERC6551 accounts just to handle this. +We may include ERC4337 functionality once ERC4337 has been finalized. +Recent updates to the account abstraction validation scope rules +[ERC7562](https://eips.ethereum.org/EIPS/eip-7562) has made ERC6551 compatible with ERC4337. +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 +for latest updates on the ERC6551 standard, as well as canonical registry information. + +Inherits: + +- `utils/UUPSUpgradeable.sol` +- `accounts/Receiver.sol` +- `accounts/ERC1271.sol` + + + + +## Structs + +### Call + +```solidity +struct Call { + address target; + uint256 value; + bytes data; +} +``` + +Call struct for the `executeBatch` function. + +## Custom Errors + +### Unauthorized() + +```solidity +error Unauthorized() +``` + +The caller is not authorized to call the function. + +### OperationNotSupported() + +```solidity +error OperationNotSupported() +``` + +The operation is not supported. + +### SelfOwnDetected() + +```solidity +error SelfOwnDetected() +``` + +Self ownership detected. + +## Constants And Immutables + +### _ERC6551_STATE_SLOT + +```solidity +uint256 internal constant _ERC6551_STATE_SLOT = + 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffb919c7a5 +``` + +The ERC6551 state slot is given by: +`bytes32(~uint256(uint32(bytes4(keccak256("_ERC6551_STATE_SLOT_NOT")))))`. +It is intentionally chosen to be a high value +to avoid collision with lower slots. +The choice of manual storage layout is to enable compatibility +with both regular and upgradeable contracts. + +## Token-bound Ownership Operations + +### token() + +```solidity +function token() + public + view + virtual + returns (uint256 chainId, address tokenContract, uint256 tokenId) +``` + +Returns the token-bound information. + +### owner() + +```solidity +function owner() public view virtual returns (address result) +``` + +Returns the owner of the contract. + +### _isValidSigner(address,bytes32,bytes) + +```solidity +function _isValidSigner( + address signer, + bytes32 extraData, + bytes calldata context +) internal view virtual returns (bool) +``` + +Returns if `signer` is an authorized signer. +`extraData` can be anything (e.g. an address, a pointer to a struct / string in memory). + +### isValidSigner(address,bytes) + +```solidity +function isValidSigner(address signer, bytes calldata context) + public + view + virtual + returns (bytes4 result) +``` + +Returns if `signer` is an authorized signer, with an optional `context`. +MUST return the bytes4 magic value `0x523e3260` if the given signer is valid. +By default, the holder of the non-fungible token the account is bound to +MUST be considered a valid signer. + +### _emptyContext() + +```solidity +function _emptyContext() internal pure returns (bytes calldata context) +``` + +Returns empty calldata bytes. + +### onlyValidSigner() + +```solidity +modifier onlyValidSigner() virtual +``` + +Requires that the caller is a valid signer (i.e. the owner). + +## State Operations + +### state() + +```solidity +function state() public view virtual returns (bytes32 result) +``` + +Returns the current value of the state. + +### _updateState() + +```solidity +function _updateState() internal virtual +``` + +Mutates the state. This function is required to be called in every +public / external function that may modify storage or emit events. + +## Execution Operations + +### execute(address,uint256,bytes,uint8) + +```solidity +function execute( + address target, + uint256 value, + bytes calldata data, + uint8 operation +) public payable virtual onlyValidSigner returns (bytes memory result) +``` + +Execute a call from this account. +Reverts and bubbles up error if operation fails. +Returns the result of the operation. +Accounts MUST accept the following operation parameter values: +- 0 = CALL +- 1 = DELEGATECALL +- 2 = CREATE +- 3 = CREATE2 +Accounts MAY support additional operations or restrict a signer's +ability to execute certain operations. + +### executeBatch(Call[],uint8) + +```solidity +function executeBatch(Call[] calldata calls, uint8 operation) + public + payable + virtual + onlyValidSigner + returns (bytes[] memory results) +``` + +Execute a sequence of calls from this account. +Reverts and bubbles up error if an operation fails. +Returns the results of the operations. +This is a batch variant of `execute` and is not required for `IERC6551Executable`. + +## ERC165 + +### supportsInterface(bytes4) + +```solidity +function supportsInterface(bytes4 interfaceId) + public + view + virtual + returns (bool result) +``` + +Returns true if this contract implements the interface defined by `interfaceId`. +See: https://eips.ethereum.org/EIPS/eip-165 +This function call must use less than 30000 gas. + +## Internal Helpers + +### _hasOwnershipCycle() + +```solidity +function _hasOwnershipCycle() internal view virtual returns (bool result) +``` + +Returns whether there is an ownership cycle. + +## Overrides + +### _authorizeUpgrade(address) + +```solidity +function _authorizeUpgrade(address) + internal + virtual + override(UUPSUpgradeable) + onlyValidSigner +``` + +To ensure that only the owner or the account itself can upgrade the implementation. +If you don't need upgradeability, override this function to return false. + +### _erc1271Signer() + +```solidity +function _erc1271Signer() + internal + view + virtual + override(ERC1271) + returns (address) +``` + +Uses the `owner` as the ERC1271 signer. + +### receiverFallback() + +```solidity +modifier receiverFallback() override(Receiver) +``` + +For handling token callbacks. +Safe-transferred ERC721 tokens will trigger a ownership cycle check. + +### _useLibZipCdFallback() + +```solidity +function _useLibZipCdFallback() internal view virtual returns (bool) +``` + +If you don't need to use `LibZip.cdFallback`, override this function to return false. + +### fallback() + +```solidity +fallback() external payable virtual override(Receiver) receiverFallback +``` + +Handle token callbacks. If no token callback is triggered, +use `LibZip.cdFallback` for generalized calldata decompression. \ No newline at end of file diff --git a/docs/accounts/erc6551proxy.md b/docs/accounts/erc6551proxy.md new file mode 100644 index 000000000..ffed2e170 --- /dev/null +++ b/docs/accounts/erc6551proxy.md @@ -0,0 +1,32 @@ +# ERC6551Proxy + +Relay proxy for upgradeable ERC6551 accounts. + + + + + + + + +## Immutables + +### _defaultImplementation + +```solidity +bytes32 internal immutable _defaultImplementation +``` + +The default implementation. + +## Storage + +### _ERC1967_IMPLEMENTATION_SLOT + +```solidity +bytes32 internal constant _ERC1967_IMPLEMENTATION_SLOT = + 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc +``` + +The ERC-1967 storage slot for the implementation in the proxy. +`uint256(keccak256("eip1967.proxy.implementation")) - 1`. \ No newline at end of file diff --git a/docs/accounts/erc7821.md b/docs/accounts/erc7821.md new file mode 100644 index 000000000..a085a3612 --- /dev/null +++ b/docs/accounts/erc7821.md @@ -0,0 +1,135 @@ +# ERC7821 + +Minimal batch executor mixin. + + + + +Inherits: + +- `accounts/Receiver.sol` + + + + +## Structs + +### Call + +```solidity +struct Call { + address target; // Replaced as `address(this)` if `address(0)`. + uint256 value; // Amount of native currency (i.e. Ether) to send. + bytes data; // Calldata to send with the call. +} +``` + +Call struct for the `execute` function. + +## Custom Errors + +### UnsupportedExecutionMode() + +```solidity +error UnsupportedExecutionMode() +``` + +The execution mode is not supported. + +## Execution Operations + +### execute(bytes32,bytes) + +```solidity +function execute(bytes32 mode, bytes calldata executionData) + public + payable + virtual +``` + +Executes the calls in `executionData`. +Reverts and bubbles up error if any call fails. +`executionData` encoding: +- If `opData` is empty, `executionData` is simply `abi.encode(calls)`. +- Else, `executionData` is `abi.encode(calls, opData)`. + See: https://eips.ethereum.org/EIPS/eip-7579 +Supported modes: +- `bytes32(0x01000000000000000000...)`: does not support optional `opData`. +- `bytes32(0x01000000000078210001...)`: supports optional `opData`. +Authorization checks: +- If `opData` is empty, the implementation SHOULD require that + `msg.sender == address(this)`. +- If `opData` is not empty, the implementation SHOULD use the signature + encoded in `opData` to determine if the caller can perform the execution. +- If `msg.sender` is an authorized entry point, then `execute` MAY accept + calls from the entry point, and MAY use `opData` for specialized logic. +`opData` may be used to store additional data for authentication, +paymaster data, gas limits, etc. + +### supportsExecutionMode(bytes32) + +```solidity +function supportsExecutionMode(bytes32 mode) + public + view + virtual + returns (bool result) +``` + +Provided for execution mode support detection. + +## Internal Helpers + +### _executionModeId(bytes32) + +```solidity +function _executionModeId(bytes32 mode) + internal + view + virtual + returns (uint256 id) +``` + +0: invalid mode, 1: no `opData` support, 2: with `opData` support. + +### _execute(bytes32,bytes,Call[],bytes) + +```solidity +function _execute( + bytes32 mode, + bytes calldata executionData, + Call[] calldata calls, + bytes calldata opData +) internal virtual +``` + +Executes the calls. +Reverts and bubbles up error if any call fails. +The `mode` and `executionData` are passed along in case there's a need to use them. + +### _execute(Call[],bytes32) + +```solidity +function _execute(Call[] calldata calls, bytes32 extraData) + internal + virtual +``` + +Executes the calls. +Reverts and bubbles up error if any call fails. +`extraData` can be any supplementary data (e.g. a memory pointer, some hash). + +### _execute(address,uint256,bytes,bytes32) + +```solidity +function _execute( + address target, + uint256 value, + bytes calldata data, + bytes32 extraData +) internal virtual +``` + +Executes the call. +Reverts and bubbles up error if any call fails. +`extraData` can be any supplementary data (e.g. a memory pointer, some hash). \ No newline at end of file diff --git a/docs/accounts/liberc6551.md b/docs/accounts/liberc6551.md new file mode 100644 index 000000000..4bf7a9458 --- /dev/null +++ b/docs/accounts/liberc6551.md @@ -0,0 +1,167 @@ +# LibERC6551 + +Library for interacting with ERC6551 accounts. + + + + + + + + +## Custom Errors + +### AccountCreationFailed() + +```solidity +error AccountCreationFailed() +``` + +Failed to create a ERC6551 account via the registry. + +## Constants + +### REGISTRY + +```solidity +address internal constant REGISTRY = + 0x000000006551c19487814612e58FE06813775758 +``` + +The canonical ERC6551 registry address for EVM chains. + +### REGISTRY_BYTECODE + +```solidity +bytes internal constant REGISTRY_BYTECODE = + hex"608060405234801561001057600080fd5b50600436106100365760003560e01c8063246a00211461003b5780638a54c52f1461006a575b600080fd5b61004e6100493660046101b7565b61007d565b6040516001600160a01b03909116815260200160405180910390f35b61004e6100783660046101b7565b6100e1565b600060806024608c376e5af43d82803e903d91602b57fd5bf3606c5285605d52733d60ad80600a3d3981f3363d3d373d3d3d363d7360495260ff60005360b76055206035523060601b60015284601552605560002060601b60601c60005260206000f35b600060806024608c376e5af43d82803e903d91602b57fd5bf3606c5285605d52733d60ad80600a3d3981f3363d3d373d3d3d363d7360495260ff60005360b76055206035523060601b600152846015526055600020803b61018b578560b760556000f580610157576320188a596000526004601cfd5b80606c52508284887f79f19b3655ee38b1ce526556b7731a20c8f218fbda4a3990b6cc4172fdf887226060606ca46020606cf35b8060601b60601c60005260206000f35b80356001600160a01b03811681146101b257600080fd5b919050565b600080600080600060a086880312156101cf57600080fd5b6101d88661019b565b945060208601359350604086013592506101f46060870161019b565b94979396509194608001359291505056fea2646970667358221220ea2fe53af507453c64dd7c1db05549fa47a298dfb825d6d11e1689856135f16764736f6c63430008110033" +``` + +The canonical ERC6551 registry bytecode for EVM chains. +Useful for forge tests: +`vm.etch(REGISTRY, REGISTRY_BYTECODE)`. + +## Account Bytecode Operations + +### initCode(address,bytes32,uint256,address,uint256) + +```solidity +function initCode( + address implementation_, + bytes32 salt_, + uint256 chainId_, + address tokenContract_, + uint256 tokenId_ +) internal pure returns (bytes memory result) +``` + +Returns the initialization code of the ERC6551 account. + +### initCodeHash(address,bytes32,uint256,address,uint256) + +```solidity +function initCodeHash( + address implementation_, + bytes32 salt_, + uint256 chainId_, + address tokenContract_, + uint256 tokenId_ +) internal pure returns (bytes32 result) +``` + +Returns the initialization code hash of the ERC6551 account. + +### createAccount(address,bytes32,uint256,address,uint256) + +```solidity +function createAccount( + address implementation_, + bytes32 salt_, + uint256 chainId_, + address tokenContract_, + uint256 tokenId_ +) internal returns (address result) +``` + +Creates an account via the ERC6551 registry. + +### account(address,bytes32,uint256,address,uint256) + +```solidity +function account( + address implementation_, + bytes32 salt_, + uint256 chainId_, + address tokenContract_, + uint256 tokenId_ +) internal pure returns (address result) +``` + +Returns the address of the ERC6551 account. + +### isERC6551Account(address,address) + +```solidity +function isERC6551Account(address a, address expectedImplementation) + internal + view + returns (bool result) +``` + +Returns if `a` is an ERC6551 account with `expectedImplementation`. + +### implementation(address) + +```solidity +function implementation(address a) internal view returns (address result) +``` + +Returns the implementation of the ERC6551 account `a`. + +### context(address) + +```solidity +function context(address a) + internal + view + returns ( + bytes32 salt_, + uint256 chainId_, + address tokenContract_, + uint256 tokenId_ + ) +``` + +Returns the static variables of the ERC6551 account `a`. + +### salt(address) + +```solidity +function salt(address a) internal view returns (bytes32 result) +``` + +Returns the salt of the ERC6551 account `a`. + +### chainId(address) + +```solidity +function chainId(address a) internal view returns (uint256 result) +``` + +Returns the chain ID of the ERC6551 account `a`. + +### tokenContract(address) + +```solidity +function tokenContract(address a) internal view returns (address result) +``` + +Returns the token contract of the ERC6551 account `a`. + +### tokenId(address) + +```solidity +function tokenId(address a) internal view returns (uint256 result) +``` + +Returns the token ID of the ERC6551 account `a`. \ No newline at end of file diff --git a/docs/accounts/liberc7579.md b/docs/accounts/liberc7579.md new file mode 100644 index 000000000..6f3773a86 --- /dev/null +++ b/docs/accounts/liberc7579.md @@ -0,0 +1,269 @@ +# LibERC7579 + +Library for handling ERC7579 mode and execution data. + + + + + + + + +## Custom Errors + +### DecodingError() + +```solidity +error DecodingError() +``` + +Cannot decode `executionData`. + +## Constants + +### CALLTYPE_SINGLE + +```solidity +bytes1 internal constant CALLTYPE_SINGLE = 0x00 +``` + +A single execution. + +### CALLTYPE_BATCH + +```solidity +bytes1 internal constant CALLTYPE_BATCH = 0x01 +``` + +A batch of executions. + +### CALLTYPE_DELEGATECALL + +```solidity +bytes1 internal constant CALLTYPE_DELEGATECALL = 0xff +``` + +A `delegatecall` execution. + +### EXECTYPE_DEFAULT + +```solidity +bytes1 internal constant EXECTYPE_DEFAULT = 0x00 +``` + +Default execution type that reverts on failure. + +### EXECTYPE_TRY + +```solidity +bytes1 internal constant EXECTYPE_TRY = 0x01 +``` + +Execution type that does not revert on failure. + +## Mode Operations + +### encodeMode(bytes1,bytes1,bytes4,bytes22) + +```solidity +function encodeMode( + bytes1 callType, + bytes1 execType, + bytes4 selector, + bytes22 payload +) internal pure returns (bytes32 result) +``` + +Encodes the fields into a mode. + +### getCallType(bytes32) + +```solidity +function getCallType(bytes32 mode) internal pure returns (bytes1) +``` + +Returns the call type of the mode. + +### getExecType(bytes32) + +```solidity +function getExecType(bytes32 mode) internal pure returns (bytes1) +``` + +Returns the call type of the mode. + +### getSelector(bytes32) + +```solidity +function getSelector(bytes32 mode) internal pure returns (bytes4) +``` + +Returns the selector of the mode. + +### getPayload(bytes32) + +```solidity +function getPayload(bytes32 mode) internal pure returns (bytes22) +``` + +Returns the payload stored in the mode. + +## Execution Data Operations + +### decodeSingle(bytes) + +```solidity +function decodeSingle(bytes calldata executionData) + internal + pure + returns (address target, uint256 value, bytes calldata data) +``` + +Decodes a single call execution. +Reverts if `executionData` is not correctly encoded. + +### decodeSingleUnchecked(bytes) + +```solidity +function decodeSingleUnchecked(bytes calldata executionData) + internal + pure + returns (address target, uint256 value, bytes calldata data) +``` + +Decodes a single call execution without bounds checks. + +### decodeDelegate(bytes) + +```solidity +function decodeDelegate(bytes calldata executionData) + internal + pure + returns (address target, bytes calldata data) +``` + +Decodes a single delegate execution. +Reverts if `executionData` is not correctly encoded. + +### decodeDelegateUnchecked(bytes) + +```solidity +function decodeDelegateUnchecked(bytes calldata executionData) + internal + pure + returns (address target, bytes calldata data) +``` + +Decodes a single delegate execution without bounds checks. + +### decodeBatch(bytes) + +```solidity +function decodeBatch(bytes calldata executionData) + internal + pure + returns (bytes32[] calldata pointers) +``` + +Decodes a batch. +Reverts if `executionData` is not correctly encoded. + +### decodeBatchUnchecked(bytes) + +```solidity +function decodeBatchUnchecked(bytes calldata executionData) + internal + pure + returns (bytes32[] calldata pointers) +``` + +Decodes a batch without bounds checks. +This function can be used in `execute`, if the validation phase has already +decoded the `executionData` with checks via `decodeBatch`. + +### decodeBatchAndOpData(bytes) + +```solidity +function decodeBatchAndOpData(bytes calldata executionData) + internal + pure + returns (bytes32[] calldata pointers, bytes calldata opData) +``` + +Decodes a batch and optional `opData`. +Reverts if `executionData` is not correctly encoded. + +### decodeBatchAndOpDataUnchecked(bytes) + +```solidity +function decodeBatchAndOpDataUnchecked(bytes calldata executionData) + internal + pure + returns (bytes32[] calldata pointers, bytes calldata opData) +``` + +Decodes a batch without bounds checks. +This function can be used in `execute`, if the validation phase has already +decoded the `executionData` with checks via `decodeBatchAndOpData`. + +### hasOpData(bytes) + +```solidity +function hasOpData(bytes calldata executionData) + internal + pure + returns (bool result) +``` + +Returns whether the `executionData` has optional `opData`. + +### getExecution(bytes32[],uint256) + +```solidity +function getExecution(bytes32[] calldata pointers, uint256 i) + internal + pure + returns (address target, uint256 value, bytes calldata data) +``` + +Returns the `i`th execution at `pointers`, without bounds checks. +The bounds check is excluded as this function is intended to be called in a bounded loop. + +### reencodeBatch(bytes,bytes) + +```solidity +function reencodeBatch(bytes calldata executionData, bytes memory opData) + internal + pure + returns (bytes memory result) +``` + +Reencodes `executionData` such that it has `opData` added to it. +Like `abi.encode(abi.decode(executionData, (Call[])), opData)`. +Useful for forwarding `executionData` with extra `opData`. +This function does not perform any check on the validity of `executionData`. + +### reencodeBatchAsExecuteCalldata(bytes32,bytes,bytes) + +```solidity +function reencodeBatchAsExecuteCalldata( + bytes32 mode, + bytes calldata executionData, + bytes memory opData +) internal pure returns (bytes memory result) +``` + +`abi.encodeWithSignature("execute(bytes32,bytes)", mode, reencodeBatch(executionData, opData))`. + +## Helpers + +### emptyCalldataBytes() + +```solidity +function emptyCalldataBytes() + internal + pure + returns (bytes calldata result) +``` + +Helper function to return empty calldata bytes. \ No newline at end of file diff --git a/docs/accounts/receiver.md b/docs/accounts/receiver.md new file mode 100644 index 000000000..46172ebc2 --- /dev/null +++ b/docs/accounts/receiver.md @@ -0,0 +1,74 @@ +# Receiver + +Receiver mixin for ETH and safe-transferred ERC721 and ERC1155 tokens. + + +Note: + +- Handles all ERC721 and ERC1155 token safety callbacks. +- Collapses function table gas overhead and code size. +- Utilizes fallback so unknown calldata will pass on. + + + + + +## Custom Errors + +### FnSelectorNotRecognized() + +```solidity +error FnSelectorNotRecognized() +``` + +The function selector is not recognized. + +## Receive / Fallback + +### receive() + +```solidity +receive() external payable virtual +``` + +For receiving ETH. + +### fallback() + +```solidity +fallback() external payable virtual receiverFallback +``` + +Fallback function with the `receiverFallback` modifier. + +### receiverFallback() + +```solidity +modifier receiverFallback() virtual +``` + +Modifier for the fallback function to handle token callbacks. + +### _useReceiverFallbackBody() + +```solidity +function _useReceiverFallbackBody() internal view virtual returns (bool) +``` + +Whether we want to use the body of the `receiverFallback` modifier. + +### _beforeReceiverFallbackBody() + +```solidity +function _beforeReceiverFallbackBody() internal virtual +``` + +Called before the body of the `receiverFallback` modifier. + +### _afterReceiverFallbackBody() + +```solidity +function _afterReceiverFallbackBody() internal virtual +``` + +Called after the body of the `receiverFallback` modifier. \ No newline at end of file diff --git a/docs/accounts/timelock.md b/docs/accounts/timelock.md new file mode 100644 index 000000000..48fff2a33 --- /dev/null +++ b/docs/accounts/timelock.md @@ -0,0 +1,263 @@ +# Timelock + +Simple timelock. + + + + +Inherits: + +- `accounts/ERC7821.sol` +- `auth/EnumerableRoles.sol` + + + + +## Constants + +### ADMIN_ROLE + +```solidity +uint256 public constant ADMIN_ROLE = 0 +``` + +Role that can add / remove roles without wait time. +This role cannot directly propose, execute, or cancel. +This role is NOT exempt from the execution wait time. + +### PROPOSER_ROLE + +```solidity +uint256 public constant PROPOSER_ROLE = 1 +``` + +Role that can propose operations. + +### EXECUTOR_ROLE + +```solidity +uint256 public constant EXECUTOR_ROLE = 2 +``` + +Role that can execute operations. + +### CANCELLER_ROLE + +```solidity +uint256 public constant CANCELLER_ROLE = 3 +``` + +Role that can cancel proposed operations. + +### MAX_ROLE + +```solidity +uint256 public constant MAX_ROLE = 3 +``` + +The maximum role. + +### OPEN_ROLE_HOLDER + +```solidity +address public constant OPEN_ROLE_HOLDER = + 0x0303030303030303030303030303030303030303 +``` + +Assign this holder to a role to allow anyone to call +the function guarded by `onlyRoleOrOpenRole`. + +## Enums + +### OperationState + +```solidity +enum OperationState { + Unset, // 0. + Waiting, // 1. + Ready, // 2. + Done // 3. + +} +``` + +Represents the state of an operation. + +## Custom Errors + +### TimelockInsufficientDelay(uint256,uint256) + +```solidity +error TimelockInsufficientDelay(uint256 delay, uint256 minDelay) +``` + +The proposed operation has insufficient delay. + +### TimelockInvalidOperation(bytes32,uint256) + +```solidity +error TimelockInvalidOperation(bytes32 id, uint256 expectedStates) +``` + +The operation cannot be performed. +The `expectedStates` is a bitmap with the bits enabled for +each enum position, starting from the least significant bit. + +### TimelockUnexecutedPredecessor(bytes32) + +```solidity +error TimelockUnexecutedPredecessor(bytes32 predecessor) +``` + +The operation has an predecessor that has not been executed. + +### TimelockUnauthorized() + +```solidity +error TimelockUnauthorized() +``` + +Unauthorized to call the function. + +### TimelockDelayOverflow() + +```solidity +error TimelockDelayOverflow() +``` + +The delay cannot be greater than `2 ** 254 - 1`. + +### TimelockAlreadyInitialized() + +```solidity +error TimelockAlreadyInitialized() +``` + +The timelock has already been initialized. + +## Initializer + +### initialize(uint256,address,address[],address[],address[]) + +```solidity +function initialize( + uint256 initialMinDelay, + address initialAdmin, + address[] calldata proposers, + address[] calldata executors, + address[] calldata cancellers +) public virtual +``` + +Initializes the timelock contract. + +## Public Update Functions + +### propose(bytes32,bytes,uint256) + +```solidity +function propose(bytes32 mode, bytes calldata executionData, uint256 delay) + public + virtual + onlyRole(PROPOSER_ROLE) + returns (bytes32 id) +``` + +Proposes an execute payload (`mode`, `executionData`) with `delay`. +Emits a {Proposed} event. + +### cancel(bytes32) + +```solidity +function cancel(bytes32 id) public virtual onlyRole(CANCELLER_ROLE) +``` + +Cancels the operation with `id`. +Emits a {Cancelled} event. + +### setMinDelay(uint256) + +```solidity +function setMinDelay(uint256 newMinDelay) public virtual +``` + +Allows the timelock itself to set the minimum delay. +Emits a {MinDelaySet} event. + +## Public View Functions + +### minDelay() + +```solidity +function minDelay() public view virtual returns (uint256 result) +``` + +Returns the minimum delay. + +### readyTimestamp(bytes32) + +```solidity +function readyTimestamp(bytes32 id) + public + view + virtual + returns (uint256 result) +``` + +Returns the ready timestamp for `id`. + +### operationState(bytes32) + +```solidity +function operationState(bytes32 id) + public + view + virtual + returns (OperationState result) +``` + +Returns the current operation state of `id`. + +## Internal Helpers + +### _bulkSetRole(address[],uint256,bool) + +```solidity +function _bulkSetRole( + address[] calldata addresses, + uint256 role, + bool active +) internal virtual +``` + +Helper to set roles in bulk. + +## Overrides + +### _execute(bytes32,bytes,Call[],bytes) + +```solidity +function _execute( + bytes32 mode, + bytes calldata executionData, + Call[] calldata calls, + bytes calldata opData +) internal virtual override(ERC7821) +``` + +For ERC7821. +To ensure that the function can only be called by the proper role holder. +To ensure that the operation is ready to be executed. +Updates the operation state and emits a {Executed} event after the calls. + +### _authorizeSetRole(address,uint256,bool) + +```solidity +function _authorizeSetRole(address, uint256, bool) + internal + virtual + override(EnumerableRoles) +``` + +This guards the public `setRole` function, +such that it can only be called by the timelock itself, or an admin. \ No newline at end of file diff --git a/docs/assets/css/prism-theme.css b/docs/assets/css/prism-theme.css new file mode 100644 index 000000000..eec36df19 --- /dev/null +++ b/docs/assets/css/prism-theme.css @@ -0,0 +1,149 @@ +/* Generated with http://k88hudson.github.io/syntax-highlighting-theme-generator/www */ +/* http://k88hudson.github.io/react-markdocs */ +/** + * @author k88hudson + * + * Based on prism.js default theme for JavaScript, CSS and HTML + * Based on dabblet (http://dabblet.com) + * @author Lea Verou + */ +/********************************************************* +* General +*/ +pre[class*="language-"], +code[class*="language-"] { + color: #555; + font-size: 13px; + text-shadow: none; + direction: ltr; + text-align: left; + white-space: pre; + word-spacing: normal; + word-break: normal; + line-height: 1.5; + -moz-tab-size: 4; + -o-tab-size: 4; + tab-size: 4; + -webkit-hyphens: none; + -moz-hyphens: none; + -ms-hyphens: none; + hyphens: none; +} +pre[class*="language-"]::selection, +code[class*="language-"]::selection, +pre[class*="language-"]::mozselection, +code[class*="language-"]::mozselection { + text-shadow: none; + background: #bbb; +} +@media print { + pre[class*="language-"], + code[class*="language-"] { + text-shadow: none; + } +} +pre[class*="language-"] { + padding: 1em; + margin: .5em 0; + overflow: auto; + background: #f2f2f2; +} +:not(pre) > code[class*="language-"] { + padding: .1em .3em; + border-radius: .3em; + color: #db4c69; + background: #f9f2f4; +} +/********************************************************* +* Tokens +*/ +.namespace { + opacity: .7; +} +.token.keyword, +.token.comment { + font-style: italic; +} +.token.comment, +.token.prolog, +.token.doctype, +.token.cdata { + color: #888; + color: rgba(0,0,0,0.45); +} +.token.punctuation { + color: #666; +} +.token.property, +.token.tag, +.token.boolean, +.token.number, +.token.constant, +.token.symbol, +.token.deleted { + color: #598; +} +.token.selector, +.token.attr-name, +.token.builtin, +.token.inserted { + color: #853; +} +.token.char, +.token.string { + color: #763; +} +.token.operator, +.token.entity, +.token.url, +.language-css .token.string, +.style .token.string { + color: #788; + background: #f2f2f2; +} +.token.atrule, +.token.attr-value, +.token.keyword { + color: #369; +} +.token.function { + color: #345; +} +.token.regex, +.token.important, +.token.variable { + color: #598; +} +.token.important, +.token.bold { + font-weight: bold; +} +.token.italic { + font-style: italic; +} +.token.entity { + cursor: help; +} +/********************************************************* +* Line highlighting +*/ +pre[data-line] { + position: relative; +} +pre[class*="language-"] > code[class*="language-"] { + position: relative; + z-index: 1; +} +.line-highlight { + position: absolute; + left: 0; + right: 0; + padding: inherit 0; + margin-top: 1em; + background: #f7ebc6; + box-shadow: inset 5px 0 0 #f7d87c; + z-index: 0; + pointer-events: none; + line-height: inherit; + white-space: pre; +} diff --git a/docs/assets/fontello/LICENSE.txt b/docs/assets/fontello/LICENSE.txt new file mode 100755 index 000000000..042245e12 --- /dev/null +++ b/docs/assets/fontello/LICENSE.txt @@ -0,0 +1,21 @@ +Font license info + + +## Meteocons + + Copyright (C) 2012 by Alessio Atzeni + + Author: Alessio Atzeni + License: SIL (http://scripts.sil.org/OFL) + Homepage: http://www.alessioatzeni.com + + +## Font Awesome + + Copyright (C) 2016 by Dave Gandy + + Author: Dave Gandy + License: SIL () + Homepage: http://fortawesome.github.com/Font-Awesome/ + + diff --git a/docs/assets/fontello/README.txt b/docs/assets/fontello/README.txt new file mode 100755 index 000000000..d870892e3 --- /dev/null +++ b/docs/assets/fontello/README.txt @@ -0,0 +1,75 @@ +This webfont is generated by https://fontello.com open source project. + + +================================================================================ +Please, note, that you should obey original font licenses, used to make this +webfont pack. Details available in LICENSE.txt file. + +- Usually, it's enough to publish content of LICENSE.txt file somewhere on your + site in "About" section. + +- If your project is open-source, usually, it will be ok to make LICENSE.txt + file publicly available in your repository. + +- Fonts, used in Fontello, don't require a clickable link on your site. + But any kind of additional authors crediting is welcome. +================================================================================ + + +Comments on archive content +--------------------------- + +- /font/* - fonts in different formats + +- /css/* - different kinds of css, for all situations. Should be ok with + twitter bootstrap. Also, you can skip style and assign icon classes + directly to text elements, if you don't mind about IE7. + +- demo.html - demo file, to show your webfont content + +- LICENSE.txt - license info about source fonts, used to build your one. + +- config.json - keeps your settings. You can import it back into fontello + anytime, to continue your work + + +Why so many CSS files ? +----------------------- + +Because we like to fit all your needs :) + +- basic file, .css - is usually enough, it contains @font-face + and character code definitions + +- *-ie7.css - if you need IE7 support, but still don't wish to put char codes + directly into html + +- *-codes.css and *-ie7-codes.css - if you like to use your own @font-face + rules, but still wish to benefit from css generation. That can be very + convenient for automated asset build systems. When you need to update font - + no need to manually edit files, just override old version with archive + content. See fontello source code for examples. + +- *-embedded.css - basic css file, but with embedded WOFF font, to avoid + CORS issues in Firefox and IE9+, when fonts are hosted on the separate domain. + We strongly recommend to resolve this issue by `Access-Control-Allow-Origin` + server headers. But if you ok with dirty hack - this file is for you. Note, + that data url moved to separate @font-face to avoid problems with ZzRiliJ-mM?WJ$}uk~nUW~QmL-K0CEHRGNp>7kNgPtt_w*Hs zcAR8&mDJ8MB^`pIC|aZgh9LunVFM23E=z_E3x;5Afo90B4f`{sMKKuIkmbh;Y-nrm zdG93^*|9fle|M#O&vV}QJ?Fe%=RNoGUt1U(!OfY(=#rQ!TL6@IIH8G2yZ`0WBBT51 zufBKgOKJ@@um!fk)>)a&vsL_UfZ=1)=q<7<=oi@*C?R$Ulr6T+mMv+Won#5t1&Q{QDwE-Xt!A~uL;24ne=+pYgme$JGLO%myE*+1DIT}0H^tX`7G;mIG<%ZGuxExZ4x8;VQ_paT_i~3M zPcTJQZfaa*>P;qb2bUZ>PVSKLf1Sy7T&}y$>gsMl3C^%b7%xH{KJ~;zo6&Y65NbM> zbZJLpjXkN;JQ)gT4x=sF80{J2sqUswpq^`Oao<1LM?CnXl@*_N;wM7r@;{<=z?;Y~`t;b7lciim`y4^8P$n6e=JTZ639c+3% zf21vPWM)UYkvkG;0~kEpJ2cdL_G|uT|NcK8_WAuS4cvd{-&`2z^HV>oMlt& zdA7n{VpoQ@CPpQ99iM3D9zH&NN|Mj9I(OYo=2qM{nMZLb9>)%oG*y$-9p+SJ)hX|| zxGdj5EFDa7tav%|acm8~%pjxXnWm{lrfTZc)$-=r%JN+4xo6Lx3kCv>M=1{V2jkH3 zz&M1yj6*WylgRn0zEn?wYvlc8s3{oG5>_NE?Bf*6)KLk+YwJKD5!Pf#LsSh!(hfK+ zblLAE_xJ{V4ObB&mnZ0Q?T5$}@E}BcuS?h8zkX)sMy&I>oy%WuX!S|{=73afZ@WXT zP}~(b?2cK%4M}wf^qE@ZeGU9FQh?;|eBnm)JZ?|O6-V?uAxo6P_oJDeogYvRJpP;% z>wJAix_sw+RV&0#`fEFhd<|0IH$QiULYy=Vx%of41D@*2Kdi2SET@Wx;w4S9HdM36 zhEtt&lElJXcM;qfb>melEFH&qPl!sJCjWCm;nn z&i~!Fhx$@acrGOav+uYZeSB{5dXrg-Rqg9I|E=XG`%~KE@5}}? zXUeumUX}Kk8|QB4u<3THlA@@5LPlXxQG^$n!nyJcjNmUwK>Vpgeq0Tf72Ps7IvhqF z?`~@B=7#js@~`>v+wXt6&AoSi@%ek-8NO2*k@oIM94r8aUQPOZBi z%X!(&E};6nz~=CRu#VS+YiwnB@mOm(h~?(Jk}R!ohc?Dlhk|;9(xgb(8Zwut25DT@ zt~1R6=UitFl{?hyOjU0*185|Tq}LS$OyCe7jFZPAVd@8oS-D?iGuTS|5JA#ec=jNYC> zE@P-e3pJ&pUwQQPXn|B8=qdhZ<-gr}@3ng05k1-8)-0L9M;ZnYp!Hs7>u~)e0rPNM ze^(@^d77hbKDUl^c1liJ@f_Ar7LP|gUf$q)?Y;8fd>h+d;;w+=cDMqX%jIfOymj7o zen>eKZEV!JU-HZD^2b-+{wyZ@Tvt<%$i7zdY*(hMdq@rWy!G{(zgZjV?#gtYO|&5M zqpEhe$sdxr;?iVUYxQ}9%}z;9wn#3Y9Q*9;D<7AC^IZjgSG0QBt$Biq&*2LwUYDm1 zDX1w9?&WTW?6Zz*IG#?XbKm>br!UkG{F2qn)?xLt&R6LDgxM`lq1%W)WrDS*>@n86 z2D9byq?rz08gagI)9FLk9{&T$DUHY{foY`1UZz@%OJc34z~2OV!)KqSjQQC=?a$u} zj=dJWJ@r`&EQ21eVg>k26{{@7pQvID^imbO*d@MQ#cmemKgn!tzPz=(xK!4U zXCBp)UCC~J_GNtoq~-PEs$RTOUfS5&)`#_ljrH>U>gq^Xv0l#q#_d&AxqgFwqp$>MCI zKaBhSFOmc+fxq?@`n_K%_m8^2|KKl}`=!S4owIIz>lCeTqB-be>%Psd!oDP^WoSZL zZdqFCY!vOmFDM=UAl?e*DM316d8G{MDb|U<``4`5XJt4Zxa@ql@xiBt+KJtbb4ue5 z=9n+7E^ltn%iCAhm9>qHb$(4-TrMwNnWZtPpLip$KRBGQV5TnE)46P3*T+9#zNvAc zU6{#33`x8y*Or8A;2qZbP4iWJDCEA4VdNSTY*bm1`oGQ~NeOkUfQBni`q$b3tLsC&L3 zPq*lRMtZN2H-cvfHkq5x?}a!?#)V=EIVOUc9IYopnM_q6tk3D?OPp87_`t z6bA2`c5sl7^500`@_Lw@MTo*iB!2=)TyIt+DJ$lRBXQAS!USCx^_lZz82}}pz!A>S_9+r$j|1nVS4c0?KSYfQufRm9>gL|BFD<6U;t1u~hF(>>+TF(j} z($9;?71Da)FAg8(>=2H~bUIBQ2!O|nm4GuQ-in3WklrEK7>vb5lUd=^9)`cEeZ;KD z)Ha(Hh1#%LQK@Y)D;l*&%!-5BRv|HlBJirX? zGheis@dM20K6A@v>LwHQv4`3TqyF4BmFzrdUj+8)(5nshQER|HYLCG_YTIESwNcnd zZ3pb5_BiaL_EFeJ?FraNZNk(Ctc}!Z>IHGQprh#V0_8*ztw>PLcA26xCOWYnPhu;K zA!8r7A&p|cL52Oll|VYiMY0y+iciZ@#)*?BDk=|Vb0~@w#qI;{d6-O(srOo%_hL4C zp6pl41gg&iwIwxaj|%M3LAf zh(Cr9u~567(8s7Gz_sUgcgKt|l%O0AK2%+tNc|jN7x3^Y)UJ?df|!DG+HQ$eJS;8T znb`bp!qD}BUCep=b?X{xj?6m6^z4UEx( z&=Bo=w<~rQkJ+b^k}1p?LdBtqVy9$^Vcgwd$`l#$$Plzd$_f+ z2j{zgM8*`SVh06kgK7(onBsJ77wJbiwu_zqFx?Q)gy@2bS<7Tf6ang72_>9GeT*#9Mq$=_7R28{l2M;@P=HUxYF;^u z-sxC`Vn%+cTC?whb8tb>-u8Gq!47Xsh!l4D`G?TQF&z&yiay9pnBp-sPmmY0aJN2+ zL%8OxCrwId@dVubl)1;)D8M8DCopC1af>nyU{NlR%otb~Nru4FBtzg5$q;zPyoFkr z0m=d4YzNAlx42E40kUb&k{l=Qb0lY>=Sj{&mr2e-FVLD`Cz&yziSRfe!ixy$G#adJ)=yj|cVx zxM}soFc>e|@NvK`ayp5LG?vQhAqo7p4N2f@kR9Bg@4D5q=KH!0NqonKB>oyk4%+j*ZbK6Ih7C#J24si! z=eue3toh!sA&LKv4N3e>j2yD(`&}E7z^)BR;4O2{ZN1qFExe~lauy#=ILq?sm~hSu z`Pk&O+JPQt_yGLzG+rn9@8PVoKlwH*%#p_H-wC^Q-P3-EJak(W8-0l1E7(Zo7=LpL zum5l6s6RJSIZpi#oXjS$k$kw)L8QNQ?%?N>;WtYcElDuwsxaS)5BS}iLir|+ + + +Copyright (C) 2023 by original authors @ fontello.com + + + + + + + + + + + + + + + + diff --git a/docs/assets/fontello/font/fontello.ttf b/docs/assets/fontello/font/fontello.ttf new file mode 100755 index 0000000000000000000000000000000000000000..ebdf162eb0bcaf33027e9876938c4245c4fe509c GIT binary patch literal 7236 zcmd^DYiwIbcAmK}QhZ6KNXijy`BK-S9P^TrDTz{SSyD(*vMnW%WXBSIn0gk9TN|J^V15Im zb7AGx`F|gK=DUo^1;(_Q#kt~a+j8$8GFJB~_^Cw@9Q|@0bK3vt;%fP7=;uJprQ>yQ zWxZ5X|3&^K=6#s^R*P3Rc-r?f%+Fx1uN7D4KKns)81qHOq|Y|ix5{t*RR0Y7ll<7m z=G?}$4^Mr_Son`I|2`w%U96K0Fll&X`~vf>6w7O@nJJ*tL;U@iuPiMTnX}5_;1QRD z!kJc+mp|w4F%|p2CjAJsckPjX!A@`qRHn+HKIEC0&(5+>ZnLl6m#6M7vuXKH*>@mD zHhld+1L;P#7&Gz1{(QD7a|u+EHZi&^y26r}Ymnkhx-Eb8{@uHb(GE1?A*(&sC}E94 znmPIL|NWtuFg9Kd1EO*pkbV^3+tnXZ$!=GFl#kohALZn$_w64d>R{~dpUBJ7KOoZ0 zEXtl>Y4$XmX3q^>7&6;rrk>^!@8J$f9%qWG+|;l1za~Q4B#%T8-Pjxkg0`**L zm80FMB`3NUb{XK=9R%p3k@|K9(6 z$mjPTYT*7m|LVd*uLny_w{!?fCiV znOkw+WFEz#cpTeI(o{`Sx0zFwRj0h|;<9`LxpXkavFzo{$8j|H5`&DEXPTxKnX0Li zSIQf!%S*GR7oI&IuFT^Pom(bdQ;sAu2J-pp{8I!OIVq( zu#ZzNQ%58uueBYCL|T&}4OumiNju@R(Ivl^!s8q8HC#c8T%MrIwU;7Sz=IU+UYD+Y zck)8-gbvvp|~q>&>gdq8XT zLgVaQd#|c`{9JOYp7HKrP;b#xPe2N^pZmLS5B8>>@?1;?X5Mo-dim_axppu-s@9?h zgWcmE)hz|ws@mIr?psSw_ocKa-&UOIKf|%fcP^9{CFBHFS=xIv^$JC-qqCD#SQ6aZ}4Vg>SgETH{*O=x&aIP_j${p%8rm8obXhUd87-~IhAJ;;w+=cDMqX%jG(xcQzcku%3foAYcN|LZ_>2?(TMZFk8U4&cKIJjPH9*^0Zc13 z_A2#aJQ8a`2mU6|TR!_XWz5h1X-|I-IQCxj_0&_v61wf_DwaVXu3`mvyoyzvn+sK} zf&NkzyI71ZRI!^ivTxDXkWza-`HGVo-36Ti{K_zd!h7`r`V=GL zujL}7H_@7wEbTfw0ll3MtQv*Xnk8AZESQBow(VQ&3U*6^TE;4}a?`R(XCs!zukF-yM7%r`kEwDZ$B(H$1Y@`ZVQ z=h>W)+KL}LaSTc&V=F==AO}?#*ONS)pZf5h1tbr=HJ2 zIJ}e7#l!?iL;0{S`Uv&q^LoXWhDFCfs?K!LN&HTd{A41hBN{tJUAQK41yFS2xd^2Q zr3&FfKA#UGTEdel2{x4zY>b2>n1{zi3!#>=;ztdvL=qpVY$l(dE#?J}mFvX>6N?bThQJ0DBqS0DWcVcR! z4U~(KE(&R8UhonO5su?=QD^F8tq*P~Yz88*cc_pjk;1TLt;^i4^RY}eeLS*PIBxUa zLh{&Jcnl_F;CeyN?ifW%sugS&ri2JR3?pk+BDF?w*xthXh~?raR$=j;Yx@`ZsQ!)g zEw6{kS)?dzMDoW`#Pw!HlCom9I2;!ZCS1^UQJ*K{qRbBGj|%UcaWyU)&9TYc*m;{6j)2~1(F10M`7_Vv zDt>=P@M2mVh|!TlX{9Um^lHFM@DOq#w@u_KbPf@&^bRtNZ5xh93@oc*)C2Kp2~IL` z^YCO8_K$*kZ?Ybd!U|)J27-)&8rbEWTlEk$S%pd23pwF8(t1|-P<~!yu8`IXe{t|2 zX9sXarqgMPKma^mtOT4f@lGtBP@gU+&<6~w;rm@+qC^Ux6ib~@l zv!c;>*sM5cY%wcN8jqNjIvQgpqG88hXaz*t&=Z2cNT($(%zezz9`j|J8Q;f@?lCuQ zrfxD(AA6*qaO%%(SIN)){zc%Q4!c_6AB_h5qwy&Gqp=PC(HMn)G`7P(8jrz08Xt#$ zG#-b4G$u^F-#SPgrd|*S3p$z}FHlVsF^UA$Y^NzYVxj}*@dS>-C@S`$2hu3^8PwSS zTM3k7TqJ8LuK2VpRh&3+yrS}8HixE2S?t;uo=3@an|hCBc@MPNda@6;33Q)_T1#{m z`XR0=#)b!szDhR_lCLSm0}ecNO#z3c*cTVQW}>M-F8cl_Q51Fw;!hw&EYzka^igUF z2<_ROol#>HEhvYJ4_y~GQXj`(7l`ml^sbO-f|!DK+GdGWJS;8Tnb_P;!qD~p9q2rD zub7^&^$E>L*Q9k(pq?@`nY*Rvsvf?jMAhbenmVluO&j~e0%N2gG-UhUSQz~X)9F2yaG{y#`iL<~n^G1BYCOvs zJJNz($R+fCTF&DI)7XY)^@X^UrkqmK5*`L zxt8J~^p6BZaYQs_auZ?Psd|4tQR(CXoZBbw;ZB7o?%}5I;nvpf*LVMlj44jW_6yV& z)ixY9#i`g1%8zPn2PgeewjrSj(Fqf?mdjMeQ9JTQe4wRm*QuNhoU{Z^p6$?xS#ja6 zq3X9P|9@A~qYo>v|4S89ys3}%8-3x(zIut|t9Fi}0iTT3qH+eaQ?Ur;jN(%DW-kP1 z5rUw7?D2Ji6W*8*DV*|ikD!l19S<~$UdW7_;t32-Q53TXw?2YPxE8IaO)6;d6vF(B zxy#rHzyts%Flp{`i!udZQO=XhC|DOrhQPBVL*OFG5O~hKgYLMxVCgjOxP2(4Lm5n4x#`}Y#KVa>!47%$uKNx)4C zI*ExiW?Q&x0ZFE8Lz1~{$q<8Nu3+)$J*}@;Gi$|F8`6qbZAjv;LCfjxcKteK_n8#W~IZ5xvKn^-wu>$`4468Ie(lE4kf4({o@Y0WHsZ`qK6F`a-rAwCxh!p8T zrAtSOpn%duc$fEk|M~9BGv}P&J?HM(yEA*|`sizD03-l7Xl8*c7nWV^|Kbb({}0W3 z#wq|nVhXCVAV!>V2!H*1w?#qi1sJP=U=(=JUvbV@S5TV-V|&onECu{|iu3m51OQSc z001t7P=f$=u8*8S?JfX7w?T>0TKL%i5!M5&h0B4{ z^g&Iw1zB;%`hw4;jt67T3rJL`2cKY_Z9(k~_zqrRpF=}f;AFTgTuJH?ZdGP1KPLxaY@z~Y%q`{Cz>O2 zLrgw71kwZfR2%F-&1n}FO$zYIl4$`KwOB%jbVx{ANJx3C!xacb^-8#1U7azwU{Jpcyn;~$`Q~mXx6uY8DOL0POBX~b z7(I{>MvK~lJCXpZpLu;p{n2WQ3X~$Ln@@Byf>tKYe1zU{M67L1KcA06=?ET&HOdtBk?5NBj0T=c30z1T<+u%I z#=I|7@gxwH$)VOAew<;(wSHbVc56ZEDO*E!M0rQ^oY#{!t!CZShbiCICEBfCD0_;IORP|6xy9JIX*5>}eX8#!9FcGF|H~ zVl2flq>D4kSCG+e6{T_Z!K>J{PTpyje1R1?4qMV3s8)m<;$sth4=c%Se3-R2{~#OS zlFrEKXk3<=GL7RVepcdW5{x zTmlc{1Wr5Wko!#wd&cYwK3xYHCSM-I8i%|dgJX)-!qXQNf3Ng!e4xoTcO;^Orl$Rx zjp_cT=obv}+UeBUzQKG-1-shZ}F)~$&cfOBnh z_0^_nRq8aoiER;U95?YEzK~fZ?)By_YwS_zFhxWXbmM;NRq--3 zF=9bN0RUJE$*yl(zs2k|M2B6yYrtzg8f9lrNr$@2E5z-jYfhYN=NF`ETzW0;Q$U?# z^koiT7BHgM>NRLGbXqsujdoT1l%7uNj?TX-PjKfKQf%u`ynMvM?+HvWc!%ipq|b(IHMm`sfkerk72%2GdRUP0J*^eiLnC>;_L7H*3(tOL%SaDHb*dx&XsFjk^W) ze~yc7+V+eLNCwwvS|yJh?K@|J=Pst%W}WSSX39*F8pypFQ7W9k^3#p%H?&ry^+Vo{wwnI9I~PRQGl zKx{C3nDx_@$rhNB_m0pSD*l^Yp7KxRNP$n*qtSpjVwbc`Z-l+@5}ka6r#u<-W5jf@ zLt%s1Ur8uR!lNJ4q$h;hxUs)I!WxQ5Z;_LZ$&c%*IHn>F);8vUePGZV?G}*Ik)KKH zO!~}bQ81XpV|1vmcfHit(PMbzmd)@8Rc}A)eaBh`U+Eb!elSt>vR`lYEt`{SH$AqW|BNl9_15QVxB9AT_zkValX zY;{0{yA`d3`j;6*96|h5mgrvQDQT4zvePU@HXD<_%%gxMenvVH4dD0dUGnU{y_4Gi z+kU7-div+)11`l-I3y|R=`T|DFm>rE-%7)2-4K1AP5~X2oDS(3n!XShKsiRun~uNy zx^sbcala&Q>J|`P1Nh58$fbkcvc!{(NawwO?G(LeEg64+oAL-}zq~gUXxdx06rjhd zuC$Ley58eky%3dbbx@>(ic*1+y-aYN)>L?7mRT8TNF6mwt4wgQ;OIU4VI*&R*ey|V zAh0T6EG}OnH*!lrzvXPY%K$0!c9LtW`bq-SJS(g6>(-a4!)=m)0L+KF?M}++xp~T` zNZZXKggUf=O+J9S!i8yK6e;5~Q)`(kgZ(VU))TXH8gEN4SX81*nEe_<7TI&8@Gt4K zHexqi<5)d2N(xI>)%m4obq!mXGC7;TN0{|Z9OX$e>ZdZe>m1zAD`pFeUI_g~%`3eM zpB70XdSN(2`qLOfBlv*~<(X(Qn$Ua_;iJ>XTSQsGf$t-Df80*=mh{wOX4LO-Ifk$TEJw4Vh*c z>n3AcBWrb&7c;X9ha`xEnY@RVxAk&2Z#_-wH|xIc+V}O;z%R0C!u70r6Kq&#X)L{c<5Nz2v3tX>PO4VdpuWdUb;TQmpjz zAW69^%WVD>LB@$KjK^`6%rXP;?j!xn#6dYWi%ICE1k3|fifQ5 z2*i(xDY4)=Do>_TZggX4KV(Cj3&%W*U9Txd5ln6#-nVS$R<{HQO&mqpJ#OYE5lWeY zpQWXod1G^iM!huMLvyIzC_Lupt0oGI)?(^B4$`?Ceb2fqm0dC|S2Qf8oU$!xHQgQx z4nBPw=p;Y~dxG~;<39N=|J%6^PC-PD@t0q^5%1=NzVwfLfhm})F7<@gH`|`dYNP&7 z#zuRgirX8`-W1c_dPa7h`G&J@`71xqT*>auSzVtyZXT2OiFWel@T^w!59expwpo?J zNu4z+;r?9MfUMW+5JmMJ%Oc#x*i0>$aJkK0_QAECN`{vPNfT(*oFkf%17tnF|tR)r7Y3e!tq_|l~q=%PI zOq7Mps_5rv)W)6PW+!aD=ofr<*JS5&QDP{dYL_ZxZoj)07b2!1E4;w)U_kxk(EwsE zZdJ6xw?0ti{7FkFEIj>nb0wnwGxo!P{M0 zLTmeOnYi61oIGwBb7N*P+nOku@tkq5OO6%LYgh9Zq`!&p&&w_Ud`Y{I-Ad>{j-tzW zY2#^ges9RIb=s%&@!8kdBBLyMO2lD7;5}67fe!BxFH)xaO1|M<29Cl`mL*C zW2nTf8wEl`)Djwpr_@u6bhDAFq8=HHJP}dhJs)Ca3j-0j+2u?T9S4XVuMJG$eH@P> zcf@RdO{{{se0*>5HjCR1!u-vQ+$Yu)qTKkv_V2?TmalR{B@(j@?Ipu52odQruBqqS z)44sRK6_Qn)6}ei=g03k=B&f-{CD4R80%m_82TePAvq>FD>))LEjb|>A0jV-x=~*s zoz~JU{v08tsQA1#R7k#_w@5rDgak+qgiBw1Gu*Flovz&c);v5os}*Puo}H4NvY(8N zWfCtbinLd@7iRFk0f9iI=p1iA#2{e<8jL-O9nnaQuLR@Hs*A`HKfFchdyk;?kj^Nl!*y=!7cy;fd2r*oxPX< literal 0 HcmV?d00001 diff --git a/docs/assets/fontello/font/fontello.woff2 b/docs/assets/fontello/font/fontello.woff2 new file mode 100755 index 0000000000000000000000000000000000000000..004098955b4533f3f3ed40dde7946753ef595b21 GIT binary patch literal 3576 zcmV zOJx7m0dE-pD1jlZ)D$U_hL!FtLW$O3Bd1%2M+8Mdm>d4zYhU8>d*v{=@{PeH6Y!W3 zlFa(i^3^x9GrL!QQ|qTz`pLCcW@u(EF*`^wVS#}O`!Ilc2siDn^#rO(sG6l}Goe&G zn}^K_RSy+oVh(J3ae?QFarOSX25`D?@E(yWOM!*&oEsBM0R)j{R| zN%&cW@O+xNTvU)n_~KL9qa`GVCFv4mJ4-~#x4xowQ8MbPr*!}t0MPOO-_Moyy`TJU ziXf4NL&?r%|86q-k{odM7_%t>34`k9WZ{5F-Hq>5C?H?!Dtw(gSB2pPuY=g6tI6sB zR_j#PKETm{00ig~L1k_s-i6eqok2#Gby`2z>)uZ7(sWcN5)$45lDwU z3`*WXBq}opQ>|Kup>(Ha;mVvJkS9sWS6&$ST3-v+-ieTKScBXlFHU-{DkV>K|CS|$ z_Nm4B%UjZhsPFS^ez_(EFT!!`3#}>*#APxC3Q-P)8c>I7q!Tt@AkDYF$tE?LjjNH-0wH26|vuhAt`5uXW3{YcP;zJESd> zcVf_JqcHV42*a2}t4D1PM|`dJsB8?L(|4}|{1zGR%%JXZxC4hzL0Uyh(|>}F0G&8h zB0VMzgN6e3{uDIwE7oZsJlBb=L;-D6Rv;vjj7n`Qou;F)ZjCacb*8jsV`9@9=6^HE zv{BSuKwL0_l#pi3PLmU;ueX9VYU7G^q*=MT=2Sa$WC#@z()y6vTNk>IWOncsW-=T( zgij-l%0EH3)VAa(Nja7(brrPHTz=dOReHmCpJZQ8CXkoC9X{^1qKvgt-s<_RnA3hB zw`d+}Jvli7!QpEz&Wa6H72aVgteHk4ina6!Ujy(hzXl8VKXLd z!IafOX`K~1LlebC2HH0V_ROS0hri}`k7Tv-&8{P^a{B4sLK=-HV}&Ly(%q(tluXZf^KW*J__F zs#zfelvXC#Z6N&%IR@EWYaK&;8IY!Xn;B+hEQK^O0e(&y$M@yKtxq&dI5IXu?)xFL z#mg&>5rU=PMedP6g2%22^eYXudR#hOq%A{qJEJkuG)e{QUU0<1u@^y@dKpe7Ehlp- z&GK6GUWGtXYK3hbC;dFZ$i*d{{~D0J z#-s_KBz_||2;PK7TD1l~k|wAfg4h^b^Zs^=-+~wPbnQeL?(X4}17Uc*``ScQW^LWR z_7wGqFrb<>UZk*Pc4Ck=HnqzZRyVet-hanz-FPP3MGL?6EE&nAIp@e|E)j%(J!Bc; z3&E

oCm6V97VF#^}YFgnPM#a~`VFN~3E<|Hc21Q0phD%th z4@=i7jf_ieYpCcgbml15+K{d6#ko;9V1eP3z!8fvX5%fJ2!QF7z!^*WoTq@I1*E`o zYT!x=Y|O!MQwnTN4cwMu>{N%>Y*&P^HzjbN#W-N&9Xk{NM^ggVEaovLypm2t2TrF3 zo=Gv!K>%Jzfy=3ZS5nHZS=Fs)-t0utHu5cYj603{0_^78vxW^1Jklc%JSE67ULZEf z4!Y+Bt-d1Taw)cFGgjB~M_tJb{!3u!lp~%OUNfo=MyuJ!bsc^$a0tLS#!IFWdD@9YsrZ2^Pe|74ab%ZM9}epGmQWHD z70z`}VhGI^i78%W4{FbJV__n?e2^{?;^Cr_S>;O2_9~AKShtnR3%X_T zFR0vGuZo~wG&KdJ(X9F=etJ4zWtP~1c&jN}D0>x)++2#ttCUQH830x03+&D=w_r%D3gI+<%z@)QZ6%hA6`{hP!VfB;(K;>cj!1V z`v6<^z66q8zAyEkH4{zJ7fkwDf}lkVgX7E`j`y9Ho<(^eyjw)b<&aV+N_z+~CSvS+ z#3IIdIt2foY0*?5HQ7DmD4t|yS|fGzxshCbGs|nT@kYHlLh@i9O=SsIa)Cfhbvj90 zkkC%%j;0WIiz%uQm>X-G7k70*>E4cl-V|-)O2UhR63OK6SAR&xG3|>HI{GKg^;n9D z{^gATS3y}BSD$-KF?`;PQlQHck_Q8vlmVh|z8sLOo_%h9FBiN0$_K z>aN=$aD^=?j40yA3t7=F&pZFAFed~W9fMCOX+t{zvFX!P5IwX zyk-tZ4O+)}n!H3CZu58D6dalOpxfo+_mIYbdq10Zm>MTq#$Js%_Nz2KEn<6y;Q3#l z&F5;YCoj>wO=%+683&$x?6=iX4&PW{<0I`TE3Gwd%I4hgF@wl|FLIgq;D~^K^E&_Z z2E&*veN`sHhpij%%N-IAt@%DW{4hyfEmS>M(~4{L_mF`(zPT9yoUJ#jD1hIsX_a5e z003vJ8~`wvc=dd5s?A;%Iu4oop<@$6R9+83g}w%pBX-Y5pfl;>Con!uJWt^JuK*(K z2hed4X!}}RV{7Ar5j;B|#8$aR?T!~1^(n5030j>RQ8CN#L;p2G311^2P7>}J*s5iH z22YK8=GhoD<`o1E;w~g1QbZPX9+uVahqZbfYIXaaTh}gMIDhKop@S>S1sG;%St8SI zHo#Mx8D&x87+}=?bK=(^sF0qA7$f^3VvfUz*Gjt;~Y`JTc8|o>GD8&W>D$uhK zBH0TOI?9lQw&obbrXKI&4Rsc#`0(g-QpNBE(zJ`D?j(i~lkhXJAvP3Pu(oxSE`9>1 zq?SdhuSTHe5^6C1Bm{2WUB9+4Hx%gY<>qQ`26B_@YZSTy2!Md$=Ydzh(_z1j=$b45 z@SkU^+CrS%+PAo;x%w@%$6m?-N>PabM61qf)%j0NzY-5T@mN zzbNR}HY*4o`d2U<#>p)4ITFg_6^anM$WnfEMSxZt+76ND6bwjw02lm#6@*OED;O!N zB13sQ3FYG}6opwMOZmwa0rrIdQiz89^-OgZ8>fBkHXR;>k1dq=F9G zmkH=CeWAUMAl2K$YyX@VhPwHUXL}kN&b%5REP<(iTa@-3>^W5p8MCgs=Dr)wJL{ZV zB2Hp8v*N=mBj1Lqc}ir5fXZ9C;n$xAO{2gjsb(usv zSn#ad?77F?V4Q!K_B5h+^E|2i5pN#61aQ&3B4i#XM4ZAML#fyAYs7OH77@lq@;8(@+1oP8k)_t#*p1#^ACvy{>R literal 0 HcmV?d00001 diff --git a/docs/assets/img/favicon.png b/docs/assets/img/favicon.png new file mode 100644 index 0000000000000000000000000000000000000000..5ce0402cd78627280f4bb87ffebad02e66a086e6 GIT binary patch literal 1833 zcmV+^2iEwBP)i00004XF*Lt006O% z3;baP00001b5ch_0Itp)=>Px#El^BUMMrQ<`T6<(|NsC0|NsC0larJG|NsC0{{R30 zDJd!4-Q81DQ@gvnczAf3nVFc0wEqAA00(qZPE!Euph+3VZ32jV>Hq)+herQY39s>-#TzOCY09=ufWwj?lR*{M) zP5CN`8#O`?s;{One+&k{x&hE}gM{i|V$9KE?W@p~a%`&ErJ3l_T>(vOuzx(93 zpP6<1Kmsg)zq3Hz{|#C%2cbGs4~@CwaUiI0Jf?F-75}gt-`Tg zHBB;ATUCPY(N_P-Bdj0EeZ&t@&uuI~cX6Oo9w(URo-IH<BpGqHw9=LXQ&v^aRJ)GfqDe; z=k$9hKZSTI;G9H13bZMK4pE?phw2jO3)JC9JaZy}wyOf2N}vG!4=z8PzfP#2eF>D8 zf?xRQT;CQ(BcJn`{Flpfa9bGVkgD{*{U9x&Lj+xt-x9w*5dXWHr0x_M_K+TmUoXP6 zf0^>q@Mxe*@+bX*{@|}Z*T#qjx7nD|2%K|p^hltQV7Jb#<0T2S zE=X_ML1{A`i{AuR%vM4Ior;4L^lhLsnw<*r!_2DLV=TD80xlcSIhZD#;KPvBQd1TOsX5VpYR00mr zX5V-s#bLN0N7F~3bsk8Py-N>D+{xm7zeTiM~mMwI2XVeMm?oByDr-<>#`e=M*hUc9JQWVqz0L z`{@xtBbD4h3mA1&j>b&!_;~dW;H_;uXi$E&eTmmLkN^bp47-a-q=mQLH3+#+nVNXr0#b9%uz4T zooiIM=EzMyLndWuvEsl@zY#P@O$WB`tfVtk*-*)!GAI2EpOkh=Z<|~LG&NO88czBd zJ}J%RQ|P3hVQR*z6Y!lMQW&OYT=Jo*i+*M&zXff;*hN3HSB`p{zy{oR(a-Faqe&@f zO;GeRd*vv}KN-qlpy^U+%vv^#H7#_6p`TgF@9HOOhM=EW%Z3NKyMYQ|w{4Fdvcm&WfD8obhw;dN~3a2&$4RnYH^$q!gE`?s; zK|@mx7Mb%Q1=O>CFqk>C5J*4#E&7C;Jceeh2^uuxMlU?DecdTQw=CoXi}O=A{a`18 zZ~H}LN-|~8T{HPHLbpQnKZ9CEB5U0-bke^MHMi95nbN>T|5K<9=ftiR)N=*Ac>`(~ z${bRuVfwTw#$%|pY3kDSnc*X>7~71QRHP-P39X<$*e>Qy=-=6_e-CPG3*0rbRpA<_ z`0hh3cp;+hxM?X(Z$Qn00jA$(YA#LhfNhO^L=#KX=pB5x0ds8q+#s7(3q1K?t7ya# zU7-ti4Y{!mLsRP%(-b-|NXczO`)%{Wjd^8OGtimds8KiqUwv<#EzN6bzOJ%Od}F;0 z?Q3bhU(Y3hwOnUd&&7+iToI|{GRxPW=i1F$E(opXD${x{UESn**jL-1_aa+WSML4? X+`DcOw9~e*00000NkvXXu0mjfVrFsw literal 0 HcmV?d00001 diff --git a/docs/assets/img/preview.png b/docs/assets/img/preview.png new file mode 100644 index 0000000000000000000000000000000000000000..1c213343a4791d19df6a76219ab9deb6ef205d2c GIT binary patch literal 11624 zcmd_QXH*nXur5l@L6DrIgc+iMNK_=}I5g22kRTvAM`1)HNd^H4f}k)1G&#czNJbEm zQ9+V|AUWr7Ip_X3cdh&0-*?Vh??$0ORbBnX8yjj-Q?OCs;o(v1Xsesz z;SquVaS;*TNLXpBFKz}Rmxl%q@$hO>C@&DiH*T>M@RgHxqheeRGYQ@%s8& zQBiSbW~QpDDj*;LC+jYRhsT4bqyEr5czR=YC~#UE?|}*N+s6M?nx9pnZfRsFe)eTC4)YIEM&=;}b1AvSY5e?pA>LEbzLSGQ~sND!| znyFPFSnHhTU)$6x;kuK)Jf`QKO))BkmXue>^j zw_-K?6QLux9=@aJhd2wlH(bEn zh|@JA;1R-PZgRO`thhWE{3tzKm%~DsU6GoMzh0Gub`W|_?shYOfhr7;m>JhaZbx^!R|;l>^fY|Rqp^QHQm}gU^M|uSh=K+s z?ES!1t4Bi-e`+36u4jsUMO&@qXg_1JX21K-7WmN7Gd#Ibm-qQackk7GFM8)+-=jf# zL&J3yNVTDR2w0_4*Vqo4+OHiPQ@U6sV>f#p7p5-_0U@;ZJ(6$PwKY|jPIf{z?Uaz} zp}%{lEvVx&8>N4^tsY%@xW$~cRb*7XtvLTB#_9oZF4XGp9)u7q$PE;Fr*l<%&>9hZ zS!)}}C3uGyvDqFZZz$hE0V&^9>{-uy_G{+r*~)Q?YTZ|bg#bwg+&@q9W{K6EFNjZ% zn`>03Q*0Ac!D@o8BTZoCHqK(Fb#iljdtY9){%c31#)&Zc?$6sWv<(f7L~~8mv~}a- zCskjcQN(7+prQVlv)dT=ea7#?OPF_|pk9jz18mq}@#up7>jMmR*I&OygUj^=UEqVe z&q>1T{o+I8qc0v}kH19?44l<^3Zo|*!>sRnbVQ#6!{hBq8Hl@!e{0%R#=-2zQBVn0 z^b|HCa`pM)O6!Y-R!Ogrq%2>vA4b5RmE)-M@kG^UKRSDmFhbn6LV!~*K?@$t_`r9H0N_7IySEO zPh7{;^DKX}A6h`7ICq`jocr^x5pl{=blHe@T^&6=Zmbr8DvH#Q`Rm& zo?B{;?w0n`%6W9t{B>c*l^m{E*!E0cZZo!zwY3&CD-DNIg>rt1qI`neem*rbpvj3{ z{i1K~PlftB$&&Dw5GSxXd1}>7h!ZSw{!H`h`dO3)3ig?hn?srTxk`^3`F#OzPM2xmmH<>!|x zeoZd(_vAsRBzad0mk4eJj7p&uFnPzw$9AcFXS>)$UDSQv=jp_O;M=1HULPRL`6|)2 zTY`q$*sxBU>+d4rU&n7rO^%p<(%2 zZ)qSo+vh=H-{T*ziu8&qL_YW{=s`hS{kVVRL-x~%E3Uu?VT^%q!~9@~WE-V$Toi4s z+;k~Z(0ZY#W1*sqO;-)QDqE@~8fnBsZ6tuUKnJX&|M@{47qu7kcN2*{-G1$#lqHGI zn{oUg_2iQIS%is9X!Gil$aaU~ulp~Hnl6b-8TPf>z;ZEFD)e@&$@^|Mt}FF#E$i?` zFYw}vLUAT(|XVxcQTAUAw4iu5?2j_3@#fI8$wm10HPm7_*BJqVHUH`s8 za9-~o^ZnMBgc$8<9IE=$E22Ekuid4|?fn?yQ)<7)T3o*!tmXDSVY<6(aXKGhC+nW(^h%0oA$=xV)_SWr5Q)nLWd!VySYWl+Y=_3Vm*utLjsTAxnf_neuHt)X`GKe)$|9P=yF!bo_ z&L>3Xg|q;ryB}-F-65m3n>F^>uPyU$j|eMTTOsaIxeRfWtwPXiE}WjP8F8X}+i6~1 zS05%~PA?AcZ>V-C`bP#&o=d@^5Eic|1{8*^)oH>z4$roCoNH#;lQUK{9dUe1+qMFa z*X~fRhn^1`5CrvHav}P1smf<^Dh~hkz`Le@-cRXXrXFUC^T7x)`l(7pgW8b1v+QU zK}86QDy7$w%;F`qZTU@@IV_~x2o7+ogxlCiS>GK$_98-^r^6yz} z(-?mzN1}8U%)gkqd%P83r0_23{;2oyBv#YIGoc5l_s?TcUD<)wiSS-TA#OvolQ;j&KQ z>HZ?YmRQ)YpF&2-(hnnLSONa7&bTM=!#D%XUMTt_MjwyKm-Fy*w}i;h^aYE*8tC?= z>q9^tlv)27E5lf|Vi#Pb{5g5>{33Qy`;{M|2N>!C&w3-!LhD!eOAa32cIM3Za;R;5 zY{dod&f~L5{@|B zW>4@h(a$dOuxo}9A)biC;ta=vtnuB;ymHKV`;3P6j)`D#Ht(g#E$i=fGC`(#lEK2e z4x0BJ!<#hYWiHn~J6{pn1mFv_w<9nH1CRF1d%NuoT3@@dJ>9lIvKYY;kedV-w)(#K z()F~G{z+IbAzZ|R zgl}U)-_hy%8OQd^AY8eA!o8fDLt*-qz5LO5AZfOiP}2$C_AD{(gZ0)*T4b1DyuGhV zMv=Q;7hz%Il}@_BL{sL5?+kz1$hr>_QEeFgb)X^$HB8arU^+5JRNH0lVfq%1Y302yUR&y*D1k5zM!ys| zYYEkQM&Ot}56igw^VoCCZLgMp?`F+P8dqFF=Ok_st)R`@S=MPHqsyL}59XX&Xw41U34AG3D)nJCJKQ3o^LvFH%~f%0!3yQNu>f%b@lH@;Xq z^G6`!FAT|ZJabMg`CIGjhP>ofrZ5U-`3+e)lE(y07Og)2del6 z`l`D5o4CR{-WM>Ogqf3g7A7G#W}~O*OTFDmgz6!xUNY;tqlhxi{8nrKOgCanOM3!b z{P?-R)7Tk$bj**hDUfnAg7brX^vw0X{yI4=&a&FB!BGg$OY4rxz_@`%N^j(Y-w|fu zFtP=U(BY%}ShKWfPi>*b7#4B4pSAgLQRsm@@XVyx!6U!@E(nz>4eZ1ZT^ht3Xt6oB zahqEZu}a*LriTQ;Sv~oloh6Kw!wV`(D^NerxE?EMHPH)W)GYr}KC7#2=`)XUvTFaA zZt34dJaRj1s)nHe=zvtdwo;GOku}_|ewjl4C6|7$Mpv>kq zRSslyl!(Vku5@OqJRb-<6V-&aWQz@Ta5ByWnJ+zQ+9aQ6fDVVEQR!yR8eWL2vfGA6NV=#mCjM`~a4DmB(2q7gEZR8r~*$ zu>bta9Ci;%rsdA_WmeNE;`N7XcB_2H>a@PtkoYt$KMS~p^y6Qe3}UKcKsHOf4NbNt zs0I-rr1Uk6TsItPz322+%@tE;I?{9%#->Vx_O>ALxU03nx!L}E;LQ(8;PoHwTR)Lc zT*$TlF~S=i46Ba`VXi;iNA)$IPeHK5{0| zU7a!_ce!0n2XA58#G0#qIT=w*UBYM91LlH2N+zGY= zqCV8ghBPpglt+`U#l%lGXd-Egvj|{Fjq~7xTooJZ$PqIrNk?RwmExgHhZgl1`HPEg zp}*KB4_=$5Oqhp)*QmFa+ConTevV%f)J_vdb9@T_TQn}PYnPY(3mYSxrQ zOy1N%cjWCh+X52kqa!^4M@MmqnQViHY~Hh}O}pHHhxm`X(cWK_3&bPfdI(<)=3kEY z8V)_$Js-4fW`LH;xjW_ERUpT>nFyh5iLxop2NMR{YFWf+nf?u0py^Ks_hF`BXaHZS z{>?MFpudLd;slXI)*DZJ9IEj3I6`q>jcDCtmZwYt(ms~dD+442*7ZbC@V2hG(kR^{ z3rg9z6uBYV6i7^2;OsUzw1Y4@#dOP^8j!9tEU`t(2MG|4Xnk|GElDsW0C)7W z6TP~d-u$r@UMkC6{v`Nh$`qTU$jof#S(X4NwvQ8%VYi_M2OPDy-Tu0Qxu(?HeNEaePWGGx6Mj8ykc;Crz#*S z8LMGVF#C%UU@}RPwyz}vott)oA2MnZGGz$&d5wK;H|1ucz$Dy;=2wwae+-dJA z1*FBu+Qo++!>yu4Orte44IUOTXPT}Zz@?tZzJY6S;IFrm?xzJeRER3v)ICPba_ljT zM)Y;T)~vLS{l=XIVwA^6X4y^E8->53vTz!?rr2z@AFOCNikj8I%`z zAP!M6}3QFV7rsFAFa<&y~zuTYPjDII=#@++jx6d?_AJduSFxWC7&fjhh|bxf=2 zN~!T*`w1ymG7<0i!!Law+UDHslnPBy7i+O`wY#LycuSlHjP(UQJLjx}e|SI8iZV_1 zI;;6ifX!1G=(T(9#B0_-56}_;_X}lf7{$;vX7FnIAj%*qzo`>0aHD%imYD@Ow0q7N zIzAu*d^nL%q=P$ot6Z(@CD;Jx_Zedx(fnOiuPb+_-uSN-yjQW(5aI+7dts7s0hp3A zXSZJ?ivFg3b=Xk(EI9F;;tIQkFmPFtu76W+#gfNm#5bK3GT@Pp*{?27rPNIo9-J(@ zumZA-?MZB)raH*?cH6(K#~&VBz6xksUF3Mx82K}|61qqvQPykaI^dJMkd3YPat}c8 zQe@kZXx^Ae0eo%{IfZnxw?FOe<6^3p{IjT@;1rD}3wzPXdzg2d-NXL~{M4Jr>Dk5% zQXE=2JgBl4EIQoT@cXc>I3&kScUVg7zSX&sKy)ewP!dDBULNIQ>k_fjHGCm0vTey1 z_>y4g)&g73CjyS>o70WvTPF)v7nsl?WBQY`!+xuq`SgY1JWmuJ5p<{jQp;o_^<>kq zi*&xvi(Z}T8W}6ZAyd6Hf|6;_@VCWwwJPFc}X;6mn}x%O!nJ+d=EnmBwua3??=VB4i5by|o!&E854`^ilFAZ(*8( zCs20#C*Um-_gc6?cXKN{s74=X5 z5pIXq*IDDG17_l_qXLhF<$t>A@ftbLwF+}Q;DOIhz@tr1>{bD{vYmK9^H8SUx$uQ77wD{X zX4DqMhtnJxoW81}wMQ)8!qYKT7XLF<%#Um&Ex(-xG;(D$jIhMxt-GqJuIK9}@^-v= zLqhl<=XpYlova){>;bC=n`e*(8_Zs0k)ffZn?p7QKhkM5 zLI?p|-nRN$3lejnr{8RuBWbPPE|PFF{k0)0l9I2M)5ysZ zU5}ERo=R)kXL0GI0toR>mgQL{?*&@30I?BvkM?1Aa?BLPVq#(}*!!9=hb|HA;wM8q zB`yh!CiZuosTJgaJBhVdJ!_H6%44%$M!OXaG(hL<*rr%`pLZx4c7)H)#58-ZV5(Ev z6ShCRiFDeFbw@XbPQ4TPHQj=DG^hQ@`@5sxx?xJhb#^#$6;q&x&7@r-@9Ewf+0|7z zYfqinSMqW-p=-b9QaZ^*L1;2XZ@(Y;+8yG!*x7r=I?_%IKJ9MdAXUJ^0R8$&L*P6A zJi^4#nj{i;$MmN<%M`LUwxX^kAH??C!y~%o zer`VYDkY!ooObQ$;nWrv5VZ3vOahRvX<Zog{(m&JQzN;dYr-b!HF3ob}8pUwxVKWC$whx#zWEVHTvm&m))6sUCV>s7fc6|5Pb`b3Eq}ZIa9|=8LHQsOcgRdbx={8ty-W1H$mwP?E%9<~dc%z}kb;6{O47wXSiq z-Cu{?!UjLZqQ~BK0^ZSxcMk%+!ibmt?P2x~Vl9PS51uL>{F$;wkE-N%sus58-0Q;a z^gbj+#r6pgUy?qzFoT!b{CIi`xV|$sSIXDsl!nr}IN!zh{)SC?DZy%Y)^r&&>AT)YvcIO?i!@EG|;@fF)JoH0U zu^i2aB20ZvEaAoMEE|`dad7oV+0|F@Wg#UPBR!qAwr3;2iEIpbGgMG<4T(E+d%xg8 zIAmWHG0NsI1MV0MoEd+i%kfGZZ>Gf!$!-@E8|Mk!+9(hvm!I)|_lBTV9VC-&w|G)^ z1&_$y*Uf2mjXHBJ6nb+P{k%KnPCn~RtdT-Hn2F$JDMi1g-!U+BE|UAbVjC3dR(m&C$>8K0o~J?JwM6)DAxdDY zm&MOJgylC?0OH+WYA*Fq*G6FwEKv?oW{09%Lp39#7ELVf#smn@ z*0*ZOEZ|QgMe$P1N%Wwk(8VyOw0Y5QUX`_$a?^hpCG#l|e6f~*u$GSOuRc#tmfL7% z|8mY6Q^BsQTH1#lpZuxX3l_(cw{o!*cP%4f*RQ;!ev)3Ka+Ll1HH2=obI7RNX!%TC z8XY@kM|Y;yem4`pyA<=xM|cPEj%V%x0xa?)h8*8l>?sCS@$jft|APzgc|G#*jna$g z#z$n=pY1S>FNv6U*dM;WS?164WvA*3s;KC|N-?@p@TD1_4d(4xXRV^!@bCx$Mxm;M z^z5a9LjNyX@5={m1Ev+ARXtl+w{NC-??Qe)Ys~UGiSj<=j+dX0Q1SO`UTWCux$ecU z+luZ#a$%0q7N2R+Jk?6s=_Wjn-}+v^<)zLZcwJA>oZ7JMSH|i#2VWL_1)=@p)j;m` zI@hq0YEIDUreF2Ugc@Es@%2x^ivPWP;7unt74^3xb1b7lzsLIV>`#2NhZuOTNm7$- zOp}Y~+6>_!HYVUeIXw>={WQ-DIlqc^yM-hDjdIIe_xh~5iR%tQ5-+apo@(d&fcNvy z4VewEzWwYdBVNZBH7o9(s-7R$q|wO=+sI&lg(YY(C?C%%{TKs72S&VA>bg`3e?31t z*%fpa>W@tIo7tH^9vS5I(d6;6DqneA_P98~E)HoX43!Rzww)#H=NKz6-Y9!?#^r8PIgF6md#W*qDKOT1`8rM9HPKoyx`di(& zHA9y`?pnnr#8@d0uV~o>)Zwfj0)l&{x?JQMjKXi9EWpoCeScXb@}NQm^ky!3K>gR+ z$LX)?iu5aZU(0%NZN$>)K#XtUi2|^%{tc4bH8; zlN_5Z@;eZt>r9Y+mG+NzX@=GUVvx=-;dWhoJ?rvqui|6me2qN3kA?-t&kCKCqFVlv z!yv;-8l2a#d)q+Nn3(M#j04GK zO?Bqe`vgMgYK$;?PQAUr>m<+8{2p7&*$RF(m_uTa61cKMXV3anTW-C?@{i)TyzW%x z$^&r~Am8e_;9*4mIODh5Y{5IjjV;9CZYRr(B+z+Jk^5QLHMad51w3kMwiwe=DKgYp z+n}4vcfmC)$`}T$F|npJFfmixgH3NLpvs!KT|MjLBuiq&j9hvu2|t}QHp=W}bf187$}Y%D?A1oa zOd#zh=V2RDAxHiXV;Pxmw^`7+(Soo@N9xOJP$*Tkvm+9dC6IDv*{J&-fxc{-q>0Q< z@B-WN%31?JHzSbk<01b?We%FS;aYLgPaDPugN#1MD^ywipOF@4KEzSXdxOdi^ts~D zSEdg{+pxoqH$A0ji(8>;$RW0SSwg9|-|FR++tc}daFdw4OA2NR0WK|$oL2LNsU;#p z)92z^@`fb%xY=jOtT5lQc_+l6eA2pvig>Pi!9vvc8^1c@zY9)dF z6pEYgyz);#AMhe26b5HRVRnDuNz*9y$FQJ3S0R`4L+%w0m4Al6PtrK~F;0p0U{ng# z)iVql8!w4Vn%(0ffh|CmWOVgD897M-&7`>5*~R05;HaohS}E%+WghJ}l-6M6XFRl= zgG5(wqn;A$hq`_iw=Q_ZY5#}gbIH;&2#c?1A`^P^0(17Le{s2yO43^PXQ3MXI`5qaq#~=6uX_XKebdP_2jfvnr9b_iP#o0Ux z{UkwM^Mm;{CG2h(_=RhCKWQlM<}Sr!4uIRW)1mZ{L4R}vFLGJ3H+9up^{2?W9;e2I z=KEc2<;280_~Su%Yg~_zo?!ENG8wFn3Jhm^v;C9#>uc!MRpvyEFQfj$XVDv!Lm1s` ze4OfAxrehh9Lz71uCqyD6NbKAgh{yET^<669T8AhZ%B~Dbgo9PT*m? zQKrE>pFEW`Y7@Ng9SQO+Y^Bm6z-j8cS-r;Hb)nor40;6XqO%3$trxLVVd`LI2r>%+ zBLf2m*9x#-Ij5kxU4xoU77M^ymUl-Qv+imlHO#;aA z$Flax9V%Q3De6e7!|+`n{4|+d?q3oSQ?dR>P9c&+EZ>MMCYGuB?9w014B~JZarOBg z<|@D_)xbrJ<||J36ydDHp8bOl-Kuxb-0=XlG1lYEXeIRFKqkZq$%xi>rh#$hN#C!< zveBY9J+NvAvTy+dI?^JQbvAH1nwp6k*bU6cKnjv4Z^h@Q z>tOPFcFd51+7`dl9_v4(fT{NyQD?umh>x12q17iP2k5dyrGOY~!N~MJibQ8q2Nf*` z&~2}}=tJFMLfB0Ux6iz?0d6;$=Z~lgj&hcB#Z)>|;tKD%&4T?2Y}OeuSveE?-b#3X zAT9+m^~5M=WI#sg8y;qDawc}P4X1RZcq%J(kg~N+*mk8N{p$9tQQG$6fu8b&m f|G(ycdb7Kj{IY-!E-T%zqVaSz4AraE;4%LT=c`1f literal 0 HcmV?d00001 diff --git a/docs/auth/enumerableroles.md b/docs/auth/enumerableroles.md new file mode 100644 index 000000000..237cf899f --- /dev/null +++ b/docs/auth/enumerableroles.md @@ -0,0 +1,244 @@ +# EnumerableRoles + +Enumerable multiroles authorization mixin. + + +Note: + +This implementation is agnostic to the Ownable that the contract inherits from. +It performs a self-staticcall to the `owner()` function to determine the owner. +This is useful for situations where the contract inherits from +OpenZeppelin's Ownable, such as in LayerZero's OApp contracts. + +This implementation performs a self-staticcall to `MAX_ROLE()` to determine +the maximum role that can be set/unset. If the inheriting contract does not +have `MAX_ROLE()`, then any role can be set/unset. + +This implementation allows for any uint256 role, +it does NOT take in a bitmask of roles. +This is to accommodate teams that are allergic to bitwise flags. + +By default, the `owner()` is the only account that is authorized to set roles. +This behavior can be changed via overrides. + +This implementation is compatible with any Ownable. +This implementation is NOT compatible with OwnableRoles. + + + + + +## Custom Errors + +### RoleHoldersIndexOutOfBounds() + +```solidity +error RoleHoldersIndexOutOfBounds() +``` + +The index is out of bounds of the role holders array. + +### RoleHolderIsZeroAddress() + +```solidity +error RoleHolderIsZeroAddress() +``` + +Cannot set the role of the zero address. + +### InvalidRole() + +```solidity +error InvalidRole() +``` + +The role has exceeded the maximum role. + +### EnumerableRolesUnauthorized() + +```solidity +error EnumerableRolesUnauthorized() +``` + +Unauthorized to perform the action. + +## Public Update Functions + +### setRole(address,uint256,bool) + +```solidity +function setRole(address holder, uint256 role, bool active) + public + payable + virtual +``` + +Sets the status of `role` of `holder` to `active`. + +## Public Read Functions + +### hasRole(address,uint256) + +```solidity +function hasRole(address holder, uint256 role) + public + view + virtual + returns (bool result) +``` + +Returns if `holder` has active `role`. + +### roleHolders(uint256) + +```solidity +function roleHolders(uint256 role) + public + view + virtual + returns (address[] memory result) +``` + +Returns an array of the holders of `role`. + +### roleHolderCount(uint256) + +```solidity +function roleHolderCount(uint256 role) + public + view + virtual + returns (uint256 result) +``` + +Returns the total number of holders of `role`. + +### roleHolderAt(uint256,uint256) + +```solidity +function roleHolderAt(uint256 role, uint256 i) + public + view + virtual + returns (address result) +``` + +Returns the holder of `role` at the index `i`. + +## Internal Functions + +### _setRole(address,uint256,bool) + +```solidity +function _setRole(address holder, uint256 role, bool active) + internal + virtual +``` + +Set the role for holder directly without authorization guard. + +### _validateRole(uint256) + +```solidity +function _validateRole(uint256 role) internal view virtual +``` + +Requires the role is not greater than `MAX_ROLE()`. +If `MAX_ROLE()` is not implemented, this is an no-op. + +### _authorizeSetRole(address,uint256,bool) + +```solidity +function _authorizeSetRole(address holder, uint256 role, bool active) + internal + virtual +``` + +Checks that the caller is authorized to set the role. + +### _hasAnyRoles(address,bytes) + +```solidity +function _hasAnyRoles(address holder, bytes memory encodedRoles) + internal + view + virtual + returns (bool result) +``` + +Returns if `holder` has any roles in `encodedRoles`. +`encodedRoles` is `abi.encode(SAMPLE_ROLE_0, SAMPLE_ROLE_1, ...)`. + +### _checkRole(uint256) + +```solidity +function _checkRole(uint256 role) internal view virtual +``` + +Reverts if `msg.sender` does not have `role`. + +### _checkRoles(bytes) + +```solidity +function _checkRoles(bytes memory encodedRoles) internal view virtual +``` + +Reverts if `msg.sender` does not have any role in `encodedRoles`. + +### _checkOwnerOrRole(uint256) + +```solidity +function _checkOwnerOrRole(uint256 role) internal view virtual +``` + +Reverts if `msg.sender` is not the contract owner and does not have `role`. + +### _checkOwnerOrRoles(bytes) + +```solidity +function _checkOwnerOrRoles(bytes memory encodedRoles) + internal + view + virtual +``` + +Reverts if `msg.sender` is not the contract owner and +does not have any role in `encodedRoles`. + +## Modifiers + +### onlyRole(uint256) + +```solidity +modifier onlyRole(uint256 role) virtual +``` + +Marks a function as only callable by an account with `role`. + +### onlyRoles(bytes) + +```solidity +modifier onlyRoles(bytes memory encodedRoles) virtual +``` + +Marks a function as only callable by an account with any role in `encodedRoles`. +`encodedRoles` is `abi.encode(SAMPLE_ROLE_0, SAMPLE_ROLE_1, ...)`. + +### onlyOwnerOrRole(uint256) + +```solidity +modifier onlyOwnerOrRole(uint256 role) virtual +``` + +Marks a function as only callable by the owner or by an account with `role`. + +### onlyOwnerOrRoles(bytes) + +```solidity +modifier onlyOwnerOrRoles(bytes memory encodedRoles) virtual +``` + +Marks a function as only callable by the owner or +by an account with any role in `encodedRoles`. +Checks for ownership first, then checks for roles. +`encodedRoles` is `abi.encode(SAMPLE_ROLE_0, SAMPLE_ROLE_1, ...)`. \ No newline at end of file diff --git a/docs/auth/ownable.md b/docs/auth/ownable.md new file mode 100644 index 000000000..556263bc7 --- /dev/null +++ b/docs/auth/ownable.md @@ -0,0 +1,209 @@ +# Ownable + +Simple single owner authorization mixin. + + +Note: + +This implementation does NOT auto-initialize the owner to `msg.sender`. +You MUST call the `_initializeOwner` in the constructor / initializer. + +While the ownable portion follows +[EIP-173](https://eips.ethereum.org/EIPS/eip-173) for compatibility, +the nomenclature for the 2-step ownership handover may be unique to this codebase. + + + + + +## Custom Errors + +### Unauthorized() + +```solidity +error Unauthorized() +``` + +The caller is not authorized to call the function. + +### NewOwnerIsZeroAddress() + +```solidity +error NewOwnerIsZeroAddress() +``` + +The `newOwner` cannot be the zero address. + +### NoHandoverRequest() + +```solidity +error NoHandoverRequest() +``` + +The `pendingOwner` does not have a valid handover request. + +### AlreadyInitialized() + +```solidity +error AlreadyInitialized() +``` + +Cannot double-initialize. + +## Storage + +### _OWNER_SLOT + +```solidity +bytes32 internal constant _OWNER_SLOT = + 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffff74873927 +``` + +The owner slot is given by: +`bytes32(~uint256(uint32(bytes4(keccak256("_OWNER_SLOT_NOT")))))`. +It is intentionally chosen to be a high value +to avoid collision with lower slots. +The choice of manual storage layout is to enable compatibility +with both regular and upgradeable contracts. + +## Internal Functions + +### _guardInitializeOwner() + +```solidity +function _guardInitializeOwner() + internal + pure + virtual + returns (bool guard) +``` + +Override to return true to make `_initializeOwner` prevent double-initialization. + +### _initializeOwner(address) + +```solidity +function _initializeOwner(address newOwner) internal virtual +``` + +Initializes the owner directly without authorization guard. +This function must be called upon initialization, +regardless of whether the contract is upgradeable or not. +This is to enable generalization to both regular and upgradeable contracts, +and to save gas in case the initial owner is not the caller. +For performance reasons, this function will not check if there +is an existing owner. + +### _setOwner(address) + +```solidity +function _setOwner(address newOwner) internal virtual +``` + +Sets the owner directly without authorization guard. + +### _checkOwner() + +```solidity +function _checkOwner() internal view virtual +``` + +Throws if the sender is not the owner. + +### _ownershipHandoverValidFor() + +```solidity +function _ownershipHandoverValidFor() + internal + view + virtual + returns (uint64) +``` + +Returns how long a two-step ownership handover is valid for in seconds. +Override to return a different value if needed. +Made internal to conserve bytecode. Wrap it in a public function if needed. + +## Public Update Functions + +### transferOwnership(address) + +```solidity +function transferOwnership(address newOwner) + public + payable + virtual + onlyOwner +``` + +Allows the owner to transfer the ownership to `newOwner`. + +### renounceOwnership() + +```solidity +function renounceOwnership() public payable virtual onlyOwner +``` + +Allows the owner to renounce their ownership. + +### requestOwnershipHandover() + +```solidity +function requestOwnershipHandover() public payable virtual +``` + +Request a two-step ownership handover to the caller. +The request will automatically expire in 48 hours (172800 seconds) by default. + +### cancelOwnershipHandover() + +```solidity +function cancelOwnershipHandover() public payable virtual +``` + +Cancels the two-step ownership handover to the caller, if any. + +### completeOwnershipHandover(address) + +```solidity +function completeOwnershipHandover(address pendingOwner) + public + payable + virtual + onlyOwner +``` + +Allows the owner to complete the two-step ownership handover to `pendingOwner`. +Reverts if there is no existing ownership handover requested by `pendingOwner`. + +## Public Read Functions + +### owner() + +```solidity +function owner() public view virtual returns (address result) +``` + +Returns the owner of the contract. + +### ownershipHandoverExpiresAt(address) + +```solidity +function ownershipHandoverExpiresAt(address pendingOwner) + public + view + virtual + returns (uint256 result) +``` + +Returns the expiry timestamp for the two-step ownership handover to `pendingOwner`. + +## Modifiers + +### onlyOwner() + +```solidity +modifier onlyOwner() virtual +``` + +Marks a function as only callable by the owner. \ No newline at end of file diff --git a/docs/auth/ownableroles.md b/docs/auth/ownableroles.md new file mode 100644 index 000000000..6f7f74e17 --- /dev/null +++ b/docs/auth/ownableroles.md @@ -0,0 +1,219 @@ +# OwnableRoles + +Simple single owner and multiroles authorization mixin. + + +Note: + +This implementation does NOT auto-initialize the owner to `msg.sender`. +You MUST call the `_initializeOwner` in the constructor / initializer. + +While the ownable portion follows +[EIP-173](https://eips.ethereum.org/EIPS/eip-173) for compatibility, +the nomenclature for the 2-step ownership handover may be unique to this codebase. + +Inherits: + +- `auth/Ownable.sol` + + + + +## Internal Functions + +### _setRoles(address,uint256) + +```solidity +function _setRoles(address user, uint256 roles) internal virtual +``` + +Overwrite the roles directly without authorization guard. + +### _updateRoles(address,uint256,bool) + +```solidity +function _updateRoles(address user, uint256 roles, bool on) + internal + virtual +``` + +Updates the roles directly without authorization guard. +If `on` is true, each set bit of `roles` will be turned on, +otherwise, each set bit of `roles` will be turned off. + +### _grantRoles(address,uint256) + +```solidity +function _grantRoles(address user, uint256 roles) internal virtual +``` + +Grants the roles directly without authorization guard. +Each bit of `roles` represents the role to turn on. + +### _removeRoles(address,uint256) + +```solidity +function _removeRoles(address user, uint256 roles) internal virtual +``` + +Removes the roles directly without authorization guard. +Each bit of `roles` represents the role to turn off. + +### _checkRoles(uint256) + +```solidity +function _checkRoles(uint256 roles) internal view virtual +``` + +Throws if the sender does not have any of the `roles`. + +### _checkOwnerOrRoles(uint256) + +```solidity +function _checkOwnerOrRoles(uint256 roles) internal view virtual +``` + +Throws if the sender is not the owner, +and does not have any of the `roles`. +Checks for ownership first, then lazily checks for roles. + +### _checkRolesOrOwner(uint256) + +```solidity +function _checkRolesOrOwner(uint256 roles) internal view virtual +``` + +Throws if the sender does not have any of the `roles`, +and is not the owner. +Checks for roles first, then lazily checks for ownership. + +### _rolesFromOrdinals(uint8[]) + +```solidity +function _rolesFromOrdinals(uint8[] memory ordinals) + internal + pure + returns (uint256 roles) +``` + +Convenience function to return a `roles` bitmap from an array of `ordinals`. +This is meant for frontends like Etherscan, and is therefore not fully optimized. +Not recommended to be called on-chain. +Made internal to conserve bytecode. Wrap it in a public function if needed. + +### _ordinalsFromRoles(uint256) + +```solidity +function _ordinalsFromRoles(uint256 roles) + internal + pure + returns (uint8[] memory ordinals) +``` + +Convenience function to return an array of `ordinals` from the `roles` bitmap. +This is meant for frontends like Etherscan, and is therefore not fully optimized. +Not recommended to be called on-chain. +Made internal to conserve bytecode. Wrap it in a public function if needed. + +## Public Update Functions + +### grantRoles(address,uint256) + +```solidity +function grantRoles(address user, uint256 roles) + public + payable + virtual + onlyOwner +``` + +Allows the owner to grant `user` `roles`. +If the `user` already has a role, then it will be an no-op for the role. + +### revokeRoles(address,uint256) + +```solidity +function revokeRoles(address user, uint256 roles) + public + payable + virtual + onlyOwner +``` + +Allows the owner to remove `user` `roles`. +If the `user` does not have a role, then it will be an no-op for the role. + +### renounceRoles(uint256) + +```solidity +function renounceRoles(uint256 roles) public payable virtual +``` + +Allow the caller to remove their own roles. +If the caller does not have a role, then it will be an no-op for the role. + +## Public Read Functions + +### rolesOf(address) + +```solidity +function rolesOf(address user) + public + view + virtual + returns (uint256 roles) +``` + +Returns the roles of `user`. + +### hasAnyRole(address,uint256) + +```solidity +function hasAnyRole(address user, uint256 roles) + public + view + virtual + returns (bool) +``` + +Returns whether `user` has any of `roles`. + +### hasAllRoles(address,uint256) + +```solidity +function hasAllRoles(address user, uint256 roles) + public + view + virtual + returns (bool) +``` + +Returns whether `user` has all of `roles`. + +## Modifiers + +### onlyRoles(uint256) + +```solidity +modifier onlyRoles(uint256 roles) virtual +``` + +Marks a function as only callable by an account with `roles`. + +### onlyOwnerOrRoles(uint256) + +```solidity +modifier onlyOwnerOrRoles(uint256 roles) virtual +``` + +Marks a function as only callable by the owner or by an account +with `roles`. Checks for ownership first, then lazily checks for roles. + +### onlyRolesOrOwner(uint256) + +```solidity +modifier onlyRolesOrOwner(uint256 roles) virtual +``` + +Marks a function as only callable by an account with `roles` +or the owner. Checks for roles first, then lazily checks for ownership. \ No newline at end of file diff --git a/docs/auth/timedroles.md b/docs/auth/timedroles.md new file mode 100644 index 000000000..67480c1c0 --- /dev/null +++ b/docs/auth/timedroles.md @@ -0,0 +1,226 @@ +# TimedRoles + +Timed multiroles authorization mixin. + + +Note: + +This implementation is agnostic to the Ownable that the contract inherits from. +It performs a self-staticcall to the `owner()` function to determine the owner. +This is useful for situations where the contract inherits from +OpenZeppelin's Ownable, such as in LayerZero's OApp contracts. + +This implementation performs a self-staticcall to `MAX_TIMED_ROLE()` to determine +the maximum timed role that can be set/unset. If the inheriting contract does not +have `MAX_TIMED_ROLE()`, then any timed role can be set/unset. + +This implementation allows for any uint256 role, +it does NOT take in a bitmask of roles. +This is to accommodate teams that are allergic to bitwise flags. + +By default, the `owner()` is the only account that is authorized to set timed roles. +This behavior can be changed via overrides. + +This implementation is compatible with any Ownable. +This implementation is NOT compatible with OwnableRoles. + +As timed roles can turn active or inactive anytime, enumeration is omitted here. +Querying the number of active timed roles will cost `O(n)` instead of `O(1)`. + +Names are deliberately prefixed with "Timed", so that this contract +can be used in conjunction with EnumerableRoles without collisions. + + + + + +## Custom Errors + +### TimedRoleHolderIsZeroAddress() + +```solidity +error TimedRoleHolderIsZeroAddress() +``` + +Cannot set the timed role of the zero address. + +### InvalidTimedRole() + +```solidity +error InvalidTimedRole() +``` + +The timed role has exceeded the maximum timed role. + +### TimedRolesUnauthorized() + +```solidity +error TimedRolesUnauthorized() +``` + +Unauthorized to perform the action. + +### InvalidTimedRoleRange() + +```solidity +error InvalidTimedRoleRange() +``` + +The `expires` cannot be less than the `start`. + +## Public Update Functions + +### setTimedRole(address,uint256,uint40,uint40) + +```solidity +function setTimedRole( + address holder, + uint256 timedRole, + uint40 start, + uint40 expires +) public payable virtual +``` + +Sets the active time range of `timedRole` of `holder` to [`start`, `expires`]. +The `timedRole` is active when `start <= block.timestamp && block.timestamp <= expires`. + +## Public Read Functions + +### timedRoleActive(address,uint256) + +```solidity +function timedRoleActive(address holder, uint256 timedRole) + public + view + virtual + returns (bool isActive, uint40 start, uint40 expires) +``` + +Returns whether the `timedRole` is active for `holder` and the active time range. + +## Internal Functions + +### _setTimedRole(address,uint256,uint40,uint40) + +```solidity +function _setTimedRole( + address holder, + uint256 timedRole, + uint40 start, + uint40 expires +) internal virtual +``` + +Set the timed role for holder directly without authorization guard. + +### _validateTimedRole(uint256) + +```solidity +function _validateTimedRole(uint256 timedRole) internal view virtual +``` + +Requires the timedRole is not greater than `MAX_TIMED_ROLE()`. +If `MAX_TIMED_ROLE()` is not implemented, this is an no-op. + +### _authorizeSetTimedRole(address,uint256,uint40,uint40) + +```solidity +function _authorizeSetTimedRole( + address holder, + uint256 timedRole, + uint40 start, + uint40 expires +) internal virtual +``` + +Checks that the caller is authorized to set the timed role. + +### _hasAnyTimedRoles(address,bytes) + +```solidity +function _hasAnyTimedRoles(address holder, bytes memory encodedTimeRoles) + internal + view + virtual + returns (bool result) +``` + +Returns if `holder` has any roles in `encodedTimeRoles`. +`encodedTimeRoles` is `abi.encode(SAMPLE_TIMED_ROLE_0, SAMPLE_TIMED_ROLE_1, ...)`. + +### _checkTimedRole(uint256) + +```solidity +function _checkTimedRole(uint256 timedRole) internal view virtual +``` + +Reverts if `msg.sender` does not have `timedRole`. + +### _checkTimedRoles(bytes) + +```solidity +function _checkTimedRoles(bytes memory encodedTimedRoles) + internal + view + virtual +``` + +Reverts if `msg.sender` does not have any timed role in `encodedTimedRoles`. + +### _checkOwnerOrTimedRole(uint256) + +```solidity +function _checkOwnerOrTimedRole(uint256 timedRole) internal view virtual +``` + +Reverts if `msg.sender` is not the contract owner and does not have `timedRole`. + +### _checkOwnerOrTimedRoles(bytes) + +```solidity +function _checkOwnerOrTimedRoles(bytes memory encodedTimedRoles) + internal + view + virtual +``` + +Reverts if `msg.sender` is not the contract owner and +does not have any timed role in `encodedTimedRoles`. + +## Modifiers + +### onlyTimedRole(uint256) + +```solidity +modifier onlyTimedRole(uint256 timedRole) virtual +``` + +Marks a function as only callable by an account with `timedRole`. + +### onlyTimedRoles(bytes) + +```solidity +modifier onlyTimedRoles(bytes memory encodedTimedRoles) virtual +``` + +Marks a function as only callable by an account with any role in `encodedTimedRoles`. +`encodedTimedRoles` is `abi.encode(SAMPLE_TIMED_ROLE_0, SAMPLE_TIMED_ROLE_1, ...)`. + +### onlyOwnerOrTimedRole(uint256) + +```solidity +modifier onlyOwnerOrTimedRole(uint256 timedRole) virtual +``` + +Marks a function as only callable by the owner or by an account with `timedRole`. + +### onlyOwnerOrTimedRoles(bytes) + +```solidity +modifier onlyOwnerOrTimedRoles(bytes memory encodedTimedRoles) virtual +``` + +Marks a function as only callable by the owner or +by an account with any role in `encodedTimedRoles`. +Checks for ownership first, then checks for roles. +`encodedTimedRoles` is `abi.encode(SAMPLE_TIMED_ROLE_0, SAMPLE_TIMED_ROLE_1, ...)`. \ No newline at end of file diff --git a/docs/index.html b/docs/index.html new file mode 100644 index 000000000..9dea9fefa --- /dev/null +++ b/docs/index.html @@ -0,0 +1,359 @@ + + + +Solady Documentation + + + + + + + + + + + + + + + + + + + + + + +

+ + + + + + + + diff --git a/docs/overview.md b/docs/overview.md new file mode 100644 index 000000000..f2937e6fc --- /dev/null +++ b/docs/overview.md @@ -0,0 +1,35 @@ +# Overview + +Solady offers highly-optimized Solidity snippets with flexible, easy-to-use APIs. + +## Installation + +To install with [**Foundry**](https://github.com/gakonst/foundry): + +```sh +forge install vectorized/solady +``` + +To install with [**Hardhat**](https://github.com/nomiclabs/hardhat) or [**Truffle**](https://github.com/trufflesuite/truffle): + +```sh +npm install solady +``` + +## Principles + +Formless precision. + +Disciplined freedom. + +## Upgradability + +Most contracts in Solady are compatible with both upgradeable and non-upgradeable (i.e. regular) contracts. + +Please call any required internal initialization methods accordingly. + +## EVM Compatibility + +Some parts of Solady may not be compatible with chains with partial EVM equivalence. + +Please always check and test for compatibility accordingly. \ No newline at end of file diff --git a/docs/sidebar.md b/docs/sidebar.md new file mode 100644 index 000000000..a3872d3e7 --- /dev/null +++ b/docs/sidebar.md @@ -0,0 +1,84 @@ +- [Overview](/) + +- accounts + - [ERC1271](accounts/erc1271.md) + - [ERC4337](accounts/erc4337.md) + - [ERC4337Factory](accounts/erc4337factory.md) + - [ERC6551](accounts/erc6551.md) + - [ERC7821](accounts/erc7821.md) + - [LibERC6551](accounts/liberc6551.md) + - [LibERC7579](accounts/liberc7579.md) + - [Receiver](accounts/receiver.md) + - [Timelock](accounts/timelock.md) +- auth + - [EnumerableRoles](auth/enumerableroles.md) + - [Ownable](auth/ownable.md) + - [OwnableRoles](auth/ownableroles.md) + - [TimedRoles](auth/timedroles.md) +- tokens + - [ERC1155](tokens/erc1155.md) + - [ERC20](tokens/erc20.md) + - [ERC20Votes](tokens/erc20votes.md) + - [ERC2981](tokens/erc2981.md) + - [ERC4626](tokens/erc4626.md) + - [ERC6909](tokens/erc6909.md) + - [ERC721](tokens/erc721.md) + - [WETH](tokens/weth.md) +- utils + - [CREATE3](utils/create3.md) + - [DateTimeLib](utils/datetimelib.md) + - [DeploylessPredeployQueryer](utils/deploylesspredeployqueryer.md) + - [DynamicArrayLib](utils/dynamicarraylib.md) + - [DynamicBufferLib](utils/dynamicbufferlib.md) + - [ECDSA](utils/ecdsa.md) + - [EIP712](utils/eip712.md) + - [ERC1967Factory](utils/erc1967factory.md) + - [EfficientHashLib](utils/efficienthashlib.md) + - [EnumerableMapLib](utils/enumerablemaplib.md) + - [EnumerableSetLib](utils/enumerablesetlib.md) + - [FixedPointMathLib](utils/fixedpointmathlib.md) + - [Initializable](utils/initializable.md) + - [JSONParserLib](utils/jsonparserlib.md) + - [LibBit](utils/libbit.md) + - [LibBitmap](utils/libbitmap.md) + - [LibBytes](utils/libbytes.md) + - [LibCall](utils/libcall.md) + - [LibClone](utils/libclone.md) + - [LibMap](utils/libmap.md) + - [LibPRNG](utils/libprng.md) + - [LibRLP](utils/librlp.md) + - [LibSort](utils/libsort.md) + - [LibString](utils/libstring.md) + - [LibTransient](utils/libtransient.md) + - [LibZip](utils/libzip.md) + - [Lifebuoy](utils/lifebuoy.md) + - [MerkleProofLib](utils/merkleprooflib.md) + - [MetadataReaderLib](utils/metadatareaderlib.md) + - [MinHeapLib](utils/minheaplib.md) + - [P256](utils/p256.md) + - [RedBlackTreeLib](utils/redblacktreelib.md) + - [ReentrancyGuard](utils/reentrancyguard.md) + - [ReentrancyGuardTransient](utils/reentrancyguardtransient.md) + - [SSTORE2](utils/sstore2.md) + - [SafeTransferLib](utils/safetransferlib.md) + - [SignatureCheckerLib](utils/signaturecheckerlib.md) + - [UUPSUpgradeable](utils/uupsupgradeable.md) + - [UpgradeableBeacon](utils/upgradeablebeacon.md) + - [WebAuthn](utils/webauthn.md) + +- **Theme** +
+
+
+
light
+
+
+
auto
+
+
+
dark
+
+- **Links** + - [
Github
](https://github.com/Vectorized/solady) + - [
X
](https://x.com/optimizoor) + diff --git a/docs/tokens/erc1155.md b/docs/tokens/erc1155.md new file mode 100644 index 000000000..b125ec516 --- /dev/null +++ b/docs/tokens/erc1155.md @@ -0,0 +1,434 @@ +# ERC1155 + +Simple ERC1155 implementation. + + +Note: + +- The ERC1155 standard allows for self-approvals. +For performance, this implementation WILL NOT revert for such actions. +Please add any checks with overrides if desired. +- The transfer functions use the identity precompile (0x4) +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). +- 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. + + + + + +## Custom Errors + +### ArrayLengthsMismatch() + +```solidity +error ArrayLengthsMismatch() +``` + +The lengths of the input arrays are not the same. + +### TransferToZeroAddress() + +```solidity +error TransferToZeroAddress() +``` + +Cannot mint or transfer to the zero address. + +### AccountBalanceOverflow() + +```solidity +error AccountBalanceOverflow() +``` + +The recipient's balance has overflowed. + +### InsufficientBalance() + +```solidity +error InsufficientBalance() +``` + +Insufficient balance. + +### NotOwnerNorApproved() + +```solidity +error NotOwnerNorApproved() +``` + +Only the token owner or an approved account can manage the tokens. + +### TransferToNonERC1155ReceiverImplementer() + +```solidity +error TransferToNonERC1155ReceiverImplementer() +``` + +Cannot safely transfer to a contract that does not implement +the ERC1155Receiver interface. + +## ERC1155 Metadata + +### uri(uint256) + +```solidity +function uri(uint256 id) public view virtual returns (string memory); +``` + +Returns the URI for token `id`. +You can either return the same templated URI for all token IDs, +(e.g. "https://example.com/api/{id}.json"), +or return a unique URI for each `id`. +See: https://eips.ethereum.org/EIPS/eip-1155#metadata + +## ERC1155 + +### balanceOf(address,uint256) + +```solidity +function balanceOf(address owner, uint256 id) + public + view + virtual + returns (uint256 result) +``` + +Returns the amount of `id` owned by `owner`. + +### isApprovedForAll(address,address) + +```solidity +function isApprovedForAll(address owner, address operator) + public + view + virtual + returns (bool result) +``` + +Returns whether `operator` is approved to manage the tokens of `owner`. + +### setApprovalForAll(address,bool) + +```solidity +function setApprovalForAll(address operator, bool isApproved) + public + virtual +``` + +Sets whether `operator` is approved to manage the tokens of the caller. +Emits a {ApprovalForAll} event. + +### safeTransferFrom(address,address,uint256,uint256,bytes) + +```solidity +function safeTransferFrom( + address from, + address to, + uint256 id, + uint256 amount, + bytes calldata data +) public virtual +``` + +Transfers `amount` of `id` from `from` to `to`. +Requirements: +- `to` cannot be the zero address. +- `from` must have at least `amount` of `id`. +- If the caller is not `from`, + it must be approved to manage the tokens of `from`. +- If `to` refers to a smart contract, it must implement + {ERC1155-onERC1155Received}, which is called upon a batch transfer. +Emits a {TransferSingle} event. + +### safeBatchTransferFrom(address,address,uint256[],uint256[],bytes) + +```solidity +function safeBatchTransferFrom( + address from, + address to, + uint256[] calldata ids, + uint256[] calldata amounts, + bytes calldata data +) public virtual +``` + +Transfers `amounts` of `ids` from `from` to `to`. +Requirements: +- `to` cannot be the zero address. +- `from` must have at least `amount` of `id`. +- `ids` and `amounts` must have the same length. +- If the caller is not `from`, + it must be approved to manage the tokens of `from`. +- If `to` refers to a smart contract, it must implement + {ERC1155-onERC1155BatchReceived}, which is called upon a batch transfer. +Emits a {TransferBatch} event. + +### balanceOfBatch(address[],uint256[]) + +```solidity +function balanceOfBatch(address[] calldata owners, uint256[] calldata ids) + public + view + virtual + returns (uint256[] memory balances) +``` + +Returns the amounts of `ids` for `owners. +Requirements: +- `owners` and `ids` must have the same length. + +### supportsInterface(bytes4) + +```solidity +function supportsInterface(bytes4 interfaceId) + public + view + virtual + returns (bool result) +``` + +Returns true if this contract implements the interface defined by `interfaceId`. +See: https://eips.ethereum.org/EIPS/eip-165 +This function call must use less than 30000 gas. + +## Internal Mint Functions + +### _mint(address,uint256,uint256,bytes) + +```solidity +function _mint(address to, uint256 id, uint256 amount, bytes memory data) + internal + virtual +``` + +Mints `amount` of `id` to `to`. +Requirements: +- `to` cannot be the zero address. +- If `to` refers to a smart contract, it must implement + {ERC1155-onERC1155Received}, which is called upon a batch transfer. +Emits a {TransferSingle} event. + +### _batchMint(address,uint256[],uint256[],bytes) + +```solidity +function _batchMint( + address to, + uint256[] memory ids, + uint256[] memory amounts, + bytes memory data +) internal virtual +``` + +Mints `amounts` of `ids` to `to`. +Requirements: +- `to` cannot be the zero address. +- `ids` and `amounts` must have the same length. +- If `to` refers to a smart contract, it must implement + {ERC1155-onERC1155BatchReceived}, which is called upon a batch transfer. +Emits a {TransferBatch} event. + +## Internal Burn Functions + +### _burn(address,uint256,uint256) + +```solidity +function _burn(address from, uint256 id, uint256 amount) internal virtual +``` + +Equivalent to `_burn(address(0), from, id, amount)`. + +### _burn(address,address,uint256,uint256) + +```solidity +function _burn(address by, address from, uint256 id, uint256 amount) + internal + virtual +``` + +Destroys `amount` of `id` from `from`. +Requirements: +- `from` must have at least `amount` of `id`. +- If `by` is not the zero address, it must be either `from`, + or approved to manage the tokens of `from`. +Emits a {TransferSingle} event. + +### _batchBurn(address,uint256[],uint256[]) + +```solidity +function _batchBurn( + address from, + uint256[] memory ids, + uint256[] memory amounts +) internal virtual +``` + +Equivalent to `_batchBurn(address(0), from, ids, amounts)`. + +### _batchBurn(address,address,uint256[],uint256[]) + +```solidity +function _batchBurn( + address by, + address from, + uint256[] memory ids, + uint256[] memory amounts +) internal virtual +``` + +Destroys `amounts` of `ids` from `from`. +Requirements: +- `ids` and `amounts` must have the same length. +- `from` must have at least `amounts` of `ids`. +- If `by` is not the zero address, it must be either `from`, + or approved to manage the tokens of `from`. +Emits a {TransferBatch} event. + +## Internal Approval Functions + +### _setApprovalForAll(address,address,bool) + +```solidity +function _setApprovalForAll(address by, address operator, bool isApproved) + internal + virtual +``` + +Approve or remove the `operator` as an operator for `by`, +without authorization checks. +Emits a {ApprovalForAll} event. + +## Internal Transfer Functions + +### _safeTransfer(address,address,uint256,uint256,bytes) + +```solidity +function _safeTransfer( + address from, + address to, + uint256 id, + uint256 amount, + bytes memory data +) internal virtual +``` + +Equivalent to `_safeTransfer(address(0), from, to, id, amount, data)`. + +### _safeTransfer(address,address,address,uint256,uint256,bytes) + +```solidity +function _safeTransfer( + address by, + address from, + address to, + uint256 id, + uint256 amount, + bytes memory data +) internal virtual +``` + +Transfers `amount` of `id` from `from` to `to`. +Requirements: +- `to` cannot be the zero address. +- `from` must have at least `amount` of `id`. +- If `by` is not the zero address, it must be either `from`, + or approved to manage the tokens of `from`. +- If `to` refers to a smart contract, it must implement + {ERC1155-onERC1155Received}, which is called upon a batch transfer. +Emits a {TransferSingle} event. + +### _safeBatchTransfer(address,address,uint256[],uint256[],bytes) + +```solidity +function _safeBatchTransfer( + address from, + address to, + uint256[] memory ids, + uint256[] memory amounts, + bytes memory data +) internal virtual +``` + +Equivalent to `_safeBatchTransfer(address(0), from, to, ids, amounts, data)`. + +### _safeBatchTransfer(address,address,address,uint256[],uint256[],bytes) + +```solidity +function _safeBatchTransfer( + address by, + address from, + address to, + uint256[] memory ids, + uint256[] memory amounts, + bytes memory data +) internal virtual +``` + +Transfers `amounts` of `ids` from `from` to `to`. +Requirements: +- `to` cannot be the zero address. +- `ids` and `amounts` must have the same length. +- `from` must have at least `amounts` of `ids`. +- If `by` is not the zero address, it must be either `from`, + or approved to manage the tokens of `from`. +- If `to` refers to a smart contract, it must implement + {ERC1155-onERC1155BatchReceived}, which is called upon a batch transfer. +Emits a {TransferBatch} event. + +## Hooks For Overriding + +### _useBeforeTokenTransfer() + +```solidity +function _useBeforeTokenTransfer() internal view virtual returns (bool) +``` + +Override this function to return true if `_beforeTokenTransfer` is used. +This is to help the compiler avoid producing dead bytecode. + +### _beforeTokenTransfer(address,address,uint256[],uint256[],bytes) + +```solidity +function _beforeTokenTransfer( + address from, + address to, + uint256[] memory ids, + uint256[] memory amounts, + bytes memory data +) internal virtual +``` + +Hook that is called before any token transfer. +This includes minting and burning, as well as batched variants. +The same hook is called on both single and batched variants. +For single transfers, the length of the `id` and `amount` arrays are 1. + +### _useAfterTokenTransfer() + +```solidity +function _useAfterTokenTransfer() internal view virtual returns (bool) +``` + +Override this function to return true if `_afterTokenTransfer` is used. +This is to help the compiler avoid producing dead bytecode. + +### _afterTokenTransfer(address,address,uint256[],uint256[],bytes) + +```solidity +function _afterTokenTransfer( + address from, + address to, + uint256[] memory ids, + uint256[] memory amounts, + bytes memory data +) internal virtual +``` + +Hook that is called after any token transfer. +This includes minting and burning, as well as batched variants. +The same hook is called on both single and batched variants. +For single transfers, the length of the `id` and `amount` arrays are 1. \ No newline at end of file diff --git a/docs/tokens/erc20.md b/docs/tokens/erc20.md new file mode 100644 index 000000000..44a446dc9 --- /dev/null +++ b/docs/tokens/erc20.md @@ -0,0 +1,347 @@ +# ERC20 + +Simple ERC20 + EIP-2612 implementation. + + +Note: + +- The ERC20 standard allows minting and transferring to and from the zero address, +minting and transferring zero tokens, as well as self-approvals. +For performance, this implementation WILL NOT revert for such actions. +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: +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. + + + + + +## Custom Errors + +### TotalSupplyOverflow() + +```solidity +error TotalSupplyOverflow() +``` + +The total supply has overflowed. + +### AllowanceOverflow() + +```solidity +error AllowanceOverflow() +``` + +The allowance has overflowed. + +### AllowanceUnderflow() + +```solidity +error AllowanceUnderflow() +``` + +The allowance has underflowed. + +### InsufficientBalance() + +```solidity +error InsufficientBalance() +``` + +Insufficient balance. + +### InsufficientAllowance() + +```solidity +error InsufficientAllowance() +``` + +Insufficient allowance. + +### InvalidPermit() + +```solidity +error InvalidPermit() +``` + +The permit is invalid. + +### PermitExpired() + +```solidity +error PermitExpired() +``` + +The permit has expired. + +### Permit2AllowanceIsFixedAtInfinity() + +```solidity +error Permit2AllowanceIsFixedAtInfinity() +``` + +The allowance of Permit2 is fixed at infinity. + +## Constants + +### _PERMIT2 + +```solidity +address internal constant _PERMIT2 = + 0x000000000022D473030F116dDEE9F6B43aC78BA3 +``` + +The canonical Permit2 address. +For signature-based allowance granting for single transaction ERC20 `transferFrom`. +To enable, override `_givePermit2InfiniteAllowance()`. +[Github](https://github.com/Uniswap/permit2) +[Etherscan](https://etherscan.io/address/0x000000000022D473030F116dDEE9F6B43aC78BA3) + +## ERC20 + +### totalSupply() + +```solidity +function totalSupply() public view virtual returns (uint256 result) +``` + +Returns the amount of tokens in existence. + +### balanceOf(address) + +```solidity +function balanceOf(address owner) + public + view + virtual + returns (uint256 result) +``` + +Returns the amount of tokens owned by `owner`. + +### allowance(address,address) + +```solidity +function allowance(address owner, address spender) + public + view + virtual + returns (uint256 result) +``` + +Returns the amount of tokens that `spender` can spend on behalf of `owner`. + +### approve(address,uint256) + +```solidity +function approve(address spender, uint256 amount) + public + virtual + returns (bool) +``` + +Sets `amount` as the allowance of `spender` over the caller's tokens. +Emits a {Approval} event. + +### transfer(address,uint256) + +```solidity +function transfer(address to, uint256 amount) + public + virtual + returns (bool) +``` + +Transfer `amount` tokens from the caller to `to`. +Requirements: +- `from` must at least have `amount`. +Emits a {Transfer} event. + +### transferFrom(address,address,uint256) + +```solidity +function transferFrom(address from, address to, uint256 amount) + public + virtual + returns (bool) +``` + +Transfers `amount` tokens from `from` to `to`. +Note: Does not update the allowance if it is the maximum uint256 value. +Requirements: +- `from` must at least have `amount`. +- The caller must have at least `amount` of allowance to transfer the tokens of `from`. +Emits a {Transfer} event. + +## EIP-2612 + +### _constantNameHash() + +```solidity +function _constantNameHash() + internal + view + virtual + returns (bytes32 result) +``` + +For more performance, override to return the constant value +of `keccak256(bytes(name()))` if `name()` will never change. + +### _versionHash() + +```solidity +function _versionHash() internal view virtual returns (bytes32 result) +``` + +If you need a different value, override this function. + +### _incrementNonce(address) + +```solidity +function _incrementNonce(address owner) internal virtual +``` + +For inheriting contracts to increment the nonce. + +### nonces(address) + +```solidity +function nonces(address owner) + public + view + virtual + returns (uint256 result) +``` + +Returns the current nonce for `owner`. +This value is used to compute the signature for EIP-2612 permit. + +### permit(address,address,uint256,uint256,uint8,bytes32,bytes32) + +```solidity +function permit( + address owner, + address spender, + uint256 value, + uint256 deadline, + uint8 v, + bytes32 r, + bytes32 s +) public virtual +``` + +Sets `value` as the allowance of `spender` over the tokens of `owner`, +authorized by a signed approval by `owner`. +Emits a {Approval} event. + +### DOMAIN_SEPARATOR() + +```solidity +function DOMAIN_SEPARATOR() public view virtual returns (bytes32 result) +``` + +Returns the EIP-712 domain separator for the EIP-2612 permit. + +## Internal Mint Functions + +### _mint(address,uint256) + +```solidity +function _mint(address to, uint256 amount) internal virtual +``` + +Mints `amount` tokens to `to`, increasing the total supply. +Emits a {Transfer} event. + +## Internal Burn Functions + +### _burn(address,uint256) + +```solidity +function _burn(address from, uint256 amount) internal virtual +``` + +Burns `amount` tokens from `from`, reducing the total supply. +Emits a {Transfer} event. + +## Internal Transfer Functions + +### _transfer(address,address,uint256) + +```solidity +function _transfer(address from, address to, uint256 amount) + internal + virtual +``` + +Moves `amount` of tokens from `from` to `to`. + +## Internal Allowance Functions + +### _spendAllowance(address,address,uint256) + +```solidity +function _spendAllowance(address owner, address spender, uint256 amount) + internal + virtual +``` + +Updates the allowance of `owner` for `spender` based on spent `amount`. + +### _approve(address,address,uint256) + +```solidity +function _approve(address owner, address spender, uint256 amount) + internal + virtual +``` + +Sets `amount` as the allowance of `spender` over the tokens of `owner`. +Emits a {Approval} event. + +## Hooks To Override + +### _beforeTokenTransfer(address,address,uint256) + +```solidity +function _beforeTokenTransfer(address from, address to, uint256 amount) + internal + virtual +``` + +Hook that is called before any transfer of tokens. +This includes minting and burning. + +### _afterTokenTransfer(address,address,uint256) + +```solidity +function _afterTokenTransfer(address from, address to, uint256 amount) + internal + virtual +``` + +Hook that is called after any transfer of tokens. +This includes minting and burning. + +## Permit2 + +### _givePermit2InfiniteAllowance() + +```solidity +function _givePermit2InfiniteAllowance() + internal + view + virtual + returns (bool) +``` + +Returns whether to fix the Permit2 contract's allowance at infinity. +This value should be kept constant after contract initialization, +or else the actual allowance values may not match with the {Approval} events. +For best performance, return a compile-time constant for zero-cost abstraction. \ No newline at end of file diff --git a/docs/tokens/erc20votes.md b/docs/tokens/erc20votes.md new file mode 100644 index 000000000..f7c1d4eb2 --- /dev/null +++ b/docs/tokens/erc20votes.md @@ -0,0 +1,240 @@ +# ERC20Votes + +ERC20 with votes based on ERC5805 and ERC6372. + + + + +Inherits: + +- `tokens/ERC20.sol` + + + + +## Custom Errors + +### ERC5805FutureLookup() + +```solidity +error ERC5805FutureLookup() +``` + +The timepoint is in the future. + +### ERC5805DelegateSignatureExpired() + +```solidity +error ERC5805DelegateSignatureExpired() +``` + +The ERC5805 signature to set a delegate has expired. + +### ERC5805DelegateInvalidSignature() + +```solidity +error ERC5805DelegateInvalidSignature() +``` + +The ERC5805 signature to set a delegate is invalid. + +### ERC5805CheckpointIndexOutOfBounds() + +```solidity +error ERC5805CheckpointIndexOutOfBounds() +``` + +Out-of-bounds access for the checkpoints. + +### ERC5805CheckpointValueOverflow() + +```solidity +error ERC5805CheckpointValueOverflow() +``` + +Arithmetic overflow when pushing a new checkpoint. + +### ERC5805CheckpointValueUnderflow() + +```solidity +error ERC5805CheckpointValueUnderflow() +``` + +Arithmetic underflow when pushing a new checkpoint. + +## ERC6372 + +### CLOCK_MODE() + +```solidity +function CLOCK_MODE() public view virtual returns (string memory) +``` + +Returns the clock mode. + +### clock() + +```solidity +function clock() public view returns (uint48 result) +``` + +Retusn the current clock. + +## ERC5805 + +### getVotes(address) + +```solidity +function getVotes(address account) public view virtual returns (uint256) +``` + +Returns the latest amount of voting units for `account`. + +### getPastVotes(address,uint256) + +```solidity +function getPastVotes(address account, uint256 timepoint) + public + view + virtual + returns (uint256) +``` + +Returns the latest amount of voting units `account` has before `timepoint`. + +### delegates(address) + +```solidity +function delegates(address delegator) + public + view + virtual + returns (address result) +``` + +Returns the current voting delegate of `delegator`. + +### delegate(address) + +```solidity +function delegate(address delegatee) public virtual +``` + +Set the voting delegate of the caller to `delegatee`. + +### delegateBySig(address,uint256,uint256,uint8,bytes32,bytes32) + +```solidity +function delegateBySig( + address delegatee, + uint256 nonce, + uint256 expiry, + uint8 v, + bytes32 r, + bytes32 s +) public virtual +``` + +Sets the voting delegate of the signature signer to `delegatee`. + +## Other Vote Public View Functions + +### checkpointCount(address) + +```solidity +function checkpointCount(address account) + public + view + virtual + returns (uint256 result) +``` + +Returns the number of checkpoints for `account`. + +### checkpointAt(address,uint256) + +```solidity +function checkpointAt(address account, uint256 i) + public + view + virtual + returns (uint48 checkpointClock, uint256 checkpointValue) +``` + +Returns the voting checkpoint for `account` at index `i`. + +### getVotesTotalSupply() + +```solidity +function getVotesTotalSupply() public view virtual returns (uint256) +``` + +Returns the latest amount of total voting units. + +### getPastVotesTotalSupply(uint256) + +```solidity +function getPastVotesTotalSupply(uint256 timepoint) + public + view + virtual + returns (uint256) +``` + +Returns the latest amount of total voting units before `timepoint`. + +## Internal Functions + +### _getVotingUnits(address) + +```solidity +function _getVotingUnits(address delegator) + internal + view + virtual + returns (uint256) +``` + +Returns the amount of voting units `delegator` has control over. +Override if you need a different formula. + +### _afterTokenTransfer(address,address,uint256) + +```solidity +function _afterTokenTransfer(address from, address to, uint256 amount) + internal + virtual + override +``` + +ERC20 after token transfer internal hook. + +### _transferVotingUnits(address,address,uint256) + +```solidity +function _transferVotingUnits(address from, address to, uint256 amount) + internal + virtual +``` + +Used in `_afterTokenTransfer(address from, address to, uint256 amount)`. + +### _moveDelegateVotes(address,address,uint256) + +```solidity +function _moveDelegateVotes(address from, address to, uint256 amount) + internal + virtual +``` + +Transfer `amount` of delegated votes from `from` to `to`. +Emits a {DelegateVotesChanged} event for each change of delegated votes. + +### _delegate(address,address) + +```solidity +function _delegate(address account, address delegatee) internal virtual +``` + +Delegates all of `account`'s voting units to `delegatee`. +Emits the {DelegateChanged} and {DelegateVotesChanged} events. \ No newline at end of file diff --git a/docs/tokens/erc2981.md b/docs/tokens/erc2981.md new file mode 100644 index 000000000..8195db836 --- /dev/null +++ b/docs/tokens/erc2981.md @@ -0,0 +1,110 @@ +# ERC2981 + +Simple ERC2981 NFT Royalty Standard implementation. + + + + + + + + +## Custom Errors + +### RoyaltyOverflow() + +```solidity +error RoyaltyOverflow() +``` + +The royalty fee numerator exceeds the fee denominator. + +### RoyaltyReceiverIsZeroAddress() + +```solidity +error RoyaltyReceiverIsZeroAddress() +``` + +The royalty receiver cannot be the zero address. + +## ERC2981 + +### _feeDenominator() + +```solidity +function _feeDenominator() internal pure virtual returns (uint96) +``` + +Returns the denominator for the royalty amount. +Defaults to 10000, which represents fees in basis points. +Override this function to return a custom amount if needed. + +### supportsInterface(bytes4) + +```solidity +function supportsInterface(bytes4 interfaceId) + public + view + virtual + returns (bool result) +``` + +Returns true if this contract implements the interface defined by `interfaceId`. +See: https://eips.ethereum.org/EIPS/eip-165 +This function call must use less than 30000 gas. + +### royaltyInfo(uint256,uint256) + +```solidity +function royaltyInfo(uint256 tokenId, uint256 salePrice) + public + view + virtual + returns (address receiver, uint256 royaltyAmount) +``` + +Returns the `receiver` and `royaltyAmount` for `tokenId` sold at `salePrice`. + +### _setDefaultRoyalty(address,uint96) + +```solidity +function _setDefaultRoyalty(address receiver, uint96 feeNumerator) + internal + virtual +``` + +Sets the default royalty `receiver` and `feeNumerator`. +Requirements: +- `receiver` must not be the zero address. +- `feeNumerator` must not be greater than the fee denominator. + +### _deleteDefaultRoyalty() + +```solidity +function _deleteDefaultRoyalty() internal virtual +``` + +Sets the default royalty `receiver` and `feeNumerator` to zero. + +### _setTokenRoyalty(uint256,address,uint96) + +```solidity +function _setTokenRoyalty( + uint256 tokenId, + address receiver, + uint96 feeNumerator +) internal virtual +``` + +Sets the royalty `receiver` and `feeNumerator` for `tokenId`. +Requirements: +- `receiver` must not be the zero address. +- `feeNumerator` must not be greater than the fee denominator. + +### _resetTokenRoyalty(uint256) + +```solidity +function _resetTokenRoyalty(uint256 tokenId) internal virtual +``` + +Sets the royalty `receiver` and `feeNumerator` for `tokenId` to zero. \ No newline at end of file diff --git a/docs/tokens/erc4626.md b/docs/tokens/erc4626.md new file mode 100644 index 000000000..a1238ea15 --- /dev/null +++ b/docs/tokens/erc4626.md @@ -0,0 +1,482 @@ +# ERC4626 + +Simple ERC4626 tokenized Vault implementation. + + + + +Inherits: + +- `tokens/ERC20.sol` + + + + +## Constants + +### _DEFAULT_UNDERLYING_DECIMALS + +```solidity +uint8 internal constant _DEFAULT_UNDERLYING_DECIMALS = 18 +``` + +The default underlying decimals. + +### _DEFAULT_DECIMALS_OFFSET + +```solidity +uint8 internal constant _DEFAULT_DECIMALS_OFFSET = 0 +``` + +The default decimals offset. + +## Custom Errors + +### DepositMoreThanMax() + +```solidity +error DepositMoreThanMax() +``` + +Cannot deposit more than the max limit. + +### MintMoreThanMax() + +```solidity +error MintMoreThanMax() +``` + +Cannot mint more than the max limit. + +### WithdrawMoreThanMax() + +```solidity +error WithdrawMoreThanMax() +``` + +Cannot withdraw more than the max limit. + +### RedeemMoreThanMax() + +```solidity +error RedeemMoreThanMax() +``` + +Cannot redeem more than the max limit. + +## ERC4626 Constants + +### _decimalsOffset() + +```solidity +function _decimalsOffset() internal view virtual returns (uint8) +``` + +Override to return a non-zero value to make the inflation attack even more unfeasible. +Only used when {_useVirtualShares} returns true. +Default: 0. +- MUST NOT revert. + +### _useVirtualShares() + +```solidity +function _useVirtualShares() internal view virtual returns (bool) +``` + +Returns whether virtual shares will be used to mitigate the inflation attack. +See: https://github.com/OpenZeppelin/openzeppelin-contracts/issues/3706 +Override to return true or false. +Default: true. +- MUST NOT revert. + +### decimals() + +```solidity +function decimals() public view virtual override(ERC20) returns (uint8) +``` + +Returns the decimals places of the token. +- MUST NOT revert. + +## Asset Decimals Getter Helper + +### _tryGetAssetDecimals(address) + +```solidity +function _tryGetAssetDecimals(address underlying) + internal + view + returns (bool success, uint8 result) +``` + +Helper function to get the decimals of the underlying asset. +Useful for setting the return value of `_underlyingDecimals` during initialization. +If the retrieval succeeds, `success` will be true, and `result` will hold the result. +Otherwise, `success` will be false, and `result` will be zero. +Example usage: +```solidity +(bool success, uint8 result) = _tryGetAssetDecimals(underlying); +_decimals = success ? result : _DEFAULT_UNDERLYING_DECIMALS; +``` + +## Accounting Logic + +### totalAssets() + +```solidity +function totalAssets() public view virtual returns (uint256 assets) +``` + +Returns the total amount of the underlying asset managed by the Vault. +- SHOULD include any compounding that occurs from the yield. +- MUST be inclusive of any fees that are charged against assets in the Vault. +- MUST NOT revert. + +### convertToShares(uint256) + +```solidity +function convertToShares(uint256 assets) + public + view + virtual + returns (uint256 shares) +``` + +Returns the amount of shares that the Vault will exchange for the amount of +assets provided, in an ideal scenario where all conditions are met. +- MUST NOT be inclusive of any fees that are charged against assets in the Vault. +- MUST NOT show any variations depending on the caller. +- MUST NOT reflect slippage or other on-chain conditions, during the actual exchange. +- MUST NOT revert. +Note: This calculation MAY NOT reflect the "per-user" price-per-share, and instead +should reflect the "average-user's" price-per-share, i.e. what the average user should +expect to see when exchanging to and from. + +### convertToAssets(uint256) + +```solidity +function convertToAssets(uint256 shares) + public + view + virtual + returns (uint256 assets) +``` + +Returns the amount of assets that the Vault will exchange for the amount of +shares provided, in an ideal scenario where all conditions are met. +- MUST NOT be inclusive of any fees that are charged against assets in the Vault. +- MUST NOT show any variations depending on the caller. +- MUST NOT reflect slippage or other on-chain conditions, during the actual exchange. +- MUST NOT revert. +Note: This calculation MAY NOT reflect the "per-user" price-per-share, and instead +should reflect the "average-user's" price-per-share, i.e. what the average user should +expect to see when exchanging to and from. + +### previewDeposit(uint256) + +```solidity +function previewDeposit(uint256 assets) + public + view + virtual + returns (uint256 shares) +``` + +Allows an on-chain or off-chain user to simulate the effects of their deposit +at the current block, given current on-chain conditions. +- MUST return as close to and no more than the exact amount of Vault shares that + will be minted in a deposit call in the same transaction, i.e. deposit should + return the same or more shares as `previewDeposit` if call in the same transaction. +- MUST NOT account for deposit limits like those returned from `maxDeposit` and should + always act as if the deposit will be accepted, regardless of approvals, etc. +- MUST be inclusive of deposit fees. Integrators should be aware of this. +- MUST not revert. +Note: Any unfavorable discrepancy between `convertToShares` and `previewDeposit` SHOULD +be considered slippage in share price or some other type of condition, meaning +the depositor will lose assets by depositing. + +### previewMint(uint256) + +```solidity +function previewMint(uint256 shares) + public + view + virtual + returns (uint256 assets) +``` + +Allows an on-chain or off-chain user to simulate the effects of their mint +at the current block, given current on-chain conditions. +- MUST return as close to and no fewer than the exact amount of assets that + will be deposited in a mint call in the same transaction, i.e. mint should + return the same or fewer assets as `previewMint` if called in the same transaction. +- MUST NOT account for mint limits like those returned from `maxMint` and should + always act as if the mint will be accepted, regardless of approvals, etc. +- MUST be inclusive of deposit fees. Integrators should be aware of this. +- MUST not revert. +Note: Any unfavorable discrepancy between `convertToAssets` and `previewMint` SHOULD +be considered slippage in share price or some other type of condition, +meaning the depositor will lose assets by minting. + +### previewWithdraw(uint256) + +```solidity +function previewWithdraw(uint256 assets) + public + view + virtual + returns (uint256 shares) +``` + +Allows an on-chain or off-chain user to simulate the effects of their withdrawal +at the current block, given the current on-chain conditions. +- MUST return as close to and no fewer than the exact amount of Vault shares that + will be burned in a withdraw call in the same transaction, i.e. withdraw should + return the same or fewer shares as `previewWithdraw` if call in the same transaction. +- MUST NOT account for withdrawal limits like those returned from `maxWithdraw` and should + always act as if the withdrawal will be accepted, regardless of share balance, etc. +- MUST be inclusive of withdrawal fees. Integrators should be aware of this. +- MUST not revert. +Note: Any unfavorable discrepancy between `convertToShares` and `previewWithdraw` SHOULD +be considered slippage in share price or some other type of condition, +meaning the depositor will lose assets by depositing. + +### previewRedeem(uint256) + +```solidity +function previewRedeem(uint256 shares) + public + view + virtual + returns (uint256 assets) +``` + +Allows an on-chain or off-chain user to simulate the effects of their redemption +at the current block, given current on-chain conditions. +- MUST return as close to and no more than the exact amount of assets that + will be withdrawn in a redeem call in the same transaction, i.e. redeem should + return the same or more assets as `previewRedeem` if called in the same transaction. +- MUST NOT account for redemption limits like those returned from `maxRedeem` and should + always act as if the redemption will be accepted, regardless of approvals, etc. +- MUST be inclusive of withdrawal fees. Integrators should be aware of this. +- MUST NOT revert. +Note: Any unfavorable discrepancy between `convertToAssets` and `previewRedeem` SHOULD +be considered slippage in share price or some other type of condition, +meaning the depositor will lose assets by depositing. + +## Deposit / Withdrawal Limit Logic + +### maxDeposit(address) + +```solidity +function maxDeposit(address to) + public + view + virtual + returns (uint256 maxAssets) +``` + +Returns the maximum amount of the underlying asset that can be deposited +into the Vault for `to`, via a deposit call. +- MUST return a limited value if `to` is subject to some deposit limit. +- MUST return `2**256-1` if there is no maximum limit. +- MUST NOT revert. + +### maxMint(address) + +```solidity +function maxMint(address to) + public + view + virtual + returns (uint256 maxShares) +``` + +Returns the maximum amount of the Vault shares that can be minter for `to`, +via a mint call. +- MUST return a limited value if `to` is subject to some mint limit. +- MUST return `2**256-1` if there is no maximum limit. +- MUST NOT revert. + +### maxWithdraw(address) + +```solidity +function maxWithdraw(address owner) + public + view + virtual + returns (uint256 maxAssets) +``` + +Returns the maximum amount of the underlying asset that can be withdrawn +from the `owner`'s balance in the Vault, via a withdraw call. +- MUST return a limited value if `owner` is subject to some withdrawal limit or timelock. +- MUST NOT revert. + +### maxRedeem(address) + +```solidity +function maxRedeem(address owner) + public + view + virtual + returns (uint256 maxShares) +``` + +Returns the maximum amount of Vault shares that can be redeemed +from the `owner`'s balance in the Vault, via a redeem call. +- MUST return a limited value if `owner` is subject to some withdrawal limit or timelock. +- MUST return `balanceOf(owner)` otherwise. +- MUST NOT revert. + +## Deposit / Withdrawal Logic + +### deposit(uint256,address) + +```solidity +function deposit(uint256 assets, address to) + public + virtual + returns (uint256 shares) +``` + +Mints `shares` Vault shares to `to` by depositing exactly `assets` +of underlying tokens. +- MUST emit the {Deposit} event. +- MAY support an additional flow in which the underlying tokens are owned by the Vault + contract before the deposit execution, and are accounted for during deposit. +- MUST revert if all of `assets` cannot be deposited, such as due to deposit limit, + slippage, insufficient approval, etc. +Note: Most implementations will require pre-approval of the Vault with the +Vault's underlying `asset` token. + +### mint(uint256,address) + +```solidity +function mint(uint256 shares, address to) + public + virtual + returns (uint256 assets) +``` + +Mints exactly `shares` Vault shares to `to` by depositing `assets` +of underlying tokens. +- MUST emit the {Deposit} event. +- MAY support an additional flow in which the underlying tokens are owned by the Vault + contract before the mint execution, and are accounted for during mint. +- MUST revert if all of `shares` cannot be deposited, such as due to deposit limit, + slippage, insufficient approval, etc. +Note: Most implementations will require pre-approval of the Vault with the +Vault's underlying `asset` token. + +### withdraw(uint256,address,address) + +```solidity +function withdraw(uint256 assets, address to, address owner) + public + virtual + returns (uint256 shares) +``` + +Burns `shares` from `owner` and sends exactly `assets` of underlying tokens to `to`. +- MUST emit the {Withdraw} event. +- MAY support an additional flow in which the underlying tokens are owned by the Vault + contract before the withdraw execution, and are accounted for during withdraw. +- MUST revert if all of `assets` cannot be withdrawn, such as due to withdrawal limit, + slippage, insufficient balance, etc. +Note: Some implementations will require pre-requesting to the Vault before a withdrawal +may be performed. Those methods should be performed separately. + +### redeem(uint256,address,address) + +```solidity +function redeem(uint256 shares, address to, address owner) + public + virtual + returns (uint256 assets) +``` + +Burns exactly `shares` from `owner` and sends `assets` of underlying tokens to `to`. +- MUST emit the {Withdraw} event. +- MAY support an additional flow in which the underlying tokens are owned by the Vault + contract before the redeem execution, and are accounted for during redeem. +- MUST revert if all of shares cannot be redeemed, such as due to withdrawal limit, + slippage, insufficient balance, etc. +Note: Some implementations will require pre-requesting to the Vault before a redeem +may be performed. Those methods should be performed separately. + +## Internal Helpers + +### _deposit(address,address,uint256,uint256) + +```solidity +function _deposit(address by, address to, uint256 assets, uint256 shares) + internal + virtual +``` + +For deposits and mints. +Emits a {Deposit} event. + +### _withdraw(address,address,address,uint256,uint256) + +```solidity +function _withdraw( + address by, + address to, + address owner, + uint256 assets, + uint256 shares +) internal virtual +``` + +For withdrawals and redemptions. +Emits a {Withdraw} event. + +### _initialConvertToShares(uint256) + +```solidity +function _initialConvertToShares(uint256 assets) + internal + view + virtual + returns (uint256 shares) +``` + +Internal conversion function (from assets to shares) to apply when the Vault is empty. +Only used when {_useVirtualShares} returns false. +Note: Make sure to keep this function consistent with {_initialConvertToAssets} +when overriding it. + +### _initialConvertToAssets(uint256) + +```solidity +function _initialConvertToAssets(uint256 shares) + internal + view + virtual + returns (uint256 assets) +``` + +Internal conversion function (from shares to assets) to apply when the Vault is empty. +Only used when {_useVirtualShares} returns false. +Note: Make sure to keep this function consistent with {_initialConvertToShares} +when overriding it. + +## Hooks To Override + +### _beforeWithdraw(uint256,uint256) + +```solidity +function _beforeWithdraw(uint256 assets, uint256 shares) internal virtual +``` + +Hook that is called before any withdrawal or redemption. + +### _afterDeposit(uint256,uint256) + +```solidity +function _afterDeposit(uint256 assets, uint256 shares) internal virtual +``` + +Hook that is called after any deposit or mint. \ No newline at end of file diff --git a/docs/tokens/erc6909.md b/docs/tokens/erc6909.md new file mode 100644 index 000000000..95e64cb4e --- /dev/null +++ b/docs/tokens/erc6909.md @@ -0,0 +1,262 @@ +# ERC6909 + +Simple EIP-6909 implementation. + + +Note: + +The ERC6909 standard allows minting and transferring to and from the zero address, +minting and transferring zero tokens, as well as self-approvals. +For performance, this implementation WILL NOT revert for such actions. +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). +- 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. + + + + + +## Custom Errors + +### InsufficientBalance() + +```solidity +error InsufficientBalance() +``` + +Insufficient balance. + +### InsufficientPermission() + +```solidity +error InsufficientPermission() +``` + +Insufficient permission to perform the action. + +### BalanceOverflow() + +```solidity +error BalanceOverflow() +``` + +The balance has overflowed. + +## ERC6909 Metadata + +### tokenURI(uint256) + +```solidity +function tokenURI(uint256 id) public view virtual returns (string memory); +``` + +Returns the Uniform Resource Identifier (URI) for token `id`. + +## ERC6909 + +### balanceOf(address,uint256) + +```solidity +function balanceOf(address owner, uint256 id) + public + view + virtual + returns (uint256 amount) +``` + +Returns the amount of token `id` owned by `owner`. + +### allowance(address,address,uint256) + +```solidity +function allowance(address owner, address spender, uint256 id) + public + view + virtual + returns (uint256 amount) +``` + +Returns the amount of token `id` that `spender` can spend on behalf of `owner`. + +### isOperator(address,address) + +```solidity +function isOperator(address owner, address spender) + public + view + virtual + returns (bool status) +``` + +Checks if a `spender` is approved by `owner` to manage all of their tokens. + +### transfer(address,uint256,uint256) + +```solidity +function transfer(address to, uint256 id, uint256 amount) + public + payable + virtual + returns (bool) +``` + +Transfers `amount` of token `id` from the caller to `to`. +Requirements: +- caller must at least have `amount`. +Emits a {Transfer} event. + +### transferFrom(address,address,uint256,uint256) + +```solidity +function transferFrom(address from, address to, uint256 id, uint256 amount) + public + payable + virtual + returns (bool) +``` + +Transfers `amount` of token `id` from `from` to `to`. +Note: Does not update the allowance if it is the maximum uint256 value. +Requirements: +- `from` must at least have `amount` of token `id`. +- The caller must have at least `amount` of allowance to transfer the + tokens of `from` or approved as an operator. +Emits a {Transfer} event. + +### approve(address,uint256,uint256) + +```solidity +function approve(address spender, uint256 id, uint256 amount) + public + payable + virtual + returns (bool) +``` + +Sets `amount` as the allowance of `spender` for the caller for token `id`. +Emits a {Approval} event. + +### setOperator(address,bool) + +```solidity +function setOperator(address operator, bool approved) + public + payable + virtual + returns (bool) +``` + +Sets whether `operator` is approved to manage the tokens of the caller. +Emits {OperatorSet} event. + +### supportsInterface(bytes4) + +```solidity +function supportsInterface(bytes4 interfaceId) + public + view + virtual + returns (bool result) +``` + +Returns true if this contract implements the interface defined by `interfaceId`. + +## Internal Functions + +### _mint(address,uint256,uint256) + +```solidity +function _mint(address to, uint256 id, uint256 amount) internal virtual +``` + +Mints `amount` of token `id` to `to`. +Emits a {Transfer} event. + +### _burn(address,uint256,uint256) + +```solidity +function _burn(address from, uint256 id, uint256 amount) internal virtual +``` + +Burns `amount` token `id` from `from`. +Emits a {Transfer} event. + +### _transfer(address,address,address,uint256,uint256) + +```solidity +function _transfer( + address by, + address from, + address to, + uint256 id, + uint256 amount +) internal virtual +``` + +Transfers `amount` of token `id` from `from` to `to`. +Note: Does not update the allowance if it is the maximum uint256 value. +Requirements: +- `from` must at least have `amount` of token `id`. +- If `by` is not the zero address, + it must have at least `amount` of allowance to transfer the + tokens of `from` or approved as an operator. +Emits a {Transfer} event. + +### _approve(address,address,uint256,uint256) + +```solidity +function _approve( + address owner, + address spender, + uint256 id, + uint256 amount +) internal virtual +``` + +Sets `amount` as the allowance of `spender` for `owner` for token `id`. +Emits a {Approval} event. + +### _setOperator(address,address,bool) + +```solidity +function _setOperator(address owner, address operator, bool approved) + internal + virtual +``` + +Sets whether `operator` is approved to manage the tokens of `owner`. +Emits {OperatorSet} event. + +## Hooks To Override + +### _beforeTokenTransfer(address,address,uint256,uint256) + +```solidity +function _beforeTokenTransfer( + address from, + address to, + uint256 id, + uint256 amount +) internal virtual +``` + +Hook that is called before any transfer of tokens. +This includes minting and burning. + +### _afterTokenTransfer(address,address,uint256,uint256) + +```solidity +function _afterTokenTransfer( + address from, + address to, + uint256 id, + uint256 amount +) internal virtual +``` + +Hook that is called after any transfer of tokens. +This includes minting and burning. \ No newline at end of file diff --git a/docs/tokens/erc721.md b/docs/tokens/erc721.md new file mode 100644 index 000000000..c103ca99b --- /dev/null +++ b/docs/tokens/erc721.md @@ -0,0 +1,570 @@ +# ERC721 + +Simple ERC721 implementation with storage hitchhiking. + + +Note: + +- The ERC721 standard allows for self-approvals. +For performance, this implementation WILL NOT revert for such actions. +Please add any checks with overrides if desired. +- For performance, methods are made payable where permitted by the ERC721 standard. +- The `safeTransfer` functions use the identity precompile (0x4) +to copy memory internally. + +If you are overriding: +- 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). +- 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. + + + + + +## Constants + +### _MAX_ACCOUNT_BALANCE + +```solidity +uint256 internal constant _MAX_ACCOUNT_BALANCE = 0xffffffff +``` + +An account can hold up to 4294967295 tokens. + +## Custom Errors + +### NotOwnerNorApproved() + +```solidity +error NotOwnerNorApproved() +``` + +Only the token owner or an approved account can manage the token. + +### TokenDoesNotExist() + +```solidity +error TokenDoesNotExist() +``` + +The token does not exist. + +### TokenAlreadyExists() + +```solidity +error TokenAlreadyExists() +``` + +The token already exists. + +### BalanceQueryForZeroAddress() + +```solidity +error BalanceQueryForZeroAddress() +``` + +Cannot query the balance for the zero address. + +### TransferToZeroAddress() + +```solidity +error TransferToZeroAddress() +``` + +Cannot mint or transfer to the zero address. + +### TransferFromIncorrectOwner() + +```solidity +error TransferFromIncorrectOwner() +``` + +The token must be owned by `from`. + +### AccountBalanceOverflow() + +```solidity +error AccountBalanceOverflow() +``` + +The recipient's balance has overflowed. + +### TransferToNonERC721ReceiverImplementer() + +```solidity +error TransferToNonERC721ReceiverImplementer() +``` + +Cannot safely transfer to a contract that does not implement +the ERC721Receiver interface. + +## ERC721 + +### ownerOf(uint256) + +```solidity +function ownerOf(uint256 id) public view virtual returns (address result) +``` + +Returns the owner of token `id`. +Requirements: +- Token `id` must exist. + +### balanceOf(address) + +```solidity +function balanceOf(address owner) + public + view + virtual + returns (uint256 result) +``` + +Returns the number of tokens owned by `owner`. +Requirements: +- `owner` must not be the zero address. + +### getApproved(uint256) + +```solidity +function getApproved(uint256 id) + public + view + virtual + returns (address result) +``` + +Returns the account approved to manage token `id`. +Requirements: +- Token `id` must exist. + +### approve(address,uint256) + +```solidity +function approve(address account, uint256 id) public payable virtual +``` + +Sets `account` as the approved account to manage token `id`. +Requirements: +- Token `id` must exist. +- The caller must be the owner of the token, + or an approved operator for the token owner. +Emits an {Approval} event. + +### isApprovedForAll(address,address) + +```solidity +function isApprovedForAll(address owner, address operator) + public + view + virtual + returns (bool result) +``` + +Returns whether `operator` is approved to manage the tokens of `owner`. + +### setApprovalForAll(address,bool) + +```solidity +function setApprovalForAll(address operator, bool isApproved) + public + virtual +``` + +Sets whether `operator` is approved to manage the tokens of the caller. +Emits an {ApprovalForAll} event. + +### transferFrom(address,address,uint256) + +```solidity +function transferFrom(address from, address to, uint256 id) + public + payable + virtual +``` + +Transfers token `id` from `from` to `to`. +Requirements: +- Token `id` must exist. +- `from` must be the owner of the token. +- `to` cannot be the zero address. +- The caller must be the owner of the token, or be approved to manage the token. +Emits a {Transfer} event. + +### safeTransferFrom(address,address,uint256) + +```solidity +function safeTransferFrom(address from, address to, uint256 id) + public + payable + virtual +``` + +Equivalent to `safeTransferFrom(from, to, id, "")`. + +### safeTransferFrom(address,address,uint256,bytes) + +```solidity +function safeTransferFrom( + address from, + address to, + uint256 id, + bytes calldata data +) public payable virtual +``` + +Transfers token `id` from `from` to `to`. +Requirements: +- Token `id` must exist. +- `from` must be the owner of the token. +- `to` cannot be the zero address. +- The caller must be the owner of the token, or be approved to manage the token. +- If `to` refers to a smart contract, it must implement + {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. +Emits a {Transfer} event. + +### supportsInterface(bytes4) + +```solidity +function supportsInterface(bytes4 interfaceId) + public + view + virtual + returns (bool result) +``` + +Returns true if this contract implements the interface defined by `interfaceId`. +See: https://eips.ethereum.org/EIPS/eip-165 +This function call must use less than 30000 gas. + +## Internal Query Functions + +### _exists(uint256) + +```solidity +function _exists(uint256 id) internal view virtual returns (bool result) +``` + +Returns if token `id` exists. + +### _ownerOf(uint256) + +```solidity +function _ownerOf(uint256 id) + internal + view + virtual + returns (address result) +``` + +Returns the owner of token `id`. +Returns the zero address instead of reverting if the token does not exist. + +## Internal Data Hitchhiking Functions + +For performance, no events are emitted for the hitchhiking setters. +Please emit your own events if required. + +### _getAux(address) + +```solidity +function _getAux(address owner) + internal + view + virtual + returns (uint224 result) +``` + +Returns the auxiliary data for `owner`. +Minting, transferring, burning the tokens of `owner` will not change the auxiliary data. +Auxiliary data can be set for any address, even if it does not have any tokens. + +### _setAux(address,uint224) + +```solidity +function _setAux(address owner, uint224 value) internal virtual +``` + +Set the auxiliary data for `owner` to `value`. +Minting, transferring, burning the tokens of `owner` will not change the auxiliary data. +Auxiliary data can be set for any address, even if it does not have any tokens. + +### _getExtraData(uint256) + +```solidity +function _getExtraData(uint256 id) + internal + view + virtual + returns (uint96 result) +``` + +Returns the extra data for token `id`. +Minting, transferring, burning a token will not change the extra data. +The extra data can be set on a non-existent token. + +### _setExtraData(uint256,uint96) + +```solidity +function _setExtraData(uint256 id, uint96 value) internal virtual +``` + +Sets the extra data for token `id` to `value`. +Minting, transferring, burning a token will not change the extra data. +The extra data can be set on a non-existent token. + +## Internal Mint Functions + +### _mint(address,uint256) + +```solidity +function _mint(address to, uint256 id) internal virtual +``` + +Mints token `id` to `to`. +Requirements: +- Token `id` must not exist. +- `to` cannot be the zero address. +Emits a {Transfer} event. + +### _mintAndSetExtraDataUnchecked(address,uint256,uint96) + +```solidity +function _mintAndSetExtraDataUnchecked(address to, uint256 id, uint96 value) + internal + virtual +``` + +Mints token `id` to `to`, and updates the extra data for token `id` to `value`. +Does NOT check if token `id` already exists (assumes `id` is auto-incrementing). +Requirements: +- `to` cannot be the zero address. +Emits a {Transfer} event. + +### _safeMint(address,uint256) + +```solidity +function _safeMint(address to, uint256 id) internal virtual +``` + +Equivalent to `_safeMint(to, id, "")`. + +### _safeMint(address,uint256,bytes) + +```solidity +function _safeMint(address to, uint256 id, bytes memory data) + internal + virtual +``` + +Mints token `id` to `to`. +Requirements: +- Token `id` must not exist. +- `to` cannot be the zero address. +- If `to` refers to a smart contract, it must implement + {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. +Emits a {Transfer} event. + +## Internal Burn Functions + +### _burn(uint256) + +```solidity +function _burn(uint256 id) internal virtual +``` + +Equivalent to `_burn(address(0), id)`. + +### _burn(address,uint256) + +```solidity +function _burn(address by, uint256 id) internal virtual +``` + +Destroys token `id`, using `by`. +Requirements: +- Token `id` must exist. +- If `by` is not the zero address, + it must be the owner of the token, or be approved to manage the token. +Emits a {Transfer} event. + +## Internal Approval Functions + +### _isApprovedOrOwner(address,uint256) + +```solidity +function _isApprovedOrOwner(address account, uint256 id) + internal + view + virtual + returns (bool result) +``` + +Returns whether `account` is the owner of token `id`, or is approved to manage it. +Requirements: +- Token `id` must exist. + +### _getApproved(uint256) + +```solidity +function _getApproved(uint256 id) + internal + view + virtual + returns (address result) +``` + +Returns the account approved to manage token `id`. +Returns the zero address instead of reverting if the token does not exist. + +### _approve(address,uint256) + +```solidity +function _approve(address account, uint256 id) internal virtual +``` + +Equivalent to `_approve(address(0), account, id)`. + +### _approve(address,address,uint256) + +```solidity +function _approve(address by, address account, uint256 id) + internal + virtual +``` + +Sets `account` as the approved account to manage token `id`, using `by`. +Requirements: +- Token `id` must exist. +- If `by` is not the zero address, `by` must be the owner + or an approved operator for the token owner. +Emits a {Approval} event. + +### _setApprovalForAll(address,address,bool) + +```solidity +function _setApprovalForAll(address by, address operator, bool isApproved) + internal + virtual +``` + +Approve or remove the `operator` as an operator for `by`, +without authorization checks. +Emits an {ApprovalForAll} event. + +## Internal Transfer Functions + +### _transfer(address,address,uint256) + +```solidity +function _transfer(address from, address to, uint256 id) internal virtual +``` + +Equivalent to `_transfer(address(0), from, to, id)`. + +### _transfer(address,address,address,uint256) + +```solidity +function _transfer(address by, address from, address to, uint256 id) + internal + virtual +``` + +Transfers token `id` from `from` to `to`. +Requirements: +- Token `id` must exist. +- `from` must be the owner of the token. +- `to` cannot be the zero address. +- If `by` is not the zero address, + it must be the owner of the token, or be approved to manage the token. +Emits a {Transfer} event. + +### _safeTransfer(address,address,uint256) + +```solidity +function _safeTransfer(address from, address to, uint256 id) + internal + virtual +``` + +Equivalent to `_safeTransfer(from, to, id, "")`. + +### _safeTransfer(address,address,uint256,bytes) + +```solidity +function _safeTransfer( + address from, + address to, + uint256 id, + bytes memory data +) internal virtual +``` + +Transfers token `id` from `from` to `to`. +Requirements: +- Token `id` must exist. +- `from` must be the owner of the token. +- `to` cannot be the zero address. +- The caller must be the owner of the token, or be approved to manage the token. +- If `to` refers to a smart contract, it must implement + {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. +Emits a {Transfer} event. + +### _safeTransfer(address,address,address,uint256) + +```solidity +function _safeTransfer(address by, address from, address to, uint256 id) + internal + virtual +``` + +Equivalent to `_safeTransfer(by, from, to, id, "")`. + +### _safeTransfer(address,address,address,uint256,bytes) + +```solidity +function _safeTransfer( + address by, + address from, + address to, + uint256 id, + bytes memory data +) internal virtual +``` + +Transfers token `id` from `from` to `to`. +Requirements: +- Token `id` must exist. +- `from` must be the owner of the token. +- `to` cannot be the zero address. +- If `by` is not the zero address, + it must be the owner of the token, or be approved to manage the token. +- If `to` refers to a smart contract, it must implement + {IERC721Receiver-onERC721Received}, which is called upon a safe transfer. +Emits a {Transfer} event. + +## Hooks For Overriding + +### _beforeTokenTransfer(address,address,uint256) + +```solidity +function _beforeTokenTransfer(address from, address to, uint256 id) + internal + virtual +``` + +Hook that is called before any token transfers, including minting and burning. + +### _afterTokenTransfer(address,address,uint256) + +```solidity +function _afterTokenTransfer(address from, address to, uint256 id) + internal + virtual +``` + +Hook that is called after any token transfers, including minting and burning. \ No newline at end of file diff --git a/docs/tokens/weth.md b/docs/tokens/weth.md new file mode 100644 index 000000000..aa90f33a1 --- /dev/null +++ b/docs/tokens/weth.md @@ -0,0 +1,67 @@ +# WETH + +Simple Wrapped Ether implementation. + + + + +Inherits: + +- `tokens/ERC20.sol` + + + + +## Custom Errors + +### ETHTransferFailed() + +```solidity +error ETHTransferFailed() +``` + +The ETH transfer has failed. + +## ERC20 Metadata + +### name() + +```solidity +function name() public view virtual override returns (string memory) +``` + +Returns the name of the token. + +### symbol() + +```solidity +function symbol() public view virtual override returns (string memory) +``` + +Returns the symbol of the token. + +## WETH + +### deposit() + +```solidity +function deposit() public payable virtual +``` + +Deposits `amount` ETH of the caller and mints `amount` WETH to the caller. + +### withdraw(uint256) + +```solidity +function withdraw(uint256 amount) public virtual +``` + +Burns `amount` WETH of the caller and sends `amount` ETH to the caller. + +### receive() + +```solidity +receive() external payable virtual +``` + +Equivalent to `deposit()`. \ No newline at end of file diff --git a/docs/utils/base64.md b/docs/utils/base64.md new file mode 100644 index 000000000..204910ef7 --- /dev/null +++ b/docs/utils/base64.md @@ -0,0 +1,71 @@ +# Base64 + +Library to encode strings in Base64. + + + + + + + + +## Functions + +### encode(bytes,bool,bool) + +```solidity +function encode(bytes memory data, bool fileSafe, bool noPadding) + internal + pure + returns (string memory result) +``` + +Encodes `data` using the base64 encoding described in RFC 4648. +See: https://datatracker.ietf.org/doc/html/rfc4648 +@param fileSafe Whether to replace '+' with '-' and '/' with '_'. +@param noPadding Whether to strip away the padding. + +### encode(bytes) + +```solidity +function encode(bytes memory data) + internal + pure + returns (string memory result) +``` + +Encodes `data` using the base64 encoding described in RFC 4648. +Equivalent to `encode(data, false, false)`. + +### encode(bytes,bool) + +```solidity +function encode(bytes memory data, bool fileSafe) + internal + pure + returns (string memory result) +``` + +Encodes `data` using the base64 encoding described in RFC 4648. +Equivalent to `encode(data, fileSafe, false)`. + +### decode(string) + +```solidity +function decode(string memory data) + internal + pure + returns (bytes memory result) +``` + +Decodes base64 encoded `data`. +Supports: +- RFC 4648 (both standard and file-safe mode). +- RFC 3501 (63: ','). +Does not support: +- Line breaks. +Note: For performance reasons, +this function will NOT revert on invalid `data` inputs. +Outputs for invalid inputs will simply be undefined behaviour. +It is the user's responsibility to ensure that the `data` +is a valid base64 encoded string. \ No newline at end of file diff --git a/docs/utils/create3.md b/docs/utils/create3.md new file mode 100644 index 000000000..65b445c16 --- /dev/null +++ b/docs/utils/create3.md @@ -0,0 +1,83 @@ +# CREATE3 + +Deterministic deployments agnostic to the initialization code. + + + + + + + + +## Custom Errors + +### DeploymentFailed() + +```solidity +error DeploymentFailed() +``` + +Unable to deploy the contract. + +## Bytecode Constants + +### PROXY_INITCODE_HASH + +```solidity +bytes32 internal constant PROXY_INITCODE_HASH = + 0x21c35dbe1b344a2488cf3321d6ce542f8e9f305544ff09e4993a62319a497c1f +``` + +Hash of the `_PROXY_INITCODE`. +Equivalent to `keccak256(abi.encodePacked(hex"67363d3d37363d34f03d5260086018f3"))`. + +## CREATE3 Operations + +### deployDeterministic(bytes,bytes32) + +```solidity +function deployDeterministic(bytes memory initCode, bytes32 salt) + internal + returns (address deployed) +``` + +Deploys `initCode` deterministically with a `salt`. +Returns the deterministic address of the deployed contract, +which solely depends on `salt`. + +### deployDeterministic(uint256,bytes,bytes32) + +```solidity +function deployDeterministic( + uint256 value, + bytes memory initCode, + bytes32 salt +) internal returns (address deployed) +``` + +Deploys `initCode` deterministically with a `salt`. +The deployed contract is funded with `value` (in wei) ETH. +Returns the deterministic address of the deployed contract, +which solely depends on `salt`. + +### predictDeterministicAddress(bytes32) + +```solidity +function predictDeterministicAddress(bytes32 salt) + internal + view + returns (address deployed) +``` + +Returns the deterministic address for `salt`. + +### predictDeterministicAddress(bytes32,address) + +```solidity +function predictDeterministicAddress(bytes32 salt, address deployer) + internal + pure + returns (address deployed) +``` + +Returns the deterministic address for `salt` with `deployer`. \ No newline at end of file diff --git a/docs/utils/datetimelib.md b/docs/utils/datetimelib.md new file mode 100644 index 000000000..476f7dbab --- /dev/null +++ b/docs/utils/datetimelib.md @@ -0,0 +1,467 @@ +# DateTimeLib + +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. + + + + + +## Date Time Operations + +### dateToEpochDay(uint256,uint256,uint256) + +```solidity +function dateToEpochDay(uint256 year, uint256 month, uint256 day) + internal + pure + returns (uint256 epochDay) +``` + +Returns the number of days since 1970-01-01 from (`year`,`month`,`day`). +See: https://howardhinnant.github.io/date_algorithms.html +Note: Inputs outside the supported ranges result in undefined behavior. +Use {isSupportedDate} to check if the inputs are supported. + +### epochDayToDate(uint256) + +```solidity +function epochDayToDate(uint256 epochDay) + internal + pure + returns (uint256 year, uint256 month, uint256 day) +``` + +Returns (`year`,`month`,`day`) from the number of days since 1970-01-01. +Note: Inputs outside the supported ranges result in undefined behavior. +Use {isSupportedDays} to check if the inputs is supported. + +### dateToTimestamp(uint256,uint256,uint256) + +```solidity +function dateToTimestamp(uint256 year, uint256 month, uint256 day) + internal + pure + returns (uint256 result) +``` + +Returns the unix timestamp from (`year`,`month`,`day`). +Note: Inputs outside the supported ranges result in undefined behavior. +Use {isSupportedDate} to check if the inputs are supported. + +### timestampToDate(uint256) + +```solidity +function timestampToDate(uint256 timestamp) + internal + pure + returns (uint256 year, uint256 month, uint256 day) +``` + +Returns (`year`,`month`,`day`) from the given unix timestamp. +Note: Inputs outside the supported ranges result in undefined behavior. +Use {isSupportedTimestamp} to check if the inputs are supported. + +### dateTimeToTimestamp(uint256,uint256,uint256,uint256,uint256,uint256) + +```solidity +function dateTimeToTimestamp( + uint256 year, + uint256 month, + uint256 day, + uint256 hour, + uint256 minute, + uint256 second +) internal pure returns (uint256 result) +``` + +Returns the unix timestamp from +(`year`,`month`,`day`,`hour`,`minute`,`second`). +Note: Inputs outside the supported ranges result in undefined behavior. +Use {isSupportedDateTime} to check if the inputs are supported. + +### timestampToDateTime(uint256) + +```solidity +function timestampToDateTime(uint256 timestamp) + internal + pure + returns ( + uint256 year, + uint256 month, + uint256 day, + uint256 hour, + uint256 minute, + uint256 second + ) +``` + +Returns (`year`,`month`,`day`,`hour`,`minute`,`second`) +from the given unix timestamp. +Note: Inputs outside the supported ranges result in undefined behavior. +Use {isSupportedTimestamp} to check if the inputs are supported. + +### isLeapYear(uint256) + +```solidity +function isLeapYear(uint256 year) internal pure returns (bool leap) +``` + +Returns if the `year` is leap. + +### daysInMonth(uint256,uint256) + +```solidity +function daysInMonth(uint256 year, uint256 month) + internal + pure + returns (uint256 result) +``` + +Returns number of days in given `month` of `year`. + +### weekday(uint256) + +```solidity +function weekday(uint256 timestamp) + internal + pure + returns (uint256 result) +``` + +Returns the weekday from the unix timestamp. +Monday: 1, Tuesday: 2, ....., Sunday: 7. + +### isSupportedDate(uint256,uint256,uint256) + +```solidity +function isSupportedDate(uint256 year, uint256 month, uint256 day) + internal + pure + returns (bool result) +``` + +Returns if (`year`,`month`,`day`) is a supported date. +- `1970 <= year <= MAX_SUPPORTED_YEAR`. +- `1 <= month <= 12`. +- `1 <= day <= daysInMonth(year, month)`. + +### isSupportedDateTime(uint256,uint256,uint256,uint256,uint256,uint256) + +```solidity +function isSupportedDateTime( + uint256 year, + uint256 month, + uint256 day, + uint256 hour, + uint256 minute, + uint256 second +) internal pure returns (bool result) +``` + +Returns if (`year`,`month`,`day`,`hour`,`minute`,`second`) is a supported date time. +- `1970 <= year <= MAX_SUPPORTED_YEAR`. +- `1 <= month <= 12`. +- `1 <= day <= daysInMonth(year, month)`. +- `hour < 24`. +- `minute < 60`. +- `second < 60`. + +### isSupportedEpochDay(uint256) + +```solidity +function isSupportedEpochDay(uint256 epochDay) + internal + pure + returns (bool result) +``` + +Returns if `epochDay` is a supported unix epoch day. + +### isSupportedTimestamp(uint256) + +```solidity +function isSupportedTimestamp(uint256 timestamp) + internal + pure + returns (bool result) +``` + +Returns if `timestamp` is a supported unix timestamp. + +### nthWeekdayInMonthOfYearTimestamp(uint256,uint256,uint256,uint256) + +```solidity +function nthWeekdayInMonthOfYearTimestamp( + uint256 year, + uint256 month, + uint256 n, + uint256 wd +) internal pure returns (uint256 result) +``` + +Returns the unix timestamp of the given `n`th weekday `wd`, in `month` of `year`. +Example: 3rd Friday of Feb 2022 is `nthWeekdayInMonthOfYearTimestamp(2022, 2, 3, 5)` +Note: `n` is 1-indexed for traditional consistency. +Invalid weekdays (i.e. `wd == 0 || wd > 7`) result in undefined behavior. + +### mondayTimestamp(uint256) + +```solidity +function mondayTimestamp(uint256 timestamp) + internal + pure + returns (uint256 result) +``` + +Returns the unix timestamp of the most recent Monday. + +### isWeekEnd(uint256) + +```solidity +function isWeekEnd(uint256 timestamp) internal pure returns (bool result) +``` + +Returns whether the unix timestamp falls on a Saturday or Sunday. +To check whether it is a week day, just take the negation of the result. + +## Date Time Arithmetic Operations + +### addYears(uint256,uint256) + +```solidity +function addYears(uint256 timestamp, uint256 numYears) + internal + pure + returns (uint256 result) +``` + +Adds `numYears` to the unix timestamp, and returns the result. +Note: The result will share the same Gregorian calendar month, +but different Gregorian calendar years for non-zero `numYears`. +If the Gregorian calendar month of the result has less days +than the Gregorian calendar month day of the `timestamp`, +the result's month day will be the maximum possible value for the month. +(e.g. from 29th Feb to 28th Feb) + +### addMonths(uint256,uint256) + +```solidity +function addMonths(uint256 timestamp, uint256 numMonths) + internal + pure + returns (uint256 result) +``` + +Adds `numMonths` to the unix timestamp, and returns the result. +Note: If the Gregorian calendar month of the result has less days +than the Gregorian calendar month day of the `timestamp`, +the result's month day will be the maximum possible value for the month. +(e.g. from 29th Feb to 28th Feb) + +### addDays(uint256,uint256) + +```solidity +function addDays(uint256 timestamp, uint256 numDays) + internal + pure + returns (uint256 result) +``` + +Adds `numDays` to the unix timestamp, and returns the result. + +### addHours(uint256,uint256) + +```solidity +function addHours(uint256 timestamp, uint256 numHours) + internal + pure + returns (uint256 result) +``` + +Adds `numHours` to the unix timestamp, and returns the result. + +### addMinutes(uint256,uint256) + +```solidity +function addMinutes(uint256 timestamp, uint256 numMinutes) + internal + pure + returns (uint256 result) +``` + +Adds `numMinutes` to the unix timestamp, and returns the result. + +### addSeconds(uint256,uint256) + +```solidity +function addSeconds(uint256 timestamp, uint256 numSeconds) + internal + pure + returns (uint256 result) +``` + +Adds `numSeconds` to the unix timestamp, and returns the result. + +### subYears(uint256,uint256) + +```solidity +function subYears(uint256 timestamp, uint256 numYears) + internal + pure + returns (uint256 result) +``` + +Subtracts `numYears` from the unix timestamp, and returns the result. +Note: The result will share the same Gregorian calendar month, +but different Gregorian calendar years for non-zero `numYears`. +If the Gregorian calendar month of the result has less days +than the Gregorian calendar month day of the `timestamp`, +the result's month day will be the maximum possible value for the month. +(e.g. from 29th Feb to 28th Feb) + +### subMonths(uint256,uint256) + +```solidity +function subMonths(uint256 timestamp, uint256 numMonths) + internal + pure + returns (uint256 result) +``` + +Subtracts `numYears` from the unix timestamp, and returns the result. +Note: If the Gregorian calendar month of the result has less days +than the Gregorian calendar month day of the `timestamp`, +the result's month day will be the maximum possible value for the month. +(e.g. from 29th Feb to 28th Feb) + +### subDays(uint256,uint256) + +```solidity +function subDays(uint256 timestamp, uint256 numDays) + internal + pure + returns (uint256 result) +``` + +Subtracts `numDays` from the unix timestamp, and returns the result. + +### subHours(uint256,uint256) + +```solidity +function subHours(uint256 timestamp, uint256 numHours) + internal + pure + returns (uint256 result) +``` + +Subtracts `numHours` from the unix timestamp, and returns the result. + +### subMinutes(uint256,uint256) + +```solidity +function subMinutes(uint256 timestamp, uint256 numMinutes) + internal + pure + returns (uint256 result) +``` + +Subtracts `numMinutes` from the unix timestamp, and returns the result. + +### subSeconds(uint256,uint256) + +```solidity +function subSeconds(uint256 timestamp, uint256 numSeconds) + internal + pure + returns (uint256 result) +``` + +Subtracts `numSeconds` from the unix timestamp, and returns the result. + +### diffYears(uint256,uint256) + +```solidity +function diffYears(uint256 fromTimestamp, uint256 toTimestamp) + internal + pure + returns (uint256 result) +``` + +Returns the difference in Gregorian calendar years +between `fromTimestamp` and `toTimestamp`. +Note: Even if the true time difference is less than a year, +the difference can be non-zero is the timestamps are +from different Gregorian calendar years + +### diffMonths(uint256,uint256) + +```solidity +function diffMonths(uint256 fromTimestamp, uint256 toTimestamp) + internal + pure + returns (uint256 result) +``` + +Returns the difference in Gregorian calendar months +between `fromTimestamp` and `toTimestamp`. +Note: Even if the true time difference is less than a month, +the difference can be non-zero is the timestamps are +from different Gregorian calendar months. + +### diffDays(uint256,uint256) + +```solidity +function diffDays(uint256 fromTimestamp, uint256 toTimestamp) + internal + pure + returns (uint256 result) +``` + +Returns the difference in days between `fromTimestamp` and `toTimestamp`. + +### diffHours(uint256,uint256) + +```solidity +function diffHours(uint256 fromTimestamp, uint256 toTimestamp) + internal + pure + returns (uint256 result) +``` + +Returns the difference in hours between `fromTimestamp` and `toTimestamp`. + +### diffMinutes(uint256,uint256) + +```solidity +function diffMinutes(uint256 fromTimestamp, uint256 toTimestamp) + internal + pure + returns (uint256 result) +``` + +Returns the difference in minutes between `fromTimestamp` and `toTimestamp`. + +### diffSeconds(uint256,uint256) + +```solidity +function diffSeconds(uint256 fromTimestamp, uint256 toTimestamp) + internal + pure + returns (uint256 result) +``` + +Returns the difference in seconds between `fromTimestamp` and `toTimestamp`. \ No newline at end of file diff --git a/docs/utils/deploylesspredeployqueryer.md b/docs/utils/deploylesspredeployqueryer.md new file mode 100644 index 000000000..473516650 --- /dev/null +++ b/docs/utils/deploylesspredeployqueryer.md @@ -0,0 +1,20 @@ +# DeploylessPredeployQueryer + +Deployless queryer for predeploys. + + + + + + + + +## Custom Errors + +### ReturnedAddressMismatch() + +```solidity +error ReturnedAddressMismatch() +``` + +The returned address by the factory does not match the provided address. \ No newline at end of file diff --git a/docs/utils/dynamicarraylib.md b/docs/utils/dynamicarraylib.md new file mode 100644 index 000000000..516fa1e4c --- /dev/null +++ b/docs/utils/dynamicarraylib.md @@ -0,0 +1,977 @@ +# DynamicArrayLib + +Library for memory arrays with automatic capacity resizing. + + + + + + + + +## Structs + +### DynamicArray + +```solidity +struct DynamicArray { + uint256[] data; +} +``` + +Type to represent a dynamic array in memory. +You can directly assign to `data`, and the `p` function will +take care of the memory allocation. + +## Constants + +### NOT_FOUND + +```solidity +uint256 internal constant NOT_FOUND = type(uint256).max +``` + +The constant returned when the element is not found in the array. + +## Uint256 Array Operations + +Low level minimalist uint256 array operations. +If you don't need syntax sugar, it's recommended to use these. +Some of these functions returns the same array for function chaining. +e.g. `array.set(0, 1).set(1, 2)`. + +### malloc(uint256) + +```solidity +function malloc(uint256 n) + internal + pure + returns (uint256[] memory result) +``` + +Returns a uint256 array with `n` elements. The elements are not zeroized. + +### zeroize(uint256[]) + +```solidity +function zeroize(uint256[] memory a) + internal + pure + returns (uint256[] memory result) +``` + +Zeroizes all the elements of `a`. + +### get(uint256[],uint256) + +```solidity +function get(uint256[] memory a, uint256 i) + internal + pure + returns (uint256 result) +``` + +Returns the element at `a[i]`, without bounds checking. + +### getUint256(uint256[],uint256) + +```solidity +function getUint256(uint256[] memory a, uint256 i) + internal + pure + returns (uint256 result) +``` + +Returns the element at `a[i]`, without bounds checking. + +### getAddress(uint256[],uint256) + +```solidity +function getAddress(uint256[] memory a, uint256 i) + internal + pure + returns (address result) +``` + +Returns the element at `a[i]`, without bounds checking. + +### getBool(uint256[],uint256) + +```solidity +function getBool(uint256[] memory a, uint256 i) + internal + pure + returns (bool result) +``` + +Returns the element at `a[i]`, without bounds checking. + +### getBytes32(uint256[],uint256) + +```solidity +function getBytes32(uint256[] memory a, uint256 i) + internal + pure + returns (bytes32 result) +``` + +Returns the element at `a[i]`, without bounds checking. + +### set(uint256[],uint256,uint256) + +```solidity +function set(uint256[] memory a, uint256 i, uint256 data) + internal + pure + returns (uint256[] memory result) +``` + +Sets `a.data[i]` to `data`, without bounds checking. + +### set(uint256[],uint256,address) + +```solidity +function set(uint256[] memory a, uint256 i, address data) + internal + pure + returns (uint256[] memory result) +``` + +Sets `a.data[i]` to `data`, without bounds checking. + +### set(uint256[],uint256,bool) + +```solidity +function set(uint256[] memory a, uint256 i, bool data) + internal + pure + returns (uint256[] memory result) +``` + +Sets `a.data[i]` to `data`, without bounds checking. + +### set(uint256[],uint256,bytes32) + +```solidity +function set(uint256[] memory a, uint256 i, bytes32 data) + internal + pure + returns (uint256[] memory result) +``` + +Sets `a.data[i]` to `data`, without bounds checking. + +### asAddressArray(uint256[]) + +```solidity +function asAddressArray(uint256[] memory a) + internal + pure + returns (address[] memory result) +``` + +Casts `a` to `address[]`. + +### asBoolArray(uint256[]) + +```solidity +function asBoolArray(uint256[] memory a) + internal + pure + returns (bool[] memory result) +``` + +Casts `a` to `bool[]`. + +### asBytes32Array(uint256[]) + +```solidity +function asBytes32Array(uint256[] memory a) + internal + pure + returns (bytes32[] memory result) +``` + +Casts `a` to `bytes32[]`. + +### toUint256Array(address[]) + +```solidity +function toUint256Array(address[] memory a) + internal + pure + returns (uint256[] memory result) +``` + +Casts `a` to `uint256[]`. + +### toUint256Array(bool[]) + +```solidity +function toUint256Array(bool[] memory a) + internal + pure + returns (uint256[] memory result) +``` + +Casts `a` to `uint256[]`. + +### toUint256Array(bytes32[]) + +```solidity +function toUint256Array(bytes32[] memory a) + internal + pure + returns (uint256[] memory result) +``` + +Casts `a` to `uint256[]`. + +### truncate(uint256[],uint256) + +```solidity +function truncate(uint256[] memory a, uint256 n) + internal + pure + returns (uint256[] memory result) +``` + +Reduces the size of `a` to `n`. +If `n` is greater than the size of `a`, this will be a no-op. + +### free(uint256[]) + +```solidity +function free(uint256[] memory a) + internal + pure + returns (uint256[] memory result) +``` + +Clears the array and attempts to free the memory if possible. + +### hash(uint256[]) + +```solidity +function hash(uint256[] memory a) internal pure returns (bytes32 result) +``` + +Equivalent to `keccak256(abi.encodePacked(a))`. + +### slice(uint256[],uint256,uint256) + +```solidity +function slice(uint256[] memory a, uint256 start, uint256 end) + internal + pure + returns (uint256[] memory result) +``` + +Returns a copy of `a` sliced from `start` to `end` (exclusive). + +### contains(uint256[],uint256) + +```solidity +function contains(uint256[] memory a, uint256 needle) + internal + pure + returns (bool) +``` + +Returns if `needle` is in `a`. + +### indexOf(uint256[],uint256,uint256) + +```solidity +function indexOf(uint256[] memory a, uint256 needle, uint256 from) + internal + pure + returns (uint256 result) +``` + +Returns the first index of `needle`, scanning forward from `from`. +If `needle` is not in `a`, returns `NOT_FOUND`. + +### indexOf(uint256[],uint256) + +```solidity +function indexOf(uint256[] memory a, uint256 needle) + internal + pure + returns (uint256 result) +``` + +Returns the first index of `needle`. +If `needle` is not in `a`, returns `NOT_FOUND`. + +### lastIndexOf(uint256[],uint256,uint256) + +```solidity +function lastIndexOf(uint256[] memory a, uint256 needle, uint256 from) + internal + pure + returns (uint256 result) +``` + +Returns the last index of `needle`, scanning backwards from `from`. +If `needle` is not in `a`, returns `NOT_FOUND`. + +### lastIndexOf(uint256[],uint256) + +```solidity +function lastIndexOf(uint256[] memory a, uint256 needle) + internal + pure + returns (uint256 result) +``` + +Returns the first index of `needle`. +If `needle` is not in `a`, returns `NOT_FOUND`. + +### directReturn(uint256[]) + +```solidity +function directReturn(uint256[] memory a) internal pure +``` + +Directly returns `a` without copying. + +## Dynamic Array Operations + +Some of these functions returns the same array for function chaining. +e.g. `a.p("1").p("2")`. + +### length(DynamicArray) + +```solidity +function length(DynamicArray memory a) internal pure returns (uint256) +``` + +Shorthand for `a.data.length`. + +### wrap(uint256[]) + +```solidity +function wrap(uint256[] memory a) + internal + pure + returns (DynamicArray memory result) +``` + +Wraps `a` in a dynamic array struct. + +### wrap(address[]) + +```solidity +function wrap(address[] memory a) + internal + pure + returns (DynamicArray memory result) +``` + +Wraps `a` in a dynamic array struct. + +### wrap(bool[]) + +```solidity +function wrap(bool[] memory a) + internal + pure + returns (DynamicArray memory result) +``` + +Wraps `a` in a dynamic array struct. + +### wrap(bytes32[]) + +```solidity +function wrap(bytes32[] memory a) + internal + pure + returns (DynamicArray memory result) +``` + +Wraps `a` in a dynamic array struct. + +### clear(DynamicArray) + +```solidity +function clear(DynamicArray memory a) + internal + pure + returns (DynamicArray memory result) +``` + +Clears the array without deallocating the memory. + +### free(DynamicArray) + +```solidity +function free(DynamicArray memory a) + internal + pure + returns (DynamicArray memory result) +``` + +Clears the array and attempts to free the memory if possible. + +### resize(DynamicArray,uint256) + +```solidity +function resize(DynamicArray memory a, uint256 n) + internal + pure + returns (DynamicArray memory result) +``` + +Resizes the array to contain `n` elements. New elements will be zeroized. + +### expand(DynamicArray,uint256) + +```solidity +function expand(DynamicArray memory a, uint256 n) + internal + pure + returns (DynamicArray memory result) +``` + +Increases the size of `a` to `n`. +If `n` is less than the size of `a`, this will be a no-op. +This method does not zeroize any newly created elements. + +### truncate(DynamicArray,uint256) + +```solidity +function truncate(DynamicArray memory a, uint256 n) + internal + pure + returns (DynamicArray memory result) +``` + +Reduces the size of `a` to `n`. +If `n` is greater than the size of `a`, this will be a no-op. + +### reserve(DynamicArray,uint256) + +```solidity +function reserve(DynamicArray memory a, uint256 minimum) + internal + pure + returns (DynamicArray memory result) +``` + +Reserves at least `minimum` amount of contiguous memory. + +### p(DynamicArray,uint256) + +```solidity +function p(DynamicArray memory a, uint256 data) + internal + pure + returns (DynamicArray memory result) +``` + +Appends `data` to `a`. + +### p(DynamicArray,address) + +```solidity +function p(DynamicArray memory a, address data) + internal + pure + returns (DynamicArray memory result) +``` + +Appends `data` to `a`. + +### p(DynamicArray,bool) + +```solidity +function p(DynamicArray memory a, bool data) + internal + pure + returns (DynamicArray memory result) +``` + +Appends `data` to `a`. + +### p(DynamicArray,bytes32) + +```solidity +function p(DynamicArray memory a, bytes32 data) + internal + pure + returns (DynamicArray memory result) +``` + +Appends `data` to `a`. + +### p() + +```solidity +function p() internal pure returns (DynamicArray memory result) +``` + +Shorthand for returning an empty array. + +### p(uint256) + +```solidity +function p(uint256 data) + internal + pure + returns (DynamicArray memory result) +``` + +Shorthand for `p(p(), data)`. + +### p(address) + +```solidity +function p(address data) + internal + pure + returns (DynamicArray memory result) +``` + +Shorthand for `p(p(), data)`. + +### p(bool) + +```solidity +function p(bool data) internal pure returns (DynamicArray memory result) +``` + +Shorthand for `p(p(), data)`. + +### p(bytes32) + +```solidity +function p(bytes32 data) + internal + pure + returns (DynamicArray memory result) +``` + +Shorthand for `p(p(), data)`. + +### pop(DynamicArray) + +```solidity +function pop(DynamicArray memory a) + internal + pure + returns (uint256 result) +``` + +Removes and returns the last element of `a`. +Returns 0 and does not pop anything if the array is empty. + +### popUint256(DynamicArray) + +```solidity +function popUint256(DynamicArray memory a) + internal + pure + returns (uint256 result) +``` + +Removes and returns the last element of `a`. +Returns 0 and does not pop anything if the array is empty. + +### popAddress(DynamicArray) + +```solidity +function popAddress(DynamicArray memory a) + internal + pure + returns (address result) +``` + +Removes and returns the last element of `a`. +Returns 0 and does not pop anything if the array is empty. + +### popBool(DynamicArray) + +```solidity +function popBool(DynamicArray memory a) + internal + pure + returns (bool result) +``` + +Removes and returns the last element of `a`. +Returns 0 and does not pop anything if the array is empty. + +### popBytes32(DynamicArray) + +```solidity +function popBytes32(DynamicArray memory a) + internal + pure + returns (bytes32 result) +``` + +Removes and returns the last element of `a`. +Returns 0 and does not pop anything if the array is empty. + +### get(DynamicArray,uint256) + +```solidity +function get(DynamicArray memory a, uint256 i) + internal + pure + returns (uint256 result) +``` + +Returns the element at `a.data[i]`, without bounds checking. + +### getUint256(DynamicArray,uint256) + +```solidity +function getUint256(DynamicArray memory a, uint256 i) + internal + pure + returns (uint256 result) +``` + +Returns the element at `a.data[i]`, without bounds checking. + +### getAddress(DynamicArray,uint256) + +```solidity +function getAddress(DynamicArray memory a, uint256 i) + internal + pure + returns (address result) +``` + +Returns the element at `a.data[i]`, without bounds checking. + +### getBool(DynamicArray,uint256) + +```solidity +function getBool(DynamicArray memory a, uint256 i) + internal + pure + returns (bool result) +``` + +Returns the element at `a.data[i]`, without bounds checking. + +### getBytes32(DynamicArray,uint256) + +```solidity +function getBytes32(DynamicArray memory a, uint256 i) + internal + pure + returns (bytes32 result) +``` + +Returns the element at `a.data[i]`, without bounds checking. + +### set(DynamicArray,uint256,uint256) + +```solidity +function set(DynamicArray memory a, uint256 i, uint256 data) + internal + pure + returns (DynamicArray memory result) +``` + +Sets `a.data[i]` to `data`, without bounds checking. + +### set(DynamicArray,uint256,address) + +```solidity +function set(DynamicArray memory a, uint256 i, address data) + internal + pure + returns (DynamicArray memory result) +``` + +Sets `a.data[i]` to `data`, without bounds checking. + +### set(DynamicArray,uint256,bool) + +```solidity +function set(DynamicArray memory a, uint256 i, bool data) + internal + pure + returns (DynamicArray memory result) +``` + +Sets `a.data[i]` to `data`, without bounds checking. + +### set(DynamicArray,uint256,bytes32) + +```solidity +function set(DynamicArray memory a, uint256 i, bytes32 data) + internal + pure + returns (DynamicArray memory result) +``` + +Sets `a.data[i]` to `data`, without bounds checking. + +### asUint256Array(DynamicArray) + +```solidity +function asUint256Array(DynamicArray memory a) + internal + pure + returns (uint256[] memory result) +``` + +Returns the underlying array as a `uint256[]`. + +### asAddressArray(DynamicArray) + +```solidity +function asAddressArray(DynamicArray memory a) + internal + pure + returns (address[] memory result) +``` + +Returns the underlying array as a `address[]`. + +### asBoolArray(DynamicArray) + +```solidity +function asBoolArray(DynamicArray memory a) + internal + pure + returns (bool[] memory result) +``` + +Returns the underlying array as a `bool[]`. + +### asBytes32Array(DynamicArray) + +```solidity +function asBytes32Array(DynamicArray memory a) + internal + pure + returns (bytes32[] memory result) +``` + +Returns the underlying array as a `bytes32[]`. + +### slice(DynamicArray,uint256,uint256) + +```solidity +function slice(DynamicArray memory a, uint256 start, uint256 end) + internal + pure + returns (DynamicArray memory result) +``` + +Returns a copy of `a` sliced from `start` to `end` (exclusive). + +### slice(DynamicArray,uint256) + +```solidity +function slice(DynamicArray memory a, uint256 start) + internal + pure + returns (DynamicArray memory result) +``` + +Returns a copy of `a` sliced from `start` to the end of the array. + +### contains(DynamicArray,uint256) + +```solidity +function contains(DynamicArray memory a, uint256 needle) + internal + pure + returns (bool) +``` + +Returns if `needle` is in `a`. + +### contains(DynamicArray,address) + +```solidity +function contains(DynamicArray memory a, address needle) + internal + pure + returns (bool) +``` + +Returns if `needle` is in `a`. + +### contains(DynamicArray,bytes32) + +```solidity +function contains(DynamicArray memory a, bytes32 needle) + internal + pure + returns (bool) +``` + +Returns if `needle` is in `a`. + +### indexOf(DynamicArray,uint256,uint256) + +```solidity +function indexOf(DynamicArray memory a, uint256 needle, uint256 from) + internal + pure + returns (uint256) +``` + +Returns the first index of `needle`, scanning forward from `from`. +If `needle` is not in `a`, returns `NOT_FOUND`. + +### indexOf(DynamicArray,address,uint256) + +```solidity +function indexOf(DynamicArray memory a, address needle, uint256 from) + internal + pure + returns (uint256) +``` + +Returns the first index of `needle`, scanning forward from `from`. +If `needle` is not in `a`, returns `NOT_FOUND`. + +### indexOf(DynamicArray,bytes32,uint256) + +```solidity +function indexOf(DynamicArray memory a, bytes32 needle, uint256 from) + internal + pure + returns (uint256) +``` + +Returns the first index of `needle`, scanning forward from `from`. +If `needle` is not in `a`, returns `NOT_FOUND`. + +### indexOf(DynamicArray,uint256) + +```solidity +function indexOf(DynamicArray memory a, uint256 needle) + internal + pure + returns (uint256) +``` + +Returns the first index of `needle`. +If `needle` is not in `a`, returns `NOT_FOUND`. + +### indexOf(DynamicArray,address) + +```solidity +function indexOf(DynamicArray memory a, address needle) + internal + pure + returns (uint256) +``` + +Returns the first index of `needle`. +If `needle` is not in `a`, returns `NOT_FOUND`. + +### indexOf(DynamicArray,bytes32) + +```solidity +function indexOf(DynamicArray memory a, bytes32 needle) + internal + pure + returns (uint256) +``` + +Returns the first index of `needle`. +If `needle` is not in `a`, returns `NOT_FOUND`. + +### lastIndexOf(DynamicArray,uint256,uint256) + +```solidity +function lastIndexOf(DynamicArray memory a, uint256 needle, uint256 from) + internal + pure + returns (uint256) +``` + +Returns the last index of `needle`, scanning backwards from `from`. +If `needle` is not in `a`, returns `NOT_FOUND`. + +### lastIndexOf(DynamicArray,address,uint256) + +```solidity +function lastIndexOf(DynamicArray memory a, address needle, uint256 from) + internal + pure + returns (uint256) +``` + +Returns the last index of `needle`, scanning backwards from `from`. +If `needle` is not in `a`, returns `NOT_FOUND`. + +### lastIndexOf(DynamicArray,bytes32,uint256) + +```solidity +function lastIndexOf(DynamicArray memory a, bytes32 needle, uint256 from) + internal + pure + returns (uint256) +``` + +Returns the last index of `needle`, scanning backwards from `from`. +If `needle` is not in `a`, returns `NOT_FOUND`. + +### lastIndexOf(DynamicArray,uint256) + +```solidity +function lastIndexOf(DynamicArray memory a, uint256 needle) + internal + pure + returns (uint256) +``` + +Returns the last index of `needle`. +If `needle` is not in `a`, returns `NOT_FOUND`. + +### lastIndexOf(DynamicArray,address) + +```solidity +function lastIndexOf(DynamicArray memory a, address needle) + internal + pure + returns (uint256) +``` + +Returns the last index of `needle`. +If `needle` is not in `a`, returns `NOT_FOUND`. + +### lastIndexOf(DynamicArray,bytes32) + +```solidity +function lastIndexOf(DynamicArray memory a, bytes32 needle) + internal + pure + returns (uint256) +``` + +Returns the last index of `needle`. +If `needle` is not in `a`, returns `NOT_FOUND`. + +### hash(DynamicArray) + +```solidity +function hash(DynamicArray memory a) + internal + pure + returns (bytes32 result) +``` + +Equivalent to `keccak256(abi.encodePacked(a.data))`. + +### directReturn(DynamicArray) + +```solidity +function directReturn(DynamicArray memory a) internal pure +``` + +Directly returns `a` without copying. \ No newline at end of file diff --git a/docs/utils/dynamicbufferlib.md b/docs/utils/dynamicbufferlib.md new file mode 100644 index 000000000..50210fc98 --- /dev/null +++ b/docs/utils/dynamicbufferlib.md @@ -0,0 +1,1723 @@ +# DynamicBufferLib + +Library for buffers with automatic capacity resizing. + + + + + + + + +## Structs + +### DynamicBuffer + +```solidity +struct DynamicBuffer { + bytes data; +} +``` + +Type to represent a dynamic buffer in memory. +You can directly assign to `data`, and the `p` function will +take care of the memory allocation. + +## Operations + +Some of these functions returns the same buffer for function chaining. +e.g. `buffer.p("1").p("2")`. + +### length(DynamicBuffer) + +```solidity +function length(DynamicBuffer memory buffer) + internal + pure + returns (uint256) +``` + +Shorthand for `buffer.data.length`. + +### reserve(DynamicBuffer,uint256) + +```solidity +function reserve(DynamicBuffer memory buffer, uint256 minimum) + internal + pure + returns (DynamicBuffer memory result) +``` + +Reserves at least `minimum` amount of contiguous memory. + +### clear(DynamicBuffer) + +```solidity +function clear(DynamicBuffer memory buffer) + internal + pure + returns (DynamicBuffer memory result) +``` + +Clears the buffer without deallocating the memory. + +### s(DynamicBuffer) + +```solidity +function s(DynamicBuffer memory buffer) + internal + pure + returns (string memory) +``` + +Returns a string pointing to the underlying bytes data. +Note: The string WILL change if the buffer is updated. + +### p(DynamicBuffer,bytes) + +```solidity +function p(DynamicBuffer memory buffer, bytes memory data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Appends `data` to `buffer`. + +### p(DynamicBuffer,bytes,bytes) + +```solidity +function p( + DynamicBuffer memory buffer, + bytes memory data0, + bytes memory data1 +) internal pure returns (DynamicBuffer memory result) +``` + +Appends `data0`, `data1` to `buffer`. + +### p(DynamicBuffer,bytes,bytes,bytes) + +```solidity +function p( + DynamicBuffer memory buffer, + bytes memory data0, + bytes memory data1, + bytes memory data2 +) internal pure returns (DynamicBuffer memory result) +``` + +Appends `data0` .. `data2` to `buffer`. + +### p(DynamicBuffer,bytes,bytes,bytes,bytes) + +```solidity +function p( + DynamicBuffer memory buffer, + bytes memory data0, + bytes memory data1, + bytes memory data2, + bytes memory data3 +) internal pure returns (DynamicBuffer memory result) +``` + +Appends `data0` .. `data3` to `buffer`. + +### p(DynamicBuffer,bytes,bytes,bytes,bytes,bytes) + +```solidity +function p( + DynamicBuffer memory buffer, + bytes memory data0, + bytes memory data1, + bytes memory data2, + bytes memory data3, + bytes memory data4 +) internal pure returns (DynamicBuffer memory result) +``` + +Appends `data0` .. `data4` to `buffer`. + +### p(DynamicBuffer,bytes,bytes,bytes,bytes,bytes,bytes) + +```solidity +function p( + DynamicBuffer memory buffer, + bytes memory data0, + bytes memory data1, + bytes memory data2, + bytes memory data3, + bytes memory data4, + bytes memory data5 +) internal pure returns (DynamicBuffer memory result) +``` + +Appends `data0` .. `data5` to `buffer`. + +### p(DynamicBuffer,bytes,bytes,bytes,bytes,bytes,bytes,bytes) + +```solidity +function p( + DynamicBuffer memory buffer, + bytes memory data0, + bytes memory data1, + bytes memory data2, + bytes memory data3, + bytes memory data4, + bytes memory data5, + bytes memory data6 +) internal pure returns (DynamicBuffer memory result) +``` + +Appends `data0` .. `data6` to `buffer`. + +### pBool(DynamicBuffer,bool) + +```solidity +function pBool(DynamicBuffer memory buffer, bool data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Appends `abi.encodePacked(bool(data))` to buffer. + +### pAddress(DynamicBuffer,address) + +```solidity +function pAddress(DynamicBuffer memory buffer, address data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Appends `abi.encodePacked(address(data))` to buffer. + +### pUint8(DynamicBuffer,uint8) + +```solidity +function pUint8(DynamicBuffer memory buffer, uint8 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Appends `abi.encodePacked(uint8(data))` to buffer. + +### pUint16(DynamicBuffer,uint16) + +```solidity +function pUint16(DynamicBuffer memory buffer, uint16 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Appends `abi.encodePacked(uint16(data))` to buffer. + +### pUint24(DynamicBuffer,uint24) + +```solidity +function pUint24(DynamicBuffer memory buffer, uint24 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Appends `abi.encodePacked(uint24(data))` to buffer. + +### pUint32(DynamicBuffer,uint32) + +```solidity +function pUint32(DynamicBuffer memory buffer, uint32 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Appends `abi.encodePacked(uint32(data))` to buffer. + +### pUint40(DynamicBuffer,uint40) + +```solidity +function pUint40(DynamicBuffer memory buffer, uint40 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Appends `abi.encodePacked(uint40(data))` to buffer. + +### pUint48(DynamicBuffer,uint48) + +```solidity +function pUint48(DynamicBuffer memory buffer, uint48 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Appends `abi.encodePacked(uint48(data))` to buffer. + +### pUint56(DynamicBuffer,uint56) + +```solidity +function pUint56(DynamicBuffer memory buffer, uint56 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Appends `abi.encodePacked(uint56(data))` to buffer. + +### pUint64(DynamicBuffer,uint64) + +```solidity +function pUint64(DynamicBuffer memory buffer, uint64 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Appends `abi.encodePacked(uint64(data))` to buffer. + +### pUint72(DynamicBuffer,uint72) + +```solidity +function pUint72(DynamicBuffer memory buffer, uint72 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Appends `abi.encodePacked(uint72(data))` to buffer. + +### pUint80(DynamicBuffer,uint80) + +```solidity +function pUint80(DynamicBuffer memory buffer, uint80 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Appends `abi.encodePacked(uint80(data))` to buffer. + +### pUint88(DynamicBuffer,uint88) + +```solidity +function pUint88(DynamicBuffer memory buffer, uint88 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Appends `abi.encodePacked(uint88(data))` to buffer. + +### pUint96(DynamicBuffer,uint96) + +```solidity +function pUint96(DynamicBuffer memory buffer, uint96 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Appends `abi.encodePacked(uint96(data))` to buffer. + +### pUint104(DynamicBuffer,uint104) + +```solidity +function pUint104(DynamicBuffer memory buffer, uint104 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Appends `abi.encodePacked(uint104(data))` to buffer. + +### pUint112(DynamicBuffer,uint112) + +```solidity +function pUint112(DynamicBuffer memory buffer, uint112 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Appends `abi.encodePacked(uint112(data))` to buffer. + +### pUint120(DynamicBuffer,uint120) + +```solidity +function pUint120(DynamicBuffer memory buffer, uint120 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Appends `abi.encodePacked(uint120(data))` to buffer. + +### pUint128(DynamicBuffer,uint128) + +```solidity +function pUint128(DynamicBuffer memory buffer, uint128 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Appends `abi.encodePacked(uint128(data))` to buffer. + +### pUint136(DynamicBuffer,uint136) + +```solidity +function pUint136(DynamicBuffer memory buffer, uint136 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Appends `abi.encodePacked(uint136(data))` to buffer. + +### pUint144(DynamicBuffer,uint144) + +```solidity +function pUint144(DynamicBuffer memory buffer, uint144 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Appends `abi.encodePacked(uint144(data))` to buffer. + +### pUint152(DynamicBuffer,uint152) + +```solidity +function pUint152(DynamicBuffer memory buffer, uint152 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Appends `abi.encodePacked(uint152(data))` to buffer. + +### pUint160(DynamicBuffer,uint160) + +```solidity +function pUint160(DynamicBuffer memory buffer, uint160 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Appends `abi.encodePacked(uint160(data))` to buffer. + +### pUint168(DynamicBuffer,uint168) + +```solidity +function pUint168(DynamicBuffer memory buffer, uint168 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Appends `abi.encodePacked(uint168(data))` to buffer. + +### pUint176(DynamicBuffer,uint176) + +```solidity +function pUint176(DynamicBuffer memory buffer, uint176 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Appends `abi.encodePacked(uint176(data))` to buffer. + +### pUint184(DynamicBuffer,uint184) + +```solidity +function pUint184(DynamicBuffer memory buffer, uint184 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Appends `abi.encodePacked(uint184(data))` to buffer. + +### pUint192(DynamicBuffer,uint192) + +```solidity +function pUint192(DynamicBuffer memory buffer, uint192 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Appends `abi.encodePacked(uint192(data))` to buffer. + +### pUint200(DynamicBuffer,uint200) + +```solidity +function pUint200(DynamicBuffer memory buffer, uint200 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Appends `abi.encodePacked(uint200(data))` to buffer. + +### pUint208(DynamicBuffer,uint208) + +```solidity +function pUint208(DynamicBuffer memory buffer, uint208 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Appends `abi.encodePacked(uint208(data))` to buffer. + +### pUint216(DynamicBuffer,uint216) + +```solidity +function pUint216(DynamicBuffer memory buffer, uint216 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Appends `abi.encodePacked(uint216(data))` to buffer. + +### pUint224(DynamicBuffer,uint224) + +```solidity +function pUint224(DynamicBuffer memory buffer, uint224 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Appends `abi.encodePacked(uint224(data))` to buffer. + +### pUint232(DynamicBuffer,uint232) + +```solidity +function pUint232(DynamicBuffer memory buffer, uint232 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Appends `abi.encodePacked(uint232(data))` to buffer. + +### pUint240(DynamicBuffer,uint240) + +```solidity +function pUint240(DynamicBuffer memory buffer, uint240 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Appends `abi.encodePacked(uint240(data))` to buffer. + +### pUint248(DynamicBuffer,uint248) + +```solidity +function pUint248(DynamicBuffer memory buffer, uint248 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Appends `abi.encodePacked(uint248(data))` to buffer. + +### pUint256(DynamicBuffer,uint256) + +```solidity +function pUint256(DynamicBuffer memory buffer, uint256 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Appends `abi.encodePacked(uint256(data))` to buffer. + +### pBytes1(DynamicBuffer,bytes1) + +```solidity +function pBytes1(DynamicBuffer memory buffer, bytes1 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Appends `abi.encodePacked(bytes1(data))` to buffer. + +### pBytes2(DynamicBuffer,bytes2) + +```solidity +function pBytes2(DynamicBuffer memory buffer, bytes2 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Appends `abi.encodePacked(bytes2(data))` to buffer. + +### pBytes3(DynamicBuffer,bytes3) + +```solidity +function pBytes3(DynamicBuffer memory buffer, bytes3 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Appends `abi.encodePacked(bytes3(data))` to buffer. + +### pBytes4(DynamicBuffer,bytes4) + +```solidity +function pBytes4(DynamicBuffer memory buffer, bytes4 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Appends `abi.encodePacked(bytes4(data))` to buffer. + +### pBytes5(DynamicBuffer,bytes5) + +```solidity +function pBytes5(DynamicBuffer memory buffer, bytes5 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Appends `abi.encodePacked(bytes5(data))` to buffer. + +### pBytes6(DynamicBuffer,bytes6) + +```solidity +function pBytes6(DynamicBuffer memory buffer, bytes6 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Appends `abi.encodePacked(bytes6(data))` to buffer. + +### pBytes7(DynamicBuffer,bytes7) + +```solidity +function pBytes7(DynamicBuffer memory buffer, bytes7 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Appends `abi.encodePacked(bytes7(data))` to buffer. + +### pBytes8(DynamicBuffer,bytes8) + +```solidity +function pBytes8(DynamicBuffer memory buffer, bytes8 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Appends `abi.encodePacked(bytes8(data))` to buffer. + +### pBytes9(DynamicBuffer,bytes9) + +```solidity +function pBytes9(DynamicBuffer memory buffer, bytes9 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Appends `abi.encodePacked(bytes9(data))` to buffer. + +### pBytes10(DynamicBuffer,bytes10) + +```solidity +function pBytes10(DynamicBuffer memory buffer, bytes10 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Appends `abi.encodePacked(bytes10(data))` to buffer. + +### pBytes11(DynamicBuffer,bytes11) + +```solidity +function pBytes11(DynamicBuffer memory buffer, bytes11 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Appends `abi.encodePacked(bytes11(data))` to buffer. + +### pBytes12(DynamicBuffer,bytes12) + +```solidity +function pBytes12(DynamicBuffer memory buffer, bytes12 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Appends `abi.encodePacked(bytes12(data))` to buffer. + +### pBytes13(DynamicBuffer,bytes13) + +```solidity +function pBytes13(DynamicBuffer memory buffer, bytes13 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Appends `abi.encodePacked(bytes13(data))` to buffer. + +### pBytes14(DynamicBuffer,bytes14) + +```solidity +function pBytes14(DynamicBuffer memory buffer, bytes14 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Appends `abi.encodePacked(bytes14(data))` to buffer. + +### pBytes15(DynamicBuffer,bytes15) + +```solidity +function pBytes15(DynamicBuffer memory buffer, bytes15 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Appends `abi.encodePacked(bytes15(data))` to buffer. + +### pBytes16(DynamicBuffer,bytes16) + +```solidity +function pBytes16(DynamicBuffer memory buffer, bytes16 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Appends `abi.encodePacked(bytes16(data))` to buffer. + +### pBytes17(DynamicBuffer,bytes17) + +```solidity +function pBytes17(DynamicBuffer memory buffer, bytes17 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Appends `abi.encodePacked(bytes17(data))` to buffer. + +### pBytes18(DynamicBuffer,bytes18) + +```solidity +function pBytes18(DynamicBuffer memory buffer, bytes18 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Appends `abi.encodePacked(bytes18(data))` to buffer. + +### pBytes19(DynamicBuffer,bytes19) + +```solidity +function pBytes19(DynamicBuffer memory buffer, bytes19 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Appends `abi.encodePacked(bytes19(data))` to buffer. + +### pBytes20(DynamicBuffer,bytes20) + +```solidity +function pBytes20(DynamicBuffer memory buffer, bytes20 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Appends `abi.encodePacked(bytes20(data))` to buffer. + +### pBytes21(DynamicBuffer,bytes21) + +```solidity +function pBytes21(DynamicBuffer memory buffer, bytes21 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Appends `abi.encodePacked(bytes21(data))` to buffer. + +### pBytes22(DynamicBuffer,bytes22) + +```solidity +function pBytes22(DynamicBuffer memory buffer, bytes22 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Appends `abi.encodePacked(bytes22(data))` to buffer. + +### pBytes23(DynamicBuffer,bytes23) + +```solidity +function pBytes23(DynamicBuffer memory buffer, bytes23 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Appends `abi.encodePacked(bytes23(data))` to buffer. + +### pBytes24(DynamicBuffer,bytes24) + +```solidity +function pBytes24(DynamicBuffer memory buffer, bytes24 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Appends `abi.encodePacked(bytes24(data))` to buffer. + +### pBytes25(DynamicBuffer,bytes25) + +```solidity +function pBytes25(DynamicBuffer memory buffer, bytes25 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Appends `abi.encodePacked(bytes25(data))` to buffer. + +### pBytes26(DynamicBuffer,bytes26) + +```solidity +function pBytes26(DynamicBuffer memory buffer, bytes26 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Appends `abi.encodePacked(bytes26(data))` to buffer. + +### pBytes27(DynamicBuffer,bytes27) + +```solidity +function pBytes27(DynamicBuffer memory buffer, bytes27 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Appends `abi.encodePacked(bytes27(data))` to buffer. + +### pBytes28(DynamicBuffer,bytes28) + +```solidity +function pBytes28(DynamicBuffer memory buffer, bytes28 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Appends `abi.encodePacked(bytes28(data))` to buffer. + +### pBytes29(DynamicBuffer,bytes29) + +```solidity +function pBytes29(DynamicBuffer memory buffer, bytes29 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Appends `abi.encodePacked(bytes29(data))` to buffer. + +### pBytes30(DynamicBuffer,bytes30) + +```solidity +function pBytes30(DynamicBuffer memory buffer, bytes30 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Appends `abi.encodePacked(bytes30(data))` to buffer. + +### pBytes31(DynamicBuffer,bytes31) + +```solidity +function pBytes31(DynamicBuffer memory buffer, bytes31 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Appends `abi.encodePacked(bytes31(data))` to buffer. + +### pBytes32(DynamicBuffer,bytes32) + +```solidity +function pBytes32(DynamicBuffer memory buffer, bytes32 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Appends `abi.encodePacked(bytes32(data))` to buffer. + +### p() + +```solidity +function p() internal pure returns (DynamicBuffer memory result) +``` + +Shorthand for returning a new buffer. + +### p(bytes) + +```solidity +function p(bytes memory data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Shorthand for `p(p(), data)`. + +### p(bytes,bytes) + +```solidity +function p(bytes memory data0, bytes memory data1) + internal + pure + returns (DynamicBuffer memory result) +``` + +Shorthand for `p(p(), data0, data1)`. + +### p(bytes,bytes,bytes) + +```solidity +function p(bytes memory data0, bytes memory data1, bytes memory data2) + internal + pure + returns (DynamicBuffer memory result) +``` + +Shorthand for `p(p(), data0, .., data2)`. + +### p(bytes,bytes,bytes,bytes) + +```solidity +function p( + bytes memory data0, + bytes memory data1, + bytes memory data2, + bytes memory data3 +) internal pure returns (DynamicBuffer memory result) +``` + +Shorthand for `p(p(), data0, .., data3)`. + +### p(bytes,bytes,bytes,bytes,bytes) + +```solidity +function p( + bytes memory data0, + bytes memory data1, + bytes memory data2, + bytes memory data3, + bytes memory data4 +) internal pure returns (DynamicBuffer memory result) +``` + +Shorthand for `p(p(), data0, .., data4)`. + +### p(bytes,bytes,bytes,bytes,bytes,bytes) + +```solidity +function p( + bytes memory data0, + bytes memory data1, + bytes memory data2, + bytes memory data3, + bytes memory data4, + bytes memory data5 +) internal pure returns (DynamicBuffer memory result) +``` + +Shorthand for `p(p(), data0, .., data5)`. + +### p(bytes,bytes,bytes,bytes,bytes,bytes,bytes) + +```solidity +function p( + bytes memory data0, + bytes memory data1, + bytes memory data2, + bytes memory data3, + bytes memory data4, + bytes memory data5, + bytes memory data6 +) internal pure returns (DynamicBuffer memory result) +``` + +Shorthand for `p(p(), data0, .., data6)`. + +### pBool(bool) + +```solidity +function pBool(bool data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Shorthand for `pBool(p(), data)`. + +### pAddress(address) + +```solidity +function pAddress(address data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Shorthand for `pAddress(p(), data)`. + +### pUint8(uint8) + +```solidity +function pUint8(uint8 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Shorthand for `pUint8(p(), data)`. + +### pUint16(uint16) + +```solidity +function pUint16(uint16 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Shorthand for `pUint16(p(), data)`. + +### pUint24(uint24) + +```solidity +function pUint24(uint24 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Shorthand for `pUint24(p(), data)`. + +### pUint32(uint32) + +```solidity +function pUint32(uint32 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Shorthand for `pUint32(p(), data)`. + +### pUint40(uint40) + +```solidity +function pUint40(uint40 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Shorthand for `pUint40(p(), data)`. + +### pUint48(uint48) + +```solidity +function pUint48(uint48 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Shorthand for `pUint48(p(), data)`. + +### pUint56(uint56) + +```solidity +function pUint56(uint56 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Shorthand for `pUint56(p(), data)`. + +### pUint64(uint64) + +```solidity +function pUint64(uint64 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Shorthand for `pUint64(p(), data)`. + +### pUint72(uint72) + +```solidity +function pUint72(uint72 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Shorthand for `pUint72(p(), data)`. + +### pUint80(uint80) + +```solidity +function pUint80(uint80 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Shorthand for `pUint80(p(), data)`. + +### pUint88(uint88) + +```solidity +function pUint88(uint88 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Shorthand for `pUint88(p(), data)`. + +### pUint96(uint96) + +```solidity +function pUint96(uint96 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Shorthand for `pUint96(p(), data)`. + +### pUint104(uint104) + +```solidity +function pUint104(uint104 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Shorthand for `pUint104(p(), data)`. + +### pUint112(uint112) + +```solidity +function pUint112(uint112 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Shorthand for `pUint112(p(), data)`. + +### pUint120(uint120) + +```solidity +function pUint120(uint120 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Shorthand for `pUint120(p(), data)`. + +### pUint128(uint128) + +```solidity +function pUint128(uint128 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Shorthand for `pUint128(p(), data)`. + +### pUint136(uint136) + +```solidity +function pUint136(uint136 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Shorthand for `pUint136(p(), data)`. + +### pUint144(uint144) + +```solidity +function pUint144(uint144 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Shorthand for `pUint144(p(), data)`. + +### pUint152(uint152) + +```solidity +function pUint152(uint152 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Shorthand for `pUint152(p(), data)`. + +### pUint160(uint160) + +```solidity +function pUint160(uint160 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Shorthand for `pUint160(p(), data)`. + +### pUint168(uint168) + +```solidity +function pUint168(uint168 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Shorthand for `pUint168(p(), data)`. + +### pUint176(uint176) + +```solidity +function pUint176(uint176 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Shorthand for `pUint176(p(), data)`. + +### pUint184(uint184) + +```solidity +function pUint184(uint184 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Shorthand for `pUint184(p(), data)`. + +### pUint192(uint192) + +```solidity +function pUint192(uint192 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Shorthand for `pUint192(p(), data)`. + +### pUint200(uint200) + +```solidity +function pUint200(uint200 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Shorthand for `pUint200(p(), data)`. + +### pUint208(uint208) + +```solidity +function pUint208(uint208 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Shorthand for `pUint208(p(), data)`. + +### pUint216(uint216) + +```solidity +function pUint216(uint216 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Shorthand for `pUint216(p(), data)`. + +### pUint224(uint224) + +```solidity +function pUint224(uint224 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Shorthand for `pUint224(p(), data)`. + +### pUint232(uint232) + +```solidity +function pUint232(uint232 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Shorthand for `pUint232(p(), data)`. + +### pUint240(uint240) + +```solidity +function pUint240(uint240 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Shorthand for `pUint240(p(), data)`. + +### pUint248(uint248) + +```solidity +function pUint248(uint248 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Shorthand for `pUint248(p(), data)`. + +### pUint256(uint256) + +```solidity +function pUint256(uint256 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Shorthand for `pUint256(p(), data)`. + +### pBytes1(bytes1) + +```solidity +function pBytes1(bytes1 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Shorthand for `pBytes1(p(), data)`. + +### pBytes2(bytes2) + +```solidity +function pBytes2(bytes2 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Shorthand for `pBytes2(p(), data)`. + +### pBytes3(bytes3) + +```solidity +function pBytes3(bytes3 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Shorthand for `pBytes3(p(), data)`. + +### pBytes4(bytes4) + +```solidity +function pBytes4(bytes4 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Shorthand for `pBytes4(p(), data)`. + +### pBytes5(bytes5) + +```solidity +function pBytes5(bytes5 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Shorthand for `pBytes5(p(), data)`. + +### pBytes6(bytes6) + +```solidity +function pBytes6(bytes6 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Shorthand for `pBytes6(p(), data)`. + +### pBytes7(bytes7) + +```solidity +function pBytes7(bytes7 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Shorthand for `pBytes7(p(), data)`. + +### pBytes8(bytes8) + +```solidity +function pBytes8(bytes8 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Shorthand for `pBytes8(p(), data)`. + +### pBytes9(bytes9) + +```solidity +function pBytes9(bytes9 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Shorthand for `pBytes9(p(), data)`. + +### pBytes10(bytes10) + +```solidity +function pBytes10(bytes10 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Shorthand for `pBytes10(p(), data)`. + +### pBytes11(bytes11) + +```solidity +function pBytes11(bytes11 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Shorthand for `pBytes11(p(), data)`. + +### pBytes12(bytes12) + +```solidity +function pBytes12(bytes12 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Shorthand for `pBytes12(p(), data)`. + +### pBytes13(bytes13) + +```solidity +function pBytes13(bytes13 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Shorthand for `pBytes13(p(), data)`. + +### pBytes14(bytes14) + +```solidity +function pBytes14(bytes14 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Shorthand for `pBytes14(p(), data)`. + +### pBytes15(bytes15) + +```solidity +function pBytes15(bytes15 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Shorthand for `pBytes15(p(), data)`. + +### pBytes16(bytes16) + +```solidity +function pBytes16(bytes16 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Shorthand for `pBytes16(p(), data)`. + +### pBytes17(bytes17) + +```solidity +function pBytes17(bytes17 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Shorthand for `pBytes17(p(), data)`. + +### pBytes18(bytes18) + +```solidity +function pBytes18(bytes18 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Shorthand for `pBytes18(p(), data)`. + +### pBytes19(bytes19) + +```solidity +function pBytes19(bytes19 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Shorthand for `pBytes19(p(), data)`. + +### pBytes20(bytes20) + +```solidity +function pBytes20(bytes20 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Shorthand for `pBytes20(p(), data)`. + +### pBytes21(bytes21) + +```solidity +function pBytes21(bytes21 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Shorthand for `pBytes21(p(), data)`. + +### pBytes22(bytes22) + +```solidity +function pBytes22(bytes22 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Shorthand for `pBytes22(p(), data)`. + +### pBytes23(bytes23) + +```solidity +function pBytes23(bytes23 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Shorthand for `pBytes23(p(), data)`. + +### pBytes24(bytes24) + +```solidity +function pBytes24(bytes24 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Shorthand for `pBytes24(p(), data)`. + +### pBytes25(bytes25) + +```solidity +function pBytes25(bytes25 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Shorthand for `pBytes25(p(), data)`. + +### pBytes26(bytes26) + +```solidity +function pBytes26(bytes26 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Shorthand for `pBytes26(p(), data)`. + +### pBytes27(bytes27) + +```solidity +function pBytes27(bytes27 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Shorthand for `pBytes27(p(), data)`. + +### pBytes28(bytes28) + +```solidity +function pBytes28(bytes28 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Shorthand for `pBytes28(p(), data)`. + +### pBytes29(bytes29) + +```solidity +function pBytes29(bytes29 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Shorthand for `pBytes29(p(), data)`. + +### pBytes30(bytes30) + +```solidity +function pBytes30(bytes30 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Shorthand for `pBytes30(p(), data)`. + +### pBytes31(bytes31) + +```solidity +function pBytes31(bytes31 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Shorthand for `pBytes31(p(), data)`. + +### pBytes32(bytes32) + +```solidity +function pBytes32(bytes32 data) + internal + pure + returns (DynamicBuffer memory result) +``` + +Shorthand for `pBytes32(p(), data)`. \ No newline at end of file diff --git a/docs/utils/ecdsa.md b/docs/utils/ecdsa.md new file mode 100644 index 000000000..deee74fce --- /dev/null +++ b/docs/utils/ecdsa.md @@ -0,0 +1,248 @@ +# ECDSA + +Gas optimized ECDSA wrapper. + + +Note: + +- The recovery functions use the ecrecover precompile (0x1). +- As of Solady version 0.0.68, the `recover` variants will revert upon recovery failure. +This is for more safety by default. +Use the `tryRecover` variants if you need to get the zero address back +upon recovery failure instead. +- As of Solady version 0.0.134, all `bytes signature` variants accept both +regular 65-byte `(r, s, v)` and EIP-2098 `(r, vs)` short form signatures. +See: https://eips.ethereum.org/EIPS/eip-2098 +This is for calldata efficiency on smart accounts prevalent on L2s. + +WARNING! Do NOT directly use signatures as unique identifiers: +- The recovery operations do NOT check if a signature is non-malleable. +- Use a nonce in the digest to prevent replay attacks on the same contract. +- Use EIP-712 for the digest to prevent replay attacks across different chains and contracts. +EIP-712 also enables readable signing of typed data for better user safety. +- If you need a unique hash from a signature, please use the `canonicalHash` functions. + + + + + +## Constants + +### N + +```solidity +uint256 internal constant N = + 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141 +``` + +The order of the secp256k1 elliptic curve. + +## Custom Errors + +### InvalidSignature() + +```solidity +error InvalidSignature() +``` + +The signature is invalid. + +## Recovery Operations + +### recover(bytes32,bytes) + +```solidity +function recover(bytes32 hash, bytes memory signature) + internal + view + returns (address result) +``` + +Recovers the signer's address from a message digest `hash`, and the `signature`. + +### recoverCalldata(bytes32,bytes) + +```solidity +function recoverCalldata(bytes32 hash, bytes calldata signature) + internal + view + returns (address result) +``` + +Recovers the signer's address from a message digest `hash`, and the `signature`. + +### recover(bytes32,bytes32,bytes32) + +```solidity +function recover(bytes32 hash, bytes32 r, bytes32 vs) + internal + view + returns (address result) +``` + +Recovers the signer's address from a message digest `hash`, +and the EIP-2098 short form signature defined by `r` and `vs`. + +### recover(bytes32,uint8,bytes32,bytes32) + +```solidity +function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) + internal + view + returns (address result) +``` + +Recovers the signer's address from a message digest `hash`, +and the signature defined by `v`, `r`, `s`. + +## Try-recover Operations + +WARNING! +These functions will NOT revert upon recovery failure. +Instead, they will return the zero address upon recovery failure. +It is critical that the returned address is NEVER compared against +a zero address (e.g. an uninitialized address variable). + +### tryRecover(bytes32,bytes) + +```solidity +function tryRecover(bytes32 hash, bytes memory signature) + internal + view + returns (address result) +``` + +Recovers the signer's address from a message digest `hash`, and the `signature`. + +### tryRecoverCalldata(bytes32,bytes) + +```solidity +function tryRecoverCalldata(bytes32 hash, bytes calldata signature) + internal + view + returns (address result) +``` + +Recovers the signer's address from a message digest `hash`, and the `signature`. + +### tryRecover(bytes32,bytes32,bytes32) + +```solidity +function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) + internal + view + returns (address result) +``` + +Recovers the signer's address from a message digest `hash`, +and the EIP-2098 short form signature defined by `r` and `vs`. + +### tryRecover(bytes32,uint8,bytes32,bytes32) + +```solidity +function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) + internal + view + returns (address result) +``` + +Recovers the signer's address from a message digest `hash`, +and the signature defined by `v`, `r`, `s`. + +## Hashing Operations + +### toEthSignedMessageHash(bytes32) + +```solidity +function toEthSignedMessageHash(bytes32 hash) + internal + pure + returns (bytes32 result) +``` + +Returns an Ethereum Signed Message, created from a `hash`. +This produces a hash corresponding to the one signed with the +[`eth_sign`](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_sign) +JSON-RPC method as part of EIP-191. + +### toEthSignedMessageHash(bytes) + +```solidity +function toEthSignedMessageHash(bytes memory s) + internal + pure + returns (bytes32 result) +``` + +Returns an Ethereum Signed Message, created from `s`. +This produces a hash corresponding to the one signed with the +[`eth_sign`](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_sign) +JSON-RPC method as part of EIP-191. +Note: Supports lengths of `s` up to 999999 bytes. + +## Canonical Hash Functions + +The following functions returns the hash of the signature in it's canonicalized format, +which is the 65-byte `abi.encodePacked(r, s, uint8(v))`, where `v` is either 27 or 28. +If `s` is greater than `N / 2` then it will be converted to `N - s` +and the `v` value will be flipped. +If the signature has an invalid length, or if `v` is invalid, +a uniquely corrupt hash will be returned. +These functions are useful for "poor-mans-VRF". + +### canonicalHash(bytes) + +```solidity +function canonicalHash(bytes memory signature) + internal + pure + returns (bytes32 result) +``` + +Returns the canonical hash of `signature`. + +### canonicalHashCalldata(bytes) + +```solidity +function canonicalHashCalldata(bytes calldata signature) + internal + pure + returns (bytes32 result) +``` + +Returns the canonical hash of `signature`. + +### canonicalHash(bytes32,bytes32) + +```solidity +function canonicalHash(bytes32 r, bytes32 vs) + internal + pure + returns (bytes32 result) +``` + +Returns the canonical hash of `signature`. + +### canonicalHash(uint8,bytes32,bytes32) + +```solidity +function canonicalHash(uint8 v, bytes32 r, bytes32 s) + internal + pure + returns (bytes32 result) +``` + +Returns the canonical hash of `signature`. + +## Empty Calldata Helpers + +### emptySignature() + +```solidity +function emptySignature() + internal + pure + returns (bytes calldata signature) +``` + +Returns an empty calldata bytes. \ No newline at end of file diff --git a/docs/utils/efficienthashlib.md b/docs/utils/efficienthashlib.md new file mode 100644 index 000000000..7ce49ec78 --- /dev/null +++ b/docs/utils/efficienthashlib.md @@ -0,0 +1,689 @@ +# EfficientHashLib + +Library for efficiently performing keccak256 hashes. + + +To avoid stack-too-deep, you can use: + +``` +bytes32[] memory buffer = EfficientHashLib.malloc(10); +EfficientHashLib.set(buffer, 0, value0); +.. +EfficientHashLib.set(buffer, 9, value9); +bytes32 finalHash = EfficientHashLib.hash(buffer); +``` + + + + + +## Malloc-less Hashing Operations + +### hash(bytes32) + +```solidity +function hash(bytes32 v0) internal pure returns (bytes32 result) +``` + +Returns `keccak256(abi.encode(v0))`. + +### hash(uint256) + +```solidity +function hash(uint256 v0) internal pure returns (bytes32 result) +``` + +Returns `keccak256(abi.encode(v0))`. + +### hash(bytes32,bytes32) + +```solidity +function hash(bytes32 v0, bytes32 v1) + internal + pure + returns (bytes32 result) +``` + +Returns `keccak256(abi.encode(v0, v1))`. + +### hash(uint256,uint256) + +```solidity +function hash(uint256 v0, uint256 v1) + internal + pure + returns (bytes32 result) +``` + +Returns `keccak256(abi.encode(v0, v1))`. + +### hash(bytes32,bytes32,bytes32) + +```solidity +function hash(bytes32 v0, bytes32 v1, bytes32 v2) + internal + pure + returns (bytes32 result) +``` + +Returns `keccak256(abi.encode(v0, v1, v2))`. + +### hash(uint256,uint256,uint256) + +```solidity +function hash(uint256 v0, uint256 v1, uint256 v2) + internal + pure + returns (bytes32 result) +``` + +Returns `keccak256(abi.encode(v0, v1, v2))`. + +### hash(bytes32,bytes32,bytes32,bytes32) + +```solidity +function hash(bytes32 v0, bytes32 v1, bytes32 v2, bytes32 v3) + internal + pure + returns (bytes32 result) +``` + +Returns `keccak256(abi.encode(v0, v1, v2, v3))`. + +### hash(uint256,uint256,uint256,uint256) + +```solidity +function hash(uint256 v0, uint256 v1, uint256 v2, uint256 v3) + internal + pure + returns (bytes32 result) +``` + +Returns `keccak256(abi.encode(v0, v1, v2, v3))`. + +### hash(bytes32,bytes32,bytes32,bytes32,bytes32) + +```solidity +function hash(bytes32 v0, bytes32 v1, bytes32 v2, bytes32 v3, bytes32 v4) + internal + pure + returns (bytes32 result) +``` + +Returns `keccak256(abi.encode(v0, .., v4))`. + +### hash(uint256,uint256,uint256,uint256,uint256) + +```solidity +function hash(uint256 v0, uint256 v1, uint256 v2, uint256 v3, uint256 v4) + internal + pure + returns (bytes32 result) +``` + +Returns `keccak256(abi.encode(v0, .., v4))`. + +### hash(bytes32,bytes32,bytes32,bytes32,bytes32,bytes32) + +```solidity +function hash( + bytes32 v0, + bytes32 v1, + bytes32 v2, + bytes32 v3, + bytes32 v4, + bytes32 v5 +) internal pure returns (bytes32 result) +``` + +Returns `keccak256(abi.encode(v0, .., v5))`. + +### hash(uint256,uint256,uint256,uint256,uint256,uint256) + +```solidity +function hash( + uint256 v0, + uint256 v1, + uint256 v2, + uint256 v3, + uint256 v4, + uint256 v5 +) internal pure returns (bytes32 result) +``` + +Returns `keccak256(abi.encode(v0, .., v5))`. + +### hash(bytes32,bytes32,bytes32,bytes32,bytes32,bytes32,bytes32) + +```solidity +function hash( + bytes32 v0, + bytes32 v1, + bytes32 v2, + bytes32 v3, + bytes32 v4, + bytes32 v5, + bytes32 v6 +) internal pure returns (bytes32 result) +``` + +Returns `keccak256(abi.encode(v0, .., v6))`. + +### hash(uint256,uint256,uint256,uint256,uint256,uint256,uint256) + +```solidity +function hash( + uint256 v0, + uint256 v1, + uint256 v2, + uint256 v3, + uint256 v4, + uint256 v5, + uint256 v6 +) internal pure returns (bytes32 result) +``` + +Returns `keccak256(abi.encode(v0, .., v6))`. + +### hash(bytes32,bytes32,bytes32,bytes32,bytes32,bytes32,bytes32,bytes32) + +```solidity +function hash( + bytes32 v0, + bytes32 v1, + bytes32 v2, + bytes32 v3, + bytes32 v4, + bytes32 v5, + bytes32 v6, + bytes32 v7 +) internal pure returns (bytes32 result) +``` + +Returns `keccak256(abi.encode(v0, .., v7))`. + +### hash(uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256) + +```solidity +function hash( + uint256 v0, + uint256 v1, + uint256 v2, + uint256 v3, + uint256 v4, + uint256 v5, + uint256 v6, + uint256 v7 +) internal pure returns (bytes32 result) +``` + +Returns `keccak256(abi.encode(v0, .., v7))`. + +### hash(bytes32,bytes32,bytes32,bytes32,bytes32,bytes32,bytes32,bytes32,bytes32) + +```solidity +function hash( + bytes32 v0, + bytes32 v1, + bytes32 v2, + bytes32 v3, + bytes32 v4, + bytes32 v5, + bytes32 v6, + bytes32 v7, + bytes32 v8 +) internal pure returns (bytes32 result) +``` + +Returns `keccak256(abi.encode(v0, .., v8))`. + +### hash(uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256) + +```solidity +function hash( + uint256 v0, + uint256 v1, + uint256 v2, + uint256 v3, + uint256 v4, + uint256 v5, + uint256 v6, + uint256 v7, + uint256 v8 +) internal pure returns (bytes32 result) +``` + +Returns `keccak256(abi.encode(v0, .., v8))`. + +### hash(bytes32,bytes32,bytes32,bytes32,bytes32,bytes32,bytes32,bytes32,bytes32,bytes32) + +```solidity +function hash( + bytes32 v0, + bytes32 v1, + bytes32 v2, + bytes32 v3, + bytes32 v4, + bytes32 v5, + bytes32 v6, + bytes32 v7, + bytes32 v8, + bytes32 v9 +) internal pure returns (bytes32 result) +``` + +Returns `keccak256(abi.encode(v0, .., v9))`. + +### hash(uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256) + +```solidity +function hash( + uint256 v0, + uint256 v1, + uint256 v2, + uint256 v3, + uint256 v4, + uint256 v5, + uint256 v6, + uint256 v7, + uint256 v8, + uint256 v9 +) internal pure returns (bytes32 result) +``` + +Returns `keccak256(abi.encode(v0, .., v9))`. + +### hash(bytes32,bytes32,bytes32,bytes32,bytes32,bytes32,bytes32,bytes32,bytes32,bytes32,bytes32) + +```solidity +function hash( + bytes32 v0, + bytes32 v1, + bytes32 v2, + bytes32 v3, + bytes32 v4, + bytes32 v5, + bytes32 v6, + bytes32 v7, + bytes32 v8, + bytes32 v9, + bytes32 v10 +) internal pure returns (bytes32 result) +``` + +Returns `keccak256(abi.encode(v0, .., v10))`. + +### hash(uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256) + +```solidity +function hash( + uint256 v0, + uint256 v1, + uint256 v2, + uint256 v3, + uint256 v4, + uint256 v5, + uint256 v6, + uint256 v7, + uint256 v8, + uint256 v9, + uint256 v10 +) internal pure returns (bytes32 result) +``` + +Returns `keccak256(abi.encode(v0, .., v10))`. + +### hash(bytes32,bytes32,bytes32,bytes32,bytes32,bytes32,bytes32,bytes32,bytes32,bytes32,bytes32,bytes32) + +```solidity +function hash( + bytes32 v0, + bytes32 v1, + bytes32 v2, + bytes32 v3, + bytes32 v4, + bytes32 v5, + bytes32 v6, + bytes32 v7, + bytes32 v8, + bytes32 v9, + bytes32 v10, + bytes32 v11 +) internal pure returns (bytes32 result) +``` + +Returns `keccak256(abi.encode(v0, .., v11))`. + +### hash(uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256) + +```solidity +function hash( + uint256 v0, + uint256 v1, + uint256 v2, + uint256 v3, + uint256 v4, + uint256 v5, + uint256 v6, + uint256 v7, + uint256 v8, + uint256 v9, + uint256 v10, + uint256 v11 +) internal pure returns (bytes32 result) +``` + +Returns `keccak256(abi.encode(v0, .., v11))`. + +### hash(bytes32,bytes32,bytes32,bytes32,bytes32,bytes32,bytes32,bytes32,bytes32,bytes32,bytes32,bytes32,bytes32) + +```solidity +function hash( + bytes32 v0, + bytes32 v1, + bytes32 v2, + bytes32 v3, + bytes32 v4, + bytes32 v5, + bytes32 v6, + bytes32 v7, + bytes32 v8, + bytes32 v9, + bytes32 v10, + bytes32 v11, + bytes32 v12 +) internal pure returns (bytes32 result) +``` + +Returns `keccak256(abi.encode(v0, .., v12))`. + +### hash(uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256) + +```solidity +function hash( + uint256 v0, + uint256 v1, + uint256 v2, + uint256 v3, + uint256 v4, + uint256 v5, + uint256 v6, + uint256 v7, + uint256 v8, + uint256 v9, + uint256 v10, + uint256 v11, + uint256 v12 +) internal pure returns (bytes32 result) +``` + +Returns `keccak256(abi.encode(v0, .., v12))`. + +### hash(bytes32,bytes32,bytes32,bytes32,bytes32,bytes32,bytes32,bytes32,bytes32,bytes32,bytes32,bytes32,bytes32,bytes32) + +```solidity +function hash( + bytes32 v0, + bytes32 v1, + bytes32 v2, + bytes32 v3, + bytes32 v4, + bytes32 v5, + bytes32 v6, + bytes32 v7, + bytes32 v8, + bytes32 v9, + bytes32 v10, + bytes32 v11, + bytes32 v12, + bytes32 v13 +) internal pure returns (bytes32 result) +``` + +Returns `keccak256(abi.encode(v0, .., v13))`. + +### hash(uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256,uint256) + +```solidity +function hash( + uint256 v0, + uint256 v1, + uint256 v2, + uint256 v3, + uint256 v4, + uint256 v5, + uint256 v6, + uint256 v7, + uint256 v8, + uint256 v9, + uint256 v10, + uint256 v11, + uint256 v12, + uint256 v13 +) internal pure returns (bytes32 result) +``` + +Returns `keccak256(abi.encode(v0, .., v13))`. + +## Bytes32 Buffer Hashing Operations + +### hash(bytes32[]) + +```solidity +function hash(bytes32[] memory buffer) + internal + pure + returns (bytes32 result) +``` + +Returns `keccak256(abi.encode(buffer[0], .., buffer[buffer.length - 1]))`. + +### set(bytes32[],uint256,bytes32) + +```solidity +function set(bytes32[] memory buffer, uint256 i, bytes32 value) + internal + pure + returns (bytes32[] memory) +``` + +Sets `buffer[i]` to `value`, without a bounds check. +Returns the `buffer` for function chaining. + +### set(bytes32[],uint256,uint256) + +```solidity +function set(bytes32[] memory buffer, uint256 i, uint256 value) + internal + pure + returns (bytes32[] memory) +``` + +Sets `buffer[i]` to `value`, without a bounds check. +Returns the `buffer` for function chaining. + +### malloc(uint256) + +```solidity +function malloc(uint256 n) + internal + pure + returns (bytes32[] memory buffer) +``` + +Returns `new bytes32[](n)`, without zeroing out the memory. + +### free(bytes32[]) + +```solidity +function free(bytes32[] memory buffer) internal pure +``` + +Frees memory that has been allocated for `buffer`. +No-op if `buffer.length` is zero, or if new memory has been allocated after `buffer`. + +## Equality Checks + +### eq(bytes32,bytes) + +```solidity +function eq(bytes32 a, bytes memory b) + internal + pure + returns (bool result) +``` + +Returns `a == abi.decode(b, (bytes32))`. + +### eq(bytes,bytes32) + +```solidity +function eq(bytes memory a, bytes32 b) + internal + pure + returns (bool result) +``` + +Returns `abi.decode(a, (bytes32)) == a`. + +## Byte Slice Hashing Operations + +### hash(bytes,uint256,uint256) + +```solidity +function hash(bytes memory b, uint256 start, uint256 end) + internal + pure + returns (bytes32 result) +``` + +Returns the keccak256 of the slice from `start` to `end` (exclusive). +`start` and `end` are byte offsets. + +### hash(bytes,uint256) + +```solidity +function hash(bytes memory b, uint256 start) + internal + pure + returns (bytes32 result) +``` + +Returns the keccak256 of the slice from `start` to the end of the bytes. + +### hash(bytes) + +```solidity +function hash(bytes memory b) internal pure returns (bytes32 result) +``` + +Returns the keccak256 of the bytes. + +### hashCalldata(bytes,uint256,uint256) + +```solidity +function hashCalldata(bytes calldata b, uint256 start, uint256 end) + internal + pure + returns (bytes32 result) +``` + +Returns the keccak256 of the slice from `start` to `end` (exclusive). +`start` and `end` are byte offsets. + +### hashCalldata(bytes,uint256) + +```solidity +function hashCalldata(bytes calldata b, uint256 start) + internal + pure + returns (bytes32 result) +``` + +Returns the keccak256 of the slice from `start` to the end of the bytes. + +### hashCalldata(bytes) + +```solidity +function hashCalldata(bytes calldata b) + internal + pure + returns (bytes32 result) +``` + +Returns the keccak256 of the bytes. + +## SHA2-256 Helpers + +### sha2(bytes32) + +```solidity +function sha2(bytes32 b) internal view returns (bytes32 result) +``` + +Returns `sha256(abi.encode(b))`. Yes, it's more efficient. + +### sha2(bytes,uint256,uint256) + +```solidity +function sha2(bytes memory b, uint256 start, uint256 end) + internal + view + returns (bytes32 result) +``` + +Returns the sha256 of the slice from `start` to `end` (exclusive). +`start` and `end` are byte offsets. + +### sha2(bytes,uint256) + +```solidity +function sha2(bytes memory b, uint256 start) + internal + view + returns (bytes32 result) +``` + +Returns the sha256 of the slice from `start` to the end of the bytes. + +### sha2(bytes) + +```solidity +function sha2(bytes memory b) internal view returns (bytes32 result) +``` + +Returns the sha256 of the bytes. + +### sha2Calldata(bytes,uint256,uint256) + +```solidity +function sha2Calldata(bytes calldata b, uint256 start, uint256 end) + internal + view + returns (bytes32 result) +``` + +Returns the sha256 of the slice from `start` to `end` (exclusive). +`start` and `end` are byte offsets. + +### sha2Calldata(bytes,uint256) + +```solidity +function sha2Calldata(bytes calldata b, uint256 start) + internal + view + returns (bytes32 result) +``` + +Returns the sha256 of the slice from `start` to the end of the bytes. + +### sha2Calldata(bytes) + +```solidity +function sha2Calldata(bytes calldata b) + internal + view + returns (bytes32 result) +``` + +Returns the sha256 of the bytes. \ No newline at end of file diff --git a/docs/utils/eip712.md b/docs/utils/eip712.md new file mode 100644 index 000000000..aa1cf0128 --- /dev/null +++ b/docs/utils/eip712.md @@ -0,0 +1,86 @@ +# EIP712 + +Contract for EIP-712 typed structured data hashing and signing. + + +Note, this implementation: + +- Uses `address(this)` for the `verifyingContract` field. +- Does NOT use the optional EIP-712 salt. +- Does NOT use any EIP-712 extensions. +This is for simplicity and to save gas. +If you need to customize, please fork / modify accordingly. + + + + + +## Constants And Immutables + +### _DOMAIN_TYPEHASH + +```solidity +bytes32 internal constant _DOMAIN_TYPEHASH = + 0x8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f +``` + +`keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)")`. + +## Hashing Operations + +### _domainSeparator() + +```solidity +function _domainSeparator() + internal + view + virtual + returns (bytes32 separator) +``` + +Returns the EIP-712 domain separator. + +### _hashTypedData(bytes32) + +```solidity +function _hashTypedData(bytes32 structHash) + internal + view + virtual + returns (bytes32 digest) +``` + +Returns the hash of the fully encoded EIP-712 message for this domain, +given `structHash`, as defined in +https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct. +The hash can be used together with {ECDSA-recover} to obtain the signer of a message: +```solidity +bytes32 digest = _hashTypedData(keccak256(abi.encode( + keccak256("Mail(address to,string contents)"), + mailTo, + keccak256(bytes(mailContents)) +))); +address signer = ECDSA.recover(digest, signature); +``` + +## EIP-5267 Operations + +### eip712Domain() + +```solidity +function eip712Domain() + public + view + virtual + returns ( + bytes1 fields, + string memory name, + string memory version, + uint256 chainId, + address verifyingContract, + bytes32 salt, + uint256[] memory extensions + ) +``` + +See: https://eips.ethereum.org/EIPS/eip-5267 \ No newline at end of file diff --git a/docs/utils/enumerablemaplib.md b/docs/utils/enumerablemaplib.md new file mode 100644 index 000000000..fa84ca898 --- /dev/null +++ b/docs/utils/enumerablemaplib.md @@ -0,0 +1,915 @@ +# EnumerableMapLib + +Library for managing enumerable maps in storage. + + + + + + + + +## Custom Errors + +### EnumerableMapKeyNotFound() + +```solidity +error EnumerableMapKeyNotFound() +``` + +The key does not exist in the enumerable map. + +## Structs + +### Bytes32ToBytes32Map + +```solidity +struct Bytes32ToBytes32Map { + EnumerableSetLib.Bytes32Set _keys; + mapping(bytes32 => bytes32) _values; +} +``` + +A enumerable map of `bytes32` to `bytes32`. + +### Bytes32ToUint256Map + +```solidity +struct Bytes32ToUint256Map { + EnumerableSetLib.Bytes32Set _keys; + mapping(bytes32 => uint256) _values; +} +``` + +A enumerable map of `bytes32` to `uint256`. + +### Bytes32ToAddressMap + +```solidity +struct Bytes32ToAddressMap { + EnumerableSetLib.Bytes32Set _keys; + mapping(bytes32 => address) _values; +} +``` + +A enumerable map of `bytes32` to `address`. + +### Uint256ToBytes32Map + +```solidity +struct Uint256ToBytes32Map { + EnumerableSetLib.Uint256Set _keys; + mapping(uint256 => bytes32) _values; +} +``` + +A enumerable map of `uint256` to `bytes32`. + +### Uint256ToUint256Map + +```solidity +struct Uint256ToUint256Map { + EnumerableSetLib.Uint256Set _keys; + mapping(uint256 => uint256) _values; +} +``` + +A enumerable map of `uint256` to `uint256`. + +### Uint256ToAddressMap + +```solidity +struct Uint256ToAddressMap { + EnumerableSetLib.Uint256Set _keys; + mapping(uint256 => address) _values; +} +``` + +A enumerable map of `uint256` to `address`. + +### AddressToBytes32Map + +```solidity +struct AddressToBytes32Map { + EnumerableSetLib.AddressSet _keys; + mapping(address => bytes32) _values; +} +``` + +A enumerable map of `address` to `bytes32`. + +### AddressToUint256Map + +```solidity +struct AddressToUint256Map { + EnumerableSetLib.AddressSet _keys; + mapping(address => uint256) _values; +} +``` + +A enumerable map of `address` to `uint256`. + +### AddressToAddressMap + +```solidity +struct AddressToAddressMap { + EnumerableSetLib.AddressSet _keys; + mapping(address => address) _values; +} +``` + +A enumerable map of `address` to `address`. + +## Getters / Setters + +### set(Bytes32ToBytes32Map,bytes32,bytes32) + +```solidity +function set(Bytes32ToBytes32Map storage map, bytes32 key, bytes32 value) + internal + returns (bool) +``` + +Adds a key-value pair to the map, or updates the value for an existing key. +Returns true if `key` was added to the map, that is if it was not already present. + +### remove(Bytes32ToBytes32Map,bytes32) + +```solidity +function remove(Bytes32ToBytes32Map storage map, bytes32 key) + internal + returns (bool) +``` + +Removes a key-value pair from the map. +Returns true if `key` was removed from the map, that is if it was present. + +### contains(Bytes32ToBytes32Map,bytes32) + +```solidity +function contains(Bytes32ToBytes32Map storage map, bytes32 key) + internal + view + returns (bool) +``` + +Returns true if the key is in the map. + +### length(Bytes32ToBytes32Map) + +```solidity +function length(Bytes32ToBytes32Map storage map) + internal + view + returns (uint256) +``` + +Returns the number of key-value pairs in the map. + +### at(Bytes32ToBytes32Map,uint256) + +```solidity +function at(Bytes32ToBytes32Map storage map, uint256 i) + internal + view + returns (bytes32 key, bytes32 value) +``` + +Returns the key-value pair at index `i`. Reverts if `i` is out-of-bounds. + +### tryGet(Bytes32ToBytes32Map,bytes32) + +```solidity +function tryGet(Bytes32ToBytes32Map storage map, bytes32 key) + internal + view + returns (bool exists, bytes32 value) +``` + +Tries to return the value associated with the key. + +### get(Bytes32ToBytes32Map,bytes32) + +```solidity +function get(Bytes32ToBytes32Map storage map, bytes32 key) + internal + view + returns (bytes32 value) +``` + +Returns the value for the key. Reverts if the key is not found. + +### keys(Bytes32ToBytes32Map) + +```solidity +function keys(Bytes32ToBytes32Map storage map) + internal + view + returns (bytes32[] memory) +``` + +Returns the keys. May run out-of-gas if the map is too big. + +### set(Bytes32ToUint256Map,bytes32,uint256) + +```solidity +function set(Bytes32ToUint256Map storage map, bytes32 key, uint256 value) + internal + returns (bool) +``` + +Adds a key-value pair to the map, or updates the value for an existing key. +Returns true if `key` was added to the map, that is if it was not already present. + +### remove(Bytes32ToUint256Map,bytes32) + +```solidity +function remove(Bytes32ToUint256Map storage map, bytes32 key) + internal + returns (bool) +``` + +Removes a key-value pair from the map. +Returns true if `key` was removed from the map, that is if it was present. + +### contains(Bytes32ToUint256Map,bytes32) + +```solidity +function contains(Bytes32ToUint256Map storage map, bytes32 key) + internal + view + returns (bool) +``` + +Returns true if the key is in the map. + +### length(Bytes32ToUint256Map) + +```solidity +function length(Bytes32ToUint256Map storage map) + internal + view + returns (uint256) +``` + +Returns the number of key-value pairs in the map. + +### at(Bytes32ToUint256Map,uint256) + +```solidity +function at(Bytes32ToUint256Map storage map, uint256 i) + internal + view + returns (bytes32 key, uint256 value) +``` + +Returns the key-value pair at index `i`. Reverts if `i` is out-of-bounds. + +### tryGet(Bytes32ToUint256Map,bytes32) + +```solidity +function tryGet(Bytes32ToUint256Map storage map, bytes32 key) + internal + view + returns (bool exists, uint256 value) +``` + +Tries to return the value associated with the key. + +### get(Bytes32ToUint256Map,bytes32) + +```solidity +function get(Bytes32ToUint256Map storage map, bytes32 key) + internal + view + returns (uint256 value) +``` + +Returns the value for the key. Reverts if the key is not found. + +### keys(Bytes32ToUint256Map) + +```solidity +function keys(Bytes32ToUint256Map storage map) + internal + view + returns (bytes32[] memory) +``` + +Returns the keys. May run out-of-gas if the map is too big. + +### set(Bytes32ToAddressMap,bytes32,address) + +```solidity +function set(Bytes32ToAddressMap storage map, bytes32 key, address value) + internal + returns (bool) +``` + +Adds a key-value pair to the map, or updates the value for an existing key. +Returns true if `key` was added to the map, that is if it was not already present. + +### remove(Bytes32ToAddressMap,bytes32) + +```solidity +function remove(Bytes32ToAddressMap storage map, bytes32 key) + internal + returns (bool) +``` + +Removes a key-value pair from the map. +Returns true if `key` was removed from the map, that is if it was present. + +### contains(Bytes32ToAddressMap,bytes32) + +```solidity +function contains(Bytes32ToAddressMap storage map, bytes32 key) + internal + view + returns (bool) +``` + +Returns true if the key is in the map. + +### length(Bytes32ToAddressMap) + +```solidity +function length(Bytes32ToAddressMap storage map) + internal + view + returns (uint256) +``` + +Returns the number of key-value pairs in the map. + +### at(Bytes32ToAddressMap,uint256) + +```solidity +function at(Bytes32ToAddressMap storage map, uint256 i) + internal + view + returns (bytes32 key, address value) +``` + +Returns the key-value pair at index `i`. Reverts if `i` is out-of-bounds. + +### tryGet(Bytes32ToAddressMap,bytes32) + +```solidity +function tryGet(Bytes32ToAddressMap storage map, bytes32 key) + internal + view + returns (bool exists, address value) +``` + +Tries to return the value associated with the key. + +### get(Bytes32ToAddressMap,bytes32) + +```solidity +function get(Bytes32ToAddressMap storage map, bytes32 key) + internal + view + returns (address value) +``` + +Returns the value for the key. Reverts if the key is not found. + +### keys(Bytes32ToAddressMap) + +```solidity +function keys(Bytes32ToAddressMap storage map) + internal + view + returns (bytes32[] memory) +``` + +Returns the keys. May run out-of-gas if the map is too big. + +### set(Uint256ToBytes32Map,uint256,bytes32) + +```solidity +function set(Uint256ToBytes32Map storage map, uint256 key, bytes32 value) + internal + returns (bool) +``` + +Adds a key-value pair to the map, or updates the value for an existing key. +Returns true if `key` was added to the map, that is if it was not already present. + +### remove(Uint256ToBytes32Map,uint256) + +```solidity +function remove(Uint256ToBytes32Map storage map, uint256 key) + internal + returns (bool) +``` + +Removes a key-value pair from the map. +Returns true if `key` was removed from the map, that is if it was present. + +### contains(Uint256ToBytes32Map,uint256) + +```solidity +function contains(Uint256ToBytes32Map storage map, uint256 key) + internal + view + returns (bool) +``` + +Returns true if the key is in the map. + +### length(Uint256ToBytes32Map) + +```solidity +function length(Uint256ToBytes32Map storage map) + internal + view + returns (uint256) +``` + +Returns the number of key-value pairs in the map. + +### at(Uint256ToBytes32Map,uint256) + +```solidity +function at(Uint256ToBytes32Map storage map, uint256 i) + internal + view + returns (uint256 key, bytes32 value) +``` + +Returns the key-value pair at index `i`. Reverts if `i` is out-of-bounds. + +### tryGet(Uint256ToBytes32Map,uint256) + +```solidity +function tryGet(Uint256ToBytes32Map storage map, uint256 key) + internal + view + returns (bool exists, bytes32 value) +``` + +Tries to return the value associated with the key. + +### get(Uint256ToBytes32Map,uint256) + +```solidity +function get(Uint256ToBytes32Map storage map, uint256 key) + internal + view + returns (bytes32 value) +``` + +Returns the value for the key. Reverts if the key is not found. + +### keys(Uint256ToBytes32Map) + +```solidity +function keys(Uint256ToBytes32Map storage map) + internal + view + returns (uint256[] memory) +``` + +Returns the keys. May run out-of-gas if the map is too big. + +### set(Uint256ToUint256Map,uint256,uint256) + +```solidity +function set(Uint256ToUint256Map storage map, uint256 key, uint256 value) + internal + returns (bool) +``` + +Adds a key-value pair to the map, or updates the value for an existing key. +Returns true if `key` was added to the map, that is if it was not already present. + +### remove(Uint256ToUint256Map,uint256) + +```solidity +function remove(Uint256ToUint256Map storage map, uint256 key) + internal + returns (bool) +``` + +Removes a key-value pair from the map. +Returns true if `key` was removed from the map, that is if it was present. + +### contains(Uint256ToUint256Map,uint256) + +```solidity +function contains(Uint256ToUint256Map storage map, uint256 key) + internal + view + returns (bool) +``` + +Returns true if the key is in the map. + +### length(Uint256ToUint256Map) + +```solidity +function length(Uint256ToUint256Map storage map) + internal + view + returns (uint256) +``` + +Returns the number of key-value pairs in the map. + +### at(Uint256ToUint256Map,uint256) + +```solidity +function at(Uint256ToUint256Map storage map, uint256 i) + internal + view + returns (uint256 key, uint256 value) +``` + +Returns the key-value pair at index `i`. Reverts if `i` is out-of-bounds. + +### tryGet(Uint256ToUint256Map,uint256) + +```solidity +function tryGet(Uint256ToUint256Map storage map, uint256 key) + internal + view + returns (bool exists, uint256 value) +``` + +Tries to return the value associated with the key. + +### get(Uint256ToUint256Map,uint256) + +```solidity +function get(Uint256ToUint256Map storage map, uint256 key) + internal + view + returns (uint256 value) +``` + +Returns the value for the key. Reverts if the key is not found. + +### keys(Uint256ToUint256Map) + +```solidity +function keys(Uint256ToUint256Map storage map) + internal + view + returns (uint256[] memory) +``` + +Returns the keys. May run out-of-gas if the map is too big. + +### set(Uint256ToAddressMap,uint256,address) + +```solidity +function set(Uint256ToAddressMap storage map, uint256 key, address value) + internal + returns (bool) +``` + +Adds a key-value pair to the map, or updates the value for an existing key. +Returns true if `key` was added to the map, that is if it was not already present. + +### remove(Uint256ToAddressMap,uint256) + +```solidity +function remove(Uint256ToAddressMap storage map, uint256 key) + internal + returns (bool) +``` + +Removes a key-value pair from the map. +Returns true if `key` was removed from the map, that is if it was present. + +### contains(Uint256ToAddressMap,uint256) + +```solidity +function contains(Uint256ToAddressMap storage map, uint256 key) + internal + view + returns (bool) +``` + +Returns true if the key is in the map. + +### length(Uint256ToAddressMap) + +```solidity +function length(Uint256ToAddressMap storage map) + internal + view + returns (uint256) +``` + +Returns the number of key-value pairs in the map. + +### at(Uint256ToAddressMap,uint256) + +```solidity +function at(Uint256ToAddressMap storage map, uint256 i) + internal + view + returns (uint256 key, address value) +``` + +Returns the key-value pair at index `i`. Reverts if `i` is out-of-bounds. + +### tryGet(Uint256ToAddressMap,uint256) + +```solidity +function tryGet(Uint256ToAddressMap storage map, uint256 key) + internal + view + returns (bool exists, address value) +``` + +Tries to return the value associated with the key. + +### get(Uint256ToAddressMap,uint256) + +```solidity +function get(Uint256ToAddressMap storage map, uint256 key) + internal + view + returns (address value) +``` + +Returns the value for the key. Reverts if the key is not found. + +### keys(Uint256ToAddressMap) + +```solidity +function keys(Uint256ToAddressMap storage map) + internal + view + returns (uint256[] memory) +``` + +Returns the keys. May run out-of-gas if the map is too big. + +### set(AddressToBytes32Map,address,bytes32) + +```solidity +function set(AddressToBytes32Map storage map, address key, bytes32 value) + internal + returns (bool) +``` + +Adds a key-value pair to the map, or updates the value for an existing key. +Returns true if `key` was added to the map, that is if it was not already present. + +### remove(AddressToBytes32Map,address) + +```solidity +function remove(AddressToBytes32Map storage map, address key) + internal + returns (bool) +``` + +Removes a key-value pair from the map. +Returns true if `key` was removed from the map, that is if it was present. + +### contains(AddressToBytes32Map,address) + +```solidity +function contains(AddressToBytes32Map storage map, address key) + internal + view + returns (bool) +``` + +Returns true if the key is in the map. + +### length(AddressToBytes32Map) + +```solidity +function length(AddressToBytes32Map storage map) + internal + view + returns (uint256) +``` + +Returns the number of key-value pairs in the map. + +### at(AddressToBytes32Map,uint256) + +```solidity +function at(AddressToBytes32Map storage map, uint256 i) + internal + view + returns (address key, bytes32 value) +``` + +Returns the key-value pair at index `i`. Reverts if `i` is out-of-bounds. + +### tryGet(AddressToBytes32Map,address) + +```solidity +function tryGet(AddressToBytes32Map storage map, address key) + internal + view + returns (bool exists, bytes32 value) +``` + +Tries to return the value associated with the key. + +### get(AddressToBytes32Map,address) + +```solidity +function get(AddressToBytes32Map storage map, address key) + internal + view + returns (bytes32 value) +``` + +Returns the value for the key. Reverts if the key is not found. + +### keys(AddressToBytes32Map) + +```solidity +function keys(AddressToBytes32Map storage map) + internal + view + returns (address[] memory) +``` + +Returns the keys. May run out-of-gas if the map is too big. + +### set(AddressToUint256Map,address,uint256) + +```solidity +function set(AddressToUint256Map storage map, address key, uint256 value) + internal + returns (bool) +``` + +Adds a key-value pair to the map, or updates the value for an existing key. +Returns true if `key` was added to the map, that is if it was not already present. + +### remove(AddressToUint256Map,address) + +```solidity +function remove(AddressToUint256Map storage map, address key) + internal + returns (bool) +``` + +Removes a key-value pair from the map. +Returns true if `key` was removed from the map, that is if it was present. + +### contains(AddressToUint256Map,address) + +```solidity +function contains(AddressToUint256Map storage map, address key) + internal + view + returns (bool) +``` + +Returns true if the key is in the map. + +### length(AddressToUint256Map) + +```solidity +function length(AddressToUint256Map storage map) + internal + view + returns (uint256) +``` + +Returns the number of key-value pairs in the map. + +### at(AddressToUint256Map,uint256) + +```solidity +function at(AddressToUint256Map storage map, uint256 i) + internal + view + returns (address key, uint256 value) +``` + +Returns the key-value pair at index `i`. Reverts if `i` is out-of-bounds. + +### tryGet(AddressToUint256Map,address) + +```solidity +function tryGet(AddressToUint256Map storage map, address key) + internal + view + returns (bool exists, uint256 value) +``` + +Tries to return the value associated with the key. + +### get(AddressToUint256Map,address) + +```solidity +function get(AddressToUint256Map storage map, address key) + internal + view + returns (uint256 value) +``` + +Returns the value for the key. Reverts if the key is not found. + +### keys(AddressToUint256Map) + +```solidity +function keys(AddressToUint256Map storage map) + internal + view + returns (address[] memory) +``` + +Returns the keys. May run out-of-gas if the map is too big. + +### set(AddressToAddressMap,address,address) + +```solidity +function set(AddressToAddressMap storage map, address key, address value) + internal + returns (bool) +``` + +Adds a key-value pair to the map, or updates the value for an existing key. +Returns true if `key` was added to the map, that is if it was not already present. + +### remove(AddressToAddressMap,address) + +```solidity +function remove(AddressToAddressMap storage map, address key) + internal + returns (bool) +``` + +Removes a key-value pair from the map. +Returns true if `key` was removed from the map, that is if it was present. + +### contains(AddressToAddressMap,address) + +```solidity +function contains(AddressToAddressMap storage map, address key) + internal + view + returns (bool) +``` + +Returns true if the key is in the map. + +### length(AddressToAddressMap) + +```solidity +function length(AddressToAddressMap storage map) + internal + view + returns (uint256) +``` + +Returns the number of key-value pairs in the map. + +### at(AddressToAddressMap,uint256) + +```solidity +function at(AddressToAddressMap storage map, uint256 i) + internal + view + returns (address key, address value) +``` + +Returns the key-value pair at index `i`. Reverts if `i` is out-of-bounds. + +### tryGet(AddressToAddressMap,address) + +```solidity +function tryGet(AddressToAddressMap storage map, address key) + internal + view + returns (bool exists, address value) +``` + +Tries to return the value associated with the key. + +### get(AddressToAddressMap,address) + +```solidity +function get(AddressToAddressMap storage map, address key) + internal + view + returns (address value) +``` + +Returns the value for the key. Reverts if the key is not found. + +### keys(AddressToAddressMap) + +```solidity +function keys(AddressToAddressMap storage map) + internal + view + returns (address[] memory) +``` + +Returns the keys. May run out-of-gas if the map is too big. \ No newline at end of file diff --git a/docs/utils/enumerablesetlib.md b/docs/utils/enumerablesetlib.md new file mode 100644 index 000000000..0835a0959 --- /dev/null +++ b/docs/utils/enumerablesetlib.md @@ -0,0 +1,413 @@ +# EnumerableSetLib + +Library for managing enumerable sets in storage. + + +Note: + +In many applications, the number of elements in an enumerable set is small. +This enumerable set implementation avoids storing the length and indices +for up to 3 elements. Once the length exceeds 3 for the first time, the length +and indices will be initialized. The amortized cost of adding elements is O(1). + +The AddressSet implementation packs the length with the 0th entry. + + + + + +## Custom Errors + +### IndexOutOfBounds() + +```solidity +error IndexOutOfBounds() +``` + +The index must be less than the length. + +### ValueIsZeroSentinel() + +```solidity +error ValueIsZeroSentinel() +``` + +The value cannot be the zero sentinel. + +## Structs + +### AddressSet + +```solidity +struct AddressSet { + uint256 _spacer; +} +``` + +An enumerable address set in storage. + +### Bytes32Set + +```solidity +struct Bytes32Set { + uint256 _spacer; +} +``` + +An enumerable bytes32 set in storage. + +### Uint256Set + +```solidity +struct Uint256Set { + uint256 _spacer; +} +``` + +An enumerable uint256 set in storage. + +### Int256Set + +```solidity +struct Int256Set { + uint256 _spacer; +} +``` + +An enumerable int256 set in storage. + +### Uint8Set + +```solidity +struct Uint8Set { + uint256 data; +} +``` + +An enumerable uint8 set in storage. Useful for enums. + +## Getters / Setters + +### length(AddressSet) + +```solidity +function length(AddressSet storage set) + internal + view + returns (uint256 result) +``` + +Returns the number of elements in the set. + +### length(Bytes32Set) + +```solidity +function length(Bytes32Set storage set) + internal + view + returns (uint256 result) +``` + +Returns the number of elements in the set. + +### length(Uint256Set) + +```solidity +function length(Uint256Set storage set) + internal + view + returns (uint256 result) +``` + +Returns the number of elements in the set. + +### length(Int256Set) + +```solidity +function length(Int256Set storage set) + internal + view + returns (uint256 result) +``` + +Returns the number of elements in the set. + +### length(Uint8Set) + +```solidity +function length(Uint8Set storage set) + internal + view + returns (uint256 result) +``` + +Returns the number of elements in the set. + +### contains(AddressSet,address) + +```solidity +function contains(AddressSet storage set, address value) + internal + view + returns (bool result) +``` + +Returns whether `value` is in the set. + +### contains(Bytes32Set,bytes32) + +```solidity +function contains(Bytes32Set storage set, bytes32 value) + internal + view + returns (bool result) +``` + +Returns whether `value` is in the set. + +### contains(Uint256Set,uint256) + +```solidity +function contains(Uint256Set storage set, uint256 value) + internal + view + returns (bool result) +``` + +Returns whether `value` is in the set. + +### contains(Int256Set,int256) + +```solidity +function contains(Int256Set storage set, int256 value) + internal + view + returns (bool result) +``` + +Returns whether `value` is in the set. + +### contains(Uint8Set,uint8) + +```solidity +function contains(Uint8Set storage set, uint8 value) + internal + view + returns (bool result) +``` + +Returns whether `value` is in the set. + +### add(AddressSet,address) + +```solidity +function add(AddressSet storage set, address value) + internal + returns (bool result) +``` + +Adds `value` to the set. Returns whether `value` was not in the set. + +### add(Bytes32Set,bytes32) + +```solidity +function add(Bytes32Set storage set, bytes32 value) + internal + returns (bool result) +``` + +Adds `value` to the set. Returns whether `value` was not in the set. + +### add(Uint256Set,uint256) + +```solidity +function add(Uint256Set storage set, uint256 value) + internal + returns (bool result) +``` + +Adds `value` to the set. Returns whether `value` was not in the set. + +### add(Int256Set,int256) + +```solidity +function add(Int256Set storage set, int256 value) + internal + returns (bool result) +``` + +Adds `value` to the set. Returns whether `value` was not in the set. + +### add(Uint8Set,uint8) + +```solidity +function add(Uint8Set storage set, uint8 value) + internal + returns (bool result) +``` + +Adds `value` to the set. Returns whether `value` was not in the set. + +### remove(AddressSet,address) + +```solidity +function remove(AddressSet storage set, address value) + internal + returns (bool result) +``` + +Removes `value` from the set. Returns whether `value` was in the set. + +### remove(Bytes32Set,bytes32) + +```solidity +function remove(Bytes32Set storage set, bytes32 value) + internal + returns (bool result) +``` + +Removes `value` from the set. Returns whether `value` was in the set. + +### remove(Uint256Set,uint256) + +```solidity +function remove(Uint256Set storage set, uint256 value) + internal + returns (bool result) +``` + +Removes `value` from the set. Returns whether `value` was in the set. + +### remove(Int256Set,int256) + +```solidity +function remove(Int256Set storage set, int256 value) + internal + returns (bool result) +``` + +Removes `value` from the set. Returns whether `value` was in the set. + +### remove(Uint8Set,uint8) + +```solidity +function remove(Uint8Set storage set, uint8 value) + internal + returns (bool result) +``` + +Removes `value` from the set. Returns whether `value` was in the set. + +### values(AddressSet) + +```solidity +function values(AddressSet storage set) + internal + view + returns (address[] memory result) +``` + +Returns all of the values in the set. +Note: This can consume more gas than the block gas limit for large sets. + +### values(Bytes32Set) + +```solidity +function values(Bytes32Set storage set) + internal + view + returns (bytes32[] memory result) +``` + +Returns all of the values in the set. +Note: This can consume more gas than the block gas limit for large sets. + +### values(Uint256Set) + +```solidity +function values(Uint256Set storage set) + internal + view + returns (uint256[] memory result) +``` + +Returns all of the values in the set. +Note: This can consume more gas than the block gas limit for large sets. + +### values(Int256Set) + +```solidity +function values(Int256Set storage set) + internal + view + returns (int256[] memory result) +``` + +Returns all of the values in the set. +Note: This can consume more gas than the block gas limit for large sets. + +### values(Uint8Set) + +```solidity +function values(Uint8Set storage set) + internal + view + returns (uint8[] memory result) +``` + +Returns all of the values in the set. + +### at(AddressSet,uint256) + +```solidity +function at(AddressSet storage set, uint256 i) + internal + view + returns (address result) +``` + +Returns the element at index `i` in the set. Reverts if `i` is out-of-bounds. + +### at(Bytes32Set,uint256) + +```solidity +function at(Bytes32Set storage set, uint256 i) + internal + view + returns (bytes32 result) +``` + +Returns the element at index `i` in the set. Reverts if `i` is out-of-bounds. + +### at(Uint256Set,uint256) + +```solidity +function at(Uint256Set storage set, uint256 i) + internal + view + returns (uint256 result) +``` + +Returns the element at index `i` in the set. Reverts if `i` is out-of-bounds. + +### at(Int256Set,uint256) + +```solidity +function at(Int256Set storage set, uint256 i) + internal + view + returns (int256 result) +``` + +Returns the element at index `i` in the set. Reverts if `i` is out-of-bounds. + +### at(Uint8Set,uint256) + +```solidity +function at(Uint8Set storage set, uint256 i) + internal + view + returns (uint8 result) +``` + +Returns the element at index `i` in the set. Reverts if `i` is out-of-bounds. \ No newline at end of file diff --git a/docs/utils/erc1967factory.md b/docs/utils/erc1967factory.md new file mode 100644 index 000000000..ef839f5c9 --- /dev/null +++ b/docs/utils/erc1967factory.md @@ -0,0 +1,243 @@ +# ERC1967Factory + +Factory for deploying and managing ERC1967 proxy contracts. + + + + + + + + +## Custom Errors + +### Unauthorized() + +```solidity +error Unauthorized() +``` + +The caller is not authorized to call the function. + +### DeploymentFailed() + +```solidity +error DeploymentFailed() +``` + +The proxy deployment failed. + +### UpgradeFailed() + +```solidity +error UpgradeFailed() +``` + +The upgrade failed. + +### SaltDoesNotStartWithCaller() + +```solidity +error SaltDoesNotStartWithCaller() +``` + +The salt does not start with the caller. + +## Events + +### _ADMIN_CHANGED_EVENT_SIGNATURE + +```solidity +uint256 internal constant _ADMIN_CHANGED_EVENT_SIGNATURE = + 0x7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f +``` + +`keccak256(bytes("AdminChanged(address,address)"))`. + +### _UPGRADED_EVENT_SIGNATURE + +```solidity +uint256 internal constant _UPGRADED_EVENT_SIGNATURE = + 0x5d611f318680d00598bb735d61bacf0c514c6b50e1e5ad30040a4df2b12791c7 +``` + +`keccak256(bytes("Upgraded(address,address)"))`. + +### _DEPLOYED_EVENT_SIGNATURE + +```solidity +uint256 internal constant _DEPLOYED_EVENT_SIGNATURE = + 0xc95935a66d15e0da5e412aca0ad27ae891d20b2fb91cf3994b6a3bf2b8178082 +``` + +`keccak256(bytes("Deployed(address,address,address)"))`. + +## Storage + +The admin slot for a `proxy` is `shl(96, proxy)`. + +### _IMPLEMENTATION_SLOT + +```solidity +uint256 internal constant _IMPLEMENTATION_SLOT = + 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc +``` + +The ERC-1967 storage slot for the implementation in the proxy. +`uint256(keccak256("eip1967.proxy.implementation")) - 1`. + +## Admin Functions + +### adminOf(address) + +```solidity +function adminOf(address proxy) public view returns (address admin) +``` + +Returns the admin of the proxy. + +### changeAdmin(address,address) + +```solidity +function changeAdmin(address proxy, address admin) public +``` + +Sets the admin of the proxy. +The caller of this function must be the admin of the proxy on this factory. + +## Upgrade Functions + +### upgrade(address,address) + +```solidity +function upgrade(address proxy, address implementation) public payable +``` + +Upgrades the proxy to point to `implementation`. +The caller of this function must be the admin of the proxy on this factory. + +### upgradeAndCall(address,address,bytes) + +```solidity +function upgradeAndCall( + address proxy, + address implementation, + bytes calldata data +) public payable +``` + +Upgrades the proxy to point to `implementation`. +Then, calls the proxy with abi encoded `data`. +The caller of this function must be the admin of the proxy on this factory. + +## Deploy Functions + +### deploy(address,address) + +```solidity +function deploy(address implementation, address admin) + public + payable + returns (address proxy) +``` + +Deploys a proxy for `implementation`, with `admin`, +and returns its address. +The value passed into this function will be forwarded to the proxy. + +### deployAndCall(address,address,bytes) + +```solidity +function deployAndCall( + address implementation, + address admin, + bytes calldata data +) public payable returns (address proxy) +``` + +Deploys a proxy for `implementation`, with `admin`, +and returns its address. +The value passed into this function will be forwarded to the proxy. +Then, calls the proxy with abi encoded `data`. + +### deployDeterministic(address,address,bytes32) + +```solidity +function deployDeterministic( + address implementation, + address admin, + bytes32 salt +) public payable returns (address proxy) +``` + +Deploys a proxy for `implementation`, with `admin`, `salt`, +and returns its deterministic address. +The value passed into this function will be forwarded to the proxy. + +### deployDeterministicAndCall(address,address,bytes32,bytes) + +```solidity +function deployDeterministicAndCall( + address implementation, + address admin, + bytes32 salt, + bytes calldata data +) public payable returns (address proxy) +``` + +Deploys a proxy for `implementation`, with `admin`, `salt`, +and returns its deterministic address. +The value passed into this function will be forwarded to the proxy. +Then, calls the proxy with abi encoded `data`. + +### _deploy(address,address,bytes32,bool,bytes) + +```solidity +function _deploy( + address implementation, + address admin, + bytes32 salt, + bool useSalt, + bytes calldata data +) internal returns (address proxy) +``` + +Deploys the proxy, with optionality to deploy deterministically with a `salt`. + +### predictDeterministicAddress(bytes32) + +```solidity +function predictDeterministicAddress(bytes32 salt) + public + view + returns (address predicted) +``` + +Returns the address of the proxy deployed with `salt`. + +### initCodeHash() + +```solidity +function initCodeHash() public view returns (bytes32 result) +``` + +Returns the initialization code hash of the proxy. +Used for mining vanity addresses with create2crunch. + +### _initCode() + +```solidity +function _initCode() internal view returns (bytes32 m) +``` + +Returns a pointer to the initialization code of a proxy created via this factory. + +## Helpers + +### _emptyData() + +```solidity +function _emptyData() internal pure returns (bytes calldata data) +``` + +Helper function to return an empty bytes calldata. \ No newline at end of file diff --git a/docs/utils/erc1967factoryconstants.md b/docs/utils/erc1967factoryconstants.md new file mode 100644 index 000000000..983c02e9c --- /dev/null +++ b/docs/utils/erc1967factoryconstants.md @@ -0,0 +1,70 @@ +# ERC1967FactoryConstants + +The address and bytecode of the canonical ERC1967Factory deployment. + + +The canonical ERC1967Factory is deployed permissionlessly via +0age's ImmutableCreate2Factory located at 0x0000000000FFe8B47B3e2130213B802212439497. + +`ADDRESS = immutableCreate2Factory.safeCreate2(SALT, INITCODE)` + +If the canonical ERC1967Factory has not been deployed on your EVM chain of choice, +please feel free to deploy via 0age's ImmutableCreate2Factory. + +If 0age's ImmutableCreate2Factory has not been deployed on your EVM chain of choice, +please refer to 0age's ImmutableCreate2Factory deployment instructions at: +https://github.com/ProjectOpenSea/seaport/blob/main/docs/Deployment.md + +Contract verification: +- 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 + + + + + +## Functions + +### ADDRESS + +```solidity +address internal constant ADDRESS = + 0x0000000000006396FF2a80c067f99B3d2Ab4Df24 +``` + +The canonical ERC1967Factory address for EVM chains. + +### BYTECODE + +```solidity +bytes internal constant BYTECODE = + hex"6080604052600436106100b15760003560e01c8063545e7c611161006957806399a88ec41161004e57806399a88ec41461019d578063a97b90d5146101b0578063db4c545e146101c357600080fd5b8063545e7c61146101775780639623609d1461018a57600080fd5b80633729f9221161009a5780633729f922146101315780634314f120146101445780635414dff01461015757600080fd5b80631acfd02a146100b65780632abbef15146100d8575b600080fd5b3480156100c257600080fd5b506100d66100d1366004610604565b6101e6565b005b3480156100e457600080fd5b506101076100f3366004610637565b30600c908152600091909152602090205490565b60405173ffffffffffffffffffffffffffffffffffffffff90911681526020015b60405180910390f35b61010761013f366004610652565b610237565b6101076101523660046106d7565b61024e565b34801561016357600080fd5b50610107610172366004610738565b610267565b610107610185366004610604565b61029a565b6100d66101983660046106d7565b6102af565b6100d66101ab366004610604565b61035f565b6101076101be366004610751565b610370565b3480156101cf57600080fd5b506101d86103a9565b604051908152602001610128565b30600c52816000526020600c2033815414610209576382b429006000526004601cfd5b81905580827f7e644d79422f17c01e4894b5f4f588d331ebfa28653d42ae832dc59e38c9798f600080a35050565b60006102468484843685610370565b949350505050565b600061025e8585838087876103c2565b95945050505050565b6000806102726103a9565b905060ff600053806035523060601b6001528260155260556000209150600060355250919050565b60006102a88383368461024e565b9392505050565b30600c5283600052336020600c2054146102d1576382b429006000526004601cfd5b6040518381527f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc602082015281836040830137600080836040018334895af1610331573d610327576355299b496000526004601cfd5b3d6000803e3d6000fd5b5082847f5d611f318680d00598bb735d61bacf0c514c6b50e1e5ad30040a4df2b12791c7600080a350505050565b61036c82823660006102af565b5050565b60008360601c33148460601c151761039057632f6348366000526004601cfd5b61039f868686600187876103c2565b9695505050505050565b6000806103b461049c565b608960139091012092915050565b6000806103cd61049c565b90508480156103e757866089601384016000f592506103f3565b6089601383016000f092505b50816104075763301164256000526004601cfd5b8781527f360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc602082015282846040830137600080846040018334865af161045a573d6103275763301164256000526004601cfd5b30600c5281600052866020600c20558688837fc95935a66d15e0da5e412aca0ad27ae891d20b2fb91cf3994b6a3bf2b8178082600080a4509695505050505050565b6040513060701c801561054257666052573d6000fd607b8301527f3d356020355560408036111560525736038060403d373d3d355af43d6000803e60748301527f3735a920a3ca505d382bbc545af43d6000803e6052573d6000fd5b3d6000f35b60548301527f14605757363d3d37363d7f360894a13ba1a3210667c828492db98dca3e2076cc60348301523060148301526c607f3d8160093d39f33d3d337382525090565b66604c573d6000fd60758301527f3d3560203555604080361115604c5736038060403d373d3d355af43d6000803e606e8301527f3735a920a3ca505d382bbc545af43d6000803e604c573d6000fd5b3d6000f35b604e8301527f14605157363d3d37363d7f360894a13ba1a3210667c828492db98dca3e2076cc602e83015230600e8301526c60793d8160093d39f33d3d336d82525090565b803573ffffffffffffffffffffffffffffffffffffffff811681146105ff57600080fd5b919050565b6000806040838503121561061757600080fd5b610620836105db565b915061062e602084016105db565b90509250929050565b60006020828403121561064957600080fd5b6102a8826105db565b60008060006060848603121561066757600080fd5b610670846105db565b925061067e602085016105db565b9150604084013590509250925092565b60008083601f8401126106a057600080fd5b50813567ffffffffffffffff8111156106b857600080fd5b6020830191508360208285010111156106d057600080fd5b9250929050565b600080600080606085870312156106ed57600080fd5b6106f6856105db565b9350610704602086016105db565b9250604085013567ffffffffffffffff81111561072057600080fd5b61072c8782880161068e565b95989497509550505050565b60006020828403121561074a57600080fd5b5035919050565b60008060008060006080868803121561076957600080fd5b610772866105db565b9450610780602087016105db565b935060408601359250606086013567ffffffffffffffff8111156107a357600080fd5b6107af8882890161068e565b96999598509396509294939250505056fea26469706673582212200ac7c3ccbc2d311c48bf5465b021542e0e306fe3c462c060ba6a3d2f81ff6c5f64736f6c63430008130033" +``` + +The canonical ERC1967Factory bytecode for EVM chains. +Useful for forge tests: +`vm.etch(ADDRESS, BYTECODE)`. + +### INITCODE + +```solidity +bytes internal constant INITCODE = abi.encodePacked( + hex"608060405234801561001057600080fd5b506107f6806100206000396000f3fe", + BYTECODE +) +``` + +The initialization code used to deploy the canonical ERC1967Factory. + +### SALT + +```solidity +bytes32 internal constant SALT = + 0x0000000000000000000000000000000000000000e75e4f228818c80007508f33 +``` + +For deterministic deployment via 0age's ImmutableCreate2Factory. \ No newline at end of file diff --git a/docs/utils/fixedpointmathlib.md b/docs/utils/fixedpointmathlib.md new file mode 100644 index 000000000..e58d0a6f0 --- /dev/null +++ b/docs/utils/fixedpointmathlib.md @@ -0,0 +1,823 @@ +# FixedPointMathLib + +Arithmetic library with operations for fixed-point numbers. + + + + + + + + +## Custom Errors + +### ExpOverflow() + +```solidity +error ExpOverflow() +``` + +The operation failed, as the output exceeds the maximum value of uint256. + +### FactorialOverflow() + +```solidity +error FactorialOverflow() +``` + +The operation failed, as the output exceeds the maximum value of uint256. + +### RPowOverflow() + +```solidity +error RPowOverflow() +``` + +The operation failed, due to an overflow. + +### MantissaOverflow() + +```solidity +error MantissaOverflow() +``` + +The mantissa is too big to fit. + +### MulWadFailed() + +```solidity +error MulWadFailed() +``` + +The operation failed, due to an multiplication overflow. + +### SMulWadFailed() + +```solidity +error SMulWadFailed() +``` + +The operation failed, due to an multiplication overflow. + +### DivWadFailed() + +```solidity +error DivWadFailed() +``` + +The operation failed, either due to a multiplication overflow, or a division by a zero. + +### SDivWadFailed() + +```solidity +error SDivWadFailed() +``` + +The operation failed, either due to a multiplication overflow, or a division by a zero. + +### MulDivFailed() + +```solidity +error MulDivFailed() +``` + +The operation failed, either due to a multiplication overflow, or a division by a zero. + +### DivFailed() + +```solidity +error DivFailed() +``` + +The division failed, as the denominator is zero. + +### FullMulDivFailed() + +```solidity +error FullMulDivFailed() +``` + +The full precision multiply-divide operation failed, either due +to the result being larger than 256 bits, or a division by a zero. + +### LnWadUndefined() + +```solidity +error LnWadUndefined() +``` + +The output is undefined, as the input is less-than-or-equal to zero. + +### OutOfDomain() + +```solidity +error OutOfDomain() +``` + +The input outside the acceptable domain. + +## Constants + +### WAD + +```solidity +uint256 internal constant WAD = 1e18 +``` + +The scalar of ETH and most ERC20s. + +## Simplified Fixed Point Operations + +### mulWad(uint256,uint256) + +```solidity +function mulWad(uint256 x, uint256 y) internal pure returns (uint256 z) +``` + +Equivalent to `(x * y) / WAD` rounded down. + +### sMulWad(int256,int256) + +```solidity +function sMulWad(int256 x, int256 y) internal pure returns (int256 z) +``` + +Equivalent to `(x * y) / WAD` rounded down. + +### rawMulWad(uint256,uint256) + +```solidity +function rawMulWad(uint256 x, uint256 y) + internal + pure + returns (uint256 z) +``` + +Equivalent to `(x * y) / WAD` rounded down, but without overflow checks. + +### rawSMulWad(int256,int256) + +```solidity +function rawSMulWad(int256 x, int256 y) internal pure returns (int256 z) +``` + +Equivalent to `(x * y) / WAD` rounded down, but without overflow checks. + +### mulWadUp(uint256,uint256) + +```solidity +function mulWadUp(uint256 x, uint256 y) internal pure returns (uint256 z) +``` + +Equivalent to `(x * y) / WAD` rounded up. + +### rawMulWadUp(uint256,uint256) + +```solidity +function rawMulWadUp(uint256 x, uint256 y) + internal + pure + returns (uint256 z) +``` + +Equivalent to `(x * y) / WAD` rounded up, but without overflow checks. + +### divWad(uint256,uint256) + +```solidity +function divWad(uint256 x, uint256 y) internal pure returns (uint256 z) +``` + +Equivalent to `(x * WAD) / y` rounded down. + +### sDivWad(int256,int256) + +```solidity +function sDivWad(int256 x, int256 y) internal pure returns (int256 z) +``` + +Equivalent to `(x * WAD) / y` rounded down. + +### rawDivWad(uint256,uint256) + +```solidity +function rawDivWad(uint256 x, uint256 y) + internal + pure + returns (uint256 z) +``` + +Equivalent to `(x * WAD) / y` rounded down, but without overflow and divide by zero checks. + +### rawSDivWad(int256,int256) + +```solidity +function rawSDivWad(int256 x, int256 y) internal pure returns (int256 z) +``` + +Equivalent to `(x * WAD) / y` rounded down, but without overflow and divide by zero checks. + +### divWadUp(uint256,uint256) + +```solidity +function divWadUp(uint256 x, uint256 y) internal pure returns (uint256 z) +``` + +Equivalent to `(x * WAD) / y` rounded up. + +### rawDivWadUp(uint256,uint256) + +```solidity +function rawDivWadUp(uint256 x, uint256 y) + internal + pure + returns (uint256 z) +``` + +Equivalent to `(x * WAD) / y` rounded up, but without overflow and divide by zero checks. + +### powWad(int256,int256) + +```solidity +function powWad(int256 x, int256 y) internal pure returns (int256) +``` + +Equivalent to `x` to the power of `y`. +because `x ** y = (e ** ln(x)) ** y = e ** (ln(x) * y)`. +Note: This function is an approximation. + +### expWad(int256) + +```solidity +function expWad(int256 x) internal pure returns (int256 r) +``` + +Returns `exp(x)`, denominated in `WAD`. +Credit to Remco Bloemen under MIT license: https://2π.com/22/exp-ln +Note: This function is an approximation. Monotonically increasing. + +### lnWad(int256) + +```solidity +function lnWad(int256 x) internal pure returns (int256 r) +``` + +Returns `ln(x)`, denominated in `WAD`. +Credit to Remco Bloemen under MIT license: https://2π.com/22/exp-ln +Note: This function is an approximation. Monotonically increasing. + +### lambertW0Wad(int256) + +```solidity +function lambertW0Wad(int256 x) internal pure returns (int256 w) +``` + +Returns `W_0(x)`, denominated in `WAD`. +See: https://en.wikipedia.org/wiki/Lambert_W_function +a.k.a. Product log function. This is an approximation of the principal branch. +Note: This function is an approximation. Monotonically increasing. + +## General Number Utilities + +### fullMulEq(uint256,uint256,uint256,uint256) + +```solidity +function fullMulEq(uint256 a, uint256 b, uint256 x, uint256 y) + internal + pure + returns (bool result) +``` + +Returns `a * b == x * y`, with full precision. + +### fullMulDiv(uint256,uint256,uint256) + +```solidity +function fullMulDiv(uint256 x, uint256 y, uint256 d) + internal + pure + returns (uint256 z) +``` + +Calculates `floor(x * y / d)` with full precision. +Throws if result overflows a uint256 or when `d` is zero. +Credit to Remco Bloemen under MIT license: https://2π.com/21/muldiv + +### fullMulDivUnchecked(uint256,uint256,uint256) + +```solidity +function fullMulDivUnchecked(uint256 x, uint256 y, uint256 d) + internal + pure + returns (uint256 z) +``` + +Calculates `floor(x * y / d)` with full precision. +Behavior is undefined if `d` is zero or the final result cannot fit in 256 bits. +Performs the full 512 bit calculation regardless. + +### fullMulDivUp(uint256,uint256,uint256) + +```solidity +function fullMulDivUp(uint256 x, uint256 y, uint256 d) + internal + pure + returns (uint256 z) +``` + +Calculates `floor(x * y / d)` with full precision, rounded up. +Throws if result overflows a uint256 or when `d` is zero. +Credit to Uniswap-v3-core under MIT license: +https://github.com/Uniswap/v3-core/blob/main/contracts/libraries/FullMath.sol + +### fullMulDivN(uint256,uint256,uint8) + +```solidity +function fullMulDivN(uint256 x, uint256 y, uint8 n) + internal + pure + returns (uint256 z) +``` + +Calculates `floor(x * y / 2 ** n)` with full precision. +Throws if result overflows a uint256. +Credit to Philogy under MIT license: +https://github.com/SorellaLabs/angstrom/blob/main/contracts/src/libraries/X128MathLib.sol + +### mulDiv(uint256,uint256,uint256) + +```solidity +function mulDiv(uint256 x, uint256 y, uint256 d) + internal + pure + returns (uint256 z) +``` + +Returns `floor(x * y / d)`. +Reverts if `x * y` overflows, or `d` is zero. + +### mulDivUp(uint256,uint256,uint256) + +```solidity +function mulDivUp(uint256 x, uint256 y, uint256 d) + internal + pure + returns (uint256 z) +``` + +Returns `ceil(x * y / d)`. +Reverts if `x * y` overflows, or `d` is zero. + +### invMod(uint256,uint256) + +```solidity +function invMod(uint256 a, uint256 n) internal pure returns (uint256 x) +``` + +Returns `x`, the modular multiplicative inverse of `a`, such that `(a * x) % n == 1`. + +### divUp(uint256,uint256) + +```solidity +function divUp(uint256 x, uint256 d) internal pure returns (uint256 z) +``` + +Returns `ceil(x / d)`. +Reverts if `d` is zero. + +### zeroFloorSub(uint256,uint256) + +```solidity +function zeroFloorSub(uint256 x, uint256 y) + internal + pure + returns (uint256 z) +``` + +Returns `max(0, x - y)`. + +### ternary(bool,uint256,uint256) + +```solidity +function ternary(bool condition, uint256 x, uint256 y) + internal + pure + returns (uint256 z) +``` + +Returns `condition ? x : y`, without branching. + +### ternary(bool,bytes32,bytes32) + +```solidity +function ternary(bool condition, bytes32 x, bytes32 y) + internal + pure + returns (bytes32 z) +``` + +Returns `condition ? x : y`, without branching. + +### ternary(bool,address,address) + +```solidity +function ternary(bool condition, address x, address y) + internal + pure + returns (address z) +``` + +Returns `condition ? x : y`, without branching. + +### rpow(uint256,uint256,uint256) + +```solidity +function rpow(uint256 x, uint256 y, uint256 b) + internal + pure + returns (uint256 z) +``` + +Exponentiate `x` to `y` by squaring, denominated in base `b`. +Reverts if the computation overflows. + +### sqrt(uint256) + +```solidity +function sqrt(uint256 x) internal pure returns (uint256 z) +``` + +Returns the square root of `x`, rounded down. + +### cbrt(uint256) + +```solidity +function cbrt(uint256 x) internal pure returns (uint256 z) +``` + +Returns the cube root of `x`, rounded down. +Credit to bout3fiddy and pcaversaccio under AGPLv3 license: +https://github.com/pcaversaccio/snekmate/blob/main/src/utils/Math.vy +Formally verified by xuwinnie: +https://github.com/vectorized/solady/blob/main/audits/xuwinnie-solady-cbrt-proof.pdf + +### sqrtWad(uint256) + +```solidity +function sqrtWad(uint256 x) internal pure returns (uint256 z) +``` + +Returns the square root of `x`, denominated in `WAD`, rounded down. + +### cbrtWad(uint256) + +```solidity +function cbrtWad(uint256 x) internal pure returns (uint256 z) +``` + +Returns the cube root of `x`, denominated in `WAD`, rounded down. +Formally verified by xuwinnie: +https://github.com/vectorized/solady/blob/main/audits/xuwinnie-solady-cbrt-proof.pdf + +### factorial(uint256) + +```solidity +function factorial(uint256 x) internal pure returns (uint256 z) +``` + +Returns the factorial of `x`. + +### log2(uint256) + +```solidity +function log2(uint256 x) internal pure returns (uint256 r) +``` + +Returns the log2 of `x`. +Equivalent to computing the index of the most significant bit (MSB) of `x`. +Returns 0 if `x` is zero. + +### log2Up(uint256) + +```solidity +function log2Up(uint256 x) internal pure returns (uint256 r) +``` + +Returns the log2 of `x`, rounded up. +Returns 0 if `x` is zero. + +### log10(uint256) + +```solidity +function log10(uint256 x) internal pure returns (uint256 r) +``` + +Returns the log10 of `x`. +Returns 0 if `x` is zero. + +### log10Up(uint256) + +```solidity +function log10Up(uint256 x) internal pure returns (uint256 r) +``` + +Returns the log10 of `x`, rounded up. +Returns 0 if `x` is zero. + +### log256(uint256) + +```solidity +function log256(uint256 x) internal pure returns (uint256 r) +``` + +Returns the log256 of `x`. +Returns 0 if `x` is zero. + +### log256Up(uint256) + +```solidity +function log256Up(uint256 x) internal pure returns (uint256 r) +``` + +Returns the log256 of `x`, rounded up. +Returns 0 if `x` is zero. + +### sci(uint256) + +```solidity +function sci(uint256 x) + internal + pure + returns (uint256 mantissa, uint256 exponent) +``` + +Returns the scientific notation format `mantissa * 10 ** exponent` of `x`. +Useful for compressing prices (e.g. using 25 bit mantissa and 7 bit exponent). + +### packSci(uint256) + +```solidity +function packSci(uint256 x) internal pure returns (uint256 packed) +``` + +Convenience function for packing `x` into a smaller number using `sci`. +The `mantissa` will be in bits [7..255] (the upper 249 bits). +The `exponent` will be in bits [0..6] (the lower 7 bits). +Use `SafeCastLib` to safely ensure that the `packed` number is small +enough to fit in the desired unsigned integer type: +```solidity +uint32 packed = SafeCastLib.toUint32(FixedPointMathLib.packSci(777 ether)); +``` + +### unpackSci(uint256) + +```solidity +function unpackSci(uint256 packed) + internal + pure + returns (uint256 unpacked) +``` + +Convenience function for unpacking a packed number from `packSci`. + +### avg(uint256,uint256) + +```solidity +function avg(uint256 x, uint256 y) internal pure returns (uint256 z) +``` + +Returns the average of `x` and `y`. Rounds towards zero. + +### avg(int256,int256) + +```solidity +function avg(int256 x, int256 y) internal pure returns (int256 z) +``` + +Returns the average of `x` and `y`. Rounds towards negative infinity. + +### abs(int256) + +```solidity +function abs(int256 x) internal pure returns (uint256 z) +``` + +Returns the absolute value of `x`. + +### dist(uint256,uint256) + +```solidity +function dist(uint256 x, uint256 y) internal pure returns (uint256 z) +``` + +Returns the absolute distance between `x` and `y`. + +### dist(int256,int256) + +```solidity +function dist(int256 x, int256 y) internal pure returns (uint256 z) +``` + +Returns the absolute distance between `x` and `y`. + +### min(uint256,uint256) + +```solidity +function min(uint256 x, uint256 y) internal pure returns (uint256 z) +``` + +Returns the minimum of `x` and `y`. + +### min(int256,int256) + +```solidity +function min(int256 x, int256 y) internal pure returns (int256 z) +``` + +Returns the minimum of `x` and `y`. + +### max(uint256,uint256) + +```solidity +function max(uint256 x, uint256 y) internal pure returns (uint256 z) +``` + +Returns the maximum of `x` and `y`. + +### max(int256,int256) + +```solidity +function max(int256 x, int256 y) internal pure returns (int256 z) +``` + +Returns the maximum of `x` and `y`. + +### clamp(uint256,uint256,uint256) + +```solidity +function clamp(uint256 x, uint256 minValue, uint256 maxValue) + internal + pure + returns (uint256 z) +``` + +Returns `x`, bounded to `minValue` and `maxValue`. + +### clamp(int256,int256,int256) + +```solidity +function clamp(int256 x, int256 minValue, int256 maxValue) + internal + pure + returns (int256 z) +``` + +Returns `x`, bounded to `minValue` and `maxValue`. + +### gcd(uint256,uint256) + +```solidity +function gcd(uint256 x, uint256 y) internal pure returns (uint256 z) +``` + +Returns greatest common divisor of `x` and `y`. + +### lerp(uint256,uint256,uint256,uint256,uint256) + +```solidity +function lerp(uint256 a, uint256 b, uint256 t, uint256 begin, uint256 end) + internal + pure + returns (uint256) +``` + +Returns `a + (b - a) * (t - begin) / (end - begin)`, +with `t` clamped between `begin` and `end` (inclusive). +Agnostic to the order of (`a`, `b`) and (`end`, `begin`). +If `begins == end`, returns `t <= begin ? a : b`. + +### lerp(int256,int256,int256,int256,int256) + +```solidity +function lerp(int256 a, int256 b, int256 t, int256 begin, int256 end) + internal + pure + returns (int256) +``` + +Returns `a + (b - a) * (t - begin) / (end - begin)`. +with `t` clamped between `begin` and `end` (inclusive). +Agnostic to the order of (`a`, `b`) and (`end`, `begin`). +If `begins == end`, returns `t <= begin ? a : b`. + +### isEven(uint256) + +```solidity +function isEven(uint256 x) internal pure returns (bool) +``` + +Returns if `x` is an even number. Some people may need this. + +## Raw Number Operations + +### rawAdd(uint256,uint256) + +```solidity +function rawAdd(uint256 x, uint256 y) internal pure returns (uint256 z) +``` + +Returns `x + y`, without checking for overflow. + +### rawAdd(int256,int256) + +```solidity +function rawAdd(int256 x, int256 y) internal pure returns (int256 z) +``` + +Returns `x + y`, without checking for overflow. + +### rawSub(uint256,uint256) + +```solidity +function rawSub(uint256 x, uint256 y) internal pure returns (uint256 z) +``` + +Returns `x - y`, without checking for underflow. + +### rawSub(int256,int256) + +```solidity +function rawSub(int256 x, int256 y) internal pure returns (int256 z) +``` + +Returns `x - y`, without checking for underflow. + +### rawMul(uint256,uint256) + +```solidity +function rawMul(uint256 x, uint256 y) internal pure returns (uint256 z) +``` + +Returns `x * y`, without checking for overflow. + +### rawMul(int256,int256) + +```solidity +function rawMul(int256 x, int256 y) internal pure returns (int256 z) +``` + +Returns `x * y`, without checking for overflow. + +### rawDiv(uint256,uint256) + +```solidity +function rawDiv(uint256 x, uint256 y) internal pure returns (uint256 z) +``` + +Returns `x / y`, returning 0 if `y` is zero. + +### rawSDiv(int256,int256) + +```solidity +function rawSDiv(int256 x, int256 y) internal pure returns (int256 z) +``` + +Returns `x / y`, returning 0 if `y` is zero. + +### rawMod(uint256,uint256) + +```solidity +function rawMod(uint256 x, uint256 y) internal pure returns (uint256 z) +``` + +Returns `x % y`, returning 0 if `y` is zero. + +### rawSMod(int256,int256) + +```solidity +function rawSMod(int256 x, int256 y) internal pure returns (int256 z) +``` + +Returns `x % y`, returning 0 if `y` is zero. + +### rawAddMod(uint256,uint256,uint256) + +```solidity +function rawAddMod(uint256 x, uint256 y, uint256 d) + internal + pure + returns (uint256 z) +``` + +Returns `(x + y) % d`, return 0 if `d` if zero. + +### rawMulMod(uint256,uint256,uint256) + +```solidity +function rawMulMod(uint256 x, uint256 y, uint256 d) + internal + pure + returns (uint256 z) +``` + +Returns `(x * y) % d`, return 0 if `d` if zero. \ No newline at end of file diff --git a/docs/utils/gasburnerlib.md b/docs/utils/gasburnerlib.md new file mode 100644 index 000000000..262244837 --- /dev/null +++ b/docs/utils/gasburnerlib.md @@ -0,0 +1,41 @@ +# GasBurnerLib + +Library for burning gas without reverting. + + +Intended for Contract Secured Revenue (CSR). + +Recommendation: for the amount of gas to burn, +pass in an admin-controlled dynamic value instead of a hardcoded one. +This is so that you can adjust your contract as needed depending on market conditions, +and to give you and your users a leeway in case the L2 chain change the rules. + + + + + +## Functions + +### burnPure(uint256) + +```solidity +function burnPure(uint256 x) internal pure +``` + +Burns approximately `x` amount of gas. + +### burnView(uint256) + +```solidity +function burnView(uint256 x) internal view +``` + +Burns approximately `x` amount of gas. + +### burn(uint256) + +```solidity +function burn(uint256 x) internal +``` + +Burns approximately `x` amount of gas. \ No newline at end of file diff --git a/docs/utils/initializable.md b/docs/utils/initializable.md new file mode 100644 index 000000000..de7c21205 --- /dev/null +++ b/docs/utils/initializable.md @@ -0,0 +1,112 @@ +# Initializable + +Initializable mixin for the upgradeable contracts. + + + + + + + + +## Custom Errors + +### InvalidInitialization() + +```solidity +error InvalidInitialization() +``` + +The contract is already initialized. + +### NotInitializing() + +```solidity +error NotInitializing() +``` + +The contract is not initializing. + +## Operations + +### _initializableSlot() + +```solidity +function _initializableSlot() internal pure virtual returns (bytes32) +``` + +Override to return a custom storage slot if required. + +### initializer() + +```solidity +modifier initializer() virtual +``` + +Guards an initializer function so that it can be invoked at most once. +You can guard a function with `onlyInitializing` such that it can be called +through a function guarded with `initializer`. +This is similar to `reinitializer(1)`, except that in the context of a constructor, +an `initializer` guarded function can be invoked multiple times. +This can be useful during testing and is not expected to be used in production. +Emits an {Initialized} event. + +### reinitializer(uint64) + +```solidity +modifier reinitializer(uint64 version) virtual +``` + +Guards an reinitialzer function so that it can be invoked at most once. +You can guard a function with `onlyInitializing` such that it can be called +through a function guarded with `reinitializer`. +Emits an {Initialized} event. + +### onlyInitializing() + +```solidity +modifier onlyInitializing() virtual +``` + +Guards a function such that it can only be called in the scope +of a function guarded with `initializer` or `reinitializer`. + +### _checkInitializing() + +```solidity +function _checkInitializing() internal view virtual +``` + +Reverts if the contract is not initializing. + +### _disableInitializers() + +```solidity +function _disableInitializers() internal virtual +``` + +Locks any future initializations by setting the initialized version to `2**64 - 1`. +Calling this in the constructor will prevent the contract from being initialized +or reinitialized. It is recommended to use this to lock implementation contracts +that are designed to be called through proxies. +Emits an {Initialized} event the first time it is successfully called. + +### _getInitializedVersion() + +```solidity +function _getInitializedVersion() + internal + view + virtual + returns (uint64 version) +``` + +Returns the highest version that has been initialized. + +### _isInitializing() + +```solidity +function _isInitializing() internal view virtual returns (bool result) +``` + +Returns whether the contract is currently initializing. \ No newline at end of file diff --git a/docs/utils/jsonparserlib.md b/docs/utils/jsonparserlib.md new file mode 100644 index 000000000..fc40d7e28 --- /dev/null +++ b/docs/utils/jsonparserlib.md @@ -0,0 +1,351 @@ +# JSONParserLib + +Library for parsing JSONs. + + + + + + + + +## Custom Errors + +### ParsingFailed() + +```solidity +error ParsingFailed() +``` + +The input is invalid. + +## Constants + +There are 6 types of variables in JSON (excluding undefined). + +### TYPE_UNDEFINED + +```solidity +uint8 internal constant TYPE_UNDEFINED = 0 +``` + +For denoting that an item has not been initialized. +A item returned from `parse` will never be of an undefined type. +Parsing a invalid JSON string will simply revert. + +### TYPE_ARRAY + +```solidity +uint8 internal constant TYPE_ARRAY = 1 +``` + +Type representing an array (e.g. `[1,2,3]`). + +### TYPE_OBJECT + +```solidity +uint8 internal constant TYPE_OBJECT = 2 +``` + +Type representing an object (e.g. `{"a":"A","b":"B"}`). + +### TYPE_NUMBER + +```solidity +uint8 internal constant TYPE_NUMBER = 3 +``` + +Type representing a number (e.g. `-1.23e+21`). + +### TYPE_STRING + +```solidity +uint8 internal constant TYPE_STRING = 4 +``` + +Type representing a string (e.g. `"hello"`). + +### TYPE_BOOLEAN + +```solidity +uint8 internal constant TYPE_BOOLEAN = 5 +``` + +Type representing a boolean (i.e. `true` or `false`). + +### TYPE_NULL + +```solidity +uint8 internal constant TYPE_NULL = 6 +``` + +Type representing null (i.e. `null`). + +## Structs + +### Item + +```solidity +struct Item { + // Do NOT modify the `_data` directly. + uint256 _data; +} +``` + +A pointer to a parsed JSON node. + +## Json Parsing Operation + +### parse(string) + +```solidity +function parse(string memory s) + internal + pure + returns (Item memory result) +``` + +Parses the JSON string `s`, and returns the root. +Reverts if `s` is not a valid JSON as specified in RFC 8259. +Object items WILL simply contain all their children, inclusive of repeated keys, +in the same order which they appear in the JSON string. +Note: For efficiency, this function WILL NOT make a copy of `s`. +The parsed tree WILL contain offsets to `s`. +Do NOT pass in a string that WILL be modified later on. + +## Json Item Operations + +Note: +- An item is a node in the JSON tree. +- The value of a string item WILL be double-quoted, JSON encoded. +- We make a distinction between `index` and `key`. + - Items in arrays are located by `index` (uint256). + - Items in objects are located by `key` (string). +- Keys are always strings, double-quoted, JSON encoded. +These design choices are made to balance between efficiency and ease-of-use. + +### value(Item) + +```solidity +function value(Item memory item) + internal + pure + returns (string memory result) +``` + +Returns the string value of the item. +This is its exact string representation in the original JSON string. +The returned string WILL have leading and trailing whitespace trimmed. +All inner whitespace WILL be preserved, exactly as it is in the original JSON string. +If the item's type is string, the returned string WILL be double-quoted, JSON encoded. +Note: This function lazily instantiates and caches the returned string. +Do NOT modify the returned string. + +### index(Item) + +```solidity +function index(Item memory item) internal pure returns (uint256 result) +``` + +Returns the index of the item in the array. +It the item's parent is not an array, returns 0. + +### key(Item) + +```solidity +function key(Item memory item) + internal + pure + returns (string memory result) +``` + +Returns the key of the item in the object. +It the item's parent is not an object, returns an empty string. +The returned string WILL be double-quoted, JSON encoded. +Note: This function lazily instantiates and caches the returned string. +Do NOT modify the returned string. + +### children(Item) + +```solidity +function children(Item memory item) + internal + pure + returns (Item[] memory result) +``` + +Returns the key of the item in the object. +It the item is neither an array nor object, returns an empty array. +Note: This function lazily instantiates and caches the returned array. +Do NOT modify the returned array. + +### size(Item) + +```solidity +function size(Item memory item) internal pure returns (uint256 result) +``` + +Returns the number of children. +It the item is neither an array nor object, returns zero. + +### at(Item,uint256) + +```solidity +function at(Item memory item, uint256 i) + internal + pure + returns (Item memory result) +``` + +Returns the item at index `i` for (array). +If `item` is not an array, the result's type WILL be undefined. +If there is no item with the index, the result's type WILL be undefined. + +### at(Item,string) + +```solidity +function at(Item memory item, string memory k) + internal + pure + returns (Item memory result) +``` + +Returns the item at key `k` for (object). +If `item` is not an object, the result's type WILL be undefined. +The key MUST be double-quoted, JSON encoded. This is for efficiency reasons. +- Correct : `item.at('"k"')`. +- Wrong : `item.at("k")`. +For duplicated keys, the last item with the key WILL be returned. +If there is no item with the key, the result's type WILL be undefined. + +### getType(Item) + +```solidity +function getType(Item memory item) internal pure returns (uint8 result) +``` + +Returns the item's type. + +### isUndefined(Item) + +```solidity +function isUndefined(Item memory item) + internal + pure + returns (bool result) +``` + +/// Note: All types are mutually exclusive. +@dev Returns whether the item is of type undefined. + +### isArray(Item) + +```solidity +function isArray(Item memory item) internal pure returns (bool result) +``` + +Returns whether the item is of type array. + +### isObject(Item) + +```solidity +function isObject(Item memory item) internal pure returns (bool result) +``` + +Returns whether the item is of type object. + +### isNumber(Item) + +```solidity +function isNumber(Item memory item) internal pure returns (bool result) +``` + +Returns whether the item is of type number. + +### isString(Item) + +```solidity +function isString(Item memory item) internal pure returns (bool result) +``` + +Returns whether the item is of type string. + +### isBoolean(Item) + +```solidity +function isBoolean(Item memory item) internal pure returns (bool result) +``` + +Returns whether the item is of type boolean. + +### isNull(Item) + +```solidity +function isNull(Item memory item) internal pure returns (bool result) +``` + +Returns whether the item is of type null. + +### parent(Item) + +```solidity +function parent(Item memory item) + internal + pure + returns (Item memory result) +``` + +Returns the item's parent. +If the item does not have a parent, the result's type will be undefined. + +## Utility Functions + +### parseUint(string) + +```solidity +function parseUint(string memory s) + internal + pure + returns (uint256 result) +``` + +Parses an unsigned integer from a string (in decimal, i.e. base 10). +Reverts if `s` is not a valid uint256 string matching the RegEx `^[0-9]+$`, +or if the parsed number is too big for a uint256. + +### parseInt(string) + +```solidity +function parseInt(string memory s) internal pure returns (int256 result) +``` + +Parses a signed integer from a string (in decimal, i.e. base 10). +Reverts if `s` is not a valid int256 string matching the RegEx `^[+-]?[0-9]+$`, +or if the parsed number cannot fit within `[-2**255 .. 2**255 - 1]`. + +### parseUintFromHex(string) + +```solidity +function parseUintFromHex(string memory s) + internal + pure + returns (uint256 result) +``` + +Parses an unsigned integer from a string (in hexadecimal, i.e. base 16). +Reverts if `s` is not a valid uint256 hex string matching the RegEx +`^(0[xX])?[0-9a-fA-F]+$`, or if the parsed number cannot fit within `[0 .. 2**256 - 1]`. + +### decodeString(string) + +```solidity +function decodeString(string memory s) + internal + pure + returns (string memory result) +``` + +Decodes a JSON encoded string. +The string MUST be double-quoted, JSON encoded. +Reverts if the string is invalid. +As you can see, it's pretty complex for a deceptively simple looking task. \ No newline at end of file diff --git a/docs/utils/libbit.md b/docs/utils/libbit.md new file mode 100644 index 000000000..54f977458 --- /dev/null +++ b/docs/utils/libbit.md @@ -0,0 +1,137 @@ +# LibBit + +Library for bit twiddling and boolean operations. + + + + + + + + +## Bit Twiddling Operations + +### fls(uint256) + +```solidity +function fls(uint256 x) internal pure returns (uint256 r) +``` + +Find last set. +Returns the index of the most significant bit of `x`, +counting from the least significant bit position. +If `x` is zero, returns 256. + +### clz(uint256) + +```solidity +function clz(uint256 x) internal pure returns (uint256 r) +``` + +Count leading zeros. +Returns the number of zeros preceding the most significant one bit. +If `x` is zero, returns 256. + +### ffs(uint256) + +```solidity +function ffs(uint256 x) internal pure returns (uint256 r) +``` + +Find first set. +Returns the index of the least significant bit of `x`, +counting from the least significant bit position. +If `x` is zero, returns 256. +Equivalent to `ctz` (count trailing zeros), which gives +the number of zeros following the least significant one bit. + +### popCount(uint256) + +```solidity +function popCount(uint256 x) internal pure returns (uint256 c) +``` + +Returns the number of set bits in `x`. + +### isPo2(uint256) + +```solidity +function isPo2(uint256 x) internal pure returns (bool result) +``` + +Returns whether `x` is a power of 2. + +### reverseBits(uint256) + +```solidity +function reverseBits(uint256 x) internal pure returns (uint256 r) +``` + +Returns `x` reversed at the bit level. + +### reverseBytes(uint256) + +```solidity +function reverseBytes(uint256 x) internal pure returns (uint256 r) +``` + +Returns `x` reversed at the byte level. + +## Boolean Operations + +A Solidity bool on the stack or memory is represented as a 256-bit word. +Non-zero values are true, zero is false. +A clean bool is either 0 (false) or 1 (true) under the hood. +Usually, if not always, the bool result of a regular Solidity expression, +or the argument of a public/external function will be a clean bool. +You can usually use the raw variants for more performance. +If uncertain, test (best with exact compiler settings). +Or use the non-raw variants (compiler can sometimes optimize out the double `iszero`s). + +### rawAnd(bool,bool) + +```solidity +function rawAnd(bool x, bool y) internal pure returns (bool z) +``` + +Returns `x & y`. Inputs must be clean. + +### and(bool,bool) + +```solidity +function and(bool x, bool y) internal pure returns (bool z) +``` + +Returns `x & y`. + +### rawOr(bool,bool) + +```solidity +function rawOr(bool x, bool y) internal pure returns (bool z) +``` + +Returns `x | y`. Inputs must be clean. + +### or(bool,bool) + +```solidity +function or(bool x, bool y) internal pure returns (bool z) +``` + +Returns `x | y`. + +### rawToUint(bool) + +```solidity +function rawToUint(bool b) internal pure returns (uint256 z) +``` + +Returns 1 if `b` is true, else 0. Input must be clean. + +### toUint(bool) + +```solidity +function toUint(bool b) internal pure returns (uint256 z) +``` + +Returns 1 if `b` is true, else 0. \ No newline at end of file diff --git a/docs/utils/libbitmap.md b/docs/utils/libbitmap.md new file mode 100644 index 000000000..5e4150e01 --- /dev/null +++ b/docs/utils/libbitmap.md @@ -0,0 +1,135 @@ +# LibBitmap + +Library for storage of packed unsigned booleans. + + + + + + + + +## Constants + +### NOT_FOUND + +```solidity +uint256 internal constant NOT_FOUND = type(uint256).max +``` + +The constant returned when a bitmap scan does not find a result. + +## Structs + +### Bitmap + +```solidity +struct Bitmap { + mapping(uint256 => uint256) map; +} +``` + +A bitmap in storage. + +## Operations + +### get(Bitmap,uint256) + +```solidity +function get(Bitmap storage bitmap, uint256 index) + internal + view + returns (bool isSet) +``` + +Returns the boolean value of the bit at `index` in `bitmap`. + +### set(Bitmap,uint256) + +```solidity +function set(Bitmap storage bitmap, uint256 index) internal +``` + +Updates the bit at `index` in `bitmap` to true. + +### unset(Bitmap,uint256) + +```solidity +function unset(Bitmap storage bitmap, uint256 index) internal +``` + +Updates the bit at `index` in `bitmap` to false. + +### toggle(Bitmap,uint256) + +```solidity +function toggle(Bitmap storage bitmap, uint256 index) + internal + returns (bool newIsSet) +``` + +Flips the bit at `index` in `bitmap`. +Returns the boolean result of the flipped bit. + +### setTo(Bitmap,uint256,bool) + +```solidity +function setTo(Bitmap storage bitmap, uint256 index, bool shouldSet) + internal +``` + +Updates the bit at `index` in `bitmap` to `shouldSet`. + +### setBatch(Bitmap,uint256,uint256) + +```solidity +function setBatch(Bitmap storage bitmap, uint256 start, uint256 amount) + internal +``` + +Consecutively sets `amount` of bits starting from the bit at `start`. + +### unsetBatch(Bitmap,uint256,uint256) + +```solidity +function unsetBatch(Bitmap storage bitmap, uint256 start, uint256 amount) + internal +``` + +Consecutively unsets `amount` of bits starting from the bit at `start`. + +### popCount(Bitmap,uint256,uint256) + +```solidity +function popCount(Bitmap storage bitmap, uint256 start, uint256 amount) + internal + view + returns (uint256 count) +``` + +Returns number of set bits within a range by +scanning `amount` of bits starting from the bit at `start`. + +### findLastSet(Bitmap,uint256) + +```solidity +function findLastSet(Bitmap storage bitmap, uint256 upTo) + internal + view + returns (uint256 setBitIndex) +``` + +Returns the index of the most significant set bit in `[0..upTo]`. +If no set bit is found, returns `NOT_FOUND`. + +### findFirstUnset(Bitmap,uint256,uint256) + +```solidity +function findFirstUnset(Bitmap storage bitmap, uint256 begin, uint256 upTo) + internal + view + returns (uint256 unsetBitIndex) +``` + +Returns the index of the least significant unset bit in `[begin..upTo]`. +If no unset bit is found, returns `NOT_FOUND`. \ No newline at end of file diff --git a/docs/utils/libbytes.md b/docs/utils/libbytes.md new file mode 100644 index 000000000..d0e7ef375 --- /dev/null +++ b/docs/utils/libbytes.md @@ -0,0 +1,390 @@ +# LibBytes + +Library for byte related operations. + + + + + + + + +## Structs + +### BytesStorage + +```solidity +struct BytesStorage { + bytes32 _spacer; +} +``` + +Goated bytes storage struct that totally MOGs, no cap, fr. +Uses less gas and bytecode than Solidity's native bytes storage. It's meta af. +Packs length with the first 31 bytes if <255 bytes, so it’s mad tight. + +## Constants + +### NOT_FOUND + +```solidity +uint256 internal constant NOT_FOUND = type(uint256).max +``` + +The constant returned when the `search` is not found in the bytes. + +## Byte Storage Operations + +### set(BytesStorage,bytes) + +```solidity +function set(BytesStorage storage $, bytes memory s) internal +``` + +Sets the value of the bytes storage `$` to `s`. + +### setCalldata(BytesStorage,bytes) + +```solidity +function setCalldata(BytesStorage storage $, bytes calldata s) internal +``` + +Sets the value of the bytes storage `$` to `s`. + +### clear(BytesStorage) + +```solidity +function clear(BytesStorage storage $) internal +``` + +Sets the value of the bytes storage `$` to the empty bytes. + +### isEmpty(BytesStorage) + +```solidity +function isEmpty(BytesStorage storage $) internal view returns (bool) +``` + +Returns whether the value stored is `$` is the empty bytes "". + +### length(BytesStorage) + +```solidity +function length(BytesStorage storage $) + internal + view + returns (uint256 result) +``` + +Returns the length of the value stored in `$`. + +### get(BytesStorage) + +```solidity +function get(BytesStorage storage $) + internal + view + returns (bytes memory result) +``` + +Returns the value stored in `$`. + +## Bytes Operations + +### replace(bytes,bytes,bytes) + +```solidity +function replace( + bytes memory subject, + bytes memory needle, + bytes memory replacement +) internal pure returns (bytes memory result) +``` + +Returns `subject` all occurrences of `needle` replaced with `replacement`. + +### indexOf(bytes,bytes,uint256) + +```solidity +function indexOf(bytes memory subject, bytes memory needle, uint256 from) + internal + pure + returns (uint256 result) +``` + +Returns the byte index of the first location of `needle` in `subject`, +needleing from left to right, starting from `from`. +Returns `NOT_FOUND` (i.e. `type(uint256).max`) if the `needle` is not found. + +### indexOf(bytes,bytes) + +```solidity +function indexOf(bytes memory subject, bytes memory needle) + internal + pure + returns (uint256) +``` + +Returns the byte index of the first location of `needle` in `subject`, +needleing from left to right. +Returns `NOT_FOUND` (i.e. `type(uint256).max`) if the `needle` is not found. + +### lastIndexOf(bytes,bytes,uint256) + +```solidity +function lastIndexOf( + bytes memory subject, + bytes memory needle, + uint256 from +) internal pure returns (uint256 result) +``` + +Returns the byte index of the first location of `needle` in `subject`, +needleing from right to left, starting from `from`. +Returns `NOT_FOUND` (i.e. `type(uint256).max`) if the `needle` is not found. + +### lastIndexOf(bytes,bytes) + +```solidity +function lastIndexOf(bytes memory subject, bytes memory needle) + internal + pure + returns (uint256) +``` + +Returns the byte index of the first location of `needle` in `subject`, +needleing from right to left. +Returns `NOT_FOUND` (i.e. `type(uint256).max`) if the `needle` is not found. + +### contains(bytes,bytes) + +```solidity +function contains(bytes memory subject, bytes memory needle) + internal + pure + returns (bool) +``` + +Returns true if `needle` is found in `subject`, false otherwise. + +### startsWith(bytes,bytes) + +```solidity +function startsWith(bytes memory subject, bytes memory needle) + internal + pure + returns (bool result) +``` + +Returns whether `subject` starts with `needle`. + +### endsWith(bytes,bytes) + +```solidity +function endsWith(bytes memory subject, bytes memory needle) + internal + pure + returns (bool result) +``` + +Returns whether `subject` ends with `needle`. + +### repeat(bytes,uint256) + +```solidity +function repeat(bytes memory subject, uint256 times) + internal + pure + returns (bytes memory result) +``` + +Returns `subject` repeated `times`. + +### slice(bytes,uint256,uint256) + +```solidity +function slice(bytes memory subject, uint256 start, uint256 end) + internal + pure + returns (bytes memory result) +``` + +Returns a copy of `subject` sliced from `start` to `end` (exclusive). +`start` and `end` are byte offsets. + +### slice(bytes,uint256) + +```solidity +function slice(bytes memory subject, uint256 start) + internal + pure + returns (bytes memory result) +``` + +Returns a copy of `subject` sliced from `start` to the end of the bytes. +`start` is a byte offset. + +### sliceCalldata(bytes,uint256,uint256) + +```solidity +function sliceCalldata(bytes calldata subject, uint256 start, uint256 end) + internal + pure + returns (bytes calldata result) +``` + +Returns a copy of `subject` sliced from `start` to `end` (exclusive). +`start` and `end` are byte offsets. Faster than Solidity's native slicing. + +### sliceCalldata(bytes,uint256) + +```solidity +function sliceCalldata(bytes calldata subject, uint256 start) + internal + pure + returns (bytes calldata result) +``` + +Returns a copy of `subject` sliced from `start` to the end of the bytes. +`start` is a byte offset. Faster than Solidity's native slicing. + +### truncate(bytes,uint256) + +```solidity +function truncate(bytes memory subject, uint256 n) + internal + pure + returns (bytes memory result) +``` + +Reduces the size of `subject` to `n`. +If `n` is greater than the size of `subject`, this will be a no-op. + +### truncatedCalldata(bytes,uint256) + +```solidity +function truncatedCalldata(bytes calldata subject, uint256 n) + internal + pure + returns (bytes calldata result) +``` + +Returns a copy of `subject`, with the length reduced to `n`. +If `n` is greater than the size of `subject`, this will be a no-op. + +### indicesOf(bytes,bytes) + +```solidity +function indicesOf(bytes memory subject, bytes memory needle) + internal + pure + returns (uint256[] memory result) +``` + +Returns all the indices of `needle` in `subject`. +The indices are byte offsets. + +### split(bytes,bytes) + +```solidity +function split(bytes memory subject, bytes memory delimiter) + internal + pure + returns (bytes[] memory result) +``` + +Returns a arrays of bytess based on the `delimiter` inside of the `subject` bytes. + +### concat(bytes,bytes) + +```solidity +function concat(bytes memory a, bytes memory b) + internal + pure + returns (bytes memory result) +``` + +Returns a concatenated bytes of `a` and `b`. +Cheaper than `bytes.concat()` and does not de-align the free memory pointer. + +### eq(bytes,bytes) + +```solidity +function eq(bytes memory a, bytes memory b) + internal + pure + returns (bool result) +``` + +Returns whether `a` equals `b`. + +### eqs(bytes,bytes32) + +```solidity +function eqs(bytes memory a, bytes32 b) + internal + pure + returns (bool result) +``` + +Returns whether `a` equals `b`, where `b` is a null-terminated small bytes. + +### cmp(bytes,bytes) + +```solidity +function cmp(bytes memory a, bytes memory b) + internal + pure + returns (int256 result) +``` + +Returns 0 if `a == b`, -1 if `a < b`, +1 if `a > b`. +If `a` == b[:a.length]`, and `a.length < b.length`, returns -1. + +### directReturn(bytes) + +```solidity +function directReturn(bytes memory a) internal pure +``` + +Directly returns `a` without copying. + +### directReturn(bytes[]) + +```solidity +function directReturn(bytes[] memory a) internal pure +``` + +Directly returns `a` with minimal copying. + +### load(bytes,uint256) + +```solidity +function load(bytes memory a, uint256 offset) + internal + pure + returns (bytes32 result) +``` + +Returns the word at `offset`, without any bounds checks. +To load an address, you can use `address(bytes20(load(a, offset)))`. + +### loadCalldata(bytes,uint256) + +```solidity +function loadCalldata(bytes calldata a, uint256 offset) + internal + pure + returns (bytes32 result) +``` + +Returns the word at `offset`, without any bounds checks. +To load an address, you can use `address(bytes20(loadCalldata(a, offset)))`. + +### emptyCalldata() + +```solidity +function emptyCalldata() internal pure returns (bytes calldata result) +``` + +Returns empty calldata bytes. For silencing the compiler. \ No newline at end of file diff --git a/docs/utils/libcall.md b/docs/utils/libcall.md new file mode 100644 index 000000000..da4aaf4cd --- /dev/null +++ b/docs/utils/libcall.md @@ -0,0 +1,139 @@ +# LibCall + +Library for making calls. + + +Note: + +- The arguments of the functions may differ from the libraries. +Please read the functions carefully before use. + + + + + +## Custom Errors + +### TargetIsNotContract() + +```solidity +error TargetIsNotContract() +``` + +The target of the call is not a contract. + +### DataTooShort() + +```solidity +error DataTooShort() +``` + +The data is too short to contain a function selector. + +## Contract Call Operations + +These functions will revert if called on a non-contract +(i.e. address without code). +They will bubble up the revert if the call fails. + +### callContract(address,uint256,bytes) + +```solidity +function callContract(address target, uint256 value, bytes memory data) + internal + returns (bytes memory result) +``` + +Makes a call to `target`, with `data` and `value`. + +### callContract(address,bytes) + +```solidity +function callContract(address target, bytes memory data) + internal + returns (bytes memory result) +``` + +Makes a call to `target`, with `data`. + +### staticCallContract(address,bytes) + +```solidity +function staticCallContract(address target, bytes memory data) + internal + view + returns (bytes memory result) +``` + +Makes a static call to `target`, with `data`. + +### delegateCallContract(address,bytes) + +```solidity +function delegateCallContract(address target, bytes memory data) + internal + returns (bytes memory result) +``` + +Makes a delegate call to `target`, with `data`. + +## Try Call Operations + +These functions enable gas limited calls to be performed, +with a cap on the number of return data bytes to be copied. +The can be used to ensure that the calling contract will not +run out-of-gas. + +### tryCall(address,uint256,uint256,uint16,bytes) + +```solidity +function tryCall( + address target, + uint256 value, + uint256 gasStipend, + uint16 maxCopy, + bytes memory data +) + internal + returns (bool success, bool exceededMaxCopy, bytes memory result) +``` + +Makes a call to `target`, with `data` and `value`. +The call is given a gas limit of `gasStipend`, +and up to `maxCopy` bytes of return data can be copied. + +### tryStaticCall(address,uint256,uint16,bytes) + +```solidity +function tryStaticCall( + address target, + uint256 gasStipend, + uint16 maxCopy, + bytes memory data +) + internal + view + returns (bool success, bool exceededMaxCopy, bytes memory result) +``` + +Makes a call to `target`, with `data`. +The call is given a gas limit of `gasStipend`, +and up to `maxCopy` bytes of return data can be copied. + +## Other Operations + +### bubbleUpRevert(bytes) + +```solidity +function bubbleUpRevert(bytes memory revertReturnData) internal pure +``` + +Bubbles up the revert. + +### setSelector(bytes4,bytes) + +```solidity +function setSelector(bytes4 newSelector, bytes memory data) internal pure +``` + +In-place replaces the function selector of encoded contract call data. \ No newline at end of file diff --git a/docs/utils/libclone.md b/docs/utils/libclone.md new file mode 100644 index 000000000..e9ac1a91d --- /dev/null +++ b/docs/utils/libclone.md @@ -0,0 +1,1706 @@ +# LibClone + +Minimal proxy library. + + +Minimal proxy: + +Although the sw0nt pattern saves 5 gas over the ERC1167 pattern during runtime, +it is not supported out-of-the-box on Etherscan. Hence, we choose to use the 0age pattern, +which saves 4 gas over the ERC1167 pattern during runtime, and has the smallest bytecode. +- Automatically verified on Etherscan. + +Minimal proxy (PUSH0 variant): + +This is a new minimal proxy that uses the PUSH0 opcode introduced during Shanghai. +It is optimized first for minimal runtime gas, then for minimal bytecode. +The PUSH0 clone functions are intentionally postfixed with a jarring "_PUSH0" as +many EVM chains may not support the PUSH0 opcode in the early months after Shanghai. +Please use with caution. +- Automatically verified on Etherscan. + +Clones with immutable args (CWIA): + +The implementation of CWIA here is does NOT append the immutable args into the calldata +passed into delegatecall. It is simply an ERC1167 minimal proxy with the immutable arguments +appended to the back of the runtime bytecode. +- Uses the identity precompile (0x4) to copy args during deployment. + +Minimal ERC1967 proxy: + +An minimal ERC1967 proxy, intended to be upgraded with UUPS. +This is NOT the same as ERC1967Factory's transparent proxy, which includes admin logic. +- Automatically verified on Etherscan. + +Minimal ERC1967 proxy with immutable args: + +- Uses the identity precompile (0x4) to copy args during deployment. +- Automatically verified on Etherscan. + +ERC1967I proxy: + +An variant of the minimal ERC1967 proxy, with a special code path that activates +if `calldatasize() == 1`. This code path skips the delegatecall and directly returns the +`implementation` address. The returned implementation is guaranteed to be valid if the +keccak256 of the proxy's code is equal to `ERC1967I_CODE_HASH`. + +ERC1967I proxy with immutable args: + +An variant of the minimal ERC1967 proxy, with a special code path that activates +if `calldatasize() == 1`. This code path skips the delegatecall and directly returns the +- Uses the identity precompile (0x4) to copy args during deployment. + +Minimal ERC1967 beacon proxy: + +A minimal beacon proxy, intended to be upgraded with an upgradable beacon. +- Automatically verified on Etherscan. + +Minimal ERC1967 beacon proxy with immutable args: + +- Uses the identity precompile (0x4) to copy args during deployment. +- Automatically verified on Etherscan. + +ERC1967I beacon proxy: + +An variant of the minimal ERC1967 beacon proxy, with a special code path that activates +if `calldatasize() == 1`. This code path skips the delegatecall and directly returns the +`implementation` address. The returned implementation is guaranteed to be valid if the +keccak256 of the proxy's code is equal to `ERC1967I_CODE_HASH`. + +ERC1967I proxy with immutable args: + +An variant of the minimal ERC1967 beacon proxy, with a special code path that activates +if `calldatasize() == 1`. This code path skips the delegatecall and directly returns the +- Uses the identity precompile (0x4) to copy args during deployment. + + + + + +## Constants + +### CLONE_CODE_HASH + +```solidity +bytes32 internal constant CLONE_CODE_HASH = + 0x48db2cfdb2853fce0b464f1f93a1996469459df3ab6c812106074c4106a1eb1f +``` + +The keccak256 of deployed code for the clone proxy, +with the implementation set to `address(0)`. + +### PUSH0_CLONE_CODE_HASH + +```solidity +bytes32 internal constant PUSH0_CLONE_CODE_HASH = + 0x67bc6bde1b84d66e267c718ba44cf3928a615d29885537955cb43d44b3e789dc +``` + +The keccak256 of deployed code for the PUSH0 proxy, +with the implementation set to `address(0)`. + +### CWIA_CODE_HASH + +```solidity +bytes32 internal constant CWIA_CODE_HASH = + 0x3cf92464268225a4513da40a34d967354684c32cd0edd67b5f668dfe3550e940 +``` + +The keccak256 of deployed code for the ERC-1167 CWIA proxy, +with the implementation set to `address(0)`. + +### ERC1967_CODE_HASH + +```solidity +bytes32 internal constant ERC1967_CODE_HASH = + 0xaaa52c8cc8a0e3fd27ce756cc6b4e70c51423e9b597b11f32d3e49f8b1fc890d +``` + +The keccak256 of the deployed code for the ERC1967 proxy. + +### ERC1967I_CODE_HASH + +```solidity +bytes32 internal constant ERC1967I_CODE_HASH = + 0xce700223c0d4cea4583409accfc45adac4a093b3519998a9cbbe1504dadba6f7 +``` + +The keccak256 of the deployed code for the ERC1967I proxy. + +### ERC1967_BEACON_PROXY_CODE_HASH + +```solidity +bytes32 internal constant ERC1967_BEACON_PROXY_CODE_HASH = + 0x14044459af17bc4f0f5aa2f658cb692add77d1302c29fe2aebab005eea9d1162 +``` + +The keccak256 of the deployed code for the ERC1967 beacon proxy. + +### ERC1967I_BEACON_PROXY_CODE_HASH + +```solidity +bytes32 internal constant ERC1967I_BEACON_PROXY_CODE_HASH = + 0xf8c46d2793d5aa984eb827aeaba4b63aedcab80119212fce827309788735519a +``` + +The keccak256 of the deployed code for the ERC1967 beacon proxy. + +## Custom Errors + +### DeploymentFailed() + +```solidity +error DeploymentFailed() +``` + +Unable to deploy the clone. + +### SaltDoesNotStartWith() + +```solidity +error SaltDoesNotStartWith() +``` + +The salt must start with either the zero address or `by`. + +### ETHTransferFailed() + +```solidity +error ETHTransferFailed() +``` + +The ETH transfer has failed. + +## Minimal Proxy Operations + +### clone(address) + +```solidity +function clone(address implementation) + internal + returns (address instance) +``` + +Deploys a clone of `implementation`. + +### clone(uint256,address) + +```solidity +function clone(uint256 value, address implementation) + internal + returns (address instance) +``` + +Deploys a clone of `implementation`. +Deposits `value` ETH during deployment. + +### cloneDeterministic(address,bytes32) + +```solidity +function cloneDeterministic(address implementation, bytes32 salt) + internal + returns (address instance) +``` + +Deploys a deterministic clone of `implementation` with `salt`. + +### cloneDeterministic(uint256,address,bytes32) + +```solidity +function cloneDeterministic( + uint256 value, + address implementation, + bytes32 salt +) internal returns (address instance) +``` + +Deploys a deterministic clone of `implementation` with `salt`. +Deposits `value` ETH during deployment. + +### initCode(address) + +```solidity +function initCode(address implementation) + internal + pure + returns (bytes memory c) +``` + +Returns the initialization code of the clone of `implementation`. + +### initCodeHash(address) + +```solidity +function initCodeHash(address implementation) + internal + pure + returns (bytes32 hash) +``` + +Returns the initialization code hash of the clone of `implementation`. + +### predictDeterministicAddress(address,bytes32,address) + +```solidity +function predictDeterministicAddress( + address implementation, + bytes32 salt, + address deployer +) internal pure returns (address predicted) +``` + +Returns the address of the clone of `implementation`, with `salt` by `deployer`. +Note: The returned result has dirty upper 96 bits. Please clean if used in assembly. + +## Minimal Proxy Operations (PUSH0 Variant) + +### clone_PUSH0(address) + +```solidity +function clone_PUSH0(address implementation) + internal + returns (address instance) +``` + +Deploys a PUSH0 clone of `implementation`. + +### clone_PUSH0(uint256,address) + +```solidity +function clone_PUSH0(uint256 value, address implementation) + internal + returns (address instance) +``` + +Deploys a PUSH0 clone of `implementation`. +Deposits `value` ETH during deployment. + +### cloneDeterministic_PUSH0(address,bytes32) + +```solidity +function cloneDeterministic_PUSH0(address implementation, bytes32 salt) + internal + returns (address instance) +``` + +Deploys a deterministic PUSH0 clone of `implementation` with `salt`. + +### cloneDeterministic_PUSH0(uint256,address,bytes32) + +```solidity +function cloneDeterministic_PUSH0( + uint256 value, + address implementation, + bytes32 salt +) internal returns (address instance) +``` + +Deploys a deterministic PUSH0 clone of `implementation` with `salt`. +Deposits `value` ETH during deployment. + +### initCode_PUSH0(address) + +```solidity +function initCode_PUSH0(address implementation) + internal + pure + returns (bytes memory c) +``` + +Returns the initialization code of the PUSH0 clone of `implementation`. + +### initCodeHash_PUSH0(address) + +```solidity +function initCodeHash_PUSH0(address implementation) + internal + pure + returns (bytes32 hash) +``` + +Returns the initialization code hash of the PUSH0 clone of `implementation`. + +### predictDeterministicAddress_PUSH0(address,bytes32,address) + +```solidity +function predictDeterministicAddress_PUSH0( + address implementation, + bytes32 salt, + address deployer +) internal pure returns (address predicted) +``` + +Returns the address of the PUSH0 clone of `implementation`, with `salt` by `deployer`. +Note: The returned result has dirty upper 96 bits. Please clean if used in assembly. + +## Clones With Immutable Args Operations + +### clone(address,bytes) + +```solidity +function clone(address implementation, bytes memory args) + internal + returns (address instance) +``` + +Deploys a clone of `implementation` with immutable arguments encoded in `args`. + +### clone(uint256,address,bytes) + +```solidity +function clone(uint256 value, address implementation, bytes memory args) + internal + returns (address instance) +``` + +Deploys a clone of `implementation` with immutable arguments encoded in `args`. +Deposits `value` ETH during deployment. + +### cloneDeterministic(address,bytes,bytes32) + +```solidity +function cloneDeterministic( + address implementation, + bytes memory args, + bytes32 salt +) internal returns (address instance) +``` + +Deploys a deterministic clone of `implementation` +with immutable arguments encoded in `args` and `salt`. + +### cloneDeterministic(uint256,address,bytes,bytes32) + +```solidity +function cloneDeterministic( + uint256 value, + address implementation, + bytes memory args, + bytes32 salt +) internal returns (address instance) +``` + +Deploys a deterministic clone of `implementation` +with immutable arguments encoded in `args` and `salt`. + +### createDeterministicClone(address,bytes,bytes32) + +```solidity +function createDeterministicClone( + address implementation, + bytes memory args, + bytes32 salt +) internal returns (bool alreadyDeployed, address instance) +``` + +Deploys a deterministic clone of `implementation` +with immutable arguments encoded in `args` and `salt`. +This method does not revert if the clone has already been deployed. + +### createDeterministicClone(uint256,address,bytes,bytes32) + +```solidity +function createDeterministicClone( + uint256 value, + address implementation, + bytes memory args, + bytes32 salt +) internal returns (bool alreadyDeployed, address instance) +``` + +Deploys a deterministic clone of `implementation` +with immutable arguments encoded in `args` and `salt`. +This method does not revert if the clone has already been deployed. + +### initCode(address,bytes) + +```solidity +function initCode(address implementation, bytes memory args) + internal + pure + returns (bytes memory c) +``` + +Returns the initialization code hash of the clone of `implementation` +using immutable arguments encoded in `args`. + +### initCodeHash(address,bytes) + +```solidity +function initCodeHash(address implementation, bytes memory args) + internal + pure + returns (bytes32 hash) +``` + +Returns the initialization code hash of the clone of `implementation` +using immutable arguments encoded in `args`. + +### predictDeterministicAddress(address,bytes,bytes32,address) + +```solidity +function predictDeterministicAddress( + address implementation, + bytes memory data, + bytes32 salt, + address deployer +) internal pure returns (address predicted) +``` + +Returns the address of the clone of +`implementation` using immutable arguments encoded in `args`, with `salt`, by `deployer`. +Note: The returned result has dirty upper 96 bits. Please clean if used in assembly. + +### argsOnClone(address) + +```solidity +function argsOnClone(address instance) + internal + view + returns (bytes memory args) +``` + +Equivalent to `argsOnClone(instance, 0, 2 ** 256 - 1)`. + +### argsOnClone(address,uint256) + +```solidity +function argsOnClone(address instance, uint256 start) + internal + view + returns (bytes memory args) +``` + +Equivalent to `argsOnClone(instance, start, 2 ** 256 - 1)`. + +### argsOnClone(address,uint256,uint256) + +```solidity +function argsOnClone(address instance, uint256 start, uint256 end) + internal + view + returns (bytes memory args) +``` + +Returns a slice of the immutable arguments on `instance` from `start` to `end`. +`start` and `end` will be clamped to the range `[0, args.length]`. +The `instance` MUST be deployed via the clone with immutable args functions. +Otherwise, the behavior is undefined. +Out-of-gas reverts if `instance` does not have any code. + +## Minimal ERC1967 Proxy Operations + +Note: The ERC1967 proxy here is intended to be upgraded with UUPS. +This is NOT the same as ERC1967Factory's transparent proxy, which includes admin logic. + +### deployERC1967(address) + +```solidity +function deployERC1967(address implementation) + internal + returns (address instance) +``` + +Deploys a minimal ERC1967 proxy with `implementation`. + +### deployERC1967(uint256,address) + +```solidity +function deployERC1967(uint256 value, address implementation) + internal + returns (address instance) +``` + +Deploys a minimal ERC1967 proxy with `implementation`. +Deposits `value` ETH during deployment. + +### deployDeterministicERC1967(address,bytes32) + +```solidity +function deployDeterministicERC1967(address implementation, bytes32 salt) + internal + returns (address instance) +``` + +Deploys a deterministic minimal ERC1967 proxy with `implementation` and `salt`. + +### deployDeterministicERC1967(uint256,address,bytes32) + +```solidity +function deployDeterministicERC1967( + uint256 value, + address implementation, + bytes32 salt +) internal returns (address instance) +``` + +Deploys a deterministic minimal ERC1967 proxy with `implementation` and `salt`. +Deposits `value` ETH during deployment. + +### createDeterministicERC1967(address,bytes32) + +```solidity +function createDeterministicERC1967(address implementation, bytes32 salt) + internal + returns (bool alreadyDeployed, address instance) +``` + +Creates a deterministic minimal ERC1967 proxy with `implementation` and `salt`. +Note: This method is intended for use in ERC4337 factories, +which are expected to NOT revert if the proxy is already deployed. + +### createDeterministicERC1967(uint256,address,bytes32) + +```solidity +function createDeterministicERC1967( + uint256 value, + address implementation, + bytes32 salt +) internal returns (bool alreadyDeployed, address instance) +``` + +Creates a deterministic minimal ERC1967 proxy with `implementation` and `salt`. +Deposits `value` ETH during deployment. +Note: This method is intended for use in ERC4337 factories, +which are expected to NOT revert if the proxy is already deployed. + +### initCodeERC1967(address) + +```solidity +function initCodeERC1967(address implementation) + internal + pure + returns (bytes memory c) +``` + +Returns the initialization code of the minimal ERC1967 proxy of `implementation`. + +### initCodeHashERC1967(address) + +```solidity +function initCodeHashERC1967(address implementation) + internal + pure + returns (bytes32 hash) +``` + +Returns the initialization code hash of the minimal ERC1967 proxy of `implementation`. + +### predictDeterministicAddressERC1967(address,bytes32,address) + +```solidity +function predictDeterministicAddressERC1967( + address implementation, + bytes32 salt, + address deployer +) internal pure returns (address predicted) +``` + +Returns the address of the ERC1967 proxy of `implementation`, with `salt` by `deployer`. +Note: The returned result has dirty upper 96 bits. Please clean if used in assembly. + +## Minimal ERC1967 Proxy With Immutable Args Operations + +### deployERC1967(address,bytes) + +```solidity +function deployERC1967(address implementation, bytes memory args) + internal + returns (address instance) +``` + +Deploys a minimal ERC1967 proxy with `implementation` and `args`. + +### deployERC1967(uint256,address,bytes) + +```solidity +function deployERC1967( + uint256 value, + address implementation, + bytes memory args +) internal returns (address instance) +``` + +Deploys a minimal ERC1967 proxy with `implementation` and `args`. +Deposits `value` ETH during deployment. + +### deployDeterministicERC1967(address,bytes,bytes32) + +```solidity +function deployDeterministicERC1967( + address implementation, + bytes memory args, + bytes32 salt +) internal returns (address instance) +``` + +Deploys a deterministic minimal ERC1967 proxy with `implementation`, `args` and `salt`. + +### deployDeterministicERC1967(uint256,address,bytes,bytes32) + +```solidity +function deployDeterministicERC1967( + uint256 value, + address implementation, + bytes memory args, + bytes32 salt +) internal returns (address instance) +``` + +Deploys a deterministic minimal ERC1967 proxy with `implementation`, `args` and `salt`. +Deposits `value` ETH during deployment. + +### createDeterministicERC1967(address,bytes,bytes32) + +```solidity +function createDeterministicERC1967( + address implementation, + bytes memory args, + bytes32 salt +) internal returns (bool alreadyDeployed, address instance) +``` + +Creates a deterministic minimal ERC1967 proxy with `implementation`, `args` and `salt`. +Note: This method is intended for use in ERC4337 factories, +which are expected to NOT revert if the proxy is already deployed. + +### createDeterministicERC1967(uint256,address,bytes,bytes32) + +```solidity +function createDeterministicERC1967( + uint256 value, + address implementation, + bytes memory args, + bytes32 salt +) internal returns (bool alreadyDeployed, address instance) +``` + +Creates a deterministic minimal ERC1967 proxy with `implementation`, `args` and `salt`. +Deposits `value` ETH during deployment. +Note: This method is intended for use in ERC4337 factories, +which are expected to NOT revert if the proxy is already deployed. + +### initCodeERC1967(address,bytes) + +```solidity +function initCodeERC1967(address implementation, bytes memory args) + internal + pure + returns (bytes memory c) +``` + +Returns the initialization code of the minimal ERC1967 proxy of `implementation` and `args`. + +### initCodeHashERC1967(address,bytes) + +```solidity +function initCodeHashERC1967(address implementation, bytes memory args) + internal + pure + returns (bytes32 hash) +``` + +Returns the initialization code hash of the minimal ERC1967 proxy of `implementation` and `args`. + +### predictDeterministicAddressERC1967(address,bytes,bytes32,address) + +```solidity +function predictDeterministicAddressERC1967( + address implementation, + bytes memory args, + bytes32 salt, + address deployer +) internal pure returns (address predicted) +``` + +Returns the address of the ERC1967 proxy of `implementation`, `args`, with `salt` by `deployer`. +Note: The returned result has dirty upper 96 bits. Please clean if used in assembly. + +### argsOnERC1967(address) + +```solidity +function argsOnERC1967(address instance) + internal + view + returns (bytes memory args) +``` + +Equivalent to `argsOnERC1967(instance, start, 2 ** 256 - 1)`. + +### argsOnERC1967(address,uint256) + +```solidity +function argsOnERC1967(address instance, uint256 start) + internal + view + returns (bytes memory args) +``` + +Equivalent to `argsOnERC1967(instance, start, 2 ** 256 - 1)`. + +### argsOnERC1967(address,uint256,uint256) + +```solidity +function argsOnERC1967(address instance, uint256 start, uint256 end) + internal + view + returns (bytes memory args) +``` + +Returns a slice of the immutable arguments on `instance` from `start` to `end`. +`start` and `end` will be clamped to the range `[0, args.length]`. +The `instance` MUST be deployed via the ERC1967 with immutable args functions. +Otherwise, the behavior is undefined. +Out-of-gas reverts if `instance` does not have any code. + +## ERC1967I Proxy Operations + +Note: This proxy has a special code path that activates if `calldatasize() == 1`. +This code path skips the delegatecall and directly returns the `implementation` address. +The returned implementation is guaranteed to be valid if the keccak256 of the +proxy's code is equal to `ERC1967I_CODE_HASH`. + +### deployERC1967I(address) + +```solidity +function deployERC1967I(address implementation) + internal + returns (address instance) +``` + +Deploys a ERC1967I proxy with `implementation`. + +### deployERC1967I(uint256,address) + +```solidity +function deployERC1967I(uint256 value, address implementation) + internal + returns (address instance) +``` + +Deploys a ERC1967I proxy with `implementation`. +Deposits `value` ETH during deployment. + +### deployDeterministicERC1967I(address,bytes32) + +```solidity +function deployDeterministicERC1967I(address implementation, bytes32 salt) + internal + returns (address instance) +``` + +Deploys a deterministic ERC1967I proxy with `implementation` and `salt`. + +### deployDeterministicERC1967I(uint256,address,bytes32) + +```solidity +function deployDeterministicERC1967I( + uint256 value, + address implementation, + bytes32 salt +) internal returns (address instance) +``` + +Deploys a deterministic ERC1967I proxy with `implementation` and `salt`. +Deposits `value` ETH during deployment. + +### createDeterministicERC1967I(address,bytes32) + +```solidity +function createDeterministicERC1967I(address implementation, bytes32 salt) + internal + returns (bool alreadyDeployed, address instance) +``` + +Creates a deterministic ERC1967I proxy with `implementation` and `salt`. +Note: This method is intended for use in ERC4337 factories, +which are expected to NOT revert if the proxy is already deployed. + +### createDeterministicERC1967I(uint256,address,bytes32) + +```solidity +function createDeterministicERC1967I( + uint256 value, + address implementation, + bytes32 salt +) internal returns (bool alreadyDeployed, address instance) +``` + +Creates a deterministic ERC1967I proxy with `implementation` and `salt`. +Deposits `value` ETH during deployment. +Note: This method is intended for use in ERC4337 factories, +which are expected to NOT revert if the proxy is already deployed. + +### initCodeERC1967I(address) + +```solidity +function initCodeERC1967I(address implementation) + internal + pure + returns (bytes memory c) +``` + +Returns the initialization code of the ERC1967I proxy of `implementation`. + +### initCodeHashERC1967I(address) + +```solidity +function initCodeHashERC1967I(address implementation) + internal + pure + returns (bytes32 hash) +``` + +Returns the initialization code hash of the ERC1967I proxy of `implementation`. + +### predictDeterministicAddressERC1967I(address,bytes32,address) + +```solidity +function predictDeterministicAddressERC1967I( + address implementation, + bytes32 salt, + address deployer +) internal pure returns (address predicted) +``` + +Returns the address of the ERC1967I proxy of `implementation`, with `salt` by `deployer`. +Note: The returned result has dirty upper 96 bits. Please clean if used in assembly. + +## ERC1967I Proxy With Immutable Args Operations + +### deployERC1967I(address,bytes) + +```solidity +function deployERC1967I(address implementation, bytes memory args) + internal + returns (address) +``` + +Deploys a minimal ERC1967I proxy with `implementation` and `args`. + +### deployERC1967I(uint256,address,bytes) + +```solidity +function deployERC1967I( + uint256 value, + address implementation, + bytes memory args +) internal returns (address instance) +``` + +Deploys a minimal ERC1967I proxy with `implementation` and `args`. +Deposits `value` ETH during deployment. + +### deployDeterministicERC1967I(address,bytes,bytes32) + +```solidity +function deployDeterministicERC1967I( + address implementation, + bytes memory args, + bytes32 salt +) internal returns (address instance) +``` + +Deploys a deterministic ERC1967I proxy with `implementation`, `args`, and `salt`. + +### deployDeterministicERC1967I(uint256,address,bytes,bytes32) + +```solidity +function deployDeterministicERC1967I( + uint256 value, + address implementation, + bytes memory args, + bytes32 salt +) internal returns (address instance) +``` + +Deploys a deterministic ERC1967I proxy with `implementation`, `args`, and `salt`. +Deposits `value` ETH during deployment. + +### createDeterministicERC1967I(address,bytes,bytes32) + +```solidity +function createDeterministicERC1967I( + address implementation, + bytes memory args, + bytes32 salt +) internal returns (bool alreadyDeployed, address instance) +``` + +Creates a deterministic ERC1967I proxy with `implementation`, `args` and `salt`. +Note: This method is intended for use in ERC4337 factories, +which are expected to NOT revert if the proxy is already deployed. + +### createDeterministicERC1967I(uint256,address,bytes,bytes32) + +```solidity +function createDeterministicERC1967I( + uint256 value, + address implementation, + bytes memory args, + bytes32 salt +) internal returns (bool alreadyDeployed, address instance) +``` + +Creates a deterministic ERC1967I proxy with `implementation`, `args` and `salt`. +Deposits `value` ETH during deployment. +Note: This method is intended for use in ERC4337 factories, +which are expected to NOT revert if the proxy is already deployed. + +### initCodeERC1967I(address,bytes) + +```solidity +function initCodeERC1967I(address implementation, bytes memory args) + internal + pure + returns (bytes memory c) +``` + +Returns the initialization code of the ERC1967I proxy of `implementation` and `args`. + +### initCodeHashERC1967I(address,bytes) + +```solidity +function initCodeHashERC1967I(address implementation, bytes memory args) + internal + pure + returns (bytes32 hash) +``` + +Returns the initialization code hash of the ERC1967I proxy of `implementation` and `args. + +### predictDeterministicAddressERC1967I(address,bytes,bytes32,address) + +```solidity +function predictDeterministicAddressERC1967I( + address implementation, + bytes memory args, + bytes32 salt, + address deployer +) internal pure returns (address predicted) +``` + +Returns the address of the ERC1967I proxy of `implementation`, `args` with `salt` by `deployer`. +Note: The returned result has dirty upper 96 bits. Please clean if used in assembly. + +### argsOnERC1967I(address) + +```solidity +function argsOnERC1967I(address instance) + internal + view + returns (bytes memory args) +``` + +Equivalent to `argsOnERC1967I(instance, start, 2 ** 256 - 1)`. + +### argsOnERC1967I(address,uint256) + +```solidity +function argsOnERC1967I(address instance, uint256 start) + internal + view + returns (bytes memory args) +``` + +Equivalent to `argsOnERC1967I(instance, start, 2 ** 256 - 1)`. + +### argsOnERC1967I(address,uint256,uint256) + +```solidity +function argsOnERC1967I(address instance, uint256 start, uint256 end) + internal + view + returns (bytes memory args) +``` + +Returns a slice of the immutable arguments on `instance` from `start` to `end`. +`start` and `end` will be clamped to the range `[0, args.length]`. +The `instance` MUST be deployed via the ERC1967 with immutable args functions. +Otherwise, the behavior is undefined. +Out-of-gas reverts if `instance` does not have any code. + +## ERC1967 Bootstrap Operations + +A bootstrap is a minimal UUPS implementation that allows an ERC1967 proxy +pointing to it to be upgraded. The ERC1967 proxy can then be deployed to a +deterministic address independent of the implementation: +```solidity +address bootstrap = LibClone.erc1967Bootstrap(); +address instance = LibClone.deployDeterministicERC1967(0, bootstrap, salt); +LibClone.bootstrapERC1967(bootstrap, implementation); +``` + +### erc1967Bootstrap() + +```solidity +function erc1967Bootstrap() internal returns (address) +``` + +Deploys the ERC1967 bootstrap if it has not been deployed. + +### erc1967Bootstrap(address) + +```solidity +function erc1967Bootstrap(address authorizedUpgrader) + internal + returns (address bootstrap) +``` + +Deploys the ERC1967 bootstrap if it has not been deployed. + +### bootstrapERC1967(address,address) + +```solidity +function bootstrapERC1967(address instance, address implementation) + internal +``` + +Replaces the implementation at `instance`. + +### bootstrapERC1967AndCall(address,address,bytes) + +```solidity +function bootstrapERC1967AndCall( + address instance, + address implementation, + bytes memory data +) internal +``` + +Replaces the implementation at `instance`, and then call it with `data`. + +### predictDeterministicAddressERC1967Bootstrap() + +```solidity +function predictDeterministicAddressERC1967Bootstrap() + internal + view + returns (address) +``` + +Returns the implementation address of the ERC1967 bootstrap for this contract. + +### predictDeterministicAddressERC1967Bootstrap(address,address) + +```solidity +function predictDeterministicAddressERC1967Bootstrap( + address authorizedUpgrader, + address deployer +) internal pure returns (address) +``` + +Returns the implementation address of the ERC1967 bootstrap for this contract. + +### initCodeERC1967Bootstrap(address) + +```solidity +function initCodeERC1967Bootstrap(address authorizedUpgrader) + internal + pure + returns (bytes memory c) +``` + +Returns the initialization code of the ERC1967 bootstrap. + +### initCodeHashERC1967Bootstrap(address) + +```solidity +function initCodeHashERC1967Bootstrap(address authorizedUpgrader) + internal + pure + returns (bytes32) +``` + +Returns the initialization code hash of the ERC1967 bootstrap. + +## Minimal ERC1967 Beacon Proxy Operations + +Note: If you use this proxy, you MUST make sure that the beacon is a +valid ERC1967 beacon. This means that the beacon must always return a valid +address upon a staticcall to `implementation()`, given sufficient gas. +For performance, the deployment operations and the proxy assumes that the +beacon is always valid and will NOT validate it. + +### deployERC1967BeaconProxy(address) + +```solidity +function deployERC1967BeaconProxy(address beacon) + internal + returns (address instance) +``` + +Deploys a minimal ERC1967 beacon proxy. + +### deployERC1967BeaconProxy(uint256,address) + +```solidity +function deployERC1967BeaconProxy(uint256 value, address beacon) + internal + returns (address instance) +``` + +Deploys a minimal ERC1967 beacon proxy. +Deposits `value` ETH during deployment. + +### deployDeterministicERC1967BeaconProxy(address,bytes32) + +```solidity +function deployDeterministicERC1967BeaconProxy(address beacon, bytes32 salt) + internal + returns (address instance) +``` + +Deploys a deterministic minimal ERC1967 beacon proxy with `salt`. + +### deployDeterministicERC1967BeaconProxy(uint256,address,bytes32) + +```solidity +function deployDeterministicERC1967BeaconProxy( + uint256 value, + address beacon, + bytes32 salt +) internal returns (address instance) +``` + +Deploys a deterministic minimal ERC1967 beacon proxy with `salt`. +Deposits `value` ETH during deployment. + +### createDeterministicERC1967BeaconProxy(address,bytes32) + +```solidity +function createDeterministicERC1967BeaconProxy(address beacon, bytes32 salt) + internal + returns (bool alreadyDeployed, address instance) +``` + +Creates a deterministic minimal ERC1967 beacon proxy with `salt`. +Note: This method is intended for use in ERC4337 factories, +which are expected to NOT revert if the proxy is already deployed. + +### createDeterministicERC1967BeaconProxy(uint256,address,bytes32) + +```solidity +function createDeterministicERC1967BeaconProxy( + uint256 value, + address beacon, + bytes32 salt +) internal returns (bool alreadyDeployed, address instance) +``` + +Creates a deterministic minimal ERC1967 beacon proxy with `salt`. +Deposits `value` ETH during deployment. +Note: This method is intended for use in ERC4337 factories, +which are expected to NOT revert if the proxy is already deployed. + +### initCodeERC1967BeaconProxy(address) + +```solidity +function initCodeERC1967BeaconProxy(address beacon) + internal + pure + returns (bytes memory c) +``` + +Returns the initialization code of the minimal ERC1967 beacon proxy. + +### initCodeHashERC1967BeaconProxy(address) + +```solidity +function initCodeHashERC1967BeaconProxy(address beacon) + internal + pure + returns (bytes32 hash) +``` + +Returns the initialization code hash of the minimal ERC1967 beacon proxy. + +### predictDeterministicAddressERC1967BeaconProxy(address,bytes32,address) + +```solidity +function predictDeterministicAddressERC1967BeaconProxy( + address beacon, + bytes32 salt, + address deployer +) internal pure returns (address predicted) +``` + +Returns the address of the ERC1967 beacon proxy, with `salt` by `deployer`. +Note: The returned result has dirty upper 96 bits. Please clean if used in assembly. + +## ERC1967 Beacon Proxy With Immutable Args Operations + +### deployERC1967BeaconProxy(address,bytes) + +```solidity +function deployERC1967BeaconProxy(address beacon, bytes memory args) + internal + returns (address instance) +``` + +Deploys a minimal ERC1967 beacon proxy with `args`. + +### deployERC1967BeaconProxy(uint256,address,bytes) + +```solidity +function deployERC1967BeaconProxy( + uint256 value, + address beacon, + bytes memory args +) internal returns (address instance) +``` + +Deploys a minimal ERC1967 beacon proxy with `args`. +Deposits `value` ETH during deployment. + +### deployDeterministicERC1967BeaconProxy(address,bytes,bytes32) + +```solidity +function deployDeterministicERC1967BeaconProxy( + address beacon, + bytes memory args, + bytes32 salt +) internal returns (address instance) +``` + +Deploys a deterministic minimal ERC1967 beacon proxy with `args` and `salt`. + +### deployDeterministicERC1967BeaconProxy(uint256,address,bytes,bytes32) + +```solidity +function deployDeterministicERC1967BeaconProxy( + uint256 value, + address beacon, + bytes memory args, + bytes32 salt +) internal returns (address instance) +``` + +Deploys a deterministic minimal ERC1967 beacon proxy with `args` and `salt`. +Deposits `value` ETH during deployment. + +### createDeterministicERC1967BeaconProxy(address,bytes,bytes32) + +```solidity +function createDeterministicERC1967BeaconProxy( + address beacon, + bytes memory args, + bytes32 salt +) internal returns (bool alreadyDeployed, address instance) +``` + +Creates a deterministic minimal ERC1967 beacon proxy with `args` and `salt`. +Note: This method is intended for use in ERC4337 factories, +which are expected to NOT revert if the proxy is already deployed. + +### createDeterministicERC1967BeaconProxy(uint256,address,bytes,bytes32) + +```solidity +function createDeterministicERC1967BeaconProxy( + uint256 value, + address beacon, + bytes memory args, + bytes32 salt +) internal returns (bool alreadyDeployed, address instance) +``` + +Creates a deterministic minimal ERC1967 beacon proxy with `args` and `salt`. +Deposits `value` ETH during deployment. +Note: This method is intended for use in ERC4337 factories, +which are expected to NOT revert if the proxy is already deployed. + +### initCodeERC1967BeaconProxy(address,bytes) + +```solidity +function initCodeERC1967BeaconProxy(address beacon, bytes memory args) + internal + pure + returns (bytes memory c) +``` + +Returns the initialization code of the minimal ERC1967 beacon proxy. + +### initCodeHashERC1967BeaconProxy(address,bytes) + +```solidity +function initCodeHashERC1967BeaconProxy(address beacon, bytes memory args) + internal + pure + returns (bytes32 hash) +``` + +Returns the initialization code hash of the minimal ERC1967 beacon proxy with `args`. + +### predictDeterministicAddressERC1967BeaconProxy(address,bytes,bytes32,address) + +```solidity +function predictDeterministicAddressERC1967BeaconProxy( + address beacon, + bytes memory args, + bytes32 salt, + address deployer +) internal pure returns (address predicted) +``` + +Returns the address of the ERC1967 beacon proxy with `args`, with `salt` by `deployer`. +Note: The returned result has dirty upper 96 bits. Please clean if used in assembly. + +### argsOnERC1967BeaconProxy(address) + +```solidity +function argsOnERC1967BeaconProxy(address instance) + internal + view + returns (bytes memory args) +``` + +Equivalent to `argsOnERC1967BeaconProxy(instance, start, 2 ** 256 - 1)`. + +### argsOnERC1967BeaconProxy(address,uint256) + +```solidity +function argsOnERC1967BeaconProxy(address instance, uint256 start) + internal + view + returns (bytes memory args) +``` + +Equivalent to `argsOnERC1967BeaconProxy(instance, start, 2 ** 256 - 1)`. + +### argsOnERC1967BeaconProxy(address,uint256,uint256) + +```solidity +function argsOnERC1967BeaconProxy( + address instance, + uint256 start, + uint256 end +) internal view returns (bytes memory args) +``` + +Returns a slice of the immutable arguments on `instance` from `start` to `end`. +`start` and `end` will be clamped to the range `[0, args.length]`. +The `instance` MUST be deployed via the ERC1967 beacon proxy with immutable args functions. +Otherwise, the behavior is undefined. +Out-of-gas reverts if `instance` does not have any code. + +## ERC1967I Beacon Proxy Operations + +Note: This proxy has a special code path that activates if `calldatasize() == 1`. +This code path skips the delegatecall and directly returns the `implementation` address. +The returned implementation is guaranteed to be valid if the keccak256 of the +proxy's code is equal to `ERC1967_BEACON_PROXY_CODE_HASH`. +If you use this proxy, you MUST make sure that the beacon is a +valid ERC1967 beacon. This means that the beacon must always return a valid +address upon a staticcall to `implementation()`, given sufficient gas. +For performance, the deployment operations and the proxy assumes that the +beacon is always valid and will NOT validate it. + +### deployERC1967IBeaconProxy(address) + +```solidity +function deployERC1967IBeaconProxy(address beacon) + internal + returns (address instance) +``` + +Deploys a ERC1967I beacon proxy. + +### deployERC1967IBeaconProxy(uint256,address) + +```solidity +function deployERC1967IBeaconProxy(uint256 value, address beacon) + internal + returns (address instance) +``` + +Deploys a ERC1967I beacon proxy. +Deposits `value` ETH during deployment. + +### deployDeterministicERC1967IBeaconProxy(address,bytes32) + +```solidity +function deployDeterministicERC1967IBeaconProxy( + address beacon, + bytes32 salt +) internal returns (address instance) +``` + +Deploys a deterministic ERC1967I beacon proxy with `salt`. + +### deployDeterministicERC1967IBeaconProxy(uint256,address,bytes32) + +```solidity +function deployDeterministicERC1967IBeaconProxy( + uint256 value, + address beacon, + bytes32 salt +) internal returns (address instance) +``` + +Deploys a deterministic ERC1967I beacon proxy with `salt`. +Deposits `value` ETH during deployment. + +### createDeterministicERC1967IBeaconProxy(address,bytes32) + +```solidity +function createDeterministicERC1967IBeaconProxy( + address beacon, + bytes32 salt +) internal returns (bool alreadyDeployed, address instance) +``` + +Creates a deterministic ERC1967I beacon proxy with `salt`. +Note: This method is intended for use in ERC4337 factories, +which are expected to NOT revert if the proxy is already deployed. + +### createDeterministicERC1967IBeaconProxy(uint256,address,bytes32) + +```solidity +function createDeterministicERC1967IBeaconProxy( + uint256 value, + address beacon, + bytes32 salt +) internal returns (bool alreadyDeployed, address instance) +``` + +Creates a deterministic ERC1967I beacon proxy with `salt`. +Deposits `value` ETH during deployment. +Note: This method is intended for use in ERC4337 factories, +which are expected to NOT revert if the proxy is already deployed. + +### initCodeERC1967IBeaconProxy(address) + +```solidity +function initCodeERC1967IBeaconProxy(address beacon) + internal + pure + returns (bytes memory c) +``` + +Returns the initialization code of the ERC1967I beacon proxy. + +### initCodeHashERC1967IBeaconProxy(address) + +```solidity +function initCodeHashERC1967IBeaconProxy(address beacon) + internal + pure + returns (bytes32 hash) +``` + +Returns the initialization code hash of the ERC1967I beacon proxy. + +### predictDeterministicAddressERC1967IBeaconProxy(address,bytes32,address) + +```solidity +function predictDeterministicAddressERC1967IBeaconProxy( + address beacon, + bytes32 salt, + address deployer +) internal pure returns (address predicted) +``` + +Returns the address of the ERC1967I beacon proxy, with `salt` by `deployer`. +Note: The returned result has dirty upper 96 bits. Please clean if used in assembly. + +## ERC1967I Beacon Proxy With Immutable Args Operations + +### deployERC1967IBeaconProxy(address,bytes) + +```solidity +function deployERC1967IBeaconProxy(address beacon, bytes memory args) + internal + returns (address instance) +``` + +Deploys a ERC1967I beacon proxy with `args. + +### deployERC1967IBeaconProxy(uint256,address,bytes) + +```solidity +function deployERC1967IBeaconProxy( + uint256 value, + address beacon, + bytes memory args +) internal returns (address instance) +``` + +Deploys a ERC1967I beacon proxy with `args. +Deposits `value` ETH during deployment. + +### deployDeterministicERC1967IBeaconProxy(address,bytes,bytes32) + +```solidity +function deployDeterministicERC1967IBeaconProxy( + address beacon, + bytes memory args, + bytes32 salt +) internal returns (address instance) +``` + +Deploys a deterministic ERC1967I beacon proxy with `args` and `salt`. + +### deployDeterministicERC1967IBeaconProxy(uint256,address,bytes,bytes32) + +```solidity +function deployDeterministicERC1967IBeaconProxy( + uint256 value, + address beacon, + bytes memory args, + bytes32 salt +) internal returns (address instance) +``` + +Deploys a deterministic ERC1967I beacon proxy with `args` and `salt`. +Deposits `value` ETH during deployment. + +### createDeterministicERC1967IBeaconProxy(address,bytes,bytes32) + +```solidity +function createDeterministicERC1967IBeaconProxy( + address beacon, + bytes memory args, + bytes32 salt +) internal returns (bool alreadyDeployed, address instance) +``` + +Creates a deterministic ERC1967I beacon proxy with `args` and `salt`. +Note: This method is intended for use in ERC4337 factories, +which are expected to NOT revert if the proxy is already deployed. + +### createDeterministicERC1967IBeaconProxy(uint256,address,bytes,bytes32) + +```solidity +function createDeterministicERC1967IBeaconProxy( + uint256 value, + address beacon, + bytes memory args, + bytes32 salt +) internal returns (bool alreadyDeployed, address instance) +``` + +Creates a deterministic ERC1967I beacon proxy with `args` and `salt`. +Deposits `value` ETH during deployment. +Note: This method is intended for use in ERC4337 factories, +which are expected to NOT revert if the proxy is already deployed. + +### initCodeERC1967IBeaconProxy(address,bytes) + +```solidity +function initCodeERC1967IBeaconProxy(address beacon, bytes memory args) + internal + pure + returns (bytes memory c) +``` + +Returns the initialization code of the ERC1967I beacon proxy with `args`. + +### initCodeHashERC1967IBeaconProxy(address,bytes) + +```solidity +function initCodeHashERC1967IBeaconProxy(address beacon, bytes memory args) + internal + pure + returns (bytes32 hash) +``` + +Returns the initialization code hash of the ERC1967I beacon proxy with `args`. + +### predictDeterministicAddressERC1967IBeaconProxy(address,bytes,bytes32,address) + +```solidity +function predictDeterministicAddressERC1967IBeaconProxy( + address beacon, + bytes memory args, + bytes32 salt, + address deployer +) internal pure returns (address predicted) +``` + +Returns the address of the ERC1967I beacon proxy, with `args` and salt` by `deployer`. +Note: The returned result has dirty upper 96 bits. Please clean if used in assembly. + +### argsOnERC1967IBeaconProxy(address) + +```solidity +function argsOnERC1967IBeaconProxy(address instance) + internal + view + returns (bytes memory args) +``` + +Equivalent to `argsOnERC1967IBeaconProxy(instance, start, 2 ** 256 - 1)`. + +### argsOnERC1967IBeaconProxy(address,uint256) + +```solidity +function argsOnERC1967IBeaconProxy(address instance, uint256 start) + internal + view + returns (bytes memory args) +``` + +Equivalent to `argsOnERC1967IBeaconProxy(instance, start, 2 ** 256 - 1)`. + +### argsOnERC1967IBeaconProxy(address,uint256,uint256) + +```solidity +function argsOnERC1967IBeaconProxy( + address instance, + uint256 start, + uint256 end +) internal view returns (bytes memory args) +``` + +Returns a slice of the immutable arguments on `instance` from `start` to `end`. +`start` and `end` will be clamped to the range `[0, args.length]`. +The `instance` MUST be deployed via the ERC1967I beacon proxy with immutable args functions. +Otherwise, the behavior is undefined. +Out-of-gas reverts if `instance` does not have any code. + +## Other Operations + +### implementationOf(address) + +```solidity +function implementationOf(address instance) + internal + view + returns (address result) +``` + +Returns `address(0)` if the implementation address cannot be determined. + +### predictDeterministicAddress(bytes32,bytes32,address) + +```solidity +function predictDeterministicAddress( + bytes32 hash, + bytes32 salt, + address deployer +) internal pure returns (address predicted) +``` + +Returns the address when a contract with initialization code hash, +`hash`, is deployed with `salt`, by `deployer`. +Note: The returned result has dirty upper 96 bits. Please clean if used in assembly. + +### checkStartsWith(bytes32,address) + +```solidity +function checkStartsWith(bytes32 salt, address by) internal pure +``` + +Requires that `salt` starts with either the zero address or `by`. + +### argLoad(bytes,uint256) + +```solidity +function argLoad(bytes memory args, uint256 offset) + internal + pure + returns (bytes32 result) +``` + +Returns the `bytes32` at `offset` in `args`, without any bounds checks. +To load an address, you can use `address(bytes20(argLoad(args, offset)))`. \ No newline at end of file diff --git a/docs/utils/libmap.md b/docs/utils/libmap.md new file mode 100644 index 000000000..937bc7f16 --- /dev/null +++ b/docs/utils/libmap.md @@ -0,0 +1,314 @@ +# LibMap + +Library for storage of packed unsigned integers. + + + + + + + + +## Structs + +### Uint8Map + +```solidity +struct Uint8Map { + mapping(uint256 => uint256) map; +} +``` + +A uint8 map in storage. + +### Uint16Map + +```solidity +struct Uint16Map { + mapping(uint256 => uint256) map; +} +``` + +A uint16 map in storage. + +### Uint32Map + +```solidity +struct Uint32Map { + mapping(uint256 => uint256) map; +} +``` + +A uint32 map in storage. + +### Uint40Map + +```solidity +struct Uint40Map { + mapping(uint256 => uint256) map; +} +``` + +A uint40 map in storage. Useful for storing timestamps up to 34841 A.D. + +### Uint64Map + +```solidity +struct Uint64Map { + mapping(uint256 => uint256) map; +} +``` + +A uint64 map in storage. + +### Uint128Map + +```solidity +struct Uint128Map { + mapping(uint256 => uint256) map; +} +``` + +A uint128 map in storage. + +## Getters / Setters + +### get(Uint8Map,uint256) + +```solidity +function get(Uint8Map storage map, uint256 index) + internal + view + returns (uint8 result) +``` + +Returns the uint8 value at `index` in `map`. + +### set(Uint8Map,uint256,uint8) + +```solidity +function set(Uint8Map storage map, uint256 index, uint8 value) internal +``` + +Updates the uint8 value at `index` in `map`. + +### get(Uint16Map,uint256) + +```solidity +function get(Uint16Map storage map, uint256 index) + internal + view + returns (uint16 result) +``` + +Returns the uint16 value at `index` in `map`. + +### set(Uint16Map,uint256,uint16) + +```solidity +function set(Uint16Map storage map, uint256 index, uint16 value) internal +``` + +Updates the uint16 value at `index` in `map`. + +### get(Uint32Map,uint256) + +```solidity +function get(Uint32Map storage map, uint256 index) + internal + view + returns (uint32 result) +``` + +Returns the uint32 value at `index` in `map`. + +### set(Uint32Map,uint256,uint32) + +```solidity +function set(Uint32Map storage map, uint256 index, uint32 value) internal +``` + +Updates the uint32 value at `index` in `map`. + +### get(Uint40Map,uint256) + +```solidity +function get(Uint40Map storage map, uint256 index) + internal + view + returns (uint40 result) +``` + +Returns the uint40 value at `index` in `map`. + +### set(Uint40Map,uint256,uint40) + +```solidity +function set(Uint40Map storage map, uint256 index, uint40 value) internal +``` + +Updates the uint40 value at `index` in `map`. + +### get(Uint64Map,uint256) + +```solidity +function get(Uint64Map storage map, uint256 index) + internal + view + returns (uint64 result) +``` + +Returns the uint64 value at `index` in `map`. + +### set(Uint64Map,uint256,uint64) + +```solidity +function set(Uint64Map storage map, uint256 index, uint64 value) internal +``` + +Updates the uint64 value at `index` in `map`. + +### get(Uint128Map,uint256) + +```solidity +function get(Uint128Map storage map, uint256 index) + internal + view + returns (uint128 result) +``` + +Returns the uint128 value at `index` in `map`. + +### set(Uint128Map,uint256,uint128) + +```solidity +function set(Uint128Map storage map, uint256 index, uint128 value) + internal +``` + +Updates the uint128 value at `index` in `map`. + +### get(mapping(uint256) + +```solidity +function get( + mapping(uint256 => uint256) storage map, + uint256 index, + uint256 bitWidth +) internal view returns (uint256 result) +``` + +Returns the value at `index` in `map`. + +### set(mapping(uint256) + +```solidity +function set( + mapping(uint256 => uint256) storage map, + uint256 index, + uint256 value, + uint256 bitWidth +) internal +``` + +Updates the value at `index` in `map`. + +## Binary Search + +The following functions search in the range of [`start`, `end`) +(i.e. `start <= index < end`). +The range must be sorted in ascending order. +`index` precedence: equal to > nearest before > nearest after. +An invalid search range will simply return `(found = false, index = start)`. + +### searchSorted(Uint8Map,uint8,uint256,uint256) + +```solidity +function searchSorted( + Uint8Map storage map, + uint8 needle, + uint256 start, + uint256 end +) internal view returns (bool found, uint256 index) +``` + +Returns whether `map` contains `needle`, and the index of `needle`. + +### searchSorted(Uint16Map,uint16,uint256,uint256) + +```solidity +function searchSorted( + Uint16Map storage map, + uint16 needle, + uint256 start, + uint256 end +) internal view returns (bool found, uint256 index) +``` + +Returns whether `map` contains `needle`, and the index of `needle`. + +### searchSorted(Uint32Map,uint32,uint256,uint256) + +```solidity +function searchSorted( + Uint32Map storage map, + uint32 needle, + uint256 start, + uint256 end +) internal view returns (bool found, uint256 index) +``` + +Returns whether `map` contains `needle`, and the index of `needle`. + +### searchSorted(Uint40Map,uint40,uint256,uint256) + +```solidity +function searchSorted( + Uint40Map storage map, + uint40 needle, + uint256 start, + uint256 end +) internal view returns (bool found, uint256 index) +``` + +Returns whether `map` contains `needle`, and the index of `needle`. + +### searchSorted(Uint64Map,uint64,uint256,uint256) + +```solidity +function searchSorted( + Uint64Map storage map, + uint64 needle, + uint256 start, + uint256 end +) internal view returns (bool found, uint256 index) +``` + +Returns whether `map` contains `needle`, and the index of `needle`. + +### searchSorted(Uint128Map,uint128,uint256,uint256) + +```solidity +function searchSorted( + Uint128Map storage map, + uint128 needle, + uint256 start, + uint256 end +) internal view returns (bool found, uint256 index) +``` + +Returns whether `map` contains `needle`, and the index of `needle`. + +### searchSorted(mapping(uint256) + +```solidity +function searchSorted( + mapping(uint256 => uint256) storage map, + uint256 needle, + uint256 start, + uint256 end, + uint256 bitWidth +) internal view returns (bool found, uint256 index) +``` + +Returns whether `map` contains `needle`, and the index of `needle`. \ No newline at end of file diff --git a/docs/utils/libprng.md b/docs/utils/libprng.md new file mode 100644 index 000000000..24ec1ee9c --- /dev/null +++ b/docs/utils/libprng.md @@ -0,0 +1,325 @@ +# LibPRNG + +Library for generating pseudorandom numbers. + + + + + + + + +## Custom Errors + +### InvalidInitialLazyShufflerLength() + +```solidity +error InvalidInitialLazyShufflerLength() +``` + +The initial length must be greater than zero and less than `2**32 - 1`. + +### InvalidNewLazyShufflerLength() + +```solidity +error InvalidNewLazyShufflerLength() +``` + +The new length must not be less than the current length. + +### LazyShufflerNotInitialized() + +```solidity +error LazyShufflerNotInitialized() +``` + +The lazy shuffler has not been initialized. + +### LazyShufflerAlreadyInitialized() + +```solidity +error LazyShufflerAlreadyInitialized() +``` + +Cannot double initialize the lazy shuffler. + +### LazyShuffleFinished() + +```solidity +error LazyShuffleFinished() +``` + +The lazy shuffle has finished. + +### LazyShufflerGetOutOfBounds() + +```solidity +error LazyShufflerGetOutOfBounds() +``` + +The queried index is out of bounds. + +## Constants + +### WAD + +```solidity +uint256 internal constant WAD = 1e18 +``` + +The scalar of ETH and most ERC20s. + +## Structs + +### PRNG + +```solidity +struct PRNG { + uint256 state; +} +``` + +A pseudorandom number state in memory. + +### LazyShuffler + +```solidity +struct LazyShuffler { + // Bits Layout: + // - [0..31] `numShuffled` + // - [32..223] `permutationSlot` + // - [224..255] `length` + uint256 _state; +} +``` + +A lazy Fisher-Yates shuffler for a range `[0..n)` in storage. + +## Operations + +### seed(PRNG,uint256) + +```solidity +function seed(PRNG memory prng, uint256 state) internal pure +``` + +Seeds the `prng` with `state`. + +### next(PRNG) + +```solidity +function next(PRNG memory prng) internal pure returns (uint256 result) +``` + +Returns the next pseudorandom uint256. +All bits of the returned uint256 pass the NIST Statistical Test Suite. + +### uniform(PRNG,uint256) + +```solidity +function uniform(PRNG memory prng, uint256 upper) + internal + pure + returns (uint256 result) +``` + +Returns a pseudorandom uint256, uniformly distributed +between 0 (inclusive) and `upper` (exclusive). +If your modulus is big, this method is recommended +for uniform sampling to avoid modulo bias. +For uniform sampling across all uint256 values, +or for small enough moduli such that the bias is negligible, +use {next} instead. + +### standardNormalWad(PRNG) + +```solidity +function standardNormalWad(PRNG memory prng) + internal + pure + returns (int256 result) +``` + +Returns a sample from the standard normal distribution denominated in `WAD`. + +### exponentialWad(PRNG) + +```solidity +function exponentialWad(PRNG memory prng) + internal + pure + returns (uint256 result) +``` + +Returns a sample from the unit exponential distribution denominated in `WAD`. + +## Memory Array Shuffling Operations + +### shuffle(PRNG,uint256[]) + +```solidity +function shuffle(PRNG memory prng, uint256[] memory a) internal pure +``` + +Shuffles the array in-place with Fisher-Yates shuffle. + +### shuffle(PRNG,int256[]) + +```solidity +function shuffle(PRNG memory prng, int256[] memory a) internal pure +``` + +Shuffles the array in-place with Fisher-Yates shuffle. + +### shuffle(PRNG,address[]) + +```solidity +function shuffle(PRNG memory prng, address[] memory a) internal pure +``` + +Shuffles the array in-place with Fisher-Yates shuffle. + +### shuffle(PRNG,uint256[],uint256) + +```solidity +function shuffle(PRNG memory prng, uint256[] memory a, uint256 k) + internal + pure +``` + +Partially shuffles the array in-place with Fisher-Yates shuffle. +The first `k` elements will be uniformly sampled without replacement. + +### shuffle(PRNG,int256[],uint256) + +```solidity +function shuffle(PRNG memory prng, int256[] memory a, uint256 k) + internal + pure +``` + +Partially shuffles the array in-place with Fisher-Yates shuffle. +The first `k` elements will be uniformly sampled without replacement. + +### shuffle(PRNG,address[],uint256) + +```solidity +function shuffle(PRNG memory prng, address[] memory a, uint256 k) + internal + pure +``` + +Partially shuffles the array in-place with Fisher-Yates shuffle. +The first `k` elements will be uniformly sampled without replacement. + +### shuffle(PRNG,bytes) + +```solidity +function shuffle(PRNG memory prng, bytes memory a) internal pure +``` + +Shuffles the bytes in-place with Fisher-Yates shuffle. + +## Storage-based Range Lazy Shuffling Operations + +### initialize(LazyShuffler,uint256) + +```solidity +function initialize(LazyShuffler storage $, uint256 n) internal +``` + +Initializes the state for lazy-shuffling the range `[0..n)`. +Reverts if `n == 0 || n >= 2**32 - 1`. +Reverts if `$` has already been initialized. +If you need to reduce the length after initialization, just use a fresh new `$`. + +### grow(LazyShuffler,uint256) + +```solidity +function grow(LazyShuffler storage $, uint256 n) internal +``` + +Increases the length of `$`. +Reverts if `$` has not been initialized. + +### restart(LazyShuffler) + +```solidity +function restart(LazyShuffler storage $) internal +``` + +Restarts the shuffler by setting `numShuffled` to zero, +such that all elements can be drawn again. +Restarting does NOT clear the internal permutation, nor changes the length. +Even with the same sequence of randomness, reshuffling can yield different results. + +### numShuffled(LazyShuffler) + +```solidity +function numShuffled(LazyShuffler storage $) + internal + view + returns (uint256 result) +``` + +Returns the number of elements that have been shuffled. + +### length(LazyShuffler) + +```solidity +function length(LazyShuffler storage $) + internal + view + returns (uint256 result) +``` + +Returns the length of `$`. +Returns zero if `$` is not initialized, else a non-zero value less than `2**32 - 1`. + +### initialized(LazyShuffler) + +```solidity +function initialized(LazyShuffler storage $) + internal + view + returns (bool result) +``` + +Returns if `$` has been initialized. + +### finished(LazyShuffler) + +```solidity +function finished(LazyShuffler storage $) + internal + view + returns (bool result) +``` + +Returns if there are any more elements left to shuffle. +Reverts if `$` is not initialized. + +### get(LazyShuffler,uint256) + +```solidity +function get(LazyShuffler storage $, uint256 index) + internal + view + returns (uint256 result) +``` + +Returns the current value stored at `index`, accounting for all historical shuffling. +Reverts if `index` is greater than or equal to the `length` of `$`. + +### next(LazyShuffler,uint256) + +```solidity +function next(LazyShuffler storage $, uint256 randomness) + internal + returns (uint256 chosen) +``` + +Does a single Fisher-Yates shuffle step, increments the `numShuffled` in `$`, +and returns the next value in the shuffled range. +`randomness` can be taken from a good-enough source, or a higher quality source like VRF. +Reverts if there are no more values to shuffle, which includes the case if `$` is not initialized. \ No newline at end of file diff --git a/docs/utils/librlp.md b/docs/utils/librlp.md new file mode 100644 index 000000000..09f571478 --- /dev/null +++ b/docs/utils/librlp.md @@ -0,0 +1,212 @@ +# LibRLP + +Library for RLP encoding and CREATE address computation. + + + + + + + + +## Structs + +### List + +```solidity +struct List { + // Do NOT modify the `_data` directly. + uint256 _data; +} +``` + +A pointer to a RLP item list in memory. + +## Create Address Prediction + +### computeAddress(address,uint256) + +```solidity +function computeAddress(address deployer, uint256 nonce) + internal + pure + returns (address deployed) +``` + +Returns the address where a contract will be stored if deployed via +`deployer` with `nonce` using the `CREATE` opcode. +For the specification of the Recursive Length Prefix (RLP) +encoding scheme, please refer to p. 19 of the Ethereum Yellow Paper +(https://ethereum.github.io/yellowpaper/paper.pdf) +and the Ethereum Wiki (https://eth.wiki/fundamentals/rlp). +Based on the EIP-161 (https://github.com/ethereum/EIPs/blob/master/EIPS/eip-161.md) +specification, all contract accounts on the Ethereum mainnet are initiated with +`nonce = 1`. Thus, the first contract address created by another contract +is calculated with a non-zero nonce. +The theoretical allowed limit, based on EIP-2681 +(https://eips.ethereum.org/EIPS/eip-2681), for an account nonce is 2**64-2. +Caution! This function will NOT check that the nonce is within the theoretical range. +This is for performance, as exceeding the range is extremely impractical. +It is the user's responsibility to ensure that the nonce is valid +(e.g. no dirty bits after packing / unpacking). +This is equivalent to: +`address(uint160(uint256(keccak256(LibRLP.p(deployer).p(nonce).encode()))))`. +Note: The returned result has dirty upper 96 bits. Please clean if used in assembly. + +## Rlp Encoding Operations + +Note: +- addresses are treated like byte strings of length 20, agnostic of leading zero bytes. +- uint256s are converted to byte strings, stripped of leading zero bytes, and encoded. +- bools are converted to uint256s (`b ? 1 : 0`), then encoded with the uint256. +- For bytes1 to bytes32, you must manually convert them to bytes memory + with `abi.encodePacked(x)` before encoding. + +### p() + +```solidity +function p() internal pure returns (List memory result) +``` + +Returns a new empty list. + +### p(uint256) + +```solidity +function p(uint256 x) internal pure returns (List memory result) +``` + +Returns a new list with `x` as the only element. Equivalent to `LibRLP.p().p(x)`. + +### p(address) + +```solidity +function p(address x) internal pure returns (List memory result) +``` + +Returns a new list with `x` as the only element. Equivalent to `LibRLP.p().p(x)`. + +### p(bool) + +```solidity +function p(bool x) internal pure returns (List memory result) +``` + +Returns a new list with `x` as the only element. Equivalent to `LibRLP.p().p(x)`. + +### p(bytes) + +```solidity +function p(bytes memory x) internal pure returns (List memory result) +``` + +Returns a new list with `x` as the only element. Equivalent to `LibRLP.p().p(x)`. + +### p(List) + +```solidity +function p(List memory x) internal pure returns (List memory result) +``` + +Returns a new list with `x` as the only element. Equivalent to `LibRLP.p().p(x)`. + +### p(List,uint256) + +```solidity +function p(List memory list, uint256 x) + internal + pure + returns (List memory result) +``` + +Appends `x` to `list`. Returns `list` for function chaining. + +### p(List,address) + +```solidity +function p(List memory list, address x) + internal + pure + returns (List memory result) +``` + +Appends `x` to `list`. Returns `list` for function chaining. + +### p(List,bool) + +```solidity +function p(List memory list, bool x) + internal + pure + returns (List memory result) +``` + +Appends `x` to `list`. Returns `list` for function chaining. + +### p(List,bytes) + +```solidity +function p(List memory list, bytes memory x) + internal + pure + returns (List memory result) +``` + +Appends `x` to `list`. Returns `list` for function chaining. + +### p(List,List) + +```solidity +function p(List memory list, List memory x) + internal + pure + returns (List memory result) +``` + +Appends `x` to `list`. Returns `list` for function chaining. + +### encode(List) + +```solidity +function encode(List memory list) + internal + pure + returns (bytes memory result) +``` + +Returns the RLP encoding of `list`. + +### encode(uint256) + +```solidity +function encode(uint256 x) internal pure returns (bytes memory result) +``` + +Returns the RLP encoding of `x`. + +### encode(address) + +```solidity +function encode(address x) internal pure returns (bytes memory result) +``` + +Returns the RLP encoding of `x`. + +### encode(bool) + +```solidity +function encode(bool x) internal pure returns (bytes memory result) +``` + +Returns the RLP encoding of `x`. + +### encode(bytes) + +```solidity +function encode(bytes memory x) + internal + pure + returns (bytes memory result) +``` + +Returns the RLP encoding of `x`. \ No newline at end of file diff --git a/docs/utils/libsort.md b/docs/utils/libsort.md new file mode 100644 index 000000000..40b79c8e2 --- /dev/null +++ b/docs/utils/libsort.md @@ -0,0 +1,521 @@ +# LibSort + +Optimized sorts and operations for sorted arrays. + + + + + + + + +## Insertion Sort + +- Faster on small arrays (32 or lesser elements). +- Faster on almost sorted arrays. +- Smaller bytecode. +- May be suitable for view functions intended for off-chain querying. + +### insertionSort(uint256[]) + +```solidity +function insertionSort(uint256[] memory a) internal pure +``` + +Sorts the array in-place with insertion sort. + +### insertionSort(int256[]) + +```solidity +function insertionSort(int256[] memory a) internal pure +``` + +Sorts the array in-place with insertion sort. + +### insertionSort(address[]) + +```solidity +function insertionSort(address[] memory a) internal pure +``` + +Sorts the array in-place with insertion sort. + +### insertionSort(bytes32[]) + +```solidity +function insertionSort(bytes32[] memory a) internal pure +``` + +Sorts the array in-place with insertion sort. + +## Intro-quicksort + +- Faster on larger arrays (more than 32 elements). +- Robust performance. +- Larger bytecode. + +### sort(uint256[]) + +```solidity +function sort(uint256[] memory a) internal pure +``` + +Sorts the array in-place with intro-quicksort. + +### sort(int256[]) + +```solidity +function sort(int256[] memory a) internal pure +``` + +Sorts the array in-place with intro-quicksort. + +### sort(address[]) + +```solidity +function sort(address[] memory a) internal pure +``` + +Sorts the array in-place with intro-quicksort. + +### sort(bytes32[]) + +```solidity +function sort(bytes32[] memory a) internal pure +``` + +Sorts the array in-place with intro-quicksort. + +## Other Useful Operations + +For performance, the `uniquifySorted` methods will not revert if the +array is not sorted -- it will simply remove consecutive duplicate elements. + +### uniquifySorted(uint256[]) + +```solidity +function uniquifySorted(uint256[] memory a) internal pure +``` + +Removes duplicate elements from a ascendingly sorted memory array. + +### uniquifySorted(int256[]) + +```solidity +function uniquifySorted(int256[] memory a) internal pure +``` + +Removes duplicate elements from a ascendingly sorted memory array. + +### uniquifySorted(address[]) + +```solidity +function uniquifySorted(address[] memory a) internal pure +``` + +Removes duplicate elements from a ascendingly sorted memory array. + +### uniquifySorted(bytes32[]) + +```solidity +function uniquifySorted(bytes32[] memory a) internal pure +``` + +Removes duplicate elements from a ascendingly sorted memory array. + +### searchSorted(uint256[],uint256) + +```solidity +function searchSorted(uint256[] memory a, uint256 needle) + internal + pure + returns (bool found, uint256 index) +``` + +Returns whether `a` contains `needle`, and the index of `needle`. +`index` precedence: equal to > nearest before > nearest after. + +### searchSorted(int256[],int256) + +```solidity +function searchSorted(int256[] memory a, int256 needle) + internal + pure + returns (bool found, uint256 index) +``` + +Returns whether `a` contains `needle`, and the index of `needle`. +`index` precedence: equal to > nearest before > nearest after. + +### searchSorted(address[],address) + +```solidity +function searchSorted(address[] memory a, address needle) + internal + pure + returns (bool found, uint256 index) +``` + +Returns whether `a` contains `needle`, and the index of `needle`. +`index` precedence: equal to > nearest before > nearest after. + +### searchSorted(bytes32[],bytes32) + +```solidity +function searchSorted(bytes32[] memory a, bytes32 needle) + internal + pure + returns (bool found, uint256 index) +``` + +Returns whether `a` contains `needle`, and the index of `needle`. +`index` precedence: equal to > nearest before > nearest after. + +### inSorted(uint256[],uint256) + +```solidity +function inSorted(uint256[] memory a, uint256 needle) + internal + pure + returns (bool found) +``` + +Returns whether `a` contains `needle`. + +### inSorted(int256[],int256) + +```solidity +function inSorted(int256[] memory a, int256 needle) + internal + pure + returns (bool found) +``` + +Returns whether `a` contains `needle`. + +### inSorted(address[],address) + +```solidity +function inSorted(address[] memory a, address needle) + internal + pure + returns (bool found) +``` + +Returns whether `a` contains `needle`. + +### inSorted(bytes32[],bytes32) + +```solidity +function inSorted(bytes32[] memory a, bytes32 needle) + internal + pure + returns (bool found) +``` + +Returns whether `a` contains `needle`. + +### reverse(uint256[]) + +```solidity +function reverse(uint256[] memory a) internal pure +``` + +Reverses the array in-place. + +### reverse(int256[]) + +```solidity +function reverse(int256[] memory a) internal pure +``` + +Reverses the array in-place. + +### reverse(address[]) + +```solidity +function reverse(address[] memory a) internal pure +``` + +Reverses the array in-place. + +### reverse(bytes32[]) + +```solidity +function reverse(bytes32[] memory a) internal pure +``` + +Reverses the array in-place. + +### copy(uint256[]) + +```solidity +function copy(uint256[] memory a) + internal + pure + returns (uint256[] memory result) +``` + +Returns a copy of the array. + +### copy(int256[]) + +```solidity +function copy(int256[] memory a) + internal + pure + returns (int256[] memory result) +``` + +Returns a copy of the array. + +### copy(address[]) + +```solidity +function copy(address[] memory a) + internal + pure + returns (address[] memory result) +``` + +Returns a copy of the array. + +### copy(bytes32[]) + +```solidity +function copy(bytes32[] memory a) + internal + pure + returns (bytes32[] memory result) +``` + +Returns a copy of the array. + +### isSorted(uint256[]) + +```solidity +function isSorted(uint256[] memory a) internal pure returns (bool result) +``` + +Returns whether the array is sorted in ascending order. + +### isSorted(int256[]) + +```solidity +function isSorted(int256[] memory a) internal pure returns (bool result) +``` + +Returns whether the array is sorted in ascending order. + +### isSorted(address[]) + +```solidity +function isSorted(address[] memory a) internal pure returns (bool result) +``` + +Returns whether the array is sorted in ascending order. + +### isSorted(bytes32[]) + +```solidity +function isSorted(bytes32[] memory a) internal pure returns (bool result) +``` + +Returns whether the array is sorted in ascending order. + +### isSortedAndUniquified(uint256[]) + +```solidity +function isSortedAndUniquified(uint256[] memory a) + internal + pure + returns (bool result) +``` + +Returns whether the array is strictly ascending (sorted and uniquified). + +### isSortedAndUniquified(int256[]) + +```solidity +function isSortedAndUniquified(int256[] memory a) + internal + pure + returns (bool result) +``` + +Returns whether the array is strictly ascending (sorted and uniquified). + +### isSortedAndUniquified(address[]) + +```solidity +function isSortedAndUniquified(address[] memory a) + internal + pure + returns (bool result) +``` + +Returns whether the array is strictly ascending (sorted and uniquified). + +### isSortedAndUniquified(bytes32[]) + +```solidity +function isSortedAndUniquified(bytes32[] memory a) + internal + pure + returns (bool result) +``` + +Returns whether the array is strictly ascending (sorted and uniquified). + +### difference(uint256[],uint256[]) + +```solidity +function difference(uint256[] memory a, uint256[] memory b) + internal + pure + returns (uint256[] memory c) +``` + +Returns the sorted set difference of `a` and `b`. +Note: Behaviour is undefined if inputs are not sorted and uniquified. + +### difference(int256[],int256[]) + +```solidity +function difference(int256[] memory a, int256[] memory b) + internal + pure + returns (int256[] memory c) +``` + +Returns the sorted set difference between `a` and `b`. +Note: Behaviour is undefined if inputs are not sorted and uniquified. + +### difference(address[],address[]) + +```solidity +function difference(address[] memory a, address[] memory b) + internal + pure + returns (address[] memory c) +``` + +Returns the sorted set difference between `a` and `b`. +Note: Behaviour is undefined if inputs are not sorted and uniquified. + +### difference(bytes32[],bytes32[]) + +```solidity +function difference(bytes32[] memory a, bytes32[] memory b) + internal + pure + returns (bytes32[] memory c) +``` + +Returns the sorted set difference between `a` and `b`. +Note: Behaviour is undefined if inputs are not sorted and uniquified. + +### intersection(uint256[],uint256[]) + +```solidity +function intersection(uint256[] memory a, uint256[] memory b) + internal + pure + returns (uint256[] memory c) +``` + +Returns the sorted set intersection between `a` and `b`. +Note: Behaviour is undefined if inputs are not sorted and uniquified. + +### intersection(int256[],int256[]) + +```solidity +function intersection(int256[] memory a, int256[] memory b) + internal + pure + returns (int256[] memory c) +``` + +Returns the sorted set intersection between `a` and `b`. +Note: Behaviour is undefined if inputs are not sorted and uniquified. + +### intersection(address[],address[]) + +```solidity +function intersection(address[] memory a, address[] memory b) + internal + pure + returns (address[] memory c) +``` + +Returns the sorted set intersection between `a` and `b`. +Note: Behaviour is undefined if inputs are not sorted and uniquified. + +### intersection(bytes32[],bytes32[]) + +```solidity +function intersection(bytes32[] memory a, bytes32[] memory b) + internal + pure + returns (bytes32[] memory c) +``` + +Returns the sorted set intersection between `a` and `b`. +Note: Behaviour is undefined if inputs are not sorted and uniquified. + +### union(uint256[],uint256[]) + +```solidity +function union(uint256[] memory a, uint256[] memory b) + internal + pure + returns (uint256[] memory c) +``` + +Returns the sorted set union of `a` and `b`. +Note: Behaviour is undefined if inputs are not sorted and uniquified. + +### union(int256[],int256[]) + +```solidity +function union(int256[] memory a, int256[] memory b) + internal + pure + returns (int256[] memory c) +``` + +Returns the sorted set union of `a` and `b`. +Note: Behaviour is undefined if inputs are not sorted and uniquified. + +### union(address[],address[]) + +```solidity +function union(address[] memory a, address[] memory b) + internal + pure + returns (address[] memory c) +``` + +Returns the sorted set union between `a` and `b`. +Note: Behaviour is undefined if inputs are not sorted and uniquified. + +### union(bytes32[],bytes32[]) + +```solidity +function union(bytes32[] memory a, bytes32[] memory b) + internal + pure + returns (bytes32[] memory c) +``` + +Returns the sorted set union between `a` and `b`. +Note: Behaviour is undefined if inputs are not sorted and uniquified. + +### clean(address[]) + +```solidity +function clean(address[] memory a) internal pure +``` + +Cleans the upper 96 bits of the addresses. +In case `a` is produced via assembly and might have dirty upper bits. \ No newline at end of file diff --git a/docs/utils/libstring.md b/docs/utils/libstring.md new file mode 100644 index 000000000..d74e976bf --- /dev/null +++ b/docs/utils/libstring.md @@ -0,0 +1,819 @@ +# LibString + +Library for converting numbers into strings and other string operations. + + +Note: + +For performance and bytecode compactness, most of the string operations are restricted to +byte strings (7-bit ASCII), except where otherwise specified. +Usage of byte string operations on charsets with runes spanning two or more bytes +can lead to undefined behavior. + + + + + +## Structs + +### StringStorage + +```solidity +struct StringStorage { + bytes32 _spacer; +} +``` + +Goated string storage struct that totally MOGs, no cap, fr. +Uses less gas and bytecode than Solidity's native string storage. It's meta af. +Packs length with the first 31 bytes if <255 bytes, so it’s mad tight. + +## Custom Errors + +### HexLengthInsufficient() + +```solidity +error HexLengthInsufficient() +``` + +The length of the output is too small to contain all the hex digits. + +### TooBigForSmallString() + +```solidity +error TooBigForSmallString() +``` + +The length of the string is more than 32 bytes. + +### StringNot7BitASCII() + +```solidity +error StringNot7BitASCII() +``` + +The input string must be a 7-bit ASCII. + +## Constants + +### NOT_FOUND + +```solidity +uint256 internal constant NOT_FOUND = type(uint256).max +``` + +The constant returned when the `search` is not found in the string. + +### ALPHANUMERIC_7_BIT_ASCII + +```solidity +uint128 internal constant ALPHANUMERIC_7_BIT_ASCII = + 0x7fffffe07fffffe03ff000000000000 +``` + +Lookup for '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'. + +### LETTERS_7_BIT_ASCII + +```solidity +uint128 internal constant LETTERS_7_BIT_ASCII = + 0x7fffffe07fffffe0000000000000000 +``` + +Lookup for 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'. + +### LOWERCASE_7_BIT_ASCII + +```solidity +uint128 internal constant LOWERCASE_7_BIT_ASCII = + 0x7fffffe000000000000000000000000 +``` + +Lookup for 'abcdefghijklmnopqrstuvwxyz'. + +### UPPERCASE_7_BIT_ASCII + +```solidity +uint128 internal constant UPPERCASE_7_BIT_ASCII = 0x7fffffe0000000000000000 +``` + +Lookup for 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'. + +### DIGITS_7_BIT_ASCII + +```solidity +uint128 internal constant DIGITS_7_BIT_ASCII = 0x3ff000000000000 +``` + +Lookup for '0123456789'. + +### HEXDIGITS_7_BIT_ASCII + +```solidity +uint128 internal constant HEXDIGITS_7_BIT_ASCII = + 0x7e0000007e03ff000000000000 +``` + +Lookup for '0123456789abcdefABCDEF'. + +### OCTDIGITS_7_BIT_ASCII + +```solidity +uint128 internal constant OCTDIGITS_7_BIT_ASCII = 0xff000000000000 +``` + +Lookup for '01234567'. + +### PRINTABLE_7_BIT_ASCII + +```solidity +uint128 internal constant PRINTABLE_7_BIT_ASCII = + 0x7fffffffffffffffffffffff00003e00 +``` + +Lookup for '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~ \t\n\r\x0b\x0c'. + +### PUNCTUATION_7_BIT_ASCII + +```solidity +uint128 internal constant PUNCTUATION_7_BIT_ASCII = + 0x78000001f8000001fc00fffe00000000 +``` + +Lookup for '!"#$%&\'()*+,-./:;<=>?@[\\]^_`{|}~'. + +### WHITESPACE_7_BIT_ASCII + +```solidity +uint128 internal constant WHITESPACE_7_BIT_ASCII = 0x100003e00 +``` + +Lookup for ' \t\n\r\x0b\x0c'. + +## String Storage Operations + +### set(StringStorage,string) + +```solidity +function set(StringStorage storage $, string memory s) internal +``` + +Sets the value of the string storage `$` to `s`. + +### setCalldata(StringStorage,string) + +```solidity +function setCalldata(StringStorage storage $, string calldata s) internal +``` + +Sets the value of the string storage `$` to `s`. + +### clear(StringStorage) + +```solidity +function clear(StringStorage storage $) internal +``` + +Sets the value of the string storage `$` to the empty string. + +### isEmpty(StringStorage) + +```solidity +function isEmpty(StringStorage storage $) internal view returns (bool) +``` + +Returns whether the value stored is `$` is the empty string "". + +### length(StringStorage) + +```solidity +function length(StringStorage storage $) internal view returns (uint256) +``` + +Returns the length of the value stored in `$`. + +### get(StringStorage) + +```solidity +function get(StringStorage storage $) + internal + view + returns (string memory) +``` + +Returns the value stored in `$`. + +### bytesStorage(StringStorage) + +```solidity +function bytesStorage(StringStorage storage $) + internal + pure + returns (LibBytes.BytesStorage storage casted) +``` + +Helper to cast `$` to a `BytesStorage`. + +## Decimal Operations + +### toString(uint256) + +```solidity +function toString(uint256 value) + internal + pure + returns (string memory result) +``` + +Returns the base 10 decimal representation of `value`. + +### toString(int256) + +```solidity +function toString(int256 value) + internal + pure + returns (string memory result) +``` + +Returns the base 10 decimal representation of `value`. + +## Hexadecimal Operations + +### toHexString(uint256,uint256) + +```solidity +function toHexString(uint256 value, uint256 byteCount) + internal + pure + returns (string memory result) +``` + +Returns the hexadecimal representation of `value`, +left-padded to an input length of `byteCount` bytes. +The output is prefixed with "0x" encoded using 2 hexadecimal digits per byte, +giving a total length of `byteCount * 2 + 2` bytes. +Reverts if `byteCount` is too small for the output to contain all the digits. + +### toHexStringNoPrefix(uint256,uint256) + +```solidity +function toHexStringNoPrefix(uint256 value, uint256 byteCount) + internal + pure + returns (string memory result) +``` + +Returns the hexadecimal representation of `value`, +left-padded to an input length of `byteCount` bytes. +The output is not prefixed with "0x" and is encoded using 2 hexadecimal digits per byte, +giving a total length of `byteCount * 2` bytes. +Reverts if `byteCount` is too small for the output to contain all the digits. + +### toHexString(uint256) + +```solidity +function toHexString(uint256 value) + internal + pure + returns (string memory result) +``` + +Returns the hexadecimal representation of `value`. +The output is prefixed with "0x" and encoded using 2 hexadecimal digits per byte. +As address are 20 bytes long, the output will left-padded to have +a length of `20 * 2 + 2` bytes. + +### toMinimalHexString(uint256) + +```solidity +function toMinimalHexString(uint256 value) + internal + pure + returns (string memory result) +``` + +Returns the hexadecimal representation of `value`. +The output is prefixed with "0x". +The output excludes leading "0" from the `toHexString` output. +`0x00: "0x0", 0x01: "0x1", 0x12: "0x12", 0x123: "0x123"`. + +### toMinimalHexStringNoPrefix(uint256) + +```solidity +function toMinimalHexStringNoPrefix(uint256 value) + internal + pure + returns (string memory result) +``` + +Returns the hexadecimal representation of `value`. +The output excludes leading "0" from the `toHexStringNoPrefix` output. +`0x00: "0", 0x01: "1", 0x12: "12", 0x123: "123"`. + +### toHexStringNoPrefix(uint256) + +```solidity +function toHexStringNoPrefix(uint256 value) + internal + pure + returns (string memory result) +``` + +Returns the hexadecimal representation of `value`. +The output is encoded using 2 hexadecimal digits per byte. +As address are 20 bytes long, the output will left-padded to have +a length of `20 * 2` bytes. + +### toHexStringChecksummed(address) + +```solidity +function toHexStringChecksummed(address value) + internal + pure + returns (string memory result) +``` + +Returns the hexadecimal representation of `value`. +The output is prefixed with "0x", encoded using 2 hexadecimal digits per byte, +and the alphabets are capitalized conditionally according to +https://eips.ethereum.org/EIPS/eip-55 + +### toHexString(address) + +```solidity +function toHexString(address value) + internal + pure + returns (string memory result) +``` + +Returns the hexadecimal representation of `value`. +The output is prefixed with "0x" and encoded using 2 hexadecimal digits per byte. + +### toHexStringNoPrefix(address) + +```solidity +function toHexStringNoPrefix(address value) + internal + pure + returns (string memory result) +``` + +Returns the hexadecimal representation of `value`. +The output is encoded using 2 hexadecimal digits per byte. + +### toHexString(bytes) + +```solidity +function toHexString(bytes memory raw) + internal + pure + returns (string memory result) +``` + +Returns the hex encoded string from the raw bytes. +The output is encoded using 2 hexadecimal digits per byte. + +### toHexStringNoPrefix(bytes) + +```solidity +function toHexStringNoPrefix(bytes memory raw) + internal + pure + returns (string memory result) +``` + +Returns the hex encoded string from the raw bytes. +The output is encoded using 2 hexadecimal digits per byte. + +## Rune String Operations + +### runeCount(string) + +```solidity +function runeCount(string memory s) + internal + pure + returns (uint256 result) +``` + +Returns the number of UTF characters in the string. + +### is7BitASCII(string) + +```solidity +function is7BitASCII(string memory s) internal pure returns (bool result) +``` + +Returns if this string is a 7-bit ASCII string. +(i.e. all characters codes are in [0..127]) + +### is7BitASCII(string,uint128) + +```solidity +function is7BitASCII(string memory s, uint128 allowed) + internal + pure + returns (bool result) +``` + +Returns if this string is a 7-bit ASCII string, +AND all characters are in the `allowed` lookup. +Note: If `s` is empty, returns true regardless of `allowed`. + +### to7BitASCIIAllowedLookup(string) + +```solidity +function to7BitASCIIAllowedLookup(string memory s) + internal + pure + returns (uint128 result) +``` + +Converts the bytes in the 7-bit ASCII string `s` to +an allowed lookup for use in `is7BitASCII(s, allowed)`. +To save runtime gas, you can cache the result in an immutable variable. + +## Byte String Operations + +For performance and bytecode compactness, byte string operations are restricted +to 7-bit ASCII strings. All offsets are byte offsets, not UTF character offsets. +Usage of byte string operations on charsets with runes spanning two or more bytes +can lead to undefined behavior. + +### replace(string,string,string) + +```solidity +function replace( + string memory subject, + string memory needle, + string memory replacement +) internal pure returns (string memory) +``` + +Returns `subject` all occurrences of `needle` replaced with `replacement`. + +### indexOf(string,string,uint256) + +```solidity +function indexOf(string memory subject, string memory needle, uint256 from) + internal + pure + returns (uint256) +``` + +Returns the byte index of the first location of `needle` in `subject`, +needleing from left to right, starting from `from`. +Returns `NOT_FOUND` (i.e. `type(uint256).max`) if the `needle` is not found. + +### indexOf(string,string) + +```solidity +function indexOf(string memory subject, string memory needle) + internal + pure + returns (uint256) +``` + +Returns the byte index of the first location of `needle` in `subject`, +needleing from left to right. +Returns `NOT_FOUND` (i.e. `type(uint256).max`) if the `needle` is not found. + +### lastIndexOf(string,string,uint256) + +```solidity +function lastIndexOf( + string memory subject, + string memory needle, + uint256 from +) internal pure returns (uint256) +``` + +Returns the byte index of the first location of `needle` in `subject`, +needleing from right to left, starting from `from`. +Returns `NOT_FOUND` (i.e. `type(uint256).max`) if the `needle` is not found. + +### lastIndexOf(string,string) + +```solidity +function lastIndexOf(string memory subject, string memory needle) + internal + pure + returns (uint256) +``` + +Returns the byte index of the first location of `needle` in `subject`, +needleing from right to left. +Returns `NOT_FOUND` (i.e. `type(uint256).max`) if the `needle` is not found. + +### contains(string,string) + +```solidity +function contains(string memory subject, string memory needle) + internal + pure + returns (bool) +``` + +Returns true if `needle` is found in `subject`, false otherwise. + +### startsWith(string,string) + +```solidity +function startsWith(string memory subject, string memory needle) + internal + pure + returns (bool) +``` + +Returns whether `subject` starts with `needle`. + +### endsWith(string,string) + +```solidity +function endsWith(string memory subject, string memory needle) + internal + pure + returns (bool) +``` + +Returns whether `subject` ends with `needle`. + +### repeat(string,uint256) + +```solidity +function repeat(string memory subject, uint256 times) + internal + pure + returns (string memory) +``` + +Returns `subject` repeated `times`. + +### slice(string,uint256,uint256) + +```solidity +function slice(string memory subject, uint256 start, uint256 end) + internal + pure + returns (string memory) +``` + +Returns a copy of `subject` sliced from `start` to `end` (exclusive). +`start` and `end` are byte offsets. + +### slice(string,uint256) + +```solidity +function slice(string memory subject, uint256 start) + internal + pure + returns (string memory) +``` + +Returns a copy of `subject` sliced from `start` to the end of the string. +`start` is a byte offset. + +### indicesOf(string,string) + +```solidity +function indicesOf(string memory subject, string memory needle) + internal + pure + returns (uint256[] memory) +``` + +Returns all the indices of `needle` in `subject`. +The indices are byte offsets. + +### split(string,string) + +```solidity +function split(string memory subject, string memory delimiter) + internal + pure + returns (string[] memory result) +``` + +Returns a arrays of strings based on the `delimiter` inside of the `subject` string. + +### concat(string,string) + +```solidity +function concat(string memory a, string memory b) + internal + pure + returns (string memory) +``` + +Returns a concatenated string of `a` and `b`. +Cheaper than `string.concat()` and does not de-align the free memory pointer. + +### toCase(string,bool) + +```solidity +function toCase(string memory subject, bool toUpper) + internal + pure + returns (string memory result) +``` + +Returns a copy of the string in either lowercase or UPPERCASE. +WARNING! This function is only compatible with 7-bit ASCII strings. + +### fromSmallString(bytes32) + +```solidity +function fromSmallString(bytes32 s) + internal + pure + returns (string memory result) +``` + +Returns a string from a small bytes32 string. +`s` must be null-terminated, or behavior will be undefined. + +### normalizeSmallString(bytes32) + +```solidity +function normalizeSmallString(bytes32 s) + internal + pure + returns (bytes32 result) +``` + +Returns the small string, with all bytes after the first null byte zeroized. + +### toSmallString(string) + +```solidity +function toSmallString(string memory s) + internal + pure + returns (bytes32 result) +``` + +Returns the string as a normalized null-terminated small string. + +### lower(string) + +```solidity +function lower(string memory subject) + internal + pure + returns (string memory result) +``` + +Returns a lowercased copy of the string. +WARNING! This function is only compatible with 7-bit ASCII strings. + +### upper(string) + +```solidity +function upper(string memory subject) + internal + pure + returns (string memory result) +``` + +Returns an UPPERCASED copy of the string. +WARNING! This function is only compatible with 7-bit ASCII strings. + +### escapeHTML(string) + +```solidity +function escapeHTML(string memory s) + internal + pure + returns (string memory result) +``` + +Escapes the string to be used within HTML tags. + +### escapeJSON(string,bool) + +```solidity +function escapeJSON(string memory s, bool addDoubleQuotes) + internal + pure + returns (string memory result) +``` + +Escapes the string to be used within double-quotes in a JSON. +If `addDoubleQuotes` is true, the result will be enclosed in double-quotes. + +### escapeJSON(string) + +```solidity +function escapeJSON(string memory s) + internal + pure + returns (string memory result) +``` + +Escapes the string to be used within double-quotes in a JSON. + +### encodeURIComponent(string) + +```solidity +function encodeURIComponent(string memory s) + internal + pure + returns (string memory result) +``` + +Encodes `s` so that it can be safely used in a URI, +just like `encodeURIComponent` in JavaScript. +See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/encodeURIComponent +See: https://datatracker.ietf.org/doc/html/rfc2396 +See: https://datatracker.ietf.org/doc/html/rfc3986 + +### eq(string,string) + +```solidity +function eq(string memory a, string memory b) + internal + pure + returns (bool result) +``` + +Returns whether `a` equals `b`. + +### eqs(string,bytes32) + +```solidity +function eqs(string memory a, bytes32 b) + internal + pure + returns (bool result) +``` + +Returns whether `a` equals `b`, where `b` is a null-terminated small string. + +### cmp(string,string) + +```solidity +function cmp(string memory a, string memory b) + internal + pure + returns (int256) +``` + +Returns 0 if `a == b`, -1 if `a < b`, +1 if `a > b`. +If `a` == b[:a.length]`, and `a.length < b.length`, returns -1. + +### packOne(string) + +```solidity +function packOne(string memory a) internal pure returns (bytes32 result) +``` + +Packs a single string with its length into a single word. +Returns `bytes32(0)` if the length is zero or greater than 31. + +### unpackOne(bytes32) + +```solidity +function unpackOne(bytes32 packed) + internal + pure + returns (string memory result) +``` + +Unpacks a string packed using {packOne}. +Returns the empty string if `packed` is `bytes32(0)`. +If `packed` is not an output of {packOne}, the output behavior is undefined. + +### packTwo(string,string) + +```solidity +function packTwo(string memory a, string memory b) + internal + pure + returns (bytes32 result) +``` + +Packs two strings with their lengths into a single word. +Returns `bytes32(0)` if combined length is zero or greater than 30. + +### unpackTwo(bytes32) + +```solidity +function unpackTwo(bytes32 packed) + internal + pure + returns (string memory resultA, string memory resultB) +``` + +Unpacks strings packed using {packTwo}. +Returns the empty strings if `packed` is `bytes32(0)`. +If `packed` is not an output of {packTwo}, the output behavior is undefined. + +### directReturn(string) + +```solidity +function directReturn(string memory a) internal pure +``` + +Directly returns `a` without copying. \ No newline at end of file diff --git a/docs/utils/libtransient.md b/docs/utils/libtransient.md new file mode 100644 index 000000000..a1205e554 --- /dev/null +++ b/docs/utils/libtransient.md @@ -0,0 +1,745 @@ +# LibTransient + +Library for RLP encoding and CREATE address computation. + + +Note: + +The functions postfixed with `Compat` will only use transient storage on L1. +L2s are super cheap anyway. +For best safety, always clear the storage after use. + + + + + +## Structs + +### TUint256 + +```solidity +struct TUint256 { + uint256 _spacer; +} +``` + +Pointer struct to a `uint256` in transient storage. + +### TInt256 + +```solidity +struct TInt256 { + uint256 _spacer; +} +``` + +Pointer struct to a `int256` in transient storage. + +### TBytes32 + +```solidity +struct TBytes32 { + uint256 _spacer; +} +``` + +Pointer struct to a `bytes32` in transient storage. + +### TAddress + +```solidity +struct TAddress { + uint256 _spacer; +} +``` + +Pointer struct to a `address` in transient storage. + +### TBool + +```solidity +struct TBool { + uint256 _spacer; +} +``` + +Pointer struct to a `bool` in transient storage. + +### TBytes + +```solidity +struct TBytes { + uint256 _spacer; +} +``` + +Pointer struct to a `bytes` in transient storage. + +## Uint256 Operations + +### tUint256(bytes32) + +```solidity +function tUint256(bytes32 tSlot) + internal + pure + returns (TUint256 storage ptr) +``` + +Returns a pointer to a `uint256` in transient storage. + +### tUint256(uint256) + +```solidity +function tUint256(uint256 tSlot) + internal + pure + returns (TUint256 storage ptr) +``` + +Returns a pointer to a `uint256` in transient storage. + +### get(TUint256) + +```solidity +function get(TUint256 storage ptr) internal view returns (uint256 result) +``` + +Returns the value at transient `ptr`. + +### getCompat(TUint256) + +```solidity +function getCompat(TUint256 storage ptr) + internal + view + returns (uint256 result) +``` + +Returns the value at transient `ptr`. + +### set(TUint256,uint256) + +```solidity +function set(TUint256 storage ptr, uint256 value) internal +``` + +Sets the value at transient `ptr`. + +### setCompat(TUint256,uint256) + +```solidity +function setCompat(TUint256 storage ptr, uint256 value) internal +``` + +Sets the value at transient `ptr`. + +### clear(TUint256) + +```solidity +function clear(TUint256 storage ptr) internal +``` + +Clears the value at transient `ptr`. + +### clearCompat(TUint256) + +```solidity +function clearCompat(TUint256 storage ptr) internal +``` + +Clears the value at transient `ptr`. + +### inc(TUint256) + +```solidity +function inc(TUint256 storage ptr) internal returns (uint256 newValue) +``` + +Increments the value at transient `ptr` by 1. + +### incCompat(TUint256) + +```solidity +function incCompat(TUint256 storage ptr) + internal + returns (uint256 newValue) +``` + +Increments the value at transient `ptr` by 1. + +### inc(TUint256,uint256) + +```solidity +function inc(TUint256 storage ptr, uint256 delta) + internal + returns (uint256 newValue) +``` + +Increments the value at transient `ptr` by `delta`. + +### incCompat(TUint256,uint256) + +```solidity +function incCompat(TUint256 storage ptr, uint256 delta) + internal + returns (uint256 newValue) +``` + +Increments the value at transient `ptr` by `delta`. + +### dec(TUint256) + +```solidity +function dec(TUint256 storage ptr) internal returns (uint256 newValue) +``` + +Decrements the value at transient `ptr` by 1. + +### decCompat(TUint256) + +```solidity +function decCompat(TUint256 storage ptr) + internal + returns (uint256 newValue) +``` + +Decrements the value at transient `ptr` by `delta`. + +### dec(TUint256,uint256) + +```solidity +function dec(TUint256 storage ptr, uint256 delta) + internal + returns (uint256 newValue) +``` + +Decrements the value at transient `ptr` by `delta`. + +### decCompat(TUint256,uint256) + +```solidity +function decCompat(TUint256 storage ptr, uint256 delta) + internal + returns (uint256 newValue) +``` + +Decrements the value at transient `ptr` by `delta`. + +### incSigned(TUint256,int256) + +```solidity +function incSigned(TUint256 storage ptr, int256 delta) + internal + returns (uint256 newValue) +``` + +Increments the value at transient `ptr` by `delta`. + +### incSignedCompat(TUint256,int256) + +```solidity +function incSignedCompat(TUint256 storage ptr, int256 delta) + internal + returns (uint256 newValue) +``` + +Increments the value at transient `ptr` by `delta`. + +### decSigned(TUint256,int256) + +```solidity +function decSigned(TUint256 storage ptr, int256 delta) + internal + returns (uint256 newValue) +``` + +Decrements the value at transient `ptr` by `delta`. + +### decSignedCompat(TUint256,int256) + +```solidity +function decSignedCompat(TUint256 storage ptr, int256 delta) + internal + returns (uint256 newValue) +``` + +Decrements the value at transient `ptr` by `delta`. + +## Int256 Operations + +### tInt256(bytes32) + +```solidity +function tInt256(bytes32 tSlot) + internal + pure + returns (TInt256 storage ptr) +``` + +Returns a pointer to a `int256` in transient storage. + +### tInt256(uint256) + +```solidity +function tInt256(uint256 tSlot) + internal + pure + returns (TInt256 storage ptr) +``` + +Returns a pointer to a `int256` in transient storage. + +### get(TInt256) + +```solidity +function get(TInt256 storage ptr) internal view returns (int256 result) +``` + +Returns the value at transient `ptr`. + +### getCompat(TInt256) + +```solidity +function getCompat(TInt256 storage ptr) + internal + view + returns (int256 result) +``` + +Returns the value at transient `ptr`. + +### set(TInt256,int256) + +```solidity +function set(TInt256 storage ptr, int256 value) internal +``` + +Sets the value at transient `ptr`. + +### setCompat(TInt256,int256) + +```solidity +function setCompat(TInt256 storage ptr, int256 value) internal +``` + +Sets the value at transient `ptr`. + +### clear(TInt256) + +```solidity +function clear(TInt256 storage ptr) internal +``` + +Clears the value at transient `ptr`. + +### clearCompat(TInt256) + +```solidity +function clearCompat(TInt256 storage ptr) internal +``` + +Clears the value at transient `ptr`. + +### inc(TInt256) + +```solidity +function inc(TInt256 storage ptr) internal returns (int256 newValue) +``` + +Increments the value at transient `ptr` by 1. + +### incCompat(TInt256) + +```solidity +function incCompat(TInt256 storage ptr) + internal + returns (int256 newValue) +``` + +Increments the value at transient `ptr` by 1. + +### inc(TInt256,int256) + +```solidity +function inc(TInt256 storage ptr, int256 delta) + internal + returns (int256 newValue) +``` + +Increments the value at transient `ptr` by `delta`. + +### incCompat(TInt256,int256) + +```solidity +function incCompat(TInt256 storage ptr, int256 delta) + internal + returns (int256 newValue) +``` + +Increments the value at transient `ptr` by `delta`. + +### dec(TInt256) + +```solidity +function dec(TInt256 storage ptr) internal returns (int256 newValue) +``` + +Decrements the value at transient `ptr` by 1. + +### decCompat(TInt256) + +```solidity +function decCompat(TInt256 storage ptr) + internal + returns (int256 newValue) +``` + +Decrements the value at transient `ptr` by 1. + +### dec(TInt256,int256) + +```solidity +function dec(TInt256 storage ptr, int256 delta) + internal + returns (int256 newValue) +``` + +Decrements the value at transient `ptr` by `delta`. + +### decCompat(TInt256,int256) + +```solidity +function decCompat(TInt256 storage ptr, int256 delta) + internal + returns (int256 newValue) +``` + +Decrements the value at transient `ptr` by `delta`. + +## Bytes32 Operations + +### tBytes32(bytes32) + +```solidity +function tBytes32(bytes32 tSlot) + internal + pure + returns (TBytes32 storage ptr) +``` + +Returns a pointer to a `bytes32` in transient storage. + +### tBytes32(uint256) + +```solidity +function tBytes32(uint256 tSlot) + internal + pure + returns (TBytes32 storage ptr) +``` + +Returns a pointer to a `bytes32` in transient storage. + +### get(TBytes32) + +```solidity +function get(TBytes32 storage ptr) internal view returns (bytes32 result) +``` + +Returns the value at transient `ptr`. + +### getCompat(TBytes32) + +```solidity +function getCompat(TBytes32 storage ptr) + internal + view + returns (bytes32 result) +``` + +Returns the value at transient `ptr`. + +### set(TBytes32,bytes32) + +```solidity +function set(TBytes32 storage ptr, bytes32 value) internal +``` + +Sets the value at transient `ptr`. + +### setCompat(TBytes32,bytes32) + +```solidity +function setCompat(TBytes32 storage ptr, bytes32 value) internal +``` + +Sets the value at transient `ptr`. + +### clear(TBytes32) + +```solidity +function clear(TBytes32 storage ptr) internal +``` + +Clears the value at transient `ptr`. + +### clearCompat(TBytes32) + +```solidity +function clearCompat(TBytes32 storage ptr) internal +``` + +Clears the value at transient `ptr`. + +## Address Operations + +### tAddress(bytes32) + +```solidity +function tAddress(bytes32 tSlot) + internal + pure + returns (TAddress storage ptr) +``` + +Returns a pointer to a `address` in transient storage. + +### tAddress(uint256) + +```solidity +function tAddress(uint256 tSlot) + internal + pure + returns (TAddress storage ptr) +``` + +Returns a pointer to a `address` in transient storage. + +### get(TAddress) + +```solidity +function get(TAddress storage ptr) internal view returns (address result) +``` + +Returns the value at transient `ptr`. + +### getCompat(TAddress) + +```solidity +function getCompat(TAddress storage ptr) + internal + view + returns (address result) +``` + +Returns the value at transient `ptr`. + +### set(TAddress,address) + +```solidity +function set(TAddress storage ptr, address value) internal +``` + +Sets the value at transient `ptr`. + +### setCompat(TAddress,address) + +```solidity +function setCompat(TAddress storage ptr, address value) internal +``` + +Sets the value at transient `ptr`. + +### clear(TAddress) + +```solidity +function clear(TAddress storage ptr) internal +``` + +Clears the value at transient `ptr`. + +### clearCompat(TAddress) + +```solidity +function clearCompat(TAddress storage ptr) internal +``` + +Clears the value at transient `ptr`. + +## Bool Operations + +### tBool(bytes32) + +```solidity +function tBool(bytes32 tSlot) internal pure returns (TBool storage ptr) +``` + +Returns a pointer to a `bool` in transient storage. + +### tBool(uint256) + +```solidity +function tBool(uint256 tSlot) internal pure returns (TBool storage ptr) +``` + +Returns a pointer to a `bool` in transient storage. + +### get(TBool) + +```solidity +function get(TBool storage ptr) internal view returns (bool result) +``` + +Returns the value at transient `ptr`. + +### getCompat(TBool) + +```solidity +function getCompat(TBool storage ptr) internal view returns (bool result) +``` + +Returns the value at transient `ptr`. + +### set(TBool,bool) + +```solidity +function set(TBool storage ptr, bool value) internal +``` + +Sets the value at transient `ptr`. + +### setCompat(TBool,bool) + +```solidity +function setCompat(TBool storage ptr, bool value) internal +``` + +Sets the value at transient `ptr`. + +### clear(TBool) + +```solidity +function clear(TBool storage ptr) internal +``` + +Clears the value at transient `ptr`. + +### clearCompat(TBool) + +```solidity +function clearCompat(TBool storage ptr) internal +``` + +Clears the value at transient `ptr`. + +## Bytes Operations + +### tBytes(bytes32) + +```solidity +function tBytes(bytes32 tSlot) internal pure returns (TBytes storage ptr) +``` + +Returns a pointer to a `bytes` in transient storage. + +### tBytes(uint256) + +```solidity +function tBytes(uint256 tSlot) internal pure returns (TBytes storage ptr) +``` + +Returns a pointer to a `bytes` in transient storage. + +### length(TBytes) + +```solidity +function length(TBytes storage ptr) + internal + view + returns (uint256 result) +``` + +Returns the length of the bytes stored at transient `ptr`. + +### lengthCompat(TBytes) + +```solidity +function lengthCompat(TBytes storage ptr) + internal + view + returns (uint256 result) +``` + +Returns the length of the bytes stored at transient `ptr`. + +### get(TBytes) + +```solidity +function get(TBytes storage ptr) + internal + view + returns (bytes memory result) +``` + +Returns the bytes stored at transient `ptr`. + +### getCompat(TBytes) + +```solidity +function getCompat(TBytes storage ptr) + internal + view + returns (bytes memory result) +``` + +Returns the bytes stored at transient `ptr`. + +### set(TBytes,bytes) + +```solidity +function set(TBytes storage ptr, bytes memory value) internal +``` + +Sets the value at transient `ptr`. + +### setCompat(TBytes,bytes) + +```solidity +function setCompat(TBytes storage ptr, bytes memory value) internal +``` + +Sets the value at transient `ptr`. + +### setCalldata(TBytes,bytes) + +```solidity +function setCalldata(TBytes storage ptr, bytes calldata value) internal +``` + +Sets the value at transient `ptr`. + +### setCalldataCompat(TBytes,bytes) + +```solidity +function setCalldataCompat(TBytes storage ptr, bytes calldata value) + internal +``` + +Sets the value at transient `ptr`. + +### clear(TBytes) + +```solidity +function clear(TBytes storage ptr) internal +``` + +Clears the value at transient `ptr`. + +### clearCompat(TBytes) + +```solidity +function clearCompat(TBytes storage ptr) internal +``` + +Clears the value at transient `ptr`. \ No newline at end of file diff --git a/docs/utils/libzip.md b/docs/utils/libzip.md new file mode 100644 index 000000000..773f92042 --- /dev/null +++ b/docs/utils/libzip.md @@ -0,0 +1,91 @@ +# LibZip + +Library for compressing and decompressing bytes. + + +Note: + +The accompanying solady.js + + + + + +## Fast LZ Operations + +LZ77 implementation based on FastLZ. +Equivalent to level 1 compression and decompression at the following commit: +https://github.com/ariya/FastLZ/commit/344eb4025f9ae866ebf7a2ec48850f7113a97a42 +Decompression is backwards compatible. + +### flzCompress(bytes) + +```solidity +function flzCompress(bytes memory data) + internal + pure + returns (bytes memory result) +``` + +Returns the compressed `data`. + +### flzDecompress(bytes) + +```solidity +function flzDecompress(bytes memory data) + internal + pure + returns (bytes memory result) +``` + +Returns the decompressed `data`. + +## Calldata Operations + +Calldata compression and decompression using selective run length encoding: +- Sequences of 0x00 (up to 128 consecutive). +- Sequences of 0xff (up to 32 consecutive). +A run length encoded block consists of two bytes: +(0) 0x00 +(1) A control byte with the following bit layout: +- [7] `0: 0x00, 1: 0xff`. +- [0..6] `runLength - 1`. +The first 4 bytes are bitwise negated so that the compressed calldata +can be dispatched into the `fallback` and `receive` functions. + +### cdCompress(bytes) + +```solidity +function cdCompress(bytes memory data) + internal + pure + returns (bytes memory result) +``` + +Returns the compressed `data`. + +### cdDecompress(bytes) + +```solidity +function cdDecompress(bytes memory data) + internal + pure + returns (bytes memory result) +``` + +Returns the decompressed `data`. + +### cdFallback() + +```solidity +function cdFallback() internal +``` + +To be called in the `fallback` function. +```solidity +fallback() external payable { LibZip.cdFallback(); } +receive() external payable {} +Silence compiler warning to add a `receive` function. +``` +For efficiency, this function will directly return the results, terminating the context. +If called internally, it must be called at the end of the function. \ No newline at end of file diff --git a/docs/utils/lifebuoy.md b/docs/utils/lifebuoy.md new file mode 100644 index 000000000..854000156 --- /dev/null +++ b/docs/utils/lifebuoy.md @@ -0,0 +1,262 @@ +# Lifebuoy + +Class that allows for rescue of ETH, ERC20, ERC721 tokens. + + + + + + + + +## Custom Errors + +### RescueUnauthorizedOrLocked() + +```solidity +error RescueUnauthorizedOrLocked() +``` + +The caller is not authorized to rescue or lock the rescue function. + +### RescueTransferFailed() + +```solidity +error RescueTransferFailed() +``` + +The rescue operation has failed due to a failed transfer. + +## Lock Flags Constants + +These flags are kept internal to avoid bloating up the function dispatch. +You can just copy paste this into your own code. + +### _LIFEBUOY_DEPLOYER_ACCESS_LOCK + +```solidity +uint256 internal constant _LIFEBUOY_DEPLOYER_ACCESS_LOCK = 1 << 0 +``` + +Flag to denote that the deployer's access is locked. (1) + +### _LIFEBUOY_OWNER_ACCESS_LOCK + +```solidity +uint256 internal constant _LIFEBUOY_OWNER_ACCESS_LOCK = 1 << 1 +``` + +Flag to denote that the `owner()`'s access is locked. (2) + +### _LIFEBUOY_LOCK_RESCUE_LOCK + +```solidity +uint256 internal constant _LIFEBUOY_LOCK_RESCUE_LOCK = 1 << 2 +``` + +Flag to denote that the `lockRescue` function is locked. (4) + +### _LIFEBUOY_RESCUE_ETH_LOCK + +```solidity +uint256 internal constant _LIFEBUOY_RESCUE_ETH_LOCK = 1 << 3 +``` + +Flag to denote that the `rescueETH` function is locked. (8) + +### _LIFEBUOY_RESCUE_ERC20_LOCK + +```solidity +uint256 internal constant _LIFEBUOY_RESCUE_ERC20_LOCK = 1 << 4 +``` + +Flag to denote that the `rescueERC20` function is locked. (16) + +### _LIFEBUOY_RESCUE_ERC721_LOCK + +```solidity +uint256 internal constant _LIFEBUOY_RESCUE_ERC721_LOCK = 1 << 5 +``` + +Flag to denote that the `rescueERC721` function is locked. (32) + +### _LIFEBUOY_RESCUE_ERC1155_LOCK + +```solidity +uint256 internal constant _LIFEBUOY_RESCUE_ERC1155_LOCK = 1 << 6 +``` + +Flag to denote that the `rescueERC1155` function is locked. (64) + +### _LIFEBUOY_RESCUE_ERC6909_LOCK + +```solidity +uint256 internal constant _LIFEBUOY_RESCUE_ERC6909_LOCK = 1 << 7 +``` + +Flag to denote that the `rescueERC6909` function is locked. (128) + +## Immutables + +### _lifebuoyDeployerHash + +```solidity +bytes32 internal immutable _lifebuoyDeployerHash +``` + +For checking that the caller is the deployer and +that the context is not a delegatecall +(so that the implementation deployer cannot drain proxies). + +## Storage + +### _RESCUE_LOCKED_FLAGS_SLOT + +```solidity +bytes32 internal constant _RESCUE_LOCKED_FLAGS_SLOT = + 0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffb8e2915b +``` + +The rescue locked flags slot is given by: +`bytes32(~uint256(uint32(bytes4(keccak256("_RESCUE_LOCKED_FLAGS_SLOT_NOT")))))`. +It is intentionally chosen to be a high value +to avoid collision with lower slots. +The choice of manual storage layout is to enable compatibility +with both regular and upgradeable contracts. + +## Constructor + +### _lifebuoyDefaultDeployer() + +```solidity +function _lifebuoyDefaultDeployer() + internal + view + virtual + returns (address) +``` + +Returns `tx.origin` by default. Override to return another address if needed. +Note: If you are deploying via a untrusted `tx.origin` (e.g. ERC4337 bundler) +you MUST override this function to return a trusted address. + +## Rescue Operations + +### rescueETH(address,uint256) + +```solidity +function rescueETH(address to, uint256 amount) + public + payable + virtual + onlyRescuer(_LIFEBUOY_RESCUE_ETH_LOCK) +``` + +Sends `amount` (in wei) ETH from the current contract to `to`. +Reverts upon failure. + +### rescueERC20(address,address,uint256) + +```solidity +function rescueERC20(address token, address to, uint256 amount) + public + payable + virtual + onlyRescuer(_LIFEBUOY_RESCUE_ERC20_LOCK) +``` + +Sends `amount` of ERC20 `token` from the current contract to `to`. +Does not check for existence of token or return data. Reverts upon failure. + +### rescueERC721(address,address,uint256) + +```solidity +function rescueERC721(address token, address to, uint256 id) + public + payable + virtual + onlyRescuer(_LIFEBUOY_RESCUE_ERC721_LOCK) +``` + +Sends `id` of ERC721 `token` from the current contract to `to`. +Does not check for existence of token or return data. Reverts upon failure. + +### rescueERC1155(address,address,uint256,uint256,bytes) + +```solidity +function rescueERC1155( + address token, + address to, + uint256 id, + uint256 amount, + bytes calldata data +) public payable virtual onlyRescuer(_LIFEBUOY_RESCUE_ERC1155_LOCK) +``` + +Sends `amount` of `id` of ERC1155 `token` from the current contract to `to`. +Does not check for existence of token or return data. Reverts upon failure. + +### rescueERC6909(address,address,uint256,uint256) + +```solidity +function rescueERC6909( + address token, + address to, + uint256 id, + uint256 amount +) public payable virtual onlyRescuer(_LIFEBUOY_RESCUE_ERC6909_LOCK) +``` + +Sends `amount` of `id` of ERC6909 `token` from the current contract to `to`. +Does not check for existence of token or return data. Reverts upon failure. + +## Rescue Authorization Operations + +### rescueLocked() + +```solidity +function rescueLocked() public view virtual returns (uint256 locks) +``` + +Returns the flags denoting whether access to rescue functions +(including `lockRescue`) is locked. + +### lockRescue(uint256) + +```solidity +function lockRescue(uint256 locksToSet) + public + payable + virtual + onlyRescuer(_LIFEBUOY_LOCK_RESCUE_LOCK) +``` + +Locks (i.e. permanently removes) access to rescue functions (including `lockRescue`). + +### _lockRescue(uint256) + +```solidity +function _lockRescue(uint256 locksToSet) internal virtual +``` + +Internal function to set the lock flags without going through access control. + +### _checkRescuer(uint256) + +```solidity +function _checkRescuer(uint256 modeLock) internal view virtual +``` + +Requires that the rescue function being guarded is: +1. Not locked, AND +2. Called by either: + (a) The `owner()`, OR + (b) The deployer (if not via a delegate call and deployer is an EOA). + +### onlyRescuer(uint256) + +```solidity +modifier onlyRescuer(uint256 modeLock) virtual +``` + +Modifier that calls `_checkRescuer()` at the start of the function. \ No newline at end of file diff --git a/docs/utils/merkleprooflib.md b/docs/utils/merkleprooflib.md new file mode 100644 index 000000000..2d896ee0c --- /dev/null +++ b/docs/utils/merkleprooflib.md @@ -0,0 +1,102 @@ +# MerkleProofLib + +Gas optimized verification of proof of inclusion for a leaf in a Merkle tree. + + + + + + + + +## Merkle Proof Verification Operations + +### verify(bytes32[],bytes32,bytes32) + +```solidity +function verify(bytes32[] memory proof, bytes32 root, bytes32 leaf) + internal + pure + returns (bool isValid) +``` + +Returns whether `leaf` exists in the Merkle tree with `root`, given `proof`. + +### verifyCalldata(bytes32[],bytes32,bytes32) + +```solidity +function verifyCalldata( + bytes32[] calldata proof, + bytes32 root, + bytes32 leaf +) internal pure returns (bool isValid) +``` + +Returns whether `leaf` exists in the Merkle tree with `root`, given `proof`. + +### verifyMultiProof(bytes32[],bytes32,bytes32[],bool[]) + +```solidity +function verifyMultiProof( + bytes32[] memory proof, + bytes32 root, + bytes32[] memory leaves, + bool[] memory flags +) internal pure returns (bool isValid) +``` + +Returns whether all `leaves` exist in the Merkle tree with `root`, +given `proof` and `flags`. +Note: +- Breaking the invariant `flags.length == (leaves.length - 1) + proof.length` + will always return false. +- The sum of the lengths of `proof` and `leaves` must never overflow. +- Any non-zero word in the `flags` array is treated as true. +- The memory offset of `proof` must be non-zero + (i.e. `proof` is not pointing to the scratch space). + +### verifyMultiProofCalldata(bytes32[],bytes32,bytes32[],bool[]) + +```solidity +function verifyMultiProofCalldata( + bytes32[] calldata proof, + bytes32 root, + bytes32[] calldata leaves, + bool[] calldata flags +) internal pure returns (bool isValid) +``` + +Returns whether all `leaves` exist in the Merkle tree with `root`, +given `proof` and `flags`. +Note: +- Breaking the invariant `flags.length == (leaves.length - 1) + proof.length` + will always return false. +- Any non-zero word in the `flags` array is treated as true. +- The calldata offset of `proof` must be non-zero + (i.e. `proof` is from a regular Solidity function with a 4-byte selector). + +## Empty Calldata Helpers + +### emptyProof() + +```solidity +function emptyProof() internal pure returns (bytes32[] calldata proof) +``` + +Returns an empty calldata bytes32 array. + +### emptyLeaves() + +```solidity +function emptyLeaves() internal pure returns (bytes32[] calldata leaves) +``` + +Returns an empty calldata bytes32 array. + +### emptyFlags() + +```solidity +function emptyFlags() internal pure returns (bool[] calldata flags) +``` + +Returns an empty calldata bool array. \ No newline at end of file diff --git a/docs/utils/metadatareaderlib.md b/docs/utils/metadatareaderlib.md new file mode 100644 index 000000000..d5e564a01 --- /dev/null +++ b/docs/utils/metadatareaderlib.md @@ -0,0 +1,181 @@ +# MetadataReaderLib + +Library for reading contract metadata robustly. + + + + + + + + +## Constants + +### GAS_STIPEND_NO_GRIEF + +```solidity +uint256 internal constant GAS_STIPEND_NO_GRIEF = 100000 +``` + +Default gas stipend for contract reads. High enough for most practical use cases +(able to SLOAD about 1000 bytes of data), but low enough to prevent griefing. + +### STRING_LIMIT_DEFAULT + +```solidity +uint256 internal constant STRING_LIMIT_DEFAULT = 1000 +``` + +Default string byte length limit. + +## Metadata Reading Operations + +Best-effort string reading operations. +Should NOT revert as long as sufficient gas is provided. +Performs the following in order: +1. Returns the empty string for the following cases: +- Reverts. +- No returndata (e.g. function returns nothing, EOA). +- Returns empty string. +2. Attempts to `abi.decode` the returndata into a string. +3. With any remaining gas, scans the returndata from start to end for the + null byte '\0', to interpret the returndata as a null-terminated string. + +### readName(address) + +```solidity +function readName(address target) internal view returns (string memory) +``` + +Equivalent to `readString(abi.encodeWithSignature("name()"))`. + +### readName(address,uint256) + +```solidity +function readName(address target, uint256 limit) + internal + view + returns (string memory) +``` + +Equivalent to `readString(abi.encodeWithSignature("name()"), limit)`. + +### readName(address,uint256,uint256) + +```solidity +function readName(address target, uint256 limit, uint256 gasStipend) + internal + view + returns (string memory) +``` + +Equivalent to `readString(abi.encodeWithSignature("name()"), limit, gasStipend)`. + +### readSymbol(address) + +```solidity +function readSymbol(address target) internal view returns (string memory) +``` + +Equivalent to `readString(abi.encodeWithSignature("symbol()"))`. + +### readSymbol(address,uint256) + +```solidity +function readSymbol(address target, uint256 limit) + internal + view + returns (string memory) +``` + +Equivalent to `readString(abi.encodeWithSignature("symbol()"), limit)`. + +### readSymbol(address,uint256,uint256) + +```solidity +function readSymbol(address target, uint256 limit, uint256 gasStipend) + internal + view + returns (string memory) +``` + +Equivalent to `readString(abi.encodeWithSignature("symbol()"), limit, gasStipend)`. + +### readString(address,bytes) + +```solidity +function readString(address target, bytes memory data) + internal + view + returns (string memory) +``` + +Performs a best-effort string query on `target` with `data` as the calldata. +The string will be truncated to `STRING_LIMIT_DEFAULT` (1000) bytes. + +### readString(address,bytes,uint256) + +```solidity +function readString(address target, bytes memory data, uint256 limit) + internal + view + returns (string memory) +``` + +Performs a best-effort string query on `target` with `data` as the calldata. +The string will be truncated to `limit` bytes. + +### readString(address,bytes,uint256,uint256) + +```solidity +function readString( + address target, + bytes memory data, + uint256 limit, + uint256 gasStipend +) internal view returns (string memory) +``` + +Performs a best-effort string query on `target` with `data` as the calldata. +The string will be truncated to `limit` bytes. + +### readDecimals(address) + +```solidity +function readDecimals(address target) internal view returns (uint8) +``` + +Equivalent to `uint8(readUint(abi.encodeWithSignature("decimals()")))`. + +### readDecimals(address,uint256) + +```solidity +function readDecimals(address target, uint256 gasStipend) + internal + view + returns (uint8) +``` + +Equivalent to `uint8(readUint(abi.encodeWithSignature("decimals()"), gasStipend))`. + +### readUint(address,bytes) + +```solidity +function readUint(address target, bytes memory data) + internal + view + returns (uint256) +``` + +Performs a best-effort uint query on `target` with `data` as the calldata. + +### readUint(address,bytes,uint256) + +```solidity +function readUint(address target, bytes memory data, uint256 gasStipend) + internal + view + returns (uint256) +``` + +Performs a best-effort uint query on `target` with `data` as the calldata. \ No newline at end of file diff --git a/docs/utils/minheaplib.md b/docs/utils/minheaplib.md new file mode 100644 index 000000000..0c011d423 --- /dev/null +++ b/docs/utils/minheaplib.md @@ -0,0 +1,249 @@ +# MinHeapLib + +Library for managing a min-heap in storage or memory. + + + + + + + + +## Custom Errors + +### HeapIsEmpty() + +```solidity +error HeapIsEmpty() +``` + +The heap is empty. + +## Structs + +### Heap + +```solidity +struct Heap { + uint256[] data; +} +``` + +A heap in storage. + +### MemHeap + +```solidity +struct MemHeap { + uint256[] data; +} +``` + +A heap in memory. + +## Operations + +Tips: +- To use as a max-heap, bitwise negate the input and output values (e.g. `heap.push(~x)`). +- To use on tuples, pack the tuple values into a single integer. +- To use on signed integers, convert the signed integers into + their ordered unsigned counterparts via `uint256(x) + (1 << 255)`. + +### root(Heap) + +```solidity +function root(Heap storage heap) internal view returns (uint256 result) +``` + +Returns the minimum value of the heap. +Reverts if the heap is empty. + +### root(MemHeap) + +```solidity +function root(MemHeap memory heap) internal pure returns (uint256 result) +``` + +Returns the minimum value of the heap. +Reverts if the heap is empty. + +### reserve(MemHeap,uint256) + +```solidity +function reserve(MemHeap memory heap, uint256 minimum) internal pure +``` + +Reserves at least `minimum` slots of memory for the heap. +Helps avoid reallocation if you already know the max size of the heap. + +### smallest(Heap,uint256) + +```solidity +function smallest(Heap storage heap, uint256 k) + internal + view + returns (uint256[] memory a) +``` + +Returns an array of the `k` smallest items in the heap, +sorted in ascending order, without modifying the heap. +If the heap has less than `k` items, all items in the heap will be returned. + +### smallest(MemHeap,uint256) + +```solidity +function smallest(MemHeap memory heap, uint256 k) + internal + pure + returns (uint256[] memory a) +``` + +Returns an array of the `k` smallest items in the heap, +sorted in ascending order, without modifying the heap. +If the heap has less than `k` items, all items in the heap will be returned. + +### length(Heap) + +```solidity +function length(Heap storage heap) internal view returns (uint256) +``` + +Returns the number of items in the heap. + +### length(MemHeap) + +```solidity +function length(MemHeap memory heap) internal pure returns (uint256) +``` + +Returns the number of items in the heap. + +### push(Heap,uint256) + +```solidity +function push(Heap storage heap, uint256 value) internal +``` + +Pushes the `value` onto the min-heap. + +### push(MemHeap,uint256) + +```solidity +function push(MemHeap memory heap, uint256 value) internal pure +``` + +Pushes the `value` onto the min-heap. + +### pop(Heap) + +```solidity +function pop(Heap storage heap) internal returns (uint256 popped) +``` + +Pops the minimum value from the min-heap. +Reverts if the heap is empty. + +### pop(MemHeap) + +```solidity +function pop(MemHeap memory heap) internal pure returns (uint256 popped) +``` + +Pops the minimum value from the min-heap. +Reverts if the heap is empty. + +### pushPop(Heap,uint256) + +```solidity +function pushPop(Heap storage heap, uint256 value) + internal + returns (uint256 popped) +``` + +Pushes the `value` onto the min-heap, and pops the minimum value. + +### pushPop(MemHeap,uint256) + +```solidity +function pushPop(MemHeap memory heap, uint256 value) + internal + pure + returns (uint256 popped) +``` + +Pushes the `value` onto the min-heap, and pops the minimum value. + +### replace(Heap,uint256) + +```solidity +function replace(Heap storage heap, uint256 value) + internal + returns (uint256 popped) +``` + +Pops the minimum value, and pushes the new `value` onto the min-heap. +Reverts if the heap is empty. + +### replace(MemHeap,uint256) + +```solidity +function replace(MemHeap memory heap, uint256 value) + internal + pure + returns (uint256 popped) +``` + +Pops the minimum value, and pushes the new `value` onto the min-heap. +Reverts if the heap is empty. + +### enqueue(Heap,uint256,uint256) + +```solidity +function enqueue(Heap storage heap, uint256 value, uint256 maxLength) + internal + returns (bool success, bool hasPopped, uint256 popped) +``` + +Pushes the `value` onto the min-heap, and pops the minimum value +if the length of the heap exceeds `maxLength`. +Reverts if `maxLength` is zero. +- If the queue is not full: + (`success` = true, `hasPopped` = false, `popped` = 0) +- If the queue is full, and `value` is not greater than the minimum value: + (`success` = false, `hasPopped` = false, `popped` = 0) +- If the queue is full, and `value` is greater than the minimum value: + (`success` = true, `hasPopped` = true, `popped` = ) +Useful for implementing a bounded priority queue. + +### enqueue(MemHeap,uint256,uint256) + +```solidity +function enqueue(MemHeap memory heap, uint256 value, uint256 maxLength) + internal + pure + returns (bool success, bool hasPopped, uint256 popped) +``` + +Pushes the `value` onto the min-heap, and pops the minimum value +if the length of the heap exceeds `maxLength`. +Reverts if `maxLength` is zero. +- If the queue is not full: + (`success` = true, `hasPopped` = false, `popped` = 0) +- If the queue is full, and `value` is not greater than the minimum value: + (`success` = false, `hasPopped` = false, `popped` = 0) +- If the queue is full, and `value` is greater than the minimum value: + (`success` = true, `hasPopped` = true, `popped` = ) +Useful for implementing a bounded priority queue. + +### bumpFreeMemoryPointer() + +```solidity +function bumpFreeMemoryPointer() internal pure +``` + +Increments the free memory pointer by a word and fills the word with 0. +This is if you want to take extra precaution that the memory word slot before +the `data` array in `MemHeap` doesn't contain a non-zero multiple of prime +to masquerade as a prime-checksummed capacity. +If you are not directly assigning some array to `data`, +you don't have to worry about it. \ No newline at end of file diff --git a/docs/utils/multicallable.md b/docs/utils/multicallable.md new file mode 100644 index 000000000..342c2e895 --- /dev/null +++ b/docs/utils/multicallable.md @@ -0,0 +1,75 @@ +# Multicallable + +Contract that enables a single call to call multiple methods on itself. + + +WARNING: +This implementation is NOT to be used with ERC2771 out-of-the-box. +https://blog.openzeppelin.com/arbitrary-address-spoofing-vulnerability-erc2771context-multicall-public-disclosure +This also applies to potentially other ERCs / patterns appending to the back of calldata. + +We do NOT have a check for ERC2771, as we do not inherit from OpenZeppelin's context. +Moreover, it is infeasible and inefficient for us to add checks and mitigations +for all possible ERC / patterns appending to the back of calldata. + +We would highly recommend using an alternative pattern such as +https://github.com/Vectorized/multicaller +which is more flexible, futureproof, and safer by default. + + + + + +## Functions + +### multicall(bytes[]) + +```solidity +function multicall(bytes[] calldata data) + public + payable + virtual + returns (bytes[] memory) +``` + +Apply `delegatecall` with the current contract to each calldata in `data`, +and store the `abi.encode` formatted results of each `delegatecall` into `results`. +If any of the `delegatecall`s reverts, the entire context is reverted, +and the error is bubbled up. +By default, this function directly returns the results and terminates the call context. +If you need to add before and after actions to the multicall, please override this function. + +### _multicall(bytes[]) + +```solidity +function _multicall(bytes[] calldata data) + internal + virtual + returns (bytes32 results) +``` + +The inner logic of `multicall`. +This function is included so that you can override `multicall` +to add before and after actions, and use the `_multicallDirectReturn` function. + +### _multicallResultsToBytesArray(bytes32) + +```solidity +function _multicallResultsToBytesArray(bytes32 results) + internal + pure + virtual + returns (bytes[] memory decoded) +``` + +Decodes the `results` into an array of bytes. +This can be useful if you need to access the results or re-encode it. + +### _multicallDirectReturn(bytes32) + +```solidity +function _multicallDirectReturn(bytes32 results) internal pure virtual +``` + +Directly returns the `results` and terminates the current call context. +`results` must be from `_multicall`, else behavior is undefined. \ No newline at end of file diff --git a/docs/utils/p256.md b/docs/utils/p256.md new file mode 100644 index 000000000..9b76832c1 --- /dev/null +++ b/docs/utils/p256.md @@ -0,0 +1,114 @@ +# P256 + +Gas optimized P256 wrapper. + + + + + + + + +## Custom Errors + +### P256VerificationFailed() + +```solidity +error P256VerificationFailed() +``` + +Unable to verify the P256 signature, due to missing +RIP-7212 P256 verifier precompile and missing Solidity P256 verifier. + +## Constants + +### VERIFIER + +```solidity +address internal constant VERIFIER = + 0x000000000000cB83347bEB24C695BBb85dBe99b7 +``` + +Address of the Solidity P256 verifier. +Please make sure the contract is deployed onto the chain you are working on. +See: https://gist.github.com/Vectorized/599b0d8a94d21bc74700eb1354e2f55c +Unlike RIP-7212, this verifier returns `uint256(0)` on failure, to +facilitate easier existence check. This verifier will also never revert. + +### RIP_PRECOMPILE + +```solidity +address internal constant RIP_PRECOMPILE = + 0x0000000000000000000000000000000000000100 +``` + +Address of the RIP-7212 P256 verifier precompile. +Currently, we don't support EIP-7212's precompile at 0x0b as it has not been finalized. +See: https://github.com/ethereum/RIPs/blob/master/RIPS/rip-7212.md + +### N + +```solidity +uint256 internal constant N = + 0xFFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551 +``` + +The order of the secp256r1 elliptic curve. + +## P256 Verification Operations + +### verifySignatureAllowMalleability(bytes32,bytes32,bytes32,bytes32,bytes32) + +```solidity +function verifySignatureAllowMalleability( + bytes32 hash, + bytes32 r, + bytes32 s, + bytes32 x, + bytes32 y +) internal view returns (bool isValid) +``` + +Returns if the signature (`r`, `s`) is valid for `hash` and public key (`x`, `y`). +Does NOT include the malleability check. + +### verifySignature(bytes32,bytes32,bytes32,bytes32,bytes32) + +```solidity +function verifySignature( + bytes32 hash, + bytes32 r, + bytes32 s, + bytes32 x, + bytes32 y +) internal view returns (bool isValid) +``` + +Returns if the signature (`r`, `s`) is valid for `hash` and public key (`x`, `y`). +Includes the malleability check. + +## Other Operations + +### tryDecodePoint(bytes) + +```solidity +function tryDecodePoint(bytes memory encoded) + internal + pure + returns (bytes32 x, bytes32 y) +``` + +Helper function for `abi.decode(encoded, (bytes32, bytes32))`. +If `encoded.length < 64`, `(x, y)` will be `(0, 0)`, which is an invalid point. + +### tryDecodePointCalldata(bytes) + +```solidity +function tryDecodePointCalldata(bytes calldata encoded) + internal + pure + returns (bytes32 x, bytes32 y) +``` + +Helper function for `abi.decode(encoded, (bytes32, bytes32))`. +If `encoded.length < 64`, `(x, y)` will be `(0, 0)`, which is an invalid point. \ No newline at end of file diff --git a/docs/utils/redblacktreelib.md b/docs/utils/redblacktreelib.md new file mode 100644 index 000000000..831ea9768 --- /dev/null +++ b/docs/utils/redblacktreelib.md @@ -0,0 +1,266 @@ +# RedBlackTreeLib + +Library for managing a red-black-tree in storage. + + +This implementation does not support the zero (i.e. empty) value. +This implementation supports up to 2147483647 values. + + + + + +## Custom Errors + +### ValueIsEmpty() + +```solidity +error ValueIsEmpty() +``` + +The value cannot be zero. + +### ValueAlreadyExists() + +```solidity +error ValueAlreadyExists() +``` + +Cannot insert a value that already exists. + +### ValueDoesNotExist() + +```solidity +error ValueDoesNotExist() +``` + +Cannot remove a value that does not exist. + +### PointerOutOfBounds() + +```solidity +error PointerOutOfBounds() +``` + +The pointer is out of bounds. + +### TreeIsFull() + +```solidity +error TreeIsFull() +``` + +The tree is full. + +## Structs + +### Tree + +```solidity +struct Tree { + uint256 _spacer; +} +``` + +A red-black-tree in storage. + +## Operations + +### size(Tree) + +```solidity +function size(Tree storage tree) internal view returns (uint256 result) +``` + +Returns the number of unique values in the tree. + +### values(Tree) + +```solidity +function values(Tree storage tree) + internal + view + returns (uint256[] memory result) +``` + +Returns an array of all the values in the tree in ascending sorted order. +WARNING! This function can exhaust the block gas limit if the tree is big. +It is intended for usage in off-chain view functions. + +### find(Tree,uint256) + +```solidity +function find(Tree storage tree, uint256 x) + internal + view + returns (bytes32 result) +``` + +Returns a pointer to the value `x`. +If the value `x` is not in the tree, the returned pointer will be empty. + +### nearest(Tree,uint256) + +```solidity +function nearest(Tree storage tree, uint256 x) + internal + view + returns (bytes32 result) +``` + +Returns a pointer to the nearest value to `x`. +In a tie-breaker, the returned pointer will point to the smaller value. +If the tree is empty, the returned pointer will be empty. + +### nearestBefore(Tree,uint256) + +```solidity +function nearestBefore(Tree storage tree, uint256 x) + internal + view + returns (bytes32 result) +``` + +Returns a pointer to the nearest value lesser or equal to `x`. +If there is no value lesser or equal to `x`, the returned pointer will be empty. + +### nearestAfter(Tree,uint256) + +```solidity +function nearestAfter(Tree storage tree, uint256 x) + internal + view + returns (bytes32 result) +``` + +Returns a pointer to the nearest value greater or equal to `x`. +If there is no value greater or equal to `x`, the returned pointer will be empty. + +### exists(Tree,uint256) + +```solidity +function exists(Tree storage tree, uint256 x) + internal + view + returns (bool result) +``` + +Returns whether the value `x` exists. + +### insert(Tree,uint256) + +```solidity +function insert(Tree storage tree, uint256 x) internal +``` + +Inserts the value `x` into the tree. +Reverts if the value `x` already exists. + +### tryInsert(Tree,uint256) + +```solidity +function tryInsert(Tree storage tree, uint256 x) + internal + returns (uint256 err) +``` + +Inserts the value `x` into the tree. +Returns a non-zero error code upon failure instead of reverting +(except for reverting if `x` is an empty value). + +### remove(Tree,uint256) + +```solidity +function remove(Tree storage tree, uint256 x) internal +``` + +Removes the value `x` from the tree. +Reverts if the value does not exist. + +### tryRemove(Tree,uint256) + +```solidity +function tryRemove(Tree storage tree, uint256 x) + internal + returns (uint256 err) +``` + +Removes the value `x` from the tree. +Returns a non-zero error code upon failure instead of reverting +(except for reverting if `x` is an empty value). + +### remove(bytes32) + +```solidity +function remove(bytes32 ptr) internal +``` + +Removes the value at pointer `ptr` from the tree. +Reverts if `ptr` is empty (i.e. value does not exist), +or if `ptr` is out of bounds. +After removal, `ptr` may point to another existing value. +For safety, do not reuse `ptr` after calling remove on it. + +### tryRemove(bytes32) + +```solidity +function tryRemove(bytes32 ptr) internal returns (uint256 err) +``` + +Removes the value at pointer `ptr` from the tree. +Returns a non-zero error code upon failure instead of reverting. + +### value(bytes32) + +```solidity +function value(bytes32 ptr) internal view returns (uint256 result) +``` + +Returns the value at pointer `ptr`. +If `ptr` is empty, the result will be zero. + +### first(Tree) + +```solidity +function first(Tree storage tree) internal view returns (bytes32 result) +``` + +Returns a pointer to the smallest value in the tree. +If the tree is empty, the returned pointer will be empty. + +### last(Tree) + +```solidity +function last(Tree storage tree) internal view returns (bytes32 result) +``` + +Returns a pointer to the largest value in the tree. +If the tree is empty, the returned pointer will be empty. + +### next(bytes32) + +```solidity +function next(bytes32 ptr) internal view returns (bytes32 result) +``` + +Returns the pointer to the next largest value. +If there is no next value, or if `ptr` is empty, +the returned pointer will be empty. + +### prev(bytes32) + +```solidity +function prev(bytes32 ptr) internal view returns (bytes32 result) +``` + +Returns the pointer to the next smallest value. +If there is no previous value, or if `ptr` is empty, +the returned pointer will be empty. + +### isEmpty(bytes32) + +```solidity +function isEmpty(bytes32 ptr) internal pure returns (bool result) +``` + +Returns whether the pointer is empty. \ No newline at end of file diff --git a/docs/utils/reentrancyguard.md b/docs/utils/reentrancyguard.md new file mode 100644 index 000000000..1f9b8276b --- /dev/null +++ b/docs/utils/reentrancyguard.md @@ -0,0 +1,38 @@ +# ReentrancyGuard + +Reentrancy guard mixin. + + + + + + + + +## Custom Errors + +### Reentrancy() + +```solidity +error Reentrancy() +``` + +Unauthorized reentrant call. + +## Reentrancy Guard + +### nonReentrant() + +```solidity +modifier nonReentrant() virtual +``` + +Guards a function from reentrancy. + +### nonReadReentrant() + +```solidity +modifier nonReadReentrant() virtual +``` + +Guards a view function from read-only reentrancy. \ No newline at end of file diff --git a/docs/utils/reentrancyguardtransient.md b/docs/utils/reentrancyguardtransient.md new file mode 100644 index 000000000..c42f85669 --- /dev/null +++ b/docs/utils/reentrancyguardtransient.md @@ -0,0 +1,54 @@ +# ReentrancyGuardTransient + +Reentrancy guard mixin (transient storage variant). + + +Note: + +This implementation utilizes the `TSTORE` and `TLOAD` opcodes. +Please ensure that the chain you are deploying on supports them. + + + + + +## Custom Errors + +### Reentrancy() + +```solidity +error Reentrancy() +``` + +Unauthorized reentrant call. + +## Reentrancy Guard + +### nonReentrant() + +```solidity +modifier nonReentrant() virtual +``` + +Guards a function from reentrancy. + +### nonReadReentrant() + +```solidity +modifier nonReadReentrant() virtual +``` + +Guards a view function from read-only reentrancy. + +### _useTransientReentrancyGuardOnlyOnMainnet() + +```solidity +function _useTransientReentrancyGuardOnlyOnMainnet() + internal + view + virtual + returns (bool) +``` + +For widespread compatibility with L2s. +Only Ethereum mainnet is expensive anyways. \ No newline at end of file diff --git a/docs/utils/safecastlib.md b/docs/utils/safecastlib.md new file mode 100644 index 000000000..fcc670d1b --- /dev/null +++ b/docs/utils/safecastlib.md @@ -0,0 +1,786 @@ +# SafeCastLib + +Safe integer casting library that reverts on overflow. + + +Optimized for runtime gas for very high number of optimizer runs (i.e. >= 1000000). + + + + + +## Custom Errors + +### Overflow() + +```solidity +error Overflow() +``` + +Unable to cast to the target type due to overflow. + +## Unsigned Integer Safe Casting Operations + +### toUint8(uint256) + +```solidity +function toUint8(uint256 x) internal pure returns (uint8) +``` + +Casts `x` to a uint8. Reverts on overflow. + +### toUint16(uint256) + +```solidity +function toUint16(uint256 x) internal pure returns (uint16) +``` + +Casts `x` to a uint16. Reverts on overflow. + +### toUint24(uint256) + +```solidity +function toUint24(uint256 x) internal pure returns (uint24) +``` + +Casts `x` to a uint24. Reverts on overflow. + +### toUint32(uint256) + +```solidity +function toUint32(uint256 x) internal pure returns (uint32) +``` + +Casts `x` to a uint32. Reverts on overflow. + +### toUint40(uint256) + +```solidity +function toUint40(uint256 x) internal pure returns (uint40) +``` + +Casts `x` to a uint40. Reverts on overflow. + +### toUint48(uint256) + +```solidity +function toUint48(uint256 x) internal pure returns (uint48) +``` + +Casts `x` to a uint48. Reverts on overflow. + +### toUint56(uint256) + +```solidity +function toUint56(uint256 x) internal pure returns (uint56) +``` + +Casts `x` to a uint56. Reverts on overflow. + +### toUint64(uint256) + +```solidity +function toUint64(uint256 x) internal pure returns (uint64) +``` + +Casts `x` to a uint64. Reverts on overflow. + +### toUint72(uint256) + +```solidity +function toUint72(uint256 x) internal pure returns (uint72) +``` + +Casts `x` to a uint72. Reverts on overflow. + +### toUint80(uint256) + +```solidity +function toUint80(uint256 x) internal pure returns (uint80) +``` + +Casts `x` to a uint80. Reverts on overflow. + +### toUint88(uint256) + +```solidity +function toUint88(uint256 x) internal pure returns (uint88) +``` + +Casts `x` to a uint88. Reverts on overflow. + +### toUint96(uint256) + +```solidity +function toUint96(uint256 x) internal pure returns (uint96) +``` + +Casts `x` to a uint96. Reverts on overflow. + +### toUint104(uint256) + +```solidity +function toUint104(uint256 x) internal pure returns (uint104) +``` + +Casts `x` to a uint104. Reverts on overflow. + +### toUint112(uint256) + +```solidity +function toUint112(uint256 x) internal pure returns (uint112) +``` + +Casts `x` to a uint112. Reverts on overflow. + +### toUint120(uint256) + +```solidity +function toUint120(uint256 x) internal pure returns (uint120) +``` + +Casts `x` to a uint120. Reverts on overflow. + +### toUint128(uint256) + +```solidity +function toUint128(uint256 x) internal pure returns (uint128) +``` + +Casts `x` to a uint128. Reverts on overflow. + +### toUint136(uint256) + +```solidity +function toUint136(uint256 x) internal pure returns (uint136) +``` + +Casts `x` to a uint136. Reverts on overflow. + +### toUint144(uint256) + +```solidity +function toUint144(uint256 x) internal pure returns (uint144) +``` + +Casts `x` to a uint144. Reverts on overflow. + +### toUint152(uint256) + +```solidity +function toUint152(uint256 x) internal pure returns (uint152) +``` + +Casts `x` to a uint152. Reverts on overflow. + +### toUint160(uint256) + +```solidity +function toUint160(uint256 x) internal pure returns (uint160) +``` + +Casts `x` to a uint160. Reverts on overflow. + +### toUint168(uint256) + +```solidity +function toUint168(uint256 x) internal pure returns (uint168) +``` + +Casts `x` to a uint168. Reverts on overflow. + +### toUint176(uint256) + +```solidity +function toUint176(uint256 x) internal pure returns (uint176) +``` + +Casts `x` to a uint176. Reverts on overflow. + +### toUint184(uint256) + +```solidity +function toUint184(uint256 x) internal pure returns (uint184) +``` + +Casts `x` to a uint184. Reverts on overflow. + +### toUint192(uint256) + +```solidity +function toUint192(uint256 x) internal pure returns (uint192) +``` + +Casts `x` to a uint192. Reverts on overflow. + +### toUint200(uint256) + +```solidity +function toUint200(uint256 x) internal pure returns (uint200) +``` + +Casts `x` to a uint200. Reverts on overflow. + +### toUint208(uint256) + +```solidity +function toUint208(uint256 x) internal pure returns (uint208) +``` + +Casts `x` to a uint208. Reverts on overflow. + +### toUint216(uint256) + +```solidity +function toUint216(uint256 x) internal pure returns (uint216) +``` + +Casts `x` to a uint216. Reverts on overflow. + +### toUint224(uint256) + +```solidity +function toUint224(uint256 x) internal pure returns (uint224) +``` + +Casts `x` to a uint224. Reverts on overflow. + +### toUint232(uint256) + +```solidity +function toUint232(uint256 x) internal pure returns (uint232) +``` + +Casts `x` to a uint232. Reverts on overflow. + +### toUint240(uint256) + +```solidity +function toUint240(uint256 x) internal pure returns (uint240) +``` + +Casts `x` to a uint240. Reverts on overflow. + +### toUint248(uint256) + +```solidity +function toUint248(uint256 x) internal pure returns (uint248) +``` + +Casts `x` to a uint248. Reverts on overflow. + +## Signed Integer Safe Casting Operations + +### toInt8(int256) + +```solidity +function toInt8(int256 x) internal pure returns (int8) +``` + +Casts `x` to a int8. Reverts on overflow. + +### toInt16(int256) + +```solidity +function toInt16(int256 x) internal pure returns (int16) +``` + +Casts `x` to a int16. Reverts on overflow. + +### toInt24(int256) + +```solidity +function toInt24(int256 x) internal pure returns (int24) +``` + +Casts `x` to a int24. Reverts on overflow. + +### toInt32(int256) + +```solidity +function toInt32(int256 x) internal pure returns (int32) +``` + +Casts `x` to a int32. Reverts on overflow. + +### toInt40(int256) + +```solidity +function toInt40(int256 x) internal pure returns (int40) +``` + +Casts `x` to a int40. Reverts on overflow. + +### toInt48(int256) + +```solidity +function toInt48(int256 x) internal pure returns (int48) +``` + +Casts `x` to a int48. Reverts on overflow. + +### toInt56(int256) + +```solidity +function toInt56(int256 x) internal pure returns (int56) +``` + +Casts `x` to a int56. Reverts on overflow. + +### toInt64(int256) + +```solidity +function toInt64(int256 x) internal pure returns (int64) +``` + +Casts `x` to a int64. Reverts on overflow. + +### toInt72(int256) + +```solidity +function toInt72(int256 x) internal pure returns (int72) +``` + +Casts `x` to a int72. Reverts on overflow. + +### toInt80(int256) + +```solidity +function toInt80(int256 x) internal pure returns (int80) +``` + +Casts `x` to a int80. Reverts on overflow. + +### toInt88(int256) + +```solidity +function toInt88(int256 x) internal pure returns (int88) +``` + +Casts `x` to a int88. Reverts on overflow. + +### toInt96(int256) + +```solidity +function toInt96(int256 x) internal pure returns (int96) +``` + +Casts `x` to a int96. Reverts on overflow. + +### toInt104(int256) + +```solidity +function toInt104(int256 x) internal pure returns (int104) +``` + +Casts `x` to a int104. Reverts on overflow. + +### toInt112(int256) + +```solidity +function toInt112(int256 x) internal pure returns (int112) +``` + +Casts `x` to a int112. Reverts on overflow. + +### toInt120(int256) + +```solidity +function toInt120(int256 x) internal pure returns (int120) +``` + +Casts `x` to a int120. Reverts on overflow. + +### toInt128(int256) + +```solidity +function toInt128(int256 x) internal pure returns (int128) +``` + +Casts `x` to a int128. Reverts on overflow. + +### toInt136(int256) + +```solidity +function toInt136(int256 x) internal pure returns (int136) +``` + +Casts `x` to a int136. Reverts on overflow. + +### toInt144(int256) + +```solidity +function toInt144(int256 x) internal pure returns (int144) +``` + +Casts `x` to a int144. Reverts on overflow. + +### toInt152(int256) + +```solidity +function toInt152(int256 x) internal pure returns (int152) +``` + +Casts `x` to a int152. Reverts on overflow. + +### toInt160(int256) + +```solidity +function toInt160(int256 x) internal pure returns (int160) +``` + +Casts `x` to a int160. Reverts on overflow. + +### toInt168(int256) + +```solidity +function toInt168(int256 x) internal pure returns (int168) +``` + +Casts `x` to a int168. Reverts on overflow. + +### toInt176(int256) + +```solidity +function toInt176(int256 x) internal pure returns (int176) +``` + +Casts `x` to a int176. Reverts on overflow. + +### toInt184(int256) + +```solidity +function toInt184(int256 x) internal pure returns (int184) +``` + +Casts `x` to a int184. Reverts on overflow. + +### toInt192(int256) + +```solidity +function toInt192(int256 x) internal pure returns (int192) +``` + +Casts `x` to a int192. Reverts on overflow. + +### toInt200(int256) + +```solidity +function toInt200(int256 x) internal pure returns (int200) +``` + +Casts `x` to a int200. Reverts on overflow. + +### toInt208(int256) + +```solidity +function toInt208(int256 x) internal pure returns (int208) +``` + +Casts `x` to a int208. Reverts on overflow. + +### toInt216(int256) + +```solidity +function toInt216(int256 x) internal pure returns (int216) +``` + +Casts `x` to a int216. Reverts on overflow. + +### toInt224(int256) + +```solidity +function toInt224(int256 x) internal pure returns (int224) +``` + +Casts `x` to a int224. Reverts on overflow. + +### toInt232(int256) + +```solidity +function toInt232(int256 x) internal pure returns (int232) +``` + +Casts `x` to a int232. Reverts on overflow. + +### toInt240(int256) + +```solidity +function toInt240(int256 x) internal pure returns (int240) +``` + +Casts `x` to a int240. Reverts on overflow. + +### toInt248(int256) + +```solidity +function toInt248(int256 x) internal pure returns (int248) +``` + +Casts `x` to a int248. Reverts on overflow. + +## Other Safe Casting Operations + +### toInt8(uint256) + +```solidity +function toInt8(uint256 x) internal pure returns (int8) +``` + +Casts `x` to a int8. Reverts on overflow. + +### toInt16(uint256) + +```solidity +function toInt16(uint256 x) internal pure returns (int16) +``` + +Casts `x` to a int16. Reverts on overflow. + +### toInt24(uint256) + +```solidity +function toInt24(uint256 x) internal pure returns (int24) +``` + +Casts `x` to a int24. Reverts on overflow. + +### toInt32(uint256) + +```solidity +function toInt32(uint256 x) internal pure returns (int32) +``` + +Casts `x` to a int32. Reverts on overflow. + +### toInt40(uint256) + +```solidity +function toInt40(uint256 x) internal pure returns (int40) +``` + +Casts `x` to a int40. Reverts on overflow. + +### toInt48(uint256) + +```solidity +function toInt48(uint256 x) internal pure returns (int48) +``` + +Casts `x` to a int48. Reverts on overflow. + +### toInt56(uint256) + +```solidity +function toInt56(uint256 x) internal pure returns (int56) +``` + +Casts `x` to a int56. Reverts on overflow. + +### toInt64(uint256) + +```solidity +function toInt64(uint256 x) internal pure returns (int64) +``` + +Casts `x` to a int64. Reverts on overflow. + +### toInt72(uint256) + +```solidity +function toInt72(uint256 x) internal pure returns (int72) +``` + +Casts `x` to a int72. Reverts on overflow. + +### toInt80(uint256) + +```solidity +function toInt80(uint256 x) internal pure returns (int80) +``` + +Casts `x` to a int80. Reverts on overflow. + +### toInt88(uint256) + +```solidity +function toInt88(uint256 x) internal pure returns (int88) +``` + +Casts `x` to a int88. Reverts on overflow. + +### toInt96(uint256) + +```solidity +function toInt96(uint256 x) internal pure returns (int96) +``` + +Casts `x` to a int96. Reverts on overflow. + +### toInt104(uint256) + +```solidity +function toInt104(uint256 x) internal pure returns (int104) +``` + +Casts `x` to a int104. Reverts on overflow. + +### toInt112(uint256) + +```solidity +function toInt112(uint256 x) internal pure returns (int112) +``` + +Casts `x` to a int112. Reverts on overflow. + +### toInt120(uint256) + +```solidity +function toInt120(uint256 x) internal pure returns (int120) +``` + +Casts `x` to a int120. Reverts on overflow. + +### toInt128(uint256) + +```solidity +function toInt128(uint256 x) internal pure returns (int128) +``` + +Casts `x` to a int128. Reverts on overflow. + +### toInt136(uint256) + +```solidity +function toInt136(uint256 x) internal pure returns (int136) +``` + +Casts `x` to a int136. Reverts on overflow. + +### toInt144(uint256) + +```solidity +function toInt144(uint256 x) internal pure returns (int144) +``` + +Casts `x` to a int144. Reverts on overflow. + +### toInt152(uint256) + +```solidity +function toInt152(uint256 x) internal pure returns (int152) +``` + +Casts `x` to a int152. Reverts on overflow. + +### toInt160(uint256) + +```solidity +function toInt160(uint256 x) internal pure returns (int160) +``` + +Casts `x` to a int160. Reverts on overflow. + +### toInt168(uint256) + +```solidity +function toInt168(uint256 x) internal pure returns (int168) +``` + +Casts `x` to a int168. Reverts on overflow. + +### toInt176(uint256) + +```solidity +function toInt176(uint256 x) internal pure returns (int176) +``` + +Casts `x` to a int176. Reverts on overflow. + +### toInt184(uint256) + +```solidity +function toInt184(uint256 x) internal pure returns (int184) +``` + +Casts `x` to a int184. Reverts on overflow. + +### toInt192(uint256) + +```solidity +function toInt192(uint256 x) internal pure returns (int192) +``` + +Casts `x` to a int192. Reverts on overflow. + +### toInt200(uint256) + +```solidity +function toInt200(uint256 x) internal pure returns (int200) +``` + +Casts `x` to a int200. Reverts on overflow. + +### toInt208(uint256) + +```solidity +function toInt208(uint256 x) internal pure returns (int208) +``` + +Casts `x` to a int208. Reverts on overflow. + +### toInt216(uint256) + +```solidity +function toInt216(uint256 x) internal pure returns (int216) +``` + +Casts `x` to a int216. Reverts on overflow. + +### toInt224(uint256) + +```solidity +function toInt224(uint256 x) internal pure returns (int224) +``` + +Casts `x` to a int224. Reverts on overflow. + +### toInt232(uint256) + +```solidity +function toInt232(uint256 x) internal pure returns (int232) +``` + +Casts `x` to a int232. Reverts on overflow. + +### toInt240(uint256) + +```solidity +function toInt240(uint256 x) internal pure returns (int240) +``` + +Casts `x` to a int240. Reverts on overflow. + +### toInt248(uint256) + +```solidity +function toInt248(uint256 x) internal pure returns (int248) +``` + +Casts `x` to a int248. Reverts on overflow. + +### toInt256(uint256) + +```solidity +function toInt256(uint256 x) internal pure returns (int256) +``` + +Casts `x` to a int256. Reverts on overflow. + +### toUint256(int256) + +```solidity +function toUint256(int256 x) internal pure returns (uint256) +``` + +Casts `x` to a uint256. Reverts on overflow. \ No newline at end of file diff --git a/docs/utils/safetransferlib.md b/docs/utils/safetransferlib.md new file mode 100644 index 000000000..21dacea31 --- /dev/null +++ b/docs/utils/safetransferlib.md @@ -0,0 +1,382 @@ +# SafeTransferLib + +Safe ETH and ERC20 transfer library that gracefully handles missing return values. + + +Note: + +- For ETH transfers, please use `forceSafeTransferETH` for DoS protection. + + + + + +## Custom Errors + +### ETHTransferFailed() + +```solidity +error ETHTransferFailed() +``` + +The ETH transfer has failed. + +### TransferFromFailed() + +```solidity +error TransferFromFailed() +``` + +The ERC20 `transferFrom` has failed. + +### TransferFailed() + +```solidity +error TransferFailed() +``` + +The ERC20 `transfer` has failed. + +### ApproveFailed() + +```solidity +error ApproveFailed() +``` + +The ERC20 `approve` has failed. + +### TotalSupplyQueryFailed() + +```solidity +error TotalSupplyQueryFailed() +``` + +The ERC20 `totalSupply` query has failed. + +### Permit2Failed() + +```solidity +error Permit2Failed() +``` + +The Permit2 operation has failed. + +### Permit2AmountOverflow() + +```solidity +error Permit2AmountOverflow() +``` + +The Permit2 amount must be less than `2**160 - 1`. + +## Constants + +### GAS_STIPEND_NO_STORAGE_WRITES + +```solidity +uint256 internal constant GAS_STIPEND_NO_STORAGE_WRITES = 2300 +``` + +Suggested gas stipend for contract receiving ETH that disallows any storage writes. + +### GAS_STIPEND_NO_GRIEF + +```solidity +uint256 internal constant GAS_STIPEND_NO_GRIEF = 100000 +``` + +Suggested gas stipend for contract receiving ETH to perform a few +storage reads and writes, but low enough to prevent griefing. + +### DAI_DOMAIN_SEPARATOR + +```solidity +bytes32 internal constant DAI_DOMAIN_SEPARATOR = + 0xdbb8cf42e1ecb028be3f3dbc922e1d878b963f411dc388ced501601c60f7c6f7 +``` + +The unique EIP-712 domain domain separator for the DAI token contract. + +### WETH9 + +```solidity +address internal constant WETH9 = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2 +``` + +The address for the WETH9 contract on Ethereum mainnet. + +### PERMIT2 + +```solidity +address internal constant PERMIT2 = + 0x000000000022D473030F116dDEE9F6B43aC78BA3 +``` + +The canonical Permit2 address. +[Github](https://github.com/Uniswap/permit2) +[Etherscan](https://etherscan.io/address/0x000000000022D473030F116dDEE9F6B43aC78BA3) + +## ETH Operations + +If the ETH transfer MUST succeed with a reasonable gas budget, use the force variants. +The regular variants: +- Forwards all remaining gas to the target. +- Reverts if the target reverts. +- Reverts if the current contract has insufficient balance. +The force variants: +- Forwards with an optional gas stipend + (defaults to `GAS_STIPEND_NO_GRIEF`, which is sufficient for most cases). +- If the target reverts, or if the gas stipend is exhausted, + creates a temporary contract to force send the ETH via `SELFDESTRUCT`. + Future compatible with `SENDALL`: https://eips.ethereum.org/EIPS/eip-4758. +- Reverts if the current contract has insufficient balance. +The try variants: +- Forwards with a mandatory gas stipend. +- Instead of reverting, returns whether the transfer succeeded. + +### safeTransferETH(address,uint256) + +```solidity +function safeTransferETH(address to, uint256 amount) internal +``` + +Sends `amount` (in wei) ETH to `to`. + +### safeTransferAllETH(address) + +```solidity +function safeTransferAllETH(address to) internal +``` + +Sends all the ETH in the current contract to `to`. + +### forceSafeTransferETH(address,uint256,uint256) + +```solidity +function forceSafeTransferETH( + address to, + uint256 amount, + uint256 gasStipend +) internal +``` + +Force sends `amount` (in wei) ETH to `to`, with a `gasStipend`. + +### forceSafeTransferAllETH(address,uint256) + +```solidity +function forceSafeTransferAllETH(address to, uint256 gasStipend) internal +``` + +Force sends all the ETH in the current contract to `to`, with a `gasStipend`. + +### forceSafeTransferETH(address,uint256) + +```solidity +function forceSafeTransferETH(address to, uint256 amount) internal +``` + +Force sends `amount` (in wei) ETH to `to`, with `GAS_STIPEND_NO_GRIEF`. + +### forceSafeTransferAllETH(address) + +```solidity +function forceSafeTransferAllETH(address to) internal +``` + +Force sends all the ETH in the current contract to `to`, with `GAS_STIPEND_NO_GRIEF`. + +### trySafeTransferETH(address,uint256,uint256) + +```solidity +function trySafeTransferETH(address to, uint256 amount, uint256 gasStipend) + internal + returns (bool success) +``` + +Sends `amount` (in wei) ETH to `to`, with a `gasStipend`. + +### trySafeTransferAllETH(address,uint256) + +```solidity +function trySafeTransferAllETH(address to, uint256 gasStipend) + internal + returns (bool success) +``` + +Sends all the ETH in the current contract to `to`, with a `gasStipend`. + +## ERC20 Operations + +### safeTransferFrom(address,address,address,uint256) + +```solidity +function safeTransferFrom( + address token, + address from, + address to, + uint256 amount +) internal +``` + +Sends `amount` of ERC20 `token` from `from` to `to`. +Reverts upon failure. +The `from` account must have at least `amount` approved for +the current contract to manage. + +### trySafeTransferFrom(address,address,address,uint256) + +```solidity +function trySafeTransferFrom( + address token, + address from, + address to, + uint256 amount +) internal returns (bool success) +``` + +Sends `amount` of ERC20 `token` from `from` to `to`. +The `from` account must have at least `amount` approved for the current contract to manage. + +### safeTransferAllFrom(address,address,address) + +```solidity +function safeTransferAllFrom(address token, address from, address to) + internal + returns (uint256 amount) +``` + +Sends all of ERC20 `token` from `from` to `to`. +Reverts upon failure. +The `from` account must have their entire balance approved for the current contract to manage. + +### safeTransfer(address,address,uint256) + +```solidity +function safeTransfer(address token, address to, uint256 amount) internal +``` + +Sends `amount` of ERC20 `token` from the current contract to `to`. +Reverts upon failure. + +### safeTransferAll(address,address) + +```solidity +function safeTransferAll(address token, address to) + internal + returns (uint256 amount) +``` + +Sends all of ERC20 `token` from the current contract to `to`. +Reverts upon failure. + +### safeApprove(address,address,uint256) + +```solidity +function safeApprove(address token, address to, uint256 amount) internal +``` + +Sets `amount` of ERC20 `token` for `to` to manage on behalf of the current contract. +Reverts upon failure. + +### safeApproveWithRetry(address,address,uint256) + +```solidity +function safeApproveWithRetry(address token, address to, uint256 amount) + internal +``` + +Sets `amount` of ERC20 `token` for `to` to manage on behalf of the current contract. +If the initial attempt to approve fails, attempts to reset the approved amount to zero, +then retries the approval again (some tokens, e.g. USDT, requires this). +Reverts upon failure. + +### balanceOf(address,address) + +```solidity +function balanceOf(address token, address account) + internal + view + returns (uint256 amount) +``` + +Returns the amount of ERC20 `token` owned by `account`. +Returns zero if the `token` does not exist. + +### totalSupply(address) + +```solidity +function totalSupply(address token) + internal + view + returns (uint256 result) +``` + +Returns the total supply of the `token`. +Reverts if the token does not exist or does not implement `totalSupply()`. + +### safeTransferFrom2(address,address,address,uint256) + +```solidity +function safeTransferFrom2( + address token, + address from, + address to, + uint256 amount +) internal +``` + +Sends `amount` of ERC20 `token` from `from` to `to`. +If the initial attempt fails, try to use Permit2 to transfer the token. +Reverts upon failure. +The `from` account must have at least `amount` approved for the current contract to manage. + +### permit2TransferFrom(address,address,address,uint256) + +```solidity +function permit2TransferFrom( + address token, + address from, + address to, + uint256 amount +) internal +``` + +Sends `amount` of ERC20 `token` from `from` to `to` via Permit2. +Reverts upon failure. + +### permit2(address,address,address,uint256,uint256,uint8,bytes32,bytes32) + +```solidity +function permit2( + address token, + address owner, + address spender, + uint256 amount, + uint256 deadline, + uint8 v, + bytes32 r, + bytes32 s +) internal +``` + +Permit a user to spend a given amount of +another user's tokens via native EIP-2612 permit if possible, falling +back to Permit2 if native permit fails or is not implemented on the token. + +### simplePermit2(address,address,address,uint256,uint256,uint8,bytes32,bytes32) + +```solidity +function simplePermit2( + address token, + address owner, + address spender, + uint256 amount, + uint256 deadline, + uint8 v, + bytes32 r, + bytes32 s +) internal +``` + +Simple permit on the Permit2 contract. \ No newline at end of file diff --git a/docs/utils/signaturecheckerlib.md b/docs/utils/signaturecheckerlib.md new file mode 100644 index 000000000..025064a39 --- /dev/null +++ b/docs/utils/signaturecheckerlib.md @@ -0,0 +1,231 @@ +# SignatureCheckerLib + +Signature verification helper that supports both ECDSA signatures from EOAs and ERC1271 signatures from smart contract wallets like Argent and Gnosis safe. + + +Note: + +- The signature checking functions use the ecrecover precompile (0x1). +- The `bytes memory signature` variants use the identity precompile (0x4) +to copy memory internally. +- Unlike ECDSA signatures, contract signatures are revocable. +- As of Solady version 0.0.134, all `bytes signature` variants accept both +regular 65-byte `(r, s, v)` and EIP-2098 `(r, vs)` short form signatures. +See: https://eips.ethereum.org/EIPS/eip-2098 +This is for calldata efficiency on smart accounts prevalent on L2s. + +WARNING! Do NOT use signatures as unique identifiers: +- Use a nonce in the digest to prevent replay attacks on the same contract. +- Use EIP-712 for the digest to prevent replay attacks across different chains and contracts. +EIP-712 also enables readable signing of typed data for better user safety. +This implementation does NOT check if a signature is non-malleable. + + + + + +## Signature Checking Operations + +### isValidSignatureNow(address,bytes32,bytes) + +```solidity +function isValidSignatureNow( + address signer, + bytes32 hash, + bytes memory signature +) internal view returns (bool isValid) +``` + +Returns whether `signature` is valid for `signer` and `hash`. +First, it will try to validate with `ecrecover`, and if the validation fails, +it will try to validate with ERC1271 on `signer`. + +### isValidSignatureNowCalldata(address,bytes32,bytes) + +```solidity +function isValidSignatureNowCalldata( + address signer, + bytes32 hash, + bytes calldata signature +) internal view returns (bool isValid) +``` + +Returns whether `signature` is valid for `signer` and `hash`. +First, it will try to validate with `ecrecover`, and if the validation fails, +it will try to validate with ERC1271 on `signer`. + +### isValidSignatureNow(address,bytes32,bytes32,bytes32) + +```solidity +function isValidSignatureNow( + address signer, + bytes32 hash, + bytes32 r, + bytes32 vs +) internal view returns (bool isValid) +``` + +Returns whether the signature (`r`, `vs`) is valid for `signer` and `hash`. +First, it will try to validate with `ecrecover`, and if the validation fails, +it will try to validate with ERC1271 on `signer`. + +### isValidSignatureNow(address,bytes32,uint8,bytes32,bytes32) + +```solidity +function isValidSignatureNow( + address signer, + bytes32 hash, + uint8 v, + bytes32 r, + bytes32 s +) internal view returns (bool isValid) +``` + +Returns whether the signature (`v`, `r`, `s`) is valid for `signer` and `hash`. +First, it will try to validate with `ecrecover`, and if the validation fails, +it will try to validate with ERC1271 on `signer`. + +## ERC1271 Operations + +Note: These ERC1271 operations do NOT have an ECDSA fallback. + +### isValidERC1271SignatureNow(address,bytes32,bytes) + +```solidity +function isValidERC1271SignatureNow( + address signer, + bytes32 hash, + bytes memory signature +) internal view returns (bool isValid) +``` + +Returns whether `signature` is valid for `hash` for an ERC1271 `signer` contract. + +### isValidERC1271SignatureNowCalldata(address,bytes32,bytes) + +```solidity +function isValidERC1271SignatureNowCalldata( + address signer, + bytes32 hash, + bytes calldata signature +) internal view returns (bool isValid) +``` + +Returns whether `signature` is valid for `hash` for an ERC1271 `signer` contract. + +### isValidERC1271SignatureNow(address,bytes32,bytes32,bytes32) + +```solidity +function isValidERC1271SignatureNow( + address signer, + bytes32 hash, + bytes32 r, + bytes32 vs +) internal view returns (bool isValid) +``` + +Returns whether the signature (`r`, `vs`) is valid for `hash` +for an ERC1271 `signer` contract. + +### isValidERC1271SignatureNow(address,bytes32,uint8,bytes32,bytes32) + +```solidity +function isValidERC1271SignatureNow( + address signer, + bytes32 hash, + uint8 v, + bytes32 r, + bytes32 s +) internal view returns (bool isValid) +``` + +Returns whether the signature (`v`, `r`, `s`) is valid for `hash` +for an ERC1271 `signer` contract. + +## ERC6492 Operations + +Note: These ERC6492 operations now include an ECDSA fallback at the very end. +The calldata variants are excluded for brevity. + +### isValidERC6492SignatureNowAllowSideEffects(address,bytes32,bytes) + +```solidity +function isValidERC6492SignatureNowAllowSideEffects( + address signer, + bytes32 hash, + bytes memory signature +) internal returns (bool isValid) +``` + +Returns whether `signature` is valid for `hash`. +If the signature is postfixed with the ERC6492 magic number, it will attempt to +deploy / prepare the `signer` smart account before doing a regular ERC1271 check. +Note: This function is NOT reentrancy safe. +The verifier must be deployed. +Otherwise, the function will return false if `signer` is not yet deployed / prepared. +See: https://gist.github.com/Vectorized/011d6becff6e0a73e42fe100f8d7ef04 +With a dedicated verifier, this function is safe to use in contracts +that have been granted special permissions. + +### isValidERC6492SignatureNow(address,bytes32,bytes) + +```solidity +function isValidERC6492SignatureNow( + address signer, + bytes32 hash, + bytes memory signature +) internal returns (bool isValid) +``` + +Returns whether `signature` is valid for `hash`. +If the signature is postfixed with the ERC6492 magic number, it will attempt +to use a reverting verifier to deploy / prepare the `signer` smart account +and do a `isValidSignature` check via the reverting verifier. +Note: This function is reentrancy safe. +The reverting verifier must be deployed. +Otherwise, the function will return false if `signer` is not yet deployed / prepared. +See: https://gist.github.com/Vectorized/846a474c855eee9e441506676800a9ad + +## Hashing Operations + +### toEthSignedMessageHash(bytes32) + +```solidity +function toEthSignedMessageHash(bytes32 hash) + internal + pure + returns (bytes32 result) +``` + +Returns an Ethereum Signed Message, created from a `hash`. +This produces a hash corresponding to the one signed with the +[`eth_sign`](https://eth.wiki/json-rpc/API#eth_sign) +JSON-RPC method as part of EIP-191. + +### toEthSignedMessageHash(bytes) + +```solidity +function toEthSignedMessageHash(bytes memory s) + internal + pure + returns (bytes32 result) +``` + +Returns an Ethereum Signed Message, created from `s`. +This produces a hash corresponding to the one signed with the +[`eth_sign`](https://eth.wiki/json-rpc/API#eth_sign) +JSON-RPC method as part of EIP-191. +Note: Supports lengths of `s` up to 999999 bytes. + +## Empty Calldata Helpers + +### emptySignature() + +```solidity +function emptySignature() + internal + pure + returns (bytes calldata signature) +``` + +Returns an empty calldata bytes. \ No newline at end of file diff --git a/docs/utils/sstore2.md b/docs/utils/sstore2.md new file mode 100644 index 000000000..4a5f8741a --- /dev/null +++ b/docs/utils/sstore2.md @@ -0,0 +1,162 @@ +# SSTORE2 + +Read and write to persistent storage at a fraction of the cost. + + + + + + + + +## Constants + +### CREATE3_PROXY_INITCODE_HASH + +```solidity +bytes32 internal constant CREATE3_PROXY_INITCODE_HASH = + 0x21c35dbe1b344a2488cf3321d6ce542f8e9f305544ff09e4993a62319a497c1f +``` + +Hash of the `_CREATE3_PROXY_INITCODE`. +Equivalent to `keccak256(abi.encodePacked(hex"67363d3d37363d34f03d5260086018f3"))`. + +## Custom Errors + +### DeploymentFailed() + +```solidity +error DeploymentFailed() +``` + +Unable to deploy the storage contract. + +## Write Logic + +### write(bytes) + +```solidity +function write(bytes memory data) internal returns (address pointer) +``` + +Writes `data` into the bytecode of a storage contract and returns its address. + +### writeCounterfactual(bytes,bytes32) + +```solidity +function writeCounterfactual(bytes memory data, bytes32 salt) + internal + returns (address pointer) +``` + +Writes `data` into the bytecode of a storage contract with `salt` +and returns its normal CREATE2 deterministic address. + +### writeDeterministic(bytes,bytes32) + +```solidity +function writeDeterministic(bytes memory data, bytes32 salt) + internal + returns (address pointer) +``` + +Writes `data` into the bytecode of a storage contract and returns its address. +This uses the so-called "CREATE3" workflow, +which means that `pointer` is agnostic to `data, and only depends on `salt`. + +## Address Calculations + +### initCodeHash(bytes) + +```solidity +function initCodeHash(bytes memory data) + internal + pure + returns (bytes32 hash) +``` + +Returns the initialization code hash of the storage contract for `data`. +Used for mining vanity addresses with create2crunch. + +### predictCounterfactualAddress(bytes,bytes32) + +```solidity +function predictCounterfactualAddress(bytes memory data, bytes32 salt) + internal + view + returns (address pointer) +``` + +Equivalent to `predictCounterfactualAddress(data, salt, address(this))` + +### predictCounterfactualAddress(bytes,bytes32,address) + +```solidity +function predictCounterfactualAddress( + bytes memory data, + bytes32 salt, + address deployer +) internal pure returns (address predicted) +``` + +Returns the CREATE2 address of the storage contract for `data` +deployed with `salt` by `deployer`. +Note: The returned result has dirty upper 96 bits. Please clean if used in assembly. + +### predictDeterministicAddress(bytes32) + +```solidity +function predictDeterministicAddress(bytes32 salt) + internal + view + returns (address pointer) +``` + +Equivalent to `predictDeterministicAddress(salt, address(this))`. + +### predictDeterministicAddress(bytes32,address) + +```solidity +function predictDeterministicAddress(bytes32 salt, address deployer) + internal + pure + returns (address pointer) +``` + +Returns the "CREATE3" deterministic address for `salt` with `deployer`. + +## Read Logic + +### read(address) + +```solidity +function read(address pointer) internal view returns (bytes memory data) +``` + +Equivalent to `read(pointer, 0, 2 ** 256 - 1)`. + +### read(address,uint256) + +```solidity +function read(address pointer, uint256 start) + internal + view + returns (bytes memory data) +``` + +Equivalent to `read(pointer, start, 2 ** 256 - 1)`. + +### read(address,uint256,uint256) + +```solidity +function read(address pointer, uint256 start, uint256 end) + internal + view + returns (bytes memory data) +``` + +Returns a slice of the data on `pointer` from `start` to `end`. +`start` and `end` will be clamped to the range `[0, args.length]`. +The `pointer` MUST be deployed via the SSTORE2 write functions. +Otherwise, the behavior is undefined. +Out-of-gas reverts if `pointer` does not have any code. \ No newline at end of file diff --git a/docs/utils/upgradeablebeacon.md b/docs/utils/upgradeablebeacon.md new file mode 100644 index 000000000..5f9692375 --- /dev/null +++ b/docs/utils/upgradeablebeacon.md @@ -0,0 +1,160 @@ +# UpgradeableBeacon + +Upgradeable beacon for ERC1967 beacon proxies. + + + + + + + + +## Custom Errors + +### NewImplementationHasNoCode() + +```solidity +error NewImplementationHasNoCode() +``` + +The new implementation is not a deployed contract. + +### Unauthorized() + +```solidity +error Unauthorized() +``` + +The caller is not authorized to perform the operation. + +### NewOwnerIsZeroAddress() + +```solidity +error NewOwnerIsZeroAddress() +``` + +The `newOwner` cannot be the zero address. + +## Storage + +### _UPGRADEABLE_BEACON_IMPLEMENTATION_SLOT + +```solidity +uint256 internal constant _UPGRADEABLE_BEACON_IMPLEMENTATION_SLOT = + 0x911c5a209f08d5ec5e +``` + +The storage slot for the implementation address. +`uint72(bytes9(keccak256("_UPGRADEABLE_BEACON_IMPLEMENTATION_SLOT")))`. + +### _UPGRADEABLE_BEACON_OWNER_SLOT + +```solidity +uint256 internal constant _UPGRADEABLE_BEACON_OWNER_SLOT = + 0x4343a0dc92ed22dbfc +``` + +The storage slot for the owner address. +`uint72(bytes9(keccak256("_UPGRADEABLE_BEACON_OWNER_SLOT")))`. + +## Constructor + +### _constructUpgradeableBeacon(address,address) + +```solidity +function _constructUpgradeableBeacon( + address initialOwner, + address initialImplementation +) internal virtual +``` + +Called in the constructor. Override as required. + +## Upgradeable Beacon Operations + +### _initializeUpgradeableBeacon(address,address) + +```solidity +function _initializeUpgradeableBeacon( + address initialOwner, + address initialImplementation +) internal virtual +``` + +Required to be called in the constructor or initializer. +This function does not guard against double-initialization. + +### _setImplementation(address) + +```solidity +function _setImplementation(address newImplementation) internal virtual +``` + +Sets the implementation directly without authorization guard. + +### _setOwner(address) + +```solidity +function _setOwner(address newOwner) internal virtual +``` + +Sets the owner directly without authorization guard. + +### implementation() + +```solidity +function implementation() public view returns (address result) +``` + +Returns the implementation stored in the beacon. +See: https://eips.ethereum.org/EIPS/eip-1967#beacon-contract-address + +### owner() + +```solidity +function owner() public view returns (address result) +``` + +Returns the owner of the beacon. + +### upgradeTo(address) + +```solidity +function upgradeTo(address newImplementation) public virtual onlyOwner +``` + +Allows the owner to upgrade the implementation. + +### transferOwnership(address) + +```solidity +function transferOwnership(address newOwner) public virtual onlyOwner +``` + +Allows the owner to transfer the ownership to `newOwner`. + +### renounceOwnership() + +```solidity +function renounceOwnership() public virtual onlyOwner +``` + +Allows the owner to renounce their ownership. + +### _checkOwner() + +```solidity +function _checkOwner() internal view virtual +``` + +Throws if the sender is not the owner. + +## Modifiers + +### onlyOwner() + +```solidity +modifier onlyOwner() virtual +``` + +Marks a function as only callable by the owner. \ No newline at end of file diff --git a/docs/utils/uupsupgradeable.md b/docs/utils/uupsupgradeable.md new file mode 100644 index 000000000..2fd6ce428 --- /dev/null +++ b/docs/utils/uupsupgradeable.md @@ -0,0 +1,78 @@ +# UUPSUpgradeable + +UUPS proxy mixin. + + +Note: + +- 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`. + + + + + +## Custom Errors + +### UpgradeFailed() + +```solidity +error UpgradeFailed() +``` + +The upgrade failed. + +### UnauthorizedCallContext() + +```solidity +error UnauthorizedCallContext() +``` + +The call is from an unauthorized call context. + +## Storage + +### _ERC1967_IMPLEMENTATION_SLOT + +```solidity +bytes32 internal constant _ERC1967_IMPLEMENTATION_SLOT = + 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc +``` + +The ERC-1967 storage slot for the implementation in the proxy. +`uint256(keccak256("eip1967.proxy.implementation")) - 1`. + +## UUPS Operations + +### upgradeToAndCall(address,bytes) + +```solidity +function upgradeToAndCall(address newImplementation, bytes calldata data) + public + payable + virtual + onlyProxy +``` + +Upgrades the proxy's implementation to `newImplementation`. +Emits a {Upgraded} event. +Note: Passing in empty `data` skips the delegatecall to `newImplementation`. + +### onlyProxy() + +```solidity +modifier onlyProxy() +``` + +Requires that the execution is performed through a proxy. + +### notDelegated() + +```solidity +modifier notDelegated() +``` + +Requires that the execution is NOT performed via delegatecall. +This is the opposite of `onlyProxy`. \ No newline at end of file diff --git a/docs/utils/webauthn.md b/docs/utils/webauthn.md new file mode 100644 index 000000000..d6195220f --- /dev/null +++ b/docs/utils/webauthn.md @@ -0,0 +1,187 @@ +# WebAuthn + +WebAuthn helper. + + + + + + + + +## Structs + +### WebAuthnAuth + +```solidity +struct WebAuthnAuth { + // The WebAuthn authenticator data. + // See: https://www.w3.org/TR/webauthn-2/#dom-authenticatorassertionresponse-authenticatordata. + bytes authenticatorData; + // The WebAuthn client data JSON. + // See: https://www.w3.org/TR/webauthn-2/#dom-authenticatorresponse-clientdatajson. + string clientDataJSON; + // Start index of "challenge":"..." in `clientDataJSON`. + uint256 challengeIndex; + // Start index of "type":"..." in `clientDataJSON`. + uint256 typeIndex; + // The r value of secp256r1 signature. + bytes32 r; + // The s value of secp256r1 signature. + bytes32 s; +} +``` + +Helps make encoding and decoding easier, alleviates stack-too-deep. + +## Webauthn Verification Operations + +### verify(bytes,bool,WebAuthnAuth,bytes32,bytes32) + +```solidity +function verify( + bytes memory challenge, + bool requireUserVerification, + WebAuthnAuth memory auth, + bytes32 x, + bytes32 y +) internal view returns (bool result) +``` + +Verifies a Webauthn Authentication Assertion. +See: https://www.w3.org/TR/webauthn-2/#sctn-verifying-assertion. +We do not verify all the steps as described in the specification, only ones +relevant to our context. Please carefully read through this list before usage. +Specifically, we do verify the following: +- Verify that `authenticatorData` (which comes from the authenticator, + such as iCloud Keychain) indicates a well-formed assertion with the + "User Present" bit set. If `requireUserVerification` is set, checks that the + authenticator enforced user verification. User verification should be required + if, and only if, `options.userVerification` is set to required in the request. +- Verifies that the client JSON is of type "webauthn.get", + i.e. the client was responding to a request to assert authentication. +- Verifies that the client JSON contains the requested challenge. +- Verifies that (r, s) constitute a valid signature over both the + `authData` and client JSON, for public key (x, y). +We make some assumptions about the particular use case of this verifier, +so we do NOT verify the following: +- Does NOT verify that the origin in the `clientDataJSON` matches the + Relying Party's origin: it is considered the authenticator's responsibility to + ensure that the user is interacting with the correct RP. This is enforced by + most high quality authenticators properly, particularly the iCloud Keychain + and Google Password Manager were tested. +- Does NOT verify That `topOrigin` in `clientDataJSON` is well-formed: + We assume it would never be present, i.e. the credentials are never used in a + cross-origin/iframe context. The website/app set up should disallow cross-origin + usage of the credentials. This is the default behavior for created credentials + in common settings. +- Does NOT verify that the `rpIdHash` in `authenticatorData` is the SHA-256 hash + of the RP ID expected by the Relying Party: + this means that we rely on the authenticator to properly enforce + credentials to be used only by the correct RP. + This is generally enforced with features like Apple App Site Association + and Google Asset Links. To protect from edge cases in which a previously-linked + RP ID is removed from the authorized RP IDs, we recommend that messages + signed by the authenticator include some expiry mechanism. +- Does NOT verify the credential backup state: this assumes the credential backup + state is NOT used as part of Relying Party business logic or policy. +- Does NOT verify the values of the client extension outputs: + this assumes that the Relying Party does not use client extension outputs. +- Does NOT verify the signature counter: signature counters are intended to enable + risk scoring for the Relying Party. This assumes risk scoring is not used as part + of Relying Party business logic or policy. +- Does NOT verify the attestation object: this assumes that + response.attestationObject is NOT present in the response, + i.e. the RP does not intend to verify an attestation. + +### verify(bytes,bool,bytes,string,uint256,uint256,bytes32,bytes32,bytes32,bytes32) + +```solidity +function verify( + bytes memory challenge, + bool requireUserVerification, + bytes memory authenticatorData, + string memory clientDataJSON, + uint256 challengeIndex, + uint256 typeIndex, + bytes32 r, + bytes32 s, + bytes32 x, + bytes32 y +) internal view returns (bool) +``` + +Plain variant of verify. + +## Encoding / Decoding Helpers + +### encodeAuth(WebAuthnAuth) + +```solidity +function encodeAuth(WebAuthnAuth memory auth) + internal + pure + returns (bytes memory) +``` + +Returns `abi.encode(auth)`. + +### tryDecodeAuth(bytes) + +```solidity +function tryDecodeAuth(bytes memory encodedAuth) + internal + pure + returns (WebAuthnAuth memory decoded) +``` + +Performs a best-effort attempt to `abi.decode(auth)`. Won't revert. +If any fields cannot be successfully extracted, `decoded` will not be populated, +which will cause `verify` to return false (as `clientDataJSON` is empty). + +### tryEncodeAuthCompact(WebAuthnAuth) + +```solidity +function tryEncodeAuthCompact(WebAuthnAuth memory auth) + internal + pure + returns (bytes memory result) +``` + +Returns the compact encoding of `auth`: +```solidity +abi.encodePacked( + uint16(auth.authenticatorData.length), + bytes(auth.authenticatorData), + bytes(auth.clientDataJSON), + uint16(auth.challengeIndex), + uint16(auth.typeIndex), + bytes32(auth.r), + bytes32(auth.s) +) +``` +Returns the empty string if any length or index exceeds 16 bits. + +### tryDecodeAuthCompact(bytes) + +```solidity +function tryDecodeAuthCompact(bytes memory encodedAuth) + internal + pure + returns (WebAuthnAuth memory decoded) +``` + +Approximately the same gas as `tryDecodeAuth`, but helps save on calldata. +If any fields cannot be successfully extracted, `decoded` will not be populated, +which will cause `verify` to return false (as `clientDataJSON` is empty). + +### tryDecodeAuthCompactCalldata(bytes) + +```solidity +function tryDecodeAuthCompactCalldata(bytes calldata encodedAuth) + internal + pure + returns (WebAuthnAuth memory decoded) +``` + +Calldata variant of `tryDecodeAuthCompact`. \ No newline at end of file diff --git a/prep/common.js b/prep/common.js index 608184de2..b8e7d4e56 100644 --- a/prep/common.js +++ b/prep/common.js @@ -7,7 +7,8 @@ const normalizeNewlines = s => s.replace(/\n(\n\s*)+/g, '\n\n'); const hexNoPrefix = x => x.toString(16).replace(/^0[xX]/, ''); -const readSync = srcPath => fs.readFileSync(srcPath, { encoding: 'utf8', flag: 'r' }); +const readSync = srcPath => + fs.existsSync(srcPath) ? fs.readFileSync(srcPath, { encoding: 'utf8', flag: 'r' }) : ''; const runCommandSync = (command, args) => { const result = spawnSync(command, args, { encoding:'utf-8' }); @@ -53,6 +54,34 @@ const forEachWalkSync = (dirs, callback) => { dirs.forEach(dir => walkSync(dir, callback)); }; +const readSolWithLineLengthSync = (srcPath, lineLength) => { + const withModifiedToml = callback => { + const originalFile = path.resolve('foundry.toml'); + const backupFile = path.resolve('__tmp_foundry.toml'); + try { + fs.copyFileSync(originalFile, backupFile); + let content = fs.readFileSync(originalFile, 'utf8'); + content = content.replace(/line_length\s*=\s*\d+/g, 'line_length = ' + lineLength); + fs.writeFileSync(originalFile, content, 'utf8'); + return callback(); + } catch (err) { + } finally { + if (fs.existsSync(backupFile)) { + fs.copyFileSync(backupFile, originalFile); + fs.unlinkSync(backupFile); + } + } + }; + return withModifiedToml(() => { + const tempFile = '__tmp.sol'; + fs.copyFileSync(srcPath, tempFile); + runCommandSync('forge', ['fmt', tempFile]); + let content = fs.readFileSync(tempFile, 'utf8'); + fs.unlinkSync(tempFile); + return content; + }); +}; + module.exports = { genSectionRegex, hexNoPrefix, @@ -63,5 +92,6 @@ module.exports = { writeSync, writeAndFmtSync, walkSync, - forEachWalkSync + forEachWalkSync, + readSolWithLineLengthSync }; diff --git a/prep/gen-docs.js b/prep/gen-docs.js new file mode 100644 index 000000000..aad6e7560 --- /dev/null +++ b/prep/gen-docs.js @@ -0,0 +1,248 @@ +#!/usr/bin/env node +const { + readSync, + writeSync, + forEachWalkSync, + hasAnyPathSequence, + readSolWithLineLengthSync, + normalizeNewlines +} = require('./common.js'); +const path = require('path'); + +async function main() { + const pathSequencesToIgnore = ['g', 'ext', 'legacy']; + + const cleanForRegex = s => s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); + + const makeTagRegex = tag => new RegExp( + '()([\s\S]*?)' + + '()' + ); + + const has = (a, b) => a.toLowerCase().indexOf(b.toLowerCase()) !== -1; + + const strip = s => s.replace(/^\s+|\s+$/g, ''); + + const replaceInTag = (s, tag, replacement) => + s.replace( + makeTagRegex(tag), + (m0, m1, m2, m3) => m1 + '\n' + strip(replacement) + '\n' + m3 + ); + + const getTag = (s, tag) => { + const m = s.match(makeTagRegex(tag)); + if (m === null) return '' + ''; + return m[0]; + }; + + const coalesce = (m, f) => m === null ? '' : f(m); + + const toHeaderCase = str => + strip(str).toLowerCase() + .replace(/(eth|sha|lz|uups|(eip|rip|erc|push|create)\-?[0-9]+i?)/g, m => m.toUpperCase()) + .split(/\s+/) + .map(w => w.replace(/^([a-zA-Z])/, c => c.toUpperCase())) + .join(' '); + + const deindent = s => s.replace(/^ {4}/gm, ''); + + const getFunctionSig = s => coalesce( + s.match(/(\w+)\s*\(([^)]*)\)/), + m => m[1] + '(' + m[2].split(',').map(x => strip(x).split(/\s+/)[0]) + ')' + ); + + const cleanNatspecOrNote = s => deindent(strip( + s.replace(/\s+\/\/\/?/g, '\n') + .replace(/\s?\n\s?/g, ' \n') + .replace(/```([\s\S]+?)```/g, '```solidity$1```') + .replace(/^\/\/\/\s+@[a-z]+\s?/, '') + )); + + const getSections = s => { + const sectionHeaderRe = /\/\*\S+?\*\/\s*\/\*([^*]{60})\*\/\s*\/\*\S+?\*\//g; + let a = [], l = null; + for (let m = null; (m = sectionHeaderRe.exec(s)) !== null; l = m) { + if (l !== null) { + a.push({ + h2: toHeaderCase(l[1]), + src: s.slice(l.index + l[0].length, m.index) + }); + } + } + if (l !== null) { + a.push({ + h2: toHeaderCase(l[1]), + src: s.slice(l.index + l[0].length) + }); + } + return a + .filter(x => !has(x.h2, 'private')) + .map(item => { + const m = (/^((\s+\/\/\s[^\n]+)+)/).exec(item.src); + if (m) item.note = cleanNatspecOrNote(m[0]); + return item; + }); + }; + + const getSubSections = (s, r) => { + let a = []; + for (let m = null; (m = r.exec(s)) !== null; ) { + if (!has(m[2], '///') && !/\sprivate\s/.test(m[2])) a.push(m); + } + return a; + } + + const getFunctionsAndModifiers = s => + getSubSections(s, /((?:\/\/\/\s[^\n]+\n\s*?)+)((?:function|fallback|receive|modifier)[^{]+)/g) + .map(m => ({ + natspec: cleanNatspecOrNote(m[1]), + def: deindent(strip(m[2])), + h3: getFunctionSig(deindent(strip(m[2]))) + })); + + const getConstantsAndImmutables = s => + getSubSections(s, /((?:\/\/\/\s[^\n]+\n\s*?)+)((?:bytes|uint|address)[0-9]*\s+(?:public|internal)\s+(?:immutable|constant)\s+([A-Za-z0-9_]+)[^;]*)/g) + .map(m => ({ + natspec: cleanNatspecOrNote(m[1]), + def: deindent(strip(m[2])), + h3: deindent(strip(m[3])) + })); + + const getCustomErrors = s => + getSubSections(s, /((?:\/\/\/\s[^\n]+\n\s*?)+)(error\s[^;]+);/g) + .map(m => ({ + natspec: cleanNatspecOrNote(m[1]), + def: deindent(strip(m[2])), + h3: getFunctionSig(deindent(strip(m[2]))) + })); + + const getStructsAndEnums = s => + getSubSections(s, /((?:\/\/\/\s[^\n]+\n\s*?)+)((?:struct|enum)\s([A-Za-z0-9_]+)\s+\{[^}]+})/g) + .map(m => ({ + natspec: cleanNatspecOrNote(m[1]), + def: deindent(strip(m[2])), + h3: deindent(strip(m[3])) + })); + + const getNotice = s => coalesce( + s.match(/\/\/\/\s+@notice\s+([\s\S]+?)\/\/\/\s?@author/), + m => m[1].replace(/\n\/\/\//g, '') + ); + + const getImports = (s, srcPath) => { + const r = /import\s[\s\S]*?(["'][\s\S]+?["'])/g; + let a = []; + for (let m = null; (m = r.exec(s)) !== null; ) { + const p = path.normalize(path.dirname(srcPath) + path.sep + m[1].slice(1, -1)); + a.push(p.split(path.sep).slice(-2).join(path.sep)); + } + return a; + }; + + 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]+?\{/), + m => normalizeNewlines(strip( + m[1].replace('\n\n', '\n\n\n').split('\n') + .map(l => l + .replace(/^\/\/\/\s*/, '') + .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(/@dev\s/g, '') + )) + ); + + const getInherits = (s, srcPath) => coalesce( + s.match(/contract\s+[A-Za-z0-9_]+\s+is\s+([^\{]*?)\s*\{/), + m => 'Inherits: \n\n' + + m[1].split(',').map(strip).map(p => + getImports(s, srcPath).map(q => has(q, p) ? '- `' + q + '` \n' : '').join('') + ).join('') + ); + + const getSrcDir = srcPath => srcPath.split(path.sep).slice(-2)[0]; + const getTitle = srcPath => path.parse(srcPath).name; + const getDocSubPath = srcPath => getSrcDir(srcPath) + path.sep + getTitle(srcPath).toLowerCase() + '.md'; + const getDocPath = srcPath => 'docs' + path.sep + getDocSubPath(srcPath); + + let docSrcPaths = []; + + forEachWalkSync(['src'], srcPath => { + if (!srcPath.match(/\.sol$/i)) return; + if (hasAnyPathSequence(srcPath, pathSequencesToIgnore)) return; + if (has(srcPath, 'Milady.sol')) return; + console.log(srcPath); + + let src = readSolWithLineLengthSync(srcPath, 80); + let sections = getSections(src); + + if (sections.length < 1) { + src = src.replace( + /(library|contract)\s[\s\S]*?\{/, + m => m + + '/*============================================================*/\n' + + '/* FUNCTIONS */\n' + + '/*============================================================*/\n' + ); + sections = getSections(src); + } + + const docHeader = '# ' + getTitle(srcPath) + '\n\n' + getNotice(src); + let docChunks = []; + sections.forEach(x => + [ + getStructsAndEnums, + getCustomErrors, + getFunctionsAndModifiers, + getConstantsAndImmutables + ] + .reduce((acc, f) => acc.length ? acc : f(x.src), []) + .forEach((y, i) => + docChunks.push( + ...(i ? [] : ['## ' + x.h2, ...(x.note ? [x.note] : [])]), + '### ' + y.h3, + '```solidity\n' + y.def + '\n```', + y.natspec + ) + ) + ); + + if (docChunks.length) { + writeSync( + getDocPath(srcPath), + [ + docHeader, + getTopIntro(src), + getInherits(src, srcPath), + getTag(readSync(getDocPath(srcPath)), 'customintro'), + docChunks.join('\n\n') + ].join('\n\n') + ); + docSrcPaths.push(srcPath); + } + }); + + if (docSrcPaths.length) { + const sidebarDocPath = 'docs' + path.sep + 'sidebar.md'; + writeSync( + sidebarDocPath, + replaceInTag( + readSync(sidebarDocPath), + 'gen', + [...new Set(docSrcPaths.map(getSrcDir))] + .map(dir => '- ' + dir + '\n' + + docSrcPaths + .filter(p => getSrcDir(p) === dir) + .map(p => ' - [' + getTitle(p) + '](' + getDocSubPath(p) + ')') + .join('\n') + ).join('\n') + ) + ); + } +}; + +main().catch(e => { + console.error(e); + process.exit(1); +});