ETH Price: $2,439.84 (-4.48%)
Gas: 0.28 Gwei

Transaction Decoder

Block:
20049293 at Jun-08-2024 07:47:35 PM +UTC
Transaction Fee:
0.014723788850734647 ETH $35.92
Gas Used:
1,416,991 Gas / 10.390883817 Gwei

Emitted Events:

26 0x6f11fb4d4178c5d5e3ee4bc7820d8cfed0b59ce7.0x00ed5939179dc194223f0edd1517ecee2210b22da7f82c8e4b1795e93b9f06aa( 0x00ed5939179dc194223f0edd1517ecee2210b22da7f82c8e4b1795e93b9f06aa, 0000000000000000000000000000000000000000000000000000000000000000, 00000000000000000000000046762bde09c1a1c566c3efd959368455bf20c354, 000000000000000000000000000000000000000000000000001550f7dca70000 )
27 0x148acd3cd4d6a17cd2abbecd0745b09b62c64f84.0x00ed5939179dc194223f0edd1517ecee2210b22da7f82c8e4b1795e93b9f06aa( 0x00ed5939179dc194223f0edd1517ecee2210b22da7f82c8e4b1795e93b9f06aa, 0x0000000000000000000000000000000000000000000000000000000000000000, 0x00000000000000000000000046762bde09c1a1c566c3efd959368455bf20c354, 000000000000000000000000000000000000000000000000001550f7dca70000 )
28 ERC20Token.Transfer( from=0x0000000000000000000000000000000000000000, to=0x46762bdE09C1a1c566c3efD959368455Bf20c354, value=2191200 )
29 0xd856f0f9efa054896fe3596e05978bbe686de131.0xdfdcfe14b965674fff33e543e57c9e0150c14e72485a82b8ee0d20bf1f243a0b( 0xdfdcfe14b965674fff33e543e57c9e0150c14e72485a82b8ee0d20bf1f243a0b, 0x00000000000000000000000000000000000000000000000000000000000000d6, 0xb483afd3f4caedc6eebf44246fe54e38c95e3179a5ec9ea81740eca5b482d12e, 0xd724d9c2f62549b9d81846f9a9a1a2756834829a4b1c2e52f04e8ceacade59db, 0000000000000000000000000000000000000000000000000000000000000100, 0000000000000000000000000000000000000000000000000000000000000140, 0000000000000000000000000000000000000000000000000000000000000180, 00000000000000000000000000000000000000000000000000000000000001c0, 0000000000000000000000000000000000000000000000000000000000000200, 0000000000000000000000000000000000000000000000000000000000000001, 000000000000000000000000000000000000000000000000000000000131f52d, 00000000000000000000000000000000000000000000000017d6ca1c55c08bc0, 0000000000000000000000000000000000000000000000000000000000000008, 7472616e73666572000000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000009, 6368616e6e656c2d320000000000000000000000000000000000000000000000, 0000000000000000000000000000000000000000000000000000000000000008, 7472616e73666572000000000000000000000000000000000000000000000000, 000000000000000000000000000000000000000000000000000000000000000a, 6368616e6e656c2d353200000000000000000000000000000000000000000000, 000000000000000000000000000000000000000000000000000000000000016b, 7b22616d6f756e74223a2232313931323030222c2264656e6f6d223a22747261, 6e736665722f6368616e6e656c2d322f7472616e736665722f6368616e6e656c, 2d352f73747561746f6d222c226d656d6f223a227b5c22666f72776172645c22, 3a7b5c2272656365697665725c223a5c227374726964653165776d3937743571, 7733757574776439716830796479303037796d686c3871743072656530655c22, 2c5c22706f72745c223a5c227472616e736665725c222c5c226368616e6e656c, 5c223a5c226368616e6e656c2d355c222c5c2274696d656f75745c223a363030, 303030303030303030302c5c22726574726965735c223a307d7d222c22726563, 6569766572223a22706963613165776d39377435717733757574776439716830, 796479303037796d686c387174683536716c6a222c2273656e646572223a2230, 7834363736326264653039633161316335363663336566643935393336383435, 356266323063333534227d000000000000000000000000000000000000000000 )

Account State Difference:

  Address   Before After State Difference Code
0x46762bdE...5Bf20c354 0.194872300202949428 Eth0.200872300202949428 Eth0.006
0x6c57e54C...B35AC2CB9
(IBC Protocol: Relayer)
0.961820328328277612 Eth
Nonce: 1239
0.947096539477542965 Eth
Nonce: 1240
0.014723788850734647
0x6f11fb4D...ED0b59ce7 0.78362280492 Eth0.77762280492 Eth0.006
(beaverbuild)
6.480409426267650474 Eth6.484660399267650474 Eth0.004250973
0xA534115D...5189a1de2
0xd856f0f9...e686De131

Execution Trace

0xd856f0f9efa054896fe3596e05978bbe686de131.6de049d6( )
  • 0xa5111b33e465db832ad8ee040c2a8d01cf26f833.6de049d6( )
    • 0xd856f0f9efa054896fe3596e05978bbe686de131.aa18c8b1( )
      • 0xebc4ddeca969572e4891dc2e0e0c7a9c5f2d06fa.aa18c8b1( )
        • 0xa3837753d4599eb6b089ded840cfff63da0f3314.329681d0( )
          • 0xdfe34b77af654394add0a6426ebe8aecc2e58dce.329681d0( )
          • 0xa3837753d4599eb6b089ded840cfff63da0f3314.4b0bbdc4( )
            • 0xdfe34b77af654394add0a6426ebe8aecc2e58dce.4b0bbdc4( )
            • Null: 0x000...002.7b22616d( )
            • Null: 0x000...002.17d6ca1c( )
            • 0xa3837753d4599eb6b089ded840cfff63da0f3314.4d2fdeb8( )
              • 0xdfe34b77af654394add0a6426ebe8aecc2e58dce.4d2fdeb8( )
                • 0x57f7457d9c4849f4babdb43c84aaa10445b7fb6b.5c45ddd8( )
                • 0x148acd3cd4d6a17cd2abbecd0745b09b62c64f84.52c7157d( )
                  • 0xa919ad106495cb566dd08daa132e054845716724.52c7157d( )
                    • 0x5933fde9fa60d4f1c0124aa7a7a988f46ba42d78.STATICCALL( )
                    • 0x6f11fb4d4178c5d5e3ee4bc7820d8cfed0b59ce7.07b18bde( )
                    • 0x5933fde9fa60d4f1c0124aa7a7a988f46ba42d78.ba7aef43( )
                      // SPDX-License-Identifier: Apache-2.0
                      pragma solidity ^0.8.0;
                      import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
                      import "@openzeppelin/contracts/access/Ownable.sol";
                      /**
                       * @title ERC20Token
                       * @dev Implementation of the ERC20 interface with customizable token properties.
                       * This contract extends the ERC20 standard with the ability for the contract owner to
                       * modify token name, symbol, and decimals after deployment. It also includes minting
                       * and burning functionalities controlled by the contract owner.
                       */
                      contract ERC20Token is ERC20, Ownable {
                          uint8 private _decimals;
                          string private _name;
                          string private _symbol;
                          bool private _isDecimalsSet;
                          uint256 constant internal MAX_DECIMALS = 77; // log10(2^256 - 1)
                          /**
                           * @dev emitted when the decimals are changed by the owner.
                           */
                          event SetDecimals(uint8 precision);
                          /**
                           * @dev emitted when the name is changed by the owner.
                           */
                          event SetName(string name);
                          /**
                           * @dev emitted when the symbol is changed by the owner.
                           */
                          event SetSymbol(string symbol);
                          /**
                           * @dev Constructor for initializing the ERC20Token contract Sets the owner of the contract
                           *      to the deployer of the contract. Mints the initial supply of tokens to the deployer.
                           *
                           *      Reverts if the number of decimal places is greater than `MAX_DECIMALS`.
                           * @param initialName The name of the token.
                           * @param initialSymbol The symbol of the token.
                           * @param initSupply The initial supply of tokens to mint upon contract deployment.
                           * @param initialDecimals The number of decimal places for the token.
                           */
                          constructor(string memory initialName, string memory initialSymbol, uint256 initSupply, uint8 initialDecimals)
                          ERC20(initialName, initialSymbol)
                          Ownable(_msgSender())
                          {
                              _mint(_msgSender(), initSupply);
                              _decimals = initialDecimals;
                              _name = initialName;
                              _symbol = initialSymbol;
                              _isDecimalsSet = false;
                              require(initialDecimals <= MAX_DECIMALS, "ERC20Token: precision too high");
                          }
                          /**
                           * @notice Mint new tokens.
                           * @dev Mint new tokens to the specified account. Only the owner can call this function.
                           *      A `Transfer` event is emitted from the internal `_mint` function.
                           * @param account The account to mint the tokens to.
                           * @param amount The amount of tokens to mint.
                           */
                          function mint(address account, uint256 amount) external onlyOwner {
                              _mint(account, amount);
                          }
                          /**
                           * @notice Burn tokens.
                           * @dev Burn tokens from the specified account. Only the owner can call this function.
                           *      A `Transfer` event is emitted from the internal `_burn` function.
                           * @param account The account to burn the tokens from.
                           * @param amount The amount of tokens to burn.
                           */
                          function burn(address account, uint256 amount) external onlyOwner {
                              _burn(account, amount);
                          }
                          /**
                           * @notice Set the number of decimal places for the token.
                           * @dev Set the number of decimal places for the token. Only the owner can call this function.
                           *
                           * Reverts if one of the following is true:
                           *   - the number of decimal places is already set.
                           *   - the new number of decimal places is greater than `MAX_DECIMALS`.
                           * @param newDecimals The number of decimal places for the token.
                           */
                          function setDecimals(uint8 newDecimals) external onlyOwner {
                              require(!_isDecimalsSet, "ERC20Token: decimals is already set");
                              require(newDecimals <= MAX_DECIMALS, "ERC20Token: precision too high");
                              _decimals = newDecimals;
                              _isDecimalsSet = true;
                              emit SetDecimals(newDecimals);
                          }
                          /**
                           * @notice Set the name of the token.
                           * @dev Set the name of the token. Only the owner can call this function.
                           * @param newName The name of the token.
                           */
                          function setName(string memory newName) external onlyOwner {
                              _name = newName;
                              emit SetName(newName);
                          }
                          /**
                           * @notice Set the symbol of the token.
                           * @dev Set the symbol of the token. Only the owner can call this function.
                           * @param newSymbol The symbol of the token.
                           */
                          function setSymbol(string memory newSymbol) external onlyOwner {
                              _symbol = newSymbol;
                              emit SetSymbol(newSymbol);
                          }
                          /**
                           * @notice Get the number of decimal places for the token.
                           * @return The number of decimal places for the token.
                           */
                          function decimals() public view virtual override returns (uint8) {
                              return _decimals;
                          }
                          /**
                           * @notice Get the name of the token.
                           * @return The name of the token.
                           */
                          function name() public view virtual override returns (string memory) {
                              return _name;
                          }
                          /**
                           * @notice Get the symbol of the token.
                           * @return The symbol of the token.
                           */
                          function symbol() public view virtual override returns (string memory) {
                              return _symbol;
                          }
                      }
                      // 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.0.0) (interfaces/draft-IERC6093.sol)
                      pragma solidity ^0.8.20;
                      /**
                       * @dev Standard ERC20 Errors
                       * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC20 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 ERC721 Errors
                       * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC721 tokens.
                       */
                      interface IERC721Errors {
                          /**
                           * @dev Indicates that an address can't be an owner. For example, `address(0)` is a forbidden owner in EIP-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 ERC1155 Errors
                       * Interface of the https://eips.ethereum.org/EIPS/eip-6093[ERC-6093] custom errors for ERC1155 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.0.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 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.
                       */
                      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}.
                           *
                           * 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_;
                          }
                          /**
                           * @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}.
                           *
                           * 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 `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:
                           * ```
                           * 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.0.0) (token/ERC20/IERC20.sol)
                      pragma solidity ^0.8.20;
                      /**
                       * @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 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.0.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 ERC20 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.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;
                          }
                      }