แนวทางปฏิบัติด้านความปลอดภัยที่ดีที่สุดสำหรับสัญญาตัวแทนของ Diamond

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

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

สัญญาเพชรพร็อกซี่หรือที่เรียกว่า "เพชร" เป็นรูปแบบการออกแบบสำหรับ 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 ถูกกำหนดให้มีจำนวนและประเภทของตัวแปรสถานะที่แอปพลิเคชันต้องการ ลักษณะจะประกาศโครงสร้าง AppStorage เป็นตัวแปรสถานะตัวแรกและตัวเดียวเสมอ ที่ตำแหน่ง 0 ของสล็อตที่เก็บข้อมูล ด้านต่างๆจึงสามารถเข้าถึงตัวแปรจากโครงสร้างนี้ได้

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

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

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

1.EPI-2535:

2.EPI-1967:

3.การดำเนินการอ้างอิงพร็อกซีไดมอนด์:

4.การใช้งาน OpenZeppelin:

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

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

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

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

ที่มา: Aavegotchi Github

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

ดูต้นฉบับ
เนื้อหานี้มีสำหรับการอ้างอิงเท่านั้น ไม่ใช่การชักชวนหรือข้อเสนอ ไม่มีคำแนะนำด้านการลงทุน ภาษี หรือกฎหมาย ดูข้อจำกัดความรับผิดชอบสำหรับการเปิดเผยความเสี่ยงเพิ่มเติม
  • รางวัล
  • แสดงความคิดเห็น
  • แชร์
แสดงความคิดเห็น
0/400
ไม่มีความคิดเห็น
  • ปักหมุด