itests: Add tests for eth get balance and transaction submits (#9966)
* Add tests for eth get balance and transaction submits * fix lint * one more lint * Add contract invocation test * address comments * fix lint * address final comment * make gen and fix lint as always
This commit is contained in:
parent
95501b77dd
commit
3456d90e0d
@ -731,6 +731,11 @@ workflows:
|
||||
suite: itest-eth_account_abstraction
|
||||
target: "./itests/eth_account_abstraction_test.go"
|
||||
|
||||
- test:
|
||||
name: test-itest-eth_balance
|
||||
suite: itest-eth_balance
|
||||
target: "./itests/eth_balance_test.go"
|
||||
|
||||
- test:
|
||||
name: test-itest-eth_deploy
|
||||
suite: itest-eth_deploy
|
||||
@ -741,6 +746,11 @@ workflows:
|
||||
suite: itest-eth_filter
|
||||
target: "./itests/eth_filter_test.go"
|
||||
|
||||
- test:
|
||||
name: test-itest-eth_transactions
|
||||
suite: itest-eth_transactions
|
||||
target: "./itests/eth_transactions_test.go"
|
||||
|
||||
- test:
|
||||
name: test-itest-fevm_address
|
||||
suite: itest-fevm_address
|
||||
|
@ -151,6 +151,7 @@ func TestTransformParams(t *testing.T) {
|
||||
|
||||
require.Equal(t, mustDecodeHex("0x1122334455"), evmParams.Initcode)
|
||||
}
|
||||
|
||||
func TestEcRecover(t *testing.T) {
|
||||
rHex := "0x479ff7fa64cf8bf641eb81635d1e8a698530d2f219951d234539e6d074819529"
|
||||
sHex := "0x4b6146d27be50cdbb2853ba9a42f207af8d730272f1ebe9c9a78aeef1d6aa924"
|
||||
|
97
itests/eth_balance_test.go
Normal file
97
itests/eth_balance_test.go
Normal file
@ -0,0 +1,97 @@
|
||||
package itests
|
||||
|
||||
import (
|
||||
"context"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/filecoin-project/go-address"
|
||||
"github.com/filecoin-project/go-state-types/abi"
|
||||
"github.com/filecoin-project/go-state-types/big"
|
||||
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/chain/types/ethtypes"
|
||||
"github.com/filecoin-project/lotus/itests/kit"
|
||||
)
|
||||
|
||||
func TestEthGetBalanceExistingF4address(t *testing.T) {
|
||||
blockTime := 100 * time.Millisecond
|
||||
client, _, ens := kit.EnsembleMinimal(t, kit.MockProofs(), kit.ThroughRPC())
|
||||
ens.InterconnectAll().BeginMining(blockTime)
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
|
||||
defer cancel()
|
||||
|
||||
_, ethAddr, deployer := client.EVM().NewAccount()
|
||||
|
||||
fundAmount := types.FromFil(0)
|
||||
// send some funds to the f410 address
|
||||
kit.SendFunds(ctx, t, client, deployer, fundAmount)
|
||||
|
||||
balance, err := client.EthGetBalance(ctx, ethAddr, "latest")
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, balance, ethtypes.EthBigInt{Int: fundAmount.Int})
|
||||
}
|
||||
|
||||
func TestEthGetBalanceNonExistentF4address(t *testing.T) {
|
||||
blockTime := 100 * time.Millisecond
|
||||
client, _, ens := kit.EnsembleMinimal(t, kit.MockProofs(), kit.ThroughRPC())
|
||||
ens.InterconnectAll().BeginMining(blockTime)
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
|
||||
defer cancel()
|
||||
|
||||
_, ethAddr, _ := client.EVM().NewAccount()
|
||||
|
||||
balance, err := client.EthGetBalance(ctx, ethAddr, "latest")
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, balance, ethtypes.EthBigIntZero)
|
||||
}
|
||||
|
||||
func TestEthGetBalanceExistentIDMaskedAddr(t *testing.T) {
|
||||
blockTime := 100 * time.Millisecond
|
||||
client, _, ens := kit.EnsembleMinimal(t, kit.MockProofs(), kit.ThroughRPC())
|
||||
ens.InterconnectAll().BeginMining(blockTime)
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
|
||||
defer cancel()
|
||||
|
||||
faddr, err := client.WalletDefaultAddress(ctx)
|
||||
require.NoError(t, err)
|
||||
fid, err := client.StateLookupID(ctx, faddr, types.EmptyTSK)
|
||||
require.NoError(t, err)
|
||||
|
||||
ethAddr, err := ethtypes.EthAddressFromFilecoinAddress(fid)
|
||||
require.NoError(t, err)
|
||||
|
||||
balance, err := client.WalletBalance(ctx, fid)
|
||||
require.NoError(t, err)
|
||||
|
||||
ebal, err := client.EthGetBalance(ctx, ethAddr, "latest")
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, ebal, ethtypes.EthBigInt{Int: balance.Int})
|
||||
}
|
||||
|
||||
func TestEthGetBalanceBuiltinActor(t *testing.T) {
|
||||
blockTime := 100 * time.Millisecond
|
||||
client, _, ens := kit.EnsembleMinimal(t, kit.MockProofs(), kit.ThroughRPC())
|
||||
ens.InterconnectAll().BeginMining(blockTime)
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
|
||||
defer cancel()
|
||||
|
||||
// Address for market actor
|
||||
fid, err := address.NewFromString("f05")
|
||||
require.NoError(t, err)
|
||||
|
||||
kit.SendFunds(ctx, t, client, fid, abi.TokenAmount{Int: big.NewInt(10).Int})
|
||||
|
||||
ethAddr, err := ethtypes.EthAddressFromFilecoinAddress(fid)
|
||||
require.NoError(t, err)
|
||||
|
||||
ebal, err := client.EthGetBalance(ctx, ethAddr, "latest")
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, ethtypes.EthBigInt{Int: big.NewInt(10).Int}, ebal)
|
||||
}
|
300
itests/eth_transactions_test.go
Normal file
300
itests/eth_transactions_test.go
Normal file
@ -0,0 +1,300 @@
|
||||
package itests
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/hex"
|
||||
"os"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
|
||||
"github.com/filecoin-project/go-state-types/big"
|
||||
"github.com/filecoin-project/go-state-types/manifest"
|
||||
|
||||
"github.com/filecoin-project/lotus/api"
|
||||
"github.com/filecoin-project/lotus/build"
|
||||
"github.com/filecoin-project/lotus/chain/types"
|
||||
"github.com/filecoin-project/lotus/chain/types/ethtypes"
|
||||
"github.com/filecoin-project/lotus/itests/kit"
|
||||
)
|
||||
|
||||
func TestValueTransferValidSignature(t *testing.T) {
|
||||
blockTime := 100 * time.Millisecond
|
||||
client, _, ens := kit.EnsembleMinimal(t, kit.MockProofs(), kit.ThroughRPC())
|
||||
|
||||
ens.InterconnectAll().BeginMining(blockTime)
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
|
||||
defer cancel()
|
||||
|
||||
// install contract
|
||||
contractHex, err := os.ReadFile("./contracts/SimpleCoin.bin")
|
||||
require.NoError(t, err)
|
||||
|
||||
contract, err := hex.DecodeString(string(contractHex))
|
||||
require.NoError(t, err)
|
||||
|
||||
// create a new Ethereum account
|
||||
key, ethAddr, deployer := client.EVM().NewAccount()
|
||||
_, ethAddr2, _ := client.EVM().NewAccount()
|
||||
|
||||
kit.SendFunds(ctx, t, client, deployer, types.FromFil(1000))
|
||||
|
||||
gaslimit, err := client.EthEstimateGas(ctx, ethtypes.EthCall{
|
||||
From: ðAddr,
|
||||
Data: contract,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
maxPriorityFeePerGas, err := client.EthMaxPriorityFeePerGas(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
tx := ethtypes.EthTxArgs{
|
||||
ChainID: build.Eip155ChainId,
|
||||
Value: big.NewInt(100),
|
||||
Nonce: 0,
|
||||
To: ðAddr2,
|
||||
MaxFeePerGas: types.NanoFil,
|
||||
MaxPriorityFeePerGas: big.Int(maxPriorityFeePerGas),
|
||||
GasLimit: int(gaslimit),
|
||||
V: big.Zero(),
|
||||
R: big.Zero(),
|
||||
S: big.Zero(),
|
||||
}
|
||||
|
||||
client.EVM().SignTransaction(&tx, key.PrivateKey)
|
||||
// Mangle signature
|
||||
tx.V.Int.Xor(tx.V.Int, big.NewInt(1).Int)
|
||||
|
||||
signed, err := tx.ToRlpSignedMsg()
|
||||
require.NoError(t, err)
|
||||
// Submit transaction with bad signature
|
||||
_, err = client.EVM().EthSendRawTransaction(ctx, signed)
|
||||
require.Error(t, err)
|
||||
|
||||
// Submit transaction with valid signature
|
||||
client.EVM().SignTransaction(&tx, key.PrivateKey)
|
||||
hash := client.EVM().SubmitTransaction(ctx, &tx)
|
||||
|
||||
receipt, err := waitForEthTxReceipt(ctx, client, hash)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, receipt)
|
||||
|
||||
// Success.
|
||||
require.EqualValues(t, ethtypes.EthUint64(0x1), receipt.Status)
|
||||
}
|
||||
|
||||
func TestLegacyTransaction(t *testing.T) {
|
||||
blockTime := 100 * time.Millisecond
|
||||
client, _, ens := kit.EnsembleMinimal(t, kit.MockProofs(), kit.ThroughRPC())
|
||||
|
||||
ens.InterconnectAll().BeginMining(blockTime)
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
|
||||
defer cancel()
|
||||
|
||||
// This is a legacy style transaction obtained from etherscan
|
||||
// Tx details: https://etherscan.io/getRawTx?tx=0x0763262208d89efeeb50c8bb05b50c537903fe9d7bdef3b223fd1f5f69f69b32
|
||||
txBytes, err := hex.DecodeString("f86f830131cf8504a817c800825208942cf1e5a8250ded8835694ebeb90cfa0237fcb9b1882ec4a5251d1100008026a0f5f8d2244d619e211eeb634acd1bea0762b7b4c97bba9f01287c82bfab73f911a015be7982898aa7cc6c6f27ff33e999e4119d6cd51330353474b98067ff56d930")
|
||||
require.NoError(t, err)
|
||||
_, err = client.EVM().EthSendRawTransaction(ctx, txBytes)
|
||||
require.ErrorContains(t, err, "legacy transaction is not supported")
|
||||
|
||||
}
|
||||
|
||||
func TestContractDeploymentValidSignature(t *testing.T) {
|
||||
|
||||
blockTime := 100 * time.Millisecond
|
||||
client, _, ens := kit.EnsembleMinimal(t, kit.MockProofs(), kit.ThroughRPC())
|
||||
|
||||
ens.InterconnectAll().BeginMining(blockTime)
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
|
||||
defer cancel()
|
||||
|
||||
// install contract
|
||||
contractHex, err := os.ReadFile("./contracts/SimpleCoin.bin")
|
||||
require.NoError(t, err)
|
||||
|
||||
contract, err := hex.DecodeString(string(contractHex))
|
||||
require.NoError(t, err)
|
||||
|
||||
// create a new Ethereum account
|
||||
key, ethAddr, deployer := client.EVM().NewAccount()
|
||||
|
||||
// send some funds to the f410 address
|
||||
kit.SendFunds(ctx, t, client, deployer, types.FromFil(10))
|
||||
|
||||
// verify the deployer address is an embryo.
|
||||
client.AssertActorType(ctx, deployer, manifest.EmbryoKey)
|
||||
|
||||
tx, err := deployContractTx(ctx, client, ethAddr, contract)
|
||||
require.NoError(t, err)
|
||||
|
||||
client.EVM().SignTransaction(tx, key.PrivateKey)
|
||||
// Mangle signature
|
||||
tx.V.Int.Xor(tx.V.Int, big.NewInt(1).Int)
|
||||
|
||||
signed, err := tx.ToRlpSignedMsg()
|
||||
require.NoError(t, err)
|
||||
// Submit transaction with bad signature
|
||||
_, err = client.EVM().EthSendRawTransaction(ctx, signed)
|
||||
require.Error(t, err)
|
||||
|
||||
// Submit transaction with valid signature
|
||||
client.EVM().SignTransaction(tx, key.PrivateKey)
|
||||
hash := client.EVM().SubmitTransaction(ctx, tx)
|
||||
|
||||
receipt, err := waitForEthTxReceipt(ctx, client, hash)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, receipt)
|
||||
|
||||
// Success.
|
||||
require.EqualValues(t, ethtypes.EthUint64(0x1), receipt.Status)
|
||||
|
||||
// Verify that the deployer is now an account.
|
||||
client.AssertActorType(ctx, deployer, manifest.EthAccountKey)
|
||||
|
||||
// Verify that the nonce was incremented.
|
||||
nonce, err := client.MpoolGetNonce(ctx, deployer)
|
||||
require.NoError(t, err)
|
||||
require.EqualValues(t, 1, nonce)
|
||||
|
||||
// Verify that the deployer is now an account.
|
||||
client.AssertActorType(ctx, deployer, manifest.EthAccountKey)
|
||||
}
|
||||
|
||||
func TestContractInvocation(t *testing.T) {
|
||||
blockTime := 100 * time.Millisecond
|
||||
client, _, ens := kit.EnsembleMinimal(t, kit.MockProofs(), kit.ThroughRPC())
|
||||
|
||||
ens.InterconnectAll().BeginMining(blockTime)
|
||||
|
||||
ctx, cancel := context.WithTimeout(context.Background(), time.Minute)
|
||||
defer cancel()
|
||||
|
||||
// install contract
|
||||
contractHex, err := os.ReadFile("./contracts/SimpleCoin.bin")
|
||||
require.NoError(t, err)
|
||||
|
||||
contract, err := hex.DecodeString(string(contractHex))
|
||||
require.NoError(t, err)
|
||||
|
||||
// create a new Ethereum account
|
||||
key, ethAddr, deployer := client.EVM().NewAccount()
|
||||
// send some funds to the f410 address
|
||||
kit.SendFunds(ctx, t, client, deployer, types.FromFil(10))
|
||||
|
||||
// DEPLOY CONTRACT
|
||||
tx, err := deployContractTx(ctx, client, ethAddr, contract)
|
||||
require.NoError(t, err)
|
||||
|
||||
client.EVM().SignTransaction(tx, key.PrivateKey)
|
||||
hash := client.EVM().SubmitTransaction(ctx, tx)
|
||||
|
||||
receipt, err := waitForEthTxReceipt(ctx, client, hash)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, receipt)
|
||||
require.EqualValues(t, ethtypes.EthUint64(0x1), receipt.Status)
|
||||
|
||||
// Get contract address.
|
||||
contractAddr := client.EVM().ComputeContractAddress(ethAddr, 0)
|
||||
|
||||
// INVOKE CONTRACT
|
||||
|
||||
// Params
|
||||
// entry point for getBalance - f8b2cb4f
|
||||
// address - ff00000000000000000000000000000000000064
|
||||
params, err := hex.DecodeString("f8b2cb4f000000000000000000000000ff00000000000000000000000000000000000064")
|
||||
require.NoError(t, err)
|
||||
|
||||
gaslimit, err := client.EthEstimateGas(ctx, ethtypes.EthCall{
|
||||
From: ðAddr,
|
||||
To: &contractAddr,
|
||||
Data: params,
|
||||
})
|
||||
require.NoError(t, err)
|
||||
|
||||
maxPriorityFeePerGas, err := client.EthMaxPriorityFeePerGas(ctx)
|
||||
require.NoError(t, err)
|
||||
|
||||
invokeTx := ethtypes.EthTxArgs{
|
||||
ChainID: build.Eip155ChainId,
|
||||
To: &contractAddr,
|
||||
Value: big.Zero(),
|
||||
Nonce: 1,
|
||||
MaxFeePerGas: types.NanoFil,
|
||||
MaxPriorityFeePerGas: big.Int(maxPriorityFeePerGas),
|
||||
GasLimit: int(gaslimit),
|
||||
Input: params,
|
||||
V: big.Zero(),
|
||||
R: big.Zero(),
|
||||
S: big.Zero(),
|
||||
}
|
||||
|
||||
client.EVM().SignTransaction(&invokeTx, key.PrivateKey)
|
||||
// Mangle signature
|
||||
invokeTx.V.Int.Xor(invokeTx.V.Int, big.NewInt(1).Int)
|
||||
|
||||
signed, err := invokeTx.ToRlpSignedMsg()
|
||||
require.NoError(t, err)
|
||||
// Submit transaction with bad signature
|
||||
_, err = client.EVM().EthSendRawTransaction(ctx, signed)
|
||||
require.Error(t, err)
|
||||
|
||||
// Submit transaction with valid signature
|
||||
client.EVM().SignTransaction(&invokeTx, key.PrivateKey)
|
||||
hash = client.EVM().SubmitTransaction(ctx, &invokeTx)
|
||||
|
||||
receipt, err = waitForEthTxReceipt(ctx, client, hash)
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, receipt)
|
||||
|
||||
// Success.
|
||||
require.EqualValues(t, ethtypes.EthUint64(0x1), receipt.Status)
|
||||
|
||||
}
|
||||
|
||||
func deployContractTx(ctx context.Context, client *kit.TestFullNode, ethAddr ethtypes.EthAddress, contract []byte) (*ethtypes.EthTxArgs, error) {
|
||||
gaslimit, err := client.EthEstimateGas(ctx, ethtypes.EthCall{
|
||||
From: ðAddr,
|
||||
Data: contract,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
maxPriorityFeePerGas, err := client.EthMaxPriorityFeePerGas(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// now deploy a contract from the embryo, and validate it went well
|
||||
return ðtypes.EthTxArgs{
|
||||
ChainID: build.Eip155ChainId,
|
||||
Value: big.Zero(),
|
||||
Nonce: 0,
|
||||
MaxFeePerGas: types.NanoFil,
|
||||
MaxPriorityFeePerGas: big.Int(maxPriorityFeePerGas),
|
||||
GasLimit: int(gaslimit),
|
||||
Input: contract,
|
||||
V: big.Zero(),
|
||||
R: big.Zero(),
|
||||
S: big.Zero(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func waitForEthTxReceipt(ctx context.Context, client *kit.TestFullNode, hash ethtypes.EthHash) (*api.EthTxReceipt, error) {
|
||||
var receipt *api.EthTxReceipt
|
||||
var err error
|
||||
for i := 0; i < 10000000000; i++ {
|
||||
receipt, err = client.EthGetTransactionReceipt(ctx, hash)
|
||||
if err != nil || receipt == nil {
|
||||
time.Sleep(500 * time.Millisecond)
|
||||
continue
|
||||
}
|
||||
break
|
||||
}
|
||||
return receipt, err
|
||||
}
|
Loading…
Reference in New Issue
Block a user