ERC-20
Overview
Max Total Supply
500,365.292988352038182842 unKat
Holders
277
Market
Price
$0.00 @ 0.000000 ETH
Onchain Market Cap
-
Circulating Supply Market Cap
-
Other Info
Token Contract (WITH 18 Decimals)
Balance
1.240888883418127118 unKatValue
$0.00Loading...
Loading
Loading...
Loading
Loading...
Loading
Contract Source Code Verified (Exact Match)
Contract Name:
UnKat
Compiler Version
v0.8.28+commit.7893614a
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.28; import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import {UnKatFactory} from "./UnKatFactory.sol"; import "./Errors.sol"; contract UnKat is ERC20 { using SafeERC20 for ERC20; uint256 constant BPS = 10_000; bytes32 public constant CALLBACK_SUCCESS = keccak256("IClaimRecipient.onClaim"); UnKatFactory public immutable factory; address public immutable distributor; ERC20 public immutable kat; /// @notice constructor /// @param _kat Address of the official kat token /// @param _distributor Address of the Merkl distributor constructor(address _kat, address _distributor) ERC20("unlocked Kat", "unKat") { factory = UnKatFactory(msg.sender); kat = ERC20(_kat); distributor = _distributor; } /// @notice Hook called by the Merkl's Distributor, only way to mint unkat, will mint the difference between supply and kat balance function onClaim(address user, address token, uint256, /*amount*/ bytes memory data) external returns (bytes32) { require(msg.sender == distributor, OnlyDistributor()); require(token == address(kat) || factory.isWrappedKat(token), InvalidToken()); //Prob not necessary but good additional safety check address referral; if (data.length == 32) { referral = abi.decode(data, (address)); } uint256 toMint = kat.balanceOf(address(this)) - totalSupply(); _mintUnKat(user, toMint, referral); return CALLBACK_SUCCESS; } /// @notice Mint unKat minus the factory fee /// @param receiver Address receiving the unKat tokens /// @param amount Amount of unKat tokens to mint /// @param referral Address to use as referral function _mintUnKat(address receiver, uint256 amount, address referral) internal { (uint256 opsFee, uint256 referralFee) = factory.getFees(referral); uint256 opsFeeAmount = amount * opsFee / BPS; uint256 referralFeeAmount = amount * referralFee / BPS; _mint(factory.owner(), opsFeeAmount); _mint(receiver, amount - opsFeeAmount - referralFeeAmount); if (referralFeeAmount > 0) { _mint(referral, referralFeeAmount); } } /// @notice Redeem unKat for kat tokens 1-1, callable by anyone /// @param amount Amount of unKat tokens to redeem function redeem(uint256 amount) external { _burn(msg.sender, amount); kat.safeTransfer(msg.sender, amount); } }
// SPDX-License-Identifier: BUSL-1.1 pragma solidity ^0.8.17; import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import { SafeERC20 } from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import { SafeCast } from "@openzeppelin/contracts/utils/math/SafeCast.sol"; import { UUPSHelper } from "./utils/UUPSHelper.sol"; import { IAccessControlManager } from "./interfaces/IAccessControlManager.sol"; import { Errors } from "./utils/Errors.sol"; struct MerkleTree { // Root of a Merkle tree which leaves are `(address user, address token, uint amount)` // representing an amount of tokens accumulated by `user`. // The Merkle tree is assumed to have only increasing amounts: that is to say if a user can claim 1, // then after the amount associated in the Merkle tree for this token should be x > 1 bytes32 merkleRoot; // Ipfs hash of the tree data bytes32 ipfsHash; } struct Claim { uint208 amount; uint48 timestamp; bytes32 merkleRoot; } interface IClaimRecipient { /// @notice Hook to call within contracts receiving token rewards on behalf of users function onClaim(address user, address token, uint256 amount, bytes memory data) external returns (bytes32); } /// @title Distributor /// @notice Allows to claim rewards distributed to them through Merkl /// @author Angle Labs. Inc contract Distributor is UUPSHelper { using SafeERC20 for IERC20; /// @notice Default epoch duration uint32 internal constant _EPOCH_DURATION = 3600; /// @notice Success message received when calling a `ClaimRecipient` contract bytes32 public constant CALLBACK_SUCCESS = keccak256("IClaimRecipient.onClaim"); /*////////////////////////////////////////////////////////////////////////////////////////////////////////////////// VARIABLES //////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/ /// @notice Tree of claimable tokens through this contract MerkleTree public tree; /// @notice Tree that was in place in the contract before the last `tree` update MerkleTree public lastTree; /// @notice Token to deposit to freeze the roots update IERC20 public disputeToken; /// @notice `AccessControlManager` contract handling access control IAccessControlManager public accessControlManager; /// @notice Address which created the last dispute /// @dev Used to store if there is an ongoing dispute address public disputer; /// @notice When the current tree becomes valid uint48 public endOfDisputePeriod; /// @notice Time after which a change in a tree becomes effective, in EPOCH_DURATION uint48 public disputePeriod; /// @notice Amount to deposit to freeze the roots update uint256 public disputeAmount; /// @notice Mapping user -> token -> amount to track claimed amounts mapping(address => mapping(address => Claim)) public claimed; /// @notice Trusted EOAs to update the Merkle root mapping(address => uint256) public canUpdateMerkleRoot; /// @notice Deprecated mapping mapping(address => uint256) public onlyOperatorCanClaim; /// @notice User -> Operator -> authorisation to claim on behalf of the user mapping(address => mapping(address => uint256)) public operators; /// @notice Whether the contract has been made non upgradeable or not uint128 public upgradeabilityDeactivated; /// @notice Reentrancy status uint96 private _status; /// @notice Epoch duration for dispute periods (in seconds) uint32 internal _epochDuration; /// @notice user -> token -> recipient address for when user claims `token` /// @dev If the mapping is empty, by default rewards will accrue on the user address mapping(address => mapping(address => address)) public claimRecipient; uint256[36] private __gap; /*////////////////////////////////////////////////////////////////////////////////////////////////////////////////// EVENTS //////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/ event Claimed(address indexed user, address indexed token, uint256 amount); event ClaimRecipientUpdated(address indexed user, address indexed token, address indexed recipient); event DisputeAmountUpdated(uint256 _disputeAmount); event Disputed(string reason); event DisputePeriodUpdated(uint48 _disputePeriod); event DisputeResolved(bool valid); event DisputeTokenUpdated(address indexed _disputeToken); event EpochDurationUpdated(uint32 newEpochDuration); event OperatorClaimingToggled(address indexed user, bool isEnabled); event OperatorToggled(address indexed user, address indexed operator, bool isWhitelisted); event Recovered(address indexed token, address indexed to, uint256 amount); event Revoked(); // With this event an indexer could maintain a table (timestamp, merkleRootUpdate) event TreeUpdated(bytes32 merkleRoot, bytes32 ipfsHash, uint48 endOfDisputePeriod); event TrustedToggled(address indexed eoa, bool trust); event UpgradeabilityRevoked(); /*////////////////////////////////////////////////////////////////////////////////////////////////////////////////// MODIFIERS //////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/ /// @notice Checks whether the `msg.sender` has the governor role modifier onlyGovernor() { if (!accessControlManager.isGovernor(msg.sender)) revert Errors.NotGovernor(); _; } /// @notice Checks whether the `msg.sender` is the `user` address or is a trusted address modifier onlyTrustedOrUser(address user) { if ( user != msg.sender && canUpdateMerkleRoot[msg.sender] != 1 && !accessControlManager.isGovernorOrGuardian(msg.sender) ) revert Errors.NotTrusted(); _; } /// @notice Checks whether the contract is upgradeable or whether the caller is allowed to upgrade the contract modifier onlyUpgradeableInstance() { if (upgradeabilityDeactivated == 1) revert Errors.NotUpgradeable(); else if (!accessControlManager.isGovernor(msg.sender)) revert Errors.NotGovernor(); _; } /// @notice Checks whether a call is reentrant or not modifier nonReentrant() { if (_status == 2) revert Errors.ReentrantCall(); // Any calls to nonReentrant after this point will fail _status = 2; _; // By storing the original value once again, a refund is triggered (see // https://eips.ethereum.org/EIPS/eip-2200) _status = 1; } /*////////////////////////////////////////////////////////////////////////////////////////////////////////////////// CONSTRUCTOR //////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/ constructor() initializer {} function initialize(IAccessControlManager _accessControlManager) external initializer { if (address(_accessControlManager) == address(0)) revert Errors.ZeroAddress(); accessControlManager = _accessControlManager; } /// @inheritdoc UUPSHelper function _authorizeUpgrade(address) internal view override onlyUpgradeableInstance {} /*////////////////////////////////////////////////////////////////////////////////////////////////////////////////// MAIN FUNCTIONS //////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/ /// @notice Claims rewards for a given set of users /// @dev Unless another address has been approved for claiming, only an address can claim for itself /// @param users Addresses for which claiming is taking place /// @param tokens ERC20 token claimed /// @param amounts Amount of tokens that will be sent to the corresponding users /// @param proofs Array of hashes bridging from a leaf `(hash of user | token | amount)` to the Merkle root function claim( address[] calldata users, address[] calldata tokens, uint256[] calldata amounts, bytes32[][] calldata proofs ) external { address[] memory recipients = new address[](users.length); bytes[] memory datas = new bytes[](users.length); _claim(users, tokens, amounts, proofs, recipients, datas); } /// @notice Same as the function above except that for each token claimed, the caller may set different /// recipients for rewards and pass arbitrary data to the reward recipient on claim /// @dev Only a `msg.sender` calling for itself can set a different recipient for the token rewards /// within the context of a call to claim /// @dev Non-zero recipient addresses given by the `msg.sender` can override any previously set reward address function claimWithRecipient( address[] calldata users, address[] calldata tokens, uint256[] calldata amounts, bytes32[][] calldata proofs, address[] calldata recipients, bytes[] memory datas ) external { _claim(users, tokens, amounts, proofs, recipients, datas); } /// @notice Returns the Merkle root that is currently live for the contract function getMerkleRoot() public view returns (bytes32) { if (block.timestamp >= endOfDisputePeriod && disputer == address(0)) return tree.merkleRoot; else return lastTree.merkleRoot; } function getEpochDuration() public view returns (uint32 epochDuration) { epochDuration = _epochDuration; if (epochDuration == 0) epochDuration = _EPOCH_DURATION; } /*////////////////////////////////////////////////////////////////////////////////////////////////////////////////// USER ADMIN FUNCTIONS //////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/ /// @notice Toggles whitelisting for a given user and a given operator /// @dev When an operator is whitelisted for a user, the operator can claim rewards on behalf of the user function toggleOperator(address user, address operator) external onlyTrustedOrUser(user) { uint256 oldValue = operators[user][operator]; operators[user][operator] = 1 - oldValue; emit OperatorToggled(user, operator, oldValue == 0); } /// @notice Sets a recipient for a user claiming rewards for a token /// @dev This is an optional functionality and if the `recipient` is set to the zero address, then /// the user will still accrue all rewards to its address /// @dev Users may still specify a different recipient when they claim token rewards with the /// `claimWithRecipient` function function setClaimRecipient(address recipient, address token) external { claimRecipient[msg.sender][token] = recipient; emit ClaimRecipientUpdated(msg.sender, recipient, token); } /// @notice Freezes the Merkle tree update until the dispute is resolved /// @dev Requires a deposit of `disputeToken` that'll be slashed if the dispute is not accepted /// @dev It is only possible to create a dispute within `disputePeriod` after each tree update function disputeTree(string memory reason) external { if (disputer != address(0)) revert Errors.UnresolvedDispute(); if (block.timestamp >= endOfDisputePeriod) revert Errors.InvalidDispute(); IERC20(disputeToken).safeTransferFrom(msg.sender, address(this), disputeAmount); disputer = msg.sender; emit Disputed(reason); } /*////////////////////////////////////////////////////////////////////////////////////////////////////////////////// GOVERNANCE FUNCTIONS //////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/ /// @notice Updates the Merkle tree function updateTree(MerkleTree calldata _tree) external { if ( disputer != address(0) || // A trusted address cannot update a tree right after a precedent tree update otherwise it can de facto // validate a tree which has not passed the dispute period ((canUpdateMerkleRoot[msg.sender] != 1 || block.timestamp < endOfDisputePeriod) && !accessControlManager.isGovernor(msg.sender)) ) revert Errors.NotTrusted(); MerkleTree memory _lastTree = tree; tree = _tree; lastTree = _lastTree; uint48 _endOfPeriod = _endOfDisputePeriod(uint48(block.timestamp)); endOfDisputePeriod = _endOfPeriod; emit TreeUpdated(_tree.merkleRoot, _tree.ipfsHash, _endOfPeriod); } /// @notice Adds or removes addresses which are trusted to update the Merkle root function toggleTrusted(address trustAddress) external onlyGovernor { uint256 trustedStatus = 1 - canUpdateMerkleRoot[trustAddress]; canUpdateMerkleRoot[trustAddress] = trustedStatus; emit TrustedToggled(trustAddress, trustedStatus == 1); } /// @notice Prevents future contract upgrades function revokeUpgradeability() external onlyGovernor { upgradeabilityDeactivated = 1; emit UpgradeabilityRevoked(); } /// @notice Updates the epoch duration period function setEpochDuration(uint32 epochDuration) external onlyGovernor { _epochDuration = epochDuration; emit EpochDurationUpdated(epochDuration); } /// @notice Resolve the ongoing dispute, if any /// @param valid Whether the dispute was valid function resolveDispute(bool valid) external onlyGovernor { if (disputer == address(0)) revert Errors.NoDispute(); if (valid) { IERC20(disputeToken).safeTransfer(disputer, disputeAmount); // If a dispute is valid, the contract falls back to the last tree that was updated _revokeTree(); } else { IERC20(disputeToken).safeTransfer(msg.sender, disputeAmount); endOfDisputePeriod = _endOfDisputePeriod(uint48(block.timestamp)); } disputer = address(0); emit DisputeResolved(valid); } /// @notice Allows the governor of this contract to fallback to the last version of the tree /// immediately function revokeTree() external onlyGovernor { if (disputer != address(0)) revert Errors.UnresolvedDispute(); _revokeTree(); } /// @notice Recovers any ERC20 token left on the contract function recoverERC20(address tokenAddress, address to, uint256 amountToRecover) external onlyGovernor { IERC20(tokenAddress).safeTransfer(to, amountToRecover); emit Recovered(tokenAddress, to, amountToRecover); } /// @notice Sets the dispute period after which a tree update becomes effective function setDisputePeriod(uint48 _disputePeriod) external onlyGovernor { disputePeriod = uint48(_disputePeriod); emit DisputePeriodUpdated(_disputePeriod); } /// @notice Sets the token used as a caution during disputes function setDisputeToken(IERC20 _disputeToken) external onlyGovernor { if (disputer != address(0)) revert Errors.UnresolvedDispute(); disputeToken = _disputeToken; emit DisputeTokenUpdated(address(_disputeToken)); } /// @notice Sets the amount of `disputeToken` used as a caution during disputes function setDisputeAmount(uint256 _disputeAmount) external onlyGovernor { if (disputer != address(0)) revert Errors.UnresolvedDispute(); disputeAmount = _disputeAmount; emit DisputeAmountUpdated(_disputeAmount); } /*////////////////////////////////////////////////////////////////////////////////////////////////////////////////// INTERNAL HELPERS //////////////////////////////////////////////////////////////////////////////////////////////////////////////////*/ /// @notice Internal version of `claimWithRecipient` function _claim( address[] calldata users, address[] calldata tokens, uint256[] calldata amounts, bytes32[][] calldata proofs, address[] memory recipients, bytes[] memory datas ) internal nonReentrant { uint256 usersLength = users.length; if ( usersLength == 0 || usersLength != tokens.length || usersLength != amounts.length || usersLength != proofs.length || usersLength != recipients.length || usersLength != datas.length ) revert Errors.InvalidLengths(); for (uint256 i; i < usersLength; ) { address user = users[i]; address token = tokens[i]; uint256 amount = amounts[i]; bytes memory data = datas[i]; // Only approved operator can claim for `user` if (msg.sender != user && tx.origin != user && operators[user][msg.sender] == 0) revert Errors.NotWhitelisted(); // Verifying proof bytes32 leaf = keccak256(abi.encode(user, token, amount)); if (!_verifyProof(leaf, proofs[i])) revert Errors.InvalidProof(); // Closing reentrancy gate here uint256 toSend = amount - claimed[user][token].amount; claimed[user][token] = Claim(SafeCast.toUint208(amount), uint48(block.timestamp), getMerkleRoot()); emit Claimed(user, token, toSend); address recipient = recipients[i]; // Only `msg.sender` can set a different recipient for itself within the context of a call to claim // The recipient set in the context of the call to `claim` can override the default recipient set by the user if (msg.sender != user || recipient == address(0)) { address userSetRecipient = claimRecipient[user][token]; if (userSetRecipient == address(0)) recipient = user; else recipient = userSetRecipient; } if (toSend != 0) { IERC20(token).safeTransfer(recipient, toSend); if (data.length != 0) { try IClaimRecipient(recipient).onClaim(user, token, amount, data) returns ( bytes32 callbackSuccess ) { if (callbackSuccess != CALLBACK_SUCCESS) revert Errors.InvalidReturnMessage(); } catch {} } } unchecked { ++i; } } } /// @notice Fallback to the last version of the tree function _revokeTree() internal { MerkleTree memory _tree = lastTree; endOfDisputePeriod = 0; tree = _tree; uint32 epochDuration = getEpochDuration(); emit Revoked(); emit TreeUpdated( _tree.merkleRoot, _tree.ipfsHash, (uint48(block.timestamp) / epochDuration) * (epochDuration) // Last hour ); } /// @notice Returns the end of the dispute period /// @dev treeUpdate is rounded up to next hour and then `disputePeriod` hours are added function _endOfDisputePeriod(uint48 treeUpdate) internal view returns (uint48) { uint32 epochDuration = getEpochDuration(); return ((treeUpdate - 1) / epochDuration + 1 + disputePeriod) * (epochDuration); } /// @notice Checks the validity of a proof /// @param leaf Hashed leaf data, the starting point of the proof /// @param proof Array of hashes forming a hash chain from leaf to root /// @return true If proof is correct, else false function _verifyProof(bytes32 leaf, bytes32[] memory proof) internal view returns (bool) { bytes32 currentHash = leaf; uint256 proofLength = proof.length; for (uint256 i; i < proofLength; ) { if (currentHash < proof[i]) { currentHash = keccak256(abi.encode(currentHash, proof[i])); } else { currentHash = keccak256(abi.encode(proof[i], currentHash)); } unchecked { ++i; } } bytes32 root = getMerkleRoot(); if (root == bytes32(0)) revert Errors.InvalidUninitializedRoot(); return currentHash == root; } }
// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.17; /// @title IAccessControlManager /// @author Angle Labs, Inc. /// @notice Interface for the `AccessControlManager` contracts of Merkl contracts interface IAccessControlManager { /// @notice Checks whether an address is governor /// @param admin Address to check /// @return Whether the address has the `GOVERNOR_ROLE` or not function isGovernor(address admin) external view returns (bool); /// @notice Checks whether an address is a governor or a guardian of a module /// @param admin Address to check /// @return Whether the address has the `GUARDIAN_ROLE` or not /// @dev Governance should make sure when adding a governor to also give this governor the guardian /// role by calling the `addGovernor` function function isGovernorOrGuardian(address admin) external view returns (bool); }
// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.17; library Errors { error CampaignDoesNotExist(); error CampaignAlreadyExists(); error CampaignDurationBelowHour(); error CampaignRewardTokenNotWhitelisted(); error CampaignRewardTooLow(); error CampaignShouldStartInFuture(); error InvalidDispute(); error InvalidLengths(); error InvalidOverride(); error InvalidParam(); error InvalidParams(); error InvalidProof(); error InvalidUninitializedRoot(); error InvalidReturnMessage(); error InvalidReward(); error InvalidSignature(); error KeyAlreadyUsed(); error NoDispute(); error NoOverrideForCampaign(); error NotAllowed(); error NotEnoughPayment(); error NotGovernor(); error NotGovernorOrGuardian(); error NotSigned(); error NotTrusted(); error NotUpgradeable(); error NotWhitelisted(); error UnresolvedDispute(); error ZeroAddress(); error DisputeFundsTransferFailed(); error EthNotAccepted(); error ReentrantCall(); error WithdrawalFailed(); error InvalidClaim(); error RefererNotSet(); }
// SPDX-License-Identifier: GPL-3.0 pragma solidity ^0.8.17; import { UUPSUpgradeable } from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol"; import { IAccessControlManager } from "../interfaces/IAccessControlManager.sol"; import { Errors } from "./Errors.sol"; /// @title UUPSHelper /// @notice Helper contract for UUPSUpgradeable contracts where the upgradeability is controlled by a specific address /// @author Angle Labs., Inc /// @dev The 0 address check in the modifier allows the use of these modifiers during initialization abstract contract UUPSHelper is UUPSUpgradeable { modifier onlyGuardianUpgrader(IAccessControlManager _accessControlManager) { if (address(_accessControlManager) != address(0) && !_accessControlManager.isGovernorOrGuardian(msg.sender)) revert Errors.NotGovernorOrGuardian(); _; } modifier onlyGovernorUpgrader(IAccessControlManager _accessControlManager) { if (address(_accessControlManager) != address(0) && !_accessControlManager.isGovernor(msg.sender)) revert Errors.NotGovernor(); _; } constructor() initializer {} /// @inheritdoc UUPSUpgradeable function _authorizeUpgrade(address newImplementation) internal virtual override {} }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.3.0) (proxy/utils/Initializable.sol) pragma solidity ^0.8.20; /** * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect. * * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in * case an upgrade adds a module that needs to be initialized. * * For example: * * [.hljs-theme-light.nopadding] * ```solidity * contract MyToken is ERC20Upgradeable { * function initialize() initializer public { * __ERC20_init("MyToken", "MTK"); * } * } * * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable { * function initializeV2() reinitializer(2) public { * __ERC20Permit_init("MyToken"); * } * } * ``` * * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}. * * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity. * * [CAUTION] * ==== * Avoid leaving a contract uninitialized. * * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed: * * [.hljs-theme-light.nopadding] * ``` * /// @custom:oz-upgrades-unsafe-allow constructor * constructor() { * _disableInitializers(); * } * ``` * ==== */ abstract contract Initializable { /** * @dev Storage of the initializable contract. * * It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions * when using with upgradeable contracts. * * @custom:storage-location erc7201:openzeppelin.storage.Initializable */ struct InitializableStorage { /** * @dev Indicates that the contract has been initialized. */ uint64 _initialized; /** * @dev Indicates that the contract is in the process of being initialized. */ bool _initializing; } // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Initializable")) - 1)) & ~bytes32(uint256(0xff)) bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00; /** * @dev The contract is already initialized. */ error InvalidInitialization(); /** * @dev The contract is not initializing. */ error NotInitializing(); /** * @dev Triggered when the contract has been initialized or reinitialized. */ event Initialized(uint64 version); /** * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope, * `onlyInitializing` functions can be used to initialize parent contracts. * * Similar to `reinitializer(1)`, except that in the context of a constructor an `initializer` may be invoked any * number of times. This behavior in the constructor can be useful during testing and is not expected to be used in * production. * * Emits an {Initialized} event. */ modifier initializer() { // solhint-disable-next-line var-name-mixedcase InitializableStorage storage $ = _getInitializableStorage(); // Cache values to avoid duplicated sloads bool isTopLevelCall = !$._initializing; uint64 initialized = $._initialized; // Allowed calls: // - initialSetup: the contract is not in the initializing state and no previous version was // initialized // - construction: the contract is initialized at version 1 (no reinitialization) and the // current contract is just being deployed bool initialSetup = initialized == 0 && isTopLevelCall; bool construction = initialized == 1 && address(this).code.length == 0; if (!initialSetup && !construction) { revert InvalidInitialization(); } $._initialized = 1; if (isTopLevelCall) { $._initializing = true; } _; if (isTopLevelCall) { $._initializing = false; emit Initialized(1); } } /** * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be * used to initialize parent contracts. * * A reinitializer may be used after the original initialization step. This is essential to configure modules that * are added through upgrades and that require initialization. * * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer` * cannot be nested. If one is invoked in the context of another, execution will revert. * * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in * a contract, executing them in the right order is up to the developer or operator. * * WARNING: Setting the version to 2**64 - 1 will prevent any future reinitialization. * * Emits an {Initialized} event. */ modifier reinitializer(uint64 version) { // solhint-disable-next-line var-name-mixedcase InitializableStorage storage $ = _getInitializableStorage(); if ($._initializing || $._initialized >= version) { revert InvalidInitialization(); } $._initialized = version; $._initializing = true; _; $._initializing = false; emit Initialized(version); } /** * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the * {initializer} and {reinitializer} modifiers, directly or indirectly. */ modifier onlyInitializing() { _checkInitializing(); _; } /** * @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}. */ function _checkInitializing() internal view virtual { if (!_isInitializing()) { revert NotInitializing(); } } /** * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call. * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized * to any version. It is recommended to use this to lock implementation contracts that are designed to be called * through proxies. * * Emits an {Initialized} event the first time it is successfully executed. */ function _disableInitializers() internal virtual { // solhint-disable-next-line var-name-mixedcase InitializableStorage storage $ = _getInitializableStorage(); if ($._initializing) { revert InvalidInitialization(); } if ($._initialized != type(uint64).max) { $._initialized = type(uint64).max; emit Initialized(type(uint64).max); } } /** * @dev Returns the highest version that has been initialized. See {reinitializer}. */ function _getInitializedVersion() internal view returns (uint64) { return _getInitializableStorage()._initialized; } /** * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}. */ function _isInitializing() internal view returns (bool) { return _getInitializableStorage()._initializing; } /** * @dev Pointer to storage slot. Allows integrators to override it with a custom storage location. * * NOTE: Consider following the ERC-7201 formula to derive storage locations. */ function _initializableStorageSlot() internal pure virtual returns (bytes32) { return INITIALIZABLE_STORAGE; } /** * @dev Returns a pointer to the storage namespace. */ // solhint-disable-next-line var-name-mixedcase function _getInitializableStorage() private pure returns (InitializableStorage storage $) { bytes32 slot = _initializableStorageSlot(); assembly { $.slot := slot } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.3.0) (proxy/utils/UUPSUpgradeable.sol) pragma solidity ^0.8.22; import {IERC1822Proxiable} from "@openzeppelin/contracts/interfaces/draft-IERC1822.sol"; import {ERC1967Utils} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Utils.sol"; import {Initializable} from "./Initializable.sol"; /** * @dev An upgradeability mechanism designed for UUPS proxies. The functions included here can perform an upgrade of an * {ERC1967Proxy}, when this contract is set as the implementation behind such a proxy. * * A security mechanism ensures that an upgrade does not turn off upgradeability accidentally, although this risk is * reinstated if the upgrade retains upgradeability but removes the security mechanism, e.g. by replacing * `UUPSUpgradeable` with a custom implementation of upgrades. * * The {_authorizeUpgrade} function must be overridden to include access restriction to the upgrade mechanism. */ abstract contract UUPSUpgradeable is Initializable, IERC1822Proxiable { /// @custom:oz-upgrades-unsafe-allow state-variable-immutable address private immutable __self = address(this); /** * @dev The version of the upgrade interface of the contract. If this getter is missing, both `upgradeTo(address)` * and `upgradeToAndCall(address,bytes)` are present, and `upgradeTo` must be used if no function should be called, * while `upgradeToAndCall` will invoke the `receive` function if the second argument is the empty byte string. * If the getter returns `"5.0.0"`, only `upgradeToAndCall(address,bytes)` is present, and the second argument must * be the empty byte string if no function should be called, making it impossible to invoke the `receive` function * during an upgrade. */ string public constant UPGRADE_INTERFACE_VERSION = "5.0.0"; /** * @dev The call is from an unauthorized context. */ error UUPSUnauthorizedCallContext(); /** * @dev The storage `slot` is unsupported as a UUID. */ error UUPSUnsupportedProxiableUUID(bytes32 slot); /** * @dev Check that the execution is being performed through a delegatecall call and that the execution context is * a proxy contract with an implementation (as defined in ERC-1967) pointing to self. This should only be the case * for UUPS and transparent proxies that are using the current contract as their implementation. Execution of a * function through ERC-1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to * fail. */ modifier onlyProxy() { _checkProxy(); _; } /** * @dev Check that the execution is not being performed through a delegate call. This allows a function to be * callable on the implementing contract but not through proxies. */ modifier notDelegated() { _checkNotDelegated(); _; } function __UUPSUpgradeable_init() internal onlyInitializing { } function __UUPSUpgradeable_init_unchained() internal onlyInitializing { } /** * @dev Implementation of the ERC-1822 {proxiableUUID} function. This returns the storage slot used by the * implementation. It is used to validate the implementation's compatibility when performing an upgrade. * * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this * function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier. */ function proxiableUUID() external view virtual notDelegated returns (bytes32) { return ERC1967Utils.IMPLEMENTATION_SLOT; } /** * @dev Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call * encoded in `data`. * * Calls {_authorizeUpgrade}. * * Emits an {Upgraded} event. * * @custom:oz-upgrades-unsafe-allow-reachable delegatecall */ function upgradeToAndCall(address newImplementation, bytes memory data) public payable virtual onlyProxy { _authorizeUpgrade(newImplementation); _upgradeToAndCallUUPS(newImplementation, data); } /** * @dev Reverts if the execution is not performed via delegatecall or the execution * context is not of a proxy with an ERC-1967 compliant implementation pointing to self. */ function _checkProxy() internal view virtual { if ( address(this) == __self || // Must be called through delegatecall ERC1967Utils.getImplementation() != __self // Must be called through an active proxy ) { revert UUPSUnauthorizedCallContext(); } } /** * @dev Reverts if the execution is performed via delegatecall. * See {notDelegated}. */ function _checkNotDelegated() internal view virtual { if (address(this) != __self) { // Must not be called through delegatecall revert UUPSUnauthorizedCallContext(); } } /** * @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by * {upgradeToAndCall}. * * Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}. * * ```solidity * function _authorizeUpgrade(address) internal onlyOwner {} * ``` */ function _authorizeUpgrade(address newImplementation) internal virtual; /** * @dev Performs an implementation upgrade with a security check for UUPS proxies, and additional setup call. * * As a security check, {proxiableUUID} is invoked in the new implementation, and the return value * is expected to be the implementation slot in ERC-1967. * * Emits an {IERC1967-Upgraded} event. */ function _upgradeToAndCallUUPS(address newImplementation, bytes memory data) private { try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) { if (slot != ERC1967Utils.IMPLEMENTATION_SLOT) { revert UUPSUnsupportedProxiableUUID(slot); } ERC1967Utils.upgradeToAndCall(newImplementation, data); } catch { // The implementation is not UUPS revert ERC1967Utils.ERC1967InvalidImplementation(newImplementation); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol) pragma solidity ^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. */ abstract contract Ownable is Context { address private _owner; /** * @dev The caller account is not authorized to perform an operation. */ error OwnableUnauthorizedAccount(address account); /** * @dev The owner is not a valid owner account. (eg. `address(0)`) */ error OwnableInvalidOwner(address owner); event OwnershipTransferred(address indexed previousOwner, address indexed 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. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { 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. */ function renounceOwnership() public virtual onlyOwner { _transferOwnership(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { 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) internal virtual { address oldOwner = _owner; _owner = newOwner; emit OwnershipTransferred(oldOwner, newOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (interfaces/IERC1363.sol) pragma solidity ^0.8.20; import {IERC20} from "./IERC20.sol"; import {IERC165} from "./IERC165.sol"; /** * @title IERC1363 * @dev Interface of the ERC-1363 standard as defined in the https://eips.ethereum.org/EIPS/eip-1363[ERC-1363]. * * Defines an extension interface for ERC-20 tokens that supports executing code on a recipient contract * after `transfer` or `transferFrom`, or code on a spender contract after `approve`, in a single transaction. */ interface IERC1363 is IERC20, IERC165 { /* * Note: the ERC-165 identifier for this interface is 0xb0202a11. * 0xb0202a11 === * bytes4(keccak256('transferAndCall(address,uint256)')) ^ * bytes4(keccak256('transferAndCall(address,uint256,bytes)')) ^ * bytes4(keccak256('transferFromAndCall(address,address,uint256)')) ^ * bytes4(keccak256('transferFromAndCall(address,address,uint256,bytes)')) ^ * bytes4(keccak256('approveAndCall(address,uint256)')) ^ * bytes4(keccak256('approveAndCall(address,uint256,bytes)')) */ /** * @dev Moves a `value` amount of tokens from the caller's account to `to` * and then calls {IERC1363Receiver-onTransferReceived} on `to`. * @param to The address which you want to transfer to. * @param value The amount of tokens to be transferred. * @return A boolean value indicating whether the operation succeeded unless throwing. */ function transferAndCall(address to, uint256 value) external returns (bool); /** * @dev Moves a `value` amount of tokens from the caller's account to `to` * and then calls {IERC1363Receiver-onTransferReceived} on `to`. * @param to The address which you want to transfer to. * @param value The amount of tokens to be transferred. * @param data Additional data with no specified format, sent in call to `to`. * @return A boolean value indicating whether the operation succeeded unless throwing. */ function transferAndCall(address to, uint256 value, bytes calldata data) external returns (bool); /** * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism * and then calls {IERC1363Receiver-onTransferReceived} on `to`. * @param from The address which you want to send tokens from. * @param to The address which you want to transfer to. * @param value The amount of tokens to be transferred. * @return A boolean value indicating whether the operation succeeded unless throwing. */ function transferFromAndCall(address from, address to, uint256 value) external returns (bool); /** * @dev Moves a `value` amount of tokens from `from` to `to` using the allowance mechanism * and then calls {IERC1363Receiver-onTransferReceived} on `to`. * @param from The address which you want to send tokens from. * @param to The address which you want to transfer to. * @param value The amount of tokens to be transferred. * @param data Additional data with no specified format, sent in call to `to`. * @return A boolean value indicating whether the operation succeeded unless throwing. */ function transferFromAndCall(address from, address to, uint256 value, bytes calldata data) external returns (bool); /** * @dev Sets a `value` amount of tokens as the allowance of `spender` over the * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`. * @param spender The address which will spend the funds. * @param value The amount of tokens to be spent. * @return A boolean value indicating whether the operation succeeded unless throwing. */ function approveAndCall(address spender, uint256 value) external returns (bool); /** * @dev Sets a `value` amount of tokens as the allowance of `spender` over the * caller's tokens and then calls {IERC1363Spender-onApprovalReceived} on `spender`. * @param spender The address which will spend the funds. * @param value The amount of tokens to be spent. * @param data Additional data with no specified format, sent in call to `spender`. * @return A boolean value indicating whether the operation succeeded unless throwing. */ function approveAndCall(address spender, uint256 value, bytes calldata data) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC165.sol) pragma solidity ^0.8.20; import {IERC165} from "../utils/introspection/IERC165.sol";
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC1967.sol) pragma solidity ^0.8.20; /** * @dev ERC-1967: Proxy Storage Slots. This interface contains the events defined in the ERC. */ interface IERC1967 { /** * @dev Emitted when the implementation is upgraded. */ event Upgraded(address indexed implementation); /** * @dev Emitted when the admin account has changed. */ event AdminChanged(address previousAdmin, address newAdmin); /** * @dev Emitted when the beacon is changed. */ event BeaconUpgraded(address indexed beacon); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC20.sol) pragma solidity ^0.8.20; import {IERC20} from "../token/ERC20/IERC20.sol";
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (interfaces/draft-IERC1822.sol) pragma solidity ^0.8.20; /** * @dev ERC-1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified * proxy whose upgrades are fully controlled by the current implementation. */ interface IERC1822Proxiable { /** * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation * address. * * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this * function revert if invoked through a proxy. */ function proxiableUUID() external view returns (bytes32); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (interfaces/draft-IERC6093.sol) pragma solidity ^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. */ interface IERC20Errors { /** * @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. */ error ERC20InsufficientBalance(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. */ error ERC20InvalidSender(address sender); /** * @dev Indicates a failure with the token `receiver`. Used in transfers. * @param receiver Address to which tokens are being transferred. */ error ERC20InvalidReceiver(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. */ error ERC20InsufficientAllowance(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. */ error ERC20InvalidApprover(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. */ error ERC20InvalidSpender(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. */ interface IERC721Errors { /** * @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. */ error ERC721InvalidOwner(address owner); /** * @dev Indicates a `tokenId` whose `owner` is the zero address. * @param tokenId Identifier number of a token. */ error ERC721NonexistentToken(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. */ error ERC721IncorrectOwner(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. */ error ERC721InvalidSender(address sender); /** * @dev Indicates a failure with the token `receiver`. Used in transfers. * @param receiver Address to which tokens are being transferred. */ error ERC721InvalidReceiver(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. */ error ERC721InsufficientApproval(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. */ error ERC721InvalidApprover(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. */ error ERC721InvalidOperator(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. */ interface IERC1155Errors { /** * @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. */ error ERC1155InsufficientBalance(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. */ error ERC1155InvalidSender(address sender); /** * @dev Indicates a failure with the token `receiver`. Used in transfers. * @param receiver Address to which tokens are being transferred. */ error ERC1155InvalidReceiver(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. */ error ERC1155MissingApprovalForAll(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. */ error ERC1155InvalidApprover(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. */ error ERC1155InvalidOperator(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 */ error ERC1155InvalidArrayLength(uint256 idsLength, uint256 valuesLength); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.3.0) (proxy/Clones.sol) pragma solidity ^0.8.20; import {Create2} from "../utils/Create2.sol"; import {Errors} from "../utils/Errors.sol"; /** * @dev https://eips.ethereum.org/EIPS/eip-1167[ERC-1167] is a standard for * deploying minimal proxy contracts, also known as "clones". * * > To simply and cheaply clone contract functionality in an immutable way, this standard specifies * > a minimal bytecode implementation that delegates all calls to a known, fixed address. * * The library includes functions to deploy a proxy using either `create` (traditional deployment) or `create2` * (salted deterministic deployment). It also includes functions to predict the addresses of clones deployed using the * deterministic method. */ library Clones { error CloneArgumentsTooLong(); /** * @dev Deploys and returns the address of a clone that mimics the behavior of `implementation`. * * This function uses the create opcode, which should never revert. */ function clone(address implementation) internal returns (address instance) { return clone(implementation, 0); } /** * @dev Same as {xref-Clones-clone-address-}[clone], but with a `value` parameter to send native currency * to the new contract. * * NOTE: Using a non-zero value at creation will require the contract using this function (e.g. a factory) * to always have enough balance for new deployments. Consider exposing this function under a payable method. */ function clone(address implementation, uint256 value) internal returns (address instance) { if (address(this).balance < value) { revert Errors.InsufficientBalance(address(this).balance, value); } assembly ("memory-safe") { // Cleans the upper 96 bits of the `implementation` word, then packs the first 3 bytes // of the `implementation` address with the bytecode before the address. mstore(0x00, or(shr(0xe8, shl(0x60, implementation)), 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000)) // Packs the remaining 17 bytes of `implementation` with the bytecode after the address. mstore(0x20, or(shl(0x78, implementation), 0x5af43d82803e903d91602b57fd5bf3)) instance := create(value, 0x09, 0x37) } if (instance == address(0)) { revert Errors.FailedDeployment(); } } /** * @dev Deploys and returns the address of a clone that mimics the behavior of `implementation`. * * This function uses the create2 opcode and a `salt` to deterministically deploy * the clone. Using the same `implementation` and `salt` multiple times will revert, since * the clones cannot be deployed twice at the same address. */ function cloneDeterministic(address implementation, bytes32 salt) internal returns (address instance) { return cloneDeterministic(implementation, salt, 0); } /** * @dev Same as {xref-Clones-cloneDeterministic-address-bytes32-}[cloneDeterministic], but with * a `value` parameter to send native currency to the new contract. * * NOTE: Using a non-zero value at creation will require the contract using this function (e.g. a factory) * to always have enough balance for new deployments. Consider exposing this function under a payable method. */ function cloneDeterministic( address implementation, bytes32 salt, uint256 value ) internal returns (address instance) { if (address(this).balance < value) { revert Errors.InsufficientBalance(address(this).balance, value); } assembly ("memory-safe") { // Cleans the upper 96 bits of the `implementation` word, then packs the first 3 bytes // of the `implementation` address with the bytecode before the address. mstore(0x00, or(shr(0xe8, shl(0x60, implementation)), 0x3d602d80600a3d3981f3363d3d373d3d3d363d73000000)) // Packs the remaining 17 bytes of `implementation` with the bytecode after the address. mstore(0x20, or(shl(0x78, implementation), 0x5af43d82803e903d91602b57fd5bf3)) instance := create2(value, 0x09, 0x37, salt) } if (instance == address(0)) { revert Errors.FailedDeployment(); } } /** * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}. */ function predictDeterministicAddress( address implementation, bytes32 salt, address deployer ) internal pure returns (address predicted) { assembly ("memory-safe") { let ptr := mload(0x40) mstore(add(ptr, 0x38), deployer) mstore(add(ptr, 0x24), 0x5af43d82803e903d91602b57fd5bf3ff) mstore(add(ptr, 0x14), implementation) mstore(ptr, 0x3d602d80600a3d3981f3363d3d373d3d3d363d73) mstore(add(ptr, 0x58), salt) mstore(add(ptr, 0x78), keccak256(add(ptr, 0x0c), 0x37)) predicted := and(keccak256(add(ptr, 0x43), 0x55), 0xffffffffffffffffffffffffffffffffffffffff) } } /** * @dev Computes the address of a clone deployed using {Clones-cloneDeterministic}. */ function predictDeterministicAddress( address implementation, bytes32 salt ) internal view returns (address predicted) { return predictDeterministicAddress(implementation, salt, address(this)); } /** * @dev Deploys and returns the address of a clone that mimics the behavior of `implementation` with custom * immutable arguments. These are provided through `args` and cannot be changed after deployment. To * access the arguments within the implementation, use {fetchCloneArgs}. * * This function uses the create opcode, which should never revert. */ function cloneWithImmutableArgs(address implementation, bytes memory args) internal returns (address instance) { return cloneWithImmutableArgs(implementation, args, 0); } /** * @dev Same as {xref-Clones-cloneWithImmutableArgs-address-bytes-}[cloneWithImmutableArgs], but with a `value` * parameter to send native currency to the new contract. * * NOTE: Using a non-zero value at creation will require the contract using this function (e.g. a factory) * to always have enough balance for new deployments. Consider exposing this function under a payable method. */ function cloneWithImmutableArgs( address implementation, bytes memory args, uint256 value ) internal returns (address instance) { if (address(this).balance < value) { revert Errors.InsufficientBalance(address(this).balance, value); } bytes memory bytecode = _cloneCodeWithImmutableArgs(implementation, args); assembly ("memory-safe") { instance := create(value, add(bytecode, 0x20), mload(bytecode)) } if (instance == address(0)) { revert Errors.FailedDeployment(); } } /** * @dev Deploys and returns the address of a clone that mimics the behavior of `implementation` with custom * immutable arguments. These are provided through `args` and cannot be changed after deployment. To * access the arguments within the implementation, use {fetchCloneArgs}. * * This function uses the create2 opcode and a `salt` to deterministically deploy the clone. Using the same * `implementation`, `args` and `salt` multiple times will revert, since the clones cannot be deployed twice * at the same address. */ function cloneDeterministicWithImmutableArgs( address implementation, bytes memory args, bytes32 salt ) internal returns (address instance) { return cloneDeterministicWithImmutableArgs(implementation, args, salt, 0); } /** * @dev Same as {xref-Clones-cloneDeterministicWithImmutableArgs-address-bytes-bytes32-}[cloneDeterministicWithImmutableArgs], * but with a `value` parameter to send native currency to the new contract. * * NOTE: Using a non-zero value at creation will require the contract using this function (e.g. a factory) * to always have enough balance for new deployments. Consider exposing this function under a payable method. */ function cloneDeterministicWithImmutableArgs( address implementation, bytes memory args, bytes32 salt, uint256 value ) internal returns (address instance) { bytes memory bytecode = _cloneCodeWithImmutableArgs(implementation, args); return Create2.deploy(value, salt, bytecode); } /** * @dev Computes the address of a clone deployed using {Clones-cloneDeterministicWithImmutableArgs}. */ function predictDeterministicAddressWithImmutableArgs( address implementation, bytes memory args, bytes32 salt, address deployer ) internal pure returns (address predicted) { bytes memory bytecode = _cloneCodeWithImmutableArgs(implementation, args); return Create2.computeAddress(salt, keccak256(bytecode), deployer); } /** * @dev Computes the address of a clone deployed using {Clones-cloneDeterministicWithImmutableArgs}. */ function predictDeterministicAddressWithImmutableArgs( address implementation, bytes memory args, bytes32 salt ) internal view returns (address predicted) { return predictDeterministicAddressWithImmutableArgs(implementation, args, salt, address(this)); } /** * @dev Get the immutable args attached to a clone. * * - If `instance` is a clone that was deployed using `clone` or `cloneDeterministic`, this * function will return an empty array. * - If `instance` is a clone that was deployed using `cloneWithImmutableArgs` or * `cloneDeterministicWithImmutableArgs`, this function will return the args array used at * creation. * - If `instance` is NOT a clone deployed using this library, the behavior is undefined. This * function should only be used to check addresses that are known to be clones. */ function fetchCloneArgs(address instance) internal view returns (bytes memory) { bytes memory result = new bytes(instance.code.length - 45); // revert if length is too short assembly ("memory-safe") { extcodecopy(instance, add(result, 32), 45, mload(result)) } return result; } /** * @dev Helper that prepares the initcode of the proxy with immutable args. * * An assembly variant of this function requires copying the `args` array, which can be efficiently done using * `mcopy`. Unfortunately, that opcode is not available before cancun. A pure solidity implementation using * abi.encodePacked is more expensive but also more portable and easier to review. * * NOTE: https://eips.ethereum.org/EIPS/eip-170[EIP-170] limits the length of the contract code to 24576 bytes. * With the proxy code taking 45 bytes, that limits the length of the immutable args to 24531 bytes. */ function _cloneCodeWithImmutableArgs( address implementation, bytes memory args ) private pure returns (bytes memory) { if (args.length > 24531) revert CloneArgumentsTooLong(); return abi.encodePacked( hex"61", uint16(args.length + 45), hex"3d81600a3d39f3363d3d373d3d3d363d73", implementation, hex"5af43d82803e903d91602b57fd5bf3", args ); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.2.0) (proxy/ERC1967/ERC1967Utils.sol) pragma solidity ^0.8.22; import {IBeacon} from "../beacon/IBeacon.sol"; import {IERC1967} from "../../interfaces/IERC1967.sol"; import {Address} from "../../utils/Address.sol"; import {StorageSlot} from "../../utils/StorageSlot.sol"; /** * @dev This library provides getters and event emitting update functions for * https://eips.ethereum.org/EIPS/eip-1967[ERC-1967] slots. */ library ERC1967Utils { /** * @dev Storage slot with the address of the current implementation. * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1. */ // solhint-disable-next-line private-vars-leading-underscore bytes32 internal constant IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc; /** * @dev The `implementation` of the proxy is invalid. */ error ERC1967InvalidImplementation(address implementation); /** * @dev The `admin` of the proxy is invalid. */ error ERC1967InvalidAdmin(address admin); /** * @dev The `beacon` of the proxy is invalid. */ error ERC1967InvalidBeacon(address beacon); /** * @dev An upgrade function sees `msg.value > 0` that may be lost. */ error ERC1967NonPayable(); /** * @dev Returns the current implementation address. */ function getImplementation() internal view returns (address) { return StorageSlot.getAddressSlot(IMPLEMENTATION_SLOT).value; } /** * @dev Stores a new address in the ERC-1967 implementation slot. */ function _setImplementation(address newImplementation) private { if (newImplementation.code.length == 0) { revert ERC1967InvalidImplementation(newImplementation); } StorageSlot.getAddressSlot(IMPLEMENTATION_SLOT).value = newImplementation; } /** * @dev Performs implementation upgrade with additional setup call if data is nonempty. * This function is payable only if the setup call is performed, otherwise `msg.value` is rejected * to avoid stuck value in the contract. * * Emits an {IERC1967-Upgraded} event. */ function upgradeToAndCall(address newImplementation, bytes memory data) internal { _setImplementation(newImplementation); emit IERC1967.Upgraded(newImplementation); if (data.length > 0) { Address.functionDelegateCall(newImplementation, data); } else { _checkNonPayable(); } } /** * @dev Storage slot with the admin of the contract. * This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1. */ // solhint-disable-next-line private-vars-leading-underscore bytes32 internal constant ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103; /** * @dev Returns the current admin. * * TIP: To get this value clients can read directly from the storage slot shown below (specified by ERC-1967) using * the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call. * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103` */ function getAdmin() internal view returns (address) { return StorageSlot.getAddressSlot(ADMIN_SLOT).value; } /** * @dev Stores a new address in the ERC-1967 admin slot. */ function _setAdmin(address newAdmin) private { if (newAdmin == address(0)) { revert ERC1967InvalidAdmin(address(0)); } StorageSlot.getAddressSlot(ADMIN_SLOT).value = newAdmin; } /** * @dev Changes the admin of the proxy. * * Emits an {IERC1967-AdminChanged} event. */ function changeAdmin(address newAdmin) internal { emit IERC1967.AdminChanged(getAdmin(), newAdmin); _setAdmin(newAdmin); } /** * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy. * This is the keccak-256 hash of "eip1967.proxy.beacon" subtracted by 1. */ // solhint-disable-next-line private-vars-leading-underscore bytes32 internal constant BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50; /** * @dev Returns the current beacon. */ function getBeacon() internal view returns (address) { return StorageSlot.getAddressSlot(BEACON_SLOT).value; } /** * @dev Stores a new beacon in the ERC-1967 beacon slot. */ function _setBeacon(address newBeacon) private { if (newBeacon.code.length == 0) { revert ERC1967InvalidBeacon(newBeacon); } StorageSlot.getAddressSlot(BEACON_SLOT).value = newBeacon; address beaconImplementation = IBeacon(newBeacon).implementation(); if (beaconImplementation.code.length == 0) { revert ERC1967InvalidImplementation(beaconImplementation); } } /** * @dev Change the beacon and trigger a setup call if data is nonempty. * This function is payable only if the setup call is performed, otherwise `msg.value` is rejected * to avoid stuck value in the contract. * * Emits an {IERC1967-BeaconUpgraded} event. * * CAUTION: Invoking this function has no effect on an instance of {BeaconProxy} since v5, since * it uses an immutable beacon without looking at the value of the ERC-1967 beacon slot for * efficiency. */ function upgradeBeaconToAndCall(address newBeacon, bytes memory data) internal { _setBeacon(newBeacon); emit IERC1967.BeaconUpgraded(newBeacon); if (data.length > 0) { Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data); } else { _checkNonPayable(); } } /** * @dev Reverts if `msg.value` is not zero. It can be used to avoid `msg.value` stuck in the contract * if an upgrade doesn't perform an initialization call. */ function _checkNonPayable() private { if (msg.value > 0) { revert ERC1967NonPayable(); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.0) (proxy/beacon/IBeacon.sol) pragma solidity ^0.8.20; /** * @dev This is the interface that {BeaconProxy} expects of its beacon. */ interface IBeacon { /** * @dev Must return an address that can be used as a delegate call target. * * {UpgradeableBeacon} will check that this address is a contract. */ function implementation() external view returns (address); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.3.0) (token/ERC20/ERC20.sol) pragma solidity ^0.8.20; import {IERC20} from "./IERC20.sol"; import {IERC20Metadata} from "./extensions/IERC20Metadata.sol"; import {Context} from "../../utils/Context.sol"; import {IERC20Errors} from "../../interfaces/draft-IERC6093.sol"; /** * @dev Implementation of the {IERC20} interface. * * This implementation is agnostic to the way tokens are created. This means * that a supply mechanism has to be added in a derived contract using {_mint}. * * TIP: For a detailed writeup see our guide * https://forum.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How * to implement supply mechanisms]. * * The default value of {decimals} is 18. To change this, you should override * this function so it returns a different value. * * We have followed general OpenZeppelin Contracts guidelines: functions revert * instead returning `false` on failure. This behavior is nonetheless * conventional and does not conflict with the expectations of ERC-20 * applications. */ abstract contract ERC20 is Context, IERC20, IERC20Metadata, IERC20Errors { mapping(address account => uint256) private _balances; mapping(address account => mapping(address spender => uint256)) private _allowances; uint256 private _totalSupply; string private _name; string private _symbol; /** * @dev Sets the values for {name} and {symbol}. * * Both values are immutable: they can only be set once during construction. */ constructor(string memory name_, string memory symbol_) { _name = name_; _symbol = symbol_; } /** * @dev Returns the name of the token. */ function name() public view virtual returns (string memory) { return _name; } /** * @dev Returns the symbol of the token, usually a shorter version of the * name. */ function symbol() public view virtual returns (string memory) { return _symbol; } /** * @dev Returns the number of decimals used to get its user representation. * For example, if `decimals` equals `2`, a balance of `505` tokens should * be displayed to a user as `5.05` (`505 / 10 ** 2`). * * Tokens usually opt for a value of 18, imitating the relationship between * Ether and Wei. This is the default value returned by this function, unless * it's overridden. * * NOTE: This information is only used for _display_ purposes: it in * no way affects any of the arithmetic of the contract, including * {IERC20-balanceOf} and {IERC20-transfer}. */ function decimals() public view virtual returns (uint8) { return 18; } /** * @dev See {IERC20-totalSupply}. */ function totalSupply() public view virtual returns (uint256) { return _totalSupply; } /** * @dev See {IERC20-balanceOf}. */ function balanceOf(address account) public view virtual returns (uint256) { return _balances[account]; } /** * @dev See {IERC20-transfer}. * * Requirements: * * - `to` cannot be the zero address. * - the caller must have a balance of at least `value`. */ function transfer(address to, uint256 value) public virtual returns (bool) { address owner = _msgSender(); _transfer(owner, to, value); return true; } /** * @dev See {IERC20-allowance}. */ function allowance(address owner, address spender) public view virtual returns (uint256) { return _allowances[owner][spender]; } /** * @dev See {IERC20-approve}. * * NOTE: If `value` is the maximum `uint256`, the allowance is not updated on * `transferFrom`. This is semantically equivalent to an infinite approval. * * Requirements: * * - `spender` cannot be the zero address. */ function approve(address spender, uint256 value) public virtual returns (bool) { address owner = _msgSender(); _approve(owner, spender, value); return true; } /** * @dev See {IERC20-transferFrom}. * * Skips emitting an {Approval} event indicating an allowance update. This is not * required by the ERC. See {xref-ERC20-_approve-address-address-uint256-bool-}[_approve]. * * NOTE: Does not update the allowance if the current allowance * is the maximum `uint256`. * * Requirements: * * - `from` and `to` cannot be the zero address. * - `from` must have a balance of at least `value`. * - the caller must have allowance for ``from``'s tokens of at least * `value`. */ function transferFrom(address from, address to, uint256 value) public virtual returns (bool) { address spender = _msgSender(); _spendAllowance(from, spender, value); _transfer(from, to, value); return true; } /** * @dev Moves a `value` amount of tokens from `from` to `to`. * * This internal function is equivalent to {transfer}, and can be used to * e.g. implement automatic token fees, slashing mechanisms, etc. * * Emits a {Transfer} event. * * NOTE: This function is not virtual, {_update} should be overridden instead. */ function _transfer(address from, address to, uint256 value) internal { if (from == address(0)) { revert ERC20InvalidSender(address(0)); } if (to == address(0)) { revert ERC20InvalidReceiver(address(0)); } _update(from, to, value); } /** * @dev Transfers a `value` amount of tokens from `from` to `to`, or alternatively mints (or burns) if `from` * (or `to`) is the zero address. All customizations to transfers, mints, and burns should be done by overriding * this function. * * Emits a {Transfer} event. */ function _update(address from, address to, uint256 value) internal virtual { if (from == address(0)) { // Overflow check required: The rest of the code assumes that totalSupply never overflows _totalSupply += value; } else { uint256 fromBalance = _balances[from]; if (fromBalance < value) { revert ERC20InsufficientBalance(from, fromBalance, value); } unchecked { // Overflow not possible: value <= fromBalance <= totalSupply. _balances[from] = fromBalance - value; } } if (to == address(0)) { unchecked { // Overflow not possible: value <= totalSupply or value <= fromBalance <= totalSupply. _totalSupply -= value; } } else { unchecked { // Overflow not possible: balance + value is at most totalSupply, which we know fits into a uint256. _balances[to] += value; } } emit Transfer(from, to, value); } /** * @dev Creates a `value` amount of tokens and assigns them to `account`, by transferring it from address(0). * Relies on the `_update` mechanism * * Emits a {Transfer} event with `from` set to the zero address. * * NOTE: This function is not virtual, {_update} should be overridden instead. */ function _mint(address account, uint256 value) internal { if (account == address(0)) { revert ERC20InvalidReceiver(address(0)); } _update(address(0), account, value); } /** * @dev Destroys a `value` amount of tokens from `account`, lowering the total supply. * Relies on the `_update` mechanism. * * Emits a {Transfer} event with `to` set to the zero address. * * NOTE: This function is not virtual, {_update} should be overridden instead */ function _burn(address account, uint256 value) internal { if (account == address(0)) { revert ERC20InvalidSender(address(0)); } _update(account, address(0), value); } /** * @dev Sets `value` as the allowance of `spender` over the `owner`'s tokens. * * This internal function is equivalent to `approve`, and can be used to * e.g. set automatic allowances for certain subsystems, etc. * * Emits an {Approval} event. * * Requirements: * * - `owner` cannot be the zero address. * - `spender` cannot be the zero address. * * Overrides to this logic should be done to the variant with an additional `bool emitEvent` argument. */ function _approve(address owner, address spender, uint256 value) internal { _approve(owner, spender, value, true); } /** * @dev Variant of {_approve} with an optional flag to enable or disable the {Approval} event. * * By default (when calling {_approve}) the flag is set to true. On the other hand, approval changes made by * `_spendAllowance` during the `transferFrom` operation set the flag to false. This saves gas by not emitting any * `Approval` event during `transferFrom` operations. * * Anyone who wishes to continue emitting `Approval` events on the`transferFrom` operation can force the flag to * true using the following override: * * ```solidity * function _approve(address owner, address spender, uint256 value, bool) internal virtual override { * super._approve(owner, spender, value, true); * } * ``` * * Requirements are the same as {_approve}. */ function _approve(address owner, address spender, uint256 value, bool emitEvent) internal virtual { if (owner == address(0)) { revert ERC20InvalidApprover(address(0)); } if (spender == address(0)) { revert ERC20InvalidSpender(address(0)); } _allowances[owner][spender] = value; if (emitEvent) { emit Approval(owner, spender, value); } } /** * @dev Updates `owner`'s allowance for `spender` based on spent `value`. * * Does not update the allowance value in case of infinite allowance. * Revert if not enough allowance is available. * * Does not emit an {Approval} event. */ function _spendAllowance(address owner, address spender, uint256 value) internal virtual { uint256 currentAllowance = allowance(owner, spender); if (currentAllowance < type(uint256).max) { if (currentAllowance < value) { revert ERC20InsufficientAllowance(spender, currentAllowance, value); } unchecked { _approve(owner, spender, currentAllowance - value, false); } } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/IERC20.sol) pragma solidity ^0.8.20; /** * @dev Interface of the ERC-20 standard as defined in the ERC. */ interface IERC20 { /** * @dev Emitted when `value` tokens are moved from one account (`from`) to * another (`to`). * * Note that `value` may be zero. */ event Transfer(address indexed from, address indexed 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. */ event Approval(address indexed owner, address indexed spender, uint256 value); /** * @dev Returns the value of tokens in existence. */ function totalSupply() external view returns (uint256); /** * @dev Returns the value of tokens owned by `account`. */ function balanceOf(address account) external view returns (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. */ function transfer(address to, uint256 value) external returns (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. */ function allowance(address owner, address spender) external view returns (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. */ function approve(address spender, uint256 value) external returns (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. */ function transferFrom(address from, address to, uint256 value) external returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (token/ERC20/extensions/IERC20Metadata.sol) pragma solidity ^0.8.20; import {IERC20} from "../IERC20.sol"; /** * @dev Interface for the optional metadata functions from the ERC-20 standard. */ interface IERC20Metadata is IERC20 { /** * @dev Returns the name of the token. */ function name() external view returns (string memory); /** * @dev Returns the symbol of the token. */ function symbol() external view returns (string memory); /** * @dev Returns the decimals places of the token. */ function decimals() external view returns (uint8); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.3.0) (token/ERC20/utils/SafeERC20.sol) pragma solidity ^0.8.20; import {IERC20} from "../IERC20.sol"; import {IERC1363} from "../../../interfaces/IERC1363.sol"; /** * @title SafeERC20 * @dev Wrappers around ERC-20 operations that throw on failure (when the token * contract returns false). Tokens that return no value (and instead revert or * throw on failure) are also supported, non-reverting calls are assumed to be * successful. * To use this library you can add a `using SafeERC20 for IERC20;` statement to your contract, * which allows you to call the safe operations as `token.safeTransfer(...)`, etc. */ library SafeERC20 { /** * @dev An operation with an ERC-20 token failed. */ error SafeERC20FailedOperation(address token); /** * @dev Indicates a failed `decreaseAllowance` request. */ error SafeERC20FailedDecreaseAllowance(address spender, uint256 currentAllowance, uint256 requestedDecrease); /** * @dev Transfer `value` amount of `token` from the calling contract to `to`. If `token` returns no value, * non-reverting calls are assumed to be successful. */ function safeTransfer(IERC20 token, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeCall(token.transfer, (to, value))); } /** * @dev Transfer `value` amount of `token` from `from` to `to`, spending the approval given by `from` to the * calling contract. If `token` returns no value, non-reverting calls are assumed to be successful. */ function safeTransferFrom(IERC20 token, address from, address to, uint256 value) internal { _callOptionalReturn(token, abi.encodeCall(token.transferFrom, (from, to, value))); } /** * @dev Variant of {safeTransfer} that returns a bool instead of reverting if the operation is not successful. */ function trySafeTransfer(IERC20 token, address to, uint256 value) internal returns (bool) { return _callOptionalReturnBool(token, abi.encodeCall(token.transfer, (to, value))); } /** * @dev Variant of {safeTransferFrom} that returns a bool instead of reverting if the operation is not successful. */ function trySafeTransferFrom(IERC20 token, address from, address to, uint256 value) internal returns (bool) { return _callOptionalReturnBool(token, abi.encodeCall(token.transferFrom, (from, to, value))); } /** * @dev Increase the calling contract's allowance toward `spender` by `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. * * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client" * smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior. */ function safeIncreaseAllowance(IERC20 token, address spender, uint256 value) internal { uint256 oldAllowance = token.allowance(address(this), spender); forceApprove(token, spender, oldAllowance + value); } /** * @dev Decrease the calling contract's allowance toward `spender` by `requestedDecrease`. If `token` returns no * value, non-reverting calls are assumed to be successful. * * IMPORTANT: If the token implements ERC-7674 (ERC-20 with temporary allowance), and if the "client" * smart contract uses ERC-7674 to set temporary allowances, then the "client" smart contract should avoid using * this function. Performing a {safeIncreaseAllowance} or {safeDecreaseAllowance} operation on a token contract * that has a non-zero temporary allowance (for that particular owner-spender) will result in unexpected behavior. */ function safeDecreaseAllowance(IERC20 token, address spender, uint256 requestedDecrease) internal { unchecked { uint256 currentAllowance = token.allowance(address(this), spender); if (currentAllowance < requestedDecrease) { revert SafeERC20FailedDecreaseAllowance(spender, currentAllowance, requestedDecrease); } forceApprove(token, spender, currentAllowance - requestedDecrease); } } /** * @dev Set the calling contract's allowance toward `spender` to `value`. If `token` returns no value, * non-reverting calls are assumed to be successful. Meant to be used with tokens that require the approval * to be set to zero before setting it to a non-zero value, such as USDT. * * NOTE: If the token implements ERC-7674, this function will not modify any temporary allowance. This function * only sets the "standard" allowance. Any temporary allowance will remain active, in addition to the value being * set here. */ function forceApprove(IERC20 token, address spender, uint256 value) internal { bytes memory approvalCall = abi.encodeCall(token.approve, (spender, value)); if (!_callOptionalReturnBool(token, approvalCall)) { _callOptionalReturn(token, abi.encodeCall(token.approve, (spender, 0))); _callOptionalReturn(token, approvalCall); } } /** * @dev Performs an {ERC1363} transferAndCall, with a fallback to the simple {ERC20} transfer if the target has no * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when * targeting contracts. * * Reverts if the returned value is other than `true`. */ function transferAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal { if (to.code.length == 0) { safeTransfer(token, to, value); } else if (!token.transferAndCall(to, value, data)) { revert SafeERC20FailedOperation(address(token)); } } /** * @dev Performs an {ERC1363} transferFromAndCall, with a fallback to the simple {ERC20} transferFrom if the target * has no code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when * targeting contracts. * * Reverts if the returned value is other than `true`. */ function transferFromAndCallRelaxed( IERC1363 token, address from, address to, uint256 value, bytes memory data ) internal { if (to.code.length == 0) { safeTransferFrom(token, from, to, value); } else if (!token.transferFromAndCall(from, to, value, data)) { revert SafeERC20FailedOperation(address(token)); } } /** * @dev Performs an {ERC1363} approveAndCall, with a fallback to the simple {ERC20} approve if the target has no * code. This can be used to implement an {ERC721}-like safe transfer that rely on {ERC1363} checks when * targeting contracts. * * NOTE: When the recipient address (`to`) has no code (i.e. is an EOA), this function behaves as {forceApprove}. * Opposedly, when the recipient address (`to`) has code, this function only attempts to call {ERC1363-approveAndCall} * once without retrying, and relies on the returned value to be true. * * Reverts if the returned value is other than `true`. */ function approveAndCallRelaxed(IERC1363 token, address to, uint256 value, bytes memory data) internal { if (to.code.length == 0) { forceApprove(token, to, value); } else if (!token.approveAndCall(to, value, data)) { revert SafeERC20FailedOperation(address(token)); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). * * This is a variant of {_callOptionalReturnBool} that reverts if call fails to meet the requirements. */ function _callOptionalReturn(IERC20 token, bytes memory data) private { uint256 returnSize; uint256 returnValue; assembly ("memory-safe") { let success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20) // bubble errors if iszero(success) { let ptr := mload(0x40) returndatacopy(ptr, 0, returndatasize()) revert(ptr, returndatasize()) } returnSize := returndatasize() returnValue := mload(0) } if (returnSize == 0 ? address(token).code.length == 0 : returnValue != 1) { revert SafeERC20FailedOperation(address(token)); } } /** * @dev Imitates a Solidity high-level call (i.e. a regular function call to a contract), relaxing the requirement * on the return value: the return value is optional (but if data is returned, it must not be false). * @param token The token targeted by the call. * @param data The call data (encoded using abi.encode or one of its variants). * * This is a variant of {_callOptionalReturn} that silently catches all reverts and returns a bool instead. */ function _callOptionalReturnBool(IERC20 token, bytes memory data) private returns (bool) { bool success; uint256 returnSize; uint256 returnValue; assembly ("memory-safe") { success := call(gas(), token, 0, add(data, 0x20), mload(data), 0, 0x20) returnSize := returndatasize() returnValue := mload(0) } return success && (returnSize == 0 ? address(token).code.length > 0 : returnValue == 1); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.2.0) (utils/Address.sol) pragma solidity ^0.8.20; import {Errors} from "./Errors.sol"; /** * @dev Collection of functions related to the address type */ library Address { /** * @dev There's no code at `target` (it is not a contract). */ error AddressEmptyCode(address target); /** * @dev Replacement for Solidity's `transfer`: sends `amount` wei to * `recipient`, forwarding all available gas and reverting on errors. * * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost * of certain opcodes, possibly making contracts go over the 2300 gas limit * imposed by `transfer`, making them unable to receive funds via * `transfer`. {sendValue} removes this limitation. * * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more]. * * IMPORTANT: because control is transferred to `recipient`, care must be * taken to not create reentrancy vulnerabilities. Consider using * {ReentrancyGuard} or the * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { if (address(this).balance < amount) { revert Errors.InsufficientBalance(address(this).balance, amount); } (bool success, bytes memory returndata) = recipient.call{value: amount}(""); if (!success) { _revert(returndata); } } /** * @dev Performs a Solidity function call using a low level `call`. A * plain `call` is an unsafe replacement for a function call: use this * function instead. * * If `target` reverts with a revert reason or custom error, it is bubbled * up by this function (like regular Solidity function calls). However, if * the call reverted with no returned reason, this function reverts with a * {Errors.FailedCall} error. * * Returns the raw returned data. To convert to the expected return value, * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`]. * * Requirements: * * - `target` must be a contract. * - calling `target` with `data` must not revert. */ function functionCall(address target, bytes memory data) internal returns (bytes memory) { return functionCallWithValue(target, data, 0); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but also transferring `value` wei to `target`. * * Requirements: * * - the calling contract must have an ETH balance of at least `value`. * - the called Solidity function must be `payable`. */ function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) { if (address(this).balance < value) { revert Errors.InsufficientBalance(address(this).balance, value); } (bool success, bytes memory returndata) = target.call{value: value}(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a static call. */ function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) { (bool success, bytes memory returndata) = target.staticcall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], * but performing a delegate call. */ function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) { (bool success, bytes memory returndata) = target.delegatecall(data); return verifyCallResultFromTarget(target, success, returndata); } /** * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target * was not a contract or bubbling up the revert reason (falling back to {Errors.FailedCall}) in case * of an unsuccessful call. */ function verifyCallResultFromTarget( address target, bool success, bytes memory returndata ) internal view returns (bytes memory) { if (!success) { _revert(returndata); } else { // only check if target is a contract if the call was successful and the return data is empty // otherwise we already know that it was a contract if (returndata.length == 0 && target.code.length == 0) { revert AddressEmptyCode(target); } return returndata; } } /** * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the * revert reason or with a default {Errors.FailedCall} error. */ function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) { if (!success) { _revert(returndata); } else { return returndata; } } /** * @dev Reverts with returndata if present. Otherwise reverts with {Errors.FailedCall}. */ function _revert(bytes memory returndata) private pure { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly assembly ("memory-safe") { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert Errors.FailedCall(); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol) pragma solidity ^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. */ abstract contract Context { function _msgSender() internal view virtual returns (address) { return msg.sender; } function _msgData() internal view virtual returns (bytes calldata) { return msg.data; } function _contextSuffixLength() internal view virtual returns (uint256) { return 0; } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/Create2.sol) pragma solidity ^0.8.20; import {Errors} from "./Errors.sol"; /** * @dev Helper to make usage of the `CREATE2` EVM opcode easier and safer. * `CREATE2` can be used to compute in advance the address where a smart * contract will be deployed, which allows for interesting new mechanisms known * as 'counterfactual interactions'. * * See the https://eips.ethereum.org/EIPS/eip-1014#motivation[EIP] for more * information. */ library Create2 { /** * @dev There's no code to deploy. */ error Create2EmptyBytecode(); /** * @dev Deploys a contract using `CREATE2`. The address where the contract * will be deployed can be known in advance via {computeAddress}. * * The bytecode for a contract can be obtained from Solidity with * `type(contractName).creationCode`. * * Requirements: * * - `bytecode` must not be empty. * - `salt` must have not been used for `bytecode` already. * - the factory must have a balance of at least `amount`. * - if `amount` is non-zero, `bytecode` must have a `payable` constructor. */ function deploy(uint256 amount, bytes32 salt, bytes memory bytecode) internal returns (address addr) { if (address(this).balance < amount) { revert Errors.InsufficientBalance(address(this).balance, amount); } if (bytecode.length == 0) { revert Create2EmptyBytecode(); } assembly ("memory-safe") { addr := create2(amount, add(bytecode, 0x20), mload(bytecode), salt) // if no address was created, and returndata is not empty, bubble revert if and(iszero(addr), not(iszero(returndatasize()))) { let p := mload(0x40) returndatacopy(p, 0, returndatasize()) revert(p, returndatasize()) } } if (addr == address(0)) { revert Errors.FailedDeployment(); } } /** * @dev Returns the address where a contract will be stored if deployed via {deploy}. Any change in the * `bytecodeHash` or `salt` will result in a new destination address. */ function computeAddress(bytes32 salt, bytes32 bytecodeHash) internal view returns (address) { return computeAddress(salt, bytecodeHash, address(this)); } /** * @dev Returns the address where a contract will be stored if deployed via {deploy} from a contract located at * `deployer`. If `deployer` is this contract's address, returns the same value as {computeAddress}. */ function computeAddress(bytes32 salt, bytes32 bytecodeHash, address deployer) internal pure returns (address addr) { assembly ("memory-safe") { let ptr := mload(0x40) // Get free memory pointer // | | ? ptr ... ? ptr + 0x0B (start) ... ? ptr + 0x20 ... ? ptr + 0x40 ... | // |-------------------|---------------------------------------------------------------------------| // | bytecodeHash | CCCCCCCCCCCCC...CC | // | salt | BBBBBBBBBBBBB...BB | // | deployer | 000000...0000AAAAAAAAAAAAAAAAAAA...AA | // | 0xFF | FF | // |-------------------|---------------------------------------------------------------------------| // | memory | 000000...00FFAAAAAAAAAAAAAAAAAAA...AABBBBBBBBBBBBB...BBCCCCCCCCCCCCC...CC | // | keccak(start, 85) | ?????????????????????????????????????????????????????????????? | mstore(add(ptr, 0x40), bytecodeHash) mstore(add(ptr, 0x20), salt) mstore(ptr, deployer) // Right-aligned with 12 preceding garbage bytes let start := add(ptr, 0x0b) // The hashed data starts at the final garbage byte which we will set to 0xff mstore8(start, 0xff) addr := and(keccak256(start, 85), 0xffffffffffffffffffffffffffffffffffffffff) } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/Errors.sol) pragma solidity ^0.8.20; /** * @dev Collection of common custom errors used in multiple contracts * * IMPORTANT: Backwards compatibility is not guaranteed in future versions of the library. * It is recommended to avoid relying on the error API for critical functionality. * * _Available since v5.1._ */ library Errors { /** * @dev The ETH balance of the account is not enough to perform the operation. */ error InsufficientBalance(uint256 balance, uint256 needed); /** * @dev A call to an address target failed. The target may have reverted. */ error FailedCall(); /** * @dev The deployment failed. */ error FailedDeployment(); /** * @dev A necessary precompile is missing. */ error MissingPrecompile(address); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/StorageSlot.sol) // This file was procedurally generated from scripts/generate/templates/StorageSlot.js. pragma solidity ^0.8.20; /** * @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; * } * } * ``` * * TIP: Consider using this library along with {SlotDerivation}. */ library StorageSlot { struct AddressSlot { address value; } struct BooleanSlot { bool value; } struct Bytes32Slot { bytes32 value; } struct Uint256Slot { uint256 value; } struct Int256Slot { int256 value; } struct StringSlot { string value; } struct BytesSlot { bytes value; } /** * @dev Returns an `AddressSlot` with member `value` located at `slot`. */ function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) { assembly ("memory-safe") { r.slot := slot } } /** * @dev Returns a `BooleanSlot` with member `value` located at `slot`. */ function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) { assembly ("memory-safe") { r.slot := slot } } /** * @dev Returns a `Bytes32Slot` with member `value` located at `slot`. */ function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) { assembly ("memory-safe") { r.slot := slot } } /** * @dev Returns a `Uint256Slot` with member `value` located at `slot`. */ function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) { assembly ("memory-safe") { r.slot := slot } } /** * @dev Returns a `Int256Slot` with member `value` located at `slot`. */ function getInt256Slot(bytes32 slot) internal pure returns (Int256Slot storage r) { assembly ("memory-safe") { r.slot := slot } } /** * @dev Returns a `StringSlot` with member `value` located at `slot`. */ function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) { assembly ("memory-safe") { r.slot := slot } } /** * @dev Returns an `StringSlot` representation of the string storage pointer `store`. */ function getStringSlot(string storage store) internal pure returns (StringSlot storage r) { assembly ("memory-safe") { r.slot := store.slot } } /** * @dev Returns a `BytesSlot` with member `value` located at `slot`. */ function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) { assembly ("memory-safe") { r.slot := slot } } /** * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`. */ function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) { assembly ("memory-safe") { r.slot := store.slot } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/introspection/IERC165.sol) pragma solidity ^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}. */ interface IERC165 { /** * @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. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v5.1.0) (utils/math/SafeCast.sol) // This file was procedurally generated from scripts/generate/templates/SafeCast.js. pragma solidity ^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. */ library SafeCast { /** * @dev Value doesn't fit in an uint of `bits` size. */ error SafeCastOverflowedUintDowncast(uint8 bits, uint256 value); /** * @dev An int value doesn't fit in an uint of `bits` size. */ error SafeCastOverflowedIntToUint(int256 value); /** * @dev Value doesn't fit in an int of `bits` size. */ error SafeCastOverflowedIntDowncast(uint8 bits, int256 value); /** * @dev An uint value doesn't fit in an int of `bits` size. */ error SafeCastOverflowedUintToInt(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 */ function toUint248(uint256 value) internal pure returns (uint248) { if (value > type(uint248).max) { revert SafeCastOverflowedUintDowncast(248, value); } return uint248(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 */ function toUint240(uint256 value) internal pure returns (uint240) { if (value > type(uint240).max) { revert SafeCastOverflowedUintDowncast(240, value); } return uint240(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 */ function toUint232(uint256 value) internal pure returns (uint232) { if (value > type(uint232).max) { revert SafeCastOverflowedUintDowncast(232, value); } return uint232(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 */ function toUint224(uint256 value) internal pure returns (uint224) { if (value > type(uint224).max) { revert SafeCastOverflowedUintDowncast(224, value); } return uint224(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 */ function toUint216(uint256 value) internal pure returns (uint216) { if (value > type(uint216).max) { revert SafeCastOverflowedUintDowncast(216, value); } return uint216(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 */ function toUint208(uint256 value) internal pure returns (uint208) { if (value > type(uint208).max) { revert SafeCastOverflowedUintDowncast(208, value); } return uint208(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 */ function toUint200(uint256 value) internal pure returns (uint200) { if (value > type(uint200).max) { revert SafeCastOverflowedUintDowncast(200, value); } return uint200(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 */ function toUint192(uint256 value) internal pure returns (uint192) { if (value > type(uint192).max) { revert SafeCastOverflowedUintDowncast(192, value); } return uint192(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 */ function toUint184(uint256 value) internal pure returns (uint184) { if (value > type(uint184).max) { revert SafeCastOverflowedUintDowncast(184, value); } return uint184(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 */ function toUint176(uint256 value) internal pure returns (uint176) { if (value > type(uint176).max) { revert SafeCastOverflowedUintDowncast(176, value); } return uint176(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 */ function toUint168(uint256 value) internal pure returns (uint168) { if (value > type(uint168).max) { revert SafeCastOverflowedUintDowncast(168, value); } return uint168(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 */ function toUint160(uint256 value) internal pure returns (uint160) { if (value > type(uint160).max) { revert SafeCastOverflowedUintDowncast(160, value); } return uint160(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 */ function toUint152(uint256 value) internal pure returns (uint152) { if (value > type(uint152).max) { revert SafeCastOverflowedUintDowncast(152, value); } return uint152(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 */ function toUint144(uint256 value) internal pure returns (uint144) { if (value > type(uint144).max) { revert SafeCastOverflowedUintDowncast(144, value); } return uint144(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 */ function toUint136(uint256 value) internal pure returns (uint136) { if (value > type(uint136).max) { revert SafeCastOverflowedUintDowncast(136, value); } return uint136(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 */ function toUint128(uint256 value) internal pure returns (uint128) { if (value > type(uint128).max) { revert SafeCastOverflowedUintDowncast(128, value); } return uint128(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 */ function toUint120(uint256 value) internal pure returns (uint120) { if (value > type(uint120).max) { revert SafeCastOverflowedUintDowncast(120, value); } return uint120(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 */ function toUint112(uint256 value) internal pure returns (uint112) { if (value > type(uint112).max) { revert SafeCastOverflowedUintDowncast(112, value); } return uint112(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 */ function toUint104(uint256 value) internal pure returns (uint104) { if (value > type(uint104).max) { revert SafeCastOverflowedUintDowncast(104, value); } return uint104(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 */ function toUint96(uint256 value) internal pure returns (uint96) { if (value > type(uint96).max) { revert SafeCastOverflowedUintDowncast(96, value); } return uint96(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 */ function toUint88(uint256 value) internal pure returns (uint88) { if (value > type(uint88).max) { revert SafeCastOverflowedUintDowncast(88, value); } return uint88(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 */ function toUint80(uint256 value) internal pure returns (uint80) { if (value > type(uint80).max) { revert SafeCastOverflowedUintDowncast(80, value); } return uint80(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 */ function toUint72(uint256 value) internal pure returns (uint72) { if (value > type(uint72).max) { revert SafeCastOverflowedUintDowncast(72, value); } return uint72(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 */ function toUint64(uint256 value) internal pure returns (uint64) { if (value > type(uint64).max) { revert SafeCastOverflowedUintDowncast(64, value); } return uint64(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 */ function toUint56(uint256 value) internal pure returns (uint56) { if (value > type(uint56).max) { revert SafeCastOverflowedUintDowncast(56, value); } return uint56(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 */ function toUint48(uint256 value) internal pure returns (uint48) { if (value > type(uint48).max) { revert SafeCastOverflowedUintDowncast(48, value); } return uint48(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 */ function toUint40(uint256 value) internal pure returns (uint40) { if (value > type(uint40).max) { revert SafeCastOverflowedUintDowncast(40, value); } return uint40(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 */ function toUint32(uint256 value) internal pure returns (uint32) { if (value > type(uint32).max) { revert SafeCastOverflowedUintDowncast(32, value); } return uint32(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 */ function toUint24(uint256 value) internal pure returns (uint24) { if (value > type(uint24).max) { revert SafeCastOverflowedUintDowncast(24, value); } return uint24(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 */ function toUint16(uint256 value) internal pure returns (uint16) { if (value > type(uint16).max) { revert SafeCastOverflowedUintDowncast(16, value); } return uint16(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 */ function toUint8(uint256 value) internal pure returns (uint8) { if (value > type(uint8).max) { revert SafeCastOverflowedUintDowncast(8, value); } return uint8(value); } /** * @dev Converts a signed int256 into an unsigned uint256. * * Requirements: * * - input must be greater than or equal to 0. */ function toUint256(int256 value) internal pure returns (uint256) { if (value < 0) { revert SafeCastOverflowedIntToUint(value); } return uint256(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 */ function toInt248(int256 value) internal pure returns (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 */ function toInt240(int256 value) internal pure returns (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 */ function toInt232(int256 value) internal pure returns (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 */ function toInt224(int256 value) internal pure returns (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 */ function toInt216(int256 value) internal pure returns (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 */ function toInt208(int256 value) internal pure returns (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 */ function toInt200(int256 value) internal pure returns (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 */ function toInt192(int256 value) internal pure returns (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 */ function toInt184(int256 value) internal pure returns (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 */ function toInt176(int256 value) internal pure returns (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 */ function toInt168(int256 value) internal pure returns (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 */ function toInt160(int256 value) internal pure returns (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 */ function toInt152(int256 value) internal pure returns (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 */ function toInt144(int256 value) internal pure returns (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 */ function toInt136(int256 value) internal pure returns (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 */ function toInt128(int256 value) internal pure returns (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 */ function toInt120(int256 value) internal pure returns (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 */ function toInt112(int256 value) internal pure returns (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 */ function toInt104(int256 value) internal pure returns (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 */ function toInt96(int256 value) internal pure returns (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 */ function toInt88(int256 value) internal pure returns (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 */ function toInt80(int256 value) internal pure returns (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 */ function toInt72(int256 value) internal pure returns (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 */ function toInt64(int256 value) internal pure returns (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 */ function toInt56(int256 value) internal pure returns (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 */ function toInt48(int256 value) internal pure returns (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 */ function toInt40(int256 value) internal pure returns (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 */ function toInt32(int256 value) internal pure returns (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 */ function toInt24(int256 value) internal pure returns (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 */ function toInt16(int256 value) internal pure returns (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 */ function toInt8(int256 value) internal pure returns (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. */ function toInt256(uint256 value) internal pure returns (int256) { // Note: Unsafe cast below is okay because `type(int256).max` is guaranteed to be positive if (value > uint256(type(int256).max)) { revert SafeCastOverflowedUintToInt(value); } return int256(value); } /** * @dev Cast a boolean (false or true) to a uint256 (0 or 1) with no jump. */ function toUint(bool b) internal pure returns (uint256 u) { assembly ("memory-safe") { u := iszero(iszero(b)) } } }
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.28; error InvalidFee(); error InvalidToken(); error OnlyDistributor();
// SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8.28; import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; import {Clones} from "@openzeppelin/contracts/proxy/Clones.sol"; import {Distributor} from "merkl-contracts/contracts/Distributor.sol"; import {UnKat} from "./UnKat.sol"; import "./Errors.sol"; contract UnKatFactory is Ownable { uint256 public constant MAX_FEE = 2000; //20% max (in BPS) uint256 public constant MAX_REF_FEE = 500; //5% max (in BPS) event ReferralFeeSet(address indexed referral, uint256 fee); event FeeSet(uint256 fee); event WrappedKat(address indexed target, bool isWrapped); ERC20 public immutable kat; UnKat public immutable unKat; uint256 private opsFee; mapping(address => uint256) public referrals; mapping(address => bool) public isWrappedKat; /// @notice constructor /// @param _kat Address of the kat token /// @param _merklDistributor Address of the Merkl distributor /// @param _opsFee Initial ops fee share constructor(address _kat, address _merklDistributor, uint256 _opsFee) Ownable(msg.sender) { kat = ERC20(_kat); unKat = new UnKat(_kat, _merklDistributor); require(_opsFee <= MAX_FEE, InvalidFee()); opsFee = _opsFee; } /// @notice Set fee share for a referral address /// @param _referral Address of the referral /// @param _fee Fee rate for the referral function setReferral(address _referral, uint256 _fee) external onlyOwner { require(_fee <= MAX_REF_FEE, InvalidFee()); referrals[_referral] = _fee; emit ReferralFeeSet(_referral, _fee); } /// @notice Set the fee for the protocol, cannot be greater than 15% nor smaller than 5% /// @param _opsFee Ops fee share, referral will be deducted from it function setOpsFee(uint256 _opsFee) external onlyOwner { require(_opsFee >= MAX_REF_FEE && _opsFee <= MAX_FEE, InvalidFee()); opsFee = _opsFee; emit FeeSet(_opsFee); } /// @notice Add a contract as wrapped kat /// @param target address to add/remove /// @param _isWrapped true to add to the wrapped mapping, false to remove function setIsWrappedKat(address target, bool _isWrapped) external onlyOwner { isWrappedKat[target] = _isWrapped; emit WrappedKat(target, _isWrapped); } /// @notice Get the fees for the protocol /// @return Ops Fee and referral fee of the protocol in BPS function getFees(address _referral) external view returns (uint256, uint256) { uint256 referralFee = referrals[_referral]; uint256 _opsFee = opsFee; return (_opsFee - referralFee, referralFee); } }
{ "evmVersion": "prague", "metadata": { "appendCBOR": true, "bytecodeHash": "ipfs", "useLiteralContent": false }, "optimizer": { "enabled": false, "runs": 200 }, "outputSelection": { "*": { "*": [ "evm.bytecode", "evm.deployedBytecode", "abi" ] } }, "remappings": [ "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/", "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/", "forge-std/=lib/forge-std/src/", "halmos-cheatcodes/=lib/openzeppelin-contracts/lib/halmos-cheatcodes/src/", "openzeppelin-contracts/=lib/openzeppelin-contracts/", "@utils/=lib/merkl-contracts/node_modules/utils/src/", "merkl-contracts/=lib/merkl-contracts/", "oz/=lib/openzeppelin-contracts/contracts/", "@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/", "openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/" ], "viaIR": false }
Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"_kat","type":"address"},{"internalType":"address","name":"_distributor","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"allowance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"ERC20InsufficientAllowance","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"},{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"uint256","name":"needed","type":"uint256"}],"name":"ERC20InsufficientBalance","type":"error"},{"inputs":[{"internalType":"address","name":"approver","type":"address"}],"name":"ERC20InvalidApprover","type":"error"},{"inputs":[{"internalType":"address","name":"receiver","type":"address"}],"name":"ERC20InvalidReceiver","type":"error"},{"inputs":[{"internalType":"address","name":"sender","type":"address"}],"name":"ERC20InvalidSender","type":"error"},{"inputs":[{"internalType":"address","name":"spender","type":"address"}],"name":"ERC20InvalidSpender","type":"error"},{"inputs":[],"name":"InvalidToken","type":"error"},{"inputs":[],"name":"OnlyDistributor","type":"error"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"SafeERC20FailedOperation","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"CALLBACK_SUCCESS","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"distributor","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"factory","outputs":[{"internalType":"contract UnKatFactory","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"kat","outputs":[{"internalType":"contract ERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"user","type":"address"},{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"onClaim","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"redeem","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"}]
Contract Creation Code
60e060405234801561000f575f5ffd5b506040516120f53803806120f5833981810160405281019061003191906101c0565b6040518060400160405280600c81526020017f756e6c6f636b6564204b617400000000000000000000000000000000000000008152506040518060400160405280600581526020017f756e4b617400000000000000000000000000000000000000000000000000000081525081600390816100ac919061043b565b5080600490816100bc919061043b565b5050503373ffffffffffffffffffffffffffffffffffffffff1660808173ffffffffffffffffffffffffffffffffffffffff16815250508173ffffffffffffffffffffffffffffffffffffffff1660c08173ffffffffffffffffffffffffffffffffffffffff16815250508073ffffffffffffffffffffffffffffffffffffffff1660a08173ffffffffffffffffffffffffffffffffffffffff1681525050505061050a565b5f5ffd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f61018f82610166565b9050919050565b61019f81610185565b81146101a9575f5ffd5b50565b5f815190506101ba81610196565b92915050565b5f5f604083850312156101d6576101d5610162565b5b5f6101e3858286016101ac565b92505060206101f4858286016101ac565b9150509250929050565b5f81519050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f600282049050600182168061027957607f821691505b60208210810361028c5761028b610235565b5b50919050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f600883026102ee7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff826102b3565b6102f886836102b3565b95508019841693508086168417925050509392505050565b5f819050919050565b5f819050919050565b5f61033c61033761033284610310565b610319565b610310565b9050919050565b5f819050919050565b61035583610322565b61036961036182610343565b8484546102bf565b825550505050565b5f5f905090565b610380610371565b61038b81848461034c565b505050565b5b818110156103ae576103a35f82610378565b600181019050610391565b5050565b601f8211156103f3576103c481610292565b6103cd846102a4565b810160208510156103dc578190505b6103f06103e8856102a4565b830182610390565b50505b505050565b5f82821c905092915050565b5f6104135f19846008026103f8565b1980831691505092915050565b5f61042b8383610404565b9150826002028217905092915050565b610444826101fe565b67ffffffffffffffff81111561045d5761045c610208565b5b6104678254610262565b6104728282856103b2565b5f60209050601f8311600181146104a3575f8415610491578287015190505b61049b8582610420565b865550610502565b601f1984166104b186610292565b5f5b828110156104d8578489015182556001820191506020850194506020810190506104b3565b868310156104f557848901516104f1601f891682610404565b8355505b6001600288020188555050505b505050505050565b60805160a05160c051611b906105655f395f818161049c015281816105ea01528181610838015261088101525f818161041701526107e101525f81816104f10152818161080501528181610ac50152610b9b0152611b905ff3fe608060405234801561000f575f5ffd5b50600436106100f3575f3560e01c80638237e53811610095578063c45a015511610064578063c45a01551461029b578063db006a75146102b9578063dc7feb26146102d5578063dd62ed3e146102f3576100f3565b80638237e5381461021157806395d89b411461022f578063a9059cbb1461024d578063bfe109281461027d576100f3565b806323b872dd116100d157806323b872dd14610163578063313ce567146101935780635f20da2d146101b157806370a08231146101e1576100f3565b806306fdde03146100f7578063095ea7b31461011557806318160ddd14610145575b5f5ffd5b6100ff610323565b60405161010c91906112d8565b60405180910390f35b61012f600480360381019061012a9190611396565b6103b3565b60405161013c91906113ee565b60405180910390f35b61014d6103d5565b60405161015a9190611416565b60405180910390f35b61017d6004803603810190610178919061142f565b6103de565b60405161018a91906113ee565b60405180910390f35b61019b61040c565b6040516101a8919061149a565b60405180910390f35b6101cb60048036038101906101c691906115df565b610414565b6040516101d89190611677565b60405180910390f35b6101fb60048036038101906101f69190611690565b6106c4565b6040516102089190611416565b60405180910390f35b610219610709565b6040516102269190611677565b60405180910390f35b61023761072d565b60405161024491906112d8565b60405180910390f35b61026760048036038101906102629190611396565b6107bd565b60405161027491906113ee565b60405180910390f35b6102856107df565b60405161029291906116ca565b60405180910390f35b6102a3610803565b6040516102b0919061173e565b60405180910390f35b6102d360048036038101906102ce9190611757565b610827565b005b6102dd61087f565b6040516102ea91906117a2565b60405180910390f35b61030d600480360381019061030891906117bb565b6108a3565b60405161031a9190611416565b60405180910390f35b60606003805461033290611826565b80601f016020809104026020016040519081016040528092919081815260200182805461035e90611826565b80156103a95780601f10610380576101008083540402835291602001916103a9565b820191905f5260205f20905b81548152906001019060200180831161038c57829003601f168201915b5050505050905090565b5f5f6103bd610925565b90506103ca81858561092c565b600191505092915050565b5f600254905090565b5f5f6103e8610925565b90506103f585828561093e565b6104008585856109d1565b60019150509392505050565b5f6012905090565b5f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461049a576040517f1b8f6df300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16148061058857507f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166345f87227856040518263ffffffff1660e01b815260040161054891906116ca565b602060405180830381865afa158015610563573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105879190611880565b5b6105be576040517fc1ab6dc100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f60208351036105df57828060200190518101906105dc91906118e6565b90505b5f6105e86103d5565b7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b815260040161064191906116ca565b602060405180830381865afa15801561065c573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106809190611925565b61068a919061197d565b9050610697878284610ac1565b7f41263d2f619e70e9cb211899844b4cf7322f9939361a152780541ef1d2031cb692505050949350505050565b5f5f5f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20549050919050565b7f41263d2f619e70e9cb211899844b4cf7322f9939361a152780541ef1d2031cb681565b60606004805461073c90611826565b80601f016020809104026020016040519081016040528092919081815260200182805461076890611826565b80156107b35780601f1061078a576101008083540402835291602001916107b3565b820191905f5260205f20905b81548152906001019060200180831161079657829003601f168201915b5050505050905090565b5f5f6107c7610925565b90506107d48185856109d1565b600191505092915050565b7f000000000000000000000000000000000000000000000000000000000000000081565b7f000000000000000000000000000000000000000000000000000000000000000081565b6108313382610c68565b61087c33827f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16610ce79092919063ffffffff16565b50565b7f000000000000000000000000000000000000000000000000000000000000000081565b5f60015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054905092915050565b5f33905090565b6109398383836001610d66565b505050565b5f61094984846108a3565b90507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8110156109cb57818110156109bc578281836040517ffb8f41b20000000000000000000000000000000000000000000000000000000081526004016109b3939291906119b0565b60405180910390fd5b6109ca84848484035f610d66565b5b50505050565b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610a41575f6040517f96c6fd1e000000000000000000000000000000000000000000000000000000008152600401610a3891906116ca565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610ab1575f6040517fec442f05000000000000000000000000000000000000000000000000000000008152600401610aa891906116ca565b60405180910390fd5b610abc838383610f35565b505050565b5f5f7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16639af608c9846040518263ffffffff1660e01b8152600401610b1c91906116ca565b6040805180830381865afa158015610b36573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b5a91906119e5565b915091505f6127108386610b6e9190611a23565b610b789190611a91565b90505f6127108387610b8a9190611a23565b610b949190611a91565b9050610c2c7f000000000000000000000000000000000000000000000000000000000000000073ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c02573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c269190611ad5565b8361114e565b610c4c87828489610c3d919061197d565b610c47919061197d565b61114e565b5f811115610c5f57610c5e858261114e565b5b50505050505050565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610cd8575f6040517f96c6fd1e000000000000000000000000000000000000000000000000000000008152600401610ccf91906116ca565b60405180910390fd5b610ce3825f83610f35565b5050565b610d61838473ffffffffffffffffffffffffffffffffffffffff1663a9059cbb8585604051602401610d1a929190611b00565b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506111cd565b505050565b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603610dd6575f6040517fe602df05000000000000000000000000000000000000000000000000000000008152600401610dcd91906116ca565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610e46575f6040517f94280d62000000000000000000000000000000000000000000000000000000008152600401610e3d91906116ca565b60405180910390fd5b8160015f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055508015610f2f578273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92584604051610f269190611416565b60405180910390a35b50505050565b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610f85578060025f828254610f799190611b27565b92505081905550611053565b5f5f5f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205490508181101561100e578381836040517fe450d38c000000000000000000000000000000000000000000000000000000008152600401611005939291906119b0565b60405180910390fd5b8181035f5f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2081905550505b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160361109a578060025f82825403925050819055506110e4565b805f5f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825401925050819055505b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040516111419190611416565b60405180910390a3505050565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036111be575f6040517fec442f050000000000000000000000000000000000000000000000000000000081526004016111b591906116ca565b60405180910390fd5b6111c95f8383610f35565b5050565b5f5f60205f8451602086015f885af1806111ec576040513d5f823e3d81fd5b3d92505f519150505f8214611205576001811415611220565b5f8473ffffffffffffffffffffffffffffffffffffffff163b145b1561126257836040517f5274afe700000000000000000000000000000000000000000000000000000000815260040161125991906116ca565b60405180910390fd5b50505050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f6112aa82611268565b6112b48185611272565b93506112c4818560208601611282565b6112cd81611290565b840191505092915050565b5f6020820190508181035f8301526112f081846112a0565b905092915050565b5f604051905090565b5f5ffd5b5f5ffd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f61133282611309565b9050919050565b61134281611328565b811461134c575f5ffd5b50565b5f8135905061135d81611339565b92915050565b5f819050919050565b61137581611363565b811461137f575f5ffd5b50565b5f813590506113908161136c565b92915050565b5f5f604083850312156113ac576113ab611301565b5b5f6113b98582860161134f565b92505060206113ca85828601611382565b9150509250929050565b5f8115159050919050565b6113e8816113d4565b82525050565b5f6020820190506114015f8301846113df565b92915050565b61141081611363565b82525050565b5f6020820190506114295f830184611407565b92915050565b5f5f5f6060848603121561144657611445611301565b5b5f6114538682870161134f565b93505060206114648682870161134f565b925050604061147586828701611382565b9150509250925092565b5f60ff82169050919050565b6114948161147f565b82525050565b5f6020820190506114ad5f83018461148b565b92915050565b5f5ffd5b5f5ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6114f182611290565b810181811067ffffffffffffffff821117156115105761150f6114bb565b5b80604052505050565b5f6115226112f8565b905061152e82826114e8565b919050565b5f67ffffffffffffffff82111561154d5761154c6114bb565b5b61155682611290565b9050602081019050919050565b828183375f83830152505050565b5f61158361157e84611533565b611519565b90508281526020810184848401111561159f5761159e6114b7565b5b6115aa848285611563565b509392505050565b5f82601f8301126115c6576115c56114b3565b5b81356115d6848260208601611571565b91505092915050565b5f5f5f5f608085870312156115f7576115f6611301565b5b5f6116048782880161134f565b94505060206116158782880161134f565b935050604061162687828801611382565b925050606085013567ffffffffffffffff81111561164757611646611305565b5b611653878288016115b2565b91505092959194509250565b5f819050919050565b6116718161165f565b82525050565b5f60208201905061168a5f830184611668565b92915050565b5f602082840312156116a5576116a4611301565b5b5f6116b28482850161134f565b91505092915050565b6116c481611328565b82525050565b5f6020820190506116dd5f8301846116bb565b92915050565b5f819050919050565b5f6117066117016116fc84611309565b6116e3565b611309565b9050919050565b5f611717826116ec565b9050919050565b5f6117288261170d565b9050919050565b6117388161171e565b82525050565b5f6020820190506117515f83018461172f565b92915050565b5f6020828403121561176c5761176b611301565b5b5f61177984828501611382565b91505092915050565b5f61178c8261170d565b9050919050565b61179c81611782565b82525050565b5f6020820190506117b55f830184611793565b92915050565b5f5f604083850312156117d1576117d0611301565b5b5f6117de8582860161134f565b92505060206117ef8582860161134f565b9150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f600282049050600182168061183d57607f821691505b6020821081036118505761184f6117f9565b5b50919050565b61185f816113d4565b8114611869575f5ffd5b50565b5f8151905061187a81611856565b92915050565b5f6020828403121561189557611894611301565b5b5f6118a28482850161186c565b91505092915050565b5f6118b582611309565b9050919050565b6118c5816118ab565b81146118cf575f5ffd5b50565b5f815190506118e0816118bc565b92915050565b5f602082840312156118fb576118fa611301565b5b5f611908848285016118d2565b91505092915050565b5f8151905061191f8161136c565b92915050565b5f6020828403121561193a57611939611301565b5b5f61194784828501611911565b91505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f61198782611363565b915061199283611363565b92508282039050818111156119aa576119a9611950565b5b92915050565b5f6060820190506119c35f8301866116bb565b6119d06020830185611407565b6119dd6040830184611407565b949350505050565b5f5f604083850312156119fb576119fa611301565b5b5f611a0885828601611911565b9250506020611a1985828601611911565b9150509250929050565b5f611a2d82611363565b9150611a3883611363565b9250828202611a4681611363565b91508282048414831517611a5d57611a5c611950565b5b5092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f611a9b82611363565b9150611aa683611363565b925082611ab657611ab5611a64565b5b828204905092915050565b5f81519050611acf81611339565b92915050565b5f60208284031215611aea57611ae9611301565b5b5f611af784828501611ac1565b91505092915050565b5f604082019050611b135f8301856116bb565b611b206020830184611407565b9392505050565b5f611b3182611363565b9150611b3c83611363565b9250828201905080821115611b5457611b53611950565b5b9291505056fea2646970667358221220c780866f2330c59bdac77bf8e1e12a2680728eb6b0e1494e7fc7edbbe72c6ef164736f6c634300081c00330000000000000000000000007f1f4b4b29f5058fa32cc7a97141b8d7e5abdc2d0000000000000000000000003ef3d8ba38ebe18db133cec108f4d14ce00dd9ae
Deployed Bytecode
0x608060405234801561000f575f5ffd5b50600436106100f3575f3560e01c80638237e53811610095578063c45a015511610064578063c45a01551461029b578063db006a75146102b9578063dc7feb26146102d5578063dd62ed3e146102f3576100f3565b80638237e5381461021157806395d89b411461022f578063a9059cbb1461024d578063bfe109281461027d576100f3565b806323b872dd116100d157806323b872dd14610163578063313ce567146101935780635f20da2d146101b157806370a08231146101e1576100f3565b806306fdde03146100f7578063095ea7b31461011557806318160ddd14610145575b5f5ffd5b6100ff610323565b60405161010c91906112d8565b60405180910390f35b61012f600480360381019061012a9190611396565b6103b3565b60405161013c91906113ee565b60405180910390f35b61014d6103d5565b60405161015a9190611416565b60405180910390f35b61017d6004803603810190610178919061142f565b6103de565b60405161018a91906113ee565b60405180910390f35b61019b61040c565b6040516101a8919061149a565b60405180910390f35b6101cb60048036038101906101c691906115df565b610414565b6040516101d89190611677565b60405180910390f35b6101fb60048036038101906101f69190611690565b6106c4565b6040516102089190611416565b60405180910390f35b610219610709565b6040516102269190611677565b60405180910390f35b61023761072d565b60405161024491906112d8565b60405180910390f35b61026760048036038101906102629190611396565b6107bd565b60405161027491906113ee565b60405180910390f35b6102856107df565b60405161029291906116ca565b60405180910390f35b6102a3610803565b6040516102b0919061173e565b60405180910390f35b6102d360048036038101906102ce9190611757565b610827565b005b6102dd61087f565b6040516102ea91906117a2565b60405180910390f35b61030d600480360381019061030891906117bb565b6108a3565b60405161031a9190611416565b60405180910390f35b60606003805461033290611826565b80601f016020809104026020016040519081016040528092919081815260200182805461035e90611826565b80156103a95780601f10610380576101008083540402835291602001916103a9565b820191905f5260205f20905b81548152906001019060200180831161038c57829003601f168201915b5050505050905090565b5f5f6103bd610925565b90506103ca81858561092c565b600191505092915050565b5f600254905090565b5f5f6103e8610925565b90506103f585828561093e565b6104008585856109d1565b60019150509392505050565b5f6012905090565b5f7f0000000000000000000000003ef3d8ba38ebe18db133cec108f4d14ce00dd9ae73ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff161461049a576040517f1b8f6df300000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b7f0000000000000000000000007f1f4b4b29f5058fa32cc7a97141b8d7e5abdc2d73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff16148061058857507f000000000000000000000000f2d70e8d9b77619f3c48376c7d66d4f727d0bfac73ffffffffffffffffffffffffffffffffffffffff166345f87227856040518263ffffffff1660e01b815260040161054891906116ca565b602060405180830381865afa158015610563573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105879190611880565b5b6105be576040517fc1ab6dc100000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b5f60208351036105df57828060200190518101906105dc91906118e6565b90505b5f6105e86103d5565b7f0000000000000000000000007f1f4b4b29f5058fa32cc7a97141b8d7e5abdc2d73ffffffffffffffffffffffffffffffffffffffff166370a08231306040518263ffffffff1660e01b815260040161064191906116ca565b602060405180830381865afa15801561065c573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906106809190611925565b61068a919061197d565b9050610697878284610ac1565b7f41263d2f619e70e9cb211899844b4cf7322f9939361a152780541ef1d2031cb692505050949350505050565b5f5f5f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20549050919050565b7f41263d2f619e70e9cb211899844b4cf7322f9939361a152780541ef1d2031cb681565b60606004805461073c90611826565b80601f016020809104026020016040519081016040528092919081815260200182805461076890611826565b80156107b35780601f1061078a576101008083540402835291602001916107b3565b820191905f5260205f20905b81548152906001019060200180831161079657829003601f168201915b5050505050905090565b5f5f6107c7610925565b90506107d48185856109d1565b600191505092915050565b7f0000000000000000000000003ef3d8ba38ebe18db133cec108f4d14ce00dd9ae81565b7f000000000000000000000000f2d70e8d9b77619f3c48376c7d66d4f727d0bfac81565b6108313382610c68565b61087c33827f0000000000000000000000007f1f4b4b29f5058fa32cc7a97141b8d7e5abdc2d73ffffffffffffffffffffffffffffffffffffffff16610ce79092919063ffffffff16565b50565b7f0000000000000000000000007f1f4b4b29f5058fa32cc7a97141b8d7e5abdc2d81565b5f60015f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054905092915050565b5f33905090565b6109398383836001610d66565b505050565b5f61094984846108a3565b90507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8110156109cb57818110156109bc578281836040517ffb8f41b20000000000000000000000000000000000000000000000000000000081526004016109b3939291906119b0565b60405180910390fd5b6109ca84848484035f610d66565b5b50505050565b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610a41575f6040517f96c6fd1e000000000000000000000000000000000000000000000000000000008152600401610a3891906116ca565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610ab1575f6040517fec442f05000000000000000000000000000000000000000000000000000000008152600401610aa891906116ca565b60405180910390fd5b610abc838383610f35565b505050565b5f5f7f000000000000000000000000f2d70e8d9b77619f3c48376c7d66d4f727d0bfac73ffffffffffffffffffffffffffffffffffffffff16639af608c9846040518263ffffffff1660e01b8152600401610b1c91906116ca565b6040805180830381865afa158015610b36573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610b5a91906119e5565b915091505f6127108386610b6e9190611a23565b610b789190611a91565b90505f6127108387610b8a9190611a23565b610b949190611a91565b9050610c2c7f000000000000000000000000f2d70e8d9b77619f3c48376c7d66d4f727d0bfac73ffffffffffffffffffffffffffffffffffffffff16638da5cb5b6040518163ffffffff1660e01b8152600401602060405180830381865afa158015610c02573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610c269190611ad5565b8361114e565b610c4c87828489610c3d919061197d565b610c47919061197d565b61114e565b5f811115610c5f57610c5e858261114e565b5b50505050505050565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff1603610cd8575f6040517f96c6fd1e000000000000000000000000000000000000000000000000000000008152600401610ccf91906116ca565b60405180910390fd5b610ce3825f83610f35565b5050565b610d61838473ffffffffffffffffffffffffffffffffffffffff1663a9059cbb8585604051602401610d1a929190611b00565b604051602081830303815290604052915060e01b6020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff83818316178352505050506111cd565b505050565b5f73ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff1603610dd6575f6040517fe602df05000000000000000000000000000000000000000000000000000000008152600401610dcd91906116ca565b60405180910390fd5b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610e46575f6040517f94280d62000000000000000000000000000000000000000000000000000000008152600401610e3d91906116ca565b60405180910390fd5b8160015f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055508015610f2f578273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92584604051610f269190611416565b60405180910390a35b50505050565b5f73ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff1603610f85578060025f828254610f799190611b27565b92505081905550611053565b5f5f5f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205490508181101561100e578381836040517fe450d38c000000000000000000000000000000000000000000000000000000008152600401611005939291906119b0565b60405180910390fd5b8181035f5f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2081905550505b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff160361109a578060025f82825403925050819055506110e4565b805f5f8473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825401925050819055505b8173ffffffffffffffffffffffffffffffffffffffff168373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef836040516111419190611416565b60405180910390a3505050565b5f73ffffffffffffffffffffffffffffffffffffffff168273ffffffffffffffffffffffffffffffffffffffff16036111be575f6040517fec442f050000000000000000000000000000000000000000000000000000000081526004016111b591906116ca565b60405180910390fd5b6111c95f8383610f35565b5050565b5f5f60205f8451602086015f885af1806111ec576040513d5f823e3d81fd5b3d92505f519150505f8214611205576001811415611220565b5f8473ffffffffffffffffffffffffffffffffffffffff163b145b1561126257836040517f5274afe700000000000000000000000000000000000000000000000000000000815260040161125991906116ca565b60405180910390fd5b50505050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f6112aa82611268565b6112b48185611272565b93506112c4818560208601611282565b6112cd81611290565b840191505092915050565b5f6020820190508181035f8301526112f081846112a0565b905092915050565b5f604051905090565b5f5ffd5b5f5ffd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f61133282611309565b9050919050565b61134281611328565b811461134c575f5ffd5b50565b5f8135905061135d81611339565b92915050565b5f819050919050565b61137581611363565b811461137f575f5ffd5b50565b5f813590506113908161136c565b92915050565b5f5f604083850312156113ac576113ab611301565b5b5f6113b98582860161134f565b92505060206113ca85828601611382565b9150509250929050565b5f8115159050919050565b6113e8816113d4565b82525050565b5f6020820190506114015f8301846113df565b92915050565b61141081611363565b82525050565b5f6020820190506114295f830184611407565b92915050565b5f5f5f6060848603121561144657611445611301565b5b5f6114538682870161134f565b93505060206114648682870161134f565b925050604061147586828701611382565b9150509250925092565b5f60ff82169050919050565b6114948161147f565b82525050565b5f6020820190506114ad5f83018461148b565b92915050565b5f5ffd5b5f5ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6114f182611290565b810181811067ffffffffffffffff821117156115105761150f6114bb565b5b80604052505050565b5f6115226112f8565b905061152e82826114e8565b919050565b5f67ffffffffffffffff82111561154d5761154c6114bb565b5b61155682611290565b9050602081019050919050565b828183375f83830152505050565b5f61158361157e84611533565b611519565b90508281526020810184848401111561159f5761159e6114b7565b5b6115aa848285611563565b509392505050565b5f82601f8301126115c6576115c56114b3565b5b81356115d6848260208601611571565b91505092915050565b5f5f5f5f608085870312156115f7576115f6611301565b5b5f6116048782880161134f565b94505060206116158782880161134f565b935050604061162687828801611382565b925050606085013567ffffffffffffffff81111561164757611646611305565b5b611653878288016115b2565b91505092959194509250565b5f819050919050565b6116718161165f565b82525050565b5f60208201905061168a5f830184611668565b92915050565b5f602082840312156116a5576116a4611301565b5b5f6116b28482850161134f565b91505092915050565b6116c481611328565b82525050565b5f6020820190506116dd5f8301846116bb565b92915050565b5f819050919050565b5f6117066117016116fc84611309565b6116e3565b611309565b9050919050565b5f611717826116ec565b9050919050565b5f6117288261170d565b9050919050565b6117388161171e565b82525050565b5f6020820190506117515f83018461172f565b92915050565b5f6020828403121561176c5761176b611301565b5b5f61177984828501611382565b91505092915050565b5f61178c8261170d565b9050919050565b61179c81611782565b82525050565b5f6020820190506117b55f830184611793565b92915050565b5f5f604083850312156117d1576117d0611301565b5b5f6117de8582860161134f565b92505060206117ef8582860161134f565b9150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f600282049050600182168061183d57607f821691505b6020821081036118505761184f6117f9565b5b50919050565b61185f816113d4565b8114611869575f5ffd5b50565b5f8151905061187a81611856565b92915050565b5f6020828403121561189557611894611301565b5b5f6118a28482850161186c565b91505092915050565b5f6118b582611309565b9050919050565b6118c5816118ab565b81146118cf575f5ffd5b50565b5f815190506118e0816118bc565b92915050565b5f602082840312156118fb576118fa611301565b5b5f611908848285016118d2565b91505092915050565b5f8151905061191f8161136c565b92915050565b5f6020828403121561193a57611939611301565b5b5f61194784828501611911565b91505092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f61198782611363565b915061199283611363565b92508282039050818111156119aa576119a9611950565b5b92915050565b5f6060820190506119c35f8301866116bb565b6119d06020830185611407565b6119dd6040830184611407565b949350505050565b5f5f604083850312156119fb576119fa611301565b5b5f611a0885828601611911565b9250506020611a1985828601611911565b9150509250929050565b5f611a2d82611363565b9150611a3883611363565b9250828202611a4681611363565b91508282048414831517611a5d57611a5c611950565b5b5092915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601260045260245ffd5b5f611a9b82611363565b9150611aa683611363565b925082611ab657611ab5611a64565b5b828204905092915050565b5f81519050611acf81611339565b92915050565b5f60208284031215611aea57611ae9611301565b5b5f611af784828501611ac1565b91505092915050565b5f604082019050611b135f8301856116bb565b611b206020830184611407565b9392505050565b5f611b3182611363565b9150611b3c83611363565b9250828201905080821115611b5457611b53611950565b5b9291505056fea2646970667358221220c780866f2330c59bdac77bf8e1e12a2680728eb6b0e1494e7fc7edbbe72c6ef164736f6c634300081c0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000007f1f4b4b29f5058fa32cc7a97141b8d7e5abdc2d0000000000000000000000003ef3d8ba38ebe18db133cec108f4d14ce00dd9ae
-----Decoded View---------------
Arg [0] : _kat (address): 0x7F1f4b4b29f5058fA32CC7a97141b8D7e5ABDC2d
Arg [1] : _distributor (address): 0x3Ef3D8bA38EBe18DB133cEc108f4D14CE00Dd9Ae
-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 0000000000000000000000007f1f4b4b29f5058fa32cc7a97141b8d7e5abdc2d
Arg [1] : 0000000000000000000000003ef3d8ba38ebe18db133cec108f4d14ce00dd9ae
Deployed Bytecode Sourcemap
290:2343:28:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1760:89:16;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;3979:186;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;2830:97;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;4757:244;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;2688:82;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;1069:595:28;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;2985:116:16;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;387:79:28;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;1962:93:16;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;3296:178;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;516:36:28;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;473:37;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;2502:129;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;558:26;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;3532:140:16;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;1760:89;1805:13;1837:5;1830:12;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1760:89;:::o;3979:186::-;4052:4;4068:13;4084:12;:10;:12::i;:::-;4068:28;;4106:31;4115:5;4122:7;4131:5;4106:8;:31::i;:::-;4154:4;4147:11;;;3979:186;;;;:::o;2830:97::-;2882:7;2908:12;;2901:19;;2830:97;:::o;4757:244::-;4844:4;4860:15;4878:12;:10;:12::i;:::-;4860:30;;4900:37;4916:4;4922:7;4931:5;4900:15;:37::i;:::-;4947:26;4957:4;4963:2;4967:5;4947:9;:26::i;:::-;4990:4;4983:11;;;4757:244;;;;;:::o;2688:82::-;2737:5;2761:2;2754:9;;2688:82;:::o;1069:595:28:-;1172:7;1213:11;1199:25;;:10;:25;;;1191:53;;;;;;;;;;;;;;;;;1279:3;1262:21;;:5;:21;;;:52;;;;1287:7;:20;;;1308:5;1287:27;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;1262:52;1254:77;;;;;;;;;;;;;;;;;1396:16;1441:2;1426:4;:11;:17;1422:86;;1481:4;1470:27;;;;;;;;;;;;:::i;:::-;1459:38;;1422:86;1518:14;1566:13;:11;:13::i;:::-;1535:3;:13;;;1557:4;1535:28;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;:44;;;;:::i;:::-;1518:61;;1589:34;1600:4;1606:6;1614:8;1589:10;:34::i;:::-;430:36;1634:23;;;;1069:595;;;;;;:::o;2985:116:16:-;3050:7;3076:9;:18;3086:7;3076:18;;;;;;;;;;;;;;;;3069:25;;2985:116;;;:::o;387:79:28:-;430:36;387:79;:::o;1962:93:16:-;2009:13;2041:7;2034:14;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1962:93;:::o;3296:178::-;3365:4;3381:13;3397:12;:10;:12::i;:::-;3381:28;;3419:27;3429:5;3436:2;3440:5;3419:9;:27::i;:::-;3463:4;3456:11;;;3296:178;;;;:::o;516:36:28:-;;;:::o;473:37::-;;;:::o;2502:129::-;2553:25;2559:10;2571:6;2553:5;:25::i;:::-;2588:36;2605:10;2617:6;2588:3;:16;;;;:36;;;;;:::i;:::-;2502:129;:::o;558:26::-;;;:::o;3532:140:16:-;3612:7;3638:11;:18;3650:5;3638:18;;;;;;;;;;;;;;;:27;3657:7;3638:27;;;;;;;;;;;;;;;;3631:34;;3532:140;;;;:::o;656:96:21:-;709:7;735:10;728:17;;656:96;:::o;8707:128:16:-;8791:37;8800:5;8807:7;8816:5;8823:4;8791:8;:37::i;:::-;8707:128;;;:::o;10396:476::-;10495:24;10522:25;10532:5;10539:7;10522:9;:25::i;:::-;10495:52;;10580:17;10561:16;:36;10557:309;;;10636:5;10617:16;:24;10613:130;;;10695:7;10704:16;10722:5;10668:60;;;;;;;;;;;;;:::i;:::-;;;;;;;;10613:130;10784:57;10793:5;10800:7;10828:5;10809:16;:24;10835:5;10784:8;:57::i;:::-;10557:309;10485:387;10396:476;;;:::o;5374:300::-;5473:1;5457:18;;:4;:18;;;5453:86;;5525:1;5498:30;;;;;;;;;;;:::i;:::-;;;;;;;;5453:86;5566:1;5552:16;;:2;:16;;;5548:86;;5620:1;5591:32;;;;;;;;;;;:::i;:::-;;;;;;;;5548:86;5643:24;5651:4;5657:2;5661:5;5643:7;:24::i;:::-;5374:300;;;:::o;1882:491:28:-;1974:14;1990:19;2013:7;:15;;;2029:8;2013:25;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;1973:65;;;;2048:20;375:6;2080;2071;:15;;;;:::i;:::-;:21;;;;:::i;:::-;2048:44;;2102:25;375:6;2139:11;2130:6;:20;;;;:::i;:::-;:26;;;;:::i;:::-;2102:54;;2167:36;2173:7;:13;;;:15;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;2190:12;2167:5;:36::i;:::-;2213:58;2219:8;2253:17;2238:12;2229:6;:21;;;;:::i;:::-;:41;;;;:::i;:::-;2213:5;:58::i;:::-;2305:1;2285:17;:21;2281:86;;;2322:34;2328:8;2338:17;2322:5;:34::i;:::-;2281:86;1963:410;;;;1882:491;;;:::o;7965:206:16:-;8054:1;8035:21;;:7;:21;;;8031:89;;8106:1;8079:30;;;;;;;;;;;:::i;:::-;;;;;;;;8031:89;8129:35;8137:7;8154:1;8158:5;8129:7;:35::i;:::-;7965:206;;:::o;1219:160:19:-;1301:71;1321:5;1343;:14;;;1360:2;1364:5;1328:43;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1301:19;:71::i;:::-;1219:160;;;:::o;9682:432:16:-;9811:1;9794:19;;:5;:19;;;9790:89;;9865:1;9836:32;;;;;;;;;;;:::i;:::-;;;;;;;;9790:89;9911:1;9892:21;;:7;:21;;;9888:90;;9964:1;9936:31;;;;;;;;;;;:::i;:::-;;;;;;;;9888:90;10017:5;9987:11;:18;9999:5;9987:18;;;;;;;;;;;;;;;:27;10006:7;9987:27;;;;;;;;;;;;;;;:35;;;;10036:9;10032:76;;;10082:7;10066:31;;10075:5;10066:31;;;10091:5;10066:31;;;;;;:::i;:::-;;;;;;;;10032:76;9682:432;;;;:::o;5989:1107::-;6094:1;6078:18;;:4;:18;;;6074:540;;6230:5;6214:12;;:21;;;;;;;:::i;:::-;;;;;;;;6074:540;;;6266:19;6288:9;:15;6298:4;6288:15;;;;;;;;;;;;;;;;6266:37;;6335:5;6321:11;:19;6317:115;;;6392:4;6398:11;6411:5;6367:50;;;;;;;;;;;;;:::i;:::-;;;;;;;;6317:115;6584:5;6570:11;:19;6552:9;:15;6562:4;6552:15;;;;;;;;;;;;;;;:37;;;;6252:362;6074:540;6642:1;6628:16;;:2;:16;;;6624:425;;6807:5;6791:12;;:21;;;;;;;;;;;6624:425;;;7019:5;7002:9;:13;7012:2;7002:13;;;;;;;;;;;;;;;;:22;;;;;;;;;;;6624:425;7079:2;7064:25;;7073:4;7064:25;;;7083:5;7064:25;;;;;;:::i;:::-;;;;;;;;5989:1107;;;:::o;7439:208::-;7528:1;7509:21;;:7;:21;;;7505:91;;7582:1;7553:32;;;;;;;;;;;:::i;:::-;;;;;;;;7505:91;7605:35;7621:1;7625:7;7634:5;7605:7;:35::i;:::-;7439:208;;:::o;8370:720:19:-;8450:18;8478:19;8616:4;8613:1;8606:4;8600:11;8593:4;8587;8583:15;8580:1;8573:5;8566;8561:60;8673:7;8663:176;;8717:4;8711:11;8762:16;8759:1;8754:3;8739:40;8808:16;8803:3;8796:29;8663:176;8866:16;8852:30;;8916:1;8910:8;8895:23;;8532:396;8956:1;8942:10;:15;:68;;9009:1;8994:11;:16;;8942:68;;;8990:1;8968:5;8960:26;;;:31;8942:68;8938:146;;;9066:5;9033:40;;;;;;;;;;;:::i;:::-;;;;;;;;8938:146;8440:650;;8370:720;;:::o;7:99:30:-;59:6;93:5;87:12;77:22;;7:99;;;:::o;112:169::-;196:11;230:6;225:3;218:19;270:4;265:3;261:14;246:29;;112:169;;;;:::o;287:139::-;376:6;371:3;366;360:23;417:1;408:6;403:3;399:16;392:27;287:139;;;:::o;432:102::-;473:6;524:2;520:7;515:2;508:5;504:14;500:28;490:38;;432:102;;;:::o;540:377::-;628:3;656:39;689:5;656:39;:::i;:::-;711:71;775:6;770:3;711:71;:::i;:::-;704:78;;791:65;849:6;844:3;837:4;830:5;826:16;791:65;:::i;:::-;881:29;903:6;881:29;:::i;:::-;876:3;872:39;865:46;;632:285;540:377;;;;:::o;923:313::-;1036:4;1074:2;1063:9;1059:18;1051:26;;1123:9;1117:4;1113:20;1109:1;1098:9;1094:17;1087:47;1151:78;1224:4;1215:6;1151:78;:::i;:::-;1143:86;;923:313;;;;:::o;1242:75::-;1275:6;1308:2;1302:9;1292:19;;1242:75;:::o;1323:117::-;1432:1;1429;1422:12;1446:117;1555:1;1552;1545:12;1569:126;1606:7;1646:42;1639:5;1635:54;1624:65;;1569:126;;;:::o;1701:96::-;1738:7;1767:24;1785:5;1767:24;:::i;:::-;1756:35;;1701:96;;;:::o;1803:122::-;1876:24;1894:5;1876:24;:::i;:::-;1869:5;1866:35;1856:63;;1915:1;1912;1905:12;1856:63;1803:122;:::o;1931:139::-;1977:5;2015:6;2002:20;1993:29;;2031:33;2058:5;2031:33;:::i;:::-;1931:139;;;;:::o;2076:77::-;2113:7;2142:5;2131:16;;2076:77;;;:::o;2159:122::-;2232:24;2250:5;2232:24;:::i;:::-;2225:5;2222:35;2212:63;;2271:1;2268;2261:12;2212:63;2159:122;:::o;2287:139::-;2333:5;2371:6;2358:20;2349:29;;2387:33;2414:5;2387:33;:::i;:::-;2287:139;;;;:::o;2432:474::-;2500:6;2508;2557:2;2545:9;2536:7;2532:23;2528:32;2525:119;;;2563:79;;:::i;:::-;2525:119;2683:1;2708:53;2753:7;2744:6;2733:9;2729:22;2708:53;:::i;:::-;2698:63;;2654:117;2810:2;2836:53;2881:7;2872:6;2861:9;2857:22;2836:53;:::i;:::-;2826:63;;2781:118;2432:474;;;;;:::o;2912:90::-;2946:7;2989:5;2982:13;2975:21;2964:32;;2912:90;;;:::o;3008:109::-;3089:21;3104:5;3089:21;:::i;:::-;3084:3;3077:34;3008:109;;:::o;3123:210::-;3210:4;3248:2;3237:9;3233:18;3225:26;;3261:65;3323:1;3312:9;3308:17;3299:6;3261:65;:::i;:::-;3123:210;;;;:::o;3339:118::-;3426:24;3444:5;3426:24;:::i;:::-;3421:3;3414:37;3339:118;;:::o;3463:222::-;3556:4;3594:2;3583:9;3579:18;3571:26;;3607:71;3675:1;3664:9;3660:17;3651:6;3607:71;:::i;:::-;3463:222;;;;:::o;3691:619::-;3768:6;3776;3784;3833:2;3821:9;3812:7;3808:23;3804:32;3801:119;;;3839:79;;:::i;:::-;3801:119;3959:1;3984:53;4029:7;4020:6;4009:9;4005:22;3984:53;:::i;:::-;3974:63;;3930:117;4086:2;4112:53;4157:7;4148:6;4137:9;4133:22;4112:53;:::i;:::-;4102:63;;4057:118;4214:2;4240:53;4285:7;4276:6;4265:9;4261:22;4240:53;:::i;:::-;4230:63;;4185:118;3691:619;;;;;:::o;4316:86::-;4351:7;4391:4;4384:5;4380:16;4369:27;;4316:86;;;:::o;4408:112::-;4491:22;4507:5;4491:22;:::i;:::-;4486:3;4479:35;4408:112;;:::o;4526:214::-;4615:4;4653:2;4642:9;4638:18;4630:26;;4666:67;4730:1;4719:9;4715:17;4706:6;4666:67;:::i;:::-;4526:214;;;;:::o;4746:117::-;4855:1;4852;4845:12;4869:117;4978:1;4975;4968:12;4992:180;5040:77;5037:1;5030:88;5137:4;5134:1;5127:15;5161:4;5158:1;5151:15;5178:281;5261:27;5283:4;5261:27;:::i;:::-;5253:6;5249:40;5391:6;5379:10;5376:22;5355:18;5343:10;5340:34;5337:62;5334:88;;;5402:18;;:::i;:::-;5334:88;5442:10;5438:2;5431:22;5221:238;5178:281;;:::o;5465:129::-;5499:6;5526:20;;:::i;:::-;5516:30;;5555:33;5583:4;5575:6;5555:33;:::i;:::-;5465:129;;;:::o;5600:307::-;5661:4;5751:18;5743:6;5740:30;5737:56;;;5773:18;;:::i;:::-;5737:56;5811:29;5833:6;5811:29;:::i;:::-;5803:37;;5895:4;5889;5885:15;5877:23;;5600:307;;;:::o;5913:148::-;6011:6;6006:3;6001;5988:30;6052:1;6043:6;6038:3;6034:16;6027:27;5913:148;;;:::o;6067:423::-;6144:5;6169:65;6185:48;6226:6;6185:48;:::i;:::-;6169:65;:::i;:::-;6160:74;;6257:6;6250:5;6243:21;6295:4;6288:5;6284:16;6333:3;6324:6;6319:3;6315:16;6312:25;6309:112;;;6340:79;;:::i;:::-;6309:112;6430:54;6477:6;6472:3;6467;6430:54;:::i;:::-;6150:340;6067:423;;;;;:::o;6509:338::-;6564:5;6613:3;6606:4;6598:6;6594:17;6590:27;6580:122;;6621:79;;:::i;:::-;6580:122;6738:6;6725:20;6763:78;6837:3;6829:6;6822:4;6814:6;6810:17;6763:78;:::i;:::-;6754:87;;6570:277;6509:338;;;;:::o;6853:943::-;6948:6;6956;6964;6972;7021:3;7009:9;7000:7;6996:23;6992:33;6989:120;;;7028:79;;:::i;:::-;6989:120;7148:1;7173:53;7218:7;7209:6;7198:9;7194:22;7173:53;:::i;:::-;7163:63;;7119:117;7275:2;7301:53;7346:7;7337:6;7326:9;7322:22;7301:53;:::i;:::-;7291:63;;7246:118;7403:2;7429:53;7474:7;7465:6;7454:9;7450:22;7429:53;:::i;:::-;7419:63;;7374:118;7559:2;7548:9;7544:18;7531:32;7590:18;7582:6;7579:30;7576:117;;;7612:79;;:::i;:::-;7576:117;7717:62;7771:7;7762:6;7751:9;7747:22;7717:62;:::i;:::-;7707:72;;7502:287;6853:943;;;;;;;:::o;7802:77::-;7839:7;7868:5;7857:16;;7802:77;;;:::o;7885:118::-;7972:24;7990:5;7972:24;:::i;:::-;7967:3;7960:37;7885:118;;:::o;8009:222::-;8102:4;8140:2;8129:9;8125:18;8117:26;;8153:71;8221:1;8210:9;8206:17;8197:6;8153:71;:::i;:::-;8009:222;;;;:::o;8237:329::-;8296:6;8345:2;8333:9;8324:7;8320:23;8316:32;8313:119;;;8351:79;;:::i;:::-;8313:119;8471:1;8496:53;8541:7;8532:6;8521:9;8517:22;8496:53;:::i;:::-;8486:63;;8442:117;8237:329;;;;:::o;8572:118::-;8659:24;8677:5;8659:24;:::i;:::-;8654:3;8647:37;8572:118;;:::o;8696:222::-;8789:4;8827:2;8816:9;8812:18;8804:26;;8840:71;8908:1;8897:9;8893:17;8884:6;8840:71;:::i;:::-;8696:222;;;;:::o;8924:60::-;8952:3;8973:5;8966:12;;8924:60;;;:::o;8990:142::-;9040:9;9073:53;9091:34;9100:24;9118:5;9100:24;:::i;:::-;9091:34;:::i;:::-;9073:53;:::i;:::-;9060:66;;8990:142;;;:::o;9138:126::-;9188:9;9221:37;9252:5;9221:37;:::i;:::-;9208:50;;9138:126;;;:::o;9270:147::-;9341:9;9374:37;9405:5;9374:37;:::i;:::-;9361:50;;9270:147;;;:::o;9423:173::-;9531:58;9583:5;9531:58;:::i;:::-;9526:3;9519:71;9423:173;;:::o;9602:264::-;9716:4;9754:2;9743:9;9739:18;9731:26;;9767:92;9856:1;9845:9;9841:17;9832:6;9767:92;:::i;:::-;9602:264;;;;:::o;9872:329::-;9931:6;9980:2;9968:9;9959:7;9955:23;9951:32;9948:119;;;9986:79;;:::i;:::-;9948:119;10106:1;10131:53;10176:7;10167:6;10156:9;10152:22;10131:53;:::i;:::-;10121:63;;10077:117;9872:329;;;;:::o;10207:140::-;10271:9;10304:37;10335:5;10304:37;:::i;:::-;10291:50;;10207:140;;;:::o;10353:159::-;10454:51;10499:5;10454:51;:::i;:::-;10449:3;10442:64;10353:159;;:::o;10518:250::-;10625:4;10663:2;10652:9;10648:18;10640:26;;10676:85;10758:1;10747:9;10743:17;10734:6;10676:85;:::i;:::-;10518:250;;;;:::o;10774:474::-;10842:6;10850;10899:2;10887:9;10878:7;10874:23;10870:32;10867:119;;;10905:79;;:::i;:::-;10867:119;11025:1;11050:53;11095:7;11086:6;11075:9;11071:22;11050:53;:::i;:::-;11040:63;;10996:117;11152:2;11178:53;11223:7;11214:6;11203:9;11199:22;11178:53;:::i;:::-;11168:63;;11123:118;10774:474;;;;;:::o;11254:180::-;11302:77;11299:1;11292:88;11399:4;11396:1;11389:15;11423:4;11420:1;11413:15;11440:320;11484:6;11521:1;11515:4;11511:12;11501:22;;11568:1;11562:4;11558:12;11589:18;11579:81;;11645:4;11637:6;11633:17;11623:27;;11579:81;11707:2;11699:6;11696:14;11676:18;11673:38;11670:84;;11726:18;;:::i;:::-;11670:84;11491:269;11440:320;;;:::o;11766:116::-;11836:21;11851:5;11836:21;:::i;:::-;11829:5;11826:32;11816:60;;11872:1;11869;11862:12;11816:60;11766:116;:::o;11888:137::-;11942:5;11973:6;11967:13;11958:22;;11989:30;12013:5;11989:30;:::i;:::-;11888:137;;;;:::o;12031:345::-;12098:6;12147:2;12135:9;12126:7;12122:23;12118:32;12115:119;;;12153:79;;:::i;:::-;12115:119;12273:1;12298:61;12351:7;12342:6;12331:9;12327:22;12298:61;:::i;:::-;12288:71;;12244:125;12031:345;;;;:::o;12382:104::-;12427:7;12456:24;12474:5;12456:24;:::i;:::-;12445:35;;12382:104;;;:::o;12492:138::-;12573:32;12599:5;12573:32;:::i;:::-;12566:5;12563:43;12553:71;;12620:1;12617;12610:12;12553:71;12492:138;:::o;12636:159::-;12701:5;12732:6;12726:13;12717:22;;12748:41;12783:5;12748:41;:::i;:::-;12636:159;;;;:::o;12801:367::-;12879:6;12928:2;12916:9;12907:7;12903:23;12899:32;12896:119;;;12934:79;;:::i;:::-;12896:119;13054:1;13079:72;13143:7;13134:6;13123:9;13119:22;13079:72;:::i;:::-;13069:82;;13025:136;12801:367;;;;:::o;13174:143::-;13231:5;13262:6;13256:13;13247:22;;13278:33;13305:5;13278:33;:::i;:::-;13174:143;;;;:::o;13323:351::-;13393:6;13442:2;13430:9;13421:7;13417:23;13413:32;13410:119;;;13448:79;;:::i;:::-;13410:119;13568:1;13593:64;13649:7;13640:6;13629:9;13625:22;13593:64;:::i;:::-;13583:74;;13539:128;13323:351;;;;:::o;13680:180::-;13728:77;13725:1;13718:88;13825:4;13822:1;13815:15;13849:4;13846:1;13839:15;13866:194;13906:4;13926:20;13944:1;13926:20;:::i;:::-;13921:25;;13960:20;13978:1;13960:20;:::i;:::-;13955:25;;14004:1;14001;13997:9;13989:17;;14028:1;14022:4;14019:11;14016:37;;;14033:18;;:::i;:::-;14016:37;13866:194;;;;:::o;14066:442::-;14215:4;14253:2;14242:9;14238:18;14230:26;;14266:71;14334:1;14323:9;14319:17;14310:6;14266:71;:::i;:::-;14347:72;14415:2;14404:9;14400:18;14391:6;14347:72;:::i;:::-;14429;14497:2;14486:9;14482:18;14473:6;14429:72;:::i;:::-;14066:442;;;;;;:::o;14514:507::-;14593:6;14601;14650:2;14638:9;14629:7;14625:23;14621:32;14618:119;;;14656:79;;:::i;:::-;14618:119;14776:1;14801:64;14857:7;14848:6;14837:9;14833:22;14801:64;:::i;:::-;14791:74;;14747:128;14914:2;14940:64;14996:7;14987:6;14976:9;14972:22;14940:64;:::i;:::-;14930:74;;14885:129;14514:507;;;;;:::o;15027:410::-;15067:7;15090:20;15108:1;15090:20;:::i;:::-;15085:25;;15124:20;15142:1;15124:20;:::i;:::-;15119:25;;15179:1;15176;15172:9;15201:30;15219:11;15201:30;:::i;:::-;15190:41;;15380:1;15371:7;15367:15;15364:1;15361:22;15341:1;15334:9;15314:83;15291:139;;15410:18;;:::i;:::-;15291:139;15075:362;15027:410;;;;:::o;15443:180::-;15491:77;15488:1;15481:88;15588:4;15585:1;15578:15;15612:4;15609:1;15602:15;15629:185;15669:1;15686:20;15704:1;15686:20;:::i;:::-;15681:25;;15720:20;15738:1;15720:20;:::i;:::-;15715:25;;15759:1;15749:35;;15764:18;;:::i;:::-;15749:35;15806:1;15803;15799:9;15794:14;;15629:185;;;;:::o;15820:143::-;15877:5;15908:6;15902:13;15893:22;;15924:33;15951:5;15924:33;:::i;:::-;15820:143;;;;:::o;15969:351::-;16039:6;16088:2;16076:9;16067:7;16063:23;16059:32;16056:119;;;16094:79;;:::i;:::-;16056:119;16214:1;16239:64;16295:7;16286:6;16275:9;16271:22;16239:64;:::i;:::-;16229:74;;16185:128;15969:351;;;;:::o;16326:332::-;16447:4;16485:2;16474:9;16470:18;16462:26;;16498:71;16566:1;16555:9;16551:17;16542:6;16498:71;:::i;:::-;16579:72;16647:2;16636:9;16632:18;16623:6;16579:72;:::i;:::-;16326:332;;;;;:::o;16664:191::-;16704:3;16723:20;16741:1;16723:20;:::i;:::-;16718:25;;16757:20;16775:1;16757:20;:::i;:::-;16752:25;;16800:1;16797;16793:9;16786:16;;16821:3;16818:1;16815:10;16812:36;;;16828:18;;:::i;:::-;16812:36;16664:191;;;;:::o
Swarm Source
ipfs://c780866f2330c59bdac77bf8e1e12a2680728eb6b0e1494e7fc7edbbe72c6ef1
[ Download: CSV Export ]
[ Download: CSV Export ]
A token is a representation of an on-chain or off-chain asset. The token page shows information such as price, total supply, holders, transfers and social links. Learn more about this page in our Knowledge Base.