Transaction Tracing
All transactions on the Lombard Protocol are fully traceable between different blockchain networks (both Bitcoin and destination chains where LBTC is supported).
This technical document is aimed at users and developers familiar with different blockchain networks and how data is represented on-chain.
Tracing the Bitcoin Transaction Hash from an LBTC Mint
Scenario: When a user mints LBTC from staking native BTC, the Bitcoin transaction hash corresponding to their deposit address is included in the on-chain event logs.
First, find the on chain events log on the Implementation contract. Check the logs of the transaction and find the event mintProofConsumed
which corresponds to the mint event. The topic ID which corresponds to this event is 0x91f5c148b0f5ac9ddafe7030867f0d968adec49652c7ea760cf51fa233424b14
.
Tip: you can also use this link to Etherscan's block explorer to see all methods which contain topic0
for this event on Ethereum. Similar for all other EVM chains.
After locating the corresponding the mintProofConsumed
event corresponding to the minting transaction in the transaction logs, the data needs to be decoded. This data object is a Hex encoded object of 4 bytes, where each variable is left padded 32 bytes.
You can identify the minting event data by the four encoded bytes F2E73F7C
. The four variables included are the following:
chain
recipient
amount
vout
This data needs to be decoded. You can directly locate the recipient variable, and reverse order the bytes to see the corresponding deposit transaction for this mint event. Below, we have provided the relevant ABI code which you can use to decode the message in any convenient ABI decoder by inputting both the script below and the encoded data into this online decoder:
[
{
"inputs": [
{
"internalType": "bytes32",
"name": "chain",
"type": "bytes32"
},
{
"internalType": "bytes32",
"name": "recipient",
"type": "bytes32"
},
{
"internalType": "uint64",
"name": "amount",
"type": "uint64"
},
{
"internalType": "bytes32",
"name": "txid",
"type": "bytes32"
},
{
"internalType": "uint32",
"name": "vout",
"type": "uint32"
}
],
"name": "payload",
"outputs": [],
"stateMutability": "nonpayable",
"type": "function"
}
]
Bitcoin transactions are stored in big-endian order, but displayed in little-endian order. To search for the transaction on Mempool Space, you will need to select the txid
, the third variable, and convert.
The easiest method to convert the Bitcoin transaction hash from big-endian to little-endian is to use an online tool such as this handy converter, selecting Hexal.
Alternatively, via script:
# Reverse the byte order of a transaction ID and convert it to lowercase
echo "D4A6996A178682D3D7123F19E48A502C6076D6916A188C1DAB1C83CCADE7D7D9" \
| tr 'A-F' 'a-f' \
| sed 's/../& /g' \
| awk '{for (i=NF; i>0; i--) printf $i" "; print ""}' \
| tr -d ' \n'
# Resulting transaction ID to search for on Mempool Space
d9d7e7adcc831cab1d8c186a91d676602c508ae4193f12d7d38286176a99a6d4
Finding the Bitcoin address from an LBTC Redemption
Scenario: Users can initiate the redemption of their native BTC at any time to a chosen recipient address by unstaking LBTC. When a user unstakes LBTC, the recipient Bitcoin address is embedded within the script public key in the on-chain event logs.
View Unstake Events
To view the mint event logs, use a blockchain explorer like Etherscan. Select any one of the transactions of Method type Redeem
made on the LBTC ERC-20 token smart contract. In the Transaction Details, view the Logs tab and find the UnstakeRequest
event log. This log contains:
The address is embedded in the
scriptPubKey
value of in the event log'sdata
object.The amount of the unstake request
Decode Recipient Bitcoin Address
Use the following Go code snippet with the relevant hexadecimal-encoded scriptPubKey
. The resulting output is the recipient Bitcoin address. Alternatively, this snippet can also be run here.
Note: Lombard only supports unstaking to Native Segwit and Taproot addresses. For more information.
package main
import (
"encoding/hex"
"log"
"github.com/btcsuite/btcd/chaincfg"
"github.com/btcsuite/btcd/txscript"
)
func main() {
// Example script public key
scriptPubKey := "0014ECF86E0724CDD2F803B40FD72D9E40E621494674"
// Decode the hex-encoded scriptPubKey
pkScript, err := hex.DecodeString(scriptPubKey)
if err != nil {
log.Fatalf("Error decoding hex string: %v", err)
}
// Extract the script class and address from the pkScript
scriptClass, addresses, _, err := txscript.ExtractPkScriptAddrs(pkScript, &chaincfg.MainNetParams)
if err != nil {
log.Fatalf("Error extracting address: %v", err)
}
// Ensure exactly one address is returned for supported cases
if len(addresses) != 1 {
log.Fatalf("Error: Unexpected number of addresses: %d", len(addresses))
}
// Handle supported script classes
switch scriptClass {
case txscript.WitnessV0PubKeyHashTy: // P2WPKH
log.Println("Extracted Recipient Address:", addresses[0].EncodeAddress())
case txscript.WitnessV0ScriptHashTy: // P2WSH
log.Println("Extracted Recipient Address:", addresses[0].EncodeAddress())
case txscript.WitnessV1TaprootTy: // P2TR
log.Println("Extracted Recipient Address:", addresses[0].EncodeAddress())
default:
log.Fatalf("Unsupported script type: %v", scriptClass)
}
}
Last updated