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 94b5acfa..6b225d1f 100644 --- a/README.md +++ b/README.md @@ -57,6 +57,7 @@ spamoor eoatx --privkey="0x..." \ Spamoor provides a comprehensive suite of transaction scenarios for different testing needs: + | Scenario | Description | |----------|-------------| | [`eoatx`](./scenarios/eoatx/README.md) | **EOA Transactions** - Send standard ETH transfers with configurable amounts | diff --git a/go.mod b/go.mod index d1150dbc..34285f22 100644 --- a/go.mod +++ b/go.mod @@ -16,6 +16,7 @@ require ( github.com/prometheus/client_golang v1.22.0 github.com/sirupsen/logrus v1.9.3 github.com/spf13/pflag v1.0.6 + github.com/stretchr/testify v1.10.0 github.com/swaggo/http-swagger v1.3.4 github.com/swaggo/swag v1.16.4 github.com/tdewolff/minify v2.3.6+incompatible @@ -34,6 +35,7 @@ require ( github.com/consensys/bavard v0.1.27 // indirect github.com/consensys/gnark-crypto v0.16.0 // indirect github.com/crate-crypto/go-ipa v0.0.0-20240724233137-53bbb0ceb27a // indirect + github.com/davecgh/go-spew v1.1.1 // indirect github.com/deckarep/golang-set/v2 v2.6.0 // indirect github.com/decred/dcrd/dcrec/secp256k1/v4 v4.0.1 // indirect github.com/dustin/go-humanize v1.0.1 // indirect @@ -54,6 +56,7 @@ require ( github.com/mmcloughlin/addchain v0.4.0 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/ncruces/go-strftime v0.1.9 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect github.com/prometheus/client_model v0.6.1 // indirect github.com/prometheus/common v0.62.0 // indirect github.com/prometheus/procfs v0.16.1 // indirect diff --git a/scenarios/scenarios.go b/scenarios/scenarios.go index b6e9c9ce..8b4a971d 100644 --- a/scenarios/scenarios.go +++ b/scenarios/scenarios.go @@ -16,7 +16,13 @@ import ( "github.com/ethpandaops/spamoor/scenarios/gasburnertx" "github.com/ethpandaops/spamoor/scenarios/geastx" "github.com/ethpandaops/spamoor/scenarios/setcodetx" + contractdeploy "github.com/ethpandaops/spamoor/scenarios/statebloat/contract_deploy" + eoadelegation "github.com/ethpandaops/spamoor/scenarios/statebloat/eoa_delegation" + erc20maxtransfers "github.com/ethpandaops/spamoor/scenarios/statebloat/erc20_max_transfers" + //extcodesizeoverload "github.com/ethpandaops/spamoor/scenarios/statebloat/extcodesize-overload" + randsstorebloater "github.com/ethpandaops/spamoor/scenarios/statebloat/rand_sstore_bloater" "github.com/ethpandaops/spamoor/scenarios/storagespam" + uniswapswaps "github.com/ethpandaops/spamoor/scenarios/uniswap-swaps" "github.com/ethpandaops/spamoor/scenarios/wallets" "github.com/ethpandaops/spamoor/scenarios/xentoken" @@ -39,10 +45,19 @@ var ScenarioDescriptors = []*scenario.Descriptor{ &gasburnertx.ScenarioDescriptor, &geastx.ScenarioDescriptor, &setcodetx.ScenarioDescriptor, + &randsstorebloater.ScenarioDescriptor, + &uniswapswaps.ScenarioDescriptor, + &wallets.ScenarioDescriptor, + &contractdeploy.ScenarioDescriptor, + &eoadelegation.ScenarioDescriptor, &storagespam.ScenarioDescriptor, &uniswapswaps.ScenarioDescriptor, &wallets.ScenarioDescriptor, + &contractdeploy.ScenarioDescriptor, + &eoadelegation.ScenarioDescriptor, + &erc20maxtransfers.ScenarioDescriptor, &xentoken.ScenarioDescriptor, + } // GetScenario finds and returns a scenario descriptor by name. 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/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.abi b/scenarios/statebloat/contract_deploy/contract/StateBloatToken.abi new file mode 100644 index 00000000..0f67a8f3 --- /dev/null +++ b/scenarios/statebloat/contract_deploy/contract/StateBloatToken.abi @@ -0,0 +1 @@ +[{"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":[{"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":"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"}] \ No newline at end of file diff --git a/scenarios/statebloat/contract_deploy/contract/StateBloatToken.bin b/scenarios/statebloat/contract_deploy/contract/StateBloatToken.bin new file mode 100644 index 00000000..755497f1 --- /dev/null +++ b/scenarios/statebloat/contract_deploy/contract/StateBloatToken.bin @@ -0,0 +1 @@ +60a060405234801561000f575f5ffd5b50604051615fba380380615fba833981810160405281019061003191906101f4565b6040518060400160405280601181526020017f537461746520426c6f617420546f6b656e0000000000000000000000000000008152505f90816100749190610453565b506040518060400160405280600381526020017f5342540000000000000000000000000000000000000000000000000000000000815250600190816100b99190610453565b50601260025f6101000a81548160ff021916908360ff160217905550806080818152505060025f9054906101000a900460ff16600a6100f8919061068a565b620f424061010691906106d4565b60038190555060035460045f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055503373ffffffffffffffffffffffffffffffffffffffff165f73ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef6003546040516101af9190610724565b60405180910390a35061073d565b5f5ffd5b5f819050919050565b6101d3816101c1565b81146101dd575f5ffd5b50565b5f815190506101ee816101ca565b92915050565b5f60208284031215610209576102086101bd565b5b5f610216848285016101e0565b91505092915050565b5f81519050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f600282049050600182168061029a57607f821691505b6020821081036102ad576102ac610256565b5b50919050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f6008830261030f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff826102d4565b61031986836102d4565b95508019841693508086168417925050509392505050565b5f819050919050565b5f61035461034f61034a846101c1565b610331565b6101c1565b9050919050565b5f819050919050565b61036d8361033a565b6103816103798261035b565b8484546102e0565b825550505050565b5f5f905090565b610398610389565b6103a3818484610364565b505050565b5b818110156103c6576103bb5f82610390565b6001810190506103a9565b5050565b601f82111561040b576103dc816102b3565b6103e5846102c5565b810160208510156103f4578190505b610408610400856102c5565b8301826103a8565b50505b505050565b5f82821c905092915050565b5f61042b5f1984600802610410565b1980831691505092915050565b5f610443838361041c565b9150826002028217905092915050565b61045c8261021f565b67ffffffffffffffff81111561047557610474610229565b5b61047f8254610283565b61048a8282856103ca565b5f60209050601f8311600181146104bb575f84156104a9578287015190505b6104b38582610438565b86555061051a565b601f1984166104c9866102b3565b5f5b828110156104f0578489015182556001820191506020850194506020810190506104cb565b8683101561050d5784890151610509601f89168261041c565b8355505b6001600288020188555050505b505050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f8160011c9050919050565b5f5f8291508390505b60018511156105a4578086048111156105805761057f610522565b5b600185161561058f5780820291505b808102905061059d8561054f565b9450610564565b94509492505050565b5f826105bc5760019050610677565b816105c9575f9050610677565b81600181146105df57600281146105e957610618565b6001915050610677565b60ff8411156105fb576105fa610522565b5b8360020a91508482111561061257610611610522565b5b50610677565b5060208310610133831016604e8410600b841016171561064d5782820a90508381111561064857610647610522565b5b610677565b61065a848484600161055b565b9250905081840481111561067157610670610522565b5b81810290505b9392505050565b5f60ff82169050919050565b5f610694826101c1565b915061069f8361067e565b92506106cc7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff84846105ad565b905092915050565b5f6106de826101c1565b91506106e9836101c1565b92508282026106f7816101c1565b9150828204841483151761070e5761070d610522565b5b5092915050565b61071e816101c1565b82525050565b5f6020820190506107375f830184610715565b92915050565b6080516158656107555f395f61493601526158655ff3fe608060405234801561000f575f5ffd5b506004361061057f575f3560e01c8063657b6ef7116102e3578063ad8f42211161018b578063d9bb3174116100f2578063ee1682b6116100ab578063f8716f1411610085578063f8716f1414611243578063faf35ced14611261578063fe7d599614611291578063ffbf0469146112af5761057f565b8063ee1682b6146111e9578063f26c779b14611207578063f5f57381146112255761057f565b8063d9bb317414611111578063dc1d8a9b1461112f578063dd62ed3e1461114d578063e2d275301461117d578063e8c927b31461119b578063eb4329c8146111b95761057f565b8063bfa0b13311610144578063bfa0b1331461104b578063c2be97e314611069578063c958d4bf14611099578063cfd66863146110b7578063d101dcd0146110d5578063d7419469146110f35761057f565b8063ad8f422114610f73578063b1802b9a14610f91578063b2bb360e14610fc1578063b66dd75014610fdf578063b9a6d64514610ffd578063bb9bfe061461101b5761057f565b80637dffdc321161024a57806395d89b4111610203578063a891d4d4116101dd578063a891d4d414610ed7578063a9059cbb14610ef5578063aaa7af7014610f25578063acc5aee914610f435761057f565b806395d89b4114610e7d5780639c5dfe7314610e9b5780639df61a2514610eb95761057f565b80637dffdc3214610db75780637e54493714610dd55780637f34d94b14610df35780638619d60714610e115780638789ca6714610e2f5780638f4a840614610e5f5761057f565b806374f83d021161029c57806374f83d0214610cf157806377c0209e14610d0f578063792c7f3e14610d2d5780637a319c1814610d4b5780637c66673e14610d695780637c72ed0d14610d995761057f565b8063657b6ef714610c07578063672151fe14610c375780636abceacd14610c555780636c12ed2814610c7357806370a0823114610ca357806374e73fd314610cd35761057f565b80633125f37a116104465780634a2e93c6116103ad578063552a1b561161036657806361b970eb1161034057806361b970eb14610b8f578063639ec53a14610bad5780636547317414610bcb5780636578534c14610be95761057f565b8063552a1b5614610b2357806358b6a9bd14610b535780635af92c0514610b715761057f565b80634a2e93c614610a5d5780634b3c7f5f14610a7b5780634e1dbb8214610a995780634f5e555714610ab75780634f7bd75a14610ad557806354c2792014610b055761057f565b80633ea117ce116103ff5780633ea117ce146109975780634128a85d146109b5578063418b1816146109d357806342937dbd146109f157806343a6b92d14610a0f57806344050a2814610a2d5761057f565b80633125f37a146108bf578063313ce567146108dd57806334517f0b146108fb57806339e0bd12146109195780633a131990146109495780633b6be459146109795761057f565b80631b17c65c116104ea57806321ecd7a3116104a357806321ecd7a3146107e7578063239af2a51461080557806323b872dd146108235780632545d8b7146108535780632787325b14610871578063291c3bd71461088f5761057f565b80631b17c65c1461070f5780631bbffe6f1461073f5780631d527cde1461076f5780631eaa7c521461078d5780631f449589146107ab5780631fd298ec146107c95761057f565b806312901b421161053c57806312901b421461065b57806313ebb5ec1461067957806316a3045b1461069757806318160ddd146106b557806319cf6a91146106d35780631a97f18e146106f15761057f565b80630460faf61461058357806306fdde03146105b35780630717b161146105d1578063095ea7b3146105ef5780630cb7a9e71461061f5780631215a3ab1461063d575b5f5ffd5b61059d60048036038101906105989190615275565b6112cd565b6040516105aa91906152df565b60405180910390f35b6105bb6115ad565b6040516105c89190615368565b60405180910390f35b6105d9611638565b6040516105e69190615397565b60405180910390f35b610609600480360381019061060491906153b0565b611640565b60405161061691906152df565b60405180910390f35b61062761172d565b6040516106349190615397565b60405180910390f35b610645611735565b6040516106529190615397565b60405180910390f35b61066361173d565b6040516106709190615397565b60405180910390f35b610681611745565b60405161068e9190615397565b60405180910390f35b61069f61174d565b6040516106ac9190615397565b60405180910390f35b6106bd611755565b6040516106ca9190615397565b60405180910390f35b6106db61175b565b6040516106e89190615397565b60405180910390f35b6106f9611763565b6040516107069190615397565b60405180910390f35b61072960048036038101906107249190615275565b61176b565b60405161073691906152df565b60405180910390f35b61075960048036038101906107549190615275565b611a4b565b60405161076691906152df565b60405180910390f35b610777611d2b565b6040516107849190615397565b60405180910390f35b610795611d33565b6040516107a29190615397565b60405180910390f35b6107b3611d3b565b6040516107c09190615397565b60405180910390f35b6107d1611d43565b6040516107de9190615397565b60405180910390f35b6107ef611d4b565b6040516107fc9190615397565b60405180910390f35b61080d611d53565b60405161081a9190615397565b60405180910390f35b61083d60048036038101906108389190615275565b611d5b565b60405161084a91906152df565b60405180910390f35b61085b61203b565b6040516108689190615397565b60405180910390f35b610879612043565b6040516108869190615397565b60405180910390f35b6108a960048036038101906108a49190615275565b61204b565b6040516108b691906152df565b60405180910390f35b6108c761232b565b6040516108d49190615397565b60405180910390f35b6108e5612333565b6040516108f29190615409565b60405180910390f35b610903612345565b6040516109109190615397565b60405180910390f35b610933600480360381019061092e9190615275565b61234d565b60405161094091906152df565b60405180910390f35b610963600480360381019061095e9190615275565b61262d565b60405161097091906152df565b60405180910390f35b61098161290d565b60405161098e9190615397565b60405180910390f35b61099f612915565b6040516109ac9190615397565b60405180910390f35b6109bd61291d565b6040516109ca9190615397565b60405180910390f35b6109db612925565b6040516109e89190615397565b60405180910390f35b6109f961292d565b604051610a069190615397565b60405180910390f35b610a17612935565b604051610a249190615397565b60405180910390f35b610a476004803603810190610a429190615275565b61293d565b604051610a5491906152df565b60405180910390f35b610a65612c1d565b604051610a729190615397565b60405180910390f35b610a83612c25565b604051610a909190615397565b60405180910390f35b610aa1612c2d565b604051610aae9190615397565b60405180910390f35b610abf612c35565b604051610acc9190615397565b60405180910390f35b610aef6004803603810190610aea9190615275565b612c3d565b604051610afc91906152df565b60405180910390f35b610b0d612f1d565b604051610b1a9190615397565b60405180910390f35b610b3d6004803603810190610b389190615275565b612f25565b604051610b4a91906152df565b60405180910390f35b610b5b613205565b604051610b689190615397565b60405180910390f35b610b7961320d565b604051610b869190615397565b60405180910390f35b610b97613215565b604051610ba49190615397565b60405180910390f35b610bb561321d565b604051610bc29190615397565b60405180910390f35b610bd3613225565b604051610be09190615397565b60405180910390f35b610bf161322d565b604051610bfe9190615397565b60405180910390f35b610c216004803603810190610c1c9190615275565b613235565b604051610c2e91906152df565b60405180910390f35b610c3f613515565b604051610c4c9190615397565b60405180910390f35b610c5d61351d565b604051610c6a9190615397565b60405180910390f35b610c8d6004803603810190610c889190615275565b613525565b604051610c9a91906152df565b60405180910390f35b610cbd6004803603810190610cb89190615422565b613805565b604051610cca9190615397565b60405180910390f35b610cdb61381a565b604051610ce89190615397565b60405180910390f35b610cf9613822565b604051610d069190615397565b60405180910390f35b610d1761382a565b604051610d249190615397565b60405180910390f35b610d35613832565b604051610d429190615397565b60405180910390f35b610d5361383a565b604051610d609190615397565b60405180910390f35b610d836004803603810190610d7e9190615275565b613842565b604051610d9091906152df565b60405180910390f35b610da1613b22565b604051610dae9190615397565b60405180910390f35b610dbf613b2a565b604051610dcc9190615397565b60405180910390f35b610ddd613b32565b604051610dea9190615397565b60405180910390f35b610dfb613b3a565b604051610e089190615397565b60405180910390f35b610e19613b42565b604051610e269190615397565b60405180910390f35b610e496004803603810190610e449190615275565b613b4a565b604051610e5691906152df565b60405180910390f35b610e67613e2a565b604051610e749190615397565b60405180910390f35b610e85613e32565b604051610e929190615368565b60405180910390f35b610ea3613ebe565b604051610eb09190615397565b60405180910390f35b610ec1613ec6565b604051610ece9190615397565b60405180910390f35b610edf613ece565b604051610eec9190615397565b60405180910390f35b610f0f6004803603810190610f0a91906153b0565b613ed6565b604051610f1c91906152df565b60405180910390f35b610f2d61406c565b604051610f3a9190615397565b60405180910390f35b610f5d6004803603810190610f589190615275565b614074565b604051610f6a91906152df565b60405180910390f35b610f7b614354565b604051610f889190615397565b60405180910390f35b610fab6004803603810190610fa69190615275565b61435c565b604051610fb891906152df565b60405180910390f35b610fc961463c565b604051610fd69190615397565b60405180910390f35b610fe7614644565b604051610ff49190615397565b60405180910390f35b61100561464c565b6040516110129190615397565b60405180910390f35b61103560048036038101906110309190615275565b614654565b60405161104291906152df565b60405180910390f35b611053614934565b6040516110609190615397565b60405180910390f35b611083600480360381019061107e9190615275565b614958565b60405161109091906152df565b60405180910390f35b6110a1614c38565b6040516110ae9190615397565b60405180910390f35b6110bf614c40565b6040516110cc9190615397565b60405180910390f35b6110dd614c48565b6040516110ea9190615397565b60405180910390f35b6110fb614c50565b6040516111089190615397565b60405180910390f35b611119614c58565b6040516111269190615397565b60405180910390f35b611137614c60565b6040516111449190615397565b60405180910390f35b6111676004803603810190611162919061544d565b614c68565b6040516111749190615397565b60405180910390f35b611185614c88565b6040516111929190615397565b60405180910390f35b6111a3614c90565b6040516111b09190615397565b60405180910390f35b6111d360048036038101906111ce9190615275565b614c98565b6040516111e091906152df565b60405180910390f35b6111f1614ebd565b6040516111fe9190615368565b60405180910390f35b61120f614edc565b60405161121c9190615397565b60405180910390f35b61122d614ee4565b60405161123a9190615397565b60405180910390f35b61124b614eec565b6040516112589190615397565b60405180910390f35b61127b60048036038101906112769190615275565b614ef4565b60405161128891906152df565b60405180910390f35b6112996151d4565b6040516112a69190615397565b60405180910390f35b6112b76151dc565b6040516112c49190615397565b60405180910390f35b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054101561134e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611345906154d5565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015611409576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114009061553d565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546114559190615588565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546114a891906155bb565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546115369190615588565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161159a9190615397565b60405180910390a3600190509392505050565b5f80546115b99061561b565b80601f01602080910402602001604051908101604052809291908181526020018280546115e59061561b565b80156116305780601f1061160757610100808354040283529160200191611630565b820191905f5260205f20905b81548152906001019060200180831161161357829003601f168201915b505050505081565b5f602f905090565b5f8160055f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9258460405161171b9190615397565b60405180910390a36001905092915050565b5f601b905090565b5f6005905090565b5f601a905090565b5f601d905090565b5f6033905090565b60035481565b5f6008905090565b5f6003905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156117ec576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117e3906154d5565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156118a7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161189e9061553d565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546118f39190615588565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461194691906155bb565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546119d49190615588565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051611a389190615397565b60405180910390a3600190509392505050565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015611acc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ac3906154d5565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015611b87576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b7e9061553d565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254611bd39190615588565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254611c2691906155bb565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254611cb49190615588565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051611d189190615397565b60405180910390a3600190509392505050565b5f6002905090565b5f6010905090565b5f6041905090565b5f6035905090565b5f602e905090565b5f602c905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015611ddc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611dd3906154d5565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015611e97576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e8e9061553d565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254611ee39190615588565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254611f3691906155bb565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254611fc49190615588565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516120289190615397565b60405180910390a3600190509392505050565b5f6001905090565b5f6045905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156120cc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016120c390615695565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015612187576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161217e906156fd565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546121d39190615588565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461222691906155bb565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546122b49190615588565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516123189190615397565b60405180910390a3600190509392505050565b5f6034905090565b60025f9054906101000a900460ff1681565b5f603c905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156123ce576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016123c5906154d5565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015612489576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016124809061553d565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546124d59190615588565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461252891906155bb565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546125b69190615588565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161261a9190615397565b60405180910390a3600190509392505050565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156126ae576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016126a5906154d5565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015612769576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016127609061553d565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546127b59190615588565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461280891906155bb565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546128969190615588565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516128fa9190615397565b60405180910390a3600190509392505050565b5f6004905090565b5f600c905090565b5f6006905090565b5f601c905090565b5f6032905090565b5f6023905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156129be576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016129b5906154d5565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015612a79576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612a709061553d565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254612ac59190615588565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254612b1891906155bb565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254612ba69190615588565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051612c0a9190615397565b60405180910390a3600190509392505050565b5f6011905090565b5f6021905090565b5f601f905090565b5f6026905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015612cbe576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612cb5906154d5565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015612d79576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612d709061553d565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254612dc59190615588565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254612e1891906155bb565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254612ea69190615588565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051612f0a9190615397565b60405180910390a3600190509392505050565b5f603a905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015612fa6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612f9d906154d5565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015613061576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016130589061553d565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546130ad9190615588565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461310091906155bb565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461318e9190615588565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516131f29190615397565b60405180910390a3600190509392505050565b5f6009905090565b5f602a905090565b5f6014905090565b5f6025905090565b5f6013905090565b5f6043905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156132b6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016132ad90615695565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015613371576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613368906156fd565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546133bd9190615588565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461341091906155bb565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461349e9190615588565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516135029190615397565b60405180910390a3600190509392505050565b5f600d905090565b5f6017905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156135a6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161359d906154d5565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015613661576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016136589061553d565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546136ad9190615588565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461370091906155bb565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461378e9190615588565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516137f29190615397565b60405180910390a3600190509392505050565b6004602052805f5260405f205f915090505481565b5f6016905090565b5f6039905090565b5f603b905090565b5f6036905090565b5f603f905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156138c3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016138ba906154d5565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054101561397e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016139759061553d565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546139ca9190615588565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254613a1d91906155bb565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254613aab9190615588565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051613b0f9190615397565b60405180910390a3600190509392505050565b5f602b905090565b5f6037905090565b5f600a905090565b5f602d905090565b5f6030905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015613bcb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613bc2906154d5565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015613c86576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613c7d9061553d565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254613cd29190615588565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254613d2591906155bb565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254613db39190615588565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051613e179190615397565b60405180910390a3600190509392505050565b5f600b905090565b60018054613e3f9061561b565b80601f0160208091040260200160405190810160405280929190818152602001828054613e6b9061561b565b8015613eb65780601f10613e8d57610100808354040283529160200191613eb6565b820191905f5260205f20905b815481529060010190602001808311613e9957829003601f168201915b505050505081565b5f6015905090565b5f6029905090565b5f6038905090565b5f8160045f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015613f57576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613f4e906154d5565b60405180910390fd5b8160045f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254613fa39190615588565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254613ff691906155bb565b925050819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161405a9190615397565b60405180910390a36001905092915050565b5f6028905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156140f5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016140ec906154d5565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156141b0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016141a79061553d565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546141fc9190615588565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461424f91906155bb565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546142dd9190615588565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516143419190615397565b60405180910390a3600190509392505050565b5f6040905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156143dd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016143d4906154d5565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015614498576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161448f9061553d565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546144e49190615588565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461453791906155bb565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546145c59190615588565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516146299190615397565b60405180910390a3600190509392505050565b5f6018905090565b5f600f905090565b5f6044905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156146d5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016146cc906154d5565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015614790576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016147879061553d565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546147dc9190615588565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461482f91906155bb565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546148bd9190615588565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516149219190615397565b60405180910390a3600190509392505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156149d9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016149d0906154d5565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015614a94576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401614a8b9061553d565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254614ae09190615588565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254614b3391906155bb565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254614bc19190615588565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051614c259190615397565b60405180910390a3600190509392505050565b5f6024905090565b5f601e905090565b5f6031905090565b5f6019905090565b5f6042905090565b5f6027905090565b6005602052815f5260405f20602052805f5260405f205f91509150505481565b5f603d905090565b5f6022905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015614d19576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401614d1090615695565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254614d659190615588565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254614db891906155bb565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254614e469190615588565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051614eaa9190615397565b60405180910390a3600190509392505050565b604051806101400160405280610114815260200161571c610114913981565b5f6007905090565b5f603e905090565b5f6020905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015614f75576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401614f6c906154d5565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015615030576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016150279061553d565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461507c9190615588565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546150cf91906155bb565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461515d9190615588565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516151c19190615397565b60405180910390a3600190509392505050565b5f600e905090565b5f6012905090565b5f5ffd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f615211826151e8565b9050919050565b61522181615207565b811461522b575f5ffd5b50565b5f8135905061523c81615218565b92915050565b5f819050919050565b61525481615242565b811461525e575f5ffd5b50565b5f8135905061526f8161524b565b92915050565b5f5f5f6060848603121561528c5761528b6151e4565b5b5f6152998682870161522e565b93505060206152aa8682870161522e565b92505060406152bb86828701615261565b9150509250925092565b5f8115159050919050565b6152d9816152c5565b82525050565b5f6020820190506152f25f8301846152d0565b92915050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f61533a826152f8565b6153448185615302565b9350615354818560208601615312565b61535d81615320565b840191505092915050565b5f6020820190508181035f8301526153808184615330565b905092915050565b61539181615242565b82525050565b5f6020820190506153aa5f830184615388565b92915050565b5f5f604083850312156153c6576153c56151e4565b5b5f6153d38582860161522e565b92505060206153e485828601615261565b9150509250929050565b5f60ff82169050919050565b615403816153ee565b82525050565b5f60208201905061541c5f8301846153fa565b92915050565b5f60208284031215615437576154366151e4565b5b5f6154448482850161522e565b91505092915050565b5f5f60408385031215615463576154626151e4565b5b5f6154708582860161522e565b92505060206154818582860161522e565b9150509250929050565b7f496e73756666696369656e742062616c616e63650000000000000000000000005f82015250565b5f6154bf601483615302565b91506154ca8261548b565b602082019050919050565b5f6020820190508181035f8301526154ec816154b3565b9050919050565b7f496e73756666696369656e7420616c6c6f77616e6365000000000000000000005f82015250565b5f615527601683615302565b9150615532826154f3565b602082019050919050565b5f6020820190508181035f8301526155548161551b565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f61559282615242565b915061559d83615242565b92508282039050818111156155b5576155b461555b565b5b92915050565b5f6155c582615242565b91506155d083615242565b92508282019050808211156155e8576155e761555b565b5b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f600282049050600182168061563257607f821691505b602082108103615645576156446155ee565b5b50919050565b7f41000000000000000000000000000000000000000000000000000000000000005f82015250565b5f61567f600183615302565b915061568a8261564b565b602082019050919050565b5f6020820190508181035f8301526156ac81615673565b9050919050565b7f42000000000000000000000000000000000000000000000000000000000000005f82015250565b5f6156e7600183615302565b91506156f2826156b3565b602082019050919050565b5f6020820190508181035f830152615714816156db565b905091905056fe414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141a26469706673582212203e477b8749988ccd0a67b1a6d43c11976c00a420dbe43a9f84158e8962430d7664736f6c634300081e0033 \ 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..13a8ab62 --- /dev/null +++ b/scenarios/statebloat/contract_deploy/contract/StateBloatToken.go @@ -0,0 +1,3205 @@ +// 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 +) + +// ContractMetaData contains all meta data concerning the Contract contract. +var ContractMetaData = &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\":[{\"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\":\"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: "0x60a060405234801561000f575f5ffd5b50604051615d6a380380615d6a833981810160405281019061003191906101f4565b6040518060400160405280601181526020017f537461746520426c6f617420546f6b656e0000000000000000000000000000008152505f90816100749190610453565b506040518060400160405280600381526020017f5342540000000000000000000000000000000000000000000000000000000000815250600190816100b99190610453565b50601260025f6101000a81548160ff021916908360ff160217905550806080818152505060025f9054906101000a900460ff16600a6100f8919061068a565b620f424061010691906106d4565b60038190555060035460045f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055503373ffffffffffffffffffffffffffffffffffffffff165f73ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef6003546040516101af9190610724565b60405180910390a35061073d565b5f5ffd5b5f819050919050565b6101d3816101c1565b81146101dd575f5ffd5b50565b5f815190506101ee816101ca565b92915050565b5f60208284031215610209576102086101bd565b5b5f610216848285016101e0565b91505092915050565b5f81519050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f600282049050600182168061029a57607f821691505b6020821081036102ad576102ac610256565b5b50919050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f6008830261030f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff826102d4565b61031986836102d4565b95508019841693508086168417925050509392505050565b5f819050919050565b5f61035461034f61034a846101c1565b610331565b6101c1565b9050919050565b5f819050919050565b61036d8361033a565b6103816103798261035b565b8484546102e0565b825550505050565b5f5f905090565b610398610389565b6103a3818484610364565b505050565b5b818110156103c6576103bb5f82610390565b6001810190506103a9565b5050565b601f82111561040b576103dc816102b3565b6103e5846102c5565b810160208510156103f4578190505b610408610400856102c5565b8301826103a8565b50505b505050565b5f82821c905092915050565b5f61042b5f1984600802610410565b1980831691505092915050565b5f610443838361041c565b9150826002028217905092915050565b61045c8261021f565b67ffffffffffffffff81111561047557610474610229565b5b61047f8254610283565b61048a8282856103ca565b5f60209050601f8311600181146104bb575f84156104a9578287015190505b6104b38582610438565b86555061051a565b601f1984166104c9866102b3565b5f5b828110156104f0578489015182556001820191506020850194506020810190506104cb565b8683101561050d5784890151610509601f89168261041c565b8355505b6001600288020188555050505b505050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f8160011c9050919050565b5f5f8291508390505b60018511156105a4578086048111156105805761057f610522565b5b600185161561058f5780820291505b808102905061059d8561054f565b9450610564565b94509492505050565b5f826105bc5760019050610677565b816105c9575f9050610677565b81600181146105df57600281146105e957610618565b6001915050610677565b60ff8411156105fb576105fa610522565b5b8360020a91508482111561061257610611610522565b5b50610677565b5060208310610133831016604e8410600b841016171561064d5782820a90508381111561064857610647610522565b5b610677565b61065a848484600161055b565b9250905081840481111561067157610670610522565b5b81810290505b9392505050565b5f60ff82169050919050565b5f610694826101c1565b915061069f8361067e565b92506106cc7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff84846105ad565b905092915050565b5f6106de826101c1565b91506106e9836101c1565b92508282026106f7816101c1565b9150828204841483151761070e5761070d610522565b5b5092915050565b61071e816101c1565b82525050565b5f6020820190506107375f830184610715565b92915050565b6080516156156107555f395f61482101526156155ff3fe608060405234801561000f575f5ffd5b5060043610610518575f3560e01c8063657b6ef7116102a2578063aaa7af7011610170578063d7419469116100d7578063f26c779b11610090578063f26c779b1461110a578063f5f5738114611128578063f8716f1414611146578063faf35ced14611164578063fe7d599614611194578063ffbf0469146111b257610518565b8063d741946914611032578063dc1d8a9b14611050578063dd62ed3e1461106e578063e2d275301461109e578063e8c927b3146110bc578063eb4329c8146110da57610518565b8063bb9bfe0611610129578063bb9bfe0614610f5a578063bfa0b13314610f8a578063c2be97e314610fa8578063c958d4bf14610fd8578063cfd6686314610ff6578063d101dcd01461101457610518565b8063aaa7af7014610e82578063acc5aee914610ea0578063ad8f422114610ed0578063b1802b9a14610eee578063b2bb360e14610f1e578063b66dd75014610f3c57610518565b80637c72ed0d116102145780638f4a8406116101cd5780638f4a840614610dbc57806395d89b4114610dda5780639c5dfe7314610df85780639df61a2514610e16578063a891d4d414610e34578063a9059cbb14610e5257610518565b80637c72ed0d14610cf65780637dffdc3214610d145780637e54493714610d325780637f34d94b14610d505780638619d60714610d6e5780638789ca6714610d8c57610518565b806374e73fd31161026657806374e73fd314610c3057806374f83d0214610c4e57806377c0209e14610c6c578063792c7f3e14610c8a5780637a319c1814610ca85780637c66673e14610cc657610518565b8063657b6ef714610b64578063672151fe14610b945780636abceacd14610bb25780636c12ed2814610bd057806370a0823114610c0057610518565b80633125f37a116103ea5780634a2e93c611610351578063552a1b561161030a578063552a1b5614610a9e57806358b6a9bd14610ace5780635af92c0514610aec57806361b970eb14610b0a578063639ec53a14610b285780636547317414610b4657610518565b80634a2e93c6146109d85780634b3c7f5f146109f65780634e1dbb8214610a145780634f5e555714610a325780634f7bd75a14610a5057806354c2792014610a8057610518565b80633ea117ce116103a35780633ea117ce146109125780634128a85d14610930578063418b18161461094e57806342937dbd1461096c57806343a6b92d1461098a57806344050a28146109a857610518565b80633125f37a1461083a578063313ce5671461085857806334517f0b1461087657806339e0bd12146108945780633a131990146108c45780633b6be459146108f457610518565b80631a97f18e1161048e5780631fd298ec116104475780631fd298ec1461076257806321ecd7a314610780578063239af2a51461079e57806323b872dd146107bc5780632545d8b7146107ec578063291c3bd71461080a57610518565b80631a97f18e1461068a5780631b17c65c146106a85780631bbffe6f146106d85780631d527cde146107085780631eaa7c52146107265780631f4495891461074457610518565b80631215a3ab116104e05780631215a3ab146105d657806312901b42146105f457806313ebb5ec1461061257806316a3045b1461063057806318160ddd1461064e57806319cf6a911461066c57610518565b80630460faf61461051c57806306fdde031461054c5780630717b1611461056a578063095ea7b3146105885780630cb7a9e7146105b8575b5f5ffd5b61053660048036038101906105319190615139565b6111d0565b60405161054391906151a3565b60405180910390f35b6105546114b0565b604051610561919061522c565b60405180910390f35b61057261153b565b60405161057f919061525b565b60405180910390f35b6105a2600480360381019061059d9190615274565b611543565b6040516105af91906151a3565b60405180910390f35b6105c0611630565b6040516105cd919061525b565b60405180910390f35b6105de611638565b6040516105eb919061525b565b60405180910390f35b6105fc611640565b604051610609919061525b565b60405180910390f35b61061a611648565b604051610627919061525b565b60405180910390f35b610638611650565b604051610645919061525b565b60405180910390f35b610656611658565b604051610663919061525b565b60405180910390f35b61067461165e565b604051610681919061525b565b60405180910390f35b610692611666565b60405161069f919061525b565b60405180910390f35b6106c260048036038101906106bd9190615139565b61166e565b6040516106cf91906151a3565b60405180910390f35b6106f260048036038101906106ed9190615139565b61194e565b6040516106ff91906151a3565b60405180910390f35b610710611c2e565b60405161071d919061525b565b60405180910390f35b61072e611c36565b60405161073b919061525b565b60405180910390f35b61074c611c3e565b604051610759919061525b565b60405180910390f35b61076a611c46565b604051610777919061525b565b60405180910390f35b610788611c4e565b604051610795919061525b565b60405180910390f35b6107a6611c56565b6040516107b3919061525b565b60405180910390f35b6107d660048036038101906107d19190615139565b611c5e565b6040516107e391906151a3565b60405180910390f35b6107f4611f3e565b604051610801919061525b565b60405180910390f35b610824600480360381019061081f9190615139565b611f46565b60405161083191906151a3565b60405180910390f35b610842612226565b60405161084f919061525b565b60405180910390f35b61086061222e565b60405161086d91906152cd565b60405180910390f35b61087e612240565b60405161088b919061525b565b60405180910390f35b6108ae60048036038101906108a99190615139565b612248565b6040516108bb91906151a3565b60405180910390f35b6108de60048036038101906108d99190615139565b612528565b6040516108eb91906151a3565b60405180910390f35b6108fc612808565b604051610909919061525b565b60405180910390f35b61091a612810565b604051610927919061525b565b60405180910390f35b610938612818565b604051610945919061525b565b60405180910390f35b610956612820565b604051610963919061525b565b60405180910390f35b610974612828565b604051610981919061525b565b60405180910390f35b610992612830565b60405161099f919061525b565b60405180910390f35b6109c260048036038101906109bd9190615139565b612838565b6040516109cf91906151a3565b60405180910390f35b6109e0612b18565b6040516109ed919061525b565b60405180910390f35b6109fe612b20565b604051610a0b919061525b565b60405180910390f35b610a1c612b28565b604051610a29919061525b565b60405180910390f35b610a3a612b30565b604051610a47919061525b565b60405180910390f35b610a6a6004803603810190610a659190615139565b612b38565b604051610a7791906151a3565b60405180910390f35b610a88612e18565b604051610a95919061525b565b60405180910390f35b610ab86004803603810190610ab39190615139565b612e20565b604051610ac591906151a3565b60405180910390f35b610ad6613100565b604051610ae3919061525b565b60405180910390f35b610af4613108565b604051610b01919061525b565b60405180910390f35b610b12613110565b604051610b1f919061525b565b60405180910390f35b610b30613118565b604051610b3d919061525b565b60405180910390f35b610b4e613120565b604051610b5b919061525b565b60405180910390f35b610b7e6004803603810190610b799190615139565b613128565b604051610b8b91906151a3565b60405180910390f35b610b9c613408565b604051610ba9919061525b565b60405180910390f35b610bba613410565b604051610bc7919061525b565b60405180910390f35b610bea6004803603810190610be59190615139565b613418565b604051610bf791906151a3565b60405180910390f35b610c1a6004803603810190610c1591906152e6565b6136f8565b604051610c27919061525b565b60405180910390f35b610c3861370d565b604051610c45919061525b565b60405180910390f35b610c56613715565b604051610c63919061525b565b60405180910390f35b610c7461371d565b604051610c81919061525b565b60405180910390f35b610c92613725565b604051610c9f919061525b565b60405180910390f35b610cb061372d565b604051610cbd919061525b565b60405180910390f35b610ce06004803603810190610cdb9190615139565b613735565b604051610ced91906151a3565b60405180910390f35b610cfe613a15565b604051610d0b919061525b565b60405180910390f35b610d1c613a1d565b604051610d29919061525b565b60405180910390f35b610d3a613a25565b604051610d47919061525b565b60405180910390f35b610d58613a2d565b604051610d65919061525b565b60405180910390f35b610d76613a35565b604051610d83919061525b565b60405180910390f35b610da66004803603810190610da19190615139565b613a3d565b604051610db391906151a3565b60405180910390f35b610dc4613d1d565b604051610dd1919061525b565b60405180910390f35b610de2613d25565b604051610def919061522c565b60405180910390f35b610e00613db1565b604051610e0d919061525b565b60405180910390f35b610e1e613db9565b604051610e2b919061525b565b60405180910390f35b610e3c613dc1565b604051610e49919061525b565b60405180910390f35b610e6c6004803603810190610e679190615274565b613dc9565b604051610e7991906151a3565b60405180910390f35b610e8a613f5f565b604051610e97919061525b565b60405180910390f35b610eba6004803603810190610eb59190615139565b613f67565b604051610ec791906151a3565b60405180910390f35b610ed8614247565b604051610ee5919061525b565b60405180910390f35b610f086004803603810190610f039190615139565b61424f565b604051610f1591906151a3565b60405180910390f35b610f2661452f565b604051610f33919061525b565b60405180910390f35b610f44614537565b604051610f51919061525b565b60405180910390f35b610f746004803603810190610f6f9190615139565b61453f565b604051610f8191906151a3565b60405180910390f35b610f9261481f565b604051610f9f919061525b565b60405180910390f35b610fc26004803603810190610fbd9190615139565b614843565b604051610fcf91906151a3565b60405180910390f35b610fe0614b23565b604051610fed919061525b565b60405180910390f35b610ffe614b2b565b60405161100b919061525b565b60405180910390f35b61101c614b33565b604051611029919061525b565b60405180910390f35b61103a614b3b565b604051611047919061525b565b60405180910390f35b611058614b43565b604051611065919061525b565b60405180910390f35b61108860048036038101906110839190615311565b614b4b565b604051611095919061525b565b60405180910390f35b6110a6614b6b565b6040516110b3919061525b565b60405180910390f35b6110c4614b73565b6040516110d1919061525b565b60405180910390f35b6110f460048036038101906110ef9190615139565b614b7b565b60405161110191906151a3565b60405180910390f35b611112614da0565b60405161111f919061525b565b60405180910390f35b611130614da8565b60405161113d919061525b565b60405180910390f35b61114e614db0565b60405161115b919061525b565b60405180910390f35b61117e60048036038101906111799190615139565b614db8565b60405161118b91906151a3565b60405180910390f35b61119c615098565b6040516111a9919061525b565b60405180910390f35b6111ba6150a0565b6040516111c7919061525b565b60405180910390f35b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015611251576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161124890615399565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054101561130c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161130390615401565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254611358919061544c565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546113ab919061547f565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254611439919061544c565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161149d919061525b565b60405180910390a3600190509392505050565b5f80546114bc906154df565b80601f01602080910402602001604051908101604052809291908181526020018280546114e8906154df565b80156115335780601f1061150a57610100808354040283529160200191611533565b820191905f5260205f20905b81548152906001019060200180831161151657829003601f168201915b505050505081565b5f602f905090565b5f8160055f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9258460405161161e919061525b565b60405180910390a36001905092915050565b5f601b905090565b5f6005905090565b5f601a905090565b5f601d905090565b5f6033905090565b60035481565b5f6008905090565b5f6003905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156116ef576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116e690615399565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156117aa576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117a190615401565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546117f6919061544c565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254611849919061547f565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546118d7919061544c565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161193b919061525b565b60405180910390a3600190509392505050565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156119cf576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119c690615399565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015611a8a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a8190615401565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254611ad6919061544c565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254611b29919061547f565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254611bb7919061544c565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051611c1b919061525b565b60405180910390a3600190509392505050565b5f6002905090565b5f6010905090565b5f6041905090565b5f6035905090565b5f602e905090565b5f602c905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015611cdf576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611cd690615399565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015611d9a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611d9190615401565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254611de6919061544c565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254611e39919061547f565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254611ec7919061544c565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051611f2b919061525b565b60405180910390a3600190509392505050565b5f6001905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015611fc7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611fbe90615559565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015612082576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612079906155c1565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546120ce919061544c565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254612121919061547f565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546121af919061544c565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051612213919061525b565b60405180910390a3600190509392505050565b5f6034905090565b60025f9054906101000a900460ff1681565b5f603c905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156122c9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016122c090615399565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015612384576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161237b90615401565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546123d0919061544c565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254612423919061547f565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546124b1919061544c565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051612515919061525b565b60405180910390a3600190509392505050565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156125a9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016125a090615399565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015612664576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161265b90615401565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546126b0919061544c565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254612703919061547f565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254612791919061544c565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516127f5919061525b565b60405180910390a3600190509392505050565b5f6004905090565b5f600c905090565b5f6006905090565b5f601c905090565b5f6032905090565b5f6023905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156128b9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016128b090615399565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015612974576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161296b90615401565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546129c0919061544c565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254612a13919061547f565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254612aa1919061544c565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051612b05919061525b565b60405180910390a3600190509392505050565b5f6011905090565b5f6021905090565b5f601f905090565b5f6026905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015612bb9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612bb090615399565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015612c74576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612c6b90615401565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254612cc0919061544c565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254612d13919061547f565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254612da1919061544c565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051612e05919061525b565b60405180910390a3600190509392505050565b5f603a905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015612ea1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612e9890615399565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015612f5c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612f5390615401565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254612fa8919061544c565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254612ffb919061547f565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254613089919061544c565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516130ed919061525b565b60405180910390a3600190509392505050565b5f6009905090565b5f602a905090565b5f6014905090565b5f6025905090565b5f6013905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156131a9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016131a090615559565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015613264576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161325b906155c1565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546132b0919061544c565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254613303919061547f565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254613391919061544c565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516133f5919061525b565b60405180910390a3600190509392505050565b5f600d905090565b5f6017905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015613499576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161349090615399565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015613554576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161354b90615401565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546135a0919061544c565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546135f3919061547f565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254613681919061544c565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516136e5919061525b565b60405180910390a3600190509392505050565b6004602052805f5260405f205f915090505481565b5f6016905090565b5f6039905090565b5f603b905090565b5f6036905090565b5f603f905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156137b6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016137ad90615399565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015613871576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161386890615401565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546138bd919061544c565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254613910919061547f565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461399e919061544c565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051613a02919061525b565b60405180910390a3600190509392505050565b5f602b905090565b5f6037905090565b5f600a905090565b5f602d905090565b5f6030905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015613abe576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613ab590615399565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015613b79576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613b7090615401565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254613bc5919061544c565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254613c18919061547f565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254613ca6919061544c565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051613d0a919061525b565b60405180910390a3600190509392505050565b5f600b905090565b60018054613d32906154df565b80601f0160208091040260200160405190810160405280929190818152602001828054613d5e906154df565b8015613da95780601f10613d8057610100808354040283529160200191613da9565b820191905f5260205f20905b815481529060010190602001808311613d8c57829003601f168201915b505050505081565b5f6015905090565b5f6029905090565b5f6038905090565b5f8160045f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015613e4a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613e4190615399565b60405180910390fd5b8160045f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254613e96919061544c565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254613ee9919061547f565b925050819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051613f4d919061525b565b60405180910390a36001905092915050565b5f6028905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015613fe8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613fdf90615399565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156140a3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161409a90615401565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546140ef919061544c565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254614142919061547f565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546141d0919061544c565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051614234919061525b565b60405180910390a3600190509392505050565b5f6040905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156142d0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016142c790615399565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054101561438b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161438290615401565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546143d7919061544c565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461442a919061547f565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546144b8919061544c565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161451c919061525b565b60405180910390a3600190509392505050565b5f6018905090565b5f600f905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156145c0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016145b790615399565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054101561467b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161467290615401565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546146c7919061544c565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461471a919061547f565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546147a8919061544c565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161480c919061525b565b60405180910390a3600190509392505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156148c4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016148bb90615399565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054101561497f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161497690615401565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546149cb919061544c565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254614a1e919061547f565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254614aac919061544c565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051614b10919061525b565b60405180910390a3600190509392505050565b5f6024905090565b5f601e905090565b5f6031905090565b5f6019905090565b5f6027905090565b6005602052815f5260405f20602052805f5260405f205f91509150505481565b5f603d905090565b5f6022905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015614bfc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401614bf390615559565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254614c48919061544c565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254614c9b919061547f565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254614d29919061544c565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051614d8d919061525b565b60405180910390a3600190509392505050565b5f6007905090565b5f603e905090565b5f6020905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015614e39576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401614e3090615399565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015614ef4576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401614eeb90615401565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254614f40919061544c565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254614f93919061547f565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254615021919061544c565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051615085919061525b565b60405180910390a3600190509392505050565b5f600e905090565b5f6012905090565b5f5ffd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6150d5826150ac565b9050919050565b6150e5816150cb565b81146150ef575f5ffd5b50565b5f81359050615100816150dc565b92915050565b5f819050919050565b61511881615106565b8114615122575f5ffd5b50565b5f813590506151338161510f565b92915050565b5f5f5f606084860312156151505761514f6150a8565b5b5f61515d868287016150f2565b935050602061516e868287016150f2565b925050604061517f86828701615125565b9150509250925092565b5f8115159050919050565b61519d81615189565b82525050565b5f6020820190506151b65f830184615194565b92915050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f6151fe826151bc565b61520881856151c6565b93506152188185602086016151d6565b615221816151e4565b840191505092915050565b5f6020820190508181035f83015261524481846151f4565b905092915050565b61525581615106565b82525050565b5f60208201905061526e5f83018461524c565b92915050565b5f5f6040838503121561528a576152896150a8565b5b5f615297858286016150f2565b92505060206152a885828601615125565b9150509250929050565b5f60ff82169050919050565b6152c7816152b2565b82525050565b5f6020820190506152e05f8301846152be565b92915050565b5f602082840312156152fb576152fa6150a8565b5b5f615308848285016150f2565b91505092915050565b5f5f60408385031215615327576153266150a8565b5b5f615334858286016150f2565b9250506020615345858286016150f2565b9150509250929050565b7f496e73756666696369656e742062616c616e63650000000000000000000000005f82015250565b5f6153836014836151c6565b915061538e8261534f565b602082019050919050565b5f6020820190508181035f8301526153b081615377565b9050919050565b7f496e73756666696369656e7420616c6c6f77616e6365000000000000000000005f82015250565b5f6153eb6016836151c6565b91506153f6826153b7565b602082019050919050565b5f6020820190508181035f830152615418816153df565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f61545682615106565b915061546183615106565b92508282039050818111156154795761547861541f565b5b92915050565b5f61548982615106565b915061549483615106565b92508282019050808211156154ac576154ab61541f565b5b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f60028204905060018216806154f657607f821691505b602082108103615509576155086154b2565b5b50919050565b7f41000000000000000000000000000000000000000000000000000000000000005f82015250565b5f6155436001836151c6565b915061554e8261550f565b602082019050919050565b5f6020820190508181035f83015261557081615537565b9050919050565b7f42000000000000000000000000000000000000000000000000000000000000005f82015250565b5f6155ab6001836151c6565b91506155b682615577565b602082019050919050565b5f6020820190508181035f8301526155d88161559f565b905091905056fea26469706673582212206fbf384dcd110eb4456b07e83a2c8a392433c7852a66dec9f8ebf3989cad1f6764736f6c634300081e0033", +} + +// ContractABI is the input ABI used to generate the binding from. +// Deprecated: Use ContractMetaData.ABI instead. +var ContractABI = ContractMetaData.ABI + +// ContractBin is the compiled bytecode used for deploying new contracts. +// Deprecated: Use ContractMetaData.Bin instead. +var ContractBin = ContractMetaData.Bin + +// DeployContract deploys a new Ethereum contract, binding an instance of Contract to it. +func DeployContract(auth *bind.TransactOpts, backend bind.ContractBackend, _salt *big.Int) (common.Address, *types.Transaction, *Contract, error) { + parsed, err := ContractMetaData.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(ContractBin), backend, _salt) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &Contract{ContractCaller: ContractCaller{contract: contract}, ContractTransactor: ContractTransactor{contract: contract}, ContractFilterer: ContractFilterer{contract: contract}}, nil +} + +// Contract is an auto generated Go binding around an Ethereum contract. +type Contract struct { + ContractCaller // Read-only binding to the contract + ContractTransactor // Write-only binding to the contract + ContractFilterer // Log filterer for contract events +} + +// ContractCaller is an auto generated read-only Go binding around an Ethereum contract. +type ContractCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// ContractTransactor is an auto generated write-only Go binding around an Ethereum contract. +type ContractTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// ContractFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type ContractFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// ContractSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type ContractSession struct { + Contract *Contract // 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 +} + +// ContractCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type ContractCallerSession struct { + Contract *ContractCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// ContractTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type ContractTransactorSession struct { + Contract *ContractTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// ContractRaw is an auto generated low-level Go binding around an Ethereum contract. +type ContractRaw struct { + Contract *Contract // Generic contract binding to access the raw methods on +} + +// ContractCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type ContractCallerRaw struct { + Contract *ContractCaller // Generic read-only contract binding to access the raw methods on +} + +// ContractTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type ContractTransactorRaw struct { + Contract *ContractTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewContract creates a new instance of Contract, bound to a specific deployed contract. +func NewContract(address common.Address, backend bind.ContractBackend) (*Contract, error) { + contract, err := bindContract(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &Contract{ContractCaller: ContractCaller{contract: contract}, ContractTransactor: ContractTransactor{contract: contract}, ContractFilterer: ContractFilterer{contract: contract}}, nil +} + +// NewContractCaller creates a new read-only instance of Contract, bound to a specific deployed contract. +func NewContractCaller(address common.Address, caller bind.ContractCaller) (*ContractCaller, error) { + contract, err := bindContract(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &ContractCaller{contract: contract}, nil +} + +// NewContractTransactor creates a new write-only instance of Contract, bound to a specific deployed contract. +func NewContractTransactor(address common.Address, transactor bind.ContractTransactor) (*ContractTransactor, error) { + contract, err := bindContract(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &ContractTransactor{contract: contract}, nil +} + +// NewContractFilterer creates a new log filterer instance of Contract, bound to a specific deployed contract. +func NewContractFilterer(address common.Address, filterer bind.ContractFilterer) (*ContractFilterer, error) { + contract, err := bindContract(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &ContractFilterer{contract: contract}, nil +} + +// bindContract binds a generic wrapper to an already deployed contract. +func bindContract(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := ContractMetaData.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 (_Contract *ContractRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Contract.Contract.ContractCaller.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 (_Contract *ContractRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Contract.Contract.ContractTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Contract *ContractRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Contract.Contract.ContractTransactor.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 (_Contract *ContractCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Contract.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 (_Contract *ContractTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Contract.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Contract *ContractTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Contract.Contract.contract.Transact(opts, method, params...) +} + +// Allowance is a free data retrieval call binding the contract method 0xdd62ed3e. +// +// Solidity: function allowance(address , address ) view returns(uint256) +func (_Contract *ContractCaller) Allowance(opts *bind.CallOpts, arg0 common.Address, arg1 common.Address) (*big.Int, error) { + var out []interface{} + err := _Contract.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 (_Contract *ContractSession) Allowance(arg0 common.Address, arg1 common.Address) (*big.Int, error) { + return _Contract.Contract.Allowance(&_Contract.CallOpts, arg0, arg1) +} + +// Allowance is a free data retrieval call binding the contract method 0xdd62ed3e. +// +// Solidity: function allowance(address , address ) view returns(uint256) +func (_Contract *ContractCallerSession) Allowance(arg0 common.Address, arg1 common.Address) (*big.Int, error) { + return _Contract.Contract.Allowance(&_Contract.CallOpts, arg0, arg1) +} + +// BalanceOf is a free data retrieval call binding the contract method 0x70a08231. +// +// Solidity: function balanceOf(address ) view returns(uint256) +func (_Contract *ContractCaller) BalanceOf(opts *bind.CallOpts, arg0 common.Address) (*big.Int, error) { + var out []interface{} + err := _Contract.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 (_Contract *ContractSession) BalanceOf(arg0 common.Address) (*big.Int, error) { + return _Contract.Contract.BalanceOf(&_Contract.CallOpts, arg0) +} + +// BalanceOf is a free data retrieval call binding the contract method 0x70a08231. +// +// Solidity: function balanceOf(address ) view returns(uint256) +func (_Contract *ContractCallerSession) BalanceOf(arg0 common.Address) (*big.Int, error) { + return _Contract.Contract.BalanceOf(&_Contract.CallOpts, arg0) +} + +// Decimals is a free data retrieval call binding the contract method 0x313ce567. +// +// Solidity: function decimals() view returns(uint8) +func (_Contract *ContractCaller) Decimals(opts *bind.CallOpts) (uint8, error) { + var out []interface{} + err := _Contract.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 (_Contract *ContractSession) Decimals() (uint8, error) { + return _Contract.Contract.Decimals(&_Contract.CallOpts) +} + +// Decimals is a free data retrieval call binding the contract method 0x313ce567. +// +// Solidity: function decimals() view returns(uint8) +func (_Contract *ContractCallerSession) Decimals() (uint8, error) { + return _Contract.Contract.Decimals(&_Contract.CallOpts) +} + +// Dummy1 is a free data retrieval call binding the contract method 0x2545d8b7. +// +// Solidity: function dummy1() pure returns(uint256) +func (_Contract *ContractCaller) Dummy1(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Contract.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 (_Contract *ContractSession) Dummy1() (*big.Int, error) { + return _Contract.Contract.Dummy1(&_Contract.CallOpts) +} + +// Dummy1 is a free data retrieval call binding the contract method 0x2545d8b7. +// +// Solidity: function dummy1() pure returns(uint256) +func (_Contract *ContractCallerSession) Dummy1() (*big.Int, error) { + return _Contract.Contract.Dummy1(&_Contract.CallOpts) +} + +// Dummy10 is a free data retrieval call binding the contract method 0x7e544937. +// +// Solidity: function dummy10() pure returns(uint256) +func (_Contract *ContractCaller) Dummy10(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Contract.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 (_Contract *ContractSession) Dummy10() (*big.Int, error) { + return _Contract.Contract.Dummy10(&_Contract.CallOpts) +} + +// Dummy10 is a free data retrieval call binding the contract method 0x7e544937. +// +// Solidity: function dummy10() pure returns(uint256) +func (_Contract *ContractCallerSession) Dummy10() (*big.Int, error) { + return _Contract.Contract.Dummy10(&_Contract.CallOpts) +} + +// Dummy11 is a free data retrieval call binding the contract method 0x8f4a8406. +// +// Solidity: function dummy11() pure returns(uint256) +func (_Contract *ContractCaller) Dummy11(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Contract.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 (_Contract *ContractSession) Dummy11() (*big.Int, error) { + return _Contract.Contract.Dummy11(&_Contract.CallOpts) +} + +// Dummy11 is a free data retrieval call binding the contract method 0x8f4a8406. +// +// Solidity: function dummy11() pure returns(uint256) +func (_Contract *ContractCallerSession) Dummy11() (*big.Int, error) { + return _Contract.Contract.Dummy11(&_Contract.CallOpts) +} + +// Dummy12 is a free data retrieval call binding the contract method 0x3ea117ce. +// +// Solidity: function dummy12() pure returns(uint256) +func (_Contract *ContractCaller) Dummy12(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Contract.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 (_Contract *ContractSession) Dummy12() (*big.Int, error) { + return _Contract.Contract.Dummy12(&_Contract.CallOpts) +} + +// Dummy12 is a free data retrieval call binding the contract method 0x3ea117ce. +// +// Solidity: function dummy12() pure returns(uint256) +func (_Contract *ContractCallerSession) Dummy12() (*big.Int, error) { + return _Contract.Contract.Dummy12(&_Contract.CallOpts) +} + +// Dummy13 is a free data retrieval call binding the contract method 0x672151fe. +// +// Solidity: function dummy13() pure returns(uint256) +func (_Contract *ContractCaller) Dummy13(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Contract.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 (_Contract *ContractSession) Dummy13() (*big.Int, error) { + return _Contract.Contract.Dummy13(&_Contract.CallOpts) +} + +// Dummy13 is a free data retrieval call binding the contract method 0x672151fe. +// +// Solidity: function dummy13() pure returns(uint256) +func (_Contract *ContractCallerSession) Dummy13() (*big.Int, error) { + return _Contract.Contract.Dummy13(&_Contract.CallOpts) +} + +// Dummy14 is a free data retrieval call binding the contract method 0xfe7d5996. +// +// Solidity: function dummy14() pure returns(uint256) +func (_Contract *ContractCaller) Dummy14(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Contract.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 (_Contract *ContractSession) Dummy14() (*big.Int, error) { + return _Contract.Contract.Dummy14(&_Contract.CallOpts) +} + +// Dummy14 is a free data retrieval call binding the contract method 0xfe7d5996. +// +// Solidity: function dummy14() pure returns(uint256) +func (_Contract *ContractCallerSession) Dummy14() (*big.Int, error) { + return _Contract.Contract.Dummy14(&_Contract.CallOpts) +} + +// Dummy15 is a free data retrieval call binding the contract method 0xb66dd750. +// +// Solidity: function dummy15() pure returns(uint256) +func (_Contract *ContractCaller) Dummy15(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Contract.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 (_Contract *ContractSession) Dummy15() (*big.Int, error) { + return _Contract.Contract.Dummy15(&_Contract.CallOpts) +} + +// Dummy15 is a free data retrieval call binding the contract method 0xb66dd750. +// +// Solidity: function dummy15() pure returns(uint256) +func (_Contract *ContractCallerSession) Dummy15() (*big.Int, error) { + return _Contract.Contract.Dummy15(&_Contract.CallOpts) +} + +// Dummy16 is a free data retrieval call binding the contract method 0x1eaa7c52. +// +// Solidity: function dummy16() pure returns(uint256) +func (_Contract *ContractCaller) Dummy16(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Contract.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 (_Contract *ContractSession) Dummy16() (*big.Int, error) { + return _Contract.Contract.Dummy16(&_Contract.CallOpts) +} + +// Dummy16 is a free data retrieval call binding the contract method 0x1eaa7c52. +// +// Solidity: function dummy16() pure returns(uint256) +func (_Contract *ContractCallerSession) Dummy16() (*big.Int, error) { + return _Contract.Contract.Dummy16(&_Contract.CallOpts) +} + +// Dummy17 is a free data retrieval call binding the contract method 0x4a2e93c6. +// +// Solidity: function dummy17() pure returns(uint256) +func (_Contract *ContractCaller) Dummy17(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Contract.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 (_Contract *ContractSession) Dummy17() (*big.Int, error) { + return _Contract.Contract.Dummy17(&_Contract.CallOpts) +} + +// Dummy17 is a free data retrieval call binding the contract method 0x4a2e93c6. +// +// Solidity: function dummy17() pure returns(uint256) +func (_Contract *ContractCallerSession) Dummy17() (*big.Int, error) { + return _Contract.Contract.Dummy17(&_Contract.CallOpts) +} + +// Dummy18 is a free data retrieval call binding the contract method 0xffbf0469. +// +// Solidity: function dummy18() pure returns(uint256) +func (_Contract *ContractCaller) Dummy18(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Contract.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 (_Contract *ContractSession) Dummy18() (*big.Int, error) { + return _Contract.Contract.Dummy18(&_Contract.CallOpts) +} + +// Dummy18 is a free data retrieval call binding the contract method 0xffbf0469. +// +// Solidity: function dummy18() pure returns(uint256) +func (_Contract *ContractCallerSession) Dummy18() (*big.Int, error) { + return _Contract.Contract.Dummy18(&_Contract.CallOpts) +} + +// Dummy19 is a free data retrieval call binding the contract method 0x65473174. +// +// Solidity: function dummy19() pure returns(uint256) +func (_Contract *ContractCaller) Dummy19(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Contract.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 (_Contract *ContractSession) Dummy19() (*big.Int, error) { + return _Contract.Contract.Dummy19(&_Contract.CallOpts) +} + +// Dummy19 is a free data retrieval call binding the contract method 0x65473174. +// +// Solidity: function dummy19() pure returns(uint256) +func (_Contract *ContractCallerSession) Dummy19() (*big.Int, error) { + return _Contract.Contract.Dummy19(&_Contract.CallOpts) +} + +// Dummy2 is a free data retrieval call binding the contract method 0x1d527cde. +// +// Solidity: function dummy2() pure returns(uint256) +func (_Contract *ContractCaller) Dummy2(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Contract.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 (_Contract *ContractSession) Dummy2() (*big.Int, error) { + return _Contract.Contract.Dummy2(&_Contract.CallOpts) +} + +// Dummy2 is a free data retrieval call binding the contract method 0x1d527cde. +// +// Solidity: function dummy2() pure returns(uint256) +func (_Contract *ContractCallerSession) Dummy2() (*big.Int, error) { + return _Contract.Contract.Dummy2(&_Contract.CallOpts) +} + +// Dummy20 is a free data retrieval call binding the contract method 0x61b970eb. +// +// Solidity: function dummy20() pure returns(uint256) +func (_Contract *ContractCaller) Dummy20(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Contract.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 (_Contract *ContractSession) Dummy20() (*big.Int, error) { + return _Contract.Contract.Dummy20(&_Contract.CallOpts) +} + +// Dummy20 is a free data retrieval call binding the contract method 0x61b970eb. +// +// Solidity: function dummy20() pure returns(uint256) +func (_Contract *ContractCallerSession) Dummy20() (*big.Int, error) { + return _Contract.Contract.Dummy20(&_Contract.CallOpts) +} + +// Dummy21 is a free data retrieval call binding the contract method 0x9c5dfe73. +// +// Solidity: function dummy21() pure returns(uint256) +func (_Contract *ContractCaller) Dummy21(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Contract.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 (_Contract *ContractSession) Dummy21() (*big.Int, error) { + return _Contract.Contract.Dummy21(&_Contract.CallOpts) +} + +// Dummy21 is a free data retrieval call binding the contract method 0x9c5dfe73. +// +// Solidity: function dummy21() pure returns(uint256) +func (_Contract *ContractCallerSession) Dummy21() (*big.Int, error) { + return _Contract.Contract.Dummy21(&_Contract.CallOpts) +} + +// Dummy22 is a free data retrieval call binding the contract method 0x74e73fd3. +// +// Solidity: function dummy22() pure returns(uint256) +func (_Contract *ContractCaller) Dummy22(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Contract.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 (_Contract *ContractSession) Dummy22() (*big.Int, error) { + return _Contract.Contract.Dummy22(&_Contract.CallOpts) +} + +// Dummy22 is a free data retrieval call binding the contract method 0x74e73fd3. +// +// Solidity: function dummy22() pure returns(uint256) +func (_Contract *ContractCallerSession) Dummy22() (*big.Int, error) { + return _Contract.Contract.Dummy22(&_Contract.CallOpts) +} + +// Dummy23 is a free data retrieval call binding the contract method 0x6abceacd. +// +// Solidity: function dummy23() pure returns(uint256) +func (_Contract *ContractCaller) Dummy23(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Contract.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 (_Contract *ContractSession) Dummy23() (*big.Int, error) { + return _Contract.Contract.Dummy23(&_Contract.CallOpts) +} + +// Dummy23 is a free data retrieval call binding the contract method 0x6abceacd. +// +// Solidity: function dummy23() pure returns(uint256) +func (_Contract *ContractCallerSession) Dummy23() (*big.Int, error) { + return _Contract.Contract.Dummy23(&_Contract.CallOpts) +} + +// Dummy24 is a free data retrieval call binding the contract method 0xb2bb360e. +// +// Solidity: function dummy24() pure returns(uint256) +func (_Contract *ContractCaller) Dummy24(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Contract.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 (_Contract *ContractSession) Dummy24() (*big.Int, error) { + return _Contract.Contract.Dummy24(&_Contract.CallOpts) +} + +// Dummy24 is a free data retrieval call binding the contract method 0xb2bb360e. +// +// Solidity: function dummy24() pure returns(uint256) +func (_Contract *ContractCallerSession) Dummy24() (*big.Int, error) { + return _Contract.Contract.Dummy24(&_Contract.CallOpts) +} + +// Dummy25 is a free data retrieval call binding the contract method 0xd7419469. +// +// Solidity: function dummy25() pure returns(uint256) +func (_Contract *ContractCaller) Dummy25(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Contract.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 (_Contract *ContractSession) Dummy25() (*big.Int, error) { + return _Contract.Contract.Dummy25(&_Contract.CallOpts) +} + +// Dummy25 is a free data retrieval call binding the contract method 0xd7419469. +// +// Solidity: function dummy25() pure returns(uint256) +func (_Contract *ContractCallerSession) Dummy25() (*big.Int, error) { + return _Contract.Contract.Dummy25(&_Contract.CallOpts) +} + +// Dummy26 is a free data retrieval call binding the contract method 0x12901b42. +// +// Solidity: function dummy26() pure returns(uint256) +func (_Contract *ContractCaller) Dummy26(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Contract.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 (_Contract *ContractSession) Dummy26() (*big.Int, error) { + return _Contract.Contract.Dummy26(&_Contract.CallOpts) +} + +// Dummy26 is a free data retrieval call binding the contract method 0x12901b42. +// +// Solidity: function dummy26() pure returns(uint256) +func (_Contract *ContractCallerSession) Dummy26() (*big.Int, error) { + return _Contract.Contract.Dummy26(&_Contract.CallOpts) +} + +// Dummy27 is a free data retrieval call binding the contract method 0x0cb7a9e7. +// +// Solidity: function dummy27() pure returns(uint256) +func (_Contract *ContractCaller) Dummy27(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Contract.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 (_Contract *ContractSession) Dummy27() (*big.Int, error) { + return _Contract.Contract.Dummy27(&_Contract.CallOpts) +} + +// Dummy27 is a free data retrieval call binding the contract method 0x0cb7a9e7. +// +// Solidity: function dummy27() pure returns(uint256) +func (_Contract *ContractCallerSession) Dummy27() (*big.Int, error) { + return _Contract.Contract.Dummy27(&_Contract.CallOpts) +} + +// Dummy28 is a free data retrieval call binding the contract method 0x418b1816. +// +// Solidity: function dummy28() pure returns(uint256) +func (_Contract *ContractCaller) Dummy28(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Contract.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 (_Contract *ContractSession) Dummy28() (*big.Int, error) { + return _Contract.Contract.Dummy28(&_Contract.CallOpts) +} + +// Dummy28 is a free data retrieval call binding the contract method 0x418b1816. +// +// Solidity: function dummy28() pure returns(uint256) +func (_Contract *ContractCallerSession) Dummy28() (*big.Int, error) { + return _Contract.Contract.Dummy28(&_Contract.CallOpts) +} + +// Dummy29 is a free data retrieval call binding the contract method 0x13ebb5ec. +// +// Solidity: function dummy29() pure returns(uint256) +func (_Contract *ContractCaller) Dummy29(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Contract.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 (_Contract *ContractSession) Dummy29() (*big.Int, error) { + return _Contract.Contract.Dummy29(&_Contract.CallOpts) +} + +// Dummy29 is a free data retrieval call binding the contract method 0x13ebb5ec. +// +// Solidity: function dummy29() pure returns(uint256) +func (_Contract *ContractCallerSession) Dummy29() (*big.Int, error) { + return _Contract.Contract.Dummy29(&_Contract.CallOpts) +} + +// Dummy3 is a free data retrieval call binding the contract method 0x1a97f18e. +// +// Solidity: function dummy3() pure returns(uint256) +func (_Contract *ContractCaller) Dummy3(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Contract.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 (_Contract *ContractSession) Dummy3() (*big.Int, error) { + return _Contract.Contract.Dummy3(&_Contract.CallOpts) +} + +// Dummy3 is a free data retrieval call binding the contract method 0x1a97f18e. +// +// Solidity: function dummy3() pure returns(uint256) +func (_Contract *ContractCallerSession) Dummy3() (*big.Int, error) { + return _Contract.Contract.Dummy3(&_Contract.CallOpts) +} + +// Dummy30 is a free data retrieval call binding the contract method 0xcfd66863. +// +// Solidity: function dummy30() pure returns(uint256) +func (_Contract *ContractCaller) Dummy30(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Contract.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 (_Contract *ContractSession) Dummy30() (*big.Int, error) { + return _Contract.Contract.Dummy30(&_Contract.CallOpts) +} + +// Dummy30 is a free data retrieval call binding the contract method 0xcfd66863. +// +// Solidity: function dummy30() pure returns(uint256) +func (_Contract *ContractCallerSession) Dummy30() (*big.Int, error) { + return _Contract.Contract.Dummy30(&_Contract.CallOpts) +} + +// Dummy31 is a free data retrieval call binding the contract method 0x4e1dbb82. +// +// Solidity: function dummy31() pure returns(uint256) +func (_Contract *ContractCaller) Dummy31(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Contract.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 (_Contract *ContractSession) Dummy31() (*big.Int, error) { + return _Contract.Contract.Dummy31(&_Contract.CallOpts) +} + +// Dummy31 is a free data retrieval call binding the contract method 0x4e1dbb82. +// +// Solidity: function dummy31() pure returns(uint256) +func (_Contract *ContractCallerSession) Dummy31() (*big.Int, error) { + return _Contract.Contract.Dummy31(&_Contract.CallOpts) +} + +// Dummy32 is a free data retrieval call binding the contract method 0xf8716f14. +// +// Solidity: function dummy32() pure returns(uint256) +func (_Contract *ContractCaller) Dummy32(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Contract.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 (_Contract *ContractSession) Dummy32() (*big.Int, error) { + return _Contract.Contract.Dummy32(&_Contract.CallOpts) +} + +// Dummy32 is a free data retrieval call binding the contract method 0xf8716f14. +// +// Solidity: function dummy32() pure returns(uint256) +func (_Contract *ContractCallerSession) Dummy32() (*big.Int, error) { + return _Contract.Contract.Dummy32(&_Contract.CallOpts) +} + +// Dummy33 is a free data retrieval call binding the contract method 0x4b3c7f5f. +// +// Solidity: function dummy33() pure returns(uint256) +func (_Contract *ContractCaller) Dummy33(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Contract.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 (_Contract *ContractSession) Dummy33() (*big.Int, error) { + return _Contract.Contract.Dummy33(&_Contract.CallOpts) +} + +// Dummy33 is a free data retrieval call binding the contract method 0x4b3c7f5f. +// +// Solidity: function dummy33() pure returns(uint256) +func (_Contract *ContractCallerSession) Dummy33() (*big.Int, error) { + return _Contract.Contract.Dummy33(&_Contract.CallOpts) +} + +// Dummy34 is a free data retrieval call binding the contract method 0xe8c927b3. +// +// Solidity: function dummy34() pure returns(uint256) +func (_Contract *ContractCaller) Dummy34(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Contract.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 (_Contract *ContractSession) Dummy34() (*big.Int, error) { + return _Contract.Contract.Dummy34(&_Contract.CallOpts) +} + +// Dummy34 is a free data retrieval call binding the contract method 0xe8c927b3. +// +// Solidity: function dummy34() pure returns(uint256) +func (_Contract *ContractCallerSession) Dummy34() (*big.Int, error) { + return _Contract.Contract.Dummy34(&_Contract.CallOpts) +} + +// Dummy35 is a free data retrieval call binding the contract method 0x43a6b92d. +// +// Solidity: function dummy35() pure returns(uint256) +func (_Contract *ContractCaller) Dummy35(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Contract.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 (_Contract *ContractSession) Dummy35() (*big.Int, error) { + return _Contract.Contract.Dummy35(&_Contract.CallOpts) +} + +// Dummy35 is a free data retrieval call binding the contract method 0x43a6b92d. +// +// Solidity: function dummy35() pure returns(uint256) +func (_Contract *ContractCallerSession) Dummy35() (*big.Int, error) { + return _Contract.Contract.Dummy35(&_Contract.CallOpts) +} + +// Dummy36 is a free data retrieval call binding the contract method 0xc958d4bf. +// +// Solidity: function dummy36() pure returns(uint256) +func (_Contract *ContractCaller) Dummy36(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Contract.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 (_Contract *ContractSession) Dummy36() (*big.Int, error) { + return _Contract.Contract.Dummy36(&_Contract.CallOpts) +} + +// Dummy36 is a free data retrieval call binding the contract method 0xc958d4bf. +// +// Solidity: function dummy36() pure returns(uint256) +func (_Contract *ContractCallerSession) Dummy36() (*big.Int, error) { + return _Contract.Contract.Dummy36(&_Contract.CallOpts) +} + +// Dummy37 is a free data retrieval call binding the contract method 0x639ec53a. +// +// Solidity: function dummy37() pure returns(uint256) +func (_Contract *ContractCaller) Dummy37(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Contract.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 (_Contract *ContractSession) Dummy37() (*big.Int, error) { + return _Contract.Contract.Dummy37(&_Contract.CallOpts) +} + +// Dummy37 is a free data retrieval call binding the contract method 0x639ec53a. +// +// Solidity: function dummy37() pure returns(uint256) +func (_Contract *ContractCallerSession) Dummy37() (*big.Int, error) { + return _Contract.Contract.Dummy37(&_Contract.CallOpts) +} + +// Dummy38 is a free data retrieval call binding the contract method 0x4f5e5557. +// +// Solidity: function dummy38() pure returns(uint256) +func (_Contract *ContractCaller) Dummy38(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Contract.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 (_Contract *ContractSession) Dummy38() (*big.Int, error) { + return _Contract.Contract.Dummy38(&_Contract.CallOpts) +} + +// Dummy38 is a free data retrieval call binding the contract method 0x4f5e5557. +// +// Solidity: function dummy38() pure returns(uint256) +func (_Contract *ContractCallerSession) Dummy38() (*big.Int, error) { + return _Contract.Contract.Dummy38(&_Contract.CallOpts) +} + +// Dummy39 is a free data retrieval call binding the contract method 0xdc1d8a9b. +// +// Solidity: function dummy39() pure returns(uint256) +func (_Contract *ContractCaller) Dummy39(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Contract.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 (_Contract *ContractSession) Dummy39() (*big.Int, error) { + return _Contract.Contract.Dummy39(&_Contract.CallOpts) +} + +// Dummy39 is a free data retrieval call binding the contract method 0xdc1d8a9b. +// +// Solidity: function dummy39() pure returns(uint256) +func (_Contract *ContractCallerSession) Dummy39() (*big.Int, error) { + return _Contract.Contract.Dummy39(&_Contract.CallOpts) +} + +// Dummy4 is a free data retrieval call binding the contract method 0x3b6be459. +// +// Solidity: function dummy4() pure returns(uint256) +func (_Contract *ContractCaller) Dummy4(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Contract.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 (_Contract *ContractSession) Dummy4() (*big.Int, error) { + return _Contract.Contract.Dummy4(&_Contract.CallOpts) +} + +// Dummy4 is a free data retrieval call binding the contract method 0x3b6be459. +// +// Solidity: function dummy4() pure returns(uint256) +func (_Contract *ContractCallerSession) Dummy4() (*big.Int, error) { + return _Contract.Contract.Dummy4(&_Contract.CallOpts) +} + +// Dummy40 is a free data retrieval call binding the contract method 0xaaa7af70. +// +// Solidity: function dummy40() pure returns(uint256) +func (_Contract *ContractCaller) Dummy40(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Contract.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 (_Contract *ContractSession) Dummy40() (*big.Int, error) { + return _Contract.Contract.Dummy40(&_Contract.CallOpts) +} + +// Dummy40 is a free data retrieval call binding the contract method 0xaaa7af70. +// +// Solidity: function dummy40() pure returns(uint256) +func (_Contract *ContractCallerSession) Dummy40() (*big.Int, error) { + return _Contract.Contract.Dummy40(&_Contract.CallOpts) +} + +// Dummy41 is a free data retrieval call binding the contract method 0x9df61a25. +// +// Solidity: function dummy41() pure returns(uint256) +func (_Contract *ContractCaller) Dummy41(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Contract.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 (_Contract *ContractSession) Dummy41() (*big.Int, error) { + return _Contract.Contract.Dummy41(&_Contract.CallOpts) +} + +// Dummy41 is a free data retrieval call binding the contract method 0x9df61a25. +// +// Solidity: function dummy41() pure returns(uint256) +func (_Contract *ContractCallerSession) Dummy41() (*big.Int, error) { + return _Contract.Contract.Dummy41(&_Contract.CallOpts) +} + +// Dummy42 is a free data retrieval call binding the contract method 0x5af92c05. +// +// Solidity: function dummy42() pure returns(uint256) +func (_Contract *ContractCaller) Dummy42(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Contract.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 (_Contract *ContractSession) Dummy42() (*big.Int, error) { + return _Contract.Contract.Dummy42(&_Contract.CallOpts) +} + +// Dummy42 is a free data retrieval call binding the contract method 0x5af92c05. +// +// Solidity: function dummy42() pure returns(uint256) +func (_Contract *ContractCallerSession) Dummy42() (*big.Int, error) { + return _Contract.Contract.Dummy42(&_Contract.CallOpts) +} + +// Dummy43 is a free data retrieval call binding the contract method 0x7c72ed0d. +// +// Solidity: function dummy43() pure returns(uint256) +func (_Contract *ContractCaller) Dummy43(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Contract.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 (_Contract *ContractSession) Dummy43() (*big.Int, error) { + return _Contract.Contract.Dummy43(&_Contract.CallOpts) +} + +// Dummy43 is a free data retrieval call binding the contract method 0x7c72ed0d. +// +// Solidity: function dummy43() pure returns(uint256) +func (_Contract *ContractCallerSession) Dummy43() (*big.Int, error) { + return _Contract.Contract.Dummy43(&_Contract.CallOpts) +} + +// Dummy44 is a free data retrieval call binding the contract method 0x239af2a5. +// +// Solidity: function dummy44() pure returns(uint256) +func (_Contract *ContractCaller) Dummy44(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Contract.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 (_Contract *ContractSession) Dummy44() (*big.Int, error) { + return _Contract.Contract.Dummy44(&_Contract.CallOpts) +} + +// Dummy44 is a free data retrieval call binding the contract method 0x239af2a5. +// +// Solidity: function dummy44() pure returns(uint256) +func (_Contract *ContractCallerSession) Dummy44() (*big.Int, error) { + return _Contract.Contract.Dummy44(&_Contract.CallOpts) +} + +// Dummy45 is a free data retrieval call binding the contract method 0x7f34d94b. +// +// Solidity: function dummy45() pure returns(uint256) +func (_Contract *ContractCaller) Dummy45(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Contract.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 (_Contract *ContractSession) Dummy45() (*big.Int, error) { + return _Contract.Contract.Dummy45(&_Contract.CallOpts) +} + +// Dummy45 is a free data retrieval call binding the contract method 0x7f34d94b. +// +// Solidity: function dummy45() pure returns(uint256) +func (_Contract *ContractCallerSession) Dummy45() (*big.Int, error) { + return _Contract.Contract.Dummy45(&_Contract.CallOpts) +} + +// Dummy46 is a free data retrieval call binding the contract method 0x21ecd7a3. +// +// Solidity: function dummy46() pure returns(uint256) +func (_Contract *ContractCaller) Dummy46(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Contract.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 (_Contract *ContractSession) Dummy46() (*big.Int, error) { + return _Contract.Contract.Dummy46(&_Contract.CallOpts) +} + +// Dummy46 is a free data retrieval call binding the contract method 0x21ecd7a3. +// +// Solidity: function dummy46() pure returns(uint256) +func (_Contract *ContractCallerSession) Dummy46() (*big.Int, error) { + return _Contract.Contract.Dummy46(&_Contract.CallOpts) +} + +// Dummy47 is a free data retrieval call binding the contract method 0x0717b161. +// +// Solidity: function dummy47() pure returns(uint256) +func (_Contract *ContractCaller) Dummy47(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Contract.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 (_Contract *ContractSession) Dummy47() (*big.Int, error) { + return _Contract.Contract.Dummy47(&_Contract.CallOpts) +} + +// Dummy47 is a free data retrieval call binding the contract method 0x0717b161. +// +// Solidity: function dummy47() pure returns(uint256) +func (_Contract *ContractCallerSession) Dummy47() (*big.Int, error) { + return _Contract.Contract.Dummy47(&_Contract.CallOpts) +} + +// Dummy48 is a free data retrieval call binding the contract method 0x8619d607. +// +// Solidity: function dummy48() pure returns(uint256) +func (_Contract *ContractCaller) Dummy48(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Contract.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 (_Contract *ContractSession) Dummy48() (*big.Int, error) { + return _Contract.Contract.Dummy48(&_Contract.CallOpts) +} + +// Dummy48 is a free data retrieval call binding the contract method 0x8619d607. +// +// Solidity: function dummy48() pure returns(uint256) +func (_Contract *ContractCallerSession) Dummy48() (*big.Int, error) { + return _Contract.Contract.Dummy48(&_Contract.CallOpts) +} + +// Dummy49 is a free data retrieval call binding the contract method 0xd101dcd0. +// +// Solidity: function dummy49() pure returns(uint256) +func (_Contract *ContractCaller) Dummy49(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Contract.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 (_Contract *ContractSession) Dummy49() (*big.Int, error) { + return _Contract.Contract.Dummy49(&_Contract.CallOpts) +} + +// Dummy49 is a free data retrieval call binding the contract method 0xd101dcd0. +// +// Solidity: function dummy49() pure returns(uint256) +func (_Contract *ContractCallerSession) Dummy49() (*big.Int, error) { + return _Contract.Contract.Dummy49(&_Contract.CallOpts) +} + +// Dummy5 is a free data retrieval call binding the contract method 0x1215a3ab. +// +// Solidity: function dummy5() pure returns(uint256) +func (_Contract *ContractCaller) Dummy5(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Contract.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 (_Contract *ContractSession) Dummy5() (*big.Int, error) { + return _Contract.Contract.Dummy5(&_Contract.CallOpts) +} + +// Dummy5 is a free data retrieval call binding the contract method 0x1215a3ab. +// +// Solidity: function dummy5() pure returns(uint256) +func (_Contract *ContractCallerSession) Dummy5() (*big.Int, error) { + return _Contract.Contract.Dummy5(&_Contract.CallOpts) +} + +// Dummy50 is a free data retrieval call binding the contract method 0x42937dbd. +// +// Solidity: function dummy50() pure returns(uint256) +func (_Contract *ContractCaller) Dummy50(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Contract.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 (_Contract *ContractSession) Dummy50() (*big.Int, error) { + return _Contract.Contract.Dummy50(&_Contract.CallOpts) +} + +// Dummy50 is a free data retrieval call binding the contract method 0x42937dbd. +// +// Solidity: function dummy50() pure returns(uint256) +func (_Contract *ContractCallerSession) Dummy50() (*big.Int, error) { + return _Contract.Contract.Dummy50(&_Contract.CallOpts) +} + +// Dummy51 is a free data retrieval call binding the contract method 0x16a3045b. +// +// Solidity: function dummy51() pure returns(uint256) +func (_Contract *ContractCaller) Dummy51(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Contract.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 (_Contract *ContractSession) Dummy51() (*big.Int, error) { + return _Contract.Contract.Dummy51(&_Contract.CallOpts) +} + +// Dummy51 is a free data retrieval call binding the contract method 0x16a3045b. +// +// Solidity: function dummy51() pure returns(uint256) +func (_Contract *ContractCallerSession) Dummy51() (*big.Int, error) { + return _Contract.Contract.Dummy51(&_Contract.CallOpts) +} + +// Dummy52 is a free data retrieval call binding the contract method 0x3125f37a. +// +// Solidity: function dummy52() pure returns(uint256) +func (_Contract *ContractCaller) Dummy52(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Contract.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 (_Contract *ContractSession) Dummy52() (*big.Int, error) { + return _Contract.Contract.Dummy52(&_Contract.CallOpts) +} + +// Dummy52 is a free data retrieval call binding the contract method 0x3125f37a. +// +// Solidity: function dummy52() pure returns(uint256) +func (_Contract *ContractCallerSession) Dummy52() (*big.Int, error) { + return _Contract.Contract.Dummy52(&_Contract.CallOpts) +} + +// Dummy53 is a free data retrieval call binding the contract method 0x1fd298ec. +// +// Solidity: function dummy53() pure returns(uint256) +func (_Contract *ContractCaller) Dummy53(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Contract.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 (_Contract *ContractSession) Dummy53() (*big.Int, error) { + return _Contract.Contract.Dummy53(&_Contract.CallOpts) +} + +// Dummy53 is a free data retrieval call binding the contract method 0x1fd298ec. +// +// Solidity: function dummy53() pure returns(uint256) +func (_Contract *ContractCallerSession) Dummy53() (*big.Int, error) { + return _Contract.Contract.Dummy53(&_Contract.CallOpts) +} + +// Dummy54 is a free data retrieval call binding the contract method 0x792c7f3e. +// +// Solidity: function dummy54() pure returns(uint256) +func (_Contract *ContractCaller) Dummy54(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Contract.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 (_Contract *ContractSession) Dummy54() (*big.Int, error) { + return _Contract.Contract.Dummy54(&_Contract.CallOpts) +} + +// Dummy54 is a free data retrieval call binding the contract method 0x792c7f3e. +// +// Solidity: function dummy54() pure returns(uint256) +func (_Contract *ContractCallerSession) Dummy54() (*big.Int, error) { + return _Contract.Contract.Dummy54(&_Contract.CallOpts) +} + +// Dummy55 is a free data retrieval call binding the contract method 0x7dffdc32. +// +// Solidity: function dummy55() pure returns(uint256) +func (_Contract *ContractCaller) Dummy55(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Contract.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 (_Contract *ContractSession) Dummy55() (*big.Int, error) { + return _Contract.Contract.Dummy55(&_Contract.CallOpts) +} + +// Dummy55 is a free data retrieval call binding the contract method 0x7dffdc32. +// +// Solidity: function dummy55() pure returns(uint256) +func (_Contract *ContractCallerSession) Dummy55() (*big.Int, error) { + return _Contract.Contract.Dummy55(&_Contract.CallOpts) +} + +// Dummy56 is a free data retrieval call binding the contract method 0xa891d4d4. +// +// Solidity: function dummy56() pure returns(uint256) +func (_Contract *ContractCaller) Dummy56(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Contract.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 (_Contract *ContractSession) Dummy56() (*big.Int, error) { + return _Contract.Contract.Dummy56(&_Contract.CallOpts) +} + +// Dummy56 is a free data retrieval call binding the contract method 0xa891d4d4. +// +// Solidity: function dummy56() pure returns(uint256) +func (_Contract *ContractCallerSession) Dummy56() (*big.Int, error) { + return _Contract.Contract.Dummy56(&_Contract.CallOpts) +} + +// Dummy57 is a free data retrieval call binding the contract method 0x74f83d02. +// +// Solidity: function dummy57() pure returns(uint256) +func (_Contract *ContractCaller) Dummy57(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Contract.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 (_Contract *ContractSession) Dummy57() (*big.Int, error) { + return _Contract.Contract.Dummy57(&_Contract.CallOpts) +} + +// Dummy57 is a free data retrieval call binding the contract method 0x74f83d02. +// +// Solidity: function dummy57() pure returns(uint256) +func (_Contract *ContractCallerSession) Dummy57() (*big.Int, error) { + return _Contract.Contract.Dummy57(&_Contract.CallOpts) +} + +// Dummy58 is a free data retrieval call binding the contract method 0x54c27920. +// +// Solidity: function dummy58() pure returns(uint256) +func (_Contract *ContractCaller) Dummy58(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Contract.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 (_Contract *ContractSession) Dummy58() (*big.Int, error) { + return _Contract.Contract.Dummy58(&_Contract.CallOpts) +} + +// Dummy58 is a free data retrieval call binding the contract method 0x54c27920. +// +// Solidity: function dummy58() pure returns(uint256) +func (_Contract *ContractCallerSession) Dummy58() (*big.Int, error) { + return _Contract.Contract.Dummy58(&_Contract.CallOpts) +} + +// Dummy59 is a free data retrieval call binding the contract method 0x77c0209e. +// +// Solidity: function dummy59() pure returns(uint256) +func (_Contract *ContractCaller) Dummy59(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Contract.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 (_Contract *ContractSession) Dummy59() (*big.Int, error) { + return _Contract.Contract.Dummy59(&_Contract.CallOpts) +} + +// Dummy59 is a free data retrieval call binding the contract method 0x77c0209e. +// +// Solidity: function dummy59() pure returns(uint256) +func (_Contract *ContractCallerSession) Dummy59() (*big.Int, error) { + return _Contract.Contract.Dummy59(&_Contract.CallOpts) +} + +// Dummy6 is a free data retrieval call binding the contract method 0x4128a85d. +// +// Solidity: function dummy6() pure returns(uint256) +func (_Contract *ContractCaller) Dummy6(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Contract.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 (_Contract *ContractSession) Dummy6() (*big.Int, error) { + return _Contract.Contract.Dummy6(&_Contract.CallOpts) +} + +// Dummy6 is a free data retrieval call binding the contract method 0x4128a85d. +// +// Solidity: function dummy6() pure returns(uint256) +func (_Contract *ContractCallerSession) Dummy6() (*big.Int, error) { + return _Contract.Contract.Dummy6(&_Contract.CallOpts) +} + +// Dummy60 is a free data retrieval call binding the contract method 0x34517f0b. +// +// Solidity: function dummy60() pure returns(uint256) +func (_Contract *ContractCaller) Dummy60(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Contract.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 (_Contract *ContractSession) Dummy60() (*big.Int, error) { + return _Contract.Contract.Dummy60(&_Contract.CallOpts) +} + +// Dummy60 is a free data retrieval call binding the contract method 0x34517f0b. +// +// Solidity: function dummy60() pure returns(uint256) +func (_Contract *ContractCallerSession) Dummy60() (*big.Int, error) { + return _Contract.Contract.Dummy60(&_Contract.CallOpts) +} + +// Dummy61 is a free data retrieval call binding the contract method 0xe2d27530. +// +// Solidity: function dummy61() pure returns(uint256) +func (_Contract *ContractCaller) Dummy61(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Contract.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 (_Contract *ContractSession) Dummy61() (*big.Int, error) { + return _Contract.Contract.Dummy61(&_Contract.CallOpts) +} + +// Dummy61 is a free data retrieval call binding the contract method 0xe2d27530. +// +// Solidity: function dummy61() pure returns(uint256) +func (_Contract *ContractCallerSession) Dummy61() (*big.Int, error) { + return _Contract.Contract.Dummy61(&_Contract.CallOpts) +} + +// Dummy62 is a free data retrieval call binding the contract method 0xf5f57381. +// +// Solidity: function dummy62() pure returns(uint256) +func (_Contract *ContractCaller) Dummy62(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Contract.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 (_Contract *ContractSession) Dummy62() (*big.Int, error) { + return _Contract.Contract.Dummy62(&_Contract.CallOpts) +} + +// Dummy62 is a free data retrieval call binding the contract method 0xf5f57381. +// +// Solidity: function dummy62() pure returns(uint256) +func (_Contract *ContractCallerSession) Dummy62() (*big.Int, error) { + return _Contract.Contract.Dummy62(&_Contract.CallOpts) +} + +// Dummy63 is a free data retrieval call binding the contract method 0x7a319c18. +// +// Solidity: function dummy63() pure returns(uint256) +func (_Contract *ContractCaller) Dummy63(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Contract.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 (_Contract *ContractSession) Dummy63() (*big.Int, error) { + return _Contract.Contract.Dummy63(&_Contract.CallOpts) +} + +// Dummy63 is a free data retrieval call binding the contract method 0x7a319c18. +// +// Solidity: function dummy63() pure returns(uint256) +func (_Contract *ContractCallerSession) Dummy63() (*big.Int, error) { + return _Contract.Contract.Dummy63(&_Contract.CallOpts) +} + +// Dummy64 is a free data retrieval call binding the contract method 0xad8f4221. +// +// Solidity: function dummy64() pure returns(uint256) +func (_Contract *ContractCaller) Dummy64(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Contract.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 (_Contract *ContractSession) Dummy64() (*big.Int, error) { + return _Contract.Contract.Dummy64(&_Contract.CallOpts) +} + +// Dummy64 is a free data retrieval call binding the contract method 0xad8f4221. +// +// Solidity: function dummy64() pure returns(uint256) +func (_Contract *ContractCallerSession) Dummy64() (*big.Int, error) { + return _Contract.Contract.Dummy64(&_Contract.CallOpts) +} + +// Dummy65 is a free data retrieval call binding the contract method 0x1f449589. +// +// Solidity: function dummy65() pure returns(uint256) +func (_Contract *ContractCaller) Dummy65(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Contract.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 (_Contract *ContractSession) Dummy65() (*big.Int, error) { + return _Contract.Contract.Dummy65(&_Contract.CallOpts) +} + +// Dummy65 is a free data retrieval call binding the contract method 0x1f449589. +// +// Solidity: function dummy65() pure returns(uint256) +func (_Contract *ContractCallerSession) Dummy65() (*big.Int, error) { + return _Contract.Contract.Dummy65(&_Contract.CallOpts) +} + +// Dummy7 is a free data retrieval call binding the contract method 0xf26c779b. +// +// Solidity: function dummy7() pure returns(uint256) +func (_Contract *ContractCaller) Dummy7(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Contract.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 (_Contract *ContractSession) Dummy7() (*big.Int, error) { + return _Contract.Contract.Dummy7(&_Contract.CallOpts) +} + +// Dummy7 is a free data retrieval call binding the contract method 0xf26c779b. +// +// Solidity: function dummy7() pure returns(uint256) +func (_Contract *ContractCallerSession) Dummy7() (*big.Int, error) { + return _Contract.Contract.Dummy7(&_Contract.CallOpts) +} + +// Dummy8 is a free data retrieval call binding the contract method 0x19cf6a91. +// +// Solidity: function dummy8() pure returns(uint256) +func (_Contract *ContractCaller) Dummy8(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Contract.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 (_Contract *ContractSession) Dummy8() (*big.Int, error) { + return _Contract.Contract.Dummy8(&_Contract.CallOpts) +} + +// Dummy8 is a free data retrieval call binding the contract method 0x19cf6a91. +// +// Solidity: function dummy8() pure returns(uint256) +func (_Contract *ContractCallerSession) Dummy8() (*big.Int, error) { + return _Contract.Contract.Dummy8(&_Contract.CallOpts) +} + +// Dummy9 is a free data retrieval call binding the contract method 0x58b6a9bd. +// +// Solidity: function dummy9() pure returns(uint256) +func (_Contract *ContractCaller) Dummy9(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Contract.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 (_Contract *ContractSession) Dummy9() (*big.Int, error) { + return _Contract.Contract.Dummy9(&_Contract.CallOpts) +} + +// Dummy9 is a free data retrieval call binding the contract method 0x58b6a9bd. +// +// Solidity: function dummy9() pure returns(uint256) +func (_Contract *ContractCallerSession) Dummy9() (*big.Int, error) { + return _Contract.Contract.Dummy9(&_Contract.CallOpts) +} + +// Name is a free data retrieval call binding the contract method 0x06fdde03. +// +// Solidity: function name() view returns(string) +func (_Contract *ContractCaller) Name(opts *bind.CallOpts) (string, error) { + var out []interface{} + err := _Contract.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 (_Contract *ContractSession) Name() (string, error) { + return _Contract.Contract.Name(&_Contract.CallOpts) +} + +// Name is a free data retrieval call binding the contract method 0x06fdde03. +// +// Solidity: function name() view returns(string) +func (_Contract *ContractCallerSession) Name() (string, error) { + return _Contract.Contract.Name(&_Contract.CallOpts) +} + +// Salt is a free data retrieval call binding the contract method 0xbfa0b133. +// +// Solidity: function salt() view returns(uint256) +func (_Contract *ContractCaller) Salt(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Contract.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 (_Contract *ContractSession) Salt() (*big.Int, error) { + return _Contract.Contract.Salt(&_Contract.CallOpts) +} + +// Salt is a free data retrieval call binding the contract method 0xbfa0b133. +// +// Solidity: function salt() view returns(uint256) +func (_Contract *ContractCallerSession) Salt() (*big.Int, error) { + return _Contract.Contract.Salt(&_Contract.CallOpts) +} + +// Symbol is a free data retrieval call binding the contract method 0x95d89b41. +// +// Solidity: function symbol() view returns(string) +func (_Contract *ContractCaller) Symbol(opts *bind.CallOpts) (string, error) { + var out []interface{} + err := _Contract.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 (_Contract *ContractSession) Symbol() (string, error) { + return _Contract.Contract.Symbol(&_Contract.CallOpts) +} + +// Symbol is a free data retrieval call binding the contract method 0x95d89b41. +// +// Solidity: function symbol() view returns(string) +func (_Contract *ContractCallerSession) Symbol() (string, error) { + return _Contract.Contract.Symbol(&_Contract.CallOpts) +} + +// TotalSupply is a free data retrieval call binding the contract method 0x18160ddd. +// +// Solidity: function totalSupply() view returns(uint256) +func (_Contract *ContractCaller) TotalSupply(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Contract.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 (_Contract *ContractSession) TotalSupply() (*big.Int, error) { + return _Contract.Contract.TotalSupply(&_Contract.CallOpts) +} + +// TotalSupply is a free data retrieval call binding the contract method 0x18160ddd. +// +// Solidity: function totalSupply() view returns(uint256) +func (_Contract *ContractCallerSession) TotalSupply() (*big.Int, error) { + return _Contract.Contract.TotalSupply(&_Contract.CallOpts) +} + +// Approve is a paid mutator transaction binding the contract method 0x095ea7b3. +// +// Solidity: function approve(address spender, uint256 value) returns(bool) +func (_Contract *ContractTransactor) Approve(opts *bind.TransactOpts, spender common.Address, value *big.Int) (*types.Transaction, error) { + return _Contract.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 (_Contract *ContractSession) Approve(spender common.Address, value *big.Int) (*types.Transaction, error) { + return _Contract.Contract.Approve(&_Contract.TransactOpts, spender, value) +} + +// Approve is a paid mutator transaction binding the contract method 0x095ea7b3. +// +// Solidity: function approve(address spender, uint256 value) returns(bool) +func (_Contract *ContractTransactorSession) Approve(spender common.Address, value *big.Int) (*types.Transaction, error) { + return _Contract.Contract.Approve(&_Contract.TransactOpts, spender, value) +} + +// Transfer is a paid mutator transaction binding the contract method 0xa9059cbb. +// +// Solidity: function transfer(address to, uint256 value) returns(bool) +func (_Contract *ContractTransactor) Transfer(opts *bind.TransactOpts, to common.Address, value *big.Int) (*types.Transaction, error) { + return _Contract.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 (_Contract *ContractSession) Transfer(to common.Address, value *big.Int) (*types.Transaction, error) { + return _Contract.Contract.Transfer(&_Contract.TransactOpts, to, value) +} + +// Transfer is a paid mutator transaction binding the contract method 0xa9059cbb. +// +// Solidity: function transfer(address to, uint256 value) returns(bool) +func (_Contract *ContractTransactorSession) Transfer(to common.Address, value *big.Int) (*types.Transaction, error) { + return _Contract.Contract.Transfer(&_Contract.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 (_Contract *ContractTransactor) TransferFrom(opts *bind.TransactOpts, from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) { + return _Contract.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 (_Contract *ContractSession) TransferFrom(from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) { + return _Contract.Contract.TransferFrom(&_Contract.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 (_Contract *ContractTransactorSession) TransferFrom(from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) { + return _Contract.Contract.TransferFrom(&_Contract.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 (_Contract *ContractTransactor) TransferFrom1(opts *bind.TransactOpts, from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) { + return _Contract.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 (_Contract *ContractSession) TransferFrom1(from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) { + return _Contract.Contract.TransferFrom1(&_Contract.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 (_Contract *ContractTransactorSession) TransferFrom1(from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) { + return _Contract.Contract.TransferFrom1(&_Contract.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 (_Contract *ContractTransactor) TransferFrom10(opts *bind.TransactOpts, from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) { + return _Contract.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 (_Contract *ContractSession) TransferFrom10(from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) { + return _Contract.Contract.TransferFrom10(&_Contract.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 (_Contract *ContractTransactorSession) TransferFrom10(from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) { + return _Contract.Contract.TransferFrom10(&_Contract.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 (_Contract *ContractTransactor) TransferFrom11(opts *bind.TransactOpts, from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) { + return _Contract.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 (_Contract *ContractSession) TransferFrom11(from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) { + return _Contract.Contract.TransferFrom11(&_Contract.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 (_Contract *ContractTransactorSession) TransferFrom11(from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) { + return _Contract.Contract.TransferFrom11(&_Contract.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 (_Contract *ContractTransactor) TransferFrom12(opts *bind.TransactOpts, from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) { + return _Contract.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 (_Contract *ContractSession) TransferFrom12(from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) { + return _Contract.Contract.TransferFrom12(&_Contract.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 (_Contract *ContractTransactorSession) TransferFrom12(from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) { + return _Contract.Contract.TransferFrom12(&_Contract.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 (_Contract *ContractTransactor) TransferFrom13(opts *bind.TransactOpts, from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) { + return _Contract.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 (_Contract *ContractSession) TransferFrom13(from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) { + return _Contract.Contract.TransferFrom13(&_Contract.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 (_Contract *ContractTransactorSession) TransferFrom13(from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) { + return _Contract.Contract.TransferFrom13(&_Contract.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 (_Contract *ContractTransactor) TransferFrom14(opts *bind.TransactOpts, from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) { + return _Contract.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 (_Contract *ContractSession) TransferFrom14(from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) { + return _Contract.Contract.TransferFrom14(&_Contract.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 (_Contract *ContractTransactorSession) TransferFrom14(from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) { + return _Contract.Contract.TransferFrom14(&_Contract.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 (_Contract *ContractTransactor) TransferFrom15(opts *bind.TransactOpts, from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) { + return _Contract.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 (_Contract *ContractSession) TransferFrom15(from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) { + return _Contract.Contract.TransferFrom15(&_Contract.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 (_Contract *ContractTransactorSession) TransferFrom15(from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) { + return _Contract.Contract.TransferFrom15(&_Contract.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 (_Contract *ContractTransactor) TransferFrom16(opts *bind.TransactOpts, from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) { + return _Contract.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 (_Contract *ContractSession) TransferFrom16(from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) { + return _Contract.Contract.TransferFrom16(&_Contract.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 (_Contract *ContractTransactorSession) TransferFrom16(from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) { + return _Contract.Contract.TransferFrom16(&_Contract.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 (_Contract *ContractTransactor) TransferFrom17(opts *bind.TransactOpts, from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) { + return _Contract.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 (_Contract *ContractSession) TransferFrom17(from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) { + return _Contract.Contract.TransferFrom17(&_Contract.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 (_Contract *ContractTransactorSession) TransferFrom17(from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) { + return _Contract.Contract.TransferFrom17(&_Contract.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 (_Contract *ContractTransactor) TransferFrom18(opts *bind.TransactOpts, from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) { + return _Contract.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 (_Contract *ContractSession) TransferFrom18(from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) { + return _Contract.Contract.TransferFrom18(&_Contract.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 (_Contract *ContractTransactorSession) TransferFrom18(from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) { + return _Contract.Contract.TransferFrom18(&_Contract.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 (_Contract *ContractTransactor) TransferFrom19(opts *bind.TransactOpts, from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) { + return _Contract.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 (_Contract *ContractSession) TransferFrom19(from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) { + return _Contract.Contract.TransferFrom19(&_Contract.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 (_Contract *ContractTransactorSession) TransferFrom19(from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) { + return _Contract.Contract.TransferFrom19(&_Contract.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 (_Contract *ContractTransactor) TransferFrom2(opts *bind.TransactOpts, from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) { + return _Contract.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 (_Contract *ContractSession) TransferFrom2(from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) { + return _Contract.Contract.TransferFrom2(&_Contract.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 (_Contract *ContractTransactorSession) TransferFrom2(from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) { + return _Contract.Contract.TransferFrom2(&_Contract.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 (_Contract *ContractTransactor) TransferFrom3(opts *bind.TransactOpts, from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) { + return _Contract.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 (_Contract *ContractSession) TransferFrom3(from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) { + return _Contract.Contract.TransferFrom3(&_Contract.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 (_Contract *ContractTransactorSession) TransferFrom3(from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) { + return _Contract.Contract.TransferFrom3(&_Contract.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 (_Contract *ContractTransactor) TransferFrom4(opts *bind.TransactOpts, from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) { + return _Contract.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 (_Contract *ContractSession) TransferFrom4(from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) { + return _Contract.Contract.TransferFrom4(&_Contract.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 (_Contract *ContractTransactorSession) TransferFrom4(from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) { + return _Contract.Contract.TransferFrom4(&_Contract.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 (_Contract *ContractTransactor) TransferFrom5(opts *bind.TransactOpts, from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) { + return _Contract.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 (_Contract *ContractSession) TransferFrom5(from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) { + return _Contract.Contract.TransferFrom5(&_Contract.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 (_Contract *ContractTransactorSession) TransferFrom5(from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) { + return _Contract.Contract.TransferFrom5(&_Contract.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 (_Contract *ContractTransactor) TransferFrom6(opts *bind.TransactOpts, from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) { + return _Contract.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 (_Contract *ContractSession) TransferFrom6(from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) { + return _Contract.Contract.TransferFrom6(&_Contract.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 (_Contract *ContractTransactorSession) TransferFrom6(from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) { + return _Contract.Contract.TransferFrom6(&_Contract.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 (_Contract *ContractTransactor) TransferFrom7(opts *bind.TransactOpts, from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) { + return _Contract.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 (_Contract *ContractSession) TransferFrom7(from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) { + return _Contract.Contract.TransferFrom7(&_Contract.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 (_Contract *ContractTransactorSession) TransferFrom7(from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) { + return _Contract.Contract.TransferFrom7(&_Contract.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 (_Contract *ContractTransactor) TransferFrom8(opts *bind.TransactOpts, from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) { + return _Contract.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 (_Contract *ContractSession) TransferFrom8(from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) { + return _Contract.Contract.TransferFrom8(&_Contract.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 (_Contract *ContractTransactorSession) TransferFrom8(from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) { + return _Contract.Contract.TransferFrom8(&_Contract.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 (_Contract *ContractTransactor) TransferFrom9(opts *bind.TransactOpts, from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) { + return _Contract.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 (_Contract *ContractSession) TransferFrom9(from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) { + return _Contract.Contract.TransferFrom9(&_Contract.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 (_Contract *ContractTransactorSession) TransferFrom9(from common.Address, to common.Address, value *big.Int) (*types.Transaction, error) { + return _Contract.Contract.TransferFrom9(&_Contract.TransactOpts, from, to, value) +} + +// ContractApprovalIterator is returned from FilterApproval and is used to iterate over the raw logs and unpacked data for Approval events raised by the Contract contract. +type ContractApprovalIterator struct { + Event *ContractApproval // 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 *ContractApprovalIterator) 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(ContractApproval) + 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(ContractApproval) + 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 *ContractApprovalIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *ContractApprovalIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// ContractApproval represents a Approval event raised by the Contract contract. +type ContractApproval 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 (_Contract *ContractFilterer) FilterApproval(opts *bind.FilterOpts, owner []common.Address, spender []common.Address) (*ContractApprovalIterator, 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 := _Contract.contract.FilterLogs(opts, "Approval", ownerRule, spenderRule) + if err != nil { + return nil, err + } + return &ContractApprovalIterator{contract: _Contract.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 (_Contract *ContractFilterer) WatchApproval(opts *bind.WatchOpts, sink chan<- *ContractApproval, 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 := _Contract.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(ContractApproval) + if err := _Contract.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 (_Contract *ContractFilterer) ParseApproval(log types.Log) (*ContractApproval, error) { + event := new(ContractApproval) + if err := _Contract.contract.UnpackLog(event, "Approval", log); err != nil { + return nil, err + } + event.Raw = log + return event, nil +} + +// ContractTransferIterator is returned from FilterTransfer and is used to iterate over the raw logs and unpacked data for Transfer events raised by the Contract contract. +type ContractTransferIterator struct { + Event *ContractTransfer // 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 *ContractTransferIterator) 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(ContractTransfer) + 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(ContractTransfer) + 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 *ContractTransferIterator) Error() error { + return it.fail +} + +// Close terminates the iteration process, releasing any pending underlying +// resources. +func (it *ContractTransferIterator) Close() error { + it.sub.Unsubscribe() + return nil +} + +// ContractTransfer represents a Transfer event raised by the Contract contract. +type ContractTransfer 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 (_Contract *ContractFilterer) FilterTransfer(opts *bind.FilterOpts, from []common.Address, to []common.Address) (*ContractTransferIterator, 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 := _Contract.contract.FilterLogs(opts, "Transfer", fromRule, toRule) + if err != nil { + return nil, err + } + return &ContractTransferIterator{contract: _Contract.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 (_Contract *ContractFilterer) WatchTransfer(opts *bind.WatchOpts, sink chan<- *ContractTransfer, 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 := _Contract.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(ContractTransfer) + if err := _Contract.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 (_Contract *ContractFilterer) ParseTransfer(log types.Log) (*ContractTransfer, error) { + event := new(ContractTransfer) + if err := _Contract.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_deploy.go b/scenarios/statebloat/contract_deploy/contract_deploy.go new file mode 100644 index 00000000..4d4197ec --- /dev/null +++ b/scenarios/statebloat/contract_deploy/contract_deploy.go @@ -0,0 +1,719 @@ +package contractdeploy + +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/sirupsen/logrus" + "github.com/spf13/pflag" + + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethpandaops/spamoor/scenarios/statebloat/contract_deploy/contract" + "github.com/ethpandaops/spamoor/scenario" + "github.com/ethpandaops/spamoor/spamoor" +) + +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"` +} + +// ContractDeployment tracks a deployed contract with its deployer info +type ContractDeployment struct { + ContractAddress string `json:"contract_address"` + PrivateKey string `json:"private_key"` +} + +// PendingTransaction tracks a transaction until it's mined +type PendingTransaction struct { + TxHash common.Hash + PrivateKey *ecdsa.PrivateKey + Timestamp time.Time +} + +// 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 + + // Cached chain ID to avoid repeated RPC calls + chainID *big.Int + chainIDOnce sync.Once + chainIDError error + + // Transaction tracking + pendingTxs map[common.Hash]*PendingTransaction + pendingTxsMutex sync.RWMutex + + // Results tracking + deployedContracts []ContractDeployment + contractsMutex sync.Mutex + + // Block-level statistics tracking + blockStats map[uint64]*BlockDeploymentStats + blockStatsMutex sync.Mutex + lastLoggedBlock uint64 + + // Block monitoring for real-time logging + blockMonitorCancel context.CancelFunc + blockMonitorDone chan struct{} +} + +var ScenarioName = "contract-deploy" +var ScenarioDefaultOptions = ScenarioOptions{ + MaxPending: 100, // Allow up to 100 pending transactions + MaxWallets: 0, // Use root wallet only by default + BaseFee: 5, // Moderate base fee (5 gwei) + TipFee: 1, // Priority fee (1 gwei) + MaxTransactions: 0, +} +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), + pendingTxs: make(map[common.Hash]*PendingTransaction), + } +} + +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)") + 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 { + // Use only root wallet by default for better efficiency + // This avoids child wallet funding overhead + s.walletPool.SetWalletCount(0) + } + + return nil +} + + +// getChainID caches the chain ID to avoid repeated RPC calls +func (s *Scenario) getChainID(ctx context.Context) (*big.Int, error) { + s.chainIDOnce.Do(func() { + client := s.walletPool.GetClient(spamoor.SelectClientByIndex, 0, s.options.ClientGroup) + if client == nil { + s.chainIDError = fmt.Errorf("no client available for chain ID") + return + } + s.chainID, s.chainIDError = client.GetChainId(ctx) + }) + return s.chainID, s.chainIDError +} + +// waitForPendingTxSlot waits until we have capacity for another transaction +func (s *Scenario) waitForPendingTxSlot(ctx context.Context) { + for { + s.pendingTxsMutex.RLock() + count := len(s.pendingTxs) + s.pendingTxsMutex.RUnlock() + + if count < int(s.options.MaxPending) { + return + } + + // Check and clean up confirmed transactions + s.processPendingTransactions(ctx) + time.Sleep(1 * time.Second) + } +} + +// processPendingTransactions checks for transaction confirmations and updates state +func (s *Scenario) processPendingTransactions(ctx context.Context) { + s.pendingTxsMutex.Lock() + + client := s.walletPool.GetClient(spamoor.SelectClientByIndex, 0, s.options.ClientGroup) + if client == nil { + s.pendingTxsMutex.Unlock() + return + } + + ethClient := client.GetEthClient() + var confirmedTxs []common.Hash + var timedOutTxs []common.Hash + var successfulDeployments []struct { + ContractAddress common.Address + PrivateKey *ecdsa.PrivateKey + Receipt *types.Receipt + TxHash common.Hash + } + + for txHash, pendingTx := range s.pendingTxs { + // Check if transaction is too old (1 minute timeout) + if time.Since(pendingTx.Timestamp) > 1*time.Minute { + s.logger.Warnf("Transaction %s timed out after 1 minute, removing from pending", txHash.Hex()) + timedOutTxs = append(timedOutTxs, txHash) + continue + } + + receipt, err := ethClient.TransactionReceipt(ctx, txHash) + if err != nil { + // Transaction still pending or error retrieving receipt + continue + } + + confirmedTxs = append(confirmedTxs, txHash) + + // Process successful deployment + if receipt.Status == 1 && receipt.ContractAddress != (common.Address{}) { + successfulDeployments = append(successfulDeployments, struct { + ContractAddress common.Address + PrivateKey *ecdsa.PrivateKey + Receipt *types.Receipt + TxHash common.Hash + }{ + ContractAddress: receipt.ContractAddress, + PrivateKey: pendingTx.PrivateKey, + Receipt: receipt, + TxHash: txHash, + }) + } + } + + // Remove confirmed transactions from pending map + for _, txHash := range confirmedTxs { + delete(s.pendingTxs, txHash) + } + + // Remove timed out transactions from pending map + for _, txHash := range timedOutTxs { + delete(s.pendingTxs, txHash) + } + + s.pendingTxsMutex.Unlock() + + // Process successful deployments after releasing the lock + for _, deployment := range successfulDeployments { + s.recordDeployedContract(deployment.ContractAddress, deployment.PrivateKey, deployment.Receipt, deployment.TxHash) + } +} + +// 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 { + // 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("deployments.json") + if err != nil { + return fmt.Errorf("failed to create deployments.json file: %w", 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 deployments.json: %w", 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) { + monitorCtx, cancel := context.WithCancel(ctx) + s.blockMonitorCancel = cancel + s.blockMonitorDone = make(chan struct{}) + + go func() { + defer close(s.blockMonitorDone) + + 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 <-monitorCtx.Done(): + return + case <-ticker.C: + // Get current block number + latestBlock, err := ethClient.BlockByNumber(monitorCtx, 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() + } + } + }() +} + +// stopBlockMonitor stops the block monitoring goroutine +func (s *Scenario) stopBlockMonitor() { + if s.blockMonitorCancel != nil { + s.blockMonitorCancel() + } + if s.blockMonitorDone != nil { + <-s.blockMonitorDone // Wait for goroutine to finish + } +} + +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) + defer s.stopBlockMonitor() + + // Cache chain ID at startup + chainID, err := s.getChainID(ctx) + if err != nil { + return fmt.Errorf("failed to get chain ID: %w", err) + } + + s.logger.Infof("Chain ID: %s", chainID.String()) + + // Get client first + client := s.walletPool.GetClient(spamoor.SelectClientByIndex, 0, s.options.ClientGroup) + if client == nil { + return fmt.Errorf("no client available") + } + ethClient := client.GetEthClient() + + // Get current block for initialization + currentBlock, err := ethClient.BlockByNumber(ctx, nil) + if err != nil { + return fmt.Errorf("failed to get current block: %w", err) + } + + // Calculate rate limiting based on block gas limit if max-transactions is 0 + var maxTxsPerBlock uint64 + var useRateLimiting bool + + if s.options.MaxTransactions == 0 { + blockGasLimit := currentBlock.GasLimit() + // TODO: This should be a constant. + estimatedGasPerContract := uint64(4949468) // Updated estimate based on contract size reduction + expectedThroughput := blockGasLimit / estimatedGasPerContract + maxTxsPerBlock = expectedThroughput * 2 // Set rate limit to 2x expected throughput + useRateLimiting = true + + s.logger.Infof("Rate limiting enabled: block gas limit %d, gas per contract %d, expected throughput %d, rate limit %d txs/block", + blockGasLimit, estimatedGasPerContract, expectedThroughput, maxTxsPerBlock) + } + + txIdxCounter := uint64(0) + totalTxCount := atomic.Uint64{} + blockTxCount := uint64(0) + lastBlockNumber := currentBlock.Number().Uint64() + + for { + // Check if we've reached max transactions (if set) + if s.options.MaxTransactions > 0 && txIdxCounter >= s.options.MaxTransactions { + s.logger.Infof("reached maximum number of transactions (%d)", s.options.MaxTransactions) + break + } + + // Rate limiting logic + if useRateLimiting { + // If we've sent expected throughput transactions, wait for next block + if blockTxCount >= maxTxsPerBlock/2 { // Send throughput amount, not rate limit amount + s.logger.Infof("Sent %d txs, waiting for next block", blockTxCount) + + // Wait for block number to change + for { + currentBlock, err := ethClient.BlockByNumber(ctx, nil) + if err == nil && currentBlock.Number().Uint64() > lastBlockNumber { + lastBlockNumber = currentBlock.Number().Uint64() + blockTxCount = 0 + break + } + time.Sleep(100 * time.Millisecond) + } + } + } + + // Wait for available slot + s.waitForPendingTxSlot(ctx) + + // Send a single transaction + err := s.sendTransaction(ctx, txIdxCounter) + if err != nil { + s.logger.Warnf("failed to send transaction %d: %v", txIdxCounter, err) + time.Sleep(1 * time.Second) + continue + } + + txIdxCounter++ + totalTxCount.Add(1) + blockTxCount++ + + // Process pending transactions periodically with 1 second intervals + if txIdxCounter%10 == 0 { + s.processPendingTransactions(ctx) + + s.contractsMutex.Lock() + contractCount := len(s.deployedContracts) + s.contractsMutex.Unlock() + + s.logger.Infof("Progress: sent %d txs, deployed %d contracts", txIdxCounter, contractCount) + } + + // Small delay to prevent overwhelming the RPC + time.Sleep(100 * time.Millisecond) + } + + // Wait for all pending transactions to complete with 1 second intervals + s.logger.Info("Waiting for remaining transactions to complete...") + for { + s.processPendingTransactions(ctx) + + s.pendingTxsMutex.RLock() + pendingCount := len(s.pendingTxs) + s.pendingTxsMutex.RUnlock() + + if pendingCount == 0 { + break + } + + s.logger.Infof("Waiting for %d pending transactions...", pendingCount) + time.Sleep(1 * time.Second) // Changed from 2 seconds to 1 second + } + + // Stop block monitoring before final cleanup + s.stopBlockMonitor() + + // 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.Load(), + "total_contracts": totalContracts, + }).Info("All transactions completed") + + return nil +} + +// sendTransaction sends a single contract deployment transaction +func (s *Scenario) sendTransaction(ctx context.Context, txIdx uint64) error { + maxRetries := 3 + + for attempt := 0; attempt < maxRetries; attempt++ { + err := s.attemptTransaction(ctx, txIdx, attempt) + if err == nil { + return 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 err + } + + return 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) error { + // Get client and wallet + client := s.walletPool.GetClient(spamoor.SelectClientRoundRobin, 0, "") + wallet := s.walletPool.GetRootWallet() + + if client == nil { + return fmt.Errorf("no client available") + } + if wallet == nil { + return fmt.Errorf("no wallet available") + } + + // Get cached chain ID + chainID, err := s.getChainID(ctx) + if err != nil { + return fmt.Errorf("failed to get chain ID: %w", err) + } + + // Get current nonce for this wallet + addr := crypto.PubkeyToAddress(wallet.GetWallet().GetPrivateKey().PublicKey) + nonce, err := client.GetEthClient().PendingNonceAt(ctx, addr) + if err != nil { + return fmt.Errorf("failed to get nonce for %s: %w", addr.Hex(), err) + } + + // Create transaction auth + auth, err := bind.NewKeyedTransactorWithChainID(wallet.GetWallet().GetPrivateKey(), chainID) + if err != nil { + return fmt.Errorf("failed to create auth: %w", err) + } + + auth.Nonce = big.NewInt(int64(nonce)) + auth.Value = big.NewInt(0) + auth.GasLimit = 5200000 // Fixed gas limit for contract deployment + + // Set EIP-1559 fee parameters + if s.options.BaseFee > 0 { + auth.GasFeeCap = new(big.Int).Mul(big.NewInt(int64(s.options.BaseFee)), big.NewInt(1000000000)) + } + if s.options.TipFee > 0 { + auth.GasTipCap = new(big.Int).Mul(big.NewInt(int64(s.options.TipFee)), big.NewInt(1000000000)) + } + + // Generate random salt for unique contract + salt := make([]byte, 32) + _, err = rand.Read(salt) + if err != nil { + return fmt.Errorf("failed to generate salt: %w", err) + } + saltInt := new(big.Int).SetBytes(salt) + + // Deploy the contract + ethClient := client.GetEthClient() + if ethClient == nil { + return fmt.Errorf("failed to get eth client") + } + + _, tx, _, err := contract.DeployContract(auth, ethClient, saltInt) + if err != nil { + return fmt.Errorf("failed to deploy contract: %w", err) + } + + // Track pending transaction + pendingTx := &PendingTransaction{ + TxHash: tx.Hash(), + PrivateKey: wallet.GetWallet().GetPrivateKey(), + Timestamp: time.Now(), + } + + s.pendingTxsMutex.Lock() + s.pendingTxs[tx.Hash()] = pendingTx + s.pendingTxsMutex.Unlock() + + return 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..8f6cf269 --- /dev/null +++ b/scenarios/statebloat/eoa_delegation/eoa_delegation.go @@ -0,0 +1,1167 @@ +package eoadelegation + +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/scenariotypes" + "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"` +} + +// 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 + + // Semaphore for worker control + workerSemaphore chan struct{} + workerDone chan struct{} + workerWg sync.WaitGroup +} + +var ScenarioName = "eoa-delegation" +var ScenarioDefaultOptions = ScenarioOptions{ + BaseFee: 20, + TipFee: 2, + CodeAddr: "", +} +var ScenarioDescriptor = scenariotypes.ScenarioDescriptor{ + Name: ScenarioName, + Description: "Maximum state bloating via EIP-7702 EOA delegations", + DefaultOptions: ScenarioDefaultOptions, + NewScenario: newScenario, +} + +func newScenario(logger logrus.FieldLogger) scenariotypes.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)") + return nil +} + +func (s *Scenario) Init(walletPool *spamoor.WalletPool, config string) error { + s.walletPool = walletPool + + if config != "" { + err := yaml.Unmarshal([]byte(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 1 wallet (the root wallet) + s.walletPool.SetWalletCount(1) + + // Initialize FIFO queue and worker for EOA management + s.eoaQueue = make([]EOAEntry, 0) + s.workerSemaphore = make(chan struct{}, 1) // Buffered channel for semaphore + s.workerDone = make(chan struct{}) + + // Start the worker goroutine for writing EOAs to file + s.workerWg.Add(1) + go s.eoaWorker() + + return nil +} + +func (s *Scenario) Config() string { + yamlBytes, _ := yaml.Marshal(&s.options) + return string(yamlBytes) +} + +// 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 *txbuilder.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 +} + +func (s *Scenario) Run(ctx context.Context) error { + // This scenario only runs in max-bloating mode + return s.runMaxBloatingMode(ctx) +} + +func (s *Scenario) prepareDelegator(delegatorIndex uint64) (*txbuilder.Wallet, error) { + idxBytes := make([]byte, 8) + binary.BigEndian.PutUint64(idxBytes, delegatorIndex) + childKey := sha256.Sum256(append(common.FromHex(s.walletPool.GetRootWallet().GetAddress().Hex()), idxBytes...)) + return txbuilder.NewWallet(fmt.Sprintf("%x", childKey)) +} + +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.GetRootWallet().GetChainId().Uint64() + + 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.NewInt(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 +} + +func (s *Scenario) runMaxBloatingMode(ctx context.Context) error { + s.logger.Infof("starting max bloating 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 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 ════════════════") + confirmedCount, 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 + } + + // Wait for funding transactions to be confirmed and included in blocks + err = s.waitForFundingConfirmations(ctx, confirmedCount) + if err != nil { + s.logger.Errorf("error waiting for funding confirmations: %v", err) + } + } + + // 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 + } + + // Open semaphore (green light) during analysis phase to allow worker to process EOA queue + s.openWorkerSemaphore() + + 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) + confirmedCount, 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 + } + + // Wait for funding transactions to be confirmed before next bloating phase + if confirmedCount > 0 { + err = s.waitForFundingConfirmations(ctx, confirmedCount) + if err != nil { + s.logger.Errorf("error waiting for funding confirmations: %v", err) + } + } + } +} + +func (s *Scenario) fundMaxBloatingDelegators(ctx context.Context, targetCount int, iteration int, gasLimit uint64) (int64, error) { + // Close semaphore (red light) during funding phase + s.closeWorkerSemaphore() + + client := s.walletPool.GetClient(spamoor.SelectClientByIndex, 0, "") + if client == nil { + return 0, fmt.Errorf("no client available for funding delegators") + } + + // Use root wallet since we set child wallet count to 0 in max-bloating mode + wallet := s.walletPool.GetRootWallet() + + // Get suggested fees for funding transactions + var feeCap *big.Int + var tipCap *big.Int + + if s.options.BaseFee > 0 { + feeCap = new(big.Int).Mul(big.NewInt(int64(s.options.BaseFee)), big.NewInt(GweiPerEth)) + } + if s.options.TipFee > 0 { + tipCap = new(big.Int).Mul(big.NewInt(int64(s.options.TipFee)), big.NewInt(GweiPerEth)) + } + + if feeCap == nil || tipCap == nil { + var err error + feeCap, tipCap, err = client.GetSuggestedFee(s.walletPool.GetContext()) + if err != nil { + return 0, fmt.Errorf("failed to get suggested fees for funding: %w", err) + } + } + + // Minimum gas prices + if feeCap.Cmp(big.NewInt(GweiPerEth)) < 0 { + feeCap = big.NewInt(GweiPerEth) + } + if tipCap.Cmp(big.NewInt(GweiPerEth)) < 0 { + tipCap = big.NewInt(GweiPerEth) + } + + // Fund with 1 wei as requested by user + fundingAmount := uint256.NewInt(1) + + var confirmedCount int64 + sentCount := uint64(0) + delegatorIndex := uint64(iteration * FundingIterationOffset) // Large offset per iteration to avoid conflicts + + // Calculate approximate transactions per block based on gas limit + // Standard transfer = BaseTransferCost gas. + var maxTxsPerBlock = gasLimit / uint64(BaseTransferCost) + + for { + // Check if we have enough confirmed transactions + confirmed := atomic.LoadInt64(&confirmedCount) + if confirmed >= int64(targetCount) { + // We have minimum required, but let's check if we should fill the current block + // If we've sent transactions recently, wait a bit to see if block gets filled + if sentCount > 0 && (sentCount%TransactionBatchSize) > TransactionBatchThreshold { + // Continue to fill the block + } else { + break + } + } + + // Generate unique delegator address + delegator, err := s.prepareDelegator(delegatorIndex) + if err != nil { + s.logger.Errorf("could not prepare delegator %v for funding: %v", delegatorIndex, err) + delegatorIndex++ + continue + } + + // 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) + delegatorIndex++ + continue + } + + tx, err := wallet.BuildDynamicFeeTx(txData) + if err != nil { + s.logger.Errorf("failed to build funding transaction for delegator %d: %v", delegatorIndex, err) + delegatorIndex++ + continue + } + + // Send funding transaction with no retries to avoid duplicates + err = s.walletPool.GetTxPool().SendTransaction(ctx, wallet, tx, &txbuilder.SendTransactionOptions{ + Client: client, + MaxRebroadcasts: 0, // No retries to avoid duplicates + OnConfirm: 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) + + // 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 *txbuilder.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) + } + }, + }) + + if err != nil { + delegatorIndex++ + continue + } + + sentCount++ + delegatorIndex++ + + // Check if we should continue filling the block + confirmed = atomic.LoadInt64(&confirmedCount) + if confirmed >= int64(targetCount) && sentCount%maxTxsPerBlock < TransactionBatchSize { + // We have enough confirmed and we're at the end of a block cycle, stop for now + break + } + + // Small delay between transactions to ensure proper nonce ordering + // Reduce delay as we get more efficient + if sentCount < TransactionBatchSize { + time.Sleep(InitialTransactionDelay) + } else { + time.Sleep(OptimizedTransactionDelay) + } + + // Add context cancellation check + select { + case <-ctx.Done(): + return 0, ctx.Err() + default: + } + } + + // Wait for any remaining transactions to be included + time.Sleep(FundingConfirmationDelay) + + // Return the confirmed count + confirmed := atomic.LoadInt64(&confirmedCount) + return confirmed, nil +} + +// waitForFundingConfirmations waits for funding transactions to be confirmed by monitoring for new blocks +func (s *Scenario) waitForFundingConfirmations(ctx context.Context, targetConfirmations int64) error { + client := s.walletPool.GetClient(spamoor.SelectClientByIndex, 0, "") + if client == nil { + return fmt.Errorf("no client available for monitoring blocks") + } + + s.logger.Infof("Waiting for funding transactions to be confirmed (expecting ~%d confirmations)...", targetConfirmations) + + // Get the starting block number + startBlock, err := client.GetEthClient().BlockNumber(ctx) + if err != nil { + return fmt.Errorf("failed to get starting block number: %w", err) + } + + // Monitor until we see at least 1 new block to ensure funding txs are included + ticker := time.NewTicker(1 * time.Second) + defer ticker.Stop() + + blocksWaited := uint64(0) + for { + select { + case <-ctx.Done(): + return ctx.Err() + case <-ticker.C: + // Check current block number + currentBlock, err := client.GetEthClient().BlockNumber(ctx) + if err != nil { + s.logger.Debugf("Error getting block number: %v", err) + continue + } + + // If we have new blocks + if currentBlock > startBlock { + blocksWaited = currentBlock - startBlock + s.logger.Debugf("New block %d mined (%d blocks since funding started)", currentBlock, blocksWaited) + + // Wait for at least 1 block to ensure funding transactions are included + if blocksWaited >= 1 { + s.logger.Infof("Funding transactions should be confirmed (waited %d blocks)", blocksWaited) + return 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 root wallet since we set child wallet count to 0 in max-bloating mode + wallet := s.walletPool.GetRootWallet() + + // Get suggested fees or use configured values + var feeCap *big.Int + var tipCap *big.Int + + if s.options.BaseFee > 0 { + feeCap = new(big.Int).Mul(big.NewInt(int64(s.options.BaseFee)), big.NewInt(GweiPerEth)) + } + if s.options.TipFee > 0 { + tipCap = new(big.Int).Mul(big.NewInt(int64(s.options.TipFee)), big.NewInt(GweiPerEth)) + } + + if feeCap == nil || tipCap == nil { + var err error + feeCap, tipCap, err = client.GetSuggestedFee(s.walletPool.GetContext()) + if err != nil { + return 0, "", 0, 0, 0, "", fmt.Errorf("failed to get suggested fees: %w", err) + } + } + + // Ensure minimum gas prices for inclusion + if feeCap.Cmp(big.NewInt(GweiPerEth)) < 0 { + feeCap = big.NewInt(GweiPerEth) + } + if tipCap.Cmp(big.NewInt(GweiPerEth)) < 0 { + tipCap = big.NewInt(GweiPerEth) + } + + // 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) + } +} + +// 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 *txbuilder.Wallet, client *txbuilder.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) + + // Use channels to capture transaction results + resultChan := make(chan struct { + gasUsed uint64 + blockNumber string + authCount int + gasPerAuth float64 + gasPerByte float64 + gweiTotalFee string + err error + }, 1) + + // Send the transaction + err = s.walletPool.GetTxPool().SendTransaction(ctx, wallet, tx, &txbuilder.SendTransactionOptions{ + Client: client, + MaxRebroadcasts: 10, + RebroadcastInterval: 120 * time.Second, // Default rebroadcast interval + OnConfirm: func(tx *types.Transaction, receipt *types.Receipt, err error) { + if err != nil { + s.logger.WithField("rpc", client.GetName()).Errorf("max bloating tx failed: %v", err) + resultChan <- struct { + gasUsed uint64 + blockNumber string + authCount int + gasPerAuth float64 + gasPerByte float64 + gweiTotalFee string + err error + }{0, "", 0, 0, 0, "", err} + return + } + if receipt == nil { + resultChan <- struct { + gasUsed uint64 + blockNumber string + authCount int + gasPerAuth float64 + gasPerByte float64 + gweiTotalFee string + err error + }{0, "", 0, 0, 0, "", fmt.Errorf("no receipt received")} + return + } + + effectiveGasPrice := receipt.EffectiveGasPrice + if effectiveGasPrice == nil { + effectiveGasPrice = big.NewInt(0) + } + feeAmount := new(big.Int).Mul(effectiveGasPrice, big.NewInt(int64(receipt.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(receipt.GasUsed) / float64(authCount) + gasPerByte := gasPerAuth / EstimatedBytesPerAuth + + resultChan <- struct { + gasUsed uint64 + blockNumber string + authCount int + gasPerAuth float64 + gasPerByte float64 + gweiTotalFee string + err error + }{receipt.GasUsed, receipt.BlockNumber.String(), + authCount, + gasPerAuth, + gasPerByte, + gweiTotalFee.String(), nil} + }, + LogFn: func(client *txbuilder.Client, retry int, rebroadcast int, err error) { + logger := s.logger.WithField("rpc", client.GetName()) + if retry > 0 { + logger = logger.WithField("retry", retry) + } + if rebroadcast > 0 { + logger = logger.WithField("rebroadcast", rebroadcast) + } + if err != nil { + logger.Errorf("failed sending max bloating tx: %v", err) + } else if retry > 0 || rebroadcast > 0 { + logger.Infof("successfully sent max bloating tx") + } + }, + }) + + if err != nil { + wallet.ResetPendingNonce(ctx, client) + return 0, "", 0, 0, 0, "", fmt.Errorf("failed to send max bloating transaction: %w", err) + } + + // Wait for transaction confirmation + result := <-resultChan + return result.gasUsed, result.blockNumber, result.authCount, result.gasPerAuth, result.gasPerByte, result.gweiTotalFee, result.err +} + +// 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 *txbuilder.Wallet, client *txbuilder.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 + resultChans := make([]chan struct { + gasUsed uint64 + blockNumber string + authCount int + gweiTotalFee string + err error + }, len(batches)) + + // Send all batches quickly with minimal delay to increase chance of same block inclusion + for batchIndex, batch := range batches { + // Create result channel for this batch + resultChans[batchIndex] = make(chan struct { + gasUsed uint64 + blockNumber string + authCount int + gweiTotalFee string + err error + }, 1) + + // 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 0, "", 0, 0, 0, "", fmt.Errorf("failed to build batch %d transaction metadata: %w", batchIndex+1, err) + } + + tx, err := wallet.BuildSetCodeTx(txData) + if err != nil { + return 0, "", 0, 0, 0, "", fmt.Errorf("failed to build batch %d transaction: %w", batchIndex+1, err) + } + + // Send the transaction immediately without waiting for confirmation + resultChan := resultChans[batchIndex] + err = s.walletPool.GetTxPool().SendTransaction(ctx, wallet, tx, &txbuilder.SendTransactionOptions{ + Client: client, + MaxRebroadcasts: MaxRebroadcasts, + RebroadcastInterval: 120 * time.Second, // Default rebroadcast interval + OnConfirm: func(tx *types.Transaction, receipt *types.Receipt, err error) { + if err != nil { + s.logger.WithField("rpc", client.GetName()).Errorf("batch %d tx failed: %v", batchIndex+1, err) + resultChan <- struct { + gasUsed uint64 + blockNumber string + authCount int + gweiTotalFee string + err error + }{0, "", 0, "", err} + return + } + if receipt == nil { + resultChan <- struct { + gasUsed uint64 + blockNumber string + authCount int + gweiTotalFee string + err error + }{0, "", 0, "", fmt.Errorf("batch %d: no receipt received", batchIndex+1)} + return + } + + effectiveGasPrice := receipt.EffectiveGasPrice + if effectiveGasPrice == nil { + effectiveGasPrice = big.NewInt(0) + } + feeAmount := new(big.Int).Mul(effectiveGasPrice, big.NewInt(int64(receipt.GasUsed))) + totalAmount := new(big.Int).Add(tx.Value(), feeAmount) + wallet.SubBalance(totalAmount) + + gweiTotalFee := new(big.Int).Div(feeAmount, big.NewInt(GweiPerEth)) + + resultChan <- struct { + gasUsed uint64 + blockNumber string + authCount int + gweiTotalFee string + err error + }{receipt.GasUsed, receipt.BlockNumber.String(), len(batch), gweiTotalFee.String(), nil} + }, + LogFn: func(client *txbuilder.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 0, "", 0, 0, 0, "", fmt.Errorf("failed to send batch %d transaction: %w", batchIndex+1, err) + } + + // No delay between batches - send as fast as possible to ensure same block inclusion + } + + // Now wait for all batch confirmations + 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 { + result := <-resultChans[batchIndex] + if result.err != nil { + return 0, "", 0, 0, 0, "", fmt.Errorf("batch %d failed: %w", batchIndex+1, result.err) + } + + // Aggregate successful results + totalGasUsed += result.gasUsed + totalAuthCount += result.authCount + lastBlockNumber = result.blockNumber + + // Track block numbers + blockNumbers[result.blockNumber]++ + + // Parse and add fee + if feeGwei, ok := new(big.Int).SetString(result.gweiTotalFee, 10); ok { + totalFees.Add(totalFees, feeGwei) + } + + // Store batch details + batchGasInM := float64(result.gasUsed) / GasPerMillion + gasPerAuthBatch := float64(result.gasUsed) / float64(result.authCount) + 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, result.authCount, sizeKiB, gasPerAuthBatch, gasPerByteBatch, result.blockNumber) + } + + // 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 +// when the semaphore is open (green). It sleeps when the semaphore is closed (red). +func (s *Scenario) eoaWorker() { + defer s.workerWg.Done() + + for { + select { + case <-s.workerDone: + // Shutdown signal received + return + case <-s.workerSemaphore: + // Semaphore is green, process the queue + s.processEOAQueue() + } + } +} + +// processEOAQueue drains the EOA queue and writes entries to EOAs.json +func (s *Scenario) processEOAQueue() { + for { + // 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() + + // 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) +} + +// openWorkerSemaphore opens the semaphore (green light) allowing the worker to process +func (s *Scenario) openWorkerSemaphore() { + select { + case s.workerSemaphore <- struct{}{}: + // Semaphore opened successfully + default: + // Semaphore already open, do nothing + } +} + +// closeWorkerSemaphore closes the semaphore (red light) putting the worker to sleep +func (s *Scenario) closeWorkerSemaphore() { + select { + case <-s.workerSemaphore: + // Semaphore closed successfully + default: + // Semaphore already closed, do nothing + } +} + +// shutdownWorker signals the worker to stop and waits for it to finish +func (s *Scenario) shutdownWorker() { + close(s.workerDone) + s.workerWg.Wait() +} + +// 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 +} + +// 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 +} 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..51c000d0 --- /dev/null +++ b/scenarios/statebloat/erc20_max_transfers/erc20_max_transfers.go @@ -0,0 +1,829 @@ +package erc20maxtransfers + +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" + + contract "github.com/ethpandaops/spamoor/scenarios/statebloat/contract_deploy/contract" + "github.com/ethpandaops/spamoor/scenariotypes" + "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"` +} + +// 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 *txbuilder.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 = "erc20-max-transfers" +var ScenarioDefaultOptions = ScenarioOptions{ + BaseFee: DefaultBaseFeeGwei, + TipFee: DefaultTipFeeGwei, + Contract: "", +} +var ScenarioDescriptor = scenariotypes.ScenarioDescriptor{ + Name: ScenarioName, + Description: "Maximum ERC20 transfers per block to unique addresses", + DefaultOptions: ScenarioDefaultOptions, + NewScenario: newScenario, +} + +func newScenario(logger logrus.FieldLogger) scenariotypes.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)") + return nil +} + +func (s *Scenario) Init(walletPool *spamoor.WalletPool, config string) error { + s.walletPool = walletPool + + if config != "" { + err := yaml.Unmarshal([]byte(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 { + data, err := os.ReadFile("deployments.json") + if err != nil { + return fmt.Errorf("failed to read deployments.json: %w", 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 + if strings.HasPrefix(privateKey, "0x") { + privateKey = privateKey[2:] + } + 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.ContractMetaData.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 *txbuilder.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 := txbuilder.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 *txbuilder.Wallet, targetTransfers int, targetGasLimit uint64, blockCounter int, client *txbuilder.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 + var feeCap *big.Int + var tipCap *big.Int + + if s.options.BaseFee > 0 { + feeCap = new(big.Int).Mul(big.NewInt(int64(s.options.BaseFee)), big.NewInt(GweiPerEth)) + } + if s.options.TipFee > 0 { + tipCap = new(big.Int).Mul(big.NewInt(int64(s.options.TipFee)), big.NewInt(GweiPerEth)) + } + + if feeCap == nil || tipCap == nil { + var err error + feeCap, tipCap, err = client.GetSuggestedFee(s.walletPool.GetContext()) + if err != nil { + return 0, "", 0, 0, 0, fmt.Errorf("failed to get suggested fees: %w", err) + } + } + + // Ensure minimum gas prices for inclusion + minFeeCap := new(big.Int).Mul(big.NewInt(int64(s.options.BaseFee)), big.NewInt(GweiPerEth)) + minTipCap := new(big.Int).Mul(big.NewInt(int64(s.options.TipFee)), big.NewInt(GweiPerEth)) + + if feeCap.Cmp(minFeeCap) < 0 { + feeCap = minFeeCap + } + if tipCap.Cmp(minTipCap) < 0 { + tipCap = minTipCap + } + + // Send transfers in batches + return s.sendTransferBatch(ctx, deployerWallet, targetTransfers, targetGasLimit, blockCounter, client, feeCap, tipCap) +} + +func (s *Scenario) sendTransferBatch(ctx context.Context, wallet *txbuilder.Wallet, targetTransfers int, targetGasLimit uint64, iteration int, client *txbuilder.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, &txbuilder.SendTransactionOptions{ + Client: client, + MaxRebroadcasts: 0, // No retries to avoid duplicates + OnConfirm: 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 *txbuilder.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_bloater/README.md b/scenarios/statebloat/rand_sstore_bloater/README.md new file mode 100644 index 00000000..f7a9c6b6 --- /dev/null +++ b/scenarios/statebloat/rand_sstore_bloater/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_bloater/contract/SSTOREStorageBloater.go b/scenarios/statebloat/rand_sstore_bloater/contract/SSTOREStorageBloater.go new file mode 100644 index 00000000..b99fb9f5 --- /dev/null +++ b/scenarios/statebloat/rand_sstore_bloater/contract/SSTOREStorageBloater.go @@ -0,0 +1,225 @@ +// 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 +) + +// ContractMetaData contains all meta data concerning the Contract contract. +var ContractMetaData = &bind.MetaData{ + ABI: "[{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"count\",\"type\":\"uint256\"}],\"name\":\"createSlots\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]", + Bin: "0x6080604052348015600e575f5ffd5b5060b780601a5f395ff3fe6080604052348015600e575f5ffd5b50600436106026575f3560e01c8063e3b393a414602a575b5f5ffd5b60396035366004606b565b603b565b005b6013600160ff1b0381600143034042185f5b828110156064575f1984838301098055600101604d565b5050505050565b5f60208284031215607a575f5ffd5b503591905056fea26469706673582212204ef28faab84898d88945da94b05dca578974093de11f6a0be4b796396638d88264736f6c634300081e0033", +} + +// ContractABI is the input ABI used to generate the binding from. +// Deprecated: Use ContractMetaData.ABI instead. +var ContractABI = ContractMetaData.ABI + +// ContractBin is the compiled bytecode used for deploying new contracts. +// Deprecated: Use ContractMetaData.Bin instead. +var ContractBin = ContractMetaData.Bin + +// DeployContract deploys a new Ethereum contract, binding an instance of Contract to it. +func DeployContract(auth *bind.TransactOpts, backend bind.ContractBackend) (common.Address, *types.Transaction, *Contract, error) { + parsed, err := ContractMetaData.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(ContractBin), backend) + if err != nil { + return common.Address{}, nil, nil, err + } + return address, tx, &Contract{ContractCaller: ContractCaller{contract: contract}, ContractTransactor: ContractTransactor{contract: contract}, ContractFilterer: ContractFilterer{contract: contract}}, nil +} + +// Contract is an auto generated Go binding around an Ethereum contract. +type Contract struct { + ContractCaller // Read-only binding to the contract + ContractTransactor // Write-only binding to the contract + ContractFilterer // Log filterer for contract events +} + +// ContractCaller is an auto generated read-only Go binding around an Ethereum contract. +type ContractCaller struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// ContractTransactor is an auto generated write-only Go binding around an Ethereum contract. +type ContractTransactor struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// ContractFilterer is an auto generated log filtering Go binding around an Ethereum contract events. +type ContractFilterer struct { + contract *bind.BoundContract // Generic contract wrapper for the low level calls +} + +// ContractSession is an auto generated Go binding around an Ethereum contract, +// with pre-set call and transact options. +type ContractSession struct { + Contract *Contract // 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 +} + +// ContractCallerSession is an auto generated read-only Go binding around an Ethereum contract, +// with pre-set call options. +type ContractCallerSession struct { + Contract *ContractCaller // Generic contract caller binding to set the session for + CallOpts bind.CallOpts // Call options to use throughout this session +} + +// ContractTransactorSession is an auto generated write-only Go binding around an Ethereum contract, +// with pre-set transact options. +type ContractTransactorSession struct { + Contract *ContractTransactor // Generic contract transactor binding to set the session for + TransactOpts bind.TransactOpts // Transaction auth options to use throughout this session +} + +// ContractRaw is an auto generated low-level Go binding around an Ethereum contract. +type ContractRaw struct { + Contract *Contract // Generic contract binding to access the raw methods on +} + +// ContractCallerRaw is an auto generated low-level read-only Go binding around an Ethereum contract. +type ContractCallerRaw struct { + Contract *ContractCaller // Generic read-only contract binding to access the raw methods on +} + +// ContractTransactorRaw is an auto generated low-level write-only Go binding around an Ethereum contract. +type ContractTransactorRaw struct { + Contract *ContractTransactor // Generic write-only contract binding to access the raw methods on +} + +// NewContract creates a new instance of Contract, bound to a specific deployed contract. +func NewContract(address common.Address, backend bind.ContractBackend) (*Contract, error) { + contract, err := bindContract(address, backend, backend, backend) + if err != nil { + return nil, err + } + return &Contract{ContractCaller: ContractCaller{contract: contract}, ContractTransactor: ContractTransactor{contract: contract}, ContractFilterer: ContractFilterer{contract: contract}}, nil +} + +// NewContractCaller creates a new read-only instance of Contract, bound to a specific deployed contract. +func NewContractCaller(address common.Address, caller bind.ContractCaller) (*ContractCaller, error) { + contract, err := bindContract(address, caller, nil, nil) + if err != nil { + return nil, err + } + return &ContractCaller{contract: contract}, nil +} + +// NewContractTransactor creates a new write-only instance of Contract, bound to a specific deployed contract. +func NewContractTransactor(address common.Address, transactor bind.ContractTransactor) (*ContractTransactor, error) { + contract, err := bindContract(address, nil, transactor, nil) + if err != nil { + return nil, err + } + return &ContractTransactor{contract: contract}, nil +} + +// NewContractFilterer creates a new log filterer instance of Contract, bound to a specific deployed contract. +func NewContractFilterer(address common.Address, filterer bind.ContractFilterer) (*ContractFilterer, error) { + contract, err := bindContract(address, nil, nil, filterer) + if err != nil { + return nil, err + } + return &ContractFilterer{contract: contract}, nil +} + +// bindContract binds a generic wrapper to an already deployed contract. +func bindContract(address common.Address, caller bind.ContractCaller, transactor bind.ContractTransactor, filterer bind.ContractFilterer) (*bind.BoundContract, error) { + parsed, err := ContractMetaData.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 (_Contract *ContractRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Contract.Contract.ContractCaller.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 (_Contract *ContractRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Contract.Contract.ContractTransactor.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Contract *ContractRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Contract.Contract.ContractTransactor.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 (_Contract *ContractCallerRaw) Call(opts *bind.CallOpts, result *[]interface{}, method string, params ...interface{}) error { + return _Contract.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 (_Contract *ContractTransactorRaw) Transfer(opts *bind.TransactOpts) (*types.Transaction, error) { + return _Contract.Contract.contract.Transfer(opts) +} + +// Transact invokes the (paid) contract method with params as input values. +func (_Contract *ContractTransactorRaw) Transact(opts *bind.TransactOpts, method string, params ...interface{}) (*types.Transaction, error) { + return _Contract.Contract.contract.Transact(opts, method, params...) +} + +// CreateSlots is a paid mutator transaction binding the contract method 0xe3b393a4. +// +// Solidity: function createSlots(uint256 count) returns() +func (_Contract *ContractTransactor) CreateSlots(opts *bind.TransactOpts, count *big.Int) (*types.Transaction, error) { + return _Contract.contract.Transact(opts, "createSlots", count) +} + +// CreateSlots is a paid mutator transaction binding the contract method 0xe3b393a4. +// +// Solidity: function createSlots(uint256 count) returns() +func (_Contract *ContractSession) CreateSlots(count *big.Int) (*types.Transaction, error) { + return _Contract.Contract.CreateSlots(&_Contract.TransactOpts, count) +} + +// CreateSlots is a paid mutator transaction binding the contract method 0xe3b393a4. +// +// Solidity: function createSlots(uint256 count) returns() +func (_Contract *ContractTransactorSession) CreateSlots(count *big.Int) (*types.Transaction, error) { + return _Contract.Contract.CreateSlots(&_Contract.TransactOpts, count) +} + diff --git a/scenarios/statebloat/rand_sstore_bloater/contract/SSTOREStorageBloater.sol b/scenarios/statebloat/rand_sstore_bloater/contract/SSTOREStorageBloater.sol new file mode 100644 index 00000000..6a48bf81 --- /dev/null +++ b/scenarios/statebloat/rand_sstore_bloater/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_bloater/rand_sstore_bloater.go b/scenarios/statebloat/rand_sstore_bloater/rand_sstore_bloater.go new file mode 100644 index 00000000..e7708ccc --- /dev/null +++ b/scenarios/statebloat/rand_sstore_bloater/rand_sstore_bloater.go @@ -0,0 +1,441 @@ +package randsstorebloater + +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/sirupsen/logrus" + "github.com/spf13/pflag" + "gopkg.in/yaml.v3" + + "github.com/ethpandaops/spamoor/scenarios/statebloat/rand_sstore_bloater/contract" + "github.com/ethpandaops/spamoor/scenariotypes" + "github.com/ethpandaops/spamoor/spamoor" +) + +//go:embed contract/SSTOREStorageBloater.abi +var contractABIBytes []byte + +//go:embed contract/SSTOREStorageBloater.bin +var contractBytecodeHex []byte + +// 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) + + // Deployment tracking file + DeploymentFileName = "deployments_sstore_bloating.json" +) + +// 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"` +} + +type Scenario struct { + options ScenarioOptions + logger *logrus.Entry + walletPool *spamoor.WalletPool + + // Contract state + contractAddress common.Address + contractABI abi.ABI + contractInstance *contract.Contract // Generated contract binding + isDeployed bool + deployMutex sync.Mutex + + // Scenario state + totalSlots uint64 // Total number of slots created + cycleCount uint64 // Number of complete create/update cycles + 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 + + // Cached values + chainID *big.Int + chainIDOnce sync.Once + chainIDError error +} + +var ScenarioName = "rand_sstore_bloater" +var ScenarioDefaultOptions = ScenarioOptions{ + BaseFee: 10, // 10 gwei default + TipFee: 2, // 2 gwei default +} +var ScenarioDescriptor = scenariotypes.ScenarioDescriptor{ + Name: ScenarioName, + Description: "Maximum state bloat via SSTORE operations using curve25519 prime dispersion", + DefaultOptions: ScenarioDefaultOptions, + NewScenario: newScenario, +} + +func newScenario(logger logrus.FieldLogger) scenariotypes.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") + return nil +} + +func (s *Scenario) Init(walletPool *spamoor.WalletPool, config string) error { + s.walletPool = walletPool + + if config != "" { + err := yaml.Unmarshal([]byte(config), &s.options) + if err != nil { + return fmt.Errorf("failed to unmarshal config: %w", err) + } + } + + // Use only root wallet for simplicity + s.walletPool.SetWalletCount(1) + + // Parse contract ABI + parsedABI, err := abi.JSON(strings.NewReader(string(contractABIBytes))) + 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 loadDeploymentFile() (DeploymentFile, error) { + data, err := os.ReadFile(DeploymentFileName) + 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 saveDeploymentFile(deployments DeploymentFile) error { + data, err := json.MarshalIndent(deployments, "", " ") + if err != nil { + return fmt.Errorf("failed to marshal deployment file: %w", err) + } + + if err := os.WriteFile(DeploymentFileName, data, 0644); err != nil { + return fmt.Errorf("failed to write deployment file: %w", err) + } + + return nil +} + +func (s *Scenario) getChainID(ctx context.Context) (*big.Int, error) { + s.chainIDOnce.Do(func() { + client := s.walletPool.GetClient(spamoor.SelectClientByIndex, 0, "") + if client == nil { + s.chainIDError = fmt.Errorf("no client available for chain ID") + return + } + s.chainID, s.chainIDError = client.GetChainId(ctx) + }) + return s.chainID, s.chainIDError +} + +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.GetRootWallet() + if wallet == nil { + return fmt.Errorf("no wallet available") + } + + chainID, err := s.getChainID(ctx) + if err != nil { + return err + } + + auth, err := bind.NewKeyedTransactorWithChainID(wallet.GetPrivateKey(), chainID) + if err != nil { + return fmt.Errorf("failed to create transactor: %w", err) + } + + // Set gas parameters + auth.GasLimit = EstimatedDeployGas + auth.GasFeeCap = new(big.Int).Mul(big.NewInt(int64(s.options.BaseFee)), big.NewInt(1000000000)) + auth.GasTipCap = new(big.Int).Mul(big.NewInt(int64(s.options.TipFee)), big.NewInt(1000000000)) + + // Deploy contract using generated bindings + address, tx, contractInstance, err := contract.DeployContract(auth, client.GetEthClient()) + if err != nil { + return fmt.Errorf("failed to deploy contract: %w", err) + } + + s.logger.WithField("tx", tx.Hash().Hex()).Info("Contract deployment transaction sent") + + // Wait for deployment + receipt, err := bind.WaitMined(ctx, client.GetEthClient(), tx) + if err != nil { + return fmt.Errorf("failed to wait for deployment: %w", err) + } + + if receipt.Status != 1 { + return fmt.Errorf("contract deployment failed") + } + + s.contractAddress = address + s.contractInstance = contractInstance + s.isDeployed = true + + // No need to reset nonce - the wallet manager handles it automatically + + // Track deployment in JSON file + deployments, err := loadDeploymentFile() + if err != nil { + s.logger.Warnf("failed to load deployment file: %v", err) + deployments = make(DeploymentFile) + } + + // Initialize deployment data for this contract + deployments[address.Hex()] = &DeploymentData{ + StorageRounds: []BlockInfo{}, + } + + if err := saveDeploymentFile(deployments); err != nil { + s.logger.Warnf("failed to save deployment file: %v", err) + } + + s.logger.WithField("address", address.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: + } + + // Get current block gas limit + latestBlock, err := client.GetEthClient().BlockByNumber(ctx, nil) + if err != nil { + s.logger.Warnf("failed to get latest block: %v", err) + time.Sleep(5 * time.Second) + continue + } + + blockGasLimit := latestBlock.GasLimit() + 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.GetRootWallet() + if wallet == nil { + return fmt.Errorf("no wallet available") + } + + // Create transaction options + chainID, err := s.getChainID(ctx) + if err != nil { + return err + } + + auth, err := bind.NewKeyedTransactorWithChainID(wallet.GetPrivateKey(), chainID) + if err != nil { + return fmt.Errorf("failed to create transactor: %w", err) + } + + // Set gas parameters + auth.GasLimit = targetGas + auth.GasFeeCap = new(big.Int).Mul(big.NewInt(int64(s.options.BaseFee)), big.NewInt(1000000000)) + auth.GasTipCap = new(big.Int).Mul(big.NewInt(int64(s.options.TipFee)), big.NewInt(1000000000)) + + // Execute transaction using contract bindings + tx, err := s.contractInstance.CreateSlots(auth, big.NewInt(int64(slotsToCreate))) + if err != nil { + // Check if it's an out-of-gas error + if strings.Contains(err.Error(), "out of gas") || strings.Contains(err.Error(), "OutOfGas") { + // Increase our gas estimate by 10% + s.actualGasPerNewSlotIteration = uint64(float64(s.actualGasPerNewSlotIteration) * 1.1) + s.logger.Warnf("Out of gas error detected. Adjusting gas per slot estimate to %d", s.actualGasPerNewSlotIteration) + } + return err + } + + // Wait for transaction confirmation + receipt, err := bind.WaitMined(ctx, client.GetEthClient(), tx) + if err != nil { + return fmt.Errorf("failed to wait for transaction: %w", err) + } + + if receipt.Status != 1 { + return fmt.Errorf("transaction failed") + } + + // Mark this slot count as successful + s.successfulSlotCounts[slotsToCreate] = true + + // Update metrics and adaptive gas tracking + s.totalSlots += slotsToCreate + totalOverhead := BaseTxCost + FunctionCallOverhead + actualGasPerSlotIteration := (receipt.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 := receipt.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 := 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 := 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(receipt.GasUsed) / float64(blockGasLimit) * 100 + + s.logger.WithFields(logrus.Fields{ + "block_number": receipt.BlockNumber, + "gas_used": receipt.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 +}