Skip to content

Instantly share code, notes, and snippets.

@k26dr
Created February 21, 2025 16:27
Show Gist options
  • Select an option

  • Save k26dr/3205f7a615ead3df28dcd969e814cf07 to your computer and use it in GitHub Desktop.

Select an option

Save k26dr/3205f7a615ead3df28dcd969e814cf07 to your computer and use it in GitHub Desktop.
How to Upload Books to Ethereum L1
Calldata on Ethereum has gotten so cheap that you can upload entire books in text format directly to Layer 1.
I'll use Meditations by Marcus Aurelius as an example because it's short enough to upload easily.
This book is available for free, so the first thing I did is to download a TXT copy of the book from the internet.
$ wget http://classics.mit.edu/Antoninus/meditations.mb.txt
Ethereum has a limit on how much data you can upload in a single transaction,
so I use a bash script to split the file up into 1000 line segments.
First determine how many lines the file has.
$ wc -l
4328 meditations.mb.txt
This means the file has 4328 lines. The following script will create the first 4 parts.
Since the last part will have 328 lines, I need to do that custom.
$ for i in $(seq 1 4); do head meditations.mb.txt -n $((i * 1000)) | tail -n 1000 > med_p$((i)).txt; done
Now do the last part with a custom line count.
$ tail meditations.mb.txt -n 328 > med_p5.txt
Now you have the book split into 5 parts which you can upload to the chain individually.
I wrote a Python script to make this part easier.
```
from web3 import Web3, AsyncWeb3
# Mainnet
address = "MY_ETHEREUM_ADDRESS" # TODO
pkey = bytes.fromhex("MY_PRIVATE_KEY") #TODO
w3 = Web3(Web3.HTTPProvider('ETHEREUM_RPC_URL')) #TODO
chainId = 1
contract_address = "0xc0a9c5BA3076fa7eE600A9f0E659DDa6382B2701"
maxFeePerGas = 0.8
maxPriorityFeePerGas = 0.8
abi = [{"inputs":[{"internalType":"string","name":"name","type":"string"},{"internalType":"string","name":"text","type":"string"}],"name":"book","outputs":[],"stateMutability":"nonpayable","type":"function"}]
book = w3.eth.contract(address=contract_address, abi=abi)
# TODO: Replace this with the next nonce on your Ethereum address
nonce = 0
for i in range(1,6):
print(nonce + i - 1)
filename = "med_p" + str(i) + ".txt"
with open(filename) as f:
content = f.read()
book_txn = book.functions.book("Meditations: Part " + str(i), content).build_transaction({
'chainId': chainId,
'gas': 1407106,
'maxFeePerGas': w3.to_wei(maxFeePerGas, 'gwei'),
'maxPriorityFeePerGas': w3.to_wei(maxPriorityFeePerGas, 'gwei'),
'nonce': nonce + i - 1,
})
signed_txn = w3.eth.account.sign_transaction(book_txn, private_key=pkey)
w3.eth.send_raw_transaction(signed_txn.raw_transaction)
print(signed_txn.hash.hex())
```
You need to replace MY_ETHEREUM_ADDRESS, MY_PRIVATE_KEY, ETHEREUM_RPC_URL,
and add in your account's current nonce to make the script work. If you're
uploading a different book, you will want to update the title in the book_txn
field as well.
I would also recommend updating maxFeePerGas and maxPriorityFeePerGas
as needed toget the transaction to go through. I set it low so that I spend as little
money as possible, but that means it can take a few hours to clear.
If you do, the script will spit out a series of transaction hashes for submitted
transactions that you can look up on Etherscan. If you look those up, you will see
that the data has been uploaded.
Congrats! You've just uploaded a book to Ethereum L1.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment