发布时间: 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