Defi Scams —Yield Farming: วิธีการเอา LP Token ออก พร้อมทั้ง Remove Liquidity จากเว็บที่บินหรือโดน Rug Pull (2/2021)

yoisha
6 min readFeb 28, 2021

--

Disclaimer: This article only aims to provide basic knowledge to the smart contract fraudulent schemes and prevent scams to grow and hurt the Defi community. This is NOT financial advice.

This guide wrote especially for Specific yield farming in Binance smart chain, Other protocols may differ.

How to Unstake & Remove Liquidity

Introduction

ในปี 2021 เรียกว่าเป็นช่วงเวลาที่ฮอทฮิตที่สุดของ Decentralize Finance หรือโดยย่อ “Defi” มี Dapp (Decentralize Application) ผุดขึ้นมาเป็นดอกเห็ด คอยให้บริการเหล่านักซิ่งไม่ว่าทั้งเร็วหรือช้า ไม่ว่าจะเป็น DEX (Decentralize Exchange), Yield Farming, Liquidity Mining, Collateral Loans, Stable coins, และเทคโนโลยีที่ถูกสร้างขึ้นมาโดย Blockchain Smart Contract อื่นๆอีกมากมาย

PancakeSwap — Yield farming

แต่ใช่ว่าทุกผู้ให้บริการ Smart Contract จะหวังดีต่อผู้ใช้เสมอไป บางเจ้ามีประสงค์ร้ายและคอยกัดกินผู้ใช้งาน Defi ทั้งทางตรงและทางอ้อม คอยสรรหาวิธีการ Scam ผู้ใช้โดยวิธีต่างๆ ไม่ว่าจะเป็นช่องโหว่ของระบบ Smart Contract, หรือแม้แต่ User Error.

ทั้งนี้ ถึงแม้ว่า Smart Contract จะสามารถตรวจสอบได้ 100% แต่ไม่ได้หมายความว่าทุกคนจะมีความสามารถในการมองเห็นช่องโหว่ที่ถูกสร้าง(หรือไม่ได้จงใจสร้าง) ในนั้น ผู้ใช้งานสมควรจะรู้ถึงหลักการทำงานต่างๆและอ่าน Source code ของ Smart contract ในเบื้องต้นได้ เพื่อป้องกันตัวเองจากภัยอันตรายของโลก Defi ที่พร้อมจะกลืนกินผู้ใช้หน้าใหม่ที่ไม่ระวังตัวและตกเป็นเหยื่อในที่สุด

Rug Pull Execution

ตามรายงานและข้อมูลที่เก็บได้แล้ว แต่ละเดือนมี % ของการ Rug pull เพิ่มขึ้นมากเรื่อยๆ และเพิ่มขึ้นสูงมากกว่าช่วงเวลาก่อนๆเป็นพิเศษในเดือนนี้(Feb 2021) ด้วยเหตุผลของจำนวนผู้ใช้งานที่เพิ่มมากขึ้น และโอกาสในการทำกำไรของ Scammer เอง ด้วยเหตุนี้ผู้ใช้ถึงต้องระวังตัวเป็นพิเศษ

จะไม่ขอลงรายละเอียดวิธีการและประเภทของ Rug pull ในส่วนนี้ แต่พูดง่ายๆ, Rug pull, ก็คือเว็บบิน — โดนโกงเงินนั่นแหละ เราจะไม่สามารถถอน LP Token โดยผ่านทางเว็บได้อีกต่อไป (เพราะเว็บมันปิด) จึงต้องทำการถอนด้วยตัวเองผ่าน Smart Contract Function Execution ผ่านหน้าเว็บ Bscscan

Bscscan.com write contract

Verify Your Token

เมื่อเรา Stake LP Token ของเราลงไปในเว็บ นั่นหมายความว่า LP Token ที่อยู่ในกระเป๋าเงินของเรา ถูก”ส่ง”ไปให้กระเป๋าเงินของ Smart Contract — แปลว่าเรา ”ไม่มี Token จริงๆอยู่ในกระเป๋าเงินของเราอีกต่อไป” แต่มี Allowance หรือ การยินยอมให้ใช้จ่าย Token ใน Smart Contract ตามจำนวน Token ที่เราส่ง (Stake)

การทำงานของ Staking

ดังนั้นตัว Contract ก็จะสามารถแยกแยะได้ว่า Token ที่อยู่ใน Contract นั้นเป็นของใครบ้าง จำนวนเท่าไหร่บ้าง

ก่อนที่เราจะเอา LP Token ออกได้นั้น เราต้องมาดูก่อนว่า Token ของเรา “อยู่ใน Pool ไหน” — เช่น BNB/BUSD, BNB/EGG, BUSD/EGG เป็นต้น

วิธีเช็คเบื้องต้น

เริ่มต้น เข้าไปที่ Contract ของ MasterChef หรือ Main Staking Contract หลักที่เป็นตัวจัดการ Token, Mint เหรียญ, ปล่อย Farm, จัดการ Assets ต่างๆตามหลักแล้วจะใช้ชื่อ Masterxxx, xxxChef, ฯลฯ และกดที Tab Contract และเลือก Read Contract

วิธีหา MasterChef Contract ง่ายๆคือ เข้าไปที่ Transaction ที่เรา Stake LP Token ของเรา จะเห็นได้ชัดว่าเรา Interact กับ Staking Contractให้กดเข้าไปใน Contract นั้น

Staking Transaction
Staking Transaction Details

จากนั้นหา Function ที่ชื่อว่า poolInfo , Function นี้จะเป็นตัวบอกตำแหน่งของ Pool ของเรา เอาไว้ใช้เป็นข้อมูลในการทำอย่างอื่นต่อไป จากนั้นใส่ตัวเลขไปเริ่มจาก 0 (0 เป็นอันแรก) แล้วคลิกใน lpToken address ดูว่า pool นี้เป็นของ LP อะไร ถ้าคลิกเข้าไปแล้วจะเจอหน้า LP Token Contract ให้สุ่มเลขไปเรื่อยๆจนกว่าจะกดเข้าไปแล้วเจอหน้า LP Token ของเรา แล้วจำเลข pool แล้วไปใช้ใน Function ถัดไป

poolInfo

จากนั้นหา Function ที่ชื่อว่า userInfo (ชื่ออาจแตกต่างกันไปในแต่ละ Contract) ช่องแรกให้ใส่ poolIdที่เราได้จาก Function ด้านบน ช่องที่สองให้ใส่ addressของกระเป๋าเรา, Function นี้จะทำให้เราสามารถดูได้ว่าเรา Stake ใน pool นั้นและมี LP อยู่ใน pool เท่าไหร่ในช่อง amount และดู Token ที่เราสามารถ Harvest ได้ที่ rewardDebt

ซึ่งในตัวเลขพวกนี้จะมีหน่วยเป็น Wei หรือ 10¹⁸, เช่นมันขึ้นเป็นเลข 46304767801968835341 เราก็เอามาหาร 18 จะได้ 46.3 กว่าๆ นั่นหมายความว่าเรา Stake LP Token ของเราใน pool 0 อยู่ 46.3 LP Token นั่นเอง

ต่อไปให้จำเลข amount นี้ไว้ แล้วกลับไปที่ poolInfo และกดเข้า address ของ lpToken มันจะเด้งไปหน้า LP Token Contract

userInfo

พอเข้าหน้า LP Token Contract มาแล้วเราสามารถดูธุรกรรมได้ว่าใครทำอะไรกับ LP Token นี้บ้าง รวมถึงสามารถกดดูจำนวนและมูลค่าของ Token ต้น (เช่น BNB หรือ USD) ที่อยู่ใน Contract นี้ได้ด้วย

LP Token Contract

จากนั้นให้มองตรงฝั่งขวา จะมีที่เขียนว่า Token Tracker ให้กดเข้าไป จะเจอหน้าของ Token นั้นๆ แล้วให้กดตรง Holder, Tab ที่ 2 นับจาก Transfer

LP Token page
Lp Token page, Holders

ให้กดตรงแว่นขยายขวาบน จะเป็นการ Search Token Holder จาก address ซึ่งตรงนี้ให้คุณใส่ address ของ MasterChef เข้าไป เพื่อเป็นการ Recheck ว่า MasterChef มี LP Token ของคุณอยู่ จ ริ ง ๆ หรือเปล่า

Lp Token page, Token holder balances

ถ้าเกิดว่า Balance ของ Contract มีมากกว่า amount ที่คุณจดมาตอนแรก ยินดีด้วย 🎆 เงินของคุณยังอยู่ดี (แม้มูลค่าของ LP จะลดลงเนื่องจาก Impermanent Loss จากการโดน Dump แต่ก็ยังได้เหรียญต้นกลับมา)

แต่ถ้า Balance มีน้อยกว่า amount หรือ Balance เป็น 0

ยินดีด้วย คุณโดน รั บ น้ อ ง แบบ ส ม บู ร ณ์ แ บ บ

คือถ้า Balance เป็น 0 นั่นหมายความว่ามีคนอื่นหรือเจ้าของ Contract สามารถเข้าถึง LP Token ของคุณได้ บอกได้สองอย่าง 1. คุณโดน Backdoor ใน Contract Code 2. คุณไม่ควรเชื่อใจ Smart Contract ใดๆบนโลกอีก

หากยังเหลือ Balance แต่ว่า น้อยกว่า amount ของคุณ ให้จดค่า Balance นั้นไว้ อย่าลืมนับจุด Decimal ให้ครบ 18 ตัว ขั้นตอนต่อไปเราจะไป Unstake จาก Contract แล้วเอา LP Token กลับมากัน

Unstake

ก่อนอื่นให้กลับไปที่ MasterChef Contract และเลือก Write Contract แทน

ถ้า Balance เหลือมากกว่าหรือเท่ากับ amount ให้มองหา Function ที่ชื่อว่า emergencyWithdraw

ก่อนที่จะกดใช้ เรามาดู Code ก่อนว่ามันทำงานยังไง, emergencyWithdraw รับค่า _pid (Pool Id) และเรียกดู amount ของเราใน poolId จากนั้นใช้ safeTransfer เข้าสู่ address ของเรา, และ set rewardDebt หรือ Token ที่ยังไม่ถูก Harvest เป็น 0, แต่ใครจะสนใจกันล่ะตอนนี้

emergencyWithdraw Source Code

safeTransfer เป็น Standard ของ OpenZeplin ที่หลักการทำงานของมันคือ ถ้า amount มากกว่า balance ในตัว, Transaction จะถูก revert นั่นแปลว่าถ้าเรามี amount ที่เรา Stake ไปเกิน balance ของ Contract เราจะไม่สามารถถอนได้

ถ้าไม่มีอะไรแล้วก็ใส่ _pid เป็น Pool Id ของ LP เราแล้วกด Write หากไม่มีอะไรผิดพลาด LP Token จะกลับมาใน Wallet ของเรา

emergencyWithdraw

ถ้า Balance เหลือน้อยกว่า amount ให้มองหา Function ที่ชื่อว่า withdraw

Source code ของ withdraw ก็จะทำงานคล้ายๆ emergencyWithdraw แต่จะโอน Token ที่ยังไม่ถูก Harvest เข้ากระเป๋าของเราด้วย ทำให้ใช้ Gas มากกว่า

withdraw Source Code

ถ้าพร้อมแล้วก็ใส่ _pid เป็น Pool Id ของ LP เรากับ amount ที่เราจดมาจาก BSC Scan ( amount ต้องมากกว่า 0 ) ให้ลบจุด Decimal ออกด้วย เช่น 44.5128 Token ให้ x 10¹⁸ เข้าไป ก็จะกลายเป็น 44512800000000000000 เสร็จแล้วกด Write

withdraw

หากได้ LP Token ออกมาแล้วให้กลับไป Remove Liquidity ที่ PancakeSwap ถ้าเป็น LP/ใช้ AMM ของ Pancake แต่ถ้าเป็นของเจ้าอื่นหรือเป็นของเว็บที่ปิดไปแล้ว ขั้นตอนถัดไปจะมาสอน Remove Liquidity โดยใช้ BSCScan กัน

Remove Liquidity

ก่อนอื่นเข้าไปที่หน้า LP Token Contract ของเราก่อน แล้วเข้าไป Recheck ว่ามี Token ต้นอยู่ใน LP Contract ไหม วิธีการเช็คมีอยู่ 2 วิธีให้ลองทำทั้ง 2 วิธี

  • กดดูตรง Token Dropdown
Initial Token on LP Token pages
  • กด Read Contract แล้วหา Function ที่ชื่อว่า getReserves
getReserves function

ถ้าเกิดว่าอันใดอันหนึ่งมีค่าเป็น 0 ขึ้นมา นั่นยังไม่ได้แปลว่าเงินคุณหาย เช่นเดียวกับการที่คุณยังเห็นตัวเลขในนั้น ไม่ได้แปลว่าเงินคุณยังอยู่ เพราะว่าค่าของ getReserves อาจจะยังไม่ถูกอัพเดตโดย sync

sync function

อย่างไรก็ถาม ให้ลอง Remove Liquidity/Unwrap LP เลย

หากจะ Remove Liquidity ต้องไปทำที่ Router Contract, ซึ่ง remove,add liquidity เป็น periphery ของ swap อยู่ใน Contract เดียวกัน

วิธีหา Router Contract ง่ายๆคือ เข้าไปที่ Transaction ที่เราแลก Token เป็น LP Token จะเห็นได้ชัดว่าเรา swap หรือ add liquidity บน Router ให้กดเข้าไปใน Contract

Transaction on Router Contract

ให้เข้าไปที่ Contract แล้วกด Write Contract จากนี้ไปจะซับซ้อนเล็กน้อย ให้หา Function ที่ชื่อว่า removeLiquidity

removeLiquidity Function

จะเห็นได้ว่ามีช่องให้กรอกเยอะแยะเต็มไปหมด เราจะไปกันอย่างช้าๆในตรงนี้

ช่อง tokenA/ tokenB ให้ใส่ address Token ต้นทั้งสองอันของ LP Token เข้าไป เช่นถ้ามี LP ของ BNB/BUSD ช่องแรก Token A ให้ใส่ Contract Address ของ BNB (ซึ่งปกติแล้วถ้าใช้ BNB ในการ Stake จะถูกแปลงเป็น WBNB โดยอัตโนมัติ) คือ 0xbb4cdb9cbd36b01bd1cbaebf2de08d9173bc095c และ Token B ให้ใส่ Contract Address ของ BUSD คือ 0xe9e7cea3dedca5984780bafc599bd69add087d56

ช่อง liquidity ให้ใส่จำนวน LP Token ที่เรามีในหน่วย Wei (x10¹⁸)

ช่อง amountAMin/amountBMin เป็นช่องที่กำหนดว่าเราจะได้รับ Token ต้นของเราคืนมาขั้นต่ำเท่าไหร่ (ถ้าเว็บยังใช้ได้มันจะถูกเรียกว่า Slippage) ในส่วนนี้ให้ใส่ไปที่ 0 ทั้งสองช่องเพราะเราจะเอา Token เราออกมาไม่ว่าจะได้เท่าไหร่

ช่อง to ให้ใส่ Address ของกระเป๋าเรา

ช่อง deadline จะเป็นช่องที่กำหนดเวลา Transaction มากสุด ในหน่วย Unix Epoch Time หากเกินเวลานี้ Transaction จะถูก Revert, ให้ไปดูเวลาที่ https://www.epochconverter.com/ แล้วปรับเวลาให้มากขึ้นสัก 1 ชม เสร็จแล้วก็ก็อป Unix Timestamp กลับมาแปะที่ช่องนี้

เสร็จแล้วให้กด Write ตามหลักการแล้วถ้ายังมี Token อยู่ใน Reserve แม้แต่ 0.0000001 มันก็จะถูกโอนมาให้เรา แต่ถ้า Transaction ถูก Revert แปลว่า

RIP 💤

ถ้าอยากจะ Recheck อีกรอบ ให้กด Write ที่ Function syncเพื่อให้ LP Token Contract Re-calculate getReserves ใหม่ หรือไปเช็คจาก Contract ของ Token ต้นโดยใส่ Address ของ LP Token เข้าไป

ถ้าทำทั้งสองทางแล้วยังเจอ Balance ที่เป็น 0 อยู่ก็

That’s all for now. Remember to ape in responsibly and your funds will be SAFU, stay safe my fellow degens.

Feedback is always appreciated.

--

--

yoisha
yoisha

Written by yoisha

Flutter & Blockchain Developer

Responses (3)