柜台智能合约
用 C 语言编写、构建和部署一个简单的智能合约
先决条件
您需要安装 erdpy 。
创建合约
在您选择的文件夹中,运行以下命令:
erdpy contract new --template="simple-counter" mycounter
这会创建一个名为mycounter
的新文件夹,其中包含一个简单智能合约的 C 源代码——基于模板 simple-counter 。文件counter.c
是智能合约的实现,它定义了以下功能:
init()
:该功能在区块链上部署合约时执行increment()
和decrement()
:这些函数修改智能合约的内部状态- 这是一个纯粹的函数(不修改状态),我们将用它来查询计数器的值
建立合约
为了构建到 WASM 的合约,运行以下命令:
erdpy --verbose contract build mycounter
上面,mycounter
指的是之前创建的文件夹,保存源代码的那个。执行该命令后,您可以在mycounter/output
中检查生成的文件。
在 Testnet 上部署合约
为了在 Testnet 上部署合约,您需要有一个有足够余额的账户(部署费用所需)和相关的 PEM 格式的私钥。
部署命令如下:
erdpy --verbose contract deploy --project=mycounter --pem="alice.pem" --gas-limit=5000000 --proxy="https://testnet-gateway.elrond.com" --outfile="counter.json" --recall-nonce --send
在上面,mycounter
指的是包含源代码和构建工件的同一个文件夹。deploy
命令知道在这个文件夹中搜索 WASM 字节码。
注意命令的最后一个参数——这指示 erdpy 将操作的输出转储到指定的文件中。输出包含新部署的合约的地址和部署交易的散列。
counter.json {
"emitted_tx": {
"tx": {
"nonce": 0,
"value": "0",
"receiver": "erd1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq6gq4hu",
"sender": "erd1...",
"gasPrice": 1000000000,
"gasLimit": 5000000,
"data": "MDA2MTczNmQwMTAwMDA...MDA=",
"chainID": "T",
"version": 1,
"signature": "a0ba..."
},
"hash": "...",
"data": "...",
"address": "erd1qqqqqqqqqqqqqpgqp93y6..."
}
}
在浏览器中随意检查这些值。
与已部署的合约进行交互
在进行实际的合约执行之前,让我们从counter.json
中提取合约地址。
export CONTRACT_ADDRESS=$(python3 -c "import json; data = json.load(open('counter.json')); print(data['emitted_tx']['address'])")
现在我们已经将合约地址保存在一个 shell 变量中,我们可以如下调用合约的increment
函数:
erdpy --verbose contract call $CONTRACT_ADDRESS --pem="alice.pem" --gas-limit=2000000 --function="increment" --proxy="https://testnet-gateway.elrond.com" --recall-nonce --send
执行上面的命令几次,其间稍作停顿。然后随意尝试调用decrement
函数。
然后,为了查询计数器的值——也就是说,为了执行合约的get
纯函数——运行下面的代码:
erdpy contract query $CONTRACT_ADDRESS --function="get" --proxy="https://testnet-gateway.elrond.com"
输出应该如下所示:
[{'base64': 'AQ==', 'hex': '01', 'number': 1}]
交互脚本
前面的步骤可以总结为一个简单的脚本,如下所示:
#!/bin/bash
# Deployment
erdpy --verbose contract deploy --project=mycounter --pem="alice.pem" --gas-limit=5000000 --proxy="https://testnet-gateway.elrond.com" --outfile="counter.json" --recall-nonce --send
export CONTRACT_ADDRESS=$(python3 -c "import json; data = json.load(open('address.json')); print(data['emitted_tx']['contract'])")
# Interaction
erdpy --verbose contract call $CONTRACT_ADDRESS --pem="alice.pem" --gas-limit=2000000 --function="increment" --proxy="https://testnet-gateway.elrond.com" --recall-nonce --send
sleep 10
erdpy --verbose contract call $CONTRACT_ADDRESS --pem="alice.pem" --gas-limit=2000000 --function="increment" --proxy="https://testnet-gateway.elrond.com" --recall-nonce --send
sleep 10
erdpy --verbose contract call $CONTRACT_ADDRESS --pem="alice.pem" --gas-limit=2000000 --function="decrement" --proxy="https://testnet-gateway.elrond.com" --recall-nonce --send
sleep 10
# Querying
erdpy contract query $CONTRACT_ADDRESS --function="get" --proxy="https://testnet-gateway.elrond.com"