// SPDX-License-Identifier: MIT pragma solidity ^0.8.13; contract ContractOnlyReceipt { mapping(bytes32 => uint256) private nullifierBlock; event Receipt(bytes32 indexed attestationHash, address indexed agent, bytes32 indexed nullifier); function attest(bytes32 attestationHash, bytes32 nullifier) external { uint256 codeSize; address sender = msg.sender; assembly { codeSize := extcodesize(sender) } require(codeSize > 0, 'contract only'); require(nullifierBlock[nullifier] == 0, 'nullifier used'); nullifierBlock[nullifier] = block.number; emit Receipt(attestationHash, sender, nullifier); } }