区块链入门基础课:《Nethereum教程》零基础玩转以太坊开发(二)合约交互

图片

今天我们要讨论的是如何与智能合约进行交互,发送交易。下面的示例将会详细讲解如何与合约进行交互,及一些概念性的解释,有需要的朋友们可以收藏一下。

一:概念解释

在下面示例之前呢,我先解释下什么叫智能合约,以及与代币的区别。明白这些后可能对开发而言事半功倍。

智能合约是在以太坊或者其他公链上部署的代码,它可以执行各种功能,包括,但不限于代币的发行和管理,智能合约可以被用来创建代币,但是智能合约本身并不仅仅是作用于代币,它是一个更加广泛的概念。

当项目方在以太坊(或其他公链上)部署代币时,他们其实是部署了一个特定类型的智能合约,这个合约遵循代币标准,比如ERC-20或者ERC-721,ERC404等等。

拿ERC-20来举例吧,ERC20标准定义了一些接口,包括transfer,balanceOf,allowance等函数,这些函数可以让代币在不同账户间转移,并允许第三方应用与该智能合约代币进行交互的权限。

智能合约更加复杂的逻辑还可以实现比如说21年很火的,去中心化金融(Defi)中的借贷协议,保险协议,资产管理,KYC验证等等逻辑。

而代币只是智能合约中的一小块(代币合约),用来管理数字资产。

概念就解释到这里,以下开始示例代码:

二:示例内容

我先梳理下关键步骤:

  1. 设置交易事件

  2. 预估gas费

  3. 支付gas费

  4. 发送交易并等待确认

1.初始化web3实例和Account

首先,你需要创建一个 Web3 实例和一个 Account 实例,Account将用于签署交易。

以下是代码:


using Nethereum.Web3;
using Nethereum.Web3.Accounts;

// 创建 Web3 实例,连接到以太坊节点
var web3 = new Web3(new HttpProvider("https://mainnet.infura.io/v3/YOUR_INFURA_PROJECT_ID"));

// 创建 Account 实例,使用你的私钥
var account = new Account("YOUR_PRIVATE_KEY");

2.获取智能合约实例

使用智能合约的 ABI 和地址来创建一个 Contract 实例。

智能合约的 ABI(Application Binary Interface)是合约接口的 JSON 表达形式,它包含了合约的所有公共函数、事件、输入和输出类型的信息。ABI 允许外部实体(如 dApp、智能合约或其他以太坊账户)与智能合约交互。当你编写和编译智能合约时,编译器(如 Solidity 编译器)会生成 ABI。

如果对于学习目的的话,在网上可以找到很多公开的ABI例子,特别是对于ERC20常见的一些模板,JSON格式的,例如


[
    // 这是一个数组,其中每个元素描述了合约的一个功能(函数或事件)。

    {
      // 第一个元素是一个只读的函数(view function),用于获取代币的名称。
      "constant": true,               // constant 属性表示这是一个只读操作,不会改变合约状态。
      "inputs": [],                   // inputs 数组表示该函数不需要任何输入参数。
      "name": "name",                 // name 是函数的名称,在智能合约中调用。
      "outputs": [                    // outputs 数组定义了函数的返回值。
        {
          "name": "",                 // 输出值没有名字,这是 Solidity 编译器默认的空字符串。
          "type": "string"            // 返回值的数据类型是 string,意味着返回一个文本字符串。
        }
      ],
      "payable": false,               // payable 属性表明此函数不能接收以太币作为调用费用。
      "stateMutability": "view",      // stateMutability 指示函数不修改合约状态。
      "type": "function"              // type 定义这是一个函数类型的条目。
    },

    {
      // 第二个元素是一个非只读函数(non-view function),用于批准另一个地址使用指定数量的代币。
      "constant": false,              // constant 设置为 false,因为这是一个可以改变合约状态的操作。
      "inputs": [                     // inputs 数组定义了函数的输入参数。
        {
          "name": "_spender",         // 第一个参数是接收者地址,被批准使用代币。
          "type": "address"           // 数据类型是 address,代表以太坊上的一个账户地址。
        },
        {
          "name": "_value",           // 第二个参数是批准的数量。
          "type": "uint256"           // 数据类型是 uint256,无符号整数,最大值为 2^256 - 1。
        }
      ],
      "name": "approve",              // 函数名称是 approve,用于批准代币的使用。
      "outputs": [                    // outputs 数组定义了函数的返回值。
        {
          "name": "",                 // 输出值没有名字,这是默认的空字符串。
          "type": "bool"              // 返回值的数据类型是 bool,意味着返回一个布尔值。
        }
      ],
      "payable": false,               // payable 设置为 false,因为这个函数不接受以太币支付。
      "stateMutability": "nonpayable",// stateMutability 指示函数可能改变合约状态。
      "type": "function"              // type 定义这是一个函数类型的条目。
    },

    // 更多的功能可以添加到这个数组中,包括其他 ERC-20 标准函数,如 transfer, balanceOf 等。
]

 

其实说白了,ERC20 的合约代码 这里所谓的发币,其实就只是逻辑上维护一个总数和一个map来记录每个地址下有多少币种。。。。用其他语言也能实现这么个demo,只不过ERC20 是运行在以太坊上的。

好了,话说回来。假如你现在已经有了一个ABI

using Nethereum.Contracts;

string contractAddress = "0xYourContractAddress";
string contractAbi = "[Your_ABI_here]";

var contract = web3.Eth.GetContract(contractAbi, contractAddress);

就可以这样去获取一个Contract 实例。

3.准备交易(gas费)相关

以下示例包括了指定要调用的函数,参数,以及gas相关的信息。

关于gas费的话,在以太坊上面,gas你可以理解为执行一次交易,或者执行一次交互所需要的成本的单位。每次交互都需要支付一定数量的gas费。

实际消耗的gas数量*gas价格=交易总费用

Gas Limit:你愿意为此次交互支付的最大gas数量

Gas Price:你原因为每个单位支付的gas费,通常以gwei计算。


using Nethereum.RPC.Eth;
using Nethereum.RPC.Eth.Transactions;
using System.Threading.Tasks;

// 估计 gas 用量
var gasEstimate = await contract.EstimateGasAsync(account.Address, "YourFunctionName", new object[] { /* 参数 */ });

// 设置 gas 价格
var gasPrice = await web3.Eth.GetGasPrice.SendRequestAsync();

// 通常设置的 gas limit 比估计的 gas 大一点,以防万一
var gasLimit = gasEstimate.Value.Add(new HexBigInteger(100000L)); // 例如,增加 100000 作为缓冲

// 创建交易描述
var transactionDescription = new TransactionInput
{
    From = account.Address,
    To = contractAddress,
    Value = 0, // 如果不是转账,通常是 0
    Gas = gasLimit,
    GasPrice = gasPrice,
};

4.发送交易


using System.Numerics;

// 发送交易并等待确认
var transactionReceipt = await contract.SendTransactionAndWaitForReceiptAsync(
    transactionDescription,
    "YourFunctionName",
    new object[] { /* 参数 */ },
    account.GetCredentials());

Console.WriteLine($"Transaction hash: {transactionReceipt.TransactionHash}");

三:总结

关于gas费的体现

    支付:gas 费用是由发起交易的账户支付的。如果 gas 价格设为 20 gwei,gas limit 设为 21000,那么总费用将是 21000 * 20 gwei = 420000 gwei,即 0.00042 ETH。

gas 费用体现在你的以太币账户余额减少上。你可以在任何以太坊区块链浏览器中查看你的账户,那里会显示你的账户余额,包括交易前后的变化。

关于等待交易确认

    在C#里我们可以使用task异步,我们的任务在会在交易被矿工纳入区块并确认后完成。这中间需要很长的时间,我们可以使用await关键字等待这些任务完成。而不是使用回调。

当你使用SendTransactionAndWaitForReceiptAsync 方法时,Nethereum 将会等待交易被包含在一个区块中,并返回一个 TransactionReceipt 对象,这个对象包含了关于交易的信息,包括区块哈希、交易索引、合约地址(如果是创建合约的交易)、累积的 gas 用量、状态等。一旦这个任务完成,就意味着交易已经被确认。

以下是使用await来等待交易确认的代码示例:


using Nethereum.Contracts;
using Nethereum.Hex.HexTypes;
using System.Threading.Tasks;

// ... 初始化 web3 和 account,以及获取 contract 实例 ...

// 准备交易描述
var transactionDescription = new TransactionInput
{
    From = account.Address,
    To = contractAddress,
    Value = 0,
    Gas = new HexBigInteger(21000),
    GasPrice = new HexBigInteger(20000000000), // 20 gwei
};

// 发送交易并等待确认
TransactionReceipt transactionReceipt = await contract.SendTransactionAndWaitForReceiptAsync(
    transactionDescription,
    "YourFunctionName",
    new object[] { /* 参数 */ },
    account.GetCredentials());

Console.WriteLine($"Transaction hash: {transactionReceipt.TransactionHash}");
Console.WriteLine($"Block number: {transactionReceipt.BlockNumber}");

在这里例子里面,一旦任务完成,你就可以访问TransactionReceipt 对象,从中就可以获取到有关该次交易的相关信息,以用于做后续的业务逻辑。

那么截止到这里,就已经简单的完成了一个与智能合约交易的示例。

后期内容我们会进阶讲解

如何监听事件

如何获取合约状态

如何获取账户余额

如何账户管理,管理生成以太坊的账户,私钥,公钥和地址

如何构建,签署和广播交易到以太坊主网

如何在链中扫描块

如何扫描交易数据

如何转移代币,等等功能开发,敬请关注!

  • 37
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

加密社

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值