Разбор изощренной мошеннической схемы с поддельным мейннетом GIWA, в результате которой 27.09.2026 пользователи потеряли 766 ETH, а децентрализованная биржа DYORSWAP подверглась атаке из-за интеграции фейкового RPC.
Изощренный обман: как подделывают блокчейн
Листаю ленту мониторинга безопасности и ... чуть чашку не выронил. Семьсот шестьдесят шесть эфиров. Просто в никуда. И ладно бы классический фишинг через поддельную либу или взлом контракта с флэш-лоунами — этого я навидался. Но тут схема куда изящнее. Мошенники подняли фальшивый майннет GIWA, прикрутили к нему чужой DEX и выпотрошили пользователей на пару миллионов долларов.
Давайте разберем этот инцидент детально, потому что архитектурно здесь есть на что посмотреть инженерным взглядом. Как специалист по ИБ и действующий CTO, я прямо-таки восхищаюсь дерзостью реализации, хотя ребятам из DYORSWAP, конечно, не позавидуешь.
Погодите, а как вообще можно "подделать" блокчейн уровня 2? Звучит дико для неподготовленного человека, но в мире EVM, сеть — это не магия, а набор конвенций и RPC-эндпоинтов.
Злоумышленники взяли опенсорсный стек (скорее всего, форкнули что-то вроде OP Stack) и развернули ноду. Но мало поднять сервер, нужно заставить кошельки и приложения верить, что это официальный продукт южнокорейской биржи Upbit, у которой этот самый GIWA еще даже официально не стартовал в мейннете.
Они жестко захардкодили в конфигурацию ноды официальный Chain ID — цифру 9134, которую команда GIWA заблаговременно зарегистрировала для своего будущего блокчейна. И вот тут кроется главная уязвимость всей экосистемы: кошельки вроде MetaMask проверяют сеть по строчкам конфигурации и по ID, а не по криптографическим корням доверия к создателям.
И вот тут мы подходим к моменту, где погорел DEX DYORSWAP. Они добавили этот фейковый RPC в свою инфраструктуру, решив первыми запрыгнуть на хайп новой сети.
Знаете, когда я сам еще гонял аудиты смарт-контрактов на коленке, мы всегда думали: ну окей, фронтенд могут подделать, RPC могут подменить, но смарт-контракт моста — это святое, там же код в блокчейне Ethereum! И вот тут кроется самая изящная ловушка этой атаки.
Почему пользователи не подозревали подвоха?
Пользователи не подозревали подвоха, потому что мост выглядел как родной интерфейс для перевода средств из Ethereum в L2-сеть GIWA. Люди подписывали транзакции в MetaMask, отправляя свои кровные ETH на депозитный смарт-контракт в мейннете.
Технически этот контракт был написан злоумышленниками так, чтобы имитировать работу стандартного локатора депозитов. Как только транзакция проходила валидацию в главной сети, мошенники получали контроль над средствами. А взамен пользователь получал фальшивые, ничем не подкрепленные фантики на баланс поддельного L2. Цифры на экране росли, создавая иллюзию успешного бриджа, а реальный эфир уже улетал на адреса организаторов схемы, испаряясь через миксеры. В итоге пострадали 1 335 уникальных адресов, оставив в капкане около 767.7 ETH. Причем вывели чисто около 766.3 ETH, сработав с минимальными издержками на газ.
Команда DYORSWAP поступила круто, выделив больше 200 ETH из своего кармана на компенсации. Уважаю такой подход к репутации, хотя архитектурную дыру в валидации внешних RPC-подключений придется заделывать кровь из носу.
А теперь давайте перейдем к практической части. Как не стать спонсором очередных аферистов, если вы любите первыми тестировать новые блокчейны? Набросал для вас скрипт-проверку на Python для верификации RPC-нод перед тем, как вообще думать о взаимодействии с ними через кошелек.
#!/usr/bin/env python3
import requests
def rpc_call(rpc_url, method, params=None):
if params is None:
params = []
payload = {
"jsonrpc": "2.0",
"method": method,
"params": params,
"id": 1
}
response = requests.post(rpc_url, json=payload, timeout=10)
response.raise_for_status()
data = response.json()
if "error" in data:
raise RuntimeError(f"{method}: {data['error']}")
return data.get("result")
def verify_evm_node(rpc_url, expected_chain_id):
try:
chain_id_hex = rpc_call(rpc_url, "eth_chainId")
chain_id = int(chain_id_hex, 16)
net_version = rpc_call(rpc_url, "net_version")
client_version = rpc_call(rpc_url, "web3_clientVersion")
block_number_hex = rpc_call(rpc_url, "eth_blockNumber")
block_number = int(block_number_hex, 16)
latest_block = rpc_call(
rpc_url,
"eth_getBlockByNumber",
["latest", False]
)
print("=" * 60)
print(f"RPC URL : {rpc_url}")
print(f"Chain ID : {chain_id}")
print(f"Expected ChainID : {expected_chain_id}")
print(f"Net Version : {net_version}")
print(f"Client Version : {client_version}")
print(f"Block Number : {block_number}")
if latest_block:
print(f"Latest Block Hash: {latest_block.get('hash')}")
print(f"Latest Block Num : {int(latest_block['number'], 16)}")
print(f"Parent Hash : {latest_block.get('parentHash')}")
print(f"Timestamp : {int(latest_block['timestamp'], 16)}")
print("=" * 60)
checks = []
checks.append(chain_id == expected_chain_id)
try:
checks.append(int(net_version) == expected_chain_id)
except Exception:
checks.append(False)
checks.append(block_number > 0)
checks.append(
latest_block is not None
and latest_block.get("hash")
and latest_block.get("parentHash")
and latest_block.get("number")
)
if all(checks):
print("VERIFICATION PASSED")
return True
print("VERIFICATION FAILED")
return False
except Exception as e:
print(f"ERROR: {e}")
return False
if __name__ == "__main__":
verify_evm_node(
"https://your-rpc-endpoint",
9134
)Запомните главное правило: никогда не доверяйте спискам сетей из сомнительных твиттер-аккаунтов или непроверенных DEX, пока официальный проект в своих подтвержденных каналах (не в соцсетях, а в документации или на официальном сайте с SSL-сертификатами) не опубликует точные эндпоинты. Биржа Upbit прямо заявила, что их мейннет еще не запущен, а все текущие RPC — это пальцы в небо и чистый скам.