GitHub repo: https://github.com/Yamamuchi/LedgerLink/tree/main
Slides: https://docs.google.com/presentation/d/15JKctjQ7dSkyNdyNLRqfJYHa0SPS_1R87tvZEfwBbeA/edit?usp=sharing
Automatic cross-chain smart contract deployment
At the core of our innovative project lies the Cross-Chain Interoperability Protocol (CCIP), a beacon facilitating seamless communication between varied blockchain ecosystems. Imagine diverse blockchain islands, previously isolated, now interlinked, bridging the gaps of communication. With the CCIP's prowess in standardizing messages, these islands can effortlessly interact and synchronize. When developers deploy a primary smart contract on a chosen blockchain, our system, backed by utility functions and an intuitive API, simultaneously launches proxy contracts on secondary chains. Depending on user preference, these proxies can either mirror the primary contract's functions or offer selective cross-chain interactions. The beauty lies in the user-friendly UI, ensuring even novices can navigate with ease. Users simply input details like the contract source and desired networks, and our system manages the intricate deployment process, later showcasing the addresses of the established contracts. Drawing parallels, envision a universal song, crafted once, yet resonating across global radio stations, irrespective of linguistic barriers. By integrating frameworks like Express and libraries such as solc and ethers, we're not just championing technical advancement but are crafting a future where blockchain ecosystems coalesce harmoniously, unlocking untapped avenues for expansive innovation.
CCIP code:
import { IRouterClient } from "../contracts/IRouterClient";
import { LinkTokenInterface } from "../contracts/LinkTokenInterface";
export function generateReplicatedFunctionProxyContract(signaturesAndFunctions: string[][]): string {
let proxyCode = `
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
${IRouterClient}
${LinkTokenInterface}
contract CCIPProxy {
IRouterClient router;
LinkTokenInterface linkToken;
address public immutable targetAddress;
uint64 public immutable destinationChainSelector;
error NotEnoughBalance(uint256 currentBalance, uint256 calculatedFees);
constructor(address _router, address _link, address _targetAddress, uint64 _destinationChainSelector) {
router = IRouterClient(_router);
linkToken = LinkTokenInterface(_link);
targetAddress = _targetAddress;
destinationChainSelector = _destinationChainSelector;
}
`;
signaturesAndFunctions.forEach(([signature, func]) => {
proxyCode += `
${func} {
_forwardCCIPMessage("${signature}"); // Passing the entire signature directly
}
`;
});
proxyCode += `
function _forwardCCIPMessage(string memory signature) private {
// Constructing the CCIP message
Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({
receiver: abi.encode(address(this)),
data: abi.encodeWithSignature(signature, targetAddress),
tokenAmounts: new Client.EVMTokenAmount[](0),
extraArgs: Client._argsToBytes(
Client.EVMExtraArgsV1({gasLimit: 200_000, strict: false})
),
feeToken: address(linkToken)
});
uint256 fees = router.getFee(destinationChainSelector, message);
if (fees > linkToken.balanceOf(address(this)))
revert NotEnoughBalance(linkToken.balanceOf(address(this)), fees);
linkToken.approve(address(router), fees);
router.ccipSend(destinationChainSelector, message);
}
`;
proxyCode += `}`;
return proxyCode;
}
export function generateSingularFowardingProxyContract(): string {
let proxyCode = `
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
${IRouterClient}
${LinkTokenInterface}
contract CCIPProxy {
IRouterClient router;
LinkTokenInterface linkToken;
address public immutable targetAddress;
address public owner;
uint64 public immutable destinationChainSelector;
mapping(string => bool) public allowList;
error NotEnoughBalance(uint256 currentBalance, uint256 calculatedFees);
error FunctionNotAllowlisted(string signature);
error NotOwner();
constructor(address _router, address _link, address _targetAddress, uint64 _destinationChainSelector) {
router = IRouterClient(_router);
linkToken = LinkTokenInterface(_link);
targetAddress = _targetAddress;
owner = msg.sender;
destinationChainSelector = _destinationChainSelector;
}
modifier onlyOwner() {
if(msg.sender != owner) {
revert NotOwner();
}
_;
}
function addToAllowList(string memory signature) external onlyOwner {
allowList[signature] = true;
}
function removeFromAllowList(string memory signature) external onlyOwner {
allowList[signature] = false;
}
function forward(string memory signature, bytes memory data) external {
if(!allowList[signature]) {
revert FunctionNotAllowlisted(signature);
}
_forwardCCIPMessage(signature, data);
}
function _forwardCCIPMessage(string memory signature, bytes memory data) private {
// Constructing the CCIP message
Client.EVM2AnyMessage memory message = Client.EVM2AnyMessage({
receiver: abi.encode(address(this)), // This might need adjustment based on specific use-cases
data: abi.encodeWithSignature(signature, data),
tokenAmounts: new Client.EVMTokenAmount[](0),
extraArgs: Client._argsToBytes(
Client.EVMExtraArgsV1({gasLimit: 200_000, strict: false})
),
feeToken: address(linkToken)
});
uint256 fees = router.getFee(destinationChainSelector, message);
if (fees > linkToken.balanceOf(address(this)))
revert NotEnoughBalance(linkToken.balanceOf(address(this)), fees);
linkToken.approve(address(router), fees);
router.ccipSend(destinationChainSelector, message);
}
}`;
return proxyCode;
}