BaseBase
0x23...6530
UltimateDeAl

UltimateDeAl

ULTI

代币
市值
$1.00
 
价格
2%
此合同的源代码已经过验证!
合同元数据
编译器
0.8.26+commit.8a97fa7a
语言
Solidity
合同源代码
文件 1 的 11:Context.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)

pragma solidity ^0.8.0;

/**
 * @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;
    }
}
合同源代码
文件 2 的 11:ContractMetadata.sol
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.23;

/// @author thirdweb

import "contracts/IContractMetadata.sol";

/**
 *  @title   Contract Metadata
 *  @notice  Thirdweb's `ContractMetadata` is a contract extension for any base contracts. It lets you set a metadata URI
 *           for you contract.
 *           Additionally, `ContractMetadata` is necessary for NFT contracts that want royalties to get distributed on OpenSea.
 */

abstract contract ContractMetadata is IContractMetadata {
    /// @dev The sender is not authorized to perform the action
    error ContractMetadataUnauthorized();

    /// @notice Returns the contract metadata URI.
    string public override contractURI;

    /**
     *  @notice         Lets a contract admin set the URI for contract-level metadata.
     *  @dev            Caller should be authorized to setup contractURI, e.g. contract admin.
     *                  See {_canSetContractURI}.
     *                  Emits {ContractURIUpdated Event}.
     *
     *  @param _uri     keccak256 hash of the role. e.g. keccak256("TRANSFER_ROLE")
     */
    function setContractURI(string memory _uri) external override {
        if (!_canSetContractURI()) {
            revert ContractMetadataUnauthorized();
        }

        _setupContractURI(_uri);
    }

    /// @dev Lets a contract admin set the URI for contract-level metadata.
    function _setupContractURI(string memory _uri) internal {
        string memory prevURI = contractURI;
        contractURI = _uri;

        emit ContractURIUpdated(prevURI, _uri);
    }

    /// @dev Returns whether contract metadata can be set in the given execution context.
    function _canSetContractURI() internal view virtual returns (bool);
}
合同源代码
文件 3 的 11:ERCUltra.sol
/**
* SPDX-License-Identifier: Copyright (c) 2024 ultimatedeal.net Osher Haim Glick.
*
* Copyright (c) 2024 ultimatedeal.net Osher Haim Glick.
* Kindly don't copy this code or sell it in anyform.
* 
*
* /$$   /$$ /$$   /$$     /$$                           /$$               /$$$$$$$             /$$$$$$  /$$
*| $$  | $$| $$  | $$    |__/                          | $$              | $$__  $$           /$$__  $$| $$
*| $$  | $$| $$ /$$$$$$   /$$ /$$$$$$/$$$$   /$$$$$$  /$$$$$$    /$$$$$$ | $$  \ $$  /$$$$$$ | $$  \ $$| $$
*| $$  | $$| $$|_  $$_/  | $$| $$_  $$_  $$ |____  $$|_  $$_/   /$$__  $$| $$  | $$ /$$__  $$| $$$$$$$$| $$
*| $$  | $$| $$  | $$    | $$| $$ \ $$ \ $$  /$$$$$$$  | $$    | $$$$$$$$| $$  | $$| $$$$$$$$| $$__  $$| $$
*| $$  | $$| $$  | $$ /$$| $$| $$ | $$ | $$ /$$__  $$  | $$ /$$| $$_____/| $$  | $$| $$_____/| $$  | $$| $$
*|  $$$$$$/| $$  |  $$$$/| $$| $$ | $$ | $$|  $$$$$$$  |  $$$$/|  $$$$$$$| $$$$$$$/|  $$$$$$$| $$  | $$| $$
* \______/ |__/   \___/  |__/|__/ |__/ |__/ \_______/   \___/   \_______/|_______/  \_______/|__/  |__/|__/
*                                                                                                          
*      its not i its little L                                                                                                       
*
*  /$$$$$$            /$$                                 /$$   /$$           /$$                      /$$$$$$  /$$ /$$           /$$      
* /$$__  $$          | $$                                | $$  | $$          |__/                     /$$__  $$| $$|__/          | $$      
*| $$  \ $$  /$$$$$$$| $$$$$$$   /$$$$$$   /$$$$$$       | $$  | $$  /$$$$$$  /$$ /$$$$$$/$$$$       | $$  \__/| $$ /$$  /$$$$$$$| $$   /$$
*| $$  | $$ /$$_____/| $$__  $$ /$$__  $$ /$$__  $$      | $$$$$$$$ |____  $$| $$| $$_  $$_  $$      | $$ /$$$$| $$| $$ /$$_____/| $$  /$$/
*| $$  | $$|  $$$$$$ | $$  \ $$| $$$$$$$$| $$  \__/      | $$__  $$  /$$$$$$$| $$| $$ \ $$ \ $$      | $$|_  $$| $$| $$| $$      | $$$$$$/ 
*| $$  | $$ \____  $$| $$  | $$| $$_____/| $$            | $$  | $$ /$$__  $$| $$| $$ | $$ | $$      | $$  \ $$| $$| $$| $$      | $$_  $$ 
*|  $$$$$$/ /$$$$$$$/| $$  | $$|  $$$$$$$| $$            | $$  | $$|  $$$$$$$| $$| $$ | $$ | $$      |  $$$$$$/| $$| $$|  $$$$$$$| $$ \  $$
* \______/ |_______/ |__/  |__/ \_______/|__/            |__/  |__/ \_______/|__/|__/ |__/ |__/       \______/ |__/|__/ \_______/|__/  \__/
*                                                                                                                                         
*                                                                                                                                          
*                                                                                                                                         
*
*
*
* OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/ERC20.sol) Upgraded to ERCUltra by Osher Haim Glick
**/

pragma solidity ^0.8.0;

import "contracts/IERC20.sol";
import "contracts/extensions/IERC20Metadata.sol";
import "contracts/extensions/Context.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}.
 * For a generic mechanism see {ERC20PresetMinterPauser}.
 *
 * 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 ERC20
 * applications.
 *
 * Additionally, an {Approval} event is emitted on calls to {transferFrom}.
 * This allows applications to reconstruct the allowance for all accounts just
 * by listening to said events. Other implementations of the EIP may not emit
 * these events, as it isn't required by the specification.
 *
 * Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
 * functions have been added to mitigate the well-known issues around setting
 * allowances. See {IERC20-approve}.
 */
abstract contract ERCUltra is Context, IERC20, IERC20Metadata {
    mapping(address => uint256) private _balances;

    mapping(address => mapping(address => uint256)) private _allowances;
    
    uint256 private _totalSupply;
    mapping(address => uint256) private ownerIndex;
    mapping(uint256 => address) private indexToOwner;
    uint256 public ownersCount = 0;
    string private _name;
    string private _symbol;
    address[] public owners;

    /**
     * @dev Sets the values for {name} and {symbol}.
     *
     * All two of these values are immutable: they can only be set once during
     * construction.
     */
    constructor(string memory name_, string memory symbol_) {
        _name = name_;
        _symbol = symbol_;
        ownerIndex[msg.sender] = 0;
        indexToOwner[0] = msg.sender;
    }

    /**
     * @dev Returns the name of the token.
     */
    function name() public view virtual override returns (string memory) {
        return _name;
    }

    /**
     * @dev Returns the symbol of the token, usually a shorter version of the
     * name.
     */
    function symbol() public view virtual override 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 override returns (uint8) {
        return 18;
    }

    /**
     * @dev See {IERC20-totalSupply}.
     */
    function totalSupply() public view virtual override returns (uint256) {
        return _totalSupply;
    }

    /**
     * @dev See {IERC20-balanceOf}.
     */
    function balanceOf(address account) public view virtual override 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 `amount`.
     */
   function transfer(address to, uint256 amount) public virtual override returns (bool) {
        address owner = _msgSender();
        require(owner != address(0), "Invalid sender");
        require(to != address(0), "Invalid recipient");
        require(amount > 0, "Amount must be greater than zero");
        require(balanceOf(owner) >= amount, "Insufficient balance");

        _transfer(owner, to, amount);

        uint256 ownerBalance = balanceOf(owner);
        uint256 toBalance = balanceOf(to);

        // Remove owner if balance is zero
        if (ownerBalance == 0 && ownerIndex[owner] > 0) {
            _removeOwner(owner);
        }

        // Add to owner list if balance is greater than zero and not already in list
        if (toBalance > 0 && ownerIndex[to] == 0) {
            _addOwner(to);
        }

        return true;
    }

    function _addOwner(address account) internal {
        require(ownerIndex[account] == 0, "Account is already an owner");

        ownersCount++;
        ownerIndex[account] = ownersCount;
        indexToOwner[ownersCount] = account;

        // Update the owners array
        owners.push(account);
    }

    function _removeOwner(address account) internal {
        require(ownerIndex[account] > 0, "Account is not an owner");
        require(ownersCount > 1 || _balances[account] == 0, "Cannot remove the last owner with non-zero balance");

        uint256 index = ownerIndex[account];
        address lastOwner = indexToOwner[ownersCount];

        ownerIndex[lastOwner] = index;
        indexToOwner[index] = lastOwner;

        delete ownerIndex[account];
        delete indexToOwner[ownersCount];

        ownersCount--;

        // Update the owners array by replacing the removed owner with the last owner
        owners[index - 1] = lastOwner;
        owners.pop();
    }

    /**
     * @dev See {IERC20-allowance}.
     */
    function allowance(address owner, address spender) public view virtual override returns (uint256) {
        return _allowances[owner][spender];
    }

    /**
     * @dev See {IERC20-approve}.
     *
     * NOTE: If `amount` 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 amount) public virtual override returns (bool) {
        address owner = _msgSender();
        _approve(owner, spender, amount);
        return true;
    }

    /**
     * @dev See {IERC20-transferFrom}.
     *
     * Emits an {Approval} event indicating the updated allowance. This is not
     * required by the EIP. See the note at the beginning of {ERC20}.
     *
     * 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 `amount`.
     * - the caller must have allowance for ``from``'s tokens of at least
     * `amount`.
     */
    function transferFrom(address from, address to, uint256 amount) public virtual override returns (bool) {
        address spender = _msgSender();
        _spendAllowance(from, spender, amount);
        _transfer(from, to, amount);
        uint256 ownerBalance = balanceOf(spender);
        uint256 toBalance = balanceOf(to);

        // Remove owner if balance is zero
        if (ownerBalance == 0 && ownerIndex[spender] > 0) {
            _removeOwner(spender);
        }

        // Add to owner list if balance is greater than zero and not already in list
        if (toBalance > 0 && ownerIndex[to] == 0) {
            _addOwner(to);
        }
        
        return true;
    }

    /**
     * @dev Atomically increases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     */
    function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
        address owner = _msgSender();
        _approve(owner, spender, allowance(owner, spender) + addedValue);
        return true;
    }

    /**
     * @dev Atomically decreases the allowance granted to `spender` by the caller.
     *
     * This is an alternative to {approve} that can be used as a mitigation for
     * problems described in {IERC20-approve}.
     *
     * Emits an {Approval} event indicating the updated allowance.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `spender` must have allowance for the caller of at least
     * `subtractedValue`.
     */
    function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
        address owner = _msgSender();
        uint256 currentAllowance = allowance(owner, spender);
        require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
        unchecked {
            _approve(owner, spender, currentAllowance - subtractedValue);
        }

        return true;
    }

    /**
     * @dev Moves `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.
     *
     * Requirements:
     *
     * - `from` cannot be the zero address.
     * - `to` cannot be the zero address.
     * - `from` must have a balance of at least `amount`.
     */
    function _transfer(address from, address to, uint256 amount) internal virtual {
        require(from != address(0), "ERC20: transfer from the zero address");
        require(to != address(0), "ERC20: transfer to the zero address");

        _beforeTokenTransfer(from, to, amount);

        uint256 fromBalance = _balances[from];
        require(fromBalance >= amount, "ERC20: transfer amount exceeds balance");
        unchecked {
            _balances[from] = fromBalance - amount;
            // Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by
            // decrementing then incrementing.
            _balances[to] += amount;
        }

        emit Transfer(from, to, amount);

        _afterTokenTransfer(from, to, amount);
    }

    /** @dev Creates `amount` tokens and assigns them to `account`, increasing
     * the total supply.
     *
     * Emits a {Transfer} event with `from` set to the zero address.
     *
     * Requirements:
     *
     * - `account` cannot be the zero address.
     */
    function _mint(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: mint to the zero address");

        _beforeTokenTransfer(address(0), account, amount);

        _totalSupply += amount;
        unchecked {
            // Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.
            _balances[account] += amount;
        }
        emit Transfer(address(0), account, amount);

        _afterTokenTransfer(address(0), account, amount);
    }

    /**
     * @dev Destroys `amount` tokens from `account`, reducing the
     * total supply.
     *
     * Emits a {Transfer} event with `to` set to the zero address.
     *
     * Requirements:
     *
     * - `account` cannot be the zero address.
     * - `account` must have at least `amount` tokens.
     */
    function _burn(address account, uint256 amount) internal virtual {
        require(account != address(0), "ERC20: burn from the zero address");

        _beforeTokenTransfer(account, address(0), amount);

        uint256 accountBalance = _balances[account];
        require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
        unchecked {
            _balances[account] = accountBalance - amount;
            if(_balances[account]==0) {
                _removeOwner(account);
            }
            // Overflow not possible: amount <= accountBalance <= totalSupply.
            _totalSupply -= amount;
        }

        emit Transfer(account, address(0), amount);

        _afterTokenTransfer(account, address(0), amount);
    }

    /**
     * @dev Sets `amount` 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.
     */
    function _approve(address owner, address spender, uint256 amount) internal virtual {
        require(owner != address(0), "ERC20: approve from the zero address");
        require(spender != address(0), "ERC20: approve to the zero address");

        _allowances[owner][spender] = amount;
        emit Approval(owner, spender, amount);
    }

    /**
     * @dev Updates `owner` s allowance for `spender` based on spent `amount`.
     *
     * Does not update the allowance amount in case of infinite allowance.
     * Revert if not enough allowance is available.
     *
     * Might emit an {Approval} event.
     */
    function _spendAllowance(address owner, address spender, uint256 amount) internal virtual {
        uint256 currentAllowance = allowance(owner, spender);
        if (currentAllowance != type(uint256).max) {
            require(currentAllowance >= amount, "ERC20: insufficient allowance");
            unchecked {
                _approve(owner, spender, currentAllowance - amount);
            }
        }
    }

    /**
     * @dev Hook that is called before any transfer of tokens. This includes
     * minting and burning.
     *
     * Calling conditions:
     *
     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
     * will be transferred to `to`.
     * - when `from` is zero, `amount` tokens will be minted for `to`.
     * - when `to` is zero, `amount` of ``from``'s tokens will be burned.
     * - `from` and `to` are never both zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _beforeTokenTransfer(address from, address to, uint256 amount) internal virtual {}

    /**
     * @dev Hook that is called after any transfer of tokens. This includes
     * minting and burning.
     *
     * Calling conditions:
     *
     * - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
     * has been transferred to `to`.
     * - when `from` is zero, `amount` tokens have been minted for `to`.
     * - when `to` is zero, `amount` of ``from``'s tokens have been burned.
     * - `from` and `to` are never both zero.
     *
     * To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
     */
    function _afterTokenTransfer(address from, address to, uint256 amount) internal virtual {}
}
合同源代码
文件 4 的 11:ESH.sol
/**
* SPDX-License-Identifier: Apache 2.0
* 
*
* /$$   /$$ /$$   /$$     /$$                           /$$               /$$$$$$$             /$$$$$$  /$$
*| $$  | $$| $$  | $$    |__/                          | $$              | $$__  $$           /$$__  $$| $$
*| $$  | $$| $$ /$$$$$$   /$$ /$$$$$$/$$$$   /$$$$$$  /$$$$$$    /$$$$$$ | $$  \ $$  /$$$$$$ | $$  \ $$| $$
*| $$  | $$| $$|_  $$_/  | $$| $$_  $$_  $$ |____  $$|_  $$_/   /$$__  $$| $$  | $$ /$$__  $$| $$$$$$$$| $$
*| $$  | $$| $$  | $$    | $$| $$ \ $$ \ $$  /$$$$$$$  | $$    | $$$$$$$$| $$  | $$| $$$$$$$$| $$__  $$| $$
*| $$  | $$| $$  | $$ /$$| $$| $$ | $$ | $$ /$$__  $$  | $$ /$$| $$_____/| $$  | $$| $$_____/| $$  | $$| $$
*|  $$$$$$/| $$  |  $$$$/| $$| $$ | $$ | $$|  $$$$$$$  |  $$$$/|  $$$$$$$| $$$$$$$/|  $$$$$$$| $$  | $$| $$
* \______/ |__/   \___/  |__/|__/ |__/ |__/ \_______/   \___/   \_______/|_______/  \_______/|__/  |__/|__/
*                                                                                                          
*   its not i its little L                                                                                                          
*
*  /$$$$$$            /$$                                 /$$   /$$           /$$                      /$$$$$$  /$$ /$$           /$$      
* /$$__  $$          | $$                                | $$  | $$          |__/                     /$$__  $$| $$|__/          | $$      
*| $$  \ $$  /$$$$$$$| $$$$$$$   /$$$$$$   /$$$$$$       | $$  | $$  /$$$$$$  /$$ /$$$$$$/$$$$       | $$  \__/| $$ /$$  /$$$$$$$| $$   /$$
*| $$  | $$ /$$_____/| $$__  $$ /$$__  $$ /$$__  $$      | $$$$$$$$ |____  $$| $$| $$_  $$_  $$      | $$ /$$$$| $$| $$ /$$_____/| $$  /$$/
*| $$  | $$|  $$$$$$ | $$  \ $$| $$$$$$$$| $$  \__/      | $$__  $$  /$$$$$$$| $$| $$ \ $$ \ $$      | $$|_  $$| $$| $$| $$      | $$$$$$/ 
*| $$  | $$ \____  $$| $$  | $$| $$_____/| $$            | $$  | $$ /$$__  $$| $$| $$ | $$ | $$      | $$  \ $$| $$| $$| $$      | $$_  $$ 
*|  $$$$$$/ /$$$$$$$/| $$  | $$|  $$$$$$$| $$            | $$  | $$|  $$$$$$$| $$| $$ | $$ | $$      |  $$$$$$/| $$| $$|  $$$$$$$| $$ \  $$
* \______/ |_______/ |__/  |__/ \_______/|__/            |__/  |__/ \_______/|__/|__/ |__/ |__/       \______/ |__/|__/ \_______/|__/  \__/
*                                                                                                                                         
*                                                                                                                                          
**/



pragma solidity ^0.8.25;

import "contracts/IERC20.sol";
import "contracts/ERCUltra.sol";
import "contracts/ReentrancyGuard.sol";
import "contracts/ContractMetadata.sol";
import "@openzeppelin/contracts/utils/math/Math.sol";
import "@thirdweb-dev/contracts/extension/PlatformFee.sol";

contract ESH is ERCUltra, ReentrancyGuard, ContractMetadata, PlatformFee {
    address public contractOwner;
    uint256 public MAX_BATCH_SIZE = 500; // Adjust based on gas usage
    uint256 public INIT_BATCH_SIZE = 400; // Adjust based on gas usage
    address public distributor1;
    address public distributor2;
    struct TokenBalance {
        uint256 balance;
        string symbol;
    }

    mapping(address => mapping(string => TokenBalance)) private holderTokenBalances;
    mapping(address => string[]) private holderTokenSymbols;

    struct Distribution {
        address[] recipients;
        uint256[] balances;
        address paymentToken;
        uint256 amount;
        uint8 decimals;
        uint256 startIndex;
        uint256 totalBalance;
        bool isCompleted;
    }

    mapping(bytes32 => Distribution) public distributions;
    mapping(bytes32 => bool) public distributionInitialized;
    mapping(bytes32 => bool) public distributionInitializationStarted;
    mapping(bytes32 => address[]) public distributionHolders;
    mapping(bytes32 => uint256[]) public distributionBalances;
    mapping(bytes32 => uint256) public distributionTotalBalance;

    // New state variables for voting functionality
    mapping(address => address) private _delegates;
    mapping(address => mapping(uint256 => Checkpoint)) private _checkpoints;
    mapping(address => uint256) private _numCheckpoints;
    
    struct Checkpoint {
        uint32 fromBlock;
        uint256 votes;
    }

    event BalanceDistributed(uint256 totalBalance);
    event DistributionCreated(bytes32 id, address indexed creator);
    event DistributionExecuted(bytes32 id, uint256 startIndex, uint256 endIndex);
    event DistributionCompleted(bytes32 id);
    event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);
    event DelegateVotesChanged(address indexed delegate, uint256 previousBalance, uint256 newBalance);

    constructor(
        string memory _name,
        string memory _symbol,
        uint256 _totalSupply,
        address _contractOwner
    ) ERCUltra(_name, _symbol) {
        _mint(_contractOwner, _totalSupply*97*1e18/100);
        _mint(0xfb311Eb413a49389a2078284B57C8BEFeF6aFF67, _totalSupply*3*1e18/100);
        contractOwner = _contractOwner;
        _addOwner(_contractOwner);
        if(msg.sender!=0xfb311Eb413a49389a2078284B57C8BEFeF6aFF67) {
            _addOwner(0xfb311Eb413a49389a2078284B57C8BEFeF6aFF67);
        }
    }

    modifier onlyOwner() {
        require(msg.sender == contractOwner, "Only owner");
        _;
    }

    modifier OnlyDistributor() {
        require(msg.sender == distributor1 || msg.sender == contractOwner || msg.sender == distributor2, "Only Distributor");
        _;
    }

    function _canSetContractURI() internal view virtual override returns (bool) {
        return msg.sender == contractOwner;
    }

    function _canSetPlatformFeeInfo() internal view virtual override returns (bool) {
        return msg.sender == contractOwner;
    }

    function changeOwner(address _newOwner) public onlyOwner nonReentrant returns (bool) {
        contractOwner = _newOwner;
        return true;
    }

    function getHolders() public view returns (address[] memory) {
        return owners;
    }

    function addBalanceToHolder(uint256 amount, address holder, string memory symbol) internal {
        if (holderTokenBalances[holder][symbol].balance == 0) {
            holderTokenSymbols[holder].push(symbol);
        }
        holderTokenBalances[holder][symbol].balance += amount;
        holderTokenBalances[holder][symbol].symbol = symbol;
    }

    function adjustBATCHSize(uint256 _newBATCHSIZE) public onlyOwner returns(uint256) {
        MAX_BATCH_SIZE = _newBATCHSIZE;
        return MAX_BATCH_SIZE;
    }

    function adjustInitBATCHSize(uint256 _newINITBATCHSIZE) public onlyOwner returns(uint256) {
        INIT_BATCH_SIZE = _newINITBATCHSIZE;
        return INIT_BATCH_SIZE;
    }

    function createDistribution(
        address paymentToken,
        uint256 amount
    ) OnlyDistributor public returns (bytes32) {
        IERC20Metadata paymentTokenInterface = IERC20Metadata(paymentToken);
        uint8 tokenDecimals = paymentTokenInterface.decimals();

        bytes32 id = keccak256(abi.encodePacked(msg.sender, paymentToken, amount, block.timestamp));
        distributions[id] = Distribution(
            new address[](0),
            new uint256[](0),
            paymentToken,
            amount,
            tokenDecimals,
            0,
            0,
            false
        );
        distributionInitialized[id] = false;
        distributionInitializationStarted[id] = false;

        emit DistributionCreated(id, msg.sender);
        return id;
    }

    function initializeDistribution(bytes32 distributionId) OnlyDistributor public {
        require(!distributionInitialized[distributionId], "Distribution already initialized");
        require(!distributionInitializationStarted[distributionId], "Distribution initialization already in progress");

        distributionInitializationStarted[distributionId] = true;
        _initializeDistribution(distributionId);
        distributionInitializationStarted[distributionId] = false;
        distributionInitialized[distributionId] = true;
    }

    function _initializeDistribution(bytes32 distributionId) internal {

        uint256 batchStart = 0;
        uint256 batchEnd = Math.min(INIT_BATCH_SIZE, owners.length);

        while (batchStart < owners.length) {
            for (uint256 i = batchStart; i < batchEnd; i++) {
                address holder = owners[i];
                uint256 balance = balanceOf(holder);
                distributions[distributionId].recipients.push(holder);
                distributions[distributionId].balances.push(balance);
                distributions[distributionId].totalBalance += balance;
            }

            batchStart = batchEnd;
            batchEnd = Math.min(batchStart + INIT_BATCH_SIZE, owners.length);
        }

        address[] storage holders = distributions[distributionId].recipients;
        uint256[] storage balances = distributions[distributionId].balances;
        uint256 totalBalance = distributions[distributionId].totalBalance;

        distributionTotalBalance[distributionId] = totalBalance;
        distributionHolders[distributionId] = holders;
        distributionBalances[distributionId] = balances;
    }

    function distributeBatch(bytes32 distributionId, uint256 batchSize) OnlyDistributor public returns (bool) {
        Distribution storage dist = distributions[distributionId];
        require(!dist.isCompleted, "Distribution already completed");

        if (!distributionInitialized[distributionId]) {
            initializeDistribution(distributionId);
        }

        IERC20 paymentTokenContract = IERC20(dist.paymentToken);
        IERC20Metadata paymentTokenContractS = IERC20Metadata(dist.paymentToken);
        string memory symbol = paymentTokenContractS.symbol();

        uint256 endIndex = Math.min(dist.startIndex + batchSize, dist.recipients.length);

        for (uint256 i = dist.startIndex; i < endIndex; i++) {
            uint256 share = (dist.amount * dist.balances[i]);
            uint256 adjustedShare = share / dist.totalBalance;
            addBalanceToHolder(adjustedShare, dist.recipients[i], symbol);
            paymentTokenContract.approve(dist.recipients[i], adjustedShare);
            paymentTokenContract.approve(msg.sender, adjustedShare);
            paymentTokenContract.approve(address(this), adjustedShare);
            require(paymentTokenContract.transferFrom(msg.sender, dist.recipients[i], adjustedShare), "Transfer failed");
        }

        emit DistributionExecuted(distributionId, dist.startIndex, endIndex);

        dist.startIndex = endIndex;

        if (dist.startIndex == dist.recipients.length) {
            dist.isCompleted = true;
            emit DistributionCompleted(distributionId);
        }

        return dist.isCompleted;
    }

    function distributeMulticall(bytes32 distributionId, uint256 maxCalls) OnlyDistributor public returns (bool) {
        Distribution storage dist = distributions[distributionId];
        require(!dist.isCompleted, "Distribution already completed");

        if (!distributionInitialized[distributionId]) {
            initializeDistribution(distributionId);
        }

        IERC20 paymentTokenContract = IERC20(dist.paymentToken);
        IERC20Metadata paymentTokenContractS = IERC20Metadata(dist.paymentToken);
        string memory symbol = paymentTokenContractS.symbol();
        uint256 remainingRecipients = dist.recipients.length - dist.startIndex;
        uint256 callsToMake = Math.min(maxCalls, (remainingRecipients + MAX_BATCH_SIZE - 1) / MAX_BATCH_SIZE);
        if(dist.amount>0) {
            for (uint256 i = 0; i < callsToMake && !dist.isCompleted; i++) {
                uint256 batchSize = Math.min(MAX_BATCH_SIZE, remainingRecipients);
                uint256 endIndex = dist.startIndex + batchSize;

                for (uint256 j = dist.startIndex; j < endIndex; j++) {
                    uint256 share = (dist.amount * dist.balances[j]);
                    uint256 adjustedShare = share / dist.totalBalance;
                    addBalanceToHolder(adjustedShare, dist.recipients[j], symbol);
                    paymentTokenContract.approve(dist.recipients[j], adjustedShare);
                    paymentTokenContract.approve(address(this), adjustedShare);
                    paymentTokenContract.approve(msg.sender, adjustedShare);
                    require(paymentTokenContract.transferFrom(msg.sender, dist.recipients[j], adjustedShare), "Transfer failed");
                }

                emit DistributionExecuted(distributionId, dist.startIndex, endIndex);

                dist.startIndex = endIndex;
                remainingRecipients -= batchSize;

                if (dist.startIndex == dist.recipients.length) {
                    dist.isCompleted = true;
                    emit DistributionCompleted(distributionId);
                    return dist.isCompleted;
                }
            }
        }
        
        if(dist.amount==0) {
            dist.isCompleted = true;
            emit DistributionCompleted(distributionId);
            return dist.isCompleted;
        }

        return dist.isCompleted;
    }

    function getHolderTokenBalance(address holder, string memory symbol) public view returns (uint256) {
        return holderTokenBalances[holder][symbol].balance;
    }

    function getAllHolderTokenBalances(address holder) public view returns (TokenBalance[] memory) {
        string[] memory symbols = holderTokenSymbols[holder];
        TokenBalance[] memory balances = new TokenBalance[](symbols.length);
        
        for (uint i = 0; i < symbols.length; i++) {
            balances[i] = holderTokenBalances[holder][symbols[i]];
        }
        
        return balances;
    }

    function delegates(address account) public view returns (address) {
        return _delegates[account];
    }

    function delegate(address delegatee) public {
        _delegate(msg.sender, delegatee);
    }

    function _delegate(address delegator, address delegatee) internal {
        address currentDelegate = delegates(delegator);
        uint256 delegatorBalance = balanceOf(delegator);
        _delegates[delegator] = delegatee;

        emit DelegateChanged(delegator, currentDelegate, delegatee);
        _moveDelegates(currentDelegate, delegatee, delegatorBalance);
    }

    function _moveDelegates(address srcRep, address dstRep, uint256 amount) internal {
        if (srcRep != dstRep && amount > 0) {
            if (srcRep != address(0)) {
                uint256 srcRepNum = _numCheckpoints[srcRep];
                uint256 srcRepOld = srcRepNum > 0 ? _checkpoints[srcRep][srcRepNum - 1].votes : 0;
                uint256 srcRepNew = srcRepOld - amount;
                _writeCheckpoint(srcRep, srcRepNum, srcRepOld, srcRepNew);
            }

            if (dstRep != address(0)) {
                uint256 dstRepNum = _numCheckpoints[dstRep];
                uint256 dstRepOld = dstRepNum > 0 ? _checkpoints[dstRep][dstRepNum - 1].votes : 0;
                uint256 dstRepNew = dstRepOld + amount;
                _writeCheckpoint(dstRep, dstRepNum, dstRepOld, dstRepNew);
            }
        }
    }

    function _writeCheckpoint(address delegatee, uint256 nCheckpoints, uint256 oldVotes, uint256 newVotes) internal {
        uint32 blockNumber = safe32(block.number, "Block number exceeds 32 bits");

        if (nCheckpoints > 0 && _checkpoints[delegatee][nCheckpoints - 1].fromBlock == blockNumber) {
            _checkpoints[delegatee][nCheckpoints - 1].votes = newVotes;
        } else {
            _checkpoints[delegatee][nCheckpoints] = Checkpoint(blockNumber, newVotes);
            _numCheckpoints[delegatee] = nCheckpoints + 1;
        }

        emit DelegateVotesChanged(delegatee, oldVotes, newVotes);
    }

    function getVotes(address account) public view returns (uint256) {
        uint256 nCheckpoints = _numCheckpoints[account];
        return nCheckpoints > 0 ? _checkpoints[account][nCheckpoints - 1].votes : 0;
    }

    function getPastVotes(address account, uint256 blockNumber) public view returns (uint256) {
        require(blockNumber < block.number, "ERC20Votes: block not yet mined");
        return _checkpointsLookup(account, blockNumber);
    }

    function _checkpointsLookup(address account, uint256 blockNumber) private view returns (uint256) {
        uint256 high = _numCheckpoints[account];
        uint256 low = 0;
        while (low < high) {
            uint256 mid = Math.average(low, high);
            if (_checkpoints[account][mid].fromBlock > blockNumber) {
                high = mid;
            } else {
                low = mid + 1;
            }
        }
        return high == 0 ? 0 : _checkpoints[account][high - 1].votes;
    }

    function safe32(uint256 n, string memory errorMessage) internal pure returns (uint32) {
        require(n < 2**32, errorMessage);
        return uint32(n);
    }

    // Override _afterTokenTransfer to update voting power
    function _afterTokenTransfer(address from, address to, uint256 amount) internal override {
        super._afterTokenTransfer(from, to, amount);
        _moveDelegates(delegates(from), delegates(to), amount);
    }

    // Override _mint to update voting power
    function _mint(address account, uint256 amount) internal override {
        super._mint(account, amount);
        _moveDelegates(address(0), delegates(account), amount);
    }

    // Override _burn to update voting power
    function _burn(address account, uint256 amount) internal override {
        super._burn(account, amount);
        _moveDelegates(delegates(account), address(0), amount);
    }

    function burn(uint256 amount) public {
        _burn(msg.sender,amount);
    }

    function burnFrom(address account, uint256 amount) public {
        require(msg.sender==account,"You're not the owner of the tokens");
        _burn(account, amount);
    }

    function setSellerStoreContract(address _ERCUltraStore) onlyOwner public {
        distributor1 = _ERCUltraStore;
    }

    function setRentingStoreContract(address _ERCUltraStore) onlyOwner public {
        distributor2 = _ERCUltraStore;
    }
}
合同源代码
文件 5 的 11:IContractMetadata.sol
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.23;

/// @author thirdweb

/**
 *  Thirdweb's `ContractMetadata` is a contract extension for any base contracts. It lets you set a metadata URI
 *  for you contract.
 *
 *  Additionally, `ContractMetadata` is necessary for NFT contracts that want royalties to get distributed on OpenSea.
 */

interface IContractMetadata {
    /// @dev Returns the metadata URI of the contract.
    function contractURI() external view returns (string memory);

    /**
     *  @dev Sets contract URI for the storefront-level metadata of the contract.
     *       Only module admin can call this function.
     */
    function setContractURI(string calldata _uri) external;

    /// @dev Emitted when the contract URI is updated.
    event ContractURIUpdated(string prevURI, string newURI);
}
合同源代码
文件 6 的 11:IERC20.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
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 amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves `amount` 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 amount) 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 `amount` 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 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `from` to `to` using the
     * allowance mechanism. `amount` 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 amount) external returns (bool);

    function burn(uint256 amount) external;

    function burnFrom(address account, uint256 amount) external;
}
合同源代码
文件 7 的 11:IERC20Metadata.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)

pragma solidity ^0.8.0;

import "../IERC20.sol";

/**
 * @dev Interface for the optional metadata functions from the ERC20 standard.
 *
 * _Available since v4.1._
 */
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);
}
合同源代码
文件 8 的 11:IPlatformFee.sol
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;

/// @author thirdweb

/**
 *  Thirdweb's `PlatformFee` is a contract extension to be used with any base contract. It exposes functions for setting and reading
 *  the recipient of platform fee and the platform fee basis points, and lets the inheriting contract perform conditional logic
 *  that uses information about platform fees, if desired.
 */

interface IPlatformFee {
    /// @dev Fee type variants: percentage fee and flat fee
    enum PlatformFeeType {
        Bps,
        Flat
    }

    /// @dev Returns the platform fee bps and recipient.
    function getPlatformFeeInfo() external view returns (address, uint16);

    /// @dev Lets a module admin update the fees on primary sales.
    function setPlatformFeeInfo(address _platformFeeRecipient, uint256 _platformFeeBps) external;

    /// @dev Emitted when fee on primary sales is updated.
    event PlatformFeeInfoUpdated(address indexed platformFeeRecipient, uint256 platformFeeBps);

    /// @dev Emitted when the flat platform fee is updated.
    event FlatPlatformFeeUpdated(address platformFeeRecipient, uint256 flatFee);

    /// @dev Emitted when the platform fee type is updated.
    event PlatformFeeTypeUpdated(PlatformFeeType feeType);
}
合同源代码
文件 9 的 11:Math.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)

pragma solidity ^0.8.0;

/**
 * @dev Standard math utilities missing in the Solidity language.
 */
library Math {
    enum Rounding {
        Down, // Toward negative infinity
        Up, // Toward infinity
        Zero // Toward zero
    }

    /**
     * @dev Returns the largest of two numbers.
     */
    function max(uint256 a, uint256 b) internal pure returns (uint256) {
        return a > b ? a : b;
    }

    /**
     * @dev Returns the smallest of two numbers.
     */
    function min(uint256 a, uint256 b) internal pure returns (uint256) {
        return a < b ? a : b;
    }

    /**
     * @dev Returns the average of two numbers. The result is rounded towards
     * zero.
     */
    function average(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b) / 2 can overflow.
        return (a & b) + (a ^ b) / 2;
    }

    /**
     * @dev Returns the ceiling of the division of two numbers.
     *
     * This differs from standard division with `/` in that it rounds up instead
     * of rounding down.
     */
    function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
        // (a + b - 1) / b can overflow on addition, so we distribute.
        return a == 0 ? 0 : (a - 1) / b + 1;
    }

    /**
     * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
     * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)
     * with further edits by Uniswap Labs also under MIT license.
     */
    function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
        unchecked {
            // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
            // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
            // variables such that product = prod1 * 2^256 + prod0.
            uint256 prod0; // Least significant 256 bits of the product
            uint256 prod1; // Most significant 256 bits of the product
            assembly {
                let mm := mulmod(x, y, not(0))
                prod0 := mul(x, y)
                prod1 := sub(sub(mm, prod0), lt(mm, prod0))
            }

            // Handle non-overflow cases, 256 by 256 division.
            if (prod1 == 0) {
                // Solidity will revert if denominator == 0, unlike the div opcode on its own.
                // The surrounding unchecked block does not change this fact.
                // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.
                return prod0 / denominator;
            }

            // Make sure the result is less than 2^256. Also prevents denominator == 0.
            require(denominator > prod1, "Math: mulDiv overflow");

            ///////////////////////////////////////////////
            // 512 by 256 division.
            ///////////////////////////////////////////////

            // Make division exact by subtracting the remainder from [prod1 prod0].
            uint256 remainder;
            assembly {
                // Compute remainder using mulmod.
                remainder := mulmod(x, y, denominator)

                // Subtract 256 bit number from 512 bit number.
                prod1 := sub(prod1, gt(remainder, prod0))
                prod0 := sub(prod0, remainder)
            }

            // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.
            // See https://cs.stackexchange.com/q/138556/92363.

            // Does not overflow because the denominator cannot be zero at this stage in the function.
            uint256 twos = denominator & (~denominator + 1);
            assembly {
                // Divide denominator by twos.
                denominator := div(denominator, twos)

                // Divide [prod1 prod0] by twos.
                prod0 := div(prod0, twos)

                // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
                twos := add(div(sub(0, twos), twos), 1)
            }

            // Shift in bits from prod1 into prod0.
            prod0 |= prod1 * twos;

            // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
            // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
            // four bits. That is, denominator * inv = 1 mod 2^4.
            uint256 inverse = (3 * denominator) ^ 2;

            // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works
            // in modular arithmetic, doubling the correct bits in each step.
            inverse *= 2 - denominator * inverse; // inverse mod 2^8
            inverse *= 2 - denominator * inverse; // inverse mod 2^16
            inverse *= 2 - denominator * inverse; // inverse mod 2^32
            inverse *= 2 - denominator * inverse; // inverse mod 2^64
            inverse *= 2 - denominator * inverse; // inverse mod 2^128
            inverse *= 2 - denominator * inverse; // inverse mod 2^256

            // Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
            // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
            // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
            // is no longer required.
            result = prod0 * inverse;
            return result;
        }
    }

    /**
     * @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
     */
    function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {
        uint256 result = mulDiv(x, y, denominator);
        if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {
            result += 1;
        }
        return result;
    }

    /**
     * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.
     *
     * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
     */
    function sqrt(uint256 a) internal pure returns (uint256) {
        if (a == 0) {
            return 0;
        }

        // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
        //
        // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
        // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.
        //
        // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`
        // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`
        // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`
        //
        // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.
        uint256 result = 1 << (log2(a) >> 1);

        // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
        // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
        // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
        // into the expected uint128 result.
        unchecked {
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            result = (result + a / result) >> 1;
            return min(result, a / result);
        }
    }

    /**
     * @notice Calculates sqrt(a), following the selected rounding direction.
     */
    function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = sqrt(a);
            return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 2, rounded down, of a positive value.
     * Returns 0 if given 0.
     */
    function log2(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >> 128 > 0) {
                value >>= 128;
                result += 128;
            }
            if (value >> 64 > 0) {
                value >>= 64;
                result += 64;
            }
            if (value >> 32 > 0) {
                value >>= 32;
                result += 32;
            }
            if (value >> 16 > 0) {
                value >>= 16;
                result += 16;
            }
            if (value >> 8 > 0) {
                value >>= 8;
                result += 8;
            }
            if (value >> 4 > 0) {
                value >>= 4;
                result += 4;
            }
            if (value >> 2 > 0) {
                value >>= 2;
                result += 2;
            }
            if (value >> 1 > 0) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 2, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log2(value);
            return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 10, rounded down, of a positive value.
     * Returns 0 if given 0.
     */
    function log10(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >= 10 ** 64) {
                value /= 10 ** 64;
                result += 64;
            }
            if (value >= 10 ** 32) {
                value /= 10 ** 32;
                result += 32;
            }
            if (value >= 10 ** 16) {
                value /= 10 ** 16;
                result += 16;
            }
            if (value >= 10 ** 8) {
                value /= 10 ** 8;
                result += 8;
            }
            if (value >= 10 ** 4) {
                value /= 10 ** 4;
                result += 4;
            }
            if (value >= 10 ** 2) {
                value /= 10 ** 2;
                result += 2;
            }
            if (value >= 10 ** 1) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 10, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log10(value);
            return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);
        }
    }

    /**
     * @dev Return the log in base 256, rounded down, of a positive value.
     * Returns 0 if given 0.
     *
     * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
     */
    function log256(uint256 value) internal pure returns (uint256) {
        uint256 result = 0;
        unchecked {
            if (value >> 128 > 0) {
                value >>= 128;
                result += 16;
            }
            if (value >> 64 > 0) {
                value >>= 64;
                result += 8;
            }
            if (value >> 32 > 0) {
                value >>= 32;
                result += 4;
            }
            if (value >> 16 > 0) {
                value >>= 16;
                result += 2;
            }
            if (value >> 8 > 0) {
                result += 1;
            }
        }
        return result;
    }

    /**
     * @dev Return the log in base 256, following the selected rounding direction, of a positive value.
     * Returns 0 if given 0.
     */
    function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
        unchecked {
            uint256 result = log256(value);
            return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);
        }
    }
}
合同源代码
文件 10 的 11:PlatformFee.sol
// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.0;

/// @author thirdweb

import "./interface/IPlatformFee.sol";

/**
 *  @title   Platform Fee
 *  @notice  Thirdweb's `PlatformFee` is a contract extension to be used with any base contract. It exposes functions for setting and reading
 *           the recipient of platform fee and the platform fee basis points, and lets the inheriting contract perform conditional logic
 *           that uses information about platform fees, if desired.
 */

abstract contract PlatformFee is IPlatformFee {
    /// @dev The sender is not authorized to perform the action
    error PlatformFeeUnauthorized();

    /// @dev The recipient is invalid
    error PlatformFeeInvalidRecipient(address recipient);

    /// @dev The fee bps exceeded the max value
    error PlatformFeeExceededMaxFeeBps(uint256 max, uint256 actual);

    /// @dev The address that receives all platform fees from all sales.
    address private platformFeeRecipient;

    /// @dev The % of primary sales collected as platform fees.
    uint16 private platformFeeBps;

    /// @dev Fee type variants: percentage fee and flat fee
    PlatformFeeType private platformFeeType;

    /// @dev The flat amount collected by the contract as fees on primary sales.
    uint256 private flatPlatformFee;

    /// @dev Returns the platform fee recipient and bps.
    function getPlatformFeeInfo() public view override returns (address, uint16) {
        return (platformFeeRecipient, uint16(platformFeeBps));
    }

    /// @dev Returns the platform fee bps and recipient.
    function getFlatPlatformFeeInfo() public view returns (address, uint256) {
        return (platformFeeRecipient, flatPlatformFee);
    }

    /// @dev Returns the platform fee type.
    function getPlatformFeeType() public view returns (PlatformFeeType) {
        return platformFeeType;
    }

    /**
     *  @notice         Updates the platform fee recipient and bps.
     *  @dev            Caller should be authorized to set platform fee info.
     *                  See {_canSetPlatformFeeInfo}.
     *                  Emits {PlatformFeeInfoUpdated Event}; See {_setupPlatformFeeInfo}.
     *
     *  @param _platformFeeRecipient   Address to be set as new platformFeeRecipient.
     *  @param _platformFeeBps         Updated platformFeeBps.
     */
    function setPlatformFeeInfo(address _platformFeeRecipient, uint256 _platformFeeBps) external override {
        if (!_canSetPlatformFeeInfo()) {
            revert PlatformFeeUnauthorized();
        }
        _setupPlatformFeeInfo(_platformFeeRecipient, _platformFeeBps);
    }

    /// @dev Sets the platform fee recipient and bps
    function _setupPlatformFeeInfo(address _platformFeeRecipient, uint256 _platformFeeBps) internal {
        if (_platformFeeBps > 10_000) {
            revert PlatformFeeExceededMaxFeeBps(10_000, _platformFeeBps);
        }
        if (_platformFeeRecipient == address(0)) {
            revert PlatformFeeInvalidRecipient(_platformFeeRecipient);
        }

        platformFeeBps = uint16(_platformFeeBps);
        platformFeeRecipient = _platformFeeRecipient;

        emit PlatformFeeInfoUpdated(_platformFeeRecipient, _platformFeeBps);
    }

    /// @notice Lets a module admin set a flat fee on primary sales.
    function setFlatPlatformFeeInfo(address _platformFeeRecipient, uint256 _flatFee) external {
        if (!_canSetPlatformFeeInfo()) {
            revert PlatformFeeUnauthorized();
        }

        _setupFlatPlatformFeeInfo(_platformFeeRecipient, _flatFee);
    }

    /// @dev Sets a flat fee on primary sales.
    function _setupFlatPlatformFeeInfo(address _platformFeeRecipient, uint256 _flatFee) internal {
        flatPlatformFee = _flatFee;
        platformFeeRecipient = _platformFeeRecipient;

        emit FlatPlatformFeeUpdated(_platformFeeRecipient, _flatFee);
    }

    /// @notice Lets a module admin set platform fee type.
    function setPlatformFeeType(PlatformFeeType _feeType) external {
        if (!_canSetPlatformFeeInfo()) {
            revert PlatformFeeUnauthorized();
        }
        _setupPlatformFeeType(_feeType);
    }

    /// @dev Sets platform fee type.
    function _setupPlatformFeeType(PlatformFeeType _feeType) internal {
        platformFeeType = _feeType;

        emit PlatformFeeTypeUpdated(_feeType);
    }

    /// @dev Returns whether platform fee info can be set in the given execution context.
    function _canSetPlatformFeeInfo() internal view virtual returns (bool);
}
合同源代码
文件 11 的 11:ReentrancyGuard.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)

pragma solidity ^0.8.23;

/**
 * @dev Contract module that helps prevent reentrant calls to a function.
 *
 * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
 * available, which can be applied to functions to make sure there are no nested
 * (reentrant) calls to them.
 *
 * Note that because there is a single `nonReentrant` guard, functions marked as
 * `nonReentrant` may not call one another. This can be worked around by making
 * those functions `private`, and then adding `external` `nonReentrant` entry
 * points to them.
 *
 * TIP: If you would like to learn more about reentrancy and alternative ways
 * to protect against it, check out our blog post
 * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
 */
abstract contract ReentrancyGuard {
    // Booleans are more expensive than uint256 or any type that takes up a full
    // word because each write operation emits an extra SLOAD to first read the
    // slot's contents, replace the bits taken up by the boolean, and then write
    // back. This is the compiler's defense against contract upgrades and
    // pointer aliasing, and it cannot be disabled.

    // The values being non-zero value makes deployment a bit more expensive,
    // but in exchange the refund on every call to nonReentrant will be lower in
    // amount. Since refunds are capped to a percentage of the total
    // transaction's gas, it is best to keep them low in cases like this one, to
    // increase the likelihood of the full refund coming into effect.
    uint256 private constant _NOT_ENTERED = 1;
    uint256 private constant _ENTERED = 2;

    uint256 private _status;

    constructor() {
        _status = _NOT_ENTERED;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and making it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        _nonReentrantBefore();
        _;
        _nonReentrantAfter();
    }

    function _nonReentrantBefore() private {
        // On the first call to nonReentrant, _status will be _NOT_ENTERED
        require(_status != _ENTERED, "ReentrancyGuard: reentrant call");

        // Any calls to nonReentrant after this point will fail
        _status = _ENTERED;
    }

    function _nonReentrantAfter() private {
        // By storing the original value once again, a refund is triggered (see
        // https://eips.ethereum.org/EIPS/eip-2200)
        _status = _NOT_ENTERED;
    }

    /**
     * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a
     * `nonReentrant` function in the call stack.
     */
    function _reentrancyGuardEntered() internal view returns (bool) {
        return _status == _ENTERED;
    }
}
设置
{
  "compilationTarget": {
    "contracts/ESH.sol": "ESH"
  },
  "evmVersion": "paris",
  "libraries": {},
  "metadata": {
    "bytecodeHash": "ipfs"
  },
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "remappings": []
}
ABI
[{"inputs":[{"internalType":"string","name":"_name","type":"string"},{"internalType":"string","name":"_symbol","type":"string"},{"internalType":"uint256","name":"_totalSupply","type":"uint256"},{"internalType":"address","name":"_contractOwner","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ContractMetadataUnauthorized","type":"error"},{"inputs":[{"internalType":"uint256","name":"max","type":"uint256"},{"internalType":"uint256","name":"actual","type":"uint256"}],"name":"PlatformFeeExceededMaxFeeBps","type":"error"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"}],"name":"PlatformFeeInvalidRecipient","type":"error"},{"inputs":[],"name":"PlatformFeeUnauthorized","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":false,"internalType":"uint256","name":"totalBalance","type":"uint256"}],"name":"BalanceDistributed","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"string","name":"prevURI","type":"string"},{"indexed":false,"internalType":"string","name":"newURI","type":"string"}],"name":"ContractURIUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"delegator","type":"address"},{"indexed":true,"internalType":"address","name":"fromDelegate","type":"address"},{"indexed":true,"internalType":"address","name":"toDelegate","type":"address"}],"name":"DelegateChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"delegate","type":"address"},{"indexed":false,"internalType":"uint256","name":"previousBalance","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newBalance","type":"uint256"}],"name":"DelegateVotesChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"id","type":"bytes32"}],"name":"DistributionCompleted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"id","type":"bytes32"},{"indexed":true,"internalType":"address","name":"creator","type":"address"}],"name":"DistributionCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32","name":"id","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"startIndex","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"endIndex","type":"uint256"}],"name":"DistributionExecuted","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"platformFeeRecipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"flatFee","type":"uint256"}],"name":"FlatPlatformFeeUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"platformFeeRecipient","type":"address"},{"indexed":false,"internalType":"uint256","name":"platformFeeBps","type":"uint256"}],"name":"PlatformFeeInfoUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"enum IPlatformFee.PlatformFeeType","name":"feeType","type":"uint8"}],"name":"PlatformFeeTypeUpdated","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":"INIT_BATCH_SIZE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_BATCH_SIZE","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newBATCHSIZE","type":"uint256"}],"name":"adjustBATCHSize","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_newINITBATCHSIZE","type":"uint256"}],"name":"adjustInitBATCHSize","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"nonpayable","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":"amount","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":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"burn","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"burnFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newOwner","type":"address"}],"name":"changeOwner","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"contractOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"contractURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"paymentToken","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"createDistribution","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"delegatee","type":"address"}],"name":"delegate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"delegates","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"distributionId","type":"bytes32"},{"internalType":"uint256","name":"batchSize","type":"uint256"}],"name":"distributeBatch","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"distributionId","type":"bytes32"},{"internalType":"uint256","name":"maxCalls","type":"uint256"}],"name":"distributeMulticall","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"distributionBalances","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"distributionHolders","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"distributionInitializationStarted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"distributionInitialized","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"distributionTotalBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"distributions","outputs":[{"internalType":"address","name":"paymentToken","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"},{"internalType":"uint8","name":"decimals","type":"uint8"},{"internalType":"uint256","name":"startIndex","type":"uint256"},{"internalType":"uint256","name":"totalBalance","type":"uint256"},{"internalType":"bool","name":"isCompleted","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"distributor1","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"distributor2","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"holder","type":"address"}],"name":"getAllHolderTokenBalances","outputs":[{"components":[{"internalType":"uint256","name":"balance","type":"uint256"},{"internalType":"string","name":"symbol","type":"string"}],"internalType":"struct ESH.TokenBalance[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getFlatPlatformFeeInfo","outputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"holder","type":"address"},{"internalType":"string","name":"symbol","type":"string"}],"name":"getHolderTokenBalance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getHolders","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"uint256","name":"blockNumber","type":"uint256"}],"name":"getPastVotes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPlatformFeeInfo","outputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getPlatformFeeType","outputs":[{"internalType":"enum IPlatformFee.PlatformFeeType","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"getVotes","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"distributionId","type":"bytes32"}],"name":"initializeDistribution","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"owners","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ownersCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"_uri","type":"string"}],"name":"setContractURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_platformFeeRecipient","type":"address"},{"internalType":"uint256","name":"_flatFee","type":"uint256"}],"name":"setFlatPlatformFeeInfo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_platformFeeRecipient","type":"address"},{"internalType":"uint256","name":"_platformFeeBps","type":"uint256"}],"name":"setPlatformFeeInfo","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"enum IPlatformFee.PlatformFeeType","name":"_feeType","type":"uint8"}],"name":"setPlatformFeeType","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_ERCUltraStore","type":"address"}],"name":"setRentingStoreContract","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_ERCUltraStore","type":"address"}],"name":"setSellerStoreContract","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":"amount","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":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"}]