diff --git a/.gitignore b/.gitignore
index 92ed6a37..d1db59b8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,3 +8,5 @@ bin
spamoor.db*
go.lib.mod
go.lib.sum
+*.abi
+*.bin
diff --git a/README.md b/README.md
index b91643b5..2cdcfae3 100644
--- a/README.md
+++ b/README.md
@@ -53,6 +53,7 @@ RPC hosts support additional configuration parameters through URL prefixes:
Spamoor provides multiple scenarios for different transaction types:
+
| Scenario | Description |
|----------|-------------|
| [`eoatx`](./scenarios/eoatx/README.md) | **EOA Transactions**
Send standard EOA transactions with configurable amounts and targets |
diff --git a/scenarios/scenarios.go b/scenarios/scenarios.go
index b6e9c9ce..8eae67c5 100644
--- a/scenarios/scenarios.go
+++ b/scenarios/scenarios.go
@@ -16,6 +16,10 @@ import (
"github.com/ethpandaops/spamoor/scenarios/gasburnertx"
"github.com/ethpandaops/spamoor/scenarios/geastx"
"github.com/ethpandaops/spamoor/scenarios/setcodetx"
+ sbcontractdeploy "github.com/ethpandaops/spamoor/scenarios/statebloat/contract_deploy"
+ sbeoadelegation "github.com/ethpandaops/spamoor/scenarios/statebloat/eoa_delegation"
+ sberc20maxtransfers "github.com/ethpandaops/spamoor/scenarios/statebloat/erc20_max_transfers"
+ sbrandsstore "github.com/ethpandaops/spamoor/scenarios/statebloat/rand_sstore"
"github.com/ethpandaops/spamoor/scenarios/storagespam"
uniswapswaps "github.com/ethpandaops/spamoor/scenarios/uniswap-swaps"
"github.com/ethpandaops/spamoor/scenarios/wallets"
@@ -39,6 +43,10 @@ var ScenarioDescriptors = []*scenario.Descriptor{
&gasburnertx.ScenarioDescriptor,
&geastx.ScenarioDescriptor,
&setcodetx.ScenarioDescriptor,
+ &sbcontractdeploy.ScenarioDescriptor,
+ &sbeoadelegation.ScenarioDescriptor,
+ &sberc20maxtransfers.ScenarioDescriptor,
+ &sbrandsstore.ScenarioDescriptor,
&storagespam.ScenarioDescriptor,
&uniswapswaps.ScenarioDescriptor,
&wallets.ScenarioDescriptor,
diff --git a/scenarios/statebloat/README.md b/scenarios/statebloat/README.md
new file mode 100644
index 00000000..28d23d77
--- /dev/null
+++ b/scenarios/statebloat/README.md
@@ -0,0 +1,35 @@
+# State Bloat Scenarios
+
+This directory contains scenarios designed to test different vectors of state growth on Ethereum. Each scenario focuses on a specific method of increasing the state size while minimizing ETH cost.
+
+## Available Scenarios
+
+1. `contract-deploy` - Deploys 24kB contracts (EIP-170 limit)
+2. `delegate-flag` - Adds delegate flags to funded EOAs (EIP-7702)
+3. `fund-eoa` - Funds fresh EOAs with minimal ETH
+4. `empty-auth` - Creates EIP-7702 authorizations for empty addresses
+5. `storage-slots` - Fills new storage slots in contracts
+
+## Testing
+
+These scenarios can be tested using Anvil (Foundry's local Ethereum node) or any other EVM-compatible testnet. For local testing:
+
+```bash
+# Start Anvil
+anvil
+
+# Run a scenario (example)
+spamoor statebloat/contract-deploy [flags]
+```
+
+Each scenario directory contains its own README with specific configuration options and testing instructions.
+
+## Gas Efficiency Comparison
+
+| Rank | Scenario | Gas/Byte | Max Units in 30M Gas Block |
+| ---- | --------------- | -------- | -------------------------- |
+| 1 | Contract Deploy | ~202 | 6 deployments |
+| 2 | Delegate Flag | ~232 | 960 tuples |
+| 3 | Fund EOA | ~267 | 1000 accounts |
+| 4 | Empty Auth | ~289 | 767 tuples |
+| 5 | Storage Slots | 625 | 1500 slots |
\ No newline at end of file
diff --git a/scenarios/statebloat/contract_deploy/README.md b/scenarios/statebloat/contract_deploy/README.md
new file mode 100644
index 00000000..26b2f56b
--- /dev/null
+++ b/scenarios/statebloat/contract_deploy/README.md
@@ -0,0 +1,58 @@
+# π Contract Deployment State Bloat
+
+This scenario deploys contracts that are exactly 24kB in size (EIP-170 limit) to maximize state growth while minimizing gas cost.
+
+## How it Works
+
+1. Generates a contract with exactly 24,576 bytes of runtime code
+2. Deploys the contract using CREATE with a salt that makes the bytecode unique
+3. Uses batch-based deployment:
+ - Calculates how many contracts fit in one block based on gas limits
+ - Sends a batch of transactions that fit within the block gas limit
+ - Waits for a new block to be mined
+ - Repeats the process ("bombards" the RPC after each block)
+4. Each deployment adds:
+ - 24,576 bytes of runtime code
+ - Account trie node
+ - Total state growth: ~24.7kB per deployment
+
+## β½ Gas Cost Breakdown
+
+- 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**
+
+## Batch Strategy
+
+The scenario automatically calculates how many contracts can fit in one block:
+- Default block gas limit: 30,000,000 gas
+- Gas per contract: 4,967,200 gas
+- Contracts per batch: ~6 contracts per block
+
+This ensures optimal utilization of block space while maintaining predictable transaction inclusion patterns.
+
+## π Usage
+
+### Build
+```bash
+go build -o bin/spamoor cmd/spamoor/main.go
+```
+
+### Run
+```bash
+./bin/spamoor --privkey --rpchost http://localhost:8545 contract-deploy [flags]
+```
+
+#### Key Flags
+- `--max-transactions` - Total number of contracts to deploy (0 = infinite, default: 0)
+- `--max-wallets` - Max child wallets to use (0 = root wallet only, default: 0)
+- `--basefee` - Base fee per gas in gwei (default: 10)
+- `--tipfee` - Tip fee per gas in gwei (default: 2)
+
+#### Example with Anvil node
+```bash
+./bin/spamoor --privkey ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 \
+ --rpchost http://localhost:8545 contract-deploy \
+ --max-transactions 0
+```
\ No newline at end of file
diff --git a/scenarios/statebloat/contract_deploy/contract/.gitignore b/scenarios/statebloat/contract_deploy/contract/.gitignore
new file mode 100644
index 00000000..f9096e53
--- /dev/null
+++ b/scenarios/statebloat/contract_deploy/contract/.gitignore
@@ -0,0 +1,3 @@
+*.output.json
+*.bin
+*.abi
\ No newline at end of file
diff --git a/scenarios/statebloat/contract_deploy/contract/README.md b/scenarios/statebloat/contract_deploy/contract/README.md
new file mode 100644
index 00000000..de0d8758
--- /dev/null
+++ b/scenarios/statebloat/contract_deploy/contract/README.md
@@ -0,0 +1,35 @@
+# Contract Compilation
+
+This directory contains the Solidity contract and its compiled artifacts. To compile the contract and generate Go bindings:
+
+1. Install solc (Solidity compiler):
+```bash
+# On macOS
+brew install solidity
+
+# On Ubuntu/Debian
+sudo add-apt-repository ppa:ethereum/ethereum
+sudo apt-get update
+sudo apt-get install solc
+```
+
+2. Install abigen (ABI generator):
+```bash
+go install github.com/ethereum/go-ethereum/cmd/abigen@latest
+```
+
+3. Compile the contract:
+```bash
+solc --abi StateBloatToken.sol -o . --overwrite
+solc --bin StateBloatToken.sol -o . --overwrite
+```
+
+4. Generate Go bindings:
+```bash
+abigen --bin=StateBloatToken.bin --abi=StateBloatToken.abi --pkg=contract --out=StateBloatToken.go
+```
+
+The generated files will be:
+- `StateBloatToken.abi` - Contract ABI
+- `StateBloatToken.bin` - Contract bytecode
+- `StateBloatToken.go` - Go bindings
\ No newline at end of file
diff --git a/scenarios/statebloat/contract_deploy/contract/StateBloatToken.go b/scenarios/statebloat/contract_deploy/contract/StateBloatToken.go
new file mode 100644
index 00000000..3021968a
--- /dev/null
+++ b/scenarios/statebloat/contract_deploy/contract/StateBloatToken.go
@@ -0,0 +1,3360 @@
+// Code generated - DO NOT EDIT.
+// This file is a generated binding and any manual changes will be lost.
+
+package contract
+
+import (
+ "errors"
+ "math/big"
+ "strings"
+
+ ethereum "github.com/ethereum/go-ethereum"
+ "github.com/ethereum/go-ethereum/accounts/abi"
+ "github.com/ethereum/go-ethereum/accounts/abi/bind"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/event"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var (
+ _ = errors.New
+ _ = big.NewInt
+ _ = strings.NewReader
+ _ = ethereum.NotFound
+ _ = bind.Bind
+ _ = common.Big1
+ _ = types.BloomLookup
+ _ = event.NewSubscription
+ _ = abi.ConvertType
+)
+
+// StateBloatTokenMetaData contains all meta data concerning the StateBloatToken contract.
+var StateBloatTokenMetaData = &bind.MetaData{
+ ABI: "[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_salt\",\"type\":\"uint256\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Approval\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"Transfer\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"PADDING_DATA\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"allowance\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"approve\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"name\":\"balanceOf\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"decimals\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dummy1\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dummy10\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dummy11\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dummy12\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dummy13\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dummy14\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dummy15\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dummy16\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dummy17\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dummy18\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dummy19\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dummy2\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dummy20\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dummy21\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dummy22\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dummy23\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dummy24\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dummy25\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dummy26\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dummy27\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dummy28\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dummy29\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dummy3\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dummy30\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dummy31\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dummy32\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dummy33\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dummy34\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dummy35\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dummy36\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dummy37\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dummy38\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dummy39\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dummy4\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dummy40\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dummy41\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dummy42\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dummy43\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dummy44\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dummy45\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dummy46\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dummy47\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dummy48\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dummy49\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dummy5\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dummy50\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dummy51\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dummy52\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dummy53\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dummy54\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dummy55\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dummy56\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dummy57\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dummy58\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dummy59\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dummy6\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dummy60\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dummy61\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dummy62\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dummy63\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dummy64\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dummy65\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dummy66\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dummy67\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dummy68\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dummy69\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dummy7\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dummy8\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dummy9\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"name\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"salt\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"symbol\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"totalSupply\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"transfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"transferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"transferFrom1\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"transferFrom10\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"transferFrom11\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"transferFrom12\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"transferFrom13\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"transferFrom14\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"transferFrom15\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"transferFrom16\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"transferFrom17\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"transferFrom18\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"transferFrom19\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"transferFrom2\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"transferFrom3\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"transferFrom4\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"transferFrom5\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"transferFrom6\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"transferFrom7\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"transferFrom8\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"transferFrom9\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]",
+ Bin: "0x60a060405234801562000010575f80fd5b50604051620016f1380380620016f1833981016040819052620000339162000118565b60408051808201909152601181527029ba30ba3290213637b0ba102a37b5b2b760791b60208201525f90620000699082620001ce565b5060408051808201909152600381526214d09560ea1b6020820152600190620000939082620001ce565b506002805460ff191660129081179091556080829052620000b690600a620003a9565b620000c590620f4240620003c0565b6003819055335f81815260046020908152604080832085905551938452919290917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef910160405180910390a350620003da565b5f6020828403121562000129575f80fd5b5051919050565b634e487b7160e01b5f52604160045260245ffd5b600181811c908216806200015957607f821691505b6020821081036200017857634e487b7160e01b5f52602260045260245ffd5b50919050565b601f821115620001c957805f5260205f20601f840160051c81016020851015620001a55750805b601f840160051c820191505b81811015620001c6575f8155600101620001b1565b50505b505050565b81516001600160401b03811115620001ea57620001ea62000130565b6200020281620001fb845462000144565b846200017e565b602080601f83116001811462000238575f8415620002205750858301515b5f19600386901b1c1916600185901b17855562000292565b5f85815260208120601f198616915b82811015620002685788860151825594840194600190910190840162000247565b50858210156200028657878501515f19600388901b60f8161c191681555b505060018460011b0185555b505050505050565b634e487b7160e01b5f52601160045260245ffd5b600181815b80851115620002ee57815f1904821115620002d257620002d26200029a565b80851615620002e057918102915b93841c9390800290620002b3565b509250929050565b5f826200030657506001620003a3565b816200031457505f620003a3565b81600181146200032d5760028114620003385762000358565b6001915050620003a3565b60ff8411156200034c576200034c6200029a565b50506001821b620003a3565b5060208310610133831016604e8410600b84101617156200037d575081810a620003a3565b620003898383620002ae565b805f19048211156200039f576200039f6200029a565b0290505b92915050565b5f620003b960ff841683620002f6565b9392505050565b8082028115828204841417620003a357620003a36200029a565b6080516112fe620003f35f395f61089001526112fe5ff3fe608060405234801561000f575f80fd5b5060043610610630575f3560e01c8063657b6ef711610333578063ad8f4221116101b3578063d9bb3174116100fe578063ee1682b6116100a9578063f8716f1411610084578063f8716f141461093d578063faf35ced14610634578063fe7d599614610944578063ffbf04691461094b575f80fd5b8063ee1682b614610927578063f26c779b1461092f578063f5f5738114610936575f80fd5b8063e2d27530116100d9578063e2d2753014610906578063e8c927b31461090d578063eb4329c814610914575f80fd5b8063d9bb3174146108ce578063dc1d8a9b146108d5578063dd62ed3e146108dc575f80fd5b8063bfa0b1331161015e578063cfd6686311610139578063cfd66863146108b9578063d101dcd0146108c0578063d7419469146108c7575f80fd5b8063bfa0b1331461088b578063c2be97e314610634578063c958d4bf146108b2575f80fd5b8063b66dd7501161018e578063b66dd7501461087d578063b9a6d64514610884578063bb9bfe0614610634575f80fd5b8063ad8f42211461086f578063b1802b9a14610634578063b2bb360e14610876575f80fd5b80637dffdc321161027e57806395d89b4111610229578063a891d4d411610204578063a891d4d41461084e578063a9059cbb14610855578063aaa7af7014610868578063acc5aee914610634575f80fd5b806395d89b41146108385780639c5dfe73146108405780639df61a2514610847575f80fd5b80638619d607116102595780638619d6071461082a5780638789ca67146106345780638f4a840614610831575f80fd5b80637dffdc32146108155780637e5449371461081c5780637f34d94b14610823575f80fd5b806374f83d02116102de5780637a319c18116102b95780637a319c18146108075780637c66673e146106345780637c72ed0d1461080e575f80fd5b806374f83d02146107f257806377c0209e146107f9578063792c7f3e14610800575f80fd5b80636c12ed281161030e5780636c12ed281461063457806370a08231146107cc57806374e73fd3146107eb575f80fd5b8063657b6ef714610707578063672151fe146107be5780636abceacd146107c5575f80fd5b80633125f37a116104be5780634a2e93c611610409578063552a1b56116103b457806361b970eb1161038f57806361b970eb146107a2578063639ec53a146107a957806365473174146107b05780636578534c146107b7575f80fd5b8063552a1b561461063457806358b6a9bd146107945780635af92c051461079b575f80fd5b80634f5e5557116103e45780634f5e5557146107865780634f7bd75a1461063457806354c279201461078d575f80fd5b80634a2e93c6146107715780634b3c7f5f146107785780634e1dbb821461077f575f80fd5b80633ea117ce1161046957806342937dbd1161044457806342937dbd1461076357806343a6b92d1461076a57806344050a2814610634575f80fd5b80633ea117ce1461074e5780634128a85d14610755578063418b18161461075c575f80fd5b806339e0bd121161049957806339e0bd12146106345780633a131990146106345780633b6be45914610747575f80fd5b80633125f37a1461071a578063313ce5671461072157806334517f0b14610740575f80fd5b80631b17c65c1161057e57806321ecd7a3116105295780632545d8b7116105045780632545d8b7146106f95780632787325b14610700578063291c3bd714610707575f80fd5b806321ecd7a3146106eb578063239af2a5146106f257806323b872dd14610634575f80fd5b80631eaa7c52116105595780631eaa7c52146106d65780631f449589146106dd5780631fd298ec146106e4575f80fd5b80631b17c65c146106345780631bbffe6f146106345780631d527cde146106cf575f80fd5b806312901b42116105de57806318160ddd116105b957806318160ddd146106b857806319cf6a91146106c15780631a97f18e146106c8575f80fd5b806312901b42146106a357806313ebb5ec146106aa57806316a3045b146106b1575f80fd5b8063095ea7b31161060e578063095ea7b3146106825780630cb7a9e7146106955780631215a3ab1461069c575f80fd5b80630460faf61461063457806306fdde031461065c5780630717b16114610671575b5f80fd5b610647610642366004610fd2565b610952565b60405190151581526020015b60405180910390f35b610664610ba7565b604051610653919061100b565b602f5b604051908152602001610653565b610647610690366004611075565b610c32565b601b610674565b6005610674565b601a610674565b601d610674565b6033610674565b61067460035481565b6008610674565b6003610674565b6002610674565b6010610674565b6041610674565b6035610674565b602e610674565b602c610674565b6001610674565b6045610674565b610647610715366004610fd2565b610cab565b6034610674565b60025461072e9060ff1681565b60405160ff9091168152602001610653565b603c610674565b6004610674565b600c610674565b6006610674565b601c610674565b6032610674565b6023610674565b6011610674565b6021610674565b601f610674565b6026610674565b603a610674565b6009610674565b602a610674565b6014610674565b6025610674565b6013610674565b6043610674565b600d610674565b6017610674565b6106746107da36600461109d565b60046020525f908152604090205481565b6016610674565b6039610674565b603b610674565b6036610674565b603f610674565b602b610674565b6037610674565b600a610674565b602d610674565b6030610674565b600b610674565b610664610dd2565b6015610674565b6029610674565b6038610674565b610647610863366004611075565b610ddf565b6028610674565b6040610674565b6018610674565b600f610674565b6044610674565b6106747f000000000000000000000000000000000000000000000000000000000000000081565b6024610674565b601e610674565b6031610674565b6019610674565b6042610674565b6027610674565b6106746108ea3660046110bd565b600560209081525f928352604080842090915290825290205481565b603d610674565b6022610674565b610647610922366004610fd2565b610efd565b610664610f8b565b6007610674565b603e610674565b6020610674565b600e610674565b6012610674565b73ffffffffffffffffffffffffffffffffffffffff83165f908152600460205260408120548211156109e5576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f496e73756666696369656e742062616c616e636500000000000000000000000060448201526064015b60405180910390fd5b73ffffffffffffffffffffffffffffffffffffffff84165f908152600560209081526040808320338452909152902054821115610a7e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601660248201527f496e73756666696369656e7420616c6c6f77616e63650000000000000000000060448201526064016109dc565b73ffffffffffffffffffffffffffffffffffffffff84165f9081526004602052604081208054849290610ab290849061111b565b909155505073ffffffffffffffffffffffffffffffffffffffff83165f9081526004602052604081208054849290610aeb90849061112e565b909155505073ffffffffffffffffffffffffffffffffffffffff84165f90815260056020908152604080832033845290915281208054849290610b2f90849061111b565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051610b9591815260200190565b60405180910390a35060019392505050565b5f8054610bb390611141565b80601f0160208091040260200160405190810160405280929190818152602001828054610bdf90611141565b8015610c2a5780601f10610c0157610100808354040283529160200191610c2a565b820191905f5260205f20905b815481529060010190602001808311610c0d57829003601f168201915b505050505081565b335f81815260056020908152604080832073ffffffffffffffffffffffffffffffffffffffff8716808552925280832085905551919290917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92590610c999086815260200190565b60405180910390a35060015b92915050565b73ffffffffffffffffffffffffffffffffffffffff83165f90815260046020526040812054821115610d39576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600160248201527f410000000000000000000000000000000000000000000000000000000000000060448201526064016109dc565b73ffffffffffffffffffffffffffffffffffffffff84165f908152600560209081526040808320338452909152902054821115610a7e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600160248201527f420000000000000000000000000000000000000000000000000000000000000060448201526064016109dc565b60018054610bb390611141565b335f90815260046020526040812054821115610e57576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152601460248201527f496e73756666696369656e742062616c616e636500000000000000000000000060448201526064016109dc565b335f9081526004602052604081208054849290610e7590849061111b565b909155505073ffffffffffffffffffffffffffffffffffffffff83165f9081526004602052604081208054849290610eae90849061112e565b909155505060405182815273ffffffffffffffffffffffffffffffffffffffff84169033907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90602001610c99565b73ffffffffffffffffffffffffffffffffffffffff83165f90815260046020526040812054821115610a7e576040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152600160248201527f410000000000000000000000000000000000000000000000000000000000000060448201526064016109dc565b6040518061016001604052806101368152602001611193610136913981565b803573ffffffffffffffffffffffffffffffffffffffff81168114610fcd575f80fd5b919050565b5f805f60608486031215610fe4575f80fd5b610fed84610faa565b9250610ffb60208501610faa565b9150604084013590509250925092565b5f602080835283518060208501525f5b818110156110375785810183015185820160400152820161101b565b505f6040828601015260407fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8301168501019250505092915050565b5f8060408385031215611086575f80fd5b61108f83610faa565b946020939093013593505050565b5f602082840312156110ad575f80fd5b6110b682610faa565b9392505050565b5f80604083850312156110ce575f80fd5b6110d783610faa565b91506110e560208401610faa565b90509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b81810381811115610ca557610ca56110ee565b80820180821115610ca557610ca56110ee565b600181811c9082168061115557607f821691505b60208210810361118c577f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5091905056fe41414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141a2646970667358221220c70035169e4d38ee509e85ab2f5566c500caae43b66c105f4552e44745217d5f64736f6c63430008160033",
+}
+
+// StateBloatTokenABI is the input ABI used to generate the binding from.
+// Deprecated: Use StateBloatTokenMetaData.ABI instead.
+var StateBloatTokenABI = StateBloatTokenMetaData.ABI
+
+// StateBloatTokenBin is the compiled bytecode used for deploying new contracts.
+// Deprecated: Use StateBloatTokenMetaData.Bin instead.
+var StateBloatTokenBin = StateBloatTokenMetaData.Bin
+
+// DeployStateBloatToken deploys a new Ethereum contract, binding an instance of StateBloatToken to it.
+func DeployStateBloatToken(auth *bind.TransactOpts, backend bind.ContractBackend, _salt *big.Int) (common.Address, *types.Transaction, *StateBloatToken, error) {
+ parsed, err := StateBloatTokenMetaData.GetAbi()
+ if err != nil {
+ return common.Address{}, nil, nil, err
+ }
+ if parsed == nil {
+ return common.Address{}, nil, nil, errors.New("GetABI returned nil")
+ }
+
+ address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(StateBloatTokenBin), backend, _salt)
+ if err != nil {
+ return common.Address{}, nil, nil, err
+ }
+ return address, tx, &StateBloatToken{StateBloatTokenCaller: StateBloatTokenCaller{contract: contract}, StateBloatTokenTransactor: StateBloatTokenTransactor{contract: contract}, StateBloatTokenFilterer: StateBloatTokenFilterer{contract: contract}}, nil
+}
+
+// StateBloatToken is an auto generated Go binding around an Ethereum contract.
+type StateBloatToken struct {
+ StateBloatTokenCaller // Read-only binding to the contract
+ StateBloatTokenTransactor // Write-only binding to the contract
+ StateBloatTokenFilterer // Log filterer for contract events
+}
+
+// StateBloatTokenCaller is an auto generated read-only Go binding around an Ethereum contract.
+type StateBloatTokenCaller struct {
+ contract *bind.BoundContract // Generic contract wrapper for the low level calls
+}
+
+// StateBloatTokenTransactor is an auto generated write-only Go binding around an Ethereum contract.
+type StateBloatTokenTransactor struct {
+ contract *bind.BoundContract // Generic contract wrapper for the low level calls
+}
+
+// StateBloatTokenFilterer is an auto generated log filtering Go binding around an Ethereum contract events.
+type StateBloatTokenFilterer struct {
+ contract *bind.BoundContract // Generic contract wrapper for the low level calls
+}
+
+// StateBloatTokenSession is an auto generated Go binding around an Ethereum contract,
+// with pre-set call and transact options.
+type StateBloatTokenSession struct {
+ Contract *StateBloatToken // Generic contract binding to set the session for
+ CallOpts bind.CallOpts // Call options to use throughout this session
+ TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session
+}
+
+// StateBloatTokenCallerSession is an auto generated read-only Go binding around an Ethereum contract,
+// with pre-set call options.
+type StateBloatTokenCallerSession struct {
+ Contract *StateBloatTokenCaller // Generic contract caller binding to set the session for
+ CallOpts bind.CallOpts // Call options to use throughout this session
+}
+
+// StateBloatTokenTransactorSession is an auto generated write-only Go binding around an Ethereum contract,
+// with pre-set transact options.
+type StateBloatTokenTransactorSession struct {
+ Contract *StateBloatTokenTransactor // Generic contract transactor binding to set the session for
+ TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session
+}
+
+// StateBloatTokenRaw is an auto generated low-level Go binding around an Ethereum contract.
+type StateBloatTokenRaw struct {
+ Contract *StateBloatToken // Generic contract binding to access the raw methods on
+}
+
+// StateBloatTokenCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract.
+type StateBloatTokenCallerRaw struct {
+ Contract *StateBloatTokenCaller // Generic read-only contract binding to access the raw methods on
+}
+
+// StateBloatTokenTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract.
+type StateBloatTokenTransactorRaw struct {
+ Contract *StateBloatTokenTransactor // Generic write-only contract binding to access the raw methods on
+}
+
+// NewStateBloatToken creates a new instance of StateBloatToken, bound to a specific deployed contract.
+func NewStateBloatToken(address common.Address, backend bind.ContractBackend) (*StateBloatToken, error) {
+ contract, err := bindStateBloatToken(address, backend, backend, backend)
+ if err != nil {
+ return nil, err
+ }
+ return &StateBloatToken{StateBloatTokenCaller: StateBloatTokenCaller{contract: contract}, StateBloatTokenTransactor: StateBloatTokenTransactor{contract: contract}, StateBloatTokenFilterer: StateBloatTokenFilterer{contract: contract}}, nil
+}
+
+// NewStateBloatTokenCaller creates a new read-only instance of StateBloatToken, bound to a specific deployed contract.
+func NewStateBloatTokenCaller(address common.Address, caller bind.ContractCaller) (*StateBloatTokenCaller, error) {
+ contract, err := bindStateBloatToken(address, caller, nil, nil)
+ if err != nil {
+ return nil, err
+ }
+ return &StateBloatTokenCaller{contract: contract}, nil
+}
+
+// NewStateBloatTokenTransactor creates a new write-only instance of StateBloatToken, bound to a specific deployed contract.
+func NewStateBloatTokenTransactor(address common.Address, transactor bind.ContractTransactor) (*StateBloatTokenTransactor, error) {
+ contract, err := bindStateBloatToken(address, nil, transactor, nil)
+ if err != nil {
+ return nil, err
+ }
+ return &StateBloatTokenTransactor{contract: contract}, nil
+}
+
+// NewStateBloatTokenFilterer creates a new log filterer instance of StateBloatToken, bound to a specific deployed contract.
+func NewStateBloatTokenFilterer(address common.Address, filterer bind.ContractFilterer) (*StateBloatTokenFilterer, error) {
+ contract, err := bindStateBloatToken(address, nil, nil, filterer)
+ if err != nil {
+ return nil, err
+ }
+ return &StateBloatTokenFilterer{contract: contract}, nil
+}
+
+// bindStateBloatToken binds a generic wrapper to an already deployed contract.
+func bindStateBloatToken(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) {
+ parsed, err := StateBloatTokenMetaData.GetAbi()
+ if err != nil {
+ return nil, err
+ }
+ return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil
+}
+
+// Call invokes the (constant) contract method with params as input values and
+// sets the output to result. The result type might be a single field for simple
+// returns, a slice of interfaces for anonymous returns and a struct for named
+// returns.
+func (_StateBloatToken *StateBloatTokenRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error {
+ return _StateBloatToken.Contract.StateBloatTokenCaller.contract.Call(opts, result, method, params...)
+}
+
+// Transfer initiates a plain transaction to move funds to the contract, calling
+// its default method if one is available.
+func (_StateBloatToken *StateBloatTokenRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) {
+ return _StateBloatToken.Contract.StateBloatTokenTransactor.contract.Transfer(opts)
+}
+
+// Transact invokes the (paid) contract method with params as input values.
+func (_StateBloatToken *StateBloatTokenRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) {
+ return _StateBloatToken.Contract.StateBloatTokenTransactor.contract.Transact(opts, method, params...)
+}
+
+// Call invokes the (constant) contract method with params as input values and
+// sets the output to result. The result type might be a single field for simple
+// returns, a slice of interfaces for anonymous returns and a struct for named
+// returns.
+func (_StateBloatToken *StateBloatTokenCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error {
+ return _StateBloatToken.Contract.contract.Call(opts, result, method, params...)
+}
+
+// Transfer initiates a plain transaction to move funds to the contract, calling
+// its default method if one is available.
+func (_StateBloatToken *StateBloatTokenTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) {
+ return _StateBloatToken.Contract.contract.Transfer(opts)
+}
+
+// Transact invokes the (paid) contract method with params as input values.
+func (_StateBloatToken *StateBloatTokenTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) {
+ return _StateBloatToken.Contract.contract.Transact(opts, method, params...)
+}
+
+// PADDINGDATA is a free data retrieval call binding the contract method 0xee1682b6.
+//
+// Solidity: function PADDING_DATA() view returns(string)
+func (_StateBloatToken *StateBloatTokenCaller) PADDINGDATA(opts *bind.CallOpts) (string, error) {
+ var out []interface{}
+ err := _StateBloatToken.contract.Call(opts, &out, "PADDING_DATA")
+
+ if err != nil {
+ return *new(string), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(string)).(*string)
+
+ return out0, err
+
+}
+
+// PADDINGDATA is a free data retrieval call binding the contract method 0xee1682b6.
+//
+// Solidity: function PADDING_DATA() view returns(string)
+func (_StateBloatToken *StateBloatTokenSession) PADDINGDATA() (string, error) {
+ return _StateBloatToken.Contract.PADDINGDATA(&_StateBloatToken.CallOpts)
+}
+
+// PADDINGDATA is a free data retrieval call binding the contract method 0xee1682b6.
+//
+// Solidity: function PADDING_DATA() view returns(string)
+func (_StateBloatToken *StateBloatTokenCallerSession) PADDINGDATA() (string, error) {
+ return _StateBloatToken.Contract.PADDINGDATA(&_StateBloatToken.CallOpts)
+}
+
+// Allowance is a free data retrieval call binding the contract method 0xdd62ed3e.
+//
+// Solidity: function allowance(address , address ) view returns(uint256)
+func (_StateBloatToken *StateBloatTokenCaller) Allowance(opts *bind.CallOpts, arg0 common.Address, arg1 common.Address) (*big.Int, error) {
+ var out []interface{}
+ err := _StateBloatToken.contract.Call(opts, &out, "allowance", arg0, arg1)
+
+ if err != nil {
+ return *new(*big.Int), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
+
+ return out0, err
+
+}
+
+// Allowance is a free data retrieval call binding the contract method 0xdd62ed3e.
+//
+// Solidity: function allowance(address , address ) view returns(uint256)
+func (_StateBloatToken *StateBloatTokenSession) Allowance(arg0 common.Address, arg1 common.Address) (*big.Int, error) {
+ return _StateBloatToken.Contract.Allowance(&_StateBloatToken.CallOpts, arg0, arg1)
+}
+
+// Allowance is a free data retrieval call binding the contract method 0xdd62ed3e.
+//
+// Solidity: function allowance(address , address ) view returns(uint256)
+func (_StateBloatToken *StateBloatTokenCallerSession) Allowance(arg0 common.Address, arg1 common.Address) (*big.Int, error) {
+ return _StateBloatToken.Contract.Allowance(&_StateBloatToken.CallOpts, arg0, arg1)
+}
+
+// BalanceOf is a free data retrieval call binding the contract method 0x70a08231.
+//
+// Solidity: function balanceOf(address ) view returns(uint256)
+func (_StateBloatToken *StateBloatTokenCaller) BalanceOf(opts *bind.CallOpts, arg0 common.Address) (*big.Int, error) {
+ var out []interface{}
+ err := _StateBloatToken.contract.Call(opts, &out, "balanceOf", arg0)
+
+ if err != nil {
+ return *new(*big.Int), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
+
+ return out0, err
+
+}
+
+// BalanceOf is a free data retrieval call binding the contract method 0x70a08231.
+//
+// Solidity: function balanceOf(address ) view returns(uint256)
+func (_StateBloatToken *StateBloatTokenSession) BalanceOf(arg0 common.Address) (*big.Int, error) {
+ return _StateBloatToken.Contract.BalanceOf(&_StateBloatToken.CallOpts, arg0)
+}
+
+// BalanceOf is a free data retrieval call binding the contract method 0x70a08231.
+//
+// Solidity: function balanceOf(address ) view returns(uint256)
+func (_StateBloatToken *StateBloatTokenCallerSession) BalanceOf(arg0 common.Address) (*big.Int, error) {
+ return _StateBloatToken.Contract.BalanceOf(&_StateBloatToken.CallOpts, arg0)
+}
+
+// Decimals is a free data retrieval call binding the contract method 0x313ce567.
+//
+// Solidity: function decimals() view returns(uint8)
+func (_StateBloatToken *StateBloatTokenCaller) Decimals(opts *bind.CallOpts) (uint8, error) {
+ var out []interface{}
+ err := _StateBloatToken.contract.Call(opts, &out, "decimals")
+
+ if err != nil {
+ return *new(uint8), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(uint8)).(*uint8)
+
+ return out0, err
+
+}
+
+// Decimals is a free data retrieval call binding the contract method 0x313ce567.
+//
+// Solidity: function decimals() view returns(uint8)
+func (_StateBloatToken *StateBloatTokenSession) Decimals() (uint8, error) {
+ return _StateBloatToken.Contract.Decimals(&_StateBloatToken.CallOpts)
+}
+
+// Decimals is a free data retrieval call binding the contract method 0x313ce567.
+//
+// Solidity: function decimals() view returns(uint8)
+func (_StateBloatToken *StateBloatTokenCallerSession) Decimals() (uint8, error) {
+ return _StateBloatToken.Contract.Decimals(&_StateBloatToken.CallOpts)
+}
+
+// Dummy1 is a free data retrieval call binding the contract method 0x2545d8b7.
+//
+// Solidity: function dummy1() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCaller) Dummy1(opts *bind.CallOpts) (*big.Int, error) {
+ var out []interface{}
+ err := _StateBloatToken.contract.Call(opts, &out, "dummy1")
+
+ if err != nil {
+ return *new(*big.Int), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
+
+ return out0, err
+
+}
+
+// Dummy1 is a free data retrieval call binding the contract method 0x2545d8b7.
+//
+// Solidity: function dummy1() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenSession) Dummy1() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy1(&_StateBloatToken.CallOpts)
+}
+
+// Dummy1 is a free data retrieval call binding the contract method 0x2545d8b7.
+//
+// Solidity: function dummy1() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCallerSession) Dummy1() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy1(&_StateBloatToken.CallOpts)
+}
+
+// Dummy10 is a free data retrieval call binding the contract method 0x7e544937.
+//
+// Solidity: function dummy10() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCaller) Dummy10(opts *bind.CallOpts) (*big.Int, error) {
+ var out []interface{}
+ err := _StateBloatToken.contract.Call(opts, &out, "dummy10")
+
+ if err != nil {
+ return *new(*big.Int), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
+
+ return out0, err
+
+}
+
+// Dummy10 is a free data retrieval call binding the contract method 0x7e544937.
+//
+// Solidity: function dummy10() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenSession) Dummy10() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy10(&_StateBloatToken.CallOpts)
+}
+
+// Dummy10 is a free data retrieval call binding the contract method 0x7e544937.
+//
+// Solidity: function dummy10() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCallerSession) Dummy10() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy10(&_StateBloatToken.CallOpts)
+}
+
+// Dummy11 is a free data retrieval call binding the contract method 0x8f4a8406.
+//
+// Solidity: function dummy11() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCaller) Dummy11(opts *bind.CallOpts) (*big.Int, error) {
+ var out []interface{}
+ err := _StateBloatToken.contract.Call(opts, &out, "dummy11")
+
+ if err != nil {
+ return *new(*big.Int), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
+
+ return out0, err
+
+}
+
+// Dummy11 is a free data retrieval call binding the contract method 0x8f4a8406.
+//
+// Solidity: function dummy11() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenSession) Dummy11() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy11(&_StateBloatToken.CallOpts)
+}
+
+// Dummy11 is a free data retrieval call binding the contract method 0x8f4a8406.
+//
+// Solidity: function dummy11() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCallerSession) Dummy11() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy11(&_StateBloatToken.CallOpts)
+}
+
+// Dummy12 is a free data retrieval call binding the contract method 0x3ea117ce.
+//
+// Solidity: function dummy12() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCaller) Dummy12(opts *bind.CallOpts) (*big.Int, error) {
+ var out []interface{}
+ err := _StateBloatToken.contract.Call(opts, &out, "dummy12")
+
+ if err != nil {
+ return *new(*big.Int), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
+
+ return out0, err
+
+}
+
+// Dummy12 is a free data retrieval call binding the contract method 0x3ea117ce.
+//
+// Solidity: function dummy12() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenSession) Dummy12() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy12(&_StateBloatToken.CallOpts)
+}
+
+// Dummy12 is a free data retrieval call binding the contract method 0x3ea117ce.
+//
+// Solidity: function dummy12() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCallerSession) Dummy12() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy12(&_StateBloatToken.CallOpts)
+}
+
+// Dummy13 is a free data retrieval call binding the contract method 0x672151fe.
+//
+// Solidity: function dummy13() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCaller) Dummy13(opts *bind.CallOpts) (*big.Int, error) {
+ var out []interface{}
+ err := _StateBloatToken.contract.Call(opts, &out, "dummy13")
+
+ if err != nil {
+ return *new(*big.Int), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
+
+ return out0, err
+
+}
+
+// Dummy13 is a free data retrieval call binding the contract method 0x672151fe.
+//
+// Solidity: function dummy13() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenSession) Dummy13() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy13(&_StateBloatToken.CallOpts)
+}
+
+// Dummy13 is a free data retrieval call binding the contract method 0x672151fe.
+//
+// Solidity: function dummy13() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCallerSession) Dummy13() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy13(&_StateBloatToken.CallOpts)
+}
+
+// Dummy14 is a free data retrieval call binding the contract method 0xfe7d5996.
+//
+// Solidity: function dummy14() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCaller) Dummy14(opts *bind.CallOpts) (*big.Int, error) {
+ var out []interface{}
+ err := _StateBloatToken.contract.Call(opts, &out, "dummy14")
+
+ if err != nil {
+ return *new(*big.Int), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
+
+ return out0, err
+
+}
+
+// Dummy14 is a free data retrieval call binding the contract method 0xfe7d5996.
+//
+// Solidity: function dummy14() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenSession) Dummy14() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy14(&_StateBloatToken.CallOpts)
+}
+
+// Dummy14 is a free data retrieval call binding the contract method 0xfe7d5996.
+//
+// Solidity: function dummy14() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCallerSession) Dummy14() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy14(&_StateBloatToken.CallOpts)
+}
+
+// Dummy15 is a free data retrieval call binding the contract method 0xb66dd750.
+//
+// Solidity: function dummy15() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCaller) Dummy15(opts *bind.CallOpts) (*big.Int, error) {
+ var out []interface{}
+ err := _StateBloatToken.contract.Call(opts, &out, "dummy15")
+
+ if err != nil {
+ return *new(*big.Int), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
+
+ return out0, err
+
+}
+
+// Dummy15 is a free data retrieval call binding the contract method 0xb66dd750.
+//
+// Solidity: function dummy15() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenSession) Dummy15() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy15(&_StateBloatToken.CallOpts)
+}
+
+// Dummy15 is a free data retrieval call binding the contract method 0xb66dd750.
+//
+// Solidity: function dummy15() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCallerSession) Dummy15() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy15(&_StateBloatToken.CallOpts)
+}
+
+// Dummy16 is a free data retrieval call binding the contract method 0x1eaa7c52.
+//
+// Solidity: function dummy16() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCaller) Dummy16(opts *bind.CallOpts) (*big.Int, error) {
+ var out []interface{}
+ err := _StateBloatToken.contract.Call(opts, &out, "dummy16")
+
+ if err != nil {
+ return *new(*big.Int), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
+
+ return out0, err
+
+}
+
+// Dummy16 is a free data retrieval call binding the contract method 0x1eaa7c52.
+//
+// Solidity: function dummy16() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenSession) Dummy16() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy16(&_StateBloatToken.CallOpts)
+}
+
+// Dummy16 is a free data retrieval call binding the contract method 0x1eaa7c52.
+//
+// Solidity: function dummy16() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCallerSession) Dummy16() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy16(&_StateBloatToken.CallOpts)
+}
+
+// Dummy17 is a free data retrieval call binding the contract method 0x4a2e93c6.
+//
+// Solidity: function dummy17() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCaller) Dummy17(opts *bind.CallOpts) (*big.Int, error) {
+ var out []interface{}
+ err := _StateBloatToken.contract.Call(opts, &out, "dummy17")
+
+ if err != nil {
+ return *new(*big.Int), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
+
+ return out0, err
+
+}
+
+// Dummy17 is a free data retrieval call binding the contract method 0x4a2e93c6.
+//
+// Solidity: function dummy17() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenSession) Dummy17() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy17(&_StateBloatToken.CallOpts)
+}
+
+// Dummy17 is a free data retrieval call binding the contract method 0x4a2e93c6.
+//
+// Solidity: function dummy17() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCallerSession) Dummy17() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy17(&_StateBloatToken.CallOpts)
+}
+
+// Dummy18 is a free data retrieval call binding the contract method 0xffbf0469.
+//
+// Solidity: function dummy18() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCaller) Dummy18(opts *bind.CallOpts) (*big.Int, error) {
+ var out []interface{}
+ err := _StateBloatToken.contract.Call(opts, &out, "dummy18")
+
+ if err != nil {
+ return *new(*big.Int), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
+
+ return out0, err
+
+}
+
+// Dummy18 is a free data retrieval call binding the contract method 0xffbf0469.
+//
+// Solidity: function dummy18() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenSession) Dummy18() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy18(&_StateBloatToken.CallOpts)
+}
+
+// Dummy18 is a free data retrieval call binding the contract method 0xffbf0469.
+//
+// Solidity: function dummy18() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCallerSession) Dummy18() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy18(&_StateBloatToken.CallOpts)
+}
+
+// Dummy19 is a free data retrieval call binding the contract method 0x65473174.
+//
+// Solidity: function dummy19() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCaller) Dummy19(opts *bind.CallOpts) (*big.Int, error) {
+ var out []interface{}
+ err := _StateBloatToken.contract.Call(opts, &out, "dummy19")
+
+ if err != nil {
+ return *new(*big.Int), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
+
+ return out0, err
+
+}
+
+// Dummy19 is a free data retrieval call binding the contract method 0x65473174.
+//
+// Solidity: function dummy19() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenSession) Dummy19() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy19(&_StateBloatToken.CallOpts)
+}
+
+// Dummy19 is a free data retrieval call binding the contract method 0x65473174.
+//
+// Solidity: function dummy19() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCallerSession) Dummy19() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy19(&_StateBloatToken.CallOpts)
+}
+
+// Dummy2 is a free data retrieval call binding the contract method 0x1d527cde.
+//
+// Solidity: function dummy2() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCaller) Dummy2(opts *bind.CallOpts) (*big.Int, error) {
+ var out []interface{}
+ err := _StateBloatToken.contract.Call(opts, &out, "dummy2")
+
+ if err != nil {
+ return *new(*big.Int), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
+
+ return out0, err
+
+}
+
+// Dummy2 is a free data retrieval call binding the contract method 0x1d527cde.
+//
+// Solidity: function dummy2() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenSession) Dummy2() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy2(&_StateBloatToken.CallOpts)
+}
+
+// Dummy2 is a free data retrieval call binding the contract method 0x1d527cde.
+//
+// Solidity: function dummy2() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCallerSession) Dummy2() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy2(&_StateBloatToken.CallOpts)
+}
+
+// Dummy20 is a free data retrieval call binding the contract method 0x61b970eb.
+//
+// Solidity: function dummy20() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCaller) Dummy20(opts *bind.CallOpts) (*big.Int, error) {
+ var out []interface{}
+ err := _StateBloatToken.contract.Call(opts, &out, "dummy20")
+
+ if err != nil {
+ return *new(*big.Int), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
+
+ return out0, err
+
+}
+
+// Dummy20 is a free data retrieval call binding the contract method 0x61b970eb.
+//
+// Solidity: function dummy20() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenSession) Dummy20() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy20(&_StateBloatToken.CallOpts)
+}
+
+// Dummy20 is a free data retrieval call binding the contract method 0x61b970eb.
+//
+// Solidity: function dummy20() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCallerSession) Dummy20() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy20(&_StateBloatToken.CallOpts)
+}
+
+// Dummy21 is a free data retrieval call binding the contract method 0x9c5dfe73.
+//
+// Solidity: function dummy21() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCaller) Dummy21(opts *bind.CallOpts) (*big.Int, error) {
+ var out []interface{}
+ err := _StateBloatToken.contract.Call(opts, &out, "dummy21")
+
+ if err != nil {
+ return *new(*big.Int), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
+
+ return out0, err
+
+}
+
+// Dummy21 is a free data retrieval call binding the contract method 0x9c5dfe73.
+//
+// Solidity: function dummy21() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenSession) Dummy21() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy21(&_StateBloatToken.CallOpts)
+}
+
+// Dummy21 is a free data retrieval call binding the contract method 0x9c5dfe73.
+//
+// Solidity: function dummy21() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCallerSession) Dummy21() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy21(&_StateBloatToken.CallOpts)
+}
+
+// Dummy22 is a free data retrieval call binding the contract method 0x74e73fd3.
+//
+// Solidity: function dummy22() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCaller) Dummy22(opts *bind.CallOpts) (*big.Int, error) {
+ var out []interface{}
+ err := _StateBloatToken.contract.Call(opts, &out, "dummy22")
+
+ if err != nil {
+ return *new(*big.Int), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
+
+ return out0, err
+
+}
+
+// Dummy22 is a free data retrieval call binding the contract method 0x74e73fd3.
+//
+// Solidity: function dummy22() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenSession) Dummy22() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy22(&_StateBloatToken.CallOpts)
+}
+
+// Dummy22 is a free data retrieval call binding the contract method 0x74e73fd3.
+//
+// Solidity: function dummy22() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCallerSession) Dummy22() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy22(&_StateBloatToken.CallOpts)
+}
+
+// Dummy23 is a free data retrieval call binding the contract method 0x6abceacd.
+//
+// Solidity: function dummy23() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCaller) Dummy23(opts *bind.CallOpts) (*big.Int, error) {
+ var out []interface{}
+ err := _StateBloatToken.contract.Call(opts, &out, "dummy23")
+
+ if err != nil {
+ return *new(*big.Int), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
+
+ return out0, err
+
+}
+
+// Dummy23 is a free data retrieval call binding the contract method 0x6abceacd.
+//
+// Solidity: function dummy23() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenSession) Dummy23() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy23(&_StateBloatToken.CallOpts)
+}
+
+// Dummy23 is a free data retrieval call binding the contract method 0x6abceacd.
+//
+// Solidity: function dummy23() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCallerSession) Dummy23() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy23(&_StateBloatToken.CallOpts)
+}
+
+// Dummy24 is a free data retrieval call binding the contract method 0xb2bb360e.
+//
+// Solidity: function dummy24() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCaller) Dummy24(opts *bind.CallOpts) (*big.Int, error) {
+ var out []interface{}
+ err := _StateBloatToken.contract.Call(opts, &out, "dummy24")
+
+ if err != nil {
+ return *new(*big.Int), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
+
+ return out0, err
+
+}
+
+// Dummy24 is a free data retrieval call binding the contract method 0xb2bb360e.
+//
+// Solidity: function dummy24() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenSession) Dummy24() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy24(&_StateBloatToken.CallOpts)
+}
+
+// Dummy24 is a free data retrieval call binding the contract method 0xb2bb360e.
+//
+// Solidity: function dummy24() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCallerSession) Dummy24() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy24(&_StateBloatToken.CallOpts)
+}
+
+// Dummy25 is a free data retrieval call binding the contract method 0xd7419469.
+//
+// Solidity: function dummy25() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCaller) Dummy25(opts *bind.CallOpts) (*big.Int, error) {
+ var out []interface{}
+ err := _StateBloatToken.contract.Call(opts, &out, "dummy25")
+
+ if err != nil {
+ return *new(*big.Int), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
+
+ return out0, err
+
+}
+
+// Dummy25 is a free data retrieval call binding the contract method 0xd7419469.
+//
+// Solidity: function dummy25() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenSession) Dummy25() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy25(&_StateBloatToken.CallOpts)
+}
+
+// Dummy25 is a free data retrieval call binding the contract method 0xd7419469.
+//
+// Solidity: function dummy25() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCallerSession) Dummy25() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy25(&_StateBloatToken.CallOpts)
+}
+
+// Dummy26 is a free data retrieval call binding the contract method 0x12901b42.
+//
+// Solidity: function dummy26() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCaller) Dummy26(opts *bind.CallOpts) (*big.Int, error) {
+ var out []interface{}
+ err := _StateBloatToken.contract.Call(opts, &out, "dummy26")
+
+ if err != nil {
+ return *new(*big.Int), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
+
+ return out0, err
+
+}
+
+// Dummy26 is a free data retrieval call binding the contract method 0x12901b42.
+//
+// Solidity: function dummy26() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenSession) Dummy26() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy26(&_StateBloatToken.CallOpts)
+}
+
+// Dummy26 is a free data retrieval call binding the contract method 0x12901b42.
+//
+// Solidity: function dummy26() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCallerSession) Dummy26() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy26(&_StateBloatToken.CallOpts)
+}
+
+// Dummy27 is a free data retrieval call binding the contract method 0x0cb7a9e7.
+//
+// Solidity: function dummy27() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCaller) Dummy27(opts *bind.CallOpts) (*big.Int, error) {
+ var out []interface{}
+ err := _StateBloatToken.contract.Call(opts, &out, "dummy27")
+
+ if err != nil {
+ return *new(*big.Int), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
+
+ return out0, err
+
+}
+
+// Dummy27 is a free data retrieval call binding the contract method 0x0cb7a9e7.
+//
+// Solidity: function dummy27() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenSession) Dummy27() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy27(&_StateBloatToken.CallOpts)
+}
+
+// Dummy27 is a free data retrieval call binding the contract method 0x0cb7a9e7.
+//
+// Solidity: function dummy27() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCallerSession) Dummy27() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy27(&_StateBloatToken.CallOpts)
+}
+
+// Dummy28 is a free data retrieval call binding the contract method 0x418b1816.
+//
+// Solidity: function dummy28() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCaller) Dummy28(opts *bind.CallOpts) (*big.Int, error) {
+ var out []interface{}
+ err := _StateBloatToken.contract.Call(opts, &out, "dummy28")
+
+ if err != nil {
+ return *new(*big.Int), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
+
+ return out0, err
+
+}
+
+// Dummy28 is a free data retrieval call binding the contract method 0x418b1816.
+//
+// Solidity: function dummy28() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenSession) Dummy28() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy28(&_StateBloatToken.CallOpts)
+}
+
+// Dummy28 is a free data retrieval call binding the contract method 0x418b1816.
+//
+// Solidity: function dummy28() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCallerSession) Dummy28() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy28(&_StateBloatToken.CallOpts)
+}
+
+// Dummy29 is a free data retrieval call binding the contract method 0x13ebb5ec.
+//
+// Solidity: function dummy29() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCaller) Dummy29(opts *bind.CallOpts) (*big.Int, error) {
+ var out []interface{}
+ err := _StateBloatToken.contract.Call(opts, &out, "dummy29")
+
+ if err != nil {
+ return *new(*big.Int), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
+
+ return out0, err
+
+}
+
+// Dummy29 is a free data retrieval call binding the contract method 0x13ebb5ec.
+//
+// Solidity: function dummy29() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenSession) Dummy29() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy29(&_StateBloatToken.CallOpts)
+}
+
+// Dummy29 is a free data retrieval call binding the contract method 0x13ebb5ec.
+//
+// Solidity: function dummy29() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCallerSession) Dummy29() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy29(&_StateBloatToken.CallOpts)
+}
+
+// Dummy3 is a free data retrieval call binding the contract method 0x1a97f18e.
+//
+// Solidity: function dummy3() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCaller) Dummy3(opts *bind.CallOpts) (*big.Int, error) {
+ var out []interface{}
+ err := _StateBloatToken.contract.Call(opts, &out, "dummy3")
+
+ if err != nil {
+ return *new(*big.Int), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
+
+ return out0, err
+
+}
+
+// Dummy3 is a free data retrieval call binding the contract method 0x1a97f18e.
+//
+// Solidity: function dummy3() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenSession) Dummy3() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy3(&_StateBloatToken.CallOpts)
+}
+
+// Dummy3 is a free data retrieval call binding the contract method 0x1a97f18e.
+//
+// Solidity: function dummy3() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCallerSession) Dummy3() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy3(&_StateBloatToken.CallOpts)
+}
+
+// Dummy30 is a free data retrieval call binding the contract method 0xcfd66863.
+//
+// Solidity: function dummy30() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCaller) Dummy30(opts *bind.CallOpts) (*big.Int, error) {
+ var out []interface{}
+ err := _StateBloatToken.contract.Call(opts, &out, "dummy30")
+
+ if err != nil {
+ return *new(*big.Int), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
+
+ return out0, err
+
+}
+
+// Dummy30 is a free data retrieval call binding the contract method 0xcfd66863.
+//
+// Solidity: function dummy30() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenSession) Dummy30() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy30(&_StateBloatToken.CallOpts)
+}
+
+// Dummy30 is a free data retrieval call binding the contract method 0xcfd66863.
+//
+// Solidity: function dummy30() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCallerSession) Dummy30() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy30(&_StateBloatToken.CallOpts)
+}
+
+// Dummy31 is a free data retrieval call binding the contract method 0x4e1dbb82.
+//
+// Solidity: function dummy31() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCaller) Dummy31(opts *bind.CallOpts) (*big.Int, error) {
+ var out []interface{}
+ err := _StateBloatToken.contract.Call(opts, &out, "dummy31")
+
+ if err != nil {
+ return *new(*big.Int), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
+
+ return out0, err
+
+}
+
+// Dummy31 is a free data retrieval call binding the contract method 0x4e1dbb82.
+//
+// Solidity: function dummy31() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenSession) Dummy31() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy31(&_StateBloatToken.CallOpts)
+}
+
+// Dummy31 is a free data retrieval call binding the contract method 0x4e1dbb82.
+//
+// Solidity: function dummy31() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCallerSession) Dummy31() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy31(&_StateBloatToken.CallOpts)
+}
+
+// Dummy32 is a free data retrieval call binding the contract method 0xf8716f14.
+//
+// Solidity: function dummy32() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCaller) Dummy32(opts *bind.CallOpts) (*big.Int, error) {
+ var out []interface{}
+ err := _StateBloatToken.contract.Call(opts, &out, "dummy32")
+
+ if err != nil {
+ return *new(*big.Int), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
+
+ return out0, err
+
+}
+
+// Dummy32 is a free data retrieval call binding the contract method 0xf8716f14.
+//
+// Solidity: function dummy32() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenSession) Dummy32() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy32(&_StateBloatToken.CallOpts)
+}
+
+// Dummy32 is a free data retrieval call binding the contract method 0xf8716f14.
+//
+// Solidity: function dummy32() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCallerSession) Dummy32() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy32(&_StateBloatToken.CallOpts)
+}
+
+// Dummy33 is a free data retrieval call binding the contract method 0x4b3c7f5f.
+//
+// Solidity: function dummy33() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCaller) Dummy33(opts *bind.CallOpts) (*big.Int, error) {
+ var out []interface{}
+ err := _StateBloatToken.contract.Call(opts, &out, "dummy33")
+
+ if err != nil {
+ return *new(*big.Int), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
+
+ return out0, err
+
+}
+
+// Dummy33 is a free data retrieval call binding the contract method 0x4b3c7f5f.
+//
+// Solidity: function dummy33() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenSession) Dummy33() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy33(&_StateBloatToken.CallOpts)
+}
+
+// Dummy33 is a free data retrieval call binding the contract method 0x4b3c7f5f.
+//
+// Solidity: function dummy33() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCallerSession) Dummy33() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy33(&_StateBloatToken.CallOpts)
+}
+
+// Dummy34 is a free data retrieval call binding the contract method 0xe8c927b3.
+//
+// Solidity: function dummy34() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCaller) Dummy34(opts *bind.CallOpts) (*big.Int, error) {
+ var out []interface{}
+ err := _StateBloatToken.contract.Call(opts, &out, "dummy34")
+
+ if err != nil {
+ return *new(*big.Int), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
+
+ return out0, err
+
+}
+
+// Dummy34 is a free data retrieval call binding the contract method 0xe8c927b3.
+//
+// Solidity: function dummy34() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenSession) Dummy34() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy34(&_StateBloatToken.CallOpts)
+}
+
+// Dummy34 is a free data retrieval call binding the contract method 0xe8c927b3.
+//
+// Solidity: function dummy34() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCallerSession) Dummy34() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy34(&_StateBloatToken.CallOpts)
+}
+
+// Dummy35 is a free data retrieval call binding the contract method 0x43a6b92d.
+//
+// Solidity: function dummy35() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCaller) Dummy35(opts *bind.CallOpts) (*big.Int, error) {
+ var out []interface{}
+ err := _StateBloatToken.contract.Call(opts, &out, "dummy35")
+
+ if err != nil {
+ return *new(*big.Int), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
+
+ return out0, err
+
+}
+
+// Dummy35 is a free data retrieval call binding the contract method 0x43a6b92d.
+//
+// Solidity: function dummy35() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenSession) Dummy35() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy35(&_StateBloatToken.CallOpts)
+}
+
+// Dummy35 is a free data retrieval call binding the contract method 0x43a6b92d.
+//
+// Solidity: function dummy35() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCallerSession) Dummy35() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy35(&_StateBloatToken.CallOpts)
+}
+
+// Dummy36 is a free data retrieval call binding the contract method 0xc958d4bf.
+//
+// Solidity: function dummy36() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCaller) Dummy36(opts *bind.CallOpts) (*big.Int, error) {
+ var out []interface{}
+ err := _StateBloatToken.contract.Call(opts, &out, "dummy36")
+
+ if err != nil {
+ return *new(*big.Int), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
+
+ return out0, err
+
+}
+
+// Dummy36 is a free data retrieval call binding the contract method 0xc958d4bf.
+//
+// Solidity: function dummy36() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenSession) Dummy36() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy36(&_StateBloatToken.CallOpts)
+}
+
+// Dummy36 is a free data retrieval call binding the contract method 0xc958d4bf.
+//
+// Solidity: function dummy36() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCallerSession) Dummy36() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy36(&_StateBloatToken.CallOpts)
+}
+
+// Dummy37 is a free data retrieval call binding the contract method 0x639ec53a.
+//
+// Solidity: function dummy37() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCaller) Dummy37(opts *bind.CallOpts) (*big.Int, error) {
+ var out []interface{}
+ err := _StateBloatToken.contract.Call(opts, &out, "dummy37")
+
+ if err != nil {
+ return *new(*big.Int), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
+
+ return out0, err
+
+}
+
+// Dummy37 is a free data retrieval call binding the contract method 0x639ec53a.
+//
+// Solidity: function dummy37() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenSession) Dummy37() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy37(&_StateBloatToken.CallOpts)
+}
+
+// Dummy37 is a free data retrieval call binding the contract method 0x639ec53a.
+//
+// Solidity: function dummy37() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCallerSession) Dummy37() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy37(&_StateBloatToken.CallOpts)
+}
+
+// Dummy38 is a free data retrieval call binding the contract method 0x4f5e5557.
+//
+// Solidity: function dummy38() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCaller) Dummy38(opts *bind.CallOpts) (*big.Int, error) {
+ var out []interface{}
+ err := _StateBloatToken.contract.Call(opts, &out, "dummy38")
+
+ if err != nil {
+ return *new(*big.Int), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
+
+ return out0, err
+
+}
+
+// Dummy38 is a free data retrieval call binding the contract method 0x4f5e5557.
+//
+// Solidity: function dummy38() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenSession) Dummy38() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy38(&_StateBloatToken.CallOpts)
+}
+
+// Dummy38 is a free data retrieval call binding the contract method 0x4f5e5557.
+//
+// Solidity: function dummy38() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCallerSession) Dummy38() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy38(&_StateBloatToken.CallOpts)
+}
+
+// Dummy39 is a free data retrieval call binding the contract method 0xdc1d8a9b.
+//
+// Solidity: function dummy39() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCaller) Dummy39(opts *bind.CallOpts) (*big.Int, error) {
+ var out []interface{}
+ err := _StateBloatToken.contract.Call(opts, &out, "dummy39")
+
+ if err != nil {
+ return *new(*big.Int), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
+
+ return out0, err
+
+}
+
+// Dummy39 is a free data retrieval call binding the contract method 0xdc1d8a9b.
+//
+// Solidity: function dummy39() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenSession) Dummy39() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy39(&_StateBloatToken.CallOpts)
+}
+
+// Dummy39 is a free data retrieval call binding the contract method 0xdc1d8a9b.
+//
+// Solidity: function dummy39() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCallerSession) Dummy39() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy39(&_StateBloatToken.CallOpts)
+}
+
+// Dummy4 is a free data retrieval call binding the contract method 0x3b6be459.
+//
+// Solidity: function dummy4() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCaller) Dummy4(opts *bind.CallOpts) (*big.Int, error) {
+ var out []interface{}
+ err := _StateBloatToken.contract.Call(opts, &out, "dummy4")
+
+ if err != nil {
+ return *new(*big.Int), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
+
+ return out0, err
+
+}
+
+// Dummy4 is a free data retrieval call binding the contract method 0x3b6be459.
+//
+// Solidity: function dummy4() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenSession) Dummy4() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy4(&_StateBloatToken.CallOpts)
+}
+
+// Dummy4 is a free data retrieval call binding the contract method 0x3b6be459.
+//
+// Solidity: function dummy4() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCallerSession) Dummy4() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy4(&_StateBloatToken.CallOpts)
+}
+
+// Dummy40 is a free data retrieval call binding the contract method 0xaaa7af70.
+//
+// Solidity: function dummy40() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCaller) Dummy40(opts *bind.CallOpts) (*big.Int, error) {
+ var out []interface{}
+ err := _StateBloatToken.contract.Call(opts, &out, "dummy40")
+
+ if err != nil {
+ return *new(*big.Int), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
+
+ return out0, err
+
+}
+
+// Dummy40 is a free data retrieval call binding the contract method 0xaaa7af70.
+//
+// Solidity: function dummy40() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenSession) Dummy40() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy40(&_StateBloatToken.CallOpts)
+}
+
+// Dummy40 is a free data retrieval call binding the contract method 0xaaa7af70.
+//
+// Solidity: function dummy40() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCallerSession) Dummy40() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy40(&_StateBloatToken.CallOpts)
+}
+
+// Dummy41 is a free data retrieval call binding the contract method 0x9df61a25.
+//
+// Solidity: function dummy41() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCaller) Dummy41(opts *bind.CallOpts) (*big.Int, error) {
+ var out []interface{}
+ err := _StateBloatToken.contract.Call(opts, &out, "dummy41")
+
+ if err != nil {
+ return *new(*big.Int), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
+
+ return out0, err
+
+}
+
+// Dummy41 is a free data retrieval call binding the contract method 0x9df61a25.
+//
+// Solidity: function dummy41() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenSession) Dummy41() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy41(&_StateBloatToken.CallOpts)
+}
+
+// Dummy41 is a free data retrieval call binding the contract method 0x9df61a25.
+//
+// Solidity: function dummy41() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCallerSession) Dummy41() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy41(&_StateBloatToken.CallOpts)
+}
+
+// Dummy42 is a free data retrieval call binding the contract method 0x5af92c05.
+//
+// Solidity: function dummy42() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCaller) Dummy42(opts *bind.CallOpts) (*big.Int, error) {
+ var out []interface{}
+ err := _StateBloatToken.contract.Call(opts, &out, "dummy42")
+
+ if err != nil {
+ return *new(*big.Int), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
+
+ return out0, err
+
+}
+
+// Dummy42 is a free data retrieval call binding the contract method 0x5af92c05.
+//
+// Solidity: function dummy42() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenSession) Dummy42() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy42(&_StateBloatToken.CallOpts)
+}
+
+// Dummy42 is a free data retrieval call binding the contract method 0x5af92c05.
+//
+// Solidity: function dummy42() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCallerSession) Dummy42() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy42(&_StateBloatToken.CallOpts)
+}
+
+// Dummy43 is a free data retrieval call binding the contract method 0x7c72ed0d.
+//
+// Solidity: function dummy43() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCaller) Dummy43(opts *bind.CallOpts) (*big.Int, error) {
+ var out []interface{}
+ err := _StateBloatToken.contract.Call(opts, &out, "dummy43")
+
+ if err != nil {
+ return *new(*big.Int), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
+
+ return out0, err
+
+}
+
+// Dummy43 is a free data retrieval call binding the contract method 0x7c72ed0d.
+//
+// Solidity: function dummy43() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenSession) Dummy43() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy43(&_StateBloatToken.CallOpts)
+}
+
+// Dummy43 is a free data retrieval call binding the contract method 0x7c72ed0d.
+//
+// Solidity: function dummy43() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCallerSession) Dummy43() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy43(&_StateBloatToken.CallOpts)
+}
+
+// Dummy44 is a free data retrieval call binding the contract method 0x239af2a5.
+//
+// Solidity: function dummy44() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCaller) Dummy44(opts *bind.CallOpts) (*big.Int, error) {
+ var out []interface{}
+ err := _StateBloatToken.contract.Call(opts, &out, "dummy44")
+
+ if err != nil {
+ return *new(*big.Int), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
+
+ return out0, err
+
+}
+
+// Dummy44 is a free data retrieval call binding the contract method 0x239af2a5.
+//
+// Solidity: function dummy44() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenSession) Dummy44() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy44(&_StateBloatToken.CallOpts)
+}
+
+// Dummy44 is a free data retrieval call binding the contract method 0x239af2a5.
+//
+// Solidity: function dummy44() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCallerSession) Dummy44() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy44(&_StateBloatToken.CallOpts)
+}
+
+// Dummy45 is a free data retrieval call binding the contract method 0x7f34d94b.
+//
+// Solidity: function dummy45() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCaller) Dummy45(opts *bind.CallOpts) (*big.Int, error) {
+ var out []interface{}
+ err := _StateBloatToken.contract.Call(opts, &out, "dummy45")
+
+ if err != nil {
+ return *new(*big.Int), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
+
+ return out0, err
+
+}
+
+// Dummy45 is a free data retrieval call binding the contract method 0x7f34d94b.
+//
+// Solidity: function dummy45() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenSession) Dummy45() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy45(&_StateBloatToken.CallOpts)
+}
+
+// Dummy45 is a free data retrieval call binding the contract method 0x7f34d94b.
+//
+// Solidity: function dummy45() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCallerSession) Dummy45() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy45(&_StateBloatToken.CallOpts)
+}
+
+// Dummy46 is a free data retrieval call binding the contract method 0x21ecd7a3.
+//
+// Solidity: function dummy46() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCaller) Dummy46(opts *bind.CallOpts) (*big.Int, error) {
+ var out []interface{}
+ err := _StateBloatToken.contract.Call(opts, &out, "dummy46")
+
+ if err != nil {
+ return *new(*big.Int), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
+
+ return out0, err
+
+}
+
+// Dummy46 is a free data retrieval call binding the contract method 0x21ecd7a3.
+//
+// Solidity: function dummy46() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenSession) Dummy46() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy46(&_StateBloatToken.CallOpts)
+}
+
+// Dummy46 is a free data retrieval call binding the contract method 0x21ecd7a3.
+//
+// Solidity: function dummy46() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCallerSession) Dummy46() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy46(&_StateBloatToken.CallOpts)
+}
+
+// Dummy47 is a free data retrieval call binding the contract method 0x0717b161.
+//
+// Solidity: function dummy47() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCaller) Dummy47(opts *bind.CallOpts) (*big.Int, error) {
+ var out []interface{}
+ err := _StateBloatToken.contract.Call(opts, &out, "dummy47")
+
+ if err != nil {
+ return *new(*big.Int), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
+
+ return out0, err
+
+}
+
+// Dummy47 is a free data retrieval call binding the contract method 0x0717b161.
+//
+// Solidity: function dummy47() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenSession) Dummy47() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy47(&_StateBloatToken.CallOpts)
+}
+
+// Dummy47 is a free data retrieval call binding the contract method 0x0717b161.
+//
+// Solidity: function dummy47() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCallerSession) Dummy47() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy47(&_StateBloatToken.CallOpts)
+}
+
+// Dummy48 is a free data retrieval call binding the contract method 0x8619d607.
+//
+// Solidity: function dummy48() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCaller) Dummy48(opts *bind.CallOpts) (*big.Int, error) {
+ var out []interface{}
+ err := _StateBloatToken.contract.Call(opts, &out, "dummy48")
+
+ if err != nil {
+ return *new(*big.Int), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
+
+ return out0, err
+
+}
+
+// Dummy48 is a free data retrieval call binding the contract method 0x8619d607.
+//
+// Solidity: function dummy48() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenSession) Dummy48() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy48(&_StateBloatToken.CallOpts)
+}
+
+// Dummy48 is a free data retrieval call binding the contract method 0x8619d607.
+//
+// Solidity: function dummy48() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCallerSession) Dummy48() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy48(&_StateBloatToken.CallOpts)
+}
+
+// Dummy49 is a free data retrieval call binding the contract method 0xd101dcd0.
+//
+// Solidity: function dummy49() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCaller) Dummy49(opts *bind.CallOpts) (*big.Int, error) {
+ var out []interface{}
+ err := _StateBloatToken.contract.Call(opts, &out, "dummy49")
+
+ if err != nil {
+ return *new(*big.Int), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
+
+ return out0, err
+
+}
+
+// Dummy49 is a free data retrieval call binding the contract method 0xd101dcd0.
+//
+// Solidity: function dummy49() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenSession) Dummy49() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy49(&_StateBloatToken.CallOpts)
+}
+
+// Dummy49 is a free data retrieval call binding the contract method 0xd101dcd0.
+//
+// Solidity: function dummy49() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCallerSession) Dummy49() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy49(&_StateBloatToken.CallOpts)
+}
+
+// Dummy5 is a free data retrieval call binding the contract method 0x1215a3ab.
+//
+// Solidity: function dummy5() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCaller) Dummy5(opts *bind.CallOpts) (*big.Int, error) {
+ var out []interface{}
+ err := _StateBloatToken.contract.Call(opts, &out, "dummy5")
+
+ if err != nil {
+ return *new(*big.Int), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
+
+ return out0, err
+
+}
+
+// Dummy5 is a free data retrieval call binding the contract method 0x1215a3ab.
+//
+// Solidity: function dummy5() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenSession) Dummy5() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy5(&_StateBloatToken.CallOpts)
+}
+
+// Dummy5 is a free data retrieval call binding the contract method 0x1215a3ab.
+//
+// Solidity: function dummy5() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCallerSession) Dummy5() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy5(&_StateBloatToken.CallOpts)
+}
+
+// Dummy50 is a free data retrieval call binding the contract method 0x42937dbd.
+//
+// Solidity: function dummy50() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCaller) Dummy50(opts *bind.CallOpts) (*big.Int, error) {
+ var out []interface{}
+ err := _StateBloatToken.contract.Call(opts, &out, "dummy50")
+
+ if err != nil {
+ return *new(*big.Int), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
+
+ return out0, err
+
+}
+
+// Dummy50 is a free data retrieval call binding the contract method 0x42937dbd.
+//
+// Solidity: function dummy50() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenSession) Dummy50() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy50(&_StateBloatToken.CallOpts)
+}
+
+// Dummy50 is a free data retrieval call binding the contract method 0x42937dbd.
+//
+// Solidity: function dummy50() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCallerSession) Dummy50() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy50(&_StateBloatToken.CallOpts)
+}
+
+// Dummy51 is a free data retrieval call binding the contract method 0x16a3045b.
+//
+// Solidity: function dummy51() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCaller) Dummy51(opts *bind.CallOpts) (*big.Int, error) {
+ var out []interface{}
+ err := _StateBloatToken.contract.Call(opts, &out, "dummy51")
+
+ if err != nil {
+ return *new(*big.Int), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
+
+ return out0, err
+
+}
+
+// Dummy51 is a free data retrieval call binding the contract method 0x16a3045b.
+//
+// Solidity: function dummy51() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenSession) Dummy51() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy51(&_StateBloatToken.CallOpts)
+}
+
+// Dummy51 is a free data retrieval call binding the contract method 0x16a3045b.
+//
+// Solidity: function dummy51() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCallerSession) Dummy51() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy51(&_StateBloatToken.CallOpts)
+}
+
+// Dummy52 is a free data retrieval call binding the contract method 0x3125f37a.
+//
+// Solidity: function dummy52() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCaller) Dummy52(opts *bind.CallOpts) (*big.Int, error) {
+ var out []interface{}
+ err := _StateBloatToken.contract.Call(opts, &out, "dummy52")
+
+ if err != nil {
+ return *new(*big.Int), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
+
+ return out0, err
+
+}
+
+// Dummy52 is a free data retrieval call binding the contract method 0x3125f37a.
+//
+// Solidity: function dummy52() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenSession) Dummy52() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy52(&_StateBloatToken.CallOpts)
+}
+
+// Dummy52 is a free data retrieval call binding the contract method 0x3125f37a.
+//
+// Solidity: function dummy52() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCallerSession) Dummy52() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy52(&_StateBloatToken.CallOpts)
+}
+
+// Dummy53 is a free data retrieval call binding the contract method 0x1fd298ec.
+//
+// Solidity: function dummy53() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCaller) Dummy53(opts *bind.CallOpts) (*big.Int, error) {
+ var out []interface{}
+ err := _StateBloatToken.contract.Call(opts, &out, "dummy53")
+
+ if err != nil {
+ return *new(*big.Int), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
+
+ return out0, err
+
+}
+
+// Dummy53 is a free data retrieval call binding the contract method 0x1fd298ec.
+//
+// Solidity: function dummy53() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenSession) Dummy53() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy53(&_StateBloatToken.CallOpts)
+}
+
+// Dummy53 is a free data retrieval call binding the contract method 0x1fd298ec.
+//
+// Solidity: function dummy53() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCallerSession) Dummy53() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy53(&_StateBloatToken.CallOpts)
+}
+
+// Dummy54 is a free data retrieval call binding the contract method 0x792c7f3e.
+//
+// Solidity: function dummy54() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCaller) Dummy54(opts *bind.CallOpts) (*big.Int, error) {
+ var out []interface{}
+ err := _StateBloatToken.contract.Call(opts, &out, "dummy54")
+
+ if err != nil {
+ return *new(*big.Int), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
+
+ return out0, err
+
+}
+
+// Dummy54 is a free data retrieval call binding the contract method 0x792c7f3e.
+//
+// Solidity: function dummy54() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenSession) Dummy54() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy54(&_StateBloatToken.CallOpts)
+}
+
+// Dummy54 is a free data retrieval call binding the contract method 0x792c7f3e.
+//
+// Solidity: function dummy54() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCallerSession) Dummy54() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy54(&_StateBloatToken.CallOpts)
+}
+
+// Dummy55 is a free data retrieval call binding the contract method 0x7dffdc32.
+//
+// Solidity: function dummy55() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCaller) Dummy55(opts *bind.CallOpts) (*big.Int, error) {
+ var out []interface{}
+ err := _StateBloatToken.contract.Call(opts, &out, "dummy55")
+
+ if err != nil {
+ return *new(*big.Int), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
+
+ return out0, err
+
+}
+
+// Dummy55 is a free data retrieval call binding the contract method 0x7dffdc32.
+//
+// Solidity: function dummy55() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenSession) Dummy55() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy55(&_StateBloatToken.CallOpts)
+}
+
+// Dummy55 is a free data retrieval call binding the contract method 0x7dffdc32.
+//
+// Solidity: function dummy55() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCallerSession) Dummy55() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy55(&_StateBloatToken.CallOpts)
+}
+
+// Dummy56 is a free data retrieval call binding the contract method 0xa891d4d4.
+//
+// Solidity: function dummy56() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCaller) Dummy56(opts *bind.CallOpts) (*big.Int, error) {
+ var out []interface{}
+ err := _StateBloatToken.contract.Call(opts, &out, "dummy56")
+
+ if err != nil {
+ return *new(*big.Int), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
+
+ return out0, err
+
+}
+
+// Dummy56 is a free data retrieval call binding the contract method 0xa891d4d4.
+//
+// Solidity: function dummy56() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenSession) Dummy56() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy56(&_StateBloatToken.CallOpts)
+}
+
+// Dummy56 is a free data retrieval call binding the contract method 0xa891d4d4.
+//
+// Solidity: function dummy56() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCallerSession) Dummy56() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy56(&_StateBloatToken.CallOpts)
+}
+
+// Dummy57 is a free data retrieval call binding the contract method 0x74f83d02.
+//
+// Solidity: function dummy57() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCaller) Dummy57(opts *bind.CallOpts) (*big.Int, error) {
+ var out []interface{}
+ err := _StateBloatToken.contract.Call(opts, &out, "dummy57")
+
+ if err != nil {
+ return *new(*big.Int), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
+
+ return out0, err
+
+}
+
+// Dummy57 is a free data retrieval call binding the contract method 0x74f83d02.
+//
+// Solidity: function dummy57() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenSession) Dummy57() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy57(&_StateBloatToken.CallOpts)
+}
+
+// Dummy57 is a free data retrieval call binding the contract method 0x74f83d02.
+//
+// Solidity: function dummy57() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCallerSession) Dummy57() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy57(&_StateBloatToken.CallOpts)
+}
+
+// Dummy58 is a free data retrieval call binding the contract method 0x54c27920.
+//
+// Solidity: function dummy58() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCaller) Dummy58(opts *bind.CallOpts) (*big.Int, error) {
+ var out []interface{}
+ err := _StateBloatToken.contract.Call(opts, &out, "dummy58")
+
+ if err != nil {
+ return *new(*big.Int), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
+
+ return out0, err
+
+}
+
+// Dummy58 is a free data retrieval call binding the contract method 0x54c27920.
+//
+// Solidity: function dummy58() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenSession) Dummy58() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy58(&_StateBloatToken.CallOpts)
+}
+
+// Dummy58 is a free data retrieval call binding the contract method 0x54c27920.
+//
+// Solidity: function dummy58() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCallerSession) Dummy58() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy58(&_StateBloatToken.CallOpts)
+}
+
+// Dummy59 is a free data retrieval call binding the contract method 0x77c0209e.
+//
+// Solidity: function dummy59() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCaller) Dummy59(opts *bind.CallOpts) (*big.Int, error) {
+ var out []interface{}
+ err := _StateBloatToken.contract.Call(opts, &out, "dummy59")
+
+ if err != nil {
+ return *new(*big.Int), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
+
+ return out0, err
+
+}
+
+// Dummy59 is a free data retrieval call binding the contract method 0x77c0209e.
+//
+// Solidity: function dummy59() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenSession) Dummy59() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy59(&_StateBloatToken.CallOpts)
+}
+
+// Dummy59 is a free data retrieval call binding the contract method 0x77c0209e.
+//
+// Solidity: function dummy59() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCallerSession) Dummy59() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy59(&_StateBloatToken.CallOpts)
+}
+
+// Dummy6 is a free data retrieval call binding the contract method 0x4128a85d.
+//
+// Solidity: function dummy6() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCaller) Dummy6(opts *bind.CallOpts) (*big.Int, error) {
+ var out []interface{}
+ err := _StateBloatToken.contract.Call(opts, &out, "dummy6")
+
+ if err != nil {
+ return *new(*big.Int), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
+
+ return out0, err
+
+}
+
+// Dummy6 is a free data retrieval call binding the contract method 0x4128a85d.
+//
+// Solidity: function dummy6() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenSession) Dummy6() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy6(&_StateBloatToken.CallOpts)
+}
+
+// Dummy6 is a free data retrieval call binding the contract method 0x4128a85d.
+//
+// Solidity: function dummy6() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCallerSession) Dummy6() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy6(&_StateBloatToken.CallOpts)
+}
+
+// Dummy60 is a free data retrieval call binding the contract method 0x34517f0b.
+//
+// Solidity: function dummy60() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCaller) Dummy60(opts *bind.CallOpts) (*big.Int, error) {
+ var out []interface{}
+ err := _StateBloatToken.contract.Call(opts, &out, "dummy60")
+
+ if err != nil {
+ return *new(*big.Int), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
+
+ return out0, err
+
+}
+
+// Dummy60 is a free data retrieval call binding the contract method 0x34517f0b.
+//
+// Solidity: function dummy60() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenSession) Dummy60() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy60(&_StateBloatToken.CallOpts)
+}
+
+// Dummy60 is a free data retrieval call binding the contract method 0x34517f0b.
+//
+// Solidity: function dummy60() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCallerSession) Dummy60() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy60(&_StateBloatToken.CallOpts)
+}
+
+// Dummy61 is a free data retrieval call binding the contract method 0xe2d27530.
+//
+// Solidity: function dummy61() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCaller) Dummy61(opts *bind.CallOpts) (*big.Int, error) {
+ var out []interface{}
+ err := _StateBloatToken.contract.Call(opts, &out, "dummy61")
+
+ if err != nil {
+ return *new(*big.Int), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
+
+ return out0, err
+
+}
+
+// Dummy61 is a free data retrieval call binding the contract method 0xe2d27530.
+//
+// Solidity: function dummy61() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenSession) Dummy61() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy61(&_StateBloatToken.CallOpts)
+}
+
+// Dummy61 is a free data retrieval call binding the contract method 0xe2d27530.
+//
+// Solidity: function dummy61() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCallerSession) Dummy61() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy61(&_StateBloatToken.CallOpts)
+}
+
+// Dummy62 is a free data retrieval call binding the contract method 0xf5f57381.
+//
+// Solidity: function dummy62() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCaller) Dummy62(opts *bind.CallOpts) (*big.Int, error) {
+ var out []interface{}
+ err := _StateBloatToken.contract.Call(opts, &out, "dummy62")
+
+ if err != nil {
+ return *new(*big.Int), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
+
+ return out0, err
+
+}
+
+// Dummy62 is a free data retrieval call binding the contract method 0xf5f57381.
+//
+// Solidity: function dummy62() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenSession) Dummy62() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy62(&_StateBloatToken.CallOpts)
+}
+
+// Dummy62 is a free data retrieval call binding the contract method 0xf5f57381.
+//
+// Solidity: function dummy62() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCallerSession) Dummy62() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy62(&_StateBloatToken.CallOpts)
+}
+
+// Dummy63 is a free data retrieval call binding the contract method 0x7a319c18.
+//
+// Solidity: function dummy63() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCaller) Dummy63(opts *bind.CallOpts) (*big.Int, error) {
+ var out []interface{}
+ err := _StateBloatToken.contract.Call(opts, &out, "dummy63")
+
+ if err != nil {
+ return *new(*big.Int), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
+
+ return out0, err
+
+}
+
+// Dummy63 is a free data retrieval call binding the contract method 0x7a319c18.
+//
+// Solidity: function dummy63() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenSession) Dummy63() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy63(&_StateBloatToken.CallOpts)
+}
+
+// Dummy63 is a free data retrieval call binding the contract method 0x7a319c18.
+//
+// Solidity: function dummy63() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCallerSession) Dummy63() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy63(&_StateBloatToken.CallOpts)
+}
+
+// Dummy64 is a free data retrieval call binding the contract method 0xad8f4221.
+//
+// Solidity: function dummy64() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCaller) Dummy64(opts *bind.CallOpts) (*big.Int, error) {
+ var out []interface{}
+ err := _StateBloatToken.contract.Call(opts, &out, "dummy64")
+
+ if err != nil {
+ return *new(*big.Int), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
+
+ return out0, err
+
+}
+
+// Dummy64 is a free data retrieval call binding the contract method 0xad8f4221.
+//
+// Solidity: function dummy64() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenSession) Dummy64() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy64(&_StateBloatToken.CallOpts)
+}
+
+// Dummy64 is a free data retrieval call binding the contract method 0xad8f4221.
+//
+// Solidity: function dummy64() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCallerSession) Dummy64() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy64(&_StateBloatToken.CallOpts)
+}
+
+// Dummy65 is a free data retrieval call binding the contract method 0x1f449589.
+//
+// Solidity: function dummy65() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCaller) Dummy65(opts *bind.CallOpts) (*big.Int, error) {
+ var out []interface{}
+ err := _StateBloatToken.contract.Call(opts, &out, "dummy65")
+
+ if err != nil {
+ return *new(*big.Int), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
+
+ return out0, err
+
+}
+
+// Dummy65 is a free data retrieval call binding the contract method 0x1f449589.
+//
+// Solidity: function dummy65() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenSession) Dummy65() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy65(&_StateBloatToken.CallOpts)
+}
+
+// Dummy65 is a free data retrieval call binding the contract method 0x1f449589.
+//
+// Solidity: function dummy65() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCallerSession) Dummy65() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy65(&_StateBloatToken.CallOpts)
+}
+
+// Dummy66 is a free data retrieval call binding the contract method 0xd9bb3174.
+//
+// Solidity: function dummy66() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCaller) Dummy66(opts *bind.CallOpts) (*big.Int, error) {
+ var out []interface{}
+ err := _StateBloatToken.contract.Call(opts, &out, "dummy66")
+
+ if err != nil {
+ return *new(*big.Int), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
+
+ return out0, err
+
+}
+
+// Dummy66 is a free data retrieval call binding the contract method 0xd9bb3174.
+//
+// Solidity: function dummy66() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenSession) Dummy66() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy66(&_StateBloatToken.CallOpts)
+}
+
+// Dummy66 is a free data retrieval call binding the contract method 0xd9bb3174.
+//
+// Solidity: function dummy66() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCallerSession) Dummy66() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy66(&_StateBloatToken.CallOpts)
+}
+
+// Dummy67 is a free data retrieval call binding the contract method 0x6578534c.
+//
+// Solidity: function dummy67() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCaller) Dummy67(opts *bind.CallOpts) (*big.Int, error) {
+ var out []interface{}
+ err := _StateBloatToken.contract.Call(opts, &out, "dummy67")
+
+ if err != nil {
+ return *new(*big.Int), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
+
+ return out0, err
+
+}
+
+// Dummy67 is a free data retrieval call binding the contract method 0x6578534c.
+//
+// Solidity: function dummy67() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenSession) Dummy67() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy67(&_StateBloatToken.CallOpts)
+}
+
+// Dummy67 is a free data retrieval call binding the contract method 0x6578534c.
+//
+// Solidity: function dummy67() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCallerSession) Dummy67() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy67(&_StateBloatToken.CallOpts)
+}
+
+// Dummy68 is a free data retrieval call binding the contract method 0xb9a6d645.
+//
+// Solidity: function dummy68() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCaller) Dummy68(opts *bind.CallOpts) (*big.Int, error) {
+ var out []interface{}
+ err := _StateBloatToken.contract.Call(opts, &out, "dummy68")
+
+ if err != nil {
+ return *new(*big.Int), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
+
+ return out0, err
+
+}
+
+// Dummy68 is a free data retrieval call binding the contract method 0xb9a6d645.
+//
+// Solidity: function dummy68() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenSession) Dummy68() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy68(&_StateBloatToken.CallOpts)
+}
+
+// Dummy68 is a free data retrieval call binding the contract method 0xb9a6d645.
+//
+// Solidity: function dummy68() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCallerSession) Dummy68() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy68(&_StateBloatToken.CallOpts)
+}
+
+// Dummy69 is a free data retrieval call binding the contract method 0x2787325b.
+//
+// Solidity: function dummy69() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCaller) Dummy69(opts *bind.CallOpts) (*big.Int, error) {
+ var out []interface{}
+ err := _StateBloatToken.contract.Call(opts, &out, "dummy69")
+
+ if err != nil {
+ return *new(*big.Int), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
+
+ return out0, err
+
+}
+
+// Dummy69 is a free data retrieval call binding the contract method 0x2787325b.
+//
+// Solidity: function dummy69() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenSession) Dummy69() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy69(&_StateBloatToken.CallOpts)
+}
+
+// Dummy69 is a free data retrieval call binding the contract method 0x2787325b.
+//
+// Solidity: function dummy69() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCallerSession) Dummy69() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy69(&_StateBloatToken.CallOpts)
+}
+
+// Dummy7 is a free data retrieval call binding the contract method 0xf26c779b.
+//
+// Solidity: function dummy7() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCaller) Dummy7(opts *bind.CallOpts) (*big.Int, error) {
+ var out []interface{}
+ err := _StateBloatToken.contract.Call(opts, &out, "dummy7")
+
+ if err != nil {
+ return *new(*big.Int), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
+
+ return out0, err
+
+}
+
+// Dummy7 is a free data retrieval call binding the contract method 0xf26c779b.
+//
+// Solidity: function dummy7() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenSession) Dummy7() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy7(&_StateBloatToken.CallOpts)
+}
+
+// Dummy7 is a free data retrieval call binding the contract method 0xf26c779b.
+//
+// Solidity: function dummy7() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCallerSession) Dummy7() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy7(&_StateBloatToken.CallOpts)
+}
+
+// Dummy8 is a free data retrieval call binding the contract method 0x19cf6a91.
+//
+// Solidity: function dummy8() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCaller) Dummy8(opts *bind.CallOpts) (*big.Int, error) {
+ var out []interface{}
+ err := _StateBloatToken.contract.Call(opts, &out, "dummy8")
+
+ if err != nil {
+ return *new(*big.Int), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
+
+ return out0, err
+
+}
+
+// Dummy8 is a free data retrieval call binding the contract method 0x19cf6a91.
+//
+// Solidity: function dummy8() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenSession) Dummy8() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy8(&_StateBloatToken.CallOpts)
+}
+
+// Dummy8 is a free data retrieval call binding the contract method 0x19cf6a91.
+//
+// Solidity: function dummy8() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCallerSession) Dummy8() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy8(&_StateBloatToken.CallOpts)
+}
+
+// Dummy9 is a free data retrieval call binding the contract method 0x58b6a9bd.
+//
+// Solidity: function dummy9() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCaller) Dummy9(opts *bind.CallOpts) (*big.Int, error) {
+ var out []interface{}
+ err := _StateBloatToken.contract.Call(opts, &out, "dummy9")
+
+ if err != nil {
+ return *new(*big.Int), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
+
+ return out0, err
+
+}
+
+// Dummy9 is a free data retrieval call binding the contract method 0x58b6a9bd.
+//
+// Solidity: function dummy9() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenSession) Dummy9() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy9(&_StateBloatToken.CallOpts)
+}
+
+// Dummy9 is a free data retrieval call binding the contract method 0x58b6a9bd.
+//
+// Solidity: function dummy9() pure returns(uint256)
+func (_StateBloatToken *StateBloatTokenCallerSession) Dummy9() (*big.Int, error) {
+ return _StateBloatToken.Contract.Dummy9(&_StateBloatToken.CallOpts)
+}
+
+// Name is a free data retrieval call binding the contract method 0x06fdde03.
+//
+// Solidity: function name() view returns(string)
+func (_StateBloatToken *StateBloatTokenCaller) Name(opts *bind.CallOpts) (string, error) {
+ var out []interface{}
+ err := _StateBloatToken.contract.Call(opts, &out, "name")
+
+ if err != nil {
+ return *new(string), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(string)).(*string)
+
+ return out0, err
+
+}
+
+// Name is a free data retrieval call binding the contract method 0x06fdde03.
+//
+// Solidity: function name() view returns(string)
+func (_StateBloatToken *StateBloatTokenSession) Name() (string, error) {
+ return _StateBloatToken.Contract.Name(&_StateBloatToken.CallOpts)
+}
+
+// Name is a free data retrieval call binding the contract method 0x06fdde03.
+//
+// Solidity: function name() view returns(string)
+func (_StateBloatToken *StateBloatTokenCallerSession) Name() (string, error) {
+ return _StateBloatToken.Contract.Name(&_StateBloatToken.CallOpts)
+}
+
+// Salt is a free data retrieval call binding the contract method 0xbfa0b133.
+//
+// Solidity: function salt() view returns(uint256)
+func (_StateBloatToken *StateBloatTokenCaller) Salt(opts *bind.CallOpts) (*big.Int, error) {
+ var out []interface{}
+ err := _StateBloatToken.contract.Call(opts, &out, "salt")
+
+ if err != nil {
+ return *new(*big.Int), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
+
+ return out0, err
+
+}
+
+// Salt is a free data retrieval call binding the contract method 0xbfa0b133.
+//
+// Solidity: function salt() view returns(uint256)
+func (_StateBloatToken *StateBloatTokenSession) Salt() (*big.Int, error) {
+ return _StateBloatToken.Contract.Salt(&_StateBloatToken.CallOpts)
+}
+
+// Salt is a free data retrieval call binding the contract method 0xbfa0b133.
+//
+// Solidity: function salt() view returns(uint256)
+func (_StateBloatToken *StateBloatTokenCallerSession) Salt() (*big.Int, error) {
+ return _StateBloatToken.Contract.Salt(&_StateBloatToken.CallOpts)
+}
+
+// Symbol is a free data retrieval call binding the contract method 0x95d89b41.
+//
+// Solidity: function symbol() view returns(string)
+func (_StateBloatToken *StateBloatTokenCaller) Symbol(opts *bind.CallOpts) (string, error) {
+ var out []interface{}
+ err := _StateBloatToken.contract.Call(opts, &out, "symbol")
+
+ if err != nil {
+ return *new(string), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(string)).(*string)
+
+ return out0, err
+
+}
+
+// Symbol is a free data retrieval call binding the contract method 0x95d89b41.
+//
+// Solidity: function symbol() view returns(string)
+func (_StateBloatToken *StateBloatTokenSession) Symbol() (string, error) {
+ return _StateBloatToken.Contract.Symbol(&_StateBloatToken.CallOpts)
+}
+
+// Symbol is a free data retrieval call binding the contract method 0x95d89b41.
+//
+// Solidity: function symbol() view returns(string)
+func (_StateBloatToken *StateBloatTokenCallerSession) Symbol() (string, error) {
+ return _StateBloatToken.Contract.Symbol(&_StateBloatToken.CallOpts)
+}
+
+// TotalSupply is a free data retrieval call binding the contract method 0x18160ddd.
+//
+// Solidity: function totalSupply() view returns(uint256)
+func (_StateBloatToken *StateBloatTokenCaller) TotalSupply(opts *bind.CallOpts) (*big.Int, error) {
+ var out []interface{}
+ err := _StateBloatToken.contract.Call(opts, &out, "totalSupply")
+
+ if err != nil {
+ return *new(*big.Int), err
+ }
+
+ out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int)
+
+ return out0, err
+
+}
+
+// TotalSupply is a free data retrieval call binding the contract method 0x18160ddd.
+//
+// Solidity: function totalSupply() view returns(uint256)
+func (_StateBloatToken *StateBloatTokenSession) TotalSupply() (*big.Int, error) {
+ return _StateBloatToken.Contract.TotalSupply(&_StateBloatToken.CallOpts)
+}
+
+// TotalSupply is a free data retrieval call binding the contract method 0x18160ddd.
+//
+// Solidity: function totalSupply() view returns(uint256)
+func (_StateBloatToken *StateBloatTokenCallerSession) TotalSupply() (*big.Int, error) {
+ return _StateBloatToken.Contract.TotalSupply(&_StateBloatToken.CallOpts)
+}
+
+// Approve is a paid mutator transaction binding the contract method 0x095ea7b3.
+//
+// Solidity: function approve(address spender, uint256 value) returns(bool)
+func (_StateBloatToken *StateBloatTokenTransactor) Approve(opts *bind.TransactOpts, spender common.Address, value *big.Int) (*types.Transaction, error) {
+ return _StateBloatToken.contract.Transact(opts, "approve", spender, value)
+}
+
+// Approve is a paid mutator transaction binding the contract method 0x095ea7b3.
+//
+// Solidity: function approve(address spender, uint256 value) returns(bool)
+func (_StateBloatToken *StateBloatTokenSession) Approve(spender common.Address, value *big.Int) (*types.Transaction, error) {
+ return _StateBloatToken.Contract.Approve(&_StateBloatToken.TransactOpts, spender, value)
+}
+
+// Approve is a paid mutator transaction binding the contract method 0x095ea7b3.
+//
+// Solidity: function approve(address spender, uint256 value) returns(bool)
+func (_StateBloatToken *StateBloatTokenTransactorSession) Approve(spender common.Address, value *big.Int) (*types.Transaction, error) {
+ return _StateBloatToken.Contract.Approve(&_StateBloatToken.TransactOpts, spender, value)
+}
+
+// Transfer is a paid mutator transaction binding the contract method 0xa9059cbb.
+//
+// Solidity: function transfer(address to, uint256 value) returns(bool)
+func (_StateBloatToken *StateBloatTokenTransactor) Transfer(opts *bind.TransactOpts, to common.Address, value *big.Int) (*types.Transaction, error) {
+ return _StateBloatToken.contract.Transact(opts, "transfer", to, value)
+}
+
+// Transfer is a paid mutator transaction binding the contract method 0xa9059cbb.
+//
+// Solidity: function transfer(address to, uint256 value) returns(bool)
+func (_StateBloatToken *StateBloatTokenSession) Transfer(to common.Address, value *big.Int) (*types.Transaction, error) {
+ return _StateBloatToken.Contract.Transfer(&_StateBloatToken.TransactOpts, to, value)
+}
+
+// Transfer is a paid mutator transaction binding the contract method 0xa9059cbb.
+//
+// Solidity: function transfer(address to, uint256 value) returns(bool)
+func (_StateBloatToken *StateBloatTokenTransactorSession) Transfer(to common.Address, value *big.Int) (*types.Transaction, error) {
+ return _StateBloatToken.Contract.Transfer(&_StateBloatToken.TransactOpts, to, value)
+}
+
+// TransferFrom is a paid mutator transaction binding the contract method 0x23b872dd.
+//
+// Solidity: function transferFrom(address from, address to, uint256 value) returns(bool)
+func (_StateBloatToken *StateBloatTokenTransactor) TransferFrom(opts *bind.TransactOpts, from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) {
+ return _StateBloatToken.contract.Transact(opts, "transferFrom", from, to, value)
+}
+
+// TransferFrom is a paid mutator transaction binding the contract method 0x23b872dd.
+//
+// Solidity: function transferFrom(address from, address to, uint256 value) returns(bool)
+func (_StateBloatToken *StateBloatTokenSession) TransferFrom(from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) {
+ return _StateBloatToken.Contract.TransferFrom(&_StateBloatToken.TransactOpts, from, to, value)
+}
+
+// TransferFrom is a paid mutator transaction binding the contract method 0x23b872dd.
+//
+// Solidity: function transferFrom(address from, address to, uint256 value) returns(bool)
+func (_StateBloatToken *StateBloatTokenTransactorSession) TransferFrom(from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) {
+ return _StateBloatToken.Contract.TransferFrom(&_StateBloatToken.TransactOpts, from, to, value)
+}
+
+// TransferFrom1 is a paid mutator transaction binding the contract method 0xbb9bfe06.
+//
+// Solidity: function transferFrom1(address from, address to, uint256 value) returns(bool)
+func (_StateBloatToken *StateBloatTokenTransactor) TransferFrom1(opts *bind.TransactOpts, from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) {
+ return _StateBloatToken.contract.Transact(opts, "transferFrom1", from, to, value)
+}
+
+// TransferFrom1 is a paid mutator transaction binding the contract method 0xbb9bfe06.
+//
+// Solidity: function transferFrom1(address from, address to, uint256 value) returns(bool)
+func (_StateBloatToken *StateBloatTokenSession) TransferFrom1(from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) {
+ return _StateBloatToken.Contract.TransferFrom1(&_StateBloatToken.TransactOpts, from, to, value)
+}
+
+// TransferFrom1 is a paid mutator transaction binding the contract method 0xbb9bfe06.
+//
+// Solidity: function transferFrom1(address from, address to, uint256 value) returns(bool)
+func (_StateBloatToken *StateBloatTokenTransactorSession) TransferFrom1(from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) {
+ return _StateBloatToken.Contract.TransferFrom1(&_StateBloatToken.TransactOpts, from, to, value)
+}
+
+// TransferFrom10 is a paid mutator transaction binding the contract method 0xb1802b9a.
+//
+// Solidity: function transferFrom10(address from, address to, uint256 value) returns(bool)
+func (_StateBloatToken *StateBloatTokenTransactor) TransferFrom10(opts *bind.TransactOpts, from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) {
+ return _StateBloatToken.contract.Transact(opts, "transferFrom10", from, to, value)
+}
+
+// TransferFrom10 is a paid mutator transaction binding the contract method 0xb1802b9a.
+//
+// Solidity: function transferFrom10(address from, address to, uint256 value) returns(bool)
+func (_StateBloatToken *StateBloatTokenSession) TransferFrom10(from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) {
+ return _StateBloatToken.Contract.TransferFrom10(&_StateBloatToken.TransactOpts, from, to, value)
+}
+
+// TransferFrom10 is a paid mutator transaction binding the contract method 0xb1802b9a.
+//
+// Solidity: function transferFrom10(address from, address to, uint256 value) returns(bool)
+func (_StateBloatToken *StateBloatTokenTransactorSession) TransferFrom10(from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) {
+ return _StateBloatToken.Contract.TransferFrom10(&_StateBloatToken.TransactOpts, from, to, value)
+}
+
+// TransferFrom11 is a paid mutator transaction binding the contract method 0xc2be97e3.
+//
+// Solidity: function transferFrom11(address from, address to, uint256 value) returns(bool)
+func (_StateBloatToken *StateBloatTokenTransactor) TransferFrom11(opts *bind.TransactOpts, from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) {
+ return _StateBloatToken.contract.Transact(opts, "transferFrom11", from, to, value)
+}
+
+// TransferFrom11 is a paid mutator transaction binding the contract method 0xc2be97e3.
+//
+// Solidity: function transferFrom11(address from, address to, uint256 value) returns(bool)
+func (_StateBloatToken *StateBloatTokenSession) TransferFrom11(from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) {
+ return _StateBloatToken.Contract.TransferFrom11(&_StateBloatToken.TransactOpts, from, to, value)
+}
+
+// TransferFrom11 is a paid mutator transaction binding the contract method 0xc2be97e3.
+//
+// Solidity: function transferFrom11(address from, address to, uint256 value) returns(bool)
+func (_StateBloatToken *StateBloatTokenTransactorSession) TransferFrom11(from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) {
+ return _StateBloatToken.Contract.TransferFrom11(&_StateBloatToken.TransactOpts, from, to, value)
+}
+
+// TransferFrom12 is a paid mutator transaction binding the contract method 0x44050a28.
+//
+// Solidity: function transferFrom12(address from, address to, uint256 value) returns(bool)
+func (_StateBloatToken *StateBloatTokenTransactor) TransferFrom12(opts *bind.TransactOpts, from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) {
+ return _StateBloatToken.contract.Transact(opts, "transferFrom12", from, to, value)
+}
+
+// TransferFrom12 is a paid mutator transaction binding the contract method 0x44050a28.
+//
+// Solidity: function transferFrom12(address from, address to, uint256 value) returns(bool)
+func (_StateBloatToken *StateBloatTokenSession) TransferFrom12(from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) {
+ return _StateBloatToken.Contract.TransferFrom12(&_StateBloatToken.TransactOpts, from, to, value)
+}
+
+// TransferFrom12 is a paid mutator transaction binding the contract method 0x44050a28.
+//
+// Solidity: function transferFrom12(address from, address to, uint256 value) returns(bool)
+func (_StateBloatToken *StateBloatTokenTransactorSession) TransferFrom12(from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) {
+ return _StateBloatToken.Contract.TransferFrom12(&_StateBloatToken.TransactOpts, from, to, value)
+}
+
+// TransferFrom13 is a paid mutator transaction binding the contract method 0xacc5aee9.
+//
+// Solidity: function transferFrom13(address from, address to, uint256 value) returns(bool)
+func (_StateBloatToken *StateBloatTokenTransactor) TransferFrom13(opts *bind.TransactOpts, from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) {
+ return _StateBloatToken.contract.Transact(opts, "transferFrom13", from, to, value)
+}
+
+// TransferFrom13 is a paid mutator transaction binding the contract method 0xacc5aee9.
+//
+// Solidity: function transferFrom13(address from, address to, uint256 value) returns(bool)
+func (_StateBloatToken *StateBloatTokenSession) TransferFrom13(from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) {
+ return _StateBloatToken.Contract.TransferFrom13(&_StateBloatToken.TransactOpts, from, to, value)
+}
+
+// TransferFrom13 is a paid mutator transaction binding the contract method 0xacc5aee9.
+//
+// Solidity: function transferFrom13(address from, address to, uint256 value) returns(bool)
+func (_StateBloatToken *StateBloatTokenTransactorSession) TransferFrom13(from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) {
+ return _StateBloatToken.Contract.TransferFrom13(&_StateBloatToken.TransactOpts, from, to, value)
+}
+
+// TransferFrom14 is a paid mutator transaction binding the contract method 0x1bbffe6f.
+//
+// Solidity: function transferFrom14(address from, address to, uint256 value) returns(bool)
+func (_StateBloatToken *StateBloatTokenTransactor) TransferFrom14(opts *bind.TransactOpts, from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) {
+ return _StateBloatToken.contract.Transact(opts, "transferFrom14", from, to, value)
+}
+
+// TransferFrom14 is a paid mutator transaction binding the contract method 0x1bbffe6f.
+//
+// Solidity: function transferFrom14(address from, address to, uint256 value) returns(bool)
+func (_StateBloatToken *StateBloatTokenSession) TransferFrom14(from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) {
+ return _StateBloatToken.Contract.TransferFrom14(&_StateBloatToken.TransactOpts, from, to, value)
+}
+
+// TransferFrom14 is a paid mutator transaction binding the contract method 0x1bbffe6f.
+//
+// Solidity: function transferFrom14(address from, address to, uint256 value) returns(bool)
+func (_StateBloatToken *StateBloatTokenTransactorSession) TransferFrom14(from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) {
+ return _StateBloatToken.Contract.TransferFrom14(&_StateBloatToken.TransactOpts, from, to, value)
+}
+
+// TransferFrom15 is a paid mutator transaction binding the contract method 0x8789ca67.
+//
+// Solidity: function transferFrom15(address from, address to, uint256 value) returns(bool)
+func (_StateBloatToken *StateBloatTokenTransactor) TransferFrom15(opts *bind.TransactOpts, from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) {
+ return _StateBloatToken.contract.Transact(opts, "transferFrom15", from, to, value)
+}
+
+// TransferFrom15 is a paid mutator transaction binding the contract method 0x8789ca67.
+//
+// Solidity: function transferFrom15(address from, address to, uint256 value) returns(bool)
+func (_StateBloatToken *StateBloatTokenSession) TransferFrom15(from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) {
+ return _StateBloatToken.Contract.TransferFrom15(&_StateBloatToken.TransactOpts, from, to, value)
+}
+
+// TransferFrom15 is a paid mutator transaction binding the contract method 0x8789ca67.
+//
+// Solidity: function transferFrom15(address from, address to, uint256 value) returns(bool)
+func (_StateBloatToken *StateBloatTokenTransactorSession) TransferFrom15(from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) {
+ return _StateBloatToken.Contract.TransferFrom15(&_StateBloatToken.TransactOpts, from, to, value)
+}
+
+// TransferFrom16 is a paid mutator transaction binding the contract method 0x39e0bd12.
+//
+// Solidity: function transferFrom16(address from, address to, uint256 value) returns(bool)
+func (_StateBloatToken *StateBloatTokenTransactor) TransferFrom16(opts *bind.TransactOpts, from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) {
+ return _StateBloatToken.contract.Transact(opts, "transferFrom16", from, to, value)
+}
+
+// TransferFrom16 is a paid mutator transaction binding the contract method 0x39e0bd12.
+//
+// Solidity: function transferFrom16(address from, address to, uint256 value) returns(bool)
+func (_StateBloatToken *StateBloatTokenSession) TransferFrom16(from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) {
+ return _StateBloatToken.Contract.TransferFrom16(&_StateBloatToken.TransactOpts, from, to, value)
+}
+
+// TransferFrom16 is a paid mutator transaction binding the contract method 0x39e0bd12.
+//
+// Solidity: function transferFrom16(address from, address to, uint256 value) returns(bool)
+func (_StateBloatToken *StateBloatTokenTransactorSession) TransferFrom16(from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) {
+ return _StateBloatToken.Contract.TransferFrom16(&_StateBloatToken.TransactOpts, from, to, value)
+}
+
+// TransferFrom17 is a paid mutator transaction binding the contract method 0x291c3bd7.
+//
+// Solidity: function transferFrom17(address from, address to, uint256 value) returns(bool)
+func (_StateBloatToken *StateBloatTokenTransactor) TransferFrom17(opts *bind.TransactOpts, from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) {
+ return _StateBloatToken.contract.Transact(opts, "transferFrom17", from, to, value)
+}
+
+// TransferFrom17 is a paid mutator transaction binding the contract method 0x291c3bd7.
+//
+// Solidity: function transferFrom17(address from, address to, uint256 value) returns(bool)
+func (_StateBloatToken *StateBloatTokenSession) TransferFrom17(from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) {
+ return _StateBloatToken.Contract.TransferFrom17(&_StateBloatToken.TransactOpts, from, to, value)
+}
+
+// TransferFrom17 is a paid mutator transaction binding the contract method 0x291c3bd7.
+//
+// Solidity: function transferFrom17(address from, address to, uint256 value) returns(bool)
+func (_StateBloatToken *StateBloatTokenTransactorSession) TransferFrom17(from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) {
+ return _StateBloatToken.Contract.TransferFrom17(&_StateBloatToken.TransactOpts, from, to, value)
+}
+
+// TransferFrom18 is a paid mutator transaction binding the contract method 0x657b6ef7.
+//
+// Solidity: function transferFrom18(address from, address to, uint256 value) returns(bool)
+func (_StateBloatToken *StateBloatTokenTransactor) TransferFrom18(opts *bind.TransactOpts, from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) {
+ return _StateBloatToken.contract.Transact(opts, "transferFrom18", from, to, value)
+}
+
+// TransferFrom18 is a paid mutator transaction binding the contract method 0x657b6ef7.
+//
+// Solidity: function transferFrom18(address from, address to, uint256 value) returns(bool)
+func (_StateBloatToken *StateBloatTokenSession) TransferFrom18(from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) {
+ return _StateBloatToken.Contract.TransferFrom18(&_StateBloatToken.TransactOpts, from, to, value)
+}
+
+// TransferFrom18 is a paid mutator transaction binding the contract method 0x657b6ef7.
+//
+// Solidity: function transferFrom18(address from, address to, uint256 value) returns(bool)
+func (_StateBloatToken *StateBloatTokenTransactorSession) TransferFrom18(from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) {
+ return _StateBloatToken.Contract.TransferFrom18(&_StateBloatToken.TransactOpts, from, to, value)
+}
+
+// TransferFrom19 is a paid mutator transaction binding the contract method 0xeb4329c8.
+//
+// Solidity: function transferFrom19(address from, address to, uint256 value) returns(bool)
+func (_StateBloatToken *StateBloatTokenTransactor) TransferFrom19(opts *bind.TransactOpts, from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) {
+ return _StateBloatToken.contract.Transact(opts, "transferFrom19", from, to, value)
+}
+
+// TransferFrom19 is a paid mutator transaction binding the contract method 0xeb4329c8.
+//
+// Solidity: function transferFrom19(address from, address to, uint256 value) returns(bool)
+func (_StateBloatToken *StateBloatTokenSession) TransferFrom19(from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) {
+ return _StateBloatToken.Contract.TransferFrom19(&_StateBloatToken.TransactOpts, from, to, value)
+}
+
+// TransferFrom19 is a paid mutator transaction binding the contract method 0xeb4329c8.
+//
+// Solidity: function transferFrom19(address from, address to, uint256 value) returns(bool)
+func (_StateBloatToken *StateBloatTokenTransactorSession) TransferFrom19(from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) {
+ return _StateBloatToken.Contract.TransferFrom19(&_StateBloatToken.TransactOpts, from, to, value)
+}
+
+// TransferFrom2 is a paid mutator transaction binding the contract method 0x6c12ed28.
+//
+// Solidity: function transferFrom2(address from, address to, uint256 value) returns(bool)
+func (_StateBloatToken *StateBloatTokenTransactor) TransferFrom2(opts *bind.TransactOpts, from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) {
+ return _StateBloatToken.contract.Transact(opts, "transferFrom2", from, to, value)
+}
+
+// TransferFrom2 is a paid mutator transaction binding the contract method 0x6c12ed28.
+//
+// Solidity: function transferFrom2(address from, address to, uint256 value) returns(bool)
+func (_StateBloatToken *StateBloatTokenSession) TransferFrom2(from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) {
+ return _StateBloatToken.Contract.TransferFrom2(&_StateBloatToken.TransactOpts, from, to, value)
+}
+
+// TransferFrom2 is a paid mutator transaction binding the contract method 0x6c12ed28.
+//
+// Solidity: function transferFrom2(address from, address to, uint256 value) returns(bool)
+func (_StateBloatToken *StateBloatTokenTransactorSession) TransferFrom2(from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) {
+ return _StateBloatToken.Contract.TransferFrom2(&_StateBloatToken.TransactOpts, from, to, value)
+}
+
+// TransferFrom3 is a paid mutator transaction binding the contract method 0x1b17c65c.
+//
+// Solidity: function transferFrom3(address from, address to, uint256 value) returns(bool)
+func (_StateBloatToken *StateBloatTokenTransactor) TransferFrom3(opts *bind.TransactOpts, from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) {
+ return _StateBloatToken.contract.Transact(opts, "transferFrom3", from, to, value)
+}
+
+// TransferFrom3 is a paid mutator transaction binding the contract method 0x1b17c65c.
+//
+// Solidity: function transferFrom3(address from, address to, uint256 value) returns(bool)
+func (_StateBloatToken *StateBloatTokenSession) TransferFrom3(from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) {
+ return _StateBloatToken.Contract.TransferFrom3(&_StateBloatToken.TransactOpts, from, to, value)
+}
+
+// TransferFrom3 is a paid mutator transaction binding the contract method 0x1b17c65c.
+//
+// Solidity: function transferFrom3(address from, address to, uint256 value) returns(bool)
+func (_StateBloatToken *StateBloatTokenTransactorSession) TransferFrom3(from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) {
+ return _StateBloatToken.Contract.TransferFrom3(&_StateBloatToken.TransactOpts, from, to, value)
+}
+
+// TransferFrom4 is a paid mutator transaction binding the contract method 0x3a131990.
+//
+// Solidity: function transferFrom4(address from, address to, uint256 value) returns(bool)
+func (_StateBloatToken *StateBloatTokenTransactor) TransferFrom4(opts *bind.TransactOpts, from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) {
+ return _StateBloatToken.contract.Transact(opts, "transferFrom4", from, to, value)
+}
+
+// TransferFrom4 is a paid mutator transaction binding the contract method 0x3a131990.
+//
+// Solidity: function transferFrom4(address from, address to, uint256 value) returns(bool)
+func (_StateBloatToken *StateBloatTokenSession) TransferFrom4(from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) {
+ return _StateBloatToken.Contract.TransferFrom4(&_StateBloatToken.TransactOpts, from, to, value)
+}
+
+// TransferFrom4 is a paid mutator transaction binding the contract method 0x3a131990.
+//
+// Solidity: function transferFrom4(address from, address to, uint256 value) returns(bool)
+func (_StateBloatToken *StateBloatTokenTransactorSession) TransferFrom4(from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) {
+ return _StateBloatToken.Contract.TransferFrom4(&_StateBloatToken.TransactOpts, from, to, value)
+}
+
+// TransferFrom5 is a paid mutator transaction binding the contract method 0x0460faf6.
+//
+// Solidity: function transferFrom5(address from, address to, uint256 value) returns(bool)
+func (_StateBloatToken *StateBloatTokenTransactor) TransferFrom5(opts *bind.TransactOpts, from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) {
+ return _StateBloatToken.contract.Transact(opts, "transferFrom5", from, to, value)
+}
+
+// TransferFrom5 is a paid mutator transaction binding the contract method 0x0460faf6.
+//
+// Solidity: function transferFrom5(address from, address to, uint256 value) returns(bool)
+func (_StateBloatToken *StateBloatTokenSession) TransferFrom5(from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) {
+ return _StateBloatToken.Contract.TransferFrom5(&_StateBloatToken.TransactOpts, from, to, value)
+}
+
+// TransferFrom5 is a paid mutator transaction binding the contract method 0x0460faf6.
+//
+// Solidity: function transferFrom5(address from, address to, uint256 value) returns(bool)
+func (_StateBloatToken *StateBloatTokenTransactorSession) TransferFrom5(from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) {
+ return _StateBloatToken.Contract.TransferFrom5(&_StateBloatToken.TransactOpts, from, to, value)
+}
+
+// TransferFrom6 is a paid mutator transaction binding the contract method 0x7c66673e.
+//
+// Solidity: function transferFrom6(address from, address to, uint256 value) returns(bool)
+func (_StateBloatToken *StateBloatTokenTransactor) TransferFrom6(opts *bind.TransactOpts, from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) {
+ return _StateBloatToken.contract.Transact(opts, "transferFrom6", from, to, value)
+}
+
+// TransferFrom6 is a paid mutator transaction binding the contract method 0x7c66673e.
+//
+// Solidity: function transferFrom6(address from, address to, uint256 value) returns(bool)
+func (_StateBloatToken *StateBloatTokenSession) TransferFrom6(from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) {
+ return _StateBloatToken.Contract.TransferFrom6(&_StateBloatToken.TransactOpts, from, to, value)
+}
+
+// TransferFrom6 is a paid mutator transaction binding the contract method 0x7c66673e.
+//
+// Solidity: function transferFrom6(address from, address to, uint256 value) returns(bool)
+func (_StateBloatToken *StateBloatTokenTransactorSession) TransferFrom6(from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) {
+ return _StateBloatToken.Contract.TransferFrom6(&_StateBloatToken.TransactOpts, from, to, value)
+}
+
+// TransferFrom7 is a paid mutator transaction binding the contract method 0xfaf35ced.
+//
+// Solidity: function transferFrom7(address from, address to, uint256 value) returns(bool)
+func (_StateBloatToken *StateBloatTokenTransactor) TransferFrom7(opts *bind.TransactOpts, from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) {
+ return _StateBloatToken.contract.Transact(opts, "transferFrom7", from, to, value)
+}
+
+// TransferFrom7 is a paid mutator transaction binding the contract method 0xfaf35ced.
+//
+// Solidity: function transferFrom7(address from, address to, uint256 value) returns(bool)
+func (_StateBloatToken *StateBloatTokenSession) TransferFrom7(from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) {
+ return _StateBloatToken.Contract.TransferFrom7(&_StateBloatToken.TransactOpts, from, to, value)
+}
+
+// TransferFrom7 is a paid mutator transaction binding the contract method 0xfaf35ced.
+//
+// Solidity: function transferFrom7(address from, address to, uint256 value) returns(bool)
+func (_StateBloatToken *StateBloatTokenTransactorSession) TransferFrom7(from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) {
+ return _StateBloatToken.Contract.TransferFrom7(&_StateBloatToken.TransactOpts, from, to, value)
+}
+
+// TransferFrom8 is a paid mutator transaction binding the contract method 0x552a1b56.
+//
+// Solidity: function transferFrom8(address from, address to, uint256 value) returns(bool)
+func (_StateBloatToken *StateBloatTokenTransactor) TransferFrom8(opts *bind.TransactOpts, from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) {
+ return _StateBloatToken.contract.Transact(opts, "transferFrom8", from, to, value)
+}
+
+// TransferFrom8 is a paid mutator transaction binding the contract method 0x552a1b56.
+//
+// Solidity: function transferFrom8(address from, address to, uint256 value) returns(bool)
+func (_StateBloatToken *StateBloatTokenSession) TransferFrom8(from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) {
+ return _StateBloatToken.Contract.TransferFrom8(&_StateBloatToken.TransactOpts, from, to, value)
+}
+
+// TransferFrom8 is a paid mutator transaction binding the contract method 0x552a1b56.
+//
+// Solidity: function transferFrom8(address from, address to, uint256 value) returns(bool)
+func (_StateBloatToken *StateBloatTokenTransactorSession) TransferFrom8(from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) {
+ return _StateBloatToken.Contract.TransferFrom8(&_StateBloatToken.TransactOpts, from, to, value)
+}
+
+// TransferFrom9 is a paid mutator transaction binding the contract method 0x4f7bd75a.
+//
+// Solidity: function transferFrom9(address from, address to, uint256 value) returns(bool)
+func (_StateBloatToken *StateBloatTokenTransactor) TransferFrom9(opts *bind.TransactOpts, from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) {
+ return _StateBloatToken.contract.Transact(opts, "transferFrom9", from, to, value)
+}
+
+// TransferFrom9 is a paid mutator transaction binding the contract method 0x4f7bd75a.
+//
+// Solidity: function transferFrom9(address from, address to, uint256 value) returns(bool)
+func (_StateBloatToken *StateBloatTokenSession) TransferFrom9(from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) {
+ return _StateBloatToken.Contract.TransferFrom9(&_StateBloatToken.TransactOpts, from, to, value)
+}
+
+// TransferFrom9 is a paid mutator transaction binding the contract method 0x4f7bd75a.
+//
+// Solidity: function transferFrom9(address from, address to, uint256 value) returns(bool)
+func (_StateBloatToken *StateBloatTokenTransactorSession) TransferFrom9(from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) {
+ return _StateBloatToken.Contract.TransferFrom9(&_StateBloatToken.TransactOpts, from, to, value)
+}
+
+// StateBloatTokenApprovalIterator is returned from FilterApproval and is used to iterate over the raw logs and unpacked data for Approval events raised by the StateBloatToken contract.
+type StateBloatTokenApprovalIterator struct {
+ Event *StateBloatTokenApproval // Event containing the contract specifics and raw log
+
+ contract *bind.BoundContract // Generic contract to use for unpacking event data
+ event string // Event name to use for unpacking event data
+
+ logs chan types.Log // Log channel receiving the found contract events
+ sub ethereum.Subscription // Subscription for errors, completion and termination
+ done bool // Whether the subscription completed delivering logs
+ fail error // Occurred error to stop iteration
+}
+
+// Next advances the iterator to the subsequent event, returning whether there
+// are any more events found. In case of a retrieval or parsing error, false is
+// returned and Error() can be queried for the exact failure.
+func (it *StateBloatTokenApprovalIterator) Next() bool {
+ // If the iterator failed, stop iterating
+ if it.fail != nil {
+ return false
+ }
+ // If the iterator completed, deliver directly whatever's available
+ if it.done {
+ select {
+ case log := <-it.logs:
+ it.Event = new(StateBloatTokenApproval)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ default:
+ return false
+ }
+ }
+ // Iterator still in progress, wait for either a data or an error event
+ select {
+ case log := <-it.logs:
+ it.Event = new(StateBloatTokenApproval)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ case err := <-it.sub.Err():
+ it.done = true
+ it.fail = err
+ return it.Next()
+ }
+}
+
+// Error returns any retrieval or parsing error occurred during filtering.
+func (it *StateBloatTokenApprovalIterator) Error() error {
+ return it.fail
+}
+
+// Close terminates the iteration process, releasing any pending underlying
+// resources.
+func (it *StateBloatTokenApprovalIterator) Close() error {
+ it.sub.Unsubscribe()
+ return nil
+}
+
+// StateBloatTokenApproval represents a Approval event raised by the StateBloatToken contract.
+type StateBloatTokenApproval struct {
+ Owner common.Address
+ Spender common.Address
+ Value *big.Int
+ Raw types.Log // Blockchain specific contextual infos
+}
+
+// FilterApproval is a free log retrieval operation binding the contract event 0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925.
+//
+// Solidity: event Approval(address indexed owner, address indexed spender, uint256 value)
+func (_StateBloatToken *StateBloatTokenFilterer) FilterApproval(opts *bind.FilterOpts, owner []common.Address, spender []common.Address) (*StateBloatTokenApprovalIterator, error) {
+
+ var ownerRule []interface{}
+ for _, ownerItem := range owner {
+ ownerRule = append(ownerRule, ownerItem)
+ }
+ var spenderRule []interface{}
+ for _, spenderItem := range spender {
+ spenderRule = append(spenderRule, spenderItem)
+ }
+
+ logs, sub, err := _StateBloatToken.contract.FilterLogs(opts, "Approval", ownerRule, spenderRule)
+ if err != nil {
+ return nil, err
+ }
+ return &StateBloatTokenApprovalIterator{contract: _StateBloatToken.contract, event: "Approval", logs: logs, sub: sub}, nil
+}
+
+// WatchApproval is a free log subscription operation binding the contract event 0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925.
+//
+// Solidity: event Approval(address indexed owner, address indexed spender, uint256 value)
+func (_StateBloatToken *StateBloatTokenFilterer) WatchApproval(opts *bind.WatchOpts, sink chan<- *StateBloatTokenApproval, owner []common.Address, spender []common.Address) (event.Subscription, error) {
+
+ var ownerRule []interface{}
+ for _, ownerItem := range owner {
+ ownerRule = append(ownerRule, ownerItem)
+ }
+ var spenderRule []interface{}
+ for _, spenderItem := range spender {
+ spenderRule = append(spenderRule, spenderItem)
+ }
+
+ logs, sub, err := _StateBloatToken.contract.WatchLogs(opts, "Approval", ownerRule, spenderRule)
+ if err != nil {
+ return nil, err
+ }
+ return event.NewSubscription(func(quit <-chan struct{}) error {
+ defer sub.Unsubscribe()
+ for {
+ select {
+ case log := <-logs:
+ // New log arrived, parse the event and forward to the user
+ event := new(StateBloatTokenApproval)
+ if err := _StateBloatToken.contract.UnpackLog(event, "Approval", log); err != nil {
+ return err
+ }
+ event.Raw = log
+
+ select {
+ case sink <- event:
+ case err := <-sub.Err():
+ return err
+ case <-quit:
+ return nil
+ }
+ case err := <-sub.Err():
+ return err
+ case <-quit:
+ return nil
+ }
+ }
+ }), nil
+}
+
+// ParseApproval is a log parse operation binding the contract event 0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925.
+//
+// Solidity: event Approval(address indexed owner, address indexed spender, uint256 value)
+func (_StateBloatToken *StateBloatTokenFilterer) ParseApproval(log types.Log) (*StateBloatTokenApproval, error) {
+ event := new(StateBloatTokenApproval)
+ if err := _StateBloatToken.contract.UnpackLog(event, "Approval", log); err != nil {
+ return nil, err
+ }
+ event.Raw = log
+ return event, nil
+}
+
+// StateBloatTokenTransferIterator is returned from FilterTransfer and is used to iterate over the raw logs and unpacked data for Transfer events raised by the StateBloatToken contract.
+type StateBloatTokenTransferIterator struct {
+ Event *StateBloatTokenTransfer // Event containing the contract specifics and raw log
+
+ contract *bind.BoundContract // Generic contract to use for unpacking event data
+ event string // Event name to use for unpacking event data
+
+ logs chan types.Log // Log channel receiving the found contract events
+ sub ethereum.Subscription // Subscription for errors, completion and termination
+ done bool // Whether the subscription completed delivering logs
+ fail error // Occurred error to stop iteration
+}
+
+// Next advances the iterator to the subsequent event, returning whether there
+// are any more events found. In case of a retrieval or parsing error, false is
+// returned and Error() can be queried for the exact failure.
+func (it *StateBloatTokenTransferIterator) Next() bool {
+ // If the iterator failed, stop iterating
+ if it.fail != nil {
+ return false
+ }
+ // If the iterator completed, deliver directly whatever's available
+ if it.done {
+ select {
+ case log := <-it.logs:
+ it.Event = new(StateBloatTokenTransfer)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ default:
+ return false
+ }
+ }
+ // Iterator still in progress, wait for either a data or an error event
+ select {
+ case log := <-it.logs:
+ it.Event = new(StateBloatTokenTransfer)
+ if err := it.contract.UnpackLog(it.Event, it.event, log); err != nil {
+ it.fail = err
+ return false
+ }
+ it.Event.Raw = log
+ return true
+
+ case err := <-it.sub.Err():
+ it.done = true
+ it.fail = err
+ return it.Next()
+ }
+}
+
+// Error returns any retrieval or parsing error occurred during filtering.
+func (it *StateBloatTokenTransferIterator) Error() error {
+ return it.fail
+}
+
+// Close terminates the iteration process, releasing any pending underlying
+// resources.
+func (it *StateBloatTokenTransferIterator) Close() error {
+ it.sub.Unsubscribe()
+ return nil
+}
+
+// StateBloatTokenTransfer represents a Transfer event raised by the StateBloatToken contract.
+type StateBloatTokenTransfer struct {
+ From common.Address
+ To common.Address
+ Value *big.Int
+ Raw types.Log // Blockchain specific contextual infos
+}
+
+// FilterTransfer is a free log retrieval operation binding the contract event 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef.
+//
+// Solidity: event Transfer(address indexed from, address indexed to, uint256 value)
+func (_StateBloatToken *StateBloatTokenFilterer) FilterTransfer(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*StateBloatTokenTransferIterator, error) {
+
+ var fromRule []interface{}
+ for _, fromItem := range from {
+ fromRule = append(fromRule, fromItem)
+ }
+ var toRule []interface{}
+ for _, toItem := range to {
+ toRule = append(toRule, toItem)
+ }
+
+ logs, sub, err := _StateBloatToken.contract.FilterLogs(opts, "Transfer", fromRule, toRule)
+ if err != nil {
+ return nil, err
+ }
+ return &StateBloatTokenTransferIterator{contract: _StateBloatToken.contract, event: "Transfer", logs: logs, sub: sub}, nil
+}
+
+// WatchTransfer is a free log subscription operation binding the contract event 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef.
+//
+// Solidity: event Transfer(address indexed from, address indexed to, uint256 value)
+func (_StateBloatToken *StateBloatTokenFilterer) WatchTransfer(opts *bind.WatchOpts, sink chan<- *StateBloatTokenTransfer, from []common.Address, to []common.Address) (event.Subscription, error) {
+
+ var fromRule []interface{}
+ for _, fromItem := range from {
+ fromRule = append(fromRule, fromItem)
+ }
+ var toRule []interface{}
+ for _, toItem := range to {
+ toRule = append(toRule, toItem)
+ }
+
+ logs, sub, err := _StateBloatToken.contract.WatchLogs(opts, "Transfer", fromRule, toRule)
+ if err != nil {
+ return nil, err
+ }
+ return event.NewSubscription(func(quit <-chan struct{}) error {
+ defer sub.Unsubscribe()
+ for {
+ select {
+ case log := <-logs:
+ // New log arrived, parse the event and forward to the user
+ event := new(StateBloatTokenTransfer)
+ if err := _StateBloatToken.contract.UnpackLog(event, "Transfer", log); err != nil {
+ return err
+ }
+ event.Raw = log
+
+ select {
+ case sink <- event:
+ case err := <-sub.Err():
+ return err
+ case <-quit:
+ return nil
+ }
+ case err := <-sub.Err():
+ return err
+ case <-quit:
+ return nil
+ }
+ }
+ }), nil
+}
+
+// ParseTransfer is a log parse operation binding the contract event 0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef.
+//
+// Solidity: event Transfer(address indexed from, address indexed to, uint256 value)
+func (_StateBloatToken *StateBloatTokenFilterer) ParseTransfer(log types.Log) (*StateBloatTokenTransfer, error) {
+ event := new(StateBloatTokenTransfer)
+ if err := _StateBloatToken.contract.UnpackLog(event, "Transfer", log); err != nil {
+ return nil, err
+ }
+ event.Raw = log
+ return event, nil
+}
diff --git a/scenarios/statebloat/contract_deploy/contract/StateBloatToken.sol b/scenarios/statebloat/contract_deploy/contract/StateBloatToken.sol
new file mode 100644
index 00000000..eb7dc2dc
--- /dev/null
+++ b/scenarios/statebloat/contract_deploy/contract/StateBloatToken.sol
@@ -0,0 +1,606 @@
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.22;
+
+contract StateBloatToken {
+ string public name;
+ string public symbol;
+ uint8 public decimals;
+ uint256 public totalSupply;
+ mapping(address => uint256) public balanceOf;
+ mapping(address => mapping(address => uint256)) public allowance;
+
+ // Salt to make each deployment unique
+ uint256 public immutable salt;
+
+ // Large constant to increase bytecode size to exactly 24KiB
+ string public constant PADDING_DATA =
+ "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA";
+
+ event Transfer(address indexed from, address indexed to, uint256 value);
+ event Approval(
+ address indexed owner,
+ address indexed spender,
+ uint256 value
+ );
+
+ constructor(uint256 _salt) {
+ name = "State Bloat Token";
+ symbol = "SBT";
+ decimals = 18;
+ salt = _salt;
+ totalSupply = 1000000 * 10 ** decimals;
+ balanceOf[msg.sender] = totalSupply;
+ emit Transfer(address(0), msg.sender, totalSupply);
+ }
+
+ function transfer(address to, uint256 value) public returns (bool) {
+ require(balanceOf[msg.sender] >= value, "Insufficient balance");
+ balanceOf[msg.sender] -= value;
+ balanceOf[to] += value;
+ emit Transfer(msg.sender, to, value);
+ return true;
+ }
+
+ function approve(address spender, uint256 value) public returns (bool) {
+ allowance[msg.sender][spender] = value;
+ emit Approval(msg.sender, spender, value);
+ return true;
+ }
+
+ function transferFrom(
+ address from,
+ address to,
+ uint256 value
+ ) public returns (bool) {
+ require(balanceOf[from] >= value, "Insufficient balance");
+ require(allowance[from][msg.sender] >= value, "Insufficient allowance");
+ balanceOf[from] -= value;
+ balanceOf[to] += value;
+ allowance[from][msg.sender] -= value;
+ emit Transfer(from, to, value);
+ return true;
+ }
+
+ // Dummy functions to increase bytecode size
+ function dummy1() public pure returns (uint256) {
+ return 1;
+ }
+
+ function dummy2() public pure returns (uint256) {
+ return 2;
+ }
+
+ function dummy3() public pure returns (uint256) {
+ return 3;
+ }
+
+ function dummy4() public pure returns (uint256) {
+ return 4;
+ }
+
+ function dummy5() public pure returns (uint256) {
+ return 5;
+ }
+
+ function dummy6() public pure returns (uint256) {
+ return 6;
+ }
+
+ function dummy7() public pure returns (uint256) {
+ return 7;
+ }
+
+ function dummy8() public pure returns (uint256) {
+ return 8;
+ }
+
+ function dummy9() public pure returns (uint256) {
+ return 9;
+ }
+
+ function dummy10() public pure returns (uint256) {
+ return 10;
+ }
+
+ function dummy11() public pure returns (uint256) {
+ return 11;
+ }
+
+ function dummy12() public pure returns (uint256) {
+ return 12;
+ }
+
+ function dummy13() public pure returns (uint256) {
+ return 13;
+ }
+
+ function dummy14() public pure returns (uint256) {
+ return 14;
+ }
+
+ function dummy15() public pure returns (uint256) {
+ return 15;
+ }
+
+ function dummy16() public pure returns (uint256) {
+ return 16;
+ }
+
+ function dummy17() public pure returns (uint256) {
+ return 17;
+ }
+
+ function dummy18() public pure returns (uint256) {
+ return 18;
+ }
+
+ function dummy19() public pure returns (uint256) {
+ return 19;
+ }
+
+ function dummy20() public pure returns (uint256) {
+ return 20;
+ }
+
+ function dummy21() public pure returns (uint256) {
+ return 21;
+ }
+
+ function dummy22() public pure returns (uint256) {
+ return 22;
+ }
+
+ function dummy23() public pure returns (uint256) {
+ return 23;
+ }
+
+ function dummy24() public pure returns (uint256) {
+ return 24;
+ }
+
+ function dummy25() public pure returns (uint256) {
+ return 25;
+ }
+
+ function dummy26() public pure returns (uint256) {
+ return 26;
+ }
+
+ function dummy27() public pure returns (uint256) {
+ return 27;
+ }
+
+ function dummy28() public pure returns (uint256) {
+ return 28;
+ }
+
+ function dummy29() public pure returns (uint256) {
+ return 29;
+ }
+
+ function dummy30() public pure returns (uint256) {
+ return 30;
+ }
+
+ function dummy31() public pure returns (uint256) {
+ return 31;
+ }
+
+ function dummy32() public pure returns (uint256) {
+ return 32;
+ }
+
+ function dummy33() public pure returns (uint256) {
+ return 33;
+ }
+
+ function dummy34() public pure returns (uint256) {
+ return 34;
+ }
+
+ function dummy35() public pure returns (uint256) {
+ return 35;
+ }
+
+ function dummy36() public pure returns (uint256) {
+ return 36;
+ }
+
+ function dummy37() public pure returns (uint256) {
+ return 37;
+ }
+
+ function dummy38() public pure returns (uint256) {
+ return 38;
+ }
+
+ function dummy39() public pure returns (uint256) {
+ return 39;
+ }
+
+ function dummy40() public pure returns (uint256) {
+ return 40;
+ }
+
+ function dummy41() public pure returns (uint256) {
+ return 41;
+ }
+
+ function dummy42() public pure returns (uint256) {
+ return 42;
+ }
+
+ function dummy43() public pure returns (uint256) {
+ return 43;
+ }
+
+ function dummy44() public pure returns (uint256) {
+ return 44;
+ }
+
+ function dummy45() public pure returns (uint256) {
+ return 45;
+ }
+
+ function dummy46() public pure returns (uint256) {
+ return 46;
+ }
+
+ function dummy47() public pure returns (uint256) {
+ return 47;
+ }
+
+ function dummy48() public pure returns (uint256) {
+ return 48;
+ }
+
+ function dummy49() public pure returns (uint256) {
+ return 49;
+ }
+
+ function dummy50() public pure returns (uint256) {
+ return 50;
+ }
+
+ function dummy51() public pure returns (uint256) {
+ return 51;
+ }
+
+ function dummy52() public pure returns (uint256) {
+ return 52;
+ }
+
+ function dummy53() public pure returns (uint256) {
+ return 53;
+ }
+
+ function dummy54() public pure returns (uint256) {
+ return 54;
+ }
+
+ function dummy55() public pure returns (uint256) {
+ return 55;
+ }
+
+ function dummy56() public pure returns (uint256) {
+ return 56;
+ }
+
+ function dummy57() public pure returns (uint256) {
+ return 57;
+ }
+
+ function dummy58() public pure returns (uint256) {
+ return 58;
+ }
+
+ function dummy59() public pure returns (uint256) {
+ return 59;
+ }
+
+ function dummy60() public pure returns (uint256) {
+ return 60;
+ }
+
+ function dummy61() public pure returns (uint256) {
+ return 61;
+ }
+
+ function dummy62() public pure returns (uint256) {
+ return 62;
+ }
+
+ function dummy63() public pure returns (uint256) {
+ return 63;
+ }
+
+ function dummy64() public pure returns (uint256) {
+ return 64;
+ }
+
+ function dummy65() public pure returns (uint256) {
+ return 65;
+ }
+
+ // Additional dummy functions to increase bytecode to exactly 24KiB
+ function dummy66() public pure returns (uint256) {
+ return 66;
+ }
+
+ function dummy67() public pure returns (uint256) {
+ return 67;
+ }
+
+ function dummy68() public pure returns (uint256) {
+ return 68;
+ }
+
+ function dummy69() public pure returns (uint256) {
+ return 69;
+ }
+
+ function transferFrom1(
+ address from,
+ address to,
+ uint256 value
+ ) public returns (bool) {
+ require(balanceOf[from] >= value, "Insufficient balance");
+ require(allowance[from][msg.sender] >= value, "Insufficient allowance");
+ balanceOf[from] -= value;
+ balanceOf[to] += value;
+ allowance[from][msg.sender] -= value;
+ emit Transfer(from, to, value);
+ return true;
+ }
+
+ function transferFrom2(
+ address from,
+ address to,
+ uint256 value
+ ) public returns (bool) {
+ require(balanceOf[from] >= value, "Insufficient balance");
+ require(allowance[from][msg.sender] >= value, "Insufficient allowance");
+ balanceOf[from] -= value;
+ balanceOf[to] += value;
+ allowance[from][msg.sender] -= value;
+ emit Transfer(from, to, value);
+ return true;
+ }
+
+ function transferFrom3(
+ address from,
+ address to,
+ uint256 value
+ ) public returns (bool) {
+ require(balanceOf[from] >= value, "Insufficient balance");
+ require(allowance[from][msg.sender] >= value, "Insufficient allowance");
+ balanceOf[from] -= value;
+ balanceOf[to] += value;
+ allowance[from][msg.sender] -= value;
+ emit Transfer(from, to, value);
+ return true;
+ }
+
+ function transferFrom4(
+ address from,
+ address to,
+ uint256 value
+ ) public returns (bool) {
+ require(balanceOf[from] >= value, "Insufficient balance");
+ require(allowance[from][msg.sender] >= value, "Insufficient allowance");
+ balanceOf[from] -= value;
+ balanceOf[to] += value;
+ allowance[from][msg.sender] -= value;
+ emit Transfer(from, to, value);
+ return true;
+ }
+
+ function transferFrom5(
+ address from,
+ address to,
+ uint256 value
+ ) public returns (bool) {
+ require(balanceOf[from] >= value, "Insufficient balance");
+ require(allowance[from][msg.sender] >= value, "Insufficient allowance");
+ balanceOf[from] -= value;
+ balanceOf[to] += value;
+ allowance[from][msg.sender] -= value;
+ emit Transfer(from, to, value);
+ return true;
+ }
+
+ function transferFrom6(
+ address from,
+ address to,
+ uint256 value
+ ) public returns (bool) {
+ require(balanceOf[from] >= value, "Insufficient balance");
+ require(allowance[from][msg.sender] >= value, "Insufficient allowance");
+ balanceOf[from] -= value;
+ balanceOf[to] += value;
+ allowance[from][msg.sender] -= value;
+ emit Transfer(from, to, value);
+ return true;
+ }
+
+ function transferFrom7(
+ address from,
+ address to,
+ uint256 value
+ ) public returns (bool) {
+ require(balanceOf[from] >= value, "Insufficient balance");
+ require(allowance[from][msg.sender] >= value, "Insufficient allowance");
+ balanceOf[from] -= value;
+ balanceOf[to] += value;
+ allowance[from][msg.sender] -= value;
+ emit Transfer(from, to, value);
+ return true;
+ }
+
+ function transferFrom8(
+ address from,
+ address to,
+ uint256 value
+ ) public returns (bool) {
+ require(balanceOf[from] >= value, "Insufficient balance");
+ require(allowance[from][msg.sender] >= value, "Insufficient allowance");
+ balanceOf[from] -= value;
+ balanceOf[to] += value;
+ allowance[from][msg.sender] -= value;
+ emit Transfer(from, to, value);
+ return true;
+ }
+
+ function transferFrom9(
+ address from,
+ address to,
+ uint256 value
+ ) public returns (bool) {
+ require(balanceOf[from] >= value, "Insufficient balance");
+ require(allowance[from][msg.sender] >= value, "Insufficient allowance");
+ balanceOf[from] -= value;
+ balanceOf[to] += value;
+ allowance[from][msg.sender] -= value;
+ emit Transfer(from, to, value);
+ return true;
+ }
+
+ function transferFrom10(
+ address from,
+ address to,
+ uint256 value
+ ) public returns (bool) {
+ require(balanceOf[from] >= value, "Insufficient balance");
+ require(allowance[from][msg.sender] >= value, "Insufficient allowance");
+ balanceOf[from] -= value;
+ balanceOf[to] += value;
+ allowance[from][msg.sender] -= value;
+ emit Transfer(from, to, value);
+ return true;
+ }
+
+ function transferFrom11(
+ address from,
+ address to,
+ uint256 value
+ ) public returns (bool) {
+ require(balanceOf[from] >= value, "Insufficient balance");
+ require(allowance[from][msg.sender] >= value, "Insufficient allowance");
+ balanceOf[from] -= value;
+ balanceOf[to] += value;
+ allowance[from][msg.sender] -= value;
+ emit Transfer(from, to, value);
+ return true;
+ }
+
+ function transferFrom12(
+ address from,
+ address to,
+ uint256 value
+ ) public returns (bool) {
+ require(balanceOf[from] >= value, "Insufficient balance");
+ require(allowance[from][msg.sender] >= value, "Insufficient allowance");
+ balanceOf[from] -= value;
+ balanceOf[to] += value;
+ allowance[from][msg.sender] -= value;
+ emit Transfer(from, to, value);
+ return true;
+ }
+
+ function transferFrom13(
+ address from,
+ address to,
+ uint256 value
+ ) public returns (bool) {
+ require(balanceOf[from] >= value, "Insufficient balance");
+ require(allowance[from][msg.sender] >= value, "Insufficient allowance");
+ balanceOf[from] -= value;
+ balanceOf[to] += value;
+ allowance[from][msg.sender] -= value;
+ emit Transfer(from, to, value);
+ return true;
+ }
+
+ function transferFrom14(
+ address from,
+ address to,
+ uint256 value
+ ) public returns (bool) {
+ require(balanceOf[from] >= value, "Insufficient balance");
+ require(allowance[from][msg.sender] >= value, "Insufficient allowance");
+ balanceOf[from] -= value;
+ balanceOf[to] += value;
+ allowance[from][msg.sender] -= value;
+ emit Transfer(from, to, value);
+ return true;
+ }
+
+ function transferFrom15(
+ address from,
+ address to,
+ uint256 value
+ ) public returns (bool) {
+ require(balanceOf[from] >= value, "Insufficient balance");
+ require(allowance[from][msg.sender] >= value, "Insufficient allowance");
+ balanceOf[from] -= value;
+ balanceOf[to] += value;
+ allowance[from][msg.sender] -= value;
+ emit Transfer(from, to, value);
+ return true;
+ }
+
+ function transferFrom16(
+ address from,
+ address to,
+ uint256 value
+ ) public returns (bool) {
+ require(balanceOf[from] >= value, "Insufficient balance");
+ require(allowance[from][msg.sender] >= value, "Insufficient allowance");
+ balanceOf[from] -= value;
+ balanceOf[to] += value;
+ allowance[from][msg.sender] -= value;
+ emit Transfer(from, to, value);
+ return true;
+ }
+
+ function transferFrom17(
+ address from,
+ address to,
+ uint256 value
+ ) public returns (bool) {
+ require(balanceOf[from] >= value, "A");
+ require(allowance[from][msg.sender] >= value, "B");
+ balanceOf[from] -= value;
+ balanceOf[to] += value;
+ allowance[from][msg.sender] -= value;
+ emit Transfer(from, to, value);
+ return true;
+ }
+
+ function transferFrom18(
+ address from,
+ address to,
+ uint256 value
+ ) public returns (bool) {
+ require(balanceOf[from] >= value, "A");
+ require(allowance[from][msg.sender] >= value, "B");
+ balanceOf[from] -= value;
+ balanceOf[to] += value;
+ allowance[from][msg.sender] -= value;
+ emit Transfer(from, to, value);
+ return true;
+ }
+
+ function transferFrom19(
+ address from,
+ address to,
+ uint256 value
+ ) public returns (bool) {
+ require(balanceOf[from] >= value, "A");
+ balanceOf[from] -= value;
+ balanceOf[to] += value;
+ allowance[from][msg.sender] -= value;
+ emit Transfer(from, to, value);
+ return true;
+ }
+}
diff --git a/scenarios/statebloat/contract_deploy/contract/compile.sh b/scenarios/statebloat/contract_deploy/contract/compile.sh
new file mode 100755
index 00000000..c96a3f4f
--- /dev/null
+++ b/scenarios/statebloat/contract_deploy/contract/compile.sh
@@ -0,0 +1,35 @@
+#!/bin/bash
+
+compile_contract() {
+ local workdir=$1
+ local solc_version=$2
+ local solc_args=$3
+ local contract_file=$4
+ local contract_name=$5
+
+ if [ -z "$contract_name" ]; then
+ contract_name="$contract_file"
+ fi
+
+ #echo "docker run --rm -v $workdir:/contracts ethereum/solc:$solc_version /contracts/$contract_file.sol --combined-json abi,bin $solc_args"
+ local contract_json=$(docker run --rm -v $workdir:/contracts ethereum/solc:$solc_version /contracts/$contract_file.sol --combined-json abi,bin $solc_args)
+
+ local contract_abi=$(echo "$contract_json" | jq -r '.contracts["/contracts/'$contract_file'.sol:'$contract_name'"].abi')
+ if [ "$contract_abi" == "null" ]; then
+ contract_abi=$(echo "$contract_json" | jq -r '.contracts["contracts/'$contract_file'.sol:'$contract_name'"].abi')
+ fi
+
+ local contract_bin=$(echo "$contract_json" | jq -r '.contracts["/contracts/'$contract_file'.sol:'$contract_name'"].bin')
+ if [ "$contract_bin" == "null" ]; then
+ contract_bin=$(echo "$contract_json" | jq -r '.contracts["contracts/'$contract_file'.sol:'$contract_name'"].bin')
+ fi
+
+ echo "$contract_abi" > $contract_name.abi
+ echo "$contract_bin" > $contract_name.bin
+ abigen --bin=./$contract_name.bin --abi=./$contract_name.abi --pkg=contract --out=$contract_name.go --type $contract_name
+ rm $contract_name.bin $contract_name.abi
+ echo "$contract_json" | jq > $contract_name.output.json
+}
+
+# StateBloatToken
+compile_contract "$(pwd)" 0.8.22 "--optimize --optimize-runs 999999" StateBloatToken
diff --git a/scenarios/statebloat/contract_deploy/contract_deploy.go b/scenarios/statebloat/contract_deploy/contract_deploy.go
new file mode 100644
index 00000000..8c08b7b4
--- /dev/null
+++ b/scenarios/statebloat/contract_deploy/contract_deploy.go
@@ -0,0 +1,524 @@
+package sbcontractdeploy
+
+import (
+ "context"
+ "crypto/ecdsa"
+ "crypto/rand"
+ "encoding/json"
+ "fmt"
+ "math/big"
+ "os"
+ "strings"
+ "sync"
+ "sync/atomic"
+ "time"
+
+ "gopkg.in/yaml.v3"
+
+ "github.com/ethereum/go-ethereum/accounts/abi/bind"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/crypto"
+ "github.com/holiman/uint256"
+ "github.com/sirupsen/logrus"
+ "github.com/spf13/pflag"
+
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethpandaops/spamoor/scenario"
+ "github.com/ethpandaops/spamoor/scenarios/statebloat/contract_deploy/contract"
+ "github.com/ethpandaops/spamoor/spamoor"
+ "github.com/ethpandaops/spamoor/txbuilder"
+)
+
+type ScenarioOptions struct {
+ MaxPending uint64 `yaml:"max_pending"`
+ MaxWallets uint64 `yaml:"max_wallets"`
+ BaseFee uint64 `yaml:"base_fee"`
+ TipFee uint64 `yaml:"tip_fee"`
+ ClientGroup string `yaml:"client_group"`
+ MaxTransactions uint64 `yaml:"max_transactions"`
+ DeploymentsFile string `yaml:"deployments_file"`
+}
+
+// ContractDeployment tracks a deployed contract with its deployer info
+type ContractDeployment struct {
+ ContractAddress string `json:"contract_address"`
+ PrivateKey string `json:"private_key"`
+}
+
+// BlockDeploymentStats tracks deployment statistics per block
+type BlockDeploymentStats struct {
+ BlockNumber uint64
+ ContractCount int
+ TotalGasUsed uint64
+ TotalBytecodeSize int
+}
+
+type Scenario struct {
+ options ScenarioOptions
+ logger *logrus.Entry
+ walletPool *spamoor.WalletPool
+
+ // Results tracking
+ deployedContracts []ContractDeployment
+ contractsMutex sync.Mutex
+
+ // Block-level statistics tracking
+ blockStats map[uint64]*BlockDeploymentStats
+ blockStatsMutex sync.Mutex
+ lastLoggedBlock uint64
+}
+
+var ScenarioName = "statebloat-contract-deploy"
+var ScenarioDefaultOptions = ScenarioOptions{
+ MaxWallets: 0, // Use root wallet only by default
+ BaseFee: 5, // Moderate base fee (5 gwei)
+ TipFee: 1, // Priority fee (1 gwei)
+ MaxTransactions: 0,
+ DeploymentsFile: "deployments.json",
+}
+var ScenarioDescriptor = scenario.Descriptor{
+ Name: ScenarioName,
+ Description: "Deploy contracts to create state bloat",
+ DefaultOptions: ScenarioDefaultOptions,
+ NewScenario: newScenario,
+}
+
+func newScenario(logger logrus.FieldLogger) scenario.Scenario {
+ return &Scenario{
+ logger: logger.WithField("scenario", ScenarioName),
+ }
+}
+
+func (s *Scenario) Flags(flags *pflag.FlagSet) error {
+ flags.Uint64Var(&s.options.MaxPending, "max-pending", ScenarioDefaultOptions.MaxPending, "Maximum number of pending transactions")
+ flags.Uint64Var(&s.options.MaxWallets, "max-wallets", ScenarioDefaultOptions.MaxWallets, "Maximum number of child wallets to use")
+ flags.Uint64Var(&s.options.BaseFee, "basefee", ScenarioDefaultOptions.BaseFee, "Base fee per gas in gwei")
+ flags.Uint64Var(&s.options.TipFee, "tipfee", ScenarioDefaultOptions.TipFee, "Tip fee per gas in gwei")
+ flags.StringVar(&s.options.ClientGroup, "client-group", ScenarioDefaultOptions.ClientGroup, "Client group to use for sending transactions")
+ flags.Uint64Var(&s.options.MaxTransactions, "max-transactions", ScenarioDefaultOptions.MaxTransactions, "Maximum number of transactions to send (0 = use rate limiting based on block gas limit)")
+ flags.StringVar(&s.options.DeploymentsFile, "deployments-file", ScenarioDefaultOptions.DeploymentsFile, "File to save deployments to")
+ return nil
+}
+
+func (s *Scenario) Init(options *scenario.Options) error {
+ s.walletPool = options.WalletPool
+
+ if options.Config != "" {
+ err := yaml.Unmarshal([]byte(options.Config), &s.options)
+ if err != nil {
+ return fmt.Errorf("failed to unmarshal config: %w", err)
+ }
+ }
+
+ if s.options.MaxWallets > 0 {
+ s.walletPool.SetWalletCount(s.options.MaxWallets)
+ } else {
+ s.walletPool.SetWalletCount(10)
+ }
+
+ return nil
+}
+
+// recordDeployedContract records a successfully deployed contract
+func (s *Scenario) recordDeployedContract(contractAddress common.Address, privateKey *ecdsa.PrivateKey, receipt *types.Receipt, txHash common.Hash) {
+ s.contractsMutex.Lock()
+ defer s.contractsMutex.Unlock()
+
+ // Keep the JSON structure simple - only contract address and private key
+ deployment := ContractDeployment{
+ ContractAddress: contractAddress.Hex(),
+ PrivateKey: fmt.Sprintf("0x%x", crypto.FromECDSA(privateKey)),
+ }
+
+ s.deployedContracts = append(s.deployedContracts, deployment)
+
+ // Get the actual deployed contract bytecode size
+ client := s.walletPool.GetClient(spamoor.SelectClientByIndex, 0, s.options.ClientGroup)
+ // TODO: This should be a constant documented on how this number is obtained.
+ var bytecodeSize int = 23914
+
+ if client != nil {
+ // Get the actual deployed bytecode size using eth_getCode
+ contractCode, err := client.GetEthClient().CodeAt(context.Background(), contractAddress, nil)
+ if err == nil {
+ bytecodeSize = len(contractCode)
+ }
+ }
+
+ blockNumber := receipt.BlockNumber.Uint64()
+
+ // Debug logging for block tracking
+ s.logger.WithFields(logrus.Fields{
+ "tx_block": blockNumber,
+ "existing_blocks": len(s.blockStats),
+ }).Debug("Recording contract deployment")
+
+ // Update block-level statistics
+ s.blockStatsMutex.Lock()
+ defer s.blockStatsMutex.Unlock()
+
+ if s.blockStats == nil {
+ s.blockStats = make(map[uint64]*BlockDeploymentStats)
+ }
+
+ // Create or update current block stats (removed the old logging logic)
+ if s.blockStats[blockNumber] == nil {
+ s.blockStats[blockNumber] = &BlockDeploymentStats{
+ BlockNumber: blockNumber,
+ }
+ s.logger.WithField("block_number", blockNumber).Debug("Created new block stats")
+ }
+
+ blockStat := s.blockStats[blockNumber]
+ blockStat.ContractCount++
+ blockStat.TotalGasUsed += receipt.GasUsed
+ blockStat.TotalBytecodeSize += bytecodeSize
+
+ s.logger.WithFields(logrus.Fields{
+ "block_number": blockNumber,
+ "contracts_in_block": blockStat.ContractCount,
+ "gas_used": blockStat.TotalGasUsed,
+ "bytecode_size": blockStat.TotalBytecodeSize,
+ }).Debug("Updated block stats")
+
+ // Save the deployments.json file each time a contract is confirmed
+ if err := s.saveDeploymentsMapping(); err != nil {
+ s.logger.Warnf("Failed to save deployments.json: %v", err)
+ }
+}
+
+// Helper function for max calculation
+func max(a, b int) int {
+ if a > b {
+ return a
+ }
+ return b
+}
+
+// saveDeploymentsMapping creates/updates deployments.json with private key to contract address mapping
+func (s *Scenario) saveDeploymentsMapping() error {
+ if s.options.DeploymentsFile == "" {
+ return nil
+ }
+
+ // Create a map from private key to array of contract addresses
+ deploymentMap := make(map[string][]string)
+
+ for _, contract := range s.deployedContracts {
+ privateKey := contract.PrivateKey
+ contractAddr := contract.ContractAddress
+ deploymentMap[privateKey] = append(deploymentMap[privateKey], contractAddr)
+ }
+
+ // Create or overwrite the deployments.json file
+ deploymentsFile, err := os.Create(s.options.DeploymentsFile)
+ if err != nil {
+ return fmt.Errorf("failed to create %v file: %w", s.options.DeploymentsFile, err)
+ }
+ defer deploymentsFile.Close()
+
+ // Write the mapping as JSON with pretty formatting
+ encoder := json.NewEncoder(deploymentsFile)
+ encoder.SetIndent("", " ")
+ err = encoder.Encode(deploymentMap)
+ if err != nil {
+ return fmt.Errorf("failed to write %v: %w", s.options.DeploymentsFile, err)
+ }
+
+ return nil
+}
+
+// startBlockMonitor starts a background goroutine that monitors for new blocks
+// and logs block deployment summaries immediately when blocks are mined
+func (s *Scenario) startBlockMonitor(ctx context.Context) {
+ go func() {
+ client := s.walletPool.GetClient(spamoor.SelectClientByIndex, 0, s.options.ClientGroup)
+ if client == nil {
+ s.logger.Warn("No client available for block monitoring")
+ return
+ }
+
+ ethClient := client.GetEthClient()
+ ticker := time.NewTicker(2 * time.Second) // Poll every 2 seconds
+ defer ticker.Stop()
+
+ for {
+ select {
+ case <-ctx.Done():
+ return
+ case <-ticker.C:
+ // Get current block number
+ latestBlock, err := ethClient.BlockByNumber(ctx, nil)
+ if err != nil {
+ s.logger.WithError(err).Debug("Failed to get latest block for monitoring")
+ continue
+ }
+
+ currentBlockNumber := latestBlock.Number().Uint64()
+
+ // Log any completed blocks that haven't been logged yet
+ s.blockStatsMutex.Lock()
+ for bn := s.lastLoggedBlock + 1; bn < currentBlockNumber; bn++ {
+ if stats, exists := s.blockStats[bn]; exists && stats.ContractCount > 0 {
+ avgGasPerByte := float64(stats.TotalGasUsed) / float64(max(stats.TotalBytecodeSize, 1))
+
+ s.contractsMutex.Lock()
+ totalContracts := len(s.deployedContracts)
+ s.contractsMutex.Unlock()
+
+ s.logger.WithFields(logrus.Fields{
+ "block_number": bn,
+ "contracts_deployed": stats.ContractCount,
+ "total_gas_used": stats.TotalGasUsed,
+ "total_bytecode_size": stats.TotalBytecodeSize,
+ "avg_gas_per_byte": fmt.Sprintf("%.2f", avgGasPerByte),
+ "total_contracts": totalContracts,
+ }).Info("Block deployment summary")
+
+ s.lastLoggedBlock = bn
+ }
+ }
+ s.blockStatsMutex.Unlock()
+ }
+ }
+ }()
+}
+
+func (s *Scenario) Run(ctx context.Context) error {
+ s.logger.Infof("starting scenario: %s", ScenarioName)
+ defer s.logger.Infof("scenario %s finished.", ScenarioName)
+
+ // Start block monitoring for real-time logging
+ s.startBlockMonitor(ctx)
+
+ // Calculate rate limiting based on block gas limit if max-transactions is 0
+ var maxTxsPerBlock uint64
+ var maxPending uint64 = 100
+ var totalTxCount uint64 = 0
+
+ if s.options.MaxTransactions == 0 {
+ // Get block gas limit from the network
+ client := s.walletPool.GetClient(spamoor.SelectClientByIndex, 0, s.options.ClientGroup)
+ if client == nil {
+ return fmt.Errorf("no client available for gas limit query")
+ }
+
+ latestBlock, err := client.GetEthClient().BlockByNumber(ctx, nil)
+ if err != nil {
+ return fmt.Errorf("failed to get latest block: %w", err)
+ }
+
+ blockGasLimit := latestBlock.GasLimit()
+ // TODO: This should be a constant.
+ estimatedGasPerContract := uint64(4949468) // Updated estimate based on contract size reduction
+ maxTxsPerBlock = blockGasLimit / estimatedGasPerContract
+
+ s.logger.Infof("Rate limiting enabled: block gas limit %d, gas per contract %d, max txs per block %d",
+ blockGasLimit, estimatedGasPerContract, maxTxsPerBlock)
+ }
+
+ if s.options.MaxPending > 0 {
+ maxPending = s.options.MaxPending
+ }
+
+ err := scenario.RunTransactionScenario(ctx, scenario.TransactionScenarioOptions{
+ TotalCount: s.options.MaxTransactions,
+ Throughput: maxTxsPerBlock,
+ MaxPending: maxPending,
+ WalletPool: s.walletPool,
+
+ Logger: s.logger,
+ ProcessNextTxFn: func(ctx context.Context, txIdx uint64, onComplete func()) (func(), error) {
+ logger := s.logger
+ tx, err := s.sendTransaction(ctx, txIdx, onComplete)
+
+ atomic.AddUint64(&totalTxCount, 1)
+
+ return func() {
+ if err != nil {
+ logger.Warnf("could not send transaction: %v", err)
+ } else {
+ logger.Debugf("sent deployment tx #%6d: %v", txIdx+1, tx.Hash().String())
+ }
+ }, err
+ },
+ })
+
+ // Log any remaining unlogged blocks (final blocks) - keep this as final safety net
+ s.blockStatsMutex.Lock()
+ for bn, stats := range s.blockStats {
+ if bn > s.lastLoggedBlock && stats.ContractCount > 0 {
+ avgGasPerByte := float64(stats.TotalGasUsed) / float64(max(stats.TotalBytecodeSize, 1))
+
+ s.logger.WithFields(logrus.Fields{
+ "block_number": bn,
+ "contracts_deployed": stats.ContractCount,
+ "total_gas_used": stats.TotalGasUsed,
+ "total_bytecode_size": stats.TotalBytecodeSize,
+ "avg_gas_per_byte": fmt.Sprintf("%.2f", avgGasPerByte),
+ "total_contracts": len(s.deployedContracts),
+ }).Info("Block deployment summary")
+ }
+ }
+ s.blockStatsMutex.Unlock()
+
+ // Log final summary
+ s.contractsMutex.Lock()
+ totalContracts := len(s.deployedContracts)
+ s.contractsMutex.Unlock()
+
+ s.logger.WithFields(logrus.Fields{
+ "total_txs": totalTxCount,
+ "total_contracts": totalContracts,
+ }).Info("All transactions completed")
+
+ return err
+}
+
+// sendTransaction sends a single contract deployment transaction
+func (s *Scenario) sendTransaction(ctx context.Context, txIdx uint64, onComplete func()) (*types.Transaction, error) {
+ maxRetries := 3
+
+ for attempt := 0; attempt < maxRetries; attempt++ {
+ tx, err := s.attemptTransaction(ctx, txIdx, attempt, onComplete)
+ if err == nil {
+ return tx, nil
+ }
+
+ // Check if it's a base fee error
+ if strings.Contains(err.Error(), "max fee per gas less than block base fee") {
+ s.logger.Warnf("Transaction %d base fee too low, adjusting fees and retrying (attempt %d/%d)",
+ txIdx, attempt+1, maxRetries)
+
+ // Update fees based on current network conditions
+ if updateErr := s.updateDynamicFees(ctx); updateErr != nil {
+ s.logger.Warnf("Failed to update dynamic fees: %v", updateErr)
+ }
+
+ time.Sleep(time.Duration(attempt+1) * 500 * time.Millisecond) // Exponential backoff
+ continue
+ }
+
+ // For other errors, return immediately
+ return nil, err
+ }
+
+ return nil, fmt.Errorf("failed to send transaction after %d attempts", maxRetries)
+}
+
+// updateDynamicFees queries the network and updates base fee and tip fee
+func (s *Scenario) updateDynamicFees(ctx context.Context) error {
+ client := s.walletPool.GetClient(spamoor.SelectClientByIndex, 0, s.options.ClientGroup)
+ if client == nil {
+ return fmt.Errorf("no client available")
+ }
+
+ ethClient := client.GetEthClient()
+
+ // Get the latest block to check current base fee
+ latestBlock, err := ethClient.BlockByNumber(ctx, nil)
+ if err != nil {
+ return fmt.Errorf("failed to get latest block: %w", err)
+ }
+
+ if latestBlock.BaseFee() != nil {
+ // Convert base fee from wei to gwei
+ currentBaseFeeGwei := new(big.Int).Div(latestBlock.BaseFee(), big.NewInt(1000000000))
+
+ newBaseFeeGwei := new(big.Int).Add(currentBaseFeeGwei, big.NewInt(100))
+
+ s.options.BaseFee = newBaseFeeGwei.Uint64()
+
+ // Also increase tip fee slightly to ensure competitive priority
+ if s.options.TipFee+1 > 3 {
+ s.options.TipFee = s.options.TipFee + 1
+ } else {
+ s.options.TipFee = 2 // Minimum 3 gwei tip
+ }
+
+ s.logger.Infof("Updated dynamic fees - Base fee: %d gwei, Tip fee: %d gwei (network base fee: %s gwei)",
+ s.options.BaseFee, s.options.TipFee, currentBaseFeeGwei.String())
+ }
+
+ return nil
+}
+
+// attemptTransaction makes a single attempt to send a transaction
+func (s *Scenario) attemptTransaction(ctx context.Context, txIdx uint64, attempt int, onComplete func()) (*types.Transaction, error) {
+ // Get client and wallet
+ client := s.walletPool.GetClient(spamoor.SelectClientRoundRobin, 0, "")
+ wallet := s.walletPool.GetWallet(spamoor.SelectWalletByIndex, int(txIdx))
+
+ if client == nil {
+ return nil, fmt.Errorf("no client available")
+ }
+ if wallet == nil {
+ return nil, fmt.Errorf("no wallet available")
+ }
+
+ // Set EIP-1559 fee parameters
+ feeCap, tipCap, err := s.walletPool.GetTxPool().GetSuggestedFees(client, s.options.BaseFee, s.options.TipFee)
+ if err != nil {
+ return nil, fmt.Errorf("failed to get suggested fees: %w", err)
+ }
+
+ // Generate random salt for unique contract
+ salt := make([]byte, 32)
+ _, err = rand.Read(salt)
+ if err != nil {
+ return nil, fmt.Errorf("failed to generate salt: %w", err)
+ }
+ saltInt := new(big.Int).SetBytes(salt)
+
+ // Deploy the contract
+ ethClient := client.GetEthClient()
+ if ethClient == nil {
+ return nil, fmt.Errorf("failed to get eth client")
+ }
+
+ tx, err := wallet.BuildBoundTx(ctx, &txbuilder.TxMetadata{
+ GasFeeCap: uint256.MustFromBig(feeCap),
+ GasTipCap: uint256.MustFromBig(tipCap),
+ Gas: 5200000,
+ Value: uint256.NewInt(0),
+ }, func(transactOpts *bind.TransactOpts) (*types.Transaction, error) {
+ _, deployTx, _, err := contract.DeployStateBloatToken(transactOpts, client.GetEthClient(), saltInt)
+ return deployTx, err
+ })
+
+ if err != nil {
+ return nil, fmt.Errorf("failed to create deployment transaction: %w", err)
+ }
+
+ mu := sync.Mutex{}
+ mu.Lock()
+ defer mu.Unlock()
+
+ var callOnComplete bool
+
+ err = s.walletPool.GetTxPool().SendTransaction(ctx, wallet, tx, &spamoor.SendTransactionOptions{
+ Client: client,
+ Rebroadcast: true,
+ OnComplete: func(tx *types.Transaction, receipt *types.Receipt, err error) {
+ defer func() {
+ mu.Lock()
+ defer mu.Unlock()
+
+ if callOnComplete {
+ onComplete()
+ }
+ }()
+
+ if receipt != nil {
+ s.recordDeployedContract(receipt.ContractAddress, wallet.GetPrivateKey(), receipt, tx.Hash())
+ }
+ },
+ })
+
+ callOnComplete = err == nil
+ if err != nil {
+ return nil, err
+ }
+
+ return tx, nil
+}
diff --git a/scenarios/statebloat/eoa_delegation/README.md b/scenarios/statebloat/eoa_delegation/README.md
new file mode 100644
index 00000000..0a4f5a60
--- /dev/null
+++ b/scenarios/statebloat/eoa_delegation/README.md
@@ -0,0 +1,79 @@
+# EOA Delegation Scenario
+
+## Overview
+
+The EOA Delegation scenario is designed for maximum state bloating through EIP-7702 SetCode transactions. It creates the largest possible state growth by delegating thousands of Externally Owned Accounts (EOAs) to existing contracts in a single block.
+
+This scenario is a specialized stress-testing tool that:
+- Automatically adjusts to fill 99.5% of block gas limit
+- Funds EOAs with 1 wei each before delegation
+- Tracks all funded EOAs in `EOAs.json` for future reference
+- Handles transaction size limits by batching when necessary
+- Continuously operates in a loop, creating maximum state growth
+
+## How It Works
+
+### Three-Phase Operation
+
+1. **Funding Phase**: Pre-funds delegator EOAs with 1 wei each
+2. **Bloating Phase**: Sends SetCode transaction(s) with maximum authorizations
+3. **Analysis Phase**: Measures performance and adjusts parameters
+
+### Key Features
+
+- **Self-Adjusting**: Dynamically adjusts authorization count based on actual gas usage
+- **Network-Aware**: Queries actual block gas limit from the network
+- **Size-Aware**: Automatically splits large transactions that exceed 128KiB limit
+- **Persistent Storage**: Saves all funded EOAs to `EOAs.json` for reuse
+
+### Technical Details
+
+- Each EOA delegation creates ~135 bytes of new state
+- Uses ecrecover precompile (0x1) as default delegation target
+- Targets 99.5% block utilization for maximum impact
+- Handles up to ~1300 authorizations per 128KiB RLP-encoded transaction
+- Transaction size limit: 128KiB (131,072 bytes) applies to the RLP-encoded transaction
+- Actual authorization size in transaction: ~94 bytes per authorization (RLP-encoded)
+
+## Usage
+
+### Basic Usage
+
+```bash
+# Run with default settings (auto-adjusts to network)
+# Address is set to Identity precompile by default.
+eoa-delegation -h -p
+
+# Specify custom delegation target
+eoa-delegation eoa-delegation --code-addr 0x1234567890123456789012345678901234567890
+
+# Control gas prices
+eoa-delegation eoa-delegation --basefee 30 --tipfee 3
+```
+
+### Command Line Options
+
+- `--code-addr`: Contract address to delegate to (default: ecrecover precompile)
+- `--basefee`: Base fee in gwei (default: 20)
+- `--tipfee`: Priority fee in gwei (default: 2)
+- `--client-group`: Specific client group to use
+- `--rebroadcast`: Seconds between transaction rebroadcasts (default: 120)
+
+### Output
+
+The scenario logs detailed metrics for each iteration:
+
+```
+STATE BLOATING METRICS - Total bytes written: 130.5 KiB, Gas used: 25.2M, Block utilization: 98.7%, Authorizations: 990, Gas/auth: 25454.5, Gas/byte: 188.6, Total fee: 0.0504 ETH
+```
+
+## State Impact
+
+This scenario creates maximum state growth by:
+1. Creating new EOA accounts (funded with 1 wei)
+2. Adding delegation records for each EOA
+3. Updating nonce and balance for each account
+
+## Files Created
+
+- `EOAs.json`: Contains addresses and private keys of all funded EOAs
diff --git a/scenarios/statebloat/eoa_delegation/eoa_delegation.go b/scenarios/statebloat/eoa_delegation/eoa_delegation.go
new file mode 100644
index 00000000..43473770
--- /dev/null
+++ b/scenarios/statebloat/eoa_delegation/eoa_delegation.go
@@ -0,0 +1,891 @@
+package sbeoadelegation
+
+import (
+ "context"
+ "crypto/sha256"
+ "encoding/binary"
+ "encoding/json"
+ "fmt"
+ "math/big"
+ "os"
+ "strings"
+ "sync"
+ "sync/atomic"
+ "time"
+
+ "gopkg.in/yaml.v3"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/holiman/uint256"
+ "github.com/sirupsen/logrus"
+ "github.com/spf13/pflag"
+
+ "github.com/ethpandaops/spamoor/scenario"
+ "github.com/ethpandaops/spamoor/spamoor"
+ "github.com/ethpandaops/spamoor/txbuilder"
+)
+
+// EIP-7702 gas cost constants
+const (
+ // PER_AUTH_BASE_COST (EIP-7702) - upper bound on gas cost per authorization when delegating to existing contract in this scenario
+ GasPerAuthorization = 26000
+ // EstimatedBytesPerAuth - estimated state change in bytes per EOA delegation
+ EstimatedBytesPerAuth = 135.0
+ // ActualBytesPerAuth - actual observed RLP-encoded bytes per authorization in transaction
+ // RLP encoding breakdown for typical authorization:
+ // - ChainID: ~3 bytes (RLP encodes integers efficiently, not fixed 8 bytes)
+ // - Address: 21 bytes (0x94 prefix + 20 bytes)
+ // - Nonce: 1 byte (0x80 for nonce 0, small values)
+ // - YParity: 1 byte (0x00 or 0x01)
+ // - R: 33 bytes (0xa0 prefix + 32 bytes)
+ // - S: 33 bytes (0xa0 prefix + 32 bytes)
+ // - List overhead: 2 bytes (0xf8 + length byte)
+ // Total: ~94 bytes (confirmed by empirical data: 89KiB for 969 auths)
+ ActualBytesPerAuth = 94
+ // DefaultTargetGasRatio - target percentage of block gas limit to use (99.5% for minimal safety margin)
+ DefaultTargetGasRatio = 0.995
+ // FallbackBlockGasLimit - fallback gas limit if network query fails
+ FallbackBlockGasLimit = 30000000
+ // BaseTransferCost - gas cost for a standard ETH transfer
+ BaseTransferCost = 21000
+ // MaxTransactionSize - Ethereum transaction size limit in bytes (128KiB)
+ MaxTransactionSize = 131072 // 128 * 1024
+ // GweiPerEth - conversion factor from Gwei to Wei
+ GweiPerEth = 1000000000
+ // BlockMiningTimeout - timeout for waiting for a new block to be mined
+ BlockMiningTimeout = 30 * time.Second
+ // BlockPollingInterval - interval for checking new blocks
+ BlockPollingInterval = 1 * time.Second
+ // MaxRebroadcasts - maximum number of times to rebroadcast a transaction
+ MaxRebroadcasts = 10
+ // TransactionBatchSize - used for batching funding transactions
+ TransactionBatchSize = 100
+ // TransactionBatchThreshold - threshold for continuing to fill a block
+ TransactionBatchThreshold = 50
+ // InitialTransactionDelay - delay between initial funding transactions
+ InitialTransactionDelay = 10 * time.Millisecond
+ // OptimizedTransactionDelay - reduced delay after initial batch
+ OptimizedTransactionDelay = 5 * time.Millisecond
+ // FundingConfirmationDelay - delay before checking funding confirmations
+ FundingConfirmationDelay = 3 * time.Second
+ // RetryDelay - delay before retrying failed operations
+ RetryDelay = 5 * time.Second
+ // FundingIterationOffset - large offset to avoid delegator index conflicts between iterations
+ FundingIterationOffset = 1000000
+ // TransactionBaseOverhead - base RLP encoding overhead for a transaction
+ TransactionBaseOverhead = 200
+ // TransactionExtraOverhead - additional RLP encoding overhead
+ TransactionExtraOverhead = 50
+ // GasPerCallDataByte - gas cost per byte of calldata (16 gas per non-zero byte)
+ GasPerCallDataByte = 16
+ // BytesPerKiB - bytes in a kibibyte
+ BytesPerKiB = 1024.0
+ // GasPerMillion - divisor for converting gas to millions
+ GasPerMillion = 1_000_000.0
+ // TransactionSizeSafetyFactor - safety factor for transaction size (95%)
+ TransactionSizeSafetyFactor = 95
+)
+
+type ScenarioOptions struct {
+ BaseFee uint64 `yaml:"base_fee"`
+ TipFee uint64 `yaml:"tip_fee"`
+ CodeAddr string `yaml:"code_addr"`
+ EoaFile string `yaml:"eoa_file"`
+ LogTxs bool `yaml:"log_txs"`
+}
+
+// EOAEntry represents a funded EOA account
+type EOAEntry struct {
+ Address string `json:"address"`
+ PrivateKey string `json:"private_key"`
+}
+
+type Scenario struct {
+ options ScenarioOptions
+ logger *logrus.Entry
+ walletPool *spamoor.WalletPool
+
+ // FIFO queue for funded accounts
+ eoaQueue []EOAEntry
+ eoaQueueMutex sync.Mutex
+}
+
+var ScenarioName = "statebloat-eoa-delegation"
+var ScenarioDefaultOptions = ScenarioOptions{
+ BaseFee: 20,
+ TipFee: 2,
+ CodeAddr: "",
+ EoaFile: "",
+ LogTxs: false,
+}
+var ScenarioDescriptor = scenario.Descriptor{
+ Name: ScenarioName,
+ Description: "Maximum state bloating via EIP-7702 EOA delegations",
+ DefaultOptions: ScenarioDefaultOptions,
+ NewScenario: newScenario,
+}
+
+func newScenario(logger logrus.FieldLogger) scenario.Scenario {
+ return &Scenario{
+ logger: logger.WithField("scenario", ScenarioName),
+ }
+}
+
+func (s *Scenario) Flags(flags *pflag.FlagSet) error {
+ flags.Uint64Var(&s.options.BaseFee, "basefee", ScenarioDefaultOptions.BaseFee, "Max fee per gas to use in transactions (in gwei)")
+ flags.Uint64Var(&s.options.TipFee, "tipfee", ScenarioDefaultOptions.TipFee, "Max tip per gas to use in transactions (in gwei)")
+ flags.StringVar(&s.options.CodeAddr, "code-addr", ScenarioDefaultOptions.CodeAddr, "Code delegation target address to use for transactions (default: ecrecover precompile)")
+ flags.StringVar(&s.options.EoaFile, "eoa-file", ScenarioDefaultOptions.EoaFile, "File to write EOAs to")
+ flags.BoolVar(&s.options.LogTxs, "log-txs", ScenarioDefaultOptions.LogTxs, "Log transactions")
+ return nil
+}
+
+func (s *Scenario) Init(options *scenario.Options) error {
+ s.walletPool = options.WalletPool
+
+ if options.Config != "" {
+ err := yaml.Unmarshal([]byte(options.Config), &s.options)
+ if err != nil {
+ return fmt.Errorf("failed to unmarshal config: %w", err)
+ }
+ }
+
+ if s.options.CodeAddr == "" {
+ s.logger.Infof("no --code-addr specified, using ecrecover precompile as delegate: %s", common.HexToAddress("0x0000000000000000000000000000000000000001"))
+ }
+
+ // In max-bloating mode, use 100 wallets for funding delegators
+ s.walletPool.SetWalletCount(100)
+ s.walletPool.SetRefillAmount(uint256.NewInt(0).Mul(uint256.NewInt(20), uint256.NewInt(1000000000000000000))) // 20 ETH
+ s.walletPool.SetRefillBalance(uint256.NewInt(0).Mul(uint256.NewInt(10), uint256.NewInt(1000000000000000000))) // 10 ETH
+
+ // register well known wallets
+ s.walletPool.AddWellKnownWallet(&spamoor.WellKnownWalletConfig{
+ Name: "bloater",
+ RefillAmount: uint256.NewInt(0).Mul(uint256.NewInt(20), uint256.NewInt(1000000000000000000)), // 20 ETH
+ RefillBalance: uint256.NewInt(0).Mul(uint256.NewInt(10), uint256.NewInt(1000000000000000000)), // 10 ETH
+ })
+
+ // Initialize FIFO queue and worker for EOA management
+ s.eoaQueue = make([]EOAEntry, 0)
+
+ return nil
+}
+
+func (s *Scenario) Config() string {
+ yamlBytes, _ := yaml.Marshal(&s.options)
+ return string(yamlBytes)
+}
+
+func (s *Scenario) prepareDelegator(delegatorIndex uint64) (*spamoor.Wallet, error) {
+ delegatorSeed := make([]byte, 8)
+ binary.BigEndian.PutUint64(delegatorSeed, delegatorIndex)
+ delegatorSeed = append(delegatorSeed, s.walletPool.GetWalletSeed()...)
+ delegatorSeed = append(delegatorSeed, s.walletPool.GetRootWallet().GetWallet().GetAddress().Bytes()...)
+ childKey := sha256.Sum256(delegatorSeed)
+ return spamoor.NewWallet(fmt.Sprintf("%x", childKey))
+}
+
+func (s *Scenario) Run(ctx context.Context) error {
+ s.logger.Infof("starting max bloating mode: self-adjusting to target block gas limit, continuous operation")
+
+ go s.eoaWorker(ctx)
+
+ // Get the actual network block gas limit
+ networkGasLimit, err := s.walletPool.GetTxPool().GetCurrentGasLimitWithInit()
+ if err != nil {
+ s.logger.Errorf("failed to get current gas limit: %v", err)
+ return err
+ }
+
+ targetGas := uint64(float64(networkGasLimit) * DefaultTargetGasRatio)
+
+ // Calculate initial authorization count based on network gas limit and known gas cost per authorization
+ initialAuthorizations := int(targetGas / GasPerAuthorization)
+
+ // Dynamic authorization count - starts based on network parameters and adjusts based on actual performance
+ currentAuthorizations := initialAuthorizations
+
+ var blockCounter int
+
+ for {
+ select {
+ case <-ctx.Done():
+ s.logger.Errorf("max bloating mode stopping due to context cancellation")
+ return ctx.Err()
+ default:
+ }
+
+ blockCounter++
+
+ // For the first iteration, we need to fund delegators before bloating
+ // For subsequent iterations, funding happens after analysis
+ if blockCounter == 1 {
+ s.logger.Infof("ββββββββββββββββ INITIAL FUNDING PHASE ββββββββββββββββ")
+ _, err := s.fundMaxBloatingDelegators(ctx, currentAuthorizations, blockCounter, networkGasLimit)
+ if err != nil {
+ s.logger.Errorf("failed to fund delegators for initial iteration: %v", err)
+ time.Sleep(RetryDelay) // Wait before retry
+ blockCounter-- // Retry the same iteration
+ continue
+ }
+ }
+
+ // Send the max bloating transaction and wait for confirmation
+ s.logger.Infof("ββββββββββββββββ BLOATING PHASE #%d ββββββββββββββββ", blockCounter)
+ actualGasUsed, _, authCount, gasPerAuth, gasPerByte, _, err := s.sendMaxBloatingTransaction(ctx, currentAuthorizations, targetGas, blockCounter)
+ if err != nil {
+ s.logger.Errorf("failed to send max bloating transaction for iteration %d: %v", blockCounter, err)
+ time.Sleep(RetryDelay) // Wait before retry
+ continue
+ }
+
+ s.logger.Infof("%%%%%%%%%%%%%%%%%%%% ANALYSIS PHASE #%d %%%%%%%%%%%%%%%%%%%%", blockCounter)
+
+ // Calculate total bytes written to state
+ totalBytesWritten := authCount * int(EstimatedBytesPerAuth)
+
+ // Get block gas limit for utilization calculation
+ blockGasLimit := float64(networkGasLimit)
+ gasUtilization := (float64(actualGasUsed) / blockGasLimit) * 100
+
+ s.logger.WithField("scenario", "eoa-delegation").Infof("STATE BLOATING METRICS - Total bytes written: %.2f KiB, Gas used: %.2fM, Block utilization: %.2f%%, Authorizations: %d, Gas/auth: %.1f, Gas/byte: %.1f",
+ float64(totalBytesWritten)/BytesPerKiB, float64(actualGasUsed)/GasPerMillion, gasUtilization, authCount, gasPerAuth, gasPerByte)
+
+ // Self-adjust authorization count based on actual performance
+ if actualGasUsed > 0 && authCount > 0 {
+ gasPerAuth := float64(actualGasUsed) / float64(authCount)
+ targetAuths := int(float64(targetGas) / gasPerAuth)
+
+ // Calculate the adjustment needed
+ authDifference := targetAuths - authCount
+
+ if actualGasUsed < targetGas {
+ // We're under target, increase authorization count with a slight safety margin
+ newAuthorizations := currentAuthorizations + authDifference - 1
+
+ if newAuthorizations > currentAuthorizations {
+ s.logger.Infof("Adjusting authorizations: %d β %d (need %d more for target)",
+ currentAuthorizations, newAuthorizations, authDifference)
+ currentAuthorizations = newAuthorizations
+ }
+ } else if actualGasUsed > targetGas {
+ // We're over target, reduce to reach max block utilization
+ excess := actualGasUsed - targetGas
+ newAuthorizations := currentAuthorizations - int(excess) + 1
+
+ s.logger.Infof("Reducing authorizations: %d β %d (excess: %d gas)",
+ currentAuthorizations, newAuthorizations, excess)
+ currentAuthorizations = newAuthorizations
+
+ } else {
+ s.logger.Infof("Target achieved! Gas Used: %d / Target: %d", actualGasUsed, targetGas)
+ }
+ }
+
+ // Now fund delegators for the next iteration (except on the last iteration)
+ // This ensures funding happens AFTER bloating transactions are confirmed
+ s.logger.Infof("ββββββββββββββββ FUNDING PHASE #%d (for next iteration) ββββββββββββββββ", blockCounter)
+ _, err = s.fundMaxBloatingDelegators(ctx, currentAuthorizations, blockCounter+1, networkGasLimit)
+ if err != nil {
+ s.logger.Errorf("failed to fund delegators for next iteration: %v", err)
+ // Don't fail the entire loop, just log the error and continue
+ }
+ }
+}
+
+func (s *Scenario) fundMaxBloatingDelegators(ctx context.Context, targetCount int, iteration int, gasLimit uint64) (int64, error) {
+ client := s.walletPool.GetClient(spamoor.SelectClientByIndex, 0, "")
+ if client == nil {
+ return 0, fmt.Errorf("no client available for funding delegators")
+ }
+
+ // Get suggested fees for funding transactions
+ feeCap, tipCap, err := s.walletPool.GetTxPool().GetSuggestedFees(client, s.options.BaseFee, s.options.TipFee)
+ if err != nil {
+ return 0, fmt.Errorf("failed to get suggested fees for funding: %w", err)
+ }
+
+ // Fund with 1 wei as requested by user
+ fundingAmount := uint256.NewInt(1)
+
+ var confirmedCount int64
+
+ delegatorIndexBase := uint64(iteration * FundingIterationOffset) // Large offset per iteration to avoid conflicts
+
+ fundNextDelegator := func(ctx context.Context, txIdx uint64, onComplete func()) (*types.Transaction, *spamoor.Client, *spamoor.Wallet, error) {
+ wallet := s.walletPool.GetWallet(spamoor.SelectWalletByIndex, int(txIdx))
+ if wallet == nil {
+ return nil, nil, nil, fmt.Errorf("no wallet available for funding")
+ }
+
+ client := s.walletPool.GetClient(spamoor.SelectClientByIndex, 0, "")
+ if client == nil {
+ return nil, nil, nil, fmt.Errorf("no client available for funding delegators")
+ }
+
+ delegatorIndex := delegatorIndexBase + txIdx
+ transactionSubmitted := false
+
+ defer func() {
+ if !transactionSubmitted {
+ onComplete()
+ }
+ }()
+
+ delegator, err := s.prepareDelegator(delegatorIndex)
+ if err != nil {
+ s.logger.Errorf("could not prepare delegator %v for funding: %v", delegatorIndex, err)
+ return nil, nil, nil, err
+ }
+
+ // Build funding transaction
+ delegatorAddr := delegator.GetAddress()
+ txData, err := txbuilder.DynFeeTx(&txbuilder.TxMetadata{
+ GasFeeCap: uint256.MustFromBig(feeCap),
+ GasTipCap: uint256.MustFromBig(tipCap),
+ Gas: BaseTransferCost, // Standard ETH transfer gas
+ To: &delegatorAddr,
+ Value: fundingAmount,
+ Data: []byte{},
+ })
+ if err != nil {
+ s.logger.Errorf("failed to build funding tx for delegator %d: %v", delegatorIndex, err)
+ return nil, nil, nil, err
+ }
+
+ tx, err := wallet.BuildDynamicFeeTx(txData)
+ if err != nil {
+ s.logger.Errorf("failed to build funding transaction for delegator %d: %v", delegatorIndex, err)
+ return nil, nil, nil, err
+ }
+
+ // Send funding transaction with no retries to avoid duplicates
+ transactionSubmitted = true
+ err = s.walletPool.GetTxPool().SendTransaction(ctx, wallet, tx, &spamoor.SendTransactionOptions{
+ Client: client,
+ Rebroadcast: false, // No retries to avoid duplicates
+ OnComplete: func(tx *types.Transaction, receipt *types.Receipt, err error) {
+ defer onComplete()
+
+ if err != nil {
+ return // Don't log individual failures
+ }
+ if receipt != nil && receipt.Status == 1 {
+ atomic.AddInt64(&confirmedCount, 1)
+
+ // Add successfully funded delegator to EOA queue
+ s.addEOAToQueue(delegator.GetAddress().Hex(), fmt.Sprintf("%x", delegator.GetPrivateKey().D))
+
+ // No progress logging - only log when target is reached
+ }
+ },
+ LogFn: func(client *spamoor.Client, retry int, rebroadcast int, err error) {
+ // Only log actual send failures, not confirmation failures
+ if err != nil {
+ s.logger.Debugf("funding tx send failed: %v", err)
+ }
+ },
+ })
+
+ return tx, client, wallet, err
+ }
+
+ // Calculate approximate transactions per block based on gas limit
+ // Standard transfer = BaseTransferCost gas.
+ maxTxsPerBlock := gasLimit / uint64(BaseTransferCost)
+
+ scenario.RunTransactionScenario(ctx, scenario.TransactionScenarioOptions{
+ TotalCount: uint64(targetCount),
+ Throughput: maxTxsPerBlock * 2,
+ MaxPending: maxTxsPerBlock * 2,
+ WalletPool: s.walletPool,
+ Logger: s.logger,
+ ProcessNextTxFn: func(ctx context.Context, txIdx uint64, onComplete func()) (func(), error) {
+ logger := s.logger
+ tx, client, wallet, err := fundNextDelegator(ctx, txIdx, onComplete)
+ if client != nil {
+ logger = logger.WithField("rpc", client.GetName())
+ }
+ if tx != nil {
+ logger = logger.WithField("nonce", tx.Nonce())
+ }
+ if wallet != nil {
+ logger = logger.WithField("wallet", s.walletPool.GetWalletName(wallet.GetAddress()))
+ }
+
+ return func() {
+ if err != nil {
+ logger.Warnf("could not send transaction: %v", err)
+ } else if s.options.LogTxs {
+ logger.Infof("sent tx #%6d: %v", txIdx+1, tx.Hash().String())
+ } else {
+ logger.Debugf("sent tx #%6d: %v", txIdx+1, tx.Hash().String())
+ }
+ }, err
+ },
+ })
+
+ // Return the confirmed count
+ confirmed := atomic.LoadInt64(&confirmedCount)
+ return confirmed, nil
+}
+
+func (s *Scenario) sendMaxBloatingTransaction(ctx context.Context, targetAuthorizations int, targetGasLimit uint64, blockCounter int) (uint64, string, int, float64, float64, string, error) {
+ client := s.walletPool.GetClient(spamoor.SelectClientByIndex, 0, "")
+ if client == nil {
+ return 0, "", 0, 0, 0, "", fmt.Errorf("no client available for sending max bloating transaction")
+ }
+
+ // Use bloater wallet
+ wallet := s.walletPool.GetWellKnownWallet("bloater")
+ if wallet == nil {
+ return 0, "", 0, 0, 0, "", fmt.Errorf("no bloater wallet available")
+ }
+
+ // Get suggested fees or use configured values
+ feeCap, tipCap, err := s.walletPool.GetTxPool().GetSuggestedFees(client, s.options.BaseFee, s.options.TipFee)
+ if err != nil {
+ return 0, "", 0, 0, 0, "", fmt.Errorf("failed to get suggested fees for max bloating: %w", err)
+ }
+
+ // Use minimal amount for max bloating (focus on authorizations, not value transfer)
+ amount := uint256.NewInt(0) // No value transfer needed
+
+ // Target address - use our own wallet for simplicity
+ toAddr := wallet.GetAddress()
+
+ // No call data for max bloating transactions
+ txCallData := []byte{}
+
+ // Build the authorizations for maximum state bloat
+ authorizations := s.buildMaxBloatingAuthorizations(targetAuthorizations, blockCounter)
+
+ // Check transaction size and split into batches if needed
+ batches := s.splitAuthorizationsBatches(authorizations, len(txCallData))
+
+ if len(batches) == 1 {
+ // Single transaction - use existing logic
+ return s.sendSingleMaxBloatingTransaction(ctx, batches[0], txCallData, feeCap, tipCap, amount, toAddr, targetGasLimit, wallet, client)
+ } else {
+ // Multiple transactions needed - send them as a batch
+ return s.sendBatchedMaxBloatingTransactions(ctx, batches, txCallData, feeCap, tipCap, amount, toAddr, targetGasLimit, wallet, client)
+ }
+}
+
+// buildMaxBloatingAuthorizations builds the authorizations for the max bloating transaction
+func (s *Scenario) buildMaxBloatingAuthorizations(targetCount int, iteration int) []types.SetCodeAuthorization {
+ authorizations := make([]types.SetCodeAuthorization, 0, targetCount)
+
+ // Use a fixed delegate contract address for maximum efficiency
+ // In max bloating mode, we want all EOAs to delegate to the same existing contract
+ // to benefit from reduced gas costs (PER_AUTH_BASE_COST vs PER_EMPTY_ACCOUNT_COST)
+ // Precompiles are ideal as they're guaranteed to exist with code on all networks
+ var codeAddr common.Address
+ if s.options.CodeAddr != "" {
+ codeAddr = common.HexToAddress(s.options.CodeAddr)
+ } else {
+ // Default to using the ecrecover precompile (0x1) as delegate target
+ codeAddr = common.HexToAddress("0x0000000000000000000000000000000000000001")
+ }
+
+ chainId := s.walletPool.GetChainId()
+
+ for i := 0; i < targetCount; i++ {
+ // Create a unique delegator for each authorization
+ // Include iteration counter to ensure different addresses for each iteration
+ delegatorIndex := uint64(iteration*targetCount + i)
+
+ delegator, err := s.prepareDelegator(delegatorIndex)
+ if err != nil {
+ s.logger.Errorf("could not prepare delegator %v: %v", delegatorIndex, err)
+ continue
+ }
+
+ // Each EOA uses auth_nonce = 0 (assuming first EIP-7702 operation)
+ // This creates maximum new state as each EOA gets its first delegation
+ authorization := types.SetCodeAuthorization{
+ ChainID: *uint256.MustFromBig(chainId),
+ Address: codeAddr,
+ Nonce: 0, // First delegation for each EOA
+ }
+
+ // Sign the authorization with the delegator's private key
+ signedAuth, err := types.SignSetCode(delegator.GetPrivateKey(), authorization)
+ if err != nil {
+ s.logger.Errorf("could not sign set code authorization for delegator %v: %v", delegatorIndex, err)
+ continue
+ }
+
+ authorizations = append(authorizations, signedAuth)
+ }
+
+ return authorizations
+}
+
+// splitAuthorizationsBatches splits authorizations into batches that fit within transaction size limit
+func (s *Scenario) splitAuthorizationsBatches(authorizations []types.SetCodeAuthorization, callDataSize int) [][]types.SetCodeAuthorization {
+ if len(authorizations) == 0 {
+ return [][]types.SetCodeAuthorization{authorizations}
+ }
+
+ // To get closer to 128KiB limit, we need to adjust our estimate
+ // Using a safety factor of 0.95 to stay just under the limit
+ targetSize := MaxTransactionSize * TransactionSizeSafetyFactor / 100 // Safety margin
+
+ maxAuthsPerTx := (targetSize - TransactionBaseOverhead - callDataSize) / ActualBytesPerAuth
+ if maxAuthsPerTx <= 0 {
+ s.logger.Warnf("Transaction call data too large, using minimal batch size of 1")
+ maxAuthsPerTx = 1
+ }
+
+ // If all authorizations fit in one transaction, return as single batch
+ if len(authorizations) <= maxAuthsPerTx {
+ estimatedSize := s.calculateTransactionSize(len(authorizations), callDataSize)
+ s.logger.Infof("All %d authorizations fit in single transaction (estimated size: %d bytes)", len(authorizations), estimatedSize)
+ return [][]types.SetCodeAuthorization{authorizations}
+ }
+
+ // Split into multiple batches
+ var batches [][]types.SetCodeAuthorization
+ for i := 0; i < len(authorizations); i += maxAuthsPerTx {
+ end := i + maxAuthsPerTx
+ if end > len(authorizations) {
+ end = len(authorizations)
+ }
+ batch := authorizations[i:end]
+ batches = append(batches, batch)
+ }
+
+ s.logger.Infof("Split %d authorizations into %d batches (max %d auths per batch, target size: %.2f KiB)",
+ len(authorizations), len(batches), maxAuthsPerTx, float64(targetSize)/BytesPerKiB)
+ return batches
+}
+
+// calculateTransactionSize estimates the serialized size of a transaction with given authorizations
+func (s *Scenario) calculateTransactionSize(authCount int, callDataSize int) int {
+ // Estimation based on empirical data and RLP encoding structure:
+ // - Base transaction overhead: ~200 bytes
+ // - Each SetCodeAuthorization: ~94 bytes (based on actual observed data)
+ // - Call data: variable size
+ // - Additional RLP encoding overhead: ~50 bytes
+
+ baseSize := TransactionBaseOverhead + callDataSize + TransactionExtraOverhead
+ authSize := authCount * ActualBytesPerAuth
+ return baseSize + authSize
+}
+
+// sendSingleMaxBloatingTransaction sends a single transaction (original logic)
+func (s *Scenario) sendSingleMaxBloatingTransaction(ctx context.Context, authorizations []types.SetCodeAuthorization, txCallData []byte, feeCap, tipCap *big.Int, amount *uint256.Int, toAddr common.Address, targetGasLimit uint64, wallet *spamoor.Wallet, client *spamoor.Client) (uint64, string, int, float64, float64, string, error) {
+ txData, err := txbuilder.SetCodeTx(&txbuilder.TxMetadata{
+ GasFeeCap: uint256.MustFromBig(feeCap),
+ GasTipCap: uint256.MustFromBig(tipCap),
+ Gas: targetGasLimit,
+ To: &toAddr,
+ Value: amount,
+ Data: txCallData,
+ AuthList: authorizations,
+ })
+ if err != nil {
+ return 0, "", 0, 0, 0, "", fmt.Errorf("failed to build transaction metadata: %w", err)
+ }
+
+ tx, err := wallet.BuildSetCodeTx(txData)
+ if err != nil {
+ return 0, "", 0, 0, 0, "", fmt.Errorf("failed to build transaction: %w", err)
+ }
+
+ // Log actual transaction size
+ txSize := len(tx.Data())
+ if encoded, err := tx.MarshalBinary(); err == nil {
+ txSize = len(encoded)
+ }
+ sizeKiB := float64(txSize) / BytesPerKiB
+ exceedsLimit := txSize > MaxTransactionSize
+ limitKiB := float64(MaxTransactionSize) / BytesPerKiB
+
+ s.logger.WithField("scenario", "eoa-delegation").Infof("MAX BLOATING TX SIZE: %d bytes (%.2f KiB) | Limit: %d bytes (%.1f KiB) | %d authorizations | Exceeds limit: %v",
+ txSize, sizeKiB, MaxTransactionSize, limitKiB, len(authorizations), exceedsLimit)
+
+ // Send the transaction
+ txreceipt, txerr := s.walletPool.GetTxPool().SendAndAwaitTransaction(ctx, wallet, tx, &spamoor.SendTransactionOptions{
+ Client: client,
+ Rebroadcast: true,
+ LogFn: spamoor.GetDefaultLogFn(s.logger, "max bloating", "", tx),
+ })
+
+ if txerr != nil {
+ return 0, "", 0, 0, 0, "", fmt.Errorf("failed to send max bloating transaction: %w", txerr)
+ }
+
+ if txreceipt == nil {
+ return 0, "", 0, 0, 0, "", fmt.Errorf("no receipt received")
+ }
+
+ effectiveGasPrice := txreceipt.EffectiveGasPrice
+ if effectiveGasPrice == nil {
+ effectiveGasPrice = big.NewInt(0)
+ }
+ feeAmount := new(big.Int).Mul(effectiveGasPrice, big.NewInt(int64(txreceipt.GasUsed)))
+ totalAmount := new(big.Int).Add(tx.Value(), feeAmount)
+ wallet.SubBalance(totalAmount)
+
+ gweiTotalFee := new(big.Int).Div(feeAmount, big.NewInt(1000000000))
+
+ // Calculate efficiency metrics
+ authCount := len(authorizations)
+ gasPerAuth := float64(txreceipt.GasUsed) / float64(authCount)
+ gasPerByte := gasPerAuth / EstimatedBytesPerAuth
+
+ return txreceipt.GasUsed, txreceipt.BlockNumber.String(), authCount, gasPerAuth, gasPerByte, gweiTotalFee.String(), nil
+}
+
+// sendBatchedMaxBloatingTransactions sends multiple transactions when size limit is exceeded
+func (s *Scenario) sendBatchedMaxBloatingTransactions(ctx context.Context, batches [][]types.SetCodeAuthorization, txCallData []byte, feeCap, tipCap *big.Int, amount *uint256.Int, toAddr common.Address, targetGasLimit uint64, wallet *spamoor.Wallet, client *spamoor.Client) (uint64, string, int, float64, float64, string, error) {
+ // Aggregate results
+ var totalGasUsed uint64
+ var totalAuthCount int
+ var totalFees *big.Int = big.NewInt(0)
+ var lastBlockNumber string
+
+ // Create result channels for all batches upfront
+ wg := sync.WaitGroup{}
+ wg.Add(len(batches))
+
+ txreceipts := make([]*types.Receipt, len(batches))
+ txerrs := make([]error, len(batches))
+
+ // Send all batches quickly with minimal delay to increase chance of same block inclusion
+ for batchIndex, batch := range batches {
+
+ err := func(batchIndex int, batch []types.SetCodeAuthorization) error {
+ // Calculate appropriate gas limit for this batch based on authorization count
+ // Each authorization needs ~26000 gas, plus some overhead for the transaction itself
+ batchGasLimit := uint64(len(batch))*GasPerAuthorization + BaseTransferCost + uint64(len(txCallData)*GasPerCallDataByte)
+
+ // Ensure we don't exceed the target limit per transaction
+ maxGasPerTx := targetGasLimit
+ if batchGasLimit > maxGasPerTx {
+ batchGasLimit = maxGasPerTx
+ }
+
+ // Build the transaction for this batch
+ txData, err := txbuilder.SetCodeTx(&txbuilder.TxMetadata{
+ GasFeeCap: uint256.MustFromBig(feeCap),
+ GasTipCap: uint256.MustFromBig(tipCap),
+ Gas: batchGasLimit,
+ To: &toAddr,
+ Value: amount,
+ Data: txCallData,
+ AuthList: batch,
+ })
+ if err != nil {
+ return fmt.Errorf("failed to build batch %d transaction metadata: %w", batchIndex+1, err)
+ }
+
+ tx, err := wallet.BuildSetCodeTx(txData)
+ if err != nil {
+ return fmt.Errorf("failed to build batch %d transaction: %w", batchIndex+1, err)
+ }
+
+ // Send the transaction immediately without waiting for confirmation
+ err = s.walletPool.GetTxPool().SendTransaction(ctx, wallet, tx, &spamoor.SendTransactionOptions{
+ Client: client,
+ Rebroadcast: true,
+ OnComplete: func(tx *types.Transaction, receipt *types.Receipt, err error) {
+ txreceipts[batchIndex] = receipt
+ txerrs[batchIndex] = err
+ wg.Done()
+ },
+ LogFn: func(client *spamoor.Client, retry int, rebroadcast int, err error) {
+ logger := s.logger.WithField("rpc", client.GetName())
+ if err != nil {
+ logger.Errorf("failed sending batch %d tx: %v", batchIndex+1, err)
+ } else if retry > 0 || rebroadcast > 0 {
+ logger.Debugf("successfully sent batch %d tx (retry/rebroadcast)", batchIndex+1)
+ }
+ },
+ })
+
+ if err != nil {
+ wallet.ResetPendingNonce(ctx, client)
+ return fmt.Errorf("failed to send batch %d transaction: %w", batchIndex+1, err)
+ }
+
+ return nil
+ }(batchIndex, batch)
+
+ if err != nil {
+ return 0, "", 0, 0, 0, "", fmt.Errorf("failed to send batch %d transaction: %w", batchIndex+1, err)
+ }
+ }
+
+ // Now wait for all batch confirmations
+ wg.Wait()
+
+ blockNumbers := make(map[string]int) // Track which blocks contain our transactions
+ batchDetails := make([]string, len(batches)) // Store details of each batch
+ for batchIndex := range batches {
+ if txerrs[batchIndex] != nil {
+ return 0, "", 0, 0, 0, "", fmt.Errorf("batch %d failed: %w", batchIndex+1, txerrs[batchIndex])
+ }
+
+ txreceipt := txreceipts[batchIndex]
+ if txreceipt == nil {
+ return 0, "", 0, 0, 0, "", fmt.Errorf("batch %d: no receipt received", batchIndex+1)
+ }
+
+ effectiveGasPrice := txreceipt.EffectiveGasPrice
+ if effectiveGasPrice == nil {
+ effectiveGasPrice = big.NewInt(0)
+ }
+ feeAmount := new(big.Int).Mul(effectiveGasPrice, big.NewInt(int64(txreceipt.GasUsed)))
+
+ gweiTotalFee := new(big.Int).Div(feeAmount, big.NewInt(GweiPerEth))
+
+ // Aggregate successful results
+ totalGasUsed += txreceipt.GasUsed
+ totalAuthCount += len(batches[batchIndex])
+ lastBlockNumber = txreceipt.BlockNumber.String()
+
+ // Track block numbers
+ blockNumbers[txreceipt.BlockNumber.String()]++
+
+ // Parse and add fee
+ totalFees.Add(totalFees, gweiTotalFee)
+
+ // Store batch details
+ batchGasInM := float64(txreceipt.GasUsed) / GasPerMillion
+ gasPerAuthBatch := float64(txreceipt.GasUsed) / float64(len(batches[batchIndex]))
+ gasPerByteBatch := gasPerAuthBatch / EstimatedBytesPerAuth
+
+ // Calculate tx size based on authorizations
+ txSize := s.calculateTransactionSize(len(batches[batchIndex]), len(txCallData))
+ sizeKiB := float64(txSize) / BytesPerKiB
+
+ batchDetails[batchIndex] = fmt.Sprintf("Batch %d/%d: %.2fM gas, %d auths, %.2f KiB, %.2f gas/auth, %.2f gas/byte, (block %s)",
+ batchIndex+1, len(batches), batchGasInM, len(batches[batchIndex]), sizeKiB, gasPerAuthBatch, gasPerByteBatch, txreceipt.BlockNumber.String())
+ }
+
+ // Calculate aggregate metrics
+ gasPerAuth := float64(totalGasUsed) / float64(totalAuthCount)
+ gasPerByte := gasPerAuth / EstimatedBytesPerAuth
+ totalGasInM := float64(totalGasUsed) / GasPerMillion
+
+ // Build block distribution summary
+ var blockDistribution strings.Builder
+ for blockNum, txCount := range blockNumbers {
+ if blockDistribution.Len() > 0 {
+ blockDistribution.WriteString(", ")
+ }
+ blockDistribution.WriteString(fmt.Sprintf("Block #%s: %d tx", blockNum, txCount))
+ }
+
+ // Create comprehensive summary log with decorative border
+ s.logger.WithField("scenario", "eoa-delegation").Infof(`ββββββββββββββββ BATCHED MAX BLOATING SUMMARY ββββββββββββββββ
+Individual Batches:
+%s
+
+Block Distribution: %s
+
+Aggregate Metrics:
+- Total Gas Used: %.2fM
+- Total Authorizations: %d
+- Gas per Auth: %.2f
+- Gas per Byte: %.2f`,
+ strings.Join(batchDetails, "\n"),
+ blockDistribution.String(),
+ totalGasInM,
+ totalAuthCount,
+ gasPerAuth,
+ gasPerByte)
+
+ return totalGasUsed, lastBlockNumber, totalAuthCount, gasPerAuth, gasPerByte, totalFees.String(), nil
+}
+
+// eoaWorker runs in a separate goroutine and writes funded EOAs to EOAs.json
+func (s *Scenario) eoaWorker(ctx context.Context) {
+ for {
+ select {
+ case <-ctx.Done():
+ // Shutdown signal received
+ return
+ case <-time.After(30 * time.Second): // flush every 30 seconds
+ s.processEOAQueue()
+ }
+ }
+}
+
+// processEOAQueue drains the EOA queue and writes entries to EOAs.json
+func (s *Scenario) processEOAQueue() {
+ // Check if there are items in the queue
+ s.eoaQueueMutex.Lock()
+ if len(s.eoaQueue) == 0 {
+ s.eoaQueueMutex.Unlock()
+ return // Queue is empty, exit processing
+ }
+
+ // Dequeue all items (FIFO)
+ eoasToWrite := make([]EOAEntry, len(s.eoaQueue))
+ copy(eoasToWrite, s.eoaQueue)
+ s.eoaQueue = s.eoaQueue[:0] // Clear the queue
+ s.eoaQueueMutex.Unlock()
+
+ if s.options.EoaFile != "" {
+ // Write to file
+ err := s.writeEOAsToFile(eoasToWrite)
+ if err != nil {
+ s.logger.Errorf("failed to write EOAs to file: %v", err)
+ // Re-queue the items if write failed
+ s.eoaQueueMutex.Lock()
+ s.eoaQueue = append(eoasToWrite, s.eoaQueue...)
+ s.eoaQueueMutex.Unlock()
+ return
+ }
+ }
+}
+
+// writeEOAsToFile appends EOA entries to EOAs.json file
+func (s *Scenario) writeEOAsToFile(eoas []EOAEntry) error {
+ if len(eoas) == 0 {
+ return nil
+ }
+
+ fileName := "EOAs.json"
+
+ // Read existing entries if file exists
+ var existingEntries []EOAEntry
+ if data, err := os.ReadFile(fileName); err == nil {
+ json.Unmarshal(data, &existingEntries)
+ }
+
+ // Append new entries
+ allEntries := append(existingEntries, eoas...)
+
+ // Write back to file
+ data, err := json.MarshalIndent(allEntries, "", " ")
+ if err != nil {
+ return fmt.Errorf("failed to marshal EOA entries: %w", err)
+ }
+
+ err = os.WriteFile(fileName, data, 0644)
+ if err != nil {
+ return fmt.Errorf("failed to write EOAs.json: %w", err)
+ }
+
+ return nil
+}
+
+// addEOAToQueue adds a funded EOA to the queue
+func (s *Scenario) addEOAToQueue(address, privateKey string) {
+ s.eoaQueueMutex.Lock()
+ defer s.eoaQueueMutex.Unlock()
+
+ entry := EOAEntry{
+ Address: address,
+ PrivateKey: privateKey,
+ }
+
+ s.eoaQueue = append(s.eoaQueue, entry)
+}
diff --git a/scenarios/statebloat/erc20_max_transfers/README.md b/scenarios/statebloat/erc20_max_transfers/README.md
new file mode 100644
index 00000000..2767073b
--- /dev/null
+++ b/scenarios/statebloat/erc20_max_transfers/README.md
@@ -0,0 +1,81 @@
+# ERC20 Max Transfers Scenario
+
+This scenario maximizes the number of ERC20 token transfers per block to unique recipient addresses, creating state bloat through new account storage entries.
+
+## Overview
+
+The scenario uses deployed StateBloatToken contracts from `deployments.json` to send the maximum possible number of ERC20 transfers per block. Each transfer sends 1 token to a unique, never-before-used address, maximizing state growth.
+
+## Features
+
+- **Dynamic Block Gas Limit**: Fetches the actual network block gas limit before starting
+- **Self-Adjusting Transfer Count**: Automatically adjusts the number of transfers based on actual gas usage
+- **Unique Recipients**: Generates deterministic unique addresses for each transfer
+- **Minimum Gas Fees**: Uses configured minimum gas fees (default: 10 gwei base, 5 gwei tip)
+- **Round-Robin Contract Usage**: Distributes transfers across multiple deployed contracts
+- **Recipient Tracking**: Saves all recipient addresses to `recipients.json` for analysis
+
+## Configuration
+
+### Command Line Flags
+
+- `--basefee`: Max fee per gas in gwei (default: 10)
+- `--tipfee`: Max tip per gas in gwei (default: 5)
+- `--contract`: Specific contract address to use (default: rotate through all)
+
+## How It Works
+
+1. **Initialization**:
+ - Loads deployed contracts and private key from `deployments.json`
+ - Sets up the deployer wallet (which holds all tokens)
+ - Fetches network block gas limit
+
+2. **Transfer Phase**:
+ - Calculates optimal transfer count based on gas limit
+ - Generates unique recipient addresses deterministically
+ - Sends transfers in batches with minimal delays
+ - Uses round-robin contract selection
+
+3. **Analysis Phase**:
+ - Tracks confirmed transfers and gas usage
+ - Calculates actual gas per transfer
+ - Adjusts transfer count for next iteration
+ - Saves recipient data to file
+
+4. **Self-Adjustment**:
+ - If under target gas usage: increases transfers
+ - If over target gas usage: decreases transfers
+ - Aims for 99.5% block utilization
+
+## State Growth Impact
+
+Each successful transfer creates:
+- New account entry for the recipient (~100 bytes)
+- Token balance storage slot for the recipient
+- Estimated state growth: 100 bytes per transfer
+
+## Output
+
+Recipient addresses are saved to `recipients.json` with:
+- Address
+- Block number
+- Tokens sent
+
+## Requirements
+
+- Deployed StateBloatToken contracts (via contract_deploy scenario)
+- Deployer private key with full token supply
+- Sufficient ETH for gas fees
+
+## Example Usage
+
+```bash
+# Use default settings
+./spamoor scenario --scenario erc20-max-transfers
+
+# Custom gas fees
+./spamoor scenario --scenario erc20-max-transfers --basefee 20 --tipfee 10
+
+# Use specific contract only
+./spamoor scenario --scenario erc20-max-transfers --contract 0xa513E6E4b8f2a923D98304ec87F64353C4D5C853
+```
diff --git a/scenarios/statebloat/erc20_max_transfers/erc20_max_transfers.go b/scenarios/statebloat/erc20_max_transfers/erc20_max_transfers.go
new file mode 100644
index 00000000..f271a324
--- /dev/null
+++ b/scenarios/statebloat/erc20_max_transfers/erc20_max_transfers.go
@@ -0,0 +1,811 @@
+package sberc20maxtransfers
+
+import (
+ "context"
+ "crypto/rand"
+ "crypto/sha256"
+ "encoding/binary"
+ "encoding/json"
+ "fmt"
+ "math/big"
+ "os"
+ "strings"
+ "sync"
+ "sync/atomic"
+ "time"
+
+ "gopkg.in/yaml.v3"
+
+ "github.com/ethereum/go-ethereum/accounts/abi"
+ //"github.com/ethereum/go-ethereum/accounts/abi/bind"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/holiman/uint256"
+ "github.com/sirupsen/logrus"
+ "github.com/spf13/pflag"
+
+ "github.com/ethpandaops/spamoor/scenario"
+ contract "github.com/ethpandaops/spamoor/scenarios/statebloat/contract_deploy/contract"
+ "github.com/ethpandaops/spamoor/spamoor"
+ "github.com/ethpandaops/spamoor/txbuilder"
+)
+
+// Constants for ERC20 transfer operations
+const (
+ // ERC20TransferGasCost - gas cost for a standard ERC20 transfer (updated to 70K)
+ ERC20TransferGasCost = 70000
+ // DefaultBaseFeeGwei - default base fee in gwei
+ DefaultBaseFeeGwei = 10
+ // DefaultTipFeeGwei - default tip fee in gwei
+ DefaultTipFeeGwei = 5
+ // TokenTransferAmount - amount of tokens to transfer (1 token in smallest unit)
+ TokenTransferAmount = 1
+ // DefaultTargetGasRatio - target percentage of block gas limit to use (99.5% for minimal safety margin)
+ DefaultTargetGasRatio = 0.995
+ // FallbackBlockGasLimit - fallback gas limit if network query fails
+ FallbackBlockGasLimit = 30000000
+ // GweiPerEth - conversion factor from Gwei to Wei
+ GweiPerEth = 1000000000
+ // BlockMiningTimeout - timeout for waiting for a new block to be mined
+ BlockMiningTimeout = 30 * time.Second
+ // BlockPollingInterval - interval for checking new blocks
+ BlockPollingInterval = 1 * time.Second
+ // TransactionBatchSize - number of transactions to send in a batch
+ TransactionBatchSize = 100
+ // TransactionBatchThreshold - threshold for continuing to fill a block
+ TransactionBatchThreshold = 50
+ // InitialTransactionDelay - delay between initial transactions
+ InitialTransactionDelay = 10 * time.Millisecond
+ // OptimizedTransactionDelay - reduced delay after initial batch
+ OptimizedTransactionDelay = 5 * time.Millisecond
+ // ConfirmationDelay - delay before checking confirmations
+ ConfirmationDelay = 2 * time.Second
+ // MaxRebroadcasts - maximum number of times to rebroadcast a transaction
+ MaxRebroadcasts = 10
+ // RetryDelay - delay before retrying failed operations
+ RetryDelay = 5 * time.Second
+ // GasPerMillion - divisor for converting gas to millions
+ GasPerMillion = 1_000_000.0
+ // BytesPerKiB - bytes in a kibibyte
+ BytesPerKiB = 1024.0
+ // EstimatedStateGrowthPerTransfer - estimated state growth in bytes per new recipient
+ EstimatedStateGrowthPerTransfer = 100
+ // BloatingSummaryFileName - name of the bloating summary file
+ BloatingSummaryFileName = "erc20_bloating_summary.json"
+)
+
+// ScenarioOptions defines the configuration options for the scenario
+type ScenarioOptions struct {
+ BaseFee uint64 `yaml:"base_fee"`
+ TipFee uint64 `yaml:"tip_fee"`
+ Contract string `yaml:"contract"`
+ DeploymentsFile string `yaml:"deployments_file"`
+}
+
+// DeploymentEntry represents a contract deployment from deployments.json
+type DeploymentEntry map[string][]string
+
+// ContractBloatStats tracks unique recipients per contract
+type ContractBloatStats struct {
+ UniqueRecipients int `json:"unique_recipients"`
+}
+
+// BloatingSummary represents the JSON file structure
+type BloatingSummary struct {
+ Contracts map[string]*ContractBloatStats `json:"contracts"`
+ TotalRecipients int `json:"total_recipients"`
+ LastBlockNumber string `json:"last_block_number"`
+ LastBlockUpdate time.Time `json:"last_block_update"`
+}
+
+// Scenario implements the ERC20 max transfers scenario
+type Scenario struct {
+ options ScenarioOptions
+ logger *logrus.Entry
+ walletPool *spamoor.WalletPool
+
+ // Deployed contracts and private key
+ deployerPrivateKey string
+ deployerAddress common.Address
+ deployerWallet *spamoor.Wallet // Store the wallet instance
+ deployedContracts []common.Address
+ currentRoundContract common.Address // Contract being used for current round
+ contractsLock sync.Mutex
+
+ // Transfer function ABI
+ transferABI abi.Method
+ contractABI abi.ABI
+
+ // Used addresses tracking
+ usedAddresses map[common.Address]bool
+ usedAddressesLock sync.Mutex
+
+ // Bloating statistics tracking
+ contractStats map[common.Address]*ContractBloatStats
+ contractStatsLock sync.Mutex
+}
+
+var ScenarioName = "statebloat-erc20-max-transfers"
+var ScenarioDefaultOptions = ScenarioOptions{
+ BaseFee: DefaultBaseFeeGwei,
+ TipFee: DefaultTipFeeGwei,
+ Contract: "",
+ DeploymentsFile: "deployments.json",
+}
+var ScenarioDescriptor = scenario.Descriptor{
+ Name: ScenarioName,
+ Description: "Maximum ERC20 transfers per block to unique addresses",
+ DefaultOptions: ScenarioDefaultOptions,
+ NewScenario: newScenario,
+}
+
+func newScenario(logger logrus.FieldLogger) scenario.Scenario {
+ return &Scenario{
+ logger: logger.WithField("scenario", ScenarioName),
+ usedAddresses: make(map[common.Address]bool),
+ contractStats: make(map[common.Address]*ContractBloatStats),
+ }
+}
+
+func (s *Scenario) Flags(flags *pflag.FlagSet) error {
+ flags.Uint64Var(&s.options.BaseFee, "basefee", ScenarioDefaultOptions.BaseFee, "Max fee per gas to use in transactions (in gwei)")
+ flags.Uint64Var(&s.options.TipFee, "tipfee", ScenarioDefaultOptions.TipFee, "Max tip per gas to use in transactions (in gwei)")
+ flags.StringVar(&s.options.Contract, "contract", ScenarioDefaultOptions.Contract, "Specific contract address to use (default: rotate through all)")
+ flags.StringVar(&s.options.DeploymentsFile, "deployments-file", ScenarioDefaultOptions.DeploymentsFile, "File to save deployments to")
+ return nil
+}
+
+func (s *Scenario) Init(options *scenario.Options) error {
+ s.walletPool = options.WalletPool
+
+ if options.Config != "" {
+ err := yaml.Unmarshal([]byte(options.Config), &s.options)
+ if err != nil {
+ return fmt.Errorf("failed to unmarshal config: %w", err)
+ }
+ }
+
+ // Load deployed contracts from deployments.json
+ err := s.loadDeployedContracts()
+ if err != nil {
+ return fmt.Errorf("failed to load deployed contracts: %w", err)
+ }
+
+ // Load transfer function ABI
+ err = s.loadTransferABI()
+ if err != nil {
+ return fmt.Errorf("failed to load transfer ABI: %w", err)
+ }
+
+ // We'll use the deployer wallet which we'll prepare in runMaxTransfersMode
+ s.walletPool.SetWalletCount(0)
+
+ return nil
+}
+
+func (s *Scenario) Config() string {
+ yamlBytes, _ := yaml.Marshal(&s.options)
+ return string(yamlBytes)
+}
+
+// loadDeployedContracts loads contract addresses and private key from deployments.json
+func (s *Scenario) loadDeployedContracts() error {
+ if s.options.DeploymentsFile == "" {
+ return fmt.Errorf("deployments file is not set")
+ }
+
+ data, err := os.ReadFile(s.options.DeploymentsFile)
+ if err != nil {
+ return fmt.Errorf("failed to read %v: %w", s.options.DeploymentsFile, err)
+ }
+
+ var deployments DeploymentEntry
+ err = json.Unmarshal(data, &deployments)
+ if err != nil {
+ return fmt.Errorf("failed to parse deployments.json: %w", err)
+ }
+
+ // Get the first (and only) entry
+ for privateKey, addresses := range deployments {
+ // Trim 0x prefix if present
+ privateKey = strings.TrimPrefix(privateKey, "0x")
+
+ s.deployerPrivateKey = privateKey
+ s.deployedContracts = make([]common.Address, len(addresses))
+ for i, addr := range addresses {
+ s.deployedContracts[i] = common.HexToAddress(addr)
+ }
+ break // Only process the first entry
+ }
+
+ if s.deployerPrivateKey == "" || len(s.deployedContracts) == 0 {
+ return fmt.Errorf("no valid deployments found in deployments.json")
+ }
+
+ s.logger.Infof("Loaded %d deployed contracts from deployments.json", len(s.deployedContracts))
+
+ // Initialize contract stats for all deployed contracts
+ for _, contractAddr := range s.deployedContracts {
+ s.contractStats[contractAddr] = &ContractBloatStats{
+ UniqueRecipients: 0,
+ }
+ }
+
+ // If specific contract requested, validate it exists
+ if s.options.Contract != "" {
+ contractAddr := common.HexToAddress(s.options.Contract)
+ found := false
+ for _, addr := range s.deployedContracts {
+ if addr == contractAddr {
+ found = true
+ s.deployedContracts = []common.Address{contractAddr} // Use only this contract
+ break
+ }
+ }
+ if !found {
+ return fmt.Errorf("specified contract %s not found in deployments", s.options.Contract)
+ }
+ s.logger.Infof("Using specific contract: %s", contractAddr.Hex())
+ }
+
+ return nil
+}
+
+// loadTransferABI loads the transfer function ABI from the contract
+func (s *Scenario) loadTransferABI() error {
+ // Parse the contract ABI to get the transfer method
+ contractABI, err := abi.JSON(strings.NewReader(contract.StateBloatTokenMetaData.ABI))
+ if err != nil {
+ return fmt.Errorf("failed to parse contract ABI: %w", err)
+ }
+
+ transferMethod, exists := contractABI.Methods["transfer"]
+ if !exists {
+ return fmt.Errorf("transfer method not found in contract ABI")
+ }
+
+ s.transferABI = transferMethod
+ s.contractABI = contractABI
+ return nil
+}
+
+// getNetworkBlockGasLimit retrieves the current block gas limit from the network
+// It waits for a new block to be mined (with timeout) to ensure fresh data
+func (s *Scenario) getNetworkBlockGasLimit(ctx context.Context, client *spamoor.Client) uint64 {
+ // Create a timeout context for the entire operation
+ timeoutCtx, cancel := context.WithTimeout(ctx, BlockMiningTimeout)
+ defer cancel()
+
+ // Get the current block number first
+ currentBlockNumber, err := client.GetEthClient().BlockNumber(timeoutCtx)
+ if err != nil {
+ s.logger.Warnf("failed to get current block number: %v, using fallback: %d", err, FallbackBlockGasLimit)
+ return FallbackBlockGasLimit
+ }
+
+ s.logger.Debugf("waiting for new block to be mined (current: %d, timeout: %v)", currentBlockNumber, BlockMiningTimeout)
+
+ // Wait for a new block to be mined
+ ticker := time.NewTicker(BlockPollingInterval)
+ defer ticker.Stop()
+
+ var latestBlock *types.Block
+ for {
+ select {
+ case <-timeoutCtx.Done():
+ s.logger.Warnf("timeout waiting for new block to be mined, using fallback: %d", FallbackBlockGasLimit)
+ return FallbackBlockGasLimit
+ case <-ticker.C:
+ // Check for a new block
+ newBlockNumber, err := client.GetEthClient().BlockNumber(timeoutCtx)
+ if err != nil {
+ s.logger.Debugf("error checking block number: %v", err)
+ continue
+ }
+
+ // If we have a new block, get its details
+ if newBlockNumber > currentBlockNumber {
+ latestBlock, err = client.GetEthClient().BlockByNumber(timeoutCtx, nil)
+ if err != nil {
+ s.logger.Debugf("error getting latest block details: %v", err)
+ continue
+ }
+ s.logger.Debugf("new block mined: %d", newBlockNumber)
+ goto blockFound
+ }
+ }
+ }
+
+blockFound:
+ gasLimit := latestBlock.GasLimit()
+ s.logger.Debugf("network block gas limit from fresh block #%d: %d", latestBlock.NumberU64(), gasLimit)
+ return gasLimit
+}
+
+// generateRecipient generates a deterministic recipient address based on index
+func (s *Scenario) generateRecipient(recipientIndex uint64) common.Address {
+ idxBytes := make([]byte, 8)
+ binary.BigEndian.PutUint64(idxBytes, recipientIndex)
+ // Use deployer address as seed for deterministic generation
+ hash := sha256.Sum256(append(s.deployerAddress.Bytes(), idxBytes...))
+ return common.BytesToAddress(hash[12:]) // Use last 20 bytes as address
+}
+
+// loadBloatingSummary loads the bloating summary from file or creates a new one
+func (s *Scenario) loadBloatingSummary() (*BloatingSummary, error) {
+ data, err := os.ReadFile(BloatingSummaryFileName)
+ if err != nil {
+ if os.IsNotExist(err) {
+ // File doesn't exist, return new summary
+ return &BloatingSummary{
+ Contracts: make(map[string]*ContractBloatStats),
+ TotalRecipients: 0,
+ }, nil
+ }
+ return nil, fmt.Errorf("failed to read bloating summary: %w", err)
+ }
+
+ var summary BloatingSummary
+ if err := json.Unmarshal(data, &summary); err != nil {
+ return nil, fmt.Errorf("failed to unmarshal bloating summary: %w", err)
+ }
+
+ // Ensure contracts map is initialized
+ if summary.Contracts == nil {
+ summary.Contracts = make(map[string]*ContractBloatStats)
+ }
+
+ return &summary, nil
+}
+
+// saveBloatingSummary saves the bloating summary to file
+func (s *Scenario) saveBloatingSummary(summary *BloatingSummary) error {
+ data, err := json.MarshalIndent(summary, "", " ")
+ if err != nil {
+ return fmt.Errorf("failed to marshal bloating summary: %w", err)
+ }
+
+ if err := os.WriteFile(BloatingSummaryFileName, data, 0644); err != nil {
+ return fmt.Errorf("failed to write bloating summary: %w", err)
+ }
+
+ return nil
+}
+
+// updateContractStats updates the statistics for a contract when a transfer is confirmed
+func (s *Scenario) updateContractStats(contractAddr common.Address) {
+ s.contractStatsLock.Lock()
+ defer s.contractStatsLock.Unlock()
+
+ stats, exists := s.contractStats[contractAddr]
+ if !exists {
+ stats = &ContractBloatStats{
+ UniqueRecipients: 0,
+ }
+ s.contractStats[contractAddr] = stats
+ }
+ stats.UniqueRecipients++
+}
+
+// updateAndSaveBloatingSummary updates the bloating summary with current stats and saves to file
+func (s *Scenario) updateAndSaveBloatingSummary(blockNumber string) error {
+ // Load existing summary
+ summary, err := s.loadBloatingSummary()
+ if err != nil {
+ return err
+ }
+
+ // Update with current stats
+ s.contractStatsLock.Lock()
+ totalRecipients := 0
+ for contractAddr, stats := range s.contractStats {
+ contractHex := contractAddr.Hex()
+ summary.Contracts[contractHex] = &ContractBloatStats{
+ UniqueRecipients: stats.UniqueRecipients,
+ }
+ totalRecipients += stats.UniqueRecipients
+ }
+ s.contractStatsLock.Unlock()
+
+ // Update summary metadata
+ summary.TotalRecipients = totalRecipients
+ summary.LastBlockNumber = blockNumber
+ summary.LastBlockUpdate = time.Now()
+
+ // Save to file
+ return s.saveBloatingSummary(summary)
+}
+
+// getContractBloatingSummaryForBlock returns a formatted string with contract bloating info for latest block
+func (s *Scenario) getContractBloatingSummaryForBlock() string {
+ s.contractStatsLock.Lock()
+ defer s.contractStatsLock.Unlock()
+
+ // Get current round contract
+ s.contractsLock.Lock()
+ currentContract := s.currentRoundContract
+ s.contractsLock.Unlock()
+
+ if currentContract == (common.Address{}) {
+ return "No contract selected for current round"
+ }
+
+ // Get stats for current contract
+ stats, exists := s.contractStats[currentContract]
+ if !exists {
+ return fmt.Sprintf("CONTRACT BLOATING STATUS:\n Round Contract: %s - No transfers yet", currentContract.Hex())
+ }
+
+ return fmt.Sprintf("CONTRACT BLOATING STATUS:\n Round Contract: %s - %d unique recipients",
+ currentContract.Hex(), stats.UniqueRecipients)
+}
+
+// selectRandomContract randomly selects a contract from the deployed contracts
+func (s *Scenario) selectRandomContract() (common.Address, error) {
+ s.contractsLock.Lock()
+ defer s.contractsLock.Unlock()
+
+ if len(s.deployedContracts) == 0 {
+ return common.Address{}, fmt.Errorf("no deployed contracts available")
+ }
+
+ // If only one contract, return it
+ if len(s.deployedContracts) == 1 {
+ return s.deployedContracts[0], nil
+ }
+
+ // Generate random index
+ max := big.NewInt(int64(len(s.deployedContracts)))
+ n, err := rand.Int(rand.Reader, max)
+ if err != nil {
+ return common.Address{}, fmt.Errorf("failed to generate random number: %w", err)
+ }
+
+ return s.deployedContracts[n.Int64()], nil
+}
+
+func (s *Scenario) Run(ctx context.Context) error {
+ return s.runMaxTransfersMode(ctx)
+}
+
+func (s *Scenario) runMaxTransfersMode(ctx context.Context) error {
+ s.logger.Infof("starting max transfers mode: self-adjusting to target block gas limit, continuous operation")
+
+ // Get a client for network operations
+ client := s.walletPool.GetClient(spamoor.SelectClientByIndex, 0, "")
+
+ // Get the actual network block gas limit
+ networkGasLimit := s.getNetworkBlockGasLimit(ctx, client)
+ targetGas := uint64(float64(networkGasLimit) * DefaultTargetGasRatio)
+
+ // Calculate initial transfer count based on network gas limit and known gas cost per transfer
+ initialTransfers := int(targetGas / ERC20TransferGasCost)
+
+ // Dynamic transfer count - starts based on network parameters and adjusts based on actual performance
+ currentTransfers := initialTransfers
+
+ // Prepare the deployer wallet if not already done
+ if s.deployerWallet == nil {
+ // Create wallet from deployer private key
+ deployerWallet, err := spamoor.NewWallet(s.deployerPrivateKey)
+ if err != nil {
+ return fmt.Errorf("failed to create deployer wallet: %w", err)
+ }
+
+ // Update wallet with chain info using the client
+ err = client.UpdateWallet(ctx, deployerWallet)
+ if err != nil {
+ return fmt.Errorf("failed to update deployer wallet: %w", err)
+ }
+
+ // Store the wallet instance
+ s.deployerWallet = deployerWallet
+ s.deployerAddress = deployerWallet.GetAddress()
+
+ s.logger.Infof("Initialized deployer wallet - Address: %s, Nonce: %d, Balance: %s ETH",
+ s.deployerAddress.Hex(), deployerWallet.GetNonce(), new(big.Int).Div(deployerWallet.GetBalance(), big.NewInt(1e18)).String())
+ }
+
+ var blockCounter int
+ var totalTransfers uint64
+ var totalUniqueRecipients uint64
+
+ for {
+ select {
+ case <-ctx.Done():
+ s.logger.Errorf("max transfers mode stopping due to context cancellation")
+ return ctx.Err()
+ default:
+ }
+
+ blockCounter++
+
+ // Send the max transfer transactions and wait for confirmation
+ s.logger.Infof("ββββββββββββββββ TRANSFER PHASE #%d ββββββββββββββββ", blockCounter)
+ actualGasUsed, blockNumber, transferCount, gasPerTransfer, uniqueRecipients, err := s.sendMaxTransfers(ctx, s.deployerWallet, currentTransfers, targetGas, blockCounter, client)
+ if err != nil {
+ s.logger.Errorf("failed to send max transfers for iteration %d: %v", blockCounter, err)
+ time.Sleep(RetryDelay) // Wait before retry
+ continue
+ }
+
+ // Update totals
+ totalTransfers += uint64(transferCount)
+ totalUniqueRecipients += uint64(uniqueRecipients)
+
+ s.logger.Infof("%%%%%%%%%%%%%%%%%%%% ANALYSIS PHASE #%d %%%%%%%%%%%%%%%%%%%%", blockCounter)
+
+ // Calculate metrics
+ blockGasLimit := float64(networkGasLimit)
+ gasUtilization := (float64(actualGasUsed) / blockGasLimit) * 100
+ estimatedStateGrowth := uniqueRecipients * EstimatedStateGrowthPerTransfer
+
+ s.logger.WithField("scenario", ScenarioName).Infof("TRANSFER METRICS - Block #%s | Transfers: %d | Unique recipients: %d | Gas used: %.2fM | Block utilization: %.2f%% | Gas/transfer: %.1f | Est. state growth: %.2f KiB",
+ blockNumber, transferCount, uniqueRecipients, float64(actualGasUsed)/GasPerMillion, gasUtilization, gasPerTransfer, float64(estimatedStateGrowth)/BytesPerKiB)
+
+ // Log contract-specific bloating info
+ s.logger.WithField("scenario", ScenarioName).Info(s.getContractBloatingSummaryForBlock())
+
+ // Log cumulative metrics
+ s.logger.WithField("scenario", ScenarioName).Infof("CUMULATIVE TOTALS - Total transfers: %d | Total unique recipients: %d | Avg transfers/block: %.1f",
+ totalTransfers, totalUniqueRecipients, float64(totalTransfers)/float64(blockCounter))
+
+ // Update and save bloating summary
+ err = s.updateAndSaveBloatingSummary(blockNumber)
+ if err != nil {
+ s.logger.Warnf("Failed to update bloating summary: %v", err)
+ }
+
+ // Self-adjust transfer count based on actual performance
+ if actualGasUsed > 0 && transferCount > 0 {
+ avgGasPerTransfer := float64(actualGasUsed) / float64(transferCount)
+ targetTransfers := int(float64(targetGas) / avgGasPerTransfer)
+
+ // Calculate the adjustment needed
+ transferDifference := targetTransfers - transferCount
+
+ if actualGasUsed < targetGas {
+ // We're under target, increase transfer count with a slight safety margin
+ newTransfers := currentTransfers + transferDifference - 1
+
+ if newTransfers > currentTransfers {
+ s.logger.Infof("Adjusting transfers: %d β %d (need %d more for target)",
+ currentTransfers, newTransfers, transferDifference)
+ currentTransfers = newTransfers
+ }
+ } else if actualGasUsed > targetGas {
+ // We're over target, reduce to reach max block utilization
+ excess := actualGasUsed - targetGas
+ excessTransfers := int(float64(excess) / avgGasPerTransfer)
+ newTransfers := currentTransfers - excessTransfers
+
+ s.logger.Infof("Reducing transfers: %d β %d (excess: %d gas, ~%d transfers)",
+ currentTransfers, newTransfers, excess, excessTransfers)
+ currentTransfers = newTransfers
+
+ } else {
+ s.logger.Infof("Target achieved! Gas Used: %d / Target: %d", actualGasUsed, targetGas)
+ }
+ }
+ }
+}
+
+func (s *Scenario) sendMaxTransfers(ctx context.Context, deployerWallet *spamoor.Wallet, targetTransfers int, targetGasLimit uint64, blockCounter int, client *spamoor.Client) (uint64, string, int, float64, int, error) {
+ // Select a random contract for this round
+ contractForRound, err := s.selectRandomContract()
+ if err != nil {
+ return 0, "", 0, 0, 0, fmt.Errorf("failed to select contract for round: %w", err)
+ }
+
+ // Update current round contract
+ s.contractsLock.Lock()
+ s.currentRoundContract = contractForRound
+ s.contractsLock.Unlock()
+
+ s.logger.Infof("Selected contract for round #%d: %s", blockCounter, contractForRound.Hex())
+
+ // Get suggested fees or use configured values
+ feeCap, tipCap, err := s.walletPool.GetTxPool().GetSuggestedFees(client, s.options.BaseFee, s.options.TipFee)
+ if err != nil {
+ return 0, "", 0, 0, 0, fmt.Errorf("failed to get suggested fees: %w", err)
+ }
+
+ // Send transfers in batches
+ return s.sendTransferBatch(ctx, deployerWallet, targetTransfers, targetGasLimit, blockCounter, client, feeCap, tipCap)
+}
+
+func (s *Scenario) sendTransferBatch(ctx context.Context, wallet *spamoor.Wallet, targetTransfers int, targetGasLimit uint64, iteration int, client *spamoor.Client, feeCap, tipCap *big.Int) (uint64, string, int, float64, int, error) {
+ var confirmedCount int64
+ var uniqueRecipientsCount int64
+ var totalGasUsed uint64
+ var lastBlockNumber string
+
+ sentCount := 0
+ recipientIndex := uint64(iteration * 1000000) // Large offset per iteration to avoid conflicts
+
+ // Calculate approximate transactions per block based on gas limit
+ maxTxsPerBlock := int(targetGasLimit / ERC20TransferGasCost)
+
+ // Track confirmations
+ type confirmResult struct {
+ gasUsed uint64
+ blockNumber string
+ recipient common.Address
+ contractUsed common.Address
+ }
+ // Make channel buffered with enough capacity for all transactions
+ confirmChan := make(chan confirmResult, targetTransfers*2) // Double buffer to be safe
+
+ // Send transactions
+ for sentCount < targetTransfers {
+ // Generate unique recipient address
+ var recipient common.Address
+ for {
+ recipient = s.generateRecipient(recipientIndex)
+ recipientIndex++
+
+ // Check if address already used
+ s.usedAddressesLock.Lock()
+ if !s.usedAddresses[recipient] {
+ s.usedAddresses[recipient] = true
+ s.usedAddressesLock.Unlock()
+ break
+ }
+ s.usedAddressesLock.Unlock()
+ }
+
+ // Use the contract selected for this round
+ s.contractsLock.Lock()
+ contractAddr := s.currentRoundContract
+ s.contractsLock.Unlock()
+
+ // Encode transfer call data
+ transferAmount := big.NewInt(TokenTransferAmount)
+ callData, err := s.contractABI.Pack("transfer", recipient, transferAmount)
+ if err != nil {
+ s.logger.Errorf("failed to pack transfer call data: %v", err)
+ continue
+ }
+
+ // Build transaction
+ txMetadata := &txbuilder.TxMetadata{
+ GasFeeCap: uint256.MustFromBig(feeCap),
+ GasTipCap: uint256.MustFromBig(tipCap),
+ Gas: ERC20TransferGasCost,
+ To: &contractAddr,
+ Value: uint256.NewInt(0), // No ETH value for ERC20 transfer
+ Data: callData,
+ }
+
+ txData, err := txbuilder.DynFeeTx(txMetadata)
+ if err != nil {
+ s.logger.Errorf("failed to create tx data: %v", err)
+ continue
+ }
+
+ tx, err := wallet.BuildDynamicFeeTx(txData)
+ if err != nil {
+ s.logger.Errorf("failed to build transaction: %v", err)
+ continue
+ }
+
+ // Capture values for closure
+ capturedRecipient := recipient
+ capturedContract := contractAddr
+
+ // Send transaction
+ err = s.walletPool.GetTxPool().SendTransaction(ctx, wallet, tx, &spamoor.SendTransactionOptions{
+ Client: client,
+ Rebroadcast: false, // No retries to avoid duplicates
+ OnComplete: func(tx *types.Transaction, receipt *types.Receipt, err error) {
+ if err != nil {
+ return // Don't log individual failures
+ }
+ if receipt != nil && receipt.Status == 1 {
+ atomic.AddInt64(&confirmedCount, 1)
+ atomic.AddInt64(&uniqueRecipientsCount, 1)
+
+ // Update contract stats
+ s.updateContractStats(capturedContract)
+
+ // Send result to channel with captured values
+ confirmChan <- confirmResult{
+ gasUsed: receipt.GasUsed,
+ blockNumber: receipt.BlockNumber.String(),
+ recipient: capturedRecipient,
+ contractUsed: capturedContract,
+ }
+ }
+ },
+ LogFn: func(client *spamoor.Client, retry int, rebroadcast int, err error) {
+ // Only log actual send failures
+ if err != nil {
+ s.logger.Debugf("transfer tx send failed: %v", err)
+ }
+ },
+ })
+
+ if err != nil {
+ continue
+ }
+
+ sentCount++
+
+ // Small delay between transactions to ensure proper nonce ordering
+ if sentCount < TransactionBatchSize {
+ time.Sleep(InitialTransactionDelay)
+ } else if sentCount%maxTxsPerBlock < TransactionBatchThreshold {
+ time.Sleep(OptimizedTransactionDelay)
+ }
+
+ // Add context cancellation check
+ select {
+ case <-ctx.Done():
+ return 0, "", 0, 0, 0, ctx.Err()
+ default:
+ }
+ }
+
+ // Wait for confirmations
+ s.logger.Infof("Sent %d transfer transactions, waiting for confirmations...", sentCount)
+ time.Sleep(ConfirmationDelay)
+
+ // Log initial confirmation status
+ initialConfirmed := atomic.LoadInt64(&confirmedCount)
+ if initialConfirmed > 0 {
+ s.logger.Debugf("Already have %d confirmations before collection", initialConfirmed)
+ }
+
+ // Collect results - wait for all sent transactions or timeout
+ confirmTimeout := time.After(30 * time.Second)
+ resultCount := 0
+
+collectResults:
+ for resultCount < sentCount {
+ select {
+ case result := <-confirmChan:
+ totalGasUsed += result.gasUsed
+ lastBlockNumber = result.blockNumber
+ resultCount++
+
+ case <-confirmTimeout:
+ // Final check for any remaining confirmations
+ confirmed := atomic.LoadInt64(&confirmedCount)
+ s.logger.Warnf("Timeout waiting for confirmations, received %d results, %d confirmed, %d sent", resultCount, confirmed, sentCount)
+ break collectResults
+
+ case <-ctx.Done():
+ return 0, "", 0, 0, 0, ctx.Err()
+ }
+ }
+
+ // Drain any remaining results from the channel (non-blocking)
+ for {
+ select {
+ case result := <-confirmChan:
+ totalGasUsed += result.gasUsed
+ lastBlockNumber = result.blockNumber
+ resultCount++
+ default:
+ // No more results available
+ goto done
+ }
+ }
+done:
+
+ // Calculate metrics
+ confirmed := atomic.LoadInt64(&confirmedCount)
+ uniqueRecipients := atomic.LoadInt64(&uniqueRecipientsCount)
+
+ // Log detailed confirmation statistics
+ s.logger.Debugf("Confirmation stats: sent=%d, confirmed=%d, results=%d, gas=%d",
+ sentCount, confirmed, resultCount, totalGasUsed)
+
+ if confirmed == 0 {
+ return 0, "", 0, 0, 0, fmt.Errorf("no transfers confirmed")
+ }
+
+ gasPerTransfer := float64(totalGasUsed) / float64(confirmed)
+
+ return totalGasUsed, lastBlockNumber, int(confirmed), gasPerTransfer, int(uniqueRecipients), nil
+}
diff --git a/scenarios/statebloat/rand_sstore/README.md b/scenarios/statebloat/rand_sstore/README.md
new file mode 100644
index 00000000..f7a9c6b6
--- /dev/null
+++ b/scenarios/statebloat/rand_sstore/README.md
@@ -0,0 +1,124 @@
+# π₯ Random SSTORE State Bloater
+
+This scenario maximizes state growth by performing the maximum number of SSTORE operations per block using random key distribution.
+
+## π οΈ Contract Compilation
+
+### Prerequisites
+- Solidity compiler (solc) version 0.8.30 or compatible
+- Go 1.16+ (for go:embed directive)
+
+### Compiling the Contract
+
+To compile the SSTOREStorageBloater contract:
+
+```bash
+cd scenarios/statebloat/rand_sstore_bloater/contract
+solc --optimize --optimize-runs 200 --combined-json abi,bin SSTOREStorageBloater.sol
+```
+
+### Extracting ABI and Bytecode
+
+The compilation output is in JSON format. Extract the ABI and bytecode:
+
+```bash
+# Extract ABI (already done)
+jq -r '.contracts["SSTOREStorageBloater.sol:SSTOREStorageBloater"].abi' < output.json > SSTOREStorageBloater.abi
+
+# Extract bytecode (already done)
+jq -r '.contracts["SSTOREStorageBloater.sol:SSTOREStorageBloater"].bin' < output.json > SSTOREStorageBloater.bin
+```
+
+### Regenerating Go Bindings (Optional)
+
+If you need to regenerate the Go bindings:
+
+```bash
+abigen --abi SSTOREStorageBloater.abi --bin SSTOREStorageBloater.bin --pkg contract --out SSTOREStorageBloater.go
+```
+
+**Note**: The Go scenario code uses `go:embed` directives to automatically include the ABI and bytecode files at compile time.
+
+## How it Works
+
+1. **Contract Deployment**: Deploys an optimized `SSTOREStorageBloater` contract that uses assembly for minimal overhead
+2. **Two-Stage Process**:
+ - **Stage 1**: Creates new storage slots (0 β non-zero transitions)
+ - **Stage 2**: Updates existing storage slots (non-zero β non-zero transitions)
+3. **Key Distribution**: Uses curve25519 prime multiplication to distribute keys across the entire storage space, maximizing trie node creation
+4. **Adaptive Gas Estimation**: Dynamically adjusts gas estimates based on actual usage to maximize slots per transaction
+
+## β½ Gas Cost Breakdown
+
+### Actual Gas Costs (Measured)
+The actual gas cost per SSTORE operation is higher than the base opcode cost due to additional overhead:
+
+**For New Slots (0 β non-zero):**
+- Base SSTORE cost: 20,000 gas
+- Assembly loop overhead per iteration:
+ - MULMOD for key calculation: ~8 gas
+ - TIMESTAMP calls: ~2 gas
+ - AND operation: ~3 gas
+ - Loop control (JUMPI, LT, ADD): ~10 gas
+- **Total: ~22,000 gas per slot**
+
+**For Updates (non-zero β non-zero):**
+- Base SSTORE cost: 5,000 gas
+- Same assembly overhead: ~2,000 gas
+- **Total: ~7,000 gas per slot**
+
+**Transaction Overhead:**
+- Base transaction cost: 21,000 gas
+- Function selector matching: ~100 gas
+- ABI decoding (uint256 parameter): ~1,000 gas
+- Contract code loading: ~2,600 gas
+- Memory allocation: ~1,000 gas
+- Function dispatch: ~300 gas
+- Return handling: ~1,000 gas
+- Safety margin: ~73,000 gas
+- **Total: ~100,000 gas overhead**
+
+Example with 30M gas limit block (97% utilization):
+- Stage 1: ~1,300 new slots per block
+- Stage 2: ~4,100 slot updates per block
+
+## π Usage
+
+### Build
+```bash
+go build -o bin/spamoor cmd/spamoor/main.go
+```
+
+### Run
+```bash
+./bin/spamoor --privkey --rpchost http://localhost:8545 rand_sstore_bloater [flags]
+```
+
+#### Flags
+- `--basefee` - Base fee per gas in gwei (default: 10)
+- `--tipfee` - Tip fee per gas in gwei (default: 2)
+
+### Example
+```bash
+./bin/spamoor --privkey ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 \
+ --rpchost http://localhost:8545 rand_sstore_bloater
+```
+
+## π Deployment Tracking
+
+The scenario tracks all contract deployments and storage operations in `deployments_sstore_bloating.json`. This file enables future scenarios to perform targeted SLOAD operations on known storage slots.
+
+### File Format
+```json
+{
+ "0xContractAddress": {
+ "storage_rounds": [
+ {
+ "block_number": 123,
+ "timestamp": 1234567890
+ },
+ ...
+ ]
+ }
+}
+```
\ No newline at end of file
diff --git a/scenarios/statebloat/rand_sstore/contract/.gitignore b/scenarios/statebloat/rand_sstore/contract/.gitignore
new file mode 100644
index 00000000..f9096e53
--- /dev/null
+++ b/scenarios/statebloat/rand_sstore/contract/.gitignore
@@ -0,0 +1,3 @@
+*.output.json
+*.bin
+*.abi
\ No newline at end of file
diff --git a/scenarios/statebloat/rand_sstore/contract/SSTOREStorageBloater.go b/scenarios/statebloat/rand_sstore/contract/SSTOREStorageBloater.go
new file mode 100644
index 00000000..6defd74e
--- /dev/null
+++ b/scenarios/statebloat/rand_sstore/contract/SSTOREStorageBloater.go
@@ -0,0 +1,224 @@
+// Code generated - DO NOT EDIT.
+// This file is a generated binding and any manual changes will be lost.
+
+package contract
+
+import (
+ "errors"
+ "math/big"
+ "strings"
+
+ ethereum "github.com/ethereum/go-ethereum"
+ "github.com/ethereum/go-ethereum/accounts/abi"
+ "github.com/ethereum/go-ethereum/accounts/abi/bind"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/event"
+)
+
+// Reference imports to suppress errors if they are not otherwise used.
+var (
+ _ = errors.New
+ _ = big.NewInt
+ _ = strings.NewReader
+ _ = ethereum.NotFound
+ _ = bind.Bind
+ _ = common.Big1
+ _ = types.BloomLookup
+ _ = event.NewSubscription
+ _ = abi.ConvertType
+)
+
+// SSTOREStorageBloaterMetaData contains all meta data concerning the SSTOREStorageBloater contract.
+var SSTOREStorageBloaterMetaData = &bind.MetaData{
+ ABI: "[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"count\",\"type\":\"uint256\"}],\"name\":\"createSlots\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]",
+ Bin: "0x608060405234801561001057600080fd5b5060f48061001f6000396000f3fe6080604052348015600f57600080fd5b506004361060285760003560e01c8063e3b393a414602d575b600080fd5b603c603836600460a7565b603e565b005b7f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed816001430340421860005b8281101560a0577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff84838301098055600101606a565b5050505050565b60006020828403121560b7578081fd5b503591905056fea264697066735822122079e4ae597ac68792390217bfee59415f78d7e370132ab6590720d9f7898a50be64736f6c63430008000033",
+}
+
+// SSTOREStorageBloaterABI is the input ABI used to generate the binding from.
+// Deprecated: Use SSTOREStorageBloaterMetaData.ABI instead.
+var SSTOREStorageBloaterABI = SSTOREStorageBloaterMetaData.ABI
+
+// SSTOREStorageBloaterBin is the compiled bytecode used for deploying new contracts.
+// Deprecated: Use SSTOREStorageBloaterMetaData.Bin instead.
+var SSTOREStorageBloaterBin = SSTOREStorageBloaterMetaData.Bin
+
+// DeploySSTOREStorageBloater deploys a new Ethereum contract, binding an instance of SSTOREStorageBloater to it.
+func DeploySSTOREStorageBloater(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *SSTOREStorageBloater, error) {
+ parsed, err := SSTOREStorageBloaterMetaData.GetAbi()
+ if err != nil {
+ return common.Address{}, nil, nil, err
+ }
+ if parsed == nil {
+ return common.Address{}, nil, nil, errors.New("GetABI returned nil")
+ }
+
+ address, tx, contract, err := bind.DeployContract(auth, *parsed, common.FromHex(SSTOREStorageBloaterBin), backend)
+ if err != nil {
+ return common.Address{}, nil, nil, err
+ }
+ return address, tx, &SSTOREStorageBloater{SSTOREStorageBloaterCaller: SSTOREStorageBloaterCaller{contract: contract}, SSTOREStorageBloaterTransactor: SSTOREStorageBloaterTransactor{contract: contract}, SSTOREStorageBloaterFilterer: SSTOREStorageBloaterFilterer{contract: contract}}, nil
+}
+
+// SSTOREStorageBloater is an auto generated Go binding around an Ethereum contract.
+type SSTOREStorageBloater struct {
+ SSTOREStorageBloaterCaller // Read-only binding to the contract
+ SSTOREStorageBloaterTransactor // Write-only binding to the contract
+ SSTOREStorageBloaterFilterer // Log filterer for contract events
+}
+
+// SSTOREStorageBloaterCaller is an auto generated read-only Go binding around an Ethereum contract.
+type SSTOREStorageBloaterCaller struct {
+ contract *bind.BoundContract // Generic contract wrapper for the low level calls
+}
+
+// SSTOREStorageBloaterTransactor is an auto generated write-only Go binding around an Ethereum contract.
+type SSTOREStorageBloaterTransactor struct {
+ contract *bind.BoundContract // Generic contract wrapper for the low level calls
+}
+
+// SSTOREStorageBloaterFilterer is an auto generated log filtering Go binding around an Ethereum contract events.
+type SSTOREStorageBloaterFilterer struct {
+ contract *bind.BoundContract // Generic contract wrapper for the low level calls
+}
+
+// SSTOREStorageBloaterSession is an auto generated Go binding around an Ethereum contract,
+// with pre-set call and transact options.
+type SSTOREStorageBloaterSession struct {
+ Contract *SSTOREStorageBloater // Generic contract binding to set the session for
+ CallOpts bind.CallOpts // Call options to use throughout this session
+ TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session
+}
+
+// SSTOREStorageBloaterCallerSession is an auto generated read-only Go binding around an Ethereum contract,
+// with pre-set call options.
+type SSTOREStorageBloaterCallerSession struct {
+ Contract *SSTOREStorageBloaterCaller // Generic contract caller binding to set the session for
+ CallOpts bind.CallOpts // Call options to use throughout this session
+}
+
+// SSTOREStorageBloaterTransactorSession is an auto generated write-only Go binding around an Ethereum contract,
+// with pre-set transact options.
+type SSTOREStorageBloaterTransactorSession struct {
+ Contract *SSTOREStorageBloaterTransactor // Generic contract transactor binding to set the session for
+ TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session
+}
+
+// SSTOREStorageBloaterRaw is an auto generated low-level Go binding around an Ethereum contract.
+type SSTOREStorageBloaterRaw struct {
+ Contract *SSTOREStorageBloater // Generic contract binding to access the raw methods on
+}
+
+// SSTOREStorageBloaterCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract.
+type SSTOREStorageBloaterCallerRaw struct {
+ Contract *SSTOREStorageBloaterCaller // Generic read-only contract binding to access the raw methods on
+}
+
+// SSTOREStorageBloaterTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract.
+type SSTOREStorageBloaterTransactorRaw struct {
+ Contract *SSTOREStorageBloaterTransactor // Generic write-only contract binding to access the raw methods on
+}
+
+// NewSSTOREStorageBloater creates a new instance of SSTOREStorageBloater, bound to a specific deployed contract.
+func NewSSTOREStorageBloater(address common.Address, backend bind.ContractBackend) (*SSTOREStorageBloater, error) {
+ contract, err := bindSSTOREStorageBloater(address, backend, backend, backend)
+ if err != nil {
+ return nil, err
+ }
+ return &SSTOREStorageBloater{SSTOREStorageBloaterCaller: SSTOREStorageBloaterCaller{contract: contract}, SSTOREStorageBloaterTransactor: SSTOREStorageBloaterTransactor{contract: contract}, SSTOREStorageBloaterFilterer: SSTOREStorageBloaterFilterer{contract: contract}}, nil
+}
+
+// NewSSTOREStorageBloaterCaller creates a new read-only instance of SSTOREStorageBloater, bound to a specific deployed contract.
+func NewSSTOREStorageBloaterCaller(address common.Address, caller bind.ContractCaller) (*SSTOREStorageBloaterCaller, error) {
+ contract, err := bindSSTOREStorageBloater(address, caller, nil, nil)
+ if err != nil {
+ return nil, err
+ }
+ return &SSTOREStorageBloaterCaller{contract: contract}, nil
+}
+
+// NewSSTOREStorageBloaterTransactor creates a new write-only instance of SSTOREStorageBloater, bound to a specific deployed contract.
+func NewSSTOREStorageBloaterTransactor(address common.Address, transactor bind.ContractTransactor) (*SSTOREStorageBloaterTransactor, error) {
+ contract, err := bindSSTOREStorageBloater(address, nil, transactor, nil)
+ if err != nil {
+ return nil, err
+ }
+ return &SSTOREStorageBloaterTransactor{contract: contract}, nil
+}
+
+// NewSSTOREStorageBloaterFilterer creates a new log filterer instance of SSTOREStorageBloater, bound to a specific deployed contract.
+func NewSSTOREStorageBloaterFilterer(address common.Address, filterer bind.ContractFilterer) (*SSTOREStorageBloaterFilterer, error) {
+ contract, err := bindSSTOREStorageBloater(address, nil, nil, filterer)
+ if err != nil {
+ return nil, err
+ }
+ return &SSTOREStorageBloaterFilterer{contract: contract}, nil
+}
+
+// bindSSTOREStorageBloater binds a generic wrapper to an already deployed contract.
+func bindSSTOREStorageBloater(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) {
+ parsed, err := SSTOREStorageBloaterMetaData.GetAbi()
+ if err != nil {
+ return nil, err
+ }
+ return bind.NewBoundContract(address, *parsed, caller, transactor, filterer), nil
+}
+
+// Call invokes the (constant) contract method with params as input values and
+// sets the output to result. The result type might be a single field for simple
+// returns, a slice of interfaces for anonymous returns and a struct for named
+// returns.
+func (_SSTOREStorageBloater *SSTOREStorageBloaterRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error {
+ return _SSTOREStorageBloater.Contract.SSTOREStorageBloaterCaller.contract.Call(opts, result, method, params...)
+}
+
+// Transfer initiates a plain transaction to move funds to the contract, calling
+// its default method if one is available.
+func (_SSTOREStorageBloater *SSTOREStorageBloaterRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) {
+ return _SSTOREStorageBloater.Contract.SSTOREStorageBloaterTransactor.contract.Transfer(opts)
+}
+
+// Transact invokes the (paid) contract method with params as input values.
+func (_SSTOREStorageBloater *SSTOREStorageBloaterRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) {
+ return _SSTOREStorageBloater.Contract.SSTOREStorageBloaterTransactor.contract.Transact(opts, method, params...)
+}
+
+// Call invokes the (constant) contract method with params as input values and
+// sets the output to result. The result type might be a single field for simple
+// returns, a slice of interfaces for anonymous returns and a struct for named
+// returns.
+func (_SSTOREStorageBloater *SSTOREStorageBloaterCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error {
+ return _SSTOREStorageBloater.Contract.contract.Call(opts, result, method, params...)
+}
+
+// Transfer initiates a plain transaction to move funds to the contract, calling
+// its default method if one is available.
+func (_SSTOREStorageBloater *SSTOREStorageBloaterTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) {
+ return _SSTOREStorageBloater.Contract.contract.Transfer(opts)
+}
+
+// Transact invokes the (paid) contract method with params as input values.
+func (_SSTOREStorageBloater *SSTOREStorageBloaterTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) {
+ return _SSTOREStorageBloater.Contract.contract.Transact(opts, method, params...)
+}
+
+// CreateSlots is a paid mutator transaction binding the contract method 0xe3b393a4.
+//
+// Solidity: function createSlots(uint256 count) returns()
+func (_SSTOREStorageBloater *SSTOREStorageBloaterTransactor) CreateSlots(opts *bind.TransactOpts, count *big.Int) (*types.Transaction, error) {
+ return _SSTOREStorageBloater.contract.Transact(opts, "createSlots", count)
+}
+
+// CreateSlots is a paid mutator transaction binding the contract method 0xe3b393a4.
+//
+// Solidity: function createSlots(uint256 count) returns()
+func (_SSTOREStorageBloater *SSTOREStorageBloaterSession) CreateSlots(count *big.Int) (*types.Transaction, error) {
+ return _SSTOREStorageBloater.Contract.CreateSlots(&_SSTOREStorageBloater.TransactOpts, count)
+}
+
+// CreateSlots is a paid mutator transaction binding the contract method 0xe3b393a4.
+//
+// Solidity: function createSlots(uint256 count) returns()
+func (_SSTOREStorageBloater *SSTOREStorageBloaterTransactorSession) CreateSlots(count *big.Int) (*types.Transaction, error) {
+ return _SSTOREStorageBloater.Contract.CreateSlots(&_SSTOREStorageBloater.TransactOpts, count)
+}
diff --git a/scenarios/statebloat/rand_sstore/contract/SSTOREStorageBloater.sol b/scenarios/statebloat/rand_sstore/contract/SSTOREStorageBloater.sol
new file mode 100644
index 00000000..6a48bf81
--- /dev/null
+++ b/scenarios/statebloat/rand_sstore/contract/SSTOREStorageBloater.sol
@@ -0,0 +1,45 @@
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.0;
+
+/**
+ * @title SSTOREStorageBloater
+ * @dev Optimized contract for maximum SSTORE operations using curve25519 prime (2^255 - 19)
+ * Uses assembly for gas efficiency and distributes keys across storage space
+ */
+contract SSTOREStorageBloater {
+ // Counter to track total slots created (stored at slot 0)
+ uint256 private counter;
+
+ // curve25519 prime: 2^255 - 19 = 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed
+ uint256 private constant CURVE25519_PRIME =
+ 0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffed;
+
+ /**
+ * @dev Creates new storage slots (0 -> non-zero transition, ~20k gas each)
+ * @param count Number of slots to create
+ */
+ function createSlots(uint256 count) external {
+ assembly {
+ // Load current counter from storage slot 0
+ let prime := CURVE25519_PRIME
+ let endCounter := count
+
+ // Calculate pseudo-random offset using block data
+ // XOR timestamp with previous block hash for randomness
+ let offset := xor(timestamp(), blockhash(sub(number(), 1)))
+
+ // Create slots with distributed keys
+ for {
+ let i := 0
+ } lt(i, endCounter) {
+ i := add(i, 1)
+ } {
+ // Calculate key = (offset + i) * CURVE25519_PRIME
+ let key := mulmod(add(offset, i), prime, not(0))
+
+ // Store value = key
+ sstore(key, key)
+ }
+ }
+ }
+}
diff --git a/scenarios/statebloat/rand_sstore/contract/compile.sh b/scenarios/statebloat/rand_sstore/contract/compile.sh
new file mode 100755
index 00000000..4c5e0591
--- /dev/null
+++ b/scenarios/statebloat/rand_sstore/contract/compile.sh
@@ -0,0 +1,35 @@
+#!/bin/bash
+
+compile_contract() {
+ local workdir=$1
+ local solc_version=$2
+ local solc_args=$3
+ local contract_file=$4
+ local contract_name=$5
+
+ if [ -z "$contract_name" ]; then
+ contract_name="$contract_file"
+ fi
+
+ #echo "docker run --rm -v $workdir:/contracts ethereum/solc:$solc_version /contracts/$contract_file.sol --combined-json abi,bin $solc_args"
+ local contract_json=$(docker run --rm -v $workdir:/contracts ethereum/solc:$solc_version /contracts/$contract_file.sol --combined-json abi,bin $solc_args)
+
+ local contract_abi=$(echo "$contract_json" | jq -r '.contracts["/contracts/'$contract_file'.sol:'$contract_name'"].abi')
+ if [ "$contract_abi" == "null" ]; then
+ contract_abi=$(echo "$contract_json" | jq -r '.contracts["contracts/'$contract_file'.sol:'$contract_name'"].abi')
+ fi
+
+ local contract_bin=$(echo "$contract_json" | jq -r '.contracts["/contracts/'$contract_file'.sol:'$contract_name'"].bin')
+ if [ "$contract_bin" == "null" ]; then
+ contract_bin=$(echo "$contract_json" | jq -r '.contracts["contracts/'$contract_file'.sol:'$contract_name'"].bin')
+ fi
+
+ echo "$contract_abi" > $contract_name.abi
+ echo "$contract_bin" > $contract_name.bin
+ abigen --bin=./$contract_name.bin --abi=./$contract_name.abi --pkg=contract --out=$contract_name.go --type $contract_name
+ rm $contract_name.bin $contract_name.abi
+ echo "$contract_json" | jq > $contract_name.output.json
+}
+
+# SSTOREStorageBloater
+compile_contract "$(pwd)" 0.8.0 "--optimize --optimize-runs 999999" SSTOREStorageBloater
diff --git a/scenarios/statebloat/rand_sstore/rand_sstore_bloater.go b/scenarios/statebloat/rand_sstore/rand_sstore_bloater.go
new file mode 100644
index 00000000..5ad0ea89
--- /dev/null
+++ b/scenarios/statebloat/rand_sstore/rand_sstore_bloater.go
@@ -0,0 +1,433 @@
+package sbrandsstore
+
+import (
+ "context"
+ _ "embed"
+ "encoding/json"
+ "fmt"
+ "math/big"
+ "os"
+ "strings"
+ "sync"
+ "time"
+
+ "github.com/ethereum/go-ethereum/accounts/abi"
+ "github.com/ethereum/go-ethereum/accounts/abi/bind"
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/holiman/uint256"
+ "github.com/sirupsen/logrus"
+ "github.com/spf13/pflag"
+ "gopkg.in/yaml.v3"
+
+ "github.com/ethpandaops/spamoor/scenario"
+ "github.com/ethpandaops/spamoor/scenarios/statebloat/rand_sstore/contract"
+ "github.com/ethpandaops/spamoor/spamoor"
+ "github.com/ethpandaops/spamoor/txbuilder"
+ "github.com/ethpandaops/spamoor/utils"
+)
+
+// Constants for SSTORE operations
+const (
+ // Base Ethereum transaction cost
+ BaseTxCost = uint64(21000)
+
+ // Function call overhead (measured from actual transactions)
+ // Includes: function selector, ABI decoding, contract loading, etc.
+ FunctionCallOverhead = uint64(1556)
+
+ // Gas cost per iteration (measured from actual transactions)
+ // Includes: SSTORE (0βnon-zero), MULMOD, loop overhead, stack operations
+ // Measured: 22,165 gas per iteration
+ GasPerNewSlotIteration = uint64(22165)
+
+ // Contract deployment and call overhead
+ EstimatedDeployGas = uint64(500000) // Deployment gas for our contract
+
+ // Safety margins and multipliers
+ GasLimitSafetyMargin = 0.99 // Use 99% of block gas limit (1% margin for gas price variations)
+)
+
+// BlockInfo stores block information for each storage round
+type BlockInfo struct {
+ BlockNumber uint64 `json:"block_number"`
+ Timestamp uint64 `json:"timestamp"`
+}
+
+// DeploymentData tracks a single contract deployment and its storage rounds
+type DeploymentData struct {
+ StorageRounds []BlockInfo `json:"storage_rounds"`
+}
+
+// DeploymentFile represents the entire deployment tracking file
+type DeploymentFile map[string]*DeploymentData // key is contract address
+
+type ScenarioOptions struct {
+ BaseFee uint64 `yaml:"base_fee"`
+ TipFee uint64 `yaml:"tip_fee"`
+ DeploymentsFile string `yaml:"deployments_file"`
+}
+
+type Scenario struct {
+ options ScenarioOptions
+ logger *logrus.Entry
+ walletPool *spamoor.WalletPool
+
+ // Contract state
+ contractAddress common.Address
+ contractABI abi.ABI
+ contractInstance *contract.SSTOREStorageBloater // Generated contract binding
+ isDeployed bool
+ deployMutex sync.Mutex
+
+ // Scenario state
+ totalSlots uint64 // Total number of slots created
+ roundNumber uint64 // Current round number for SSTORE bloating
+
+ // Adaptive gas tracking
+ actualGasPerNewSlotIteration uint64 // Dynamically adjusted based on actual usage
+ successfulSlotCounts map[uint64]bool // Track successful slot counts to avoid retries
+}
+
+var ScenarioName = "statebloat-rand-sstore"
+var ScenarioDefaultOptions = ScenarioOptions{
+ BaseFee: 10, // 10 gwei default
+ TipFee: 2, // 2 gwei default
+ DeploymentsFile: "",
+}
+var ScenarioDescriptor = scenario.Descriptor{
+ Name: ScenarioName,
+ Description: "Maximum state bloat via SSTORE operations using curve25519 prime dispersion",
+ DefaultOptions: ScenarioDefaultOptions,
+ NewScenario: newScenario,
+}
+
+func newScenario(logger logrus.FieldLogger) scenario.Scenario {
+ return &Scenario{
+ logger: logger.WithField("scenario", ScenarioName),
+ actualGasPerNewSlotIteration: GasPerNewSlotIteration, // Start with estimated values
+ successfulSlotCounts: make(map[uint64]bool),
+ }
+}
+
+func (s *Scenario) Flags(flags *pflag.FlagSet) error {
+ flags.Uint64Var(&s.options.BaseFee, "basefee", ScenarioDefaultOptions.BaseFee, "Base fee per gas in gwei")
+ flags.Uint64Var(&s.options.TipFee, "tipfee", ScenarioDefaultOptions.TipFee, "Tip fee per gas in gwei")
+ flags.StringVar(&s.options.DeploymentsFile, "deployments-file", ScenarioDefaultOptions.DeploymentsFile, "Deployments file")
+ return nil
+}
+
+func (s *Scenario) Init(options *scenario.Options) error {
+ s.walletPool = options.WalletPool
+
+ if options.Config != "" {
+ err := yaml.Unmarshal([]byte(options.Config), &s.options)
+ if err != nil {
+ return fmt.Errorf("failed to unmarshal config: %w", err)
+ }
+ }
+
+ s.walletPool.SetWalletCount(1)
+ s.walletPool.SetRefillAmount(uint256.NewInt(0).Mul(uint256.NewInt(20), uint256.NewInt(1000000000000000000))) // 20 ETH
+ s.walletPool.SetRefillBalance(uint256.NewInt(0).Mul(uint256.NewInt(10), uint256.NewInt(1000000000000000000))) // 10 ETH
+
+ // register well known wallets
+ s.walletPool.AddWellKnownWallet(&spamoor.WellKnownWalletConfig{
+ Name: "deployer",
+ RefillAmount: uint256.NewInt(2000000000000000000), // 2 ETH
+ RefillBalance: uint256.NewInt(1000000000000000000), // 1 ETH
+ })
+
+ // Parse contract ABI
+ parsedABI, err := abi.JSON(strings.NewReader(string(contract.SSTOREStorageBloaterMetaData.ABI)))
+ if err != nil {
+ return fmt.Errorf("failed to parse contract ABI: %w", err)
+ }
+ s.contractABI = parsedABI
+
+ return nil
+}
+
+func (s *Scenario) Config() string {
+ yamlBytes, _ := yaml.Marshal(&s.options)
+ return string(yamlBytes)
+}
+
+// loadDeploymentFile loads the deployment tracking file or creates an empty one
+func (s *Scenario) loadDeploymentFile() (DeploymentFile, error) {
+ if s.options.DeploymentsFile == "" {
+ return make(DeploymentFile), nil
+ }
+
+ data, err := os.ReadFile(s.options.DeploymentsFile)
+ if err != nil {
+ if os.IsNotExist(err) {
+ // File doesn't exist, return empty map
+ return make(DeploymentFile), nil
+ }
+ return nil, fmt.Errorf("failed to read deployment file: %w", err)
+ }
+
+ var deployments DeploymentFile
+ if err := json.Unmarshal(data, &deployments); err != nil {
+ return nil, fmt.Errorf("failed to unmarshal deployment file: %w", err)
+ }
+
+ return deployments, nil
+}
+
+// saveDeploymentFile saves the deployment tracking file
+func (s *Scenario) saveDeploymentFile(deployments DeploymentFile) error {
+ if s.options.DeploymentsFile == "" {
+ return nil
+ }
+
+ data, err := json.MarshalIndent(deployments, "", " ")
+ if err != nil {
+ return fmt.Errorf("failed to marshal deployment file: %w", err)
+ }
+
+ if err := os.WriteFile(s.options.DeploymentsFile, data, 0644); err != nil {
+ return fmt.Errorf("failed to write deployment file: %w", err)
+ }
+
+ return nil
+}
+
+func (s *Scenario) deployContract(ctx context.Context) error {
+ s.deployMutex.Lock()
+ defer s.deployMutex.Unlock()
+
+ if s.isDeployed {
+ return nil
+ }
+
+ s.logger.Info("Deploying SSTOREStorageBloater contract...")
+
+ client := s.walletPool.GetClient(spamoor.SelectClientByIndex, 0, "")
+ if client == nil {
+ return fmt.Errorf("no client available")
+ }
+
+ wallet := s.walletPool.GetWellKnownWallet("deployer")
+ if wallet == nil {
+ return fmt.Errorf("no wallet available")
+ }
+
+ feeCap, tipCap, err := s.walletPool.GetTxPool().GetSuggestedFees(client, s.options.BaseFee, s.options.TipFee)
+ if err != nil {
+ return err
+ }
+
+ tx, err := wallet.BuildBoundTx(ctx, &txbuilder.TxMetadata{
+ GasFeeCap: uint256.MustFromBig(feeCap),
+ GasTipCap: uint256.MustFromBig(tipCap),
+ Gas: 2000000,
+ Value: uint256.NewInt(0),
+ }, func(transactOpts *bind.TransactOpts) (*types.Transaction, error) {
+ _, deployTx, _, err := contract.DeploySSTOREStorageBloater(transactOpts, client.GetEthClient())
+ return deployTx, err
+ })
+
+ if err != nil {
+ return err
+ }
+
+ txreceipt, err := s.walletPool.GetTxPool().SendAndAwaitTransaction(ctx, wallet, tx, &spamoor.SendTransactionOptions{
+ Client: client,
+ Rebroadcast: true,
+ })
+ if err != nil {
+ return err
+ }
+
+ s.contractAddress = txreceipt.ContractAddress
+ s.contractInstance, err = contract.NewSSTOREStorageBloater(s.contractAddress, client.GetEthClient())
+ if err != nil {
+ return err
+ }
+ s.isDeployed = true
+
+ // No need to reset nonce - the wallet manager handles it automatically
+
+ // Track deployment in JSON file
+ deployments, err := s.loadDeploymentFile()
+ if err != nil {
+ s.logger.Warnf("failed to load deployment file: %v", err)
+ deployments = make(DeploymentFile)
+ }
+
+ // Initialize deployment data for this contract
+ deployments[s.contractAddress.Hex()] = &DeploymentData{
+ StorageRounds: []BlockInfo{},
+ }
+
+ if err := s.saveDeploymentFile(deployments); err != nil {
+ s.logger.Warnf("failed to save deployment file: %v", err)
+ }
+
+ s.logger.WithField("address", s.contractAddress.Hex()).Info("SSTOREStorageBloater contract deployed successfully")
+
+ return nil
+}
+
+func (s *Scenario) Run(ctx context.Context) error {
+ s.logger.Infof("starting scenario: %s", ScenarioName)
+ defer s.logger.Infof("scenario %s finished.", ScenarioName)
+
+ // Deploy the contract if not already deployed
+ if !s.isDeployed {
+ if err := s.deployContract(ctx); err != nil {
+ return fmt.Errorf("failed to deploy contract: %w", err)
+ }
+ }
+
+ // Get network parameters
+ client := s.walletPool.GetClient(spamoor.SelectClientByIndex, 0, "")
+ if client == nil {
+ return fmt.Errorf("no client available")
+ }
+
+ // Main loop - alternate between creating and updating slots
+ for {
+ select {
+ case <-ctx.Done():
+ return ctx.Err()
+ default:
+ }
+
+ blockGasLimit, err := s.walletPool.GetTxPool().GetCurrentGasLimitWithInit()
+ if err != nil {
+ s.logger.Warnf("failed to get current gas limit: %v", err)
+ time.Sleep(5 * time.Second)
+ continue
+ }
+
+ targetGas := uint64(float64(blockGasLimit) * GasLimitSafetyMargin)
+
+ // Never stop spamming SSTORE operations.
+ s.roundNumber++
+ if err := s.executeCreateSlots(ctx, targetGas, blockGasLimit); err != nil {
+ s.logger.Errorf("failed to create slots: %v", err)
+ time.Sleep(5 * time.Second)
+ continue
+ }
+ }
+}
+
+func (s *Scenario) executeCreateSlots(ctx context.Context, targetGas uint64, blockGasLimit uint64) error {
+ // Calculate how many slots we can create with precise gas costs
+ // Account for base tx cost and function overhead
+ availableGas := targetGas - BaseTxCost - FunctionCallOverhead
+ slotsToCreate := availableGas / s.actualGasPerNewSlotIteration // Integer division rounds down
+
+ if slotsToCreate == 0 {
+ return fmt.Errorf("not enough gas to create any slots")
+ }
+
+ // Get client and wallet
+ client := s.walletPool.GetClient(spamoor.SelectClientByIndex, 0, "")
+ if client == nil {
+ return fmt.Errorf("no client available")
+ }
+
+ wallet := s.walletPool.GetWallet(spamoor.SelectWalletByIndex, 0)
+ if wallet == nil {
+ return fmt.Errorf("no wallet available")
+ }
+
+ // Create transaction options
+ feeCap, tipCap, err := s.walletPool.GetTxPool().GetSuggestedFees(client, s.options.BaseFee, s.options.TipFee)
+ if err != nil {
+ return fmt.Errorf("failed to get suggested fees: %w", err)
+ }
+
+ tx, err := wallet.BuildBoundTx(ctx, &txbuilder.TxMetadata{
+ GasFeeCap: uint256.MustFromBig(feeCap),
+ GasTipCap: uint256.MustFromBig(tipCap),
+ Gas: targetGas,
+ Value: uint256.NewInt(0),
+ }, func(transactOpts *bind.TransactOpts) (*types.Transaction, error) {
+ return s.contractInstance.CreateSlots(transactOpts, big.NewInt(int64(slotsToCreate)))
+ })
+ if err != nil {
+ return err
+ }
+
+ txreceipt, txerr := s.walletPool.GetTxPool().SendAndAwaitTransaction(ctx, wallet, tx, &spamoor.SendTransactionOptions{
+ Client: client,
+ Rebroadcast: true,
+ LogFn: spamoor.GetDefaultLogFn(s.logger, "rand-sstore", "", tx),
+ })
+
+ if txerr != nil {
+ return fmt.Errorf("transaction failed: %w", txerr)
+ }
+
+ if txreceipt == nil || txreceipt.Status != 1 {
+ // Increase our gas estimate by 10%
+ s.actualGasPerNewSlotIteration = uint64(float64(s.actualGasPerNewSlotIteration) * 1.1)
+
+ return fmt.Errorf("transaction rejected")
+ }
+
+ txFees := utils.GetTransactionFees(tx, txreceipt)
+ s.logger.WithField("rpc", client.GetName()).Debugf(" transaction confirmed in block #%v. total fee: %v gwei (base: %v) logs: %v", txreceipt.BlockNumber.String(), txFees.TotalFeeGwei(), txFees.TxBaseFeeGwei(), len(txreceipt.Logs))
+
+ // Mark this slot count as successful
+ s.successfulSlotCounts[slotsToCreate] = true
+
+ // Update metrics and adaptive gas tracking
+ s.totalSlots += slotsToCreate
+ totalOverhead := BaseTxCost + FunctionCallOverhead
+ actualGasPerSlotIteration := (txreceipt.GasUsed - totalOverhead) / slotsToCreate
+
+ // Update our gas estimate using exponential moving average
+ // New estimate = 0.7 * old estimate + 0.3 * actual
+ s.actualGasPerNewSlotIteration = uint64(float64(s.actualGasPerNewSlotIteration)*0.7 + float64(actualGasPerSlotIteration)*0.3)
+
+ // Get previous block info for tracking
+ prevBlockNumber := txreceipt.BlockNumber.Uint64() - 1
+
+ prevBlock, err := client.GetEthClient().BlockByNumber(ctx, big.NewInt(int64(prevBlockNumber)))
+ if err != nil {
+ s.logger.Warnf("failed to get previous block info: %v", err)
+ } else {
+ // Track this storage round in deployment file
+ deployments, err := s.loadDeploymentFile()
+ if err != nil {
+ s.logger.Warnf("failed to load deployment file: %v", err)
+ } else if deployments != nil {
+ contractAddr := s.contractAddress.Hex()
+ if deploymentData, exists := deployments[contractAddr]; exists {
+ // Append new block info
+ deploymentData.StorageRounds = append(deploymentData.StorageRounds, BlockInfo{
+ BlockNumber: prevBlockNumber,
+ Timestamp: prevBlock.Time(),
+ })
+
+ if err := s.saveDeploymentFile(deployments); err != nil {
+ s.logger.Warnf("failed to save deployment file: %v", err)
+ }
+ }
+ }
+ }
+
+ // Calculate MB written in this transaction (64 bytes per slot: 32 byte key + 32 byte value)
+ mbWrittenThisTx := float64(slotsToCreate*64) / (1024 * 1024)
+
+ // Calculate block utilization percentage
+ blockUtilization := float64(txreceipt.GasUsed) / float64(blockGasLimit) * 100
+
+ s.logger.WithFields(logrus.Fields{
+ "block_number": txreceipt.BlockNumber,
+ "gas_used": txreceipt.GasUsed,
+ "slots_created": slotsToCreate,
+ "gas_per_slot": actualGasPerSlotIteration,
+ "total_slots": s.totalSlots,
+ "mb_written": mbWrittenThisTx,
+ "block_utilization": fmt.Sprintf("%.2f%%", blockUtilization),
+ }).Info("SSTORE bloating round summary")
+
+ return nil
+}
diff --git a/spamoor/walletpool.go b/spamoor/walletpool.go
index 3fba6ac5..949611ec 100644
--- a/spamoor/walletpool.go
+++ b/spamoor/walletpool.go
@@ -55,6 +55,16 @@ type WellKnownWalletConfig struct {
VeryWellKnown bool
}
+// ExternalWalletConfig defines configuration for an external wallet imported into the pool.
+// External wallets are not used for GetWallet calls but can optionally be funded.
+type ExternalWalletConfig struct {
+ Name string
+ Wallet *Wallet
+ RefillAmount *uint256.Int
+ RefillBalance *uint256.Int
+ EnableFunding bool
+}
+
// WalletPool manages a pool of child wallets derived from a root wallet with automatic funding
// and balance monitoring. It provides wallet selection strategies, automatic refills when balances
// drop below thresholds, and batch funding operations for efficiency.
@@ -70,9 +80,11 @@ type WalletPool struct {
childWallets []*Wallet
wellKnownNames []*WellKnownWalletConfig
wellKnownWallets map[string]*Wallet
+ externalWallets []*ExternalWalletConfig
selectionMutex sync.Mutex
rrWalletIdx int
reclaimedFunds bool
+ preparedWallets bool
// Optional callback to track transaction results for metrics
transactionTracker func(err error)
@@ -112,6 +124,7 @@ func NewWalletPool(ctx context.Context, logger logrus.FieldLogger, rootWallet *R
txpool: txpool,
childWallets: make([]*Wallet, 0),
wellKnownWallets: make(map[string]*Wallet),
+ externalWallets: make([]*ExternalWalletConfig, 0),
runFundings: true,
lowBalanceNotifyChan: make(chan struct{}, 100), // buffered channel
}
@@ -179,6 +192,16 @@ func (pool *WalletPool) AddWellKnownWallet(config *WellKnownWalletConfig) {
pool.wellKnownNames = append(pool.wellKnownNames, config)
}
+// AddExternalWallet adds an external wallet with custom funding configuration.
+// External wallets are not part of the deterministic wallet generation but can optionally be tracked and funded.
+func (pool *WalletPool) AddExternalWallet(config *ExternalWalletConfig) {
+ pool.externalWallets = append(pool.externalWallets, config)
+
+ if pool.runFundings && config.EnableFunding && pool.preparedWallets {
+ config.Wallet.setLowBalanceNotification(pool.lowBalanceNotifyChan, config.RefillBalance.ToBig())
+ }
+}
+
// SetRefillAmount sets the amount sent to wallets when they need funding.
func (pool *WalletPool) SetRefillAmount(amount *uint256.Int) {
pool.config.RefillAmount = amount
@@ -189,6 +212,11 @@ func (pool *WalletPool) SetRefillBalance(balance *uint256.Int) {
pool.config.RefillBalance = balance
}
+// GetWalletSeed returns the seed used for deterministic wallet generation.
+func (pool *WalletPool) GetWalletSeed() string {
+ return pool.config.WalletSeed
+}
+
// SetWalletSeed sets the seed used for deterministic wallet generation.
// The same seed will always generate the same set of wallets.
func (pool *WalletPool) SetWalletSeed(seed string) {
@@ -260,6 +288,17 @@ func (pool *WalletPool) GetWellKnownWallet(name string) *Wallet {
return pool.wellKnownWallets[name]
}
+// GetExternalWallet returns an external wallet by name.
+// Returns nil if the wallet doesn't exist.
+func (pool *WalletPool) GetExternalWallet(name string) *Wallet {
+ for _, config := range pool.externalWallets {
+ if config.Name == name {
+ return config.Wallet
+ }
+ }
+ return nil
+}
+
// GetVeryWellKnownWalletAddress derives the address of a "very well known" wallet
// without registering it. Very well known wallets are derived only from the root
// wallet's private key and the wallet name, without any scenario seed.
@@ -308,17 +347,30 @@ func (pool *WalletPool) GetWalletName(address common.Address) string {
}
}
+ for _, config := range pool.externalWallets {
+ if config.Wallet != nil && config.Wallet.GetAddress() == address {
+ return config.Name
+ }
+ }
+
return "unknown"
}
-// GetAllWallets returns a slice containing all wallets (well-known and child wallets).
+// GetAllWallets returns a slice containing all wallets (well-known, external, and child wallets).
// The root wallet is not included in this list.
func (pool *WalletPool) GetAllWallets() []*Wallet {
- wallets := make([]*Wallet, len(pool.childWallets)+len(pool.wellKnownWallets))
- for i, config := range pool.wellKnownNames {
- wallets[i] = pool.wellKnownWallets[config.Name]
+ totalCount := len(pool.childWallets) + len(pool.wellKnownWallets) + len(pool.externalWallets)
+ wallets := make([]*Wallet, totalCount)
+ idx := 0
+ for _, config := range pool.wellKnownNames {
+ wallets[idx] = pool.wellKnownWallets[config.Name]
+ idx++
+ }
+ for _, config := range pool.externalWallets {
+ wallets[idx] = config.Wallet
+ idx++
}
- copy(wallets[len(pool.wellKnownWallets):], pool.childWallets)
+ copy(wallets[idx:], pool.childWallets)
return wallets
}
@@ -337,13 +389,14 @@ func (pool *WalletPool) GetWalletCount() uint64 {
// then funds any wallets below the refill threshold. Also starts the
// automatic balance monitoring if funding is enabled.
func (pool *WalletPool) PrepareWallets() error {
- if len(pool.childWallets) > 0 {
+ if pool.preparedWallets {
return nil
}
+ pool.preparedWallets = true
seed := pool.config.WalletSeed
- if pool.config.WalletCount == 0 && len(pool.wellKnownWallets) == 0 {
+ if pool.config.WalletCount == 0 && len(pool.wellKnownWallets) == 0 && len(pool.externalWallets) == 0 {
pool.childWallets = make([]*Wallet, 0)
} else {
var client *Client
@@ -392,6 +445,52 @@ func (pool *WalletPool) PrepareWallets() error {
}(config)
}
+ for _, config := range pool.externalWallets {
+ if config.EnableFunding && pool.runFundings {
+ wg.Add(1)
+ wl <- true
+ go func(config *ExternalWalletConfig) {
+ defer func() {
+ <-wl
+ wg.Done()
+ }()
+ if walletErr != nil {
+ return
+ }
+
+ // Set up low balance notification
+ if pool.runFundings {
+ config.Wallet.setLowBalanceNotification(pool.lowBalanceNotifyChan, config.RefillBalance.ToBig())
+ }
+
+ err := client.UpdateWallet(pool.ctx, config.Wallet)
+ if err != nil {
+ pool.logger.Errorf("could not update external wallet %v: %v", config.Name, err)
+ walletErr = err
+ return
+ }
+
+ refillAmount := pool.config.RefillAmount
+ refillBalance := pool.config.RefillBalance
+ if config.RefillAmount != nil {
+ refillAmount = config.RefillAmount
+ }
+ if config.RefillBalance != nil {
+ refillBalance = config.RefillBalance
+ }
+
+ if config.Wallet.GetBalance().Cmp(refillBalance.ToBig()) < 0 {
+ walletsMutex.Lock()
+ fundingReqs = append(fundingReqs, &FundingRequest{
+ Wallet: config.Wallet,
+ Amount: refillAmount,
+ })
+ walletsMutex.Unlock()
+ }
+ }(config)
+ }
+ }
+
for childIdx := uint64(0); childIdx < pool.config.WalletCount; childIdx++ {
wg.Add(1)
wl <- true
@@ -618,7 +717,8 @@ func (pool *WalletPool) resupplyChildWallets() error {
wl := make(chan bool, 50)
wellKnownCount := uint64(len(pool.wellKnownWallets))
- fundingReqs := make([]*FundingRequest, 0, pool.config.WalletCount+wellKnownCount)
+ externalCount := uint64(len(pool.externalWallets))
+ fundingReqs := make([]*FundingRequest, 0, pool.config.WalletCount+wellKnownCount+externalCount)
reqsMutex := &sync.Mutex{}
for idx, config := range pool.wellKnownNames {
@@ -665,6 +765,47 @@ func (pool *WalletPool) resupplyChildWallets() error {
}(idx, wellKnownWallet, config)
}
+ for _, config := range pool.externalWallets {
+ if config.EnableFunding {
+ wg.Add(1)
+ wl <- true
+ go func(config *ExternalWalletConfig) {
+ defer func() {
+ <-wl
+ wg.Done()
+ }()
+ if walletErr != nil {
+ return
+ }
+
+ refillAmount := pool.config.RefillAmount
+ refillBalance := pool.config.RefillBalance
+
+ if config.RefillAmount != nil {
+ refillAmount = config.RefillAmount
+ }
+ if config.RefillBalance != nil {
+ refillBalance = config.RefillBalance
+ }
+
+ err := client.UpdateWallet(pool.ctx, config.Wallet)
+ if err != nil {
+ walletErr = err
+ return
+ }
+
+ if config.Wallet.GetBalance().Cmp(refillBalance.ToBig()) < 0 {
+ reqsMutex.Lock()
+ fundingReqs = append(fundingReqs, &FundingRequest{
+ Wallet: config.Wallet,
+ Amount: refillAmount,
+ })
+ reqsMutex.Unlock()
+ }
+ }(config)
+ }
+ }
+
for childIdx := uint64(0); childIdx < pool.config.WalletCount; childIdx++ {
wg.Add(1)
wl <- true
@@ -930,7 +1071,7 @@ func (pool *WalletPool) buildWalletReclaimTx(ctx context.Context, childWallet *W
return tx, nil
}
-// collectPoolWallets adds all wallets (root, child, and well-known) to the provided map.
+// collectPoolWallets adds all wallets (root, child, well-known, and external) to the provided map.
// This is used by the transaction pool to track which addresses belong to this wallet pool.
func (pool *WalletPool) collectPoolWallets(walletMap map[common.Address]*Wallet) {
walletMap[pool.rootWallet.wallet.GetAddress()] = pool.rootWallet.wallet
@@ -940,6 +1081,11 @@ func (pool *WalletPool) collectPoolWallets(walletMap map[common.Address]*Wallet)
for _, wallet := range pool.wellKnownWallets {
walletMap[wallet.GetAddress()] = wallet
}
+ for _, config := range pool.externalWallets {
+ if config.Wallet != nil {
+ walletMap[config.Wallet.GetAddress()] = config.Wallet
+ }
+ }
}
// CheckChildWalletBalance checks and refills a specific wallet if needed.
@@ -1041,6 +1187,11 @@ func (pool *WalletPool) ReclaimFunds(ctx context.Context, client *Client) error
for _, wallet := range pool.wellKnownWallets {
reclaimWallet(wallet)
}
+ for _, config := range pool.externalWallets {
+ if config.Wallet != nil {
+ reclaimWallet(config.Wallet)
+ }
+ }
reclaimWg.Wait()
if len(reclaimTxs) > 0 {