The Ocean: Accounting Hub
An explanation of the Ocean architecture
Shell Protocol is a new paradigm that reimagines how to build and compose financial primitives like AMMs, lending pools, or algorithmic stablecoins. The key to this achievement is the Ocean, a new shared accounting system that reduces code complexity and costs up to four times less gas for multi-step transactions.
To understand this revolution and what makes it possible, we first need to understand a bit about DeFi’s great ambition and its current limitations.
Financial primitives are the building blocks of DeFi. Often described as “money legos,” these simple components can be connected together (“composed”) into complex systems and transactions.
Composability is perhaps the single most important feature of DeFi, opening the door to financial innovation. For example, consider this transaction: depositing ETH to mint DAI, then swapping DAI for USDC, which is then used as collateral to borrow more ETH. Good composability makes it easy for users to design and conduct transactions like this, unleashing creative and unexpected use cases.
At least, that’s the promise. In reality, composing primitives is onerous. Typically, you have to interact with one primitive at a time, waiting idly for each successive transaction to get mined. Not only is this inconvenient and costs a lot of gas, it also means you can’t make atomic transactions (required for certain use cases like arbitrage trading).
A few niche projects offer special-purpose smart contracts that help users compose certain types of primitives. For example, DEX aggregators such as 1inch let users split swaps through multiple AMMs in order to get the best rate, and InstaDapp lets users compose AMMs with lending pools in order to gain leverage.
Solutions like this are a lot of work. They rely on large teams of developers to continuously build new “adapter” smart contracts every time a big, complicated primitive has to connect to another big, complicated primitive — to say nothing of connecting a third, fourth, or fifth primitive.
This strategy is a bit like cable adapter kits: one adapter for USB, one for HDMI, one for Lightning, etc. A tangled web of adapters is better than nothing, but suboptimal compared to a universal standard such as USB-C. Why is this the status quo for DeFi and how can we improve it?
Under the hood, every token is just a number on a ledger. When Alice “sends” a token to Bob, the token is simply subtracted from Alice’s balance and added to Bob’s balance. However, most token ledgers currently exist in a dedicated smart contract. This is like having a separate database for every token! Intuitively, it would be much simpler to have one database, one ledger, for all tokens.
Moreover, consider that every time a user invokes a new smart contract, they have to pay a fixed cost of 2,600 gas. This adds up! If all tokens lived in the same smart contract, it would not only be a major simplification of the token architecture — it would also significantly reduce gas costs.
From a token ledger’s perspective, all DeFi primitives follow the same pattern: They take one token as input and give another token as output. For example, when swapping DAI for USDC, an AMM primitive will take DAI as input and return USDC as output. When staking collateral to mint an algorithmic stablecoin, the primitive will take the collateral as input and mint new stablecoins as output.
From the token ledger’s perspective, the accounting logic is always the same. The input token is added to the primitive’s balance and subtracted from the user’s balance, and vice versa for the output token. The ledger can treat the primitive like a black box, unconcerned with what happens inside.
Why should DeFi protocols each deploy their own accounting logic when they could just share a standardized accounting framework? In other words — why don’t we have a “USB-C” equivalent for DeFi?
When composing multiple primitives, you inevitably add and subtract a lot of input and output numbers. However, many of these balance updates may be transitory, meaning they simply cancel out by the end of the transaction. For example, consider a two-step swap from DAI to USDC, then USDC to USDT. At the end of the final swap, you won’t be left with any USDC, so your balance on the USDC ledger should remain zero.
The Ethereum Virtual Machine (EVM) is like a computer that has the equivalent of a hard drive, referred to as “storage.” When smart contracts save data to storage, it’s expensive because it is replicated in thousands of computers around the world to live on the blockchain forever. A “storage write” can cost between 5,000 to 20,000 gas.
Thankfully, the EVM also has the equivalent of RAM, referred to as “memory.” Saving data to memory is much cheaper because at the end of the transaction, the data in memory is erased. Writing data to memory can cost as little as 3 gas! We would save a lot of gas by tracking transitory balance updates in memory instead of storage.
The Ocean synthesizes these three insights into a single smart contract, acting as a conduit between users, tokens, and primitives (see Figure 1). In particular, the Ocean:
- Has a single ERC-1155 ledger for all tokens
- Uses a standardized accounting framework for all primitives
- Tracks intermediate balance updates in memory instead of storage
As a ledger, the Ocean can support all major token types: ERC-20, ERC-721 and ERC-1155. Old tokens can be wrapped into the Ocean’s ledger, and new tokens can be created natively on the ledger.
As an accounting system, the Ocean can support any primitive type: AMMs, lending pools, algorithmic stablecoins, NFT markets, and even primitives yet to be invented. Primitives that are built using the Ocean’s framework (i.e., Ocean-native primitives) will be much simpler than older DeFi primitives because they only need to compute input and output tokens; all accounting logic is outsourced to the Ocean.
Figure 1: Complete architecture diagram of the Ocean
To compose primitives, the user simply sends a list of primitive interactions to the Ocean. For each interaction, the user specifies:
- The targeted primitive
- The input token
- The output token
- The input amount
The Ocean queries each primitive, asking it to compute the output amount. The Ocean then directly updates both the user’s and the primitives’ balances on its ledger, either in memory or storage where appropriate. If the user wants to wrap or unwrap external tokens, they can do so using the same framework.
The Ocean provides substantial gas savings when composing primitives. In fact, the more primitives being composed, the more gas the Ocean saves. As can be seen in Figure 2, the marginal cost of interacting with a primitive on the Ocean is 27 thousand gas. In other words, if you’re already interacting with a few primitives, it only costs 27 thousand gas to add just one more. That is over 4x lower than interacting with primitives one at a time. Because the Ocean’s marginal cost is so low, after 10 primitive interactions, the total cost of transacting on the Ocean is 3x lower than alternatives (see Figure 3).
Figure 2: Comparison of marginal gas costs with and without the Ocean
Figure 3: Comparison of total gas costs with and without the Ocean
Even beyond gas savings, the Ocean has several advantages. For one thing, developer teams previously had to write custom contracts in order to atomically compose DeFi primitives. Now any Web3 developer can accomplish this — no Solidity necessary!
But the biggest beneficiaries of the Ocean may be the primitives themselves. The more primitives that join the ecosystem, the more options for composability, and the more each individual primitive benefits. This creates a positive network effect for the whole ecosystem.