Gas reference
This page gathers what COLLAB's transactions cost in gas, as measured for release 2.2, and the formula the web app uses when a transaction is too large for a node to estimate. It is for developers who send COLLAB transactions from their own code, for reviewers, and for anyone who wants the numbers behind the fee review in the app. Members will find the short version in Costs and gas.
GenesisL1's rules
| Rule | Value | Consequence |
|---|---|---|
| Block gas limit | 1,000,000,000 | every COLLAB transaction fits a block, the largest creation included; local chains start anvil with --gas-limit 1000000000 |
| Base fee | 50 gwei, the figure every cost here uses | 1,000,000 gas costs 0.05 L1 |
| Gas schedule | London rules | a new 32-byte storage word costs 22,100 gas, a rewritten or cleared one at most 5,000 |
| Estimate cap | eth_estimateGas and eth_call stop at the node's json-rpc gas cap, 25,000,000 by default | above it a wallet cannot estimate: the transaction needs an explicit gas limit |
| Charge | max(gasUsed, gasLimit / 2), even when the transaction reverts | a failure pays at least half the limit it was sent with |
The last rule is Ethermint's minimum gas multiplier of 0.5, seen in GenesisL1 mainnet receipts during the 2.2 contract review (RV22-1). Explicit limits therefore matter: a limit far above what a transaction needs costs nothing when it succeeds, since gasUsed is then above half the limit, but costs half of it when it fails.
Measured gas
Measured on November 1, 2026 on anvil (chain 29, block gas limit 1,000,000,000, London schedule), each write its own transaction. "Limit" is eth_estimateGas, the smallest gas limit that works; it is above gasUsed for big writes, because nested calls forward only 63/64 of their gas and refunds for cleared words come back only at the end. Logos are random PNG bytes. "ASCII" text is prose with tabs and newlines; "adversarial" text has a 2-byte letter every 30 bytes, so no 32-byte window takes the fast path (the slowest text to check).
| Transaction | Limit | gasUsed |
|---|---|---|
| createDAO, no logo, no description | 5,427,346 | 5,427,346 |
| createDAO, 4 KB logo + 1 KB description | 9,164,010 | 9,164,010 |
| createDAO, 64 KB logo + 16 KB description | 65,267,781 | 63,850,801 |
| createDAO, 64 KB logo only | 53,053,507 | 52,006,663 |
| createDAO, 16 KB description: ASCII / CJK / accented Latin / adversarial | 17,251,108 / 19,629,680 / 20,345,563 / 20,420,402 | 17,251,108 / 19,593,864 / 20,287,546 / 20,360,075 |
| createDAO, worst case: 512 KB logo + 256 KB ASCII description | 587,697,589 | 570,494,853 |
| createDAO, worst case with adversarial text | 639,052,179 | 620,257,186 |
| setLogo by a representative: 64 KB over 64 KB, every word differs | 11,702,924 | 11,537,131 |
| … the same 64 KB again | 5,875,493 | 5,799,931 |
| … 16 KB over 64 KB / 64 KB over 16 KB | 10,854,391 / 38,385,770 | 8,551,468 / 37,802,227 |
| … a first 64 KB logo / removing a 64 KB logo | 47,319,741 / 10,576,585 | 46,597,431 / 8,329,388 |
| setDescription by a representative: 16 KB, one word differs / every word differs | 1,663,050 / 6,226,602 | 1,640,798 / 6,128,235 |
| … removing a 16 KB description | 2,679,566 | 2,109,820 |
| submitProposal: Signal, no actions, no description | 316,125 | 306,631 |
| … with a 16 KB / 64 KB proposal description | 4,081,421 / 15,129,710 | 4,017,247 / 14,905,459 |
| … Representatives & profile: setLogo 4 KB / setLogo 64 KB + setDescription 16 KB | 440,288 / 2,486,273 | 429,908 / 2,463,790 |
| … Representatives & profile: setLogo 512 KB + setDescription 256 KB (above the 25M cap) | 27,305,905 | 27,091,724 |
| castVote | 132,712 | 131,050 |
| execute: a first 4 KB logo / a first 64 KB logo + 16 KB description | 3,320,849 / 61,837,201 | 3,061,096 / 58,661,210 |
| execute: a first 512 KB logo + 256 KB description | 603,597,652 | 570,636,022 |
| execute: rewrite a 64 KB logo, every word differs | 12,608,266 | 11,726,942 |
At 50 gwei: a DAO without logo or description costs about 0.27 L1, one with a 64 KB logo and a 16 KB description about 3.2 L1, a vote about 0.0066 L1, and a representative's rewrite of a 64 KB logo about 0.58 L1. Real 128 × 128 logos are usually 5 to 30 KB.
ProfileGasTest in test/Profile.t.sol reports creation figures close to this table, but measures its edits inside the transaction that created the DAO, where rewritten words count as already written, so its edit figures are about half the real cost (RV22-2). Use this table for edits.
Above the estimate cap
These need an explicit gas limit, because a node stops estimating at 25,000,000:
- a createDAO with more than about 25 KB of logo and description together (about 20 KB when the text is not ASCII); each new 32-byte word adds about 23,000 gas to the 5.4M base;
- an execute, or a representative's write, of more than about 33 KB of new words (rewrites cost about a quarter as much);
- removing a logo or description of more than about 150 KB;
- a submitProposal near the maximum: about 0.7 MB of action data, or big actions with a long proposal description.
A node whose operator set a per-transaction gas cap below these figures refuses them; send them through another RPC.
The gas-limit formula
The web app uses this formula only when eth_estimateGas fails at the node's cap without a revert (an "out of gas" or "gas required exceeds allowance" answer); below the cap, the estimate with the usual margin is better. The constants are GAS and MARGIN in web/js/core/daoprofile.js, and every row of the measured table was checked against them: the formula gives 1.07 to 1.24 times the smallest working limit, more only where it assumes every word changes.
w(n) = ceil(n / 32), the 32-byte words ofnbytes.Store(N, O), writingNbytes overOstored bytes (OfromlogoInfoordescriptionInfo):22,100 × max(0, w(N) − w(O)) + 5,000 × min(w(N), w(O)) + 5,000 × max(0, w(O) − w(N)), plus44,200whenO = 0andN > 0, else10,000(the length and hash slots).Proc(N) = 1,000 × w(N)for a logo or an all-ASCII text,8,000 × w(N)for any other text.Write(N, O) = Store(N, O) + Proc(N) + 20,000.
| Transaction | Gas limit | Function |
|---|---|---|
| createDAO | 1.10 × (E + Σ Write(N, 0)) over a non-empty logo and description; E is eth_estimateGas of the same call with both empty (about 5.43M, GAS.createEmpty when it cannot be estimated) | createGasLimit |
| execute | 1.10 × (400,000 + 100,000 × A + Σ Write(N, O) + 20 × P + (P / 32)² / 100) over its setLogo and setDescription actions; A actions, P bytes of action data | executeGasLimit |
| a representative's setLogo or setDescription | 1.10 × (60,000 + Store(N, O) + Proc(N)) | directGasLimit |
| submitProposal | 1.10 × (350,000 + 25,000 × A + 26 × P + (P / 32)² / 75), plus 1.10 × (100,000 + 230 × D) for a description of D bytes | submitGasLimit |
The quadratic terms are memory: the actions are copied in the governor's and the treasury's frames. Other heavy actions in an execute need their own allowance. Every limit is capped at 990,000,000 (GAS_CEILING). The largest the formula gives are about 694M (createDAO with adversarial text) and about 712M (an execute of the maximum with adversarial text, extrapolated), and the wallet must hold gasLimit × maxFeePerGas to send them: about 35 L1 at 50 gwei.
A worked example, createDAO with a 64 KB logo and a 16 KB ASCII description:
logo: Write(65,536, 0) = 22,100 × 2,048 + 44,200 + 1,000 × 2,048 + 20,000 = 47,373,000
description: Write(16,384, 0) = 22,100 × 512 + 44,200 + 1,000 × 512 + 20,000 = 11,891,400
limit = 1.10 × (5,427,346 + 47,373,000 + 11,891,400) = 71,160,921The smallest limit that works is 65,267,781, so the margin is 9 %; the transaction uses 63,850,801 gas and pays that.
The web app's composer does not simulate a proposal whose profile writes need more than 20,000,000 gas (ESTIMATE_SAFE) and says why. send() in web/js/core/wallet.js takes an explicit gasLimit, still runs the preflight, and uses the limit only when the estimate failed at the cap.
What a failure costs
A transaction that fails pays half its gas limit on GenesisL1, and some failures are caused by someone else:
| Case | Limit | Paid on failure |
|---|---|---|
| the largest createDAO (512 KB + 256 KB ASCII) loses its slug to a creation mined first | about 631M | about 315M gas, 15.8 L1 |
| a createDAO with a 64 KB logo and 16 KB description loses its slug | about 71M | about 35.6M gas, 1.8 L1 |
| the second of two executions of one large proposal in a block | up to 712M | up to about 356M gas |
| the front-runner's cheapest creation, for comparison | about 5.4M gas, 0.27 L1 |
A creation that loses its slug reverts SlugTaken at once, after about 12.6M gas of calldata for the largest one, but is charged half its limit. An execution that runs out of gas pays its whole limit, as on any EVM chain; that can happen when a representative enlarged the logo between your estimate and the block, leaving more words to clear than counted. The app shows failureLine() with every transaction it sends with its own limit, checks the web address again just before the wallet opens, and reads state(id) again just before a large execute. A commit–reveal slug reservation and a two-step creation (the DAO first, then its logo and description uploaded by its creator as a representative) are future work, not in 2.2.
Removing or shrinking a large logo
Store(0, O) counts 5,000 gas for every cleared word, before refunds. London refunds at most a fifth of the gas used, and only at the end of the transaction, so the limit must cover the full cost:
| Write | Smallest limit | Charged |
|---|---|---|
| removing a 512 KB logo | about 83M (82,879,271) | about 66M (66,303,417) |
| removing a 64 KB logo | 10,576,585 | 8,329,388 |
| removing a 16 KB description | 2,679,566 | 2,109,820 |
Removing more than about 150 KB is above the estimate cap; the formula then gives the limit (about 90M for a 512 KB logo by a representative).
Reads and history
- A full 16 KB
logoChunkordescriptionChunkcosts about 1.2M gas ineth_call, so a 512 KB logo is 32 calls, each far below the cap. DAOLens.directorycosts about 70,000 gas per DAO, cold: 200 entries with the longest fields take 13.1M.getDAOswith 200 such summaries takes 23.6M, which is why its pages stay at 100 or less (page sizes).- An edit by proposal puts the bytes into the chain's history three times (the submit calldata, the
ProposalSubmittedevent, the execute calldata); a representative's edit puts them in once. Prefer a representative for large edits.
Deploying the protocol
The admin page's Deploy tab sends the 20 creations with the estimate × 1.2 + 20,000 as their limits. Measured on the 2.2 bundle: the largest creation (the DAOGovernor implementation) uses 4,631,659 gas, the largest limit sent is 5,577,990, and all 20 take 42,931,071 (the release rehearsal measured 42,953,788 on its own test chain), so every creation stays below the 25M cap. Deploy the protocol from /admin covers the operator's side.
Related
- Costs and gas: the members' view of fees.
- Contracts guide: what the profile stores and how it rewrites in place.
- Reading COLLAB from the chain: chunk reads within the cap.
- Known limitations: slugs, front-running and other limits.
- Security: the RV22 findings behind these rules.