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

เหตุใดการอนุมัติโทเค็นบางชนิดจึงต้องปรับเป็นศูนย์ก่อน

โทเค็น ERC-20 บางชนิดปฏิเสธการเปลี่ยน allowance ที่ไม่ใช่ศูนย์ไปเป็นค่าอื่นที่ไม่ใช่ศูนย์โดยตรง บทความนี้อธิบายว่าเมื่อใดต้องปรับเป็นศูนย์ก่อน เหตุใดธุรกรรมทั้งสองจึงต้องยืนยันตามลำดับ และยังมีความเสี่ยงใดเหลืออยู่

อัปเดต

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

คำตอบโดยตรง

การใช้งาน ERC-20 บางแบบจะปฏิเสธ approve(spender, newAmount) เมื่อ allowance เดิมและ newAmount ต่างก็ไม่ใช่ศูนย์ สำหรับโทเค็นเหล่านี้ ให้ส่ง approve(spender, 0) ก่อน รอให้ยืนยัน แล้วจึงส่งการอนุมัติใหม่ที่ไม่ใช่ศูนย์

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

เหตุใดการอนุมัติโทเค็นบางชนิดจึงต้องปรับเป็นศูนย์ก่อน
0 / 5
0 ตรวจสอบรายการแล้ว; 5 รายการยังไม่ได้รับการแก้ไข

การเสร็จสิ้นการตรวจสอบนี้ไม่ได้พิสูจน์ว่าสินทรัพย์ ธุรกรรม หรือระบบมีความปลอดภัย

กลไกการทำงาน

  1. ตรวจสอบเชน สัญญาโทเค็น เจ้าของ spender และจำนวนที่ตั้งใจไว้ อ่าน allowance(owner, spender) จากสัญญาโทเค็นโดยตรง แทนที่จะเชื่อเพียงป้ายชื่อในกระเป๋าสินทรัพย์ดิจิทัล
  2. หาก allowance เป็น 0 อยู่แล้ว ให้ส่งการอนุมัติที่ต้องการเพียงครั้งเดียว หากไม่ใช่ศูนย์ การแทนที่โดยตรงด้วยค่าอื่นที่ไม่ใช่ศูนย์อาจสำเร็จในสัญญามาตรฐาน หรือ revert ในโทเค็นที่กำหนดให้ปรับเป็นศูนย์ก่อน
  3. สำหรับขั้นตอนนี้ ให้ส่ง approve(spender, 0) และรอ receipt ที่สำเร็จ จากนั้นอ่าน allowance ของคู่เจ้าของ-spender เดิมอีกครั้งและยืนยันว่าเป็น 0
  4. ตรวจสอบยอดคงเหลือของโทเค็น spender และวัตถุประสงค์อีกครั้ง จากนั้นจึงส่ง approve(spender, newAmount) และรอการยืนยันก่อนถือว่า allowance ใหม่มีผล
  5. ตรวจสอบ allowance สุดท้าย รวมทั้งเหตุการณ์ Transfer และ Approval ที่เกิดขึ้นระหว่างทาง receipt ที่สำเร็จพิสูจน์ว่ามีการดำเนินการ ส่วนสถานะปัจจุบันของสัญญาแสดงสิทธิ์ที่ยังเหลืออยู่

SafeERC20.forceApprove ของ OpenZeppelin เป็นทางเลือกสำรองด้านความเข้ากันได้สำหรับสัญญา โดยลองค่าที่ต้องการก่อน และถ้าการเรียกล้มเหลว จะลอง 0 ตามด้วยค่าที่ต้องการ ฟังก์ชันช่วยนี้เปลี่ยน allowance ของสัญญาที่เป็นผู้เรียกเอง ไม่ได้แก้การอนุมัติในกระเป๋าของผู้ใช้โดยอัตโนมัติ และไม่ได้ทำให้ไม่ต้องตรวจสอบลำดับธุรกรรมกับสถานะสุดท้าย

ตัวอย่าง

เจ้าของให้ allowance แก่ spender จำนวน 1000 โทเค็นและต้องการลดเป็น 100 สำหรับโทเค็นที่กำหนดให้ปรับเป็นศูนย์ก่อน การเรียก approve(spender, 100) จะ revert ดังนั้น allowance บนเชนยังคงเป็น 1000 การเรียกที่ revert จะไม่อัปเดตสถานะเพียงบางส่วน

เจ้าของจึงส่ง approve(spender, 0) แทน ก่อนธุรกรรมจะยืนยัน spender ใช้ไป 400 ทำให้เหลือ 600 จากนั้นธุรกรรมปรับเป็นศูนย์ที่ยืนยันแล้วจะแทนที่ส่วนที่เหลือด้วย 0 หลังตรวจสอบยอดโทเค็นที่ลดลง เจ้าของจึงตัดสินใจได้ว่าจะให้ allowance ใหม่ 100 หรือไม่ หากให้ spender ได้ใช้ไปแล้ว 400 และภายหลังยังใช้ได้อีกไม่เกิน 100 การปรับเป็นศูนย์ก่อนทำให้เห็นการใช้จ่ายระหว่างทางก่อนให้สิทธิ์ใหม่ แต่ไม่ได้ย้อนคืนการใช้จ่ายนั้น

ความเสี่ยง

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

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

  • ERC-20 ทุกชนิดต้องปรับเป็นศูนย์ก่อน มาตรฐานแนะนำลำดับนี้ในฝั่งไคลเอนต์ แต่ระบุว่าสัญญาโทเค็นไม่ควรบังคับ มีเพียงบางการใช้งานที่ปฏิเสธการเปลี่ยนระหว่างสองค่าที่ไม่ใช่ศูนย์
  • การปรับเป็นศูนย์ก่อนแก้การแข่งขันด้านการอนุมัติได้ทั้งหมด spender ยังใช้ allowance เดิมได้ก่อนธุรกรรมปรับเป็นศูนย์จะยืนยัน
  • การแทนที่ที่ revert ล้าง allowance เดิมแล้ว revert จะย้อนการเปลี่ยนสถานะที่พยายามทำ ดังนั้น allowance ก่อนหน้าจึงมักยังอยู่
  • ส่งสองธุรกรรมพร้อมกันเท่ากับรอการยืนยัน จุดตรวจสอบด้านความปลอดภัยเกิดจากการยืนยันและตรวจสถานะศูนย์ก่อนตัดสินใจส่งค่าทดแทน
  • ตัดการเชื่อมต่อเว็บไซต์แล้วการอนุมัติจะถูกเพิกถอน สถานะการเชื่อมต่อกระเป๋าและ allowance บนเชนในสัญญาโทเค็นเป็นคนละส่วนกัน

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

แหล่งข้อมูล

การนำทาง

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