Skip to main content

Overview

Trust gating enables you to build applications that control access to features, content, or services based on user trust scores, attestations, and reputation. This guide shows you how to implement comprehensive trust-gating systems in your applications.
Trust gating is like a VIP system for Web3. Instead of just checking if someone has enough tokens, you verify their reputation, experience, and trustworthiness before granting access.

What is Trust Gating?

Trust gating is a security pattern that uses reputation and attestation data to control access to application features. It enables:
  • Reputation-based access control - Grant access based on trust scores
  • Attestation verification - Require specific credentials or achievements
  • Risk-based decisions - Adjust access levels based on user risk profiles
  • Progressive access - Gradually unlock features as users build reputation
  • Fraud prevention - Block malicious actors based on behavior patterns

Trust Gating Patterns

1. Score-Based Gating

Control access based on trust score thresholds:
import { ZKScoreClient } from '@zkscore/sdk';

const client = new ZKScoreClient({
  apiKey: 'your_api_key_here',
  environment: 'mainnet'
});

// Basic score-based trust gate
async function checkScoreGate(userAddress, minScore = 500) {
  try {
    const score = await client.getScore(userAddress);
    
    if (score.total >= minScore) {
      return { 
        allowed: true, 
        score: score.total,
        tier: getTrustTier(score.total)
      };
    } else {
      return { 
        allowed: false, 
        score: score.total,
        required: minScore,
        message: `Minimum trust score of ${minScore} required`,
        suggestions: getScoreImprovementSuggestions(score)
      };
    }
  } catch (error) {
    console.error('Score gate check failed:', error);
    return { allowed: false, error: error.message };
  }
}

function getTrustTier(score) {
  if (score >= 1200) return 'platinum';
  if (score >= 800) return 'gold';
  if (score >= 400) return 'silver';
  if (score >= 100) return 'bronze';
  return 'none';
}

function getScoreImprovementSuggestions(score) {
  const suggestions = [];
  
  if (score.breakdown.defi < 100) {
    suggestions.push('Try DeFi protocols like Uniswap or Aave');
  }
  if (score.breakdown.nft < 50) {
    suggestions.push('Explore NFT marketplaces');
  }
  if (score.breakdown.governance < 75) {
    suggestions.push('Participate in DAO governance');
  }
  
  return suggestions;
}

2. Attestation-Based Gating

Require specific attestations for access:
// Attestation-based trust gate
async function checkAttestationGate(userAddress, requiredSchemas) {
  try {
    const attestations = await client.getAttestations(userAddress);
    const userSchemas = new Set(attestations.map(a => a.schema));
    
    const missingSchemas = requiredSchemas.filter(
      schema => !userSchemas.has(schema)
    );
    
    if (missingSchemas.length === 0) {
      return { 
        allowed: true, 
        attestations: attestations.length,
        schemas: Array.from(userSchemas)
      };
    } else {
      return { 
        allowed: false, 
        missing_schemas: missingSchemas,
        message: `Required attestations: ${missingSchemas.join(', ')}`,
        suggestions: getAttestationSuggestions(missingSchemas)
      };
    }
  } catch (error) {
    console.error('Attestation gate check failed:', error);
    return { allowed: false, error: error.message };
  }
}

function getAttestationSuggestions(missingSchemas) {
  const suggestions = {};
  
  missingSchemas.forEach(schema => {
    switch (schema) {
      case 'kyc_verification_v1':
        suggestions[schema] = 'Complete KYC verification with a trusted provider';
        break;
      case 'defi_experience_v1':
        suggestions[schema] = 'Use DeFi protocols to build experience';
        break;
      case 'nft_collector_v1':
        suggestions[schema] = 'Start collecting NFTs to build reputation';
        break;
      default:
        suggestions[schema] = `Obtain ${schema} attestation`;
    }
  });
  
  return suggestions;
}

3. Policy-Based Gating

Use complex policies for sophisticated access control:
// Policy-based trust gate
async function checkPolicyGate(userAddress, policyId, context = {}) {
  try {
    const result = await client.evaluatePolicy({
      policyId,
      subject: userAddress,
      context
    });
    
    return {
      allowed: result.passed,
      decision: result.decision,
      metadata: result.metadata,
      reasons: result.reasons,
      suggestions: result.suggestions
    };
  } catch (error) {
    console.error('Policy gate check failed:', error);
    return { allowed: false, error: error.message };
  }
}

4. Composite Gating

Combine multiple gating mechanisms:
// Composite trust gate with multiple conditions
async function checkCompositeGate(userAddress, requirements) {
  const results = {};
  
  // Check score requirement
  if (requirements.minScore) {
    results.score = await checkScoreGate(userAddress, requirements.minScore);
  }
  
  // Check attestation requirements
  if (requirements.attestations) {
    results.attestations = await checkAttestationGate(userAddress, requirements.attestations);
  }
  
  // Check policy requirements
  if (requirements.policies) {
    results.policies = {};
    for (const [policyId, context] of Object.entries(requirements.policies)) {
      results.policies[policyId] = await checkPolicyGate(userAddress, policyId, context);
    }
  }
  
  // Determine overall access
  const allPassed = Object.values(results).every(result => 
    typeof result === 'object' && result.allowed
  );
  
  return {
    allowed: allPassed,
    results,
    summary: generateAccessSummary(results)
  };
}

function generateAccessSummary(results) {
  const summary = {
    passed_checks: [],
    failed_checks: [],
    overall_tier: 'none'
  };
  
  Object.entries(results).forEach(([type, result]) => {
    if (result.allowed) {
      summary.passed_checks.push(type);
    } else {
      summary.failed_checks.push({
        type,
        reason: result.message || result.error
      });
    }
  });
  
  // Calculate suggestions from all failed checks
  summary.suggestions = [];
  Object.values(results).forEach(result => {
    if (!result.allowed && result.suggestions) {
      if (Array.isArray(result.suggestions)) {
        summary.suggestions.push(...result.suggestions);
      } else if (typeof result.suggestions === 'object') {
        summary.suggestions.push(...Object.values(result.suggestions));
      }
    }
  });
  
  // Determine overall tier based on passed checks
  if (summary.passed_checks.includes('score') && results.score.tier) {
    summary.overall_tier = results.score.tier;
  }
  
  return summary;
}

Building a Trust-Gated Application

Let’s build a complete trust-gated DeFi lending application:

1. Application Setup

// app.js - Express.js application with trust gating
const express = require('express');
const { ZKScoreClient } = require('@zkscore/sdk');

const app = express();
app.use(express.json());

const zkscoreClient = new ZKScoreClient({
  apiKey: process.env.ZKSCORE_API_KEY,
  environment: 'mainnet'
});

// Mock user authentication middleware
app.use((req, res, next) => {
  // In real app, this would verify JWT or session
  req.user = { address: '0x742d35Cc6634C0532925a3b8D2Ac8e4C8d4e4f4f' };
  next();
});

2. Trust Gate Middleware

// trust-gate-middleware.js
function createTrustGate(options = {}) {
  return async (req, res, next) => {
    try {
      const userAddress = req.user.address;
      
      // Default requirements
      const requirements = {
        minScore: options.minScore || 500,
        attestations: options.attestations || [],
        policies: options.policies || {},
        ...options.requirements
      };
      
      // Check trust requirements
      const gateResult = await checkCompositeGate(userAddress, requirements);
      
      if (gateResult.allowed) {
        // Add trust data to request
        req.trustData = {
          score: gateResult.results.score?.score,
          tier: gateResult.results.score?.tier,
          attestations: gateResult.results.attestations?.attestations,
          metadata: gateResult.results.policies ? 
            Object.values(gateResult.results.policies)[0]?.metadata : {}
        };
        next();
      } else {
        res.status(403).json({
          error: 'Trust gate failed',
          summary: gateResult.summary,
          suggestions: gateResult.summary.suggestions
        });
      }
    } catch (error) {
      console.error('Trust gate middleware error:', error);
      res.status(500).json({ error: 'Trust verification failed' });
    }
  };
}

3. Protected Routes

// Lending routes with different trust requirements

// Basic lending - requires minimum score
app.get('/api/lending/basic', 
  createTrustGate({ minScore: 300 }),
  async (req, res) => {
    const { score, tier } = req.trustData;
    
    res.json({
      available_products: [
        {
          name: 'Basic Personal Loan',
          max_amount: 10000,
          interest_rate: 0.12,
          term: '12 months'
        }
      ],
      user_tier: tier,
      trust_score: score
    });
  }
);

// Premium lending - requires DeFi experience
app.get('/api/lending/premium',
  createTrustGate({ 
    minScore: 600,
    attestations: ['defi_experience_v1'],
    policies: {
      'defi_access_policy_v1': { requested_amount: 50000 }
    }
  }),
  async (req, res) => {
    const { score, tier, metadata } = req.trustData;
    
    res.json({
      available_products: [
        {
          name: 'Premium DeFi Loan',
          max_amount: metadata.max_amount || 100000,
          interest_rate: metadata.interest_rate || 0.08,
          term: '24 months',
          features: ['collateral_free', 'instant_approval']
        }
      ],
      user_tier: tier,
      trust_score: score,
      access_level: metadata.access_level
    });
  }
);

// Institutional lending - requires high trust and KYC
app.get('/api/lending/institutional',
  createTrustGate({
    minScore: 1000,
    attestations: ['kyc_verification_v1', 'defi_experience_v1'],
    policies: {
      'institutional_access_policy_v1': { 
        requested_amount: 1000000,
        loan_type: 'institutional'
      }
    }
  }),
  async (req, res) => {
    const { score, tier, metadata } = req.trustData;
    
    res.json({
      available_products: [
        {
          name: 'Institutional Credit Line',
          max_amount: metadata.max_amount || 5000000,
          interest_rate: metadata.interest_rate || 0.05,
          term: '36 months',
          features: [
            'collateral_free',
            'instant_approval',
            'priority_support',
            'custom_terms'
          ]
        }
      ],
      user_tier: tier,
      trust_score: score,
      access_level: metadata.access_level
    });
  }
);

4. Dynamic Access Control

// Dynamic access based on real-time trust data
app.post('/api/lending/calculate-terms',
  createTrustGate({ minScore: 400 }),
  async (req, res) => {
    try {
      const { requested_amount, loan_type } = req.body;
      const { score, tier } = req.trustData;
      
      // Calculate dynamic terms based on trust
      const terms = await calculateLoanTerms(req.user.address, {
        requested_amount,
        loan_type,
        trust_score: score,
        tier
      });
      
      res.json({
        approved: terms.approved,
        amount: terms.amount,
        interest_rate: terms.interest_rate,
        term_months: terms.term_months,
        collateral_required: terms.collateral_required,
        features: terms.features,
        trust_benefits: terms.trust_benefits
      });
    } catch (error) {
      res.status(500).json({ error: 'Failed to calculate terms' });
    }
  }
);

async function calculateLoanTerms(userAddress, params) {
  const { requested_amount, loan_type, trust_score, tier } = params;
  
  // Base terms
  let baseRate = 0.15;
  let maxAmount = 25000;
  let termMonths = 12;
  let collateralRequired = true;
  const features = [];
  const trustBenefits = [];
  
  // Adjust based on trust score
  if (trust_score >= 1000) {
    baseRate = 0.06;
    maxAmount = 500000;
    termMonths = 36;
    collateralRequired = false;
    features.push('no_collateral', 'instant_approval', 'priority_support');
    trustBenefits.push('20% rate discount', '5x higher limits');
  } else if (trust_score >= 700) {
    baseRate = 0.09;
    maxAmount = 150000;
    termMonths = 24;
    collateralRequired = false;
    features.push('no_collateral', 'fast_approval');
    trustBenefits.push('15% rate discount', '3x higher limits');
  } else if (trust_score >= 500) {
    baseRate = 0.12;
    maxAmount = 75000;
    termMonths = 18;
    collateralRequired = false;
    features.push('reduced_collateral');
    trustBenefits.push('10% rate discount', '2x higher limits');
  }
  
  // Adjust based on tier
  switch (tier) {
    case 'platinum':
      baseRate *= 0.8;
      maxAmount *= 2;
      features.push('platinum_support');
      break;
    case 'gold':
      baseRate *= 0.9;
      maxAmount *= 1.5;
      features.push('priority_support');
      break;
    case 'silver':
      baseRate *= 0.95;
      maxAmount *= 1.2;
      break;
  }
  
  const approved = requested_amount <= maxAmount;
  const amount = approved ? requested_amount : maxAmount;
  
  return {
    approved,
    amount,
    interest_rate: baseRate,
    term_months: termMonths,
    collateral_required: collateralRequired,
    features,
    trust_benefits
  };
}

5. Frontend Integration

// React components for trust-gated UI
import React, { useState, useEffect } from 'react';
import { useZKScore } from '@zkscore/react-sdk';

// Trust gate wrapper component
function TrustGate({ requirements, children, fallback }) {
  const { client } = useZKScore();
  const [access, setAccess] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);
  
  useEffect(() => {
    const checkAccess = async () => {
      try {
        setLoading(true);
        const result = await checkCompositeGate(
          await client.getCurrentUser(),
          requirements
        );
        setAccess(result);
      } catch (err) {
        setError(err.message);
      } finally {
        setLoading(false);
      }
    };
    
    checkAccess();
  }, [client, requirements]);
  
  if (loading) {
    return <div className="trust-gate-loading">Verifying access...</div>;
  }
  
  if (error) {
    return <div className="trust-gate-error">Error: {error}</div>;
  }
  
  if (!access.allowed) {
    return fallback ? fallback(access) : <TrustGateFailed access={access} />;
  }
  
  return children;
}

// Trust gate failed component
function TrustGateFailed({ access }) {
  return (
    <div className="trust-gate-failed">
      <div className="access-denied">
        <h3>🚫 Access Denied</h3>
        <p>You don't meet the trust requirements for this feature.</p>
        
        <div className="requirements">
          <h4>Requirements:</h4>
          <ul>
            {access.summary.failed_checks.map((check, i) => (
              <li key={i}>
                <strong>{check.type}:</strong> {check.reason}
              </li>
            ))}
          </ul>
        </div>
        
        <div className="suggestions">
          <h4>How to improve:</h4>
          <ul>
            {access.summary.suggestions.map((suggestion, i) => (
              <li key={i}>{suggestion}</li>
            ))}
          </ul>
        </div>
        
        <div className="actions">
          <button onClick={() => window.location.href = '/build-trust'}>
            Build Your Trust Score
          </button>
          <button onClick={() => window.location.href = '/attestations'}>
            Get Attestations
          </button>
        </div>
      </div>
    </div>
  );
}

// Usage in application
function LendingApplication() {
  return (
    <div className="lending-app">
      <h1>DeFi Lending Platform</h1>
      
      {/* Basic lending - accessible to most users */}
      <section>
        <h2>Basic Lending</h2>
        <TrustGate 
          requirements={{ minScore: 300 }}
          fallback={(access) => (
            <div>
              <p>Basic lending requires a trust score of 300+</p>
              <p>Your current score: {access.results.score?.score || 0}</p>
            </div>
          )}
        >
          <BasicLendingProducts />
        </TrustGate>
      </section>
      
      {/* Premium lending - requires DeFi experience */}
      <section>
        <h2>Premium Lending</h2>
        <TrustGate 
          requirements={{ 
            minScore: 600,
            attestations: ['defi_experience_v1']
          }}
        >
          <PremiumLendingProducts />
        </TrustGate>
      </section>
      
      {/* Institutional lending - high trust requirements */}
      <section>
        <h2>Institutional Lending</h2>
        <TrustGate 
          requirements={{
            minScore: 1000,
            attestations: ['kyc_verification_v1', 'defi_experience_v1']
          }}
        >
          <InstitutionalLendingProducts />
        </TrustGate>
      </section>
    </div>
  );
}

6. Real-time Trust Updates

// Real-time trust monitoring
class TrustMonitor {
  constructor(client, userAddress) {
    this.client = client;
    this.userAddress = userAddress;
    this.listeners = [];
    this.lastScore = null;
  }
  
  async start() {
    // Initial check
    await this.checkTrust();
    
    // Poll for updates every 30 seconds
    this.interval = setInterval(() => {
      this.checkTrust();
    }, 30000);
  }
  
  stop() {
    if (this.interval) {
      clearInterval(this.interval);
    }
  }
  
  async checkTrust() {
    try {
      const score = await this.client.getScore(this.userAddress);
      
      // Check if score changed significantly
      if (this.lastScore && Math.abs(score.total - this.lastScore.total) > 50) {
        this.notifyListeners({
          type: 'score_change',
          oldScore: this.lastScore.total,
          newScore: score.total,
          change: score.total - this.lastScore.total
        });
      }
      
      this.lastScore = score;
    } catch (error) {
      console.error('Trust monitoring error:', error);
    }
  }
  
  addListener(listener) {
    this.listeners.push(listener);
  }
  
  removeListener(listener) {
    this.listeners = this.listeners.filter(l => l !== listener);
  }
  
  notifyListeners(event) {
    this.listeners.forEach(listener => {
      try {
        listener(event);
      } catch (error) {
        console.error('Trust listener error:', error);
      }
    });
  }
}

// Usage in React component
function TrustAwareComponent() {
  const { client } = useZKScore();
  const [trustEvents, setTrustEvents] = useState([]);
  
  useEffect(() => {
    const monitor = new TrustMonitor(client, userAddress);
    
    monitor.addListener((event) => {
      setTrustEvents(prev => [...prev, event]);
      
      // Show notification for score improvements
      if (event.type === 'score_change' && event.change > 0) {
        showNotification(`Trust score improved by ${event.change} points!`);
      }
    });
    
    monitor.start();
    
    return () => monitor.stop();
  }, [client, userAddress]);
  
  return (
    <div>
      <h3>Trust Events</h3>
      <ul>
        {trustEvents.map((event, i) => (
          <li key={i}>
            {event.type}: {event.change > 0 ? '+' : ''}{event.change}
          </li>
        ))}
      </ul>
    </div>
  );
}

Advanced Trust Gating Patterns

1. Progressive Unlocking

// Progressive feature unlocking based on trust milestones
class ProgressiveUnlock {
  constructor(client) {
    this.client = client;
    this.milestones = [
      { score: 100, features: ['basic_trading'] },
      { score: 300, features: ['lending', 'borrowing'] },
      { score: 500, features: ['margin_trading', 'futures'] },
      { score: 700, features: ['institutional_products'] },
      { score: 1000, features: ['whitelist_access', 'beta_features'] }
    ];
  }
  
  async getUnlockedFeatures(userAddress) {
    const score = await this.client.getScore(userAddress);
    const unlockedFeatures = [];
    
    this.milestones.forEach(milestone => {
      if (score.total >= milestone.score) {
        unlockedFeatures.push(...milestone.features);
      }
    });
    
    return {
      unlocked_features: unlockedFeatures,
      current_score: score.total,
      next_milestone: this.getNextMilestone(score.total)
    };
  }
  
  getNextMilestone(currentScore) {
    return this.milestones.find(m => m.score > currentScore);
  }
}

2. Risk-Based Gating

// Risk-based access control
async function checkRiskBasedGate(userAddress, context) {
  const [score, attestations] = await Promise.all([
    client.getScore(userAddress),
    client.getAttestations(userAddress)
  ]);
  
  // Calculate risk score
  const riskScore = calculateRiskScore(score, attestations, context);
  
  // Determine access level based on risk
  if (riskScore < 0.2) {
    return { 
      allowed: true, 
      access_level: 'high',
      limits: { max_amount: 1000000, rate: 0.05 }
    };
  } else if (riskScore < 0.5) {
    return { 
      allowed: true, 
      access_level: 'medium',
      limits: { max_amount: 100000, rate: 0.08 }
    };
  } else if (riskScore < 0.8) {
    return { 
      allowed: true, 
      access_level: 'low',
      limits: { max_amount: 10000, rate: 0.12 }
    };
  } else {
    return { 
      allowed: false, 
      access_level: 'blocked',
      reason: 'High risk profile detected'
    };
  }
}

function calculateRiskScore(score, attestations, context) {
  let riskScore = 0.5; // Base risk
  
  // Adjust based on trust score
  if (score.total > 800) riskScore -= 0.3;
  else if (score.total > 500) riskScore -= 0.2;
  else if (score.total < 200) riskScore += 0.3;
  
  // Adjust based on attestations
  if (attestations.some(a => a.schema === 'kyc_verification_v1')) {
    riskScore -= 0.2;
  }
  if (attestations.some(a => a.schema === 'defi_experience_v1')) {
    riskScore -= 0.1;
  }
  
  // Adjust based on context
  if (context.requested_amount > 100000) {
    riskScore += 0.2;
  }
  if (context.is_first_time) {
    riskScore += 0.1;
  }
  
  return Math.max(0, Math.min(1, riskScore));
}

3. Time-Based Gating

// Time-based trust requirements
async function checkTimeBasedGate(userAddress, requirements) {
  const attestations = await client.getAttestations(userAddress);
  
  const timeChecks = requirements.time_requirements || {};
  const results = {};
  
  // Check recent activity requirement
  if (timeChecks.recent_activity_days) {
    const recentAttestations = attestations.filter(att => {
      const daysSinceIssued = (Date.now() - new Date(att.issued_at)) / (1000 * 60 * 60 * 24);
      return daysSinceIssued <= timeChecks.recent_activity_days;
    });
    
    results.recent_activity = recentAttestations.length > 0;
  }
  
  // Check minimum account age
  if (timeChecks.min_account_age_days) {
    const oldestAttestation = attestations.reduce((oldest, att) => {
      return new Date(att.issued_at) < new Date(oldest.issued_at) ? att : oldest;
    }, attestations[0]);
    
    const accountAge = (Date.now() - new Date(oldestAttestation.issued_at)) / (1000 * 60 * 60 * 24);
    results.account_age = accountAge >= timeChecks.min_account_age_days;
  }
  
  return {
    allowed: Object.values(results).every(Boolean),
    results
  };
}

Best Practices

1. User Experience

  • Clear requirements: Always show users what they need to access features
  • Progress indicators: Show users how close they are to unlocking features
  • Helpful suggestions: Provide actionable steps to improve trust
  • Graceful degradation: Offer alternative features when trust requirements aren’t met

2. Performance

  • Cache trust data: Cache trust scores and attestations to reduce API calls
  • Batch requests: Use batch evaluation for multiple trust checks
  • Lazy loading: Only check trust when features are accessed
  • Background updates: Update trust data in the background

3. Security

  • Server-side validation: Always validate trust on the server side
  • Rate limiting: Implement rate limiting on trust-gated endpoints
  • Audit logging: Log all trust-based access decisions
  • Regular updates: Keep trust requirements up to date

4. Monitoring

  • Trust metrics: Monitor trust score distributions and trends
  • Access patterns: Track which trust gates are most restrictive
  • User feedback: Collect feedback on trust requirements
  • A/B testing: Test different trust requirements for optimal conversion