มารู้จักกับ Solidity ขั้นพื้นฐานกัน

Jedsada Tiwongvorakul
20Scoops CNX
Published in
5 min readJul 29, 2018

สวัสดีครับ หลังจากช่วงนี้งานที่ถืออยู่ในมือเริ่มเบาบางลง ผมก็เลยพอมีเวลาไปลองศึกษาอะไรใหม่ๆ ที่ตัวเองยังไม่เคยทำมาก่อน หลังจากหมกมุ่นกับการเขียน Android ซึ่งในปัจจุบันเทคโนโลยีก็ไปไกลมากแล้ว (กลัวตามไม่ทัน ฮ่าๆ) และเทคโนโลยีที่ผมสนใจก็คือ Smart Contract ก็ใช้เวลาว่างที่มีไป Researching และ Learning ดูว่ามันคืออะไร และใช้ภาษาอะไรในการพัฒนา

บทความนี้จะพูดถึงเรื่องของ ความหมายของ Smart Contract และ ภาษา Solidity ขั้นพื้นฐานนะครับ เพราะว่าผมก็มือใหม่หัดขับเหมือนกัน…✌️

Part 1 : Smart Contract คืออไร?

ถ้าจะแปลความหมายแบบตรงตัวก็ คือ “สัญญา อัจริยะ” ซึ่งเข้ามาช่วยให้คุณสามารถแลกเปลี่ยน เงิน หรือสิ่งของอะไรก็ได้ที่มีมูลค่าได้อย่างโปร่งใสปราศจากความขัดแย้งและหลีกเลี่ยงจากพ่อค้าคนกลาง

ตัวอย่างเช่น การระดมทุนเพื่อสนับสนุนโครงการอะไรสักอย่างหนึ่ง เช่น Kickstarter เป็นต้น ซึ่งระบบจะทำหน้าที่เป็นบุคคลที่สามระหว่างทีมพัฒนากับผู้สนับสนุนนั้นหมายความว่าทั้งสองฝ่ายต้องเชื่อถือ Kickstarter ซึ่งต้องจ่ายค่าธรรมเนียมให้กับระบบเพื่อทำหน้าที่เป็นตัวกลาง

แต่เราสามารถสร้าง Smart Contract ในการทำสัญญา ซึ่งโดยปกติสัญญาได้ระบุไว้อย่างชัดเจนว่า เงินทุนต้องถึงเท่าไหร่ในระยะเวลาที่กำหนด และระยะเวลาในการพัฒนาถึงเมื่อไหร่ เป็นต้น และเมื่อเงินทุนถึงตามเป้าที่ตั้งไว้ก่อนกำหนด เงินทุนก็จะถูกโอนไปยังทีมพัฒนาโดยอัตโนมัติ และเมื่อโครงการพัฒนาได้สำเสร็จสิ้นค้าก็จะถูกส่งไปยังผู้ที่สนับสนุน แต่ถ้าหากโครงการไม่สำเสร็จ เงินทุนก็จะถูกโอนกลับไปยังผู้สนับสนุนโดยอัตโนมัติด้วยเช่นกัน

นั่นหมายความว่า Smart Contract เป็นชิ้นส่วนของซอฟต์แวร์ที่จัดเก็บกฎสำหรับการเจรจาเงื่อนไขของข้อตกลงโดยอัตโนมัติ และมีการยืนยันความสำเร็จและจากนั้นดำเนินการตามเงื่อนไขที่ตกลงกันไว้ ทั้งหมดนี้จะอยู่บนระบบ Blockchain อีกทีหนึ่ง

เข้าสู่คำถามต่อมาว่า… 🤔

ทำไมเราถึงต้องเชื่อ Smart Contract ?

อย่างที่กล่าวไว้ว่า Smart Contract ทำงานบนระบบของ Blockchain อีกทีหนึ่งทำให้มีคุณสมบัติบางอย่างของ Blockchain

  • Immutable : เปลี่ยนรูปไม่ได้ ซึ่งหมายความว่าสัญญาไม่สามารถเปลี่ยนแปลงได้และไม่มีใครสามารถเข้าไปแก้ไขหรือทำลายสัญญาได้
  • Distributed : สัญญาถูกกระจายออกไปซึ่งหมายความว่าผลลัพธ์ของสัญญาก็จะได้รับการตรวจสอบจากทุกคนในเครือข่าย หากมีผู้ไม่หวังดีทำการเปลี่ยนแปลงผลลัพธ์ก็จะถูกตรวจพบ และทำเครื่องหมายไว้ว่าไม่ถูกต้อง

สำหรับเรื่องของ Blockchain ผมขอหยุดไว้แค่นี้ก่อนนะครับ เพราะผมก็ยังไม่รู้ 100% ขนาดนั้น แต่ถ้าหากพูดถึง Smart Contract จะไม่พูดเรื่อง Blockchain เลยก็ไม่ได้ ถ้าหากใครอยากศึกษาเพิ่มเติมเกี่ยวกับ Blockchain ก็สามารถเข้าไปอ่านเพิ่มเติมได้จากด้านล้างนี้เลยนะครับ

พอผมได้ศึกษาหัวข้อต่างๆ ที่เกี่ยวกับ Smart Contract เรียบร้อยในระดับหนึ่งแล้ว ก็หันไปลงในส่วนของการพัฒนาว่าใช้ภาษาอะไร ซึ่งภาษาก็มีชื่อว่า Solidity…

Part 2 : Solidity Introduction (101)

ความเป็นมา (History)

solidity เป็นภาษาสำหรับการสร้าง Smart Contract เป็นภาษาที่ได้รับอิทธิพลมาจาก C ++, Python และ JavaScript ที่สำคัญเลยก็คือเป็นภาษาชนิดที่ statically typed และเป็นภาษาแบบ Object Oriented (OO) เพราะว่ามีคุณสมบัติของการสืบทอดและการทำ struct เป็นต้น

ชนิดของตัวแปร (Value Types)

  1. Booleans : bool (true and false)
  2. Integers : int/uint อันนี้เราสามารถกำหนดขนาดที่เราจะใช้ได้โดยมีขนาดตั้งแต่ 8-256 bits เช่น int8 และ uint16 และถ้าหากเราไม่ได้ได้ระบุขนาดของ bits ก็จะมีขนาด 256 โดยอัตโนมัติ เช่น int หรือ uint นั้นหมายความว่ามีค่าเท่ากับ int256 หรือ uint256
  3. Bytes : bytes มีขนาดตั้งแต่ 1–32 bytes เช่น bytes8 หรือ bytes32แต่ถ้าเราไม่กำหนดขนาดก็จะเป็น array dynamic size
  4. Strings : string อันนี้ไม่มีให้กำหนดขนาดของ bytes หมายความว่าจะมองเป็น array dynamic size ซึ่งมีความแตกต่างจากการใช้ bytes ที่มีการกำหนดขนาดตรงที่จำนวนของ gas ที่ใช้ strings จะใช้ gas มากว่านิคหน่อย
  5. Address : address มีค่าอยู่ที่ 20 byte ตามขนาดของ Ethereum address

ซึ่งหลักๆ ใน solidity ก็จะมี value types ให้ใช้ประมาณนี้ครับผม จะเห็นว่าผมไม่ได้อธิบายในส่วนที่เป็น flaot และ double ซึ่งใน solidity คือ fixed และ ufixed แต่ยังไม่ support นะสิ เราสามารถประกาศได้แต่ก็จะขึ้นว่า “ Not yet implemented” ก็คงต้องรอก็ต่อไป…

และนอกจากนี้เรายังสามารถประกาศเป็น array หรือ struct ได้ตามปกติ และแต่ละตัวก็มี member ให้เรียกใช้น้อยมากแทบจะไม่มีเลยก็ว่าได้ผมและก็เพื่อนๆ ในบริษัทก็เลยทำ utils ของบางตัวขึ้นมาก็สามารถเอาไปใช้ และถ้าหากใจดีมาร่วมทำด้วยกันก็จะดีใจมากครับ

Tie In แบบหน้าด้านๆ เลยนะเราเนี่ย ฮ่า ฮ่า ฮ่า 😘

รูปแบบการเขียน (Syntax)

  • การประกาศ Contract : จุดนี้คือหัวใจสำคัญเพราะมันคือการสร้างเงื่อนไขของเราว่าต้องการให้เป็นยังไง ซึ่งการสร้าง Contract ต้องมี keyword contract เหมือนกับ keyword class ในการสร้างคลาสใน JAVA นะครับ
syntax : contract name {...}--------------------------------------------------------------------pragma solidity ^0.4.17;contract MyContract {

...
}
  • การประกาศตัวแปร : และเมื่อเรารู้แล้วว่า value types มีอะไรบ้างจากที่กล่าวไว้ข้างบน ที่นี้เรามาดูวิธีการเรียกใช้งานกันแบบคร่าวๆ กันหน่อย
syntax : value_types name = value;--------------------------------------------------------------------pragma solidity ^0.4.17;contract ExampleContract {    bool myBool = true;    int myInt = 5;
uint myUint = 999;
uint8 myUint8 = 255; // uint8 range 0 to 255
int16 myInt16 = 32767; // int16 range -32,768 to 32,767
bytes myBytes = "20scoops CNX";
string myStr = "Chiang Mai, the most beautiful city";
address myAddress = 0x72ba7d8e73fe8eb666ea66babc8116a41bfb10e2; uint[] myArr = [1,3,5,7,9]; struct User {
string name;
int age;
}
}
  • เงื่อนไขและการวนลูป (Condition and Loop) : ส่วนวิธีการทำ if else และ loop อย่างเช่น for, while หรือ do while ซึ่งมีวิธีการเขียนเหมือนกับภาษาอื่นๆ เลยไปดูตัวอย่างกันสักหน่อยดีกว่า
pragma solidity ^0.4.17;contract ExampleContract {

uint[] myArr = [1,2,3,4,5,6,7,8,9,10];

function testCondition(uint n) public view returns (string) {
if (n%2 == 0) {
return "is even number";
} else {
return "is odd number";
}
}

function testFor() public view returns (uint) {
uint sum = 0;
for(uint i=0; i<myArr.length; i++) {
sum += myArr[i];
}
return sum;
}

function testWhile() public view returns (uint) {
uint sum = 0;
uint i = 0;
while (i<myArr.length) {
sum += myArr[i];
i++;
}
return sum;
}

function testDoWhile() public view returns (uint) {
uint sum = 0;
uint i = 0;
do {
sum += myArr[i];
i++;
} while (i<myArr.length);
return sum;
}
}
  • การประกาศฟังก์ชัน : ส่วนเรื่องของการประกาศฟังก์ชันก็ต้องขึ้นต้นด้วย keyword ว่า function แล้วตามด้วย ชื่อฟังก์ชัน ตามด้วย paremeter และ ลักษณะ การเข้าถึงฟังก์ชัน และอื่นๆ ที่เป็น optional อีกนิดหน่อย
syntax : function name(<parameter types>) {internal|external|public|private} [pure|view|payable] [(modifiers)] [returns (<return types>)]คำอธิบายแบบพอสังเขป : อะไรที่อยู่ใน [...] หรือ parameter เป็น optional หมายความว่ามีก็ได้ไม่มีก็ได้public:   เป็นการประกาศให้ฟังก์สามารถเข้าถึงได้ทุกที
private: เป็นการประกาศให้ฟังก์ชันสามารถเข้าถึงได้เฉพาะ current contract
internal: เป็นการประกาศให้ฟังก์ชันสามารถเข้าถึงได้ current contract และ
contract ที่สืบทอด
external: เป็นการประกาศให้ฟังก์ชันสามารถเข้าถึงได้ทั้ง current contract และ
contract ที่สืบทอดแต่ต้องมี keyword ว่า this ก่อนสำหรับการเรียกใช้
ฟังก์ชันเช่น this.print();
pure: เป็นการบ่งบอกว่าฟังก์ชันนี้มีใช้งานเกี่ยวกับค่าคงที่เท่านั้นแต่ไม่มีการยุ่งเกี่ยวกับค่า
กับค่าใน storage
view: เป็นการบ่งบอกว่าฟังก์ชันนี้มีการยุ่งเกี่ยวกับค่าใน storage
payable: เป็นการบ่งบอกว่าฟังก์ชันนี้มีเรียกเก็บ ether ก่อนจะทำงานในฟังก์ชัน
modifiers: อันนี้จะมีจะมีคำอธิบายในตัวอย่างด้านล่างนะครับ--------------------------------------------------------------------pragma solidity ^0.4.17;contract ExampleContract {

string [] fruit = ["apple", "banana", "cherry", "kiwi"];

// function ธรรมดา default จะเป็น public
function a() {

}
/*
function ที่เป็นแบบ private
สามารถเรียกใช้ได้แค่ Contract นี้เท่านั้น
*/

function b() private {

}

// function แบบมี parameter
function plus(int x, int y) {
int sum = x+y;
}

// function ที่มีการ return single value
function speak(string sound) public pure returns (string) {
return sound;
}

// function ที่มีการ return multi value
function fullName() public pure returns (string fn, string ln){
return (fn = "20scoops", ln = "CNX");
}

/*
function ที่มีการ return ค่าที่ยุ่งเกี่ยวกับ
storage ต้องใช้ keyword ว่า view
*/

function getSizeFruit() public view returns (uint) {
return fruit.length;
}

// วิธีรับค่าจาก function ที่มีการ return multi value
function setFullName() public pure returns (string) {
var (fristName, lastNmae) = getFullName();
return fristName;
}

/*
function ที่ต้องค่าใช้จ่ายก่อนการ execute
โดยมี keyword ว่า payable
*/

function lucky() public payable {
// TODO: something
}
}
  • การสืบทอดของ Contract : อย่างที่ผมได้บอกไว้ด้านบนว่า solidity เป็น OO ซึ่งมีคุณสมบัติในการสืบทอด ซึ่งการสืบทอดของ solidity มี keyword is เหมือนกับ keyword extends ใน JAVA นะครับ เรามาดูกันตัวอย่างกันหน่อยดีกว่า
syntax : contract is contractParent--------------------------------------------------------------------pragma solidity ^0.4.17;contract Animal {

string internal nameAnimal;

function setName(string name) public {
nameAnimal = name;
}

function getName() public view returns (string) {
return nameAnimal;
}

function speak(string sound) public pure returns (string) {
return sound;
}
function somethingAnimal() private { }
}
contract Cat is Animal {

function something() public { }
}

หมายความว่า contract ที่มีชื่อว่า cat สืบทอดคุณสมบัติของ contract animal ทำให้ cat มี member ของ animal ทั้งหมดยกเว้นฟังก์ชันที่ชื่อว่า somthingAnimal() เพราะว่าเป็นแบบ private นั้นเอง

  • การเรียกใช้ Contract : ในการทำงานจริงๆ คงไม่ได้มีเพียงแค่ contract เดียวไม่งั้นคง งง ตายเลยและการเรียกใช้งานจากอีก contract หนึ่งนั้นสามารถเรียกใช้เหมือนกับการประกาศ object ของ JAVA นะครับ โดยมี keyword new ดังนี้
syntax : ContractName contract = new ContractName();--------------------------------------------------------------------contract A {
function printName() public pure returns (string) {
return "20scoops CNX";
}
}
contract B {

A a = new A();

function printString() public view returns (string) {
return a.printName();
}
}

ตัวอย่าง : contract calculator อาจจะไม่น่าเป็น contract เท่าไรนัก ฮ่า ฮ่า ฮ่า ผมเพิ่งหัดเดินนะครับ

จากตัวอย่าง จะมีฟังก์ชันหนึ่งที่ชื่อว่า divideByZero() จะมี keyword ว่า modifier อยู่แล้วมีการเรียกใช้งานจากฟังก์ชัน divide() หมายความว่าต้องผ่านเงื่อนไขจาก divideByZero() ก่อนถึงจะเข้าไปทำงานเห็นได้จากว่ามีการ require(y>0) ก่อนถ้าตรงตามเงื่อนไขถึงจะทำงานต่อไปได้…

IDE’s ที่ใช้ในการพัฒนา (เท่าที่รู้นะครับ)

  1. Remix
  2. Ethfiddle
  3. VS Code อันนี้ต้องลง plugin ที่มีชื่อว่า solidity
  4. Atom อันนี้ก็ต้อง plugin เหมือนกัน etheratom อันนี้เข้าท่า deploy ได้เลย

การ Deploy เพื่อทดสอบ

ในที่นี้ผมจะใช้ Remix ในการ deploy เพื่อทดสอบ contract calculator นะครับให้ทำการ copy code จากตัวอย่าง calculator ด้านบนแล้วทำการเปิด Remix ขึ้นมา จากนั้นให้ทำการสร้างไฟล์ที่มีชื่อว่า calculator.sol ขึ้นมาใหม่นะครับโดยการกดปุ่มที่เป็นสัญลักษณ์บวกแล้วทำการ paste code ลงไปก็จะได้หน้าตาประมาณนี้

จากนั้นให้กดปุ่ม start to compile เพื่อตรวจสอบว่าสิ่งที่เราเขียนถูก syntax รึ เปล่า

จากนั้นให้สลับเมนูที่ไป Run แล้ว make sure ว่า Environment ที่เราอยู่ว่าเป็น Java Script Vm รึ เปล่า อันนี้ผมขอยังไม่ขออธิบายสำหรับการเทสบน env อื่นในบทความนี้กลัวจะยาวเกินไป

ต่อไปก็ให้ทำการกดปุ่ม Deploy ได้เลยครับผม เพียงเท่านี้ contract ของเราก็ถูกเก็บไว้บนระบบ blockchain ใน env เทสเรียบร้อยแล้วอยากรู้ว่า contract address อะไรก็สามารถกด debug ดูได้เลย

จากภาพจะเห็นว่ามีฟังก์ชันอะไรบ้างจากกรอบสีแดง จากนั้นให้กรอก parameter ในฟังก์ชัน multiply() ตามภาพแล้วแล้วกดปุ่ม multiply แล้วรอดูผลลัพธ์ต้องได้ 20 ถ้าไม่ได้ก็ตัวใครตัวมัน…

และทั้งหมดของบทความนี้เป็นเพียงแค่พื้นฐานเอามากๆ สำหรับภาษา Solidity ซึ่งถ้าหากใครสนใจอยากศึกษาเพิ่มเติมก็สามารถเข้าไปอ่านจากลิงค์ด้านล่างนี้ได้เลยครับ

สรุป

จากที่ผมได้ศึกษาภาษา Solidity มาสักพักวันละนิควันละหน่อยรู้สึกปวดหัวดีนะครับ ฮ่าฮ่า สำหรับผมแล้วมีการบ้านที่ต้องศึกษาเพิ่มเติมอยู่หลายเรื่องเอามากๆ เพราะมันเป็นเรื่องที่ใหม่อยู่พอสมควร และถ้าหากจะสร้าง Contract ที่ใช้งานได้จริงผมต้องคำนึงถึงหลายๆ เรื่อง ยกตัวอย่างเช่นในส่วนของ performance ที่ต้องระวังกันเป็นพิเศษ เพราะ code ที่เขียนลงไปมันอาจทำให้เสียเงินโดยใช่เหตุ เหตุผลก็คือ ในทุกๆ การ execute จำเป็นต้องใช้ gas ซึ่งเจ้านี้แหละมีค่าใช้จ่าย สุดท้ายแล้วก็ถือว่าเป็นอีกหนึ่งความท้าทายใหม่ของผมสำหรับการเรียนรู้เทคโนโลยีใหม่ๆ

Happy Coding… 🇹🇭

--

--