Skip to content

Commit

Permalink
Merge pull request onflow#6481 from onflow/ramtin/port-6480
Browse files Browse the repository at this point in the history
[EVM] backport of 6480 - handle UInt,Int types for ABI encoding/decoding
  • Loading branch information
ramtinms authored Sep 19, 2024
2 parents ae4ce43 + a80a139 commit 62de9f2
Show file tree
Hide file tree
Showing 2 changed files with 157 additions and 2 deletions.
44 changes: 44 additions & 0 deletions fvm/evm/impl/abi.go
Original file line number Diff line number Diff line change
Expand Up @@ -95,12 +95,14 @@ func reportABIEncodingComputation(
reportComputation(computation)

case interpreter.BoolValue,
interpreter.UIntValue,
interpreter.UInt8Value,
interpreter.UInt16Value,
interpreter.UInt32Value,
interpreter.UInt64Value,
interpreter.UInt128Value,
interpreter.UInt256Value,
interpreter.IntValue,
interpreter.Int8Value,
interpreter.Int16Value,
interpreter.Int32Value,
Expand Down Expand Up @@ -227,6 +229,8 @@ var gethTypeString = gethABI.Type{T: gethABI.StringTy}

var gethTypeBool = gethABI.Type{T: gethABI.BoolTy}

var gethTypeUint = gethABI.Type{T: gethABI.UintTy, Size: 256}

var gethTypeUint8 = gethABI.Type{T: gethABI.UintTy, Size: 8}

var gethTypeUint16 = gethABI.Type{T: gethABI.UintTy, Size: 16}
Expand All @@ -239,6 +243,8 @@ var gethTypeUint128 = gethABI.Type{T: gethABI.UintTy, Size: 128}

var gethTypeUint256 = gethABI.Type{T: gethABI.UintTy, Size: 256}

var gethTypeInt = gethABI.Type{T: gethABI.IntTy, Size: 256}

var gethTypeInt8 = gethABI.Type{T: gethABI.IntTy, Size: 8}

var gethTypeInt16 = gethABI.Type{T: gethABI.IntTy, Size: 16}
Expand All @@ -259,6 +265,8 @@ func gethABIType(staticType interpreter.StaticType, evmAddressTypeID common.Type
return gethTypeString, true
case interpreter.PrimitiveStaticTypeBool:
return gethTypeBool, true
case interpreter.PrimitiveStaticTypeUInt:
return gethTypeUint, true
case interpreter.PrimitiveStaticTypeUInt8:
return gethTypeUint8, true
case interpreter.PrimitiveStaticTypeUInt16:
Expand All @@ -271,6 +279,8 @@ func gethABIType(staticType interpreter.StaticType, evmAddressTypeID common.Type
return gethTypeUint128, true
case interpreter.PrimitiveStaticTypeUInt256:
return gethTypeUint256, true
case interpreter.PrimitiveStaticTypeInt:
return gethTypeInt, true
case interpreter.PrimitiveStaticTypeInt8:
return gethTypeInt8, true
case interpreter.PrimitiveStaticTypeInt16:
Expand Down Expand Up @@ -338,6 +348,8 @@ func goType(
return reflect.TypeOf(""), true
case interpreter.PrimitiveStaticTypeBool:
return reflect.TypeOf(true), true
case interpreter.PrimitiveStaticTypeUInt:
return reflect.TypeOf((*big.Int)(nil)), true
case interpreter.PrimitiveStaticTypeUInt8:
return reflect.TypeOf(uint8(0)), true
case interpreter.PrimitiveStaticTypeUInt16:
Expand All @@ -350,6 +362,8 @@ func goType(
return reflect.TypeOf((*big.Int)(nil)), true
case interpreter.PrimitiveStaticTypeUInt256:
return reflect.TypeOf((*big.Int)(nil)), true
case interpreter.PrimitiveStaticTypeInt:
return reflect.TypeOf((*big.Int)(nil)), true
case interpreter.PrimitiveStaticTypeInt8:
return reflect.TypeOf(int8(0)), true
case interpreter.PrimitiveStaticTypeInt16:
Expand Down Expand Up @@ -414,6 +428,11 @@ func encodeABI(
return bool(value), gethTypeBool, nil
}

case interpreter.UIntValue:
if staticType == interpreter.PrimitiveStaticTypeUInt {
return value.BigInt, gethTypeUint, nil
}

case interpreter.UInt8Value:
if staticType == interpreter.PrimitiveStaticTypeUInt8 {
return uint8(value), gethTypeUint8, nil
Expand Down Expand Up @@ -444,6 +463,11 @@ func encodeABI(
return value.BigInt, gethTypeUint256, nil
}

case interpreter.IntValue:
if staticType == interpreter.PrimitiveStaticTypeInt {
return value.BigInt, gethTypeInt, nil
}

case interpreter.Int8Value:
if staticType == interpreter.PrimitiveStaticTypeInt8 {
return int8(value), gethTypeInt8, nil
Expand Down Expand Up @@ -712,6 +736,16 @@ func decodeABI(
}
return interpreter.BoolValue(value), nil

case interpreter.PrimitiveStaticTypeUInt:
value, ok := value.(*big.Int)
if !ok {
break
}
memoryUsage := common.NewBigIntMemoryUsage(
common.BigIntByteLength(value),
)
return interpreter.NewUIntValueFromBigInt(inter, memoryUsage, func() *big.Int { return value }), nil

case interpreter.PrimitiveStaticTypeUInt8:
value, ok := value.(uint8)
if !ok {
Expand Down Expand Up @@ -754,6 +788,16 @@ func decodeABI(
}
return interpreter.NewUInt256ValueFromBigInt(inter, func() *big.Int { return value }), nil

case interpreter.PrimitiveStaticTypeInt:
value, ok := value.(*big.Int)
if !ok {
break
}
memoryUsage := common.NewBigIntMemoryUsage(
common.BigIntByteLength(value),
)
return interpreter.NewIntValueFromBigInt(inter, memoryUsage, func() *big.Int { return value }), nil

case interpreter.PrimitiveStaticTypeInt8:
value, ok := value.(int8)
if !ok {
Expand Down
115 changes: 113 additions & 2 deletions fvm/evm/stdlib/contract_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -989,6 +989,111 @@ func TestEVMDecodeABIComputation(t *testing.T) {
assert.Equal(t, computation, uint(len(cdcBytes.Values)))
}

func TestEVMEncodeDecodeABIRoundtripForUintIntTypes(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 {
// Check UInt*/Int* encode/decode
let amount: UInt256 = 18446744073709551615
let minBalance: Int256 = -18446744073709551615
let data = EVM.encodeABIWithSignature(
"withdraw(uint,int)",
[UInt(amount), Int(minBalance)]
)
let values = EVM.decodeABIWithSignature(
"withdraw(uint,int)",
types: [Type<UInt>(), Type<Int>()],
data: data
)
assert((values[0] as! UInt) == UInt(amount))
assert((values[1] as! Int) == Int(minBalance))
return true
}
`)

accountCodes := map[common.Location][]byte{}
var events []cadence.Event

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)
},
OnHash: func(
data []byte,
tag string,
hashAlgorithm runtime.HashAlgorithm,
) ([]byte, error) {
return crypto.Keccak256(data), 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 TestEVMEncodeDecodeABIRoundtrip(t *testing.T) {

t.Parallel()
Expand Down Expand Up @@ -1043,7 +1148,9 @@ func TestEVMEncodeDecodeABIRoundtrip(t *testing.T) {
Int32(-33),
Int64(-33),
Int128(-33),
Int256(-33)
Int256(-33),
UInt(33),
Int(-33)
])
values = EVM.decodeABI(
types: [
Expand All @@ -1058,7 +1165,9 @@ func TestEVMEncodeDecodeABIRoundtrip(t *testing.T) {
Type<Int32>(),
Type<Int64>(),
Type<Int128>(),
Type<Int256>()
Type<Int256>(),
Type<UInt>(),
Type<Int>()
],
data: data
)
Expand All @@ -1074,6 +1183,8 @@ func TestEVMEncodeDecodeABIRoundtrip(t *testing.T) {
assert((values[9] as! Int64) == -33)
assert((values[10] as! Int128) == -33)
assert((values[11] as! Int256) == -33)
assert((values[12] as! UInt) == 33)
assert((values[13] as! Int) == -33)
// Check variable-size array of leaf types encode/decode
data = EVM.encodeABI([
Expand Down

0 comments on commit 62de9f2

Please sign in to comment.