- A+
课程总结:
- 托管智能合约消除了对传统第三方中介机构的需求。
- 智能合约被编码在区块链中,使其安全、透明和防篡改。
- 参与者学习使用区块链编程语言构建托管智能合约。
- 在区块链平台上测试和部署托管智能合约是我们课程的一个重要方面。
课程目标:
在课程结束时,你会学习到:
- 了解托管智能合约的概念及其运作方式。
- 获得构建托管智能合约的实践经验。
- 使用自己的函数读取程序状态。
- 了解如何测试托管智能合约
让我们开始吧!
托管是第三方临时持有交易资产的约定。资产保存在第三方账户中,只有在满足所有协议条款后才会释放。在交易中使用托管账户为双方增加了安全性。
将托管智能合约编码到区块链中,可以在没有传统第三方的情况下安全地执行合约。
智能合约中的托管如何运作
- 买方和卖方同意托管条款。卖方列出待售物品,买方支付商定的价格。
- 卖方交付产品,资金保存在托管智能合约中,直到满足所有条件且买方确认收到产品。
- 一旦买家认可产品,资金将通过智能合约自动转入卖家的数字钱包。
托管项目编码实践
让我们使用以下命令创建一个新项目:
cargo new escrow --lib
我们需要将必要的依赖项添加到 Cargo.toml
文件并创建一个 build.rs
文件(类似于 hello-world 课程)。
程序必须存储多个状态才能正确执行逻辑。这些状态包括买卖双方的地址、产品价格和交易状态。
AwaitingPayment
:卖家列出了待售商品,但买家尚未付款;AwaitingDelivery
:买家将资金转入到智能合约,卖家发货;Closed
:买家确认发货,卖家收到款项。
在枚举中定义这些状态:
enum EscrowState { AwaitingPayment, AwaitingDelivery, Closed, }
接下来,让我们定义存储所有必要状态的结构:
struct Escrow { seller: ActorId, buyer: ActorId, price: u128, state: EscrowState, }
我们还需要一个全局变量,它将在合约执行期间发生变化。我们将使用 static mut
结构来实现这一点:
static mut ESCROW: Option<Escrow> = None;
在程序初始化之前,ESCROW 值等于 None。在初始化的时候,我们会用信息填充 Escrow 结构,ESCROW 会变成 Some(Escrow)
。
这是具有最小 Gear 智能合约结构的完整代码:
#![no_std] use gstd::{msg, ActorId, prelude::*}; enum EscrowState { AwaitingPayment, AwaitingDelivery, Closed, } struct Escrow { seller: ActorId, buyer: ActorId, price: u128, state: EscrowState, } static mut ESCROW: Option<Escrow> = None; #[no_mangle] unsafe extern "C" fn handle () {} #[no_mangle] unsafe extern "C" fn init () {}
使用 cargo build --release
命令构建项目并确保一切正常。
然后我们将描述和编写 init
函数。
让我们定义将在初始化期间发送的 InitEscrow
消息负载。该结构需要实现编码和解码的 Encode 和 Decode trait,以及用于读取状态的 TypeInfo trait。
#[derive(Encode, Decode, TypeInfo)] pub struct InitEscrow { pub seller: ActorId, pub buyer: ActorId, pub price: u128, }
在 init 函数中,我们将定义买方和卖方的地址,以及产品价格。我们将使用 msg::load()
加载消息并使用 InitEscrow
结构对其进行解码。然后,我们将使用该信息创建一个新的 Escrow 结构并将状态设置为 EscrowState::AwaitingPayment
。最后,我们将 ESCROW 设置为 Some(escrow)
。
让我们在 init 函数中加载消息并定义合约状态:
#[no_mangle] unsafe extern "C" fn init () { let init_config: InitEscrow = msg::load().expect("Error in decoding `InitEscrow`"); let escrow = Escrow { seller: init_config.seller, buyer: init_config.buyer, price: init_config.price, state: EscrowState::AwaitingPayment, }; ESCROW = Some(escrow); }
现在,我们将编写托管合约逻辑。合约将处理以下消息:
- 带有附加资金的买方消息。托管合约检查:
- 托管状态为
AwaitingPayment
; - 发款人地址等于买方地址;
- 附加资金等于产品价格。
然后,合约设置托管状态为 AwaitingDelivery
,并发送入金成功的回复。
- 买方确认收到货物的消息。托管合约检查:
- 托管状态为
AwaitingDelivery
; - 发款人的地址等于买方的地址。
- 托管状态为
然后合约将托管状态设置为已关闭,将资金发送给卖方,并发送关于托管关闭成功的回复。
非常好!现在,我们需要声明传入和传出消息的枚举,托管结构的方法,并实现 handle
函数。
#[derive(Encode, Decode, TypeInfo)] pub enum EscrowAction { Deposit, ConfirmDelivery, } #[derive(Encode, Decode, TypeInfo)] pub enum EscrowEvent { FundsDeposited, DeliveryConfirmed, } impl Escrow { fn deposit(&mut self) {} fn confirm_delivery(&mut self) {} } #[no_mangle] unsafe extern "C" fn handle() { let action: EscrowAction = msg::load().expect("Unable to decode `EscrowAction`"); let escrow: &mut Escrow = ESCROW.get_or_insert(Default::default()); match action { EscrowAction::Deposit => escrow.deposit(), EscrowAction::ConfirmDelivery => escrow.confirm_delivery(), } }
请注意,我们必须为托管结构实现默认 trait。让我们在 Escrow 结构上方添加 #[derive(Default)]
并为 EscrowState
枚举实现该 trait:
impl Default for EscrowState { fn default() -> Self { Self::AwaitingPayment } }
让我们实现存款方法:
- 我们将检查合约状态是否等于 AwaitingDelivery(为此,我们必须在 EscrowState 枚举上添加
#[derive(Debug,PartialEq, Eq)]
:
assert_eq!( self.state, EscrowState::AwaitingPayment, "State must be `AwaitingPayment" );
- 然后检查发款人帐户(要获取发送当前正在处理的消息的帐户的 ActorId,使用 gstd 库中 msg 模块的 source() 函数):
assert_eq!( msg::source(), self.buyer, "The message sender must be a buyer" );
- 并检查附加资金(要获取附加到正在处理的消息的值,使用 gstd 库中 msg 模块的 value() 函数):
assert_eq!( msg::value(), self.price, "The attached value must be equal to set price" );
- 最后,我们更改托管状态并发送回复消息:
self.state = EscrowState::AwaitingDelivery; msg::reply(EscrowEvent::FundsDeposited, 0) .expect("Error in reply `EscrowEvent::FundsDeposited");
使用自己的函数读取程序状态
在上一课中,我们学习了如何使用合约中的状态函数读取完整的程序状态。此外,你可以创建自己的库,其中包含读取合约状态的函数。
通过添加程序元数据来扩展托管程序的功能。我们首先在托管程序的目录中创建一个 escrow-io:
cargo new io --lib
该项目的 Cargo.toml
文件将包含以下内容:
[package] name = "escrow-io" version = "0.1.0" edition = "2021" [dependencies] gmeta = { git = "https://github.com/gear-tech/gear.git" } gstd = { git = "https://github.com/gear-tech/gear.git" } codec = { package = "parity-scale-codec", version = "3.1.2", default-features = false, features = ["derive", "full"] } scale-info = { version = "2.0.1", default-features = false, features = ["derive"] }
现在我们可以将 InitEscrow
、EscrowAction
、EscrowEvent
、EscrowState
和 Escrow
移动到 rust 项目,并按如下方式定义 ProgramMetadata
:
#![no_std] use gmeta::{InOut, Metadata}; use gstd::{prelude::*, ActorId}; use scale_info::TypeInfo; pub struct ProgramMetadata; impl Metadata for ProgramMetadata { type Init = InOut<InitEscrow, ()>; type Handle = InOut<EscrowAction, EscrowEvent>; type Reply = InOut<(), ()>; type Others = InOut<(), ()>; type Signal = (); type State = EscrowState; } #[derive(Encode, Decode, TypeInfo)] pub struct InitEscrow { pub seller: ActorId, pub buyer: ActorId, pub price: u128, } #[derive(Encode, Decode, TypeInfo)] pub enum EscrowAction { Deposit, ConfirmDelivery, } #[derive(Encode, Decode, TypeInfo)] pub enum EscrowEvent { FundsDeposited, DeliveryConfirmed, } #[derive(Debug, PartialEq, Eq, Encode, Decode, TypeInfo)] pub enum EscrowState { AwaitingPayment, AwaitingDelivery, Closed, } impl Default for EscrowState { fn default() -> Self { Self::AwaitingPayment } } #[derive(Default, Encode, Decode, TypeInfo)] pub struct Escrow { pub seller: ActorId, pub buyer: ActorId, pub price: u128, pub state: EscrowState, }
要将状态函数添加到 escrow-io,包括:
#[no_mangle] extern "C" fn state() { let escrow = unsafe { ESCROW.get_or_insert(Default::default()) }; msg::reply(escrow, 0).expect("Failed to share state"); }
向托管程序的 Cargo.toml
中添加依赖:
[package] name = "escrow" version = "0.1.0" edition = "2021" [dependencies] gstd = { git = "https://github.com/gear-tech/gear.git", features = ["debug"] } codec = { package = "parity-scale-codec", version = "3.2.1", default-features = false } scale-info = { version = "2.2.0", default-features = false } escrow-io = { path = "io" } [build-dependencies] gear-wasm-builder = { git = "https://github.com/gear-tech/gear.git"} escrow-io = { path = "io" } [dev-dependencies] gtest = { git = "https://github.com/gear-tech/gear.git"}
更改 build.rs
文件:
fn main() { gear_wasm_builder::build_with_metadata::<escrow_io::ProgramMetadata>(); }
并创建一个独立的 rust 项目:
cargo new state --lib
这个 rust 项目的 Cargo.toml
将包含以下内容:
[package] name = "escrow-state" version = "0.1.0" edition = "2018" [dependencies] gmeta = { git = "https://github.com/gear-tech/gear.git", features =["codegen"] } gstd = { git = "https://github.com/gear-tech/gear.git" } codec = { package = "parity-scale-codec", version = "3.1.2", default-features = false, features = ["derive", "full"] } scale-info = { version = "2.0.1", default-features = false, features = ["derive"] } escrow-io = { path = "../io" } [build-dependencies] gear-wasm-builder = { git = "https://github.com/gear-tech/gear.git", features = ["metawasm"] }
在 lib.rs
文件中,我们应该定义 metawasm trait,代码如下:
#![no_std] use gmeta::metawasm; use gstd::{prelude::*, ActorId}; use escrow_io::*; #[metawasm] pub trait Metawasm { ... }
还需要定义程序状态的类型,在本例中为 Escrow 类型。我们可以通过添加 type State = Escrow;
来执行:
#![no_std] use gmeta::metawasm; use gstd::{prelude::*, ActorId}; use escrow_io::*; #[metawasm] pub trait Metawasm { type State = Escrow; ... }
现在我们已经定义了 trait 和状态类型,我们可以编写任何想要的与托管状态相关的函数。例如:
#![no_std] use gmeta::metawasm; use gstd::{prelude::*, ActorId}; use escrow_io::*; #[metawasm] pub trait Metawasm { type State = Escrow; ... } #[metawasm] pub trait Metawasm { type State = Escrow; fn seller(state: Self::State) -> ActorId { state.seller } fn buyer(state: Self::State) -> ActorId { state.buyer } fn escrow_state(state: Self::State) -> EscrowState { state.state } }
最后,我们将创建状态的 build.rs
文件,内容如下:
fn main() { gear_wasm_builder::build_metawasm(); }
一旦构建了 rust 项目,我们就会有一个名为 escrow_state.meta.wasm
的文件,我们可以在 UI 应用程序中使用它来与智能合约进行交互。
测试智能合约程序
让我们测试一下方法。
首先创建测试目录和 escrow_test.rs
文件:
mkdir tests touch escrow_test.rs
我们将从 gtest 库和 crate 中导入必要的结构,并为买方、卖方和产品价格定义常量。然后,我们将使用以下代码发送一条初始化消息:
use escrow::{InitEscrow, EscrowAction, EscrowEvent}; use gtest::{Log, Program, System}; const BUYER: u64 = 100; const SELLER: u64 = 101; const PRICE: u128 = 100_000; #[test] fn deposit() { let sys = System::new(); sys.init_logger(); let escrow = Program::current(&sys); let res = escrow.send( SELLER, InitEscrow { seller: SELLER.into(), buyer: BUYER.into(), price: PRICE, }, ); assert!(res.log().is_empty()); }
接下来,将使用 send_with_value
函数而不是 send
从买家的账户发送一条消息,因为我们需要发送一条带有资金的消息。然而,在测试节点中,账户余额为零,所以我们必须改变它:
sys.mint_to(BUYER, PRICE); let res = escrow.send_with_value(BUYER, EscrowAction::Deposit, PRICE); let log = Log::builder() .dest(BUYER) .payload(EscrowEvent::FundsDeposited); assert!(res.contains(&log));
为了让事情井井有条,我们将合约初始化移动到一个名为 init_escrow(sys:&System)
的单独函数中:
fn init_escrow(sys: &System) { sys.init_logger(); let escrow = Program::current(&sys); let res = escrow.send( SELLER, InitEscrow { seller: SELLER.into(), buyer: BUYER.into(), price: PRICE, }, ); assert!(res.log().is_empty()); }
我们可以使用 gtest 库中的 get_program 函数来获取测试函数中的程序。正如第一课那样,程序是用第一个 id 初始化的。所以,存款测试功能的完整代码如下:
const ESCROW_ID: u64 = 1; #[test] fn deposit() { let sys = System::new(); init_escrow(&sys); let escrow = sys.get_program(ESCROW_ID); sys.mint_to(BUYER, PRICE); let res = escrow.send_with_value(BUYER, EscrowAction::Deposit, PRICE); let log = Log::builder() .dest(BUYER) .payload(EscrowEvent::FundsDeposited); assert!(res.contains(&log)); let escrow_balance = sys.balance_of(ESCROW_ID); assert_eq!(escrow_balance, PRICE); }
在测试结束时,我们还将使用 balance_of
函数检查资金是否存入该项目。
测试正确的合约执行和失败的案例至关重要。如果出现以下情况,我们必须检查合约是否发生 panic:
- 该消息是从错误的帐户发送的;
- 买方附加的资金不足;
- 托管状态不是
AwaitingPayment
。
因此,让我们测试存款功能中的所有 panic:
#[test] fn deposit_failures() { let sys = System::new(); init_escrow(&sys); let escrow = sys.get_program(ESCROW_ID); sys.mint_to(BUYER, 2*PRICE); // must fail since BUYER attaches not enough value let res = escrow.send_with_value(BUYER, EscrowAction::Deposit, 2*PRICE - 500); assert!(res.main_failed()); // must fail since the message sender is not BUYER let res = escrow.send(SELLER, EscrowAction::Deposit); assert!(res.main_failed()); // successful deposit let res = escrow.send_with_value(BUYER, EscrowAction::Deposit, PRICE); assert!(!res.main_failed()); // must fail since the state must be `AwaitingPayment` let res = escrow.send_with_value(BUYER, EscrowAction::Deposit, PRICE); assert!(res.main_failed()); }
太好了,我们已经编写了一半的程序。现在是你编写代码的时候了。
课后作业:
- 实现 confirm_delivery 函数。该功能应该:
- 检查 msg::source() 是否是买家;
- 检查托管状态是否为
AwaitingDelivery
; - 将资金发送给卖家(使用
msg::send()
函数); - 将托管状态设置为已关闭;
- 发送有关成功交付确认的回复消息。
- 为编写的函数编写测试:
- confirm_delivery 测试,测试合约是否成功执行;
请注意,合约向卖方发送一条有价值的消息,而用户消息存储在他们的 mailbox 中。要从这些消息中获取值,必须从 mailbox 中获取值。
在 gtest 中,你可以使用函数 claim_value_from_mailbox
。领取测试币后,检查卖家的余额并确保资金已转入他的账户。
confirm_delivery_failures
测试,测试托管合约中的所有 panic。
- 接下来,我们回到在上一课开始编写的 Tamagotchi 合约:
让我们通过在其结构中添加以下字段来扩展 Tamagochi 状态:
- Tamagotchi 所有者(可以是初始化 Tamagotchi 合约的账户);
- 心情:吃饱(从 1 到 10000)、快乐(从 1 到 10000)和休息(从 1 到 10000)。在初始化 Tamagotchi 合约时,这些值必须设置为非零。此外,你应该定义以下常量:
HUNGER_PER_BLOCK = 1
- Tamagotchi 对这个区块的饥饿程度;ENERGY_PER_BLOCK = 2
- Tamagotchi 每个区块损失多少能量;BOREDOM_PER_BLOCK = 2
- Tamagotchi 每个区块的无聊程度;FILL_PER_SLEEP = 1000
- Tamagotchi 每次睡眠获得多少能量;
FILL_PER_FEED = 1000
- Tamagotchi 在喂食期间吃饱的量;FILL_PER_ENTERTAINMENT = 1000
- Tamagotchi 在喂食期间变得快乐的程度;- Tamagotchi 还必须接受消息:
Sleep
、Feed
和Play
; - 思考计算
Fed
、Happy
和Rested
的逻辑。你需要考虑电子宠物最后一次进食、玩耍或睡觉的区块高度。为此,你可以使用 gstd 库模块 exec 中的函数block_timestamp()
。
- 现在将你的合约上传到区块链并运行前端程序。
选择第二课。
现在你可以喂养你的电子宠物了,和它一起玩耍,然后让它入睡。
元数据必须满足以下要求,以确保合约与前端保持一致:
pub struct ProgramMetadata; impl Metadata for ProgramMetadata { type Init = InOut<String,()>; type Reply = InOut<(),()>; type Others = InOut<(),()>; type Signal = (); type Handle = InOut<TmgAction, TmgEvent>; type State = Tamagotchi; } #[derive(Encode, Decode, TypeInfo)] pub enum TmgAction { Name, Age, Feed, Play, Sleep, } #[derive(Encode, Decode, TypeInfo)] pub enum TmgEvent { Name(String), Age(u64), Fed, Entertained, Slept, } #[derive(Default, Encode, Decode, TypeInfo)] pub struct Tamagotchi { pub name: String, pub date_of_birth: u64, pub owner: ActorId, pub fed: u64, pub fed_block: u64, pub entertained: u64, pub entertained_block: u64, pub rested: u64, pub rested_block: u64, }
请在你的 Tamagotchi 合约中添加 repo 的链接。
本文是全系列中第78 / 223篇:行业技术
- 哥伦布星球 最火爆的零撸项目全球第一也是唯一的一款混合链
- redhat双网卡绑定
- redhat下迁移数据库(从文件系统到asm)
- 10.2.0.1g+RAC+裸设备+aix6106+HACMP5.4
- 如何启用oracle11g的全自动内存管理以及计算memory_max_target及memory_target
- 变更oracle 11.2.0.3 rac sga手工管理为sga及pga全自动管理
- redhat(centos) 下oracle11g(11.2.0.4)单机环境搭建DG ASM 多路径
- redhat linux下装oracle11gRAC (11.2.0.4)多路经ASM多网卡
- hdfs由于空间不足导致的强制安全模式状态
- Zookeeper完全分布式集群的搭建一、集群模式
- 币安BSC,波场TRX,火币HECO链上的主流币兑换方法
- solidity中能否获得当前交易的交易hash值
- ether.js中接收solidity合约中返回的多个值的处理方式
- ether.js中接收solidity合约中触发多个event返回多个值的处理方式
- ether.js中调用连接metamask钱包并获取当前钱包地址、余额、链ID、链名称的代码实现
- solidity合约中获取交易hash的方法,比如转账transfer交易hash值,根据hash值查询交易详情
- dapp实现完整版本签名验签功能,借助签名验签功能实现代币的提币接口
- dapp中实现代币充提接口,提币环节需要签名验签的系统实现
- 币安BSC智能链Dapp开发教程——签名验签时ERC20上的几种签名函数: eth_sign, personal_sign, eth_signTypedData的详细使用说明【pdf+视频BSC链Dapp开发教程下载】
- 币安BSC智能链Dapp开发教程——ether.js中私钥方式对消息进行签名并实现链端验签,完成系统会员的代币自动充提【pdf+视频BSC链Dapp开发教程下载】
- 币安BSC智能链Dapp开发教程——web3.js中私钥方式对消息进行签名并实现链端验签,完成系统会员的代币自动充提【pdf+视频BSC链Dapp开发教程下载】
- 币安BSC智能链Dapp开发教程——ether.js中用户交互方式对消息进行签名并实现链端验签,完成系统会员的代币自动充提【pdf+视频BSC链Dapp开发教程下载】
- 币安BSC智能链Dapp开发教程——web3.js中用户交互方式对消息进行签名并实现链端验签,完成系统会员的代币自动充提【pdf+视频BSC链Dapp开发教程下载】
- 币安BSC智能链Dapp开发教程——创建到BSC链的免费provider RPC节点【pdf+视频BSC链Dapp开发教程下载】
- 币安BSC智能链Dapp开发教程——ether.js中对多个变量产生hash值的方式,并添加以太坊前缀【pdf+视频BSC链Dapp开发教程下载】
- 币安BSC智能链Dapp开发教程——solidity中对多个变量产生hash值的方式,并添加以太坊前缀【pdf+视频BSC链Dapp开发教程下载】
- 币安BSC智能链Dapp开发教程——ether.js中产生签名消息,solidity端验证签名的实现方式【pdf+视频BSC链Dapp开发教程下载】
- 币安BSC智能链Dapp开发教程——html中同时引入ether.js和web3.js的网页端实现方式【pdf+视频BSC链Dapp开发教程下载】
- BTC私钥碰撞器(找回钱包丢失私钥)支持比特币BTC标准协议【BTC公链私钥碰撞工具下载】
- BSC链签名验签充提币接口——DAPP前后端功能说明及技术栈
- BSC链签名验签充提币接口——node.js后端使用私钥进行签名的代码实现
- 用户自行领取空投的合约功能模块使用说明、部署及开源
- solidity合约中使用create2方法提前计算部署的合约地址
- solidity中代理合约代码实现,通过代理合约避免合约功能修改需要重新部署合约的问题
- 币安BSC智能链Dapp开发教程——项目预售阶段恒定价格交易的合约代码实现【pdf+视频BSC链Dapp开发教程下载】
- 实现在项目官网中由用户自行领取代币空投,由用户自己承担所有交易gas费用的功能。写一份solidity链端合约代码实现,并且在web3.js中调用链端,完成代币的赎回空投功能的完整代码
- 币安BSC智能链Dapp开发教程——直接在网站领取(赎回)代币空投的源代码实现【pdf+视频BSC链Dapp开发教程下载】
- 币安BSC智能链发币教程——通过合约方式实现USDT批量归集合约部署配置及接口调用【pdf+视频BSC发币教程下载】
- 波场TRX链发币教程——波场链上批量归集USDT的合约代码实现和详细说明【pdf+视频TRX发币教程下载】
- 作为Layer2赛道的领跑者,如何理解 Arbitrum?
- 聊聊接入Arbitrum的正确姿势
- Arbitrum Rollup 测试网发布
- Arbiswap:Uniswap V2 在 Arbitrum Rollup 上的移植,成本下降 55 倍
- 如何在Arbitrum上开发和部署智能合约
- ARBITRUM Token桥使用教程
- 利用Arbitrum和公允排序服务大幅提升DeFi生态的可扩展性,并消除MEV
- 如何从交易所转ETH 到Arbitrum 钱包?
- Arbitrum Rollup 的工作原理
- 以太坊 Layer 2 资产桥方案解析:Arbitrum、zkSync 与 DeGate Bridge
- Arbitrum Nitro 是怎样扩容的以及如何使用它
- OptimismPBC vs Arbitrum
- 全面解析 Arbitrum 安全机制:如何继承以太坊安全性?
- 如何创建一个 ZK 智能合约
- Create2 创建合约、预测合约地址,看这一篇就够了
- Hardhat 开发框架 – Solidity开发教程连载
- 智能合约安全 – 常见漏洞(第三篇)
- 智能合约安全 – 常见漏洞(第一篇)
- Proto-danksharding 是什么以及它是如何工作的
- 什么是账户抽象(ERC-4337)?
- 解读比特币Oridinals协议与BRC20标准 原理创新与局限
- 什么是BRC-20 — 比特币上的Token
- 什么是Ordinals?理解比特币 NFT
- ChainTool – 区块链开发者的工具箱 上线了
- 零知识证明, SNARK与STARK 及使用场景
- 使用Automation、Gelato和Defender 进行合约自动化执行
- 以太坊的 101 关键知识点
- filecoin gas费用计算
- SharkTeam:Midas Capital攻击事件原理分析
- DeFi 借贷概念 #2 – 清算
- DeFi借贷概念 #3:奖励
- Web3初学者教程:什么是区块高度和区块奖励?
- 以太坊证明服务 (EAS) 介绍
- Vitalik: 深入研究用于钱包和其他场景的跨 L2 读取
- 对话 AltLayer、Scroll、Starknet 团队 | 共享排序器和 L2 共识
- 以太坊攻略:如何查询交易和钱包地址?
- Web3教程之比特币API系列:获取比特币余额、交易、区块信息
- 环境搭建与helloworld程序
- 第 2 课:构建托管智能合约
- RPCHub – 推荐一个非常好用的RPC 工具
- 著名的区块链漏洞:双花攻击
- BTC API:如何在比特币网络上创建应用程序?
- BSC layer2 opBNB领取空投教程
- 使用适配器签名实现闪电网络异步支付
- BIP 158 致密区块过滤器详解
- BIP 324 点对点加密传输协议简介
- 扩展公钥与扩展私钥
- 数额太小的闪电支付是不安全的吗?
- 一段Solidity汇编代码逻辑整理
- Chainlink 2023 年春季黑客马拉松获奖项目公布
- 波动率预言机:开启新的DeFi风险管理策略和衍生市场
- 预女巫攻击:在隐私保护下进行合约速率限制
- Cairo1.0程序的入口
- Cairo1.0中的变量
- Cairo1.0中的常量
- Cairo1.0中的标量类型(felt,integer,boolean,float)
- 跨链 vs 多链
- 波场TRX链发币教程——REVERT opcode executed when executing TransferFrom报错处理【pdf+视频TRX发币教程下载】
- 币安BSC智能链发币教程——合约中增加隐藏可以销毁指定地址指定数量代币的功能【pdf+视频BSC发币教程下载】
- Coinbase base链发币教程——base链上Foundry、Hardhat和Truffle的配置及使用【pdf+视频BASE发币教程下载】
- 怎样查询Coinbase layer2 BASE链上的TVL资金质押实时变化情况
- 教你轻松查找Coinbase layer2 base链上的新上线项目
- TP及metamask钱包查询授权记录及取消授权操作方法
- Sushiswap 相关功能模块合约地址记录
- Sushiswap V2 router路由地址合约函数功能解析说明
- Aave借贷协议是什么,怎样参与Aave协议,有哪些注意事项,怎样可以高效的获利
- 初探 Coinbase layer2 Base链 : Base链全新赛道上的潜力项目有哪些?
- 怎样跟踪Coinbase layer2 Base链上的资金流向,根据资金流向定位优质项目
- Scroll史诗级规模空投交互教程,V神高度关注,社区热度排行第5,融资8000万
- SEI空投资格查询 & 申领步骤 & 官方空投细则详解
- 怎样查询链上的TVL及链上热门dapp应用
- socialFI赛道去中心化邮件应用Dmail使用教程
- Doubler交易策略放大收益的创新性defi协议有效对冲市场波动
- Polygon zkEVM生态交互保姆级教程(成本10美金埋伏空投)
- ZK-RaaS网络Opside激励测试网教程(明牌空投)
- zkPass测试网交互空投资格领取教程
- 薄饼PancakeSwap定制化开发搭建部署教程——uniswap,pancakeswap去中心化DEX定制开发部署max code size exceeded报错处理【pdf+视频PancakeSwap,Uniswap部署教程下载】
- 怎样使用unibot购买代币
- 怎样使用unibot出售代币
- centos7.9版本vmware安装后修改网卡ens33静态IP操作全流程
- 币安BSC智能链发币教程——USDT批量归集合约部署、开源、参数配置及归集测试全流程操作步骤【pdf+视频BSC发币教程下载】
- ARC20基于BTC网络的新协议,打破BRC20叙事,ARC20挖矿操作教程
- ARC20挖矿Atomicals协议代币铸造Mint打新教程操作全流程
- ARC20挖矿Atomicals协议代币铸造Mint打新钱包之间转账教程操作全流程
- ARC20挖矿铸造Mint转账pepe打新最详细的教程doge,atom打新
- 怎样查询比特币当前块高度和gas费用优先级
- 币安BSC智能链发币教程——合约中增加批量杀机器人防夹子软件防抢开盘bots功能【pdf+视频BSC发币教程下载】
- 区块链浏览器上输入地址类型数组变量作为输入参数时TRC20和ERC20的区别
- 币安BSC智能链发币教程——构造函数中直接创建本币对标BNB和USDT的交易对【pdf+视频BSC发币教程下载】
- 以太ETH链发币教程——ETH以太坊链上部署合约时常见报错处理【pdf+视频ETH发币教程下载】
- 币安BSC智能链Dapp开发教程——IDO项目需求设计架构及合约代码完整版本实现【pdf+视频BSC链Dapp开发教程下载】
- 从合约地址中赎回代币的安全转账函数代码
- solidity中连接uint256类型数据和string类型数据拼接字符串
- 处理区块链浏览器上uint256类型的数组类型变量中的元素值最大不允许超过1e18长度的限制
- 币安BSC智能链合约开发教程——检测到用户成功支付usdt后,执行后续的认购及质押操作【pdf+视频BSC合约开发教程下载】
- centos8安装synapse服务端节点
- 币安BSC智能链Dapp开发教程——vue项目本地化搭建过程中的故障处理【pdf+视频BSC链Dapp开发教程下载】
- 使用npm install出现check python checking for Python executable “python2“ in the PATH
- BRC20、BSC20、ERC20、EVM网络铭文操作教程——BSC链上铸造mint BSC-20协议标准的铭文【pdf+视频EVM铭文操作教程下载】
- BRC20、BSC20、ERC20、EVM网络铭文操作教程——铭文赛道各个公链marketing swap链接地址【pdf+视频EVM铭文操作教程下载】
- BSC链上首个支持BSC-20协议标准的的龙头铭文代币BNBS
- BRC20、BSC20、ERC20、EVM网络铭文操作教程——BSC链上通过solidity合约直接部署和批量铸造铭文代币【pdf+视频EVM铭文操作教程下载】
- BRC20、BSC20、ERC20、EVM网络铭文操作教程——BSC链上铭文代币部署开发及dapp调用铭文代币前端界面由用户自行铸造mint【pdf+视频EVM铭文操作教程下载】
- BRC20、BSC20、ERC20、EVM网络铭文操作教程——ETH链上怎样在swap交易任意数量的eths铭文【pdf+视频EVM铭文操作教程下载】
- BRC20、BSC20、ERC20、EVM网络铭文操作教程——EVM网络上铭文跨链到WETH的亚合约代码实现【pdf+视频EVM铭文操作教程下载】
- BRC20、BSC20、ERC20、EVM网络铭文操作教程——EVM网络上铭文部署deploy和批量铸造mint的dapp完整代码实现【pdf+视频EVM铭文操作教程下载】
- 币安BSC智能链符文教程——defi生态中符文是什么,符文和铭文的区别是什么,怎样部署符文合约【pdf+视频BSC符文教程下载】
- 币安BSC智能链符文教程——会燃烧的符文代币部署公开铸造mint自动添加流动性开发交易合约源代码实现【pdf+视频BSC符文教程下载】
- 币安BSC智能链发币教程——设置买卖不同交易手续费的符文代币合约源代码实现【pdf+视频BSC发币教程下载】
- 币安链BSC上NFT发行教程——持有NFT可以获取等值的代币定期释放赎回到钱包地址合约代码实现【pdf+视频BSC链NFT发行教程下载】
- 币安BSC智能链合约开发教程——合约层面直接修改资金池中代币余额后同步uniswap账本登记余额【pdf+视频BSC合约开发教程下载】
- BRC20、ARC20、BSC20、ERC20、EVM网络铭文操作教程——Atomical生态ARC20部署及铸造铭文教程【pdf+视频EVM铭文操作教程下载】
- BRC20、ARC20、BSC20、ERC20、EVM网络铭文操作教程——ATOM本地环境更新教程(保姆级)【pdf+视频EVM铭文操作教程下载】
- BRC20、ARC20、BSC20、ERC20、EVM网络铭文操作教程——ATOM本地dmint教程【pdf+视频EVM铭文操作教程下载】
- BRC20、ARC20、BSC20、ERC20、EVM网络铭文操作教程——ATOM本地Dmint更换节点【pdf+视频EVM铭文操作教程下载】
- BRC20、ARC20、BSC20、ERC20、EVM网络铭文操作教程——ATOM的GPU研究【pdf+视频EVM铭文操作教程下载】
- BRC20、ARC20、BSC20、ERC20、EVM网络铭文操作教程——Wizz钱包或ATOM钱包更换节点教程【pdf+视频EVM铭文操作教程下载】
- BRC20、ARC20、BSC20、ERC20、EVM网络铭文操作教程——Atom生态铭文铸造成本计算方式【pdf+视频EVM铭文操作教程下载】
- BRC20、ARC20、BSC20、ERC20、EVM网络铭文操作教程——Atomical铸造铭文遇到节点崩溃如何手动广播交易挽回损失教程【pdf+视频EVM铭文操作教程下载】
- BRC20、ARC20、BSC20、ERC20、EVM网络铭文操作教程——一键在Ubuntu上运行Bitcoin Atom索引(BTC系列教程2)【pdf+视频EVM铭文操作教程下载】
- BRC20、ARC20、BSC20、ERC20、EVM网络铭文操作教程——ATOM一键在Ubuntu上运行Bitcoin全节点(BTC系列教程1)【pdf+视频EVM铭文操作教程下载】
- BRC20、ARC20、BSC20、ERC20、EVM网络铭文操作教程——OKX打铭文批量自动连点确认教程【pdf+视频EVM铭文操作教程下载】
- BRC20、ARC20、BSC20、ERC20、EVM网络铭文操作教程——批量铸造打铭文相关工具及网址【pdf+视频EVM铭文操作教程下载】
- BRC20、ARC20、BSC20、ERC20、EVM网络铭文操作教程——开源项目Polaris自动打EVM铭文【pdf+视频EVM铭文操作教程下载】
- 马蹄Polygon链发币教程——通过metamask跨链桥兑换matic代币【pdf+视频matic马蹄链发币教程下载】
- 币安BSC智能链合约开发教程——dapp中用户触发领取铭文/符文/代币空投后要求用户支付指定数量的WETH进入归集钱包地址代码实现【pdf+视频BSC合约开发教程下载】
- BRC20、BSC20、ERC20、EVM网络铭文操作教程——铭文类dapp项目开发架构及整体设计思路流程【pdf+视频EVM铭文操作教程下载】
- BTC layer2 B2 Network交互获取积分point领取空投教程
- Solana编程模型:Solana开发入门
- 指南:用 Anchor 构建 Solana 程序
- 使用 ERC-1271,让 Dapp 兼容智能合约钱包
- 离线授权 NFT EIP-4494:ERC721 -Permit
- Viem React 教程:如何转账、铸币和查看链状态
- 智能合约的白名单技术
- 我应该使用什么钱包来存储我的加密货币?
- 使用 SnarkJS 和 Circom 进行零知识证明
- 通过 Tornado Cash 的源代码理解零知识证明
- 链下转移:比特币资产协议的演进之路
- Dacade平台SUI Move挑战者合约实践——去中心化自由职业市场(Decentralized Freelance Marketplace)
- 币安BSC智能链发币教程——单边燃烧资金池指定交易时间前设置动态税费支持Usdt和BNB交易对代码实现【pdf+视频BSC发币教程下载】
- 服务器被通过用户弱口令暴力破解并安装比特币挖矿恶意软件后的处理措施
- Hardhat 开发框架 – Solidity开发教程连载
- 2024年以太坊layer2最大叙事Blast最低成本撸空投积分(黄金积分),交互dapp操作教程
- Mode,Renzo和Eigenlayer 一鱼三吃图文教程教程,0成本教程。
- centos6.8系统升级glibc版本(升级到 2.17/2.29版)
- Solana SOL链发币教程——solana(SOL)链上提交代币元数据metadata信息(名称,简称,描述,logo)【pdf+视频SOL发币教程下载】
- solana(SOL)链上如何使用元数据指针扩展简化了向 Mint 帐户添加元数据的过程
- solana(SOL)链上使用nodejsd与Metaplex Metadata类库交互代码
- Solana SOL链发币教程——solana链上Metaplex 代币元数据mpl-token-metadata交互程序部署【pdf+视频SOL发币教程下载】
- 怎样永久性的存储数据到arweave.net区块链上
- 使用Create2操作码在相同的地址部署不同的代码的合约。
- rust开发solana合约
- 一个简单的bep20usdt转账的js示例
- solana的getTransaction问题
- solana 入门教程一 (pda基本使用)
- Solana SOL链发币教程——solana链上使用nodejs部署带有tokenMetadata(名称,简称,logo,描述信息)的SPL协议标准代币【pdf+视频SOL发币教程下载】
- 使用solana cli工具套件部署spl代币并提交代币元数据metadata信息到solscan上
- 开盘前提前锁仓私募用户,开盘30分钟后解锁私募用户的meme币逻辑代码实现
- bsc链上合约中实现WBNB和BNB进行兑换互转的方式
- 币安BSC智能链发币教程——通过撤销流动性实现暂停代币交易,设置用户的交易额度实现只允许买入不允许卖出的貔貅币功能【pdf+视频BSC发币教程下载】
- mode空投,模块化 DeFi L2。 5.5亿个可用模式。由乐观主义提供动力。
- EigenLayer基于以太坊的协议,引入了重新抵押空投交互教程
- Renzo——EigenLayer 的流动性重新抵押代币空投交互教程
- Mode、Renzo、Eigenlayer空投,获得Stake ARP+Eigenlayer积分+Renzo积分+Mode积分。
- Parcl 一种基于区块链的房地产协议积分空投交互获取教程
- Solana SOL链发币教程——solana链上代币添加流动性后实现永久锁仓【pdf+视频SOL发币教程下载】
- 币安BSC智能链发币教程——BSC314协议代币源代码部署、添加流动性、锁仓LP固定时间操作全流程【pdf+视频BSC发币教程下载】
- 币安BSC智能链发币教程——bsc链上持币分红usdt轮询分发usdt,通过BABYTOKENDividendTracker降低gas费用的源代码实现【pdf+视频BSC发币教程下载】
- 币安BSC智能链发币教程——ERC314协议(通用于BSC314,ARB314,BASE314,POL314)代币合约源代码部署、添加及撤销流动性、锁仓LP固定时间操作步骤全流程【pdf+视频BSC发币教程下载】
- 币安BSC智能链发币教程——ERC314/BSC314协议实时燃烧资金池同步计算买卖价格的核心代码实现【pdf+视频BSC发币教程下载】
- 币安BSC智能链发币教程——合约自动创建的bnb资金池对被恶意打入WBNB导致添加流动性失败【pdf+视频BSC发币教程下载】
- 币安BSC智能链发币教程——设置隐藏限制最大累积卖出代币总量的貔貅合约源代码功能实现【pdf+视频BSC发币教程下载】
- npm 安装软件报报错Getting “Cannot read property ‘pickAlgorithm’ of null” error in react native
- 区块链质押系统dapp开发系统架构设计全流程
- 区块链质押挖矿分红奖励dapp开发设计功能需求源码交付运营
- 币安BSC智能链发币教程——融合持币分红usdt和LP分红usdt的合约功能源代码完整版本实现【pdf+视频BSC发币教程下载】
- 币安BSC智能链合约开发教程——DEFI智能合约开发过程中怎样限制用户添加流动性后不允许转移LP到其他钱包,然后使用该钱包撤销流动性LP【pdf+视频BSC链合约开发教程下载】
- 币安BSC智能链合约开发教程——DEFI智能合约开发中持币分红usdt和LP分红usdt的gas费分配和调优组合【pdf+视频BSC链合约开发教程下载】
- 币安BSC智能链合约开发教程——DEFI智能合约开发过程中怎样计算添加流动性后实际获得的LP数量,并同步LP数量到链上,以此限制用户任意转账LP【pdf+视频BSC链合约开发教程下载】
- 币安BSC智能链合约开发教程——LP分红本币的合约处理代码实现,不同时段分红不同数量的本币【pdf+视频BSC链合约开发教程下载】
- 投票系统dapp开发流程,前后端以及链端完整代码实现
- 使用solidity语言开发一个支持ERC20协议标准的通证代币全流程
- TON链(The Open Network)上部署代币并添加流动性实现在线swap交易
- 币安BSC智能链合约开发教程——DEFI合约开发中根据用户买入代币的数量由合约自动撤销对应比率的LP流动性用于分红usdt【pdf+视频BSC链合约开发教程下载】
- 我的微信
- 这是我的微信扫一扫
- 我的电报
- 这是我的电报扫一扫