Some checks failed
CI/CD Pipeline / Solidity Contracts (push) Failing after 1m3s
CI/CD Pipeline / Security Scanning (push) Successful in 2m18s
CI/CD Pipeline / Lint and Format (push) Failing after 34s
CI/CD Pipeline / Terraform Validation (push) Failing after 20s
CI/CD Pipeline / Kubernetes Validation (push) Successful in 22s
Deploy ChainID 138 / Deploy ChainID 138 (push) Failing after 40s
HYBX OMNL TypeScript & anchor / token-aggregation build + reconcile artifact (push) Failing after 49s
OMNL reconcile anchor / Run omnl:reconcile and upload artifacts (push) Failing after 21s
Validation / validate-genesis (push) Successful in 25s
Validation / validate-terraform (push) Failing after 21s
Validation / validate-kubernetes (push) Failing after 8s
Validation / validate-smart-contracts (push) Failing after 8s
Validation / validate-security (push) Failing after 1m11s
Validation / validate-documentation (push) Failing after 14s
Verify Deployment / Verify Deployment (push) Failing after 45s
Ship AddressActivityRegistry V1/V2, ISO20022IntakeGateway, Chain138ParticipantSurface, checkpoint hub contracts, checkpoint-core package, aggregator/indexer/sdk services, relay profile guards, M00 diamond bridge facet, and OMNL compliance contracts. Co-authored-by: Cursor <cursoragent@cursor.com>
138 lines
4.2 KiB
Solidity
138 lines
4.2 KiB
Solidity
// SPDX-License-Identifier: MIT
|
|
pragma solidity ^0.8.20;
|
|
|
|
/**
|
|
* @title Chain138ParticipantSurface
|
|
* @notice Surfaces Chain 138 payment activity on each participant's mainnet address history.
|
|
* @dev Emits indexed events (Etherscan Events tab on participant via log filters) and optional
|
|
* zero-value wallet touch (Internal Transactions tab). Top-level 0 ETH txs are sent
|
|
* separately by the relayer when CHECKPOINT_SURFACE_TOPLEVEL_ZERO_ETH=1 (aggregator).
|
|
*/
|
|
contract Chain138ParticipantSurface {
|
|
uint8 public constant DIRECTION_CREDITED = 0;
|
|
uint8 public constant DIRECTION_DEBITED = 1;
|
|
|
|
address public admin;
|
|
bool public paused;
|
|
bool public walletTouchEnabled;
|
|
|
|
struct Notification {
|
|
address participant;
|
|
bytes32 chain138TxHash;
|
|
bytes32 instructionId;
|
|
uint8 direction;
|
|
uint64 batchId;
|
|
uint256 valueWei;
|
|
uint64 valueUsdE8;
|
|
}
|
|
|
|
mapping(bytes32 => bool) public notified;
|
|
|
|
event AdminChanged(address indexed newAdmin);
|
|
event WalletTouchEnabled(bool enabled);
|
|
event Paused();
|
|
event Unpaused();
|
|
|
|
/// @notice Indexed for Etherscan log lookup on participant address (topic1).
|
|
event Chain138ActivityNotified(
|
|
address indexed participant,
|
|
bytes32 indexed chain138TxHash,
|
|
bytes32 indexed instructionId,
|
|
uint8 direction,
|
|
uint64 batchId,
|
|
uint256 valueWei,
|
|
uint64 valueUsdE8,
|
|
bool walletTouched
|
|
);
|
|
|
|
event BatchNotificationsSurfaced(uint64 indexed batchId, uint256 count);
|
|
|
|
modifier onlyAdmin() {
|
|
require(msg.sender == admin, "only admin");
|
|
_;
|
|
}
|
|
|
|
modifier whenNotPaused() {
|
|
require(!paused, "paused");
|
|
_;
|
|
}
|
|
|
|
constructor(address _admin) {
|
|
require(_admin != address(0), "zero admin");
|
|
admin = _admin;
|
|
walletTouchEnabled = true;
|
|
}
|
|
|
|
function setAdmin(address newAdmin) external onlyAdmin {
|
|
require(newAdmin != address(0), "zero admin");
|
|
admin = newAdmin;
|
|
emit AdminChanged(newAdmin);
|
|
}
|
|
|
|
function setWalletTouchEnabled(bool enabled) external onlyAdmin {
|
|
walletTouchEnabled = enabled;
|
|
emit WalletTouchEnabled(enabled);
|
|
}
|
|
|
|
function pause() external onlyAdmin {
|
|
paused = true;
|
|
emit Paused();
|
|
}
|
|
|
|
function unpause() external onlyAdmin {
|
|
paused = false;
|
|
emit Unpaused();
|
|
}
|
|
|
|
function notificationKey(
|
|
address participant,
|
|
bytes32 chain138TxHash,
|
|
uint8 direction
|
|
) public pure returns (bytes32) {
|
|
return keccak256(abi.encodePacked(participant, chain138TxHash, direction));
|
|
}
|
|
|
|
/**
|
|
* @notice Record Chain 138 activity for each participant role (credit + debit) in one mainnet tx.
|
|
* @param batchId Checkpoint batch id (for correlation)
|
|
* @param items Parallel notifications (typically 2 per Chain 138 tx: debited from, credited to)
|
|
*/
|
|
function notifyBatch(uint64 batchId, Notification[] calldata items) external onlyAdmin whenNotPaused {
|
|
uint256 n = items.length;
|
|
for (uint256 i = 0; i < n; i++) {
|
|
Notification calldata item = items[i];
|
|
require(item.participant != address(0), "zero participant");
|
|
require(item.chain138TxHash != bytes32(0), "zero hash");
|
|
|
|
bytes32 key = notificationKey(item.participant, item.chain138TxHash, item.direction);
|
|
if (notified[key]) continue;
|
|
notified[key] = true;
|
|
|
|
bool touched = false;
|
|
if (walletTouchEnabled) {
|
|
(bool ok,) = item.participant.call{value: 0}(
|
|
abi.encodeWithSignature(
|
|
"chain138Attestation(bytes32,uint8,uint64)",
|
|
item.chain138TxHash,
|
|
item.direction,
|
|
batchId
|
|
)
|
|
);
|
|
touched = ok;
|
|
}
|
|
|
|
emit Chain138ActivityNotified(
|
|
item.participant,
|
|
item.chain138TxHash,
|
|
item.instructionId,
|
|
item.direction,
|
|
batchId,
|
|
item.valueWei,
|
|
item.valueUsdE8,
|
|
touched
|
|
);
|
|
}
|
|
emit BatchNotificationsSurfaced(batchId, n);
|
|
}
|
|
}
|