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
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.
Last updated