From 4dfdda57ad0a833c254a8e6792085b029d8fb9d7 Mon Sep 17 00:00:00 2001 From: Ardit Marku Date: Wed, 9 Oct 2024 13:02:07 +0300 Subject: [PATCH 01/15] Add support for ABI encoding/decoding of EVM.EVMBytes --- fvm/evm/impl/abi.go | 91 ++++++++++---- fvm/evm/impl/impl.go | 45 +++++++ fvm/evm/stdlib/contract.cdc | 10 ++ fvm/evm/stdlib/contract.go | 2 + fvm/evm/stdlib/contract_test.go | 209 ++++++++++++++++++++++++++++++++ 5 files changed, 335 insertions(+), 22 deletions(-) diff --git a/fvm/evm/impl/abi.go b/fvm/evm/impl/abi.go index 871d523abef..e2d971f7d5d 100644 --- a/fvm/evm/impl/abi.go +++ b/fvm/evm/impl/abi.go @@ -82,9 +82,12 @@ func reportABIEncodingComputation( inter *interpreter.Interpreter, locationRange interpreter.LocationRange, values *interpreter.ArrayValue, - evmAddressTypeID common.TypeID, + evmLocation common.AddressLocation, reportComputation func(intensity uint), ) { + evmAddressTypeID := evmLocation.TypeID(inter, stdlib.EVMAddressTypeQualifiedIdentifier) + evmBytesTypeID := evmLocation.TypeID(inter, "EVM.EVMBytes") + values.Iterate( inter, func(element interpreter.Value) (resume bool) { @@ -127,6 +130,14 @@ func reportABIEncodingComputation( // EVM addresses are static variables with a fixed // size of 32 bytes. reportComputation(abiEncodingByteSize) + } else if value.TypeID() == evmBytesTypeID { + computation := uint(2 * abiEncodingByteSize) + bytesArrayValue := value.GetMember(inter, locationRange, "value") + arrValue := bytesArrayValue.(*interpreter.ArrayValue) + bytesLength := arrValue.Count() + chunks := math.Ceil(float64(bytesLength) / float64(abiEncodingByteSize)) + computation += uint(chunks * abiEncodingByteSize) + reportComputation(computation) } else { panic(abiEncodingError{ Type: value.StaticType(inter), @@ -145,7 +156,7 @@ func reportABIEncodingComputation( inter, locationRange, value, - evmAddressTypeID, + evmLocation, reportComputation, ) @@ -188,7 +199,7 @@ func newInternalEVMTypeEncodeABIFunction( inter, locationRange, valuesArray, - evmAddressTypeID, + location, func(intensity uint) { inter.ReportComputation(environment.ComputationKindEVMEncodeABI, intensity) }, @@ -265,9 +276,18 @@ var gethTypeInt128 = gethABI.Type{T: gethABI.IntTy, Size: 128} var gethTypeInt256 = gethABI.Type{T: gethABI.IntTy, Size: 256} -var gethTypeAddress = gethABI.Type{Size: 20, T: gethABI.AddressTy} +var gethTypeAddress = gethABI.Type{T: gethABI.AddressTy, Size: 20} + +var gethTypeBytes = gethABI.Type{T: gethABI.BytesTy} + +// var gethTypeBytes4 = gethABI.Type{T: gethABI.BytesTy, Size: 4} -func gethABIType(staticType interpreter.StaticType, evmAddressTypeID common.TypeID) (gethABI.Type, bool) { +// var gethTypeBytes32 = gethABI.Type{T: gethABI.BytesTy, Size: 32} + +func gethABIType( + staticType interpreter.StaticType, + evmAddressTypeID common.TypeID, +) (gethABI.Type, bool) { switch staticType { case interpreter.PrimitiveStaticTypeString: return gethTypeString, true @@ -307,11 +327,13 @@ func gethABIType(staticType interpreter.StaticType, evmAddressTypeID common.Type switch staticType := staticType.(type) { case *interpreter.CompositeStaticType: - if staticType.TypeID != evmAddressTypeID { - break + if staticType.TypeID == evmAddressTypeID { + return gethTypeAddress, true } - return gethTypeAddress, true + if staticType.TypeID == "A.0000000000000001.EVM.EVMBytes" { + return gethTypeBytes, true + } case *interpreter.ConstantSizedStaticType: elementGethABIType, ok := gethABIType( @@ -533,6 +555,20 @@ func encodeABI( return gethCommon.Address(bytes), gethTypeAddress, nil } + if value.TypeID() == "A.0000000000000001.EVM.EVMBytes" { + bytesArrayValue := value.GetMember(inter, locationRange, "value") + bytes, err := interpreter.ByteArrayValueToByteSlice( + inter, + bytesArrayValue, + locationRange, + ) + if err != nil { + panic(err) + } + + return bytes, gethTypeBytes, nil + } + case *interpreter.ArrayValue: arrayStaticType := value.Type @@ -901,23 +937,34 @@ func decodeABI( ), nil case *interpreter.CompositeStaticType: - if staticType.TypeID != evmAddressTypeID { - break - } + if staticType.TypeID == evmAddressTypeID { + addr, ok := value.(gethCommon.Address) + if !ok { + break + } - addr, ok := value.(gethCommon.Address) - if !ok { - break + var address types.Address + copy(address[:], addr.Bytes()) + return NewEVMAddress( + inter, + locationRange, + location, + address, + ), nil } - var address types.Address - copy(address[:], addr.Bytes()) - return NewEVMAddress( - inter, - locationRange, - location, - address, - ), nil + if staticType.TypeID == "A.0000000000000001.EVM.EVMBytes" { + bytes, ok := value.([]uint8) + if !ok { + break + } + return NewEVMBytes( + inter, + locationRange, + location, + bytes, + ), nil + } } return nil, abiDecodingError{ diff --git a/fvm/evm/impl/impl.go b/fvm/evm/impl/impl.go index 73e3ff8eb49..56b6a7b1df0 100644 --- a/fvm/evm/impl/impl.go +++ b/fvm/evm/impl/impl.go @@ -150,6 +150,28 @@ func NewEVMAddress( ) } +func NewEVMBytes( + inter *interpreter.Interpreter, + locationRange interpreter.LocationRange, + location common.AddressLocation, + bytes []byte, +) *interpreter.CompositeValue { + return interpreter.NewCompositeValue( + inter, + locationRange, + location, + "EVM.EVMBytes", + common.CompositeKindStructure, + []interpreter.CompositeField{ + { + Name: "value", + Value: EVMBytesToBytesArrayValue(inter, bytes), + }, + }, + common.ZeroAddress, + ) +} + func AddressBytesArrayValueToEVMAddress( inter *interpreter.Interpreter, locationRange interpreter.LocationRange, @@ -210,6 +232,29 @@ func EVMAddressToAddressBytesArrayValue( ) } +func EVMBytesToBytesArrayValue( + inter *interpreter.Interpreter, + bytes []byte, +) *interpreter.ArrayValue { + var index int + return interpreter.NewArrayValueWithIterator( + inter, + stdlib.EVMBytesValueStaticType, + common.ZeroAddress, + uint64(len(bytes)), + func() interpreter.Value { + if index >= len(bytes) { + return nil + } + result := interpreter.NewUInt8Value(inter, func() uint8 { + return bytes[index] + }) + index++ + return result + }, + ) +} + func newInternalEVMTypeCreateCadenceOwnedAccountFunction( gauge common.MemoryGauge, handler types.ContractHandler, diff --git a/fvm/evm/stdlib/contract.cdc b/fvm/evm/stdlib/contract.cdc index 226a58d2b3c..5c2a720a6f0 100644 --- a/fvm/evm/stdlib/contract.cdc +++ b/fvm/evm/stdlib/contract.cdc @@ -203,6 +203,16 @@ contract EVM { } } + access(all) + struct EVMBytes { + access(all) + let value: [UInt8] + + view init(value: [UInt8]) { + self.value = value + } + } + /// Converts a hex string to an EVM address if the string is a valid hex string /// Future implementations should pass data to InternalEVM for native deserialization access(all) diff --git a/fvm/evm/stdlib/contract.go b/fvm/evm/stdlib/contract.go index 7c580190a07..18434f58e6b 100644 --- a/fvm/evm/stdlib/contract.go +++ b/fvm/evm/stdlib/contract.go @@ -74,6 +74,8 @@ var ( EVMAddressBytesStaticType = interpreter.ConvertSemaArrayTypeToStaticArrayType(nil, EVMAddressBytesType) + EVMBytesValueStaticType = interpreter.ConvertSemaArrayTypeToStaticArrayType(nil, EVMTransactionBytesType) + EVMAddressBytesCadenceType = cadence.NewConstantSizedArrayType(EVMAddressLength, cadence.UInt8Type) ) diff --git a/fvm/evm/stdlib/contract_test.go b/fvm/evm/stdlib/contract_test.go index f64963f59db..f2649d5721c 100644 --- a/fvm/evm/stdlib/contract_test.go +++ b/fvm/evm/stdlib/contract_test.go @@ -455,6 +455,215 @@ func TestEVMEncodeABI(t *testing.T) { assert.Equal(t, computation, uint(len(cdcBytes))) } +func TestEVMEncodeABIBytes(t *testing.T) { + + t.Parallel() + + handler := &testContractHandler{} + + contractsAddress := flow.BytesToAddress([]byte{0x1}) + + transactionEnvironment := newEVMTransactionEnvironment(handler, contractsAddress) + scriptEnvironment := newEVMScriptEnvironment(handler, contractsAddress) + + rt := runtime.NewInterpreterRuntime(runtime.Config{}) + + script := []byte(` + import EVM from 0x1 + + access(all) + fun main(): [UInt8] { + let bytes: EVM.EVMBytes = EVM.EVMBytes(value: [5, 10, 15, 20, 25]) + return EVM.encodeABI([bytes]) + } + `) + + accountCodes := map[common.Location][]byte{} + var events []cadence.Event + + computation := uint(0) + runtimeInterface := &TestRuntimeInterface{ + Storage: NewTestLedger(nil, nil), + OnGetSigningAccounts: func() ([]runtime.Address, error) { + return []runtime.Address{runtime.Address(contractsAddress)}, nil + }, + OnResolveLocation: LocationResolver, + OnUpdateAccountContractCode: func(location common.AddressLocation, code []byte) error { + accountCodes[location] = code + return nil + }, + OnGetAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { + code = accountCodes[location] + return code, nil + }, + OnEmitEvent: func(event cadence.Event) error { + events = append(events, event) + return nil + }, + OnDecodeArgument: func(b []byte, t cadence.Type) (cadence.Value, error) { + return json.Decode(nil, b) + }, + OnMeterComputation: func(compKind common.ComputationKind, intensity uint) error { + if compKind == environment.ComputationKindEVMEncodeABI { + computation += intensity + } + return nil + }, + } + + nextTransactionLocation := NewTransactionLocationGenerator() + nextScriptLocation := NewScriptLocationGenerator() + + // Deploy contracts + + deployContracts( + t, + rt, + contractsAddress, + runtimeInterface, + transactionEnvironment, + nextTransactionLocation, + ) + + // Run script + + result, err := rt.ExecuteScript( + runtime.Script{ + Source: script, + Arguments: [][]byte{}, + }, + runtime.Context{ + Interface: runtimeInterface, + Environment: scriptEnvironment, + Location: nextScriptLocation(), + }, + ) + require.NoError(t, err) + + abiBytes := []byte{ + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5, 0x5, + 0xa, 0xf, 0x14, 0x19, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, + } + cdcBytes := make([]cadence.Value, 0) + for _, bt := range abiBytes { + cdcBytes = append(cdcBytes, cadence.UInt8(bt)) + } + encodedABI := cadence.NewArray( + cdcBytes, + ).WithType(cadence.NewVariableSizedArrayType(cadence.UInt8Type)) + + assert.Equal(t, + encodedABI, + result, + ) + assert.Equal(t, computation, uint(len(cdcBytes))) +} + +func TestEVMEncodeABIBytesRoundtrip(t *testing.T) { + + t.Parallel() + + handler := &testContractHandler{} + + contractsAddress := flow.BytesToAddress([]byte{0x1}) + + transactionEnvironment := newEVMTransactionEnvironment(handler, contractsAddress) + scriptEnvironment := newEVMScriptEnvironment(handler, contractsAddress) + + rt := runtime.NewInterpreterRuntime(runtime.Config{}) + + script := []byte(` + import EVM from 0x1 + + access(all) + fun main(): Bool { + let bytes: EVM.EVMBytes = EVM.EVMBytes(value: [5, 10, 15, 20, 25]) + let encodedData = EVM.encodeABI([bytes]) + let types = [Type()] + let values = EVM.decodeABI(types: types, data: encodedData) + + assert(values.length == 1) + let evmBytes = values[0] as! EVM.EVMBytes + assert(evmBytes.value == [5, 10, 15, 20, 25]) + + return true + } + `) + + accountCodes := map[common.Location][]byte{} + var events []cadence.Event + + computation := uint(0) + runtimeInterface := &TestRuntimeInterface{ + Storage: NewTestLedger(nil, nil), + OnGetSigningAccounts: func() ([]runtime.Address, error) { + return []runtime.Address{runtime.Address(contractsAddress)}, nil + }, + OnResolveLocation: LocationResolver, + OnUpdateAccountContractCode: func(location common.AddressLocation, code []byte) error { + accountCodes[location] = code + return nil + }, + OnGetAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { + code = accountCodes[location] + return code, nil + }, + OnEmitEvent: func(event cadence.Event) error { + events = append(events, event) + return nil + }, + OnDecodeArgument: func(b []byte, t cadence.Type) (cadence.Value, error) { + return json.Decode(nil, b) + }, + OnMeterComputation: func(compKind common.ComputationKind, intensity uint) error { + if compKind == environment.ComputationKindEVMEncodeABI { + computation += intensity + } + return nil + }, + } + + nextTransactionLocation := NewTransactionLocationGenerator() + nextScriptLocation := NewScriptLocationGenerator() + + // Deploy contracts + + deployContracts( + t, + rt, + contractsAddress, + runtimeInterface, + transactionEnvironment, + nextTransactionLocation, + ) + + // Run script + + result, err := rt.ExecuteScript( + runtime.Script{ + Source: script, + Arguments: [][]byte{}, + }, + runtime.Context{ + Interface: runtimeInterface, + Environment: scriptEnvironment, + Location: nextScriptLocation(), + }, + ) + require.NoError(t, err) + + assert.Equal(t, + cadence.Bool(true), + result, + ) +} + func TestEVMEncodeABIComputation(t *testing.T) { t.Parallel() From 9df6f9c7bce12a55330e56cc27e1e1f3cab1a722 Mon Sep 17 00:00:00 2001 From: Ardit Marku Date: Wed, 9 Oct 2024 13:22:08 +0300 Subject: [PATCH 02/15] Add support for ABI encoding/decoding of EVM.EVMBytes4 --- fvm/evm/impl/abi.go | 42 ++++++- fvm/evm/impl/impl.go | 45 +++++++ fvm/evm/stdlib/contract.cdc | 10 ++ fvm/evm/stdlib/contract.go | 2 + fvm/evm/stdlib/contract_test.go | 209 ++++++++++++++++++++++++++++++++ 5 files changed, 307 insertions(+), 1 deletion(-) diff --git a/fvm/evm/impl/abi.go b/fvm/evm/impl/abi.go index e2d971f7d5d..56771a908ff 100644 --- a/fvm/evm/impl/abi.go +++ b/fvm/evm/impl/abi.go @@ -138,6 +138,14 @@ func reportABIEncodingComputation( chunks := math.Ceil(float64(bytesLength) / float64(abiEncodingByteSize)) computation += uint(chunks * abiEncodingByteSize) reportComputation(computation) + } else if value.TypeID() == evmLocation.TypeID(inter, "EVM.EVMBytes4") { + computation := uint(2 * abiEncodingByteSize) + bytesArrayValue := value.GetMember(inter, locationRange, "value") + arrValue := bytesArrayValue.(*interpreter.ArrayValue) + bytesLength := arrValue.Count() + chunks := math.Ceil(float64(bytesLength) / float64(abiEncodingByteSize)) + computation += uint(chunks * abiEncodingByteSize) + reportComputation(computation) } else { panic(abiEncodingError{ Type: value.StaticType(inter), @@ -280,7 +288,7 @@ var gethTypeAddress = gethABI.Type{T: gethABI.AddressTy, Size: 20} var gethTypeBytes = gethABI.Type{T: gethABI.BytesTy} -// var gethTypeBytes4 = gethABI.Type{T: gethABI.BytesTy, Size: 4} +var gethTypeBytes4 = gethABI.Type{T: gethABI.BytesTy, Size: 4} // var gethTypeBytes32 = gethABI.Type{T: gethABI.BytesTy, Size: 32} @@ -335,6 +343,10 @@ func gethABIType( return gethTypeBytes, true } + if staticType.TypeID == "A.0000000000000001.EVM.EVMBytes4" { + return gethTypeBytes4, true + } + case *interpreter.ConstantSizedStaticType: elementGethABIType, ok := gethABIType( staticType.ElementType(), @@ -569,6 +581,20 @@ func encodeABI( return bytes, gethTypeBytes, nil } + if value.TypeID() == "A.0000000000000001.EVM.EVMBytes4" { + bytesArrayValue := value.GetMember(inter, locationRange, "value") + bytes, err := interpreter.ByteArrayValueToByteSlice( + inter, + bytesArrayValue, + locationRange, + ) + if err != nil { + panic(err) + } + + return bytes, gethTypeBytes4, nil + } + case *interpreter.ArrayValue: arrayStaticType := value.Type @@ -965,6 +991,20 @@ func decodeABI( bytes, ), nil } + + if staticType.TypeID == "A.0000000000000001.EVM.EVMBytes4" { + bytes, ok := value.([]uint8) + if !ok { + break + } + compValue := NewEVMBytes4( + inter, + locationRange, + location, + bytes, + ) + return compValue, nil + } } return nil, abiDecodingError{ diff --git a/fvm/evm/impl/impl.go b/fvm/evm/impl/impl.go index 56b6a7b1df0..d558ab5cb15 100644 --- a/fvm/evm/impl/impl.go +++ b/fvm/evm/impl/impl.go @@ -172,6 +172,28 @@ func NewEVMBytes( ) } +func NewEVMBytes4( + inter *interpreter.Interpreter, + locationRange interpreter.LocationRange, + location common.AddressLocation, + bytes []byte, +) *interpreter.CompositeValue { + return interpreter.NewCompositeValue( + inter, + locationRange, + location, + "EVM.EVMBytes4", + common.CompositeKindStructure, + []interpreter.CompositeField{ + { + Name: "value", + Value: EVMBytes4ToBytesArrayValue(inter, bytes), + }, + }, + common.ZeroAddress, + ) +} + func AddressBytesArrayValueToEVMAddress( inter *interpreter.Interpreter, locationRange interpreter.LocationRange, @@ -255,6 +277,29 @@ func EVMBytesToBytesArrayValue( ) } +func EVMBytes4ToBytesArrayValue( + inter *interpreter.Interpreter, + bytes []byte, +) *interpreter.ArrayValue { + var index int + return interpreter.NewArrayValueWithIterator( + inter, + stdlib.EVMBytes4ValueStaticType, + common.ZeroAddress, + uint64(len(bytes)), + func() interpreter.Value { + if index >= len(bytes) { + return nil + } + result := interpreter.NewUInt8Value(inter, func() uint8 { + return bytes[index] + }) + index++ + return result + }, + ) +} + func newInternalEVMTypeCreateCadenceOwnedAccountFunction( gauge common.MemoryGauge, handler types.ContractHandler, diff --git a/fvm/evm/stdlib/contract.cdc b/fvm/evm/stdlib/contract.cdc index 5c2a720a6f0..057b096e97d 100644 --- a/fvm/evm/stdlib/contract.cdc +++ b/fvm/evm/stdlib/contract.cdc @@ -213,6 +213,16 @@ contract EVM { } } + access(all) + struct EVMBytes4 { + access(all) + let value: [UInt8; 4] + + view init(value: [UInt8; 4]) { + self.value = value + } + } + /// Converts a hex string to an EVM address if the string is a valid hex string /// Future implementations should pass data to InternalEVM for native deserialization access(all) diff --git a/fvm/evm/stdlib/contract.go b/fvm/evm/stdlib/contract.go index 18434f58e6b..cc4c85e8819 100644 --- a/fvm/evm/stdlib/contract.go +++ b/fvm/evm/stdlib/contract.go @@ -76,6 +76,8 @@ var ( EVMBytesValueStaticType = interpreter.ConvertSemaArrayTypeToStaticArrayType(nil, EVMTransactionBytesType) + EVMBytes4ValueStaticType = interpreter.ConvertSemaArrayTypeToStaticArrayType(nil, sema.NewConstantSizedType(nil, sema.UInt8Type, 4)) + EVMAddressBytesCadenceType = cadence.NewConstantSizedArrayType(EVMAddressLength, cadence.UInt8Type) ) diff --git a/fvm/evm/stdlib/contract_test.go b/fvm/evm/stdlib/contract_test.go index f2649d5721c..a623719095d 100644 --- a/fvm/evm/stdlib/contract_test.go +++ b/fvm/evm/stdlib/contract_test.go @@ -664,6 +664,215 @@ func TestEVMEncodeABIBytesRoundtrip(t *testing.T) { ) } +func TestEVMEncodeABIBytes4(t *testing.T) { + + t.Parallel() + + handler := &testContractHandler{} + + contractsAddress := flow.BytesToAddress([]byte{0x1}) + + transactionEnvironment := newEVMTransactionEnvironment(handler, contractsAddress) + scriptEnvironment := newEVMScriptEnvironment(handler, contractsAddress) + + rt := runtime.NewInterpreterRuntime(runtime.Config{}) + + script := []byte(` + import EVM from 0x1 + + access(all) + fun main(): [UInt8] { + let bytes: EVM.EVMBytes4 = EVM.EVMBytes4(value: [5, 10, 15, 20]) + return EVM.encodeABI([bytes]) + } + `) + + accountCodes := map[common.Location][]byte{} + var events []cadence.Event + + computation := uint(0) + runtimeInterface := &TestRuntimeInterface{ + Storage: NewTestLedger(nil, nil), + OnGetSigningAccounts: func() ([]runtime.Address, error) { + return []runtime.Address{runtime.Address(contractsAddress)}, nil + }, + OnResolveLocation: LocationResolver, + OnUpdateAccountContractCode: func(location common.AddressLocation, code []byte) error { + accountCodes[location] = code + return nil + }, + OnGetAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { + code = accountCodes[location] + return code, nil + }, + OnEmitEvent: func(event cadence.Event) error { + events = append(events, event) + return nil + }, + OnDecodeArgument: func(b []byte, t cadence.Type) (cadence.Value, error) { + return json.Decode(nil, b) + }, + OnMeterComputation: func(compKind common.ComputationKind, intensity uint) error { + if compKind == environment.ComputationKindEVMEncodeABI { + computation += intensity + } + return nil + }, + } + + nextTransactionLocation := NewTransactionLocationGenerator() + nextScriptLocation := NewScriptLocationGenerator() + + // Deploy contracts + + deployContracts( + t, + rt, + contractsAddress, + runtimeInterface, + transactionEnvironment, + nextTransactionLocation, + ) + + // Run script + + result, err := rt.ExecuteScript( + runtime.Script{ + Source: script, + Arguments: [][]byte{}, + }, + runtime.Context{ + Interface: runtimeInterface, + Environment: scriptEnvironment, + Location: nextScriptLocation(), + }, + ) + require.NoError(t, err) + + abiBytes := []byte{ + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, 0x5, + 0xa, 0xf, 0x14, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, + } + cdcBytes := make([]cadence.Value, 0) + for _, bt := range abiBytes { + cdcBytes = append(cdcBytes, cadence.UInt8(bt)) + } + encodedABI := cadence.NewArray( + cdcBytes, + ).WithType(cadence.NewVariableSizedArrayType(cadence.UInt8Type)) + + assert.Equal(t, + encodedABI, + result, + ) + assert.Equal(t, computation, uint(len(cdcBytes))) +} + +func TestEVMEncodeABIBytes4Roundtrip(t *testing.T) { + + t.Parallel() + + handler := &testContractHandler{} + + contractsAddress := flow.BytesToAddress([]byte{0x1}) + + transactionEnvironment := newEVMTransactionEnvironment(handler, contractsAddress) + scriptEnvironment := newEVMScriptEnvironment(handler, contractsAddress) + + rt := runtime.NewInterpreterRuntime(runtime.Config{}) + + script := []byte(` + import EVM from 0x1 + + access(all) + fun main(): Bool { + let bytes: EVM.EVMBytes4 = EVM.EVMBytes4(value: [5, 10, 15, 20]) + let encodedData = EVM.encodeABI([bytes]) + let types = [Type()] + let values = EVM.decodeABI(types: types, data: encodedData) + + assert(values.length == 1) + let evmBytes = values[0] as! EVM.EVMBytes4 + assert(evmBytes.value == [5, 10, 15, 20]) + + return true + } + `) + + accountCodes := map[common.Location][]byte{} + var events []cadence.Event + + computation := uint(0) + runtimeInterface := &TestRuntimeInterface{ + Storage: NewTestLedger(nil, nil), + OnGetSigningAccounts: func() ([]runtime.Address, error) { + return []runtime.Address{runtime.Address(contractsAddress)}, nil + }, + OnResolveLocation: LocationResolver, + OnUpdateAccountContractCode: func(location common.AddressLocation, code []byte) error { + accountCodes[location] = code + return nil + }, + OnGetAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { + code = accountCodes[location] + return code, nil + }, + OnEmitEvent: func(event cadence.Event) error { + events = append(events, event) + return nil + }, + OnDecodeArgument: func(b []byte, t cadence.Type) (cadence.Value, error) { + return json.Decode(nil, b) + }, + OnMeterComputation: func(compKind common.ComputationKind, intensity uint) error { + if compKind == environment.ComputationKindEVMEncodeABI { + computation += intensity + } + return nil + }, + } + + nextTransactionLocation := NewTransactionLocationGenerator() + nextScriptLocation := NewScriptLocationGenerator() + + // Deploy contracts + + deployContracts( + t, + rt, + contractsAddress, + runtimeInterface, + transactionEnvironment, + nextTransactionLocation, + ) + + // Run script + + result, err := rt.ExecuteScript( + runtime.Script{ + Source: script, + Arguments: [][]byte{}, + }, + runtime.Context{ + Interface: runtimeInterface, + Environment: scriptEnvironment, + Location: nextScriptLocation(), + }, + ) + require.NoError(t, err) + + assert.Equal(t, + cadence.Bool(true), + result, + ) +} + func TestEVMEncodeABIComputation(t *testing.T) { t.Parallel() From 7aef2bdce4728271523ff89eaa01ea48f1ddb479 Mon Sep 17 00:00:00 2001 From: Ardit Marku Date: Wed, 9 Oct 2024 13:31:07 +0300 Subject: [PATCH 03/15] Add support for ABI encoding/decoding of EVM.EVMBytes32 --- fvm/evm/impl/abi.go | 42 +++++- fvm/evm/impl/impl.go | 45 +++++++ fvm/evm/stdlib/contract.cdc | 10 ++ fvm/evm/stdlib/contract.go | 2 + fvm/evm/stdlib/contract_test.go | 226 ++++++++++++++++++++++++++++++++ 5 files changed, 324 insertions(+), 1 deletion(-) diff --git a/fvm/evm/impl/abi.go b/fvm/evm/impl/abi.go index 56771a908ff..68aa43fb00e 100644 --- a/fvm/evm/impl/abi.go +++ b/fvm/evm/impl/abi.go @@ -146,6 +146,14 @@ func reportABIEncodingComputation( chunks := math.Ceil(float64(bytesLength) / float64(abiEncodingByteSize)) computation += uint(chunks * abiEncodingByteSize) reportComputation(computation) + } else if value.TypeID() == evmLocation.TypeID(inter, "EVM.EVMBytes32") { + computation := uint(2 * abiEncodingByteSize) + bytesArrayValue := value.GetMember(inter, locationRange, "value") + arrValue := bytesArrayValue.(*interpreter.ArrayValue) + bytesLength := arrValue.Count() + chunks := math.Ceil(float64(bytesLength) / float64(abiEncodingByteSize)) + computation += uint(chunks * abiEncodingByteSize) + reportComputation(computation) } else { panic(abiEncodingError{ Type: value.StaticType(inter), @@ -290,7 +298,7 @@ var gethTypeBytes = gethABI.Type{T: gethABI.BytesTy} var gethTypeBytes4 = gethABI.Type{T: gethABI.BytesTy, Size: 4} -// var gethTypeBytes32 = gethABI.Type{T: gethABI.BytesTy, Size: 32} +var gethTypeBytes32 = gethABI.Type{T: gethABI.BytesTy, Size: 32} func gethABIType( staticType interpreter.StaticType, @@ -347,6 +355,10 @@ func gethABIType( return gethTypeBytes4, true } + if staticType.TypeID == "A.0000000000000001.EVM.EVMBytes32" { + return gethTypeBytes32, true + } + case *interpreter.ConstantSizedStaticType: elementGethABIType, ok := gethABIType( staticType.ElementType(), @@ -595,6 +607,20 @@ func encodeABI( return bytes, gethTypeBytes4, nil } + if value.TypeID() == "A.0000000000000001.EVM.EVMBytes32" { + bytesArrayValue := value.GetMember(inter, locationRange, "value") + bytes, err := interpreter.ByteArrayValueToByteSlice( + inter, + bytesArrayValue, + locationRange, + ) + if err != nil { + panic(err) + } + + return bytes, gethTypeBytes32, nil + } + case *interpreter.ArrayValue: arrayStaticType := value.Type @@ -1005,6 +1031,20 @@ func decodeABI( ) return compValue, nil } + + if staticType.TypeID == "A.0000000000000001.EVM.EVMBytes32" { + bytes, ok := value.([]uint8) + if !ok { + break + } + compValue := NewEVMBytes32( + inter, + locationRange, + location, + bytes, + ) + return compValue, nil + } } return nil, abiDecodingError{ diff --git a/fvm/evm/impl/impl.go b/fvm/evm/impl/impl.go index d558ab5cb15..169db5e15e2 100644 --- a/fvm/evm/impl/impl.go +++ b/fvm/evm/impl/impl.go @@ -194,6 +194,28 @@ func NewEVMBytes4( ) } +func NewEVMBytes32( + inter *interpreter.Interpreter, + locationRange interpreter.LocationRange, + location common.AddressLocation, + bytes []byte, +) *interpreter.CompositeValue { + return interpreter.NewCompositeValue( + inter, + locationRange, + location, + "EVM.EVMBytes32", + common.CompositeKindStructure, + []interpreter.CompositeField{ + { + Name: "value", + Value: EVMBytes32ToBytesArrayValue(inter, bytes), + }, + }, + common.ZeroAddress, + ) +} + func AddressBytesArrayValueToEVMAddress( inter *interpreter.Interpreter, locationRange interpreter.LocationRange, @@ -300,6 +322,29 @@ func EVMBytes4ToBytesArrayValue( ) } +func EVMBytes32ToBytesArrayValue( + inter *interpreter.Interpreter, + bytes []byte, +) *interpreter.ArrayValue { + var index int + return interpreter.NewArrayValueWithIterator( + inter, + stdlib.EVMBytes32ValueStaticType, + common.ZeroAddress, + uint64(len(bytes)), + func() interpreter.Value { + if index >= len(bytes) { + return nil + } + result := interpreter.NewUInt8Value(inter, func() uint8 { + return bytes[index] + }) + index++ + return result + }, + ) +} + func newInternalEVMTypeCreateCadenceOwnedAccountFunction( gauge common.MemoryGauge, handler types.ContractHandler, diff --git a/fvm/evm/stdlib/contract.cdc b/fvm/evm/stdlib/contract.cdc index 057b096e97d..68ec36507ef 100644 --- a/fvm/evm/stdlib/contract.cdc +++ b/fvm/evm/stdlib/contract.cdc @@ -223,6 +223,16 @@ contract EVM { } } + access(all) + struct EVMBytes32 { + access(all) + let value: [UInt8; 32] + + view init(value: [UInt8; 32]) { + self.value = value + } + } + /// Converts a hex string to an EVM address if the string is a valid hex string /// Future implementations should pass data to InternalEVM for native deserialization access(all) diff --git a/fvm/evm/stdlib/contract.go b/fvm/evm/stdlib/contract.go index cc4c85e8819..a0cd92583f7 100644 --- a/fvm/evm/stdlib/contract.go +++ b/fvm/evm/stdlib/contract.go @@ -78,6 +78,8 @@ var ( EVMBytes4ValueStaticType = interpreter.ConvertSemaArrayTypeToStaticArrayType(nil, sema.NewConstantSizedType(nil, sema.UInt8Type, 4)) + EVMBytes32ValueStaticType = interpreter.ConvertSemaArrayTypeToStaticArrayType(nil, sema.NewConstantSizedType(nil, sema.UInt8Type, 32)) + EVMAddressBytesCadenceType = cadence.NewConstantSizedArrayType(EVMAddressLength, cadence.UInt8Type) ) diff --git a/fvm/evm/stdlib/contract_test.go b/fvm/evm/stdlib/contract_test.go index a623719095d..4c21e7e0dc0 100644 --- a/fvm/evm/stdlib/contract_test.go +++ b/fvm/evm/stdlib/contract_test.go @@ -873,6 +873,232 @@ func TestEVMEncodeABIBytes4Roundtrip(t *testing.T) { ) } +func TestEVMEncodeABIBytes32(t *testing.T) { + + t.Parallel() + + handler := &testContractHandler{} + + contractsAddress := flow.BytesToAddress([]byte{0x1}) + + transactionEnvironment := newEVMTransactionEnvironment(handler, contractsAddress) + scriptEnvironment := newEVMScriptEnvironment(handler, contractsAddress) + + rt := runtime.NewInterpreterRuntime(runtime.Config{}) + + script := []byte(` + import EVM from 0x1 + + access(all) + fun main(): [UInt8] { + let bytes: EVM.EVMBytes32 = EVM.EVMBytes32( + value: [ + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, + 31, 32 + ] + ) + return EVM.encodeABI([bytes]) + } + `) + + accountCodes := map[common.Location][]byte{} + var events []cadence.Event + + computation := uint(0) + runtimeInterface := &TestRuntimeInterface{ + Storage: NewTestLedger(nil, nil), + OnGetSigningAccounts: func() ([]runtime.Address, error) { + return []runtime.Address{runtime.Address(contractsAddress)}, nil + }, + OnResolveLocation: LocationResolver, + OnUpdateAccountContractCode: func(location common.AddressLocation, code []byte) error { + accountCodes[location] = code + return nil + }, + OnGetAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { + code = accountCodes[location] + return code, nil + }, + OnEmitEvent: func(event cadence.Event) error { + events = append(events, event) + return nil + }, + OnDecodeArgument: func(b []byte, t cadence.Type) (cadence.Value, error) { + return json.Decode(nil, b) + }, + OnMeterComputation: func(compKind common.ComputationKind, intensity uint) error { + if compKind == environment.ComputationKindEVMEncodeABI { + computation += intensity + } + return nil + }, + } + + nextTransactionLocation := NewTransactionLocationGenerator() + nextScriptLocation := NewScriptLocationGenerator() + + // Deploy contracts + + deployContracts( + t, + rt, + contractsAddress, + runtimeInterface, + transactionEnvironment, + nextTransactionLocation, + ) + + // Run script + + result, err := rt.ExecuteScript( + runtime.Script{ + Source: script, + Arguments: [][]byte{}, + }, + runtime.Context{ + Interface: runtimeInterface, + Environment: scriptEnvironment, + Location: nextScriptLocation(), + }, + ) + require.NoError(t, err) + + abiBytes := []byte{ + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x1, + 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, + 0xf, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, + 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, + } + cdcBytes := make([]cadence.Value, 0) + for _, bt := range abiBytes { + cdcBytes = append(cdcBytes, cadence.UInt8(bt)) + } + encodedABI := cadence.NewArray( + cdcBytes, + ).WithType(cadence.NewVariableSizedArrayType(cadence.UInt8Type)) + + assert.Equal(t, + encodedABI, + result, + ) + assert.Equal(t, computation, uint(len(cdcBytes))) +} + +func TestEVMEncodeABIBytes32Roundtrip(t *testing.T) { + + t.Parallel() + + handler := &testContractHandler{} + + contractsAddress := flow.BytesToAddress([]byte{0x1}) + + transactionEnvironment := newEVMTransactionEnvironment(handler, contractsAddress) + scriptEnvironment := newEVMScriptEnvironment(handler, contractsAddress) + + rt := runtime.NewInterpreterRuntime(runtime.Config{}) + + script := []byte(` + import EVM from 0x1 + + access(all) + fun main(): Bool { + let bytes: EVM.EVMBytes32 = EVM.EVMBytes32( + value: [ + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, + 31, 32 + ] + ) + let encodedData = EVM.encodeABI([bytes]) + let types = [Type()] + let values = EVM.decodeABI(types: types, data: encodedData) + + assert(values.length == 1) + let evmBytes = values[0] as! EVM.EVMBytes32 + assert(evmBytes.value == [ + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, + 31, 32 + ] + ) + + return true + } + `) + + accountCodes := map[common.Location][]byte{} + var events []cadence.Event + + computation := uint(0) + runtimeInterface := &TestRuntimeInterface{ + Storage: NewTestLedger(nil, nil), + OnGetSigningAccounts: func() ([]runtime.Address, error) { + return []runtime.Address{runtime.Address(contractsAddress)}, nil + }, + OnResolveLocation: LocationResolver, + OnUpdateAccountContractCode: func(location common.AddressLocation, code []byte) error { + accountCodes[location] = code + return nil + }, + OnGetAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { + code = accountCodes[location] + return code, nil + }, + OnEmitEvent: func(event cadence.Event) error { + events = append(events, event) + return nil + }, + OnDecodeArgument: func(b []byte, t cadence.Type) (cadence.Value, error) { + return json.Decode(nil, b) + }, + OnMeterComputation: func(compKind common.ComputationKind, intensity uint) error { + if compKind == environment.ComputationKindEVMEncodeABI { + computation += intensity + } + return nil + }, + } + + nextTransactionLocation := NewTransactionLocationGenerator() + nextScriptLocation := NewScriptLocationGenerator() + + // Deploy contracts + + deployContracts( + t, + rt, + contractsAddress, + runtimeInterface, + transactionEnvironment, + nextTransactionLocation, + ) + + // Run script + + result, err := rt.ExecuteScript( + runtime.Script{ + Source: script, + Arguments: [][]byte{}, + }, + runtime.Context{ + Interface: runtimeInterface, + Environment: scriptEnvironment, + Location: nextScriptLocation(), + }, + ) + require.NoError(t, err) + + assert.Equal(t, + cadence.Bool(true), + result, + ) +} + func TestEVMEncodeABIComputation(t *testing.T) { t.Parallel() From 4b968c144b620e1f98d4bc89e2a8d3487b9556de Mon Sep 17 00:00:00 2001 From: Ardit Marku Date: Thu, 10 Oct 2024 11:38:10 +0300 Subject: [PATCH 04/15] Rework tests for ABI encoding into Solidity bytes types --- fvm/evm/stdlib/contract_test.go | 435 ++++++++++++-------------------- 1 file changed, 161 insertions(+), 274 deletions(-) diff --git a/fvm/evm/stdlib/contract_test.go b/fvm/evm/stdlib/contract_test.go index 4c21e7e0dc0..65bdf965b7d 100644 --- a/fvm/evm/stdlib/contract_test.go +++ b/fvm/evm/stdlib/contract_test.go @@ -455,29 +455,16 @@ func TestEVMEncodeABI(t *testing.T) { assert.Equal(t, computation, uint(len(cdcBytes))) } -func TestEVMEncodeABIBytes(t *testing.T) { +func TestEVMEncodeABIByteTypes(t *testing.T) { t.Parallel() handler := &testContractHandler{} - contractsAddress := flow.BytesToAddress([]byte{0x1}) - transactionEnvironment := newEVMTransactionEnvironment(handler, contractsAddress) scriptEnvironment := newEVMScriptEnvironment(handler, contractsAddress) - rt := runtime.NewInterpreterRuntime(runtime.Config{}) - script := []byte(` - import EVM from 0x1 - - access(all) - fun main(): [UInt8] { - let bytes: EVM.EVMBytes = EVM.EVMBytes(value: [5, 10, 15, 20, 25]) - return EVM.encodeABI([bytes]) - } - `) - accountCodes := map[common.Location][]byte{} var events []cadence.Event @@ -525,146 +512,173 @@ func TestEVMEncodeABIBytes(t *testing.T) { nextTransactionLocation, ) - // Run script - - result, err := rt.ExecuteScript( - runtime.Script{ - Source: script, - Arguments: [][]byte{}, - }, - runtime.Context{ - Interface: runtimeInterface, - Environment: scriptEnvironment, - Location: nextScriptLocation(), - }, - ) - require.NoError(t, err) - - abiBytes := []byte{ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5, 0x5, - 0xa, 0xf, 0x14, 0x19, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, - } - cdcBytes := make([]cadence.Value, 0) - for _, bt := range abiBytes { - cdcBytes = append(cdcBytes, cadence.UInt8(bt)) - } - encodedABI := cadence.NewArray( - cdcBytes, - ).WithType(cadence.NewVariableSizedArrayType(cadence.UInt8Type)) - - assert.Equal(t, - encodedABI, - result, - ) - assert.Equal(t, computation, uint(len(cdcBytes))) -} - -func TestEVMEncodeABIBytesRoundtrip(t *testing.T) { + t.Run("ABI encode into `bytes` Solidity type", func(t *testing.T) { + script := []byte(` + import EVM from 0x1 - t.Parallel() + access(all) + fun main(): [UInt8] { + let bytes: EVM.EVMBytes = EVM.EVMBytes(value: [5, 10, 15, 20, 25]) + return EVM.encodeABI([bytes]) + } + `) - handler := &testContractHandler{} + // Run script + result, err := rt.ExecuteScript( + runtime.Script{ + Source: script, + Arguments: [][]byte{}, + }, + runtime.Context{ + Interface: runtimeInterface, + Environment: scriptEnvironment, + Location: nextScriptLocation(), + }, + ) + require.NoError(t, err) - contractsAddress := flow.BytesToAddress([]byte{0x1}) + abiBytes := []byte{ + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5, 0x5, + 0xa, 0xf, 0x14, 0x19, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, + } + cdcBytes := make([]cadence.Value, 0) + for _, bt := range abiBytes { + cdcBytes = append(cdcBytes, cadence.UInt8(bt)) + } + encodedABI := cadence.NewArray( + cdcBytes, + ).WithType(cadence.NewVariableSizedArrayType(cadence.UInt8Type)) - transactionEnvironment := newEVMTransactionEnvironment(handler, contractsAddress) - scriptEnvironment := newEVMScriptEnvironment(handler, contractsAddress) + assert.Equal(t, + encodedABI, + result, + ) + assert.Equal(t, computation, uint(len(cdcBytes))) - rt := runtime.NewInterpreterRuntime(runtime.Config{}) + // Reset computation + computation = uint(0) + }) - script := []byte(` - import EVM from 0x1 + t.Run("ABI encode into `bytes4` Solidity type", func(t *testing.T) { + script := []byte(` + import EVM from 0x1 - access(all) - fun main(): Bool { - let bytes: EVM.EVMBytes = EVM.EVMBytes(value: [5, 10, 15, 20, 25]) - let encodedData = EVM.encodeABI([bytes]) - let types = [Type()] - let values = EVM.decodeABI(types: types, data: encodedData) + access(all) + fun main(): [UInt8] { + let bytes: EVM.EVMBytes4 = EVM.EVMBytes4(value: [5, 10, 15, 20]) + return EVM.encodeABI([bytes]) + } + `) - assert(values.length == 1) - let evmBytes = values[0] as! EVM.EVMBytes - assert(evmBytes.value == [5, 10, 15, 20, 25]) + // Run script + result, err := rt.ExecuteScript( + runtime.Script{ + Source: script, + Arguments: [][]byte{}, + }, + runtime.Context{ + Interface: runtimeInterface, + Environment: scriptEnvironment, + Location: nextScriptLocation(), + }, + ) + require.NoError(t, err) - return true - } - `) + abiBytes := []byte{ + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, 0x5, + 0xa, 0xf, 0x14, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, + } + cdcBytes := make([]cadence.Value, 0) + for _, bt := range abiBytes { + cdcBytes = append(cdcBytes, cadence.UInt8(bt)) + } + encodedABI := cadence.NewArray( + cdcBytes, + ).WithType(cadence.NewVariableSizedArrayType(cadence.UInt8Type)) - accountCodes := map[common.Location][]byte{} - var events []cadence.Event + assert.Equal(t, + encodedABI, + result, + ) + assert.Equal(t, computation, uint(len(cdcBytes))) - computation := uint(0) - runtimeInterface := &TestRuntimeInterface{ - Storage: NewTestLedger(nil, nil), - OnGetSigningAccounts: func() ([]runtime.Address, error) { - return []runtime.Address{runtime.Address(contractsAddress)}, nil - }, - OnResolveLocation: LocationResolver, - OnUpdateAccountContractCode: func(location common.AddressLocation, code []byte) error { - accountCodes[location] = code - return nil - }, - OnGetAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { - code = accountCodes[location] - return code, nil - }, - OnEmitEvent: func(event cadence.Event) error { - events = append(events, event) - return nil - }, - OnDecodeArgument: func(b []byte, t cadence.Type) (cadence.Value, error) { - return json.Decode(nil, b) - }, - OnMeterComputation: func(compKind common.ComputationKind, intensity uint) error { - if compKind == environment.ComputationKindEVMEncodeABI { - computation += intensity - } - return nil - }, - } + // Reset computation + computation = uint(0) + }) - nextTransactionLocation := NewTransactionLocationGenerator() - nextScriptLocation := NewScriptLocationGenerator() + t.Run("ABI encode into `bytes32` Solidity type", func(t *testing.T) { + script := []byte(` + import EVM from 0x1 - // Deploy contracts + access(all) + fun main(): [UInt8] { + let bytes: EVM.EVMBytes32 = EVM.EVMBytes32( + value: [ + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, + 31, 32 + ] + ) + return EVM.encodeABI([bytes]) + } + `) - deployContracts( - t, - rt, - contractsAddress, - runtimeInterface, - transactionEnvironment, - nextTransactionLocation, - ) + // Run script + result, err := rt.ExecuteScript( + runtime.Script{ + Source: script, + Arguments: [][]byte{}, + }, + runtime.Context{ + Interface: runtimeInterface, + Environment: scriptEnvironment, + Location: nextScriptLocation(), + }, + ) + require.NoError(t, err) - // Run script + abiBytes := []byte{ + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x1, + 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, + 0xf, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, + 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, + } + cdcBytes := make([]cadence.Value, 0) + for _, bt := range abiBytes { + cdcBytes = append(cdcBytes, cadence.UInt8(bt)) + } + encodedABI := cadence.NewArray( + cdcBytes, + ).WithType(cadence.NewVariableSizedArrayType(cadence.UInt8Type)) - result, err := rt.ExecuteScript( - runtime.Script{ - Source: script, - Arguments: [][]byte{}, - }, - runtime.Context{ - Interface: runtimeInterface, - Environment: scriptEnvironment, - Location: nextScriptLocation(), - }, - ) - require.NoError(t, err) + assert.Equal(t, + encodedABI, + result, + ) + assert.Equal(t, computation, uint(len(cdcBytes))) - assert.Equal(t, - cadence.Bool(true), - result, - ) + // Reset computation + computation = uint(0) + }) } -func TestEVMEncodeABIBytes4(t *testing.T) { +func TestEVMEncodeABIBytesRoundtrip(t *testing.T) { t.Parallel() @@ -681,9 +695,17 @@ func TestEVMEncodeABIBytes4(t *testing.T) { import EVM from 0x1 access(all) - fun main(): [UInt8] { - let bytes: EVM.EVMBytes4 = EVM.EVMBytes4(value: [5, 10, 15, 20]) - return EVM.encodeABI([bytes]) + fun main(): Bool { + let bytes: EVM.EVMBytes = EVM.EVMBytes(value: [5, 10, 15, 20, 25]) + let encodedData = EVM.encodeABI([bytes]) + let types = [Type()] + let values = EVM.decodeABI(types: types, data: encodedData) + + assert(values.length == 1) + let evmBytes = values[0] as! EVM.EVMBytes + assert(evmBytes.value == [5, 10, 15, 20, 25]) + + return true } `) @@ -749,29 +771,10 @@ func TestEVMEncodeABIBytes4(t *testing.T) { ) require.NoError(t, err) - abiBytes := []byte{ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, 0x5, - 0xa, 0xf, 0x14, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, - } - cdcBytes := make([]cadence.Value, 0) - for _, bt := range abiBytes { - cdcBytes = append(cdcBytes, cadence.UInt8(bt)) - } - encodedABI := cadence.NewArray( - cdcBytes, - ).WithType(cadence.NewVariableSizedArrayType(cadence.UInt8Type)) - assert.Equal(t, - encodedABI, + cadence.Bool(true), result, ) - assert.Equal(t, computation, uint(len(cdcBytes))) } func TestEVMEncodeABIBytes4Roundtrip(t *testing.T) { @@ -873,122 +876,6 @@ func TestEVMEncodeABIBytes4Roundtrip(t *testing.T) { ) } -func TestEVMEncodeABIBytes32(t *testing.T) { - - t.Parallel() - - handler := &testContractHandler{} - - contractsAddress := flow.BytesToAddress([]byte{0x1}) - - transactionEnvironment := newEVMTransactionEnvironment(handler, contractsAddress) - scriptEnvironment := newEVMScriptEnvironment(handler, contractsAddress) - - rt := runtime.NewInterpreterRuntime(runtime.Config{}) - - script := []byte(` - import EVM from 0x1 - - access(all) - fun main(): [UInt8] { - let bytes: EVM.EVMBytes32 = EVM.EVMBytes32( - value: [ - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, - 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, - 31, 32 - ] - ) - return EVM.encodeABI([bytes]) - } - `) - - accountCodes := map[common.Location][]byte{} - var events []cadence.Event - - computation := uint(0) - runtimeInterface := &TestRuntimeInterface{ - Storage: NewTestLedger(nil, nil), - OnGetSigningAccounts: func() ([]runtime.Address, error) { - return []runtime.Address{runtime.Address(contractsAddress)}, nil - }, - OnResolveLocation: LocationResolver, - OnUpdateAccountContractCode: func(location common.AddressLocation, code []byte) error { - accountCodes[location] = code - return nil - }, - OnGetAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { - code = accountCodes[location] - return code, nil - }, - OnEmitEvent: func(event cadence.Event) error { - events = append(events, event) - return nil - }, - OnDecodeArgument: func(b []byte, t cadence.Type) (cadence.Value, error) { - return json.Decode(nil, b) - }, - OnMeterComputation: func(compKind common.ComputationKind, intensity uint) error { - if compKind == environment.ComputationKindEVMEncodeABI { - computation += intensity - } - return nil - }, - } - - nextTransactionLocation := NewTransactionLocationGenerator() - nextScriptLocation := NewScriptLocationGenerator() - - // Deploy contracts - - deployContracts( - t, - rt, - contractsAddress, - runtimeInterface, - transactionEnvironment, - nextTransactionLocation, - ) - - // Run script - - result, err := rt.ExecuteScript( - runtime.Script{ - Source: script, - Arguments: [][]byte{}, - }, - runtime.Context{ - Interface: runtimeInterface, - Environment: scriptEnvironment, - Location: nextScriptLocation(), - }, - ) - require.NoError(t, err) - - abiBytes := []byte{ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x1, - 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, - 0xf, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, - 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, - } - cdcBytes := make([]cadence.Value, 0) - for _, bt := range abiBytes { - cdcBytes = append(cdcBytes, cadence.UInt8(bt)) - } - encodedABI := cadence.NewArray( - cdcBytes, - ).WithType(cadence.NewVariableSizedArrayType(cadence.UInt8Type)) - - assert.Equal(t, - encodedABI, - result, - ) - assert.Equal(t, computation, uint(len(cdcBytes))) -} - func TestEVMEncodeABIBytes32Roundtrip(t *testing.T) { t.Parallel() From 413a92d1d239307be67404e8360b2905d6f93d6b Mon Sep 17 00:00:00 2001 From: Ardit Marku Date: Thu, 10 Oct 2024 11:53:41 +0300 Subject: [PATCH 05/15] Rework tests for ABI encoding/decoding into Solidity bytes types --- fvm/evm/stdlib/contract_test.go | 346 +++++++++++--------------------- 1 file changed, 115 insertions(+), 231 deletions(-) diff --git a/fvm/evm/stdlib/contract_test.go b/fvm/evm/stdlib/contract_test.go index 65bdf965b7d..bf725faa1ba 100644 --- a/fvm/evm/stdlib/contract_test.go +++ b/fvm/evm/stdlib/contract_test.go @@ -502,7 +502,6 @@ func TestEVMEncodeABIByteTypes(t *testing.T) { nextScriptLocation := NewScriptLocationGenerator() // Deploy contracts - deployContracts( t, rt, @@ -683,32 +682,11 @@ func TestEVMEncodeABIBytesRoundtrip(t *testing.T) { t.Parallel() handler := &testContractHandler{} - contractsAddress := flow.BytesToAddress([]byte{0x1}) - transactionEnvironment := newEVMTransactionEnvironment(handler, contractsAddress) scriptEnvironment := newEVMScriptEnvironment(handler, contractsAddress) - rt := runtime.NewInterpreterRuntime(runtime.Config{}) - script := []byte(` - import EVM from 0x1 - - access(all) - fun main(): Bool { - let bytes: EVM.EVMBytes = EVM.EVMBytes(value: [5, 10, 15, 20, 25]) - let encodedData = EVM.encodeABI([bytes]) - let types = [Type()] - let values = EVM.decodeABI(types: types, data: encodedData) - - assert(values.length == 1) - let evmBytes = values[0] as! EVM.EVMBytes - assert(evmBytes.value == [5, 10, 15, 20, 25]) - - return true - } - `) - accountCodes := map[common.Location][]byte{} var events []cadence.Event @@ -735,7 +713,7 @@ func TestEVMEncodeABIBytesRoundtrip(t *testing.T) { return json.Decode(nil, b) }, OnMeterComputation: func(compKind common.ComputationKind, intensity uint) error { - if compKind == environment.ComputationKindEVMEncodeABI { + if compKind == environment.ComputationKindEVMDecodeABI { computation += intensity } return nil @@ -746,7 +724,6 @@ func TestEVMEncodeABIBytesRoundtrip(t *testing.T) { nextScriptLocation := NewScriptLocationGenerator() // Deploy contracts - deployContracts( t, rt, @@ -756,234 +733,141 @@ func TestEVMEncodeABIBytesRoundtrip(t *testing.T) { nextTransactionLocation, ) - // Run script - - result, err := rt.ExecuteScript( - runtime.Script{ - Source: script, - Arguments: [][]byte{}, - }, - runtime.Context{ - Interface: runtimeInterface, - Environment: scriptEnvironment, - Location: nextScriptLocation(), - }, - ) - require.NoError(t, err) - - assert.Equal(t, - cadence.Bool(true), - result, - ) -} - -func TestEVMEncodeABIBytes4Roundtrip(t *testing.T) { - - t.Parallel() - - handler := &testContractHandler{} - - contractsAddress := flow.BytesToAddress([]byte{0x1}) - - transactionEnvironment := newEVMTransactionEnvironment(handler, contractsAddress) - scriptEnvironment := newEVMScriptEnvironment(handler, contractsAddress) - - rt := runtime.NewInterpreterRuntime(runtime.Config{}) - - script := []byte(` - import EVM from 0x1 - - access(all) - fun main(): Bool { - let bytes: EVM.EVMBytes4 = EVM.EVMBytes4(value: [5, 10, 15, 20]) - let encodedData = EVM.encodeABI([bytes]) - let types = [Type()] - let values = EVM.decodeABI(types: types, data: encodedData) - - assert(values.length == 1) - let evmBytes = values[0] as! EVM.EVMBytes4 - assert(evmBytes.value == [5, 10, 15, 20]) - - return true - } - `) - - accountCodes := map[common.Location][]byte{} - var events []cadence.Event - - computation := uint(0) - runtimeInterface := &TestRuntimeInterface{ - Storage: NewTestLedger(nil, nil), - OnGetSigningAccounts: func() ([]runtime.Address, error) { - return []runtime.Address{runtime.Address(contractsAddress)}, nil - }, - OnResolveLocation: LocationResolver, - OnUpdateAccountContractCode: func(location common.AddressLocation, code []byte) error { - accountCodes[location] = code - return nil - }, - OnGetAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { - code = accountCodes[location] - return code, nil - }, - OnEmitEvent: func(event cadence.Event) error { - events = append(events, event) - return nil - }, - OnDecodeArgument: func(b []byte, t cadence.Type) (cadence.Value, error) { - return json.Decode(nil, b) - }, - OnMeterComputation: func(compKind common.ComputationKind, intensity uint) error { - if compKind == environment.ComputationKindEVMEncodeABI { - computation += intensity - } - return nil - }, - } - - nextTransactionLocation := NewTransactionLocationGenerator() - nextScriptLocation := NewScriptLocationGenerator() - - // Deploy contracts - - deployContracts( - t, - rt, - contractsAddress, - runtimeInterface, - transactionEnvironment, - nextTransactionLocation, - ) + t.Run("ABI encode/decode into `bytes` Solidity type", func(t *testing.T) { + script := []byte(` + import EVM from 0x1 - // Run script + access(all) + fun main(): Bool { + let bytes: EVM.EVMBytes = EVM.EVMBytes(value: [5, 10, 15, 20, 25]) + let encodedData = EVM.encodeABI([bytes]) + let types = [Type()] + let values = EVM.decodeABI(types: types, data: encodedData) - result, err := rt.ExecuteScript( - runtime.Script{ - Source: script, - Arguments: [][]byte{}, - }, - runtime.Context{ - Interface: runtimeInterface, - Environment: scriptEnvironment, - Location: nextScriptLocation(), - }, - ) - require.NoError(t, err) + assert(values.length == 1) + let evmBytes = values[0] as! EVM.EVMBytes + assert(evmBytes.value == [5, 10, 15, 20, 25]) - assert.Equal(t, - cadence.Bool(true), - result, - ) -} + return true + } + `) -func TestEVMEncodeABIBytes32Roundtrip(t *testing.T) { + // Run script + result, err := rt.ExecuteScript( + runtime.Script{ + Source: script, + Arguments: [][]byte{}, + }, + runtime.Context{ + Interface: runtimeInterface, + Environment: scriptEnvironment, + Location: nextScriptLocation(), + }, + ) + require.NoError(t, err) - t.Parallel() + assert.Equal(t, + cadence.Bool(true), + result, + ) - handler := &testContractHandler{} + // Reset computation + computation = uint(0) + }) - contractsAddress := flow.BytesToAddress([]byte{0x1}) + t.Run("ABI encode/decode into `bytes4` Solidity type", func(t *testing.T) { + script := []byte(` + import EVM from 0x1 - transactionEnvironment := newEVMTransactionEnvironment(handler, contractsAddress) - scriptEnvironment := newEVMScriptEnvironment(handler, contractsAddress) + access(all) + fun main(): Bool { + let bytes: EVM.EVMBytes4 = EVM.EVMBytes4(value: [5, 10, 15, 20]) + let encodedData = EVM.encodeABI([bytes]) + let types = [Type()] + let values = EVM.decodeABI(types: types, data: encodedData) - rt := runtime.NewInterpreterRuntime(runtime.Config{}) + assert(values.length == 1) + let evmBytes = values[0] as! EVM.EVMBytes4 + assert(evmBytes.value == [5, 10, 15, 20]) - script := []byte(` - import EVM from 0x1 + return true + } + `) - access(all) - fun main(): Bool { - let bytes: EVM.EVMBytes32 = EVM.EVMBytes32( - value: [ - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, - 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, - 31, 32 - ] + // Run script + result, err := rt.ExecuteScript( + runtime.Script{ + Source: script, + Arguments: [][]byte{}, + }, + runtime.Context{ + Interface: runtimeInterface, + Environment: scriptEnvironment, + Location: nextScriptLocation(), + }, ) - let encodedData = EVM.encodeABI([bytes]) - let types = [Type()] - let values = EVM.decodeABI(types: types, data: encodedData) + require.NoError(t, err) - assert(values.length == 1) - let evmBytes = values[0] as! EVM.EVMBytes32 - assert(evmBytes.value == [ - 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, - 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, - 31, 32 - ] + assert.Equal(t, + cadence.Bool(true), + result, ) - return true - } - `) - - accountCodes := map[common.Location][]byte{} - var events []cadence.Event - - computation := uint(0) - runtimeInterface := &TestRuntimeInterface{ - Storage: NewTestLedger(nil, nil), - OnGetSigningAccounts: func() ([]runtime.Address, error) { - return []runtime.Address{runtime.Address(contractsAddress)}, nil - }, - OnResolveLocation: LocationResolver, - OnUpdateAccountContractCode: func(location common.AddressLocation, code []byte) error { - accountCodes[location] = code - return nil - }, - OnGetAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { - code = accountCodes[location] - return code, nil - }, - OnEmitEvent: func(event cadence.Event) error { - events = append(events, event) - return nil - }, - OnDecodeArgument: func(b []byte, t cadence.Type) (cadence.Value, error) { - return json.Decode(nil, b) - }, - OnMeterComputation: func(compKind common.ComputationKind, intensity uint) error { - if compKind == environment.ComputationKindEVMEncodeABI { - computation += intensity - } - return nil - }, - } + // Reset computation + computation = uint(0) + }) - nextTransactionLocation := NewTransactionLocationGenerator() - nextScriptLocation := NewScriptLocationGenerator() + t.Run("ABI encode/decode into `bytes32` Solidity type", func(t *testing.T) { + script := []byte(` + import EVM from 0x1 - // Deploy contracts + access(all) + fun main(): Bool { + let bytes: EVM.EVMBytes32 = EVM.EVMBytes32( + value: [ + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, + 31, 32 + ] + ) + let encodedData = EVM.encodeABI([bytes]) + let types = [Type()] + let values = EVM.decodeABI(types: types, data: encodedData) + + assert(values.length == 1) + let evmBytes = values[0] as! EVM.EVMBytes32 + assert(evmBytes.value == [ + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, + 31, 32 + ]) - deployContracts( - t, - rt, - contractsAddress, - runtimeInterface, - transactionEnvironment, - nextTransactionLocation, - ) + return true + } + `) - // Run script + // Run script + result, err := rt.ExecuteScript( + runtime.Script{ + Source: script, + Arguments: [][]byte{}, + }, + runtime.Context{ + Interface: runtimeInterface, + Environment: scriptEnvironment, + Location: nextScriptLocation(), + }, + ) + require.NoError(t, err) - result, err := rt.ExecuteScript( - runtime.Script{ - Source: script, - Arguments: [][]byte{}, - }, - runtime.Context{ - Interface: runtimeInterface, - Environment: scriptEnvironment, - Location: nextScriptLocation(), - }, - ) - require.NoError(t, err) + assert.Equal(t, + cadence.Bool(true), + result, + ) - assert.Equal(t, - cadence.Bool(true), - result, - ) + // Reset computation + computation = uint(0) + }) } func TestEVMEncodeABIComputation(t *testing.T) { From eefda8587f57c38d2547c9dd02d6edc964275070 Mon Sep 17 00:00:00 2001 From: Ardit Marku Date: Thu, 10 Oct 2024 11:55:29 +0300 Subject: [PATCH 06/15] Simplify return values --- fvm/evm/impl/abi.go | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/fvm/evm/impl/abi.go b/fvm/evm/impl/abi.go index 68aa43fb00e..a409a56ae6c 100644 --- a/fvm/evm/impl/abi.go +++ b/fvm/evm/impl/abi.go @@ -1023,13 +1023,12 @@ func decodeABI( if !ok { break } - compValue := NewEVMBytes4( + return NewEVMBytes4( inter, locationRange, location, bytes, - ) - return compValue, nil + ), nil } if staticType.TypeID == "A.0000000000000001.EVM.EVMBytes32" { @@ -1037,13 +1036,12 @@ func decodeABI( if !ok { break } - compValue := NewEVMBytes32( + return NewEVMBytes32( inter, locationRange, location, bytes, - ) - return compValue, nil + ), nil } } From 73cff4ffd15ced6c302fe55a37ff93074e1d1ed7 Mon Sep 17 00:00:00 2001 From: Ardit Marku Date: Thu, 10 Oct 2024 11:57:23 +0300 Subject: [PATCH 07/15] Simplify checks for calculating ABI encoding/decoding computation --- fvm/evm/impl/abi.go | 18 +----------------- 1 file changed, 1 insertion(+), 17 deletions(-) diff --git a/fvm/evm/impl/abi.go b/fvm/evm/impl/abi.go index a409a56ae6c..c79e67e6cd5 100644 --- a/fvm/evm/impl/abi.go +++ b/fvm/evm/impl/abi.go @@ -130,23 +130,7 @@ func reportABIEncodingComputation( // EVM addresses are static variables with a fixed // size of 32 bytes. reportComputation(abiEncodingByteSize) - } else if value.TypeID() == evmBytesTypeID { - computation := uint(2 * abiEncodingByteSize) - bytesArrayValue := value.GetMember(inter, locationRange, "value") - arrValue := bytesArrayValue.(*interpreter.ArrayValue) - bytesLength := arrValue.Count() - chunks := math.Ceil(float64(bytesLength) / float64(abiEncodingByteSize)) - computation += uint(chunks * abiEncodingByteSize) - reportComputation(computation) - } else if value.TypeID() == evmLocation.TypeID(inter, "EVM.EVMBytes4") { - computation := uint(2 * abiEncodingByteSize) - bytesArrayValue := value.GetMember(inter, locationRange, "value") - arrValue := bytesArrayValue.(*interpreter.ArrayValue) - bytesLength := arrValue.Count() - chunks := math.Ceil(float64(bytesLength) / float64(abiEncodingByteSize)) - computation += uint(chunks * abiEncodingByteSize) - reportComputation(computation) - } else if value.TypeID() == evmLocation.TypeID(inter, "EVM.EVMBytes32") { + } else if value.TypeID() == evmBytesTypeID || value.TypeID() == evmLocation.TypeID(inter, "EVM.EVMBytes4") || value.TypeID() == evmLocation.TypeID(inter, "EVM.EVMBytes32") { computation := uint(2 * abiEncodingByteSize) bytesArrayValue := value.GetMember(inter, locationRange, "value") arrValue := bytesArrayValue.(*interpreter.ArrayValue) From ba42eef5994de758d34cedefca65f6e51d661a43 Mon Sep 17 00:00:00 2001 From: Ardit Marku Date: Thu, 10 Oct 2024 12:27:01 +0300 Subject: [PATCH 08/15] Add support for slices of Solidity bytes types --- fvm/evm/impl/abi.go | 12 +++ fvm/evm/stdlib/contract_test.go | 186 ++++++++++++++++++++++++++++++++ 2 files changed, 198 insertions(+) diff --git a/fvm/evm/impl/abi.go b/fvm/evm/impl/abi.go index c79e67e6cd5..5828431225e 100644 --- a/fvm/evm/impl/abi.go +++ b/fvm/evm/impl/abi.go @@ -440,6 +440,18 @@ func goType( return reflect.TypeOf(gethCommon.Address{}), true } + if staticType.ID() == "A.0000000000000001.EVM.EVMBytes" { + return reflect.SliceOf(reflect.TypeOf(byte(0))), true + } + + if staticType.ID() == "A.0000000000000001.EVM.EVMBytes4" { + return reflect.SliceOf(reflect.TypeOf(byte(0))), true + } + + if staticType.ID() == "A.0000000000000001.EVM.EVMBytes32" { + return reflect.SliceOf(reflect.TypeOf(byte(0))), true + } + return nil, false } diff --git a/fvm/evm/stdlib/contract_test.go b/fvm/evm/stdlib/contract_test.go index bf725faa1ba..d9bb51fa4a7 100644 --- a/fvm/evm/stdlib/contract_test.go +++ b/fvm/evm/stdlib/contract_test.go @@ -564,6 +564,66 @@ func TestEVMEncodeABIByteTypes(t *testing.T) { computation = uint(0) }) + t.Run("ABI encode into `bytes[]` Solidity type", func(t *testing.T) { + script := []byte(` + import EVM from 0x1 + + access(all) + fun main(): [UInt8] { + let bytes: EVM.EVMBytes = EVM.EVMBytes(value: [5, 10, 15, 20, 25]) + let bytesArray: [EVM.EVMBytes] = [bytes] + return EVM.encodeABI([bytesArray]) + } + `) + + // Run script + result, err := rt.ExecuteScript( + runtime.Script{ + Source: script, + Arguments: [][]byte{}, + }, + runtime.Context{ + Interface: runtimeInterface, + Environment: scriptEnvironment, + Location: nextScriptLocation(), + }, + ) + require.NoError(t, err) + + abiBytes := []byte{ + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5, 0x5, 0xa, 0xf, 0x14, + 0x19, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, + } + cdcBytes := make([]cadence.Value, 0) + for _, bt := range abiBytes { + cdcBytes = append(cdcBytes, cadence.UInt8(bt)) + } + encodedABI := cadence.NewArray( + cdcBytes, + ).WithType(cadence.NewVariableSizedArrayType(cadence.UInt8Type)) + + assert.Equal(t, + encodedABI, + result, + ) + assert.Equal(t, computation, uint(len(cdcBytes))) + + // Reset computation + computation = uint(0) + }) + t.Run("ABI encode into `bytes4` Solidity type", func(t *testing.T) { script := []byte(` import EVM from 0x1 @@ -617,6 +677,66 @@ func TestEVMEncodeABIByteTypes(t *testing.T) { computation = uint(0) }) + t.Run("ABI encode into `bytes4[]` Solidity type", func(t *testing.T) { + script := []byte(` + import EVM from 0x1 + + access(all) + fun main(): [UInt8] { + let bytes: EVM.EVMBytes4 = EVM.EVMBytes4(value: [5, 10, 15, 20]) + let bytesArray: [EVM.EVMBytes4] = [bytes] + return EVM.encodeABI([bytesArray]) + } + `) + + // Run script + result, err := rt.ExecuteScript( + runtime.Script{ + Source: script, + Arguments: [][]byte{}, + }, + runtime.Context{ + Interface: runtimeInterface, + Environment: scriptEnvironment, + Location: nextScriptLocation(), + }, + ) + require.NoError(t, err) + + abiBytes := []byte{ + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, 0x5, 0xa, 0xf, 0x14, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, + } + cdcBytes := make([]cadence.Value, 0) + for _, bt := range abiBytes { + cdcBytes = append(cdcBytes, cadence.UInt8(bt)) + } + encodedABI := cadence.NewArray( + cdcBytes, + ).WithType(cadence.NewVariableSizedArrayType(cadence.UInt8Type)) + + assert.Equal(t, + encodedABI, + result, + ) + assert.Equal(t, computation, uint(len(cdcBytes))) + + // Reset computation + computation = uint(0) + }) + t.Run("ABI encode into `bytes32` Solidity type", func(t *testing.T) { script := []byte(` import EVM from 0x1 @@ -675,6 +795,72 @@ func TestEVMEncodeABIByteTypes(t *testing.T) { // Reset computation computation = uint(0) }) + + t.Run("ABI encode into `bytes32[]` Solidity type", func(t *testing.T) { + script := []byte(` + import EVM from 0x1 + + access(all) + fun main(): [UInt8] { + let bytes: EVM.EVMBytes32 = EVM.EVMBytes32( + value: [ + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, + 31, 32 + ] + ) + let bytesArray: [EVM.EVMBytes32] = [bytes] + return EVM.encodeABI([bytesArray]) + } + `) + + // Run script + result, err := rt.ExecuteScript( + runtime.Script{ + Source: script, + Arguments: [][]byte{}, + }, + runtime.Context{ + Interface: runtimeInterface, + Environment: scriptEnvironment, + Location: nextScriptLocation(), + }, + ) + require.NoError(t, err) + + abiBytes := []byte{ + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x1, 0x2, 0x3, 0x4, + 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10, + 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, + 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, + } + cdcBytes := make([]cadence.Value, 0) + for _, bt := range abiBytes { + cdcBytes = append(cdcBytes, cadence.UInt8(bt)) + } + encodedABI := cadence.NewArray( + cdcBytes, + ).WithType(cadence.NewVariableSizedArrayType(cadence.UInt8Type)) + + assert.Equal(t, + encodedABI, + result, + ) + assert.Equal(t, computation, uint(len(cdcBytes))) + + // Reset computation + computation = uint(0) + }) } func TestEVMEncodeABIBytesRoundtrip(t *testing.T) { From 0c2524a44ccd145a7ef6679720f479c76ce85ccb Mon Sep 17 00:00:00 2001 From: Ardit Marku Date: Thu, 10 Oct 2024 12:33:37 +0300 Subject: [PATCH 09/15] Add more tests for ABI encoding/decoding slices of Solidity bytes types --- fvm/evm/stdlib/contract_test.go | 139 ++++++++++++++++++++++++++++++++ 1 file changed, 139 insertions(+) diff --git a/fvm/evm/stdlib/contract_test.go b/fvm/evm/stdlib/contract_test.go index d9bb51fa4a7..e119e4cfd41 100644 --- a/fvm/evm/stdlib/contract_test.go +++ b/fvm/evm/stdlib/contract_test.go @@ -961,6 +961,49 @@ func TestEVMEncodeABIBytesRoundtrip(t *testing.T) { computation = uint(0) }) + t.Run("ABI encode/decode into `bytes[]` Solidity type", func(t *testing.T) { + script := []byte(` + import EVM from 0x1 + + access(all) + fun main(): Bool { + let bytes: EVM.EVMBytes = EVM.EVMBytes(value: [5, 10, 15, 20, 25]) + let bytesArray: [EVM.EVMBytes] = [bytes] + let encodedData = EVM.encodeABI([bytesArray]) + let types = [Type<[EVM.EVMBytes]>()] + let values = EVM.decodeABI(types: types, data: encodedData) + + assert(values.length == 1) + let evmBytes = values[0] as! [EVM.EVMBytes] + assert(evmBytes[0].value == [5, 10, 15, 20, 25]) + + return true + } + `) + + // Run script + result, err := rt.ExecuteScript( + runtime.Script{ + Source: script, + Arguments: [][]byte{}, + }, + runtime.Context{ + Interface: runtimeInterface, + Environment: scriptEnvironment, + Location: nextScriptLocation(), + }, + ) + require.NoError(t, err) + + assert.Equal(t, + cadence.Bool(true), + result, + ) + + // Reset computation + computation = uint(0) + }) + t.Run("ABI encode/decode into `bytes4` Solidity type", func(t *testing.T) { script := []byte(` import EVM from 0x1 @@ -1003,6 +1046,49 @@ func TestEVMEncodeABIBytesRoundtrip(t *testing.T) { computation = uint(0) }) + t.Run("ABI encode/decode into `bytes4[]` Solidity type", func(t *testing.T) { + script := []byte(` + import EVM from 0x1 + + access(all) + fun main(): Bool { + let bytes: EVM.EVMBytes4 = EVM.EVMBytes4(value: [5, 10, 15, 20]) + let bytesArray: [EVM.EVMBytes4] = [bytes] + let encodedData = EVM.encodeABI([bytesArray]) + let types = [Type<[EVM.EVMBytes4]>()] + let values = EVM.decodeABI(types: types, data: encodedData) + + assert(values.length == 1) + let evmBytes = values[0] as! [EVM.EVMBytes4] + assert(evmBytes[0].value == [5, 10, 15, 20]) + + return true + } + `) + + // Run script + result, err := rt.ExecuteScript( + runtime.Script{ + Source: script, + Arguments: [][]byte{}, + }, + runtime.Context{ + Interface: runtimeInterface, + Environment: scriptEnvironment, + Location: nextScriptLocation(), + }, + ) + require.NoError(t, err) + + assert.Equal(t, + cadence.Bool(true), + result, + ) + + // Reset computation + computation = uint(0) + }) + t.Run("ABI encode/decode into `bytes32` Solidity type", func(t *testing.T) { script := []byte(` import EVM from 0x1 @@ -1054,6 +1140,59 @@ func TestEVMEncodeABIBytesRoundtrip(t *testing.T) { // Reset computation computation = uint(0) }) + + t.Run("ABI encode/decode into `bytes32[]` Solidity type", func(t *testing.T) { + script := []byte(` + import EVM from 0x1 + + access(all) + fun main(): Bool { + let bytes: EVM.EVMBytes32 = EVM.EVMBytes32( + value: [ + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, + 31, 32 + ] + ) + let bytesArray: [EVM.EVMBytes32] = [bytes] + let encodedData = EVM.encodeABI([bytesArray]) + let types = [Type<[EVM.EVMBytes32]>()] + let values = EVM.decodeABI(types: types, data: encodedData) + + assert(values.length == 1) + let evmBytes = values[0] as! [EVM.EVMBytes32] + assert(evmBytes[0].value == [ + 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, + 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, + 31, 32 + ]) + + return true + } + `) + + // Run script + result, err := rt.ExecuteScript( + runtime.Script{ + Source: script, + Arguments: [][]byte{}, + }, + runtime.Context{ + Interface: runtimeInterface, + Environment: scriptEnvironment, + Location: nextScriptLocation(), + }, + ) + require.NoError(t, err) + + assert.Equal(t, + cadence.Bool(true), + result, + ) + + // Reset computation + computation = uint(0) + }) } func TestEVMEncodeABIComputation(t *testing.T) { From b90d62dc68111f141084561f7b41adfc45089be9 Mon Sep 17 00:00:00 2001 From: Ardit Marku Date: Thu, 10 Oct 2024 14:09:20 +0300 Subject: [PATCH 10/15] Add constants for EVMBytes Cadence struct --- fvm/evm/impl/abi.go | 19 ++++++++++++++----- fvm/evm/stdlib/contract.go | 8 ++++++++ 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/fvm/evm/impl/abi.go b/fvm/evm/impl/abi.go index 5828431225e..287d37fcee2 100644 --- a/fvm/evm/impl/abi.go +++ b/fvm/evm/impl/abi.go @@ -86,7 +86,9 @@ func reportABIEncodingComputation( reportComputation func(intensity uint), ) { evmAddressTypeID := evmLocation.TypeID(inter, stdlib.EVMAddressTypeQualifiedIdentifier) - evmBytesTypeID := evmLocation.TypeID(inter, "EVM.EVMBytes") + evmBytesTypeID := evmLocation.TypeID(inter, stdlib.EVMBytesTypeQualifiedIdentifier) + evmBytes4TypeID := evmLocation.TypeID(inter, stdlib.EVMBytes4TypeQualifiedIdentifier) + evmBytes32TypeID := evmLocation.TypeID(inter, stdlib.EVMBytes32TypeQualifiedIdentifier) values.Iterate( inter, @@ -126,23 +128,30 @@ func reportABIEncodingComputation( reportComputation(abiEncodingByteSize) case *interpreter.CompositeValue: - if value.TypeID() == evmAddressTypeID { + switch value.TypeID() { + case evmAddressTypeID: // EVM addresses are static variables with a fixed // size of 32 bytes. reportComputation(abiEncodingByteSize) - } else if value.TypeID() == evmBytesTypeID || value.TypeID() == evmLocation.TypeID(inter, "EVM.EVMBytes4") || value.TypeID() == evmLocation.TypeID(inter, "EVM.EVMBytes32") { + + case evmBytesTypeID, + evmBytes4TypeID, + evmBytes32TypeID: + computation := uint(2 * abiEncodingByteSize) - bytesArrayValue := value.GetMember(inter, locationRange, "value") + bytesArrayValue := value.GetMember(inter, locationRange, stdlib.EVMBytesTypeValueFieldName) arrValue := bytesArrayValue.(*interpreter.ArrayValue) bytesLength := arrValue.Count() chunks := math.Ceil(float64(bytesLength) / float64(abiEncodingByteSize)) computation += uint(chunks * abiEncodingByteSize) reportComputation(computation) - } else { + + default: panic(abiEncodingError{ Type: value.StaticType(inter), }) } + case *interpreter.ArrayValue: // Dynamic variables, such as arrays & slices, are encoded // in 2+ chunks of 32 bytes. The first chunk contains diff --git a/fvm/evm/stdlib/contract.go b/fvm/evm/stdlib/contract.go index a0cd92583f7..0db15777f92 100644 --- a/fvm/evm/stdlib/contract.go +++ b/fvm/evm/stdlib/contract.go @@ -46,10 +46,18 @@ const ( EVMAddressTypeBytesFieldName = "bytes" + EVMBytesTypeValueFieldName = "value" + EVMAddressTypeQualifiedIdentifier = "EVM.EVMAddress" EVMBalanceTypeQualifiedIdentifier = "EVM.Balance" + EVMBytesTypeQualifiedIdentifier = "EVM.EVMBytes" + + EVMBytes4TypeQualifiedIdentifier = "EVM.EVMBytes4" + + EVMBytes32TypeQualifiedIdentifier = "EVM.EVMBytes32" + EVMResultTypeQualifiedIdentifier = "EVM.Result" EVMResultTypeStatusFieldName = "status" EVMResultTypeErrorCodeFieldName = "errorCode" From d8631a4dc50ad90eb7701e81ecb309a69715a7b8 Mon Sep 17 00:00:00 2001 From: Ardit Marku Date: Thu, 10 Oct 2024 15:07:57 +0300 Subject: [PATCH 11/15] Add dedicated struct to hold the special type IDs from the EVM contract --- fvm/evm/impl/abi.go | 105 +++++++++++++++++++++++++------------------- 1 file changed, 61 insertions(+), 44 deletions(-) diff --git a/fvm/evm/impl/abi.go b/fvm/evm/impl/abi.go index 287d37fcee2..a5c20a4edab 100644 --- a/fvm/evm/impl/abi.go +++ b/fvm/evm/impl/abi.go @@ -78,17 +78,32 @@ func (e abiDecodingError) Error() string { return b.String() } +type evmSpecialTypeIDs struct { + AddressTypeID common.TypeID + BytesTypeID common.TypeID + Bytes4TypeID common.TypeID + Bytes32TypeID common.TypeID +} + +func NewEVMSpecialTypeIDs( + gauge common.MemoryGauge, + location common.AddressLocation, +) evmSpecialTypeIDs { + return evmSpecialTypeIDs{ + AddressTypeID: location.TypeID(gauge, stdlib.EVMAddressTypeQualifiedIdentifier), + BytesTypeID: location.TypeID(gauge, stdlib.EVMBytesTypeQualifiedIdentifier), + Bytes4TypeID: location.TypeID(gauge, stdlib.EVMBytes4TypeQualifiedIdentifier), + Bytes32TypeID: location.TypeID(gauge, stdlib.EVMBytes32TypeQualifiedIdentifier), + } +} + func reportABIEncodingComputation( inter *interpreter.Interpreter, locationRange interpreter.LocationRange, values *interpreter.ArrayValue, - evmLocation common.AddressLocation, + evmTypeIDs evmSpecialTypeIDs, reportComputation func(intensity uint), ) { - evmAddressTypeID := evmLocation.TypeID(inter, stdlib.EVMAddressTypeQualifiedIdentifier) - evmBytesTypeID := evmLocation.TypeID(inter, stdlib.EVMBytesTypeQualifiedIdentifier) - evmBytes4TypeID := evmLocation.TypeID(inter, stdlib.EVMBytes4TypeQualifiedIdentifier) - evmBytes32TypeID := evmLocation.TypeID(inter, stdlib.EVMBytes32TypeQualifiedIdentifier) values.Iterate( inter, @@ -129,14 +144,14 @@ func reportABIEncodingComputation( case *interpreter.CompositeValue: switch value.TypeID() { - case evmAddressTypeID: + case evmTypeIDs.AddressTypeID: // EVM addresses are static variables with a fixed // size of 32 bytes. reportComputation(abiEncodingByteSize) - case evmBytesTypeID, - evmBytes4TypeID, - evmBytes32TypeID: + case evmTypeIDs.BytesTypeID, + evmTypeIDs.Bytes4TypeID, + evmTypeIDs.Bytes32TypeID: computation := uint(2 * abiEncodingByteSize) bytesArrayValue := value.GetMember(inter, locationRange, stdlib.EVMBytesTypeValueFieldName) @@ -165,7 +180,7 @@ func reportABIEncodingComputation( inter, locationRange, value, - evmLocation, + evmTypeIDs, reportComputation, ) @@ -188,7 +203,7 @@ func newInternalEVMTypeEncodeABIFunction( location common.AddressLocation, ) *interpreter.HostFunctionValue { - evmAddressTypeID := location.TypeID(gauge, stdlib.EVMAddressTypeQualifiedIdentifier) + evmSpecialTypeIDs := NewEVMSpecialTypeIDs(gauge, location) return interpreter.NewStaticHostFunctionValue( gauge, @@ -208,7 +223,7 @@ func newInternalEVMTypeEncodeABIFunction( inter, locationRange, valuesArray, - location, + evmSpecialTypeIDs, func(intensity uint) { inter.ReportComputation(environment.ComputationKindEVMEncodeABI, intensity) }, @@ -227,7 +242,7 @@ func newInternalEVMTypeEncodeABIFunction( locationRange, element, element.StaticType(inter), - evmAddressTypeID, + evmSpecialTypeIDs, ) if err != nil { panic(err) @@ -295,7 +310,7 @@ var gethTypeBytes32 = gethABI.Type{T: gethABI.BytesTy, Size: 32} func gethABIType( staticType interpreter.StaticType, - evmAddressTypeID common.TypeID, + evmTypeIDs evmSpecialTypeIDs, ) (gethABI.Type, bool) { switch staticType { case interpreter.PrimitiveStaticTypeString: @@ -336,26 +351,26 @@ func gethABIType( switch staticType := staticType.(type) { case *interpreter.CompositeStaticType: - if staticType.TypeID == evmAddressTypeID { + if staticType.TypeID == evmTypeIDs.AddressTypeID { return gethTypeAddress, true } - if staticType.TypeID == "A.0000000000000001.EVM.EVMBytes" { + if staticType.TypeID == evmTypeIDs.BytesTypeID { return gethTypeBytes, true } - if staticType.TypeID == "A.0000000000000001.EVM.EVMBytes4" { + if staticType.TypeID == evmTypeIDs.Bytes4TypeID { return gethTypeBytes4, true } - if staticType.TypeID == "A.0000000000000001.EVM.EVMBytes32" { + if staticType.TypeID == evmTypeIDs.Bytes32TypeID { return gethTypeBytes32, true } case *interpreter.ConstantSizedStaticType: elementGethABIType, ok := gethABIType( staticType.ElementType(), - evmAddressTypeID, + evmTypeIDs, ) if !ok { break @@ -370,7 +385,7 @@ func gethABIType( case *interpreter.VariableSizedStaticType: elementGethABIType, ok := gethABIType( staticType.ElementType(), - evmAddressTypeID, + evmTypeIDs, ) if !ok { break @@ -388,7 +403,7 @@ func gethABIType( func goType( staticType interpreter.StaticType, - evmAddressTypeID common.TypeID, + evmTypeIDs evmSpecialTypeIDs, ) (reflect.Type, bool) { switch staticType { case interpreter.PrimitiveStaticTypeString: @@ -429,7 +444,7 @@ func goType( switch staticType := staticType.(type) { case *interpreter.ConstantSizedStaticType: - elementType, ok := goType(staticType.ElementType(), evmAddressTypeID) + elementType, ok := goType(staticType.ElementType(), evmTypeIDs) if !ok { break } @@ -437,7 +452,7 @@ func goType( return reflect.ArrayOf(int(staticType.Size), elementType), true case *interpreter.VariableSizedStaticType: - elementType, ok := goType(staticType.ElementType(), evmAddressTypeID) + elementType, ok := goType(staticType.ElementType(), evmTypeIDs) if !ok { break } @@ -445,19 +460,19 @@ func goType( return reflect.SliceOf(elementType), true } - if staticType.ID() == evmAddressTypeID { + if staticType.ID() == evmTypeIDs.AddressTypeID { return reflect.TypeOf(gethCommon.Address{}), true } - if staticType.ID() == "A.0000000000000001.EVM.EVMBytes" { + if staticType.ID() == evmTypeIDs.BytesTypeID { return reflect.SliceOf(reflect.TypeOf(byte(0))), true } - if staticType.ID() == "A.0000000000000001.EVM.EVMBytes4" { + if staticType.ID() == evmTypeIDs.Bytes4TypeID { return reflect.SliceOf(reflect.TypeOf(byte(0))), true } - if staticType.ID() == "A.0000000000000001.EVM.EVMBytes32" { + if staticType.ID() == evmTypeIDs.Bytes32TypeID { return reflect.SliceOf(reflect.TypeOf(byte(0))), true } @@ -469,7 +484,7 @@ func encodeABI( locationRange interpreter.LocationRange, value interpreter.Value, staticType interpreter.StaticType, - evmAddressTypeID common.TypeID, + evmTypeIDs evmSpecialTypeIDs, ) ( any, gethABI.Type, @@ -570,7 +585,9 @@ func encodeABI( } case *interpreter.CompositeValue: - if value.TypeID() == evmAddressTypeID { + typeID := value.TypeID() + + if typeID == evmTypeIDs.AddressTypeID { addressBytesArrayValue := value.GetMember(inter, locationRange, stdlib.EVMAddressTypeBytesFieldName) bytes, err := interpreter.ByteArrayValueToByteSlice( inter, @@ -584,7 +601,7 @@ func encodeABI( return gethCommon.Address(bytes), gethTypeAddress, nil } - if value.TypeID() == "A.0000000000000001.EVM.EVMBytes" { + if typeID == evmTypeIDs.BytesTypeID { bytesArrayValue := value.GetMember(inter, locationRange, "value") bytes, err := interpreter.ByteArrayValueToByteSlice( inter, @@ -598,7 +615,7 @@ func encodeABI( return bytes, gethTypeBytes, nil } - if value.TypeID() == "A.0000000000000001.EVM.EVMBytes4" { + if typeID == evmTypeIDs.Bytes4TypeID { bytesArrayValue := value.GetMember(inter, locationRange, "value") bytes, err := interpreter.ByteArrayValueToByteSlice( inter, @@ -612,7 +629,7 @@ func encodeABI( return bytes, gethTypeBytes4, nil } - if value.TypeID() == "A.0000000000000001.EVM.EVMBytes32" { + if typeID == evmTypeIDs.Bytes32TypeID { bytesArrayValue := value.GetMember(inter, locationRange, "value") bytes, err := interpreter.ByteArrayValueToByteSlice( inter, @@ -629,14 +646,14 @@ func encodeABI( case *interpreter.ArrayValue: arrayStaticType := value.Type - arrayGethABIType, ok := gethABIType(arrayStaticType, evmAddressTypeID) + arrayGethABIType, ok := gethABIType(arrayStaticType, evmTypeIDs) if !ok { break } elementStaticType := arrayStaticType.ElementType() - elementGoType, ok := goType(elementStaticType, evmAddressTypeID) + elementGoType, ok := goType(elementStaticType, evmTypeIDs) if !ok { break } @@ -663,7 +680,7 @@ func encodeABI( locationRange, element, element.StaticType(inter), - evmAddressTypeID, + evmTypeIDs, ) if err != nil { panic(err) @@ -691,7 +708,7 @@ func newInternalEVMTypeDecodeABIFunction( gauge common.MemoryGauge, location common.AddressLocation, ) *interpreter.HostFunctionValue { - evmAddressTypeID := location.TypeID(gauge, stdlib.EVMAddressTypeQualifiedIdentifier) + evmSpecialTypeIDs := NewEVMSpecialTypeIDs(gauge, location) return interpreter.NewStaticHostFunctionValue( gauge, @@ -735,7 +752,7 @@ func newInternalEVMTypeDecodeABIFunction( staticType := typeValue.Type - gethABITy, ok := gethABIType(staticType, evmAddressTypeID) + gethABITy, ok := gethABIType(staticType, evmSpecialTypeIDs) if !ok { panic(abiDecodingError{ Type: staticType, @@ -780,7 +797,7 @@ func newInternalEVMTypeDecodeABIFunction( decodedValues[index], staticType, location, - evmAddressTypeID, + evmSpecialTypeIDs, ) if err != nil { panic(err) @@ -822,7 +839,7 @@ func decodeABI( value any, staticType interpreter.StaticType, location common.AddressLocation, - evmAddressTypeID common.TypeID, + evmTypeIDs evmSpecialTypeIDs, ) ( interpreter.Value, error, @@ -981,7 +998,7 @@ func decodeABI( element, elementStaticType, location, - evmAddressTypeID, + evmTypeIDs, ) if err != nil { panic(err) @@ -994,7 +1011,7 @@ func decodeABI( ), nil case *interpreter.CompositeStaticType: - if staticType.TypeID == evmAddressTypeID { + if staticType.TypeID == evmTypeIDs.AddressTypeID { addr, ok := value.(gethCommon.Address) if !ok { break @@ -1010,7 +1027,7 @@ func decodeABI( ), nil } - if staticType.TypeID == "A.0000000000000001.EVM.EVMBytes" { + if staticType.TypeID == evmTypeIDs.BytesTypeID { bytes, ok := value.([]uint8) if !ok { break @@ -1023,7 +1040,7 @@ func decodeABI( ), nil } - if staticType.TypeID == "A.0000000000000001.EVM.EVMBytes4" { + if staticType.TypeID == evmTypeIDs.Bytes4TypeID { bytes, ok := value.([]uint8) if !ok { break @@ -1036,7 +1053,7 @@ func decodeABI( ), nil } - if staticType.TypeID == "A.0000000000000001.EVM.EVMBytes32" { + if staticType.TypeID == evmTypeIDs.Bytes32TypeID { bytes, ok := value.([]uint8) if !ok { break From 1f52950a10fbe95534f1926d85c6685a04d971f9 Mon Sep 17 00:00:00 2001 From: Ardit Marku Date: Thu, 10 Oct 2024 15:42:01 +0300 Subject: [PATCH 12/15] Remove hard-coded values in favor of constants --- fvm/evm/impl/abi.go | 30 ++++++++++++++++++------------ fvm/evm/impl/impl.go | 20 ++++++++++---------- fvm/evm/stdlib/contract.cdc | 12 ++++++++++++ fvm/evm/stdlib/contract.go | 16 +++++++++++++--- 4 files changed, 53 insertions(+), 25 deletions(-) diff --git a/fvm/evm/impl/abi.go b/fvm/evm/impl/abi.go index a5c20a4edab..a141e6e19a5 100644 --- a/fvm/evm/impl/abi.go +++ b/fvm/evm/impl/abi.go @@ -154,9 +154,15 @@ func reportABIEncodingComputation( evmTypeIDs.Bytes32TypeID: computation := uint(2 * abiEncodingByteSize) - bytesArrayValue := value.GetMember(inter, locationRange, stdlib.EVMBytesTypeValueFieldName) - arrValue := bytesArrayValue.(*interpreter.ArrayValue) - bytesLength := arrValue.Count() + valueMember := value.GetMember(inter, locationRange, stdlib.EVMBytesTypeValueFieldName) + bytesArray, ok := valueMember.(*interpreter.ArrayValue) + if !ok { + panic(abiEncodingError{ + Type: value.StaticType(inter), + Message: "could not convert value field to array", + }) + } + bytesLength := bytesArray.Count() chunks := math.Ceil(float64(bytesLength) / float64(abiEncodingByteSize)) computation += uint(chunks * abiEncodingByteSize) reportComputation(computation) @@ -602,10 +608,10 @@ func encodeABI( } if typeID == evmTypeIDs.BytesTypeID { - bytesArrayValue := value.GetMember(inter, locationRange, "value") + bytesValue := value.GetMember(inter, locationRange, stdlib.EVMBytesTypeValueFieldName) bytes, err := interpreter.ByteArrayValueToByteSlice( inter, - bytesArrayValue, + bytesValue, locationRange, ) if err != nil { @@ -616,10 +622,10 @@ func encodeABI( } if typeID == evmTypeIDs.Bytes4TypeID { - bytesArrayValue := value.GetMember(inter, locationRange, "value") + bytesValue := value.GetMember(inter, locationRange, stdlib.EVMBytesTypeValueFieldName) bytes, err := interpreter.ByteArrayValueToByteSlice( inter, - bytesArrayValue, + bytesValue, locationRange, ) if err != nil { @@ -630,10 +636,10 @@ func encodeABI( } if typeID == evmTypeIDs.Bytes32TypeID { - bytesArrayValue := value.GetMember(inter, locationRange, "value") + bytesValue := value.GetMember(inter, locationRange, stdlib.EVMBytesTypeValueFieldName) bytes, err := interpreter.ByteArrayValueToByteSlice( inter, - bytesArrayValue, + bytesValue, locationRange, ) if err != nil { @@ -1028,7 +1034,7 @@ func decodeABI( } if staticType.TypeID == evmTypeIDs.BytesTypeID { - bytes, ok := value.([]uint8) + bytes, ok := value.([]byte) if !ok { break } @@ -1041,7 +1047,7 @@ func decodeABI( } if staticType.TypeID == evmTypeIDs.Bytes4TypeID { - bytes, ok := value.([]uint8) + bytes, ok := value.([]byte) if !ok { break } @@ -1054,7 +1060,7 @@ func decodeABI( } if staticType.TypeID == evmTypeIDs.Bytes32TypeID { - bytes, ok := value.([]uint8) + bytes, ok := value.([]byte) if !ok { break } diff --git a/fvm/evm/impl/impl.go b/fvm/evm/impl/impl.go index 169db5e15e2..16d7fcc5e1e 100644 --- a/fvm/evm/impl/impl.go +++ b/fvm/evm/impl/impl.go @@ -160,11 +160,11 @@ func NewEVMBytes( inter, locationRange, location, - "EVM.EVMBytes", + stdlib.EVMBytesTypeQualifiedIdentifier, common.CompositeKindStructure, []interpreter.CompositeField{ { - Name: "value", + Name: stdlib.EVMBytesTypeValueFieldName, Value: EVMBytesToBytesArrayValue(inter, bytes), }, }, @@ -182,11 +182,11 @@ func NewEVMBytes4( inter, locationRange, location, - "EVM.EVMBytes4", + stdlib.EVMBytes4TypeQualifiedIdentifier, common.CompositeKindStructure, []interpreter.CompositeField{ { - Name: "value", + Name: stdlib.EVMBytesTypeValueFieldName, Value: EVMBytes4ToBytesArrayValue(inter, bytes), }, }, @@ -204,11 +204,11 @@ func NewEVMBytes32( inter, locationRange, location, - "EVM.EVMBytes32", + stdlib.EVMBytes32TypeQualifiedIdentifier, common.CompositeKindStructure, []interpreter.CompositeField{ { - Name: "value", + Name: stdlib.EVMBytesTypeValueFieldName, Value: EVMBytes32ToBytesArrayValue(inter, bytes), }, }, @@ -308,9 +308,9 @@ func EVMBytes4ToBytesArrayValue( inter, stdlib.EVMBytes4ValueStaticType, common.ZeroAddress, - uint64(len(bytes)), + stdlib.EVMBytes4Length, func() interpreter.Value { - if index >= len(bytes) { + if index >= stdlib.EVMBytes4Length { return nil } result := interpreter.NewUInt8Value(inter, func() uint8 { @@ -331,9 +331,9 @@ func EVMBytes32ToBytesArrayValue( inter, stdlib.EVMBytes32ValueStaticType, common.ZeroAddress, - uint64(len(bytes)), + stdlib.EVMBytes32Length, func() interpreter.Value { - if index >= len(bytes) { + if index >= stdlib.EVMBytes32Length { return nil } result := interpreter.NewUInt8Value(inter, func() uint8 { diff --git a/fvm/evm/stdlib/contract.cdc b/fvm/evm/stdlib/contract.cdc index 68ec36507ef..986313c50df 100644 --- a/fvm/evm/stdlib/contract.cdc +++ b/fvm/evm/stdlib/contract.cdc @@ -203,8 +203,12 @@ contract EVM { } } + /// EVMBytes is a type wrapper used for ABI encoding/decoding into + /// Solidity `bytes` type access(all) struct EVMBytes { + + /// Byte array representing the `bytes` value access(all) let value: [UInt8] @@ -213,8 +217,12 @@ contract EVM { } } + /// EVMBytes4 is a type wrapper used for ABI encoding/decoding into + /// Solidity `bytes4` type access(all) struct EVMBytes4 { + + /// Byte array representing the `bytes4` value access(all) let value: [UInt8; 4] @@ -223,8 +231,12 @@ contract EVM { } } + /// EVMBytes32 is a type wrapper used for ABI encoding/decoding into + /// Solidity `bytes32` type access(all) struct EVMBytes32 { + + /// Byte array representing the `bytes32` value access(all) let value: [UInt8; 32] diff --git a/fvm/evm/stdlib/contract.go b/fvm/evm/stdlib/contract.go index 0db15777f92..389e15c75a8 100644 --- a/fvm/evm/stdlib/contract.go +++ b/fvm/evm/stdlib/contract.go @@ -71,7 +71,11 @@ const ( EVMBlockTypeQualifiedIdentifier = "EVM.EVMBlock" ) -const EVMAddressLength = 20 +const ( + EVMAddressLength = 20 + EVMBytes4Length = 4 + EVMBytes32Length = 32 +) var ( EVMTransactionBytesCadenceType = cadence.NewVariableSizedArrayType(cadence.UInt8Type) @@ -84,9 +88,15 @@ var ( EVMBytesValueStaticType = interpreter.ConvertSemaArrayTypeToStaticArrayType(nil, EVMTransactionBytesType) - EVMBytes4ValueStaticType = interpreter.ConvertSemaArrayTypeToStaticArrayType(nil, sema.NewConstantSizedType(nil, sema.UInt8Type, 4)) + EVMBytes4ValueStaticType = interpreter.ConvertSemaArrayTypeToStaticArrayType( + nil, + sema.NewConstantSizedType(nil, sema.UInt8Type, EVMBytes4Length), + ) - EVMBytes32ValueStaticType = interpreter.ConvertSemaArrayTypeToStaticArrayType(nil, sema.NewConstantSizedType(nil, sema.UInt8Type, 32)) + EVMBytes32ValueStaticType = interpreter.ConvertSemaArrayTypeToStaticArrayType( + nil, + sema.NewConstantSizedType(nil, sema.UInt8Type, EVMBytes32Length), + ) EVMAddressBytesCadenceType = cadence.NewConstantSizedArrayType(EVMAddressLength, cadence.UInt8Type) ) From c4f7d119e84654b18a728774e78facd74557178b Mon Sep 17 00:00:00 2001 From: Ardit Marku Date: Thu, 10 Oct 2024 17:38:38 +0300 Subject: [PATCH 13/15] Fix ABI encoding/decoding for bytes4 & bytes4 Solidity types --- fvm/evm/impl/abi.go | 33 ++++---- fvm/evm/impl/impl.go | 8 +- fvm/evm/stdlib/contract_test.go | 131 +++++++++++++++++++++----------- 3 files changed, 109 insertions(+), 63 deletions(-) diff --git a/fvm/evm/impl/abi.go b/fvm/evm/impl/abi.go index a141e6e19a5..742bbe12a61 100644 --- a/fvm/evm/impl/abi.go +++ b/fvm/evm/impl/abi.go @@ -149,10 +149,7 @@ func reportABIEncodingComputation( // size of 32 bytes. reportComputation(abiEncodingByteSize) - case evmTypeIDs.BytesTypeID, - evmTypeIDs.Bytes4TypeID, - evmTypeIDs.Bytes32TypeID: - + case evmTypeIDs.BytesTypeID: computation := uint(2 * abiEncodingByteSize) valueMember := value.GetMember(inter, locationRange, stdlib.EVMBytesTypeValueFieldName) bytesArray, ok := valueMember.(*interpreter.ArrayValue) @@ -167,6 +164,12 @@ func reportABIEncodingComputation( computation += uint(chunks * abiEncodingByteSize) reportComputation(computation) + case evmTypeIDs.Bytes4TypeID: + reportComputation(abiEncodingByteSize) + + case evmTypeIDs.Bytes32TypeID: + reportComputation(abiEncodingByteSize) + default: panic(abiEncodingError{ Type: value.StaticType(inter), @@ -266,7 +269,11 @@ func newInternalEVMTypeEncodeABIFunction( encodedValues, err := arguments.Pack(values...) if err != nil { - panic(abiEncodingError{}) + panic( + abiEncodingError{ + Message: err.Error(), + }, + ) } return interpreter.ByteSliceToByteArrayValue(inter, encodedValues) @@ -310,9 +317,9 @@ var gethTypeAddress = gethABI.Type{T: gethABI.AddressTy, Size: 20} var gethTypeBytes = gethABI.Type{T: gethABI.BytesTy} -var gethTypeBytes4 = gethABI.Type{T: gethABI.BytesTy, Size: 4} +var gethTypeBytes4 = gethABI.Type{T: gethABI.FixedBytesTy, Size: 4} -var gethTypeBytes32 = gethABI.Type{T: gethABI.BytesTy, Size: 32} +var gethTypeBytes32 = gethABI.Type{T: gethABI.FixedBytesTy, Size: 32} func gethABIType( staticType interpreter.StaticType, @@ -475,11 +482,11 @@ func goType( } if staticType.ID() == evmTypeIDs.Bytes4TypeID { - return reflect.SliceOf(reflect.TypeOf(byte(0))), true + return reflect.ArrayOf(stdlib.EVMBytes4Length, reflect.TypeOf(byte(0))), true } if staticType.ID() == evmTypeIDs.Bytes32TypeID { - return reflect.SliceOf(reflect.TypeOf(byte(0))), true + return reflect.ArrayOf(stdlib.EVMBytes32Length, reflect.TypeOf(byte(0))), true } return nil, false @@ -632,7 +639,7 @@ func encodeABI( panic(err) } - return bytes, gethTypeBytes4, nil + return [stdlib.EVMBytes4Length]byte(bytes), gethTypeBytes4, nil } if typeID == evmTypeIDs.Bytes32TypeID { @@ -646,7 +653,7 @@ func encodeABI( panic(err) } - return bytes, gethTypeBytes32, nil + return [stdlib.EVMBytes32Length]byte(bytes), gethTypeBytes32, nil } case *interpreter.ArrayValue: @@ -1047,7 +1054,7 @@ func decodeABI( } if staticType.TypeID == evmTypeIDs.Bytes4TypeID { - bytes, ok := value.([]byte) + bytes, ok := value.([stdlib.EVMBytes4Length]byte) if !ok { break } @@ -1060,7 +1067,7 @@ func decodeABI( } if staticType.TypeID == evmTypeIDs.Bytes32TypeID { - bytes, ok := value.([]byte) + bytes, ok := value.([stdlib.EVMBytes32Length]byte) if !ok { break } diff --git a/fvm/evm/impl/impl.go b/fvm/evm/impl/impl.go index 16d7fcc5e1e..f897746f3d6 100644 --- a/fvm/evm/impl/impl.go +++ b/fvm/evm/impl/impl.go @@ -176,7 +176,7 @@ func NewEVMBytes4( inter *interpreter.Interpreter, locationRange interpreter.LocationRange, location common.AddressLocation, - bytes []byte, + bytes [4]byte, ) *interpreter.CompositeValue { return interpreter.NewCompositeValue( inter, @@ -198,7 +198,7 @@ func NewEVMBytes32( inter *interpreter.Interpreter, locationRange interpreter.LocationRange, location common.AddressLocation, - bytes []byte, + bytes [32]byte, ) *interpreter.CompositeValue { return interpreter.NewCompositeValue( inter, @@ -301,7 +301,7 @@ func EVMBytesToBytesArrayValue( func EVMBytes4ToBytesArrayValue( inter *interpreter.Interpreter, - bytes []byte, + bytes [4]byte, ) *interpreter.ArrayValue { var index int return interpreter.NewArrayValueWithIterator( @@ -324,7 +324,7 @@ func EVMBytes4ToBytesArrayValue( func EVMBytes32ToBytesArrayValue( inter *interpreter.Interpreter, - bytes []byte, + bytes [32]byte, ) *interpreter.ArrayValue { var index int return interpreter.NewArrayValueWithIterator( diff --git a/fvm/evm/stdlib/contract_test.go b/fvm/evm/stdlib/contract_test.go index e119e4cfd41..69d8be1670f 100644 --- a/fvm/evm/stdlib/contract_test.go +++ b/fvm/evm/stdlib/contract_test.go @@ -546,6 +546,12 @@ func TestEVMEncodeABIByteTypes(t *testing.T) { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, } + expected := "00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000005050a0f1419000000000000000000000000000000000000000000000000000000" + assert.Equal( + t, + expected, + hex.EncodeToString(abiBytes), + ) cdcBytes := make([]cadence.Value, 0) for _, bt := range abiBytes { cdcBytes = append(cdcBytes, cadence.UInt8(bt)) @@ -570,8 +576,10 @@ func TestEVMEncodeABIByteTypes(t *testing.T) { access(all) fun main(): [UInt8] { - let bytes: EVM.EVMBytes = EVM.EVMBytes(value: [5, 10, 15, 20, 25]) - let bytesArray: [EVM.EVMBytes] = [bytes] + let bytesArray: [EVM.EVMBytes] = [ + EVM.EVMBytes(value: [5]), + EVM.EVMBytes(value: [10]) + ] return EVM.encodeABI([bytesArray]) } `) @@ -596,16 +604,30 @@ func TestEVMEncodeABIByteTypes(t *testing.T) { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x2, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x40, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x80, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, + 0x0, 0x0, 0x0, 0x1, 0x5, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5, 0x5, 0xa, 0xf, 0x14, - 0x19, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0xa, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, } + expected := "00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000000000000000000000000000001050000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010a00000000000000000000000000000000000000000000000000000000000000" + assert.Equal( + t, + expected, + hex.EncodeToString(abiBytes), + ) cdcBytes := make([]cadence.Value, 0) for _, bt := range abiBytes { cdcBytes = append(cdcBytes, cadence.UInt8(bt)) @@ -650,15 +672,16 @@ func TestEVMEncodeABIByteTypes(t *testing.T) { require.NoError(t, err) abiBytes := []byte{ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, 0x5, - 0xa, 0xf, 0x14, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, + 0x5, 0xa, 0xf, 0x14, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, } + expected := "050a0f1400000000000000000000000000000000000000000000000000000000" + assert.Equal( + t, + expected, + hex.EncodeToString(abiBytes), + ) cdcBytes := make([]cadence.Value, 0) for _, bt := range abiBytes { cdcBytes = append(cdcBytes, cadence.UInt8(bt)) @@ -683,8 +706,10 @@ func TestEVMEncodeABIByteTypes(t *testing.T) { access(all) fun main(): [UInt8] { - let bytes: EVM.EVMBytes4 = EVM.EVMBytes4(value: [5, 10, 15, 20]) - let bytesArray: [EVM.EVMBytes4] = [bytes] + let bytesArray: [EVM.EVMBytes4] = [ + EVM.EVMBytes4(value: [5, 10, 15, 20]), + EVM.EVMBytes4(value: [25, 30, 35, 40]) + ] return EVM.encodeABI([bytesArray]) } `) @@ -709,16 +734,19 @@ func TestEVMEncodeABIByteTypes(t *testing.T) { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x2, 0x5, 0xa, 0xf, 0x14, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, 0x5, 0xa, 0xf, 0x14, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x19, 0x1e, 0x23, 0x28, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, } + expected := "00000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000002050a0f1400000000000000000000000000000000000000000000000000000000191e232800000000000000000000000000000000000000000000000000000000" + assert.Equal( + t, + expected, + hex.EncodeToString(abiBytes), + ) cdcBytes := make([]cadence.Value, 0) for _, bt := range abiBytes { cdcBytes = append(cdcBytes, cadence.UInt8(bt)) @@ -769,15 +797,16 @@ func TestEVMEncodeABIByteTypes(t *testing.T) { require.NoError(t, err) abiBytes := []byte{ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x1, - 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, - 0xf, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, - 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, + 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, + 0xd, 0xe, 0xf, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, } + expected := "0102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20" + assert.Equal( + t, + expected, + hex.EncodeToString(abiBytes), + ) cdcBytes := make([]cadence.Value, 0) for _, bt := range abiBytes { cdcBytes = append(cdcBytes, cadence.UInt8(bt)) @@ -802,14 +831,21 @@ func TestEVMEncodeABIByteTypes(t *testing.T) { access(all) fun main(): [UInt8] { - let bytes: EVM.EVMBytes32 = EVM.EVMBytes32( + let bytesA: EVM.EVMBytes32 = EVM.EVMBytes32( value: [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32 ] ) - let bytesArray: [EVM.EVMBytes32] = [bytes] + let bytesB: EVM.EVMBytes32 = EVM.EVMBytes32( + value: [ + 32, 31, 30, 29, 28, 27, 26, 25, 24, 23, 22, 21, 20, 19, + 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, + 2, 1 + ] + ) + let bytesArray: [EVM.EVMBytes32] = [bytesA, bytesB] return EVM.encodeABI([bytesArray]) } `) @@ -829,21 +865,24 @@ func TestEVMEncodeABIByteTypes(t *testing.T) { require.NoError(t, err) abiBytes := []byte{ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x1, 0x2, 0x3, 0x4, - 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, 0xf, 0x10, - 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, 0x1a, - 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x20, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, + 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x2, 0x1, + 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xa, 0xb, 0xc, 0xd, 0xe, + 0xf, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19, + 0x1a, 0x1b, 0x1c, 0x1d, 0x1e, 0x1f, 0x20, 0x20, 0x1f, 0x1e, 0x1d, + 0x1c, 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16, 0x15, 0x14, 0x13, 0x12, + 0x11, 0x10, 0xf, 0xe, 0xd, 0xc, 0xb, 0xa, 0x9, 0x8, 0x7, 0x6, 0x5, + 0x4, 0x3, 0x2, 0x1, } + expected := "000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000020102030405060708090a0b0c0d0e0f101112131415161718191a1b1c1d1e1f20201f1e1d1c1b1a191817161514131211100f0e0d0c0b0a090807060504030201" + assert.Equal( + t, + expected, + hex.EncodeToString(abiBytes), + ) cdcBytes := make([]cadence.Value, 0) for _, bt := range abiBytes { cdcBytes = append(cdcBytes, cadence.UInt8(bt)) From 853543c9952abb4adfcf3fc41bd94fba6ccb555c Mon Sep 17 00:00:00 2001 From: Ardit Marku Date: Wed, 16 Oct 2024 11:04:38 +0300 Subject: [PATCH 14/15] Replace if statements with switch statements --- fvm/evm/impl/abi.go | 60 +++++++++++++++------------------------------ 1 file changed, 20 insertions(+), 40 deletions(-) diff --git a/fvm/evm/impl/abi.go b/fvm/evm/impl/abi.go index 742bbe12a61..50d781c1ca2 100644 --- a/fvm/evm/impl/abi.go +++ b/fvm/evm/impl/abi.go @@ -364,19 +364,14 @@ func gethABIType( switch staticType := staticType.(type) { case *interpreter.CompositeStaticType: - if staticType.TypeID == evmTypeIDs.AddressTypeID { + switch staticType.TypeID { + case evmTypeIDs.AddressTypeID: return gethTypeAddress, true - } - - if staticType.TypeID == evmTypeIDs.BytesTypeID { + case evmTypeIDs.BytesTypeID: return gethTypeBytes, true - } - - if staticType.TypeID == evmTypeIDs.Bytes4TypeID { + case evmTypeIDs.Bytes4TypeID: return gethTypeBytes4, true - } - - if staticType.TypeID == evmTypeIDs.Bytes32TypeID { + case evmTypeIDs.Bytes32TypeID: return gethTypeBytes32, true } @@ -473,19 +468,14 @@ func goType( return reflect.SliceOf(elementType), true } - if staticType.ID() == evmTypeIDs.AddressTypeID { + switch staticType.ID() { + case evmTypeIDs.AddressTypeID: return reflect.TypeOf(gethCommon.Address{}), true - } - - if staticType.ID() == evmTypeIDs.BytesTypeID { + case evmTypeIDs.BytesTypeID: return reflect.SliceOf(reflect.TypeOf(byte(0))), true - } - - if staticType.ID() == evmTypeIDs.Bytes4TypeID { + case evmTypeIDs.Bytes4TypeID: return reflect.ArrayOf(stdlib.EVMBytes4Length, reflect.TypeOf(byte(0))), true - } - - if staticType.ID() == evmTypeIDs.Bytes32TypeID { + case evmTypeIDs.Bytes32TypeID: return reflect.ArrayOf(stdlib.EVMBytes32Length, reflect.TypeOf(byte(0))), true } @@ -598,9 +588,8 @@ func encodeABI( } case *interpreter.CompositeValue: - typeID := value.TypeID() - - if typeID == evmTypeIDs.AddressTypeID { + switch value.TypeID() { + case evmTypeIDs.AddressTypeID: addressBytesArrayValue := value.GetMember(inter, locationRange, stdlib.EVMAddressTypeBytesFieldName) bytes, err := interpreter.ByteArrayValueToByteSlice( inter, @@ -610,11 +599,9 @@ func encodeABI( if err != nil { panic(err) } - return gethCommon.Address(bytes), gethTypeAddress, nil - } - if typeID == evmTypeIDs.BytesTypeID { + case evmTypeIDs.BytesTypeID: bytesValue := value.GetMember(inter, locationRange, stdlib.EVMBytesTypeValueFieldName) bytes, err := interpreter.ByteArrayValueToByteSlice( inter, @@ -624,11 +611,9 @@ func encodeABI( if err != nil { panic(err) } - return bytes, gethTypeBytes, nil - } - if typeID == evmTypeIDs.Bytes4TypeID { + case evmTypeIDs.Bytes4TypeID: bytesValue := value.GetMember(inter, locationRange, stdlib.EVMBytesTypeValueFieldName) bytes, err := interpreter.ByteArrayValueToByteSlice( inter, @@ -638,11 +623,9 @@ func encodeABI( if err != nil { panic(err) } - return [stdlib.EVMBytes4Length]byte(bytes), gethTypeBytes4, nil - } - if typeID == evmTypeIDs.Bytes32TypeID { + case evmTypeIDs.Bytes32TypeID: bytesValue := value.GetMember(inter, locationRange, stdlib.EVMBytesTypeValueFieldName) bytes, err := interpreter.ByteArrayValueToByteSlice( inter, @@ -652,7 +635,6 @@ func encodeABI( if err != nil { panic(err) } - return [stdlib.EVMBytes32Length]byte(bytes), gethTypeBytes32, nil } @@ -1024,7 +1006,8 @@ func decodeABI( ), nil case *interpreter.CompositeStaticType: - if staticType.TypeID == evmTypeIDs.AddressTypeID { + switch staticType.TypeID { + case evmTypeIDs.AddressTypeID: addr, ok := value.(gethCommon.Address) if !ok { break @@ -1038,9 +1021,8 @@ func decodeABI( location, address, ), nil - } - if staticType.TypeID == evmTypeIDs.BytesTypeID { + case evmTypeIDs.BytesTypeID: bytes, ok := value.([]byte) if !ok { break @@ -1051,9 +1033,8 @@ func decodeABI( location, bytes, ), nil - } - if staticType.TypeID == evmTypeIDs.Bytes4TypeID { + case evmTypeIDs.Bytes4TypeID: bytes, ok := value.([stdlib.EVMBytes4Length]byte) if !ok { break @@ -1064,9 +1045,8 @@ func decodeABI( location, bytes, ), nil - } - if staticType.TypeID == evmTypeIDs.Bytes32TypeID { + case evmTypeIDs.Bytes32TypeID: bytes, ok := value.([stdlib.EVMBytes32Length]byte) if !ok { break From f067110dbcc8fcfec0715c43dec762d981efce63 Mon Sep 17 00:00:00 2001 From: Ardit Marku Date: Wed, 16 Oct 2024 11:19:52 +0300 Subject: [PATCH 15/15] Update state commitment expected values --- engine/execution/state/bootstrap/bootstrap_test.go | 2 +- utils/unittest/execution_state.go | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/engine/execution/state/bootstrap/bootstrap_test.go b/engine/execution/state/bootstrap/bootstrap_test.go index 91e4c03002c..e5eb6ab0c73 100644 --- a/engine/execution/state/bootstrap/bootstrap_test.go +++ b/engine/execution/state/bootstrap/bootstrap_test.go @@ -53,7 +53,7 @@ func TestBootstrapLedger(t *testing.T) { } func TestBootstrapLedger_ZeroTokenSupply(t *testing.T) { - expectedStateCommitmentBytes, _ := hex.DecodeString("d4c956063e3d187b73cfe81bbecc75279e055ddd4741b79847faf407999888c0") + expectedStateCommitmentBytes, _ := hex.DecodeString("ee5cf2cc18be411036aafc471b8a1389490491c698d54164612583351188dac6") expectedStateCommitment, err := flow.ToStateCommitment(expectedStateCommitmentBytes) require.NoError(t, err) diff --git a/utils/unittest/execution_state.go b/utils/unittest/execution_state.go index 221d62987e7..80790ac14e7 100644 --- a/utils/unittest/execution_state.go +++ b/utils/unittest/execution_state.go @@ -23,7 +23,7 @@ const ServiceAccountPrivateKeySignAlgo = crypto.ECDSAP256 const ServiceAccountPrivateKeyHashAlgo = hash.SHA2_256 // Pre-calculated state commitment with root account with the above private key -const GenesisStateCommitmentHex = "341a6372c961713e6ed9c975f3a61d036d65c2ff242a374c5b56cbf267a15b20" +const GenesisStateCommitmentHex = "2b6dc29f4fa1e718add5e1ed1ff9198bbe29948ffa662d7d05c74468238a2206" var GenesisStateCommitment flow.StateCommitment @@ -87,10 +87,10 @@ func genesisCommitHexByChainID(chainID flow.ChainID) string { return GenesisStateCommitmentHex } if chainID == flow.Testnet { - return "441731faf7bf1d8d6217cf67ad7e4ab2cda9da614bae14fb5f0a590fe0ce23df" + return "5f7dd293ddbc7311e6b206411b3c48f093269a7d7338ed9af49dd2d334877084" } if chainID == flow.Sandboxnet { return "e1c08b17f9e5896f03fe28dd37ca396c19b26628161506924fbf785834646ea1" } - return "15d74ad1359542b589138868c8c91a0ce5f0b6115171d68cdabf982c4b684553" + return "a86230127ab67b08d98c9601532dee8d4e0e05221d58715f78bf302eede95ce6" }