From 03f5b7e4b36584466f4404f0c798755d15bc3d37 Mon Sep 17 00:00:00 2001 From: CPerezz Date: Wed, 7 May 2025 16:45:09 +0200 Subject: [PATCH 01/26] add: README for statebloat scenarios Includes the scenarios contemplated within statebloat as well as any extra data about them such as gas cost metrics. --- scenarios/statebloat/README.md | 35 ++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 scenarios/statebloat/README.md 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 From b50c7850a2dcdd5b4a1d3d6dca21c3af64a2c5f9 Mon Sep 17 00:00:00 2001 From: CPerezz Date: Wed, 7 May 2025 16:46:09 +0200 Subject: [PATCH 02/26] add: Add first iteration over contract-deploy This scenario deploys contracts that are exactly 24kB in size (EIP-170 limit) to maximize state growth while minimizing gas cost. 1. Generates a contract with exactly 24,576 bytes of runtime code 2. Deploys the contract using CREATE 3. Each deployment adds: - 24,576 bytes of runtime code - Account trie node - Total state growth: ~24.7kB per deployment - 32,000 gas for CREATE - 20,000 gas for new account - 200 gas per byte for code deposit (24,576 bytes) - Total: 4,967,200 gas per deployment --- .../statebloat/contract-deploy/README.md | 80 ++ .../contract-deploy/contract/README.md | 35 + .../contract/StateBloatToken.abi | 1 + .../contract/StateBloatToken.bin | 1 + .../contract/StateBloatToken.go | 791 ++++++++++++++++++ .../contract/StateBloatToken.sol | 61 ++ .../contract-deploy/contract_deploy.go | 305 +++++++ 7 files changed, 1274 insertions(+) create mode 100644 scenarios/statebloat/contract-deploy/README.md create mode 100644 scenarios/statebloat/contract-deploy/contract/README.md create mode 100644 scenarios/statebloat/contract-deploy/contract/StateBloatToken.abi create mode 100644 scenarios/statebloat/contract-deploy/contract/StateBloatToken.bin create mode 100644 scenarios/statebloat/contract-deploy/contract/StateBloatToken.go create mode 100644 scenarios/statebloat/contract-deploy/contract/StateBloatToken.sol create mode 100644 scenarios/statebloat/contract-deploy/contract_deploy.go diff --git a/scenarios/statebloat/contract-deploy/README.md b/scenarios/statebloat/contract-deploy/README.md new file mode 100644 index 00000000..ecd830a7 --- /dev/null +++ b/scenarios/statebloat/contract-deploy/README.md @@ -0,0 +1,80 @@ +# 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 +3. 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 + +## Usage + +```bash +spamoor statebloat/contract-deploy [flags] +``` + +### Configuration + +#### Base Settings (required) +- `--privkey` - Private key of the sending wallet +- `--rpchost` - RPC endpoint(s) to send transactions to + +#### Volume Control (either -c or -t required) +- `-c, --count` - Total number of contracts to deploy +- `-t, --throughput` - Contracts to deploy per slot +- `--max-pending` - Maximum number of pending deployments + +#### Transaction Settings +- `--basefee` - Max fee per gas in gwei (default: 20) +- `--tipfee` - Max tip per gas in gwei (default: 2) +- `--rebroadcast` - Seconds to wait before rebroadcasting (default: 120) + +#### Wallet Management +- `--max-wallets` - Maximum number of child wallets to use +- `--refill-amount` - ETH amount to fund each child wallet (default: 5) +- `--refill-balance` - Minimum ETH balance before refilling (default: 2) +- `--refill-interval` - Seconds between balance checks (default: 300) + +## Example + +Deploy 10 contracts: +```bash +spamoor statebloat/contract-deploy -p "" -h http://localhost:8545 -c 10 +``` + +Deploy 1 contract per slot: +```bash +spamoor statebloat/contract-deploy -p "" -h http://localhost:8545 -t 1 +``` + +## Testing with Anvil + +1. Start Anvil: +```bash +anvil +``` + +2. Run the scenario: +```bash +spamoor statebloat/contract-deploy -p "" -h http://localhost:8545 -c 1 +``` + +3. Verify state growth: +```bash +# Get the contract address from the deployment receipt +# Then check the code size +cast code --rpc-url http://localhost:8545 +``` + +The code size should be exactly 24,576 bytes. \ 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..fb9e7b53 --- /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":"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"}] \ 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..0ea68c09 --- /dev/null +++ b/scenarios/statebloat/contract-deploy/contract/StateBloatToken.bin @@ -0,0 +1 @@ +60a060405234801561000f575f5ffd5b50604051611503380380611503833981810160405281019061003191906101f4565b6040518060400160405280601181526020017f537461746520426c6f617420546f6b656e0000000000000000000000000000008152505f90816100749190610453565b506040518060400160405280600381526020017f5342540000000000000000000000000000000000000000000000000000000000815250600190816100b99190610453565b50601260025f6101000a81548160ff021916908360ff160217905550806080818152505060025f9054906101000a900460ff16600a6100f8919061068a565b620f424061010691906106d4565b60038190555060035460045f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055503373ffffffffffffffffffffffffffffffffffffffff165f73ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef6003546040516101af9190610724565b60405180910390a35061073d565b5f5ffd5b5f819050919050565b6101d3816101c1565b81146101dd575f5ffd5b50565b5f815190506101ee816101ca565b92915050565b5f60208284031215610209576102086101bd565b5b5f610216848285016101e0565b91505092915050565b5f81519050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f600282049050600182168061029a57607f821691505b6020821081036102ad576102ac610256565b5b50919050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f6008830261030f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff826102d4565b61031986836102d4565b95508019841693508086168417925050509392505050565b5f819050919050565b5f61035461034f61034a846101c1565b610331565b6101c1565b9050919050565b5f819050919050565b61036d8361033a565b6103816103798261035b565b8484546102e0565b825550505050565b5f5f905090565b610398610389565b6103a3818484610364565b505050565b5b818110156103c6576103bb5f82610390565b6001810190506103a9565b5050565b601f82111561040b576103dc816102b3565b6103e5846102c5565b810160208510156103f4578190505b610408610400856102c5565b8301826103a8565b50505b505050565b5f82821c905092915050565b5f61042b5f1984600802610410565b1980831691505092915050565b5f610443838361041c565b9150826002028217905092915050565b61045c8261021f565b67ffffffffffffffff81111561047557610474610229565b5b61047f8254610283565b61048a8282856103ca565b5f60209050601f8311600181146104bb575f84156104a9578287015190505b6104b38582610438565b86555061051a565b601f1984166104c9866102b3565b5f5b828110156104f0578489015182556001820191506020850194506020810190506104cb565b8683101561050d5784890151610509601f89168261041c565b8355505b6001600288020188555050505b505050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f8160011c9050919050565b5f5f8291508390505b60018511156105a4578086048111156105805761057f610522565b5b600185161561058f5780820291505b808102905061059d8561054f565b9450610564565b94509492505050565b5f826105bc5760019050610677565b816105c9575f9050610677565b81600181146105df57600281146105e957610618565b6001915050610677565b60ff8411156105fb576105fa610522565b5b8360020a91508482111561061257610611610522565b5b50610677565b5060208310610133831016604e8410600b841016171561064d5782820a90508381111561064857610647610522565b5b610677565b61065a848484600161055b565b9250905081840481111561067157610670610522565b5b81810290505b9392505050565b5f60ff82169050919050565b5f610694826101c1565b915061069f8361067e565b92506106cc7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff84846105ad565b905092915050565b5f6106de826101c1565b91506106e9836101c1565b92508282026106f7816101c1565b9150828204841483151761070e5761070d610522565b5b5092915050565b61071e816101c1565b82525050565b5f6020820190506107375f830184610715565b92915050565b608051610dae6107555f395f6108cf0152610dae5ff3fe608060405234801561000f575f5ffd5b506004361061009c575f3560e01c806370a082311161006457806370a082311461015a57806395d89b411461018a578063a9059cbb146101a8578063bfa0b133146101d8578063dd62ed3e146101f65761009c565b806306fdde03146100a0578063095ea7b3146100be57806318160ddd146100ee57806323b872dd1461010c578063313ce5671461013c575b5f5ffd5b6100a8610226565b6040516100b59190610981565b60405180910390f35b6100d860048036038101906100d39190610a32565b6102b1565b6040516100e59190610a8a565b60405180910390f35b6100f661039e565b6040516101039190610ab2565b60405180910390f35b61012660048036038101906101219190610acb565b6103a4565b6040516101339190610a8a565b60405180910390f35b610144610684565b6040516101519190610b36565b60405180910390f35b610174600480360381019061016f9190610b4f565b610696565b6040516101819190610ab2565b60405180910390f35b6101926106ab565b60405161019f9190610981565b60405180910390f35b6101c260048036038101906101bd9190610a32565b610737565b6040516101cf9190610a8a565b60405180910390f35b6101e06108cd565b6040516101ed9190610ab2565b60405180910390f35b610210600480360381019061020b9190610b7a565b6108f1565b60405161021d9190610ab2565b60405180910390f35b5f805461023290610be5565b80601f016020809104026020016040519081016040528092919081815260200182805461025e90610be5565b80156102a95780601f10610280576101008083540402835291602001916102a9565b820191905f5260205f20905b81548152906001019060200180831161028c57829003601f168201915b505050505081565b5f8160055f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9258460405161038c9190610ab2565b60405180910390a36001905092915050565b60035481565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015610425576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161041c90610c5f565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156104e0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104d790610cc7565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461052c9190610d12565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461057f9190610d45565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461060d9190610d12565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516106719190610ab2565b60405180910390a3600190509392505050565b60025f9054906101000a900460ff1681565b6004602052805f5260405f205f915090505481565b600180546106b890610be5565b80601f01602080910402602001604051908101604052809291908181526020018280546106e490610be5565b801561072f5780601f106107065761010080835404028352916020019161072f565b820191905f5260205f20905b81548152906001019060200180831161071257829003601f168201915b505050505081565b5f8160045f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156107b8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107af90610c5f565b60405180910390fd5b8160045f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546108049190610d12565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546108579190610d45565b925050819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516108bb9190610ab2565b60405180910390a36001905092915050565b7f000000000000000000000000000000000000000000000000000000000000000081565b6005602052815f5260405f20602052805f5260405f205f91509150505481565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f61095382610911565b61095d818561091b565b935061096d81856020860161092b565b61097681610939565b840191505092915050565b5f6020820190508181035f8301526109998184610949565b905092915050565b5f5ffd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6109ce826109a5565b9050919050565b6109de816109c4565b81146109e8575f5ffd5b50565b5f813590506109f9816109d5565b92915050565b5f819050919050565b610a11816109ff565b8114610a1b575f5ffd5b50565b5f81359050610a2c81610a08565b92915050565b5f5f60408385031215610a4857610a476109a1565b5b5f610a55858286016109eb565b9250506020610a6685828601610a1e565b9150509250929050565b5f8115159050919050565b610a8481610a70565b82525050565b5f602082019050610a9d5f830184610a7b565b92915050565b610aac816109ff565b82525050565b5f602082019050610ac55f830184610aa3565b92915050565b5f5f5f60608486031215610ae257610ae16109a1565b5b5f610aef868287016109eb565b9350506020610b00868287016109eb565b9250506040610b1186828701610a1e565b9150509250925092565b5f60ff82169050919050565b610b3081610b1b565b82525050565b5f602082019050610b495f830184610b27565b92915050565b5f60208284031215610b6457610b636109a1565b5b5f610b71848285016109eb565b91505092915050565b5f5f60408385031215610b9057610b8f6109a1565b5b5f610b9d858286016109eb565b9250506020610bae858286016109eb565b9150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f6002820490506001821680610bfc57607f821691505b602082108103610c0f57610c0e610bb8565b5b50919050565b7f496e73756666696369656e742062616c616e63650000000000000000000000005f82015250565b5f610c4960148361091b565b9150610c5482610c15565b602082019050919050565b5f6020820190508181035f830152610c7681610c3d565b9050919050565b7f496e73756666696369656e7420616c6c6f77616e6365000000000000000000005f82015250565b5f610cb160168361091b565b9150610cbc82610c7d565b602082019050919050565b5f6020820190508181035f830152610cde81610ca5565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f610d1c826109ff565b9150610d27836109ff565b9250828203905081811115610d3f57610d3e610ce5565b5b92915050565b5f610d4f826109ff565b9150610d5a836109ff565b9250828201905080821115610d7257610d71610ce5565b5b9291505056fea26469706673582212207182ee741671c2a140c5eb4e62cb72b950c446fa68846143d961b62f544f59c764736f6c634300081e0033 \ 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..bfb58592 --- /dev/null +++ b/scenarios/statebloat/contract-deploy/contract/StateBloatToken.go @@ -0,0 +1,791 @@ +// 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\":\"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\"}]", + Bin: "0x60a060405234801561000f575f5ffd5b50604051611503380380611503833981810160405281019061003191906101f4565b6040518060400160405280601181526020017f537461746520426c6f617420546f6b656e0000000000000000000000000000008152505f90816100749190610453565b506040518060400160405280600381526020017f5342540000000000000000000000000000000000000000000000000000000000815250600190816100b99190610453565b50601260025f6101000a81548160ff021916908360ff160217905550806080818152505060025f9054906101000a900460ff16600a6100f8919061068a565b620f424061010691906106d4565b60038190555060035460045f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055503373ffffffffffffffffffffffffffffffffffffffff165f73ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef6003546040516101af9190610724565b60405180910390a35061073d565b5f5ffd5b5f819050919050565b6101d3816101c1565b81146101dd575f5ffd5b50565b5f815190506101ee816101ca565b92915050565b5f60208284031215610209576102086101bd565b5b5f610216848285016101e0565b91505092915050565b5f81519050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f600282049050600182168061029a57607f821691505b6020821081036102ad576102ac610256565b5b50919050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f6008830261030f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff826102d4565b61031986836102d4565b95508019841693508086168417925050509392505050565b5f819050919050565b5f61035461034f61034a846101c1565b610331565b6101c1565b9050919050565b5f819050919050565b61036d8361033a565b6103816103798261035b565b8484546102e0565b825550505050565b5f5f905090565b610398610389565b6103a3818484610364565b505050565b5b818110156103c6576103bb5f82610390565b6001810190506103a9565b5050565b601f82111561040b576103dc816102b3565b6103e5846102c5565b810160208510156103f4578190505b610408610400856102c5565b8301826103a8565b50505b505050565b5f82821c905092915050565b5f61042b5f1984600802610410565b1980831691505092915050565b5f610443838361041c565b9150826002028217905092915050565b61045c8261021f565b67ffffffffffffffff81111561047557610474610229565b5b61047f8254610283565b61048a8282856103ca565b5f60209050601f8311600181146104bb575f84156104a9578287015190505b6104b38582610438565b86555061051a565b601f1984166104c9866102b3565b5f5b828110156104f0578489015182556001820191506020850194506020810190506104cb565b8683101561050d5784890151610509601f89168261041c565b8355505b6001600288020188555050505b505050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f8160011c9050919050565b5f5f8291508390505b60018511156105a4578086048111156105805761057f610522565b5b600185161561058f5780820291505b808102905061059d8561054f565b9450610564565b94509492505050565b5f826105bc5760019050610677565b816105c9575f9050610677565b81600181146105df57600281146105e957610618565b6001915050610677565b60ff8411156105fb576105fa610522565b5b8360020a91508482111561061257610611610522565b5b50610677565b5060208310610133831016604e8410600b841016171561064d5782820a90508381111561064857610647610522565b5b610677565b61065a848484600161055b565b9250905081840481111561067157610670610522565b5b81810290505b9392505050565b5f60ff82169050919050565b5f610694826101c1565b915061069f8361067e565b92506106cc7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff84846105ad565b905092915050565b5f6106de826101c1565b91506106e9836101c1565b92508282026106f7816101c1565b9150828204841483151761070e5761070d610522565b5b5092915050565b61071e816101c1565b82525050565b5f6020820190506107375f830184610715565b92915050565b608051610dae6107555f395f6108cf0152610dae5ff3fe608060405234801561000f575f5ffd5b506004361061009c575f3560e01c806370a082311161006457806370a082311461015a57806395d89b411461018a578063a9059cbb146101a8578063bfa0b133146101d8578063dd62ed3e146101f65761009c565b806306fdde03146100a0578063095ea7b3146100be57806318160ddd146100ee57806323b872dd1461010c578063313ce5671461013c575b5f5ffd5b6100a8610226565b6040516100b59190610981565b60405180910390f35b6100d860048036038101906100d39190610a32565b6102b1565b6040516100e59190610a8a565b60405180910390f35b6100f661039e565b6040516101039190610ab2565b60405180910390f35b61012660048036038101906101219190610acb565b6103a4565b6040516101339190610a8a565b60405180910390f35b610144610684565b6040516101519190610b36565b60405180910390f35b610174600480360381019061016f9190610b4f565b610696565b6040516101819190610ab2565b60405180910390f35b6101926106ab565b60405161019f9190610981565b60405180910390f35b6101c260048036038101906101bd9190610a32565b610737565b6040516101cf9190610a8a565b60405180910390f35b6101e06108cd565b6040516101ed9190610ab2565b60405180910390f35b610210600480360381019061020b9190610b7a565b6108f1565b60405161021d9190610ab2565b60405180910390f35b5f805461023290610be5565b80601f016020809104026020016040519081016040528092919081815260200182805461025e90610be5565b80156102a95780601f10610280576101008083540402835291602001916102a9565b820191905f5260205f20905b81548152906001019060200180831161028c57829003601f168201915b505050505081565b5f8160055f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9258460405161038c9190610ab2565b60405180910390a36001905092915050565b60035481565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015610425576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161041c90610c5f565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156104e0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104d790610cc7565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461052c9190610d12565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461057f9190610d45565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461060d9190610d12565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516106719190610ab2565b60405180910390a3600190509392505050565b60025f9054906101000a900460ff1681565b6004602052805f5260405f205f915090505481565b600180546106b890610be5565b80601f01602080910402602001604051908101604052809291908181526020018280546106e490610be5565b801561072f5780601f106107065761010080835404028352916020019161072f565b820191905f5260205f20905b81548152906001019060200180831161071257829003601f168201915b505050505081565b5f8160045f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156107b8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107af90610c5f565b60405180910390fd5b8160045f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546108049190610d12565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546108579190610d45565b925050819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516108bb9190610ab2565b60405180910390a36001905092915050565b7f000000000000000000000000000000000000000000000000000000000000000081565b6005602052815f5260405f20602052805f5260405f205f91509150505481565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f61095382610911565b61095d818561091b565b935061096d81856020860161092b565b61097681610939565b840191505092915050565b5f6020820190508181035f8301526109998184610949565b905092915050565b5f5ffd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6109ce826109a5565b9050919050565b6109de816109c4565b81146109e8575f5ffd5b50565b5f813590506109f9816109d5565b92915050565b5f819050919050565b610a11816109ff565b8114610a1b575f5ffd5b50565b5f81359050610a2c81610a08565b92915050565b5f5f60408385031215610a4857610a476109a1565b5b5f610a55858286016109eb565b9250506020610a6685828601610a1e565b9150509250929050565b5f8115159050919050565b610a8481610a70565b82525050565b5f602082019050610a9d5f830184610a7b565b92915050565b610aac816109ff565b82525050565b5f602082019050610ac55f830184610aa3565b92915050565b5f5f5f60608486031215610ae257610ae16109a1565b5b5f610aef868287016109eb565b9350506020610b00868287016109eb565b9250506040610b1186828701610a1e565b9150509250925092565b5f60ff82169050919050565b610b3081610b1b565b82525050565b5f602082019050610b495f830184610b27565b92915050565b5f60208284031215610b6457610b636109a1565b5b5f610b71848285016109eb565b91505092915050565b5f5f60408385031215610b9057610b8f6109a1565b5b5f610b9d858286016109eb565b9250506020610bae858286016109eb565b9150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f6002820490506001821680610bfc57607f821691505b602082108103610c0f57610c0e610bb8565b5b50919050565b7f496e73756666696369656e742062616c616e63650000000000000000000000005f82015250565b5f610c4960148361091b565b9150610c5482610c15565b602082019050919050565b5f6020820190508181035f830152610c7681610c3d565b9050919050565b7f496e73756666696369656e7420616c6c6f77616e6365000000000000000000005f82015250565b5f610cb160168361091b565b9150610cbc82610c7d565b602082019050919050565b5f6020820190508181035f830152610cde81610ca5565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f610d1c826109ff565b9150610d27836109ff565b9250828203905081811115610d3f57610d3e610ce5565b5b92915050565b5f610d4f826109ff565b9150610d5a836109ff565b9250828201905080821115610d7257610d71610ce5565b5b9291505056fea26469706673582212207182ee741671c2a140c5eb4e62cb72b950c446fa68846143d961b62f544f59c764736f6c634300081e0033", +} + +// 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) +} + +// 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) +} + +// 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..28dc8454 --- /dev/null +++ b/scenarios/statebloat/contract-deploy/contract/StateBloatToken.sol @@ -0,0 +1,61 @@ +// 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; + + 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; + + // Initialize with some state + 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; + } +} diff --git a/scenarios/statebloat/contract-deploy/contract_deploy.go b/scenarios/statebloat/contract-deploy/contract_deploy.go new file mode 100644 index 00000000..650d7cab --- /dev/null +++ b/scenarios/statebloat/contract-deploy/contract_deploy.go @@ -0,0 +1,305 @@ +package contractdeploy + +import ( + "context" + "crypto/rand" + "fmt" + "math/big" + "sync" + "sync/atomic" + "time" + + "golang.org/x/time/rate" + "gopkg.in/yaml.v3" + + "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/core/types" + "github.com/sirupsen/logrus" + "github.com/spf13/pflag" + + "github.com/ethpandaops/spamoor/scenarios/statebloat/contract-deploy/contract" + "github.com/ethpandaops/spamoor/scenariotypes" + "github.com/ethpandaops/spamoor/spamoor" + "github.com/ethpandaops/spamoor/txbuilder" + "github.com/ethpandaops/spamoor/utils" +) + +type ScenarioOptions struct { + TotalCount uint64 `yaml:"total_count"` + Throughput uint64 `yaml:"throughput"` + MaxPending uint64 `yaml:"max_pending"` + MaxWallets uint64 `yaml:"max_wallets"` + Rebroadcast uint64 `yaml:"rebroadcast"` + BaseFee uint64 `yaml:"base_fee"` + TipFee uint64 `yaml:"tip_fee"` + GasPerBlock uint64 `yaml:"gas_per_block"` + ClientGroup string `yaml:"client_group"` +} + +type Scenario struct { + options ScenarioOptions + logger *logrus.Entry + walletPool *spamoor.WalletPool + + pendingChan chan bool + pendingWGroup sync.WaitGroup +} + +var ScenarioName = "contract-deploy" +var ScenarioDefaultOptions = ScenarioOptions{ + TotalCount: 0, + Throughput: 0, + MaxPending: 0, + MaxWallets: 0, + Rebroadcast: 30, + BaseFee: 20, + TipFee: 2, + GasPerBlock: 0, + ClientGroup: "", +} +var ScenarioDescriptor = scenariotypes.ScenarioDescriptor{ + Name: ScenarioName, + Description: "Deploy contracts to create state bloat", + 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.Uint64VarP(&s.options.TotalCount, "count", "c", ScenarioDefaultOptions.TotalCount, "Total number of contracts to deploy") + flags.Uint64VarP(&s.options.Throughput, "throughput", "t", ScenarioDefaultOptions.Throughput, "Number of contracts to deploy per slot") + 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.Rebroadcast, "rebroadcast", ScenarioDefaultOptions.Rebroadcast, "Number of seconds to wait before re-broadcasting a transaction") + 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.Uint64Var(&s.options.GasPerBlock, "gas-per-block", ScenarioDefaultOptions.GasPerBlock, "Target gas to use per block (will calculate number of contracts to deploy)") + flags.StringVar(&s.options.ClientGroup, "client-group", ScenarioDefaultOptions.ClientGroup, "Client group to use for sending transactions") + 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.MaxWallets > 0 { + walletPool.SetWalletCount(s.options.MaxWallets) + } else if s.options.TotalCount > 0 { + if s.options.TotalCount < 1000 { + walletPool.SetWalletCount(s.options.TotalCount) + } else { + walletPool.SetWalletCount(1000) + } + } else { + if s.options.Throughput*10 < 1000 { + walletPool.SetWalletCount(s.options.Throughput * 10) + } else { + walletPool.SetWalletCount(1000) + } + } + + if s.options.TotalCount == 0 && s.options.Throughput == 0 && s.options.GasPerBlock == 0 { + return fmt.Errorf("neither total count, throughput, nor gas per block limit set, must define at least one of them (see --help for list of all flags)") + } + + if s.options.MaxPending > 0 { + s.pendingChan = make(chan bool, s.options.MaxPending) + } + + return nil +} + +func (s *Scenario) Config() string { + yamlBytes, _ := yaml.Marshal(&s.options) + return string(yamlBytes) +} + +func (s *Scenario) Run(ctx context.Context) error { + txIdxCounter := uint64(0) + pendingCount := atomic.Int64{} + txCount := atomic.Uint64{} + var lastChan chan bool + + s.logger.Infof("starting scenario: %s", ScenarioName) + defer s.logger.Infof("scenario %s finished.", ScenarioName) + + // Calculate throughput based on gas per block if specified + throughput := s.options.Throughput + if s.options.GasPerBlock > 0 { + // Each deployment costs ~4.967M gas + throughput = s.options.GasPerBlock / 4967200 + if throughput == 0 { + throughput = 1 + } + s.logger.Infof("calculated throughput: %d contracts per block (target gas: %d)", throughput, s.options.GasPerBlock) + } + + initialRate := rate.Limit(float64(throughput) / float64(utils.SecondsPerSlot)) + if initialRate == 0 { + initialRate = rate.Inf + } + limiter := rate.NewLimiter(initialRate, 1) + + for { + if err := limiter.Wait(ctx); err != nil { + if ctx.Err() != nil { + break + } + + s.logger.Debugf("rate limited: %s", err.Error()) + time.Sleep(100 * time.Millisecond) + continue + } + + txIdx := txIdxCounter + txIdxCounter++ + + if s.pendingChan != nil { + // await pending transactions + s.pendingChan <- true + } + pendingCount.Add(1) + currentChan := make(chan bool, 1) + + go func(txIdx uint64, lastChan, currentChan chan bool) { + defer func() { + pendingCount.Add(-1) + currentChan <- true + }() + + logger := s.logger + tx, client, wallet, err := s.sendTx(ctx, txIdx, func() { + if s.pendingChan != nil { + time.Sleep(100 * time.Millisecond) + <-s.pendingChan + } + }) + if client != nil { + logger = logger.WithField("rpc", client.GetName()) + } + if tx != nil { + logger = logger.WithField("nonce", tx.Nonce()) + } + if wallet != nil { + logger = logger.WithField("wallet", s.walletPool.GetWalletName(wallet.GetAddress())) + } + if lastChan != nil { + <-lastChan + close(lastChan) + } + if err != nil { + logger.Warnf("could not send transaction: %v", err) + return + } + + txCount.Add(1) + if lastChan != nil { + <-lastChan + close(lastChan) + } + logger.Infof("sent tx #%6d: %v", txIdx+1, tx.Hash().String()) + }(txIdx, lastChan, currentChan) + + lastChan = currentChan + + count := txCount.Load() + uint64(pendingCount.Load()) + if s.options.TotalCount > 0 && count >= s.options.TotalCount { + break + } + } + s.pendingWGroup.Wait() + s.logger.Infof("finished sending transactions, awaiting block inclusion...") + + return nil +} + +func (s *Scenario) sendTx(ctx context.Context, txIdx uint64, onComplete func()) (*types.Transaction, *txbuilder.Client, *txbuilder.Wallet, error) { + client := s.walletPool.GetClient(spamoor.SelectClientByIndex, int(txIdx), s.options.ClientGroup) + wallet := s.walletPool.GetWallet(spamoor.SelectWalletByIndex, int(txIdx)) + + if client == nil { + return nil, nil, nil, fmt.Errorf("no client available") + } + + 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(1000000000)) + } + if s.options.TipFee > 0 { + tipCap = 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 nil, nil, nil, fmt.Errorf("failed to generate salt: %w", err) + } + saltInt := new(big.Int).SetBytes(salt) + + // Get chain ID + chainId, err := client.GetChainId(ctx) + if err != nil { + return nil, nil, nil, fmt.Errorf("failed to get chain ID: %w", err) + } + + // Deploy contract + auth, err := bind.NewKeyedTransactorWithChainID(wallet.GetPrivateKey(), chainId) + if err != nil { + return nil, nil, nil, fmt.Errorf("failed to create auth: %w", err) + } + + auth.Nonce = big.NewInt(int64(wallet.GetNonce())) + auth.Value = big.NewInt(0) + auth.GasLimit = 5000000 // Enough for 24kB contract + auth.GasPrice = feeCap + auth.GasTipCap = tipCap + + // Get contract bytecode + bytecode, err := contract.StateBloatTokenMetaData.GetDeployedBytecode("StateBloatToken") + if err != nil { + return nil, nil, nil, fmt.Errorf("failed to get bytecode: %w", err) + } + + // Pack constructor arguments + packedArgs, err := contract.StateBloatTokenMetaData.Abi.Pack("", saltInt) + if err != nil { + return nil, nil, nil, fmt.Errorf("failed to pack constructor args: %w", err) + } + + // Combine bytecode and constructor args + fullBytecode := append(bytecode, packedArgs...) + + // Create transaction + tx := types.NewContractCreation(auth.Nonce.Uint64(), auth.Value, auth.GasLimit, auth.GasPrice, fullBytecode) + + // Sign transaction + signedTx, err := auth.Signer(auth.From, tx) + if err != nil { + return nil, nil, nil, fmt.Errorf("failed to sign transaction: %w", err) + } + + // Send transaction + err = client.SendTransactionCtx(ctx, signedTx) + if err != nil { + return nil, nil, nil, fmt.Errorf("failed to send transaction: %w", err) + } + + // Update nonce + wallet.SetNonce(wallet.GetNonce() + 1) + + return signedTx, client, wallet, nil +} From 372feec634ffa983a11562cb672ef844c520ff28 Mon Sep 17 00:00:00 2001 From: CPerezz Date: Wed, 7 May 2025 17:13:24 +0200 Subject: [PATCH 03/26] refactor(contract-deploy): simplify deployment rate control - Remove redundant throughput flag and consolidate to contracts-per-tx - Remove count flag and related code for cleaner interface - Update wallet count calculation to use contracts-per-tx - Keep only two deployment rate control methods: - contracts-per-tx: direct control of contracts per transaction - gas-per-block: calculate contracts based on target gas The scenario now runs indefinitely until stopped, with cleaner and more focused configuration options. --- .../contract-deploy/contract_deploy.go | 68 +++++++++---------- 1 file changed, 31 insertions(+), 37 deletions(-) diff --git a/scenarios/statebloat/contract-deploy/contract_deploy.go b/scenarios/statebloat/contract-deploy/contract_deploy.go index 650d7cab..12363833 100644 --- a/scenarios/statebloat/contract-deploy/contract_deploy.go +++ b/scenarios/statebloat/contract-deploy/contract_deploy.go @@ -25,15 +25,14 @@ import ( ) type ScenarioOptions struct { - TotalCount uint64 `yaml:"total_count"` - Throughput uint64 `yaml:"throughput"` - MaxPending uint64 `yaml:"max_pending"` - MaxWallets uint64 `yaml:"max_wallets"` - Rebroadcast uint64 `yaml:"rebroadcast"` - BaseFee uint64 `yaml:"base_fee"` - TipFee uint64 `yaml:"tip_fee"` - GasPerBlock uint64 `yaml:"gas_per_block"` - ClientGroup string `yaml:"client_group"` + MaxPending uint64 `yaml:"max_pending"` + MaxWallets uint64 `yaml:"max_wallets"` + Rebroadcast uint64 `yaml:"rebroadcast"` + BaseFee uint64 `yaml:"base_fee"` + TipFee uint64 `yaml:"tip_fee"` + GasPerBlock uint64 `yaml:"gas_per_block"` + ClientGroup string `yaml:"client_group"` + ContractsPerTx uint64 `yaml:"contracts_per_tx"` } type Scenario struct { @@ -47,15 +46,14 @@ type Scenario struct { var ScenarioName = "contract-deploy" var ScenarioDefaultOptions = ScenarioOptions{ - TotalCount: 0, - Throughput: 0, - MaxPending: 0, - MaxWallets: 0, - Rebroadcast: 30, - BaseFee: 20, - TipFee: 2, - GasPerBlock: 0, - ClientGroup: "", + MaxPending: 0, + MaxWallets: 0, + Rebroadcast: 30, + BaseFee: 20, + TipFee: 2, + GasPerBlock: 0, + ClientGroup: "default", + ContractsPerTx: 1, } var ScenarioDescriptor = scenariotypes.ScenarioDescriptor{ Name: ScenarioName, @@ -71,8 +69,6 @@ func newScenario(logger logrus.FieldLogger) scenariotypes.Scenario { } func (s *Scenario) Flags(flags *pflag.FlagSet) error { - flags.Uint64VarP(&s.options.TotalCount, "count", "c", ScenarioDefaultOptions.TotalCount, "Total number of contracts to deploy") - flags.Uint64VarP(&s.options.Throughput, "throughput", "t", ScenarioDefaultOptions.Throughput, "Number of contracts to deploy per slot") 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.Rebroadcast, "rebroadcast", ScenarioDefaultOptions.Rebroadcast, "Number of seconds to wait before re-broadcasting a transaction") @@ -80,6 +76,7 @@ func (s *Scenario) Flags(flags *pflag.FlagSet) error { flags.Uint64Var(&s.options.TipFee, "tipfee", ScenarioDefaultOptions.TipFee, "Max tip per gas to use in transactions (in gwei)") flags.Uint64Var(&s.options.GasPerBlock, "gas-per-block", ScenarioDefaultOptions.GasPerBlock, "Target gas to use per block (will calculate number of contracts to deploy)") flags.StringVar(&s.options.ClientGroup, "client-group", ScenarioDefaultOptions.ClientGroup, "Client group to use for sending transactions") + flags.Uint64Var(&s.options.ContractsPerTx, "contracts-per-tx", ScenarioDefaultOptions.ContractsPerTx, "Number of contracts to deploy in a single transaction") return nil } @@ -95,22 +92,18 @@ func (s *Scenario) Init(walletPool *spamoor.WalletPool, config string) error { if s.options.MaxWallets > 0 { walletPool.SetWalletCount(s.options.MaxWallets) - } else if s.options.TotalCount > 0 { - if s.options.TotalCount < 1000 { - walletPool.SetWalletCount(s.options.TotalCount) - } else { - walletPool.SetWalletCount(1000) - } } else { - if s.options.Throughput*10 < 1000 { - walletPool.SetWalletCount(s.options.Throughput * 10) + if s.options.ContractsPerTx*10 < 1000 { + walletPool.SetWalletCount(s.options.ContractsPerTx * 10) } else { walletPool.SetWalletCount(1000) } } - if s.options.TotalCount == 0 && s.options.Throughput == 0 && s.options.GasPerBlock == 0 { - return fmt.Errorf("neither total count, throughput, nor gas per block limit set, must define at least one of them (see --help for list of all flags)") + // TODO: We need to check that we don't exceed block gas limit with the number of contracts we're deploying. + // Otherwise fail with an error message that explains that we're exceeding the block gas limit. + if s.options.GasPerBlock == 0 && s.options.ContractsPerTx == 0 { + return fmt.Errorf("neither gas per block limit nor contracts per tx set, must define at least one of them (see --help for list of all flags)") } if s.options.MaxPending > 0 { @@ -134,8 +127,8 @@ func (s *Scenario) Run(ctx context.Context) error { s.logger.Infof("starting scenario: %s", ScenarioName) defer s.logger.Infof("scenario %s finished.", ScenarioName) - // Calculate throughput based on gas per block if specified - throughput := s.options.Throughput + // Calculate throughput based on gas per block or contracts per tx + throughput := s.options.ContractsPerTx if s.options.GasPerBlock > 0 { // Each deployment costs ~4.967M gas throughput = s.options.GasPerBlock / 4967200 @@ -143,6 +136,12 @@ func (s *Scenario) Run(ctx context.Context) error { throughput = 1 } s.logger.Infof("calculated throughput: %d contracts per block (target gas: %d)", throughput, s.options.GasPerBlock) + } else { + // Calculate gas needed for the specified number of contracts + // TODO: This should be a constant value, not a variable. We should change it everywhere. + gasPerContract := uint64(4967200) // ~4.967M gas per contract + totalGas := gasPerContract * s.options.ContractsPerTx + s.logger.Infof("calculated gas: %d per tx for %d contracts", totalGas, throughput) } initialRate := rate.Limit(float64(throughput) / float64(utils.SecondsPerSlot)) @@ -212,11 +211,6 @@ func (s *Scenario) Run(ctx context.Context) error { }(txIdx, lastChan, currentChan) lastChan = currentChan - - count := txCount.Load() + uint64(pendingCount.Load()) - if s.options.TotalCount > 0 && count >= s.options.TotalCount { - break - } } s.pendingWGroup.Wait() s.logger.Infof("finished sending transactions, awaiting block inclusion...") From b9ac6eb8b655cba76c306a3723edb2e0a7135071 Mon Sep 17 00:00:00 2001 From: CPerezz Date: Wed, 7 May 2025 17:24:01 +0200 Subject: [PATCH 04/26] fix: use correct contract metadata fields for bytecode and ABI packing --- .../{contract-deploy => contract_deploy}/README.md | 0 .../contract/README.md | 0 .../contract/StateBloatToken.abi | 0 .../contract/StateBloatToken.bin | 0 .../contract/StateBloatToken.go | 0 .../contract/StateBloatToken.sol | 0 .../contract_deploy.go | 12 ++++++++---- 7 files changed, 8 insertions(+), 4 deletions(-) rename scenarios/statebloat/{contract-deploy => contract_deploy}/README.md (100%) rename scenarios/statebloat/{contract-deploy => contract_deploy}/contract/README.md (100%) rename scenarios/statebloat/{contract-deploy => contract_deploy}/contract/StateBloatToken.abi (100%) rename scenarios/statebloat/{contract-deploy => contract_deploy}/contract/StateBloatToken.bin (100%) rename scenarios/statebloat/{contract-deploy => contract_deploy}/contract/StateBloatToken.go (100%) rename scenarios/statebloat/{contract-deploy => contract_deploy}/contract/StateBloatToken.sol (100%) rename scenarios/statebloat/{contract-deploy => contract_deploy}/contract_deploy.go (96%) diff --git a/scenarios/statebloat/contract-deploy/README.md b/scenarios/statebloat/contract_deploy/README.md similarity index 100% rename from scenarios/statebloat/contract-deploy/README.md rename to scenarios/statebloat/contract_deploy/README.md diff --git a/scenarios/statebloat/contract-deploy/contract/README.md b/scenarios/statebloat/contract_deploy/contract/README.md similarity index 100% rename from scenarios/statebloat/contract-deploy/contract/README.md rename to scenarios/statebloat/contract_deploy/contract/README.md diff --git a/scenarios/statebloat/contract-deploy/contract/StateBloatToken.abi b/scenarios/statebloat/contract_deploy/contract/StateBloatToken.abi similarity index 100% rename from scenarios/statebloat/contract-deploy/contract/StateBloatToken.abi rename to scenarios/statebloat/contract_deploy/contract/StateBloatToken.abi diff --git a/scenarios/statebloat/contract-deploy/contract/StateBloatToken.bin b/scenarios/statebloat/contract_deploy/contract/StateBloatToken.bin similarity index 100% rename from scenarios/statebloat/contract-deploy/contract/StateBloatToken.bin rename to scenarios/statebloat/contract_deploy/contract/StateBloatToken.bin diff --git a/scenarios/statebloat/contract-deploy/contract/StateBloatToken.go b/scenarios/statebloat/contract_deploy/contract/StateBloatToken.go similarity index 100% rename from scenarios/statebloat/contract-deploy/contract/StateBloatToken.go rename to scenarios/statebloat/contract_deploy/contract/StateBloatToken.go diff --git a/scenarios/statebloat/contract-deploy/contract/StateBloatToken.sol b/scenarios/statebloat/contract_deploy/contract/StateBloatToken.sol similarity index 100% rename from scenarios/statebloat/contract-deploy/contract/StateBloatToken.sol rename to scenarios/statebloat/contract_deploy/contract/StateBloatToken.sol diff --git a/scenarios/statebloat/contract-deploy/contract_deploy.go b/scenarios/statebloat/contract_deploy/contract_deploy.go similarity index 96% rename from scenarios/statebloat/contract-deploy/contract_deploy.go rename to scenarios/statebloat/contract_deploy/contract_deploy.go index 12363833..7df17c47 100644 --- a/scenarios/statebloat/contract-deploy/contract_deploy.go +++ b/scenarios/statebloat/contract_deploy/contract_deploy.go @@ -17,7 +17,8 @@ import ( "github.com/sirupsen/logrus" "github.com/spf13/pflag" - "github.com/ethpandaops/spamoor/scenarios/statebloat/contract-deploy/contract" + "github.com/ethereum/go-ethereum/common" + "github.com/ethpandaops/spamoor/scenarios/statebloat/contract_deploy/contract" "github.com/ethpandaops/spamoor/scenariotypes" "github.com/ethpandaops/spamoor/spamoor" "github.com/ethpandaops/spamoor/txbuilder" @@ -263,13 +264,16 @@ func (s *Scenario) sendTx(ctx context.Context, txIdx uint64, onComplete func()) auth.GasTipCap = tipCap // Get contract bytecode - bytecode, err := contract.StateBloatTokenMetaData.GetDeployedBytecode("StateBloatToken") + bytecode := common.FromHex(contract.ContractBin) + + // Get ABI + parsed, err := contract.ContractMetaData.GetAbi() if err != nil { - return nil, nil, nil, fmt.Errorf("failed to get bytecode: %w", err) + return nil, nil, nil, fmt.Errorf("failed to get ABI: %w", err) } // Pack constructor arguments - packedArgs, err := contract.StateBloatTokenMetaData.Abi.Pack("", saltInt) + packedArgs, err := parsed.Pack("", saltInt) if err != nil { return nil, nil, nil, fmt.Errorf("failed to pack constructor args: %w", err) } From 76840e666da2d0c346cd5a788791416b4fca93ef Mon Sep 17 00:00:00 2001 From: CPerezz Date: Wed, 7 May 2025 17:54:45 +0200 Subject: [PATCH 05/26] chore: rename gas constant to uppercase for better visibility --- .../statebloat/contract_deploy/contract_deploy.go | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/scenarios/statebloat/contract_deploy/contract_deploy.go b/scenarios/statebloat/contract_deploy/contract_deploy.go index 7df17c47..0f95b40b 100644 --- a/scenarios/statebloat/contract_deploy/contract_deploy.go +++ b/scenarios/statebloat/contract_deploy/contract_deploy.go @@ -25,6 +25,11 @@ import ( "github.com/ethpandaops/spamoor/utils" ) +const ( + // GAS_PER_CONTRACT is the estimated gas cost for deploying one StateBloatToken contract + GAS_PER_CONTRACT = 4970000 // ~4.97M gas per contract +) + type ScenarioOptions struct { MaxPending uint64 `yaml:"max_pending"` MaxWallets uint64 `yaml:"max_wallets"` @@ -131,17 +136,15 @@ func (s *Scenario) Run(ctx context.Context) error { // Calculate throughput based on gas per block or contracts per tx throughput := s.options.ContractsPerTx if s.options.GasPerBlock > 0 { - // Each deployment costs ~4.967M gas - throughput = s.options.GasPerBlock / 4967200 + // Each deployment costs ~4.97M gas + throughput = s.options.GasPerBlock / GAS_PER_CONTRACT if throughput == 0 { throughput = 1 } s.logger.Infof("calculated throughput: %d contracts per block (target gas: %d)", throughput, s.options.GasPerBlock) } else { // Calculate gas needed for the specified number of contracts - // TODO: This should be a constant value, not a variable. We should change it everywhere. - gasPerContract := uint64(4967200) // ~4.967M gas per contract - totalGas := gasPerContract * s.options.ContractsPerTx + totalGas := GAS_PER_CONTRACT * s.options.ContractsPerTx s.logger.Infof("calculated gas: %d per tx for %d contracts", totalGas, throughput) } From dbf118de9f037dda6c54cfedd456779a07701c03 Mon Sep 17 00:00:00 2001 From: CPerezz Date: Wed, 7 May 2025 18:20:32 +0200 Subject: [PATCH 06/26] feat(contract-deploy): add block gas limit validation - Add validation to ensure contract deployments don't exceed block gas limit - Check both gas-per-block and contracts-per-tx against block gas limit - Add clear error messages when gas limits are exceeded - Move validation to Run() function to access context --- .../contract_deploy/contract_deploy.go | 30 +++++++++++++++---- 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/scenarios/statebloat/contract_deploy/contract_deploy.go b/scenarios/statebloat/contract_deploy/contract_deploy.go index 0f95b40b..10acc361 100644 --- a/scenarios/statebloat/contract_deploy/contract_deploy.go +++ b/scenarios/statebloat/contract_deploy/contract_deploy.go @@ -96,6 +96,10 @@ func (s *Scenario) Init(walletPool *spamoor.WalletPool, config string) error { } } + if s.options.GasPerBlock == 0 && s.options.ContractsPerTx == 0 { + return fmt.Errorf("neither gas per block limit nor contracts per tx set, must define at least one of them (see --help for list of all flags)") + } + if s.options.MaxWallets > 0 { walletPool.SetWalletCount(s.options.MaxWallets) } else { @@ -106,12 +110,6 @@ func (s *Scenario) Init(walletPool *spamoor.WalletPool, config string) error { } } - // TODO: We need to check that we don't exceed block gas limit with the number of contracts we're deploying. - // Otherwise fail with an error message that explains that we're exceeding the block gas limit. - if s.options.GasPerBlock == 0 && s.options.ContractsPerTx == 0 { - return fmt.Errorf("neither gas per block limit nor contracts per tx set, must define at least one of them (see --help for list of all flags)") - } - if s.options.MaxPending > 0 { s.pendingChan = make(chan bool, s.options.MaxPending) } @@ -133,6 +131,26 @@ func (s *Scenario) Run(ctx context.Context) error { s.logger.Infof("starting scenario: %s", ScenarioName) defer s.logger.Infof("scenario %s finished.", ScenarioName) + // Get block gas limit and validate contract deployment gas + client := s.walletPool.GetClient(spamoor.SelectClientByIndex, 0, s.options.ClientGroup) + if client == nil { + return fmt.Errorf("no client available") + } + block, err := client.GetEthClient().BlockByNumber(ctx, nil) + if err != nil { + return fmt.Errorf("failed to get latest block: %w", err) + } + blockGasLimit := block.GasLimit() + + // Validate gas usage against block limit + if s.options.GasPerBlock > blockGasLimit { + return fmt.Errorf("gas per block (%d) exceeds block gas limit (%d)", s.options.GasPerBlock, blockGasLimit) + } + if s.options.ContractsPerTx*GAS_PER_CONTRACT > blockGasLimit { + return fmt.Errorf("contracts per tx (%d) requires %d gas, exceeding block gas limit (%d)", + s.options.ContractsPerTx, s.options.ContractsPerTx*GAS_PER_CONTRACT, blockGasLimit) + } + // Calculate throughput based on gas per block or contracts per tx throughput := s.options.ContractsPerTx if s.options.GasPerBlock > 0 { From 5438bdd2f203182fb64cbc4579ab88539e8a35fd Mon Sep 17 00:00:00 2001 From: CPerezz Date: Thu, 8 May 2025 15:45:41 +0200 Subject: [PATCH 07/26] add: Basic testing for contract deploying --- go.mod | 3 + .../contract_deploy/contract_deploy.go | 5 - .../contract_deploy/contract_deploy_test.go | 114 ++++++++++++++++++ 3 files changed, 117 insertions(+), 5 deletions(-) create mode 100644 scenarios/statebloat/contract_deploy/contract_deploy_test.go diff --git a/go.mod b/go.mod index 71054d9b..ebdfcc40 100644 --- a/go.mod +++ b/go.mod @@ -14,6 +14,7 @@ require ( github.com/pressly/goose/v3 v3.24.2 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 @@ -30,6 +31,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 @@ -49,6 +51,7 @@ require ( github.com/mfridman/interpolate v0.0.2 // indirect github.com/mmcloughlin/addchain v0.4.0 // indirect github.com/ncruces/go-strftime v0.1.9 // indirect + github.com/pmezard/go-difflib v1.0.0 // indirect github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect github.com/sethvargo/go-retry v0.3.0 // indirect github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible // indirect diff --git a/scenarios/statebloat/contract_deploy/contract_deploy.go b/scenarios/statebloat/contract_deploy/contract_deploy.go index 10acc361..cf3a293b 100644 --- a/scenarios/statebloat/contract_deploy/contract_deploy.go +++ b/scenarios/statebloat/contract_deploy/contract_deploy.go @@ -217,7 +217,6 @@ func (s *Scenario) Run(ctx context.Context) error { } if lastChan != nil { <-lastChan - close(lastChan) } if err != nil { logger.Warnf("could not send transaction: %v", err) @@ -225,10 +224,6 @@ func (s *Scenario) Run(ctx context.Context) error { } txCount.Add(1) - if lastChan != nil { - <-lastChan - close(lastChan) - } logger.Infof("sent tx #%6d: %v", txIdx+1, tx.Hash().String()) }(txIdx, lastChan, currentChan) diff --git a/scenarios/statebloat/contract_deploy/contract_deploy_test.go b/scenarios/statebloat/contract_deploy/contract_deploy_test.go new file mode 100644 index 00000000..77b8be28 --- /dev/null +++ b/scenarios/statebloat/contract_deploy/contract_deploy_test.go @@ -0,0 +1,114 @@ +package contractdeploy + +import ( + "context" + "os/exec" + "testing" + "time" + + "github.com/ethereum/go-ethereum/ethclient" + "github.com/holiman/uint256" + "github.com/sirupsen/logrus" + "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" + + "github.com/ethpandaops/spamoor/spamoor" + "github.com/ethpandaops/spamoor/txbuilder" + "github.com/ethpandaops/spamoor/utils" +) + +func TestContractDeploy(t *testing.T) { + // Start Anvil server with legacy transactions + cmd := exec.Command("anvil", "--hardfork", "pectra") + err := cmd.Start() + require.NoError(t, err) + defer cmd.Process.Kill() + + // Wait for Anvil to start + time.Sleep(2 * time.Second) + + // Connect to Anvil + client, err := ethclient.Dial("http://localhost:8545") + require.NoError(t, err) + defer client.Close() + + // Create context + ctx := context.Background() + logger := logrus.New().WithField("test", "contract-deploy") + + // Create client pool + clientPool := spamoor.NewClientPool(ctx, []string{"http://localhost:8545"}, logger) + err = clientPool.PrepareClients() + require.NoError(t, err) + + // Create root wallet using a pre-funded Anvil account + rootWallet, err := spamoor.InitRootWallet(ctx, "ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80", clientPool.GetClient(spamoor.SelectClientByIndex, 0, ""), logger) + require.NoError(t, err) + + // Create tx pool + txpool := txbuilder.NewTxPool(&txbuilder.TxPoolOptions{ + Context: ctx, + GetClientFn: func(index int, random bool) *txbuilder.Client { + mode := spamoor.SelectClientByIndex + if random { + mode = spamoor.SelectClientRandom + } + return clientPool.GetClient(mode, index, "") + }, + GetClientCountFn: func() int { + return len(clientPool.GetAllClients()) + }, + }) + + // Create wallet pool + walletPool := spamoor.NewWalletPool(ctx, logger, rootWallet, clientPool, txpool) + walletPool.SetWalletCount(1) + walletPool.SetRefillAmount(utils.EtherToWei(uint256.NewInt(1))) // 1 ETH + walletPool.SetRefillBalance(utils.EtherToWei(uint256.NewInt(1))) // 1 ETH + walletPool.SetRefillInterval(60) + + // Create scenario instance + scenario := newScenario(logger) + + // Configure scenario with 6 contracts per tx which is the maximum allowed by the latest fork. + config := ` +max_pending: 0 +max_wallets: 1 +rebroadcast: 30 +base_fee: 20 +tip_fee: 2 +gas_per_block: 30000000 +client_group: default +contracts_per_tx: 6 +` + err = scenario.Init(walletPool, config) + require.NoError(t, err) + + // Prepare wallets + err = walletPool.PrepareWallets(true) + require.NoError(t, err) + + // Create context with timeout + runCtx, cancel := context.WithTimeout(ctx, 30*time.Second) + defer cancel() + + // Run scenario + err = scenario.Run(runCtx) + require.NoError(t, err) + + // Verify contract deployment + block, err := client.BlockByNumber(ctx, nil) + require.NoError(t, err) + assert.Greater(t, block.Transactions().Len(), 0) + + // Get transaction receipt + tx := block.Transactions()[0] + receipt, err := client.TransactionReceipt(ctx, tx.Hash()) + require.NoError(t, err) + assert.Equal(t, uint64(1), receipt.Status) + + // Verify contract was created + code, err := client.CodeAt(ctx, receipt.ContractAddress, nil) + require.NoError(t, err) + assert.Greater(t, len(code), 0) +} From af640f2086574c8665b71d6dd76cbd82b5f2f094 Mon Sep 17 00:00:00 2001 From: CPerezz Date: Mon, 12 May 2025 12:17:42 +0200 Subject: [PATCH 08/26] feat(contract-deploy): enhance contract deployment scenarios - Introduce multiple test cases for contract deployment: using contracts per block, gas per block, and handling invalid configurations. - Update config opts to replace `contracts-per-tx` with `contracts-per-block` for better clarity. - Add error handling for scenarios where neither gas per block nor contracts per block is set. --- .../contract_deploy/contract_deploy.go | 96 +++++-------- .../contract_deploy/contract_deploy_test.go | 126 +++++++++++++----- 2 files changed, 128 insertions(+), 94 deletions(-) diff --git a/scenarios/statebloat/contract_deploy/contract_deploy.go b/scenarios/statebloat/contract_deploy/contract_deploy.go index cf3a293b..a49e3628 100644 --- a/scenarios/statebloat/contract_deploy/contract_deploy.go +++ b/scenarios/statebloat/contract_deploy/contract_deploy.go @@ -17,7 +17,6 @@ import ( "github.com/sirupsen/logrus" "github.com/spf13/pflag" - "github.com/ethereum/go-ethereum/common" "github.com/ethpandaops/spamoor/scenarios/statebloat/contract_deploy/contract" "github.com/ethpandaops/spamoor/scenariotypes" "github.com/ethpandaops/spamoor/spamoor" @@ -31,14 +30,14 @@ const ( ) type ScenarioOptions struct { - MaxPending uint64 `yaml:"max_pending"` - MaxWallets uint64 `yaml:"max_wallets"` - Rebroadcast uint64 `yaml:"rebroadcast"` - BaseFee uint64 `yaml:"base_fee"` - TipFee uint64 `yaml:"tip_fee"` - GasPerBlock uint64 `yaml:"gas_per_block"` - ClientGroup string `yaml:"client_group"` - ContractsPerTx uint64 `yaml:"contracts_per_tx"` + MaxPending uint64 `yaml:"max_pending"` + MaxWallets uint64 `yaml:"max_wallets"` + Rebroadcast uint64 `yaml:"rebroadcast"` + BaseFee uint64 `yaml:"base_fee"` + TipFee uint64 `yaml:"tip_fee"` + GasPerBlock uint64 `yaml:"gas_per_block"` + ClientGroup string `yaml:"client_group"` + ContractsPerBlock uint64 `yaml:"contracts_per_block"` } type Scenario struct { @@ -52,14 +51,14 @@ type Scenario struct { var ScenarioName = "contract-deploy" var ScenarioDefaultOptions = ScenarioOptions{ - MaxPending: 0, - MaxWallets: 0, - Rebroadcast: 30, - BaseFee: 20, - TipFee: 2, - GasPerBlock: 0, - ClientGroup: "default", - ContractsPerTx: 1, + MaxPending: 0, + MaxWallets: 0, + Rebroadcast: 30, + BaseFee: 20, + TipFee: 2, + GasPerBlock: 0, + ClientGroup: "default", + ContractsPerBlock: 1, } var ScenarioDescriptor = scenariotypes.ScenarioDescriptor{ Name: ScenarioName, @@ -82,7 +81,7 @@ func (s *Scenario) Flags(flags *pflag.FlagSet) error { flags.Uint64Var(&s.options.TipFee, "tipfee", ScenarioDefaultOptions.TipFee, "Max tip per gas to use in transactions (in gwei)") flags.Uint64Var(&s.options.GasPerBlock, "gas-per-block", ScenarioDefaultOptions.GasPerBlock, "Target gas to use per block (will calculate number of contracts to deploy)") flags.StringVar(&s.options.ClientGroup, "client-group", ScenarioDefaultOptions.ClientGroup, "Client group to use for sending transactions") - flags.Uint64Var(&s.options.ContractsPerTx, "contracts-per-tx", ScenarioDefaultOptions.ContractsPerTx, "Number of contracts to deploy in a single transaction") + flags.Uint64Var(&s.options.ContractsPerBlock, "contracts-per-block", ScenarioDefaultOptions.ContractsPerBlock, "Number of contracts to deploy per block") return nil } @@ -96,15 +95,15 @@ func (s *Scenario) Init(walletPool *spamoor.WalletPool, config string) error { } } - if s.options.GasPerBlock == 0 && s.options.ContractsPerTx == 0 { - return fmt.Errorf("neither gas per block limit nor contracts per tx set, must define at least one of them (see --help for list of all flags)") + if s.options.GasPerBlock == 0 && s.options.ContractsPerBlock == 0 { + return fmt.Errorf("neither gas per block limit nor contracts per block set, must define at least one of them (see --help for list of all flags)") } if s.options.MaxWallets > 0 { walletPool.SetWalletCount(s.options.MaxWallets) } else { - if s.options.ContractsPerTx*10 < 1000 { - walletPool.SetWalletCount(s.options.ContractsPerTx * 10) + if s.options.ContractsPerBlock*10 < 1000 { + walletPool.SetWalletCount(s.options.ContractsPerBlock * 10) } else { walletPool.SetWalletCount(1000) } @@ -146,13 +145,13 @@ func (s *Scenario) Run(ctx context.Context) error { if s.options.GasPerBlock > blockGasLimit { return fmt.Errorf("gas per block (%d) exceeds block gas limit (%d)", s.options.GasPerBlock, blockGasLimit) } - if s.options.ContractsPerTx*GAS_PER_CONTRACT > blockGasLimit { - return fmt.Errorf("contracts per tx (%d) requires %d gas, exceeding block gas limit (%d)", - s.options.ContractsPerTx, s.options.ContractsPerTx*GAS_PER_CONTRACT, blockGasLimit) + if s.options.ContractsPerBlock*GAS_PER_CONTRACT > blockGasLimit { + return fmt.Errorf("contracts per block (%d) requires %d gas, exceeding block gas limit (%d)", + s.options.ContractsPerBlock, s.options.ContractsPerBlock*GAS_PER_CONTRACT, blockGasLimit) } - // Calculate throughput based on gas per block or contracts per tx - throughput := s.options.ContractsPerTx + // Calculate throughput based on gas per block or contracts per block + throughput := s.options.ContractsPerBlock if s.options.GasPerBlock > 0 { // Each deployment costs ~4.97M gas throughput = s.options.GasPerBlock / GAS_PER_CONTRACT @@ -162,8 +161,8 @@ func (s *Scenario) Run(ctx context.Context) error { s.logger.Infof("calculated throughput: %d contracts per block (target gas: %d)", throughput, s.options.GasPerBlock) } else { // Calculate gas needed for the specified number of contracts - totalGas := GAS_PER_CONTRACT * s.options.ContractsPerTx - s.logger.Infof("calculated gas: %d per tx for %d contracts", totalGas, throughput) + totalGas := GAS_PER_CONTRACT * s.options.ContractsPerBlock + s.logger.Infof("calculated gas: %d per block for %d contracts", totalGas, throughput) } initialRate := rate.Limit(float64(throughput) / float64(utils.SecondsPerSlot)) @@ -275,45 +274,20 @@ func (s *Scenario) sendTx(ctx context.Context, txIdx uint64, onComplete func()) auth.Nonce = big.NewInt(int64(wallet.GetNonce())) auth.Value = big.NewInt(0) - auth.GasLimit = 5000000 // Enough for 24kB contract + auth.GasLimit = GAS_PER_CONTRACT // Gas for single contract deployment auth.GasPrice = feeCap auth.GasTipCap = tipCap - // Get contract bytecode - bytecode := common.FromHex(contract.ContractBin) - - // Get ABI - parsed, err := contract.ContractMetaData.GetAbi() - if err != nil { - return nil, nil, nil, fmt.Errorf("failed to get ABI: %w", err) - } - - // Pack constructor arguments - packedArgs, err := parsed.Pack("", saltInt) - if err != nil { - return nil, nil, nil, fmt.Errorf("failed to pack constructor args: %w", err) - } - - // Combine bytecode and constructor args - fullBytecode := append(bytecode, packedArgs...) - - // Create transaction - tx := types.NewContractCreation(auth.Nonce.Uint64(), auth.Value, auth.GasLimit, auth.GasPrice, fullBytecode) - - // Sign transaction - signedTx, err := auth.Signer(auth.From, tx) - if err != nil { - return nil, nil, nil, fmt.Errorf("failed to sign transaction: %w", err) - } - - // Send transaction - err = client.SendTransactionCtx(ctx, signedTx) + // Deploy the StateBloatToken contract + address, tx, _, err := contract.DeployContract(auth, client.GetEthClient(), saltInt) if err != nil { - return nil, nil, nil, fmt.Errorf("failed to send transaction: %w", err) + return nil, nil, nil, fmt.Errorf("failed to deploy contract: %w", err) } // Update nonce wallet.SetNonce(wallet.GetNonce() + 1) - return signedTx, client, wallet, nil + // TODO: This should mention: Gas spent and bytes written. Also should give contract code hash for each contract. + s.logger.Infof("deployed contract at address: %s", address.Hex()) + return tx, client, wallet, nil } diff --git a/scenarios/statebloat/contract_deploy/contract_deploy_test.go b/scenarios/statebloat/contract_deploy/contract_deploy_test.go index 77b8be28..dcbe0f6a 100644 --- a/scenarios/statebloat/contract_deploy/contract_deploy_test.go +++ b/scenarios/statebloat/contract_deploy/contract_deploy_test.go @@ -32,11 +32,9 @@ func TestContractDeploy(t *testing.T) { require.NoError(t, err) defer client.Close() - // Create context + // Create client pool ctx := context.Background() logger := logrus.New().WithField("test", "contract-deploy") - - // Create client pool clientPool := spamoor.NewClientPool(ctx, []string{"http://localhost:8545"}, logger) err = clientPool.PrepareClients() require.NoError(t, err) @@ -70,45 +68,107 @@ func TestContractDeploy(t *testing.T) { // Create scenario instance scenario := newScenario(logger) - // Configure scenario with 6 contracts per tx which is the maximum allowed by the latest fork. - config := ` + // Test case 1: Using contracts_per_block + t.Run("contracts_per_block", func(t *testing.T) { + // Initialize with contracts_per_block configuration + config := ` max_pending: 0 max_wallets: 1 rebroadcast: 30 base_fee: 20 tip_fee: 2 -gas_per_block: 30000000 +gas_per_block: 0 client_group: default -contracts_per_tx: 6 +contracts_per_block: 6 ` - err = scenario.Init(walletPool, config) - require.NoError(t, err) - - // Prepare wallets - err = walletPool.PrepareWallets(true) - require.NoError(t, err) - - // Create context with timeout - runCtx, cancel := context.WithTimeout(ctx, 30*time.Second) - defer cancel() + require.NoError(t, scenario.Init(walletPool, config)) + + // Run scenario + runCtx, cancel := context.WithTimeout(ctx, 30*time.Second) + defer cancel() + + err := scenario.Run(runCtx) + require.NoError(t, err) + + // Verify contract deployment + block, err := client.BlockByNumber(runCtx, nil) + require.NoError(t, err) + assert.Greater(t, len(block.Transactions()), 0) + + // Check the first transaction + tx, _, err := client.TransactionByHash(runCtx, block.Transactions()[0].Hash()) + require.NoError(t, err) + receipt, err := client.TransactionReceipt(runCtx, tx.Hash()) + require.NoError(t, err) + assert.Equal(t, uint64(1), receipt.Status) + + // Verify contract was created + code, err := client.CodeAt(runCtx, receipt.ContractAddress, nil) + require.NoError(t, err) + assert.Greater(t, len(code), 0) + }) - // Run scenario - err = scenario.Run(runCtx) - require.NoError(t, err) + // Test case 2: Using gas_per_block + t.Run("gas_per_block", func(t *testing.T) { + // Initialize with gas_per_block configuration + config := ` +max_pending: 0 +max_wallets: 1 +rebroadcast: 30 +base_fee: 20 +tip_fee: 2 +gas_per_block: 30000000 +client_group: default +contracts_per_block: 0 +` + require.NoError(t, scenario.Init(walletPool, config)) + + // Run scenario + runCtx, cancel := context.WithTimeout(ctx, 30*time.Second) + defer cancel() + + err := scenario.Run(runCtx) + require.NoError(t, err) + + // Verify contract deployment + block, err := client.BlockByNumber(runCtx, nil) + require.NoError(t, err) + assert.Greater(t, len(block.Transactions()), 0) + + // Check the first transaction + tx, _, err := client.TransactionByHash(runCtx, block.Transactions()[0].Hash()) + require.NoError(t, err) + receipt, err := client.TransactionReceipt(runCtx, tx.Hash()) + require.NoError(t, err) + assert.Equal(t, uint64(1), receipt.Status) + + // Verify contract was created + code, err := client.CodeAt(runCtx, receipt.ContractAddress, nil) + require.NoError(t, err) + assert.Greater(t, len(code), 0) + }) - // Verify contract deployment - block, err := client.BlockByNumber(ctx, nil) - require.NoError(t, err) - assert.Greater(t, block.Transactions().Len(), 0) + // Test case 3: Invalid configuration + t.Run("invalid_config", func(t *testing.T) { + // Initialize with invalid configuration + config := ` +max_pending: 0 +max_wallets: 1 +rebroadcast: 30 +base_fee: 20 +tip_fee: 2 +gas_per_block: 0 +client_group: default +contracts_per_block: 0 +` + require.NoError(t, scenario.Init(walletPool, config)) - // Get transaction receipt - tx := block.Transactions()[0] - receipt, err := client.TransactionReceipt(ctx, tx.Hash()) - require.NoError(t, err) - assert.Equal(t, uint64(1), receipt.Status) + // Run scenario + runCtx, cancel := context.WithTimeout(ctx, 30*time.Second) + defer cancel() - // Verify contract was created - code, err := client.CodeAt(ctx, receipt.ContractAddress, nil) - require.NoError(t, err) - assert.Greater(t, len(code), 0) + err := scenario.Run(runCtx) + require.Error(t, err) + assert.Contains(t, err.Error(), "neither gas per block limit nor contracts per block set") + }) } From 54337183d482a0a5688d207657cdbdb91fb72750 Mon Sep 17 00:00:00 2001 From: CPerezz Date: Mon, 12 May 2025 12:54:19 +0200 Subject: [PATCH 09/26] fix(contract-deploy): Use 1559 fee config - Refactor gas fee parameters to align with EIP-1559 standards. - Initialize wallet pool in the contract deployment test. --- .../contract_deploy/contract_deploy.go | 46 ++++++++++--------- .../contract_deploy/contract_deploy_test.go | 4 ++ 2 files changed, 29 insertions(+), 21 deletions(-) diff --git a/scenarios/statebloat/contract_deploy/contract_deploy.go b/scenarios/statebloat/contract_deploy/contract_deploy.go index a49e3628..c3f79b47 100644 --- a/scenarios/statebloat/contract_deploy/contract_deploy.go +++ b/scenarios/statebloat/contract_deploy/contract_deploy.go @@ -241,25 +241,10 @@ func (s *Scenario) sendTx(ctx context.Context, txIdx uint64, onComplete func()) if client == nil { return nil, nil, nil, fmt.Errorf("no client available") } - - 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(1000000000)) - } - if s.options.TipFee > 0 { - tipCap = new(big.Int).Mul(big.NewInt(int64(s.options.TipFee)), big.NewInt(1000000000)) + if wallet == nil { + return nil, nil, nil, fmt.Errorf("no wallet available") } - // Generate random salt for unique contract - salt := make([]byte, 32) - _, err := rand.Read(salt) - if err != nil { - return nil, nil, nil, fmt.Errorf("failed to generate salt: %w", err) - } - saltInt := new(big.Int).SetBytes(salt) - // Get chain ID chainId, err := client.GetChainId(ctx) if err != nil { @@ -275,11 +260,31 @@ func (s *Scenario) sendTx(ctx context.Context, txIdx uint64, onComplete func()) auth.Nonce = big.NewInt(int64(wallet.GetNonce())) auth.Value = big.NewInt(0) auth.GasLimit = GAS_PER_CONTRACT // Gas for single contract deployment - auth.GasPrice = feeCap - auth.GasTipCap = tipCap + + // 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 nil, nil, nil, fmt.Errorf("failed to generate salt: %w", err) + } + saltInt := new(big.Int).SetBytes(salt) + + // Ensure we have a valid client + ethClient := client.GetEthClient() + if ethClient == nil { + return nil, nil, nil, fmt.Errorf("failed to get eth client") + } // Deploy the StateBloatToken contract - address, tx, _, err := contract.DeployContract(auth, client.GetEthClient(), saltInt) + address, tx, _, err := contract.DeployContract(auth, ethClient, saltInt) if err != nil { return nil, nil, nil, fmt.Errorf("failed to deploy contract: %w", err) } @@ -287,7 +292,6 @@ func (s *Scenario) sendTx(ctx context.Context, txIdx uint64, onComplete func()) // Update nonce wallet.SetNonce(wallet.GetNonce() + 1) - // TODO: This should mention: Gas spent and bytes written. Also should give contract code hash for each contract. s.logger.Infof("deployed contract at address: %s", address.Hex()) return tx, client, wallet, nil } diff --git a/scenarios/statebloat/contract_deploy/contract_deploy_test.go b/scenarios/statebloat/contract_deploy/contract_deploy_test.go index dcbe0f6a..886eb0a8 100644 --- a/scenarios/statebloat/contract_deploy/contract_deploy_test.go +++ b/scenarios/statebloat/contract_deploy/contract_deploy_test.go @@ -65,6 +65,10 @@ func TestContractDeploy(t *testing.T) { walletPool.SetRefillBalance(utils.EtherToWei(uint256.NewInt(1))) // 1 ETH walletPool.SetRefillInterval(60) + // Initialize wallet pool + err = walletPool.PrepareWallets(true) + require.NoError(t, err) + // Create scenario instance scenario := newScenario(logger) From 02affa8ecebdfd1f6ecbaa707e2f818265be40ec Mon Sep 17 00:00:00 2001 From: CPerezz Date: Mon, 12 May 2025 15:55:26 +0200 Subject: [PATCH 10/26] feat(contract-deploy): setup-teardown for tests - Introduced setup and teardown for contract deployment tests. - Updated scenario options to include a maximum transactions limit. St we can test for a single tx at a time and shortening testing time. --- .../contract_deploy/contract_deploy.go | 46 +++- .../contract_deploy/contract_deploy_test.go | 221 +++++++++++------- 2 files changed, 180 insertions(+), 87 deletions(-) diff --git a/scenarios/statebloat/contract_deploy/contract_deploy.go b/scenarios/statebloat/contract_deploy/contract_deploy.go index c3f79b47..482ddc8f 100644 --- a/scenarios/statebloat/contract_deploy/contract_deploy.go +++ b/scenarios/statebloat/contract_deploy/contract_deploy.go @@ -38,6 +38,7 @@ type ScenarioOptions struct { GasPerBlock uint64 `yaml:"gas_per_block"` ClientGroup string `yaml:"client_group"` ContractsPerBlock uint64 `yaml:"contracts_per_block"` + MaxTransactions uint64 `yaml:"max_transactions"` // Maximum number of transactions to send (0 for unlimited) } type Scenario struct { @@ -53,12 +54,13 @@ var ScenarioName = "contract-deploy" var ScenarioDefaultOptions = ScenarioOptions{ MaxPending: 0, MaxWallets: 0, - Rebroadcast: 30, + Rebroadcast: 1, BaseFee: 20, TipFee: 2, GasPerBlock: 0, ClientGroup: "default", ContractsPerBlock: 1, + MaxTransactions: 0, // Default to unlimited } var ScenarioDescriptor = scenariotypes.ScenarioDescriptor{ Name: ScenarioName, @@ -82,6 +84,7 @@ func (s *Scenario) Flags(flags *pflag.FlagSet) error { flags.Uint64Var(&s.options.GasPerBlock, "gas-per-block", ScenarioDefaultOptions.GasPerBlock, "Target gas to use per block (will calculate number of contracts to deploy)") flags.StringVar(&s.options.ClientGroup, "client-group", ScenarioDefaultOptions.ClientGroup, "Client group to use for sending transactions") flags.Uint64Var(&s.options.ContractsPerBlock, "contracts-per-block", ScenarioDefaultOptions.ContractsPerBlock, "Number of contracts to deploy per block") + flags.Uint64Var(&s.options.MaxTransactions, "max-transactions", ScenarioDefaultOptions.MaxTransactions, "Maximum number of transactions to send (0 for unlimited)") return nil } @@ -158,11 +161,21 @@ func (s *Scenario) Run(ctx context.Context) error { if throughput == 0 { throughput = 1 } - s.logger.Infof("calculated throughput: %d contracts per block (target gas: %d)", throughput, s.options.GasPerBlock) + s.logger.WithFields(logrus.Fields{ + "test": "contract-deploy", + "throughput": throughput, + "target_gas": s.options.GasPerBlock, + "gas_per_contract": GAS_PER_CONTRACT, + }).Info("calculated throughput") } else { // Calculate gas needed for the specified number of contracts totalGas := GAS_PER_CONTRACT * s.options.ContractsPerBlock - s.logger.Infof("calculated gas: %d per block for %d contracts", totalGas, throughput) + s.logger.WithFields(logrus.Fields{ + "test": "contract-deploy", + "total_gas": totalGas, + "contracts": s.options.ContractsPerBlock, + "gas_per_contract": GAS_PER_CONTRACT, + }).Info("calculated gas") } initialRate := rate.Limit(float64(throughput) / float64(utils.SecondsPerSlot)) @@ -172,6 +185,12 @@ func (s *Scenario) Run(ctx context.Context) error { limiter := rate.NewLimiter(initialRate, 1) for { + // Check if we've reached the maximum number of transactions + if s.options.MaxTransactions > 0 && txIdxCounter >= s.options.MaxTransactions { + s.logger.Infof("reached maximum number of transactions (%d)", s.options.MaxTransactions) + break + } + if err := limiter.Wait(ctx); err != nil { if ctx.Err() != nil { break @@ -223,13 +242,16 @@ func (s *Scenario) Run(ctx context.Context) error { } txCount.Add(1) - logger.Infof("sent tx #%6d: %v", txIdx+1, tx.Hash().String()) }(txIdx, lastChan, currentChan) lastChan = currentChan } s.pendingWGroup.Wait() - s.logger.Infof("finished sending transactions, awaiting block inclusion...") + s.logger.WithFields(logrus.Fields{ + "test": "contract-deploy", + "total_txs": txCount.Load(), + "pending_txs": pendingCount.Load(), + }).Info("finished sending transactions, awaiting block inclusion...") return nil } @@ -292,6 +314,18 @@ func (s *Scenario) sendTx(ctx context.Context, txIdx uint64, onComplete func()) // Update nonce wallet.SetNonce(wallet.GetNonce() + 1) - s.logger.Infof("deployed contract at address: %s", address.Hex()) + // Calculate bytes written and gas/byte ratio + txBytes := len(tx.Data()) + gasPerByte := float64(GAS_PER_CONTRACT) / float64(txBytes) + + s.logger.WithFields(logrus.Fields{ + "test": "contract-deploy", + "tx_hash": tx.Hash().Hex(), + "contract_address": address.Hex(), + "bytes_written": txBytes, + "gas_per_byte": fmt.Sprintf("%.2f", gasPerByte), + "contracts": 1, + }).Info("deployed contract") + return tx, client, wallet, nil } diff --git a/scenarios/statebloat/contract_deploy/contract_deploy_test.go b/scenarios/statebloat/contract_deploy/contract_deploy_test.go index 886eb0a8..653bd50d 100644 --- a/scenarios/statebloat/contract_deploy/contract_deploy_test.go +++ b/scenarios/statebloat/contract_deploy/contract_deploy_test.go @@ -12,17 +12,30 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + "github.com/ethereum/go-ethereum/common" "github.com/ethpandaops/spamoor/spamoor" "github.com/ethpandaops/spamoor/txbuilder" "github.com/ethpandaops/spamoor/utils" ) -func TestContractDeploy(t *testing.T) { +type testFixture struct { + t *testing.T + cmd *exec.Cmd + client *ethclient.Client + ctx context.Context + logger *logrus.Entry + clientPool *spamoor.ClientPool + rootWallet *txbuilder.Wallet + txpool *txbuilder.TxPool + walletPool *spamoor.WalletPool + scenario *Scenario +} + +func setupTestFixture(t *testing.T) *testFixture { // Start Anvil server with legacy transactions cmd := exec.Command("anvil", "--hardfork", "pectra") err := cmd.Start() require.NoError(t, err) - defer cmd.Process.Kill() // Wait for Anvil to start time.Sleep(2 * time.Second) @@ -30,7 +43,6 @@ func TestContractDeploy(t *testing.T) { // Connect to Anvil client, err := ethclient.Dial("http://localhost:8545") require.NoError(t, err) - defer client.Close() // Create client pool ctx := context.Background() @@ -70,109 +82,156 @@ func TestContractDeploy(t *testing.T) { require.NoError(t, err) // Create scenario instance - scenario := newScenario(logger) + scenario := newScenario(logger).(*Scenario) + + return &testFixture{ + t: t, + cmd: cmd, + client: client, + ctx: ctx, + logger: logger, + clientPool: clientPool, + rootWallet: rootWallet, + txpool: txpool, + walletPool: walletPool, + scenario: scenario, + } +} + +func (f *testFixture) teardown() { + if f.cmd != nil && f.cmd.Process != nil { + f.cmd.Process.Kill() + } + if f.client != nil { + f.client.Close() + } +} + +func (f *testFixture) verifyContractDeployment(runCtx context.Context) { + // Verify contract deployment + block, err := f.client.BlockByNumber(runCtx, nil) + require.NoError(f.t, err) + assert.Greater(f.t, len(block.Transactions()), 0) + + // Get the expected number of contracts based on scenario config + expectedContracts := f.scenario.options.ContractsPerBlock + if f.scenario.options.GasPerBlock > 0 { + expectedContracts = f.scenario.options.GasPerBlock / GAS_PER_CONTRACT + if expectedContracts == 0 { + expectedContracts = 1 + } + } + + // Track deployed contracts + deployedContracts := 0 + contractAddresses := make([]common.Address, 0) + + // Check all transactions in the block + for _, tx := range block.Transactions() { + receipt, err := f.client.TransactionReceipt(runCtx, tx.Hash()) + require.NoError(f.t, err) + assert.Equal(f.t, uint64(1), receipt.Status) + + // If this is a contract creation transaction + if receipt.ContractAddress != (common.Address{}) { + deployedContracts++ + contractAddresses = append(contractAddresses, receipt.ContractAddress) + } + } + + // Verify the number of contracts deployed matches the expected count + assert.Equal(f.t, expectedContracts, deployedContracts, "Number of deployed contracts should match the scenario configuration") + + // Verify each contract's size + for _, addr := range contractAddresses { + code, err := f.client.CodeAt(runCtx, addr, nil) + require.NoError(f.t, err) + + // EIP-170 limit is 24,576 bytes (0x6000) + assert.Equal(f.t, 24576, len(code), "Contract code size should be exactly 24,576 bytes (EIP-170 limit)") + } + + f.logger.WithFields(logrus.Fields{ + "expected_contracts": expectedContracts, + "deployed_contracts": deployedContracts, + "contract_addresses": contractAddresses, + }).Info("Verified contract deployments") +} - // Test case 1: Using contracts_per_block - t.Run("contracts_per_block", func(t *testing.T) { - // Initialize with contracts_per_block configuration - config := ` +func TestContractDeployWithContractsPerBlock(t *testing.T) { + fixture := setupTestFixture(t) + defer fixture.teardown() + + // Initialize with contracts_per_block configuration + config := ` max_pending: 0 max_wallets: 1 -rebroadcast: 30 +rebroadcast: 2 base_fee: 20 tip_fee: 2 gas_per_block: 0 client_group: default contracts_per_block: 6 +max_transactions: 1 ` - require.NoError(t, scenario.Init(walletPool, config)) - - // Run scenario - runCtx, cancel := context.WithTimeout(ctx, 30*time.Second) - defer cancel() - - err := scenario.Run(runCtx) - require.NoError(t, err) - - // Verify contract deployment - block, err := client.BlockByNumber(runCtx, nil) - require.NoError(t, err) - assert.Greater(t, len(block.Transactions()), 0) - - // Check the first transaction - tx, _, err := client.TransactionByHash(runCtx, block.Transactions()[0].Hash()) - require.NoError(t, err) - receipt, err := client.TransactionReceipt(runCtx, tx.Hash()) - require.NoError(t, err) - assert.Equal(t, uint64(1), receipt.Status) - - // Verify contract was created - code, err := client.CodeAt(runCtx, receipt.ContractAddress, nil) - require.NoError(t, err) - assert.Greater(t, len(code), 0) - }) + require.NoError(t, fixture.scenario.Init(fixture.walletPool, config)) + + // Run scenario + runCtx, cancel := context.WithTimeout(fixture.ctx, 30*time.Second) + defer cancel() - // Test case 2: Using gas_per_block - t.Run("gas_per_block", func(t *testing.T) { - // Initialize with gas_per_block configuration - config := ` + err := fixture.scenario.Run(runCtx) + require.NoError(t, err) + + fixture.verifyContractDeployment(runCtx) +} + +func TestContractDeployWithGasPerBlock(t *testing.T) { + fixture := setupTestFixture(t) + defer fixture.teardown() + + // Initialize with gas_per_block configuration + config := ` max_pending: 0 max_wallets: 1 -rebroadcast: 30 +rebroadcast: 2 base_fee: 20 tip_fee: 2 gas_per_block: 30000000 client_group: default contracts_per_block: 0 +max_transactions: 1 ` - require.NoError(t, scenario.Init(walletPool, config)) - - // Run scenario - runCtx, cancel := context.WithTimeout(ctx, 30*time.Second) - defer cancel() - - err := scenario.Run(runCtx) - require.NoError(t, err) - - // Verify contract deployment - block, err := client.BlockByNumber(runCtx, nil) - require.NoError(t, err) - assert.Greater(t, len(block.Transactions()), 0) - - // Check the first transaction - tx, _, err := client.TransactionByHash(runCtx, block.Transactions()[0].Hash()) - require.NoError(t, err) - receipt, err := client.TransactionReceipt(runCtx, tx.Hash()) - require.NoError(t, err) - assert.Equal(t, uint64(1), receipt.Status) - - // Verify contract was created - code, err := client.CodeAt(runCtx, receipt.ContractAddress, nil) - require.NoError(t, err) - assert.Greater(t, len(code), 0) - }) + require.NoError(t, fixture.scenario.Init(fixture.walletPool, config)) + + // Run scenario + runCtx, cancel := context.WithTimeout(fixture.ctx, 30*time.Second) + defer cancel() + + err := fixture.scenario.Run(runCtx) + require.NoError(t, err) - // Test case 3: Invalid configuration - t.Run("invalid_config", func(t *testing.T) { - // Initialize with invalid configuration - config := ` + fixture.verifyContractDeployment(runCtx) +} + +func TestContractDeployWithInvalidConfig(t *testing.T) { + fixture := setupTestFixture(t) + defer fixture.teardown() + + // Initialize with invalid configuration + config := ` max_pending: 0 max_wallets: 1 -rebroadcast: 30 +rebroadcast: 1 base_fee: 20 tip_fee: 2 gas_per_block: 0 client_group: default contracts_per_block: 0 +max_transactions: 1 ` - require.NoError(t, scenario.Init(walletPool, config)) - - // Run scenario - runCtx, cancel := context.WithTimeout(ctx, 30*time.Second) - defer cancel() - - err := scenario.Run(runCtx) - require.Error(t, err) - assert.Contains(t, err.Error(), "neither gas per block limit nor contracts per block set") - }) + // We expect Init to fail with this configuration + err := fixture.scenario.Init(fixture.walletPool, config) + require.Error(t, err) + assert.Contains(t, err.Error(), "neither gas per block limit nor contracts per block set") } From 09241822eebf27681a2f0d29185c614c286a8e40 Mon Sep 17 00:00:00 2001 From: CPerezz Date: Tue, 13 May 2025 23:40:11 +0200 Subject: [PATCH 11/26] feat(contract-deploy): add dummy functions to increase bytecode size to max (EIP170) - Introduced multiple dummy functions in the StateBloatToken contract to artificially inflate bytecode size. - Updated ABI and binary files to reflect changes in the contract structure. --- .../contract/StateBloatToken.abi | 2 +- .../contract/StateBloatToken.bin | 2 +- .../contract/StateBloatToken.go | 2728 ++++++++++++++++- .../contract/StateBloatToken.sol | 568 +++- 4 files changed, 3294 insertions(+), 6 deletions(-) diff --git a/scenarios/statebloat/contract_deploy/contract/StateBloatToken.abi b/scenarios/statebloat/contract_deploy/contract/StateBloatToken.abi index fb9e7b53..4dea8206 100644 --- a/scenarios/statebloat/contract_deploy/contract/StateBloatToken.abi +++ b/scenarios/statebloat/contract_deploy/contract/StateBloatToken.abi @@ -1 +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":"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"}] \ No newline at end of file +[{"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":"dummy66","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"dummy67","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"dummy68","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"dummy69","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"dummy7","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"dummy70","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"dummy71","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"dummy72","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"dummy73","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"dummy74","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"dummy75","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 index 0ea68c09..10e9b41a 100644 --- a/scenarios/statebloat/contract_deploy/contract/StateBloatToken.bin +++ b/scenarios/statebloat/contract_deploy/contract/StateBloatToken.bin @@ -1 +1 @@ -60a060405234801561000f575f5ffd5b50604051611503380380611503833981810160405281019061003191906101f4565b6040518060400160405280601181526020017f537461746520426c6f617420546f6b656e0000000000000000000000000000008152505f90816100749190610453565b506040518060400160405280600381526020017f5342540000000000000000000000000000000000000000000000000000000000815250600190816100b99190610453565b50601260025f6101000a81548160ff021916908360ff160217905550806080818152505060025f9054906101000a900460ff16600a6100f8919061068a565b620f424061010691906106d4565b60038190555060035460045f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055503373ffffffffffffffffffffffffffffffffffffffff165f73ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef6003546040516101af9190610724565b60405180910390a35061073d565b5f5ffd5b5f819050919050565b6101d3816101c1565b81146101dd575f5ffd5b50565b5f815190506101ee816101ca565b92915050565b5f60208284031215610209576102086101bd565b5b5f610216848285016101e0565b91505092915050565b5f81519050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f600282049050600182168061029a57607f821691505b6020821081036102ad576102ac610256565b5b50919050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f6008830261030f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff826102d4565b61031986836102d4565b95508019841693508086168417925050509392505050565b5f819050919050565b5f61035461034f61034a846101c1565b610331565b6101c1565b9050919050565b5f819050919050565b61036d8361033a565b6103816103798261035b565b8484546102e0565b825550505050565b5f5f905090565b610398610389565b6103a3818484610364565b505050565b5b818110156103c6576103bb5f82610390565b6001810190506103a9565b5050565b601f82111561040b576103dc816102b3565b6103e5846102c5565b810160208510156103f4578190505b610408610400856102c5565b8301826103a8565b50505b505050565b5f82821c905092915050565b5f61042b5f1984600802610410565b1980831691505092915050565b5f610443838361041c565b9150826002028217905092915050565b61045c8261021f565b67ffffffffffffffff81111561047557610474610229565b5b61047f8254610283565b61048a8282856103ca565b5f60209050601f8311600181146104bb575f84156104a9578287015190505b6104b38582610438565b86555061051a565b601f1984166104c9866102b3565b5f5b828110156104f0578489015182556001820191506020850194506020810190506104cb565b8683101561050d5784890151610509601f89168261041c565b8355505b6001600288020188555050505b505050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f8160011c9050919050565b5f5f8291508390505b60018511156105a4578086048111156105805761057f610522565b5b600185161561058f5780820291505b808102905061059d8561054f565b9450610564565b94509492505050565b5f826105bc5760019050610677565b816105c9575f9050610677565b81600181146105df57600281146105e957610618565b6001915050610677565b60ff8411156105fb576105fa610522565b5b8360020a91508482111561061257610611610522565b5b50610677565b5060208310610133831016604e8410600b841016171561064d5782820a90508381111561064857610647610522565b5b610677565b61065a848484600161055b565b9250905081840481111561067157610670610522565b5b81810290505b9392505050565b5f60ff82169050919050565b5f610694826101c1565b915061069f8361067e565b92506106cc7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff84846105ad565b905092915050565b5f6106de826101c1565b91506106e9836101c1565b92508282026106f7816101c1565b9150828204841483151761070e5761070d610522565b5b5092915050565b61071e816101c1565b82525050565b5f6020820190506107375f830184610715565b92915050565b608051610dae6107555f395f6108cf0152610dae5ff3fe608060405234801561000f575f5ffd5b506004361061009c575f3560e01c806370a082311161006457806370a082311461015a57806395d89b411461018a578063a9059cbb146101a8578063bfa0b133146101d8578063dd62ed3e146101f65761009c565b806306fdde03146100a0578063095ea7b3146100be57806318160ddd146100ee57806323b872dd1461010c578063313ce5671461013c575b5f5ffd5b6100a8610226565b6040516100b59190610981565b60405180910390f35b6100d860048036038101906100d39190610a32565b6102b1565b6040516100e59190610a8a565b60405180910390f35b6100f661039e565b6040516101039190610ab2565b60405180910390f35b61012660048036038101906101219190610acb565b6103a4565b6040516101339190610a8a565b60405180910390f35b610144610684565b6040516101519190610b36565b60405180910390f35b610174600480360381019061016f9190610b4f565b610696565b6040516101819190610ab2565b60405180910390f35b6101926106ab565b60405161019f9190610981565b60405180910390f35b6101c260048036038101906101bd9190610a32565b610737565b6040516101cf9190610a8a565b60405180910390f35b6101e06108cd565b6040516101ed9190610ab2565b60405180910390f35b610210600480360381019061020b9190610b7a565b6108f1565b60405161021d9190610ab2565b60405180910390f35b5f805461023290610be5565b80601f016020809104026020016040519081016040528092919081815260200182805461025e90610be5565b80156102a95780601f10610280576101008083540402835291602001916102a9565b820191905f5260205f20905b81548152906001019060200180831161028c57829003601f168201915b505050505081565b5f8160055f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9258460405161038c9190610ab2565b60405180910390a36001905092915050565b60035481565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015610425576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161041c90610c5f565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156104e0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104d790610cc7565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461052c9190610d12565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461057f9190610d45565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461060d9190610d12565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516106719190610ab2565b60405180910390a3600190509392505050565b60025f9054906101000a900460ff1681565b6004602052805f5260405f205f915090505481565b600180546106b890610be5565b80601f01602080910402602001604051908101604052809291908181526020018280546106e490610be5565b801561072f5780601f106107065761010080835404028352916020019161072f565b820191905f5260205f20905b81548152906001019060200180831161071257829003601f168201915b505050505081565b5f8160045f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156107b8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107af90610c5f565b60405180910390fd5b8160045f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546108049190610d12565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546108579190610d45565b925050819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516108bb9190610ab2565b60405180910390a36001905092915050565b7f000000000000000000000000000000000000000000000000000000000000000081565b6005602052815f5260405f20602052805f5260405f205f91509150505481565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f61095382610911565b61095d818561091b565b935061096d81856020860161092b565b61097681610939565b840191505092915050565b5f6020820190508181035f8301526109998184610949565b905092915050565b5f5ffd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6109ce826109a5565b9050919050565b6109de816109c4565b81146109e8575f5ffd5b50565b5f813590506109f9816109d5565b92915050565b5f819050919050565b610a11816109ff565b8114610a1b575f5ffd5b50565b5f81359050610a2c81610a08565b92915050565b5f5f60408385031215610a4857610a476109a1565b5b5f610a55858286016109eb565b9250506020610a6685828601610a1e565b9150509250929050565b5f8115159050919050565b610a8481610a70565b82525050565b5f602082019050610a9d5f830184610a7b565b92915050565b610aac816109ff565b82525050565b5f602082019050610ac55f830184610aa3565b92915050565b5f5f5f60608486031215610ae257610ae16109a1565b5b5f610aef868287016109eb565b9350506020610b00868287016109eb565b9250506040610b1186828701610a1e565b9150509250925092565b5f60ff82169050919050565b610b3081610b1b565b82525050565b5f602082019050610b495f830184610b27565b92915050565b5f60208284031215610b6457610b636109a1565b5b5f610b71848285016109eb565b91505092915050565b5f5f60408385031215610b9057610b8f6109a1565b5b5f610b9d858286016109eb565b9250506020610bae858286016109eb565b9150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f6002820490506001821680610bfc57607f821691505b602082108103610c0f57610c0e610bb8565b5b50919050565b7f496e73756666696369656e742062616c616e63650000000000000000000000005f82015250565b5f610c4960148361091b565b9150610c5482610c15565b602082019050919050565b5f6020820190508181035f830152610c7681610c3d565b9050919050565b7f496e73756666696369656e7420616c6c6f77616e6365000000000000000000005f82015250565b5f610cb160168361091b565b9150610cbc82610c7d565b602082019050919050565b5f6020820190508181035f830152610cde81610ca5565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f610d1c826109ff565b9150610d27836109ff565b9250828203905081811115610d3f57610d3e610ce5565b5b92915050565b5f610d4f826109ff565b9150610d5a836109ff565b9250828201905080821115610d7257610d71610ce5565b5b9291505056fea26469706673582212207182ee741671c2a140c5eb4e62cb72b950c446fa68846143d961b62f544f59c764736f6c634300081e0033 \ No newline at end of file +60a060405234801561000f575f5ffd5b50604051615fd4380380615fd4833981810160405281019061003191906101f4565b6040518060400160405280601181526020017f537461746520426c6f617420546f6b656e0000000000000000000000000000008152505f90816100749190610453565b506040518060400160405280600381526020017f5342540000000000000000000000000000000000000000000000000000000000815250600190816100b99190610453565b50601260025f6101000a81548160ff021916908360ff160217905550806080818152505060025f9054906101000a900460ff16600a6100f8919061068a565b620f424061010691906106d4565b60038190555060035460045f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055503373ffffffffffffffffffffffffffffffffffffffff165f73ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef6003546040516101af9190610724565b60405180910390a35061073d565b5f5ffd5b5f819050919050565b6101d3816101c1565b81146101dd575f5ffd5b50565b5f815190506101ee816101ca565b92915050565b5f60208284031215610209576102086101bd565b5b5f610216848285016101e0565b91505092915050565b5f81519050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f600282049050600182168061029a57607f821691505b6020821081036102ad576102ac610256565b5b50919050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f6008830261030f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff826102d4565b61031986836102d4565b95508019841693508086168417925050509392505050565b5f819050919050565b5f61035461034f61034a846101c1565b610331565b6101c1565b9050919050565b5f819050919050565b61036d8361033a565b6103816103798261035b565b8484546102e0565b825550505050565b5f5f905090565b610398610389565b6103a3818484610364565b505050565b5b818110156103c6576103bb5f82610390565b6001810190506103a9565b5050565b601f82111561040b576103dc816102b3565b6103e5846102c5565b810160208510156103f4578190505b610408610400856102c5565b8301826103a8565b50505b505050565b5f82821c905092915050565b5f61042b5f1984600802610410565b1980831691505092915050565b5f610443838361041c565b9150826002028217905092915050565b61045c8261021f565b67ffffffffffffffff81111561047557610474610229565b5b61047f8254610283565b61048a8282856103ca565b5f60209050601f8311600181146104bb575f84156104a9578287015190505b6104b38582610438565b86555061051a565b601f1984166104c9866102b3565b5f5b828110156104f0578489015182556001820191506020850194506020810190506104cb565b8683101561050d5784890151610509601f89168261041c565b8355505b6001600288020188555050505b505050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f8160011c9050919050565b5f5f8291508390505b60018511156105a4578086048111156105805761057f610522565b5b600185161561058f5780820291505b808102905061059d8561054f565b9450610564565b94509492505050565b5f826105bc5760019050610677565b816105c9575f9050610677565b81600181146105df57600281146105e957610618565b6001915050610677565b60ff8411156105fb576105fa610522565b5b8360020a91508482111561061257610611610522565b5b50610677565b5060208310610133831016604e8410600b841016171561064d5782820a90508381111561064857610647610522565b5b610677565b61065a848484600161055b565b9250905081840481111561067157610670610522565b5b81810290505b9392505050565b5f60ff82169050919050565b5f610694826101c1565b915061069f8361067e565b92506106cc7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff84846105ad565b905092915050565b5f6106de826101c1565b91506106e9836101c1565b92508282026106f7816101c1565b9150828204841483151761070e5761070d610522565b5b5092915050565b61071e816101c1565b82525050565b5f6020820190506107375f830184610715565b92915050565b60805161587f6107555f395f614a7b015261587f5ff3fe608060405234801561000f575f5ffd5b5060043610610606575f3560e01c8063657b6ef711610319578063b1802b9a116101a6578063d9bb3174116100f2578063f26c779b116100ab578063f8716f1411610085578063f8716f1414611360578063faf35ced1461137e578063fe7d5996146113ae578063ffbf0469146113cc57610606565b8063f26c779b14611306578063f4978b0414611324578063f5f573811461134257610606565b8063d9bb31741461122e578063dc1d8a9b1461124c578063dd62ed3e1461126a578063e2d275301461129a578063e8c927b3146112b8578063eb4329c8146112d657610606565b8063bbe231321161015f578063c958d4bf11610139578063c958d4bf146111b6578063cfd66863146111d4578063d101dcd0146111f2578063d74194691461121057610606565b8063bbe231321461114a578063bfa0b13314611168578063c2be97e31461118657610606565b8063b1802b9a14611072578063b2bb360e146110a2578063b4c48668146110c0578063b66dd750146110de578063b9a6d645146110fc578063bb9bfe061461111a57610606565b80637e544937116102655780639c5dfe731161021e578063a9059cbb116101f8578063a9059cbb14610fd6578063aaa7af7014611006578063acc5aee914611024578063ad8f42211461105457610606565b80639c5dfe7314610f7c5780639df61a2514610f9a578063a891d4d414610fb857610606565b80637e54493714610eb65780637f34d94b14610ed45780638619d60714610ef25780638789ca6714610f105780638f4a840614610f4057806395d89b4114610f5e57610606565b806374f83d02116102d25780637a319c18116102ac5780637a319c1814610e2c5780637c66673e14610e4a5780637c72ed0d14610e7a5780637dffdc3214610e9857610606565b806374f83d0214610dd257806377c0209e14610df0578063792c7f3e14610e0e57610606565b8063657b6ef714610ce8578063672151fe14610d185780636abceacd14610d365780636c12ed2814610d5457806370a0823114610d8457806374e73fd314610db457610606565b8063313ce567116104975780634b3c7f5f116103e357806358b6a9bd1161039c57806361b970eb1161037657806361b970eb14610c70578063639ec53a14610c8e5780636547317414610cac5780636578534c14610cca57610606565b806358b6a9bd14610c16578063595471b814610c345780635af92c0514610c5257610606565b80634b3c7f5f14610b3e5780634e1dbb8214610b5c5780634f5e555714610b7a5780634f7bd75a14610b9857806354c2792014610bc8578063552a1b5614610be657610606565b80633ea117ce1161045057806342937dbd1161042a57806342937dbd14610ab457806343a6b92d14610ad257806344050a2814610af05780634a2e93c614610b2057610606565b80633ea117ce14610a5a5780634128a85d14610a78578063418b181614610a9657610606565b8063313ce5671461098257806334517f0b146109a0578063378c5382146109be57806339e0bd12146109dc5780633a13199014610a0c5780633b6be45914610a3c57610606565b80631bbffe6f1161055657806321ecd7a31161050f5780632545d8b7116104e95780632545d8b7146108f85780632787325b14610916578063291c3bd7146109345780633125f37a1461096457610606565b806321ecd7a31461088c578063239af2a5146108aa57806323b872dd146108c857610606565b80631bbffe6f146107c65780631d527cde146107f65780631eaa7c52146108145780631f29783f146108325780631f449589146108505780631fd298ec1461086e57610606565b806312901b42116105c357806318160ddd1161059d57806318160ddd1461073c57806319cf6a911461075a5780631a97f18e146107785780631b17c65c1461079657610606565b806312901b42146106e257806313ebb5ec1461070057806316a3045b1461071e57610606565b80630460faf61461060a57806306fdde031461063a5780630717b16114610658578063095ea7b3146106765780630cb7a9e7146106a65780631215a3ab146106c4575b5f5ffd5b610624600480360381019061061f91906153a3565b6113ea565b604051610631919061540d565b60405180910390f35b6106426116ca565b60405161064f9190615496565b60405180910390f35b610660611755565b60405161066d91906154c5565b60405180910390f35b610690600480360381019061068b91906154de565b61175d565b60405161069d919061540d565b60405180910390f35b6106ae61184a565b6040516106bb91906154c5565b60405180910390f35b6106cc611852565b6040516106d991906154c5565b60405180910390f35b6106ea61185a565b6040516106f791906154c5565b60405180910390f35b610708611862565b60405161071591906154c5565b60405180910390f35b61072661186a565b60405161073391906154c5565b60405180910390f35b610744611872565b60405161075191906154c5565b60405180910390f35b610762611878565b60405161076f91906154c5565b60405180910390f35b610780611880565b60405161078d91906154c5565b60405180910390f35b6107b060048036038101906107ab91906153a3565b611888565b6040516107bd919061540d565b60405180910390f35b6107e060048036038101906107db91906153a3565b611b68565b6040516107ed919061540d565b60405180910390f35b6107fe611e48565b60405161080b91906154c5565b60405180910390f35b61081c611e50565b60405161082991906154c5565b60405180910390f35b61083a611e58565b60405161084791906154c5565b60405180910390f35b610858611e60565b60405161086591906154c5565b60405180910390f35b610876611e68565b60405161088391906154c5565b60405180910390f35b610894611e70565b6040516108a191906154c5565b60405180910390f35b6108b2611e78565b6040516108bf91906154c5565b60405180910390f35b6108e260048036038101906108dd91906153a3565b611e80565b6040516108ef919061540d565b60405180910390f35b610900612160565b60405161090d91906154c5565b60405180910390f35b61091e612168565b60405161092b91906154c5565b60405180910390f35b61094e600480360381019061094991906153a3565b612170565b60405161095b919061540d565b60405180910390f35b61096c612450565b60405161097991906154c5565b60405180910390f35b61098a612458565b6040516109979190615537565b60405180910390f35b6109a861246a565b6040516109b591906154c5565b60405180910390f35b6109c6612472565b6040516109d391906154c5565b60405180910390f35b6109f660048036038101906109f191906153a3565b61247a565b604051610a03919061540d565b60405180910390f35b610a266004803603810190610a2191906153a3565b61275a565b604051610a33919061540d565b60405180910390f35b610a44612a3a565b604051610a5191906154c5565b60405180910390f35b610a62612a42565b604051610a6f91906154c5565b60405180910390f35b610a80612a4a565b604051610a8d91906154c5565b60405180910390f35b610a9e612a52565b604051610aab91906154c5565b60405180910390f35b610abc612a5a565b604051610ac991906154c5565b60405180910390f35b610ada612a62565b604051610ae791906154c5565b60405180910390f35b610b0a6004803603810190610b0591906153a3565b612a6a565b604051610b17919061540d565b60405180910390f35b610b28612d4a565b604051610b3591906154c5565b60405180910390f35b610b46612d52565b604051610b5391906154c5565b60405180910390f35b610b64612d5a565b604051610b7191906154c5565b60405180910390f35b610b82612d62565b604051610b8f91906154c5565b60405180910390f35b610bb26004803603810190610bad91906153a3565b612d6a565b604051610bbf919061540d565b60405180910390f35b610bd061304a565b604051610bdd91906154c5565b60405180910390f35b610c006004803603810190610bfb91906153a3565b613052565b604051610c0d919061540d565b60405180910390f35b610c1e613332565b604051610c2b91906154c5565b60405180910390f35b610c3c61333a565b604051610c4991906154c5565b60405180910390f35b610c5a613342565b604051610c6791906154c5565b60405180910390f35b610c7861334a565b604051610c8591906154c5565b60405180910390f35b610c96613352565b604051610ca391906154c5565b60405180910390f35b610cb461335a565b604051610cc191906154c5565b60405180910390f35b610cd2613362565b604051610cdf91906154c5565b60405180910390f35b610d026004803603810190610cfd91906153a3565b61336a565b604051610d0f919061540d565b60405180910390f35b610d2061364a565b604051610d2d91906154c5565b60405180910390f35b610d3e613652565b604051610d4b91906154c5565b60405180910390f35b610d6e6004803603810190610d6991906153a3565b61365a565b604051610d7b919061540d565b60405180910390f35b610d9e6004803603810190610d999190615550565b61393a565b604051610dab91906154c5565b60405180910390f35b610dbc61394f565b604051610dc991906154c5565b60405180910390f35b610dda613957565b604051610de791906154c5565b60405180910390f35b610df861395f565b604051610e0591906154c5565b60405180910390f35b610e16613967565b604051610e2391906154c5565b60405180910390f35b610e3461396f565b604051610e4191906154c5565b60405180910390f35b610e646004803603810190610e5f91906153a3565b613977565b604051610e71919061540d565b60405180910390f35b610e82613c57565b604051610e8f91906154c5565b60405180910390f35b610ea0613c5f565b604051610ead91906154c5565b60405180910390f35b610ebe613c67565b604051610ecb91906154c5565b60405180910390f35b610edc613c6f565b604051610ee991906154c5565b60405180910390f35b610efa613c77565b604051610f0791906154c5565b60405180910390f35b610f2a6004803603810190610f2591906153a3565b613c7f565b604051610f37919061540d565b60405180910390f35b610f48613f5f565b604051610f5591906154c5565b60405180910390f35b610f66613f67565b604051610f739190615496565b60405180910390f35b610f84613ff3565b604051610f9191906154c5565b60405180910390f35b610fa2613ffb565b604051610faf91906154c5565b60405180910390f35b610fc0614003565b604051610fcd91906154c5565b60405180910390f35b610ff06004803603810190610feb91906154de565b61400b565b604051610ffd919061540d565b60405180910390f35b61100e6141a1565b60405161101b91906154c5565b60405180910390f35b61103e600480360381019061103991906153a3565b6141a9565b60405161104b919061540d565b60405180910390f35b61105c614489565b60405161106991906154c5565b60405180910390f35b61108c600480360381019061108791906153a3565b614491565b604051611099919061540d565b60405180910390f35b6110aa614771565b6040516110b791906154c5565b60405180910390f35b6110c8614779565b6040516110d591906154c5565b60405180910390f35b6110e6614781565b6040516110f391906154c5565b60405180910390f35b611104614789565b60405161111191906154c5565b60405180910390f35b611134600480360381019061112f91906153a3565b614791565b604051611141919061540d565b60405180910390f35b611152614a71565b60405161115f91906154c5565b60405180910390f35b611170614a79565b60405161117d91906154c5565b60405180910390f35b6111a0600480360381019061119b91906153a3565b614a9d565b6040516111ad919061540d565b60405180910390f35b6111be614d7d565b6040516111cb91906154c5565b60405180910390f35b6111dc614d85565b6040516111e991906154c5565b60405180910390f35b6111fa614d8d565b60405161120791906154c5565b60405180910390f35b611218614d95565b60405161122591906154c5565b60405180910390f35b611236614d9d565b60405161124391906154c5565b60405180910390f35b611254614da5565b60405161126191906154c5565b60405180910390f35b611284600480360381019061127f919061557b565b614dad565b60405161129191906154c5565b60405180910390f35b6112a2614dcd565b6040516112af91906154c5565b60405180910390f35b6112c0614dd5565b6040516112cd91906154c5565b60405180910390f35b6112f060048036038101906112eb91906153a3565b614ddd565b6040516112fd919061540d565b60405180910390f35b61130e615002565b60405161131b91906154c5565b60405180910390f35b61132c61500a565b60405161133991906154c5565b60405180910390f35b61134a615012565b60405161135791906154c5565b60405180910390f35b61136861501a565b60405161137591906154c5565b60405180910390f35b611398600480360381019061139391906153a3565b615022565b6040516113a5919061540d565b60405180910390f35b6113b6615302565b6040516113c391906154c5565b60405180910390f35b6113d461530a565b6040516113e191906154c5565b60405180910390f35b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054101561146b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161146290615603565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015611526576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161151d9061566b565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461157291906156b6565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546115c591906156e9565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461165391906156b6565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516116b791906154c5565b60405180910390a3600190509392505050565b5f80546116d690615749565b80601f016020809104026020016040519081016040528092919081815260200182805461170290615749565b801561174d5780601f106117245761010080835404028352916020019161174d565b820191905f5260205f20905b81548152906001019060200180831161173057829003601f168201915b505050505081565b5f602f905090565b5f8160055f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9258460405161183891906154c5565b60405180910390a36001905092915050565b5f601b905090565b5f6005905090565b5f601a905090565b5f601d905090565b5f6033905090565b60035481565b5f6008905090565b5f6003905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015611909576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161190090615603565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156119c4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119bb9061566b565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254611a1091906156b6565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254611a6391906156e9565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254611af191906156b6565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051611b5591906154c5565b60405180910390a3600190509392505050565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015611be9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611be090615603565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015611ca4576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c9b9061566b565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254611cf091906156b6565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254611d4391906156e9565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254611dd191906156b6565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051611e3591906154c5565b60405180910390a3600190509392505050565b5f6002905090565b5f6010905090565b5f6048905090565b5f6041905090565b5f6035905090565b5f602e905090565b5f602c905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015611f01576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ef890615603565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015611fbc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611fb39061566b565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461200891906156b6565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461205b91906156e9565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546120e991906156b6565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161214d91906154c5565b60405180910390a3600190509392505050565b5f6001905090565b5f6045905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156121f1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016121e8906157c3565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156122ac576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016122a39061582b565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546122f891906156b6565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461234b91906156e9565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546123d991906156b6565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161243d91906154c5565b60405180910390a3600190509392505050565b5f6034905090565b60025f9054906101000a900460ff1681565b5f603c905090565b5f604b905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156124fb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016124f290615603565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156125b6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016125ad9061566b565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461260291906156b6565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461265591906156e9565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546126e391906156b6565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161274791906154c5565b60405180910390a3600190509392505050565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156127db576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016127d290615603565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015612896576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161288d9061566b565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546128e291906156b6565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461293591906156e9565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546129c391906156b6565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051612a2791906154c5565b60405180910390a3600190509392505050565b5f6004905090565b5f600c905090565b5f6006905090565b5f601c905090565b5f6032905090565b5f6023905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015612aeb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612ae290615603565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015612ba6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612b9d9061566b565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254612bf291906156b6565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254612c4591906156e9565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254612cd391906156b6565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051612d3791906154c5565b60405180910390a3600190509392505050565b5f6011905090565b5f6021905090565b5f601f905090565b5f6026905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015612deb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612de290615603565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015612ea6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612e9d9061566b565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254612ef291906156b6565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254612f4591906156e9565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254612fd391906156b6565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161303791906154c5565b60405180910390a3600190509392505050565b5f603a905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156130d3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016130ca90615603565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054101561318e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016131859061566b565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546131da91906156b6565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461322d91906156e9565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546132bb91906156b6565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161331f91906154c5565b60405180910390a3600190509392505050565b5f6009905090565b5f6049905090565b5f602a905090565b5f6014905090565b5f6025905090565b5f6013905090565b5f6043905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156133eb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016133e2906157c3565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156134a6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161349d9061582b565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546134f291906156b6565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461354591906156e9565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546135d391906156b6565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161363791906154c5565b60405180910390a3600190509392505050565b5f600d905090565b5f6017905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156136db576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016136d290615603565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015613796576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161378d9061566b565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546137e291906156b6565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461383591906156e9565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546138c391906156b6565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161392791906154c5565b60405180910390a3600190509392505050565b6004602052805f5260405f205f915090505481565b5f6016905090565b5f6039905090565b5f603b905090565b5f6036905090565b5f603f905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156139f8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016139ef90615603565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015613ab3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613aaa9061566b565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254613aff91906156b6565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254613b5291906156e9565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254613be091906156b6565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051613c4491906154c5565b60405180910390a3600190509392505050565b5f602b905090565b5f6037905090565b5f600a905090565b5f602d905090565b5f6030905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015613d00576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613cf790615603565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015613dbb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613db29061566b565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254613e0791906156b6565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254613e5a91906156e9565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254613ee891906156b6565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051613f4c91906154c5565b60405180910390a3600190509392505050565b5f600b905090565b60018054613f7490615749565b80601f0160208091040260200160405190810160405280929190818152602001828054613fa090615749565b8015613feb5780601f10613fc257610100808354040283529160200191613feb565b820191905f5260205f20905b815481529060010190602001808311613fce57829003601f168201915b505050505081565b5f6015905090565b5f6029905090565b5f6038905090565b5f8160045f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054101561408c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161408390615603565b60405180910390fd5b8160045f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546140d891906156b6565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461412b91906156e9565b925050819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161418f91906154c5565b60405180910390a36001905092915050565b5f6028905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054101561422a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161422190615603565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156142e5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016142dc9061566b565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461433191906156b6565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461438491906156e9565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461441291906156b6565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161447691906154c5565b60405180910390a3600190509392505050565b5f6040905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015614512576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161450990615603565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156145cd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016145c49061566b565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461461991906156b6565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461466c91906156e9565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546146fa91906156b6565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161475e91906154c5565b60405180910390a3600190509392505050565b5f6018905090565b5f604a905090565b5f600f905090565b5f6044905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015614812576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161480990615603565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156148cd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016148c49061566b565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461491991906156b6565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461496c91906156e9565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546149fa91906156b6565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051614a5e91906154c5565b60405180910390a3600190509392505050565b5f6046905090565b7f000000000000000000000000000000000000000000000000000000000000000081565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015614b1e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401614b1590615603565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015614bd9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401614bd09061566b565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254614c2591906156b6565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254614c7891906156e9565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254614d0691906156b6565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051614d6a91906154c5565b60405180910390a3600190509392505050565b5f6024905090565b5f601e905090565b5f6031905090565b5f6019905090565b5f6042905090565b5f6027905090565b6005602052815f5260405f20602052805f5260405f205f91509150505481565b5f603d905090565b5f6022905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015614e5e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401614e55906157c3565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254614eaa91906156b6565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254614efd91906156e9565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254614f8b91906156b6565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051614fef91906154c5565b60405180910390a3600190509392505050565b5f6007905090565b5f6047905090565b5f603e905090565b5f6020905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156150a3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161509a90615603565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054101561515e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016151559061566b565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546151aa91906156b6565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546151fd91906156e9565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461528b91906156b6565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516152ef91906154c5565b60405180910390a3600190509392505050565b5f600e905090565b5f6012905090565b5f5ffd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f61533f82615316565b9050919050565b61534f81615335565b8114615359575f5ffd5b50565b5f8135905061536a81615346565b92915050565b5f819050919050565b61538281615370565b811461538c575f5ffd5b50565b5f8135905061539d81615379565b92915050565b5f5f5f606084860312156153ba576153b9615312565b5b5f6153c78682870161535c565b93505060206153d88682870161535c565b92505060406153e98682870161538f565b9150509250925092565b5f8115159050919050565b615407816153f3565b82525050565b5f6020820190506154205f8301846153fe565b92915050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f61546882615426565b6154728185615430565b9350615482818560208601615440565b61548b8161544e565b840191505092915050565b5f6020820190508181035f8301526154ae818461545e565b905092915050565b6154bf81615370565b82525050565b5f6020820190506154d85f8301846154b6565b92915050565b5f5f604083850312156154f4576154f3615312565b5b5f6155018582860161535c565b92505060206155128582860161538f565b9150509250929050565b5f60ff82169050919050565b6155318161551c565b82525050565b5f60208201905061554a5f830184615528565b92915050565b5f6020828403121561556557615564615312565b5b5f6155728482850161535c565b91505092915050565b5f5f6040838503121561559157615590615312565b5b5f61559e8582860161535c565b92505060206155af8582860161535c565b9150509250929050565b7f496e73756666696369656e742062616c616e63650000000000000000000000005f82015250565b5f6155ed601483615430565b91506155f8826155b9565b602082019050919050565b5f6020820190508181035f83015261561a816155e1565b9050919050565b7f496e73756666696369656e7420616c6c6f77616e6365000000000000000000005f82015250565b5f615655601683615430565b915061566082615621565b602082019050919050565b5f6020820190508181035f83015261568281615649565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6156c082615370565b91506156cb83615370565b92508282039050818111156156e3576156e2615689565b5b92915050565b5f6156f382615370565b91506156fe83615370565b925082820190508082111561571657615715615689565b5b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f600282049050600182168061576057607f821691505b6020821081036157735761577261571c565b5b50919050565b7f41000000000000000000000000000000000000000000000000000000000000005f82015250565b5f6157ad600183615430565b91506157b882615779565b602082019050919050565b5f6020820190508181035f8301526157da816157a1565b9050919050565b7f42000000000000000000000000000000000000000000000000000000000000005f82015250565b5f615815600183615430565b9150615820826157e1565b602082019050919050565b5f6020820190508181035f83015261584281615809565b905091905056fea2646970667358221220ce03f2ea0f8ec341a07b9c0512b41f44d879b740c55b3572c5707216663e8a3f64736f6c634300081e0033 \ No newline at end of file diff --git a/scenarios/statebloat/contract_deploy/contract/StateBloatToken.go b/scenarios/statebloat/contract_deploy/contract/StateBloatToken.go index bfb58592..f744e474 100644 --- a/scenarios/statebloat/contract_deploy/contract/StateBloatToken.go +++ b/scenarios/statebloat/contract_deploy/contract/StateBloatToken.go @@ -31,8 +31,8 @@ var ( // 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\":\"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\"}]", - Bin: "0x60a060405234801561000f575f5ffd5b50604051611503380380611503833981810160405281019061003191906101f4565b6040518060400160405280601181526020017f537461746520426c6f617420546f6b656e0000000000000000000000000000008152505f90816100749190610453565b506040518060400160405280600381526020017f5342540000000000000000000000000000000000000000000000000000000000815250600190816100b99190610453565b50601260025f6101000a81548160ff021916908360ff160217905550806080818152505060025f9054906101000a900460ff16600a6100f8919061068a565b620f424061010691906106d4565b60038190555060035460045f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055503373ffffffffffffffffffffffffffffffffffffffff165f73ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef6003546040516101af9190610724565b60405180910390a35061073d565b5f5ffd5b5f819050919050565b6101d3816101c1565b81146101dd575f5ffd5b50565b5f815190506101ee816101ca565b92915050565b5f60208284031215610209576102086101bd565b5b5f610216848285016101e0565b91505092915050565b5f81519050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f600282049050600182168061029a57607f821691505b6020821081036102ad576102ac610256565b5b50919050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f6008830261030f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff826102d4565b61031986836102d4565b95508019841693508086168417925050509392505050565b5f819050919050565b5f61035461034f61034a846101c1565b610331565b6101c1565b9050919050565b5f819050919050565b61036d8361033a565b6103816103798261035b565b8484546102e0565b825550505050565b5f5f905090565b610398610389565b6103a3818484610364565b505050565b5b818110156103c6576103bb5f82610390565b6001810190506103a9565b5050565b601f82111561040b576103dc816102b3565b6103e5846102c5565b810160208510156103f4578190505b610408610400856102c5565b8301826103a8565b50505b505050565b5f82821c905092915050565b5f61042b5f1984600802610410565b1980831691505092915050565b5f610443838361041c565b9150826002028217905092915050565b61045c8261021f565b67ffffffffffffffff81111561047557610474610229565b5b61047f8254610283565b61048a8282856103ca565b5f60209050601f8311600181146104bb575f84156104a9578287015190505b6104b38582610438565b86555061051a565b601f1984166104c9866102b3565b5f5b828110156104f0578489015182556001820191506020850194506020810190506104cb565b8683101561050d5784890151610509601f89168261041c565b8355505b6001600288020188555050505b505050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f8160011c9050919050565b5f5f8291508390505b60018511156105a4578086048111156105805761057f610522565b5b600185161561058f5780820291505b808102905061059d8561054f565b9450610564565b94509492505050565b5f826105bc5760019050610677565b816105c9575f9050610677565b81600181146105df57600281146105e957610618565b6001915050610677565b60ff8411156105fb576105fa610522565b5b8360020a91508482111561061257610611610522565b5b50610677565b5060208310610133831016604e8410600b841016171561064d5782820a90508381111561064857610647610522565b5b610677565b61065a848484600161055b565b9250905081840481111561067157610670610522565b5b81810290505b9392505050565b5f60ff82169050919050565b5f610694826101c1565b915061069f8361067e565b92506106cc7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff84846105ad565b905092915050565b5f6106de826101c1565b91506106e9836101c1565b92508282026106f7816101c1565b9150828204841483151761070e5761070d610522565b5b5092915050565b61071e816101c1565b82525050565b5f6020820190506107375f830184610715565b92915050565b608051610dae6107555f395f6108cf0152610dae5ff3fe608060405234801561000f575f5ffd5b506004361061009c575f3560e01c806370a082311161006457806370a082311461015a57806395d89b411461018a578063a9059cbb146101a8578063bfa0b133146101d8578063dd62ed3e146101f65761009c565b806306fdde03146100a0578063095ea7b3146100be57806318160ddd146100ee57806323b872dd1461010c578063313ce5671461013c575b5f5ffd5b6100a8610226565b6040516100b59190610981565b60405180910390f35b6100d860048036038101906100d39190610a32565b6102b1565b6040516100e59190610a8a565b60405180910390f35b6100f661039e565b6040516101039190610ab2565b60405180910390f35b61012660048036038101906101219190610acb565b6103a4565b6040516101339190610a8a565b60405180910390f35b610144610684565b6040516101519190610b36565b60405180910390f35b610174600480360381019061016f9190610b4f565b610696565b6040516101819190610ab2565b60405180910390f35b6101926106ab565b60405161019f9190610981565b60405180910390f35b6101c260048036038101906101bd9190610a32565b610737565b6040516101cf9190610a8a565b60405180910390f35b6101e06108cd565b6040516101ed9190610ab2565b60405180910390f35b610210600480360381019061020b9190610b7a565b6108f1565b60405161021d9190610ab2565b60405180910390f35b5f805461023290610be5565b80601f016020809104026020016040519081016040528092919081815260200182805461025e90610be5565b80156102a95780601f10610280576101008083540402835291602001916102a9565b820191905f5260205f20905b81548152906001019060200180831161028c57829003601f168201915b505050505081565b5f8160055f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9258460405161038c9190610ab2565b60405180910390a36001905092915050565b60035481565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015610425576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161041c90610c5f565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156104e0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104d790610cc7565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461052c9190610d12565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461057f9190610d45565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461060d9190610d12565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516106719190610ab2565b60405180910390a3600190509392505050565b60025f9054906101000a900460ff1681565b6004602052805f5260405f205f915090505481565b600180546106b890610be5565b80601f01602080910402602001604051908101604052809291908181526020018280546106e490610be5565b801561072f5780601f106107065761010080835404028352916020019161072f565b820191905f5260205f20905b81548152906001019060200180831161071257829003601f168201915b505050505081565b5f8160045f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156107b8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016107af90610c5f565b60405180910390fd5b8160045f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546108049190610d12565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546108579190610d45565b925050819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516108bb9190610ab2565b60405180910390a36001905092915050565b7f000000000000000000000000000000000000000000000000000000000000000081565b6005602052815f5260405f20602052805f5260405f205f91509150505481565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f61095382610911565b61095d818561091b565b935061096d81856020860161092b565b61097681610939565b840191505092915050565b5f6020820190508181035f8301526109998184610949565b905092915050565b5f5ffd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6109ce826109a5565b9050919050565b6109de816109c4565b81146109e8575f5ffd5b50565b5f813590506109f9816109d5565b92915050565b5f819050919050565b610a11816109ff565b8114610a1b575f5ffd5b50565b5f81359050610a2c81610a08565b92915050565b5f5f60408385031215610a4857610a476109a1565b5b5f610a55858286016109eb565b9250506020610a6685828601610a1e565b9150509250929050565b5f8115159050919050565b610a8481610a70565b82525050565b5f602082019050610a9d5f830184610a7b565b92915050565b610aac816109ff565b82525050565b5f602082019050610ac55f830184610aa3565b92915050565b5f5f5f60608486031215610ae257610ae16109a1565b5b5f610aef868287016109eb565b9350506020610b00868287016109eb565b9250506040610b1186828701610a1e565b9150509250925092565b5f60ff82169050919050565b610b3081610b1b565b82525050565b5f602082019050610b495f830184610b27565b92915050565b5f60208284031215610b6457610b636109a1565b5b5f610b71848285016109eb565b91505092915050565b5f5f60408385031215610b9057610b8f6109a1565b5b5f610b9d858286016109eb565b9250506020610bae858286016109eb565b9150509250929050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f6002820490506001821680610bfc57607f821691505b602082108103610c0f57610c0e610bb8565b5b50919050565b7f496e73756666696369656e742062616c616e63650000000000000000000000005f82015250565b5f610c4960148361091b565b9150610c5482610c15565b602082019050919050565b5f6020820190508181035f830152610c7681610c3d565b9050919050565b7f496e73756666696369656e7420616c6c6f77616e6365000000000000000000005f82015250565b5f610cb160168361091b565b9150610cbc82610c7d565b602082019050919050565b5f6020820190508181035f830152610cde81610ca5565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f610d1c826109ff565b9150610d27836109ff565b9250828203905081811115610d3f57610d3e610ce5565b5b92915050565b5f610d4f826109ff565b9150610d5a836109ff565b9250828201905080821115610d7257610d71610ce5565b5b9291505056fea26469706673582212207182ee741671c2a140c5eb4e62cb72b950c446fa68846143d961b62f544f59c764736f6c634300081e0033", + 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\":\"dummy66\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dummy67\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dummy68\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dummy69\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dummy7\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dummy70\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dummy71\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dummy72\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dummy73\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dummy74\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dummy75\",\"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: "0x60a060405234801561000f575f5ffd5b50604051615fd4380380615fd4833981810160405281019061003191906101f4565b6040518060400160405280601181526020017f537461746520426c6f617420546f6b656e0000000000000000000000000000008152505f90816100749190610453565b506040518060400160405280600381526020017f5342540000000000000000000000000000000000000000000000000000000000815250600190816100b99190610453565b50601260025f6101000a81548160ff021916908360ff160217905550806080818152505060025f9054906101000a900460ff16600a6100f8919061068a565b620f424061010691906106d4565b60038190555060035460045f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055503373ffffffffffffffffffffffffffffffffffffffff165f73ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef6003546040516101af9190610724565b60405180910390a35061073d565b5f5ffd5b5f819050919050565b6101d3816101c1565b81146101dd575f5ffd5b50565b5f815190506101ee816101ca565b92915050565b5f60208284031215610209576102086101bd565b5b5f610216848285016101e0565b91505092915050565b5f81519050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f600282049050600182168061029a57607f821691505b6020821081036102ad576102ac610256565b5b50919050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f6008830261030f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff826102d4565b61031986836102d4565b95508019841693508086168417925050509392505050565b5f819050919050565b5f61035461034f61034a846101c1565b610331565b6101c1565b9050919050565b5f819050919050565b61036d8361033a565b6103816103798261035b565b8484546102e0565b825550505050565b5f5f905090565b610398610389565b6103a3818484610364565b505050565b5b818110156103c6576103bb5f82610390565b6001810190506103a9565b5050565b601f82111561040b576103dc816102b3565b6103e5846102c5565b810160208510156103f4578190505b610408610400856102c5565b8301826103a8565b50505b505050565b5f82821c905092915050565b5f61042b5f1984600802610410565b1980831691505092915050565b5f610443838361041c565b9150826002028217905092915050565b61045c8261021f565b67ffffffffffffffff81111561047557610474610229565b5b61047f8254610283565b61048a8282856103ca565b5f60209050601f8311600181146104bb575f84156104a9578287015190505b6104b38582610438565b86555061051a565b601f1984166104c9866102b3565b5f5b828110156104f0578489015182556001820191506020850194506020810190506104cb565b8683101561050d5784890151610509601f89168261041c565b8355505b6001600288020188555050505b505050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f8160011c9050919050565b5f5f8291508390505b60018511156105a4578086048111156105805761057f610522565b5b600185161561058f5780820291505b808102905061059d8561054f565b9450610564565b94509492505050565b5f826105bc5760019050610677565b816105c9575f9050610677565b81600181146105df57600281146105e957610618565b6001915050610677565b60ff8411156105fb576105fa610522565b5b8360020a91508482111561061257610611610522565b5b50610677565b5060208310610133831016604e8410600b841016171561064d5782820a90508381111561064857610647610522565b5b610677565b61065a848484600161055b565b9250905081840481111561067157610670610522565b5b81810290505b9392505050565b5f60ff82169050919050565b5f610694826101c1565b915061069f8361067e565b92506106cc7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff84846105ad565b905092915050565b5f6106de826101c1565b91506106e9836101c1565b92508282026106f7816101c1565b9150828204841483151761070e5761070d610522565b5b5092915050565b61071e816101c1565b82525050565b5f6020820190506107375f830184610715565b92915050565b60805161587f6107555f395f614a7b015261587f5ff3fe608060405234801561000f575f5ffd5b5060043610610606575f3560e01c8063657b6ef711610319578063b1802b9a116101a6578063d9bb3174116100f2578063f26c779b116100ab578063f8716f1411610085578063f8716f1414611360578063faf35ced1461137e578063fe7d5996146113ae578063ffbf0469146113cc57610606565b8063f26c779b14611306578063f4978b0414611324578063f5f573811461134257610606565b8063d9bb31741461122e578063dc1d8a9b1461124c578063dd62ed3e1461126a578063e2d275301461129a578063e8c927b3146112b8578063eb4329c8146112d657610606565b8063bbe231321161015f578063c958d4bf11610139578063c958d4bf146111b6578063cfd66863146111d4578063d101dcd0146111f2578063d74194691461121057610606565b8063bbe231321461114a578063bfa0b13314611168578063c2be97e31461118657610606565b8063b1802b9a14611072578063b2bb360e146110a2578063b4c48668146110c0578063b66dd750146110de578063b9a6d645146110fc578063bb9bfe061461111a57610606565b80637e544937116102655780639c5dfe731161021e578063a9059cbb116101f8578063a9059cbb14610fd6578063aaa7af7014611006578063acc5aee914611024578063ad8f42211461105457610606565b80639c5dfe7314610f7c5780639df61a2514610f9a578063a891d4d414610fb857610606565b80637e54493714610eb65780637f34d94b14610ed45780638619d60714610ef25780638789ca6714610f105780638f4a840614610f4057806395d89b4114610f5e57610606565b806374f83d02116102d25780637a319c18116102ac5780637a319c1814610e2c5780637c66673e14610e4a5780637c72ed0d14610e7a5780637dffdc3214610e9857610606565b806374f83d0214610dd257806377c0209e14610df0578063792c7f3e14610e0e57610606565b8063657b6ef714610ce8578063672151fe14610d185780636abceacd14610d365780636c12ed2814610d5457806370a0823114610d8457806374e73fd314610db457610606565b8063313ce567116104975780634b3c7f5f116103e357806358b6a9bd1161039c57806361b970eb1161037657806361b970eb14610c70578063639ec53a14610c8e5780636547317414610cac5780636578534c14610cca57610606565b806358b6a9bd14610c16578063595471b814610c345780635af92c0514610c5257610606565b80634b3c7f5f14610b3e5780634e1dbb8214610b5c5780634f5e555714610b7a5780634f7bd75a14610b9857806354c2792014610bc8578063552a1b5614610be657610606565b80633ea117ce1161045057806342937dbd1161042a57806342937dbd14610ab457806343a6b92d14610ad257806344050a2814610af05780634a2e93c614610b2057610606565b80633ea117ce14610a5a5780634128a85d14610a78578063418b181614610a9657610606565b8063313ce5671461098257806334517f0b146109a0578063378c5382146109be57806339e0bd12146109dc5780633a13199014610a0c5780633b6be45914610a3c57610606565b80631bbffe6f1161055657806321ecd7a31161050f5780632545d8b7116104e95780632545d8b7146108f85780632787325b14610916578063291c3bd7146109345780633125f37a1461096457610606565b806321ecd7a31461088c578063239af2a5146108aa57806323b872dd146108c857610606565b80631bbffe6f146107c65780631d527cde146107f65780631eaa7c52146108145780631f29783f146108325780631f449589146108505780631fd298ec1461086e57610606565b806312901b42116105c357806318160ddd1161059d57806318160ddd1461073c57806319cf6a911461075a5780631a97f18e146107785780631b17c65c1461079657610606565b806312901b42146106e257806313ebb5ec1461070057806316a3045b1461071e57610606565b80630460faf61461060a57806306fdde031461063a5780630717b16114610658578063095ea7b3146106765780630cb7a9e7146106a65780631215a3ab146106c4575b5f5ffd5b610624600480360381019061061f91906153a3565b6113ea565b604051610631919061540d565b60405180910390f35b6106426116ca565b60405161064f9190615496565b60405180910390f35b610660611755565b60405161066d91906154c5565b60405180910390f35b610690600480360381019061068b91906154de565b61175d565b60405161069d919061540d565b60405180910390f35b6106ae61184a565b6040516106bb91906154c5565b60405180910390f35b6106cc611852565b6040516106d991906154c5565b60405180910390f35b6106ea61185a565b6040516106f791906154c5565b60405180910390f35b610708611862565b60405161071591906154c5565b60405180910390f35b61072661186a565b60405161073391906154c5565b60405180910390f35b610744611872565b60405161075191906154c5565b60405180910390f35b610762611878565b60405161076f91906154c5565b60405180910390f35b610780611880565b60405161078d91906154c5565b60405180910390f35b6107b060048036038101906107ab91906153a3565b611888565b6040516107bd919061540d565b60405180910390f35b6107e060048036038101906107db91906153a3565b611b68565b6040516107ed919061540d565b60405180910390f35b6107fe611e48565b60405161080b91906154c5565b60405180910390f35b61081c611e50565b60405161082991906154c5565b60405180910390f35b61083a611e58565b60405161084791906154c5565b60405180910390f35b610858611e60565b60405161086591906154c5565b60405180910390f35b610876611e68565b60405161088391906154c5565b60405180910390f35b610894611e70565b6040516108a191906154c5565b60405180910390f35b6108b2611e78565b6040516108bf91906154c5565b60405180910390f35b6108e260048036038101906108dd91906153a3565b611e80565b6040516108ef919061540d565b60405180910390f35b610900612160565b60405161090d91906154c5565b60405180910390f35b61091e612168565b60405161092b91906154c5565b60405180910390f35b61094e600480360381019061094991906153a3565b612170565b60405161095b919061540d565b60405180910390f35b61096c612450565b60405161097991906154c5565b60405180910390f35b61098a612458565b6040516109979190615537565b60405180910390f35b6109a861246a565b6040516109b591906154c5565b60405180910390f35b6109c6612472565b6040516109d391906154c5565b60405180910390f35b6109f660048036038101906109f191906153a3565b61247a565b604051610a03919061540d565b60405180910390f35b610a266004803603810190610a2191906153a3565b61275a565b604051610a33919061540d565b60405180910390f35b610a44612a3a565b604051610a5191906154c5565b60405180910390f35b610a62612a42565b604051610a6f91906154c5565b60405180910390f35b610a80612a4a565b604051610a8d91906154c5565b60405180910390f35b610a9e612a52565b604051610aab91906154c5565b60405180910390f35b610abc612a5a565b604051610ac991906154c5565b60405180910390f35b610ada612a62565b604051610ae791906154c5565b60405180910390f35b610b0a6004803603810190610b0591906153a3565b612a6a565b604051610b17919061540d565b60405180910390f35b610b28612d4a565b604051610b3591906154c5565b60405180910390f35b610b46612d52565b604051610b5391906154c5565b60405180910390f35b610b64612d5a565b604051610b7191906154c5565b60405180910390f35b610b82612d62565b604051610b8f91906154c5565b60405180910390f35b610bb26004803603810190610bad91906153a3565b612d6a565b604051610bbf919061540d565b60405180910390f35b610bd061304a565b604051610bdd91906154c5565b60405180910390f35b610c006004803603810190610bfb91906153a3565b613052565b604051610c0d919061540d565b60405180910390f35b610c1e613332565b604051610c2b91906154c5565b60405180910390f35b610c3c61333a565b604051610c4991906154c5565b60405180910390f35b610c5a613342565b604051610c6791906154c5565b60405180910390f35b610c7861334a565b604051610c8591906154c5565b60405180910390f35b610c96613352565b604051610ca391906154c5565b60405180910390f35b610cb461335a565b604051610cc191906154c5565b60405180910390f35b610cd2613362565b604051610cdf91906154c5565b60405180910390f35b610d026004803603810190610cfd91906153a3565b61336a565b604051610d0f919061540d565b60405180910390f35b610d2061364a565b604051610d2d91906154c5565b60405180910390f35b610d3e613652565b604051610d4b91906154c5565b60405180910390f35b610d6e6004803603810190610d6991906153a3565b61365a565b604051610d7b919061540d565b60405180910390f35b610d9e6004803603810190610d999190615550565b61393a565b604051610dab91906154c5565b60405180910390f35b610dbc61394f565b604051610dc991906154c5565b60405180910390f35b610dda613957565b604051610de791906154c5565b60405180910390f35b610df861395f565b604051610e0591906154c5565b60405180910390f35b610e16613967565b604051610e2391906154c5565b60405180910390f35b610e3461396f565b604051610e4191906154c5565b60405180910390f35b610e646004803603810190610e5f91906153a3565b613977565b604051610e71919061540d565b60405180910390f35b610e82613c57565b604051610e8f91906154c5565b60405180910390f35b610ea0613c5f565b604051610ead91906154c5565b60405180910390f35b610ebe613c67565b604051610ecb91906154c5565b60405180910390f35b610edc613c6f565b604051610ee991906154c5565b60405180910390f35b610efa613c77565b604051610f0791906154c5565b60405180910390f35b610f2a6004803603810190610f2591906153a3565b613c7f565b604051610f37919061540d565b60405180910390f35b610f48613f5f565b604051610f5591906154c5565b60405180910390f35b610f66613f67565b604051610f739190615496565b60405180910390f35b610f84613ff3565b604051610f9191906154c5565b60405180910390f35b610fa2613ffb565b604051610faf91906154c5565b60405180910390f35b610fc0614003565b604051610fcd91906154c5565b60405180910390f35b610ff06004803603810190610feb91906154de565b61400b565b604051610ffd919061540d565b60405180910390f35b61100e6141a1565b60405161101b91906154c5565b60405180910390f35b61103e600480360381019061103991906153a3565b6141a9565b60405161104b919061540d565b60405180910390f35b61105c614489565b60405161106991906154c5565b60405180910390f35b61108c600480360381019061108791906153a3565b614491565b604051611099919061540d565b60405180910390f35b6110aa614771565b6040516110b791906154c5565b60405180910390f35b6110c8614779565b6040516110d591906154c5565b60405180910390f35b6110e6614781565b6040516110f391906154c5565b60405180910390f35b611104614789565b60405161111191906154c5565b60405180910390f35b611134600480360381019061112f91906153a3565b614791565b604051611141919061540d565b60405180910390f35b611152614a71565b60405161115f91906154c5565b60405180910390f35b611170614a79565b60405161117d91906154c5565b60405180910390f35b6111a0600480360381019061119b91906153a3565b614a9d565b6040516111ad919061540d565b60405180910390f35b6111be614d7d565b6040516111cb91906154c5565b60405180910390f35b6111dc614d85565b6040516111e991906154c5565b60405180910390f35b6111fa614d8d565b60405161120791906154c5565b60405180910390f35b611218614d95565b60405161122591906154c5565b60405180910390f35b611236614d9d565b60405161124391906154c5565b60405180910390f35b611254614da5565b60405161126191906154c5565b60405180910390f35b611284600480360381019061127f919061557b565b614dad565b60405161129191906154c5565b60405180910390f35b6112a2614dcd565b6040516112af91906154c5565b60405180910390f35b6112c0614dd5565b6040516112cd91906154c5565b60405180910390f35b6112f060048036038101906112eb91906153a3565b614ddd565b6040516112fd919061540d565b60405180910390f35b61130e615002565b60405161131b91906154c5565b60405180910390f35b61132c61500a565b60405161133991906154c5565b60405180910390f35b61134a615012565b60405161135791906154c5565b60405180910390f35b61136861501a565b60405161137591906154c5565b60405180910390f35b611398600480360381019061139391906153a3565b615022565b6040516113a5919061540d565b60405180910390f35b6113b6615302565b6040516113c391906154c5565b60405180910390f35b6113d461530a565b6040516113e191906154c5565b60405180910390f35b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054101561146b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161146290615603565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015611526576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161151d9061566b565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461157291906156b6565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546115c591906156e9565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461165391906156b6565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516116b791906154c5565b60405180910390a3600190509392505050565b5f80546116d690615749565b80601f016020809104026020016040519081016040528092919081815260200182805461170290615749565b801561174d5780601f106117245761010080835404028352916020019161174d565b820191905f5260205f20905b81548152906001019060200180831161173057829003601f168201915b505050505081565b5f602f905090565b5f8160055f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9258460405161183891906154c5565b60405180910390a36001905092915050565b5f601b905090565b5f6005905090565b5f601a905090565b5f601d905090565b5f6033905090565b60035481565b5f6008905090565b5f6003905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015611909576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161190090615603565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156119c4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119bb9061566b565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254611a1091906156b6565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254611a6391906156e9565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254611af191906156b6565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051611b5591906154c5565b60405180910390a3600190509392505050565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015611be9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611be090615603565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015611ca4576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c9b9061566b565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254611cf091906156b6565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254611d4391906156e9565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254611dd191906156b6565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051611e3591906154c5565b60405180910390a3600190509392505050565b5f6002905090565b5f6010905090565b5f6048905090565b5f6041905090565b5f6035905090565b5f602e905090565b5f602c905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015611f01576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ef890615603565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015611fbc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611fb39061566b565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461200891906156b6565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461205b91906156e9565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546120e991906156b6565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161214d91906154c5565b60405180910390a3600190509392505050565b5f6001905090565b5f6045905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156121f1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016121e8906157c3565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156122ac576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016122a39061582b565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546122f891906156b6565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461234b91906156e9565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546123d991906156b6565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161243d91906154c5565b60405180910390a3600190509392505050565b5f6034905090565b60025f9054906101000a900460ff1681565b5f603c905090565b5f604b905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156124fb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016124f290615603565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156125b6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016125ad9061566b565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461260291906156b6565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461265591906156e9565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546126e391906156b6565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161274791906154c5565b60405180910390a3600190509392505050565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156127db576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016127d290615603565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015612896576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161288d9061566b565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546128e291906156b6565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461293591906156e9565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546129c391906156b6565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051612a2791906154c5565b60405180910390a3600190509392505050565b5f6004905090565b5f600c905090565b5f6006905090565b5f601c905090565b5f6032905090565b5f6023905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015612aeb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612ae290615603565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015612ba6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612b9d9061566b565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254612bf291906156b6565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254612c4591906156e9565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254612cd391906156b6565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051612d3791906154c5565b60405180910390a3600190509392505050565b5f6011905090565b5f6021905090565b5f601f905090565b5f6026905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015612deb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612de290615603565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015612ea6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612e9d9061566b565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254612ef291906156b6565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254612f4591906156e9565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254612fd391906156b6565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161303791906154c5565b60405180910390a3600190509392505050565b5f603a905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156130d3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016130ca90615603565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054101561318e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016131859061566b565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546131da91906156b6565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461322d91906156e9565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546132bb91906156b6565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161331f91906154c5565b60405180910390a3600190509392505050565b5f6009905090565b5f6049905090565b5f602a905090565b5f6014905090565b5f6025905090565b5f6013905090565b5f6043905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156133eb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016133e2906157c3565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156134a6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161349d9061582b565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546134f291906156b6565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461354591906156e9565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546135d391906156b6565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161363791906154c5565b60405180910390a3600190509392505050565b5f600d905090565b5f6017905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156136db576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016136d290615603565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015613796576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161378d9061566b565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546137e291906156b6565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461383591906156e9565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546138c391906156b6565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161392791906154c5565b60405180910390a3600190509392505050565b6004602052805f5260405f205f915090505481565b5f6016905090565b5f6039905090565b5f603b905090565b5f6036905090565b5f603f905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156139f8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016139ef90615603565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015613ab3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613aaa9061566b565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254613aff91906156b6565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254613b5291906156e9565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254613be091906156b6565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051613c4491906154c5565b60405180910390a3600190509392505050565b5f602b905090565b5f6037905090565b5f600a905090565b5f602d905090565b5f6030905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015613d00576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613cf790615603565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015613dbb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613db29061566b565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254613e0791906156b6565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254613e5a91906156e9565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254613ee891906156b6565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051613f4c91906154c5565b60405180910390a3600190509392505050565b5f600b905090565b60018054613f7490615749565b80601f0160208091040260200160405190810160405280929190818152602001828054613fa090615749565b8015613feb5780601f10613fc257610100808354040283529160200191613feb565b820191905f5260205f20905b815481529060010190602001808311613fce57829003601f168201915b505050505081565b5f6015905090565b5f6029905090565b5f6038905090565b5f8160045f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054101561408c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161408390615603565b60405180910390fd5b8160045f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546140d891906156b6565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461412b91906156e9565b925050819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161418f91906154c5565b60405180910390a36001905092915050565b5f6028905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054101561422a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161422190615603565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156142e5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016142dc9061566b565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461433191906156b6565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461438491906156e9565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461441291906156b6565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161447691906154c5565b60405180910390a3600190509392505050565b5f6040905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015614512576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161450990615603565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156145cd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016145c49061566b565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461461991906156b6565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461466c91906156e9565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546146fa91906156b6565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161475e91906154c5565b60405180910390a3600190509392505050565b5f6018905090565b5f604a905090565b5f600f905090565b5f6044905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015614812576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161480990615603565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156148cd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016148c49061566b565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461491991906156b6565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461496c91906156e9565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546149fa91906156b6565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051614a5e91906154c5565b60405180910390a3600190509392505050565b5f6046905090565b7f000000000000000000000000000000000000000000000000000000000000000081565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015614b1e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401614b1590615603565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015614bd9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401614bd09061566b565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254614c2591906156b6565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254614c7891906156e9565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254614d0691906156b6565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051614d6a91906154c5565b60405180910390a3600190509392505050565b5f6024905090565b5f601e905090565b5f6031905090565b5f6019905090565b5f6042905090565b5f6027905090565b6005602052815f5260405f20602052805f5260405f205f91509150505481565b5f603d905090565b5f6022905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015614e5e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401614e55906157c3565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254614eaa91906156b6565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254614efd91906156e9565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254614f8b91906156b6565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051614fef91906154c5565b60405180910390a3600190509392505050565b5f6007905090565b5f6047905090565b5f603e905090565b5f6020905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156150a3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161509a90615603565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054101561515e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016151559061566b565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546151aa91906156b6565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546151fd91906156e9565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461528b91906156b6565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516152ef91906154c5565b60405180910390a3600190509392505050565b5f600e905090565b5f6012905090565b5f5ffd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f61533f82615316565b9050919050565b61534f81615335565b8114615359575f5ffd5b50565b5f8135905061536a81615346565b92915050565b5f819050919050565b61538281615370565b811461538c575f5ffd5b50565b5f8135905061539d81615379565b92915050565b5f5f5f606084860312156153ba576153b9615312565b5b5f6153c78682870161535c565b93505060206153d88682870161535c565b92505060406153e98682870161538f565b9150509250925092565b5f8115159050919050565b615407816153f3565b82525050565b5f6020820190506154205f8301846153fe565b92915050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f61546882615426565b6154728185615430565b9350615482818560208601615440565b61548b8161544e565b840191505092915050565b5f6020820190508181035f8301526154ae818461545e565b905092915050565b6154bf81615370565b82525050565b5f6020820190506154d85f8301846154b6565b92915050565b5f5f604083850312156154f4576154f3615312565b5b5f6155018582860161535c565b92505060206155128582860161538f565b9150509250929050565b5f60ff82169050919050565b6155318161551c565b82525050565b5f60208201905061554a5f830184615528565b92915050565b5f6020828403121561556557615564615312565b5b5f6155728482850161535c565b91505092915050565b5f5f6040838503121561559157615590615312565b5b5f61559e8582860161535c565b92505060206155af8582860161535c565b9150509250929050565b7f496e73756666696369656e742062616c616e63650000000000000000000000005f82015250565b5f6155ed601483615430565b91506155f8826155b9565b602082019050919050565b5f6020820190508181035f83015261561a816155e1565b9050919050565b7f496e73756666696369656e7420616c6c6f77616e6365000000000000000000005f82015250565b5f615655601683615430565b915061566082615621565b602082019050919050565b5f6020820190508181035f83015261568281615649565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6156c082615370565b91506156cb83615370565b92508282039050818111156156e3576156e2615689565b5b92915050565b5f6156f382615370565b91506156fe83615370565b925082820190508082111561571657615715615689565b5b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f600282049050600182168061576057607f821691505b6020821081036157735761577261571c565b5b50919050565b7f41000000000000000000000000000000000000000000000000000000000000005f82015250565b5f6157ad600183615430565b91506157b882615779565b602082019050919050565b5f6020820190508181035f8301526157da816157a1565b9050919050565b7f42000000000000000000000000000000000000000000000000000000000000005f82015250565b5f615815600183615430565b9150615820826157e1565b602082019050919050565b5f6020820190508181035f83015261584281615809565b905091905056fea2646970667358221220ce03f2ea0f8ec341a07b9c0512b41f44d879b740c55b3572c5707216663e8a3f64736f6c634300081e0033", } // ContractABI is the input ABI used to generate the binding from. @@ -295,6 +295,2331 @@ 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) +} + +// Dummy66 is a free data retrieval call binding the contract method 0xd9bb3174. +// +// Solidity: function dummy66() pure returns(uint256) +func (_Contract *ContractCaller) Dummy66(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Contract.contract.Call(opts, &out, "dummy66") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// Dummy66 is a free data retrieval call binding the contract method 0xd9bb3174. +// +// Solidity: function dummy66() pure returns(uint256) +func (_Contract *ContractSession) Dummy66() (*big.Int, error) { + return _Contract.Contract.Dummy66(&_Contract.CallOpts) +} + +// Dummy66 is a free data retrieval call binding the contract method 0xd9bb3174. +// +// Solidity: function dummy66() pure returns(uint256) +func (_Contract *ContractCallerSession) Dummy66() (*big.Int, error) { + return _Contract.Contract.Dummy66(&_Contract.CallOpts) +} + +// Dummy67 is a free data retrieval call binding the contract method 0x6578534c. +// +// Solidity: function dummy67() pure returns(uint256) +func (_Contract *ContractCaller) Dummy67(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Contract.contract.Call(opts, &out, "dummy67") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// Dummy67 is a free data retrieval call binding the contract method 0x6578534c. +// +// Solidity: function dummy67() pure returns(uint256) +func (_Contract *ContractSession) Dummy67() (*big.Int, error) { + return _Contract.Contract.Dummy67(&_Contract.CallOpts) +} + +// Dummy67 is a free data retrieval call binding the contract method 0x6578534c. +// +// Solidity: function dummy67() pure returns(uint256) +func (_Contract *ContractCallerSession) Dummy67() (*big.Int, error) { + return _Contract.Contract.Dummy67(&_Contract.CallOpts) +} + +// Dummy68 is a free data retrieval call binding the contract method 0xb9a6d645. +// +// Solidity: function dummy68() pure returns(uint256) +func (_Contract *ContractCaller) Dummy68(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Contract.contract.Call(opts, &out, "dummy68") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// Dummy68 is a free data retrieval call binding the contract method 0xb9a6d645. +// +// Solidity: function dummy68() pure returns(uint256) +func (_Contract *ContractSession) Dummy68() (*big.Int, error) { + return _Contract.Contract.Dummy68(&_Contract.CallOpts) +} + +// Dummy68 is a free data retrieval call binding the contract method 0xb9a6d645. +// +// Solidity: function dummy68() pure returns(uint256) +func (_Contract *ContractCallerSession) Dummy68() (*big.Int, error) { + return _Contract.Contract.Dummy68(&_Contract.CallOpts) +} + +// Dummy69 is a free data retrieval call binding the contract method 0x2787325b. +// +// Solidity: function dummy69() pure returns(uint256) +func (_Contract *ContractCaller) Dummy69(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Contract.contract.Call(opts, &out, "dummy69") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// Dummy69 is a free data retrieval call binding the contract method 0x2787325b. +// +// Solidity: function dummy69() pure returns(uint256) +func (_Contract *ContractSession) Dummy69() (*big.Int, error) { + return _Contract.Contract.Dummy69(&_Contract.CallOpts) +} + +// Dummy69 is a free data retrieval call binding the contract method 0x2787325b. +// +// Solidity: function dummy69() pure returns(uint256) +func (_Contract *ContractCallerSession) Dummy69() (*big.Int, error) { + return _Contract.Contract.Dummy69(&_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) +} + +// Dummy70 is a free data retrieval call binding the contract method 0xbbe23132. +// +// Solidity: function dummy70() pure returns(uint256) +func (_Contract *ContractCaller) Dummy70(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Contract.contract.Call(opts, &out, "dummy70") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// Dummy70 is a free data retrieval call binding the contract method 0xbbe23132. +// +// Solidity: function dummy70() pure returns(uint256) +func (_Contract *ContractSession) Dummy70() (*big.Int, error) { + return _Contract.Contract.Dummy70(&_Contract.CallOpts) +} + +// Dummy70 is a free data retrieval call binding the contract method 0xbbe23132. +// +// Solidity: function dummy70() pure returns(uint256) +func (_Contract *ContractCallerSession) Dummy70() (*big.Int, error) { + return _Contract.Contract.Dummy70(&_Contract.CallOpts) +} + +// Dummy71 is a free data retrieval call binding the contract method 0xf4978b04. +// +// Solidity: function dummy71() pure returns(uint256) +func (_Contract *ContractCaller) Dummy71(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Contract.contract.Call(opts, &out, "dummy71") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// Dummy71 is a free data retrieval call binding the contract method 0xf4978b04. +// +// Solidity: function dummy71() pure returns(uint256) +func (_Contract *ContractSession) Dummy71() (*big.Int, error) { + return _Contract.Contract.Dummy71(&_Contract.CallOpts) +} + +// Dummy71 is a free data retrieval call binding the contract method 0xf4978b04. +// +// Solidity: function dummy71() pure returns(uint256) +func (_Contract *ContractCallerSession) Dummy71() (*big.Int, error) { + return _Contract.Contract.Dummy71(&_Contract.CallOpts) +} + +// Dummy72 is a free data retrieval call binding the contract method 0x1f29783f. +// +// Solidity: function dummy72() pure returns(uint256) +func (_Contract *ContractCaller) Dummy72(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Contract.contract.Call(opts, &out, "dummy72") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// Dummy72 is a free data retrieval call binding the contract method 0x1f29783f. +// +// Solidity: function dummy72() pure returns(uint256) +func (_Contract *ContractSession) Dummy72() (*big.Int, error) { + return _Contract.Contract.Dummy72(&_Contract.CallOpts) +} + +// Dummy72 is a free data retrieval call binding the contract method 0x1f29783f. +// +// Solidity: function dummy72() pure returns(uint256) +func (_Contract *ContractCallerSession) Dummy72() (*big.Int, error) { + return _Contract.Contract.Dummy72(&_Contract.CallOpts) +} + +// Dummy73 is a free data retrieval call binding the contract method 0x595471b8. +// +// Solidity: function dummy73() pure returns(uint256) +func (_Contract *ContractCaller) Dummy73(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Contract.contract.Call(opts, &out, "dummy73") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// Dummy73 is a free data retrieval call binding the contract method 0x595471b8. +// +// Solidity: function dummy73() pure returns(uint256) +func (_Contract *ContractSession) Dummy73() (*big.Int, error) { + return _Contract.Contract.Dummy73(&_Contract.CallOpts) +} + +// Dummy73 is a free data retrieval call binding the contract method 0x595471b8. +// +// Solidity: function dummy73() pure returns(uint256) +func (_Contract *ContractCallerSession) Dummy73() (*big.Int, error) { + return _Contract.Contract.Dummy73(&_Contract.CallOpts) +} + +// Dummy74 is a free data retrieval call binding the contract method 0xb4c48668. +// +// Solidity: function dummy74() pure returns(uint256) +func (_Contract *ContractCaller) Dummy74(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Contract.contract.Call(opts, &out, "dummy74") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// Dummy74 is a free data retrieval call binding the contract method 0xb4c48668. +// +// Solidity: function dummy74() pure returns(uint256) +func (_Contract *ContractSession) Dummy74() (*big.Int, error) { + return _Contract.Contract.Dummy74(&_Contract.CallOpts) +} + +// Dummy74 is a free data retrieval call binding the contract method 0xb4c48668. +// +// Solidity: function dummy74() pure returns(uint256) +func (_Contract *ContractCallerSession) Dummy74() (*big.Int, error) { + return _Contract.Contract.Dummy74(&_Contract.CallOpts) +} + +// Dummy75 is a free data retrieval call binding the contract method 0x378c5382. +// +// Solidity: function dummy75() pure returns(uint256) +func (_Contract *ContractCaller) Dummy75(opts *bind.CallOpts) (*big.Int, error) { + var out []interface{} + err := _Contract.contract.Call(opts, &out, "dummy75") + + if err != nil { + return *new(*big.Int), err + } + + out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) + + return out0, err + +} + +// Dummy75 is a free data retrieval call binding the contract method 0x378c5382. +// +// Solidity: function dummy75() pure returns(uint256) +func (_Contract *ContractSession) Dummy75() (*big.Int, error) { + return _Contract.Contract.Dummy75(&_Contract.CallOpts) +} + +// Dummy75 is a free data retrieval call binding the contract method 0x378c5382. +// +// Solidity: function dummy75() pure returns(uint256) +func (_Contract *ContractCallerSession) Dummy75() (*big.Int, error) { + return _Contract.Contract.Dummy75(&_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) @@ -482,6 +2807,405 @@ func (_Contract *ContractTransactorSession) TransferFrom(from common.Address, to 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 diff --git a/scenarios/statebloat/contract_deploy/contract/StateBloatToken.sol b/scenarios/statebloat/contract_deploy/contract/StateBloatToken.sol index 28dc8454..29fe7221 100644 --- a/scenarios/statebloat/contract_deploy/contract/StateBloatToken.sol +++ b/scenarios/statebloat/contract_deploy/contract/StateBloatToken.sol @@ -24,8 +24,6 @@ contract StateBloatToken { symbol = "SBT"; decimals = 18; salt = _salt; - - // Initialize with some state totalSupply = 1000000 * 10 ** decimals; balanceOf[msg.sender] = totalSupply; emit Transfer(address(0), msg.sender, totalSupply); @@ -58,4 +56,570 @@ contract StateBloatToken { 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; + } + + 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 dummy70() public pure returns (uint256) { + return 70; + } + + function dummy71() public pure returns (uint256) { + return 71; + } + + function dummy72() public pure returns (uint256) { + return 72; + } + + function dummy73() public pure returns (uint256) { + return 73; + } + + function dummy74() public pure returns (uint256) { + return 74; + } + + function dummy75() public pure returns (uint256) { + return 75; + } + + 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; + } } From e29266981ff33d80d0e4c366b2087fedfb9113d6 Mon Sep 17 00:00:00 2001 From: CPerezz Date: Fri, 23 May 2025 09:45:47 +0200 Subject: [PATCH 12/26] feat(contract-deploy): enhance contract deployment scenario and logging - Updated the contract deployment scenario to log deployed contract addresses and gas used. - Added functionality to write deployed addresses to a JSON file for easier tracking. - Removed gas-per-block validation and adjusted wallet count logic. - Improved README with instructions for running against a local Anvil node without Go tests. --- README.md | 26 +- scenarios/scenarios.go | 2 + .../statebloat/contract_deploy/README.md | 40 ++- .../contract_deploy/contract_deploy.go | 168 ++++++------- .../contract_deploy/contract_deploy_test.go | 237 ------------------ 5 files changed, 125 insertions(+), 348 deletions(-) delete mode 100644 scenarios/statebloat/contract_deploy/contract_deploy_test.go diff --git a/README.md b/README.md index 8b602c8c..d5dd212f 100644 --- a/README.md +++ b/README.md @@ -29,19 +29,19 @@ All scenarios require: Spamoor provides multiple scenarios for different transaction types: -| Scenario | Description | -|----------|-------------| -| [`eoatx`](./scenarios/eoatx/README.md) | **EOA Transactions**
Send standard EOA transactions with configurable amounts and targets | -| [`erctx`](./scenarios/erctx/README.md) | **ERC20 Transactions**
Deploy a ERC20 contract and transfer tokens | -| [`deploytx`](./scenarios/deploytx/README.md) | **Contract Deployments**
Deploy contracts with custom bytecode | -| [`deploy-destruct`](./scenarios/deploy-destruct/README.md) | **Self-Destruct Deployments**
Deploy contracts that self-destruct | -| [`setcodetx`](./scenarios/setcodetx/README.md) | **Set Code Transactions**
Send EIP-7702 setcode-transactions with various settings | -| [`uniswap-swaps`](./scenarios/uniswap-swaps/README.md) | **Uniswap Swaps**
Deploy and perform token swaps on Uniswap V2 pools | -| [`blobs`](./scenarios/blobs/README.md) | **Blob Transactions**
Send blob transactions with random data | -| [`blob-replacements`](./scenarios/blob-replacements/README.md) | **Blob Replacements**
Send and replace blob transactions | -| [`blob-conflicting`](./scenarios/blob-conflicting/README.md) | **Conflicting Blobs**
Send conflicting blob and normal transactions | -| [`blob-combined`](./scenarios/blob-combined/README.md) | **Combined Blob Testing**
Randomized combination of all blob scenarios | -| [`gasburnertx`](./scenarios/gasburnertx/README.md) | **Gas Burner**
Send transactions that burn specific amounts of gas | +| Scenario | Description | +| -------------------------------------------------------------- | -------------------------------------------------------------------------------------------- | +| [`eoatx`](./scenarios/eoatx/README.md) | **EOA Transactions**
Send standard EOA transactions with configurable amounts and targets | +| [`erctx`](./scenarios/erctx/README.md) | **ERC20 Transactions**
Deploy a ERC20 contract and transfer tokens | +| [`deploytx`](./scenarios/deploytx/README.md) | **Contract Deployments**
Deploy contracts with custom bytecode | +| [`deploy-destruct`](./scenarios/deploy-destruct/README.md) | **Self-Destruct Deployments**
Deploy contracts that self-destruct | +| [`setcodetx`](./scenarios/setcodetx/README.md) | **Set Code Transactions**
Send EIP-7702 setcode-transactions with various settings | +| [`uniswap-swaps`](./scenarios/uniswap-swaps/README.md) | **Uniswap Swaps**
Deploy and perform token swaps on Uniswap V2 pools | +| [`blobs`](./scenarios/blobs/README.md) | **Blob Transactions**
Send blob transactions with random data | +| [`blob-replacements`](./scenarios/blob-replacements/README.md) | **Blob Replacements**
Send and replace blob transactions | +| [`blob-conflicting`](./scenarios/blob-conflicting/README.md) | **Conflicting Blobs**
Send conflicting blob and normal transactions | +| [`blob-combined`](./scenarios/blob-combined/README.md) | **Combined Blob Testing**
Randomized combination of all blob scenarios | +| [`gasburnertx`](./scenarios/gasburnertx/README.md) | **Gas Burner**
Send transactions that burn specific amounts of gas | ## Daemon Mode diff --git a/scenarios/scenarios.go b/scenarios/scenarios.go index e0f32a82..6515fb6f 100644 --- a/scenarios/scenarios.go +++ b/scenarios/scenarios.go @@ -13,6 +13,7 @@ import ( "github.com/ethpandaops/spamoor/scenarios/erctx" "github.com/ethpandaops/spamoor/scenarios/gasburnertx" "github.com/ethpandaops/spamoor/scenarios/setcodetx" + contractdeploy "github.com/ethpandaops/spamoor/scenarios/statebloat/contract_deploy" uniswapswaps "github.com/ethpandaops/spamoor/scenarios/uniswap-swaps" "github.com/ethpandaops/spamoor/scenarios/wallets" ) @@ -30,6 +31,7 @@ var ScenarioDescriptors = []*scenariotypes.ScenarioDescriptor{ &setcodetx.ScenarioDescriptor, &uniswapswaps.ScenarioDescriptor, &wallets.ScenarioDescriptor, + &contractdeploy.ScenarioDescriptor, } func GetScenario(name string) *scenariotypes.ScenarioDescriptor { diff --git a/scenarios/statebloat/contract_deploy/README.md b/scenarios/statebloat/contract_deploy/README.md index ecd830a7..e6b70c0e 100644 --- a/scenarios/statebloat/contract_deploy/README.md +++ b/scenarios/statebloat/contract_deploy/README.md @@ -58,23 +58,43 @@ Deploy 1 contract per slot: spamoor statebloat/contract-deploy -p "" -h http://localhost:8545 -t 1 ``` -## Testing with Anvil +## Running Against a Local Anvil Node (without Go tests) + +You can run this scenario directly against your own Anvil node using the Spamoor CLI, without running Go tests. + +### 1. Start Anvil -1. Start Anvil: ```bash -anvil +anvil --hardfork pectra ``` -2. Run the scenario: +You can add other flags as needed (e.g., `--no-mining` if you want to control mining manually). + +### 2. Build Spamoor (if not already built) + ```bash -spamoor statebloat/contract-deploy -p "" -h http://localhost:8545 -c 1 +go build -o spamoor ./cmd/spamoor ``` -3. Verify state growth: +### 3. Run the Scenario + ```bash -# Get the contract address from the deployment receipt -# Then check the code size -cast code --rpc-url http://localhost:8545 +./spamoor statebloat/contract-deploy \ + --privkey \ + --rpchost http://localhost:8545 \ + --contracts-per-block 1 ``` -The code size should be exactly 24,576 bytes. \ No newline at end of file +- Replace `` with the private key of a funded account in your Anvil instance (Anvil prints these on startup). +- Adjust other flags as needed (`--contracts-per-block`, `--max-wallets`, etc.). + +### 4. Mining Notes + +- If you started Anvil with `--no-mining`, you will need to manually mine blocks (e.g., by calling `evm_mine` via RPC or using Anvil's console) to include the transactions. +- If you use Anvil's default mining mode, blocks will be mined automatically as transactions are sent. + +### 5. See All Flags + +```bash +./spamoor statebloat/contract-deploy --help +``` \ No newline at end of file diff --git a/scenarios/statebloat/contract_deploy/contract_deploy.go b/scenarios/statebloat/contract_deploy/contract_deploy.go index 482ddc8f..0eb63a48 100644 --- a/scenarios/statebloat/contract_deploy/contract_deploy.go +++ b/scenarios/statebloat/contract_deploy/contract_deploy.go @@ -3,16 +3,18 @@ package contractdeploy import ( "context" "crypto/rand" + "encoding/json" "fmt" "math/big" + "os" "sync" "sync/atomic" "time" - "golang.org/x/time/rate" "gopkg.in/yaml.v3" "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" "github.com/sirupsen/logrus" "github.com/spf13/pflag" @@ -21,7 +23,6 @@ import ( "github.com/ethpandaops/spamoor/scenariotypes" "github.com/ethpandaops/spamoor/spamoor" "github.com/ethpandaops/spamoor/txbuilder" - "github.com/ethpandaops/spamoor/utils" ) const ( @@ -30,15 +31,13 @@ const ( ) type ScenarioOptions struct { - MaxPending uint64 `yaml:"max_pending"` - MaxWallets uint64 `yaml:"max_wallets"` - Rebroadcast uint64 `yaml:"rebroadcast"` - BaseFee uint64 `yaml:"base_fee"` - TipFee uint64 `yaml:"tip_fee"` - GasPerBlock uint64 `yaml:"gas_per_block"` - ClientGroup string `yaml:"client_group"` - ContractsPerBlock uint64 `yaml:"contracts_per_block"` - MaxTransactions uint64 `yaml:"max_transactions"` // Maximum number of transactions to send (0 for unlimited) + MaxPending uint64 `yaml:"max_pending"` + MaxWallets uint64 `yaml:"max_wallets"` + Rebroadcast uint64 `yaml:"rebroadcast"` + BaseFee uint64 `yaml:"base_fee"` + TipFee uint64 `yaml:"tip_fee"` + ClientGroup string `yaml:"client_group"` + MaxTransactions uint64 `yaml:"max_transactions"` // Maximum number of transactions to send (0 for unlimited) } type Scenario struct { @@ -48,19 +47,20 @@ type Scenario struct { pendingChan chan bool pendingWGroup sync.WaitGroup + + deployedAddresses []string + addressesMutex sync.Mutex } var ScenarioName = "contract-deploy" var ScenarioDefaultOptions = ScenarioOptions{ - MaxPending: 0, - MaxWallets: 0, - Rebroadcast: 1, - BaseFee: 20, - TipFee: 2, - GasPerBlock: 0, - ClientGroup: "default", - ContractsPerBlock: 1, - MaxTransactions: 0, // Default to unlimited + MaxPending: 0, + MaxWallets: 0, + Rebroadcast: 1, + BaseFee: 20, + TipFee: 2, + ClientGroup: "default", + MaxTransactions: 0, // Default to unlimited } var ScenarioDescriptor = scenariotypes.ScenarioDescriptor{ Name: ScenarioName, @@ -81,9 +81,7 @@ func (s *Scenario) Flags(flags *pflag.FlagSet) error { flags.Uint64Var(&s.options.Rebroadcast, "rebroadcast", ScenarioDefaultOptions.Rebroadcast, "Number of seconds to wait before re-broadcasting a transaction") 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.Uint64Var(&s.options.GasPerBlock, "gas-per-block", ScenarioDefaultOptions.GasPerBlock, "Target gas to use per block (will calculate number of contracts to deploy)") flags.StringVar(&s.options.ClientGroup, "client-group", ScenarioDefaultOptions.ClientGroup, "Client group to use for sending transactions") - flags.Uint64Var(&s.options.ContractsPerBlock, "contracts-per-block", ScenarioDefaultOptions.ContractsPerBlock, "Number of contracts to deploy per block") flags.Uint64Var(&s.options.MaxTransactions, "max-transactions", ScenarioDefaultOptions.MaxTransactions, "Maximum number of transactions to send (0 for unlimited)") return nil } @@ -98,18 +96,10 @@ func (s *Scenario) Init(walletPool *spamoor.WalletPool, config string) error { } } - if s.options.GasPerBlock == 0 && s.options.ContractsPerBlock == 0 { - return fmt.Errorf("neither gas per block limit nor contracts per block set, must define at least one of them (see --help for list of all flags)") - } - if s.options.MaxWallets > 0 { walletPool.SetWalletCount(s.options.MaxWallets) } else { - if s.options.ContractsPerBlock*10 < 1000 { - walletPool.SetWalletCount(s.options.ContractsPerBlock * 10) - } else { - walletPool.SetWalletCount(1000) - } + walletPool.SetWalletCount(1000) } if s.options.MaxPending > 0 { @@ -133,74 +123,20 @@ func (s *Scenario) Run(ctx context.Context) error { s.logger.Infof("starting scenario: %s", ScenarioName) defer s.logger.Infof("scenario %s finished.", ScenarioName) - // Get block gas limit and validate contract deployment gas client := s.walletPool.GetClient(spamoor.SelectClientByIndex, 0, s.options.ClientGroup) if client == nil { return fmt.Errorf("no client available") } - block, err := client.GetEthClient().BlockByNumber(ctx, nil) - if err != nil { - return fmt.Errorf("failed to get latest block: %w", err) - } - blockGasLimit := block.GasLimit() - // Validate gas usage against block limit - if s.options.GasPerBlock > blockGasLimit { - return fmt.Errorf("gas per block (%d) exceeds block gas limit (%d)", s.options.GasPerBlock, blockGasLimit) - } - if s.options.ContractsPerBlock*GAS_PER_CONTRACT > blockGasLimit { - return fmt.Errorf("contracts per block (%d) requires %d gas, exceeding block gas limit (%d)", - s.options.ContractsPerBlock, s.options.ContractsPerBlock*GAS_PER_CONTRACT, blockGasLimit) - } - - // Calculate throughput based on gas per block or contracts per block - throughput := s.options.ContractsPerBlock - if s.options.GasPerBlock > 0 { - // Each deployment costs ~4.97M gas - throughput = s.options.GasPerBlock / GAS_PER_CONTRACT - if throughput == 0 { - throughput = 1 - } - s.logger.WithFields(logrus.Fields{ - "test": "contract-deploy", - "throughput": throughput, - "target_gas": s.options.GasPerBlock, - "gas_per_contract": GAS_PER_CONTRACT, - }).Info("calculated throughput") - } else { - // Calculate gas needed for the specified number of contracts - totalGas := GAS_PER_CONTRACT * s.options.ContractsPerBlock - s.logger.WithFields(logrus.Fields{ - "test": "contract-deploy", - "total_gas": totalGas, - "contracts": s.options.ContractsPerBlock, - "gas_per_contract": GAS_PER_CONTRACT, - }).Info("calculated gas") - } - - initialRate := rate.Limit(float64(throughput) / float64(utils.SecondsPerSlot)) - if initialRate == 0 { - initialRate = rate.Inf - } - limiter := rate.NewLimiter(initialRate, 1) + var deployTxHashesMu sync.Mutex + var deployTxHashes []common.Hash for { - // Check if we've reached the maximum number of transactions if s.options.MaxTransactions > 0 && txIdxCounter >= s.options.MaxTransactions { s.logger.Infof("reached maximum number of transactions (%d)", s.options.MaxTransactions) break } - if err := limiter.Wait(ctx); err != nil { - if ctx.Err() != nil { - break - } - - s.logger.Debugf("rate limited: %s", err.Error()) - time.Sleep(100 * time.Millisecond) - continue - } - txIdx := txIdxCounter txIdxCounter++ @@ -241,18 +177,74 @@ func (s *Scenario) Run(ctx context.Context) error { return } + // Collect tx hash for later receipt lookup + deployTxHashesMu.Lock() + deployTxHashes = append(deployTxHashes, tx.Hash()) + deployTxHashesMu.Unlock() + txCount.Add(1) }(txIdx, lastChan, currentChan) lastChan = currentChan } s.pendingWGroup.Wait() + s.logger.WithFields(logrus.Fields{ "test": "contract-deploy", "total_txs": txCount.Load(), "pending_txs": pendingCount.Load(), }).Info("finished sending transactions, awaiting block inclusion...") + // Wait for a new block to be mined + ethClient := client.GetEthClient() + startBlock, err := ethClient.BlockByNumber(ctx, nil) + if err != nil { + s.logger.Warnf("Failed to get current block: %v", err) + return err + } + startBlockNum := startBlock.NumberU64() + var latestBlockNum uint64 + for { + block, err := ethClient.BlockByNumber(ctx, nil) + if err != nil { + s.logger.Warnf("Failed to get block: %v", err) + return err + } + latestBlockNum = block.NumberU64() + if latestBlockNum > startBlockNum { + break + } + time.Sleep(2 * time.Second) + } + + // For each deployment tx, get the receipt and log contract address and gas used + var deployedAddresses []string + for _, txHash := range deployTxHashes { + receipt, err := ethClient.TransactionReceipt(ctx, txHash) + if err != nil { + s.logger.Warnf("Failed to get receipt for tx %s: %v", txHash.Hex(), err) + continue + } + if receipt.ContractAddress != (common.Address{}) { + addr := receipt.ContractAddress.Hex() + deployedAddresses = append(deployedAddresses, addr) + s.logger.Infof("Deployed contract at address: %s (gas used: %d)", addr, receipt.GasUsed) + } + } + + // Write deployed addresses to JSON file and log them + if len(deployedAddresses) > 0 { + file, err := os.Create("deployed_contracts.json") + if err == nil { + _ = json.NewEncoder(file).Encode(deployedAddresses) + file.Close() + s.logger.Infof("Wrote %d deployed contract addresses to deployed_contracts.json", len(deployedAddresses)) + } else { + s.logger.Warnf("Failed to write deployed_contracts.json: %v", err) + } + s.logger.Infof("Deployed contract addresses: %v", deployedAddresses) + } + return nil } @@ -281,7 +273,7 @@ func (s *Scenario) sendTx(ctx context.Context, txIdx uint64, onComplete func()) auth.Nonce = big.NewInt(int64(wallet.GetNonce())) auth.Value = big.NewInt(0) - auth.GasLimit = GAS_PER_CONTRACT // Gas for single contract deployment + auth.GasLimit = GAS_PER_CONTRACT + GAS_PER_CONTRACT*5/100 // Gas for single contract deployment // Set EIP-1559 fee parameters if s.options.BaseFee > 0 { diff --git a/scenarios/statebloat/contract_deploy/contract_deploy_test.go b/scenarios/statebloat/contract_deploy/contract_deploy_test.go deleted file mode 100644 index 653bd50d..00000000 --- a/scenarios/statebloat/contract_deploy/contract_deploy_test.go +++ /dev/null @@ -1,237 +0,0 @@ -package contractdeploy - -import ( - "context" - "os/exec" - "testing" - "time" - - "github.com/ethereum/go-ethereum/ethclient" - "github.com/holiman/uint256" - "github.com/sirupsen/logrus" - "github.com/stretchr/testify/assert" - "github.com/stretchr/testify/require" - - "github.com/ethereum/go-ethereum/common" - "github.com/ethpandaops/spamoor/spamoor" - "github.com/ethpandaops/spamoor/txbuilder" - "github.com/ethpandaops/spamoor/utils" -) - -type testFixture struct { - t *testing.T - cmd *exec.Cmd - client *ethclient.Client - ctx context.Context - logger *logrus.Entry - clientPool *spamoor.ClientPool - rootWallet *txbuilder.Wallet - txpool *txbuilder.TxPool - walletPool *spamoor.WalletPool - scenario *Scenario -} - -func setupTestFixture(t *testing.T) *testFixture { - // Start Anvil server with legacy transactions - cmd := exec.Command("anvil", "--hardfork", "pectra") - err := cmd.Start() - require.NoError(t, err) - - // Wait for Anvil to start - time.Sleep(2 * time.Second) - - // Connect to Anvil - client, err := ethclient.Dial("http://localhost:8545") - require.NoError(t, err) - - // Create client pool - ctx := context.Background() - logger := logrus.New().WithField("test", "contract-deploy") - clientPool := spamoor.NewClientPool(ctx, []string{"http://localhost:8545"}, logger) - err = clientPool.PrepareClients() - require.NoError(t, err) - - // Create root wallet using a pre-funded Anvil account - rootWallet, err := spamoor.InitRootWallet(ctx, "ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80", clientPool.GetClient(spamoor.SelectClientByIndex, 0, ""), logger) - require.NoError(t, err) - - // Create tx pool - txpool := txbuilder.NewTxPool(&txbuilder.TxPoolOptions{ - Context: ctx, - GetClientFn: func(index int, random bool) *txbuilder.Client { - mode := spamoor.SelectClientByIndex - if random { - mode = spamoor.SelectClientRandom - } - return clientPool.GetClient(mode, index, "") - }, - GetClientCountFn: func() int { - return len(clientPool.GetAllClients()) - }, - }) - - // Create wallet pool - walletPool := spamoor.NewWalletPool(ctx, logger, rootWallet, clientPool, txpool) - walletPool.SetWalletCount(1) - walletPool.SetRefillAmount(utils.EtherToWei(uint256.NewInt(1))) // 1 ETH - walletPool.SetRefillBalance(utils.EtherToWei(uint256.NewInt(1))) // 1 ETH - walletPool.SetRefillInterval(60) - - // Initialize wallet pool - err = walletPool.PrepareWallets(true) - require.NoError(t, err) - - // Create scenario instance - scenario := newScenario(logger).(*Scenario) - - return &testFixture{ - t: t, - cmd: cmd, - client: client, - ctx: ctx, - logger: logger, - clientPool: clientPool, - rootWallet: rootWallet, - txpool: txpool, - walletPool: walletPool, - scenario: scenario, - } -} - -func (f *testFixture) teardown() { - if f.cmd != nil && f.cmd.Process != nil { - f.cmd.Process.Kill() - } - if f.client != nil { - f.client.Close() - } -} - -func (f *testFixture) verifyContractDeployment(runCtx context.Context) { - // Verify contract deployment - block, err := f.client.BlockByNumber(runCtx, nil) - require.NoError(f.t, err) - assert.Greater(f.t, len(block.Transactions()), 0) - - // Get the expected number of contracts based on scenario config - expectedContracts := f.scenario.options.ContractsPerBlock - if f.scenario.options.GasPerBlock > 0 { - expectedContracts = f.scenario.options.GasPerBlock / GAS_PER_CONTRACT - if expectedContracts == 0 { - expectedContracts = 1 - } - } - - // Track deployed contracts - deployedContracts := 0 - contractAddresses := make([]common.Address, 0) - - // Check all transactions in the block - for _, tx := range block.Transactions() { - receipt, err := f.client.TransactionReceipt(runCtx, tx.Hash()) - require.NoError(f.t, err) - assert.Equal(f.t, uint64(1), receipt.Status) - - // If this is a contract creation transaction - if receipt.ContractAddress != (common.Address{}) { - deployedContracts++ - contractAddresses = append(contractAddresses, receipt.ContractAddress) - } - } - - // Verify the number of contracts deployed matches the expected count - assert.Equal(f.t, expectedContracts, deployedContracts, "Number of deployed contracts should match the scenario configuration") - - // Verify each contract's size - for _, addr := range contractAddresses { - code, err := f.client.CodeAt(runCtx, addr, nil) - require.NoError(f.t, err) - - // EIP-170 limit is 24,576 bytes (0x6000) - assert.Equal(f.t, 24576, len(code), "Contract code size should be exactly 24,576 bytes (EIP-170 limit)") - } - - f.logger.WithFields(logrus.Fields{ - "expected_contracts": expectedContracts, - "deployed_contracts": deployedContracts, - "contract_addresses": contractAddresses, - }).Info("Verified contract deployments") -} - -func TestContractDeployWithContractsPerBlock(t *testing.T) { - fixture := setupTestFixture(t) - defer fixture.teardown() - - // Initialize with contracts_per_block configuration - config := ` -max_pending: 0 -max_wallets: 1 -rebroadcast: 2 -base_fee: 20 -tip_fee: 2 -gas_per_block: 0 -client_group: default -contracts_per_block: 6 -max_transactions: 1 -` - require.NoError(t, fixture.scenario.Init(fixture.walletPool, config)) - - // Run scenario - runCtx, cancel := context.WithTimeout(fixture.ctx, 30*time.Second) - defer cancel() - - err := fixture.scenario.Run(runCtx) - require.NoError(t, err) - - fixture.verifyContractDeployment(runCtx) -} - -func TestContractDeployWithGasPerBlock(t *testing.T) { - fixture := setupTestFixture(t) - defer fixture.teardown() - - // Initialize with gas_per_block configuration - config := ` -max_pending: 0 -max_wallets: 1 -rebroadcast: 2 -base_fee: 20 -tip_fee: 2 -gas_per_block: 30000000 -client_group: default -contracts_per_block: 0 -max_transactions: 1 -` - require.NoError(t, fixture.scenario.Init(fixture.walletPool, config)) - - // Run scenario - runCtx, cancel := context.WithTimeout(fixture.ctx, 30*time.Second) - defer cancel() - - err := fixture.scenario.Run(runCtx) - require.NoError(t, err) - - fixture.verifyContractDeployment(runCtx) -} - -func TestContractDeployWithInvalidConfig(t *testing.T) { - fixture := setupTestFixture(t) - defer fixture.teardown() - - // Initialize with invalid configuration - config := ` -max_pending: 0 -max_wallets: 1 -rebroadcast: 1 -base_fee: 20 -tip_fee: 2 -gas_per_block: 0 -client_group: default -contracts_per_block: 0 -max_transactions: 1 -` - // We expect Init to fail with this configuration - err := fixture.scenario.Init(fixture.walletPool, config) - require.Error(t, err) - assert.Contains(t, err.Error(), "neither gas per block limit nor contracts per block set") -} From 2ab46fd94757ac59ab77c790cff3130285bc6d24 Mon Sep 17 00:00:00 2001 From: CPerezz Date: Sat, 24 May 2025 14:46:43 +0200 Subject: [PATCH 13/26] feat(contract-deploy): implement batch deployment strategy and transaction tracking - Introduced a batch deployment strategy that calculates the number of contracts fitting within the block gas limit. - Added detailed tracking for deployed contracts, including gas used and bytecode size, with structured loggin. - Improved nonce management and transaction retry logic. --- .../statebloat/contract_deploy/README.md | 54 +- .../contract_deploy/contract_deploy.go | 586 +++++++++++++----- 2 files changed, 478 insertions(+), 162 deletions(-) diff --git a/scenarios/statebloat/contract_deploy/README.md b/scenarios/statebloat/contract_deploy/README.md index e6b70c0e..f0049958 100644 --- a/scenarios/statebloat/contract_deploy/README.md +++ b/scenarios/statebloat/contract_deploy/README.md @@ -6,7 +6,12 @@ This scenario deploys contracts that are exactly 24kB in size (EIP-170 limit) to 1. Generates a contract with exactly 24,576 bytes of runtime code 2. Deploys the contract using CREATE -3. Each deployment adds: +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 @@ -18,6 +23,15 @@ This scenario deploys contracts that are exactly 24kB in size (EIP-170 limit) to - 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 ```bash @@ -30,37 +44,40 @@ spamoor statebloat/contract-deploy [flags] - `--privkey` - Private key of the sending wallet - `--rpchost` - RPC endpoint(s) to send transactions to -#### Volume Control (either -c or -t required) -- `-c, --count` - Total number of contracts to deploy -- `-t, --throughput` - Contracts to deploy per slot +#### Volume Control +- `--max-transactions` - Maximum number of transactions to send (0 for unlimited) - `--max-pending` - Maximum number of pending deployments +- `--block-gas-limit` - Block gas limit for batching (default: 30,000,000, 0 = use default) #### Transaction Settings - `--basefee` - Max fee per gas in gwei (default: 20) - `--tipfee` - Max tip per gas in gwei (default: 2) -- `--rebroadcast` - Seconds to wait before rebroadcasting (default: 120) +- `--rebroadcast` - Seconds to wait before rebroadcasting (default: 1) #### Wallet Management - `--max-wallets` - Maximum number of child wallets to use -- `--refill-amount` - ETH amount to fund each child wallet (default: 5) -- `--refill-balance` - Minimum ETH balance before refilling (default: 2) -- `--refill-interval` - Seconds between balance checks (default: 300) +- `--client-group` - Client group to use for sending transactions (default: "default") -## Example +## Examples -Deploy 10 contracts: +Deploy 30 contracts in batches: ```bash -spamoor statebloat/contract-deploy -p "" -h http://localhost:8545 -c 10 +spamoor statebloat/contract-deploy \ + --privkey "" \ + --rpchost http://localhost:8545 \ + --max-transactions 30 ``` -Deploy 1 contract per slot: +Deploy with custom block gas limit (for testnets): ```bash -spamoor statebloat/contract-deploy -p "" -h http://localhost:8545 -t 1 +spamoor statebloat/contract-deploy \ + --privkey "" \ + --rpchost http://localhost:8545 \ + --max-transactions 10 \ + --block-gas-limit 15000000 ``` -## Running Against a Local Anvil Node (without Go tests) - -You can run this scenario directly against your own Anvil node using the Spamoor CLI, without running Go tests. +## Running Against a Local Anvil Node ### 1. Start Anvil @@ -82,16 +99,17 @@ go build -o spamoor ./cmd/spamoor ./spamoor statebloat/contract-deploy \ --privkey \ --rpchost http://localhost:8545 \ - --contracts-per-block 1 + --max-transactions 30 ``` - Replace `` with the private key of a funded account in your Anvil instance (Anvil prints these on startup). -- Adjust other flags as needed (`--contracts-per-block`, `--max-wallets`, etc.). +- The scenario will automatically calculate the optimal batch size based on gas limits. ### 4. Mining Notes - If you started Anvil with `--no-mining`, you will need to manually mine blocks (e.g., by calling `evm_mine` via RPC or using Anvil's console) to include the transactions. - If you use Anvil's default mining mode, blocks will be mined automatically as transactions are sent. +- The scenario waits for each block to be mined before sending the next batch, ensuring predictable transaction ordering. ### 5. See All Flags diff --git a/scenarios/statebloat/contract_deploy/contract_deploy.go b/scenarios/statebloat/contract_deploy/contract_deploy.go index 0eb63a48..8525d613 100644 --- a/scenarios/statebloat/contract_deploy/contract_deploy.go +++ b/scenarios/statebloat/contract_deploy/contract_deploy.go @@ -2,11 +2,13 @@ package contractdeploy import ( "context" + "crypto/ecdsa" "crypto/rand" "encoding/json" "fmt" "math/big" "os" + "strings" "sync" "sync/atomic" "time" @@ -16,6 +18,7 @@ import ( "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/crypto" "github.com/sirupsen/logrus" "github.com/spf13/pflag" @@ -28,6 +31,8 @@ import ( const ( // GAS_PER_CONTRACT is the estimated gas cost for deploying one StateBloatToken contract GAS_PER_CONTRACT = 4970000 // ~4.97M gas per contract + // BLOCK_GAS_LIMIT is the typical block gas limit for Ethereum mainnet + BLOCK_GAS_LIMIT = 30000000 // 30M gas ) type ScenarioOptions struct { @@ -38,6 +43,27 @@ type ScenarioOptions struct { TipFee uint64 `yaml:"tip_fee"` ClientGroup string `yaml:"client_group"` MaxTransactions uint64 `yaml:"max_transactions"` // Maximum number of transactions to send (0 for unlimited) + BlockGasLimit uint64 `yaml:"block_gas_limit"` // Block gas limit for batching (0 = use default) +} + +// ContractDeployment tracks a deployed contract with its deployer info +type ContractDeployment struct { + ContractAddress string `json:"contract_address"` + PrivateKey string `json:"private_key"` + TxHash string `json:"tx_hash"` + GasUsed uint64 `json:"gas_used"` + BlockNumber uint64 `json:"block_number"` + BytecodeSize int `json:"bytecode_size"` + GasPerByte string `json:"gas_per_byte"` +} + +// PendingTransaction tracks a transaction until it's mined +type PendingTransaction struct { + TxHash common.Hash + Wallet *txbuilder.Wallet + TxIndex uint64 + SentAt time.Time + PrivateKey *ecdsa.PrivateKey } type Scenario struct { @@ -45,22 +71,35 @@ type Scenario struct { logger *logrus.Entry walletPool *spamoor.WalletPool - pendingChan chan bool - pendingWGroup sync.WaitGroup + // 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 + maxConcurrent int - deployedAddresses []string - addressesMutex sync.Mutex + // Results tracking + deployedContracts []ContractDeployment + contractsMutex sync.Mutex + + // Nonce management per wallet + walletNonces map[common.Address]uint64 + nonceMutex sync.RWMutex } var ScenarioName = "contract-deploy" var ScenarioDefaultOptions = ScenarioOptions{ - MaxPending: 0, + MaxPending: 10, // Limit concurrent transactions MaxWallets: 0, Rebroadcast: 1, BaseFee: 20, TipFee: 2, ClientGroup: "default", MaxTransactions: 0, // Default to unlimited + BlockGasLimit: 0, // Use default BLOCK_GAS_LIMIT } var ScenarioDescriptor = scenariotypes.ScenarioDescriptor{ Name: ScenarioName, @@ -71,7 +110,10 @@ var ScenarioDescriptor = scenariotypes.ScenarioDescriptor{ func newScenario(logger logrus.FieldLogger) scenariotypes.Scenario { return &Scenario{ - logger: logger.WithField("scenario", ScenarioName), + logger: logger.WithField("scenario", ScenarioName), + pendingTxs: make(map[common.Hash]*PendingTransaction), + walletNonces: make(map[common.Address]uint64), + maxConcurrent: 5, // Conservative default } } @@ -83,6 +125,7 @@ func (s *Scenario) Flags(flags *pflag.FlagSet) error { flags.Uint64Var(&s.options.TipFee, "tipfee", ScenarioDefaultOptions.TipFee, "Max tip per gas to use in transactions (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 for unlimited)") + flags.Uint64Var(&s.options.BlockGasLimit, "block-gas-limit", ScenarioDefaultOptions.BlockGasLimit, "Block gas limit for batching (0 = use default)") return nil } @@ -102,8 +145,9 @@ func (s *Scenario) Init(walletPool *spamoor.WalletPool, config string) error { walletPool.SetWalletCount(1000) } + // Set concurrent transaction limit if s.options.MaxPending > 0 { - s.pendingChan = make(chan bool, s.options.MaxPending) + s.maxConcurrent = int(s.options.MaxPending) } return nil @@ -114,210 +158,464 @@ func (s *Scenario) Config() string { return string(yamlBytes) } -func (s *Scenario) Run(ctx context.Context) error { - txIdxCounter := uint64(0) - pendingCount := atomic.Int64{} - txCount := atomic.Uint64{} - var lastChan chan bool +// 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) + if s.chainIDError == nil { + s.logger.Infof("Cached chain ID: %s", s.chainID.String()) + } + }) + return s.chainID, s.chainIDError +} - s.logger.Infof("starting scenario: %s", ScenarioName) - defer s.logger.Infof("scenario %s finished.", ScenarioName) +// getWalletNonce gets the current nonce for a wallet (without incrementing) +func (s *Scenario) getWalletNonce(ctx context.Context, wallet *txbuilder.Wallet, client *txbuilder.Client) (uint64, error) { + s.nonceMutex.Lock() + defer s.nonceMutex.Unlock() + + addr := crypto.PubkeyToAddress(wallet.GetPrivateKey().PublicKey) + + // Always refresh nonce from network to avoid gaps + nonce, err := client.GetEthClient().PendingNonceAt(ctx, addr) + if err != nil { + return 0, fmt.Errorf("failed to get nonce for %s: %w", addr.Hex(), err) + } + + // Store the current network nonce + s.walletNonces[addr] = nonce + s.logger.Debugf("Current nonce for wallet %s: %d", addr.Hex(), nonce) + + return nonce, nil +} + +// incrementWalletNonce increments the local nonce counter after successful tx send +func (s *Scenario) incrementWalletNonce(wallet *txbuilder.Wallet) { + s.nonceMutex.Lock() + defer s.nonceMutex.Unlock() + + addr := crypto.PubkeyToAddress(wallet.GetPrivateKey().PublicKey) + s.walletNonces[addr]++ + s.logger.Debugf("Incremented nonce for wallet %s to: %d", addr.Hex(), s.walletNonces[addr]) +} + +// 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 < s.maxConcurrent { + return + } + + // Check and clean up confirmed transactions + s.processPendingTransactions(ctx) + time.Sleep(500 * time.Millisecond) + } +} + +// processPendingTransactions checks for transaction confirmations and updates state +func (s *Scenario) processPendingTransactions(ctx context.Context) { + s.pendingTxsMutex.Lock() + defer s.pendingTxsMutex.Unlock() client := s.walletPool.GetClient(spamoor.SelectClientByIndex, 0, s.options.ClientGroup) if client == nil { - return fmt.Errorf("no client available") + return } - var deployTxHashesMu sync.Mutex - var deployTxHashes []common.Hash + ethClient := client.GetEthClient() + var confirmedTxs []common.Hash - for { - if s.options.MaxTransactions > 0 && txIdxCounter >= s.options.MaxTransactions { - s.logger.Infof("reached maximum number of transactions (%d)", s.options.MaxTransactions) - break + for txHash, pendingTx := range s.pendingTxs { + receipt, err := ethClient.TransactionReceipt(ctx, txHash) + if err != nil { + // Transaction still pending or error retrieving receipt + continue } - txIdx := txIdxCounter - txIdxCounter++ + confirmedTxs = append(confirmedTxs, txHash) + + // Process successful deployment + if receipt.Status == 1 && receipt.ContractAddress != (common.Address{}) { + s.recordDeployedContract(receipt, pendingTx) + } else if receipt.Status != 1 { + s.logger.Warnf("Transaction failed: %s (gas used: %d)", txHash.Hex(), receipt.GasUsed) + } + } + + // Remove confirmed transactions from pending map + for _, txHash := range confirmedTxs { + delete(s.pendingTxs, txHash) + } + + if len(confirmedTxs) > 0 { + s.logger.Debugf("Processed %d confirmed transactions, %d still pending", + len(confirmedTxs), len(s.pendingTxs)) + } +} - if s.pendingChan != nil { - // await pending transactions - s.pendingChan <- true +// recordDeployedContract records a successfully deployed contract +func (s *Scenario) recordDeployedContract(receipt *types.Receipt, pendingTx *PendingTransaction) { + s.contractsMutex.Lock() + defer s.contractsMutex.Unlock() + + // Get the actual transaction to calculate real bytecode size + client := s.walletPool.GetClient(spamoor.SelectClientByIndex, 0, s.options.ClientGroup) + var txBytes int + var gasPerByte float64 + + if client != nil { + tx, _, err := client.GetEthClient().TransactionByHash(context.Background(), receipt.TxHash) + if err == nil { + txBytes = len(tx.Data()) + gasPerByte = float64(receipt.GasUsed) / float64(max(txBytes, 1)) + } else { + // Fallback to estimated size + txBytes = 24564 // Approximate StateBloatToken bytecode size + gasPerByte = float64(receipt.GasUsed) / float64(txBytes) } - pendingCount.Add(1) - currentChan := make(chan bool, 1) - - go func(txIdx uint64, lastChan, currentChan chan bool) { - defer func() { - pendingCount.Add(-1) - currentChan <- true - }() - - logger := s.logger - tx, client, wallet, err := s.sendTx(ctx, txIdx, func() { - if s.pendingChan != nil { - time.Sleep(100 * time.Millisecond) - <-s.pendingChan - } - }) - if client != nil { - logger = logger.WithField("rpc", client.GetName()) - } - if tx != nil { - logger = logger.WithField("nonce", tx.Nonce()) - } - if wallet != nil { - logger = logger.WithField("wallet", s.walletPool.GetWalletName(wallet.GetAddress())) - } - if lastChan != nil { - <-lastChan - } - if err != nil { - logger.Warnf("could not send transaction: %v", err) - return - } - - // Collect tx hash for later receipt lookup - deployTxHashesMu.Lock() - deployTxHashes = append(deployTxHashes, tx.Hash()) - deployTxHashesMu.Unlock() - - txCount.Add(1) - }(txIdx, lastChan, currentChan) - - lastChan = currentChan - } - s.pendingWGroup.Wait() + } else { + // Fallback values + txBytes = 24564 + gasPerByte = float64(receipt.GasUsed) / float64(txBytes) + } + + deployment := ContractDeployment{ + ContractAddress: receipt.ContractAddress.Hex(), + PrivateKey: fmt.Sprintf("0x%x", crypto.FromECDSA(pendingTx.PrivateKey)), + TxHash: receipt.TxHash.Hex(), + GasUsed: receipt.GasUsed, + BlockNumber: receipt.BlockNumber.Uint64(), + BytecodeSize: txBytes, + GasPerByte: fmt.Sprintf("%.2f", gasPerByte), + } + + s.deployedContracts = append(s.deployedContracts, deployment) s.logger.WithFields(logrus.Fields{ - "test": "contract-deploy", - "total_txs": txCount.Load(), - "pending_txs": pendingCount.Load(), - }).Info("finished sending transactions, awaiting block inclusion...") + "contract_address": deployment.ContractAddress, + "tx_hash": deployment.TxHash, + "gas_used": deployment.GasUsed, + "block_number": deployment.BlockNumber, + "bytecode_size": deployment.BytecodeSize, + "gas_per_byte": deployment.GasPerByte, + "total_contracts": len(s.deployedContracts), + }).Info("Contract successfully deployed and recorded") +} - // Wait for a new block to be mined - ethClient := client.GetEthClient() - startBlock, err := ethClient.BlockByNumber(ctx, nil) +func (s *Scenario) Run(ctx context.Context) error { + s.logger.Infof("starting scenario: %s", ScenarioName) + defer s.logger.Infof("scenario %s finished.", ScenarioName) + + // Cache chain ID at startup + chainID, err := s.getChainID(ctx) if err != nil { - s.logger.Warnf("Failed to get current block: %v", err) - return err + return fmt.Errorf("failed to get chain ID: %w", err) } - startBlockNum := startBlock.NumberU64() - var latestBlockNum uint64 + + // Determine block gas limit to use + blockGasLimit := s.options.BlockGasLimit + if blockGasLimit == 0 { + blockGasLimit = BLOCK_GAS_LIMIT + } + + // Calculate how many contracts can fit in one block + contractsPerBlock := int(blockGasLimit / GAS_PER_CONTRACT) + if contractsPerBlock == 0 { + contractsPerBlock = 1 + } + + s.logger.Infof("Chain ID: %s, Block gas limit: %d, Gas per contract: %d, Contracts per block: %d, Max concurrent: %d", + chainID.String(), blockGasLimit, GAS_PER_CONTRACT, contractsPerBlock, s.maxConcurrent) + + txIdxCounter := uint64(0) + totalTxCount := atomic.Uint64{} + for { - block, err := ethClient.BlockByNumber(ctx, nil) - if err != nil { - s.logger.Warnf("Failed to get block: %v", err) - return err - } - latestBlockNum = block.NumberU64() - if latestBlockNum > startBlockNum { + // Check if we've reached max transactions + if s.options.MaxTransactions > 0 && txIdxCounter >= s.options.MaxTransactions { + s.logger.Infof("reached maximum number of transactions (%d)", s.options.MaxTransactions) break } - time.Sleep(2 * time.Second) - } - // For each deployment tx, get the receipt and log contract address and gas used - var deployedAddresses []string - for _, txHash := range deployTxHashes { - receipt, err := ethClient.TransactionReceipt(ctx, txHash) + // Wait for available slot + s.waitForPendingTxSlot(ctx) + + // Send a single transaction + err := s.sendTransaction(ctx, txIdxCounter) if err != nil { - s.logger.Warnf("Failed to get receipt for tx %s: %v", txHash.Hex(), err) + s.logger.Warnf("failed to send transaction %d: %v", txIdxCounter, err) + time.Sleep(1 * time.Second) continue } - if receipt.ContractAddress != (common.Address{}) { - addr := receipt.ContractAddress.Hex() - deployedAddresses = append(deployedAddresses, addr) - s.logger.Infof("Deployed contract at address: %s (gas used: %d)", addr, receipt.GasUsed) + + txIdxCounter++ + totalTxCount.Add(1) + + // Process pending transactions periodically + 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 + 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(2 * time.Second) } - // Write deployed addresses to JSON file and log them - if len(deployedAddresses) > 0 { - file, err := os.Create("deployed_contracts.json") + // Save results to JSON + s.contractsMutex.Lock() + totalContracts := len(s.deployedContracts) + s.contractsMutex.Unlock() + + s.logger.WithFields(logrus.Fields{ + "test": "contract-deploy", + "total_txs": totalTxCount.Load(), + "total_contracts": totalContracts, + }).Info("All transactions completed") + + return s.saveDeployedContracts() +} + +// sendTransaction sends a single contract deployment transaction with retry logic +func (s *Scenario) sendTransaction(ctx context.Context, txIdx uint64) error { + maxRetries := 3 + baseGasMultiplier := 1.0 + + for attempt := 0; attempt < maxRetries; attempt++ { + err := s.attemptTransaction(ctx, txIdx, baseGasMultiplier) if err == nil { - _ = json.NewEncoder(file).Encode(deployedAddresses) - file.Close() - s.logger.Infof("Wrote %d deployed contract addresses to deployed_contracts.json", len(deployedAddresses)) - } else { - s.logger.Warnf("Failed to write deployed_contracts.json: %v", err) + return nil } - s.logger.Infof("Deployed contract addresses: %v", deployedAddresses) + + // Check if it's an underpriced error + if strings.Contains(err.Error(), "replacement transaction underpriced") || + strings.Contains(err.Error(), "transaction underpriced") { + baseGasMultiplier += 0.2 // Increase gas by 20% each retry + s.logger.Warnf("Transaction %d underpriced, retrying with %.1fx gas (attempt %d/%d)", + txIdx, baseGasMultiplier, attempt+1, maxRetries) + time.Sleep(time.Duration(attempt+1) * 500 * time.Millisecond) // Exponential backoff + continue + } + + // For other errors, return immediately + return err } - return nil + return fmt.Errorf("failed to send transaction after %d attempts", maxRetries) } -func (s *Scenario) sendTx(ctx context.Context, txIdx uint64, onComplete func()) (*types.Transaction, *txbuilder.Client, *txbuilder.Wallet, error) { - client := s.walletPool.GetClient(spamoor.SelectClientByIndex, int(txIdx), s.options.ClientGroup) - wallet := s.walletPool.GetWallet(spamoor.SelectWalletByIndex, int(txIdx)) +// attemptTransaction makes a single attempt to send a transaction +func (s *Scenario) attemptTransaction(ctx context.Context, txIdx uint64, gasMultiplier float64) error { + // Get client and wallet + client := s.walletPool.GetClient(spamoor.SelectClientRoundRobin, 0, s.options.ClientGroup) + wallet := s.walletPool.GetWallet(spamoor.SelectWalletRoundRobin, 0) if client == nil { - return nil, nil, nil, fmt.Errorf("no client available") + return fmt.Errorf("no client available") } if wallet == nil { - return nil, nil, nil, fmt.Errorf("no wallet available") + return fmt.Errorf("no wallet available") } - // Get chain ID - chainId, err := client.GetChainId(ctx) + // Get cached chain ID + chainID, err := s.getChainID(ctx) if err != nil { - return nil, nil, nil, fmt.Errorf("failed to get chain ID: %w", err) + return fmt.Errorf("failed to get chain ID: %w", err) } - // Deploy contract - auth, err := bind.NewKeyedTransactorWithChainID(wallet.GetPrivateKey(), chainId) + // Get current nonce for this wallet + nonce, err := s.getWalletNonce(ctx, wallet, client) if err != nil { - return nil, nil, nil, fmt.Errorf("failed to create auth: %w", err) + return fmt.Errorf("failed to get nonce: %w", err) } - auth.Nonce = big.NewInt(int64(wallet.GetNonce())) + // Create transaction auth + auth, err := bind.NewKeyedTransactorWithChainID(wallet.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 = GAS_PER_CONTRACT + GAS_PER_CONTRACT*5/100 // Gas for single contract deployment + auth.GasLimit = GAS_PER_CONTRACT + GAS_PER_CONTRACT*5/100 + + // Set EIP-1559 fee parameters with dynamic adjustment + baseFee := s.options.BaseFee + tipFee := s.options.TipFee + + if gasMultiplier > 1.0 { + baseFee = uint64(float64(baseFee) * gasMultiplier) + tipFee = uint64(float64(tipFee) * gasMultiplier) + } - // 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 baseFee > 0 { + auth.GasFeeCap = new(big.Int).Mul(big.NewInt(int64(baseFee)), big.NewInt(1000000000)) } - if s.options.TipFee > 0 { - auth.GasTipCap = new(big.Int).Mul(big.NewInt(int64(s.options.TipFee)), big.NewInt(1000000000)) + if tipFee > 0 { + auth.GasTipCap = new(big.Int).Mul(big.NewInt(int64(tipFee)), big.NewInt(1000000000)) } // Generate random salt for unique contract salt := make([]byte, 32) _, err = rand.Read(salt) if err != nil { - return nil, nil, nil, fmt.Errorf("failed to generate salt: %w", err) + return fmt.Errorf("failed to generate salt: %w", err) } saltInt := new(big.Int).SetBytes(salt) - // Ensure we have a valid client + // Deploy the contract ethClient := client.GetEthClient() if ethClient == nil { - return nil, nil, nil, fmt.Errorf("failed to get eth client") + return fmt.Errorf("failed to get eth client") } - // Deploy the StateBloatToken contract address, tx, _, err := contract.DeployContract(auth, ethClient, saltInt) if err != nil { - return nil, nil, nil, fmt.Errorf("failed to deploy contract: %w", err) + return fmt.Errorf("failed to deploy contract: %w", err) } - // Update nonce - wallet.SetNonce(wallet.GetNonce() + 1) + // Track pending transaction + pendingTx := &PendingTransaction{ + TxHash: tx.Hash(), + Wallet: wallet, + TxIndex: txIdx, + SentAt: time.Now(), + PrivateKey: wallet.GetPrivateKey(), + } - // Calculate bytes written and gas/byte ratio - txBytes := len(tx.Data()) - gasPerByte := float64(GAS_PER_CONTRACT) / float64(txBytes) + s.pendingTxsMutex.Lock() + s.pendingTxs[tx.Hash()] = pendingTx + s.pendingTxsMutex.Unlock() s.logger.WithFields(logrus.Fields{ - "test": "contract-deploy", + "tx_index": txIdx, "tx_hash": tx.Hash().Hex(), - "contract_address": address.Hex(), - "bytes_written": txBytes, - "gas_per_byte": fmt.Sprintf("%.2f", gasPerByte), - "contracts": 1, - }).Info("deployed contract") + "expected_address": address.Hex(), + "nonce": nonce, + "wallet": crypto.PubkeyToAddress(wallet.GetPrivateKey().PublicKey).Hex(), + "gas_limit": auth.GasLimit, + "base_fee_gwei": baseFee, + "tip_fee_gwei": tipFee, + "gas_multiplier": fmt.Sprintf("%.1fx", gasMultiplier), + }).Info("Transaction sent successfully") + + // Only increment nonce after successful send + s.incrementWalletNonce(wallet) + + return nil +} + +// saveDeployedContracts saves the deployed contracts to JSON files +func (s *Scenario) saveDeployedContracts() error { + s.contractsMutex.Lock() + defer s.contractsMutex.Unlock() + + if len(s.deployedContracts) == 0 { + s.logger.Info("No contracts were deployed") + return nil + } + + // Save detailed contract info with private keys + contractsFile, err := os.Create("deployed_contracts_detailed.json") + if err != nil { + return fmt.Errorf("failed to create detailed contracts file: %w", err) + } + defer contractsFile.Close() + + err = json.NewEncoder(contractsFile).Encode(s.deployedContracts) + if err != nil { + return fmt.Errorf("failed to write detailed contracts: %w", err) + } + + // Save simple addresses list for compatibility + var addresses []string + for _, contract := range s.deployedContracts { + addresses = append(addresses, contract.ContractAddress) + } + + addressFile, err := os.Create("deployed_contracts.json") + if err != nil { + return fmt.Errorf("failed to create addresses file: %w", err) + } + defer addressFile.Close() + + err = json.NewEncoder(addressFile).Encode(addresses) + if err != nil { + return fmt.Errorf("failed to write addresses: %w", err) + } + + // Create contract-to-private-key mapping + contractKeyMap := make(map[string]string) + for _, contract := range s.deployedContracts { + contractKeyMap[contract.ContractAddress] = contract.PrivateKey + } + + keyMapFile, err := os.Create("contract_private_key_mapping.json") + if err != nil { + return fmt.Errorf("failed to create key mapping file: %w", err) + } + defer keyMapFile.Close() + + err = json.NewEncoder(keyMapFile).Encode(contractKeyMap) + if err != nil { + return fmt.Errorf("failed to write key mapping: %w", err) + } - return tx, client, wallet, nil + s.logger.WithFields(logrus.Fields{ + "contracts_deployed": len(s.deployedContracts), + "detailed_file": "deployed_contracts_detailed.json", + "addresses_file": "deployed_contracts.json", + "key_mapping_file": "contract_private_key_mapping.json", + }).Info("Successfully saved deployed contract information to JSON files") + + // Log summary of deployed contracts + var totalGasUsed uint64 + for _, contract := range s.deployedContracts { + totalGasUsed += contract.GasUsed + } + + s.logger.WithFields(logrus.Fields{ + "total_contracts": len(s.deployedContracts), + "total_gas_used": totalGasUsed, + "avg_gas_per_contract": totalGasUsed / uint64(len(s.deployedContracts)), + }).Info("Deployment summary") + + return nil +} + +func max(a, b int) int { + if a > b { + return a + } + return b } From 2c73f645efa01550713055eb27ba66c87532bd86 Mon Sep 17 00:00:00 2001 From: CPerezz Date: Sat, 24 May 2025 23:46:00 +0200 Subject: [PATCH 14/26] feat(contract-deploy): implement deployment mapping and final summary logging - Added functionality to save a mapping of private keys to contract addresses in a deployments.json file after each contract deployment. - Refactored the final summary logging to focus on the deployments.json file, removing the previous detailed contract saving logic. - imporved logging to provide insights into the total number of deployers and contracts processed. --- .../contract_deploy/contract_deploy.go | 106 ++++++++---------- 1 file changed, 48 insertions(+), 58 deletions(-) diff --git a/scenarios/statebloat/contract_deploy/contract_deploy.go b/scenarios/statebloat/contract_deploy/contract_deploy.go index 8525d613..478065ca 100644 --- a/scenarios/statebloat/contract_deploy/contract_deploy.go +++ b/scenarios/statebloat/contract_deploy/contract_deploy.go @@ -309,6 +309,47 @@ func (s *Scenario) recordDeployedContract(receipt *types.Receipt, pendingTx *Pen "gas_per_byte": deployment.GasPerByte, "total_contracts": len(s.deployedContracts), }).Info("Contract successfully deployed and recorded") + + // 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) + } +} + +// 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) + } + + s.logger.WithFields(logrus.Fields{ + "total_deployers": len(deploymentMap), + "total_contracts": len(s.deployedContracts), + "file": "deployments.json", + }).Info("Updated deployments mapping file") + + return nil } func (s *Scenario) Run(ctx context.Context) error { @@ -403,7 +444,8 @@ func (s *Scenario) Run(ctx context.Context) error { "total_contracts": totalContracts, }).Info("All transactions completed") - return s.saveDeployedContracts() + // Log final summary + return s.logFinalSummary() } // sendTransaction sends a single contract deployment transaction with retry logic @@ -535,8 +577,8 @@ func (s *Scenario) attemptTransaction(ctx context.Context, txIdx uint64, gasMult return nil } -// saveDeployedContracts saves the deployed contracts to JSON files -func (s *Scenario) saveDeployedContracts() error { +// logFinalSummary logs the final summary of the scenario +func (s *Scenario) logFinalSummary() error { s.contractsMutex.Lock() defer s.contractsMutex.Unlock() @@ -545,60 +587,7 @@ func (s *Scenario) saveDeployedContracts() error { return nil } - // Save detailed contract info with private keys - contractsFile, err := os.Create("deployed_contracts_detailed.json") - if err != nil { - return fmt.Errorf("failed to create detailed contracts file: %w", err) - } - defer contractsFile.Close() - - err = json.NewEncoder(contractsFile).Encode(s.deployedContracts) - if err != nil { - return fmt.Errorf("failed to write detailed contracts: %w", err) - } - - // Save simple addresses list for compatibility - var addresses []string - for _, contract := range s.deployedContracts { - addresses = append(addresses, contract.ContractAddress) - } - - addressFile, err := os.Create("deployed_contracts.json") - if err != nil { - return fmt.Errorf("failed to create addresses file: %w", err) - } - defer addressFile.Close() - - err = json.NewEncoder(addressFile).Encode(addresses) - if err != nil { - return fmt.Errorf("failed to write addresses: %w", err) - } - - // Create contract-to-private-key mapping - contractKeyMap := make(map[string]string) - for _, contract := range s.deployedContracts { - contractKeyMap[contract.ContractAddress] = contract.PrivateKey - } - - keyMapFile, err := os.Create("contract_private_key_mapping.json") - if err != nil { - return fmt.Errorf("failed to create key mapping file: %w", err) - } - defer keyMapFile.Close() - - err = json.NewEncoder(keyMapFile).Encode(contractKeyMap) - if err != nil { - return fmt.Errorf("failed to write key mapping: %w", err) - } - - s.logger.WithFields(logrus.Fields{ - "contracts_deployed": len(s.deployedContracts), - "detailed_file": "deployed_contracts_detailed.json", - "addresses_file": "deployed_contracts.json", - "key_mapping_file": "contract_private_key_mapping.json", - }).Info("Successfully saved deployed contract information to JSON files") - - // Log summary of deployed contracts + // Log final summary var totalGasUsed uint64 for _, contract := range s.deployedContracts { totalGasUsed += contract.GasUsed @@ -608,7 +597,8 @@ func (s *Scenario) saveDeployedContracts() error { "total_contracts": len(s.deployedContracts), "total_gas_used": totalGasUsed, "avg_gas_per_contract": totalGasUsed / uint64(len(s.deployedContracts)), - }).Info("Deployment summary") + "deployments_file": "deployments.json", + }).Info("Final deployment summary - only deployments.json file created") return nil } From bdf65289b9e1912b831b7a0efe22b27ff41164cc Mon Sep 17 00:00:00 2001 From: CPerezz Date: Sun, 25 May 2025 00:12:34 +0200 Subject: [PATCH 15/26] refactor(contract-deploy): streamline contract deployment logic and improve transaction handling - Removed unused imports and redundant fields. - Simplified transaction processing by releasing locks earlier. - Improved logging for transaction sending and contract deployment confirmation. - Cleaned up nonce management by directly fetching the nonce from the client. --- .../contract_deploy/contract_deploy.go | 281 +++--------------- 1 file changed, 44 insertions(+), 237 deletions(-) diff --git a/scenarios/statebloat/contract_deploy/contract_deploy.go b/scenarios/statebloat/contract_deploy/contract_deploy.go index 478065ca..5fe42591 100644 --- a/scenarios/statebloat/contract_deploy/contract_deploy.go +++ b/scenarios/statebloat/contract_deploy/contract_deploy.go @@ -8,7 +8,6 @@ import ( "fmt" "math/big" "os" - "strings" "sync" "sync/atomic" "time" @@ -17,7 +16,6 @@ import ( "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/crypto" "github.com/sirupsen/logrus" "github.com/spf13/pflag" @@ -25,44 +23,26 @@ import ( "github.com/ethpandaops/spamoor/scenarios/statebloat/contract_deploy/contract" "github.com/ethpandaops/spamoor/scenariotypes" "github.com/ethpandaops/spamoor/spamoor" - "github.com/ethpandaops/spamoor/txbuilder" -) - -const ( - // GAS_PER_CONTRACT is the estimated gas cost for deploying one StateBloatToken contract - GAS_PER_CONTRACT = 4970000 // ~4.97M gas per contract - // BLOCK_GAS_LIMIT is the typical block gas limit for Ethereum mainnet - BLOCK_GAS_LIMIT = 30000000 // 30M gas ) type ScenarioOptions struct { MaxPending uint64 `yaml:"max_pending"` MaxWallets uint64 `yaml:"max_wallets"` - Rebroadcast uint64 `yaml:"rebroadcast"` BaseFee uint64 `yaml:"base_fee"` TipFee uint64 `yaml:"tip_fee"` ClientGroup string `yaml:"client_group"` - MaxTransactions uint64 `yaml:"max_transactions"` // Maximum number of transactions to send (0 for unlimited) - BlockGasLimit uint64 `yaml:"block_gas_limit"` // Block gas limit for batching (0 = use default) + 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"` - TxHash string `json:"tx_hash"` - GasUsed uint64 `json:"gas_used"` - BlockNumber uint64 `json:"block_number"` - BytecodeSize int `json:"bytecode_size"` - GasPerByte string `json:"gas_per_byte"` } // PendingTransaction tracks a transaction until it's mined type PendingTransaction struct { TxHash common.Hash - Wallet *txbuilder.Wallet - TxIndex uint64 - SentAt time.Time PrivateKey *ecdsa.PrivateKey } @@ -79,27 +59,20 @@ type Scenario struct { // Transaction tracking pendingTxs map[common.Hash]*PendingTransaction pendingTxsMutex sync.RWMutex - maxConcurrent int // Results tracking deployedContracts []ContractDeployment contractsMutex sync.Mutex - - // Nonce management per wallet - walletNonces map[common.Address]uint64 - nonceMutex sync.RWMutex } var ScenarioName = "contract-deploy" var ScenarioDefaultOptions = ScenarioOptions{ - MaxPending: 10, // Limit concurrent transactions + MaxPending: 10, MaxWallets: 0, - Rebroadcast: 1, BaseFee: 20, TipFee: 2, ClientGroup: "default", - MaxTransactions: 0, // Default to unlimited - BlockGasLimit: 0, // Use default BLOCK_GAS_LIMIT + MaxTransactions: 0, } var ScenarioDescriptor = scenariotypes.ScenarioDescriptor{ Name: ScenarioName, @@ -110,22 +83,18 @@ var ScenarioDescriptor = scenariotypes.ScenarioDescriptor{ func newScenario(logger logrus.FieldLogger) scenariotypes.Scenario { return &Scenario{ - logger: logger.WithField("scenario", ScenarioName), - pendingTxs: make(map[common.Hash]*PendingTransaction), - walletNonces: make(map[common.Address]uint64), - maxConcurrent: 5, // Conservative default + 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.Rebroadcast, "rebroadcast", ScenarioDefaultOptions.Rebroadcast, "Number of seconds to wait before re-broadcasting a transaction") 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.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 for unlimited)") - flags.Uint64Var(&s.options.BlockGasLimit, "block-gas-limit", ScenarioDefaultOptions.BlockGasLimit, "Block gas limit for batching (0 = use default)") return nil } @@ -145,11 +114,6 @@ func (s *Scenario) Init(walletPool *spamoor.WalletPool, config string) error { walletPool.SetWalletCount(1000) } - // Set concurrent transaction limit - if s.options.MaxPending > 0 { - s.maxConcurrent = int(s.options.MaxPending) - } - return nil } @@ -167,43 +131,10 @@ func (s *Scenario) getChainID(ctx context.Context) (*big.Int, error) { return } s.chainID, s.chainIDError = client.GetChainId(ctx) - if s.chainIDError == nil { - s.logger.Infof("Cached chain ID: %s", s.chainID.String()) - } }) return s.chainID, s.chainIDError } -// getWalletNonce gets the current nonce for a wallet (without incrementing) -func (s *Scenario) getWalletNonce(ctx context.Context, wallet *txbuilder.Wallet, client *txbuilder.Client) (uint64, error) { - s.nonceMutex.Lock() - defer s.nonceMutex.Unlock() - - addr := crypto.PubkeyToAddress(wallet.GetPrivateKey().PublicKey) - - // Always refresh nonce from network to avoid gaps - nonce, err := client.GetEthClient().PendingNonceAt(ctx, addr) - if err != nil { - return 0, fmt.Errorf("failed to get nonce for %s: %w", addr.Hex(), err) - } - - // Store the current network nonce - s.walletNonces[addr] = nonce - s.logger.Debugf("Current nonce for wallet %s: %d", addr.Hex(), nonce) - - return nonce, nil -} - -// incrementWalletNonce increments the local nonce counter after successful tx send -func (s *Scenario) incrementWalletNonce(wallet *txbuilder.Wallet) { - s.nonceMutex.Lock() - defer s.nonceMutex.Unlock() - - addr := crypto.PubkeyToAddress(wallet.GetPrivateKey().PublicKey) - s.walletNonces[addr]++ - s.logger.Debugf("Incremented nonce for wallet %s to: %d", addr.Hex(), s.walletNonces[addr]) -} - // waitForPendingTxSlot waits until we have capacity for another transaction func (s *Scenario) waitForPendingTxSlot(ctx context.Context) { for { @@ -211,7 +142,7 @@ func (s *Scenario) waitForPendingTxSlot(ctx context.Context) { count := len(s.pendingTxs) s.pendingTxsMutex.RUnlock() - if count < s.maxConcurrent { + if count < int(s.options.MaxPending) { return } @@ -224,15 +155,19 @@ func (s *Scenario) waitForPendingTxSlot(ctx context.Context) { // processPendingTransactions checks for transaction confirmations and updates state func (s *Scenario) processPendingTransactions(ctx context.Context) { s.pendingTxsMutex.Lock() - defer s.pendingTxsMutex.Unlock() 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 successfulDeployments []struct { + ContractAddress common.Address + PrivateKey *ecdsa.PrivateKey + } for txHash, pendingTx := range s.pendingTxs { receipt, err := ethClient.TransactionReceipt(ctx, txHash) @@ -245,9 +180,13 @@ func (s *Scenario) processPendingTransactions(ctx context.Context) { // Process successful deployment if receipt.Status == 1 && receipt.ContractAddress != (common.Address{}) { - s.recordDeployedContract(receipt, pendingTx) - } else if receipt.Status != 1 { - s.logger.Warnf("Transaction failed: %s (gas used: %d)", txHash.Hex(), receipt.GasUsed) + successfulDeployments = append(successfulDeployments, struct { + ContractAddress common.Address + PrivateKey *ecdsa.PrivateKey + }{ + ContractAddress: receipt.ContractAddress, + PrivateKey: pendingTx.PrivateKey, + }) } } @@ -256,59 +195,30 @@ func (s *Scenario) processPendingTransactions(ctx context.Context) { delete(s.pendingTxs, txHash) } - if len(confirmedTxs) > 0 { - s.logger.Debugf("Processed %d confirmed transactions, %d still pending", - len(confirmedTxs), len(s.pendingTxs)) + s.pendingTxsMutex.Unlock() + + // Process successful deployments after releasing the lock + for _, deployment := range successfulDeployments { + s.recordDeployedContract(deployment.ContractAddress, deployment.PrivateKey) } } // recordDeployedContract records a successfully deployed contract -func (s *Scenario) recordDeployedContract(receipt *types.Receipt, pendingTx *PendingTransaction) { +func (s *Scenario) recordDeployedContract(contractAddress common.Address, privateKey *ecdsa.PrivateKey) { s.contractsMutex.Lock() defer s.contractsMutex.Unlock() - // Get the actual transaction to calculate real bytecode size - client := s.walletPool.GetClient(spamoor.SelectClientByIndex, 0, s.options.ClientGroup) - var txBytes int - var gasPerByte float64 - - if client != nil { - tx, _, err := client.GetEthClient().TransactionByHash(context.Background(), receipt.TxHash) - if err == nil { - txBytes = len(tx.Data()) - gasPerByte = float64(receipt.GasUsed) / float64(max(txBytes, 1)) - } else { - // Fallback to estimated size - txBytes = 24564 // Approximate StateBloatToken bytecode size - gasPerByte = float64(receipt.GasUsed) / float64(txBytes) - } - } else { - // Fallback values - txBytes = 24564 - gasPerByte = float64(receipt.GasUsed) / float64(txBytes) - } - deployment := ContractDeployment{ - ContractAddress: receipt.ContractAddress.Hex(), - PrivateKey: fmt.Sprintf("0x%x", crypto.FromECDSA(pendingTx.PrivateKey)), - TxHash: receipt.TxHash.Hex(), - GasUsed: receipt.GasUsed, - BlockNumber: receipt.BlockNumber.Uint64(), - BytecodeSize: txBytes, - GasPerByte: fmt.Sprintf("%.2f", gasPerByte), + ContractAddress: contractAddress.Hex(), + PrivateKey: fmt.Sprintf("0x%x", crypto.FromECDSA(privateKey)), } s.deployedContracts = append(s.deployedContracts, deployment) s.logger.WithFields(logrus.Fields{ "contract_address": deployment.ContractAddress, - "tx_hash": deployment.TxHash, - "gas_used": deployment.GasUsed, - "block_number": deployment.BlockNumber, - "bytecode_size": deployment.BytecodeSize, - "gas_per_byte": deployment.GasPerByte, "total_contracts": len(s.deployedContracts), - }).Info("Contract successfully deployed and recorded") + }).Info("Contract deployed") // Save the deployments.json file each time a contract is confirmed if err := s.saveDeploymentsMapping(); err != nil { @@ -324,7 +234,6 @@ func (s *Scenario) saveDeploymentsMapping() error { for _, contract := range s.deployedContracts { privateKey := contract.PrivateKey contractAddr := contract.ContractAddress - deploymentMap[privateKey] = append(deploymentMap[privateKey], contractAddr) } @@ -343,12 +252,6 @@ func (s *Scenario) saveDeploymentsMapping() error { return fmt.Errorf("failed to write deployments.json: %w", err) } - s.logger.WithFields(logrus.Fields{ - "total_deployers": len(deploymentMap), - "total_contracts": len(s.deployedContracts), - "file": "deployments.json", - }).Info("Updated deployments mapping file") - return nil } @@ -362,20 +265,7 @@ func (s *Scenario) Run(ctx context.Context) error { return fmt.Errorf("failed to get chain ID: %w", err) } - // Determine block gas limit to use - blockGasLimit := s.options.BlockGasLimit - if blockGasLimit == 0 { - blockGasLimit = BLOCK_GAS_LIMIT - } - - // Calculate how many contracts can fit in one block - contractsPerBlock := int(blockGasLimit / GAS_PER_CONTRACT) - if contractsPerBlock == 0 { - contractsPerBlock = 1 - } - - s.logger.Infof("Chain ID: %s, Block gas limit: %d, Gas per contract: %d, Contracts per block: %d, Max concurrent: %d", - chainID.String(), blockGasLimit, GAS_PER_CONTRACT, contractsPerBlock, s.maxConcurrent) + s.logger.Infof("Chain ID: %s", chainID.String()) txIdxCounter := uint64(0) totalTxCount := atomic.Uint64{} @@ -433,51 +323,21 @@ func (s *Scenario) Run(ctx context.Context) error { time.Sleep(2 * time.Second) } - // Save results to JSON + // Log final summary s.contractsMutex.Lock() totalContracts := len(s.deployedContracts) s.contractsMutex.Unlock() s.logger.WithFields(logrus.Fields{ - "test": "contract-deploy", "total_txs": totalTxCount.Load(), "total_contracts": totalContracts, }).Info("All transactions completed") - // Log final summary - return s.logFinalSummary() + return nil } -// sendTransaction sends a single contract deployment transaction with retry logic +// sendTransaction sends a single contract deployment transaction func (s *Scenario) sendTransaction(ctx context.Context, txIdx uint64) error { - maxRetries := 3 - baseGasMultiplier := 1.0 - - for attempt := 0; attempt < maxRetries; attempt++ { - err := s.attemptTransaction(ctx, txIdx, baseGasMultiplier) - if err == nil { - return nil - } - - // Check if it's an underpriced error - if strings.Contains(err.Error(), "replacement transaction underpriced") || - strings.Contains(err.Error(), "transaction underpriced") { - baseGasMultiplier += 0.2 // Increase gas by 20% each retry - s.logger.Warnf("Transaction %d underpriced, retrying with %.1fx gas (attempt %d/%d)", - txIdx, baseGasMultiplier, attempt+1, maxRetries) - 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) -} - -// attemptTransaction makes a single attempt to send a transaction -func (s *Scenario) attemptTransaction(ctx context.Context, txIdx uint64, gasMultiplier float64) error { // Get client and wallet client := s.walletPool.GetClient(spamoor.SelectClientRoundRobin, 0, s.options.ClientGroup) wallet := s.walletPool.GetWallet(spamoor.SelectWalletRoundRobin, 0) @@ -496,9 +356,10 @@ func (s *Scenario) attemptTransaction(ctx context.Context, txIdx uint64, gasMult } // Get current nonce for this wallet - nonce, err := s.getWalletNonce(ctx, wallet, client) + addr := crypto.PubkeyToAddress(wallet.GetPrivateKey().PublicKey) + nonce, err := client.GetEthClient().PendingNonceAt(ctx, addr) if err != nil { - return fmt.Errorf("failed to get nonce: %w", err) + return fmt.Errorf("failed to get nonce for %s: %w", addr.Hex(), err) } // Create transaction auth @@ -509,22 +370,14 @@ func (s *Scenario) attemptTransaction(ctx context.Context, txIdx uint64, gasMult auth.Nonce = big.NewInt(int64(nonce)) auth.Value = big.NewInt(0) - auth.GasLimit = GAS_PER_CONTRACT + GAS_PER_CONTRACT*5/100 - - // Set EIP-1559 fee parameters with dynamic adjustment - baseFee := s.options.BaseFee - tipFee := s.options.TipFee - - if gasMultiplier > 1.0 { - baseFee = uint64(float64(baseFee) * gasMultiplier) - tipFee = uint64(float64(tipFee) * gasMultiplier) - } + auth.GasLimit = 5200000 // Fixed gas limit for contract deployment - if baseFee > 0 { - auth.GasFeeCap = new(big.Int).Mul(big.NewInt(int64(baseFee)), big.NewInt(1000000000)) + // 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 tipFee > 0 { - auth.GasTipCap = new(big.Int).Mul(big.NewInt(int64(tipFee)), 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 @@ -541,7 +394,7 @@ func (s *Scenario) attemptTransaction(ctx context.Context, txIdx uint64, gasMult return fmt.Errorf("failed to get eth client") } - address, tx, _, err := contract.DeployContract(auth, ethClient, saltInt) + _, tx, _, err := contract.DeployContract(auth, ethClient, saltInt) if err != nil { return fmt.Errorf("failed to deploy contract: %w", err) } @@ -549,9 +402,6 @@ func (s *Scenario) attemptTransaction(ctx context.Context, txIdx uint64, gasMult // Track pending transaction pendingTx := &PendingTransaction{ TxHash: tx.Hash(), - Wallet: wallet, - TxIndex: txIdx, - SentAt: time.Now(), PrivateKey: wallet.GetPrivateKey(), } @@ -560,52 +410,9 @@ func (s *Scenario) attemptTransaction(ctx context.Context, txIdx uint64, gasMult s.pendingTxsMutex.Unlock() s.logger.WithFields(logrus.Fields{ - "tx_index": txIdx, - "tx_hash": tx.Hash().Hex(), - "expected_address": address.Hex(), - "nonce": nonce, - "wallet": crypto.PubkeyToAddress(wallet.GetPrivateKey().PublicKey).Hex(), - "gas_limit": auth.GasLimit, - "base_fee_gwei": baseFee, - "tip_fee_gwei": tipFee, - "gas_multiplier": fmt.Sprintf("%.1fx", gasMultiplier), - }).Info("Transaction sent successfully") - - // Only increment nonce after successful send - s.incrementWalletNonce(wallet) + "tx_hash": tx.Hash().Hex(), + "nonce": nonce, + }).Info("Transaction sent") return nil } - -// logFinalSummary logs the final summary of the scenario -func (s *Scenario) logFinalSummary() error { - s.contractsMutex.Lock() - defer s.contractsMutex.Unlock() - - if len(s.deployedContracts) == 0 { - s.logger.Info("No contracts were deployed") - return nil - } - - // Log final summary - var totalGasUsed uint64 - for _, contract := range s.deployedContracts { - totalGasUsed += contract.GasUsed - } - - s.logger.WithFields(logrus.Fields{ - "total_contracts": len(s.deployedContracts), - "total_gas_used": totalGasUsed, - "avg_gas_per_contract": totalGasUsed / uint64(len(s.deployedContracts)), - "deployments_file": "deployments.json", - }).Info("Final deployment summary - only deployments.json file created") - - return nil -} - -func max(a, b int) int { - if a > b { - return a - } - return b -} From bdbaa836400e47872ad31e63ff3c43383e25375e Mon Sep 17 00:00:00 2001 From: CPerezz Date: Sun, 25 May 2025 23:05:32 +0200 Subject: [PATCH 16/26] feat(contract-deploy): enhance transaction handling and dynamic fee adjustment - Added functionality to dynamically adjust transaction fees based on current network conditions. - Implemented retry logic for transaction sending with exponential backoff for base fee errors. --- .../contract_deploy/contract_deploy.go | 131 +++++++++++++++++- 1 file changed, 126 insertions(+), 5 deletions(-) diff --git a/scenarios/statebloat/contract_deploy/contract_deploy.go b/scenarios/statebloat/contract_deploy/contract_deploy.go index 5fe42591..cc7e80af 100644 --- a/scenarios/statebloat/contract_deploy/contract_deploy.go +++ b/scenarios/statebloat/contract_deploy/contract_deploy.go @@ -8,6 +8,7 @@ import ( "fmt" "math/big" "os" + "strings" "sync" "sync/atomic" "time" @@ -20,6 +21,7 @@ import ( "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/scenariotypes" "github.com/ethpandaops/spamoor/spamoor" @@ -167,6 +169,8 @@ func (s *Scenario) processPendingTransactions(ctx context.Context) { var successfulDeployments []struct { ContractAddress common.Address PrivateKey *ecdsa.PrivateKey + Receipt *types.Receipt + TxHash common.Hash } for txHash, pendingTx := range s.pendingTxs { @@ -183,9 +187,13 @@ func (s *Scenario) processPendingTransactions(ctx context.Context) { 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, }) } } @@ -199,15 +207,16 @@ func (s *Scenario) processPendingTransactions(ctx context.Context) { // Process successful deployments after releasing the lock for _, deployment := range successfulDeployments { - s.recordDeployedContract(deployment.ContractAddress, deployment.PrivateKey) + 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) { +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)), @@ -215,10 +224,35 @@ func (s *Scenario) recordDeployedContract(contractAddress common.Address, privat s.deployedContracts = append(s.deployedContracts, deployment) + // Calculate detailed information for logging + walletAddress := crypto.PubkeyToAddress(privateKey.PublicKey) + + // Get the actual transaction to calculate real bytecode size + client := s.walletPool.GetClient(spamoor.SelectClientByIndex, 0, s.options.ClientGroup) + var bytecodeSize int = 24564 // Default fallback + var gasPerByte float64 + + if client != nil { + tx, _, err := client.GetEthClient().TransactionByHash(context.Background(), txHash) + if err == nil { + bytecodeSize = len(tx.Data()) + } + } + + // Calculate gas per byte + gasPerByte = float64(receipt.GasUsed) / float64(max(bytecodeSize, 1)) + + // Log with detailed information s.logger.WithFields(logrus.Fields{ + "block_number": receipt.BlockNumber.Uint64(), + "bytecode_size": bytecodeSize, "contract_address": deployment.ContractAddress, + "gas_per_byte": fmt.Sprintf("%.2f", gasPerByte), + "gas_used": receipt.GasUsed, "total_contracts": len(s.deployedContracts), - }).Info("Contract deployed") + "tx_hash": txHash.Hex(), + "wallet_address": walletAddress.Hex(), + }).Info("Contract successfully deployed and recorded") // Save the deployments.json file each time a contract is confirmed if err := s.saveDeploymentsMapping(); err != nil { @@ -226,6 +260,14 @@ func (s *Scenario) recordDeployedContract(contractAddress common.Address, privat } } +// 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 @@ -338,6 +380,82 @@ func (s *Scenario) Run(ctx context.Context) error { // 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)) + + // Set new base fee to current base fee + 20% buffer + newBaseFeeGwei := new(big.Int).Mul(currentBaseFeeGwei, big.NewInt(120)) + newBaseFeeGwei = new(big.Int).Div(newBaseFeeGwei, big.NewInt(100)) + + // Ensure minimum increase of 5 gwei + minIncrease := big.NewInt(5) + if newBaseFeeGwei.Cmp(new(big.Int).Add(big.NewInt(int64(s.options.BaseFee)), minIncrease)) < 0 { + newBaseFeeGwei = new(big.Int).Add(big.NewInt(int64(s.options.BaseFee)), minIncrease) + } + + 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 = 3 // 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, s.options.ClientGroup) wallet := s.walletPool.GetWallet(spamoor.SelectWalletRoundRobin, 0) @@ -410,8 +528,11 @@ func (s *Scenario) sendTransaction(ctx context.Context, txIdx uint64) error { s.pendingTxsMutex.Unlock() s.logger.WithFields(logrus.Fields{ - "tx_hash": tx.Hash().Hex(), - "nonce": nonce, + "tx_hash": tx.Hash().Hex(), + "nonce": nonce, + "base_fee_gwei": s.options.BaseFee, + "tip_fee_gwei": s.options.TipFee, + "attempt": attempt + 1, }).Info("Transaction sent") return nil From 82138080f71dee7402ee694734d691543112974f Mon Sep 17 00:00:00 2001 From: CPerezz Date: Sun, 25 May 2025 23:18:19 +0200 Subject: [PATCH 17/26] chore: update readme --- scenarios/statebloat/contract_deploy/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/scenarios/statebloat/contract_deploy/README.md b/scenarios/statebloat/contract_deploy/README.md index f0049958..dd839c48 100644 --- a/scenarios/statebloat/contract_deploy/README.md +++ b/scenarios/statebloat/contract_deploy/README.md @@ -5,7 +5,7 @@ This scenario deploys contracts that are exactly 24kB in size (EIP-170 limit) to ## How it Works 1. Generates a contract with exactly 24,576 bytes of runtime code -2. Deploys the contract using CREATE +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 @@ -82,7 +82,7 @@ spamoor statebloat/contract-deploy \ ### 1. Start Anvil ```bash -anvil --hardfork pectra +anvil --hardfork latest --block-time 12 ``` You can add other flags as needed (e.g., `--no-mining` if you want to control mining manually). From 891a0b4cd00161de15e7cf5be866af6434a41b50 Mon Sep 17 00:00:00 2001 From: CPerezz Date: Mon, 26 May 2025 00:17:16 +0200 Subject: [PATCH 18/26] chore: Clarify running instructions in contract_deploy readme --- .../statebloat/contract_deploy/README.md | 97 ++++--------------- 1 file changed, 19 insertions(+), 78 deletions(-) diff --git a/scenarios/statebloat/contract_deploy/README.md b/scenarios/statebloat/contract_deploy/README.md index dd839c48..204e3dfe 100644 --- a/scenarios/statebloat/contract_deploy/README.md +++ b/scenarios/statebloat/contract_deploy/README.md @@ -1,11 +1,11 @@ -# Contract Deployment State Bloat +# 🏭 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. +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 @@ -16,12 +16,12 @@ This scenario deploys contracts that are exactly 24kB in size (EIP-170 limit) to - Account trie node - Total state growth: ~24.7kB per deployment -## Gas Cost Breakdown +## ⛽ 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 +- **Total: 4,967,200 gas per deployment** ## Batch Strategy @@ -32,87 +32,28 @@ The scenario automatically calculates how many contracts can fit in one block: This ensures optimal utilization of block space while maintaining predictable transaction inclusion patterns. -## Usage +## 🚀 Usage +### Build ```bash -spamoor statebloat/contract-deploy [flags] +go build -o bin/spamoor cmd/spamoor/main.go ``` -### Configuration - -#### Base Settings (required) -- `--privkey` - Private key of the sending wallet -- `--rpchost` - RPC endpoint(s) to send transactions to - -#### Volume Control -- `--max-transactions` - Maximum number of transactions to send (0 for unlimited) -- `--max-pending` - Maximum number of pending deployments -- `--block-gas-limit` - Block gas limit for batching (default: 30,000,000, 0 = use default) - -#### Transaction Settings -- `--basefee` - Max fee per gas in gwei (default: 20) -- `--tipfee` - Max tip per gas in gwei (default: 2) -- `--rebroadcast` - Seconds to wait before rebroadcasting (default: 1) - -#### Wallet Management -- `--max-wallets` - Maximum number of child wallets to use -- `--client-group` - Client group to use for sending transactions (default: "default") - -## Examples - -Deploy 30 contracts in batches: -```bash -spamoor statebloat/contract-deploy \ - --privkey "" \ - --rpchost http://localhost:8545 \ - --max-transactions 30 -``` - -Deploy with custom block gas limit (for testnets): -```bash -spamoor statebloat/contract-deploy \ - --privkey "" \ - --rpchost http://localhost:8545 \ - --max-transactions 10 \ - --block-gas-limit 15000000 -``` - -## Running Against a Local Anvil Node - -### 1. Start Anvil - +### Run ```bash -anvil --hardfork latest --block-time 12 +./bin/spamoor --privkey --rpchost http://localhost:8545 contract-deploy [flags] ``` -You can add other flags as needed (e.g., `--no-mining` if you want to control mining manually). - -### 2. Build Spamoor (if not already built) - -```bash -go build -o spamoor ./cmd/spamoor -``` - -### 3. Run the Scenario - -```bash -./spamoor statebloat/contract-deploy \ - --privkey \ - --rpchost http://localhost:8545 \ - --max-transactions 30 -``` - -- Replace `` with the private key of a funded account in your Anvil instance (Anvil prints these on startup). -- The scenario will automatically calculate the optimal batch size based on gas limits. - -### 4. Mining Notes - -- If you started Anvil with `--no-mining`, you will need to manually mine blocks (e.g., by calling `evm_mine` via RPC or using Anvil's console) to include the transactions. -- If you use Anvil's default mining mode, blocks will be mined automatically as transactions are sent. -- The scenario waits for each block to be mined before sending the next batch, ensuring predictable transaction ordering. - -### 5. See All Flags +#### Key Flags +- `--max-transactions` - Number of contracts to deploy (0 = infinite, default: 0) +- `--max-pending` - Max concurrent pending transactions (default: 10) +- `--max-wallets` - Max child wallets to use (default: 1000) +- `--basefee` - Base fee per gas in gwei (default: 20) +- `--tipfee` - Tip fee per gas in gwei (default: 2) +#### Example with Anvil node ```bash -./spamoor statebloat/contract-deploy --help +./bin/spamoor --privkey ac0974bec39a17e36ba4a6b4d238ff944bacb478cbed5efcae784d7bf4f2ff80 \ + --rpchost http://localhost:8545 contract-deploy \ + --max-transactions 100 --max-pending 20 --basefee 25 --tipfee 5 ``` \ No newline at end of file From c2d431369be84a015d76312cbb90e986278499af Mon Sep 17 00:00:00 2001 From: CPerezz Date: Wed, 4 Jun 2025 12:51:34 +0200 Subject: [PATCH 19/26] update: Contract bytecode reduction to account for extra costs --- .../contract/StateBloatToken.abi | 2 +- .../contract/StateBloatToken.bin | 2 +- .../contract/StateBloatToken.go | 314 +----------------- .../contract/StateBloatToken.sol | 40 --- 4 files changed, 4 insertions(+), 354 deletions(-) diff --git a/scenarios/statebloat/contract_deploy/contract/StateBloatToken.abi b/scenarios/statebloat/contract_deploy/contract/StateBloatToken.abi index 4dea8206..0f67a8f3 100644 --- a/scenarios/statebloat/contract_deploy/contract/StateBloatToken.abi +++ b/scenarios/statebloat/contract_deploy/contract/StateBloatToken.abi @@ -1 +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":"dummy66","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"dummy67","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"dummy68","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"dummy69","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"dummy7","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"dummy70","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"dummy71","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"dummy72","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"dummy73","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"dummy74","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"dummy75","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 +[{"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 index 10e9b41a..7d363997 100644 --- a/scenarios/statebloat/contract_deploy/contract/StateBloatToken.bin +++ b/scenarios/statebloat/contract_deploy/contract/StateBloatToken.bin @@ -1 +1 @@ -60a060405234801561000f575f5ffd5b50604051615fd4380380615fd4833981810160405281019061003191906101f4565b6040518060400160405280601181526020017f537461746520426c6f617420546f6b656e0000000000000000000000000000008152505f90816100749190610453565b506040518060400160405280600381526020017f5342540000000000000000000000000000000000000000000000000000000000815250600190816100b99190610453565b50601260025f6101000a81548160ff021916908360ff160217905550806080818152505060025f9054906101000a900460ff16600a6100f8919061068a565b620f424061010691906106d4565b60038190555060035460045f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055503373ffffffffffffffffffffffffffffffffffffffff165f73ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef6003546040516101af9190610724565b60405180910390a35061073d565b5f5ffd5b5f819050919050565b6101d3816101c1565b81146101dd575f5ffd5b50565b5f815190506101ee816101ca565b92915050565b5f60208284031215610209576102086101bd565b5b5f610216848285016101e0565b91505092915050565b5f81519050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f600282049050600182168061029a57607f821691505b6020821081036102ad576102ac610256565b5b50919050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f6008830261030f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff826102d4565b61031986836102d4565b95508019841693508086168417925050509392505050565b5f819050919050565b5f61035461034f61034a846101c1565b610331565b6101c1565b9050919050565b5f819050919050565b61036d8361033a565b6103816103798261035b565b8484546102e0565b825550505050565b5f5f905090565b610398610389565b6103a3818484610364565b505050565b5b818110156103c6576103bb5f82610390565b6001810190506103a9565b5050565b601f82111561040b576103dc816102b3565b6103e5846102c5565b810160208510156103f4578190505b610408610400856102c5565b8301826103a8565b50505b505050565b5f82821c905092915050565b5f61042b5f1984600802610410565b1980831691505092915050565b5f610443838361041c565b9150826002028217905092915050565b61045c8261021f565b67ffffffffffffffff81111561047557610474610229565b5b61047f8254610283565b61048a8282856103ca565b5f60209050601f8311600181146104bb575f84156104a9578287015190505b6104b38582610438565b86555061051a565b601f1984166104c9866102b3565b5f5b828110156104f0578489015182556001820191506020850194506020810190506104cb565b8683101561050d5784890151610509601f89168261041c565b8355505b6001600288020188555050505b505050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f8160011c9050919050565b5f5f8291508390505b60018511156105a4578086048111156105805761057f610522565b5b600185161561058f5780820291505b808102905061059d8561054f565b9450610564565b94509492505050565b5f826105bc5760019050610677565b816105c9575f9050610677565b81600181146105df57600281146105e957610618565b6001915050610677565b60ff8411156105fb576105fa610522565b5b8360020a91508482111561061257610611610522565b5b50610677565b5060208310610133831016604e8410600b841016171561064d5782820a90508381111561064857610647610522565b5b610677565b61065a848484600161055b565b9250905081840481111561067157610670610522565b5b81810290505b9392505050565b5f60ff82169050919050565b5f610694826101c1565b915061069f8361067e565b92506106cc7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff84846105ad565b905092915050565b5f6106de826101c1565b91506106e9836101c1565b92508282026106f7816101c1565b9150828204841483151761070e5761070d610522565b5b5092915050565b61071e816101c1565b82525050565b5f6020820190506107375f830184610715565b92915050565b60805161587f6107555f395f614a7b015261587f5ff3fe608060405234801561000f575f5ffd5b5060043610610606575f3560e01c8063657b6ef711610319578063b1802b9a116101a6578063d9bb3174116100f2578063f26c779b116100ab578063f8716f1411610085578063f8716f1414611360578063faf35ced1461137e578063fe7d5996146113ae578063ffbf0469146113cc57610606565b8063f26c779b14611306578063f4978b0414611324578063f5f573811461134257610606565b8063d9bb31741461122e578063dc1d8a9b1461124c578063dd62ed3e1461126a578063e2d275301461129a578063e8c927b3146112b8578063eb4329c8146112d657610606565b8063bbe231321161015f578063c958d4bf11610139578063c958d4bf146111b6578063cfd66863146111d4578063d101dcd0146111f2578063d74194691461121057610606565b8063bbe231321461114a578063bfa0b13314611168578063c2be97e31461118657610606565b8063b1802b9a14611072578063b2bb360e146110a2578063b4c48668146110c0578063b66dd750146110de578063b9a6d645146110fc578063bb9bfe061461111a57610606565b80637e544937116102655780639c5dfe731161021e578063a9059cbb116101f8578063a9059cbb14610fd6578063aaa7af7014611006578063acc5aee914611024578063ad8f42211461105457610606565b80639c5dfe7314610f7c5780639df61a2514610f9a578063a891d4d414610fb857610606565b80637e54493714610eb65780637f34d94b14610ed45780638619d60714610ef25780638789ca6714610f105780638f4a840614610f4057806395d89b4114610f5e57610606565b806374f83d02116102d25780637a319c18116102ac5780637a319c1814610e2c5780637c66673e14610e4a5780637c72ed0d14610e7a5780637dffdc3214610e9857610606565b806374f83d0214610dd257806377c0209e14610df0578063792c7f3e14610e0e57610606565b8063657b6ef714610ce8578063672151fe14610d185780636abceacd14610d365780636c12ed2814610d5457806370a0823114610d8457806374e73fd314610db457610606565b8063313ce567116104975780634b3c7f5f116103e357806358b6a9bd1161039c57806361b970eb1161037657806361b970eb14610c70578063639ec53a14610c8e5780636547317414610cac5780636578534c14610cca57610606565b806358b6a9bd14610c16578063595471b814610c345780635af92c0514610c5257610606565b80634b3c7f5f14610b3e5780634e1dbb8214610b5c5780634f5e555714610b7a5780634f7bd75a14610b9857806354c2792014610bc8578063552a1b5614610be657610606565b80633ea117ce1161045057806342937dbd1161042a57806342937dbd14610ab457806343a6b92d14610ad257806344050a2814610af05780634a2e93c614610b2057610606565b80633ea117ce14610a5a5780634128a85d14610a78578063418b181614610a9657610606565b8063313ce5671461098257806334517f0b146109a0578063378c5382146109be57806339e0bd12146109dc5780633a13199014610a0c5780633b6be45914610a3c57610606565b80631bbffe6f1161055657806321ecd7a31161050f5780632545d8b7116104e95780632545d8b7146108f85780632787325b14610916578063291c3bd7146109345780633125f37a1461096457610606565b806321ecd7a31461088c578063239af2a5146108aa57806323b872dd146108c857610606565b80631bbffe6f146107c65780631d527cde146107f65780631eaa7c52146108145780631f29783f146108325780631f449589146108505780631fd298ec1461086e57610606565b806312901b42116105c357806318160ddd1161059d57806318160ddd1461073c57806319cf6a911461075a5780631a97f18e146107785780631b17c65c1461079657610606565b806312901b42146106e257806313ebb5ec1461070057806316a3045b1461071e57610606565b80630460faf61461060a57806306fdde031461063a5780630717b16114610658578063095ea7b3146106765780630cb7a9e7146106a65780631215a3ab146106c4575b5f5ffd5b610624600480360381019061061f91906153a3565b6113ea565b604051610631919061540d565b60405180910390f35b6106426116ca565b60405161064f9190615496565b60405180910390f35b610660611755565b60405161066d91906154c5565b60405180910390f35b610690600480360381019061068b91906154de565b61175d565b60405161069d919061540d565b60405180910390f35b6106ae61184a565b6040516106bb91906154c5565b60405180910390f35b6106cc611852565b6040516106d991906154c5565b60405180910390f35b6106ea61185a565b6040516106f791906154c5565b60405180910390f35b610708611862565b60405161071591906154c5565b60405180910390f35b61072661186a565b60405161073391906154c5565b60405180910390f35b610744611872565b60405161075191906154c5565b60405180910390f35b610762611878565b60405161076f91906154c5565b60405180910390f35b610780611880565b60405161078d91906154c5565b60405180910390f35b6107b060048036038101906107ab91906153a3565b611888565b6040516107bd919061540d565b60405180910390f35b6107e060048036038101906107db91906153a3565b611b68565b6040516107ed919061540d565b60405180910390f35b6107fe611e48565b60405161080b91906154c5565b60405180910390f35b61081c611e50565b60405161082991906154c5565b60405180910390f35b61083a611e58565b60405161084791906154c5565b60405180910390f35b610858611e60565b60405161086591906154c5565b60405180910390f35b610876611e68565b60405161088391906154c5565b60405180910390f35b610894611e70565b6040516108a191906154c5565b60405180910390f35b6108b2611e78565b6040516108bf91906154c5565b60405180910390f35b6108e260048036038101906108dd91906153a3565b611e80565b6040516108ef919061540d565b60405180910390f35b610900612160565b60405161090d91906154c5565b60405180910390f35b61091e612168565b60405161092b91906154c5565b60405180910390f35b61094e600480360381019061094991906153a3565b612170565b60405161095b919061540d565b60405180910390f35b61096c612450565b60405161097991906154c5565b60405180910390f35b61098a612458565b6040516109979190615537565b60405180910390f35b6109a861246a565b6040516109b591906154c5565b60405180910390f35b6109c6612472565b6040516109d391906154c5565b60405180910390f35b6109f660048036038101906109f191906153a3565b61247a565b604051610a03919061540d565b60405180910390f35b610a266004803603810190610a2191906153a3565b61275a565b604051610a33919061540d565b60405180910390f35b610a44612a3a565b604051610a5191906154c5565b60405180910390f35b610a62612a42565b604051610a6f91906154c5565b60405180910390f35b610a80612a4a565b604051610a8d91906154c5565b60405180910390f35b610a9e612a52565b604051610aab91906154c5565b60405180910390f35b610abc612a5a565b604051610ac991906154c5565b60405180910390f35b610ada612a62565b604051610ae791906154c5565b60405180910390f35b610b0a6004803603810190610b0591906153a3565b612a6a565b604051610b17919061540d565b60405180910390f35b610b28612d4a565b604051610b3591906154c5565b60405180910390f35b610b46612d52565b604051610b5391906154c5565b60405180910390f35b610b64612d5a565b604051610b7191906154c5565b60405180910390f35b610b82612d62565b604051610b8f91906154c5565b60405180910390f35b610bb26004803603810190610bad91906153a3565b612d6a565b604051610bbf919061540d565b60405180910390f35b610bd061304a565b604051610bdd91906154c5565b60405180910390f35b610c006004803603810190610bfb91906153a3565b613052565b604051610c0d919061540d565b60405180910390f35b610c1e613332565b604051610c2b91906154c5565b60405180910390f35b610c3c61333a565b604051610c4991906154c5565b60405180910390f35b610c5a613342565b604051610c6791906154c5565b60405180910390f35b610c7861334a565b604051610c8591906154c5565b60405180910390f35b610c96613352565b604051610ca391906154c5565b60405180910390f35b610cb461335a565b604051610cc191906154c5565b60405180910390f35b610cd2613362565b604051610cdf91906154c5565b60405180910390f35b610d026004803603810190610cfd91906153a3565b61336a565b604051610d0f919061540d565b60405180910390f35b610d2061364a565b604051610d2d91906154c5565b60405180910390f35b610d3e613652565b604051610d4b91906154c5565b60405180910390f35b610d6e6004803603810190610d6991906153a3565b61365a565b604051610d7b919061540d565b60405180910390f35b610d9e6004803603810190610d999190615550565b61393a565b604051610dab91906154c5565b60405180910390f35b610dbc61394f565b604051610dc991906154c5565b60405180910390f35b610dda613957565b604051610de791906154c5565b60405180910390f35b610df861395f565b604051610e0591906154c5565b60405180910390f35b610e16613967565b604051610e2391906154c5565b60405180910390f35b610e3461396f565b604051610e4191906154c5565b60405180910390f35b610e646004803603810190610e5f91906153a3565b613977565b604051610e71919061540d565b60405180910390f35b610e82613c57565b604051610e8f91906154c5565b60405180910390f35b610ea0613c5f565b604051610ead91906154c5565b60405180910390f35b610ebe613c67565b604051610ecb91906154c5565b60405180910390f35b610edc613c6f565b604051610ee991906154c5565b60405180910390f35b610efa613c77565b604051610f0791906154c5565b60405180910390f35b610f2a6004803603810190610f2591906153a3565b613c7f565b604051610f37919061540d565b60405180910390f35b610f48613f5f565b604051610f5591906154c5565b60405180910390f35b610f66613f67565b604051610f739190615496565b60405180910390f35b610f84613ff3565b604051610f9191906154c5565b60405180910390f35b610fa2613ffb565b604051610faf91906154c5565b60405180910390f35b610fc0614003565b604051610fcd91906154c5565b60405180910390f35b610ff06004803603810190610feb91906154de565b61400b565b604051610ffd919061540d565b60405180910390f35b61100e6141a1565b60405161101b91906154c5565b60405180910390f35b61103e600480360381019061103991906153a3565b6141a9565b60405161104b919061540d565b60405180910390f35b61105c614489565b60405161106991906154c5565b60405180910390f35b61108c600480360381019061108791906153a3565b614491565b604051611099919061540d565b60405180910390f35b6110aa614771565b6040516110b791906154c5565b60405180910390f35b6110c8614779565b6040516110d591906154c5565b60405180910390f35b6110e6614781565b6040516110f391906154c5565b60405180910390f35b611104614789565b60405161111191906154c5565b60405180910390f35b611134600480360381019061112f91906153a3565b614791565b604051611141919061540d565b60405180910390f35b611152614a71565b60405161115f91906154c5565b60405180910390f35b611170614a79565b60405161117d91906154c5565b60405180910390f35b6111a0600480360381019061119b91906153a3565b614a9d565b6040516111ad919061540d565b60405180910390f35b6111be614d7d565b6040516111cb91906154c5565b60405180910390f35b6111dc614d85565b6040516111e991906154c5565b60405180910390f35b6111fa614d8d565b60405161120791906154c5565b60405180910390f35b611218614d95565b60405161122591906154c5565b60405180910390f35b611236614d9d565b60405161124391906154c5565b60405180910390f35b611254614da5565b60405161126191906154c5565b60405180910390f35b611284600480360381019061127f919061557b565b614dad565b60405161129191906154c5565b60405180910390f35b6112a2614dcd565b6040516112af91906154c5565b60405180910390f35b6112c0614dd5565b6040516112cd91906154c5565b60405180910390f35b6112f060048036038101906112eb91906153a3565b614ddd565b6040516112fd919061540d565b60405180910390f35b61130e615002565b60405161131b91906154c5565b60405180910390f35b61132c61500a565b60405161133991906154c5565b60405180910390f35b61134a615012565b60405161135791906154c5565b60405180910390f35b61136861501a565b60405161137591906154c5565b60405180910390f35b611398600480360381019061139391906153a3565b615022565b6040516113a5919061540d565b60405180910390f35b6113b6615302565b6040516113c391906154c5565b60405180910390f35b6113d461530a565b6040516113e191906154c5565b60405180910390f35b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054101561146b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161146290615603565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015611526576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161151d9061566b565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461157291906156b6565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546115c591906156e9565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461165391906156b6565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516116b791906154c5565b60405180910390a3600190509392505050565b5f80546116d690615749565b80601f016020809104026020016040519081016040528092919081815260200182805461170290615749565b801561174d5780601f106117245761010080835404028352916020019161174d565b820191905f5260205f20905b81548152906001019060200180831161173057829003601f168201915b505050505081565b5f602f905090565b5f8160055f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9258460405161183891906154c5565b60405180910390a36001905092915050565b5f601b905090565b5f6005905090565b5f601a905090565b5f601d905090565b5f6033905090565b60035481565b5f6008905090565b5f6003905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015611909576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161190090615603565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156119c4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119bb9061566b565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254611a1091906156b6565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254611a6391906156e9565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254611af191906156b6565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051611b5591906154c5565b60405180910390a3600190509392505050565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015611be9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611be090615603565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015611ca4576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c9b9061566b565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254611cf091906156b6565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254611d4391906156e9565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254611dd191906156b6565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051611e3591906154c5565b60405180910390a3600190509392505050565b5f6002905090565b5f6010905090565b5f6048905090565b5f6041905090565b5f6035905090565b5f602e905090565b5f602c905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015611f01576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ef890615603565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015611fbc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611fb39061566b565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461200891906156b6565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461205b91906156e9565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546120e991906156b6565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161214d91906154c5565b60405180910390a3600190509392505050565b5f6001905090565b5f6045905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156121f1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016121e8906157c3565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156122ac576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016122a39061582b565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546122f891906156b6565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461234b91906156e9565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546123d991906156b6565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161243d91906154c5565b60405180910390a3600190509392505050565b5f6034905090565b60025f9054906101000a900460ff1681565b5f603c905090565b5f604b905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156124fb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016124f290615603565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156125b6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016125ad9061566b565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461260291906156b6565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461265591906156e9565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546126e391906156b6565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161274791906154c5565b60405180910390a3600190509392505050565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156127db576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016127d290615603565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015612896576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161288d9061566b565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546128e291906156b6565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461293591906156e9565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546129c391906156b6565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051612a2791906154c5565b60405180910390a3600190509392505050565b5f6004905090565b5f600c905090565b5f6006905090565b5f601c905090565b5f6032905090565b5f6023905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015612aeb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612ae290615603565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015612ba6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612b9d9061566b565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254612bf291906156b6565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254612c4591906156e9565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254612cd391906156b6565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051612d3791906154c5565b60405180910390a3600190509392505050565b5f6011905090565b5f6021905090565b5f601f905090565b5f6026905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015612deb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612de290615603565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015612ea6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612e9d9061566b565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254612ef291906156b6565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254612f4591906156e9565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254612fd391906156b6565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161303791906154c5565b60405180910390a3600190509392505050565b5f603a905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156130d3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016130ca90615603565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054101561318e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016131859061566b565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546131da91906156b6565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461322d91906156e9565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546132bb91906156b6565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161331f91906154c5565b60405180910390a3600190509392505050565b5f6009905090565b5f6049905090565b5f602a905090565b5f6014905090565b5f6025905090565b5f6013905090565b5f6043905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156133eb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016133e2906157c3565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156134a6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161349d9061582b565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546134f291906156b6565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461354591906156e9565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546135d391906156b6565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161363791906154c5565b60405180910390a3600190509392505050565b5f600d905090565b5f6017905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156136db576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016136d290615603565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015613796576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161378d9061566b565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546137e291906156b6565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461383591906156e9565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546138c391906156b6565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161392791906154c5565b60405180910390a3600190509392505050565b6004602052805f5260405f205f915090505481565b5f6016905090565b5f6039905090565b5f603b905090565b5f6036905090565b5f603f905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156139f8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016139ef90615603565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015613ab3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613aaa9061566b565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254613aff91906156b6565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254613b5291906156e9565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254613be091906156b6565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051613c4491906154c5565b60405180910390a3600190509392505050565b5f602b905090565b5f6037905090565b5f600a905090565b5f602d905090565b5f6030905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015613d00576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613cf790615603565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015613dbb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613db29061566b565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254613e0791906156b6565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254613e5a91906156e9565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254613ee891906156b6565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051613f4c91906154c5565b60405180910390a3600190509392505050565b5f600b905090565b60018054613f7490615749565b80601f0160208091040260200160405190810160405280929190818152602001828054613fa090615749565b8015613feb5780601f10613fc257610100808354040283529160200191613feb565b820191905f5260205f20905b815481529060010190602001808311613fce57829003601f168201915b505050505081565b5f6015905090565b5f6029905090565b5f6038905090565b5f8160045f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054101561408c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161408390615603565b60405180910390fd5b8160045f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546140d891906156b6565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461412b91906156e9565b925050819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161418f91906154c5565b60405180910390a36001905092915050565b5f6028905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054101561422a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161422190615603565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156142e5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016142dc9061566b565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461433191906156b6565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461438491906156e9565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461441291906156b6565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161447691906154c5565b60405180910390a3600190509392505050565b5f6040905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015614512576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161450990615603565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156145cd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016145c49061566b565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461461991906156b6565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461466c91906156e9565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546146fa91906156b6565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161475e91906154c5565b60405180910390a3600190509392505050565b5f6018905090565b5f604a905090565b5f600f905090565b5f6044905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015614812576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161480990615603565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156148cd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016148c49061566b565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461491991906156b6565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461496c91906156e9565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546149fa91906156b6565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051614a5e91906154c5565b60405180910390a3600190509392505050565b5f6046905090565b7f000000000000000000000000000000000000000000000000000000000000000081565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015614b1e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401614b1590615603565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015614bd9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401614bd09061566b565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254614c2591906156b6565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254614c7891906156e9565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254614d0691906156b6565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051614d6a91906154c5565b60405180910390a3600190509392505050565b5f6024905090565b5f601e905090565b5f6031905090565b5f6019905090565b5f6042905090565b5f6027905090565b6005602052815f5260405f20602052805f5260405f205f91509150505481565b5f603d905090565b5f6022905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015614e5e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401614e55906157c3565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254614eaa91906156b6565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254614efd91906156e9565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254614f8b91906156b6565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051614fef91906154c5565b60405180910390a3600190509392505050565b5f6007905090565b5f6047905090565b5f603e905090565b5f6020905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156150a3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161509a90615603565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054101561515e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016151559061566b565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546151aa91906156b6565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546151fd91906156e9565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461528b91906156b6565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516152ef91906154c5565b60405180910390a3600190509392505050565b5f600e905090565b5f6012905090565b5f5ffd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f61533f82615316565b9050919050565b61534f81615335565b8114615359575f5ffd5b50565b5f8135905061536a81615346565b92915050565b5f819050919050565b61538281615370565b811461538c575f5ffd5b50565b5f8135905061539d81615379565b92915050565b5f5f5f606084860312156153ba576153b9615312565b5b5f6153c78682870161535c565b93505060206153d88682870161535c565b92505060406153e98682870161538f565b9150509250925092565b5f8115159050919050565b615407816153f3565b82525050565b5f6020820190506154205f8301846153fe565b92915050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f61546882615426565b6154728185615430565b9350615482818560208601615440565b61548b8161544e565b840191505092915050565b5f6020820190508181035f8301526154ae818461545e565b905092915050565b6154bf81615370565b82525050565b5f6020820190506154d85f8301846154b6565b92915050565b5f5f604083850312156154f4576154f3615312565b5b5f6155018582860161535c565b92505060206155128582860161538f565b9150509250929050565b5f60ff82169050919050565b6155318161551c565b82525050565b5f60208201905061554a5f830184615528565b92915050565b5f6020828403121561556557615564615312565b5b5f6155728482850161535c565b91505092915050565b5f5f6040838503121561559157615590615312565b5b5f61559e8582860161535c565b92505060206155af8582860161535c565b9150509250929050565b7f496e73756666696369656e742062616c616e63650000000000000000000000005f82015250565b5f6155ed601483615430565b91506155f8826155b9565b602082019050919050565b5f6020820190508181035f83015261561a816155e1565b9050919050565b7f496e73756666696369656e7420616c6c6f77616e6365000000000000000000005f82015250565b5f615655601683615430565b915061566082615621565b602082019050919050565b5f6020820190508181035f83015261568281615649565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6156c082615370565b91506156cb83615370565b92508282039050818111156156e3576156e2615689565b5b92915050565b5f6156f382615370565b91506156fe83615370565b925082820190508082111561571657615715615689565b5b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f600282049050600182168061576057607f821691505b6020821081036157735761577261571c565b5b50919050565b7f41000000000000000000000000000000000000000000000000000000000000005f82015250565b5f6157ad600183615430565b91506157b882615779565b602082019050919050565b5f6020820190508181035f8301526157da816157a1565b9050919050565b7f42000000000000000000000000000000000000000000000000000000000000005f82015250565b5f615815600183615430565b9150615820826157e1565b602082019050919050565b5f6020820190508181035f83015261584281615809565b905091905056fea2646970667358221220ce03f2ea0f8ec341a07b9c0512b41f44d879b740c55b3572c5707216663e8a3f64736f6c634300081e0033 \ No newline at end of file +60a060405234801561000f575f5ffd5b50604051615d6a380380615d6a833981810160405281019061003191906101f4565b6040518060400160405280601181526020017f537461746520426c6f617420546f6b656e0000000000000000000000000000008152505f90816100749190610453565b506040518060400160405280600381526020017f5342540000000000000000000000000000000000000000000000000000000000815250600190816100b99190610453565b50601260025f6101000a81548160ff021916908360ff160217905550806080818152505060025f9054906101000a900460ff16600a6100f8919061068a565b620f424061010691906106d4565b60038190555060035460045f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055503373ffffffffffffffffffffffffffffffffffffffff165f73ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef6003546040516101af9190610724565b60405180910390a35061073d565b5f5ffd5b5f819050919050565b6101d3816101c1565b81146101dd575f5ffd5b50565b5f815190506101ee816101ca565b92915050565b5f60208284031215610209576102086101bd565b5b5f610216848285016101e0565b91505092915050565b5f81519050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f600282049050600182168061029a57607f821691505b6020821081036102ad576102ac610256565b5b50919050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f6008830261030f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff826102d4565b61031986836102d4565b95508019841693508086168417925050509392505050565b5f819050919050565b5f61035461034f61034a846101c1565b610331565b6101c1565b9050919050565b5f819050919050565b61036d8361033a565b6103816103798261035b565b8484546102e0565b825550505050565b5f5f905090565b610398610389565b6103a3818484610364565b505050565b5b818110156103c6576103bb5f82610390565b6001810190506103a9565b5050565b601f82111561040b576103dc816102b3565b6103e5846102c5565b810160208510156103f4578190505b610408610400856102c5565b8301826103a8565b50505b505050565b5f82821c905092915050565b5f61042b5f1984600802610410565b1980831691505092915050565b5f610443838361041c565b9150826002028217905092915050565b61045c8261021f565b67ffffffffffffffff81111561047557610474610229565b5b61047f8254610283565b61048a8282856103ca565b5f60209050601f8311600181146104bb575f84156104a9578287015190505b6104b38582610438565b86555061051a565b601f1984166104c9866102b3565b5f5b828110156104f0578489015182556001820191506020850194506020810190506104cb565b8683101561050d5784890151610509601f89168261041c565b8355505b6001600288020188555050505b505050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f8160011c9050919050565b5f5f8291508390505b60018511156105a4578086048111156105805761057f610522565b5b600185161561058f5780820291505b808102905061059d8561054f565b9450610564565b94509492505050565b5f826105bc5760019050610677565b816105c9575f9050610677565b81600181146105df57600281146105e957610618565b6001915050610677565b60ff8411156105fb576105fa610522565b5b8360020a91508482111561061257610611610522565b5b50610677565b5060208310610133831016604e8410600b841016171561064d5782820a90508381111561064857610647610522565b5b610677565b61065a848484600161055b565b9250905081840481111561067157610670610522565b5b81810290505b9392505050565b5f60ff82169050919050565b5f610694826101c1565b915061069f8361067e565b92506106cc7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff84846105ad565b905092915050565b5f6106de826101c1565b91506106e9836101c1565b92508282026106f7816101c1565b9150828204841483151761070e5761070d610522565b5b5092915050565b61071e816101c1565b82525050565b5f6020820190506107375f830184610715565b92915050565b6080516156156107555f395f61482101526156155ff3fe608060405234801561000f575f5ffd5b5060043610610518575f3560e01c8063657b6ef7116102a2578063aaa7af7011610170578063d7419469116100d7578063f26c779b11610090578063f26c779b1461110a578063f5f5738114611128578063f8716f1414611146578063faf35ced14611164578063fe7d599614611194578063ffbf0469146111b257610518565b8063d741946914611032578063dc1d8a9b14611050578063dd62ed3e1461106e578063e2d275301461109e578063e8c927b3146110bc578063eb4329c8146110da57610518565b8063bb9bfe0611610129578063bb9bfe0614610f5a578063bfa0b13314610f8a578063c2be97e314610fa8578063c958d4bf14610fd8578063cfd6686314610ff6578063d101dcd01461101457610518565b8063aaa7af7014610e82578063acc5aee914610ea0578063ad8f422114610ed0578063b1802b9a14610eee578063b2bb360e14610f1e578063b66dd75014610f3c57610518565b80637c72ed0d116102145780638f4a8406116101cd5780638f4a840614610dbc57806395d89b4114610dda5780639c5dfe7314610df85780639df61a2514610e16578063a891d4d414610e34578063a9059cbb14610e5257610518565b80637c72ed0d14610cf65780637dffdc3214610d145780637e54493714610d325780637f34d94b14610d505780638619d60714610d6e5780638789ca6714610d8c57610518565b806374e73fd31161026657806374e73fd314610c3057806374f83d0214610c4e57806377c0209e14610c6c578063792c7f3e14610c8a5780637a319c1814610ca85780637c66673e14610cc657610518565b8063657b6ef714610b64578063672151fe14610b945780636abceacd14610bb25780636c12ed2814610bd057806370a0823114610c0057610518565b80633125f37a116103ea5780634a2e93c611610351578063552a1b561161030a578063552a1b5614610a9e57806358b6a9bd14610ace5780635af92c0514610aec57806361b970eb14610b0a578063639ec53a14610b285780636547317414610b4657610518565b80634a2e93c6146109d85780634b3c7f5f146109f65780634e1dbb8214610a145780634f5e555714610a325780634f7bd75a14610a5057806354c2792014610a8057610518565b80633ea117ce116103a35780633ea117ce146109125780634128a85d14610930578063418b18161461094e57806342937dbd1461096c57806343a6b92d1461098a57806344050a28146109a857610518565b80633125f37a1461083a578063313ce5671461085857806334517f0b1461087657806339e0bd12146108945780633a131990146108c45780633b6be459146108f457610518565b80631a97f18e1161048e5780631fd298ec116104475780631fd298ec1461076257806321ecd7a314610780578063239af2a51461079e57806323b872dd146107bc5780632545d8b7146107ec578063291c3bd71461080a57610518565b80631a97f18e1461068a5780631b17c65c146106a85780631bbffe6f146106d85780631d527cde146107085780631eaa7c52146107265780631f4495891461074457610518565b80631215a3ab116104e05780631215a3ab146105d657806312901b42146105f457806313ebb5ec1461061257806316a3045b1461063057806318160ddd1461064e57806319cf6a911461066c57610518565b80630460faf61461051c57806306fdde031461054c5780630717b1611461056a578063095ea7b3146105885780630cb7a9e7146105b8575b5f5ffd5b61053660048036038101906105319190615139565b6111d0565b60405161054391906151a3565b60405180910390f35b6105546114b0565b604051610561919061522c565b60405180910390f35b61057261153b565b60405161057f919061525b565b60405180910390f35b6105a2600480360381019061059d9190615274565b611543565b6040516105af91906151a3565b60405180910390f35b6105c0611630565b6040516105cd919061525b565b60405180910390f35b6105de611638565b6040516105eb919061525b565b60405180910390f35b6105fc611640565b604051610609919061525b565b60405180910390f35b61061a611648565b604051610627919061525b565b60405180910390f35b610638611650565b604051610645919061525b565b60405180910390f35b610656611658565b604051610663919061525b565b60405180910390f35b61067461165e565b604051610681919061525b565b60405180910390f35b610692611666565b60405161069f919061525b565b60405180910390f35b6106c260048036038101906106bd9190615139565b61166e565b6040516106cf91906151a3565b60405180910390f35b6106f260048036038101906106ed9190615139565b61194e565b6040516106ff91906151a3565b60405180910390f35b610710611c2e565b60405161071d919061525b565b60405180910390f35b61072e611c36565b60405161073b919061525b565b60405180910390f35b61074c611c3e565b604051610759919061525b565b60405180910390f35b61076a611c46565b604051610777919061525b565b60405180910390f35b610788611c4e565b604051610795919061525b565b60405180910390f35b6107a6611c56565b6040516107b3919061525b565b60405180910390f35b6107d660048036038101906107d19190615139565b611c5e565b6040516107e391906151a3565b60405180910390f35b6107f4611f3e565b604051610801919061525b565b60405180910390f35b610824600480360381019061081f9190615139565b611f46565b60405161083191906151a3565b60405180910390f35b610842612226565b60405161084f919061525b565b60405180910390f35b61086061222e565b60405161086d91906152cd565b60405180910390f35b61087e612240565b60405161088b919061525b565b60405180910390f35b6108ae60048036038101906108a99190615139565b612248565b6040516108bb91906151a3565b60405180910390f35b6108de60048036038101906108d99190615139565b612528565b6040516108eb91906151a3565b60405180910390f35b6108fc612808565b604051610909919061525b565b60405180910390f35b61091a612810565b604051610927919061525b565b60405180910390f35b610938612818565b604051610945919061525b565b60405180910390f35b610956612820565b604051610963919061525b565b60405180910390f35b610974612828565b604051610981919061525b565b60405180910390f35b610992612830565b60405161099f919061525b565b60405180910390f35b6109c260048036038101906109bd9190615139565b612838565b6040516109cf91906151a3565b60405180910390f35b6109e0612b18565b6040516109ed919061525b565b60405180910390f35b6109fe612b20565b604051610a0b919061525b565b60405180910390f35b610a1c612b28565b604051610a29919061525b565b60405180910390f35b610a3a612b30565b604051610a47919061525b565b60405180910390f35b610a6a6004803603810190610a659190615139565b612b38565b604051610a7791906151a3565b60405180910390f35b610a88612e18565b604051610a95919061525b565b60405180910390f35b610ab86004803603810190610ab39190615139565b612e20565b604051610ac591906151a3565b60405180910390f35b610ad6613100565b604051610ae3919061525b565b60405180910390f35b610af4613108565b604051610b01919061525b565b60405180910390f35b610b12613110565b604051610b1f919061525b565b60405180910390f35b610b30613118565b604051610b3d919061525b565b60405180910390f35b610b4e613120565b604051610b5b919061525b565b60405180910390f35b610b7e6004803603810190610b799190615139565b613128565b604051610b8b91906151a3565b60405180910390f35b610b9c613408565b604051610ba9919061525b565b60405180910390f35b610bba613410565b604051610bc7919061525b565b60405180910390f35b610bea6004803603810190610be59190615139565b613418565b604051610bf791906151a3565b60405180910390f35b610c1a6004803603810190610c1591906152e6565b6136f8565b604051610c27919061525b565b60405180910390f35b610c3861370d565b604051610c45919061525b565b60405180910390f35b610c56613715565b604051610c63919061525b565b60405180910390f35b610c7461371d565b604051610c81919061525b565b60405180910390f35b610c92613725565b604051610c9f919061525b565b60405180910390f35b610cb061372d565b604051610cbd919061525b565b60405180910390f35b610ce06004803603810190610cdb9190615139565b613735565b604051610ced91906151a3565b60405180910390f35b610cfe613a15565b604051610d0b919061525b565b60405180910390f35b610d1c613a1d565b604051610d29919061525b565b60405180910390f35b610d3a613a25565b604051610d47919061525b565b60405180910390f35b610d58613a2d565b604051610d65919061525b565b60405180910390f35b610d76613a35565b604051610d83919061525b565b60405180910390f35b610da66004803603810190610da19190615139565b613a3d565b604051610db391906151a3565b60405180910390f35b610dc4613d1d565b604051610dd1919061525b565b60405180910390f35b610de2613d25565b604051610def919061522c565b60405180910390f35b610e00613db1565b604051610e0d919061525b565b60405180910390f35b610e1e613db9565b604051610e2b919061525b565b60405180910390f35b610e3c613dc1565b604051610e49919061525b565b60405180910390f35b610e6c6004803603810190610e679190615274565b613dc9565b604051610e7991906151a3565b60405180910390f35b610e8a613f5f565b604051610e97919061525b565b60405180910390f35b610eba6004803603810190610eb59190615139565b613f67565b604051610ec791906151a3565b60405180910390f35b610ed8614247565b604051610ee5919061525b565b60405180910390f35b610f086004803603810190610f039190615139565b61424f565b604051610f1591906151a3565b60405180910390f35b610f2661452f565b604051610f33919061525b565b60405180910390f35b610f44614537565b604051610f51919061525b565b60405180910390f35b610f746004803603810190610f6f9190615139565b61453f565b604051610f8191906151a3565b60405180910390f35b610f9261481f565b604051610f9f919061525b565b60405180910390f35b610fc26004803603810190610fbd9190615139565b614843565b604051610fcf91906151a3565b60405180910390f35b610fe0614b23565b604051610fed919061525b565b60405180910390f35b610ffe614b2b565b60405161100b919061525b565b60405180910390f35b61101c614b33565b604051611029919061525b565b60405180910390f35b61103a614b3b565b604051611047919061525b565b60405180910390f35b611058614b43565b604051611065919061525b565b60405180910390f35b61108860048036038101906110839190615311565b614b4b565b604051611095919061525b565b60405180910390f35b6110a6614b6b565b6040516110b3919061525b565b60405180910390f35b6110c4614b73565b6040516110d1919061525b565b60405180910390f35b6110f460048036038101906110ef9190615139565b614b7b565b60405161110191906151a3565b60405180910390f35b611112614da0565b60405161111f919061525b565b60405180910390f35b611130614da8565b60405161113d919061525b565b60405180910390f35b61114e614db0565b60405161115b919061525b565b60405180910390f35b61117e60048036038101906111799190615139565b614db8565b60405161118b91906151a3565b60405180910390f35b61119c615098565b6040516111a9919061525b565b60405180910390f35b6111ba6150a0565b6040516111c7919061525b565b60405180910390f35b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015611251576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161124890615399565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054101561130c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161130390615401565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254611358919061544c565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546113ab919061547f565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254611439919061544c565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161149d919061525b565b60405180910390a3600190509392505050565b5f80546114bc906154df565b80601f01602080910402602001604051908101604052809291908181526020018280546114e8906154df565b80156115335780601f1061150a57610100808354040283529160200191611533565b820191905f5260205f20905b81548152906001019060200180831161151657829003601f168201915b505050505081565b5f602f905090565b5f8160055f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9258460405161161e919061525b565b60405180910390a36001905092915050565b5f601b905090565b5f6005905090565b5f601a905090565b5f601d905090565b5f6033905090565b60035481565b5f6008905090565b5f6003905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156116ef576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116e690615399565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156117aa576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117a190615401565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546117f6919061544c565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254611849919061547f565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546118d7919061544c565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161193b919061525b565b60405180910390a3600190509392505050565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156119cf576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119c690615399565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015611a8a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a8190615401565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254611ad6919061544c565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254611b29919061547f565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254611bb7919061544c565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051611c1b919061525b565b60405180910390a3600190509392505050565b5f6002905090565b5f6010905090565b5f6041905090565b5f6035905090565b5f602e905090565b5f602c905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015611cdf576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611cd690615399565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015611d9a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611d9190615401565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254611de6919061544c565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254611e39919061547f565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254611ec7919061544c565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051611f2b919061525b565b60405180910390a3600190509392505050565b5f6001905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015611fc7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611fbe90615559565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015612082576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612079906155c1565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546120ce919061544c565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254612121919061547f565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546121af919061544c565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051612213919061525b565b60405180910390a3600190509392505050565b5f6034905090565b60025f9054906101000a900460ff1681565b5f603c905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156122c9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016122c090615399565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015612384576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161237b90615401565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546123d0919061544c565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254612423919061547f565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546124b1919061544c565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051612515919061525b565b60405180910390a3600190509392505050565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156125a9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016125a090615399565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015612664576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161265b90615401565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546126b0919061544c565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254612703919061547f565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254612791919061544c565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516127f5919061525b565b60405180910390a3600190509392505050565b5f6004905090565b5f600c905090565b5f6006905090565b5f601c905090565b5f6032905090565b5f6023905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156128b9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016128b090615399565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015612974576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161296b90615401565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546129c0919061544c565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254612a13919061547f565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254612aa1919061544c565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051612b05919061525b565b60405180910390a3600190509392505050565b5f6011905090565b5f6021905090565b5f601f905090565b5f6026905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015612bb9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612bb090615399565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015612c74576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612c6b90615401565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254612cc0919061544c565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254612d13919061547f565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254612da1919061544c565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051612e05919061525b565b60405180910390a3600190509392505050565b5f603a905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015612ea1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612e9890615399565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015612f5c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612f5390615401565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254612fa8919061544c565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254612ffb919061547f565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254613089919061544c565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516130ed919061525b565b60405180910390a3600190509392505050565b5f6009905090565b5f602a905090565b5f6014905090565b5f6025905090565b5f6013905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156131a9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016131a090615559565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015613264576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161325b906155c1565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546132b0919061544c565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254613303919061547f565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254613391919061544c565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516133f5919061525b565b60405180910390a3600190509392505050565b5f600d905090565b5f6017905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015613499576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161349090615399565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015613554576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161354b90615401565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546135a0919061544c565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546135f3919061547f565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254613681919061544c565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516136e5919061525b565b60405180910390a3600190509392505050565b6004602052805f5260405f205f915090505481565b5f6016905090565b5f6039905090565b5f603b905090565b5f6036905090565b5f603f905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156137b6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016137ad90615399565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015613871576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161386890615401565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546138bd919061544c565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254613910919061547f565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461399e919061544c565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051613a02919061525b565b60405180910390a3600190509392505050565b5f602b905090565b5f6037905090565b5f600a905090565b5f602d905090565b5f6030905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015613abe576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613ab590615399565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015613b79576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613b7090615401565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254613bc5919061544c565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254613c18919061547f565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254613ca6919061544c565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051613d0a919061525b565b60405180910390a3600190509392505050565b5f600b905090565b60018054613d32906154df565b80601f0160208091040260200160405190810160405280929190818152602001828054613d5e906154df565b8015613da95780601f10613d8057610100808354040283529160200191613da9565b820191905f5260205f20905b815481529060010190602001808311613d8c57829003601f168201915b505050505081565b5f6015905090565b5f6029905090565b5f6038905090565b5f8160045f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015613e4a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613e4190615399565b60405180910390fd5b8160045f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254613e96919061544c565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254613ee9919061547f565b925050819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051613f4d919061525b565b60405180910390a36001905092915050565b5f6028905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015613fe8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613fdf90615399565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156140a3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161409a90615401565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546140ef919061544c565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254614142919061547f565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546141d0919061544c565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051614234919061525b565b60405180910390a3600190509392505050565b5f6040905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156142d0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016142c790615399565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054101561438b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161438290615401565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546143d7919061544c565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461442a919061547f565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546144b8919061544c565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161451c919061525b565b60405180910390a3600190509392505050565b5f6018905090565b5f600f905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156145c0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016145b790615399565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054101561467b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161467290615401565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546146c7919061544c565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461471a919061547f565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546147a8919061544c565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161480c919061525b565b60405180910390a3600190509392505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156148c4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016148bb90615399565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054101561497f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161497690615401565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546149cb919061544c565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254614a1e919061547f565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254614aac919061544c565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051614b10919061525b565b60405180910390a3600190509392505050565b5f6024905090565b5f601e905090565b5f6031905090565b5f6019905090565b5f6027905090565b6005602052815f5260405f20602052805f5260405f205f91509150505481565b5f603d905090565b5f6022905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015614bfc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401614bf390615559565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254614c48919061544c565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254614c9b919061547f565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254614d29919061544c565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051614d8d919061525b565b60405180910390a3600190509392505050565b5f6007905090565b5f603e905090565b5f6020905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015614e39576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401614e3090615399565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015614ef4576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401614eeb90615401565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254614f40919061544c565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254614f93919061547f565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254615021919061544c565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051615085919061525b565b60405180910390a3600190509392505050565b5f600e905090565b5f6012905090565b5f5ffd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6150d5826150ac565b9050919050565b6150e5816150cb565b81146150ef575f5ffd5b50565b5f81359050615100816150dc565b92915050565b5f819050919050565b61511881615106565b8114615122575f5ffd5b50565b5f813590506151338161510f565b92915050565b5f5f5f606084860312156151505761514f6150a8565b5b5f61515d868287016150f2565b935050602061516e868287016150f2565b925050604061517f86828701615125565b9150509250925092565b5f8115159050919050565b61519d81615189565b82525050565b5f6020820190506151b65f830184615194565b92915050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f6151fe826151bc565b61520881856151c6565b93506152188185602086016151d6565b615221816151e4565b840191505092915050565b5f6020820190508181035f83015261524481846151f4565b905092915050565b61525581615106565b82525050565b5f60208201905061526e5f83018461524c565b92915050565b5f5f6040838503121561528a576152896150a8565b5b5f615297858286016150f2565b92505060206152a885828601615125565b9150509250929050565b5f60ff82169050919050565b6152c7816152b2565b82525050565b5f6020820190506152e05f8301846152be565b92915050565b5f602082840312156152fb576152fa6150a8565b5b5f615308848285016150f2565b91505092915050565b5f5f60408385031215615327576153266150a8565b5b5f615334858286016150f2565b9250506020615345858286016150f2565b9150509250929050565b7f496e73756666696369656e742062616c616e63650000000000000000000000005f82015250565b5f6153836014836151c6565b915061538e8261534f565b602082019050919050565b5f6020820190508181035f8301526153b081615377565b9050919050565b7f496e73756666696369656e7420616c6c6f77616e6365000000000000000000005f82015250565b5f6153eb6016836151c6565b91506153f6826153b7565b602082019050919050565b5f6020820190508181035f830152615418816153df565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f61545682615106565b915061546183615106565b92508282039050818111156154795761547861541f565b5b92915050565b5f61548982615106565b915061549483615106565b92508282019050808211156154ac576154ab61541f565b5b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f60028204905060018216806154f657607f821691505b602082108103615509576155086154b2565b5b50919050565b7f41000000000000000000000000000000000000000000000000000000000000005f82015250565b5f6155436001836151c6565b915061554e8261550f565b602082019050919050565b5f6020820190508181035f83015261557081615537565b9050919050565b7f42000000000000000000000000000000000000000000000000000000000000005f82015250565b5f6155ab6001836151c6565b91506155b682615577565b602082019050919050565b5f6020820190508181035f8301526155d88161559f565b905091905056fea26469706673582212206fbf384dcd110eb4456b07e83a2c8a392433c7852a66dec9f8ebf3989cad1f6764736f6c634300081e0033 \ No newline at end of file diff --git a/scenarios/statebloat/contract_deploy/contract/StateBloatToken.go b/scenarios/statebloat/contract_deploy/contract/StateBloatToken.go index f744e474..13a8ab62 100644 --- a/scenarios/statebloat/contract_deploy/contract/StateBloatToken.go +++ b/scenarios/statebloat/contract_deploy/contract/StateBloatToken.go @@ -31,8 +31,8 @@ var ( // 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\":\"dummy66\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dummy67\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dummy68\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dummy69\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dummy7\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dummy70\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dummy71\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dummy72\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dummy73\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dummy74\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"pure\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"dummy75\",\"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: "0x60a060405234801561000f575f5ffd5b50604051615fd4380380615fd4833981810160405281019061003191906101f4565b6040518060400160405280601181526020017f537461746520426c6f617420546f6b656e0000000000000000000000000000008152505f90816100749190610453565b506040518060400160405280600381526020017f5342540000000000000000000000000000000000000000000000000000000000815250600190816100b99190610453565b50601260025f6101000a81548160ff021916908360ff160217905550806080818152505060025f9054906101000a900460ff16600a6100f8919061068a565b620f424061010691906106d4565b60038190555060035460045f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055503373ffffffffffffffffffffffffffffffffffffffff165f73ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef6003546040516101af9190610724565b60405180910390a35061073d565b5f5ffd5b5f819050919050565b6101d3816101c1565b81146101dd575f5ffd5b50565b5f815190506101ee816101ca565b92915050565b5f60208284031215610209576102086101bd565b5b5f610216848285016101e0565b91505092915050565b5f81519050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f600282049050600182168061029a57607f821691505b6020821081036102ad576102ac610256565b5b50919050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f6008830261030f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff826102d4565b61031986836102d4565b95508019841693508086168417925050509392505050565b5f819050919050565b5f61035461034f61034a846101c1565b610331565b6101c1565b9050919050565b5f819050919050565b61036d8361033a565b6103816103798261035b565b8484546102e0565b825550505050565b5f5f905090565b610398610389565b6103a3818484610364565b505050565b5b818110156103c6576103bb5f82610390565b6001810190506103a9565b5050565b601f82111561040b576103dc816102b3565b6103e5846102c5565b810160208510156103f4578190505b610408610400856102c5565b8301826103a8565b50505b505050565b5f82821c905092915050565b5f61042b5f1984600802610410565b1980831691505092915050565b5f610443838361041c565b9150826002028217905092915050565b61045c8261021f565b67ffffffffffffffff81111561047557610474610229565b5b61047f8254610283565b61048a8282856103ca565b5f60209050601f8311600181146104bb575f84156104a9578287015190505b6104b38582610438565b86555061051a565b601f1984166104c9866102b3565b5f5b828110156104f0578489015182556001820191506020850194506020810190506104cb565b8683101561050d5784890151610509601f89168261041c565b8355505b6001600288020188555050505b505050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f8160011c9050919050565b5f5f8291508390505b60018511156105a4578086048111156105805761057f610522565b5b600185161561058f5780820291505b808102905061059d8561054f565b9450610564565b94509492505050565b5f826105bc5760019050610677565b816105c9575f9050610677565b81600181146105df57600281146105e957610618565b6001915050610677565b60ff8411156105fb576105fa610522565b5b8360020a91508482111561061257610611610522565b5b50610677565b5060208310610133831016604e8410600b841016171561064d5782820a90508381111561064857610647610522565b5b610677565b61065a848484600161055b565b9250905081840481111561067157610670610522565b5b81810290505b9392505050565b5f60ff82169050919050565b5f610694826101c1565b915061069f8361067e565b92506106cc7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff84846105ad565b905092915050565b5f6106de826101c1565b91506106e9836101c1565b92508282026106f7816101c1565b9150828204841483151761070e5761070d610522565b5b5092915050565b61071e816101c1565b82525050565b5f6020820190506107375f830184610715565b92915050565b60805161587f6107555f395f614a7b015261587f5ff3fe608060405234801561000f575f5ffd5b5060043610610606575f3560e01c8063657b6ef711610319578063b1802b9a116101a6578063d9bb3174116100f2578063f26c779b116100ab578063f8716f1411610085578063f8716f1414611360578063faf35ced1461137e578063fe7d5996146113ae578063ffbf0469146113cc57610606565b8063f26c779b14611306578063f4978b0414611324578063f5f573811461134257610606565b8063d9bb31741461122e578063dc1d8a9b1461124c578063dd62ed3e1461126a578063e2d275301461129a578063e8c927b3146112b8578063eb4329c8146112d657610606565b8063bbe231321161015f578063c958d4bf11610139578063c958d4bf146111b6578063cfd66863146111d4578063d101dcd0146111f2578063d74194691461121057610606565b8063bbe231321461114a578063bfa0b13314611168578063c2be97e31461118657610606565b8063b1802b9a14611072578063b2bb360e146110a2578063b4c48668146110c0578063b66dd750146110de578063b9a6d645146110fc578063bb9bfe061461111a57610606565b80637e544937116102655780639c5dfe731161021e578063a9059cbb116101f8578063a9059cbb14610fd6578063aaa7af7014611006578063acc5aee914611024578063ad8f42211461105457610606565b80639c5dfe7314610f7c5780639df61a2514610f9a578063a891d4d414610fb857610606565b80637e54493714610eb65780637f34d94b14610ed45780638619d60714610ef25780638789ca6714610f105780638f4a840614610f4057806395d89b4114610f5e57610606565b806374f83d02116102d25780637a319c18116102ac5780637a319c1814610e2c5780637c66673e14610e4a5780637c72ed0d14610e7a5780637dffdc3214610e9857610606565b806374f83d0214610dd257806377c0209e14610df0578063792c7f3e14610e0e57610606565b8063657b6ef714610ce8578063672151fe14610d185780636abceacd14610d365780636c12ed2814610d5457806370a0823114610d8457806374e73fd314610db457610606565b8063313ce567116104975780634b3c7f5f116103e357806358b6a9bd1161039c57806361b970eb1161037657806361b970eb14610c70578063639ec53a14610c8e5780636547317414610cac5780636578534c14610cca57610606565b806358b6a9bd14610c16578063595471b814610c345780635af92c0514610c5257610606565b80634b3c7f5f14610b3e5780634e1dbb8214610b5c5780634f5e555714610b7a5780634f7bd75a14610b9857806354c2792014610bc8578063552a1b5614610be657610606565b80633ea117ce1161045057806342937dbd1161042a57806342937dbd14610ab457806343a6b92d14610ad257806344050a2814610af05780634a2e93c614610b2057610606565b80633ea117ce14610a5a5780634128a85d14610a78578063418b181614610a9657610606565b8063313ce5671461098257806334517f0b146109a0578063378c5382146109be57806339e0bd12146109dc5780633a13199014610a0c5780633b6be45914610a3c57610606565b80631bbffe6f1161055657806321ecd7a31161050f5780632545d8b7116104e95780632545d8b7146108f85780632787325b14610916578063291c3bd7146109345780633125f37a1461096457610606565b806321ecd7a31461088c578063239af2a5146108aa57806323b872dd146108c857610606565b80631bbffe6f146107c65780631d527cde146107f65780631eaa7c52146108145780631f29783f146108325780631f449589146108505780631fd298ec1461086e57610606565b806312901b42116105c357806318160ddd1161059d57806318160ddd1461073c57806319cf6a911461075a5780631a97f18e146107785780631b17c65c1461079657610606565b806312901b42146106e257806313ebb5ec1461070057806316a3045b1461071e57610606565b80630460faf61461060a57806306fdde031461063a5780630717b16114610658578063095ea7b3146106765780630cb7a9e7146106a65780631215a3ab146106c4575b5f5ffd5b610624600480360381019061061f91906153a3565b6113ea565b604051610631919061540d565b60405180910390f35b6106426116ca565b60405161064f9190615496565b60405180910390f35b610660611755565b60405161066d91906154c5565b60405180910390f35b610690600480360381019061068b91906154de565b61175d565b60405161069d919061540d565b60405180910390f35b6106ae61184a565b6040516106bb91906154c5565b60405180910390f35b6106cc611852565b6040516106d991906154c5565b60405180910390f35b6106ea61185a565b6040516106f791906154c5565b60405180910390f35b610708611862565b60405161071591906154c5565b60405180910390f35b61072661186a565b60405161073391906154c5565b60405180910390f35b610744611872565b60405161075191906154c5565b60405180910390f35b610762611878565b60405161076f91906154c5565b60405180910390f35b610780611880565b60405161078d91906154c5565b60405180910390f35b6107b060048036038101906107ab91906153a3565b611888565b6040516107bd919061540d565b60405180910390f35b6107e060048036038101906107db91906153a3565b611b68565b6040516107ed919061540d565b60405180910390f35b6107fe611e48565b60405161080b91906154c5565b60405180910390f35b61081c611e50565b60405161082991906154c5565b60405180910390f35b61083a611e58565b60405161084791906154c5565b60405180910390f35b610858611e60565b60405161086591906154c5565b60405180910390f35b610876611e68565b60405161088391906154c5565b60405180910390f35b610894611e70565b6040516108a191906154c5565b60405180910390f35b6108b2611e78565b6040516108bf91906154c5565b60405180910390f35b6108e260048036038101906108dd91906153a3565b611e80565b6040516108ef919061540d565b60405180910390f35b610900612160565b60405161090d91906154c5565b60405180910390f35b61091e612168565b60405161092b91906154c5565b60405180910390f35b61094e600480360381019061094991906153a3565b612170565b60405161095b919061540d565b60405180910390f35b61096c612450565b60405161097991906154c5565b60405180910390f35b61098a612458565b6040516109979190615537565b60405180910390f35b6109a861246a565b6040516109b591906154c5565b60405180910390f35b6109c6612472565b6040516109d391906154c5565b60405180910390f35b6109f660048036038101906109f191906153a3565b61247a565b604051610a03919061540d565b60405180910390f35b610a266004803603810190610a2191906153a3565b61275a565b604051610a33919061540d565b60405180910390f35b610a44612a3a565b604051610a5191906154c5565b60405180910390f35b610a62612a42565b604051610a6f91906154c5565b60405180910390f35b610a80612a4a565b604051610a8d91906154c5565b60405180910390f35b610a9e612a52565b604051610aab91906154c5565b60405180910390f35b610abc612a5a565b604051610ac991906154c5565b60405180910390f35b610ada612a62565b604051610ae791906154c5565b60405180910390f35b610b0a6004803603810190610b0591906153a3565b612a6a565b604051610b17919061540d565b60405180910390f35b610b28612d4a565b604051610b3591906154c5565b60405180910390f35b610b46612d52565b604051610b5391906154c5565b60405180910390f35b610b64612d5a565b604051610b7191906154c5565b60405180910390f35b610b82612d62565b604051610b8f91906154c5565b60405180910390f35b610bb26004803603810190610bad91906153a3565b612d6a565b604051610bbf919061540d565b60405180910390f35b610bd061304a565b604051610bdd91906154c5565b60405180910390f35b610c006004803603810190610bfb91906153a3565b613052565b604051610c0d919061540d565b60405180910390f35b610c1e613332565b604051610c2b91906154c5565b60405180910390f35b610c3c61333a565b604051610c4991906154c5565b60405180910390f35b610c5a613342565b604051610c6791906154c5565b60405180910390f35b610c7861334a565b604051610c8591906154c5565b60405180910390f35b610c96613352565b604051610ca391906154c5565b60405180910390f35b610cb461335a565b604051610cc191906154c5565b60405180910390f35b610cd2613362565b604051610cdf91906154c5565b60405180910390f35b610d026004803603810190610cfd91906153a3565b61336a565b604051610d0f919061540d565b60405180910390f35b610d2061364a565b604051610d2d91906154c5565b60405180910390f35b610d3e613652565b604051610d4b91906154c5565b60405180910390f35b610d6e6004803603810190610d6991906153a3565b61365a565b604051610d7b919061540d565b60405180910390f35b610d9e6004803603810190610d999190615550565b61393a565b604051610dab91906154c5565b60405180910390f35b610dbc61394f565b604051610dc991906154c5565b60405180910390f35b610dda613957565b604051610de791906154c5565b60405180910390f35b610df861395f565b604051610e0591906154c5565b60405180910390f35b610e16613967565b604051610e2391906154c5565b60405180910390f35b610e3461396f565b604051610e4191906154c5565b60405180910390f35b610e646004803603810190610e5f91906153a3565b613977565b604051610e71919061540d565b60405180910390f35b610e82613c57565b604051610e8f91906154c5565b60405180910390f35b610ea0613c5f565b604051610ead91906154c5565b60405180910390f35b610ebe613c67565b604051610ecb91906154c5565b60405180910390f35b610edc613c6f565b604051610ee991906154c5565b60405180910390f35b610efa613c77565b604051610f0791906154c5565b60405180910390f35b610f2a6004803603810190610f2591906153a3565b613c7f565b604051610f37919061540d565b60405180910390f35b610f48613f5f565b604051610f5591906154c5565b60405180910390f35b610f66613f67565b604051610f739190615496565b60405180910390f35b610f84613ff3565b604051610f9191906154c5565b60405180910390f35b610fa2613ffb565b604051610faf91906154c5565b60405180910390f35b610fc0614003565b604051610fcd91906154c5565b60405180910390f35b610ff06004803603810190610feb91906154de565b61400b565b604051610ffd919061540d565b60405180910390f35b61100e6141a1565b60405161101b91906154c5565b60405180910390f35b61103e600480360381019061103991906153a3565b6141a9565b60405161104b919061540d565b60405180910390f35b61105c614489565b60405161106991906154c5565b60405180910390f35b61108c600480360381019061108791906153a3565b614491565b604051611099919061540d565b60405180910390f35b6110aa614771565b6040516110b791906154c5565b60405180910390f35b6110c8614779565b6040516110d591906154c5565b60405180910390f35b6110e6614781565b6040516110f391906154c5565b60405180910390f35b611104614789565b60405161111191906154c5565b60405180910390f35b611134600480360381019061112f91906153a3565b614791565b604051611141919061540d565b60405180910390f35b611152614a71565b60405161115f91906154c5565b60405180910390f35b611170614a79565b60405161117d91906154c5565b60405180910390f35b6111a0600480360381019061119b91906153a3565b614a9d565b6040516111ad919061540d565b60405180910390f35b6111be614d7d565b6040516111cb91906154c5565b60405180910390f35b6111dc614d85565b6040516111e991906154c5565b60405180910390f35b6111fa614d8d565b60405161120791906154c5565b60405180910390f35b611218614d95565b60405161122591906154c5565b60405180910390f35b611236614d9d565b60405161124391906154c5565b60405180910390f35b611254614da5565b60405161126191906154c5565b60405180910390f35b611284600480360381019061127f919061557b565b614dad565b60405161129191906154c5565b60405180910390f35b6112a2614dcd565b6040516112af91906154c5565b60405180910390f35b6112c0614dd5565b6040516112cd91906154c5565b60405180910390f35b6112f060048036038101906112eb91906153a3565b614ddd565b6040516112fd919061540d565b60405180910390f35b61130e615002565b60405161131b91906154c5565b60405180910390f35b61132c61500a565b60405161133991906154c5565b60405180910390f35b61134a615012565b60405161135791906154c5565b60405180910390f35b61136861501a565b60405161137591906154c5565b60405180910390f35b611398600480360381019061139391906153a3565b615022565b6040516113a5919061540d565b60405180910390f35b6113b6615302565b6040516113c391906154c5565b60405180910390f35b6113d461530a565b6040516113e191906154c5565b60405180910390f35b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054101561146b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161146290615603565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015611526576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161151d9061566b565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461157291906156b6565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546115c591906156e9565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461165391906156b6565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516116b791906154c5565b60405180910390a3600190509392505050565b5f80546116d690615749565b80601f016020809104026020016040519081016040528092919081815260200182805461170290615749565b801561174d5780601f106117245761010080835404028352916020019161174d565b820191905f5260205f20905b81548152906001019060200180831161173057829003601f168201915b505050505081565b5f602f905090565b5f8160055f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9258460405161183891906154c5565b60405180910390a36001905092915050565b5f601b905090565b5f6005905090565b5f601a905090565b5f601d905090565b5f6033905090565b60035481565b5f6008905090565b5f6003905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015611909576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161190090615603565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156119c4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119bb9061566b565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254611a1091906156b6565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254611a6391906156e9565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254611af191906156b6565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051611b5591906154c5565b60405180910390a3600190509392505050565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015611be9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611be090615603565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015611ca4576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611c9b9061566b565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254611cf091906156b6565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254611d4391906156e9565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254611dd191906156b6565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051611e3591906154c5565b60405180910390a3600190509392505050565b5f6002905090565b5f6010905090565b5f6048905090565b5f6041905090565b5f6035905090565b5f602e905090565b5f602c905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015611f01576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ef890615603565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015611fbc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611fb39061566b565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461200891906156b6565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461205b91906156e9565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546120e991906156b6565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161214d91906154c5565b60405180910390a3600190509392505050565b5f6001905090565b5f6045905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156121f1576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016121e8906157c3565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156122ac576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016122a39061582b565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546122f891906156b6565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461234b91906156e9565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546123d991906156b6565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161243d91906154c5565b60405180910390a3600190509392505050565b5f6034905090565b60025f9054906101000a900460ff1681565b5f603c905090565b5f604b905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156124fb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016124f290615603565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156125b6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016125ad9061566b565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461260291906156b6565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461265591906156e9565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546126e391906156b6565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161274791906154c5565b60405180910390a3600190509392505050565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156127db576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016127d290615603565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015612896576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161288d9061566b565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546128e291906156b6565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461293591906156e9565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546129c391906156b6565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051612a2791906154c5565b60405180910390a3600190509392505050565b5f6004905090565b5f600c905090565b5f6006905090565b5f601c905090565b5f6032905090565b5f6023905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015612aeb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612ae290615603565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015612ba6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612b9d9061566b565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254612bf291906156b6565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254612c4591906156e9565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254612cd391906156b6565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051612d3791906154c5565b60405180910390a3600190509392505050565b5f6011905090565b5f6021905090565b5f601f905090565b5f6026905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015612deb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612de290615603565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015612ea6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612e9d9061566b565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254612ef291906156b6565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254612f4591906156e9565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254612fd391906156b6565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161303791906154c5565b60405180910390a3600190509392505050565b5f603a905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156130d3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016130ca90615603565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054101561318e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016131859061566b565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546131da91906156b6565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461322d91906156e9565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546132bb91906156b6565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161331f91906154c5565b60405180910390a3600190509392505050565b5f6009905090565b5f6049905090565b5f602a905090565b5f6014905090565b5f6025905090565b5f6013905090565b5f6043905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156133eb576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016133e2906157c3565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156134a6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161349d9061582b565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546134f291906156b6565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461354591906156e9565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546135d391906156b6565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161363791906154c5565b60405180910390a3600190509392505050565b5f600d905090565b5f6017905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156136db576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016136d290615603565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015613796576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161378d9061566b565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546137e291906156b6565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461383591906156e9565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546138c391906156b6565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161392791906154c5565b60405180910390a3600190509392505050565b6004602052805f5260405f205f915090505481565b5f6016905090565b5f6039905090565b5f603b905090565b5f6036905090565b5f603f905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156139f8576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016139ef90615603565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015613ab3576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613aaa9061566b565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254613aff91906156b6565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254613b5291906156e9565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254613be091906156b6565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051613c4491906154c5565b60405180910390a3600190509392505050565b5f602b905090565b5f6037905090565b5f600a905090565b5f602d905090565b5f6030905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015613d00576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613cf790615603565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015613dbb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613db29061566b565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254613e0791906156b6565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254613e5a91906156e9565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254613ee891906156b6565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051613f4c91906154c5565b60405180910390a3600190509392505050565b5f600b905090565b60018054613f7490615749565b80601f0160208091040260200160405190810160405280929190818152602001828054613fa090615749565b8015613feb5780601f10613fc257610100808354040283529160200191613feb565b820191905f5260205f20905b815481529060010190602001808311613fce57829003601f168201915b505050505081565b5f6015905090565b5f6029905090565b5f6038905090565b5f8160045f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054101561408c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161408390615603565b60405180910390fd5b8160045f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546140d891906156b6565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461412b91906156e9565b925050819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161418f91906154c5565b60405180910390a36001905092915050565b5f6028905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054101561422a576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161422190615603565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156142e5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016142dc9061566b565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461433191906156b6565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461438491906156e9565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461441291906156b6565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161447691906154c5565b60405180910390a3600190509392505050565b5f6040905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015614512576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161450990615603565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156145cd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016145c49061566b565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461461991906156b6565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461466c91906156e9565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546146fa91906156b6565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161475e91906154c5565b60405180910390a3600190509392505050565b5f6018905090565b5f604a905090565b5f600f905090565b5f6044905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015614812576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161480990615603565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156148cd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016148c49061566b565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461491991906156b6565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461496c91906156e9565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546149fa91906156b6565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051614a5e91906154c5565b60405180910390a3600190509392505050565b5f6046905090565b7f000000000000000000000000000000000000000000000000000000000000000081565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015614b1e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401614b1590615603565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015614bd9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401614bd09061566b565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254614c2591906156b6565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254614c7891906156e9565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254614d0691906156b6565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051614d6a91906154c5565b60405180910390a3600190509392505050565b5f6024905090565b5f601e905090565b5f6031905090565b5f6019905090565b5f6042905090565b5f6027905090565b6005602052815f5260405f20602052805f5260405f205f91509150505481565b5f603d905090565b5f6022905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015614e5e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401614e55906157c3565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254614eaa91906156b6565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254614efd91906156e9565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254614f8b91906156b6565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051614fef91906154c5565b60405180910390a3600190509392505050565b5f6007905090565b5f6047905090565b5f603e905090565b5f6020905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156150a3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161509a90615603565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054101561515e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016151559061566b565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546151aa91906156b6565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546151fd91906156e9565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461528b91906156b6565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516152ef91906154c5565b60405180910390a3600190509392505050565b5f600e905090565b5f6012905090565b5f5ffd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f61533f82615316565b9050919050565b61534f81615335565b8114615359575f5ffd5b50565b5f8135905061536a81615346565b92915050565b5f819050919050565b61538281615370565b811461538c575f5ffd5b50565b5f8135905061539d81615379565b92915050565b5f5f5f606084860312156153ba576153b9615312565b5b5f6153c78682870161535c565b93505060206153d88682870161535c565b92505060406153e98682870161538f565b9150509250925092565b5f8115159050919050565b615407816153f3565b82525050565b5f6020820190506154205f8301846153fe565b92915050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f61546882615426565b6154728185615430565b9350615482818560208601615440565b61548b8161544e565b840191505092915050565b5f6020820190508181035f8301526154ae818461545e565b905092915050565b6154bf81615370565b82525050565b5f6020820190506154d85f8301846154b6565b92915050565b5f5f604083850312156154f4576154f3615312565b5b5f6155018582860161535c565b92505060206155128582860161538f565b9150509250929050565b5f60ff82169050919050565b6155318161551c565b82525050565b5f60208201905061554a5f830184615528565b92915050565b5f6020828403121561556557615564615312565b5b5f6155728482850161535c565b91505092915050565b5f5f6040838503121561559157615590615312565b5b5f61559e8582860161535c565b92505060206155af8582860161535c565b9150509250929050565b7f496e73756666696369656e742062616c616e63650000000000000000000000005f82015250565b5f6155ed601483615430565b91506155f8826155b9565b602082019050919050565b5f6020820190508181035f83015261561a816155e1565b9050919050565b7f496e73756666696369656e7420616c6c6f77616e6365000000000000000000005f82015250565b5f615655601683615430565b915061566082615621565b602082019050919050565b5f6020820190508181035f83015261568281615649565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f6156c082615370565b91506156cb83615370565b92508282039050818111156156e3576156e2615689565b5b92915050565b5f6156f382615370565b91506156fe83615370565b925082820190508082111561571657615715615689565b5b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f600282049050600182168061576057607f821691505b6020821081036157735761577261571c565b5b50919050565b7f41000000000000000000000000000000000000000000000000000000000000005f82015250565b5f6157ad600183615430565b91506157b882615779565b602082019050919050565b5f6020820190508181035f8301526157da816157a1565b9050919050565b7f42000000000000000000000000000000000000000000000000000000000000005f82015250565b5f615815600183615430565b9150615820826157e1565b602082019050919050565b5f6020820190508181035f83015261584281615809565b905091905056fea2646970667358221220ce03f2ea0f8ec341a07b9c0512b41f44d879b740c55b3572c5707216663e8a3f64736f6c634300081e0033", + 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. @@ -2217,130 +2217,6 @@ func (_Contract *ContractCallerSession) Dummy65() (*big.Int, error) { return _Contract.Contract.Dummy65(&_Contract.CallOpts) } -// Dummy66 is a free data retrieval call binding the contract method 0xd9bb3174. -// -// Solidity: function dummy66() pure returns(uint256) -func (_Contract *ContractCaller) Dummy66(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _Contract.contract.Call(opts, &out, "dummy66") - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -// Dummy66 is a free data retrieval call binding the contract method 0xd9bb3174. -// -// Solidity: function dummy66() pure returns(uint256) -func (_Contract *ContractSession) Dummy66() (*big.Int, error) { - return _Contract.Contract.Dummy66(&_Contract.CallOpts) -} - -// Dummy66 is a free data retrieval call binding the contract method 0xd9bb3174. -// -// Solidity: function dummy66() pure returns(uint256) -func (_Contract *ContractCallerSession) Dummy66() (*big.Int, error) { - return _Contract.Contract.Dummy66(&_Contract.CallOpts) -} - -// Dummy67 is a free data retrieval call binding the contract method 0x6578534c. -// -// Solidity: function dummy67() pure returns(uint256) -func (_Contract *ContractCaller) Dummy67(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _Contract.contract.Call(opts, &out, "dummy67") - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -// Dummy67 is a free data retrieval call binding the contract method 0x6578534c. -// -// Solidity: function dummy67() pure returns(uint256) -func (_Contract *ContractSession) Dummy67() (*big.Int, error) { - return _Contract.Contract.Dummy67(&_Contract.CallOpts) -} - -// Dummy67 is a free data retrieval call binding the contract method 0x6578534c. -// -// Solidity: function dummy67() pure returns(uint256) -func (_Contract *ContractCallerSession) Dummy67() (*big.Int, error) { - return _Contract.Contract.Dummy67(&_Contract.CallOpts) -} - -// Dummy68 is a free data retrieval call binding the contract method 0xb9a6d645. -// -// Solidity: function dummy68() pure returns(uint256) -func (_Contract *ContractCaller) Dummy68(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _Contract.contract.Call(opts, &out, "dummy68") - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -// Dummy68 is a free data retrieval call binding the contract method 0xb9a6d645. -// -// Solidity: function dummy68() pure returns(uint256) -func (_Contract *ContractSession) Dummy68() (*big.Int, error) { - return _Contract.Contract.Dummy68(&_Contract.CallOpts) -} - -// Dummy68 is a free data retrieval call binding the contract method 0xb9a6d645. -// -// Solidity: function dummy68() pure returns(uint256) -func (_Contract *ContractCallerSession) Dummy68() (*big.Int, error) { - return _Contract.Contract.Dummy68(&_Contract.CallOpts) -} - -// Dummy69 is a free data retrieval call binding the contract method 0x2787325b. -// -// Solidity: function dummy69() pure returns(uint256) -func (_Contract *ContractCaller) Dummy69(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _Contract.contract.Call(opts, &out, "dummy69") - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -// Dummy69 is a free data retrieval call binding the contract method 0x2787325b. -// -// Solidity: function dummy69() pure returns(uint256) -func (_Contract *ContractSession) Dummy69() (*big.Int, error) { - return _Contract.Contract.Dummy69(&_Contract.CallOpts) -} - -// Dummy69 is a free data retrieval call binding the contract method 0x2787325b. -// -// Solidity: function dummy69() pure returns(uint256) -func (_Contract *ContractCallerSession) Dummy69() (*big.Int, error) { - return _Contract.Contract.Dummy69(&_Contract.CallOpts) -} - // Dummy7 is a free data retrieval call binding the contract method 0xf26c779b. // // Solidity: function dummy7() pure returns(uint256) @@ -2372,192 +2248,6 @@ func (_Contract *ContractCallerSession) Dummy7() (*big.Int, error) { return _Contract.Contract.Dummy7(&_Contract.CallOpts) } -// Dummy70 is a free data retrieval call binding the contract method 0xbbe23132. -// -// Solidity: function dummy70() pure returns(uint256) -func (_Contract *ContractCaller) Dummy70(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _Contract.contract.Call(opts, &out, "dummy70") - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -// Dummy70 is a free data retrieval call binding the contract method 0xbbe23132. -// -// Solidity: function dummy70() pure returns(uint256) -func (_Contract *ContractSession) Dummy70() (*big.Int, error) { - return _Contract.Contract.Dummy70(&_Contract.CallOpts) -} - -// Dummy70 is a free data retrieval call binding the contract method 0xbbe23132. -// -// Solidity: function dummy70() pure returns(uint256) -func (_Contract *ContractCallerSession) Dummy70() (*big.Int, error) { - return _Contract.Contract.Dummy70(&_Contract.CallOpts) -} - -// Dummy71 is a free data retrieval call binding the contract method 0xf4978b04. -// -// Solidity: function dummy71() pure returns(uint256) -func (_Contract *ContractCaller) Dummy71(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _Contract.contract.Call(opts, &out, "dummy71") - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -// Dummy71 is a free data retrieval call binding the contract method 0xf4978b04. -// -// Solidity: function dummy71() pure returns(uint256) -func (_Contract *ContractSession) Dummy71() (*big.Int, error) { - return _Contract.Contract.Dummy71(&_Contract.CallOpts) -} - -// Dummy71 is a free data retrieval call binding the contract method 0xf4978b04. -// -// Solidity: function dummy71() pure returns(uint256) -func (_Contract *ContractCallerSession) Dummy71() (*big.Int, error) { - return _Contract.Contract.Dummy71(&_Contract.CallOpts) -} - -// Dummy72 is a free data retrieval call binding the contract method 0x1f29783f. -// -// Solidity: function dummy72() pure returns(uint256) -func (_Contract *ContractCaller) Dummy72(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _Contract.contract.Call(opts, &out, "dummy72") - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -// Dummy72 is a free data retrieval call binding the contract method 0x1f29783f. -// -// Solidity: function dummy72() pure returns(uint256) -func (_Contract *ContractSession) Dummy72() (*big.Int, error) { - return _Contract.Contract.Dummy72(&_Contract.CallOpts) -} - -// Dummy72 is a free data retrieval call binding the contract method 0x1f29783f. -// -// Solidity: function dummy72() pure returns(uint256) -func (_Contract *ContractCallerSession) Dummy72() (*big.Int, error) { - return _Contract.Contract.Dummy72(&_Contract.CallOpts) -} - -// Dummy73 is a free data retrieval call binding the contract method 0x595471b8. -// -// Solidity: function dummy73() pure returns(uint256) -func (_Contract *ContractCaller) Dummy73(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _Contract.contract.Call(opts, &out, "dummy73") - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -// Dummy73 is a free data retrieval call binding the contract method 0x595471b8. -// -// Solidity: function dummy73() pure returns(uint256) -func (_Contract *ContractSession) Dummy73() (*big.Int, error) { - return _Contract.Contract.Dummy73(&_Contract.CallOpts) -} - -// Dummy73 is a free data retrieval call binding the contract method 0x595471b8. -// -// Solidity: function dummy73() pure returns(uint256) -func (_Contract *ContractCallerSession) Dummy73() (*big.Int, error) { - return _Contract.Contract.Dummy73(&_Contract.CallOpts) -} - -// Dummy74 is a free data retrieval call binding the contract method 0xb4c48668. -// -// Solidity: function dummy74() pure returns(uint256) -func (_Contract *ContractCaller) Dummy74(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _Contract.contract.Call(opts, &out, "dummy74") - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -// Dummy74 is a free data retrieval call binding the contract method 0xb4c48668. -// -// Solidity: function dummy74() pure returns(uint256) -func (_Contract *ContractSession) Dummy74() (*big.Int, error) { - return _Contract.Contract.Dummy74(&_Contract.CallOpts) -} - -// Dummy74 is a free data retrieval call binding the contract method 0xb4c48668. -// -// Solidity: function dummy74() pure returns(uint256) -func (_Contract *ContractCallerSession) Dummy74() (*big.Int, error) { - return _Contract.Contract.Dummy74(&_Contract.CallOpts) -} - -// Dummy75 is a free data retrieval call binding the contract method 0x378c5382. -// -// Solidity: function dummy75() pure returns(uint256) -func (_Contract *ContractCaller) Dummy75(opts *bind.CallOpts) (*big.Int, error) { - var out []interface{} - err := _Contract.contract.Call(opts, &out, "dummy75") - - if err != nil { - return *new(*big.Int), err - } - - out0 := *abi.ConvertType(out[0], new(*big.Int)).(**big.Int) - - return out0, err - -} - -// Dummy75 is a free data retrieval call binding the contract method 0x378c5382. -// -// Solidity: function dummy75() pure returns(uint256) -func (_Contract *ContractSession) Dummy75() (*big.Int, error) { - return _Contract.Contract.Dummy75(&_Contract.CallOpts) -} - -// Dummy75 is a free data retrieval call binding the contract method 0x378c5382. -// -// Solidity: function dummy75() pure returns(uint256) -func (_Contract *ContractCallerSession) Dummy75() (*big.Int, error) { - return _Contract.Contract.Dummy75(&_Contract.CallOpts) -} - // Dummy8 is a free data retrieval call binding the contract method 0x19cf6a91. // // Solidity: function dummy8() pure returns(uint256) diff --git a/scenarios/statebloat/contract_deploy/contract/StateBloatToken.sol b/scenarios/statebloat/contract_deploy/contract/StateBloatToken.sol index 29fe7221..4fb9e66d 100644 --- a/scenarios/statebloat/contract_deploy/contract/StateBloatToken.sol +++ b/scenarios/statebloat/contract_deploy/contract/StateBloatToken.sol @@ -318,46 +318,6 @@ contract StateBloatToken { return 65; } - 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 dummy70() public pure returns (uint256) { - return 70; - } - - function dummy71() public pure returns (uint256) { - return 71; - } - - function dummy72() public pure returns (uint256) { - return 72; - } - - function dummy73() public pure returns (uint256) { - return 73; - } - - function dummy74() public pure returns (uint256) { - return 74; - } - - function dummy75() public pure returns (uint256) { - return 75; - } - function transferFrom1( address from, address to, From 3132162b5f6762ec654a972c18d49bad74fc3c08 Mon Sep 17 00:00:00 2001 From: CPerezz Date: Sat, 7 Jun 2025 12:43:44 +0200 Subject: [PATCH 20/26] feat(contract-deploy): improve bytecode size ratio & auto-adapt to gas_limit - Introduced BlockDeploymentStats struct to track deployment statistics per block, including contract count, total gas used, and total bytecode size. - Implemented real-time block monitoring for logging deployment summaries. - Updated contract bytecode size calculations to reflect actual deployed bytecode. - Adjusted transaction processing intervals for improved efficiency. --- .../contract/StateBloatToken.bin | 2 +- .../contract/StateBloatToken.sol | 21 ++ .../contract_deploy/contract_deploy.go | 245 +++++++++++++++--- 3 files changed, 230 insertions(+), 38 deletions(-) diff --git a/scenarios/statebloat/contract_deploy/contract/StateBloatToken.bin b/scenarios/statebloat/contract_deploy/contract/StateBloatToken.bin index 7d363997..755497f1 100644 --- a/scenarios/statebloat/contract_deploy/contract/StateBloatToken.bin +++ b/scenarios/statebloat/contract_deploy/contract/StateBloatToken.bin @@ -1 +1 @@ -60a060405234801561000f575f5ffd5b50604051615d6a380380615d6a833981810160405281019061003191906101f4565b6040518060400160405280601181526020017f537461746520426c6f617420546f6b656e0000000000000000000000000000008152505f90816100749190610453565b506040518060400160405280600381526020017f5342540000000000000000000000000000000000000000000000000000000000815250600190816100b99190610453565b50601260025f6101000a81548160ff021916908360ff160217905550806080818152505060025f9054906101000a900460ff16600a6100f8919061068a565b620f424061010691906106d4565b60038190555060035460045f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055503373ffffffffffffffffffffffffffffffffffffffff165f73ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef6003546040516101af9190610724565b60405180910390a35061073d565b5f5ffd5b5f819050919050565b6101d3816101c1565b81146101dd575f5ffd5b50565b5f815190506101ee816101ca565b92915050565b5f60208284031215610209576102086101bd565b5b5f610216848285016101e0565b91505092915050565b5f81519050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f600282049050600182168061029a57607f821691505b6020821081036102ad576102ac610256565b5b50919050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f6008830261030f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff826102d4565b61031986836102d4565b95508019841693508086168417925050509392505050565b5f819050919050565b5f61035461034f61034a846101c1565b610331565b6101c1565b9050919050565b5f819050919050565b61036d8361033a565b6103816103798261035b565b8484546102e0565b825550505050565b5f5f905090565b610398610389565b6103a3818484610364565b505050565b5b818110156103c6576103bb5f82610390565b6001810190506103a9565b5050565b601f82111561040b576103dc816102b3565b6103e5846102c5565b810160208510156103f4578190505b610408610400856102c5565b8301826103a8565b50505b505050565b5f82821c905092915050565b5f61042b5f1984600802610410565b1980831691505092915050565b5f610443838361041c565b9150826002028217905092915050565b61045c8261021f565b67ffffffffffffffff81111561047557610474610229565b5b61047f8254610283565b61048a8282856103ca565b5f60209050601f8311600181146104bb575f84156104a9578287015190505b6104b38582610438565b86555061051a565b601f1984166104c9866102b3565b5f5b828110156104f0578489015182556001820191506020850194506020810190506104cb565b8683101561050d5784890151610509601f89168261041c565b8355505b6001600288020188555050505b505050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f8160011c9050919050565b5f5f8291508390505b60018511156105a4578086048111156105805761057f610522565b5b600185161561058f5780820291505b808102905061059d8561054f565b9450610564565b94509492505050565b5f826105bc5760019050610677565b816105c9575f9050610677565b81600181146105df57600281146105e957610618565b6001915050610677565b60ff8411156105fb576105fa610522565b5b8360020a91508482111561061257610611610522565b5b50610677565b5060208310610133831016604e8410600b841016171561064d5782820a90508381111561064857610647610522565b5b610677565b61065a848484600161055b565b9250905081840481111561067157610670610522565b5b81810290505b9392505050565b5f60ff82169050919050565b5f610694826101c1565b915061069f8361067e565b92506106cc7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff84846105ad565b905092915050565b5f6106de826101c1565b91506106e9836101c1565b92508282026106f7816101c1565b9150828204841483151761070e5761070d610522565b5b5092915050565b61071e816101c1565b82525050565b5f6020820190506107375f830184610715565b92915050565b6080516156156107555f395f61482101526156155ff3fe608060405234801561000f575f5ffd5b5060043610610518575f3560e01c8063657b6ef7116102a2578063aaa7af7011610170578063d7419469116100d7578063f26c779b11610090578063f26c779b1461110a578063f5f5738114611128578063f8716f1414611146578063faf35ced14611164578063fe7d599614611194578063ffbf0469146111b257610518565b8063d741946914611032578063dc1d8a9b14611050578063dd62ed3e1461106e578063e2d275301461109e578063e8c927b3146110bc578063eb4329c8146110da57610518565b8063bb9bfe0611610129578063bb9bfe0614610f5a578063bfa0b13314610f8a578063c2be97e314610fa8578063c958d4bf14610fd8578063cfd6686314610ff6578063d101dcd01461101457610518565b8063aaa7af7014610e82578063acc5aee914610ea0578063ad8f422114610ed0578063b1802b9a14610eee578063b2bb360e14610f1e578063b66dd75014610f3c57610518565b80637c72ed0d116102145780638f4a8406116101cd5780638f4a840614610dbc57806395d89b4114610dda5780639c5dfe7314610df85780639df61a2514610e16578063a891d4d414610e34578063a9059cbb14610e5257610518565b80637c72ed0d14610cf65780637dffdc3214610d145780637e54493714610d325780637f34d94b14610d505780638619d60714610d6e5780638789ca6714610d8c57610518565b806374e73fd31161026657806374e73fd314610c3057806374f83d0214610c4e57806377c0209e14610c6c578063792c7f3e14610c8a5780637a319c1814610ca85780637c66673e14610cc657610518565b8063657b6ef714610b64578063672151fe14610b945780636abceacd14610bb25780636c12ed2814610bd057806370a0823114610c0057610518565b80633125f37a116103ea5780634a2e93c611610351578063552a1b561161030a578063552a1b5614610a9e57806358b6a9bd14610ace5780635af92c0514610aec57806361b970eb14610b0a578063639ec53a14610b285780636547317414610b4657610518565b80634a2e93c6146109d85780634b3c7f5f146109f65780634e1dbb8214610a145780634f5e555714610a325780634f7bd75a14610a5057806354c2792014610a8057610518565b80633ea117ce116103a35780633ea117ce146109125780634128a85d14610930578063418b18161461094e57806342937dbd1461096c57806343a6b92d1461098a57806344050a28146109a857610518565b80633125f37a1461083a578063313ce5671461085857806334517f0b1461087657806339e0bd12146108945780633a131990146108c45780633b6be459146108f457610518565b80631a97f18e1161048e5780631fd298ec116104475780631fd298ec1461076257806321ecd7a314610780578063239af2a51461079e57806323b872dd146107bc5780632545d8b7146107ec578063291c3bd71461080a57610518565b80631a97f18e1461068a5780631b17c65c146106a85780631bbffe6f146106d85780631d527cde146107085780631eaa7c52146107265780631f4495891461074457610518565b80631215a3ab116104e05780631215a3ab146105d657806312901b42146105f457806313ebb5ec1461061257806316a3045b1461063057806318160ddd1461064e57806319cf6a911461066c57610518565b80630460faf61461051c57806306fdde031461054c5780630717b1611461056a578063095ea7b3146105885780630cb7a9e7146105b8575b5f5ffd5b61053660048036038101906105319190615139565b6111d0565b60405161054391906151a3565b60405180910390f35b6105546114b0565b604051610561919061522c565b60405180910390f35b61057261153b565b60405161057f919061525b565b60405180910390f35b6105a2600480360381019061059d9190615274565b611543565b6040516105af91906151a3565b60405180910390f35b6105c0611630565b6040516105cd919061525b565b60405180910390f35b6105de611638565b6040516105eb919061525b565b60405180910390f35b6105fc611640565b604051610609919061525b565b60405180910390f35b61061a611648565b604051610627919061525b565b60405180910390f35b610638611650565b604051610645919061525b565b60405180910390f35b610656611658565b604051610663919061525b565b60405180910390f35b61067461165e565b604051610681919061525b565b60405180910390f35b610692611666565b60405161069f919061525b565b60405180910390f35b6106c260048036038101906106bd9190615139565b61166e565b6040516106cf91906151a3565b60405180910390f35b6106f260048036038101906106ed9190615139565b61194e565b6040516106ff91906151a3565b60405180910390f35b610710611c2e565b60405161071d919061525b565b60405180910390f35b61072e611c36565b60405161073b919061525b565b60405180910390f35b61074c611c3e565b604051610759919061525b565b60405180910390f35b61076a611c46565b604051610777919061525b565b60405180910390f35b610788611c4e565b604051610795919061525b565b60405180910390f35b6107a6611c56565b6040516107b3919061525b565b60405180910390f35b6107d660048036038101906107d19190615139565b611c5e565b6040516107e391906151a3565b60405180910390f35b6107f4611f3e565b604051610801919061525b565b60405180910390f35b610824600480360381019061081f9190615139565b611f46565b60405161083191906151a3565b60405180910390f35b610842612226565b60405161084f919061525b565b60405180910390f35b61086061222e565b60405161086d91906152cd565b60405180910390f35b61087e612240565b60405161088b919061525b565b60405180910390f35b6108ae60048036038101906108a99190615139565b612248565b6040516108bb91906151a3565b60405180910390f35b6108de60048036038101906108d99190615139565b612528565b6040516108eb91906151a3565b60405180910390f35b6108fc612808565b604051610909919061525b565b60405180910390f35b61091a612810565b604051610927919061525b565b60405180910390f35b610938612818565b604051610945919061525b565b60405180910390f35b610956612820565b604051610963919061525b565b60405180910390f35b610974612828565b604051610981919061525b565b60405180910390f35b610992612830565b60405161099f919061525b565b60405180910390f35b6109c260048036038101906109bd9190615139565b612838565b6040516109cf91906151a3565b60405180910390f35b6109e0612b18565b6040516109ed919061525b565b60405180910390f35b6109fe612b20565b604051610a0b919061525b565b60405180910390f35b610a1c612b28565b604051610a29919061525b565b60405180910390f35b610a3a612b30565b604051610a47919061525b565b60405180910390f35b610a6a6004803603810190610a659190615139565b612b38565b604051610a7791906151a3565b60405180910390f35b610a88612e18565b604051610a95919061525b565b60405180910390f35b610ab86004803603810190610ab39190615139565b612e20565b604051610ac591906151a3565b60405180910390f35b610ad6613100565b604051610ae3919061525b565b60405180910390f35b610af4613108565b604051610b01919061525b565b60405180910390f35b610b12613110565b604051610b1f919061525b565b60405180910390f35b610b30613118565b604051610b3d919061525b565b60405180910390f35b610b4e613120565b604051610b5b919061525b565b60405180910390f35b610b7e6004803603810190610b799190615139565b613128565b604051610b8b91906151a3565b60405180910390f35b610b9c613408565b604051610ba9919061525b565b60405180910390f35b610bba613410565b604051610bc7919061525b565b60405180910390f35b610bea6004803603810190610be59190615139565b613418565b604051610bf791906151a3565b60405180910390f35b610c1a6004803603810190610c1591906152e6565b6136f8565b604051610c27919061525b565b60405180910390f35b610c3861370d565b604051610c45919061525b565b60405180910390f35b610c56613715565b604051610c63919061525b565b60405180910390f35b610c7461371d565b604051610c81919061525b565b60405180910390f35b610c92613725565b604051610c9f919061525b565b60405180910390f35b610cb061372d565b604051610cbd919061525b565b60405180910390f35b610ce06004803603810190610cdb9190615139565b613735565b604051610ced91906151a3565b60405180910390f35b610cfe613a15565b604051610d0b919061525b565b60405180910390f35b610d1c613a1d565b604051610d29919061525b565b60405180910390f35b610d3a613a25565b604051610d47919061525b565b60405180910390f35b610d58613a2d565b604051610d65919061525b565b60405180910390f35b610d76613a35565b604051610d83919061525b565b60405180910390f35b610da66004803603810190610da19190615139565b613a3d565b604051610db391906151a3565b60405180910390f35b610dc4613d1d565b604051610dd1919061525b565b60405180910390f35b610de2613d25565b604051610def919061522c565b60405180910390f35b610e00613db1565b604051610e0d919061525b565b60405180910390f35b610e1e613db9565b604051610e2b919061525b565b60405180910390f35b610e3c613dc1565b604051610e49919061525b565b60405180910390f35b610e6c6004803603810190610e679190615274565b613dc9565b604051610e7991906151a3565b60405180910390f35b610e8a613f5f565b604051610e97919061525b565b60405180910390f35b610eba6004803603810190610eb59190615139565b613f67565b604051610ec791906151a3565b60405180910390f35b610ed8614247565b604051610ee5919061525b565b60405180910390f35b610f086004803603810190610f039190615139565b61424f565b604051610f1591906151a3565b60405180910390f35b610f2661452f565b604051610f33919061525b565b60405180910390f35b610f44614537565b604051610f51919061525b565b60405180910390f35b610f746004803603810190610f6f9190615139565b61453f565b604051610f8191906151a3565b60405180910390f35b610f9261481f565b604051610f9f919061525b565b60405180910390f35b610fc26004803603810190610fbd9190615139565b614843565b604051610fcf91906151a3565b60405180910390f35b610fe0614b23565b604051610fed919061525b565b60405180910390f35b610ffe614b2b565b60405161100b919061525b565b60405180910390f35b61101c614b33565b604051611029919061525b565b60405180910390f35b61103a614b3b565b604051611047919061525b565b60405180910390f35b611058614b43565b604051611065919061525b565b60405180910390f35b61108860048036038101906110839190615311565b614b4b565b604051611095919061525b565b60405180910390f35b6110a6614b6b565b6040516110b3919061525b565b60405180910390f35b6110c4614b73565b6040516110d1919061525b565b60405180910390f35b6110f460048036038101906110ef9190615139565b614b7b565b60405161110191906151a3565b60405180910390f35b611112614da0565b60405161111f919061525b565b60405180910390f35b611130614da8565b60405161113d919061525b565b60405180910390f35b61114e614db0565b60405161115b919061525b565b60405180910390f35b61117e60048036038101906111799190615139565b614db8565b60405161118b91906151a3565b60405180910390f35b61119c615098565b6040516111a9919061525b565b60405180910390f35b6111ba6150a0565b6040516111c7919061525b565b60405180910390f35b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015611251576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161124890615399565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054101561130c576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161130390615401565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254611358919061544c565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546113ab919061547f565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254611439919061544c565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161149d919061525b565b60405180910390a3600190509392505050565b5f80546114bc906154df565b80601f01602080910402602001604051908101604052809291908181526020018280546114e8906154df565b80156115335780601f1061150a57610100808354040283529160200191611533565b820191905f5260205f20905b81548152906001019060200180831161151657829003601f168201915b505050505081565b5f602f905090565b5f8160055f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9258460405161161e919061525b565b60405180910390a36001905092915050565b5f601b905090565b5f6005905090565b5f601a905090565b5f601d905090565b5f6033905090565b60035481565b5f6008905090565b5f6003905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156116ef576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016116e690615399565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156117aa576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117a190615401565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546117f6919061544c565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254611849919061547f565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546118d7919061544c565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161193b919061525b565b60405180910390a3600190509392505050565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156119cf576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016119c690615399565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015611a8a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611a8190615401565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254611ad6919061544c565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254611b29919061547f565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254611bb7919061544c565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051611c1b919061525b565b60405180910390a3600190509392505050565b5f6002905090565b5f6010905090565b5f6041905090565b5f6035905090565b5f602e905090565b5f602c905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015611cdf576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611cd690615399565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015611d9a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611d9190615401565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254611de6919061544c565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254611e39919061547f565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254611ec7919061544c565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051611f2b919061525b565b60405180910390a3600190509392505050565b5f6001905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015611fc7576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611fbe90615559565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015612082576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612079906155c1565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546120ce919061544c565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254612121919061547f565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546121af919061544c565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051612213919061525b565b60405180910390a3600190509392505050565b5f6034905090565b60025f9054906101000a900460ff1681565b5f603c905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156122c9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016122c090615399565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015612384576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161237b90615401565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546123d0919061544c565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254612423919061547f565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546124b1919061544c565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051612515919061525b565b60405180910390a3600190509392505050565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156125a9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016125a090615399565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015612664576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161265b90615401565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546126b0919061544c565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254612703919061547f565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254612791919061544c565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516127f5919061525b565b60405180910390a3600190509392505050565b5f6004905090565b5f600c905090565b5f6006905090565b5f601c905090565b5f6032905090565b5f6023905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156128b9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016128b090615399565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015612974576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161296b90615401565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546129c0919061544c565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254612a13919061547f565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254612aa1919061544c565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051612b05919061525b565b60405180910390a3600190509392505050565b5f6011905090565b5f6021905090565b5f601f905090565b5f6026905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015612bb9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612bb090615399565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015612c74576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612c6b90615401565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254612cc0919061544c565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254612d13919061547f565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254612da1919061544c565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051612e05919061525b565b60405180910390a3600190509392505050565b5f603a905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015612ea1576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612e9890615399565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015612f5c576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612f5390615401565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254612fa8919061544c565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254612ffb919061547f565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254613089919061544c565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516130ed919061525b565b60405180910390a3600190509392505050565b5f6009905090565b5f602a905090565b5f6014905090565b5f6025905090565b5f6013905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156131a9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016131a090615559565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015613264576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161325b906155c1565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546132b0919061544c565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254613303919061547f565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254613391919061544c565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516133f5919061525b565b60405180910390a3600190509392505050565b5f600d905090565b5f6017905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015613499576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161349090615399565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015613554576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161354b90615401565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546135a0919061544c565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546135f3919061547f565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254613681919061544c565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516136e5919061525b565b60405180910390a3600190509392505050565b6004602052805f5260405f205f915090505481565b5f6016905090565b5f6039905090565b5f603b905090565b5f6036905090565b5f603f905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156137b6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016137ad90615399565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015613871576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161386890615401565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546138bd919061544c565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254613910919061547f565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461399e919061544c565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051613a02919061525b565b60405180910390a3600190509392505050565b5f602b905090565b5f6037905090565b5f600a905090565b5f602d905090565b5f6030905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015613abe576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613ab590615399565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015613b79576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613b7090615401565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254613bc5919061544c565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254613c18919061547f565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254613ca6919061544c565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051613d0a919061525b565b60405180910390a3600190509392505050565b5f600b905090565b60018054613d32906154df565b80601f0160208091040260200160405190810160405280929190818152602001828054613d5e906154df565b8015613da95780601f10613d8057610100808354040283529160200191613da9565b820191905f5260205f20905b815481529060010190602001808311613d8c57829003601f168201915b505050505081565b5f6015905090565b5f6029905090565b5f6038905090565b5f8160045f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015613e4a576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613e4190615399565b60405180910390fd5b8160045f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254613e96919061544c565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254613ee9919061547f565b925050819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051613f4d919061525b565b60405180910390a36001905092915050565b5f6028905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015613fe8576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613fdf90615399565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156140a3576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161409a90615401565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546140ef919061544c565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254614142919061547f565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546141d0919061544c565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051614234919061525b565b60405180910390a3600190509392505050565b5f6040905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156142d0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016142c790615399565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054101561438b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161438290615401565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546143d7919061544c565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461442a919061547f565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546144b8919061544c565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161451c919061525b565b60405180910390a3600190509392505050565b5f6018905090565b5f600f905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156145c0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016145b790615399565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054101561467b576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161467290615401565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546146c7919061544c565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461471a919061547f565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546147a8919061544c565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161480c919061525b565b60405180910390a3600190509392505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156148c4576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016148bb90615399565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054101561497f576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161497690615401565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546149cb919061544c565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254614a1e919061547f565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254614aac919061544c565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051614b10919061525b565b60405180910390a3600190509392505050565b5f6024905090565b5f601e905090565b5f6031905090565b5f6019905090565b5f6027905090565b6005602052815f5260405f20602052805f5260405f205f91509150505481565b5f603d905090565b5f6022905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015614bfc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401614bf390615559565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254614c48919061544c565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254614c9b919061547f565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254614d29919061544c565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051614d8d919061525b565b60405180910390a3600190509392505050565b5f6007905090565b5f603e905090565b5f6020905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015614e39576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401614e3090615399565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015614ef4576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401614eeb90615401565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254614f40919061544c565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254614f93919061547f565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254615021919061544c565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051615085919061525b565b60405180910390a3600190509392505050565b5f600e905090565b5f6012905090565b5f5ffd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f6150d5826150ac565b9050919050565b6150e5816150cb565b81146150ef575f5ffd5b50565b5f81359050615100816150dc565b92915050565b5f819050919050565b61511881615106565b8114615122575f5ffd5b50565b5f813590506151338161510f565b92915050565b5f5f5f606084860312156151505761514f6150a8565b5b5f61515d868287016150f2565b935050602061516e868287016150f2565b925050604061517f86828701615125565b9150509250925092565b5f8115159050919050565b61519d81615189565b82525050565b5f6020820190506151b65f830184615194565b92915050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f6151fe826151bc565b61520881856151c6565b93506152188185602086016151d6565b615221816151e4565b840191505092915050565b5f6020820190508181035f83015261524481846151f4565b905092915050565b61525581615106565b82525050565b5f60208201905061526e5f83018461524c565b92915050565b5f5f6040838503121561528a576152896150a8565b5b5f615297858286016150f2565b92505060206152a885828601615125565b9150509250929050565b5f60ff82169050919050565b6152c7816152b2565b82525050565b5f6020820190506152e05f8301846152be565b92915050565b5f602082840312156152fb576152fa6150a8565b5b5f615308848285016150f2565b91505092915050565b5f5f60408385031215615327576153266150a8565b5b5f615334858286016150f2565b9250506020615345858286016150f2565b9150509250929050565b7f496e73756666696369656e742062616c616e63650000000000000000000000005f82015250565b5f6153836014836151c6565b915061538e8261534f565b602082019050919050565b5f6020820190508181035f8301526153b081615377565b9050919050565b7f496e73756666696369656e7420616c6c6f77616e6365000000000000000000005f82015250565b5f6153eb6016836151c6565b91506153f6826153b7565b602082019050919050565b5f6020820190508181035f830152615418816153df565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f61545682615106565b915061546183615106565b92508282039050818111156154795761547861541f565b5b92915050565b5f61548982615106565b915061549483615106565b92508282019050808211156154ac576154ab61541f565b5b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f60028204905060018216806154f657607f821691505b602082108103615509576155086154b2565b5b50919050565b7f41000000000000000000000000000000000000000000000000000000000000005f82015250565b5f6155436001836151c6565b915061554e8261550f565b602082019050919050565b5f6020820190508181035f83015261557081615537565b9050919050565b7f42000000000000000000000000000000000000000000000000000000000000005f82015250565b5f6155ab6001836151c6565b91506155b682615577565b602082019050919050565b5f6020820190508181035f8301526155d88161559f565b905091905056fea26469706673582212206fbf384dcd110eb4456b07e83a2c8a392433c7852a66dec9f8ebf3989cad1f6764736f6c634300081e0033 \ No newline at end of file +60a060405234801561000f575f5ffd5b50604051615fba380380615fba833981810160405281019061003191906101f4565b6040518060400160405280601181526020017f537461746520426c6f617420546f6b656e0000000000000000000000000000008152505f90816100749190610453565b506040518060400160405280600381526020017f5342540000000000000000000000000000000000000000000000000000000000815250600190816100b99190610453565b50601260025f6101000a81548160ff021916908360ff160217905550806080818152505060025f9054906101000a900460ff16600a6100f8919061068a565b620f424061010691906106d4565b60038190555060035460045f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055503373ffffffffffffffffffffffffffffffffffffffff165f73ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef6003546040516101af9190610724565b60405180910390a35061073d565b5f5ffd5b5f819050919050565b6101d3816101c1565b81146101dd575f5ffd5b50565b5f815190506101ee816101ca565b92915050565b5f60208284031215610209576102086101bd565b5b5f610216848285016101e0565b91505092915050565b5f81519050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f600282049050600182168061029a57607f821691505b6020821081036102ad576102ac610256565b5b50919050565b5f819050815f5260205f209050919050565b5f6020601f8301049050919050565b5f82821b905092915050565b5f6008830261030f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff826102d4565b61031986836102d4565b95508019841693508086168417925050509392505050565b5f819050919050565b5f61035461034f61034a846101c1565b610331565b6101c1565b9050919050565b5f819050919050565b61036d8361033a565b6103816103798261035b565b8484546102e0565b825550505050565b5f5f905090565b610398610389565b6103a3818484610364565b505050565b5b818110156103c6576103bb5f82610390565b6001810190506103a9565b5050565b601f82111561040b576103dc816102b3565b6103e5846102c5565b810160208510156103f4578190505b610408610400856102c5565b8301826103a8565b50505b505050565b5f82821c905092915050565b5f61042b5f1984600802610410565b1980831691505092915050565b5f610443838361041c565b9150826002028217905092915050565b61045c8261021f565b67ffffffffffffffff81111561047557610474610229565b5b61047f8254610283565b61048a8282856103ca565b5f60209050601f8311600181146104bb575f84156104a9578287015190505b6104b38582610438565b86555061051a565b601f1984166104c9866102b3565b5f5b828110156104f0578489015182556001820191506020850194506020810190506104cb565b8683101561050d5784890151610509601f89168261041c565b8355505b6001600288020188555050505b505050505050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f8160011c9050919050565b5f5f8291508390505b60018511156105a4578086048111156105805761057f610522565b5b600185161561058f5780820291505b808102905061059d8561054f565b9450610564565b94509492505050565b5f826105bc5760019050610677565b816105c9575f9050610677565b81600181146105df57600281146105e957610618565b6001915050610677565b60ff8411156105fb576105fa610522565b5b8360020a91508482111561061257610611610522565b5b50610677565b5060208310610133831016604e8410600b841016171561064d5782820a90508381111561064857610647610522565b5b610677565b61065a848484600161055b565b9250905081840481111561067157610670610522565b5b81810290505b9392505050565b5f60ff82169050919050565b5f610694826101c1565b915061069f8361067e565b92506106cc7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff84846105ad565b905092915050565b5f6106de826101c1565b91506106e9836101c1565b92508282026106f7816101c1565b9150828204841483151761070e5761070d610522565b5b5092915050565b61071e816101c1565b82525050565b5f6020820190506107375f830184610715565b92915050565b6080516158656107555f395f61493601526158655ff3fe608060405234801561000f575f5ffd5b506004361061057f575f3560e01c8063657b6ef7116102e3578063ad8f42211161018b578063d9bb3174116100f2578063ee1682b6116100ab578063f8716f1411610085578063f8716f1414611243578063faf35ced14611261578063fe7d599614611291578063ffbf0469146112af5761057f565b8063ee1682b6146111e9578063f26c779b14611207578063f5f57381146112255761057f565b8063d9bb317414611111578063dc1d8a9b1461112f578063dd62ed3e1461114d578063e2d275301461117d578063e8c927b31461119b578063eb4329c8146111b95761057f565b8063bfa0b13311610144578063bfa0b1331461104b578063c2be97e314611069578063c958d4bf14611099578063cfd66863146110b7578063d101dcd0146110d5578063d7419469146110f35761057f565b8063ad8f422114610f73578063b1802b9a14610f91578063b2bb360e14610fc1578063b66dd75014610fdf578063b9a6d64514610ffd578063bb9bfe061461101b5761057f565b80637dffdc321161024a57806395d89b4111610203578063a891d4d4116101dd578063a891d4d414610ed7578063a9059cbb14610ef5578063aaa7af7014610f25578063acc5aee914610f435761057f565b806395d89b4114610e7d5780639c5dfe7314610e9b5780639df61a2514610eb95761057f565b80637dffdc3214610db75780637e54493714610dd55780637f34d94b14610df35780638619d60714610e115780638789ca6714610e2f5780638f4a840614610e5f5761057f565b806374f83d021161029c57806374f83d0214610cf157806377c0209e14610d0f578063792c7f3e14610d2d5780637a319c1814610d4b5780637c66673e14610d695780637c72ed0d14610d995761057f565b8063657b6ef714610c07578063672151fe14610c375780636abceacd14610c555780636c12ed2814610c7357806370a0823114610ca357806374e73fd314610cd35761057f565b80633125f37a116104465780634a2e93c6116103ad578063552a1b561161036657806361b970eb1161034057806361b970eb14610b8f578063639ec53a14610bad5780636547317414610bcb5780636578534c14610be95761057f565b8063552a1b5614610b2357806358b6a9bd14610b535780635af92c0514610b715761057f565b80634a2e93c614610a5d5780634b3c7f5f14610a7b5780634e1dbb8214610a995780634f5e555714610ab75780634f7bd75a14610ad557806354c2792014610b055761057f565b80633ea117ce116103ff5780633ea117ce146109975780634128a85d146109b5578063418b1816146109d357806342937dbd146109f157806343a6b92d14610a0f57806344050a2814610a2d5761057f565b80633125f37a146108bf578063313ce567146108dd57806334517f0b146108fb57806339e0bd12146109195780633a131990146109495780633b6be459146109795761057f565b80631b17c65c116104ea57806321ecd7a3116104a357806321ecd7a3146107e7578063239af2a51461080557806323b872dd146108235780632545d8b7146108535780632787325b14610871578063291c3bd71461088f5761057f565b80631b17c65c1461070f5780631bbffe6f1461073f5780631d527cde1461076f5780631eaa7c521461078d5780631f449589146107ab5780631fd298ec146107c95761057f565b806312901b421161053c57806312901b421461065b57806313ebb5ec1461067957806316a3045b1461069757806318160ddd146106b557806319cf6a91146106d35780631a97f18e146106f15761057f565b80630460faf61461058357806306fdde03146105b35780630717b161146105d1578063095ea7b3146105ef5780630cb7a9e71461061f5780631215a3ab1461063d575b5f5ffd5b61059d60048036038101906105989190615275565b6112cd565b6040516105aa91906152df565b60405180910390f35b6105bb6115ad565b6040516105c89190615368565b60405180910390f35b6105d9611638565b6040516105e69190615397565b60405180910390f35b610609600480360381019061060491906153b0565b611640565b60405161061691906152df565b60405180910390f35b61062761172d565b6040516106349190615397565b60405180910390f35b610645611735565b6040516106529190615397565b60405180910390f35b61066361173d565b6040516106709190615397565b60405180910390f35b610681611745565b60405161068e9190615397565b60405180910390f35b61069f61174d565b6040516106ac9190615397565b60405180910390f35b6106bd611755565b6040516106ca9190615397565b60405180910390f35b6106db61175b565b6040516106e89190615397565b60405180910390f35b6106f9611763565b6040516107069190615397565b60405180910390f35b61072960048036038101906107249190615275565b61176b565b60405161073691906152df565b60405180910390f35b61075960048036038101906107549190615275565b611a4b565b60405161076691906152df565b60405180910390f35b610777611d2b565b6040516107849190615397565b60405180910390f35b610795611d33565b6040516107a29190615397565b60405180910390f35b6107b3611d3b565b6040516107c09190615397565b60405180910390f35b6107d1611d43565b6040516107de9190615397565b60405180910390f35b6107ef611d4b565b6040516107fc9190615397565b60405180910390f35b61080d611d53565b60405161081a9190615397565b60405180910390f35b61083d60048036038101906108389190615275565b611d5b565b60405161084a91906152df565b60405180910390f35b61085b61203b565b6040516108689190615397565b60405180910390f35b610879612043565b6040516108869190615397565b60405180910390f35b6108a960048036038101906108a49190615275565b61204b565b6040516108b691906152df565b60405180910390f35b6108c761232b565b6040516108d49190615397565b60405180910390f35b6108e5612333565b6040516108f29190615409565b60405180910390f35b610903612345565b6040516109109190615397565b60405180910390f35b610933600480360381019061092e9190615275565b61234d565b60405161094091906152df565b60405180910390f35b610963600480360381019061095e9190615275565b61262d565b60405161097091906152df565b60405180910390f35b61098161290d565b60405161098e9190615397565b60405180910390f35b61099f612915565b6040516109ac9190615397565b60405180910390f35b6109bd61291d565b6040516109ca9190615397565b60405180910390f35b6109db612925565b6040516109e89190615397565b60405180910390f35b6109f961292d565b604051610a069190615397565b60405180910390f35b610a17612935565b604051610a249190615397565b60405180910390f35b610a476004803603810190610a429190615275565b61293d565b604051610a5491906152df565b60405180910390f35b610a65612c1d565b604051610a729190615397565b60405180910390f35b610a83612c25565b604051610a909190615397565b60405180910390f35b610aa1612c2d565b604051610aae9190615397565b60405180910390f35b610abf612c35565b604051610acc9190615397565b60405180910390f35b610aef6004803603810190610aea9190615275565b612c3d565b604051610afc91906152df565b60405180910390f35b610b0d612f1d565b604051610b1a9190615397565b60405180910390f35b610b3d6004803603810190610b389190615275565b612f25565b604051610b4a91906152df565b60405180910390f35b610b5b613205565b604051610b689190615397565b60405180910390f35b610b7961320d565b604051610b869190615397565b60405180910390f35b610b97613215565b604051610ba49190615397565b60405180910390f35b610bb561321d565b604051610bc29190615397565b60405180910390f35b610bd3613225565b604051610be09190615397565b60405180910390f35b610bf161322d565b604051610bfe9190615397565b60405180910390f35b610c216004803603810190610c1c9190615275565b613235565b604051610c2e91906152df565b60405180910390f35b610c3f613515565b604051610c4c9190615397565b60405180910390f35b610c5d61351d565b604051610c6a9190615397565b60405180910390f35b610c8d6004803603810190610c889190615275565b613525565b604051610c9a91906152df565b60405180910390f35b610cbd6004803603810190610cb89190615422565b613805565b604051610cca9190615397565b60405180910390f35b610cdb61381a565b604051610ce89190615397565b60405180910390f35b610cf9613822565b604051610d069190615397565b60405180910390f35b610d1761382a565b604051610d249190615397565b60405180910390f35b610d35613832565b604051610d429190615397565b60405180910390f35b610d5361383a565b604051610d609190615397565b60405180910390f35b610d836004803603810190610d7e9190615275565b613842565b604051610d9091906152df565b60405180910390f35b610da1613b22565b604051610dae9190615397565b60405180910390f35b610dbf613b2a565b604051610dcc9190615397565b60405180910390f35b610ddd613b32565b604051610dea9190615397565b60405180910390f35b610dfb613b3a565b604051610e089190615397565b60405180910390f35b610e19613b42565b604051610e269190615397565b60405180910390f35b610e496004803603810190610e449190615275565b613b4a565b604051610e5691906152df565b60405180910390f35b610e67613e2a565b604051610e749190615397565b60405180910390f35b610e85613e32565b604051610e929190615368565b60405180910390f35b610ea3613ebe565b604051610eb09190615397565b60405180910390f35b610ec1613ec6565b604051610ece9190615397565b60405180910390f35b610edf613ece565b604051610eec9190615397565b60405180910390f35b610f0f6004803603810190610f0a91906153b0565b613ed6565b604051610f1c91906152df565b60405180910390f35b610f2d61406c565b604051610f3a9190615397565b60405180910390f35b610f5d6004803603810190610f589190615275565b614074565b604051610f6a91906152df565b60405180910390f35b610f7b614354565b604051610f889190615397565b60405180910390f35b610fab6004803603810190610fa69190615275565b61435c565b604051610fb891906152df565b60405180910390f35b610fc961463c565b604051610fd69190615397565b60405180910390f35b610fe7614644565b604051610ff49190615397565b60405180910390f35b61100561464c565b6040516110129190615397565b60405180910390f35b61103560048036038101906110309190615275565b614654565b60405161104291906152df565b60405180910390f35b611053614934565b6040516110609190615397565b60405180910390f35b611083600480360381019061107e9190615275565b614958565b60405161109091906152df565b60405180910390f35b6110a1614c38565b6040516110ae9190615397565b60405180910390f35b6110bf614c40565b6040516110cc9190615397565b60405180910390f35b6110dd614c48565b6040516110ea9190615397565b60405180910390f35b6110fb614c50565b6040516111089190615397565b60405180910390f35b611119614c58565b6040516111269190615397565b60405180910390f35b611137614c60565b6040516111449190615397565b60405180910390f35b6111676004803603810190611162919061544d565b614c68565b6040516111749190615397565b60405180910390f35b611185614c88565b6040516111929190615397565b60405180910390f35b6111a3614c90565b6040516111b09190615397565b60405180910390f35b6111d360048036038101906111ce9190615275565b614c98565b6040516111e091906152df565b60405180910390f35b6111f1614ebd565b6040516111fe9190615368565b60405180910390f35b61120f614edc565b60405161121c9190615397565b60405180910390f35b61122d614ee4565b60405161123a9190615397565b60405180910390f35b61124b614eec565b6040516112589190615397565b60405180910390f35b61127b60048036038101906112769190615275565b614ef4565b60405161128891906152df565b60405180910390f35b6112996151d4565b6040516112a69190615397565b60405180910390f35b6112b76151dc565b6040516112c49190615397565b60405180910390f35b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054101561134e576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611345906154d5565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015611409576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016114009061553d565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546114559190615588565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546114a891906155bb565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546115369190615588565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161159a9190615397565b60405180910390a3600190509392505050565b5f80546115b99061561b565b80601f01602080910402602001604051908101604052809291908181526020018280546115e59061561b565b80156116305780601f1061160757610100808354040283529160200191611630565b820191905f5260205f20905b81548152906001019060200180831161161357829003601f168201915b505050505081565b5f602f905090565b5f8160055f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b9258460405161171b9190615397565b60405180910390a36001905092915050565b5f601b905090565b5f6005905090565b5f601a905090565b5f601d905090565b5f6033905090565b60035481565b5f6008905090565b5f6003905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156117ec576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016117e3906154d5565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156118a7576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161189e9061553d565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546118f39190615588565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461194691906155bb565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546119d49190615588565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051611a389190615397565b60405180910390a3600190509392505050565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015611acc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611ac3906154d5565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015611b87576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611b7e9061553d565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254611bd39190615588565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254611c2691906155bb565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254611cb49190615588565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051611d189190615397565b60405180910390a3600190509392505050565b5f6002905090565b5f6010905090565b5f6041905090565b5f6035905090565b5f602e905090565b5f602c905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015611ddc576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611dd3906154d5565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015611e97576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401611e8e9061553d565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254611ee39190615588565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254611f3691906155bb565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254611fc49190615588565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516120289190615397565b60405180910390a3600190509392505050565b5f6001905090565b5f6045905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156120cc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016120c390615695565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015612187576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161217e906156fd565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546121d39190615588565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461222691906155bb565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546122b49190615588565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516123189190615397565b60405180910390a3600190509392505050565b5f6034905090565b60025f9054906101000a900460ff1681565b5f603c905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156123ce576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016123c5906154d5565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015612489576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016124809061553d565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546124d59190615588565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461252891906155bb565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546125b69190615588565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161261a9190615397565b60405180910390a3600190509392505050565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156126ae576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016126a5906154d5565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015612769576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016127609061553d565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546127b59190615588565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461280891906155bb565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546128969190615588565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516128fa9190615397565b60405180910390a3600190509392505050565b5f6004905090565b5f600c905090565b5f6006905090565b5f601c905090565b5f6032905090565b5f6023905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156129be576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016129b5906154d5565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015612a79576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612a709061553d565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254612ac59190615588565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254612b1891906155bb565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254612ba69190615588565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051612c0a9190615397565b60405180910390a3600190509392505050565b5f6011905090565b5f6021905090565b5f601f905090565b5f6026905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015612cbe576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612cb5906154d5565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015612d79576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612d709061553d565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254612dc59190615588565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254612e1891906155bb565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254612ea69190615588565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051612f0a9190615397565b60405180910390a3600190509392505050565b5f603a905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015612fa6576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401612f9d906154d5565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015613061576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016130589061553d565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546130ad9190615588565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461310091906155bb565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461318e9190615588565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516131f29190615397565b60405180910390a3600190509392505050565b5f6009905090565b5f602a905090565b5f6014905090565b5f6025905090565b5f6013905090565b5f6043905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156132b6576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016132ad90615695565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015613371576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613368906156fd565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546133bd9190615588565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461341091906155bb565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461349e9190615588565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516135029190615397565b60405180910390a3600190509392505050565b5f600d905090565b5f6017905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156135a6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161359d906154d5565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015613661576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016136589061553d565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546136ad9190615588565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461370091906155bb565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461378e9190615588565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516137f29190615397565b60405180910390a3600190509392505050565b6004602052805f5260405f205f915090505481565b5f6016905090565b5f6039905090565b5f603b905090565b5f6036905090565b5f603f905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156138c3576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016138ba906154d5565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f2054101561397e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016139759061553d565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546139ca9190615588565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254613a1d91906155bb565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254613aab9190615588565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051613b0f9190615397565b60405180910390a3600190509392505050565b5f602b905090565b5f6037905090565b5f600a905090565b5f602d905090565b5f6030905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015613bcb576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613bc2906154d5565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015613c86576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613c7d9061553d565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254613cd29190615588565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254613d2591906155bb565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254613db39190615588565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051613e179190615397565b60405180910390a3600190509392505050565b5f600b905090565b60018054613e3f9061561b565b80601f0160208091040260200160405190810160405280929190818152602001828054613e6b9061561b565b8015613eb65780601f10613e8d57610100808354040283529160200191613eb6565b820191905f5260205f20905b815481529060010190602001808311613e9957829003601f168201915b505050505081565b5f6015905090565b5f6029905090565b5f6038905090565b5f8160045f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015613f57576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401613f4e906154d5565b60405180910390fd5b8160045f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254613fa39190615588565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254613ff691906155bb565b925050819055508273ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef8460405161405a9190615397565b60405180910390a36001905092915050565b5f6028905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156140f5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016140ec906154d5565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156141b0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016141a79061553d565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546141fc9190615588565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461424f91906155bb565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546142dd9190615588565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516143419190615397565b60405180910390a3600190509392505050565b5f6040905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156143dd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016143d4906154d5565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015614498576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161448f9061553d565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546144e49190615588565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461453791906155bb565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546145c59190615588565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516146299190615397565b60405180910390a3600190509392505050565b5f6018905090565b5f600f905090565b5f6044905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156146d5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016146cc906154d5565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015614790576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016147879061553d565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546147dc9190615588565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461482f91906155bb565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546148bd9190615588565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516149219190615397565b60405180910390a3600190509392505050565b7f000000000000000000000000000000000000000000000000000000000000000081565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205410156149d9576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016149d0906154d5565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015614a94576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401614a8b9061553d565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254614ae09190615588565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254614b3391906155bb565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254614bc19190615588565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051614c259190615397565b60405180910390a3600190509392505050565b5f6024905090565b5f601e905090565b5f6031905090565b5f6019905090565b5f6042905090565b5f6027905090565b6005602052815f5260405f20602052805f5260405f205f91509150505481565b5f603d905090565b5f6022905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015614d19576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401614d1090615695565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254614d659190615588565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254614db891906155bb565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f828254614e469190615588565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef84604051614eaa9190615397565b60405180910390a3600190509392505050565b604051806101400160405280610114815260200161571c610114913981565b5f6007905090565b5f603e905090565b5f6020905090565b5f8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015614f75576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401614f6c906154d5565b60405180910390fd5b8160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f20541015615030576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016150279061553d565b60405180910390fd5b8160045f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461507c9190615588565b925050819055508160045f8573ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f8282546150cf91906155bb565b925050819055508160055f8673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f3373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020019081526020015f205f82825461515d9190615588565b925050819055508273ffffffffffffffffffffffffffffffffffffffff168473ffffffffffffffffffffffffffffffffffffffff167fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef846040516151c19190615397565b60405180910390a3600190509392505050565b5f600e905090565b5f6012905090565b5f5ffd5b5f73ffffffffffffffffffffffffffffffffffffffff82169050919050565b5f615211826151e8565b9050919050565b61522181615207565b811461522b575f5ffd5b50565b5f8135905061523c81615218565b92915050565b5f819050919050565b61525481615242565b811461525e575f5ffd5b50565b5f8135905061526f8161524b565b92915050565b5f5f5f6060848603121561528c5761528b6151e4565b5b5f6152998682870161522e565b93505060206152aa8682870161522e565b92505060406152bb86828701615261565b9150509250925092565b5f8115159050919050565b6152d9816152c5565b82525050565b5f6020820190506152f25f8301846152d0565b92915050565b5f81519050919050565b5f82825260208201905092915050565b8281835e5f83830152505050565b5f601f19601f8301169050919050565b5f61533a826152f8565b6153448185615302565b9350615354818560208601615312565b61535d81615320565b840191505092915050565b5f6020820190508181035f8301526153808184615330565b905092915050565b61539181615242565b82525050565b5f6020820190506153aa5f830184615388565b92915050565b5f5f604083850312156153c6576153c56151e4565b5b5f6153d38582860161522e565b92505060206153e485828601615261565b9150509250929050565b5f60ff82169050919050565b615403816153ee565b82525050565b5f60208201905061541c5f8301846153fa565b92915050565b5f60208284031215615437576154366151e4565b5b5f6154448482850161522e565b91505092915050565b5f5f60408385031215615463576154626151e4565b5b5f6154708582860161522e565b92505060206154818582860161522e565b9150509250929050565b7f496e73756666696369656e742062616c616e63650000000000000000000000005f82015250565b5f6154bf601483615302565b91506154ca8261548b565b602082019050919050565b5f6020820190508181035f8301526154ec816154b3565b9050919050565b7f496e73756666696369656e7420616c6c6f77616e6365000000000000000000005f82015250565b5f615527601683615302565b9150615532826154f3565b602082019050919050565b5f6020820190508181035f8301526155548161551b565b9050919050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b5f61559282615242565b915061559d83615242565b92508282039050818111156155b5576155b461555b565b5b92915050565b5f6155c582615242565b91506155d083615242565b92508282019050808211156155e8576155e761555b565b5b92915050565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602260045260245ffd5b5f600282049050600182168061563257607f821691505b602082108103615645576156446155ee565b5b50919050565b7f41000000000000000000000000000000000000000000000000000000000000005f82015250565b5f61567f600183615302565b915061568a8261564b565b602082019050919050565b5f6020820190508181035f8301526156ac81615673565b9050919050565b7f42000000000000000000000000000000000000000000000000000000000000005f82015250565b5f6156e7600183615302565b91506156f2826156b3565b602082019050919050565b5f6020820190508181035f830152615714816156db565b905091905056fe414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141414141a26469706673582212203e477b8749988ccd0a67b1a6d43c11976c00a420dbe43a9f84158e8962430d7664736f6c634300081e0033 \ No newline at end of file diff --git a/scenarios/statebloat/contract_deploy/contract/StateBloatToken.sol b/scenarios/statebloat/contract_deploy/contract/StateBloatToken.sol index 4fb9e66d..eb7dc2dc 100644 --- a/scenarios/statebloat/contract_deploy/contract/StateBloatToken.sol +++ b/scenarios/statebloat/contract_deploy/contract/StateBloatToken.sol @@ -12,6 +12,10 @@ contract StateBloatToken { // 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, @@ -318,6 +322,23 @@ contract StateBloatToken { 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, diff --git a/scenarios/statebloat/contract_deploy/contract_deploy.go b/scenarios/statebloat/contract_deploy/contract_deploy.go index cc7e80af..4e8948b1 100644 --- a/scenarios/statebloat/contract_deploy/contract_deploy.go +++ b/scenarios/statebloat/contract_deploy/contract_deploy.go @@ -48,6 +48,14 @@ type PendingTransaction struct { PrivateKey *ecdsa.PrivateKey } +// 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 @@ -65,12 +73,21 @@ type Scenario struct { // 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: 10, - MaxWallets: 0, + MaxWallets: 1000, BaseFee: 20, TipFee: 2, ClientGroup: "default", @@ -93,10 +110,10 @@ func newScenario(logger logrus.FieldLogger) scenariotypes.Scenario { 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, "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.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 for unlimited)") + 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 } @@ -112,6 +129,8 @@ func (s *Scenario) Init(walletPool *spamoor.WalletPool, config string) error { if s.options.MaxWallets > 0 { walletPool.SetWalletCount(s.options.MaxWallets) + } else if s.options.MaxTransactions == 0 { + walletPool.SetWalletCount(1) } else { walletPool.SetWalletCount(1000) } @@ -150,7 +169,7 @@ func (s *Scenario) waitForPendingTxSlot(ctx context.Context) { // Check and clean up confirmed transactions s.processPendingTransactions(ctx) - time.Sleep(500 * time.Millisecond) + time.Sleep(1 * time.Second) } } @@ -224,35 +243,54 @@ func (s *Scenario) recordDeployedContract(contractAddress common.Address, privat s.deployedContracts = append(s.deployedContracts, deployment) - // Calculate detailed information for logging - walletAddress := crypto.PubkeyToAddress(privateKey.PublicKey) - - // Get the actual transaction to calculate real bytecode size + // Get the actual deployed contract bytecode size client := s.walletPool.GetClient(spamoor.SelectClientByIndex, 0, s.options.ClientGroup) - var bytecodeSize int = 24564 // Default fallback - var gasPerByte float64 + // TODO: This should be a constant documented on how this number is obtained. + var bytecodeSize int = 23914 if client != nil { - tx, _, err := client.GetEthClient().TransactionByHash(context.Background(), txHash) + // Get the actual deployed bytecode size using eth_getCode + contractCode, err := client.GetEthClient().CodeAt(context.Background(), contractAddress, nil) if err == nil { - bytecodeSize = len(tx.Data()) + 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") } - // Calculate gas per byte - gasPerByte = float64(receipt.GasUsed) / float64(max(bytecodeSize, 1)) + blockStat := s.blockStats[blockNumber] + blockStat.ContractCount++ + blockStat.TotalGasUsed += receipt.GasUsed + blockStat.TotalBytecodeSize += bytecodeSize - // Log with detailed information s.logger.WithFields(logrus.Fields{ - "block_number": receipt.BlockNumber.Uint64(), - "bytecode_size": bytecodeSize, - "contract_address": deployment.ContractAddress, - "gas_per_byte": fmt.Sprintf("%.2f", gasPerByte), - "gas_used": receipt.GasUsed, - "total_contracts": len(s.deployedContracts), - "tx_hash": txHash.Hex(), - "wallet_address": walletAddress.Hex(), - }).Info("Contract successfully deployed and recorded") + "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 { @@ -297,10 +335,86 @@ func (s *Scenario) saveDeploymentsMapping() error { 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 { @@ -309,16 +423,59 @@ func (s *Scenario) Run(ctx context.Context) error { s.logger.Infof("Chain ID: %s", chainID.String()) + // Calculate rate limiting based on block gas limit if max-transactions is 0 + var maxTxsPerBlock uint64 + var useRateLimiting bool + + if s.options.MaxTransactions == 0 { + // Get block gas limit from the network + client := s.walletPool.GetClient(spamoor.SelectClientByIndex, 0, s.options.ClientGroup) + if client == nil { + return fmt.Errorf("no client available for gas limit query") + } + + latestBlock, err := client.GetEthClient().BlockByNumber(ctx, nil) + if err != nil { + return fmt.Errorf("failed to get latest block: %w", err) + } + + blockGasLimit := latestBlock.GasLimit() + // TODO: This should be a constant. + estimatedGasPerContract := uint64(4949468) // Updated estimate based on contract size reduction + maxTxsPerBlock = blockGasLimit / estimatedGasPerContract + useRateLimiting = true + + s.logger.Infof("Rate limiting enabled: block gas limit %d, gas per contract %d, max txs per block %d", + blockGasLimit, estimatedGasPerContract, maxTxsPerBlock) + } + txIdxCounter := uint64(0) totalTxCount := atomic.Uint64{} + blockTxCount := uint64(0) + lastBlockTime := time.Now() for { - // Check if we've reached max transactions + // 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 maxTxsPerBlock transactions, wait for next block interval + if blockTxCount >= maxTxsPerBlock { + timeSinceLastBlock := time.Since(lastBlockTime) + if timeSinceLastBlock < 12*time.Second { // Assume ~12 second block time + sleepTime := 12*time.Second - timeSinceLastBlock + s.logger.Infof("Rate limit reached (%d txs), waiting %v for next block", maxTxsPerBlock, sleepTime) + time.Sleep(sleepTime) + } + blockTxCount = 0 + lastBlockTime = time.Now() + } + } + // Wait for available slot s.waitForPendingTxSlot(ctx) @@ -332,8 +489,9 @@ func (s *Scenario) Run(ctx context.Context) error { txIdxCounter++ totalTxCount.Add(1) + blockTxCount++ - // Process pending transactions periodically + // Process pending transactions periodically with 1 second intervals if txIdxCounter%10 == 0 { s.processPendingTransactions(ctx) @@ -348,7 +506,7 @@ func (s *Scenario) Run(ctx context.Context) error { time.Sleep(100 * time.Millisecond) } - // Wait for all pending transactions to complete + // Wait for all pending transactions to complete with 1 second intervals s.logger.Info("Waiting for remaining transactions to complete...") for { s.processPendingTransactions(ctx) @@ -362,8 +520,29 @@ func (s *Scenario) Run(ctx context.Context) error { } s.logger.Infof("Waiting for %d pending transactions...", pendingCount) - time.Sleep(2 * time.Second) + 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() @@ -527,13 +706,5 @@ func (s *Scenario) attemptTransaction(ctx context.Context, txIdx uint64, attempt s.pendingTxs[tx.Hash()] = pendingTx s.pendingTxsMutex.Unlock() - s.logger.WithFields(logrus.Fields{ - "tx_hash": tx.Hash().Hex(), - "nonce": nonce, - "base_fee_gwei": s.options.BaseFee, - "tip_fee_gwei": s.options.TipFee, - "attempt": attempt + 1, - }).Info("Transaction sent") - return nil } From 94fc7640dc4b7056a1e26e33002fca9852120bbf Mon Sep 17 00:00:00 2001 From: CPerezz Date: Fri, 13 Jun 2025 01:13:09 +0200 Subject: [PATCH 21/26] feat(contract-deploy): improve transaction handling with timestamp and timeout logic --- .../statebloat/contract_deploy/README.md | 9 ++-- .../contract_deploy/contract_deploy.go | 45 ++++++++++--------- 2 files changed, 29 insertions(+), 25 deletions(-) diff --git a/scenarios/statebloat/contract_deploy/README.md b/scenarios/statebloat/contract_deploy/README.md index 204e3dfe..26b2f56b 100644 --- a/scenarios/statebloat/contract_deploy/README.md +++ b/scenarios/statebloat/contract_deploy/README.md @@ -45,15 +45,14 @@ go build -o bin/spamoor cmd/spamoor/main.go ``` #### Key Flags -- `--max-transactions` - Number of contracts to deploy (0 = infinite, default: 0) -- `--max-pending` - Max concurrent pending transactions (default: 10) -- `--max-wallets` - Max child wallets to use (default: 1000) -- `--basefee` - Base fee per gas in gwei (default: 20) +- `--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 100 --max-pending 20 --basefee 25 --tipfee 5 + --max-transactions 0 ``` \ No newline at end of file diff --git a/scenarios/statebloat/contract_deploy/contract_deploy.go b/scenarios/statebloat/contract_deploy/contract_deploy.go index 4e8948b1..d2018956 100644 --- a/scenarios/statebloat/contract_deploy/contract_deploy.go +++ b/scenarios/statebloat/contract_deploy/contract_deploy.go @@ -46,6 +46,7 @@ type ContractDeployment struct { type PendingTransaction struct { TxHash common.Hash PrivateKey *ecdsa.PrivateKey + Timestamp time.Time } // BlockDeploymentStats tracks deployment statistics per block @@ -86,11 +87,9 @@ type Scenario struct { var ScenarioName = "contract-deploy" var ScenarioDefaultOptions = ScenarioOptions{ - MaxPending: 10, - MaxWallets: 1000, - BaseFee: 20, - TipFee: 2, - ClientGroup: "default", + 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 = scenariotypes.ScenarioDescriptor{ @@ -129,10 +128,10 @@ func (s *Scenario) Init(walletPool *spamoor.WalletPool, config string) error { if s.options.MaxWallets > 0 { walletPool.SetWalletCount(s.options.MaxWallets) - } else if s.options.MaxTransactions == 0 { - walletPool.SetWalletCount(1) } else { - walletPool.SetWalletCount(1000) + // Use only root wallet by default for better efficiency + // This avoids child wallet funding overhead + walletPool.SetWalletCount(0) } return nil @@ -185,6 +184,7 @@ func (s *Scenario) processPendingTransactions(ctx context.Context) { ethClient := client.GetEthClient() var confirmedTxs []common.Hash + var timedOutTxs []common.Hash var successfulDeployments []struct { ContractAddress common.Address PrivateKey *ecdsa.PrivateKey @@ -193,6 +193,13 @@ func (s *Scenario) processPendingTransactions(ctx context.Context) { } 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 @@ -222,6 +229,11 @@ func (s *Scenario) processPendingTransactions(ctx context.Context) { 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 @@ -607,15 +619,7 @@ func (s *Scenario) updateDynamicFees(ctx context.Context) error { // Convert base fee from wei to gwei currentBaseFeeGwei := new(big.Int).Div(latestBlock.BaseFee(), big.NewInt(1000000000)) - // Set new base fee to current base fee + 20% buffer - newBaseFeeGwei := new(big.Int).Mul(currentBaseFeeGwei, big.NewInt(120)) - newBaseFeeGwei = new(big.Int).Div(newBaseFeeGwei, big.NewInt(100)) - - // Ensure minimum increase of 5 gwei - minIncrease := big.NewInt(5) - if newBaseFeeGwei.Cmp(new(big.Int).Add(big.NewInt(int64(s.options.BaseFee)), minIncrease)) < 0 { - newBaseFeeGwei = new(big.Int).Add(big.NewInt(int64(s.options.BaseFee)), minIncrease) - } + newBaseFeeGwei := new(big.Int).Add(currentBaseFeeGwei, big.NewInt(100)) s.options.BaseFee = newBaseFeeGwei.Uint64() @@ -623,7 +627,7 @@ func (s *Scenario) updateDynamicFees(ctx context.Context) error { if s.options.TipFee+1 > 3 { s.options.TipFee = s.options.TipFee + 1 } else { - s.options.TipFee = 3 // Minimum 3 gwei tip + 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)", @@ -636,8 +640,8 @@ func (s *Scenario) updateDynamicFees(ctx context.Context) error { // 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, s.options.ClientGroup) - wallet := s.walletPool.GetWallet(spamoor.SelectWalletRoundRobin, 0) + client := s.walletPool.GetClient(spamoor.SelectClientRoundRobin, 0, "") + wallet := s.walletPool.GetRootWallet() if client == nil { return fmt.Errorf("no client available") @@ -700,6 +704,7 @@ func (s *Scenario) attemptTransaction(ctx context.Context, txIdx uint64, attempt pendingTx := &PendingTransaction{ TxHash: tx.Hash(), PrivateKey: wallet.GetPrivateKey(), + Timestamp: time.Now(), } s.pendingTxsMutex.Lock() From 139b18e0430de25cc7d83e145a047199143808e5 Mon Sep 17 00:00:00 2001 From: CPerezz Date: Wed, 18 Jun 2025 11:17:06 +0200 Subject: [PATCH 22/26] chore: gitignore update to remoive .bin & .abi --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 998622c1..a10d2501 100644 --- a/.gitignore +++ b/.gitignore @@ -5,3 +5,5 @@ bin spamoor.db* go.lib.mod go.lib.sum +*.abi +*.bin From 2b21a1111893615f91ab219026e7a3c849a4dc07 Mon Sep 17 00:00:00 2001 From: CPerezz Date: Wed, 11 Jun 2025 00:57:55 +0200 Subject: [PATCH 23/26] add(eao-delegation): Create eoa-delegation scenario oriented to bloating Revert the changes done to the original `setcodetx`. - Move the bloating code to `eoa-delegation` under statebloat. --- scenarios/scenarios.go | 7 + scenarios/statebloat/eoa_delegation/README.md | 79 ++ .../eoa_delegation/eoa_delegation.go | 1167 +++++++++++++++++ 3 files changed, 1253 insertions(+) create mode 100644 scenarios/statebloat/eoa_delegation/README.md create mode 100644 scenarios/statebloat/eoa_delegation/eoa_delegation.go diff --git a/scenarios/scenarios.go b/scenarios/scenarios.go index e0f32a82..d5a6a9a7 100644 --- a/scenarios/scenarios.go +++ b/scenarios/scenarios.go @@ -13,6 +13,10 @@ import ( "github.com/ethpandaops/spamoor/scenarios/erctx" "github.com/ethpandaops/spamoor/scenarios/gasburnertx" "github.com/ethpandaops/spamoor/scenarios/setcodetx" + contractdeploy "github.com/ethpandaops/spamoor/scenarios/statebloat/contract_deploy" + eoadelegation "github.com/ethpandaops/spamoor/scenarios/statebloat/eoa_delegation" + + //extcodesizeoverload "github.com/ethpandaops/spamoor/scenarios/statebloat/extcodesize_overload" uniswapswaps "github.com/ethpandaops/spamoor/scenarios/uniswap-swaps" "github.com/ethpandaops/spamoor/scenarios/wallets" ) @@ -30,6 +34,9 @@ var ScenarioDescriptors = []*scenariotypes.ScenarioDescriptor{ &setcodetx.ScenarioDescriptor, &uniswapswaps.ScenarioDescriptor, &wallets.ScenarioDescriptor, + &contractdeploy.ScenarioDescriptor, + &eoadelegation.ScenarioDescriptor, + //&extcodesizeoverload.ScenarioDescriptor, } func GetScenario(name string) *scenariotypes.ScenarioDescriptor { 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 +} From e36c0c26cb5b31f4e6353903a7fa49f786cd6632 Mon Sep 17 00:00:00 2001 From: CPerezz Date: Fri, 13 Jun 2025 18:34:11 +0200 Subject: [PATCH 24/26] feat(rand_sstore_bloater): add SSTOREStorageBloater contract and scenario for state bloat testing The idea is that it performs the maximum amount of SSTORE possible with the available gas limit within a single tx execution that consumes it all. --- scenarios/scenarios.go | 11 + .../statebloat/rand_sstore_bloater/README.md | 124 +++++ .../contract/SSTOREStorageBloater.go | 225 +++++++++ .../contract/SSTOREStorageBloater.sol | 45 ++ .../rand_sstore_bloater.go | 441 ++++++++++++++++++ 5 files changed, 846 insertions(+) create mode 100644 scenarios/statebloat/rand_sstore_bloater/README.md create mode 100644 scenarios/statebloat/rand_sstore_bloater/contract/SSTOREStorageBloater.go create mode 100644 scenarios/statebloat/rand_sstore_bloater/contract/SSTOREStorageBloater.sol create mode 100644 scenarios/statebloat/rand_sstore_bloater/rand_sstore_bloater.go diff --git a/scenarios/scenarios.go b/scenarios/scenarios.go index e0f32a82..b4e388ee 100644 --- a/scenarios/scenarios.go +++ b/scenarios/scenarios.go @@ -13,6 +13,12 @@ import ( "github.com/ethpandaops/spamoor/scenarios/erctx" "github.com/ethpandaops/spamoor/scenarios/gasburnertx" "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" uniswapswaps "github.com/ethpandaops/spamoor/scenarios/uniswap-swaps" "github.com/ethpandaops/spamoor/scenarios/wallets" ) @@ -28,8 +34,13 @@ var ScenarioDescriptors = []*scenariotypes.ScenarioDescriptor{ &erctx.ScenarioDescriptor, &gasburnertx.ScenarioDescriptor, &setcodetx.ScenarioDescriptor, + &randsstorebloater.ScenarioDescriptor, &uniswapswaps.ScenarioDescriptor, &wallets.ScenarioDescriptor, + &contractdeploy.ScenarioDescriptor, + &eoadelegation.ScenarioDescriptor, + //&erc20maxtransfers.ScenarioDescriptor, + //&extcodesizeoverload.ScenarioDescriptor, } func GetScenario(name string) *scenariotypes.ScenarioDescriptor { 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 +} From a5a17b08c95955e2149c523df3dc045582827190 Mon Sep 17 00:00:00 2001 From: CPerezz Date: Thu, 19 Jun 2025 00:26:36 +0200 Subject: [PATCH 25/26] fix(contract-deploy): resolve transaction stalling and improve block-based rate limiting - Set MaxPending default to 100 to fix scenario hanging at startup (was 0, preventing any transactions) - Remove hardcoded 12-second block time assumption that caused deployments only every 2 blocks - Implement proper block-based rate limiting that waits for actual block changes - Set rate limit to 2x expected throughput for better network utilization - Send transactions at expected throughput rate per block instead of arbitrary delays --- .../contract_deploy/contract_deploy.go | 64 +++++++++++-------- 1 file changed, 36 insertions(+), 28 deletions(-) diff --git a/scenarios/statebloat/contract_deploy/contract_deploy.go b/scenarios/statebloat/contract_deploy/contract_deploy.go index d2018956..3a19bfb5 100644 --- a/scenarios/statebloat/contract_deploy/contract_deploy.go +++ b/scenarios/statebloat/contract_deploy/contract_deploy.go @@ -87,9 +87,10 @@ type Scenario struct { var ScenarioName = "contract-deploy" var ScenarioDefaultOptions = ScenarioOptions{ - MaxWallets: 0, // Use root wallet only by default - BaseFee: 5, // Moderate base fee (5 gwei) - TipFee: 1, // Priority fee (1 gwei) + 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 = scenariotypes.ScenarioDescriptor{ @@ -435,36 +436,39 @@ func (s *Scenario) Run(ctx context.Context) error { 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 { - // Get block gas limit from the network - client := s.walletPool.GetClient(spamoor.SelectClientByIndex, 0, s.options.ClientGroup) - if client == nil { - return fmt.Errorf("no client available for gas limit query") - } - - latestBlock, err := client.GetEthClient().BlockByNumber(ctx, nil) - if err != nil { - return fmt.Errorf("failed to get latest block: %w", err) - } - - blockGasLimit := latestBlock.GasLimit() + blockGasLimit := currentBlock.GasLimit() // TODO: This should be a constant. estimatedGasPerContract := uint64(4949468) // Updated estimate based on contract size reduction - maxTxsPerBlock = blockGasLimit / estimatedGasPerContract + 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, max txs per block %d", - blockGasLimit, estimatedGasPerContract, maxTxsPerBlock) + 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) - lastBlockTime := time.Now() + lastBlockNumber := currentBlock.Number().Uint64() for { // Check if we've reached max transactions (if set) @@ -475,16 +479,20 @@ func (s *Scenario) Run(ctx context.Context) error { // Rate limiting logic if useRateLimiting { - // If we've sent maxTxsPerBlock transactions, wait for next block interval - if blockTxCount >= maxTxsPerBlock { - timeSinceLastBlock := time.Since(lastBlockTime) - if timeSinceLastBlock < 12*time.Second { // Assume ~12 second block time - sleepTime := 12*time.Second - timeSinceLastBlock - s.logger.Infof("Rate limit reached (%d txs), waiting %v for next block", maxTxsPerBlock, sleepTime) - time.Sleep(sleepTime) + // 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) } - blockTxCount = 0 - lastBlockTime = time.Now() } } From 8f679d78ba812897771ea4622a115107b236e439 Mon Sep 17 00:00:00 2001 From: CPerezz Date: Thu, 19 Jun 2025 00:43:08 +0200 Subject: [PATCH 26/26] fix(contract-deploy): resolve compilation errors in contract deployment scenario - Replace incorrect import 'scenariotypes' with 'scenario' package - Update ScenarioDescriptor to use correct scenario.Descriptor type - Fix Init method signature to match scenario.Scenario interface - Update wallet private key access to use GetWallet().GetPrivateKey() - Remove unused Config() method not part of the interface - Fix walletPool references in Init method --- .../contract_deploy/contract_deploy.go | 28 ++++++++----------- 1 file changed, 12 insertions(+), 16 deletions(-) diff --git a/scenarios/statebloat/contract_deploy/contract_deploy.go b/scenarios/statebloat/contract_deploy/contract_deploy.go index 3a19bfb5..4d4197ec 100644 --- a/scenarios/statebloat/contract_deploy/contract_deploy.go +++ b/scenarios/statebloat/contract_deploy/contract_deploy.go @@ -23,7 +23,7 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/ethpandaops/spamoor/scenarios/statebloat/contract_deploy/contract" - "github.com/ethpandaops/spamoor/scenariotypes" + "github.com/ethpandaops/spamoor/scenario" "github.com/ethpandaops/spamoor/spamoor" ) @@ -93,14 +93,14 @@ var ScenarioDefaultOptions = ScenarioOptions{ TipFee: 1, // Priority fee (1 gwei) MaxTransactions: 0, } -var ScenarioDescriptor = scenariotypes.ScenarioDescriptor{ +var ScenarioDescriptor = scenario.Descriptor{ Name: ScenarioName, Description: "Deploy contracts to create state bloat", DefaultOptions: ScenarioDefaultOptions, NewScenario: newScenario, } -func newScenario(logger logrus.FieldLogger) scenariotypes.Scenario { +func newScenario(logger logrus.FieldLogger) scenario.Scenario { return &Scenario{ logger: logger.WithField("scenario", ScenarioName), pendingTxs: make(map[common.Hash]*PendingTransaction), @@ -117,31 +117,27 @@ func (s *Scenario) Flags(flags *pflag.FlagSet) error { return nil } -func (s *Scenario) Init(walletPool *spamoor.WalletPool, config string) error { - s.walletPool = walletPool +func (s *Scenario) Init(options *scenario.Options) error { + s.walletPool = options.WalletPool - if config != "" { - err := yaml.Unmarshal([]byte(config), &s.options) + 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 { - walletPool.SetWalletCount(s.options.MaxWallets) + s.walletPool.SetWalletCount(s.options.MaxWallets) } else { // Use only root wallet by default for better efficiency // This avoids child wallet funding overhead - walletPool.SetWalletCount(0) + s.walletPool.SetWalletCount(0) } return nil } -func (s *Scenario) Config() string { - yamlBytes, _ := yaml.Marshal(&s.options) - return string(yamlBytes) -} // getChainID caches the chain ID to avoid repeated RPC calls func (s *Scenario) getChainID(ctx context.Context) (*big.Int, error) { @@ -665,14 +661,14 @@ func (s *Scenario) attemptTransaction(ctx context.Context, txIdx uint64, attempt } // Get current nonce for this wallet - addr := crypto.PubkeyToAddress(wallet.GetPrivateKey().PublicKey) + 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.GetPrivateKey(), chainID) + auth, err := bind.NewKeyedTransactorWithChainID(wallet.GetWallet().GetPrivateKey(), chainID) if err != nil { return fmt.Errorf("failed to create auth: %w", err) } @@ -711,7 +707,7 @@ func (s *Scenario) attemptTransaction(ctx context.Context, txIdx uint64, attempt // Track pending transaction pendingTx := &PendingTransaction{ TxHash: tx.Hash(), - PrivateKey: wallet.GetPrivateKey(), + PrivateKey: wallet.GetWallet().GetPrivateKey(), Timestamp: time.Now(), }