// Contract: Kaomojis
// Target function: function createDutchAuction
getElapsedAuctionTime() internal view returns (uint256) {
        return startTime > 0 ? block.timestamp - startTime : 0;
    }

    /**
     * @dev returns the remaining time until a Dutch auction's resting price is
     *  hit. If the sale has not started yet, the auction duration is returned.
     *
     * Returning "0" shows the price has reached its final value - the auction
     *  may still be biddable.
     *
     * Use _endAuction() to stop the auction and prevent further bids.
     */
    function getRemainingSaleTime() external view returns (uint256) {
        if (startTime == 0) {
            // not started yet
            return duration;
        } else if (_getElapsedAuctionTime() >= duration) {
            // already at the resting price
            return 0;
        }

        return (startTime + duration) - block.timestamp;
    }

    /**
     * @dev calculates the current Dutch auction price. If not begun, returns
     *  the start price. Returns the calculated auction price or finalPrice,
     *  whichever is greatest.
     */
    function getAuctionPrice() public view returns (uint256) {
        uint256 elapsed = _getElapsedAuctionTime();

        if (elapsed >= duration) {
            return finalPrice;
        }

        // step function
        uint256 steps = elapsed / timeStepSeconds;
        uint256 auctionPriceDecrease = steps * priceStep;
        uint256 auctionPrice = startPrice - auctionPriceDecrease;

        return auctionPrice;
    }
}


















pragma solidity ^0.8.4;
/**
 * @title ERC721AQueryable.
 *
 * @dev ERC721A subclass with convenience query functions.
 */
abstract contract ERC721AQueryable is ERC721A, IERC721AQueryable {
    /**
     * @dev Returns the `TokenOwnership` struct at `tokenId` without reverting.
     *
     * If the `tokenId` is out of bounds:
     *
     * - `addr = address(0)`
     * - `startTimestamp = 0`
     * - `burned = false`
     * - `extraData = 0`
     *
     * If the `tokenId` is burned:
     *
     * - `addr = <Address of owner before token was burned>`
     * - `startTimestamp = <Timestamp when token was burned>`
     * - `burned = true`
     * - `extraData = <Extra data when token was burned>`
     *
     * Otherwise:
     *
     * - `addr = <Address of owner>`
     * - `startTimestamp = <Timestamp of start of ownership>`
     * - `burned = false`
     * - `extraData = <Extra data at start of ownership>`
     */
    function explicitOwnershipOf(uint256 tokenId) public view virtual override returns (TokenOwnership memory) {
        TokenOwnership memory ownership;
        if (tokenId < _startTokenId() || tokenId >= _nextTokenId()) {
            return ownership;
        }
        ownership = _ownershipAt(tokenId);
        if (ownership.burned) {
            return ownership;
        }
        return _ownershipOf(tokenId);
    }

    /**
     * @dev Returns an array of `TokenOwnership` structs at `tokenIds` in order.
     * See {ERC721AQueryable-explicitOwnershipOf}
     */
    function explicitOwnershipsOf(uint256[] calldata tokenIds)
        external
        view
        virtual
        override
        returns (TokenOwnership[] memory)
    {
        unchecked {
            uint256 tokenIdsLength = tokenIds.length;
            TokenOwnership[] memory ownerships = new TokenOwnership[](tokenIdsLength);
            for (uint256 i; i != tokenIdsLength; ++i) {
                ownerships[i] = explicitOwnershipOf(tokenIds[i]);
            }
            return ownerships;
        }
    }

    /**
     * @dev Returns an array of token IDs owned by `owner`,
     * in the range [`start`, `stop`)
     * (i.e. `start <= tokenId < stop`).
     *
     * This function allows for tokens to be queried if the collection
     * grows too big for a single call of {ERC721AQueryable-tokensOfOwner}.
     *
     * Requirements:
     *
     * - `start < stop`
     */
    function tokensOfOwnerIn(
        address owner,
        uint256 start,
        uint256 stop
    ) external view virtual override returns (uint256[] memory) {
        unchecked {
            if (start >= stop) revert InvalidQueryRange();
            uint256 tokenIdsIdx;
            uint256 stopLimit = _nextTokenId();
            // Set `start = max(start, _startTokenId())`.
            if (start < _startTokenId()) {
                start = _startTokenId();
            }
            // Set `stop = min(stop, stopLimit)`.
            if (stop > stopLimit) {
                stop = stopLimit;
            }
            uint256 tokenIdsMaxLength = balanceOf(owner);
            // Set `tokenIdsMaxLength = min(balanceOf(owner), stop - start)`,
            // to cater for cases where `balanceOf(owner)` is too big.
            if (start < stop) {
                uint256 rangeLength = stop - start;
                if (rangeLength < tokenIdsMaxLength) {
                    tokenIdsMaxLength = rangeLength;
                }
            } else {
                tokenIdsMaxLength = 0;
            }
            uint256[] memory tokenIds = new uint256[](tokenIdsMaxLength);
            if (tokenIdsMaxLength == 0) {
                return tokenIds;
            }
            // We need to call `explicitOwnershipOf(start)`,
            // because the slot at `start` may not be initialized.
            TokenOwnership memory ownership = explicitOwnershipOf(start);
            address currOwnershipAddr;
            // If the starting slot exists (i.e. not burned), initialize `currOwnershipAddr`.
            // `ownership.address` will not be zero, as `start` is clamped to the valid token ID range.
            if (!ownership.burned) {
                currOwnershipAddr = ownership.addr;
            }
            for (uint256 i = start; i != stop && tokenIdsIdx != tokenIdsMaxLength; ++i) {
                ownership = _ownershipAt(i);
                if (ownership.burned) {
                    continue;
                }
                if (ownership.addr != address(0)) {
                    currOwnershipAddr = ownership.addr;
                }
                if (currOwnershipAddr == owner) {
                    tokenIds[tokenIdsIdx++] = i;
                }
            }
            // Downsize the array to fit.
            assembly {
                mstore(tokenIds, tokenIdsIdx)
            }
            return tokenIds;
        }
    }

    /**
     * @dev Returns an array of token IDs owned by `owner`.
     *
     * This function scans the ownership mapping and is O(`totalSupply`) in complexity.
     * It is meant to be called off-chain.
     *
     * See {ERC721AQueryable-tokensOfOwnerIn} for splitting the scan into
     * multiple smaller scans if the collection is large enough to cause
     * an out-of-gas error (10K collections should be fine).
     */
    function tokensOfOwner(address owner) external view virtual override returns (uint256[] memory) {
        unchecked {
            uint256 tokenIdsIdx;
            address currOwnershipAddr;
            uint256 tokenIdsLength = balanceOf(owner);
            uint256[] memory tokenIds = new uint256[](tokenIdsLength);
            TokenOwnership memory ownership;
            for (uint256 i = _startTokenId(); tokenIdsIdx != tokenIdsLength; ++i) {
                ownership = _ownershipAt(i);
                if (ownership.burned) {
                    continue;
                }
                if (ownership.addr != address(0)) {
                    currOwnershipAddr = ownership.addr;
                }
                if (currOwnershipAddr == owner) {
                    tokenIds[tokenIdsIdx++] = i;
                }
            }
            return tokenIds;
        }
    }
}








pragma solidity ^0.8.12;
abstract contract ERC721AOpensea is
    ERC721AQueryable,
    OperatorFilterer,
    Ownable
{
    bool public operatorFilteringEnabled;

    constructor() {
        _registerForOperatorFiltering();
        operatorFilteringEnabled = true;
    }

    /***************************************************************************
     * Operator Filterer
     */

    function setApprovalForAll(address operator, bool approved)
        public
        override(IERC721A, ERC721A)
        onlyAllowedOperatorApproval(operator)
    {
        super.setApprovalForAll(operator, approved);
    }

    function approve(address operator, uint256 tokenId)
        public
        payable
        override(IERC721A, ERC721A)
        onlyAllowedOperatorApproval(operator)
    {
        super.approve(operator, tokenId);
    }

    function transferFrom(
        address from,
        address to,
        uint256 tokenId
    ) public payable override(IERC721A, ERC721A) onlyAllowedOperator(from) {
        super.transferFrom(from, to, tokenId);
    }

    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId
    ) public payable override(IERC721A, ERC721A) onlyAllowedOperator(from) {
        super.safeTransferFrom(from, to, tokenId);
    }

    function safeTransferFrom(
        address from,
        address to,
        uint256 tokenId,
        bytes memory data
    ) public payable override(IERC721A, ERC721A) onlyAllowedOperator(from) {
        super.safeTransferFrom(from, to, tokenId, data);
    }

    function supportsInterface(bytes4 interfaceId)
        public
        view
        virtual
        override(IERC721A, ERC721A)
        returns (bool)
    {
        // Supports the following `interfaceId`s:
        // - IERC165: 0x01ffc9a7
        // - IERC721: 0x80ac58cd
        // - IERC721Metadata: 0x5b5e139f
        return ERC721A.supportsInterface(interfaceId);
    }

    function setOperatorFilteringEnabled(bool value) public onlyOwner {
        operatorFilteringEnabled = value;
    }

    function _operatorFilteringEnabled() internal view override returns (bool) {
        return operatorFilteringEnabled;
    }

    function _isPriorityOperator(address operator)
        internal
        pure
        override
        returns (bool)
    {
        // OpenSea Seaport Conduit:
        // https://etherscan.io/address/0x1E0049783F008A0085193E00003D00cd54003c71
        // https://goerli.etherscan.io/address/0x1E0049783F008A0085193E00003D00cd54003c71
        return operator == address(0x1E0049783F008A0085193E00003D00cd54003c71);
    }
}




// ******************************************************************************************************************************************
// ******************************************************************************************************************************************
// ******************************************************************************************************************************************
/*                                                                                       
#                     ▄█   ▄█▄    ▄████████  ▄██████▄    ▄▄▄▄███▄▄▄▄    ▄██████▄       ▄█  ▄█     ▄████████     
#                     ███ ▄███▀   ███    ███ ███    ███ ▄██▀▀▀███▀▀▀██▄ ███    ███     ███ ███    ███    ███     
#                     ███▐██▀     ███    ███ ███    ███ ███   ███   ███ ███    ███     ███ ███▌   ███    █▀      
#                    ▄█████▀      ███    ███ ███    ███ ███   ███   ███ ███    ███     ███ ███▌   ███            
#                   ▀▀█████▄    ▀███████████ ███    ███ ███   ███   ███ ███    ███     ███ ███▌ ▀███████████     
#                     ███▐██▄     ███    ███ ███    ███ ███   ███   ███ ███    ███     ███ ███           ███     
#                     ███ ▀███▄   ███    ███ ███    ███ ███   ███   ███ ███    ███     ███ ███     ▄█    ███     
#                     ███   ▀█▀   ███    █▀   ▀██████▀   ▀█   ███   █▀   ▀██████▀  █▄ ▄███ █▀    ▄████████▀      
#                     ▀                                                            ▀▀▀▀▀▀                        
#                                                                                                                                                                                                                          
#                                                                                                                                
#                              ███████╗████████╗██╗  ██╗███████╗██████╗ ███████╗██╗   ██╗███╗   ███╗                
#                              ██╔════╝╚══██╔══╝██║  ██║██╔════╝██╔══██╗██╔════╝██║   ██║████╗ ████║                
#              █████╗█████╗    █████╗     ██║   ███████║█████╗  ██████╔╝█████╗  ██║   ██║██╔████╔██║    █████╗█████╗
#              ╚════╝╚════╝    ██╔══╝     ██║   ██╔══██║██╔══╝  ██╔══██╗██╔══╝  ██║   ██║██║╚██╔╝██║    ╚════╝╚════╝
#                              ███████╗   ██║   ██║  ██║███████╗██║  ██║███████╗╚██████╔╝██║ ╚═╝ ██║                
#                              ╚══════╝   ╚═╝   ╚═╝  ╚═╝╚══════╝╚═╝  ╚═╝╚══════╝ ╚═════╝ ╚═╝     ╚═╝  
#              
#                       $$$$$$$$\  $$$$$$\  $$\   $$\ $$$$$$$$\        $$$$$$\  $$\    $$\ $$$$$$$$\ $$$$$$$\                 
#                       \__$$  __|$$  __$$\ $$ | $$  |$$  _____|      $$  __$$\ $$ |   $$ |$$  _____|$$  __$$\                
#                          $$ |   $$ /  $$ |$$ |$$  / $$ |            $$ /  $$ |$$ |   $$ |$$ |      $$ |  $$ |               
#                          $$ |   $$$$$$$$ |$$$$$  /  $$$$$\          $$ |  $$ |\$$\  $$  |$$$$$\    $$$$$$$ /      
#                          $$ |   $$  __$$ |$$  $$<   $$  __|         $$ |  $$ | \$$\$$  / $$  __|   $$  __$$<          
#                          $$ |   $$ |  $$ |$$ |\$$\  $$ |            $$ |  $$ |  \$$$  /  $$ |      $$ |  $$ |               
#                          $$ |   $$ |  $$ |$$ | \$$\ $$$$$$$$\        $$$$$$  |   \$  /   $$$$$$$$\ $$ |  $$ |               
#                          \__|   \__|  \__|\__|  \__|\________|       \______/     \_/    \________|\__|  \__|   
# ⫙σηiϝέ$t Ἴͳ           
*/                                                                                      
// ******************************************************************************************************************************************
// ******************************************************************************************************************************************
// ******************************************************************************************************************************************



pragma solidity ^0.8.17;
contract Kaomojis is ERC2981, ReentrancyGuard, Ownable, SteppedDutchAuction, ERC721AOpensea {
  // State Vars
  uint16 public constant AUCTION_SUPPLY = 900;
  uint8 public constant MAX_TOKENS_PER_PURCHASE = 5;
  uint8 public constant FREE_MINT_SUPPLY = 100;
  uint8 public constant DEV_MINT_SUPPLY = 50;

  uint8 public freeMintedSupply; // Track freeMint() supply
  uint8 public devMintedSupply; // Track devMint() supply

  string private _baseURIextended;
  string public provenance;
   

  // =============================================================
  //                   CUSTOM ERRORS
  // =============================================================
  /// not accepting mints from contracts on the Dutch Auction
  error NoContractMinting();

  /// Exceeds maximum tokens per transaction
  error ExceedsMaximumTokensPerTransaction();

  /// The wrong ETH value has been sent with a transaction
  error WrongETHValueSent();

  /// refund of excess payment failed
  error RefundFailed();


  // =============================================================
  //                   EVENTS
  // =============================================================
  /**
  * @dev emit when a user mints on the Dutch auction
  * @param userAddress the minting wallet and token recipient
  * @param numberOfTokens the quantity of tokens purchased
  */
  event DutchAuctionMint(address indexed userAddress, uint256 numberOfTokens);


  // =============================================================
  //                   FUNCTIONS
  // =============================================================
  constructor()
      ERC721A("Kaomoji", "KAOMOJIS")
      ERC721AOpensea()
  {
    // TΔΚξ ⨀VξR
  }
  

  // #####################
  // STEPPED DUTCH AUCTION
  // #####################
  /**
  * @notice initialize a new Dutch auction. Price will step down in fixed
  *  amounts, at fixed time intervals, until it hits the final resting price,
  *  where it remains until the auction is ended
  *
  * @dev if the prices do not divide perfectly, the final price step will be
  *  smaller than the rest, i.e. it will stop at finalPrice_.
  *  NOTE calling this multiple times will overwrite the previous parameters.
  *  See {_createNewAuction() in SteppedDutchAuction.sol}