Skip to main content

15 posts tagged with "enscribe"

View All Tags

How to perform onchain versioning of smart contracts

· 5 min read
Abhijeet Bhagat
Enscribe Senior Engineer

In software engineering, versioning is a core tenet of release management. However, when smart contracts are deployed to Ethereum networks, the deployment artifacts live as 42-character hexadecimal strings, with no onchain versioning information being captured about them.

They may be versioned in the GitHub repositories they were deployed on, or documented in docs, but there is no decentralised location where release information is captured, which seems ironic given they live on permissionless networks.

We want to see this change. It is now possible to easily deploy smart contracts with onchain versioning, and in this post we’re going to outline how you can do it.

We will demonstrate how you can bridge the gap between CI/CD pipelines, deployment scripts and onchain identity by programmatically assigning ENS names during deployment using open source tools.

Most developers use Foundry and Hardhat - two very popular options for smart contracts management. We provide examples showing usages of both these tools.

We’ll use Github Actions as an example but the steps/configs described should be fairly straightforward and similar with other CI/CD tools.

Naming with Foundry

We can use the Enscribe Foundry library that is written in Solidity to version your contracts. This is an example script that demonstrates how you can set a name to a contract using an environment variable:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {Script, console} from "forge-std/Script.sol";
import {Counter} from "../src/Counter.sol";
import {Ens} from "enscribe/Ens.sol";

contract MyContractScript is Script {
function run() public {
vm.startBroadcast();

counter = new Counter();
Ens.setName(block.chainid, address(counter),
string.concat(vm.envString("VERSION"), ".", vm.envString("ENS_PARENT")));

vm.stopBroadcast();
}
}

Assume we already have a top level domain name registered like mydomain.eth. You can now run this script directly from the command line to deploy & set a version for your contract:

$ export VERSION=v1 ENS_PARENT=app.mydomain.eth
$ forge script script/Counter.s.sol:CounterScript --rpc-url <BASE RPC URL> --chain-id 8453 --broadcast --private-key <PRIVATE KEY>

You can also run this script from Github Actions like so:

- name: Version Contract
env:
VERSION: v1
ENS_PARENT: app.mydomain.eth
RPC_URL: ${{ secrets.RPC_URL }}
PRIVATE_KEY: ${{ secrets.PRIVATE_KEY }}

# Execute forge script command to set the name
run: forge script script/Counter.s.sol:CounterScript --rpc-url "$RPC_URL" --chain-id 8453 --broadcast --private-key "$PRIVATE_KEY"

You can name multiple contracts in the same script as well:

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import {Script, console} from "forge-std/Script.sol";
import {Counter} from "../src/Counter.sol";
import {HelloWorld} from "../src/HelloWorld.sol";
import {MyAwesomeApp} from "../src/MyAwesomeApp.sol";
import {Ens} from "enscribe/Ens.sol";

contract DeployScript is Script {
function run() public {
vm.startBroadcast();

counter = new Counter();
hello = new HelloWorld();
app = new MyAwesomeApp();

Ens.setName(block.chainid, address(counter), string.concat(vm.envString("VERSION"), ".counter.", vm.envString("ENS_PARENT"));
Ens.setName(block.chainid, address(hello), string.concat(vm.envString("VERSION"), ".hello.", vm.envString("ENS_PARENT"));
Ens.setName(block.chainid, address(app), string.concat(vm.envString("VERSION"), ".app.", vm.envString("ENS_PARENT"));

vm.stopBroadcast();
}
}
- name: Version Contracts
env:
VERSION: v1
ENS_PARENT: mydomain.eth
RPC_URL: ${{ secrets.RPC_URL }}
PRIVATE_KEY: ${{ secrets.PRIVATE_KEY }}

# Execute forge script command to set the names
run: forge script script/DeployScript.s.sol:DeployScript --rpc-url "$RPC_URL" --chain-id 8453 --broadcast --private-key "$PRIVATE_KEY"

Naming with Hardhat

If Hardhat, instead, is what you use for contracts management, then you can version using Hardhat and the Hardhat Enscribe plugin.

We can now set an environment variable in your CI/CD pipeline like $CONTRACT_NAME=v1.app.mydomain.eth and add a Hardhat Enscribe plugin command to set this name to the contract address to the pipeline:

$ npx hardhat enscribe name $CONTRACT_NAME --contract <contract address>

For e.g., this is an example Github Actions workflow file where you can set this variable and set the name of a contract:

- name: Version Contract
env:
CONTRACT_NAME: v1.app.mydomain.eth
CONTRACT_ADDRESS: ${{ env.DEPLOYED_ADDRESS }}
RPC_URL: ${{ secrets.RPC_URL }}
PRIVATE_KEY: ${{ secrets.PRIVATE_KEY }}

# Execute Hardhat plugin command to set the name
run: npx hardhat enscribe name "$CONTRACT_NAME" --contract "$CONTRACT_ADDRESS" --network mainnet

Your should add the Hardhat Enscribe plugin to your dev dependencies in the package.json file before:

{
"devDependencies": {
"hardhat": "^3.0.0",
"@enscribe/hardhat-enscribe": "^0.1.5",
...
}
}

When you trigger a build and release cycle in the pipeline, your contract is now automatically versioned.

We can use a Git based commit hash as a part of the contract version if it is preferred over semantic versioning by extracting it programmatically and exposing it as an environment variable:

- name: Extract and set Git Hash
shell: bash
run: |
# 1. Get the short hash (7 chars)
SHORT_SHA=$(git rev-parse --short HEAD)

# 2. Save it to the Global Environment for this job
echo "GIT_HASH=$SHORT_SHA" >> $GITHUB_ENV

- name: Run Deployment
run: npx hardhat enscribe name "$CONTRACT_NAME" --contract "$CONTRACT_ADDRESS" --network mainnet
env:
CONTRACT_NAME: ${{ env.GIT_HASH }}.app.mydomain.eth
CONTRACT_ADDRESS: ${{ env.DEPLOYED_ADDRESS }}
RPC_URL: ${{ secrets.RPC_URL }}
PRIVATE_KEY: ${{ secrets.PRIVATE_KEY }}

Why Versioning Matters

By adopting onchain versioning, we aren't just making our own lives easier; we are establishing long-overdue transparency for releases. We are moving from a world where users are forced to trust hexadecimal strings to one where every deployment has a human-readable, verifiable name. The tools to make this happen are now here and ready to integrate into your pipeline.

Ready to upgrade your workflow? Check out the Foundry Library, Hardhat Plugin and TypeScript SDK or these examples to start versioning your contracts.

Happy Versioning! 🚀

The Enscribe homepage now features card-based navigation and a new search modal

· 2 min read
Nischal Sharma
Co-Founder and Lead Engineer at Enscribe

The Enscribe homepage has been redesigned. The new layout uses three feature cards for clearer navigation, and the search now resolves ENS names in your browser before making any backend calls.

Enscribe main page with card-based design

Why We Changed It

As Enscribe added the new feature Batch Naming, the text-heavy homepage made it hard for new users to find what they needed.

The search bar also created unnecessary load. Users would search for an ENS name, navigate to a details page, and only then discover the name didn't resolve or pointed somewhere unexpected or they were on the wrong chain. This meant:

  • Wasted API calls for typos and invalid names
  • Extra clicks to discover resolution failures
  • Backend queries for exploratory searches

The redesign fixes both issues.

Card-Based Navigation

The homepage now shows three feature cards:

📄 Name Contract

Name existing smart contracts with ENS names. Set forward and reverse resolution for contracts you've already deployed.

🚀 Deploy Contract

Deploy and name contracts in one flow. Skip the extra step of naming after deployment.

📚 Batch Naming

Name multiple contracts under a single parent domain.

Client-Side ENS Resolution

The search bar is now a modal that resolves ENS names before you navigate.

Search modal with ENS resolution

How It Works

  1. Click "Explore Contract or Wallet"
  2. Type an ENS name like vitalik.eth or 0x1234...5678
  3. See the resolved address: vitalik.eth → 0x1234...5678 on the desired chain
  4. Verify it's correct and resolves to an address, then click to view details

If the name doesn't resolve, you see it immediately — no wasted navigation.

Demo of search modal

Why This Matters

For users:

  • Catch typos before navigating
  • Verify resolution and chain before committing

For the platform:

  • ENS resolution happens in the browser using viem
  • Only validated searches hit the backend

The new design is live at Enscribe. We'd like to hear what you think:

  • Does the card layout help you find what you need?
  • Is the search modal helpful?
  • What would you like to see in the future?

Reach out on Discord, Telegram, or X.

Happy naming! 🚀

Batch Naming - Name Multiple Contracts in One Go

· 6 min read
Nischal Sharma
Co-Founder and Lead Engineer at Enscribe

Enscribe has shipped Contract Batch Naming feature for our Enscribe UI app. Teams and projects can now name multiple smart contracts at once under a single parent domain. This reduces the contract naming process for projects with multiple deployed contracts from hours to minutes.

Batch naming page

Why Batch Naming?

Managing multiple smart contracts across different chains has always been a challenge and time-consuming. Whether you're a DAO with governance contracts, a DeFi with multiple vault, protocol, core and utility contracts, or an infrastructure project with contracts deployed across chains, naming each contract individually means repeating the same steps: creating subnames, setting forward resolutions, and setting reverse resolutions. Each step costs gas.

When we worked with Nouns DAO to name their contracts, we saw this problem firsthand. They had to create subnames, set forward resolutions, and set reverse resolutions for each contract as a new step and their governance only allows maximum 10 transaction in a single proposal. This was their first proposal: ENS x Nouns, Name our Smart Contracts which didn't get through because of this issue.

Thus we built the Enscribe V2 contract to support batch naming with multi-chain support. This contract is now live on Ethereum mainnet and Sepolia testnet. You can read more about it in this blog post. Using the Enscribe V2 contract, you can name multiple contracts in one transaction.

We are now adding this batch naming feature support to our Enscribe UI app.

How Batch Naming Works

Batch naming uses the Enscribe V2 contract's setNameBatch() function. This involves a single transaction for creating subnames under the same parent domain and setting forward resolutions for all contracts at once. For example, if you're naming 10 contracts under myproject.eth, you just need one transaction to create 10 subnames and forward resolutions for all 10 contracts.

But for setting primary names, you need to execute one transaction for each compatible contract (contracts that are ownable/ERC-173 compliant) to set reverse resolution. Here's what happens under the hood:

The Technical Flow

  1. Operator Access: First, Enscribe requests operator approval for your parent ENS domain. This is a one-time permission that allows the Enscribe contract to create subnames under your domain.

  2. Batch Creation: All contract addresses and their corresponding names are sent in a single transaction to the Enscribe V2 contract. This creates subnames and sets forward resolutions for all contracts at once.

  3. Reverse Resolution (L1): For contracts which are ownable/ERC-173 compliant and owned by your wallet, Enscribe sets up reverse resolution on Ethereum mainnet (or testnet), enabling address-to-name lookups.

  4. L2 Primary Names: If you've selected L2 chains, Enscribe automatically switches to each chain and sets up primary names for the contracts there, ensuring consistent naming across all networks.

  5. Operator Revocation: Finally, operator access is revoked, returning full control of your ENS domain to you.

All of this happens in one modal flow, with clear progress indicators for each step.

Batch naming form

Parent Subdomains Support

Batch naming supports automatic parent subdomain creation. If you're naming contracts hierarchically (e.g., vault1.defi.myproject.eth, vault2.defi.myproject.eth), Enscribe automatically creates the intermediate parent (defi.myproject.eth) with no forward resolution. This keeps your namespace organized.

Note that each new level of parent subdomain requires a new batch naming transaction. For example, if you're naming three contracts under myproject.eth (app1.myproject.eth, app2.myproject.eth, app3.myproject.eth) and two more contracts under defi.myproject.eth (vault1.defi.myproject.eth, vault2.defi.myproject.eth), you need two separate batch naming transactions:

  1. First transaction: app1.myproject.eth, app2.myproject.eth, app3.myproject.eth, defi.myproject.eth
  2. Second transaction: vault1.defi.myproject.eth, vault2.defi.myproject.eth

Step-by-Step Guide: Batch Naming Your Contracts

Let's walk through naming multiple contracts using batch naming.

1. Navigate to Batch Naming

Head to app.enscribe.xyz and click on "Batch Naming" from the homepage.

2. Choose Your Parent Domain

Select the parent ENS domain under which all your contracts will be named. You can use:

  • Your project's ENS domain (e.g., myproject.eth)
  • The default Enscribe parent (deployd.eth)
Operator Access

Batch naming requires operator access to create subnames. An info tooltip explains this next to the Parent Domain field. Don't worry—access is revoked after naming completes or else it can be revoked manually anytime.

3. Add Your Contracts

Enter your contract addresses and their desired names. You can:

  • Add contracts one by one using the "Add Entry" button or use Upload CSV to import a CSV file with contract addresses and names.
  • You can also download a template CSV file to get started with the format. It has two columns - address and name.
  • Use hierarchical names with dots (e.g., vault1.defi, vault2.defi)
  • Mix different types of contracts in the same batch

Validation Features:

  • Real-time validation of contract addresses
  • Duplicate address detection
  • Duplicate name detection
  • Invalid label format warnings
  • Auto-generated parent subdomains highlighted

4. Advanced Options: L2 Chain Selection

Expand the Advanced Options section to configure L2 primary names.

Advanced options with L2 selection

Click "Choose L2 Chains" to select which Layer 2 networks you want to set up primary names on:

  • Optimism
  • Arbitrum
  • Base
  • Scroll
  • Linea

The system will add the corresponding coin types and create additional transaction steps to switch to each chain and set primary names.

If you only want to set up L2 primary names without L1 forward/reverse resolution, enable "Skip L1 Naming" in the Advanced Options.

5. Review and Submit

Once you've added all contracts and configured your options, click "Name Your Contracts". The system will:

  • Validate all entries
  • Verify contract ownership (for reverse resolution)
  • Add steps for naming process

6. Execute Transaction Steps

A modal will guide you through each step of the process:

Transaction steps modal

Step Progress:

  • ✅ Grant operator access
  • ✅ Create subnames and set forward resolution (batched)
  • ✅ Set reverse records (for owned contracts)
  • ✅ Switch to L2 chains and set primary names
  • ✅ Revoke operator access

Once all steps complete, you'll see a success screen showing:

  • Your parent domain
  • An expandable list of all named contracts with their addresses
  • Share buttons for X/Twitter and Farcaster
  • POAP claiming button (for mainnet deployments)

Limitations and Considerations

Prerequisites

  • You must connect from an L1 chain (Ethereum mainnet or Sepolia)
  • You need to give operator access for the parent domain (granted during the flow)
  • For reverse resolution, you must own the contract (also contract must be ownable/ERC173 compatible)

Gas Considerations

Batch naming is more gas-efficient than individual naming, but naming many contracts still requires significant gas. The transaction cost will depend on:

  • Number of contracts in the batch
  • Number of L2 chains selected

Maximum recommended batch size: 50 contracts (gas limits may reach for larger batches)

Try Batch Naming Today

Ready to name multiple contracts? Visit app.enscribe.xyz, connect your wallet to Ethereum mainnet or Sepolia, navigate to "Batch Naming", and start naming.

We'd love to hear about your batch naming experience:

Happy batch naming! 🚀

Naming Smart Contracts with Foundry

· 3 min read
Abhijeet Bhagat
Enscribe Senior Engineer

handshake

Foundry is one of the most popular toolchains for Ethereum smart contract development. Built in Rust, Foundry provides everything needed to build, test, and deploy smart contracts. At the center of this workflow is Forge, Foundry’s scripting and deployment tool. Forge scripts are written in Solidity itself, allowing developers to deploy contracts and interact with them.

However, one key step that developers miss in their workflows is to name their contracts right after the deployment is done. This is where our new Enscribe plugin comes in.

The key idea behind Enscribe is simple: naming should be automated and baked into the deployment scripts. Using Enscribe, a Forge script can register or update an ENS name for a deployed contract, optimally only set forward resolution (ENS → address), and set reverse resolution (address → ENS). Because this logic runs in Solidity, it integrates naturally with Foundry’s scripting environment.

Let’s see how developers can set names for their contract with Enscribe and Forge working together.

  1. Create a new project:

    forge init counter
    cd counter
  2. Install the Enscribe plugin:

    forge install enscribexyz/enscribe
  3. Install openzeppelin:

    forge install OpenZeppelin/openzeppelin-contracts
  4. Create remapping.txt in the root dir and add the following to it to simplify imports:

    enscribe/=lib/enscribe/src/
    @openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/
  5. Make Counter implement Ownable:

    import "@openzeppelin/contracts/access/Ownable.sol";  

    contract Counter is Ownable {
    constructor(uint256 initialCount) Ownable(msg.sender) {
    number = initialCount
    }
    }
  6. Edit our deployment script Counter.s.sol to set a primary name for the contract once deployed:

    import {Ens} from "enscribe/Ens.sol";  
    import {Script, console} from "forge-std/Script.sol";
    import {Counter} from "../src/Counter.sol";

    contract CounterScript is Script {
    Counter public counter;

    function setUp() public {}

    function run() public {
    vm.startBroadcast();

    counter = new Counter(0);
    Ens.setName(block.chainid, address(counter), "v1.counter.abhi.eth");

    vm.stopBroadcast();
    }
    }
  7. Run the script to deploy the contract on Sepolia and set the name at deployment!

    forge script script/Counter.s.sol:CounterScript --chain-id 11155111 --rpc-url $SEPOLIA_RPC_URL --broadcast --private-key $PRIVATE_KEY

You can now view the deployed contract in Enscribe app:

details

This simplification means that teams can use Enscribe to name their releases. For example, we not only named our contract but versioned it too with v1.counter.abhi.eth.

By making contract naming easier and part of the deployment workflow with Foundry, Enscribe encourages better UX and improves safety and usability across the Ethereum ecosystem.

In a world where users increasingly should see human-readable names instead of hex addresses in wallets and explorers, Enscribe helps ensure that smart contracts are just as legible as the accounts that interact with them.

Give it a try.

Happy naming! 🚀

Naming your contracts with Basenames

· 3 min read
Abhijeet Bhagat
Enscribe Senior Engineer

Basenames are growing in popularity. Users set them for their EOA accounts so that they don’t have to use hex addresses when interacting on Base. Basenames use the solid ENS infra underneath and are fully ENSIP-19 compliant.

Since Enscribe is on a mission to eradicate hex addresses from Web3 UX and contract naming is overlooked, we wanted to enable users to set Basenames for deployed contracts as well. We are excited to announce support for naming your contracts using Basenames.

ENSIP-19 in short

ENSIP-19 is an ENS Standardization Proposal that standardizes reverse and primary name resolution for all coin types, and defines how this resolution process operates across the multichain Ethereum ecosystem.

This is done by deploying an L2-specific Reverse Registrar contract that takes care of setting reverse records.

For example, suppose we want to set a Basename v1app.alice.base.eth. Then, we first create a subname on L2 ENS Registry by calling setSubnodeRecord:

setSubnodeRecord(namehash(alice.base.eth), labelhas(v1app), deployerAddress, resolverAddress, 0)

Then we can set a forward resolution that maps the name to address with:

setAddr(namehash(v1app.alice.base.eth), BASE_COIN_TYPE, contractAddress)

Finally, set the reverse record with the L2 Reverse Registrar:

setNameForAddr(contractAddress, v1app.alice.base.eth)

How to set a Basename for your contract?

Navigate to the Name Contract page & connect your wallet if you haven’t already. From the chain dropdown, select Base/Base Sepolia i.e. the chain you want to set the Basename on.

Name Contract

Enter your contract’s address in the Contract Address field and it should automatically detect the chain like shown above.

Click on Create New Name button and enter the new contract name you want to register and the parent domain under which you want to register the subname:

details

Note: the parent domain entered should already be registered. If you want to register a new parent domain, then use https://www.base.org/names to do so.

Click on Name Your Contract button & you’ll see all the transactions executing successfully:

success

And just like that, we have successfully set a Basename for our deployed Ownable contract!

Here's a video tutorial on how to set a Basename for your contract:

What This Means for the Ecosystem

We’re excited to see how the community puts this to use. As always, feedback is welcome—we’re continuing to refine our ENSIP-19 aligned features and would love to hear what you think.

Head over to Enscribe and use a Basename to name your contract!

Happy naming! 🚀

EnscribeV2 is now live on Ethereum mainnet

· 4 min read
Nischal Sharma
Co-Founder and Lead Engineer at Enscribe

Enscribe V2 is now deployed on Ethereum mainnet. This upgrade brings batch operations, multi-chain support, and gas optimizations that make naming large numbers of contracts practical.

Contract Addresses

Ethereum Mainnet:

Testnet (Sepolia):

The Problem: Naming Contracts at Scale

Projects deploying multiple smart contracts face a challenge: each contract needs a separate ENS transaction to get a human-readable name. For a project with 10, 20, or 100+ contracts, this means:

  • Dozens of individual transactions
  • High cumulative gas costs
  • Hours of manual execution
  • Complex workflow coordination

A DAO deploying governance contracts, treasury modules, and token contracts previously needed separate ENS transactions for each — monitoring every transaction and managing a complex deployment process.

Enscribe V2 solves this.

What's New

Batch Contract Naming

Name multiple existing contracts in a single transaction.

// Name 10 contracts at once
address[] memory contracts = [
0x1234..., // governance.dao.eth
0x5678..., // treasury.dao.eth
0x9abc..., // token.dao.eth
0x0000.... // 0x0 address to reserve the subname
];

string[] memory labels = ["governance", "treasury", "token", "reserve"];

enscribeV2.setNameBatch(
contracts,
labels,
"dao.eth",
[60, 2147492101] // Ethereum and Base cointypes
);

Note: The reserve subname is created with the address(0) address. This is useful when you just want to create the subname but not set an address yet.

ENSIP-19 Multi-Chain Support

Set forward resolution for multiple chains at once:

uint256[] memory coinTypes = [
60, // Ethereum
2147492101, // Base
42161, // Arbitrum
10 // Optimism
];

enscribeV2.setName(
contractAddress,
"bridge",
"protocol.eth",
coinTypes
);

This matters for cross-chain protocols and multi-chain deployments where the same contract needs to resolve on different networks.

Simpler API

Before V2:

bytes32 parentNode = namehash("myproject.eth"); // Manual computation
enscribe.setName(addr, "app", "myproject.eth", parentNode);

With V2:

enscribe.setName(addr, "app", "myproject.eth"); // Computed automatically

The contract now computes parent nodes using ENS's NameCoder library.

Reserve Names Without Addresses

Create subnames without setting an address:

address[] memory contracts = [
0x1234..., // Active contract
address(0), // Reserve "staging", 0x0000000000000000000000000000000000000000 address
0x5678... // Active contract
];

enscribeV2.setNameBatch(
contracts,
["prod", "staging", "analytics"],
"myproject.eth"
);

As demontrated in Batch Contract Naming section also, using address(0) creates the subname but skips forward resolution — useful for just creating the subname.

EnscribeV2 Functions

Projects can now:

  • Name dozens of contracts in one transaction
  • Save gas through batch operations and new gas optimizations
  • Can name contracts on multiple chains at once
  • Fully ENSIP-19 compatible

Technical Improvements

V2 includes several optimizations:

  • ENS NameCoder Integration: Uses official ENS library gas savings per operation
  • OpenZeppelin Create2: Deterministic contract deployment with industry-standard implementation
  • Custom Errors and Events: ~50% gas savings on reverts compared to string messages
  • Internal Optimizations: Automatic subname existence checking and address validation

What's Next

Enscribe V2 contracts are live and ready to use via web3 libraries or transaction builders like Gnosis Safe.

Coming Soon:

  • UI updates for batch operations and multi-chain support on Enscribe app
  • EnscribeV2 integration to our Enscribe library
  • EnscribeV2 for Basenames

Building Contract Identity

Enscribe makes smart contracts easier to trust by giving them human-readable names. Earlier this year, we proposed an ENSIP for contract metadata standards. V2's batch capabilities and multi-chain support lay the groundwork for that vision — making it practical for projects to build complete, discoverable contract identities.

Whether you're deploying a DeFi protocol, launching a DAO, or building any multi-contract system, Enscribe V2 helps you establish clear contract identity from day one.

Questions? Join our Discord, Telegram or reach out on X.

Happy naming! 🚀

ENS Contract Naming Season

· 3 min read
Conor Svensson
Founder of Enscribe and Web3 Labs

The ENS DAO has officially passed a proposal launching ENS Contract Naming Season — a new community initiative to bring names, identity, and trust to smart contracts across Ethereum.

Contract naming season banner

What is Contract Naming Season?

Contract Naming Season is a collaborative effort between the ENS DAO, Enscribe and others to help projects name their smart contracts using ENS names, turning unreadable hexadecimal addresses into human-readable, trustworthy names.

To encourage adoption, the ENS DAO has created a 10,000 ENS reward pool, offering incentives to teams that name their contracts and help lead others to do the same.

Enscribe naming contract view

You can read the proposal on Tally for background.

Why it Matters

Every time users interact with a smart contract, they’re asked to trust a long, meaningless hex address.

Not only does this make Ethereum harder to use, it leaves users exposed to address spoofing and phishing attacks from scammers.

Web3 UX Needs to Change slide

Millions of dollars is lost every year to address spoofing and poisoning attacks on Ethereum.

Enscribe was created to address these issues. It’s a smart contract naming service built on ENS.

It allows developers and projects to easily name their smart contracts with ENS names. This creates human-readable, trustworthy identities for contracts, turning unreadable hexadecimal addresses into meaningful names.

Where it’s Happening

Enscribe is live on Ethereum and integrates directly with ENS and contract verification platforms like Etherscan, Blockscout and Sourcify.

We've integrated with projects like Safe, Ethereum Follow Protocol and Open Labels Initiative to make contract naming a new standard for increased safety for Ethereum’s users.

Try it now: app.enscribe.xyz

Enscribe contract view

How to Get Involved

  1. Join the conversation in the:

  2. Check out our Best Practice Guides for:

  3. Start naming your contracts:

When

Contract Naming Season runs November 2025 → April 2026.

Reward distribution details will be announced soon — stay tuned!

Voices From the Community

ENS has always been about empowering the Ethereum community to name and own their digital identities. Contract Naming Season continues that mission — helping developers, DAOs, and protocols give their smart contracts names users can trust.

nick.eth, Creator of ENS

All smart contracts should be named onchain, for security, readability, and transparency. Contract Naming Season with Enscribe is a great opportunity to finally get it done.

brantly.eth, Executive Director, Ethereum Identity Foundation, ENS DAO Delegate, ex-Director of Operations, ENS

Naming Season captures what makes ENS, DAOs and Ethereum special — community-led initiatives that drive our ecosystem forward! It’s actions like naming contracts that build the culture of safety and transparency we all depend on.

james.eth, Fire Eyes DAO, ENS DAO Delegate

Named contracts upgrade security and enhance UX. Promoting awareness of contract naming opportunities across protocols, DAOs, and apps through Contract Naming Season is a key step forward for the Ethereum community.

lightwalker.eth, NameHash Labs

Let’s Make Ethereum Safer

Contract naming is a simple step every team can take to strengthen Ethereum’s foundation of trust and transparency. Let’s eliminate hex contract addresses and make human-readable contracts the new default.

Join the movement: app.enscribe.xyz

Happy naming! 🚀

Viewing Calldata to Simplify DAO Smart Contract Naming

· 3 min read
Abhijeet Bhagat
Enscribe Senior Engineer

We created the Enscribe App to make it as simple as possible for teams to name their smart contracts. However, this approach is not always compatible with naming DAO contracts.

What we’ve noticed is that DAOs often use a high-level function wrapper that needs to call multiple transactions required to name a contract.

This requires multi-sig high level transaction calling a method such as execute() or executeTransactions() which wraps over executing multiple transactions, each represented by a calldata – an encoded form of a function call along with its arguments.

To make this kind of name setting easy, we’ve shipped a small feature in Enscribe that enables displaying call-data previews.

How to View Calldata?

In the Enscribe App, there is now a new collapsable Advanced Options section. Open it and you’ll see a calldata section that shows a list of the transactions Enscribe will execute for your naming flow — including items such as subname creation, forward resolution, and reverse resolution.

name-contract

To try this out yourself, when you paste a contract address, pick a parent (e.g. myapp.eth), and type a name, Enscribe now shows the exact encoded function calls of the transactions that will be sent on-chain as individual transactions.

Each entry shows the target, selector, and ABI-encoded calldata:

calldata

You can copy the individual calldata using the copy button displayed against it or you can also copy the entire calldata list in different forms by clicking on the Copy All button at the top of the list on the right side.

Realtime Updates

This isn’t a static blob. Change any of the inputs — address, label, or parent, and the calldata recomputes instantly. If you switch from router.myapp.eth to vault.myapp.eth, you’ll watch the encoded arguments update in place.

L2 Calldata

We also moved the Choose L2 Chains button into the Advanced Options section. L2 forward/reverse steps sometimes add extra calls (or different targets), and keeping them alongside the call-data preview makes it obvious what will happen. The calldata displayed also includes transactions that will execute on the L2 chain.

TLDR;

  • Enter your contract address.
  • Pick a parent (e.g., myapp.eth) and type a label (e.g., router).
  • Expand the Advanced Options section
  • Expand the Call data section
  • Copy the calldata

So head over to the Enscribe App, enter the details about the contract you want to name and inspect the calldata generated in the Advanced Options section.

Happy naming! 🚀

Name Your Contracts with the Enscribe Library

· 3 min read
Abhijeet Bhagat
Enscribe Senior Engineer

Last week, we announced the hardhat-enscribe plugin for smart contract developers to name their contracts. We showed how smart contract developers can name their contracts with hardhat:

  • Using a CLI command, powered by the hardhat-enscribe plugin, that can be executed after the deployment command
  • Using the enscribe library in the hardhat deployment script

Under the hood, the hardhat-enscribe plugin uses the same @enscribe/enscribe library. It is a small TypeScript library you can use in any app or tool.

In this post, we will take a look at how to use the library to name your smart contracts in your apps.

It is very simple to use. From its public API, a single abstraction function creates the subname, sets forward and reverse records, and returns useful metadata (tx hashes, detected contract type, explorer link).

Using the Library

Start by installing the library:

pnpm install @enscribe/enscribe  

Once installed, import the nameContract function:

import { nameContract } from "@enscribe/enscribe";

The nameContract function itself has a simple interface. It accepts the following parameters:

  • Contract name
  • Contract address
  • Wallet client (from viem or wagmi)
  • Name of the chain on which the contract address is
  • Optional flag for logging naming metrics

We now create a wallet client object with wagmi:

import useWalletClient from ‘wagmi’

const { data: walletClient } = useWalletClient()

Once we have the wallet client created, we are ready to name our contract with nameContract:

const res = await nameContract({
name: "vault.myapp.eth",
contractAddress: "0x…",
walletClient,
chainName: "sepolia",
enableMetrics: true
});

That’s it! With this single function, developers can easily set a name to their contracts without having to worry about sending individual transactions like creation of subname and setting resolutions.

However, the library is also flexible in leaking this abstraction (which isn’t a bad thing always 🙂) by exposing the following functions and use them however you want:

  • createSubname
  • setForwardResolution
  • setReverseResolution

We want to make it easier for developers to name their contracts during contract deployment time and this is where the library comes in – they can integrate it in their Hardhat scripts. But they can also name their contracts after the contract is deployed with the hardhat-enscribe plugin. You can head over to the library documentation to explore the API.

Get started

  • Hardhat plugin: install, configure, and run npm hardhat enscribe name ... to label new or existing deployments. (GitHub)
  • Core library: import @enscribe/enscribe and call nameContract() wherever you manage contracts (GitHub)
  • Docs & guides: quick starts, concepts, and best practices for contract naming and multi-chain resolution. (enscribe.xyz)

Happy naming! 🚀

Smart Contract Naming With Hardhat

· 4 min read
Abhijeet Bhagat
Enscribe Senior Engineer

Adding support for contract naming into dev workflows has always been our top priority. Hardhat is a leading Ethereum developer environment. It’s TypeScript-first, fast, and built around a clean plugin architecture. Hence, it’s the perfect tool for contract management like deployment, testing, etc. We are excited to announce a plugin for the popular Hardhat ecosystem that adds contract naming to it.

Naming your contract from the CLI

hardhat-enscribe is a Hardhat v3 plugin that assigns ENS names to contracts, handling the full flow for you:

  • subname creation
  • forward resolution and
  • reverse resolution

It auto-detects common patterns like Ownable and ReverseClaimer, waits for confirmations, and plugs neatly into a viem-powered stack. It can be installed using the following command:

pnpm install @enscribe/hardhat-enscribe  

Let’s create new Hardhat project to deploy a contract on Sepolia:

mkdir hardhat-example
cd hardhat-example
pnpm dlx hardhat --init

This will generate a skeletal Hardhat project with a sample contract with the following project structure –

hardhat.config.ts
contracts
├── Counter.sol
└── Counter.t.sol
test
└── Counter.ts
ignition
└── modules
└── Counter.ts
scripts
└── send-op-tx.ts

We can build our project with the following command:

npx hardhat build

Let’s now deploy our contract on Sepolia. For this, we’ll need to add configuration to interact with Sepolia. First, let’s export some env variables for the RPC URL and the private key of the account that we want to use to deploy the contract:

export SEPOLIA_RPC_URL=<sepolia rpc url>
export SEPOLIA_PRIVATE_KEY=<your sepolia account private key>
npx hardhat keystore set SEPOLIA_RPC_URL
npx hardhat keystore set SEPOLIA_PRIVATE_KEY

Now open the hardhat.config.ts file and add configuration for sepolia –

const config: HardhatUserConfig = {

networks: {
sepolia: {
type: "http",
chainType: "l1",
url: configVariable("SEPOLIA_RPC_URL"),
accounts: [configVariable("SEPOLIA_PRIVATE_KEY")],
},
},
}

Our sample contract Counter.sol can now be deployed on sepolia with:

npx hardhat ignition --network sepolia deploy ignition/modules/Counter.ts

Once deployed, we are now ready to name our deployed contract. We need to add the hardhat-enscribe plugin to the list of plugins first. Open the hardhat.config.ts file and add the plugin:

import hardhatEnscribePlugin from "@enscribe/hardhat-enscribe";

const config: HardhatUserConfig = {
plugins: [hardhatToolboxViemPlugin, hardhatEnscribePlugin],

}

Then, invoke the plugin by passing the name and contract address in the command:

pnpm hardhat enscribe name mycontract.app.eth --contract 0x1234...abcd

This is what you’ll see in the output –

normalized name is mycontract.app.eth

Naming completed successfully!
Contract Type: ReverseClaimer
Transactions: {
subname: '0xb5a4131bb0bf3c2708a8181349998f57c76226559042cf68423aeefc74e8cd55',
forwardResolution: '0xa6aa6ac9a0857aaeaff1ef3d69b2962ab01650230bc5c9d8d3108dcfb63cebfa',
reverseResolution: '0xb1f260a587f793251804b6f809b4d1546d81dd98c1605c5eb7d812d1afc190b9'
}

Naming your contract from a Hardhat deployment script

You aren’t limited to setting a name for a contract from the CLI though. Scripting is a very powerful feature of Hardhat that allows you to do more than just contract development. You can call APIs, interact with contracts and even interact with the blockchain. You can now name your contract from a script too and we shall now see how you can do that.

First, connect to the network and deploy the CounterModule:

import hre from "hardhat";
import CounterModule from "../ignition/modules/Counter.js";


const connection = await hre.network.connect();
const { counter } = await connection.ignition.deploy(CounterModule);

Next, get the walletClient –

 const [walletClient] = await connection.viem.getWalletClients();
console.log(`Using account: ${walletClient.account?.address}`);

Now create a normalized name –

 const ensName = `wpsqhsld.abhi.eth`;
const normalizedName = normalize(ensName);

We are now ready to set the name by using the enscribe library (more about this in the next blog) –

import { nameContract } from "@enscribe/enscribe";


try {
const result = await nameContract({
name: normalizedName,
contractAddress: counter.address,
walletClient: walletClient,
chainName: networkName,
opType: "ignition-deploy-and-name",
enableMetrics: true,
});

} catch (error) {

}

That’s it! Your contract can be deployed and named with a Hardhat script easily. You can see the full example here.

Parting Thoughts

Our focus will always be on improving developer workflows for contract naming and the hardhat-enscribe is an important integration for us.

We are continuing to focus on different ways to make contract naming better for developers. So go ahead and integrate contract naming today in your workflows!

Happy naming! 🚀