claimDelegate: stack unique owners
for some array of tokenIds: [0,1,2,3,...]
the owners array, could contain repeated owners: [userA, userB, userA, userA]
this collapses the owner array to unique owners, and calculates their total claimable amount to be transferred out
the uniqueArrays have the same length of the original arrays -- they have trailing 0s to fill up the replaced elements
/**
* @notice Users to claim via delegated hot wallets
* @dev msg.sender is designated delegate of nfts
* @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[]));
//note: ending w/ 0s as placeholder
address[] memory uniqueOwners = new address[](tokenIdsLength);
uint256[] memory uniqueAmounts = new uint256[](tokenIdsLength);
uint256 totalAmount;
uint256 uniqueCounter;
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;
address owner = owners[i];
// populate 1st element
if(i == 0) {
uniqueOwners[i] = owner;
uniqueAmounts[i] = claimable;
++uniqueCounter;
} else {
// check all prev.| reverse loop decrement to 0
for (uint256 j = i-1; j >= 0; j--) {
// check if match w/ any of the previous owners
if (owner == uniqueOwners[j]) {
uniqueAmounts[j] += claimable;
break;
}
// If we've reached the beginning and found no match
if (j == 0) {
// add to array
uniqueOwners[i] = owner;
uniqueAmounts[i] = claimable;
++uniqueCounter;
}
}
}
}
Last updated