จัดทำขึ้นเพื่อการศึกษาเท่านั้น ไม่ใช่คำแนะนำการลงทุน การลงทุนอาจทำให้สูญเสียเงินลงทุนได้
คำตอบโดยตรง
ภาวะแข่งขันในการอนุมัติ ERC-20 อาจเกิดขึ้นเมื่อเจ้าของเรียก approve(spender, newAmount) เพื่อแทนที่วงเงินที่ไม่ใช่ศูนย์ด้วยวงเงินอื่นที่ไม่ใช่ศูนย์ ผู้รับอนุญาตอาจเห็นการเปลี่ยนแปลงที่รอดำเนินการ ใช้วงเงินเดิมก่อนด้วย transferFrom แล้วใช้วงเงินทดแทนหลังจากได้รับการยืนยัน
ดังนั้น ข้อกำหนด ERC-20 จึงแนะนำให้อินเทอร์เฟซฝั่งไคลเอนต์ตั้งวงเงินเป็น 0 ก่อนกำหนดค่าใหม่ให้ผู้รับอนุญาตรายเดิม ธุรกรรมแต่ละรายการต้องได้รับการยืนยันตามลำดับ หากโทเค็นรองรับ การเรียก increaseAllowance หรือ decreaseAllowance แบบอะตอมมิกจะช่วยหลีกเลี่ยงการแทนที่วงเงินที่ไม่ใช่ศูนย์โดยตรง
การเสร็จสิ้นการตรวจสอบนี้ไม่ได้พิสูจน์ว่าสินทรัพย์ ธุรกรรม หรือระบบมีความปลอดภัย
วิธีการทำงาน
ERC-20 กำหนดให้ approve เป็นการเขียนทับ กล่าวคือ approve(spender, amount) ที่สำเร็จจะตั้งวงเงินของผู้รับอนุญาตเป็น amount ส่วน transferFrom(owner, recipient, amount) เปิดให้ผู้รับอนุญาตรายนั้นโอนโทเค็นของเจ้าของ และโดยทั่วไปจะลดวงเงินที่เหลือ ธุรกรรมที่รอดำเนินการไม่ได้จองลำดับการดำเนินการไว้ ผู้รับอนุญาตจึงอาจส่งคำสั่งโอนที่ดำเนินการก่อนการเปลี่ยนแปลงการอนุมัติของเจ้าของได้
การเปลี่ยนผ่านที่มีความเสี่ยงคือ N -> M โดยที่ทั้ง N > 0 และ M > 0 หากผู้รับอนุญาตใช้ N หมดก่อนการอนุมัติทดแทนจะดำเนินการ การอนุมัติที่ตามมาจะกำหนดวงเงินใหม่เป็น M ดังนั้น ยอดใช้จ่ายสูงสุดตลอดลำดับนี้อาจเป็น N + M โดยขึ้นอยู่กับยอดคงเหลือโทเค็นของเจ้าของและการทำงานของโทเค็น
ตัวอย่าง
Alice อนุมัติให้โปรโตคอลใช้โทเค็น 100 หน่วย เธอส่ง approve(protocol, 50) โดยตั้งใจลดวงเงินคงเหลือเป็น 50 ก่อนที่ธุรกรรมนั้นจะได้รับการยืนยัน ผู้รับอนุญาตของโปรโตคอลส่ง transferFrom(Alice, recipient, 100) และทำให้รายการนี้ดำเนินการก่อน จากนั้นการอนุมัติของ Alice จะตั้งวงเงินเป็น 50 ซึ่งผู้รับอนุญาตสามารถใช้ในการโอนอีกครั้งได้ การโอนทั้งสองครั้งรวมเป็นโทเค็น 150 หน่วย
ขั้นตอนทดแทนที่ปลอดภัยกว่าคือส่ง approve(protocol, 0) รอการยืนยัน ตรวจสอบวงเงินและยอดคงเหลือที่ได้ แล้วจึงส่ง approve(protocol, 50) เฉพาะเมื่อการอนุมัติใหม่ยังเหมาะสมอยู่ หากผู้รับอนุญาตใช้วงเงินเดิมก่อนที่ธุรกรรมตั้งวงเงินเป็นศูนย์จะได้รับการยืนยัน Alice จะเห็นยอดคงเหลือที่เปลี่ยนไปและหยุดได้ก่อนอนุมัติวงเงินใหม่ 50
ความเสี่ยง
- การตั้งวงเงินเป็น
0ไม่ได้เพิกถอนการใช้จ่ายที่ดำเนินการไปแล้ว และไม่สามารถป้องกันการใช้วงเงินเดิมก่อนที่ธุรกรรมตั้งวงเงินเป็นศูนย์จะได้รับการยืนยัน - การส่งคำสั่งอนุมัติเพื่อตั้งวงเงินเป็นศูนย์และคำสั่งอนุมัติทดแทนพร้อมกันโดยไม่รอการยืนยันรายการแรก จะทำให้ความเสี่ยงด้านลำดับกลับมาอีกครั้ง
increaseAllowanceและdecreaseAllowanceไม่ได้เป็นส่วนหนึ่งของมาตรฐาน ERC-20 พื้นฐาน ให้ใช้เฉพาะเมื่อสัญญาโทเค็นที่ตรวจสอบแล้วรองรับ- วงเงินแบบไม่จำกัดอาจทำให้ยอดคงเหลือโทเค็นทั้งหมดของเจ้าของมีความเสี่ยงตราบใดที่ยังเปิดใช้งานอยู่ ตรวจสอบเชน สัญญาโทเค็น ผู้รับอนุญาต และจำนวนเงินก่อนลงนาม
- โทเค็นบางรายการมีพฤติกรรมการอนุมัติที่ไม่เป็นมาตรฐาน อ่านผลจำลองของกระเป๋าเงินและ calldata ของธุรกรรม แล้วตรวจสอบวงเงินบนเชนหลังจากแต่ละขั้นตอน
ความเข้าใจผิดที่พบบ่อย
- “ธุรกรรมอนุมัติล่าสุดจะแทนที่รายการเดิมทันที” สถานะจะเปลี่ยนก็ต่อเมื่อธุรกรรมนั้นดำเนินการบนเชนแล้ว
- “การลดวงเงินจะจำกัดยอดใช้จ่ายทั้งหมดในอนาคตไว้ที่จำนวนใหม่” ผู้รับอนุญาตอาจใช้วงเงินเดิมก่อนที่การเปลี่ยนแปลงจะดำเนินการ
- “การตั้งเป็นศูนย์ก่อนรับประกันว่าจะไม่มีโทเค็นออกไปอีก” วงเงินเดิมยังใช้ได้จนกว่าธุรกรรมตั้งวงเงินเป็นศูนย์จะได้รับการยืนยัน
- “ERC-20 ทุกตัวมี
increaseAllowanceและdecreaseAllowance” ทั้งสองอย่างเป็นส่วนขยายทางเลือก ไม่ใช่ข้อกำหนดของ ERC-20 - “การยกเลิกการเชื่อมต่อเว็บไซต์จะเพิกถอนการอนุมัติโทเค็น” สถานะการเชื่อมต่อกระเป๋าเงินและวงเงินบนเชนในสัญญาโทเค็นเป็นคนละส่วนกัน
หัวข้อที่เกี่ยวข้อง
- วิธีแยกโทเค็นมาตรฐานออกจากโทเค็นแบบ wrapped
- Mempool
- ความเสี่ยงจากลายเซ็น Permit2
- คำสั่งแบบ Reduce-only
- การอนุมัติของกระเป๋าเงิน
แหล่งที่มา
- ERC-20: Token Standard - Ethereum Improvement Proposals (เข้าถึงเมื่อ: 2026-08-20)
- ERC20 | OpenZeppelin Docs - OpenZeppelin (เข้าถึงเมื่อ: 2026-08-20)