Transient programs, an ancient execution paradigm (with multi-send example); and why storage clean-up doesn't happen

ux
transient-program
storage-cleanup
multisend

#1

This started out as a reply to a message in another thread, but boiled off into a rant.

That has essentially been answered.


However, I’d like to add that the currently dominant contract architecture, coupled with wallet design tropes, prevents the SSTORE-refund incentive from being usable.

For people to want to clean up after themselves, the cleaning-up has to happen within the same transaction as some other “useful” work. But there is no way to “chain” the two.

GasToken currently suggests using it from within other contracts, but this puts users at the mercy of contract developers. Also, from observing the ecosystem for years, most (sane) developers are reluctant to put code into their contracts that is not strictly related to its business logic.

If we want to incentivise certain kinds of behaviour, we must incentivise the users, not the contract coders - as, ultimately, it is the users that are the initiators of transactions that result in storage increase; and coders all too often have the option of shifting costs onto users anyway, so tend to be less frugal.


I’ve been working recently on an alternative program execution paradigm, which I call transient programs (in comparison to resident programs, commonly known as “contracts”).

For a short (and wholly-incorrect) explanation of what it is, to people who are familiar with Solidity only: “it’s like stuffing everything into the constructor”.

Transient programs execute at the bottom of the call stack, and are calling nobody (leaving the to field empty).

An example of such a program, implementing ether multi-send, can be seen on gitlab (or, with minimal lisp syntax highlighting, at the github backup).

(Also of interest is perhaps the Python test case, which shows how a transaction using this can be constructed; and this transaction on Ropsten showing a simple send to 2 recipients (wasteful).)


Using transient programs could remove the need for explicit GasToken support in end-contracts (as is currently suggested by GasToken crew), special “clean-up proxy contracts” (proxy this proxy that ugh the word is as sickening by now as your lack of imagination get a dictionary), batchStuff() functions that bloat contracts; and the general notion that for code to run, an authority has to deploy it first.

It could allow for vastly more to be “garbage-collected”; what comes to mind immediately is outdated ERC-20 allowances and spam naïve air-drop ERC-20 balances, both of which are relatively easy to track by wallet software.


I’ve called this execution paradigm “ancient” in the title, because that’s how contracts resident programs have been created since forever: a certain kind of a transient program claims a tiny bit of address space, where it pushes its payload.

However, development of transients seems to have stopped immediately afterwards; and residents are now completely entrenched.

I can’t start imagining how to convince wallet makers that this feature is one that they’d want to develop and support. Most wallets (all?..) don’t even have a way to deploy user-provided residents (they don’t allow leaving the to field empty).


Perhaps the above is too tongue-in-cheek; and this is a use pattern that no one thought of (not counting me sitting on my hands…). Indeed, some EVM design choices tend to suggest so.

If you followed either of the LLL links above, you’d have read that:

In a transient program, both code and data must be passed in the same transaction field. Although called “transaction data” when viewed externally, it will be available as code in its entirety during execution.

In the linked repository, it seems awkward that the resident variant accesses its data via CALLDATALOAD, whereas the transient has to resort to BYTECODESIZE.

The fact that leaving the to field empty results in increased gas use - by way of a nonced account address assignment, instead of just using the EOA’s address and deferring the nonce-ing until an actual CREATE is requested, - suggests that “contract deployment” at this point is expected. (For this reason, the linked transient multi-send program only starts saving gas when having at least 5 recipients.)


I was thinking of having this ready around Devcon; for many reasons, a month later, it’s in a state as sorry as ever - so here you go, a rant for a README.


Ethereum 1 dot X: a half-baked roadmap for mainnet improvements
Ethereum State rent for Eth 1.x pre-EIP document
#2

A slightly less universal example would be SHARE-backed orders on resolved Augur markets; and, generally speaking, losing shares - in markets and disputes (although perhaps these fall under the “ERC-20 balances” category).

I invite all to come up with more examples of garbage that you’d totally get rid of, if doing so was useful didn’t come at your own petty loss. Especially if it’s not related to ERC-20 tokens.