Smart Contracts

Complete reference for all 13 Inferno on-chain components — 9 repository contracts, 3 v2 upgrades (LiquidityReserve, BuybackVault, BurnReserve with transferOwnership), and the Uniswap V2 liquidity pair. Includes constructor parameters, public functions, events, access control, and ethers.js usage examples.

InfernoToken

ERC-20
contracts/token/InfernoToken.sol

The core ERC-20 token of the Inferno protocol. Inherits from OpenZeppelin's ERC20, ERC20Burnable, and Ownable. Uses 9 decimals (not the standard 18) and a total supply of 1 billion IFR. Implements a fee-on-transfer mechanism: every non-exempt transfer deducts a sender burn fee, a recipient burn fee, and a pool fee. The combined fee rate is capped at 5%. Default rates are 2.0% sender burn, 0.5% recipient burn, and 1.0% pool fee (3.5% total).

Note: Mint and burn operations (transfers from/to address(0)) bypass fee logic. Addresses marked as feeExempt also bypass fees entirely.

Constructor

ParameterTypeDescription
_poolFeeReceiver address Address that receives the pool fee portion of each transfer. Cannot be address(0).

State Variables

VariableTypeDefaultDescription
senderBurnBps uint256 200 (2.0%) Basis points burned from sender on each transfer
recipientBurnBps uint256 50 (0.5%) Basis points burned from recipient portion on each transfer
poolFeeBps uint256 100 (1.0%) Basis points sent to poolFeeReceiver on each transfer
poolFeeReceiver address -- Address receiving pool fees
feeExempt mapping(address => bool) -- Addresses exempt from transfer fees

Functions

FunctionParametersReturnsAccess
decimals() -- uint8 (always 9) Public
setFeeExempt(address, bool) account, exempt -- Owner
setPoolFeeReceiver(address) receiver (non-zero) -- Owner
setFeeRates(uint256, uint256, uint256) _senderBurnBps, _recipientBurnBps, _poolFeeBps -- Owner
burn(uint256) amount -- Public
Fee cap: setFeeRates enforces senderBurnBps + recipientBurnBps + poolFeeBps <= 500 (5% maximum total fee).

Internal Functions

FunctionDescription
_update(from, to, value) Overrides ERC20._update to implement fee-on-transfer. On non-exempt transfers: calculates burnSender, burnRecipient, and poolFee; sends netAmount to recipient, poolFee to poolFeeReceiver, and burns totalBurn (sender + recipient burn) via transfer to address(0).

Events

EventParameters
FeeExemptUpdated address indexed account, bool exempt
PoolFeeReceiverUpdated address indexed receiver
FeesUpdated uint256 senderBurnBps, uint256 recipientBurnBps, uint256 poolFeeBps

ethers.js Example

JavaScript (ethers v5)
const { ethers } = require("ethers");

const TOKEN_ADDR = "0x3Bd71947F288d1dd8B21129B1bE4FF16EDd5d1F4";
const abi = [
  "function decimals() view returns (uint8)",
  "function balanceOf(address) view returns (uint256)",
  "function senderBurnBps() view returns (uint256)",
  "function recipientBurnBps() view returns (uint256)",
  "function poolFeeBps() view returns (uint256)",
  "function feeExempt(address) view returns (bool)",
  "function transfer(address to, uint256 amount) returns (bool)",
  "function setFeeExempt(address account, bool exempt)",
];

const provider = new ethers.providers.JsonRpcProvider(RPC_URL);
const token = new ethers.Contract(TOKEN_ADDR, abi, provider);

// Read fee rates
const senderBurn = await token.senderBurnBps();   // 200 = 2.0%
const recipBurn  = await token.recipientBurnBps(); // 50  = 0.5%
const poolFee   = await token.poolFeeBps();       // 100 = 1.0%

// Calculate net transfer amount (for 1000 IFR)
const amount = ethers.utils.parseUnits("1000", 9);
const totalFee = amount.mul(senderBurn.add(recipBurn).add(poolFee)).div(10000);
const netAmount = amount.sub(totalFee);
console.log("Net received:", ethers.utils.formatUnits(netAmount, 9), "IFR");

// Transfer tokens (signer required)
const signer = provider.getSigner();
const tokenWithSigner = token.connect(signer);
await tokenWithSigner.transfer(recipientAddr, amount);

LiquidityReserve

Reserve
contracts/liquidity/LiquidityReserve.sol

Holds 200M IFR as a strategic liquidity reserve with a time-lock and staged withdrawal mechanism. Tokens are locked for an initial lock period (6 months in production). After the lock expires, withdrawals are rate-limited to a maximum amount per period (e.g. 50M per quarter) to prevent supply shocks. Includes a guardian role for emergency pause/unpause.

Constructor

ParameterTypeDescription
_token address Address of the IFR token contract
_lockDuration uint256 Duration in seconds before first withdrawal is allowed
_maxWithdrawPerPeriod uint256 Maximum tokens withdrawable per period (raw units, 9 decimals)
_periodDuration uint256 Duration of each withdrawal period in seconds
_guardian address Guardian address for emergency pause/unpause

Functions

FunctionParametersReturnsAccess
withdraw(address, uint256) to, amount -- Owner
availableToWithdraw() -- uint256 Public
currentPeriod() -- uint256 Public
pendingBalance() -- uint256 Public
setMaxWithdrawPerPeriod(uint256) _max -- Owner
setGuardian(address) _guardian -- Owner
pause() -- -- Guardian
unpause() -- -- Guardian

Events

EventParameters
Withdrawn address indexed to, uint256 amount
MaxWithdrawPerPeriodUpdated uint256 newMax
GuardianUpdated address indexed newGuardian
Paused address indexed account
Unpaused address indexed account

ethers.js Example

JavaScript (ethers v5)
const RESERVE_ADDR = "0xF7E90D0d17f8232365186AA085D26eaEfAf011aF";
const abi = [
  "function lockEnd() view returns (uint256)",
  "function currentPeriod() view returns (uint256)",
  "function availableToWithdraw() view returns (uint256)",
  "function pendingBalance() view returns (uint256)",
  "function withdraw(address to, uint256 amount)",
  "function paused() view returns (bool)",
];

const reserve = new ethers.Contract(RESERVE_ADDR, abi, provider);

// Check lock status
const lockEnd = await reserve.lockEnd();
const now = Math.floor(Date.now() / 1000);
console.log("Locked:", now < lockEnd.toNumber());

// Check available withdrawal
const available = await reserve.availableToWithdraw();
console.log("Available:", ethers.utils.formatUnits(available, 9), "IFR");

// Withdraw (owner only, via governance proposal)
const amount = ethers.utils.parseUnits("10000000", 9); // 10M IFR
await reserve.connect(owner).withdraw(treasuryAddr, amount);

Vesting

Vesting
contracts/vesting/Vesting.sol

Linear vesting contract for 150M IFR team allocation. Implements a 12-month cliff followed by 36-month linear vesting. No tokens are releasable before the cliff. After the cliff, tokens vest linearly based on elapsed time. The beneficiary calls release() to claim vested tokens. A guardian can pause releases for emergency situations.

Vesting formula: vestedAmount = totalAllocation * (elapsed - cliffDuration) / (duration - cliffDuration)
Returns 0 before cliff, and totalAllocation after full duration.

Constructor

ParameterTypeDescription
_token address Address of the IFR token contract
_beneficiary address Address that can claim vested tokens
_cliffDuration uint256 Cliff period in seconds (e.g. 365 days for 12 months)
_duration uint256 Total vesting duration in seconds (must be >= cliffDuration)
_totalAllocation uint256 Total tokens to vest (raw units, 9 decimals)
_guardian address Guardian address for emergency pause/unpause

Functions

FunctionParametersReturnsAccess
release() -- -- Beneficiary
releasableAmount() -- uint256 Public
vestedAmount() -- uint256 Public
vestingSchedule() -- (uint256 _start, uint256 _cliff, uint256 _duration) Public
pause() -- -- Guardian
unpause() -- -- Guardian

Events

EventParameters
Released address indexed beneficiary, uint256 amount
Paused address indexed guardian
Unpaused address indexed guardian

Custom Errors

ErrorDescription
NotBeneficiary()Caller is not the beneficiary
NothingToRelease()No tokens available to release
OnlyGuardian()Caller is not the guardian
IsPaused()Contract is paused

ethers.js Example

JavaScript (ethers v5)
const VESTING_ADDR = "0xa710f9FE7bf42981E60BE2Fbe7D87Fb3541a3F8B";
const abi = [
  "function beneficiary() view returns (address)",
  "function vestedAmount() view returns (uint256)",
  "function releasableAmount() view returns (uint256)",
  "function released() view returns (uint256)",
  "function vestingSchedule() view returns (uint256, uint256, uint256)",
  "function release()",
];

const vesting = new ethers.Contract(VESTING_ADDR, abi, provider);

// Check vesting progress
const [start, cliff, duration] = await vesting.vestingSchedule();
const vested = await vesting.vestedAmount();
const releasable = await vesting.releasableAmount();
const released = await vesting.released();

console.log("Vested:", ethers.utils.formatUnits(vested, 9), "IFR");
console.log("Releasable:", ethers.utils.formatUnits(releasable, 9), "IFR");
console.log("Released:", ethers.utils.formatUnits(released, 9), "IFR");

// Release vested tokens (beneficiary only)
await vesting.connect(beneficiarySigner).release();

BuybackVault

Buyback
contracts/buyback/BuybackVault.sol

Accepts ETH deposits and uses them to buy IFR tokens on Uniswap V2. Purchased tokens are split 50/50 between the BurnReserve (permanent burn) and the treasury. Features a configurable activation delay (60 days in production), a cooldown between buybacks (default 1 hour), and slippage protection (default 5%) using price quotes recorded at deposit time.

Constructor

ParameterTypeDescription
_token address Address of the IFR token contract
_burnReserve address BurnReserve contract address (receives burn share)
_treasury address Treasury address (receives treasury share)
_router address Uniswap V2 Router address for swap execution
_guardian address Guardian address for emergency pause/unpause
_activationDelay uint256 Seconds before buybacks can execute (from deploy time)

State Variables

VariableTypeDefaultDescription
burnShareBps uint256 5000 (50%) Percentage of purchased IFR sent to BurnReserve
cooldown uint256 3600 (1 hour) Minimum seconds between buyback executions
slippageBps uint256 500 (5%) Maximum allowed slippage for swaps
pendingExpectedOut uint256 0 Accumulated expected output from deposits (for slippage calc)

Functions

FunctionParametersReturnsAccess
depositETH() -- (payable, sends ETH via msg.value) -- Public
executeBuyback() -- -- Owner
setParams(uint256, uint256, uint256, address, address) _burnShareBps, _cooldown, _slippageBps, _router, _treasury -- Owner
pause() -- -- Guardian
unpause() -- -- Guardian

Events

EventParameters
Deposited address indexed sender, uint256 amount
BuybackExecuted uint256 ethSpent, uint256 burnAmount, uint256 treasuryAmount
Paused address indexed account
Unpaused address indexed account
ParamsUpdated uint256 burnShareBps, uint256 cooldown, uint256 slippageBps

ethers.js Example

JavaScript (ethers v5)
const VAULT_ADDR = "0xC8ABb9039BEd24f4dBf5Cff09699877D81f0D63C";
const abi = [
  "function depositETH() payable",
  "function executeBuyback()",
  "function activationTime() view returns (uint256)",
  "function lastBuybackAt() view returns (uint256)",
  "function cooldown() view returns (uint256)",
  "function pendingExpectedOut() view returns (uint256)",
  "function paused() view returns (bool)",
];

const vault = new ethers.Contract(VAULT_ADDR, abi, provider);

// Deposit ETH for future buyback
await vault.connect(signer).depositETH({
  value: ethers.utils.parseEther("0.5"),
});

// Check if buyback is ready
const activation = await vault.activationTime();
const lastBuyback = await vault.lastBuybackAt();
const cd = await vault.cooldown();
const now = Math.floor(Date.now() / 1000);

const isActive = now >= activation.toNumber();
const cooldownPassed = now >= lastBuyback.add(cd).toNumber();
console.log("Ready:", isActive && cooldownPassed);

// Execute buyback (owner only)
await vault.connect(owner).executeBuyback();

BurnReserve

Deflationary
contracts/burnreserve/BurnReserve.sol

Permanent token burning contract with on-chain tracking. Tokens are deposited via deposit() (requires prior approval) or sent directly from BuybackVault. The owner or guardian can then call burn() or burnAll() to permanently destroy the tokens, reducing the total supply. Tracks cumulative totalBurned for transparency.

Constructor

ParameterTypeDescription
_token address Address of the IFR token contract
_guardian address Guardian address (can trigger burns alongside owner)

Functions

FunctionParametersReturnsAccess
deposit(uint256) amount -- Public
burn(uint256) amount -- Owner | Guardian
burnAll() -- -- Owner | Guardian
pendingBurn() -- uint256 Public
setGuardian(address) _guardian -- Owner

Events

EventParameters
Deposited address indexed from, uint256 amount
Burned uint256 amount, uint256 newTotalBurned
GuardianUpdated address indexed newGuardian

ethers.js Example

JavaScript (ethers v5)
const BURN_ADDR = "0x6D4582FCac792FD3880e252fC0a585A0c1823e80";
const abi = [
  "function pendingBurn() view returns (uint256)",
  "function totalBurned() view returns (uint256)",
  "function deposit(uint256 amount)",
  "function burn(uint256 amount)",
  "function burnAll()",
];

const burnReserve = new ethers.Contract(BURN_ADDR, abi, provider);

// Check burn stats
const pending = await burnReserve.pendingBurn();
const totalBurned = await burnReserve.totalBurned();
console.log("Pending burn:", ethers.utils.formatUnits(pending, 9));
console.log("Total burned:", ethers.utils.formatUnits(totalBurned, 9));

// Deposit tokens (requires prior token.approve())
const amount = ethers.utils.parseUnits("100000", 9);
await token.connect(signer).approve(BURN_ADDR, amount);
await burnReserve.connect(signer).deposit(amount);

// Burn all pending tokens (owner or guardian)
await burnReserve.connect(owner).burnAll();

Governance

Timelock
contracts/governance/Governance.sol

Timelock-based governor for the Inferno protocol with a 48-hour delay. All protocol contracts have their ownership transferred to this contract, ensuring that parameter changes (fee rates, treasury address, etc.) go through the timelock. The owner proposes parameter changes; after the delay passes, the owner can execute them. The guardian (or owner) can cancel pending proposals for emergency response. The delay itself can only be changed via a governance proposal (self-call).

Security: The setDelay function uses the onlySelf modifier, meaning it can only be called by the Governance contract itself -- i.e., through a proposal that targets this contract. Delay must be between MIN_DELAY (1 hour) and MAX_DELAY (30 days).

Constructor

ParameterTypeDescription
_delay uint256 Timelock delay in seconds (must be between 1 hour and 30 days)
_guardian address Guardian address for proposal cancellation

Proposal Struct

FieldTypeDescription
target address Contract address to call
data bytes Encoded function call data
eta uint256 Earliest execution time (block.timestamp + delay)
executed bool Whether the proposal has been executed
cancelled bool Whether the proposal has been cancelled

Functions

FunctionParametersReturnsAccess
propose(address, bytes) target, data uint256 proposalId Owner
execute(uint256) proposalId -- Owner
cancel(uint256) proposalId -- Owner | Guardian
setDelay(uint256) _delay -- Self Only
setGuardian(address) _guardian -- Owner
setOwner(address) _owner -- Owner
getProposal(uint256) proposalId (address, bytes, uint256, bool, bool) Public

Events

EventParameters
ProposalCreated uint256 indexed id, address target, bytes data, uint256 eta
ProposalExecuted uint256 indexed id
ProposalCancelled uint256 indexed id
DelayUpdated uint256 oldDelay, uint256 newDelay
GuardianUpdated address indexed oldGuardian, address indexed newGuardian
OwnerUpdated address indexed oldOwner, address indexed newOwner

ethers.js Example

JavaScript (ethers v5)
const GOV_ADDR = "0x6050b22E4EAF3f414d1155fBaF30B868e0107017";
const TOKEN_ADDR = "0x3Bd71947F288d1dd8B21129B1bE4FF16EDd5d1F4";

const govAbi = [
  "function propose(address target, bytes data) returns (uint256)",
  "function execute(uint256 proposalId)",
  "function cancel(uint256 proposalId)",
  "function getProposal(uint256) view returns (address, bytes, uint256, bool, bool)",
  "function delay() view returns (uint256)",
  "function proposalCount() view returns (uint256)",
];

const gov = new ethers.Contract(GOV_ADDR, govAbi, provider);

// Create a proposal to update fee rates on InfernoToken
const iface = new ethers.utils.Interface([
  "function setFeeRates(uint256, uint256, uint256)",
]);
const calldata = iface.encodeFunctionData("setFeeRates", [150, 50, 100]);

const tx = await gov.connect(owner).propose(TOKEN_ADDR, calldata);
const receipt = await tx.wait();
const proposalId = receipt.events[0].args.id;

// After delay has passed, execute
await gov.connect(owner).execute(proposalId);

// Read a proposal
const [target, data, eta, executed, cancelled] =
  await gov.getProposal(proposalId);

IFRLock

Lock
contracts/lock/IFRLock.sol

Generic token lock contract designed for multi-application use. Users lock IFR tokens (with an optional lockType tag) and external resolvers query isLocked() to gate access to features (e.g. premium content, voting weight, staking tiers). Inherits OpenZeppelin's ReentrancyGuard and Pausable. No rewards or vesting -- purely a lock/unlock mechanism with on-chain queryability.

Important: This contract must be set as feeExempt on InfernoToken to prevent fee deductions on lock/unlock transfers. Otherwise, users will lose tokens to fees when locking and unlocking.

Constructor

ParameterTypeDescription
_token address Address of the IFR token contract
_guardian address Guardian address for pause/unpause and guardian updates

LockData Struct

FieldTypeDescription
amount uint256 Total IFR locked by the user
lockedAt uint256 Timestamp of last lock/increase

Functions

FunctionParametersReturnsAccess
lock(uint256) amount -- Public
lockWithType(uint256, bytes32) amount, lockType -- Public
unlock() -- -- Public
lockedBalance(address) user uint256 Public
isLocked(address, uint256) user, minAmount bool Public
lockInfo(address) user (uint256 amount, uint256 lockedAt) Public
pause() -- -- Guardian
unpause() -- -- Guardian
setGuardian(address) _guardian -- Guardian
Reentrancy protection: Both lock() / lockWithType() (via internal _lock) and unlock() use OpenZeppelin's nonReentrant modifier. Locking is also gated by whenNotPaused, but unlock() always remains available even when paused so users can recover their funds.

Events

EventParameters
Locked address indexed user, uint256 amount, bytes32 indexed lockType
Unlocked address indexed user, uint256 amount
GuardianUpdated address indexed oldGuardian, address indexed newGuardian

ethers.js Example

JavaScript (ethers v5)
const LOCK_ADDR = "0x..."; // IFRLock deployment address
const TOKEN_ADDR = "0x3Bd71947F288d1dd8B21129B1bE4FF16EDd5d1F4";

const lockAbi = [
  "function lock(uint256 amount)",
  "function lockWithType(uint256 amount, bytes32 lockType)",
  "function unlock()",
  "function lockedBalance(address) view returns (uint256)",
  "function isLocked(address, uint256) view returns (bool)",
  "function lockInfo(address) view returns (uint256, uint256)",
  "function totalLocked() view returns (uint256)",
];

const tokenAbi = [
  "function approve(address spender, uint256 amount) returns (bool)",
];

const lockContract = new ethers.Contract(LOCK_ADDR, lockAbi, provider);
const token = new ethers.Contract(TOKEN_ADDR, tokenAbi, provider);

// Approve and lock 10,000 IFR
const amount = ethers.utils.parseUnits("10000", 9);
await token.connect(signer).approve(LOCK_ADDR, amount);
await lockContract.connect(signer).lock(amount);

// Lock with a specific type (e.g. "premium" access)
const lockType = ethers.utils.id("premium"); // keccak256("premium")
await lockContract.connect(signer).lockWithType(amount, lockType);

// Check if user qualifies (has >= 5000 IFR locked)
const minRequired = ethers.utils.parseUnits("5000", 9);
const qualifies = await lockContract.isLocked(userAddr, minRequired);
console.log("Qualifies:", qualifies);

// Get lock details
const [lockedAmt, lockedAt] = await lockContract.lockInfo(userAddr);
console.log("Locked:", ethers.utils.formatUnits(lockedAmt, 9), "IFR");
console.log("Since:", new Date(lockedAt.toNumber() * 1000));

// Unlock all tokens
await lockContract.connect(signer).unlock();

PartnerVault

Partner Ecosystem
contracts/partner/PartnerVault.sol

Manages the 40M IFR Partner Ecosystem Pool (4% of total supply). Two mechanisms: milestone-based unlocking (governance records milestones that unlock IFR allocations) and lock-triggered creator rewards (when a user locks IFR for a partner's product, the partner accrues a reward of lockAmount × rewardBps / 10000 from the pool). Rewards vest linearly over 6–12 months with optional cliff.

Constructor

ParameterTypeDescription
_ifrTokenaddressInfernoToken address
_adminaddressGovernance Timelock address
_guardianaddressEmergency pause authority
_rewardBpsuint256Creator reward rate in bps (500–2500 = 5–25%)
_annualEmissionCapuint256Max IFR distributable per year (1M–10M)

Admin Functions (Governance only)

FunctionDescription
createPartner(partnerId, beneficiary, maxAllocation, vestingDuration, cliff, tier)Register a new partner with allocation cap and vesting schedule
activatePartner(partnerId)Activate a partner to start earning rewards
recordMilestone(partnerId, milestoneId, unlockAmount)Record milestone completion, unlock IFR allocation
recordLockReward(partnerId, lockAmount, wallet)Record a user lock → creator reward (lockAmount × effectiveBps / 10000). Anti-double-count per wallet.
setRewardBps(newBps)Update reward rate (500–2500 bps)
setAnnualEmissionCap(newCap)Update annual emission cap (1M–10M IFR)
setAuthorizedCaller(caller, status)Whitelist an address (e.g. backend wallet) to call recordLockReward
setIFRLock(ifrLockAddress)Set IFRLock reference for algorithmic emission throttle
setPartnerBeneficiary(partnerId, newBeneficiary)Change partner payout address
setPartnerAllocation(partnerId, newMax)Adjust partner allocation cap
finalizeMilestones(partnerId)Lock milestones — no further milestone unlocks

Permissionless Functions

FunctionDescription
claim(partnerId)Transfer vested IFR to partner beneficiary (ReentrancyGuard)
claimable(partnerId)View: currently claimable amount
vestedAmount(partnerId)View: total vested so far
partners(partnerId)View: full partner data struct
pendingBalance()View: IFR balance held by vault
walletRewardClaimed(wallet, partnerId)View: whether a wallet has been rewarded for a partner
authorizedCaller(address)View: whether an address is whitelisted for recordLockReward

Key Design

  • MUST be feeExempt on InfernoToken for correct claim transfers
  • Governance-controlled parameters with enforced min/max bounds
  • Annual emission cap resets every 365 days
  • Milestone replay protection via milestoneDone mapping
  • AuthorizedCaller whitelist: recordLockReward callable by admin OR whitelisted backend wallet
  • Anti-double-count: each (wallet, partnerId) pair can only be rewarded once
  • Algorithmic emission throttle: reward rate scales from rewardBps down to MIN_REWARD_BPS (500) as global lock ratio rises from 1% to 50%
  • SafeERC20 for all token transfers

FeeRouterV1

165 LOC
contracts/FeeRouterV1.sol

Handles protocol-level fees on IFR swaps. Accepts optional EIP-712 discount vouchers issued by the Points Backend.

Deployment (Sepolia)

0x499289C8Ef49769F4FcFF3ca86D4BD7b55B49aa4Etherscan

Key Parameters

ParameterValueGovernance
protocolFeeBps5 (0.05%)setFeeBps() — max 25
FEE_CAP_BPS25 (0.25%)Hard-coded, immutable
voucherSignerPoints Backend WalletsetVoucherSigner()
pausedfalsesetPaused()

Core Functions

FunctionDescription
swapWithFee(adapter, data, voucher, sig, useVoucher)Swap with optional discount
isVoucherValid(voucher, sig)Off-chain voucher check
setFeeBps(uint16)Change protocol fee (Governance)
setAdapter(address, bool)Whitelist adapter (Governance)
setVoucherSigner(address)Rotate signer (Governance)
setPaused(bool)Emergency pause (Governance)

EIP-712 Voucher Struct

DiscountVoucher {
  address user
  uint16  discountBps
  uint32  maxUses
  uint64  expiry
  uint256 nonce
}

Key Design Points

  • Replay protection: usedNonces[user][nonce] = true after voucher use
  • Fee cap: FEE_CAP_BPS = 25 is immutable — governance cannot exceed 0.25%
  • Adapter whitelist: only governance-approved adapters can receive swap calls
  • Pause: governance can halt all swaps in emergency
  • Owned by Governance timelock

LP Pair (IFR/WETH)

Uniswap V2
Created by Uniswap V2 Factory

The IFR/WETH liquidity pair on Uniswap V2. This is not a custom contract but a standard UniswapV2Pair created by the factory during the LP pairing step. It holds 400M IFR (40% of total supply) paired with ETH, providing the primary trading market for the token.

Note: The LP Pair is a standard Uniswap V2 contract, not an Inferno-authored contract. It is included here as the 10th on-chain component because it holds a significant portion of the token supply and is critical infrastructure for the protocol.

Addresses

ComponentAddress
LP Pair 0x2252e8bBDE0E50CD372748aC233A99C08627d9c7
Uniswap V2 Router 0xC532a74256D3Db42D0Bf7a0400fEFDbad7694008
Uniswap V2 Factory 0x7E0987E5b3a30e3f2828572Bb659A548460a3003
WETH 0x7b79995e5f793A07Bc00c21412e50Ecae098E7f9

Pool Details

PropertyValue
IFR in Pool 400,000,000 IFR (40% of supply)
ETH in Pool 0.01 ETH (Sepolia testnet)
LP Tokens Held by deployer (to be locked/burned on mainnet)

ethers.js Example

JavaScript (ethers v5)
const PAIR_ADDR = "0x2252e8bBDE0E50CD372748aC233A99C08627d9c7";
const pairAbi = [
  "function getReserves() view returns (uint112, uint112, uint32)",
  "function token0() view returns (address)",
  "function token1() view returns (address)",
  "function totalSupply() view returns (uint256)",
];

const pair = new ethers.Contract(PAIR_ADDR, pairAbi, provider);

// Read reserves
const [reserve0, reserve1] = await pair.getReserves();
const token0 = await pair.token0();

console.log("Token0:", token0);
console.log("Reserve0:", reserve0.toString());
console.log("Reserve1:", reserve1.toString());

Inferno Protocol — Solidity 0.8.20 • OpenZeppelin v5 • Hardhat v2

All contracts verified on Sepolia Etherscan