译文出自:登链翻译计划[1] 译者:翻译小组[2] 校对:Tiny 熊[3]
Openzeppelin 合约首次增加了跨链支持,特别是目前支持以下链:
在跨链通信中到底有哪些需要考虑的事情呢?
msg.sender
实际上是一个子链上的地址。当然 msg.sender
到底是什么取决于子链,但它不会是根链的实际交易者地址。function processMessageFromRoot(
uint256, /* stateId */
address rootMessageSender,
bytes calldata data
)
AMB_Bridge(bridge).messageSender()
LibArbitrumL2.crossChainSender(LibArbitrumL2.ARBSYS)
Optimism_Bridge(messenger).xDomainMessageSender()
关于完整的细节,请查看这里的合约代码[14],相应的文档在这里[15]。
让我们以 Polygon 为例,深入了解一下如何实际使用 Openzeppelin 跨链功能。
我们将在根链(Root chain)和子链(child chain)上创建具有安全访问控制的合约。
首先让我们创建一个合约,并在根链上部署。在正常情况下,通常是以太坊主网。我们可以继承FxBaseRootTunnel.sol[16]合约,并根据网络的不同传递检查点和根地址。
import {FxBaseRootTunnel} from
"fx-portal/contracts/tunnel/FxBaseRootTunnel.sol";
// see left for full addresses
address constant GOERLI_CP_MANAGER = 0x2890bA17EfE978480615e...;
address constant GOERLI_FX_ROOT = 0x3d1d3E34f7fB6D26245E6640...;
contract PolygonRoot is FxBaseRootTunnel {
bytes public latestData;
constructor()
FxBaseRootTunnel(GOERLI_CP_MANAGER, GOERLI_FX_ROOT) {
}
function _processMessageFromChild(
bytes memory data
) internal override {
latestData = data;
}
function sendMessageToChild(bytes memory message) public {
_sendMessageToChild(message);
}
}
它有两个内部函数:
_processMessageFromChild
: 重写(Override)函数,以便处理从子合约发来的消息。_sendMessageToChild
:调用函数来向子合约发送消息。然后我们在子链上创建部署子合约,在我们的案例中,子链是 Polygon 网络。我们可以继承 Openzeppelin CrossChainEnabledPolygonChild.sol[17]合约,并根据网络的情况传递 FX Portal 子合约。
也可以使用 Openzeppelin 的AccessControlCrossChain.sol[18]。只要在合约中继承它,我们就会得到通常的访问控制功能[19]以及一个新的_crossChainRoleAlias
函数。
import {CrossChainEnabledPolygonChild} from
"oz/contracts/crosschain/polygon/CrossChainEnabledPolygonChild.sol";
import {AccessControlCrossChain} from
"oz/contracts/access/AccessControlCrossChain.sol";
address constant MUMBAI_FX_CHILD = 0xCf73231F...; // see right
contract PolygonChild is
CrossChainEnabledPolygonChild,
AccessControlCrossChain
{
event MessageSent(bytes message);
uint256 public myNumber = 12;
constructor(
address rootParent
) CrossChainEnabledPolygonChild(MUMBAI_FX_CHILD) {
_grantRole(
_crossChainRoleAlias(DEFAULT_ADMIN_ROLE),
rootParent
);
}
function setNumberForParentChain(
uint256 newNumber
) external onlyRole(DEFAULT_ADMIN_ROLE) {
myNumber = newNumber;
}
function _sendMessageToRoot(
bytes memory message
) internal {
emit MessageSent(message);
}
}
在示例中,在部署时,我们将把先前部署的根合约地址传到这里,并立即授予它管理角色,但由于这实际上是一个跨链通信,它的工作方式有点不同:
_crossChainRoleAlias
来授予角色权限。然后我们添加一个测试函数setNumberForParentChain
,只允许 CrossChain 的根合约调用。
为了完整起见,如果你想把信息发回给根,可以在 Polygon 中通过发出 MessageSent 事件来实现。
这个部署是可选的,但是处于我们的测试需要,你可以添加一个额外的函数,就像这样:
function getEncodedSetNumberData(uint256 newNumber) external pure returns (bytes memory) {
return abi.encodeWithSelector(PolygonChild.setNumberForParentChain.selector, newNumber);
}
基本上这个函数就是返回要调用函数的编码数据,如果你想调用 setNumberForParentChain 函数,你需要获得它的编码数据,你需要通过sendMessageToChild
在根合约中发送这个数据。当然,在大多数环境中,你只是在使用 Web3.js 或任何你所使用的前端框架来获得编码数据。
好了,现在让我们把它部署到测试网,我们这里使用:
对比部署到正式主网,流程是相同的,只是使用的地址不同。
所以我们可以直接把这里的全部代码复制到 Remix 中:
// SPDX-License-Identifier: MIT
pragma solidity 0.8.13;
import {CrossChainEnabledPolygonChild} from "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/crosschain/polygon/CrossChainEnabledPolygonChild.sol";
import {AccessControlCrossChain} from "https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/access/AccessControlCrossChain.sol";
import {FxBaseRootTunnel} from "https://github.com/fx-portal/contracts/blob/main/contracts/tunnel/FxBaseRootTunnel.sol";
address constant MUMBAI_FX_CHILD = 0xCf73231F28B7331BBe3124B907840A94851f9f11;
address constant GOERLI_CHECKPOINT_MANAGER = 0x2890bA17EfE978480615e330ecB65333b880928e;
address constant GOERLI_FX_ROOT = 0x3d1d3E34f7fB6D26245E6640E1c50710eFFf15bA;
address constant MAINNET_FX_CHILD = 0x8397259c983751DAf40400790063935a11afa28a;
address constant MAINNET_CHECKPOINT_MANAGER = 0x86E4Dc95c7FBdBf52e33D563BbDB00823894C287;
address constant MAINNET_FX_ROOT = 0xfe5e5D361b2ad62c541bAb87C45a0B9B018389a2;
contract PolygonChild is CrossChainEnabledPolygonChild, AccessControlCrossChain {
uint256 public myNumber;
constructor(address rootParent) CrossChainEnabledPolygonChild(MUMBAI_FX_CHILD) {
_grantRole(_crossChainRoleAlias(DEFAULT_ADMIN_ROLE), rootParent);
myNumber = 12;
}
function setNumberForParentChain(uint256 newNumber) external onlyRole(DEFAULT_ADMIN_ROLE) {
myNumber = newNumber;
}
function getEncodedSetNumberData(uint256 newNumber) external pure returns (bytes memory) {
return abi.encodeWithSelector(PolygonChild.setNumberForParentChain.selector, newNumber);
}
}
contract PolygonRoot is FxBaseRootTunnel {
bytes public latestData;
constructor() FxBaseRootTunnel(GOERLI_CHECKPOINT_MANAGER, GOERLI_FX_ROOT) {}
function _processMessageFromChild(bytes memory data) internal override {
latestData = data;
}
function sendMessageToChild(bytes memory message) public {
_sendMessageToChild(message);
}
}
现在你可以:
setFxChildTunnel
,传递子合约地址。setNumberForParentChain
的数字设置为 42,编码后的数据是:0x21148d91000000000000000000000000000000000000000000000000000000000000002a. 最简单的方法是通过getEncodedSetNumberData
帮方法来获得。这些交易看起来可能让你感到困惑,但它并不奇怪。零地址是 Polygon 的一个特殊系统地址,用于提交 CrossChain 调用。
在我的测试中,直到 Polygon 上的 CrossChain 转账完成,需要 2 到 25 分钟。
跨链调用到这里就完成了,如果一切都正确,你可以切换回 Mumbai 测试网,并读取新设置的数字,它应该已经变成了 42。
本翻译由 Duet Protocol[25] 赞助支持。
原文:https://soliditydeveloper.com/openzeppelin-crosschain
[1]
登链翻译计划: https://github.com/lbc-team/Pioneer
[2]
翻译小组: https://learnblockchain.cn/people/412
[3]
Tiny 熊: https://learnblockchain.cn/people/15
[4]
Polygon: https://polygon.technology/
[5]
这篇文章: https://soliditydeveloper.com/deploy-to-matic
[6]
Optimism: https://www.optimism.io/
[7]
在这篇文章: https://soliditydeveloper.com/optimism
[8]
Arbitrum: https://arbitrum.io/
[9]
AMB: https://docs.tokenbridge.net/amb-bridge/about-amb-bridge
[10]
EIP-712: https://eips.ethereum.org/EIPS/eip-712
[11]
CrossChainEnabled.sol: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/crosschain/CrossChainEnabled.sol
[12]
AccessControlCrossChain.sol: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/access/AccessControlCrossChain.sol
[13]
这里: https://docs.openzeppelin.com/contracts/4.x/api/crosschain
[14]
这里的合约代码: https://github.com/OpenZeppelin/openzeppelin-contracts/tree/master/contracts/crosschain
[15]
这里: https://docs.openzeppelin.com/contracts/4.x/api/crosschain
[16]
FxBaseRootTunnel.sol: https://github.com/fx-portal/contracts/blob/main/contracts/tunnel/FxBaseRootTunnel.sol
[17]
CrossChainEnabledPolygonChild.sol: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.6.0/contracts/crosschain/polygon/CrossChainEnabledPolygonChild.sol
[18]
AccessControlCrossChain.sol: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.6.0/contracts/access/AccessControlCrossChain.sol
[19]
访问控制功能: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.6.0/contracts/access/AccessControl.sol
[20]
CrossChainEnabled.sol: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/v4.6.0/contracts/crosschain/CrossChainEnabled.sol
[21]
Goerli: https://goerli.net/
[22]
Mumbai: https://docs.polygon.technology/docs/develop/network-details/network#mumbai-testnet
[23]
这里: https://mumbai.polygonscan.com/address/0xcf73231f28b7331bbe3124b907840a94851f9f11#events
[24]
这里: https://mumbai.polygonscan.com/address/0x0000000000000000000000000000000000000000
[25]
Duet Protocol: https://duet.finance/?utm_souce=learnblockchain