I want to generate the address from the plutus script's cborhex value, but so far without much luck. I am using the alwayssucceeds.plutus contract as an example for which the cborhex value is 4E4D01000033222220051200120011 and the for which the address is known to be addr_test1wpnlxv2xv9a9ucvnvzqakwepzl9ltx7jzgm53av2e9ncv4sysemm8. What i want to do is derive the same address from the cboxhex by using the cardano-serialization-lib

Why not use the cardano-cli for this by running cardano-cli address build --payment-script-file alwayssucceeds.plutus --testnet-magic 1097911063 --out-file script.addr ?

Well, if it can be done in the cardano-serialization-lib then it means it can be done in the client's front end which is faster and requires less wiring to the backend. cardano-serialization-lib is already used for a lot of the interaction with the wallet and submitting transactions, so it is a natural place to derive the address from the cborhex

This is my code, but it does not produce the correct address

// cborhex of the alwayssucceeds.plutus
const cborhex = "4E4D01000033222220051200120011";
const cbor = Buffer.from(cborhex, "hex");
const blake2bhash = blake.blake2b(cbor, 0, 28); //blake2b-224 -> 28 bytes
const scripthash = ScriptHash.from_bytes(blake2bhash);
const cred = StakeCredential.from_scripthash(scripthash);
const networkId = NetworkInfo.testnet().network_id();
const baseAddr = EnterpriseAddress.new(networkId, cred);
const addr = baseAddr.to_address();
const addrBech32 = addr.to_bech32();

// hash of the address generated from script
console.log(Buffer.from(addr.to_bytes(), "utf8").toString("hex"))

// hash of the address generated using cardano-cli
const ScriptAddress = Address.from_bech32("addr_test1wpnlxv2xv9a9ucvnvzqakwepzl9ltx7jzgm53av2e9ncv4sysemm8");
console.log(Buffer.from(ScriptAddress.to_bytes(), "utf8").toString("hex"))

And the hex outputs are: geneated from cborhex: 70d4e0f6e402a19e086f2fb9914124604ece088db0fa5906fb0f66fc07 generated by cardano-cli: 7067f33146617a5e61936081db3b2117cbf59bd2123748f58ac9678656

The corresponding bech32 addresses are: geneated from cborhex: addr_test1wpnlxv2xv9a9ucvnvzqakwepzl9ltx7jzgm53av2e9ncv4sysemm8 generated by cardano-cli: addr_test1wr2wpahyq2seuzr097uezsfyvp8vuzydkra9jphmpan0cpczfflxx

The blake package is npm install blakejs

Similar question has been raised in the below 2 links, without an adequate answer so far: Link1 Link2

  • Typically the CBOR hex would have a prefix of number of bytes and the data after that prefix. So for example the CBOR hex 4E4D01000033222220051200120011 would have 4E bytes (14 bytes) after the prefix 4E namely 4D01000033222220051200120011 (use cbor.me to decode the cbor). This might possibly be throwing off your blake2B hash output? Commented Aug 5, 2022 at 16:57

2 Answers 2


I've answered this here, but as a reference I'll copy my answer below:

Plutus-Core script bytes are wrapped twice in a CBOR bytearray.

Use the following steps to calculate the script address:

  1. unwrap one layer of CBOR
  2. prepend a byte representing the PlutusScript version: 0x01 for PlutusScriptV1, 0x02 for PlutusScriptV2
  3. calculate the 28-byte (224-bit) blake2b digest to get the payment part of the address
  4. form the full script address using CIP19 (so for script addresses without a staking part simply prepend 0x70 to the digest)
  5. encode the script address bytes using bech32 ("addr_test" prefix for testnet, "addr" prefix for mainnet)

The pseudo code of these steps would look as follows: encodeBech32("addr_test", prepend(hashBlake2b224(prepend(unwrapCborBytes(hexToBytes(cborHex)), 0x01)), 0x70))

As an example consider the commonly used AlwaysSucceeds script. It has the following hexadecimal representation: "4e4d01000033222220051200120011".

  1. Unwrapping one layer of CBOR bytearray would give: "4d01000033222220051200120011".
  2. Prepend 0x01: "014d01000033222220051200120011"
  3. Blake2b 28-byte digest: "67f33146617a5e61936081db3b2117cbf59bd2123748f58ac9678656"
  4. Prepend 0x70: "7067f33146617a5e61936081db3b2117cbf59bd2123748f58ac9678656"
  5. Bech32 encoding of testnet address: "addr_test1wpnlxv2xv9a9ucvnvzqakwepzl9ltx7jzgm53av2e9ncv4sysemm8"

Don't ask me why Plutus-Core scripts are wrapped twice in CBOR, and then unwrapped once to calculate the address. Some smart guys somewhere must have a good reason.

If you'd like to do these calculations in Javascript without some complicated Rust/Haskell dependencies check out the Helios Lang library. The library is UNLICENSEd so you can copy the relevant functionality as you please.


I have since implemented this in a git repo:


Your Answer

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

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