diff --git a/CHANGELOG.md b/CHANGELOG.md index d2182d2dec..58a32e4ec7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -35,6 +35,10 @@ Ref: https://keepachangelog.com/en/1.0.0/ # Changelog +## Unreleased + +* (evm) [#725](https://github.com/crypto-org-chain/ethermint/pull/725) feat(RPC): add authorizationList from eth_getTransactionByHash response for EIP-7702 transactions + ## [v0.22.0] - 2025-08-12 * (geth) [#665](https://github.com/crypto-org-chain/ethermint/pull/665) Update go-ethereum version to [`v1.15.11`](https://github.com/ethereum/go-ethereum/releases/tag/v1.15.11). diff --git a/rpc/backend/tx_info_test.go b/rpc/backend/tx_info_test.go index afb8aa36c5..4b429dfdae 100644 --- a/rpc/backend/tx_info_test.go +++ b/rpc/backend/tx_info_test.go @@ -12,11 +12,13 @@ import ( dbm "github.com/cosmos/cosmos-db" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/common/hexutil" + ethtypes "github.com/ethereum/go-ethereum/core/types" "github.com/evmos/ethermint/indexer" "github.com/evmos/ethermint/rpc/backend/mocks" rpctypes "github.com/evmos/ethermint/rpc/types" ethermint "github.com/evmos/ethermint/types" evmtypes "github.com/evmos/ethermint/x/evm/types" + "github.com/holiman/uint256" "google.golang.org/grpc/metadata" ) @@ -648,3 +650,114 @@ func (suite *BackendTestSuite) TestGetGasUsed() { }) } } + +func (suite *BackendTestSuite) TestGetTransactionByHash_SetCodeTxType() { + msgSetCodeTx := suite.buildSetCodeTx() + txBz := suite.signAndEncodeEthTx(msgSetCodeTx) + txHash := msgSetCodeTx.Hash() + block := &types.Block{Header: types.Header{Height: 1, ChainID: "test"}, Data: types.Data{Txs: []types.Tx{txBz}}} + responseDeliver := []*abci.ExecTxResult{ + { + Code: 0, + Events: []abci.Event{ + {Type: evmtypes.EventTypeEthereumTx, Attributes: []abci.EventAttribute{ + {Key: "ethereumTxHash", Value: txHash.Hex()}, + {Key: "txIndex", Value: "0"}, + {Key: "amount", Value: "0"}, + {Key: "txGasUsed", Value: "100000"}, + {Key: "txHash", Value: ""}, + {Key: "recipient", Value: "0x742d35cc6561c9d8f6b1b8e6e2c8b9f8f4a1e2d3"}, + }}, + }, + }, + } + + expectedRPCTx, _ := rpctypes.NewRPCTransaction(msgSetCodeTx, common.Hash{}, 0, 0, big.NewInt(1), suite.backend.chainID) + + testCases := []struct { + name string + registerMock func() + expPass bool + }{ + { + "pass - SetCodeTx transaction found and returned", + func() { + client := suite.backend.clientCtx.Client.(*mocks.Client) + queryClient := suite.backend.queryClient.QueryClient.(*mocks.EVMQueryClient) + RegisterBlock(client, 1, txBz) + RegisterBlockResults(client, 1) + RegisterBaseFee(queryClient, sdkmath.NewInt(1)) + }, + true, + }, + } + + for _, tc := range testCases { + suite.Run(tc.name, func() { + suite.SetupTest() + tc.registerMock() + + db := dbm.NewMemDB() + suite.backend.indexer = indexer.NewKVIndexer(db, tmlog.NewNopLogger(), suite.backend.clientCtx) + err := suite.backend.indexer.IndexBlock(block, responseDeliver) + suite.Require().NoError(err) + + rpcTx, err := suite.backend.GetTransactionByHash(txHash) + + if tc.expPass { + suite.Require().NoError(err) + suite.Require().NotNil(rpcTx) + + suite.Require().Equal(hexutil.Uint64(ethtypes.SetCodeTxType), rpcTx.Type) + + suite.Require().NotNil(rpcTx.GasFeeCap, "GasFeeCap should be set") + suite.Require().NotNil(rpcTx.GasTipCap, "GasTipCap should be set") + suite.Require().NotNil(rpcTx.ChainID, "ChainID should be set") + suite.Require().NotNil(rpcTx.Accesses, "AccessList should be set") + suite.Require().NotNil(rpcTx.AuthorizationList, "AuthorizationList should be set") + + suite.Require().Equal(expectedRPCTx.Type, rpcTx.Type) + suite.Require().Equal(expectedRPCTx.From, rpcTx.From) + suite.Require().Equal(expectedRPCTx.Hash, rpcTx.Hash) + } else { + suite.Require().Error(err) + } + }) + } +} + +func (suite *BackendTestSuite) buildSetCodeTx() *evmtypes.MsgEthereumTx { + auth := ethtypes.SetCodeAuthorization{ + ChainID: *uint256.MustFromBig(suite.backend.chainID), + Address: common.HexToAddress("0x4Cd241E8d1510e30b2076397afc7508Ae59C66c9"), + Nonce: 1, + V: uint8(27), + R: *uint256.NewInt(1), + S: *uint256.NewInt(1), + } + + setCodeTx := ðtypes.SetCodeTx{ + ChainID: uint256.MustFromBig(suite.backend.chainID), + Nonce: 0, + GasTipCap: uint256.NewInt(10000), + GasFeeCap: uint256.NewInt(1000000000000), + Gas: 100000, + To: common.HexToAddress("0x742d35cc6561c9d8f6b1b8e6e2c8b9f8f4a1e2d3"), + Value: uint256.NewInt(0), + Data: []byte{}, + AccessList: ethtypes.AccessList{}, + AuthList: []ethtypes.SetCodeAuthorization{auth}, + V: uint256.NewInt(1), + R: uint256.NewInt(1), + S: uint256.NewInt(1), + } + + ethTx := ethtypes.NewTx(setCodeTx) + msgEthereumTx := &evmtypes.MsgEthereumTx{} + err := msgEthereumTx.FromSignedEthereumTx(ethTx, ethtypes.LatestSignerForChainID(suite.backend.chainID)) + suite.Require().NoError(err) + + msgEthereumTx.From = suite.signerAddress + + return msgEthereumTx +} diff --git a/rpc/types/types.go b/rpc/types/types.go index 8519298064..f7c5dae0f5 100644 --- a/rpc/types/types.go +++ b/rpc/types/types.go @@ -53,25 +53,27 @@ type StorageResult struct { // RPCTransaction represents a transaction that will serialize to the RPC representation of a transaction type RPCTransaction struct { - BlockHash *common.Hash `json:"blockHash"` - BlockNumber *hexutil.Big `json:"blockNumber"` - From common.Address `json:"from"` - Gas hexutil.Uint64 `json:"gas"` - GasPrice *hexutil.Big `json:"gasPrice"` - GasFeeCap *hexutil.Big `json:"maxFeePerGas,omitempty"` - GasTipCap *hexutil.Big `json:"maxPriorityFeePerGas,omitempty"` - Hash common.Hash `json:"hash"` - Input hexutil.Bytes `json:"input"` - Nonce hexutil.Uint64 `json:"nonce"` - To *common.Address `json:"to"` - TransactionIndex *hexutil.Uint64 `json:"transactionIndex"` - Value *hexutil.Big `json:"value"` - Type hexutil.Uint64 `json:"type"` - Accesses *ethtypes.AccessList `json:"accessList,omitempty"` - ChainID *hexutil.Big `json:"chainId,omitempty"` - V *hexutil.Big `json:"v"` - R *hexutil.Big `json:"r"` - S *hexutil.Big `json:"s"` + BlockHash *common.Hash `json:"blockHash"` + BlockNumber *hexutil.Big `json:"blockNumber"` + From common.Address `json:"from"` + Gas hexutil.Uint64 `json:"gas"` + GasPrice *hexutil.Big `json:"gasPrice"` + GasFeeCap *hexutil.Big `json:"maxFeePerGas,omitempty"` + GasTipCap *hexutil.Big `json:"maxPriorityFeePerGas,omitempty"` + Hash common.Hash `json:"hash"` + Input hexutil.Bytes `json:"input"` + Nonce hexutil.Uint64 `json:"nonce"` + To *common.Address `json:"to"` + TransactionIndex *hexutil.Uint64 `json:"transactionIndex"` + Value *hexutil.Big `json:"value"` + Type hexutil.Uint64 `json:"type"` + Accesses *ethtypes.AccessList `json:"accessList,omitempty"` + ChainID *hexutil.Big `json:"chainId,omitempty"` + AuthorizationList []ethtypes.SetCodeAuthorization `json:"authorizationList,omitempty"` + V *hexutil.Big `json:"v"` + R *hexutil.Big `json:"r"` + S *hexutil.Big `json:"s"` + YParity *hexutil.Uint64 `json:"yParity,omitempty"` } // StateOverride is the collection of overridden accounts. diff --git a/rpc/types/utils.go b/rpc/types/utils.go index 33971a99f7..6e7ffddd38 100644 --- a/rpc/types/utils.go +++ b/rpc/types/utils.go @@ -240,25 +240,42 @@ func NewRPCTransaction( result.BlockNumber = (*hexutil.Big)(new(big.Int).SetUint64(blockNumber)) result.TransactionIndex = (*hexutil.Uint64)(&index) } + yparity := hexutil.Uint64(v.Sign()) //#nosec G115 switch tx.Type() { case ethtypes.AccessListTxType: al := tx.AccessList() result.Accesses = &al result.ChainID = (*hexutil.Big)(tx.ChainId()) + result.YParity = &yparity case ethtypes.DynamicFeeTxType: al := tx.AccessList() result.Accesses = &al result.ChainID = (*hexutil.Big)(tx.ChainId()) + result.YParity = &yparity result.GasFeeCap = (*hexutil.Big)(tx.GasFeeCap()) result.GasTipCap = (*hexutil.Big)(tx.GasTipCap()) // if the transaction has been mined, compute the effective gas price if baseFee != nil && blockHash != (common.Hash{}) { - // price = min(tip, gasFeeCap - baseFee) + baseFee + // price = min(tip + baseFee, gasFeeCap) price := ethermint.BigMin(new(big.Int).Add(tx.GasTipCap(), baseFee), tx.GasFeeCap()) result.GasPrice = (*hexutil.Big)(price) } else { result.GasPrice = (*hexutil.Big)(tx.GasFeeCap()) } + case ethtypes.SetCodeTxType: + al := tx.AccessList() + result.Accesses = &al + result.ChainID = (*hexutil.Big)(tx.ChainId()) + result.YParity = &yparity + result.GasFeeCap = (*hexutil.Big)(tx.GasFeeCap()) + result.GasTipCap = (*hexutil.Big)(tx.GasTipCap()) + if baseFee != nil && blockHash != (common.Hash{}) { + price := ethermint.BigMin(new(big.Int).Add(tx.GasTipCap(), baseFee), tx.GasFeeCap()) + result.GasPrice = (*hexutil.Big)(price) + } else { + result.GasPrice = (*hexutil.Big)(tx.GasFeeCap()) + } + result.AuthorizationList = tx.SetCodeAuthorizations() } return result, nil } diff --git a/rpc/types/utils_test.go b/rpc/types/utils_test.go new file mode 100644 index 0000000000..648fe14028 --- /dev/null +++ b/rpc/types/utils_test.go @@ -0,0 +1,289 @@ +package types + +import ( + "math/big" + "testing" + + "github.com/cosmos/cosmos-sdk/crypto/keyring" + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + ethtypes "github.com/ethereum/go-ethereum/core/types" + "github.com/evmos/ethermint/crypto/ethsecp256k1" + "github.com/evmos/ethermint/tests" + evmtypes "github.com/evmos/ethermint/x/evm/types" + "github.com/holiman/uint256" + "github.com/stretchr/testify/require" +) + +var ( + testChainID = big.NewInt(9000) + testAddress = common.HexToAddress("0x1234567890123456789012345678901234567890") + testBlockHash = common.HexToHash("0xa9d32b77fbfe2f9310b9eb8a29138b95ca3da6b04a4432e1d14c360644a9b8c7") + testSigner keyring.Signer + testFromAddr common.Address +) + +func init() { + privKey, _ := ethsecp256k1.GenerateKey() + testSigner = tests.NewSigner(privKey) + testFromAddr = common.BytesToAddress(privKey.PubKey().Address().Bytes()) +} + +func buildLegacyTx(t *testing.T) *evmtypes.MsgEthereumTx { + tx := evmtypes.NewTx( + testChainID, + 0, + &testAddress, + big.NewInt(1000), + 100000, + big.NewInt(1000000000), + nil, + nil, + nil, + nil, + ) + tx.From = testFromAddr.Bytes() + + err := tx.Sign(ethtypes.LatestSignerForChainID(testChainID), testSigner) + require.NoError(t, err) + + return tx +} + +func buildDynamicFeeTx(t *testing.T) *evmtypes.MsgEthereumTx { + tx := evmtypes.NewTx( + testChainID, + 1, + &testAddress, + big.NewInt(2000), + 120000, + nil, + big.NewInt(2000000000), + big.NewInt(1000000000), + []byte("test data"), + ðtypes.AccessList{}, + ) + tx.From = testFromAddr.Bytes() + + err := tx.Sign(ethtypes.LatestSignerForChainID(testChainID), testSigner) + require.NoError(t, err) + + return tx +} + +func buildSetCodeTx(t *testing.T) *evmtypes.MsgEthereumTx { + auth := ethtypes.SetCodeAuthorization{ + ChainID: *uint256.MustFromBig(testChainID), + Address: testAddress, + Nonce: 1, + V: uint8(27), + R: *uint256.NewInt(1), + S: *uint256.NewInt(1), + } + + setCodeTx := ðtypes.SetCodeTx{ + ChainID: uint256.MustFromBig(testChainID), + Nonce: 2, + GasTipCap: uint256.NewInt(1000000000), + GasFeeCap: uint256.NewInt(2000000000), + Gas: 100000, + To: testAddress, + Value: uint256.NewInt(3000), + Data: []byte("setcode data"), + AccessList: ethtypes.AccessList{}, + AuthList: []ethtypes.SetCodeAuthorization{auth}, + V: uint256.NewInt(1), + R: uint256.NewInt(1), + S: uint256.NewInt(1), + } + + ethTx := ethtypes.NewTx(setCodeTx) + msgEthereumTx := &evmtypes.MsgEthereumTx{} + err := msgEthereumTx.FromSignedEthereumTx(ethTx, ethtypes.LatestSignerForChainID(testChainID)) + require.NoError(t, err) + + msgEthereumTx.From = testFromAddr.Bytes() + return msgEthereumTx +} + +func TestNewRPCTransaction(t *testing.T) { + testCases := []struct { + name string + setupTx func() *evmtypes.MsgEthereumTx + blockHash common.Hash + blockNumber uint64 + index uint64 + baseFee *big.Int + chainID *big.Int + expectError bool + validateResult func(t *testing.T, result *RPCTransaction) + }{ + { + name: "Legacy transaction - pending", + setupTx: func() *evmtypes.MsgEthereumTx { return buildLegacyTx(t) }, + blockHash: common.Hash{}, + blockNumber: 0, + index: 0, + baseFee: nil, + chainID: testChainID, + expectError: false, + validateResult: func(t *testing.T, result *RPCTransaction) { + require.Equal(t, hexutil.Uint64(ethtypes.LegacyTxType), result.Type) + require.Equal(t, testFromAddr, result.From) + require.Equal(t, &testAddress, result.To) + require.Equal(t, (*hexutil.Big)(big.NewInt(1000)), result.Value) + require.Equal(t, hexutil.Uint64(100000), result.Gas) + require.Equal(t, (*hexutil.Big)(big.NewInt(1000000000)), result.GasPrice) + require.Nil(t, result.BlockHash) + require.Nil(t, result.BlockNumber) + require.Nil(t, result.TransactionIndex) + require.Nil(t, result.Accesses) + require.Nil(t, result.GasFeeCap) + require.Nil(t, result.GasTipCap) + }, + }, + { + name: "Legacy transaction - mined", + setupTx: func() *evmtypes.MsgEthereumTx { return buildLegacyTx(t) }, + blockHash: testBlockHash, + blockNumber: 100, + index: 5, + baseFee: big.NewInt(500000000), + chainID: testChainID, + expectError: false, + validateResult: func(t *testing.T, result *RPCTransaction) { + require.Equal(t, hexutil.Uint64(ethtypes.LegacyTxType), result.Type) + require.Equal(t, &testBlockHash, result.BlockHash) + require.Equal(t, (*hexutil.Big)(big.NewInt(100)), result.BlockNumber) + idx := hexutil.Uint64(5) + require.Equal(t, &idx, result.TransactionIndex) + }, + }, + { + name: "Dynamic fee transaction - pending", + setupTx: func() *evmtypes.MsgEthereumTx { return buildDynamicFeeTx(t) }, + blockHash: common.Hash{}, + blockNumber: 0, + index: 0, + baseFee: nil, + chainID: testChainID, + expectError: false, + validateResult: func(t *testing.T, result *RPCTransaction) { + require.Equal(t, hexutil.Uint64(ethtypes.DynamicFeeTxType), result.Type) + require.Equal(t, testFromAddr, result.From) + require.Equal(t, &testAddress, result.To) + require.Equal(t, (*hexutil.Big)(big.NewInt(2000)), result.Value) + require.Equal(t, hexutil.Uint64(120000), result.Gas) + require.Equal(t, (*hexutil.Big)(big.NewInt(2000000000)), result.GasFeeCap) + require.Equal(t, (*hexutil.Big)(big.NewInt(1000000000)), result.GasTipCap) + require.NotNil(t, result.Accesses) + require.NotNil(t, result.YParity) + require.Equal(t, hexutil.Bytes([]byte("test data")), result.Input) + }, + }, + { + name: "Dynamic fee transaction - mined with baseFee", + setupTx: func() *evmtypes.MsgEthereumTx { return buildDynamicFeeTx(t) }, + blockHash: testBlockHash, + blockNumber: 200, + index: 3, + baseFee: big.NewInt(500000000), + chainID: testChainID, + expectError: false, + validateResult: func(t *testing.T, result *RPCTransaction) { + require.Equal(t, hexutil.Uint64(ethtypes.DynamicFeeTxType), result.Type) + expectedPrice := big.NewInt(1500000000) + require.Equal(t, (*hexutil.Big)(expectedPrice), result.GasPrice) + require.Equal(t, &testBlockHash, result.BlockHash) + }, + }, + { + name: "SetCode transaction - pending", + setupTx: func() *evmtypes.MsgEthereumTx { return buildSetCodeTx(t) }, + blockHash: common.Hash{}, + blockNumber: 0, + index: 0, + baseFee: nil, + chainID: testChainID, + expectError: false, + validateResult: func(t *testing.T, result *RPCTransaction) { + require.Equal(t, hexutil.Uint64(ethtypes.SetCodeTxType), result.Type) + require.Equal(t, testFromAddr, result.From) + require.Equal(t, &testAddress, result.To) + require.Equal(t, (*hexutil.Big)(big.NewInt(3000)), result.Value) + require.Equal(t, hexutil.Uint64(100000), result.Gas) + require.Equal(t, (*hexutil.Big)(big.NewInt(2000000000)), result.GasFeeCap) + require.Equal(t, (*hexutil.Big)(big.NewInt(1000000000)), result.GasTipCap) + require.NotNil(t, result.Accesses) + require.NotNil(t, result.YParity) + require.NotNil(t, result.AuthorizationList) + require.Len(t, result.AuthorizationList, 1) + auth := result.AuthorizationList[0] + require.Equal(t, testAddress, auth.Address) + require.Equal(t, *uint256.MustFromBig(testChainID), auth.ChainID) + require.Equal(t, uint64(1), auth.Nonce) + require.Equal(t, uint8(27), auth.V) + require.Equal(t, *uint256.NewInt(1), auth.R) + require.Equal(t, *uint256.NewInt(1), auth.S) + require.Equal(t, hexutil.Bytes([]byte("setcode data")), result.Input) + }, + }, + { + name: "SetCode transaction - mined with baseFee", + setupTx: func() *evmtypes.MsgEthereumTx { return buildSetCodeTx(t) }, + blockHash: testBlockHash, + blockNumber: 300, + index: 7, + baseFee: big.NewInt(800000000), + chainID: testChainID, + expectError: false, + validateResult: func(t *testing.T, result *RPCTransaction) { + require.Equal(t, hexutil.Uint64(ethtypes.SetCodeTxType), result.Type) + expectedPrice := big.NewInt(1800000000) + require.Equal(t, (*hexutil.Big)(expectedPrice), result.GasPrice) + require.Equal(t, &testBlockHash, result.BlockHash) + require.NotNil(t, result.AuthorizationList) + require.Len(t, result.AuthorizationList, 1) + auth := result.AuthorizationList[0] + require.Equal(t, testAddress, auth.Address) + require.Equal(t, *uint256.MustFromBig(testChainID), auth.ChainID) + require.Equal(t, uint64(1), auth.Nonce) + require.Equal(t, uint8(27), auth.V) + require.Equal(t, *uint256.NewInt(1), auth.R) + require.Equal(t, *uint256.NewInt(1), auth.S) + }, + }, + } + + for _, tc := range testCases { + t.Run(tc.name, func(t *testing.T) { + msg := tc.setupTx() + + result, err := NewRPCTransaction( + msg, + tc.blockHash, + tc.blockNumber, + tc.index, + tc.baseFee, + tc.chainID, + ) + + if tc.expectError { + require.Error(t, err) + require.Nil(t, result) + } else { + require.NoError(t, err) + require.NotNil(t, result) + + require.NotEmpty(t, result.Hash) + require.NotNil(t, result.V) + require.NotNil(t, result.R) + require.NotNil(t, result.S) + + if tc.validateResult != nil { + tc.validateResult(t, result) + } + } + }) + } +} diff --git a/tests/integration_tests/test_set_code_tx.py b/tests/integration_tests/test_set_code_tx.py index acb11ed748..da5c527eb4 100644 --- a/tests/integration_tests/test_set_code_tx.py +++ b/tests/integration_tests/test_set_code_tx.py @@ -2,6 +2,9 @@ from pathlib import Path import pytest +from eth_account import Account +from eth_account.typed_transactions.set_code_transaction import Authorization +from eth_utils import to_canonical_address from hexbytes import HexBytes from web3 import Web3, exceptions @@ -318,6 +321,88 @@ def process(w3): assert res[0]["type"] == res[-1]["type"] == 4, res +def recover_auth(auth_item): + + chain_id = auth_item["chainId"] + code_address = to_canonical_address(auth_item["address"]) + nonce = auth_item["nonce"] + + unsigned_authorization = Authorization(chain_id, code_address, nonce) + authorization_hash = unsigned_authorization.hash() + + v = auth_item["yParity"] + r = auth_item["r"] + s = auth_item["s"] + + return Account._recover_hash(authorization_hash, vrs=(v, r, s)) + + +def test_set_code_tx_get_transaction_by_hash(ethermint, geth): + acc = derive_new_account(n=3) + + def process(w3): + target_acc = derive_new_account(n=4) + fund_acc(w3, acc) + + chain_id = w3.eth.chain_id + nonce = w3.eth.get_transaction_count(acc.address) + + auth_addr = target_acc.address + auth = { + "chainId": chain_id, + "address": auth_addr, + "nonce": nonce + 1, + } + signed_auth = acc.sign_authorization(auth) + + setcode_tx = { + "chainId": chain_id, + "type": 4, + "to": acc.address, + "value": 0, + "gas": 100000, + "maxFeePerGas": 1000000000000, + "maxPriorityFeePerGas": 10000, + "nonce": nonce, + "authorizationList": [signed_auth], + } + + signed_tx = acc.sign_transaction(setcode_tx) + tx_hash = w3.eth.send_raw_transaction(signed_tx.raw_transaction) + receipt = w3.eth.wait_for_transaction_receipt(tx_hash, timeout=30) + + assert receipt.status == 1, f"transaction failed: {receipt}" + + code = w3.eth.get_code(acc.address, "latest") + expected_code = HexBytes(address_to_delegation(auth_addr)) + assert ( + code == expected_code + ), f"code incorrect: got {Web3.to_hex(code)}, want {expected_code}" + + tx = w3.eth.get_transaction(tx_hash) + + return tx + + providers = [ethermint.w3, geth.w3] + with ThreadPoolExecutor(len(providers)) as exec: + tasks = [exec.submit(process, w3) for w3 in providers] + res = [future.result() for future in as_completed(tasks)] + assert len(res) == len(providers) + auth_list0 = res[0]["authorizationList"][0] + auth_list1 = res[1]["authorizationList"][0] + assert len(auth_list0) == len(auth_list1) + assert auth_list0["chainId"] == auth_list1["chainId"] + assert auth_list0["address"] == auth_list1["address"] + auth_0_addr = recover_auth(auth_list0) + auth_1_addr = recover_auth(auth_list1) + + assert auth_0_addr == auth_1_addr == acc.address, ( + f"auth_0_addr: {auth_0_addr}, " + f"auth_1_addr: {auth_1_addr}, " + f"acc.address: {acc.address}" + ) + + def test_set_code_tx_signature_invalid(ethermint, geth): def process(w3): acc = derive_new_account(n=3) @@ -544,14 +629,14 @@ def test_set_code_tx_delegate_auth_call_using_different_account(cluster): assert code == expected_code_hex, f"Expected code {expected_code_hex}, got {code}" new_auth_nonce = w3.eth.get_transaction_count(auth_account.address) - assert new_auth_nonce == auth_nonce + 1, ( - f"Expected auth_account nonce {auth_nonce + 1}, got {new_auth_nonce}" - ) + assert ( + new_auth_nonce == auth_nonce + 1 + ), f"Expected auth_account nonce {auth_nonce + 1}, got {new_auth_nonce}" new_sender_nonce = w3.eth.get_transaction_count(sender_account.address) - assert new_sender_nonce == sender_nonce + 1, ( - f"Expected sender_account nonce {sender_nonce + 1}, got {new_sender_nonce}" - ) + assert ( + new_sender_nonce == sender_nonce + 1 + ), f"Expected sender_account nonce {sender_nonce + 1}, got {new_sender_nonce}" def generate_signed_auth(w3, acc, delegate_addr, nonce): @@ -616,6 +701,6 @@ def test_set_code_tx_revoke_delegation(cluster): code = w3.eth.get_code(acc.address, "latest") expected_code = "0x" - assert Web3.to_hex(code) == expected_code, ( - f"Expected code {expected_code}, got {Web3.to_hex(code)}" - ) + assert ( + Web3.to_hex(code) == expected_code + ), f"Expected code {expected_code}, got {Web3.to_hex(code)}"