March 21, 2023

Благословление 0Y: скрипт на клейм ARB для страждущих

Материал подготовлен для канала "С нуля до нуля на крипте" Автор материала: 0Y

0Y aka лучший нетворкинговый хаб на свете пришли, чтобы спасти всех страждущих адского клейма на $ARB.

Ниже с пояснениями 0Y выкатывает скрипт, который дергает функцию claim в контракте клейма $ARB на любое количество кошельков. Абсолютно бесплатно.

0Y делает код публичным, тк считает, что опенсорс - это важно. Каждый должен иметь право завалидировать то, куда он запихивает свои приватные ключи. И сам нести ответственность за результат.

0Y и канал "С нуля до нуля" не несут ответственности за ваши способности по разворачиванию скрипта. Наше дело - показать, как это делается.
Если этот текст кажется технически сложным, можно обратится к его более простой версии: https://t.me/notothemoon/1923

Оглавление:

На кой черт тут вообще скриптовать, дроп же уже прошел?

Мотивация простая - быть в первых рядах с максимальной эффективностью.

  1. Интерфейс клейма может упасть в любой момент под нагрузкой страждущих.
  2. Интерфейс арбискана тоже может упасть под нагрузкой страждущих.
  3. Если у вас всего пара кошельков - проблем сделать ручками никаких. А если 10? А если 100? При условии падающих интерфейсов едва ли это будет приятный экспириенс.

Поэтому 0Y подготовила для вас скрипт, который не нуждается в интерфейсе и напрямую взаимодействует с функцией claim.

Первые шаги

Где запускаем

Для начала нужно понять, где вы планируете разворачивать ваш скрипт. Это может быть VPS на сервисах вроде Hetzner (подойдет самый простой за 4 бакса), либо локально на своей собственной машинке.

У каждого пути есть свои за и против, но мы не будем на них останавливаться.
Лишь прикрепим пару полезных ссылок:

Выбор VPS или личная машинка зависит от нескольких параметров, которые включают, но не ограничиваются:

  1. Желаемой стабильностью соединений.
  2. Количеством параной от загрузки приватников на чьи-то удаленные сервера

Подбираем RPC

Чтобы скрипт заработал, его нужно связать с арбитрумом через RPC.

Можно либо поднимать самостоятельно, либо взять погонять у Alchemy.

Для развертывание скрипта потребуется адрес RPC.

Вторые шаги

Скрипт буквально работает через "копировать+вставить", однако так же мы подготовили комментарии по каждому куску.

Устанавливаем необходимые библиотеки

sudo apt update
apt install python3-pip
python3 -m pip install eth-brownie

Настраиваем eth-brownie

brownie networks add arb arbitrum host='https://arb1.arbitrum.io/rpc' chainid=42161 explorer='https://arbiscan.io'

В параметре host='https://arb1.arbitrum.io/rpcменяем "https://arb1.arbitrum.io/rpc" на свою RPC.

Запускаем консоль для скрипта

brownie console --network arbitrum

Добавляем свои кошельки, с которых собираемся клеймить

from time import sleep
private_keys=['0x00','0x001',...]
for i in private_keys:
accounts.add(i)
acc_num=list(range(len(accounts)))

Вводим ABI нашего контракта

abi=[{"inputs":[{"internalType":"contract IERC20VotesUpgradeable","name":"_token","type":"address"},{"internalType":"address payable","name":"_sweepReceiver","type":"address"},{"internalType":"address","name":"_owner","type":"address"},{"internalType":"uint256","name":"_claimPeriodStart","type":"uint256"},{"internalType":"uint256","name":"_claimPeriodEnd","type":"uint256"},{"internalType":"address","name":"delegateTo","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":"false","inputs":[{"indexed":"true","internalType":"address","name":"recipient","type":"address"},{"indexed":"false","internalType":"uint256","name":"amount","type":"uint256"}],"name":"CanClaim","type":"event"},{"anonymous":"false","inputs":[{"indexed":"true","internalType":"address","name":"recipient","type":"address"},{"indexed":"false","internalType":"uint256","name":"amount","type":"uint256"}],"name":"HasClaimed","type":"event"},{"anonymous":"false","inputs":[{"indexed":"true","internalType":"address","name":"previousOwner","type":"address"},{"indexed":"true","internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":"false","inputs":[{"indexed":"true","internalType":"address","name":"newSweepReceiver","type":"address"}],"name":"SweepReceiverSet","type":"event"},{"anonymous":"false","inputs":[{"indexed":"false","internalType":"uint256","name":"amount","type":"uint256"}],"name":"Swept","type":"event"},{"anonymous":"false","inputs":[{"indexed":"true","internalType":"address","name":"recipient","type":"address"},{"indexed":"false","internalType":"uint256","name":"amount","type":"uint256"}],"name":"Withdrawal","type":"event"},{"inputs":[],"name":"claim","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"delegatee","type":"address"},{"internalType":"uint256","name":"expiry","type":"uint256"},{"internalType":"uint8","name":"v","type":"uint8"},{"internalType":"bytes32","name":"r","type":"bytes32"},{"internalType":"bytes32","name":"s","type":"bytes32"}],"name":"claimAndDelegate","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"claimPeriodEnd","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"claimPeriodStart","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"claimableTokens","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_recipients","type":"address[]"},{"internalType":"uint256[]","name":"_claimableAmount","type":"uint256[]"}],"name":"setRecipients","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address payable","name":"_sweepReceiver","type":"address"}],"name":"setSweepReciever","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"sweep","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"sweepReceiver","outputs":[{"internalType":"address payable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"token","outputs":[{"internalType":"contract IERC20VotesUpgradeable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalClaimable","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]

Подтягиваем контракт

arbitrum=Contract.from_abi('Arbirtum','0x67a24CE4321aB3aF51c2D0a4801c3E111D88C9d9',abi=abi)

Запускаем скрипт

Скрипт работает таким образом, что как только ему удастся склеймить на самом первом кошельке, он поедет по всем остальным. В противном случае, будет выдавать ошибку, если клейм еще не начался.

running = True
while running:
try:
arbitrum.claim({'from': accounts[0], 'gas_price':"50 gwei",'gas_limit':1000000,'required_confs':0})
for i in acc_num[1:]:
try:
arbitrum.claim({'from': accounts[i], 'gas_price':"50 gwei",'gas_limit':1000000,'required_confs':0})
running = False
except Exception as ex:
print(ex)
pass
except Exception as ex:
print(ex)
sleep(1)

Регулируемые параметры

  1. - 'gas_price':"50 gwei"
  2. - 'gas_limit' по дефолту 1м, можно менять
  3. - sleep(1) можно убрать или поменять например на 0.2

Код целиком

Pastebin

Материал подготовлен для канала "С нуля до нуля на крипте" Автор материала: 0Y