diff --git a/migrations/account_type/migration.go b/migrations/account_type/migration.go index e7454e55b8..b3b0502410 100644 --- a/migrations/account_type/migration.go +++ b/migrations/account_type/migration.go @@ -55,6 +55,23 @@ func (AccountTypeMigration) Migrate(value interpreter.Value) (newValue interpret } return interpreter.NewUnmeteredCapabilityValue(value.ID, value.Address, convertedBorrowType) + case *interpreter.AccountCapabilityControllerValue: + convertedBorrowType := maybeConvertAccountType(value.BorrowType) + if convertedBorrowType == nil { + return + } + borrowType := convertedBorrowType.(*interpreter.ReferenceStaticType) + return interpreter.NewUnmeteredAccountCapabilityControllerValue(borrowType, value.CapabilityID) + + case *interpreter.StorageCapabilityControllerValue: + // Note: A storage capability with Account type shouldn't be possible theoretically. + convertedBorrowType := maybeConvertAccountType(value.BorrowType) + if convertedBorrowType == nil { + return + } + borrowType := convertedBorrowType.(*interpreter.ReferenceStaticType) + return interpreter.NewUnmeteredStorageCapabilityControllerValue(borrowType, value.CapabilityID, value.TargetPath) + default: return nil } @@ -94,7 +111,13 @@ func maybeConvertAccountType(staticType interpreter.StaticType) interpreter.Stat } case *interpreter.IntersectionStaticType: - // Nothing to do. Inner types can only be interfaces. + // No need to convert `staticType.Types` as they can only be interfaces. + convertedLegacyType := maybeConvertAccountType(staticType.LegacyType) + if convertedLegacyType != nil { + intersectionType := interpreter.NewIntersectionStaticType(nil, staticType.Types) + intersectionType.LegacyType = convertedLegacyType + return intersectionType + } case *interpreter.OptionalStaticType: convertedInnerType := maybeConvertAccountType(staticType.Type) diff --git a/migrations/account_type/migration_test.go b/migrations/account_type/migration_test.go index bf2c95bc7c..349ef70e5a 100644 --- a/migrations/account_type/migration_test.go +++ b/migrations/account_type/migration_test.go @@ -22,6 +22,7 @@ import ( "fmt" "testing" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "github.com/onflow/atree" @@ -234,6 +235,16 @@ func TestTypeValueMigration(t *testing.T) { []*interpreter.InterfaceStaticType{}, ), }, + "intersection_with_legacy_type": { + storedType: &interpreter.IntersectionStaticType{ + Types: []*interpreter.InterfaceStaticType{}, + LegacyType: publicAccountType, + }, + expectedType: &interpreter.IntersectionStaticType{ + Types: []*interpreter.InterfaceStaticType{}, + LegacyType: unauthorizedAccountReferenceType, + }, + }, "public_account_reference": { storedType: interpreter.NewReferenceStaticType( nil, @@ -390,14 +401,22 @@ func TestTypeValueMigration(t *testing.T) { testCase, ok := testCases[identifier] require.True(t, ok) - var storageValue interpreter.Value + var expectedValue interpreter.Value if testCase.expectedType != nil { - storageValue = interpreter.NewTypeValue(nil, testCase.expectedType) + expectedValue = interpreter.NewTypeValue(nil, testCase.expectedType) + + // `IntersectionType.LegacyType` is not considered in the `IntersectionType.Equal` method. + // Therefore, check for the legacy type equality manually. + typeValue := value.(interpreter.TypeValue) + if actualIntersectionType, ok := typeValue.Type.(*interpreter.IntersectionStaticType); ok { + expectedIntersectionType := testCase.expectedType.(*interpreter.IntersectionStaticType) + assert.True(t, actualIntersectionType.LegacyType.Equal(expectedIntersectionType.LegacyType)) + } } else { - storageValue = interpreter.NewTypeValue(nil, testCase.storedType) + expectedValue = interpreter.NewTypeValue(nil, testCase.storedType) } - utils.AssertValuesEqual(t, inter, storageValue, value) + utils.AssertValuesEqual(t, inter, expectedValue, value) }) } } @@ -737,6 +756,36 @@ func TestValuesWithStaticTypeMigration(t *testing.T) { interpreter.PrimitiveStaticTypeString, ), }, + "account_capability_controller": { + storedValue: interpreter.NewUnmeteredAccountCapabilityControllerValue( + interpreter.NewReferenceStaticType( + nil, + interpreter.UnauthorizedAccess, + interpreter.PrimitiveStaticTypeAuthAccount, //nolint:staticcheck, + ), + 1234, + ), + expectedValue: interpreter.NewUnmeteredAccountCapabilityControllerValue( + authAccountReferenceType, + 1234, + ), + }, + "storage_capability_controller": { + storedValue: interpreter.NewUnmeteredStorageCapabilityControllerValue( + interpreter.NewReferenceStaticType( + nil, + interpreter.UnauthorizedAccess, + interpreter.PrimitiveStaticTypePublicAccount, //nolint:staticcheck, + ), + 1234, + interpreter.NewUnmeteredPathValue(common.PathDomainStorage, "v1"), + ), + expectedValue: interpreter.NewUnmeteredStorageCapabilityControllerValue( + unauthorizedAccountReferenceType, + 1234, + interpreter.NewUnmeteredPathValue(common.PathDomainStorage, "v1"), + ), + }, } // Store values