Как развернуть EVM-функционал на Solana
Семён Медведев, Head of Development в Neon Labs, рассказал про то, как развернуть EVM на Solana, как решить проблему оплаты комиссий транзакций, хранение данных и механизм подключения других систем сразу в двух абсолютно разных системах в докладе «Neon beyond Ethereum – EVM on Solana. Keynote and demo». Сделали конспект доклада!
Интеграция с нативными токенами Solana
У Neon Labs. есть две фундаментальные задачи:
- предоставить платформу, на которой можно было бы запускать приложение Solidity не изменяя с точки зрения когда выполняемого контракта, так и в плане адаптации самих приложений;
- предоставить доступ смарт-контрактам Ethereum к функциональным возможностям на Solana.

В первую очередь мы работали над предоставлением доступа к SPL Token. Это программа, которая, которая на Solana реализует функционал токенов. То есть, на Solana есть одна программа и к ней создаются разные монеты. На Ethereum есть зафиксированный интерфейс ERC20 и все контракты, которые хотят быть представлены как токен, должны реализовать этот интерфейс. Чтобы связать смарт-контракты Ethereum с балансами пользователя, мы реализовали смарт-контракт ERC20 для SPL, привычный для Ethereum интерфейс, умеющий работать с данными Solana, хранит балансы, которые принадлежат SPL-токену и узнает информацию о балансах из соответствующих записей в аккаунтах Solana. Контракт формирует транзакции во внешней к Neon EVM программе, чтобы сделать переводы.

NFT-коллекция
Мы решили пойти дальше и реализовать стандарт ERC721 — взаимонезаменяемые токены или NFT. Он реализуется с помощью токена SPL + метаданные через контракт MetaPlex. В MetaPlex заложено понятие коллекции — элементы, которые есть у конкретного пользователя. Для ERC721, коллекция — набор элементов, который был выпущен одним сетом, который может расширяться. Каждый элемент может принадлежать отдельному пользователю. В этом и есть фундаментальное отличие. Нам удалось объединить эти контракты, но когда внедряется коллекция в Neon EVM, необходимо преобразовывать этот концептуальный момент.
Реализация оракулов
На Solana уже есть оракулы от Pyth. А Chainlink предоставляет интерфейс оракулов для Ethereum. Нашей задачей было реализовать контракт, который будет поддерживать интерфейс Chainlink, но при это будет получать актуальные данные с Pyth Network. Выяснилось, что Pyth Network гораздо чаще обновляет данные, чем может выполняться итеративная транзакция. Пришлось ввести элемент кеширования данных, чтобы определенной итерации при обращении к данным, можно было загрузить в стейт виртуальной машины определенный набор данных и в следующих итерациях работали с консистентным состоянием. Сейчас мы тестируем эту интеграцию в составе Aave.
Интеграция с другими сетями
На базе ERC20-контракта можно интегрироваться с другими блокчейнами достаточно простым образом. Мы берем стандартный мост и пробрасываем ликвидность между другой сетью и Solana. Это делают команды мостов вроде Wormhole. Когда мост доносит ликвидность до SPL-токена, можно простым образом подключить ликвидность через ERC20-wrapper и через Neon EVM можно делать переводы, узнавать балансы и так далее.
Оплата транзакций в Neon EVM

Большой вопрос был с оплатой транзакций со счета пользователя, которая бы учитывала особенности и различия, которые есть между Ethereum и Solana. Изначально мы взяли оригинальный газометр, который есть в Ethereum. Но, когда мы подошли к расчету прибыльности транзакций, мы столкнулись с тем, что газометр Ethereum хорошо работает только с экономикой Ethereum. Для Solana он не приемлем в принципе. В Ethereum употребление газа сильно зависит от того, какие операции выполняет контракт, как работает со стораджем и памятью. У Solana модель оплаты другая: достаточно дешевые транзакции, причем они могут включать BPF-инструкции. И в рамках этого количества, списывает по 5 тысяч лампортов за каждую проверенную подпись в рамках транзакции. Если подписывает один пользователь — 5 тысяч лампортов, если два — 10 тысяч и так далее.
У Solana очень дорогое хранение данных в аккаунте. Один байт стоит около 7 тысяч лампортов (около 5 центов). Если мы хотим хранить данные без платы за время, которые они там буду находиться. Данные приходится хранить таким образом, чтобы аккаунты не были удалены сетью Solana по истечению балансов. Каждый аккаунт требует 128 байтов.
Мы столкнулись с выбором: либо делать транзакции слишком дорогими для пользователя по правила Ethereum, либо мы не до конца вознаграждаем оператора за SOL, которые он потратил на выполнение транзакции. Чтобы избежать этого, мы решили следовать правилу: когда Neon EVM считает газ за выполнение транзакции, то газ равен лампортам за выполнение той же транзакции. Мы платим за выполнение транзакции и за данные, которые были сохранены: код контракта, записи ячеек стораджа, создание новых аккаунтов.
Модель газометра используется точно так же как и в Ethereum, кроме этого момента. Neon EVM считает весь газ, который был потрачен во время каждой транзакции, затем автоматически списывает токены NEON на счет оператора. Оператор выполняет транзакцию, платит валидаторам Solana за проверку подписей и хранение данных, и отчисления в Treasury Pool, который используется для развития проекта.
Каким образом оператор может обеспечить себе прибыльность, получая оплату в одном токене и отдавая другой токен за ее выполнение. Прокси оператора следит за ценой между NEON и SOL, учитывает процент комиссий, который закладывает оператор и выставляет его как минимальный газпрайс, с которым он готов выполнять транзакции.
Подключение dApp и хранение данных

Сейчас мы активно тестируем решение на Devnet. Привлекаем различные приложения и пробуем их запускать. Часть мы уже протестировали, начиная с Uniswap v2. Запуская различные приложения, мы проверяем, насколько можно работать и адаптируем подходы, которые мы реализовали.
Приложение Aave выявило достаточно много проблем, связанных с тем, что у Solana количество аккаунтов, которое может быть указано в одной транзакции — жестко ограничено. Это ограничение было изначально из-за размера транзакции Solana, которая должна уместиться в UDP-пакет длиной 1500 байт. Выбрасывая данные для заголовков, мы получаем, что одна транзакция может включать в себя не больше 30-32 аккаунтов. В эти аккаунты входят все служебные аккаунты и по несколько аккаунтов на каждый выполняемый контракт. Для хранения одного контракта, надо было хранить два аккаунта с заголовком и стораджем и кодом. Сторадж в первоначальной реализации оказался разбит на отдельный аккаунт Solana в каждой ячейке. Транзакции могут быть достаточно сложные, контракты Ethereum взаимодействуют друг с другом, соответственно нужно указывать все эти аккаунты в заголовки — список исчислялся сотнями.
Solana пошла нам на встречу и реализовала расширение для адресов аккаунтов — в списке можно указать аккаунт, на котором хранится address lookup table, где можно разместить дополнительно аккаунты. Всего в майннете можно использовать 64 аккаунта в списке, в будущем список будет расширяться и модель оплаты будет меняться.
Нам пришлось провести ряд оптимизаций, чтобы наша модель хранения данных занимала меньше места. Наша оптимизация была в том, что мы сохраняли последовательные ячейки стораджа на один аккаунт Solana. Это дало нам достаточно большой выигрыш. Как правило, контракты Solidity работают с несколькими структурами данных, которые при такой организации помещаются на один аккаунт Solana.
Слияние аккаунтов

Следующей задачей было объединение аккаунтов в один. Изначально разбиение нужно было, чтобы код контракта мог принимать большие объемы. В Ethereum это 24 килобайта, но у нас не было возможности в Solana запросить такой объем данных. Некоторое время назад Solana реализовала метод по изменению размера таких аккаунтов. Когда мы объединили, получилось вместить в список аккаунтов по одному аккаунту на каждый контракт + некоторое количество сторадж-аккаунтов. Для Aave все эти оптимизации привели к тому, что нам надо всего 54 аккаунта для выполнения их транзакций.
Проведя эту работу, мы получили решение, которое с одной стороны предоставляет стандартный интерфейс для утилит и программ, которые реализованы, а также открывает мир Solana для работы.
Демонстрационная часть
Ссылка на демо: https://github.com/neonlabsorg/examples
Демо на примере MetaMask и Remix
Чтобы подключить MetaMask, можно использовать ChainList.org. Там у нас зарегистрированы наши сети. Подключаете ваш кошелек и добавляете сеть к известному в MetaMask.
Здесь указано три сети, майннет скоро будет запущен, но пока он неактивен. Различие между тестнетом и девнетом идет из идеологии Solana. Тестнет используется для внутреннего тестирования решений, которые сейчас разрабатываются для сети. Им пользуются разработчики из команды Solana. Девнет — сеть, открытая для всех пользователей и разработчиков.

Где получить тестовые токены для работы. Для этого можно воспользоваться Neon faucet.org. Он начисляет тестовые токены. Нужно подключить кошелек, который сейчас активный в Metamask. Выбираете токены. Пока доступны только Neon-токены, но скоро появятся ERC20 обернутые токены, которые хранят балансы на Solana. Указывайте, сколько надо токенов и отправляете транзакцию. Они придут к вам через какое-то время.

Буду показывать демо на базе простого контракта ERC20. Это стандартная реализация, поэтому она будет сохранять балансы пользователей внутри стораджа самого контракта. Компилируем.

Подключаемся к injected provider в Metamask. Указываем в конструкторе указывается total supply, после чего можно загрузить данные контракта.

Сразу можно увидеть, что транзакция будет стоить 6 NEON. Это обусловлено, как раз, отличиями, которые мы реализовали в газометре.

Когда контракт успешно задеплоен, можно вызывать его методы, total supply, баланс пользователя. После того как контракт задеплоен, все средства хранятся на балансе того пользователя, который задеплоил его.
Давайте добавим новый токен в Metamask. Видно, что он подгрузил данные из самого смарт-контракта, а также видно его баланс.

Давайте создадим второй счет и переведем эти токены на другой счет. Видно, что транзакция потребляет очень много газа. Это происходит из-за того, что в данной транзакции создается аккаунт получается. Последующие транзакции потребляют существенно меньше газа.

Для блокчейна Neon есть отдельный эксплорер neonscan.org, где можно посмотреть все эти транзакции. Два создания контракта и перевод токенов уже подтянулись.

Здесь можно посмотреть все подробности по выполнению транзакций. Сейчас мы работаем над тем, чтобы предоставить трейсинг APY, после этого можно будет смотреть как транзакция выполнялась.

Все последующие переводы будут потреблять гораздо меньше газа. Давайте сделаем еще одну транзакцию обратно на первый счет. И эта транзакция будет требоваться всего 31 тысячу газа.
