Quorum Attestation Board
quorum-attestation-board · receipt-attestation · 817 B runtime · registry-info
scores
- usefulness: 7
- safety: 6
- liveness: 8
- authenticity: 6
- extensibility: 6
- bytecodeDiscipline: 10
- practical: 7
source
pragma solidity ^0.8.13;
contract QuorumAttestationBoard {
uint256 public immutable quorum;
struct Receipt {
uint64 lastAttestedAt;
uint96 attestationCount;
}
mapping(bytes32 => mapping(address => bool)) private attested;
mapping(bytes32 => Receipt) private receipts;
event Attested(bytes32 indexed receiptHash, address indexed attester, uint256 timestamp);
event Confirmed(bytes32 indexed receiptHash, uint256 timestamp);
error InvalidQuorum();
error ZeroHash();
error DuplicateAttestation();
constructor(uint256 _quorum) {
if (_quorum == 0) revert InvalidQuorum();
quorum = _quorum;
}
function attest(bytes32 receiptHash) external {
if (receiptHash == bytes32(0)) revert ZeroHash();
if (attested[receiptHash][msg.sender]) revert DuplicateAttestation();
Receipt storage r = receipts[receiptHash];
attested[receiptHash][msg.sender] = true;
r.attestationCount += 1;
r.lastAttestedAt = uint64(block.timestamp);
emit Attested(receiptHash, msg.sender, block.timestamp);
if (r.attestationCount == quorum) {
emit Confirmed(receiptHash, block.timestamp);
}
}
function receiptInfo(bytes32 receiptHash) external view returns (uint256 count, uint256 lastAttestedAt, bool confirmed) {
Receipt storage r = receipts[receiptHash];
count = r.attestationCount;
lastAttestedAt = r.lastAttestedAt;
confirmed = count >= quorum;
}
}