// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)pragmasolidity ^0.8.20;/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/abstractcontractContext{
function_msgSender() internalviewvirtualreturns (address) {
returnmsg.sender;
}
function_msgData() internalviewvirtualreturns (bytescalldata) {
returnmsg.data;
}
function_contextSuffixLength() internalviewvirtualreturns (uint256) {
return0;
}
}
Contract Source Code
File 5 of 44: Currency.sol
// SPDX-License-Identifier: GPL-2.0-or-laterpragmasolidity ^0.8.20;import {IERC20} from"@openzeppelin/contracts/token/ERC20/IERC20.sol";
type Currency isaddress;
/// @title CurrencyLibrary/// @dev This library allows for transferring and holding native tokens and ERC20 tokenslibraryCurrencyLibrary{
usingCurrencyLibraryforCurrency;
/// @notice Thrown when a native transfer failserrorNativeTransferFailed();
/// @notice Thrown when an ERC20 transfer failserrorERC20TransferFailed();
Currency publicconstant NATIVE = Currency.wrap(address(0));
functiontransfer(Currency currency, address to, uint256 amount) internal{
// implementation from// https://github.com/transmissions11/solmate/blob/e8f96f25d48fe702117ce76c79228ca4f20206cb/src/utils/SafeTransferLib.solbool success;
if (currency.isNative()) {
assembly {
// Transfer the ETH and store if it succeeded or not.
success :=call(gas(), to, amount, 0, 0, 0, 0)
}
if (!success) revert NativeTransferFailed();
} else {
assembly {
// Get a pointer to some free memory.let freeMemoryPointer :=mload(0x40)
// Write the abi-encoded calldata into memory, beginning with the function selector.mstore(freeMemoryPointer, 0xa9059cbb00000000000000000000000000000000000000000000000000000000)
mstore(add(freeMemoryPointer, 4), and(to, 0xffffffffffffffffffffffffffffffffffffffff)) // Append and mask the "to" argument.mstore(add(freeMemoryPointer, 36), amount) // Append the "amount" argument. Masking not required as it's a full 32 byte type.
success :=and(
// Set success to whether the call reverted, if not we check it either// returned exactly 1 (can't just be non-zero data), or had no return data.or(and(eq(mload(0), 1), gt(returndatasize(), 31)), iszero(returndatasize())),
// We use 68 because the length of our calldata totals up like so: 4 + 32 * 2.// We use 0 and 32 to copy up to 32 bytes of return data into the scratch space.// Counterintuitively, this call must be positioned second to the or() call in the// surrounding and() call or else returndatasize() will be zero during the computation.call(gas(), currency, 0, freeMemoryPointer, 68, 0, 32)
)
}
if (!success) revert ERC20TransferFailed();
}
}
functionbalanceOfSelf(Currency currency) internalviewreturns (uint256) {
if (currency.isNative()) returnaddress(this).balance;
elsereturn IERC20(Currency.unwrap(currency)).balanceOf(address(this));
}
functionequals(Currency currency, Currency other) internalpurereturns (bool) {
return Currency.unwrap(currency) == Currency.unwrap(other);
}
functionisNative(Currency currency) internalpurereturns (bool) {
return Currency.unwrap(currency) == Currency.unwrap(NATIVE);
}
functiontoId(Currency currency) internalpurereturns (uint256) {
returnuint160(Currency.unwrap(currency));
}
functionfromId(uint256 id) internalpurereturns (Currency) {
return Currency.wrap(address(uint160(id)));
}
}
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v5.0.0) (utils/cryptography/ECDSA.sol)pragmasolidity ^0.8.20;/**
* @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.
*
* These functions can be used to verify that a message was signed by the holder
* of the private keys of a given address.
*/libraryECDSA{
enumRecoverError {
NoError,
InvalidSignature,
InvalidSignatureLength,
InvalidSignatureS
}
/**
* @dev The signature derives the `address(0)`.
*/errorECDSAInvalidSignature();
/**
* @dev The signature has an invalid length.
*/errorECDSAInvalidSignatureLength(uint256 length);
/**
* @dev The signature has an S value that is in the upper half order.
*/errorECDSAInvalidSignatureS(bytes32 s);
/**
* @dev Returns the address that signed a hashed message (`hash`) with `signature` or an error. This will not
* return address(0) without also returning an error description. Errors are documented using an enum (error type)
* and a bytes32 providing additional information about the error.
*
* If no error is returned, then the address can be used for verification purposes.
*
* The `ecrecover` EVM precompile allows for malleable (non-unique) signatures:
* this function rejects them by requiring the `s` value to be in the lower
* half order, and the `v` value to be either 27 or 28.
*
* IMPORTANT: `hash` _must_ be the result of a hash operation for the
* verification to be secure: it is possible to craft signatures that
* recover to arbitrary addresses for non-hashed data. A safe way to ensure
* this is by receiving a hash of the original message (which may otherwise
* be too long), and then calling {MessageHashUtils-toEthSignedMessageHash} on it.
*
* Documentation for signature generation:
* - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]
* - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]
*/functiontryRecover(bytes32 hash, bytesmemory signature) internalpurereturns (address, RecoverError, bytes32) {
if (signature.length==65) {
bytes32 r;
bytes32 s;
uint8 v;
// ecrecover takes the signature parameters, and the only way to get them// currently is to use assembly./// @solidity memory-safe-assemblyassembly {
r :=mload(add(signature, 0x20))
s :=mload(add(signature, 0x40))
v :=byte(0, mload(add(signature, 0x60)))
}
return tryRecover(hash, v, r, s);
} else {
return (address(0), RecoverError.InvalidSignatureLength, bytes32(signature.length));
}
}
/**
* @dev Returns the address that signed a hashed message (`hash`) with
* `signature`. This address can then be used for verification purposes.
*
* The `ecrecover` EVM precompile allows for malleable (non-unique) signatures:
* this function rejects them by requiring the `s` value to be in the lower
* half order, and the `v` value to be either 27 or 28.
*
* IMPORTANT: `hash` _must_ be the result of a hash operation for the
* verification to be secure: it is possible to craft signatures that
* recover to arbitrary addresses for non-hashed data. A safe way to ensure
* this is by receiving a hash of the original message (which may otherwise
* be too long), and then calling {MessageHashUtils-toEthSignedMessageHash} on it.
*/functionrecover(bytes32 hash, bytesmemory signature) internalpurereturns (address) {
(address recovered, RecoverError error, bytes32errorArg) = tryRecover(hash, signature);
_throwError(error, errorArg);
return recovered;
}
/**
* @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.
*
* See https://eips.ethereum.org/EIPS/eip-2098[ERC-2098 short signatures]
*/functiontryRecover(bytes32 hash, bytes32 r, bytes32 vs) internalpurereturns (address, RecoverError, bytes32) {
unchecked {
bytes32 s = vs &bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
// We do not check for an overflow here since the shift operation results in 0 or 1.uint8 v =uint8((uint256(vs) >>255) +27);
return tryRecover(hash, v, r, s);
}
}
/**
* @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.
*/functionrecover(bytes32 hash, bytes32 r, bytes32 vs) internalpurereturns (address) {
(address recovered, RecoverError error, bytes32errorArg) = tryRecover(hash, r, vs);
_throwError(error, errorArg);
return recovered;
}
/**
* @dev Overload of {ECDSA-tryRecover} that receives the `v`,
* `r` and `s` signature fields separately.
*/functiontryRecover(bytes32 hash,
uint8 v,
bytes32 r,
bytes32 s
) internalpurereturns (address, RecoverError, bytes32) {
// EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature// unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines// the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most// signatures from current libraries generate a unique signature with an s-value in the lower half order.//// If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value// with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or// vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept// these malleable signatures as well.if (uint256(s) >0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
return (address(0), RecoverError.InvalidSignatureS, s);
}
// If the signature is valid (and not malleable), return the signer addressaddress signer =ecrecover(hash, v, r, s);
if (signer ==address(0)) {
return (address(0), RecoverError.InvalidSignature, bytes32(0));
}
return (signer, RecoverError.NoError, bytes32(0));
}
/**
* @dev Overload of {ECDSA-recover} that receives the `v`,
* `r` and `s` signature fields separately.
*/functionrecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internalpurereturns (address) {
(address recovered, RecoverError error, bytes32errorArg) = tryRecover(hash, v, r, s);
_throwError(error, errorArg);
return recovered;
}
/**
* @dev Optionally reverts with the corresponding custom error according to the `error` argument provided.
*/function_throwError(RecoverError error, bytes32 errorArg) privatepure{
if (error == RecoverError.NoError) {
return; // no error: do nothing
} elseif (error == RecoverError.InvalidSignature) {
revert ECDSAInvalidSignature();
} elseif (error == RecoverError.InvalidSignatureLength) {
revert ECDSAInvalidSignatureLength(uint256(errorArg));
} elseif (error == RecoverError.InvalidSignatureS) {
revert ECDSAInvalidSignatureS(errorArg);
}
}
}
Contract Source Code
File 9 of 44: EIP712.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v5.0.0) (utils/cryptography/EIP712.sol)pragmasolidity ^0.8.20;import {MessageHashUtils} from"./MessageHashUtils.sol";
import {ShortStrings, ShortString} from"../ShortStrings.sol";
import {IERC5267} from"../../interfaces/IERC5267.sol";
/**
* @dev https://eips.ethereum.org/EIPS/eip-712[EIP-712] is a standard for hashing and signing of typed structured data.
*
* The encoding scheme specified in the EIP requires a domain separator and a hash of the typed structured data, whose
* encoding is very generic and therefore its implementation in Solidity is not feasible, thus this contract
* does not implement the encoding itself. Protocols need to implement the type-specific encoding they need in order to
* produce the hash of their typed data using a combination of `abi.encode` and `keccak256`.
*
* This contract implements the EIP-712 domain separator ({_domainSeparatorV4}) that is used as part of the encoding
* scheme, and the final step of the encoding to obtain the message digest that is then signed via ECDSA
* ({_hashTypedDataV4}).
*
* The implementation of the domain separator was designed to be as efficient as possible while still properly updating
* the chain id to protect against replay attacks on an eventual fork of the chain.
*
* NOTE: This contract implements the version of the encoding known as "v4", as implemented by the JSON RPC method
* https://docs.metamask.io/guide/signing-data.html[`eth_signTypedDataV4` in MetaMask].
*
* NOTE: In the upgradeable version of this contract, the cached values will correspond to the address, and the domain
* separator of the implementation contract. This will cause the {_domainSeparatorV4} function to always rebuild the
* separator from the immutable values, which is cheaper than accessing a cached version in cold storage.
*
* @custom:oz-upgrades-unsafe-allow state-variable-immutable
*/abstractcontractEIP712isIERC5267{
usingShortStringsfor*;
bytes32privateconstant TYPE_HASH =keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)");
// Cache the domain separator as an immutable value, but also store the chain id that it corresponds to, in order to// invalidate the cached domain separator if the chain id changes.bytes32privateimmutable _cachedDomainSeparator;
uint256privateimmutable _cachedChainId;
addressprivateimmutable _cachedThis;
bytes32privateimmutable _hashedName;
bytes32privateimmutable _hashedVersion;
ShortString privateimmutable _name;
ShortString privateimmutable _version;
stringprivate _nameFallback;
stringprivate _versionFallback;
/**
* @dev Initializes the domain separator and parameter caches.
*
* The meaning of `name` and `version` is specified in
* https://eips.ethereum.org/EIPS/eip-712#definition-of-domainseparator[EIP-712]:
*
* - `name`: the user readable name of the signing domain, i.e. the name of the DApp or the protocol.
* - `version`: the current major version of the signing domain.
*
* NOTE: These parameters cannot be changed except through a xref:learn::upgrading-smart-contracts.adoc[smart
* contract upgrade].
*/constructor(stringmemory name, stringmemory version) {
_name = name.toShortStringWithFallback(_nameFallback);
_version = version.toShortStringWithFallback(_versionFallback);
_hashedName =keccak256(bytes(name));
_hashedVersion =keccak256(bytes(version));
_cachedChainId =block.chainid;
_cachedDomainSeparator = _buildDomainSeparator();
_cachedThis =address(this);
}
/**
* @dev Returns the domain separator for the current chain.
*/function_domainSeparatorV4() internalviewreturns (bytes32) {
if (address(this) == _cachedThis &&block.chainid== _cachedChainId) {
return _cachedDomainSeparator;
} else {
return _buildDomainSeparator();
}
}
function_buildDomainSeparator() privateviewreturns (bytes32) {
returnkeccak256(abi.encode(TYPE_HASH, _hashedName, _hashedVersion, block.chainid, address(this)));
}
/**
* @dev Given an already https://eips.ethereum.org/EIPS/eip-712#definition-of-hashstruct[hashed struct], this
* function returns the hash of the fully encoded EIP712 message for this domain.
*
* This hash can be used together with {ECDSA-recover} to obtain the signer of a message. For example:
*
* ```solidity
* bytes32 digest = _hashTypedDataV4(keccak256(abi.encode(
* keccak256("Mail(address to,string contents)"),
* mailTo,
* keccak256(bytes(mailContents))
* )));
* address signer = ECDSA.recover(digest, signature);
* ```
*/function_hashTypedDataV4(bytes32 structHash) internalviewvirtualreturns (bytes32) {
return MessageHashUtils.toTypedDataHash(_domainSeparatorV4(), structHash);
}
/**
* @dev See {IERC-5267}.
*/functioneip712Domain()
publicviewvirtualreturns (bytes1 fields,
stringmemory name,
stringmemory version,
uint256 chainId,
address verifyingContract,
bytes32 salt,
uint256[] memory extensions
)
{
return (
hex"0f", // 01111
_EIP712Name(),
_EIP712Version(),
block.chainid,
address(this),
bytes32(0),
newuint256[](0)
);
}
/**
* @dev The name parameter for the EIP712 domain.
*
* NOTE: By default this function reads _name which is an immutable value.
* It only reads from storage if necessary (in case the value is too large to fit in a ShortString).
*/// solhint-disable-next-line func-name-mixedcasefunction_EIP712Name() internalviewreturns (stringmemory) {
return _name.toStringWithFallback(_nameFallback);
}
/**
* @dev The version parameter for the EIP712 domain.
*
* NOTE: By default this function reads _version which is an immutable value.
* It only reads from storage if necessary (in case the value is too large to fit in a ShortString).
*/// solhint-disable-next-line func-name-mixedcasefunction_EIP712Version() internalviewreturns (stringmemory) {
return _version.toStringWithFallback(_versionFallback);
}
}
Contract Source Code
File 10 of 44: ERC165.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/ERC165.sol)pragmasolidity ^0.8.20;import {IERC165} from"./IERC165.sol";
/**
* @dev Implementation of the {IERC165} interface.
*
* Contracts that want to implement ERC-165 should inherit from this contract and override {supportsInterface} to check
* for the additional interface id that will be supported. For example:
*
* ```solidity
* function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
* return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
* }
* ```
*/abstractcontractERC165isIERC165{
/**
* @dev See {IERC165-supportsInterface}.
*/functionsupportsInterface(bytes4 interfaceId) publicviewvirtualreturns (bool) {
return interfaceId ==type(IERC165).interfaceId;
}
}
Contract Source Code
File 11 of 44: ERC721.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC721/ERC721.sol)// Modified by Clober Teampragmasolidity ^0.8.20;import {IERC721} from"@openzeppelin/contracts/token/ERC721/IERC721.sol";
import {IERC721Receiver} from"@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol";
import {IERC721Metadata} from"@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol";
import {Context} from"@openzeppelin/contracts/utils/Context.sol";
import {Strings} from"@openzeppelin/contracts/utils/Strings.sol";
import {IERC165, ERC165} from"@openzeppelin/contracts/utils/introspection/ERC165.sol";
import {IERC721Errors} from"@openzeppelin/contracts/interfaces/draft-IERC6093.sol";
/**
* @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC721] Non-Fungible Token Standard, including
* the Metadata extension, but not including the Enumerable extension, which is available separately as
* {ERC721Enumerable}.
*/abstractcontractERC721isContext, ERC165, IERC721, IERC721Metadata, IERC721Errors{
usingStringsforuint256;
// Token namestringprivate _name;
// Token symbolstringprivate _symbol;
mapping(address owner =>uint256) private _balances;
mapping(uint256 tokenId =>address) private _tokenApprovals;
mapping(address owner =>mapping(address operator =>bool)) private _operatorApprovals;
/**
* @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.
*/constructor(stringmemory name_, stringmemory symbol_) {
_name = name_;
_symbol = symbol_;
}
/**
* @dev See {IERC165-supportsInterface}.
*/functionsupportsInterface(bytes4 interfaceId) publicviewvirtualoverride(ERC165, IERC165) returns (bool) {
return interfaceId ==type(IERC721).interfaceId|| interfaceId ==type(IERC721Metadata).interfaceId||super.supportsInterface(interfaceId);
}
/**
* @dev See {IERC721-balanceOf}.
*/functionbalanceOf(address owner) publicviewvirtualreturns (uint256) {
if (owner ==address(0)) {
revert ERC721InvalidOwner(address(0));
}
return _balances[owner];
}
/**
* @dev See {IERC721-ownerOf}.
*/functionownerOf(uint256 tokenId) publicviewvirtualreturns (address) {
return _requireOwned(tokenId);
}
/**
* @dev See {IERC721Metadata-name}.
*/functionname() publicviewvirtualreturns (stringmemory) {
return _name;
}
/**
* @dev See {IERC721Metadata-symbol}.
*/functionsymbol() publicviewvirtualreturns (stringmemory) {
return _symbol;
}
/**
* @dev See {IERC721Metadata-tokenURI}.
*/functiontokenURI(uint256 tokenId) publicviewvirtualreturns (stringmemory) {
_requireOwned(tokenId);
stringmemory baseURI = _baseURI();
returnbytes(baseURI).length>0 ? string.concat(baseURI, tokenId.toString()) : "";
}
/**
* @dev Base URI for computing {tokenURI}. If set, the resulting URI for each
* token will be the concatenation of the `baseURI` and the `tokenId`. Empty
* by default, can be overridden in child contracts.
*/function_baseURI() internalviewvirtualreturns (stringmemory) {
return"";
}
/**
* @dev See {IERC721-approve}.
*/functionapprove(address to, uint256 tokenId) publicvirtual{
_approve(to, tokenId, _msgSender());
}
/**
* @dev See {IERC721-getApproved}.
*/functiongetApproved(uint256 tokenId) publicviewvirtualreturns (address) {
_requireOwned(tokenId);
return _getApproved(tokenId);
}
/**
* @dev See {IERC721-setApprovalForAll}.
*/functionsetApprovalForAll(address operator, bool approved) publicvirtual{
_setApprovalForAll(_msgSender(), operator, approved);
}
/**
* @dev See {IERC721-isApprovedForAll}.
*/functionisApprovedForAll(address owner, address operator) publicviewvirtualreturns (bool) {
return _operatorApprovals[owner][operator];
}
/**
* @dev See {IERC721-transferFrom}.
*/functiontransferFrom(addressfrom, address to, uint256 tokenId) publicvirtual{
if (to ==address(0)) {
revert ERC721InvalidReceiver(address(0));
}
// Setting an "auth" arguments enables the `_isAuthorized` check which verifies that the token exists// (from != 0). Therefore, it is not needed to verify that the return value is not 0 here.address previousOwner = _update(to, tokenId, _msgSender());
if (previousOwner !=from) {
revert ERC721IncorrectOwner(from, tokenId, previousOwner);
}
}
/**
* @dev See {IERC721-safeTransferFrom}.
*/functionsafeTransferFrom(addressfrom, address to, uint256 tokenId) public{
safeTransferFrom(from, to, tokenId, "");
}
/**
* @dev See {IERC721-safeTransferFrom}.
*/functionsafeTransferFrom(addressfrom, address to, uint256 tokenId, bytesmemory data) publicvirtual{
transferFrom(from, to, tokenId);
_checkOnERC721Received(from, to, tokenId, data);
}
/**
* @dev Returns the owner of the `tokenId`. Does NOT revert if token doesn't exist
*
* IMPORTANT: Any overrides to this function that add ownership of tokens not tracked by the
* core ERC721 logic MUST be matched with the use of {_increaseBalance} to keep balances
* consistent with ownership. The invariant to preserve is that for any address `a` the value returned by
* `balanceOf(a)` must be equal to the number of tokens such that `_ownerOf(tokenId)` is `a`.
*/function_ownerOf(uint256 tokenId) internalviewvirtualreturns (address);
/**
* @dev Returns the approved address for `tokenId`. Returns 0 if `tokenId` is not minted.
*/function_getApproved(uint256 tokenId) internalviewvirtualreturns (address) {
return _tokenApprovals[tokenId];
}
/**
* @dev Returns whether `spender` is allowed to manage `owner`'s tokens, or `tokenId` in
* particular (ignoring whether it is owned by `owner`).
*
* WARNING: This function assumes that `owner` is the actual owner of `tokenId` and does not verify this
* assumption.
*/function_isAuthorized(address owner, address spender, uint256 tokenId) internalviewvirtualreturns (bool) {
return spender !=address(0)
&& (owner == spender || isApprovedForAll(owner, spender) || _getApproved(tokenId) == spender);
}
/**
* @dev Checks if `spender` can operate on `tokenId`, assuming the provided `owner` is the actual owner.
* Reverts if `spender` does not have approval from the provided `owner` for the given token or for all its assets
* the `spender` for the specific `tokenId`.
*
* WARNING: This function assumes that `owner` is the actual owner of `tokenId` and does not verify this
* assumption.
*/function_checkAuthorized(address owner, address spender, uint256 tokenId) internalviewvirtual{
if (!_isAuthorized(owner, spender, tokenId)) {
if (owner ==address(0)) {
revert ERC721NonexistentToken(tokenId);
} else {
revert ERC721InsufficientApproval(spender, tokenId);
}
}
}
/**
* @dev Unsafe write access to the balances, used by extensions that "mint" tokens using an {ownerOf} override.
*
* NOTE: the value is limited to type(uint128).max. This protect against _balance overflow. It is unrealistic that
* a uint256 would ever overflow from increments when these increments are bounded to uint128 values.
*
* WARNING: Increasing an account's balance using this function tends to be paired with an override of the
* {_ownerOf} function to resolve the ownership of the corresponding tokens so that balances and ownership
* remain consistent with one another.
*/function_increaseBalance(address account, uint128 value) internalvirtual{
unchecked {
_balances[account] += value;
}
}
/**
* @dev Transfers `tokenId` from its current owner to `to`, or alternatively mints (or burns) if the current owner
* (or `to`) is the zero address. Returns the owner of the `tokenId` before the update.
*
* The `auth` argument is optional. If the value passed is non 0, then this function will check that
* `auth` is either the owner of the token, or approved to operate on the token (by the owner).
*
* Emits a {Transfer} event.
*
* NOTE: If overriding this function in a way that tracks balances, see also {_increaseBalance}.
*/function_update(address to, uint256 tokenId, address auth) internalvirtualreturns (address) {
addressfrom= _ownerOf(tokenId);
// Perform (optional) operator checkif (auth !=address(0)) {
_checkAuthorized(from, auth, tokenId);
}
// Execute the updateif (from!=address(0)) {
// Clear approval. No need to re-authorize or emit the Approval event
_approve(address(0), tokenId, address(0), false);
unchecked {
_balances[from] -=1;
}
}
if (to !=address(0)) {
unchecked {
_balances[to] +=1;
}
}
// @dev MODIFIED: Define _setOwner
_setOwner(tokenId, to);
emit Transfer(from, to, tokenId);
returnfrom;
}
/**
* @dev Mints `tokenId` and transfers it to `to`.
*
* WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible
*
* Requirements:
*
* - `tokenId` must not exist.
* - `to` cannot be the zero address.
*
* Emits a {Transfer} event.
*/function_mint(address to, uint256 tokenId) internal{
if (to ==address(0)) {
revert ERC721InvalidReceiver(address(0));
}
address previousOwner = _update(to, tokenId, address(0));
if (previousOwner !=address(0)) {
revert ERC721InvalidSender(address(0));
}
}
/**
* @dev Mints `tokenId`, transfers it to `to` and checks for `to` acceptance.
*
* Requirements:
*
* - `tokenId` must not exist.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.
*
* Emits a {Transfer} event.
*/function_safeMint(address to, uint256 tokenId) internal{
_safeMint(to, tokenId, "");
}
/**
* @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is
* forwarded in {IERC721Receiver-onERC721Received} to contract recipients.
*/function_safeMint(address to, uint256 tokenId, bytesmemory data) internalvirtual{
_mint(to, tokenId);
_checkOnERC721Received(address(0), to, tokenId, data);
}
/**
* @dev Destroys `tokenId`.
* The approval is cleared when the token is burned.
* This is an internal function that does not check if the sender is authorized to operate on the token.
*
* Requirements:
*
* - `tokenId` must exist.
*
* Emits a {Transfer} event.
*/function_burn(uint256 tokenId) internal{
address previousOwner = _update(address(0), tokenId, address(0));
if (previousOwner ==address(0)) {
revert ERC721NonexistentToken(tokenId);
}
}
/**
* @dev Transfers `tokenId` from `from` to `to`.
* As opposed to {transferFrom}, this imposes no restrictions on msg.sender.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - `tokenId` token must be owned by `from`.
*
* Emits a {Transfer} event.
*/function_transfer(addressfrom, address to, uint256 tokenId) internal{
if (to ==address(0)) {
revert ERC721InvalidReceiver(address(0));
}
address previousOwner = _update(to, tokenId, address(0));
if (previousOwner ==address(0)) {
revert ERC721NonexistentToken(tokenId);
} elseif (previousOwner !=from) {
revert ERC721IncorrectOwner(from, tokenId, previousOwner);
}
}
/**
* @dev Safely transfers `tokenId` token from `from` to `to`, checking that contract recipients
* are aware of the ERC721 standard to prevent tokens from being forever locked.
*
* `data` is additional data, it has no specified format and it is sent in call to `to`.
*
* This internal function is like {safeTransferFrom} in the sense that it invokes
* {IERC721Receiver-onERC721Received} on the receiver, and can be used to e.g.
* implement alternative mechanisms to perform token transfer, such as signature-based.
*
* Requirements:
*
* - `tokenId` token must exist and be owned by `from`.
* - `to` cannot be the zero address.
* - `from` 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.
*/function_safeTransfer(addressfrom, address to, uint256 tokenId) internal{
_safeTransfer(from, to, tokenId, "");
}
/**
* @dev Same as {xref-ERC721-_safeTransfer-address-address-uint256-}[`_safeTransfer`], with an additional `data` parameter which is
* forwarded in {IERC721Receiver-onERC721Received} to contract recipients.
*/function_safeTransfer(addressfrom, address to, uint256 tokenId, bytesmemory data) internalvirtual{
_transfer(from, to, tokenId);
_checkOnERC721Received(from, to, tokenId, data);
}
/**
* @dev Approve `to` to operate on `tokenId`
*
* The `auth` argument is optional. If the value passed is non 0, then this function will check that `auth` is
* either the owner of the token, or approved to operate on all tokens held by this owner.
*
* Emits an {Approval} event.
*
* Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument.
*/function_approve(address to, uint256 tokenId, address auth) internal{
_approve(to, tokenId, auth, true);
}
/**
* @dev Variant of `_approve` with an optional flag to enable or disable the {Approval} event. The event is not
* emitted in the context of transfers.
*/function_approve(address to, uint256 tokenId, address auth, bool emitEvent) internalvirtual{
// Avoid reading the owner unless necessaryif (emitEvent || auth !=address(0)) {
address owner = _requireOwned(tokenId);
// We do not use _isAuthorized because single-token approvals should not be able to call approveif (auth !=address(0) && owner != auth &&!isApprovedForAll(owner, auth)) {
revert ERC721InvalidApprover(auth);
}
if (emitEvent) {
emit Approval(owner, to, tokenId);
}
}
_tokenApprovals[tokenId] = to;
}
/**
* @dev Approve `operator` to operate on all of `owner` tokens
*
* Requirements:
* - operator can't be the address zero.
*
* Emits an {ApprovalForAll} event.
*/function_setApprovalForAll(address owner, address operator, bool approved) internalvirtual{
if (operator ==address(0)) {
revert ERC721InvalidOperator(operator);
}
_operatorApprovals[owner][operator] = approved;
emit ApprovalForAll(owner, operator, approved);
}
/**
* @dev Reverts if the `tokenId` doesn't have a current owner (it hasn't been minted, or it has been burned).
* Returns the owner.
*
* Overrides to ownership logic should be done to {_ownerOf}.
*/function_requireOwned(uint256 tokenId) internalviewreturns (address) {
address owner = _ownerOf(tokenId);
if (owner ==address(0)) {
revert ERC721NonexistentToken(tokenId);
}
return owner;
}
/**
* @dev Private function to invoke {IERC721Receiver-onERC721Received} on a target address. This will revert if the
* recipient doesn't accept the token transfer. The call is not executed if the target address is not a contract.
*
* @param from address representing the previous owner of the given token ID
* @param to target address that will receive the tokens
* @param tokenId uint256 ID of the token to be transferred
* @param data bytes optional data to send along with the call
*/function_checkOnERC721Received(addressfrom, address to, uint256 tokenId, bytesmemory data) private{
if (to.code.length>0) {
try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, data) returns (bytes4 retval) {
if (retval != IERC721Receiver.onERC721Received.selector) {
revert ERC721InvalidReceiver(to);
}
} catch (bytesmemory reason) {
if (reason.length==0) {
revert ERC721InvalidReceiver(to);
} else {
/// @solidity memory-safe-assemblyassembly {
revert(add(32, reason), mload(reason))
}
}
}
}
}
/**
* @dev Override this function to set owner
*/function_setOwner(uint256 tokenId, address owner) internalvirtual;
}
// SPDX-License-Identifier: MITpragmasolidity ^0.8.20;import {Lockers} from"./Lockers.sol";
import {IBookManager} from"../interfaces/IBookManager.sol";
import {IHooks} from"../interfaces/IHooks.sol";
import {OrderId} from"../libraries/OrderId.sol";
/// @author Clober/// @author Modified from Uniswap V4 (https://github.com/Uniswap/v4-core/blob/1f350fa95e862ba8c56c8ff7e146d47c9043465e)/// @notice V4 decides whether to invoke specific hooks by inspecting the leading bits of the address that/// the hooks contract is deployed to./// For example, a hooks contract deployed to address: 0x9000000000000000000000000000000000000000/// has leading bits '1001' which would cause the 'before open' and 'after make' hooks to be used.libraryHooks{
usingHooksforIHooks;
uint256internalconstant BEFORE_OPEN_FLAG =1<<159;
uint256internalconstant AFTER_OPEN_FLAG =1<<158;
uint256internalconstant BEFORE_MAKE_FLAG =1<<157;
uint256internalconstant AFTER_MAKE_FLAG =1<<156;
uint256internalconstant BEFORE_TAKE_FLAG =1<<155;
uint256internalconstant AFTER_TAKE_FLAG =1<<154;
uint256internalconstant BEFORE_CANCEL_FLAG =1<<153;
uint256internalconstant AFTER_CANCEL_FLAG =1<<152;
uint256internalconstant BEFORE_CLAIM_FLAG =1<<151;
uint256internalconstant AFTER_CLAIM_FLAG =1<<150;
structPermissions {
bool beforeOpen;
bool afterOpen;
bool beforeMake;
bool afterMake;
bool beforeTake;
bool afterTake;
bool beforeCancel;
bool afterCancel;
bool beforeClaim;
bool afterClaim;
}
/// @notice Thrown if the address will not lead to the specified hook calls being called/// @param hooks The address of the hooks contracterrorHookAddressNotValid(address hooks);
/// @notice Hook did not return its selectorerrorInvalidHookResponse();
/// @notice thrown when a hook call failserrorFailedHookCall();
/// @notice Utility function intended to be used in hook constructors to ensure/// the deployed hooks address causes the intended hooks to be called/// @param permissions The hooks that are intended to be called/// @dev permissions param is memory as the function will be called from constructorsfunctionvalidateHookPermissions(IHooks self, Permissions memory permissions) internalpure{
if (
permissions.beforeOpen !=self.hasPermission(BEFORE_OPEN_FLAG)
|| permissions.afterOpen !=self.hasPermission(AFTER_OPEN_FLAG)
|| permissions.beforeMake !=self.hasPermission(BEFORE_MAKE_FLAG)
|| permissions.afterMake !=self.hasPermission(AFTER_MAKE_FLAG)
|| permissions.beforeTake !=self.hasPermission(BEFORE_TAKE_FLAG)
|| permissions.afterTake !=self.hasPermission(AFTER_TAKE_FLAG)
|| permissions.beforeCancel !=self.hasPermission(BEFORE_CANCEL_FLAG)
|| permissions.afterCancel !=self.hasPermission(AFTER_CANCEL_FLAG)
|| permissions.beforeClaim !=self.hasPermission(BEFORE_CLAIM_FLAG)
|| permissions.afterClaim !=self.hasPermission(AFTER_CLAIM_FLAG)
) {
revert HookAddressNotValid(address(self));
}
}
/// @notice Ensures that the hook address includes at least one hook flag or is the 0 address/// @param hook The hook to verifyfunctionisValidHookAddress(IHooks hook) internalpurereturns (bool) {
// If a hook contract is set, it must have at least 1 flag setreturnaddress(hook) ==address(0) ||uint160(address(hook)) >= AFTER_CLAIM_FLAG;
}
/// @notice performs a hook call using the given calldata on the given hook/// @return expectedSelector The selector that the hook is expected to return/// @return selector The selector that the hook actually returnedfunction_callHook(IHooks self, bytesmemory data) privatereturns (bytes4 expectedSelector, bytes4 selector) {
bool set = Lockers.setCurrentHook(self);
assembly {
expectedSelector :=mload(add(data, 0x20))
}
(bool success, bytesmemory result) =address(self).call(data);
if (!success) _revert(result);
selector =abi.decode(result, (bytes4));
// We only want to clear the current hook if it was set in setCurrentHook in this execution frame.if (set) Lockers.clearCurrentHook();
}
/// @notice performs a hook call using the given calldata on the given hookfunctioncallHook(IHooks self, bytesmemory data) internal{
(bytes4 expectedSelector, bytes4 selector) = _callHook(self, data);
if (selector != expectedSelector) revert InvalidHookResponse();
}
/// @notice calls beforeOpen hook if permissioned and validates return valuefunctionbeforeOpen(IHooks self, IBookManager.BookKey memory key, bytescalldata hookData) internal{
if (self.hasPermission(BEFORE_OPEN_FLAG)) {
self.callHook(abi.encodeWithSelector(IHooks.beforeOpen.selector, msg.sender, key, hookData));
}
}
/// @notice calls afterOpen hook if permissioned and validates return valuefunctionafterOpen(IHooks self, IBookManager.BookKey memory key, bytescalldata hookData) internal{
if (self.hasPermission(AFTER_OPEN_FLAG)) {
self.callHook(abi.encodeWithSelector(IHooks.afterOpen.selector, msg.sender, key, hookData));
}
}
/// @notice calls beforeMake hook if permissioned and validates return valuefunctionbeforeMake(IHooks self, IBookManager.MakeParams memory params, bytescalldata hookData) internal{
if (self.hasPermission(BEFORE_MAKE_FLAG)) {
self.callHook(abi.encodeWithSelector(IHooks.beforeMake.selector, msg.sender, params, hookData));
}
}
/// @notice calls afterMake hook if permissioned and validates return valuefunctionafterMake(IHooks self, IBookManager.MakeParams memory params, OrderId orderId, bytescalldata hookData)
internal{
if (self.hasPermission(AFTER_MAKE_FLAG)) {
self.callHook(abi.encodeWithSelector(IHooks.afterMake.selector, msg.sender, params, orderId, hookData));
}
}
/// @notice calls beforeTake hook if permissioned and validates return valuefunctionbeforeTake(IHooks self, IBookManager.TakeParams memory params, bytescalldata hookData) internal{
if (self.hasPermission(BEFORE_TAKE_FLAG)) {
self.callHook(abi.encodeWithSelector(IHooks.beforeTake.selector, msg.sender, params, hookData));
}
}
/// @notice calls afterTake hook if permissioned and validates return valuefunctionafterTake(IHooks self, IBookManager.TakeParams memory params, uint64 takenAmount, bytescalldata hookData)
internal{
if (self.hasPermission(AFTER_TAKE_FLAG)) {
self.callHook(abi.encodeWithSelector(IHooks.afterTake.selector, msg.sender, params, takenAmount, hookData));
}
}
/// @notice calls beforeCancel hook if permissioned and validates return valuefunctionbeforeCancel(IHooks self, IBookManager.CancelParams calldata params, bytescalldata hookData) internal{
if (self.hasPermission(BEFORE_CANCEL_FLAG)) {
self.callHook(abi.encodeWithSelector(IHooks.beforeCancel.selector, msg.sender, params, hookData));
}
}
/// @notice calls afterCancel hook if permissioned and validates return valuefunctionafterCancel(
IHooks self,
IBookManager.CancelParams calldata params,
uint64 canceledAmount,
bytescalldata hookData
) internal{
if (self.hasPermission(AFTER_CANCEL_FLAG)) {
self.callHook(
abi.encodeWithSelector(IHooks.afterCancel.selector, msg.sender, params, canceledAmount, hookData)
);
}
}
/// @notice calls beforeClaim hook if permissioned and validates return valuefunctionbeforeClaim(IHooks self, OrderId orderId, bytescalldata hookData) internal{
if (self.hasPermission(BEFORE_CLAIM_FLAG)) {
self.callHook(abi.encodeWithSelector(IHooks.beforeClaim.selector, msg.sender, orderId, hookData));
}
}
/// @notice calls afterClaim hook if permissioned and validates return valuefunctionafterClaim(IHooks self, OrderId orderId, uint64 claimedAmount, bytescalldata hookData) internal{
if (self.hasPermission(AFTER_CLAIM_FLAG)) {
self.callHook(
abi.encodeWithSelector(IHooks.afterClaim.selector, msg.sender, orderId, claimedAmount, hookData)
);
}
}
functionhasPermission(IHooks self, uint256 flag) internalpurereturns (bool) {
returnuint256(uint160(address(self))) & flag !=0;
}
/// @notice bubble up revert if present. Else throw FailedHookCallfunction_revert(bytesmemory result) privatepure{
if (result.length==0) revert FailedHookCall();
assembly {
revert(add(0x20, result), mload(result))
}
}
}
Contract Source Code
File 15 of 44: IBookManager.sol
// SPDX-License-Identifier: MITpragmasolidity ^0.8.0;import {IERC721Metadata} from"@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol";
import {BookId} from"../libraries/BookId.sol";
import {Currency} from"../libraries/Currency.sol";
import {OrderId} from"../libraries/OrderId.sol";
import {Tick} from"../libraries/Tick.sol";
import {FeePolicy} from"../libraries/FeePolicy.sol";
import {IERC721Permit} from"./IERC721Permit.sol";
import {IHooks} from"./IHooks.sol";
/**
* @title IBookManager
* @notice The interface for the BookManager contract
*/interfaceIBookManagerisIERC721Metadata, IERC721Permit{
errorInvalidUnitSize();
errorInvalidFeePolicy();
errorInvalidProvider(address provider);
errorLockedBy(address locker, address hook);
errorCurrencyNotSettled();
/**
* @notice Event emitted when a new book is opened
* @param id The book id
* @param base The base currency
* @param quote The quote currency
* @param unitSize The unit size of the book
* @param makerPolicy The maker fee policy
* @param takerPolicy The taker fee policy
* @param hooks The hooks contract
*/eventOpen(
BookId indexed id,
Currency indexed base,
Currency indexed quote,
uint64 unitSize,
FeePolicy makerPolicy,
FeePolicy takerPolicy,
IHooks hooks
);
/**
* @notice Event emitted when a new order is made
* @param bookId The book id
* @param user The user address
* @param tick The order tick
* @param orderIndex The order index
* @param unit The order unit
* @param provider The provider address
*/eventMake(
BookId indexed bookId, addressindexed user, Tick tick, uint256 orderIndex, uint64 unit, address provider
);
/**
* @notice Event emitted when an order is taken
* @param bookId The book id
* @param user The user address
* @param tick The order tick
* @param unit The order unit
*/eventTake(BookId indexed bookId, addressindexed user, Tick tick, uint64 unit);
/**
* @notice Event emitted when an order is canceled
* @param orderId The order id
* @param unit The canceled unit
*/eventCancel(OrderId indexed orderId, uint64 unit);
/**
* @notice Event emitted when an order is claimed
* @param orderId The order id
* @param unit The claimed unit
*/eventClaim(OrderId indexed orderId, uint64 unit);
/**
* @notice Event emitted when a provider is whitelisted
* @param provider The provider address
*/eventWhitelist(addressindexed provider);
/**
* @notice Event emitted when a provider is delisted
* @param provider The provider address
*/eventDelist(addressindexed provider);
/**
* @notice Event emitted when a provider collects fees
* @param provider The provider address
* @param recipient The recipient address
* @param currency The currency
* @param amount The collected amount
*/eventCollect(addressindexed provider, addressindexed recipient, Currency indexed currency, uint256 amount);
/**
* @notice Event emitted when new default provider is set
* @param newDefaultProvider The new default provider address
*/eventSetDefaultProvider(addressindexed newDefaultProvider);
/**
* @notice This structure represents a unique identifier for a book in the BookManager.
* @param base The base currency of the book
* @param unitSize The unit size of the book
* @param quote The quote currency of the book
* @param makerPolicy The maker fee policy of the book
* @param hooks The hooks contract of the book
* @param takerPolicy The taker fee policy of the book
*/structBookKey {
Currency base;
uint64 unitSize;
Currency quote;
FeePolicy makerPolicy;
IHooks hooks;
FeePolicy takerPolicy;
}
/**
* @notice Returns the base URI
* @return The base URI
*/functionbaseURI() externalviewreturns (stringmemory);
/**
* @notice Returns the contract URI
* @return The contract URI
*/functioncontractURI() externalviewreturns (stringmemory);
/**
* @notice Returns the default provider
* @return The default provider
*/functiondefaultProvider() externalviewreturns (address);
/**
* @notice Returns the total reserves of a given currency
* @param currency The currency in question
* @return The total reserves amount
*/functionreservesOf(Currency currency) externalviewreturns (uint256);
/**
* @notice Checks if a provider is whitelisted
* @param provider The address of the provider
* @return True if the provider is whitelisted, false otherwise
*/functionisWhitelisted(address provider) externalviewreturns (bool);
/**
* @notice Verifies if an owner has authorized a spender for a token
* @param owner The address of the token owner
* @param spender The address of the spender
* @param tokenId The token ID
*/functioncheckAuthorized(address owner, address spender, uint256 tokenId) externalview;
/**
* @notice Calculates the amount owed to a provider in a given currency
* @param provider The provider's address
* @param currency The currency in question
* @return The owed amount
*/functiontokenOwed(address provider, Currency currency) externalviewreturns (uint256);
/**
* @notice Calculates the currency balance changes for a given locker
* @param locker The address of the locker
* @param currency The currency in question
* @return The net change in currency balance
*/functiongetCurrencyDelta(address locker, Currency currency) externalviewreturns (int256);
/**
* @notice Retrieves the book key for a given book ID
* @param id The book ID
* @return The book key
*/functiongetBookKey(BookId id) externalviewreturns (BookKey memory);
/**
* @notice This structure represents a current status for an order in the BookManager.
* @param provider The provider of the order
* @param open The open unit of the order
* @param claimable The claimable unit of the order
*/structOrderInfo {
address provider;
uint64 open;
uint64 claimable;
}
/**
* @notice Provides information about an order
* @param id The order ID
* @return Order information including provider, open status, and claimable unit
*/functiongetOrder(OrderId id) externalviewreturns (OrderInfo memory);
/**
* @notice Retrieves the locker and caller addresses for a given lock
* @param i The index of the lock
* @return locker The locker's address
* @return lockCaller The caller's address
*/functiongetLock(uint256 i) externalviewreturns (address locker, address lockCaller);
/**
* @notice Provides the lock data
* @return The lock data including necessary numeric values
*/functiongetLockData() externalviewreturns (uint128, uint128);
/**
* @notice Returns the depth of a given book ID and tick
* @param id The book ID
* @param tick The tick
* @return The depth of the tick
*/functiongetDepth(BookId id, Tick tick) externalviewreturns (uint64);
/**
* @notice Retrieves the highest tick for a given book ID
* @param id The book ID
* @return tick The highest tick
*/functiongetHighest(BookId id) externalviewreturns (Tick tick);
/**
* @notice Finds the maximum tick less than a specified tick in a book
* @dev Returns `Tick.wrap(type(int24).min)` if the specified tick is the lowest
* @param id The book ID
* @param tick The specified tick
* @return The next lower tick
*/functionmaxLessThan(BookId id, Tick tick) externalviewreturns (Tick);
/**
* @notice Checks if a book is opened
* @param id The book ID
* @return True if the book is opened, false otherwise
*/functionisOpened(BookId id) externalviewreturns (bool);
/**
* @notice Checks if a book is empty
* @param id The book ID
* @return True if the book is empty, false otherwise
*/functionisEmpty(BookId id) externalviewreturns (bool);
/**
* @notice Encodes a BookKey into a BookId
* @param key The BookKey to encode
* @return The encoded BookId
*/functionencodeBookKey(BookKey calldata key) externalpurereturns (BookId);
/**
* @notice Loads a value from a specific storage slot
* @param slot The storage slot
* @return The value in the slot
*/functionload(bytes32 slot) externalviewreturns (bytes32);
/**
* @notice Loads a sequence of values starting from a specific slot
* @param startSlot The starting slot
* @param nSlot The number of slots to load
* @return The sequence of values
*/functionload(bytes32 startSlot, uint256 nSlot) externalviewreturns (bytesmemory);
/**
* @notice Opens a new book
* @param key The book key
* @param hookData The hook data
*/functionopen(BookKey calldata key, bytescalldata hookData) external;
/**
* @notice Locks a book manager function
* @param locker The locker address
* @param data The lock data
* @return The lock return data
*/functionlock(address locker, bytescalldata data) externalreturns (bytesmemory);
/**
* @notice This structure represents the parameters for making an order.
* @param key The book key for the order
* @param tick The tick for the order
* @param unit The unit for the order. Times key.unitSize to get actual bid amount.
* @param provider The provider for the order. The limit order service provider address to collect fees.
*/structMakeParams {
BookKey key;
Tick tick;
uint64 unit;
address provider;
}
/**
* @notice Make a limit order
* @param params The order parameters
* @param hookData The hook data
* @return id The order id. Returns 0 if the order is not settled
* @return quoteAmount The amount of quote currency to be paid
*/functionmake(MakeParams calldata params, bytescalldata hookData)
externalreturns (OrderId id, uint256 quoteAmount);
/**
* @notice This structure represents the parameters for taking orders in the specified tick.
* @param key The book key for the order
* @param tick The tick for the order
* @param maxUnit The max unit to take
*/structTakeParams {
BookKey key;
Tick tick;
uint64 maxUnit;
}
/**
* @notice Take a limit order at specific tick
* @param params The order parameters
* @param hookData The hook data
* @return quoteAmount The amount of quote currency to be received
* @return baseAmount The amount of base currency to be paid
*/functiontake(TakeParams calldata params, bytescalldata hookData)
externalreturns (uint256 quoteAmount, uint256 baseAmount);
/**
* @notice This structure represents the parameters for canceling an order.
* @param id The order id for the order
* @param toUnit The remaining open unit for the order after cancellation. Must not exceed the current open unit.
*/structCancelParams {
OrderId id;
uint64 toUnit;
}
/**
* @notice Cancel a limit order
* @param params The order parameters
* @param hookData The hook data
* @return canceledAmount The amount of quote currency canceled
*/functioncancel(CancelParams calldata params, bytescalldata hookData) externalreturns (uint256 canceledAmount);
/**
* @notice Claims an order
* @param id The order ID
* @param hookData The hook data
* @return claimedAmount The amount claimed
*/functionclaim(OrderId id, bytescalldata hookData) externalreturns (uint256 claimedAmount);
/**
* @notice Collects fees from a provider
* @param recipient The recipient address
* @param currency The currency
* @return The collected amount
*/functioncollect(address recipient, Currency currency) externalreturns (uint256);
/**
* @notice Withdraws a currency
* @param currency The currency
* @param to The recipient address
* @param amount The amount
*/functionwithdraw(Currency currency, address to, uint256 amount) external;
/**
* @notice Settles a currency
* @param currency The currency
* @return The settled amount
*/functionsettle(Currency currency) externalpayablereturns (uint256);
/**
* @notice Whitelists a provider
* @param provider The provider address
*/functionwhitelist(address provider) external;
/**
* @notice Delists a provider
* @param provider The provider address
*/functiondelist(address provider) external;
/**
* @notice Sets the default provider
* @param newDefaultProvider The new default provider address
*/functionsetDefaultProvider(address newDefaultProvider) external;
}
Contract Source Code
File 16 of 44: IERC1271.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC1271.sol)pragmasolidity ^0.8.20;/**
* @dev Interface of the ERC-1271 standard signature validation method for
* contracts as defined in https://eips.ethereum.org/EIPS/eip-1271[ERC-1271].
*/interfaceIERC1271{
/**
* @dev Should return whether the signature provided is valid for the provided data
* @param hash Hash of the data to be signed
* @param signature Signature byte array associated with _data
*/functionisValidSignature(bytes32 hash, bytesmemory signature) externalviewreturns (bytes4 magicValue);
}
Contract Source Code
File 17 of 44: IERC165.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v5.0.0) (utils/introspection/IERC165.sol)pragmasolidity ^0.8.20;/**
* @dev Interface of the ERC-165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[ERC].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/interfaceIERC165{
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/functionsupportsInterface(bytes4 interfaceId) externalviewreturns (bool);
}
Contract Source Code
File 18 of 44: IERC20.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)pragmasolidity ^0.8.20;/**
* @dev Interface of the ERC-20 standard as defined in the ERC.
*/interfaceIERC20{
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/eventTransfer(addressindexedfrom, addressindexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/eventApproval(addressindexed owner, addressindexed spender, uint256 value);
/**
* @dev Returns the value of tokens in existence.
*/functiontotalSupply() externalviewreturns (uint256);
/**
* @dev Returns the value of tokens owned by `account`.
*/functionbalanceOf(address account) externalviewreturns (uint256);
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/functiontransfer(address to, uint256 value) externalreturns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/functionallowance(address owner, address spender) externalviewreturns (uint256);
/**
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the
* caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/functionapprove(address spender, uint256 value) externalreturns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the
* allowance mechanism. `value` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/functiontransferFrom(addressfrom, address to, uint256 value) externalreturns (bool);
}
Contract Source Code
File 19 of 44: IERC5267.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC5267.sol)pragmasolidity ^0.8.20;interfaceIERC5267{
/**
* @dev MAY be emitted to signal that the domain could have changed.
*/eventEIP712DomainChanged();
/**
* @dev returns the fields and values that describe the domain separator used by this contract for EIP-712
* signature.
*/functioneip712Domain()
externalviewreturns (bytes1 fields,
stringmemory name,
stringmemory version,
uint256 chainId,
address verifyingContract,
bytes32 salt,
uint256[] memory extensions
);
}
Contract Source Code
File 20 of 44: IERC721.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/IERC721.sol)pragmasolidity ^0.8.20;import {IERC165} from"../../utils/introspection/IERC165.sol";
/**
* @dev Required interface of an ERC-721 compliant contract.
*/interfaceIERC721isIERC165{
/**
* @dev Emitted when `tokenId` token is transferred from `from` to `to`.
*/eventTransfer(addressindexedfrom, addressindexed to, uint256indexed tokenId);
/**
* @dev Emitted when `owner` enables `approved` to manage the `tokenId` token.
*/eventApproval(addressindexed owner, addressindexed approved, uint256indexed tokenId);
/**
* @dev Emitted when `owner` enables or disables (`approved`) `operator` to manage all of its assets.
*/eventApprovalForAll(addressindexed owner, addressindexed operator, bool approved);
/**
* @dev Returns the number of tokens in ``owner``'s account.
*/functionbalanceOf(address owner) externalviewreturns (uint256 balance);
/**
* @dev Returns the owner of the `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/functionownerOf(uint256 tokenId) externalviewreturns (address owner);
/**
* @dev Safely transfers `tokenId` token from `from` to `to`.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon
* a safe transfer.
*
* Emits a {Transfer} event.
*/functionsafeTransferFrom(addressfrom, address to, uint256 tokenId, bytescalldata data) external;
/**
* @dev Safely transfers `tokenId` token from `from` to `to`, checking first that contract recipients
* are aware of the ERC-721 protocol to prevent tokens from being forever locked.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must exist and be owned by `from`.
* - If the caller is not `from`, it must have been allowed to move this token by either {approve} or
* {setApprovalForAll}.
* - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon
* a safe transfer.
*
* Emits a {Transfer} event.
*/functionsafeTransferFrom(addressfrom, address to, uint256 tokenId) external;
/**
* @dev Transfers `tokenId` token from `from` to `to`.
*
* WARNING: Note that the caller is responsible to confirm that the recipient is capable of receiving ERC-721
* or else they may be permanently lost. Usage of {safeTransferFrom} prevents loss, though the caller must
* understand this adds an external call which potentially creates a reentrancy vulnerability.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `tokenId` token must be owned by `from`.
* - If the caller is not `from`, it must be approved to move this token by either {approve} or {setApprovalForAll}.
*
* Emits a {Transfer} event.
*/functiontransferFrom(addressfrom, address to, uint256 tokenId) external;
/**
* @dev Gives permission to `to` to transfer `tokenId` token to another account.
* The approval is cleared when the token is transferred.
*
* Only a single account can be approved at a time, so approving the zero address clears previous approvals.
*
* Requirements:
*
* - The caller must own the token or be an approved operator.
* - `tokenId` must exist.
*
* Emits an {Approval} event.
*/functionapprove(address to, uint256 tokenId) external;
/**
* @dev Approve or remove `operator` as an operator for the caller.
* Operators can call {transferFrom} or {safeTransferFrom} for any token owned by the caller.
*
* Requirements:
*
* - The `operator` cannot be the address zero.
*
* Emits an {ApprovalForAll} event.
*/functionsetApprovalForAll(address operator, bool approved) external;
/**
* @dev Returns the account approved for `tokenId` token.
*
* Requirements:
*
* - `tokenId` must exist.
*/functiongetApproved(uint256 tokenId) externalviewreturns (address operator);
/**
* @dev Returns if the `operator` is allowed to manage all of the assets of `owner`.
*
* See {setApprovalForAll}
*/functionisApprovedForAll(address owner, address operator) externalviewreturns (bool);
}
// SPDX-License-Identifier: MITpragmasolidity ^0.8.0;import {IERC721} from"@openzeppelin/contracts/token/ERC721/IERC721.sol";
/**
* @title IERC721Permit
* @notice An interface for the ERC721 permit extension
*/interfaceIERC721PermitisIERC721{
errorInvalidSignature();
errorPermitExpired();
/**
* @notice The EIP-712 typehash for the permit struct used by the contract
*/functionPERMIT_TYPEHASH() externalpurereturns (bytes32);
/**
* @notice The EIP-712 domain separator for this contract
*/functionDOMAIN_SEPARATOR() externalviewreturns (bytes32);
/**
* @notice Approve the spender to transfer the given tokenId
* @param spender The address to approve
* @param tokenId The tokenId to approve
* @param deadline The deadline for the signature
* @param v The recovery id of the signature
* @param r The r value of the signature
* @param s The s value of the signature
*/functionpermit(address spender, uint256 tokenId, uint256 deadline, uint8 v, bytes32 r, bytes32 s) external;
/**
* @notice Get the current nonce for a token
* @param tokenId The tokenId to get the nonce for
* @return The current nonce
*/functionnonces(uint256 tokenId) externalviewreturns (uint256);
}
Contract Source Code
File 23 of 44: IERC721Receiver.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC721/IERC721Receiver.sol)pragmasolidity ^0.8.20;/**
* @title ERC-721 token receiver interface
* @dev Interface for any contract that wants to support safeTransfers
* from ERC-721 asset contracts.
*/interfaceIERC721Receiver{
/**
* @dev Whenever an {IERC721} `tokenId` token is transferred to this contract via {IERC721-safeTransferFrom}
* by `operator` from `from`, this function is called.
*
* It must return its Solidity selector to confirm the token transfer.
* If any other value is returned or the interface is not implemented by the recipient, the transfer will be
* reverted.
*
* The selector can be obtained in Solidity with `IERC721Receiver.onERC721Received.selector`.
*/functiononERC721Received(address operator,
addressfrom,
uint256 tokenId,
bytescalldata data
) externalreturns (bytes4);
}
Contract Source Code
File 24 of 44: IHooks.sol
// SPDX-License-Identifier: MITpragmasolidity ^0.8.20;import {IBookManager} from"./IBookManager.sol";
import {OrderId} from"../libraries/OrderId.sol";
/**
* @title IHooks
* @notice Interface for the hooks contract
*/interfaceIHooks{
/**
* @notice Hook called before opening a new book
* @param sender The sender of the open transaction
* @param key The key of the book being opened
* @param hookData The data passed to the hook
* @return Returns the function selector if the hook is successful
*/functionbeforeOpen(address sender, IBookManager.BookKey calldata key, bytescalldata hookData)
externalreturns (bytes4);
/**
* @notice Hook called after opening a new book
* @param sender The sender of the open transaction
* @param key The key of the book being opened
* @param hookData The data passed to the hook
* @return Returns the function selector if the hook is successful
*/functionafterOpen(address sender, IBookManager.BookKey calldata key, bytescalldata hookData)
externalreturns (bytes4);
/**
* @notice Hook called before making a new order
* @param sender The sender of the make transaction
* @param params The parameters of the make transaction
* @param hookData The data passed to the hook
* @return Returns the function selector if the hook is successful
*/functionbeforeMake(address sender, IBookManager.MakeParams calldata params, bytescalldata hookData)
externalreturns (bytes4);
/**
* @notice Hook called after making a new order
* @param sender The sender of the make transaction
* @param params The parameters of the make transaction
* @param orderId The id of the order that was made
* @param hookData The data passed to the hook
* @return Returns the function selector if the hook is successful
*/functionafterMake(address sender,
IBookManager.MakeParams calldata params,
OrderId orderId,
bytescalldata hookData
) externalreturns (bytes4);
/**
* @notice Hook called before taking an order
* @param sender The sender of the take transaction
* @param params The parameters of the take transaction
* @param hookData The data passed to the hook
* @return Returns the function selector if the hook is successful
*/functionbeforeTake(address sender, IBookManager.TakeParams calldata params, bytescalldata hookData)
externalreturns (bytes4);
/**
* @notice Hook called after taking an order
* @param sender The sender of the take transaction
* @param params The parameters of the take transaction
* @param takenUnit The unit that was taken
* @param hookData The data passed to the hook
* @return Returns the function selector if the hook is successful
*/functionafterTake(address sender,
IBookManager.TakeParams calldata params,
uint64 takenUnit,
bytescalldata hookData
) externalreturns (bytes4);
/**
* @notice Hook called before canceling an order
* @param sender The sender of the cancel transaction
* @param params The parameters of the cancel transaction
* @param hookData The data passed to the hook
* @return Returns the function selector if the hook is successful
*/functionbeforeCancel(address sender, IBookManager.CancelParams calldata params, bytescalldata hookData)
externalreturns (bytes4);
/**
* @notice Hook called after canceling an order
* @param sender The sender of the cancel transaction
* @param params The parameters of the cancel transaction
* @param canceledUnit The unit that was canceled
* @param hookData The data passed to the hook
* @return Returns the function selector if the hook is successful
*/functionafterCancel(address sender,
IBookManager.CancelParams calldata params,
uint64 canceledUnit,
bytescalldata hookData
) externalreturns (bytes4);
/**
* @notice Hook called before claiming an order
* @param sender The sender of the claim transaction
* @param orderId The id of the order being claimed
* @param hookData The data passed to the hook
* @return Returns the function selector if the hook is successful
*/functionbeforeClaim(address sender, OrderId orderId, bytescalldata hookData) externalreturns (bytes4);
/**
* @notice Hook called after claiming an order
* @param sender The sender of the claim transaction
* @param orderId The id of the order being claimed
* @param claimedUnit The unit that was claimed
* @param hookData The data passed to the hook
* @return Returns the function selector if the hook is successful
*/functionafterClaim(address sender, OrderId orderId, uint64 claimedUnit, bytescalldata hookData)
externalreturns (bytes4);
}
Contract Source Code
File 25 of 44: ILocker.sol
// SPDX-License-Identifier: MITpragmasolidity ^0.8.0;/**
* @title ILocker
* @notice Interface for the locker contract
*/interfaceILocker{
/**
* @notice Called by the book manager on `msg.sender` when a lock is acquired
* @param data The data that was passed to the call to lock
* @return Any data that you want to be returned from the lock call
*/functionlockAcquired(address lockCaller, bytescalldata data) externalreturns (bytesmemory);
}
Contract Source Code
File 26 of 44: Lockers.sol
// SPDX-License-Identifier: BUSL-1.1pragmasolidity ^0.8.23;import {IHooks} from"../interfaces/IHooks.sol";
/// @author Clober/// @author Modified from Uniswap V4 (https://github.com/Uniswap/v4-core/tree/98680ebc1a654120e995d53a5b10ec6fe153066f)/// @notice Contains data about pool lockers./// @dev This library manages a custom storage implementation for a queue/// that tracks current lockers. The "sentinel" storage slot for this data structure,/// always passed in as IPoolManager.LockData storage self, stores not just the current/// length of the queue but also the global count of non-zero deltas across all lockers./// The values of the data structure start at OFFSET, and each value is a locker address.libraryLockers{
/// struct LockData {/// /// @notice The current number of active lockers/// uint128 length;/// /// @notice The total number of nonzero deltas over all active + completed lockers/// uint128 nonzeroDeltaCount;/// }// uint256(keccak256("LockData")) + 1uint256internalconstant LOCK_DATA_SLOT =0x760a9a962ae3d184e99c0483cf5684fb3170f47116ca4f445c50209da4f4f907;
// uint256(keccak256("Lockers")) + 1uint256internalconstant LOCKERS_SLOT =0x722b431450ce53c44434ec138439e45a0639fe031b803ee019b776fae5cfa2b1;
// The number of slots per item in the lockers arrayuint256internalconstant LOCKER_STRUCT_SIZE =2;
// uint256(keccak256("HookAddress")) + 1uint256internalconstant HOOK_ADDRESS_SLOT =0xfcac7593714b88fec0c578a53e9f3f6e4b47eb26c9dcaa7eff23a3ac156be422;
uint256internalconstant NONZERO_DELTA_COUNT_OFFSET =2**128;
uint256internalconstant LENGTH_MASK = (1<<128) -1;
/// @dev Pushes a locker onto the end of the queue, and updates the sentinel storage slot.functionpush(address locker, address lockCaller) internal{
assembly {
let data := tload(LOCK_DATA_SLOT)
let l :=and(data, LENGTH_MASK)
// LOCKERS_SLOT + l * LOCKER_STRUCT_SIZElet indexToWrite :=add(LOCKERS_SLOT, mul(l, LOCKER_STRUCT_SIZE))
// in the next storage slot, write the locker and lockCaller
tstore(indexToWrite, locker)
tstore(add(indexToWrite, 1), lockCaller)
// increase the length
tstore(LOCK_DATA_SLOT, add(data, 1))
}
}
functionlockData() internalviewreturns (uint128 l, uint128 nonzeroDeltaCount) {
assembly {
let data := tload(LOCK_DATA_SLOT)
l :=and(data, LENGTH_MASK)
nonzeroDeltaCount :=shr(128, data)
}
}
functionlength() internalviewreturns (uint128 l) {
assembly {
l :=and(tload(LOCK_DATA_SLOT), LENGTH_MASK)
}
}
/// @dev Pops a locker off the end of the queue. Note that no storage gets cleared.functionpop() internal{
assembly {
let data := tload(LOCK_DATA_SLOT)
let l :=and(data, LENGTH_MASK)
ifiszero(l) {
mstore(0x00, 0xf1c77ed0) // LockersPopFailed()revert(0x1c, 0x04)
}
// LOCKERS_SLOT + (l - 1) * LOCKER_STRUCT_SIZElet indexToWrite :=add(LOCKERS_SLOT, mul(sub(l, 1), LOCKER_STRUCT_SIZE))
// in the next storage slot, delete the locker and lockCaller
tstore(indexToWrite, 0)
tstore(add(indexToWrite, 1), 0)
// decrease the length
tstore(LOCK_DATA_SLOT, sub(data, 1))
}
}
functiongetLocker(uint256 i) internalviewreturns (address locker) {
assembly {
// LOCKERS_SLOT + (i * LOCKER_STRUCT_SIZE)
locker := tload(add(LOCKERS_SLOT, mul(i, LOCKER_STRUCT_SIZE)))
}
}
functiongetLockCaller(uint256 i) internalviewreturns (address locker) {
assembly {
// LOCKERS_SLOT + (i * LOCKER_STRUCT_SIZE + 1)
locker := tload(add(LOCKERS_SLOT, add(mul(i, LOCKER_STRUCT_SIZE), 1)))
}
}
functiongetCurrentLocker() internalviewreturns (address) {
unchecked {
uint256 l = length();
return l >0 ? getLocker(l -1) : address(0);
}
}
functiongetCurrentLockCaller() internalviewreturns (address) {
unchecked {
uint256 l = length();
return l >0 ? getLockCaller(l -1) : address(0);
}
}
functionincrementNonzeroDeltaCount() internal{
assembly {
tstore(LOCK_DATA_SLOT, add(tload(LOCK_DATA_SLOT), NONZERO_DELTA_COUNT_OFFSET))
}
}
functiondecrementNonzeroDeltaCount() internal{
assembly {
tstore(LOCK_DATA_SLOT, sub(tload(LOCK_DATA_SLOT), NONZERO_DELTA_COUNT_OFFSET))
}
}
functiongetCurrentHook() internalviewreturns (IHooks currentHook) {
return IHooks(getHook(length()));
}
functiongetHook(uint256 i) internalviewreturns (address hook) {
assembly {
hook := tload(add(HOOK_ADDRESS_SLOT, i))
}
}
functionsetCurrentHook(IHooks currentHook) internalreturns (bool set) {
// Set the hook address for the current locker if the address is 0.// If the address is nonzero, a hook has already been set for this lock, and is not allowed to be updated or cleared at the end of the call.if (address(getCurrentHook()) ==address(0)) {
uint256 l = length();
assembly {
tstore(add(HOOK_ADDRESS_SLOT, l), currentHook)
}
returntrue;
}
}
functionclearCurrentHook() internal{
uint256 l = length();
assembly {
tstore(add(HOOK_ADDRESS_SLOT, l), 0)
}
}
}
Contract Source Code
File 27 of 44: Math.sol
// SPDX-License-Identifier: GPL-2.0-or-laterpragmasolidity ^0.8.0;libraryMath{
functiondivide(uint256 a, uint256 b, bool roundingUp) internalpurereturns (uint256 ret) {
// In the OrderBook contract code, b is never zero.assembly {
ret :=add(div(a, b), and(gt(mod(a, b), 0), roundingUp))
}
}
/// @dev Returns `ln(x)`, denominated in `WAD`./// Credit to Remco Bloemen under MIT license: https://2π.com/22/exp-lnfunctionlnWad(int256 x) internalpurereturns (int256 r) {
/// @solidity memory-safe-assemblyassembly {
// We want to convert `x` from `10**18` fixed point to `2**96` fixed point.// We do this by multiplying by `2**96 / 10**18`. But since// `ln(x * C) = ln(x) + ln(C)`, we can simply do nothing here// and add `ln(2**96 / 10**18)` at the end.// Compute `k = log2(x) - 96`, `r = 159 - k = 255 - log2(x) = 255 ^ log2(x)`.
r :=shl(7, lt(0xffffffffffffffffffffffffffffffff, x))
r :=or(r, shl(6, lt(0xffffffffffffffff, shr(r, x))))
r :=or(r, shl(5, lt(0xffffffff, shr(r, x))))
r :=or(r, shl(4, lt(0xffff, shr(r, x))))
r :=or(r, shl(3, lt(0xff, shr(r, x))))
// We place the check here for more optimal stack operations.ifiszero(sgt(x, 0)) {
mstore(0x00, 0x1615e638) // `LnWadUndefined()`.revert(0x1c, 0x04)
}
// forgefmt: disable-next-item
r :=xor(r, byte(and(0x1f, shr(shr(r, x), 0x8421084210842108cc6318c6db6d54be)),
0xf8f9f9faf9fdfafbf9fdfcfdfafbfcfef9fafdfafcfcfbfefafafcfbffffffff))
// Reduce range of x to (1, 2) * 2**96// ln(2^k * x) = k * ln(2) + ln(x)
x :=shr(159, shl(r, x))
// Evaluate using a (8, 8)-term rational approximation.// `p` is made monic, we will multiply by a scale factor later.// forgefmt: disable-next-itemlet p :=sub( // This heavily nested expression is to avoid stack-too-deep for via-ir.sar(96, mul(add(43456485725739037958740375743393,
sar(96, mul(add(24828157081833163892658089445524,
sar(96, mul(add(3273285459638523848632254066296,
x), x))), x))), x)), 11111509109440967052023855526967)
p :=sub(sar(96, mul(p, x)), 45023709667254063763336534515857)
p :=sub(sar(96, mul(p, x)), 14706773417378608786704636184526)
p :=sub(mul(p, x), shl(96, 795164235651350426258249787498))
// We leave `p` in `2**192` basis so we don't need to scale it back up for the division.// `q` is monic by convention.let q :=add(5573035233440673466300451813936, x)
q :=add(71694874799317883764090561454958, sar(96, mul(x, q)))
q :=add(283447036172924575727196451306956, sar(96, mul(x, q)))
q :=add(401686690394027663651624208769553, sar(96, mul(x, q)))
q :=add(204048457590392012362485061816622, sar(96, mul(x, q)))
q :=add(31853899698501571402653359427138, sar(96, mul(x, q)))
q :=add(909429971244387300277376558375, sar(96, mul(x, q)))
// `p / q` is in the range `(0, 0.125) * 2**96`.// Finalization, we need to:// - Multiply by the scale factor `s = 5.549…`.// - Add `ln(2**96 / 10**18)`.// - Add `k * ln(2)`.// - Multiply by `10**18 / 2**96 = 5**18 >> 78`.// The q polynomial is known not to have zeros in the domain.// No scaling required because p is already `2**96` too large.
p :=sdiv(p, q)
// Multiply by the scaling factor: `s * 5**18 * 2**96`, base is now `5**18 * 2**192`.
p :=mul(1677202110996718588342820967067443963516166, p)
// Add `ln(2) * k * 5**18 * 2**192`.// forgefmt: disable-next-item
p :=add(mul(16597577552685614221487285958193947469193820559219878177908093499208371, sub(159, r)), p)
// Base conversion: mul `2**96 / (5**18 * 2**192)`.
r :=sdiv(p, 302231454903657293676544000000000000000000)
}
}
}
Contract Source Code
File 28 of 44: MessageHashUtils.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v5.0.0) (utils/cryptography/MessageHashUtils.sol)pragmasolidity ^0.8.20;import {Strings} from"../Strings.sol";
/**
* @dev Signature message hash utilities for producing digests to be consumed by {ECDSA} recovery or signing.
*
* The library provides methods for generating a hash of a message that conforms to the
* https://eips.ethereum.org/EIPS/eip-191[ERC-191] and https://eips.ethereum.org/EIPS/eip-712[EIP 712]
* specifications.
*/libraryMessageHashUtils{
/**
* @dev Returns the keccak256 digest of an ERC-191 signed data with version
* `0x45` (`personal_sign` messages).
*
* The digest is calculated by prefixing a bytes32 `messageHash` with
* `"\x19Ethereum Signed Message:\n32"` and hashing the result. It corresponds with the
* hash signed when using the https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] JSON-RPC method.
*
* NOTE: The `messageHash` parameter is intended to be the result of hashing a raw message with
* keccak256, although any bytes32 value can be safely used because the final digest will
* be re-hashed.
*
* See {ECDSA-recover}.
*/functiontoEthSignedMessageHash(bytes32 messageHash) internalpurereturns (bytes32 digest) {
/// @solidity memory-safe-assemblyassembly {
mstore(0x00, "\x19Ethereum Signed Message:\n32") // 32 is the bytes-length of messageHashmstore(0x1c, messageHash) // 0x1c (28) is the length of the prefix
digest :=keccak256(0x00, 0x3c) // 0x3c is the length of the prefix (0x1c) + messageHash (0x20)
}
}
/**
* @dev Returns the keccak256 digest of an ERC-191 signed data with version
* `0x45` (`personal_sign` messages).
*
* The digest is calculated by prefixing an arbitrary `message` with
* `"\x19Ethereum Signed Message:\n" + len(message)` and hashing the result. It corresponds with the
* hash signed when using the https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] JSON-RPC method.
*
* See {ECDSA-recover}.
*/functiontoEthSignedMessageHash(bytesmemory message) internalpurereturns (bytes32) {
returnkeccak256(bytes.concat("\x19Ethereum Signed Message:\n", bytes(Strings.toString(message.length)), message));
}
/**
* @dev Returns the keccak256 digest of an ERC-191 signed data with version
* `0x00` (data with intended validator).
*
* The digest is calculated by prefixing an arbitrary `data` with `"\x19\x00"` and the intended
* `validator` address. Then hashing the result.
*
* See {ECDSA-recover}.
*/functiontoDataWithIntendedValidatorHash(address validator, bytesmemory data) internalpurereturns (bytes32) {
returnkeccak256(abi.encodePacked(hex"19_00", validator, data));
}
/**
* @dev Returns the keccak256 digest of an EIP-712 typed data (ERC-191 version `0x01`).
*
* The digest is calculated from a `domainSeparator` and a `structHash`, by prefixing them with
* `\x19\x01` and hashing the result. It corresponds to the hash signed by the
* https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] JSON-RPC method as part of EIP-712.
*
* See {ECDSA-recover}.
*/functiontoTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internalpurereturns (bytes32 digest) {
/// @solidity memory-safe-assemblyassembly {
let ptr :=mload(0x40)
mstore(ptr, hex"19_01")
mstore(add(ptr, 0x02), domainSeparator)
mstore(add(ptr, 0x22), structHash)
digest :=keccak256(ptr, 0x42)
}
}
}
Contract Source Code
File 29 of 44: OrderId.sol
// SPDX-License-Identifier: GPL-2.0-or-laterpragmasolidity ^0.8.0;import {Tick} from"./Tick.sol";
import {BookId} from"./BookId.sol";
type OrderId isuint256;
libraryOrderIdLibrary{
/**
* @dev Encode the order id.
* @param bookId The book id.
* @param tick The tick.
* @param index The index.
* @return id The order id.
*/functionencode(BookId bookId, Tick tick, uint40 index) internalpurereturns (OrderId id) {
// @dev If we just use tick at the assembly code, the code will convert tick into bytes32.// e.g. When index == -2, the shifted value( shl(40, tick) ) will be// 0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0000000000 instead of 0xfffffffe0000000000// Therefore, we have to safely cast tick into uint256 first.uint256 _tick =uint256(uint24(Tick.unwrap(tick)));
assembly {
id :=add(index, add(shl(40, _tick), shl(64, bookId)))
}
}
functiondecode(OrderId id) internalpurereturns (BookId bookId, Tick tick, uint40 index) {
assembly {
bookId :=shr(64, id)
tick :=and(shr(40, id), 0xffffff)
index :=and(id, 0xffffffffff)
}
}
functiongetBookId(OrderId id) internalpurereturns (BookId bookId) {
assembly {
bookId :=shr(64, id)
}
}
functiongetTick(OrderId id) internalpurereturns (Tick tick) {
assembly {
tick :=and(shr(40, id), 0xffffff)
}
}
functiongetIndex(OrderId id) internalpurereturns (uint40 index) {
assembly {
index :=and(id, 0xffffffffff)
}
}
}
Contract Source Code
File 30 of 44: Ownable.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)pragmasolidity ^0.8.20;import {Context} from"../utils/Context.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* The initial owner is set to the address provided by the deployer. This can
* later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/abstractcontractOwnableisContext{
addressprivate _owner;
/**
* @dev The caller account is not authorized to perform an operation.
*/errorOwnableUnauthorizedAccount(address account);
/**
* @dev The owner is not a valid owner account. (eg. `address(0)`)
*/errorOwnableInvalidOwner(address owner);
eventOwnershipTransferred(addressindexed previousOwner, addressindexed newOwner);
/**
* @dev Initializes the contract setting the address provided by the deployer as the initial owner.
*/constructor(address initialOwner) {
if (initialOwner ==address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(initialOwner);
}
/**
* @dev Throws if called by any account other than the owner.
*/modifieronlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/functionowner() publicviewvirtualreturns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/function_checkOwner() internalviewvirtual{
if (owner() != _msgSender()) {
revert OwnableUnauthorizedAccount(_msgSender());
}
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby disabling any functionality that is only available to the owner.
*/functionrenounceOwnership() publicvirtualonlyOwner{
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/functiontransferOwnership(address newOwner) publicvirtualonlyOwner{
if (newOwner ==address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/function_transferOwnership(address newOwner) internalvirtual{
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
Contract Source Code
File 31 of 44: Ownable2Step.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable2Step.sol)pragmasolidity ^0.8.20;import {Ownable} from"./Ownable.sol";
/**
* @dev Contract module which provides access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* This extension of the {Ownable} contract includes a two-step mechanism to transfer
* ownership, where the new owner must call {acceptOwnership} in order to replace the
* old one. This can help prevent common mistakes, such as transfers of ownership to
* incorrect accounts, or to contracts that are unable to interact with the
* permission system.
*
* The initial owner is specified at deployment time in the constructor for `Ownable`. This
* can later be changed with {transferOwnership} and {acceptOwnership}.
*
* This module is used through inheritance. It will make available all functions
* from parent (Ownable).
*/abstractcontractOwnable2StepisOwnable{
addressprivate _pendingOwner;
eventOwnershipTransferStarted(addressindexed previousOwner, addressindexed newOwner);
/**
* @dev Returns the address of the pending owner.
*/functionpendingOwner() publicviewvirtualreturns (address) {
return _pendingOwner;
}
/**
* @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.
* Can only be called by the current owner.
*/functiontransferOwnership(address newOwner) publicvirtualoverrideonlyOwner{
_pendingOwner = newOwner;
emit OwnershipTransferStarted(owner(), newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.
* Internal function without access restriction.
*/function_transferOwnership(address newOwner) internalvirtualoverride{
delete _pendingOwner;
super._transferOwnership(newOwner);
}
/**
* @dev The new owner accepts the ownership transfer.
*/functionacceptOwnership() publicvirtual{
address sender = _msgSender();
if (pendingOwner() != sender) {
revert OwnableUnauthorizedAccount(sender);
}
_transferOwnership(sender);
}
}
// SPDX-License-Identifier: MITpragmasolidity ^0.8.20;/**
* @dev Helper library for emitting standardized panic codes.
*
* ```solidity
* contract Example {
* using Panic for uint256;
*
* // Use any of the declared internal constants
* function foo() { Panic.GENERIC.panic(); }
*
* // Alternatively
* function foo() { Panic.panic(Panic.GENERIC); }
* }
* ```
*
* Follows the list from https://github.com/ethereum/solidity/blob/v0.8.24/libsolutil/ErrorCodes.h[libsolutil].
*/// slither-disable-next-line unused-statelibraryPanic{
/// @dev generic / unspecified erroruint256internalconstant GENERIC =0x00;
/// @dev used by the assert() builtinuint256internalconstant ASSERT =0x01;
/// @dev arithmetic underflow or overflowuint256internalconstant UNDER_OVERFLOW =0x11;
/// @dev division or modulo by zerouint256internalconstant DIVISION_BY_ZERO =0x12;
/// @dev enum conversion erroruint256internalconstant ENUM_CONVERSION_ERROR =0x21;
/// @dev invalid encoding in storageuint256internalconstant STORAGE_ENCODING_ERROR =0x22;
/// @dev empty array popuint256internalconstant EMPTY_ARRAY_POP =0x31;
/// @dev array out of bounds accessuint256internalconstant ARRAY_OUT_OF_BOUNDS =0x32;
/// @dev resource error (too large allocation or too large array)uint256internalconstant RESOURCE_ERROR =0x41;
/// @dev calling invalid internal functionuint256internalconstant INVALID_INTERNAL_FUNCTION =0x51;
/// @dev Reverts with a panic code. Recommended to use with/// the internal constants with predefined codes.functionpanic(uint256 code) internalpure{
/// @solidity memory-safe-assemblyassembly {
mstore(0x00, 0x4e487b71)
mstore(0x20, code)
revert(0x1c, 0x24)
}
}
}
Contract Source Code
File 34 of 44: SafeCast.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v5.0.0) (utils/math/SafeCast.sol)// This file was procedurally generated from scripts/generate/templates/SafeCast.js.pragmasolidity ^0.8.20;/**
* @dev Wrappers over Solidity's uintXX/intXX/bool casting operators with added overflow
* checks.
*
* Downcasting from uint256/int256 in Solidity does not revert on overflow. This can
* easily result in undesired exploitation or bugs, since developers usually
* assume that overflows raise errors. `SafeCast` restores this intuition by
* reverting the transaction when such an operation overflows.
*
* Using this library instead of the unchecked operations eliminates an entire
* class of bugs, so it's recommended to use it always.
*/librarySafeCast{
/**
* @dev Value doesn't fit in an uint of `bits` size.
*/errorSafeCastOverflowedUintDowncast(uint8 bits, uint256 value);
/**
* @dev An int value doesn't fit in an uint of `bits` size.
*/errorSafeCastOverflowedIntToUint(int256 value);
/**
* @dev Value doesn't fit in an int of `bits` size.
*/errorSafeCastOverflowedIntDowncast(uint8 bits, int256 value);
/**
* @dev An uint value doesn't fit in an int of `bits` size.
*/errorSafeCastOverflowedUintToInt(uint256 value);
/**
* @dev Returns the downcasted uint248 from uint256, reverting on
* overflow (when the input is greater than largest uint248).
*
* Counterpart to Solidity's `uint248` operator.
*
* Requirements:
*
* - input must fit into 248 bits
*/functiontoUint248(uint256 value) internalpurereturns (uint248) {
if (value >type(uint248).max) {
revert SafeCastOverflowedUintDowncast(248, value);
}
returnuint248(value);
}
/**
* @dev Returns the downcasted uint240 from uint256, reverting on
* overflow (when the input is greater than largest uint240).
*
* Counterpart to Solidity's `uint240` operator.
*
* Requirements:
*
* - input must fit into 240 bits
*/functiontoUint240(uint256 value) internalpurereturns (uint240) {
if (value >type(uint240).max) {
revert SafeCastOverflowedUintDowncast(240, value);
}
returnuint240(value);
}
/**
* @dev Returns the downcasted uint232 from uint256, reverting on
* overflow (when the input is greater than largest uint232).
*
* Counterpart to Solidity's `uint232` operator.
*
* Requirements:
*
* - input must fit into 232 bits
*/functiontoUint232(uint256 value) internalpurereturns (uint232) {
if (value >type(uint232).max) {
revert SafeCastOverflowedUintDowncast(232, value);
}
returnuint232(value);
}
/**
* @dev Returns the downcasted uint224 from uint256, reverting on
* overflow (when the input is greater than largest uint224).
*
* Counterpart to Solidity's `uint224` operator.
*
* Requirements:
*
* - input must fit into 224 bits
*/functiontoUint224(uint256 value) internalpurereturns (uint224) {
if (value >type(uint224).max) {
revert SafeCastOverflowedUintDowncast(224, value);
}
returnuint224(value);
}
/**
* @dev Returns the downcasted uint216 from uint256, reverting on
* overflow (when the input is greater than largest uint216).
*
* Counterpart to Solidity's `uint216` operator.
*
* Requirements:
*
* - input must fit into 216 bits
*/functiontoUint216(uint256 value) internalpurereturns (uint216) {
if (value >type(uint216).max) {
revert SafeCastOverflowedUintDowncast(216, value);
}
returnuint216(value);
}
/**
* @dev Returns the downcasted uint208 from uint256, reverting on
* overflow (when the input is greater than largest uint208).
*
* Counterpart to Solidity's `uint208` operator.
*
* Requirements:
*
* - input must fit into 208 bits
*/functiontoUint208(uint256 value) internalpurereturns (uint208) {
if (value >type(uint208).max) {
revert SafeCastOverflowedUintDowncast(208, value);
}
returnuint208(value);
}
/**
* @dev Returns the downcasted uint200 from uint256, reverting on
* overflow (when the input is greater than largest uint200).
*
* Counterpart to Solidity's `uint200` operator.
*
* Requirements:
*
* - input must fit into 200 bits
*/functiontoUint200(uint256 value) internalpurereturns (uint200) {
if (value >type(uint200).max) {
revert SafeCastOverflowedUintDowncast(200, value);
}
returnuint200(value);
}
/**
* @dev Returns the downcasted uint192 from uint256, reverting on
* overflow (when the input is greater than largest uint192).
*
* Counterpart to Solidity's `uint192` operator.
*
* Requirements:
*
* - input must fit into 192 bits
*/functiontoUint192(uint256 value) internalpurereturns (uint192) {
if (value >type(uint192).max) {
revert SafeCastOverflowedUintDowncast(192, value);
}
returnuint192(value);
}
/**
* @dev Returns the downcasted uint184 from uint256, reverting on
* overflow (when the input is greater than largest uint184).
*
* Counterpart to Solidity's `uint184` operator.
*
* Requirements:
*
* - input must fit into 184 bits
*/functiontoUint184(uint256 value) internalpurereturns (uint184) {
if (value >type(uint184).max) {
revert SafeCastOverflowedUintDowncast(184, value);
}
returnuint184(value);
}
/**
* @dev Returns the downcasted uint176 from uint256, reverting on
* overflow (when the input is greater than largest uint176).
*
* Counterpart to Solidity's `uint176` operator.
*
* Requirements:
*
* - input must fit into 176 bits
*/functiontoUint176(uint256 value) internalpurereturns (uint176) {
if (value >type(uint176).max) {
revert SafeCastOverflowedUintDowncast(176, value);
}
returnuint176(value);
}
/**
* @dev Returns the downcasted uint168 from uint256, reverting on
* overflow (when the input is greater than largest uint168).
*
* Counterpart to Solidity's `uint168` operator.
*
* Requirements:
*
* - input must fit into 168 bits
*/functiontoUint168(uint256 value) internalpurereturns (uint168) {
if (value >type(uint168).max) {
revert SafeCastOverflowedUintDowncast(168, value);
}
returnuint168(value);
}
/**
* @dev Returns the downcasted uint160 from uint256, reverting on
* overflow (when the input is greater than largest uint160).
*
* Counterpart to Solidity's `uint160` operator.
*
* Requirements:
*
* - input must fit into 160 bits
*/functiontoUint160(uint256 value) internalpurereturns (uint160) {
if (value >type(uint160).max) {
revert SafeCastOverflowedUintDowncast(160, value);
}
returnuint160(value);
}
/**
* @dev Returns the downcasted uint152 from uint256, reverting on
* overflow (when the input is greater than largest uint152).
*
* Counterpart to Solidity's `uint152` operator.
*
* Requirements:
*
* - input must fit into 152 bits
*/functiontoUint152(uint256 value) internalpurereturns (uint152) {
if (value >type(uint152).max) {
revert SafeCastOverflowedUintDowncast(152, value);
}
returnuint152(value);
}
/**
* @dev Returns the downcasted uint144 from uint256, reverting on
* overflow (when the input is greater than largest uint144).
*
* Counterpart to Solidity's `uint144` operator.
*
* Requirements:
*
* - input must fit into 144 bits
*/functiontoUint144(uint256 value) internalpurereturns (uint144) {
if (value >type(uint144).max) {
revert SafeCastOverflowedUintDowncast(144, value);
}
returnuint144(value);
}
/**
* @dev Returns the downcasted uint136 from uint256, reverting on
* overflow (when the input is greater than largest uint136).
*
* Counterpart to Solidity's `uint136` operator.
*
* Requirements:
*
* - input must fit into 136 bits
*/functiontoUint136(uint256 value) internalpurereturns (uint136) {
if (value >type(uint136).max) {
revert SafeCastOverflowedUintDowncast(136, value);
}
returnuint136(value);
}
/**
* @dev Returns the downcasted uint128 from uint256, reverting on
* overflow (when the input is greater than largest uint128).
*
* Counterpart to Solidity's `uint128` operator.
*
* Requirements:
*
* - input must fit into 128 bits
*/functiontoUint128(uint256 value) internalpurereturns (uint128) {
if (value >type(uint128).max) {
revert SafeCastOverflowedUintDowncast(128, value);
}
returnuint128(value);
}
/**
* @dev Returns the downcasted uint120 from uint256, reverting on
* overflow (when the input is greater than largest uint120).
*
* Counterpart to Solidity's `uint120` operator.
*
* Requirements:
*
* - input must fit into 120 bits
*/functiontoUint120(uint256 value) internalpurereturns (uint120) {
if (value >type(uint120).max) {
revert SafeCastOverflowedUintDowncast(120, value);
}
returnuint120(value);
}
/**
* @dev Returns the downcasted uint112 from uint256, reverting on
* overflow (when the input is greater than largest uint112).
*
* Counterpart to Solidity's `uint112` operator.
*
* Requirements:
*
* - input must fit into 112 bits
*/functiontoUint112(uint256 value) internalpurereturns (uint112) {
if (value >type(uint112).max) {
revert SafeCastOverflowedUintDowncast(112, value);
}
returnuint112(value);
}
/**
* @dev Returns the downcasted uint104 from uint256, reverting on
* overflow (when the input is greater than largest uint104).
*
* Counterpart to Solidity's `uint104` operator.
*
* Requirements:
*
* - input must fit into 104 bits
*/functiontoUint104(uint256 value) internalpurereturns (uint104) {
if (value >type(uint104).max) {
revert SafeCastOverflowedUintDowncast(104, value);
}
returnuint104(value);
}
/**
* @dev Returns the downcasted uint96 from uint256, reverting on
* overflow (when the input is greater than largest uint96).
*
* Counterpart to Solidity's `uint96` operator.
*
* Requirements:
*
* - input must fit into 96 bits
*/functiontoUint96(uint256 value) internalpurereturns (uint96) {
if (value >type(uint96).max) {
revert SafeCastOverflowedUintDowncast(96, value);
}
returnuint96(value);
}
/**
* @dev Returns the downcasted uint88 from uint256, reverting on
* overflow (when the input is greater than largest uint88).
*
* Counterpart to Solidity's `uint88` operator.
*
* Requirements:
*
* - input must fit into 88 bits
*/functiontoUint88(uint256 value) internalpurereturns (uint88) {
if (value >type(uint88).max) {
revert SafeCastOverflowedUintDowncast(88, value);
}
returnuint88(value);
}
/**
* @dev Returns the downcasted uint80 from uint256, reverting on
* overflow (when the input is greater than largest uint80).
*
* Counterpart to Solidity's `uint80` operator.
*
* Requirements:
*
* - input must fit into 80 bits
*/functiontoUint80(uint256 value) internalpurereturns (uint80) {
if (value >type(uint80).max) {
revert SafeCastOverflowedUintDowncast(80, value);
}
returnuint80(value);
}
/**
* @dev Returns the downcasted uint72 from uint256, reverting on
* overflow (when the input is greater than largest uint72).
*
* Counterpart to Solidity's `uint72` operator.
*
* Requirements:
*
* - input must fit into 72 bits
*/functiontoUint72(uint256 value) internalpurereturns (uint72) {
if (value >type(uint72).max) {
revert SafeCastOverflowedUintDowncast(72, value);
}
returnuint72(value);
}
/**
* @dev Returns the downcasted uint64 from uint256, reverting on
* overflow (when the input is greater than largest uint64).
*
* Counterpart to Solidity's `uint64` operator.
*
* Requirements:
*
* - input must fit into 64 bits
*/functiontoUint64(uint256 value) internalpurereturns (uint64) {
if (value >type(uint64).max) {
revert SafeCastOverflowedUintDowncast(64, value);
}
returnuint64(value);
}
/**
* @dev Returns the downcasted uint56 from uint256, reverting on
* overflow (when the input is greater than largest uint56).
*
* Counterpart to Solidity's `uint56` operator.
*
* Requirements:
*
* - input must fit into 56 bits
*/functiontoUint56(uint256 value) internalpurereturns (uint56) {
if (value >type(uint56).max) {
revert SafeCastOverflowedUintDowncast(56, value);
}
returnuint56(value);
}
/**
* @dev Returns the downcasted uint48 from uint256, reverting on
* overflow (when the input is greater than largest uint48).
*
* Counterpart to Solidity's `uint48` operator.
*
* Requirements:
*
* - input must fit into 48 bits
*/functiontoUint48(uint256 value) internalpurereturns (uint48) {
if (value >type(uint48).max) {
revert SafeCastOverflowedUintDowncast(48, value);
}
returnuint48(value);
}
/**
* @dev Returns the downcasted uint40 from uint256, reverting on
* overflow (when the input is greater than largest uint40).
*
* Counterpart to Solidity's `uint40` operator.
*
* Requirements:
*
* - input must fit into 40 bits
*/functiontoUint40(uint256 value) internalpurereturns (uint40) {
if (value >type(uint40).max) {
revert SafeCastOverflowedUintDowncast(40, value);
}
returnuint40(value);
}
/**
* @dev Returns the downcasted uint32 from uint256, reverting on
* overflow (when the input is greater than largest uint32).
*
* Counterpart to Solidity's `uint32` operator.
*
* Requirements:
*
* - input must fit into 32 bits
*/functiontoUint32(uint256 value) internalpurereturns (uint32) {
if (value >type(uint32).max) {
revert SafeCastOverflowedUintDowncast(32, value);
}
returnuint32(value);
}
/**
* @dev Returns the downcasted uint24 from uint256, reverting on
* overflow (when the input is greater than largest uint24).
*
* Counterpart to Solidity's `uint24` operator.
*
* Requirements:
*
* - input must fit into 24 bits
*/functiontoUint24(uint256 value) internalpurereturns (uint24) {
if (value >type(uint24).max) {
revert SafeCastOverflowedUintDowncast(24, value);
}
returnuint24(value);
}
/**
* @dev Returns the downcasted uint16 from uint256, reverting on
* overflow (when the input is greater than largest uint16).
*
* Counterpart to Solidity's `uint16` operator.
*
* Requirements:
*
* - input must fit into 16 bits
*/functiontoUint16(uint256 value) internalpurereturns (uint16) {
if (value >type(uint16).max) {
revert SafeCastOverflowedUintDowncast(16, value);
}
returnuint16(value);
}
/**
* @dev Returns the downcasted uint8 from uint256, reverting on
* overflow (when the input is greater than largest uint8).
*
* Counterpart to Solidity's `uint8` operator.
*
* Requirements:
*
* - input must fit into 8 bits
*/functiontoUint8(uint256 value) internalpurereturns (uint8) {
if (value >type(uint8).max) {
revert SafeCastOverflowedUintDowncast(8, value);
}
returnuint8(value);
}
/**
* @dev Converts a signed int256 into an unsigned uint256.
*
* Requirements:
*
* - input must be greater than or equal to 0.
*/functiontoUint256(int256 value) internalpurereturns (uint256) {
if (value <0) {
revert SafeCastOverflowedIntToUint(value);
}
returnuint256(value);
}
/**
* @dev Returns the downcasted int248 from int256, reverting on
* overflow (when the input is less than smallest int248 or
* greater than largest int248).
*
* Counterpart to Solidity's `int248` operator.
*
* Requirements:
*
* - input must fit into 248 bits
*/functiontoInt248(int256 value) internalpurereturns (int248 downcasted) {
downcasted =int248(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(248, value);
}
}
/**
* @dev Returns the downcasted int240 from int256, reverting on
* overflow (when the input is less than smallest int240 or
* greater than largest int240).
*
* Counterpart to Solidity's `int240` operator.
*
* Requirements:
*
* - input must fit into 240 bits
*/functiontoInt240(int256 value) internalpurereturns (int240 downcasted) {
downcasted =int240(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(240, value);
}
}
/**
* @dev Returns the downcasted int232 from int256, reverting on
* overflow (when the input is less than smallest int232 or
* greater than largest int232).
*
* Counterpart to Solidity's `int232` operator.
*
* Requirements:
*
* - input must fit into 232 bits
*/functiontoInt232(int256 value) internalpurereturns (int232 downcasted) {
downcasted =int232(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(232, value);
}
}
/**
* @dev Returns the downcasted int224 from int256, reverting on
* overflow (when the input is less than smallest int224 or
* greater than largest int224).
*
* Counterpart to Solidity's `int224` operator.
*
* Requirements:
*
* - input must fit into 224 bits
*/functiontoInt224(int256 value) internalpurereturns (int224 downcasted) {
downcasted =int224(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(224, value);
}
}
/**
* @dev Returns the downcasted int216 from int256, reverting on
* overflow (when the input is less than smallest int216 or
* greater than largest int216).
*
* Counterpart to Solidity's `int216` operator.
*
* Requirements:
*
* - input must fit into 216 bits
*/functiontoInt216(int256 value) internalpurereturns (int216 downcasted) {
downcasted =int216(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(216, value);
}
}
/**
* @dev Returns the downcasted int208 from int256, reverting on
* overflow (when the input is less than smallest int208 or
* greater than largest int208).
*
* Counterpart to Solidity's `int208` operator.
*
* Requirements:
*
* - input must fit into 208 bits
*/functiontoInt208(int256 value) internalpurereturns (int208 downcasted) {
downcasted =int208(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(208, value);
}
}
/**
* @dev Returns the downcasted int200 from int256, reverting on
* overflow (when the input is less than smallest int200 or
* greater than largest int200).
*
* Counterpart to Solidity's `int200` operator.
*
* Requirements:
*
* - input must fit into 200 bits
*/functiontoInt200(int256 value) internalpurereturns (int200 downcasted) {
downcasted =int200(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(200, value);
}
}
/**
* @dev Returns the downcasted int192 from int256, reverting on
* overflow (when the input is less than smallest int192 or
* greater than largest int192).
*
* Counterpart to Solidity's `int192` operator.
*
* Requirements:
*
* - input must fit into 192 bits
*/functiontoInt192(int256 value) internalpurereturns (int192 downcasted) {
downcasted =int192(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(192, value);
}
}
/**
* @dev Returns the downcasted int184 from int256, reverting on
* overflow (when the input is less than smallest int184 or
* greater than largest int184).
*
* Counterpart to Solidity's `int184` operator.
*
* Requirements:
*
* - input must fit into 184 bits
*/functiontoInt184(int256 value) internalpurereturns (int184 downcasted) {
downcasted =int184(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(184, value);
}
}
/**
* @dev Returns the downcasted int176 from int256, reverting on
* overflow (when the input is less than smallest int176 or
* greater than largest int176).
*
* Counterpart to Solidity's `int176` operator.
*
* Requirements:
*
* - input must fit into 176 bits
*/functiontoInt176(int256 value) internalpurereturns (int176 downcasted) {
downcasted =int176(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(176, value);
}
}
/**
* @dev Returns the downcasted int168 from int256, reverting on
* overflow (when the input is less than smallest int168 or
* greater than largest int168).
*
* Counterpart to Solidity's `int168` operator.
*
* Requirements:
*
* - input must fit into 168 bits
*/functiontoInt168(int256 value) internalpurereturns (int168 downcasted) {
downcasted =int168(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(168, value);
}
}
/**
* @dev Returns the downcasted int160 from int256, reverting on
* overflow (when the input is less than smallest int160 or
* greater than largest int160).
*
* Counterpart to Solidity's `int160` operator.
*
* Requirements:
*
* - input must fit into 160 bits
*/functiontoInt160(int256 value) internalpurereturns (int160 downcasted) {
downcasted =int160(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(160, value);
}
}
/**
* @dev Returns the downcasted int152 from int256, reverting on
* overflow (when the input is less than smallest int152 or
* greater than largest int152).
*
* Counterpart to Solidity's `int152` operator.
*
* Requirements:
*
* - input must fit into 152 bits
*/functiontoInt152(int256 value) internalpurereturns (int152 downcasted) {
downcasted =int152(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(152, value);
}
}
/**
* @dev Returns the downcasted int144 from int256, reverting on
* overflow (when the input is less than smallest int144 or
* greater than largest int144).
*
* Counterpart to Solidity's `int144` operator.
*
* Requirements:
*
* - input must fit into 144 bits
*/functiontoInt144(int256 value) internalpurereturns (int144 downcasted) {
downcasted =int144(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(144, value);
}
}
/**
* @dev Returns the downcasted int136 from int256, reverting on
* overflow (when the input is less than smallest int136 or
* greater than largest int136).
*
* Counterpart to Solidity's `int136` operator.
*
* Requirements:
*
* - input must fit into 136 bits
*/functiontoInt136(int256 value) internalpurereturns (int136 downcasted) {
downcasted =int136(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(136, value);
}
}
/**
* @dev Returns the downcasted int128 from int256, reverting on
* overflow (when the input is less than smallest int128 or
* greater than largest int128).
*
* Counterpart to Solidity's `int128` operator.
*
* Requirements:
*
* - input must fit into 128 bits
*/functiontoInt128(int256 value) internalpurereturns (int128 downcasted) {
downcasted =int128(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(128, value);
}
}
/**
* @dev Returns the downcasted int120 from int256, reverting on
* overflow (when the input is less than smallest int120 or
* greater than largest int120).
*
* Counterpart to Solidity's `int120` operator.
*
* Requirements:
*
* - input must fit into 120 bits
*/functiontoInt120(int256 value) internalpurereturns (int120 downcasted) {
downcasted =int120(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(120, value);
}
}
/**
* @dev Returns the downcasted int112 from int256, reverting on
* overflow (when the input is less than smallest int112 or
* greater than largest int112).
*
* Counterpart to Solidity's `int112` operator.
*
* Requirements:
*
* - input must fit into 112 bits
*/functiontoInt112(int256 value) internalpurereturns (int112 downcasted) {
downcasted =int112(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(112, value);
}
}
/**
* @dev Returns the downcasted int104 from int256, reverting on
* overflow (when the input is less than smallest int104 or
* greater than largest int104).
*
* Counterpart to Solidity's `int104` operator.
*
* Requirements:
*
* - input must fit into 104 bits
*/functiontoInt104(int256 value) internalpurereturns (int104 downcasted) {
downcasted =int104(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(104, value);
}
}
/**
* @dev Returns the downcasted int96 from int256, reverting on
* overflow (when the input is less than smallest int96 or
* greater than largest int96).
*
* Counterpart to Solidity's `int96` operator.
*
* Requirements:
*
* - input must fit into 96 bits
*/functiontoInt96(int256 value) internalpurereturns (int96 downcasted) {
downcasted =int96(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(96, value);
}
}
/**
* @dev Returns the downcasted int88 from int256, reverting on
* overflow (when the input is less than smallest int88 or
* greater than largest int88).
*
* Counterpart to Solidity's `int88` operator.
*
* Requirements:
*
* - input must fit into 88 bits
*/functiontoInt88(int256 value) internalpurereturns (int88 downcasted) {
downcasted =int88(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(88, value);
}
}
/**
* @dev Returns the downcasted int80 from int256, reverting on
* overflow (when the input is less than smallest int80 or
* greater than largest int80).
*
* Counterpart to Solidity's `int80` operator.
*
* Requirements:
*
* - input must fit into 80 bits
*/functiontoInt80(int256 value) internalpurereturns (int80 downcasted) {
downcasted =int80(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(80, value);
}
}
/**
* @dev Returns the downcasted int72 from int256, reverting on
* overflow (when the input is less than smallest int72 or
* greater than largest int72).
*
* Counterpart to Solidity's `int72` operator.
*
* Requirements:
*
* - input must fit into 72 bits
*/functiontoInt72(int256 value) internalpurereturns (int72 downcasted) {
downcasted =int72(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(72, value);
}
}
/**
* @dev Returns the downcasted int64 from int256, reverting on
* overflow (when the input is less than smallest int64 or
* greater than largest int64).
*
* Counterpart to Solidity's `int64` operator.
*
* Requirements:
*
* - input must fit into 64 bits
*/functiontoInt64(int256 value) internalpurereturns (int64 downcasted) {
downcasted =int64(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(64, value);
}
}
/**
* @dev Returns the downcasted int56 from int256, reverting on
* overflow (when the input is less than smallest int56 or
* greater than largest int56).
*
* Counterpart to Solidity's `int56` operator.
*
* Requirements:
*
* - input must fit into 56 bits
*/functiontoInt56(int256 value) internalpurereturns (int56 downcasted) {
downcasted =int56(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(56, value);
}
}
/**
* @dev Returns the downcasted int48 from int256, reverting on
* overflow (when the input is less than smallest int48 or
* greater than largest int48).
*
* Counterpart to Solidity's `int48` operator.
*
* Requirements:
*
* - input must fit into 48 bits
*/functiontoInt48(int256 value) internalpurereturns (int48 downcasted) {
downcasted =int48(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(48, value);
}
}
/**
* @dev Returns the downcasted int40 from int256, reverting on
* overflow (when the input is less than smallest int40 or
* greater than largest int40).
*
* Counterpart to Solidity's `int40` operator.
*
* Requirements:
*
* - input must fit into 40 bits
*/functiontoInt40(int256 value) internalpurereturns (int40 downcasted) {
downcasted =int40(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(40, value);
}
}
/**
* @dev Returns the downcasted int32 from int256, reverting on
* overflow (when the input is less than smallest int32 or
* greater than largest int32).
*
* Counterpart to Solidity's `int32` operator.
*
* Requirements:
*
* - input must fit into 32 bits
*/functiontoInt32(int256 value) internalpurereturns (int32 downcasted) {
downcasted =int32(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(32, value);
}
}
/**
* @dev Returns the downcasted int24 from int256, reverting on
* overflow (when the input is less than smallest int24 or
* greater than largest int24).
*
* Counterpart to Solidity's `int24` operator.
*
* Requirements:
*
* - input must fit into 24 bits
*/functiontoInt24(int256 value) internalpurereturns (int24 downcasted) {
downcasted =int24(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(24, value);
}
}
/**
* @dev Returns the downcasted int16 from int256, reverting on
* overflow (when the input is less than smallest int16 or
* greater than largest int16).
*
* Counterpart to Solidity's `int16` operator.
*
* Requirements:
*
* - input must fit into 16 bits
*/functiontoInt16(int256 value) internalpurereturns (int16 downcasted) {
downcasted =int16(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(16, value);
}
}
/**
* @dev Returns the downcasted int8 from int256, reverting on
* overflow (when the input is less than smallest int8 or
* greater than largest int8).
*
* Counterpart to Solidity's `int8` operator.
*
* Requirements:
*
* - input must fit into 8 bits
*/functiontoInt8(int256 value) internalpurereturns (int8 downcasted) {
downcasted =int8(value);
if (downcasted != value) {
revert SafeCastOverflowedIntDowncast(8, value);
}
}
/**
* @dev Converts an unsigned uint256 into a signed int256.
*
* Requirements:
*
* - input must be less than or equal to maxInt256.
*/functiontoInt256(uint256 value) internalpurereturns (int256) {
// Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positiveif (value >uint256(type(int256).max)) {
revert SafeCastOverflowedUintToInt(value);
}
returnint256(value);
}
/**
* @dev Cast a boolean (false or true) to a uint256 (0 or 1) with no jump.
*/functiontoUint(bool b) internalpurereturns (uint256 u) {
/// @solidity memory-safe-assemblyassembly {
u :=iszero(iszero(b))
}
}
}
Contract Source Code
File 35 of 44: SegmentedSegmentTree.sol
// SPDX-License-Identifier: -// License: https://license.clober.io/LICENSE.pdfpragmasolidity ^0.8.0;import"./PackedUint256.sol";
import"./DirtyUint64.sol";
/**
* 🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲
*
* Segmented Segment Tree
* by Clober
*
* ____________/\\\_______________/\\\\\____________/\\\____
* __________/\\\\\___________/\\\\////___________/\\\\\____
* ________/\\\/\\\________/\\\///______________/\\\/\\\____
* ______/\\\/\/\\\______/\\\\\\\\\\\_________/\\\/\/\\\____
* ____/\\\/__\/\\\_____/\\\\///////\\\_____/\\\/__\/\\\____
* __/\\\\\\\\\\\\\\\\_\/\\\______\//\\\__/\\\\\\\\\\\\\\\\_
* _\///////////\\\//__\//\\\______/\\\__\///////////\\\//__
* ___________\/\\\_____\///\\\\\\\\\/_____________\/\\\____
* ___________\///________\/////////_______________\///_____
*
* 4 Layers of 64-bit nodes, hence 464
*
* 🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲🌲
*/librarySegmentedSegmentTree{
usingPackedUint256foruint256;
usingDirtyUint64foruint64;
errorSegmentedSegmentTreeError(uint256 errorCode);
uint256privateconstant _INDEX_ERROR =0;
uint256privateconstant _OVERFLOW_ERROR =1;
// uint8 private constant _R = 2; // There are `2` root node groups// uint8 private constant _C = 4; // There are `4` children (each child is a node group of its own) for each nodeuint8privateconstant _L =4; // There are `4` layers of node groupsuint256privateconstant _P =4; // uint256 / uint64 = `4`uint256privateconstant _P_M =3; // % 4 = & `3`uint256privateconstant _P_P =2; // 2 ** `2` = 4uint256privateconstant _N_P =4; // C * P = 2 ** `4`uint256privateconstant _MAX_NODES =2**15; // (R * P) * ((C * P) ** (L - 1)) = `32768`uint256privateconstant _MAX_NODES_P_MINUS_ONE =14; // MAX_NODES / R = 2 ** `14`structCore {
mapping(uint256=>uint256)[_L] layers;
}
structLayerIndex {
uint256 group;
uint256 node;
}
functionget(Core storage core, uint256 index) internalviewreturns (uint64 ret) {
if (index >= _MAX_NODES) {
revert SegmentedSegmentTreeError(_INDEX_ERROR);
}
unchecked {
ret = core.layers[_L -1][index >> _P_P].get64(index & _P_M).toClean();
}
}
functiontotal(Core storage core) internalviewreturns (uint64) {
return DirtyUint64.sumPackedUnsafe(core.layers[0][0], 0, _P)
+ DirtyUint64.sumPackedUnsafe(core.layers[0][1], 0, _P);
}
functionquery(Core storage core, uint256 left, uint256 right) internalviewreturns (uint64 sum) {
if (left == right) {
return0;
}
// right should be greater than leftif (left >= right) {
revert SegmentedSegmentTreeError(_INDEX_ERROR);
}
if (right > _MAX_NODES) {
revert SegmentedSegmentTreeError(_INDEX_ERROR);
}
LayerIndex[] memory leftIndices = _getLayerIndices(left);
LayerIndex[] memory rightIndices = _getLayerIndices(right);
uint256 ret;
uint256 deficit;
unchecked {
uint256 leftNodeIndex;
uint256 rightNodeIndex;
for (uint256 l = _L -1;; --l) {
LayerIndex memory leftIndex = leftIndices[l];
LayerIndex memory rightIndex = rightIndices[l];
leftNodeIndex += leftIndex.node;
rightNodeIndex += rightIndex.node;
if (rightIndex.group == leftIndex.group) {
ret += DirtyUint64.sumPackedUnsafe(core.layers[l][leftIndex.group], leftNodeIndex, rightNodeIndex);
break;
}
if (rightIndex.group - leftIndex.group <4) {
ret += DirtyUint64.sumPackedUnsafe(core.layers[l][leftIndex.group], leftNodeIndex, _P);
ret += DirtyUint64.sumPackedUnsafe(core.layers[l][rightIndex.group], 0, rightNodeIndex);
for (uint256 group = leftIndex.group +1; group < rightIndex.group; group++) {
ret += DirtyUint64.sumPackedUnsafe(core.layers[l][group], 0, _P);
}
break;
}
if (leftIndex.group %4==0) {
deficit += DirtyUint64.sumPackedUnsafe(core.layers[l][leftIndex.group], 0, leftNodeIndex);
leftNodeIndex =0;
} elseif (leftIndex.group %4==1) {
deficit += DirtyUint64.sumPackedUnsafe(core.layers[l][leftIndex.group -1], 0, _P);
deficit += DirtyUint64.sumPackedUnsafe(core.layers[l][leftIndex.group], 0, leftNodeIndex);
leftNodeIndex =0;
} elseif (leftIndex.group %4==2) {
ret += DirtyUint64.sumPackedUnsafe(core.layers[l][leftIndex.group], leftNodeIndex, _P);
ret += DirtyUint64.sumPackedUnsafe(core.layers[l][leftIndex.group +1], 0, _P);
leftNodeIndex =1;
} else {
ret += DirtyUint64.sumPackedUnsafe(core.layers[l][leftIndex.group], leftNodeIndex, _P);
leftNodeIndex =1;
}
if (rightIndex.group %4==0) {
ret += DirtyUint64.sumPackedUnsafe(core.layers[l][rightIndex.group], 0, rightNodeIndex);
rightNodeIndex =0;
} elseif (rightIndex.group %4==1) {
ret += DirtyUint64.sumPackedUnsafe(core.layers[l][rightIndex.group -1], 0, _P);
ret += DirtyUint64.sumPackedUnsafe(core.layers[l][rightIndex.group], 0, rightNodeIndex);
rightNodeIndex =0;
} elseif (rightIndex.group %4==2) {
deficit += DirtyUint64.sumPackedUnsafe(core.layers[l][rightIndex.group], rightNodeIndex, _P);
deficit += DirtyUint64.sumPackedUnsafe(core.layers[l][rightIndex.group +1], 0, _P);
rightNodeIndex =1;
} else {
deficit += DirtyUint64.sumPackedUnsafe(core.layers[l][rightIndex.group], rightNodeIndex, _P);
rightNodeIndex =1;
}
}
ret -= deficit;
}
sum =uint64(ret);
}
functionupdate(Core storage core, uint256 index, uint64 value) internalreturns (uint64 replaced) {
if (index >= _MAX_NODES) {
revert SegmentedSegmentTreeError(_INDEX_ERROR);
}
LayerIndex[] memory indices = _getLayerIndices(index);
unchecked {
LayerIndex memory bottomIndex = indices[_L -1];
replaced = core.layers[_L -1][bottomIndex.group].get64Unsafe(bottomIndex.node).toClean();
if (replaced >= value) {
uint64 diff = replaced - value;
for (uint256 l =0; l < _L; ++l) {
LayerIndex memory layerIndex = indices[l];
uint256 node = core.layers[l][layerIndex.group];
core.layers[l][layerIndex.group] =
node.update64(layerIndex.node, node.get64(layerIndex.node).subClean(diff));
}
} else {
uint64 diff = value - replaced;
if (total(core) >type(uint64).max- diff) revert SegmentedSegmentTreeError(_OVERFLOW_ERROR);
for (uint256 l =0; l < _L; ++l) {
LayerIndex memory layerIndex = indices[l];
uint256 node = core.layers[l][layerIndex.group];
core.layers[l][layerIndex.group] =
node.update64(layerIndex.node, node.get64(layerIndex.node).addClean(diff));
}
}
}
}
function_getLayerIndices(uint256 index) privatepurereturns (LayerIndex[] memory) {
unchecked {
LayerIndex[] memory indices =new LayerIndex[](_L);
uint256 shifter = _MAX_NODES_P_MINUS_ONE;
for (uint256 l =0; l < _L; ++l) {
indices[l] = LayerIndex({group: index >> shifter, node: (index >> (shifter - _P_P)) & _P_M});
shifter = shifter - _N_P;
}
return indices;
}
}
}
/*
* Segmented Segment Tree is a Segment Tree
* that has been compressed so that `C` nodes
* are compressed into a single uint256.
*
* Each node in a non-leaf node group is the sum of the
* total sum of each child node group that it represents.
* Each non-leaf node represents `E` node groups.
*
* A node group consists of `S` uint256.
*
* By expressing the index in `N` notation,
* we can find the index in each respective layer
*
* S: Size of each node group
* C: Compression Coefficient
* E: Expansion Coefficient
* L: Number of Layers
* N: Notation, S * C * E
*
* `E` will not be considered for this version of the implementation. (E = 2)
*/
Contract Source Code
File 36 of 44: ShortStrings.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v5.0.0) (utils/ShortStrings.sol)pragmasolidity ^0.8.20;import {StorageSlot} from"./StorageSlot.sol";
// | string | 0xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA |// | length | 0x BB |type ShortString isbytes32;
/**
* @dev This library provides functions to convert short memory strings
* into a `ShortString` type that can be used as an immutable variable.
*
* Strings of arbitrary length can be optimized using this library if
* they are short enough (up to 31 bytes) by packing them with their
* length (1 byte) in a single EVM word (32 bytes). Additionally, a
* fallback mechanism can be used for every other case.
*
* Usage example:
*
* ```solidity
* contract Named {
* using ShortStrings for *;
*
* ShortString private immutable _name;
* string private _nameFallback;
*
* constructor(string memory contractName) {
* _name = contractName.toShortStringWithFallback(_nameFallback);
* }
*
* function name() external view returns (string memory) {
* return _name.toStringWithFallback(_nameFallback);
* }
* }
* ```
*/libraryShortStrings{
// Used as an identifier for strings longer than 31 bytes.bytes32privateconstant FALLBACK_SENTINEL =0x00000000000000000000000000000000000000000000000000000000000000FF;
errorStringTooLong(string str);
errorInvalidShortString();
/**
* @dev Encode a string of at most 31 chars into a `ShortString`.
*
* This will trigger a `StringTooLong` error is the input string is too long.
*/functiontoShortString(stringmemory str) internalpurereturns (ShortString) {
bytesmemory bstr =bytes(str);
if (bstr.length>31) {
revert StringTooLong(str);
}
return ShortString.wrap(bytes32(uint256(bytes32(bstr)) | bstr.length));
}
/**
* @dev Decode a `ShortString` back to a "normal" string.
*/functiontoString(ShortString sstr) internalpurereturns (stringmemory) {
uint256 len = byteLength(sstr);
// using `new string(len)` would work locally but is not memory safe.stringmemory str =newstring(32);
/// @solidity memory-safe-assemblyassembly {
mstore(str, len)
mstore(add(str, 0x20), sstr)
}
return str;
}
/**
* @dev Return the length of a `ShortString`.
*/functionbyteLength(ShortString sstr) internalpurereturns (uint256) {
uint256 result =uint256(ShortString.unwrap(sstr)) &0xFF;
if (result >31) {
revert InvalidShortString();
}
return result;
}
/**
* @dev Encode a string into a `ShortString`, or write it to storage if it is too long.
*/functiontoShortStringWithFallback(stringmemory value, stringstorage store) internalreturns (ShortString) {
if (bytes(value).length<32) {
return toShortString(value);
} else {
StorageSlot.getStringSlot(store).value= value;
return ShortString.wrap(FALLBACK_SENTINEL);
}
}
/**
* @dev Decode a string that was encoded to `ShortString` or written to storage using {setWithFallback}.
*/functiontoStringWithFallback(ShortString value, stringstorage store) internalpurereturns (stringmemory) {
if (ShortString.unwrap(value) != FALLBACK_SENTINEL) {
return toString(value);
} else {
return store;
}
}
/**
* @dev Return the length of a string that was encoded to `ShortString` or written to storage using
* {setWithFallback}.
*
* WARNING: This will return the "byte length" of the string. This may not reflect the actual length in terms of
* actual characters as the UTF-8 encoding of a single character can span over multiple bytes.
*/functionbyteLengthWithFallback(ShortString value, stringstorage store) internalviewreturns (uint256) {
if (ShortString.unwrap(value) != FALLBACK_SENTINEL) {
return byteLength(value);
} else {
returnbytes(store).length;
}
}
}
Contract Source Code
File 37 of 44: SignedMath.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v5.0.0) (utils/math/SignedMath.sol)pragmasolidity ^0.8.20;/**
* @dev Standard signed math utilities missing in the Solidity language.
*/librarySignedMath{
/**
* @dev Returns the largest of two signed numbers.
*/functionmax(int256 a, int256 b) internalpurereturns (int256) {
return a > b ? a : b;
}
/**
* @dev Returns the smallest of two signed numbers.
*/functionmin(int256 a, int256 b) internalpurereturns (int256) {
return a < b ? a : b;
}
/**
* @dev Returns the average of two signed numbers without overflow.
* The result is rounded towards zero.
*/functionaverage(int256 a, int256 b) internalpurereturns (int256) {
// Formula from the book "Hacker's Delight"int256 x = (a & b) + ((a ^ b) >>1);
return x + (int256(uint256(x) >>255) & (a ^ b));
}
/**
* @dev Returns the absolute unsigned value of a signed value.
*/functionabs(int256 n) internalpurereturns (uint256) {
unchecked {
// Formula from the "Bit Twiddling Hacks" by Sean Eron Anderson.// Since `n` is a signed integer, the generated bytecode will use the SAR opcode to perform the right shift,// taking advantage of the most significant (or "sign" bit) in two's complement representation.// This opcode adds new most significant bits set to the value of the previous most significant bit. As a result,// the mask will either be `bytes(0)` (if n is positive) or `~bytes32(0)` (if n is negative).int256 mask = n >>255;
// A `bytes(0)` mask leaves the input unchanged, while a `~bytes32(0)` mask complements it.returnuint256((n + mask) ^ mask);
}
}
}
Contract Source Code
File 38 of 44: SignificantBit.sol
// SPDX-License-Identifier: GPL-2.0-or-laterpragmasolidity ^0.8.0;librarySignificantBit{
// http://supertech.csail.mit.edu/papers/debruijn.pdfuint256internalconstant DEBRUIJN_SEQ =0x818283848586878898A8B8C8D8E8F929395969799A9B9D9E9FAAEB6BEDEEFF;
bytesinternalconstant DEBRUIJN_INDEX =hex"0001020903110a19042112290b311a3905412245134d2a550c5d32651b6d3a7506264262237d468514804e8d2b95569d0d495ea533a966b11c886eb93bc176c9071727374353637324837e9b47af86c7155181ad4fd18ed32c9096db57d59ee30e2e4a6a5f92a6be3498aae067ddb2eb1d5989b56fd7baf33ca0c2ee77e5caf7ff0810182028303840444c545c646c7425617c847f8c949c48a4a8b087b8c0c816365272829aaec650acd0d28fdad4e22d6991bd97dfdcea58b4d6f29fede4f6fe0f1f2f3f4b5b6b607b8b93a3a7b7bf357199c5abcfd9e168bcdee9b3f1ecf5fd1e3e5a7a8aa2b670c4ced8bbe8f0f4fc3d79a1c3cde7effb78cce6facbf9f8";
/**
* @notice Finds the index of the least significant bit.
* @param x The value to compute the least significant bit for. Must be a non-zero value.
* @return ret The index of the least significant bit.
*/functionleastSignificantBit(uint256 x) internalpurereturns (uint8) {
require(x >0);
uint256 index;
assembly {
index :=shr(248, mul(and(x, add(not(x), 1)), DEBRUIJN_SEQ))
}
returnuint8(DEBRUIJN_INDEX[index]); // can optimize with CODECOPY opcode
}
functionmostSignificantBit(uint256 x) internalpurereturns (uint8 msb) {
require(x >0);
assembly {
let f :=shl(7, gt(x, 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF))
msb :=or(msb, f)
x :=shr(f, x)
f :=shl(6, gt(x, 0xFFFFFFFFFFFFFFFF))
msb :=or(msb, f)
x :=shr(f, x)
f :=shl(5, gt(x, 0xFFFFFFFF))
msb :=or(msb, f)
x :=shr(f, x)
f :=shl(4, gt(x, 0xFFFF))
msb :=or(msb, f)
x :=shr(f, x)
f :=shl(3, gt(x, 0xFF))
msb :=or(msb, f)
x :=shr(f, x)
f :=shl(2, gt(x, 0xF))
msb :=or(msb, f)
x :=shr(f, x)
f :=shl(1, gt(x, 0x3))
msb :=or(msb, f)
x :=shr(f, x)
f :=gt(x, 0x1)
msb :=or(msb, f)
}
}
}
Contract Source Code
File 39 of 44: StorageSlot.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v5.0.0) (utils/StorageSlot.sol)// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.pragmasolidity ^0.8.24;/**
* @dev Library for reading and writing primitive types to specific storage slots.
*
* Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.
* This library helps with reading and writing to such slots without the need for inline assembly.
*
* The functions in this library return Slot structs that contain a `value` member that can be used to read or write.
*
* Example usage to set ERC-1967 implementation slot:
* ```solidity
* contract ERC1967 {
* // Define the slot. Alternatively, use the SlotDerivation library to derive the slot.
* bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
*
* function _getImplementation() internal view returns (address) {
* return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
* }
*
* function _setImplementation(address newImplementation) internal {
* require(newImplementation.code.length > 0);
* StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
* }
* }
* ```
*
* Since version 5.1, this library also support writing and reading value types to and from transient storage.
*
* * Example using transient storage:
* ```solidity
* contract Lock {
* // Define the slot. Alternatively, use the SlotDerivation library to derive the slot.
* bytes32 internal constant _LOCK_SLOT = 0xf4678858b2b588224636b8522b729e7722d32fc491da849ed75b3fdf3c84f542;
*
* modifier locked() {
* require(!_LOCK_SLOT.asBoolean().tload());
*
* _LOCK_SLOT.asBoolean().tstore(true);
* _;
* _LOCK_SLOT.asBoolean().tstore(false);
* }
* }
* ```
*
* TIP: Consider using this library along with {SlotDerivation}.
*/libraryStorageSlot{
structAddressSlot {
address value;
}
structBooleanSlot {
bool value;
}
structBytes32Slot {
bytes32 value;
}
structUint256Slot {
uint256 value;
}
structInt256Slot {
int256 value;
}
structStringSlot {
string value;
}
structBytesSlot {
bytes value;
}
/**
* @dev Returns an `AddressSlot` with member `value` located at `slot`.
*/functiongetAddressSlot(bytes32 slot) internalpurereturns (AddressSlot storage r) {
/// @solidity memory-safe-assemblyassembly {
r.slot:= slot
}
}
/**
* @dev Returns an `BooleanSlot` with member `value` located at `slot`.
*/functiongetBooleanSlot(bytes32 slot) internalpurereturns (BooleanSlot storage r) {
/// @solidity memory-safe-assemblyassembly {
r.slot:= slot
}
}
/**
* @dev Returns an `Bytes32Slot` with member `value` located at `slot`.
*/functiongetBytes32Slot(bytes32 slot) internalpurereturns (Bytes32Slot storage r) {
/// @solidity memory-safe-assemblyassembly {
r.slot:= slot
}
}
/**
* @dev Returns an `Uint256Slot` with member `value` located at `slot`.
*/functiongetUint256Slot(bytes32 slot) internalpurereturns (Uint256Slot storage r) {
/// @solidity memory-safe-assemblyassembly {
r.slot:= slot
}
}
/**
* @dev Returns an `Int256Slot` with member `value` located at `slot`.
*/functiongetInt256Slot(bytes32 slot) internalpurereturns (Int256Slot storage r) {
/// @solidity memory-safe-assemblyassembly {
r.slot:= slot
}
}
/**
* @dev Returns an `StringSlot` with member `value` located at `slot`.
*/functiongetStringSlot(bytes32 slot) internalpurereturns (StringSlot storage r) {
/// @solidity memory-safe-assemblyassembly {
r.slot:= slot
}
}
/**
* @dev Returns an `StringSlot` representation of the string storage pointer `store`.
*/functiongetStringSlot(stringstorage store) internalpurereturns (StringSlot storage r) {
/// @solidity memory-safe-assemblyassembly {
r.slot:= store.slot
}
}
/**
* @dev Returns an `BytesSlot` with member `value` located at `slot`.
*/functiongetBytesSlot(bytes32 slot) internalpurereturns (BytesSlot storage r) {
/// @solidity memory-safe-assemblyassembly {
r.slot:= slot
}
}
/**
* @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.
*/functiongetBytesSlot(bytesstorage store) internalpurereturns (BytesSlot storage r) {
/// @solidity memory-safe-assemblyassembly {
r.slot:= store.slot
}
}
/**
* @dev UDVT that represent a slot holding a address.
*/type AddressSlotType isbytes32;
/**
* @dev Cast an arbitrary slot to a AddressSlotType.
*/functionasAddress(bytes32 slot) internalpurereturns (AddressSlotType) {
return AddressSlotType.wrap(slot);
}
/**
* @dev UDVT that represent a slot holding a bool.
*/type BooleanSlotType isbytes32;
/**
* @dev Cast an arbitrary slot to a BooleanSlotType.
*/functionasBoolean(bytes32 slot) internalpurereturns (BooleanSlotType) {
return BooleanSlotType.wrap(slot);
}
/**
* @dev UDVT that represent a slot holding a bytes32.
*/type Bytes32SlotType isbytes32;
/**
* @dev Cast an arbitrary slot to a Bytes32SlotType.
*/functionasBytes32(bytes32 slot) internalpurereturns (Bytes32SlotType) {
return Bytes32SlotType.wrap(slot);
}
/**
* @dev UDVT that represent a slot holding a uint256.
*/type Uint256SlotType isbytes32;
/**
* @dev Cast an arbitrary slot to a Uint256SlotType.
*/functionasUint256(bytes32 slot) internalpurereturns (Uint256SlotType) {
return Uint256SlotType.wrap(slot);
}
/**
* @dev UDVT that represent a slot holding a int256.
*/type Int256SlotType isbytes32;
/**
* @dev Cast an arbitrary slot to a Int256SlotType.
*/functionasInt256(bytes32 slot) internalpurereturns (Int256SlotType) {
return Int256SlotType.wrap(slot);
}
/**
* @dev Load the value held at location `slot` in transient storage.
*/functiontload(AddressSlotType slot) internalviewreturns (address value) {
/// @solidity memory-safe-assemblyassembly {
value := tload(slot)
}
}
/**
* @dev Store `value` at location `slot` in transient storage.
*/functiontstore(AddressSlotType slot, address value) internal{
/// @solidity memory-safe-assemblyassembly {
tstore(slot, value)
}
}
/**
* @dev Load the value held at location `slot` in transient storage.
*/functiontload(BooleanSlotType slot) internalviewreturns (bool value) {
/// @solidity memory-safe-assemblyassembly {
value := tload(slot)
}
}
/**
* @dev Store `value` at location `slot` in transient storage.
*/functiontstore(BooleanSlotType slot, bool value) internal{
/// @solidity memory-safe-assemblyassembly {
tstore(slot, value)
}
}
/**
* @dev Load the value held at location `slot` in transient storage.
*/functiontload(Bytes32SlotType slot) internalviewreturns (bytes32 value) {
/// @solidity memory-safe-assemblyassembly {
value := tload(slot)
}
}
/**
* @dev Store `value` at location `slot` in transient storage.
*/functiontstore(Bytes32SlotType slot, bytes32 value) internal{
/// @solidity memory-safe-assemblyassembly {
tstore(slot, value)
}
}
/**
* @dev Load the value held at location `slot` in transient storage.
*/functiontload(Uint256SlotType slot) internalviewreturns (uint256 value) {
/// @solidity memory-safe-assemblyassembly {
value := tload(slot)
}
}
/**
* @dev Store `value` at location `slot` in transient storage.
*/functiontstore(Uint256SlotType slot, uint256 value) internal{
/// @solidity memory-safe-assemblyassembly {
tstore(slot, value)
}
}
/**
* @dev Load the value held at location `slot` in transient storage.
*/functiontload(Int256SlotType slot) internalviewreturns (int256 value) {
/// @solidity memory-safe-assemblyassembly {
value := tload(slot)
}
}
/**
* @dev Store `value` at location `slot` in transient storage.
*/functiontstore(Int256SlotType slot, int256 value) internal{
/// @solidity memory-safe-assemblyassembly {
tstore(slot, value)
}
}
}
Contract Source Code
File 40 of 44: Strings.sol
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v5.0.0) (utils/Strings.sol)pragmasolidity ^0.8.20;import {Math} from"./math/Math.sol";
import {SignedMath} from"./math/SignedMath.sol";
/**
* @dev String operations.
*/libraryStrings{
bytes16privateconstant HEX_DIGITS ="0123456789abcdef";
uint8privateconstant ADDRESS_LENGTH =20;
/**
* @dev The `value` string doesn't fit in the specified `length`.
*/errorStringsInsufficientHexLength(uint256 value, uint256 length);
/**
* @dev Converts a `uint256` to its ASCII `string` decimal representation.
*/functiontoString(uint256 value) internalpurereturns (stringmemory) {
unchecked {
uint256 length = Math.log10(value) +1;
stringmemory buffer =newstring(length);
uint256 ptr;
/// @solidity memory-safe-assemblyassembly {
ptr :=add(buffer, add(32, length))
}
while (true) {
ptr--;
/// @solidity memory-safe-assemblyassembly {
mstore8(ptr, byte(mod(value, 10), HEX_DIGITS))
}
value /=10;
if (value ==0) break;
}
return buffer;
}
}
/**
* @dev Converts a `int256` to its ASCII `string` decimal representation.
*/functiontoStringSigned(int256 value) internalpurereturns (stringmemory) {
returnstring.concat(value <0 ? "-" : "", toString(SignedMath.abs(value)));
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
*/functiontoHexString(uint256 value) internalpurereturns (stringmemory) {
unchecked {
return toHexString(value, Math.log256(value) +1);
}
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
*/functiontoHexString(uint256 value, uint256 length) internalpurereturns (stringmemory) {
uint256 localValue = value;
bytesmemory buffer =newbytes(2* length +2);
buffer[0] ="0";
buffer[1] ="x";
for (uint256 i =2* length +1; i >1; --i) {
buffer[i] = HEX_DIGITS[localValue &0xf];
localValue >>=4;
}
if (localValue !=0) {
revert StringsInsufficientHexLength(value, length);
}
returnstring(buffer);
}
/**
* @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal
* representation.
*/functiontoHexString(address addr) internalpurereturns (stringmemory) {
return toHexString(uint256(uint160(addr)), ADDRESS_LENGTH);
}
/**
* @dev Returns true if the two strings are equal.
*/functionequal(stringmemory a, stringmemory b) internalpurereturns (bool) {
returnbytes(a).length==bytes(b).length&&keccak256(bytes(a)) ==keccak256(bytes(b));
}
}
// SPDX-License-Identifier: MIT// OpenZeppelin Contracts (last updated v5.0.0) (interfaces/draft-IERC6093.sol)pragmasolidity ^0.8.20;/**
* @dev Standard ERC-20 Errors
* Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-20 tokens.
*/interfaceIERC20Errors{
/**
* @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
* @param balance Current balance for the interacting account.
* @param needed Minimum amount required to perform a transfer.
*/errorERC20InsufficientBalance(address sender, uint256 balance, uint256 needed);
/**
* @dev Indicates a failure with the token `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
*/errorERC20InvalidSender(address sender);
/**
* @dev Indicates a failure with the token `receiver`. Used in transfers.
* @param receiver Address to which tokens are being transferred.
*/errorERC20InvalidReceiver(address receiver);
/**
* @dev Indicates a failure with the `spender`’s `allowance`. Used in transfers.
* @param spender Address that may be allowed to operate on tokens without being their owner.
* @param allowance Amount of tokens a `spender` is allowed to operate with.
* @param needed Minimum amount required to perform a transfer.
*/errorERC20InsufficientAllowance(address spender, uint256 allowance, uint256 needed);
/**
* @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
* @param approver Address initiating an approval operation.
*/errorERC20InvalidApprover(address approver);
/**
* @dev Indicates a failure with the `spender` to be approved. Used in approvals.
* @param spender Address that may be allowed to operate on tokens without being their owner.
*/errorERC20InvalidSpender(address spender);
}
/**
* @dev Standard ERC-721 Errors
* Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-721 tokens.
*/interfaceIERC721Errors{
/**
* @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in ERC-20.
* Used in balance queries.
* @param owner Address of the current owner of a token.
*/errorERC721InvalidOwner(address owner);
/**
* @dev Indicates a `tokenId` whose `owner` is the zero address.
* @param tokenId Identifier number of a token.
*/errorERC721NonexistentToken(uint256 tokenId);
/**
* @dev Indicates an error related to the ownership over a particular token. Used in transfers.
* @param sender Address whose tokens are being transferred.
* @param tokenId Identifier number of a token.
* @param owner Address of the current owner of a token.
*/errorERC721IncorrectOwner(address sender, uint256 tokenId, address owner);
/**
* @dev Indicates a failure with the token `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
*/errorERC721InvalidSender(address sender);
/**
* @dev Indicates a failure with the token `receiver`. Used in transfers.
* @param receiver Address to which tokens are being transferred.
*/errorERC721InvalidReceiver(address receiver);
/**
* @dev Indicates a failure with the `operator`’s approval. Used in transfers.
* @param operator Address that may be allowed to operate on tokens without being their owner.
* @param tokenId Identifier number of a token.
*/errorERC721InsufficientApproval(address operator, uint256 tokenId);
/**
* @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
* @param approver Address initiating an approval operation.
*/errorERC721InvalidApprover(address approver);
/**
* @dev Indicates a failure with the `operator` to be approved. Used in approvals.
* @param operator Address that may be allowed to operate on tokens without being their owner.
*/errorERC721InvalidOperator(address operator);
}
/**
* @dev Standard ERC-1155 Errors
* Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC-1155 tokens.
*/interfaceIERC1155Errors{
/**
* @dev Indicates an error related to the current `balance` of a `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
* @param balance Current balance for the interacting account.
* @param needed Minimum amount required to perform a transfer.
* @param tokenId Identifier number of a token.
*/errorERC1155InsufficientBalance(address sender, uint256 balance, uint256 needed, uint256 tokenId);
/**
* @dev Indicates a failure with the token `sender`. Used in transfers.
* @param sender Address whose tokens are being transferred.
*/errorERC1155InvalidSender(address sender);
/**
* @dev Indicates a failure with the token `receiver`. Used in transfers.
* @param receiver Address to which tokens are being transferred.
*/errorERC1155InvalidReceiver(address receiver);
/**
* @dev Indicates a failure with the `operator`’s approval. Used in transfers.
* @param operator Address that may be allowed to operate on tokens without being their owner.
* @param owner Address of the current owner of a token.
*/errorERC1155MissingApprovalForAll(address operator, address owner);
/**
* @dev Indicates a failure with the `approver` of a token to be approved. Used in approvals.
* @param approver Address initiating an approval operation.
*/errorERC1155InvalidApprover(address approver);
/**
* @dev Indicates a failure with the `operator` to be approved. Used in approvals.
* @param operator Address that may be allowed to operate on tokens without being their owner.
*/errorERC1155InvalidOperator(address operator);
/**
* @dev Indicates an array length mismatch between ids and values in a safeBatchTransferFrom operation.
* Used in batch transfers.
* @param idsLength Length of the array of token identifiers
* @param valuesLength Length of the array of token amounts
*/errorERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength);
}