智能合约项目开发实例
环境
相关环境的安装本人的其他博客中已提到
-
remix编辑器(http://remix.ethereum.org/),由于https进不去,此处采用http
-
Truffle v5.5.2 (core: 5.5.2)
-
Ganache v7.0.1
-
Solidity - 0.8.11 (solc-js)
-
Node v12.16.0
-
Web3.js v1.5.3
solidity简单投票代码
代码
仿照remix样例写的简单代码,voter.sol
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
contract SimBallot{
Candidate[] public candidates ;
struct Voter{
address from;
string to;
}
struct Candidate{
string candidate;
uint8 count;
}
// ["aa","bb","cc"]
constructor (string[] memory _candidate ){
require(_candidate.length>0,"require candidate");
for(uint i = 0;i< _candidate.length;i++){
candidates.push(Candidate({
candidate:_candidate[i],
count:0
}));
}
}
function vote(string memory to) public{
require(bytes(to).length !=0,"to is null");
int256 pos = -1;
for(uint256 i=0;i<candidates.length;i++){
if(keccak256(bytes(candidates[i].candidate))==keccak256(bytes(to))){
pos = int256(i);
}
}
require(pos!=-1,"voted person is not in candidates");
candidates[uint256(pos)].count++;
}
function getCounts() public view returns (uint8[] memory){
uint8[] memory counts = new uint8 [](candidates.length);
for(uint256 i;i<candidates.length;i++){
counts[i] = candidates[i].count;
}
return counts;
}
function getNames() public view returns (string[] memory){
string[] memory names = new string [](candidates.length);
for(uint256 i;i<candidates.length;i++){
names[i] = candidates[i].candidate;
}
return names;
}
}
验证
在Deploy后,若出现以下错误
creation of Ballot errored: Error encoding arguments: Error: expected array value
可以在At Address处填写钱包地址,若没有正常测试方法即可
编译
在项目目录初始化
truffle init
生成以下文件:
contracts/
: solidity合约目录migrations/
: 部署脚本文件目录test/
: 测试脚本目录truffle.js
: Truffle配置文件
将之前写的voter.sol放到migrations目录中
测试与编译
- 测试
truffle test ./voter.sol
返回结果,说找不到**‘./uws_win32_x64_72.node’**,不过这个只影响速度,对结果没有影响,可以忽略
D:\work\coding\blockchain\truffle\workspace\voter\contracts>truffle test ./voter.sol --reset
> Warning: possible unsupported (undocumented in help) command line option(s): --reset
This version of µWS is not compatible with your Node.js build:
Error: Cannot find module './uws_win32_x64_72.node'
Falling back to a NodeJS implementation; performance may be degraded.
Compiling your contracts...
===========================
> Compiling .\contracts\Migrations.sol
> Compiling .\contracts\voter.sol
> Compiling .\contracts\voter.sol
> Artifacts written to C:\Users\战神\AppData\Local\Temp\test--14236-0XaxWpfKOIvu
> Compiled successfully using:
- solc: 0.8.11+commit.d7f03943.Emscripten.clang
0 passing (2ms)
- 编译
truffle compile
返回编译结果,显示将编译结果放到了contracts文件夹下
Compiling your contracts...
===========================
> Compiling .\contracts\Migrations.sol
> Compiling .\contracts\voter.sol
> Artifacts written to D:\work\coding\blockchain\truffle\workspace\voter\build\contracts
> Compiled successfully using:
- solc: 0.8.11+commit.d7f03943.Emscripten.clang
搭建私链
- 使用ganache客户端,new workspace
- 配置工作空间
- 配置服务
部署与测试
- 修改配置文件,host、port、network_id都取决于ganache的配置
networks: {
development: {
host: "127.0.0.1", // Localhost (default: none)
port: 8545, // Standard Ethereum port (default: none)
network_id: "5777", // Any network (default: none)
},}
- 编写部署脚本
const Migrations = artifacts.require("SimBallot");//脚本名
module.exports = function (deployer) {
deployer.deploy(Migrations,["aa","bb","cc"]);//后面为传参
};
在命令行中进行部署
truffle migrate
- 新建测试脚本,测试ganache中的账户余额
const Web3 = require('web3')
const rpcURL = "https://rinkeby.infura.io/v3/xxxxxxxxxx" // RPC URL
const web3 = new Web3(rpcURL)
const address = "xxxxxxxxxxxxxxxxxx" // 账户地址
// 读取address中的余额,余额单位是wei
web3.eth.getBalance(address, (err, wei) => {
// 余额单位从wei转换为ether
balance = web3.utils.fromWei(wei, 'ether')
console.log("balance: " + balance)
})
- 修改测试脚本,调用合约方法,查询投票人名单
let SimBallotContract = require("../build/contracts/SimBallot.json");
const Web3 = require('web3')
const rpcURL = "HTTP://127.0.0.1:8545" // RPC URL
const web3 = new Web3(rpcURL)
const address = "0x3ccb98a80F786AF54079f087F3DE62B043D1cf72" // 合约地址
let SimBallot = new web3.eth.Contract(
SimBallotContract.abi,
address,
);
SimBallot.methods.getNames().call()
.then((res)=>{
console.log(res)
})