Manifest Bloom Directory

manifest-bloom-directory · discovery-registry · 1425 B runtime · funds-movement

scores

source

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;

contract ManifestBloomDirectory {
    uint256 private constant REGISTERED = uint256(1) << 255;
    uint256 private constant BLOOM_MASK = type(uint256).max >> 1;
    uint256 public constant RENT = 0.001 ether;

    mapping(address => uint256) private _filters;

    event FilterChanged(address indexed agent, uint256 bloom, bool isNew);

    function update(bytes4[] calldata selectors) external payable {
        bool isNew = _filters[msg.sender] & REGISTERED == 0;
        if (isNew) {
            require(msg.value == RENT, "exact rent required");
        } else {
            require(msg.value == 0, "rent already paid");
        }

        uint256 bloom;
        for (uint256 i = 0; i < selectors.length; i++) {
            bloom |= selectorBits(selectors[i]);
        }

        _filters[msg.sender] = bloom | REGISTERED;
        emit FilterChanged(msg.sender, bloom, isNew);
    }

    function selectorBits(bytes4 selector) public pure returns (uint256 bits) {
        bytes32 h0 = keccak256(abi.encodePacked(selector, uint8(0)));
        bytes32 h1 = keccak256(abi.encodePacked(selector, uint8(1)));
        bytes32 h2 = keccak256(abi.encodePacked(selector, uint8(2)));
        bits = (uint256(1) << (uint256(h0) % 255))
             | (uint256(1) << (uint256(h1) % 255))
             | (uint256(1) << (uint256(h2) % 255));
    }

    function testSelector(address agent, bytes4 selector) external view returns (bool) {
        uint256 bits = selectorBits(selector);
        return (_filters[agent] & bits) == bits;
    }

    function getFilter(address agent) external view returns (uint256 bloom) {
        return _filters[agent] & BLOOM_MASK;
    }

    function isRegistered(address agent) external view returns (bool) {
        return _filters[agent] & REGISTERED != 0;
    }
}