当前位置: 首页 > wzjs >正文

wordpress图片分组seo需要懂代码吗

wordpress图片分组,seo需要懂代码吗,网站开发宣传语,微网站怎么做在《Arbitrum Stylus 深入解析与 Rust 合约部署实战》篇中,我们深入探讨了 Arbitrum Stylus 的核心技术架构,包括其 MultiVM 机制、Rust 合约开发环境搭建,以及通过 cargo stylus 实现简单计数器合约的部署与测试。Stylus 作为 Arbitrum Nitr…

在《Arbitrum Stylus 深入解析与 Rust 合约部署实战》篇中,我们深入探讨了 Arbitrum Stylus 的核心技术架构,包括其 MultiVM 机制、Rust 合约开发环境搭建,以及通过 cargo stylus 实现简单计数器合约的部署与测试。Stylus 作为 Arbitrum Nitro 的升级,允许开发者使用 Rust、C++ 等语言编写高效的 WebAssembly(WASM)合约,显著降低了 Gas 成本并提升了性能。本文将更进一步,使用 Rust 在 Stylus 上实现 ERC20  标准合约,并在 Arbitrum Sepolia 上完成部署实战,带您从代码到上链一步到位

1. 前置准备:开发环境与工具链

在开始编写 ERC20  合约之前,确保开发环境已正确配置,在我的《Arbitrum Stylus 深入解析与rust合约部署实战》中,已经有这段内容了,也可以移步到那里先配置好环境:

  • Rust 工具链:安装 Rust 和 Cargo
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source $HOME/.cargo/env
  • cargo-stylus 是 Stylus 合约开发的 CLI 工具,用于编译、检查和部署
cargo install --force cargo-stylus
  • WASM (WebAssembly)  设置 WASM 作为 Rust 编译器的构建目标,可以看到这里执行的第三个和第四个命令有重叠的地方,官方文档是只需要执行第四个命令,但是经过我的实践,有可能会报错,提示说需要执行第三个命令,看过我上一篇《Arbitrum Stylus 深入解析与rust合约部署实战》的观众就会知道有这个问题, 所以为了保险起见,这里一并执行了
rustup install 1.81
rustup default 1.81
rustup target add wasm32-unknown-unknown
rustup target add wasm32-unknown-unknown --toolchain 1.81
  • 安装好docker并启动 

2. ERC20 合约:设计与实现

ERC20 是代币标准,支持转账、余额查询等功能,关于ERC协议,我会专门出一期来讲,这里就不展开讲了。这里我们将实现一个简单的 ERC20 代币,我们先来创建项目:

cargo stylus new stylus-tokens

然后在 vscode 中打开项目,我是在 wsl 中,直接执行 code .   就OK。然后,我们修改rust-toolchain.toml 中的版本 为 1.81.0

 接下来我们在src 下面创建 erc20.rs 文件,并复制或者手敲一遍我给的代码,在代码中,每一行我都加上了详细的注释:

// 引入 alloc 模块中的 String 类型,用于动态字符串
use alloc::string::String;
// 引入 alloy_primitives 库中的 Address 和 U256 类型,用于处理以太坊地址和256位无符号整数
use alloy_primitives::{Address, U256};
// 引入 alloy_sol_types 库中的 sol 宏,用于定义 Solidity 风格的数据结构和事件
use alloy_sol_types::sol;
// 引入 PhantomData,用于在泛型中占位,标记类型但不实际存储数据
use core::marker::PhantomData;
// 引入 stylus_sdk 的 msg evm 和 prelude 模块,提供以太坊虚拟机交互和消息处理功能
use stylus_sdk::{evm, msg, prelude::*};// 定义 Erc20Params 特质,用于指定 ERC20 代币的静态参数
pub trait Erc20Params {const NAME: &'static str; // 代币名称,静态字符串const SYMBOL: &'static str; // 代币符号,静态字符串const DECIMALS: u8; // 代币小数位数
}// 使用 sol_storage 宏定义 Solidity 风格的存储结构
sol_storage! {// 定义泛型结构体 Erc20,T 需实现 Erc20Params 特质pub struct Erc20<T> {// 地址到余额的映射,存储每个地址的代币余额mapping(address => uint256) balances;// 地址到授权额度的映射,记录每个地址对其他地址的代币授权mapping(address => mapping(address => uint256)) allowances;// 代币总供应量uint256 total_supply;// 占位符,确保泛型 T 被使用但不占用存储空间PhantomData<T> phantom;}
}// 使用 sol 宏定义 Solidity 风格的事件和错误
sol! {// 定义 Transfer 事件,记录代币转账信息event Transfer(address indexed from, address indexed to, uint256 value);// 定义 Approval 事件,记录代币授权信息event Approval(address indexed owner, address indexed spender, uint256 value);// 定义错误:余额不足error InsufficientBalance(address from, uint256 have, uint256 want);// 定义错误:授权额度不足error InsufficientAllowance(address owner, address spender, uint256 have, uint256 want);
}// 标记 Erc20Error 为 Solidity 风格的错误类型
#[derive(SolidityError)]// 定义 ERC20 错误枚举
pub enum Erc20Error {// 余额不足错误InsufficientBalance(InsufficientBalance),// 授权额度不足错误InsufficientAllowance(InsufficientAllowance),
}// 为 Erc20 结构体实现方法,T 需实现 Erc20Params 特质
impl<T: Erc20Params> Erc20<T> {// 内部转账函数,执行代币转账逻辑pub fn _transfer(&mut self, from: Address, to: Address, value: U256) -> Result<(), Erc20Error> {// 获取发送者余额的 setterlet mut sender_balance = self.balances.setter(from);// 获取发送者的当前余额let old_sender_balance = sender_balance.get();if old_sender_balance < value {// 检查发送者余额是否足够return Err(Erc20Error::InsufficientBalance(InsufficientBalance {// 返回余额不足错误from,                     // 发送者地址have: old_sender_balance, // 当前余额want: value,              // 所需金额}));}// 扣除发送者余额sender_balance.set(old_sender_balance - value);// 获取接收者余额的 setterlet mut to_balance = self.balances.setter(to);// 计算接收者的新余额let new_to_balance = to_balance.get() + value;// 更新接收者余额to_balance.set(new_to_balance);// 记录转账事件到 EVM 日志evm::log(Transfer { from, to, value });Ok(())}// 铸造代币函数pub fn mint(&mut self, address: Address, value: U256) -> Result<(), Erc20Error> {// 获取目标地址余额的 setterlet mut balance = self.balances.setter(address);// 计算新余额let new_balance = balance.get() + value;// 更新目标地址余额balance.set(new_balance);// 增加总供应量self.total_supply.set(self.total_supply.get() + value);// 记录铸造事件(从零地址转账)evm::log(Transfer {from: Address::ZERO, // 零地址表示铸造to: address,         // 目标地址value,               // 铸造数量});Ok(())}// 销毁代币函数pub fn burn(&mut self, address: Address, value: U256) -> Result<(), Erc20Error> {// 获取目标地址余额的 setterlet mut balance = self.balances.setter(address);// 获取当前余额let old_balance = balance.get();if old_balance < value {// 检查余额是否足够销毁return Err(Erc20Error::InsufficientBalance(InsufficientBalance {// 返回余额不足错误from: address,     // 目标地址have: old_balance, // 当前余额want: value,       // 所需销毁金额}));}// 扣除余额balance.set(old_balance - value);// 减少总供应量self.total_supply.set(self.total_supply.get() - value);// 记录销毁事件(转账到零地址)evm::log(Transfer {from: address,     // 目标地址to: Address::ZERO, // 零地址表示销毁value,             // 销毁数量});Ok(())}
}// 标记以下方法为公开,暴露给外部调用
#[public]
// 为 Erc20 实现公开方法
impl<T: Erc20Params> Erc20<T> {// 返回代币名称pub fn name() -> String {// 将静态名称转换为 StringT::NAME.into()}// 返回代币符号pub fn symbol() -> String {// 将静态符号转换为 StringT::SYMBOL.into()}// 返回代币小数位数pub fn decimals() -> u8 {// 返回静态小数位数T::DECIMALS}// 返回代币总供应量pub fn total_supply(&self) -> U256 {// 获取存储中的总供应量self.total_supply.get()}// 查询指定地址的余额pub fn balance_of(&self, owner: Address) -> U256 {// 从映射中获取余额self.balances.get(owner)}// 转账函数pub fn transfer(&mut self, to: Address, value: U256) -> Result<bool, Erc20Error> {// 调用内部转账函数,从调用者转账self._transfer(msg::sender(), to, value)?;Ok(true)}// 授权转账函数,允许 spender 从 from 地址转账pub fn transfer_from(&mut self,from: Address,to: Address,value: U256,) -> Result<bool, Erc20Error> {// 获取 from 地址的授权映射let mut sender_allowances = self.allowances.setter(from);// 获取调用者的授权额度let mut allowance = sender_allowances.setter(msg::sender());// 获取当前授权额度let old_allowance = allowance.get();// 检查授权额度是否足够if old_allowance < value {// 返回授权不足错误return Err(Erc20Error::InsufficientAllowance(InsufficientAllowance {owner: from,            // 拥有者地址spender: msg::sender(), // 花费者地址have: old_allowance,    // 当前授权额度want: value,            // 所需授权额度}));}// 扣除授权额度allowance.set(old_allowance - value);// 执行转账self._transfer(from, to, value)?;Ok(true)}// 授权函数,允许 spender 花费指定金额pub fn approve(&mut self, spender: Address, value: U256) -> bool {// 设置授权额度self.allowances.setter(msg::sender()).insert(spender, value);// 记录授权事件evm::log(Approval {owner: msg::sender(), // 授权者地址spender,              // 被授权者地址value,                // 授权金额});true}// 查询授权额度pub fn allowance(&self, owner: Address, spender: Address) -> U256 {// 从映射中获取指定授权额度self.allowances.getter(owner).get(spender)}
}

接着在 src 文件夹 中创建 lib.rs:

// 条件编译属性:除非启用 export-abi 或 test 功能,否则不生成 main 函数
#![cfg_attr(not(any(feature = "export-abi", test)), no_main)]
// 引入 alloc 模块,支持动态内存分配
extern crate alloc;
// 引入 erc20 模块,包含 ERC20 代币逻辑
mod erc20;// 从 erc20 模块导入 Erc20 结构体、错误类型和参数特质
use crate::erc20::{Erc20, Erc20Error, Erc20Params};
// 引入 Address 和 U256 类型
use alloy_primitives::{Address, U256};
// 引入 stylus_sdk 的消息处理和预定义功能
use stylus_sdk::{msg, prelude::*};// 定义 StylusTokenParams 结构体,用于指定代币参数
struct StylusTokenParams;
// 为 StylusTokenParams 实现 Erc20Params 特质
impl Erc20Params for StylusTokenParams {const NAME: &'static str = "StylusToken";const SYMBOL: &'static str = "STK";// 代币小数位数:18const DECIMALS: u8 = 18;
}// 使用 sol_storage 宏定义存储结构
sol_storage! {// 标记 StylusToken 为合约入口点#[entrypoint]// 定义 StylusToken 结构体struct StylusToken {// 标记 erc20 字段为借用,继承 Erc20 功能#[borrow]// 嵌入 Erc20 结构体,使用 StylusTokenParams 参数Erc20<StylusTokenParams> erc20;}
}// 标记以下方法为公开
#[public]
// 继承 Erc20<StylusTokenParams> 的方法
#[inherit(Erc20<StylusTokenParams>)]
// 为 StylusToken 实现方法
impl StylusToken {// 铸造代币到调用者地址pub fn mint(&mut self, value: U256) -> Result<(), Erc20Error> {// 调用 Erc20 的 mint 方法self.erc20.mint(msg::sender(), value)?;Ok(())}// 铸造代币到指定地址pub fn mint_to(&mut self, to: Address, value: U256) -> Result<(), Erc20Error> {// 调用 Erc20 的 mint 方法self.erc20.mint(to, value)?;Ok(())}// 销毁调用者的代币pub fn burn(&mut self, value: U256) -> Result<(), Erc20Error> {// 调用 Erc20 的 burn 方法self.erc20.burn(msg::sender(), value)?;Ok(())}
}

接着是 main.rs 中的内容:

 // 条件编译属性:除非启用 test 或 export-abi 功能,否则不生成 main 函数
#![cfg_attr(not(any(test, feature = "export-abi")), no_main)]// 条件编译:当 test 和 export-abi 均未启用时
#[cfg(not(any(test, feature = "export-abi")))] // 禁止名称修饰,确保函数名在编译后保持不变
#[no_mangle]
// 定义空的 main 函数,用于合约入口
pub extern "C" fn main() {} // 条件编译:当启用 export-abi 功能时
#[cfg(feature = "export-abi")] 
// 定义 main 函数,用于导出 ABI
fn main() { // 调用 print_abi 函数,生成 Solidity ABI,指定许可证和 Solidity 版本stylus_tokens::print_abi("MIT-OR-APACHE-2.0", "pragma solidity ^0.8.23;"); 
}

Cargo.toml 中的配置:

[package]
name = "stylus_tokens"
version = "0.1.11"
edition = "2021"
license = "MIT OR Apache-2.0"
homepage = "https://github.com/OffchainLabs/stylus-hello-world"
repository = "https://github.com/OffchainLabs/stylus-hello-world"
keywords = ["arbitrum", "ethereum", "stylus", "alloy"]
description = "Stylus tokens example"[dependencies]
alloy-primitives = "=0.8.20"
alloy-sol-types = "=0.8.20"
mini-alloc = "0.4.2"
stylus-sdk = "0.8.0"
hex = "0.4.3"
dotenv = "0.15.0"[dev-dependencies]
tokio = { version = "1.12.0", features = ["full"] }
ethers = "2.0"
eyre = "0.6.8"[features]
export-abi = ["stylus-sdk/export-abi"]
debug = ["stylus-sdk/debug"][[bin]]
name = "stylus_tokens"
path = "src/main.rs"[lib]
crate-type = ["lib", "cdylib"][profile.release]
codegen-units = 1
strip = true
lto = true
panic = "abort"
opt-level = "s"

3. 合约部署上链并mint代币

一切准备就绪之后,我们来编译并且在链上验证我们的代码:

cargo stylus check -e https://sepolia-rollup.arbitrum.io/rpc

我们将一些参数导出成变量

export ARB_RPC_URL=https://sepolia-rollup.arbitrum.io/rpc
export PRIVATE_KEY=你的私钥

然后我们 可以来估算部署合约所需的 gas,这一个步骤不是必需的:

cargo stylus deploy --endpoint=$ARB_RPC_URL --private-key=$PRIVATE_KEY --estimate-gas

OK,开始部署:

cargo stylus deploy --endpoint=$ARB_RPC_URL --private-key=$PRIVATE_KEY

到这里已经部署成功,可以看到合约地址与交易hash,接下来我们开始铸造代币,如果你没有安装 foundry,(foundry 我会出一期详细的教程),请参考我的《Arbitrum Stylus 深入解析与rust合约部署实战》中的方式,导出ABI,然后在 remix 中去操作,这里我使用 foundry cast 命令去mint 代币:

cast send --rpc-url $ARB_RPC_URL --private-key $PRIVATE_KEY 0xb032fb53175b9c24ac157f4a7896ad200fd93468 "mint(uint256)" 100000000000000000000000000

可以看到我成功mint了一亿枚代币,因为有18位小数,所以在你想要mint的数量后面,再加上18个0,0xb032fb53175b9c24ac157f4a7896ad200fd93468  是合约的地址,到时候替换成你们部署成功的合约地址,我们去钱包导入代币,看看代币有没有到账:

可以看到我们代币已经到账了,接下来演示使用命令查看某个地址的代币余额:

OK,如果你走到了这里,恭喜你,你已经完成了 使用 Rust 在 Stylus 上实现 ERC20 合约,重复是最好的老师,希望大家多多练习,后面我也会继续更新系列教程,我是红烧6,关注我,带你上车 web3!

 Arbitrum官方文档:官方文档

stylus 官方示例:stylus-by-example

代码仓库:stylus-tokens

http://www.dtcms.com/wzjs/75768.html

相关文章:

  • 网站开发与设计专业百度seo自动优化
  • 做自己的网站餐饮营销策划与运营
  • 大学做视频网站如何自己做网络推广
  • 如何维护企业电子商务网站建设郑州做网络优化的公司
  • 外贸服饰网站建设福建百度代理公司
  • 自己服务器做网站服务器备案seo企业培训班
  • wordpress 相互关注搜狗搜索引擎优化指南
  • 建设网站主要有哪些技术网络营销讲师
  • 建设银行个人手机银行下载快抖霸屏乐云seo
  • 网站 建设 业务需求表杭州网络优化公司排名
  • 房地产开发公司网站建设方案郑州千锋教育培训机构怎么样
  • 微信公众号平台登录入口新网站seo
  • 电子商务网站建设课件seo优化公司排名
  • 昆明医院网站建设制作一个网站的全过程
  • 网站建设推广语百度云搜索资源入口
  • 制作大型网站开发营销型网站建设怎么做
  • 网站开发产品需求说明优化网络的软件
  • 2010年最具人气的平面设计师必备网站广东网站seo营销
  • 公司官方网站一般什么公司做google推广专员招聘
  • 做网站需注重的几点搜狗收录提交入口
  • 织梦手机网站制作教程营销策划与运营团队
  • 网站关于我们怎么做单页面模板上海网站建设开发
  • python在线运行seo外包资讯
  • 潍坊网站设计企业管理8大系统
  • 网站流量劫持怎么做广告主平台
  • 魔都网站建设百度免费推广方法
  • 做网站销售门窗怎么做徐州百度seo排名优化
  • 如何做网站连接深圳网站优化公司哪家好
  • wordpress php.ini在哪里关键词推广优化app
  • 做网站开发淘宝权重查询入口