Link a Polygon Address to Your BABY Address

Before proceeding with this guide, please make sure you sign the terms first.

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}

To make sure your polygon address was successfully registered, you can query it by the associated baby address.

curl -X 'GET' 'https://airdrop-api.babylon.foundation/pop/baby-polygon?babyAddress=bbn1kg3hw2trn4lpv4kg92tafqpwq4lpea2ep5d9r4' -H 'accept: application/json'

The API will return the following response (formatted by jq):

[
  {
    "babyAddress": "bbn1kg3hw2trn4lpv4kg92tafqpwq4lpea2ep5d9r4",
    "polygonAddress": "0x74b9b4ee0caaeea82c6b35385dc9f7c7d57fd9f3",
    "babyPublicKey": {
      "type": "tendermint/PubKeySecp256k1",
      "value": "A7pgdC3q+IOeeavUqdhYpupU2U/qL+kEu0wDxXLhFs6m"
    }
  }
]

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.

Search Your Wallet Address Here

Wallet 1

bbn10rh86jtzxf7m6xqyj66s98837ry8xzsppd9c7a

Wallet 2

bbn1wq7zn8zv7n4hzwpp3058aw2aewnqqwpkrfxyf6

Wallet 3

bbn1rl5gkegkvf6sxsncgw4qenrq0eh5eha33svdug

Wallet 4

bbn18ufhwqgpxxs70884jq9f3uelsnl45da5t3uqcl

Wallet 5

bbn124jc8uvxup3g9zcjxrgds5f6dvax2fh8czj76u

Wallet 6

bbn18vjeh5c3x2q4s8at28ymqu9nhj68sp2z8fef0w

Wallet 7

bbn13x858q229e5ujw0zuretkye6fmz4hq3y2myrnh

Wallet 8

bbn14ekvxc2ck5ch5q594jggmdgh3xt54wdhtl0rwa

Wallet 9

bbn1dprn0e6hk3325vuzzaaedjx6nzne3flt08rldr

Wallet 10

bbn10p9e8gpekxx6d4d4uyknjvuzhmznxy230zyygy

Wallet 11

bbn1e8fxrv9w6h607z699yfgaatvnvsp7x3mcqct4h

Wallet 12

bbn14u2v9gltqn89q63u8jhnwvh2p0jh6k6y9hgm8l

Wallet 13

bbn1qg07l0h2hqkjuf4wpz3k7d32jsg6hrmr6efnu3

Wallet 14

bbn1kw5qtpnh2eghrtu49l92v8lzcnvl8a043v9pc4

Wallet 15

bbn1f4fzqnnw9afffmuldpa3ugfrnkmpf6k0eud96l

Wallet 16

bbn1n373grch739lspqadtfxxhzs3el65jzuntsmmy

Wallet 17

bbn1jtfee5ra8ct22sq3gclx7ht67e44n5z097mg6f

Wallet 18

bbn106wqjczqnhp8actuy3zpdnscvtqexmeeuldvkv

Wallet 19

bbn1a4whapxufv5ncct22w0m2kumh5sr59qrfgyuam

Wallet 20

bbn1cfyljtyne6m049ndujgtlaf9ddafpx4xtk76va

Wallet 21

bbn1amjplrq5q7ewz9t74jk0vvdx7rcglztuj9xlfy

Wallet 22

bbn132rz7pvhx390ruad7trvjzuhv0scd8hj9a7xnh

Wallet 23

bbn18pq536vl9zeejc0e56cp5sum90e2qlxtzmlst7

Wallet 24

bbn1r97z3fz4y774d4utfycemf03a8m3k6rs3lr4mp

Wallet 25

bbn10xjmgmzgsrr8772rd2h5cqpqgc3ma9wcfyj4xq

Wallet 26

bbn1334mztgkc5t97t4asc94t6wmk44vlczklh9zpa

Wallet 27

bbn1puzavkguwcs0st6e5tx8yxvxme0zxdckqwt6tm

Wallet 28

bbn1pmwvzdt3kqhxjmxlqdu74nn8zz3fdzrqnuf3nu

Wallet 29

bbn1sk2dfuwea943z0rdzqqqa8twjm8tmy56l4vm7s

Wallet 30

bbn1kppgtc5t2kvjgwfn5gkvulmhh9v7sppxywqca2

Wallet 31

bbn1ese6gav6w33kwecu0feraa26axhlaq7x2rh9yt

Wallet 32

bbn1ydemfukvgtkrftnrzxfqznlh0equ0wq2sg398h

Wallet 33

bbn1wvdvu63ygdstjpwvzjhlnsen77253c734zc92f

Wallet 34

bbn1xgcjmgsxa6yjmp9scluck9et6zmpywl3j7ptlc

Wallet 35

bbn1j2l2zw2peumuv6dttss7d4yz0w346syxpqhm7r

Wallet 36

bbn13fpmkujle7d2p6j8y9et85u3jq9shngfurau87

Wallet 37

bbn1fa3trycvug2l42nvwsmmrjmpaa6jzplvwfmt0w

Wallet 38

bbn1azztqetled0u5pzck3rz022pnsx23ramhlm5ds

Wallet 39

bbn16pr5l8l9yakkuupt0re2fqtkd6ajm2w8sslrcx

Wallet 40

bbn1d0qddtxg0mdh2zj0td9jp38r2zw7ueyndf2ras

Wallet 41

bbn13ycjl4sasjmzrtn6hxt4s6z9smn23c70wv2clf

Wallet 42

bbn1d8979nzt99fqjj74j2896pelz63lw6du0e465l

Wallet 43

bbn1q499ng50gt3gctdtywpre2dgv6kh80yxmfpc23

Wallet 44

bbn1nfsn0zvzusuv02g50prjvhd45amnqqhn8nlcg0

Wallet 45

bbn1lak6nldhv38pjsx32xlgswplrc9yf66c3h99ja

Wallet 46

bbn1d7jw3ply86e4kcudmlv78ask32kdp7r22l3f8l

Wallet 47

bbn14wugxz2urj4q7f7ersjx98kn4hm7fzxraclflh

Wallet 48

bbn1swyqw8nc337wj085zj2lz0tus9dnu50k78txyf

Wallet 49

bbn1ggx42rdapec973mr77pfv2x30apcw7fl7vvfda

Wallet 50

bbn175apaxz8ftcqf95xpm0jgn8r8aemggcywadnaj

Wallet 51

bbn1kgkhuw96fsart5qj0wz98979repkmflcnwle5d

Wallet 52

bbn1c3wwy7pzfsqdvskxhtwvutv7yf4jz2a24c8mgl

Wallet 53

bbn192derv4ygx2dmx6aaepurkluefukhheqd7ztxs

Wallet 54

bbn1vpefq8se8ng4mu8607l3lpzqlq5cdlw2mm85zz

Wallet 55

bbn1rr36znfay0047epyplhmtaywhwzac9kw6xk04t

Wallet 56

bbn174jrrw2hsqdj2jww2dsa3rg7y2papjls6e7knf

Wallet 57

bbn1tf92cu2nvtt9fcklnxl4mkfn4f6d4c9ls8y2g2

Wallet 58

bbn1kqvj0rzmyy2v9qtsa08gdm8jr7gc8lfm3ta44e

Wallet 59

bbn18y3ws467knzses8ku4pcutve23vfpfc6xqwrad

Wallet 60

bbn1awejwcxcm2fq4uttkqmr75040r8hn0079k4rsk

Wallet 61

bbn1g2tpjj236gulpalkt54c9gcfhh54ayr7dacg5u

Wallet 62

bbn1jdnvt9speuqp3eqvkwp0l0pk2tmvunzuhppzz6

Wallet 63

bbn1ndr908qqmfs0atazz205rq84v06g78zc9pjz62

Wallet 64

bbn1k83fut7dmspnmwyaxgvt0h38n0lnyytp67zvqw

Wallet 65

bbn1dgkwlq7p8z2r483stzuts20d8rmk7n97ettvhw

Wallet 66

bbn1l8yf5ek359dqszfy2r3frzmmcsu27nua8ce0wm

Wallet 67

bbn1ejs9evfk3aau3krz4dasdk8e5c00ms64cr2xry

Wallet 68

bbn1yffmajcszy0smt4g7ra4pqhfj5779tf3r5cvaf

Wallet 69

bbn19hx35p4y77ewdl3qcj3j65nwf60063sr4ykvew

Wallet 70

bbn1pqq9ncvfalrx46a3ru5vgr3uvdajgywarxahzp

Wallet 71

bbn1tarkqzxg7fgqrthmefdlrwurawfrsxzaqkly2l

Wallet 72

bbn15yktnc52zlyugmlydcnjln7csjvlut2c82mn0h

Wallet 73

bbn1v24m290u8kz6286d8f8tcr85ha9kqvrhs9wlh7

Wallet 74

bbn18erprsxdrjvmzpze30j52l9za7x8h9dju77ew9

Wallet 75

bbn1wfpxpppes7sh6uvy56srnvfwn9jgwg9kpyp3jx

Wallet 76

bbn1y47aut2y9vmgy3hshzu8g9y823qa76xraqfw98

Wallet 77

bbn177mtk089uemq5u48wwpwagx2gm366kwchw0f6f

Wallet 78

bbn1957xsfazc4we7k0gqu44fyu4gg7gl75zy3gqk4

Wallet 79

bbn18f58pllscysfp6w3eswalsdg8gputk8gmt2cgh

Wallet 80

bbn14f3gx0sdjfz4x5kedllgl6d6rcq0w54lfwq7jw

Wallet 81

bbn1cfc55nny67xld0s84n0dqrfn7m2p3zsk7nu0a8

Wallet 82

bbn1nlxqx29eesv8wculyucju78ycz44z94557ekal

Wallet 83

bbn16r30du375ew82c6qy2h98rp7gep49tn0gjp5jt

Wallet 84

bbn165acjr45aje464yc06ff4snmuhl242najp3kap

Wallet 85

bbn1gss7c798p8256etftxfwv7j3nptf6z6g8773jj

Wallet 86

bbn136ux5m72glkwdnr09p2uwvpsywqx2yrc6ndql6

Wallet 87

bbn1cnxz0qlnrkmf4mxuf8ae8a6v4lt5ua8wp30k7g

Wallet 88

bbn19zq3gdp0dkza7arm32tmm205e3vcjq0dmjlywt

Wallet 89

bbn1g6arx4d3hpwshf8zs23pnhs0km5ktzs5pew6f5

Wallet 90

bbn1v7sw3fckp4mkd4uq3576ekyx5gr6yaqz55xsup

Wallet 91

bbn189nl335lcc90u0sga9dn5a73grx2ucql9mya9t

Wallet 92

bbn1q45eg648gpvvwsymuag6gpqkgmj9wuvg7dnfw4

Wallet 93

bbn1ld9cu7fnmmgjafq2s4r34hzqlzd8p8qwuvnvnn

Wallet 94

bbn1ww9yc58e0df2wfy8pk0hc5xw5w9qt2n50d63t8

Wallet 95

bbn18fehsvf75yz0nq7xf7r453qdxt8u38kre254ya

Wallet 96

bbn136ha68u7ug5ujj8xun8mst6z84tfv397xtqnte

Wallet 97

bbn1j40n4aacyg2skalj3kl4a5rpd2sp02r7f84neq

Wallet 98

bbn12c4wpycefle09md692mgf5wn8wmw5dnc6euwa9

Wallet 99

bbn1dm79tnzpd4k8g8r66evsn2qhmvh8w2eq3yantr

Wallet 100

bbn1s3qg9wvmey602qavdfa4l4e9hpfc3234qvc00d