feat: improved tokenomics#119
Conversation
📝 WalkthroughWalkthroughReplaces the flat transaction ChangesGas-based fee model
Estimated code review effort: 4 (Complex) | ~60 minutes Possibly related PRs
Suggested labels: Suggested reviewers: Poem
🚥 Pre-merge checks | ✅ 4✅ Passed checks (4 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
@CodeRabbit review |
✅ Action performedReview finished.
|
There was a problem hiding this comment.
Actionable comments posted: 4
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@genesis.json`:
- Line 7: The new top-level initial_supply field is not used by the genesis
loading path, so either wire it into the chain initialization flow or remove it
from the genesis schema. Update the genesis handling in minichain/chain.py,
especially the code that currently reads alloc during startup, so initial supply
is actually applied at runtime; otherwise, delete the unused initial_supply
entry to keep the genesis config accurate.
In `@main.py`:
- Around line 411-423: The send command is duplicating parsing and validation
that already exists in parse_tx_params, and the messages are diverging. Update
the send flow to delegate integer parsing and non-negativity checks to
parse_tx_params(parts, 2), then keep only the send-specific amount > 0
validation in the send handler. Make sure the logic stays aligned with the
existing deploy and call paths by reusing parse_tx_params rather than
re-implementing the checks in this block.
In `@minichain/state.py`:
- Around line 213-217: The refund logic in the transaction processing path is
unreachable because `gas_used` is being set to `tx.gas_limit`, which makes
`gas_refund` always zero. Update the transfer handling in the relevant state
transition method to either calculate a real intrinsic gas cost for simple
transfers and use that for `gas_used`, or remove the refund branch entirely if
full-limit billing is intended. Use the `gas_used`, `gas_refund`, and `Receipt`
flow in `minichain/state.py` as the place to adjust this behavior.
- Around line 141-144: The deploy refund logic in state processing is dead
because gas_used is always set from tx.gas_limit, making gas_refund permanently
zero. Update the deploy handling in state.py around the tx gas accounting path
to either compute real deployment gas usage before refunding or remove the
unreachable gas_refund branch and its sender balance adjustment for clarity. Use
the existing tx, gas_used, gas_refund, and sender balance update logic to locate
and simplify this block.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: f33fd8a3-4045-446f-af5e-deca2e41fd53
📒 Files selected for processing (10)
genesis.jsonmain.pyminichain/chain.pyminichain/mempool.pyminichain/state.pyminichain/transaction.pytests/test_contract.pytests/test_contract_transfers.pytests/test_core.pytests/test_reorg.py
| "difficulty": 4, | ||
| "target_block_time": 10000, | ||
| "alpha": 0.1, | ||
| "initial_supply": 1500000000, |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
Wire initial_supply into genesis loading or remove it.
minichain/chain.py still initializes balances from alloc only, so this new top-level field has no runtime effect and can mislead operators about the actual genesis issuance.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@genesis.json` at line 7, The new top-level initial_supply field is not used
by the genesis loading path, so either wire it into the chain initialization
flow or remove it from the genesis schema. Update the genesis handling in
minichain/chain.py, especially the code that currently reads alloc during
startup, so initial supply is actually applied at runtime; otherwise, delete the
unused initial_supply entry to keep the genesis config accurate.
| try: | ||
| amount = int(parts[2]) | ||
| fee = int(parts[3]) if len(parts) > 3 else 0 | ||
| gas_limit = int(parts[3]) if len(parts) > 3 else 0 | ||
| max_fee = int(parts[4]) if len(parts) > 4 else 0 | ||
| except ValueError: | ||
| print(" Amount and fee must be integers.") | ||
| print(" Values must be integers.") | ||
| continue | ||
| if amount <= 0: | ||
| print(" Amount must be greater than 0.") | ||
| continue | ||
| if fee < 0: | ||
| print(" Fee cannot be negative.") | ||
| if gas_limit < 0 or max_fee < 0: | ||
| print(" Gas limit and max fee cannot be negative.") | ||
| continue |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win
Reuse parse_tx_params in send to avoid duplicated, already-diverging parsing.
This block re-implements the integer parsing and non-negativity checks that parse_tx_params(parts, 2) already provides, and the error strings have started to diverge ("Gas limit and max fee cannot be negative." vs. the helper's "Values cannot be negative."). Delegating to the helper keeps send, deploy, and call consistent; only the amount <= 0 rule is specific to send.
♻️ Proposed refactor
- try:
- amount = int(parts[2])
- gas_limit = int(parts[3]) if len(parts) > 3 else 0
- max_fee = int(parts[4]) if len(parts) > 4 else 0
- except ValueError:
- print(" Values must be integers.")
- continue
- if amount <= 0:
- print(" Amount must be greater than 0.")
- continue
- if gas_limit < 0 or max_fee < 0:
- print(" Gas limit and max fee cannot be negative.")
- continue
+ parsed = parse_tx_params(parts, 2)
+ if parsed is None:
+ continue
+ amount, gas_limit, max_fee = parsed
+ if amount <= 0:
+ print(" Amount must be greater than 0.")
+ continue📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| try: | |
| amount = int(parts[2]) | |
| fee = int(parts[3]) if len(parts) > 3 else 0 | |
| gas_limit = int(parts[3]) if len(parts) > 3 else 0 | |
| max_fee = int(parts[4]) if len(parts) > 4 else 0 | |
| except ValueError: | |
| print(" Amount and fee must be integers.") | |
| print(" Values must be integers.") | |
| continue | |
| if amount <= 0: | |
| print(" Amount must be greater than 0.") | |
| continue | |
| if fee < 0: | |
| print(" Fee cannot be negative.") | |
| if gas_limit < 0 or max_fee < 0: | |
| print(" Gas limit and max fee cannot be negative.") | |
| continue | |
| parsed = parse_tx_params(parts, 2) | |
| if parsed is None: | |
| continue | |
| amount, gas_limit, max_fee = parsed | |
| if amount <= 0: | |
| print(" Amount must be greater than 0.") | |
| continue |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@main.py` around lines 411 - 423, The send command is duplicating parsing and
validation that already exists in parse_tx_params, and the messages are
diverging. Update the send flow to delegate integer parsing and non-negativity
checks to parse_tx_params(parts, 2), then keep only the send-specific amount > 0
validation in the send handler. Make sure the logic stays aligned with the
existing deploy and call paths by reusing parse_tx_params rather than
re-implementing the checks in this block.
| gas_used = getattr(tx, 'gas_limit', 0) | ||
| gas_refund = tx.gas_limit - gas_used | ||
| if gas_refund > 0: | ||
| sender['balance'] += (gas_refund * tx.max_fee_per_gas) |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '\n== minichain/state.py (around lines 120-170) ==\n'
nl -ba minichain/state.py | sed -n '120,170p'
printf '\n== search for gas_limit / gas_used / deploy handling ==\n'
rg -n "gas_limit|gas_used|deploy|refund" minichain -g '!**/__pycache__/**'
printf '\n== file list for minichain ==\n'
git ls-files minichainRepository: StabilityNexus/MiniChain
Length of output: 251
🏁 Script executed:
#!/bin/bash
set -euo pipefail
python3 - <<'PY'
from pathlib import Path
path = Path('minichain/state.py')
text = path.read_text().splitlines()
for i, line in enumerate(text[119:170], start=120):
print(f"{i:4d}: {line}")
PY
printf '\n== search for gas_limit / gas_used / deploy handling ==\n'
python3 - <<'PY'
from pathlib import Path
for path in Path('minichain').rglob('*.py'):
text = path.read_text().splitlines()
for i, line in enumerate(text, start=1):
if any(k in line for k in ('gas_limit', 'gas_used', 'deploy', 'refund')):
print(f"{path}:{i}: {line}")
PYRepository: StabilityNexus/MiniChain
Length of output: 8633
Remove the dead deploy refund branch
gas_used is set to tx.gas_limit in the deploy path, so gas_refund is always 0 and the refund block can never run. Either meter actual deployment gas here or حذف the dead branch for clarity.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@minichain/state.py` around lines 141 - 144, The deploy refund logic in state
processing is dead because gas_used is always set from tx.gas_limit, making
gas_refund permanently zero. Update the deploy handling in state.py around the
tx gas accounting path to either compute real deployment gas usage before
refunding or remove the unreachable gas_refund branch and its sender balance
adjustment for clarity. Use the existing tx, gas_used, gas_refund, and sender
balance update logic to locate and simplify this block.
| gas_used = getattr(tx, 'gas_limit', 0) | ||
| gas_refund = tx.gas_limit - gas_used | ||
| if gas_refund > 0: | ||
| sender['balance'] += (gas_refund * tx.max_fee_per_gas) | ||
| return Receipt(tx.tx_id, status=1, gas_used=gas_used) |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '== File context: minichain/state.py ==\n'
nl -ba minichain/state.py | sed -n '170,240p'
printf '\n== Search for gas/refund/receipt logic ==\n'
rg -n "gas_used|gas_refund|gas_limit|max_fee_per_gas|Receipt\(" minichain -S
printf '\n== Locate transaction fields / constructors ==\n'
rg -n "class .*Tx|dataclass.*Tx|gas_limit|max_fee_per_gas" minichain -SRepository: StabilityNexus/MiniChain
Length of output: 241
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '== File context: minichain/state.py ==\n'
sed -n '170,240p' minichain/state.py
printf '\n== Search for gas/refund/receipt logic ==\n'
rg -n "gas_used|gas_refund|gas_limit|max_fee_per_gas|Receipt\(" minichain -S
printf '\n== Locate transaction classes/constructors ==\n'
rg -n "class .*Tx|dataclass.*Tx|gas_limit|max_fee_per_gas" minichain -SRepository: StabilityNexus/MiniChain
Length of output: 14009
🏁 Script executed:
#!/bin/bash
set -euo pipefail
sed -n '1,170p' minichain/state.pyRepository: StabilityNexus/MiniChain
Length of output: 6843
Regular transfers never use the refund path
gas_used is set to tx.gas_limit, so gas_refund is always 0 and the refund block can never run. Either meter a fixed intrinsic cost for simple transfers and refund the remainder, or remove the refund logic if full-limit billing is intended.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@minichain/state.py` around lines 213 - 217, The refund logic in the
transaction processing path is unreachable because `gas_used` is being set to
`tx.gas_limit`, which makes `gas_refund` always zero. Update the transfer
handling in the relevant state transition method to either calculate a real
intrinsic gas cost for simple transfers and use that for `gas_used`, or remove
the refund branch entirely if full-limit billing is intended. Use the
`gas_used`, `gas_refund`, and `Receipt` flow in `minichain/state.py` as the
place to adjust this behavior.
…state gas refunds
This PR significantly improves the MiniChain tokenomics and transaction model by migrating away from flat fees to an EIP-1559 style structure. It also establishes a clear, declarative tokenomics specification in the genesis configuration.
Screenshots/Recordings:
TODO: If applicable, add screenshots or recordings that demonstrate the interface before and after the changes.
Additional Notes:
feeproperty withgas_limitandmax_fee_per_gasacross the protocol.(amount + (gas_limit * max_fee_per_gas)). If the transaction succeeds and uses less gas than the limit, the unspent gas is refunded to the sender.mempool.pynow sorts pending transactions by the highestmax_fee_per_gasoffered, rather than a flat fee, aligning miner incentives. The total block reward accounts for the exactgas_usedby each transaction.initial_supplyparameter (set to 1,500,000,000) togenesis.jsonto clearly document the network's maximum genesis issuance, clarifying the intent of theallocbalances.send,deploy, andcallterminal commands have been updated to accept[gas_limit]and[max_fee_per_gas].AI Usage Disclosure:
We encourage contributors to use AI tools responsibly when creating Pull Requests. While AI can be a valuable aid, it is essential to ensure that your contributions meet the task requirements, build successfully, include relevant tests, and pass all linters. Submissions that do not meet these standards may be closed without warning to maintain the quality and integrity of the project. Please take the time to understand the changes you are proposing and their impact. AI slop is strongly discouraged and may lead to banning and blocking. Do not spam our repos with AI slop.
Check one of the checkboxes below:
I have used the following AI models and tools: TODO
Checklist
Summary by CodeRabbit
New Features
Bug Fixes