diff --git a/itests/contracts/Blocktest.hex b/itests/contracts/Blocktest.hex new file mode 100644 index 000000000..2d477b3ff --- /dev/null +++ b/itests/contracts/Blocktest.hex @@ -0,0 +1 @@ +608060405234801561001057600080fd5b5061024d806100206000396000f3fe608060405234801561001057600080fd5b50600436106100625760003560e01c806311dcda5214610067578063188ec356146100715780633e64a6961461008f57806342cbb15c146100ad578063564b81ef146100cb578063bfc6ac54146100e9575b600080fd5b61006f610107565b005b610079610117565b6040516100869190610165565b60405180910390f35b61009761011f565b6040516100a49190610165565b60405180910390f35b6100b5610127565b6040516100c29190610165565b60405180910390f35b6100d361012f565b6040516100e09190610165565b60405180910390f35b6100f1610137565b6040516100fe9190610199565b60405180910390f35b61013a461461011557600080fd5b565b600042905090565b600048905090565b600043905090565b600046905090565b600060014361014691906101e3565b40905090565b6000819050919050565b61015f8161014c565b82525050565b600060208201905061017a6000830184610156565b92915050565b6000819050919050565b61019381610180565b82525050565b60006020820190506101ae600083018461018a565b92915050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b60006101ee8261014c565b91506101f98361014c565b9250828203905081811115610211576102106101b4565b5b9291505056fea264697066735822122015a2d5fbebc013a5c3ece3d5bbf98707100b155793f6d340c3df6a736a3f1dfa64736f6c63430008110033 \ No newline at end of file diff --git a/itests/contracts/Blocktest.sol b/itests/contracts/Blocktest.sol new file mode 100644 index 000000000..3fde0d56b --- /dev/null +++ b/itests/contracts/Blocktest.sol @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.17; + +contract BlockTest { + + function testChainID() public view{ + require(block.chainid == 314); + } + + function getBlockhashPrevious() public view returns (bytes32) { + return blockhash(block.number-1); + } + + function getBasefee() public view returns (uint256){ + return block.basefee; + } + + function getBlockNumber() public view returns (uint256){ + return block.number; + } + function getTimestamp() public view returns (uint256){ + return block.timestamp; + } +} diff --git a/itests/fevm_test.go b/itests/fevm_test.go index 940d56ef1..b93cc824d 100644 --- a/itests/fevm_test.go +++ b/itests/fevm_test.go @@ -883,6 +883,96 @@ func TestFEVMGetBlockDifficulty(t *testing.T) { require.Equal(t, len(ret), 32) } +func TestFEVMTestCorrectChainID(t *testing.T) { + ctx, cancel, client := kit.SetupFEVMTest(t) + defer cancel() + + //install contract + filenameActor := "contracts/Blocktest.hex" + fromAddr, contractAddr := client.EVM().DeployContractFromFilename(ctx, filenameActor) + + //run test + _, _, err := client.EVM().InvokeContractByFuncName(ctx, fromAddr, contractAddr, "testChainID()", []byte{}) + require.NoError(t, err) +} + +func TestFEVMGetChainPropertiesBlockTimestamp(t *testing.T) { + ctx, cancel, client := kit.SetupFEVMTest(t) + defer cancel() + + //install contract + filenameActor := "contracts/Blocktest.hex" + fromAddr, contractAddr := client.EVM().DeployContractFromFilename(ctx, filenameActor) + + // block number check + ret, wait, err := client.EVM().InvokeContractByFuncName(ctx, fromAddr, contractAddr, "getTimestamp()", []byte{}) + require.NoError(t, err) + + timestampFromSolidity, err := decodeOutputToUint64(ret) + require.NoError(t, err) + + ethBlock := client.EVM().GetEthBlockFromWait(ctx, wait) + + require.Equal(t, ethBlock.Timestamp, ethtypes.EthUint64(timestampFromSolidity)) +} + +func TestFEVMGetChainPropertiesBlockNumber(t *testing.T) { + ctx, cancel, client := kit.SetupFEVMTest(t) + defer cancel() + + //install contract + filenameActor := "contracts/Blocktest.hex" + fromAddr, contractAddr := client.EVM().DeployContractFromFilename(ctx, filenameActor) + + // block number check + ret, wait, err := client.EVM().InvokeContractByFuncName(ctx, fromAddr, contractAddr, "getBlockNumber()", []byte{}) + require.NoError(t, err) + + blockHeightFromSolidity, err := decodeOutputToUint64(ret) + require.NoError(t, err) + + ethBlock := client.EVM().GetEthBlockFromWait(ctx, wait) + + require.Equal(t, ethBlock.Number, ethtypes.EthUint64(blockHeightFromSolidity)) +} + +func TestFEVMGetChainPropertiesBlockHash(t *testing.T) { + ctx, cancel, client := kit.SetupFEVMTest(t) + defer cancel() + + //install contract + filenameActor := "contracts/Blocktest.hex" + fromAddr, contractAddr := client.EVM().DeployContractFromFilename(ctx, filenameActor) + + //block hash check + ret, wait, err := client.EVM().InvokeContractByFuncName(ctx, fromAddr, contractAddr, "getBlockhashPrevious()", []byte{}) + expectedBlockHash := hex.EncodeToString(ret) + require.NoError(t, err) + + ethBlock := client.EVM().GetEthBlockFromWait(ctx, wait) + //in solidity we get the parent block hash because the current block hash doesnt exist at that execution context yet + //so we compare the parent hash here in the test + require.Equal(t, "0x"+expectedBlockHash, ethBlock.ParentHash.String()) +} + +func TestFEVMGetChainPropertiesBaseFee(t *testing.T) { + ctx, cancel, client := kit.SetupFEVMTest(t) + defer cancel() + + //install contract + filenameActor := "contracts/Blocktest.hex" + fromAddr, contractAddr := client.EVM().DeployContractFromFilename(ctx, filenameActor) + + ret, wait, err := client.EVM().InvokeContractByFuncName(ctx, fromAddr, contractAddr, "getBasefee()", []byte{}) + require.NoError(t, err) + baseFeeRet, err := decodeOutputToUint64(ret) + require.NoError(t, err) + + ethBlock := client.EVM().GetEthBlockFromWait(ctx, wait) + + require.Equal(t, ethBlock.BaseFeePerGas, ethtypes.EthBigInt(big.NewInt(int64(baseFeeRet)))) +} + func TestFEVMErrorParsing(t *testing.T) { ctx, cancel, client := kit.SetupFEVMTest(t) defer cancel() diff --git a/itests/kit/evm.go b/itests/kit/evm.go index 3cbfcd5f2..a2ab5bb6f 100644 --- a/itests/kit/evm.go +++ b/itests/kit/evm.go @@ -247,6 +247,22 @@ func (e *EVM) ComputeContractAddress(deployer ethtypes.EthAddress, nonce uint64) return *(*ethtypes.EthAddress)(hasher.Sum(nil)[12:]) } +// return eth block from a wait return +// this necessarily goes back one parent in the chain because wait is one block ahead of execution +func (e *EVM) GetEthBlockFromWait(ctx context.Context, wait *api.MsgLookup) ethtypes.EthBlock { + c, err := wait.TipSet.Cid() + require.NoError(e.t, err) + hash, err := ethtypes.EthHashFromCid(c) + require.NoError(e.t, err) + + ethBlockParent, err := e.EthGetBlockByHash(ctx, hash, true) + require.NoError(e.t, err) + ethBlock, err := e.EthGetBlockByHash(ctx, ethBlockParent.ParentHash, true) + require.NoError(e.t, err) + + return ethBlock +} + func (e *EVM) InvokeContractByFuncName(ctx context.Context, fromAddr address.Address, idAddr address.Address, funcSignature string, inputData []byte) ([]byte, *api.MsgLookup, error) { entryPoint := CalcFuncSignature(funcSignature) wait, err := e.InvokeSolidity(ctx, fromAddr, idAddr, entryPoint, inputData)