Blockchain / Global / Address

Contract

0xf6C78baCB27a33fC1d86b6f4abEC4144483F3456

Balance
0 SOMI
Transactions sent
1
Type
Contract · 17,894 bytes of code

State Verified

Compiler
solc 0.8.27+commit.40a35a09
Language
Solidity
Optimization
Yes, 200 runs
EVM version
paris
License
—
Verified
2026-10-12

contracts/State.sol

and 22 more files

Solidity
//SPDX-License-Identifier: UNLICENSED

pragma solidity ^0.8.27;

import {Ownable2StepUpgradeable} from "@openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol";
import {UUPSUpgradeable} from "@openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol";
import {Initializable} from "@openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol";
import {StateLib} from "@iden3/contracts/lib/StateLib.sol";
import {IState} from "@iden3/contracts/interfaces/IState.sol";
import {GenesisUtils} from "@iden3/contracts/lib/GenesisUtils.sol";
import {AuthV3Verifier} from "./verifier/auth-v3-verifier.sol";
import {ForUEntityVerifier} from "./verifier/foru-entity-verifier.sol";
import {StateTransitionVerifier} from "./verifier/state-transition-verifier.sol";
import {CommunityMembershipVerifier} from "./verifier/community-membership-verifier.sol";

contract State is Initializable, Ownable2StepUpgradeable, UUPSUpgradeable{
    using StateLib for StateLib.Data;

    StateLib.Data internal _stateData;
    AuthV3Verifier authV3Verifier;
    ForUEntityVerifier forUEntityVerifier;
    StateTransitionVerifier stateTransitionVerifier;
    CommunityMembershipVerifier communityMembershipVerifier;

    struct EntityInfo {
        uint256 entityId; 
        uint256 entityType; 
    }

    struct MembershipInfo {
        uint256 index;
        uint256 memberRole;
        uint256 memberEntityType;
        uint256 incrementalNonce;
        uint256[8] membershipClaimCore;
    }

    struct DIDRegistrationData {
        uint256 userId;
        uint256 claimIdentity;
        uint256 entityId;
        uint256 entityType; 
        uint256 issuerState;
        uint256 issuerId;
        uint256 incrementalNonce;
        uint256 oldUserState;
        uint256 newUserState;
        bool isOldUserStateGenesis;
        uint256[8] userAuthClaimCore;
        uint256[8] forUEntityClaimCore;
        uint256[2] fvA;
        uint256[2][2] fvb;
        uint256[2] fvc;
        uint256[2] stvA;
        uint256[2][2] stvB;
        uint256[2] stvC;
    }

    struct JoinCommunityData {
        uint256 id;
        uint256 memberRole;
        uint256 memberEntityType;
        uint256 incrementalNonce;
        uint256 communityId;
        uint256 communityState;
        uint256 idAuthChallenge;
        uint256[8] membershipClaimCore;
        uint256[2] avA;
        uint256[2][2] avB;
        uint256[2] avC;
        uint256[2] mvA;
        uint256[2][2] mvB;
        uint256[2] mvC;
    }

    // did => EntityInfo;
    mapping(uint256 => EntityInfo) public entityInfo;
    // did => uint256 nonce
    mapping(uint256 => uint256) public latestDIDIncrementalNonce;
    // did => forUEntityClaim;
    mapping(uint256 => uint256[8]) public didToForUEntityClaimCore;
    // did => authClaim;
    mapping(uint256 => uint256[8]) public didToAuthClaimCore;

    // community did => array user did
    mapping(uint256 => uint256[]) public communityMembership;
    // community did => user did => MembershipInfo
    mapping(uint256 => mapping(uint256 => MembershipInfo)) public communityMembershipInfo;

    uint256 public masterDID;
    // incremental nonce;
    uint256 public latestMasterDIDIncrementalNonce;
    uint256 public totalRegisteredDID;

    event MasterDIDRegistered( uint256 indexed id, uint256 state, uint256[8] authClaimCore);
    event DIDRegistered(uint256 indexed userId, uint256 entityId, uint256 entityType, uint256[8] authClaimCore, uint256[8] forUEntityClaimCore);
    event StateTransitioned(uint256 indexed id, uint256 oldState, uint256 newState, bool isOldStateGenesis);
    event GenesisStateRegistered(uint256 indexed id, uint256 oldState, uint256 newState, bool isOldStateGenesis);
    event IdentityJoinedCommunityRegistered(uint256 indexed communityId, uint256 indexed id, uint256 memberRole, uint256 memberEntityType, uint256[8] membershipClaimCore);

    /// @custom:oz-upgrades-unsafe-allow constructor
    constructor() {
        _disableInitializers();
    }

    function initialize(
        address initialOwnerAddr, 
        address authV3VerifierAddr, 
        address stateTransitionVerifierAddr, 
        address forUEntityVerifierAddr,
        address communityMembershipVerifierAddr
    ) initializer public {
        require(initialOwnerAddr != address(0), "Invalid Initial Owner address");
        require(authV3VerifierAddr != address(0), "Invalid authV3Verifier address");
        require(stateTransitionVerifierAddr != address(0), "Invalid stateTransitionVerifier address");
        require(forUEntityVerifierAddr != address(0), "Invalid forUEntityVerifier address");
        require(communityMembershipVerifierAddr != address(0), "Invalid communityMembershipVerifier address");

        __Ownable_init(initialOwnerAddr);
        __UUPSUpgradeable_init();

        authV3Verifier = AuthV3Verifier(authV3VerifierAddr);
        stateTransitionVerifier = StateTransitionVerifier(stateTransitionVerifierAddr);
        forUEntityVerifier = ForUEntityVerifier(forUEntityVerifierAddr);
        communityMembershipVerifier = CommunityMembershipVerifier(communityMembershipVerifierAddr);
    }

    function _authorizeUpgrade(address newImplementation)
        internal
        onlyOwner
        override
    {}

    /**
     * @dev Set ZKP AuthV3 verifier contract address
     * @param authV3VerifierAddr Verifier contract address
     */
    function setAuthV3Verifier(address authV3VerifierAddr) external virtual onlyOwner {
        authV3Verifier = AuthV3Verifier(authV3VerifierAddr);
    }

     /**
     * @dev Set ZKP state transition verifier contract address
     * @param stateTransitionVerifierAddr Verifier contract address
     */
    function setStateTransitionVerifier(address stateTransitionVerifierAddr) external virtual onlyOwner {
        stateTransitionVerifier = StateTransitionVerifier(stateTransitionVerifierAddr);
    }

     /**
     * @dev Set ZKP ForUEntity verifier contract address
     * @param forUEntityVerifierAddr Verifier contract address
     */
    function setForUEntityVerifier(address forUEntityVerifierAddr) external virtual onlyOwner {
        forUEntityVerifier = ForUEntityVerifier(forUEntityVerifierAddr);
    }

    /**
     * @dev Set ZKP Community membership verifier contract address
     * @param communityMembershipVerifierAddr Verifier contract address
     */
    function setCommunityMembershipVerifier(address communityMembershipVerifierAddr) external virtual onlyOwner {
        communityMembershipVerifier = CommunityMembershipVerifier(communityMembershipVerifierAddr);
    }

    /**
     * @dev Check if identity exists.
     * @param id Identity
     * @return True if the identity exists
     */
    function idExists(uint256 id) public virtual view returns (bool) {
        return _stateData.idExists(id);
    }

    /**
     * @dev Check if state exists.
     * @param id Identity
     * @param state State
     * @return True if the state exists
     */
    function stateExists(uint256 id, uint256 state) public virtual view returns (bool) {
        return _stateData.stateExists(id, state);
    }

    /**
     * @dev Check if identity exist in community.
     * @param communityId Community Identity
     * @param id Identity
     * @return True if the identity exists
     */
    function membershipExists(uint256 communityId, uint256 id) public virtual view returns (bool) {
        MembershipInfo memory membershipInfo = communityMembershipInfo[communityId][id];
        return membershipInfo.membershipClaimCore[0] > 0;
    }

    /**
     * @dev Check if authentication proof valid.
     * @param id Identity
     * @param challenge random number for challenge in authentication
     * @param pa ZKP proof field
     * @param pb ZKP proof field
     * @param pc ZKP proof field
     * @return True if the proof valid
     */
    function verifyAuthV3Proof(
        uint256 id,
        uint256 challenge,
        uint256[2] memory pa,
        uint256[2][2] memory pb,
        uint256[2] memory pc
    ) public virtual view returns (bool) {
        uint256[2] memory input = [id, challenge];
      
        return authV3Verifier.verifyProof(pa, pb, pc, input);
    }

    /**
     * @dev Check if community membership proof valid.
     * @param communityId Identity
     * @param id Identity
     * @param memberRole member role
     * @param memberEntityType member entity type
     * @param incrementalNonce incremental nonce of membership
     * @param communityState community latest state
     * @param pa ZKP proof field
     * @param pb ZKP proof field
     * @param pc ZKP proof field
     * @return True if the proof valid
     */
    function verifyCommunityMembershipProof(
        uint256 communityId,
        uint256 id,
        uint256 memberRole,
        uint256 memberEntityType,
        uint256 incrementalNonce,
        uint256 communityState,
        uint256[2] memory pa,
        uint256[2][2] memory pb,
        uint256[2] memory pc
    ) public virtual view returns (bool) {
        uint256[6] memory input = [id, memberRole, incrementalNonce, memberEntityType, communityState, communityId];
      
        return communityMembershipVerifier.verifyProof(pa, pb, pc, input);
    }

    function registerDID(DIDRegistrationData memory data) public virtual {
        require(isEntityTypeSupported(data.entityType), "Entity type is not supported");
        require(data.issuerId == masterDID, "Invalid issuer ID");

        uint256[7] memory fvInput = [data.userId, data.claimIdentity, data.entityId, data.entityType, data.incrementalNonce, data.issuerState, data.issuerId];
    
        require(
            forUEntityVerifier.verifyProof(data.fvA, data.fvb, data.fvc, fvInput),
            "Zero-knowledge proof of foru entity is not valid"
        );

        uint256[4] memory stvInput = [data.userId, data.oldUserState, data.newUserState, data.isOldUserStateGenesis ? 1 : 0];
      
        require(
            stateTransitionVerifier.verifyProof(data.stvA, data.stvB, data.stvC, stvInput),
            "Zero-knowledge proof of state transition is not valid"
        );

        if (data.incrementalNonce > latestMasterDIDIncrementalNonce) {
            latestMasterDIDIncrementalNonce =  data.incrementalNonce;
            StateLib.EntryInfo memory prevStateInfo = _stateData.getStateInfoById(data.issuerId);
            if (prevStateInfo.state != data.issuerState) {
                _transitState(data.issuerId, prevStateInfo.state, data.issuerState, prevStateInfo.createdAtBlock == 0);
            }
        }

        entityInfo[data.userId] = EntityInfo({
            entityId: data.entityId,
            entityType: data.entityType
        });

        didToAuthClaimCore[data.userId] = data.userAuthClaimCore;
        didToForUEntityClaimCore[data.userId] = data.forUEntityClaimCore;
    
        _transitState(data.userId, data.oldUserState, data.newUserState, data.isOldUserStateGenesis);

        totalRegisteredDID += 1;

        emit DIDRegistered(data.userId, data.entityId, data.entityType, data.userAuthClaimCore, data.forUEntityClaimCore);
    }

    function registerMasterDID(
        uint256 id,
        uint256 oldState,
        uint256 newState,
        bool isOldStateGenesis,
        uint256[8] memory authClaimCore,
        uint256[2] memory a,
        uint256[2][2] memory b,
        uint256[2] memory c
    ) public virtual onlyOwner {
        require(masterDID == 0, "Master DID already registered");

        transitState(id, oldState, newState, isOldStateGenesis, a, b, c);

        masterDID = id;
        didToAuthClaimCore[id] = authClaimCore;

        entityInfo[id] = EntityInfo({
            entityId: 0,
            entityType: 0
        });

        totalRegisteredDID += 1;

        emit MasterDIDRegistered(id, newState, authClaimCore);
    }

    function registerCommunityDID(DIDRegistrationData memory data, JoinCommunityData memory joinData) public virtual {
        require(isEntityTypeSupported(data.entityType), "Entity type is not supported");
        require(data.entityType == 2, "Invalid entity type");

        registerDID(data);
        joinCommunity(joinData);
    }

    function joinCommunity(JoinCommunityData memory data) public virtual {
        require(
            verifyAuthV3Proof(data.id, data.idAuthChallenge, data.avA, data.avB, data.avC),
            "Zero-knowledge proof of user authentication is not valid"
        );

        require(
            verifyCommunityMembershipProof(
                data.communityId, 
                data.id,
                data.memberRole,
                data.memberEntityType,
                data.incrementalNonce, 
                data.communityState,
                data.mvA,
                data.mvB,
                data.mvC
            ),
            "Zero-knowledge proof of community membership is not valid"
        );

        _joinCommunity(data.communityId, data.id, data.memberRole, data.memberEntityType, data.incrementalNonce, data.membershipClaimCore);
        if (data.incrementalNonce > latestDIDIncrementalNonce[data.communityId]) {
            latestDIDIncrementalNonce[data.communityId] = data.incrementalNonce;
            StateLib.EntryInfo memory prevStateInfo = _stateData.getStateInfoById(data.communityId);
            if (prevStateInfo.state != data.communityState) {
                _transitState(data.communityId, prevStateInfo.state, data.communityState, prevStateInfo.createdAtBlock == 0);
            }
        }
    }

    function _joinCommunity(
        uint256 communityId,
        uint256 id,
        uint256 memberRole,
        uint256 memberEntityType,
        uint256 incrementalNonce,
        uint256[8] memory membershipClaimCore
    ) internal virtual {
        require(communityId != id, "Can not register own identity");
        require(idExists(communityId), "Community identity is not registered");
        require(entityInfo[communityId].entityType == 2, "Invalid community identity type");
        require(idExists(id), "Identity is not registered");
        require(!membershipExists(communityId, id), "Identity already member of community");

        uint256 index = communityMembership[communityId].length;
        communityMembershipInfo[communityId][id] = MembershipInfo({
            index: index,
            memberRole: memberRole,
            memberEntityType: memberEntityType,
            incrementalNonce: incrementalNonce,
            membershipClaimCore: membershipClaimCore
        });

        communityMembership[communityId].push(id);

        emit IdentityJoinedCommunityRegistered(communityId, id, memberRole, memberEntityType, membershipClaimCore);
    }

     /**
     * @dev Change the state of an identity (transit to the new state) with ZKP ownership check.
     * @param id Identity
     * @param oldState Previous identity state
     * @param newState New identity state
     * @param isOldStateGenesis Is the previous state genesis?
     * @param a ZKP proof field
     * @param b ZKP proof field
     * @param c ZKP proof field
     */
    function transitState(
        uint256 id,
        uint256 oldState,
        uint256 newState,
        bool isOldStateGenesis,
        uint256[2] memory a,
        uint256[2][2] memory b,
        uint256[2] memory c
    ) public virtual {
        uint256[4] memory input = [id, oldState, newState, uint256(isOldStateGenesis ? 1 : 0)];
        require(
            stateTransitionVerifier.verifyProof(a, b, c, input),
            "Zero-knowledge proof of state transition is not valid"
        );

        _transitState(id, oldState, newState, isOldStateGenesis);

        if (id == masterDID) {
            latestMasterDIDIncrementalNonce += 1;
        } else {
            latestDIDIncrementalNonce[id] = latestDIDIncrementalNonce[id] + 1;
        }
    }

     /**
     * @dev Change the state of an identity (transit to the new state) with ZKP ownership check.
     * @param id Identity
     * @param oldState Previous identity state
     * @param newState New identity state
     * @param isOldStateGenesis Is the previous state genesis?
     */
    function _transitState(
        uint256 id,
        uint256 oldState,
        uint256 newState,
        bool isOldStateGenesis
    ) internal virtual {
        require(id != 0, "ID should not be zero");
        require(newState != 0, "New state should not be zero");

        if (oldState == newState) {
            require(isOldStateGenesis, "isOldStateGenesis must be true");
            require(!idExists(id), "Identic old and new state but id already exist");
        }

        if (isOldStateGenesis) {
            if (!idExists(id)) {
                _stateData.addGenesisState(id, oldState);
                emit GenesisStateRegistered(id, oldState, newState, isOldStateGenesis);
            }
        } else {
            require(idExists(id), "Old state is not genesis but identity does not yet exist");
        }

        // this checks that oldState != newState as well
        // only push the new state if the state is not equal with old state
        if (oldState != newState) {
            require(idExists(id), "Identity is not exist");
            require(!stateExists(id, newState), "New state already exists");
            StateLib.EntryInfo memory prevStateInfo = _stateData.getStateInfoById(id);
            require(prevStateInfo.state == oldState, "Old state does not match the latest state");

            _stateData.addState(id, newState);

            emit StateTransitioned(id, oldState, newState, isOldStateGenesis);
        }
    }

    /**
     * @dev Retrieves the foru entity claim data associated with a given id.
     * @param id The DID or identity identifier.
     * @return forUEntityClaimCore The hex core of the claim.
     */
    function getForUEntityClaimCore(uint256 id) external virtual view returns (uint256[8] memory) {
        require(_stateData.idExists(id), "State does not exist for the given id");
        return didToForUEntityClaimCore[id];
    }

    /**
     * @dev Retrieves the foru entity claim data associated with a given id.
     * @param id The DID or identity identifier.
     * @return authClaimCore The hex core of the claim.
     */
    function getAuthClaimCore(uint256 id) external virtual view returns (uint256[8] memory) {
        require(_stateData.idExists(id), "State does not exist for the given id");
        return didToAuthClaimCore[id];
    }

    /**
     * @dev Retrieves the member claim data associated with a given id.
     * @param communityId The DID or identity of community
     * @param id The DID or identity identifier.
     * @return membershipClaimCore The hex core of the claim.
     */
    function getMembershipClaimCore(uint256 communityId, uint256 id) external virtual view returns (uint256[8] memory) {
        require(membershipExists(communityId, id), "Identity is not member of community");
        MembershipInfo memory membershipInfo = this.getMembershipInfoId(communityId, id);
        return membershipInfo.membershipClaimCore;
    }

    /**
     * @dev Retrieve the membership info of identity
     * @param communityId The DID or identity of community
     * @param id identity
     * @return membershipInfo membership info of identity
     */
    function getMembershipInfoId(uint256 communityId, uint256 id) external virtual view returns (MembershipInfo memory membershipInfo) {
        return communityMembershipInfo[communityId][id];
    }

    /**
     * @dev Retrieve the last state info for a given identity
     * @param id identity
     * @return State info of the last committed state
     */
    function getStateInfoById(uint256 id) external virtual view returns (IState.StateInfo memory) {
        return _stateEntryInfoAdapter(_stateData.getStateInfoById(id));
    }

    /**
     * @dev Retrieve states quantity for a given identity
     * @param id identity
     * @return States quantity
     */
    function getStateInfoHistoryLengthById(uint256 id) external virtual view returns (uint256) {
        return _stateData.getStateInfoHistoryLengthById(id);
    }

    /**
     * Retrieve state infos for a given identity
     * @param id identity
     * @param startIndex start index of the state history
     * @param length length of the state history
     * @return A list of state infos of the identity
     */
    function getStateInfoHistoryById(
        uint256 id,
        uint256 startIndex,
        uint256 length
    ) external virtual view returns (IState.StateInfo[] memory) {
        StateLib.EntryInfo[] memory stateInfos = _stateData.getStateInfoHistoryById(
            id,
            startIndex,
            length
        );
        IState.StateInfo[] memory result = new IState.StateInfo[](stateInfos.length);
        for (uint256 i = 0; i < stateInfos.length; i++) {
            result[i] = _stateEntryInfoAdapter(stateInfos[i]);
        }
        return result;
    }

     /**
     * @dev Retrieve state information by id and state.
     * @param id An identity.
     * @param state A state.
     * @return The state info.
     */
    function getStateInfoByIdAndState(
        uint256 id,
        uint256 state
    ) external virtual view returns (IState.StateInfo memory) {
        return _stateEntryInfoAdapter(_stateData.getStateInfoByIdAndState(id, state));
    }

     /**
     * @dev Retrieve the timestamp when the state was replaced by another state.
     * @param id Identity id
     * @param state State of the identity
     * @return replacedAt The timestamp when the state of the identity was replaced by another state
     */
    function getStateReplacedAt(uint256 id, uint256 state) external virtual view returns (uint256) {
        if (_stateData.stateExists(id, state)) {
            return _stateData.getStateInfoByIdAndState(id, state).replacedAtTimestamp;
        } else if (GenesisUtils.isGenesisState(id, state)) {
            return 0;
        }
        revert("State entry not found");
    }

    /**
     * @dev Converts a `StateLib.EntryInfo` struct into an `IState.StateInfo` struct.
     * @param sei The state entry information as defined by `StateLib.EntryInfo`.
     * @return A new `IState.StateInfo` struct containing the mapped state information.
     */
    function _stateEntryInfoAdapter(
        StateLib.EntryInfo memory sei
    ) internal virtual pure returns (IState.StateInfo memory) {
        return IState.StateInfo({
            id: sei.id,
            state: sei.state,
            replacedByState: sei.replacedByState,
            createdAtTimestamp: sei.createdAtTimestamp,
            replacedAtTimestamp: sei.replacedAtTimestamp,
            createdAtBlock: sei.createdAtBlock,
            replacedAtBlock: sei.replacedAtBlock
        });
    }

     /**
     * @dev Check if id type supported
     * @param entityType id type to check
     * @return True if the id type is supported
     */
    function isEntityTypeSupported(uint256 entityType) public virtual pure returns (bool) {
        return entityType < 4;
    }

    /**
     * Retrieve community member identity list
     * @param communityId community identity
     * @param startIndex start index of the state history
     * @param length length of the state history
     * @return memberIdentityList A list member identity
     */
    function getCommunityMemberList(
        uint256 communityId,
        uint256 startIndex,
        uint256 length
    ) external virtual view returns (uint256[] memory memberIdentityList) {
        if (length > communityMembership[communityId].length || startIndex >= communityMembership[communityId].length) {
            return new uint256[](0);
        }

        uint256[] memory result = new uint256[](length);
        for (uint256 i = startIndex; i < length; i++) {
            result[i] = communityMembership[communityId][i];
        }
        return result;
    }
}

Other files

  • @iden3/contracts/interfaces/IState.sol
    // SPDX-License-Identifier: GPL-3.0
    pragma solidity 0.8.27;
    
    // TODO changing this value don't forget to change GistProof.siblings array size
    // figure out how to reuse the constant in the array size
    // without compiler error
    uint256 constant MAX_SMT_DEPTH = 64;
    
    interface IState {
        /**
         * @dev Struct for public interfaces to represent a state information.
         * @param id An identity.
         * @param state A state.
         * @param replacedByState A state, which replaced this state for the identity.
         * @param createdAtTimestamp A time when the state was created.
         * @param replacedAtTimestamp A time when the state was replaced by the next identity state.
         * @param createdAtBlock A block number when the state was created.
         * @param replacedAtBlock A block number when the state was replaced by the next identity state.
         */
        struct StateInfo {
            uint256 id;
            uint256 state;
            uint256 replacedByState;
            uint256 createdAtTimestamp;
            uint256 replacedAtTimestamp;
            uint256 createdAtBlock;
            uint256 replacedAtBlock;
        }
    
        /**
         * @dev Struct for public interfaces to represent GIST root information.
         * @param root This GIST root.
         * @param replacedByRoot A root, which replaced this root.
         * @param createdAtTimestamp A time, when the root was saved to blockchain.
         * @param replacedAtTimestamp A time, when the root was replaced by the next root in blockchain.
         * @param createdAtBlock A number of block, when the root was saved to blockchain.
         * @param replacedAtBlock A number of block, when the root was replaced by the next root in blockchain.
         */
        struct GistRootInfo {
            uint256 root;
            uint256 replacedByRoot;
            uint256 createdAtTimestamp;
            uint256 replacedAtTimestamp;
            uint256 createdAtBlock;
            uint256 replacedAtBlock;
        }
    
        /**
         * @dev Struct for public interfaces to represent GIST proof information.
         * @param root This GIST root.
         * @param existence A flag, which shows if the leaf index exists in the GIST.
         * @param siblings An array of GIST sibling node hashes.
         * @param index An index of the leaf in the GIST.
         * @param value A value of the leaf in the GIST.
         * @param auxExistence A flag, which shows if the auxiliary leaf exists in the GIST.
         * @param auxIndex An index of the auxiliary leaf in the GIST.
         * @param auxValue An value of the auxiliary leaf in the GIST.
         */
        struct GistProof {
            uint256 root;
            bool existence;
            uint256[64] siblings; // TODO figure out the way how to use the MAX_SMT_DEPTH constant
            uint256 index;
            uint256 value;
            bool auxExistence;
            uint256 auxIndex;
            uint256 auxValue;
        }
        /**
         * @dev Struct for signed identity states.
         * @param idStateMsg Message of the identity state.
         * @param signature Signature of the message.
         */
        struct IdentityStateUpdate {
            IdentityStateMessage idStateMsg;
            bytes signature;
        }
        /**
         * @dev Struct for signed global states.
         * @param globalStateMsg Message of the global state.
         * @param signature Signature of the message.
         */
        struct GlobalStateUpdate {
            GlobalStateMessage globalStateMsg;
            bytes signature;
        }
        /**
         * @dev Struct for identity state message.
         * @param timestamp Timestamp when the message was signed.
         * @param id Id of the identity.
         * @param state State of the identity.
         * @param replacedAtTimestamp Timestamp when the state was replaced by next identity state.
         */
        struct IdentityStateMessage {
            uint256 timestamp;
            uint256 id;
            uint256 state;
            uint256 replacedAtTimestamp;
        }
    
        /**
         * @dev Struct for global state message.
         * @param timestamp Timestamp when the message was signed.
         * @param idType Id type of the chain.
         * @param root Root of the global state.
         * @param replacedAtTimestamp Timestamp when the global state was replaced by next global state.
         */
        struct GlobalStateMessage {
            uint256 timestamp;
            bytes2 idType;
            uint256 root;
            uint256 replacedAtTimestamp;
        }
        /**
         * @dev Struct for cross chain proof.
         * @param proofType Proof type for the proof provided ("stateProof", "globalStateProof").
         * @param proof Cross chain proof.
         */
        struct CrossChainProof {
            string proofType;
            bytes proof;
        }
    
        /**
         * @dev Struct for global state process result.
         * @param idType Id type of the chain.
         * @param root Root of the global state.
         * @param replacedAtTimestamp Timestamp when the global state was replaced by next global state.
         */
        struct GlobalStateProcessResult {
            bytes2 idType;
            uint256 root;
            uint256 replacedAtTimestamp;
        }
        /**
         * @dev Struct for identity state process result.
         * @param id Id of the identity.
         * @param state State of the identity.
         * @param replacedAtTimestamp Timestamp when the identity state was replaced by next identity state.
         */
        struct IdentityStateProcessResult {
            uint256 id;
            uint256 state;
            uint256 replacedAtTimestamp;
        }
    
        /**
         * @dev Retrieve last state information of specific id.
         * @param id An identity.
         * @return The state info.
         */
        function getStateInfoById(uint256 id) external view returns (StateInfo memory);
    
        /**
         * @dev Retrieve state information by id and state.
         * @param id An identity.
         * @param state A state.
         * @return The state info.
         */
        function getStateInfoByIdAndState(
            uint256 id,
            uint256 state
        ) external view returns (StateInfo memory);
    
        /**
         * @dev Retrieve the specific GIST root information.
         * @param root GIST root.
         * @return The GIST root info.
         */
        function getGISTRootInfo(uint256 root) external view returns (GistRootInfo memory);
    
        /**
         * @dev Check if the id type supported.
         * @param idType id type.
         * @return True if the id type supported.
         */
        function isIdTypeSupported(bytes2 idType) external view returns (bool);
    
        /**
         * @dev Get id if the id type supported for the id, otherwise revert.
         * @param id An identity.
         * @return The id type.
         */
        function getIdTypeIfSupported(uint256 id) external view returns (bytes2);
    
        /**
         * @dev Get defaultIdType
         * @return defaultIdType
         */
        function getDefaultIdType() external view returns (bytes2);
    
        /**
         * @dev Performs state transition
         * @param id Identifier of the identity
         * @param oldState Previous state of the identity
         * @param newState New state of the identity
         * @param isOldStateGenesis Flag if previous identity state is genesis
         * @param a Proof.A
         * @param b Proof.B
         * @param c Proof.C
         */
        function transitState(
            uint256 id,
            uint256 oldState,
            uint256 newState,
            bool isOldStateGenesis,
            uint256[2] memory a,
            uint256[2][2] memory b,
            uint256[2] memory c
        ) external;
    
        /**
         * @dev Performs state transition
         * @param id Identity
         * @param oldState Previous identity state
         * @param newState New identity state
         * @param isOldStateGenesis Is the previous state genesis?
         * @param methodId State transition method id
         * @param methodParams State transition method-specific params
         */
        function transitStateGeneric(
            uint256 id,
            uint256 oldState,
            uint256 newState,
            bool isOldStateGenesis,
            uint256 methodId,
            bytes calldata methodParams
        ) external;
    
        /**
         * @dev Check if identity exists.
         * @param id Identity
         * @return True if the identity exists
         */
        function idExists(uint256 id) external view returns (bool);
    
        /**
         * @dev Check if state exists.
         * @param id Identity
         * @param state State
         * @return True if the state exists
         */
        function stateExists(uint256 id, uint256 state) external view returns (bool);
    
        /**
         * @dev Get timestamp when the identity state was replaced.
         * @param id Identity
         * @param state State of the identity
         * @return replacedAtTimestamp Timestamp when the identity state was replaced by new identity state
         */
        function getStateReplacedAt(
            uint256 id,
            uint256 state
        ) external view returns (uint256 replacedAtTimestamp);
    
        /**
         * @dev Get timestamp when the global state was replaced.
         * @param idType Id type of the chain
         * @param root Root of the global state
         * @return replacedAtTimestamp Timestamp when the global state was replaced by new global state
         */
        function getGistRootReplacedAt(
            bytes2 idType,
            uint256 root
        ) external view returns (uint256 replacedAtTimestamp);
    
        /**
         * @dev Process the cross chain proofs with the identities and global states.
         * @param proofs Proofs with the identities and global states
         */
        function processCrossChainProofs(bytes calldata proofs) external;
    }
    
  • @iden3/contracts/lib/ArrayUtils.sol
    // SPDX-License-Identifier: GPL-3.0
    pragma solidity 0.8.27;
    
    /// @title A common functions for arrays.
    library ArrayUtils {
        /**
         * @dev Calculates bounds for the slice of the array.
         * @param arrLength An array length.
         * @param start A start index.
         * @param length A length of the slice.
         * @param limit A limit for the length.
         * @return The bounds for the slice of the array.
         */
        function calculateBounds(
            uint256 arrLength,
            uint256 start,
            uint256 length,
            uint256 limit
        ) internal pure returns (uint256, uint256) {
            require(length > 0, "Length should be greater than 0");
            require(length <= limit, "Length limit exceeded");
            require(start < arrLength, "Start index out of bounds");
    
            uint256 end = start + length;
            if (end > arrLength) {
                end = arrLength;
            }
    
            return (start, end);
        }
    }
    
  • @iden3/contracts/lib/GenesisUtils.sol
    // SPDX-License-Identifier: GPL-3.0
    pragma solidity 0.8.27;
    
    import {PrimitiveTypeUtils} from "./PrimitiveTypeUtils.sol";
    
    library GenesisUtils {
        /**
         *   @dev sum
         */
        function sum(bytes memory array) internal pure returns (uint16 s) {
            require(array.length == 29, "Checksum requires 29 length array");
    
            for (uint256 i = 0; i < array.length; ++i) {
                s += uint16(uint8(array[i]));
            }
        }
    
        /**
         * @dev isGenesisState
         */
        function isGenesisState(uint256 id, uint256 idState) internal pure returns (bool) {
            bytes2 idType = getIdType(id);
            uint256 computedId = calcIdFromGenesisState(idType, idState);
            return id == computedId;
        }
    
        /**
         * @dev getIdType
         */
        function getIdType(uint256 id) internal pure returns (bytes2) {
            return bytes2(PrimitiveTypeUtils.uint256ToBytes(PrimitiveTypeUtils.reverseUint256(id)));
        }
    
        /**
         * @dev calcIdFromGenesisState
         */
        function calcIdFromGenesisState(
            bytes2 idType,
            uint256 idState
        ) internal pure returns (uint256) {
            bytes memory userStateB1 = PrimitiveTypeUtils.uint256ToBytes(
                PrimitiveTypeUtils.reverseUint256(idState)
            );
    
            bytes memory cutState = PrimitiveTypeUtils.slice(userStateB1, userStateB1.length - 27, 27);
            bytes memory beforeChecksum = PrimitiveTypeUtils.concat(abi.encodePacked(idType), cutState);
    
            uint16 checksum = PrimitiveTypeUtils.reverseUint16(sum(beforeChecksum));
            bytes memory checkSumBytes = abi.encodePacked(checksum);
    
            bytes memory idBytes = PrimitiveTypeUtils.concat(beforeChecksum, checkSumBytes);
            require(idBytes.length == 31, "idBytes requires 31 length array");
    
            return PrimitiveTypeUtils.reverseUint256(PrimitiveTypeUtils.padRightToUint256(idBytes));
        }
    
        /**
         * @dev calcIdFromEthAddress
         */
        function calcIdFromEthAddress(bytes2 idType, address caller) internal pure returns (uint256) {
            uint256 addr = PrimitiveTypeUtils.addressToUint256(caller);
    
            return calcIdFromGenesisState(idType, PrimitiveTypeUtils.reverseUint256(addr));
        }
    }
    
  • @iden3/contracts/lib/PrimitiveTypeUtils.sol
    // SPDX-License-Identifier: GPL-3.0
    pragma solidity 0.8.27;
    
    import {BytesLib} from "solidity-bytes-utils/contracts/BytesLib.sol";
    
    library PrimitiveTypeUtils {
        /**
         * @dev uint256ToBytes
         */
        function uint256ToBytes(uint256 x) internal pure returns (bytes memory b) {
            b = new bytes(32);
            assembly {
                mstore(add(b, 32), x)
            }
        }
    
        /**
         * @dev reverse uint256
         */
        function reverseUint256(uint256 input) internal pure returns (uint256 v) {
            v = input;
    
            // swap bytes
            v =
                ((v & 0xFF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00) >> 8) |
                ((v & 0x00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF00FF) << 8);
    
            // swap 2-byte long pairs
            v =
                ((v & 0xFFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000) >> 16) |
                ((v & 0x0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF0000FFFF) << 16);
    
            // swap 4-byte long pairs
            v =
                ((v & 0xFFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000) >> 32) |
                ((v & 0x00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF00000000FFFFFFFF) << 32);
    
            // swap 8-byte long pairs
            v =
                ((v & 0xFFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF0000000000000000) >> 64) |
                ((v & 0x0000000000000000FFFFFFFFFFFFFFFF0000000000000000FFFFFFFFFFFFFFFF) << 64);
    
            // swap 16-byte long pairs
            v = (v >> 128) | (v << 128);
        }
    
        /**
         * @dev reverse uint16
         */
        function reverseUint16(uint16 input) internal pure returns (uint16 v) {
            v = input;
    
            // swap bytes
            v = (v >> 8) | (v << 8);
        }
    
        /**
         * @dev reverse uint32
         */
        function reverseUint32(uint32 input) internal pure returns (uint32 v) {
            v = input;
    
            // swap bytes
            v = ((v & 0xFF00FF00) >> 8) | ((v & 0x00FF00FF) << 8);
    
            // swap 2-byte long pairs
            v = (v >> 16) | (v << 16);
        }
    
        /**
         * @dev compareStrings
         */
        function compareStrings(string memory a, string memory b) internal pure returns (bool) {
            if (bytes(a).length != bytes(b).length) {
                return false;
            }
            return (keccak256(abi.encodePacked((a))) == keccak256(abi.encodePacked((b))));
        }
    
        /**
         * @dev padRightToUint256 shift left 12 bytes
         * @param b, bytes array with max length 32, other bytes are cut. e.g. 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266
         * @return value e.g 0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266000000000000000000000000
         */
        function padRightToUint256(bytes memory b) internal pure returns (uint256 value) {
            return uint256(bytes32(b));
        }
    
        /**
         * @dev bytesToAddress
         */
        function bytesToAddress(bytes memory bys) internal pure returns (address addr) {
            assembly {
                addr := mload(add(bys, 20))
            }
        }
    
        /**
         * @dev concat
         */
        function concat(
            bytes memory preBytes,
            bytes memory postBytes
        ) internal pure returns (bytes memory) {
            return BytesLib.concat(preBytes, postBytes);
        }
    
        /**
         * @dev slice
         */
        function slice(
            bytes memory bys,
            uint256 start,
            uint256 length
        ) internal pure returns (bytes memory) {
            return BytesLib.slice(bys, start, length);
        }
    
        /**
         * @dev addressToUint256 converts address to uint256 which lower 20 bytes
         * is an address in Big Endian
         * @param _addr is ethereum address: eg.0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266
         * which as 0x000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266 converted to uint160
         * @return uint256 representation of address 1390849295786071768276380950238675083608645509734
         */
        function addressToUint256(address _addr) internal pure returns (uint256) {
            return uint256(uint160(_addr));
        }
    
        /**
         * @dev uint256ToAddress converts uint256 which lower 20 bytes
         * is an address in Big Endian to address
         * @param input uint256 e.g. 1390849295786071768276380950238675083608645509734
         * which as 0x000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266 converted to address
         * @return address representation of uint256 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266
         */
        function uint256ToAddress(uint256 input) internal pure returns (address) {
            require(
                input == uint256(uint160(input)),
                "given input is not a representation of address, 12 most significant bytes should be zero"
            );
            return address(uint160(input));
        }
    
        /**
         * @dev addressToChallenge converts address to uint256 which lower 20 bytes
         * are representation of address in LittleEndian
         * @param _addr is ethereum address: eg.0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266
         * addressToBytes: 0x000000000000000000000000f39fd6e51aad88f6f4ce6ab8827279cfffb92266
         * padRightToUint256: 0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266000000000000000000000000,
         * reverseUint256 result: 0x0000000000000000000000006622b9ffcf797282b86acef4f688ad1ae5d69ff3
         * @return uint256: 583091486781463398742321306787801699791102451699
         */
        function addressToUint256LE(address _addr) internal pure returns (uint256) {
            return reverseUint256(padRightToUint256(addressToBytes(_addr)));
        }
    
        /**
         * @dev uint256LEtoAddress - converts uint256 which 20 lower bytes
         *      are representation of address in LE to address
         * @param input is uint256 which is created from bytes in LittleEndian:
         * eg. 583091486781463398742321306787801699791102451699
         *  or 0x0000000000000000000000006622b9ffcf797282b86acef4f688ad1ae5d69ff3
         * reverseUint256 result: 110194434039389003190498847789203126033799499726478230611233094447786700570624
         * uint256ToBytes result: 0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266000000000000000000000000
         * @return address - 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266
         */
        function uint256LEToAddress(uint256 input) internal pure returns (address) {
            require(
                input == uint256(uint160(input)),
                "given uint256 is not a representation of an address, 12 most significant bytes should be zero"
            );
            return bytesToAddress(uint256ToBytes(reverseUint256(input)));
        }
    
        function addressToBytes(address a) internal pure returns (bytes memory) {
            return abi.encodePacked(a);
        }
    }
    
  • @iden3/contracts/lib/StateLib.sol
    // SPDX-License-Identifier: GPL-3.0
    pragma solidity 0.8.27;
    
    import {ArrayUtils} from "../lib/ArrayUtils.sol";
    
    /// @title Library for state data management.
    // It's purpose is to keep records of identity states along with their metadata and history.
    library StateLib {
        /**
         * @dev Max return array length for id history requests
         */
        uint256 public constant ID_HISTORY_RETURN_LIMIT = 1000;
    
        /**
         * @dev Struct for public interfaces to represent a state information.
         * @param id identity.
         * @param state A state.
         * @param replacedByState A state, which replaced this state for the identity.
         * @param createdAtTimestamp A time when the state was created.
         * @param replacedAtTimestamp A time when the state was replaced by the next identity state.
         * @param createdAtBlock A block number when the state was created.
         * @param replacedAtBlock A block number when the state was replaced by the next identity state.
         */
        struct EntryInfo {
            uint256 id;
            uint256 state;
            uint256 replacedByState;
            uint256 createdAtTimestamp;
            uint256 replacedAtTimestamp;
            uint256 createdAtBlock;
            uint256 replacedAtBlock;
        }
    
        /**
         * @dev Struct for identity state internal storage representation.
         * @param state A state.
         * @param timestamp A time when the state was committed to blockchain.
         * @param block A block number when the state was committed to blockchain.
         */
        struct Entry {
            uint256 state;
            uint256 timestamp;
            uint256 block;
        }
    
        /**
         * @dev Struct for storing all the state data.
         * We assume that a state can repeat more than once for the same identity,
         * so we keep a mapping of state entries per each identity and state.
         * @param statesHistories A state history per each identity.
         * @param stateEntries A state metadata of each state.
         */
        struct Data {
            /*
            id => stateEntry[]
            --------------------------------
            id1 => [
                index 0: StateEntry1 {state1, timestamp2, block1},
                index 1: StateEntry2 {state2, timestamp2, block2},
                index 2: StateEntry3 {state1, timestamp3, block3}
            ]
            */
            mapping(uint256 => Entry[]) stateEntries;
            /*
            id => state => stateEntryIndex[]
            -------------------------------
            id1 => state1 => [index0, index2],
            id1 => state2 => [index1]
             */
            mapping(uint256 => mapping(uint256 => uint256[])) stateIndexes;
            // isIdTypeSupported is used to keep track of existing typeIds
            mapping(bytes2 => bool) isIdTypeSupported;
            // This empty reserved space is put in place to allow future versions
            // of the State contract to add new SmtData struct fields without shifting down
            // storage of upgradable contracts that use this struct as a state variable
            // (see https://docs.openzeppelin.com/upgrades-plugins/1.x/writing-upgradeable#storage-gaps)//
            uint256[47] __gap;
        }
    
        /**
         * @dev event called when a state is updated
         * @param id identity
         * @param blockN Block number when the state has been committed
         * @param timestamp Timestamp when the state has been committed
         * @param state Identity state committed
         */
        event StateUpdated(uint256 id, uint256 blockN, uint256 timestamp, uint256 state);
    
        /**
         * @dev Revert if identity does not exist in the contract
         * @param id Identity
         */
        modifier onlyExistingId(Data storage self, uint256 id) {
            require(idExists(self, id), "Identity does not exist");
            _;
        }
    
        /**
         * @dev Revert if state does not exist in the contract
         * @param id Identity
         * @param state State
         */
        modifier onlyExistingState(Data storage self, uint256 id, uint256 state) {
            require(stateExists(self, id, state), "State does not exist");
            _;
        }
    
        /**
         * @dev Add a state to the contract with transaction timestamp and block number.
         * @param id Identity
         * @param state State
         */
        function addState(Data storage self, uint256 id, uint256 state) external {
            _addState(self, id, state, block.timestamp, block.number);
        }
    
        /**
         * @dev Add a state to the contract with zero timestamp and block number.
         * @param id Identity
         * @param state State
         */
        function addGenesisState(Data storage self, uint256 id, uint256 state) external {
            require(
                !idExists(self, id),
                "Zero timestamp and block should be only in the first identity state"
            );
            _addState(self, id, state, 0, 0);
        }
    
        /**
         * @dev Retrieve the last state info for a given identity.
         * @param id Identity.
         * @return State info of the last committed state.
         */
        function getStateInfoById(
            Data storage self,
            uint256 id
        ) external view onlyExistingId(self, id) returns (EntryInfo memory) {
            Entry[] storage stateEntries = self.stateEntries[id];
            Entry memory se = stateEntries[stateEntries.length - 1];
    
            return
                EntryInfo({
                    id: id,
                    state: se.state,
                    replacedByState: 0,
                    createdAtTimestamp: se.timestamp,
                    replacedAtTimestamp: 0,
                    createdAtBlock: se.block,
                    replacedAtBlock: 0
                });
        }
    
        /**
         * @dev Retrieve states quantity for a given identity
         * @param id identity
         * @return states quantity
         */
        function getStateInfoHistoryLengthById(
            Data storage self,
            uint256 id
        ) external view onlyExistingId(self, id) returns (uint256) {
            return self.stateEntries[id].length;
        }
    
        /**
         * Retrieve state infos for a given identity
         * @param id Identity
         * @param startIndex Start index of the state history.
         * @param length Max length of the state history retrieved.
         * @return A list of state infos of the identity
         */
        function getStateInfoHistoryById(
            Data storage self,
            uint256 id,
            uint256 startIndex,
            uint256 length
        ) external view onlyExistingId(self, id) returns (EntryInfo[] memory) {
            (uint256 start, uint256 end) = ArrayUtils.calculateBounds(
                self.stateEntries[id].length,
                startIndex,
                length,
                ID_HISTORY_RETURN_LIMIT
            );
    
            EntryInfo[] memory result = new EntryInfo[](end - start);
    
            for (uint256 i = start; i < end; i++) {
                result[i - start] = _getStateInfoByIndex(self, id, i);
            }
    
            return result;
        }
    
        /**
         * @dev Retrieve state info by id and state.
         * Note, that the latest state info is returned,
         * if the state repeats more that once for the same identity.
         * @param id An identity.
         * @param state A state.
         * @return The state info.
         */
        function getStateInfoByIdAndState(
            Data storage self,
            uint256 id,
            uint256 state
        ) external view onlyExistingState(self, id, state) returns (EntryInfo memory) {
            return _getStateInfoByState(self, id, state);
        }
    
        /**
         * @dev Retrieve state entries quantity by id and state.
         * If the state repeats more that once for the same identity,
         * the length will be greater than 1.
         * @param id An identity.
         * @param state A state.
         * @return The state info list length.
         */
        function getStateInfoListLengthByIdAndState(
            Data storage self,
            uint256 id,
            uint256 state
        ) external view returns (uint256) {
            return self.stateIndexes[id][state].length;
        }
    
        /**
         * @dev Retrieve state info list by id and state.
         * If the state repeats more that once for the same identity,
         * the length of the list may be greater than 1.
         * @param id An identity.
         * @param state A state.
         * @param startIndex Start index in the same states list.
         * @param length Max length of the state info list retrieved.
         * @return The state info list.
         */
        function getStateInfoListByIdAndState(
            Data storage self,
            uint256 id,
            uint256 state,
            uint256 startIndex,
            uint256 length
        ) external view onlyExistingState(self, id, state) returns (EntryInfo[] memory) {
            uint256[] storage stateIndexes = self.stateIndexes[id][state];
            (uint256 start, uint256 end) = ArrayUtils.calculateBounds(
                stateIndexes.length,
                startIndex,
                length,
                ID_HISTORY_RETURN_LIMIT
            );
    
            EntryInfo[] memory result = new EntryInfo[](end - start);
            for (uint256 i = start; i < end; i++) {
                result[i - start] = _getStateInfoByIndex(self, id, stateIndexes[i]);
            }
    
            return result;
        }
    
        /**
         * @dev Check if identity exists.
         * @param id Identity
         * @return True if the identity exists
         */
        function idExists(Data storage self, uint256 id) public view returns (bool) {
            return self.stateEntries[id].length > 0;
        }
    
        /**
         * @dev Check if state exists.
         * @param id Identity
         * @param state State
         * @return True if the state exists
         */
        function stateExists(Data storage self, uint256 id, uint256 state) public view returns (bool) {
            return self.stateIndexes[id][state].length > 0;
        }
    
        function _addState(
            Data storage self,
            uint256 id,
            uint256 state,
            uint256 _timestamp,
            uint256 _block
        ) internal {
            Entry[] storage stateEntries = self.stateEntries[id];
    
            stateEntries.push(Entry({state: state, timestamp: _timestamp, block: _block}));
            self.stateIndexes[id][state].push(stateEntries.length - 1);
    
            emit StateUpdated(id, _block, _timestamp, state);
        }
    
        /**
         * @dev Get state info by id and state without state existence check.
         * @param id Identity
         * @param state State
         * @return The state info
         */
        function _getStateInfoByState(
            Data storage self,
            uint256 id,
            uint256 state
        ) internal view returns (EntryInfo memory) {
            uint256[] storage indexes = self.stateIndexes[id][state];
            uint256 lastIndex = indexes[indexes.length - 1];
            return _getStateInfoByIndex(self, id, lastIndex);
        }
    
        function _getStateInfoByIndex(
            Data storage self,
            uint256 id,
            uint256 index
        ) internal view returns (EntryInfo memory) {
            bool isLastState = index == self.stateEntries[id].length - 1;
            Entry storage se = self.stateEntries[id][index];
    
            return
                EntryInfo({
                    id: id,
                    state: se.state,
                    replacedByState: isLastState ? 0 : self.stateEntries[id][index + 1].state,
                    createdAtTimestamp: se.timestamp,
                    replacedAtTimestamp: isLastState ? 0 : self.stateEntries[id][index + 1].timestamp,
                    createdAtBlock: se.block,
                    replacedAtBlock: isLastState ? 0 : self.stateEntries[id][index + 1].block
                });
        }
    }
    
  • @openzeppelin/contracts-upgradeable/access/Ownable2StepUpgradeable.sol
    // SPDX-License-Identifier: MIT
    // OpenZeppelin Contracts (last updated v5.1.0) (access/Ownable2Step.sol)
    
    pragma solidity ^0.8.20;
    
    import {OwnableUpgradeable} from "./OwnableUpgradeable.sol";
    import {Initializable} from "../proxy/utils/Initializable.sol";
    
    /**
     * @dev Contract module which provides access control mechanism, where
     * there is an account (an owner) that can be granted exclusive access to
     * specific functions.
     *
     * This extension of the {Ownable} contract includes a two-step mechanism to transfer
     * ownership, where the new owner must call {acceptOwnership} in order to replace the
     * old one. This can help prevent common mistakes, such as transfers of ownership to
     * incorrect accounts, or to contracts that are unable to interact with the
     * permission system.
     *
     * The initial owner is specified at deployment time in the constructor for `Ownable`. This
     * can later be changed with {transferOwnership} and {acceptOwnership}.
     *
     * This module is used through inheritance. It will make available all functions
     * from parent (Ownable).
     */
    abstract contract Ownable2StepUpgradeable is Initializable, OwnableUpgradeable {
        /// @custom:storage-location erc7201:openzeppelin.storage.Ownable2Step
        struct Ownable2StepStorage {
            address _pendingOwner;
        }
    
        // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Ownable2Step")) - 1)) & ~bytes32(uint256(0xff))
        bytes32 private constant Ownable2StepStorageLocation = 0x237e158222e3e6968b72b9db0d8043aacf074ad9f650f0d1606b4d82ee432c00;
    
        function _getOwnable2StepStorage() private pure returns (Ownable2StepStorage storage $) {
            assembly {
                $.slot := Ownable2StepStorageLocation
            }
        }
    
        event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);
    
        function __Ownable2Step_init() internal onlyInitializing {
        }
    
        function __Ownable2Step_init_unchained() internal onlyInitializing {
        }
        /**
         * @dev Returns the address of the pending owner.
         */
        function pendingOwner() public view virtual returns (address) {
            Ownable2StepStorage storage $ = _getOwnable2StepStorage();
            return $._pendingOwner;
        }
    
        /**
         * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.
         * Can only be called by the current owner.
         *
         * Setting `newOwner` to the zero address is allowed; this can be used to cancel an initiated ownership transfer.
         */
        function transferOwnership(address newOwner) public virtual override onlyOwner {
            Ownable2StepStorage storage $ = _getOwnable2StepStorage();
            $._pendingOwner = newOwner;
            emit OwnershipTransferStarted(owner(), newOwner);
        }
    
        /**
         * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.
         * Internal function without access restriction.
         */
        function _transferOwnership(address newOwner) internal virtual override {
            Ownable2StepStorage storage $ = _getOwnable2StepStorage();
            delete $._pendingOwner;
            super._transferOwnership(newOwner);
        }
    
        /**
         * @dev The new owner accepts the ownership transfer.
         */
        function acceptOwnership() public virtual {
            address sender = _msgSender();
            if (pendingOwner() != sender) {
                revert OwnableUnauthorizedAccount(sender);
            }
            _transferOwnership(sender);
        }
    }
    
  • @openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol
    // SPDX-License-Identifier: MIT
    // OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)
    
    pragma solidity ^0.8.20;
    
    import {ContextUpgradeable} from "../utils/ContextUpgradeable.sol";
    import {Initializable} from "../proxy/utils/Initializable.sol";
    
    /**
     * @dev Contract module which provides a basic access control mechanism, where
     * there is an account (an owner) that can be granted exclusive access to
     * specific functions.
     *
     * The initial owner is set to the address provided by the deployer. This can
     * later be changed with {transferOwnership}.
     *
     * This module is used through inheritance. It will make available the modifier
     * `onlyOwner`, which can be applied to your functions to restrict their use to
     * the owner.
     */
    abstract contract OwnableUpgradeable is Initializable, ContextUpgradeable {
        /// @custom:storage-location erc7201:openzeppelin.storage.Ownable
        struct OwnableStorage {
            address _owner;
        }
    
        // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Ownable")) - 1)) & ~bytes32(uint256(0xff))
        bytes32 private constant OwnableStorageLocation = 0x9016d09d72d40fdae2fd8ceac6b6234c7706214fd39c1cd1e609a0528c199300;
    
        function _getOwnableStorage() private pure returns (OwnableStorage storage $) {
            assembly {
                $.slot := OwnableStorageLocation
            }
        }
    
        /**
         * @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.
         */
        function __Ownable_init(address initialOwner) internal onlyInitializing {
            __Ownable_init_unchained(initialOwner);
        }
    
        function __Ownable_init_unchained(address initialOwner) internal onlyInitializing {
            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) {
            OwnableStorage storage $ = _getOwnableStorage();
            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 {
            OwnableStorage storage $ = _getOwnableStorage();
            address oldOwner = $._owner;
            $._owner = newOwner;
            emit OwnershipTransferred(oldOwner, newOwner);
        }
    }
    
  • @openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol
    // SPDX-License-Identifier: MIT
    // OpenZeppelin Contracts (last updated v5.0.0) (proxy/utils/Initializable.sol)
    
    pragma solidity ^0.8.20;
    
    /**
     * @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
     * behind a proxy. Since proxied contracts do not make use of a constructor, it's common to move constructor logic to an
     * external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
     * function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
     *
     * The initialization functions use a version number. Once a version number is used, it is consumed and cannot be
     * reused. This mechanism prevents re-execution of each "step" but allows the creation of new initialization steps in
     * case an upgrade adds a module that needs to be initialized.
     *
     * For example:
     *
     * [.hljs-theme-light.nopadding]
     * ```solidity
     * contract MyToken is ERC20Upgradeable {
     *     function initialize() initializer public {
     *         __ERC20_init("MyToken", "MTK");
     *     }
     * }
     *
     * contract MyTokenV2 is MyToken, ERC20PermitUpgradeable {
     *     function initializeV2() reinitializer(2) public {
     *         __ERC20Permit_init("MyToken");
     *     }
     * }
     * ```
     *
     * TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
     * possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
     *
     * CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
     * that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
     *
     * [CAUTION]
     * ====
     * Avoid leaving a contract uninitialized.
     *
     * An uninitialized contract can be taken over by an attacker. This applies to both a proxy and its implementation
     * contract, which may impact the proxy. To prevent the implementation contract from being used, you should invoke
     * the {_disableInitializers} function in the constructor to automatically lock it when it is deployed:
     *
     * [.hljs-theme-light.nopadding]
     * ```
     * /// @custom:oz-upgrades-unsafe-allow constructor
     * constructor() {
     *     _disableInitializers();
     * }
     * ```
     * ====
     */
    abstract contract Initializable {
        /**
         * @dev Storage of the initializable contract.
         *
         * It's implemented on a custom ERC-7201 namespace to reduce the risk of storage collisions
         * when using with upgradeable contracts.
         *
         * @custom:storage-location erc7201:openzeppelin.storage.Initializable
         */
        struct InitializableStorage {
            /**
             * @dev Indicates that the contract has been initialized.
             */
            uint64 _initialized;
            /**
             * @dev Indicates that the contract is in the process of being initialized.
             */
            bool _initializing;
        }
    
        // keccak256(abi.encode(uint256(keccak256("openzeppelin.storage.Initializable")) - 1)) & ~bytes32(uint256(0xff))
        bytes32 private constant INITIALIZABLE_STORAGE = 0xf0c57e16840df040f15088dc2f81fe391c3923bec73e23a9662efc9c229c6a00;
    
        /**
         * @dev The contract is already initialized.
         */
        error InvalidInitialization();
    
        /**
         * @dev The contract is not initializing.
         */
        error NotInitializing();
    
        /**
         * @dev Triggered when the contract has been initialized or reinitialized.
         */
        event Initialized(uint64 version);
    
        /**
         * @dev A modifier that defines a protected initializer function that can be invoked at most once. In its scope,
         * `onlyInitializing` functions can be used to initialize parent contracts.
         *
         * Similar to `reinitializer(1)`, except that in the context of a constructor an `initializer` may be invoked any
         * number of times. This behavior in the constructor can be useful during testing and is not expected to be used in
         * production.
         *
         * Emits an {Initialized} event.
         */
        modifier initializer() {
            // solhint-disable-next-line var-name-mixedcase
            InitializableStorage storage $ = _getInitializableStorage();
    
            // Cache values to avoid duplicated sloads
            bool isTopLevelCall = !$._initializing;
            uint64 initialized = $._initialized;
    
            // Allowed calls:
            // - initialSetup: the contract is not in the initializing state and no previous version was
            //                 initialized
            // - construction: the contract is initialized at version 1 (no reininitialization) and the
            //                 current contract is just being deployed
            bool initialSetup = initialized == 0 && isTopLevelCall;
            bool construction = initialized == 1 && address(this).code.length == 0;
    
            if (!initialSetup && !construction) {
                revert InvalidInitialization();
            }
            $._initialized = 1;
            if (isTopLevelCall) {
                $._initializing = true;
            }
            _;
            if (isTopLevelCall) {
                $._initializing = false;
                emit Initialized(1);
            }
        }
    
        /**
         * @dev A modifier that defines a protected reinitializer function that can be invoked at most once, and only if the
         * contract hasn't been initialized to a greater version before. In its scope, `onlyInitializing` functions can be
         * used to initialize parent contracts.
         *
         * A reinitializer may be used after the original initialization step. This is essential to configure modules that
         * are added through upgrades and that require initialization.
         *
         * When `version` is 1, this modifier is similar to `initializer`, except that functions marked with `reinitializer`
         * cannot be nested. If one is invoked in the context of another, execution will revert.
         *
         * Note that versions can jump in increments greater than 1; this implies that if multiple reinitializers coexist in
         * a contract, executing them in the right order is up to the developer or operator.
         *
         * WARNING: Setting the version to 2**64 - 1 will prevent any future reinitialization.
         *
         * Emits an {Initialized} event.
         */
        modifier reinitializer(uint64 version) {
            // solhint-disable-next-line var-name-mixedcase
            InitializableStorage storage $ = _getInitializableStorage();
    
            if ($._initializing || $._initialized >= version) {
                revert InvalidInitialization();
            }
            $._initialized = version;
            $._initializing = true;
            _;
            $._initializing = false;
            emit Initialized(version);
        }
    
        /**
         * @dev Modifier to protect an initialization function so that it can only be invoked by functions with the
         * {initializer} and {reinitializer} modifiers, directly or indirectly.
         */
        modifier onlyInitializing() {
            _checkInitializing();
            _;
        }
    
        /**
         * @dev Reverts if the contract is not in an initializing state. See {onlyInitializing}.
         */
        function _checkInitializing() internal view virtual {
            if (!_isInitializing()) {
                revert NotInitializing();
            }
        }
    
        /**
         * @dev Locks the contract, preventing any future reinitialization. This cannot be part of an initializer call.
         * Calling this in the constructor of a contract will prevent that contract from being initialized or reinitialized
         * to any version. It is recommended to use this to lock implementation contracts that are designed to be called
         * through proxies.
         *
         * Emits an {Initialized} event the first time it is successfully executed.
         */
        function _disableInitializers() internal virtual {
            // solhint-disable-next-line var-name-mixedcase
            InitializableStorage storage $ = _getInitializableStorage();
    
            if ($._initializing) {
                revert InvalidInitialization();
            }
            if ($._initialized != type(uint64).max) {
                $._initialized = type(uint64).max;
                emit Initialized(type(uint64).max);
            }
        }
    
        /**
         * @dev Returns the highest version that has been initialized. See {reinitializer}.
         */
        function _getInitializedVersion() internal view returns (uint64) {
            return _getInitializableStorage()._initialized;
        }
    
        /**
         * @dev Returns `true` if the contract is currently initializing. See {onlyInitializing}.
         */
        function _isInitializing() internal view returns (bool) {
            return _getInitializableStorage()._initializing;
        }
    
        /**
         * @dev Returns a pointer to the storage namespace.
         */
        // solhint-disable-next-line var-name-mixedcase
        function _getInitializableStorage() private pure returns (InitializableStorage storage $) {
            assembly {
                $.slot := INITIALIZABLE_STORAGE
            }
        }
    }
    
  • @openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol
    // SPDX-License-Identifier: MIT
    // OpenZeppelin Contracts (last updated v5.2.0) (proxy/utils/UUPSUpgradeable.sol)
    
    pragma solidity ^0.8.22;
    
    import {IERC1822Proxiable} from "@openzeppelin/contracts/interfaces/draft-IERC1822.sol";
    import {ERC1967Utils} from "@openzeppelin/contracts/proxy/ERC1967/ERC1967Utils.sol";
    import {Initializable} from "./Initializable.sol";
    
    /**
     * @dev An upgradeability mechanism designed for UUPS proxies. The functions included here can perform an upgrade of an
     * {ERC1967Proxy}, when this contract is set as the implementation behind such a proxy.
     *
     * A security mechanism ensures that an upgrade does not turn off upgradeability accidentally, although this risk is
     * reinstated if the upgrade retains upgradeability but removes the security mechanism, e.g. by replacing
     * `UUPSUpgradeable` with a custom implementation of upgrades.
     *
     * The {_authorizeUpgrade} function must be overridden to include access restriction to the upgrade mechanism.
     */
    abstract contract UUPSUpgradeable is Initializable, IERC1822Proxiable {
        /// @custom:oz-upgrades-unsafe-allow state-variable-immutable
        address private immutable __self = address(this);
    
        /**
         * @dev The version of the upgrade interface of the contract. If this getter is missing, both `upgradeTo(address)`
         * and `upgradeToAndCall(address,bytes)` are present, and `upgradeTo` must be used if no function should be called,
         * while `upgradeToAndCall` will invoke the `receive` function if the second argument is the empty byte string.
         * If the getter returns `"5.0.0"`, only `upgradeToAndCall(address,bytes)` is present, and the second argument must
         * be the empty byte string if no function should be called, making it impossible to invoke the `receive` function
         * during an upgrade.
         */
        string public constant UPGRADE_INTERFACE_VERSION = "5.0.0";
    
        /**
         * @dev The call is from an unauthorized context.
         */
        error UUPSUnauthorizedCallContext();
    
        /**
         * @dev The storage `slot` is unsupported as a UUID.
         */
        error UUPSUnsupportedProxiableUUID(bytes32 slot);
    
        /**
         * @dev Check that the execution is being performed through a delegatecall call and that the execution context is
         * a proxy contract with an implementation (as defined in ERC-1967) pointing to self. This should only be the case
         * for UUPS and transparent proxies that are using the current contract as their implementation. Execution of a
         * function through ERC-1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to
         * fail.
         */
        modifier onlyProxy() {
            _checkProxy();
            _;
        }
    
        /**
         * @dev Check that the execution is not being performed through a delegate call. This allows a function to be
         * callable on the implementing contract but not through proxies.
         */
        modifier notDelegated() {
            _checkNotDelegated();
            _;
        }
    
        function __UUPSUpgradeable_init() internal onlyInitializing {
        }
    
        function __UUPSUpgradeable_init_unchained() internal onlyInitializing {
        }
        /**
         * @dev Implementation of the ERC-1822 {proxiableUUID} function. This returns the storage slot used by the
         * implementation. It is used to validate the implementation's compatibility when performing an upgrade.
         *
         * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks
         * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this
         * function revert if invoked through a proxy. This is guaranteed by the `notDelegated` modifier.
         */
        function proxiableUUID() external view virtual notDelegated returns (bytes32) {
            return ERC1967Utils.IMPLEMENTATION_SLOT;
        }
    
        /**
         * @dev Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call
         * encoded in `data`.
         *
         * Calls {_authorizeUpgrade}.
         *
         * Emits an {Upgraded} event.
         *
         * @custom:oz-upgrades-unsafe-allow-reachable delegatecall
         */
        function upgradeToAndCall(address newImplementation, bytes memory data) public payable virtual onlyProxy {
            _authorizeUpgrade(newImplementation);
            _upgradeToAndCallUUPS(newImplementation, data);
        }
    
        /**
         * @dev Reverts if the execution is not performed via delegatecall or the execution
         * context is not of a proxy with an ERC-1967 compliant implementation pointing to self.
         * See {_onlyProxy}.
         */
        function _checkProxy() internal view virtual {
            if (
                address(this) == __self || // Must be called through delegatecall
                ERC1967Utils.getImplementation() != __self // Must be called through an active proxy
            ) {
                revert UUPSUnauthorizedCallContext();
            }
        }
    
        /**
         * @dev Reverts if the execution is performed via delegatecall.
         * See {notDelegated}.
         */
        function _checkNotDelegated() internal view virtual {
            if (address(this) != __self) {
                // Must not be called through delegatecall
                revert UUPSUnauthorizedCallContext();
            }
        }
    
        /**
         * @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by
         * {upgradeToAndCall}.
         *
         * Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}.
         *
         * ```solidity
         * function _authorizeUpgrade(address) internal onlyOwner {}
         * ```
         */
        function _authorizeUpgrade(address newImplementation) internal virtual;
    
        /**
         * @dev Performs an implementation upgrade with a security check for UUPS proxies, and additional setup call.
         *
         * As a security check, {proxiableUUID} is invoked in the new implementation, and the return value
         * is expected to be the implementation slot in ERC-1967.
         *
         * Emits an {IERC1967-Upgraded} event.
         */
        function _upgradeToAndCallUUPS(address newImplementation, bytes memory data) private {
            try IERC1822Proxiable(newImplementation).proxiableUUID() returns (bytes32 slot) {
                if (slot != ERC1967Utils.IMPLEMENTATION_SLOT) {
                    revert UUPSUnsupportedProxiableUUID(slot);
                }
                ERC1967Utils.upgradeToAndCall(newImplementation, data);
            } catch {
                // The implementation is not UUPS
                revert ERC1967Utils.ERC1967InvalidImplementation(newImplementation);
            }
        }
    }
    
  • @openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol
    // SPDX-License-Identifier: MIT
    // OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)
    
    pragma solidity ^0.8.20;
    import {Initializable} from "../proxy/utils/Initializable.sol";
    
    /**
     * @dev Provides information about the current execution context, including the
     * sender of the transaction and its data. While these are generally available
     * via msg.sender and msg.data, they should not be accessed in such a direct
     * manner, since when dealing with meta-transactions the account sending and
     * paying for execution may not be the actual sender (as far as an application
     * is concerned).
     *
     * This contract is only required for intermediate, library-like contracts.
     */
    abstract contract ContextUpgradeable is Initializable {
        function __Context_init() internal onlyInitializing {
        }
    
        function __Context_init_unchained() internal onlyInitializing {
        }
        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;
        }
    }
    
  • @openzeppelin/contracts/interfaces/IERC1967.sol
    // SPDX-License-Identifier: MIT
    // OpenZeppelin Contracts (last updated v5.0.0) (interfaces/IERC1967.sol)
    
    pragma solidity ^0.8.20;
    
    /**
     * @dev ERC-1967: Proxy Storage Slots. This interface contains the events defined in the ERC.
     */
    interface IERC1967 {
        /**
         * @dev Emitted when the implementation is upgraded.
         */
        event Upgraded(address indexed implementation);
    
        /**
         * @dev Emitted when the admin account has changed.
         */
        event AdminChanged(address previousAdmin, address newAdmin);
    
        /**
         * @dev Emitted when the beacon is changed.
         */
        event BeaconUpgraded(address indexed beacon);
    }
    
  • @openzeppelin/contracts/interfaces/draft-IERC1822.sol
    // SPDX-License-Identifier: MIT
    // OpenZeppelin Contracts (last updated v5.1.0) (interfaces/draft-IERC1822.sol)
    
    pragma solidity ^0.8.20;
    
    /**
     * @dev ERC-1822: Universal Upgradeable Proxy Standard (UUPS) documents a method for upgradeability through a simplified
     * proxy whose upgrades are fully controlled by the current implementation.
     */
    interface IERC1822Proxiable {
        /**
         * @dev Returns the storage slot that the proxiable contract assumes is being used to store the implementation
         * address.
         *
         * IMPORTANT: A proxy pointing at a proxiable contract should not be considered proxiable itself, because this risks
         * bricking a proxy that upgrades to it, by delegating to itself until out of gas. Thus it is critical that this
         * function revert if invoked through a proxy.
         */
        function proxiableUUID() external view returns (bytes32);
    }
    
  • @openzeppelin/contracts/proxy/ERC1967/ERC1967Utils.sol
    // SPDX-License-Identifier: MIT
    // OpenZeppelin Contracts (last updated v5.2.0) (proxy/ERC1967/ERC1967Utils.sol)
    
    pragma solidity ^0.8.22;
    
    import {IBeacon} from "../beacon/IBeacon.sol";
    import {IERC1967} from "../../interfaces/IERC1967.sol";
    import {Address} from "../../utils/Address.sol";
    import {StorageSlot} from "../../utils/StorageSlot.sol";
    
    /**
     * @dev This library provides getters and event emitting update functions for
     * https://eips.ethereum.org/EIPS/eip-1967[ERC-1967] slots.
     */
    library ERC1967Utils {
        /**
         * @dev Storage slot with the address of the current implementation.
         * This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1.
         */
        // solhint-disable-next-line private-vars-leading-underscore
        bytes32 internal constant IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
    
        /**
         * @dev The `implementation` of the proxy is invalid.
         */
        error ERC1967InvalidImplementation(address implementation);
    
        /**
         * @dev The `admin` of the proxy is invalid.
         */
        error ERC1967InvalidAdmin(address admin);
    
        /**
         * @dev The `beacon` of the proxy is invalid.
         */
        error ERC1967InvalidBeacon(address beacon);
    
        /**
         * @dev An upgrade function sees `msg.value > 0` that may be lost.
         */
        error ERC1967NonPayable();
    
        /**
         * @dev Returns the current implementation address.
         */
        function getImplementation() internal view returns (address) {
            return StorageSlot.getAddressSlot(IMPLEMENTATION_SLOT).value;
        }
    
        /**
         * @dev Stores a new address in the ERC-1967 implementation slot.
         */
        function _setImplementation(address newImplementation) private {
            if (newImplementation.code.length == 0) {
                revert ERC1967InvalidImplementation(newImplementation);
            }
            StorageSlot.getAddressSlot(IMPLEMENTATION_SLOT).value = newImplementation;
        }
    
        /**
         * @dev Performs implementation upgrade with additional setup call if data is nonempty.
         * This function is payable only if the setup call is performed, otherwise `msg.value` is rejected
         * to avoid stuck value in the contract.
         *
         * Emits an {IERC1967-Upgraded} event.
         */
        function upgradeToAndCall(address newImplementation, bytes memory data) internal {
            _setImplementation(newImplementation);
            emit IERC1967.Upgraded(newImplementation);
    
            if (data.length > 0) {
                Address.functionDelegateCall(newImplementation, data);
            } else {
                _checkNonPayable();
            }
        }
    
        /**
         * @dev Storage slot with the admin of the contract.
         * This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1.
         */
        // solhint-disable-next-line private-vars-leading-underscore
        bytes32 internal constant ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;
    
        /**
         * @dev Returns the current admin.
         *
         * TIP: To get this value clients can read directly from the storage slot shown below (specified by ERC-1967) using
         * the https://eth.wiki/json-rpc/API#eth_getstorageat[`eth_getStorageAt`] RPC call.
         * `0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103`
         */
        function getAdmin() internal view returns (address) {
            return StorageSlot.getAddressSlot(ADMIN_SLOT).value;
        }
    
        /**
         * @dev Stores a new address in the ERC-1967 admin slot.
         */
        function _setAdmin(address newAdmin) private {
            if (newAdmin == address(0)) {
                revert ERC1967InvalidAdmin(address(0));
            }
            StorageSlot.getAddressSlot(ADMIN_SLOT).value = newAdmin;
        }
    
        /**
         * @dev Changes the admin of the proxy.
         *
         * Emits an {IERC1967-AdminChanged} event.
         */
        function changeAdmin(address newAdmin) internal {
            emit IERC1967.AdminChanged(getAdmin(), newAdmin);
            _setAdmin(newAdmin);
        }
    
        /**
         * @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.
         * This is the keccak-256 hash of "eip1967.proxy.beacon" subtracted by 1.
         */
        // solhint-disable-next-line private-vars-leading-underscore
        bytes32 internal constant BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;
    
        /**
         * @dev Returns the current beacon.
         */
        function getBeacon() internal view returns (address) {
            return StorageSlot.getAddressSlot(BEACON_SLOT).value;
        }
    
        /**
         * @dev Stores a new beacon in the ERC-1967 beacon slot.
         */
        function _setBeacon(address newBeacon) private {
            if (newBeacon.code.length == 0) {
                revert ERC1967InvalidBeacon(newBeacon);
            }
    
            StorageSlot.getAddressSlot(BEACON_SLOT).value = newBeacon;
    
            address beaconImplementation = IBeacon(newBeacon).implementation();
            if (beaconImplementation.code.length == 0) {
                revert ERC1967InvalidImplementation(beaconImplementation);
            }
        }
    
        /**
         * @dev Change the beacon and trigger a setup call if data is nonempty.
         * This function is payable only if the setup call is performed, otherwise `msg.value` is rejected
         * to avoid stuck value in the contract.
         *
         * Emits an {IERC1967-BeaconUpgraded} event.
         *
         * CAUTION: Invoking this function has no effect on an instance of {BeaconProxy} since v5, since
         * it uses an immutable beacon without looking at the value of the ERC-1967 beacon slot for
         * efficiency.
         */
        function upgradeBeaconToAndCall(address newBeacon, bytes memory data) internal {
            _setBeacon(newBeacon);
            emit IERC1967.BeaconUpgraded(newBeacon);
    
            if (data.length > 0) {
                Address.functionDelegateCall(IBeacon(newBeacon).implementation(), data);
            } else {
                _checkNonPayable();
            }
        }
    
        /**
         * @dev Reverts if `msg.value` is not zero. It can be used to avoid `msg.value` stuck in the contract
         * if an upgrade doesn't perform an initialization call.
         */
        function _checkNonPayable() private {
            if (msg.value > 0) {
                revert ERC1967NonPayable();
            }
        }
    }
    
  • @openzeppelin/contracts/proxy/beacon/IBeacon.sol
    // SPDX-License-Identifier: MIT
    // OpenZeppelin Contracts (last updated v5.0.0) (proxy/beacon/IBeacon.sol)
    
    pragma solidity ^0.8.20;
    
    /**
     * @dev This is the interface that {BeaconProxy} expects of its beacon.
     */
    interface IBeacon {
        /**
         * @dev Must return an address that can be used as a delegate call target.
         *
         * {UpgradeableBeacon} will check that this address is a contract.
         */
        function implementation() external view returns (address);
    }
    
  • @openzeppelin/contracts/utils/Address.sol
    // SPDX-License-Identifier: MIT
    // OpenZeppelin Contracts (last updated v5.2.0) (utils/Address.sol)
    
    pragma solidity ^0.8.20;
    
    import {Errors} from "./Errors.sol";
    
    /**
     * @dev Collection of functions related to the address type
     */
    library Address {
        /**
         * @dev There's no code at `target` (it is not a contract).
         */
        error AddressEmptyCode(address target);
    
        /**
         * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
         * `recipient`, forwarding all available gas and reverting on errors.
         *
         * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
         * of certain opcodes, possibly making contracts go over the 2300 gas limit
         * imposed by `transfer`, making them unable to receive funds via
         * `transfer`. {sendValue} removes this limitation.
         *
         * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].
         *
         * IMPORTANT: because control is transferred to `recipient`, care must be
         * taken to not create reentrancy vulnerabilities. Consider using
         * {ReentrancyGuard} or the
         * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
         */
        function sendValue(address payable recipient, uint256 amount) internal {
            if (address(this).balance < amount) {
                revert Errors.InsufficientBalance(address(this).balance, amount);
            }
    
            (bool success, bytes memory returndata) = recipient.call{value: amount}("");
            if (!success) {
                _revert(returndata);
            }
        }
    
        /**
         * @dev Performs a Solidity function call using a low level `call`. A
         * plain `call` is an unsafe replacement for a function call: use this
         * function instead.
         *
         * If `target` reverts with a revert reason or custom error, it is bubbled
         * up by this function (like regular Solidity function calls). However, if
         * the call reverted with no returned reason, this function reverts with a
         * {Errors.FailedCall} error.
         *
         * Returns the raw returned data. To convert to the expected return value,
         * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
         *
         * Requirements:
         *
         * - `target` must be a contract.
         * - calling `target` with `data` must not revert.
         */
        function functionCall(address target, bytes memory data) internal returns (bytes memory) {
            return functionCallWithValue(target, data, 0);
        }
    
        /**
         * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
         * but also transferring `value` wei to `target`.
         *
         * Requirements:
         *
         * - the calling contract must have an ETH balance of at least `value`.
         * - the called Solidity function must be `payable`.
         */
        function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
            if (address(this).balance < value) {
                revert Errors.InsufficientBalance(address(this).balance, value);
            }
            (bool success, bytes memory returndata) = target.call{value: value}(data);
            return verifyCallResultFromTarget(target, success, returndata);
        }
    
        /**
         * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
         * but performing a static call.
         */
        function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
            (bool success, bytes memory returndata) = target.staticcall(data);
            return verifyCallResultFromTarget(target, success, returndata);
        }
    
        /**
         * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
         * but performing a delegate call.
         */
        function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
            (bool success, bytes memory returndata) = target.delegatecall(data);
            return verifyCallResultFromTarget(target, success, returndata);
        }
    
        /**
         * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target
         * was not a contract or bubbling up the revert reason (falling back to {Errors.FailedCall}) in case
         * of an unsuccessful call.
         */
        function verifyCallResultFromTarget(
            address target,
            bool success,
            bytes memory returndata
        ) internal view returns (bytes memory) {
            if (!success) {
                _revert(returndata);
            } else {
                // only check if target is a contract if the call was successful and the return data is empty
                // otherwise we already know that it was a contract
                if (returndata.length == 0 && target.code.length == 0) {
                    revert AddressEmptyCode(target);
                }
                return returndata;
            }
        }
    
        /**
         * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the
         * revert reason or with a default {Errors.FailedCall} error.
         */
        function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {
            if (!success) {
                _revert(returndata);
            } else {
                return returndata;
            }
        }
    
        /**
         * @dev Reverts with returndata if present. Otherwise reverts with {Errors.FailedCall}.
         */
        function _revert(bytes memory returndata) private pure {
            // Look for revert reason and bubble it up if present
            if (returndata.length > 0) {
                // The easiest way to bubble the revert reason is using memory via assembly
                assembly ("memory-safe") {
                    let returndata_size := mload(returndata)
                    revert(add(32, returndata), returndata_size)
                }
            } else {
                revert Errors.FailedCall();
            }
        }
    }
    
  • @openzeppelin/contracts/utils/Errors.sol
    // SPDX-License-Identifier: MIT
    // OpenZeppelin Contracts (last updated v5.1.0) (utils/Errors.sol)
    
    pragma solidity ^0.8.20;
    
    /**
     * @dev Collection of common custom errors used in multiple contracts
     *
     * IMPORTANT: Backwards compatibility is not guaranteed in future versions of the library.
     * It is recommended to avoid relying on the error API for critical functionality.
     *
     * _Available since v5.1._
     */
    library Errors {
        /**
         * @dev The ETH balance of the account is not enough to perform the operation.
         */
        error InsufficientBalance(uint256 balance, uint256 needed);
    
        /**
         * @dev A call to an address target failed. The target may have reverted.
         */
        error FailedCall();
    
        /**
         * @dev The deployment failed.
         */
        error FailedDeployment();
    
        /**
         * @dev A necessary precompile is missing.
         */
        error MissingPrecompile(address);
    }
    
  • @openzeppelin/contracts/utils/StorageSlot.sol
    // SPDX-License-Identifier: MIT
    // OpenZeppelin Contracts (last updated v5.1.0) (utils/StorageSlot.sol)
    // This file was procedurally generated from scripts/generate/templates/StorageSlot.js.
    
    pragma solidity ^0.8.20;
    
    /**
     * @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.
     *
     * Example usage to set ERC-1967 implementation slot:
     * ```solidity
     * contract ERC1967 {
     *     // Define the slot. Alternatively, use the SlotDerivation library to derive the slot.
     *     bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
     *
     *     function _getImplementation() internal view returns (address) {
     *         return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
     *     }
     *
     *     function _setImplementation(address newImplementation) internal {
     *         require(newImplementation.code.length > 0);
     *         StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
     *     }
     * }
     * ```
     *
     * TIP: Consider using this library along with {SlotDerivation}.
     */
    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
            }
        }
    }
    
  • contracts/verifier/auth-v3-verifier.sol
    // SPDX-License-Identifier: GPL-3.0
    /*
        Copyright 2021 0KIMS association.
    
        This file is generated with [snarkJS](https://github.com/iden3/snarkjs).
    
        snarkJS is a free software: you can redistribute it and/or modify it
        under the terms of the GNU General Public License as published by
        the Free Software Foundation, either version 3 of the License, or
        (at your option) any later version.
    
        snarkJS is distributed in the hope that it will be useful, but WITHOUT
        ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
        or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
        License for more details.
    
        You should have received a copy of the GNU General Public License
        along with snarkJS. If not, see <https://www.gnu.org/licenses/>.
    */
    
    pragma solidity >=0.7.0 <0.9.0;
    
    contract AuthV3Verifier {
        // Scalar field size
        uint256 constant r    = 21888242871839275222246405745257275088548364400416034343698204186575808495617;
        // Base field size
        uint256 constant q   = 21888242871839275222246405745257275088696311157297823662689037894645226208583;
    
        // Verification Key data
        uint256 constant alphax  = 20491192805390485299153009773594534940189261866228447918068658471970481763042;
        uint256 constant alphay  = 9383485363053290200918347156157836566562967994039712273449902621266178545958;
        uint256 constant betax1  = 4252822878758300859123897981450591353533073413197771768651442665752259397132;
        uint256 constant betax2  = 6375614351688725206403948262868962793625744043794305715222011528459656738731;
        uint256 constant betay1  = 21847035105528745403288232691147584728191162732299865338377159692350059136679;
        uint256 constant betay2  = 10505242626370262277552901082094356697409835680220590971873171140371331206856;
        uint256 constant gammax1 = 11559732032986387107991004021392285783925812861821192530917403151452391805634;
        uint256 constant gammax2 = 10857046999023057135944570762232829481370756359578518086990519993285655852781;
        uint256 constant gammay1 = 4082367875863433681332203403145435568316851327593401208105741076214120093531;
        uint256 constant gammay2 = 8495653923123431417604973247489272438418190587263600148770280649306958101930;
        uint256 constant deltax1 = 11559732032986387107991004021392285783925812861821192530917403151452391805634;
        uint256 constant deltax2 = 10857046999023057135944570762232829481370756359578518086990519993285655852781;
        uint256 constant deltay1 = 4082367875863433681332203403145435568316851327593401208105741076214120093531;
        uint256 constant deltay2 = 8495653923123431417604973247489272438418190587263600148770280649306958101930;
    
        
        uint256 constant IC0x = 6341257018548602519320231913292992198078317848645198484141584208867280434410;
        uint256 constant IC0y = 15595957234872215024793257619158554314560512301301284562264512592023305821;
        
        uint256 constant IC1x = 17905103678222485242154215331175287115693619646094295529834082271722262451902;
        uint256 constant IC1y = 17702538036390995312173820354362822655945902477754292312802258978418365992853;
        
        uint256 constant IC2x = 2577481418278943649802300162329440533730131793988867370722516933256973666433;
        uint256 constant IC2y = 17728303210035214259061951533029088869065104178438088956086791741754557273958;
        
     
        // Memory data
        uint16 constant pVk = 0;
        uint16 constant pPairing = 128;
    
        uint16 constant pLastMem = 896;
    
        function verifyProof(uint[2] calldata _pA, uint[2][2] calldata _pB, uint[2] calldata _pC, uint[2] calldata _pubSignals) public view returns (bool) {
            assembly {
                function checkField(v) {
                    if iszero(lt(v, r)) {
                        mstore(0, 0)
                        return(0, 0x20)
                    }
                }
                
                // G1 function to multiply a G1 value(x,y) to value in an address
                function g1_mulAccC(pR, x, y, s) {
                    let success
                    let mIn := mload(0x40)
                    mstore(mIn, x)
                    mstore(add(mIn, 32), y)
                    mstore(add(mIn, 64), s)
    
                    success := staticcall(sub(gas(), 2000), 7, mIn, 96, mIn, 64)
    
                    if iszero(success) {
                        mstore(0, 0)
                        return(0, 0x20)
                    }
    
                    mstore(add(mIn, 64), mload(pR))
                    mstore(add(mIn, 96), mload(add(pR, 32)))
    
                    success := staticcall(sub(gas(), 2000), 6, mIn, 128, pR, 64)
    
                    if iszero(success) {
                        mstore(0, 0)
                        return(0, 0x20)
                    }
                }
    
                function checkPairing(pA, pB, pC, pubSignals, pMem) -> isOk {
                    let _pPairing := add(pMem, pPairing)
                    let _pVk := add(pMem, pVk)
    
                    mstore(_pVk, IC0x)
                    mstore(add(_pVk, 32), IC0y)
    
                    // Compute the linear combination vk_x
                    
                    g1_mulAccC(_pVk, IC1x, IC1y, calldataload(add(pubSignals, 0)))
                    
                    g1_mulAccC(_pVk, IC2x, IC2y, calldataload(add(pubSignals, 32)))
                    
    
                    // -A
                    mstore(_pPairing, calldataload(pA))
                    mstore(add(_pPairing, 32), mod(sub(q, calldataload(add(pA, 32))), q))
    
                    // B
                    mstore(add(_pPairing, 64), calldataload(pB))
                    mstore(add(_pPairing, 96), calldataload(add(pB, 32)))
                    mstore(add(_pPairing, 128), calldataload(add(pB, 64)))
                    mstore(add(_pPairing, 160), calldataload(add(pB, 96)))
    
                    // alpha1
                    mstore(add(_pPairing, 192), alphax)
                    mstore(add(_pPairing, 224), alphay)
    
                    // beta2
                    mstore(add(_pPairing, 256), betax1)
                    mstore(add(_pPairing, 288), betax2)
                    mstore(add(_pPairing, 320), betay1)
                    mstore(add(_pPairing, 352), betay2)
    
                    // vk_x
                    mstore(add(_pPairing, 384), mload(add(pMem, pVk)))
                    mstore(add(_pPairing, 416), mload(add(pMem, add(pVk, 32))))
    
    
                    // gamma2
                    mstore(add(_pPairing, 448), gammax1)
                    mstore(add(_pPairing, 480), gammax2)
                    mstore(add(_pPairing, 512), gammay1)
                    mstore(add(_pPairing, 544), gammay2)
    
                    // C
                    mstore(add(_pPairing, 576), calldataload(pC))
                    mstore(add(_pPairing, 608), calldataload(add(pC, 32)))
    
                    // delta2
                    mstore(add(_pPairing, 640), deltax1)
                    mstore(add(_pPairing, 672), deltax2)
                    mstore(add(_pPairing, 704), deltay1)
                    mstore(add(_pPairing, 736), deltay2)
    
    
                    let success := staticcall(sub(gas(), 2000), 8, _pPairing, 768, _pPairing, 0x20)
    
                    isOk := and(success, mload(_pPairing))
                }
    
                let pMem := mload(0x40)
                mstore(0x40, add(pMem, pLastMem))
    
                // Validate that all evaluations ∈ F
                
                checkField(calldataload(add(_pubSignals, 0)))
                
                checkField(calldataload(add(_pubSignals, 32)))
                
    
                // Validate all evaluations
                let isValid := checkPairing(_pA, _pB, _pC, _pubSignals, pMem)
    
                mstore(0, isValid)
                 return(0, 0x20)
             }
         }
     }
    
  • contracts/verifier/community-membership-verifier.sol
    // SPDX-License-Identifier: GPL-3.0
    /*
        Copyright 2021 0KIMS association.
    
        This file is generated with [snarkJS](https://github.com/iden3/snarkjs).
    
        snarkJS is a free software: you can redistribute it and/or modify it
        under the terms of the GNU General Public License as published by
        the Free Software Foundation, either version 3 of the License, or
        (at your option) any later version.
    
        snarkJS is distributed in the hope that it will be useful, but WITHOUT
        ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
        or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
        License for more details.
    
        You should have received a copy of the GNU General Public License
        along with snarkJS. If not, see <https://www.gnu.org/licenses/>.
    */
    
    pragma solidity >=0.7.0 <0.9.0;
    
    contract CommunityMembershipVerifier {
        // Scalar field size
        uint256 constant r    = 21888242871839275222246405745257275088548364400416034343698204186575808495617;
        // Base field size
        uint256 constant q   = 21888242871839275222246405745257275088696311157297823662689037894645226208583;
    
        // Verification Key data
        uint256 constant alphax  = 20491192805390485299153009773594534940189261866228447918068658471970481763042;
        uint256 constant alphay  = 9383485363053290200918347156157836566562967994039712273449902621266178545958;
        uint256 constant betax1  = 4252822878758300859123897981450591353533073413197771768651442665752259397132;
        uint256 constant betax2  = 6375614351688725206403948262868962793625744043794305715222011528459656738731;
        uint256 constant betay1  = 21847035105528745403288232691147584728191162732299865338377159692350059136679;
        uint256 constant betay2  = 10505242626370262277552901082094356697409835680220590971873171140371331206856;
        uint256 constant gammax1 = 11559732032986387107991004021392285783925812861821192530917403151452391805634;
        uint256 constant gammax2 = 10857046999023057135944570762232829481370756359578518086990519993285655852781;
        uint256 constant gammay1 = 4082367875863433681332203403145435568316851327593401208105741076214120093531;
        uint256 constant gammay2 = 8495653923123431417604973247489272438418190587263600148770280649306958101930;
        uint256 constant deltax1 = 11559732032986387107991004021392285783925812861821192530917403151452391805634;
        uint256 constant deltax2 = 10857046999023057135944570762232829481370756359578518086990519993285655852781;
        uint256 constant deltay1 = 4082367875863433681332203403145435568316851327593401208105741076214120093531;
        uint256 constant deltay2 = 8495653923123431417604973247489272438418190587263600148770280649306958101930;
    
        
        uint256 constant IC0x = 4978327156145226481337999477945283775720173669065912618297945307479793100943;
        uint256 constant IC0y = 18812738511471528317851595352973589719107347525354304888964786756917998498357;
        
        uint256 constant IC1x = 20520396770991556101136293294106458230487252947485348793144398590390810703805;
        uint256 constant IC1y = 14106680963569391814591719612084448414400383180624434248250875868993909281415;
        
        uint256 constant IC2x = 12705554229061508631219726393237790418123089328039613150429653199752169439591;
        uint256 constant IC2y = 3547361705846331502288353055613050289286383737968827153487245587068558209703;
        
        uint256 constant IC3x = 16629728237225542483687210614573854400762597684910813956755981218310979268976;
        uint256 constant IC3y = 10263522968196908009340623950428925782060277319221590060614723366257757050264;
        
        uint256 constant IC4x = 12394931034970929793418378543770041634692432677896490568161339402375855118554;
        uint256 constant IC4y = 9127246931960541499555706491230720163533701854192311626033896435180869003607;
        
        uint256 constant IC5x = 3305937307902142354337613156639150474039515204277107866848025508298340962715;
        uint256 constant IC5y = 15624161241082130344359708985940172139039067844958422430134999909934392284683;
        
        uint256 constant IC6x = 16187767808399755239678439737791969269691673798710443837203616456795936288607;
        uint256 constant IC6y = 14242372697788987041281614898855281077408144545838376284515066443590407775350;
        
     
        // Memory data
        uint16 constant pVk = 0;
        uint16 constant pPairing = 128;
    
        uint16 constant pLastMem = 896;
    
        function verifyProof(uint[2] calldata _pA, uint[2][2] calldata _pB, uint[2] calldata _pC, uint[6] calldata _pubSignals) public view returns (bool) {
            assembly {
                function checkField(v) {
                    if iszero(lt(v, r)) {
                        mstore(0, 0)
                        return(0, 0x20)
                    }
                }
                
                // G1 function to multiply a G1 value(x,y) to value in an address
                function g1_mulAccC(pR, x, y, s) {
                    let success
                    let mIn := mload(0x40)
                    mstore(mIn, x)
                    mstore(add(mIn, 32), y)
                    mstore(add(mIn, 64), s)
    
                    success := staticcall(sub(gas(), 2000), 7, mIn, 96, mIn, 64)
    
                    if iszero(success) {
                        mstore(0, 0)
                        return(0, 0x20)
                    }
    
                    mstore(add(mIn, 64), mload(pR))
                    mstore(add(mIn, 96), mload(add(pR, 32)))
    
                    success := staticcall(sub(gas(), 2000), 6, mIn, 128, pR, 64)
    
                    if iszero(success) {
                        mstore(0, 0)
                        return(0, 0x20)
                    }
                }
    
                function checkPairing(pA, pB, pC, pubSignals, pMem) -> isOk {
                    let _pPairing := add(pMem, pPairing)
                    let _pVk := add(pMem, pVk)
    
                    mstore(_pVk, IC0x)
                    mstore(add(_pVk, 32), IC0y)
    
                    // Compute the linear combination vk_x
                    
                    g1_mulAccC(_pVk, IC1x, IC1y, calldataload(add(pubSignals, 0)))
                    
                    g1_mulAccC(_pVk, IC2x, IC2y, calldataload(add(pubSignals, 32)))
                    
                    g1_mulAccC(_pVk, IC3x, IC3y, calldataload(add(pubSignals, 64)))
                    
                    g1_mulAccC(_pVk, IC4x, IC4y, calldataload(add(pubSignals, 96)))
                    
                    g1_mulAccC(_pVk, IC5x, IC5y, calldataload(add(pubSignals, 128)))
                    
                    g1_mulAccC(_pVk, IC6x, IC6y, calldataload(add(pubSignals, 160)))
                    
    
                    // -A
                    mstore(_pPairing, calldataload(pA))
                    mstore(add(_pPairing, 32), mod(sub(q, calldataload(add(pA, 32))), q))
    
                    // B
                    mstore(add(_pPairing, 64), calldataload(pB))
                    mstore(add(_pPairing, 96), calldataload(add(pB, 32)))
                    mstore(add(_pPairing, 128), calldataload(add(pB, 64)))
                    mstore(add(_pPairing, 160), calldataload(add(pB, 96)))
    
                    // alpha1
                    mstore(add(_pPairing, 192), alphax)
                    mstore(add(_pPairing, 224), alphay)
    
                    // beta2
                    mstore(add(_pPairing, 256), betax1)
                    mstore(add(_pPairing, 288), betax2)
                    mstore(add(_pPairing, 320), betay1)
                    mstore(add(_pPairing, 352), betay2)
    
                    // vk_x
                    mstore(add(_pPairing, 384), mload(add(pMem, pVk)))
                    mstore(add(_pPairing, 416), mload(add(pMem, add(pVk, 32))))
    
    
                    // gamma2
                    mstore(add(_pPairing, 448), gammax1)
                    mstore(add(_pPairing, 480), gammax2)
                    mstore(add(_pPairing, 512), gammay1)
                    mstore(add(_pPairing, 544), gammay2)
    
                    // C
                    mstore(add(_pPairing, 576), calldataload(pC))
                    mstore(add(_pPairing, 608), calldataload(add(pC, 32)))
    
                    // delta2
                    mstore(add(_pPairing, 640), deltax1)
                    mstore(add(_pPairing, 672), deltax2)
                    mstore(add(_pPairing, 704), deltay1)
                    mstore(add(_pPairing, 736), deltay2)
    
    
                    let success := staticcall(sub(gas(), 2000), 8, _pPairing, 768, _pPairing, 0x20)
    
                    isOk := and(success, mload(_pPairing))
                }
    
                let pMem := mload(0x40)
                mstore(0x40, add(pMem, pLastMem))
    
                // Validate that all evaluations ∈ F
                
                checkField(calldataload(add(_pubSignals, 0)))
                
                checkField(calldataload(add(_pubSignals, 32)))
                
                checkField(calldataload(add(_pubSignals, 64)))
                
                checkField(calldataload(add(_pubSignals, 96)))
                
                checkField(calldataload(add(_pubSignals, 128)))
                
                checkField(calldataload(add(_pubSignals, 160)))
                
    
                // Validate all evaluations
                let isValid := checkPairing(_pA, _pB, _pC, _pubSignals, pMem)
    
                mstore(0, isValid)
                 return(0, 0x20)
             }
         }
     }
    
  • contracts/verifier/foru-entity-verifier.sol
    // SPDX-License-Identifier: GPL-3.0
    /*
        Copyright 2021 0KIMS association.
    
        This file is generated with [snarkJS](https://github.com/iden3/snarkjs).
    
        snarkJS is a free software: you can redistribute it and/or modify it
        under the terms of the GNU General Public License as published by
        the Free Software Foundation, either version 3 of the License, or
        (at your option) any later version.
    
        snarkJS is distributed in the hope that it will be useful, but WITHOUT
        ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
        or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
        License for more details.
    
        You should have received a copy of the GNU General Public License
        along with snarkJS. If not, see <https://www.gnu.org/licenses/>.
    */
    
    pragma solidity >=0.7.0 <0.9.0;
    
    contract ForUEntityVerifier {
        // Scalar field size
        uint256 constant r    = 21888242871839275222246405745257275088548364400416034343698204186575808495617;
        // Base field size
        uint256 constant q   = 21888242871839275222246405745257275088696311157297823662689037894645226208583;
    
        // Verification Key data
        uint256 constant alphax  = 20491192805390485299153009773594534940189261866228447918068658471970481763042;
        uint256 constant alphay  = 9383485363053290200918347156157836566562967994039712273449902621266178545958;
        uint256 constant betax1  = 4252822878758300859123897981450591353533073413197771768651442665752259397132;
        uint256 constant betax2  = 6375614351688725206403948262868962793625744043794305715222011528459656738731;
        uint256 constant betay1  = 21847035105528745403288232691147584728191162732299865338377159692350059136679;
        uint256 constant betay2  = 10505242626370262277552901082094356697409835680220590971873171140371331206856;
        uint256 constant gammax1 = 11559732032986387107991004021392285783925812861821192530917403151452391805634;
        uint256 constant gammax2 = 10857046999023057135944570762232829481370756359578518086990519993285655852781;
        uint256 constant gammay1 = 4082367875863433681332203403145435568316851327593401208105741076214120093531;
        uint256 constant gammay2 = 8495653923123431417604973247489272438418190587263600148770280649306958101930;
        uint256 constant deltax1 = 11559732032986387107991004021392285783925812861821192530917403151452391805634;
        uint256 constant deltax2 = 10857046999023057135944570762232829481370756359578518086990519993285655852781;
        uint256 constant deltay1 = 4082367875863433681332203403145435568316851327593401208105741076214120093531;
        uint256 constant deltay2 = 8495653923123431417604973247489272438418190587263600148770280649306958101930;
    
        
        uint256 constant IC0x = 8943199411353616279853147708091837922450872749824267022111661224284422059545;
        uint256 constant IC0y = 2527782090958762911523439352806249574560278192554090669374547638098730893920;
        
        uint256 constant IC1x = 5108695703485064860621139855119367483234319835495261166670981167140833713453;
        uint256 constant IC1y = 18438852931334256666812580876780655252037335361169552835036281678859582563151;
        
        uint256 constant IC2x = 13178853929006587699180437437226965795292367855766808875140302491005965866913;
        uint256 constant IC2y = 14087703798742614278660125080694874979669401811708832190727689517246288260580;
        
        uint256 constant IC3x = 15173882640170688486619730874268025664125853360913929506566027119543982548941;
        uint256 constant IC3y = 12481492736612752406904069194590434215859197717433477706054787457666820950437;
        
        uint256 constant IC4x = 21825939569176382880526651799982401311269038266123675633599218265595978242570;
        uint256 constant IC4y = 10377087872212368550661009166651181652906269464546521053440917230645535911138;
        
        uint256 constant IC5x = 15228933173345172411635118771469796162327178254266306644753988466650401736528;
        uint256 constant IC5y = 8073250402125796078079441301938705424909513745862706257099551614566421362395;
        
        uint256 constant IC6x = 14421825156846773440625656682438208158407803331348834491457054090711239925590;
        uint256 constant IC6y = 1680229812702698462736532695532376654981075822502826204407786262892689519347;
        
        uint256 constant IC7x = 3643234728033917416727725073983717742728846812429589999346608827290474916436;
        uint256 constant IC7y = 6250500636526810865703665791123982300129122370152132824463342426119037877551;
        
     
        // Memory data
        uint16 constant pVk = 0;
        uint16 constant pPairing = 128;
    
        uint16 constant pLastMem = 896;
    
        function verifyProof(uint[2] calldata _pA, uint[2][2] calldata _pB, uint[2] calldata _pC, uint[7] calldata _pubSignals) public view returns (bool) {
            assembly {
                function checkField(v) {
                    if iszero(lt(v, r)) {
                        mstore(0, 0)
                        return(0, 0x20)
                    }
                }
                
                // G1 function to multiply a G1 value(x,y) to value in an address
                function g1_mulAccC(pR, x, y, s) {
                    let success
                    let mIn := mload(0x40)
                    mstore(mIn, x)
                    mstore(add(mIn, 32), y)
                    mstore(add(mIn, 64), s)
    
                    success := staticcall(sub(gas(), 2000), 7, mIn, 96, mIn, 64)
    
                    if iszero(success) {
                        mstore(0, 0)
                        return(0, 0x20)
                    }
    
                    mstore(add(mIn, 64), mload(pR))
                    mstore(add(mIn, 96), mload(add(pR, 32)))
    
                    success := staticcall(sub(gas(), 2000), 6, mIn, 128, pR, 64)
    
                    if iszero(success) {
                        mstore(0, 0)
                        return(0, 0x20)
                    }
                }
    
                function checkPairing(pA, pB, pC, pubSignals, pMem) -> isOk {
                    let _pPairing := add(pMem, pPairing)
                    let _pVk := add(pMem, pVk)
    
                    mstore(_pVk, IC0x)
                    mstore(add(_pVk, 32), IC0y)
    
                    // Compute the linear combination vk_x
                    
                    g1_mulAccC(_pVk, IC1x, IC1y, calldataload(add(pubSignals, 0)))
                    
                    g1_mulAccC(_pVk, IC2x, IC2y, calldataload(add(pubSignals, 32)))
                    
                    g1_mulAccC(_pVk, IC3x, IC3y, calldataload(add(pubSignals, 64)))
                    
                    g1_mulAccC(_pVk, IC4x, IC4y, calldataload(add(pubSignals, 96)))
                    
                    g1_mulAccC(_pVk, IC5x, IC5y, calldataload(add(pubSignals, 128)))
                    
                    g1_mulAccC(_pVk, IC6x, IC6y, calldataload(add(pubSignals, 160)))
                    
                    g1_mulAccC(_pVk, IC7x, IC7y, calldataload(add(pubSignals, 192)))
                    
    
                    // -A
                    mstore(_pPairing, calldataload(pA))
                    mstore(add(_pPairing, 32), mod(sub(q, calldataload(add(pA, 32))), q))
    
                    // B
                    mstore(add(_pPairing, 64), calldataload(pB))
                    mstore(add(_pPairing, 96), calldataload(add(pB, 32)))
                    mstore(add(_pPairing, 128), calldataload(add(pB, 64)))
                    mstore(add(_pPairing, 160), calldataload(add(pB, 96)))
    
                    // alpha1
                    mstore(add(_pPairing, 192), alphax)
                    mstore(add(_pPairing, 224), alphay)
    
                    // beta2
                    mstore(add(_pPairing, 256), betax1)
                    mstore(add(_pPairing, 288), betax2)
                    mstore(add(_pPairing, 320), betay1)
                    mstore(add(_pPairing, 352), betay2)
    
                    // vk_x
                    mstore(add(_pPairing, 384), mload(add(pMem, pVk)))
                    mstore(add(_pPairing, 416), mload(add(pMem, add(pVk, 32))))
    
    
                    // gamma2
                    mstore(add(_pPairing, 448), gammax1)
                    mstore(add(_pPairing, 480), gammax2)
                    mstore(add(_pPairing, 512), gammay1)
                    mstore(add(_pPairing, 544), gammay2)
    
                    // C
                    mstore(add(_pPairing, 576), calldataload(pC))
                    mstore(add(_pPairing, 608), calldataload(add(pC, 32)))
    
                    // delta2
                    mstore(add(_pPairing, 640), deltax1)
                    mstore(add(_pPairing, 672), deltax2)
                    mstore(add(_pPairing, 704), deltay1)
                    mstore(add(_pPairing, 736), deltay2)
    
    
                    let success := staticcall(sub(gas(), 2000), 8, _pPairing, 768, _pPairing, 0x20)
    
                    isOk := and(success, mload(_pPairing))
                }
    
                let pMem := mload(0x40)
                mstore(0x40, add(pMem, pLastMem))
    
                // Validate that all evaluations ∈ F
                
                checkField(calldataload(add(_pubSignals, 0)))
                
                checkField(calldataload(add(_pubSignals, 32)))
                
                checkField(calldataload(add(_pubSignals, 64)))
                
                checkField(calldataload(add(_pubSignals, 96)))
                
                checkField(calldataload(add(_pubSignals, 128)))
                
                checkField(calldataload(add(_pubSignals, 160)))
                
                checkField(calldataload(add(_pubSignals, 192)))
                
    
                // Validate all evaluations
                let isValid := checkPairing(_pA, _pB, _pC, _pubSignals, pMem)
    
                mstore(0, isValid)
                 return(0, 0x20)
             }
         }
     }
    
  • contracts/verifier/state-transition-verifier.sol
    // SPDX-License-Identifier: GPL-3.0
    /*
        Copyright 2021 0KIMS association.
    
        This file is generated with [snarkJS](https://github.com/iden3/snarkjs).
    
        snarkJS is a free software: you can redistribute it and/or modify it
        under the terms of the GNU General Public License as published by
        the Free Software Foundation, either version 3 of the License, or
        (at your option) any later version.
    
        snarkJS is distributed in the hope that it will be useful, but WITHOUT
        ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
        or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
        License for more details.
    
        You should have received a copy of the GNU General Public License
        along with snarkJS. If not, see <https://www.gnu.org/licenses/>.
    */
    
    pragma solidity >=0.7.0 <0.9.0;
    
    contract StateTransitionVerifier {
        // Scalar field size
        uint256 constant r    = 21888242871839275222246405745257275088548364400416034343698204186575808495617;
        // Base field size
        uint256 constant q   = 21888242871839275222246405745257275088696311157297823662689037894645226208583;
    
        // Verification Key data
        uint256 constant alphax  = 20491192805390485299153009773594534940189261866228447918068658471970481763042;
        uint256 constant alphay  = 9383485363053290200918347156157836566562967994039712273449902621266178545958;
        uint256 constant betax1  = 4252822878758300859123897981450591353533073413197771768651442665752259397132;
        uint256 constant betax2  = 6375614351688725206403948262868962793625744043794305715222011528459656738731;
        uint256 constant betay1  = 21847035105528745403288232691147584728191162732299865338377159692350059136679;
        uint256 constant betay2  = 10505242626370262277552901082094356697409835680220590971873171140371331206856;
        uint256 constant gammax1 = 11559732032986387107991004021392285783925812861821192530917403151452391805634;
        uint256 constant gammax2 = 10857046999023057135944570762232829481370756359578518086990519993285655852781;
        uint256 constant gammay1 = 4082367875863433681332203403145435568316851327593401208105741076214120093531;
        uint256 constant gammay2 = 8495653923123431417604973247489272438418190587263600148770280649306958101930;
        uint256 constant deltax1 = 11559732032986387107991004021392285783925812861821192530917403151452391805634;
        uint256 constant deltax2 = 10857046999023057135944570762232829481370756359578518086990519993285655852781;
        uint256 constant deltay1 = 4082367875863433681332203403145435568316851327593401208105741076214120093531;
        uint256 constant deltay2 = 8495653923123431417604973247489272438418190587263600148770280649306958101930;
    
        
        uint256 constant IC0x = 14848386072906424301650814231608272047769445024926995465112443958386575767820;
        uint256 constant IC0y = 4077962579261104689227434269268992895772575711469450452935750387049837706943;
        
        uint256 constant IC1x = 122988669606071917786404350903006956942063809491104743123304864545024047413;
        uint256 constant IC1y = 12554908852380480774240028741407435101726249313249658532176871006986442638050;
        
        uint256 constant IC2x = 16046131934256190995789826026521934973457154692573963381697380132181031607830;
        uint256 constant IC2y = 10813134100504562488912357006145697797166101684529041597578516438831215993538;
        
        uint256 constant IC3x = 19893172508358838532096218112333743199425765506107673005003768269831151222075;
        uint256 constant IC3y = 10682947962177223259266967347278199793978639523628320524426184356159805127035;
        
        uint256 constant IC4x = 15138599077834452203792659517354675080651020201307316860353001598028123502354;
        uint256 constant IC4y = 7233681229320769771260401075549429477688063490302867948257877618371466832827;
        
     
        // Memory data
        uint16 constant pVk = 0;
        uint16 constant pPairing = 128;
    
        uint16 constant pLastMem = 896;
    
        function verifyProof(uint[2] calldata _pA, uint[2][2] calldata _pB, uint[2] calldata _pC, uint[4] calldata _pubSignals) public view returns (bool) {
            assembly {
                function checkField(v) {
                    if iszero(lt(v, r)) {
                        mstore(0, 0)
                        return(0, 0x20)
                    }
                }
                
                // G1 function to multiply a G1 value(x,y) to value in an address
                function g1_mulAccC(pR, x, y, s) {
                    let success
                    let mIn := mload(0x40)
                    mstore(mIn, x)
                    mstore(add(mIn, 32), y)
                    mstore(add(mIn, 64), s)
    
                    success := staticcall(sub(gas(), 2000), 7, mIn, 96, mIn, 64)
    
                    if iszero(success) {
                        mstore(0, 0)
                        return(0, 0x20)
                    }
    
                    mstore(add(mIn, 64), mload(pR))
                    mstore(add(mIn, 96), mload(add(pR, 32)))
    
                    success := staticcall(sub(gas(), 2000), 6, mIn, 128, pR, 64)
    
                    if iszero(success) {
                        mstore(0, 0)
                        return(0, 0x20)
                    }
                }
    
                function checkPairing(pA, pB, pC, pubSignals, pMem) -> isOk {
                    let _pPairing := add(pMem, pPairing)
                    let _pVk := add(pMem, pVk)
    
                    mstore(_pVk, IC0x)
                    mstore(add(_pVk, 32), IC0y)
    
                    // Compute the linear combination vk_x
                    
                    g1_mulAccC(_pVk, IC1x, IC1y, calldataload(add(pubSignals, 0)))
                    
                    g1_mulAccC(_pVk, IC2x, IC2y, calldataload(add(pubSignals, 32)))
                    
                    g1_mulAccC(_pVk, IC3x, IC3y, calldataload(add(pubSignals, 64)))
                    
                    g1_mulAccC(_pVk, IC4x, IC4y, calldataload(add(pubSignals, 96)))
                    
    
                    // -A
                    mstore(_pPairing, calldataload(pA))
                    mstore(add(_pPairing, 32), mod(sub(q, calldataload(add(pA, 32))), q))
    
                    // B
                    mstore(add(_pPairing, 64), calldataload(pB))
                    mstore(add(_pPairing, 96), calldataload(add(pB, 32)))
                    mstore(add(_pPairing, 128), calldataload(add(pB, 64)))
                    mstore(add(_pPairing, 160), calldataload(add(pB, 96)))
    
                    // alpha1
                    mstore(add(_pPairing, 192), alphax)
                    mstore(add(_pPairing, 224), alphay)
    
                    // beta2
                    mstore(add(_pPairing, 256), betax1)
                    mstore(add(_pPairing, 288), betax2)
                    mstore(add(_pPairing, 320), betay1)
                    mstore(add(_pPairing, 352), betay2)
    
                    // vk_x
                    mstore(add(_pPairing, 384), mload(add(pMem, pVk)))
                    mstore(add(_pPairing, 416), mload(add(pMem, add(pVk, 32))))
    
    
                    // gamma2
                    mstore(add(_pPairing, 448), gammax1)
                    mstore(add(_pPairing, 480), gammax2)
                    mstore(add(_pPairing, 512), gammay1)
                    mstore(add(_pPairing, 544), gammay2)
    
                    // C
                    mstore(add(_pPairing, 576), calldataload(pC))
                    mstore(add(_pPairing, 608), calldataload(add(pC, 32)))
    
                    // delta2
                    mstore(add(_pPairing, 640), deltax1)
                    mstore(add(_pPairing, 672), deltax2)
                    mstore(add(_pPairing, 704), deltay1)
                    mstore(add(_pPairing, 736), deltay2)
    
    
                    let success := staticcall(sub(gas(), 2000), 8, _pPairing, 768, _pPairing, 0x20)
    
                    isOk := and(success, mload(_pPairing))
                }
    
                let pMem := mload(0x40)
                mstore(0x40, add(pMem, pLastMem))
    
                // Validate that all evaluations ∈ F
                
                checkField(calldataload(add(_pubSignals, 0)))
                
                checkField(calldataload(add(_pubSignals, 32)))
                
                checkField(calldataload(add(_pubSignals, 64)))
                
                checkField(calldataload(add(_pubSignals, 96)))
                
    
                // Validate all evaluations
                let isValid := checkPairing(_pA, _pB, _pC, _pubSignals, pMem)
    
                mstore(0, isValid)
                 return(0, 0x20)
             }
         }
     }
    
  • solidity-bytes-utils/contracts/BytesLib.sol
    // SPDX-License-Identifier: Unlicense
    /*
     * @title Solidity Bytes Arrays Utils
     * @author Gonçalo Sá <goncalo.sa@consensys.net>
     *
     * @dev Bytes tightly packed arrays utility library for ethereum contracts written in Solidity.
     *      The library lets you concatenate, slice and type cast bytes arrays both in memory and storage.
     */
    pragma solidity >=0.8.0 <0.9.0;
    
    
    library BytesLib {
        function concat(
            bytes memory _preBytes,
            bytes memory _postBytes
        )
            internal
            pure
            returns (bytes memory)
        {
            bytes memory tempBytes;
    
            assembly {
                // Get a location of some free memory and store it in tempBytes as
                // Solidity does for memory variables.
                tempBytes := mload(0x40)
    
                // Store the length of the first bytes array at the beginning of
                // the memory for tempBytes.
                let length := mload(_preBytes)
                mstore(tempBytes, length)
    
                // Maintain a memory counter for the current write location in the
                // temp bytes array by adding the 32 bytes for the array length to
                // the starting location.
                let mc := add(tempBytes, 0x20)
                // Stop copying when the memory counter reaches the length of the
                // first bytes array.
                let end := add(mc, length)
    
                for {
                    // Initialize a copy counter to the start of the _preBytes data,
                    // 32 bytes into its memory.
                    let cc := add(_preBytes, 0x20)
                } lt(mc, end) {
                    // Increase both counters by 32 bytes each iteration.
                    mc := add(mc, 0x20)
                    cc := add(cc, 0x20)
                } {
                    // Write the _preBytes data into the tempBytes memory 32 bytes
                    // at a time.
                    mstore(mc, mload(cc))
                }
    
                // Add the length of _postBytes to the current length of tempBytes
                // and store it as the new length in the first 32 bytes of the
                // tempBytes memory.
                length := mload(_postBytes)
                mstore(tempBytes, add(length, mload(tempBytes)))
    
                // Move the memory counter back from a multiple of 0x20 to the
                // actual end of the _preBytes data.
                mc := end
                // Stop copying when the memory counter reaches the new combined
                // length of the arrays.
                end := add(mc, length)
    
                for {
                    let cc := add(_postBytes, 0x20)
                } lt(mc, end) {
                    mc := add(mc, 0x20)
                    cc := add(cc, 0x20)
                } {
                    mstore(mc, mload(cc))
                }
    
                // Update the free-memory pointer by padding our last write location
                // to 32 bytes: add 31 bytes to the end of tempBytes to move to the
                // next 32 byte block, then round down to the nearest multiple of
                // 32. If the sum of the length of the two arrays is zero then add
                // one before rounding down to leave a blank 32 bytes (the length block with 0).
                mstore(0x40, and(
                  add(add(end, iszero(add(length, mload(_preBytes)))), 31),
                  not(31) // Round down to the nearest 32 bytes.
                ))
            }
    
            return tempBytes;
        }
    
        function concatStorage(bytes storage _preBytes, bytes memory _postBytes) internal {
            assembly {
                // Read the first 32 bytes of _preBytes storage, which is the length
                // of the array. (We don't need to use the offset into the slot
                // because arrays use the entire slot.)
                let fslot := sload(_preBytes.slot)
                // Arrays of 31 bytes or less have an even value in their slot,
                // while longer arrays have an odd value. The actual length is
                // the slot divided by two for odd values, and the lowest order
                // byte divided by two for even values.
                // If the slot is even, bitwise and the slot with 255 and divide by
                // two to get the length. If the slot is odd, bitwise and the slot
                // with -1 and divide by two.
                let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2)
                let mlength := mload(_postBytes)
                let newlength := add(slength, mlength)
                // slength can contain both the length and contents of the array
                // if length < 32 bytes so let's prepare for that
                // v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage
                switch add(lt(slength, 32), lt(newlength, 32))
                case 2 {
                    // Since the new array still fits in the slot, we just need to
                    // update the contents of the slot.
                    // uint256(bytes_storage) = uint256(bytes_storage) + uint256(bytes_memory) + new_length
                    sstore(
                        _preBytes.slot,
                        // all the modifications to the slot are inside this
                        // next block
                        add(
                            // we can just add to the slot contents because the
                            // bytes we want to change are the LSBs
                            fslot,
                            add(
                                mul(
                                    div(
                                        // load the bytes from memory
                                        mload(add(_postBytes, 0x20)),
                                        // zero all bytes to the right
                                        exp(0x100, sub(32, mlength))
                                    ),
                                    // and now shift left the number of bytes to
                                    // leave space for the length in the slot
                                    exp(0x100, sub(32, newlength))
                                ),
                                // increase length by the double of the memory
                                // bytes length
                                mul(mlength, 2)
                            )
                        )
                    )
                }
                case 1 {
                    // The stored value fits in the slot, but the combined value
                    // will exceed it.
                    // get the keccak hash to get the contents of the array
                    mstore(0x0, _preBytes.slot)
                    let sc := add(keccak256(0x0, 0x20), div(slength, 32))
    
                    // save new length
                    sstore(_preBytes.slot, add(mul(newlength, 2), 1))
    
                    // The contents of the _postBytes array start 32 bytes into
                    // the structure. Our first read should obtain the `submod`
                    // bytes that can fit into the unused space in the last word
                    // of the stored array. To get this, we read 32 bytes starting
                    // from `submod`, so the data we read overlaps with the array
                    // contents by `submod` bytes. Masking the lowest-order
                    // `submod` bytes allows us to add that value directly to the
                    // stored value.
    
                    let submod := sub(32, slength)
                    let mc := add(_postBytes, submod)
                    let end := add(_postBytes, mlength)
                    let mask := sub(exp(0x100, submod), 1)
    
                    sstore(
                        sc,
                        add(
                            and(
                                fslot,
                                0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00
                            ),
                            and(mload(mc), mask)
                        )
                    )
    
                    for {
                        mc := add(mc, 0x20)
                        sc := add(sc, 1)
                    } lt(mc, end) {
                        sc := add(sc, 1)
                        mc := add(mc, 0x20)
                    } {
                        sstore(sc, mload(mc))
                    }
    
                    mask := exp(0x100, sub(mc, end))
    
                    sstore(sc, mul(div(mload(mc), mask), mask))
                }
                default {
                    // get the keccak hash to get the contents of the array
                    mstore(0x0, _preBytes.slot)
                    // Start copying to the last used word of the stored array.
                    let sc := add(keccak256(0x0, 0x20), div(slength, 32))
    
                    // save new length
                    sstore(_preBytes.slot, add(mul(newlength, 2), 1))
    
                    // Copy over the first `submod` bytes of the new data as in
                    // case 1 above.
                    let slengthmod := mod(slength, 32)
                    let mlengthmod := mod(mlength, 32)
                    let submod := sub(32, slengthmod)
                    let mc := add(_postBytes, submod)
                    let end := add(_postBytes, mlength)
                    let mask := sub(exp(0x100, submod), 1)
    
                    sstore(sc, add(sload(sc), and(mload(mc), mask)))
    
                    for {
                        sc := add(sc, 1)
                        mc := add(mc, 0x20)
                    } lt(mc, end) {
                        sc := add(sc, 1)
                        mc := add(mc, 0x20)
                    } {
                        sstore(sc, mload(mc))
                    }
    
                    mask := exp(0x100, sub(mc, end))
    
                    sstore(sc, mul(div(mload(mc), mask), mask))
                }
            }
        }
    
        function slice(
            bytes memory _bytes,
            uint256 _start,
            uint256 _length
        )
            internal
            pure
            returns (bytes memory)
        {
            require(_length + 31 >= _length, "slice_overflow");
            require(_bytes.length >= _start + _length, "slice_outOfBounds");
    
            bytes memory tempBytes;
    
            assembly {
                switch iszero(_length)
                case 0 {
                    // Get a location of some free memory and store it in tempBytes as
                    // Solidity does for memory variables.
                    tempBytes := mload(0x40)
    
                    // The first word of the slice result is potentially a partial
                    // word read from the original array. To read it, we calculate
                    // the length of that partial word and start copying that many
                    // bytes into the array. The first word we copy will start with
                    // data we don't care about, but the last `lengthmod` bytes will
                    // land at the beginning of the contents of the new array. When
                    // we're done copying, we overwrite the full first word with
                    // the actual length of the slice.
                    let lengthmod := and(_length, 31)
    
                    // The multiplication in the next line is necessary
                    // because when slicing multiples of 32 bytes (lengthmod == 0)
                    // the following copy loop was copying the origin's length
                    // and then ending prematurely not copying everything it should.
                    let mc := add(add(tempBytes, lengthmod), mul(0x20, iszero(lengthmod)))
                    let end := add(mc, _length)
    
                    for {
                        // The multiplication in the next line has the same exact purpose
                        // as the one above.
                        let cc := add(add(add(_bytes, lengthmod), mul(0x20, iszero(lengthmod))), _start)
                    } lt(mc, end) {
                        mc := add(mc, 0x20)
                        cc := add(cc, 0x20)
                    } {
                        mstore(mc, mload(cc))
                    }
    
                    mstore(tempBytes, _length)
    
                    //update free-memory pointer
                    //allocating the array padded to 32 bytes like the compiler does now
                    mstore(0x40, and(add(mc, 31), not(31)))
                }
                //if we want a zero-length slice let's just return a zero-length array
                default {
                    tempBytes := mload(0x40)
                    //zero out the 32 bytes slice we are about to return
                    //we need to do it because Solidity does not garbage collect
                    mstore(tempBytes, 0)
    
                    mstore(0x40, add(tempBytes, 0x20))
                }
            }
    
            return tempBytes;
        }
    
        function toAddress(bytes memory _bytes, uint256 _start) internal pure returns (address) {
            require(_bytes.length >= _start + 20, "toAddress_outOfBounds");
            address tempAddress;
    
            assembly {
                tempAddress := div(mload(add(add(_bytes, 0x20), _start)), 0x1000000000000000000000000)
            }
    
            return tempAddress;
        }
    
        function toUint8(bytes memory _bytes, uint256 _start) internal pure returns (uint8) {
            require(_bytes.length >= _start + 1 , "toUint8_outOfBounds");
            uint8 tempUint;
    
            assembly {
                tempUint := mload(add(add(_bytes, 0x1), _start))
            }
    
            return tempUint;
        }
    
        function toUint16(bytes memory _bytes, uint256 _start) internal pure returns (uint16) {
            require(_bytes.length >= _start + 2, "toUint16_outOfBounds");
            uint16 tempUint;
    
            assembly {
                tempUint := mload(add(add(_bytes, 0x2), _start))
            }
    
            return tempUint;
        }
    
        function toUint32(bytes memory _bytes, uint256 _start) internal pure returns (uint32) {
            require(_bytes.length >= _start + 4, "toUint32_outOfBounds");
            uint32 tempUint;
    
            assembly {
                tempUint := mload(add(add(_bytes, 0x4), _start))
            }
    
            return tempUint;
        }
    
        function toUint64(bytes memory _bytes, uint256 _start) internal pure returns (uint64) {
            require(_bytes.length >= _start + 8, "toUint64_outOfBounds");
            uint64 tempUint;
    
            assembly {
                tempUint := mload(add(add(_bytes, 0x8), _start))
            }
    
            return tempUint;
        }
    
        function toUint96(bytes memory _bytes, uint256 _start) internal pure returns (uint96) {
            require(_bytes.length >= _start + 12, "toUint96_outOfBounds");
            uint96 tempUint;
    
            assembly {
                tempUint := mload(add(add(_bytes, 0xc), _start))
            }
    
            return tempUint;
        }
    
        function toUint128(bytes memory _bytes, uint256 _start) internal pure returns (uint128) {
            require(_bytes.length >= _start + 16, "toUint128_outOfBounds");
            uint128 tempUint;
    
            assembly {
                tempUint := mload(add(add(_bytes, 0x10), _start))
            }
    
            return tempUint;
        }
    
        function toUint256(bytes memory _bytes, uint256 _start) internal pure returns (uint256) {
            require(_bytes.length >= _start + 32, "toUint256_outOfBounds");
            uint256 tempUint;
    
            assembly {
                tempUint := mload(add(add(_bytes, 0x20), _start))
            }
    
            return tempUint;
        }
    
        function toBytes32(bytes memory _bytes, uint256 _start) internal pure returns (bytes32) {
            require(_bytes.length >= _start + 32, "toBytes32_outOfBounds");
            bytes32 tempBytes32;
    
            assembly {
                tempBytes32 := mload(add(add(_bytes, 0x20), _start))
            }
    
            return tempBytes32;
        }
    
        function equal(bytes memory _preBytes, bytes memory _postBytes) internal pure returns (bool) {
            bool success = true;
    
            assembly {
                let length := mload(_preBytes)
    
                // if lengths don't match the arrays are not equal
                switch eq(length, mload(_postBytes))
                case 1 {
                    // cb is a circuit breaker in the for loop since there's
                    //  no said feature for inline assembly loops
                    // cb = 1 - don't breaker
                    // cb = 0 - break
                    let cb := 1
    
                    let mc := add(_preBytes, 0x20)
                    let end := add(mc, length)
    
                    for {
                        let cc := add(_postBytes, 0x20)
                    // the next line is the loop condition:
                    // while(uint256(mc < end) + cb == 2)
                    } eq(add(lt(mc, end), cb), 2) {
                        mc := add(mc, 0x20)
                        cc := add(cc, 0x20)
                    } {
                        // if any of these checks fails then arrays are not equal
                        if iszero(eq(mload(mc), mload(cc))) {
                            // unsuccess:
                            success := 0
                            cb := 0
                        }
                    }
                }
                default {
                    // unsuccess:
                    success := 0
                }
            }
    
            return success;
        }
    
        function equalStorage(
            bytes storage _preBytes,
            bytes memory _postBytes
        )
            internal
            view
            returns (bool)
        {
            bool success = true;
    
            assembly {
                // we know _preBytes_offset is 0
                let fslot := sload(_preBytes.slot)
                // Decode the length of the stored array like in concatStorage().
                let slength := div(and(fslot, sub(mul(0x100, iszero(and(fslot, 1))), 1)), 2)
                let mlength := mload(_postBytes)
    
                // if lengths don't match the arrays are not equal
                switch eq(slength, mlength)
                case 1 {
                    // slength can contain both the length and contents of the array
                    // if length < 32 bytes so let's prepare for that
                    // v. http://solidity.readthedocs.io/en/latest/miscellaneous.html#layout-of-state-variables-in-storage
                    if iszero(iszero(slength)) {
                        switch lt(slength, 32)
                        case 1 {
                            // blank the last byte which is the length
                            fslot := mul(div(fslot, 0x100), 0x100)
    
                            if iszero(eq(fslot, mload(add(_postBytes, 0x20)))) {
                                // unsuccess:
                                success := 0
                            }
                        }
                        default {
                            // cb is a circuit breaker in the for loop since there's
                            //  no said feature for inline assembly loops
                            // cb = 1 - don't breaker
                            // cb = 0 - break
                            let cb := 1
    
                            // get the keccak hash to get the contents of the array
                            mstore(0x0, _preBytes.slot)
                            let sc := keccak256(0x0, 0x20)
    
                            let mc := add(_postBytes, 0x20)
                            let end := add(mc, mlength)
    
                            // the next line is the loop condition:
                            // while(uint256(mc < end) + cb == 2)
                            for {} eq(add(lt(mc, end), cb), 2) {
                                sc := add(sc, 1)
                                mc := add(mc, 0x20)
                            } {
                                if iszero(eq(sload(sc), mload(mc))) {
                                    // unsuccess:
                                    success := 0
                                    cb := 0
                                }
                            }
                        }
                    }
                }
                default {
                    // unsuccess:
                    success := 0
                }
            }
    
            return success;
        }
    }
    
ABI · 63 entries
json
[
  {
    "type": "constructor",
    "inputs": [],
    "stateMutability": "nonpayable"
  },
  {
    "name": "AddressEmptyCode",
    "type": "error",
    "inputs": [
      {
        "name": "target",
        "type": "address",
        "internalType": "address"
      }
    ]
  },
  {
    "name": "ERC1967InvalidImplementation",
    "type": "error",
    "inputs": [
      {
        "name": "implementation",
        "type": "address",
        "internalType": "address"
      }
    ]
  },
  {
    "name": "ERC1967NonPayable",
    "type": "error",
    "inputs": []
  },
  {
    "name": "FailedCall",
    "type": "error",
    "inputs": []
  },
  {
    "name": "InvalidInitialization",
    "type": "error",
    "inputs": []
  },
  {
    "name": "NotInitializing",
    "type": "error",
    "inputs": []
  },
  {
    "name": "OwnableInvalidOwner",
    "type": "error",
    "inputs": [
      {
        "name": "owner",
        "type": "address",
        "internalType": "address"
      }
    ]
  },
  {
    "name": "OwnableUnauthorizedAccount",
    "type": "error",
    "inputs": [
      {
        "name": "account",
        "type": "address",
        "internalType": "address"
      }
    ]
  },
  {
    "name": "UUPSUnauthorizedCallContext",
    "type": "error",
    "inputs": []
  },
  {
    "name": "UUPSUnsupportedProxiableUUID",
    "type": "error",
    "inputs": [
      {
        "name": "slot",
        "type": "bytes32",
        "internalType": "bytes32"
      }
    ]
  },
  {
    "name": "DIDRegistered",
    "type": "event",
    "inputs": [
      {
        "name": "userId",
        "type": "uint256",
        "indexed": true,
        "internalType": "uint256"
      },
      {
        "name": "entityId",
        "type": "uint256",
        "indexed": false,
        "internalType": "uint256"
      },
      {
        "name": "entityType",
        "type": "uint256",
        "indexed": false,
        "internalType": "uint256"
      },
      {
        "name": "authClaimCore",
        "type": "uint256[8]",
        "indexed": false,
        "internalType": "uint256[8]"
      },
      {
        "name": "forUEntityClaimCore",
        "type": "uint256[8]",
        "indexed": false,
        "internalType": "uint256[8]"
      }
    ],
    "anonymous": false
  },
  {
    "name": "GenesisStateRegistered",
    "type": "event",
    "inputs": [
      {
        "name": "id",
        "type": "uint256",
        "indexed": true,
        "internalType": "uint256"
      },
      {
        "name": "oldState",
        "type": "uint256",
        "indexed": false,
        "internalType": "uint256"
      },
      {
        "name": "newState",
        "type": "uint256",
        "indexed": false,
        "internalType": "uint256"
      },
      {
        "name": "isOldStateGenesis",
        "type": "bool",
        "indexed": false,
        "internalType": "bool"
      }
    ],
    "anonymous": false
  },
  {
    "name": "IdentityJoinedCommunityRegistered",
    "type": "event",
    "inputs": [
      {
        "name": "communityId",
        "type": "uint256",
        "indexed": true,
        "internalType": "uint256"
      },
      {
        "name": "id",
        "type": "uint256",
        "indexed": true,
        "internalType": "uint256"
      },
      {
        "name": "memberRole",
        "type": "uint256",
        "indexed": false,
        "internalType": "uint256"
      },
      {
        "name": "memberEntityType",
        "type": "uint256",
        "indexed": false,
        "internalType": "uint256"
      },
      {
        "name": "membershipClaimCore",
        "type": "uint256[8]",
        "indexed": false,
        "internalType": "uint256[8]"
      }
    ],
    "anonymous": false
  },
  {
    "name": "Initialized",
    "type": "event",
    "inputs": [
      {
        "name": "version",
        "type": "uint64",
        "indexed": false,
        "internalType": "uint64"
      }
    ],
    "anonymous": false
  },
  {
    "name": "MasterDIDRegistered",
    "type": "event",
    "inputs": [
      {
        "name": "id",
        "type": "uint256",
        "indexed": true,
        "internalType": "uint256"
      },
      {
        "name": "state",
        "type": "uint256",
        "indexed": false,
        "internalType": "uint256"
      },
      {
        "name": "authClaimCore",
        "type": "uint256[8]",
        "indexed": false,
        "internalType": "uint256[8]"
      }
    ],
    "anonymous": false
  },
  {
    "name": "OwnershipTransferStarted",
    "type": "event",
    "inputs": [
      {
        "name": "previousOwner",
        "type": "address",
        "indexed": true,
        "internalType": "address"
      },
      {
        "name": "newOwner",
        "type": "address",
        "indexed": true,
        "internalType": "address"
      }
    ],
    "anonymous": false
  },
  {
    "name": "OwnershipTransferred",
    "type": "event",
    "inputs": [
      {
        "name": "previousOwner",
        "type": "address",
        "indexed": true,
        "internalType": "address"
      },
      {
        "name": "newOwner",
        "type": "address",
        "indexed": true,
        "internalType": "address"
      }
    ],
    "anonymous": false
  },
  {
    "name": "StateTransitioned",
    "type": "event",
    "inputs": [
      {
        "name": "id",
        "type": "uint256",
        "indexed": true,
        "internalType": "uint256"
      },
      {
        "name": "oldState",
        "type": "uint256",
        "indexed": false,
        "internalType": "uint256"
      },
      {
        "name": "newState",
        "type": "uint256",
        "indexed": false,
        "internalType": "uint256"
      },
      {
        "name": "isOldStateGenesis",
        "type": "bool",
        "indexed": false,
        "internalType": "bool"
      }
    ],
    "anonymous": false
  },
  {
    "name": "Upgraded",
    "type": "event",
    "inputs": [
      {
        "name": "implementation",
        "type": "address",
        "indexed": true,
        "internalType": "address"
      }
    ],
    "anonymous": false
  },
  {
    "name": "UPGRADE_INTERFACE_VERSION",
    "type": "function",
    "inputs": [],
    "outputs": [
      {
        "name": "",
        "type": "string",
        "internalType": "string"
      }
    ],
    "stateMutability": "view"
  },
  {
    "name": "acceptOwnership",
    "type": "function",
    "inputs": [],
    "outputs": [],
    "stateMutability": "nonpayable"
  },
  {
    "name": "communityMembership",
    "type": "function",
    "inputs": [
      {
        "name": "",
        "type": "uint256",
        "internalType": "uint256"
      },
      {
        "name": "",
        "type": "uint256",
        "internalType": "uint256"
      }
    ],
    "outputs": [
      {
        "name": "",
        "type": "uint256",
        "internalType": "uint256"
      }
    ],
    "stateMutability": "view"
  },
  {
    "name": "communityMembershipInfo",
    "type": "function",
    "inputs": [
      {
        "name": "",
        "type": "uint256",
        "internalType": "uint256"
      },
      {
        "name": "",
        "type": "uint256",
        "internalType": "uint256"
      }
    ],
    "outputs": [
      {
        "name": "index",
        "type": "uint256",
        "internalType": "uint256"
      },
      {
        "name": "memberRole",
        "type": "uint256",
        "internalType": "uint256"
      },
      {
        "name": "memberEntityType",
        "type": "uint256",
        "internalType": "uint256"
      },
      {
        "name": "incrementalNonce",
        "type": "uint256",
        "internalType": "uint256"
      }
    ],
    "stateMutability": "view"
  },
  {
    "name": "didToAuthClaimCore",
    "type": "function",
    "inputs": [
      {
        "name": "",
        "type": "uint256",
        "internalType": "uint256"
      },
      {
        "name": "",
        "type": "uint256",
        "internalType": "uint256"
      }
    ],
    "outputs": [
      {
        "name": "",
        "type": "uint256",
        "internalType": "uint256"
      }
    ],
    "stateMutability": "view"
  },
  {
    "name": "didToForUEntityClaimCore",
    "type": "function",
    "inputs": [
      {
        "name": "",
        "type": "uint256",
        "internalType": "uint256"
      },
      {
        "name": "",
        "type": "uint256",
        "internalType": "uint256"
      }
    ],
    "outputs": [
      {
        "name": "",
        "type": "uint256",
        "internalType": "uint256"
      }
    ],
    "stateMutability": "view"
  },
  {
    "name": "entityInfo",
    "type": "function",
    "inputs": [
      {
        "name": "",
        "type": "uint256",
        "internalType": "uint256"
      }
    ],
    "outputs": [
      {
        "name": "entityId",
        "type": "uint256",
        "internalType": "uint256"
      },
      {
        "name": "entityType",
        "type": "uint256",
        "internalType": "uint256"
      }
    ],
    "stateMutability": "view"
  },
  {
    "name": "getAuthClaimCore",
    "type": "function",
    "inputs": [
      {
        "name": "id",
        "type": "uint256",
        "internalType": "uint256"
      }
    ],
    "outputs": [
      {
        "name": "",
        "type": "uint256[8]",
        "internalType": "uint256[8]"
      }
    ],
    "stateMutability": "view"
  },
  {
    "name": "getCommunityMemberList",
    "type": "function",
    "inputs": [
      {
        "name": "communityId",
        "type": "uint256",
        "internalType": "uint256"
      },
      {
        "name": "startIndex",
        "type": "uint256",
        "internalType": "uint256"
      },
      {
        "name": "length",
        "type": "uint256",
        "internalType": "uint256"
      }
    ],
    "outputs": [
      {
        "name": "memberIdentityList",
        "type": "uint256[]",
        "internalType": "uint256[]"
      }
    ],
    "stateMutability": "view"
  },
  {
    "name": "getForUEntityClaimCore",
    "type": "function",
    "inputs": [
      {
        "name": "id",
        "type": "uint256",
        "internalType": "uint256"
      }
    ],
    "outputs": [
      {
        "name": "",
        "type": "uint256[8]",
        "internalType": "uint256[8]"
      }
    ],
    "stateMutability": "view"
  },
  {
    "name": "getMembershipClaimCore",
    "type": "function",
    "inputs": [
      {
        "name": "communityId",
        "type": "uint256",
        "internalType": "uint256"
      },
      {
        "name": "id",
        "type": "uint256",
        "internalType": "uint256"
      }
    ],
    "outputs": [
      {
        "name": "",
        "type": "uint256[8]",
        "internalType": "uint256[8]"
      }
    ],
    "stateMutability": "view"
  },
  {
    "name": "getMembershipInfoId",
    "type": "function",
    "inputs": [
      {
        "name": "communityId",
        "type": "uint256",
        "internalType": "uint256"
      },
      {
        "name": "id",
        "type": "uint256",
        "internalType": "uint256"
      }
    ],
    "outputs": [
      {
        "name": "membershipInfo",
        "type": "tuple",
        "components": [
          {
            "name": "index",
            "type": "uint256",
            "internalType": "uint256"
          },
          {
            "name": "memberRole",
            "type": "uint256",
            "internalType": "uint256"
          },
          {
            "name": "memberEntityType",
            "type": "uint256",
            "internalType": "uint256"
          },
          {
            "name": "incrementalNonce",
            "type": "uint256",
            "internalType": "uint256"
          },
          {
            "name": "membershipClaimCore",
            "type": "uint256[8]",
            "internalType": "uint256[8]"
          }
        ],
        "internalType": "struct State.MembershipInfo"
      }
    ],
    "stateMutability": "view"
  },
  {
    "name": "getStateInfoById",
    "type": "function",
    "inputs": [
      {
        "name": "id",
        "type": "uint256",
        "internalType": "uint256"
      }
    ],
    "outputs": [
      {
        "name": "",
        "type": "tuple",
        "components": [
          {
            "name": "id",
            "type": "uint256",
            "internalType": "uint256"
          },
          {
            "name": "state",
            "type": "uint256",
            "internalType": "uint256"
          },
          {
            "name": "replacedByState",
            "type": "uint256",
            "internalType": "uint256"
          },
          {
            "name": "createdAtTimestamp",
            "type": "uint256",
            "internalType": "uint256"
          },
          {
            "name": "replacedAtTimestamp",
            "type": "uint256",
            "internalType": "uint256"
          },
          {
            "name": "createdAtBlock",
            "type": "uint256",
            "internalType": "uint256"
          },
          {
            "name": "replacedAtBlock",
            "type": "uint256",
            "internalType": "uint256"
          }
        ],
        "internalType": "struct IState.StateInfo"
      }
    ],
    "stateMutability": "view"
  },
  {
    "name": "getStateInfoByIdAndState",
    "type": "function",
    "inputs": [
      {
        "name": "id",
        "type": "uint256",
        "internalType": "uint256"
      },
      {
        "name": "state",
        "type": "uint256",
        "internalType": "uint256"
      }
    ],
    "outputs": [
      {
        "name": "",
        "type": "tuple",
        "components": [
          {
            "name": "id",
            "type": "uint256",
            "internalType": "uint256"
          },
          {
            "name": "state",
            "type": "uint256",
            "internalType": "uint256"
          },
          {
            "name": "replacedByState",
            "type": "uint256",
            "internalType": "uint256"
          },
          {
            "name": "createdAtTimestamp",
            "type": "uint256",
            "internalType": "uint256"
          },
          {
            "name": "replacedAtTimestamp",
            "type": "uint256",
            "internalType": "uint256"
          },
          {
            "name": "createdAtBlock",
            "type": "uint256",
            "internalType": "uint256"
          },
          {
            "name": "replacedAtBlock",
            "type": "uint256",
            "internalType": "uint256"
          }
        ],
        "internalType": "struct IState.StateInfo"
      }
    ],
    "stateMutability": "view"
  },
  {
    "name": "getStateInfoHistoryById",
    "type": "function",
    "inputs": [
      {
        "name": "id",
        "type": "uint256",
        "internalType": "uint256"
      },
      {
        "name": "startIndex",
        "type": "uint256",
        "internalType": "uint256"
      },
      {
        "name": "length",
        "type": "uint256",
        "internalType": "uint256"
      }
    ],
    "outputs": [
      {
        "name": "",
        "type": "tuple[]",
        "components": [
          {
            "name": "id",
            "type": "uint256",
            "internalType": "uint256"
          },
          {
            "name": "state",
            "type": "uint256",
            "internalType": "uint256"
          },
          {
            "name": "replacedByState",
            "type": "uint256",
            "internalType": "uint256"
          },
          {
            "name": "createdAtTimestamp",
            "type": "uint256",
            "internalType": "uint256"
          },
          {
            "name": "replacedAtTimestamp",
            "type": "uint256",
            "internalType": "uint256"
          },
          {
            "name": "createdAtBlock",
            "type": "uint256",
            "internalType": "uint256"
          },
          {
            "name": "replacedAtBlock",
            "type": "uint256",
            "internalType": "uint256"
          }
        ],
        "internalType": "struct IState.StateInfo[]"
      }
    ],
    "stateMutability": "view"
  },
  {
    "name": "getStateInfoHistoryLengthById",
    "type": "function",
    "inputs": [
      {
        "name": "id",
        "type": "uint256",
        "internalType": "uint256"
      }
    ],
    "outputs": [
      {
        "name": "",
        "type": "uint256",
        "internalType": "uint256"
      }
    ],
    "stateMutability": "view"
  },
  {
    "name": "getStateReplacedAt",
    "type": "function",
    "inputs": [
      {
        "name": "id",
        "type": "uint256",
        "internalType": "uint256"
      },
      {
        "name": "state",
        "type": "uint256",
        "internalType": "uint256"
      }
    ],
    "outputs": [
      {
        "name": "",
        "type": "uint256",
        "internalType": "uint256"
      }
    ],
    "stateMutability": "view"
  },
  {
    "name": "idExists",
    "type": "function",
    "inputs": [
      {
        "name": "id",
        "type": "uint256",
        "internalType": "uint256"
      }
    ],
    "outputs": [
      {
        "name": "",
        "type": "bool",
        "internalType": "bool"
      }
    ],
    "stateMutability": "view"
  },
  {
    "name": "initialize",
    "type": "function",
    "inputs": [
      {
        "name": "initialOwnerAddr",
        "type": "address",
        "internalType": "address"
      },
      {
        "name": "authV3VerifierAddr",
        "type": "address",
        "internalType": "address"
      },
      {
        "name": "stateTransitionVerifierAddr",
        "type": "address",
        "internalType": "address"
      },
      {
        "name": "forUEntityVerifierAddr",
        "type": "address",
        "internalType": "address"
      },
      {
        "name": "communityMembershipVerifierAddr",
        "type": "address",
        "internalType": "address"
      }
    ],
    "outputs": [],
    "stateMutability": "nonpayable"
  },
  {
    "name": "isEntityTypeSupported",
    "type": "function",
    "inputs": [
      {
        "name": "entityType",
        "type": "uint256",
        "internalType": "uint256"
      }
    ],
    "outputs": [
      {
        "name": "",
        "type": "bool",
        "internalType": "bool"
      }
    ],
    "stateMutability": "pure"
  },
  {
    "name": "joinCommunity",
    "type": "function",
    "inputs": [
      {
        "name": "data",
        "type": "tuple",
        "components": [
          {
            "name": "id",
            "type": "uint256",
            "internalType": "uint256"
          },
          {
            "name": "memberRole",
            "type": "uint256",
            "internalType": "uint256"
          },
          {
            "name": "memberEntityType",
            "type": "uint256",
            "internalType": "uint256"
          },
          {
            "name": "incrementalNonce",
            "type": "uint256",
            "internalType": "uint256"
          },
          {
            "name": "communityId",
            "type": "uint256",
            "internalType": "uint256"
          },
          {
            "name": "communityState",
            "type": "uint256",
            "internalType": "uint256"
          },
          {
            "name": "idAuthChallenge",
            "type": "uint256",
            "internalType": "uint256"
          },
          {
            "name": "membershipClaimCore",
            "type": "uint256[8]",
            "internalType": "uint256[8]"
          },
          {
            "name": "avA",
            "type": "uint256[2]",
            "internalType": "uint256[2]"
          },
          {
            "name": "avB",
            "type": "uint256[2][2]",
            "internalType": "uint256[2][2]"
          },
          {
            "name": "avC",
            "type": "uint256[2]",
            "internalType": "uint256[2]"
          },
          {
            "name": "mvA",
            "type": "uint256[2]",
            "internalType": "uint256[2]"
          },
          {
            "name": "mvB",
            "type": "uint256[2][2]",
            "internalType": "uint256[2][2]"
          },
          {
            "name": "mvC",
            "type": "uint256[2]",
            "internalType": "uint256[2]"
          }
        ],
        "internalType": "struct State.JoinCommunityData"
      }
    ],
    "outputs": [],
    "stateMutability": "nonpayable"
  },
  {
    "name": "latestDIDIncrementalNonce",
    "type": "function",
    "inputs": [
      {
        "name": "",
        "type": "uint256",
        "internalType": "uint256"
      }
    ],
    "outputs": [
      {
        "name": "",
        "type": "uint256",
        "internalType": "uint256"
      }
    ],
    "stateMutability": "view"
  },
  {
    "name": "latestMasterDIDIncrementalNonce",
    "type": "function",
    "inputs": [],
    "outputs": [
      {
        "name": "",
        "type": "uint256",
        "internalType": "uint256"
      }
    ],
    "stateMutability": "view"
  },
  {
    "name": "masterDID",
    "type": "function",
    "inputs": [],
    "outputs": [
      {
        "name": "",
        "type": "uint256",
        "internalType": "uint256"
      }
    ],
    "stateMutability": "view"
  },
  {
    "name": "membershipExists",
    "type": "function",
    "inputs": [
      {
        "name": "communityId",
        "type": "uint256",
        "internalType": "uint256"
      },
      {
        "name": "id",
        "type": "uint256",
        "internalType": "uint256"
      }
    ],
    "outputs": [
      {
        "name": "",
        "type": "bool",
        "internalType": "bool"
      }
    ],
    "stateMutability": "view"
  },
  {
    "name": "owner",
    "type": "function",
    "inputs": [],
    "outputs": [
      {
        "name": "",
        "type": "address",
        "internalType": "address"
      }
    ],
    "stateMutability": "view"
  },
  {
    "name": "pendingOwner",
    "type": "function",
    "inputs": [],
    "outputs": [
      {
        "name": "",
        "type": "address",
        "internalType": "address"
      }
    ],
    "stateMutability": "view"
  },
  {
    "name": "proxiableUUID",
    "type": "function",
    "inputs": [],
    "outputs": [
      {
        "name": "",
        "type": "bytes32",
        "internalType": "bytes32"
      }
    ],
    "stateMutability": "view"
  },
  {
    "name": "registerCommunityDID",
    "type": "function",
    "inputs": [
      {
        "name": "data",
        "type": "tuple",
        "components": [
          {
            "name": "userId",
            "type": "uint256",
            "internalType": "uint256"
          },
          {
            "name": "claimIdentity",
            "type": "uint256",
            "internalType": "uint256"
          },
          {
            "name": "entityId",
            "type": "uint256",
            "internalType": "uint256"
          },
          {
            "name": "entityType",
            "type": "uint256",
            "internalType": "uint256"
          },
          {
            "name": "issuerState",
            "type": "uint256",
            "internalType": "uint256"
          },
          {
            "name": "issuerId",
            "type": "uint256",
            "internalType": "uint256"
          },
          {
            "name": "incrementalNonce",
            "type": "uint256",
            "internalType": "uint256"
          },
          {
            "name": "oldUserState",
            "type": "uint256",
            "internalType": "uint256"
          },
          {
            "name": "newUserState",
            "type": "uint256",
            "internalType": "uint256"
          },
          {
            "name": "isOldUserStateGenesis",
            "type": "bool",
            "internalType": "bool"
          },
          {
            "name": "userAuthClaimCore",
            "type": "uint256[8]",
            "internalType": "uint256[8]"
          },
          {
            "name": "forUEntityClaimCore",
            "type": "uint256[8]",
            "internalType": "uint256[8]"
          },
          {
            "name": "fvA",
            "type": "uint256[2]",
            "internalType": "uint256[2]"
          },
          {
            "name": "fvb",
            "type": "uint256[2][2]",
            "internalType": "uint256[2][2]"
          },
          {
            "name": "fvc",
            "type": "uint256[2]",
            "internalType": "uint256[2]"
          },
          {
            "name": "stvA",
            "type": "uint256[2]",
            "internalType": "uint256[2]"
          },
          {
            "name": "stvB",
            "type": "uint256[2][2]",
            "internalType": "uint256[2][2]"
          },
          {
            "name": "stvC",
            "type": "uint256[2]",
            "internalType": "uint256[2]"
          }
        ],
        "internalType": "struct State.DIDRegistrationData"
      },
      {
        "name": "joinData",
        "type": "tuple",
        "components": [
          {
            "name": "id",
            "type": "uint256",
            "internalType": "uint256"
          },
          {
            "name": "memberRole",
            "type": "uint256",
            "internalType": "uint256"
          },
          {
            "name": "memberEntityType",
            "type": "uint256",
            "internalType": "uint256"
          },
          {
            "name": "incrementalNonce",
            "type": "uint256",
            "internalType": "uint256"
          },
          {
            "name": "communityId",
            "type": "uint256",
            "internalType": "uint256"
          },
          {
            "name": "communityState",
            "type": "uint256",
            "internalType": "uint256"
          },
          {
            "name": "idAuthChallenge",
            "type": "uint256",
            "internalType": "uint256"
          },
          {
            "name": "membershipClaimCore",
            "type": "uint256[8]",
            "internalType": "uint256[8]"
          },
          {
            "name": "avA",
            "type": "uint256[2]",
            "internalType": "uint256[2]"
          },
          {
            "name": "avB",
            "type": "uint256[2][2]",
            "internalType": "uint256[2][2]"
          },
          {
            "name": "avC",
            "type": "uint256[2]",
            "internalType": "uint256[2]"
          },
          {
            "name": "mvA",
            "type": "uint256[2]",
            "internalType": "uint256[2]"
          },
          {
            "name": "mvB",
            "type": "uint256[2][2]",
            "internalType": "uint256[2][2]"
          },
          {
            "name": "mvC",
            "type": "uint256[2]",
            "internalType": "uint256[2]"
          }
        ],
        "internalType": "struct State.JoinCommunityData"
      }
    ],
    "outputs": [],
    "stateMutability": "nonpayable"
  },
  {
    "name": "registerDID",
    "type": "function",
    "inputs": [
      {
        "name": "data",
        "type": "tuple",
        "components": [
          {
            "name": "userId",
            "type": "uint256",
            "internalType": "uint256"
          },
          {
            "name": "claimIdentity",
            "type": "uint256",
            "internalType": "uint256"
          },
          {
            "name": "entityId",
            "type": "uint256",
            "internalType": "uint256"
          },
          {
            "name": "entityType",
            "type": "uint256",
            "internalType": "uint256"
          },
          {
            "name": "issuerState",
            "type": "uint256",
            "internalType": "uint256"
          },
          {
            "name": "issuerId",
            "type": "uint256",
            "internalType": "uint256"
          },
          {
            "name": "incrementalNonce",
            "type": "uint256",
            "internalType": "uint256"
          },
          {
            "name": "oldUserState",
            "type": "uint256",
            "internalType": "uint256"
          },
          {
            "name": "newUserState",
            "type": "uint256",
            "internalType": "uint256"
          },
          {
            "name": "isOldUserStateGenesis",
            "type": "bool",
            "internalType": "bool"
          },
          {
            "name": "userAuthClaimCore",
            "type": "uint256[8]",
            "internalType": "uint256[8]"
          },
          {
            "name": "forUEntityClaimCore",
            "type": "uint256[8]",
            "internalType": "uint256[8]"
          },
          {
            "name": "fvA",
            "type": "uint256[2]",
            "internalType": "uint256[2]"
          },
          {
            "name": "fvb",
            "type": "uint256[2][2]",
            "internalType": "uint256[2][2]"
          },
          {
            "name": "fvc",
            "type": "uint256[2]",
            "internalType": "uint256[2]"
          },
          {
            "name": "stvA",
            "type": "uint256[2]",
            "internalType": "uint256[2]"
          },
          {
            "name": "stvB",
            "type": "uint256[2][2]",
            "internalType": "uint256[2][2]"
          },
          {
            "name": "stvC",
            "type": "uint256[2]",
            "internalType": "uint256[2]"
          }
        ],
        "internalType": "struct State.DIDRegistrationData"
      }
    ],
    "outputs": [],
    "stateMutability": "nonpayable"
  },
  {
    "name": "registerMasterDID",
    "type": "function",
    "inputs": [
      {
        "name": "id",
        "type": "uint256",
        "internalType": "uint256"
      },
      {
        "name": "oldState",
        "type": "uint256",
        "internalType": "uint256"
      },
      {
        "name": "newState",
        "type": "uint256",
        "internalType": "uint256"
      },
      {
        "name": "isOldStateGenesis",
        "type": "bool",
        "internalType": "bool"
      },
      {
        "name": "authClaimCore",
        "type": "uint256[8]",
        "internalType": "uint256[8]"
      },
      {
        "name": "a",
        "type": "uint256[2]",
        "internalType": "uint256[2]"
      },
      {
        "name": "b",
        "type": "uint256[2][2]",
        "internalType": "uint256[2][2]"
      },
      {
        "name": "c",
        "type": "uint256[2]",
        "internalType": "uint256[2]"
      }
    ],
    "outputs": [],
    "stateMutability": "nonpayable"
  },
  {
    "name": "renounceOwnership",
    "type": "function",
    "inputs": [],
    "outputs": [],
    "stateMutability": "nonpayable"
  },
  {
    "name": "setAuthV3Verifier",
    "type": "function",
    "inputs": [
      {
        "name": "authV3VerifierAddr",
        "type": "address",
        "internalType": "address"
      }
    ],
    "outputs": [],
    "stateMutability": "nonpayable"
  },
  {
    "name": "setCommunityMembershipVerifier",
    "type": "function",
    "inputs": [
      {
        "name": "communityMembershipVerifierAddr",
        "type": "address",
        "internalType": "address"
      }
    ],
    "outputs": [],
    "stateMutability": "nonpayable"
  },
  {
    "name": "setForUEntityVerifier",
    "type": "function",
    "inputs": [
      {
        "name": "forUEntityVerifierAddr",
        "type": "address",
        "internalType": "address"
      }
    ],
    "outputs": [],
    "stateMutability": "nonpayable"
  },
  {
    "name": "setStateTransitionVerifier",
    "type": "function",
    "inputs": [
      {
        "name": "stateTransitionVerifierAddr",
        "type": "address",
        "internalType": "address"
      }
    ],
    "outputs": [],
    "stateMutability": "nonpayable"
  },
  {
    "name": "stateExists",
    "type": "function",
    "inputs": [
      {
        "name": "id",
        "type": "uint256",
        "internalType": "uint256"
      },
      {
        "name": "state",
        "type": "uint256",
        "internalType": "uint256"
      }
    ],
    "outputs": [
      {
        "name": "",
        "type": "bool",
        "internalType": "bool"
      }
    ],
    "stateMutability": "view"
  },
  {
    "name": "totalRegisteredDID",
    "type": "function",
    "inputs": [],
    "outputs": [
      {
        "name": "",
        "type": "uint256",
        "internalType": "uint256"
      }
    ],
    "stateMutability": "view"
  },
  {
    "name": "transferOwnership",
    "type": "function",
    "inputs": [
      {
        "name": "newOwner",
        "type": "address",
        "internalType": "address"
      }
    ],
    "outputs": [],
    "stateMutability": "nonpayable"
  },
  {
    "name": "transitState",
    "type": "function",
    "inputs": [
      {
        "name": "id",
        "type": "uint256",
        "internalType": "uint256"
      },
      {
        "name": "oldState",
        "type": "uint256",
        "internalType": "uint256"
      },
      {
        "name": "newState",
        "type": "uint256",
        "internalType": "uint256"
      },
      {
        "name": "isOldStateGenesis",
        "type": "bool",
        "internalType": "bool"
      },
      {
        "name": "a",
        "type": "uint256[2]",
        "internalType": "uint256[2]"
      },
      {
        "name": "b",
        "type": "uint256[2][2]",
        "internalType": "uint256[2][2]"
      },
      {
        "name": "c",
        "type": "uint256[2]",
        "internalType": "uint256[2]"
      }
    ],
    "outputs": [],
    "stateMutability": "nonpayable"
  },
  {
    "name": "upgradeToAndCall",
    "type": "function",
    "inputs": [
      {
        "name": "newImplementation",
        "type": "address",
        "internalType": "address"
      },
      {
        "name": "data",
        "type": "bytes",
        "internalType": "bytes"
      }
    ],
    "outputs": [],
    "stateMutability": "payable"
  },
  {
    "name": "verifyAuthV3Proof",
    "type": "function",
    "inputs": [
      {
        "name": "id",
        "type": "uint256",
        "internalType": "uint256"
      },
      {
        "name": "challenge",
        "type": "uint256",
        "internalType": "uint256"
      },
      {
        "name": "pa",
        "type": "uint256[2]",
        "internalType": "uint256[2]"
      },
      {
        "name": "pb",
        "type": "uint256[2][2]",
        "internalType": "uint256[2][2]"
      },
      {
        "name": "pc",
        "type": "uint256[2]",
        "internalType": "uint256[2]"
      }
    ],
    "outputs": [
      {
        "name": "",
        "type": "bool",
        "internalType": "bool"
      }
    ],
    "stateMutability": "view"
  },
  {
    "name": "verifyCommunityMembershipProof",
    "type": "function",
    "inputs": [
      {
        "name": "communityId",
        "type": "uint256",
        "internalType": "uint256"
      },
      {
        "name": "id",
        "type": "uint256",
        "internalType": "uint256"
      },
      {
        "name": "memberRole",
        "type": "uint256",
        "internalType": "uint256"
      },
      {
        "name": "memberEntityType",
        "type": "uint256",
        "internalType": "uint256"
      },
      {
        "name": "incrementalNonce",
        "type": "uint256",
        "internalType": "uint256"
      },
      {
        "name": "communityState",
        "type": "uint256",
        "internalType": "uint256"
      },
      {
        "name": "pa",
        "type": "uint256[2]",
        "internalType": "uint256[2]"
      },
      {
        "name": "pb",
        "type": "uint256[2][2]",
        "internalType": "uint256[2][2]"
      },
      {
        "name": "pc",
        "type": "uint256[2]",
        "internalType": "uint256[2]"
      }
    ],
    "outputs": [
      {
        "name": "",
        "type": "bool",
        "internalType": "bool"
      }
    ],
    "stateMutability": "view"
  }
]

Send feedback

Agents: POST the same to /api/feedback.