Skip to content

Conversation

@weiihann
Copy link

♨️ Cold BALANCE + Warm EXTCODESIZE

Abuse warm cost forcing small BALANCE cold reads in distinct places and then call warm EXTCODESIZE to all the 24kb contracts: This should be the way to make a client read the most amount of data from DB possible.

Prerequisites

Depends on #41.

The contract-deploy scenario must be run prior to running this scenario in order to deploy as many 24kB contracts as possible. With 45M gas limit, we will touch roughly 10k contracts, so the network must already have that many contracts already.

How it works

  1. The contract consists of a function to call BALANCE then EXTCODESIZE on a list of addresses.
contract BalanceThenExtCodeSize{
    function pokeBatch(address[] calldata addresses) external {
        for (uint i = 0; i < addresses.length; i++) {
            address a = addresses[i];
            assembly {
                let b := balance(a)
                let s := extcodesize(a)
                mstore(0x00, b)
            }
        }
    }
}
  1. The scenario starts by reading the deployments.json file which is populated with contract addresses deployed with the contract-deploy scenario.
  2. Based on the block gas limit, it estimates the amount of addresses to be called via pokeBatch
  3. Transaction is sent sequentially, expecting 1 transaction per block.
  4. Addresses are not repeated, unless, the deployments.json file doesn't have that many addresses, then it will start from the beginning once the end is reached.

Usage

Run

./bin/spamoor warm-extcodesize  --privkey=<PRIVATE_KEY> --rpchost="http://127.0.0.1:8545"

CPerezz and others added 27 commits May 7, 2025 16:45
Includes the scenarios contemplated within statebloat as well as any
extra data about them such as gas cost metrics.
This scenario deploys contracts that are exactly 24kB in size (EIP-170 limit) to maximize state growth while minimizing gas cost.

1. Generates a contract with exactly 24,576 bytes of runtime code
2. Deploys the contract using CREATE
3. Each deployment adds:
   - 24,576 bytes of runtime code
   - Account trie node
   - Total state growth: ~24.7kB per deployment

- 32,000 gas for CREATE
- 20,000 gas for new account
- 200 gas per byte for code deposit (24,576 bytes)
- Total: 4,967,200 gas per deployment
- Remove redundant throughput flag and consolidate to contracts-per-tx
- Remove count flag and related code for cleaner interface
- Update wallet count calculation to use contracts-per-tx
- Keep only two deployment rate control methods:
  - contracts-per-tx: direct control of contracts per transaction
  - gas-per-block: calculate contracts based on target gas

The scenario now runs indefinitely until stopped, with cleaner and more
focused configuration options.
- Add validation to ensure contract deployments don't exceed block gas limit
- Check both gas-per-block and contracts-per-tx against block gas limit
- Add clear error messages when gas limits are exceeded
- Move validation to Run() function to access context
- Introduce multiple test cases for contract deployment: using contracts per block, gas per block, and handling invalid configurations.
- Update config opts to replace `contracts-per-tx` with `contracts-per-block` for better clarity.
- Add error handling for scenarios where neither gas per block nor contracts per block is set.
- Refactor gas fee parameters to align with EIP-1559 standards.
- Initialize wallet pool in the contract deployment test.
- Introduced setup and teardown for contract deployment tests.
- Updated scenario options to include a maximum transactions limit. St we can test for a single tx at a time and shortening testing time.
…to max (EIP170)

- Introduced multiple dummy functions in the StateBloatToken contract to artificially inflate bytecode size.
- Updated ABI and binary files to reflect changes in the contract structure.
- Updated the contract deployment scenario to log deployed contract addresses and gas used.
- Added functionality to write deployed addresses to a JSON file for easier tracking.
- Removed gas-per-block validation and adjusted wallet count logic.
- Improved README with instructions for running against a local Anvil node without Go tests.
…ction tracking

- Introduced a batch deployment strategy that calculates the number of contracts fitting within the block gas limit.
- Added detailed tracking for deployed contracts, including gas used and bytecode size, with structured loggin.
- Improved nonce management and transaction retry logic.
… logging

- Added functionality to save a mapping of private keys to contract addresses in a deployments.json file after each contract deployment.
- Refactored the final summary logging to focus on the deployments.json file, removing the previous detailed contract saving logic.
- imporved logging to provide insights into the total number of deployers and contracts processed.
…mprove transaction handling

- Removed unused imports and redundant fields.
- Simplified transaction processing by releasing locks earlier.
- Improved logging for transaction sending and contract deployment confirmation.
- Cleaned up nonce management by directly fetching the nonce from the client.
…djustment

- Added functionality to dynamically adjust transaction fees based on current network conditions.
- Implemented retry logic for transaction sending with exponential backoff for base fee errors.
…s_limit

- Introduced BlockDeploymentStats struct to track deployment statistics per block, including contract count, total gas used, and total bytecode size.
- Implemented real-time block monitoring for logging deployment summaries.
- Updated contract bytecode size calculations to reflect actual deployed bytecode.
- Adjusted transaction processing intervals for improved efficiency.
Signed-off-by: CPerezz <37264926+CPerezz@users.noreply.github.com>
…based rate limiting

- Set MaxPending default to 100 to fix scenario hanging at startup (was 0, preventing any transactions)
- Remove hardcoded 12-second block time assumption that caused deployments only every 2 blocks
- Implement proper block-based rate limiting that waits for actual block changes
- Set rate limit to 2x expected throughput for better network utilization
- Send transactions at expected throughput rate per block instead of arbitrary delays
…nt scenario

- Replace incorrect import 'scenariotypes' with 'scenario' package
- Update ScenarioDescriptor to use correct scenario.Descriptor type
- Fix Init method signature to match scenario.Scenario interface
- Update wallet private key access to use GetWallet().GetPrivateKey()
- Remove unused Config() method not part of the interface
- Fix walletPool references in Init method
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants