Page cover

💻เชื่อมต่อกับ Alpaca Finance

เชื่อมต่อกับ Alpaca Finance

Alpaca Finance เป็นแอปพลิเคชั่น DeFi ที่เชื่อมต่อผู้ใช้กับโปรโตคอลหลัก และตัวอย่างเช่น นักพัฒนาสามารถสร้างโปรโตคอลที่ฝากเงินของผู้ใช้ในโปรโตคอลของ Alpaca Finance และทำการทบต้นผลกำไรได้อย่างมีประสิทธิภาพและใช้ค่าแก๊สได้คุ้มค่า เป้าหมายของเอกสารนี้ก็เพื่อช่วยให้นักพัฒนาให้เชื่อมต่อกับโปรโตคอลของเราได้ โดยรักษามาตรฐานความปลอดภัยให้กับระบบนิเวศน์

การเชื่อมต่อกับ Alpaca API ต้องมีการยืนยันตัวตน โปรดติดต่อมาที่ [email protected] ถ้าหากคุณต้องการใช้บริการนี้

สถิติที่สำคัญ

APIs สาธารณะข้างต้นได้รวมข้อมูลที่สำคัญที่ถูกนำไปใช้ใน frontend ของเรา ดังนั้นคุณสามารถใช้ข้อมูลเหล่านี้ได้โดยที่ข้อมูลเหล่านี้จะถูกอัพเดทตลอดเวลาโดยเรา

AF1.0:

AF2.0:

ตัวอย่างข้อมูลที่อยู่ใน APIs:

  1. Lending pools และสถิติทั้งหมด เช่น APR, TVL, Supply and Borrow, ราคา ibToken

  2. Workers (farm) และสถิติทั้งหมด เช่น APR, TVL

  3. Automated Vaults และสถิติทั้งหมด เช่น APy, ราคา AV Share

Example of information included in the APIs:

  1. All lending pools and their stats e.g., APR, TVL, Supply and Borrow, ibToken price

  2. All workers (farm) and their stats e.g., APR, TVL

  3. All Automated Vaults and their stats e.g., APY, AV Share Price

เชื่อมต่อกับ Smart Contract

หมวดนี้จะอธิบายถึงการเชื่อมกับ Alpaca Finance โดยตรงผ่าน smart contract

การปล่อยกู้

Alpaca Finance สร้างผลตอบแทนให้ผู้ใช้ผ่านดอกเบี้ยกู้ยืมจากสินทรัพย์คริปโต โดยผู้ใช้สามารถวางเหรียญใน vault และสินทรัพย์ที่จะถูกนำไปใช้โดยผู้ทำ yield farming เพื่อเพิ่ม leverage ให้กับการฟาร์ม ตัว smart contract ใดๆที่เป็น EVM compatible และอยู่บน BNB Chain ล้วนสามารถเชื่อมต่อกับระบบปล่อยกู้ของ Alpaca Finance ได้

เพื่อทำการฝากเหรียญพื้นฐานใน vault ของ Alpaca Finance ควรเริ่มจากการทำรายการชื่อ vault และเหรียญที่เกี่ยวข้องก่อน

  • โปรดดู ที่นี่ เพื่อดูรายการที่อยู่ของ vault contract ทั้งหมด

ก่อนจะทำการฝากใดๆใน vault ตัว smart contract จะทำหน้าที่เป็นผู้ฝาก ดังนั้นต้องทำการอนุญาตจำนวนที่สามารถใช้จ่ายได้เสียก่อน นี่จะอนุญาตให้ smart contract ของ Alpaca สามารถนำเหรียญมาจากผู้ส่งได้

// JavaScript
import { ERC20 } from '../typechain/ERC20'
import { MaxUint256 } from '@ethersproject/constants'

...

const yourSmartContractAddress = 'xxx'
tokenERC20.approve(yourSmartContractAddress, MaxUint256);

โค้ด JavaScript ด้านบนคือ workflow เวอร์ชั่นพื้นฐาน ที่จะทำหน้าที่อนุญาตให้ contract ใช้เหรียญได้มากที่สุด ต้องระลึกว่า การใช้MaxUint256 จะทำให้เกิดความเสี่ยงต่อความปลอดภัย ดังนั้นแนะนำให้ใช้จำนวนตามที่ผู้ใช้ระบุมาจะดีกว่า

การทำธุรกรรมฝาก โดยใช้deposit และระบุจำนวนที่amountToken ข้อมูล amountToken เป็นประเภท uint256 และ parameter นี้ต้องถูกทำให้เป็นฟอร์แม็ตที่รองรับจำนวน decimals ของเหรียญที่จะฝาก (เช่น BNB มี 18 decimals 1 BNB = 10000000000000000000 หรือ 1 * 1e18) เคสที่เหรียญพื้นฐานเป็น BNB ตัว vault จะทำการ wrap เหรียญ BNB เป็น wBNB แต่การทำธุรกรรมต้องสามารถรองรับจำนวน BNB ที่จะส่งเป็น token พื้นฐานได้

// Solidity
address vaultContractAddress = '0xd7D069493685A581d27824Fc46EdA46B7EfC0063'; // BNB Vault
if (msg.value == 0) { // if no native token is sent, then it is a ERC20/BEP20 token deposit
	IERC20(tokenAddess).safeTransferFrom(address(msg.sender), address(this), amountToken);
}
// Allow transfer to vault
SafeToken.safeApprove(tokenAddess, vaultContractAddress, amountToken);
// Deposit to vault
IVault(vaultContractAddress).deposit(amountToken);

ถ้าฝากสำเร็จ ตัว vault จะสร้างเหรียญ interest-bearing tokens (เรียกย่อว่า ibTokens) และส่งเหรียญนี้ให้กับผู้ทำธุรกรรม จำไว้ว่า จำนวนเหรียญ ibToken และจำนวนเหรียญที่ฝากจะได้จำนวนไม่เท่ากัน ผู้เรียกการทำธุรกรรม depositจะต้องติดตามผลส่วนแบ่งของผู้ใช้ใน vault ให้ถูกต้อง โปรดดูคำอธิบายอย่างละเอียดวิธีการคำนวณ Interest Bearing Token Calculation ที่นี่

ผลตอบแทนจากดอกเบี้ยการปล่อยกู้จะสะสมใน ibToken เพื่อรับผลตอบแทนนี้ ผู้ปล่อยกู้จะต้องถอนเหรียญ ibToken ออกมาและแปลงกลับเป็นเหรียญพื้นฐาน คุณจะเห็นว่าราคาแลกเปลี่ยนของ ibToken จะสูงขึ้นตอนที่ถอนออกมา ซึ่งบ่งบอกว่าผลตอบแทนที่เป็นดอกเบี้ยได้สะสมในเหรียญ ดังนั้นคุณจะได้เหรียญพื้นฐานกลับมามากขึ้น

การถอนเหรียญพื้นฐานจาก vault จำนวนเหรียญ ibToken จะต้องส่งไปที่withdraw ของ Vault contract

// Solidityaddress vaultContractAddress = '0xd7D069493685A581d27824Fc46EdA46B7EfC0063'; // BNB VaultIVault(vaultContractAddress).withdraw(ibTokenAmount);

เหรียญพื้นฐานจะถูกส่งกลับให้กับคนทำธุรกรรม ถ้าเหรียญที่โดนเรียกคืนคือ BNB ตัว vault contract จะทำการเปลี่ยนเหรียญ WBNB เป็น BNB

การคำนวณ Interest Bearing Token

เหรียญ Interest Bearing Token (ibToken) คือเหรียญที่ทำหน้าที่เป็นส่วนแบ่งของผู้ฝาก เหรียญ ibTokens จะสะสมรายได้จากดอกเบี้ยกู้ยืมไปเรื่อยๆ โปรโตคอล DeFi ใดๆที่ต้องการใช้ vault ของ Alpaca Finance ต้องเข้าใจและสามารถคำนวณเพื่อใช้งานเหรียญ ibToken ให้ถูกต้องและแสดงผลได้ตรงตามส่วนแบ่งแท้จริงของผู้ฝากใน vault นั้นๆ

ดังนั้น จำนวนสัดส่วนระหว่าง ibToken และเหรียญพื้นฐานจะเป็น 1:1 เฉพาะเวลาที่ vault เพิ่งเปิดเท่านั้น และหลังจากนั้นจะเพิ่มมูลค่าเรื่อยๆ (มูลค่าจะเพิ่มขึ้นอย่างเดียวเท่านั้น ไม่มีลดลง) ยกตัวอย่างราคา 1 ibBNB = 1.0292 BNB หมายความว่าการฝาก 1.0292 BNB จะได้ 1 ibBNB กลับมา อีกนัยหนึ่งคือการถอนเหรียญ 1 ibBNB จะได้รับ 1.0292 BNB และส่วนต่างคือรายได้จากดอกเบี้ยที่สะสม

การทำความเข้าใจกลไกพื้นฐานเกี่ยวกับมูลค่าของ ibTokens เป็นเรื่องสำคัญมาก เพราะโปรโตคอล DeFi ที่จะเชื่อมต่อกับ vault เงินปล่อยกู้ของ Alpaca Finance ต้องสามารถคำนวณสัดส่วนเงินฝากได้อย่างแม่นยำ ความผิดพลาดในการคำนวณจะนำไปสู่ปัญหาความปลอดภัยหรือการสูญเสียทรัพย์สิน นี่เป็นปัญหาที่เกิดกับการโดนโจมตีของ bEarn.fi และ ValueDeFi ซึ่งเป็นกรณีที่โปรโตคอลกำหนดให้มูลค่าเหรียญ ibTokens กับเหรียญพื้นฐานมีสัดส่วน 1:1 ตลอดเวลา (อ่านเพิ่มเติมที่นี่ bEarn.fi และ ValueDefi).

นอกจากนั้น แม้ว่าการโจมตีด้วย flash loan จะไม่ได้ผลกับ Alpaca แต่ vault ที่ไม่ใช่ของ Alpaca อาจจะมีความเสี่ยงที่ราคา ibToken จะโดนปั่นจากการโจมตีด้วย flash loan ถ้าหากไม่เตรียมตัวให้ดี ราคาของ ibToken จะลดลงในการทำธุรกรรมของผู้โจมตี และนี่เป็นเหตุผลว่าทำไมไม่ควรพึ่งพาแต่ smart contract ของ ibToken เพื่อใช้คำนวณราคา เราแนะนำให้ใช้ price oracle feed เพื่อเชื่อมข้อมูลราคาของ ibToken ต่อสัดส่วนเหรียญพื้นฐานเพื่อป้องกันการโดนโจมตี

และเราจะแสดงตัวอย่างวิธีที่ปลอดภัยและถูกต้องในการคำนวณราคาของ ibToken

คำนวณโดยตรงจาก smart contract

การคำนวณราคา ibToken โดยตรงจาก smart contract เป็นวิธีที่ง่ายที่สุดและเพราะเป็นวิธีที่ไม่ยาก จึงไม่ควรใช้เป็นวิธีเดียว

// Solidityaddress vaultContractAddress = '0xd7D069493685A581d27824Fc46EdA46B7EfC0063'; // BNB VaultIVault vault = IVault(vaultContractAddress);uint256 ibTokenAmount = ...;uint256 ibTokenPrice = vault.totalToken()).div(vault.totalSupply();uint256 underlyingTokenAmount = ibTokenAmount.mul(ibTokenPrice);

ตัวโค้ด snippet ด้านบนแสดงถึงราคา ibToken ที่คำนวณจากการดึงราคาจาก totalToken และ totalSupply ของเหรียญที่เกี่ยวข้อง

การดึงราคาเหรียญ ibToken จาก API ของ Alpaca

Alpaca Finance มี API ข้อมูลราคาปัจจุบันของ ibToken โดยส่งคำขอ GET REST ไปที่ endpoint /ibTokens เพื่อดึงราคาเหรียญ ibToken ไม่ว่าจะอันไหน การเชื่อมต่อกับ Alpaca API ต้องมีการอนุญาตและคุณสามารถติดต่อเรามาที่ [email protected] ก่อนที่คุณจะใช้บริการนี้

ข้างล่างเป็นผลลัพท์ตัวอย่างที่ได้จาก API

{
    "status": {
        "code": 1000,
        "messages": [
            "OK"
        ]
    },
    "data": [
        {
            "symbol": "ibALPACA",
            "baseTokenPerShare": "1.051108636596531492",
            "lendingApr": "0.0003638488758058",
            "stakingApr": "0.0"
        },
        {
            "symbol": "ibBNB",
            "baseTokenPerShare": "1.025808940627339553",
            "lendingApr": "9.7785294844178225",
            "stakingApr": "316693.265280905443641"
        },
        {
            "symbol": "ibBUSD",
            "baseTokenPerShare": "0.972337256352625836",
            "lendingApr": "0.368330890561667",
            "stakingApr": "2269.786601379154162"
        },
        {
            "symbol": "ibUSDT",
            "baseTokenPerShare": "0.913094694500682622",
            "lendingApr": "0.0012775198722327",
            "stakingApr": "0.0"
        },
        {
            "symbol": "ibBTCB",
            "baseTokenPerShare": "1.000006160536069502",
            "lendingApr": "6.5534019786376696",
            "stakingApr": "0.0"
        },
        {
            "symbol": "ibETH",
            "baseTokenPerShare": "0.999463386510494271",
            "lendingApr": "0.0000004209960912",
            "stakingApr": "0.0"
        }
    ]
}

ราคาจาก from Alpaca API ต้องดึงผ่าน smart contract ที่มี price oracle การดึงข้อมูลราคาผ่าน input เข้า smart contract โดยฟังชั่น call จะมีความเสี่ยงต่อการโดนโจมตีแบบ injection จากฝั่ง client เราจึงไม่แนะนำให้ทำแบบนั้น ตัวอย่าง price oracle สามารถดูได้ ที่นี่ และการใช้ price oracle ที่น่าเชื่อถือ คุณสามารถทำให้ข้อมูลที่ได้มา มีความแม่นยำและปลอดภัย

เราแนะนำอย่างยิ่งให้ใช้ข้อมูลราคา ibToken จากทั้งการคำนวณของ smart contract และจาก Alpaca API การมีข้อมูลสองแหล่งจะได้เปรียบเทียบเพื่อหาข้อมูลที่ผิดพลาด และถ้าข้อมูลจากสองแหล่งไม่สอดคล้องกันจะทำให้ข้อมูลราคานั้นโดนปฏิเสธ

กล่าวโดยสรุป วิธีที่ปลอดภัยที่สุดในการคำนวณราคา ibToken คือ:

  1. คำนวณราคา ibToken ใน contract ของคุณ

  2. ใช้ข้อมูล off-chain oracle ของราคา ibToken หรือดึงจาก Alpaca's API

  3. เปรียบเทียบ 1 และ 2 และถ้ามีความแตกต่างมากกว่า n% ให้ปฏิเสธการทำธุรกรรมนั้น

Alpaca API จะสามารถใช้ได้โดยผู้ที่เป็น whitelist เท่านั้น (ทั้งโปรโตคอลและสถาบัน) เพื่อขอสิทธิการเข้าถึง ให้ส่งอีเมลล์มาที่ [email protected]

Staking

ตามกำหนดการปล่อยโทเค็น รางวัล ALPACA ได้สิ้นสุดลงแล้ว ดังนั้นข้อมูลที่เกี่ยวกับ Staking ด้านล่างเป็นเพียงข้อมูลอ้างอิงก่อนที่การแจกจ่ายโทเค็นจะสิ้นสุดลง

Alpaca Finance มีระบบการ staking ให้กับผู้ใช้ Interest-bearing tokens และเหรียญ LP token บางอัน สามารถนำไปวางใน pool เพื่อรับผลตอบแทนเป็นเหรียญ Alpaca และถ้าหากคุณฝากเหรียญและได้ ibTokens เราแนะนำให้นำเหรียญนี้ไปฝากต่อเพื่อรับผลตอบแทนสูงสุด

การ stake เหรียญเหล่านี้ใน stake pool ใน Alpaca Finance ต้องมีรายการ pool และรายการเหรียญที่จะ stake ทั้งหมดนี้ก่อน โปรดดู ที่นี่ เพื่อดูข้อมูลเชิงลึกของ pool contract addresses ทั้งหมด ชื่อโค้ดของ pool ใน codebase ของเราจะใช้ชื่อว่าFairlaunch เป็นส่วนใหญ่

การทำ stake จะทำโดยใช้วิธี deposit และ parameters จะเป็นดังต่อไปนี้

  • _for คือที่อยู่ของผู้ฝาก

  • _pid คือ id ของ stake pool

  • _amount คือจำนวณเหรียญที่จะฝากใน uint256 และระบุเลข decimals (ยกตัวอย่าง ibBNB ใช้ 18 decimals ดังนั้น 1 ibBNB = 10000000000000000000 หรือ 1 * 1e18)

// Solidityaddress fairlaunchContractAddress = '0xA625AB01B08ce023B2a342Dbb12a16f2C8489A8F'; // ibBNB poolIFairLaunch fairlaunch = IFairLaunch(fairlaunchContractAddress);fairlaunch.deposit(msg.sender, poolId, amount);

ข้อมูลส่วนแบ่ง staking share จะถูกใส่ไว้ใน smart contract ที่ซึ่งจะไม่มีการสร้างเหรียญจากการ stake และข้อมูล share (ส่วนแบ่ง) จะสามารถดึงได้จาก userInfo จาก Fairlaunch contract

ผลตอบแทนจากการ stake จะไม่ได้รับอัตโนมัติและจะต้อง harvest ด้วยตนเอง แต่การฝากหรือถอนใน pool ที่ฝากอยู่จะทำให้เกิดการถอนผลตอบแทนอัตโนมัติเข้าในกระเป๋าของผู้ทำธุรกรรม และการรับผลตอบแทน ผู้ทำธุรกรรมต้องเรียกฟังชั่น harvest จาก Fairlaunch และระบุ pool id.

// Solidityaddress fairlaunchContractAddress = '0xA625AB01B08ce023B2a342Dbb12a16f2C8489A8F'; // ibBNB poolIFairLaunch fairlaunch = IFairLaunch(fairlaunchContractAddress);fairlaunch.harvest(poolId);

การถอนเหรียญที่ stake จาก pool ที่ผู้ใช้ฝากไว้ จำนวนเหรียญที่ผู้ใช้ฝากไว้จะต้องระบุในwithdraw ใน Fairlaunch contract

// Solidityaddress fairlaunchContractAddress = '0xA625AB01B08ce023B2a342Dbb12a16f2C8489A8F'; // ibBNB poolIFairLaunch fairlaunch = IFairLaunch(fairlaunchContractAddress);fairlaunch.withdraw(msg.sender, poolId, amount);

เหรียญที่ฝากไว้ จะถอนออกมาคืนให้กับผู้เรียกทำธุรกรรม และเหรียญผลตอบแทนใดๆที่สามารถ harvest ได้จะถูกส่งออกมาทั้งหมด

ทดลองกับ Alpaca Finance

ตอนนี้เราไม่ได้มีการสนับสนุนสำหรับ testnet environment เราแนะนำให้ทดลองโดยการ fork มาจาก mainnet ซึ่งสามารถทำได้ง่ายๆผ่าน Tenderly's Fork สำหรับข้อมูลและแอดเดรสที่เกี่ยวข้องโปรดอ้างอิงจาก https://github.com/alpaca-finance/bsc-alpaca-contract/blob/main/.mainnet.json

Last updated

Was this helpful?