Repository: MystenLabs/sui
File: crates/sui-core/src/accumulators/object_funds_checker/integration_tests.rs (Rust)

Code before:
                }
            ));
            effects
        };
        all_effects.push(effects);
    }
    env.authority
        .settle_accumulator_for_testing(&all_effects)
        .await;

    assert_eq!(
        env.get_latest_balance(GAS::type_tag()),
        1000 - 300 * 3 - 40 * 2
    );
}

#[tokio::test]
async fn test_object_withdraw_and_deposit_same_transaction() {
    let env = TestEnv::new().await;
    env.fund_address(env.vault_obj.into(), 1).await;

    let gas = env.oref(&env.gas_obj).await;
    // In the same transaction, we are withdrawing from the object account
    // and depositing back to the same object account twice.
    // This should result in a total withdraw amount of 2, even though
    // if we merge all accumulator events they will balance out to 0.
    let tx = TestTransactionBuilder::new(env.sender, gas, env.rgp())
        .transfer_sui_to_address_balance(
            FundSource::object_fund_owned(env.package_id, env.oref(&env.vault_obj).await),
            vec![(1, env.vault_obj.into())],
        )
        .transfer_sui_to_address_balance(
            FundSource::object_fund_owned(env.package_id, env.oref(&env.vault_obj).await),
            vec![(1, env.vault_obj.into())],
        )
        .build();
    let cert = VerifiedExecutableTransaction::new_for_testing(tx, &env.keypair);
    let digest = *cert.digest();
    let accumulator_version = env.oref(&SUI_ACCUMULATOR_ROOT_OBJECT_ID).await.1;
    let output = env
        .authority
        // Fastpath execution
        .try_execute_immediately(
            &cert,
            ExecutionEnv::new()
                .with_assigned_versions(AssignedVersions::new(vec![], Some(accumulator_version))),
            &env.epoch_store,
        )
        .await;
    assert!(matches!(output, ExecutionOutput::RetryLater));
    let effects = env

Review comment (suggestion):
do you think there's any argument to be made for tracking the running total withdrawal? i.e. if you sum `[-1, 1 , -1, 1]` in order, you never drop lower than -1.

I'm not sure its worth handling this but I could imagine someone asking about this someday.

Code after:
                    error: ExecutionFailureStatus::InsufficientFundsForWithdraw,
                    ..
                }
            ));
            effects
        };
        all_effects.push(effects);
    }
    env.authority
        .settle_accumulator_for_testing(&all_effects)
        .await;

    assert_eq!(
        env.get_latest_balance(GAS::type_tag()),
        1000 - 300 * 3 - 40 * 2
    );
}

#[tokio::test]
async fn test_object_withdraw_and_deposit_same_transaction() {
    telemetry_subscribers::init_for_testing();
    let env = TestEnv::new().await;
    env.fund_address(env.vault_obj.into(), 2).await;

    // In the same transaction, we are withdrawing from the object account
    // and depositing back to the same object account.
    // The max net withdraws for this account should be 3, because at any given moment,
    // the net withdraws is at most 3.
    // Since the account has a balance of 2, the transaction should fail.
    let gas = env.oref(&env.gas_obj).await;
    let tx = TestTransactionBuilder::new(env.sender, gas, env.rgp())
        .transfer_sui_to_address_balance(
            FundSource::object_fund_owned(env.package_id, env.oref(&env.vault_obj).await),
            vec![(3, env.vault_obj.into())],
        )
        .build();
    let cert = VerifiedExecutableTransaction::new_for_testing(tx, &env.keypair);
    let digest = *cert.digest();
    let accumulator_version = env.oref(&SUI_ACCUMULATOR_ROOT_OBJECT_ID).await.1;
    let output = env
        .authority
        .try_execute_immediately(
            &cert,
            ExecutionEnv::new()
                .with_assigned_versions(AssignedVersions::new(vec![], Some(accumulator_version))),
            &env.epoch_store,
        )
        .await;
    assert!(matches!(output, ExecutionOutput::RetryLater));
    let effects = env
        .authority