ENS-verified
The ENS-verified trust layer (Layer 1 in the trust spectrum) raises a Human Proof from “some wallet attested” to “a wallet with a public ENS name attested”. The attestation’s proofMethod field carries the value ens-verified.
What “verified” means here
Section titled “What “verified” means here”A wallet’s ENS name is verified iff:
- It has a reverse record (
address -> name). - Forward resolution of that name (
name -> address) round-trips back to the wallet.
The forward check is the spoof guard: anyone can set their reverse record to “vitalik.eth” but only the actual ENS owner controls forward resolution.
Pre-flight a single resolution
Section titled “Pre-flight a single resolution”const ens = await fidemark.resolveENS(walletAddress);// { name: "alice.eth", address: "0x..." } or nullens = fidemark.resolve_ens(wallet_address)# VerifiedENS(name="alice.eth", address="0x...") or Noneens, err := client.ResolveENS(ctx, walletAddress)// (*VerifiedENS, nil) or (nil, nil) when unverifiablenull / None / nil means the wallet has no verifiable ENS: either no reverse record, no forward record, or the two disagree.
Issue a Layer-1 attestation
Section titled “Issue a Layer-1 attestation”Complete, copy-pasteable runnable. The Ethereum mainnet RPC is required for the ENS round-trip; see Configuration for every constructor option.
import { Fidemark, getNetwork } from "@fidemark/sdk";import { JsonRpcProvider } from "ethers";
const fidemark = new Fidemark({ network: getNetwork("base-sepolia"), privateKey: process.env.PRIVATE_KEY, ensProvider: new JsonRpcProvider(process.env.ENS_RPC_URL),});
const result = await fidemark.attestHumanWithENS({ content: myArticle, contentType: "text/article",});
// result.uid : the attestation UID// result.verifyUrl : public verify URL// result.ens : { name, address } as verified at attest timeimport osfrom fidemark import AttestHumanInput, Fidemark, get_network
fidemark = Fidemark( network=get_network("base-sepolia"), private_key=os.environ["PRIVATE_KEY"], ens_provider_url=os.environ["ENS_RPC_URL"],)
result, ens = fidemark.attest_human_with_ens(AttestHumanInput( content=my_article, content_type="text/article",))import ( "context" "log" "os"
"github.com/fidemark/sdk-go/fidemark")
network, _ := fidemark.GetNetwork("base-sepolia")client, err := fidemark.New(fidemark.Config{ Network: network, PrivateKey: os.Getenv("PRIVATE_KEY"), ENSProviderURL: os.Getenv("ENS_RPC_URL"),})if err != nil { log.Fatal(err) }
res, ens, err := client.AttestHumanWithENS(context.Background(), fidemark.AttestHumanInput{ Content: []byte(myArticle), ContentType: "text/article",})The helper:
- Resolves the signer’s ENS round-trip.
- Throws
INVALID_INPUTif the wallet has no verifiable ENS. - Otherwise, attests with
proofMethod = "ens-verified".
Setup requirements
Section titled “Setup requirements”ensProvider/ens_provider_url/ENSProviderURLin the Fidemark constructor: an Ethereum mainnet RPC. ENS lives on Ethereum, not Base. Keep them separate.- Resolver allowlist:
ens-verifiedis allowlisted on the deployed Fidemark resolvers on Base and Base Sepolia. Nothing to do at the consumer level.
Verifier behavior
Section titled “Verifier behavior”Verifiers (the verify page, third-party tools) typically re-check the wallet’s current ENS at view time. ENS records can change: “this wallet had ENS name X at time T” is a snapshot, not a permanent claim. The verify page renders the current verified name (if any) next to a Layer-1 attestation; mismatches surface as “ENS verification failed (record changed)”.