From d5d1c1c2bb76d9f4181b6bb7a6e10030c304a3b4 Mon Sep 17 00:00:00 2001 From: Rubilmax Date: Wed, 6 Dec 2023 09:56:16 +0100 Subject: [PATCH 1/2] fix(lib): update deps --- LICENSE.txt | 2 +- Makefile | 6 +++--- lib/forge-std | 2 +- lib/safe-contracts | 2 +- remappings.txt | 3 --- script/{ExecTransaction.s.sol => ExecTransaction.sol} | 0 script/{HashData.s.sol => HashData.sol} | 0 script/SafeTxDataBuilder.sol | 10 +++++----- 8 files changed, 11 insertions(+), 14 deletions(-) delete mode 100644 remappings.txt rename script/{ExecTransaction.s.sol => ExecTransaction.sol} (100%) rename script/{HashData.s.sol => HashData.sol} (100%) diff --git a/LICENSE.txt b/LICENSE.txt index 5172bab..f834f9a 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2023 Merlin Egalite +Copyright (c) 2023 Morpho Labs Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/Makefile b/Makefile index 8346dad..014d39c 100644 --- a/Makefile +++ b/Makefile @@ -13,17 +13,17 @@ tx: npx create-safe-tx hash: - forge script script/HashData.s.sol + forge script script/HashData.sol sign\:%: hash cast wallet sign --$* $$(cat data/hashData.txt) 1>> data/signatures.txt @echo "\033[0;32mTx signature successfully appended to data/signatures.txt" simulate\:%: - forge script script/ExecTransaction.s.sol --$* + forge script script/ExecTransaction.sol --$* exec\:%: - forge script script/ExecTransaction.s.sol --$* --broadcast + forge script script/ExecTransaction.sol --$* --broadcast clean: mkdir -p data diff --git a/lib/forge-std b/lib/forge-std index fc560fa..2f11269 160000 --- a/lib/forge-std +++ b/lib/forge-std @@ -1 +1 @@ -Subproject commit fc560fa34fa12a335a50c35d92e55a6628ca467c +Subproject commit 2f112697506eab12d433a65fdc31a639548fe365 diff --git a/lib/safe-contracts b/lib/safe-contracts index 186a21a..f03dfae 160000 --- a/lib/safe-contracts +++ b/lib/safe-contracts @@ -1 +1 @@ -Subproject commit 186a21a74b327f17fc41217a927dea7064f74604 +Subproject commit f03dfae65fd1d085224b00a10755c509a4eaacfe diff --git a/remappings.txt b/remappings.txt deleted file mode 100644 index 4ad28d5..0000000 --- a/remappings.txt +++ /dev/null @@ -1,3 +0,0 @@ -forge-std/=lib/forge-std/src/ - -safe/=lib/safe-contracts/contracts/ \ No newline at end of file diff --git a/script/ExecTransaction.s.sol b/script/ExecTransaction.sol similarity index 100% rename from script/ExecTransaction.s.sol rename to script/ExecTransaction.sol diff --git a/script/HashData.s.sol b/script/HashData.sol similarity index 100% rename from script/HashData.s.sol rename to script/HashData.sol diff --git a/script/SafeTxDataBuilder.sol b/script/SafeTxDataBuilder.sol index af90370..08e2f9b 100644 --- a/script/SafeTxDataBuilder.sol +++ b/script/SafeTxDataBuilder.sol @@ -1,12 +1,12 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import {SignatureDecoder} from "safe/common/SignatureDecoder.sol"; -import {GnosisSafe, Enum} from "safe/GnosisSafe.sol"; +import {SignatureDecoder} from "../lib/safe-contracts/contracts/common/SignatureDecoder.sol"; +import {GnosisSafe, Enum} from "../lib/safe-contracts/contracts/GnosisSafe.sol"; -import "forge-std/console2.sol"; -import "forge-std/StdJson.sol"; -import "forge-std/Script.sol"; +import "../lib/forge-std/src/console2.sol"; +import "../lib/forge-std/src/StdJson.sol"; +import "../lib/forge-std/src/Script.sol"; contract SafeTxDataBuilder is Script, SignatureDecoder { using stdJson for string; From 11e2d4eed308e9f18337b7c79327a6de0747ca82 Mon Sep 17 00:00:00 2001 From: Rubilmax Date: Wed, 6 Dec 2023 10:11:09 +0100 Subject: [PATCH 2/2] refactor(builder): use ordered struct --- script/ExecTransaction.sol | 30 ++++++++++--------- script/HashData.sol | 2 +- script/SafeTxDataBuilder.sol | 56 +++++++++++++++--------------------- 3 files changed, 40 insertions(+), 48 deletions(-) diff --git a/script/ExecTransaction.sol b/script/ExecTransaction.sol index 9685b85..9977b3b 100644 --- a/script/ExecTransaction.sol +++ b/script/ExecTransaction.sol @@ -2,7 +2,8 @@ pragma solidity ^0.8.0; import {QuickSort} from "./libraries/QuickSort.sol"; -import {SafeTxDataBuilder, Enum} from "./SafeTxDataBuilder.sol"; + +import {SafeTxDataBuilder, SafeTx, Enum} from "./SafeTxDataBuilder.sol"; contract ExecTransaction is SafeTxDataBuilder { using QuickSort for address[]; @@ -12,29 +13,30 @@ contract ExecTransaction is SafeTxDataBuilder { mapping(address => bytes) signatureOf; function run() public { - SafeTxData memory txData = loadSafeTxData(); + SafeTx memory safeTx; + safeTx.data = loadSafeTxData(); - loadSignatures(hashData(txData)); + loadSignatures(hashData(safeTx.data)); signers.sort(); for (uint256 i; i < signers.length; ++i) { - txData.signatures = bytes.concat(txData.signatures, signatureOf[signers[i]]); + safeTx.signatures = bytes.concat(safeTx.signatures, signatureOf[signers[i]]); } // Execute tx. vm.broadcast(SENDER); SAFE.execTransaction( - txData.to, - txData.value, - txData.data, - txData.operation, - txData.safeTxGas, - txData.baseGas, - txData.gasPrice, - txData.gasToken, - txData.refundReceiver, - txData.signatures + safeTx.data.to, + safeTx.data.value, + safeTx.data.data, + safeTx.data.operation, + safeTx.data.safeTxGas, + safeTx.data.baseGas, + safeTx.data.gasPrice, + safeTx.data.gasToken, + safeTx.data.refundReceiver, + safeTx.signatures ); } diff --git a/script/HashData.sol b/script/HashData.sol index 4a122b0..257473e 100644 --- a/script/HashData.sol +++ b/script/HashData.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.0; -import {SafeTxDataBuilder} from "./SafeTxDataBuilder.sol"; +import {SafeTxDataBuilder, SafeTxData} from "./SafeTxDataBuilder.sol"; contract HashData is SafeTxDataBuilder { function run() public { diff --git a/script/SafeTxDataBuilder.sol b/script/SafeTxDataBuilder.sol index 08e2f9b..62dd678 100644 --- a/script/SafeTxDataBuilder.sol +++ b/script/SafeTxDataBuilder.sol @@ -2,32 +2,32 @@ pragma solidity ^0.8.0; import {SignatureDecoder} from "../lib/safe-contracts/contracts/common/SignatureDecoder.sol"; -import {GnosisSafe, Enum} from "../lib/safe-contracts/contracts/GnosisSafe.sol"; +import {Safe, Enum} from "../lib/safe-contracts/contracts/Safe.sol"; import "../lib/forge-std/src/console2.sol"; import "../lib/forge-std/src/StdJson.sol"; import "../lib/forge-std/src/Script.sol"; -contract SafeTxDataBuilder is Script, SignatureDecoder { - using stdJson for string; +/// @dev Warning: keys must be ordered alphabetically. +struct SafeTxData { + uint256 baseGas; + bytes data; + uint256 gasPrice; + address gasToken; + Enum.Operation operation; + address payable refundReceiver; + uint256 safeTxGas; + address to; + uint256 value; +} - struct SafeTxData { - address to; - uint256 value; - bytes data; - Enum.Operation operation; - uint256 safeTxGas; - uint256 baseGas; - uint256 gasPrice; - address gasToken; - address payable refundReceiver; - bytes signatures; - } +struct SafeTx { + SafeTxData data; + bytes signatures; +} - // keccak256( - // "SafeTx(address to,uint256 value,bytes data,uint8 operation,uint256 safeTxGas,uint256 baseGas,uint256 gasPrice,address gasToken,address refundReceiver,uint256 nonce)" - // ); - bytes32 private constant SAFE_TX_TYPEHASH = 0xbb8310d486368db6bd6f849402fdd73ad53d316b5a4b2644ad6efe0f941286d8; +contract SafeTxDataBuilder is Script, SignatureDecoder { + using stdJson for string; string internal ROOT = vm.projectRoot(); string internal SIGNATURES_DIR = string.concat(ROOT, "/data/"); @@ -36,7 +36,7 @@ contract SafeTxDataBuilder is Script, SignatureDecoder { string internal HASH_DATA_FILE = string.concat(SIGNATURES_DIR, "hashData.txt"); string internal SIGNATURES_FILE = string.concat(SIGNATURES_DIR, "signatures.txt"); - GnosisSafe SAFE; + Safe SAFE; address internal SENDER; uint256 internal NONCE; uint256 internal THRESHOLD; @@ -44,25 +44,15 @@ contract SafeTxDataBuilder is Script, SignatureDecoder { function setUp() public { SENDER = vm.envAddress("SENDER"); - SAFE = GnosisSafe(payable(vm.envAddress("SAFE"))); + SAFE = Safe(payable(vm.envAddress("SAFE"))); NONCE = vm.envOr("SAFE_NONCE", SAFE.nonce()); THRESHOLD = SAFE.getThreshold(); DOMAIN_SEPARATOR = SAFE.domainSeparator(); } - function loadSafeTxData() internal returns (SafeTxData memory txData) { - string memory json = vm.readFile(TX_FILE); - - txData.to = json.readAddress("$.to"); - txData.value = json.readUint("$.value"); - txData.data = json.readBytes("$.data"); - txData.operation = Enum.Operation(json.readUint("$.operation")); - txData.safeTxGas = json.readUint("$.safeTxGas"); - txData.baseGas = json.readUint("$.baseGas"); - txData.gasPrice = json.readUint("$.gasPrice"); - txData.gasToken = json.readAddress("$.gasToken"); - txData.refundReceiver = payable(json.readAddress("$.refundReceiver")); + function loadSafeTxData() internal view returns (SafeTxData memory txData) { + return abi.decode(vm.parseJson(vm.readFile(TX_FILE)), (SafeTxData)); } function hashData(SafeTxData memory txData) internal view returns (bytes32) {