Transactions are very expensive on Ethereum, they're unlikely to get much better, and they could get significantly worse. Today the bare minimum required to get and use a planet (ie transfer it and set its networking keys) costs $20-$50 in transaction fees paid to Ethereum miners. The basic problem is that anything computed and stored on Ethereum must be computed and stored by every Ethereum node. If we were the only app on Ethereum, this would be easy, since unlike cryptocurrencies we don't have a large volume of transactions or unboundedly large amounts of data to store. In fact, with 4 billion planets at around 1KB of data per planet, we shouldn't ever exceed 4TB of data. This is large, but you can buy a 4TB disk for about $70 -- it's far from intractable. While Urbit ID's state is currently less than 100MB, Ethereum's state is already hundreds of GB. It will never be practical for all Ethereum apps to store all their data on Ethereum. If you're tempted to abandon blockchains at this point, review my blog post from November 2019, which still holds: https://urbit.org/blog/pki-maze/ We need a blockchain to provide consensus on who owns each ship. Fortunately, there are ways to do this which are much more efficient than what we and Ethereum apps are doing now. Urbit's users use Ethereum for many things. We get to use a lot of off-the-shelf software to deal with cryptographic ownership. There are a lot of public tools like Etherscan and MetaMask which allow users to verify they own their ship. We have external smart contracts to enforce lockups, or to allow collective ownership of stars or other assets. There are smart contracts to allow trustlessly purchasing ships for ETH, and even decentalized exchanges. We've grown accustomed to these, but none of those are *critical* for the security and proper functioning of a ship. The most important thing we need from a blockchain is to decide which of two conflicting transactions happens first. Without this, a ship could be transferred to two people at once, and nobody would know which one should be the real owner. Suppose we strip down our dependence on an external blockchain to the bare minimum: an ordering of transactions. Everything else we do inside Urbit, especially running and interpreting those transactions to see who owns which ship. What if instead of using Ethereum as an operating system, we use it as an event log? Urbit OS can be the OS for Urbit ID. How much could we save? It depends on a lot of specifics, but 65-100x cheaper transactions are likely. It turns out if you simply want to place a few bytes in a transaction on Ethereum and not store them in "storage" memory or do any computation on them, it's quite cheap. I'll give a few numbers to give a sense of the tradeoffs, but if your eyes glaze over, just believe me that this technique provides at least 65x cheaper transactions. If you don't belive *me*, I list several organizations later on which are relying on this fact. Every Ethereum transaction has a base cost of 21,000 gas. Using a new 32-byte word of storage memory costs 20,000 gas, and changing an existing one costs 5,000 gas. A ship transfer modifies several words of storage, most importantly the ownership address for that ship and possibly its proxies and networking keys. There's additional bookkeeping that makes certain operations easier, but the cheapest we could conceivably make a transfer transaction is around 50k gas total. Right now they cost more like 100k gas. Simply passing in data as a function argument and *not* placing it in storage memory costs 16 gas per byte, which is 10x cheaper per byte and doesn't require padding to 32 bytes. Further, the data can be the transaction itself, instead of the outcome. This is the difference between storing "update this ownership address, clear those proxies and networking keys, increment these counters, decrement those" and storing "transfer ~sampel-palnet to 0xF00", which will generally be significantly shorter. By analogy to Urbit OS, this is the difference between storing an event and storing the changes it made to your checkpoint. A simple transaction format would use one byte for the function opcode (eg "transfer"), a couple bytes for a nonce (to prevent replay attacks), 4 bytes to specify the ship, 20 bytes to specify the destination address, and 65 bytes for the signature. This is 92 bytes, which would cost about 1500 gas. Unfortunately, every transaction costs 21,000 base gas anyway, so we're only down to 22,500. This is 4x cheaper than our current transactions, but that's not good enough. What we can do is put a bunch of them in the same Ethereum Transaction (I will capitalize Ethereum Transactions to distinguish them from the many Urbit transactions inside). If we put 1000 of our transactions in the same Ethereum Transaction, the cost will be 21,000 + 1000 * 1500 = 1,521,000, which if you divide by 1000 is only 1521 gas per transaction, or about 65x cheaper than our current transactions. Since each transaction comes with its own signature, these don't need to be from the same person. Two thirds of each transaction is its signature, and there are a few experimental schemes (primarily BLS or a SNARK) to combine those into a single signature, which would reduce cost to closer to 500 gas per transaction. As well, one of the earliest milestones in Ethereum 2.0 will be "data shards", which would increase Ethereum's capacity for this sort of transaction by 50x or so. Even without these optimizations, a 65x improvment would be a big deal. Enough with the numbers, though. If the computation isn't happening on chain, where is it happening? Why, in your Urbit, of course! When your Urbit sees a new batch of Urbit transactions was added to Ethereum, it downloads them and runs them. It has a state transition function with the following signature which updates its local copy of the Urbit ID state and produces a list of events to send to Ames (key changes, sponsorship changes, and breaches): $-([txdata=@ =old=state] [(list id-event) =new=state]) For those who don't read hoon: (txdata : Bytes, old-state : State) -> (list id-event, new-state : State) This pattern of course exists throughout Urbit: "function from event + old-state to list of effects + new state". If everyone agrees on this function, much as they currently agree to look at the same Ethereum contract right now, then everyone will interpret transactions in exactly the same way and have the same Urbit ID state. Is this technique sufficient to guarantee ownership of your ship? We need to guarantee two things: (1) that only valid transactions are accepted and (2) when two valid but conflictng transactions appear, we can agree on which one happened first (making the second no longer valid). (1) is easy. Instead of crashing on invalid transctions, just interpret them as no-ops. (2) is also easy. All Ethereum Transactions are totally ordered, so we use whatever order miners chose to include the Transactions in each block. Within a single Etheruem Transaction, the Urbit transactions are in order as well. This order is chosen by the person who submitted the batch. This is safe since there's no "wrong" order; we simply need to agree on one. Other properties we need for this to be practical are spam-resistance and "data availability". If it were free to send transactions and every Urbit had to process them, a bad actor could send millions or billions of transactions, effectively halting the network. However, since each transaction costs a few hundred gas on Ethereum, such an attack would be prohibitively expensive as long as no individual Urbit transaction takes a disproportionately long amount of time to process. "Data availability" is the property that anyone can get all the current Urbit ID state without depending on a trusted third party. While they may choose to download a snapshot from a trusted party for convenience, they can always "replay the event log" -- ie process all the historical Urbit transactions. This won't be as fast but shouldn't be prohibitively slow. Something we mentioned in passing is the role of "aggregators". Of course, anyone can send an Ethereum Transaction with all the Urbit transactions they want to send, but the greatest savings come with larger numbers of transactions per batch. We expect there to naturally be a small number of entities where you can send transactions and they'll include them in their next batch. They may have different properties. One might be cheap but only send a single batch per day, while another is more expensive but sends a batch every 30 minutes. Many people may not pay directly at all; perhaps your sponsor or hosting provider will allow up to 5 free transactions per month. Someone may even run a public aggregator that gives your first 3 transactions for free, to generate publicity and goodwill, and to encourage the growth of Urbit. This mechanism should work and would be sufficient for the proper functioning of Urbit. There are several choices for migration, ranging from doing it all at once to moving only planets to this system and leaving the rest as-is to making it purely opt-in. I tend to prefer the last option. In that case, if you do nothing, you can use Urbit ID exactly as you do now, with all the convenient tools Ethereum gives you. If you want cheaper transactions, you can send your ship to a particular address, and then afterward everything happens on Urbit. For example, if you're a star owner who wants to spawn many planets, you can send your star to that address and spawn cheaply. Of course, once you send your ship to that address, there's no putting it back on the main Ethereum chain. However, there's good reason to believe we'll eventually be able to interact with smart contracts on the main chain again in the future. There are several techniques for committing a hash of the new state with every new batch, so that you can prove to other things on Ethereum who owns which ship. This would allow you to withdraw a ship back to the main Ethereum chain. These techniques are in active development and are expected to be ready in a matter of months. Maybe we won't have to be cut off from the world for *too* long. The tradeoffs here are not pleasant, but this scheme preserves all our crucial requirements. Other proposals generally fail on one of the following counts: - Not ready in the near future. This is an urgent problem for us, and "3 months away" inevitably turns into 6 months at least. This proposal doesn't rely on any other team building things. When they're ready, I expect we'll be glad to transition to a more full-featured option. - Introduces dependency on external organizations continuing to exist and service Urbit users. - Doesn't disallow double-spends - Not suitably censorship-resistant - Doesn't actually scale better than Ethereum, it's just cheaper because nobody uses it - Overly centralized, either by formal whitelists or in practice due to prohibitive hardware cost. - Reliant on complex and unproven game theory, or where theoretical attacks are known, even if they haven't happened yet. - Requires activity to maintain ownership of your ship If you've made it this far and you want to dive into the "literature", what I've been describing is a "layer 2" ("L2") solution that is essentially a "rollup", except with no state hash -- what I've taken to calling a "naive rollup". I mentioned communication with the main Ethereum chain ("layer 1", "L1") through storing a state hash on chain. "Optimistic rollups" allow anyone to challenge that state hash if the incorrect hash was submitted, burning a stake owned by the aggregator who submitted the wrong hash. Optimism PBC is working on one of these. "Zero-knowledge rollups" ("ZK rollups") require the aggregator to include a ZK proof that the new state hash is correct. Matter Labs and StarkWare are pursing this type of rollup. None of these are ready for generalized computation yet, but great progress has been made and all plan to be ready this year. Probably too far out for our immediate timeline, but well worth learning about.