Repository: stellar/go
Pull request #5179 (2024-01-24 22:40:25)

historyarchive: Improve existence checks and performance
### What
This optimizes existence checks in the case of concurrent history archive sessions sharing a cache.

It also makes a slight performance improvement to state verification memory allocation and improves logging in the state verifier.

### Why
This will reduce churn on `Exists()` requests to the archives.

### Known limitations
n/a


Patch:
diff --git a/.github/workflows/horizon.yml b/.github/workflows/horizon.yml
index 873fcd02..e7bf35cb 100644
--- a/.github/workflows/horizon.yml
+++ b/.github/workflows/horizon.yml
@@ -120,7 +120,7 @@ jobs:
           key: ${{ env.COMBINED_SOURCE_HASH }}
 
       - if: ${{ steps.horizon_binary_tests_hash.outputs.cache-hit != 'true' }}
-        run: go test -race -timeout 45m -v ./services/horizon/internal/integration/...
+        run: go test -race -timeout 65m -v ./services/horizon/internal/integration/...
 
       - name: Save Horizon binary and integration tests source hash to cache
         if: ${{ success() && steps.horizon_binary_tests_hash.outputs.cache-hit != 'true' }}
diff --git a/historyarchive/archive_cache.go b/historyarchive/archive_cache.go
index a3990428..fa279fff 100644
--- a/historyarchive/archive_cache.go
+++ b/historyarchive/archive_cache.go
@@ -113,7 +113,26 @@ func (abc *ArchiveBucketCache) GetFile(
 }
 
 func (abc *ArchiveBucketCache) Exists(filepath string) bool {
-	return abc.lru.Contains(path.Join(abc.path, filepath))
+	localPath := path.Join(abc.path, filepath)
+
+	// First, check if the file exists in the cache.
+	if abc.lru.Contains(localPath) {
+		return true
+	}
+
+	// If it doesn't, it may still exist on the disk which is still a cheaper
+	// check than going upstream.
+	//
+	// Note that this means the cache and disk are out of sync (perhaps due to
+	// other archives using the same cache location) so we can update it. This
+	// situation is well-handled by `GetFile`.
+	_, statErr := os.Stat(localPath)
+	if statErr == nil || os.IsExist(statErr) {
+		abc.lru.Add(localPath, struct{}{})
+		return true
+	}
+
+	return false
 }
 
 // Close purges the cache and cleans up the filesystem.
diff --git a/ingest/verify/main.go b/ingest/verify/main.go
index 4b97ffc2..61104487 100644
--- a/ingest/verify/main.go
+++ b/ingest/verify/main.go
@@ -66,7 +66,7 @@ func (v *StateVerifier) GetLedgerEntries(count int) ([]xdr.LedgerEntry, error) {
 	}
 
 	entries := make([]xdr.LedgerEntry, 0, count)
-	v.currentEntries = make(map[string]xdr.LedgerEntry)
+	v.currentEntries = make(map[string]xdr.LedgerEntry, count)
 
 	for count > 0 {
 		entryChange, err := v.stateReader.Read()
diff --git a/services/horizon/CHANGELOG.md b/services/horizon/CHANGELOG.md
index 25273f96..0899744f 100644
--- a/services/horizon/CHANGELOG.md
+++ b/services/horizon/CHANGELOG.md
@@ -17,6 +17,11 @@ file. This project adheres to [Semantic Versioning](http://semver.org/).
 - We now include metrics for history archive requests ([5166](https://github.com/stellar/go/pull/5166))
 - Http history archive requests now include a unique user agent ([5166](https://github.com/stellar/go/pull/5166))
 - Added a deprecation warning for using command-line flags when running Horizon ([5051](https://github.com/stellar/go/pull/5051))
+- New optional config `DISABLE_SOROBAN_INGEST` ([5175](https://github.com/stellar/go/issues/5175)). Defaults to `FALSE`, when `TRUE` and a soroban transaction is ingested, the following will occur:
+  * no effects will be generated for contract invocations.
+  * history_transactions.tx_meta column will have serialized xdr that equates to an empty `xdr.TransactionMeta.V3`, `Operations`, `TxChangesAfter`, `TxChangesBefore` will empty arrays and `SorobanMeta` will be nil.
+  * API transaction model for `result_meta_xdr` will have same empty serialized xdr for `xdr.TransactionMeta.V3`, `Operations`, `TxChangesAfter`, `TxChangesBefore` will empty arrays and `SorobanMeta` will be nil.
+  * API `Operation` model for `InvokeHostFunctionOp` type, will have empty `asset_balance_changes`
 
 ### Breaking Changes
 - Removed configuration flags `--stellar-core-url-db`, `--cursor-name` `--skip-cursor-update` , they were related to legacy non-captive core ingestion and are no longer usable.
diff --git a/services/horizon/cmd/db.go b/services/horizon/cmd/db.go
index 725df622..07bbf975 100644
--- a/services/horizon/cmd/db.go
+++ b/services/horizon/cmd/db.go
@@ -419,6 +419,7 @@ func runDBReingestRange(ledgerRanges []history.LedgerRange, reingestForce bool,
 		RoundingSlippageFilter:      config.RoundingSlippageFilter,
 		EnableIngestionFiltering:    config.EnableIngestionFiltering,
 		MaxLedgerPerFlush:           maxLedgersPerFlush,
+		SkipSorobanIngestion:        config.SkipSorobanIngestion,
 	}
 
 	if ingestConfig.HistorySession, err = db.Open("postgres", config.DatabaseURL); err != nil {
diff --git a/services/horizon/internal/config.go b/services/horizon/internal/config.go
index 7454f52b..8fb31075 100644
--- a/services/horizon/internal/config.go
+++ b/services/horizon/internal/config.go
@@ -108,4 +108,6 @@ type Config struct {
 	Network string
 	// DisableTxSub disables transaction submission functionality for Horizon.
 	DisableTxSub bool
+	// SkipSorobanIngestion skips Soroban related ingestion processing.
+	SkipSorobanIngestion bool
 }
diff --git a/services/horizon/internal/flags.go b/services/horizon/internal/flags.go
index 40bfc08a..eb229c65 100644
--- a/services/horizon/internal/flags.go
+++ b/services/horizon/internal/flags.go
@@ -57,6 +57,8 @@ const (
 	EnableIngestionFilteringFlagName = "exp-enable-ingestion-filtering"
 	// DisableTxSubFlagName is the command line flag for disabling transaction submission feature of Horizon
 	DisableTxSubFlagName = "disable-tx-sub"
+	// SkipSorobanIngestionFlagName is the command line flag for disabling Soroban related ingestion processing
+	SkipSorobanIngestionFlagName = "disable-soroban-ingest"
 
 	// StellarPubnet is a constant representing the Stellar public network
 	StellarPubnet = "pubnet"
@@ -730,6 +732,15 @@ func Flags() (*Config, support.ConfigOptions) {
 				HistoryArchiveURLsFlagName, CaptiveCoreConfigPathName),
 			UsedInCommands: IngestionCommands,
 		},
+		&support.ConfigOption{
+			Name:           SkipSorobanIngestionFlagName,
+			ConfigKey:      &config.SkipSorobanIngestion,
+			OptType:        types.Bool,
+			FlagDefault:    false,
+			Required:       false,
+			Usage:          "excludes Soroban data during ingestion processing",
+			UsedInCommands: IngestionCommands,
+		},
 	}
 
 	return config, flags
diff --git a/services/horizon/internal/ingest/main.go b/services/horizon/internal/ingest/main.go
index 3d8fcf21..7dfaea36 100644
--- a/services/horizon/internal/ingest/main.go
+++ b/services/horizon/internal/ingest/main.go
@@ -107,6 +107,8 @@ type Config struct {
 
 	EnableIngestionFiltering bool
 	MaxLedgerPerFlush        uint32
+
+	SkipSorobanIngestion bool
 }
 
 const (
diff --git a/services/horizon/internal/ingest/processor_runner.go b/services/horizon/internal/ingest/processor_runner.go
index 34b977c0..a09442b4 100644
--- a/services/horizon/internal/ingest/processor_runner.go
+++ b/services/horizon/internal/ingest/processor_runner.go
@@ -111,6 +111,7 @@ func buildChangeProcessor(
 	source ingestionSource,
 	ledgerSequence uint32,
 	networkPassphrase string,
+	skipSorobanIngestion bool,
 ) *groupChangeProcessors {
 	statsChangeProcessor := &statsChangeProcessor{
 		StatsChangeProcessor: changeStats,
@@ -144,13 +145,13 @@ func (s *ProcessorRunner) buildTransactionProcessor(ledgersProcessor *processors
 
 	processors := []horizonTransactionProcessor{
 		statsLedgerTransactionProcessor,
-		processors.NewEffectProcessor(accountLoader, s.historyQ.NewEffectBatchInsertBuilder(), s.config.NetworkPassphrase),
+		processors.NewEffectProcessor(accountLoader, s.historyQ.NewEffectBatchInsertBuilder(), s.config.NetworkPassphrase, s.config.SkipSorobanIngestion),
 		ledgersProcessor,
-		processors.NewOperationProcessor(s.historyQ.NewOperationBatchInsertBuilder(), s.config.NetworkPassphrase),
+		processors.NewOperationProcessor(s.historyQ.NewOperationBatchInsertBuilder(), s.config.NetworkPassphrase, s.config.SkipSorobanIngestion),
 		tradeProcessor,
 		processors.NewParticipantsProcessor(accountLoader,
 			s.historyQ.NewTransactionParticipantsBatchInsertBuilder(), s.historyQ.NewOperationParticipantBatchInsertBuilder()),
-		processors.NewTransactionProcessor(s.historyQ.NewTransactionBatchInsertBuilder()),
+		processors.NewTransactionProcessor(s.historyQ.NewTransactionBatchInsertBuilder(), s.config.SkipSorobanIngestion),
 		processors.NewClaimableBalancesTransactionProcessor(cbLoader,
 			s.historyQ.NewTransactionClaimableBalanceBatchInsertBuilder(), s.historyQ.NewOperationClaimableBalanceBatchInsertBuilder()),
 		processors.NewLiquidityPoolsTransactionProcessor(lpLoader,
@@ -172,7 +173,10 @@ func (s *ProcessorRunner) buildFilteredOutProcessor() *groupTransactionProcessor
 	// when in online mode, the submission result processor must always run (regardless of filtering)
 	var p []horizonTransactionProcessor
 	if s.config.EnableIngestionFiltering {
-		txSubProc := processors.NewTransactionFilteredTmpProcessor(s.historyQ.NewTransactionFilteredTmpBatchInsertBuilder())
+		txSubProc := processors.NewTransactionFilteredTmpProcessor(
+			s.historyQ.NewTransactionFilteredTmpBatchInsertBuilder(),
+			s.config.SkipSorobanIngestion,
+		)
 		p = append(p, txSubProc)
 	}
 
@@ -235,6 +239,7 @@ func (s *ProcessorRunner) RunHistoryArchiveIngestion(
 		historyArchiveSource,
 		checkpointLedger,
 		s.config.NetworkPassphrase,
+		s.config.SkipSorobanIngestion,
 	)
 
 	if checkpointLedger == 1 {
@@ -493,6 +498,7 @@ func (s *ProcessorRunner) RunAllProcessorsOnLedger(ledger xdr.LedgerCloseMeta) (
 		ledgerSource,
 		ledger.LedgerSequence(),
 		s.config.NetworkPassphrase,
+		s.config.SkipSorobanIngestion,
 	)
 	err = s.runChangeProcessorOnLedger(groupChangeProcessors, ledger)
 	if err != nil {
diff --git a/services/horizon/internal/ingest/processors/effects_processor.go b/services/horizon/internal/ingest/processors/effects_processor.go
index 34e9f916..830632f5 100644
--- a/services/horizon/internal/ingest/processors/effects_processor.go
+++ b/services/horizon/internal/ingest/processors/effects_processor.go
@@ -28,17 +28,20 @@ type EffectProcessor struct {
 	accountLoader *history.AccountLoader
 	batch         history.EffectBatchInsertBuilder
 	network       string
+	skipSoroban   bool
 }
 
 func NewEffectProcessor(
 	accountLoader *history.AccountLoader,
 	batch history.EffectBatchInsertBuilder,
 	network string,
+	skipSoroban bool,
 ) *EffectProcessor {
 	return &EffectProcessor{
 		accountLoader: accountLoader,
 		batch:         batch,
 		network:       network,
+		skipSoroban:   skipSoroban,
 	}
 }
 
@@ -50,14 +53,29 @@ func (p *EffectProcessor) ProcessTransaction(
 		return nil
 	}
 
-	for opi, op := range transaction.Envelope.Operations() {
+	elidedTransaction := transaction
+
+	if p.skipSoroban &&
+		elidedTransaction.UnsafeMeta.V == 3 &&
+		elidedTransaction.UnsafeMeta.V3.SorobanMeta != nil {
+		elidedTransaction.UnsafeMeta.V3 = &xdr.TransactionMetaV3{
+			Ext:             xdr.ExtensionPoint{},
+			TxChangesBefore: xdr.LedgerEntryChanges{},
+			Operations:      []xdr.OperationMeta{},
+			TxChangesAfter:  xdr.LedgerEntryChanges{},
+			SorobanMeta:     nil,
+		}
+	}
+
+	for opi, op := range elidedTransaction.Envelope.Operations() {
 		operation := transactionOperationWrapper{
 			index:          uint32(opi),
-			transaction:    transaction,
+			transaction:    elidedTransaction,
 			operation:      op,
 			ledgerSequence: uint32(lcm.LedgerSequence()),
 			network:        p.network,
 		}
+
 		if err := operation.ingestEffects(p.accountLoader, p.batch); err != nil {
 			return errors.Wrapf(err, "reading operation %v effects", operation.ID())
 		}
diff --git a/services/horizon/internal/ingest/processors/operations_processor.go b/services/horizon/internal/ingest/processors/operations_processor.go
index b9a23229..84ef45f0 100644
--- a/services/horizon/internal/ingest/processors/operations_processor.go
+++ b/services/horizon/internal/ingest/processors/operations_processor.go
@@ -21,14 +21,16 @@ import (
 
 // OperationProcessor operations processor
 type OperationProcessor struct {
-	batch   history.OperationBatchInsertBuilder
-	network string
+	batch       history.OperationBatchInsertBuilder
+	network     string
+	skipSoroban bool
 }
 
-func NewOperationProcessor(batch history.OperationBatchInsertBuilder, network string) *OperationProcessor {
+func NewOperationProcessor(batch history.OperationBatchInsertBuilder, network string, skipSoroban bool) *OperationProcessor {
 	return &OperationProcessor{
-		batch:   batch,
-		network: network,
+		batch:       batch,
+		network:     network,
+		skipSoroban: skipSoroban,
 	}
 }
 
@@ -36,11 +38,12 @@ func NewOperationProcessor(batch history.OperationBatchInsertBuilder, network st
 func (p *OperationProcessor) ProcessTransaction(lcm xdr.LedgerCloseMeta, transaction ingest.LedgerTransaction) error {
 	for i, op := range transaction.Envelope.Operations() {
 		operation := transactionOperationWrapper{
-			index:          uint32(i),
-			transaction:    transaction,
-			operation:      op,
-			ledgerSequence: lcm.LedgerSequence(),
-			network:        p.network,
+			index:              uint32(i),
+			transaction:        transaction,
+			operation:          op,
+			ledgerSequence:     lcm.LedgerSequence(),
+			network:            p.network,
+			skipSorobanDetails: p.skipSoroban,
 		}
 		details, err := operation.Details()
 		if err != nil {
@@ -81,11 +84,12 @@ func (p *OperationProcessor) Flush(ctx context.Context, session db.SessionInterf
 
 // transactionOperationWrapper represents the data for a single operation within a transaction
 type transactionOperationWrapper struct {
-	index          uint32
-	transaction    ingest.LedgerTransaction
-	operation      xdr.Operation
-	ledgerSequence uint32
-	network        string
+	index              uint32
+	transaction        ingest.LedgerTransaction
+	operation          xdr.Operation
+	ledgerSequence     uint32
+	network            string
+	skipSorobanDetails bool
 }
 
 // ID returns the ID for the operation.
@@ -265,6 +269,11 @@ func (operation *transactionOperationWrapper) IsPayment() bool {
 	case xdr.OperationTypeAccountMerge:
 		return true
 	case xdr.OperationTypeInvokeHostFunction:
+		// #5175, may want to consider skipping this parsing of payment from contracts
+		// as part of eliding soroban ingestion aspects when DISABLE_SOROBAN_INGEST.
+		// but, may cause inconsistencies that aren't worth the gain,
+		// as payments won't be thoroughly accurate, i.e. a payment could have
+		// happened within a contract invoke.
 		diagnosticEvents, err := operation.transaction.GetDiagnosticEvents()
 		if err != nil {
 			return false
@@ -688,11 +697,18 @@ func (operation *transactionOperationWrapper) Details() (map[string]interface{},
 			}
 			details["parameters"] = params
 
-			if balanceChanges, err := operation.parseAssetBalanceChangesFromContractEvents(); err != nil {
-				return nil, err
+			var balanceChanges []map[string]interface{}
+			var parseErr error
+			if operation.skipSorobanDetails {
+				// https://github.com/stellar/go/issues/5175
+				// intentionally toggle off parsing soroban meta into "asset_balance_changes"
+				balanceChanges = make([]map[string]interface{}, 0)
 			} else {
-				details["asset_balance_changes"] = balanceChanges
+				if balanceChanges, parseErr = operation.parseAssetBalanceChangesFromContractEvents(); parseErr != nil {
+					return nil, parseErr
+				}
 			}
+			details["asset_balance_changes"] = balanceChanges
 
 		case xdr.HostFunctionTypeHostFunctionTypeCreateContract:
 			args := op.HostFunction.MustCreateContract()
diff --git a/services/horizon/internal/ingest/processors/transactions_processor.go b/services/horizon/internal/ingest/processors/transactions_processor.go
index 871c7262..b82934d8 100644
--- a/services/horizon/internal/ingest/processors/transactions_processor.go
+++ b/services/horizon/internal/ingest/processors/transactions_processor.go
@@ -11,23 +11,40 @@ import (
 )
 
 type TransactionProcessor struct {
-	batch history.TransactionBatchInsertBuilder
+	batch       history.TransactionBatchInsertBuilder
+	skipSoroban bool
 }
 
-func NewTransactionFilteredTmpProcessor(batch history.TransactionBatchInsertBuilder) *TransactionProcessor {
+func NewTransactionFilteredTmpProcessor(batch history.TransactionBatchInsertBuilder, skipSoroban bool) *TransactionProcessor {
 	return &TransactionProcessor{
-		batch: batch,
+		batch:       batch,
+		skipSoroban: skipSoroban,
 	}
 }
 
-func NewTransactionProcessor(batch history.TransactionBatchInsertBuilder) *TransactionProcessor {
+func NewTransactionProcessor(batch history.TransactionBatchInsertBuilder, skipSoroban bool) *TransactionProcessor {
 	return &TransactionProcessor{
-		batch: batch,
+		batch:       batch,
+		skipSoroban: skipSoroban,
 	}
 }
 
 func (p *TransactionProcessor) ProcessTransaction(lcm xdr.LedgerCloseMeta, transaction ingest.LedgerTransaction) error {
-	if err := p.batch.Add(transaction, lcm.LedgerSequence()); err != nil {
+	elidedTransaction := transaction
+
+	if p.skipSoroban &&
+		elidedTransaction.UnsafeMeta.V == 3 &&
+		elidedTransaction.UnsafeMeta.MustV3().SorobanMeta != nil {
+		elidedTransaction.UnsafeMeta.V3 = &xdr.TransactionMetaV3{
+			Ext:             xdr.ExtensionPoint{},
+			TxChangesBefore: xdr.LedgerEntryChanges{},
+			Operations:      []xdr.OperationMeta{},
+			TxChangesAfter:  xdr.LedgerEntryChanges{},
+			SorobanMeta:     nil,
+		}
+	}
+
+	if err := p.batch.Add(elidedTransaction, lcm.LedgerSequence()); err != nil {
 		return errors.Wrap(err, "Error batch inserting transaction rows")
 	}
 
diff --git a/services/horizon/internal/ingest/verify.go b/services/horizon/internal/ingest/verify.go
index bf1ddbe5..41b0eb98 100644
--- a/services/horizon/internal/ingest/verify.go
+++ b/services/horizon/internal/ingest/verify.go
@@ -157,8 +157,8 @@ func (s *system) verifyState(verifyAgainstLatestCheckpoint bool) error {
 				}
 			}
 		}
-		log.WithField("duration", duration).Info("State verification finished")
 
+		localLog.WithField("duration", duration).Info("State verification finished")
 	}()
 
 	localLog.Info("Creating state reader...")
diff --git a/services/horizon/internal/init.go b/services/horizon/internal/init.go
index 1b6664b8..4078c7ad 100644
--- a/services/horizon/internal/init.go
+++ b/services/horizon/internal/init.go
@@ -110,6 +110,7 @@ func initIngester(app *App) {
 		EnableExtendedLogLedgerStats:         app.config.IngestEnableExtendedLogLedgerStats,
 		RoundingSlippageFilter:               app.config.RoundingSlippageFilter,
 		EnableIngestionFiltering:             app.config.EnableIngestionFiltering,
+		SkipSorobanIngestion:                 app.config.SkipSorobanIngestion,
 	})
 
 	if err != nil {


Test patch:
diff --git a/services/horizon/internal/ingest/processor_runner_test.go b/services/horizon/internal/ingest/processor_runner_test.go
index eaeca956..ddac48aa 100644
--- a/services/horizon/internal/ingest/processor_runner_test.go
+++ b/services/horizon/internal/ingest/processor_runner_test.go
@@ -180,7 +180,7 @@ func TestProcessorRunnerBuildChangeProcessor(t *testing.T) {
 	}
 
 	stats := &ingest.StatsChangeProcessor{}
-	processor := buildChangeProcessor(runner.historyQ, stats, ledgerSource, 123, "")
+	processor := buildChangeProcessor(runner.historyQ, stats, ledgerSource, 123, "", false)
 	assert.IsType(t, &groupChangeProcessors{}, processor)
 
 	assert.IsType(t, &statsChangeProcessor{}, processor.processors[0])
@@ -201,7 +201,7 @@ func TestProcessorRunnerBuildChangeProcessor(t *testing.T) {
 		filters:  &MockFilters{},
 	}
 
-	processor = buildChangeProcessor(runner.historyQ, stats, historyArchiveSource, 456, "")
+	processor = buildChangeProcessor(runner.historyQ, stats, historyArchiveSource, 456, "", false)
 	assert.IsType(t, &groupChangeProcessors{}, processor)
 
 	assert.IsType(t, &statsChangeProcessor{}, processor.processors[0])
@@ -271,6 +271,7 @@ func TestProcessorRunnerWithFilterEnabled(t *testing.T) {
 	config := Config{
 		NetworkPassphrase:        network.PublicNetworkPassphrase,
 		EnableIngestionFiltering: true,
+		SkipSorobanIngestion:     false,
 	}
 
 	q := &mockDBQ{}
diff --git a/services/horizon/internal/ingest/processors/effects_processor_test.go b/services/horizon/internal/ingest/processors/effects_processor_test.go
index 0243768f..70af2173 100644
--- a/services/horizon/internal/ingest/processors/effects_processor_test.go
+++ b/services/horizon/internal/ingest/processors/effects_processor_test.go
@@ -143,6 +143,7 @@ func (s *EffectsProcessorTestSuiteLedger) SetupTest() {
 		s.accountLoader,
 		s.mockBatchInsertBuilder,
 		networkPassphrase,
+		false,
 	)
 
 	s.txs = []ingest.LedgerTransaction{
diff --git a/services/horizon/internal/ingest/processors/operations_processor_test.go b/services/horizon/internal/ingest/processors/operations_processor_test.go
index 4b5fb376..275a6056 100644
--- a/services/horizon/internal/ingest/processors/operations_processor_test.go
+++ b/services/horizon/internal/ingest/processors/operations_processor_test.go
@@ -42,6 +42,7 @@ func (s *OperationsProcessorTestSuiteLedger) SetupTest() {
 	s.processor = NewOperationProcessor(
 		s.mockBatchInsertBuilder,
 		"test network",
+		false,
 	)
 }
 
@@ -375,6 +376,65 @@ func (s *OperationsProcessorTestSuiteLedger) TestOperationTypeInvokeHostFunction
 		}
 		s.Assert().Equal(found, 4, "should have one balance changed record for each of mint, burn, clawback, transfer")
 	})
+
+	s.T().Run("InvokeContractAssetBalancesElidedFromDetails", func(t *testing.T) {
+		randomIssuer := keypair.MustRandom()
+		randomAsset := xdr.MustNewCreditAsset("TESTING", randomIssuer.Address())
+		passphrase := "passphrase"
+		randomAccount := keypair.MustRandom().Address()
+		contractId := [32]byte{}
+		zeroContractStrKey, err := strkey.Encode(strkey.VersionByteContract, contractId[:])
+		s.Assert().NoError(err)
+
+		transferContractEvent := contractevents.GenerateEvent(contractevents.EventTypeTransfer, randomAccount, zeroContractStrKey, "", randomAsset, big.NewInt(10000000), passphrase)
+		burnContractEvent := contractevents.GenerateEvent(contractevents.EventTypeBurn, zeroContractStrKey, "", "", randomAsset, big.NewInt(10000000), passphrase)
+		mintContractEvent := contractevents.GenerateEvent(contractevents.EventTypeMint, "", zeroContractStrKey, randomAccount, randomAsset, big.NewInt(10000000), passphrase)
+		clawbackContractEvent := contractevents.GenerateEvent(contractevents.EventTypeClawback, zeroContractStrKey, "", randomAccount, randomAsset, big.NewInt(10000000), passphrase)
+
+		tx = ingest.LedgerTransaction{
+			UnsafeMeta: xdr.TransactionMeta{
+				V: 3,
+				V3: &xdr.TransactionMetaV3{
+					SorobanMeta: &xdr.SorobanTransactionMeta{
+						Events: []xdr.ContractEvent{
+							transferContractEvent,
+							burnContractEvent,
+							mintContractEvent,
+							clawbackContractEvent,
+						},
+					},
+				},
+			},
+		}
+		wrapper := transactionOperationWrapper{
+			skipSorobanDetails: true,
+			transaction:        tx,
+			operation: xdr.Operation{
+				SourceAccount: &source,
+				Body: xdr.OperationBody{
+					Type: xdr.OperationTypeInvokeHostFunction,
+					InvokeHostFunctionOp: &xdr.InvokeHostFunctionOp{
+						HostFunction: xdr.HostFunction{
+							Type: xdr.HostFunctionTypeHostFunctionTypeInvokeContract,
+							InvokeContract: &xdr.InvokeContractArgs{
+								ContractAddress: xdr.ScAddress{
+									Type:       xdr.ScAddressTypeScAddressTypeContract,
+									ContractId: &xdr.Hash{0x1, 0x2},
+								},
+								FunctionName: "foo",
+								Args:         xdr.ScVec{},
+							},
+						},
+					},
+				},
+			},
+			network: passphrase,
+		}
+
+		details, err := wrapper.Details()
+		s.Assert().NoError(err)
+		s.Assert().Len(details["asset_balance_changes"], 0, "for invokehostfn op, no asset balances should be in details when skip soroban is enabled")
+	})
 }
 
 func (s *OperationsProcessorTestSuiteLedger) assertInvokeHostFunctionParameter(parameters []map[string]string, paramPosition int, expectedType string, expectedVal xdr.ScVal) {
diff --git a/services/horizon/internal/ingest/processors/transactions_processor_test.go b/services/horizon/internal/ingest/processors/transactions_processor_test.go
index 987e8ce6..873a72af 100644
--- a/services/horizon/internal/ingest/processors/transactions_processor_test.go
+++ b/services/horizon/internal/ingest/processors/transactions_processor_test.go
@@ -29,7 +29,7 @@ func TestTransactionsProcessorTestSuiteLedger(t *testing.T) {
 func (s *TransactionsProcessorTestSuiteLedger) SetupTest() {
 	s.ctx = context.Background()
 	s.mockBatchInsertBuilder = &history.MockTransactionsBatchInsertBuilder{}
-	s.processor = NewTransactionProcessor(s.mockBatchInsertBuilder)
+	s.processor = NewTransactionProcessor(s.mockBatchInsertBuilder, false)
 }
 
 func (s *TransactionsProcessorTestSuiteLedger) TearDownTest() {
diff --git a/services/horizon/internal/ingest/verify_test.go b/services/horizon/internal/ingest/verify_test.go
index 901f21a0..e3c0e4ec 100644
--- a/services/horizon/internal/ingest/verify_test.go
+++ b/services/horizon/internal/ingest/verify_test.go
@@ -292,7 +292,7 @@ func TestStateVerifierLockBusy(t *testing.T) {
 	tt.Assert.NoError(q.BeginTx(tt.Ctx, &sql.TxOptions{}))
 
 	checkpointLedger := uint32(63)
-	changeProcessor := buildChangeProcessor(q, &ingest.StatsChangeProcessor{}, ledgerSource, checkpointLedger, "")
+	changeProcessor := buildChangeProcessor(q, &ingest.StatsChangeProcessor{}, ledgerSource, checkpointLedger, "", false)
 
 	gen := randxdr.NewGenerator()
 	var changes []xdr.LedgerEntryChange
@@ -350,7 +350,7 @@ func TestStateVerifier(t *testing.T) {
 
 	ledger := rand.Int31()
 	checkpointLedger := uint32(ledger - (ledger % 64) - 1)
-	changeProcessor := buildChangeProcessor(q, &ingest.StatsChangeProcessor{}, ledgerSource, checkpointLedger, "")
+	changeProcessor := buildChangeProcessor(q, &ingest.StatsChangeProcessor{}, ledgerSource, checkpointLedger, "", false)
 	mockChangeReader := &ingest.MockChangeReader{}
 
 	gen := randxdr.NewGenerator()
diff --git a/services/horizon/internal/integration/invokehostfunction_test.go b/services/horizon/internal/integration/invokehostfunction_test.go
index 275f0de2..1b1edc09 100644
--- a/services/horizon/internal/integration/invokehostfunction_test.go
+++ b/services/horizon/internal/integration/invokehostfunction_test.go
@@ -3,11 +3,13 @@ package integration
 import (
 	"crypto/sha256"
 	"encoding/hex"
+	"fmt"
 	"os"
 	"path/filepath"
 	"testing"
 
 	"github.com/stellar/go/clients/horizonclient"
+	"github.com/stellar/go/protocols/horizon"
 	"github.com/stellar/go/protocols/horizon/operations"
 	"github.com/stellar/go/services/horizon/internal/test/integration"
 	"github.com/stellar/go/txnbuild"
@@ -24,13 +26,42 @@ const increment_contract = "soroban_increment_contract.wasm"
 // Refer to ./services/horizon/internal/integration/contracts/README.md on how to recompile
 // contract code if needed to new wasm.
 
-func TestContractInvokeHostFunctionInstallContract(t *testing.T) {
+func TestInvokeHostFns(t *testing.T) {
+	// first test contracts when soroban processing is enabled
+	DisabledSoroban = false
+	runAllTests(t)
+	// now test same contracts when soroban processing is disabled
+	DisabledSoroban = true
+	runAllTests(t)
+}
+
+func runAllTests(t *testing.T) {
+	tests := []struct {
+		name string
+		fn   func(*testing.T)
+	}{
+		{"CaseContractInvokeHostFunctionInstallContract", CaseContractInvokeHostFunctionInstallContract},
+		{"CaseContractInvokeHostFunctionCreateContractByAddress", CaseContractInvokeHostFunctionCreateContractByAddress},
+		{"CaseContractInvokeHostFunctionInvokeStatelessContractFn", CaseContractInvokeHostFunctionInvokeStatelessContractFn},
+		{"CaseContractInvokeHostFunctionInvokeStatefulContractFn", CaseContractInvokeHostFunctionInvokeStatefulContractFn},
+	}
+
+	for _, tt := range tests {
+		t.Run(fmt.Sprintf("Soroban Processing Disabled = %v. ", DisabledSoroban)+tt.name, func(t *testing.T) {
+			tt.fn(t)
+		})
+	}
+}
+
+func CaseContractInvokeHostFunctionInstallContract(t *testing.T) {
 	if integration.GetCoreMaxSupportedProtocol() < 20 {
 		t.Skip("This test run does not support less than Protocol 20")
 	}
 
 	itest := integration.NewTest(t, integration.Config{
-		ProtocolVersion:  20,
+		ProtocolVersion: 20,
+		HorizonEnvironment: map[string]string{
+			"DISABLE_SOROBAN_INGEST": fmt.Sprint(DisabledSoroban)},
 		EnableSorobanRPC: true,
 	})
 
@@ -46,6 +77,7 @@ func TestContractInvokeHostFunctionInstallContract(t *testing.T) {
 
 	clientTx, err := itest.Client().TransactionDetail(tx.Hash)
 	require.NoError(t, err)
+	verifySorobanMeta(t, clientTx)
 
 	assert.Equal(t, tx.Hash, clientTx.Hash)
 	var txResult xdr.TransactionResult
@@ -71,16 +103,17 @@ func TestContractInvokeHostFunctionInstallContract(t *testing.T) {
 	invokeHostFunctionOpJson, ok := clientInvokeOp.Embedded.Records[0].(operations.InvokeHostFunction)
 	assert.True(t, ok)
 	assert.Equal(t, invokeHostFunctionOpJson.Function, "HostFunctionTypeHostFunctionTypeUploadContractWasm")
-
 }
 
-func TestContractInvokeHostFunctionCreateContractByAddress(t *testing.T) {
+func CaseContractInvokeHostFunctionCreateContractByAddress(t *testing.T) {
 	if integration.GetCoreMaxSupportedProtocol() < 20 {
 		t.Skip("This test run does not support less than Protocol 20")
 	}
 
 	itest := integration.NewTest(t, integration.Config{
-		ProtocolVersion:  20,
+		ProtocolVersion: 20,
+		HorizonEnvironment: map[string]string{
+			"DISABLE_SOROBAN_INGEST": fmt.Sprint(DisabledSoroban)},
 		EnableSorobanRPC: true,
 	})
 
@@ -103,6 +136,7 @@ func TestContractInvokeHostFunctionCreateContractByAddress(t *testing.T) {
 
 	clientTx, err := itest.Client().TransactionDetail(tx.Hash)
 	require.NoError(t, err)
+	verifySorobanMeta(t, clientTx)
 
 	assert.Equal(t, tx.Hash, clientTx.Hash)
 	var txResult xdr.TransactionResult
@@ -128,13 +162,15 @@ func TestContractInvokeHostFunctionCreateContractByAddress(t *testing.T) {
 	assert.Equal(t, invokeHostFunctionOpJson.Salt, "110986164698320180327942133831752629430491002266485370052238869825166557303060")
 }
 
-func TestContractInvokeHostFunctionInvokeStatelessContractFn(t *testing.T) {
+func CaseContractInvokeHostFunctionInvokeStatelessContractFn(t *testing.T) {
 	if integration.GetCoreMaxSupportedProtocol() < 20 {
 		t.Skip("This test run does not support less than Protocol 20")
 	}
 
 	itest := integration.NewTest(t, integration.Config{
-		ProtocolVersion:  20,
+		ProtocolVersion: 20,
+		HorizonEnvironment: map[string]string{
+			"DISABLE_SOROBAN_INGEST": fmt.Sprint(DisabledSoroban)},
 		EnableSorobanRPC: true,
 	})
 
@@ -196,6 +232,7 @@ func TestContractInvokeHostFunctionInvokeStatelessContractFn(t *testing.T) {
 
 	clientTx, err := itest.Client().TransactionDetail(tx.Hash)
 	require.NoError(t, err)
+	verifySorobanMeta(t, clientTx)
 
 	assert.Equal(t, tx.Hash, clientTx.Hash)
 	var txResult xdr.TransactionResult
@@ -209,12 +246,14 @@ func TestContractInvokeHostFunctionInvokeStatelessContractFn(t *testing.T) {
 	assert.True(t, ok)
 	assert.Equal(t, invokeHostFunctionResult.Code, xdr.InvokeHostFunctionResultCodeInvokeHostFunctionSuccess)
 
-	// check the function response, should have summed the two input numbers
-	invokeResult := xdr.Uint64(9)
-	expectedScVal := xdr.ScVal{Type: xdr.ScValTypeScvU64, U64: &invokeResult}
-	var transactionMeta xdr.TransactionMeta
-	assert.NoError(t, xdr.SafeUnmarshalBase64(tx.ResultMetaXdr, &transactionMeta))
-	assert.True(t, expectedScVal.Equals(transactionMeta.V3.SorobanMeta.ReturnValue))
+	if !DisabledSoroban {
+		// check the function response, should have summed the two input numbers
+		invokeResult := xdr.Uint64(9)
+		expectedScVal := xdr.ScVal{Type: xdr.ScValTypeScvU64, U64: &invokeResult}
+		var transactionMeta xdr.TransactionMeta
+		assert.NoError(t, xdr.SafeUnmarshalBase64(tx.ResultMetaXdr, &transactionMeta))
+		assert.True(t, expectedScVal.Equals(transactionMeta.V3.SorobanMeta.ReturnValue))
+	}
 
 	clientInvokeOp, err := itest.Client().Operations(horizonclient.OperationRequest{
 		ForTransaction: tx.Hash,
@@ -237,13 +276,15 @@ func TestContractInvokeHostFunctionInvokeStatelessContractFn(t *testing.T) {
 	assert.Equal(t, invokeHostFunctionOpJson.Parameters[3].Type, "U64")
 }
 
-func TestContractInvokeHostFunctionInvokeStatefulContractFn(t *testing.T) {
+func CaseContractInvokeHostFunctionInvokeStatefulContractFn(t *testing.T) {
 	if integration.GetCoreMaxSupportedProtocol() < 20 {
 		t.Skip("This test run does not support less than Protocol 20")
 	}
 
 	itest := integration.NewTest(t, integration.Config{
-		ProtocolVersion:  20,
+		ProtocolVersion: 20,
+		HorizonEnvironment: map[string]string{
+			"DISABLE_SOROBAN_INGEST": fmt.Sprint(DisabledSoroban)},
 		EnableSorobanRPC: true,
 	})
 
@@ -292,6 +333,7 @@ func TestContractInvokeHostFunctionInvokeStatefulContractFn(t *testing.T) {
 
 	clientTx, err := itest.Client().TransactionDetail(tx.Hash)
 	require.NoError(t, err)
+	verifySorobanMeta(t, clientTx)
 
 	assert.Equal(t, tx.Hash, clientTx.Hash)
 	var txResult xdr.TransactionResult
@@ -305,12 +347,14 @@ func TestContractInvokeHostFunctionInvokeStatefulContractFn(t *testing.T) {
 	assert.True(t, ok)
 	assert.Equal(t, invokeHostFunctionResult.Code, xdr.InvokeHostFunctionResultCodeInvokeHostFunctionSuccess)
 
-	// check the function response, should have incremented state from 0 to 1
-	invokeResult := xdr.Uint32(1)
-	expectedScVal := xdr.ScVal{Type: xdr.ScValTypeScvU32, U32: &invokeResult}
-	var transactionMeta xdr.TransactionMeta
-	assert.NoError(t, xdr.SafeUnmarshalBase64(clientTx.ResultMetaXdr, &transactionMeta))
-	assert.True(t, expectedScVal.Equals(transactionMeta.V3.SorobanMeta.ReturnValue))
+	if !DisabledSoroban {
+		// check the function response, should have incremented state from 0 to 1
+		invokeResult := xdr.Uint32(1)
+		expectedScVal := xdr.ScVal{Type: xdr.ScValTypeScvU32, U32: &invokeResult}
+		var transactionMeta xdr.TransactionMeta
+		assert.NoError(t, xdr.SafeUnmarshalBase64(clientTx.ResultMetaXdr, &transactionMeta))
+		assert.True(t, expectedScVal.Equals(transactionMeta.V3.SorobanMeta.ReturnValue))
+	}
 
 	clientInvokeOp, err := itest.Client().Operations(horizonclient.OperationRequest{
 		ForTransaction: tx.Hash,
@@ -384,3 +428,20 @@ func assembleCreateContractOp(t *testing.T, sourceAccount string, wasmFileName s
 		SourceAccount: sourceAccount,
 	}
 }
+
+func verifySorobanMeta(t *testing.T, clientTx horizon.Transaction) {
+	var txMeta xdr.TransactionMeta
+	err := xdr.SafeUnmarshalBase64(clientTx.ResultMetaXdr, &txMeta)
+	require.NoError(t, err)
+	require.NotNil(t, txMeta.V3)
+
+	if !DisabledSoroban {
+		require.NotNil(t, txMeta.V3.SorobanMeta)
+		return
+	}
+
+	require.Empty(t, txMeta.V3.Operations)
+	require.Empty(t, txMeta.V3.TxChangesAfter)
+	require.Empty(t, txMeta.V3.TxChangesBefore)
+	require.Nil(t, txMeta.V3.SorobanMeta)
+}
diff --git a/services/horizon/internal/integration/sac_test.go b/services/horizon/internal/integration/sac_test.go
index 64c772b4..c790b5a5 100644
--- a/services/horizon/internal/integration/sac_test.go
+++ b/services/horizon/internal/integration/sac_test.go
@@ -2,6 +2,7 @@ package integration
 
 import (
 	"context"
+	"fmt"
 	"math"
 	"math/big"
 	"strings"
@@ -30,19 +31,127 @@ const sac_contract = "soroban_sac_test.wasm"
 // of the integration tests.
 const LongTermTTL = 10000
 
+var (
+	DisabledSoroban bool
+)
+
+func TestSAC(t *testing.T) {
+	// first test contracts when soroban processing is enabled
+	DisabledSoroban = false
+	runAllSACTests(t)
+	// now test same contracts when soroban processing is disabled
+	DisabledSoroban = true
+	runAllSACTests(t)
+}
+
+func runAllSACTests(t *testing.T) {
+	tests := []struct {
+		name string
+		fn   func(*testing.T)
+	}{
+		{"CaseContractMintToAccount", CaseContractMintToAccount},
+		{"CaseContractMintToContract", CaseContractMintToContract},
+		{"CaseExpirationAndRestoration", CaseExpirationAndRestoration},
+		{"CaseContractTransferBetweenAccounts", CaseContractTransferBetweenAccounts},
+		{"CaseContractTransferBetweenAccountAndContract", CaseContractTransferBetweenAccountAndContract},
+		{"CaseContractTransferBetweenContracts", CaseContractTransferBetweenContracts},
+		{"CaseContractBurnFromAccount", CaseContractBurnFromAccount},
+		{"CaseContractBurnFromContract", CaseContractBurnFromContract},
+		{"CaseContractClawbackFromAccount", CaseContractClawbackFromAccount},
+		{"CaseContractClawbackFromContract", CaseContractClawbackFromContract},
+	}
+
+	for _, tt := range tests {
+		t.Run(fmt.Sprintf("Soroban Processing Disabled = %v. ", DisabledSoroban)+tt.name, func(t *testing.T) {
+			tt.fn(t)
+		})
+	}
+}
+
 // Tests use precompiled wasm bin files that are added to the testdata directory.
 // Refer to ./services/horizon/internal/integration/contracts/README.md on how to recompile
 // contract code if needed to new wasm.
 
-func TestContractMintToAccount(t *testing.T) {
+func createSAC(itest *integration.Test, asset xdr.Asset) {
+	invokeHostFunction := &txnbuild.InvokeHostFunction{
+		HostFunction: xdr.HostFunction{
+			Type: xdr.HostFunctionTypeHostFunctionTypeCreateContract,
+			CreateContract: &xdr.CreateContractArgs{
+				ContractIdPreimage: xdr.ContractIdPreimage{
+					Type:      xdr.ContractIdPreimageTypeContractIdPreimageFromAsset,
+					FromAsset: &asset,
+				},
+				Executable: xdr.ContractExecutable{
+					Type:     xdr.ContractExecutableTypeContractExecutableStellarAsset,
+					WasmHash: nil,
+				},
+			},
+		},
+		SourceAccount: itest.Master().Address(),
+	}
+	_, _, preFlightOp := assertInvokeHostFnSucceeds(itest, itest.Master(), invokeHostFunction)
+	sourceAccount, extendTTLOp, minFee := itest.PreflightExtendExpiration(
+		itest.Master().Address(),
+		preFlightOp.Ext.SorobanData.Resources.Footprint.ReadWrite,
+		LongTermTTL,
+	)
+	itest.MustSubmitOperationsWithFee(&sourceAccount, itest.Master(), minFee+txnbuild.MinBaseFee, &extendTTLOp)
+}
+
+func invokeStoreSet(
+	itest *integration.Test,
+	storeContractID xdr.Hash,
+	ledgerEntryData xdr.LedgerEntryData,
+) *txnbuild.InvokeHostFunction {
+	key := ledgerEntryData.MustContractData().Key
+	val := ledgerEntryData.MustContractData().Val
+	return &txnbuild.InvokeHostFunction{
+		HostFunction: xdr.HostFunction{
+			Type: xdr.HostFunctionTypeHostFunctionTypeInvokeContract,
+			InvokeContract: &xdr.InvokeContractArgs{
+				ContractAddress: contractIDParam(storeContractID),
+				FunctionName:    "set",
+				Args: xdr.ScVec{
+					key,
+					val,
+				},
+			},
+		},
+		SourceAccount: itest.Master().Address(),
+	}
+}
+
+func invokeStoreRemove(
+	itest *integration.Test,
+	storeContractID xdr.Hash,
+	ledgerKey xdr.LedgerKey,
+) *txnbuild.InvokeHostFunction {
+	return &txnbuild.InvokeHostFunction{
+		HostFunction: xdr.HostFunction{
+			Type: xdr.HostFunctionTypeHostFunctionTypeInvokeContract,
+			InvokeContract: &xdr.InvokeContractArgs{
+				ContractAddress: contractIDParam(storeContractID),
+				FunctionName:    "remove",
+				Args: xdr.ScVec{
+					ledgerKey.MustContractData().Key,
+				},
+			},
+		},
+		SourceAccount: itest.Master().Address(),
+	}
+}
+
+func CaseContractMintToAccount(t *testing.T) {
 	if integration.GetCoreMaxSupportedProtocol() < 20 {
 		t.Skip("This test run does not support less than Protocol 20")
 	}
 
 	itest := integration.NewTest(t, integration.Config{
-		ProtocolVersion:    20,
-		HorizonEnvironment: map[string]string{"INGEST_DISABLE_STATE_VERIFICATION": "true", "CONNECTION_TIMEOUT": "360000"},
-		EnableSorobanRPC:   true,
+		ProtocolVersion: 20,
+		HorizonEnvironment: map[string]string{
+			"DISABLE_SOROBAN_INGEST": fmt.Sprint(DisabledSoroban),
+		},
+		EnableSorobanRPC: true,
 	})
 
 	issuer := itest.Master().Address()
@@ -72,17 +181,22 @@ func TestContractMintToAccount(t *testing.T) {
 		balanceContracts:         big.NewInt(0),
 		contractID:               stellarAssetContractID(itest, asset),
 	})
-
-	fx := getTxEffects(itest, mintTx, asset)
-	require.Len(t, fx, 1)
-	creditEffect := assertContainsEffect(t, fx,
-		effects.EffectAccountCredited)[0].(effects.AccountCredited)
-	assert.Equal(t, recipientKp.Address(), creditEffect.Account)
-	assert.Equal(t, issuer, creditEffect.Asset.Issuer)
-	assert.Equal(t, code, creditEffect.Asset.Code)
-	assert.Equal(t, "20.0000000", creditEffect.Amount)
 	assertEventPayments(itest, mintTx, asset, "", recipient.GetAccountID(), "mint", "20.0000000")
 
+	if !DisabledSoroban {
+		fx := getTxEffects(itest, mintTx, asset)
+		require.Len(t, fx, 1)
+		creditEffect := assertContainsEffect(t, fx,
+			effects.EffectAccountCredited)[0].(effects.AccountCredited)
+		assert.Equal(t, recipientKp.Address(), creditEffect.Account)
+		assert.Equal(t, issuer, creditEffect.Asset.Issuer)
+		assert.Equal(t, code, creditEffect.Asset.Code)
+		assert.Equal(t, "20.0000000", creditEffect.Amount)
+	} else {
+		fx := getTxEffects(itest, mintTx, asset)
+		require.Len(t, fx, 0)
+	}
+
 	otherRecipientKp, otherRecipient := itest.CreateAccount("100")
 	itest.MustEstablishTrustline(otherRecipientKp, otherRecipient, txnbuild.MustAssetFromXDR(asset))
 
@@ -94,12 +208,6 @@ func TestContractMintToAccount(t *testing.T) {
 	)
 	assertContainsBalance(itest, recipientKp, issuer, code, amount.MustParse("20"))
 	assertContainsBalance(itest, otherRecipientKp, issuer, code, amount.MustParse("30"))
-
-	fx = getTxEffects(itest, transferTx, asset)
-	assert.Len(t, fx, 2)
-	assertContainsEffect(t, fx,
-		effects.EffectAccountCredited,
-		effects.EffectAccountDebited)
 	assertAssetStats(itest, assetStats{
 		code:                     code,
 		issuer:                   issuer,
@@ -111,41 +219,28 @@ func TestContractMintToAccount(t *testing.T) {
 		balanceContracts:         big.NewInt(0),
 		contractID:               stellarAssetContractID(itest, asset),
 	})
-}
 
-func createSAC(itest *integration.Test, asset xdr.Asset) {
-	invokeHostFunction := &txnbuild.InvokeHostFunction{
-		HostFunction: xdr.HostFunction{
-			Type: xdr.HostFunctionTypeHostFunctionTypeCreateContract,
-			CreateContract: &xdr.CreateContractArgs{
-				ContractIdPreimage: xdr.ContractIdPreimage{
-					Type:      xdr.ContractIdPreimageTypeContractIdPreimageFromAsset,
-					FromAsset: &asset,
-				},
-				Executable: xdr.ContractExecutable{
-					Type:     xdr.ContractExecutableTypeContractExecutableStellarAsset,
-					WasmHash: nil,
-				},
-			},
-		},
-		SourceAccount: itest.Master().Address(),
+	if !DisabledSoroban {
+		fx := getTxEffects(itest, transferTx, asset)
+		assert.Len(t, fx, 2)
+		assertContainsEffect(t, fx,
+			effects.EffectAccountCredited,
+			effects.EffectAccountDebited)
+	} else {
+		fx := getTxEffects(itest, transferTx, asset)
+		require.Len(t, fx, 0)
 	}
-	_, _, preFlightOp := assertInvokeHostFnSucceeds(itest, itest.Master(), invokeHostFunction)
-	sourceAccount, extendTTLOp, minFee := itest.PreflightExtendExpiration(
-		itest.Master().Address(),
-		preFlightOp.Ext.SorobanData.Resources.Footprint.ReadWrite,
-		LongTermTTL,
-	)
-	itest.MustSubmitOperationsWithFee(&sourceAccount, itest.Master(), minFee+txnbuild.MinBaseFee, &extendTTLOp)
 }
 
-func TestContractMintToContract(t *testing.T) {
+func CaseContractMintToContract(t *testing.T) {
 	if integration.GetCoreMaxSupportedProtocol() < 20 {
 		t.Skip("This test run does not support less than Protocol 20")
 	}
 
 	itest := integration.NewTest(t, integration.Config{
-		ProtocolVersion:  20,
+		ProtocolVersion: 20,
+		HorizonEnvironment: map[string]string{
+			"DISABLE_SOROBAN_INGEST": fmt.Sprint(DisabledSoroban)},
 		EnableSorobanRPC: true,
 	})
 
@@ -170,19 +265,25 @@ func TestContractMintToContract(t *testing.T) {
 			i128Param(int64(mintAmount.Hi), uint64(mintAmount.Lo)),
 			contractAddressParam(recipientContractID)),
 	)
-	assertContainsEffect(t, getTxEffects(itest, mintTx, asset),
-		effects.EffectContractCredited)
 
-	balanceAmount, _, _ := assertInvokeHostFnSucceeds(
-		itest,
-		itest.Master(),
-		contractBalance(itest, issuer, asset, recipientContractID),
-	)
-	assert.Equal(itest.CurrentTest(), xdr.ScValTypeScvI128, balanceAmount.Type)
-	assert.Equal(itest.CurrentTest(), xdr.Uint64(math.MaxUint64-3), (*balanceAmount.I128).Lo)
-	assert.Equal(itest.CurrentTest(), xdr.Int64(math.MaxInt64), (*balanceAmount.I128).Hi)
 	assertEventPayments(itest, mintTx, asset, "", strkeyRecipientContractID, "mint", amount.String128(mintAmount))
 
+	if !DisabledSoroban {
+		assertContainsEffect(t, getTxEffects(itest, mintTx, asset),
+			effects.EffectContractCredited)
+
+		balanceAmount, _, _ := assertInvokeHostFnSucceeds(
+			itest,
+			itest.Master(),
+			contractBalance(itest, issuer, asset, recipientContractID),
+		)
+		assert.Equal(itest.CurrentTest(), xdr.ScValTypeScvI128, balanceAmount.Type)
+		assert.Equal(itest.CurrentTest(), xdr.Uint64(math.MaxUint64-3), (*balanceAmount.I128).Lo)
+		assert.Equal(itest.CurrentTest(), xdr.Int64(math.MaxInt64), (*balanceAmount.I128).Hi)
+	} else {
+		fx := getTxEffects(itest, mintTx, asset)
+		require.Len(t, fx, 0)
+	}
 	// calling transfer from the issuer account will also mint the asset
 	_, transferTx, _ := assertInvokeHostFnSucceeds(
 		itest,
@@ -190,19 +291,6 @@ func TestContractMintToContract(t *testing.T) {
 		transferWithAmount(itest, issuer, asset, i128Param(0, 3), contractAddressParam(recipientContractID)),
 	)
 
-	assertContainsEffect(t, getTxEffects(itest, transferTx, asset),
-		effects.EffectAccountDebited,
-		effects.EffectContractCredited)
-
-	balanceAmount, _, _ = assertInvokeHostFnSucceeds(
-		itest,
-		itest.Master(),
-		contractBalance(itest, issuer, asset, recipientContractID),
-	)
-	assert.Equal(itest.CurrentTest(), xdr.ScValTypeScvI128, balanceAmount.Type)
-	assert.Equal(itest.CurrentTest(), xdr.Uint64(math.MaxUint64), (*balanceAmount.I128).Lo)
-	assert.Equal(itest.CurrentTest(), xdr.Int64(math.MaxInt64), (*balanceAmount.I128).Hi)
-
 	// 2^127 - 1
 	balanceContracts := new(big.Int).Lsh(big.NewInt(1), 127)
 	balanceContracts.Sub(balanceContracts, big.NewInt(1))
@@ -217,9 +305,27 @@ func TestContractMintToContract(t *testing.T) {
 		balanceContracts:         balanceContracts,
 		contractID:               stellarAssetContractID(itest, asset),
 	})
+
+	if !DisabledSoroban {
+		assertContainsEffect(t, getTxEffects(itest, transferTx, asset),
+			effects.EffectAccountDebited,
+			effects.EffectContractCredited)
+
+		balanceAmount, _, _ := assertInvokeHostFnSucceeds(
+			itest,
+			itest.Master(),
+			contractBalance(itest, issuer, asset, recipientContractID),
+		)
+		assert.Equal(itest.CurrentTest(), xdr.ScValTypeScvI128, balanceAmount.Type)
+		assert.Equal(itest.CurrentTest(), xdr.Uint64(math.MaxUint64), (*balanceAmount.I128).Lo)
+		assert.Equal(itest.CurrentTest(), xdr.Int64(math.MaxInt64), (*balanceAmount.I128).Hi)
+	} else {
+		fx := getTxEffects(itest, transferTx, asset)
+		require.Len(t, fx, 0)
+	}
 }
 
-func TestExpirationAndRestoration(t *testing.T) {
+func CaseExpirationAndRestoration(t *testing.T) {
 	if integration.GetCoreMaxSupportedProtocol() < 20 {
 		t.Skip("This test run does not support less than Protocol 20")
 	}
@@ -232,6 +338,7 @@ func TestExpirationAndRestoration(t *testing.T) {
 			// a fake asset contract in the horizon db and we don't
 			// want state verification to detect this
 			"ingest-disable-state-verification": "true",
+			"disable-soroban-ingest":            fmt.Sprint(DisabledSoroban),
 		},
 	})
 
@@ -294,6 +401,7 @@ func TestExpirationAndRestoration(t *testing.T) {
 		LongTermTTL,
 	)
 	itest.MustSubmitOperationsWithFee(&sourceAccount, itest.Master(), minFee+txnbuild.MinBaseFee, &extendTTLOp)
+
 	assertAssetStats(itest, assetStats{
 		code:                     code,
 		issuer:                   issuer,
@@ -321,6 +429,16 @@ func TestExpirationAndRestoration(t *testing.T) {
 			balanceToExpire,
 		),
 	)
+
+	balanceToExpireLedgerKey := xdr.LedgerKey{
+		Type: xdr.LedgerEntryTypeContractData,
+		ContractData: &xdr.LedgerKeyContractData{
+			Contract:   balanceToExpire.ContractData.Contract,
+			Key:        balanceToExpire.ContractData.Key,
+			Durability: balanceToExpire.ContractData.Durability,
+		},
+	}
+
 	assertAssetStats(itest, assetStats{
 		code:                     code,
 		issuer:                   issuer,
@@ -333,14 +451,6 @@ func TestExpirationAndRestoration(t *testing.T) {
 		contractID:               storeContractID,
 	})
 
-	balanceToExpireLedgerKey := xdr.LedgerKey{
-		Type: xdr.LedgerEntryTypeContractData,
-		ContractData: &xdr.LedgerKeyContractData{
-			Contract:   balanceToExpire.ContractData.Contract,
-			Key:        balanceToExpire.ContractData.Key,
-			Durability: balanceToExpire.ContractData.Durability,
-		},
-	}
 	// The TESTING_MINIMUM_PERSISTENT_ENTRY_LIFETIME=10 configuration in stellar-core
 	// will ensure that the ledger entry expires after 10 ledgers.
 	// Because ARTIFICIALLY_ACCELERATE_TIME_FOR_TESTING is set to true, 10 ledgers
@@ -372,6 +482,7 @@ func TestExpirationAndRestoration(t *testing.T) {
 			),
 		),
 	)
+
 	assertAssetStats(itest, assetStats{
 		code:                     code,
 		issuer:                   issuer,
@@ -390,6 +501,7 @@ func TestExpirationAndRestoration(t *testing.T) {
 		balanceToExpireLedgerKey,
 	)
 	itest.MustSubmitOperationsWithFee(&sourceAccount, itest.Master(), minFee+txnbuild.MinBaseFee, &restoreFootprint)
+
 	assertAssetStats(itest, assetStats{
 		code:                     code,
 		issuer:                   issuer,
@@ -419,6 +531,7 @@ func TestExpirationAndRestoration(t *testing.T) {
 			),
 		),
 	)
+
 	assertAssetStats(itest, assetStats{
 		code:                     code,
 		issuer:                   issuer,
@@ -444,6 +557,7 @@ func TestExpirationAndRestoration(t *testing.T) {
 			),
 		),
 	)
+
 	assertAssetStats(itest, assetStats{
 		code:                     code,
 		issuer:                   issuer,
@@ -457,56 +571,15 @@ func TestExpirationAndRestoration(t *testing.T) {
 	})
 }
 
-func invokeStoreSet(
-	itest *integration.Test,
-	storeContractID xdr.Hash,
-	ledgerEntryData xdr.LedgerEntryData,
-) *txnbuild.InvokeHostFunction {
-	key := ledgerEntryData.MustContractData().Key
-	val := ledgerEntryData.MustContractData().Val
-	return &txnbuild.InvokeHostFunction{
-		HostFunction: xdr.HostFunction{
-			Type: xdr.HostFunctionTypeHostFunctionTypeInvokeContract,
-			InvokeContract: &xdr.InvokeContractArgs{
-				ContractAddress: contractIDParam(storeContractID),
-				FunctionName:    "set",
-				Args: xdr.ScVec{
-					key,
-					val,
-				},
-			},
-		},
-		SourceAccount: itest.Master().Address(),
-	}
-}
-
-func invokeStoreRemove(
-	itest *integration.Test,
-	storeContractID xdr.Hash,
-	ledgerKey xdr.LedgerKey,
-) *txnbuild.InvokeHostFunction {
-	return &txnbuild.InvokeHostFunction{
-		HostFunction: xdr.HostFunction{
-			Type: xdr.HostFunctionTypeHostFunctionTypeInvokeContract,
-			InvokeContract: &xdr.InvokeContractArgs{
-				ContractAddress: contractIDParam(storeContractID),
-				FunctionName:    "remove",
-				Args: xdr.ScVec{
-					ledgerKey.MustContractData().Key,
-				},
-			},
-		},
-		SourceAccount: itest.Master().Address(),
-	}
-}
-
-func TestContractTransferBetweenAccounts(t *testing.T) {
+func CaseContractTransferBetweenAccounts(t *testing.T) {
 	if integration.GetCoreMaxSupportedProtocol() < 20 {
 		t.Skip("This test run does not support less than Protocol 20")
 	}
 
 	itest := integration.NewTest(t, integration.Config{
-		ProtocolVersion:  20,
+		ProtocolVersion: 20,
+		HorizonEnvironment: map[string]string{
+			"DISABLE_SOROBAN_INGEST": fmt.Sprint(DisabledSoroban)},
 		EnableSorobanRPC: true,
 	})
 
@@ -534,6 +607,7 @@ func TestContractTransferBetweenAccounts(t *testing.T) {
 	)
 
 	assertContainsBalance(itest, recipientKp, issuer, code, amount.MustParse("1000"))
+
 	assertAssetStats(itest, assetStats{
 		code:                     code,
 		issuer:                   issuer,
@@ -557,10 +631,6 @@ func TestContractTransferBetweenAccounts(t *testing.T) {
 
 	assertContainsBalance(itest, recipientKp, issuer, code, amount.MustParse("970"))
 	assertContainsBalance(itest, otherRecipientKp, issuer, code, amount.MustParse("30"))
-
-	fx := getTxEffects(itest, transferTx, asset)
-	assert.NotEmpty(t, fx)
-	assertContainsEffect(t, fx, effects.EffectAccountCredited, effects.EffectAccountDebited)
 	assertAssetStats(itest, assetStats{
 		code:                     code,
 		issuer:                   issuer,
@@ -573,15 +643,26 @@ func TestContractTransferBetweenAccounts(t *testing.T) {
 		contractID:               stellarAssetContractID(itest, asset),
 	})
 	assertEventPayments(itest, transferTx, asset, recipientKp.Address(), otherRecipient.GetAccountID(), "transfer", "30.0000000")
+
+	if !DisabledSoroban {
+		fx := getTxEffects(itest, transferTx, asset)
+		assert.NotEmpty(t, fx)
+		assertContainsEffect(t, fx, effects.EffectAccountCredited, effects.EffectAccountDebited)
+	} else {
+		fx := getTxEffects(itest, transferTx, asset)
+		require.Len(t, fx, 0)
+	}
 }
 
-func TestContractTransferBetweenAccountAndContract(t *testing.T) {
+func CaseContractTransferBetweenAccountAndContract(t *testing.T) {
 	if integration.GetCoreMaxSupportedProtocol() < 20 {
 		t.Skip("This test run does not support less than Protocol 20")
 	}
 
 	itest := integration.NewTest(t, integration.Config{
-		ProtocolVersion:  20,
+		ProtocolVersion: 20,
+		HorizonEnvironment: map[string]string{
+			"DISABLE_SOROBAN_INGEST": fmt.Sprint(DisabledSoroban)},
 		EnableSorobanRPC: true,
 	})
 
@@ -627,9 +708,6 @@ func TestContractTransferBetweenAccountAndContract(t *testing.T) {
 		mint(itest, issuer, asset, "1000", contractAddressParam(recipientContractID)),
 	)
 	assertContainsBalance(itest, recipientKp, issuer, code, amount.MustParse("1000"))
-	assertContainsEffect(t, getTxEffects(itest, mintTx, asset),
-		effects.EffectContractCredited)
-
 	assertAssetStats(itest, assetStats{
 		code:                     code,
 		issuer:                   issuer,
@@ -642,6 +720,14 @@ func TestContractTransferBetweenAccountAndContract(t *testing.T) {
 		contractID:               stellarAssetContractID(itest, asset),
 	})
 
+	if !DisabledSoroban {
+		assertContainsEffect(t, getTxEffects(itest, mintTx, asset),
+			effects.EffectContractCredited)
+	} else {
+		fx := getTxEffects(itest, mintTx, asset)
+		require.Len(t, fx, 0)
+	}
+
 	// transfer from account to contract
 	_, transferTx, _ := assertInvokeHostFnSucceeds(
 		itest,
@@ -649,8 +735,6 @@ func TestContractTransferBetweenAccountAndContract(t *testing.T) {
 		transfer(itest, recipientKp.Address(), asset, "30", contractAddressParam(recipientContractID)),
 	)
 	assertContainsBalance(itest, recipientKp, issuer, code, amount.MustParse("970"))
-	assertContainsEffect(t, getTxEffects(itest, transferTx, asset),
-		effects.EffectAccountDebited, effects.EffectContractCredited)
 	assertAssetStats(itest, assetStats{
 		code:                     code,
 		issuer:                   issuer,
@@ -664,14 +748,19 @@ func TestContractTransferBetweenAccountAndContract(t *testing.T) {
 	})
 	assertEventPayments(itest, transferTx, asset, recipientKp.Address(), strkeyRecipientContractID, "transfer", "30.0000000")
 
+	if !DisabledSoroban {
+		assertContainsEffect(t, getTxEffects(itest, transferTx, asset),
+			effects.EffectAccountDebited, effects.EffectContractCredited)
+	} else {
+		fx := getTxEffects(itest, transferTx, asset)
+		require.Len(t, fx, 0)
+	}
 	// transfer from contract to account
 	_, transferTx, _ = assertInvokeHostFnSucceeds(
 		itest,
 		recipientKp,
 		transferFromContract(itest, recipientKp.Address(), asset, recipientContractID, recipientContractHash, "500", accountAddressParam(recipient.GetAccountID())),
 	)
-	assertContainsEffect(t, getTxEffects(itest, transferTx, asset),
-		effects.EffectContractDebited, effects.EffectAccountCredited)
 	assertContainsBalance(itest, recipientKp, issuer, code, amount.MustParse("1470"))
 	assertAssetStats(itest, assetStats{
 		code:                     code,
@@ -686,6 +775,13 @@ func TestContractTransferBetweenAccountAndContract(t *testing.T) {
 	})
 	assertEventPayments(itest, transferTx, asset, strkeyRecipientContractID, recipientKp.Address(), "transfer", "500.0000000")
 
+	if DisabledSoroban {
+		fx := getTxEffects(itest, transferTx, asset)
+		require.Len(t, fx, 0)
+		return
+	}
+	assertContainsEffect(t, getTxEffects(itest, transferTx, asset),
+		effects.EffectContractDebited, effects.EffectAccountCredited)
 	balanceAmount, _, _ := assertInvokeHostFnSucceeds(
 		itest,
 		itest.Master(),
@@ -696,13 +792,15 @@ func TestContractTransferBetweenAccountAndContract(t *testing.T) {
 	assert.Equal(itest.CurrentTest(), xdr.Int64(0), (*balanceAmount.I128).Hi)
 }
 
-func TestContractTransferBetweenContracts(t *testing.T) {
+func CaseContractTransferBetweenContracts(t *testing.T) {
 	if integration.GetCoreMaxSupportedProtocol() < 20 {
 		t.Skip("This test run does not support less than Protocol 20")
 	}
 
 	itest := integration.NewTest(t, integration.Config{
-		ProtocolVersion:  20,
+		ProtocolVersion: 20,
+		HorizonEnvironment: map[string]string{
+			"DISABLE_SOROBAN_INGEST": fmt.Sprint(DisabledSoroban)},
 		EnableSorobanRPC: true,
 	})
 
@@ -742,8 +840,28 @@ func TestContractTransferBetweenContracts(t *testing.T) {
 		itest.Master(),
 		transferFromContract(itest, issuer, asset, emitterContractID, emitterContractHash, "10", contractAddressParam(recipientContractID)),
 	)
-	assertContainsEffect(t, getTxEffects(itest, transferTx, asset),
-		effects.EffectContractCredited, effects.EffectContractDebited)
+
+	assertAssetStats(itest, assetStats{
+		code:                     code,
+		issuer:                   issuer,
+		numAccounts:              0,
+		balanceAccounts:          0,
+		balanceArchivedContracts: big.NewInt(0),
+		numArchivedContracts:     0,
+		numContracts:             2,
+		balanceContracts:         big.NewInt(int64(amount.MustParse("1000"))),
+		contractID:               stellarAssetContractID(itest, asset),
+	})
+	assertEventPayments(itest, transferTx, asset, strkeyEmitterContractID, strkeyRecipientContractID, "transfer", "10.0000000")
+
+	if !DisabledSoroban {
+		assertContainsEffect(t, getTxEffects(itest, transferTx, asset),
+			effects.EffectContractCredited, effects.EffectContractDebited)
+	} else {
+		fx := getTxEffects(itest, transferTx, asset)
+		require.Len(t, fx, 0)
+		return
+	}
 
 	// Check balances of emitter and recipient
 	emitterBalanceAmount, _, _ := assertInvokeHostFnSucceeds(
@@ -763,28 +881,17 @@ func TestContractTransferBetweenContracts(t *testing.T) {
 	assert.Equal(itest.CurrentTest(), xdr.ScValTypeScvI128, recipientBalanceAmount.Type)
 	assert.Equal(itest.CurrentTest(), xdr.Uint64(100000000), (*recipientBalanceAmount.I128).Lo)
 	assert.Equal(itest.CurrentTest(), xdr.Int64(0), (*recipientBalanceAmount.I128).Hi)
-
-	assertAssetStats(itest, assetStats{
-		code:                     code,
-		issuer:                   issuer,
-		numAccounts:              0,
-		balanceAccounts:          0,
-		balanceArchivedContracts: big.NewInt(0),
-		numArchivedContracts:     0,
-		numContracts:             2,
-		balanceContracts:         big.NewInt(int64(amount.MustParse("1000"))),
-		contractID:               stellarAssetContractID(itest, asset),
-	})
-	assertEventPayments(itest, transferTx, asset, strkeyEmitterContractID, strkeyRecipientContractID, "transfer", "10.0000000")
 }
 
-func TestContractBurnFromAccount(t *testing.T) {
+func CaseContractBurnFromAccount(t *testing.T) {
 	if integration.GetCoreMaxSupportedProtocol() < 20 {
 		t.Skip("This test run does not support less than Protocol 20")
 	}
 
 	itest := integration.NewTest(t, integration.Config{
-		ProtocolVersion:  20,
+		ProtocolVersion: 20,
+		HorizonEnvironment: map[string]string{
+			"DISABLE_SOROBAN_INGEST": fmt.Sprint(DisabledSoroban)},
 		EnableSorobanRPC: true,
 	})
 
@@ -830,16 +937,6 @@ func TestContractBurnFromAccount(t *testing.T) {
 		burn(itest, recipientKp.Address(), asset, "500"),
 	)
 
-	fx := getTxEffects(itest, burnTx, asset)
-	require.Len(t, fx, 1)
-	assetEffects := assertContainsEffect(t, fx, effects.EffectAccountDebited)
-	require.GreaterOrEqual(t, len(assetEffects), 1)
-	burnEffect := assetEffects[0].(effects.AccountDebited)
-
-	assert.Equal(t, issuer, burnEffect.Asset.Issuer)
-	assert.Equal(t, code, burnEffect.Asset.Code)
-	assert.Equal(t, "500.0000000", burnEffect.Amount)
-	assert.Equal(t, recipientKp.Address(), burnEffect.Account)
 	assertAssetStats(itest, assetStats{
 		code:                     code,
 		issuer:                   issuer,
@@ -852,15 +949,33 @@ func TestContractBurnFromAccount(t *testing.T) {
 		contractID:               stellarAssetContractID(itest, asset),
 	})
 	assertEventPayments(itest, burnTx, asset, recipientKp.Address(), "", "burn", "500.0000000")
+
+	if !DisabledSoroban {
+		fx := getTxEffects(itest, burnTx, asset)
+		require.Len(t, fx, 1)
+		assetEffects := assertContainsEffect(t, fx, effects.EffectAccountDebited)
+		require.GreaterOrEqual(t, len(assetEffects), 1)
+		burnEffect := assetEffects[0].(effects.AccountDebited)
+
+		assert.Equal(t, issuer, burnEffect.Asset.Issuer)
+		assert.Equal(t, code, burnEffect.Asset.Code)
+		assert.Equal(t, "500.0000000", burnEffect.Amount)
+		assert.Equal(t, recipientKp.Address(), burnEffect.Account)
+	} else {
+		fx := getTxEffects(itest, burnTx, asset)
+		require.Len(t, fx, 0)
+	}
 }
 
-func TestContractBurnFromContract(t *testing.T) {
+func CaseContractBurnFromContract(t *testing.T) {
 	if integration.GetCoreMaxSupportedProtocol() < 20 {
 		t.Skip("This test run does not support less than Protocol 20")
 	}
 
 	itest := integration.NewTest(t, integration.Config{
-		ProtocolVersion:  20,
+		ProtocolVersion: 20,
+		HorizonEnvironment: map[string]string{
+			"DISABLE_SOROBAN_INGEST": fmt.Sprint(DisabledSoroban)},
 		EnableSorobanRPC: true,
 	})
 
@@ -895,19 +1010,6 @@ func TestContractBurnFromContract(t *testing.T) {
 		burnSelf(itest, issuer, asset, recipientContractID, recipientContractHash, "10"),
 	)
 
-	balanceAmount, _, _ := assertInvokeHostFnSucceeds(
-		itest,
-		itest.Master(),
-		contractBalance(itest, issuer, asset, recipientContractID),
-	)
-
-	assert.Equal(itest.CurrentTest(), xdr.ScValTypeScvI128, balanceAmount.Type)
-	assert.Equal(itest.CurrentTest(), xdr.Uint64(9900000000), (*balanceAmount.I128).Lo)
-	assert.Equal(itest.CurrentTest(), xdr.Int64(0), (*balanceAmount.I128).Hi)
-
-	assertContainsEffect(t, getTxEffects(itest, burnTx, asset),
-		effects.EffectContractDebited)
-
 	assertAssetStats(itest, assetStats{
 		code:                     code,
 		issuer:                   issuer,
@@ -920,15 +1022,35 @@ func TestContractBurnFromContract(t *testing.T) {
 		contractID:               stellarAssetContractID(itest, asset),
 	})
 	assertEventPayments(itest, burnTx, asset, strkeyRecipientContractID, "", "burn", "10.0000000")
+
+	if !DisabledSoroban {
+		balanceAmount, _, _ := assertInvokeHostFnSucceeds(
+			itest,
+			itest.Master(),
+			contractBalance(itest, issuer, asset, recipientContractID),
+		)
+
+		assert.Equal(itest.CurrentTest(), xdr.ScValTypeScvI128, balanceAmount.Type)
+		assert.Equal(itest.CurrentTest(), xdr.Uint64(9900000000), (*balanceAmount.I128).Lo)
+		assert.Equal(itest.CurrentTest(), xdr.Int64(0), (*balanceAmount.I128).Hi)
+
+		assertContainsEffect(t, getTxEffects(itest, burnTx, asset),
+			effects.EffectContractDebited)
+	} else {
+		fx := getTxEffects(itest, burnTx, asset)
+		require.Len(t, fx, 0)
+	}
 }
 
-func TestContractClawbackFromAccount(t *testing.T) {
+func CaseContractClawbackFromAccount(t *testing.T) {
 	if integration.GetCoreMaxSupportedProtocol() < 20 {
 		t.Skip("This test run does not support less than Protocol 20")
 	}
 
 	itest := integration.NewTest(t, integration.Config{
-		ProtocolVersion:  20,
+		ProtocolVersion: 20,
+		HorizonEnvironment: map[string]string{
+			"DISABLE_SOROBAN_INGEST": fmt.Sprint(DisabledSoroban)},
 		EnableSorobanRPC: true,
 	})
 
@@ -966,6 +1088,7 @@ func TestContractClawbackFromAccount(t *testing.T) {
 	)
 
 	assertContainsBalance(itest, recipientKp, issuer, code, amount.MustParse("1000"))
+
 	assertAssetStats(itest, assetStats{
 		code:                     code,
 		issuer:                   issuer,
@@ -983,8 +1106,6 @@ func TestContractClawbackFromAccount(t *testing.T) {
 		itest.Master(),
 		clawback(itest, issuer, asset, "1000", accountAddressParam(recipientKp.Address())),
 	)
-
-	assertContainsEffect(t, getTxEffects(itest, clawTx, asset), effects.EffectAccountDebited)
 	assertContainsBalance(itest, recipientKp, issuer, code, 0)
 	assertAssetStats(itest, assetStats{
 		code:                     code,
@@ -998,15 +1119,24 @@ func TestContractClawbackFromAccount(t *testing.T) {
 		contractID:               stellarAssetContractID(itest, asset),
 	})
 	assertEventPayments(itest, clawTx, asset, recipientKp.Address(), "", "clawback", "1000.0000000")
+
+	if !DisabledSoroban {
+		assertContainsEffect(t, getTxEffects(itest, clawTx, asset), effects.EffectAccountDebited)
+	} else {
+		fx := getTxEffects(itest, clawTx, asset)
+		require.Len(t, fx, 0)
+	}
 }
 
-func TestContractClawbackFromContract(t *testing.T) {
+func CaseContractClawbackFromContract(t *testing.T) {
 	if integration.GetCoreMaxSupportedProtocol() < 20 {
 		t.Skip("This test run does not support less than Protocol 20")
 	}
 
 	itest := integration.NewTest(t, integration.Config{
-		ProtocolVersion:  20,
+		ProtocolVersion: 20,
+		HorizonEnvironment: map[string]string{
+			"DISABLE_SOROBAN_INGEST": fmt.Sprint(DisabledSoroban)},
 		EnableSorobanRPC: true,
 	})
 
@@ -1044,19 +1174,6 @@ func TestContractClawbackFromContract(t *testing.T) {
 		itest.Master(),
 		clawback(itest, issuer, asset, "10", contractAddressParam(recipientContractID)),
 	)
-
-	balanceAmount, _, _ := assertInvokeHostFnSucceeds(
-		itest,
-		itest.Master(),
-		contractBalance(itest, issuer, asset, recipientContractID),
-	)
-	assert.Equal(itest.CurrentTest(), xdr.ScValTypeScvI128, balanceAmount.Type)
-	assert.Equal(itest.CurrentTest(), xdr.Uint64(9900000000), (*balanceAmount.I128).Lo)
-	assert.Equal(itest.CurrentTest(), xdr.Int64(0), (*balanceAmount.I128).Hi)
-
-	assertContainsEffect(t, getTxEffects(itest, clawTx, asset),
-		effects.EffectContractDebited)
-
 	assertAssetStats(itest, assetStats{
 		code:                     code,
 		issuer:                   issuer,
@@ -1069,6 +1186,23 @@ func TestContractClawbackFromContract(t *testing.T) {
 		contractID:               stellarAssetContractID(itest, asset),
 	})
 	assertEventPayments(itest, clawTx, asset, strkeyRecipientContractID, "", "clawback", "10.0000000")
+
+	if !DisabledSoroban {
+		balanceAmount, _, _ := assertInvokeHostFnSucceeds(
+			itest,
+			itest.Master(),
+			contractBalance(itest, issuer, asset, recipientContractID),
+		)
+		assert.Equal(itest.CurrentTest(), xdr.ScValTypeScvI128, balanceAmount.Type)
+		assert.Equal(itest.CurrentTest(), xdr.Uint64(9900000000), (*balanceAmount.I128).Lo)
+		assert.Equal(itest.CurrentTest(), xdr.Int64(0), (*balanceAmount.I128).Hi)
+
+		assertContainsEffect(t, getTxEffects(itest, clawTx, asset),
+			effects.EffectContractDebited)
+	} else {
+		fx := getTxEffects(itest, clawTx, asset)
+		require.Len(t, fx, 0)
+	}
 }
 
 func assertContainsBalance(itest *integration.Test, acct *keypair.Full, issuer, code string, amt xdr.Int64) {
@@ -1179,6 +1313,12 @@ func assertEventPayments(itest *integration.Test, txHash string, asset xdr.Asset
 
 	invokeHostFn := ops.Embedded.Records[0].(operations.InvokeHostFunction)
 	assert.Equal(itest.CurrentTest(), invokeHostFn.Function, "HostFunctionTypeHostFunctionTypeInvokeContract")
+
+	if DisabledSoroban {
+		require.Equal(itest.CurrentTest(), 0, len(invokeHostFn.AssetBalanceChanges))
+		return
+	}
+
 	require.Equal(itest.CurrentTest(), 1, len(invokeHostFn.AssetBalanceChanges))
 	assetBalanceChange := invokeHostFn.AssetBalanceChanges[0]
 	assert.Equal(itest.CurrentTest(), assetBalanceChange.Amount, amount)
@@ -1400,10 +1540,6 @@ func assertInvokeHostFnSucceeds(itest *integration.Test, signer *keypair.Full, o
 	err = xdr.SafeUnmarshalBase64(clientTx.ResultXdr, &txResult)
 	require.NoError(itest.CurrentTest(), err)
 
-	var txMetaResult xdr.TransactionMeta
-	err = xdr.SafeUnmarshalBase64(clientTx.ResultMetaXdr, &txMetaResult)
-	require.NoError(itest.CurrentTest(), err)
-
 	opResults, ok := txResult.OperationResults()
 	assert.True(itest.CurrentTest(), ok)
 	assert.Equal(itest.CurrentTest(), len(opResults), 1)
@@ -1411,9 +1547,18 @@ func assertInvokeHostFnSucceeds(itest *integration.Test, signer *keypair.Full, o
 	assert.True(itest.CurrentTest(), ok)
 	assert.Equal(itest.CurrentTest(), invokeHostFunctionResult.Code, xdr.InvokeHostFunctionResultCodeInvokeHostFunctionSuccess)
 
-	returnValue := txMetaResult.MustV3().SorobanMeta.ReturnValue
+	var returnValue *xdr.ScVal
+
+	if !DisabledSoroban {
+		var txMetaResult xdr.TransactionMeta
+		err = xdr.SafeUnmarshalBase64(clientTx.ResultMetaXdr, &txMetaResult)
+		require.NoError(itest.CurrentTest(), err)
+		returnValue = &txMetaResult.MustV3().SorobanMeta.ReturnValue
+	} else {
+		verifySorobanMeta(itest.CurrentTest(), clientTx)
+	}
 
-	return &returnValue, clientTx.Hash, &preFlightOp
+	return returnValue, clientTx.Hash, &preFlightOp
 }
 
 func stellarAssetContractID(itest *integration.Test, asset xdr.Asset) xdr.Hash {