Storage

為什麼這個對 DSProxy 的呼叫會失敗?

  • October 8, 2021

以這兩個合約為例,它們都部署在 Kovan 上並驗證了原始碼:

並採取此交易:

哪個已恢復,我不明白為什麼。

我想呼叫execute(address,bytes)函式DSProxy並傳入以下參數:

  • 0xE3CD2e7a628b57d3e50c5f7B921182f676721bDF
  • 0xb081b4eb(“wrapEth”函式的簽名)
  • 還發送一些 ETH

有效地呼叫wrapEth中定義的應付函式TargetContract,但通過DELEGATECALLDSProxy功能。

在 ethers.js 的幫助下,我為這個多合約呼叫生成了 calldata,它看起來像這樣:

0x1cff79cd000000000000000000000000e3cd2e7a628b57d3e50c5f7b921182f676721bdf00000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000004b081b4eb00000000000000000000000000000000000000000000000000000000

不幸的是,當我通過 MetaMask、MyCrypto 或任何其他錢包將此呼叫數據轉發到 Kovan 測試網時,我收到了還原的交易。雖然我覺得上面的 calldata 是正確的,但我嘗試調整字節的最後一部分(函式簽名)以防 Ethers 中存在錯誤,但沒有運氣。

你能看到這裡的錯誤嗎?

DSProxy 使用delegatecall 呼叫目標合約,因此 wrapEth您在內部訪問的是DSProxy 儲存而不是TargetContract。

您正在weth從錯誤的儲存中讀取並使用其他東西作為地址。

weth一種可能的解決方案是作為參數傳遞。

contract TargetContract {
   constructor() {}
   
   function wrapEth(WethInterface weth) public payable {
       weth.deposit{ value: msg.value }();
   }
}

另一種解決方案是讓 TargetContract 從 DSProxy 繼承並使用函式來初始化 we.

contract TargetContract is DSProxy {

   WethInterface public weth;

   function initialize(WethInterface _weth) public {
       weth = _weth;
   }
   
   function wrapEth() public payable {
       weth.deposit{ value: msg.value }();
   }
}

引用自:https://ethereum.stackexchange.com/questions/90723