Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update repo #31

Open
wants to merge 2 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion LICENSE.txt
Original file line number Diff line number Diff line change
@@ -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
Expand Down
6 changes: 3 additions & 3 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion lib/safe-contracts
3 changes: 0 additions & 3 deletions remappings.txt

This file was deleted.

30 changes: 16 additions & 14 deletions script/ExecTransaction.s.sol → script/ExecTransaction.sol
Original file line number Diff line number Diff line change
Expand Up @@ -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[];
Expand All @@ -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
);
}

Expand Down
2 changes: 1 addition & 1 deletion script/HashData.s.sol → script/HashData.sol
Original file line number Diff line number Diff line change
@@ -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 {
Expand Down
64 changes: 27 additions & 37 deletions script/SafeTxDataBuilder.sol
Original file line number Diff line number Diff line change
@@ -1,33 +1,33 @@
// 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 {Safe, Enum} from "../lib/safe-contracts/contracts/Safe.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;
/// @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/");
Expand All @@ -36,33 +36,23 @@ 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;
bytes32 internal DOMAIN_SEPARATOR;

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) {
Expand Down