62solidity环境搭建编译及编写合约-3——2020年07月12日12:55:51
Posted oneapple
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了62solidity环境搭建编译及编写合约-3——2020年07月12日12:55:51相关的知识,希望对你有一定的参考价值。
2020年07月12日12:59:00
2019年09月27日14:15:32
1.通过solc工具编译合约
1.1 先在vscode里创建sol文件
pragma solidity ^0.4.24;
contract Immo{
address public ceo;
constructor() public {
ceo=msg.sender;
}
}
1.2.准备编译环境,sol文件都是通过solc工具编译的
npm install solc@0.4.24 --save
一定要声明版本
github.com/ethereum/solc-js
1.3.项目是通过react新建的
create-react-app imooc-on-blockchain
1.4.js脚本文件读写和编译sol
mkdir scripts
touch compile.js
// 文件模块
const fs = require(‘fs‘)
const path = require(‘path‘)
//编译模块solc
const solc = require(‘solc‘)
const contractPath = path.resolve(__dirname,‘../contracts/Imooc.sol‘)
// 获取合约文件内容
const source = fs.readFileSync(contractPath,‘utf-8‘)
// 编译
const ret = solc.compile(source)
// console.log(ret)
Object.keys(ret.contracts).forEach(name=>{
//过滤掉第一个key键,它前面有一个:,不需要
const contractName = name.slice(1)
//创建即将要写进数据的文件路径
const filePath = path.resolve(__dirname, `../src/compiled/${contractName}.json`)
//同步写数据
fs.writeFileSync(filePath,JSON.stringify(ret.contracts[name]))
console.log(`${filePath} bingo`)
})
// arr = [{name:‘react‘,content:‘xx‘,{name:‘vue‘,content:‘xx‘}]
1.5.配置package.json
"compile" :"node scripts/compile.js"
1.6.启动服务
npm run compile
编译.sol文件,生成一个json(后面部署,测试等需要这些数据)
-
bytecode
部署合约用的数据
-
interface接口声明
测试使用
2.合约自动编译
- 每次compile清空文件,重新生成
- 报错信息打印
- 能监听,自动compile
2.1 安装rimraf
清除模块
npm install rimraf --save
配置package.json
rimraf src/compiled/* && node scripts/compile.js
2.2 控制报错信息
打印出error,发现errors数组长度>1
则:
if(Array.isArray(ret.errors) && ret.errors.length>0){
// 出错了
console.log(ret.errors[0])
}else{
Object.keys(ret.contracts).forEach(name=>{
const contractName = name.slice(1)
const filePath = path.resolve(__dirname, `../src/compiled/${contractName}.json`)
fs.writeFileSync(filePath,JSON.stringify(ret.contracts[name]))
console.log(`${filePath} bingo`)
})
}
再调式的时候会出现:
2.3 使用钩子precompile
在package.json文件中
precompile:"rimraf src/compiled/*"
2.4 监听——使用Onchange模块
npm install onchange --save
"precompile": "rimraf src/compiled/* ",
"compile": "node scripts/compile.js",
"precompile:w": "npm run compile",
"compile:w": "onchange ‘contracts/*.sol‘ -- npm run compile"
只要合约发生了变化,就会重新编译
npm run compile:w
3.编写合约——课程列表
3.1 两个合约:课程数组,单个课程
3.2 方法:新建课程,获取课程
3.3 代码
pragma solidity ^0.4.24;
contract CourseList{
address public ceo;
address[] public courses;
constructor() public {
ceo = msg.sender;
}
function createCourse(string _name) public{
address newCourse = new Course(ceo,msg.sender, _name);
courses.push(newCourse);
}
// 获取课程所有地址
function getCourse() public view returns(address[]){
return courses;
}
}
contract Course{
string public name;
constructor(string _name) public {
name=_name;
}
}
4.测试合约
4.1 虚拟节点
ganache-cli
4.2测试用的模块
mocha
4.3 编写测试用例
const path = require(‘path‘);
const assert = require(‘assert‘);
describe(‘测试课程的智能‘, () => {
it(‘测试1+2是否等于3‘, () => {
assert.equal(1 + 2, 3);
})
})
4.4 测试合约方法
const path = require(‘path‘);
const assert = require(‘assert‘);
const Web3 = require(‘web3‘)
const ganache = require(‘ganache-cli‘)
//const BigNumber = require(‘bignumber.js‘)
const web3 = new Web3(ganache.provider())
// 引入合约的json
const CourseList = require(path.resolve(__dirname, ‘../src/compiled/CourseList.json‘))
const Course = require(path.resolve(__dirname, ‘../src/compiled/Course.json‘))
// 定义几个全局变量,所有测试都需要
let accounts
// 实例
let courseList
let course
describe(‘测试课程的智能‘, () => {
before(async () => {
// 测试前的数据初始化
accounts = await web3.eth.getAccounts()
console.log(accounts)
// 1. 虚拟部署一个合约
courseList = await new web3.eth.Contract(JSON.parse(CourseList.interface))
.deploy({ data: CourseList.bytecode })
.send({
// 最后一个是创建者
from: accounts[9],
gas: ‘5000000‘
})
})
it(‘合约部署成功‘, () => {
assert.ok(courseList.options.address)
})
it(‘测试添加课程‘, async () => {
const oldaddress = await courseList.methods.getCourse().call()
assert.equal(oldaddress.length, 0)
await courseList.methods.createCourse(
‘蜗牛的React课程‘
)
.send({
from: accounts[0],
gas: ‘5000000‘
})
const address = await courseList.methods.getCourse().call()
assert.equal(address.length, 1)
console.log(address)
})
})
4.5 配置package.json
"test:w": "mocha --watch"
4.6 运行指令
npm run test:w
4.6 测试结果
2019年09月27日20:31:07
5.添加删除课程指令
5.1 sol文件里函数编写
function removeCourse(uint _index) public {
// 只有ceo能删除
require(msg.sender == ceo);
// 根据索引删除
require(_index<courses.length);
}
5.2 package.json配置
"rebuild": "npm run compile && mocha",
"rebuild:w": "onchange ‘contracts/*.sol‘ ‘test/*.js‘ -- npm run rebuild"
作用是当合约发生变化时,先编译再测试。
5.3 运行
npm run rebuild
5.4 测试用例
const path = require(‘path‘);
const assert = require(‘assert‘);
const Web3 = require(‘web3‘)
const ganache = require(‘ganache-cli‘)
//const BigNumber = require(‘bignumber.js‘)
const web3 = new Web3(ganache.provider())
// 引入合约的json
const CourseList = require(path.resolve(__dirname, ‘../src/compiled/CourseList.json‘))
const Course = require(path.resolve(__dirname, ‘../src/compiled/Course.json‘))
// 定义几个全局变量,所有测试都需要
let accounts
// 实例
let courseList
let course
describe(‘测试课程的智能‘, () => {
before(async () => {
// 测试前的数据初始化
accounts = await web3.eth.getAccounts()
console.log(accounts)
// 1. 虚拟部署一个合约
courseList = await new web3.eth.Contract(JSON.parse(CourseList.interface))
.deploy({ data: CourseList.bytecode })
.send({
// 最后一个是创建者——重点
from: accounts[9],
gas: ‘5000000‘
})
})
it(‘合约部署成功‘, () => {
assert.ok(courseList.options.address)
})
it(‘测试添加课程‘, async () => {
const oldaddress = await courseList.methods.getCourse().call()
assert.equal(oldaddress.length, 0)
await courseList.methods.createCourse(
‘蜗牛的React课程‘
)
.send({
from: accounts[0],
gas: ‘5000000‘
})
const address = await courseList.methods.getCourse().call()
assert.equal(address.length, 1)
console.log(address)
})
it("添加课程的属性", async () => {
const [address] = await courseList.methods.getCourse().call()
// 添加的课程合约的地址
course = await new web3.eth.Contract(JSON.parse(Course.interface), address)
const name = await course.methods.name().call()
assert.equal(name, ‘蜗牛的React课程‘)
})
//删除功能
it("只能ceo能删", async () => {
await courseList.methods.createCourse(
‘蜗牛的Vue课程‘
)
.send({
from: accounts[0],
gas: ‘5000000‘
})
const address = await courseList.methods.getCourse().call()
assert.equal(address.length, 2)
await courseList.methods.removeCourse(0).send({
from:accounts[9],
gas:‘5000000‘
})
const address1 = await courseList.methods.getCourse().call()
console.log(address1)
assert.equal(address1.length,1)
})
})
5.6 发现bug
solidity提供的delete()方法删除了地址账号后,不是清除数据,而是将数据清0.
所以得修改合约里的方法
5.7 修改合约
function removeCourse(uint _index) public {
// 只有ceo能删除
require(msg.sender == ceo);
// 根据索引删除
require(_index<courses.length);
uint len = courses.length;
for(uint i=_index;i<len-1;i++){
courses[i] = courses[i+1];
}
delete courses[len-1];
courses.length--;
}
}
5.8 添加管理员的认证——合约方法
function isCeo() public view returns(bool){
return msg.sender==ceo;
}
5.9测试用例
it(‘判断是不是ceo‘,async ()=>{
const isCeo1 = await courseList.methods.isCeo().call({
from :accounts[9]
})
const isCeo2 = await courseList.methods.isCeo().call({
from :accounts[1]
})
assert.ok(isCeo1)
assert.ok(!isCeo2)
})
5.10 运行结果
npm run rebuild:w
5.11 完整代码
//Imooc.sol
pragma solidity ^0.4.24;
contract CourseList{
address public ceo;
address[] public courses;
constructor() public {
ceo = msg.sender;
}
function createCourse(string _name) public{
address newCourse = new Course(_name);
courses.push(newCourse);
}
// 获取课程所有地址
function getCourse() public view returns(address[]){
return courses;
}
function removeCourse(uint _index) public {
// 只有ceo能删除
require(msg.sender == ceo);
// 根据索引删除
require(_index<courses.length);
uint len = courses.length;
for(uint i=_index;i<len-1;i++){
courses[i] = courses[i+1];
}
delete courses[len-1];
courses.length--;
}
function isCeo() public view returns(bool){
return msg.sender==ceo;
}
}
contract Course{
string public name;
constructor(string _name) public {
name=_name;
}
}
//course.spec.js
const path = require(‘path‘);
const assert = require(‘assert‘);
const Web3 = require(‘web3‘)
const ganache = require(‘ganache-cli‘)
//const BigNumber = require(‘bignumber.js‘)
const web3 = new Web3(ganache.provider())
// 引入合约的json
const CourseList = require(path.resolve(__dirname, ‘../src/compiled/CourseList.json‘))
const Course = require(path.resolve(__dirname, ‘../src/compiled/Course.json‘))
// 定义几个全局变量,所有测试都需要
let accounts
// 实例
let courseList
let course
describe(‘测试课程的智能‘, () => {
before(async () => {
// 测试前的数据初始化
accounts = await web3.eth.getAccounts()
console.log(accounts)
// 1. 虚拟部署一个合约
courseList = await new web3.eth.Contract(JSON.parse(CourseList.interface))
.deploy({ data: CourseList.bytecode })
.send({
// 最后一个是创建者——重点
from: accounts[9],
gas: ‘5000000‘
})
})
it(‘合约部署成功‘, () => {
assert.ok(courseList.options.address)
})
it(‘测试添加课程‘, async () => {
const oldaddress = await courseList.methods.getCourse().call()
assert.equal(oldaddress.length, 0)
await courseList.methods.createCourse(
‘蜗牛的React课程‘
)
.send({
from: accounts[0],
gas: ‘5000000‘
})
const address = await courseList.methods.getCourse().call()
assert.equal(address.length, 1)
console.log(address)
})
it("添加课程的属性", async () => {
const [address] = await courseList.methods.getCourse().call()
// 添加的课程合约的地址
course = await new web3.eth.Contract(JSON.parse(Course.interface), address)
const name = await course.methods.name().call()
assert.equal(name, ‘蜗牛的React课程‘)
})
//删除功能
it("只能ceo能删", async () => {
await courseList.methods.createCourse(
‘蜗牛的Vue课程‘
)
.send({
from: accounts[0],
gas: ‘5000000‘
})
const address = await courseList.methods.getCourse().call()
assert.equal(address.length, 2)
await courseList.methods.removeCourse(0).send({
from:accounts[9],
gas:‘5000000‘
})
const address1 = await courseList.methods.getCourse().call()
console.log(address1)
assert.equal(address1.length,1)
})
it(‘判断是不是ceo‘,async ()=>{
const isCeo1 = await courseList.methods.isCeo().call({
from :accounts[9]
})
const isCeo2 = await courseList.methods.isCeo().call({
from :accounts[1]
})
assert.ok(isCeo1)
assert.ok(!isCeo2)
})
})
6.完善课程的属性,添加其他属性
6.1 添加一下属性
课程: owner
课程创建者 name
课程名 content
课程简介 target
课程目标是募资多少 ETH
fundingPrice 众筹价格
price 上线价格
img 课程头图
video 视频
count 多少人支持
isOnline 是否上线
6.2 合约里添加Course以及createCourse完善
//Imooc.sol
function createCourse(string _name,string _content,uint _target,uint _fundingPrice,uint _price,string _img) public{
address newCourse = new Course(ceo,msg.sender, _name, _content, _target, _fundingPrice, _price, _img);
courses.push(newCourse);
}
//Imooc.sol
contract Course{
address public ceo;
address public owner;
string public name;
string public content;
uint public target;
uint public fundingPrice;
uint public price;
string public img;
string public video;
bool public isOnline;
uint public count;
constructor(address _ceo, address _owner,string _name,string _content,uint _target,uint _fundingPrice,uint _price,string _img) public{
ceo = _ceo;
owner = _owner;
name = _name;
content = _content;
target = _target;
fundingPrice = _fundingPrice;
price = _price;
img = _img;
video = ‘‘;
count = 0;
isOnline = false;
}
}
6.3 编写测试逻辑,完善属性
it(‘测试添加课程‘, async () => {
const oldaddress = await courseList.methods.getCourse().call()
assert.equal(oldaddress.length, 0)
await courseList.methods.createCourse(
‘蜗牛的React课程‘,
"React+redux+reactrouter4开发招聘app",
web3.utils.toWei(‘8‘),
// 众筹价格
web3.utils.toWei(‘2‘),
web3.utils.toWei(‘4‘),
"图片的hash"
)
.send({
from: accounts[0],
gas: ‘5000000‘
})
const address = await courseList.methods.getCourse().call()
assert.equal(address.length, 1)
})
it("添加课程的属性", async () => {
const [address] = await courseList.methods.getCourse().call()
// 添加的课程合约的地址
course = await new web3.eth.Contract(JSON.parse(Course.interface), address)
const name = await course.methods.name().call()
const content = await course.methods.content().call()
const target = await course.methods.target().call()
const fundingPrice = await course.methods.fundingPrice().call()
const price = await course.methods.price().call()
const img = await course.methods.img().call()
const count = await course.methods.count().call()
const isOnline = await course.methods.isOnline().call()
assert.equal(name, ‘蜗牛的React课程‘)
assert.equal(content, ‘React+redux+reactrouter4开发招聘app‘)
assert.equal(target, web3.utils.toWei(‘8‘))
assert.equal(fundingPrice, web3.utils.toWei(‘2‘))
assert.equal(price, web3.utils.toWei(‘4‘))
assert.equal(img, "图片的hash")
assert.ok(!isOnline)
assert.equal(count, 0)
})
it("只能ceo能删", async ()=>{
await courseList.methods.createCourse(
‘蜗牛的Vue课程‘,
‘vue也是个好框架,简单好上手‘,
web3.utils.toWei(‘8‘),
// 众筹价格
web3.utils.toWei(‘2‘),
web3.utils.toWei(‘4‘),
"图片的hash1"
)
.send({
from:accounts[0],
gas:‘5000000‘
})
const address = await courseList.methods.getCourse().call()
assert.equal(address.length,2)
})
7.用户购买课程及课程上线
7.1 设置用户列表
// 用户购买信息
mapping(address=>uint) public users;
7.2 用户购买合约以及课程上线
课程上线之后众筹的钱立刻全部打给众筹者,之后再有用户购买,则进行分成。给ceo一成的利润。
// 众筹或者购买
function buy() public payable{
// 1. 用户没有购买过
require(users[msg.sender]==0);
if(isOnline){
// 如果上线了 必须得用上线价格购买
require(price == msg.value);
}else{
// 如果上线了 必须得用众筹价格购买
require(fundingPrice == msg.value);
}
users[msg.sender] = msg.value;
// 统计人数
count += 1;
if(target <= count*fundingPrice){
// 钱超出目标
if(isOnline){
// 上线之后的购买
uint value = msg.value;
// 分成
ceo.transfer(value/10);
owner.transfer(value-value/10);
}else{
// 没上线 第一次超出
isOnline = true;
// 转账
// 上线之前的钱,都在合约内部,众筹者是拿不到的
owner.transfer(count*fundingPrice);
}
}
}
7.3 用户获取课程详情
// 获取详情
function getDetail() public view returns(string,string,uint,uint,uint,string,string,uint,bool,uint){
uint role;
if(owner==msg.sender){
role = 0; //课程创建者
}else if(users[msg.sender]>0){
role = 1; // 已购买
}else{
role = 2; // 没买
}
return (
name,
content,
target,
fundingPrice,
price,
img,
video,
count,
isOnline,
role
);
}
7.4 上线之后众筹者才可以添加视频——ipfs地址
function addVideo(string _video) public{
require(msg.sender==owner);
require(isOnline==true);
video = _video;
}
7.5编译通过
8.课程购买测试编写
8.1 金钱转换
wei
finney
szabo
ether
1 ether == 10^3 finney
1 ether == 10^6 szabo
1 ether == 10^18 Wei
it(‘金钱转换‘,()=>{
assert.equal(web3.utils.toWei(‘2‘),‘2000000000000000000‘)
})
8.2 课程购买
it(‘课程购买‘,async()=>{
await course.methods.buy().send({
from:accounts[2],
value:web3.utils.toWei(‘2‘)
})
const value = await course.methods.users(accounts[2]).call()
const count = await course.methods.count().call()
assert.equal(value,web3.utils.toWei(‘2‘))
assert.equal(count,1)
// 输出value及users+
console.log("钱是:")
console.log(value)
// console.log("uers是:")
// 用户role的判断
const detail = await course.methods.getDetail().call({from:accounts[0]})
assert.equal(detail[9],0)
// 课程
console.log(detail)
const detail2 = await course.methods.getDetail().call({from:accounts[2]})
assert.equal(detail2[9],1)
const detail3 = await course.methods.getDetail().call({from:accounts[5]})
assert.equal(detail3[9],2)
})
8.3 引入bignumber.js
npm install bignumber.js
const BigNumber = require(‘bignumber.js‘)
8.4 还没上线的话,钱不入账
it(‘还没上线,购买的课不入账‘,async()=>{
const oldBlance = new BigNumber(await web3.eth.getBalance(accounts[0]))
await course.methods.buy().send({
from:accounts[3],
value:web3.utils.toWei(‘2‘)
})
const newBlance = new BigNumber(await web3.eth.getBalance(accounts[0]))
const diff = newBlance.minus(oldBlance)
assert.equal(diff,0)
})
8.5 还没上线的话,不能上传视频
it(‘还没上线,不能上传视频‘,async()=>{
try{
await course.methods.addVideo(‘video的hash‘)
.send({
from:accounts[0],
gas:‘5000000‘
})
assert.ok(false)
}catch(e){
console.log(e)
assert.equal(e.name,‘o‘)
}
})
8.6 不能重复购买
it(‘不能重复购买‘,async()=>{
try{
await course.methods.buy().send({
from:accounts[2],
value:web3.utils.toWei(‘2‘)
})
assert.ok(false)
}catch(e){
console.log(e.name)
assert.equal(e.name,‘RuntimeError‘)
}
})
8.7 课程必须是众筹价格
it(‘课程必须是众筹价格‘,async()=>{
try{
await course.methods.buy().send({
from:accounts[4],
value:web3.utils.toWei(‘3‘)
})
assert.ok(false)
}catch(e){
assert.equal(e.name,‘RuntimeError‘)
}
})
8.8 众筹上线后,钱到账
it(‘众筹上线后,钱到账‘,async()=>{
const oldBlance = new BigNumber(await web3.eth.getBalance(accounts[0]))
// 8 众筹家是2 买4次就上线
await course.methods.buy().send({
from:accounts[4],
value:web3.utils.toWei(‘2‘)
})
await course.methods.buy().send({
from:accounts[5],
value:web3.utils.toWei(‘2‘)
})
const count = await course.methods.count().call()
const isOnline = await course.methods.isOnline().call()
assert.equal(count,4)
assert.ok(isOnline)
const newBlance = new BigNumber(await web3.eth.getBalance(accounts[0]))
const diff = newBlance.minus(oldBlance)
assert.equal(diff,web3.utils.toWei(‘8‘))
})
8.9 课程必须是线上的价格
it(‘课程必须是线上的价格‘,async()=>{
try{
await course.methods.buy().send({
from:accounts[6],
value:web3.utils.toWei(‘2‘)
})
assert.ok(false)
}catch(e){
assert.equal(e.name,‘RuntimeError‘)
}
})
it(‘课程必须是线上的价格2‘,async()=>{
// try{
await course.methods.buy().send({
from:accounts[6],
value:web3.utils.toWei(‘4‘)
})
const count = await course.methods.count().call()
assert.equal(count,5)
// }catch(e){
// assert.equal(e.name,‘RuntimeError‘)
// }
})
8.10 上线之后购买 有分成收益
it(‘上线之后购买 有分成收益‘,async()=>{
// try{
// ceo的约
const oldCeoBlance = new BigNumber(await web3.eth.getBalance(accounts[9]))
// 课程创建者
const oldOwnerBlance = new BigNumber(await web3.eth.getBalance(accounts[0]))
await course.methods.buy().send({
from:accounts[7],
value:web3.utils.toWei(‘4‘)
})
const newCeoBlance = new BigNumber(await web3.eth.getBalance(accounts[9]))
const newOwnerBlance = new BigNumber(await web3.eth.getBalance(accounts[0]))
const diffCeo = newCeoBlance.minus(oldCeoBlance)
const diffOwner = newOwnerBlance.minus(oldOwnerBlance)
assert.equal(diffCeo, web3.utils.toWei(‘0.4‘))
assert.equal(diffOwner, web3.utils.toWei(‘3.6‘))
// }catch(e){
// assert.equal(e.name,‘RuntimeError‘)
// }
})
8.11 上线之后,可以上传视频
it(‘上线之后,可以上传视频‘,async()=>{
await course.methods.addVideo(‘video的hash‘)
.send({
from:accounts[0],
gas:‘5000000‘
})
const video = await course.methods.video().call()
assert.equal(video,‘video的hash‘)
})
8.12 完整测试代码
const path = require(‘path‘);
const assert = require(‘assert‘);
const Web3 = require(‘web3‘)
const ganache = require(‘ganache-cli‘)
const BigNumber = require(‘bignumber.js‘)
const web3 = new Web3(ganache.provider())
// 引入合约的json
const CourseList = require(path.resolve(__dirname, ‘../src/compiled/CourseList.json‘))
const Course = require(path.resolve(__dirname, ‘../src/compiled/Course.json‘))
// 定义几个全局变量,所有测试都需要
let accounts
// 实例
let courseList
let course
describe(‘测试课程的智能‘, () => {
before(async () => {
// 测试前的数据初始化
accounts = await web3.eth.getAccounts()
console.log(accounts)
// 1. 虚拟部署一个合约
courseList = await new web3.eth.Contract(JSON.parse(CourseList.interface))
.deploy({ data: CourseList.bytecode })
.send({
// 最后一个是创建者——重点
from: accounts[9],
gas: ‘5000000‘
})
})
it(‘合约部署成功‘, () => {
assert.ok(courseList.options.address)
})
// it(‘测试添加课程‘, async () => {
// const oldaddress = await courseList.methods.getCourse().call()
// assert.equal(oldaddress.length, 0)
// await courseList.methods.createCourse(
// ‘蜗牛的React课程‘
// )
// .send({
// from: accounts[0],
// gas: ‘5000000‘
// })
// const address = await courseList.methods.getCourse().call()
// assert.equal(address.length, 1)
// console.log(address)
// })
// it("添加课程的属性", async () => {
// const [address] = await courseList.methods.getCourse().call()
// // 添加的课程合约的地址
// course = await new web3.eth.Contract(JSON.parse(Course.interface), address)
// const name = await course.methods.name().call()
// assert.equal(name, ‘蜗牛的React课程‘)
// })
it(‘测试添加课程‘, async () => {
const oldaddress = await courseList.methods.getCourse().call()
assert.equal(oldaddress.length, 0)
await courseList.methods.createCourse(
‘蜗牛的React课程‘,
"React+redux+reactrouter4开发招聘app",
web3.utils.toWei(‘8‘),
// 众筹价格
web3.utils.toWei(‘2‘),
web3.utils.toWei(‘4‘),
"图片的hash"
)
.send({
from: accounts[0],
gas: ‘5000000‘
})
const address = await courseList.methods.getCourse().call()
assert.equal(address.length, 1)
})
it("添加课程的属性", async () => {
const [address] = await courseList.methods.getCourse().call()
// 添加的课程合约的地址
course = await new web3.eth.Contract(JSON.parse(Course.interface), address)
const name = await course.methods.name().call()
const content = await course.methods.content().call()
const target = await course.methods.target().call()
const fundingPrice = await course.methods.fundingPrice().call()
const price = await course.methods.price().call()
const img = await course.methods.img().call()
const count = await course.methods.count().call()
const isOnline = await course.methods.isOnline().call()
assert.equal(name, ‘蜗牛的React课程‘)
assert.equal(content, ‘React+redux+reactrouter4开发招聘app‘)
assert.equal(target, web3.utils.toWei(‘8‘))
assert.equal(fundingPrice, web3.utils.toWei(‘2‘))
assert.equal(price, web3.utils.toWei(‘4‘))
assert.equal(img, "图片的hash")
assert.ok(!isOnline)
assert.equal(count, 0)
})
//删除功能
// it("只能ceo能删", async () => {
// await courseList.methods.createCourse(
// ‘蜗牛的Vue课程‘
// )
// .send({
// from: accounts[0],
// gas: ‘5000000‘
// })
// const address = await courseList.methods.getCourse().call()
// assert.equal(address.length, 2)
// await courseList.methods.removeCourse(0).send({
// from: accounts[9],
// gas: ‘5000000‘
// })
// const address1 = await courseList.methods.getCourse().call()
// console.log(address1)
// assert.equal(address1.length, 1)
// })
it("只能ceo能删", async ()=>{
await courseList.methods.createCourse(
‘蜗牛的Vue课程‘,
‘vue也是个好框架,简单好上手‘,
web3.utils.toWei(‘8‘),
// 众筹价格
web3.utils.toWei(‘2‘),
web3.utils.toWei(‘4‘),
"图片的hash1"
)
.send({
from:accounts[0],
gas:‘5000000‘
})
const address = await courseList.methods.getCourse().call()
assert.equal(address.length,2)
})
it(‘判断是不是ceo‘, async () => {
const isCeo1 = await courseList.methods.isCeo().call({
from: accounts[9]
})
const isCeo2 = await courseList.methods.isCeo().call({
from: accounts[1]
})
assert.ok(isCeo1)
assert.ok(!isCeo2)
})
it(‘金钱转换‘,()=>{
assert.equal(web3.utils.toWei(‘2‘),‘2000000000000000000‘)
})
it(‘课程购买‘,async()=>{
await course.methods.buy().send({
from:accounts[2],
value:web3.utils.toWei(‘2‘)
})
const value = await course.methods.users(accounts[2]).call()
const count = await course.methods.count().call()
assert.equal(value,web3.utils.toWei(‘2‘))
assert.equal(count,1)
// 输出value及users+
console.log("钱是:")
console.log(value)
// console.log("uers是:")
// 用户role的判断
const detail = await course.methods.getDetail().call({from:accounts[0]})
assert.equal(detail[9],0)
// 课程
console.log(detail)
const detail2 = await course.methods.getDetail().call({from:accounts[2]})
assert.equal(detail2[9],1)
const detail3 = await course.methods.getDetail().call({from:accounts[5]})
assert.equal(detail3[9],2)
})
it(‘还没上线,购买的课不入账‘,async()=>{
const oldBlance = new BigNumber(await web3.eth.getBalance(accounts[0]))
await course.methods.buy().send({
from:accounts[3],
value:web3.utils.toWei(‘2‘)
})
const newBlance = new BigNumber(await web3.eth.getBalance(accounts[0]))
const diff = newBlance.minus(oldBlance)
assert.equal(diff,0)
})
it(‘还没上线,不能上传视频‘,async()=>{
try{
await course.methods.addVideo(‘video的hash‘)
.send({
from:accounts[0],
gas:‘5000000‘
})
assert.ok(false)
}catch(e){
console.log(e)
assert.equal(e.name,‘o‘)
}
})
it(‘不能重复购买‘,async()=>{
try{
await course.methods.buy().send({
from:accounts[2],
value:web3.utils.toWei(‘2‘)
})
assert.ok(false)
}catch(e){
console.log(e.name)
assert.equal(e.name,‘RuntimeError‘)
}
})
it(‘课程必须是众筹价格‘,async()=>{
try{
await course.methods.buy().send({
from:accounts[4],
value:web3.utils.toWei(‘3‘)
})
assert.ok(false)
}catch(e){
assert.equal(e.name,‘RuntimeError‘)
}
})
it(‘众筹上线后,钱到账‘,async()=>{
const oldBlance = new BigNumber(await web3.eth.getBalance(accounts[0]))
// 8 众筹家是2 买4次就上线
await course.methods.buy().send({
from:accounts[4],
value:web3.utils.toWei(‘2‘)
})
await course.methods.buy().send({
from:accounts[5],
value:web3.utils.toWei(‘2‘)
})
const count = await course.methods.count().call()
const isOnline = await course.methods.isOnline().call()
assert.equal(count,4)
assert.ok(isOnline)
const newBlance = new BigNumber(await web3.eth.getBalance(accounts[0]))
const diff = newBlance.minus(oldBlance)
assert.equal(diff,web3.utils.toWei(‘8‘))
})
it(‘课程必须是线上的价格‘,async()=>{
try{
await course.methods.buy().send({
from:accounts[6],
value:web3.utils.toWei(‘2‘)
})
assert.ok(false)
}catch(e){
assert.equal(e.name,‘RuntimeError‘)
}
})
it(‘课程必须是线上的价格2‘,async()=>{
// try{
await course.methods.buy().send({
from:accounts[6],
value:web3.utils.toWei(‘4‘)
})
const count = await course.methods.count().call()
assert.equal(count,5)
// }catch(e){
// assert.equal(e.name,‘RuntimeError‘)
// }
})
it(‘上线之后购买 有分成收益‘,async()=>{
// try{
// ceo的约
const oldCeoBlance = new BigNumber(await web3.eth.getBalance(accounts[9]))
// 课程创建者
const oldOwnerBlance = new BigNumber(await web3.eth.getBalance(accounts[0]))
await course.methods.buy().send({
from:accounts[7],
value:web3.utils.toWei(‘4‘)
})
const newCeoBlance = new BigNumber(await web3.eth.getBalance(accounts[9]))
const newOwnerBlance = new BigNumber(await web3.eth.getBalance(accounts[0]))
const diffCeo = newCeoBlance.minus(oldCeoBlance)
const diffOwner = newOwnerBlance.minus(oldOwnerBlance)
assert.equal(diffCeo, web3.utils.toWei(‘0.4‘))
assert.equal(diffOwner, web3.utils.toWei(‘3.6‘))
// }catch(e){
// assert.equal(e.name,‘RuntimeError‘)
// }
})
it(‘上线之后,可以上传视频‘,async()=>{
await course.methods.addVideo(‘video的hash‘)
.send({
from:accounts[0],
gas:‘5000000‘
})
const video = await course.methods.video().call()
assert.equal(video,‘video的hash‘)
})
})
END
以上是关于62solidity环境搭建编译及编写合约-3——2020年07月12日12:55:51的主要内容,如果未能解决你的问题,请参考以下文章
solidity 智能合约(3):使用truffle编译部署及测试合约
Web3与智能合约:开发一个简单的DApp并部署到以太坊测试网(Solidity+Hardhat+React)① 环境搭建