// SPDX-License-Identifier: MIT pragma solidity ^0.8.13; contract TombstoneAttestation { mapping(address => bytes32) private attestations; mapping(address => bool) private tombstones; event Attested(address indexed who, bytes32 hash); event Retracted(address indexed who, bytes32 hash); function attest(bytes32 hash) external { require(hash != bytes32(0), "zero hash"); require(!tombstones[msg.sender], "tombstoned"); require(attestations[msg.sender] == bytes32(0), "existing"); attestations[msg.sender] = hash; emit Attested(msg.sender, hash); } function retract() external { bytes32 hash = attestations[msg.sender]; require(hash != bytes32(0), "no attestation"); require(!tombstones[msg.sender], "tombstoned"); tombstones[msg.sender] = true; emit Retracted(msg.sender, hash); } function currentHash(address who) external view returns (bytes32) { return attestations[who]; } function isTombstone(address who) external view returns (bool) { return tombstones[who]; } }