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 301

bbn1gysxgy62w5q9k00tldwwm2hnfaqh64cs3gq045

Wallet 302

bbn1ql6g20jcvf5kqreq0z92czflfchggsay3gc8hk

Wallet 303

bbn1ljh43sag9s6pj6h0cucz59wv7utc699lfpg6j3

Wallet 304

bbn1p0xzy0r7j2yutxvhaa9ql4ldfqqjucugmz8wcr

Wallet 305

bbn17hwc27rpkdfr66laq95lxfar2nrr8me49upxhh

Wallet 306

bbn1gece6fs5phgqm00d5pq25q2jq0jphj5yhyzxxr

Wallet 307

bbn1uwu97fck9sajv3wlnu5ae9qw6ppland0qntjyk

Wallet 308

bbn1mdq787p2kls9uz38ap439t4dap34sqdjy0qyp4

Wallet 309

bbn1jl406km7eq08ha0tsr9yayprr373lw76tx0v0w

Wallet 310

bbn1mkzf6ztp9aq2g4haxaz0mfdjz34sn9x3xf208t

Wallet 311

bbn146glgq8cj0sfg8s4v43jtj94hdtdjhm0vtr2y7

Wallet 312

bbn1ep5x94uj8mnffzjk687hqc6as9xm3sjdfk7x9g

Wallet 313

bbn1yl2dej6dkywhsfmy4tcdtzjnsatgqflkgfjthp

Wallet 314

bbn146446ekdxqfxdwem2ryd8ptaglsrtkjn8qt3je

Wallet 315

bbn1ay52m8wm46rp25amzh600qwxaj0t9ufd2axh3r

Wallet 316

bbn10k342hgmfsm04jma9suc42y7sd40sr94dm2350

Wallet 317

bbn1ds88w0ln9ftgq8t6rh53fsryn3r8k8dx3ewche

Wallet 318

bbn1gldxlsq70x52tw4w9cdasu6wk9va5xx8gwvfqu

Wallet 319

bbn1j3ppq9um98e6rvzqw2rev0ss3qv5wmgdhkrgtq

Wallet 320

bbn1dc0a9k6tlxkm5a9g3qpu3gy63ndscang7t5sht

Wallet 321

bbn1yap6z9000luz3nmfkdn96mmkhc5uk3sem789gc

Wallet 322

bbn17t2mjea3ly3ce4mv6fsnacm5tm2ugd2dvqur6d

Wallet 323

bbn13mfgzuda9wxd3qx0mqnsu9xxxh065s5k6whnjz

Wallet 324

bbn1xsz7j3c0zmrg34su5nyql82nrt6zkvwcrslq6j

Wallet 325

bbn1ppgm3qeu2uejfrgxd60zeg62sv4t6nn60p4fyh

Wallet 326

bbn1u8husmljyk4rlmc35ncp22fj7kpfvd3zk8k3w2

Wallet 327

bbn1c9uhptn8hk6jleys0vn9necumm7u0hvgpyf5as

Wallet 328

bbn14h26e0rzge5yl0c9x5k9quqlgh6fkh4v23y2a0

Wallet 329

bbn1z98eg2ztdp2glyla62629nrlvczg8s7fc42qjl

Wallet 330

bbn1zrlsh07x3dt0qh6mu65504g86kqfj3l2aezl6m

Wallet 331

bbn1tpu75t0097tg46dmdjwj5veurt2zt2cn0f6ty0

Wallet 332

bbn172gqpfu583yseddq697wl8u5rxusyej820pap4

Wallet 333

bbn1p7gnav0cxytrjs24tsd7e6tzed58tfm07982v0

Wallet 334

bbn1weud9cvsd2hrc3zdmz0ug0fv5wlearypegrh6n

Wallet 335

bbn14g9dtt5gn8zvxx7dz5z06hspef6tm5rn2sw3rc

Wallet 336

bbn1vy9eg6d5gg2xvzhu7f6598cmdp2yxldvpvjgeq

Wallet 337

bbn125rh8d62hs4a7d7cgy7xa6hj362t8wvrfg5duk

Wallet 338

bbn1nlyu6qzeuaeeefhstcc2lvn0kv5ur20xxkrczn

Wallet 339

bbn1m0qjrg0hw37y8zuxhtmpw3qp60js6fp7zp67wg

Wallet 340

bbn147s48qhxcyw3ra20hqnnc8rwmstegycugvz0ja

Wallet 341

bbn1ptry5acdxjwj6xvsmk7942xp2gs6724ezl4295

Wallet 342

bbn12y2u5pvtl3wzlu0y008qvlpk4swvw39up9jph5

Wallet 343

bbn13szs2zp62p4x33qlc6ttqhkm0a6damw053fema

Wallet 344

bbn1w3e9xs7x7ja9gfyn6klpaye5dr8hc68g050ny3

Wallet 345

bbn1qnqvuswaw8s3efuz0xdrumqq6tuz8k7l7ndta9

Wallet 346

bbn1eukyk0uhwxlvvkgx30pdkvq7nycycze9x4d5rp

Wallet 347

bbn12h2awqfulxu7ruzv5g7wssmnllj5c0gg97p5gq

Wallet 348

bbn1mjw2y7k52wne63fd8se0waa53zyvsv9qndrdjm

Wallet 349

bbn1s9482c98zw392fe7p4awpuh4v39z5xg3ngnn7f

Wallet 350

bbn1pwj0tkr7r03pzguwd8p328rnymzkts4hztynqh

Wallet 351

bbn1e0zu9pee0x2ungkau828dhu95sjx605tqkxjhn

Wallet 352

bbn1cqvl29tywhgcxx4fp38nwvqyxschgplrr4vt4q

Wallet 353

bbn1fdvnxssw86gfye4dakv6w53yzvpr9cjrf32sum

Wallet 354

bbn1ec3gvg294rs4ggrpfj84yxfer3pfhlgtnhkcl3

Wallet 355

bbn1rwuc72jven7s90cqmmncu9dwhkfj62mua3ulep

Wallet 356

bbn1dfushcy82vx9225yxaza7aaafnn7r9uzsj6eft

Wallet 357

bbn1cc0ef5s5gr9puu25tk47l42cyhyfrskvm9ne8g

Wallet 358

bbn1d3d2rcg09ahvrz3ufyn77adx49gtw8284j7sdp

Wallet 359

bbn1ghrpfanlpyxexasld77ekny99cta6jcgezt3uk

Wallet 360

bbn1v6tevtflttxsx4qdlr9vzacfdtwjwu308dufaj

Wallet 361

bbn13q6klgfxfaf6fsd34xuxp5l7perjhnx7pv2gn5

Wallet 362

bbn1hu8vqhtk0lr76jd55e2muk8pmyavrpafqjcwe4

Wallet 363

bbn1y989v3qrxagaxpjd8tr0gjjtcnk3tq9xwmt7ha

Wallet 364

bbn1kjruag2yjn62pykfhgky5ammgcx7hame2w54pe

Wallet 365

bbn14rql0qyrq0vd9523luxga0zr449a0n973zmnsu

Wallet 366

bbn16urnjnmmzyjtnvu68xhf7ve4gunwp3zkmfts25

Wallet 367

bbn12mv5prq7jh2k47ntaevturfrmj6qyk7cfq4mdn

Wallet 368

bbn1qp2tfhsz2wv9wjfs530uf770cgawu2dwlc0kuy

Wallet 369

bbn19h884swtqsklsvx2mqs4kqcewxpk7qr0nd6xcn

Wallet 370

bbn10s7ca3lut2xtzj6fq0hnznyy8jx75lxss5k237

Wallet 371

bbn1hnjvzkp3x69can22y425sk45ds5czzpvwe7fkm

Wallet 372

bbn17x4syatad9jamwfeccrppz0mk83szd5nhvfsrg

Wallet 373

bbn1nrz6es3vm30c77wk92sd8e0sc3p2tezw39a68j

Wallet 374

bbn1mtrkgq5rhchwu6krcau34a8k7h8yj8prwtufu2

Wallet 375

bbn1rhy5t5xv2fjzmrvj72j26xul9sc4pywu68vhjr

Wallet 376

bbn1ux084vmv5qeerrqzfpcq7t29fr5mn0fa8ndr38

Wallet 377

bbn1ren67x9nxt3nlfxmxmrmllpv9yurl3wflm0cky

Wallet 378

bbn16f3kca34y7u5dv8ymv6lxnpytwefqh0hvc8g22

Wallet 379

bbn1zuyrdp0y9wsrgdts0g5cuqu03jwj6z20l48p7t

Wallet 380

bbn1t3v3hvhf5ph5cnj92wftjehl665gxurghn7hn8

Wallet 381

bbn15vcnj695jrkft9nx4dz9yl4zawjyrw936k0adc

Wallet 382

bbn1x8juehetewenhktm4d00w2nm7e509uqjuvyqv7

Wallet 383

bbn12yj4wa3vs442efrfvgvmvslq75x03t5d0hxrfj

Wallet 384

bbn1lemwff7v4m8lqg325gtwl24w2dwxyccg2fmu0y

Wallet 385

bbn148h6rndsz4g3crnmm4dc0rpr8t28rj2zjm2jhk

Wallet 386

bbn109z5tz09syajx3ef56pc7sy8t39tlrgg56enza

Wallet 387

bbn1yeyytu6jhjnxes4ufty8yaxkyawzz7462q6hd6

Wallet 388

bbn1zsgpymkv0tjumsa7wlt07pql0x3s9nqa4qlran

Wallet 389

bbn16g3gm6gvaq2uwhv0ty2z9200d8p3yn9jy633fr

Wallet 390

bbn1df2prh4s6a2djv0uyuy80erprqkw59lznvp4rd

Wallet 391

bbn1lztm7kycww74qck3087hvawfnea6ldtjqfa78f

Wallet 392

bbn1nxscktq3murju3tlv3f923rzyvu2hdmwwd799s

Wallet 393

bbn19gu0alc0g8k7v0rj60xkxv2ky23u65axsmk768

Wallet 394

bbn1pu6ahpa33yeaclv5dcfmwssp25nnxv6szslqrx

Wallet 395

bbn1f4jdq7d9pezrp6asnvxjgqwxcs4tmsr8svqatn

Wallet 396

bbn1qlhg8dtgkwvzzmdztwy9mv4aegj97lu9eu2ww7

Wallet 397

bbn10wswn8xu5mgcqaesnl3895ku0gknmzv8y9076s

Wallet 398

bbn1upkfhv5wacah74y2mwpfr54ersd0fha9j4y2a3

Wallet 399

bbn1nusnyl2nrzcyu37weanu0p8xrrgdp7tp595puq

Wallet 400

bbn1z8zhxujzhl3y3lmhjjsm8dv0q4jrpdhtlzrqt5