Struct
構造委託呼叫
是否可以將結構作為參數傳遞給
delegatecall
?我有這個函式,它呼叫
delegatecall
並接受一個結構(0x 引號)作為參數,稍後在函式簽名和正確呼叫中使用:function executeDelegate(address _weth, address _contract, ZrxQuote memory _zrxQuote) private returns(uint, string memory) { console.log('spender address: ', _zrxQuote.spender); //----> testing (bool success, ) = logicContract.delegatecall( abi.encodeWithSignature('execute(address,address,uint256,ZrxQuote)', _weth, _contract, borrowed, _zrxQuote) ); console.log(success); require(success, 'Delegate Call failed'); return (0, ''); }
…但它不起作用並
false
每次都返回錯誤Delegate Call failed
。我有這個
console.log('spender address: ', _zrxQuote.spender);
來測試我的結構是否被成功讀取。此外,如果我完全刪除方程的結構(從函式、從
delegatecall
、從呼叫、從邏輯合約),則delegatecall
可以完美地工作,例如:function executeDelegate(address _weth, address _contract) private returns(uint, string memory) { (bool success, ) = logicContract.delegatecall( abi.encodeWithSignature('execute(address,address,uint256)', _weth, _contract, borrowed) ); require(success, 'Delegate Call failed'); return (0, ''); }
所以問題直接在於傳遞給的結構
delegatecall
,但我似乎無法在任何文件上找到問題所在(儲存變數是相同的)。這些是契約:
Proxy
://SPDX-License-Identifier: Unlicense pragma solidity ^0.5.0; pragma experimental ABIEncoderV2; import "@studydefi/money-legos/dydx/contracts/DydxFlashloanBase.sol"; import "@studydefi/money-legos/dydx/contracts/ICallee.sol"; import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import "hardhat/console.sol"; contract DydxFlashloaner is ICallee, DydxFlashloanBase { struct ZrxQuote { address sellTokenAddress; address buyTokenAddress; address spender; address swapTarget; bytes swapCallData; } struct MyCustomData { address token; uint256 repayAmount; } address public logicContract; uint public borrowed; constructor(address _logicContract, uint _borrowed) public { logicContract = _logicContract; borrowed = _borrowed; } /******* Part that matters ******/ function callFunction( address sender, Account.Info memory account, bytes memory data ) public { (MyCustomData memory mcd, ZrxQuote memory zrx) = abi.decode(data, (MyCustomData, ZrxQuote)); uint256 balOfLoanedToken = IERC20(mcd.token).balanceOf(address(this)); require( balOfLoanedToken >= mcd.repayAmount, "Not enough funds to repay dydx loan!" ); executeDelegate(mcd.token, address(this), zrx); //----> calls delegatecall } function executeDelegate(address _weth, address _contract, ZrxQuote memory _zrxQuote) private returns(uint, string memory) { console.log('this is: ', _zrxQuote.spender); (bool success, ) = logicContract.delegatecall( abi.encodeWithSignature('execute(address,address,uint256,ZrxQuote)', _weth, _contract, borrowed, _zrxQuote) ); console.log(success); require(success, 'Delegate Call failed'); return (0, ''); } /******* End ******/ function initiateFlashLoan( address _solo, address _token, uint256 _amount, address[] calldata _quoteAddr, bytes calldata _quoteData ) external { ZrxQuote memory zrxQuote = ZrxQuote({ sellTokenAddress: _quoteAddr[0], buyTokenAddress: _quoteAddr[1], spender: _quoteAddr[2], swapTarget: _quoteAddr[3], swapCallData: _quoteData }); ISoloMargin solo = ISoloMargin(_solo); uint256 marketId = _getMarketIdFromTokenAddress(_solo, _token); uint256 repayAmount = _getRepaymentAmountInternal(_amount); IERC20(_token).approve(_solo, repayAmount); Actions.ActionArgs[] memory operations = new Actions.ActionArgs[](3); operations[0] = _getWithdrawAction(marketId, _amount); operations[1] = _getCallAction( abi.encode(MyCustomData({token: _token, repayAmount: repayAmount}), zrxQuote) ); operations[2] = _getDepositAction(marketId, repayAmount); Account.Info[] memory accountInfos = new Account.Info[](1); accountInfos[0] = _getAccountInfo(); solo.operate(accountInfos, operations); } }
Logic
://SPDX-License-Identifier: Unlicense pragma solidity ^0.8.0; pragma abicoder v2; //tried with pragma experimental ABIEncoderV2 also import '@uniswap/v2-periphery/contracts/interfaces/IUniswapV2Router02.sol'; import './interfaces/MyILendingPool.sol'; import './interfaces/MyIERC20.sol'; import "hardhat/console.sol"; contract FlashLoaner { struct ZrxQuote { address sellTokenAddress; address buyTokenAddress; address spender; address swapTarget; bytes swapCallData; } struct MyCustomData { address token; uint256 repayAmount; } address public logicContract; uint public borrowed; function execute(address _weth, address _contract, uint256 _borrowed, ZrxQuote memory _zrxQuote) public { console.log('hello'); //I removed the code for simplicity, but it never executes, not even the 'hello'. }
謝謝您的幫助!
解決方案:
abi.encodeWithSignature
根據文件,必須將元組傳遞給: https ://docs.soliditylang.org/en/v0.8.6/abi-spec.html#mapping-solidity-to-abi-types所以它會是:
execute(address,address,uint256,(address, address, address, address, bytes))
…代替 :
execute(address,address,uint256,ZrxQuote)