@ensuro/core
Version:
Ensuro - Blockchain-based insurance protocol
1 lines • 15.9 MB
JSON
{"id":"354263644bef5d184eb8890471e404f0","_format":"hh-sol-build-info-1","solcVersion":"0.8.30","solcLongVersion":"0.8.30+commit.73712a01","input":{"language":"Solidity","sources":{"@ensuro/access-managed-proxy/contracts/AccessManagedProxy.sol":{"content":"// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.0;\n\nimport {IAccessManager} from \"@openzeppelin/contracts/access/manager/IAccessManager.sol\";\nimport {IAccessManagedProxy} from \"./interfaces/IAccessManagedProxy.sol\";\nimport {AccessManagedProxyBase} from \"./AccessManagedProxyBase.sol\";\nimport {AMPUtils} from \"./AMPUtils.sol\";\n\n/**\n * @title AccessManagedProxy\n * @notice Proxy contract using IAccessManager to manage access control before delegating calls (mutable version)\n * @dev It's a variant of ERC1967Proxy.\n *\n * Currently the check is executed on any call received by the proxy contract (even calls to view methods, i.e.\n * staticcall). For gas efficiency, you can also have `passThruMethods`, and for those methods it will skip\n * the call to the AccessManager, calling directly to the implementation contract.\n *\n * The accessManager and the passThruMethods are in the storage, but this contract doesn't include any method\n * to modify them. They should be modified by the implementation contract (check AMPUtils for functions that\n * encapsulate these operations).\n *\n * Check https://forum.openzeppelin.com/t/accessmanagedproxy-is-a-good-idea/41917 for a discussion on the\n * advantages and disadvantages of using it. Also https://www.youtube.com/watch?v=DKdwJ9Ap9vM for a presentation\n * on this approach.\n *\n * @custom:security-contact security@ensuro.co\n * @author Ensuro\n */\ncontract AccessManagedProxy is AccessManagedProxyBase {\n /// @custom:storage-location erc7201:ensuro.storage.AccessManagedProxy\n /// For struct AMPUtils.AccessManagedProxyStorage\n\n /**\n * @notice Constructor of the proxy, defining the implementation and the access manager\n * @dev Initializes the upgradeable proxy with an initial implementation specified by `implementation` and\n * with `accessManager` as the ACCESS_MANAGER that will handle access control.\n *\n * @param implementation The initial implementation contract.\n * @param _data If nonempty, it's used as data in a delegate call to `implementation`. This will typically be an\n * encoded function call, and allows initializing the storage of the proxy like a Solidity constructor.\n * @param accessManager The access manager that will handle access control\n * @param passThruMethods The selector of methods that will skip the access control validation, typically used for\n * views and other methods for gas optimization.\n *\n * @custom:pre If `_data` is empty, `msg.value` must be zero.\n */\n constructor(\n address implementation,\n bytes memory _data,\n IAccessManager accessManager,\n bytes4[] memory passThruMethods\n ) payable AccessManagedProxyBase(implementation, _data) {\n AMPUtils.setAccessManager(accessManager);\n AMPUtils.setPassThruMethods(passThruMethods);\n }\n\n /// @inheritdoc AccessManagedProxyBase\n function _skipAC(bytes4 selector) internal view override returns (bool) {\n return AMPUtils.getAccessManagedProxyStorage().skipAc[selector];\n }\n\n /// @inheritdoc IAccessManagedProxy\n // solhint-disable-next-line func-name-mixedcase\n function PASS_THRU_METHODS() external view override returns (bytes4[] memory methods) {\n return AMPUtils.getAccessManagedProxyStorage().passThruMethods;\n }\n\n /// @inheritdoc IAccessManagedProxy\n // solhint-disable-next-line func-name-mixedcase\n function ACCESS_MANAGER() public view override returns (IAccessManager) {\n return AMPUtils.getAccessManagedProxyStorage().accessManager;\n }\n}\n"},"@ensuro/access-managed-proxy/contracts/AccessManagedProxyBase.sol":{"content":"// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.0;\n\nimport {ERC1967Proxy} from \"@openzeppelin/contracts/proxy/ERC1967/ERC1967Proxy.sol\";\nimport {IAccessManager} from \"@openzeppelin/contracts/access/manager/IAccessManager.sol\";\nimport {IAccessManagedProxy} from \"./interfaces/IAccessManagedProxy.sol\";\n\n/**\n * @title AccessManagedProxyBase\n * @notice Proxy contract using IAccessManager to manage access control before delegating calls.\n * @dev It's a variant of ERC1967Proxy.\n *\n * Currently the check is executed on any call received by the proxy contract even calls to view methods\n * (staticcall). In the setup of the ACCESS_MANAGER permissions you would want to make all the views and pure\n * functions enabled for the PUBLIC_ROLE.\n *\n * This base contract delegates on descendent contracts the storage of the ACCESS_MANAGER.\n *\n * Check https://forum.openzeppelin.com/t/accessmanagedproxy-is-a-good-idea/41917 for a discussion on the\n * advantages and disadvantages of using it.\n *\n * @custom:security-contact security@ensuro.co\n * @author Ensuro\n */\nabstract contract AccessManagedProxyBase is ERC1967Proxy, IAccessManagedProxy {\n bytes4 internal constant RECEIVE_SELECTOR = bytes4(keccak256(\"receive\"));\n bytes4 internal constant FALLBACK_SELECTOR = bytes4(keccak256(\"fallback\"));\n\n /**\n * @notice Constructor of the proxy, defining the implementation and the access manager\n * @dev Initializes the upgradeable proxy with an initial implementation specified by `implementation` and\n * with `manager` as the ACCESS_MANAGER that will handle access control.\n *\n * @param implementation The initial implementation contract.\n * @param _data If nonempty, it's used as data in a delegate call to `implementation`. This will typically be an\n * encoded function call, and allows initializing the storage of the proxy like a Solidity constructor.\n *\n * @custom:pre If `_data` is empty, `msg.value` must be zero.\n */\n constructor(address implementation, bytes memory _data) payable ERC1967Proxy(implementation, _data) {}\n\n /// @inheritdoc IAccessManagedProxy\n // solhint-disable-next-line func-name-mixedcase\n function ACCESS_MANAGER() public view virtual returns (IAccessManager);\n\n /// @inheritdoc IAccessManagedProxy\n function authority() external view virtual returns (address) {\n return address(ACCESS_MANAGER());\n }\n\n /**\n * @notice Intercepts the super._delegate call to implement access control\n * @dev Checks with the ACCESS_MANAGER if msg.sender is authorized to call the current call's function,\n * and if so, delegates the current call to `implementation`.\n * @param implementation The implementation contract\n *\n * This function does not return to its internal call site, it will return directly to the external caller.\n */\n function _delegate(address implementation) internal virtual override {\n bytes4 selector = msg.data.length < 4\n ? (msg.data.length == 0 ? RECEIVE_SELECTOR : FALLBACK_SELECTOR)\n : bytes4(msg.data[0:4]);\n bool immediate = _skipAC(selector); // reuse immediate variable both for skipped methods and canCall result\n if (!immediate) {\n (immediate, ) = ACCESS_MANAGER().canCall(msg.sender, address(this), selector);\n if (!immediate) revert AccessManagedUnauthorized(msg.sender);\n }\n super._delegate(implementation);\n }\n\n /**\n * @notice Returns whether to skip the access control validation or not\n * @dev Hook called before ACCESS_MANAGER.canCall to enable skipping the call to the access manager for performance\n * reasons (for example on views) or to remove access control for other specific cases\n * @param selector The selector of the method called\n * @return Whether the access control using ACCESS_MANAGER should be skipped or not\n */\n function _skipAC(bytes4 selector) internal view virtual returns (bool);\n}\n"},"@ensuro/access-managed-proxy/contracts/AMPUtils.sol":{"content":"// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.0;\n\nimport {IAccessManager} from \"@openzeppelin/contracts/access/manager/IAccessManager.sol\";\nimport {IAccessManagedProxy} from \"./interfaces/IAccessManagedProxy.sol\";\n\n/**\n * @title AMPUtils\n * @dev Utility functions for doing custom access control rules, for contracts deployed\n * with AccessManagedProxy\n * @author Ensuro\n */\nlibrary AMPUtils {\n // Error copied from IAccessManaged\n error AccessManagedUnauthorized(address caller);\n\n struct AccessManagedProxyStorage {\n IAccessManager accessManager;\n bytes4[] passThruMethods; // This is used for observability\n mapping(bytes4 => bool) skipAc; // This is the used for actual lookup\n }\n\n /**\n * @notice Storage slot with the address of the current access mananger.\n * @dev Computed as: `keccak256(\n * abi.encode(uint256(keccak256(\"ensuro.storage.AccessManagedProxy\")) - 1)\n * ) & ~bytes32(uint256(0xff))\n */\n // solhint-disable-next-line const-name-snakecase\n bytes32 internal constant AccessManagedProxyStorageLocation =\n 0x787c9d7ac910d64252bcea05acd5b7af6d59644e0451a8bb5674587555049c00;\n\n function getAccessManagedProxyStorage() internal pure returns (AccessManagedProxyStorage storage $) {\n // solhint-disable-next-line no-inline-assembly\n assembly {\n $.slot := AccessManagedProxyStorageLocation\n }\n }\n\n function setAccessManager(IAccessManager accessManager) internal {\n if (address(accessManager).code.length == 0) {\n revert IAccessManagedProxy.AccessManagedInvalidAuthority(address(accessManager));\n }\n getAccessManagedProxyStorage().accessManager = accessManager;\n emit IAccessManagedProxy.AuthorityUpdated(address(accessManager));\n }\n\n function setPassThruMethods(bytes4[] memory passThruMethods) internal {\n AccessManagedProxyStorage storage $ = AMPUtils.getAccessManagedProxyStorage();\n $.passThruMethods = new bytes4[](passThruMethods.length);\n for (uint256 i; i < passThruMethods.length; ++i) {\n $.passThruMethods[i] = passThruMethods[i];\n $.skipAc[passThruMethods[i]] = true;\n }\n emit IAccessManagedProxy.PassThruMethodsChanged(passThruMethods);\n }\n\n function replacePassThruMethods(bytes4[] memory newPassThruMethods) internal {\n AccessManagedProxyStorage storage $ = AMPUtils.getAccessManagedProxyStorage();\n bytes4[] memory oldPassThruMethods = $.passThruMethods;\n for (uint256 i; i < oldPassThruMethods.length; ++i) {\n $.skipAc[oldPassThruMethods[i]] = false;\n }\n setPassThruMethods(newPassThruMethods);\n }\n\n /**\n * @dev Checks if the user can call a particular selector, assuming the calling contract was deployed as an AMP.\n *\n * @param user The user for which you want to check the access, typically msg.sender\n * @param selector The selector of the method called (or a fake selector generated with makeSelector or another way)\n */\n function checkCanCall(address user, bytes4 selector) internal view {\n (bool immediate, ) = IAccessManagedProxy(payable(address(this))).ACCESS_MANAGER().canCall(\n user,\n address(this),\n selector\n );\n require(immediate, AccessManagedUnauthorized(user));\n }\n\n /**\n * @dev Standard way of creating \"fake selectors\" (not necessarily tied to a method call) for specific permissions\n */\n function makeSelector(bytes memory something) internal pure returns (bytes4) {\n return bytes4(keccak256(something));\n }\n}\n"},"@ensuro/access-managed-proxy/contracts/interfaces/IAccessManagedProxy.sol":{"content":"// SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.28;\n\nimport {IAccessManager} from \"@openzeppelin/contracts/access/manager/IAccessManager.sol\";\n\n/**\n * @title IAccessManagedProxy - Interface of AccessManagedProxy contracts\n * @notice This interface gives observability of the access control setup\n *\n * @dev The `ACCESS_MANAGER()` is the AccessManager contract that stores the access roles for most of the methods,\n * except those listed in `PASS_THRU_METHODS()` that are forwarded directly to the proxy and don't have access control\n * (at least not by the AccessManager contract).\n *\n * @author Ensuro\n */\ninterface IAccessManagedProxy {\n /**\n * @notice The ACCESS_MANAGER that manages the access controls was updated\n * @dev Authority that manages this contract was updated. Uses same interface as OZ's IAccessManaged\n */\n // solhint-disable-next-line gas-indexed-events\n event AuthorityUpdated(address authority);\n\n /**\n * @dev Emitted when the passThruMethods has changed.\n */\n event PassThruMethodsChanged(bytes4[] newPassThruMethods);\n\n // Errors copied from OZ's IAccessManaged\n error AccessManagedUnauthorized(address caller);\n error AccessManagedInvalidAuthority(address authority);\n\n /**\n * @notice Returns the current authority.\n * @dev Returns the current authority. Same as ACCESS_MANAGER(), added for compatibility with OZ's IAccessManaged\n */\n function authority() external view returns (address);\n\n /**\n * @notice AccessManager contract that handles the permissions to access the implementation methods\n */\n // solhint-disable-next-line func-name-mixedcase\n function ACCESS_MANAGER() external view returns (IAccessManager);\n\n /**\n * @notice Gives observability to the methods that are skipped from access control\n * @return methods The list of method selectors that skip ACCESS_MANAGER access control\n */\n // solhint-disable-next-line func-name-mixedcase\n function PASS_THRU_METHODS() external view returns (bytes4[] memory methods);\n}\n"},"@ensuro/utils/contracts/TestCurrency.sol":{"content":"//SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.0;\n\nimport {ERC20} from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\n\ncontract TestCurrency is ERC20 {\n uint8 internal immutable _decimals;\n\n constructor(\n string memory name_,\n string memory symbol_,\n uint256 initialSupply,\n uint8 decimals_\n ) ERC20(name_, symbol_) {\n _decimals = decimals_;\n _mint(msg.sender, initialSupply);\n }\n\n function decimals() public view virtual override returns (uint8) {\n return _decimals;\n }\n\n function mint(address recipient, uint256 amount) public virtual {\n return _mint(recipient, amount);\n }\n\n function burn(address recipient, uint256 amount) public virtual {\n return _burn(recipient, amount);\n }\n}\n"},"@ensuro/utils/contracts/TestCurrencyPermit.sol":{"content":"//SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.0;\n\nimport {ERC20} from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport {ERC20Permit} from \"@openzeppelin/contracts/token/ERC20/extensions/ERC20Permit.sol\";\n\ncontract TestCurrencyPermit is ERC20Permit {\n uint8 internal immutable _decimals;\n\n constructor(\n string memory name_,\n string memory symbol_,\n uint256 initialSupply,\n uint8 decimals_\n ) ERC20(name_, symbol_) ERC20Permit(name_) {\n _decimals = decimals_;\n _mint(msg.sender, initialSupply);\n }\n\n function decimals() public view virtual override returns (uint8) {\n return _decimals;\n }\n\n function mint(address recipient, uint256 amount) public virtual {\n return _mint(recipient, amount);\n }\n\n function burn(address recipient, uint256 amount) public virtual {\n return _burn(recipient, amount);\n }\n}\n"},"@ensuro/utils/contracts/TestERC4626.sol":{"content":"//SPDX-License-Identifier: Apache-2.0\npragma solidity ^0.8.0;\n\nimport {ERC20} from \"@openzeppelin/contracts/token/ERC20/ERC20.sol\";\nimport {ERC4626} from \"@openzeppelin/contracts/token/ERC20/extensions/ERC4626.sol\";\nimport {IERC20Metadata} from \"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\";\n\ninterface IMintable {\n function mint(address recipient, uint256 amount) external;\n function burn(address recipient, uint256 amount) external;\n}\n\ncontract TestERC4626 is ERC4626 {\n bool internal _broken;\n\n uint256 public overrideMaxDeposit;\n uint256 public overrideMaxMint;\n uint256 public overrideMaxWithdraw;\n uint256 public overrideMaxRedeem;\n\n uint256 public constant OVERRIDE_UNSET = type(uint256).max - 99;\n\n enum OverrideOption {\n deposit,\n mint,\n withdraw,\n redeem\n }\n\n error VaultIsBroken(bytes4 selector);\n\n modifier isBroken() {\n require(!_broken, VaultIsBroken(bytes4(msg.data[0:4])));\n _;\n }\n\n constructor(string memory name_, string memory symbol_, IERC20Metadata asset_) ERC20(name_, symbol_) ERC4626(asset_) {\n overrideMaxRedeem = overrideMaxWithdraw = overrideMaxMint = overrideMaxDeposit = OVERRIDE_UNSET;\n }\n\n function _deposit(\n address caller,\n address receiver,\n uint256 assets,\n uint256 shares\n ) internal virtual override isBroken {\n super._deposit(caller, receiver, assets, shares);\n }\n\n function _withdraw(\n address caller,\n address receiver,\n address owner,\n uint256 assets,\n uint256 shares\n ) internal virtual override isBroken {\n super._withdraw(caller, receiver, owner, assets, shares);\n }\n\n /*\n * @dev Adds or remove assets not generated by deposits/withdraw - For testing discrete earnings/losses\n */\n function discreteEarning(int256 assets) external {\n if (assets > 0) {\n IMintable(asset()).mint(address(this), uint256(assets));\n } else {\n IMintable(asset()).burn(address(this), uint256(-assets));\n }\n }\n\n function setBroken(bool broken_) external {\n _broken = broken_;\n }\n\n function broken() external view returns (bool) {\n return _broken;\n }\n\n function maxDeposit(address owner) public view override returns (uint256) {\n return overrideMaxDeposit == OVERRIDE_UNSET ? super.maxDeposit(owner) : overrideMaxDeposit;\n }\n\n function maxMint(address owner) public view override returns (uint256) {\n return overrideMaxMint == OVERRIDE_UNSET ? super.maxMint(owner) : overrideMaxMint;\n }\n\n function maxWithdraw(address owner) public view override returns (uint256) {\n return overrideMaxWithdraw == OVERRIDE_UNSET ? super.maxWithdraw(owner) : overrideMaxWithdraw;\n }\n\n function maxRedeem(address owner) public view override returns (uint256) {\n return overrideMaxRedeem == OVERRIDE_UNSET ? super.maxRedeem(owner) : overrideMaxRedeem;\n }\n\n function setOverride(OverrideOption option, uint256 newValue) external {\n if (option == OverrideOption.deposit) overrideMaxDeposit = newValue;\n if (option == OverrideOption.mint) overrideMaxMint = newValue;\n if (option == OverrideOption.withdraw) overrideMaxWithdraw = newValue;\n if (option == OverrideOption.redeem) overrideMaxRedeem = newValue;\n }\n}\n"},"@openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.5.0) (token/ERC20/ERC20.sol)\n\npragma solidity ^0.8.20;\n\nimport {IERC20} from \"@openzeppelin/contracts/token/ERC20/IERC20.sol\";\nimport {IERC20Metadata} from \"@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol\";\nimport {ContextUpgradeable} from \"../../utils/ContextUpgradeable.sol\";\nimport {IERC20Errors} from \"@openzeppelin/contracts/interfaces/draft-IERC6093.sol\";\nimport {Initializable} from \"@openzeppelin/contracts/proxy/utils/Initializable.sol\";\n\n/**\n * @dev Implementation of the {IERC20} interface.\n *\n * This implementation is agnostic to the way tokens are created. This means\n * that a supply mechanism has to be added in a derived contract using {_mint}.\n *\n * TIP: For a detailed writeup see our guide\n * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How\n * to implement supply mechanisms].\n *\n * The default value of {decimals} is 18. To change this, you should override\n * this function so it returns a different value.\n *\n * We have followed general OpenZeppelin Contracts guidelines: functions revert\n * instead returning `false` on failure. This behavior is nonetheless\n * conventional and does not conflict with the expectations of ERC-20\n * applications.\n */\nabstract contract ERC20Upgradeable is Initializable, ContextUpgradeable, IERC20, IERC20Metadata, IERC20Errors {\n /// @custom:storage-location erc7201:openzeppelin.storage.ERC20\n struct ERC20Storage {\n mapping(address account => uint256) _balances;\n\n mapping(address account => mapping(address spender => uint256)) _allowances;\n\n uint256 _totalSupply;\n\n string _name;\n string _symbol;\n }\n\n // keccak256(abi.encode(uint256(keccak256(\"openzeppelin.storage.ERC20\")) - 1)) & ~bytes32(uint256(0xff))\n bytes32 private constant ERC20StorageLocation = 0x52c63247e1f47db19d5ce0460030c497f067ca4cebf71ba98eeadabe20bace00;\n\n function _getERC20Storage() private pure returns (ERC20Storage storage $) {\n assembly {\n $.slot := ERC20StorageLocation\n }\n }\n\n /**\n * @dev Sets the values for {name} and {symbol}.\n *\n * Both values are immutable: they can only be set once during construction.\n */\n function __ERC20_init(string memory name_, string memory symbol_) internal onlyInitializing {\n __ERC20_init_unchained(name_, symbol_);\n }\n\n function __ERC20_init_unchained(string memory name_, string memory symbol_) internal onlyInitializing {\n ERC20Storage storage $ = _getERC20Storage();\n $._name = name_;\n $._symbol = symbol_;\n }\n\n /**\n * @dev Returns the name of the token.\n */\n function name() public view virtual returns (string memory) {\n ERC20Storage storage $ = _getERC20Storage();\n return $._name;\n }\n\n /**\n * @dev Returns the symbol of the token, usually a shorter version of the\n * name.\n */\n function symbol() public view virtual returns (string memory) {\n ERC20Storage storage $ = _getERC20Storage();\n return $._symbol;\n }\n\n /**\n * @dev Returns the number of decimals used to get its user representation.\n * For example, if `decimals` equals `2`, a balance of `505` tokens should\n * be displayed to a user as `5.05` (`505 / 10 ** 2`).\n *\n * Tokens usually opt for a value of 18, imitating the relationship between\n * Ether and Wei. This is the default value returned by this function, unless\n * it's overridden.\n *\n * NOTE: This information is only used for _display_ purposes: it in\n * no way affects any of the arithmetic of the contract, including\n * {IERC20-balanceOf} and {IERC20-transfer}.\n */\n function decimals() public view virtual returns (uint8) {\n return 18;\n }\n\n /// @inheritdoc IERC20\n function totalSupply() public view virtual returns (uint256) {\n ERC20Storage storage $ = _getERC20Storage();\n return $._totalSupply;\n }\n\n /// @inheritdoc IERC20\n function balanceOf(address account) public view virtual returns (uint256) {\n ERC20Storage storage $ = _getERC20Storage();\n return $._balances[account];\n }\n\n /**\n * @dev See {IERC20-transfer}.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - the caller must have a balance of at least `value`.\n */\n function transfer(address to, uint256 value) public virtual returns (bool) {\n address owner = _msgSender();\n _transfer(owner, to, value);\n return true;\n }\n\n /// @inheritdoc IERC20\n function allowance(address owner, address spender) public view virtual returns (uint256) {\n ERC20Storage storage $ = _getERC20Storage();\n return $._allowances[owner][spender];\n }\n\n /**\n * @dev See {IERC20-approve}.\n *\n * NOTE: If `value` is the maximum `uint256`, the allowance is not updated on\n * `transferFrom`. This is semantically equivalent to an infinite approval.\n *\n * Requirements:\n *\n * - `spender` cannot be the zero address.\n */\n function approve(address spender, uint256 value) public virtual returns (bool) {\n address owner = _msgSender();\n _approve(owner, spender, value);\n return true;\n }\n\n /**\n * @dev See {IERC20-transferFrom}.\n *\n * Skips emitting an {Approval} event indicating an allowance update. This is not\n * required by the ERC. See {xref-ERC20-_approve-address-address-uint256-bool-}[_approve].\n *\n * NOTE: Does not update the allowance if the current allowance\n * is the maximum `uint256`.\n *\n * Requirements:\n *\n * - `from` and `to` cannot be the zero address.\n * - `from` must have a balance of at least `value`.\n * - the caller must have allowance for ``from``'s tokens of at least\n * `value`.\n */\n function transferFrom(address from, address to, uint256 value) public virtual returns (bool) {\n address spender = _msgSender();\n _spendAllowance(from, spender, value);\n _transfer(from, to, value);\n return true;\n }\n\n /**\n * @dev Moves a `value` amount of tokens from `from` to `to`.\n *\n * This internal function is equivalent to {transfer}, and can be used to\n * e.g. implement automatic token fees, slashing mechanisms, etc.\n *\n * Emits a {Transfer} event.\n *\n * NOTE: This function is not virtual, {_update} should be overridden instead.\n */\n function _transfer(address from, address to, uint256 value) internal {\n if (from == address(0)) {\n revert ERC20InvalidSender(address(0));\n }\n if (to == address(0)) {\n revert ERC20InvalidReceiver(address(0));\n }\n _update(from, to, value);\n }\n\n /**\n * @dev Transfers a `value` amount of tokens from `from` to `to`, or alternatively mints (or burns) if `from`\n * (or `to`) is the zero address. All customizations to transfers, mints, and burns should be done by overriding\n * this function.\n *\n * Emits a {Transfer} event.\n */\n function _update(address from, address to, uint256 value) internal virtual {\n ERC20Storage storage $ = _getERC20Storage();\n if (from == address(0)) {\n // Overflow check required: The rest of the code assumes that totalSupply never overflows\n $._totalSupply += value;\n } else {\n uint256 fromBalance = $._balances[from];\n if (fromBalance < value) {\n revert ERC20InsufficientBalance(from, fromBalance, value);\n }\n unchecked {\n // Overflow not possible: value <= fromBalance <= totalSupply.\n $._balances[from] = fromBalance - value;\n }\n }\n\n if (to == address(0)) {\n unchecked {\n // Overflow not possible: value <= totalSupply or value <= fromBalance <= totalSupply.\n $._totalSupply -= value;\n }\n } else {\n unchecked {\n // Overflow not possible: balance + value is at most totalSupply, which we know fits into a uint256.\n $._balances[to] += value;\n }\n }\n\n emit Transfer(from, to, value);\n }\n\n /**\n * @dev Creates a `value` amount of tokens and assigns them to `account`, by transferring it from address(0).\n * Relies on the `_update` mechanism\n *\n * Emits a {Transfer} event with `from` set to the zero address.\n *\n * NOTE: This function is not virtual, {_update} should be overridden instead.\n */\n function _mint(address account, uint256 value) internal {\n if (account == address(0)) {\n revert ERC20InvalidReceiver(address(0));\n }\n _update(address(0), account, value);\n }\n\n /**\n * @dev Destroys a `value` amount of tokens from `account`, lowering the total supply.\n * Relies on the `_update` mechanism.\n *\n * Emits a {Transfer} event with `to` set to the zero address.\n *\n * NOTE: This function is not virtual, {_update} should be overridden instead\n */\n function _burn(address account, uint256 value) internal {\n if (account == address(0)) {\n revert ERC20InvalidSender(address(0));\n }\n _update(account, address(0), value);\n }\n\n /**\n * @dev Sets `value` as the allowance of `spender` over the `owner`'s tokens.\n *\n * This internal function is equivalent to `approve`, and can be used to\n * e.g. set automatic allowances for certain subsystems, etc.\n *\n * Emits an {Approval} event.\n *\n * Requirements:\n *\n * - `owner` cannot be the zero address.\n * - `spender` cannot be the zero address.\n *\n * Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument.\n */\n function _approve(address owner, address spender, uint256 value) internal {\n _approve(owner, spender, value, true);\n }\n\n /**\n * @dev Variant of {_approve} with an optional flag to enable or disable the {Approval} event.\n *\n * By default (when calling {_approve}) the flag is set to true. On the other hand, approval changes made by\n * `_spendAllowance` during the `transferFrom` operation sets the flag to false. This saves gas by not emitting any\n * `Approval` event during `transferFrom` operations.\n *\n * Anyone who wishes to continue emitting `Approval` events on the `transferFrom` operation can force the flag to\n * true using the following override:\n *\n * ```solidity\n * function _approve(address owner, address spender, uint256 value, bool) internal virtual override {\n * super._approve(owner, spender, value, true);\n * }\n * ```\n *\n * Requirements are the same as {_approve}.\n */\n function _approve(address owner, address spender, uint256 value, bool emitEvent) internal virtual {\n ERC20Storage storage $ = _getERC20Storage();\n if (owner == address(0)) {\n revert ERC20InvalidApprover(address(0));\n }\n if (spender == address(0)) {\n revert ERC20InvalidSpender(address(0));\n }\n $._allowances[owner][spender] = value;\n if (emitEvent) {\n emit Approval(owner, spender, value);\n }\n }\n\n /**\n * @dev Updates `owner`'s allowance for `spender` based on spent `value`.\n *\n * Does not update the allowance value in case of infinite allowance.\n * Revert if not enough allowance is available.\n *\n * Does not emit an {Approval} event.\n */\n function _spendAllowance(address owner, address spender, uint256 value) internal virtual {\n uint256 currentAllowance = allowance(owner, spender);\n if (currentAllowance < type(uint256).max) {\n if (currentAllowance < value) {\n revert ERC20InsufficientAllowance(spender, currentAllowance, value);\n }\n unchecked {\n _approve(owner, spender, currentAllowance - value, false);\n }\n }\n }\n}\n"},"@openzeppelin/contracts-upgradeable/token/ERC20/extensions/ERC20PermitUpgradeable.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.5.0) (token/ERC20/extensions/ERC20Permit.sol)\n\npragma solidity ^0.8.24;\n\nimport {IERC20Permit} from \"@openzeppelin/contracts/token/ERC20/extensions/IERC20Permit.sol\";\nimport {ERC20Upgradeable} from \"../ERC20Upgradeable.sol\";\nimport {ECDSA} from \"@openzeppelin/contracts/utils/cryptography/ECDSA.sol\";\nimport {EIP712Upgradeable} from \"../../../utils/cryptography/EIP712Upgradeable.sol\";\nimport {NoncesUpgradeable} from \"../../../utils/NoncesUpgradeable.sol\";\nimport {Initializable} from \"@openzeppelin/contracts/proxy/utils/Initializable.sol\";\n\n/**\n * @dev Implementation of the ERC-20 Permit extension allowing approvals to be made via signatures, as defined in\n * https://eips.ethereum.org/EIPS/eip-2612[ERC-2612].\n *\n * Adds the {permit} method, which can be used to change an account's ERC-20 allowance (see {IERC20-allowance}) by\n * presenting a message signed by the account. By not relying on `{IERC20-approve}`, the token holder account doesn't\n * need to send a transaction, and thus is not required to hold Ether at all.\n */\nabstract contract ERC20PermitUpgradeable is Initializable, ERC20Upgradeable, IERC20Permit, EIP712Upgradeable, NoncesUpgradeable {\n bytes32 private constant PERMIT_TYPEHASH =\n keccak256(\"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)\");\n\n /**\n * @dev Permit deadline has expired.\n */\n error ERC2612ExpiredSignature(uint256 deadline);\n\n /**\n * @dev Mismatched signature.\n */\n error ERC2612InvalidSigner(address signer, address owner);\n\n /**\n * @dev Initializes the {EIP712} domain separator using the `name` parameter, and setting `version` to `\"1\"`.\n *\n * It's a good idea to use the same `name` that is defined as the ERC-20 token name.\n */\n function __ERC20Permit_init(string memory name) internal onlyInitializing {\n __EIP712_init_unchained(name, \"1\");\n }\n\n function __ERC20Permit_init_unchained(string memory) internal onlyInitializing {}\n\n /// @inheritdoc IERC20Permit\n function permit(\n address owner,\n address spender,\n uint256 value,\n uint256 deadline,\n uint8 v,\n bytes32 r,\n bytes32 s\n ) public virtual {\n if (block.timestamp > deadline) {\n revert ERC2612ExpiredSignature(deadline);\n }\n\n bytes32 structHash = keccak256(abi.encode(PERMIT_TYPEHASH, owner, spender, value, _useNonce(owner), deadline));\n\n bytes32 hash = _hashTypedDataV4(structHash);\n\n address signer = ECDSA.recover(hash, v, r, s);\n if (signer != owner) {\n revert ERC2612InvalidSigner(signer, owner);\n }\n\n _approve(owner, spender, value);\n }\n\n /// @inheritdoc IERC20Permit\n function nonces(address owner) public view virtual override(IERC20Permit, NoncesUpgradeable) returns (uint256) {\n return super.nonces(owner);\n }\n\n /// @inheritdoc IERC20Permit\n // solhint-disable-next-line func-name-mixedcase\n function DOMAIN_SEPARATOR() external view returns (bytes32) {\n return _domainSeparatorV4();\n }\n}\n"},"@openzeppelin/contracts-upgradeable/token/ERC721/ERC721Upgradeable.sol":{"content":"// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v5.5.0) (token/ERC721/ERC721.sol)\n\npragma solidity ^0.8.24;\n\nimport {IERC721} from \"@openzeppelin/contracts/token/ERC721/IERC721.sol\";\nimport {IERC721Metadata} from \"@openzeppelin/contracts/token/ERC721/extensions/IERC721Metadata.sol\";\nimport {ERC721Utils} from \"@openzeppelin/contracts/token/ERC721/utils/ERC721Utils.sol\";\nimport {ContextUpgradeable} from \"../../utils/ContextUpgradeable.sol\";\nimport {Strings} from \"@openzeppelin/contracts/utils/Strings.sol\";\nimport {IERC165} from \"@openzeppelin/contracts/utils/introspection/IERC165.sol\";\nimport {ERC165Upgradeable} from \"../../utils/introspection/ERC165Upgradeable.sol\";\nimport {IERC721Errors} from \"@openzeppelin/contracts/interfaces/draft-IERC6093.sol\";\nimport {Initializable} from \"@openzeppelin/contracts/proxy/utils/Initializable.sol\";\n\n/**\n * @dev Implementation of https://eips.ethereum.org/EIPS/eip-721[ERC-721] Non-Fungible Token Standard, including\n * the Metadata extension, but not including the Enumerable extension, which is available separately as\n * {ERC721Enumerable}.\n */\nabstract contract ERC721Upgradeable is Initializable, ContextUpgradeable, ERC165Upgradeable, IERC721, IERC721Metadata, IERC721Errors {\n using Strings for uint256;\n\n /// @custom:storage-location erc7201:openzeppelin.storage.ERC721\n struct ERC721Storage {\n // Token name\n string _name;\n\n // Token symbol\n string _symbol;\n\n mapping(uint256 tokenId => address) _owners;\n\n mapping(address owner => uint256) _balances;\n\n mapping(uint256 tokenId => address) _tokenApprovals;\n\n mapping(address owner => mapping(address operator => bool)) _operatorApprovals;\n }\n\n // keccak256(abi.encode(uint256(keccak256(\"openzeppelin.storage.ERC721\")) - 1)) & ~bytes32(uint256(0xff))\n bytes32 private constant ERC721StorageLocation = 0x80bb2b638cc20bc4d0a60d66940f3ab4a00c1d7b313497ca82fb0b4ab0079300;\n\n function _getERC721Storage() private pure returns (ERC721Storage storage $) {\n assembly {\n $.slot := ERC721StorageLocation\n }\n }\n\n /**\n * @dev Initializes the contract by setting a `name` and a `symbol` to the token collection.\n */\n function __ERC721_init(string memory name_, string memory symbol_) internal onlyInitializing {\n __ERC721_init_unchained(name_, symbol_);\n }\n\n function __ERC721_init_unchained(string memory name_, string memory symbol_) internal onlyInitializing {\n ERC721Storage storage $ = _getERC721Storage();\n $._name = name_;\n $._symbol = symbol_;\n }\n\n /// @inheritdoc IERC165\n function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165Upgradeable, IERC165) returns (bool) {\n return\n interfaceId == type(IERC721).interfaceId ||\n interfaceId == type(IERC721Metadata).interfaceId ||\n super.supportsInterface(interfaceId);\n }\n\n /// @inheritdoc IERC721\n function balanceOf(address owner) public view virtual returns (uint256) {\n ERC721Storage storage $ = _getERC721Storage();\n if (owner == address(0)) {\n revert ERC721InvalidOwner(address(0));\n }\n return $._balances[owner];\n }\n\n /// @inheritdoc IERC721\n function ownerOf(uint256 tokenId) public view virtual returns (address) {\n return _requireOwned(tokenId);\n }\n\n /// @inheritdoc IERC721Metadata\n function name() public view virtual returns (string memory) {\n ERC721Storage storage $ = _getERC721Storage();\n return $._name;\n }\n\n /// @inheritdoc IERC721Metadata\n function symbol() public view virtual returns (string memory) {\n ERC721Storage storage $ = _getERC721Storage();\n return $._symbol;\n }\n\n /// @inheritdoc IERC721Metadata\n function tokenURI(uint256 tokenId) public view virtual returns (string memory) {\n _requireOwned(tokenId);\n\n string memory baseURI = _baseURI();\n return bytes(baseURI).length > 0 ? string.concat(baseURI, tokenId.toString()) : \"\";\n }\n\n /**\n * @dev Base URI for computing {tokenURI}. If set, the resulting URI for each\n * token will be the concatenation of the `baseURI` and the `tokenId`. Empty\n * by default, can be overridden in child contracts.\n */\n function _baseURI() internal view virtual returns (string memory) {\n return \"\";\n }\n\n /// @inheritdoc IERC721\n function approve(address to, uint256 tokenId) public virtual {\n _approve(to, tokenId, _msgSender());\n }\n\n /// @inheritdoc IERC721\n function getApproved(uint256 tokenId) public view virtual returns (address) {\n _requireOwned(tokenId);\n\n return _getApproved(tokenId);\n }\n\n /// @inheritdoc IERC721\n function setApprovalForAll(address operator, bool approved) public virtual {\n _setApprovalForAll(_msgSender(), operator, approved);\n }\n\n /// @inheritdoc IERC721\n function isApprovedForAll(address owner, address operator) public view virtual returns (bool) {\n ERC721Storage storage $ = _getERC721Storage();\n return $._operatorApprovals[owner][operator];\n }\n\n /// @inheritdoc IERC721\n function transferFrom(address from, address to, uint256 tokenId) public virtual {\n if (to == address(0)) {\n revert ERC721InvalidReceiver(address(0));\n }\n // Setting an \"auth\" arguments enables the `_isAuthorized` check which verifies that the token exists\n // (from != 0). Therefore, it is not needed to verify that the return value is not 0 here.\n address previousOwner = _update(to, tokenId, _msgSender());\n if (previousOwner != from) {\n revert ERC721IncorrectOwner(from, tokenId, previousOwner);\n }\n }\n\n /// @inheritdoc IERC721\n function safeTransferFrom(address from, address to, uint256 tokenId) public {\n safeTransferFrom(from, to, tokenId, \"\");\n }\n\n /// @inheritdoc IERC721\n function safeTransferFrom(address from, address to, uint256 tokenId, bytes memory data) public virtual {\n transferFrom(from, to, tokenId);\n ERC721Utils.checkOnERC721Received(_msgSender(), from, to, tokenId, data);\n }\n\n /**\n * @dev Returns the owner of the `tokenId`. Does NOT revert if token doesn't exist\n *\n * IMPORTANT: Any overrides to this function that add ownership of tokens not tracked by the\n * core ERC-721 logic MUST be matched with the use of {_increaseBalance} to keep balances\n * consistent with ownership. The invariant to preserve is that for any address `a` the value returned by\n * `balanceOf(a)` must be equal to the number of tokens such that `_ownerOf(tokenId)` is `a`.\n */\n function _ownerOf(uint256 tokenId) internal view virtual returns (address) {\n ERC721Storage storage $ = _getERC721Storage();\n return $._owners[tokenId];\n }\n\n /**\n * @dev Returns the approved address for `tokenId`. Returns 0 if `tokenId` is not minted.\n */\n function _getApproved(uint256 tokenId) internal view virtual returns (address) {\n ERC721Storage storage $ = _getERC721Storage();\n return $._tokenApprovals[tokenId];\n }\n\n /**\n * @dev Returns whether `spender` is allowed to manage `owner`'s tokens, or `tokenId` in\n * particular (ignoring whether it is owned by `owner`).\n *\n * WARNING: This function assumes that `owner` is the actual owner of `tokenId` and does not verify this\n * assumption.\n */\n function _isAuthorized(address owner, address spender, uint256 tokenId) internal view virtual returns (bool) {\n return\n spender != address(0) &&\n (owner == spender || isApprovedForAll(owner, spender) || _getApproved(tokenId) == spender);\n }\n\n /**\n * @dev Checks if `spender` can operate on `tokenId`, assuming the provided `owner` is the actual owner.\n * Reverts if:\n * - `spender` does not have approval from `owner` for `tokenId`.\n * - `spender` does not have approval to manage all of `owner`'s assets.\n *\n * WARNING: This function assumes that `owner` is the actual owner of `tokenId` and does not verify this\n * assumption.\n */\n function _checkAuthorized(address owner, address spender, uint256 tokenId) internal view virtual {\n if (!_isAuthorized(owner, spender, tokenId)) {\n if (owner == address(0)) {\n revert ERC721NonexistentToken(tokenId);\n } else {\n revert ERC721InsufficientApproval(spender, tokenId);\n }\n }\n }\n\n /**\n * @dev Unsafe write access to the balances, used by extensions that \"mint\" tokens using an {ownerOf} override.\n *\n * NOTE: the value is limited to type(uint128).max. This protect against _balance overflow. It is unrealistic that\n * a uint256 would ever overflow from increments when these increments are bounded to uint128 values.\n *\n * WARNING: Increasing an account's balance using this function tends to be paired with an override of the\n * {_ownerOf} function to resolve the ownership of the corresponding tokens so that balances and ownership\n * remain consistent with one another.\n */\n function _increaseBalance(address account, uint128 value) internal virtual {\n ERC721Storage storage $ = _getERC721Storage();\n unchecked {\n $._balances[account] += value;\n }\n }\n\n /**\n * @dev Transfers `tokenId` from its current owner to `to`, or alternatively mints (or burns) if the current owner\n * (or `to`) is the zero address. Returns the owner of the `tokenId` before the update.\n *\n * The `auth` argument is optional. If the value passed is non 0, then this function will check that\n * `auth` is either the owner of the token, or approved to operate on the token (by the owner).\n *\n * Emits a {Transfer} event.\n *\n * NOTE: If overriding this function in a way that tracks balances, see also {_increaseBalance}.\n */\n function _update(address to, uint256 tokenId, address auth) internal virtual returns (address) {\n ERC721Storage storage $ = _getERC721Storage();\n address from = _ownerOf(tokenId);\n\n // Perform (optional) operator check\n if (auth != address(0)) {\n _checkAuthorized(from, auth, tokenId);\n }\n\n // Execute the update\n if (from != address(0)) {\n // Clear approval. No need to re-authorize or emit the Approval event\n _approve(address(0), tokenId, address(0), false);\n\n unchecked {\n $._balances[from] -= 1;\n }\n }\n\n if (to != address(0)) {\n unchecked {\n $._balances[to] += 1;\n }\n }\n\n $._owners[tokenId] = to;\n\n emit Transfer(from, to, tokenId);\n\n return from;\n }\n\n /**\n * @dev Mints `tokenId` and transfers it to `to`.\n *\n * WARNING: Usage of this method is discouraged, use {_safeMint} whenever possible\n *\n * Requirements:\n *\n * - `tokenId` must not exist.\n * - `to` cannot be the zero address.\n *\n * Emits a {Transfer} event.\n */\n function _mint(address to, uint256 tokenId) internal {\n if (to == address(0)) {\n revert ERC721InvalidReceiver(address(0));\n }\n address previousOwner = _update(to, tokenId, address(0));\n if (previousOwner != address(0)) {\n revert ERC721InvalidSender(address(0));\n }\n }\n\n /**\n * @dev Mints `tokenId`, transfers it to `to` and checks for `to` acceptance.\n *\n * Requirements:\n *\n * - `tokenId` must not exist.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function _safeMint(address to, uint256 tokenId) internal {\n _safeMint(to, tokenId, \"\");\n }\n\n /**\n * @dev Same as {xref-ERC721-_safeMint-address-uint256-}[`_safeMint`], with an additional `data` parameter which is\n * forwarded in {IERC721Receiver-onERC721Received} to contract recipients.\n */\n function _safeMint(address to, uint256 tokenId, bytes memory data) internal virtual {\n _mint(to, tokenId);\n ERC721Utils.checkOnERC721Received(_msgSender(), address(0), to, tokenId, data);\n }\n\n /**\n * @dev Destroys `tokenId`.\n * The approval is cleared when the token is burned.\n * This is an internal function that does not check if the sender is authorized to operate on the token.\n *\n * Requirements:\n *\n * - `tokenId` must exist.\n *\n * Emits a {Transfer} event.\n */\n function _burn(uint256 tokenId) internal {\n address previousOwner = _update(address(0), tokenId, address(0));\n if (previousOwner == address(0)) {\n revert ERC721NonexistentToken(tokenId);\n }\n }\n\n /**\n * @dev Transfers `tokenId` from `from` to `to`.\n * As opposed to {transferFrom}, this imposes no restrictions on msg.sender.\n *\n * Requirements:\n *\n * - `to` cannot be the zero address.\n * - `tokenId` token must be owned by `from`.\n *\n * Emits a {Transfer} event.\n */\n function _transfer(address from, address to, uint256 tokenId) internal {\n if (to == address(0)) {\n revert ERC721InvalidReceiver(address(0));\n }\n address previousOwner = _update(to, tokenId, address(0));\n if (previousOwner == address(0)) {\n revert ERC721NonexistentToken(tokenId);\n } else if (previousOwner != from) {\n revert ERC721IncorrectOwner(from, tokenId, previousOwner);\n }\n }\n\n /**\n * @dev Safely transfers `tokenId` token from `from` to `to`, checking that contract recipients\n * are aware of the ERC-721 standard to prevent tokens from being forever locked.\n *\n * `data` is additional data, it has no specified format and it is sent in call to `to`.\n *\n * This internal function is like {safeTransferFrom} in the sense that it invokes\n * {IERC721Receiver-onERC721Received} on the receiver, and can be used to e.g.\n * implement alternative mechanisms to perform token transfer, such as signature-based.\n *\n * Requirements:\n *\n * - `tokenId` token must exist and be owned by `from`.\n * - `to` cannot be the zero address.\n * - `from` cannot be the zero address.\n * - If `to` refers to a smart contract, it must implement {IERC721Receiver-onERC721Received}, which is called upon a safe transfer.\n *\n * Emits a {Transfer} event.\n */\n function _safeTransfer(ad