Blog About
Table of Contents
  • เริ่ม
  • ใครคือเจ้าของ contract
  • บัตรของเราจะเก็บข้องมูลอะไรบ้าง
  • constructor ประมวลผลครั้งแรกครั้งเดียวเมื่อ deploy
  • modifier ทำหน้าที่คล้าย middleware ฟังก์ชัน
  • ฟังก์ชันที่ Application จะเรียกดูข้อมูลบัตร
  • ฟังก์ชันที่ Application จะเรียกเพิ่มและแก้ไขข้อมูล
  • หากวาดการทำงานออกมาเป็นภาพจะได้
  • deply ใน remix ide

Solidity Blockchain Idcard

Apisit N.
25 Oct 2021

มาลองคิดลองเขียน smart contract กันหน่อยไหม ในตัวอย่างนี้ผมจะลองเก็บข้อมูลอะไรง่ายๆ ดู เพราะ blockchain มันก็คือการเก็บข้อมูลแบบกระจายศูนย์ มันคล้ายกับเป็น ฐานข้อมูล นั่นแหละ

เริ่ม

remix.ethereum.org

สร้างไฟล์ชื่อว่า Idcard.sol ในโฟลเดอร์ contract

1
//SPDX-License-Identifier: MIT
2
3
pragma solidity ^0.8.0;
4
5
contract Idcard {
6
// code...
7
}

ประกาศ license กำหนดให้ไฟล์นี้ใช้ compiler version อะไรแล้วสร้าง contract ชื่อ Idcard

ใครคือเจ้าของ contract

1
address private admin;

สร้างตัวแปรชื่อ admin เอาไว้เก็บข้อมูลชนิด address ของเจ้าของ contract

บัตรของเราจะเก็บข้องมูลอะไรบ้าง

  1. เลขประจำตัว 13 หลัก
  2. ชื่อ
  3. นามสกุล
  4. วันเกิด คำนวณอายุได้
  5. วันที่ออกบัตร
  6. วันหมดอายุบัตร
  7. สถานะยืนยันตัวตนด้วยการ KYC
  8. ยืนยันตัวตนโดยใคร
  9. ยืนยันตัวตน ณ เวลา
1
mapping(address => uint) private id;
2
mapping(uint => string) private name;
3
mapping(uint => string) private lastname;
4
mapping(uint => uint) private birthdate;
5
mapping(uint => uint) private date_of_issure;
6
mapping(uint => uint) private date_of_expire;
7
mapping(uint => bool) private kyc;
8
mapping(uint => address) private kycby;
9
mapping(uint => uint) private inspec_at;

จากข้อมูลนี้ จะเห็นได้ว่ามีสถานะยืนยันตัวตนอยู่ด้วย เพื่อเอาไว้ตรวจสอบว่าข้อมูลบัตรชุดนี้มีความน่าเชื่อถือและคนที่ยืนยันได้จะต้องเป็นองค์กรเชื่อถือได้เท่านั้นเช่น องค์กรที่ได้รับการยอมรับจากรัฐอย่างธนาคารพาณิชย์หรือธนาคารเองนั้นแหละที่เป็นคนยืนยัน

1
mapping(address => bool) public list_inspectors;
2
mapping(address => string) public inspectorsis;

เอาแบบคล่าวๆละกัน ทีนี้ก็ได้ข้อมูลในบัตรแล้วเรามากำหนดฟังก์ชันเพื่อให้ Application เรียกดูข้อมูลอะไรได้บ้าง

constructor ประมวลผลครั้งแรกครั้งเดียวเมื่อ deploy

1
constructor() {
2
admin = msg.sender;
3
list_inspectors[msg.sender] = true;
4
inspectorsis[msg.sender] = "Developper";
5
}

จากโค้ดใน constructor จะกำหนดความเป็นเจ้าของเพื่อนำไปกำหนดเงื่อนไขต่างๆภายใน contract เช่นฟังก์ชันที่ใช้ได้เฉพาะเจ้าของเท่านั้น

modifier ทำหน้าที่คล้าย middleware ฟังก์ชัน

1
modifier adminOnly {
2
require(msg.sender == admin, "Forbidden");
3
_;
4
}
5
6
modifier inspectorOnly {
7
require(list_inspectors[msg.sender], "Forbidden");
8
_;
9
}

modifier ฟังก์ชันนี้ถูกประมวลผลก่อนเมื่อผ่านหรือไม่เกิด error ก็จะประมวลผลโค้ดในส่วนของ body ในวงเล็บ นั้นแหละ ในฟังก์ชันนั้นๆเป็นลำดับถัดไป

ฟังก์ชันที่ Application จะเรียกดูข้อมูลบัตร

  1. สามารถดูเลขบัตรประจำตัว 13 หลักได้
  2. สามารถดูชื่อได้
  3. สามารถดูนามสกุลได้
  4. สามารถดูวันเกิดได้
  5. สามารถดูสถาณะยืนยันตัวตนได้
1
function getId() public view returns(uint) {
2
return (id[msg.sender]);
3
}
4
function getName(uint _id13) public view returns(string memory) {
5
return (name[_id13]);
6
}
7
function getLastname(uint _id13) public view returns(string memory) {
8
return (lastname[_id13]);
9
}
10
function getBirthdate(uint _id13) public view returns(uint) {
11
return (birthdate[_id13]);
12
}
13
function getIskyc(uint _id13) public view returns(bool) {
14
return (kyc[_id13]);
15
}

จะเห็นได้ว่าแต่ละฟังก์ชันจะดูข้อมูลได้แค่อย่างเดียว แต่จริงๆแล้ว solidity ก็มีความสามารถ return ค่าออกมาได้หลายๆค่าภายในฟังก์ชันเดียวนะ แล้วทำไมถึงต้องทำแยกฟังก์ชันแบบนี้ด้วย เหตุผลที่ผมทำแบบนี้คือเราสามารถกำหนดเงื่อนไขให้แต่ละฟังก์ชันว่าอนุญาตให้ใครเข้าถึงข้อมูลเหล่านี้ได้บ้าง

ฟังก์ชันที่ Application จะเรียกเพิ่มและแก้ไขข้อมูล

  1. สามารถเพิ่มผู้ที่ทำหน้าที่ตรวจสอบ KYC
  2. สามารถเพิ่มผู้ที่ทำหน้าที่ตรวจสอบ KYC
  3. สามารถยืนยันข้อมูลบัตรได้
  4. สามารถเพิ่มข้อมูลบัตรได้
  5. สามารถเพิ่มข้อมูลบัตรโดยผู้ตรวจสอบได้
1
function setInspector(address _inspector, bool _val, string memory _name) public adminOnly {
2
list_inspectors[_inspector] = _val;
3
inspectorsis[_inspector] = _name;
4
// inspec_at[_inspector] = now;
5
}
6
7
function setKyc(uint _id13, bool _val) public inspectorOnly {
8
kyc[_id13] = _val;
9
kycby[_id13] = msg.sender;
10
inspec_at[_id13] = block.timestamp;
11
}
12
13
function setAccount(
14
uint _id13,
15
string memory _name,
16
string memory _lastname,
17
uint _birthdate,
18
uint _date_of_issure,
19
uint _date_of_expire
20
) public {
21
require(id[msg.sender] == _id13, "You don't have permission");
22
23
id[msg.sender] = _id13;
24
name[_id13] = _name;
25
lastname[_id13] = _lastname;
26
birthdate[_id13] = _birthdate;
27
date_of_issure[_id13] = _date_of_issure;
28
date_of_expire[_id13] = _date_of_expire;
29
}
30
31
function setAccountByInspector(
32
address _address,
33
uint _id13,
34
string memory _name,
35
string memory _lastname,
36
uint _birthdate,
37
uint _date_of_issure,
38
uint _date_of_expire
39
) public inspectorOnly {
40
require(_address != admin, "Forbidden");
41
42
id[_address] = _id13;
43
name[_id13] = _name;
44
lastname[_id13] = _lastname;
45
birthdate[_id13] = _birthdate;
46
date_of_issure[_id13] = _date_of_issure;
47
date_of_expire[_id13] = _date_of_expire;
48
}

จากโค้ดด้านบนอธิบายแต่ละฟังก์ชันได้ว่า

  1. setInspector เป็นฟังก์ชันที่ใช้ได้เฉพาะเจ้าของ contract เท่านั้น สามารถเพิ่มและแก้ไขรายชื่อผู้มีสิทธิในการยืนยันตัวตนได้
  2. setKyc เป็นฟังก์ชันที่ใช้ได้เฉพาะผู้มีสิทธิยืนยันตัวตนเท่านั้น เจ้าของก็มีสิทธินี้นะกำหนดไว้ใน constructor แล้ว สามารถยืนยันเพื่อให้มีความน่าเชื่อถือของข้อมูลบัตร
  3. setAccount เป็นฟังก์ชันที่ใครก็ใช้ได้ สามารถเพิ่มและแก้ไขข้อมูลบัตรของตนเองได้เท่านั้น
  4. setAccountByInspector เป็นฟังก์ชันที่ใช้ได้เฉพาะผู้มีสิทธิยืนยันตัวตนเท่านั้น สามารถเพิ่มและแก้ไขข้อมูลบัตรของใครก็ได้ยกเว้นเจ้าของ contract

จะเห็นได้ว่า มีช่องโหว่หรือ logic ที่ไม่ดีในหลายๆขั้นตอนเช่น

  • Inspector สามารถแก้ไขข้อมูลของ Inspector คนอื่นได้
  • ใครก็สามารถใส่เลขประจำตัว 13 หลักที่ไม่เป็นความจริงก็ได้ในครั้งแรก
  • สามารถสร้าง account ใหม่แล้ว ใส่เลขประจำตัว 13 หลักซ้ำกับคนเก่าก็ได้
  • ยังมีเยอะเลยครับ ลองคิดกันเล่นๆดูครับ สิ่งสำคัญคือเมื่อ deploy ไปแล้วเราไม่สามารถแก้ไขโค้ดได้อีกแล้ว Code Is Law

หากวาดการทำงานออกมาเป็นภาพจะได้

this is alt tag

deply ใน remix ide

this is alt tag

ขั้นตอนดังนี้

this is alt tag

สุดท้าย ก็หวังว่าบทความนี้จะเป็นประโยชน์กับใครหลาย ๆ คนนะครับ

© 2025 Apisit N.