# 8. Reputation proof

### Generate a reputation proof

See [4. Epoch key proof](https://unirep.gitbook.io/unirep/getting-started/4.-epoch-key-proof#4.-generate-current-user-state) to know how to generate a current user state.

Specify what will be included in the reputation proof:

1. Prove the minimum `posRep-negRep` that an attester gives: `minRep`
2. Prove the [reputation nullifiers](https://unirep.gitbook.io/unirep/protocol/glossary/nullifiers#reputation-nullifiers): `nonceList`
3. Prove the graffiti pre-image: `graffitiPreImage`

User should also specify the `attesterId` and `epochKeyNonce` to generate an output epoch key.

```typescript
const attesterID = await contract.attesters(attester.address)
const epkNonce = 0
const rep = userState.getRepByAttester(BigInt(attesterId))
const minRep = Number(rep.posRep) - Number(rep.negRep)
const proveGraffiti = 0 // 0 then it will not prove the pre-image
const nonceList = 0 // 0 or [-1,..,-1] with length 'maxReputationBudget' means the proof will not generate reputation nullifiers.

const proof = await userState.genProveReputationProof(
    attesterId,
    epkNonce,
    minRep,
    proveGraffiti,
    graffitiPreImage,
    nonceList
)
```

### Spend reputation

Call the spendReputation in UniRep smart contract

```typescript
const tx = await contract.spendReputation(
    proof.publicSignals,
    proof.proof,
    {
        value: attestingFee,
    }
)
```

Get the proof index

```typescript
const fromIndex = await contract.getProofIndex(
    proof.hash()
)
```

Use the reputation proof to attest others. To construct another `attestation`, `epochKey`, and `index`, see [5. Attest](https://unirep.gitbook.io/unirep/getting-started/start-with-typescript/5.-attest)

```typescript
const tx = await unirepContract
    .connect(attester)
    .submitAttestation(
        attestation, 
        epochKey, 
        index, 
        fromIndex, 
        {
            value: attestingFee,
        }
    )
```

### Verify the proof

with UniRep smart contract:

```typescript
const isValid = await contract.verifyReputation(
    proof.publicSignals,
    proof.proof
)
```

with a prover:

```typescript
const isValid = await proof.verify()
```

### Verify UniRep state

Check global state tree root exits.

```typescript
const isGSTRootExisted = await unirepState.GSTRootExists(
    proof.globalStateTree,
    proof.epoch
)
console.log(isGSTRootExisted) // false then the proof will be invalid
```

Verify reputation nullifiers.

```typescript
const repNullifiers = proof.repNullifiers.map((i) => i.toString())
for (const nullifier of repNullifiers) {
    if (await unirepState.nullifierExist(nullifier)) {
        return false // then the proof will be invalid
    }
}
```
