智能合约自学笔记之三买家

其实除了买家后面还有,不过我看了一会实在是放弃了,因为是个全栈视频,web相关我实在是不行了,因为js我真是一点都不会。教程中用react库,在web上链接到ganache这个虚拟区块链上,同时metamask也获取ganache数据显示出来,最后全栈为用户提供了web接口,这就是全部过程。最有意思的是,这个系统所有的调用都用的js,只有脚本用的solidity。脚本用的面向对象,其实面向对象长得都一样,我用C++的底子完全可以理解。这就是我学会的东西。我在网上看到还有用其它语言写合约的。
其实我想学会的是设计dapp,而smart contract只是二代区块链,教程的题目也是dapp university。不过仔细想一下,web不管是调用smart contract还是dapp,效果都是一样的,只不过smart contract需要付钱,dapp不需要付钱,再有些其它的修改罢了,我理解为dapp只是在smart contract的应用场景上多了一些,本质没有太大变化。
下面尽快学习网络和操作系统的基本知识,保证工作能做好,后续是搞js还是换语言搞dapp还是怎么样,再说吧,该定计划了蓝莓侠

合约

// the file is for creating smart contract
pragma solidity ^0.5.0;

contract Marketplace {
	//state variable
    string public name;

    mapping(uint => Product) public products; //key and value,id and smartcontract
	uint public productCount = 0;//solidity dosen't has size function for mapping

    struct Product {
    	uint id; //unique
    	string name;
    	uint price;
		address payable owner;
    	bool purchased;
    }

	event ProductCreated(	
    	uint id,
		string name,
    	uint price,
		address payable owner,
    	bool purchased
	);

	event ProductPurchased(
		uint id,
		string name,
		uint price,
		address payable owner,
		bool purchased
	);
    constructor() public {
        name = "Dapp University Marketplace";
    }
	
	function createProduct(string memory _name, uint _price) public{
		//Make sure parameters are correct
		require(bytes(_name).length > 0);
		require(_price > 0);

		//Increment product count
		productCount++;//因为productCount初始值为0,所以这个要放在创建product之前
		// Create  the product,将新建的product加入哈希中
		products[productCount] = Product(productCount, _name, _price, msg.sender, false);//msg是个全局变量,sender就是调用ganache的那个用户,也就是谁调创建这个合约,msg.sender就是谁
		//Trigger an event
		emit ProductCreated(productCount, _name, _price, msg.sender, false);
	}

	//<按照id将product从协议中提出来,修改后再放回去,这样可以保证原子性,智能合约肯定要考虑并发的
	function purchaseProduct(uint _id) public payable {
		// Fetch the product
		Product memory _product = products[_id];
		// Fetch the owner
		address payable _seller = _product.owner;
		// Make sure the product has a valid id
		require(_product.id > 0 && _product.id <= productCount);
		// Require that there is enough Ether in the transaction
		require(msg.value >= _product.price);
		// Require that the product has not been purchased already
		require(!_product.purchased);
		// Require that the buyer is not the seller
		require(_seller != msg.sender);
		// Transfer ownership to the buyer
		_product.owner = msg.sender;
		// Mark as purchased
		_product.purchased = true;
		// Update the product
		products[_id] = _product;
		// Pay the seller by sending them Ether
		address(_seller).transfer(msg.value);
		// Trigger an event
		emit ProductPurchased(productCount, _product.name, _product.price, msg.sender, true);
	}

}

调用过程

//it's for calling smartcontract
const Marketplace = artifacts.require('./Marketplace.sol') //import the contract into the test file, of course the smartcontact is defined in this file

require('chai')
  .use(require('chai-as-promised'))
  .should()

contract('Marketplace', ([deployer, seller, buyer]) =>{
	let marketplace

	before(async () => {
		marketplace = await Marketplace.deployed()//deployed这个函数是异步的,await关键字为了将异步变为同步
	}) 

	describe('deployment', async() => { //mocha which is a framework of js
		it('deploys successfully', async()=> {
			const address = await marketplace.address
			assert.notEqual(address, 0x0) //chai for assert
			assert.notEqual(address, null)
			assert.notEqual(address, '')
			assert.notEqual(address, undefined)
		})

		it('has a name', async() => {
			const name = await marketplace.name()
			assert.equal(name, 'Dapp University Marketplace')
		})

	})
	
	describe('products', async() => { //mocha which is a framework of js
		let result, productCount

		before(async () => {
			result = await marketplace.createProduct('iPhone X', web3.utils.toWei('1','Ether'),{from:seller })//使用的时候都是用的wei为单位,但是因为wei特别的小,IPHONEX价格为2以太币比较合适,就用个转换函数
			productCount = await marketplace.productCount()
		}) 
		
		it('creates products', async() => {
			// success
			assert.equal(productCount, 1)
			const event = result.logs[0].args
			assert.equal(event.id.toNumber(), productCount.toNumber(), 'id is correct')
			assert.equal(event.name, 'iPhone X', 'name is correct')
			assert.equal(event.price, '1000000000000000000', 'price is correct')
			assert.equal(event.owner,seller ,'owner is correct')
			assert.equal(event.purchased,false,'purchased is correct')
			// FAILURE: Product must have a name
			await await marketplace.createProduct('', web3.utils.toWei('1', 'Ether'), { from: seller }).should.be.rejected;
			// FAILURE: Product must have a price
			await await marketplace.createProduct('iPhone X', 0, { from: seller }).should.be.rejected;
		})

		it('lists products', async() => {
			const product  = await marketplace.products(productCount)
			assert.equal(product.id.toNumber(), productCount.toNumber(), 'id is correct')
			assert.equal(product.name, 'iPhone X', 'name is correct')
			assert.equal(product.price, '1000000000000000000', 'price is correct')
			assert.equal(product.owner,seller ,'owner is correct')
			assert.equal(product.purchased,false,'purchased is correct')
		})

		it('sells products', async () => {
			// Track the seller balance before purchase
			let oldSellerBalance
			oldSellerBalance = await web3.eth.getBalance(seller)
			oldSellerBalance = new web3.utils.BN(oldSellerBalance)

			// SUCCESS: Buyer makes purchase
			result = await marketplace.purchaseProduct(productCount, { from: buyer, value: web3.utils.toWei('1', 'Ether')})

			// Check logs
			const event = result.logs[0].args
			assert.equal(event.id.toNumber(), productCount.toNumber(), 'id is correct')
			assert.equal(event.name, 'iPhone X', 'name is correct')
			assert.equal(event.price, '1000000000000000000', 'price is correct')
			assert.equal(event.owner, buyer, 'owner is correct')
			assert.equal(event.purchased, true, 'purchased is correct')

			// Check that seller received funds
			let newSellerBalance
			newSellerBalance = await web3.eth.getBalance(seller)
			newSellerBalance = new web3.utils.BN(newSellerBalance)

			let price
			price = web3.utils.toWei('1', 'Ether')
			price = new web3.utils.BN(price)

			const exepectedBalance = oldSellerBalance.add(price)

		//	assert.equal(newSellerBalance.toString(), exepectedBalance.toString())

			// FAILURE: Tries to buy a product that does not exist, i.e., product must have valid id
			await marketplace.purchaseProduct(99, { from: buyer, value: web3.utils.toWei('1', 'Ether')}).should.be.rejected;      // FAILURE: Buyer tries to buy without enough ether
			// FAILURE: Buyer tries to buy without enough ether
			await marketplace.purchaseProduct(productCount, { from: buyer, value: web3.utils.toWei('0.5', 'Ether') }).should.be.rejected;
			// FAILURE: Deployer tries to buy the product, i.e., product can't be purchased twice
			await marketplace.purchaseProduct(productCount, { from: deployer, value: web3.utils.toWei('1', 'Ether') }).should.be.rejected;
			// FAILURE: Buyer tries to buy again, i.e., buyer can't be the seller
			await marketplace.purchaseProduct(productCount, { from: buyer, value: web3.utils.toWei('1', 'Ether') }).should.be.rejected;
		})

	})

})

你可能感兴趣的:(区块链之以太坊)