I was looking at the smart contract wallets used by instadapp.
There are two methods:
- spell: performs a single delegatecall
- cast: performs a batch delegatecall.
It looks like the wallet contract delegatecalls into a connector (kyber.sol) and then it executes the logic.
As a result, the wallet contract is the user’s identity for other contracts on Ethereum and of course it should hold the ERC20 tokens.
Unfortunately, the wallet contracts rely on msg.sender to authenticate the owner of the wallet contract. This means the owner must sign an Ethereum Transaction and pay for their own gas in order to use instadapp. As we have seen with the volatility gas prices recently, it can lead to the user’s transaction getting stuck and for them to manually bump the gas price several times to get it in.
If the Instadapp wallet contract offered an alternative method to authenticate the user by verifying sign messages (e.g. ecrecover), then the user can use third party relay infrastructure that specialises in sending transactions to Ethereum (i.e., meta-transactions). Several wallets already do this for their users including argent / gnosis safe, either to pay for the user’s gas or just to improve the user experience. Disclaimer: I work on https://www.anydot.dev/
It looks pretty easy to add meta-transaction support to instadapp. I put together Simple Wallet to demonstrate the easiest approach. It just checks that the message hash is unique and the user has signed it. To apply it for instadapp, you just need to modify cast/spell to check the signed message before executing the delegatecall.
As a side note, I recommend adding a function that just performs a “.call” to another smart contract - so its just as expressive as an Ethereum Transaction. Maybe you can call it wand
p.s. there are more exotic ways to do replay protection like MultiNonce, but the simple wallet has minimal gas overhead, it is easier to build client-side tooling & verify that it works as you expect.