{
  "$schema": "https://ide.bitauth.com/authentication-template-v0.schema.json",
  "description": "// Imported from cashscript \n    pragma cashscript ^0.8.1;\n\n// Unspent Phi\n//\n// Annuity v2 \n//\n// Annuity: equal payments at regular intervals using rolling timelocks.\n//\n// [ ] Spending transaction must use version 2.\n// [ ] The input must have aged for a predefined number of blocks (the period)\n// [ ] All utxos must be processed atomically. One coin per tx, no merging.\n// [ ] If enough funds exist for future payments, send the remainder back to the contract,\n// [ ] Otherwise, liquidate the contract via a balloon payment to the recipient.\n// \n// Implementation notes: contract requires 32-byte locking bytecode style address.\n// \n// String & op_return serializations:\n//\n// A,2,<period>,<receiptLockingBytecode>,<installment>,<contractBytecode>\n// \n// 6a 047574786f\n// 01 41\n// 01 02\n// ... period, receipt, installment\n// ... lockingBytecode\n\ncontract Annuity(\n\n  // interval for payouts, in blocks\n  int period,\n\n  // LockingBytecode of the beneficiary, the address receiving payments\n  bytes recipientLockingBytecode,\n\n  // amount paid in each installment\n  int installment,\n\n  // extra allowance for administration of contract\n  // fees are paid from executors' allowance. \n  int executorAllowance\n) {\n  function execute() {\n\n    // Force tx version 2 to force BIP68 support\n    require(tx.version >= 2);\n\n    // Assure a rolling timelock is satisfied\n    require(tx.age >= period);\n\n    // Limit to a single utxo input\n    require(tx.inputs.length == 1);\n\n    // Get the utxo value \n    int currentValue = tx.inputs[this.activeInputIndex].value;\n  \n    // Check that the first output sends to the intended recipient. \n    require(tx.outputs[0].lockingBytecode == recipientLockingBytecode);\n\n    // if enough funds exist for a least two more payments,\n    // return the balance to the contract, minus executor's fee.\n    if(currentValue > installment*2){\n      // Calculate the value returned by the contract\n      int returnedValue = currentValue - installment - executorAllowance;\n\n      // Check that the outputs send the correct amounts\n      require(tx.outputs[0].value >= installment);\n\n      // require the second output to match the active bytecode\n      require(tx.outputs[1].lockingBytecode == new LockingBytecodeP2SH32(hash256(this.activeBytecode)));\n      require(tx.outputs[1].value >= returnedValue);\n    } \n    // Otherwise, send a final balloon payment instead of a partial payment\n    else{\n      int balloonPaymentValue = currentValue - executorAllowance;\n      // Check that the outputs send the correct amounts\n      require(tx.outputs[0].value >= balloonPaymentValue);\n    }\n  }\n}",
  "name": "Annuity",
  "entities": {
    "parameters": {
      "description": "Contract creation and function parameters",
      "name": "parameters",
      "scripts": [
        "lock",
        "unlock_lock"
      ],
      "variables": {
        "function_index": {
          "description": "Script function index to execute",
          "name": "function_index",
          "type": "WalletData"
        },
        "executor_allowance": {
          "description": "\"executorAllowance\" parameter of this contract",
          "name": "executorAllowance",
          "type": "WalletData"
        },
        "installment": {
          "description": "\"installment\" parameter of this contract",
          "name": "installment",
          "type": "WalletData"
        },
        "recipient_locking_bytecode": {
          "description": "\"recipientLockingBytecode\" parameter of this contract",
          "name": "recipientLockingBytecode",
          "type": "WalletData"
        },
        "period": {
          "description": "\"period\" parameter of this contract",
          "name": "period",
          "type": "WalletData"
        }
      }
    }
  },
  "scenarios": {
    "evaluate_function": {
      "data": {
        "bytecode": {
          "function_index": "0",
          "executor_allowance": "0xdc05",
          "installment": "0x1027",
          "recipient_locking_bytecode": "0x76a9145ad61b729b4170216bf57cd02c606ca52d13b89a88ac",
          "period": "0x01"
        },
        "currentBlockHeight": 2,
        "currentBlockTime": 1692281733,
        "keys": {
          "privateKeys": {}
        }
      },
      "description": "An example evaluation where this script execution passes.",
      "name": "Evaluate",
      "transaction": {
        "inputs": [
          {
            "outpointIndex": 1,
            "outpointTransactionHash": "93b24ca05cf93407f8358ea419de65afb432b07b191969285e3e0537549760ab",
            "sequenceNumber": 1,
            "unlockingBytecode": [
              "slot"
            ]
          },
          {
            "outpointIndex": 1,
            "outpointTransactionHash": "30bc5066c3cd50fcdf46432d942a7776b7804a740cf6fc9e3b605b8da47450ba",
            "sequenceNumber": 1,
            "unlockingBytecode": {}
          },
          {
            "outpointIndex": 0,
            "outpointTransactionHash": "93b24ca05cf93407f8358ea419de65afb432b07b191969285e3e0537549760ab",
            "sequenceNumber": 1,
            "unlockingBytecode": {}
          },
          {
            "outpointIndex": 0,
            "outpointTransactionHash": "30bc5066c3cd50fcdf46432d942a7776b7804a740cf6fc9e3b605b8da47450ba",
            "sequenceNumber": 1,
            "unlockingBytecode": {}
          }
        ],
        "locktime": 215,
        "outputs": [
          {
            "lockingBytecode": "76a9145ad61b729b4170216bf57cd02c606ca52d13b89a88ac",
            "valueSatoshis": 10000
          },
          {
            "lockingBytecode": {},
            "valueSatoshis": 153300
          }
        ],
        "version": 2
      },
      "sourceOutputs": [
        {
          "lockingBytecode": [
            "slot"
          ],
          "valueSatoshis": 41200
        },
        {
          "lockingBytecode": [
            "slot"
          ],
          "valueSatoshis": 41200
        },
        {
          "lockingBytecode": [
            "slot"
          ],
          "valueSatoshis": 41200
        },
        {
          "lockingBytecode": [
            "slot"
          ],
          "valueSatoshis": 41200
        }
      ]
    }
  },
  "scripts": {
    "unlock_lock": {
      "passes": [
        "evaluate_function"
      ],
      "name": "unlock",
      "script": "// \"execute\" function parameters\n// none\n\n// \"Annuity\" contract constructor parameters\n<executor_allowance> // int = <0xdc05>\n<installment> // int = <0x1027>\n<recipient_locking_bytecode> // bytes25 = <0x76a9145ad61b729b4170216bf57cd02c606ca52d13b89a88ac>\n<period> // int = <0x01>",
      "unlocks": "lock"
    },
    "lock": {
      "lockingType": "p2sh32",
      "name": "lock",
      "script": "OP_TXVERSION\nOP_2\nOP_GREATERTHANOREQUAL\nOP_VERIFY\nOP_CHECKSEQUENCEVERIFY\nOP_DROP\nOP_TXINPUTCOUNT\nOP_1\nOP_NUMEQUALVERIFY\nOP_INPUTINDEX\nOP_UTXOVALUE\nOP_0\nOP_OUTPUTBYTECODE\nOP_ROT\nOP_EQUALVERIFY\nOP_2DUP\nOP_SWAP\nOP_2\nOP_MUL\nOP_GREATERTHAN\nOP_IF\nOP_2DUP\nOP_SWAP\nOP_SUB\nOP_3\nOP_PICK\nOP_SUB\nOP_0\nOP_OUTPUTVALUE\nOP_3\nOP_PICK\nOP_GREATERTHANOREQUAL\nOP_VERIFY\nOP_1\nOP_OUTPUTBYTECODE\n<0xaa20>\nOP_ACTIVEBYTECODE\nOP_HASH256\nOP_CAT\n<0x87>\nOP_CAT\nOP_EQUALVERIFY\nOP_1\nOP_OUTPUTVALUE\nOP_OVER\nOP_GREATERTHANOREQUAL\nOP_VERIFY\nOP_DROP\nOP_ELSE\nOP_DUP\nOP_3\nOP_PICK\nOP_SUB\nOP_0\nOP_OUTPUTVALUE\nOP_OVER\nOP_GREATERTHANOREQUAL\nOP_VERIFY\nOP_DROP\nOP_ENDIF\nOP_2DROP\nOP_DROP\nOP_1"
    }
  },
  "supported": [
    "BCH_SPEC"
  ],
  "version": 0
}