From 01e083c266db6ddff6a16ade049d5c0ed5f9b44c Mon Sep 17 00:00:00 2001 From: Rubilmax Date: Tue, 9 May 2023 10:09:29 +0200 Subject: [PATCH 1/2] feat(nonce): let nonce be overridden --- .env.example | 1 + README.md | 1 + script/ExecTransaction.s.sol | 15 ++++++++++++++- script/HashData.s.sol | 13 ++++++++++++- script/SafeTxDataBuilder.sol | 24 +----------------------- 5 files changed, 29 insertions(+), 25 deletions(-) diff --git a/.env.example b/.env.example index 89c92d0..9c2aad6 100644 --- a/.env.example +++ b/.env.example @@ -1,4 +1,5 @@ SAFE=0x0000000000000000000000000000000000000000 SENDER=0x0000000000000000000000000000000000000000 +SAFE_NONCE= FOUNDRY_ETH_RPC_URL=https://eth.llamarpc.com diff --git a/README.md b/README.md index 1251e25..c3685be 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,7 @@ - Install [Foundry](https://github.com/foundry-rs/foundry). - Run `make` to initialize the repository. - Create a `.env` file from the template [`.env.example`](./.env.example) file. + - Use the environment variable `SAFE_NONCE` to override a transaction's nonce. Leave it blank to use the default, latest Safe nonce. You can customize the RPC url used in [`foundry.tml`](./foundry.toml) under the `rpc_endpoint` section. This is useful if your Safe is not deployed on mainnet (which is the default chain used). diff --git a/script/ExecTransaction.s.sol b/script/ExecTransaction.s.sol index 93b99f4..8e80fde 100644 --- a/script/ExecTransaction.s.sol +++ b/script/ExecTransaction.s.sol @@ -17,7 +17,20 @@ contract ExecTransaction is SafeTxDataBuilder { function run() public { SafeTxData memory txData = loadSafeTxData(); - loadSignatures(hashData(txData)); + loadSignatures( + SAFE.getTransactionHash( + txData.to, + txData.value, + txData.data, + txData.operation, + txData.safeTxGas, + txData.baseGas, + txData.gasPrice, + txData.gasToken, + txData.refundReceiver, + NONCE + ) + ); signers.sort(); diff --git a/script/HashData.s.sol b/script/HashData.s.sol index 5454e1e..10d883f 100644 --- a/script/HashData.s.sol +++ b/script/HashData.s.sol @@ -9,7 +9,18 @@ contract HashData is SafeTxDataBuilder { function run() public { SafeTxData memory txData = loadSafeTxData(); - bytes32 dataHash = hashData(txData); + bytes32 dataHash = SAFE.getTransactionHash( + txData.to, + txData.value, + txData.data, + txData.operation, + txData.safeTxGas, + txData.baseGas, + txData.gasPrice, + txData.gasToken, + txData.refundReceiver, + NONCE + ); vm.writeFile(HASH_DATA_FILE, vm.toString(dataHash)); } diff --git a/script/SafeTxDataBuilder.sol b/script/SafeTxDataBuilder.sol index d1a300f..9a3bedb 100644 --- a/script/SafeTxDataBuilder.sol +++ b/script/SafeTxDataBuilder.sol @@ -45,7 +45,7 @@ contract SafeTxDataBuilder is Script, SignatureDecoder { constructor(address payable safe) { SAFE = GnosisSafe(safe); - NONCE = SAFE.nonce(); + NONCE = vm.envOr("SAFE_NONCE", SAFE.nonce()); THRESHOLD = SAFE.getThreshold(); DOMAIN_SEPARATOR = SAFE.domainSeparator(); } @@ -64,28 +64,6 @@ contract SafeTxDataBuilder is Script, SignatureDecoder { txData.refundReceiver = payable(json.readAddress("$.refundReceiver")); } - function hashData(SafeTxData memory txData) internal view returns (bytes32) { - bytes32 safeTxHash = keccak256( - abi.encode( - SAFE_TX_TYPEHASH, - txData.to, - txData.value, - keccak256(txData.data), - txData.operation, - txData.safeTxGas, - txData.baseGas, - txData.gasPrice, - txData.gasToken, - txData.refundReceiver, - NONCE - ) - ); - - bytes memory txHashData = abi.encodePacked(bytes1(0x19), bytes1(0x01), DOMAIN_SEPARATOR, safeTxHash); - - return keccak256(txHashData); - } - function decode(bytes32 dataHash, bytes memory signature) internal pure From c6ee78ae76191ebf0dc52ab3818dd60191833ec7 Mon Sep 17 00:00:00 2001 From: Rubilmax Date: Wed, 10 May 2023 12:01:23 +0200 Subject: [PATCH 2/2] refactor(script): make less changes --- script/ExecTransaction.s.sol | 15 +-------------- script/HashData.s.sol | 13 +------------ script/SafeTxDataBuilder.sol | 15 +++++++++++++++ 3 files changed, 17 insertions(+), 26 deletions(-) diff --git a/script/ExecTransaction.s.sol b/script/ExecTransaction.s.sol index 8e80fde..93b99f4 100644 --- a/script/ExecTransaction.s.sol +++ b/script/ExecTransaction.s.sol @@ -17,20 +17,7 @@ contract ExecTransaction is SafeTxDataBuilder { function run() public { SafeTxData memory txData = loadSafeTxData(); - loadSignatures( - SAFE.getTransactionHash( - txData.to, - txData.value, - txData.data, - txData.operation, - txData.safeTxGas, - txData.baseGas, - txData.gasPrice, - txData.gasToken, - txData.refundReceiver, - NONCE - ) - ); + loadSignatures(hashData(txData)); signers.sort(); diff --git a/script/HashData.s.sol b/script/HashData.s.sol index 10d883f..5454e1e 100644 --- a/script/HashData.s.sol +++ b/script/HashData.s.sol @@ -9,18 +9,7 @@ contract HashData is SafeTxDataBuilder { function run() public { SafeTxData memory txData = loadSafeTxData(); - bytes32 dataHash = SAFE.getTransactionHash( - txData.to, - txData.value, - txData.data, - txData.operation, - txData.safeTxGas, - txData.baseGas, - txData.gasPrice, - txData.gasToken, - txData.refundReceiver, - NONCE - ); + bytes32 dataHash = hashData(txData); vm.writeFile(HASH_DATA_FILE, vm.toString(dataHash)); } diff --git a/script/SafeTxDataBuilder.sol b/script/SafeTxDataBuilder.sol index 9a3bedb..c1ba5fb 100644 --- a/script/SafeTxDataBuilder.sol +++ b/script/SafeTxDataBuilder.sol @@ -64,6 +64,21 @@ contract SafeTxDataBuilder is Script, SignatureDecoder { txData.refundReceiver = payable(json.readAddress("$.refundReceiver")); } + function hashData(SafeTxData memory txData) internal view returns (bytes32) { + return SAFE.getTransactionHash( + txData.to, + txData.value, + txData.data, + txData.operation, + txData.safeTxGas, + txData.baseGas, + txData.gasPrice, + txData.gasToken, + txData.refundReceiver, + NONCE + ); + } + function decode(bytes32 dataHash, bytes memory signature) internal pure