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:
Shrenuj Bansal 2023-01-10 19:28:49 -05:00 committed by GitHub
parent 95501b77dd
commit 3456d90e0d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 408 additions and 0 deletions

View File

@ -731,6 +731,11 @@ workflows:
suite: itest-eth_account_abstraction suite: itest-eth_account_abstraction
target: "./itests/eth_account_abstraction_test.go" target: "./itests/eth_account_abstraction_test.go"
- test:
name: test-itest-eth_balance
suite: itest-eth_balance
target: "./itests/eth_balance_test.go"
- test: - test:
name: test-itest-eth_deploy name: test-itest-eth_deploy
suite: itest-eth_deploy suite: itest-eth_deploy
@ -741,6 +746,11 @@ workflows:
suite: itest-eth_filter suite: itest-eth_filter
target: "./itests/eth_filter_test.go" target: "./itests/eth_filter_test.go"
- test:
name: test-itest-eth_transactions
suite: itest-eth_transactions
target: "./itests/eth_transactions_test.go"
- test: - test:
name: test-itest-fevm_address name: test-itest-fevm_address
suite: itest-fevm_address suite: itest-fevm_address

View File

@ -151,6 +151,7 @@ func TestTransformParams(t *testing.T) {
require.Equal(t, mustDecodeHex("0x1122334455"), evmParams.Initcode) require.Equal(t, mustDecodeHex("0x1122334455"), evmParams.Initcode)
} }
func TestEcRecover(t *testing.T) { func TestEcRecover(t *testing.T) {
rHex := "0x479ff7fa64cf8bf641eb81635d1e8a698530d2f219951d234539e6d074819529" rHex := "0x479ff7fa64cf8bf641eb81635d1e8a698530d2f219951d234539e6d074819529"
sHex := "0x4b6146d27be50cdbb2853ba9a42f207af8d730272f1ebe9c9a78aeef1d6aa924" sHex := "0x4b6146d27be50cdbb2853ba9a42f207af8d730272f1ebe9c9a78aeef1d6aa924"

View 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)
}

View 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: &ethAddr,
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: &ethAddr2,
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: &ethAddr,
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: &ethAddr,
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 &ethtypes.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
}