Safe guard

OwnerExecGuard

Solidity for the Safe Guard that reverts every owner execTransaction. Module exec from the PolicyClient is unchanged.

0xAbc1aeA4fA13B0bFCe806062De4762F7dc1E3950

Attack demo · Policy · Policy client

policy-client/src/OwnerExecGuard.sol

// SPDX-License-Identifier: Apache-2.0
pragma solidity ^0.8.27;

import {IGuard} from "./IGuard.sol";

/// @title OwnerExecGuard
/// @notice Reverts every Safe owner `execTransaction`. Module exec is unchanged.
/// @dev Safe 1.4.1 only calls the Guard from `execTransaction`, not from
///      `execTransactionFromModule`. After this Guard is set, owners cannot
///      drain USDC, remove the module, or unset the Guard via owner txs.
contract OwnerExecGuard is IGuard {
    error OwnerExecBlocked();

    bytes4 private constant ERC165_ID = 0x01ffc9a7;

    function checkTransaction(
        address,
        uint256,
        bytes memory,
        uint8,
        uint256,
        uint256,
        uint256,
        address,
        address payable,
        bytes memory,
        address
    ) external pure {
        revert OwnerExecBlocked();
    }

    function checkAfterExecution(bytes32, bool) external pure {}

    function supportsInterface(bytes4 interfaceId) external pure returns (bool) {
        return interfaceId == type(IGuard).interfaceId || interfaceId == ERC165_ID;
    }
}