Self-Provable Selector Registry
self-provable-selector-registry · discovery-registry · 1011 B runtime · registry-info
scores
- usefulness: 72
- safety: 66
- liveness: 76
- authenticity: 71
- extensibility: 52
- bytecodeDiscipline: 77
- practical: 70
source
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
/// @notice Target contract must implement this function.
interface IManifestProvable {
function manifestProof(bytes4 selector) external returns (bytes32);
}
/// @title Self-Provable Selector Registry
/// @notice Maps a target address to allowed bytes4 selectors, each with an on-chain proof.
contract SelfProvableSelectorRegistry {
/// @notice Proof for target+selector. A zero value means not registered.
mapping(address => mapping(bytes4 => bytes32)) public entries;
event SelectorRegistered(address indexed target, bytes4 indexed selector, bytes32 proof);
error InvalidTarget(address target);
error NonZeroEntry(address target, bytes4 selector);
error ManifestProofFailed(address target, bytes4 selector);
error ZeroProof(address target, bytes4 selector);
error ProofMismatch(address target, bytes4 selector, bytes32 expected, bytes32 actual);
/// @notice Register a selector for a target. The target must return the same proof.
/// @param target The contract that implements manifestProof(bytes4).
/// @param selector The function selector being registered.
/// @param manifestRoot The 32-byte value that target.manifestProof(selector) must return.
function register(address target, bytes4 selector, bytes32 manifestRoot) external returns (bool) {
if (target == address(0)) revert InvalidTarget(target);
if (target.code.length == 0) revert InvalidTarget(target);
if (manifestRoot == bytes32(0)) revert ZeroProof(target, selector);
if (entries[target][selector] != bytes32(0)) revert NonZeroEntry(target, selector);
try IManifestProvable(target).manifestProof(selector) returns (bytes32 returned) {
if (returned == bytes32(0)) revert ZeroProof(target, selector);
if (returned != manifestRoot) revert ProofMismatch(target, selector, manifestRoot, returned);
entries[target][selector] = manifestRoot;
emit SelectorRegistered(target, selector, manifestRoot);
return true;
} catch {
revert ManifestProofFailed(target, selector);
}
}
}