Типичные ошибки Web3-фронтенда: чек-лист

Собираем грабли из всего курса в один чек-лист: ошибки, которые в Web3 стоят денег и доверия.

Чек-лист антиграблей — сводка самых частых и дорогих ошибок Web3-фронтенда, проверяемых перед релизом.

В Web3 ошибки наказываются жёстче, чем в обычном вебе: пользователь теряет деньги, а откатить нельзя. Соберём в одном месте всё, что мы разбирали, как финальный чек-лист код-ревью.

1. Float для денег

Любая сумма во float (тип number) рано или поздно даст ошибку округления. Деньги — только в целых wei на bigint; конвертация через parseUnits/formatUnits с правильными decimals.

// НЕПРАВИЛЬНО: float
const amount = 0.1 + 0.2;          // 0.30000000000000004
// ПРАВИЛЬНО: bigint в минимальных единицах
const wei = 100000000000000000n + 200000000000000000n; // 0.3 в wei, точно
console.log(amount);
console.log(wei.toString());

Вывод:

0.30000000000000004
300000000000000000

2. Не обработан reject

Пользователь нажимает «Reject» в кошельке постоянно — это норма. Не ловите это как ошибку приложения. Различайте код 4001/ACTION_REJECTED и реальные сбои.

3. Хардкод адресов

Адрес контракта зависит от сети. Хардкод одного адреса — баг в мультичейне и после передеплоя. Держите карту chainId → адрес в конфиге.

4. Нет проверки сети

Пользователь может быть в другой сети, чем ваш контракт. Перед записью проверяйте chainId и предлагайте переключение; иначе транзакция уйдёт «в пустоту» и сожжёт газ.

5. UI не отражает состояние транзакции

Без статусов pending/confirming/success/error пользователь не понимает, что происходит, и кликает повторно. Блокируйте кнопку, дожидайтесь tx.wait()/receipt, обновляйте данные после успеха.

6. Игнор decimals и сырых чисел

Показ balanceOf «как есть» — в миллион раз неверно. Всегда форматируйте с decimals токена.

7. Не отписаны слушатели событий

В React подписки на события и кошелёк копятся при ремоунте. Чистите их в cleanup-функции useEffect (или используйте wagmi, который делает это сам).

Сводная таблица

ОшибкаЧем грозитКак избежать
Float для денегПотеря точности суммbigint + parseUnits/formatUnits
Reject как ошибкаПугает пользователяловить код 4001 отдельно
Хардкод адресаБитый мультичейнкарта chainId→адрес
Нет проверки сетиГаз впустуюпроверять chainId, switch
Нет статусов txДвойные транзакцииpending/confirming/success

Как работает под капотом

Все эти грабли — следствие одной особенности: в Web3 фронт напрямую распоряжается деньгами и необратимыми действиями, чего в Web2 не было. Там худшее — неверно показанные данные; тут — потерянные средства. Поэтому привычные «мелочи» (округление, обработка отмены, состояние загрузки) перестают быть косметикой и становятся вопросами безопасности и денег.

Итоги

  • Деньги — только bigint/wei, никогда float.
  • Reject — норма; адреса — из конфига по сети; сеть — проверять.
  • Состояние транзакции и decimals — обязательны; слушатели — чистить.
Проверьте себя
1. Почему нельзя считать суммы во float (number)?
AFloat медленный
BFloat теряет точность — для денег это недопустимо
CFloat не поддерживается ethers
DFloat меняет chainId
2. Как трактовать код ошибки 4001 при записи?
AСбой сети
BПользователь отклонил транзакцию — это норма, не ошибка приложения
CНеверный ABI
DНехватка газа
3. Почему хардкод одного адреса контракта — баг?
AАдрес секретный
BВ разных сетях у контракта разные адреса; нужна карта chainId→адрес
CАдрес меняется каждый блок
Dethers это запрещает