By Alex Miller, Encryption Engineer

EigenLayer is an exciting new architecture which lets developers bootstrap decentralized applications by outsourcing security and operations to collateralized service providers. Much could be said about the myriad use cases that EigenLayer enables, but I will leave those for you to imagine1. Instead, this article discusses how EigenLayer works, and how to safely become an operator.

EigenLayer and its Ecosystem

EigenLayer itself is a set of smart contracts on Ethereum which balance power and trust throughout a broader ecosystem comprised of three main actor types:

  • AVSs (actively validated services) are applications which run parallel to EigenLayer and integrate into it through their own contracts. These contracts must communicate with EigenLayer contracts via a series of hooks, which allow AVSs to manage who is doing work, and issue rewards/penalties2. This article focuses on one such hook: registration.
  • Operators provide service to AVSs. Once registered, operators receive rewards for doing some agreed-upon work and cryptographically attesting to it. Operators are analogous to block proposers in a proof-of-stake blockchain; if an operator provably misbehaves (or malfunctions), it is “slashed”, meaning some portion of its delegated stake is taken away.
  • Delegators collateralize operators by locking some tokens of value and associating themselves with the operator on EigenLayer. If an operator is slashed, its delegators lose tokens, which means the operator’s reward rate decreases3. Delegation is an implicit vote of confidence that the delegator is making toward an operator. A delegator may only choose one operator at a time4, and the operator may choose any number of AVSs in which to operate. Delegators have no technical mechanism to prevent their operator from choosing higher-risk AVSs or being slashed, so it behooves delegators to choose a trustworthy operator.

Registering with an AVS

Any Ethereum address may become an EigenLayer operator by calling registerAsOperator on EigenLayer’s DelegationManager contract. After that, the operator will need to register with the AVS itself. This is done via the AVS’ ServiceManager contract, whose address can be found by visiting the AVS directory page and clicking on the AVS - the associated ServiceManager contract is responsible for managing the AVS’ operator set in the eyes of EigenLayer.

The AVS-operator registration call is made by the ServiceManager contract to the EigenLayer AVSDirectory contract via registerOperatorToAVS. This call forwards the operator’s signature over a standard message5 and results in the operator being associated with the AVS. At this point, the link has been made on EigenLayer, so when the AVS pushes rewards or slashing events2 they will flow through this connection and simultaneously affect the operator and its delegates, if applicable.

A given AVS may not allow direct access to its ServiceManager contract, and may instead expose a custom registration contract which ensures the prospective operator meets some set of criteria before registering. In the example of EigenDA (the first AVS, created by the EigenLayer team), an operator must gather enough stake to join one or more “quorums”, and then call registerOperator6 in the EigenDA RegistryCoordinator contract. The registration process for EigenDA is visualized in the following diagram.

EigenDA registration

AVS registration contracts will often have bespoke methods for onboarding. This is because AVSs function independently of EigenLayer itself, and define their own specific criteria of who can provide service, and under what conditions. Generally, operators should familiarize themselves with the registration process for each AVS in which they wish to operate, and not take a one-size-fits-all approach.

Operator vs AVS Keys

The association in EigenLayer is between the operator key7 and an AVS’ ServiceManager contract, where an operator key is a normal Ethereum EoA, identified by its address. Typically, an operator must re-use this key for all AVS registrations, so it should be stored securely!

Doing work on an AVS involves running software distributed by that AVS, which will generally require high uptime. Thus, an operator will need to run an internet-addressable service, and will need two keys8: the operator key (a reusable “cold” key for registration, rewards, and slashing events), and the AVS key (a “hot” key for signing AVS-specific work). For EigenDA, the latter is a BLS key on the BN254 curve, which can be generated using the EigenLayer CLI9; the association10 between AVS and operator keys is made by calling registerOperator in the EigenDA RegistryCoordinator contract.

Operator Key Security

The associations described above can lead to some higher risk situations if the operator key is not used with care. Here’s a theoretical example to highlight this risk.

Suppose Alice wishes to go out on the risk curve and finds a high-yielding AVS that has a sketchy website, but requires little work and has slashing conditions with which she is comfortable2. Alice gathers some stake behind her operator key and is ready to register with the AVS. However, she doesn’t really understand its registration process on a smart contract level, and doesn’t have time to evaluate it, so she decides to use software provided by the AVS creators to generate a registration transaction (as a non-sketchy example, here is EigenDA’s registration CLI which does exactly this). The AVS’ registration CLI requires her to sign a message with her operator key, so she gives it access to do that. The CLI makes an Ethereum transaction and broadcasts it on-chain. She verifies that her operator is registered with the AVS on EigenLayer and removes the operator key from her box. Everything looks good so far.

The operator’s rewards balance starts going up - awesome! But one day Alice notices that her EigenLayer balance has dropped. She checks the AVS and sees that it has not slashed her operator. However, she notices that her operator unwittingly joined an entirely different AVS and was slashed on it. What could have happened?

Well, that AVS was sketchy indeed, but not for its own public slashing conditions. In outsourcing registration to its CLI, Alice downloaded malware that sent her operator key to a server before broadcasting the registration transaction. With the operator key in hand, attackers were able to join a different, malicious AVS, which had extremely large and permissive slashing conditions. They generated a separate AVS key and misbehaved, so EigenLayer slashed Alice’s operator and took the stake she had intended for the original AVS.

This scenario is just a hypothetical, but it is entirely plausible if an operator isn’t careful with its operator key. Remember that delegators have no way to enforce which AVSs an operator may join, so the operator key is a powerful object in the EigenLayer system and must be treated with care.

Safe Registration Example: EigenDA

The hypothetical above highlights the importance of separating registration from AVS work. If Alice had not run third party software in an online box, she would have stayed in the original AVS and had no issues. The operator got slashed because Alice coupled two processes with very different risk profiles.

Fortunately, these processes are typically easy to decouple: keep the operator key offline, and sign pre-built registration messages. To illustrate, here’s a registration example for EigenDA using contract addresses from the Holesky testnet.

The first step with all AVS registrations is to sign the following standard EIP712 message from the operator key.

{
  "types": {
    "EIP712Domain": [
      { "name": "name", "type": "string" },
      { "name": "chainId", "type": "uint256" },
      { "name": "verifyingContract", "type": "address" }
    ],
    "OperatorAVSRegistration": [
      { "name": "operator", "type": "address" },
      { "name": "avs", "type": "address" },
      { "name": "salt", "type": "bytes32" },
      { "name": "expiry", "type": "uint256" }
    ]
  },
  "primaryType": "OperatorAVSRegistration",
  "domain": {
    "name": "EigenLayer",
    "chainId": 1,
    // EigenLayer: AVSDirectory 
    "verifyingContract": "0x135dda560e946695d6f155dacafc6f1f25c1f5af"
  },
  "message": {
    "operator": {operator address},
    // EigenDA: ServiceManager contract
    "avs": "0x870679e138bcdf293b7ff14dd44b70fc97e12fc0",
    "salt": {random 32 bytes},
    "expiry": {future UNIX timestamp}
  }
}

This ECDSA signature is made on the secp256k1 curve (i.e. a standard Ethereum signature) and will be verified at registration by EigenLayer’s AVSDirectory here. The message associates the operator key with EigenDA’s ServiceManager contract (0x870679e138bcdf293b7ff14dd44b70fc97e12fc0 on mainnet, where chainID=1).

Next, the operator signs a different EIP712 message with its AVS key. This message is specific to EigenDA.

{
  "types": {
    "EIP712Domain": [
      { "name": "name", "type": "string" },
      { "name": "version", "type": "string" },
      { "name": "chainId", "type": "uint256" },
      { "name": "verifyingContract", "type": "address" }
    ],
    "BN254PubkeyRegistration": [
      { "name": "operator", "type": "address" },
    ]
  },
  "primaryType": "BN254PubkeyRegistration",
  "domain": {
    "name": "AVSRegistryCoordinator",
    "chainId": 1,
    // RegistryCoordinator
    "verifyingContract": "0x0baac79acd45a023e19345c352d8a7a83c4e5656"
  },
  "message": {
    "operator": {operator address},
  }
}

The resulting signature will be a G1 point on BN254 (with two 256 bit11 fields) and is verified by the EigenDA RegistryCoordinator contract here. The message associates the operator key with the signer of the message: the operator’s AVS key.

The operator must also extract the raw bytes of its BLS key’s G1 pubkey (two 256 bit fields) and G2 pubkey (four 256 bit fields). With all of this data in hand, the operator should be ready to register with EigenDA (assuming it has enough stake for the desired quorum(s)) by calling registerOperator on EigenDA’s RegistryCoordinator contract.

Here is decoded calldata (in YAML format) from one of Unit 410’s testnet operators’ registrations:

function: registerOperator
params:
  # quorumNumbers specify which quorum(s) we wish to join
  - name: quorumNumbers
    type: bytes
    # Register for quorum 1 (WETH)
    value: "0x01"
  # socket defines an endpoint by which to reach our EigenDA operator node
  - name: socket
    type: string
    value: "eigenda-holesky-validator-1-unit410-com:32005;32004"
  # params contains all of the signature data for making the operator<>AVS key association
  - name: params
    type: tuple
    tuple:
    # This is the signature made by our AVS key, which associates it with our operator key
    - name: pubkeyRegistrationSignature
      type: tuple
      tuple:
      - name: X
        type: uint256
        value: 0x2eada34ce2202bf43fc3be5576360123c0bbf23befaaebfc2326af4baa6008cb
      - name: Y
        type: uint256
        value: 0x207b2dba918721490c2dee081ba9b8a88e5f394b9ba888beb4e62872a9323e00
    # This is the G1 pubkey of our AVS key
    - name: pubkeyG1
      type: tuple
      tuple:
      - name: X
        type: uint256
        value: 0x04ef143098f4402be993e897fc64af15473da13dc6cb6ba4dd512f2da307b6ed
      - name: Y
        type: uint256
        value: 0x2af017e604e5f901f017337b2fa9f95df358f365b1e259fa3b0058bc0647a3f8
    # This is the G2 pubkey of our AVS key
    - name: pubkeyG2
      type: tuple
      tuple:
      - name: X
        type: uint256[2]
        value:
        - 0x0e88eabe861da1a7a9ef84b14ec284349bf9ff2813ab560e3e96efd106b388fe
        - 0x23f11b380f15ec41ff13505dbd2ec99d72d5bad19cf16fe64c6266e42677c5ef
      - name: Y
        type: uint256[2]
        value:
        - 0x16d3cf497b1b8b753bb4b7852b7203bdda93c67162a46de1ac99b99ea2083374
        - 0x0fc144392371cbd2b54a6716af9f4d18b3a7e11a322fe39a98df597219add499
    # This is the ECDSA signature made by our operator, which associates it with the EigenDA ServiceManager contract    
    - name: operatorSignature
        type: tuple
        tuple:
        - name: signature
          type: bytes
          value: 0xc51c5da37000215eeb2405fa322d3dc6b058aa7437b22c84ec8f6115097538e76c9c948a0e2c7d6c21d514480406dd27d8e1fe178baa1d9366a64fbe893c20231b
        - name: salt
          type: bytes32
          value: 0x3c2a7f4c717798aa56228aa6df60565eec1b5244c96a4d688c245d54ef3ecae8
        - name: expiry
          type: uint256
          value: 1907982515

The above payload is serialized into an Ethereum transaction and, once broadcast, registers the operator and AVS keys with EigenDA. Here is the on-chain transaction.

Separating Concerns and Choosing Wisely

At Unit 410, we generate and sign from all operator keys in a cold (i.e. airgapped) environment. These keys never touch the internet and are inaccessible at rest. Unsigned transactions are crafted (as shown above), then transmitted to the cold environment in a highly secure process which includes a series of validations. Signed transactions are transmitted from cold to hot and then broadcast. In cases where we must cross-sign AVS and operator keys, we load the AVS keys into the cold environment12 and run the same signing process.

Separation of registration from operation is possible because EigenLayer lives entirely on Ethereum, and operators are able to inspect exactly how registrations work on-chain for each AVS13 - they just need to roll up their sleeves and read the contracts. EigenLayer is a complex system and there are many risks which require careful consideration, with key management being just one. Unit 410 is a leading operator in the EigenLayer ecosystem and thinks deeply about these risks and their mitigations.

I hope this post helps you better understand how this system works. EigenLayer might be hot right now, but your keys don’t need to be.

If topics like this are interesting to you, check out our open roles here.


Footnotes

  1. If you need inspiration, check out their AVS (a.k.a. “application”) directory

  2. At the time of writing, rewards are still in development and slashing is not fully architected. Since details for both are currently fuzzy, they will not be discussed at length here.  2 3

  3. Operator rewards are proportional to stake. 

  4. A delegator may undelegate or withdraw stake from an operator at any time, but will not receive their tokens for at least 7 days after doing so. 

  5. This is an EIP712 message containing linking the AVS service manager address and the operator address, signed by the operator. See calculateOperatorAVSRegistrationDigestHash in the AVSDirectory contract

  6. There is also registerWithChurn, which must be used if the quorum has reached its maximum number of operators. Doing so requires a call to the “churn approver”, which is a hosted service run by the AVS (here is EigenDA’s churner code). Its job is to authorize new operators by providing a signed message over which operator(s) will be kicked out of the active set in order for the new operator to join. Typically this happens only if the new operator has a higher stake than the lowest stake operator in the set, for each quorum which is maxed out. 

  7. The operator key is what calls registerAsOperator in the EigenLayer DelegationManager contract. 

  8. Technically an AVS could use the same key for both purposes, but if an AVS requires this, it may be best to stay far away from it. 

  9. Typically, EigenLayer CLI is used to generate an AVS key. The result is an encrypted file with a specific format, which will likely be required by the AVS software being run. This is true for EigenDA, i.e. one cannot just generate a raw BLS key and use it out of the box. 

  10. The BLS key makes a signature over a payload which includes the operator key, i.e. it is a one-directional association. However, the operator key’s signature is included in this same request, so the bidirectional mapping is implicit. 

  11. Technically, these are 254 bit values, as the curve modulus is 254 (hence the name BN254). However, they are typically packed into 256 bit, or 32 byte, fields when used in software. 

  12. This does not make the AVS keys cold! We still consider AVS keys “insecure” because they must live in an online environment, although we do take various precautions to avoid exposing them. 

  13. This assumes precompiled contract code is available for inspection for the AVS of choice. If it isn’t, that is a red flag and likely a reason not to register.