creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "contracts/Firewall.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\n// See LICENSE file for full license text.\n// Copyright (c) Ironblocks 2023\npragma solidity 0.8.19;\n\nimport {Ownable2Step} from \"@openzeppelin/contracts/access/Ownable2Step.sol\";\nimport {IFirewall} from \"./interfaces/IFirewall.sol\";\nimport {IFirewallConsumer} from \"./interfaces/IFirewallConsumer.sol\";\nimport {IFirewallPolicy} from \"./interfaces/IFirewallPolicy.sol\";\nimport {IFirewallPrivateInvariantsPolicy} from \"./interfaces/IFirewallPrivateInvariantsPolicy.sol\";\n\n/**\n * @title Firewall\n * @author David Benchimol @ Ironblocks\n * @dev This contract provides an open marketplace of firewall policies that can be subscribed to by consumers.\n *\n * Each policy is a contract that must implement the IFirewallPolicy interface. The policy contract is responsible for\n * making the decision on whether or not to allow a call to be executed. The policy contract gets access to the consumers\n * full context, including the sender, data, and value of the call as well as the ability to read state before and after\n * function execution.\n *\n * Each consumer is a contract whos policys are managed by a single admin. The admin is responsible for adding and removing\n * policies.\n */\ncontract Firewall is IFirewall, Ownable2Step {\n\n    /**\n     * @dev Emitted when a policy is approved or disapproved by the owner.\n     * @param policy The address of the policy contract.\n     * @param status The status of the policy.\n     */\n    event PolicyStatusUpdate(address policy, bool status);\n\n    /**\n     * @dev Emitted when a policy is globally added or to a consumer.\n     * @param consumer The address of the consumer contract.\n     * @param policy The address of the policy contract.\n     */\n    event GlobalPolicyAdded(address indexed consumer, address policy);\n\n    /**\n     * @dev Emitted when a policy is globally removed or from a consumer.\n     * @param consumer The address of the consumer contract.\n     * @param policy The address of the policy contract.\n     */\n    event GlobalPolicyRemoved(address indexed consumer, address policy);\n\n    /**\n     * @dev Emitted when a policy is added to a consumer.\n     * @param consumer The address of the consumer contract.\n     * @param methodSig The method signature of the consumer contract to which the policy applies\n     * @param policy The address of the policy contract.\n     */\n    event PolicyAdded(address indexed consumer, bytes4 methodSig, address policy);\n\n    /**\n     * @dev Emitted when a policy is removed from a consumer.\n     * @param consumer The address of the consumer contract.\n     * @param methodSig The method signature of the consumer contract to which the policy applies\n     * @param policy The address of the policy contract.\n     */\n    event PolicyRemoved(address indexed consumer, bytes4 methodSig, address policy);\n\n    /**\n     * @dev Emitted when a private invariants policy is set for a consumer.\n     * @param consumer The address of the consumer contract.\n     * @param methodSig The method signature of the consumer contract to which the policy applies\n     * @param policy The address of the policy contract.\n     */\n    event InvariantPolicySet(address indexed consumer, bytes4 methodSig, address policy);\n\n    /**\n     * @dev Emitted when a policy's pre-execution hook was succesfully executed in dry-run mode.\n     * @param consumer The address of the consumer contract.\n     * @param methodSig The method signature of the consumer contract to which the policy applies\n     * @param policy The address of the policy contract.\n     */\n    event DryrunPolicyPreSuccess(address indexed consumer, bytes4 methodSig, address policy);\n\n    /**\n     * @dev Emitted when a policy's post-execution hook was succesfully executed in dry-run mode.\n     * @param consumer The address of the consumer contract.\n     * @param methodSig The method signature of the consumer contract to which the policy applies\n     * @param policy The address of the policy contract.\n     */\n    event DryrunPolicyPostSuccess(address indexed consumer, bytes4 methodSig, address policy);\n\n    /**\n     * @dev Emitted when a policy's pre-execution hook failed in dry-run mode.\n     * @param consumer The address of the consumer contract.\n     * @param methodSig The method signature of the consumer contract to which the policy applies\n     * @param policy The address of the policy contract.\n     * @param error The error message.\n     */\n    event DryrunPolicyPreError(address indexed consumer, bytes4 methodSig, address policy, bytes error);\n\n    /**\n     * @dev Emitted when a policy's post-execution hook failed in dry-run mode.\n     * @param consumer The address of the consumer contract.\n     * @param methodSig The method signature of the consumer contract to which the policy applies\n     * @param policy The address of the policy contract.\n     * @param error The error message.\n     */\n    event DryrunPolicyPostError(address indexed consumer, bytes4 methodSig, address policy, bytes error);\n\n    /**\n     * @dev Emitted when a private invariants policy's pre-execution hook was succesfully executed in dry-run mode.\n     * @param consumer The address of the consumer contract.\n     * @param methodSig The method signature of the consumer contract to which the policy applies\n     * @param policy The address of the policy contract.\n     */\n    event DryrunInvariantPolicyPreSuccess(address indexed consumer, bytes4 methodSig, address policy);\n\n    /**\n     * @dev Emitted when a private invariants policy's post-execution hook was succesfully executed in dry-run mode.\n     * @param consumer The address of the consumer contract.\n     * @param methodSig The method signature of the consumer contract to which the policy applies\n     * @param policy The address of the policy contract.\n     */\n    event DryrunInvariantPolicyPostSuccess(address indexed consumer, bytes4 methodSig, address policy);\n\n    /**\n     * @dev Emitted when a private invariants policy's pre-execution hook failed in dry-run mode.\n     * @param consumer The address of the consumer contract.\n     * @param methodSig The method signature of the consumer contract to which the policy applies\n     * @param policy The address of the policy contract.\n     * @param error The error message.\n     */\n    event DryrunInvariantPolicyPreError(address indexed consumer, bytes4 methodSig, address policy, bytes error);\n\n    /**\n     * @dev Emitted when a private invariants policy's post-execution hook failed in dry-run mode.\n     * @param consumer The address of the consumer contract.\n     * @param methodSig The method signature of the consumer contract to which the policy applies\n     * @param policy The address of the policy contract.\n     * @param error The error message.\n     */\n    event DryrunInvariantPolicyPostError(address indexed consumer, bytes4 methodSig, address policy, bytes error);\n\n    /**\n     * @dev Modifier to check if the caller is the consumer admin.\n     * @param consumer The address of the consumer contract.\n     */\n    modifier onlyConsumerAdmin(address consumer) {\n        require(msg.sender == IFirewallConsumer(consumer).firewallAdmin(), \"Firewall: not consumer admin\");\n        _;\n    }\n\n    // Mapping of policies approved by firewall owner\n    mapping (address policy => bool isApproved) public approvedPolicies;\n    // Mapping of consumer + sighash to array of policy addresses\n    mapping (address consumer => mapping (bytes4 sighash => address[] policies)) public subscribedPolicies;\n    // Mapping of consumer to array of policy addresses applied to all consumer methods\n    mapping (address consumer => address[] globalPolicies) public subscribedGlobalPolicies;\n    // Mapping of consumer + sighash to a single invariant policy\n    mapping (address consumer => mapping (bytes4 sighash => address privateInvariantsPolicy)) public subscribedPrivateInvariantsPolicy;\n    // Mapping of consumer to boolean indicating whether dry-run mode is enabled or not\n    mapping (address consumer => bool dryrun) public dryrunEnabled;\n\n    /**\n     * @dev Runs the preExecution hook of all subscribed policies.\n     * @param sender The address of the caller.\n     * @param data The calldata of the call (some firewall modifiers may pass custom data based on the use case)\n     * @param value The value of the call.\n     */\n    function preExecution(address sender, bytes calldata data, uint256 value) external override {\n        bytes4 selector = bytes4(data);\n        address[] memory policies = subscribedPolicies[msg.sender][selector];\n        address[] memory globalPolicies = subscribedGlobalPolicies[msg.sender];\n        if (dryrunEnabled[msg.sender]) {\n            for (uint256 i = 0; i < policies.length; i++) {\n                try IFirewallPolicy(policies[i]).preExecution(msg.sender, sender, data, value) {\n                    emit DryrunPolicyPreSuccess(msg.sender, selector, policies[i]);\n                } catch(bytes memory err) {\n                    emit DryrunPolicyPreError(msg.sender, selector, policies[i], err);\n                }\n            }\n            for (uint256 i = 0; i < globalPolicies.length; i++) {\n                try IFirewallPolicy(globalPolicies[i]).preExecution(msg.sender, sender, data, value) {\n                    emit DryrunPolicyPreSuccess(msg.sender, selector, globalPolicies[i]);\n                } catch(bytes memory err) {\n                    emit DryrunPolicyPreError(msg.sender, selector, globalPolicies[i], err);\n                }\n            }\n        } else {\n            for (uint256 i = 0; i < policies.length; i++) {\n                IFirewallPolicy(policies[i]).preExecution(msg.sender, sender, data, value);\n            }\n            for (uint256 i = 0; i < globalPolicies.length; i++) {\n                IFirewallPolicy(globalPolicies[i]).preExecution(msg.sender, sender, data, value);\n            }\n        }\n    }\n\n    /**\n     * @dev Runs the postExecution hook of all subscribed policies.\n     * @param sender The address of the caller.\n     * @param data The calldata of the call (some firewall modifiers may pass custom data based on the use case)\n     * @param value The value of the call.\n     */\n    function postExecution(address sender, bytes calldata data, uint256 value) external override {\n        bytes4 selector = bytes4(data);\n        address[] memory policies = subscribedPolicies[msg.sender][selector];\n        address[] memory globalPolicies = subscribedGlobalPolicies[msg.sender];\n        if (dryrunEnabled[msg.sender]) {\n            for (uint256 i = 0; i < policies.length; i++) {\n                try IFirewallPolicy(policies[i]).postExecution(msg.sender, sender, data, value) {\n                    emit DryrunPolicyPostSuccess(msg.sender, selector, policies[i]);\n                } catch(bytes memory err) {\n                    emit DryrunPolicyPostError(msg.sender, selector, policies[i], err);\n                }\n            }\n            for (uint256 i = 0; i < globalPolicies.length; i++) {\n                try IFirewallPolicy(globalPolicies[i]).postExecution(msg.sender, sender, data, value) {\n                    emit DryrunPolicyPostSuccess(msg.sender, selector, globalPolicies[i]);\n                } catch(bytes memory err) {\n                    emit DryrunPolicyPostError(msg.sender, selector, globalPolicies[i], err);\n                }\n            }\n        } else {\n            for (uint256 i = 0; i < policies.length; i++) {\n                IFirewallPolicy(policies[i]).postExecution(msg.sender, sender, data, value);\n            }\n            for (uint256 i = 0; i < globalPolicies.length; i++) {\n                IFirewallPolicy(globalPolicies[i]).postExecution(msg.sender, sender, data, value);\n            }\n        }\n    }\n\n\n    /**\n     * @dev Runs the preExecution hook of private variables policy\n     * @param sender The address of the caller.\n     * @param data The calldata of the call (some firewall modifiers may pass custom data based on the use case)\n     * @param value The value of the call.\n     * @return storageSlots The storage slots that the policy wants to read\n     */\n    function preExecutionPrivateInvariants(\n        address sender,\n        bytes calldata data,\n        uint256 value\n    ) external override returns (bytes32[] memory storageSlots) {\n        bytes4 selector = bytes4(data);\n        address privateInvariantsPolicy = subscribedPrivateInvariantsPolicy[msg.sender][selector];\n        if (privateInvariantsPolicy == address(0)) {\n            return storageSlots;\n        }\n        if (dryrunEnabled[msg.sender]) {\n            try IFirewallPrivateInvariantsPolicy(privateInvariantsPolicy).preExecution(msg.sender, sender, data, value) returns (bytes32[] memory sSlots) {\n                storageSlots = sSlots;\n                emit DryrunInvariantPolicyPreSuccess(msg.sender, selector, privateInvariantsPolicy);\n            } catch(bytes memory err) {\n                emit DryrunInvariantPolicyPreError(msg.sender, selector, privateInvariantsPolicy, err);\n            }\n        } else {\n            storageSlots = IFirewallPrivateInvariantsPolicy(privateInvariantsPolicy).preExecution(msg.sender, sender, data, value);\n        }\n    }\n\n    /**\n     * @dev Runs the postExecution hook of private variables policy\n     * @param sender The address of the caller.\n     * @param data The calldata of the call (some firewall modifiers may pass custom data\n     * based on the use case)\n     * @param value The value of the call.\n     * @param preValues The values of the storage slots before the original call\n     * @param postValues The values of the storage slots after the original call\n     */\n    function postExecutionPrivateInvariants(\n        address sender,\n        bytes memory data,\n        uint256 value,\n        bytes32[] calldata preValues,\n        bytes32[] calldata postValues\n    ) external override {\n        bytes4 selector = bytes4(data);\n        address privateInvariantsPolicy = subscribedPrivateInvariantsPolicy[msg.sender][selector];\n        if (privateInvariantsPolicy == address(0)) {\n            return;\n        }\n        if (dryrunEnabled[msg.sender]) {\n            try IFirewallPrivateInvariantsPolicy(privateInvariantsPolicy).postExecution(msg.sender, sender, data, value, preValues, postValues) {\n                emit DryrunInvariantPolicyPostSuccess(msg.sender, selector, privateInvariantsPolicy);\n            } catch(bytes memory err) {\n                emit DryrunInvariantPolicyPostError(msg.sender, selector, privateInvariantsPolicy, err);\n            }\n        } else {\n            IFirewallPrivateInvariantsPolicy(privateInvariantsPolicy).postExecution(msg.sender, sender, data, value, preValues, postValues);\n        }\n    }\n\n    /**\n     * @dev Owner only function allowing the owner to approve or remove a policy contract. This allows the policy\n     * to be subscribed to by consumers, or conversely no longer be allowed.\n     * @param policy The address of the policy contract.\n     * @param status The status of the policy.\n     */\n    function setPolicyStatus(address policy, bool status) external onlyOwner {\n        approvedPolicies[policy] = status;\n        emit PolicyStatusUpdate(policy, status);\n    }\n\n    /**\n     * @dev Admin only function allowing the consumers admin enable/disable dry run mode.\n     * @param consumer The address of the consumer contract.\n     * @param status The status of the dry run mode.\n     */\n    function setConsumerDryrunStatus(address consumer, bool status) external onlyConsumerAdmin(consumer) {\n        dryrunEnabled[consumer] = status;\n    }\n\n    /**\n     * @dev Admin only function allowing the consumers admin to add a policy to the consumers subscribed policies.\n     * @param consumer The address of the consumer contract.\n     * @param policy The address of the policy contract.\n     *\n     * NOTE: Policies that you register to may become obsolete in the future, there may be a an upgraded\n     * version of the policy in the future, and / or a new vulnerability may be found in a policy at some\n     * future time. For these reason, the Firewall Owner has the ability to disapprove a policy in the future,\n     * preventing consumers from being able to subscribe to it in the future.\n     *\n     * While doesn't block already-subscribed consumers from using the policy, it is highly recommended\n     * to have periodical reviews of the policies you are subscribed to and to make any required changes\n     * accordingly.\n     */\n    function addGlobalPolicy(address consumer, address policy) external onlyConsumerAdmin(consumer) {\n        _addGlobalPolicy(consumer, policy);\n    }\n\n    /**\n     * @dev Admin only function allowing the consumers admin to remove a policy from the consumers subscribed policies.\n     * @param consumer The address of the consumer contract.\n     * @param policy The address of the policy contract.\n     */\n    function removeGlobalPolicy(address consumer, address policy) external onlyConsumerAdmin(consumer) {\n        _removeGlobalPolicy(consumer, policy);\n    }\n\n    /**\n     * @dev Admin only function allowing the consumers admin to add a single policy to multiple consumers.\n     * Note that the consumer admin needs to be the same for all consumers\n     *\n     * @param consumers The addresses of the consumer contracts.\n     * @param policy The address of the policy contract.\n     * NOTE: Policies that you register to may become obsolete in the future, there may be a an upgraded\n     * version of the policy in the future, and / or a new vulnerability may be found in a policy at some\n     * future time. For these reason, the Firewall Owner has the ability to disapprove a policy in the future,\n     * preventing consumers from being able to subscribe to it in the future.\n     *\n     * While doesn't block already-subscribed consumers from using the policy, it is highly recommended\n     * to have periodical reviews of the policies you are subscribed to and to make any required changes\n     * accordingly.\n     */\n    function addGlobalPolicyForConsumers(address[] calldata consumers, address policy) external {\n        for (uint256 i = 0; i < consumers.length; i++) {\n            require(msg.sender == IFirewallConsumer(consumers[i]).firewallAdmin(), \"Firewall: not consumer admin\");\n            _addGlobalPolicy(consumers[i], policy);\n        }\n    }\n\n    /**\n     * @dev Admin only function allowing the consumers admin to remove a single policy from multiple consumers.\n     * Note that the consumer admin needs to be the same for all consumers\n     *\n     * @param consumers The addresses of the consumer contracts.\n     * @param policy The address of the policy contract.\n     */\n    function removeGlobalPolicyForConsumers(address[] calldata consumers, address policy) external {\n        for (uint256 i = 0; i < consumers.length; i++) {\n            require(msg.sender == IFirewallConsumer(consumers[i]).firewallAdmin(), \"Firewall: not consumer admin\");\n            _removeGlobalPolicy(consumers[i], policy);\n        }\n    }\n\n    /**\n     * @dev Admin only function allowing the consumers admin to add multiple policies to the consumers subscribed policies.\n     * @param consumer The address of the consumer contract.\n     * @param methodSigs The method signatures of the consumer contract to which the policies apply\n     * @param policies The addresses of the policy contracts.\n     *\n     * NOTE: Policies that you register to may become obsolete in the future, there may be a an upgraded\n     * version of the policy in the future, and / or a new vulnerability may be found in a policy at some\n     * future time. For these reason, the Firewall Owner has the ability to disapprove a policy in the future,\n     * preventing consumers from being able to subscribe to it in the future.\n     *\n     * While doesn't block already-subscribed consumers from using the policy, it is highly recommended\n     * to have periodical reviews of the policies you are subscribed to and to make any required changes\n     * accordingly.\n     */\n    function addPolicies(address consumer, bytes4[] calldata methodSigs, address[] calldata policies) external onlyConsumerAdmin(consumer) {\n        for (uint256 i = 0; i < policies.length; i++) {\n            _addPolicy(consumer, methodSigs[i], policies[i]);\n        }\n    }\n\n    /**\n     * @dev Admin only function allowing the consumers admin to add a policy to the consumers subscribed policies.\n     * @param consumer The address of the consumer contract.\n     * @param methodSig The method signature of the consumer contract to which the policy applies\n     * @param policy The address of the policy contract.\n     *\n     * NOTE: Policies that you register to may become obsolete in the future, there may be a an upgraded\n     * version of the policy in the future, and / or a new vulnerability may be found in a policy at some\n     * future time. For these reason, the Firewall Owner has the ability to disapprove a policy in the future,\n     * preventing consumers from being able to subscribe to it in the future.\n     *\n     * While doesn't block already-subscribed consumers from using the policy, it is highly recommended\n     * to have periodical reviews of the policies you are subscribed to and to make any required changes\n     * accordingly.\n     */\n    function addPolicy(address consumer, bytes4 methodSig, address policy) external onlyConsumerAdmin(consumer) {\n        _addPolicy(consumer, methodSig, policy);\n    }\n\n    /**\n     * @dev Admin only function allowing the consumers admin to remove multiple policies from the consumers subscribed policies.\n     * @param consumer The address of the consumer contract.\n     * @param methodSigs The method signatures of the consumer contract to which the policies apply\n     * @param policies The addresses of the policy contracts.\n     */\n    function removePolicies(address consumer, bytes4[] calldata methodSigs, address[] calldata policies) external onlyConsumerAdmin(consumer) {\n        for (uint256 i = 0; i < policies.length; i++) {\n            _removePolicy(consumer, methodSigs[i], policies[i]);\n        }\n    }\n\n    /**\n     * @dev Admin only function allowing the consumers admin to remove a policy from the consumers subscribed policies.\n     * @param consumer The address of the consumer contract.\n     * @param methodSig The method signature of the consumer contract to which the policy applies\n     * @param policy The address of the policy contract.\n     */\n    function removePolicy(address consumer, bytes4 methodSig, address policy) external onlyConsumerAdmin(consumer) {\n        _removePolicy(consumer, methodSig, policy);\n    }\n\n    /**\n     * @dev Admin only function allowing the consumers admin to set the private variables policies\n     * @param consumer The address of the consumer contract.\n     * @param methodSigs The method signatures of the consumer contract to which the policies apply\n     * @param policies The addresses of the policy contracts.\n     */\n    function setPrivateInvariantsPolicy(address consumer, bytes4[] calldata methodSigs, address[] calldata policies) external onlyConsumerAdmin(consumer) {\n        for (uint256 i = 0; i < policies.length; i++) {\n            require(approvedPolicies[policies[i]], \"Firewall: policy not approved\");\n            subscribedPrivateInvariantsPolicy[consumer][methodSigs[i]] = policies[i];\n            emit InvariantPolicySet(consumer, methodSigs[i], policies[i]);\n        }\n    }\n\n    /**\n     * @dev View function for retrieving a consumers subscribed policies for a given method.\n     * @param consumer The address of the consumer contract.\n     * @param methodSig The method signature of the consumer contract.\n     * @return policies The addresses of the policy contracts.\n     */\n    function getActivePolicies(address consumer, bytes4 methodSig) external view returns (address[] memory) {\n        return subscribedPolicies[consumer][methodSig];\n    }\n\n    /**\n     * @dev View function for retrieving a consumers subscribed global policies.\n     * @param consumer The address of the consumer contract.\n     * @return policies The addresses of the policy contracts.\n     */\n    function getActiveGlobalPolicies(address consumer) external view returns (address[] memory) {\n        return subscribedGlobalPolicies[consumer];\n    }\n\n    /**\n     * @dev Internal function for adding a policy to a consumer.\n     * @param consumer The address of the consumer contract.\n     * @param methodSig The method signature of the consumer contract to which the policy applies\n     * @param policy The address of the policy contract.\n     */\n    function _addPolicy(address consumer, bytes4 methodSig, address policy) internal {\n        require(approvedPolicies[policy], \"Firewall: policy not approved\");\n        address[] memory policies = subscribedPolicies[consumer][methodSig];\n        for (uint256 i = 0; i < policies.length; i++) {\n            require(policy != policies[i], \"Firewall: policy already exists\");\n        }\n        subscribedPolicies[consumer][methodSig].push(policy);\n        emit PolicyAdded(consumer, methodSig, policy);\n    }\n\n    /**\n     * @dev Internal function for removing a policy from a consumer.\n     * @param consumer The address of the consumer contract.\n     * @param methodSig The method signature of the consumer contract to which the policy applies\n     * @param policy The address of the policy contract.\n     */\n    function _removePolicy(address consumer, bytes4 methodSig, address policy) internal {\n        address[] storage policies = subscribedPolicies[consumer][methodSig];\n        for (uint256 i = 0; i < policies.length; i++) {\n            if (policy == policies[i]) {\n                policies[i] = policies[policies.length - 1];\n                policies.pop();\n                emit PolicyRemoved(consumer, methodSig, policy);\n                return;\n            }\n        }\n    }\n\n    /**\n     * @dev Internal function for adding a global policy to a consumer.\n     * @param consumer The address of the consumer contract.\n     * @param policy The address of the policy contract.\n     */\n    function _addGlobalPolicy(address consumer, address policy) internal {\n        require(approvedPolicies[policy], \"Firewall: policy not approved\");\n        address[] memory policies = subscribedGlobalPolicies[consumer];\n        for (uint256 i = 0; i < policies.length; i++) {\n            require(policy != policies[i], \"Firewall: policy already exists\");\n        }\n        subscribedGlobalPolicies[consumer].push(policy);\n        emit GlobalPolicyAdded(consumer, policy);\n    }\n\n    /**\n     * @dev Internal function for removing a global policy from a consumer.\n     * @param consumer The address of the consumer contract.\n     * @param policy The address of the policy contract.\n     */\n    function _removeGlobalPolicy(address consumer, address policy) internal {\n        address[] storage globalPolicies = subscribedGlobalPolicies[consumer];\n        for (uint256 i = 0; i < globalPolicies.length; i++) {\n            if (policy == globalPolicies[i]) {\n                globalPolicies[i] = globalPolicies[globalPolicies.length - 1];\n                globalPolicies.pop();\n                emit GlobalPolicyRemoved(consumer, policy);\n                return;\n            }\n        }\n    }\n}\n"
      },
      "contracts/interfaces/IFirewall.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\n// See LICENSE file for full license text.\n// Copyright (c) Ironblocks 2023\npragma solidity 0.8.19;\n\ninterface IFirewall {\n    function preExecution(address sender, bytes memory data, uint256 value) external;\n    function postExecution(address sender, bytes memory data, uint256 value) external;\n    function preExecutionPrivateInvariants(address sender, bytes memory data, uint256 value) external returns (bytes32[] calldata);\n    function postExecutionPrivateInvariants(\n        address sender,\n        bytes memory data,\n        uint256 value,\n        bytes32[] calldata preValues,\n        bytes32[] calldata postValues\n    ) external;\n}\n"
      },
      "contracts/interfaces/IFirewallPolicy.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\n// See LICENSE file for full license text.\n// Copyright (c) Ironblocks 2023\npragma solidity 0.8.19;\n\ninterface IFirewallPolicy {\n    function preExecution(address consumer, address sender, bytes memory data, uint256 value) external;\n    function postExecution(address consumer, address sender, bytes memory data, uint256 value) external;\n}\n"
      },
      "contracts/interfaces/IFirewallPrivateInvariantsPolicy.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\n// See LICENSE file for full license text.\n// Copyright (c) Ironblocks 2023\npragma solidity 0.8.19;\n\ninterface IFirewallPrivateInvariantsPolicy {\n    function preExecution(\n        address consumer,\n        address sender,\n        bytes memory data,\n        uint256 value\n    ) external returns (bytes32[] calldata);\n    function postExecution(\n        address consumer,\n        address sender,\n        bytes memory data,\n        uint256 value,\n        bytes32[] calldata preValues,\n        bytes32[] calldata postValues\n    ) external;\n}\n"
      },
      "contracts/interfaces/IFirewallConsumer.sol": {
        "content": "// SPDX-License-Identifier: UNLICENSED\n// See LICENSE file for full license text.\n// Copyright (c) Ironblocks 2023\npragma solidity 0.8.19;\n\ninterface IFirewallConsumer {\n    function firewallAdmin() external returns (address);\n}\n"
      },
      "@openzeppelin/contracts/access/Ownable2Step.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable2Step.sol)\n\npragma solidity ^0.8.0;\n\nimport \"./Ownable.sol\";\n\n/**\n * @dev Contract module which provides access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership} and {acceptOwnership}.\n *\n * This module is used through inheritance. It will make available all functions\n * from parent (Ownable).\n */\nabstract contract Ownable2Step is Ownable {\n    address private _pendingOwner;\n\n    event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Returns the address of the pending owner.\n     */\n    function pendingOwner() public view virtual returns (address) {\n        return _pendingOwner;\n    }\n\n    /**\n     * @dev Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one.\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual override onlyOwner {\n        _pendingOwner = newOwner;\n        emit OwnershipTransferStarted(owner(), newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`) and deletes any pending owner.\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual override {\n        delete _pendingOwner;\n        super._transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev The new owner accepts the ownership transfer.\n     */\n    function acceptOwnership() public virtual {\n        address sender = _msgSender();\n        require(pendingOwner() == sender, \"Ownable2Step: caller is not the new owner\");\n        _transferOwnership(sender);\n    }\n}\n"
      },
      "@openzeppelin/contracts/access/Ownable.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts (last updated v4.9.0) (access/Ownable.sol)\n\npragma solidity ^0.8.0;\n\nimport \"../utils/Context.sol\";\n\n/**\n * @dev Contract module which provides a basic access control mechanism, where\n * there is an account (an owner) that can be granted exclusive access to\n * specific functions.\n *\n * By default, the owner account will be the one that deploys the contract. This\n * can later be changed with {transferOwnership}.\n *\n * This module is used through inheritance. It will make available the modifier\n * `onlyOwner`, which can be applied to your functions to restrict their use to\n * the owner.\n */\nabstract contract Ownable is Context {\n    address private _owner;\n\n    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n    /**\n     * @dev Initializes the contract setting the deployer as the initial owner.\n     */\n    constructor() {\n        _transferOwnership(_msgSender());\n    }\n\n    /**\n     * @dev Throws if called by any account other than the owner.\n     */\n    modifier onlyOwner() {\n        _checkOwner();\n        _;\n    }\n\n    /**\n     * @dev Returns the address of the current owner.\n     */\n    function owner() public view virtual returns (address) {\n        return _owner;\n    }\n\n    /**\n     * @dev Throws if the sender is not the owner.\n     */\n    function _checkOwner() internal view virtual {\n        require(owner() == _msgSender(), \"Ownable: caller is not the owner\");\n    }\n\n    /**\n     * @dev Leaves the contract without owner. It will not be possible to call\n     * `onlyOwner` functions. Can only be called by the current owner.\n     *\n     * NOTE: Renouncing ownership will leave the contract without an owner,\n     * thereby disabling any functionality that is only available to the owner.\n     */\n    function renounceOwnership() public virtual onlyOwner {\n        _transferOwnership(address(0));\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Can only be called by the current owner.\n     */\n    function transferOwnership(address newOwner) public virtual onlyOwner {\n        require(newOwner != address(0), \"Ownable: new owner is the zero address\");\n        _transferOwnership(newOwner);\n    }\n\n    /**\n     * @dev Transfers ownership of the contract to a new account (`newOwner`).\n     * Internal function without access restriction.\n     */\n    function _transferOwnership(address newOwner) internal virtual {\n        address oldOwner = _owner;\n        _owner = newOwner;\n        emit OwnershipTransferred(oldOwner, newOwner);\n    }\n}\n"
      },
      "@openzeppelin/contracts/utils/Context.sol": {
        "content": "// SPDX-License-Identifier: MIT\n// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)\n\npragma solidity ^0.8.0;\n\n/**\n * @dev Provides information about the current execution context, including the\n * sender of the transaction and its data. While these are generally available\n * via msg.sender and msg.data, they should not be accessed in such a direct\n * manner, since when dealing with meta-transactions the account sending and\n * paying for execution may not be the actual sender (as far as an application\n * is concerned).\n *\n * This contract is only required for intermediate, library-like contracts.\n */\nabstract contract Context {\n    function _msgSender() internal view virtual returns (address) {\n        return msg.sender;\n    }\n\n    function _msgData() internal view virtual returns (bytes calldata) {\n        return msg.data;\n    }\n}\n"
      }
    },
    "settings": {
      "optimizer": {
        "enabled": true,
        "runs": 10000
      },
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      },
      "libraries": {}
    }
  }}