Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions makefile-external
Original file line number Diff line number Diff line change
Expand Up @@ -54,3 +54,12 @@ fct-vrf-cancel-subscription: fct-check-rpc-url
$(call check_set_parameter,RECEIVING_ADDRESS,receivingAddress) \
forge script ${FCT_PLUGIN_PATH}/script/vrf/VRF.CLI.s.sol --sig "cancelSubscription(address,uint64,address)" $$functionsRouterAddress $$subId $$receivingAddress --rpc-url ${RPC_URL} --broadcast --private-key ${PRIVATE_KEY} --out ${FCT_PLUGIN_PATH}/out

# CCIP
.PHONY: fcc-ccip-estimate-receive
fcc-ccip-estimate-receive:
$(call check_set_parameter,DESTINATION_RPC_URL,destinationRpcUrl) \
$(call check_set_parameter,CCIP_ROUTER_ADDRESS,ccipReceiverAddress) \
$(call check_set_parameter,SOURCE_CHAIN_SELECTOR,sourceChainSelector) \
$(call check_set_parameter,CCIP_MESSAGE_SENDER,ccipMessageSender) \
$(call check_set_parameter,CCIP_MESSAGE_DATA,ccipMessageData) \
forge script ${FCT_PLUGIN_PATH}/script/ccip/CCIPReceiver.CLI.s.sol --sig "ccipReceive(address,uint64,address,bytes)" $$ccipReceiverAddress $$sourceChainSelector $$ccipMessageSender $$ccipMessageData --rpc-url $$destinationRpcUrl --out ${FCT_PLUGIN_PATH}/out
2 changes: 1 addition & 1 deletion script/automation/Automation.CLI.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ contract AutomationCLIScript is BaseScript {
address upkeepAddress,
uint32 gasLimit,
bytes calldata checkData
) nestedScriptContext public returns (bytes32 requestHash) {
) nestedScriptContext external returns (bytes32 requestHash) {
AutomationScript automationScript = new AutomationScript(keeperRegistryAddress);
return automationScript.registerUpkeep(
amountInJuels,
Expand Down
27 changes: 27 additions & 0 deletions script/ccip/CCIPReceiver.CLI.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.2 <0.9.0;

import "forge-std/Script.sol";

import "./CCIPReceiver.s.sol";
import "../helpers/BaseScript.s.sol";

contract CCIPReceiverCLIScript is BaseScript {
function ccipReceive(
address ccipReceiverAddress,
uint64 sourceChainSelector,
address sender,
bytes memory data
) external {
Client.EVMTokenAmount[] memory destTokenAmounts = new Client.EVMTokenAmount[](0);
CCIPReceiverScript ccipReceiverScript = new CCIPReceiverScript(ccipReceiverAddress);
Client.Any2EVMMessage memory message = Client.Any2EVMMessage({
messageId: bytes32(0),
sourceChainSelector: sourceChainSelector,
sender: abi.encode(sender),
data: data,
destTokenAmounts: destTokenAmounts
});
ccipReceiverScript.ccipReceive(message);
}
}
23 changes: 23 additions & 0 deletions script/ccip/CCIPReceiver.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.2 <0.9.0;

import "forge-std/Script.sol";

import "../helpers/BaseScript.s.sol";
import "src/interfaces/ccip/IAny2EVMMessageReceiver.sol";
import "src/libraries/CCIPClient.sol";

contract CCIPReceiverScript is BaseScript {
address public ccipReceiverAddress;

constructor (address _ccipReceiverAddress) {
ccipReceiverAddress = _ccipReceiverAddress;
}

function ccipReceive(
Client.Any2EVMMessage memory message
) external {
IAny2EVMMessageReceiver ccipReceiver = IAny2EVMMessageReceiver(ccipReceiverAddress);
ccipReceiver.ccipReceive(message);
}
}
57 changes: 57 additions & 0 deletions script/ccip/CCIPRouter.CLI.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.2 <0.9.0;

import "forge-std/Script.sol";

import "./CCIPRouter.s.sol";
import "../helpers/BaseScript.s.sol";
import "src/libraries/CCIPClient.sol";

contract CCIPRouterCLIScript is BaseScript {
function getFee(
address ccipRouterAddress,
uint64 destinationChainSelector,
Client.EVM2AnyMessage memory message
) external returns (uint256 fee) {
CCIPRouterScript ccipRouterScript = new CCIPRouterScript(ccipRouterAddress);
return ccipRouterScript.getFee(destinationChainSelector, message);
}

function getSupportedTokens(
address ccipRouterAddress,
uint64 chainSelector
) external returns (address[] memory) {
CCIPRouterScript ccipRouterScript = new CCIPRouterScript(ccipRouterAddress);
return ccipRouterScript.getSupportedTokens(chainSelector);
}

function isChainSupported(
address ccipRouterAddress,
uint64 chainSelector
) external returns (bool) {
CCIPRouterScript ccipRouterScript = new CCIPRouterScript(ccipRouterAddress);
return ccipRouterScript.isChainSupported(chainSelector);
}

function getOnRamp(
address ccipRouterAddress,
uint64 destChainSelector
) external returns (address) {
CCIPRouterScript ccipRouterScript = new CCIPRouterScript(ccipRouterAddress);
return ccipRouterScript.getOnRamp(destChainSelector);
}

function isOffRamp(
address ccipRouterAddress,
uint64 sourceChainSelector,
address offRamp
) external returns (bool) {
CCIPRouterScript ccipRouterScript = new CCIPRouterScript(ccipRouterAddress);
return ccipRouterScript.isOffRamp(sourceChainSelector, offRamp);
}

function getWrappedNative(address ccipRouterAddress) external returns (address) {
CCIPRouterScript ccipRouterScript = new CCIPRouterScript(ccipRouterAddress);
return ccipRouterScript.getWrappedNative();
}
}
50 changes: 50 additions & 0 deletions script/ccip/CCIPRouter.s.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.2 <0.9.0;

import "forge-std/Script.sol";

import "../helpers/BaseScript.s.sol";
import "../helpers/TypeAndVersion.s.sol";
import "src/interfaces/ccip/CCIPRouterInterface.sol";
import "src/libraries/CCIPClient.sol";

contract CCIPRouterScript is BaseScript, TypeAndVersionScript {
address public ccipRouterAddress;

constructor (address _ccipRouterAddress) {
ccipRouterAddress = _ccipRouterAddress;
}

function getFee(
uint64 destinationChainSelector,
Client.EVM2AnyMessage memory message
) external view returns (uint256 fee) {
CCIPRouterInterface ccipRouter = CCIPRouterInterface(ccipRouterAddress);
return ccipRouter.getFee(destinationChainSelector, message);
}

function getSupportedTokens(uint64 chainSelector) external view returns (address[] memory) {
CCIPRouterInterface ccipRouter = CCIPRouterInterface(ccipRouterAddress);
return ccipRouter.getSupportedTokens(chainSelector);
}

function isChainSupported(uint64 chainSelector) public view returns (bool) {
CCIPRouterInterface ccipRouter = CCIPRouterInterface(ccipRouterAddress);
return ccipRouter.isChainSupported(chainSelector);
}

function getOnRamp(uint64 destChainSelector) external view returns (address) {
CCIPRouterInterface ccipRouter = CCIPRouterInterface(ccipRouterAddress);
return ccipRouter.getOnRamp(destChainSelector);
}

function isOffRamp(uint64 sourceChainSelector, address offRamp) public view returns (bool) {
CCIPRouterInterface ccipRouter = CCIPRouterInterface(ccipRouterAddress);
return ccipRouter.isOffRamp(sourceChainSelector, offRamp);
}

function getWrappedNative() external view returns (address) {
CCIPRouterInterface ccipRouter = CCIPRouterInterface(ccipRouterAddress);
return ccipRouter.getWrappedNative();
}
}
17 changes: 17 additions & 0 deletions src/interfaces/ccip/CCIPRouterInterface.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.2 <0.9.0;

import "../shared/TypeAndVersionInterface.sol";
import "src/libraries/CCIPClient.sol";

interface CCIPRouterInterface is TypeAndVersionInterface {
function getFee(
uint64 destinationChainSelector,
Client.EVM2AnyMessage memory message
) external view returns (uint256 fee);
function getSupportedTokens(uint64 chainSelector) external view returns (address[] memory);
function isChainSupported(uint64 chainSelector) external view returns (bool);
function getOnRamp(uint64 destChainSelector) external view returns (address);
function isOffRamp(uint64 sourceChainSelector, address offRamp) external view returns (bool);
function getWrappedNative() external view returns (address);
}
15 changes: 15 additions & 0 deletions src/interfaces/ccip/IAny2EVMMessageReceiver.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.2 <0.9.0;

import "src/libraries/CCIPClient.sol";

/// @notice Application contracts that intend to receive messages from
/// the router should implement this interface.
interface IAny2EVMMessageReceiver {
/// @notice Called by the Router to deliver a message.
/// If this reverts, any token transfers also revert. The message
/// will move to a FAILED state and become available for manual execution.
/// @param message CCIP Message
/// @dev Note ensure you check the msg.sender is the OffRampRouter
function ccipReceive(Client.Any2EVMMessage calldata message) external;
}
28 changes: 28 additions & 0 deletions src/libraries/CCIPClient.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// SPDX-License-Identifier: MIT
pragma solidity >=0.6.2 <0.9.0;

/// @title Library of common constants and enums for the CCIP Router contract
library Client {
/// @dev RMN depends on this struct, if changing, please notify the RMN maintainers.
struct EVMTokenAmount {
address token; // token address on the local chain.
uint256 amount; // Amount of tokens.
}

// If extraArgs is empty bytes, the default is 200k gas limit.
struct EVM2AnyMessage {
bytes receiver; // abi.encode(receiver address) for dest EVM chains
bytes data; // Data payload
EVMTokenAmount[] tokenAmounts; // Token transfers
address feeToken; // Address of feeToken. address(0) means you will send msg.value.
bytes extraArgs; // Populate this with _argsToBytes(EVMExtraArgsV1)
}

struct Any2EVMMessage {
bytes32 messageId; // MessageId corresponding to ccipSend on source.
uint64 sourceChainSelector; // Source chain selector.
bytes sender; // abi.decode(sender) if coming from an EVM chain.
bytes data; // payload sent in original message.
EVMTokenAmount[] destTokenAmounts; // Tokens and their amounts in their destination chain representation.
}
}