<?xml version="1.0" encoding="utf-8" ?><feed xmlns="http://www.w3.org/2005/Atom" xmlns:tt="http://teletype.in/" xmlns:opensearch="http://a9.com/-/spec/opensearch/1.1/"><title>Chpotl | dev</title><author><name>Chpotl | dev</name></author><id>https://teletype.in/atom/chpotl</id><link rel="self" type="application/atom+xml" href="https://teletype.in/atom/chpotl?offset=0"></link><link rel="alternate" type="text/html" href="https://teletype.in/@chpotl?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=chpotl"></link><link rel="next" type="application/rss+xml" href="https://teletype.in/atom/chpotl?offset=10"></link><link rel="search" type="application/opensearchdescription+xml" title="Teletype" href="https://teletype.in/opensearch.xml"></link><updated>2026-04-16T17:47:39.659Z</updated><entry><id>chpotl:the-graph-intro</id><link rel="alternate" type="text/html" href="https://teletype.in/@chpotl/the-graph-intro?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=chpotl"></link><title>The Graph: великий, но не такой уж и ужасный</title><published>2024-07-19T18:04:59.296Z</published><updated>2024-07-19T18:27:13.318Z</updated><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://img1.teletype.in/files/83/24/832448f4-cf50-4955-9d47-463b7f4400c9.png"></media:thumbnail><summary type="html">&lt;img src=&quot;https://img1.teletype.in/files/0c/32/0c326dcd-47d4-45c9-b5be-e78c68ad74f8.jpeg&quot;&gt;Всем привет! В этой статье мы рассмотрим The Graph, зачем он нужен и как у блокчейна может быть API.</summary><content type="html">
  &lt;figure id=&quot;NVTm&quot; class=&quot;m_retina&quot;&gt;
    &lt;img src=&quot;https://img1.teletype.in/files/0c/32/0c326dcd-47d4-45c9-b5be-e78c68ad74f8.jpeg&quot; width=&quot;960&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;vilV&quot;&gt;Всем привет! В этой статье мы рассмотрим The Graph, зачем он нужен и как у блокчейна может быть API.&lt;/p&gt;
  &lt;h2 id=&quot;sJfv&quot;&gt;Введение&lt;/h2&gt;
  &lt;p id=&quot;XLOe&quot;&gt;Давайте представим, что мы делаем приложение, которое будет считать объем торгов на Uniswap за последний месяц.&lt;/p&gt;
  &lt;p id=&quot;TqWd&quot;&gt;Uniswap это и без нас делает &lt;a href=&quot;https://app.uniswap.org/explore&quot; target=&quot;_blank&quot;&gt;вот тут&lt;/a&gt;, используя The Graph, но опустим этот момент.&lt;/p&gt;
  &lt;p id=&quot;Hi8Y&quot;&gt;Так вот, встает вопрос: как же это сделать?&lt;/p&gt;
  &lt;h3 id=&quot;7kC2&quot;&gt;Способ №1&lt;/h3&gt;
  &lt;p id=&quot;SiE8&quot;&gt;Давайте напишем простой скрипт, который будет с какой-то периодичностью получать текущий номер блока и искать ивенты “Swap” на заранее заданном контракте пула.&lt;/p&gt;
  &lt;p id=&quot;k42f&quot;&gt;Вот примерный псевдо-код:&lt;/p&gt;
  &lt;figure id=&quot;fpfZ&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img4.teletype.in/files/b0/b8/b0b885b1-90a1-4af3-be72-d5a712b1d0b5.jpeg&quot; width=&quot;1920&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;ZLye&quot;&gt;&lt;strong&gt;У этого подхода есть минусы:&lt;/strong&gt;&lt;/p&gt;
  &lt;ol id=&quot;JCNQ&quot;&gt;
    &lt;li id=&quot;CLVL&quot;&gt;&lt;strong&gt;RPC&lt;/strong&gt;: они имеют свойство ломаться, и мы рискуем пропустить несколько блоков, тем самым на выходе получить некорректные данные.&lt;/li&gt;
    &lt;li id=&quot;l1ny&quot;&gt;&lt;strong&gt;Масштабируемость&lt;/strong&gt;: когда мы захотим отслеживать не только один пул, а все возможные новые, то тут придется заморочиться.&lt;/li&gt;
    &lt;li id=&quot;16zB&quot;&gt;&lt;strong&gt;Архитектура&lt;/strong&gt;: вставлять модуль, который как-то циклично собирает данные в основное приложение, не очень хорошая идея, нужно его куда-то выносить.&lt;/li&gt;
  &lt;/ol&gt;
  &lt;h3 id=&quot;MiBA&quot;&gt;Подход 2&lt;/h3&gt;
  &lt;p id=&quot;HqgG&quot;&gt;Делать как Aerofrome/Velodrome - свой отдельный контракт с аналитикой.&lt;/p&gt;
  &lt;section style=&quot;background-color:hsl(hsl(236, 74%, var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;p id=&quot;m9YM&quot;&gt;Вот тут можно посмотреть код: &lt;a href=&quot;https://github.com/aerodrome-finance/sugar&quot; target=&quot;_blank&quot;&gt;https://github.com/aerodrome-finance/sugar&lt;/a&gt;&lt;/p&gt;
  &lt;/section&gt;
  &lt;figure id=&quot;bUDT&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img2.teletype.in/files/51/15/5115f56d-316f-4cce-8518-18bbb35639bd.jpeg&quot; width=&quot;1920&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;hVqK&quot;&gt;Вызвав метод &lt;code&gt;epochLatest&lt;/code&gt;, мы можем получить данные по последней эпохе или получить данные по каждой эпохе для пула, вызывая &lt;code&gt;epochByAddress&lt;/code&gt;.&lt;/p&gt;
  &lt;p id=&quot;g3d5&quot;&gt;&lt;strong&gt;Минусы:&lt;/strong&gt;&lt;/p&gt;
  &lt;ol id=&quot;UViE&quot;&gt;
    &lt;li id=&quot;Y8x6&quot;&gt;&lt;strong&gt;Сложно.&lt;/strong&gt;&lt;/li&gt;
    &lt;li id=&quot;JtKt&quot;&gt;&lt;strong&gt;Дорого.&lt;/strong&gt;&lt;/li&gt;
    &lt;li id=&quot;da1U&quot;&gt;&lt;strong&gt;Не все данные можно собрать.&lt;/strong&gt;&lt;/li&gt;
  &lt;/ol&gt;
  &lt;p id=&quot;Kbf3&quot;&gt;Таким образом, мы плавно переходим к The Graph.&lt;/p&gt;
  &lt;p id=&quot;Iy1V&quot;&gt;&lt;/p&gt;
  &lt;h2 id=&quot;UX0p&quot;&gt;&lt;strong&gt;Subgrpaph&lt;/strong&gt;&lt;/h2&gt;
  &lt;p id=&quot;uyTX&quot;&gt;The Graph - это протокол, который включает в себя такие сущности, как сабграфы (subgraph).&lt;/p&gt;
  &lt;p id=&quot;DyVR&quot;&gt;Каждый сабграф представляет из себя набор логики, позволяющий обрабатывать набор контрактов.&lt;/p&gt;
  &lt;section style=&quot;background-color:hsl(hsl(236, 74%, var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;p id=&quot;AJp4&quot;&gt;&lt;strong&gt;Если приводить очень простой пример&lt;/strong&gt;&lt;/p&gt;
    &lt;p id=&quot;g9R9&quot;&gt;Представьте, что у вас есть &lt;u&gt;большая библиотека&lt;/u&gt;, наполненная большим количеством книг на разные темы. Эта библиотека настолько большая, что поиск информации по определенной теме может оказаться очень сложным и отнять много времени. И руководство библиотеки решает нанять &lt;u&gt;библиотекарей&lt;/u&gt;, чтобы &lt;u&gt;каждый отвечал за отдельный раздел&lt;/u&gt; этой библиотеки: выдавал нужные книги, сортировал и следил за порядком.&lt;/p&gt;
  &lt;/section&gt;
  &lt;p id=&quot;9NZu&quot;&gt;В этом примере библиотека - это блокчейн, а библиотекари - это сабграфы.&lt;/p&gt;
  &lt;figure id=&quot;buW4&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img4.teletype.in/files/b8/80/b880d789-ef6f-422f-8a6b-4073c025d3fb.jpeg&quot; width=&quot;1920&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;3pFz&quot;&gt;Каждый сабграф отслеживает emit событий на контрактах и сохраняет их в свою внутреннюю базу данных, чтобы потом любое приложение могло получить данные о свапах, транзакциях пользователя или еще о каких-либо действиях, произошедших в контрактах, используя GraphQL.&lt;/p&gt;
  &lt;section style=&quot;background-color:hsl(hsl(263, 48%, var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;p id=&quot;9IYK&quot;&gt;&lt;strong&gt;Важно понимать, что сабграф - это больше data layer, чем полноценный бэкенд.&lt;/strong&gt;&lt;/p&gt;
    &lt;p id=&quot;mLcQ&quot;&gt;Если логика &lt;u&gt;не требует дополнительных расчетов&lt;/u&gt;, то можно обойтись &lt;u&gt;только сабграфом&lt;/u&gt; и веб-интерфейсом, но если вам необходимо отсылать какие-то уведомления в Slack или как-то &lt;u&gt;по-хитрому агрегировать&lt;/u&gt; уже полученные данные, то будет необходимо &lt;u&gt;построить бэкенд&lt;/u&gt;, который будет заниматься промежуточной обработкой, прежде чем отдавать их на фронт.&lt;/p&gt;
  &lt;/section&gt;
  &lt;p id=&quot;KYmT&quot;&gt;&lt;/p&gt;
  &lt;h2 id=&quot;B6Le&quot;&gt;Создание сабграфа&lt;/h2&gt;
  &lt;p id=&quot;Y5S8&quot;&gt;Чтобы развернуть свой сабграф, вам необходимо сделать следующие вещи:&lt;/p&gt;
  &lt;ol id=&quot;E4vA&quot;&gt;
    &lt;li id=&quot;ZBYj&quot;&gt;Создать обработчики событий, используя AssemblyScript (TypeScript, но с определенными ограничениями).&lt;/li&gt;
    &lt;li id=&quot;wMDR&quot;&gt;Задеплоить код в Subgraph Studio - это среда (по сути staging environment) для тестирования и отладки работы сабграфа.&lt;/li&gt;
    &lt;li id=&quot;Ia7X&quot;&gt;Опубликовать в Subgraph Network, для этого необходимо ~3000 GRT, которые вы залочите, но в любой момент сможете вытащить.&lt;/li&gt;
  &lt;/ol&gt;
  &lt;h3 id=&quot;GHVF&quot;&gt;YAML&lt;/h3&gt;
  &lt;p id=&quot;rIsG&quot;&gt;Первым компонентом необходимо создать .yaml файл, где будет указано, какие события, как часто мы “слушаем”, и какую логику мы хотим с ними сделать.&lt;/p&gt;
  &lt;figure id=&quot;Fn8P&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img4.teletype.in/files/f4/cb/f4cbd2f7-134b-4b4a-b844-9c6dace881df.jpeg&quot; width=&quot;1920&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;RuY9&quot;&gt;В качестве примера я взял код PancakeSwap: &lt;a href=&quot;https://github.com/pancakeswap/pancake-subgraph&quot; target=&quot;_blank&quot;&gt;GitHub PancakeSwap&lt;/a&gt;.&lt;/p&gt;
  &lt;h3 id=&quot;m6uk&quot;&gt;Schema&lt;/h3&gt;
  &lt;p id=&quot;IZAO&quot;&gt;Также для создания сабграфа нам нужна схема сущностей, чтобы сгенерировать типы.&lt;/p&gt;
  &lt;figure id=&quot;dgXN&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img3.teletype.in/files/e2/c5/e2c573b0-2356-4bf9-b02f-5888137959a5.jpeg&quot; width=&quot;1920&quot; /&gt;
  &lt;/figure&gt;
  &lt;h3 id=&quot;wZDa&quot;&gt;Handler&lt;/h3&gt;
  &lt;p id=&quot;ol7G&quot;&gt;Далее нам необходимо создать обработчик, который будет сохранять события в базу данных.&lt;/p&gt;
  &lt;figure id=&quot;kTxB&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img3.teletype.in/files/66/75/66759b6a-af89-4fa1-8ee2-cd9edc1e97e9.jpeg&quot; width=&quot;1920&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;OoGd&quot;&gt;Указанных выше компонентов нам будет достаточно, чтобы создать полностью рабочий сабграф.&lt;/p&gt;
  &lt;section style=&quot;background-color:hsl(hsl(263, 48%, var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;p id=&quot;AYU4&quot;&gt;Все остальные шаги в полной мере описывает документация: &lt;a href=&quot;https://thegraph.com/docs/en/&quot; target=&quot;_blank&quot;&gt;https://thegraph.com/docs/en/&lt;/a&gt;. &lt;/p&gt;
    &lt;p id=&quot;tFJQ&quot;&gt;&lt;strong&gt;Рекомендую читать английскую версию, так как в русской есть места, которые еще не переведены.&lt;/strong&gt;&lt;/p&gt;
  &lt;/section&gt;
  &lt;p id=&quot;ucPi&quot;&gt;&lt;/p&gt;
  &lt;h2 id=&quot;i54q&quot;&gt;Делитесь с друзьями, если статья была полезной 😘&lt;/h2&gt;
  &lt;h3 id=&quot;qHh0&quot;&gt;Спасибо за прочтение!&lt;/h3&gt;
  &lt;h3 id=&quot;Q6pS&quot;&gt;Мой телеграм - &lt;a href=&quot;https://t.me/chpotldev&quot; target=&quot;_blank&quot;&gt;https://t.me/chpotldev&lt;/a&gt;&lt;/h3&gt;

</content></entry><entry><id>chpotl:delta-neutral</id><link rel="alternate" type="text/html" href="https://teletype.in/@chpotl/delta-neutral?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=chpotl"></link><title>Дельта-нейтральные стратегии: просто о сложном</title><published>2024-07-01T20:47:29.242Z</published><updated>2024-07-01T21:11:16.768Z</updated><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://img1.teletype.in/files/86/fb/86fbcbd2-ad95-499a-9735-031a25090114.png"></media:thumbnail><summary type="html">&lt;img src=&quot;https://img1.teletype.in/files/c7/c1/c7c127d0-3e07-465d-b449-563a4782c7bf.jpeg&quot;&gt;Всем привет! В этой статье я расскажу, что такое дельта-нейтральные стратегии и как можно получать доходность на волатильных активах, не теряя при этом на изменении курса.</summary><content type="html">
  &lt;figure id=&quot;qgUf&quot; class=&quot;m_retina&quot;&gt;
    &lt;img src=&quot;https://img1.teletype.in/files/c7/c1/c7c127d0-3e07-465d-b449-563a4782c7bf.jpeg&quot; width=&quot;960&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;piW7&quot;&gt;Всем привет! В этой статье я расскажу, что такое дельта-нейтральные стратегии и как можно получать доходность на волатильных активах, не теряя при этом на изменении курса.&lt;/p&gt;
  &lt;p id=&quot;zOUb&quot;&gt;&lt;/p&gt;
  &lt;h2 id=&quot;fWT1&quot;&gt;Хэджирование&lt;/h2&gt;
  &lt;p id=&quot;3QnE&quot;&gt;Перед тем, как мы перейдем к самому принципу работы дельта-нейтральных стратегий, нам необходимо познакомиться с таким понятием, как хеджирование.&lt;/p&gt;
  &lt;p id=&quot;xK4L&quot;&gt;Вот как википедия объясняет этот термин:&lt;/p&gt;
  &lt;blockquote id=&quot;96c6&quot;&gt;&lt;strong&gt;Хеджи́рование&lt;/strong&gt; (от англ. hedge — ограда, изгородь) — открытие сделок на одном рынке для компенсации воздействия ценовых рисков равной, но противоположной позиции на другом рынке.&lt;/blockquote&gt;
  &lt;p id=&quot;tF3E&quot;&gt;Чтобы было понятнее, давайте разберем на примерах:&lt;/p&gt;
  &lt;p id=&quot;hcct&quot;&gt;Представим ситуацию: вы хотите участвовать в акции от биржи, где нужно залочить 3,5 ETH на 3 дня. Но эфир это волатильный актив, и за эти 3 дня цена может сильно упасть, и вы потеряете больше, чем заработаете.&lt;/p&gt;
  &lt;figure id=&quot;K9Dv&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img2.teletype.in/files/9d/20/9d20edd3-51b6-4303-85bc-c766f5d2a165.jpeg&quot; width=&quot;1920&quot; /&gt;
    &lt;figcaption&gt;Пример акции &lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;Mveu&quot;&gt;Как же нам купить эфириум и одновременно застраховать себя от потери в случае падении цены?&lt;/p&gt;
  &lt;p id=&quot;k8GK&quot;&gt;Все достаточно просто!&lt;/p&gt;
  &lt;p id=&quot;hrQ5&quot;&gt;&lt;u&gt;Нам необходимо открыть 2 противоположные позиции одну в лонг, а вторую в шорт.&lt;/u&gt;&lt;/p&gt;
  &lt;p id=&quot;AgDa&quot;&gt;Предположим у нас есть 10&amp;#x27;000 USDT, мы хотим хэджировать 1 ETH.&lt;/p&gt;
  &lt;p id=&quot;kCxy&quot;&gt;Для этого нам необходимо одновременно обменять половину USDT на ETH (предположим, курс 1 ETH = 5’000 USDT, это можно сделать на любой бирже), а также открыть шорт на 5’000 USDT по эфириуму.&lt;/p&gt;
  &lt;p id=&quot;5BVl&quot;&gt;Давайте посмотрим, как будет вести себя общая стоимость наших активов в пересчете на USDT, если 1 ETH подешевеет на 40% и будет стоить 3’000 USDT.&lt;/p&gt;
  &lt;figure id=&quot;3l8n&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img3.teletype.in/files/e0/32/e03299e8-f558-44bc-b58b-9118bc4c747f.jpeg&quot; width=&quot;1920&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;KRco&quot;&gt;Как мы можем заметить, две позиции скомпенсировали друг друга, мы ничего не потеряли, и у нас на кошельке остался 1 ETH.&lt;/p&gt;
  &lt;p id=&quot;NxqF&quot;&gt;В случае если 1 ETH подорожает на 40% и будет стоить 7&amp;#x27;000 USDT, то мы ничего не заработаем&lt;/p&gt;
  &lt;figure id=&quot;lkka&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img4.teletype.in/files/b6/6e/b66e644f-66b2-4842-8bed-a777f333e9cf.jpeg&quot; width=&quot;1920&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;GbBC&quot;&gt;Таким образом можно заметить, что при любом движении цены мы можем продать 1 ETH и закрыть шорт, и в итоге на балансе мы снова увидим 10’000 USDT.&lt;br /&gt;А пока у нас открыты две противоположные позиции, мы можем делать с нашим эфиром что захотим, не боясь потерять на курсе.&lt;/p&gt;
  &lt;section style=&quot;background-color:hsl(hsl(0,   0%,  var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;p id=&quot;ITXr&quot;&gt;&lt;strong&gt;&lt;u&gt;ВАЖНО: этот пример не учитывает риск ликвидации и фандинг рейт, возможность маржинальной торговли и тп.&lt;/u&gt;&lt;/strong&gt;&lt;/p&gt;
  &lt;/section&gt;
  &lt;p id=&quot;SKG2&quot;&gt;&lt;/p&gt;
  &lt;h2 id=&quot;pUBN&quot;&gt;Дельта-нейтральные стратегии&lt;/h2&gt;
  &lt;p id=&quot;1OHy&quot;&gt;В примере про хеджирование мы рассмотрели, как можно защитить волатильный актив от движения цены.&lt;/p&gt;
  &lt;p id=&quot;kPJ9&quot;&gt;Давайте теперь разберемся, что такое дельта-нейтральные стратегии и какие они бывают.&lt;/p&gt;
  &lt;section style=&quot;background-color:hsl(hsl(0,   0%,  var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;p id=&quot;TbTR&quot;&gt;&lt;strong&gt;Существует два основных вида дельта-нейтралных стратегий:&lt;/strong&gt;&lt;/p&gt;
    &lt;ul id=&quot;rndh&quot;&gt;
      &lt;li id=&quot;ze8U&quot;&gt;&lt;u&gt;Long-short&lt;/u&gt; - стратегии, где хэджирование происходит, &lt;em&gt;через фьючерсы&lt;/em&gt;&lt;/li&gt;
      &lt;li id=&quot;hZqF&quot;&gt;&lt;u&gt;Lend-borrow&lt;/u&gt; - стратегии, где хэджирование происходит, &lt;em&gt;через займ&lt;/em&gt;&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/section&gt;
  &lt;p id=&quot;RrTj&quot;&gt;&lt;/p&gt;
  &lt;h3 id=&quot;Hb1a&quot;&gt;Long-short стратегии&lt;/h3&gt;
  &lt;p id=&quot;0w1U&quot;&gt;В начале статьи мы познакомились с понятием хеджирования фьючерсами. Сейчас нам пригодится это.&lt;/p&gt;
  &lt;p id=&quot;L7iR&quot;&gt;Чтобы получать доход на long-short стратегиях, нам нужно:&lt;/p&gt;
  &lt;section style=&quot;background-color:hsl(hsl(0,   0%,  var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;p id=&quot;zAwe&quot;&gt;&lt;strong&gt;Вводные данные:&lt;/strong&gt; мы имеем на балансе 12&amp;#x27;000 USDT и хотим фармить, используя эфириум в нашей стратегии.&lt;/p&gt;
    &lt;p id=&quot;Ckjv&quot;&gt;1 ETH = 4&amp;#x27;000 USDT (для примера).&lt;/p&gt;
  &lt;/section&gt;
  &lt;ol id=&quot;wgXI&quot;&gt;
    &lt;li id=&quot;YxN8&quot;&gt;Мы берем наш депозит в стейблах и делим на 3 части (4&amp;#x27;000/4&amp;#x27;000/4&amp;#x27;000);&lt;/li&gt;
    &lt;li id=&quot;5jJT&quot;&gt;Первую часть временно откладываем в сторону, а используя две другие части, открываем равные противоположные позиции: лонг (покупаем 1 ETH на любом DEX/CEX) и шорт (открываем sell ордер на бирже или на децентрализованных фьючерсах). Иными словами, мы хеджируем 1 ETH, который мы купили;&lt;/li&gt;
    &lt;li id=&quot;oVi1&quot;&gt;Теперь мы имеем 1 ETH и 4&amp;#x27;000 USDT на балансе + открытый шорт;&lt;/li&gt;
    &lt;li id=&quot;QNh9&quot;&gt;С нашим 1 ETH мы теперь можем делать что угодно, положить в lido, или взять оба актива и положить в пул.&lt;/li&gt;
  &lt;/ol&gt;
  &lt;p id=&quot;afjz&quot;&gt;Defilama предоставляет список возможных стратегий в своем интерфейсе&lt;/p&gt;
  &lt;figure id=&quot;UJP2&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img2.teletype.in/files/5a/10/5a1015b1-8757-4a00-98ce-a7e65691c3b4.jpeg&quot; width=&quot;1920&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;FiKl&quot;&gt;&lt;/p&gt;
  &lt;h3 id=&quot;9cMx&quot;&gt;Lend-borrow стратегии&lt;/h3&gt;
  &lt;p id=&quot;bKaF&quot;&gt;Суть стратегии заключается в том, что мы половину стейблкоинов кладем в кредитный протокол в качестве обеспечения, под них берем волатильный актив и кладем его в пул вместе со второй половиной стейблкоинов.&lt;/p&gt;
  &lt;p id=&quot;54ps&quot;&gt;Давайте разберемся, откуда тут доходность и почему мы нейтральны.&lt;/p&gt;
  &lt;section style=&quot;background-color:hsl(hsl(0,   0%,  var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;p id=&quot;YySU&quot;&gt;&lt;strong&gt;Сразу уточню:&lt;/strong&gt; эти стратегии по факту &lt;u&gt;нельзя&lt;/u&gt; назвать 100% дельта-нейтральными, дальше объясню почему.&lt;/p&gt;
  &lt;/section&gt;
  &lt;figure id=&quot;s3jF&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img3.teletype.in/files/27/c6/27c6d355-57b6-46a3-b5ad-621dae657e7f.jpeg&quot; width=&quot;1920&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;qmT1&quot;&gt;Как мы видим на примере выше, мы положили 5454 USDT в качестве обеспечения, под них взяли 0,9 ETH, и положили все под 10% в пул.&lt;/p&gt;
  &lt;p id=&quot;U3aQ&quot;&gt;Суммарная доходность: 8%, так как мы получаем 3% APY, за то что дали свои деньги в пользование, платим -5% APY за кредит, и получаем 10% APY с комиссий + наград в пуле. Итого: 8%, если все сложить.&lt;/p&gt;
  &lt;p id=&quot;5zJt&quot;&gt;Мы разобрались с доходностью, теперь давайте рассмотрим, как будет вести себя позиция при движении цены.&lt;/p&gt;
  &lt;p id=&quot;AQba&quot;&gt;Если цена эфириума упадет на -40%, то мы окажемся в плюсе, так как сможем занять еще больше средств или вынуть из пула и погасить часть долга.&lt;/p&gt;
  &lt;figure id=&quot;jH1X&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img1.teletype.in/files/c4/0e/c40e5f4f-8c17-492d-a8a2-6319caa2973f.jpeg&quot; width=&quot;1920&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;4JRn&quot;&gt; Давайте посмотрим, как изменится наша позиция после ребалансировки.&lt;/p&gt;
  &lt;figure id=&quot;80J1&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img1.teletype.in/files/0c/ad/0caddb55-6a06-4ad7-8c94-ac8319d52a1b.jpeg&quot; width=&quot;1920&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;gcw3&quot;&gt;Теперь мы можем получать большую доходность, не изменяя изначальное количество вложенных средств.&lt;/p&gt;
  &lt;p id=&quot;bsxa&quot;&gt;Рассмотрим пример, когда цена растет. Тут уже возникает ситуация, когда нам надо компенсировать убытки.&lt;/p&gt;
  &lt;figure id=&quot;Im0M&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img1.teletype.in/files/8e/41/8e41a588-c630-49d2-b3c4-d2471a6e43a9.jpeg&quot; width=&quot;1920&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;QYOr&quot;&gt;В нашем примере для балансировки пришлось достать очень много средств, в реальности же ребалансировка должна происходить постепенно вместе с движением цены, чтобы не допускать сильных изменений.&lt;/p&gt;
  &lt;p id=&quot;kZEt&quot;&gt;Вот так будет выглядеть наша позиция после балансировки:&lt;/p&gt;
  &lt;figure id=&quot;b6pB&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img2.teletype.in/files/d6/e5/d6e527bd-fc31-47fd-8d14-134c1716a5dc.jpeg&quot; width=&quot;1920&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;rwh1&quot;&gt;Как мы убедились, стратегию сложно назвать нейтральной, так как в случае движения цены вверх мы теряем средства.&lt;/p&gt;
  &lt;section style=&quot;background-color:hsl(hsl(0,   0%,  var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;p id=&quot;ckoR&quot;&gt;&lt;em&gt;&lt;strong&gt;Также можно заметить, что мы своего рода открыли шорт используя кредитный протокол...&lt;/strong&gt;&lt;/em&gt;&lt;/p&gt;
  &lt;/section&gt;
  &lt;p id=&quot;twOF&quot;&gt;&lt;/p&gt;
  &lt;h2 id=&quot;i54q&quot;&gt;Делитесь с друзьями, если статья была полезной 😘&lt;/h2&gt;
  &lt;h3 id=&quot;qHh0&quot;&gt;Спасибо за прочтение!&lt;/h3&gt;
  &lt;h3 id=&quot;Q6pS&quot;&gt;Мой телеграм - &lt;a href=&quot;https://t.me/chpotldev&quot; target=&quot;_blank&quot;&gt;https://t.me/chpotldev&lt;/a&gt;&lt;/h3&gt;

</content></entry><entry><id>chpotl:curve-stable-swap</id><link rel="alternate" type="text/html" href="https://teletype.in/@chpotl/curve-stable-swap?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=chpotl"></link><title>Curve StableSwap введение</title><published>2024-04-26T12:04:21.827Z</published><updated>2024-04-26T12:04:21.827Z</updated><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://img3.teletype.in/files/69/69/696924e7-a390-4e10-a495-090eacef23da.png"></media:thumbnail><summary type="html">&lt;img src=&quot;https://img1.teletype.in/files/82/35/8235c310-8c36-4e00-bfe9-358650ce8f67.jpeg&quot;&gt;Всех приветствую! В этой стате я расскажу как работают пулы curve.fi, и почему это произвело революцию в мире defi.</summary><content type="html">
  &lt;figure id=&quot;5ib5&quot; class=&quot;m_retina&quot;&gt;
    &lt;img src=&quot;https://img1.teletype.in/files/82/35/8235c310-8c36-4e00-bfe9-358650ce8f67.jpeg&quot; width=&quot;960&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;GPD1&quot;&gt;&lt;strong&gt;Всех приветствую!&lt;/strong&gt; В этой стате я расскажу как работают пулы &lt;a href=&quot;http://curve.fi&quot; target=&quot;_blank&quot;&gt;curve.fi&lt;/a&gt;, и почему это произвело революцию в мире defi.&lt;/p&gt;
  &lt;p id=&quot;rugT&quot;&gt;&lt;/p&gt;
  &lt;section style=&quot;background-color:hsl(hsl(0,   0%,  var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;p id=&quot;55X4&quot;&gt;&lt;strong&gt;Важно&lt;/strong&gt;: под некоторыми графиками &lt;u&gt;прикреплена ссылка&lt;/u&gt; на&lt;u&gt; интерактивный график&lt;/u&gt;, если хотите лучше понять материал, обязательно подвигайте ползунки&lt;/p&gt;
  &lt;/section&gt;
  &lt;h2 id=&quot;pbIC&quot;&gt;Немного о Curve&lt;/h2&gt;
  &lt;p id=&quot;ZQ2p&quot;&gt;Основная цель &lt;a href=&quot;http://curve.fi&quot; target=&quot;_blank&quot;&gt;curve.fi&lt;/a&gt; - это предоставление возможности обмена стейблкоинов с низким проскальзыванием (далее подробнее разберем, что это такое).&lt;/p&gt;
  &lt;p id=&quot;soac&quot;&gt;Начнем по порядку разбираться, как устроены АММ алогоритмы.&lt;/p&gt;
  &lt;h2 id=&quot;OEaC&quot;&gt;Uniswap AMM&lt;/h2&gt;
  &lt;p id=&quot;BcBE&quot;&gt;Каждый, кто хоть немного углублялся в defi встречал формулу .&lt;/p&gt;
  &lt;section style=&quot;background-color:hsl(hsl(0,   0%,  var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;p id=&quot;W2TZ&quot;&gt;&lt;strong&gt;x*y=k&lt;/strong&gt;&lt;/p&gt;
  &lt;/section&gt;
  &lt;p id=&quot;1hPk&quot;&gt;Это упрощенное представление алгоритма, который лежит в основе Uniswap.&lt;/p&gt;
  &lt;p id=&quot;JbWe&quot;&gt;Это формула означает, что отношение активов (токенов) в пуле - это неизменное значение.&lt;/p&gt;
  &lt;p id=&quot;pTEX&quot;&gt;&lt;strong&gt;Пример:&lt;/strong&gt;&lt;/p&gt;
  &lt;p id=&quot;I0FV&quot;&gt;Представим, что у нас есть пул USDT/ETH, и в пуле лежит 40000 USDT (это X) и 10 ETH (это Y), таким образом 40000*10=400’000 (это K).&lt;/p&gt;
  &lt;p id=&quot;G2rg&quot;&gt;Теперь к нам пришел условный Вася и хочет обменять свои 4000 USDT на ETH.&lt;/p&gt;
  &lt;p id=&quot;f8gU&quot;&gt;Давайте посчитаем как изменится количество токенов в пуле, используя нашу формулу.&lt;/p&gt;
  &lt;p id=&quot;6DOZ&quot;&gt;После того как Вася внес 4000 USDT, в пуле стало 44000 USDT (там еще Uniswap забирает комиссию 0.3%, но мы опустим это).&lt;/p&gt;
  &lt;p id=&quot;Hevr&quot;&gt;Теперь на надо посчитать сколько ETH нужно отдать Васе.&lt;/p&gt;
  &lt;p id=&quot;axqB&quot;&gt;Составим простое уравнение за средней школы:&lt;/p&gt;
  &lt;p id=&quot;Om1u&quot;&gt;44000 (наш Х) * y = 400000 (наш К)&lt;/p&gt;
  &lt;p id=&quot;GcLO&quot;&gt;Теперь нам надо найти сколько ETH должно быть в пуле, чтобы уравнение сошлось. Разделим обе части на 44000 (то есть X) и получим y=400000/44000. Таким образом y=9.09&lt;br /&gt;Mы получили количество &lt;u&gt;ETH, которое ДОЛЖНО БЫТЬ В ПУЛЕ&lt;/u&gt;. Теперь надо разницу отдать Васе. 10ETH - 9.09ETH = 0.91 ETH (куда делось 0.09 ETH???, &lt;u&gt;читать продолжение…&lt;/u&gt;)&lt;/p&gt;
  &lt;h3 id=&quot;17tJ&quot;&gt;&lt;strong&gt;Автоматическая установка цены&lt;/strong&gt;&lt;/h3&gt;
  &lt;p id=&quot;8pK2&quot;&gt;Как мы могли заметить, когда Вася внес 4000 USDT, цена автоматически изменилась.&lt;/p&gt;
  &lt;p id=&quot;qyVg&quot;&gt;Теперь 1 ETH стоит Y/X, то есть 44000/9.09=4840 USDT.&lt;/p&gt;
  &lt;p id=&quot;Kvs1&quot;&gt;Давайте рассмотрим, что произойдет, когда Вася захочет еще раз обменять 4000 USDT.&lt;/p&gt;
  &lt;p id=&quot;dYfj&quot;&gt;Произведем еще раз все вычисления:&lt;/p&gt;
  &lt;p id=&quot;CtFH&quot;&gt;(44000 + 4000) * y = 400000&lt;/p&gt;
  &lt;p id=&quot;A8PC&quot;&gt;Y = 8.33&lt;/p&gt;
  &lt;p id=&quot;o0ld&quot;&gt;Таким образом в пуле станет 48000 USDT, 8,33 ETH&lt;/p&gt;
  &lt;p id=&quot;OoRD&quot;&gt;И 1 ETH будет стоить 5762 USDT&lt;/p&gt;
  &lt;p id=&quot;7R5H&quot;&gt;Как мы увидели на двух примерах, при росте спроса на один из активов, цена второго автоматики изменяется. Потому это и называется AMM (автоматический маркет мейкер).&lt;/p&gt;
  &lt;figure id=&quot;Y6Nm&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img1.teletype.in/files/87/06/8706d4e3-9d47-4342-8d76-ccedf012cddb.gif&quot; width=&quot;1920&quot; /&gt;
    &lt;figcaption&gt;извиняюсь за качество&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;section style=&quot;background-color:hsl(hsl(0,   0%,  var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;p id=&quot;QK5l&quot;&gt;&lt;u&gt;Красный график&lt;/u&gt; показывает &lt;strong&gt;количество&lt;/strong&gt; токенов в пуле&lt;/p&gt;
    &lt;p id=&quot;M3yR&quot;&gt;&lt;u&gt;Синий график&lt;/u&gt; (производная от x*y) показывает &lt;strong&gt;цену&lt;/strong&gt; токенов&lt;/p&gt;
  &lt;/section&gt;
  &lt;p id=&quot;zv4U&quot;&gt;&lt;/p&gt;
  &lt;h3 id=&quot;ok3Q&quot;&gt;&lt;strong&gt;Проскальзывание &lt;/strong&gt;&lt;/h3&gt;
  &lt;p id=&quot;V5jn&quot;&gt;Проскальзывание - это величина, которая показывает насколько изменится цена, после того как покупатель, Вася в нашем случае, захочет обменять средства. Если говорить максимально просто, то это то насколько меньше вы получите по факту сделки.&lt;/p&gt;
  &lt;p id=&quot;jgIO&quot;&gt;В первом примере мы увидели, что изначально 1 ETH стоил 4000 USDT, но по факту Вася купил по цене 4395 USDT (4000/0.91)&lt;/p&gt;
  &lt;p id=&quot;uBgc&quot;&gt;&lt;/p&gt;
  &lt;h3 id=&quot;2EoJ&quot;&gt;&lt;strong&gt;От чего зависит проскальзывание?&lt;/strong&gt;&lt;/h3&gt;
  &lt;p id=&quot;4gFV&quot;&gt;&lt;u&gt;Ответ: от ликвидности (количества токенов в пуле)&lt;/u&gt;&lt;/p&gt;
  &lt;p id=&quot;wlu1&quot;&gt;Разберемся почему:&lt;/p&gt;
  &lt;p id=&quot;3m0i&quot;&gt;Формула для расчета проскальзывания выглядит так: &lt;/p&gt;
  &lt;figure id=&quot;nOoZ&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img1.teletype.in/files/01/a2/01a22bf3-c830-4d6b-9672-0bb618bf71f7.png&quot; width=&quot;1920&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;mKuw&quot;&gt;Чтобы проще понять, как работает эта формула рассмотрим два случая&lt;/p&gt;
  &lt;ol id=&quot;jLBU&quot;&gt;
    &lt;li id=&quot;IEWk&quot;&gt;Если мы захотим купить небольшое количество токенов, то δ (сколько мы купим) будет сильно меньше X (сколько в пуле) (δ &amp;lt;&amp;lt; X, это для гиков выражение), и получился S = 1 - (очень близкое к 1 число), то есть проскальзываете будет стремиться к 0.&lt;/li&gt;
    &lt;li id=&quot;nlXP&quot;&gt;Для пула, где очень много токенов X будет стремиться к бесконечности, таким образом проскальзывание тоже будет стремиться к 0.&lt;/li&gt;
  &lt;/ol&gt;
  &lt;section style=&quot;background-color:hsl(hsl(0,   0%,  var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;p id=&quot;Htip&quot;&gt;Предположим у нас есть пул, где:&lt;/p&gt;
    &lt;p id=&quot;fg6Y&quot;&gt;&lt;strong&gt;1&amp;#x27;000&amp;#x27;000 токенов X&lt;/strong&gt;&lt;/p&gt;
    &lt;p id=&quot;ItzY&quot;&gt;&lt;strong&gt;5&amp;#x27;000&amp;#x27;000 токенов Y&lt;/strong&gt;&lt;/p&gt;
    &lt;p id=&quot;ZNEA&quot;&gt;&lt;strong&gt;K = 5 * 10^12&lt;/strong&gt;&lt;/p&gt;
  &lt;/section&gt;
  &lt;p id=&quot;3nAt&quot;&gt;Рассмотрим два примера, как менялась цена (изначальная цена была 5 у.е):&lt;/p&gt;
  &lt;figure id=&quot;9X8V&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img1.teletype.in/files/44/dd/44dd3cca-06a5-44ad-ad99-8a97ad90799f.png&quot; width=&quot;1920&quot; /&gt;
  &lt;/figure&gt;
  &lt;h3 id=&quot;Cm0R&quot;&gt;Выкупаем один актив&lt;/h3&gt;
  &lt;p id=&quot;ni4N&quot;&gt;Давайте посмотрим, что произойдет, если кто-то захочет полностью забрать один из активов в пуле.&lt;/p&gt;
  &lt;section style=&quot;background-color:hsl(hsl(0,   0%,  var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;p id=&quot;D4DD&quot;&gt;В нашем воображаемом пуле будет&lt;/p&gt;
    &lt;p id=&quot;ooOV&quot;&gt;&lt;strong&gt;100 ETH&lt;/strong&gt;&lt;/p&gt;
    &lt;p id=&quot;vwg9&quot;&gt;&lt;strong&gt;400&amp;#x27;000 USDT&lt;/strong&gt;&lt;/p&gt;
  &lt;/section&gt;
  &lt;p id=&quot;733W&quot;&gt;В нашем случае Вася будет покупать по 100 ETH на централизованной бирже и продавать в нашем пуле&lt;/p&gt;
  &lt;p id=&quot;mP2j&quot;&gt;Купив 100 ETH за 400000 USDT, он пришел в наш пул и продал 100 ETH &lt;/p&gt;
  &lt;section style=&quot;background-color:hsl(hsl(0,   0%,  var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;p id=&quot;w04U&quot;&gt;Теперь в пуле &lt;/p&gt;
    &lt;p id=&quot;DVFv&quot;&gt;&lt;strong&gt;200 ETH&lt;/strong&gt;&lt;/p&gt;
    &lt;p id=&quot;yfpp&quot;&gt;&lt;strong&gt;200&amp;#x27;000 USDT&lt;/strong&gt;&lt;/p&gt;
    &lt;p id=&quot;k67F&quot;&gt;Вася потратил 4000$&lt;/p&gt;
  &lt;/section&gt;
  &lt;p id=&quot;Xmmt&quot;&gt;Если сделать так очень много раз и построить график, то получится вот такая зависимость&lt;/p&gt;
  &lt;figure id=&quot;sZ0C&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img4.teletype.in/files/b4/0b/b40b2cdd-58a8-4a9f-96ae-96efeda2d52f.png&quot; width=&quot;1920&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;YmNE&quot;&gt;По графику видно, что чем больше денег мы тратим, тем меньше цена ETH, но в какой-то момент она начинает незначительно меняться в сравнении с потраченной суммой.&lt;/p&gt;
  &lt;p id=&quot;ypSH&quot;&gt;Таким образом можно заметить, что выкупить всю ликвидность из пула почти невозможно.&lt;/p&gt;
  &lt;p id=&quot;pYEh&quot;&gt;&lt;/p&gt;
  &lt;h2 id=&quot;2.-Curve&amp;#x27;s-AMM-algorithm&quot;&gt;Чем плох Uniswap AMM?&lt;/h2&gt;
  &lt;p id=&quot;Odop&quot;&gt;Представим ситуацию, что у нас в пуле лежит не ETH/USDT, а пара стейблкоинов USDT/USDC&lt;/p&gt;
  &lt;p id=&quot;lQXA&quot;&gt;Опять рассмотрим пример, где Вася на одну и ту же сумму покупает один из активов.&lt;/p&gt;
  &lt;section style=&quot;background-color:hsl(hsl(0,   0%,  var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;p id=&quot;KRo9&quot;&gt;У нас есть пул:&lt;/p&gt;
    &lt;p id=&quot;NxH1&quot;&gt;&lt;strong&gt;100&amp;#x27;000 USDT&lt;/strong&gt;&lt;/p&gt;
    &lt;p id=&quot;nV89&quot;&gt;&lt;strong&gt;100&amp;#x27;000 USDC&lt;/strong&gt;&lt;/p&gt;
  &lt;/section&gt;
  &lt;figure id=&quot;Ul6X&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img1.teletype.in/files/03/ed/03ed7908-157c-4c80-9dab-b424d61e64c6.png&quot; width=&quot;1920&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;Z8Xf&quot;&gt;Из таблиц видно, что при маленьких суммах разница не очень большая, но когда Вася начинает менять по 10000 USDT, то на &lt;strong&gt;3 сделке он теряет 500$ из-за проскальзывания, хотя меняет доллар на доллар.&lt;/strong&gt;&lt;/p&gt;
  &lt;p id=&quot;Qxfh&quot;&gt;&lt;/p&gt;
  &lt;h2 id=&quot;wtXZ&quot;&gt;Пул без проскальзывания (такое бывает ???)&lt;/h2&gt;
  &lt;p id=&quot;qSEu&quot;&gt;Давайте представим пул, в котором цена активов будет постоянной, то есть я в любой момент смогу обменять 1000 USDT на 1000 USDC 1:1, &lt;strong&gt;звучит как решение для нашей проблемы с обменом стейблкоинов.&lt;/strong&gt;&lt;/p&gt;
  &lt;p id=&quot;AT2B&quot;&gt;Но не так все просто и вот почему...&lt;/p&gt;
  &lt;p id=&quot;xRtS&quot;&gt;Если описывать такой пул, то это будет пул с линейной зависимостью (как на алгебре в 9 классе y=kx+b).&lt;/p&gt;
  &lt;p id=&quot;QBPS&quot;&gt;Например у нас есть пул, и в нем:&lt;/p&gt;
  &lt;section style=&quot;background-color:hsl(hsl(0,   0%,  var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;p id=&quot;hyd6&quot;&gt;&lt;strong&gt;1000 USDC&lt;/strong&gt;&lt;/p&gt;
    &lt;p id=&quot;Wvxn&quot;&gt;&lt;strong&gt;1000 USDT&lt;/strong&gt;&lt;/p&gt;
  &lt;/section&gt;
  &lt;p id=&quot;KQHo&quot;&gt;Выражение описывающее пул будет следующим:&lt;/p&gt;
  &lt;section style=&quot;background-color:hsl(hsl(0,   0%,  var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;p id=&quot;Udqe&quot;&gt;&lt;strong&gt;X + Y = C&lt;/strong&gt;&lt;/p&gt;
    &lt;p id=&quot;l7CR&quot;&gt;X - количество токена #1&lt;/p&gt;
    &lt;p id=&quot;oF8v&quot;&gt;Y - количество токена #2&lt;/p&gt;
    &lt;p id=&quot;9l90&quot;&gt;C - сумма токенов&lt;/p&gt;
    &lt;p id=&quot;MgXl&quot;&gt;&lt;u&gt;в нашем примере мы получим X + Y = 2000&lt;/u&gt;&lt;/p&gt;
  &lt;/section&gt;
  &lt;figure id=&quot;zPp4&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img3.teletype.in/files/a2/27/a227f6c4-387e-474c-9934-da2a7d5278c7.png&quot; width=&quot;1920&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;uig0&quot;&gt;Вот как это будет выглядеть, если мы построим график зависимости количества токенов в пуле.&lt;/p&gt;
  &lt;p id=&quot;cjIQ&quot;&gt;&lt;/p&gt;
  &lt;p id=&quot;yKuG&quot;&gt;Если к нам придет Вася и захочет внести пул 100 USDC, то путь вычислений будет следующий:&lt;/p&gt;
  &lt;section style=&quot;background-color:hsl(hsl(0,   0%,  var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;p id=&quot;ot8n&quot;&gt;(1000+100) + y = 2000&lt;/p&gt;
    &lt;p id=&quot;83zR&quot;&gt; y = 900&lt;/p&gt;
    &lt;p id=&quot;Cuqr&quot;&gt;&lt;strong&gt;значит Васе надо отправить 1000  - 900 = 100 USDT, &lt;/strong&gt;&lt;/p&gt;
  &lt;/section&gt;
  &lt;p id=&quot;7ycr&quot;&gt;Отлично! Вася только что обменял 100 USDT на 100 USDT, не потеряв ничего из-за проскальзывания, как это было в примере с юнисвапом&lt;/p&gt;
  &lt;p id=&quot;57xD&quot;&gt;&lt;strong&gt;Но есть одна проблема&lt;/strong&gt;&lt;/p&gt;
  &lt;p id=&quot;sG1r&quot;&gt;&lt;u&gt;Если Вася продолжит менять USDT на USDT, то в пуле закончатся USDT, а это плохо&lt;/u&gt;&lt;/p&gt;
  &lt;p id=&quot;MUJ2&quot;&gt;Что же делать?&lt;/p&gt;
  &lt;p id=&quot;5ojz&quot;&gt;&lt;/p&gt;
  &lt;h2 id=&quot;1Aak&quot;&gt;Curve AMM&lt;/h2&gt;
  &lt;p id=&quot;zGl8&quot;&gt;Curve решил это проблему, создав пул, который объединяет в себе прелести двух подходов, которые мы рассмотрели ранее.&lt;/p&gt;
  &lt;p id=&quot;Shti&quot;&gt;Как же у них это получилось?&lt;/p&gt;
  &lt;p id=&quot;Oc6j&quot;&gt;Основная задача состояла в том, чтобы создать пул, который будет иметь вид &lt;strong&gt;X+Y=C&lt;/strong&gt;, когда цена будет находиться в районе &lt;strong&gt;1$&lt;/strong&gt;, и принимать вид &lt;strong&gt;X*Y=C&lt;/strong&gt;, когда цена будет сильно отклоняться&lt;/p&gt;
  &lt;figure id=&quot;02zQ&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img4.teletype.in/files/7b/e0/7be01d81-d12d-412e-83d8-13fc8b39180e.png&quot; width=&quot;1920&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;ZXWg&quot;&gt;На графике видно, что цена при сильном отклонении от 1$ начинает вести себя как в пуле x*y=c&lt;/p&gt;
  &lt;p id=&quot;NBTz&quot;&gt;Чтобы получить такую кривую, нам надо сложить выражение для пула x+y=c и x*y=c&lt;/p&gt;
  &lt;p id=&quot;14P6&quot;&gt;Для этого давайте сначала запишем выражения для обоих пулов в общем виде:&lt;/p&gt;
  &lt;figure id=&quot;P0yI&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img4.teletype.in/files/ba/20/ba208f8d-04ad-4b1d-b534-795b3d9f502a.png&quot; width=&quot;1920&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;hHMG&quot;&gt;Слева для пула с линейной зависимостью, справа для пула с постоянным произведением.&lt;/p&gt;
  &lt;section style=&quot;background-color:hsl(hsl(0,   0%,  var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;p id=&quot;1MSv&quot;&gt;&lt;strong&gt;D - это суммарное количество токенов, при условии, что они имеют одинаковую цену&lt;/strong&gt;&lt;/p&gt;
    &lt;p id=&quot;GRM7&quot;&gt;&lt;u&gt;D = 10M USDT + 10M USDC = 20M (при условии, что USDT = USDC)&lt;/u&gt;&lt;/p&gt;
  &lt;/section&gt;
  &lt;p id=&quot;T7Eu&quot;&gt;Давайте теперь посмотрим, как будет выглядеть наш график, если мы построим его для пула USDC/USDT.&lt;/p&gt;
  &lt;section style=&quot;background-color:hsl(hsl(0,   0%,  var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;p id=&quot;asqf&quot;&gt;В нашем воображаемом пуле будет:&lt;/p&gt;
    &lt;p id=&quot;fky7&quot;&gt;&lt;strong&gt;1&amp;#x27;500&amp;#x27;000 USDC&lt;/strong&gt;&lt;/p&gt;
    &lt;p id=&quot;Z8ak&quot;&gt;&lt;strong&gt;1&amp;#x27;500&amp;#x27;000 USDT&lt;/strong&gt;&lt;/p&gt;
  &lt;/section&gt;
  &lt;figure id=&quot;Cw4V&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img4.teletype.in/files/f3/2a/f32a4352-f20a-40b6-97d8-6f989364bade.png&quot; width=&quot;1920&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;llqf&quot;&gt;Давайте теперь построим график нашего выражения.&lt;br /&gt;Вот так он будет выглядеть:&lt;/p&gt;
  &lt;figure id=&quot;S5xA&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img1.teletype.in/files/45/37/4537844e-4ba0-4c92-8448-dbf461a788d9.png&quot; width=&quot;1920&quot; /&gt;
    &lt;figcaption&gt;https://www.desmos.com/calculator/ripcngywnj&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;ognx&quot;&gt;На графике видно, что x+y+x*y несильно отличается от Uniswap AMM, чтобы исправить ситуацию нам нужно, сделать его &lt;u&gt;более &amp;quot;плоским&amp;quot; в зоне, где я обвел черненьким.&lt;/u&gt;&lt;/p&gt;
  &lt;p id=&quot;c65k&quot;&gt;Давайте умножим выражение для пула без проскальзывания на какое-то число (chi) и посмотри, что произойдет.&lt;/p&gt;
  &lt;figure id=&quot;cRle&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img3.teletype.in/files/ed/38/ed38935c-5f67-4196-8706-7b75b7696ad0.png&quot; width=&quot;1920&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;WMdD&quot;&gt;Вот так теперь выглядит наше уравнение (3).&lt;br /&gt;Давайте построим график и поиграемся с ним.&lt;/p&gt;
  &lt;figure id=&quot;ZIww&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img2.teletype.in/files/d3/e0/d3e0da58-1922-4b7a-8704-befd7f4f27e5.gif&quot; width=&quot;1920&quot; /&gt;
    &lt;figcaption&gt;https://www.desmos.com/calculator/8vn3ptit9m&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;ulJf&quot;&gt;Тут я увеличиваю значение chi, и чем больше оно становиться, тем более &amp;quot;плоский&amp;quot; становиться график.&lt;/p&gt;
  &lt;p id=&quot;qJeN&quot;&gt;&lt;strong&gt;Это конечно все круто, но зачем это нужно спросите вы?&lt;/strong&gt;&lt;br /&gt;&lt;em&gt;На данный момент мы имеем кривую, которая может становиться либо &amp;quot;плоской&amp;quot; либо круглой, при изменении одного параметра.&lt;/em&gt;&lt;/p&gt;
  &lt;section style=&quot;background-color:hsl(hsl(0,   0%,  var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;p id=&quot;p4do&quot;&gt;Когда chi &lt;strong&gt;увеличивается&lt;/strong&gt;: &lt;u&gt;уменьшается&lt;/u&gt; проскальзывание и график становится похож на x+y (красный график)&lt;/p&gt;
    &lt;p id=&quot;CII2&quot;&gt;Когда chi &lt;u&gt;уменьшается&lt;/u&gt;:  &lt;strong&gt;увеличивается&lt;/strong&gt; проскальзывание и график становится похож на x*y (синий график)&lt;/p&gt;
  &lt;/section&gt;
  &lt;p id=&quot;wM0E&quot;&gt;&lt;/p&gt;
  &lt;h3 id=&quot;DK2V&quot;&gt;Как выбрать параметры?&lt;/h3&gt;
  &lt;p id=&quot;SqRq&quot;&gt;&lt;u&gt;Как же нам понять как выбрать chi?&lt;/u&gt; Поскольку мы имеем дело с обменом стейблкоинами, нам нужно, чтобы цена возвращалась к 1, когда в пуле USDT = 15M, USDC = 15M, и вела себя как в Uniswap AMM, когда соотношение токенов в пуле не сбалансировано.&lt;/p&gt;
  &lt;p id=&quot;XpSh&quot;&gt;Чтобы добиться такого эффекта, chi должно зависеть от количества токенов х и y в пуле. При &lt;u&gt;несбалансированном&lt;/u&gt; (USDT &amp;gt; USDC) количестве токенов в пуле, chi должно &lt;u&gt;уменьшаться&lt;/u&gt;, чтобы график принимал вид x*y, а при &lt;u&gt;сбалансированном&lt;/u&gt; (USDT = USDC) количестве &lt;u&gt;увеличиваться&lt;/u&gt;, чтобы график принял вид x+y.&lt;/p&gt;
  &lt;p id=&quot;ZvhZ&quot;&gt;Также важно, чтобы суммарное количество токенов не влияло на наш параметр.&lt;/p&gt;
  &lt;p id=&quot;rEtq&quot;&gt;Давайте просто умножим наше выражения для графика x+y в этот раз уже на D:&lt;/p&gt;
  &lt;figure id=&quot;r4FC&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img2.teletype.in/files/58/3f/583f5471-c53b-45cc-bf3a-1f8b4a59e7b1.png&quot; width=&quot;1920&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;0Xb4&quot;&gt;Для вычисления chi выберем следующее выражение:&lt;/p&gt;
  &lt;figure id=&quot;fHkD&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img1.teletype.in/files/c7/35/c735cea8-24f0-49ae-a42e-e814940bb4da.png&quot; width=&quot;1920&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;RkJ8&quot;&gt;Давайте подставим все, что у нас есть в одно выражение:&lt;/p&gt;
  &lt;figure id=&quot;uc0S&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img3.teletype.in/files/ec/49/ec4964f7-6a84-456c-9926-f5f71e564033.png&quot; width=&quot;1920&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;zOlL&quot;&gt;А теперь построим график и поиграем со значениями.&lt;/p&gt;
  &lt;figure id=&quot;TJtG&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img2.teletype.in/files/d2/30/d230e24c-af5c-461c-8d0e-6c15fcf07821.gif&quot; width=&quot;1920&quot; /&gt;
    &lt;figcaption&gt;https://www.desmos.com/calculator/opzbo93gss&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;5Qt5&quot;&gt;Мы можем заметить, что при изменении параметра А, график становиться плоским&lt;/p&gt;
  &lt;section style=&quot;background-color:hsl(hsl(0,   0%,  var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;p id=&quot;HoF0&quot;&gt;Значение этого параметра определяет &lt;strong&gt;Curve DAO,&lt;/strong&gt; а нам самим его можно посмотреть перейдя в пул на Curve.fi и открыв вкладку &amp;quot;Advanced&amp;quot;&lt;/p&gt;
  &lt;/section&gt;
  &lt;figure id=&quot;oXFO&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img3.teletype.in/files/28/81/2881b684-c33a-463d-b674-06828d4e9aa4.png&quot; width=&quot;1920&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;XjFe&quot;&gt;Таким образом мы получили выражение, которое позволит пользователем обменивать стейблкоины с минимальной разницей в цене aka проскальзыванием.&lt;/p&gt;
  &lt;section style=&quot;background-color:hsl(hsl(0,   0%,  var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;p id=&quot;mSCg&quot;&gt;Curve whitepaper - &lt;a href=&quot;https://docs.curve.fi/assets/pdf/stableswap-paper.pdf&quot; target=&quot;_blank&quot;&gt;https://docs.curve.fi/assets/pdf/stableswap-paper.pdf&lt;/a&gt;&lt;/p&gt;
  &lt;/section&gt;
  &lt;h2 id=&quot;3j4b&quot;&gt;Надеюсь статья была полезной&lt;/h2&gt;
  &lt;h3 id=&quot;NVg5&quot;&gt;Спасибо за прочтение!&lt;/h3&gt;
  &lt;h3 id=&quot;eEHR&quot;&gt;Мой телеграм - &lt;a href=&quot;https://t.me/chpotldev&quot; target=&quot;_blank&quot;&gt;https://t.me/chpotldev&lt;/a&gt;&lt;/h3&gt;

</content></entry><entry><id>chpotl:zkp</id><link rel="alternate" type="text/html" href="https://teletype.in/@chpotl/zkp?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=chpotl"></link><title>Zero-knowledge proof - простыми словам</title><published>2022-10-17T13:44:44.982Z</published><updated>2022-10-18T10:51:45.361Z</updated><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://img2.teletype.in/files/d7/56/d75696ab-766d-42df-b236-14e1dee36010.png"></media:thumbnail><summary type="html">&lt;img src=&quot;https://img1.teletype.in/files/85/d0/85d0cf84-a998-4c69-809a-6060b17b0173.jpeg&quot;&gt;Всем привет!</summary><content type="html">
  &lt;figure id=&quot;9BFD&quot; class=&quot;m_retina&quot;&gt;
    &lt;img src=&quot;https://img1.teletype.in/files/85/d0/85d0cf84-a998-4c69-809a-6060b17b0173.jpeg&quot; width=&quot;960&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;zHm6&quot;&gt;Всем привет!&lt;/p&gt;
  &lt;p id=&quot;Vd9u&quot;&gt;В этой статье я простым языком расскажу про zero-knowledge proof (ZKP)&lt;/p&gt;
  &lt;p id=&quot;2eY9&quot;&gt;Это продолжение серии статей на пути к ZK-SNARKs и более сложным криптографическим штукам&lt;/p&gt;
  &lt;h2 id=&quot;2ynW&quot;&gt;TL;DR&lt;/h2&gt;
  &lt;p id=&quot;ERv4&quot;&gt;Сейчас из каждого утюга говорят про ZKP. Появляются какие-то &amp;quot;zk rollup-ы&amp;quot;,  и у меня такое ощущение, что если ты дописываешь к названию технологии &amp;quot;zk&amp;quot;, то можешь поднять любые раунды и встать на ступень выше этих одноклеточных &amp;quot;не zk&amp;quot; проектов. Если говорить серьезно, то данный механизм/протокол на самом деле решает много проблем с приватностью данных и все больше приближает нас к настоящей децентрализации (привет CZ) и анонимности&lt;/p&gt;
  &lt;p id=&quot;M0QR&quot;&gt;&lt;/p&gt;
  &lt;h2 id=&quot;JuLI&quot;&gt;Что такое zero-knowledge proof?&lt;/h2&gt;
  &lt;p id=&quot;jNpO&quot;&gt;Zero-knowledge proof или zero-knowledge protocol - это метод, с помощью которого &lt;strong&gt;П&lt;/strong&gt;етя (the &lt;strong&gt;p&lt;/strong&gt;rover) может доказать &lt;strong&gt;В&lt;/strong&gt;асе (the &lt;strong&gt;v&lt;/strong&gt;erifier), что он знает какую-то информацию &lt;strong&gt;X&lt;/strong&gt;, не раскрывая никакую информацию об этом &lt;strong&gt;X&lt;/strong&gt;&lt;/p&gt;
  &lt;p id=&quot;zm98&quot;&gt;Другими словами, я могу доказать преподавателю, что сделал домашнее задание, не принося его&lt;/p&gt;
  &lt;h3 id=&quot;GTGA&quot;&gt;&lt;strong&gt;ZKP должен удовлетворять трем условиям:&lt;/strong&gt;&lt;/h3&gt;
  &lt;ul id=&quot;yqWu&quot;&gt;
    &lt;li id=&quot;YXbL&quot;&gt;&lt;strong&gt;Completeness&lt;/strong&gt; (полнота) - если утверждение истинно, то порядочный проверяющий aka &amp;quot;Вася the verifier&amp;quot; - тот, кто честно следует правилам протокола будет убежден в этом факте порядочным проверяющим&lt;/li&gt;
    &lt;li id=&quot;DGTr&quot;&gt;&lt;strong&gt;Soundness &lt;/strong&gt;(надежность) - если утверждение ложно, то нечестный доказывающий aka &amp;quot;Петя the prover&amp;quot; не сможет убедить честного проверяющего в том, что оно истинно, &lt;u&gt;за исключением некоторых случаев возможных с очень малой вероятностью&lt;/u&gt;&lt;/li&gt;
    &lt;li id=&quot;k3LA&quot;&gt;&lt;strong&gt;Zero knowledge &lt;/strong&gt;(нулевое знание) - если утверждение истинно, то проверяющий aka &amp;quot;Вася the verifier&amp;quot; ничего не узнает, кроме того факта, что утверждение истинно&lt;/li&gt;
  &lt;/ul&gt;
  &lt;p id=&quot;gQW0&quot;&gt;Доказательство с нулевым знанием - это не совсем доказательство, в том смысле, что вывод о правильности информации &lt;strong&gt;X&lt;/strong&gt; делается на основании факта, что вероятность обмана Пети (the prover) настолько мала, что суждение на 99,9999999999% верно&lt;/p&gt;
  &lt;p id=&quot;AS73&quot;&gt;Возможно не совсем понятно, давайте рассмотрим пример с пещерой Али бабы&lt;/p&gt;
  &lt;p id=&quot;6McC&quot;&gt;&lt;/p&gt;
  &lt;h2 id=&quot;NMhc&quot;&gt;Пример с пещерой&lt;/h2&gt;
  &lt;p id=&quot;C4IC&quot;&gt;Представим ситуацию, у нас есть Петя (the prover), Вася (the verifier) и есть пещера, в которой есть дверь&lt;/p&gt;
  &lt;p id=&quot;AvM5&quot;&gt;Пете нужно доказать, что он знает код от двери в этой пещере, не говоря самого кода Васе&lt;/p&gt;
  &lt;p id=&quot;dRPr&quot;&gt;Для простоты восприятия&lt;/p&gt;
  &lt;p id=&quot;MWzh&quot;&gt;&lt;strong&gt;П&lt;/strong&gt;етя = &lt;strong&gt;P&lt;/strong&gt;rover&lt;/p&gt;
  &lt;p id=&quot;fW0P&quot;&gt;&lt;strong&gt;В&lt;/strong&gt;ася = &lt;strong&gt;V&lt;/strong&gt;erifier&lt;/p&gt;
  &lt;figure id=&quot;EZNO&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img1.teletype.in/files/0f/df/0fdfa9aa-020b-45ec-a265-f9a7d40d1df0.png&quot; width=&quot;1920&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;SdVa&quot;&gt;Петя первый заходит в пещеру и идет по одному из маршрутов к двери с кодом&lt;/p&gt;
  &lt;figure id=&quot;ZVI0&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img2.teletype.in/files/dd/ad/ddad18db-da3b-482c-8996-a4c703603d46.png&quot; width=&quot;1920&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;64cq&quot;&gt;Теперь Вася заходит в пещеру и просит Петю выйти со стороны B&lt;/p&gt;
  &lt;figure id=&quot;pIOG&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img4.teletype.in/files/b2/73/b2739ad8-96c3-4813-ad37-bd062ad01c6a.png&quot; width=&quot;1920&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;97EP&quot;&gt;Представим случай, что Петя на самом деле не знает код от двери, а пытается обмануть. С вероятностью 50% или 1/2 ему могло повезти, и он случайно выбрал сторону В, и когда Вася попросил его выйти со стороны B, то ему не пришлось проходить через дверь&lt;/p&gt;
  &lt;p id=&quot;Klm1&quot;&gt;Давайте проведем этот эксперимент 30 раз&lt;/p&gt;
  &lt;p id=&quot;XOTw&quot;&gt;Шанс, что Петя угадал каждый раз (1/2)^30 = 0.000000000931 &lt;a href=&quot;#DGTr&quot;&gt;(тут про это и сказано)&lt;/a&gt;&lt;/p&gt;
  &lt;p id=&quot;qxma&quot;&gt;для сравнения шанс разбиться на самолете = 0.000000125&lt;/p&gt;
  &lt;p id=&quot;Jf1l&quot;&gt;И только в случае, если Петя знает код от двери, он сможет безошибочно 30 раз выйти с нужной стороны и доказать Васе, что он знает код&lt;/p&gt;
  &lt;p id=&quot;QSYn&quot;&gt;&lt;/p&gt;
  &lt;h2 id=&quot;p82o&quot;&gt;Пример из Рика и Морти (спойлеры)&lt;/h2&gt;
  &lt;p id=&quot;1Xnj&quot;&gt;Рекомендую ознакомиться с этой серией, если уже смотрели, то момент который я привожу в пример начинается с 4:40&lt;/p&gt;
  &lt;p id=&quot;o3QX&quot;&gt;&lt;a href=&quot;https://rick-i-morty.online/episodes/6sez-5seriya/&quot; target=&quot;_blank&quot;&gt;https://rick-i-morty.online/episodes/6sez-5seriya/&lt;/a&gt;&lt;/p&gt;
  &lt;p id=&quot;5bzo&quot;&gt;Для тех кому лень смотреть, расскажу вкратце сюжет&lt;/p&gt;
  &lt;p id=&quot;yPeI&quot;&gt;Джерри (желтая футболка) ест печенье с предсказанием, где написано, что он займется сексом со своей мамой. Рик (синие волосы) не верит этому и решает проверить&lt;/p&gt;
  &lt;p id=&quot;33VK&quot;&gt;Рик кладет в одну коробку бумажку с именем мамы Джерри, перемешивает и просит Джерри сказать, куда бы он засунул свой пэнисс&lt;/p&gt;
  &lt;p id=&quot;oS30&quot;&gt;Каждый раз, когда Джерри отворачивается, Рик меняет коробки местами &lt;/p&gt;
  &lt;figure id=&quot;ePWV&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img3.teletype.in/files/e6/2f/e62fc2ef-f17b-4f9d-bcc2-b2394c90d5fb.png&quot; width=&quot;2880&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;ORC9&quot;&gt;Это по сути та же задачка с пещерой&lt;/p&gt;
  &lt;p id=&quot;CUO7&quot;&gt;Шанс, что Джерри угадает коробку с каждым разом становиться все меньше, тем самым Рик доказывает, что предсказание было настоящим&lt;/p&gt;
  &lt;p id=&quot;obCi&quot;&gt;&lt;/p&gt;
  &lt;h2 id=&quot;3j4b&quot;&gt;Надеюсь статья была полезной&lt;/h2&gt;
  &lt;h3 id=&quot;NVg5&quot;&gt;Спасибо за прочтение&lt;/h3&gt;
  &lt;h3 id=&quot;eEHR&quot;&gt;Мой телеграм - &lt;a href=&quot;https://t.me/chpotldev&quot; target=&quot;_blank&quot;&gt;https://t.me/chpotldev&lt;/a&gt;&lt;/h3&gt;

</content></entry><entry><id>chpotl:RSA-encryption</id><link rel="alternate" type="text/html" href="https://teletype.in/@chpotl/RSA-encryption?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=chpotl"></link><title>RSA шифрование</title><published>2022-08-27T10:21:55.846Z</published><updated>2022-08-27T10:36:02.758Z</updated><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://img4.teletype.in/files/31/d9/31d997f8-9bf5-4e61-adef-8ea814cc9752.png"></media:thumbnail><summary type="html">&lt;img src=&quot;https://img3.teletype.in/files/ae/ba/aeba8054-d043-49c2-899f-ca83d44d3f82.jpeg&quot;&gt;Всем привет!</summary><content type="html">
  &lt;figure id=&quot;sdMr&quot; class=&quot;m_retina&quot;&gt;
    &lt;img src=&quot;https://img3.teletype.in/files/ae/ba/aeba8054-d043-49c2-899f-ca83d44d3f82.jpeg&quot; width=&quot;960&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;yD6b&quot;&gt;Всем привет!&lt;/p&gt;
  &lt;p id=&quot;2sIw&quot;&gt;В этой статье я старался рассказать максимально простым языком про то, как устроено RSA шифрование&lt;/p&gt;
  &lt;p id=&quot;5p7p&quot;&gt;Хочу сделать серию статей, чтобы плавно подойти к тому, как работают ZK-SNARK штуки&lt;/p&gt;
  &lt;section style=&quot;background-color:hsl(hsl(236, 74%, var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;p id=&quot;3ZhN&quot;&gt;Ссылка на гитхаб с исходным кодом будет в конце статьи&lt;/p&gt;
    &lt;p id=&quot;I0AK&quot;&gt;Я буду делать все на js&lt;/p&gt;
  &lt;/section&gt;
  &lt;p id=&quot;Bmx5&quot;&gt;&lt;/p&gt;
  &lt;h3 id=&quot;1d9Y&quot;&gt;Почему симметричное шифрование = неудобно?&lt;/h3&gt;
  &lt;p id=&quot;sNBj&quot;&gt;Существует два вида шифрования: симметричное и ассиметричное&lt;/p&gt;
  &lt;p id=&quot;waon&quot;&gt;Приведу простой пример симметричного шифрования&lt;/p&gt;
  &lt;p id=&quot;U1ag&quot;&gt;Есть такая штука, называется шифр цезаря (любители генопетс оценят)&lt;/p&gt;
  &lt;p id=&quot;fYWq&quot;&gt;Чтобы зашифровать сообщение, мы берем слово, в моем случае это будет слово &amp;quot;дверь&amp;quot;, какое-то число не больше размера алфавита (например 2), и заменяем каждую букву на ту, которая находится на 2 буквы дальше&lt;/p&gt;
  &lt;p id=&quot;V722&quot;&gt;д-&amp;gt;ё&lt;/p&gt;
  &lt;p id=&quot;AIfR&quot;&gt;в-&amp;gt;д&lt;/p&gt;
  &lt;p id=&quot;YwT2&quot;&gt;е-&amp;gt;ж&lt;/p&gt;
  &lt;p id=&quot;OEqI&quot;&gt;р-&amp;gt;т&lt;/p&gt;
  &lt;p id=&quot;VAzy&quot;&gt;ь-&amp;gt;ю&lt;/p&gt;
  &lt;p id=&quot;uKJV&quot;&gt;Получаем &amp;quot;ёджтю&amp;quot; &lt;/p&gt;
  &lt;p id=&quot;UlKd&quot;&gt;Теперь отправляем нашему другу это сообщение, а при встрече говорим, что число на которое надо сдвигать - это 2, он получает сообщение, и расшифровывает, зная размер сдвига&lt;/p&gt;
  &lt;h3 id=&quot;baja&quot;&gt;НО!&lt;/h3&gt;
  &lt;p id=&quot;43Bc&quot;&gt;Представим ситуацию, что у нас 8531 друг, и каждый сейчас в другой стране&lt;/p&gt;
  &lt;p id=&quot;zNHT&quot;&gt;Возникнут некоторые проблемы&lt;/p&gt;
  &lt;p id=&quot;Xu7h&quot;&gt;&lt;/p&gt;
  &lt;h3 id=&quot;zM0g&quot;&gt;Почему асимметричное шифрование = круто?&lt;/h3&gt;
  &lt;p id=&quot;I0RL&quot;&gt;Объясню пример этого метода на картинках&lt;/p&gt;
  &lt;p id=&quot;Dlcn&quot;&gt;Представим, что у нас есть замок и ключ от него, а у нашего друга есть сообщение которое он хочет передать, мы &amp;quot;открываем&amp;quot; наш замок, ключом, которые есть только у нас&lt;/p&gt;
  &lt;figure id=&quot;W7SB&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img1.teletype.in/files/4b/8b/4b8b6881-d7d8-4556-bdac-716f421c9058.png&quot; width=&quot;1920&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;7dKA&quot;&gt;Отправляем открытый замок нашему другу СДЭКом или любым другим способом&lt;/p&gt;
  &lt;figure id=&quot;xV98&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img2.teletype.in/files/5f/01/5f01c5bc-710d-41ee-9f1e-96c7dcf43e26.png&quot; width=&quot;1920&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;3t6X&quot;&gt;Наш друг получает это замок, прикрепляет к нему свою бумажку с сообщением, закрывает замок и отправляет с бумажкой обратно по почте&lt;/p&gt;
  &lt;figure id=&quot;rKjW&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img1.teletype.in/files/8b/f0/8bf065d6-b925-415d-86be-0a499c36a40e.png&quot; width=&quot;1920&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;IfEl&quot;&gt;Мы получаем сообщение с замком и ключом, который есть только у нас, открываем его и видим сообщение&lt;/p&gt;
  &lt;figure id=&quot;Uxlh&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img1.teletype.in/files/4d/0a/4d0aec5f-7752-4c23-a4ca-f8eab2b1a88e.png&quot; width=&quot;1920&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;4NmO&quot;&gt;Победа! Теперь нам не нужно встречаться с каждым другом, чтобы передать сообщение&lt;/p&gt;
  &lt;p id=&quot;U0WD&quot;&gt;&lt;/p&gt;
  &lt;h2 id=&quot;FZCI&quot; data-align=&quot;center&quot;&gt;RSA&lt;/h2&gt;
  &lt;p id=&quot;Ojxs&quot;&gt;Алгоритм шифрования RSA основан на 2 вещах:&lt;/p&gt;
  &lt;ol id=&quot;BXDA&quot;&gt;
    &lt;li id=&quot;auBg&quot;&gt;Произведение двух простых чисел делается просто. Умножить на калькуляторе 5569 и 821 займет меньше 5 секунд, а понять, на какие простые множители раскладывается число, сложно. Какие числа перемножили, чтобы получить 467149?&lt;/li&gt;
    &lt;li id=&quot;8GMo&quot;&gt;ОЧЕНЬ большие числа длинной 1024 бита. Если кто-то захочет подобрать значения, то уйдут десятки лет&lt;/li&gt;
  &lt;/ol&gt;
  &lt;p id=&quot;hus4&quot;&gt;&lt;/p&gt;
  &lt;h3 id=&quot;5TZq&quot;&gt;Принцип работы RSA на пальцах&lt;/h3&gt;
  &lt;p id=&quot;RiRj&quot;&gt;&lt;u&gt;шаг 1.&lt;/u&gt; Случайно генерируем два простых числа &lt;code&gt;prime1&lt;/code&gt; и &lt;code&gt;prime2&lt;/code&gt;&lt;/p&gt;
  &lt;p id=&quot;JLSz&quot;&gt;&lt;u&gt;шаг 2.&lt;/u&gt; Вычисляем &lt;code&gt;const n = prime1 * prime2;&lt;/code&gt; &lt;/p&gt;
  &lt;p id=&quot;0vnF&quot;&gt;и &lt;strong&gt;&lt;em&gt;ϕ &lt;/em&gt;&lt;/strong&gt;&lt;code&gt;const phiN = (prime1 - 1) * (prime2 - 1);&lt;/code&gt;&lt;/p&gt;
  &lt;p id=&quot;kYrp&quot;&gt;&lt;a href=&quot;https://cp-algorithms.com/algebra/phi-function.html#properties&quot; target=&quot;_blank&quot;&gt;ТУТ&lt;/a&gt; можно почитать, что за функция &lt;strong&gt;&lt;em&gt;ϕ&lt;/em&gt;&lt;/strong&gt;, и почему &lt;strong&gt;&lt;em&gt;ϕ&lt;/em&gt;&lt;/strong&gt;(ab)=&lt;strong&gt;&lt;em&gt;ϕ&lt;/em&gt;&lt;/strong&gt;(a)*&lt;strong&gt;&lt;em&gt;ϕ&lt;/em&gt;&lt;/strong&gt;(b), но в самом алгоритме это несильно важно&lt;/p&gt;
  &lt;p id=&quot;MiiN&quot;&gt;&lt;u&gt;шаг 3.&lt;/u&gt; Выбираем значение &lt;strong&gt;encyptionKey&lt;/strong&gt; такое, чтобы оно было меньше &lt;strong&gt;phiN&lt;/strong&gt;и было взаимно простое c &lt;strong&gt;phiN&lt;/strong&gt; &lt;code&gt;НОД(encyptionKey, phiN)==1&lt;/code&gt; - его мы будем использовать для шифрования сообщения&lt;/p&gt;
  &lt;p id=&quot;PEuG&quot;&gt;&lt;u&gt;шаг 4.&lt;/u&gt; Вычисляем значение &lt;strong&gt;decryptionKey&lt;/strong&gt; - его мы будем использовать для расшифровки сообщения (дальше объясню как его считать)&lt;/p&gt;
  &lt;section style=&quot;background-color:hsl(hsl(170, 33%, var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;p id=&quot;3L66&quot;&gt;&lt;strong&gt;decryptionKey &lt;/strong&gt;- он лежит у нас, его никто не знает &lt;/p&gt;
    &lt;p id=&quot;AAEG&quot;&gt;&lt;strong&gt;encyptionKey &lt;/strong&gt;- его мы передаем другому пользователю&lt;/p&gt;
  &lt;/section&gt;
  &lt;h3 id=&quot;yLiC&quot;&gt;Все! Больше ничего не нужно, теперь шифруем&lt;/h3&gt;
  &lt;p id=&quot;ZVxz&quot;&gt;&lt;u&gt;USER 1 (он хочет получить сообщение).&lt;/u&gt; Передает USER 2 &lt;strong&gt;n&lt;/strong&gt; (шаг 2) и &lt;strong&gt;encyptionKey&lt;/strong&gt; (шаг 3)&lt;/p&gt;
  &lt;p id=&quot;Esof&quot;&gt;&lt;u&gt;USER 2 (он хочет отправить сообщение).&lt;/u&gt; Получает &lt;strong&gt;n&lt;/strong&gt; и  &lt;strong&gt;encyptionKey&lt;/strong&gt; от USER 1, берет свое сообщение &lt;strong&gt;m&lt;/strong&gt; (делаем из текста число, &lt;a href=&quot;https://www.di-mgt.com.au/rsa_alg.html#pkcs1schemes&quot; target=&quot;_blank&quot;&gt;ТУТ&lt;/a&gt; написано, как это делается, я использую упрощенный пример &lt;strong&gt;m = 5&lt;/strong&gt;) &lt;/p&gt;
  &lt;p id=&quot;iZLn&quot;&gt;и считает &lt;strong&gt;encryptedMessage = m^(encyptionKey) &lt;a href=&quot;https://ru.wikipedia.org/wiki/%D0%94%D0%B5%D0%BB%D0%B5%D0%BD%D0%B8%D0%B5_%D1%81_%D0%BE%D1%81%D1%82%D0%B0%D1%82%D0%BA%D0%BE%D0%BC&quot; target=&quot;_blank&quot;&gt;mod&lt;/a&gt; n &lt;/strong&gt;&lt;/p&gt;
  &lt;p id=&quot;hj5U&quot;&gt;далее предает &lt;strong&gt;encryptedMessage &lt;/strong&gt;USER 1&lt;/p&gt;
  &lt;p id=&quot;k8WW&quot;&gt;&lt;u&gt;USER 1.&lt;/u&gt; Получает &lt;strong&gt;encryptedMessage &lt;/strong&gt;возводит в степень&lt;strong&gt; decryptionKey&lt;/strong&gt; и берет остаток от деления на&lt;strong&gt; n&lt;/strong&gt;&lt;/p&gt;
  &lt;p id=&quot;Xmkm&quot;&gt;другими словами &lt;strong&gt;decryptedMessage&lt;/strong&gt; = &lt;strong&gt;encryptedMessage^decryptionKey mod n&lt;/strong&gt;&lt;/p&gt;
  &lt;p id=&quot;r15z&quot;&gt;Победа! &lt;strong&gt;decryptedMessage&lt;/strong&gt; будет равно сообщению, которое мы передали&lt;/p&gt;
  &lt;p id=&quot;dHKa&quot;&gt;&lt;/p&gt;
  &lt;h3 id=&quot;3sY2&quot;&gt;Проще всего будет понят суть алгоритма на примере кода&lt;/h3&gt;
  &lt;p id=&quot;5uK5&quot;&gt;Сначала зададим функцию, чтобы проверять простое число или нет. Тут интересный момент, что цикл идет от 2 до &lt;code&gt;sqrt(num)&lt;/code&gt;, почему это работает написано &lt;a href=&quot;https://ru.stackoverflow.com/questions/997034/%D0%9F%D0%BE%D1%87%D0%B5%D0%BC%D1%83-%D0%BF%D1%80%D0%B8-%D0%BF%D1%80%D0%BE%D0%B2%D0%B5%D1%80%D0%BA%D0%B5-%D0%BD%D0%B0-%D0%BF%D1%80%D0%BE%D1%81%D1%82%D0%BE%D1%82%D1%83-%D0%BF%D0%B5%D1%80%D0%B5%D0%B1%D0%B8%D1%80%D0%B0%D1%8E%D1%82-%D0%B7%D0%BD%D0%B0%D1%87%D0%B5%D0%BD%D0%B8%D1%8F-%D1%82%D0%BE%D0%BB%D1%8C%D0%BA%D0%BE-%D0%B4%D0%BE-%D0%BA%D0%B2%D0%B0%D0%B4%D1%80%D0%B0%D1%82%D0%BD%D0%BE%D0%B3%D0%BE-%D0%BA%D0%BE%D1%80%D0%BD%D1%8F&quot; target=&quot;_blank&quot;&gt;ТУТ&lt;/a&gt;&lt;/p&gt;
  &lt;pre id=&quot;mBst&quot; data-lang=&quot;javascript&quot;&gt;function isPrime(num) {
  for (let j = 2, n = Math.sqrt(num); j &amp;lt;= n; j++) {
    if (num % j === 0) {
      return false;
    }
  }
  return num;
}&lt;/pre&gt;
  &lt;p id=&quot;KDtM&quot;&gt;Далее я создаю функцию чтобы, находить случайные простые числа определенной длинны, и путем умножения создаю переменную &lt;code&gt;n&lt;/code&gt;, мы будем дальше ее использовать, когда будем хранить, публичный и приватный ключ&lt;/p&gt;
  &lt;pre id=&quot;a7Jt&quot; data-lang=&quot;javascript&quot;&gt;const k = 3;
const prime1 = getPrime(k);
const prime2 = getPrime(k);
const n = prime1 * prime2;&lt;/pre&gt;
  &lt;p id=&quot;ilGN&quot;&gt;Создадим переменную &lt;strong&gt;phiN&lt;/strong&gt; и &lt;strong&gt;encyptionKey&lt;/strong&gt;(взаимно простое с &lt;strong&gt;phiN&lt;/strong&gt; и &lt;strong&gt;n&lt;/strong&gt;)&lt;/p&gt;
  &lt;pre id=&quot;sx5f&quot; data-lang=&quot;javascript&quot;&gt;const phiN = (prime1 - 1) * (prime2 - 1);
const encyptionKey = getEncryptionKey(phiN, n);&lt;/pre&gt;
  &lt;pre id=&quot;DKQV&quot; data-lang=&quot;javascript&quot;&gt;function getEncryptionKey(phiN, N) {
  for (let i = 2; i &amp;lt; phiN; i++) {
    if (gcd(i, phiN) === 1 &amp;amp;&amp;amp; gcd(i, N) === 1) {
      return i;
    }
  }
}&lt;/pre&gt;
  &lt;p id=&quot;kfE3&quot;&gt;Тут я использую функцию &lt;code&gt;gcd&lt;/code&gt; или Наибольший Общий Делитель по-русски&lt;/p&gt;
  &lt;p id=&quot;NxIb&quot;&gt;Существует алгоритм Евклида для поиска НОД, мы вычитаем из наибольшего числа наименьшее, пока одно из них не станет нулем, значит второе - это НОД&lt;/p&gt;
  &lt;figure id=&quot;u901&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img2.teletype.in/files/56/fa/56faf614-eba1-4729-83e4-070729045953.png&quot; width=&quot;1920&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;U4ar&quot;&gt;Чтобы ускорить процесс мы можем не вычитать, а брать остатки от деления&lt;/p&gt;
  &lt;figure id=&quot;zgpT&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img4.teletype.in/files/f5/24/f524eab8-4242-48a0-b70c-b533ea92912b.png&quot; width=&quot;1920&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;GUP2&quot;&gt;В JS это выглядит так:&lt;/p&gt;
  &lt;pre id=&quot;ROkL&quot; data-lang=&quot;javascript&quot;&gt;function gcd(a, b) {
  if (a == 0) return b;
  return gcd(b % a, a);
}&lt;/pre&gt;
  &lt;p id=&quot;CHQv&quot;&gt;Теперь давайте разберемся, как нам найти &lt;strong&gt;decriptionKey&lt;/strong&gt;, чтобы расшифровать сообщение, которое мы потом получим&lt;/p&gt;
  &lt;p id=&quot;zkvD&quot;&gt;Нам нужно найти такое значение &lt;strong&gt;d(decriptionKey)&lt;/strong&gt;, что при умножении на &lt;strong&gt;e(encryptionKey)&lt;/strong&gt; и получения остатка от деления на &lt;strong&gt;&lt;em&gt;ϕ&lt;/em&gt;(phiN)&lt;/strong&gt; получится 1&lt;/p&gt;
  &lt;figure id=&quot;vfD9&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img1.teletype.in/files/0d/ec/0dec6d40-4757-4f29-8c9d-fec975d203df.png&quot; width=&quot;1920&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;n5b7&quot;&gt;Это можно сделать перебором, но если числа большие, то процессору будет больно, поэтому используем &lt;u&gt;расширенный алгоритм Евклида&lt;/u&gt; &lt;a href=&quot;https://www.youtube.com/watch?v=YZfPcvbwwvI&amp;t=329s&quot; target=&quot;_blank&quot;&gt;ТУТ&lt;/a&gt; про то, как он работает, а &lt;a href=&quot;https://www.di-mgt.com.au/euclidean.html#extendedeuclidean&quot; target=&quot;_blank&quot;&gt;ТУТ&lt;/a&gt; про реализацию, которая работает, потому что важно, чтобы функция не выдавала отрицательные числа, иначе ничего не получится&lt;/p&gt;
  &lt;p id=&quot;bWYD&quot;&gt;Вот код на JS:&lt;/p&gt;
  &lt;pre id=&quot;8rDy&quot; data-lang=&quot;javascript&quot;&gt;const decryptionKey = modInv(encyptionKey, phiN);&lt;/pre&gt;
  &lt;pre id=&quot;PlMF&quot; data-lang=&quot;javascript&quot;&gt;function modInv(u, v) {
  let u1 = 1;
  let u3 = u;
  let v1 = 0;
  let v3 = v;
  let iter = 1;
  while (v3 != 0) {
    q = Math.floor(u3 / v3);
    t3 = u3 % v3;
    t1 = u1 + q * v1;
    u1 = v1;
    v1 = t1;
    u3 = v3;
    v3 = t3;
    iter--;
  }
  if (u3 != 1) {
    return 0;
  }
  if (iter &amp;lt; 0) {
    inv = v - u1;
  } else {
    inv = u1;
  }
  return inv;
}&lt;/pre&gt;
  &lt;p id=&quot;xGAQ&quot;&gt;Теперь у нас есть &lt;strong&gt;encryptionKey&lt;/strong&gt;, &lt;strong&gt;decryptionKey&lt;/strong&gt; и &lt;strong&gt;n&lt;/strong&gt;&lt;/p&gt;
  &lt;p id=&quot;V0ve&quot;&gt;Отправляем второму пользователю &lt;strong&gt;encryptionKey &lt;/strong&gt;и&lt;strong&gt; n&lt;/strong&gt;&lt;/p&gt;
  &lt;p id=&quot;Ksqz&quot;&gt;Он берет сообщение &lt;strong&gt;m&lt;/strong&gt;(5) возводит в степень &lt;strong&gt;encryptionKey &lt;/strong&gt;и берет остаток от деления на&lt;strong&gt; n&lt;/strong&gt;&lt;/p&gt;
  &lt;p id=&quot;10aF&quot;&gt;Я использовал ethers.js чтобы работать с &lt;a href=&quot;https://docs.ethers.io/v5/api/utils/bignumber/&quot; target=&quot;_blank&quot;&gt;BigNumber&lt;/a&gt;&lt;/p&gt;
  &lt;pre id=&quot;u8yM&quot; data-lang=&quot;javascript&quot;&gt;const m = 5; //less than n-1
const encryptedMessage = BigNumber.from(m).pow(encyptionKey).mod(n);&lt;/pre&gt;
  &lt;p id=&quot;8GYd&quot;&gt;И отправляет &lt;strong&gt;encryptedMessage&lt;/strong&gt; обратно нам&lt;/p&gt;
  &lt;p id=&quot;R53j&quot;&gt;а мы берем его сообщение и делам почти тоже самое: возводим в степень &lt;strong&gt;decryptionKey &lt;/strong&gt;и берем остаток от деления на &lt;strong&gt;n&lt;/strong&gt;&lt;/p&gt;
  &lt;pre id=&quot;mcxh&quot; data-lang=&quot;javascript&quot;&gt;const decryptedMessage = encryptedMessage.pow(decryptionKey).mod(n);&lt;/pre&gt;
  &lt;p id=&quot;AxjN&quot;&gt;Ура! Мы расшифровали сообщение и получили 5&lt;/p&gt;
  &lt;p id=&quot;vGZb&quot;&gt;&lt;/p&gt;
  &lt;section style=&quot;background-color:hsl(hsl(170, 33%, var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;p id=&quot;UyiT&quot;&gt;&lt;strong&gt;Как и обещал, вот ссылка на гитхаб&lt;/strong&gt;&lt;/p&gt;
    &lt;p id=&quot;6rLT&quot;&gt;&lt;a href=&quot;https://github.com/chpotl/RSAencryption&quot; target=&quot;_blank&quot;&gt;https://github.com/chpotl/RSAencryption&lt;/a&gt;&lt;/p&gt;
    &lt;p id=&quot;AShD&quot;&gt;Тут все про алгоритмы Евклида&lt;/p&gt;
    &lt;p id=&quot;cdKw&quot;&gt;&lt;a href=&quot;https://www.di-mgt.com.au/euclidean.html#extendedeuclidean&quot; target=&quot;_blank&quot;&gt;https://www.di-mgt.com.au/euclidean.html#extendedeuclidean&lt;/a&gt;&lt;/p&gt;
    &lt;p id=&quot;xq6m&quot;&gt;Тут про то, почему RSA работает &lt;/p&gt;
    &lt;p id=&quot;Af8C&quot;&gt;&lt;a href=&quot;https://www.youtube.com/watch?v=wXB-V_Keiu8&quot; target=&quot;_blank&quot;&gt;https://www.youtube.com/watch?v=wXB-V_Keiu8&lt;/a&gt; &lt;/p&gt;
    &lt;p id=&quot;IuRU&quot;&gt;Тут про то, как RSA работает &lt;/p&gt;
    &lt;p id=&quot;0Gb2&quot;&gt;&lt;a href=&quot;https://www.di-mgt.com.au/rsa_alg.html#note4&quot; target=&quot;_blank&quot;&gt;https://www.di-mgt.com.au/rsa_alg.html#note4&lt;/a&gt;&lt;/p&gt;
    &lt;p id=&quot;sfsk&quot;&gt;Тут про функцию Ейлера (&lt;em&gt;ϕ)&lt;/em&gt;&lt;/p&gt;
    &lt;p id=&quot;DBO1&quot;&gt;&lt;a href=&quot;https://cp-algorithms.com/algebra/phi-function.html&quot; target=&quot;_blank&quot;&gt;https://cp-algorithms.com/algebra/phi-function.html&lt;/a&gt;&lt;/p&gt;
  &lt;/section&gt;
  &lt;h2 id=&quot;3j4b&quot;&gt;Надеюсь статья была полезной&lt;/h2&gt;
  &lt;h3 id=&quot;NVg5&quot;&gt;Спасибо за прочтение&lt;/h3&gt;
  &lt;h3 id=&quot;eEHR&quot;&gt;Мой телеграм - &lt;a href=&quot;https://t.me/chpotldev&quot; target=&quot;_blank&quot;&gt;https://t.me/chpotldev&lt;/a&gt;&lt;/h3&gt;

</content></entry><entry><id>chpotl:fastBalance</id><link rel="alternate" type="text/html" href="https://teletype.in/@chpotl/fastBalance?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=chpotl"></link><title>Быстрые запросы баланса кошелька</title><published>2022-07-30T17:59:58.571Z</published><updated>2022-07-30T18:21:51.059Z</updated><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://img3.teletype.in/files/e8/9d/e89d017e-d140-4a73-b36f-71141ccae8c8.png"></media:thumbnail><summary type="html">&lt;img src=&quot;https://img3.teletype.in/files/a3/3b/a33bdb8c-aec7-4ac3-a1d4-4fa2a295622c.jpeg&quot;&gt;В этой статье я расскажу, как узнать баланс кошелька пользователя, почему перебор не работает, и почему 1inch умнички???</summary><content type="html">
  &lt;figure id=&quot;9KQw&quot; class=&quot;m_retina&quot;&gt;
    &lt;img src=&quot;https://img3.teletype.in/files/a3/3b/a33bdb8c-aec7-4ac3-a1d4-4fa2a295622c.jpeg&quot; width=&quot;960&quot; /&gt;
  &lt;/figure&gt;
  &lt;h3 id=&quot;SVWG&quot;&gt;Всем привет!&lt;/h3&gt;
  &lt;p id=&quot;PUXz&quot;&gt;В этой статье я расскажу, как узнать баланс кошелька пользователя, почему перебор не работает, и почему 1inch умнички???&lt;/p&gt;
  &lt;section style=&quot;background-color:hsl(hsl(236, 74%, var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;p id=&quot;3ZhN&quot;&gt;Ссылка на гитхаб с исходным кодом будет в конце статьи&lt;/p&gt;
    &lt;p id=&quot;I0AK&quot;&gt;Я буду делать все на js&lt;/p&gt;
  &lt;/section&gt;
  &lt;p id=&quot;TkOd&quot;&gt;Если вы пользовались DEX обменником &lt;a href=&quot;https://app.1inch.io/&quot; target=&quot;_blank&quot;&gt;1inch&lt;/a&gt;, то наверняка замечали, что баланс каждого ERC20 токена загружается мгновенно&lt;/p&gt;
  &lt;figure id=&quot;SSV3&quot; class=&quot;m_retina&quot;&gt;
    &lt;img src=&quot;https://img4.teletype.in/files/7c/e7/7ce70012-a21b-44a4-9d1b-401d3908fb64.png&quot; width=&quot;464&quot; /&gt;
  &lt;/figure&gt;
  &lt;h3 id=&quot;E35s&quot;&gt;Почему это важно?&lt;/h3&gt;
  &lt;p id=&quot;pGAb&quot;&gt;Блокчейн эфириума устроен так, что для того, чтобы узнать количество токенов у пользователя, нужно делать запрос баланса по &lt;strong&gt;каждому контракту токена&lt;/strong&gt;&lt;/p&gt;
  &lt;p id=&quot;p7uH&quot;&gt;Иными словами, если у вас есть список из 100 монет, и вы хотите узнать сколько монет держит пользователь, то необходимо сделать 100 запросов в блокчейн&lt;/p&gt;
  &lt;p id=&quot;Umyk&quot;&gt;&lt;strong&gt;А если их много?&lt;/strong&gt;&lt;/p&gt;
  &lt;p id=&quot;jSMX&quot;&gt;Рассмотрим 3 метода получить количество токенов&lt;/p&gt;
  &lt;ol id=&quot;HQ9n&quot;&gt;
    &lt;li id=&quot;GOFo&quot;&gt;&lt;a href=&quot;#iCVJ&quot;&gt;Простой перебор (brute force)&lt;/a&gt;&lt;/li&gt;
    &lt;li id=&quot;dXYZ&quot;&gt;&lt;a href=&quot;#sIlL&quot;&gt;Множественный запрос&lt;/a&gt;&lt;/li&gt;
    &lt;li id=&quot;4NbL&quot;&gt;&lt;a href=&quot;#oUGT&quot;&gt;Запрос с оптимизацией газа&lt;/a&gt;&lt;/li&gt;
  &lt;/ol&gt;
  &lt;p id=&quot;MAYY&quot;&gt;&lt;/p&gt;
  &lt;section style=&quot;background-color:hsl(hsl(236, 74%, var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;p id=&quot;B5Zd&quot;&gt;В дальнейших примерах я буду использовать пакет 1inch &lt;strong&gt;multicall&lt;/strong&gt;&lt;/p&gt;
    &lt;p id=&quot;0S0G&quot;&gt;Установка: &lt;/p&gt;
    &lt;pre id=&quot;KLQq&quot; data-lang=&quot;shell&quot;&gt;npm install @1inch/multicall&lt;/pre&gt;
    &lt;pre id=&quot;njKW&quot; data-lang=&quot;shell&quot;&gt;yarn install @1inch/multicall&lt;/pre&gt;
  &lt;/section&gt;
  &lt;p id=&quot;C8JH&quot;&gt;&lt;/p&gt;
  &lt;h2 id=&quot;iCVJ&quot; data-align=&quot;center&quot;&gt;ПРОСТОЙ ПЕРЕБОР&lt;/h2&gt;
  &lt;p id=&quot;Jk2h&quot;&gt;Тут достаточно простая логика&lt;/p&gt;
  &lt;p id=&quot;RLQ5&quot;&gt;Мы берем массив &lt;code&gt;tokens&lt;/code&gt; и методом &lt;code&gt;map&lt;/code&gt; пробегаем по массиву контрактов токенов&lt;/p&gt;
  &lt;p id=&quot;D6Ax&quot;&gt;&lt;code&gt;return provider.ethCall(tokenAddress, callData);&lt;/code&gt; - возврашает нам количество токенов в hex формате&lt;/p&gt;
  &lt;figure id=&quot;DIdW&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img2.teletype.in/files/11/49/11493db7-4738-4751-afc8-aee9a7dbaecc.png&quot; width=&quot;1006&quot; /&gt;
    &lt;figcaption&gt;тут я вывел баланс монет на кошельке xdefi, weth, ARMOR (хз че за токен)&lt;/figcaption&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;0S5k&quot;&gt;Далее идем на сайт перевода систем счисления и видим, что все сходится (это все в wei, а в эфире это как раз 0,001025eth)&lt;/p&gt;
  &lt;figure id=&quot;MVJH&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img3.teletype.in/files/60/01/600109cb-86f1-4eff-9a8c-b6937e6a51e7.png&quot; width=&quot;1570&quot; /&gt;
  &lt;/figure&gt;
  &lt;figure id=&quot;m06v&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img4.teletype.in/files/7e/28/7e2841c2-d929-40d9-95fd-27b784c6186d.png&quot; width=&quot;756&quot; /&gt;
  &lt;/figure&gt;
  &lt;h2 id=&quot;47v4&quot;&gt;НО!&lt;/h2&gt;
  &lt;p id=&quot;WBzk&quot;&gt;Если у нас не три токена, а 1009, как у 1inch, то получается вот что&lt;/p&gt;
  &lt;figure id=&quot;X7a5&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img2.teletype.in/files/95/f4/95f4f7b0-d2d3-4699-bf23-74029cab73b3.png&quot; width=&quot;898&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;mF7m&quot;&gt;Поясняю, 2,7 секунд на запрос - это очень много для веб приложения&lt;/p&gt;
  &lt;p id=&quot;cpa0&quot;&gt;А если вы используете провайдера Alchemy/Infurra, то получите такое&lt;/p&gt;
  &lt;figure id=&quot;FfJh&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img1.teletype.in/files/06/10/06102a32-10dd-4013-8055-8b10ba02e23f.png&quot; width=&quot;1194&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;r94v&quot;&gt;Ребята из 1inch решили эту проблему, и вот как...&lt;/p&gt;
  &lt;p id=&quot;LXni&quot;&gt;&lt;/p&gt;
  &lt;h2 id=&quot;sIlL&quot; data-align=&quot;center&quot;&gt;МНОЖЕСТВЕННЫЙ ЗАПРОС&lt;/h2&gt;
  &lt;p id=&quot;b95H&quot;&gt;В чем суть решения&lt;/p&gt;
  &lt;p id=&quot;eb7U&quot;&gt;Мы не отправляем 1009 транзакций в блокчейн, а разбиваем их на группы (chunks)&lt;/p&gt;
  &lt;pre id=&quot;XneF&quot; data-lang=&quot;javascript&quot;&gt;const params = {
  chunkSize: 100,
  retriesLimit: 3,
  blockNumber: &amp;#x27;latest&amp;#x27;,
};&lt;/pre&gt;
  &lt;p id=&quot;kKM1&quot;&gt;В объекте &lt;code&gt;params&lt;/code&gt; мы указываем &lt;/p&gt;
  &lt;ol id=&quot;TZNA&quot;&gt;
    &lt;li id=&quot;B2JF&quot;&gt;Количество запросов в одном чанке&lt;/li&gt;
    &lt;li id=&quot;3S5v&quot;&gt;Количество попыток на запрос&lt;/li&gt;
    &lt;li id=&quot;i9Nc&quot;&gt;В каком блоке ищем ответ&lt;/li&gt;
  &lt;/ol&gt;
  &lt;p id=&quot;hlSI&quot;&gt;Далее вызываем асинхронный метод класса &lt;code&gt;multiCallService&lt;/code&gt;&lt;/p&gt;
  &lt;pre id=&quot;0Bm1&quot; data-lang=&quot;javascript&quot;&gt;multiCallService.callByChunks(callDatas, params).then((res)=&amp;gt;{//тут логика})&lt;/pre&gt;
  &lt;p id=&quot;NEzG&quot;&gt;И радуемся огромному массиву с балансами токенов)&lt;/p&gt;
  &lt;h2 id=&quot;poSK&quot;&gt;НО!&lt;/h2&gt;
  &lt;p id=&quot;jd0a&quot;&gt;Если вызов этого метода достигнет лимита по газу (даже у функций чтения имеется газлимит) при вызове контракта, то запрос развернут, и вы не получите ответа&lt;/p&gt;
  &lt;section style=&quot;background-color:hsl(hsl(170, 33%, var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;p id=&quot;Kott&quot;&gt;&lt;strong&gt;Для справки&lt;/strong&gt;&lt;/p&gt;
    &lt;p id=&quot;a4S3&quot;&gt;Изначально в блоке &lt;u&gt;15 млн газа&lt;/u&gt;&lt;/p&gt;
    &lt;p id=&quot;Osk9&quot;&gt;Но если спрос высокий, то количество газа увеличивается до &lt;u&gt;30 млн газа&lt;/u&gt;&lt;/p&gt;
  &lt;/section&gt;
  &lt;p id=&quot;u593&quot;&gt;Транзакцию также развернут, если она занимает очень много времени&lt;/p&gt;
  &lt;p id=&quot;qf1V&quot;&gt;Поэтому есть еще более умный способ это сделать...&lt;/p&gt;
  &lt;p id=&quot;zLUs&quot;&gt;&lt;/p&gt;
  &lt;h2 id=&quot;oUGT&quot; data-align=&quot;center&quot;&gt;ЗАПРОС С ОПТИМИЗАЦИЕЙ ГАЗА&lt;/h2&gt;
  &lt;p id=&quot;hbG7&quot;&gt;Чтобы не натыкаться на ограничения по газу на запрос, теперь мы будем узнавать у ноды лимиты на газ и разбивать запрос на чанки в соответсвии с лимитам&lt;/p&gt;
  &lt;p id=&quot;Yc5f&quot;&gt;Отличие тут в том, что если какой-то чанк не поместится, весь запрос не отклонят, а отклонят только один чанк, и мы потом повторно попробуем получить данные&lt;/p&gt;
  &lt;h3 id=&quot;QBWI&quot;&gt;Вот объяснение на картиночках&lt;/h3&gt;
  &lt;p id=&quot;5t10&quot;&gt;У нас есть чанк с максимальным размером 6 запросов&lt;/p&gt;
  &lt;p id=&quot;R2zj&quot;&gt;Чтобы узнать лимит по газу на запрос мы берем минимум из максимального лимита на газ, который мы установили, и лимита на газ из ноды,&lt;/p&gt;
  &lt;p id=&quot;KQvv&quot;&gt;после этого вычитаем буффер (на схемке все видно)&lt;/p&gt;
  &lt;figure id=&quot;00tG&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img1.teletype.in/files/83/c7/83c76be8-25db-4c32-968a-93bd9bf99cb1.png&quot; width=&quot;1648&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;x4mP&quot;&gt;Теперь мы знаем в какое количество газа нам нужно уложиться и добавляем в чанк запросы пока не достигнем лимита (это произошло на 5 и 11 запросе)&lt;/p&gt;
  &lt;figure id=&quot;jg8v&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img4.teletype.in/files/73/17/73170890-fcce-4b3b-ae99-7698cfca3030.png&quot; width=&quot;1642&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;oxtb&quot;&gt;Допустим запросы 4, 9, 10, 12 не выполнились&lt;/p&gt;
  &lt;figure id=&quot;9X2x&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img4.teletype.in/files/f5/0e/f50e7f99-04c9-4473-951e-e5aee92a4360.png&quot; width=&quot;1642&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;2SLR&quot;&gt;Теперь мы уменьшаем максимальное количество запросов в чанке в 2 раза и еще раз пытаемся выполнить обращения к блокчейну&lt;/p&gt;
  &lt;figure id=&quot;eHWR&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img2.teletype.in/files/51/f3/51f376d6-5e7d-40b7-9ad7-90d4c36b5366.png&quot; width=&quot;1634&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;ccSW&quot;&gt;Ура! Все запросы выполнены, в конце просто их складываем и получаем ответ &lt;/p&gt;
  &lt;p id=&quot;lQLJ&quot;&gt;&lt;strong&gt;PROFIT: Время запроса уменьшилось в 2 раза, и теперь мы не получаем ошибки из-за огромного количества обращений от Alchemy/Infurra&lt;/strong&gt;&lt;/p&gt;
  &lt;figure id=&quot;mf9t&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img4.teletype.in/files/fb/00/fb00f917-1037-479b-9822-d64153ee25d7.png&quot; width=&quot;1042&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;zlVG&quot;&gt;&lt;/p&gt;
  &lt;section style=&quot;background-color:hsl(hsl(170, 33%, var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;p id=&quot;UyiT&quot;&gt;Как и обещал, вот &lt;strong&gt;ссылка на гитхаб &lt;/strong&gt;&lt;a href=&quot;https://github.com/chpotl/fastErc20Balance&quot; target=&quot;_blank&quot;&gt;https://github.com/chpotl/fastErc20Balance&lt;/a&gt;&lt;/p&gt;
    &lt;p id=&quot;AShD&quot;&gt;Тут контракт 1inch - &lt;a href=&quot;https://etherscan.io/address/0x8d035edd8e09c3283463dade67cc0d49d6868063#code&quot; target=&quot;_blank&quot;&gt;https://etherscan.io/address/0x8d035edd8e09c3283463dade67cc0d49d6868063#code&lt;/a&gt;&lt;/p&gt;
    &lt;p id=&quot;5GBN&quot;&gt;Тут репозиторий 1inch с этим пакетом - &lt;a href=&quot;https://github.com/1inch/multicall&quot; target=&quot;_blank&quot;&gt;https://github.com/1inch/multicall&lt;/a&gt;&lt;/p&gt;
  &lt;/section&gt;
  &lt;h2 id=&quot;3j4b&quot;&gt;Надеюсь статья была полезной&lt;/h2&gt;
  &lt;h3 id=&quot;NVg5&quot;&gt;Спасибо за прочтение&lt;/h3&gt;
  &lt;h3 id=&quot;eEHR&quot;&gt;Мой телеграм - &lt;a href=&quot;https://t.me/chpotldev&quot; target=&quot;_blank&quot;&gt;https://t.me/chpotldev&lt;/a&gt;&lt;/h3&gt;

</content></entry><entry><id>chpotl:web3Auth</id><link rel="alternate" type="text/html" href="https://teletype.in/@chpotl/web3Auth?utm_source=teletype&amp;utm_medium=feed_atom&amp;utm_campaign=chpotl"></link><title>Web3 реги и как они работают</title><published>2022-07-28T22:55:10.009Z</published><updated>2022-07-30T12:33:46.551Z</updated><media:thumbnail xmlns:media="http://search.yahoo.com/mrss/" url="https://img3.teletype.in/files/e7/40/e7408e68-6608-46fd-a7c6-293eb51964fd.png"></media:thumbnail><summary type="html">&lt;img src=&quot;https://img1.teletype.in/files/4e/39/4e390ebe-f382-4873-966c-85e38c518419.jpeg&quot;&gt;Всем привет!</summary><content type="html">
  &lt;figure id=&quot;fXdu&quot; class=&quot;m_retina&quot;&gt;
    &lt;img src=&quot;https://img1.teletype.in/files/4e/39/4e390ebe-f382-4873-966c-85e38c518419.jpeg&quot; width=&quot;960&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;4iUM&quot;&gt;Всем привет!&lt;/p&gt;
  &lt;p id=&quot;MHH2&quot;&gt;В этой статье разберем принципы работы регистраций на веб3 сайтах&lt;/p&gt;
  &lt;section style=&quot;background-color:hsl(hsl(236, 74%, var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;p id=&quot;3ZhN&quot;&gt;Ссылка на гитхаб с исходным кодом будет в конце статьи&lt;/p&gt;
    &lt;p id=&quot;I0AK&quot;&gt;Я буду делать все на js&lt;/p&gt;
  &lt;/section&gt;
  &lt;p id=&quot;j8ng&quot;&gt;В мире веб3 существует несколько способов authenticaton на странице&lt;/p&gt;
  &lt;ol id=&quot;TkTX&quot;&gt;
    &lt;li id=&quot;SZXh&quot;&gt;&lt;a href=&quot;#Jtso&quot;&gt;Как у 1inch&lt;/a&gt; -  веб приложение выступает чисто интерфейсом для работы с контрактом DEXa и ничего не хранит на серверах&lt;/li&gt;
    &lt;li id=&quot;sJyN&quot;&gt;&lt;a href=&quot;#26N6&quot;&gt;Как у opensea&lt;/a&gt; - веб приложение 50/50 на веб3, потому что некоторые моменты хранятся на серверах, а остальное в блокчене&lt;/li&gt;
    &lt;li id=&quot;wdCI&quot;&gt;&lt;a href=&quot;#T7Dz&quot;&gt;Как у Дегенскана&lt;/a&gt; - веб приложение с подключением кошелька, но вся работа с блокчейнами происходит на бэкэнде&lt;/li&gt;
  &lt;/ol&gt;
  &lt;p id=&quot;L6XW&quot;&gt;Давайте разберёмся, как сделать authentication в каждом случае&lt;/p&gt;
  &lt;p id=&quot;Njfj&quot;&gt;&lt;/p&gt;
  &lt;h2 id=&quot;Jtso&quot; data-align=&quot;center&quot;&gt;1. КАК У &lt;a href=&quot;https://1inch.io/ru/&quot; target=&quot;_blank&quot;&gt;1inch&lt;/a&gt;&lt;/h2&gt;
  &lt;p id=&quot;seEQ&quot;&gt;Существует куча различный гайдов по тому, как добавить в свое приложение кнопку &amp;quot;connect wallet&amp;quot;, поэтому не буду заострять внимание на этом. Просто в общих чертах опишу, как это работает.&lt;/p&gt;
  &lt;p id=&quot;HYFQ&quot;&gt;&lt;strong&gt;ШАГ 1&lt;/strong&gt; - Создаем файл index.html, туда добавляем кнопку &amp;quot;connect wallet&amp;quot; и подключаем наш будущий файл script.js&lt;/p&gt;
  &lt;p id=&quot;OWAh&quot;&gt;&lt;strong&gt;ШАГ 2&lt;/strong&gt; - Делаем файл script.js, вешаем события на кнопки и используем чудесный API метамаска&lt;/p&gt;
  &lt;p id=&quot;TihK&quot;&gt;Прелесть тут в том, что не нужно не нужно импортировать сторонние библиотеки&lt;/p&gt;
  &lt;h3 id=&quot;gk2a&quot;&gt;А теперь подробнее&lt;/h3&gt;
  &lt;p id=&quot;SKaA&quot;&gt;&lt;code&gt;window.ethereum&lt;/code&gt; - возвращает объект, если у пользователя установлено расширение метамаска, если его нет, то возвращается undefined&lt;/p&gt;
  &lt;p id=&quot;BxoO&quot;&gt;&lt;code&gt;await ethereum.request({ method: &amp;#x27;eth_requestAccounts&amp;#x27; });&lt;/code&gt; - тут мы асинхронно запрашиваем у пользователя кошельки, чтобы подключится к веб-приложению&lt;/p&gt;
  &lt;p id=&quot;2gQs&quot;&gt;&lt;code&gt;ethereum.selectedAddress&lt;/code&gt; - хранит массив подключенных адресов. Берем [0] элемент и получаем выбранный адрес, если он один, если много, то можем брать любой&lt;/p&gt;
  &lt;p id=&quot;CVp9&quot;&gt;Ура! Мы знаем адрес пользователя и можем делать запросы на отправление транзакций и т.п., а в метамаске теперь написано &amp;quot;подключено&amp;quot;&lt;/p&gt;
  &lt;figure id=&quot;DbFE&quot; class=&quot;m_original&quot;&gt;
    &lt;img src=&quot;https://img4.teletype.in/files/fa/fb/fafb73ce-f43e-4fba-b544-64ee430436b5.png&quot; width=&quot;460&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;IhO9&quot;&gt;Теперь нам достаточно создать объект transactionParameters, куда передадим от кого (from), куда (to) и сколько эфира отправить (value)&lt;/p&gt;
  &lt;p id=&quot;aJtP&quot;&gt;&lt;code&gt;await ethereum.request({method: &amp;#x27;eth_sendTransaction&amp;#x27;, params [transactionParameters]});&lt;/code&gt; - делаем еще один request и отправляем транзакцию&lt;/p&gt;
  &lt;p id=&quot;oWV2&quot;&gt;При нажатии на кнопку send мы можем делать что угодно, я прикрутил отправку эфиров ortomich.eth&lt;/p&gt;
  &lt;section style=&quot;background-color:hsl(hsl(24,  24%, var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;p id=&quot;ms2R&quot;&gt;Вот тут документация метамаск апи: &lt;a href=&quot;https://docs.metamask.io/guide/&quot; target=&quot;_blank&quot;&gt;https://docs.metamask.io/guide/&lt;/a&gt;&lt;/p&gt;
    &lt;p id=&quot;Ijzk&quot;&gt;Тут неповторимий Патрик делает это на протяжении 10 часов: &lt;a href=&quot;https://www.youtube.com/watch?v=pdsYCkUWrgQ&amp;t=1406s&quot; target=&quot;_blank&quot;&gt;https://www.youtube.com/watch?v=pdsYCkUWrgQ&amp;amp;t=1406s&lt;/a&gt;&lt;/p&gt;
    &lt;p id=&quot;QtD6&quot;&gt;Тут про window.ethereum - &lt;a href=&quot;https://eips.ethereum.org/EIPS/eip-1193&quot; target=&quot;_blank&quot;&gt;https://eips.ethereum.org/EIPS/eip-1193&lt;/a&gt;&lt;/p&gt;
  &lt;/section&gt;
  &lt;p id=&quot;Sioi&quot;&gt;&lt;/p&gt;
  &lt;h2 id=&quot;26N6&quot; data-align=&quot;center&quot;&gt;2. КАК У &lt;a href=&quot;https://opensea.io/&quot; target=&quot;_blank&quot;&gt;OPENSEA&lt;/a&gt;&lt;/h2&gt;
  &lt;p id=&quot;XqAA&quot;&gt;На всем известной площадке используются такие штуки как &lt;strong&gt;&lt;em&gt;&lt;u&gt;ПОДПИСИ&lt;/u&gt;&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
  &lt;section style=&quot;background-color:hsl(hsl(170, 33%, var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;p id=&quot;7Zds&quot;&gt;В чем основные плюсы сигнатур (аkа подписей)&lt;/p&gt;
    &lt;ol id=&quot;BXmq&quot;&gt;
      &lt;li id=&quot;4ctX&quot;&gt;Бесплатно&lt;/li&gt;
      &lt;li id=&quot;PhQq&quot;&gt;Никто не подделает твою подпись (если только угонит приватный ключ)&lt;/li&gt;
    &lt;/ol&gt;
  &lt;/section&gt;
  &lt;p id=&quot;w1QQ&quot;&gt;Они собственно и придуманы, чтобы подтверждать различные действия на сайте от вашего лица, не платя за газ&lt;/p&gt;
  &lt;p id=&quot;s9I0&quot;&gt;Как же их использовать, чтобы зайти на сайт, где нужно не только делать свапы, а еще добавлять в избранное и т.п.?&lt;/p&gt;
  &lt;p id=&quot;CdwU&quot;&gt;Вся логика основано на том факте, что кроме самого пользователя, никто не сгенерит уникальную сигнатуру&lt;/p&gt;
  &lt;p id=&quot;T6lG&quot;&gt;&lt;strong&gt;ШАГ 0&lt;/strong&gt; - Инициализируем проект качаем модули&lt;/p&gt;
  &lt;figure id=&quot;FeKl&quot; class=&quot;m_retina&quot;&gt;
    &lt;img src=&quot;https://img1.teletype.in/files/84/93/84938dd1-8eaa-49d3-9099-bb9a062d98b9.png&quot; width=&quot;192&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;riA0&quot;&gt;&lt;strong&gt;ШАГ 1&lt;/strong&gt; - Делаем html + подключаем axios и ethers, чтобы слать запросы на сервер и взаимодействовать с блокчейном&lt;/p&gt;
  &lt;p id=&quot;mHOm&quot;&gt;&lt;strong&gt;ШАГ 2&lt;/strong&gt; - Запускаем чудо-сервер на node.js + нам понадобиться бд чтоб хранить пользователей, mongoDB = 1 love ^_^ У них красивый &lt;a href=&quot;https://www.mongodb.com/&quot; target=&quot;_blank&quot;&gt;сайт))))))&lt;/a&gt;&lt;/p&gt;
  &lt;p id=&quot;g1GT&quot;&gt;Тут стандартные node.js штучки, ну и соответвенно делаем путь &lt;code&gt;/login&lt;/code&gt;, чтобы куда-то слать наши подписи&lt;/p&gt;
  &lt;p id=&quot;2dse&quot;&gt;&lt;strong&gt;ШАГ 3&lt;/strong&gt; - Делаем файл userModel - это чисто для БД, чтобы понимала, что от нее хотят, короче просто поля для бд. По сути нам достаточно хранить только кошелек, чтобы идентифицировать пользователя, но я еще добавил роль, потому что могу x2&lt;/p&gt;
  &lt;p id=&quot;lwze&quot;&gt;&lt;strong&gt;ШАГ 4&lt;/strong&gt; - Делаем файл authController, там будет лежать логика для autentification на сервере&lt;/p&gt;
  &lt;p id=&quot;K6KE&quot;&gt;В нем у нас будет две функции &lt;strong&gt;&lt;em&gt;login&lt;/em&gt;&lt;/strong&gt; и &lt;strong&gt;&lt;em&gt;signatureVerify&lt;/em&gt;&lt;/strong&gt;, нетрудно догадаться что они делают&lt;/p&gt;
  &lt;p id=&quot;wHH2&quot;&gt;Далее в &lt;strong&gt;&lt;em&gt;signatureVerify &lt;/em&gt;&lt;/strong&gt;берем подпись, и сообщение, а чудо метод &lt;code&gt;recover&lt;/code&gt; возвращает исходный адрес, что с этой информацией делать дальше догадаться несложно. &lt;/p&gt;
  &lt;pre id=&quot;kZfu&quot; data-lang=&quot;javascript&quot;&gt;const signer = await web3.eth.accounts.recover(message, sign);
if (signer != address) {
  res.status(400).json({
    msg: &amp;#x27;error&amp;#x27;,
    data: &amp;#x27;Wrong signature&amp;#x27;,
  });
}&lt;/pre&gt;
  &lt;p id=&quot;Eqsh&quot;&gt;Простой &lt;code&gt;if&lt;/code&gt; сделает все сам. Если все хорошо, то переходим в функции &lt;strong&gt;&lt;em&gt;login&lt;/em&gt;&lt;/strong&gt;&lt;/p&gt;
  &lt;p id=&quot;xy3b&quot;&gt;В функции &lt;strong&gt;&lt;em&gt;login &lt;/em&gt;&lt;/strong&gt;мы точно знаем, что пользователь &amp;quot;владеет этим кошельком&amp;quot;, и используя его адрес мы либо создаем новый аккаунт, либо входим в уже существующий&lt;/p&gt;
  &lt;pre id=&quot;xy3b&quot; data-lang=&quot;javascript&quot;&gt;const address = req.body.address;
let user = await User.findOne({ address }); //ищем в бд
let dbMsg;
if (!user) {
  user = await User.create({ address: address });//создаем пользователя
  dbMsg = &amp;#x60;new user ${address}&amp;#x60;;
} else {
  dbMsg = &amp;#x60;user exist&amp;#x60;;//просто выводим
}&lt;/pre&gt;
  &lt;p id=&quot;IEZZ&quot;&gt;&lt;strong&gt;ШАГ 5&lt;/strong&gt; - Чтобы сделать модное сообщение для подписания как у опенси...&lt;/p&gt;
  &lt;figure id=&quot;a1ss&quot; class=&quot;m_retina&quot;&gt;
    &lt;img src=&quot;https://img3.teletype.in/files/eb/f4/ebf45180-f536-4c51-a0f3-aaf7443e8dad.png&quot; width=&quot;472&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;yTls&quot;&gt;....просто генерируем случайную строку в hex формате&lt;/p&gt;
  &lt;pre id=&quot;yTls&quot; data-lang=&quot;javascript&quot;&gt;const genRanHex = (size) =&amp;gt;
  [...Array(size)]
    .map(() =&amp;gt; Math.floor(Math.random() * 16).toString(16))
    .join(&amp;#x27;&amp;#x27;);
const nonce = genRanHex(32);
const message = &amp;#x60;Welcome to OpenSea!\n\nClick to sign in and accept the OpenSea Terms of Service: https://opensea.io/tos\n\nThis request will not trigger a blockchain transaction or cost any gas fees.\n\nYour authentication status will reset after 24 hours.\n\nWallet address:\n${ethereum.selectedAddress}\n\nNonce:\n${nonce}&amp;#x60;;&lt;/pre&gt;
  &lt;p id=&quot;kU1r&quot;&gt;Зачем это нужно&lt;/p&gt;
  &lt;p id=&quot;LLqm&quot;&gt;&lt;strong&gt;Как можно в теории угнать логин?&lt;/strong&gt; (&lt;em&gt;Представим мир, где на опенси в подписи текст &amp;quot;1234&amp;quot;, и с помощью подписи можно отправить все нфт любому человеку)&lt;/em&gt;&lt;/p&gt;
  &lt;ol id=&quot;suAk&quot;&gt;
    &lt;li id=&quot;XQlM&quot;&gt;Негодяи знают, что на опенси подпись &amp;quot;1234&amp;quot;, и делают сайт с такой же подписью&lt;/li&gt;
    &lt;li id=&quot;trQd&quot;&gt;Вы каким-то образом туда заходите, и подписываете сообщение &amp;quot;1234&amp;quot;&lt;/li&gt;
    &lt;li id=&quot;oUK0&quot;&gt;Негодяи теперь знают, ваш адрес и подпись сообщения &amp;quot;1234&amp;quot;&lt;/li&gt;
    &lt;li id=&quot;0X24&quot;&gt;Они идут на опенси и заходят под вашим логином&lt;/li&gt;
  &lt;/ol&gt;
  &lt;h3 id=&quot;YitN&quot; data-align=&quot;center&quot;&gt;НО!&lt;/h3&gt;
  &lt;p id=&quot;4Nzg&quot;&gt;&lt;strong&gt;В реальном мире они максимум уберут лайки с нфт, так что бояться не стоит, но на всякий случай, если будете делать какой-то проект, то имейте это ввиду&lt;/strong&gt;&lt;/p&gt;
  &lt;section style=&quot;background-color:hsl(hsl(170, 33%, var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;p id=&quot;cjBy&quot;&gt;Опенси &lt;strong&gt;раз в 24 часа&lt;/strong&gt; просит вас подписать подобное сообщение, чтобы обновить данные и лишить хлеба негодяев&lt;/p&gt;
  &lt;/section&gt;
  &lt;section style=&quot;background-color:hsl(hsl(24,  24%, var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;p id=&quot;UKYX&quot;&gt;Тут доки ethers - &lt;a href=&quot;https://docs.ethers.io/v5/&quot; target=&quot;_blank&quot;&gt;https://docs.ethers.io/v5/&lt;/a&gt;&lt;/p&gt;
    &lt;p id=&quot;75rL&quot;&gt;Тут можно поиграться с подписями - &lt;a href=&quot;https://etherscan.io/verifiedSignatures#&quot; target=&quot;_blank&quot;&gt;https://etherscan.io/verifiedSignatures#&lt;/a&gt;&lt;/p&gt;
    &lt;p id=&quot;9JaO&quot;&gt;Тут проект, который тоже использует подписи - &lt;a href=&quot;https://snapshot.org/&quot; target=&quot;_blank&quot;&gt;https://snapshot.org/&lt;/a&gt;&lt;/p&gt;
    &lt;p id=&quot;aZqk&quot;&gt;Тут как работают сигнатуры - &lt;a href=&quot;https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm&quot; target=&quot;_blank&quot;&gt;https://en.wikipedia.org/wiki/Elliptic_Curve_Digital_Signature_Algorithm&lt;/a&gt;&lt;/p&gt;
  &lt;/section&gt;
  &lt;p id=&quot;y0gz&quot;&gt;&lt;/p&gt;
  &lt;h2 id=&quot;T7Dz&quot; data-align=&quot;center&quot;&gt;КАК У &lt;a href=&quot;https://degenscan.pro/feeds&quot; target=&quot;_blank&quot;&gt;ДЕГЕНСКАНА&lt;/a&gt;&lt;/h2&gt;
  &lt;p id=&quot;RoG5&quot;&gt;Тут основная логика в том, что не нужны особо взаимодействия с блокчейном, поэтому работает золотое правило web3&lt;/p&gt;
  &lt;section style=&quot;background-color:hsl(hsl(323, 50%, var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;h3 id=&quot;tduo&quot;&gt;Если можно не использовать блокчейн, то мы им и не пользуемся&lt;/h3&gt;
  &lt;/section&gt;
  &lt;p id=&quot;3b2R&quot;&gt;Поэтому когда мы нажимаем &amp;quot;connect wallet&amp;quot; и подписываем сообщение, идет запрос на их сервер, где передается просто сигнатура&lt;/p&gt;
  &lt;figure id=&quot;CPNB&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img4.teletype.in/files/fa/07/fa07f387-5000-4de2-8828-3e26fbf41918.png&quot; width=&quot;818&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;REWp&quot;&gt;И получаем такой ответ, у меня нет подписки, поэтому тут false&lt;/p&gt;
  &lt;figure id=&quot;r5FN&quot; class=&quot;m_column&quot;&gt;
    &lt;img src=&quot;https://img3.teletype.in/files/e6/63/e66351dc-02f8-46f1-a31c-4187835f78d1.png&quot; width=&quot;920&quot; /&gt;
  &lt;/figure&gt;
  &lt;p id=&quot;tl6M&quot;&gt;Делаем вывод из этого, что когда вы делаете подпись, она отправляется на сервер, и там просто проверяется, нет ли у этого пользователя доступа к дегенскану или админке.&lt;/p&gt;
  &lt;p id=&quot;p3Tu&quot;&gt;Все просто и лаконично&lt;/p&gt;
  &lt;p id=&quot;ny5b&quot;&gt;&lt;/p&gt;
  &lt;section style=&quot;background-color:hsl(hsl(170, 33%, var(--autocolor-background-lightness, 95%)), 85%, 85%);&quot;&gt;
    &lt;p id=&quot;UyiT&quot;&gt;Как и обещал, вот &lt;strong&gt;ссылка на гитхаб&lt;/strong&gt;&lt;/p&gt;
    &lt;p id=&quot;N913&quot;&gt;&lt;a href=&quot;https://github.com/chpotl/web3Auth&quot; target=&quot;_blank&quot;&gt;https://github.com/chpotl/web3Auth&lt;/a&gt;&lt;/p&gt;
  &lt;/section&gt;
  &lt;h2 id=&quot;3j4b&quot;&gt;Надеюсь статья была полезной&lt;/h2&gt;
  &lt;h3 id=&quot;NVg5&quot;&gt;Спасибо за прочтение &lt;/h3&gt;
  &lt;h3 id=&quot;eEHR&quot;&gt;Мой телеграм - &lt;a href=&quot;https://t.me/chpotldev&quot; target=&quot;_blank&quot;&gt;https://t.me/chpotldev&lt;/a&gt;&lt;/h3&gt;

</content></entry></feed>