This project implements a Cross-Chain Asset Transfer System where assets can be locked on one blockchain and minted as a representation on another. The system consists of smart contracts deployed on two test networks (LocalAmoy and LocalSepolia) that enable the secure transfer of ERC20 tokens and NFTs between chains.
The system ensures:
- Security: Assets are locked before being minted on the other chain.
- Transparency: Users can verify all transactions on the blockchain.
- Proof-of-Transfer: The transfer process is traceable on both chains.
- Node.js (>=16.x)
- Hardhat (Ethereum development framework)
- Metamask (for interacting with test networks)
- Ganache (optional for local blockchain simulation)
# Clone the repository
git clone https://github.com/exploring-solver/iitkcyberhack.git
cd cross-chain-transfer
# Install dependencies
npm installRun two separate local blockchain nodes on different ports:
npx hardhat node --port 8545 # LocalAmoy
npx hardhat node --port 8546 # LocalSepolianpx hardhat run scripts/deployAmoy.js --network localAmoynpx hardhat run scripts/deploySepolia.js --network localSepolianpx hardhat console --network localAmoyconst token = await ethers.getContractAt("ERC20", "<localAmoy token address>");
const bridge = await ethers.getContractAt("BridgeAmoy", "<localAmoy bridge address>");
await token.approve(bridge.target, ethers.parseEther("10"));
await bridge.lock(ethers.parseEther("10"));
const balance = await token.balanceOf("<your_address>");
console.log(`Sender's balance on LocalAmoy: ${ethers.formatEther(balance)}`);npx hardhat console --network localSepoliaconst bridge = await ethers.getContractAt("BridgeSepolia", "<localSepolia bridge address>");
await bridge.release("<your_address>", ethers.parseEther("10"));
const token = await ethers.getContractAt("ERC20", "<localSepolia token address>");
const balance = await token.balanceOf("<your_address>");
console.log(`Receiver's balance on LocalSepolia: ${ethers.formatEther(balance)}`);npx hardhat console --network localSepoliaawait token.approve(bridge.target, ethers.parseEther("10"));
await bridge.burn(ethers.parseEther("10"));
const balance = await token.balanceOf("<your_address>");
console.log(`Sender's balance on LocalSepolia: ${ethers.formatEther(balance)}`);npx hardhat console --network localAmoyawait bridge.unlock("<your_address>", ethers.parseEther("10"));
const balance = await token.balanceOf("<your_address>");
console.log(`Receiver's balance on LocalAmoy: ${ethers.formatEther(balance)}`);npx hardhat run scripts/deployAmoyNFT.js --network localAmoynpx hardhat run scripts/deploySepoliaNFT.js --network localSepolianpx hardhat console --network localAmoyconst nft = await ethers.getContractAt("NativeNFT", "<localAmoy NFT address>");
const bridge = await ethers.getContractAt("BridgeAmoyNFT", "<localAmoy bridge address>");
const [signer] = await ethers.getSigners();
const userAddress = await signer.getAddress();
await bridge.mint(userAddress); // Mint NFT with ID 1
const tokenId = 1;
await nft.approve(bridge.target, tokenId);
await bridge.lock(tokenId);
const owner = await nft.ownerOf(tokenId);
console.log(`NFT ${tokenId} owner on LocalAmoy: ${owner}`);npx hardhat console --network localSepoliaconst bridge = await ethers.getContractAt("BridgeSepoliaNFT", "<localSepolia bridge address>");
await bridge.release(userAddress, tokenId);
const wrappedNFT = await ethers.getContractAt("WrappedNFT", "<localSepolia Wrapped NFT address>");
const newOwner = await wrappedNFT.ownerOf(tokenId);
console.log(`Wrapped NFT ${tokenId} owner on LocalSepolia: ${newOwner}`);