all files / contracts/verifierHelpers/ ReputationVerifierHelper.sol

100% Statements 17/17
85.71% Branches 12/14
100% Functions 5/5
100% Lines 36/36
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142                                          10× 10× 10× 10× 10×   10×               10×                 10×                                                   26× 26× 26× 26× 26×   26× 26×   26× 26×   26× 26×   26× 26×   26× 26×                     10×                                                          
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
 
import {Unirep} from '../Unirep.sol';
import {IVerifier} from '../interfaces/IVerifier.sol';
import {BaseVerifierHelper} from './BaseVerifierHelper.sol';
 
/// @title ReputationVerifierHelper
/// @dev https://developer.unirep.io/docs/contracts-api/verifiers/reputation-verifier-helper
contract ReputationVerifierHelper is BaseVerifierHelper {
    constructor(
        Unirep _unirep,
        IVerifier _verifier
    ) BaseVerifierHelper(_unirep, _verifier) {}
 
    /// @dev https://developer.unirep.io/docs/contracts-api/verifiers/reputation-verifier-helper#decodereputationsignals
    /// @param publicSignals The public signals of the snark proof
    /// @return signals The ReputationSignals
    function decodeReputationSignals(
        uint256[] calldata publicSignals
    ) public pure returns (ReputationSignals memory) {
        ReputationSignals memory signals;
        signals.epochKey = publicSignals[0];
        signals.stateTreeRoot = publicSignals[1];
        signals.graffiti = publicSignals[4];
        signals.data = publicSignals[5];
        // now decode the control values
        (
            signals.nonce,
            signals.epoch,
            signals.attesterId,
            signals.revealNonce,
            signals.chainId
        ) = super.decodeEpochKeyControl(publicSignals[2]);
 
        (
            signals.minRep,
            signals.maxRep,
            signals.proveMinRep,
            signals.proveMaxRep,
            signals.proveZeroRep,
            signals.proveGraffiti
        ) = decodeReputationControl(publicSignals[3]);
 
        if (signals.epochKey >= SNARK_SCALAR_FIELD) revert InvalidEpochKey();
        Iif (signals.attesterId >= type(uint160).max) revert AttesterInvalid();
 
        return signals;
    }
 
    /// @dev https://developer.unirep.io/docs/contracts-api/verifiers/reputation-verifier-helper#decodereputationcontrol
    /// @param control The encoded control field
    /// @return minRep The minimum rep information in the control field
    /// @return maxRep The maximum rep information in the control field
    /// @return proveMinRep Whether to prove minimum rep information in the control field
    /// @return proveMaxRep Whether to prove maximum rep information in the control field
    /// @return proveZeroRep Whether to prove zero rep information in the control field
    /// @return proveGraffiti Whether to prove graffiti information in the control field
    function decodeReputationControl(
        uint256 control
    )
        public
        pure
        returns (
            uint64 minRep,
            uint64 maxRep,
            bool proveMinRep,
            bool proveMaxRep,
            bool proveZeroRep,
            bool proveGraffiti
        )
    {
        uint8 repBits = 64;
        uint8 oneBit = 1;
        uint8 accBits = 0;
        minRep = uint64(shiftAndParse(control, accBits, repBits));
        accBits += repBits;
 
        maxRep = uint64(shiftAndParse(control, accBits, repBits));
        accBits += repBits;
 
        proveMinRep = bool(shiftAndParse(control, accBits, oneBit) != 0);
        accBits += oneBit;
 
        proveMaxRep = bool(shiftAndParse(control, accBits, oneBit) != 0);
        accBits += oneBit;
 
        proveZeroRep = bool(shiftAndParse(control, accBits, oneBit) != 0);
        accBits += oneBit;
 
        proveGraffiti = bool(shiftAndParse(control, accBits, oneBit) != 0);
        accBits += oneBit;
    }
 
    /// @dev https://developer.unirep.io/docs/contracts-api/verifiers/reputation-verifier-helper#verifyandcheck
    /// @param publicSignals The public signals of the snark proof
    /// @param proof The proof data of the snark proof
    /// @return signals The ReputationSignals
    function verifyAndCheck(
        uint256[] calldata publicSignals,
        uint256[8] calldata proof
    ) public view returns (ReputationSignals memory) {
        ReputationSignals memory signals = decodeReputationSignals(
            publicSignals
        );
 
        if (!verifier.verifyProof(publicSignals, proof)) revert InvalidProof();
 
        uint48 epoch = unirep.attesterCurrentEpoch(signals.attesterId);
        if (signals.epoch > epoch) revert InvalidEpoch();
 
        if (
            !unirep.attesterStateTreeRootExists(
                signals.attesterId,
                signals.epoch,
                signals.stateTreeRoot
            )
        ) revert InvalidStateTreeRoot(signals.stateTreeRoot);
 
        Iif (signals.chainId != chainid) revert ChainIdNotMatch(signals.chainId);
 
        return signals;
    }
 
    /// @dev https://developer.unirep.io/docs/contracts-api/verifiers/reputation-verifier-helper#verifyandcheckcaller
    /// @param publicSignals The public signals of the snark proof
    /// @param proof The proof data of the snark proof
    /// @return signals The ReputationSignals
    function verifyAndCheckCaller(
        uint256[] calldata publicSignals,
        uint256[8] calldata proof
    ) public view returns (ReputationSignals memory) {
        ReputationSignals memory signals = verifyAndCheck(publicSignals, proof);
 
        if (signals.attesterId != uint160(msg.sender)) {
            revert CallerInvalid();
        }
 
        return signals;
    }
}