上次完成了經典範例,可是合約內容並沒有牽扯到數字貨幣的交換(除了gas)。今天帶大家快速的看一下數字貨幣交易的部份。
在此之前需要先了解一個概念 :「每個合約也都是一個帳號」,同樣可以收錢和付錢。乙太坊好像沒有直接由使用者A付錢給B的方法。不過從架構上思考也蠻合理的,先經由合約在轉發給對象。在EOS上雖然transfer
可以指定要給誰,不過實際上,交易這部份EOS也完全是由智能合約定義。接著,我們試著以經典範例來修改(由於幾乎不會動到關鍵部份,完全全新的也是可以)。
在合約類別剛開始就先加入
event LogMessage(string message);
event LogValue(uint value);
function pay() public payable{
emit LogMessage("Pay: ");
emit LogValue(msg.value);
}
這是為了讓合約有付費的方式(payable
)。這段除了可以呼叫以外,實際作用不太大。唯一要注意的是msg.value
,這是呼叫這個方法的使用者,付給這份合約的數字貨幣(乙太幣)。
然後,是收錢的方法:
function withdraw() public{
emit LogMessage("Widthdraw: 1 ether");
msg.sender.transfer(1 ether);
}
同樣,要主意的只有msg.sender.transfer(1 ether);
。這意思是由合約轉發1 ether
給呼叫這個方法的人(sender
)。語意上我覺得有點會讓人誤會,有點像是sender要發送(transfer)什麼給誰,按理需要兩個參數,實際只需要數量即可,這是因為是由合約發給sender。
接著,將網頁邏輯程式接上,在src/js/app.js
的bindEvents
增加:
$(document).on('click', '#btn-pay', App.handlePay);
$(document).on('click', '#btn-withdraw', App.handleWithDraw);
然後轉寫App
提供的handlePay
和handleWithDraw
的方法:
handlePay: function(event){
event.preventDefault();
var adoptionInstance;
web3.eth.getAccounts(function(error, accounts) {
if (error) {
console.log(error);
}
var account = accounts[0];
App.contracts.Adoption.deployed().then(function(instance) {
adoptionInstance = instance;
// Execute adopt as a transaction by sending account
return adoptionInstance.pay({
from: web3.eth.accounts[0],
gas: 3000000,
value: 10**18*5,
});
}).then(function(result) {
console.log(result);
}).catch(function(err) {
console.log(err.message);
});
});
},
handleWithDraw: function(event){
event.preventDefault();
var adoptionInstance;
web3.eth.getAccounts(function(error, accounts) {
if (error) {
console.log(error);
}
var account = accounts[0];
App.contracts.Adoption.deployed().then(function(instance) {
adoptionInstance = instance;
// Execute adopt as a transaction by sending account
return adoptionInstance.withdraw();
}).then(function(result) {
console.log(result);
}).catch(function(err) {
console.log(err.message);
});
});
}
當中value: 10**18*5,
代表發送給合約5乙太幣。相對來說,一次能裡出來多少,就是在合約中定義的msg.sender.transfer(1 ether);
。
最後在網頁界面上加上兩個按鈕:
<button id="btn-pay">Pay</button>
<button id="btn-withdraw">Withdraw</button>
pay
的出發與以往不同,不只需要付出gas,還轉發了數字貨幣。同樣的,withdraw
,也不同,雖然需要消耗gas,卻能獲得1 eth。
合約程式
pragma solidity ^0.5.0;
contract Adoption {
address[16] public adopters;
event LogMessage(string message);
event LogValue(uint value);
// Adopting a pet
function adopt(uint petId) public returns (uint) {
require(petId >= 0 && petId <= 15);
adopters[petId] = msg.sender;
return petId;
}
// Retrieving the adopters
function getAdopters() public view returns (address[16] memory) {
return adopters;
}
function pay() public payable{
emit LogMessage("Pay: ");
emit LogValue(msg.value);
}
function withdraw() public{
emit LogMessage("Widthdraw: 1 ether");
msg.sender.transfer(1 ether);
}
}
網頁js
https://www.codepile.net/pile/a2roLlkv
網頁
https://www.codepile.net/pile/6OWXMVYb