diff --git a/src/FirewallRouter.sol b/src/FirewallRouter.sol new file mode 100644 index 0000000..29a449e --- /dev/null +++ b/src/FirewallRouter.sol @@ -0,0 +1,57 @@ +// SPDX-License-Identifier: GNU General Public License Version 3 +// See license at: https://github.com/forta-network/forta-firewall-contracts/blob/master/LICENSE-GPLv3.md + +pragma solidity ^0.8.25; + +import "./interfaces/IExternalFirewall.sol"; +import "./interfaces/ICheckpointHook.sol"; +import "./interfaces/IFirewallAccess.sol"; +import "./FirewallPermissions.sol"; + +/** + * @notice This contract provides external firewall upgradeability. + */ +contract FirewallRouter is IExternalFirewall, FirewallPermissions { + IExternalFirewall public firewall; + + constructor(IExternalFirewall _firewall, IFirewallAccess _firewallAccess) { + firewall = _firewall; + _updateFirewallAccess(_firewallAccess); + } + + /** + * @notice Allows executing checkpoints externally from an integrator contract. The selector + * is checked against the checkpoints configured on this contract. + * @param selector Selector of the function which the checkpoint is configured and executed for + * @param ref The reference number to compare with the threshold + */ + function executeCheckpoint(address caller, bytes4 selector, uint256 ref) public onlyCheckpointExecutor { + firewall.executeCheckpoint(caller, selector, ref); + } + + /** + * @notice Allows executing checkpoints externally from an integrator contract. The selector + * is checked against the checkpoints configured on this contract. + * @param selector Selector of the function which the checkpoint is configured and executed for + * @param input The input value to use in checkpoint hash computation + */ + function executeCheckpoint(address caller, bytes4 selector, bytes32 input) public onlyCheckpointExecutor { + firewall.executeCheckpoint(caller, selector, input); + } + + /** + * @notice Accepts and stores an attestation to the transient storage introduced + * with EIP-1153. Multiple contracts that operate in the same transaction can call + * a singleton of this contract. The stored values are later used during checkpoint + * execution. + * @param attestation The set of fields that correspond to and enable the execution of call(s) + * @param attestationSignature Signature of EIP-712 message + */ + function saveAttestation(Attestation calldata attestation, bytes calldata attestationSignature) public { + firewall.saveAttestation(attestation, attestationSignature); + } + + function updateFirewall(IExternalFirewall newFirewall) public onlyFirewallAdmin { + firewall = newFirewall; + } +} diff --git a/src/examples/ExternalFirewallIntegration.sol b/src/examples/ExternalFirewallIntegration.sol index 55395d9..4ca3ea1 100644 --- a/src/examples/ExternalFirewallIntegration.sol +++ b/src/examples/ExternalFirewallIntegration.sol @@ -6,6 +6,7 @@ import {CheckpointExecutor} from "../CheckpointExecutor.sol"; import {ExternalFirewall} from "../ExternalFirewall.sol"; import {ISecurityValidator} from "../interfaces/ISecurityValidator.sol"; import {FirewallAccess} from "../FirewallAccess.sol"; +import {FirewallRouter} from "../FirewallRouter.sol"; import {IExternalFirewall} from "../interfaces/IExternalFirewall.sol"; import {ICheckpointHook} from "../interfaces/ICheckpointHook.sol"; import { @@ -35,6 +36,7 @@ contract ProtectedContract is CheckpointExecutor { /// for firewall integration. contract Deployer { event DeployedFirewall(ExternalFirewall firewall); + event DeployedFirewallRouter(FirewallRouter firewallRouter); event DeployedProtectedContract(ProtectedContract protectedContract); function deploy( @@ -50,7 +52,11 @@ contract Deployer { new ExternalFirewall(validator, ICheckpointHook(address(0)), attesterControllerId, firewallAccess); emit DeployedFirewall(externalFirewall); - ProtectedContract protectedContract = new ProtectedContract(externalFirewall); + /// deploy a router for firewall upgradeability + FirewallRouter firewallRouter = new FirewallRouter(externalFirewall, firewallAccess); + emit DeployedFirewallRouter(firewallRouter); + + ProtectedContract protectedContract = new ProtectedContract(firewallRouter); emit DeployedProtectedContract(protectedContract); /// will renounce later below @@ -60,6 +66,7 @@ contract Deployer { /// let protected contract execute checkpoints on the external firewall firewallAccess.grantRole(CHECKPOINT_EXECUTOR_ROLE, address(protectedContract)); + firewallAccess.grantRole(CHECKPOINT_EXECUTOR_ROLE, address(firewallRouter)); /// set the trusted attester: /// this will be necessary when "foo()" receives an attested call later.