В мире криптовалют одна случайная ошибка при нажатии может привести к «цифровой катастрофе». Одним из самых распространённых кошмаров является отправка активов на неправильный блокчейн. Например, вы хотели отправить ETH на адрес в тестовой сети Sepolia Ethereum, но по ошибке отправили его на адрес основной сети Ethereum. В таком случае, можно ли вернуть ошибочно переведённые средства с основной сети Ethereum? Возможно ли восстановить активы, зависит от типа получающего адреса. В этой статье мы проанализируем разные ситуации.
EOA (Externally Owned Account) — это обычный кошелёк, управляемый приватным ключом или мнемонической фразой.
Предпосылки для возврата активов:
Способы возврата активов:
Владелец приватного ключа адреса EOA может напрямую вывести средства на целевой цепочке.
Это один из самых безнадёжных сценариев. Поскольку адрес смарт-контракта не генерируется приватным ключом, никто не владеет приватным ключом этого контракта, и управлять им так же, как EOA, невозможно. Более того, если контракт изначально не содержит функции для обработки «ошибочного зачисления», то ошибочно переведённые средства могут быть навсегда заблокированы внутри контракта, и никто не сможет их вывести.
Однако в некоторых случаях всё же есть шанс. Далее мы построим сценарий, в котором ETH заблокированы на основной сети Ethereum, и расскажем, как можно спасти средства.
Общий сценарий таков: пользователь хотел вызвать контракт в тестовой сети Sepolia и перевести ETH для чеканки токенов, но при отправке транзакции ошибочно подключился к основной сети, в результате ETH оказались заблокированы в контракте основной сети. Конкретный сценарий следующий:

1. В тестовой сети Ethereum Sepolia проект (EOA) развернул контракт, предположим, что этот контракт позволяет пользователю внести ETH для чеканки соответствующих AToken, примерно так реализована функция mintTokens. Адрес развертывания — A. Важно отметить, что в контракте A нет функции для прямого вывода ETH.

2. В тестовой сети Ethereum Sepolia проект (EOA) развернул фабричный контракт, который позволяет, передавая адрес реализуемого контракта и salt, развернуть прокси-контракт (например, с помощью функции deployProxyByImplementation), указывающий на реализуемый контракт A. Адрес развертывания — B. В данном случае вызывается deployProxyByImplementation с адресом A в качестве _implementation, что приводит к созданию прокси-контракта по адресу C.

3. Пользователь хочет в тестовой сети Sepolia через перевод ETH чеканить AToken, и инициирует вызов по адресу прокси-контракта C. Обычно, прокси вызывает функцию mintTokens в контракте A. Но пользователь ошибочно подключается к основной сети Ethereum и переводит ETH на адрес C в основной сети. В результате ETH попадают на адрес C в основной сети, где нет развернутого контракта, и приватный ключ этого адреса неизвестен — средства заблокированы на основном сетевом адресе C.
Перед рассмотрением вариантов спасения, нужно понять базовые знания.
create и create2 — это два способа развертывания контрактов в Solidity.
2.2.2. Минимальный прокси-контракт (Clones)
https://docs.openzeppelin.com/contracts/4.x/api/proxy#clones
Минимальный прокси-контракт, также известный как клон (Clones), — это контракт, который с минимальными затратами (Gas) развертывает прокси, указывающий на целевой реализуемый контракт. В контракте Clones можно использовать create или create2 для развертывания прокси. Например, вызов cloneDeterministic использует create2.
В функции cloneDeterministic создаваемый прокси-контракт очень короткий, его байт-код примерно такой: 0x363d3d373d3d3d363d73<адрес_реализуемого_контракта>5af43d82803e903d91602b57fd5bf3. Адрес реализуемого контракта жестко закодирован в байт-коде, и все вызовы delegatecall идут на этот контракт.
Из функции cloneDeterministic видно, что адрес создаваемого прокси зависит от адреса создателя, salt и адреса реализуемого контракта, а не от байт-кода реализуемого контракта.
![])https://img-cdn.gateio.im/webp-social/moments-628ce0ce97dbf40349dc8b7a0c07eab3.webp(
)# 2.3. Варианты спасения
Теперь расскажем, как можно вернуть ETH, заблокированные на адресе C в основной сети. Основная идея — развернуть контракт на адресе C в основной сети, чтобы он взял на себя управление и вывел средства. Конкретные шаги:
![]###https://img-cdn.gateio.im/webp-social/moments-22428dd6bb1fbd62d2205538c0cc6c92.webp(
1. В основной сети развернуть такой же фабричный контракт, как в тестовой сети, на адресе B. Для этого нужно, чтобы адрес фабричного контракта совпадал. Для этого в основном сети повторно развернуть тот же контракт с теми же параметрами, что и в тестовой, учитывая nonce. Для этого можно посмотреть транзакцию развертывания в тестовой сети, определить nonce создателя, и в основной сети развернуть контракт с таким же nonce, чтобы получить тот же адрес B.
2. В основной сети развернуть контракт реализуемого контракта A на том же адресе. Поскольку адрес прокси зависит только от адреса создателя, salt и байт-кода, достаточно развернуть контракт A на нужном адресе. Для этого можно использовать тот же подход — развернуть контракт с тем же nonce, что и в тестовой, или использовать create2 с известным salt и байт-кодом.
3. В основной сети развернуть прокси-контракт на адресе C. Для этого нужно взять транзакцию развертывания прокси в тестовой сети, определить salt, и вызвать deployProxyByImplementation с теми же параметрами, чтобы получить адрес C.
4. Вызвать функцию withdraw у прокси-контракта C, чтобы вывести заблокированные ETH. После этого средства вернутся владельцу.
)# 2.4. Итог
Из этого следует, что для успешного спасения средств необходимо, чтобы:
Поэтому при работе с контрактами очень важно тщательно проверять адреса и параметры, а также использовать инструменты для анализа безопасности. В случае блокировки средств — не паниковать, а обратиться к специалистам по безопасности и аудитам.
Этот материал подготовлен командой ZAN (@zan_team), а также Cara из AntChain OpenLabs (@Cara6289).
Связанные статьи
Новый кошелек получил от FalconX 40k ETH на сумму около 82,12 млн долларов, подозревается Bitmine
Фонд Ethereum еще не набрал и 500 ETH, чтобы достичь вехи стейкинга в 70.000 ETH
Фонд Эфириума увеличивает стейкинг, снижая давление на продажу ETH за счет пассивного дохода
Таинственный кит, связанный с Эриком Вурхизом, продолжает накопление ETH, совершив дополнительную покупку на $887,9K
Фонд Ethereum почти достигает цели по 70 000 размещенных ETH