เหตุการณ์เทียบกับพื้นที่จัดเก็บ
ข้อแลกเปลี่ยนด้านแก๊ส
เหตุการณ์เทียบกับพื้นที่จัดเก็บ เป็นบทเรียน Web3 & DApp Development Fundamentals ฟรีบน CoddyKit นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน คุณสามารถอ่านบทเรียนทั้งหมดด้านล่างฟรี — จากนั้นลองปฏิบัติด้วยตัวคุณเองในเบราว์เซอร์พร้อมตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7 บทเรียนนี้เป็นส่วนหนึ่งของเส้นทางการเรียน Web3 & DApp Development Fundamentals และความก้าวหน้าของคุณจะซิงค์ข้ามเว็บและแอป CoddyKit คอร์ส Web3 & DApp Development Fundamentals มีบทเรียนทั้งหมด 4 บทเรียน
สองวิธีในการบันทึกข้อมูล
เมื่อมีบางสิ่งเกิดขึ้นในสัญญา คุณสามารถบันทึกไว้ใน ข้อมูลจัดเก็บ หรือใน log ของอีเวนต์ การเลือกใช้อย่างเหมาะสมเป็นทักษะสำคัญในการปรับปรุงประสิทธิภาพด้านแก๊ส
บทเรียนนี้เปรียบเทียบข้อแลกเปลี่ยน เพื่อให้คุณทราบว่าควรใช้แต่ละวิธีเมื่อใด
ทบทวนข้อมูลจัดเก็บ
ข้อมูลจัดเก็บ คือสถานะถาวรของสัญญา เป็นข้อมูลเพียงประเภทเดียวที่สัญญาสามารถ อ่านกลับ ได้ภายหลัง แต่การเขียนข้อมูลลงไปมีค่าใช้จ่ายสูงมาก
<code>mapping(address => uint256) public balances; // contract can read this</code>ทบทวนอีเวนต์
อีเวนต์ จะเขียนลงใน log ของธุรกรรม มีค่าใช้จ่ายถูกกว่ามาก แต่สัญญา ไม่สามารถอ่านกลับ บนเชนได้ มีเพียงไคลเอ็นต์นอกเชนเท่านั้นที่ทำได้
<code>event BalanceChanged(address indexed who, uint256 newBalance);
// off-chain apps read this; the contract cannot</code>ความแตกต่างของค่าแก๊ส
การเขียนช่องข้อมูลจัดเก็บใหม่ (การใช้ SSTORE จากค่าเป็นศูนย์) มีค่าใช้จ่ายประมาณ 20,000 แก๊ส ส่วนการส่งหัวข้อ log หรือคำข้อมูลมีค่าใช้จ่ายเพียงไม่กี่ร้อยแก๊ส อีเวนต์จึงอาจมีราคาถูกกว่าหลายเท่าตัว
กฎทอง
แนวทางง่าย ๆ:
- จัดเก็บข้อมูลที่ สัญญาจำเป็นต้องอ่านหรือใช้ในตรรกะภายหลัง
- ส่งเหตุการณ์เฉพาะข้อมูลที่ โลกภายนอกต้องใช้ (ประวัติ ส่วนติดต่อผู้ใช้ การวิเคราะห์ข้อมูล)
อย่าจัดเก็บข้อมูลเพียงเพื่อการแสดงผล ให้ส่งเหตุการณ์แทน
สิ่งที่ต้องอยู่ในหน่วยความจำจัดเก็บ
ยอดคงเหลือ ความเป็นเจ้าของ สิทธิ์การใช้จ่าย และค่าใด ๆ ที่ใช้ในการตรวจสอบด้วย require หรือการคำนวณในอนาคต ต้องอยู่ในหน่วยความจำจัดเก็บ เนื่องจากสัญญาต้องอ่านค่าเหล่านี้
<code>function transfer(address to, uint256 amt) public {
require(balances[msg.sender] >= amt); // needs storage
balances[msg.sender] -= amt;
balances[to] += amt;
}</code>สิ่งที่เป็นเพียงเหตุการณ์ได้
ประวัติธุรกรรม บันทึกการตรวจสอบ หรือฟีดการแจ้งเตือน เหมาะอย่างยิ่งที่จะใช้เหตุการณ์ สัญญาไม่จำเป็นต้องย้อนกลับมาอ่านระเบียนเหล่านี้ ดังนั้นการจัดเก็บไว้จะเป็นการสิ้นเปลืองแก๊ส
<code>event Logged(address indexed user, string action, uint256 time);
function act(string memory a) public {
emit Logged(msg.sender, a, block.timestamp); // no storage
}</code>ใช้ทั้งสองอย่างร่วมกัน
รูปแบบที่พบได้บ่อยที่สุดคือ จัดเก็บสถานะใหม่และส่งเหตุการณ์ ที่อธิบายการเปลี่ยนแปลง ค่าที่จัดเก็บจะขับเคลื่อนตรรกะ ส่วนเหตุการณ์จะทำให้ส่วนติดต่อผู้ใช้สอดคล้องกัน
<code>function deposit() public payable {
balances[msg.sender] += msg.value; // storage for logic
emit BalanceChanged(msg.sender, balances[msg.sender]); // event for UI
}</code>บันทึกไม่สามารถสืบค้นบนเชนได้
ข้อจำกัดสำคัญคือ สัญญาอื่นไม่สามารถอ่านบันทึกที่คุณส่งออกมาได้ หากสัญญา B ต้องการค่าใด สัญญา A ต้องเปิดเผยค่านั้นผ่าน หน่วยความจำจัดเก็บหรือค่าที่ส่งคืน ห้ามส่งผ่านเหตุการณ์
หลีกเลี่ยงการจัดเก็บเพื่อทำประวัติ
ข้อผิดพลาดที่ผู้เริ่มต้นมักทำคือเพิ่มทุกการกระทำลงในอาร์เรย์ในหน่วยความจำจัดเก็บเพื่อสร้างประวัติ อาร์เรย์นี้จะขยายโดยไม่มีขอบเขตและมีค่าใช้จ่ายสูงมาก ให้ส่งเหตุการณ์แทน แล้วให้ตัวจัดทำดัชนีนอกเชนสร้างประวัติขึ้นใหม่
<code>// Anti-pattern: unbounded, costly
// historyArray.push(record);
// Better:
emit ActionRecorded(msg.sender, block.timestamp);</code>รายการตรวจสอบเพื่อการตัดสินใจ
ถามว่า มีโค้ดบนเชนใดอ่านค่านี้ในภายหลังหรือไม่
- มี - ใช้หน่วยความจำจัดเก็บ (และอาจส่งเหตุการณ์ด้วย)
- ไม่มี ใช้เพื่อการแสดงผลหรือการตรวจสอบเท่านั้น - ใช้เหตุการณ์อย่างเดียว
คำถามเดียวนี้ช่วยแก้การตัดสินใจด้านการออกแบบส่วนใหญ่ได้
ตรวจสอบอย่างรวดเร็ว
ทดสอบความเข้าใจของคุณเกี่ยวกับเหตุการณ์และหน่วยความจำจัดเก็บ
สรุปทบทวน
คุณได้เรียนรู้ข้อแลกเปลี่ยนระหว่างหน่วยความจำจัดเก็บกับเหตุการณ์:
- หน่วยความจำจัดเก็บอ่านได้บนเชน แต่มีค่าใช้จ่ายสูง (ประมาณ 20k แก๊สต่อช่องใหม่)
- เหตุการณ์มีค่าใช้จ่ายต่ำ แต่มีเพียงไคลเอ็นต์นอกเชนเท่านั้นที่อ่านได้
- จัดเก็บสิ่งที่สัญญาจำเป็นต้องใช้ และส่งเหตุการณ์สำหรับสิ่งที่โลกภายนอกเท่านั้นที่ต้องการ
- รูปแบบทั่วไปคือ อัปเดตหน่วยความจำจัดเก็บ AND ส่งเหตุการณ์
อย่าจัดเก็บข้อมูลเพียงเพื่อประวัติหรือการแสดงผล
เรียนรู้ Web3 & DApp Development Fundamentals ด้วย AI tutor — ฟรี
เขียนและเรียกใช้โค้ดจริงในเบราว์เซอร์ของคุณ รับความช่วยเหลือทันทีจาก AI tutor 24/7 และเรียนรู้ต่อจากที่คุณหยุดบนเว็บหรือในแอป
- คอร์ส
- 29
- บทเรียน
- 105
คำถามที่พบบ่อย
บทเรียน “เหตุการณ์เทียบกับพื้นที่จัดเก็บ” ฟรีหรือไม่
ใช่ — ข้อความเต็มของ “เหตุการณ์เทียบกับพื้นที่จัดเก็บ” ฟรีให้อ่านที่นี่บนเว็บ เพื่อปฏิบัติแบบโต้ตอบ (ตัวแก้ไขโค้ดในตัวและติวเตอร์ AI ตลอด 24/7) และปลดล็อคส่วนที่เหลือของคอร์ส Web3 & DApp Development Fundamentals ให้อัปเกรดเป็น CoddyKit PRO คอร์ส Web3 & DApp Development Fundamentals มีบทเรียนทั้งหมด 4 บทเรียน
คุณจะเรียนรู้อะไรในบทเรียน “เหตุการณ์เทียบกับพื้นที่จัดเก็บ”
ข้อแลกเปลี่ยนด้านแก๊ส คุณปฏิบัติ Web3 & DApp Development Fundamentals ด้วยโค้ดที่ใช้งานได้จริงที่คุณเรียกใช้โดยตรงในเบราว์เซอร์ และติวเตอร์ AI ตลอด 24/7 ตอบคำถามของคุณขณะที่คุณไปผ่านบทเรียน
คุณต้องมีประสบการณ์ก่อนที่จะเริ่มเรียน Web3 & DApp Development Fundamentals หรือไม่
ไม่จำเป็นต้องมีประสบการณ์มาก่อน Web3 & DApp Development Fundamentals บน CoddyKit ออกแบบมาสำหรับผู้เริ่มต้นไปจนถึงผู้เรียนขั้นสูง คุณสามารถเริ่มต้นที่นี่หรือเริ่มจากตัวแรกและเรียนด้วยความเร็วของคุณเอง นี่คือบทเรียนที่ 4 จากทั้งหมด 4 บทเรียน
บทเรียน “เหตุการณ์เทียบกับพื้นที่จัดเก็บ” ใช้เวลานานแค่ไหน
บทเรียน CoddyKit ส่วนใหญ่ใช้เวลาประมาณ 5–10 นาที แต่ละบทเรียนจึงสั้นและเป็นแบบโต้ตอบ คุณสามารถก้าวหน้าอย่างต่อเนื่องและกลับมาเรียนต่อจากตรงที่เพิ่งหยุดบนเว็บและแอปได้เลย
ฉันเขียนและรันโค้ดในบทเรียน Web3 & DApp Development Fundamentals นี้ได้ไหม
ได้ บทเรียน Web3 & DApp Development Fundamentals ทุกบทมีตัวแก้ไขโค้ดในตัว คุณจึงเขียนและรันโค้ดจริงได้เลยในเบราว์เซอร์ และได้รับข้อเสนอแนะจาก AI ในทันที — ไม่ต้องติดตั้งในเครื่องของคุณ
บทเรียนทั้งหมดในหลักสูตรนี้
- การประกาศเหตุการณ์
- พารามิเตอร์ที่จัดทำดัชนี
- การรับฟังเหตุการณ์
- เหตุการณ์เทียบกับพื้นที่จัดเก็บ