forked from cerc-io/laconicd-deprecated
b1cd16e5bf
* Problem: feemarket's query cli has redundant height parameter Soluton: - remove the positional height parameter, since there's a flag already. Update CHANGELOG.md * Apply feemarket to native cosmos tx - add tx extension option for user to input tip price - apply feemarket's base fee to native tx comments and cleanup fallback to default sdk logic when london hardfork not enabled integration test cleanup feemarket query cli commands Update CHANGELOG.md update unit tests disable feemarket in simulation tests for now fix lint Update app/simulation_test.go fix python lint fix lint Update x/evm/types/extension_option.go Co-authored-by: Federico Kunze Küllmer <31522760+fedekunze@users.noreply.github.com> address review suggestions * fix unit tests * fix integration test * improve unit test coverage * fix go lint * refactor * fix integration test * fix simulation tests * fix go linter Co-authored-by: Federico Kunze Küllmer <31522760+fedekunze@users.noreply.github.com>
198 lines
6.6 KiB
Python
198 lines
6.6 KiB
Python
import sys
|
|
|
|
from .network import Ethermint
|
|
from .utils import ADDRS, KEYS, eth_to_bech32, sign_transaction, wait_for_new_blocks
|
|
|
|
PRIORITY_REDUCTION = 1000000
|
|
|
|
|
|
def effective_gas_price(tx, base_fee):
|
|
if "maxFeePerGas" in tx:
|
|
# dynamic fee tx
|
|
return min(base_fee + tx["maxPriorityFeePerGas"], tx["maxFeePerGas"])
|
|
else:
|
|
# legacy tx
|
|
return tx["gasPrice"]
|
|
|
|
|
|
def tx_priority(tx, base_fee):
|
|
if "maxFeePerGas" in tx:
|
|
# dynamic fee tx
|
|
return (
|
|
min(tx["maxPriorityFeePerGas"], tx["maxFeePerGas"] - base_fee)
|
|
// PRIORITY_REDUCTION
|
|
)
|
|
else:
|
|
# legacy tx
|
|
return (tx["gasPrice"] - base_fee) // PRIORITY_REDUCTION
|
|
|
|
|
|
def test_priority(ethermint: Ethermint):
|
|
"""
|
|
test priorities of different tx types
|
|
"""
|
|
w3 = ethermint.w3
|
|
amount = 10000
|
|
base_fee = w3.eth.get_block("latest").baseFeePerGas
|
|
|
|
# [ ( sender, tx ), ... ]
|
|
# use different senders to avoid nonce conflicts
|
|
test_cases = [
|
|
(
|
|
"validator",
|
|
{
|
|
"to": "0x0000000000000000000000000000000000000000",
|
|
"value": amount,
|
|
"gas": 21000,
|
|
"maxFeePerGas": base_fee + PRIORITY_REDUCTION * 6,
|
|
"maxPriorityFeePerGas": 0,
|
|
},
|
|
),
|
|
(
|
|
"community",
|
|
{
|
|
"to": "0x0000000000000000000000000000000000000000",
|
|
"value": amount,
|
|
"gas": 21000,
|
|
"gasPrice": base_fee + PRIORITY_REDUCTION * 2,
|
|
},
|
|
),
|
|
(
|
|
"signer2",
|
|
{
|
|
"to": "0x0000000000000000000000000000000000000000",
|
|
"value": amount,
|
|
"gasPrice": base_fee + PRIORITY_REDUCTION * 4,
|
|
"accessList": [
|
|
{
|
|
"address": "0xde0b295669a9fd93d5f28d9ec85e40f4cb697bae",
|
|
"storageKeys": (
|
|
"0x00000000000000000000000000000000000000000000000000000000"
|
|
"00000003",
|
|
"0x00000000000000000000000000000000000000000000000000000000"
|
|
"00000007",
|
|
),
|
|
}
|
|
],
|
|
},
|
|
),
|
|
(
|
|
"signer1",
|
|
{
|
|
"to": "0x0000000000000000000000000000000000000000",
|
|
"value": amount,
|
|
"gas": 21000,
|
|
"maxFeePerGas": base_fee + PRIORITY_REDUCTION * 6,
|
|
"maxPriorityFeePerGas": PRIORITY_REDUCTION * 6,
|
|
},
|
|
),
|
|
]
|
|
|
|
# test cases are ordered by priority
|
|
priorities = [tx_priority(tx, base_fee) for _, tx in test_cases]
|
|
assert all(a < b for a, b in zip(priorities, priorities[1:]))
|
|
|
|
signed = [sign_transaction(w3, tx, key=KEYS[sender]) for sender, tx in test_cases]
|
|
# send the txs from low priority to high,
|
|
# but the later sent txs should be included earlier.
|
|
txhashes = [w3.eth.send_raw_transaction(tx.rawTransaction) for tx in signed]
|
|
|
|
receipts = [w3.eth.wait_for_transaction_receipt(txhash) for txhash in txhashes]
|
|
print(receipts)
|
|
assert all(receipt.status == 1 for receipt in receipts), "expect all txs success"
|
|
|
|
# the later txs should be included earlier because of higher priority
|
|
# FIXME there's some non-deterministics due to mempool logic
|
|
tx_indexes = [(r.blockNumber, r.transactionIndex) for r in receipts]
|
|
print(tx_indexes)
|
|
# the first sent tx are included later, because of lower priority
|
|
assert all(i1 > i2 for i1, i2 in zip(tx_indexes, tx_indexes[1:]))
|
|
|
|
|
|
def included_earlier(receipt1, receipt2):
|
|
"returns true if receipt1 is included earlier than receipt2"
|
|
return (receipt1.blockNumber, receipt1.transactionIndex) < (
|
|
receipt2.blockNumber,
|
|
receipt2.transactionIndex,
|
|
)
|
|
|
|
|
|
def test_native_tx_priority(ethermint: Ethermint):
|
|
cli = ethermint.cosmos_cli()
|
|
base_fee = cli.query_base_fee()
|
|
print("base_fee", base_fee)
|
|
test_cases = [
|
|
{
|
|
"from": eth_to_bech32(ADDRS["community"]),
|
|
"to": eth_to_bech32(ADDRS["validator"]),
|
|
"amount": "1000aphoton",
|
|
"gas_prices": f"{base_fee + PRIORITY_REDUCTION * 6}aphoton",
|
|
"max_priority_price": 0,
|
|
},
|
|
{
|
|
"from": eth_to_bech32(ADDRS["signer1"]),
|
|
"to": eth_to_bech32(ADDRS["signer2"]),
|
|
"amount": "1000aphoton",
|
|
"gas_prices": f"{base_fee + PRIORITY_REDUCTION * 6}aphoton",
|
|
"max_priority_price": PRIORITY_REDUCTION * 2,
|
|
},
|
|
{
|
|
"from": eth_to_bech32(ADDRS["signer2"]),
|
|
"to": eth_to_bech32(ADDRS["signer1"]),
|
|
"amount": "1000aphoton",
|
|
"gas_prices": f"{base_fee + PRIORITY_REDUCTION * 4}aphoton",
|
|
"max_priority_price": PRIORITY_REDUCTION * 4,
|
|
},
|
|
{
|
|
"from": eth_to_bech32(ADDRS["validator"]),
|
|
"to": eth_to_bech32(ADDRS["community"]),
|
|
"amount": "1000aphoton",
|
|
"gas_prices": f"{base_fee + PRIORITY_REDUCTION * 6}aphoton",
|
|
"max_priority_price": None, # no extension, maximum tipFeeCap
|
|
},
|
|
]
|
|
txs = []
|
|
expect_priorities = []
|
|
for tc in test_cases:
|
|
tx = cli.transfer(
|
|
tc["from"],
|
|
tc["to"],
|
|
tc["amount"],
|
|
gas_prices=tc["gas_prices"],
|
|
generate_only=True,
|
|
)
|
|
txs.append(
|
|
cli.sign_tx_json(
|
|
tx, tc["from"], max_priority_price=tc.get("max_priority_price")
|
|
)
|
|
)
|
|
gas_price = int(tc["gas_prices"].removesuffix("aphoton"))
|
|
expect_priorities.append(
|
|
min(
|
|
get_max_priority_price(tc.get("max_priority_price")),
|
|
gas_price - base_fee,
|
|
)
|
|
// PRIORITY_REDUCTION
|
|
)
|
|
assert expect_priorities == [0, 2, 4, 6]
|
|
|
|
txhashes = []
|
|
for tx in txs:
|
|
rsp = cli.broadcast_tx_json(tx, broadcast_mode="sync")
|
|
assert rsp["code"] == 0, rsp["raw_log"]
|
|
txhashes.append(rsp["txhash"])
|
|
|
|
print("wait for two new blocks, so the sent txs are all included")
|
|
wait_for_new_blocks(cli, 2)
|
|
|
|
tx_results = [cli.tx_search_rpc(f"tx.hash='{txhash}'")[0] for txhash in txhashes]
|
|
tx_indexes = [(int(r["height"]), r["index"]) for r in tx_results]
|
|
print(tx_indexes)
|
|
# the first sent tx are included later, because of lower priority
|
|
assert all(i1 > i2 for i1, i2 in zip(tx_indexes, tx_indexes[1:]))
|
|
|
|
|
|
def get_max_priority_price(max_priority_price):
|
|
"default to max int64 if None"
|
|
return max_priority_price if max_priority_price is not None else sys.maxsize
|