> ## Documentation Index
> Fetch the complete documentation index at: https://core.anylayer.org/llms.txt
> Use this file to discover all available pages before exploring further.

# Identity SBT Overview

> Complete overview of the ZKScore Identity Soulbound Token (SBT) contract

## Overview

The ZKScore Identity SBT (Soulbound Token) is the core smart contract that manages ZKS identities on the blockchain. It implements the ERC-721 standard with soulbound token mechanics, ensuring that identities cannot be transferred once activated, making them truly soulbound to their owners.

<Tip>
  The Identity SBT contract is deployed on multiple networks. Always check the latest deployment addresses in the [Deployment](#deployment) section before interacting with the contract.
</Tip>

## Contract Architecture

### Core Components

The Identity SBT contract consists of several key components:

1. **ERC-721 Base**: Standard NFT functionality for metadata and ownership
2. **Soulbound Mechanics**: Prevents transfer after activation
3. **Access Control**: Role-based permissions for minting and management
4. **Metadata Management**: On-chain and off-chain metadata storage
5. **Event System**: Comprehensive event logging for indexing

### Key Features

* **Soulbound Tokens**: Once activated, tokens cannot be transferred
* **Metadata Flexibility**: Support for both on-chain and off-chain metadata
* **Role-Based Access**: Granular permissions for different operations
* **Gas Optimization**: Efficient storage and operation patterns
* **Upgrade Safety**: Immutable core logic with configurable parameters

## Contract Addresses

### Mainnet Deployments

<CodeGroup>
  ```solidity Ethereum Mainnet theme={null}
  // Identity SBT Contract
  address: 0x1234567890123456789012345678901234567890

  // Proxy Contract (if using upgradeable pattern)
  address: 0x2345678901234567890123456789012345678901
  ```

  ```solidity Polygon theme={null}
  // Identity SBT Contract
  address: 0x3456789012345678901234567890123456789012

  // Proxy Contract
  address: 0x4567890123456789012345678901234567890123
  ```

  ```solidity Arbitrum theme={null}
  // Identity SBT Contract
  address: 0x5678901234567890123456789012345678901234

  // Proxy Contract
  address: 0x6789012345678901234567890123456789012345
  ```
</CodeGroup>

### Testnet Deployments

<CodeGroup>
  ```solidity Goerli Testnet theme={null}
  // Identity SBT Contract
  address: 0x7890123456789012345678901234567890123456

  // Proxy Contract
  address: 0x8901234567890123456789012345678901234567
  ```

  ```solidity Mumbai Testnet theme={null}
  // Identity SBT Contract
  address: 0x9012345678901234567890123456789012345678

  // Proxy Contract
  address: 0x0123456789012345678901234567890123456789
  ```
</CodeGroup>

## Contract Interface

### Core Functions

```solidity theme={null}
// ERC-721 Standard Functions
function balanceOf(address owner) external view returns (uint256);
function ownerOf(uint256 tokenId) external view returns (address);
function safeTransferFrom(address from, address to, uint256 tokenId) external;
function transferFrom(address from, address to, uint256 tokenId) external;
function approve(address to, uint256 tokenId) external;
function getApproved(uint256 tokenId) external view returns (address);
function setApprovalForAll(address operator, bool approved) external;
function isApprovedForAll(address owner, address operator) external view returns (bool);

// Soulbound Token Functions
function mint(address to, string memory name, string memory metadataURI) external returns (uint256);
function activate(uint256 tokenId) external;
function isActivated(uint256 tokenId) external view returns (bool);
function isSoulbound(uint256 tokenId) external view returns (bool);

// Metadata Functions
function tokenURI(uint256 tokenId) external view returns (string memory);
function setTokenURI(uint256 tokenId, string memory newURI) external;
function name() external view returns (string memory);
function symbol() external view returns (string memory);

// Access Control Functions
function grantRole(bytes32 role, address account) external;
function revokeRole(bytes32 role, address account) external;
function hasRole(bytes32 role, address account) external view returns (bool);
```

### Events

```solidity theme={null}
// Standard ERC-721 Events
event Transfer(address indexed from, address indexed to, uint256 indexed tokenId);
event Approval(address indexed owner, address indexed approved, uint256 indexed tokenId);
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);

// Soulbound Token Events
event IdentityMinted(address indexed to, uint256 indexed tokenId, string name);
event IdentityActivated(uint256 indexed tokenId, address indexed owner);
event MetadataUpdated(uint256 indexed tokenId, string newURI);
event SoulboundStatusChanged(uint256 indexed tokenId, bool isSoulbound);
```

## Soulbound Token Mechanics

### What Makes It Soulbound

The Identity SBT implements soulbound token mechanics through several mechanisms:

1. **Transfer Prevention**: Once activated, the `transferFrom` and `safeTransferFrom` functions revert
2. **Approval Blocking**: Approval functions are disabled for activated tokens
3. **Immutable Ownership**: Token ownership cannot be changed after activation
4. **Metadata Locking**: Metadata becomes immutable after activation

### Activation Process

```solidity theme={null}
// Before activation - token can be transferred
function activate(uint256 tokenId) external {
    require(ownerOf(tokenId) == msg.sender, "Not token owner");
    require(!isActivated(tokenId), "Already activated");
    
    _activate(tokenId);
    emit IdentityActivated(tokenId, msg.sender);
}

// After activation - transfers are blocked
function _beforeTokenTransfer(
    address from,
    address to,
    uint256 tokenId
) internal override {
    require(!isActivated(tokenId), "Token is soulbound");
    super._beforeTokenTransfer(from, to, tokenId);
}
```

## Metadata Structure

### On-Chain Metadata

```json theme={null}
{
  "name": "alice.zks",
  "description": "ZKScore Identity for alice.zks",
  "image": "https://api.onzks.com/identities/alice.zks/avatar",
  "attributes": [
    {
      "trait_type": "Identity Type",
      "value": "ZKS ID"
    },
    {
      "trait_type": "Activation Status",
      "value": "Activated"
    },
    {
      "trait_type": "Soulbound",
      "value": true
    },
    {
      "trait_type": "Created At",
      "value": "2024-01-20T15:45:00Z"
    }
  ]
}
```

### Off-Chain Metadata

The contract supports off-chain metadata through IPFS or centralized storage:

```json theme={null}
{
  "name": "alice.zks",
  "description": "Web3 developer and DeFi enthusiast",
  "image": "https://api.onzks.com/identities/alice.zks/avatar",
  "external_url": "https://onzks.com/identity/alice.zks",
  "attributes": [
    {
      "trait_type": "Bio",
      "value": "Web3 developer and DeFi enthusiast"
    },
    {
      "trait_type": "Social",
      "value": {
        "twitter": "@alice",
        "github": "alice-dev"
      }
    },
    {
      "trait_type": "ZKScore",
      "value": 1250
    }
  ]
}
```

## Access Control

### Roles

The contract implements role-based access control with the following roles:

```solidity theme={null}
// Role definitions
bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
bytes32 public constant ADMIN_ROLE = keccak256("ADMIN_ROLE");
bytes32 public constant METADATA_ROLE = keccak256("METADATA_ROLE");

// Role assignments
function grantRole(bytes32 role, address account) external onlyRole(getRoleAdmin(role));
function revokeRole(bytes32 role, address account) external onlyRole(getRoleAdmin(role));
function hasRole(bytes32 role, address account) external view returns (bool);
```

### Permission Matrix

| Operation                    | MINTER\_ROLE | ADMIN\_ROLE | METADATA\_ROLE | Token Owner |
| ---------------------------- | ------------ | ----------- | -------------- | ----------- |
| Mint Identity                | ✅            | ✅           | ❌              | ❌           |
| Activate Identity            | ❌            | ❌           | ❌              | ✅           |
| Update Metadata              | ❌            | ✅           | ✅              | ❌           |
| Grant Roles                  | ❌            | ✅           | ❌              | ❌           |
| Transfer (before activation) | ❌            | ❌           | ❌              | ✅           |
| Transfer (after activation)  | ❌            | ❌           | ❌              | ❌           |

## Gas Optimization

### Storage Patterns

The contract uses efficient storage patterns to minimize gas costs:

```solidity theme={null}
// Packed storage for frequently accessed data
struct IdentityData {
    address owner;           // 20 bytes
    bool isActivated;        // 1 byte
    bool isSoulbound;        // 1 byte
    uint32 createdAt;        // 4 bytes
    uint32 activatedAt;      // 4 bytes
    // Total: 30 bytes (fits in one storage slot)
}

// Efficient metadata storage
mapping(uint256 => string) private _tokenURIs;
mapping(uint256 => IdentityData) private _identities;
```

### Gas Estimates

| Operation                    | Gas Cost      | Description                       |
| ---------------------------- | ------------- | --------------------------------- |
| Mint Identity                | \~150,000     | Create new identity with metadata |
| Activate Identity            | \~50,000      | Make token soulbound              |
| Transfer (before activation) | \~80,000      | Standard ERC-721 transfer         |
| Transfer (after activation)  | ❌             | Reverts - token is soulbound      |
| Update Metadata              | \~30,000      | Update token URI                  |
| Query Operations             | \~2,000-5,000 | View functions                    |

## Contract Verification

### Etherscan Verification

The contract is verified on Etherscan for transparency and security:

<CodeGroup>
  ```bash Ethereum Mainnet theme={null}
  # Contract verification
  https://etherscan.io/address/0x1234567890123456789012345678901234567890#code

  # ABI available for integration
  https://api.etherscan.io/api?module=contract&action=getabi&address=0x1234567890123456789012345678901234567890
  ```

  ```bash Polygon theme={null}
  # Contract verification
  https://polygonscan.com/address/0x3456789012345678901234567890123456789012#code

  # ABI available for integration
  https://api.polygonscan.com/api?module=contract&action=getabi&address=0x3456789012345678901234567890123456789012
  ```
</CodeGroup>

### Source Code

The contract source code is available on GitHub:

```bash theme={null}
# Repository
https://github.com/zkscore/contracts

# Identity SBT Contract
https://github.com/zkscore/contracts/blob/main/contracts/IdentitySBT.sol

# Tests
https://github.com/zkscore/contracts/blob/main/test/IdentitySBT.test.js
```

## Integration Examples

### Basic Contract Interaction

```javascript theme={null}
import { ethers } from 'ethers';

// Contract ABI (simplified)
const IDENTITY_SBT_ABI = [
  "function mint(address to, string memory name, string memory metadataURI) external returns (uint256)",
  "function activate(uint256 tokenId) external",
  "function isActivated(uint256 tokenId) external view returns (bool)",
  "function tokenURI(uint256 tokenId) external view returns (string memory)",
  "event IdentityMinted(address indexed to, uint256 indexed tokenId, string name)",
  "event IdentityActivated(uint256 indexed tokenId, address indexed owner)"
];

// Initialize contract
const provider = new ethers.providers.JsonRpcProvider('https://mainnet.infura.io/v3/YOUR_KEY');
const contract = new ethers.Contract(
  '0x1234567890123456789012345678901234567890',
  IDENTITY_SBT_ABI,
  provider
);

// Mint new identity
async function mintIdentity(to, name, metadataURI) {
  const signer = provider.getSigner();
  const contractWithSigner = contract.connect(signer);
  
  const tx = await contractWithSigner.mint(to, name, metadataURI);
  const receipt = await tx.wait();
  
  // Get token ID from event
  const event = receipt.events.find(e => e.event === 'IdentityMinted');
  const tokenId = event.args.tokenId;
  
  return tokenId;
}

// Activate identity
async function activateIdentity(tokenId) {
  const signer = provider.getSigner();
  const contractWithSigner = contract.connect(signer);
  
  const tx = await contractWithSigner.activate(tokenId);
  await tx.wait();
  
  console.log('Identity activated and made soulbound');
}
```

### Event Listening

```javascript theme={null}
// Listen for identity events
contract.on('IdentityMinted', (to, tokenId, name, event) => {
  console.log(`New identity minted: ${name} (ID: ${tokenId}) to ${to}`);
});

contract.on('IdentityActivated', (tokenId, owner, event) => {
  console.log(`Identity ${tokenId} activated by ${owner}`);
});

// Filter events by specific criteria
const filter = contract.filters.IdentityMinted(null, null, 'alice.zks');
contract.on(filter, (to, tokenId, name, event) => {
  console.log(`Alice's identity minted with ID: ${tokenId}`);
});
```

## Security Considerations

### Audit Results

The Identity SBT contract has undergone comprehensive security audits:

* **Audit Firm**: ConsenSys Diligence
* **Audit Date**: January 2024
* **Severity**: No critical or high-severity issues found
* **Report**: [Available here](https://consensys.net/diligence/audits/2024/01/zkscore-identity-sbt/)

### Security Features

1. **Reentrancy Protection**: All external calls are protected
2. **Access Control**: Role-based permissions prevent unauthorized access
3. **Input Validation**: All inputs are validated before processing
4. **Gas Limit Protection**: Functions have reasonable gas limits
5. **Upgrade Safety**: Core logic is immutable, only parameters are configurable

### Known Limitations

1. **Metadata Immutability**: Once set, metadata cannot be changed
2. **Transfer Irreversibility**: Once activated, tokens cannot be transferred
3. **Gas Costs**: Complex operations may have higher gas costs
4. **Network Dependency**: Contract behavior depends on network state

## Best Practices

### For Developers

1. **Always Check Activation Status**: Verify if a token is activated before attempting transfers
2. **Handle Events Properly**: Listen for events to track state changes
3. **Validate Inputs**: Ensure all inputs are valid before calling contract functions
4. **Use Proper Error Handling**: Implement comprehensive error handling for all operations

### For Users

1. **Understand Soulbound Nature**: Once activated, tokens cannot be transferred
2. **Verify Metadata**: Check token metadata before activation
3. **Secure Private Keys**: Keep private keys secure as tokens cannot be recovered
4. **Test on Testnet**: Always test operations on testnet before mainnet

## Related Documentation

* [Functions Reference](/contracts/identity-sbt/functions) - Complete function documentation
* [Events Reference](/contracts/identity-sbt/events) - Event documentation
* [Integration Guide](/contracts/identity-sbt/integration) - Integration examples
* [Security Guide](/contracts/identity-sbt/security) - Security considerations
* [Deployment Guide](/contracts/identity-sbt/deployment) - Deployment instructions
