Contract Class Structure
Restrictions for Simplified Code Checks
Inheritance Rules
- Only one inheritance is allowed from 
ContractBase, generated by the contract plugin as a nested type inContractContainer. - Only one inheritance is allowed from 
CSharpSmartContract. - Only one inheritance is allowed from 
ContractState. - The type inherited from 
ContractStateshould be the element type of theCSharpSmartContractgeneric instance type. 
If these rules are not followed, code deployment will fail.

Field Usage Limitations
In Contract Implementation Class
- Initial values for non-readonly, non-constant fields are not allowed (for both static and non-static fields). This is because their value will reset to 0 or null after the first execution, losing the initial value.
 
Allowed:
class MyContract : MyContractBase
{
  int test;
  static const int test = 2;
}
Not Allowed:
class MyContract : MyContractBase
{
!  int test = 2;
}
class MyContract : MyContractBase
{
  int test;
  public MyContract
  {
!    test = 2;
  }
}
- Only primitive types or the following types are allowed for readonly/constant fields:
Marshaller<T>Method<T, T>MessageParser<T>FieldCodec<T>MapField<T, T>ReadonlyCollection<T>ReadonlyDictionary<T, T>Note: T can only be a primitive type.
 
In Non-Contract Classes (Classes not inheriting from ContractBase<T>)
- Initial values for non-readonly, non-constant static fields are not allowed. They reset to 0 or null after the first execution, losing the initial value.
 
Allowed:
class AnyClass
{
  static int test;
}
Not Allowed:
class AnyClass
{
!  static int test = 2;
}
class AnyClass
{
  static int test;
  public AnyClass
  {
!    test = 2;
  }
}
- Exception: Fields with FileDescriptor types are allowed due to protobuf-generated code. These fields don’t have a readonly modifier and write access to them is allowed only from the constructor of the declaring type.
 
Allowed:
public class TestType
{
  private static FileDescriptor test;
  public class TestType
  {
    test = ...
  }
}
Not Allowed:
public class TestType
{
  private static FileDescriptor test;
  public TestType
  {
    test = ...
  }
!  public void SetFromSomeWhereElse(FileDescriptor input)
!  {
!    test = input;
!  }
}
- 
Accessing test fields is restricted to the declaring type’s constructor only.
 - 
Only the following types are allowed for readonly/constant static fields:
Marshaller<T>Method<T, T>MessageParser<T>FieldCodec<T>MapField<T, T>ReadonlyCollection<T>ReadonlyDictionary<T, T>
 
Note: T can only be a primitive type.
- Exception: If a type has a readonly field of the same type as itself, it is only allowed if the type has no instance fields (to support LINQ-related generated types).
 
Allowed:
public class TestType
{
  private static readonly TestType test;
  private static int i;
}
Not Allowed:
public class TestType
{
  private static readonly TestType test;
!  private int i;
}
In Contract State
In contract state, only the following types are allowed:
Primitive Types
BoolStateInt32StateUInt32StateInt64StateUInt64StateStringStateBytesStateComplex Types
Complex Types
SingletonState<T>ReadonlyState<T>MappedState<T, T>MappedState<T, T, T>MappedState<T, T, T, T>MappedState<T, T, T, T, T>MethodReference<T, T>ProtobufState<T>ContractReferenceStateStructuredState