您好,登錄后才能下訂單哦!
這篇文章給大家介紹如何在DeFi應用中集成Curve協議,內容非常詳細,感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。
Curve.Fi是一組規模龐大的DEFi協議,這個教程的目的是幫助你關注智能合約開發的現代方法,以及如何在自己的Defi應用中集成Curve.Fi這種大型協議的關鍵點。
是的,我已經說過我們將深入研究代碼。盡管我們不是在談論AMM模型的數學運算,也不是在Curve.Fi合約中使用的其他一些特定技巧,但是我們仍然需要了解一些內容。當然,這不是在談論成功的DeFi開發-我沒有給出提示。這是我經驗的一部分,在這里我將分享一些有關Curve智能合約的基本架構以及我們如何與這些架構集成的知識。實際上,下圖中包含了本教程的全部內容:
我們研究的是Y-Pool,它以一種簡單明了的方式組織。存款(Deposit)合約將你的資金打包成Y-Token,然后將其發送到兌換(Swap)合約,兌換合約為用戶生成LP代幣。如果你要提取流通性份額以及所賺取的收益,則合約會執行相同的操作,但是方式相反。這一切都與金融合約有關(當然,如果我們對池平衡和股數計算背后的復雜邏輯選擇視而不見)。
此外,我們還有Gauge和Minter合同,它們是Curve.Fi DAO的一部分。這些合約使你可以獲得CRV代幣獎勵并將其抵押,以便獲得協議治理的投票權。
在我們充分了解這些需要交互的合約后,就可以開始我們的開發了。
你可能還記得,我們正在處理一些使用Vyper開發的外部合約。為了與這些合約交互,我們需要創建一些接口。這并不是最困難的工作:只需要仔細查看原始合約并挑出將要調用的方法即可。
讓我們將從存款合約開始。我們需要資金進出的方法,以及一些數據查看界面(例如,查看已注冊的代幣及其Y對應代幣)。
contract ICurveFi_DepositY { function add_liquidity(uint256[4] calldata uamounts, uint256 min_mint_amount) external; function remove_liquidity(uint256 _amount, uint256[4] calldata min_uamounts) external; function remove_liquidity_imbalance(uint256[4] calldata uamounts, uint256 max_burn_amount) external; function coins(int128 i) external view returns (address); function underlying_coins(int128 i) external view returns (address); function underlying_coins() external view returns (address[4] memory); function curve() external view returns (address); function token() external view returns (address); }
然后用相同的方法處理兌換合約(你可能還記得,該合約為用戶鑄造LP代幣)。
contract ICurveFi_Gauge { function lp_token() external view returns(address); function crv_token() external view returns(address); function balanceOf(address addr) external view returns (uint256); function deposit(uint256 _value) external; function withdraw(uint256 _value) external; function claimable_tokens(address addr) external returns (uint256); function minter() external view returns(address); //use minter().mint(gauge_addr) to claim CRV function integrate_fraction(address _for) external view returns(uint256); function user_checkpoint(address _for) external returns(bool); }
現在該處理DAO的主要合約-流動性計量器合約。它執行復雜的功能,但我們主要需要用于創建檢查點的方法以及查看Minter和CRV代幣地址的界面。
contract ICurveFi_Gauge { function lp_token() external view returns(address); function crv_token() external view returns(address); function balanceOf(address addr) external view returns (uint256); function deposit(uint256 _value) external; function withdraw(uint256 _value) external; function claimable_tokens(address addr) external returns (uint256); function minter() external view returns(address); //use minter().mint(gauge_addr) to claim CRV function integrate_fraction(address _for) external view returns(uint256); function user_checkpoint(address _for) external returns(bool); }
還有從用戶界面的角度來看其實是最簡單的合約— Minter。實際上,我們只需要minter方法本身,以及一個可以查看有效獎勵的方法。
contract ICurveFi_Minter { function mint(address gauge_addr) external; function minted(address _for, address gauge_addr) external view returns(uint256); function toggle_approve_mint(address minting_user) external; function token() external view returns(address); }
最后一個是YToken接口,不過它并非最不重要,因為我們要交互的就是Curve的Y池。YToken是一個簡單的ERC20接口,幾乎沒有其他額外的方法。
contract IYERC20 { //ERC20 functions // // //Y-token functions function deposit(uint256 amount) external; function withdraw(uint256 shares) external; function getPricePerFullShare() external view returns (uint256); function token() external returns(address); }
現在我們準備創建一些代碼來與此協議交互。
我們的實驗合約的主要目標是展示如何將Curve協議作為資金流終點來組織資金的流動。因此,我們將有兩種主要方法:一種用于完整的存款流程(具有從Curve.Fi可獲得的所有好處),另一種用于提款流程。
讓我們從存款開始。
function multiStepDeposit(uint256[4] memory _amounts) public { address[4] memory stablecoins = ICurveFi_DepositY(curveFi_Deposit).underlying_coins(); for (uint256 i = 0; i < stablecoins.length; i++) { IERC20(stablecoins[i]).safeTransferFrom(_msgSender(), address(this), _amounts[i]); IERC20(stablecoins[i]).safeApprove(curveFi_Deposit, _amounts[i]); } //Step 1 - deposit stablecoins and get Curve.Fi LP tokens ICurveFi_DepositY(curveFi_Deposit).add_liquidity(_amounts, 0); //0 to mint all Curve has to //Step 2 - stake Curve LP tokens into Gauge and get CRV rewards uint256 curveLPBalance = IERC20(curveFi_LPToken).balanceOf(address(this)); IERC20(curveFi_LPToken).safeApprove(curveFi_LPGauge, curveLPBalance); ICurveFi_Gauge(curveFi_LPGauge).deposit(curveLPBalance); //Step 3 - get all the rewards (and make whatever you need with them) crvTokenClaim(); uint256 crvAmount = IERC20(curveFi_CRVToken).balanceOf(address(this)); IERC20(curveFi_CRVToken).safeTransfer(_msgSender(), crvAmount); }
正像你看見的,我們在multiStepDeposit()
方法中執行了幾個動作。首先,將我們的資金(在本例中為選定的穩定幣)存入Deposit合約,以便接收Curve LP代幣。第二步是將LP代幣存入Gauge合約,以便獲得CRV代幣獎勵。第三步取決于你自己 —— 可以使用CRV獎勵做任何想做的事情。
實際上,相同的方案也適用于multiStepWithdraw()方法,但順序相反。
function multiStepWithdraw(uint256[4] memory _amounts) public { address[4] memory stablecoins = ICurveFi_DepositY(curveFi_Deposit).underlying_coins(); //Step 1 - Calculate amount of Curve LP-tokens to unstake uint256 nWithdraw; uint256 i; for (i = 0; i < stablecoins.length; i++) { nWithdraw = nWithdraw.add(normalize(stablecoins[i], _amounts[i])); } uint256 withdrawShares = calculateShares(nWithdraw); //Check if you can re-use unstaked LP tokens uint256 notStaked = curveLPTokenUnstaked(); if (notStaked > 0) { withdrawShares = withdrawShares.sub(notStaked); } //Step 2 - Unstake Curve LP tokens from Gauge ICurveFi_Gauge(curveFi_LPGauge).withdraw(withdrawShares); //Step 3 - Withdraw stablecoins from CurveDeposit IERC20(curveFi_LPToken).safeApprove(curveFi_Deposit, withdrawShares); ICurveFi_DepositY(curveFi_Deposit).remove_liquidity_imbalance(_amounts, withdrawShares); //Step 4 - Send stablecoins to the requestor // }
是的,解決方案非常簡單,某種程度上看起來很笨拙,并且存在幾個明顯的漏洞 —— 雖然這些代碼僅用于演示目的。你可以添加所需的所有檢查,將階段拆分為不同的方法,為方法設置不同的權限,并執行使你的DeFi項目成功所需的所有其他工作。
教程的最后一步是添加幾個單元測試,以驗證解決方案是否有效。雖然在這里我們面臨幾個問題。第一個(也是主要的)問題是Curve.Fi協議環境。為了測試解決方案,我們需要在本地環境(在我們的例子中為Ganache)上模擬完整的Curve協議。由于這是一組復雜的合約,而且是在Vyper上編寫的,因此我們不能僅將它們編譯并部署到我們的Ganache節點中。
我已經完成了一些工作,并準備了Curve協議的測試存根,可以將其與你的項目一起編譯并部署你的測試網上。除了出于測試目的的幾種簡化,這些測試存根與原始的Curve協議完全相同。你可以在這里下載。
因此,我們可以跳過將Vyper代碼轉換為可測試的Solidity合約的無聊部分,直接查看單元測試的輸出:
關于如何在DeFi應用中集成Curve協議就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。