Как это устроено
Пополнения: прокси CREATE2
Пополнение — это отправка USDC на личный адрес в HyperCore. Всё, что туда приходит, зачисляется вам; не нужно вызывать функцию пополнения и ничего одобрять. Пополняйте через приложение: USDC, отправленные на тот же адрес в HyperEVM, не зачисляются.
Ваш собственный адрес для пополнения
У каждого аккаунта свой адрес для пополнения; DepositProxyFactory вычисляет его из адреса кошелька с помощью CREATE2:
proxy = last 20 bytes of keccak256(0xff ‖ factory ‖ keccak256(user) ‖ keccak256(initCode))
initCode = DepositProxy creation code ‖ abi.encode(exchange, user)
Все входные данные публичны, поэтому кто угодно может пересчитать адрес, и он может получать средства ещё до того, как за ним появится контракт. Контракт разворачивается, когда переводится первое пополнение, — ключом развёртывания нашего релейера или самим аккаунтом; больше никто развернуть его не может.
Приложение регистрирует адрес у нашего свипера, прежде чем что-либо отправить, и сверяет собственный расчёт с ответом сервера и с блокчейном; если они расходятся, ничего не отправляется. Все маршруты приходят на сторону адреса в HyperCore: переводы с Hyperliquid, выпуск через CCTP от Circle и исполнения Across, которые приходят через контракт Circle для пополнения HyperCore в HyperEVM. Обычный перевод токена на прокси в HyperEVM не отслеживается и не зачисляется.
Дальше работает свипер
Наш свипер реагирует на признаки того, что средства пришли: проиндексированные пополнения через CCTP и HyperEVM, переводы в HyperCore на зарегистрированные адреса и проверки, запрошенные приложением. Когда на адресе для пополнения есть не меньше 10 USDC, он выполняет два вызова Exchange, оба публичные:
- Запрос. Exchange читает балансы прокси в HyperCore. Если USDC лежат в залоге перпов, он просит прокси перевести их на спот и останавливается; следующий запрос их переведёт. Иначе он записывает ожидающий перевод (сумму и баланс прокси на этот момент) и просит прокси отправить эту сумму на счёт Exchange в HyperCore через CoreWriter.
- Завершение. В одном из следующих блоков (не раньше чем через 1 после запроса) Exchange зачисляет сумму тогда и только тогда, когда выполнены обе проверки: баланс прокси теперь ниже записанного (двигать его может только Exchange, значит, отправка прошла), а собственный баланс Exchange в HyperCore превышает всё, что он уже должен, как минимум на эту сумму (средства пришли и ещё никому не зачислены).
Если проверять только баланс прокси, можно зачислить отправку, которая не прошла после списания комиссии, или зачислить дважды, когда отправка запаздывает, а в то же окно приходит новое пополнение; требование, чтобы средства действительно пришли, закрывает обе дыры. Если проверки пока не проходят, завершение повторяется в следующих блоках. Перевод, который не дошёл за 5 блоков, помечается как неподтверждённый, и его сумма записывается; позже согласователь может его зачислить, но только в пределах записанной суммы, только из средств, поступление которых можно проверить и которые никому не приписаны, и только в течение 30 дней. Каждое согласование — ончейн-событие. Поэтому приложение отправляет пополнения по одному и ждёт зачисления каждого.
Обычно средства попадают на баланс через несколько блоков после прихода на ваш адрес; первое пополнение ещё ждёт развёртывания своего прокси и оплачивает разовую активацию счёта в HyperCore — 1 USDC.
Почему прокси, а не прямые пополнения
По двум причинам. Первая — удобство: для вызова функции пополнения понадобились бы одобрение и само пополнение, каждое со своим газом. Прокси превращает пополнение в обычный перевод на адрес, который работает одинаково, откуда бы он ни пришёл: с Hyperliquid, через мост Circle или через Across.
Вторая — изоляция: прокси каждого аккаунта — отдельный адрес, поэтому чужие средства не смешиваются с вашими, а свипер обрабатывает каждый аккаунт отдельно. Проблема с пополнением одного аккаунта не затрагивает остальные.
Чему вы доверяете
Прокси разворачивает одна фабрика, через CREATE2 и с фиксированным кодом. Любой может вывести ожидаемый адрес для любого кошелька и проверить, что контракт по этому адресу совпадает: фабрика, соль и хеш кода публичны. Если бы код когда-нибудь изменился, вместе с ним изменился бы и выводимый адрес; по вашему старому адресу просто не оказалось бы контракта, а не тихо оказался бы другой код. Ни фабрику, ни прокси обновить нельзя.
Заставить прокси отправить USDC может только Exchange, и только в Exchange. То, что отправлено не туда, можете вернуть только вы: токены или HYPE, пришедшие на контракт прокси в HyperEVM, — через withdrawStuckToken и withdrawStuckNative, вызванные из вашего кошелька на прокси, а токены, отличные от USDC, пришедшие на его счёт в HyperCore, — через rescueProxyCoreToken, вызванный из вашего кошелька на Exchange.