คำเตือนความเสี่ยง: ระวังความเสี่ยงจากการระดมทุนที่ผิดกฎหมายในนาม 'สกุลเงินเสมือน' 'บล็อกเชน' — จากห้าหน่วยงานรวมถึงคณะกรรมการกำกับดูแลการธนาคารและการประกันภัย
ข่าวสาร
ค้นพบ
ค้นหา
เข้าสู่ระบบ
简中
繁中
English
日本語
한국어
ภาษาไทย
Tiếng Việt
BTC
ETH
HTX
SOL
BNB
ดูตลาด
สินค้าแห้ง: แนวทางปฏิบัติด้านความปลอดภัยที่ดีที่สุดสำหรับสัญญาตัวแทน Diamond
CertiK
特邀专栏作者
2023-06-22 08:30
บทความนี้มีประมาณ 3319 คำ การอ่านทั้งหมดใช้เวลาประมาณ 5 นาที
การออกแบบสัญญาของโมเดลพร็อกซีเพชรสามารถแก้ปัญหาข้อจำกัดขนาดสัญญาสูงสุดของเครือข่าย Ethereu

สัญญาพร็อกซีเป็นเครื่องมือสำคัญสำหรับนักพัฒนาสัญญาอัจฉริยะ ปัจจุบัน มีโหมดพร็อกซีและกฎการใช้งานที่สอดคล้องกันมากมายในระบบสัญญา ก่อนหน้านี้เราได้สรุปแนวทางปฏิบัติที่ดีที่สุดด้านความปลอดภัยของสัญญาพร็อกซีที่อัปเกรดได้

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

สัญญาเพชรพร็อกซี่หรือที่เรียกว่า "เพชร" เป็นรูปแบบการออกแบบสำหรับ Ethereum smart contract ที่นำเสนอโดย Ethereum Improvement Proposal (EIP) 2535

โหมดไดมอนด์ช่วยให้สัญญามีฟังก์ชันไม่จำกัดโดยแบ่งฟังก์ชันออกเป็นสัญญาเล็กๆ (เรียกอีกอย่างว่า "ลักษณะ") ไดมอนด์ทำหน้าที่เป็นพร็อกซี ฟังก์ชันการกำหนดเส้นทางจะเรียกไปยังลักษณะที่เหมาะสม

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

Diamond Brokerage มอบความยืดหยุ่นอย่างมากเมื่อเทียบกับสัญญาที่อัปเกรดได้แบบดั้งเดิม ช่วยให้ชิ้นส่วนสัญญาสามารถอัพเกรด เพิ่ม แทนที่ หรือลบส่วนของฟังก์ชันที่เลือกโดยไม่ต้องแตะต้องส่วนอื่น

บทความนี้ให้ภาพรวมของ EIP-2535 รวมถึงการเปรียบเทียบกับโหมดพร็อกซีโปร่งใสที่ใช้กันอย่างแพร่หลายและโหมดพร็อกซี UUPS และข้อควรพิจารณาด้านความปลอดภัยสำหรับชุมชนนักพัฒนา

ในบริบทของ EIP-2535"เพชร"เป็นสัญญาพร็อกซีที่มีการใช้งานฟังก์ชันโดยสัญญาลอจิกที่แตกต่างกัน ซึ่งเรียกว่า "ลักษณะ"

ลองนึกภาพว่าเพชรแท้มีด้านต่างๆ ที่เรียกว่า facets และสัญญาเพชร Ethereum ที่สอดคล้องกันก็มีด้านต่างๆ กัน ฟังก์ชั่นการยืมเพชรแต่ละสัญญานั้นมีด้านหรือแง่มุมที่แตกต่างกัน

มาตรฐานเพชรใช้การเปรียบเทียบเพื่อขยายขีดความสามารถของ "การเจียระไนเพชร" เพื่อเพิ่ม แทนที่ หรือลบเหลี่ยมเพชรพลอยและคุณลักษณะต่างๆ

นอกจากนี้ Diamond Standard ยังมีคุณสมบัติที่เรียกว่า "Diamond Loupe" ซึ่งจะส่งคืนข้อมูลเกี่ยวกับเหลี่ยมเพชรพลอยและการมีอยู่ของเพชร

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

สัญญากลางที่ทำหน้าที่เป็นพร็อกซี ฟังก์ชันการกำหนดเส้นทางเรียกไปยังลักษณะที่เหมาะสม ประกอบด้วยการแมปตัวเลือกฟังก์ชันกับที่อยู่ "ลักษณะ"

สัญญาเดียวที่ใช้ฟังก์ชันเฉพาะ แต่ละด้านประกอบด้วยชุดของฟังก์ชันที่เพชรเรียกได้

เป็นชุดของฟังก์ชันมาตรฐานที่กำหนดใน EIP-2535 ซึ่งให้ข้อมูลเกี่ยวกับตัวเลือกด้านและฟังก์ชันที่ใช้ในเพชร Diamond Loupe ช่วยให้นักพัฒนาและผู้ใช้ตรวจสอบและทำความเข้าใจโครงสร้างของเพชรได้

ฟังก์ชันสำหรับเพิ่ม แทนที่ หรือลบเหลี่ยมเพชรและตัวเลือกคุณลักษณะที่เกี่ยวข้อง เฉพาะที่อยู่ที่ได้รับอนุญาต (เช่น เจ้าของเพชรหรือสัญญาหลายลายเซ็น) เท่านั้นที่จะทำการเจียระไนเพชรได้

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

พร็อกซีทั้งหมดใช้ฟังก์ชัน fallback() ซึ่งมอบสิทธิ์การเรียกใช้ฟังก์ชันไปยังที่อยู่ภายนอก ด้านล่างนี้คือการใช้งานพร็อกซีไดมอนด์และการใช้งานพร็อกซีแบบดั้งเดิม

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

ข้อแตกต่างที่สำคัญคือในพร็อกซีรูปเพชร ที่อยู่ของลักษณะจะถูกกำหนดโดยแฮชแมปจาก msg.sig ของผู้โทร (ตัวเลือกฟังก์ชัน) ไปยังที่อยู่ของลักษณะ ขณะที่ในพร็อกซีแบบดั้งเดิม ที่อยู่โดยนัยจะไม่ขึ้นอยู่กับ ของผู้โทรเข้ามา

ฟังก์ชั่นสำรองตัวแทนเพชร

ฟังก์ชันสำรองพร็อกซีแบบดั้งเดิม

การแมป SelectorToFacet กำหนดว่าสัญญาใดมีการใช้งานตัวเลือกฟังก์ชันแต่ละตัว ผู้ปฏิบัติงานโครงการมักจำเป็นต้องเพิ่ม แทนที่ หรือลบการแมปสัญญาตัวเลือกการนำไปใช้งานของฟังก์ชันนี้ EIP-2535 ระบุว่า: เพื่อให้บรรลุเป้าหมายนี้ ต้องมีฟังก์ชัน diamondCut() ด้านล่างนี้คืออินเทอร์เฟซตัวอย่าง

โครงสร้าง FacetCut แต่ละโครงสร้างมีที่อยู่ของ facet และอาร์เรย์ตัวเลือกคุณลักษณะสี่ไบต์ที่จะอัปเดตในสัญญาพร็อกซีรูปเพชร FaceCutAction ช่วยให้สามารถเพิ่ม แทนที่ และลบตัวเลือกคุณสมบัติได้ การใช้ฟังก์ชัน diamondCut() ควรรวมถึงการควบคุมการเข้าถึงที่เพียงพอ ป้องกันการชนกันของช่อง การกู้คืนเมื่อล้มเหลว เป็นต้น

เพื่อสอบถามว่าตัวแทนเพชรมีหน้าที่และลักษณะอย่างไร เราจึงใช้ "แว่นขยายเพชร" "Diamond Loupe" มีลักษณะพิเศษที่ใช้อินเทอร์เฟซต่อไปนี้ที่กำหนดไว้ใน EIP-2535:

ฟังก์ชัน facets() ควรส่งคืนที่อยู่ของ facets ทั้งหมดและตัวเลือกฟังก์ชันสี่ไบต์ ฟังก์ชัน facetFunctionSelectors() ควรส่งคืนตัวเลือกฟังก์ชันทั้งหมดที่รองรับโดยลักษณะเฉพาะ ฟังก์ชัน facetAddresses() ควรส่งคืนที่อยู่ facet ทั้งหมดที่ใช้โดยเพชร

ฟังก์ชัน facetAddress() ควรส่งคืนส่วนที่สนับสนุนตัวเลือกที่กำหนด หรือที่อยู่ (0) หากไม่พบ โปรดทราบว่าไม่ควรมีที่อยู่ด้านกว้างมากกว่าหนึ่งรายการที่มีตัวเลือกคุณลักษณะเดียวกัน

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

ด้านนี้สามารถประกาศตัวแปรสถานะในโครงสร้าง ลักษณะนี้สามารถใช้โครงสร้างจำนวนเท่าใดก็ได้ โดยแต่ละส่วนมีตำแหน่งจัดเก็บต่างกัน แต่ละโครงสร้างมีตำแหน่งเฉพาะในการจัดเก็บสัญญา Aspects สามารถประกาศตัวแปรสถานะของตัวเองได้ แต่ไม่สามารถขัดแย้งกับตำแหน่งที่เก็บข้อมูลของตัวแปรสถานะที่ประกาศโดยด้านอื่นๆ ห้องสมุดตัวอย่างและสัญญาการจัดเก็บเพชรมีอยู่ใน EIP-2535 ดังแสดงในรูปต่อไปนี้:

App Store เป็น Diamond Store เวอร์ชันพิเศษกว่า รูปแบบนี้ใช้เพื่อแบ่งปันตัวแปรสถานะของลักษณะต่างๆ ได้สะดวกและง่ายดายยิ่งขึ้น โครงสร้าง App Store ถูกกำหนดให้มีจำนวนและประเภทของตัวแปรสถานะที่แอปพลิเคชันต้องการ ลักษณะจะประกาศโครงสร้าง AppStorage เป็นตัวแปรสถานะตัวแรกและตัวเดียวเสมอ ที่ตำแหน่ง 0 ของสล็อตที่เก็บข้อมูล ด้านต่างๆจึงสามารถเข้าถึงตัวแปรจากโครงสร้างนี้ได้

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

เปรียบเทียบกับ Transparent Proxy และ UUPS Proxy

โหมดพร็อกซีหลักสองโหมดที่ใช้โดยชุมชนนักพัฒนา Web3 คือโหมดพร็อกซีโปร่งใสและโหมดพร็อกซี UUPS ในส่วนนี้ เราจะเปรียบเทียบโหมดไดมอนด์พร็อกซีกับโหมดพร็อกซีแบบโปร่งใสและโหมดพร็อกซี UUPS โดยสังเขป

1.EPI-2535:https://eips.ethereum.org/EIPS/eip-2535 #Facets,% 20 State% 20 Variables% 20 and% 20 Diamond% 20 Storage

2.EPI-1967:https://eips.ethereum.org/EIPS/eip-1967    

3.Diamond proxy reference implementation: https://github.com/mudgen/Diamond    

4.OpenZeppelin implementation: https://github.com/OpenZeppelin/openzeppelin-contracts/tree/v4.7.0/contracts/proxy

พร็อกซีและโซลูชันที่ปรับขนาดได้เป็นระบบที่ซับซ้อนมากขึ้น และ OpenZeppelin จัดเตรียมฐานรหัสและเอกสารที่ครอบคลุมสำหรับพร็อกซีที่ปรับขนาดได้ของ UUPS, Transparent และ Beacon อย่างไรก็ตาม สำหรับรูปแบบ Diamond Proxy ในขณะที่ OpenZeppelin ยืนยันถึงประโยชน์ของมัน พวกเขายังคงตัดสินใจที่จะไม่รวมการใช้งาน EIP-2535 Diamond ในไลบรารีของพวกเขา

ดังนั้น นักพัฒนาที่ใช้ไลบรารีของบุคคลที่สามที่มีอยู่หรือนำโซลูชันนี้ไปใช้เองจะต้องดำเนินการด้วยความระมัดระวังอย่างยิ่ง ที่นี่เราได้รวบรวมรายการตรวจสอบแนวทางปฏิบัติที่ดีที่สุดด้านความปลอดภัยสำหรับชุมชนนักพัฒนาซอฟต์แวร์เพื่อพิจารณา

การแบ่งตรรกะของสัญญาออกเป็นโมดูลที่เล็กลงและสามารถจัดการได้มากขึ้น นักพัฒนาสามารถทดสอบและตรวจสอบรหัสของตนได้ง่ายขึ้น

คำอธิบายภาพ

ที่มา: Aavegotchi Github

คำอธิบายภาพ

ที่มา: Mugen's Diamond-3-Hardhat

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

รูปแบบ AppStorage กำหนดให้มีการประกาศโครงสร้างเดียวและโครงสร้างเดียวสำหรับไดมอนด์พร็อกซี และโครงสร้างนี้ต้องแชร์โดยทุกด้าน หากจำเป็นต้องมีโครงสร้างหลายส่วน ควรใช้รูปแบบ DiamondStorage

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

วิธีแก้ปัญหาคือเพิ่มตัวแปรสถานะใหม่ให้กับโครงสร้างที่แมปหน่วยความจำแทนการวาง "struct" โดยตรงใน "struct" ช่องจัดเก็บตัวแปรในแผนที่มีการคำนวณต่างกันและไม่ได้อยู่ติดกันในที่จัดเก็บ

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

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

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

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

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

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

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

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

ในขณะเดียวกัน ทีมงานโครงการควรทำการทดสอบอย่างเข้มงวดและการตรวจสอบจากบุคคลที่สามเพื่อลดความเสี่ยงของช่องโหว่ที่เกี่ยวข้องกับการดำเนินการตามสัญญาตัวแทนเพชร

CertiK จะเผยแพร่บทความทางเทคนิคดังกล่าวต่อไปเพื่อช่วยให้นักพัฒนาจำนวนมากขึ้นสามารถพัฒนาได้อย่างปลอดภัย ติดตามเราเพื่อรับข้อมูลและข้อมูลที่คล้ายกันมากขึ้น!

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