Arbitrum dApp开发实战
本教程适用于想要开始使用 Arbitrum 构建去中心化应用程序 (dApp) 的 Web 开发人员,我们将使用 Solidity 智能合约构建一台数字纸杯蛋糕自动售货机。
一键发币: SOL | BNB | ETH | BASE | Blast | ARB | OP | POLYGON | AVAX | FTM | OK
本快速入门适用于想要开始使用 Arbitrum 构建去中心化应用程序 (dApp) 的 Web 开发人员。 它不会对你之前使用以太坊、Arbitrum 或 Solidity 的经验做出任何假设。 但希望你熟悉 Javascript 和yarn。 如果你是以太坊新手,请考虑在继续之前研究以太坊文档。
1、项目内容简介
我们将使用 Solidity 智能合约构建一台数字纸杯蛋糕自动售货机。 我们的自动售货机将遵循两条规则:
- 自动售货机将向最近没有收到纸杯蛋糕的人分发纸杯蛋糕。
- 自动售货机的规则是任何人都无法改变的。
这是我们用 Javascript 实现的自动售货机。 要使用它,请在下面的表格中输入名称,然后按“请纸杯蛋糕!” 按钮,你应该会看到您的纸杯蛋糕余额增加:
请注意,虽然这台自动售货机看起来遵守规则,但它并没有像我们希望的那样遵守规则。 自动售货机的业务逻辑和数据由中心化服务提供商托管。 我们相信该服务提供商不是恶意的,但是:
- 我们的集中式服务提供商可以拒绝特定用户的访问。
- 恶意行为者可以随时更改自动售货机的规则,例如,给他们的朋友额外的纸杯蛋糕。
集中式第三方中介机构代表了恶意行为者可能会利用的单点故障。 为了减轻这种类型的风险,我们可以分散自动售货机的业务逻辑和数据,从而使这种类型的利用变得不可行。
这就是 Arbitrum 的核心价值主张。 Arbitrum 使你可以轻松地将自动售货机部署到以太坊的无需许可、无需信任、去中心化的节点网络,同时为你和你的用户保持较低的成本。
让我们使用 Arbitrum 实现上述自动售货机的“web3”版本。
2、准备开发环境
先决条件如下:
- VS Code:我们将用来构建自动售货机的 IDE。 请参阅 code.visualstudio.com 进行安装。
- Metamask:我们将用来与自动售货机交互的钱包。 请参阅 metamask.io 进行安装。
- Yarn:我们将用来安装依赖项的包管理器。 请参阅yarnpkg.com 进行安装。
我们将继续解决剩余的依赖关系。
3、以太坊和Arbitrum
以太坊是一个去中心化的节点网络,使用以太坊的客户端软件(如 Offchain 的 Prysm)来维护公共区块链数据结构。
- 以太坊区块链数据结构中的数据一次更改一笔交易。
- 智能合约是根据预定义规则执行交易的小程序。 以太坊的节点托管并执行智能合约。
- 你可以使用智能合约构建去中心化应用程序 (dApp),这些应用程序使用以太坊网络来处理交易和存储数据。
- DApp 允许用户在应用程序之间携带数据和身份,而无需信任中心化服务提供商。
- 运行以太坊验证器节点3的人可以通过代表用户和 dApp 处理和验证交易来赚取 ETH。
- 当网络负载较重时,这些交易可能会很昂贵。
Arbitrum 是一套面向 dApp 开发人员的 L2 扩展解决方案:
- Arbitrum One 是一条实现 Arbitrum Rollup 协议的 L2 链。
- 你可以使用 Arbitrum One 构建用户友好的 dApp,具有高吞吐量、低延迟和低交易成本,同时继承以太坊的高安全标准。
让我们回顾一下自动售货机的 Javascript 实现,然后将其转换为 Solidity 智能合约,然后将其部署到 Arbitrum One。
我们将使用此页面上的自动售货机向你的智能合约询问纸杯蛋糕。
4、回顾Javascript 自动售货机
这是我们作为 Javascript 类实现的自动售货机:
class VendingMachine {
// state variables = internal memory of the vending machine
cupcakeBalances = {};
cupcakeDistributionTimes = {};
// Vend a cupcake to the caller
giveCupcakeTo(userId) {
if (this.cupcakeDistributionTimes[userId] === undefined) {
this.cupcakeBalances[userId] = 0;
this.cupcakeDistributionTimes[userId] = 0;
}
// Rule 1: The vending machine will distribute a cupcake to anyone who hasn't recently received one.
const fiveSeconds = 5000;
const userCanReceiveCupcake = this.cupcakeDistributionTimes[userId] + fiveSeconds <= Date.now();
if (userCanReceiveCupcake) {
this.cupcakeBalances[userId]++;
this.cupcakeDistributionTimes[userId] = Date.now();
console.log(`Enjoy your cupcake, ${userId}!`);
return true;
} else {
console.error(
'HTTP 429: Too Many Cupcakes (you must wait at least 5 seconds between cupcakes)',
);
return false;
}
}
getCupcakeBalanceFor(userId) {
return this.cupcakeBalances[userId];
}
}
VendingMachine
类使用状态变量和函数来实现预定义的规则。 这种实现很有用,因为它可以自动分发纸杯蛋糕,但有一个问题:它由第三方服务提供商控制的集中式服务器托管。
让我们通过将上述 Javascript 实现移植到 Solidity 智能合约中来分散自动售货机的业务逻辑和数据。
5、配置项目目录
为你的项目创建一个去中心化的纸杯蛋糕目录,并使用 VS Code 的集成终端安装安全帽:
mkdir decentralized-cupcakes
cd decentralized-cupcakes
yarn init -y
yarn add hardhat @nomicfoundation/hardhat-toolbox -D
这将安装两个软件包: hardhat
让我们编写、测试和部署智能合约, hardhat-toolbox
是我们稍后将使用的流行 Hardhat 插件的捆绑包。
接下来,运行 yarn Hardhat init
来配置Hardhat。 出现提示时选择创建 JavaScript 项目。 确保在询问时将 decentralized-cupcake
目录指定为项目根目录。
此时,应该在 decentralized-cupcake
目录中看到以下项目:
条目 | 说明 |
---|---|
contracts/ | 包含智能合约。 应该在此处看到 Lock.sol 合约。 |
scripts/ | 包含可用于与智能合约交互的脚本。 应该在这里看到deploy.js。 |
hardhat.config.js | 包含 Hardhat 的配置设置 |
将 hardhat.config.js
替换为以下内容:
require('@nomicfoundation/hardhat-toolbox');
// NEVER record important private keys in your code - this is for demo purposes
const SEPOLIA_TESTNET_PRIVATE_KEY = '';
const ARBITRUM_MAINNET_TEMPORARY_PRIVATE_KEY = '';
/** @type import('hardhat/config').HardhatUserConfig */
module.exports = {
solidity: '0.8.18',
networks: {
hardhat: {
chainId: 1337,
},
arbitrumSepolia: {
url: 'https://sepolia-rollup.arbitrum.io/rpc',
chainId: 421614,
//accounts: [Sepolia_TESTNET_PRIVATE_KEY]
},
arbitrumOne: {
url: 'https://arb1.arbitrum.io/rpc',
//accounts: [ARBITRUM_MAINNET_TEMPORARY_PRIVATE_KEY]
},
},
};
在编译默认合约之前,你需要安装额外的依赖项。 运行 yarn hardhat compile
并预计它第一次会失败 - 按照这些说明进行操作,然后再次运行 yarn hardhat compile
直到它成功运行。 你应该在终端输出中看到 Compiled 1 Solidity file successfully
,还应该看到一个新的 decentraled-cupcakes/artifacts/
目录, 该目录包含已编译的智能合约。
打开 script/deploy.js
并将其内容替换为以下内容:
const hre = require('hardhat');
async function main() {
const vendingMachine = await hre.ethers.deployContract('VendingMachine');
await vendingMachine.waitForDeployment();
console.log(`Cupcake vending machine deployed to ${vendingMachine.target}`);
}
main().catch((error) => {
console.error(error);
process.exit(1);
});
我们稍后将使用它来部署我们的智能合约。 接下来,删除 contracts/Lock.sol
并将其替换为 contracts/VendingMachine.sol
,这是我们的Javascript实现的更智能的替代方案:
pragma solidity ^0.8.9;
// Rule 2: The vending machine's rules can't be changed by anyone.
contract VendingMachine {
// state variables = internal memory of the vending machine
mapping(address => uint) private _cupcakeBalances;
mapping(address => uint) private _cupcakeDistributionTimes;
function giveCupcakeTo(address userAddress) public returns (bool) {
// this code is unnecessary, but we're keeping it here so you can compare it to the JS implementation
if (_cupcakeDistributionTimes[userAddress] == 0) {
_cupcakeBalances[userAddress] = 0;
_cupcakeDistributionTimes[userAddress] = 0;
}
// Rule 1: The vending machine will distribute a cupcake to anyone who hasn't recently received one.
uint fiveSecondsFromLastDistribution = _cupcakeDistributionTimes[userAddress] + 5 seconds;
bool userCanReceiveCupcake = fiveSecondsFromLastDistribution <= block.timestamp;
if (userCanReceiveCupcake) {
_cupcakeBalances[userAddress]++;
_cupcakeDistributionTimes[userAddress] = block.timestamp;
return true;
} else {
revert("HTTP 429: Too Many Cupcakes (you must wait at least 5 seconds between cupcakes)");
}
}
// Getter function for the cupcake balance of a user
function getCupcakeBalanceFor(address userAddress) public view returns (uint) {
return _cupcakeBalances[userAddress];
}
}
请注意,此智能合约是用 Solidity 编写的,这是一种编译为 EVM 字节码的语言。 这意味着它可以部署到任何与以太坊兼容的区块链,包括以太坊主网、Arbitrum One 和 Arbitrum Nova。
再次运行 yarn hardhat compile
, 应该在终端输出中看到 Compiled 1 Solidity file successfully
, 还应该看到一个新的 decentraled-cupcakes/artifacts/contracts/VendingMachine.sol
目录。
6、在本地部署智能合约
要在本地部署 VendingMachine 智能合约,我们将使用两个终端窗口和一个钱包:
- 我们将使用第一个终端窗口来运行 Hardhat 的内置本地以太坊节点
- 然后,我们将配置一个钱包,以便在将其部署到 (1) 后可以与智能合约进行交互
- 然后,我们将使用第二个终端窗口将智能合约部署到 (1) 的节点
6.1 运行本地以太坊网络和节点
从 decentralized-cupcake
目录运行 yarn hardhat node
,开始运行由单个节点支持的本地以太坊网络。 这将通过使用 Hardhat 的内置 Hardhat 网络来模仿以太坊在本地计算机上的行为。
应该在终端中看到类似 Started HTTP and WebSocket JSON-RPC server at http://127.0.0.1:8545/
的内容,还应该看到自动为你生成的许多测试帐户:
...
Account #0: 0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 (10000 ETH)
Private Key: 0xac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80
...
请注意,在本快速入门的上下文中,“帐户”是指公共钱包地址及其关联的私钥5。
6.2 配置Metamask
接下来,打开 Metamask 并按照显示的说明创建或导入钱包。 默认情况下,Metamask 将连接到以太坊主网。 要连接到我们的本地“测试网络”,请通过单击网络选择器下拉列表中的显示/隐藏测试网络来启用 Metamask 的测试网络。 然后选择 localhost 8545
网络:
你的主网钱包在本地测试网节点上不会有余额,但我们可以将其中一个测试账户导入 Metamask 以获得 10,000 个假 ETH 的访问权限。 复制其中一个测试帐户的私钥(无论有或没有 0x 前缀都可以使用,例如 0xac0..f80 或 ac0..f80)并将其导入 Metamask:
你应该会看到 10,000 ETH 的余额。 将私钥放在手边; 我们稍后会再次使用它。
接下来,单击 Metamask 的网络选择器下拉列表,然后单击“添加网络”按钮。 单击“手动添加网络”,然后提供以下信息:
- 网络名称:
Arbitrum Sepolia
- 新的 RPC URL:
https://sepolia-rollup.arbitrum.io/rpc
- 链ID:
421614
- 货币符号:
ASPL
当我们与纸杯蛋糕自动售货机交互时,我们将使用 Metamask 的网络选择器下拉列表来确定我们的纸杯蛋糕交易发送到哪个网络。 现在,我们将网络设置保留为 Localhost 8545
。
6.3 将智能合约部署到本地测试网
从另一个终端实例,运行 yarn add --dev @nomicfoundation/hardhat-ethers ethers Hardhat-deploy Hardhat-deploy-ethers
以安装合约部署所需的其他依赖项。 然后运行 yarn hardhat run scripts/deploy.js --network localhost
。 此命令会将你的智能合约部署到本地测试网的节点。 应该在终端中看到 Cupcake vending machine deployed to 0xe7f1725E7734CE288F8367e1Bb143E90bb3F0512
之类的内容。 0xe7...512 是你本地测试网中智能合约的地址。
确保在 Metamask 中选择本地主机网络。 然后复制并粘贴你的合约地址,然后单击“获取纸杯蛋糕!”。 系统应该提示你签署一笔交易,为你提供纸杯蛋糕:
我们的第一台自动售货机被标记为 WEB2,因为它演示了传统的 n 层 Web 应用程序架构:
WEB3-LOCALHOST 架构与 WEB2 架构类似,但有一个关键区别:在 WEB3 版本中,业务逻辑和数据位于(目前模拟的)去中心化节点网络中,而不是集中式服务器网络中。
让我们仔细看看 VendingMachine 实现之间的差异:
接下来,我们将把智能合约部署到真实节点网络:Arbitrum 的 Sepolia 测试网。
6.4 将智能合约部署到 Arbitrum Sepolia 测试网
我们能够免费部署到本地测试网,因为我们使用的是 Hardhat 的内置以太坊网络模拟器。 Arbitrum 的 Sepolia 测试网由真实节点的真实网络提供支持,因此我们需要支付少量交易费用来部署我们的智能合约。 该费用可以使用 Arbitrum Sepolia 测试网的代币 $ASPL 支付。
首先,更新 hardhat.config.js
文件以指定你将用于部署智能合约(并支付交易费用)的测试帐户的私钥:
// ...
const SEPOLIA_TESTNET_PRIVATE_KEY = ''; // <- this should **not** begin with "0x"
// ...
accounts: [SEPOLIA_TESTNET_PRIVATE_KEY]; // <- uncomment this line
// ...
接下来,我们将一些 $ASPL 存入与我们添加到 hardhat.config.js 的私钥对应的钱包中。 在撰写本快速入门时,获取 $ASPL 的最简单方法是将 Sepolia $ETH 从以太坊的 L1 Sepolia 网络桥接到 Arbitrum 的 L2 Sepolia 网络:
- 使用 L1 Sepolia $ETH 水龙头(如 sepoliafaucet.com)在 L1 Sepolia 上获取一些测试网 $ETH。
- 使用 Arbitrum 桥将你的 L1 Sepolia $ETH 桥接至 Arbitrum L2。
一旦获得了一些 $ASPL,你就可以通过发出以下命令将智能合约部署到 Arbitrum 的 Sepolia 测试网:
yarn hardhat run scripts/deploy.js --network arbitrumSepolia
这告诉hardhat通过hardhat.config.js中与arbitrumSepolia对应的RPC端点来部署已编译的智能合约。 你应该看到以下输出:
Cupcake vending machine deployed to 0xff825139321bd8fB8b720BfFC5b9EfDB7d6e9AB3
恭喜! 你刚刚将业务逻辑和数据部署到 Arbitrum Sepolia。 该逻辑和数据将在交易中进行哈希处理并提交到以太坊的 L1 Sepolia 网络,然后它将在 Sepolia 网络中的所有节点之间进行镜像。
要在区块链浏览器中查看您的智能合约,请访问 https://sepolia.arbiscan.io/address/0x...B3
,但将 URL 的 0x...B3
部分替换为你部署的智能合约的完整地址 。
从 Metamask 的下拉列表中选择 Arbitrum Sepolia,将你的合约地址粘贴到下面的自动售货机中,然后单击获取纸杯蛋糕! 系统应该提示签署一笔交易,为你提供纸杯蛋糕:
6.5 将智能合约部署到 Arbitrum One 主网
现在我们已经验证了我们的智能合约可以在 Arbitrum 的 Sepolia 测试网上运行,我们准备将其部署到 Arbitrum One 主网。 这与部署到 Arbitrum 的 Sepolia 测试网的过程相同,只是我们需要以真实的 ETH 美元而不是 ASPL 支付交易费用。
预计在此步骤中会看到不一致的 $ETH Gas 费 - Gas 和费用部分包含有关如何确定 Arbitrum 交易的 Gas 费的更多信息。
首先,更新 hardhat.config.js 文件以指定你将用于部署智能合约(并支付交易费用)的一次性部署帐户的私钥:
// ...
const ARBITRUM_MAINNET_TEMPORARY_PRIVATE_KEY = ''; // <- this should **not** begin with "0x"
// ...
accounts: [ARBITRUM_MAINNET_TEMPORARY_PRIVATE_KEY]; // <- uncomment this line
// ...
接下来,将一些$ETH存入与我们添加到hardhat.config.js的私钥对应的钱包中。 然后,可以通过发出以下命令将智能合约部署到 Arbitrum One 主网:
yarn hardhat run scripts/deploy.js --network arbitrumOne
你应该看到以下输出:
Cupcake vending machine deployed to 0xff825139321bd8fB8b720BfFC5b9EfDB7d6e9AB3
恭喜! 你刚刚通过 Arbitrum One2 将业务逻辑和数据部署到以太坊的去中心化节点网络。
要在区块链浏览器中查看你的智能合约,请访问 https://arbiscan.io/address/0x...B3
,但将 URL 的 0x...B3
部分替换为已部署的智能合约的完整地址。
从 Metamask 的下拉列表中选择 Arbitrum One,将你的合约地址粘贴到下面的自动售货机中,然后单击获取纸杯蛋糕! 系统应该提示签署一项交易,为你提供一个不可变的纸杯蛋糕:
7、结束语
在本快速入门中,我们:
- 确定了两个业务规则:1)公平且无需许可的纸杯蛋糕分发,2)不可变的业务逻辑和数据。
- 确定了一个挑战:这些规则在集中式应用程序中很难遵循。
- 确定了解决方案:Arbitrum 使开发人员可以轻松地分散业务逻辑和数据(使用以太坊主网作为结算层)。
- 将自动售货机的 Javascript 业务逻辑转换为 Solidity 智能合约。
- 将我们的智能合约部署到 Hardhat 的本地开发网络,然后是 Arbitrum 的 Sepolia 测试网,然后是 Arbitrum One 主网。
原文链接:Quickstart: Build a decentralized app with Arbitrum (Solidity, Hardhat)
DefiPlot翻译整理,转载请标明出处