使用委託呼叫減少代幣轉移
我正在嘗試解決“玩具”應用程序中的循環依賴以測試可升級契約。
我有一份包含 ERC20 代幣的財政部合約和一組可升級的**Action合約。Action 合約與其他 DeFi 建構塊互動,例如在 Yearn 上進行質押、在 Uniswap 上進行交換、在 Olympus 上購買債券等,但合約本身並不擁有任何代幣。現在,為了節省燃料,我想避免將代幣從財政部轉移到 Action 合約,然後再轉移到外部 DeFi 協議,所以我想出了一個可能的解決方案。
在財政部有一個特殊功能,僅限於行動契約,它通過財政部的代表呼叫回調行動,從而完全控制資金。
一個方案
User -> Action -> Treasury -> (delegatecall) Action -> external DeFi contract
國庫內
function relayCall(address to, bytes calldata data) external onlyActions { require(isActionContract[to], "Err: can only call an action"); (success,) = to.delegatecall(data); require(success); }
行動內部
function makeCall(...) external { bytes memory data = abi.encodeWithSelector(Action.swap.selector, ...); ITreasury(treasury).relayCall(address(this), data); } function swap(address token0, address token1, address recipient, uint256 amount) external { uniRouter.swapExactTokensForTokens(...); }
這種方法的優點是它與可升級的 Action 合約兼容,它非常安全,因為接收者被列入白名單並且委託呼叫範圍在 Action 程式碼中是固定的,最大的缺點是循環依賴
Action -> Treasury -> Action
。
您描述的委託呼叫模式非常常見,並且被 Gnosis Safe、Gelato、DSProxy 和 InstaDapp 等合約使用。
Gnosis Safe 實際上與可以觸發的模組有一個非常相似的模式
delegatecalls
。通過將合約拆分為“觸發器”和“動作”,可以輕鬆解決循環依賴問題。但就我個人而言,我也不認為循環依賴會導致任何問題。
分離的意義在於避免潛在的不想要的狀態變化。例如,在“Action”中沒有任何狀態以避免調整“Treasury”狀態是有意義的。
參考:
您是否必須從 Action 啟動操作?為什麼不直接刪除
makeCall
,並做切入點Treasury’srelayCall
?