github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/fvm/errors/execution.go (about)

     1  package errors
     2  
     3  import (
     4  	"github.com/onflow/cadence"
     5  	"github.com/onflow/cadence/runtime"
     6  
     7  	"github.com/onflow/flow-go/model/flow"
     8  )
     9  
    10  // NewCadenceRuntimeError constructs a new CodedError which captures a
    11  // collection of errors provided by cadence runtime. It cover cadence errors
    12  // such as:
    13  //
    14  // NotDeclaredError, NotInvokableError, ArgumentCountError,
    15  // TransactionNotDeclaredError, ConditionError, RedeclarationError,
    16  // DereferenceError, OverflowError, UnderflowError, DivisionByZeroError,
    17  // DestroyedCompositeError,  ForceAssignmentToNonNilResourceError,
    18  // ForceNilError, TypeMismatchError, InvalidPathDomainError, OverwriteError,
    19  // CyclicLinkError, ArrayIndexOutOfBoundsError, ...
    20  //
    21  // The Cadence error might have occurred because of an inner fvm Error.
    22  func NewCadenceRuntimeError(err runtime.Error) CodedError {
    23  	return WrapCodedError(
    24  		ErrCodeCadenceRunTimeError,
    25  		err,
    26  		"cadence runtime error")
    27  }
    28  
    29  func IsCadenceRuntimeError(err error) bool {
    30  	return HasErrorCode(err, ErrCodeCadenceRunTimeError)
    31  }
    32  
    33  // NewTransactionFeeDeductionFailedError constructs a new CodedError which
    34  // indicates that a there was an error deducting transaction fees from the
    35  // transaction Payer
    36  func NewTransactionFeeDeductionFailedError(
    37  	payer flow.Address,
    38  	txFees uint64,
    39  	err error,
    40  ) CodedError {
    41  	return WrapCodedError(
    42  		ErrCodeTransactionFeeDeductionFailedError,
    43  		err,
    44  		"failed to deduct %d transaction fees from %s",
    45  		txFees,
    46  		payer)
    47  }
    48  
    49  // IsTransactionFeeDeductionFailedError returns true if error has this code.
    50  func IsTransactionFeeDeductionFailedError(err error) bool {
    51  	return HasErrorCode(err, ErrCodeTransactionFeeDeductionFailedError)
    52  }
    53  
    54  // NewInsufficientPayerBalanceError constructs a new CodedError which
    55  // indicates that the payer has insufficient balance to attempt transaction execution.
    56  func NewInsufficientPayerBalanceError(
    57  	payer flow.Address,
    58  	requiredBalance cadence.UFix64,
    59  ) CodedError {
    60  	return NewCodedError(
    61  		ErrCodeInsufficientPayerBalance,
    62  		"payer %s has insufficient balance to attempt transaction execution (required balance: %s)",
    63  		payer,
    64  		requiredBalance,
    65  	)
    66  }
    67  
    68  // IsInsufficientPayerBalanceError returns true if error has this code.
    69  func IsInsufficientPayerBalanceError(err error) bool {
    70  	return HasErrorCode(err, ErrCodeInsufficientPayerBalance)
    71  }
    72  
    73  // indicates that a there was an error checking the payers balance.
    74  // This is an implementation error most likely between the smart contract and FVM interaction
    75  // and should not happen in regular execution.
    76  func NewPayerBalanceCheckFailure(
    77  	payer flow.Address,
    78  	err error,
    79  ) CodedFailure {
    80  	return WrapCodedFailure(
    81  		FailureCodePayerBalanceCheckFailure,
    82  		err,
    83  		"failed to check if the payer %s has sufficient balance",
    84  		payer)
    85  }
    86  
    87  // NewDerivedDataCacheImplementationFailure indicate an implementation error in
    88  // the derived data cache.
    89  func NewDerivedDataCacheImplementationFailure(
    90  	err error,
    91  ) CodedFailure {
    92  	return WrapCodedFailure(
    93  		FailureCodeDerivedDataCacheImplementationFailure,
    94  		err,
    95  		"implementation error in derived data cache")
    96  }
    97  
    98  // NewRandomSourceFailure indicate an implementation error in
    99  // the random source provider.
   100  func NewRandomSourceFailure(
   101  	err error,
   102  ) CodedFailure {
   103  	return WrapCodedFailure(
   104  		FailureCodeRandomSourceFailure,
   105  		err,
   106  		"implementation error in random source provider")
   107  }
   108  
   109  // NewComputationLimitExceededError constructs a new CodedError which indicates
   110  // that computation has exceeded its limit.
   111  func NewComputationLimitExceededError(limit uint64) CodedError {
   112  	return NewCodedError(
   113  		ErrCodeComputationLimitExceededError,
   114  		"computation exceeds limit (%d)",
   115  		limit)
   116  }
   117  
   118  // IsComputationLimitExceededError returns true if error has this code.
   119  func IsComputationLimitExceededError(err error) bool {
   120  	return HasErrorCode(err, ErrCodeComputationLimitExceededError)
   121  }
   122  
   123  // NewMemoryLimitExceededError constructs a new CodedError which indicates
   124  // that execution has exceeded its memory limits.
   125  func NewMemoryLimitExceededError(limit uint64) CodedError {
   126  	return NewCodedError(
   127  		ErrCodeMemoryLimitExceededError,
   128  		"memory usage exceeds limit (%d)",
   129  		limit)
   130  }
   131  
   132  // IsMemoryLimitExceededError returns true if error has this code.
   133  func IsMemoryLimitExceededError(err error) bool {
   134  	return HasErrorCode(err, ErrCodeMemoryLimitExceededError)
   135  }
   136  
   137  // NewStorageCapacityExceededError constructs a new CodedError which indicates
   138  // that an account used more storage than it has storage capacity.
   139  func NewStorageCapacityExceededError(
   140  	address flow.Address,
   141  	storageUsed uint64,
   142  	storageCapacity uint64,
   143  ) CodedError {
   144  	return NewCodedError(
   145  		ErrCodeStorageCapacityExceeded,
   146  		"The account with address (%s) uses %d bytes of storage which is "+
   147  			"over its capacity (%d bytes). Capacity can be increased by "+
   148  			"adding FLOW tokens to the account.",
   149  		address,
   150  		storageUsed,
   151  		storageCapacity)
   152  }
   153  
   154  func IsStorageCapacityExceededError(err error) bool {
   155  	return HasErrorCode(err, ErrCodeStorageCapacityExceeded)
   156  }
   157  
   158  // NewEventLimitExceededError constructs a CodedError which indicates that the
   159  // transaction has produced events with size more than limit.
   160  func NewEventLimitExceededError(
   161  	totalByteSize uint64,
   162  	limit uint64) CodedError {
   163  	return NewCodedError(
   164  		ErrCodeEventLimitExceededError,
   165  		"total event byte size (%d) exceeds limit (%d)",
   166  		totalByteSize,
   167  		limit)
   168  }
   169  
   170  // NewStateKeySizeLimitError constructs a CodedError which indicates that the
   171  // provided key has exceeded the size limit allowed by the storage.
   172  func NewStateKeySizeLimitError(
   173  	id flow.RegisterID,
   174  	size uint64,
   175  	limit uint64,
   176  ) CodedError {
   177  	return NewCodedError(
   178  		ErrCodeStateKeySizeLimitError,
   179  		"key %s has size %d which is higher than storage key size limit %d.",
   180  		id,
   181  		size,
   182  		limit)
   183  }
   184  
   185  // NewStateValueSizeLimitError constructs a CodedError which indicates that the
   186  // provided value has exceeded the size limit allowed by the storage.
   187  func NewStateValueSizeLimitError(
   188  	value flow.RegisterValue,
   189  	size uint64,
   190  	limit uint64,
   191  ) CodedError {
   192  	valueStr := ""
   193  	if len(value) > 23 {
   194  		valueStr = string(value[0:10]) + "..." + string(value[len(value)-10:])
   195  	} else {
   196  		valueStr = string(value)
   197  	}
   198  
   199  	return NewCodedError(
   200  		ErrCodeStateValueSizeLimitError,
   201  		"value %s has size %d which is higher than storage value size "+
   202  			"limit %d.",
   203  		valueStr,
   204  		size,
   205  		limit)
   206  }
   207  
   208  // NewLedgerInteractionLimitExceededError constructs a CodeError. It is
   209  // returned when a tx hits the maximum ledger interaction limit.
   210  func NewLedgerInteractionLimitExceededError(
   211  	used uint64,
   212  	limit uint64,
   213  ) CodedError {
   214  	return NewCodedError(
   215  		ErrCodeLedgerInteractionLimitExceededError,
   216  		"max interaction with storage has exceeded the limit "+
   217  			"(used: %d bytes, limit %d bytes)",
   218  		used,
   219  		limit)
   220  }
   221  
   222  func IsLedgerInteractionLimitExceededError(err error) bool {
   223  	return HasErrorCode(err, ErrCodeLedgerInteractionLimitExceededError)
   224  }
   225  
   226  // NewOperationNotSupportedError construct a new CodedError. It is generated
   227  // when an operation (e.g. getting block info) is not supported in the current
   228  // environment.
   229  func NewOperationNotSupportedError(operation string) CodedError {
   230  	return NewCodedError(
   231  		ErrCodeOperationNotSupportedError,
   232  		"operation (%s) is not supported in this environment",
   233  		operation)
   234  }
   235  
   236  func IsOperationNotSupportedError(err error) bool {
   237  	return HasErrorCode(err, ErrCodeOperationNotSupportedError)
   238  }
   239  
   240  func NewBlockHeightOutOfRangeError(height uint64) CodedError {
   241  	return NewCodedError(
   242  		ErrCodeBlockHeightOutOfRangeError,
   243  		"block height (%v) is out of queriable range",
   244  		height)
   245  }
   246  
   247  func IsBlockHeightOutOfRangeError(err error) bool {
   248  	return HasErrorCode(err, ErrCodeBlockHeightOutOfRangeError)
   249  }
   250  
   251  // NewScriptExecutionCancelledError construct a new CodedError which indicates
   252  // that Cadence Script execution has been cancelled (e.g. request connection
   253  // has been droped)
   254  //
   255  // note: this error is used by scripts only and won't be emitted for
   256  // transactions since transaction execution has to be deterministic.
   257  func NewScriptExecutionCancelledError(err error) CodedError {
   258  	return WrapCodedError(
   259  		ErrCodeScriptExecutionCancelledError,
   260  		err,
   261  		"script execution is cancelled")
   262  }
   263  
   264  // NewScriptExecutionTimedOutError construct a new CodedError which indicates
   265  // that Cadence Script execution has been taking more time than what is allowed.
   266  //
   267  // note: this error is used by scripts only and won't be emitted for
   268  // transactions since transaction execution has to be deterministic.
   269  func NewScriptExecutionTimedOutError() CodedError {
   270  	return NewCodedError(
   271  		ErrCodeScriptExecutionTimedOutError,
   272  		"script execution is timed out and did not finish executing within "+
   273  			"the maximum execution time allowed")
   274  }
   275  
   276  // NewCouldNotGetExecutionParameterFromStateError constructs a new CodedError
   277  // which indicates that computation has exceeded its limit.
   278  func NewCouldNotGetExecutionParameterFromStateError(
   279  	address string,
   280  	path string,
   281  ) CodedError {
   282  	return NewCodedError(
   283  		ErrCodeCouldNotDecodeExecutionParameterFromState,
   284  		"could not get execution parameter from the state "+
   285  			"(address: %s path: %s)",
   286  		address,
   287  		path)
   288  }
   289  
   290  // NewInvalidInternalStateAccessError constructs a new CodedError which
   291  // indicates that the cadence program attempted to directly access flow's
   292  // internal state.
   293  func NewInvalidInternalStateAccessError(
   294  	id flow.RegisterID,
   295  	opType string,
   296  ) CodedError {
   297  	return NewCodedError(
   298  		ErrCodeInvalidInternalStateAccessError,
   299  		"could not directly %s flow internal state (%s)",
   300  		opType,
   301  		id)
   302  }