Link a Polygon Address to Your BABY Address

Proof-of-Possession (PoP) establishes ownership of both your Polygon address and BABY address. Note that only Polygon addresses that are holding the Bitcoin staking Pioneer Pass NFT are eligible for the airdrop boost.

This guide demonstrates how to generate PoP, validate it, submit it to the API, and remove it if you need to link your Polygon address to a different BABY address.

This guide assumes that you have created a Babylon address to receive the airdrop using the Babylon Address CLI Creation guide. Please ensure that you have access to your keyring before proceeding.

PoP format for NFT claimers

The JSON format of the PoP for NFT claimers looks like as follows:

{
  "babyAddress": "bbn1uxx48k7lzrjsy8t6l34m76jzzgjee2m35ppfhh",
  "polygonAddress": "0xa2e83b3d772901ed37d08bbe0f2e78e28e964679",
  "polygonSignBaby": "0x039ef5d42a426e91766de943a67a377c07fd6392a3c94b6d31a7425d2a1a159215e5aa748460e292f8b1c56dcdb5e58b4b19371fabc0542c86c296df96d51b601b",
  "babySignPolygon": "VvjnZkZc/n45vp5ahVhjEvQN2pYFH1tlj2MLAhin33U7NVKX6T5iHSS+Qoh7nBaxpykJZ33u4G5z4A9pfiPtYw==",
  "babyPublicKey": "AuFdQiPcFg40hsz7RUMLFvScNlKVmz01g/yt982y75mJ"
}

Detailed specification of each field:

  • babyAddress: The Bech-32 encoded BABY address.
  • polygonAddress: The hex encoded Polygon address that holds the Pioneer Pass NFT(s).
  • polygonSignBaby: The Polygon signature compatible with the personal_sign format: personal Namespace | go-ethereum. The signature must be made over the babyAddress (i.e., sign the address string you specified above for the Babylon address) and be hex encoded.
  • babySignPolygon: The Base64 encoded ADR36 signature made by the BABY key over polygonAddress (i.e., sign the address string you specified above for the Polygon address).
  • babyPublicKey: The Base64 encoded BABY public key, corresponding to the babyAddress.

Note: the BABY address and Polygon address association must be unique in the airdrop claim.

1. Generate PoP

1.1. Setup the Staker CLI program

First, clone the btc-staker repository:

git clone https://github.com/babylonlabs-io/btc-staker.git
Cloning into 'btc-staker'...

Next, checkout to the v0.15.2 release tag::

cd btc-staker
git checkout v0.15.2

In the root directory of btc-staker, install the binaries using make install:

make install
CGO_CFLAGS="-O -D__BLST_PORTABLE__" go install -mod=readonly --tags "" --ldflags ''  ./...

Verify the installation by running stakercli --help.

stakercli  --help
NAME:
   stakercli - Bitcoin staking controller
USAGE:
   stakercli [global options] command [command options] [arguments...]
COMMANDS:
   help, h  Shows a list of commands or help for one command
   Admin:
     admin, ad  Different utility and admin commands
   Daemon commands:
     daemon, dn  More advanced commands which require staker daemon to be running.
   PoP commands:
     pop  Commands realted to generation and verification of the Proof of Possession
   transaction commands:
     transaction, tr  Commands related to Babylon BTC transactions Staking/Unbonding/Slashing
GLOBAL OPTIONS:
   --btc-network value            Bitcoin network on which staking should take place (default: "testnet3")
   --btc-wallet-host value        Bitcoin wallet rpc host (default: "127.0.0.1:18554")
   --btc-wallet-rpc-user value    Bitcoin wallet rpc user (default: "user")
   --btc-wallet-rpc-pass value    Bitcoin wallet rpc password (default: "pass")
   --btc-wallet-passphrase value  Bitcoin wallet passphrase
   --help, -h                     show help

1.2. Create ADR36 signature over Polygon address

First, we partially fill the PoP by creating babySignPolygon, which is an ADR36 signature signed by the BABY key over the Polygon address:

stakercli pop sc --baby-address bbn1uxx48k7lzrjsy8t6l34m76jzzgjee2m35ppfhh \
  --keyring-dir /path/to/keyring --keyring-backend file \
  --msg '0xa2e83b3d772901ed37d08bbe0f2e78e28e964679'
  • --baby-address is the Bech-32 BABY address.
  • --keyring-dir is the directory on which the BABY key that will receive the airdrop is stored. Note that this should not contain the direct parent directory of the key files (e.g., keyring-xxx). For example, if the keyring file is stored under ~/.babylond/keyring-file/, then ~/.babylond/ should be specified in the flag.
  • --keyring-backend is the backend of the BABY key. It should be the same as the one when the key was created.
  • --msg is the hex encoded Polygon address which owns the NFT.

This command will produce json output like the follows:

{
    "babyAddress": "bbn1uxx48k7lzrjsy8t6l34m76jzzgjee2m35ppfhh",
    "babySignature": "VvjnZkZc/n45vp5ahVhjEvQN2pYFH1tlj2MLAhin33U7NVKX6T5iHSS+Qoh7nBaxpykJZ33u4G5z4A9pfiPtYw==",
    "babyPublicKey": "AuFdQiPcFg40hsz7RUMLFvScNlKVmz01g/yt982y75mJ"
}

where:

  • babyAddress is the Bech-32 encoded BABY address.
  • babySignature is the Base64 encoded ADR36 signature made by the BABY key.
  • babyPublicKey is the Base64 encoded BABY public key corresponding to the babyAddress.

Note that thebabySignature corresponds to the field of babySignPolygon in the PoP data structure.

1.3 Create the Polygon signature over the BABY address

Next, we fill the remaining parts of the PoP by creating polySignBaby, which is a signature signed by the Polygon key over the BABY address.

There are two ways to generate the signature for a given Polygon address depending on how the NFT was claimed:

Browser web wallet

If the NFT was claimed through browser web wallet, you need to go to the web application which enables signing arbitrary data following EIP-191.

Note that MyEtherWallet is not using personal_sign method in Metamask. Therefore, cannot be used to generate polySignBaby. An alternative is to use this web app instead. Source & a demo here.

Local keystore

If the NFT was claimed through local keystore, e.g., geth keystore, you need to use a personal name space (personal Namespace | go-ethereum) and the personal_sign method to create a signature as follows:

curl --data '{"id": 3, "jsonrpc": "2.0", "method": "account_signData", "params": ["data/plain", "0xa2e83b3d772901ed37d08bbe0f2e78e28e964679","bbn1uxx48k7lzrjsy8t6l34m76jzzgjee2m35ppfhh"]}' -X POST localhost:8550

where:

  • the first parameter (starting with 0x) is the Polygon address that is doing the signing, and
  • the second parameter is the data to be signed, which in this case is the BABY address.

This step should produce a tuple:

{
  "polygonAddress": "0xa2e83b3d772901ed37d08bbe0f2e78e28e964679",
  "polygonSignBaby": "0x039ef5d42a426e91766de943a67a377c07fd6392a3c94b6d31a7425d2a1a159215e5aa748460e292f8b1c56dcdb5e58b4b19371fabc0542c86c296df96d51b601b",
}

2. Submit PoP via API

To register the PoP, you need to construct the PoP payload with all the data generated from Step 1 and send it to the API endpoint as follows:

curl -X POST 'https://airdrop-api.babylon.foundation/pop/baby-polygon' \
-H 'Content-Type: application/json' \
-d '{
  "babyAddress": "bbn1uxx48k7lzrjsy8t6l34m76jzzgjee2m35ppfhh",
  "polygonAddress": "0xa2e83b3d772901ed37d08bbe0f2e78e28e964679",
  "polygonSignBaby": "0x039ef5d42a426e91766de943a67a377c07fd6392a3c94b6d31a7425d2a1a159215e5aa748460e292f8b1c56dcdb5e58b4b19371fabc0542c86c296df96d51b601b",
  "babySignPolygon": "VvjnZkZc/n45vp5ahVhjEvQN2pYFH1tlj2MLAhin33U7NVKX6T5iHSS+Qoh7nBaxpykJZ33u4G5z4A9pfiPtYw==",
  "babyPublicKey": "AuFdQiPcFg40hsz7RUMLFvScNlKVmz01g/yt982y75mJ"
}'

In case of success, the API will return a 200 status code and the following response:

{"message": "ok"}

If your Polygon address does not hold a Pioneer Pass NFT, the API will return a 400 status code and the following response:

{"message":"No Pioneer Pass NFT holdings","code":400}

3. Deleting the Proof of Possession

If you wish to change the BABY address associated with the Polygon address holding the NFT, you can delete the already registered PoP and then register a new one with a different BABY address.

3.1. Retrieve the Deletion Message

The first step to deleting your PoP is to retrieve a message containing a custom nonce from the Babylon API. You can obtain this by calling the following endpoint (replace your-baby-address with the BABY address used in the submitted PoP):

curl -X GET 'https://airdrop-api.babylon.foundation/pop/baby-sign-message?address=your-baby-address'

where your-baby-address is the Babylon for which you already registered PoP.

Example response:

{"message":"Welcome to Babylon Airdrop!\\r\\nAddress: bbn1uxx48k7lzrjsy8t6l34m76jzzgjee2m35ppfhh\\r\\nNonce: 0f7c99f145"}

3.2. Sign the response message

To prove the ownership of the BABY key that intends to delete the existing PoP, you need to cryptographically sign the entire string literal found in the message attribute of the previous JSON response.

You can accomplish this by running stakercli pop sc command (recall the need to install this program in Section 1.1.):

stakercli pop sc --baby-address bbn1uxx48k7lzrjsy8t6l34m76jzzgjee2m35ppfhh \\
  --keyring-dir /path/to/keyring --keyring-backend file \\
  --msg 'Welcome to Babylon Airdrop!\\r\\nAddress: bbn1uxx48k7lzrjsy8t6l34m76jzzgjee2m35ppfhh\\r\\nNonce: 0f7c99f145'

where --msg is the message received from Step 3.1. It is important that string is closed in single quotes.

This command will generate the following data over the provided message:

{
    "babyAddress": "bbn1uxx48k7lzrjsy8t6l34m76jzzgjee2m35ppfhh",
    "babySignature": "zuuNchJnEz31HZyBX+kftsBSuQJJnrjA2vBQTmOctVZAjaNNvVpTrItRBSxmUJKHN+E+4POyjnxTrfBXhgV9MA==",
    "babyPublicKey": "AtU4i0OjGcvtdeiJjygOaHmxk9JvNKZVipu46I6zLi/z"
}

Now create the payload and send a DELETE request to the API:

curl -X DELETE 'https://airdrop-api.babylon.foundation/pop/baby-polygon' \
-H 'Content-Type: application/json' \
-d '{
  "babyAddress": "bbn1uxx48k7lzrjsy8t6l34m76jzzgjee2m35ppfhh",
  "babySignature": "kS5WelO48HFhNdhdVDQ4cNMDgiANzpk4aWtwqGCAr7kdo97yNQdcMg/dbT4ZmJmhi57U0LdXcBahTOZf0dTO5g==",
  "babyPublicKey": "AkFPu2WhXw59YxaZjB546+FLGY/4K/IWKnUqa0fGgXd4",
  "polygonAddress": "0xa2e83b3d772901ed37d08bbe0f2e78e28e964679"
}'

In case of success, the API will return a 200 status code and the following response:

To ensure deletion, getting PoP by your BABY wallet address will return an empty array:

curl -X GET 'https://airdrop-api.babylon.foundation/pop/baby-polygon?babyAddress=bbn1uxx48k7lzrjsy8t6l34m76jzzgjee2m35ppfhh'
[]

Now, you can submit a new PoP with a new BABY address.