First Flight #12: Kitty Connect

First Flight #12: Kitty Connect
Beginner FriendlyFoundryNFTGameFi
100 EXP
View results
Submission Details
Severity: high
Valid

Insufficient LINK Token Approval in `KittyBridge::bridgeNftWithData`

Summary

The KittyBridge contract facilitates token transfers to another chain. To achieve this, the KittyConnect contract invokes KittyBridge::bridgeNftWithData. However, to bridge tokens between chains using CCIP, the KittyBridge must pay a fee in LINK tokens. This payment necessitates approval for LINK token transfer from KittyBridge to the CCIP router, which is currently absent.

Vulnerability Details

The vulnerability resides within the KittyBridge contract. In the bridgeNftWithData function, Router::ccipSend is called without prior approval for LINK token transfer.
The CCIP Router contract attempts to levy a fee from the KittyBridge for dispatching CCIP messages in LINK. However, this attempt fails due to the lack of approval from KittyBridge for the transfer.

Impact

The KittyBridge::bridgeNftWithData function consistently reverts due to insufficient allowance.

Tools Used

Manual review and forge were employed.
To replicate this issue, utilize the provided forge script below (save it in the file script/MintCatAndBridge.s.sol):

// SPDX-License-Identifier: MIT
pragma solidity 0.8.19;
import {Script} from "forge-std/Script.sol";
import {KittyConnect} from "../src/KittyConnect.sol";
import {KittyBridge} from "../src/KittyBridge.sol";
contract MintCatAndBridge is Script {
function run() external {
if (block.chainid != 11155111) {
// only run on Sepolia
return;
}
uint256 receiverPk = vm.envUint("RECEIVER_PK");
vm.startBroadcast();
address receiver = 0x065D2517ba3267391eD48a0D63Dce44b23E34d06;
KittyConnect kittyConnect = KittyConnect(0x304B6DB56659038F13868946805AF62eDfac76b3);
uint256 tokenId = kittyConnect.getTokenCounter();
kittyConnect.mintCatToNewOwner(receiver, "ipfs://QmWDK6uj7xS5NkBotM7VouqtZiZU4qvuFURa1E9DgM8JQ2", "Tom", "breed", block.timestamp);
vm.stopBroadcast();
vm.startBroadcast(receiverPk);
uint64 mumbaiChainSelector = 12532609583862916517;
address mumbaiBridgeAddress = 0xAafbFFff34E4416623C274BdEdc6984c5712E351;
// this will fail due insufficient allowance
kittyConnect.bridgeNftToAnotherChain(mumbaiChainSelector, mumbaiBridgeAddress, tokenId);
vm.stopBroadcast();
}
}

Ensure to set the appropriate values for RECEIVER_PK, sepolia-rpc-url, and adjust addresses as necessary. Running this script will consistently fail:

forge script script/MintCatAndBridge.s.sol \
--private-key <shop-partner-pk> \
--rpc-url <sepolia-rpc-rul> \
--broadcast -vvvv

Recommendations

Insert the following line before sending the CCIP message in the KittyBridge::bridgeNftWithData function:

+ s_linkToken.approve(address(router), fees);
messageId = router.ccipSend(_destinationChainSelector, evm2AnyMessage);
emit MessageSent(messageId, _destinationChainSelector, _receiver, _data, address(s_linkToken), fees);
return messageId;

This addition ensures that KittyBridge appropriately approves the transfer of LINK tokens before dispatching CCIP messages, thereby rectifying the identified issue.

Updates

Lead Judging Commences

inallhonesty Lead Judge over 1 year ago
Submission Judgement Published
Validated
Assigned finding tags:

Missing fee token approval

Support

FAQs

Can't find an answer? Chat with us on Discord, Twitter or Linkedin.