Last updated on a day ago
truffle 是什么 Truffle 是一个在以太坊进行 DApp 开发的世界级开发环境、测试框架。可以合约的编译、部署、管理,通过命令控制台直接与智能合约进行交互等功能。
truffle 安装 首先需要安装 NodeJS v8.9.4 或 之后的版本,然后通过 npm 安装 truffle
创建项目
创建项目文件夹
创建空项目
创建实例代码和项目模板,init 创建的是一个空项目,如果需要创建模板,可以 Truffle Box
进行下载
1 truffle unbox <box-name>
项目结构
contracts/
:存放合约
migrations/
:部署脚本文件目录
test/
:测试脚本目录
truffle-config.js
:配置文件
修改配置文件 配置文件自带注释,这里只讲简单的修改
项目全过程 连接到 Ganache 略
编写合约 在contracts/
文件夹中编写合约
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 // SPDX-License-Identifier: UNLICENSED pragma solidity ^0.8; contract MyContract { struct Flag { string title; string content; address owner; uint ts; } Flag[] public flags; // 添加评论 function set(string memory title , string memory content) public { flags.push(Flag(title, content, msg.sender, block.timestamp)); } 获取评论数量 function getLength() public view returns(uint) { return flags.length; } }
编写迁移脚本 迁移脚本文件,也可以叫迁移文件,是放在migrations/
文件夹中的 js 文件,以数字开头,用于部署合约
如1_deploy_MyContract.js
1 2 3 4 5 6 const MyContract = artifacts.require ("MyContract" );module .exports = function (deployer ) { deployer.deploy (MyContract ); };
MyContract
是合约名,而不是文件名,一个文件可以有多个合约,当有多个合约需要依次 部署时,可以使用异步
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 const MyContract = artifacts.require ("MyContract1" );const MyContract = artifacts.require ("MyContract2" );module .exports = async function (deployer, network, accounts ) { await deployer.deploy (MyContract1 ); const myContract1Instance = await MyContract1 .deployed (); const contract1Address = myContract1Instance.address ; await deployer.deploy (MyContract2 , contract1Address); const myContract2Instance = await MyContract2 .deployed (); const contract2Address = myContract2Instance.address ; };
部署合约 终端输入 (truffle complie
和truffle migrate
) 或 truffle migrate --reset
进行合约的编译部署或重部署
如果出现了hit an invalid opcode while deploying
这样的报错,需要修改truffle-config.js
配置文件中版本 solc 版本,和合约对应。(这里是 0.8.0)
部署成功后出现下面类似信息
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 1_deploy_MyContract.js ====================== Deploying 'MyContract' ---------------------- > transaction hash : 0xa0516507693bd555e0b6bf49ee2fc0f3ea41041f1db897d0ea7481beb5978b09 > Blocks: 0 Seconds: 0 > contract address: 0x1E5e59B3FeD2030F8D6b7B2ec1D0D53E441f23a9 > block number: 1 > block timestamp: 1713065479 > account: 0x9d3f59003Da03D71e647eE10294395Aba69C87Ae > balance: 99.998420554 > gas used: 467984 (0x72410) > gas price: 3.375 gwei > value sent: 0 ETH > total cost: 0.001579446 ETH > Saving artifacts ------------------------------------- > Total cost: 0.001579446 ETH
调用合约 调用合约的方法有三种:通过 test 脚本调用,通过网页 js 调用,使用 truffle 控制台
使用 truffle 控制台truffle console
在终端中输入truffle console
可以启动控制台,在控制台中,可以输入 js 语句对合约进行调用,且注意,一定要用异步方法
首先要实例化合约
1 2 let MyContract = await MyContract .deployed ()
接着就可以通过实例调用合约了
1 2 await MyContract .set ("title" ,"content" )
此时在 ganache 的transaction
中会出现CONTRACT CALL
的交易,在终端中也会出现对应的信息
而如果调用的函数没有对链上数据进行修改,则不会出现CONTRACT CALL
交易
1 2 3 4 let flagLength = await MyContract . getLength() flagLength.to Number()
而如果我们想要查看公开的状态变量,也可以通过实例进行访问,如果状态变量是个数组则需要输入一个 uint 作为参数
1 2 // 查看公开的状态变量 MyContract.flags(0 )
使用网页 js
编写测试脚本 测试脚本可以部署并测试合约,也可以测试以部署的合约,测试使用mocha
语法,支持一样的钩子函数before()
、after()
、beforeEach()
和afterEach()
测试脚本一般与对应的合约同名,并加上.test.js
后缀 大体格式如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 const Contract1 = artifacts.require ("Contract1" );contract ("Contract1的测试" , async function (accounts ) => { let contract1; before (async ()=>{ contract1 = await Contract1 .new (params,{value : web3.utils .toWei ("1" ,"Ether" ), gas :..., from : accounts[1 ]}); contract1 = await Contract1 .deployed (); contract1 = awati Contrac1 .at (address); }) beforeEach ( async function ( ) { }) it ("测试内容:应该初始化合约" , async ()=>{ assert.equal (actual, expected, message); assert.notEqual (actual, expected, message); assert.isTrue (value, message); assert.isFalse (value, message) }) it ( ){} afterEach ( async function ( ){ }) after ( async function ( ){ }) })
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 const Greeter = artifacts.require ("Greeter" );contract ("Greeter" , (accounts ) => { before (async () => { let a = await Greeter .deployed (); let c = await a.getGreeting (); let d = await a.setGreeting (var_b); let f = await a.getGreeting (); let g = await Greeter .at ("0x592C0067a4B3Fc66D7f26430b3EBeF9ac7796F85" ); let h = await g.getGreeting (); let i = await g.setGreeting ("您好,世界!" ); let k = await g.getGreeting (); console .log ("合约地址:" , a.address ); console .log ("获取原数据:" , c); console .log ("获取新数据:" , f); console .log ("获取原来的合约地址:" , g.address ); console .log ("获取原来的合约值:" , h); console .log ("更改原来合约的值,并且显示出来:" , k); }); it ("实例描述,比如‘应该初始化合约状态’" , async () => { console .log ("测试合约的操作:" ); }); it ("应该调用xx函数" , async ()=>{ asset.equal (i, "你好世界" , "i的值不是你好世界,执行结果不对" ); }) });
常用 truffle 命令 truffle complie - 合约编译 默认情况下,truffle complie
只会编译更新的合约。可以用 --all
强制编译所有合约,--network
指定使用的网络
truffle development - 开发网络 会启动 truffle 内置的测试网络,在该网络中部署调用等操作不会影响真实网络
truffle console - 控制台 可以使用--network
指定要使用的网络
truffle migrate - 部署合约 truffle migrate
.命令将从最后完成的迁移脚本开始运行。--reset
:从头运行所有迁移脚本
truffle networks - 检查网络构件 显示每个网络上的部署合约的地址
truffle test - 运行测试脚本 执行test/
文件夹中的测试脚本,可以加上文件名运行特定测试。
truffle unbox - 下载模板 下载指定模板,后接模板名