creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "src/OwnableTriggerFactory.sol": {
        "content": "// SPDX-License-Identifier: Unlicensed\npragma solidity 0.8.22;\n\nimport {OwnableTrigger} from \"./OwnableTrigger.sol\";\nimport {TriggerMetadata} from \"./structs/Triggers.sol\";\n\ncontract OwnableTriggerFactory {\n  /// @dev Emitted when the factory deploys a trigger.\n  /// @param trigger The address at which the trigger was deployed.\n  /// @param owner The owner of the trigger.\n  /// @param name The human-readble name of the trigger.\n  /// @param description A human-readable description of the trigger.\n  /// @param logoURI The URI of a logo image to represent the trigger.\n  /// For other attributes, see the docs for the params of `deployTrigger` in\n  /// this contract.\n  /// @param extraData Extra metadata for the trigger.\n  event TriggerDeployed(\n    address trigger, address indexed owner, string name, string description, string logoURI, string extraData\n  );\n\n  /// @notice Deploys a new OwnableTrigger contract with the supplied owner and deploy salt.\n  /// @param _owner The owner of the trigger.\n  /// @param _metadata The metadata of the trigger.\n  /// @param _salt Used during deployment to compute the address of the new OwnableTrigger.\n  function deployTrigger(address _owner, TriggerMetadata memory _metadata, bytes32 _salt)\n    external\n    returns (OwnableTrigger _trigger)\n  {\n    _trigger = new OwnableTrigger{salt: _salt}(_owner);\n    emit TriggerDeployed(\n      address(_trigger), _owner, _metadata.name, _metadata.description, _metadata.logoURI, _metadata.extraData\n    );\n  }\n\n  /// @notice Call this function to determine the address at which a trigger\n  /// with the supplied configuration would be deployed. See `deployTrigger` for\n  /// more information on parameters and their meaning.\n  function computeTriggerAddress(address _owner, bytes32 _salt) external view returns (address _address) {\n    // https://eips.ethereum.org/EIPS/eip-1014\n    bytes32 _bytecodeHash = keccak256(bytes.concat(type(OwnableTrigger).creationCode, abi.encode(_owner)));\n    bytes32 _data = keccak256(bytes.concat(bytes1(0xff), bytes20(address(this)), _salt, _bytecodeHash));\n    _address = address(uint160(uint256(_data)));\n  }\n}\n"
      },
      "src/OwnableTrigger.sol": {
        "content": "// SPDX-License-Identifier: Unlicensed\npragma solidity 0.8.22;\n\nimport {BaseTrigger} from \"./abstract/BaseTrigger.sol\";\nimport {Ownable} from \"./lib/Ownable.sol\";\nimport {TriggerState} from \"./structs/StateEnums.sol\";\n\ncontract OwnableTrigger is BaseTrigger, Ownable {\n  /// @param _owner The address of the owner of the trigger, which is allowed to call `trigger()`.\n  constructor(address _owner) Ownable(_owner) {\n    _assertAddressNotZero(_owner);\n  }\n\n  /// @notice Callable by the owner to transition the state of the trigger to triggered.\n  function trigger() external onlyOwner {\n    _updateTriggerState(TriggerState.TRIGGERED);\n  }\n}\n"
      },
      "src/structs/Triggers.sol": {
        "content": "// SPDX-License-Identifier: Unlicensed\npragma solidity ^0.8.0;\n\nstruct TriggerMetadata {\n  // The name that should be used for safety modules that use the trigger.\n  string name;\n  // A human-readable description of the trigger.\n  string description;\n  // The URI of a logo image to represent the trigger.\n  string logoURI;\n  // Extra metadata for the trigger.\n  string extraData;\n}\n"
      },
      "src/abstract/BaseTrigger.sol": {
        "content": "// SPDX-License-Identifier: Unlicensed\npragma solidity 0.8.22;\n\nimport {ITrigger} from \"../interfaces/ITrigger.sol\";\nimport {TriggerState} from \"../structs/StateEnums.sol\";\n\n/**\n * @dev Core trigger interface and implementation. All triggers should inherit from this to ensure they conform\n * to the required trigger interface.\n */\nabstract contract BaseTrigger is ITrigger {\n  /// @notice Current trigger state.\n  TriggerState public state;\n\n  /// @dev Thrown when a state update results in an invalid state transition.\n  error InvalidStateTransition();\n\n  /// @dev Child contracts should use this function to handle Trigger state transitions.\n  function _updateTriggerState(TriggerState _newState) internal returns (TriggerState) {\n    if (!_isValidTriggerStateTransition(state, _newState)) revert InvalidStateTransition();\n    state = _newState;\n    emit TriggerStateUpdated(_newState);\n    return _newState;\n  }\n\n  /// @dev Reimplement this function if different state transitions are needed.\n  function _isValidTriggerStateTransition(TriggerState _oldState, TriggerState _newState)\n    internal\n    virtual\n    returns (bool)\n  {\n    // | From / To | ACTIVE      | FROZEN      | PAUSED   | TRIGGERED |\n    // | --------- | ----------- | ----------- | -------- | --------- |\n    // | ACTIVE    | -           | true        | false    | true      |\n    // | FROZEN    | true        | -           | false    | true      |\n    // | PAUSED    | false       | false       | -        | false     | <-- PAUSED is a safety module-level state\n    // | TRIGGERED | false       | false       | false    | -         | <-- TRIGGERED is a terminal state\n\n    if (_oldState == TriggerState.TRIGGERED) return false;\n    // If oldState == newState, return true since the safety module will convert that into a no-op.\n    if (_oldState == _newState) return true;\n    if (_oldState == TriggerState.ACTIVE && _newState == TriggerState.FROZEN) return true;\n    if (_oldState == TriggerState.FROZEN && _newState == TriggerState.ACTIVE) return true;\n    if (_oldState == TriggerState.ACTIVE && _newState == TriggerState.TRIGGERED) return true;\n    if (_oldState == TriggerState.FROZEN && _newState == TriggerState.TRIGGERED) return true;\n    return false;\n  }\n}\n"
      },
      "src/lib/Ownable.sol": {
        "content": "// SPDX-License-Identifier: Unlicensed\npragma solidity 0.8.22;\n\nimport {IOwnable} from \"src/interfaces/IOwnable.sol\";\n\n/**\n * @dev Contract module providing owner functionality, intended to be used through inheritance.\n * @dev No modifiers are provided to reduce bloat from unused code (even though this should be removed by the\n * compiler), as the child contract may have more complex authentication requirements than just a modifier from\n * this contract.\n */\nabstract contract Ownable is IOwnable {\n  /// @notice Contract owner.\n  address public owner;\n\n  /// @notice The pending new owner.\n  address public pendingOwner;\n\n  /// @dev Emitted when the owner address is updated.\n  event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);\n\n  /// @dev Emitted when the first step of the two step ownership transfer is executed.\n  event OwnershipTransferStarted(address indexed previousOwner, address indexed newOwner);\n\n  /// @dev Thrown when the caller is not authorized to perform the action.\n  error Unauthorized();\n\n  /// @dev Thrown when an invalid address is passed as a parameter.\n  error InvalidAddress();\n\n  /// @param _owner The contract owner.\n  constructor(address _owner) {\n    emit OwnershipTransferred(owner, _owner);\n    owner = _owner;\n  }\n\n  /// @notice Callable by the pending owner to transfer ownership to them.\n  /// @dev Updates the owner in storage to pendingOwner and resets the pending owner.\n  function acceptOwnership() external {\n    if (msg.sender != pendingOwner) revert Unauthorized();\n    delete pendingOwner;\n    address _oldOwner = owner;\n    owner = msg.sender;\n    emit OwnershipTransferred(_oldOwner, msg.sender);\n  }\n\n  /// @notice Starts the ownership transfer of the contract to a new account.\n  /// Replaces the pending transfer if there is one.\n  /// @param _newOwner The new owner of the contract.\n  function transferOwnership(address _newOwner) external onlyOwner {\n    _assertAddressNotZero(_newOwner);\n    pendingOwner = _newOwner;\n    emit OwnershipTransferStarted(owner, _newOwner);\n  }\n\n  /// @dev Revert if the address is the zero address.\n  function _assertAddressNotZero(address _address) internal pure {\n    if (_address == address(0)) revert InvalidAddress();\n  }\n\n  modifier onlyOwner() {\n    if (msg.sender != owner) revert Unauthorized();\n    _;\n  }\n}\n"
      },
      "src/structs/StateEnums.sol": {
        "content": "// SPDX-License-Identifier: Unlicensed\npragma solidity 0.8.22;\n\nenum TriggerState {\n  ACTIVE,\n  TRIGGERED,\n  FROZEN\n}\n"
      },
      "src/interfaces/ITrigger.sol": {
        "content": "// SPDX-License-Identifier: Unlicensed\npragma solidity ^0.8.0;\n\nimport {TriggerState} from \"../structs/StateEnums.sol\";\n\n/**\n * @dev The minimal functions a trigger must implement to work with the Cozy Safety Module protocol.\n */\ninterface ITrigger {\n  /// @dev Emitted when a trigger's state is updated.\n  event TriggerStateUpdated(TriggerState indexed state);\n\n  /// @notice The current trigger state.\n  function state() external returns (TriggerState);\n}\n"
      },
      "src/interfaces/IOwnable.sol": {
        "content": "// SPDX-License-Identifier: Unlicensed\npragma solidity ^0.8.0;\n\ninterface IOwnable {\n  /// @notice Callable by the pending owner to transfer ownership to them.\n  function acceptOwnership() external;\n\n  /// @notice The current owner.\n  function owner() external view returns (address);\n\n  /// @notice Callable by the current owner to transfer ownership to a new account. The new owner must call\n  /// acceptOwnership() to finalize the transfer.\n  function transferOwnership(address newOwner_) external;\n}\n"
      }
    },
    "settings": {
      "remappings": [
        "@openzeppelin/=lib/openzeppelin-contracts/",
        "@chainlink/=lib/chainlink/",
        "chainlink/=lib/chainlink/contracts/",
        "ds-test/=lib/forge-std/lib/ds-test/src/",
        "forge-std/=lib/forge-std/src/",
        "solmate/=lib/solmate/src/",
        "uma-protocol/=lib/uma-protocol/"
      ],
      "optimizer": {
        "enabled": true,
        "runs": 10000000
      },
      "metadata": {
        "useLiteralContent": false,
        "bytecodeHash": "ipfs",
        "appendCBOR": true
      },
      "outputSelection": {
        "*": {
          "*": [
            "evm.bytecode",
            "evm.deployedBytecode",
            "devdoc",
            "userdoc",
            "metadata",
            "abi"
          ]
        }
      },
      "evmVersion": "paris",
      "viaIR": false,
      "libraries": {}
    }
  }}