นับตั้งแต่การประกาศ UniswapV4 แพลตฟอร์ม Swap นี้ได้รับการเปลี่ยนแปลงครั้งสำคัญ โดยพัฒนาจากแพลตฟอร์ม Swap ธรรมดาไปสู่ผู้ให้บริการโครงสร้างพื้นฐาน โดยเฉพาะอย่างยิ่งฟีเจอร์ Hooks ของ V4 ได้รับความสนใจอย่างกว้างขวาง หลังจากการวิจัยเชิงลึกแล้ว ฉันได้รวบรวมเนื้อหาบางส่วนเพื่อช่วยให้ทุกคนเข้าใจการเปลี่ยนแปลงนี้และการนำไปปฏิบัติได้ดีขึ้น
จุดเน้นของนวัตกรรมของ UniswapV4 ไม่ใช่แค่การปรับปรุงเทคโนโลยี AMM แต่ยังรวมถึงการขยายระบบนิเวศด้วย โดยเฉพาะนวัตกรรมนี้มีคุณสมบัติที่สำคัญดังต่อไปนี้:
ในส่วนต่อไปนี้ ผมจะอธิบายโดยละเอียดเกี่ยวกับความสำคัญของคุณลักษณะเหล่านี้และหลักการนำไปใช้งาน
ที่มา: https://twitter.com/jermywkh/status/1670779830621851650
UniswapV4 ใช้วิธีการจัดเก็บบันทึกที่คล้ายกับ Double Entry Bookkeeping เพื่อติดตามการเปลี่ยนแปลงยอดคงเหลือของโทเค็นที่สอดคล้องกับการดำเนินการแต่ละรายการ วิธีการทำบัญชีแบบ Double Entry นี้จำเป็นต้องบันทึกแต่ละธุรกรรมในหลายบัญชีพร้อมกัน และทำให้มั่นใจว่ายอดคงเหลือของสินทรัพย์ระหว่างบัญชีเหล่านี้ยังคงมีความสมดุล ตัวอย่างเช่น สมมติว่าผู้ใช้แลกเปลี่ยน 100 TokenA เป็น 50 TokenB จากพูล บันทึกในบัญชีแยกประเภทจะเป็นดังนี้:
ใน UniswapV4 วิธีการเก็บบันทึกนี้ใช้สำหรับการดำเนินการหลักเป็นหลัก และตัวแปรหน่วยเก็บข้อมูลชื่อ lockState.currencyDelta[currency] ใช้ในโค้ดเพื่อบันทึกจำนวนการเปลี่ยนแปลงยอดโทเค็น หากค่าของเดลต้านี้เป็นค่าบวก จะแสดงถึงการเพิ่มขึ้นของจำนวนโทเค็นในกลุ่มที่คาดหวัง ในขณะที่ค่าลบแสดงถึงการลดลงที่คาดไว้ของจำนวนโทเค็น อีกทางหนึ่ง หากค่าเป็นบวก จะระบุจำนวนโทเค็นที่ขาดแคลนในกลุ่ม (จำนวนที่คาดว่าจะได้รับ) ในขณะที่ค่าลบจะระบุถึงโทเค็นส่วนเกินในกลุ่ม (จำนวนที่คาดหวังสำหรับผู้ใช้ที่จะถอนออก) รายการต่อไปนี้แสดงให้เห็นถึงผลกระทบของการดำเนินการต่างๆ บน Token Delta:
ในบรรดาการดำเนินการเหล่านี้ มีเพียง "ชำระ" และ "รับ" เท่านั้นที่เกี่ยวข้องกับการโอนโทเค็นจริง ในขณะที่การดำเนินการอื่นๆ มีหน้าที่รับผิดชอบในการอัปเดตค่า TokenDelta แต่เพียงผู้เดียว
ที่นี่เราใช้ตัวอย่างง่ายๆ เพื่อแสดงวิธีอัปเดต TokenDelta สมมติว่าวันนี้เราแลกเปลี่ยน 100 TokenA เป็น 50 TokenB:
เมื่อการดำเนินการแลกเปลี่ยนทั้งหมดเสร็จสิ้น ทั้ง TokenADelta และ TokenBDelta จะถูกรีเซ็ตเป็น 0 ซึ่งหมายความว่าการดำเนินการมีความสมดุลอย่างสมบูรณ์ ดังนั้นจึงรับประกันความสอดคล้องของยอดคงเหลือในบัญชี
ก่อนหน้านี้มีการกล่าวถึงว่า UniswapV4 ใช้ตัวแปรการจัดเก็บข้อมูลเพื่อบันทึก TokenDelta อย่างไรก็ตาม ภายในสัญญา การอ่านและการเขียนตัวแปรการจัดเก็บข้อมูลมีราคาค่อนข้างแพง สิ่งนี้นำเราไปสู่ EIP อื่นที่ Uniswap นำเสนอ: EIP1153 - Transient Storage Opcodes
UniswapV4 วางแผนที่จะใช้ opcode ของ TSTORE และ TLOAD ที่ได้รับจาก EIP1153 เพื่ออัปเดต TokenDelta ตัวแปรการจัดเก็บข้อมูลที่ใช้ Opcodes การจัดเก็บข้อมูลชั่วคราวจะถูกละทิ้งหลังจากสิ้นสุดธุรกรรม (คล้ายกับตัวแปรหน่วยความจำ) ซึ่งจะช่วยลดค่าธรรมเนียมก๊าซ
EIP1153 ได้รับการยืนยันว่าจะรวมไว้ใน การอัปเกรด Cancun ที่กำลังจะมาถึง และ UniswapV4 ยังระบุด้วยว่าจะใช้งานได้หลังจากการอัปเกรด Cancun ตามที่รายงานไว้ ที่นี่
ที่มา: https://etherworld.co/2022/12/13/transient-storage-for-beginners/
UniswapV4 แนะนำกลไกการล็อค ซึ่งหมายความว่าก่อนดำเนินการกับพูล คุณต้องเรียก PoolManager.lock() ก่อนเพื่อรับการล็อค ในระหว่างการดำเนินการ lock() จะตรวจสอบว่าค่า TokenDelta เป็น 0 หรือไม่ ไม่เช่นนั้นจะกลับมา เมื่อได้รับ PoolManager.lock() สำเร็จแล้ว จะเรียกใช้ฟังก์ชัน lockAcquired() ของ msg.sender ภายในฟังก์ชัน lockAcquired() จะดำเนินการที่เกี่ยวข้องกับพูล เช่น swap และ modifiedPosition
กระบวนการนี้แสดงไว้ด้านล่าง เมื่อผู้ใช้จำเป็นต้องดำเนินการ Token Swap พวกเขาจะต้องเรียก Smart Contract ด้วยฟังก์ชัน lockAcquired() (เรียกว่า Callback Contract) สัญญาการโทรกลับจะเรียก PoolManager.lock() ก่อน จากนั้น PoolManager จะเรียกใช้ฟังก์ชัน lockAcquired() ของสัญญาการโทรกลับ ภายในฟังก์ชัน lockAcquired() มีการกำหนดตรรกะที่เกี่ยวข้องกับการดำเนินงานของพูล เช่น การสลับ ชำระ และการรับ ในที่สุด เมื่อ lock() กำลังจะสิ้นสุด PoolManager จะตรวจสอบว่า TokenDelta ที่เกี่ยวข้องกับการดำเนินการนี้ถูกรีเซ็ตเป็น 0 หรือไม่ เพื่อให้มั่นใจว่ายอดคงเหลือของสินทรัพย์ใน Pool ยังคงไม่เสียหาย
Singleton Contract หมายความว่า UniswapV4 ได้ละทิ้งโมเดล Factory-Pool ก่อนหน้านี้แล้ว แต่ละพูลไม่ใช่สัญญาอัจฉริยะที่เป็นอิสระอีกต่อไป แต่พูลทั้งหมดใช้สัญญาแบบซิงเกิลตันร่วมกัน การออกแบบนี้เมื่อรวมกับกลไก Flash Accounting จำเป็นต้องมีการอัปเดตตัวแปรการจัดเก็บข้อมูลที่จำเป็นเท่านั้น ซึ่งช่วยลดความซับซ้อนและต้นทุนในการดำเนินงานอีกด้วย
ในตัวอย่างด้านล่าง การใช้ UniswapV3 เป็นตัวอย่าง การแลกเปลี่ยน ETH สำหรับ DAI จะต้องมีการถ่ายโอนโทเค็นอย่างน้อยสี่ครั้ง (การดำเนินการเขียนการจัดเก็บ) ซึ่งรวมถึงการเปลี่ยนแปลงหลายอย่างที่บันทึกไว้สำหรับโทเค็น USDC, USDT และ DAI อย่างไรก็ตาม ด้วยการปรับปรุงใน UniswapV4 ประกอบกับกลไก Flash Accounting จำเป็นต้องมีการโอน Token เพียงครั้งเดียวเท่านั้น (การย้าย DAI จากพูลไปยังผู้ใช้) ช่วยลดจำนวนการดำเนินงานและต้นทุนได้อย่างมาก
ที่มา: https://twitter.com/Uniswap/status/1671208668304486404
ในการอัปเดตล่าสุดของ UniswapV4 คุณสมบัติที่โดดเด่นที่สุดคือสถาปัตยกรรม Hooks การอัปเดตนี้นำมาซึ่งความยืดหยุ่นอย่างมากในแง่ของความพร้อมใช้งานของพูล Hooks คือการดำเนินการเพิ่มเติมที่ทริกเกอร์ผ่านสัญญา Hooks เมื่อดำเนินการเฉพาะเจาะจงในพูล การดำเนินการเหล่านี้แบ่งออกเป็นการเริ่มต้น (สร้างพูล) แก้ไขตำแหน่ง (เพิ่ม/ลบสภาพคล่อง) สลับ และบริจาค แต่ละหมวดหมู่มีการดำเนินการก่อนดำเนินการและหลังการดำเนินการ
การออกแบบนี้ช่วยให้ผู้ใช้ดำเนินการตรรกะที่กำหนดเองก่อนและหลังการดำเนินการเฉพาะ ทำให้มีความยืดหยุ่นมากขึ้นและขยายฟังก์ชันการทำงานของ UniswapV4
ที่มา: https://github.com/Uniswap/v4-core/blob/main/whitepaper-v4-draft.pdf
ต่อไป เราจะใช้ตัวอย่างของ Limit Order เพื่ออธิบายกระบวนการทำงานจริงของ Hooks ใน UniswapV4 ก่อนที่เราจะเริ่มต้น เรามาอธิบายสั้นๆ เกี่ยวกับหลักการของการใช้ Limit Order ใน UniswapV4 กันก่อน
การใช้คำสั่งจำกัดของ UniswapV4 ทำงานโดยการเพิ่มสภาพคล่องให้กับช่วงราคาที่ระบุ จากนั้นดำเนินการลบสภาพคล่องออก หากมีการสลับสภาพคล่องในช่วงนั้น
ตัวอย่างเช่น สมมติว่าเราเพิ่มสภาพคล่องในช่วงราคา 1900-2000 สำหรับ ETH จากนั้นราคาของ ETH ก็เพิ่มขึ้นจาก 1800 เป็น 2100 ณ จุดนี้ สภาพคล่อง ETH ทั้งหมดที่เราเพิ่มไว้ก่อนหน้านี้ในช่วงราคาปี 1900-2000 ได้ถูกสลับเป็น USDC (สมมติว่าอยู่ในกลุ่ม ETH-USDC) ด้วยการลบสภาพคล่องในขณะนี้ เราสามารถบรรลุผลที่คล้ายกันในการดำเนินการคำสั่งตลาด ETH ที่ช่วงราคาปัจจุบันที่ 1900-2000
ตัวอย่างนี้นำมาจาก GitHub ของ UniswapV4 ในตัวอย่างนี้ สัญญา Limit Order Hook จะมี hook สองอัน คือ afterInitialize และ afterSwap ตะขอ afterInitialize ใช้เพื่อบันทึกช่วงราคา (ทำเครื่องหมาย) เมื่อสร้างพูล เพื่อพิจารณาว่าคำสั่งจำกัดใดที่ได้รับการจับคู่หลังจากมีคนสลับ
เมื่อผู้ใช้ต้องการสั่งซื้อ สัญญา Hook จะดำเนินการดำเนินการเพิ่มสภาพคล่องตามช่วงราคาและปริมาณที่ผู้ใช้ระบุ ในสัญญา Hook สำหรับคำสั่งจำกัด คุณสามารถดูฟังก์ชัน place() ได้ ตรรกะหลักคือการเรียกใช้ฟังก์ชัน lockAcquiredPlace() หลังจากได้รับการล็อคเพื่อดำเนินการดำเนินการเพิ่มสภาพคล่อง ซึ่งเทียบเท่ากับการวางคำสั่งจำกัด
ที่มา: https://github.com/Uniswap/v4-periphery/blob/main/contracts/hooks/examples/LimitOrder.sol#L246
หลังจากที่ผู้ใช้สร้าง Swap Token ภายในพูลนี้เสร็จแล้ว พูลจะเรียกใช้ฟังก์ชัน afterSwap() ของสัญญา Hook ตรรกะหลักของ afterSwap คือการลบสภาพคล่องของคำสั่งซื้อที่วางไว้ก่อนหน้านี้ซึ่งได้รับการดำเนินการระหว่างช่วงราคาก่อนหน้าและช่วงราคาปัจจุบัน ลักษณะการทำงานนี้เทียบเท่ากับใบสั่งที่ถูกเติม
ที่มา: https://github.com/Uniswap/v4-periphery/blob/main/contracts/hooks/examples/LimitOrder.sol#L192
นี่คือผังงานที่แสดงกระบวนการดำเนินการคำสั่งจำกัด:
ข้างต้นเป็นกระบวนการทั้งหมดของการนำ Limit-Order ไปใช้โดยใช้กลไก Hook
Hooks มีประเด็นที่น่าสนใจหลายประการที่ฉันพบว่าคุ้มค่าที่จะแบ่งปัน
การตัดสินใจดำเนินการเฉพาะก่อน/หลังถูกกำหนดโดยที่อยู่สัญญา Hook ขนาด 1 ไบต์ซ้ายสุด 1 ไบต์เท่ากับ 8 บิต ซึ่งสอดคล้องกับการดำเนินการเพิ่มเติม 8 รายการ พูลจะตรวจสอบว่าบิตของการกระทำนั้นเป็น 1 หรือไม่ เพื่อพิจารณาว่าจะเรียกใช้ฟังก์ชัน hook ที่สอดคล้องกันของสัญญา Hook หรือไม่ นอกจากนี้ยังหมายความว่าที่อยู่ของสัญญา Hook จำเป็นต้องได้รับการออกแบบในลักษณะเฉพาะและไม่สามารถเลือกโดยพลการเป็นสัญญา Hook การออกแบบนี้มีวัตถุประสงค์หลักเพื่อลดการใช้ก๊าซและเปลี่ยนต้นทุนไปเป็นการใช้งานตามสัญญาเพื่อให้การดำเนินงานมีประสิทธิภาพมากขึ้น (ปล.: ในทางปฏิบัติ สามารถใช้เกลือ CREATE2 ที่แตกต่างกันเพื่อคำนวณที่อยู่ของสัญญาที่ตรงตามเงื่อนไข)
นอกเหนือจากความสามารถในการดำเนินการเพิ่มเติมก่อนและหลังแต่ละการกระทำแล้ว Hooks ยังสนับสนุนการดำเนินการค่าธรรมเนียมแบบไดนามิกอีกด้วย เมื่อสร้างพูล คุณสามารถระบุว่าจะเปิดใช้งานค่าธรรมเนียมแบบไดนามิกหรือไม่ หากเปิดใช้งานค่าธรรมเนียมแบบไดนามิก ฟังก์ชัน getFee() ของสัญญา Hook จะถูกเรียกเมื่อทำการสลับโทเค็น สัญญา Hook สามารถกำหนดจำนวนค่าธรรมเนียมที่จะเรียกเก็บตามสถานะปัจจุบันของพูล การออกแบบนี้ช่วยให้สามารถคำนวณค่าธรรมเนียมได้อย่างยืดหยุ่นตามสถานการณ์จริง ซึ่งเป็นการเพิ่มความยืดหยุ่นของระบบ
แต่ละพูลจำเป็นต้องกำหนดสัญญา Hook ในระหว่างการสร้าง และไม่สามารถเปลี่ยนแปลงได้ในภายหลัง (แม้ว่าพูลที่แตกต่างกันสามารถใช้สัญญา Hook เดียวกันได้) สาเหตุหลักมาจาก Hooks ถือว่าเป็นส่วนหนึ่งของ PoolKey และ PoolManager ใช้ PoolKey เพื่อระบุว่าพูลใดที่จะใช้งาน แม้ว่าสินทรัพย์จะเหมือนกัน แต่หากสัญญา Hook แตกต่างกันก็จะถือเป็นพูลอื่น การออกแบบนี้ช่วยให้แน่ใจว่าสถานะและการดำเนินงานของพูลต่างๆ สามารถจัดการได้อย่างอิสระ เพื่อให้มั่นใจถึงความสอดคล้องของพูล อย่างไรก็ตาม มันยังเพิ่มความซับซ้อนของการกำหนดเส้นทางเมื่อจำนวนพูลเพิ่มขึ้น (บางที UniswapX อาจได้รับการออกแบบมาเพื่อแก้ไขปัญหานี้)
UniswapV4 เน้นย้ำอย่างชัดเจนถึงการขยายระบบนิเวศ Uniswap ทั้งหมด โดยเปลี่ยนให้เป็นโครงสร้างพื้นฐานเพื่อให้สามารถให้บริการต่างๆ ได้มากขึ้นบนรากฐานของ Uniswap Pools สิ่งนี้ช่วยเพิ่มขีดความสามารถในการแข่งขันของ Uniswap และลดความเสี่ยงของบริการทางเลือก อย่างไรก็ตาม จะต้องดูกันต่อไปว่าจะบรรลุผลสำเร็จตามที่คาดหวังหรือไม่ จุดเด่นบางประการ ได้แก่ การผสมผสานระหว่าง Flash Accounting และ EIP1153 และเราเชื่อว่าบริการต่างๆ จะนำคุณลักษณะเหล่านี้ไปใช้ในอนาคต ซึ่งนำไปสู่สถานการณ์การใช้งานที่หลากหลาย นี่คือแนวคิดหลักของ UniswapV4 และเราหวังว่าจะให้ความเข้าใจที่ลึกซึ้งยิ่งขึ้นเกี่ยวกับวิธีการทำงานของ UniswapV4 หากมีข้อผิดพลาดในบทความโปรดชี้ให้เห็น เรายังยินดีรับการอภิปรายและข้อเสนอแนะ
สุดท้ายนี้ เราขอขอบคุณ Anton Cheng และ Ping Chen สำหรับการรีวิวบทความและให้ข้อเสนอแนะอันมีค่า!
นับตั้งแต่การประกาศ UniswapV4 แพลตฟอร์ม Swap นี้ได้รับการเปลี่ยนแปลงครั้งสำคัญ โดยพัฒนาจากแพลตฟอร์ม Swap ธรรมดาไปสู่ผู้ให้บริการโครงสร้างพื้นฐาน โดยเฉพาะอย่างยิ่งฟีเจอร์ Hooks ของ V4 ได้รับความสนใจอย่างกว้างขวาง หลังจากการวิจัยเชิงลึกแล้ว ฉันได้รวบรวมเนื้อหาบางส่วนเพื่อช่วยให้ทุกคนเข้าใจการเปลี่ยนแปลงนี้และการนำไปปฏิบัติได้ดีขึ้น
จุดเน้นของนวัตกรรมของ UniswapV4 ไม่ใช่แค่การปรับปรุงเทคโนโลยี AMM แต่ยังรวมถึงการขยายระบบนิเวศด้วย โดยเฉพาะนวัตกรรมนี้มีคุณสมบัติที่สำคัญดังต่อไปนี้:
ในส่วนต่อไปนี้ ผมจะอธิบายโดยละเอียดเกี่ยวกับความสำคัญของคุณลักษณะเหล่านี้และหลักการนำไปใช้งาน
ที่มา: https://twitter.com/jermywkh/status/1670779830621851650
UniswapV4 ใช้วิธีการจัดเก็บบันทึกที่คล้ายกับ Double Entry Bookkeeping เพื่อติดตามการเปลี่ยนแปลงยอดคงเหลือของโทเค็นที่สอดคล้องกับการดำเนินการแต่ละรายการ วิธีการทำบัญชีแบบ Double Entry นี้จำเป็นต้องบันทึกแต่ละธุรกรรมในหลายบัญชีพร้อมกัน และทำให้มั่นใจว่ายอดคงเหลือของสินทรัพย์ระหว่างบัญชีเหล่านี้ยังคงมีความสมดุล ตัวอย่างเช่น สมมติว่าผู้ใช้แลกเปลี่ยน 100 TokenA เป็น 50 TokenB จากพูล บันทึกในบัญชีแยกประเภทจะเป็นดังนี้:
ใน UniswapV4 วิธีการเก็บบันทึกนี้ใช้สำหรับการดำเนินการหลักเป็นหลัก และตัวแปรหน่วยเก็บข้อมูลชื่อ lockState.currencyDelta[currency] ใช้ในโค้ดเพื่อบันทึกจำนวนการเปลี่ยนแปลงยอดโทเค็น หากค่าของเดลต้านี้เป็นค่าบวก จะแสดงถึงการเพิ่มขึ้นของจำนวนโทเค็นในกลุ่มที่คาดหวัง ในขณะที่ค่าลบแสดงถึงการลดลงที่คาดไว้ของจำนวนโทเค็น อีกทางหนึ่ง หากค่าเป็นบวก จะระบุจำนวนโทเค็นที่ขาดแคลนในกลุ่ม (จำนวนที่คาดว่าจะได้รับ) ในขณะที่ค่าลบจะระบุถึงโทเค็นส่วนเกินในกลุ่ม (จำนวนที่คาดหวังสำหรับผู้ใช้ที่จะถอนออก) รายการต่อไปนี้แสดงให้เห็นถึงผลกระทบของการดำเนินการต่างๆ บน Token Delta:
ในบรรดาการดำเนินการเหล่านี้ มีเพียง "ชำระ" และ "รับ" เท่านั้นที่เกี่ยวข้องกับการโอนโทเค็นจริง ในขณะที่การดำเนินการอื่นๆ มีหน้าที่รับผิดชอบในการอัปเดตค่า TokenDelta แต่เพียงผู้เดียว
ที่นี่เราใช้ตัวอย่างง่ายๆ เพื่อแสดงวิธีอัปเดต TokenDelta สมมติว่าวันนี้เราแลกเปลี่ยน 100 TokenA เป็น 50 TokenB:
เมื่อการดำเนินการแลกเปลี่ยนทั้งหมดเสร็จสิ้น ทั้ง TokenADelta และ TokenBDelta จะถูกรีเซ็ตเป็น 0 ซึ่งหมายความว่าการดำเนินการมีความสมดุลอย่างสมบูรณ์ ดังนั้นจึงรับประกันความสอดคล้องของยอดคงเหลือในบัญชี
ก่อนหน้านี้มีการกล่าวถึงว่า UniswapV4 ใช้ตัวแปรการจัดเก็บข้อมูลเพื่อบันทึก TokenDelta อย่างไรก็ตาม ภายในสัญญา การอ่านและการเขียนตัวแปรการจัดเก็บข้อมูลมีราคาค่อนข้างแพง สิ่งนี้นำเราไปสู่ EIP อื่นที่ Uniswap นำเสนอ: EIP1153 - Transient Storage Opcodes
UniswapV4 วางแผนที่จะใช้ opcode ของ TSTORE และ TLOAD ที่ได้รับจาก EIP1153 เพื่ออัปเดต TokenDelta ตัวแปรการจัดเก็บข้อมูลที่ใช้ Opcodes การจัดเก็บข้อมูลชั่วคราวจะถูกละทิ้งหลังจากสิ้นสุดธุรกรรม (คล้ายกับตัวแปรหน่วยความจำ) ซึ่งจะช่วยลดค่าธรรมเนียมก๊าซ
EIP1153 ได้รับการยืนยันว่าจะรวมไว้ใน การอัปเกรด Cancun ที่กำลังจะมาถึง และ UniswapV4 ยังระบุด้วยว่าจะใช้งานได้หลังจากการอัปเกรด Cancun ตามที่รายงานไว้ ที่นี่
ที่มา: https://etherworld.co/2022/12/13/transient-storage-for-beginners/
UniswapV4 แนะนำกลไกการล็อค ซึ่งหมายความว่าก่อนดำเนินการกับพูล คุณต้องเรียก PoolManager.lock() ก่อนเพื่อรับการล็อค ในระหว่างการดำเนินการ lock() จะตรวจสอบว่าค่า TokenDelta เป็น 0 หรือไม่ ไม่เช่นนั้นจะกลับมา เมื่อได้รับ PoolManager.lock() สำเร็จแล้ว จะเรียกใช้ฟังก์ชัน lockAcquired() ของ msg.sender ภายในฟังก์ชัน lockAcquired() จะดำเนินการที่เกี่ยวข้องกับพูล เช่น swap และ modifiedPosition
กระบวนการนี้แสดงไว้ด้านล่าง เมื่อผู้ใช้จำเป็นต้องดำเนินการ Token Swap พวกเขาจะต้องเรียก Smart Contract ด้วยฟังก์ชัน lockAcquired() (เรียกว่า Callback Contract) สัญญาการโทรกลับจะเรียก PoolManager.lock() ก่อน จากนั้น PoolManager จะเรียกใช้ฟังก์ชัน lockAcquired() ของสัญญาการโทรกลับ ภายในฟังก์ชัน lockAcquired() มีการกำหนดตรรกะที่เกี่ยวข้องกับการดำเนินงานของพูล เช่น การสลับ ชำระ และการรับ ในที่สุด เมื่อ lock() กำลังจะสิ้นสุด PoolManager จะตรวจสอบว่า TokenDelta ที่เกี่ยวข้องกับการดำเนินการนี้ถูกรีเซ็ตเป็น 0 หรือไม่ เพื่อให้มั่นใจว่ายอดคงเหลือของสินทรัพย์ใน Pool ยังคงไม่เสียหาย
Singleton Contract หมายความว่า UniswapV4 ได้ละทิ้งโมเดล Factory-Pool ก่อนหน้านี้แล้ว แต่ละพูลไม่ใช่สัญญาอัจฉริยะที่เป็นอิสระอีกต่อไป แต่พูลทั้งหมดใช้สัญญาแบบซิงเกิลตันร่วมกัน การออกแบบนี้เมื่อรวมกับกลไก Flash Accounting จำเป็นต้องมีการอัปเดตตัวแปรการจัดเก็บข้อมูลที่จำเป็นเท่านั้น ซึ่งช่วยลดความซับซ้อนและต้นทุนในการดำเนินงานอีกด้วย
ในตัวอย่างด้านล่าง การใช้ UniswapV3 เป็นตัวอย่าง การแลกเปลี่ยน ETH สำหรับ DAI จะต้องมีการถ่ายโอนโทเค็นอย่างน้อยสี่ครั้ง (การดำเนินการเขียนการจัดเก็บ) ซึ่งรวมถึงการเปลี่ยนแปลงหลายอย่างที่บันทึกไว้สำหรับโทเค็น USDC, USDT และ DAI อย่างไรก็ตาม ด้วยการปรับปรุงใน UniswapV4 ประกอบกับกลไก Flash Accounting จำเป็นต้องมีการโอน Token เพียงครั้งเดียวเท่านั้น (การย้าย DAI จากพูลไปยังผู้ใช้) ช่วยลดจำนวนการดำเนินงานและต้นทุนได้อย่างมาก
ที่มา: https://twitter.com/Uniswap/status/1671208668304486404
ในการอัปเดตล่าสุดของ UniswapV4 คุณสมบัติที่โดดเด่นที่สุดคือสถาปัตยกรรม Hooks การอัปเดตนี้นำมาซึ่งความยืดหยุ่นอย่างมากในแง่ของความพร้อมใช้งานของพูล Hooks คือการดำเนินการเพิ่มเติมที่ทริกเกอร์ผ่านสัญญา Hooks เมื่อดำเนินการเฉพาะเจาะจงในพูล การดำเนินการเหล่านี้แบ่งออกเป็นการเริ่มต้น (สร้างพูล) แก้ไขตำแหน่ง (เพิ่ม/ลบสภาพคล่อง) สลับ และบริจาค แต่ละหมวดหมู่มีการดำเนินการก่อนดำเนินการและหลังการดำเนินการ
การออกแบบนี้ช่วยให้ผู้ใช้ดำเนินการตรรกะที่กำหนดเองก่อนและหลังการดำเนินการเฉพาะ ทำให้มีความยืดหยุ่นมากขึ้นและขยายฟังก์ชันการทำงานของ UniswapV4
ที่มา: https://github.com/Uniswap/v4-core/blob/main/whitepaper-v4-draft.pdf
ต่อไป เราจะใช้ตัวอย่างของ Limit Order เพื่ออธิบายกระบวนการทำงานจริงของ Hooks ใน UniswapV4 ก่อนที่เราจะเริ่มต้น เรามาอธิบายสั้นๆ เกี่ยวกับหลักการของการใช้ Limit Order ใน UniswapV4 กันก่อน
การใช้คำสั่งจำกัดของ UniswapV4 ทำงานโดยการเพิ่มสภาพคล่องให้กับช่วงราคาที่ระบุ จากนั้นดำเนินการลบสภาพคล่องออก หากมีการสลับสภาพคล่องในช่วงนั้น
ตัวอย่างเช่น สมมติว่าเราเพิ่มสภาพคล่องในช่วงราคา 1900-2000 สำหรับ ETH จากนั้นราคาของ ETH ก็เพิ่มขึ้นจาก 1800 เป็น 2100 ณ จุดนี้ สภาพคล่อง ETH ทั้งหมดที่เราเพิ่มไว้ก่อนหน้านี้ในช่วงราคาปี 1900-2000 ได้ถูกสลับเป็น USDC (สมมติว่าอยู่ในกลุ่ม ETH-USDC) ด้วยการลบสภาพคล่องในขณะนี้ เราสามารถบรรลุผลที่คล้ายกันในการดำเนินการคำสั่งตลาด ETH ที่ช่วงราคาปัจจุบันที่ 1900-2000
ตัวอย่างนี้นำมาจาก GitHub ของ UniswapV4 ในตัวอย่างนี้ สัญญา Limit Order Hook จะมี hook สองอัน คือ afterInitialize และ afterSwap ตะขอ afterInitialize ใช้เพื่อบันทึกช่วงราคา (ทำเครื่องหมาย) เมื่อสร้างพูล เพื่อพิจารณาว่าคำสั่งจำกัดใดที่ได้รับการจับคู่หลังจากมีคนสลับ
เมื่อผู้ใช้ต้องการสั่งซื้อ สัญญา Hook จะดำเนินการดำเนินการเพิ่มสภาพคล่องตามช่วงราคาและปริมาณที่ผู้ใช้ระบุ ในสัญญา Hook สำหรับคำสั่งจำกัด คุณสามารถดูฟังก์ชัน place() ได้ ตรรกะหลักคือการเรียกใช้ฟังก์ชัน lockAcquiredPlace() หลังจากได้รับการล็อคเพื่อดำเนินการดำเนินการเพิ่มสภาพคล่อง ซึ่งเทียบเท่ากับการวางคำสั่งจำกัด
ที่มา: https://github.com/Uniswap/v4-periphery/blob/main/contracts/hooks/examples/LimitOrder.sol#L246
หลังจากที่ผู้ใช้สร้าง Swap Token ภายในพูลนี้เสร็จแล้ว พูลจะเรียกใช้ฟังก์ชัน afterSwap() ของสัญญา Hook ตรรกะหลักของ afterSwap คือการลบสภาพคล่องของคำสั่งซื้อที่วางไว้ก่อนหน้านี้ซึ่งได้รับการดำเนินการระหว่างช่วงราคาก่อนหน้าและช่วงราคาปัจจุบัน ลักษณะการทำงานนี้เทียบเท่ากับใบสั่งที่ถูกเติม
ที่มา: https://github.com/Uniswap/v4-periphery/blob/main/contracts/hooks/examples/LimitOrder.sol#L192
นี่คือผังงานที่แสดงกระบวนการดำเนินการคำสั่งจำกัด:
ข้างต้นเป็นกระบวนการทั้งหมดของการนำ Limit-Order ไปใช้โดยใช้กลไก Hook
Hooks มีประเด็นที่น่าสนใจหลายประการที่ฉันพบว่าคุ้มค่าที่จะแบ่งปัน
การตัดสินใจดำเนินการเฉพาะก่อน/หลังถูกกำหนดโดยที่อยู่สัญญา Hook ขนาด 1 ไบต์ซ้ายสุด 1 ไบต์เท่ากับ 8 บิต ซึ่งสอดคล้องกับการดำเนินการเพิ่มเติม 8 รายการ พูลจะตรวจสอบว่าบิตของการกระทำนั้นเป็น 1 หรือไม่ เพื่อพิจารณาว่าจะเรียกใช้ฟังก์ชัน hook ที่สอดคล้องกันของสัญญา Hook หรือไม่ นอกจากนี้ยังหมายความว่าที่อยู่ของสัญญา Hook จำเป็นต้องได้รับการออกแบบในลักษณะเฉพาะและไม่สามารถเลือกโดยพลการเป็นสัญญา Hook การออกแบบนี้มีวัตถุประสงค์หลักเพื่อลดการใช้ก๊าซและเปลี่ยนต้นทุนไปเป็นการใช้งานตามสัญญาเพื่อให้การดำเนินงานมีประสิทธิภาพมากขึ้น (ปล.: ในทางปฏิบัติ สามารถใช้เกลือ CREATE2 ที่แตกต่างกันเพื่อคำนวณที่อยู่ของสัญญาที่ตรงตามเงื่อนไข)
นอกเหนือจากความสามารถในการดำเนินการเพิ่มเติมก่อนและหลังแต่ละการกระทำแล้ว Hooks ยังสนับสนุนการดำเนินการค่าธรรมเนียมแบบไดนามิกอีกด้วย เมื่อสร้างพูล คุณสามารถระบุว่าจะเปิดใช้งานค่าธรรมเนียมแบบไดนามิกหรือไม่ หากเปิดใช้งานค่าธรรมเนียมแบบไดนามิก ฟังก์ชัน getFee() ของสัญญา Hook จะถูกเรียกเมื่อทำการสลับโทเค็น สัญญา Hook สามารถกำหนดจำนวนค่าธรรมเนียมที่จะเรียกเก็บตามสถานะปัจจุบันของพูล การออกแบบนี้ช่วยให้สามารถคำนวณค่าธรรมเนียมได้อย่างยืดหยุ่นตามสถานการณ์จริง ซึ่งเป็นการเพิ่มความยืดหยุ่นของระบบ
แต่ละพูลจำเป็นต้องกำหนดสัญญา Hook ในระหว่างการสร้าง และไม่สามารถเปลี่ยนแปลงได้ในภายหลัง (แม้ว่าพูลที่แตกต่างกันสามารถใช้สัญญา Hook เดียวกันได้) สาเหตุหลักมาจาก Hooks ถือว่าเป็นส่วนหนึ่งของ PoolKey และ PoolManager ใช้ PoolKey เพื่อระบุว่าพูลใดที่จะใช้งาน แม้ว่าสินทรัพย์จะเหมือนกัน แต่หากสัญญา Hook แตกต่างกันก็จะถือเป็นพูลอื่น การออกแบบนี้ช่วยให้แน่ใจว่าสถานะและการดำเนินงานของพูลต่างๆ สามารถจัดการได้อย่างอิสระ เพื่อให้มั่นใจถึงความสอดคล้องของพูล อย่างไรก็ตาม มันยังเพิ่มความซับซ้อนของการกำหนดเส้นทางเมื่อจำนวนพูลเพิ่มขึ้น (บางที UniswapX อาจได้รับการออกแบบมาเพื่อแก้ไขปัญหานี้)
UniswapV4 เน้นย้ำอย่างชัดเจนถึงการขยายระบบนิเวศ Uniswap ทั้งหมด โดยเปลี่ยนให้เป็นโครงสร้างพื้นฐานเพื่อให้สามารถให้บริการต่างๆ ได้มากขึ้นบนรากฐานของ Uniswap Pools สิ่งนี้ช่วยเพิ่มขีดความสามารถในการแข่งขันของ Uniswap และลดความเสี่ยงของบริการทางเลือก อย่างไรก็ตาม จะต้องดูกันต่อไปว่าจะบรรลุผลสำเร็จตามที่คาดหวังหรือไม่ จุดเด่นบางประการ ได้แก่ การผสมผสานระหว่าง Flash Accounting และ EIP1153 และเราเชื่อว่าบริการต่างๆ จะนำคุณลักษณะเหล่านี้ไปใช้ในอนาคต ซึ่งนำไปสู่สถานการณ์การใช้งานที่หลากหลาย นี่คือแนวคิดหลักของ UniswapV4 และเราหวังว่าจะให้ความเข้าใจที่ลึกซึ้งยิ่งขึ้นเกี่ยวกับวิธีการทำงานของ UniswapV4 หากมีข้อผิดพลาดในบทความโปรดชี้ให้เห็น เรายังยินดีรับการอภิปรายและข้อเสนอแนะ
สุดท้ายนี้ เราขอขอบคุณ Anton Cheng และ Ping Chen สำหรับการรีวิวบทความและให้ข้อเสนอแนะอันมีค่า!