Ether janitors and “greed-powered” garbage collection in smart-contracts
Do you know that there are miners processing their own zero-fee transactions? But how? Thanks to @nickoneill for the interesting article, which you should definitely read! In short, there are “vacuum cleaners” in the Ethereum network that monitor weak addresses (based on some simple seed phrases and passwords) and immediately transfer any tokens, or ether, that go to any of these addresses. After reading this article I got an idea of naming the utility functions in smart-contracts, similar to cron tasks and garbage collection. Entitled “janitors of Ether”, this work can be used for good :)
In complex smart-contracts that write information about some events and then process this information, the important matter is the space in blockchain storage. In all storage-related decentralized solutions you need to pay for storage, but in many situations you can later purge old information (for example records about paid actions for last month), aggregate the information, and then shrink many records into one. Such periodic aggregation of data in databases is usually launched by cron, or manually by special administrative command. Actions in smart-contract can be triggered only by a transaction, so the periodic tasks can be performed only in the centralized way. “Ether janitors” are ready to make a transaction when they see “free” tokens, and they even mine their transactions for zero gas costs! (read the article). Let’s give them free tokens! Our strategy to make them perform useful tasks is as follows:
We have a contract where we have a function “collect_garbage()”. This function aggregates data, deletes obsolete storage values and transfers fees or dividends, or does any other useful work that you want to be completed in your contract.
contract ContractWithGarbage {// … function collect_garbage() public { // aggregate data and save result // delete obsolete records and free storage space // can add small payment in ether or some tokens for cleanup }// …}
This function is accessible for anybody who can use it and simply spends the sender’s gas while doing useful work for us.
We then launch a new token contract, of which the “transfer()” function has two important features:
- it calls “collect_garbage()” function from our main contract
- it transfers not all balance, but only a small part of it, for example, 1 token
contract EtherJanitorToken {// … function transfer(address from, address to, uint256 value) internal { require(to != address(0)); ContractWithGarbage sideContract = ContractWithGarbage(0xABC………….); // call “collect_garbage() sideContract.collect_garbage(); // transfer only 1 token _balances[from] = _balances[from].sub(1); // this line is not really needed :) _balances[to] = _balances[to].add(1); // thank you, Mr. Ether Janitor }// …}
We then deploy our ether JanitorToken and transfer, for example, 42 000 tokens to a well-known weak address. The “vacuum cleaners” see the new ERC20 tokens, and try to transfer them. They call “transfer()” from this weak address, receive 1 token ( 41 999 left) and automatically call “collect_garbage()” from our contract. On the next iteration, the balance of tokens on the weak address continue to be > 0 and janitors try to transfer tokens another time. So, we have 41 999 launches left.
Thank you, Mr. Ether Janitor :)