From fc7d392c3bb1cb566e938a90b1c83683483ae634 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20M=C3=BCller?= Date: Fri, 3 May 2024 17:07:49 -0700 Subject: [PATCH] fix EVM.Result.deployedContract --- fvm/evm/evm_test.go | 16 +++---- fvm/evm/stdlib/contract.go | 84 ++++++++++++++++++--------------- fvm/evm/stdlib/contract_test.go | 6 ++- 3 files changed, 59 insertions(+), 47 deletions(-) diff --git a/fvm/evm/evm_test.go b/fvm/evm/evm_test.go index 88c905e44c8..d1c1b614604 100644 --- a/fvm/evm/evm_test.go +++ b/fvm/evm/evm_test.go @@ -1306,6 +1306,7 @@ func TestDryRun(t *testing.T) { evmAddress := sc.EVMContract.Address.HexWithPrefix() dryRunTx := func( + t *testing.T, tx *gethTypes.Transaction, ctx fvm.Context, vm fvm.VM, @@ -1368,7 +1369,7 @@ func TestDryRun(t *testing.T) { big.NewInt(0), data, ) - result := dryRunTx(tx, ctx, vm, snapshot, testContract) + result := dryRunTx(t, tx, ctx, vm, snapshot, testContract) require.Equal(t, types.ErrCodeNoError, result.ErrorCode) require.Equal(t, types.StatusSuccessful, result.Status) require.Greater(t, result.GasConsumed, uint64(0)) @@ -1384,7 +1385,7 @@ func TestDryRun(t *testing.T) { big.NewInt(0), data, ) - result = dryRunTx(tx, ctx, vm, snapshot, testContract) + result = dryRunTx(t, tx, ctx, vm, snapshot, testContract) require.Equal(t, types.ExecutionErrCodeOutOfGas, result.ErrorCode) require.Equal(t, types.StatusFailed, result.Status) require.Equal(t, result.GasConsumed, limit) // burn it all!!! @@ -1413,7 +1414,7 @@ func TestDryRun(t *testing.T) { data, ) - result := dryRunTx(tx, ctx, vm, snapshot, testContract) + result := dryRunTx(t, tx, ctx, vm, snapshot, testContract) require.Equal(t, types.ErrCodeNoError, result.ErrorCode) require.Equal(t, types.StatusSuccessful, result.Status) require.Greater(t, result.GasConsumed, uint64(0)) @@ -1485,14 +1486,13 @@ func TestDryRun(t *testing.T) { testContract.ByteCode, ) - result := dryRunTx(tx, ctx, vm, snapshot, testContract) + result := dryRunTx(t, tx, ctx, vm, snapshot, testContract) require.Equal(t, types.ErrCodeNoError, result.ErrorCode) require.Equal(t, types.StatusSuccessful, result.Status) require.Greater(t, result.GasConsumed, uint64(0)) require.NotNil(t, result.ReturnedValue) - // todo add once https://github.com/onflow/flow-go/pull/5606 is merged - //require.NotNil(t, result.DeployedContractAddress) - //require.NotEmpty(t, result.DeployedContractAddress.String()) + require.NotNil(t, result.DeployedContractAddress) + require.NotEmpty(t, result.DeployedContractAddress.String()) }) }) } @@ -1525,7 +1525,7 @@ func TestCadenceArch(t *testing.T) { )) innerTxBytes := testAccount.PrepareSignAndEncodeTx(t, testContract.DeployedAt.ToCommon(), - testContract.MakeCallData(t, "verifyArchCallToFlowBlockHeight", uint64(ctx.BlockHeader.Height)), + testContract.MakeCallData(t, "verifyArchCallToFlowBlockHeight", ctx.BlockHeader.Height), big.NewInt(0), uint64(10_000_000), big.NewInt(0), diff --git a/fvm/evm/stdlib/contract.go b/fvm/evm/stdlib/contract.go index b96fe09a3e3..ddbe568f2e4 100644 --- a/fvm/evm/stdlib/contract.go +++ b/fvm/evm/stdlib/contract.go @@ -1181,7 +1181,26 @@ func NewResultValue( locationRange interpreter.LocationRange, result *types.ResultSummary, ) *interpreter.CompositeValue { - loc := common.NewAddressLocation(gauge, handler.EVMContractAddress(), ContractName) + + evmContractLocation := common.NewAddressLocation( + gauge, + handler.EVMContractAddress(), + ContractName, + ) + + deployedContractAddress := result.DeployedContractAddress + deployedContractValue := interpreter.NilOptionalValue + if deployedContractAddress != nil { + deployedContractValue = interpreter.NewSomeValueNonCopying( + inter, + NewEVMAddress( + inter, + locationRange, + evmContractLocation, + *deployedContractAddress, + ), + ) + } fields := []interpreter.CompositeField{ { @@ -1190,7 +1209,7 @@ func NewResultValue( inter, locationRange, &sema.CompositeType{ - Location: loc, + Location: evmContractLocation, Identifier: evmStatusTypeQualifiedIdentifier, Kind: common.CompositeKindEnum, }, @@ -1216,25 +1235,16 @@ func NewResultValue( Name: "data", Value: interpreter.ByteSliceToByteArrayValue(inter, result.ReturnedValue), }, - } - - // we made the deployed contract address optional - if result.DeployedContractAddress != nil { - fields = append(fields, interpreter.CompositeField{ - Name: "deployedContract", - Value: EVMAddressToAddressBytesArrayValue(inter, *result.DeployedContractAddress), - }) - } else { - fields = append(fields, interpreter.CompositeField{ + { Name: "deployedContract", - Value: interpreter.NilOptionalValue, - }) + Value: deployedContractValue, + }, } return interpreter.NewCompositeValue( inter, locationRange, - loc, + evmContractLocation, evmResultTypeQualifiedIdentifier, common.CompositeKindStructure, fields, @@ -2255,37 +2265,37 @@ func ResultSummaryFromEVMResultValue(val cadence.Value) (*types.ResultSummary, e return nil, fmt.Errorf("invalid input: unexpected type for data field") } - var deployedAddress *cadence.Array - switch v := str.Fields[4].(type) { - case cadence.Optional: - if v.Value != nil { - arr, ok := v.Value.(cadence.Array) - if !ok { - return nil, fmt.Errorf("invalid input: unexpected type for deployed contract field") - } - deployedAddress = &arr - } - case cadence.Array: - deployedAddress = &v - default: - return nil, fmt.Errorf("invalid input: unexpected type for deployed contract field") + convertedData := make([]byte, len(data.Values)) + for i, value := range data.Values { + convertedData[i] = value.(cadence.UInt8).ToGoValue().(uint8) } var convertedDeployedAddress *types.Address - if deployedAddress != nil { - convertedAddress := make([]byte, len(deployedAddress.Values)) - for i, val := range deployedAddress.Values { + + deployedAddressField, ok := str.Fields[4].(cadence.Optional) + if !ok { + return nil, fmt.Errorf("invalid input: unexpected type for deployed contract field") + } + + if deployedAddressField.Value != nil { + evmAddress, ok := deployedAddressField.Value.(cadence.Struct) + if !ok { + return nil, fmt.Errorf("invalid input: unexpected type for deployed contract field") + } + + bytes, ok := evmAddress.Fields[0].(cadence.Array) + if !ok { + return nil, fmt.Errorf("invalid input: unexpected type for deployed contract field") + } + + convertedAddress := make([]byte, len(bytes.Values)) + for i, val := range bytes.Values { convertedAddress[i] = val.(cadence.UInt8).ToGoValue().(uint8) } addr := types.Address(convertedAddress) convertedDeployedAddress = &addr } - convertedData := make([]byte, len(data.Values)) - for i, value := range data.Values { - convertedData[i] = value.(cadence.UInt8).ToGoValue().(uint8) - } - return &types.ResultSummary{ Status: types.Status(status), ErrorCode: types.ErrorCode(errorCode), diff --git a/fvm/evm/stdlib/contract_test.go b/fvm/evm/stdlib/contract_test.go index 5fab88cadda..228f6c3a942 100644 --- a/fvm/evm/stdlib/contract_test.go +++ b/fvm/evm/stdlib/contract_test.go @@ -3826,7 +3826,7 @@ func TestCadenceOwnedAccountDeploy(t *testing.T) { return &types.ResultSummary{ Status: types.StatusSuccessful, DeployedContractAddress: &types.Address{4}, - ReturnedValue: types.Data{4}, + ReturnedValue: types.Data{5}, } }, } @@ -3850,6 +3850,8 @@ func TestCadenceOwnedAccountDeploy(t *testing.T) { value: EVM.Balance(flow: 1230000000000000000) ) destroy cadenceOwnedAccount + + assert(res.deployedContract?.bytes == [4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]) return res.data } `) @@ -3909,7 +3911,7 @@ func TestCadenceOwnedAccountDeploy(t *testing.T) { require.NoError(t, err) expected := cadence. - NewArray([]cadence.Value{cadence.UInt8(4)}). + NewArray([]cadence.Value{cadence.UInt8(5)}). WithType(cadence.NewVariableSizedArrayType(cadence.UInt8Type{})) require.Equal(t, expected, actual)