<p>The <code>sriptAddress</code> is in Base16 (aka Hexadecimal)</p>
<p>You need to do a few things to it to transform into an address:
Add &quot;70&quot; to the front for Testnet, or &quot;71&quot; for Mainnet</p>
<p>The Header for Testnet is &quot;70&quot; and for Mainnet &quot;71&quot;
To work out why you need to go read CIP19:
<a href="https://cips.cardano.org/cips/cip19/#shelley-addresses" rel="nofollow noreferrer">https://cips.cardano.org/cips/cip19/#shelley-addresses</a></p>
<p>And then look up the
Header bits '011100000' for Testnet or
Header bits '011100001' for Mainnet
In a binary to Hex table, such as here:
<a href="https://www.rapidtables.com/convert/number/binary-to-ascii.html" rel="nofollow noreferrer">https://www.rapidtables.com/convert/number/binary-to-ascii.html</a></p>
<p>Then you need to convert it into Bech32 and then further add &quot;addr_test&quot; to the front for Testnet, or &quot;addr&quot; for Mainnet. This is best all done with the help of some libraries.</p>
<p>Here is a sample script that does this, and as a bonus also gives the CBORHex of the script</p>
<pre><code>{-# LANGUAGE DataKinds         #-}
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE TemplateHaskell   #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TypeApplications  #-}
{-# LANGUAGE TypeFamilies      #-}

module Test where

-- Haskell Imports
import Prelude hiding (($))
import Data.Maybe
import Codec.Serialise (serialise)
import qualified Data.ByteString.Lazy as LBS
import qualified Data.ByteString as B
import qualified Data.ByteString.Short as SBS
import qualified Data.ByteString.Base16 as Base16
import qualified Data.Text as T
import Codec.Binary.Bech32 as B32
import Data.Text.Encoding as TE
import Data.Aeson.Encode.Pretty (Config (..), defConfig, encodePretty', keyOrder)


-- Plutus Imports
import Cardano.Api (serialiseToTextEnvelope)
import Cardano.Api.Shelley (PlutusScript (..), PlutusScriptV1)
import qualified Ledger hiding (singleton)
import qualified Plutus.V1.Ledger.Scripts as Plutus
import Plutus.V1.Ledger.Address (scriptHashAddress, Address)
import PlutusTx
import PlutusTx.Prelude hiding (Semigroup (..), unless, (.))
import qualified Cardano.Binary as CBOR
import Cardano.Codec.Bech32.Prefixes (addr_test, addr)

--------------------
-- Create Validator
--------------------
{-# INLINABLE mkValidator #-}
mkValidator :: BuiltinData -&gt; BuiltinData -&gt; BuiltinData -&gt; ()
mkValidator _ _ _ = ()

validator :: Plutus.Validator
validator = Plutus.mkValidatorScript $$(PlutusTx.compile [|| mkValidator ||])



----------------------------------------
-- Create PlutusScript from validator
-- Print the CBORHex
----------------------------------------
script :: Plutus.Script
script = Plutus.unValidatorScript validator

scrAddress :: Ledger.Address
scrAddress = Ledger.scriptAddress validator

scriptShortBs :: SBS.ShortByteString
scriptShortBs = (SBS.toShort . LBS.toStrict . serialise) script

srlScript :: PlutusScript PlutusScriptV1
srlScript = PlutusScriptSerialised scriptShortBs

scriptCBORHex :: B.ByteString
scriptCBORHex = Base16.encode $ CBOR.serialize' srlScript

-------------
-- Generate JSON format
-- for Validator CBORHex
-------------

textEnvelopeJSONKeyOrder :: T.Text -&gt; T.Text -&gt; Ordering
textEnvelopeJSONKeyOrder = keyOrder [&quot;type&quot;, &quot;description&quot;, &quot;cborHex&quot;]

textEnvelopeJSONConfig :: Config
textEnvelopeJSONConfig = defConfig { confCompare = textEnvelopeJSONKeyOrder }

textEnveloper = encodePretty' textEnvelopeJSONConfig (serialiseToTextEnvelope Nothing srlScript) &lt;&gt; &quot;\n&quot;


----------------------------------
-- Generate PlutusScript Hash
----------------------------------
validatorHash :: Plutus.ValidatorHash
validatorHash = fromJust (Ledger.toValidatorHash scrAddress)

validatorHashHex :: String
validatorHashHex = show validatorHash

-----------------------------
-- Create Script Address
-----------------------------

addHeader :: String -&gt; String -&gt; T.Text
addHeader h v = T.pack (h Prelude.++ v)

{-
Header for Testnet is &quot;70&quot; and for Mainnet &quot;71&quot;
To work out why you need to go read CIP19:
https://cips.cardano.org/cips/cip19/#shelley-addresses

And then look up the
- Header Bits '011100000' for Testnet or 
- Header Bits '011100001' for Mainnet
In a binary to Hex table, such as here:
https://www.rapidtables.com/convert/number/binary-to-ascii.html

The header is in Base16 format (aka Hexadecimal)

-}
header :: String
header = &quot;70&quot;

validatorHashHexWHeader :: B.ByteString
validatorHashHexWHeader = TE.encodeUtf8 (addHeader header validatorHashHex)

binary :: B.ByteString
Right binary = Base16.decode validatorHashHexWHeader

{-
Prefix for Testnet: &quot;addr_test&quot; and Mainnet: &quot;addr&quot;
These prefixes are imported from Cardano.Codec.Bech32.Prefixes
-}

dataPart :: B32.DataPart
dataPart = B32.dataPartFromBytes binary


{-
The bech32 representation is derived in 2 steps:
- bech32 = prefix + dataPart
- and where dataPart = header + validatorHash
-}
addrBech32 :: T.Text
Right addrBech32 = B32.encode addr_test dataPart



main :: IO ()
main = do
    putStrLn (&quot;Script CBORHex: &quot; Prelude.++ show scriptCBORHex)
    putStrLn (&quot;Script Addr: &quot; Prelude.++ show addrBech32)
</code></pre>

CC BY-SA 4.0
2022-08-05T02:07:55.380Z
2022-08-05T02:07:55.380Z
D S
<p>Because plutus uses (Template) Haskell, hence deterministic.</p>
<p>Your SC is going to run as is when it goes live. Every output you get while developing your SC on the testnet/pc is applicable when you eventually move it to the mainnet.</p>
<p>So, it becomes impractical to expect a different output during development and a different one in production.</p>

CC BY-SA 4.0
2021-08-22T06:26:53.037Z
I dont think you understood my question. On Alonzo testnet all script addresses start with addr_test1 but the string inside the Address struct does not have that format? What is this string then?
Anh Dũng Lê
CC BY-SA 4.0
2021-08-22T04:53:34.140Z
2021-08-22T04:53:34.140Z
Aoaddeola
<p>The piece of data you show is encoded in Base16. Addresses are however typically encoded as Bech32 which allows for defining human readable prefixes like &quot;addr_test&quot;.</p>
<p>As a matter of fact, it is possible to encode the same underlying data payload in different formats. The preferred one for presenting the data to end users should be Bech32, but Base16 may be a sensible choice for interoperability in contexts like command-lines or developer tools since it has wider support than Bech32.</p>

CC BY-SA 4.0
2021-11-04T18:11:00.493Z
And how to convert this address to bech32 in haskell?
martin
CC BY-SA 4.0
2021-11-05T20:31:13.777Z
https://hackage.haskell.org/package/bech32
KtorZ
CC BY-SA 4.0
2021-11-12T21:28:04.510Z
This does not actually encode it correctly. When using the CLI, the address output of both is different: ScriptCredential /= base16 representation of cardano cli address
martin
CC BY-SA 4.0
2021-11-14T08:24:10.743Z
That is because a script credential isn't an address. Addresses have a header for type and discrimination; have a look at: https://github.com/cardano-foundation/CIPs/tree/master/CIP-0019
KtorZ
CC BY-SA 4.0
2021-08-23T16:38:21.510Z
2021-08-23T16:38:21.510Z
KtorZ
<p>When I use <code>scriptAddress</code> on a validator of my SC I got the following result:</p>
<pre><code>Address {addressCredential = ScriptCredential 22261390d0b365fef5a12bc33a29987fe10b28ed58e1036d27b0db43c613edad, addressStakingCredential = Nothing}
</code></pre>
<p>Is <code>22261390d0b365fef5a12bc33a29987fe10b28ed58e1036d27b0db43c613edad</code> the script address?</p>
<p>Why doesn't it start with <code>addr_test1</code>?</p>

<plutus><address>
Structure of the Address type from Plutus.V1.Ledger.Address
# Structure of the Address type from Plutus.V1.Ledger.Address

(Asked by: username_0 on 2021-08-21)

When I use scriptAddress on a validator of my SC I got the following result:
Address {addressCredential = ScriptCredential 22261390d0b365fef5a12bc33a29987fe10b28ed58e1036d27b0db43c613edad, addressStakingCredential = Nothing}

Is 22261390d0b365fef5a12bc33a29987fe10b28ed58e1036d27b0db43c613edad the script address?
Why doesn't it start with addr_test1?

**Tags:** plutus, address

---

## 3 answers

### Answer by username_3 on 2021-08-23. Score: 4

The piece of data you show is encoded in Base16. Addresses are however typically encoded as Bech32 which allows for defining human readable prefixes like "addr\_test".

As a matter of fact, it is possible to encode the same underlying data payload in different formats. The preferred one for presenting the data to end users should be Bech32, but Base16 may be a sensible choice for interoperability in contexts like command-lines or developer tools since it has wider support than Bech32.

> **Comments:**
> **username_4**: And how to convert this address to bech32 in haskell?  
> **username_3**: https://hackage.haskell.org/package/bech32  
> **username_4**: This does not actually encode it correctly. When using the CLI, the address output of both is different: ScriptCredential /= base16 representation of cardano cli address  
> **username_3**: That is because a script credential isn't an address. Addresses have a header for type and discrimination; have a look at: https://github.com/cardano-foundation/CIPs/tree/master/CIP-0019  

---

### Answer by username_1 on 2022-08-05. Score: 2

The sriptAddress is in Base16 (aka Hexadecimal)
You need to do a few things to it to transform into an address:
Add "70" to the front for Testnet, or "71" for Mainnet
The Header for Testnet is "70" and for Mainnet "71"
To work out why you need to go read CIP19:
https://cips.cardano.org/cips/cip19/#shelley-addresses
And then look up the
Header bits '011100000' for Testnet or
Header bits '011100001' for Mainnet
In a binary to Hex table, such as here:
https://www.rapidtables.com/convert/number/binary-to-ascii.html
Then you need to convert it into Bech32 and then further add "addr_test" to the front for Testnet, or "addr" for Mainnet. This is best all done with the help of some libraries.
Here is a sample script that does this, and as a bonus also gives the CBORHex of the script
{-# LANGUAGE DataKinds         #-}
{-# LANGUAGE NoImplicitPrelude #-}
{-# LANGUAGE TemplateHaskell   #-}
{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE TypeApplications  #-}
{-# LANGUAGE TypeFamilies      #-}

module Test where

-- Haskell Imports
import Prelude hiding (($))
import Data.Maybe
import Codec.Serialise (serialise)
import qualified Data.ByteString.Lazy as LBS
import qualified Data.ByteString as B
import qualified Data.ByteString.Short as SBS
import qualified Data.ByteString.Base16 as Base16
import qualified Data.Text as T
import Codec.Binary.Bech32 as B32
import Data.Text.Encoding as TE
import Data.Aeson.Encode.Pretty (Config (..), defConfig, encodePretty', keyOrder)


-- Plutus Imports
import Cardano.Api (serialiseToTextEnvelope)
import Cardano.Api.Shelley (PlutusScript (..), PlutusScriptV1)
import qualified Ledger hiding (singleton)
import qualified Plutus.V1.Ledger.Scripts as Plutus
import Plutus.V1.Ledger.Address (scriptHashAddress, Address)
import PlutusTx
import PlutusTx.Prelude hiding (Semigroup (..), unless, (.))
import qualified Cardano.Binary as CBOR
import Cardano.Codec.Bech32.Prefixes (addr_test, addr)

--------------------
-- Create Validator
--------------------
{-# INLINABLE mkValidator #-}
mkValidator :: BuiltinData -> BuiltinData -> BuiltinData -> ()
mkValidator _ _ _ = ()

validator :: Plutus.Validator
validator = Plutus.mkValidatorScript $$(PlutusTx.compile [|| mkValidator ||])



----------------------------------------
-- Create PlutusScript from validator
-- Print the CBORHex
----------------------------------------
script :: Plutus.Script
script = Plutus.unValidatorScript validator

scrAddress :: Ledger.Address
scrAddress = Ledger.scriptAddress validator

scriptShortBs :: SBS.ShortByteString
scriptShortBs = (SBS.toShort . LBS.toStrict . serialise) script

srlScript :: PlutusScript PlutusScriptV1
srlScript = PlutusScriptSerialised scriptShortBs

scriptCBORHex :: B.ByteString
scriptCBORHex = Base16.encode $ CBOR.serialize' srlScript

-------------
-- Generate JSON format
-- for Validator CBORHex
-------------

textEnvelopeJSONKeyOrder :: T.Text -> T.Text -> Ordering
textEnvelopeJSONKeyOrder = keyOrder ["type", "description", "cborHex"]

textEnvelopeJSONConfig :: Config
textEnvelopeJSONConfig = defConfig { confCompare = textEnvelopeJSONKeyOrder }

textEnveloper = encodePretty' textEnvelopeJSONConfig (serialiseToTextEnvelope Nothing srlScript) <> "\n"


----------------------------------
-- Generate PlutusScript Hash
----------------------------------
validatorHash :: Plutus.ValidatorHash
validatorHash = fromJust (Ledger.toValidatorHash scrAddress)

validatorHashHex :: String
validatorHashHex = show validatorHash

-----------------------------
-- Create Script Address
-----------------------------

addHeader :: String -> String -> T.Text
addHeader h v = T.pack (h Prelude.++ v)

{-
Header for Testnet is "70" and for Mainnet "71"
To work out why you need to go read CIP19:
https://cips.cardano.org/cips/cip19/#shelley-addresses

And then look up the
- Header Bits '011100000' for Testnet or 
- Header Bits '011100001' for Mainnet
In a binary to Hex table, such as here:
https://www.rapidtables.com/convert/number/binary-to-ascii.html

The header is in Base16 format (aka Hexadecimal)

-}
header :: String
header = "70"

validatorHashHexWHeader :: B.ByteString
validatorHashHexWHeader = TE.encodeUtf8 (addHeader header validatorHashHex)

binary :: B.ByteString
Right binary = Base16.decode validatorHashHexWHeader

{-
Prefix for Testnet: "addr_test" and Mainnet: "addr"
These prefixes are imported from Cardano.Codec.Bech32.Prefixes
-}

dataPart :: B32.DataPart
dataPart = B32.dataPartFromBytes binary


{-
The bech32 representation is derived in 2 steps:
- bech32 = prefix + dataPart
- and where dataPart = header + validatorHash
-}
addrBech32 :: T.Text
Right addrBech32 = B32.encode addr_test dataPart



main :: IO ()
main = do
    putStrLn ("Script CBORHex: " Prelude.++ show scriptCBORHex)
    putStrLn ("Script Addr: " Prelude.++ show addrBech32)


---

### Answer by username_2 on 2021-08-22. Score: 0

Because plutus uses (Template) Haskell, hence deterministic.

Your SC is going to run as is when it goes live. Every output you get while developing your SC on the testnet/pc is applicable when you eventually move it to the mainnet.

So, it becomes impractical to expect a different output during development and a different one in production.

> **Comments:**
> **username_0**: I dont think you understood my question. On Alonzo testnet all script addresses start with addr_test1 but the string inside the Address struct does not have that format? What is this string then?  

---

