Trang chủ Tạp chí Lập trình smart contract: Phần 5 — Viết test case cho smart contracts

Lập trình smart contract: Phần 5 — Viết test case cho smart contracts

Tiếp tục loạt bài thực tế phát triển dApp, giờ chúng ta sẽ nâng độ khó lên một chút xíu khi đi vào hoàn thiện nội dung của smart contracts và viết test case kiểm thử.

Smart contracts

Events

Các smart contracts được thực thi trong môi trường của EVM, hoàn toàn tách biệt với môi trường bên ngoài. Để có thể trigger một sự kiệu ra bên ngoài EVM ta gửi các events được định nghĩa trước:

//New job append
 event NewJob(
 uint256 indexed id,
 address creator,
 uint256 salary,
 uint256 timeOut);

//An woker start working
 event TakeJob(
 uint256 indexed id,
 address indexed labor);

Các event này có thể lắng nghe thông qua các filter cung cấp bởi web3js, việc này sẽ cung cấp thêm thông tin, trigger các hệ thống third party hoặc đơn giản là điều chỉnh lại front-end.

Modifier

Để smart contract của mình bảo mật hơn, mình thêm các modifier. Mục tiêu là kiểm tra arguments trước khi method được trigger (Ethereum là một hệ hoàn toàn thụ động, không có khả năng tự tính toán).

//Transaction must contant Ethereum
 modifier onlyHaveFund {
 require(msg.value > MINIUM_SALARY);
 _;
 }

Trên đây bạn có thể đọc thấy modifier rất rõ nghĩa, với modifier này mình check số Ethereum có trong transaction. Biến msg sẽ chứa vài thông tin hữu ích của transaction (eg. msg.sender: address của người gửi, msg.value: số ethereum tính bằng wei). Để biết rõ thêm global variable các bạn xem ở đây.

Smart contract

Mình viết lại smart contract, thêm hai function mới takeJob() và viewJob():

//Take job

function

takeJob (uint256 jobId)

public onlyValidMortgage(jobId) onlyValidId(jobId) onlyValidJob(jobId)

{

//Trigger event to log labor

TakeJob(jobId, msg.sender);



//Change working state

jobData[jobId].start = block.timestamp;

}



//Veiw job data

function

viewJob(uint256 jobId)

public onlyValidId(jobId) constant returns (

uint256 id,

address creator,

uint256 salary,

uint256 start,

uint256 end,

uint256 timeOut,

bytes title,

bytes description)

{

Job memory jobReader = jobData[jobId];

return (jobReader.id,

jobReader.creator,

jobReader.salary,

jobReader.start,

jobReader.end,

jobReader.timeOut,

jobReader.title,

jobReader.description);

}

Trong phần struct mình cũng update thêm các biến liên quan tới thời gian, và để tiện xử lý mình sẽ sữ dụng Unix timestamp (Solidity không có kiểu datime nên dùng Unix time là tiện nhất):

uint256 start;

uint256 end;

uint256 timeOut;

Chúng ta có toàn bộ mã nguồn như sau:

pragma solidity ^0.4.18;





contract PartTime {



//Job structure

struct Job {

uint256 id;

address creator;

uint256 salary;

uint256 start;

uint256 end;

uint256 timeOut;

bytes title;

bytes description;

}



//New job append

event NewJob(uint256 indexed id,

address creator,

uint256 salary,

uint256 timeOut);



//An woker start working

event TakeJob(

uint256 indexed id,

address indexed labor);



//Minium accept salary

uint256 constant public MINIUM_SALARY = 0.1 ether;



//The number of jobs

uint256 public totalJob;



//Mapped data

mapping (uint256 => Job) public jobData;



//Transaction must contant Ethereum

modifier onlyHaveFund {

require(msg.value > MINIUM_SALARY);

_;

}



//Valid timeOut should be greater than 3 days

modifier onlyValidTimeOut(uint256 timeOut) {

require(timeOut > 3 days);

_;

}



//Check valid job Id

modifier onlyValidId(uint256 jobId) {

require(jobId < totalJob);

_;

}



//Mortgage should be greater than 1/10

modifier onlyValidMortgage(uint256 jobId) {

require(msg.value > jobData[jobId].salary/10);

_;

}



//Check is it a taked job

modifier onlyValidJob(uint256 jobId) {

require(jobData[jobId].end == 0);

require(jobData[jobId].start == 0);

_;

}



//Append new job to mapping

function

createJob (uint256 timeOut, bytes title, bytes description)

public onlyHaveFund onlyValidTimeOut(timeOut) payable returns(uint256 jobId)

{

// Saving a little gas by create a temporary object

Job memory newJob;



// Assign jobId

jobId = totalJob;



newJob.id = jobId;

newJob.id = timeOut;

newJob.title = title;

newJob.description = description;

newJob.salary = msg.value;

newJob.creator = msg.sender;



//Trigger event

NewJob(jobId, msg.sender, msg.value, timeOut);



// Append newJob to jobData

jobData[totalJob++] = newJob;



return jobId;

}



//Take job

function

takeJob (uint256 jobId)

public onlyValidMortgage(jobId) onlyValidId(jobId) onlyValidJob(jobId)

{

//Trigger event to log labor

TakeJob(jobId, msg.sender);



//Change working state

jobData[jobId].start = block.timestamp;

}



//Veiw job data

function

viewJob(uint256 jobId)

public onlyValidId(jobId) constant returns (

uint256 id,

address creator,

uint256 salary,

uint256 start,

uint256 end,

uint256 timeOut,

bytes title,

bytes description)

{

Job memory jobReader = jobData[jobId];

return (jobReader.id,

jobReader.creator,

jobReader.salary,

jobReader.start,

jobReader.end,

jobReader.timeOut,

jobReader.title,

jobReader.description);

}



}

Và mình viết thêm test case bằng JavaScript:

var Partime = artifacts.require("./PartTime.sol");



function createTx(from, to, value = 0, gas = 1000000, gasPrice = 20000000) {

return {

from: from,

to: to,

gas: gas,

gasPrice: gasPrice,

value: value

};

}



contract('Partime', function (accounts) {



it('should have 0 total part time job', function () {

return Partime.deployed().then(function (instance) {

return instance.totalJob.call();

}).then(function (totalJob) {

assert.equal(totalJob.valueOf(), 0, 'Total job was not equal to 0');

});

});



it('should able to add new job', function () {

return Partime.deployed().then(function (instance) {

return instance.createJob(((new Date()).getTime() / 1000 + 432000),

"This is tittle",

"This is description",

createTx(accounts[0], instance.address, web3.toWei('1', 'ether')));

}).then(function (totalJob) {

assert.equal(typeof (totalJob.valueOf()), 'object', 'Transaction was not triggered success');

});

});



it('should have total part time job geater than 0', function () {

return Partime.deployed().then(function (instance) {

return instance.totalJob.call();

}).then(function (totalJob) {

assert.equal(totalJob.valueOf() > 0, true, 'Total job was equal to 0' );

});

});



});

Bạn chú ý thấy mình đang thêm 1 job mới:

return instance.createJob(((new Date()).getTime() / 1000 + 432000),

"This is tittle",

"This is description",

createTx(accounts[0], instance.address, web3.toWei('1', 'ether')));

Đoạn code này có nghĩa là mình tạo ra 1 job có

  • Timeout: 5 ngày
  • Title: This is tittle
  • Description: This is description
  • Value: 1 Ethereum

Thực thi kiểm thử:

Smart contracts

Mình đã update source code tại https://github.com/chiro-hiro/part-time-dapp. Các bạn có thể clone về hoặc fork về viết cùng mình cho vui.

Dislaimer: Đây là thông tin cung cấp dưới dạng blog cá nhân, không phải thông tin tổng hợp hay lời khuyên đầu tư. Chúng tôi không chịu trách nhiệm về các quyết định đầu tư của bạn.

MỚI CẬP NHẬT

Token Ethena (ENA) tăng mạnh sau khi Deribit tích hợp USDe

Deribit, một trong những sàn giao dịch phái sinh crypto lớn nhất thế giới, có kế hoạch tích hợp USDe của Ethena làm tài...
phân tích kỹ thuật

Phân tích kỹ thuật tối ngày 22 tháng 11: XRP, ADA, OP, SOL và...

Tuần này, chúng ta sẽ xem xét chi tiết về Ripple (XRP), Cardano (ADA), Optimism (OP), Solana (SOL) và Dogecoin (DOGE). Phân tích kỹ thuật...
tiền điện tử

Khối lượng giao dịch tiền điện tử liên tiếp thiết lập kỷ lục vào...

Khối lượng giao dịch tiền điện tử hàng ngày trên các sàn giao dịch đã đạt mức cao nhất trong 12 tháng là 117...
eth

CryptoQuant: OI hợp đồng tương lai ETH đạt mức cao kỷ lục mới hơn...

Thị trường phái sinh Ethereum (ETH) có lẽ đang báo hiệu động lực tăng giá khi hợp đồng mở (OI)* hợp đồng tương lai...

Texas đang thảo luận về dự luật dự trữ chiến lược Bitcoin

Theo thông tin từ nhóm vận động phi lợi nhuận Satoshi Action Fund (SAF), dự luật dự trữ chiến lược Bitcoin đang được thảo...

Tin vắn Crypto 22/11: Bitcoin mới chỉ bắt đầu giai đoạn parabol trong chu...

Từ nhận định Bitcoin "mới chỉ bắt đầu giai đoạn parabol trong chu kỳ hiện tại" đến CFPB loại ví tiền điện tử ra...

Mùa Altcoin đầy sôi động: Đừng bỏ lỡ cơ hội đầu tư vào các...

Thị trường tiền điện tử vài tuần gần đây liên tục ghi nhận đà tăng trưởng bùng nổ mạnh mẽ. Đồng Bitcoin (BTC) gần...

Tập đoàn Charles Schwab cân nhắc giao dịch crypto, tân CEO ‘cảm thấy ngớ...

Charles Schwab, một trong những tập đoàn tài chính lớn nhất Hoa Kỳ, có kế hoạch tham gia thị trường crypto giao ngay khi...

Giá Popcat giảm mạnh, CatSlap bùng nổ ngày ra mắt. Meme coin hệ mèo...

Hãy quên Popcat đi! Một meme coin mới có tên CatSlap ($SLAP) vừa chính thức ra mắt và nhanh chóng trở thành cái tên...
Sandeep Nailwal của Polygon cảnh báo Rug Pulls memecoin

Các vụ kéo thảm memecoin như QUANT có thể thu hút sự đàn áp...

Sandeep Nailwal, đồng sáng lập mạng Ethereum layer-2 Polygon, cảnh báo rằng sự gia tăng các vụ lừa đảo liên quan đến memecoin có...

Các vụ kiện của SEC sẽ “âm thầm khép lại” sau khi Gensler từ...

Nhiều vụ kiện liên quan đến chứng khoán nhằm vào các công ty crypto tại Hoa Kỳ có khả năng sẽ “âm thầm khép...

[QC] Dogizen, ICO Đầu Tiên Trên Telegram, Thu Hút Được 1,4 Triệu USD Khi...

Trong thời gian ngắn, Dogizen đã thu hút sự chú ý trên khắp thế giới tiền điện tử, huy động được hơn 1,4 triệu...

The Graph (GRT) giới thiệu tiêu chuẩn GRC-20 cho cấu trúc dữ liệu Web3

The Graph, một hệ thống lập chỉ mục phi tập trung tương tự Google dành cho blockchain, đã giới thiệu một tiêu chuẩn dữ...
xrp-chau-au

Giá XRP tăng hơn 30% sau khi nhà quản lý tài sản toàn cầu...

Công ty quản lý tài sản Wisdomtree đã thông báo vào thứ Năm về việc ra mắt sản phẩm giao dịch hoán đổi (ETP)...

Tòa án Hoa Kỳ ra phán quyết SEC vượt quá thẩm quyền, hủy bỏ...

Một tòa án liên bang đã hủy bỏ quy định gây tranh cãi liên quan đến 'dealer - đại lý' của Ủy ban Chứng...
TruthFi

Trump Media tiết lộ tham vọng về giao dịch và thanh toán tiền điện...

Công ty truyền thông xã hội Trump Media and Technology Group (TMTG) của Tổng thống đắc cử Donald Trump đã tiết lộ tham vọng...