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

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

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

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

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

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

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

]]></content:encoded></item></channel></rss>