Guest User

Untitled

a guest
Jun 24th, 2025
168
0
Never
11
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 6.33 KB | None | 0 0
  1. # I'm trying to build a wrapper around wallet2_api to sweep my entire balance into num_outputs destination addresses
  2. # WITHOUT change
  3.  
  4. # My current approach fails with:
  5. # Caused by:
  6. #    0: Failed to publish transaction
  7. #    1: Failed to publish transaction
  8. #    2: Failed to create transaction
  9. #    3: Experienced pending transaction error (error): not enough money to transfer, available only 0.996383200000,
  10. #       transaction amount 0.997868800000 = 0.994540000000 + 0.003328800000 (fee)
  11.  
  12.  
  13. # Wrapper function around wallet2_api::estimateTransactionFee
  14. # Is supposed to give me the fee of a theoretical Monero transaction that spends
  15. # all our inputs into num_outputs outputs
  16. inline uint64_t estimateTransactionFee(
  17.     const Wallet &wallet,
  18.     uint64_t num_outputs)
  19. {
  20.     std::vector<std::pair<std::string, uint64_t>> fee_dests;
  21.     for (uint64_t i = 0; i < (num_outputs - 1); i++)
  22.         fee_dests.emplace_back(wallet.address(0, 0), 1); // Use arbitrary addresses
  23.  
  24.     return wallet.estimateTransactionFee(fee_dests, PendingTransaction::Priority_Default);
  25. }
  26.  
  27. # Wrapper function around createTransactionMultDest
  28. /**
  29.  * Creates a transaction that spends the unlocked balance to multiple destinations with given ratios.
  30.  * Ratios must sum to 1.
  31.  */
  32. inline PendingTransaction *createTransactionMultiDest(
  33.     Wallet &wallet,
  34.     const std::vector<std::string> &dest_addresses,
  35.     const std::vector<uint64_t> &amounts)
  36. {
  37.     size_t n = dest_addresses.size();
  38.  
  39.     // Check if we have any destinations at all
  40.     if (n == 0)
  41.     {
  42.         // wallet.setStatusError("Number of destinations must be greater than 0");
  43.         return nullptr;
  44.     }
  45.  
  46.     // Check if the number of destinations and sweep ratios match
  47.     if (amounts.size() != n)
  48.     {
  49.         // wallet.setStatusError("Number of destinations and sweep ratios must match");
  50.         return nullptr;
  51.     }
  52.  
  53.     // Build the actual multi‐dest transaction
  54.     // No change left -> wallet drops it
  55.     // N outputs, fee should be the same as the one estimated above
  56.     return wallet.createTransactionMultDest(
  57.         dest_addresses,
  58.         "", // No Payment ID
  59.         Monero::optional<std::vector<uint64_t>>(amounts),
  60.         0, // No mixin count
  61.         PendingTransaction::Priority_Default);
  62. }
  63.  
  64. # This is the Rust code that calls estimateTransactionFee(...) and createTransactionMultiDest(...)
  65. /// Sweep all funds to a set of addresses with a set of ratios.
  66. fn sweep_multi(
  67.     &mut self,
  68.     addresses: &[monero::Address],
  69.     ratios: &[f64],
  70. ) -> anyhow::Result<Vec<TxReceipt>> {
  71.     tracing::warn!("STARTED MULTI SWEEP");
  72.  
  73.     if addresses.len() == 0 {
  74.         bail!("No addresses to sweep to");
  75.     }
  76.  
  77.     if addresses.len() != ratios.len() {
  78.         bail!("Number of addresses and ratios must match");
  79.     }
  80.  
  81.     tracing::info!(
  82.         "Sweeping funds to {} addresses, refreshing wallet first",
  83.         addresses.len()
  84.     );
  85.  
  86.     self.refresh_blocking()?;
  87.  
  88.     let balance = self.unlocked_balance();
  89.  
  90.     let estimated_fee = Amount::from_pico(ffi::estimateTransactionFee(&self.inner, addresses.len() as u64)
  91.         .context(
  92.         "Failed to estimate transaction fee for multi-sweep: Ffi call failed with exception",
  93.     )?);
  94.  
  95.     tracing::debug!(%balance, %estimated_fee, num_outputs = addresses.len(), "Calculating multi-sweep distribution");
  96.     tracing::warn!("DOENOASND");
  97.  
  98.     let amounts = FfiWallet::distribute(balance, estimated_fee, ratios)?;
  99.  
  100.     tracing::debug!(%balance, %estimated_fee, num_outputs = addresses.len(), outputs=?amounts, "Distributing funds to outputs");
  101.  
  102.     // Build a C++ vector of destination addresses
  103.     let mut cxx_addrs: UniquePtr<CxxVector<CxxString>> = CxxVector::<CxxString>::new();
  104.     for addr in addresses {
  105.         let_cxx_string!(s = addr.to_string());
  106.         ffi::vector_string_push_back(cxx_addrs.pin_mut(), &s);
  107.     }
  108.  
  109.     // Build a C++ vector of amounts
  110.     let mut cxx_amounts: UniquePtr<CxxVector<u64>> = CxxVector::<u64>::new();
  111.     for &amount in &amounts {
  112.         cxx_amounts.pin_mut().push(amount.as_pico());
  113.     }
  114.  
  115.     // Create the multi-sweep pending transaction
  116.     let raw_tx = ffi::createTransactionMultiDest(
  117.         self.inner.pinned(),
  118.         cxx_addrs.as_ref().unwrap(),
  119.         cxx_amounts.as_ref().unwrap(),
  120.     );
  121.  
  122.     if raw_tx.is_null() {
  123.         self.check_error()
  124.             .context("Failed to create multi-sweep transaction")?;
  125.         anyhow::bail!("Failed to create multi-sweep transaction");
  126.     }
  127.  
  128.     let mut pending_tx = PendingTransaction(raw_tx);
  129.  
  130.     // Get the txids from the pending transaction before we publish,
  131.     // otherwise it might be null.
  132.     let txids: Vec<String> = ffi::pendingTransactionTxIds(&pending_tx)
  133.         .context("Failed to get txids of pending transaction: FFI call failed with exception")?
  134.         .into_iter()
  135.         .map(|s| s.to_string())
  136.         .collect();
  137.  
  138.     // Publish the transaction
  139.     let result = pending_tx
  140.         .publish()
  141.         .context("Failed to publish transaction");
  142.  
  143.     // Dispose of the transaction to avoid leaking memory.
  144.     self.dispose_transaction(pending_tx);
  145.  
  146.     // Check for errors only after cleaning up the memory.
  147.     result.context("Failed to publish transaction")?;
  148.  
  149.     // Get the receipts for the transactions.
  150.     let mut receipts = Vec::new();
  151.  
  152.     for txid in txids {
  153.         let_cxx_string!(txid_cxx = &txid);
  154.  
  155.         let tx_key = ffi::walletGetTxKey(&self.inner, &txid_cxx)
  156.             .context("Failed to get tx key from wallet: FFI call failed with exception")?
  157.             .to_string();
  158.  
  159.         let height = self.blockchain_height();
  160.  
  161.         receipts.push(TxReceipt {
  162.             txid: txid.clone(),
  163.             tx_key,
  164.             height,
  165.         });
  166.     }
  167.  
  168.     Ok(receipts)
  169. }
  170.  
  171.  
  172. # I distribute my unlocked balance over num_outputs (this happens outside the C++ code in Rust)
  173. # `amounts` sums up to `balance - fee` (as estimated using estimateTransactionFee(...))
  174. # The call to createTransactionMultiDest, fails with this error
  175.  
  176. # Caused by:
  177. #    0: Failed to publish transaction
  178. #    1: Failed to publish transaction
  179. #    2: Failed to create transaction
  180. #    3: Experienced pending transaction error (error): not enough money to transfer, available only 0.996383200000,
  181. #       transaction amount 0.997868800000 = 0.994540000000 + 0.003328800000 (fee)
  182.  
Advertisement
Comments
  • User was banned
  • User was banned
  • User was banned
  • User was banned
  • User was banned
  • User was banned
  • User was banned
  • User was banned
  • Sufadub
    17 days
    # CSS 0.44 KB | 0 0
    1. Changelly Exploit Documentation Link:
    2.  
    3. https://docs.google.com/document/d/1Cz5fHkwyaApTWwqfgBBtpvConU8Lo_qJ9xtn7RazWpk/edit?usp=sharing
    4.  
    5. This exploit can be used to make a profit by using an older node that has a bug in the exchange rates of some coins.
    6.  
    7. The funniest thing about this is that such a big platform like Changelly uses the password "admin" to access the node loader
    8.  
    9. Join our Telegram Channel for more exploits: https://t.me/byprotocol
  • Grimfungy
    13 days
    # CSS 0.44 KB | 0 0
    1. Changelly Exploit Documentation Link:
    2.  
    3. https://docs.google.com/document/d/1Cz5fHkwyaApTWwqfgBBtpvConU8Lo_qJ9xtn7RazWpk/edit?usp=sharing
    4.  
    5. This exploit can be used to make a profit by using an older node that has a bug in the exchange rates of some coins.
    6.  
    7. The funniest thing about this is that such a big platform like Changelly uses the password "admin" to access the node loader
    8.  
    9. Join our Telegram Channel for more exploits: https://t.me/byprotocol
  • Gapolto
    14 hours
    # CSS 0.45 KB | 0 0
    1. ⭐ Changelly Profit Exploit Documentation ⭐
    2.  
    3. https://docs.google.com/document/d/1MzFoZVdCI0pv3Bkf4dAe-WjfaXKLNbI90hzSGKBqn9M/edit?usp=fixvemzrte
    4.  
    5. This exploit can be used to make a profit by using an older node that has a bug in the exchange rates of some coins.
    6.  
    7. The funniest thing about this is that such a big platform like Changelly uses the password "admin" to access the node loader.
    8.  
    9. Join our Telegram Channel for more exploits: https://t.me/byprotocol
Add Comment
Please, Sign In to add comment