ข้ามไปยังเนื้อหา

การโจมตีเงินเฟ้อจากเงินฝากแรกของ ERC-4626: การปัดเศษทำให้หุ้นเป็นศูนย์ได้อย่างไร

เรียนรู้ว่าการบริจาคโดยตรงสามารถบิดเบือนอัตราแลกเปลี่ยนของ Vault ERC-4626 ที่ว่างเปล่า ปัดหุ้นของผู้ฝากลงเป็นศูนย์ และการนำไปใช้กับผู้ใช้จะจำกัดความเสี่ยงได้อย่างไร

อัปเดต

จัดทำขึ้นเพื่อการศึกษาเท่านั้น ไม่ใช่คำแนะนำการลงทุน การลงทุนอาจทำให้เกิดการขาดทุน

คำตอบโดยตรง

การโจมตีเงินเฟ้อจากเงินฝากแรกมุ่งเป้าไปที่ Vault ERC-4626 ที่ว่างเปล่าหรือเกือบว่างเปล่า ผู้โจมตีฝากสินทรัพย์จำนวนเล็กน้อยเพื่อรับหุ้นชุดแรก แล้วโอนสินทรัพย์อ้างอิงเข้า Vault โดยตรง การบริจาคนี้เพิ่ม totalAssets() โดยไม่เพิ่ม totalSupply() จึงทำให้หุ้นที่มีอยู่แต่ละหุ้นมีมูลค่าสูงขึ้น

หากเงินฝากของเหยื่อถูกแปลงด้วยอัตราที่ถูกบิดเบือน การหารจำนวนเต็มอาจปัดผลลัพธ์ลงเหลือหุ้นเพียงเล็กน้อยหรือเป็นศูนย์ สินทรัพย์ของเหยื่อยังอยู่ใน Vault ขณะที่ผู้โจมตีซึ่งถือหุ้นทั้งหมดที่หมุนเวียนอยู่สามารถไถ่ถอนสิทธิเรียกร้องที่พองตัวได้ นี่คือปัญหาการบิดเบือนอัตราแลกเปลี่ยนและ Slippage ไม่ใช่ข้อบกพร่องของอินเทอร์เฟซ ERC-4626 เอง

วิธีการทำงาน

ใน Vault แบบเรียบง่ายที่ไม่มีค่าธรรมเนียมหรือค่าชดเชยเพื่อการป้องกัน หุ้นที่สร้างให้กับเงินฝากจะมีค่าประมาณ assets * totalSupply / totalAssets ERC-4626 กำหนดให้การคำนวณหุ้นสำหรับจำนวนสินทรัพย์ที่กำหนดปัดลงเพื่อประโยชน์ของ Vault ที่อัตราแลกเปลี่ยนปกติ การสูญเสียจากการปัดเศษมีเพียงเล็กน้อย แต่เมื่อราคาหุ้นถูกทำให้สูงขึ้น เงินฝากที่มีมูลค่าน้อยกว่าหนึ่งหุ้นอาจสูญเสีย 100% จากการปัดเศษ

การโจมตีขึ้นอยู่กับรายละเอียดของการนำไปใช้ การโอน ERC-20 โดยตรงอาจเพิ่มสินทรัพย์ที่ Vault บันทึกไว้โดยไม่สร้างหุ้น โดยเฉพาะเมื่อ totalAssets() อ่านยอดคงเหลือโทเคนของ Vault ผู้โจมตียังต้องทำธุรกรรมก่อนเหยื่อในขณะที่อุปทานหุ้นต่ำมาก Vault ที่ใช้วิธีบัญชีต่างออกไปหรือมีมาตรการป้องกันโดยชัดแจ้งอาจไม่เสี่ยงในลักษณะเดียวกัน

ตัวอย่าง

สมมติว่า Vault ว่างเปล่าที่มีช่องโหว่เริ่มต้นด้วยอัตรา 1:1 ผู้โจมตีฝากสินทรัพย์ 1 หน่วยและรับ 1 หุ้น จากนั้นบริจาคโดยตรง 999 หน่วย ขณะนี้ Vault มีสินทรัพย์ 1,000 หน่วยรองรับ 1 หุ้น เหยื่อฝาก 999 หน่วย ดังนั้นการคำนวณแบบตรงไปตรงมาหลังปัดเศษจำนวนเต็มคือ 999 * 1 / 1,000 = 0 หุ้น

จากนั้น Vault ถือสินทรัพย์ 1,999 หน่วย ขณะที่มีเพียง 1 หุ้นของผู้โจมตี หากการฝากอนุญาตผลลัพธ์เป็นศูนย์หุ้นและไม่มีค่าธรรมเนียมหรือข้อจำกัดอื่น ผู้โจมตีสามารถไถ่ถอนหุ้นนั้นเป็นสินทรัพย์ทั้งหมด 1,999 หน่วย ได้แก่ เงินฝากแรก 1 หน่วย เงินบริจาค 999 หน่วย และเงินฝากของเหยื่อ 999 หน่วย กำไรขั้นต้นของผู้โจมตีคือ 999 หน่วยของเหยื่อก่อนหักต้นทุนธุรกรรม

ความเสี่ยงและการป้องกัน

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

ผู้ใช้และผู้เชื่อมต่อระบบควรมอง previewDeposit() เป็นราคาเสนอ ไม่ใช่ขั้นต่ำที่รับประกัน ให้ส่งเงินฝากผ่านฟังก์ชันหรือเราเตอร์ที่บังคับจำนวนหุ้นขั้นต่ำที่ยอมรับได้ และย้อนกลับธุรกรรมเมื่อไม่ถึงขีดจำกัด ก่อนฝากใน Vault ใหม่หรือมีอุปทานหุ้นน้อย ให้ตรวจสอบ totalAssets() totalSupply() สูตรการแปลงของการนำไปใช้ และการโอนโทเคนที่ไม่ได้ร้องขอมีผลต่อบัญชีหรือไม่ ราคาเสนอที่ดีบน Front-end ไม่ได้ปกป้องธุรกรรมที่ลำดับการดำเนินการอาจถูกจัดใหม่

ความเข้าใจผิดที่พบบ่อย

  • ความเชื่อที่ 1: ERC-4626 รับประกันอัตราแลกเปลี่ยนที่ปลอดภัยด้วยตัวเอง มาตรฐานกำหนดอินเทอร์เฟซร่วมและพฤติกรรมการปัดเศษ แต่ไม่ได้ทำให้ทุกการนำไปใช้ปลอดจากการบิดเบือนอัตราแลกเปลี่ยน

  • ความเชื่อที่ 2: การเรียก previewDeposit() ทันทีก่อน deposit() รับประกันผลลัพธ์นั้น สถานะบนเชนอาจเปลี่ยนระหว่างการเรียกหรือก่อนดำเนินการ เส้นทางฝากต้องมีขีดจำกัดหุ้นขั้นต่ำที่บังคับใช้ได้

  • ความเชื่อที่ 3: การปฏิเสธเฉพาะเงินฝากที่ได้ศูนย์หุ้นจะกำจัดการโจมตี วิธีนี้ป้องกันผลลัพธ์ที่รุนแรงที่สุด แต่ผู้โจมตียังอาจทำให้เงินฝากได้รับหุ้นเพียงเล็กน้อยและสูญเสียมากจากการปัดเศษ การป้องกันควรจำกัด Slippage ที่ยอมรับได้ ไม่ใช่เพียงกำหนดให้ผลลัพธ์ไม่เป็นศูนย์

หัวข้อที่เกี่ยวข้อง

แหล่งที่มา

การนำทาง

ค้นหาในวิกิ...