From 63247f11dd3e3c62dbad9005151ce30e86357ed0 Mon Sep 17 00:00:00 2001 From: TuDo1403 Date: Thu, 28 Dec 2023 18:14:02 +0700 Subject: [PATCH] feat: add OnchainExecutor to debug and broadcast raw data --- .broadcast.env.example | 12 ++++++ .debug.env.example | 4 +- broadcast.sh | 31 ++++++++++++++++ debug.sh | 14 ++----- script/BaseMigration.s.sol | 4 +- script/OnchainDebugger.s.sol | 41 --------------------- script/OnchainExecutor.s.sol | 71 ++++++++++++++++++++++++++++++++++++ 7 files changed, 122 insertions(+), 55 deletions(-) create mode 100644 .broadcast.env.example create mode 100755 broadcast.sh delete mode 100644 script/OnchainDebugger.s.sol create mode 100644 script/OnchainExecutor.s.sol diff --git a/.broadcast.env.example b/.broadcast.env.example new file mode 100644 index 0000000..e3b8d57 --- /dev/null +++ b/.broadcast.env.example @@ -0,0 +1,12 @@ +# Fork block number to debug +BLOCK=0x0 +# Caller +FROM=0x0000000000000000000000000000000000000000 +# Callee +TO=0x0000000000000000000000000000000000000000 +# Sent Value +VALUE=0 +# Gas Amount +GAS=0 +# Call Data +CALLDATA=0x0 diff --git a/.debug.env.example b/.debug.env.example index 74bfec6..e3b8d57 100644 --- a/.debug.env.example +++ b/.debug.env.example @@ -5,6 +5,8 @@ FROM=0x0000000000000000000000000000000000000000 # Callee TO=0x0000000000000000000000000000000000000000 # Sent Value -VALUE=0x27cdb0997a65b2de99 +VALUE=0 +# Gas Amount +GAS=0 # Call Data CALLDATA=0x0 diff --git a/broadcast.sh b/broadcast.sh new file mode 100755 index 0000000..e7c12c3 --- /dev/null +++ b/broadcast.sh @@ -0,0 +1,31 @@ +# Source (or "dot") the .env file to load environment variables +if [ -f .env ]; then + source .broadcast.env +else + echo "Error: .broadcast.env file not found." +fi + +verify_arg="" +extra_argument="" + +for arg in "$@"; do + case $arg in + --trezor) + extra_argument+=trezor@ + ;; + *) ;; + esac +done + +# Remove the @ character from the end of extra_argument +extra_argument="${extra_argument%%@}" + +echo Broadcast Tx... +echo From: ${FROM} +echo To: ${TO} +echo Value: ${VALUE} +echo GasAmount: ${GAS} +echo Calldata: +cast pretty-calldata ${CALLDATA} +calldata=$(cast calldata 'broadcast(address,address,uint256,uint256,bytes)' ${FROM} ${TO} ${GAS} ${VALUE} ${CALLDATA}) +forge script ${verify_arg} ${@} -g 200 OnchainExecutor --sig 'run(bytes,string)' ${calldata} "${extra_argument}" \ No newline at end of file diff --git a/debug.sh b/debug.sh index 55a2636..dcaeab7 100755 --- a/debug.sh +++ b/debug.sh @@ -7,21 +7,12 @@ fi verify_arg="" extra_argument="" -op_command="op run --env-file="./.env" --" for arg in "$@"; do case $arg in --trezor) - op_command="" extra_argument+=trezor@ ;; - --broadcast) - op_command="op run --env-file="./.env" --" - ;; - --log) - set -- "${@/#--log/}" - extra_argument+=log@ - ;; *) ;; esac done @@ -33,7 +24,8 @@ echo Debug Tx... echo From: ${FROM} echo To: ${TO} echo Value: ${VALUE} +echo GasAmount: ${GAS} echo Calldata: cast pretty-calldata ${CALLDATA} -calldata=$(cast calldata 'trace(uint256,address,address,uint256,bytes)' ${BLOCK} ${FROM} ${TO} ${VALUE} ${CALLDATA}) -${op_command} forge script ${verify_arg} --legacy ${@} OnchainDebugger --sig 'run(bytes,string)' ${calldata} "${extra_argument}" +calldata=$(cast calldata 'trace(uint256,address,address,uint256,uint256,bytes)' ${BLOCK} ${FROM} ${TO} ${GAS} ${VALUE} ${CALLDATA}) +forge script ${verify_arg} --legacy ${@} OnchainExecutor --sig 'run(bytes,string)' ${calldata} "${extra_argument}" diff --git a/script/BaseMigration.s.sol b/script/BaseMigration.s.sol index 83f832d..416d2f1 100644 --- a/script/BaseMigration.s.sol +++ b/script/BaseMigration.s.sol @@ -9,7 +9,7 @@ import { import { LibString } from "../lib/solady/src/utils/LibString.sol"; import { console, LibSharedAddress, StdStyle, IScriptExtended, ScriptExtended } from "./extensions/ScriptExtended.s.sol"; import { IArtifactFactory, ArtifactFactory } from "./ArtifactFactory.sol"; -import { OnchainDebugger } from "./OnchainDebugger.s.sol"; // cheat to load artifact to parent `out` directory +import { OnchainExecutor } from "./OnchainExecutor.s.sol"; // cheat to load artifact to parent `out` directory import { IMigrationScript } from "./interfaces/IMigrationScript.sol"; import { LibProxy } from "./libraries/LibProxy.sol"; import { DefaultContract } from "./utils/DefaultContract.sol"; @@ -272,4 +272,4 @@ abstract contract BaseMigration is ScriptExtended { function _setDependencyDeployScript(TContract contractType, address deployScript) internal virtual { _deployScript[contractType] = IMigrationScript(deployScript); } -} +} \ No newline at end of file diff --git a/script/OnchainDebugger.s.sol b/script/OnchainDebugger.s.sol deleted file mode 100644 index a63ac0c..0000000 --- a/script/OnchainDebugger.s.sol +++ /dev/null @@ -1,41 +0,0 @@ -// SPDX-License-Identifier: MIT -pragma solidity ^0.8.19; - -import { StdStyle } from "forge-std/StdStyle.sol"; -import { console2 as console } from "forge-std/console2.sol"; -import { ScriptExtended } from "./extensions/ScriptExtended.s.sol"; -import { BaseGeneralConfig } from "./BaseGeneralConfig.sol"; -import { LibErrorHandler } from "../lib/contract-libs/src/LibErrorHandler.sol"; - -contract OnchainDebugger is ScriptExtended { - using LibErrorHandler for bool; - - modifier rollFork(uint256 forkBlock) { - if (forkBlock != 0) { - vm.rollFork(forkBlock); - console.log("OnchainDebugger: Rolling to fork block number:", forkBlock); - } - _; - } - - function _configByteCode() internal virtual override returns (bytes memory) { - return abi.encodePacked(type(BaseGeneralConfig).creationCode, abi.encode("", "deployments/")); - } - - function trace(uint256 forkBlock, address from, address to, uint256 value, bytes calldata callData) - public - rollFork(forkBlock) - { - vm.prank(from); - (bool success, bytes memory returnOrRevertData) = to.call{ value: value }(callData); - if (!success) { - string[] memory commandInput = new string[](3); - commandInput[0] = "cast"; - commandInput[1] = "4byte-decode"; - commandInput[2] = vm.toString(returnOrRevertData); - bytes memory decodedError = vm.ffi(commandInput); - console.log(StdStyle.red(string(decodedError))); - } - success.handleRevert(msg.sig, returnOrRevertData); - } -} diff --git a/script/OnchainExecutor.s.sol b/script/OnchainExecutor.s.sol new file mode 100644 index 0000000..44997fa --- /dev/null +++ b/script/OnchainExecutor.s.sol @@ -0,0 +1,71 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import { StdStyle } from "../lib/forge-std/src/StdStyle.sol"; +import { console2 as console } from "../lib/forge-std/src/console2.sol"; +import { ScriptExtended } from "./extensions/ScriptExtended.s.sol"; +import { BaseGeneralConfig } from "./BaseGeneralConfig.sol"; +import { LibErrorHandler } from "../lib/contract-libs/src/LibErrorHandler.sol"; + +contract OnchainExecutor is ScriptExtended { + using LibErrorHandler for bool; + + modifier rollFork(uint256 forkBlock) { + if (forkBlock != 0) { + vm.rollFork(forkBlock); + console.log("OnchainExecutor: Rolling to fork block number:", forkBlock); + } + _; + } + + function _configByteCode() internal virtual override returns (bytes memory) { + return abi.encodePacked(type(BaseGeneralConfig).creationCode, abi.encode("", "deployments/")); + } + + function trace(uint256 forkBlock, address from, address to, uint256 gas, uint256 value, bytes calldata callData) + public + rollFork(forkBlock) + { + vm.prank(from); + _sendRawTransaction(to, gas, value, callData); + } + + function broadcast(address from, address to, uint256 gas, uint256 value, bytes calldata callData) public { + vm.broadcast(from); + _sendRawTransaction(to, gas, value, callData); + } + + function _sendRawTransaction(address to, uint256 gas, uint256 value, bytes calldata callData) internal { + bool success; + bytes memory returnOrRevertData; + + (success, returnOrRevertData) = + gas == 0 ? to.call{ value: value }(callData) : to.call{ value: value, gas: gas }(callData); + + if (!success) { + if (returnOrRevertData.length != 0) { + string[] memory commandInput = new string[](3); + commandInput[0] = "cast"; + commandInput[1] = returnOrRevertData.length > 4 ? "4byte-decode" : "4byte"; + commandInput[2] = vm.toString(returnOrRevertData); + bytes memory decodedError = vm.ffi(commandInput); + console.log(StdStyle.red(string.concat("Decoded Error: ", string(decodedError)))); + } else { + console.log(StdStyle.red("Evm Error!")); + } + } else { + console.log(StdStyle.green("OnchainExecutor: Call Executed Successfully!")); + } + } + + function _logDecodedError(bytes memory returnOrRevertData) internal { + if (returnOrRevertData.length != 0) { + string[] memory commandInput = new string[](3); + commandInput[0] = "cast"; + commandInput[1] = returnOrRevertData.length > 4 ? "4byte-decode" : "4byte"; + commandInput[2] = vm.toString(returnOrRevertData); + bytes memory decodedError = vm.ffi(commandInput); + console.log(StdStyle.red(string.concat("Decoded Error: ", string(decodedError)))); + } + } +}