claimDelegate: cache previous user

  • expects tokenIds to be ordered by the Front-end

  • ordered such that, same owners are sequence

  • since this has a 1 element lookback to compare is the owner matches

    /**
     * @notice Users to claim via delegated hot wallets
     * @dev Expects tokenIds to be ordered based on common ownership: [ownerA, ownerA, ownerB]
     * @param tokenIds Nfts' tokenId
     */  
    function claimDelegated(uint256[] calldata tokenIds) external whenStartedAndBeforeDeadline whenNotPaused {
        
        // array validation
        uint256 tokenIdsLength = tokenIds.length;
        if(tokenIdsLength == 0) revert EmptyArray(); 

        // check delegation on msg.sender
        bytes[] memory data = new bytes[](tokenIdsLength);
        address[] memory owners = new address[](tokenIdsLength);
        for (uint256 i = 0; i < tokenIdsLength; ++i) {
            
            uint256 tokenId = tokenIds[i];

            // get and store nft Owner
            address nftOwner = NFT.ownerOf(tokenId);          
            owners[i] = nftOwner;

            // data for multicall
            data[i] = abi.encodeCall(IDelegateRegistry(DELEGATE_REGISTRY).checkDelegateForERC721, 
                        (msg.sender, nftOwner, address(NFT), tokenId, ""));
        }
        
        // data for staticCall
        bytes memory staticData = abi.encodeCall(IDelegateRegistry(DELEGATE_REGISTRY).multicall, data); 
        
        // staticCall
        (bool success, bytes memory result) = DELEGATE_REGISTRY.staticcall(staticData); 
        if (!success) revert StaticCallFailed();

        // if a tokenId is not delegated will return false; as a bool
        bytes[] memory results = abi.decode(result, (bytes[]));

        uint256 totalAmount;
        uint256[] memory amounts = new uint256[](tokenIdsLength);

        address addressCache; 
        uint256 amountCache;

        for (uint256 i = 0; i < tokenIdsLength; ++i) {
            
            // multiCall uses delegateCall: decode return data
            bool isDelegated = abi.decode(results[i], (bool));
            if(!isDelegated) revert InvalidDelegate();

            // update tokenId: storage is updated
            uint256 tokenId = tokenIds[i];
            uint256 claimable = _updateLastClaimed(tokenId);
            
            totalAmount += claimable;
            amounts[i] = claimable;

            // initial reference
            if (i == 0) {

                addressCache = owners[i];
                amountCache = claimable;

            } else { 

                // check owner matches previous tokenid's owner
                if (addressCache == owners[i]) {
                    // increment amountCache
                    amountCache += claimable; 

                } else {  // if different owner from previous token id

                    // transfer current amountCache
                    TOKEN.safeTransfer(addressCache, amountCache); 

                    // update cache to current token id info
                    addressCache = owners[i];
                    amountCache = claimable;
                } 
            }
        }
       

        if (amountCache != 0) {
            TOKEN.safeTransfer(addressCache, amountCache); 
        }

        // update totalClaimed
        totalClaimed += totalAmount;

        // claimed per tokenId
        emit ClaimedByDelegate(msg.sender, owners, tokenIds, amounts);
    }

Last updated