NameSys: Off-Chain Secure Records are here!

NameSys.eth: Off-Chain ENS Records Manager

Hello frENS, degENS,

:exclamation: Have you ever wanted to set your ENS Records for free?

:exclamation: Did you ever wish that you could update your avatar dynamically for free infinite number of times?

:exclamation: Do you get sick of high gas costs getting in the way of your undeniable ENS addiction?

:exclamation: How often would you change your records if you could do it for free forever?

We are sure that you heard these musings in countless larping sessions/spaces, and lo and behold, we are esctatic to announce that we have the cure for all your ailments. Everyone knows that gas has been the biggest pain in the ass for ENS degens and regens alike. Previously, IPNS made it free to update our contenthashes at least, and in more recent times, CCIP-Read has promised us free stuff such as off-chain subdomains (e.g. etc. While that is cool, Devs at NameSys continued asking themselves the following question:

:bulb:  If we can use IPNS for free contenthash updates and CCIP-Read for free subdomains, why can’t we combine the two and use IPNS & CCIP-Read for Off-Chain Records?

The answer is naturally YES, and today is the day when we deliver to you the ultimate free stuff! NameSys is an Off-Chain ENS Records Manager which allows users to host their ENS records off-chain on IPNS in an autonomous and gasless fashion. The off-chain records are resolved using CCIP-Read by a custom resolver (called CCIP2) capable of reading records from IPNS.

:bulb:  While this sounds cool, one might wonder why this hasn’t been done already…?

The main reason for that is: Text records such as addresses are sensitive information. CCIP-Read is designed to read from off-chain sources which are usually servers. Hosting records on centralised servers requires severe trust assumptions and is therefore extremely dangerous!

:bulb:  Okay, that sounds reasonable! But what about other decentralised off-chain storage solutions like IPFS and Arweave?

While IPFS can be used, IPFS hashes are immutable and cannot be reused. So IPFS is indeed a relatively better solution but it is not gas-efficient since updating records will require posting new hashes to the blockchain.

:bulb:  Well, we already have IPNS for that! Why not use IPNS similar to how we use it for free contenthash updates?

That is indeed a good idea, but note that IPNS pointers/hashes are actually keypairs. Currently, no public service exists that will allow users to autonomously pin IPNS public key without sharing their private key with the pinning provider. Services like and require users to share their private key with them; this is highly unsuitable for storing sensitive records and a massive threat vector!

:bulb:  Hmmm, I see. It seems the key to solving this problem is to design a non-custodial solution for hosting IPNS records where users do not have to share their IPNS private key with the service provider. Unless such a solution exists, off-chain & upgradeable ENS records cannot be safely implemented. Is this correct?

Yes, that is correct, and we have the solution! NameSys stack is that non-custodial and autonomous off-chain solution which provides similar level of security as on-chain records, while saving you all that gas!

:bulb:  How does NameSys do it?

NameSys accomplishes secure record storage on IPNS by cleverly generating deterministic IPNS keypairs from users’ wallet signatures and using w3name API for keyless IPNS hosting. NameSys streamlines the entire mechanism of a) securely generating IPNS keypair, b) encoding records with secure signatures, c) posting IPFS content to IPNS in a keyless manner, and d) finally handling verified resolution of IPNS records with CCIP2 custom resolver. No more sharing your IPNS private key with a third-party service!

:bulb:  That sounds cool! Can you explain the technicals a bit more? What do I have to do to start using off-chain records?

Okay, sure! Here go the step-by-step details: You can start by simply visiting the NameSys Client and connecting your wallet.

:test_tube:  The first step to start using off-chain records is the initial Setup: it consists of setting your resolver to CCIP2 (TXN1) and setting your parent IPNS contenthash on-chain (called recordhash; TXN2) which will contain all your usual ENS records. NameSys client will handle generating the corresponding IPNS private key using your signature (SIG1 in Metamask) and a prompted password.

Note: password is your unique (and secret!) identifier for the IPNS keypair and you must remember this for future record updates

Note: Users must make sure that the auto-generated SIG1 is treated on equal footing with password in terms of secrecy

:test_tube:  Upon completing this simple setup process, you are ready to use free and secure off-chain records for your ENS domain forever! In order to set a new record, simply continue in the client. Each time you attempt to update a record, the client will ask for your secret password and prompt for a determin signature in Metamask, and generate the deterministic IPNS private key from it. Client will then sign your new records (for verification by the resolver) and pin them to your IPNS public key using w3name API. After this step, the IPNS private key is destroyed and no record of it exists anywhere in the universe! It is precisely this step that makes NameSys secure. Upon each update, the IPNS keypair can only be re-generated by the user with their unique signature and secret password that only they know!

:test_tube:  Lastly, the CCIP2 resolver is tasked with the job of reading the records that you just updated on IPNS using CCIP-Read. The resolver additionally verifies the signatures appended with the records before resolving them, thereby adding an additional layer of on-chain security!


:bulb:  Hold up, are you saying that I can use off-chain records for FREE FOREVER after completing the one-time initial Setup?

That is precisely what we are saying! Note that NameSys provides you with a similar level of security as on-chain records. It doesn’t use any centralised storage like servers. It doesn’t force you to share your IPNS private key with a third-party. It is fully autonomous! Your records are additionally verified by your unique signatures at each resolution; this means that your records will stop resolving if you sell or transfer your name.

:bulb:  This seems too good to be true! What’s the catch here? Off-chain storage cannot theoretically equate to on-chain storage; this will defeat the whole purpose of blockchain.

Well noted, there is of course a catch! IPNS records can take anywhere between 60 seconds to 60 minutes to propagate after setting them. Unlike on-chain records that have 100% live-time and instantaneous resolution, IPNS records can occassionally be slow to resolve or at least take a few minutes to become live after you have set them. This is the sacrifice we make to keep the records secure! In the grand optimisation scheme, we have tuned for safety and prioritised security over instant post-update availability. Having said that, these issues are easily solvable since NameSys allows users to re-generate & export their IPNS private key (and IPFS hash) if they seek to pin their records elsewhere such as Pinata, Fleek, dWebServices etc. This should resolve the up-time and live-time issue, if/when it exists.

:bulb:  Does this mean I can set DYNAMIC avatars?!

YES! NameSys makes dynamic avatars possible. NameSys also makes dynamic addresses possible, e.g. users can programatically set their resolved addresses to vary with time or other parameters. This is some low-level Account Abstraction built with ENS!

:bulb:  This sounds very promising and full of possibilities!

It sure is! We already have new ultra-saver features lined up for CCIP2-v2:

:battery: WALLET-SPECIFIC RECORDS: Set default records for all your names in a given wallet. No need to set individual IPNS hashes for your names :money_with_wings:

:battery: ON-CHAIN SIGNER: Set an on-chain signer for your records for additional security :lock:

:battery: REDIRECT RECORDS: Redirect records from one ENS name to another :recycle:

:partying_face: We hope that the ENS community will finally be able to take advantage of FREE & SECURE RECORDS FOREVER! :tada:

Note: Devs can read full specs on our GitHub page and contact us for discussing APIs for dynamic avatars!


Resolver: 0x57532d78FfBcC6ac5534A9b39899C7eC89082CdA

Client: | |

@Ecosystem_Stewards I would like to request a 15-minute slot (10-minute presentation + 5-minute demo) in the next Ecosystem WG weekly meeting to present our work to the DAO!

Matteo, on behalf of NameSys.eth


You are welcome to present at ecosystem. I’ll be putting out the agenda tomorrow and make sure to include namesys.

1 Like

Hi. thank you for your detailed update. Decentralised file system based offchain resolver has been presented a couple of times but all of them lacked a way to prove that the given record is the latest. Does this method resolve the timestamp issue?

Also does this approach works for issuing subnames on l2?


Very cool effort indeed!

Makoto highlights one concern that users should be made aware of: although you can prove the domain owner approved the records, you can’t prove they’re the latest version, so replay attacks are possible.

I note that you’re using a separate dedicated gateway; you may be intrigued to note that it’s actually possible for an IPFS gateway to serve as a CCIP-Read gateway. If you use substitution parameters to put the recipient and data into the URL, you can store pregenerated CCIP-read responses in an IPFS hierarchy and they can be served up directly. Combined with a custom resolver this can eliminate the need to run any dedicated gateway at all.


@broke.eth :pray: we finally released a * beta * basic working version of non-custodial off-chain+gasless records manager/ pls take a look around for feedback…


Hello, @NameSys Will you please explain why users need to share their private key?

I know you’re referring to the IPFS node private key, but non-tech users might not grasp its meaning, and some of them are even jokingly asking if you intend to ‘rug’ my wallet :sweat_smile:. Can you please rephrase the explanation for better clarity?

This is correct. IPFS/IPNS stack by itself provides no way to definitively determine the latest version. But there are solutions to this beyond IPFS and they all (ideally) require some sort of (decentralised) indexer/archiver which can store the pointer to the latest version. We jammed on some ideas and there are two main ones:

  1. Use Nostr Relays as the decentralised indexer. One can imagine Nostr bots republishing IPNS updates on the Nostr network and the CCIP2 contract can be interfaced with Nostr network to pick the latest version number of the IPNS node. This method is sort of alien to the Ethereum ecosystem with a lot of caveats but it is free.

  2. Use L2 events as the decentralised indexer. One can imagine a simple contract on a cheap L2 logging events containing the latest version number upon each IPNS update. CCIP2 contract can then be interfaced directly with the L2’s RPC provider to pick the latest IPNS version. This is our preferred solution and it is part of our v2 roadmap. This is a more native method, very cheap even if not free (fraction of a cent) but requires users to maintain an L2 wallet with small funds. With AA, this will become rather straightforward though and not as much a hassle.

Replay attacks are never possible since records require signature check for each version. The worst-case scenario here is a “stale resolution” where an older version is resolved by the IPNS lookup. In >99% of cases, it takes less than 1 hour for the IPFS network to resolve the latest version.

This was our initial prototype but we ran into problems such as extremely slow speed and high error rate of public gateways. This forced us into creating our own web3 gateway with great help from @ethlimo.eth and we are able to resolve the records with 1s latency using ETH.LIMO infra.

This is a potential ‘man in the middle’ vulnerability. Our dedicated gateway is in fact a contract that uses ETH.LIMO as the primary gateway provider but additionally has the usual public gateways coded as fallbacks. So we do exactly what you describe under the hood, plus some extra decentralisation and transparency.

Yes, I must explicitly mention that I am talking about the IPNS private key and not your Ethereum wallet key. Having said that, we are happy to help implement keyless IPNS if they want. The underlying implementation code is here: IPNS Keygen and the deep docs for it are here: README. This method is a bit of an overkill for IPNS though and it is possible to shorten it. You can ping us in our discussions and we’ll be happy to help you.

1 Like

You may be able to fetch the latest information through events but would it be possible to verify that that’s the latest version on L1 verifier contract?

Also, how do you guarantee that the event information is written in the sequence without trusting the entity that send a transaction to L2 to emit the event?

There is no need to verify on L1. It is up to the user to make sure that they complete the event logging transaction on L2 or they will risk resolving a stale version. One can additionally code a condition in the CCIP2 callback() to compare the version number resolved by IPFS and the last version number logged on L2. If the IPFS version is later, we will warn the users that they are missing event logs and resolve the IPFS version instead of the L2 version.

This entity is the user and we expect them to send the transaction to L2 via our client. It will be an optional part of the record update codeflow. If user chooses against this, then they are risking stale resolution. This may matter to some users and/or some records but not so much for others.

As requested in the earlier comment, please include the IPNS key part in your original article. We don’t want the community to get the wrong information.

Could you please explain why a user would share his IPFS node private keys? Here 1W3 or dWebservices are the ones generating the IPNS keys, not the other way around.

Thanks for offering help :pray:

The post seems locked for edits. There is no Edit button on the main post for me (screenshot below). Maybe a mod can help us? :face_with_open_eyes_and_hand_over_mouth:

That is bad since the third party is updating the content on user’s behalf. If server gets compromised/hacked, hacker can post malicious content to user’s .eth profile. If user has payment/sensitive links on their profile, visitors can get phished. A third party holding user’s private key is as bad as it gets.

Yes, If server gets hacked! This is the same with all the IPNS service providers like pinata, fleek,, etc., because of its centralized nature. That is the reason we have been given the option to choose between IPFS and IPNS for content hash.

Will you please explain who’s IPFS nodes the IPNS records are getting created for users by are you using any third-party services?

I’m trying to use this one is always 504

Not all IPNS service providers are an attack vector, only those who store the private keys at the node. w3name is an example of such an API. It doesn’t store or require your key to host your content. We are using their stack. It is open-source and very lightweight!

We use our own IPFS node for pinning IPFS content initially. This is not a limitation though since both IPNS private key and IPFS hash can be exported in our client and re-pinned by the user (and they should be!) at their own choice of service provider. For example, if a user wants to be extra sure that their records resolve if w3name API dies, they can export their IPNS key and host it additionally on their server. Users can of course pin their IPFS hash at multiple services like Pinata, Fleek, web3storage etc if they want to host their records at other nodes besides NameSys. More the merrier!

We strongly believe in the ‘not your keys, not your content’ philosophy. NameSys stack is uncompromisable at its core. If w3name API dies and NameSys node crashes, NameSys stack will keep on working. It only needs new coordinates of the new storages and it will keep running (users will have to reset their records though of course).

This is correct and expected. You have set the recordhash in the client so it is trying to read what records you have set (address in this case) in the IPNS key. When you make an update, it will be stop throwing the log. Thanks for notifying nonetheless, I’ll pass this info to the devs so that this try-catch is caught instead of logged.

1 Like

We also strongly believe in the ‘not your keys, not your content’ philosophy. We made numerous attempts to implement a user-owned IPNS KEY; however, at the time we were building our solution, w3name was not stable. We hope it is now functioning properly.

I would like to understand more about how the user can own the IPNS private key. I hope you will demonstrate this in the ECOSYSTEM call this Thursday. See you at the call.

:pray: sorry for this mix up…

Our ed25519 keygen PR was merged in GitHub - paulmillr/ed25519-keygen: Generate ed25519 keys for SSH, PGP (GPG), TOR, IPNS and SLIP-0010 hdkey recently, it’s 100% compatible with w3name keys format… still requires other half using secp256k1 deterministic signature and ?HKDF, all inspired by Umbra cash keygen.

It’s possible to inject IPNS/DHT for hourly/daily republishing services, it’s more confusing with old libp2p key specs used as node key which is also IPNS key. IPNS directly supports (at least on docs) to use secp256k1 but it’s not widely supported yet, that’d allow reusing same ETH keys directly for IPNS.

We’re recently talking with @ethlimo.eth devs for possible full ENS+IPFS cluster to store “pin” and manage IPFS data with some basic size limits per domain… That’ll require its own forum topics and funding process from ENS DAO. We’re all in this together, always happy to help around. :vulcan_salute:

That’s what a replay attack is. :slightly_smiling_face:

Wouldn’t it be simpler to just operate your own IPFS gateway instead, then? You could apply access controls to only allow access to relevant content via it.

I don’t follow; can you describe the vulnerability in more detail?

In that case, we are on the same page :vulcan_salute: I understood ‘replay attack’ to mean something else

That is correct. But the devs made this project with $239 in expenses. $173 in contract deployment and $66 for 3 months of cloud service for a basic IPFS node. We have so far received $110 from the Gitcoin round. A dedicated gateway needs more :dollar:. Lack of funds forced us into bootstrapping on ETH.LIMO infra. Plus, ETH.LIMO is a highly trusted service/gateway and we are not.

Having thought more on this, you are right. It is not necessarily MITM-vulnerable as long as the users make informed choice for a gateway. Devs were initially worried about compromised/slow choice of gateways. When the user sets the records on our client, we can offer them the option to specify the gateway and encode it in the payload. So this can indeed be a choice for users in v2 and some users may well want to use a personal access-controlled fast gateway. We have made a note of this for v2 :hand_with_index_finger_and_thumb_crossed:

1 Like

P.S. I forgot to add that devs are looking into abandoning IPNS in favour of L2 altogether. If one can read IPNS version numbers from L2, then why not read an IPFS hash directly? Then resolution will be instant and just like L1, avoiding the IPNS mess. The issue standing in the way of this is the rigid CCIP-Read interface that cannot read directly from RESTful Ethereum endpoints (as far as we know; please correct us otherwise). We don’t want to inject another web2 point-of-failure by using a middleware proxy server for interfacing. A better option would be a Chainlink Oracle that can translate the HTTP GET from common Ethereum providers (Infura, Alchemy etc) to CCIP-Read-compatible format. This would be a better and more general solution!


Update on NameSys

We are glad to announce that NameSys is now LIVE on MAINNET!

We have made several improvements to the Beta version and included some features that came up in the comments. We have also brought forward couple of features such as

  • Global Storage for all names in a wallet, and
  • Possibility to specify an HTTP Gateway instead of using the IPFS network as default.

We have also drafted a Comprehensive Guide with step-by-step instructions to using the NameSys Client. If you have any questions, feel free to ask! If you find any bugs, place report them on our Github page linked at the bottom of our Clients.

We are already aware of two issues in our Client:

  • Emoji domains not yet supported (other non-ASCII domains are fine)
  • NFT Avatars in format eip155:1/erc721:0x not yet supported

We will be fixing these shortly and updating the Client!