Files
smom-dbis-138/contracts/relay/CCIPRelayBridgeLINK.sol

69 lines
2.7 KiB
Solidity
Raw Normal View History

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import "../ccip/IRouterClient.sol";
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/access/AccessControl.sol";
/**
* @title CCIP Relay Bridge (LINK)
* @notice Accepts relayed CCIP messages carrying canonical LINK on the destination chain.
* @dev Companion to CCIPRelayBridge (WETH9-only). Grant ROUTER_ROLE to the same CCIPRelayRouter.
*/
contract CCIPRelayBridgeLINK is AccessControl {
bytes32 public constant ROUTER_ROLE = keccak256("ROUTER_ROLE");
address public immutable link;
address public relayRouter;
mapping(bytes32 => bool) public processedTransfers;
event CrossChainTransferCompleted(
bytes32 indexed messageId,
uint64 indexed sourceChainSelector,
address indexed recipient,
uint256 amount
);
constructor(address _link, address _relayRouter) {
require(_link != address(0), "CCIPRelayBridgeLINK: zero LINK");
require(_relayRouter != address(0), "CCIPRelayBridgeLINK: zero router");
link = _link;
relayRouter = _relayRouter;
_grantRole(ROUTER_ROLE, _relayRouter);
_grantRole(DEFAULT_ADMIN_ROLE, msg.sender);
}
function updateRelayRouter(address newRelayRouter) external onlyRole(DEFAULT_ADMIN_ROLE) {
require(newRelayRouter != address(0), "CCIPRelayBridgeLINK: zero address");
_revokeRole(ROUTER_ROLE, relayRouter);
relayRouter = newRelayRouter;
_grantRole(ROUTER_ROLE, newRelayRouter);
}
function ccipReceive(IRouterClient.Any2EVMMessage calldata message) external onlyRole(ROUTER_ROLE) {
require(!processedTransfers[message.messageId], "CCIPRelayBridgeLINK: already processed");
processedTransfers[message.messageId] = true;
require(message.tokenAmounts.length > 0, "CCIPRelayBridgeLINK: no tokens");
require(message.tokenAmounts[0].token == link, "CCIPRelayBridgeLINK: invalid token");
uint256 amount = message.tokenAmounts[0].amount;
require(amount > 0, "CCIPRelayBridgeLINK: invalid amount");
address recipient;
if (message.data.length == 64) {
(recipient, ) = abi.decode(message.data, (address, uint256));
} else if (message.data.length >= 128) {
(recipient, , , ) = abi.decode(message.data, (address, uint256, address, uint256));
} else {
revert("CCIPRelayBridgeLINK: invalid data");
}
require(recipient != address(0), "CCIPRelayBridgeLINK: zero recipient");
require(IERC20(link).transfer(recipient, amount), "CCIPRelayBridgeLINK: transfer failed");
emit CrossChainTransferCompleted(message.messageId, message.sourceChainSelector, recipient, amount);
}
}