Files
smom-dbis-138/contracts/ccip-integration/CCIPLogger.sol
2026-03-02 12:14:09 -08:00

123 lines
3.7 KiB
Solidity

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "../ccip/IRouterClient.sol";
/**
* @title CCIPLogger
* @notice Receives and logs Chain-138 transactions via Chainlink CCIP
* @dev Implements replay protection via batch ID tracking; optional authorized signer for future use
*/
contract CCIPLogger {
IRouterClient public immutable router;
address public authorizedSigner;
uint64 public expectedSourceChainSelector;
address public owner;
mapping(bytes32 => bool) public processedBatches;
event RemoteBatchLogged(
bytes32 indexed messageId,
bytes32 indexed batchId,
uint64 sourceChainSelector,
address sender,
bytes32[] txHashes,
address[] froms,
address[] tos,
uint256[] values
);
event AuthorizedSignerUpdated(address oldSigner, address newSigner);
event SourceChainSelectorUpdated(uint64 oldSelector, uint64 newSelector);
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
modifier onlyRouter() {
require(msg.sender == address(router), "CCIPLogger: only router");
_;
}
modifier onlyOwner() {
require(msg.sender == owner, "CCIPLogger: only owner");
_;
}
constructor(
address _router,
address _authorizedSigner,
uint64 _expectedSourceChainSelector
) {
require(_router != address(0), "CCIPLogger: zero router");
router = IRouterClient(_router);
authorizedSigner = _authorizedSigner;
expectedSourceChainSelector = _expectedSourceChainSelector;
owner = msg.sender;
}
/**
* @notice Handle CCIP message (called by CCIP Router)
* @param message The received CCIP message
*/
function ccipReceive(
IRouterClient.Any2EVMMessage calldata message
) external onlyRouter {
require(
message.sourceChainSelector == expectedSourceChainSelector,
"CCIPLogger: invalid source chain"
);
(
bytes32 batchId,
bytes32[] memory txHashes,
address[] memory froms,
address[] memory tos,
uint256[] memory values,
bytes memory _extra
) = abi.decode(
message.data,
(bytes32, bytes32[], address[], address[], uint256[], bytes)
);
require(!processedBatches[batchId], "CCIPLogger: batch already processed");
processedBatches[batchId] = true;
address sender = message.sender.length >= 20
? address(bytes20(message.sender))
: address(0);
if (message.sender.length == 32) {
sender = address(bytes20(message.sender));
}
emit RemoteBatchLogged(
message.messageId,
batchId,
message.sourceChainSelector,
sender,
txHashes,
froms,
tos,
values
);
}
function getRouter() external view returns (address) {
return address(router);
}
function setAuthorizedSigner(address _signer) external onlyOwner {
address old = authorizedSigner;
authorizedSigner = _signer;
emit AuthorizedSignerUpdated(old, _signer);
}
function setExpectedSourceChainSelector(uint64 _selector) external onlyOwner {
uint64 old = expectedSourceChainSelector;
expectedSourceChainSelector = _selector;
emit SourceChainSelectorUpdated(old, _selector);
}
function transferOwnership(address newOwner) external onlyOwner {
require(newOwner != address(0), "CCIPLogger: zero address");
emit OwnershipTransferred(owner, newOwner);
owner = newOwner;
}
}