← Inferno

Developer Integration Guide

How to integrate IFR Lock into your product — permissionless, on-chain license gating for any application.

1. Overview: How to Integrate IFR Lock Into Your Product

Any product can use IFR Lock to offer premium tiers to its users. The contract is fully permissionless — no approval, API key, or partnership is required. Your product simply queries the on-chain lock status of a wallet and gates features accordingly.

Your product decides the minimum lock amount for premium access. The user locks IFR tokens on-chain, and your application checks whether the lock meets your threshold.

Integration in 3 steps: (1) Set up a resolver that reads from the IFRLock contract, (2) query isLocked() for each user wallet, (3) gate features based on the boolean result.

2. Architecture Overview

The integration follows a simple three-layer architecture. Your application talks to a lightweight resolver (your backend), which queries the IFRLock contract on Ethereum.

Your App
Frontend / Backend
→
License Resolver
Your API server
→
IFRLock
On Ethereum

The resolver maps wallet addresses to license status. It is stateless — it queries on demand and does not persist user data. You own and operate the resolver, giving you full control over caching, rate limiting, and minimum lock thresholds.

3. Step 1: ABI Reference

You only need the read functions from the IFRLock contract. Here is the minimal ABI for integration:

Minimal ABI (read-only)
const IFR_LOCK_ABI = [
  "function isLocked(address user, uint256 minAmount) view returns (bool)",
  "function lockedBalance(address user) view returns (uint256)",
  "function lockInfo(address user) view returns (uint256 amount, uint256 lockedAt)",
  "function totalLocked() view returns (uint256)"
];
Network Contract Address
Mainnet 0x769928aBDfc949D0718d8766a1C2d7dBb63954Eb
Sepolia (testnet) 0x0Cab0A9440643128540222acC6eF5028736675d3

4. Step 2: Set Up Your Resolver

The resolver is a simple Express server that queries the IFRLock contract and returns a JSON response. Deploy this on your own infrastructure.

Node.js / Express — resolver.js
const { ethers } = require("ethers");
const express = require("express");

const LOCK_ADDRESS = "0x769928aBDfc949D0718d8766a1C2d7dBb63954Eb"; // Ethereum Mainnet
const LOCK_ABI = [
  "function isLocked(address user, uint256 minAmount) view returns (bool)",
  "function lockedBalance(address user) view returns (uint256)",
];
const MIN_LOCK = ethers.parseUnits("5000", 9); // 5000 IFR minimum

const provider = new ethers.JsonRpcProvider(process.env.RPC_URL);
const lock = new ethers.Contract(LOCK_ADDRESS, LOCK_ABI, provider);

const app = express();

app.get("/api/license/:wallet", async (req, res) => {
  try {
    const wallet = req.params.wallet;
    const isPremium = await lock.isLocked(wallet, MIN_LOCK);
    const balance = await lock.lockedBalance(wallet);
    res.json({
      wallet,
      premium: isPremium,
      lockedAmount: ethers.formatUnits(balance, 9),
      minRequired: "5000",
    });
  } catch (err) {
    res.status(500).json({ error: err.message });
  }
});

app.listen(3000);

Note: The resolver uses ethers v6 syntax. IFR uses 9 decimals (not 18), so always use parseUnits(value, 9) and formatUnits(value, 9).

5. Step 3: Gate Features in Your App

On the frontend, call your resolver endpoint and use the response to enable or disable premium features.

Frontend — feature gating
// Frontend example
async function checkPremium(walletAddress) {
  const res = await fetch(`/api/license/${walletAddress}`);
  const data = await res.json();
  if (data.premium) {
    // Enable premium features
    showPremiumUI();
  } else {
    // Show standard plan + prompt to lock IFR
    showUpgradePrompt(data.minRequired);
  }
}

The resolver returns a simple JSON object. The premium field is a boolean — true if the user has at least the minimum amount locked, false otherwise. Your frontend logic is entirely up to you.

6. Step 4: Lock/Unlock UI (Optional)

If you want to let users lock IFR directly from your application (instead of directing them to the Inferno dashboard), you can integrate the lock flow with a connected wallet such as MetaMask.

Lock flow — approve + lock
// Requires user's connected wallet (e.g., MetaMask)
const TOKEN_ADDRESS = "0x77e99917Eca8539c62F509ED1193ac36580A6e7B"; // Ethereum Mainnet
const TOKEN_ABI = ["function approve(address spender, uint256 amount) returns (bool)"];

async function lockIFR(signer, amount) {
  const token = new ethers.Contract(TOKEN_ADDRESS, TOKEN_ABI, signer);
  const lock = new ethers.Contract(LOCK_ADDRESS, LOCK_ABI_FULL, signer);

  const parsedAmount = ethers.parseUnits(amount, 9);

  // Step 1: Approve
  const approveTx = await token.approve(LOCK_ADDRESS, parsedAmount);
  await approveTx.wait();

  // Step 2: Lock
  const lockTx = await lock.lock(parsedAmount);
  await lockTx.wait();

  return true;
}

Important: The lock flow requires two transactions: (1) approve the IFRLock contract to spend tokens, then (2) call lock(). Both must be signed by the user's wallet.

7. Using lockType for Multi-App

If you want to tag locks with your application's identifier, use lockWithType(). This is useful for analytics and distinguishing which app prompted the lock.

lockType — application tagging
// Lock with your app's specific tag
const lockType = ethers.id("myapp_premium"); // bytes32 hash
await lock.lockWithType(amount, lockType);

Note: lockType is metadata only — it does not affect isLocked() queries. One user has one lock balance, shared across all apps. The tag is for your own tracking purposes.

8. Privacy Checklist

Integrating with on-chain data requires care around user privacy. Follow these guidelines:

The resolver should be stateless — query on demand, don't persist. If you need caching, use an in-memory store keyed by block, kept for at most 60 seconds, with no personal identifiers (ifr-benefits-verify/1 §5).

9. Choosing Your Minimum Lock Amount

For customer benefits (discounts, perks, access) use the shared open tiers of ifr-benefits-verify/1, so every integrator shows the same scheme. They are published as data in ifr-benefits-tiers.v1.json and implemented by the MIT-licensed reference library apps/benefits-verify. No registration and no API are involved.

Tier key Lock Amount Base units (9 decimals)
BRONZE 1,000 IFR 1000000000000
SILVER 2,500 IFR 2500000000000
GOLD 5,000 IFR 5000000000000
PLATINUM 10,000 IFR 10000000000000

Offer benefits per tier key (for example “from SILVER”), not per IFR amount: a threshold change then ships as a new tier file with a later valid_from and applies without editing your offers. A lock check is a fact about one block — repeat it when the benefit is redeemed. For a single product feature that is not a tier benefit, any threshold greater than zero in your resolver remains possible.

10. Testing on Sepolia

Before going live, test your integration on the Sepolia testnet. You will need Sepolia ETH (from a faucet) and test IFR tokens (contact the team or swap on Uniswap Sepolia).

Foundry (cast) — query lock status
# Get Sepolia ETH from a faucet
# Get test IFR tokens (contact the team or use Uniswap Sepolia)

# Query lock status directly
cast call 0x0Cab0A9440643128540222acC6eF5028736675d3 \
  "isLocked(address,uint256)(bool)" \
  YOUR_WALLET_ADDRESS \
  5000000000000  # 5000 * 1e9

Tip: The cast command is part of the Foundry toolkit. It lets you call read functions directly from the command line without writing any code. Replace YOUR_WALLET_ADDRESS with an actual Sepolia address.

Quick Reference

Resource Link / Value
IFRLock (Mainnet) 0x769928aBDfc949D0718d8766a1C2d7dBb63954Eb
InfernoToken (Mainnet) 0x77e99917Eca8539c62F509ED1193ac36580A6e7B
Token Decimals 9
Ticker IFR
Ethers.js version v6
Uniswap Router (Sepolia) 0xC532a74256D3Db42D0Bf7a0400fEFDbad7694008

11. Builder Benefits

Builders who integrate IFR Lock into their products gain access to a range of benefits designed to support growth and alignment with the Inferno ecosystem.

Live IFR Benefits app: shop.ifrunit.tech is the installable customer/seller PWA. Customers connect an external wallet, review balances and lock status, discover offers, and preferably present a private short-lived pass. Sellers manage profiles, products, discount rules and checkout operators; each rule can accept IFRLock, active TIME_ONLY CommitmentVault tranches, or the full threshold in either source without adding partial balances. Price-conditioned commitments do not qualify. Sellers may additionally require IFR to remain free in the customer wallet, bind the exact rule to that pass, and redeem an approved checkout once. The compatible seller-issued QR flow remains available. PartnerVault rewards remain governance-gated. Architecture: docs/ifrp-commerce-app/MASTER_ARCHITECTURE.md.

📖 Builder Program Docs
Read requirements & benefits
✍️ Apply as Builder
Submit registration form

Partner Rewards (planned, not active)

Partner rewards are not active: no partner is registered and no reward has been paid. Under the decided model, a pilot partner receives IFR from the PartnerVault only for verified checkout redemptions, valued in EUR, within a fixed budget. A lock alone never earns a reward. Details: reward policy.

Parameter Value Description
Trigger Verified checkout redemption Only a real, seller-confirmed purchase at a registered pilot partner counts
Valuation EUR per redemption, paid in IFR Converted at the published 7-day TWAP of the IFR/WETH pool at settlement; no fixed rate
Per-Partner Budget Hard cap per partner The partner's PartnerVault allocation; the 40M pool is never refilled
Vesting 6–12 months linear Rewards vest linearly with optional cliff — no instant dumps

How It Works

  1. Builder Registration: Governance creates a builder entry in PartnerVault with a beneficiary address, max allocation, and vesting schedule.
  2. Verified Redemptions: The Benefits backend records each seller-confirmed checkout redemption once (idempotent event id).
  3. Settlement: Per period, Governance records the exact IFR amount with recordMilestone(partnerId, milestoneId, unlockAmount), capped by the partner allocation. The contract also has recordLockReward(bytes32 partnerId, uint256 lockAmount, address wallet) (lock amount × rewardBps, one reward per wallet and partner); the project does not use it.
  4. Vested Claiming: Builders call claim(partnerId) to withdraw vested rewards. Linear vesting ensures long-term alignment.

Total Builder Pool: 40M IFR (4% of total supply), managed by the PartnerVault contract on-chain. The separate 6% Community & Grants allocation arrived as 57.9M IFR in the Community Safe; 50M funded BootstrapVaultV3 and 7.9M IFR remain as the operational reserve for community grants and ecosystem development.

PartnerVault Integration (ethers.js v6)

Query builder rewards and claim
const VAULT_ADDR = "0xc6eb7714bCb035ebc2D4d9ba7B3762ef7B9d4F7D"; // Ethereum Mainnet
const VAULT_ABI = [
  "function claimable(bytes32 partnerId) view returns (uint256)",
  "function partners(bytes32 partnerId) view returns (address beneficiary,uint256 maxAllocation,uint256 unlockedTotal,uint256 rewardAccrued,uint256 claimedTotal,uint32 vestingStart,uint32 vestingDuration,uint32 cliff,bool active,bool milestonesFinal,uint8 tier)",
  "function claim(bytes32 partnerId)",
];

const vault = new ethers.Contract(VAULT_ADDR, VAULT_ABI, provider);
const partnerId = ethers.id("example-partner");

// Check claimable amount for the bytes32 partner key
const amount = await vault.claimable(partnerId);
console.log("Claimable:", ethers.formatUnits(amount, 9), "IFR");

// Claim vested rewards (requires signer)
const vaultSigner = vault.connect(signer);
await vaultSigner.claim(partnerId);

12. Full Integration Example

Below is a complete ethers.js v6 example showing the full resolver flow — from contract setup to querying lock status, balance, and lock details for a given wallet.

Full resolver flow — ethers.js v6
const { ethers } = require("ethers");

const LOCK_ADDR = "0x769928aBDfc949D0718d8766a1C2d7dBb63954Eb"; // Ethereum Mainnet
const LOCK_ABI = [
  "function isLocked(address user, uint256 minAmount) view returns (bool)",
  "function lockedBalance(address user) view returns (uint256)",
  "function lockInfo(address user) view returns (uint256 amount, uint256 lockedAt)",
];

const provider = new ethers.JsonRpcProvider(process.env.RPC_URL);
const lock = new ethers.Contract(LOCK_ADDR, LOCK_ABI, provider);

async function checkLicense(wallet) {
  const minLock = ethers.parseUnits("5000", 9); // 5000 IFR (9 decimals)
  const premium = await lock.isLocked(wallet, minLock);
  const balance = await lock.lockedBalance(wallet);
  const [amount, lockedAt] = await lock.lockInfo(wallet);
  return {
    premium,
    lockedAmount: ethers.formatUnits(balance, 9),
    lockedSince: new Date(Number(lockedAt) * 1000).toISOString(),
  };
}

Tip: This example combines all three read functions into a single helper. In production, consider batching calls with Promise.all() or a multicall contract for better RPC efficiency.

13. Privacy & Compliance

When integrating on-chain data into your product, ensure your implementation meets privacy and compliance requirements. Use the following checklist as a guide.

Category Requirement Implementation
Data Minimization Only query boolean lock status Use isLocked() not lockedBalance()
No PII Storage Don't link wallets to identities Stateless resolver, no database
RPC Security Use private RPC endpoint Alchemy/Infura with API key
Caching Short TTL, no persistent store In-memory cache, same block only, 60 s max; re-check at redemption
Audit Trail Log access decisions, not amounts Log premium=true/false only
GDPR No personal data processed Wallet addresses are pseudonymous

14. Builder Onboarding Flow

The builder onboarding process is designed to get you integrated quickly and smoothly. Follow these steps to go from application to live integration.

  1. Application — Contact the Inferno team with your product description and user base size
  2. Technical Review — We assess integration feasibility and determine the minimum lock amount
  3. Token Allocation — Builders receive an IFR allocation for initial user onboarding
  4. Integration — Implement the resolver using the code examples above (typically 1-2 days)
  5. Testing — Verify on Sepolia testnet before going live
  6. Launch — Go live on mainnet, joint announcement, featured on the Inferno ecosystem page

Ready to integrate? The entire process from application to live integration typically takes less than a week. Most of the time is spent on your side implementing and testing the resolver.

SDK Quickstart — Full code examples for Node.js, React + wagmi v2, Python, tier system, and wallet signature verification: Integration Guide

15. Creator Gateway Integration

The Creator Gateway enables YouTube creators and content platforms to gate premium content behind an IFR Lock — as an alternative (or addition) to traditional memberships.

// Entitlement Config Example (config/entitlements.json)
{
  "premium": {
    "logic": "OR",
    "conditions": [
      { "type": "youtube_member", "tier": "any" },
      { "type": "ifr_lock", "minIFR": 5000 }
    ]
  }
}
Full Spec: Creator Gateway Spec • Creator Gateway Guide

16. Points Backend Integration

The IFR Points Backend provides off-chain points tracking and EIP-712 discount voucher issuance. Points reduce the protocol fee on swaps via FeeRouterV1.

API Endpoints

EndpointMethodDescription
/auth/siwe/noncePOSTCreate a single-use SIWE nonce
/auth/siwe/verifyPOSTVerify SIWE signature → JWT
/points/balanceGETGet wallet points balance
/points/eventPOSTRecord points event
/voucher/issuePOSTIssue EIP-712 discount voucher

SIWE Authentication Flow

  1. Frontend calls POST /auth/siwe/nonce
  2. User signs SIWE message with wallet
  3. Frontend sends signature to POST /auth/siwe/verify
  4. Backend returns JWT (24h expiry)
  5. All subsequent calls use Authorization: Bearer {jwt}

Voucher → FeeRouter Flow

  1. User accumulates points (guide completion, lock events, referrals)
  2. Frontend calls POST /voucher/issue with JWT
  3. Backend signs EIP-712 DiscountVoucher struct
  4. Frontend passes voucher to FeeRouterV1.swapWithFee()
  5. On-chain: discount applied, nonce consumed (replay-protected)
Full E2E Flow: E2E Flow Guide

17. FeeRouter Integration

FeeRouterV1 routes swaps through whitelisted adapters with an optional protocol fee, discountable via EIP-712 signed vouchers.

Key Functions

// Execute swap with protocol fee (+ optional discount voucher)
function swapWithFee(
    address adapter,                    // whitelisted swap adapter
    bytes calldata swapData,            // adapter-specific calldata
    DiscountVoucher calldata voucher,  // ignored when useVoucher=false
    bytes calldata voucherSig,          // ignored when useVoucher=false
    bool useVoucher
) external payable;

// Voucher Struct (EIP-712)
struct DiscountVoucher {
    address user;
    uint16 discountBps;
    uint32 maxUses;
    uint64 expiry;
    uint256 nonce;
}

// Off-chain voucher validation
function isVoucherValid(
    DiscountVoucher calldata voucher,
    bytes calldata voucherSig
) external view returns (bool valid, string memory reason);

Sepolia Deployment

ParameterValue
Address0x499289C8Ef49769F4FcFF3ca86D4BD7b55B49aa4
protocolFeeBps5 (0.05%)
FEE_CAP_BPS25 (0.25%) — hard cap
EIP-712 Domainname="InfernoFeeRouter", version="1", chainId=11155111

Builder Registration Process

1️⃣
APPLY
Submit GitHub Issue via builder-registry.yml template
→
2️⃣
REVIEW
Core team reviews application (48h typical)
→
3️⃣
GOVERNANCE
Governance proposal: registerBuilder() via Timelock (48h delay)
→
✅
REGISTERED
isBuilder(wallet) = true on-chain → Telegram Dev&Builder access

BuilderRegistry.sol

Status
Deployed and verified on Sepolia and Ethereum Mainnet
Owner
Governance (Timelock)
Categories
creator · integration · tooling · dao
Tests
27 / 27 passing
Key functions: registerBuilder() · removeBuilder() · isBuilder(address) · getActiveBuilders()

Builder Categories

🎨 Creator
Content creators, YouTubers, educators integrating IFR Lock for premium content access
🔌 Integration
Products and platforms using IFRLock.isLocked() for feature gating or premium tiers
🛠️ Tooling
Developer tools, SDKs, analytics, infrastructure built around the IFR ecosystem
🏛️ DAO
Governance participants, community organizations, DAO tooling contributors

Already registered as a Builder? Verify your wallet to unlock Telegram Dev&Builder topic access.

🔐 Verify Wallet →