Buy Article
update the contract contracts/ChainList.sol add sellArticleEvent and buyArticle function
pragma solidity ^0.4.2;
contract ChainList {
// State variables
address seller;
string name;
string description;
uint256 price;
// Events
event sellArticleEvent(address indexed _seller, string _name, uint256 _price);
+ event buyArticleEvent(address indexed _seller, address indexed _buyer, string _name, uint256 _price);
// sell an article
function sellArticle(string _name, string _description, uint256 _price) public {
seller = msg.sender;
name = _name;
description = _description;
price = _price;
sellArticleEvent(seller, name, price);
}
// get the article
function getArticle() public constant returns (
address _seller,
string _name,
string _description,
uint256 _price) {
return (seller, name, description, price);
}
+
+ // buy an article
+ function buyArticle() payable public {
+ // should be ready for sale
+ require(seller != 0x00);
+
+ // should not be sold
+ require(buyer == 0x00);
+
+ // you cannot by your own article
+ require(msg.sender != seller);
+
+ // the value send transacted corresponds to the article price
+ require(msg.value == price);
+
+ // keep the buyer's information
+ buyer = msg.sender;
+
+ // the buyer can buy the article
+ seller.transfer(msg.value);
+
+ //trigger event
+ buyArticleEvent(seller, buyer, name, price);
+ }
}
4 way to interrupt a contract function:
require(preconditions)assert(internal error)revert(other business errors)throw(legacy)
When a function call is interrupted:
- Transaction value will be refunded to message sender.
- Any state change will be reverted.
- Execution is interrupted here and no more gas will be spend.
- All gas spend till this point will be paid to the miner.
Try to sell and buy article in truffle develop console.
truffle(develop)> migrate
...
truffle(develop)> ChainList.deployed().then(i => app = i)
...
truffle(develop)> app.sellArticle('article 1', 'Description of article 1', web3.toWei(10, 'ether'), {from: web3.eth.accounts[1]})
{ tx: '0xe92110d8af885dca7067277d5bf85642eef350aaa98c42a688ba87c24f0f524f',
receipt:
{ transactionHash: '0xe92110d8af885dca7067277d5bf85642eef350aaa98c42a688ba87c24f0f524f',
transactionIndex: 0,
blockHash: '0x6619aca468c6054c48e5658a6bc069760cf3fcb276eca9edc506f4bb7b90dc1f',
blockNumber: 11,
gasUsed: 110369,
cumulativeGasUsed: 110369,
contractAddress: null,
logs: [ [Object] ],
status: 1 },
logs:
[ { logIndex: 0,
transactionIndex: 0,
transactionHash: '0xe92110d8af885dca7067277d5bf85642eef350aaa98c42a688ba87c24f0f524f',
blockHash: '0x6619aca468c6054c48e5658a6bc069760cf3fcb276eca9edc506f4bb7b90dc1f',
blockNumber: 11,
address: '0x345ca3e014aaf5dca488057592ee47305d9b3e10',
type: 'mined',
event: 'sellArticleEvent',
args: [Object] } ] }
truffle(develop)> app.getArticle.call()
[ '0xf17f52151ebef6c7334fad080c5704d77216b732',
'0x0000000000000000000000000000000000000000',
'article 1',
'Description of article 1',
BigNumber { s: 1, e: 19, c: [ 100000 ] } ]
truffle(develop)> var buyEvent = app.buyArticleEvent({_seller: web3.eth.accounts[1]}, {fromBlock: 0, toBlock: 'latest'}).watch((err, event) => console.log(event));
undefined
truffle(develop)> var txRes = app.buyArticle({from: web3.eth.accounts[2], value: web3.toWei(10, 'ether')})
undefined
truffle(develop)> { logIndex: 0,
transactionIndex: 0,
transactionHash: '0xc400c89a4a734c7059996768fb259740b79bee34675ffc5c0c36894926280733',
blockHash: '0x18894af68e2f1436d8f09df6b5dfbf4c24d9713989bdef74d2c357045b604127',
blockNumber: 12,
address: '0x345ca3e014aaf5dca488057592ee47305d9b3e10',
type: 'mined',
event: 'buyArticleEvent',
args:
{ _seller: '0xf17f52151ebef6c7334fad080c5704d77216b732',
_buyer: '0xc5fdf4076b8f3a5357c5e395ab970b5b54098fef',
_name: 'article 1',
_price: BigNumber { s: 1, e: 19, c: [Array] } } }
truffle(develop)> app.getArticle.call()
[ '0xf17f52151ebef6c7334fad080c5704d77216b732',
'0xc5fdf4076b8f3a5357c5e395ab970b5b54098fef',
'article 1',
'Description of article 1',
BigNumber { s: 1, e: 19, c: [ 100000 ] } ]
truffle(develop)> web3.eth.getBalance(web3.eth.accounts[1]).toString()
'109971865100000000000'
truffle(develop)> web3.eth.getBalance(web3.eth.accounts[2]).toString()
'89994545200000000000'
Restart the console and try to buy the article with insufficient ETH.
truffle(develop)> migrate
...
truffle(develop)> ChainList.deployed().then(i => app = i)
...
truffle(develop)> app.sellArticle('article 1', 'Description of article 1', web3.toWei(10, 'ether'), {from: web3.eth.accounts[1]})
...
truffle(develop)> web3.eth.getBalance(web3.eth.accounts[1]).toString()
'99988963100000000000'
truffle(develop)> var txRes = app.buyArticle({from: web3.eth.accounts[2], value: web3.toWei(5, 'ether')})
undefined
truffle(develop)> (node:20581) UnhandledPromiseRejectionWarning: Error: VM Exception while processing transaction: revert
at Object.InvalidResponse (/usr/local/lib/node_modules/truffle/build/cli.bundled.js:41484:16)
at /usr/local/lib/node_modules/truffle/build/cli.bundled.js:329530:36
at /usr/local/lib/node_modules/truffle/build/cli.bundled.js:325200:9
at XMLHttpRequest.request.onreadystatechange (/usr/local/lib/node_modules/truffle/build/cli.bundled.js:328229:7)
at XMLHttpRequestEventTarget.dispatchEvent (/usr/local/lib/node_modules/truffle/build/cli.bundled.js:176415:18)
at XMLHttpRequest._setReadyState (/usr/local/lib/node_modules/truffle/build/cli.bundled.js:176705:12)
at XMLHttpRequest._onHttpResponseEnd (/usr/local/lib/node_modules/truffle/build/cli.bundled.js:176860:12)
at IncomingMessage.<anonymous> (/usr/local/lib/node_modules/truffle/build/cli.bundled.js:176820:24)
at IncomingMessage.emit (events.js:164:20)
at endReadableNT (_stream_readable.js:1062:12)
(node:20581) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:20581) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
truffle(develop)> web3.eth.getBalance(web3.eth.accounts[1]).toString()
'99988963100000000000'
truffle(develop)> web3.eth.getBalance(web3.eth.accounts[2]).toString()
'99997757100000000000'