คำเตือนความเสี่ยง: ระวังความเสี่ยงจากการระดมทุนที่ผิดกฎหมายในนาม 'สกุลเงินเสมือน' 'บล็อกเชน' — จากห้าหน่วยงานรวมถึงคณะกรรมการกำกับดูแลการธนาคารและการประกันภัย
ข่าวสาร
ค้นพบ
ค้นหา
เข้าสู่ระบบ
简中
繁中
English
日本語
한국어
ภาษาไทย
Tiếng Việt
BTC
ETH
HTX
SOL
BNB
ดูตลาด
ไดอารี่การพัฒนาสัญญาสมาร์ทสนิม (9)
BlockSec
特邀专栏作者
2022-04-01 11:39
บทความนี้มีประมาณ 2024 คำ การอ่านทั้งหมดใช้เวลาประมาณ 3 นาที
ปัญหาพื้นฐานในการบำรุงรักษาโปรแกรมคือการแก้ไขจุดบกพร่องจะแนะนำจุดบกพร่องใหม่เสมอโดยม

ชื่อเรื่องรอง

1. ความจำเป็นในการอัพเกรดสัญญา

ชื่อเรื่องรอง

2. วิธีการอัปเกรดทั่วไปสำหรับสัญญา Solidity

ใน Ethereum สัญญาอัจฉริยะนั้นเปลี่ยนรูปไม่ได้ เมื่อนำไปใช้ในห่วงโซ่แล้วจะไม่มีใครสามารถเปลี่ยนแปลงได้

ดังนั้นหากมีช่องโหว่ในสัญญาหรือสัญญาต้องการเพิ่มฟังก์ชั่นใหม่ จะแก้ไขรหัสของสัญญาได้อย่างไร? วิธีแก้ไขคือปรับใช้สัญญาใหม่กับบล็อกเชน

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

ดังนั้น เรามักจะใช้สถาปัตยกรรมที่แยกข้อมูลและตรรกะออกจากกัน และข้อมูลจะถูกจัดเก็บไว้ในสัญญา (สัญญาสถานะ) ที่ไม่ประมวลผลตรรกะใดๆ และตรรกะทั้งหมดจะถูกนำไปใช้ในสัญญาอื่น (สัญญาตรรกะ) โดยปกติแล้วการอัปเกรดสัญญาจะแก้ไขลอจิก การใช้ สถาปัตยกรรมนี้จำเป็นต้องอัปเกรดสัญญาลอจิกเท่านั้นโดยไม่ต้องกังวลเกี่ยวกับการย้ายสถานะ

เพื่อแก้ปัญหานี้ สามารถใช้สัญญาตัวแทน (Proxy Contract) ได้ และโครงสร้างเฉพาะจะแสดงในรูปด้านล่าง

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

3. วิธีการทั่วไปของการอัปเกรดสัญญา NEAR

ต่อไป เราจะยกตัวอย่างโครงการ StatusMessage เพื่อแนะนำวิธีการอัปเกรดทั่วไปของสัญญา NEAR รหัสสัญญาของ StatusMessage มีดังนี้

ก่อนอื่นเราจะปรับใช้สัญญาที่คอมไพล์แล้วบนเครือข่ายทดสอบ

การทำธุรกรรมมีดังนี้

จากนั้นเราเรียกเมธอด set_status เพื่อเก็บข้อมูลในสัญญา

การทำธุรกรรมมีดังนี้

ต่อไปเราจะหารือในรายละเอียดสองสถานการณ์การอัปเกรดสัญญาที่แตกต่างกัน

3.1 โครงสร้างข้อมูลสัญญาไม่ได้รับการแก้ไข

ตัวอย่างเช่น เราเพิ่มฟังก์ชัน:

หลังจากคอมไพล์แล้ว ให้ใช้การปรับใช้เพื่อปรับใช้ใหม่:

หลังจากคอมไพล์แล้ว ให้ใช้การปรับใช้เพื่อปรับใช้ใหม่:

จากนั้นเราเรียกเมธอด get_status เพื่ออ่านข้อมูลที่เขียนไว้ก่อนหน้านี้

ข้อมูลในสัญญาเดิมสามารถอ่านได้สำเร็จ:

เนื่องจากสามารถใช้สัญญา NEAR ซ้ำได้ หากบัญชี (ที่อยู่) ได้ปรับใช้สัญญาแล้ว การเรียกคำสั่ง Near ปรับใช้อีกครั้งจะสามารถนำรหัสสัญญาใหม่ไปใช้กับบัญชีได้ หากเราแก้ไขเฉพาะตรรกะของสัญญาโดยไม่แก้ไขโครงสร้างข้อมูล เราสามารถใช้ Near Deploy เพื่อปรับใช้โค้ดใหม่ได้โดยตรง

3.2 มีการแก้ไขโครงสร้างข้อมูลสัญญา

เราอัปเกรดสัญญา แก้ไขโครงสร้างข้อมูลเดิม ลบบันทึก เพิ่มแท็กไลน์และประวัติ

เราพยายามปรับใช้อีกครั้ง:

สัญญายังคงใช้งานได้สำเร็จ:

แต่เราเรียกเมธอด get_tagline เพื่ออ่านข้อมูลที่เก็บไว้:

คุณจะพบว่ามีบางอย่างผิดพลาด และข้อความแสดงข้อผิดพลาดจะเป็นดังนี้:

Cannot deserialize the contract state.

ดูธุรกรรมเฉพาะ:

https://explorer.testnet.near.org/transactions/4hQQ1zAwU5bsbfb6tA6DQDqjmFcHsBwaBctdHaPiCKHu

นี่เป็นเพราะสถานะของสัญญาถูกจัดเก็บอย่างต่อเนื่องในรูปแบบของข้อมูลซีเรียลไลซ์ หลังจากปรับใช้สัญญาใหม่ โครงสร้างข้อมูลในรหัสจะเปลี่ยนไป แต่สถานะยังคงไม่เปลี่ยนแปลง หากโครงสร้างข้อมูลใหม่ไม่ตรงกับสถานะเก่า เกิดข้อผิดพลาด

3.3 ย้ายสัญญาสมาร์ทอัพเกรด

NEAR มีวิธีการย้ายข้อมูลเพื่อช่วยเราอัปเกรดสัญญา สำหรับข้อผิดพลาดใน 3.2 เราได้เพิ่มวิธีการย้ายข้อมูลในสัญญาใหม่:

#[init(ignore_state)] ในโค้ดหมายความว่าอย่าโหลดสถานะก่อนที่จะดำเนินการโอนย้ายฟังก์ชัน ต่อไป เราปรับใช้สัญญาอีกครั้ง แต่เรียกวิธีการโอนย้ายขณะปรับใช้

ดังที่แสดงด้านล่าง สัญญาถูกปรับใช้สำเร็จ:

เราพยายามเรียกเมธอดใหม่ get_tagline ของสัญญาเพื่อรับแท็กไลน์ข้อมูลใหม่

จะเห็นได้ว่ามีการเรียกใช้เมธอดสำเร็จ และข้อมูลสัญญาเก่าจะถูกย้ายไปยังสัญญาใหม่ด้วย

4. ข้อควรพิจารณาด้านความปลอดภัยสำหรับการอัปเกรดสัญญา

การอัปเกรดความปลอดภัยของสัญญาต้องพิจารณาการควบคุมสิทธิ์ก่อน โดยทั่วไป สัญญาสามารถอัปเกรดได้โดยนักพัฒนาหรือ DAO เท่านั้น ระยะสุดท้ายบันทึกการเพาะปลูกสัญญาสมาร์ทสนิม (8) ผู้มีอำนาจควบคุมการรักษาความปลอดภัยของสัญญาแนะนำการควบคุมการเข้าถึงของฟังก์ชันที่มีสิทธิพิเศษ ฟังก์ชันการอัปเกรดของสัญญาทั่วไปเป็นฟังก์ชันของเจ้าของเพียงรายเดียว เพื่อให้แน่ใจว่าเจ้าของเท่านั้นที่จะสามารถเรียกใช้ได้

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

นอกจากนี้ นักพัฒนายังสามารถพิจารณาคำแนะนำต่อไปนี้เมื่อทำการย้ายสัญญา

  • เพิ่ม #[init(ignore_state)] ก่อนฟังก์ชันการย้ายข้อมูลเพื่อให้แน่ใจว่าสถานะไม่ถูกโหลดก่อนที่ฟังก์ชันการย้ายข้อมูลจะทำงาน

  • หลังจากการย้ายข้อมูลเสร็จสิ้น ให้ลบฟังก์ชันการย้ายข้อมูลออกให้มากที่สุดเพื่อให้แน่ใจว่ามีการเรียกใช้ฟังก์ชันการย้ายข้อมูลเพียงครั้งเดียว

  • โครงสร้างข้อมูลที่เพิ่มใหม่จะเริ่มต้นระหว่างการย้ายข้อมูล

สัญญาที่ชาญฉลาด
ยินดีต้อนรับเข้าร่วมชุมชนทางการของ Odaily
กลุ่มสมาชิก
https://t.me/Odaily_News
กลุ่มสนทนา
https://t.me/Odaily_CryptoPunk
บัญชีทางการ
https://twitter.com/OdailyChina
กลุ่มสนทนา
https://t.me/Odaily_CryptoPunk
สรุปโดย AI
กลับไปด้านบน
ปัญหาพื้นฐานในการบำรุงรักษาโปรแกรมคือการแก้ไขจุดบกพร่องจะแนะนำจุดบกพร่องใหม่เสมอโดยม
ดาวน์โหลดแอพ Odaily พลาเน็ตเดลี่
ให้คนบางกลุ่มเข้าใจ Web3.0 ก่อน
IOS
Android