Мост ChainBridge между Ethereum и Moonbeam
Введение
Мост позволяет двум экономически независимым и технологически различным цепям взаимодействовать друг с другом. Мосты могут варьироваться от централизованных и надежных до децентрализованных и с минимальным доверием. Одним из доступных решений на данный момент является ChainBridge, модульный разно-направленный мост на blockchain, разработанный командой ChainSafe. Интеграция ChainBridge теперь доступна и на Moonbeam. Данная интеграция соединяет нашу альфа тестовую сеть Moonbeam — Moonbase и Rinkeby/Kovan тестовые сети эфира.
Это руководство разбито на два основных раздела. В первой части мы объясним общий рабочий процесс моста. Во второй части рассмотрим несколько примеров использования моста для передачи ресурсов ERC-20 и ERC-721 между Moonbase Alpha и Rinkeby / Kovan.
- Как работает мост
- Общие определения
- Использование моста в Moonbase Alpha
- Перенести токены ERC-20
- Перенести токены ERC-721
- Универсальный обработчик
- Связаться с нами
Как работает мост
ChainBridge по своей сути является протоколом передачи сообщений. События в исходном чейне используются для отправки сообщения, которое направляется в цепочку назначения. В данном процессе есть 3 основные роли:
- Слушатель: извлекает события из первоначального чейна и создает сообщение.
- Роутер: передает сообщение от слушателя до писателя.
- Писатель: интерпретирует сообщения и отправляет транзакцию на чейн-получатель.
В настоящее время ChainBridge полагается на доверенные ретрансляторы для выполнения этих ролей. Тем не менее, он имеет механизм, который предотвращает злоупотреблением полномочиями и ненадлежащее использование средств любым ретранслятором. На высоком уровне ретрансляторы создают предложения в целевой цепочке, которые отправляются на утверждение другим ретрансляторам. Утверждающее голосование также происходит в целевой цепочке, и каждое предложение выполняется только после того, как оно достигает определенного порога голосования.
По обе стороны моста есть набор смарт-контрактов, каждый из которых выполняет определенную функцию:
- Контракт Моста — пользователи и ретрансляторы взаимодействуют с этим контрактом. Он делегирует вызовы контрактам обработчика для депозитов, запускает транзакцию в исходной цепочке и для выполнения предложений в целевой цепочке.
- Контракты обработчика — проверяет параметры, предоставленные пользователем, создавая запись депозита / исполнения.
- Целевой контракт — как следует из названия, это контракт, с которым мы собираемся взаимодействовать с каждой стороны моста.
Общий рабочий процесс
Общий рабочий процесс следующий (от чейн A к чейн B):
- Пользователь инициирует транзакцию с помощью функции deposit () в мостовом контракте чейна A. Здесь пользователю необходимо ввести целевчй чейн, идентификатор ресурса и calldata (определения после диаграммы). После нескольких проверок вызывается функция deposit () контракта-обработчика, которая выполняет соответствующий вызов целевого контракта.
- После того, как функция целевого контракта в чейне A выполнена, мостовым контрактом генерируется событие депозита, которое содержит необходимые данные для выполнения в чейне B. Это называется предложением. Каждое предложение может иметь пять статусов (неактивно, активно, прошло, выполнено и отменено).
- Ретрансляторы всегда слушают с обеих сторон чейна. Как только ретранслятор принимает событие, он инициирует голосование по предложению, которое происходит в мостовом контракте в чейне B. Это устанавливает состояние предложения с неактивного на активное.
- Ретрансляторы должны проголосовать за предложение. Каждый раз, когда ретранслятор голосует, мостовой контракт генерирует событие, которое обновляет его статус. После достижения порога статус меняется с активного на пройденный. Затем ретранслятор выполняет предложение в чейне B через мостовой контракт.
- После нескольких проверок мост выполняет предложение в целевом контракте через контракт обработчика в чейне B. Запускается другое событие, которое обновляет статус предложения с «передано» на «выполнено».
Этот рабочий процесс представлен на следующей диаграмме:
Два целевых контракта на каждой стороне моста связаны путем выполнения серии регистраций в соответствующем контракте обработчика через мостовой контракт. Эти регистрации в настоящее время могут быть выполнены только администратором мостового контракта.
Общие определения
Здесь мы собрали список концепций, применимых к реализации ChainBridge (от цепочки A до цепочки B):
- ChainBridge Chain ID — не путать с идентификатором чейна сети. Это уникальный сетевой идентификатор, используемый протоколом для каждого чейна. Он может отличаться от фактического идентификатора чейна самой сети. Например, для Moonbase Alpha и Rinkeby мы установили идентификатор чейна ChainBridge на 43 и 4 соответственно (Кован был установлен на 42).
- Идентификатор ресурса — это 32-байтовое слово, предназначенное для однозначной идентификации актива в кросс-чейн среде. Обратите внимание, что младший байт зарезервирован для chainId, поэтому у нас будет 31 байт всего для представления актива чейна в нашем мосте. Например, это может быть выражение tokenX в чейне A эквивалентно tokenY в чейне B
- Calldata — это параметр, необходимый для обработчика, который включает информацию, необходимую для выполнения предложения в чейне B. Точная сериализация определяется для каждого обработчика. Вы можете найти больше информации здесь.
Протестируйте на Moonbase Alpha
Мы настроили ретранслятор с реализацией ChainBridge, который подключен к нашей тестовой сети Moonbase Alpha TestNet, а также к Rinkeby и Kovan TestNets Ethereum.
ChainSafe имеет предварительно запрограммированные обработчики, специфичные для интерфейсов ERC-20 и ERC-721, и эти обработчики используются для передачи токенов ERC-20 и ERC-721 между чейнами. Более подробную информацию можно найти здесь. В общих чертах, это просто сужение общей схемы, которую мы описали ранее, поэтому обработчик работает только с конкретными функциями токена, такими как блокировка / запись и чеканка / разблокировка.
В этом разделе будут рассмотрены два различных примера использования моста для перемещения токенов ERC-20 и ERC-721 между цепочками. Для взаимодействия с Moonbase Alpha и Rinkeby/Kovan вам понадобится следующая информация:
Передача токенов ERC-20
Токены ERC-20, которые нужно переместить через мост, должны быть зарегистрированы ретрансляторами в контрактах обработчиков. Поэтому для тестирования моста мы развернули токен ERC-20 (ERC20S), где любой пользователь может чеканить 5 токенов:
Аналогичным образом, прямое взаимодействие с контрактом Bridge и вызов функции deposit () с правильными параметрами может быть пугающим. Чтобы упростить процесс использования моста, мы создали модифицированный контракт моста, который создает необходимые входные данные для функции deposit ():
Проще говоря, в модифицированном контракте, используемом для инициирования передачи, для этого примера заранее определены chainID и resourceID. Следовательно, он создает объект calldata из ввода пользователя, который является только адресом получателя и значением, которое нужно отправить.
Общий рабочий процесс для этого примера можно увидеть на этой диаграмме:
Чтобы попробовать мост с этим образцом токена ERC-20, мы должны выполнить следующие шаги (независимо от направления передачи):
- Токены в исходном чейне (это подтверждает контракт обработчика источника в качестве спонсора на указанную сумму Токенов)
- Используйте модифицированный мостовой контракт в исходном чейне для отправки токенов
- Подождите, пока процесс завершится
- Утвердите контракт обработчика целевого чейна в качестве спонсора для отправки токенов обратно
- Используйте модифицированный мостовой контракт в целевом чейне для отправки токенов
Примечание:
Помните, что токены будут переданы только в том случае, если в контракте обработчика будет достаточно разрешений на использование токенов от имени владельца. Если процесс не удался, проверьте разрешение.
Давайте отправим Kovan несколько токенов ERC20S с Moonbase Alpha. Для этого воспользуемся Remix. Во-первых, мы можем использовать следующий интерфейс для взаимодействия с этим контрактом и создания токенов:
pragma solidity ^0.6.4;
/**
Interface for the Custom ERC20 Token contract for ChainBridge implementation
Rinkeby/Moonbase Alpha ERC-20 Address :
0xDb148a131d775615E8707eE11708B88e601b4397
Kovan/Moonbase Alpha ERC-20 Address:
0xF1346880D471D4345D740401A9B082265bDcc76a
*/
interface ICustomERC20 {
// Mint 5 ERC20S Tokens
function mintTokens() external;
// Get Token Name
function name() external view returns (string memory);
/**
Increase allowance to Handler
Rinkeby/Moonbase Alpha ERC-20 Handler:
0xddaDdc5148C47f9E1926520d7AD2175dD5Aad4d5
Kovan/Moonbase Alpha ERC-20 Handler:
0xC290939834364f08C8177b2A787eb3E032Fab27e
*/
function increaseAllowance(address spender, uint256 addedValue) external returns (bool);
// Get allowance
function allowance(address owner, address spender) external view returns (uint256);
}
Обратите внимание, что функция контракта токена ERC-20 также была изменена для утверждения соответствующего контракта обработчика в качестве спонсора при выпуске токенов.
В Remix загрузите интерфейсный контракт по адресу токена ERC-20 (убедитесь, что Вы используете внедренный провайдер Web3 MetaMask). Затем вызовите функцию mintTokens() и подпишите транзакцию. После подтверждения транзакции Вы должны получить 5 токенов ERC20S. Вы можете проверить свой баланс, добавив токен в MetaMask.
Когда у нас есть токены, мы можем приступить к их отправке через мост в целевой чейн. В этом случае помните, что мы делаем это от Moonbase Alpha до Кована. Следующий интерфейс позволяет использовать функцию sendERC20SToken()
для инициации передачи.
pragma solidity 0.6.4;
/**
Simple Interface to interact with bridge to transfer the ERC20S token
Rinkeby/Moonbase Alpha Bridge Address:
0xB8254105AC9EBAe528728bbdCDd1E060d8d24D08
Kovan/Moonbase Alpha Bridge Address:
0x89863493571c063171bE47e00c9404063eF1947A
*/
interface IPSBridgeERC20 {
/**
* @notice Creates a deposit in the Bridge Contract for an ERC-20 Transfer,
* @param _recipient Address recipient of the tokens in the other chain
* @param _value Amount of tokens to be sent
*/
function sendERC20SToken(address _recipient, uint _value) external;
}
Итак, еще раз в Remix загрузите интерфейсный контракт по адресу моста. Затем вызовите функцию sendERC20SToken(), указав адрес получателя на другой стороне моста и сумму для перевода в WEI. MetaMask должен появиться и попросить Вас подписать транзакцию. После подтверждения транзакции процесс может занять около 3 минут, после чего Вы должны получить токены в Kovan!
Вы можете проверить свой баланс, добавив токен в MetaMask и подключив его к целевой сети — в нашем случае Kovan.
Помните, что Вы также можете выпускать токены ERC20S в Коване и отправить их в Moonbase Alpha. Чтобы утвердить спонсора или увеличить его размер, Вы можете использовать функцию increaseAllowance()
предоставленного интерфейса. Чтобы проверить допустимость контракта обработчика в контракте токена ERC20, вы можете использовать функцию интерфейса allowance()
.
Примечание:
Токены будут переданы только в том случае, если в контракте с обработчиком будет достаточно разрешений для траты токенов от имени владельца. Если процесс не удался, проверьте припуск.
Трансфер токена ERC-721
Как и в нашем предыдущем примере, контракты токенов ERC-721 должны быть зарегистрированы ретрансляторами, чтобы обеспечить передачу через мост. Поэтому мы настроили контракт токена ERC-721, чтобы любой пользователь мог создать токен для тестирования моста. Однако, поскольку каждый токен не является взаимозаменяемым и, следовательно, уникальным, функция доступна только в контракте токенов исходной цепочки, но не в целевом контракте. Как следствие, вам понадобится пара адресов контрактов ERC-721 для токенов в Rinkeby / Kovan и передачи их в Moonbase Alpha и еще одну пару для противоположного действия. Следующая диаграмма объясняет рабочий процесс для этого примера, где важно подчеркнуть, что идентификатор токена и метаданные сохраняются.
Чтобы произвести токены в Moonbase Alpha (названные ERC721Moon с символом ERC721M) и отправлять их туда и обратно Rinkeby/Kovan, Вам понадобится следующий адрес:
Чтобы произвести токены в Rinkeby / Kovan (ERC721E) и отправлять их туда и обратно на Moonbase Alpha, Вам понадобится следующий адрес:
Вместо взаимодействия с контрактом моста и вызова функции deposit() мы изменили контракт моста, чтобы упростить процесс использования самого моста (тот же адрес, что и в предыдущем примере):
Проще говоря, в модифицированном мостовом контракте, используемом для инициирования передачи, для этого примера заранее определены chainID и resourceID. Следовательно, он создает объект calldata из ввода пользователя, который является только адресом получателя и идентификатором отправляемого токена.
Давайте отправим токен ERC720E от Kovan на Moonbase Alpha. Для этого воспользуемся Remix. Следующий интерфейс можно использовать для взаимодействия с исходными контрактами ERC721 и произведением токенов. Функцию tokenOfOwnerByIndex()
также можно использовать для проверки идентификаторов токенов, принадлежащих определенному адресу, передавая адрес и индекс для запроса (каждый идентификатор токена сохраняется как элемент массива, связанный с адресом):
pragma solidity ^0.6.4;
/**
Interface for the Custom ERC721 Token contract for ChainBridge implementation:
Rinkeby/Moonbase Alpha:
ERC721Moon: 0x23A5AdE9E1e5DB3F0Db2027d91041fe3d78b2358
ERC721Eth: 0x5A142d1658DCE58e180b0329d83569C4c0B6e424
Kovan/Moonbase Alpha:
ERC721Moon: 0xD1017C476f05DFc456c02C35Fb94D8aBf79766A0
ERC721Eth: 0xf0fC240f029c9E953D85350B35439ECA24BECbe2
interface ICustomERC721 {
// Mint 1 ERC-721 Token
function mintToken() external returns (uint256);
// Query tokens owned by Owner
function tokenOfOwnerByIndex(address _owner, uint256 _index) external view returns (uint256);
// Get Token Name
function name() external view returns (string memory);
// Get Token URI
function tokenURI(uint256 tokenId) external view returns (string memory);
**/
Set Approval for Handler
Rinkeby/Moonbase Alpha ERC-721 Handler:
0xc6B836d5C269AbB5a7a81F35597b8d9c32ea8933
Kovan/Moonbase Alpha ERC-721 Handler:
0xfB736169b682027AF57D282B83952d2a82f41d55
*/
function approve(address to, uint256 tokenId) external;
// Check the address approved for a specific token ID
function getApproved(uint256 tokenId) external view returns (address);
}
Обратите внимание, что функция контракта токена ERC-721 также была изменена для утверждения соответствующего контракта обработчика в качестве спонсора при произведении токенов.
В Remix загрузите интерфейсный контракт по адресу исходного токена ERC721E (убедитесь, что Вы используете внедренный поставщик Web3 MetaMask). Затем вызовите функцию mintTokens() и подпишите транзакцию. После подтверждения транзакции Вы должны получить токен ERC721E. Вы можете проверить свой баланс, добавив токен в MetaMask.
Получив токен, мы можем приступить к его отправке через мост в исходную цепочку. В этом случае помните, что мы сделаем это от Kovana до Moonbase Alpha. Следующий интерфейс позволяет использовать функцию sendERC721EthToken()
для инициирования передачи токенов, изначально созданного в Kovan (ERC721E). Также, вы можете использовать функцию sendERC721MoonToken()
, чтобы инициировать передачу токенов, изначально созданных в Moonbase Alpha (ERC721M).
pragma solidity 0.6.4;
/**
Simple Interface to interact with bridge to transfer the ERC721 tokens
Rinkeby/Moonbase Alpha Bridge Address:
0xB8254105AC9EBAe528728bbdCDd1E060d8d24D08
Kovan/Moonbase Alpha Bridge Address:
0x89863493571c063171bE47e00c9404063eF1947A
*/
interface IPSBridgeERC721 {
/**
* @notice Creates a deposit in the Bridge Contract for an ERC-721 Transfer,
* @param _recipient Address recipient of the tokens in the other chain
* @param _tokenID Token ID of the token to be sent
*/
// For tokens minted in Rinkeby/Kovan (ECR721E)
function sendERC721EthToken(address _recipient, uint _tokenID) external;
// For tokens minted in Moonbase Alpha (ECR721M)
function sendERC721MoonToken(address _recipient, uint _tokenID) external;
}
Итак, еще раз, в Remix загрузите контракт интерфейса по адресу моста. Затем вызовите функцию sendERC721EthToken(), указав адрес получателя на другой стороне моста и идентификатор токена для передачи. MetaMask должен показать окно с просьбой подписать транзакцию. После подтверждения транзакции процесс может занять около 3-х минут, после чего вы должны получить тот же идентификатор токена в Moonbase Alpha!
Вы можете проверить свой баланс, добавив токен в MetaMask и подключив его к исходной сети, в нашем случае Moonbase Alpha.
Помните, что Вы также можете создать токены ERC721M в Moonbase Alpha и отправить их в Kovana. Важно всегда проверять допуск, предоставленный контракту обработчика в соответствующем контракте токена ERC721. Вы можете утвердить контракт обработчика для отправки токенов от Вашего имени, используя функцию approve(), предусмотренную в интерфейсе. Вы можете проверить одобрение каждого из ваших идентификаторов токенов с помощью функции getApproved().
Примечание:
Токены будут переданы только в том случае, если контракт обработчика утвержден на передачу токенов от имени владельца. Если процесс не удался, проверьте утверждение.
Универсальный обработчик
Универсальный обработчик предлагает возможность выполнения функции в цепочке A и создания предложения для выполнения другой функции в цепочке B (аналогично общей диаграмме рабочего процесса). Это обеспечивает удобный способ соединения двух независимых блоков цепочек.
Если вы заинтересованы в реализации этой функции, вы можете связаться с нами напрямую через наш сервер Discord. Будем рады обсудить эту реализацию.
Мы хотим услышать Ваше мнение!
Если у Вас есть какие-либо отзывы относительно исследования блоков или любой другой темы, связанной с Moonbeam, не стесняйтесь связаться с нами используя официальный канал разработки в Discord .
Подготовлено при участии: Denis Bradulin, Anpol, AntonM, Lyn.