#!/usr/bin/env python3 import os from web3 import Web3 from datetime import datetime import json from dotenv import load_dotenv # Load environment variables from .env file load_dotenv() # Configuration BASE_RPC_URL = "https://mainnet.base.org" # Base mainnet RPC CONTRACT_ADDRESS = "0xDf2027318D27c4eD1C047B4d6247A7a705bb407b" # Base contract address PRIVATE_KEY = os.getenv('PRIVATE_KEY') # Read from .env file # Contract ABI - createStakes and clearStakes functions CONTRACT_ABI = [ { "inputs": [ { "components": [ {"internalType": "address", "name": "user", "type": "address"}, {"internalType": "uint256", "name": "amount", "type": "uint256"}, {"internalType": "uint256", "name": "lastClaimed", "type": "uint256"}, {"internalType": "uint256", "name": "unlockTime", "type": "uint256"}, {"internalType": "uint256", "name": "dailyRewardRate", "type": "uint256"} ], "internalType": "struct PacaFinanceWithBoostAndScheduleBase.StakeInput[]", "name": "stakesInput", "type": "tuple[]" } ], "name": "createStakes", "outputs": [], "stateMutability": "payable", "type": "function" }, { "inputs": [ {"internalType": "address", "name": "user", "type": "address"} ], "name": "clearStakes", "outputs": [], "stateMutability": "nonpayable", "type": "function" } ] # Convert CSV-like data to timestamp def parse_date(date_str): """Convert 'YYYY-MM-DD HH:MM:SS' to Unix timestamp""" dt = datetime.strptime(date_str, '%Y-%m-%d %H:%M:%S') return int(dt.timestamp()) # Stakes data with amounts from CSV and correct unlock times from original stakes # Format: (stake_id, address, amount, original_amount, last_claimed_str, pool_id, rewards, lockup_period, reward_rate, csv_unlock_time, complete) stakes_data = [ (0, "0xe1AbEC319515757e77482337eE1f99ccA2E1A500", 500000000, 500000000, "2025-06-02 02:32:14", 0, 1557129, 64, 40, 64, "no"), (1, "0xe1AbEC319515757e77482337eE1f99ccA2E1A500", 555000000, 555000000, "2025-06-02 02:32:14", 1, 1728413, 64, 40, 64, "no"), (2, "0xe1AbEC319515757e77482337eE1f99ccA2E1A500", 100000000, 100000000, "2025-06-02 02:32:14", 2, 319211, 64, 41, 64, "no"), (3, "0xe1AbEC319515757e77482337eE1f99ccA2E1A500", 500000000, 500000000, "2025-05-31 02:32:14", 3, 1557129, 66, 40, 66, "no"), (4, "0xe1AbEC319515757e77482337eE1f99ccA2E1A500", 5000000, 5000000, "2025-05-31 02:32:14", 4, 15571, 66, 40, 66, "no"), (5, "0xe1AbEC319515757e77482337eE1f99ccA2E1A500", 64249391, 64249391, "2025-05-23 02:32:14", 5, 170075, 74, 34, 74, "no"), (6, "0xe1AbEC319515757e77482337eE1f99ccA2E1A500", 60020374, 60020374, "2025-05-14 02:32:14", 6, 158881, 83, 34, 83, "no"), (7, "0xe1AbEC319515757e77482337eE1f99ccA2E1A500", 28330011, 28330011, "2025-05-10 02:32:14", 7, 90432, 87, 41, 87, "no"), (8, "0xe1AbEC319515757e77482337eE1f99ccA2E1A500", 49737274, 49737274, "2025-05-03 02:32:14", 8, 158767, 94, 41, 94, "no"), (9, "0xe1AbEC319515757e77482337eE1f99ccA2E1A500", 29634199, 29634199, "2025-04-29 02:32:14", 9, 94595, 98, 41, 98, "no"), (10, "0xe1AbEC319515757e77482337eE1f99ccA2E1A500", 23048084, 23048084, "2025-04-26 02:32:14", 10, 61011, 101, 34, 101, "no"), (11, "0xe1AbEC319515757e77482337eE1f99ccA2E1A500", 22707593, 22707593, "2025-04-23 02:32:14", 11, 60109, 104, 34, 104, "no"), (12, "0xe1AbEC319515757e77482337eE1f99ccA2E1A500", 25345568, 25345568, "2025-04-20 02:32:14", 12, 67092, 107, 34, 107, "no"), (13, "0xe1AbEC319515757e77482337eE1f99ccA2E1A500", 36625321, 36625321, "2025-04-15 02:32:14", 13, 96951, 112, 34, 112, "no"), (14, "0xe1AbEC319515757e77482337eE1f99ccA2E1A500", 31761689, 31761689, "2025-04-11 02:32:14", 14, 84077, 116, 34, 116, "no"), (15, "0xe1AbEC319515757e77482337eE1f99ccA2E1A500", 23054529, 23054529, "2025-04-08 02:32:14", 15, 70002, 119, 39, 119, "no"), (16, "0xe1AbEC319515757e77482337eE1f99ccA2E1A500", 762540000, 762540000, "2025-04-08 02:32:14", 16, 2315378, 119, 39, 119, "no"), (17, "0xe1AbEC319515757e77482337eE1f99ccA2E1A500", 33544394, 33544394, "2025-04-05 02:32:14", 17, 107077, 122, 41, 122, "no"), (18, "0xe1AbEC319515757e77482337eE1f99ccA2E1A500", 45207172, 45207172, "2025-04-01 02:32:14", 18, 119668, 126, 34, 126, "no"), (19, "0xe1AbEC319515757e77482337eE1f99ccA2E1A500", 38218086, 38218086, "2025-03-29 02:32:14", 19, 101167, 129, 34, 129, "no"), (20, "0xe1AbEC319515757e77482337eE1f99ccA2E1A500", 41700000, 41700000, "2025-03-29 02:32:14", 20, 110384, 129, 34, 129, "no"), (21, "0xe1AbEC319515757e77482337eE1f99ccA2E1A500", 23741006, 23741006, "2025-03-27 02:32:14", 21, 62845, 131, 34, 131, "no"), (22, "0xe1AbEC319515757e77482337eE1f99ccA2E1A500", 46927685, 46927685, "2025-03-23 02:32:14", 22, 124223, 135, 34, 135, "no"), (23, "0xe1AbEC319515757e77482337eE1f99ccA2E1A500", 120000000, 120000000, "2025-03-22 02:32:14", 23, 383053, 136, 41, 136, "no"), (24, "0xe1AbEC319515757e77482337eE1f99ccA2E1A500", 115000000, 115000000, "2025-03-22 02:32:14", 24, 367093, 136, 41, 136, "no"), (25, "0xe1AbEC319515757e77482337eE1f99ccA2E1A500", 45147055, 45147055, "2025-03-19 02:32:14", 25, 144114, 139, 41, 139, "no"), (26, "0xe1AbEC319515757e77482337eE1f99ccA2E1A500", 41042676, 41042676, "2025-03-16 02:32:14", 26, 131012, 142, 41, 142, "no"), (27, "0xe1AbEC319515757e77482337eE1f99ccA2E1A500", 43109632, 43109632, "2025-03-13 02:32:14", 27, 114116, 145, 34, 145, "no"), (28, "0xe1AbEC319515757e77482337eE1f99ccA2E1A500", 25191734, 25191734, "2025-03-11 02:32:14", 28, 66685, 147, 34, 147, "no"), (29, "0xe1AbEC319515757e77482337eE1f99ccA2E1A500", 49039377, 49039377, "2025-03-07 02:32:14", 29, 148903, 151, 39, 151, "no"), (30, "0xe1AbEC319515757e77482337eE1f99ccA2E1A500", 30703113, 30703113, "2025-03-05 02:32:14", 30, 93227, 153, 39, 153, "no"), (31, "0xe1AbEC319515757e77482337eE1f99ccA2E1A500", 40403249, 40403249, "2025-03-02 02:32:14", 31, 122680, 156, 39, 156, "no"), (32, "0xe1AbEC319515757e77482337eE1f99ccA2E1A500", 52333588, 52333588, "2025-02-26 02:32:14", 32, 138533, 160, 34, 160, "no"), (33, "0xe1AbEC319515757e77482337eE1f99ccA2E1A500", 47850170, 47850170, "2025-02-23 02:32:14", 33, 126665, 163, 34, 163, "no"), (34, "0xe1AbEC319515757e77482337eE1f99ccA2E1A500", 36399553, 36399553, "2025-02-20 02:32:14", 34, 96353, 166, 34, 166, "no"), (35, "0xe1AbEC319515757e77482337eE1f99ccA2E1A500", 29872672, 29872672, "2024-10-26 02:32:14", 35, 95357, 283, 41, 283, "no"), (36, "0xe1AbEC319515757e77482337eE1f99ccA2E1A500", 1265200000, 1265200000, "2024-10-25 02:32:14", 36, 4038664, 284, 41, 284, "no"), (37, "0xe1AbEC319515757e77482337eE1f99ccA2E1A500", 60141052, 60141052, "2024-10-21 02:32:14", 37, 191977, 288, 41, 288, "no"), (38, "0xe1AbEC319515757e77482337eE1f99ccA2E1A500", 1000000000, 1000000000, "2024-10-20 02:32:14", 38, 3192115, 289, 41, 289, "no"), (39, "0xe1AbEC319515757e77482337eE1f99ccA2E1A500", 106040000, 106040000, "2024-10-17 02:32:14", 39, 338491, 292, 41, 292, "no"), (40, "0xe1AbEC319515757e77482337eE1f99ccA2E1A500", 49348009, 49348009, "2025-02-04 02:32:14", 40, 130630, 182, 34, 182, "no"), (41, "0xe1AbEC319515757e77482337eE1f99ccA2E1A500", 49649369, 49649369, "2025-02-02 02:32:14", 41, 131427, 184, 34, 184, "no"), (42, "0xe1AbEC319515757e77482337eE1f99ccA2E1A500", 602810000, 602810000, "2025-01-31 02:32:14", 42, 1595710, 186, 34, 186, "no"), (43, "0xe1AbEC319515757e77482337eE1f99ccA2E1A500", 55147108, 55147108, "2025-01-29 02:32:14", 43, 145981, 188, 34, 188, "no"), (44, "0xe1AbEC319515757e77482337eE1f99ccA2E1A500", 86517786, 86517786, "2025-01-26 02:32:14", 44, 255966, 191, 38, 191, "no"), (45, "0xe1AbEC319515757e77482337eE1f99ccA2E1A500", 1722950000, 1722950000, "2025-01-23 02:32:14", 45, 5097427, 194, 38, 194, "no"), (46, "0xe1AbEC319515757e77482337eE1f99ccA2E1A500", 1280990000, 1280990000, "2025-01-21 02:32:14", 46, 3789868, 196, 38, 196, "no"), (47, "0xe1AbEC319515757e77482337eE1f99ccA2E1A500", 65944936, 65944936, "2025-01-19 02:32:14", 47, 210503, 198, 41, 198, "no"), (48, "0xe1AbEC319515757e77482337eE1f99ccA2E1A500", 812080000, 812080000, "2025-01-19 02:32:14", 48, 2592253, 198, 41, 198, "no"), (49, "0xe1AbEC319515757e77482337eE1f99ccA2E1A500", 1167490000, 1167490000, "2025-01-17 02:32:14", 49, 3726763, 200, 41, 200, "no"), (50, "0xe1AbEC319515757e77482337eE1f99ccA2E1A500", 200690000, 200690000, "2025-01-15 02:32:14", 50, 640625, 202, 41, 202, "no"), (51, "0xe1AbEC319515757e77482337eE1f99ccA2E1A500", 77691951, 77691951, "2025-01-14 02:32:14", 51, 248001, 203, 41, 203, "no"), (52, "0xe1AbEC319515757e77482337eE1f99ccA2E1A500", 992680000, 992680000, "2025-01-14 02:32:14", 52, 3168749, 203, 41, 203, "no"), (53, "0xe1AbEC319515757e77482337eE1f99ccA2E1A500", 1750000000, 1750000000, "2025-01-10 02:32:14", 53, 5586202, 207, 41, 207, "no"), (54, "0xe1AbEC319515757e77482337eE1f99ccA2E1A500", 1276680000, 1276680000, "2025-01-07 02:32:14", 54, 4075310, 210, 41, 210, "no"), (55, "0xe1AbEC319515757e77482337eE1f99ccA2E1A500", 31529749, 31529749, "2025-01-03 02:32:14", 55, 100646, 214, 41, 214, "no"), (56, "0xe1AbEC319515757e77482337eE1f99ccA2E1A500", 86528141, 86528141, "2025-01-02 02:32:14", 56, 229050, 215, 34, 215, "no"), (57, "0xe1AbEC319515757e77482337eE1f99ccA2E1A500", 228548767, 228548767, "2024-12-29 02:32:14", 57, 729554, 219, 41, 219, "no"), (58, "0xe1AbEC319515757e77482337eE1f99ccA2E1A500", 135560922, 135560922, "2024-12-27 02:32:14", 58, 358846, 221, 34, 221, "no"), (59, "0xe1AbEC319515757e77482337eE1f99ccA2E1A500", 107108280, 107108280, "2024-12-26 02:32:14", 59, 283528, 222, 34, 222, "no"), (60, "0xe1AbEC319515757e77482337eE1f99ccA2E1A500", 367606256, 367606256, "2024-12-20 02:32:14", 60, 973098, 228, 34, 228, "no"), (61, "0xe1AbEC319515757e77482337eE1f99ccA2E1A500", 116416549, 116416549, "2024-12-18 02:32:14", 61, 308168, 230, 34, 230, "no"), (62, "0xe1AbEC319515757e77482337eE1f99ccA2E1A500", 50417595, 50417595, "2024-12-18 02:32:14", 62, 160938, 230, 41, 230, "no"), (63, "0xe1AbEC319515757e77482337eE1f99ccA2E1A500", 82748602, 82748602, "2024-12-16 02:32:14", 63, 219045, 232, 34, 232, "no"), (64, "0xe1AbEC319515757e77482337eE1f99ccA2E1A500", 1680040000, 1680040000, "2024-12-13 02:32:14", 64, 4447268, 235, 34, 235, "no"), (65, "0xe1AbEC319515757e77482337eE1f99ccA2E1A500", 2478600000, 2478600000, "2024-08-15 02:32:14", 65, 8104953, 355, 42, 355, "no"), (66, "0xe1AbEC319515757e77482337eE1f99ccA2E1A500", 825000000, 825000000, "2024-08-13 02:32:14", 66, 2697727, 357, 42, 357, "no"), (67, "0xe1AbEC319515757e77482337eE1f99ccA2E1A500", 1321260000, 1321260000, "2024-12-03 02:32:14", 67, 3600402, 245, 35, 245, "no"), (68, "0xe1AbEC319515757e77482337eE1f99ccA2E1A500", 203269777, 203269777, "2024-12-01 02:32:14", 68, 553905, 247, 35, 247, "no"), ] # Correct unlock times from original stakes data (in same order) # Format: [amount, lastClaimed, dailyRewardRate, unlockTime, complete] original_unlock_times = [ 1759891211, 1759891305, 1759918669, 1760077071, 1760088359, 1760784185, 1761539197, 1761885285, 1762483073, 1762829419, 1763094435, 1763352841, 1763638363, 1764046369, 1764394603, 1764643955, 1764644281, 1764906275, 1765255337, 1765546435, 1765546657, 1765723037, 1766069703, 1766116935, 1766118637, 1766377609, 1766650301, 1766933067, 1767096487, 1767412575, 1767607691, 1767862209, 1768188137, 1768482369, 1768703629, 1778819647, 1778947171, 1779252457, 1779331565, 1779633187, 1770087661, 1770262065, 1770438873, 1770616539, 1770893373, 1771123569, 1771308419, 1771455451, 1771514943, 1771687647, 1771825181, 1771965131, 1771965439, 1772301051, 1772560007, 1772864375, 1772979599, 1773282569, 1773459725, 1773598729, 1774073209, 1774220717, 1774284231, 1774388161, 1774720189, 1785097545, 1785208749, 1775513771, 1775702013 ] def main(): if not PRIVATE_KEY: print("ERROR: Please set the PRIVATE_KEY environment variable") return # Connect to Base print("Connecting to Base network...") w3 = Web3(Web3.HTTPProvider(BASE_RPC_URL)) if not w3.is_connected(): print("ERROR: Could not connect to Base network") return print(f"Connected to Base! Latest block: {w3.eth.block_number}") # Setup account account = w3.eth.account.from_key(PRIVATE_KEY) print(f"Using account: {account.address}") # Setup contract contract = w3.eth.contract( address=Web3.to_checksum_address(CONTRACT_ADDRESS), abi=CONTRACT_ABI ) # Prepare stakes data for the contract stakes_input = [] for i, stake in enumerate(stakes_data): stake_id, address, amount, original_amount, last_claimed_str, pool_id, rewards, lockup_period, reward_rate, csv_unlock_time, complete = stake # Use the correct values from original stakes data last_claimed_timestamp = 1754275845 # From original stakes data (same for all) unlock_time = original_unlock_times[i] # Use corresponding unlock time from original data # Create stake input (mapping to contract struct) # StakeInput: user, amount, lastClaimed, unlockTime, dailyRewardRate stake_input = { 'user': Web3.to_checksum_address(address), 'amount': amount, # Amount from CSV data 'lastClaimed': last_claimed_timestamp, # From original stakes (more accurate) 'unlockTime': unlock_time, # From original stakes (correct unlock times) 'dailyRewardRate': reward_rate # From CSV data } stakes_input.append(stake_input) print(f"Prepared {len(stakes_input)} stakes for submission") # First, clear existing stakes for the user # user_address = Web3.to_checksum_address("0xe1AbEC319515757e77482337eE1f99ccA2E1A500") # print(f"\n๐Ÿงน Step 1: Clearing existing stakes for {user_address}") # Get current gas price and nonce gas_price = w3.eth.gas_price print(f"Current gas price: {w3.from_wei(gas_price, 'gwei')} Gwei") nonce = w3.eth.get_transaction_count(account.address) # Build clearStakes transaction # try: # clear_gas_estimate = contract.functions.clearStakes(user_address).estimate_gas({ # 'from': account.address # }) # print(f"Clear stakes gas estimate: {clear_gas_estimate}") # except Exception as e: # print(f"ERROR: Clear stakes gas estimation failed: {e}") # return # clear_transaction = contract.functions.clearStakes(user_address).build_transaction({ # 'from': account.address, # 'gas': int(clear_gas_estimate * 1.2), # 'gasPrice': gas_price, # 'nonce': nonce, # 'value': 0 # }) # print(f"Clear stakes transaction:") # print(f" Gas: {clear_transaction['gas']}") # print(f" Est. cost: {w3.from_wei(clear_transaction['gas'] * clear_transaction['gasPrice'], 'ether')} ETH") # Ask for confirmation # confirm_clear = input("\nDo you want to clear existing stakes first? (yes/no): ") # if confirm_clear.lower() != 'yes': # print("Operation cancelled") # return # Sign and send clear transaction # print("\n๐Ÿš€ Sending clearStakes transaction...") # signed_clear_txn = w3.eth.account.sign_transaction(clear_transaction, private_key=PRIVATE_KEY) # clear_tx_hash = w3.eth.send_raw_transaction(signed_clear_txn.raw_transaction) # print(f"Clear transaction sent! Hash: {clear_tx_hash.hex()}") # Wait for clear transaction confirmation # print("Waiting for clear transaction confirmation...") # clear_tx_receipt = w3.eth.wait_for_transaction_receipt(clear_tx_hash) # if clear_tx_receipt.status != 1: # print(f"โŒ Clear transaction failed! Hash: {clear_tx_receipt.transactionHash.hex()}") # return # print(f"โœ… Existing stakes cleared successfully!") # print(f" Block: {clear_tx_receipt.blockNumber}") # print(f" Gas used: {clear_tx_receipt.gasUsed}") print(f"\n๐Ÿ—๏ธ Creating {len(stakes_input)} new stakes") # Get nonce for transaction # nonce = w3.eth.get_transaction_count(account.address) # Estimate gas try: gas_estimate = contract.functions.createStakes(stakes_input).estimate_gas({ 'from': account.address, 'value': 0 # No ETH being sent }) print(f"Estimated gas: {gas_estimate}") except Exception as e: print(f"ERROR: Gas estimation failed: {e}") return # Build the transaction transaction = contract.functions.createStakes(stakes_input).build_transaction({ 'from': account.address, 'gas': int(gas_estimate * 1.2), # Add 20% buffer 'gasPrice': gas_price, 'nonce': nonce, 'value': 0 }) print(f"Transaction details:") print(f" To: {transaction['to']}") print(f" Gas: {transaction['gas']}") print(f" Gas Price: {w3.from_wei(transaction['gasPrice'], 'gwei')} Gwei") print(f" Est. cost: {w3.from_wei(transaction['gas'] * transaction['gasPrice'], 'ether')} ETH") # Ask for confirmation confirm = input("\nDo you want to submit this transaction? (yes/no): ") if confirm.lower() != 'yes': print("Transaction cancelled") return # Sign and send transaction print("\nSigning transaction...") signed_txn = w3.eth.account.sign_transaction(transaction, private_key=PRIVATE_KEY) print("Sending transaction...") tx_hash = w3.eth.send_raw_transaction(signed_txn.raw_transaction) print(f"Transaction sent! Hash: {tx_hash.hex()}") # Wait for confirmation print("Waiting for confirmation...") tx_receipt = w3.eth.wait_for_transaction_receipt(tx_hash) if tx_receipt.status == 1: print(f"โœ… Transaction successful!") print(f" Block: {tx_receipt.blockNumber}") print(f" Gas used: {tx_receipt.gasUsed}") print(f" Transaction hash: {tx_receipt.transactionHash.hex()}") else: print(f"โŒ Transaction failed!") print(f" Transaction hash: {tx_receipt.transactionHash.hex()}") if __name__ == "__main__": main()