หลังจากนี้ เราจะต้องไปลุยกันในเรื่องของ smart contract ซึ่งก่อนที่เราจะไปถึงตรงนั้น อยากให้ทำความเข้าใจเรื่องพื้นฐานก่อนที่ค่อนข้างสำคัญ และเป็นสิ่งที่เราต้องใช้ต่อไปด้วย นั่นก็คือ ABI
ABI หรือ Application Binary Interface
อธิบายแบบสั้นๆ ABI มันคือ interface ที่ทำหน้าที่เป็นตัวกลาง เพื่ออธิบาย และ เอาไว้เรียกใช้งาน contract จาก EVM ให้ได้ง่ายขึ้น หรือถ้าให้อธิบายคนที่เคยเขียนโค้ดมา น่าจะเคยเรียก API มาบ้าง ก็ให้นึงถึงสิ่งที่คล้ายกันครับ คือมันเป็น interface หนึ่ง ที่เป็นช่องทางให้เราเรียกใช้งาน โดยส่งค่าบางอย่างที่จำเป็นเข้าไปด้วย แล้วเมื่อทำงานเสร็จ ก็อาจจะรับ หรือไม่ต้องรับค่ากลับมา เท่านั้นเอง
ถ้าอธิบายแบบยาวหน่อย ต้องลงลึกไปในการทำงานของ EVM (Ethereum Virtual Machine) ที่มันสามารถรัน Contract ได้ โดยเจ้าตัว Contract เนี่ย เวลาเราเขียนก็ใช้ภาษาที่เราอ่านออก เข้าใจได้ แต่ว่าเวลาที่ส่งมันเข้าไปเก็บใน EVM เพื่อให้มันทำงานได้ มันจะต้อง Compile ไปเป็น Bytecode ก่อนเท่านั้น เพื่อเก็บเข้าใน address ที่เป็น Contract Address ใน Blockchain โดยใน EVM นั้น smart contract มันเป็น bytecode ที่เรียงต่อๆกันไปเรื่อยๆ การที่เราจะเรียกใช้งาน feature / function ใดๆใน smart contracat นั้น เราจะเป็นต้องแปลงชื่อ กลับไปเป็น bytecode พร้อมกับ parameter ที่จำเป็น จึงจะเรียกใช้งานได้ ดังนั้น หน้าที่นี้ ก็เลยตกเป็นของ ABI นี่แหล่ะ ที่ทำให้มันเป็น Function ที่เราอ่านได้ และแปลงจากชื่อที่เราเข้าใจ กลับไปเป็น bytecode เพื่อทำงานอีกทีนึง ผมประมาณให้ว่ามันเป็นแนว API Document spec นั่นล่ะครับ
โดย ABI นี้จะเขียนในรูปของ JSON format ซึ่งจะอธิบาย function / event เอาไว้ โดยจะมีองค์ประกอบดังนี้ สำหรับ function
- type : กำหนดประเภทของ function ซึ่งมันจะเป็น ‘function’, ‘constructor’, ‘receive’ หรือ ‘fallback’ เท่านั้น
- name : ชื่อของ function
- inputs : เป็น array object เพื่อบอกว่ามี parameter อะไรบ้าง โดยแต่ละ parameter ต้องมี
- name : ชื่อ parameter
- type : กำหนดประเภทของ parameter เช่น uint256
- components : จะใช้ในกรณีที่เป็นประเภท tuple (type = tuple)
- output : array ของ output
- stateMutability : กำหนดประเภท state ของ function ซึ่งจะเป็น ‘pure’ คือไม่สามารถอ่านเขียน state ได้, ‘view’ อ่านค่า state ได้อย่างเดียว เขียนไม่ได้, ‘nonpayable’ อันนี้คือ default state ที่ทำให้อ่านเขียน state ได้ แต่ไม่สามารถใช้รับ Ether ได้, ‘payable’ อันนี้คือ อ่านเขียน state ได้ และรับ Ether ได้ด้วย
และมีองค์ประกอบดังนี้ สำหรับ event
- type : กำหนดประเภทของ function ซึ่งมันจะเป็น ‘event’ เท่านั้น
- name : ชื่อของ event
- inputs : เป็น array object เพื่อบอกว่ามี parameter อะไรบ้าง โดยแต่ละ parameter ต้องมี
- name : ชื่อ parameter
- type : กำหนดประเภทของ parameter เช่น uint256
- components : จะใช้ในกรณีที่เป็นประเภท tuple (type = tuple)
- indexed : กำหนดเป็น ‘true’ ถ้าเป็นส่วนหนึ่งของ log’s topic และ ‘false’ ถ้าเป็นส่วนหนึ่งของ log’s data segments
- anonymous : ถ้าเป็น true ถ้ากำหนดให้เป็น event anonymous ใน contract code
เราจะได้ ABI มาจากไหน
ใน IDE ที่เราใช้เขียน Smart Contract Code มันจะสร้าง ABI ให้เราในตอนที่เรา compile อยู่แล้วครับ
ABI สำคัญกับเรายังไง
อย่างที่เล่าไปในย่อหน้าแรกเลย นั่นก็คือ เวลาที่เราจะเรียกใช้งาน function / event ใน smart contract เราต้องมี ABI ประกาศเอาไว้ เพื่อให้เราสามารถเรียกใช้งานได้อย่างถูกต้องนั่นเอง ไม่อย่างนั้น เราต้องเข้าใจและเรียกการทำงานจาก Bytecode ซึ่งเอาตรงๆไม่ค่อยเห็นใครเค้าทำกัน และตอนที่เราใช้ Web3 วิธีที่ทำให้เราเข้าใจ และใช้งานได้ง่ายก็คือการเรียกผ่าน ABI นี่แหล่ะ
ดังนั้น ถ้าเราจะเขียน code เพื่อไปเรียกใช้งานบางอย่างใน smart contract แล้วล่ะก็ (ซึ่งเราจะทำกันในบทความหน้านี่แหล่ะ) เราจำเป็นต้องรู้จักเจ้า ABI นี่เอาไว้ครับ