Skip to content

Commit

Permalink
Merge 7eacfe6 into 5a6aa44
Browse files Browse the repository at this point in the history
  • Loading branch information
akshay-ap committed Jul 12, 2023
2 parents 5a6aa44 + 7eacfe6 commit 6696cf8
Show file tree
Hide file tree
Showing 12 changed files with 238 additions and 63 deletions.
3 changes: 1 addition & 2 deletions contracts/Safe.sol
Original file line number Diff line number Diff line change
Expand Up @@ -39,8 +39,7 @@ contract Safe is
SecuredTokenTransfer,
ISignatureValidatorConstants,
FallbackManager,
StorageAccessible,
GuardManager
StorageAccessible
{
using SafeMath for uint256;

Expand Down
26 changes: 25 additions & 1 deletion contracts/base/GuardManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,18 @@ import "../common/SelfAuthorized.sol";
import "../interfaces/IERC165.sol";

interface Guard is IERC165 {
/// @dev Checks if a transaction should be allowed.
/// @param to The address of the recipient.
/// @param value The value of the transaction.
/// @param data The data of the transaction.
/// @param operation The operation type. 0 - CALL, 1 - DELEGATECALL
/// @param safeTxGas The gas limit for the transaction.
/// @param baseGas The base gas limit for the transaction.
/// @param gasPrice The gas price for the transaction.
/// @param gasToken The token used for paying gas.
/// @param refundReceiver The address that will receive the gas fees refund.
/// @param signatures The signatures of the transaction.
/// @param msgSender The sender of the message that triggered the transaction.
function checkTransaction(
address to,
uint256 value,
Expand All @@ -20,13 +32,25 @@ interface Guard is IERC165 {
address msgSender
) external;

/// @dev Checks if a module transaction should be allowed.
/// @param to The address of the recipient.
/// @param value The value of the transaction.
/// @param data The data of the transaction.
/// @param operation The operation type.
/// @param module The module that triggered the transaction.
function checkModuleTransaction(address to, uint256 value, bytes memory data, Enum.Operation operation, address module) external;

/// @dev Checks if a transaction was successful after execution.
/// @param txHash The hash of the transaction that was executed.
/// In case of a module transaction, hash of the transaction call data.
/// @param success Whether or not the transaction was successful.
function checkAfterExecution(bytes32 txHash, bool success) external;
}

abstract contract BaseGuard is Guard {
function supportsInterface(bytes4 interfaceId) external view virtual override returns (bool) {
return
interfaceId == type(Guard).interfaceId || // 0xe6d7a83a
interfaceId == type(Guard).interfaceId || // 0x945b8148
interfaceId == type(IERC165).interfaceId; // 0x01ffc9a7
}
}
Expand Down
12 changes: 11 additions & 1 deletion contracts/base/ModuleManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ pragma solidity >=0.7.0 <0.9.0;
import "../common/Enum.sol";
import "../common/SelfAuthorized.sol";
import "./Executor.sol";
import "./GuardManager.sol";

/**
* @title Module Manager - A contract managing Safe modules
Expand All @@ -13,7 +14,7 @@ import "./Executor.sol";
* @author Stefan George - @Georgi87
* @author Richard Meissner - @rmeissner
*/
abstract contract ModuleManager is SelfAuthorized, Executor {
abstract contract ModuleManager is SelfAuthorized, Executor, GuardManager {
event EnabledModule(address indexed module);
event DisabledModule(address indexed module);
event ExecutionFromModuleSuccess(address indexed module);
Expand Down Expand Up @@ -87,7 +88,16 @@ abstract contract ModuleManager is SelfAuthorized, Executor {
// Only whitelisted modules are allowed.
require(msg.sender != SENTINEL_MODULES && modules[msg.sender] != address(0), "GS104");
// Execute transaction without further confirmations.
address guard = getGuard();

if (guard != address(0)) {
Guard(guard).checkModuleTransaction(to, value, data, operation, msg.sender);
}
success = execute(to, value, data, operation, type(uint256).max);

if (guard != address(0)) {
Guard(guard).checkAfterExecution(keccak256(data), success);
}
if (success) emit ExecutionFromModuleSuccess(msg.sender);
else emit ExecutionFromModuleFailure(msg.sender);
}
Expand Down
16 changes: 16 additions & 0 deletions contracts/examples/guards/DebugTransactionGuard.sol
Original file line number Diff line number Diff line change
Expand Up @@ -85,4 +85,20 @@ contract DebugTransactionGuard is BaseGuard {
txNonces[txHash] = 0;
emit GasUsage(msg.sender, txHash, nonce, success);
}

/**
* @notice Called by the Safe contract before a transaction is executed via a module.
* @param to Destination address of Safe transaction.
* @param value Ether value of Safe transaction.
* @param data Data payload of Safe transaction.
* @param operation Operation type of Safe transaction.
* @param msgSender Account executing the transaction.
*/
function checkModuleTransaction(
address to,
uint256 value,
bytes memory data,
Enum.Operation operation,
address msgSender
) external override {}
}
16 changes: 16 additions & 0 deletions contracts/examples/guards/DelegateCallTransactionGuard.sol
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,20 @@ contract DelegateCallTransactionGuard is BaseGuard {
}

function checkAfterExecution(bytes32, bool) external view override {}

/**
* @notice Called by the Safe contract before a transaction is executed via a module.
* @param to Destination address of Safe transaction.
* @param value Ether value of Safe transaction.
* @param data Data payload of Safe transaction.
* @param operation Operation type of Safe transaction.
* @param msgSender Account executing the transaction.
*/
function checkModuleTransaction(
address to,
uint256 value,
bytes memory data,
Enum.Operation operation,
address msgSender
) external override {}
}
16 changes: 16 additions & 0 deletions contracts/examples/guards/OnlyOwnersGuard.sol
Original file line number Diff line number Diff line change
Expand Up @@ -56,4 +56,20 @@ contract OnlyOwnersGuard is BaseGuard {
}

function checkAfterExecution(bytes32, bool) external view override {}

/**
* @notice Called by the Safe contract before a transaction is executed via a module.
* @param to Destination address of Safe transaction.
* @param value Ether value of Safe transaction.
* @param data Data payload of Safe transaction.
* @param operation Operation type of Safe transaction.
* @param msgSender Account executing the transaction.
*/
function checkModuleTransaction(
address to,
uint256 value,
bytes memory data,
Enum.Operation operation,
address msgSender
) external override {}
}
16 changes: 16 additions & 0 deletions contracts/examples/guards/ReentrancyTransactionGuard.sol
Original file line number Diff line number Diff line change
Expand Up @@ -66,4 +66,20 @@ contract ReentrancyTransactionGuard is BaseGuard {
function checkAfterExecution(bytes32, bool) external override {
getGuard().active = false;
}

/**
* @notice Called by the Safe contract before a transaction is executed via a module.
* @param to Destination address of Safe transaction.
* @param value Ether value of Safe transaction.
* @param data Data payload of Safe transaction.
* @param operation Operation type of Safe transaction.
* @param msgSender Account executing the transaction.
*/
function checkModuleTransaction(
address to,
uint256 value,
bytes memory data,
Enum.Operation operation,
address msgSender
) external override {}
}
6 changes: 6 additions & 0 deletions contracts/test/TestImports.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
// SPDX-License-Identifier: LGPL-3.0-only

pragma solidity >=0.7.0 <0.9.0;

// Import the contract so hardhat compiles it, and we have the ABI available
import {MockContract} from "@safe-global/mock-contract/contracts/MockContract.sol";
1 change: 0 additions & 1 deletion contracts/test/Token.sol
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
// SPDX-License-Identifier: LGPL-3.0-only
pragma solidity >=0.6.0 <0.7.0;
import "@gnosis.pm/mock-contract/contracts/MockContract.sol";

interface Token {
function transfer(address _to, uint256 value) external returns (bool);
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
"url": "https://github.com/safe-global/safe-contracts/issues"
},
"devDependencies": {
"@gnosis.pm/mock-contract": "^4.0.0",
"@safe-global/mock-contract": "^4.0.0",
"@gnosis.pm/safe-singleton-factory": "^1.0.14",
"@nomiclabs/hardhat-ethers": "2.0.2",
"@nomiclabs/hardhat-etherscan": "^3.1.7",
Expand Down

0 comments on commit 6696cf8

Please sign in to comment.