
24 июля 2026 года злоумышленник получил из пулов Lien Finance $542 тыс. — просто указав один и тот же идентификатор облигации дважды там, где контракт ожидал два разных. Система не заметила подмены и выдала новые токены, под которые не было никакого реального обеспечения.
Введение
Lien Finance — протокол на Ethereum, работающий с облигационными токенами. Облигация в традиционных финансах — это долговой инструмент: вы даёте в долг, взамен получаете бумагу с обязательством вернуть деньги в определённый срок. В Lien Finance логика похожа: пользователи создают токены облигаций, каждый из которых соответствует реальному обеспечению, заблокированному в протоколе.
У каждого такого токена есть уникальный номер — bondID. Это идентификатор, по которому контракт определяет, что именно из себя представляет облигация: её условия, срок, сумму выплаты. Два разных bondID — два разных актива.
Ключевая уязвимость: контракт не проверял, не повторяется ли один и тот же bondID в одном запросе.
Ход инцидента
1️⃣ Создание специальных групп облигаций. Злоумышленник создал несколько групп облигационных токенов со специально подобранными параметрами. Это стандартная функция протокола — в этом шаге ничего необычного не было.
2️⃣ Обмен облигаций с повторяющимися идентификаторами. Lien Finance позволял обменивать одну группу облигационных токенов на другую. В рамках такого обмена атакующий передал в контракт данные, где один и тот же bondID фигурировал несколько раз — как будто это разные облигации.
3️⃣ Контракт не заметил дубликаты. При обработке обмена контракт должен был убедиться, что пользователь действительно передаёт все необходимые уникальные облигационные токены и не получает новые без соответствующего обеспечения. Проверки на уникальность bondID в списке не было. Контракт принял повторяющиеся идентификаторы как самостоятельные, разные облигации — и разрешил выпуск новых токенов, под которые реального обеспечения не поступало.
4️⃣ Вывод средств. Полученные «необеспеченные» облигационные токены были использованы для вывода около $542 тыс. USDC из пулов GeneralizedDotc протокола.
Почему это стало возможным
Ошибка проста по своей природе: при обмене облигационных групп контракт не проверял уникальность bondID в передаваемом списке. Это всё равно что банк, выдающий кредит под залог, проверяет номера закладных документов по списку — но не проверяет, не указан ли один и тот же номер в списке дважды.
Одна строчка проверки — «убедись, что каждый bondID в списке встречается ровно один раз» — полностью закрыла бы эту уязвимость. Её не было.
Детали расследования: движение средств
После получения около $542 тыс. USDC на контракт злоумышленника 0xe74d17c1bE3721E65e0af286D47B3BA58B08062e средства были переведены на адрес 0x0D7d9023531aD1A88414E216Ee2715F63561808a. Там USDC были обменяны через протокол LiFi — агрегатор переводов между сетями — на ETH и отправлены на адрес 0xcb2bFAe460C9915c4d4e5b70a59756CC5b2D87C8. С этого адреса все средства ушли в миксер Tornado Cash.
На момент расследования средства выведены через миксер, дальнейшее отслеживание существенно затруднено.
Заключение
Атака на Lien Finance — наглядный пример того, как отсутствие одной элементарной проверки может стоить протоколу сотни тысяч долларов. Контракт доверял списку идентификаторов, не убеждаясь в их уникальности. Злоумышленник воспользовался этим, чтобы «умножить» один и тот же залог на нужное количество новых токенов.
Средства выведены через Tornado Cash. Команда «КоинКит» продолжает мониторинг связанных адресов.


