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 {}
}
Submitted on: 2025-10-30 11:59:07
Comments
Log in to comment.
No comments yet.