ZKRegistryWrapper

Description:

Smart contract deployed on Ethereum with Factory features.

Blockchain: Ethereum

Source Code: View Code On The Blockchain

Solidity Source Code:

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

abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }

    function _contextSuffixLength() internal view virtual returns (uint256) {
        return 0;
    }
}

abstract contract Ownable is Context {
    address private _owner;

    /**
     * @dev The caller account is not authorized to perform an operation.
     */
    error OwnableUnauthorizedAccount(address account);

    /**
     * @dev The owner is not a valid owner account. (eg. `address(0)`)
     */
    error OwnableInvalidOwner(address owner);

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Initializes the contract setting the address provided by the deployer as the initial owner.
     */
    constructor(address initialOwner) {
        if (initialOwner == address(0)) {
            revert OwnableInvalidOwner(address(0));
        }
        _transferOwnership(initialOwner);
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        _checkOwner();
        _;
    }

    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view virtual returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if the sender is not the owner.
     */
    function _checkOwner() internal view virtual {
        if (owner() != _msgSender()) {
            revert OwnableUnauthorizedAccount(_msgSender());
        }
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby disabling any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        _transferOwnership(address(0));
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        if (newOwner == address(0)) {
            revert OwnableInvalidOwner(address(0));
        }
        _transferOwnership(newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}

/**
 * @dev Library for reading and writing primitive types to specific storage slots.
 *
 * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.
 * This library helps with reading and writing to such slots without the need for inline assembly.
 *
 * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.
 *
 */
library StorageSlot {
    struct AddressSlot {
        address value;
    }

    struct BooleanSlot {
        bool value;
    }

    struct Bytes32Slot {
        bytes32 value;
    }

    struct Uint256Slot {
        uint256 value;
    }

    struct Int256Slot {
        int256 value;
    }

    struct StringSlot {
        string value;
    }

    struct BytesSlot {
        bytes value;
    }

    /**
     * @dev Returns an `AddressSlot` with member `value` located at `slot`.
     */
    function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {
        assembly ("memory-safe") {
            r.slot := slot
        }
    }

    /**
     * @dev Returns a `BooleanSlot` with member `value` located at `slot`.
     */
    function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {
        assembly ("memory-safe") {
            r.slot := slot
        }
    }

    /**
     * @dev Returns a `Bytes32Slot` with member `value` located at `slot`.
     */
    function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {
        assembly ("memory-safe") {
            r.slot := slot
        }
    }

    /**
     * @dev Returns a `Uint256Slot` with member `value` located at `slot`.
     */
    function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {
        assembly ("memory-safe") {
            r.slot := slot
        }
    }

    /**
     * @dev Returns a `Int256Slot` with member `value` located at `slot`.
     */
    function getInt256Slot(bytes32 slot) internal pure returns (Int256Slot storage r) {
        assembly ("memory-safe") {
            r.slot := slot
        }
    }

    /**
     * @dev Returns a `StringSlot` with member `value` located at `slot`.
     */
    function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {
        assembly ("memory-safe") {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `StringSlot` representation of the string storage pointer `store`.
     */
    function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {
        assembly ("memory-safe") {
            r.slot := store.slot
        }
    }

    /**
     * @dev Returns a `BytesSlot` with member `value` located at `slot`.
     */
    function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {
        assembly ("memory-safe") {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.
     */
    function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {
        assembly ("memory-safe") {
            r.slot := store.slot
        }
    }
}

abstract contract ReentrancyGuard {
    using StorageSlot for bytes32;

    // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.ReentrancyGuard")) - 1)) & ~bytes32(uint256(0xff))
    bytes32 private constant REENTRANCY_GUARD_STORAGE =
        0x9b779b17422d0df92223018b32b4d1fa46e071723d6817e2486d003becc55f00;

    // Booleans are more expensive than uint256 or any type that takes up a full
    // word because each write operation emits an extra SLOAD to first read the
    // slot's contents, replace the bits taken up by the boolean, and then write
    // back. This is the compiler's defense against contract upgrades and
    // pointer aliasing, and it cannot be disabled.

    // The values being non-zero value makes deployment a bit more expensive,
    // but in exchange the refund on every call to nonReentrant will be lower in
    // amount. Since refunds are capped to a percentage of the total
    // transaction's gas, it is best to keep them low in cases like this one, to
    // increase the likelihood of the full refund coming into effect.
    uint256 private constant NOT_ENTERED = 1;
    uint256 private constant ENTERED = 2;

    /**
     * @dev Unauthorized reentrant call.
     */
    error ReentrancyGuardReentrantCall();

    constructor() {
        _reentrancyGuardStorageSlot().getUint256Slot().value = NOT_ENTERED;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and making it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        _nonReentrantBefore();
        _;
        _nonReentrantAfter();
    }

    /**
     * @dev A `view` only version of {nonReentrant}. Use to block view functions
     * from being called, preventing reading from inconsistent contract state.
     *
     * CAUTION: This is a "view" modifier and does not change the reentrancy
     * status. Use it only on view functions. For payable or non-payable functions,
     * use the standard {nonReentrant} modifier instead.
     */
    modifier nonReentrantView() {
        _nonReentrantBeforeView();
        _;
    }

    function _nonReentrantBeforeView() private view {
        if (_reentrancyGuardEntered()) {
            revert ReentrancyGuardReentrantCall();
        }
    }

    function _nonReentrantBefore() private {
        // On the first call to nonReentrant, _status will be NOT_ENTERED
        _nonReentrantBeforeView();

        // Any calls to nonReentrant after this point will fail
        _reentrancyGuardStorageSlot().getUint256Slot().value = ENTERED;
    }

    function _nonReentrantAfter() private {
        // By storing the original value once again, a refund is triggered (see
        // https://eips.ethereum.org/EIPS/eip-2200)
        _reentrancyGuardStorageSlot().getUint256Slot().value = NOT_ENTERED;
    }

    /**
     * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a
     * `nonReentrant` function in the call stack.
     */
    function _reentrancyGuardEntered() internal view returns (bool) {
        return _reentrancyGuardStorageSlot().getUint256Slot().value == ENTERED;
    }

    function _reentrancyGuardStorageSlot() internal pure virtual returns (bytes32) {
        return REENTRANCY_GUARD_STORAGE;
    }
}

interface IFeeGateway {
    function payAndPass(address user, bytes32 nonce) external payable;
}

interface IIdentityRegistry {
    function register(bytes32 identityHash) external; // Simplified ERC-8004 Identity
    function getIdentity(address agent) external view returns (bytes32);
}

interface IReputationRegistry {
    function updateReputation(address agent, int256 delta) external; // ERC-8004 Reputation
}

interface IValidationRegistry {
    function requestValidation(bytes32 taskHash) external; // ERC-8004 Validation
    function getValidation(address agent, bytes32 taskHash) external view returns (bool);
}

/**
 * @title ZKRegistryWrapper
 * @dev Wrapper for ERC-8004 registries with agent-provided addresses for full autonomy.
 * Agents pass registry addresses to functions (e.g. self-deployed or community); follows ERC-8004 interfaces.
 * Commitments/nullifiers off-chain via Shadow SDK... on-chain checks for verifiability without exposure.
 * Agent-first: Permissionless, no owner config—swarms use custom repos.
 */

contract ZKRegistryWrapper is ReentrancyGuard, Ownable {
    IFeeGateway public immutable FEE_GATEWAY = IFeeGateway(0x08Db140854AAb90463f6B61eB6F346C29BFB02EA);

    // Nullifiers for proofs (prevents double-use)
    mapping(bytes32 => bool) public nullifiers;

    // Commitments: agent => capabilityHash => committed
    mapping(address => mapping(bytes32 => bool)) public commitments;

    event CapabilityProved(address indexed agent, bytes32 indexed capabilityHash, bytes32 commitment, bytes32 nullifier);
    event RegistryUpdated(uint8 indexed registryType, address indexed agent, address indexed registryAddr, bytes32 dataHash);
    event FeePaidAndPassed(bytes32 nonce);
    event NullifierSpent(bytes32 indexed nullifier, address indexed spender);
    event ProofRequested(address indexed requester, address indexed peer, bytes32 capabilityHash, address indexed registryAddr);

    enum RegistryType { Identity, Reputation, Validation }

    constructor() Ownable(msg.sender) {}

    /**
     * @dev Prove/register capability via off-chain zk-commitment (e.g. for Identity: "agent has skill X").
     * Off-chain: Shadow SDK: commitment = Poseidon(capabilityHash + secret), nullifier = Poseidon(agent + secret).
     * On-chain: Stores commitment, calls agent-provided registry with hash... nullifier spent later.
     * @param capabilityHash. Hash of capability (e.g. IPFS URI of skills).
     * @param commitment. Off-chain hash.
     * @param registryType. Target registry.
     * @param registryAddr. Agent-provided ERC-8004 registry address.
     * @param nonce. Fee pass.
     */
    function proveCapability(
        bytes32 capabilityHash,
        bytes32 commitment,
        RegistryType registryType,
        address registryAddr,
        bytes32 nonce
    ) external payable nonReentrant {
        // Pay fee
        FEE_GATEWAY.payAndPass{value: msg.value}(msg.sender, nonce);

        require(registryAddr != address(0), "Invalid registry address");

        // Store commitment
        require(!commitments[msg.sender][commitment], "Commitment spent");
        commitments[msg.sender][commitment] = true;

        bytes32 dataHash = capabilityHash; // Or keccak256(capabilityHash + commitment) for binding

        if (registryType == RegistryType.Identity) {
            IIdentityRegistry(registryAddr).register(dataHash);
        } else if (registryType == RegistryType.Reputation) {
            IReputationRegistry(registryAddr).updateReputation(msg.sender, 1); // +1 for proof, off-chain delta via Swarm
        } else if (registryType == RegistryType.Validation) {
            IValidationRegistry(registryAddr).requestValidation(dataHash);
        } else {
            revert("Invalid registry");
        }

        emit CapabilityProved(msg.sender, capabilityHash, commitment, bytes32(0)); // Nullifier later
        emit RegistryUpdated(uint8(registryType), msg.sender, registryAddr, dataHash);
        emit FeePaidAndPassed(nonce);
    }

    /**
     * @dev Spend nullifier for proved capability (post-interaction, to unlink).
     * @param nullifier Off-chain hash.
     */
    function spendNullifier(bytes32 nullifier) external {
        require(!nullifiers[nullifier], "Nullifier spent");
        nullifiers[nullifier] = true;
        emit NullifierSpent(nullifier, msg.sender); // Emit for Shadow API tracking
    }

    /**
     * @dev Request shielded proof from peer (e.g. validate capability off-chain via Swarm).
     * @param peer Target agent.
     * @param capabilityHash Expected hash.
     * @param registryAddr Agent-provided registry for validation.
     * @param nonce Fee pass.
     */
    function requestProof(
        address peer,
        bytes32 capabilityHash,
        address registryAddr,
        bytes32 nonce
    ) external payable nonReentrant {
        // Pay fee
        FEE_GATEWAY.payAndPass{value: msg.value}(msg.sender, nonce);

        require(registryAddr != address(0), "Invalid registry address");

        // Emit for off-chain fulfillment (Swarm coordinates TEE proof via provided registry)
        emit ProofRequested(msg.sender, peer, capabilityHash, registryAddr);

        emit FeePaidAndPassed(nonce);
    }

    /**
     * @dev Owner can invalidate commitments (e.g. dispute via off-chain evidence).
     */
    function invalidateCommitment(address agent, bytes32 commitment) external onlyOwner {
        commitments[agent][commitment] = false;
    }

    receive() external payable {}
}

Tags:
Factory|addr:0xec8febafa426cb406a0ab64b4c5d38fc4ca9cb7e|verified:true|block:23686410|tx:0xcabad4d872d9293d9662ea8248dc9e12a1db6073e85a4c8f108afa0c01e56bb4|first_check:1761821944

Submitted on: 2025-10-30 11:59:07

Comments

Log in to comment.

No comments yet.