zeitgeist icon indicating copy to clipboard operation
zeitgeist copied to clipboard

`join_subsidy` and `exit_subsidy` interact incorrectly with pool after collection of subsidy

Open maltekliemann opened this issue 2 years ago • 1 comments

The following tests result in unexpected results:

#[test]
fn join_subsidy_after_collection_fails() {
    ExtBuilder::default().build().execute_with(|| {
        assert_ok!(Swaps::create_pool(
            BOB,
            ASSETS.iter().cloned().collect(),
            ASSETS.last().unwrap().clone(),
            0,
            ScoringRule::RikiddoSigmoidFeeMarketEma,
            None,
            None,
            None,
        ));
        let who = ALICE;
        let pool_id = 0;
        let min_subsidy = <Runtime as crate::Config>::MinSubsidy::get();
        assert_ok!(Currencies::deposit(ASSET_D, &who, 2 * min_subsidy));
        assert_ok!(Swaps::pool_join_subsidy(Origin::signed(who), pool_id, min_subsidy));
        assert_eq!(Swaps::end_subsidy_phase(pool_id).unwrap().result, true);
        assert!(Swaps::pool_join_subsidy(Origin::signed(who), pool_id, min_subsidy).is_err());
    });
}

This test fails with the following error message:

---- tests::join_subsidy_after_collection_fails stdout ----
thread 'tests::join_subsidy_after_collection_fails' panicked at 'assertion failed: Swaps::pool_join_subsidy(Origin::signed(who), pool_id, min_subsidy).is_err()',

Instead, it should fail because providing subsidy after collection is illegal.

#[test]
fn exit_subsidy_after_collection_fails() {
    ExtBuilder::default().build().execute_with(|| {
        assert_ok!(Swaps::create_pool(
            BOB,
            ASSETS.iter().cloned().collect(),
            ASSETS.last().unwrap().clone(),
            0,
            ScoringRule::RikiddoSigmoidFeeMarketEma,
            None,
            None,
            None,
        ));
        let who = ALICE;
        let pool_id = 0;
        let min_subsidy = <Runtime as crate::Config>::MinSubsidy::get();
        assert_ok!(Currencies::deposit(ASSET_D, &who, 10 * min_subsidy));
        assert_ok!(Swaps::pool_join_subsidy(Origin::signed(who), pool_id, 10 * min_subsidy));
        assert_eq!(Swaps::end_subsidy_phase(pool_id).unwrap().result, true);
        assert_ok!(Swaps::pool_exit_subsidy(Origin::signed(who), pool_id, min_subsidy));
    });
}

This test fails, but for the wrong reason:

---- tests::exit_subsidy_after_collection_fails stdout ----
thread 'tests::exit_subsidy_after_collection_fails' panicked at 'Expected Ok(_). Got Err(
    Module(
        ModuleError {
            index: 5,
            error: [
                22,
                0,
                0,
                0,
            ],
            message: Some(
                "NoSubsidyProvided",
            ),
        },
    ),
)',

The NoSubsidyProvided is raised because end_subsidy_phase clears the vector of subsidy providers. Instead of raising this cryptic error, exit_subsidy should fail because the pool is in an incorrect state.

maltekliemann avatar Jul 07 '22 10:07 maltekliemann

Good catch. It seems this can't be abused because it errors out (although for the wrong reason) when trying to remove subsidy from a pool after subsidy collecting state. I'll assign a low priority because nothing is in danger here.

sea212 avatar Jul 07 '22 17:07 sea212