creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "src/helpers/MerkleOwner.sol": {
        "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity ^0.8.20;\n\nimport {IMerkleManager} from \"src/interfaces/IMerkleManager.sol\";\n\ncontract MerkleOwner {\n\n    /// @notice Address of the governance contract.\n    address public governance;\n\n    /// @notice Address of the future governance contract.\n    address public futureGovernance;\n\n    /// @notice Address authorized to call the execute function.\n    mapping(address => bool) public isAllowed;\n\n    /// @notice Address who owns / manages the Merkle.\n    address public merkleManager;\n\n\n    ////////////////////////////////////////////////////////////\n    /// --- EVENTS & ERRORS\n    ////////////////////////////////////////////////////////////\n\n    /// @notice Event emitted when a new governance is proposed.\n    event GovernanceProposed(address indexed newGovernance);\n\n    /// @notice Event emitted when the governance is changed.\n    event GovernanceChanged(address indexed newGovernance);\n\n    /// @notice Throws if caller is not the governance.\n    error GOVERNANCE();\n\n    /// @notice Throws if caller is not allowed.\n    error NOT_ALLOWED();\n\n\n    ////////////////////////////////////////////////////////////\n    /// --- MODIFIERS\n    ////////////////////////////////////////////////////////////\n\n    modifier onlyGovernance() {\n        if (msg.sender != governance) revert GOVERNANCE();\n        _;\n    }\n\n    modifier onlyAllowed() {\n        if (!isAllowed[msg.sender]) revert NOT_ALLOWED();\n        _;\n    }\n\n    constructor(address owner_, address merkleManager_) {\n        governance = owner_;\n        merkleManager = merkleManager_;\n    }\n\n    ////////////////////////////////////////////////////////////////\n    /// --- ADMIN FUNCTIONS\n    ///////////////////////////////////////////////////////////////\n\n    /// @notice Allow an address to call the execute function.\n    /// @param _address Address to allow.\n    function allowAddress(address _address) external onlyGovernance {\n        isAllowed[_address] = true;\n    }\n\n    /// @notice Disallow an address to call the execute function.\n    /// @param _address Address to disallow.\n    function disallowAddress(address _address) external onlyGovernance {\n        isAllowed[_address] = false;\n    }\n\n    /// @notice Transfer the governance to a new address.\n    /// @param _governance Address of the new governance.\n    function transferGovernance(address _governance) external onlyGovernance {\n        emit GovernanceProposed(futureGovernance = _governance);\n    }\n\n    /// @notice Accept the governance transfer.\n    function acceptGovernance() external {\n        if (msg.sender != futureGovernance) revert GOVERNANCE();\n        emit GovernanceChanged(governance = msg.sender);\n    }\n    \n    ////////////////////////////////////////////////////////////\n    /// --- AUTHORIZED\n    ////////////////////////////////////////////////////////////\n\n    function multiFreeze(address[] calldata tokens) external onlyAllowed() {\n        IMerkleManager(merkleManager).multiFreeze(tokens);\n    }\n\n    function multiSet(address[] calldata tokens, bytes32[] calldata _merkleRoots) external onlyAllowed() {\n        IMerkleManager(merkleManager).multiSet(tokens, _merkleRoots);\n    }\n\n    function multiUpdateMerkleRoot(address[] calldata tokens, bytes32[] calldata _merkleRoots) external onlyAllowed() {\n        IMerkleManager(merkleManager).multiUpdateMerkleRoot(tokens, _merkleRoots);\n    }\n\n    ////////////////////////////////////////////////////////////\n    /// --- EMERGENCY ONLY\n    ////////////////////////////////////////////////////////////\n\n    /// @notice Transfer the ownership of the MerkleManager contract from that contract to another address.\n    function emergencyTransferOwnership(address _newOwner) external onlyGovernance {\n        IMerkleManager(merkleManager).transferOwnership(_newOwner);\n    }\n\n}"
      },
      "src/interfaces/IMerkleManager.sol": {
        "content": "// SPDX-License-Identifier: AGPL-3.0-only\npragma solidity ^0.8.20;\n\ninterface IMerkleManager {\n    /// @dev Freezes multiple tokens by setting their Merkle roots to zero.\n    /// Can only be called by an authorized address.\n    /// @param tokens Array of token addresses to freeze.\n    function multiFreeze(address[] calldata tokens) external;\n\n    /// @dev Sets new Merkle roots for multiple tokens.\n    /// Can only be called by an authorized address.\n    /// Each token must be frozen (Merkle root set to zero) before setting a new Merkle root.\n    /// @param tokens Array of token addresses for which to set new Merkle roots.\n    /// @param _merkleRoots Array of new Merkle roots corresponding to the tokens array.\n    function multiSet(address[] calldata tokens, bytes32[] calldata _merkleRoots) external;\n\n    /// @dev Similar as above\n    function multiUpdateMerkleRoot(address[] calldata tokens, bytes32[] calldata _merkleRoots) external;\n\n    /// @dev Transfers ownership of the MerkleManager contract.\n    function transferOwnership(address newOwner) external;\n}\n"
      }
    },
    "settings": {
      "remappings": [
        "forge-std/=lib/forge-std/src/",
        "openzeppelin-contracts/=lib/openzeppelin-contracts/contracts/",
        "solady/=lib/solady/src/",
        "solmate/=lib/solmate/src/",
        "@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/",
        "AddressBook/=lib/AddressBook/src/",
        "ds-test/=lib/forge-std/lib/ds-test/src/",
        "erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/"
      ],
      "optimizer": {
        "enabled": true,
        "runs": 200
      },
      "metadata": {
        "useLiteralContent": false,
        "bytecodeHash": "ipfs",
        "appendCBOR": true
      },
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      },
      "evmVersion": "paris",
      "viaIR": false,
      "libraries": {}
    }
  }}