pragma solidity ^0.8.0;









contract Market is OwnableContract, ReentrancyGuardUpgradeable, IMarket {
    uint64 private constant E5 = 1e5;
    mapping(address => mapping(uint256 => Lending)) internal lendingMap;
    mapping(address => mapping(uint256 => address)) internal privateOrderMap;
    mapping(address => mapping(uint256 => PaymentNormal))
        internal paymentNormalMap;
    mapping(address => mapping(address => uint256)) internal royaltyMap;
    mapping(address => uint256) public balanceOfFee;
    address payable public beneficiary;
    uint256 private fee;
    uint64 public maxIndate;
    bool public isPausing;
    bool public supportERC20;

    function initialize(address owner_, address admin_) public initializer {
        __ReentrancyGuard_init();
        initOwnableContract(owner_, admin_);
        maxIndate = 365 days;
        fee = 2500;
    }

    function onlyApprovedOrOwner(
        address spender,
        address nftAddress,
        uint256 nftId
    ) internal view {
        address _owner = ERC721(nftAddress).ownerOf(nftId);
        require(
            spender == _owner ||
                ERC721(nftAddress).getApproved(nftId) == spender ||
                ERC721(nftAddress).isApprovedForAll(_owner, spender),
            "only approved or owner"
        );
    }

    modifier whenNotPaused() {
        require(!isPausing, "is pausing");
        _;
    }

    function mintAndCreateLendOrder(
        address doNftAddress,
        uint256 oNftId,
        uint64 maxEndTime,
        uint64 minDuration,
        uint256 pricePerDay,
        address paymentToken
    ) public nonReentrant {
        uint256 nftId = _mintV(doNftAddress, oNftId, maxEndTime);
        createLendOrder(
            doNftAddress,
            nftId,
            maxEndTime,
            minDuration,
            pricePerDay,
            paymentToken
        );
    }

    function mintAndCreatePrivateLendOrder(
        address doNftAddress,
        uint256 oNftId,
        uint64 maxEndTime,
        uint64 minDuration,
        uint256 pricePerDay,
        address paymentToken,
        address renter,
        OrderType orderType
    ) public nonReentrant {
        uint256 nftId = _mintV(doNftAddress, oNftId, maxEndTime);
        createPrivateLendOrder(
            doNftAddress,
            nftId,
            maxEndTime,
            minDuration,
            pricePerDay,
            paymentToken,
            renter,
            orderType
        );
    }

    function _mintV(
        address doNftAddress,
        uint256 oNftId,
        uint64 maxEndTime
    ) internal returns (uint256 nftId) {
        address oNftAddress = IComplexDoNFT(doNftAddress)
            .getOriginalNftAddress();
        if (
            IERC165(oNftAddress).supportsInterface(type(IWrapNFT).interfaceId)
        ) {
            address gameNFTAddress = IWrapNFT(oNftAddress).originalAddress();
            bool isStaked = ERC721(gameNFTAddress).ownerOf(oNftId) ==
                oNftAddress;
            if (isStaked) {
                onlyApprovedOrOwner(msg.sender, oNftAddress, oNftId);
            } else {
                onlyApprovedOrOwner(msg.sender, gameNFTAddress, oNftId);
            }
        } else {
            onlyApprovedOrOwner(msg.sender, oNftAddress, oNftId);
        }
        require(maxEndTime > block.timestamp, "invalid maxEndTime");
        nftId = IComplexDoNFT(doNftAddress).mintVNft(oNftId);
    }

    function createLendOrder(
        address nftAddress,
        uint256 nftId,
        uint64 maxEndTime,
        uint64 minDuration,
        uint256 pricePerDay,
        address paymentToken
    ) public whenNotPaused {
        delete privateOrderMap[nftAddress][nftId];
        paymentNormalMap[nftAddress][nftId] = PaymentNormal(
            paymentToken,
            pricePerDay
        );
        _createLendOrder(
            nftAddress,
            nftId,
            maxEndTime,
            minDuration,
            pricePerDay,
            paymentToken,
            OrderType.Public,
            PaymentType.Normal,
            address(0)
        );
    }

    function createPrivateLendOrder(
        address nftAddress,
        uint256 nftId,
        uint64 maxEndTime,
        uint64 minDuration,
        uint256 pricePerDay,
        address paymentToken,
        address renter,
        OrderType orderType
    ) public whenNotPaused {
        privateOrderMap[nftAddress][nftId] = renter;
        paymentNormalMap[nftAddress][nftId] = PaymentNormal(
            paymentToken,
            pricePerDay
        );
        _createLendOrder(
            nftAddress,
            nftId,
            maxEndTime,
            minDuration,
            pricePerDay,
            paymentToken,
            orderType,
            PaymentType.Normal,
            renter
        );
    }

    function _createLendOrder(
        address nftAddress,
        uint256 nftId,
        uint64 maxEndTime,
        uint64 minDuration,
        uint256 pricePerDay,
        address paymentToken,
        OrderType orderType,
        PaymentType paymentType,
        address renter
    ) internal {
        onlyApprovedOrOwner(msg.sender, nftAddress, nftId);
        require(maxEndTime > block.timestamp, "invalid maxEndTime");
        require(
            minDuration <= IComplexDoNFT(nftAddress).getMaxDuration(),
            "Error:minDuration > max"
        );
        require(
            IERC165(nftAddress).supportsInterface(
                type(IComplexDoNFT).interfaceId
            ),
            "not doNFT"
        );
        (, , uint64 dEnd) = IComplexDoNFT(nftAddress).getDurationByIndex(
            nftId,
            0
        );
        if (maxEndTime > dEnd) {
            maxEndTime = dEnd;
        }
        if (maxEndTime > block.timestamp + maxIndate) {
            maxEndTime = uint64(block.timestamp) + maxIndate;
        }

        address _owner = ERC721(nftAddress).ownerOf(nftId);
        Lending storage lending = lendingMap[nftAddress][nftId];
        lending.lender = _owner;
        lending.nftAddress = nftAddress;
        lending.nftId = nftId;
        lending.maxEndTime = maxEndTime;
        lending.minDuration = minDuration;
        lending.nonce = IComplexDoNFT(nftAddress).getNonce(nftId);
        lending.createTime = uint64(block.timestamp);
        lending.orderType = orderType;
        lending.paymentType = paymentType;

        emit CreateLendOrder(
            _owner,
            nftAddress,
            nftId,
            maxEndTime,
            minDuration,
            pricePerDay,
            paymentToken,
            renter,
            orderType
        );
    }

    function cancelLendOrder(address nftAddress, uint256 nftId)
        public
        whenNotPaused
    {
        onlyApprovedOrOwner(msg.sender, nftAddress, nftId);
        delete lendingMap[nftAddress][nftId];
        delete paymentNormalMap[nftAddress][nftId];
        delete privateOrderMap[nftAddress][nftId];
        emit CancelLendOrder(msg.sender, nftAddress, nftId);
    }

    function getLendOrder(address nftAddress, uint256 nftId)
        public
        view
        returns (Lending memory)
    {
        return lendingMap[nftAddress][nftId];
    }

    function getRenterOfPrivateLendOrder(address nftAddress, uint256 nftId)
        external
        view
        returns (address)
    {
        return privateOrderMap[nftAddress][nftId];
    }

    function getPaymentNormal(address nftAddress, uint256 nftId)
        external
        view
        returns (PaymentNormal memory)
    {
        return paymentNormalMap[nftAddress][nftId];
    }

    function fulfillOrderNow(
        address nftAddress,
        uint256 nftId,
        uint256 durationId,
        uint64 duration,
        address user,
        address paymentToken,
        uint256 pricePerDay
    ) public payable virtual whenNotPaused nonReentrant returns (uint256 tid) {
        require(isLendOrderValid(nftAddress, nftId), "invalid order");
        Lending storage lending = lendingMap[nftAddress][nftId];
        PaymentNormal storage pNormal = paymentNormalMap[nftAddress][nftId];
        require(
            paymentToken == pNormal.token && pricePerDay == pNormal.pricePerDay,
            "invalid lending"
        );
        if (lending.orderType == OrderType.Private) {
            require(
                msg.sender == privateOrderMap[nftAddress][nftId],
                "invalid renter"
            );
        }
        uint64 endTime = uint64(block.timestamp + duration - 1);
        if (endTime > lending.maxEndTime) {
            endTime = lending.maxEndTime;
        }
        (, uint64 dEnd) = IComplexDoNFT(nftAddress).getDuration(durationId);
        if (endTime > dEnd) {
            endTime = dEnd;
        }
        uint64 startTime = uint64(block.timestamp);
        if (!(endTime == dEnd || endTime == lending.maxEndTime)) {
            require(duration >= lending.minDuration, "duration < minDuration");
        }
        distributePayment(nftAddress, nftId, startTime, endTime);
        tid = IComplexDoNFT(nftAddress).mint(
            nftId,
            durationId,
            startTime,
            endTime,
            msg.sender,
            user
        );

        emit FulfillOrder(
            msg.sender,
            lending.lender,
            nftAddress,
            nftId,
            startTime,
            endTime,
            pNormal.pricePerDay,
            tid,
            pNormal.token
        );
    }

    function distributePayment(
        address nftAddress,
        uint256 nftId,
        uint64 startTime,
        uint64 endTime
    )
        internal
        returns (
            uint256 totalPrice,
            uint256 leftTotalPrice,
            uint256 curFee,
            uint256 curRoyalty
        )
    {
        PaymentNormal storage pNormal = paymentNormalMap[nftAddress][nftId];
        if (pNormal.pricePerDay == 0) return (0, 0, 0, 0);
        totalPrice = (pNormal.pricePerDay * (endTime - startTime + 1)) / 86400;
        curFee = (totalPrice * fee) / E5;
        curRoyalty =
            (totalPrice * IComplexDoNFT(nftAddress).getRoyaltyFee()) /
            E5;
        leftTotalPrice = totalPrice - curFee - curRoyalty;

        royaltyMap[nftAddress][pNormal.token] += curRoyalty;
        balanceOfFee[pNormal.token] += curFee;

        if (pNormal.token == address(0)) {
            require(msg.value >= totalPrice, "payment is not enough");
            Address.sendValue(
                payable(ERC721(nftAddress).ownerOf(nftId)),
                leftTotalPrice
            );
            if (msg.value > totalPrice) {
                Address.sendValue(payable(msg.sender), msg.value - totalPrice);
            }
        } else {
            SafeERC20.safeTransferFrom(
                IERC20(pNormal.token),
                msg.sender,
                address(this),
                totalPrice
            );

            SafeERC20.safeTransfer(
                IERC20(pNormal.token),
                ERC721(nftAddress).ownerOf(nftId),
                leftTotalPrice
            );
        }
    }

    function setFee(uint256 fee_) public onlyAdmin {
        require(fee_ <= 1e4, "invalid fee");
        fee = fee_;
    }

    function getFee() public view returns (uint256) {
        return fee;
    }

    function setMarketBeneficiary(address payable beneficiary_)
        public
        onlyOwner
    {
        beneficiary = beneficiary_;
    }

    function claimFee(address[] calldata paymentTokens)
        public
        whenNotPaused
        nonReentrant
    {
        require(msg.sender == beneficiary, "not beneficiary");
        for (uint256 index = 0; index < paymentTokens.length; index++) {
            uint256 balance = balanceOfFee[paymentTokens[index]];
            if (balance > 0) {
                if (paymentTokens[index] == address(0)) {
                    Address.sendValue(beneficiary, balance);
                } else {
                    SafeERC20.safeTransfer(
                        IERC20(paymentTokens[index]),
                        beneficiary,
                        balance
                    );
                }
                balanceOfFee[paymentTokens[index]] = 0;
            }
        }
    }

    function balanceOfRoyalty(address nftAddress, address paymentToken)
        public
        view
        returns (uint256)
    {
        return royaltyMap[nftAddress][paymentToken];
    }

    function claimRoyalty(address nftAddress, address[] calldata paymentTokens)
        public
        whenNotPaused
        nonReentrant
    {
        address payable _beneficiary = IComplexDoNFT(nftAddress)
            .getBeneficiary();
        require(msg.sender == _beneficiary, "not beneficiary");
        for (uint256 index = 0; index < paymentTokens.length; index++) {
            uint256 balance = royaltyMap[nftAddress][paymentTokens[index]];
            if (balance > 0) {
                if (paymentTokens[index] == address(0)) {
                    Address.sendValue(_beneficiary, balance);
                } else {
                    SafeERC20.safeTransfer(
                        IERC20(paymentTokens[index]),
                        _beneficiary,
                        balance
                    );
                }
                royaltyMap[nftAddress][paymentTokens[index]] = 0;
            }
        }
    }

    function isLendOrderValid(address nftAddress, uint256 nftId)
        public
        view
        returns (bool)
    {
        Lending storage lending = lendingMap[nftAddress][nftId];
        if (isPausing) {
            return false;
        }
        return
            lending.nftId > 0 &&
            lending.maxEndTime > block.timestamp &&
            lending.nonce == IComplexDoNFT(nftAddress).getNonce(nftId);
    }

    function setPause(bool pause_) public onlyAdmin {
        isPausing = pause_;
        if (isPausing) {
            emit Paused(address(this));
        } else {
            emit Unpaused(address(this));
        }
    }

    function setMaxIndate(uint64 max_) public onlyAdmin {
        maxIndate = max_;
    }

    function multicall(bytes[] calldata data)
        external
        returns (bytes[] memory results)
    {
        results = new bytes[](data.length);
        for (uint256 i = 0; i < data.length; i++) {
            (bool success, bytes memory result) = address(this).delegatecall(
                data[i]
            );
            if (success) {
                results[i] = result;
            }
        }
        return results;
    }
}
[{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"lender","type":"address"},{"indexed":false,"internalType":"address","name":"nftAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"nftId","type":"uint256"}],"name":"CancelLendOrder","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"lender","type":"address"},{"indexed":false,"internalType":"address","name":"nftAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"nftId","type":"uint256"},{"indexed":false,"internalType":"uint64","name":"maxEndTime","type":"uint64"},{"indexed":false,"internalType":"uint64","name":"minDuration","type":"uint64"},{"indexed":false,"internalType":"uint256","name":"pricePerDay","type":"uint256"},{"indexed":false,"internalType":"address","name":"paymentToken","type":"address"},{"indexed":false,"internalType":"address","name":"renter","type":"address"},{"indexed":false,"internalType":"enum IMarket.OrderType","name":"orderType","type":"uint8"}],"name":"CreateLendOrder","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"renter","type":"address"},{"indexed":false,"internalType":"address","name":"lender","type":"address"},{"indexed":false,"internalType":"address","name":"nftAddress","type":"address"},{"indexed":false,"internalType":"uint256","name":"nftId","type":"uint256"},{"indexed":false,"internalType":"uint64","name":"startTime","type":"uint64"},{"indexed":false,"internalType":"uint64","name":"endTime","type":"uint64"},{"indexed":false,"internalType":"uint256","name":"pricePerDay","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"newId","type":"uint256"},{"indexed":false,"internalType":"address","name":"paymentToken","type":"address"}],"name":"FulfillOrder","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldAdmin","type":"address"},{"indexed":false,"internalType":"address","name":"newAdmin","type":"address"}],"name":"NewAdmin","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldOwner","type":"address"},{"indexed":false,"internalType":"address","name":"newOwner","type":"address"}],"name":"NewOwner","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"oldPendingOwner","type":"address"},{"indexed":false,"internalType":"address","name":"newPendingOwner","type":"address"}],"name":"NewPendingOwner","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Paused","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"account","type":"address"}],"name":"Unpaused","type":"event"},{"inputs":[],"name":"acceptOwner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"admin","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"balanceOfFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"nftAddress","type":"address"},{"internalType":"address","name":"paymentToken","type":"address"}],"name":"balanceOfRoyalty","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"beneficiary","outputs":[{"internalType":"address payable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"nftAddress","type":"address"},{"internalType":"uint256","name":"nftId","type":"uint256"}],"name":"cancelLendOrder","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"paymentTokens","type":"address[]"}],"name":"claimFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"nftAddress","type":"address"},{"internalType":"address[]","name":"paymentTokens","type":"address[]"}],"name":"claimRoyalty","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"nftAddress","type":"address"},{"internalType":"uint256","name":"nftId","type":"uint256"},{"internalType":"uint64","name":"maxEndTime","type":"uint64"},{"internalType":"uint64","name":"minDuration","type":"uint64"},{"internalType":"uint256","name":"pricePerDay","type":"uint256"},{"internalType":"address","name":"paymentToken","type":"address"}],"name":"createLendOrder","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"nftAddress","type":"address"},{"internalType":"uint256","name":"nftId","type":"uint256"},{"internalType":"uint64","name":"maxEndTime","type":"uint64"},{"internalType":"uint64","name":"minDuration","type":"uint64"},{"internalType":"uint256","name":"pricePerDay","type":"uint256"},{"internalType":"address","name":"paymentToken","type":"address"},{"internalType":"address","name":"renter","type":"address"},{"internalType":"enum IMarket.OrderType","name":"orderType","type":"uint8"}],"name":"createPrivateLendOrder","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"nftAddress","type":"address"},{"internalType":"uint256","name":"nftId","type":"uint256"},{"internalType":"uint256","name":"durationId","type":"uint256"},{"internalType":"uint64","name":"duration","type":"uint64"},{"internalType":"address","name":"user","type":"address"},{"internalType":"address","name":"paymentToken","type":"address"},{"internalType":"uint256","name":"pricePerDay","type":"uint256"}],"name":"fulfillOrderNow","outputs":[{"internalType":"uint256","name":"tid","type":"uint256"}],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"getFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"nftAddress","type":"address"},{"internalType":"uint256","name":"nftId","type":"uint256"}],"name":"getLendOrder","outputs":[{"components":[{"internalType":"address","name":"lender","type":"address"},{"internalType":"address","name":"nftAddress","type":"address"},{"internalType":"uint256","name":"nftId","type":"uint256"},{"internalType":"uint64","name":"maxEndTime","type":"uint64"},{"internalType":"uint64","name":"minDuration","type":"uint64"},{"internalType":"uint64","name":"createTime","type":"uint64"},{"internalType":"uint64","name":"nonce","type":"uint64"},{"internalType":"enum IMarket.OrderType","name":"orderType","type":"uint8"},{"internalType":"enum IMarket.PaymentType","name":"paymentType","type":"uint8"}],"internalType":"struct IMarket.Lending","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"nftAddress","type":"address"},{"internalType":"uint256","name":"nftId","type":"uint256"}],"name":"getPaymentNormal","outputs":[{"components":[{"internalType":"address","name":"token","type":"address"},{"internalType":"uint256","name":"pricePerDay","type":"uint256"}],"internalType":"struct IMarket.PaymentNormal","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"nftAddress","type":"address"},{"internalType":"uint256","name":"nftId","type":"uint256"}],"name":"getRenterOfPrivateLendOrder","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner_","type":"address"},{"internalType":"address","name":"admin_","type":"address"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"nftAddress","type":"address"},{"internalType":"uint256","name":"nftId","type":"uint256"}],"name":"isLendOrderValid","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"isPausing","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxIndate","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"doNftAddress","type":"address"},{"internalType":"uint256","name":"oNftId","type":"uint256"},{"internalType":"uint64","name":"maxEndTime","type":"uint64"},{"internalType":"uint64","name":"minDuration","type":"uint64"},{"internalType":"uint256","name":"pricePerDay","type":"uint256"},{"internalType":"address","name":"paymentToken","type":"address"}],"name":"mintAndCreateLendOrder","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"doNftAddress","type":"address"},{"internalType":"uint256","name":"oNftId","type":"uint256"},{"internalType":"uint64","name":"maxEndTime","type":"uint64"},{"internalType":"uint64","name":"minDuration","type":"uint64"},{"internalType":"uint256","name":"pricePerDay","type":"uint256"},{"internalType":"address","name":"paymentToken","type":"address"},{"internalType":"address","name":"renter","type":"address"},{"internalType":"enum IMarket.OrderType","name":"orderType","type":"uint8"}],"name":"mintAndCreatePrivateLendOrder","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes[]","name":"data","type":"bytes[]"}],"name":"multicall","outputs":[{"internalType":"bytes[]","name":"results","type":"bytes[]"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"pendingOwner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newAdmin","type":"address"}],"name":"setAdmin","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"fee_","type":"uint256"}],"name":"setFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"beneficiary_","type":"address"}],"name":"setMarketBeneficiary","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"max_","type":"uint64"}],"name":"setMaxIndate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"pause_","type":"bool"}],"name":"setPause","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"supportERC20","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_pendingOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]