ลองเขียนและ Deploy Smart Contract ด้วย Foundry
หลังจากที่หลายวันก่อนได้ลองใช้งาน Foundry และก็หัดใช้งานเบื้องต้นไป เผื่อจะเอามาแทนที่ Hardhat วันนี้วันหยุด ว่างๆ ก็เลยถือโอกาส ลองเล่น ลองเปลี่ยนมาลองใช้ Foundry ตั้งแต่เริ่ม เทส และ Deploy ดูว่าจะเป็นไง หลังจากได้ลองอ่าน Foundry Book พบว่ามันน่าสนใจมากๆ ตัว Foundry ให้คำนิยามตัวเองไว้ คือ Foundry is a blazing fast
Step 1 - สร้างโปรเจ็ค
เริ่มต้นสร้างโปรเจ็คขึ้นมา ผมตั้งชื่อว่า greeter เป็น Contract get set message ธรรมดานะครับ
ตัว Foundry (Forge) จะทำการ initial Project มาให้เรา ลองเปิดโฟลเดอร์ขึ้นมาดู โครงสร้าง (ผมใช้ VS Code) จะประกอบไปด้วย
src
- โฟลเดอร์หลักของ Contract (ถ้า Hardhat ก็จะเป็นโฟลเดอร์ Contract)test
- โฟลเดอร์สำหรับ testingfoundry.toml
- เป็นเหมือน configuration file คล้ายๆ hardhat.config.js
ข้างในโปรเจ็ค มี Contract Counter.sol มาให้ รวมถึงไฟล์เทส Counter.t.sol
ลองรันคำสั่ง build
หากเราดูผลลัพธ์ การ compile จะเห็นว่าเร็วมากๆ
Step 2 - สร้าง Contract
ผมทำการสร้าง Contract ขึ้นมาใหม่ ชื่อ Greeter.sol
อยู่ในโฟลเดอร์ src
ทำการเพิ่มไฟล์ Test ชื่อ test/Greeter.t.sol
Remappings
หากใครเจอปัญหา เวลาเปิดไฟล์เทสแล้วหาไฟล์ forge-std/Test.sol
ไม่เจอ
แสดงว่าเรายังไม่ได้ remappings ให้มันครับ ทำการ remappings ด้วยคำสั่ง forge remappings
และก็ทำการเซฟไว้ที่ไฟล์ชื่อ remappings.txt
ลองรัน Test
เราสามารถดู traces ได้ด้วย ใช้ -vvv เฉพาะ test ที่ fail หรือใช้ -vvvv test ทั้งหมด
อีกอันที่ชอบคือ test —gas-report โดยไม่ต้องลง plugin เพิ่ม
Step 3- Local Node
ลองรัน Local Node ด้วย anvil (เทียบกับ Hardhat คือ npx hardhat node)
แถมเราสามารถ fork network ได้ด้วย
ทีนี้ เราก็มี Local Node แล้วที่ 127.0.0.1:8545
ลอง Deploy local และทดสอบ connect RPC ดู (ใช้ Private Key ที่ได้จาก Local node เป็น private key ที่ไม่ปลอดภัย ห้ามเอาไปใช้ Production เด็ดขาด)
จะได้ผลลัพธ์ที่ Deploy แบบนี้ (0x5FbDB2315678afecb367f032d93F642f64180aa3 คือ Contract Address ที่เรา deployed ไป)
ถ้าเราไปดูในหน้า Local node ของเรา จะเห็นว่ามี Contract ถูก deploy แสดงใน log
Step 4 - Call RPC with Cast
ทดลอง Call RPC ตัว contract ที่เรา Deploy ด้วย cast ครับ ตัว cast เป็น Command Line ที่ให้เรา call RPC ได้
ถ้าเราไม่ได้ config ตัว rpc-url จะเป็น localhost:8545 สามารถกำหนด rpc url ได้ด้วย option --rpc-url=<RPC_URL>
ดู gas price
ดู block number
ทดลอง เรียก greet() จาก Contract ที่เรา Deploy ด้วยคำสั่ง cast call
ถ้าสังเกต รูปแบบมันจะเป็นแบบนี้
จะเห็นว่าได้ผลลัพธ์ เป็นค่า “Hello” ที่เราทำการ setup ที่ contructor ตอน Deploy Contract.
ลอง setGreeting ดู เปลี่ยนจาก cast call เป็น cast send
ใน localhost ผม send tx ได้ อาจจะเพราะใช้ account default แต่บน testnet ผมลอง send tx แล้วได้ Error แบบ issue นี้เลย (ขอทิ้ง issue ไว้ก่อน เดี๋ยวกลับมาดูว่า แก้ปัญหายังไง)
สรุป
cast call
- เอาไว้ call contract (read-only)cast send
- sign และ send transaction
Step 5 - Deploy Testnet
ขั้นตอนนี้ ผมจะทำการ Deploy Testnet โดยใช้ Sepolia (หรือใครจะใช้ Testnet อื่นๆ ที่สะดวกก็ได้)
Sepolia FaucetA fast and reliable Ethereum Sepolia testnet faucet for blockchain developers.Sepolia Faucet
การ Deploy ก็เหมือนกับตอน deploy local แต่เพียงต้องเพิ่ม —rpc-url ด้วย สามารถเพิ่มเป็น option หรือกำหนดที่ไฟล์ foundry.toml ก็ได้ โดย foundry config สามารถใช้ไฟล์ที่ local folder ก็ได้ หรือจะเป็น global ก็เซฟไว้ที่ ~/.foundry/foundry.toml
ไฟล์ foundry.toml
รันคำสั่ง
หรือเราสามารถใช้ Environment Variable ได้ เช่น ~/.zshrc
หรือ ~/.bashrc
หรืออีกวิธี สร้าง .env ขึ้นมา ในโฟลเดอร์ของโปรเจ็คเรานี่แหละ ( source .env)
สุดท้ายผมลอง Deploy ด้วย Config ด้านบน ก็จะเหลือคำสั่งแค่นี้
เมื่อ Deploy เสร็จ ก็จะเห็นผลลัพธ์
Step 6 - Verify Contract
จริงๆ เราสามารถ Verify พร้อมกับตอน Deploy เลยก็ได้ ถ้าเราใส่ option --verify
และ --etherscan-api-key
แบบนี้
ผลลัพธ์ก็จะเป็นประมาณนี้
- Link Etherscan - https://sepolia.etherscan.io/address/0xd42391926c4a6a5c5a3987658e18d4f1236be2a4#code
แต่ถ้ามา Verify ทีหลัง เราจำเป็นต้องมีค่าดังนี้
- Contract Address ที่เรา Deploy ไป
- Chain Id - chain ที่เรา จะ Verify
- Construct Args - เป็นแบบ ABI Code
- Etherscan API Key - ใช้ Account ของ Etherscan หลักได้เลย และขอ API Key ได้ฟรี
- Number of Optimization - default 200 ถ้าเราไม่ได้ปรับอะไร
- Compiler Version - ถ้าไม่ใส่ ตัว Foundry จะ detect ให้ เราสามารถกำหนด ให้ตรงกับที่เรา Build & Deploy ได้
ตัว abi code ของ constructor เราจะใช้คำสั่ง
จะได้ผลลัพธ์แบบนี้
ทำการ Verify Contract
หรือ
🎉 จบแล้ว ลองไปเล่นกันดูนะครับ
สรุป
หลังจากลอง Workflow การพัฒนา การ Test การ Deploy ต่างๆ ก็รู้สึกว่าเร็วดี และก็ไม่ได้ยุ่งยากเท่าไหร่ มีติดปัญหาตรง Deploy และก็ Verify Contract นิดหน่อย พวกค่า environment variables ต่างๆ ใช้ prefix FOUNDRY_ กับบางค่าไม่ได้ด้วย (ไม่ตรงกับ Struct ของ Foundry) และก็เรื่อง foundry.toml ที่ยังไม่ได้ลองกำหนด Config ดีๆเลย แบบแยก chain แยก etherscan
ดู config
นอกจากนั้น พวก Library ต่างๆ ถ้าเป็น Hardhat ส่วนใหญ่ใช้ OpenZeppelin ถ้าใน Foundry เห็นหลายๆคนนิยมใช้ Solmate และติดตั้งผ่าน forge ได้เลย
จริงๆ Foundry ก็ติดตั้ง OpenZeppelin ได้เหมือนกัน
Happy Coding ❤️
Reference
Foundry BookA book on all things FoundryFoundry Book
- Authors
-
Chai Phonbopit
เป็น Web Dev ในบริษัทแห่งหนึ่ง ทำงานมา 10 ปีกว่าๆ ด้วยภาษาและเทคโนโลยี เช่น JavaScript, Node.js, React, Vue และปัจจุบันกำลังสนใจในเรื่องของ Blockchain และ Crypto กำลังหัดเรียนภาษา Rust