# HinkalInLogic

**Overview**

`HinkalInLogic` and `HinkalInLogicBase` implement the execution-layer logic that `Hinkal.sol` delegates to. They manage:

* Approval UTXOs lifecycle (creation, modification, spending)
* External protocol execution with precise allowance/balance accounting
* Proofless deposit flow (token/NFT collection and UTXO formation)

**Files**

* `contracts/HinkalInLogicBase.sol` — core logic and helpers
* `contracts/HinkalInLogic.sol` — concrete implementation (external actions, proofless deposit)

***

#### Storage&#x20;

* `mapping(address => ApprovedUtxo[]) approvedUtxos` — per interaction/externalAddress approval notes

Approval UTXOs represent token-specific allowances scoped by an `inHinkalAddress` (a stealth/view context). They enable privacy-preserving approvals that can later be spent during operations.

***

#### Logic Actions (driven by CircomData.hinkalLogicArgs.hinkalLogicAction)

1. ONLY\_APPROVAL (1)
   * Sends flat fee to relay and returns immediately. Used to publish approvals without execution.
2. EXECUTE (2)
   * Full external call flow: spend approvals, perform external call atomically, pay relay, reconcile balances/allowances, mint UTXOs.

Entry point:

```solidity
function inHinkalTransact(CircomData circomData, int256[] approvalChangesPerToken)
    external payable returns (UTXO[] utxoSet)
```

Routes to one of: ONLY\_APPROVAL, or EXECUTE via `inHinkalExecutionFlow` (reverts on unknown action).

***

#### Approvals: Create/Modify/Spend

**handleApprovalUtxos**

```solidity
function handleApprovalUtxos(CircomData circomData) public returns (int256[] result)
```

* Iterates `UseApprovalUTXOData[]` per token index to apply per-externalAddress approval deltas.
* For each tuple `(externalAddress, token, inHinkalAddress, approvalChange)`:
  * If an approval note exists, update or remove when new amount hits zero.
  * If not found, append a new approval UTXO (only when `approvalChange >= 0`).
  * Always adjust aggregate ERC20 allowance via `approveMore` to reflect the net change.
* Emits `NewApprovedUtxo(externalAddress, tokenAddress, approvalChange, inHinkalAddress)` per token.

***

#### EXECUTE Path: inHinkalExecutionFlow

```solidity
function inHinkalExecutionFlow(CircomData circomData) internal returns (UTXO[] utxoSet)
```

1. Spend approvals: `spendApprovedUtxos(circomData)`
   * Validates the user owns matching approval UTXOs for tokens being spent.
   * Decrements or removes approval notes according to `executeApprovalChanges`.
   * Tracks any tokens that must remain balance-stable (unspent set).
2. Snapshot balances/allowances: before execution
3. Safety checks:
   * `erc20SafetyCheck` blocks dangerous ERC20 methods in metadata selectors (approve, mint, transferFrom, etc.).
   * Parse `externalActionMetadata` and compute `ethAmount` to attach when the proof indicates ETH spend.
   * Enforce signature/deadline via helper (see `HinkalHelper.checkInLogicMetadata`).
4. External call: `(success, returnData) = externalAddress.call{value: ethAmount}(callData)`
   * Bubble up revert reasons if present; else use a generic error.
5. Relay payment: send flat fee in `feeToken` if configured.
6. Snapshot balances/allowances: after execution
7. UTXO formation and allowance reconciliation:
   * `formUtxosAndCheckSpendings` compares pre/post balances and allowances:
     * Positive balance deltas mint UTXOs for that token.
     * Negative balance deltas must match allowance spend (plus relay fee when feeToken matches), else revert.
     * If aggregate allowance spend exceeds intended individual spend, `approveMore` restores the difference, ensuring aggregate == sum(individual).
   * Emits `NewApprovedUtxo` reflecting the final per-token execution change.
8. Unspent-invariant: tokens identified as unspent must have identical balances before and after.

Outcome: returns `UTXO[]` to be turned into commitments by `Hinkal.sol`.

***

#### External Actions (HinkalInLogic.sol)

```solidity
function handleRunExternalAction(CircomData circomData, int256[] approvalChangesPerToken)
    external returns (UTXO[])
```

* Computes `deltaAmountChanges[i] = calculateDeltaAmount(...)` per token.
* For negative deltas, transfers tokens/NFTs to `externalAddress` pre-call.
* Invokes `IExternalActionV2(externalAddress).runAction(circomData, deltaAmountChanges)` which returns `UTXO[]` created during the action.

This path is used by `Hinkal._internalRunExternalAction` to integrate with DeFi targets in a privacy-preserving, atomic way.

***

#### Proofless Deposit (HinkalInLogic.sol)

```solidity
function handleProoflessDeposit(address[] erc20Addresses, uint256[] amounts, uint256[] tokenIds, StealthAddressStructure[] stealthAddressStructures)
    public payable returns (UTXO[] utxoArray)
```

* Groups identical `(token, tokenId)` pairs with `calcTokenChangesForProoflessDeposit` and accumulates amounts (rejects duplicate NFTs).
* Pulls funds from `msg.sender` via `handleTransfersFromProoflessDeposit` and asserts `balanceAfter - balanceBefore == amount` per token.
* Forms UTXOs one-to-one with user inputs using `handleUtxoCreationEach`, setting `timeStamp` to `block.timestamp`.

Used by `Hinkal.prooflessDeposit` to create on-chain commitments without a ZK proof.

***

#### Safety and Helpers

* `erc20SafetyCheck`: blacklist of ERC20 methods (approve/mint/transferFrom, etc.) disallowed in external calls via metadata selector checks.
* `isERC20`: coarse detection to apply safety checks only when necessary.
* `calculateBalances`/`calculateAllowances`: snapshot helpers.
* `approveMore`: adjusts aggregate ERC20 allowances to match individual approval changes exactly.

***

#### Events

* `NewApprovedUtxo(address approveTo, address tokenAddress, int256 amount, uint256 inHinkalAddress)`

These events allow indexers and frontends to reconstruct approval states independently of private commitments.

***

#### Reverts and Invariants

* inHinkalTransact: "msg.value non allowed for inHinkalTransactions"
* spendApprovedUtxos: ownership and exact-spend assertions; "you cannot spend something you do not own"
* inHinkalExecutionFlow:
  * External call bubble-up or "Hinkal: External call failed"
  * Unspent equality: "array's must be equal"
  * Allowance/balance match: "balance and allowance Dif mismatch"
* Approvals: guard against negative creation or out-of-range indices
* Proofless deposit: length checks, duplicate NFT protection, and exact transfer assertions

***

#### Integration Surface with Hinkal.sol

* `Hinkal._inHinkalTransact` delegates to `inHinkalTransact`
* `Hinkal._internalRunExternalAction` delegates to `handleRunExternalAction`
* `Hinkal._handleApprovalUtxos` delegates to `handleApprovalUtxos`
* `Hinkal.prooflessDeposit` delegates to `handleProoflessDeposit`

This separation keeps `Hinkal` orchestration minimal while letting `HinkalInLogic` focus on evolving execution semantics.
