Solidity_delegatecall把中间人接收到的msg等context直接传给target
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中的到的不一样。
