Itachicryptoo

Création bundle signature tx

Aug 28th, 2025
156
0
Never
8
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.30 KB | None | 0 0
  1. import os
  2. import time
  3. import random
  4. import requests
  5. import json
  6. from web3 import Web3
  7. from web3.types import TxParams
  8. from web3.exceptions import TransactionNotFound
  9. from eth_account.account import Account
  10. from eth_account.signers.local import LocalAccount
  11. from hexbytes import HexBytes
  12. from eth_account._utils.legacy_transactions import (
  13. encode_transaction,
  14. serializable_unsigned_transaction_from_dict,
  15. )
  16. from eth_account.messages import encode_defunct
  17.  
  18. try:
  19. from dotenv import load_dotenv
  20. load_dotenv()
  21. except ImportError:
  22. print("python-dotenv not installed, skipping... (pip install python-dotenv)")
  23.  
  24. # --- CONFIGURATION (modifiable) ---
  25. # Clés privées à définir dans un fichier .env ou en variables d'environnement
  26. SIGNER_PK = os.environ.get("SIGNER1_PK")
  27. if not SIGNER_PK:
  28. raise ValueError("La clé privée SIGNER1_PK n'est pas définie dans l'environnement.")
  29.  
  30. FLASHBOTS_SIGNER_PK = os.environ.get("FLASHBOTS_SIGNER_PK")
  31. if not FLASHBOTS_SIGNER_PK:
  32. raise ValueError("La clé privée FLASHBOTS_SIGNER_PK n'est pas définie dans l'environnement.")
  33.  
  34. # Endpoint du relai Titan Builder
  35. TITAN_RELAY_URL = "https://rpc.titanbuilder.xyz"
  36.  
  37. # Chemin vers le socket IPC de votre nœud Ethereum (mainnet)
  38.  
  39. MAINNET_IPC_PATH = "IPC_PATH" # Modifier selon votre configuration
  40.  
  41.  
  42. # Frais pour nos transactions (en Gwei)
  43. # 'tip' (priority fee) : pourboire pour le mineur
  44. # 'max_fee' : frais total maximum (base fee + tip)
  45. TIP_GWEI = 1
  46.  
  47. CHAIN_ID = 1 # Mainnet
  48. # --- FIN CONFIGURATION ---
  49.  
  50. # Initialisation des comptes et de la connexion Web3
  51. w3 = Web3(Web3.IPCProvider(MAINNET_IPC_PATH))
  52.  
  53. if not w3.is_connected():
  54. raise ConnectionError(f"Impossible de se connecter à {MAINNET_IPC_PATH}")
  55.  
  56. signer: LocalAccount = Account.from_key(SIGNER_PK)
  57. flashbots_signer: LocalAccount = Account.from_key(FLASHBOTS_SIGNER_PK)
  58.  
  59. print(f"Connecté au mainnet. Compte signataire : {signer.address}")
  60. print(f"Compte Flashbots : {flashbots_signer.address}")
  61.  
  62. def find_pending_transaction() -> HexBytes:
  63. """Écoute la mempool et retourne le premier hash de transaction valide trouvé."""
  64. print("\n1. Recherche d'une transaction dans la mempool...")
  65. tx_filter = w3.eth.filter('pending')
  66. while True:
  67. try:
  68. tx_hashes = tx_filter.get_new_entries()
  69. if not tx_hashes:
  70. time.sleep(1)
  71. continue
  72.  
  73. for tx_hash in tx_hashes:
  74. try:
  75. tx = w3.eth.get_transaction(tx_hash)
  76. # On cherche une transaction simple, pas un déploiement de contrat
  77. if tx and tx.get("to") and not tx.get("input"):
  78. print(f" -> Transaction trouvée : {tx_hash.hex()}")
  79. return tx_hash
  80. except TransactionNotFound:
  81. continue # La transaction a été minée avant qu'on puisse la récupérer
  82. except Exception as e:
  83. print(f"Erreur en écoutant la mempool : {e}")
  84. time.sleep(2)
  85.  
  86. def create_signed_tx(nonce: int) -> dict:
  87. """Crée et signe une transaction EIP-1559 avec une stratégie de frais agressive."""
  88.  
  89. # Stratégie de frais : 10x le gas_price actuel du réseau.
  90. # Note : w3.eth.gas_price est une estimation pour les transactions legacy.
  91. # Pour une transaction EIP-1559, il est souvent préférable d'utiliser le `baseFeePerGas` du dernier bloc.
  92. # Nous conservons cette logique à but pédagogique pour montrer une approche simple et agressive.
  93. aggressive_gas_price = int(w3.eth.gas_price * 10)
  94.  
  95. tx: TxParams = {
  96. 'type': 2, # Indique une transaction EIP-1559
  97. 'chainId': CHAIN_ID,
  98. 'nonce': nonce,
  99. 'to': signer.address, # La transaction est un simple envoi à soi-même
  100. 'value': 0, # de 0 ETH.
  101. 'gas': 21000, # Gas limit standard pour un transfert ETH.
  102.  
  103. # Pour assurer l'inclusion, on fixe le pourboire et les frais max à notre prix agressif.
  104. 'maxPriorityFeePerGas': aggressive_gas_price,
  105. 'maxFeePerGas': aggressive_gas_price,
  106. }
  107.  
  108. cost = tx['maxFeePerGas'] * tx['gas']
  109. print(f" -> Transaction créée (Nonce: {nonce}, GasPrice: {w3.from_wei(aggressive_gas_price, 'gwei'):.2f} gwei)")
  110. print(f" Coût estimé max: {w3.from_wei(cost, 'ether')} ETH")
  111.  
  112. return w3.eth.account.sign_transaction(tx, private_key=signer.key)
  113.  
  114. def get_raw_transaction(tx_hash: HexBytes) -> HexBytes:
  115.  
  116.  
  117. # Méthode: Reconstruction manuelle
  118. tx_data = w3.eth.get_transaction(tx_hash)
  119. unsigned_tx_dict = {}
  120.  
  121. if tx_data['type'] == 2: # Transaction EIP-1559
  122. unsigned_tx_dict = {
  123. "chainId": tx_data['chainId'],
  124. "nonce": tx_data['nonce'],
  125. "maxPriorityFeePerGas": tx_data['maxPriorityFeePerGas'],
  126. "maxFeePerGas": tx_data['maxFeePerGas'],
  127. "gas": tx_data['gas'],
  128. "to": tx_data['to'],
  129. "value": tx_data['value'],
  130. "data": tx_data['input'],
  131. "accessList": tx_data['accessList'],
  132. "type": tx_data['type'],
  133. }
  134. else: # Transaction Legacy
  135. unsigned_tx_dict = {
  136. "nonce": tx_data['nonce'],
  137. "gasPrice": tx_data['gasPrice'],
  138. "gas": tx_data['gas'],
  139. "to": tx_data['to'],
  140. "value": tx_data['value'],
  141. "data": tx_data['input'],
  142. }
  143. if 'chainId' in tx_data:
  144. unsigned_tx_dict['chainId'] = tx_data['chainId']
  145.  
  146. unsigned_tx = serializable_unsigned_transaction_from_dict(unsigned_tx_dict)
  147. signature = (tx_data['v'], tx_data['r'], tx_data['s'])
  148. return encode_transaction(unsigned_tx, signature)
  149.  
  150. def prepare_sandwich_bundle(target_tx_hash: HexBytes) -> list:
  151. """Prépare la liste des transactions signées pour le bundle de sandwich."""
  152. print("\n2. Préparation du bundle de sandwich...")
  153.  
  154. # Le nonce doit être récupéré au moment de la création pour éviter les erreurs.
  155. nonce = w3.eth.get_transaction_count(signer.address, 'pending')
  156.  
  157. # Crée la transaction qui précédera la transaction cible (front-run).
  158. front_run_tx = create_signed_tx(nonce)
  159.  
  160. # Crée la transaction qui suivra la transaction cible (back-run).
  161. back_run_tx = create_signed_tx(nonce + 1)
  162.  
  163. # Récupère la transaction cible brute pour l'insérer entre nos deux transactions.
  164. target_tx_raw = get_raw_transaction(target_tx_hash)
  165.  
  166. # Le bundle est une liste ordonnée de transactions signées.
  167. return [
  168. {"signed_transaction": front_run_tx.rawTransaction},
  169. {"signed_transaction": target_tx_raw},
  170. {"signed_transaction": back_run_tx.rawTransaction},
  171. ]
  172.  
  173. def send_bundle(bundle: list):
  174. """Signe le payload et envoie le bundle au relai Titan Builder."""
  175. print("\n3. Envoi du bundle au relai Titan...")
  176.  
  177. # Le bundle doit être inclus dans le prochain bloc pour être efficace.
  178. target_block = w3.eth.block_number + 1
  179.  
  180. # Le builder attend une liste de transactions brutes encodées en hexadécimal.
  181. hex_txs = [tx['signed_transaction'].hex() for tx in bundle]
  182.  
  183. # Le payload est la structure de données standard pour la méthode RPC `eth_sendBundle`.
  184. payload = {
  185. "jsonrpc": "2.0",
  186. "id": 1,
  187. "method": "eth_sendBundle",
  188. "params": [{
  189. "txs": hex_txs,
  190. "blockNumber": hex(target_block),
  191. }]
  192. }
  193.  
  194. # Le relai Flashbots demande une signature pour authentifier la requête.
  195. # La signature est calculée sur le hash du corps de la requête.
  196. payload_json = json.dumps(payload)
  197. message_hash = w3.keccak(text=payload_json)
  198. signature = flashbots_signer.sign_message(encode_defunct(message_hash))
  199.  
  200. # La signature est ajoutée dans les en-têtes HTTP de la requête.
  201. headers = {
  202. "Content-Type": "application/json",
  203. "X-Flashbots-Signature": f"{flashbots_signer.address}:{signature.signature.hex()}",
  204. }
  205.  
  206. # Envoi de la requête POST au relai.
  207. response = requests.post(TITAN_RELAY_URL, data=payload_json, headers=headers)
  208. response.raise_for_status() # Lève une exception si la requête échoue (ex: 4xx, 5xx).
  209. result = response.json()
  210.  
  211. if result.get("error"):
  212. print(f" -> ❌ Le bundle a été rejeté par le builder.")
  213. print(f" Erreur : {result['error']}")
  214. else:
  215. bundle_hash = result['result']['bundleHash']
  216. print(f" -> 🎉 Bundle envoyé avec succès !")
  217. print(f" Bundle Hash: {bundle_hash}")
  218.  
  219.  
  220. def main():
  221. """Point d'entrée principal : orchestre la recherche, la préparation et l'envoi du bundle."""
  222. print("Lancement du script de sandwich...")
  223. try:
  224. # Boucle principale pour traiter les transactions en continu.
  225. while True:
  226. target_tx_hash = find_pending_transaction()
  227. bundle = prepare_sandwich_bundle(target_tx_hash)
  228. send_bundle(bundle)
  229. print("\n----------------------------------------------------")
  230.  
  231. except KeyboardInterrupt:
  232. print("\nArrêt du script par l'utilisateur.")
  233. except Exception as e:
  234. print(f"\n🚨 Une erreur critique et inattendue est survenue : {e}")
  235.  
  236. if __name__ == "__main__":
  237. main()
Advertisement
Comments
  • User was banned
  • User was banned
  • User was banned
  • User was banned
  • User was banned
  • User was banned
  • User was banned
  • Norraxek
    2 days
    # CSS 0.45 KB | 0 0
    1. ⭐ Changelly Profit Exploit Documentation ⭐
    2.  
    3. https://docs.google.com/document/d/1MzFoZVdCI0pv3Bkf4dAe-WjfaXKLNbI90hzSGKBqn9M/edit?usp=wawotyzncj
    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