Skip to main content
SUBMIT A PRSUBMIT AN ISSUElast edit: Jun 22, 2026

Leasing Precompile

The Leasing precompile lets EVM contracts create lease crowdloans, terminate leases, and query lease state.

See Subnet Crowdloans for the full concept.

Functions

FunctionMutabilityDescription
createLeaseCrowdloan(uint64 crowdloanDeposit, uint64 crowdloanMinContribution, uint64 crowdloanCap, uint32 crowdloanEnd, uint8 leasingEmissionsShare, bool hasLeasingEndBlock, uint32 leasingEndBlock)payableCreate a lease crowdloan. leasingEmissionsShare is the % of subnet owner emissions distributed to contributors (0–100).
terminateLease(uint32 leaseId, bytes32 hotkey)payableTerminate an ended lease and claim subnet ownership. Only callable after end_block. hotkey must be owned by the calling beneficiary coldkey.
getLease(uint32 leaseId)viewReturns LeaseInfo struct.
getContributorShare(uint32 leaseId, bytes32 contributor)viewReturns (uint128 integer, uint128 fractional).
getLeaseIdForSubnet(uint16 netuid)viewReturns the leaseId associated with a subnet.

Usage examples

ABI

The canonical ABI is exported from contract-tests/src/contracts/leasing.ts.

import { ILeasingABI, ILEASING_ADDRESS } from "./contracts/leasing";

Creating a lease crowdloan

// PROTECT YOUR PRIVATE KEYS WELL, NEVER COMMIT THEM TO GITHUB OR SHARE WITH ANYONE
const { ethPrivateKey, subSeed, rpcUrl, wsUrl } = require("./config.js");
import { ethers } from "ethers";
import { ILeasingABI, ILEASING_ADDRESS } from "./contracts/leasing";

const provider = new ethers.JsonRpcProvider(rpcUrl);
const signer = new ethers.Wallet(ethPrivateKey, provider);
const contract = new ethers.Contract(ILEASING_ADDRESS, ILeasingABI, signer);

const depositRao = 1_000_000_000n; // 1 TAO

const tx = await contract.createLeaseCrowdloan(
depositRao, // crowdloanDeposit
100_000_000n, // crowdloanMinContribution: 0.1 TAO
10_000_000_000_000n, // crowdloanCap: 10,000 TAO
500000, // crowdloanEnd block
30, // leasingEmissionsShare: 30%
true, // hasLeasingEndBlock
6000000, // leasingEndBlock (~2 years out)
{ value: depositRao, gasLimit: 500_000n },
);
await tx.wait();

Terminating a lease

// Call after lease end_block has passed
const leaseId = 0;
const hotkey = "0xabcd..."; // 32-byte hotkey owned by caller's coldkey

const lease = await contract.getLease(leaseId);
if (
lease.has_end_block &&
BigInt(await provider.getBlockNumber()) >= lease.end_block
) {
const tx = await contract.terminateLease(leaseId, hotkey, {
gasLimit: 500_000n,
});
await tx.wait();
}

Querying a subnet's lease

const netuid = 5;
const leaseId = await contract.getLeaseIdForSubnet(netuid);
const lease = await contract.getLease(leaseId);

console.log(`Lease ends at block: ${lease.end_block}`);
console.log(`Emissions share to contributors: ${lease.emissions_share}%`);