From 55752ac89a45fa05282ec4b7661b6f8f914587e8 Mon Sep 17 00:00:00 2001 From: Valentin Staykov <79150443+V-Staykov@users.noreply.github.com> Date: Mon, 5 Aug 2024 11:24:36 +0300 Subject: [PATCH] print values in DELEGATECALL on callTracer + added contract for testing (#914) --- eth/tracers/native/call.go | 4 + .../contracts/DelegateCalled.sol | 30 ++++++++ .../contracts/DelegateCaller.sol | 74 +++++++++++++++++++ zk/debug_tools/test-contracts/package.json | 3 +- .../test-contracts/scripts/delegate-call.js | 31 ++++++++ 5 files changed, 141 insertions(+), 1 deletion(-) create mode 100644 zk/debug_tools/test-contracts/contracts/DelegateCalled.sol create mode 100644 zk/debug_tools/test-contracts/contracts/DelegateCaller.sol create mode 100644 zk/debug_tools/test-contracts/scripts/delegate-call.js diff --git a/eth/tracers/native/call.go b/eth/tracers/native/call.go index c66d15cfe49..b7f2de4dd1d 100644 --- a/eth/tracers/native/call.go +++ b/eth/tracers/native/call.go @@ -211,6 +211,10 @@ func (t *callTracer) CaptureEnter(typ vm.OpCode, from libcommon.Address, to libc } if value != nil { call.Value = value.ToBig() + } else { + if typ == vm.DELEGATECALL { + call.Value = t.callstack[len(t.callstack)-1].Value + } } t.callstack = append(t.callstack, call) } diff --git a/zk/debug_tools/test-contracts/contracts/DelegateCalled.sol b/zk/debug_tools/test-contracts/contracts/DelegateCalled.sol new file mode 100644 index 00000000000..fb96f88369a --- /dev/null +++ b/zk/debug_tools/test-contracts/contracts/DelegateCalled.sol @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.7.0 <0.9.0; + +contract DelegateCalled { + uint256 num; + address sender; + uint256 value; + + function setVars(uint256 _num) public payable { + num = _num; + sender = msg.sender; + value = msg.value; + } + + function setVarsViaCall(uint256 _num) public payable { + bool ok; + (ok, ) = address(this).call( + abi.encodeWithSignature("setVars(uint256)", _num) + ); + require(ok, "failed to perform call"); + } + + function getVars() public view returns (uint256, address, uint256) { + return (num, sender, value); + } + + function getVarsAndVariable(uint256 _num) public view returns (uint256, address, uint256, uint256) { + return (num, sender, value, _num); + } +} \ No newline at end of file diff --git a/zk/debug_tools/test-contracts/contracts/DelegateCaller.sol b/zk/debug_tools/test-contracts/contracts/DelegateCaller.sol new file mode 100644 index 00000000000..cebda7bd72d --- /dev/null +++ b/zk/debug_tools/test-contracts/contracts/DelegateCaller.sol @@ -0,0 +1,74 @@ +// SPDX-License-Identifier: GPL-3.0 +pragma solidity >=0.7.0 <0.9.0; + +contract DelegateCaller { + function call(address _contract, uint _num) public payable { + bool ok; + (ok, ) = _contract.call( + abi.encodeWithSignature("setVars(uint256)", _num) + ); + require(ok, "failed to perform call"); + } + + function delegateCall(address _contract, uint _num) public payable { + bool ok; + (ok, ) = _contract.delegatecall( + abi.encodeWithSignature("setVars(uint256)", _num) + ); + require(ok, "failed to perform delegate call"); + } + + function staticCall(address _contract) public payable { + bool ok; + bytes memory result; + (ok, result) = _contract.staticcall( + abi.encodeWithSignature("getVars()") + ); + require(ok, "failed to perform static call"); + + uint256 num; + address sender; + uint256 value; + + (num, sender, value) = abi.decode(result, (uint256, address, uint256)); + } + + function invalidStaticCallMoreParameters(address _contract) view public { + bool ok; + (ok,) = _contract.staticcall( + abi.encodeWithSignature("getVarsAndVariable(uint256)", 1, 2) + ); + require(!ok, "static call was supposed to fail with more parameters"); + } + + function invalidStaticCallLessParameters(address _contract) view public { + bool ok; + (ok,) = _contract.staticcall( + abi.encodeWithSignature("getVarsAndVariable(uint256)") + ); + require(!ok, "static call was supposed to fail with less parameters"); + } + + function invalidStaticCallWithInnerCall(address _contract) view public { + bool ok; + (ok,) = _contract.staticcall( + abi.encodeWithSignature("getVarsAndVariable(uint256)") + ); + require(!ok, "static call was supposed to fail with less parameters"); + } + + function multiCall(address _contract, uint _num) public payable { + call(_contract, _num); + delegateCall(_contract, _num); + staticCall(_contract); + } + + function preEcrecover_0() pure public { + bytes32 messHash = 0x456e9aea5e197a1f1af7a3e85a3212fa4049a3ba34c2289b4c860fc0b0c64ef3; + uint8 v = 28; + bytes32 r = 0x9242685bf161793cc25603c231bc2f568eb630ea16aa137d2664ac8038825608; + bytes32 s = 0x4f8ae3bd7535248d0bd448298cc2e2071e56992d0774dc340c368ae950852ada; + + ecrecover(messHash, v, r, s); + } +} \ No newline at end of file diff --git a/zk/debug_tools/test-contracts/package.json b/zk/debug_tools/test-contracts/package.json index 44fde8347d4..7dc842b2cf6 100644 --- a/zk/debug_tools/test-contracts/package.json +++ b/zk/debug_tools/test-contracts/package.json @@ -13,7 +13,8 @@ "emitlog:bali": "npx hardhat compile && npx hardhat run scripts/emitlog.js --network bali", "emitlog:cardona": "npx hardhat compile && npx hardhat run scripts/emitlog.js --network cardona", "emitlog:mainnet": "npx hardhat compile && npx hardhat run scripts/emitlog.js --network mainnet", - "spam:local": "npx hardhat compile && npx hardhat run scripts/spam-transactions.js --network local" + "spam:local": "npx hardhat compile && npx hardhat run scripts/spam-transactions.js --network local", + "delegateCall:local": "npx hardhat compile && npx hardhat run scripts/delegate-call.js --network local" }, "keywords": [], "author": "", diff --git a/zk/debug_tools/test-contracts/scripts/delegate-call.js b/zk/debug_tools/test-contracts/scripts/delegate-call.js new file mode 100644 index 00000000000..a359f9890ab --- /dev/null +++ b/zk/debug_tools/test-contracts/scripts/delegate-call.js @@ -0,0 +1,31 @@ +// deploys contracts and calls a method to produce delegate call +async function main() { +try { + const DelegateCalled = await hre.ethers.getContractFactory("DelegateCalled"); + const DelegateCaller = await hre.ethers.getContractFactory("DelegateCaller"); + + // Deploy the contracts + const calledContract = await DelegateCalled.deploy(); + const callerContract = await DelegateCaller.deploy(); + + // Wait for the deployment transactions to be mined + await calledContract.waitForDeployment(); + await callerContract.waitForDeployment(); + + console.log(`DelegateCalled deployed to: ${await calledContract.getAddress()}`); + console.log(`DelegateCaller deployed to: ${await callerContract.getAddress()}`); + + const delegateCallResult = await callerContract.delegateCall(calledContract.getAddress(), 1); + console.log('delegateCallResult method call transaction: ', delegateCallResult.hash); + } catch (error) { + console.error(error.toString()); + process.exit(1); + } +} + +main() + .then(() => process.exit(0)) + .catch(error => { + console.error(error); + process.exit(1); + }); \ No newline at end of file