Auto-generated documentation.
Run a generic load test against an Eth/EVM style JSON-RPC endpoint.
polycli loadtest [flags]
The loadtest
tool is meant to generate various types of load against RPC end points. It leverages the ethclient
library Go Ethereum to interact with the blockchain.x
$ polycli wallet inspect --mnemonic "code code code code code code code code code code code quality" --addresses 1
The --mode
flag is important for this command.
t
/transaction
will perform ETH transfers. This is the simplest and cheapest transaction that can be performed.d
/deploy
will deploy the load testing contract over and over again.c
/call
will call random opcodes in our load test contract. The random function that is called will be repeatedly called in a loop based on the number of iterations from theiterations
flagf
/function
works the same way ascall
mode but instead of calling random op codes, the opcode can be specified with the-f
flag. If you want to callLOG4
you would pass-f 164
which is the opcode forLOG4
.2
/erc20
will run an ERC20 transfer test. The process initializes by minting a large amount of tokens then transferring it in small amounts. Each transaction is a single transfer.7
/erc721
will run an ERC721 mint test which will mint an NFT over and over again. Theiterations
flag here can be used to control if we are mint 1 NFT or many.i
/inc
/increment
will call the increment function repeatedly on the load test contract. It's a minimal example of a contract call that will require an update to a contract's storage.s
/store
is used to store random data in the smart contract storage. The amount of data stored per transaction is controlled with thebyte-count
flag.P
/precompiles
will randomly call the commonly implemented precompiled functions. This functions the same way ascall
mode except it's hitting precompiles rather than opcodes.p
/precompile
will call a specific precompile in a loop. This works the same way asfunction
mode except rather than specifying an opcode, you're specifying a precompile. E.g to callECRECOVER
you would pass-f 1
because it's the contract at address0x01
R
/recall
will attempt to replay all of the transactions from the previous blocks. You can use--recall-blocks
to specify how many previous blocks should be used to seed transaction history. It's expected that many of the transactions in this mode would fail.r
/random
will call any of the other modes randomly. This mode shouldn't be used in combination with other modes. Ideally this is a good way to generate a lot of random activity on a test network.rpc
is a unique mode that won't just simulate transactions, it will simulate RPC traffic (e.g. calls to get transaction receipt or filter logs). This is meant to stress test RPC servers rather than full blockchain networks. The approach is similar torecall
mode where we'll fetch some recent blocks and then use that data to generate a variety of calls to the RPC server.
The default private key is: 42b6e34dc21598a807dc19d7784c71b2a7a01f6480dc6f58258f78e539f1a1fa
. We can use wallet inspect
to get more information about this address, in particular its ETHAddress
if you want to check balance or pre-mine value for this particular account.
Here is a simple example that runs 1000 requests at a max rate of 1 request per second against the http rpc endpoint on localhost. It's running in transaction mode so it will perform simple transactions send to the default address.
$ polycli loadtest --verbosity 700 --chain-id 1256 --concurrency 1 --requests 1000 --rate-limit 1 --mode t --rpc-url http://localhost:8888
Another example, a bit slower, and that specifically calls the LOG4 function in the load test contract in a loop for 25,078 iterations. That number was picked specifically to require almost all of the gas for a single transaction.
$ polycli loadtest --verbosity 700 --chain-id 1256 --concurrency 1 --requests 50 --rate-limit 0.5 --mode f --function 164 --iterations 25078 --rpc-url http://private.validator-001.devnet02.pos-v3.polygon.private:8545
The codebase has a contract that used for load testing. It's written in Solidity. The workflow for modifying this contract is.
- Make changes to file:contracts/LoadTester.sol
- Compile the contracts:
$ solc LoadTester.sol --bin --abi -o . --overwrite
- Run
abigen
$ abigen --abi LoadTester.abi --pkg contracts --type LoadTester --bin LoadTester.bin --out loadtester.go
- Run the loadtester to enure it deploys and runs successfully
$ polycli loadtest --verbosity 700 --rpc-url http://127.0.0.1:8541
--adaptive-backoff-factor float When using adaptive rate limiting, this flag controls our multiplicative decrease value. (default 2)
--adaptive-cycle-duration-seconds uint When using adaptive rate limiting, this flag controls how often we check the queue size and adjust the rates (default 10)
--adaptive-rate-limit Enable AIMD-style congestion control to automatically adjust request rate
--adaptive-rate-limit-increment uint When using adaptive rate limiting, this flag controls the size of the additive increases. (default 50)
--batch-size uint Number of batches to perform at a time for receipt fetching. Default is 999 requests at a time. (default 999)
--blob-fee-cap uint The blob fee cap, or the maximum blob fee per chunk, in Gwei. (default 100000)
-b, --byte-count uint If we're in store mode, this controls how many bytes we'll try to store in our contract (default 1024)
--call-only When using this mode, rather than sending a transaction, we'll just call. This mode is incompatible with adaptive rate limiting, summarization, and a few other features.
--call-only-latest When using call only mode with recall, should we execute on the latest block or on the original block
--calldata string The hex encoded calldata passed in. The format is function signature + arguments encoded together. This must be paired up with --mode contract-call and --contract-address
--chain-id uint The chain id for the transactions.
-c, --concurrency int Number of requests to perform concurrently. Default is one request at a time. (default 1)
--contract-address string The address of the contract that will be used in --mode contract-call. This must be paired up with --mode contract-call and --calldata
--contract-call-payable Use this flag if the function is payable, the value amount passed will be from --eth-amount. This must be paired up with --mode contract-call and --contract-address
--erc20-address string The address of a pre-deployed ERC20 contract
--erc721-address string The address of a pre-deployed ERC721 contract
--eth-amount float The amount of ether to send on every transaction (default 0.001)
--force-contract-deploy Some load test modes don't require a contract deployment. Set this flag to true to force contract deployments. This will still respect the --lt-address flags.
-f, --function uint A specific function to be called if running with --mode f or a specific precompiled contract when running with --mode a (default 1)
--function-arg strings The arguments that will be passed to a contract function call. This must be paired up with "--mode contract-call" and "--contract-address". Args can be passed multiple times: "--function-arg 'test' --function-arg 999" or comma separated values "--function-arg "test",9". The ordering of the arguments must match the ordering of the function parameters.
--function-signature string The contract's function signature that will be called. The format is '<function name>(<types...>)'. This must be paired up with '--mode contract-call' and '--contract-address'. If the function requires parameters you can pass them with '--function-arg <value>'.
--gas-limit uint In environments where the gas limit can't be computed on the fly, we can specify it manually. This can also be used to avoid eth_estimateGas
--gas-price uint In environments where the gas price can't be determined automatically, we can specify it manually
-h, --help help for loadtest
--inscription-content string The inscription content that will be encoded as calldata. This must be paired up with --mode inscription (default "data:,{\"p\":\"erc-20\",\"op\":\"mint\",\"tick\":\"TEST\",\"amt\":\"1\"}")
-i, --iterations uint If we're making contract calls, this controls how many times the contract will execute the instruction in a loop. If we are making ERC721 Mints, this indicates the minting batch size (default 1)
--legacy Send a legacy transaction instead of an EIP1559 transaction.
--lt-address string The address of a pre-deployed load test contract
-m, --mode strings The testing mode to use. It can be multiple like: "c,d,f,t"
2, erc20 - Send ERC20 tokens
7, erc721 - Mint ERC721 tokens
b, blob - Send blob transactions
c, call - Call random contract functions
cc, contract-call - Make contract calls
d, deploy - Deploy contracts
f, function - Call random contract functions
i, inscription - Send inscription transactions
inc, increment - Increment a counter
pr, random-precompile - Call random precompiled contracts
px, specific-precompile - Call specific precompiled contracts
r, random - Random modes (does not include the following modes: blob, call, inscription, recall, rpc, uniswapv3)
R, recall - Replay or simulate transactions
rpc - Call random rpc methods
s, store - Store bytes in a dynamic byte array
t, transaction - Send transactions
v3, uniswapv3 - Perform UniswapV3 swaps (default [t])
--nonce uint Use this flag to manually set the starting nonce
--output-mode string Format mode for summary output (json | text) (default "text")
--priority-gas-price uint Specify Gas Tip Price in the case of EIP-1559
--private-key string The hex encoded private key that we'll use to send transactions (default "42b6e34dc21598a807dc19d7784c71b2a7a01f6480dc6f58258f78e539f1a1fa")
--rate-limit float An overall limit to the number of requests per second. Give a number less than zero to remove this limit all together (default 4)
--recall-blocks uint The number of blocks that we'll attempt to fetch for recall (default 50)
-n, --requests int Number of requests to perform for the benchmarking session. The default is to just perform a single request which usually leads to non-representative benchmarking results. (default 1)
-r, --rpc-url string The RPC endpoint url (default "http://localhost:8545")
--seed int A seed for generating random values and addresses (default 123456)
--send-only Send transactions and load without waiting for it to be mined.
--steady-state-tx-pool-size uint When using adaptive rate limiting, this value sets the target queue size. If the queue is smaller than this value, we'll speed up. If the queue is smaller than this value, we'll back off. (default 1000)
--summarize Should we produce an execution summary after the load test has finished. If you're running a large load test, this can take a long time
-t, --time-limit int Maximum number of seconds to spend for benchmarking. Use this to benchmark within a fixed total amount of time. Per default there is no time limit. (default -1)
--to-address string The address that we're going to send to (default "0xDEADBEEFDEADBEEFDEADBEEFDEADBEEFDEADBEEF")
--to-random When doing a transfer test, should we send to random addresses rather than DEADBEEFx5
The command also inherits flags from parent commands.
--config string config file (default is $HOME/.polygon-cli.yaml)
--pretty-logs Should logs be in pretty format or JSON (default true)
-v, --verbosity int 0 - Silent
100 Panic
200 Fatal
300 Error
400 Warning
500 Info
600 Debug
700 Trace (default 500)
- polycli - A Swiss Army knife of blockchain tools.
- polycli loadtest uniswapv3 - Run Uniswapv3-like load test against an Eth/EVm style JSON-RPC endpoint.