2023-02-13 03:43:25 +00:00
|
|
|
package itests
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"encoding/hex"
|
|
|
|
"os"
|
|
|
|
"testing"
|
|
|
|
"time"
|
|
|
|
|
2023-02-13 12:09:09 +00:00
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
|
2023-02-13 03:43:25 +00:00
|
|
|
"github.com/filecoin-project/lotus/chain/types"
|
2023-02-17 04:07:20 +00:00
|
|
|
"github.com/filecoin-project/lotus/chain/types/ethtypes"
|
2023-02-13 03:43:25 +00:00
|
|
|
"github.com/filecoin-project/lotus/itests/kit"
|
|
|
|
)
|
|
|
|
|
2023-02-17 04:07:20 +00:00
|
|
|
// TestGetCodeAndNonce ensures that GetCode and GetTransactionCount return the correct results for:
|
2023-02-13 03:43:25 +00:00
|
|
|
// 1. Placeholders.
|
|
|
|
// 2. Non-existent actors.
|
|
|
|
// 3. Normal EVM actors.
|
|
|
|
// 4. Self-destructed EVM actors.
|
2023-02-17 04:07:20 +00:00
|
|
|
func TestGetCodeAndNonce(t *testing.T) {
|
2023-02-13 03:43:25 +00:00
|
|
|
kit.QuietMiningLogs()
|
|
|
|
|
|
|
|
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()
|
|
|
|
|
2023-02-17 04:07:20 +00:00
|
|
|
// Accounts should have empty code, empty nonce.
|
2023-02-13 03:43:25 +00:00
|
|
|
{
|
|
|
|
// A random eth address should have no code.
|
|
|
|
_, ethAddr, filAddr := client.EVM().NewAccount()
|
|
|
|
bytecode, err := client.EVM().EthGetCode(ctx, ethAddr, "latest")
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Empty(t, bytecode)
|
|
|
|
|
2023-02-17 04:07:20 +00:00
|
|
|
// Nonce should also be zero
|
|
|
|
nonce, err := client.EVM().EthGetTransactionCount(ctx, ethAddr, "latest")
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Zero(t, nonce)
|
|
|
|
|
2023-02-13 03:43:25 +00:00
|
|
|
// send some funds to the account.
|
|
|
|
kit.SendFunds(ctx, t, client, filAddr, types.FromFil(10))
|
|
|
|
|
|
|
|
// The code should still be empty, target is now a placeholder.
|
|
|
|
bytecode, err = client.EVM().EthGetCode(ctx, ethAddr, "latest")
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Empty(t, bytecode)
|
2023-02-17 04:07:20 +00:00
|
|
|
|
|
|
|
// Nonce should still be zero.
|
|
|
|
nonce, err = client.EVM().EthGetTransactionCount(ctx, ethAddr, "latest")
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Zero(t, nonce)
|
2023-02-13 03:43:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// Check contract code.
|
|
|
|
{
|
|
|
|
// install a contract
|
|
|
|
contractHex, err := os.ReadFile("./contracts/SelfDestruct.hex")
|
|
|
|
require.NoError(t, err)
|
|
|
|
contract, err := hex.DecodeString(string(contractHex))
|
|
|
|
require.NoError(t, err)
|
|
|
|
createReturn := client.EVM().DeployContract(ctx, client.DefaultKey.Address, contract)
|
|
|
|
contractAddr := createReturn.EthAddress
|
|
|
|
contractFilAddr := *createReturn.RobustAddress
|
|
|
|
|
|
|
|
// The newly deployed contract should not be empty.
|
|
|
|
bytecode, err := client.EVM().EthGetCode(ctx, contractAddr, "latest")
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.NotEmpty(t, bytecode)
|
|
|
|
|
2023-02-17 04:07:20 +00:00
|
|
|
// Nonce should be one.
|
|
|
|
nonce, err := client.EVM().EthGetTransactionCount(ctx, contractAddr, "latest")
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Equal(t, ethtypes.EthUint64(1), nonce)
|
|
|
|
|
2023-02-13 03:43:25 +00:00
|
|
|
// Destroy it.
|
|
|
|
_, _, err = client.EVM().InvokeContractByFuncName(ctx, client.DefaultKey.Address, contractFilAddr, "destroy()", nil)
|
|
|
|
require.NoError(t, err)
|
|
|
|
|
|
|
|
// The code should be empty again.
|
|
|
|
bytecode, err = client.EVM().EthGetCode(ctx, contractAddr, "latest")
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Empty(t, bytecode)
|
2023-02-17 04:07:20 +00:00
|
|
|
|
|
|
|
// Nonce should go back to zero
|
|
|
|
nonce, err = client.EVM().EthGetTransactionCount(ctx, contractAddr, "latest")
|
|
|
|
require.NoError(t, err)
|
|
|
|
require.Zero(t, nonce)
|
2023-02-13 03:43:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|