From ccf766640d14a5f3840be7538864459e1e273bf0 Mon Sep 17 00:00:00 2001 From: Rubilmax Date: Wed, 6 Dec 2023 11:39:31 +0100 Subject: [PATCH] feat(signature): check not signed already --- Makefile | 1 + script/CheckNoSignature.sol | 14 +++++ script/ExecTransaction.sol | 57 ++++--------------- script/HashData.sol | 8 +-- ...SafeTxDataBuilder.sol => SafeTxScript.sol} | 2 +- script/SignatureScript.sol | 43 ++++++++++++++ 6 files changed, 72 insertions(+), 53 deletions(-) create mode 100644 script/CheckNoSignature.sol rename script/{SafeTxDataBuilder.sol => SafeTxScript.sol} (97%) create mode 100644 script/SignatureScript.sol diff --git a/Makefile b/Makefile index 014d39c..b91ecd9 100644 --- a/Makefile +++ b/Makefile @@ -16,6 +16,7 @@ hash: forge script script/HashData.sol sign\:%: hash + forge script script/CheckNoSignature.sol cast wallet sign --$* $$(cat data/hashData.txt) 1>> data/signatures.txt @echo "\033[0;32mTx signature successfully appended to data/signatures.txt" diff --git a/script/CheckNoSignature.sol b/script/CheckNoSignature.sol new file mode 100644 index 0000000..e9192ea --- /dev/null +++ b/script/CheckNoSignature.sol @@ -0,0 +1,14 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import "./SignatureScript.sol"; + +contract CheckNoSignature is SignatureScript { + function run() public { + SafeTxData memory txData = loadSafeTxData(); + + loadSignatures(hashData(txData)); + + require(signatureOf[SENDER].length == 0, "Already signed!"); + } +} diff --git a/script/ExecTransaction.sol b/script/ExecTransaction.sol index 9977b3b..7a6ac37 100644 --- a/script/ExecTransaction.sol +++ b/script/ExecTransaction.sol @@ -3,21 +3,25 @@ pragma solidity ^0.8.0; import {QuickSort} from "./libraries/QuickSort.sol"; -import {SafeTxDataBuilder, SafeTx, Enum} from "./SafeTxDataBuilder.sol"; +import "./SignatureScript.sol"; -contract ExecTransaction is SafeTxDataBuilder { +contract ExecTransaction is SignatureScript { using QuickSort for address[]; - address[] signers; - bytes[] signatures; - mapping(address => bytes) signatureOf; - function run() public { SafeTx memory safeTx; safeTx.data = loadSafeTxData(); loadSignatures(hashData(safeTx.data)); + uint256 nbSignatures = signatures.length; + require( + nbSignatures >= THRESHOLD, + string.concat( + "Not enough signatures (found: ", vm.toString(nbSignatures), "; expected: ", vm.toString(THRESHOLD), ")" + ) + ); + signers.sort(); for (uint256 i; i < signers.length; ++i) { @@ -39,45 +43,4 @@ contract ExecTransaction is SafeTxDataBuilder { safeTx.signatures ); } - - function loadSignatures(bytes32 dataHash) internal { - bytes memory line = bytes(vm.readLine(SIGNATURES_FILE)); - - while (line.length > 0 && signatures.length < THRESHOLD) { - parseSignature(dataHash, line); - - line = bytes(vm.readLine(SIGNATURES_FILE)); - } - - uint256 nbSignatures = signatures.length; - require( - nbSignatures >= THRESHOLD, - string.concat( - "Not enough signatures (found: ", vm.toString(nbSignatures), "; expected: ", vm.toString(THRESHOLD), ")" - ) - ); - } - - function parseSignature(bytes32 dataHash, bytes memory line) internal { - require( - line.length == 132, - string.concat( - "Malformed signature: ", string(line), " (length: ", vm.toString(line.length), "; expected: 132)" - ) - ); - - bytes memory hexSignature = new bytes(130); - for (uint256 j; j < 130; ++j) { - hexSignature[j] = line[j + 2]; - } - - bytes memory signature = vm.parseBytes(string(hexSignature)); - - (address signer, bytes32 r, bytes32 s, uint8 v) = decode(dataHash, signature); - require(signatureOf[signer].length == 0, string.concat("Duplicate signature: ", string(line))); - - signatureOf[signer] = abi.encodePacked(r, s, v + 4); - signatures.push(signature); - signers.push(signer); - } } diff --git a/script/HashData.sol b/script/HashData.sol index 257473e..f2a1c46 100644 --- a/script/HashData.sol +++ b/script/HashData.sol @@ -1,14 +1,12 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import {SafeTxDataBuilder, SafeTxData} from "./SafeTxDataBuilder.sol"; +import "./SafeTxScript.sol"; -contract HashData is SafeTxDataBuilder { +contract HashData is SafeTxScript { function run() public { SafeTxData memory txData = loadSafeTxData(); - bytes32 dataHash = hashData(txData); - - vm.writeFile(HASH_DATA_FILE, vm.toString(dataHash)); + vm.writeFile(HASH_DATA_FILE, vm.toString(hashData(txData))); } } diff --git a/script/SafeTxDataBuilder.sol b/script/SafeTxScript.sol similarity index 97% rename from script/SafeTxDataBuilder.sol rename to script/SafeTxScript.sol index 62dd678..ece8a58 100644 --- a/script/SafeTxDataBuilder.sol +++ b/script/SafeTxScript.sol @@ -26,7 +26,7 @@ struct SafeTx { bytes signatures; } -contract SafeTxDataBuilder is Script, SignatureDecoder { +contract SafeTxScript is Script, SignatureDecoder { using stdJson for string; string internal ROOT = vm.projectRoot(); diff --git a/script/SignatureScript.sol b/script/SignatureScript.sol new file mode 100644 index 0000000..eee32d4 --- /dev/null +++ b/script/SignatureScript.sol @@ -0,0 +1,43 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.0; + +import "./SafeTxScript.sol"; + +contract SignatureScript is SafeTxScript { + address[] signers; + bytes[] signatures; + mapping(address => bytes) signatureOf; + + function loadSignatures(bytes32 dataHash) internal { + bytes memory line = bytes(vm.readLine(SIGNATURES_FILE)); + + while (line.length > 0) { + parseSignature(dataHash, line); + + line = bytes(vm.readLine(SIGNATURES_FILE)); + } + } + + function parseSignature(bytes32 dataHash, bytes memory line) internal { + require( + line.length == 132, + string.concat( + "Malformed signature: ", string(line), " (length: ", vm.toString(line.length), "; expected: 132)" + ) + ); + + bytes memory hexSignature = new bytes(130); + for (uint256 j; j < 130; ++j) { + hexSignature[j] = line[j + 2]; + } + + bytes memory signature = vm.parseBytes(string(hexSignature)); + + (address signer, bytes32 r, bytes32 s, uint8 v) = decode(dataHash, signature); + require(signatureOf[signer].length == 0, string.concat("Duplicate signature: ", string(line))); + + signatureOf[signer] = abi.encodePacked(r, s, v + 4); + signatures.push(signature); + signers.push(signer); + } +}