creation_sourcecode: {{
    "language": "Solidity",
    "sources": {
      "src/Hostage.sol": {
        "content": "// SPDX-License-Identifier: LicenseRef-VPL+AGPL-3.0-only\npragma solidity ^0.8.25;\n\n/// An error emitted if a caller is not the manager.\nerror NotManager();\n\n/// An error emitted if a caller is not the attacker.\nerror NotAttacker();\n\n/// An error emitted if the attacker has not returned hostages.\nerror HostageUnreturned();\n\n/// An error emitted if the manager attempts to end negotiations early.\nerror NegotiationsOngoing();\n\n/**\n  This is the interface for a contract able to describe its `owner`.\n*/\ninterface Ownable {\n\n  /**\n    Provide the address of this contract's owner.\n\n    @return _ The address of the owner of this contract.\n  */\n  function owner () external view returns (address);\n}\n\n/**\n  @custom:benediction DEVS BENEDICAT ET PROTEGAT CONTRACTVM MEUM\n  @title A contract for performing hostage negotiation with an attacker.\n  @author Tim Clancy <tim-clancy.eth>\n  @custom:terry \"America is due for some wrath of God.\"\n\n  This contract allows for escrow-based hostage negotiation over contract\n  ownership. The contract is funded with Ether after it is deployed with\n  the `manager` of negotiations. The manager is able to withdraw Ether\n  after the set time period, in case negotiations fail. The manager is able\n  to specify `hostage` contracts that must be returned to the specified\n  `home` address; if the hostages are returned then the attacker is free to\n  withdraw their reward.\n\n  @custom:date May 23rd, 2024.\n*/\ncontract Hostage {\n\n  /// The address of the caller managing negotiations.\n  address public manager;\n\n  /// The address of the attacker.\n  address public attacker;\n\n  /// The address where ownership of the hostage contracts must be returned.\n  address public home;\n\n  /**\n    This is the time when negotiations end and the manager is able to\n    withdraw the escrowed negotiation funds. This timelock prevents the\n    manager from robbing the attacker.\n  */\n  uint256 public escrowTime;\n\n  /// The set of contract hostages that must be returned.\n  address[] public hostages;\n\n  /** \n    Emitted when funding with negotiation balance.\n\n    @param user The user who sent Ether.\n    @param amount The amount of Ether sent.\n  */\n  event Fund (\n    address indexed user,\n    uint256 amount\n  );\n\n  /// A modifier such that only the manager may call a function.\n  modifier onlyManager () {\n    if (msg.sender != manager) {\n      revert NotManager();\n    }\n    _;\n  }\n\n  /// A modifier such that only the attacker may call a function.\n  modifier onlyAttacker () {\n    if (msg.sender != attacker) {\n      revert NotAttacker();\n    }\n    _;\n  }\n\n  /**\n    Construct a new instance of a hostage contract.\n\n    @param _manager The manager of the negotiations.\n    @param _attacker The attacker.\n    @param _home The address where hostages are returned.\n    @param _escrowTime The time when negotiations end.\n  */\n  constructor (\n    address _manager,\n    address _attacker,\n    address _home,\n    uint256 _escrowTime\n  ) {\n    manager = _manager;\n    attacker = _attacker;\n    home = _home;\n    escrowTime = _escrowTime;\n  }\n\n  /**\n    Allow the manager to create a new hostage negotiation.\n    The manager may only create a new negotiation if the last one ended.\n\n    @param _manager The manager of the negotiations.\n    @param _attacker The attacker.\n    @param _home The address where hostages are returned.\n    @param _escrowTime The time when negotiations end.\n  */\n  function changeDeal (\n    address _manager,\n    address _attacker,\n    address _home,\n    uint256 _escrowTime\n  ) external onlyManager {\n    if (block.timestamp < escrowTime) {\n      revert NegotiationsOngoing();\n    }\n    manager = _manager;\n    attacker = _attacker;\n    home = _home;\n    escrowTime = _escrowTime;\n  }\n\n  /**\n    Allow the manager to define hostages that must be returned.\n\n    @param _hostages An array of hostage contract addresses.\n  */\n  function setHostages (\n    address[] memory _hostages\n  ) external onlyManager {\n    if (block.timestamp < escrowTime) {\n      revert NegotiationsOngoing();\n    }\n    hostages = _hostages;\n  }\n\n  /**\n    Allow the attacker to claim the negotiated funds only if they have\n    returned all hostages.\n  */\n  function hostagesReturned () external onlyAttacker {\n    for (uint256 i = 0; i < hostages.length; i++) {\n      if (Ownable(hostages[i]).owner() != home) {\n        revert HostageUnreturned();\n      }\n    }\n    msg.sender.call{value: address(this).balance}(\"\");\n  }\n\n  /**\n    Allow the manager to claim the negotiated funds if the negotiation fails.\n    The manager must wait until `escrowTime` to do this.\n  */\n  function negotiationFailed () external onlyManager {\n    if (block.timestamp < escrowTime) {\n      revert NegotiationsOngoing();\n    }\n    manager.call{value: address(this).balance}(\"\");\n  }\n\n  /**\n    Handle negotiation balance deposit.\n  */\n  receive () external payable{\n    emit Fund(\n      msg.sender, \n      msg.value\n    );\n  }\n}\n"
      }
    },
    "settings": {
      "remappings": [
        "forge-std/=lib/forge-std/src/"
      ],
      "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": {}
    }
  }}