Кто индексирует все новые NFT на TON?
TL;DR tonapi, tonscan, redoubt, getgems и еще три неизвестных сервиса, некоторые индексируют только сами нфт и пропускают коллекции
Почти все NFT в тоне хранят метаданные offчейн, это значит что внутри блокчена нет названия NFT, есть только ссылка на json файл.
Чтобы отобразить название, описание и картинку NFT, маркетплейсы и индексаторы скачивают эти json файлы. (вообще этим можно не заниматься и показывать просто адрес нфт)
Когда маркетплейс скачивает файл он делает HTTP запрос на сервер, такие запросы можно залогировать и посмотреть кто интересовался метадатой NFT.
Есть классный сервис -- webhook.site он дает вам url и логирует все запросы которые были на этот url. Я создал коллекцию из одной NFT чтобы посмотреть кто придет скачивать метаднные NFT и коллекции.
1.
Я думаю что это Tonapi, но точных пруфвов нет. По заголовкам поятно что это какой-то код на goalng и (видимо) какой-то скрипт на NodeJS, undici это популярная библиотека для http запросов на NodeJS
2.
tonscan, сенсуc показывает названия ssl серификатов, там упоминается tonscan. Два ip потому что dev и prod окружения
3.
redoubt, сенсус показывает что на этот ip резолвится хост graphql.redoubt.online
4.
getgems, не стесняются и пишут свое название в user-agent. Два ip потому что есть dev и prod версии индексера
5.
Нет никакой информации про этот ip.
Есть скрипты, которые не индексируют метаданные коллекции, им интересны только сами нфт. Возможно это какие-то боты которые ищут новые NFT в существующих коллекциях.
6.
Нет никакой информации про этот ip. Индексирует только нфт
7.
Индексировать весь блокчейн запарно, хорошо что есть несколько команд, которые делают это независимо друг от друга
TL;DR tonapi, tonscan, redoubt, getgems и еще три неизвестных сервиса, некоторые индексируют только сами нфт и пропускают коллекции
Почти все NFT в тоне хранят метаданные offчейн, это значит что внутри блокчена нет названия NFT, есть только ссылка на json файл.
Чтобы отобразить название, описание и картинку NFT, маркетплейсы и индексаторы скачивают эти json файлы. (вообще этим можно не заниматься и показывать просто адрес нфт)
Когда маркетплейс скачивает файл он делает HTTP запрос на сервер, такие запросы можно залогировать и посмотреть кто интересовался метадатой NFT.
Есть классный сервис -- webhook.site он дает вам url и логирует все запросы которые были на этот url. Я создал коллекцию из одной NFT чтобы посмотреть кто придет скачивать метаднные NFT и коллекции.
1.
2a01:4f9:3a:1491::2 HETZNER-AS, DE (AS24940) user-agent: Go-http-client/1.1
2a01:4f9:6b:488e::2 HETZNER-AS, DE (AS24940) user-agent: undici
Я думаю что это Tonapi, но точных пруфвов нет. По заголовкам поятно что это какой-то код на goalng и (видимо) какой-то скрипт на NodeJS, undici это популярная библиотека для http запросов на NodeJS
2.
16.63.46.215 AMAZON-02, US (AS16509) user-agent: python-httpx/0.27.0
16.62.75.29 AMAZON-02, US (AS16509) user-agent: python-httpx/0.27.0
tonscan, сенсуc показывает названия ssl серификатов, там упоминается tonscan. Два ip потому что dev и prod окружения
3.
44.210.191.88 AMAZON-AES, US (AS14618) user-agent: Python/3.8 aiohttp/3.9.5
redoubt, сенсус показывает что на этот ip резолвится хост graphql.redoubt.online
4.
3.68.116.9 AMAZON-02, US (AS16509) user-agent: Getgems/1.0
3.66.224.126 AMAZON-02, US (AS16509) user-agent: Getgems/1.0
getgems, не стесняются и пишут свое название в user-agent. Два ip потому что есть dev и prod версии индексера
5.
138.197.186.110 DIGITALOCEAN-ASN, US (AS14061) user-agent: Go-http-client/1.1
Нет никакой информации про этот ip.
Есть скрипты, которые не индексируют метаданные коллекции, им интересны только сами нфт. Возможно это какие-то боты которые ищут новые NFT в существующих коллекциях.
6.
51.250.53.56 YANDEXCLOUD, RU (AS200350) user-agent: Go-http-client/1.1
Нет никакой информации про этот ip. Индексирует только нфт
7.
94.74.84.248 HWCLOUDS-AS-AP HUAWEI CLOUDS, HK (AS136907) user-agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/111.0.0.0 Safari/537.36Нет никакой информации про этот ip. Индексирует только нфт, претворяется браузером
Индексировать весь блокчейн запарно, хорошо что есть несколько команд, которые делают это независимо друг от друга
❤2🔥2👍1
Более 15,000 TON «застряло» в NFT, но владельцы коллекций могут их вернуть
Как это произошло?
При минтинге NFT на её баланс нужно положить небольшое количество TON — обычно около 0.05 TON. Из этой суммы часть уходит на оплату газа. Точную сумму, которая будет потрачена на газ, рассчитать сложно, поэтому обычно отправляют чуть больше, чем нужно, а контракт возвращает неиспользованный остаток.
Однако в эталонной реализации NFT-коллекции от Ton Foundation этот механизм возврата не был реализован. В результате при минтинге NFT часть неиспользованных TON осталась на балансе коллекций.
Я проанализировал блокчейн TON и нашёл 196 NFT-коллекций с балансом более 10 TON. Вот некоторые из них с самыми большими остатками:
• X Empire Pre-Market — 2,581 TON
• W-Coin Pre-Market — 1,243 TON
• Age of Farm — 177 TON
Полный список коллекций собран в отдельном файле — там указаны названия, баланс в TON и адреса владельцев.
Как вернуть TON?
Для этого нужно быть владельцем коллекции и владеть хотя бы одной NFT из этой коллекции. Процесс возврата состоит из двух шагов:
1. Отправка запроса на минтинг нового итема с указанием индекса уже существующей NFT. Так как такая NFT уже есть, минтинг не произойдёт. В запросе также указывается количество TON, которое нужно перевести с баланса коллекции на баланс NFT-итема. Чтобы NFT-итем не вернул ошибку, передаётся пустая ячейка данных. Таким образом, TONы переносятся с баланса коллекции на баланс NFT.
2. Передача NFT самому себе. В стандартных контрактах есть механизм, который возвращает излишки TON обратно владельцу NFT во время трансфера.
Таким образом, TON сначала передаётся от коллекции к NFT, а затем от NFT — на ваш кошелёк. Чтобы упростить этот процесс, я сделал инструмент, который автоматически формирует все необходимые сообщения. Также я записал видео, где наглядно показал, как всё работает.
Если у вас не NFT, а SBT, схема остаётся такой же, но вместо передачи токена самому себе нужно отправить ему специальный op-код
Ставьте лайк, подписывайтесь на канал — буду публиковать ещё больше полезных вещей про TON-блокчейн
Как это произошло?
При минтинге NFT на её баланс нужно положить небольшое количество TON — обычно около 0.05 TON. Из этой суммы часть уходит на оплату газа. Точную сумму, которая будет потрачена на газ, рассчитать сложно, поэтому обычно отправляют чуть больше, чем нужно, а контракт возвращает неиспользованный остаток.
Однако в эталонной реализации NFT-коллекции от Ton Foundation этот механизм возврата не был реализован. В результате при минтинге NFT часть неиспользованных TON осталась на балансе коллекций.
Я проанализировал блокчейн TON и нашёл 196 NFT-коллекций с балансом более 10 TON. Вот некоторые из них с самыми большими остатками:
• X Empire Pre-Market — 2,581 TON
• W-Coin Pre-Market — 1,243 TON
• Age of Farm — 177 TON
Полный список коллекций собран в отдельном файле — там указаны названия, баланс в TON и адреса владельцев.
Как вернуть TON?
Для этого нужно быть владельцем коллекции и владеть хотя бы одной NFT из этой коллекции. Процесс возврата состоит из двух шагов:
1. Отправка запроса на минтинг нового итема с указанием индекса уже существующей NFT. Так как такая NFT уже есть, минтинг не произойдёт. В запросе также указывается количество TON, которое нужно перевести с баланса коллекции на баланс NFT-итема. Чтобы NFT-итем не вернул ошибку, передаётся пустая ячейка данных. Таким образом, TONы переносятся с баланса коллекции на баланс NFT.
2. Передача NFT самому себе. В стандартных контрактах есть механизм, который возвращает излишки TON обратно владельцу NFT во время трансфера.
Таким образом, TON сначала передаётся от коллекции к NFT, а затем от NFT — на ваш кошелёк. Чтобы упростить этот процесс, я сделал инструмент, который автоматически формирует все необходимые сообщения. Также я записал видео, где наглядно показал, как всё работает.
Если у вас не NFT, а SBT, схема остаётся такой же, но вместо передачи токена самому себе нужно отправить ему специальный op-код
op::take_excess. Отправить его можно через этот инструмент.Ставьте лайк, подписывайтесь на канал — буду публиковать ещё больше полезных вещей про TON-блокчейн
❤10🐳3👍1🔥1
Сегодня я узнал, что в func нельзя написать много условий подряд, компилятор из @ton-community/func-js упадет с ошибкой:
Зачем вообще такое писать
NFT устроены так, что внутри у них есть число — индекс. Он уникальный в рамках коллекции. Обычно индексы начинаются с нуля и идут по возрастанию: 0, 1, 2, 3 и так далее. Но только не в коллекциях gomining.
У них первый индекс в коллекции — 348903. Сомнительно, но ок: у ребят сквозная нумерация индексов на всех блокчейнах. Но это только начало. Далее примерно тысяча индексов идет последовательно с шагом в единицу до 350002, после чего идёт пропуск на 9 номеров — следующий индекс 350012. И таких пропусков — 863 штуки.
Всё было бы нормально, если бы такую коллекцию нужно было просто заминтить. Тогда никаких проблем нет — можно подставлять нужные индексы в нужные NFT, как это сделано, например, в коллекциях TON DNS или Telegram Usernames.
Но коллекции gomining должны были продаваться с ланчпада. Ланчпад — это лендинг с одной кнопкой «Купить NFT». Кнопка списывает у пользователя TON и минтит NFT на кошелёк. Весь процесс покупки и минтинга происходит полностью ончейн, вся логика зашита в смарт-контрактах.
В этой логике было очень удобно считать от нуля до максимального количества NFT и использовать этот счётчик как индекс NFT. Такой подход хорошо работал несколько лет для «обычных» коллекций, но на gomining всё сломалось.
Так я узнал что нельзя написать 863 условия подряд, контракт не соберется. Но можно разбить их по 200 штук и разнести по разным функциям, тогда будет работать
В итоге я сделал так:
https://tonviewer.com/EQCN7SkHxlSkRwXopX5iReUDuhCDaGyBevt6Bp3D2jZQU0gb?section=code
Maximum call stack size exceeded
RangeError: Maximum call stack size exceeded
Зачем вообще такое писать
NFT устроены так, что внутри у них есть число — индекс. Он уникальный в рамках коллекции. Обычно индексы начинаются с нуля и идут по возрастанию: 0, 1, 2, 3 и так далее. Но только не в коллекциях gomining.
У них первый индекс в коллекции — 348903. Сомнительно, но ок: у ребят сквозная нумерация индексов на всех блокчейнах. Но это только начало. Далее примерно тысяча индексов идет последовательно с шагом в единицу до 350002, после чего идёт пропуск на 9 номеров — следующий индекс 350012. И таких пропусков — 863 штуки.
Всё было бы нормально, если бы такую коллекцию нужно было просто заминтить. Тогда никаких проблем нет — можно подставлять нужные индексы в нужные NFT, как это сделано, например, в коллекциях TON DNS или Telegram Usernames.
Но коллекции gomining должны были продаваться с ланчпада. Ланчпад — это лендинг с одной кнопкой «Купить NFT». Кнопка списывает у пользователя TON и минтит NFT на кошелёк. Весь процесс покупки и минтинга происходит полностью ончейн, вся логика зашита в смарт-контрактах.
В этой логике было очень удобно считать от нуля до максимального количества NFT и использовать этот счётчик как индекс NFT. Такой подход хорошо работал несколько лет для «обычных» коллекций, но на gomining всё сломалось.
Так я узнал что нельзя написать 863 условия подряд, контракт не соберется. Но можно разбить их по 200 штук и разнести по разным функциям, тогда будет работать
В итоге я сделал так:
https://tonviewer.com/EQCN7SkHxlSkRwXopX5iReUDuhCDaGyBevt6Bp3D2jZQU0gb?section=code
🤯5👍2🤡2😁1
TON не любит нищих
TON сделан таким образом, чтобы вы не задавались вопросом: «Ой, а хватит ли мне денег?». У вас всегда должно быть чуть больше TON, чем вы хотите отправить.
В TON есть классная штука — комиссия за хранение (storage fee). По сути, это как платное место в iCloud, только вы платите за то, что ваш кошелек не удалился из блокчейна. Особая прелесть этой комиссии в том, что вы не знаете точно, сколько именно нужно заплатить. Это решается в момент создания транзакции: рассчитывается, сколько секунд назад было последнее списание комиссии за хранение, и эта сумма списывается с вашего баланса дополнительно к тому, что вы переводите.
Суммы там копеечные: обычный W5-кошелек тратит около 0.000022124 TON за неделю. Это всего 0.01 TON в год.
Интересное начинается, когда вы пытаетесь рассуждать как-то так: «Я хочу перевести 11.54 TON, у меня на балансе 11.540419277 TON. За газ с меня возьмут 0.000329268 TON. Я хочу добавить комментарий к переводу, значит, за action fee уйдет еще 0.000089964 TON. Последний раз storage fee я платил 20 минут назад — это еще 0.000000045 TON... Ой, пока я считал, прошла еще одна секунда, значит, storage fee стал больше!»
И вот мы получаем такую транзакцию
(посмотрите на Action Phase — Total actions: 1, Skipped actions: 1):
https://tonviewer.com/transaction/d8ef607419a3e635344f9d7e0b20d35fbd8a370aa7cd08157ac5df1b3a432eb7
Кошелек попытался отправить тоны, но тонов на комиссии не хватило. В итоге ничего не отправилось: вы просто заплатили комиссии за газ и хранение, но само действие не совершилось.
TON существует уже 5 лет, но эта ошибка все еще встречается в MyTonWallet.
По-хорошему, кошелек должен был рассчитать, что денег на транзакцию не хватит, и не давать её отправлять. Но рассчитать это сложно, потому что TON не любит нищих и не дает удобных инструментов для таких расчетов. MyTonWallet тут не одиноки, в Tonkeeper такая ошиба тоже была долгое время
TON сделан таким образом, чтобы вы не задавались вопросом: «Ой, а хватит ли мне денег?». У вас всегда должно быть чуть больше TON, чем вы хотите отправить.
В TON есть классная штука — комиссия за хранение (storage fee). По сути, это как платное место в iCloud, только вы платите за то, что ваш кошелек не удалился из блокчейна. Особая прелесть этой комиссии в том, что вы не знаете точно, сколько именно нужно заплатить. Это решается в момент создания транзакции: рассчитывается, сколько секунд назад было последнее списание комиссии за хранение, и эта сумма списывается с вашего баланса дополнительно к тому, что вы переводите.
Суммы там копеечные: обычный W5-кошелек тратит около 0.000022124 TON за неделю. Это всего 0.01 TON в год.
Интересное начинается, когда вы пытаетесь рассуждать как-то так: «Я хочу перевести 11.54 TON, у меня на балансе 11.540419277 TON. За газ с меня возьмут 0.000329268 TON. Я хочу добавить комментарий к переводу, значит, за action fee уйдет еще 0.000089964 TON. Последний раз storage fee я платил 20 минут назад — это еще 0.000000045 TON... Ой, пока я считал, прошла еще одна секунда, значит, storage fee стал больше!»
И вот мы получаем такую транзакцию
(посмотрите на Action Phase — Total actions: 1, Skipped actions: 1):
https://tonviewer.com/transaction/d8ef607419a3e635344f9d7e0b20d35fbd8a370aa7cd08157ac5df1b3a432eb7
Кошелек попытался отправить тоны, но тонов на комиссии не хватило. В итоге ничего не отправилось: вы просто заплатили комиссии за газ и хранение, но само действие не совершилось.
TON существует уже 5 лет, но эта ошибка все еще встречается в MyTonWallet.
По-хорошему, кошелек должен был рассчитать, что денег на транзакцию не хватит, и не давать её отправлять. Но рассчитать это сложно, потому что TON не любит нищих и не дает удобных инструментов для таких расчетов. MyTonWallet тут не одиноки, в Tonkeeper такая ошиба тоже была долгое время
🔥8🤯2
Недавно прочитал новость про неслучайные сид-фразы: https://t.me/ctodaily/2117
И решил попробовать поискать TON-разработчиков, которые поленились нормально сгенерировать приватный ключ.
Моё предположение было такое: в библиотеке @ton/crypto есть функция
Правильно этот сид надо создавать так
А еще, можно написать как-то так:
Тут
Идея такая: берём популярные пароли, считаем от них sha256-хеш, создаём ключ из этого сида и смотрим, есть ли кошельки c такими ключами в блокчейне.
Найти популярные пароли оказалось проще всего: есть репозиторий https://github.com/danielmiessler/SecLists/tree/master/Passwords, там собрано примерно 56 миллионов паролей. Правда, лежат они в разных файлах, но это не большая проблема.
Дальше я начал думать, как проверить, существует ли кошелёк в блокчейне. Первой идеей было взять бесплатные ключи для tonapi, toncenter и подобных сервисов и просто проверять баланс адреса: если не ноль, то считаем, что кошелёк найден. Но при таком подходе скорость перебора была бы очень низкой.
К счастью, что у tonapi есть крутой сервис TON Analytics. Суть в том, что можно делать SQL-запросы в их базу данных. На текущий момент разрешено создавать запросы, которые отдают миллион строк за раз. В TON всего ~190 миллионов активных адресов, так что выгрузить их все не составило труда и обошлось мне примерно в $20.
Кроме самих адресов, у них есть ещё и отдельная таблица с публичными ключами — там оказалось примерно 50 миллионов ключей. Эта таблица существенно облегчает поиск, потому что не надо генерировать адрес TON-кошелька, а можно проверить сразу публичный ключ. Без неё пришлось бы сначала сгенерировать адреса кошельков для разных версий (v3, v5, hl_v2, hl_v3) и проверять каждый адрес отдельно.
Дальше я попросил Claude написать мне скрипт на Rust. На удивление, получилось с первого раза.
В итоге я проверил:
- 56 миллионов самых популярных паролей;
- unix timestamp с текущего момента до начала 2022 года (134 миллиона чисел);
- просто все числа от 0 до 10 миллионов.
И нашёл только два адреса:
1.
2.
На этих кошельках нулевой баланс, видно что они использовались только один раз несколько лет назад.
Дальше искать адреса мне надоело, я потратил несколько дней на проверку всех 190 миллионов строк. Xотя еще много чего можно попробовать, брать другие хеши или применять хеш несколько раз.
Создавайте ключи правильно
И решил попробовать поискать TON-разработчиков, которые поленились нормально сгенерировать приватный ключ.
Моё предположение было такое: в библиотеке @ton/crypto есть функция
keyPairFromSeed(seed), где seed — это Buffer длиной 32 байта. Правильно этот сид надо создавать так
getSecureRandomBytes(32). Но так будет возня байтами, куда-то их придется сохранить. В общем, делать хорошо — сложно.А еще, можно написать как-то так:
const keyPair = keyPairFromSeed(await sha256('my_secret'));Тут
my_secret может быть любой строкой, а sha256 сделает из неё хеш длиной 32 байта — как раз то, что требует keyPairFromSeed.Идея такая: берём популярные пароли, считаем от них sha256-хеш, создаём ключ из этого сида и смотрим, есть ли кошельки c такими ключами в блокчейне.
Найти популярные пароли оказалось проще всего: есть репозиторий https://github.com/danielmiessler/SecLists/tree/master/Passwords, там собрано примерно 56 миллионов паролей. Правда, лежат они в разных файлах, но это не большая проблема.
Дальше я начал думать, как проверить, существует ли кошелёк в блокчейне. Первой идеей было взять бесплатные ключи для tonapi, toncenter и подобных сервисов и просто проверять баланс адреса: если не ноль, то считаем, что кошелёк найден. Но при таком подходе скорость перебора была бы очень низкой.
К счастью, что у tonapi есть крутой сервис TON Analytics. Суть в том, что можно делать SQL-запросы в их базу данных. На текущий момент разрешено создавать запросы, которые отдают миллион строк за раз. В TON всего ~190 миллионов активных адресов, так что выгрузить их все не составило труда и обошлось мне примерно в $20.
Кроме самих адресов, у них есть ещё и отдельная таблица с публичными ключами — там оказалось примерно 50 миллионов ключей. Эта таблица существенно облегчает поиск, потому что не надо генерировать адрес TON-кошелька, а можно проверить сразу публичный ключ. Без неё пришлось бы сначала сгенерировать адреса кошельков для разных версий (v3, v5, hl_v2, hl_v3) и проверять каждый адрес отдельно.
Дальше я попросил Claude написать мне скрипт на Rust. На удивление, получилось с первого раза.
В итоге я проверил:
- 56 миллионов самых популярных паролей;
- unix timestamp с текущего момента до начала 2022 года (134 миллиона чисел);
- просто все числа от 0 до 10 миллионов.
И нашёл только два адреса:
1.
EQD36D7ngLSsURYGsDhGzRGrMPPBLs2U2WLDP_THFPvQy6Np — тут приватный ключ создан из слова storm.2.
EQDEW3qkxdgj20mymJ6hPX8AafSzGmT_epYAnOmtuzt9lM6b — тут из строки 1.3.. Оказывается, этот кошелёк создавал я сам :)На этих кошельках нулевой баланс, видно что они использовались только один раз несколько лет назад.
Дальше искать адреса мне надоело, я потратил несколько дней на проверку всех 190 миллионов строк. Xотя еще много чего можно попробовать, брать другие хеши или применять хеш несколько раз.
Создавайте ключи правильно
🔥9👍3🕊1
Primate impact is too high
Этот баг ведёт к тому, что NFT нельзя купить и нельзя снять с продажи привычным методом – всё действия ловят ошибку в блокчейне. Можно сказать, что они заморожены в подпространстве.
Как я починил fragment
Просто пополнил баланс нфт на 0.005 GRAM. После этого нфт хватило денег на газ для стандартного завершения продажи.
"Чужую" нфт можно пополнить если отправить граммы без баунс флага или с комментарием "#topup"
Целый год пользователи страдали от забитой выдачи сломанными гифтами на фрагменте
Просто пополнил баланс нфт на 0.005 GRAM. После этого нфт хватило денег на газ для стандартного завершения продажи.
"Чужую" нфт можно пополнить если отправить граммы без баунс флага или с комментарием "#topup"
Целый год пользователи страдали от забитой выдачи сломанными гифтами на фрагменте
🤝5👍2
