Back

blockchain - solidity delegateCall: 把 中间人接收到的msg等context直接传给target

发布时间: 2024-03-27 07:55:00

refer to:
https://solidity-by-example.org/hacks/delegatecall/

https://solidity-by-example.org/delegatecall/

一句话:  caller -> middleman -> target 

会把 middle man 收到的 msg.sender ( caller address ) 赋值给target . 

不过奇怪的是我并没有收到该效果

middleman ( delegator)

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

// delegator
contract A {
  uint256 public num;
  address public sender;
  uint256 public value;
  bool public success;

  event setVarsEvent(bool success, bytes data);

  function setVars(address _contract, uint256 _num) public payable {
    num = _num + 200;
    sender = msg.sender;
    value = msg.value +100;
    (bool _success, bytes memory data) = _contract.delegatecall(
      abi.encodeWithSignature("setVars(uint256)", _num)
    );
    emit setVarsEvent(_success, data);
    success = _success;
  }
}

target:

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

// delegator
contract A {
  uint256 public num;
  address public sender;
  uint256 public value;
  bool public success;

  event setVarsEvent(bool success, bytes data);

  function setVars(address _contract, uint256 _num) public payable {
    num = _num + 200;
    sender = msg.sender;
    value = msg.value +100;
    (bool _success, bytes memory data) = _contract.delegatecall(
      abi.encodeWithSignature("setVars(uint256)", _num)
    );
    emit setVarsEvent(_success, data);
    success = _success;
  }
}
_@DESKTOP-GG23M21-wsl- test_solidity_truffle$ cat B.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

// target object
contract B {
  uint256 public num;
  address public sender;
  uint256 public value;

  function setVars(uint256 _num) public payable {
    num = _num;
    sender = msg.sender;
    value = msg.value;
  }
}

调用:

const Web3 = require('web3')
const fs = require('fs')

const delegatorAbi = JSON.parse(fs.readFileSync('A.json')).abi
const targetAbi = JSON.parse(fs.readFileSync('B.json')).abi
delegatorAddress = '0x959922be3caee4b8cd9a407cc3ac1c251c2007b1'
targetContractAddress = '0x0b306bf915c4d645ff596e518faf3f9669b97016'

async function main(){

  // step1. 初始化web3 实例,增加json rpc server
  const web3 = new Web3(
    new Web3.providers.HttpProvider(
      process.env.RPC_URL
    )
  )

  // step2. 创建signer
  const signer = web3.eth.accounts.privateKeyToAccount(  process.env.SIGNER_PRIVATE_KEY)
  web3.eth.accounts.wallet.add(signer)

  // step3. 创建contract, abi是关键
  let delegatorContract = new web3.eth.Contract( delegatorAbi, delegatorAddress)

  console.info("== before delegate call")
  let targetContract = new web3.eth.Contract( targetAbi, targetContractAddress)

  let num_of_target = await targetContract.methods.num().call()
  let sender_of_target = await targetContract.methods.sender().call()
  console.info("num_of_target: ", num_of_target, ",sender_of_target: ", sender_of_target)

  let num_of_delegator = await delegatorContract.methods.num().call()
  let sender_of_delegator = await delegatorContract.methods.sender().call()
  let success = await delegatorContract.methods.success().call()
  console.info("num_of_delegator: ", num_of_delegator, ",sender_of_delegator: ", sender_of_delegator, "success:" , success)

  // step4. 发起tx , 这里用到了签名
  const tx = delegatorContract.methods.setVars(targetContractAddress, 888)
  const receipt = await tx
    .send({ from: signer.address, gas: await tx.estimateGas() })
    .once("transactionHash" , (txHash) => {
      console.info("mining transaction...", txHash)
    })

  console.info("=== receipt: ", receipt)
  console.info("mined in block: ", receipt.blockNumber)
  console.log("==== events.setVarsEvent:", receipt.events.setVarsEvent)

  console.info("== after delegate call, target:")
  num_of_target = await targetContract.methods.num().call()
  sender_of_target = await targetContract.methods.sender().call()
  console.info("num: ", num_of_target, ",sender: ", sender_of_target)
  console.info("== after delegate call, delegator: ")
  num_of_delegator = await delegatorContract.methods.num().call()
  sender_of_delegator = await delegatorContract.methods.sender().call()
  success = await delegatorContract.methods.success().call()
  console.info("num_of_delegator: ", num_of_delegator, ",sender_of_delegator: ", sender_of_delegator, "success:" , success)

}

require('dotenv').config()
main()

结果:

 node callDelegatecall.js
== before delegate call
num_of_target:  0 ,sender_of_target:  0x0000000000000000000000000000000000000000
num_of_delegator:  0 ,sender_of_delegator:  0x0000000000000000000000000000000000000000 success: false
mining transaction... 0x1ef629ade87cb2cb32225ce32d01298983eb13beed1c7a44d45c770b022d0854
=== receipt:  {
  cumulativeGasUsed: 97478,
  logsBloom: '0x00000000000000000200000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000800000000000100000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000',
  status: true,
  type: '0x2',
  transactionHash: '0x1ef629ade87cb2cb32225ce32d01298983eb13beed1c7a44d45c770b022d0854',
  transactionIndex: 0,
  from: '0xf39fd6e51aad88f6f4ce6ab8827279cfffb92266',
  to: '0x959922be3caee4b8cd9a407cc3ac1c251c2007b1',
  contractAddress: null,
  gasUsed: 97478,
  effectiveGasPrice: 2592762735,
  blockHash: '0xd5363d01298f33581200509e4766da5709d82e17c5aca460badb86403272592e',
  blockNumber: 18,
  events: {
    setVarsEvent: {
      address: '0x959922bE3CAee4b8Cd9a407cc3ac1C251C2007B1',
      transactionHash: '0x1ef629ade87cb2cb32225ce32d01298983eb13beed1c7a44d45c770b022d0854',
      blockHash: '0xd5363d01298f33581200509e4766da5709d82e17c5aca460badb86403272592e',
      blockNumber: 18,
      logIndex: 0,
      transactionIndex: 0,
      removed: false,
      id: 'log_26dccc82',
      returnValues: [Result],
      event: 'setVarsEvent',
      signature: '0x83352043c8eb1b9a43d8cc12684caa28ee8676fdced21010335bdac4812051ac',
      raw: [Object]
    }
  }
}
mined in block:  18
==== events.setVarsEvent: {
  address: '0x959922bE3CAee4b8Cd9a407cc3ac1C251C2007B1',
  transactionHash: '0x1ef629ade87cb2cb32225ce32d01298983eb13beed1c7a44d45c770b022d0854',
  blockHash: '0xd5363d01298f33581200509e4766da5709d82e17c5aca460badb86403272592e',
  blockNumber: 18,
  logIndex: 0,
  transactionIndex: 0,
  removed: false,
  id: 'log_26dccc82',
  returnValues: Result { '0': true, '1': null, success: true, data: null },
  event: 'setVarsEvent',
  signature: '0x83352043c8eb1b9a43d8cc12684caa28ee8676fdced21010335bdac4812051ac',
  raw: {
    data: '0x000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000000000000000000000000000000000000400000000000000000000000000000000000000000000000000000000000000000',
    topics: [
      '0x83352043c8eb1b9a43d8cc12684caa28ee8676fdced21010335bdac4812051ac'
    ]
  }
}
== after delegate call, target:
num:  0 ,sender:  0x0000000000000000000000000000000000000000
== after delegate call, delegator:
num_of_delegator:  888 ,sender_of_delegator:  0xf39Fd6e51aad88F6F4ce6aB8827279cffFb92266 success: true

奇怪的是:(估计是我的代码有问题 )

1. delegator的setter 没有生效(应该 +200)

2. target contract 中,通过查询得到的结果,跟eventlog中的到的不一样。

Back