Reference

OctopusWallet (the borrowed code)

What each arm runs. Nothing else.

Functions

FunctionNotes
execute(Call[] calls, uint256 deadline, bytes signature)Anyone may submit. Runs the calls if the wallet's own key signed them. All or nothing.
digestFor(calls, nonce, deadline) viewThe 32 bytes the wallet key must sign.
domainSeparator() viewEIP-712 domain bound to the wallet's address and the chain.
nonce() viewThe next nonce for this wallet.
receive(), ERC-721 and ERC-1155 receiversThe wallet can still receive anything.

Digest

EIP712Domain: name "Octopus Wallet", version "1", chainId, verifyingContract = the wallet
Execute(bytes32 callsHash, uint256 nonce, uint256 deadline)
callsHash = keccak256(concat(keccak256(abi.encode(to, value, keccak256(data))) for each call))

Storage

The nonce lives at slot keccak256("octopus.wallet.nonce.v1"), not at slot 0. A wallet's own storage may be used by other delegations, so Octo never uses the low slots.

Errors

Expired()
BadSignature()
CallFailed(uint256 index, bytes reason)

The signature must be a 65-byte ECDSA signature by the wallet's own key. There is no owner and no upgrade.