Common classes of contracts and how they would handle ongoing storage maintenance fees ("rent")

Wait, the gas cost for editing one storage slot in RSK is linear in the number of existing storage slots? So quadratic total cost for N slots? This seems extreme and unnecessary…

If a contract gets too big, then fast-sync clients should just avoid syncing its state.

Well, that is my point earlier - if you want to make not linear in the number of existing storage slots, and still keep time-based cost - you would need to have timestamps for each storage slot separately, not just for the contract itself. Which brings us closer to your proposals above and LCCS

Right, agree. I personally am inclined to say don’t bother with time-based cost on a per-slot basis, and instead simply have two “modes” for the contract, one where enough rent is paid to cover all slots and the other where it is not, and in the latter case add a high fixed gas cost per access (eg. by requiring witnesses to be in transaction data and charging 68 gas/byte for them).

This solution means the user will pay for the rent and brings the question of the chicken or the egg causality dilemma? Let’s say i am a new user. I generate a public/private key. Someone wants to send to me some REP. How can I pay my rent as I don’t have any ETH?

Compare to the existing solution, it increases the complexity for new user to join the blockchain world which is not good. I believe sometimes, the end-user is totally forgotten of the equation :frowning:

Should our goal be to think about the end-user first? (if we really want to get to mass-adoption for the Internet of Values)

I think solution with CREATE2 above is a valuable direction to explore. It tries to solve griefing and free-rider problem that were described in the State rent proposal. I am going to explore it a bit more before commenting further, to see what is the difference between this and LCCS.
Receiving tokens like REP without having any ETH could still be achieved under rent regime, but indirectly. End-users are not forgotten, but they will need to do more work to receive and keep their assets, because a platform subsiding all of that seems to be un-sustainable.
The goal here is to prioritise the survival of the platform. Without platform, there will be no end-users.

In order to solve that, one would need to introduce separate timestamps for all storage items, which now becomes similar to solutions proposed in the original post.

Instead of maintaining the timestamps of all storage items individually, can we collect the storage rent in epochs(common expiry date). Any user who wants to store some data on a contract can pay for rest of the current epoch and next epoch(optional). At the end of the epoch, if the data is not paid for the next epoch then it is removed from state in which case, witness has to be provided for reviving the removed data.

PS: I have written a model for rent collection based on epochs here.

This implies that data within a contract can be selectively removed and revived, rather than the entire contract removed/revived. Which can be decomposed into Cross-Contract storage, or schemes with CREATE2 owner’s contracts that Vitalik mentioned above

This is a great idea, thanks for this contribution - I have been thinking about it today, and it seems to me that this could be a suitable alternative to LCCS, provided that we solve eviction notification, which is not too difficult.
I am going to try three things next:

  1. Implement an example of ERC-20 contract and a corresponding token holder contract (which could be made to support multiple tokens, I think), and see if it works.
  2. Use heuristic and automation to gather more accurate data (I had to use manual inspection before) about the share of ERC-20 tokens in the current state
  3. If (1) works out, I will look into comparative efficiency of this scheme and LCCS, and modify State rent proposal accordingly, adding modification to the eviction notification.

You wouldn’t. The contract would quickly get evicted, and if you later wanted to spend it, you could recover it and spend the REP by proving that the contract previously existed.

This just made me realise, that at least for token contracts, eviction notifications might not be as important as I thought - since the evicted holders can be brought back, technically, those tokens are still part of the supply - so the totalSupply does not need to be reduced when the token holders get evicted. This could make things even simpler. Thank you for that thought!

1 Like

I would be very interest to see this implementation! :slight_smile:

Thanks for starting this!

May I highlight that the .eth Registrar (for forward name->address resolution) is just one piece of the ENS system.

There is the Registry, which is currently much more susceptible to griefing, as “higher-level domains” are “free”. (Quotes here, since the Registry is actually oblivious of the concept of names/domains, operating on hashes only.)

This is proportional in the Public Resolver, probably the most popular resolver (as it’s “free for use of public” and requires no personalised deployment); and the Reverse Registrar/Resolver dual-purpose contract - perhaps to a lesser extent, as there’s only one entry possible per account address, instead of an entry for any conceivable name (as in the case of the “forward” resolver).

Then there are the Deed contracts, a copy for every auction entry; but their impact on storage bloat (and rent) is proportional to that of the .eth Registrar, which you’ve mentioned.


(Sorry for not linking all these mentioned contracts just yet - in a bit of a hurry. Ping to remind me to do this.)

See @nickjohnson’s reply with actual links.

I made an implementation of an ERC20 token that stores its state in separate contracts over the weekend. I’m not sure if it works - the tests aren’t using Constantinople. It’s at https://github.com/jvluso/openzeppelin-solidity/blob/c683a5bca151f1e10b6ff9dd247b575c9914415a/contracts/token/ERC20/ERC20.sol .

Thank you for that! I am trying to do the same, and I will definitely use some of the ideas from your code. I am going to be doing Constantinople uint tests too. Will post here in couple of days when I have the first version

1 Like

So I have some data on ERC20 tokens. I used successful invocation of “transfer” function to detect ERC20 contracts. By successful I mean either returning zero-length output (earlier version of the standard), or non-zero output 32 bytes long.

At block 6813760, which is 2nd of December, there were 149’746’097 storage items in total, spilt across 7’014’024 contracts. Note that there are also zero-storage contracts (like the ones created by GasToken2), these are not counted into this number. In fact, 4’619’309 contracts have a single item in their storage.

ERC20 heuristics identified 71139 ERC20 contracts. That includes CryptoKitties_Core, because it is both ERC20 and ERC721. And these 71139 contracts collectively occupy 80’504’952, which is about 53.7%

It would be easier to identify all ERC721 contracts, because the standard demands that Transfer event is to be issued on any transfers. But the strategy for further data analysis is to remove all ERC20 contracts from the dataset and see what seems to be the largest category now.

2 Likes

I have also started on my implementation of ERC20. Have not tested anything yet, but the general idea is to try to have a holder contract being able to hold arbitrary number of tokens, instead of having one holder contract per (token, owner) pair. I might also do data analysis on what is current number of these pairs.

Code is here, but tests will come later: https://github.com/ledgerwatch/eth_state/tree/master/erc20

1 Like

FYI, the linked contract is the .eth registrar, which hands out new domains under .eth; ENS itself is here, and its source is here). (deployed LLL version here). The same mitigation would apply, although it could be difficult to eliminate all possible storage of data on behalf of others when it comes to name issuance etc.

Another example of this issue is the DNSSEC Oracle, which allows anyone to submit a proof of existence of a DNS record.

2 Likes

I have written tests for token minting and transfer, and they pass. I did not test one holder having multiple tokens yet, but will add it in couple of days. Working with CREATE2 without extra tooling is a bit painful, of course. Here is the working token contract: https://github.com/ledgerwatch/eth_state/tree/master/erc20

@antoineherzog you wanted to see this

It looks very good :slight_smile:

i can see how we can improve the smart actor contract now to delegate any transfer authorization from the ERC20 contract to the smart actor contract by calling a isTransferAuthorized method. Then we could add very cool feature such as: improving the security of an account by switching from 1 sig to multisig or implementing a shamir secret procedure for private key recovery :grinning: I am publishing an article about that tomrorow.

More data on ERC20 tokens (at block 6856437, which was 9th of December 2018).

From my previous data, containing 71k+ ERC20 token contracts, I filtered out non-contracts, self-destructed contracts, those which do not have working balanceOf() method, and those that are not storing token balances in a straightforward way as Solidity mapping, and those that do not have any holders. 59986 contract left from such filtering.

(token, holder) pairs: 55’494’243
Tokens: 59’986
Unique holders: 18’628’814

Top 40 tokens by number of holders:

1,LivePeer_Token,2598037
2,TronToken,1063737
3,VIUToken,956329
4,XENON_Token,747466
5,OmiseGo_Token,649854
6,VinToken,478881
7,Streamr_Token,434733
8,BeautyChain_Token,364840
9,EOS_DSToken,330606
10,UCashToken,318759
11,GSENetwork_Token,305723
12,BinanceToken,301538
13,GSG_Coin,285302
14,MST_Token,244130
15,SoPay_Token,229642
16,BitClave_Token,220350
17,OCoin,216915
18,StatusToken,196825
19,BOBsRepairToken,195309
20,DecenturionToken,193224
21,BeautyChain_Token?,192536
22,BitcoinEOS_Token,184420
23,DataToken,184352
24,PentaNetwork_Token,178805
25,EMO_Token,173647
26,DRC_Token,170303
27,EthLend_Token,163939
28,AVINOCToken,163272
29,IFoods_Token,155379
30,ForAgricultureCoin,152910
31,NePay_Token,152626
32,OrmeusCoin,149907
33,BrahmaOS_Token,146113
34,StorjToken,144979
35,HashPowerToken,143476
36,ThreeDBToken,141585
37,FTI_Token,141400
38,DACC_Token,140218
39,XMAX_Token,139284
40,ExTradeCash_Token,133536

Top 25 holder by number of tokens:

1,EtherDelta_2,6711
2,IDEX_1,1340
3,3463934897d356b8659cbdfe15209e3bc3229105,1116
4,ea3a8bd1a99e16160832d6b473ce06c1058dff7e,1091
5,Freewallet,788
6,5bd5d826e4275a2180e8c5fa3c80a66ca461a375,772
7,0000000000000000000000000000000000000000,715
8,57a3e7088651b237cd363d7025554a63d47fc21f,675
9,3a2e3849945aae6b87e0ef4d13940049681e0b36,666
10,873dc5af4b3845ac90daa78383909f25efe295ac,658
11,30c8d95fb80c874dc285284147d4b4a4faeb05a9,643
12,81cd2b96a2a7625fe76f5f8c5e3032843268cc82,633
13,6204c634f06fa6a45e1f0e2a89c752f8450cdfad,629
14,Bittrex_1,627
15,f488efa00caf5bab853c7334688a5bf57db0eb7f,609
16,345f4e88905cfa1605b5f56167af7d0caa59ae74,601
17,cdae6e5d38605a4f428f2ed7c811a579d213bb97,601
18,edfc8b4d5e243e9e797b1292a6e0c4ec600dac26,595
19,3f5ce5fbfe3e9af3971dd833d26ba9b5c936f0be,589
20,51ec49876fd0f9e4bf72998fb24cd82e05802fbb,585
21,a12431d0b9db640034b0cdfceef9cce161e62be4,577
22,8460b752d49de926c8c623b4a836eb7bd402930c,562
23,TokenStore,562
24,23ef66867765adfaa9dbc518c76b42865710a114,560
25,ba95b4a5b130c4c1d27dc9e8adcf7f087cdb4c52,555

1 Like