5

If someone provides me with a payment address, how can I derive the staking address from the payment address?

This can be useful for example when we want to sent rewards to the people in return for staking to a pool.

1
  • Good question, surprised you didn't get more votes.
    – gRebel
    Jan 23, 2022 at 22:46

3 Answers 3

5

This only works if it's an address embedding the payment and stake credential. You can use cardano-address address inspect locally. You could also use a tool like cardanoscan.io which when given an address to scan tells you the stake address associated as well.

Note that some addresses don't have stake addresses and other ones can have only pointers to stake registrations.

3

As Samuel said, the address in question must contain the staking part in the first place.

cardano-address uses IOG's implementation of bech32. Instead of using cardano-address you could also install bech32 instead and decode/encode the address.

$ addr=addr1qxkmuf2gqzsm5ejxm2amrwuq3pcc02cw6tttgsgqgafj46klskg5jjufdyf4znw8sjn37enwn5ge5l66qsx8srrpg3tq8du7us
$ echo $addr | ./bech32 
01adbe254800a1ba6646dabbb1bb80887187ab0ed2d6b4410047532aeadf8591494b896913514dc784a71f666e9d119a7f5a040c780c614456

Now extract the last 57 bytes from the result as it is the staking address. Then you prefix that with the correct network tag (e0 for testnet and e1 for mainnet) and encode with bech32 to receive the staking address

$ echo "e1$(echo $addr | ./bech32 | tail -c 57)" | ./bech32 stake
stake1u9rfyvw5pkeherf56lzxjaqlpxs53fjghl4ft6w2x8wpnwchfeam3

On a side note, be aware of the existence of franken addresses. A constructed address which has the payment part of one wallet and the staking part of another. This way I could pretend I am the owner of the stake delegated to the pool.

0

Just for completeness, you can also use Haskell to decode the address into its components using a function like the one shown in the Plutus Pioneer Program.

tryReadStakeAddress :: String -> Maybe Plutus.StakingCredential
tryReadStakeAddress = show . Plutus.addressStakingCredential . tryReadAddress

tryReadAddress :: String -> Maybe Plutus.Address
tryReadAddress x = case deserialiseAddress AsAddressAny $ pack x of
    Nothing                                      -> Nothing
    Just (AddressByron _)                        -> Nothing
    Just (AddressShelley (ShelleyAddress _ p s)) -> Just Plutus.Address
        { Plutus.addressCredential        = credentialLedgerToPlutus p
        , Plutus.addressStakingCredential = stakeReferenceLedgerToPlutus s
        }

credentialLedgerToPlutus :: Ledger.Credential a StandardCrypto -> Plutus.Credential
credentialLedgerToPlutus (ScriptHashObj (ScriptHash h)) = Plutus.ScriptCredential $ Plutus.ValidatorHash $ toBuiltin $ hashToBytes h
credentialLedgerToPlutus (KeyHashObj (KeyHash h))       = Plutus.PubKeyCredential $ Plutus.PubKeyHash $ toBuiltin $ hashToBytes h

stakeReferenceLedgerToPlutus :: Ledger.StakeReference StandardCrypto -> Maybe Plutus.StakingCredential
stakeReferenceLedgerToPlutus (StakeRefBase x)                   = Just $ StakingHash $ credentialLedgerToPlutus x
stakeReferenceLedgerToPlutus (StakeRefPtr (Ptr (SlotNo x) y z)) = Just $ StakingPtr (fromIntegral x) (fromIntegral y) (fromIntegral z)
stakeReferenceLedgerToPlutus StakeRefNull                       = Nothing

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.