-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
28 changed files
with
3,543 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,235 @@ | ||
{ | ||
"cells": [ | ||
{ | ||
"cell_type": "markdown", | ||
"id": "b52d942c", | ||
"metadata": {}, | ||
"source": [ | ||
"# Storage" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"id": "6b581368", | ||
"metadata": {}, | ||
"source": [ | ||
"The storage is a mapping from a `key` to a `value`. The number of keys is for all practical purposes infinite. The value can be up to 32 bytes. Every value is initialized with a 0.\n", | ||
"\n", | ||
"This is like the SSD in your computer. Storage is non-volatile." | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"id": "2a9d3e0b", | ||
"metadata": {}, | ||
"source": [ | ||
"" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"id": "f0d8d8db", | ||
"metadata": {}, | ||
"source": [ | ||
"source: https://docs.alchemy.com/docs/smart-contract-storage-layout" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"id": "0672532a", | ||
"metadata": {}, | ||
"source": [ | ||
"We will represent the storage as a dictionary." | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 50, | ||
"id": "c5b98bfc", | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"class KeyValue:\n", | ||
" def __init__(self): self.storage = {}\n", | ||
" \n", | ||
" def load (self, key) : return self.storage[key]\n", | ||
" def store(self, key, value): self.storage[key] = value" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"id": "2e60b878", | ||
"metadata": {}, | ||
"source": [ | ||
"### Warm/Cold" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"id": "d7515c89", | ||
"metadata": {}, | ||
"source": [ | ||
"It costs different amount of gas whether we access a warm or cold storage slot. \n", | ||
"A slot is said to be `warm` if it was access before. Otherwise it is `cold`.\n", | ||
"Accessing a slot that is `cold` costs more gas than accessing a `warm` slot.\n", | ||
"\n", | ||
"We implement that logic by keeping track of a `cache`. When we load a storage slot we save its key in that `cache`. If a key is in that `cache` it is said to be warm." | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 43, | ||
"id": "4d35c9ac", | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"class Storage(KeyValue):\n", | ||
" def __init__(self):\n", | ||
" super().__init__()\n", | ||
" self.cache = []\n", | ||
" \n", | ||
" def load(self, key):\n", | ||
" warm = True if key in self.cache else False\n", | ||
" if not warm: self.cache.append(key)\n", | ||
" if key not in self.storage: return 0x00\n", | ||
" return warm, super().load(key)" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 44, | ||
"id": "c9cba219", | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"storage = Storage()" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"id": "352aa83d", | ||
"metadata": {}, | ||
"source": [ | ||
"We store `420` in storage slot `1`" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 45, | ||
"id": "4ff21851", | ||
"metadata": {}, | ||
"outputs": [], | ||
"source": [ | ||
"storage.store(1, 420)" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"id": "037c7a05", | ||
"metadata": {}, | ||
"source": [ | ||
"Notice how the first time retrieving something from storage slot `1` its `cold`" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 46, | ||
"id": "7e3f84c7", | ||
"metadata": {}, | ||
"outputs": [ | ||
{ | ||
"data": { | ||
"text/plain": [ | ||
"(False, 420)" | ||
] | ||
}, | ||
"execution_count": 46, | ||
"metadata": {}, | ||
"output_type": "execute_result" | ||
} | ||
], | ||
"source": [ | ||
"storage.load(1)" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"id": "80e548e3", | ||
"metadata": {}, | ||
"source": [ | ||
"Now storage slot `1` is `warm`" | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 47, | ||
"id": "6c25d6ff", | ||
"metadata": {}, | ||
"outputs": [ | ||
{ | ||
"data": { | ||
"text/plain": [ | ||
"(True, 420)" | ||
] | ||
}, | ||
"execution_count": 47, | ||
"metadata": {}, | ||
"output_type": "execute_result" | ||
} | ||
], | ||
"source": [ | ||
"storage.load(1)" | ||
] | ||
}, | ||
{ | ||
"cell_type": "markdown", | ||
"id": "257055b8", | ||
"metadata": {}, | ||
"source": [ | ||
"Reading a random storage that was not set to any value will return 0 and **not** throw an exception." | ||
] | ||
}, | ||
{ | ||
"cell_type": "code", | ||
"execution_count": 51, | ||
"id": "bc839596", | ||
"metadata": {}, | ||
"outputs": [ | ||
{ | ||
"data": { | ||
"text/plain": [ | ||
"0" | ||
] | ||
}, | ||
"execution_count": 51, | ||
"metadata": {}, | ||
"output_type": "execute_result" | ||
} | ||
], | ||
"source": [ | ||
"storage.load(42069)" | ||
] | ||
} | ||
], | ||
"metadata": { | ||
"kernelspec": { | ||
"display_name": "Python 3 (ipykernel)", | ||
"language": "python", | ||
"name": "python3" | ||
}, | ||
"language_info": { | ||
"codemirror_mode": { | ||
"name": "ipython", | ||
"version": 3 | ||
}, | ||
"file_extension": ".py", | ||
"mimetype": "text/x-python", | ||
"name": "python", | ||
"nbconvert_exporter": "python", | ||
"pygments_lexer": "ipython3", | ||
"version": "3.8.9" | ||
} | ||
}, | ||
"nbformat": 4, | ||
"nbformat_minor": 5 | ||
} |
Oops, something went wrong.