Files
smom-dbis-138/contracts/mainnet-checkpoint/Chain138ParticipantSurface.sol
defiQUG c336809676
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
Add mainnet checkpoint stack: ISO attestation, participant Etherscan surface, and services.
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>
2026-05-25 00:30:45 -07:00

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);
}
}