Skip to main content

Self-Custody CELO

Account access and reward details for self-custodying holder of CELO on the Celo Mainnet


This guide assumes:

  • You are self-custodying (you hold the private key to your address), and that you have provided that address directly to cLabs. If you are using a custody provider (Anchorage, Coinbase, CoinList, or others), please contact them for directions.

  • Your address is the beneficiary of a ReleaseGold contract, which releases CELO programmatically to a beneficiary over a period of time.

  • You have been informed by cLabs that the ReleaseGold instance corresponding to your address has been deployed.

  • You have your private key held on a Ledger Nano S or Ledger Nano X device, and you have a second such device available for managing a voting key. If you only have a single Ledger available, see below.


Warning: Self-custodying keys has associated security and financial risks. Loss or theft of keys can result in irrecovable loss of funds. This guide also requires technical knowledge. You should be comfortable with using a Command Line Interface (CLI) and understand the basics of how cryptographic network accounts work.


If you have any questions or need assistance with these instructions, please contact cLabs or ask in the #celo-holders channel on Celo's Discord server. Remember that Discord is a public channel: never disclose recovery phrases (also known as backup keys, or mnemonics), private keys, unsantized log output, or personal information.

Please refer to the Ledger Troubleshooting for issues using Ledgers with the Celo CLI.


In this guide, you will:

  • Install the Celo CLI (and optionally, a local node to connect to the network)
  • Access the ReleaseGold account associated with your address using your existing Ledger
  • Authorize a voting key, which you will hold on a new, second Ledger
  • Lock some of the Gold in your ReleaseGold account
  • Use that Locked Gold to vote for Validator Groups to operate Celo's Proof of Stake network (and in doing so be ready to receive epoch rewards of 6% when the community enables them in a forthcoming governance proposal)

Preparing Ledgers

You will need:

  • Your Beneficiary Ledger: One Ledger Nano S or X configured with your beneficiary key (used to produce the address you supplied cLabs). Once you have completed this guide, this will become a "cold wallet" that you can keep offline most of the time.

  • Your Vote Signer Ledger: One Ledger Nano S or X configured with a new, unused key. This will become a "warm wallet" you can use whenever you want to participate in validator elections or governance proposals.

As a first step, follow these instructions for both Ledgers to install the Ledger Celo app, obtain and verify the associated addresses, and (recommended) run a test transaction on the Alfajores test network.


The latest version of the Celo Ledger app is 1.1.8. If you are already using a Ledger with an earlier version installed, please upgrade.

The remainder of this guide assumes you are using the first address available on each Ledger. You can add the flags described in these instructions to commands below to use different addresses.

Using a single Ledger

If you only have a single Ledger, and are comfortable losing the security advantage of keeping the beneficiary key offline when voting, you can configure a second address on the same Ledger as your voting key.

First, read these instructions carefully. Then, whereever you see instructions to connect your Vote Signer Ledger, for each command line containing --useLedger also add --ledgerCustomAddresses "[1]". If in doubt, ask for help.


If you haven't already, open a terminal window and install the Celo CLI:

 npm install -g @celo/celocli

If you have previously installed the CLI, ensure that you are using version 0.0.47 or later:

celocli --version

And if not, upgrade by running the same command as above.

You will now need to point the Celo CLI to a node that is synchronized with the Mainnet network. There are two options:

  • Local Celo Blockchain node: You can run a full node on your local machine which will communicate with other nodes and cryptographically verify all data it receives. Since this approach does not require you to trust the network, it is most secure.

    To do this, follow the tutorial for running a full node (and make sure to pass --usb).

    Then run:

    celocli config:set --node http://localhost:8545
  • cLabs-operated node: As an alternative to using your own node, you can use an existing transaction node service. Forno, operated by cLabs, is one example. While this approach does not require you to deploy a node locally, it requires you to trust cLabs and the remote Forno nodes (in the same way you would trust a centralized web service). An attacker may be able to manipulate data returned to you from the service, which the CLI may rely on to complete operations.

    To use Forno, run this command:

    celocli config:set --node

Locate and verify your ReleaseGold contract address

First, copy the beneficiary address into the clipboard, and set it in an environment variable:


Next, you will find the address of the ReleaseGold contract deployed for your beneficiary address. The ReleaseGold contract has its own address and is separate from the beneficiary address, but there are certain aspects of it that can be controlled only by the beneficiary. For more details, please refer to the Understanding ReleaseGold page.

Open the list of all ReleaseGold deployments and locate your address (use Edit>Find in your browser, then paste the beneficiary address). Copy the matching value next to ContractAddress into your clipboard.

If you cannot locate your address in these mappings, please contact cLabs.

If you have more than one beneficiary address, you'll want to step through this guide and complete the steps for each one separately.

Record the value of the ContractAddress in an environment variable:

export CELO_RG_ADDRESS=<ContractAddress>

You should find your beneficiary account already has a very small CELO balance to pay for transaction fees (values are shown in wei, so For example, 1 CELO = 1000000000000000000):

celocli account:balance $CELO_BENEFICIARY_ADDRESS

Next, check the details of your ReleaseGold contract:

celocli releasecelo:show --contract $CELO_RG_ADDRESS

Verify the configuration, balance, and beneficiary details. You can find an explanation of these parameters on the ReleaseGold page.

If any of these details appear to be incorrect, please contact cLabs, and do not proceed with the remainder of this guide.

If the configuration shows canVote: true, your contract allows you to participate in electing Validator Groups for Celo's Proof of Stake protocol, and potentially earn epoch rewards for doing so. Please continue to follow the remainder of this guide (or you can come back and continue at any time).

Otherwise, you're all set. You don't need to take any further action right now.

Authorize Vote Signer Keys

To allow you to keep your Beneficiary Ledger offline on a day-to-day basis, it’s recommended to use a separate Authorized Vote Signer Account that will vote on behalf of the beneficiary.


A vote signer can either be another Ledger device or a cloud Hardware Security Module (HSM). Explore this guide to learn more about cloud HSM setup and celocli integration.

This is a two step process. First, you create a "proof of possession" that shows that the holder of the beneficiary key also holds the vote signer key. Then, you will use that when the beneficiary signs a transaction authorizing the vote signer key. This proves to the Celo network that a single entity holds both keys.


Connect your Vote Signer Ledger now, unlock it, and open the Celo application.

First obtain your vote signer address:

# Using the Vote Signer Ledger
celocli account:list --useLedger

Your address is listed under Ledger Addresses. Create an environment variable for your vote signer address.


Then create the proof of possession:

# Using the Vote Signer Ledger
celocli account:proof-of-possession --signer $CELO_VOTE_SIGNER_ADDRESS --account $CELO_RG_ADDRESS --useLedger

The Ledger Celo app will ask you to confirm the transaction. Toggle right on the device until you see Sign Message on screen. Press both buttons at the same time to confirm.

Take note of the signature produced by the proof-of-possession command and create an environment variable for it.


Now switch ledgers.


Connect your Beneficiary Ledger now, unlock it, and open the Celo application.

Next, register the ReleaseGold contract as a “Locked Gold” account:

# Using the Beneficiary Ledger
celocli releasecelo:create-account --contract $CELO_RG_ADDRESS --useLedger

You'll need to press right on the Ledger several times to review details of the transactions, then when the device says "Accept and send" press both buttons together.

Check that the ReleaseGold contract address is associated with a registered Locked Gold Account:

celocli account:show $CELO_RG_ADDRESS

Now, using the proof-of-possession you generated above, as the Locked Gold Account account, you will authorize the vote signing key to vote on the Locked Gold Account's behalf:

# Using the Beneficiary Ledger
celocli releasecelo:authorize --contract $CELO_RG_ADDRESS --role=vote --signer $CELO_VOTE_SIGNER_ADDRESS --signature $CELO_VOTE_SIGNER_SIGNATURE --useLedger

Finally, verify that your signer was correctly authorized:

celocli account:show $CELO_RG_ADDRESS

The vote address under authorizedSigners should match $CELO_VOTE_SIGNER_ADDRESS.

The ReleaseGold contract was funded with an additional 1 CELO that it sends to the first vote signer account to be authorized. This allows the vote signer account to cover transaction fees. You can confirm this:

celocli account:balance $CELO_VOTE_SIGNER_ADDRESS

Warning: If you authorize a second vote signer, it will not be automatically funded by the ReleaseGold contract. You will need to transfer a fraction of 1 CELO from your beneficiary address to it in order to cover transaction fees when using it.


To vote for Validator Groups and on governance proposals you will need to lock CELO. This is to keep the network secure by making sure each unit of CELO can only be used to vote once.

Specify the amount of CELO you wish to lock (don’t include the < > braces). All amounts are given as wei, i.e units of 10^-18 CELO. For example, 1 CELO = 1000000000000000000.


Make sure to leave at least 1 CELO unlocked to pay for transaction fees.

# Using the Beneficiary Ledger
celocli releasecelo:locked-gold --contract $CELO_RG_ADDRESS --action lock --useLedger --value <CELO-GOLD-AMOUNT>

Check that your CELO was successfully locked.

celocli lockedgold:show $CELO_RG_ADDRESS

Vote for a Validator Group

Similar to staking or delegating in other Proof of Stake cryptocurrency protocols, CELO holders can lock CELO and vote for Validator Groups on the Celo network. By doing this, not only do you contribute to the health and security of the network, but you can also earn epoch rewards.

For more details, check out the Voting for Validators page, which contains useful background on how voting Validator Elections work, as well as more guidance on how to select a Validator Group to vote for. For now, all you need to know is that:

  • in Celo, CELO holders vote for Validator Groups, not Validators directly
  • you only earn epoch rewards if the Validator Group you voted gets at least 1 Validator elected

Keeping this in mind, you will need to find a Validator Group to vote for, and copy its address. You can find this information on community validator explorers such as the cLabs Validator explorer and Bi23 Labs' thecelo dashboard.

You can also see registered Validator Groups through the Celo CLI. This will display a list of Validator Groups, the number of votes they have received, the number of additional votes they are able to receive, and whether or not they are eligible to elect Validators:

celocli election:list

Once you have found one or more Validator Groups you’d like to vote for, create an environment variable for its Group address (don’t include the < > braces):


For each vote you will need to select the amount of locked CELO you wish to vote with. You can lookup your balance again if you need to:

celocli account:balance $CELO_RG_ADDRESS

All CELO amounts should be expressed in wei: that means 1 CELO = 1000000000000000000. Don’t include the < > braces in the line below.

To vote, you will use your vote signer key, which is voting on behalf of your Locked Gold account.


Connect your Vote Signer Ledger now, unlock it, and open the Celo application.

# Using the Vote Signer Ledger
celocli election:vote --from $CELO_VOTE_SIGNER_ADDRESS --for $CELO_VALIDATOR_GROUP_ADDRESS --useLedger --value <CELO-GOLD-AMOUNT>

Verify that your votes were cast successfully. Since your Vote Signer account votes on behalf of the Celo Locked Gold account, you want to check the election status for that account:

celocli election:show $CELO_RG_ADDRESS --voter

Your locked CELO votes should be displayed next to pending under votes.

The next day: Activate your Vote

Your vote will apply starting at the next Validator Election, held once per day, and will continue to apply at each subsequent election until you change it.

After that election has occurred, you will need to activate your vote. This will allow you to receive epoch rewards if in that election (or at any subsequent one, until you change your vote) the Validator Group for which you voted elected at least one Validator. Rewards will get added to your votes for that Group and will compound automatically.


Epoch lengths in Mainnet are set to be the number of blocks produced in a day. As a result, votes may need to be activated up to 24 hours after they are cast.

Check that your votes were cast in a previous epoch:

celocli election:show $CELO_RG_ADDRESS --voter

Your vote should be displayed next to pending under votes.


Connect your Vote Signer Ledger now, unlock it, and open the Celo application.

Now activate your votes:

# Using the Vote Signer Ledger
# You must do this in an epoch after the one you voted in: this may take up to 24h
celocli election:activate --from $CELO_VOTE_SIGNER_ADDRESS --useLedger

If you run election:show again, your vote should be displayed next to active under votes.

Congratulations! You're all set.

At the end of the epoch following your vote activation, you may receive voter rewards (if at least one Validator from the Validator Group for which you voted was elected).

You can see rewards using:

celocli rewards:show --voter $CELO_RG_ADDRESS

Or by searching for your ReleaseGold address on the Block Explorer and clicking the "Celo Info" tab.

Next Steps

You are now set up to participate in the Celo network!

You might want to read more about choosing a Validator Group to vote for, and how voter rewards are calculated. You can vote for up to ten different Groups from a single account.

Now you've locked CELO, you can use it to participate in voting for or against Governance proposals. You can do this without affecting any vote you have made for Validator Groups.

You can also read more about how Celo's Proof of Stake and on-chain Governance mechanisms work.

Revoking Votes

At any point you can revoke votes cast for a Validator Group. For example, a Group may be performing poorly and affecting your rewards, and you may prefer to vote for another Group.


When you revoke your votes you will stop receiving voter rewards.

Specify the amount of CELO you wish to revoke (don’t include the < > braces). All CELO amounts should be expressed in 18 decimal places. For example, 1 CELO = 1000000000000000000.


Connect your Vote Signer Ledger now, unlock it, and open the Celo application.

Revoke votes for the Group:

# Using the Vote Signer Ledger
celocli election:revoke --from $CELO_VOTE_SIGNER_ADDRESS --for $CELO_VALIDATOR_GROUP_ADDRESS --value <CELO-GOLD-AMOUNT> --useLedger

You can immediately re-use this locked CELO to vote for another Group.

Unlocking and Withdrawing

At some point, the terms of your ReleaseGold contract will allow you to withdraw funds and transfer them to your beneficiary address.

There are actually several steps to this process:

  1. First, revoke all outstanding votes as above (including for governance proposals)
  2. Unlock the non-voting Locked Gold, starting a 72 hour unlocking period
  3. After the three day unlocking period is complete, withdraw the CELO back to the ReleaseGold contract
  4. Assuming vesting and distribution requirements are met, withdraw the CELO to the beneficiary address

Check the current status of outstanding votes:

celocli election:show $CELO_RG_ADDRESS --voter

You can view the balance of locked CELO:

celocli account:balance $CELO_RG_ADDRESS

Connect your Beneficiary Ledger now, unlock it, and open the Celo application.

Assuming you have non-voting Locked Gold, you can initiate the process to unlock:

# Using the Beneficiary Ledger
celocli releasecelo:locked-gold --contract $CELO_RG_ADDRESS --action unlock --useLedger --value <CELO-GOLD-AMOUNT>

After the 72 hour unlocking period has passed, withdraw the CELO back to the ReleaseGold contract:

# Using the Beneficiary Ledger
celocli releasecelo:locked-gold --contract $CELO_RG_ADDRESS --action withdraw --useLedger --value <CELO-GOLD-AMOUNT>

Finally, request that the ReleaseGold contract transfer an amount to your beneficiary address:

# Using the Beneficiary Ledger
celocli releasecelo:withdraw --contract $CELO_RG_ADDRESS --useLedger --value <CELO-GOLD-AMOUNT>

To vote with any CELO in your beneficiary account, you'll want to register it as a Locked Gold Acccount, authorize a new vote signing key for it, then lock CELO.