# Security, security & security

### TLDR

By combining **ERC-4337, session keys, function selectors, and call policies**, Otomato enables seamless transaction automation **without compromising security**:

* **Users stay in full control**—We never takes custody of funds.
* **No broad wallet access**—We can only perform **pre-approved actions** within strict limits.
* **Minimal risk**—even if a session key were compromised, it **can’t transfer funds**, only execute authorized operations. Funds always stay in the user’s wallet.

### Security at Otomato

{% hint style="info" %}
Security is key at Otomato. We are, and will always remain, 100% self-custodial.
{% endhint %}

Now, you might ask: _"How do we automate transactions if we don’t have access to users' funds?"_

And I would answer: _"What a great question!"_

One simple approach could be **pre-signed transactions**—asking users to sign transactions in advance and we broadcasting it at the right time.

But that’s a no-go for **many** reasons:

* Nonce management nightmare
* **Horrible UX** (it would be such a friction to pre-sign all the transactions you want us to automate)
* **Limited flexibility**—many use cases require dynamic calldata, which we can’t predict in advance.

So, how do we automate transactions while keeping security and flexibility intact?

Here’s the good part: **We don’t deploy any custom smart contracts**—we rely on the battle-tested **ERC-4337** infrastructure, which means minimal risk for users.

Now, you might ask: _"Wait, isn’t ERC-4337 for account abstraction?"_

And again, what a great question! Yes, ERC-4337 is **best known** for account abstraction, but that’s not the reason we use it. We leverage it for something even cooler: **session keys**.

### Session Keys

Session keys let Otomato automate transactions **without full wallet access**.

A session key is a **temporary key** that can sign specific transactions on behalf of the smart contract wallet owner, but only within predefined constraints.

Let’s take the example of **automating an AAVE USDC deposit**:

* The user wants Otomato to **deposit USDC into AAVE** when rates are high.
* Instead of manually approving and depositing each time, they create a **session key** with permissions.

To run this automation, Otomato needs to execute two transactions: **Approve USDC spending for AAVE** and **Deposit USDC into AAVE**

For now, we’ll focus on the first step: approving USDC spending.

When creating a session key, we bind it to a **specific smart contract address**, meaning the key **can only interact with that contract**. In this case, the user must allow Otomato to interact with the **USDC contract** (since approvals are specific to ERC-20 tokens, not the apps that use them).

However, granting permissions at the **smart contract level is risky**. If a session key can approve USDC spending, it could also call **any** function on the USDC contract, including `transfer()`, which could send funds elsewhere.

That’s where **function selectors** come in.

### Function Selector

A function selector **ensures that a session key can only call specific functions on specific contracts**.

For the **USDC Approval**, we configure the session key to call the `approve()` function only, which means Otomato won’t be able to call `transfer()` anymore.

So, that solves the problem, right?

Not quite. Function selectors control _which_ functions can be called, but not _how_ they’re used. If we allow `approve()`, an attacker with access to the session key could still call:

`approve(attackerAddress, MAX_UINT);`

This would grant them **unlimited access** to the user’s funds, allowing them to drain the wallet without needing `transfer()`.

That’s where **call policies** come in.

### Call Policies

While function selectors limit _which_ functions can be used, **call policies add another layer of security by controlling how they are used**. This is done by enforcing some parameters of the function.

For example, for our **USDC approval**, call policies ensure USDC **can only be approved to AAVE’s lending pool.**

This means that even if someone got hold of the session key, **they couldn’t approve USDC to their own wallet.**
