Skip to content

Methodology

DISCLAIMER // NFA // DYOR

This analysis is based on observations of the contract behavior. We are not smart contract security experts. This document aims to explain what the contract appears to do based on the code. It should not be considered a comprehensive security audit or financial advice. Always verify critical information independently and consult with blockchain security professionals for important decisions.

⊙ generated by robots | curated by humans

METADATA
Contract Address 0x82eb1246...90cC37 (etherscan)
Network Ethereum Mainnet
Analysis Date 2026-06-02

Overview

This analysis worked from verified Solidity source. Because the contract is verified on Etherscan (Exact Match, Solidity 0.8.34), there was no decompilation step — the source is authoritative. The effort instead went into (a) reading the contract and its three verified dependencies, (b) decoding the constructor arguments to learn the exact wiring, (c) reconstructing on-chain state with cast to confirm the source matches reality, and (d) tracing a real withdrawal transaction to confirm the withdrawal path executes as written.

A key step was tracing the withdrawal: an early reading of the constructor calldata misattributed the burn-verifier address by one nibble, which suggested the verifier had no code. Tracing tx 0x45f7ccbc...4491d9 (tx) showed the true callee — 0x031b22ba...7Ab2ca (etherscan) — executing bn254 pairing precompiles and returning true. This confirmed addresses should be checked against execution rather than eyeballed calldata.

Thought Process

mindmap
  root((TacitBridgeMixer))
    Obtain
      Etherscan getsourcecode
      Verified Solidity 0.8.34
      5 source files
      Decode constructor args
    Understand
      Standalone, no proxy, no admin
      Two directions: deposit / withdrawFromBurn
      8 fixed ETH denominations
      4 external dependencies
    Dependencies
      BitcoinLightRelay (verified)
      SP1PoolRootVerifier (verified)
      Succinct SP1 gateway
      Groth16 verifier (unverified)
    Verify On-Chain
      cast call immutables
      cast storage slots 0-25
      poolIds, totalBalance
      trace a real withdrawal
    Risk
      No roles on the mixer
      Trust relocated to SNARKs + relay
      Unverified Groth16 verifier
      One day old, unaudited

Verification Guide

The analysis used Etherscan's API v2 for source, ABI, and creation metadata, and Foundry cast for on-chain reads and transaction tracing. The reference dApp (tacit.finance) and the upstream repository at the analyzed commit provided context for the Tacit-side semantics the bridge consumes.

External Resources


Commandline Tools

Tip

Commands below use cast from the Foundry Toolkit. To run them, set the RPC URL environment variable:

export ETH_RPC_URL=https://eth.llamarpc.com

Read the contract's immutable wiring

The contract has no admin, so its "configuration" is the set of immutable values fixed at deploy. Reading them confirms which relay and verifiers the bridge trusts.

# RELAY, BURN VERIFIER, TOKEN, ASSET, AND TREE PARAMETERS

cast call 0x82eb12463560e91a8b1d2312223e77c7c490cc37 "HEADER_RELAY()(address)"
cast call 0x82eb12463560e91a8b1d2312223e77c7c490cc37 "BURN_VERIFIER()(address)"
cast call 0x82eb12463560e91a8b1d2312223e77c7c490cc37 "TOKEN()(address)"
cast call 0x82eb12463560e91a8b1d2312223e77c7c490cc37 "UNIT_SCALE()(uint256)"
cast call 0x82eb12463560e91a8b1d2312223e77c7c490cc37 "totalBalance()(uint256)"

Enumerate the pools and verify denominations

# THE 8 POOL IDS AND THEIR DENOMINATIONS

cast call 0x82eb12463560e91a8b1d2312223e77c7c490cc37 "poolIds(uint256)(bytes32)" 0
cast call 0x82eb12463560e91a8b1d2312223e77c7c490cc37 "getPoolDenomination(bytes32)(uint256)" <pid>

Confirm storage layout

# SLOT 1 = totalBalance, SLOT 5 = poolIds LENGTH, SLOTS 6-25 = zeros[]

cast storage 0x82eb12463560e91a8b1d2312223e77c7c490cc37 1
cast storage 0x82eb12463560e91a8b1d2312223e77c7c490cc37 5
cast storage 0x82eb12463560e91a8b1d2312223e77c7c490cc37 7   # zeros[1] = Poseidon(0,0)

Verify the dependency wiring and SP1 state

# THE SP1 VERIFIER POINTS BACK AT THIS MIXER AND THE SAME ASSET

cast call 0x42ab3d9df0d5077ecfbd95adf3f99b3bea2a3ccb "MIXER()(address)"
cast call 0x42ab3d9df0d5077ecfbd95adf3f99b3bea2a3ccb "ASSET_ID()(bytes32)"
cast call 0x42ab3d9df0d5077ecfbd95adf3f99b3bea2a3ccb "SP1_VERIFIER()(address)"
cast call 0x42ab3d9df0d5077ecfbd95adf3f99b3bea2a3ccb "lastProvenPoolIndex(uint8)(uint64)" 0

# THE RELAY TIP HEIGHT (BITCOIN BLOCK THE BRIDGE IS ANCHORED TO)

cast call 0x363582956488ff615ecf75783fedc5adb18ca6d0 "tipHeight()(uint256)"

Trace a real withdrawal end-to-end

This is how the burn-verifier address and the full relay→SP1→Groth16 call sequence were confirmed.

# REPLAY A WITHDRAWAL AND INSPECT THE INTERNAL CALLS

cast run 0x45f7ccbcb1c3dc37cd6b83e1b2c9e26b138d504a9d5a5a537ed432d7264491d9 --quick

Token Cost Breakdown

PHASE DESCRIPTION TOKENS
Phase 0 Obtain the Contract 20 tok
Phase 1 Discovery & Understanding 35 tok
Phase 2 Deep Dive Analysis 30 tok
Phase 3 Risk & Trust Analysis 15 tok
Phase 4 Documentation Generation 30 tok
TOTAL Complete Contract Analysis 130 tok

Note: Token costs are estimates based on typical conversation lengths and complexity. Actual consumption may vary by ±10-15% depending on API responses, iterative refinement, and verification steps.