Skip to content

Commit

Permalink
fix: 🐛 amm and revenue shares cannot be concurrent
Browse files Browse the repository at this point in the history
  • Loading branch information
ignazio-bovo committed Apr 4, 2024
1 parent 3580787 commit 6a1be39
Show file tree
Hide file tree
Showing 9 changed files with 76 additions and 4 deletions.
2 changes: 1 addition & 1 deletion chain-metadata.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion query-node/chain-metadata/2003.json

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions runtime-modules/project-token/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -155,6 +155,9 @@ decl_error! {
/// Revenue split rate cannot be 0
RevenueSplitRateIsZero,

/// Cannot Issue Revenue Split with ongoing AMM
AmmActive,

// ------ Burning ------------------------------------------------------

/// Provided amount to burn is == 0
Expand Down
7 changes: 7 additions & 0 deletions runtime-modules/project-token/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1500,6 +1500,11 @@ impl<T: Config>
let token_info = Self::ensure_token_exists(token_id)?;
token_info.revenue_split.ensure_inactive::<T>()?;

ensure!(
OfferingStateOf::<T>::ensure_amm_of::<T>(&token_info).is_err(),
Error::<T>::AmmActive
);

let allocation_amount = token_info.revenue_split_rate.mul_floor(revenue_amount);

ensure!(
Expand Down Expand Up @@ -1654,6 +1659,8 @@ impl<T: Config>

let token_data = Self::ensure_token_exists(token_id)?;

token_data.ensure_can_modify_supply::<T>()?;

ensure!(
OfferingStateOf::<T>::ensure_idle_of::<T>(&token_data).is_ok(),
Error::<T>::TokenIssuanceNotInIdleState
Expand Down
20 changes: 20 additions & 0 deletions runtime-modules/project-token/src/tests/amm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -343,6 +343,26 @@ fn activation_fails_when_status_is_not_idle() {
})
}

#[test]
fn amm_activation_fails_when_revenue_split() {
build_default_test_externalities_with_balances(vec![(
member!(1).1,
DEFAULT_SPLIT_REVENUE + ExistentialDeposit::get(),
)])
.execute_with(|| {
IssueTokenFixture::default().execute_call().unwrap();
TransferFixture::default().execute_call().unwrap(); // send participation to other acc
IssueRevenueSplitFixture::default().execute_call().unwrap();

let result = ActivateAmmFixture::default().execute_call();

assert_err!(
result,
Error::<Test>::CannotModifySupplyWhenRevenueSplitsAreActive
);
})
}

#[test]
fn activation_fails_when_amm_status_already_active() {
let config = GenesisConfigBuilder::new_empty().build();
Expand Down
37 changes: 37 additions & 0 deletions runtime-modules/project-token/src/tests/split.rs
Original file line number Diff line number Diff line change
Expand Up @@ -938,6 +938,43 @@ fn exit_revenue_split_ok_with_active_and_ended_split() {
})
}

#[test]
fn issue_revenue_split_fails_with_amm_activated() {
build_default_test_externalities_with_balances(vec![(
member!(1).1,
DEFAULT_SPLIT_REVENUE + ExistentialDeposit::get(),
)])
.execute_with(|| {
IssueTokenFixture::default().execute_call().unwrap();
TransferFixture::default().execute_call().unwrap(); // send participation to other acc
ActivateAmmFixture::default().execute_call().unwrap();

let result = IssueRevenueSplitFixture::default()
.with_revenue_amount(DEFAULT_SPLIT_REVENUE)
.execute_call();

assert_err!(result, Error::<Test>::AmmActive);
})
}

#[test]
fn issue_revenue_split_ok_with_sale_activated() {
build_default_test_externalities_with_balances(vec![(
member!(1).1,
DEFAULT_SPLIT_REVENUE + ExistentialDeposit::get(),
)])
.execute_with(|| {
IssueTokenFixture::default().execute_call().unwrap();
InitTokenSaleFixture::default().execute_call().unwrap();

let result = IssueRevenueSplitFixture::default()
.with_revenue_amount(DEFAULT_SPLIT_REVENUE)
.execute_call();

assert_ok!(result);
})
}

#[test]
fn issue_revenue_split_ok_with_revenue_leftovers_retained_by_issuer() {
let leftovers = DEFAULT_SPLIT_RATE
Expand Down
4 changes: 4 additions & 0 deletions types/src/augment/augment-api-errors.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2242,6 +2242,10 @@ declare module '@polkadot/api-base/types/errors' {
* Requested account data does not exist
**/
AccountInformationDoesNotExist: AugmentedError<ApiType>;
/**
* Cannot Issue Revenue Split with ongoing AMM
**/
AmmActive: AugmentedError<ApiType>;
/**
* Unexpected arithmetic error (overflow / underflow)
**/
Expand Down
2 changes: 1 addition & 1 deletion types/src/augment/lookup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4537,7 +4537,7 @@ export default {
* Lookup605: pallet_project_token::errors::Error<T>
**/
PalletProjectTokenErrorsError: {
_enum: ['ArithmeticError', 'InsufficientTransferrableBalance', 'TokenDoesNotExist', 'AccountInformationDoesNotExist', 'TransferDestinationMemberDoesNotExist', 'MerkleProofVerificationFailure', 'TokenSymbolAlreadyInUse', 'InitialAllocationToNonExistingMember', 'AccountAlreadyExists', 'TooManyTransferOutputs', 'TokenIssuanceNotInIdleState', 'InsufficientJoyBalance', 'JoyTransferSubjectToDusting', 'AttemptToRemoveNonOwnedAccountUnderPermissionedMode', 'AttemptToRemoveNonEmptyAccount', 'CannotJoinWhitelistInPermissionlessMode', 'CannotDeissueTokenWithOutstandingAccounts', 'NoUpcomingSale', 'NoActiveSale', 'InsufficientBalanceForTokenPurchase', 'NotEnoughTokensOnSale', 'SaleStartingBlockInThePast', 'SaleAccessProofRequired', 'SaleAccessProofParticipantIsNotSender', 'SalePurchaseCapExceeded', 'MaxVestingSchedulesPerAccountPerTokenReached', 'PreviousSaleNotFinalized', 'NoTokensToRecover', 'SaleDurationTooShort', 'SaleDurationIsZero', 'SaleUpperBoundQuantityIsZero', 'SaleCapPerMemberIsZero', 'SaleUnitPriceIsZero', 'SalePurchaseAmountIsZero', 'CannotInitSaleIfAmmIsActive', 'RevenueSplitTimeToStartTooShort', 'RevenueSplitDurationTooShort', 'RevenueSplitAlreadyActiveForToken', 'RevenueSplitNotActiveForToken', 'RevenueSplitDidNotEnd', 'RevenueSplitNotOngoing', 'UserAlreadyParticipating', 'InsufficientBalanceForSplitParticipation', 'UserNotParticipantingInAnySplit', 'CannotParticipateInSplitWithZeroAmount', 'CannotIssueSplitWithZeroAllocationAmount', 'CannotModifySupplyWhenRevenueSplitsAreActive', 'RevenueSplitRateIsZero', 'BurnAmountIsZero', 'BurnAmountGreaterThanAccountTokensAmount', 'NotInAmmState', 'InvalidCurveParameters', 'DeadlineExpired', 'SlippageToleranceExceeded', 'InsufficientTokenBalance', 'OutstandingAmmProvidedSupplyTooLarge', 'CurveSlopeParametersTooLow', 'NotEnoughTokenMintedByAmmForThisSale', 'TargetPatronageRateIsHigherThanCurrentRate', 'YearlyPatronageRateLimitExceeded', 'PalletFrozen']
_enum: ['ArithmeticError', 'InsufficientTransferrableBalance', 'TokenDoesNotExist', 'AccountInformationDoesNotExist', 'TransferDestinationMemberDoesNotExist', 'MerkleProofVerificationFailure', 'TokenSymbolAlreadyInUse', 'InitialAllocationToNonExistingMember', 'AccountAlreadyExists', 'TooManyTransferOutputs', 'TokenIssuanceNotInIdleState', 'InsufficientJoyBalance', 'JoyTransferSubjectToDusting', 'AttemptToRemoveNonOwnedAccountUnderPermissionedMode', 'AttemptToRemoveNonEmptyAccount', 'CannotJoinWhitelistInPermissionlessMode', 'CannotDeissueTokenWithOutstandingAccounts', 'NoUpcomingSale', 'NoActiveSale', 'InsufficientBalanceForTokenPurchase', 'NotEnoughTokensOnSale', 'SaleStartingBlockInThePast', 'SaleAccessProofRequired', 'SaleAccessProofParticipantIsNotSender', 'SalePurchaseCapExceeded', 'MaxVestingSchedulesPerAccountPerTokenReached', 'PreviousSaleNotFinalized', 'NoTokensToRecover', 'SaleDurationTooShort', 'SaleDurationIsZero', 'SaleUpperBoundQuantityIsZero', 'SaleCapPerMemberIsZero', 'SaleUnitPriceIsZero', 'SalePurchaseAmountIsZero', 'CannotInitSaleIfAmmIsActive', 'RevenueSplitTimeToStartTooShort', 'RevenueSplitDurationTooShort', 'RevenueSplitAlreadyActiveForToken', 'RevenueSplitNotActiveForToken', 'RevenueSplitDidNotEnd', 'RevenueSplitNotOngoing', 'UserAlreadyParticipating', 'InsufficientBalanceForSplitParticipation', 'UserNotParticipantingInAnySplit', 'CannotParticipateInSplitWithZeroAmount', 'CannotIssueSplitWithZeroAllocationAmount', 'CannotModifySupplyWhenRevenueSplitsAreActive', 'RevenueSplitRateIsZero', 'AmmActive', 'BurnAmountIsZero', 'BurnAmountGreaterThanAccountTokensAmount', 'NotInAmmState', 'InvalidCurveParameters', 'DeadlineExpired', 'SlippageToleranceExceeded', 'InsufficientTokenBalance', 'OutstandingAmmProvidedSupplyTooLarge', 'CurveSlopeParametersTooLow', 'NotEnoughTokenMintedByAmmForThisSale', 'TargetPatronageRateIsHigherThanCurrentRate', 'YearlyPatronageRateLimitExceeded', 'PalletFrozen']
},
/**
* Lookup606: pallet_proposals_engine::types::Proposal<BlockNumber, ProposerId, Balance, sp_core::crypto::AccountId32>
Expand Down
3 changes: 2 additions & 1 deletion types/src/augment/types-lookup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5507,6 +5507,7 @@ declare module '@polkadot/types/lookup' {
readonly isCannotIssueSplitWithZeroAllocationAmount: boolean;
readonly isCannotModifySupplyWhenRevenueSplitsAreActive: boolean;
readonly isRevenueSplitRateIsZero: boolean;
readonly isAmmActive: boolean;
readonly isBurnAmountIsZero: boolean;
readonly isBurnAmountGreaterThanAccountTokensAmount: boolean;
readonly isNotInAmmState: boolean;
Expand All @@ -5520,7 +5521,7 @@ declare module '@polkadot/types/lookup' {
readonly isTargetPatronageRateIsHigherThanCurrentRate: boolean;
readonly isYearlyPatronageRateLimitExceeded: boolean;
readonly isPalletFrozen: boolean;
readonly type: 'ArithmeticError' | 'InsufficientTransferrableBalance' | 'TokenDoesNotExist' | 'AccountInformationDoesNotExist' | 'TransferDestinationMemberDoesNotExist' | 'MerkleProofVerificationFailure' | 'TokenSymbolAlreadyInUse' | 'InitialAllocationToNonExistingMember' | 'AccountAlreadyExists' | 'TooManyTransferOutputs' | 'TokenIssuanceNotInIdleState' | 'InsufficientJoyBalance' | 'JoyTransferSubjectToDusting' | 'AttemptToRemoveNonOwnedAccountUnderPermissionedMode' | 'AttemptToRemoveNonEmptyAccount' | 'CannotJoinWhitelistInPermissionlessMode' | 'CannotDeissueTokenWithOutstandingAccounts' | 'NoUpcomingSale' | 'NoActiveSale' | 'InsufficientBalanceForTokenPurchase' | 'NotEnoughTokensOnSale' | 'SaleStartingBlockInThePast' | 'SaleAccessProofRequired' | 'SaleAccessProofParticipantIsNotSender' | 'SalePurchaseCapExceeded' | 'MaxVestingSchedulesPerAccountPerTokenReached' | 'PreviousSaleNotFinalized' | 'NoTokensToRecover' | 'SaleDurationTooShort' | 'SaleDurationIsZero' | 'SaleUpperBoundQuantityIsZero' | 'SaleCapPerMemberIsZero' | 'SaleUnitPriceIsZero' | 'SalePurchaseAmountIsZero' | 'CannotInitSaleIfAmmIsActive' | 'RevenueSplitTimeToStartTooShort' | 'RevenueSplitDurationTooShort' | 'RevenueSplitAlreadyActiveForToken' | 'RevenueSplitNotActiveForToken' | 'RevenueSplitDidNotEnd' | 'RevenueSplitNotOngoing' | 'UserAlreadyParticipating' | 'InsufficientBalanceForSplitParticipation' | 'UserNotParticipantingInAnySplit' | 'CannotParticipateInSplitWithZeroAmount' | 'CannotIssueSplitWithZeroAllocationAmount' | 'CannotModifySupplyWhenRevenueSplitsAreActive' | 'RevenueSplitRateIsZero' | 'BurnAmountIsZero' | 'BurnAmountGreaterThanAccountTokensAmount' | 'NotInAmmState' | 'InvalidCurveParameters' | 'DeadlineExpired' | 'SlippageToleranceExceeded' | 'InsufficientTokenBalance' | 'OutstandingAmmProvidedSupplyTooLarge' | 'CurveSlopeParametersTooLow' | 'NotEnoughTokenMintedByAmmForThisSale' | 'TargetPatronageRateIsHigherThanCurrentRate' | 'YearlyPatronageRateLimitExceeded' | 'PalletFrozen';
readonly type: 'ArithmeticError' | 'InsufficientTransferrableBalance' | 'TokenDoesNotExist' | 'AccountInformationDoesNotExist' | 'TransferDestinationMemberDoesNotExist' | 'MerkleProofVerificationFailure' | 'TokenSymbolAlreadyInUse' | 'InitialAllocationToNonExistingMember' | 'AccountAlreadyExists' | 'TooManyTransferOutputs' | 'TokenIssuanceNotInIdleState' | 'InsufficientJoyBalance' | 'JoyTransferSubjectToDusting' | 'AttemptToRemoveNonOwnedAccountUnderPermissionedMode' | 'AttemptToRemoveNonEmptyAccount' | 'CannotJoinWhitelistInPermissionlessMode' | 'CannotDeissueTokenWithOutstandingAccounts' | 'NoUpcomingSale' | 'NoActiveSale' | 'InsufficientBalanceForTokenPurchase' | 'NotEnoughTokensOnSale' | 'SaleStartingBlockInThePast' | 'SaleAccessProofRequired' | 'SaleAccessProofParticipantIsNotSender' | 'SalePurchaseCapExceeded' | 'MaxVestingSchedulesPerAccountPerTokenReached' | 'PreviousSaleNotFinalized' | 'NoTokensToRecover' | 'SaleDurationTooShort' | 'SaleDurationIsZero' | 'SaleUpperBoundQuantityIsZero' | 'SaleCapPerMemberIsZero' | 'SaleUnitPriceIsZero' | 'SalePurchaseAmountIsZero' | 'CannotInitSaleIfAmmIsActive' | 'RevenueSplitTimeToStartTooShort' | 'RevenueSplitDurationTooShort' | 'RevenueSplitAlreadyActiveForToken' | 'RevenueSplitNotActiveForToken' | 'RevenueSplitDidNotEnd' | 'RevenueSplitNotOngoing' | 'UserAlreadyParticipating' | 'InsufficientBalanceForSplitParticipation' | 'UserNotParticipantingInAnySplit' | 'CannotParticipateInSplitWithZeroAmount' | 'CannotIssueSplitWithZeroAllocationAmount' | 'CannotModifySupplyWhenRevenueSplitsAreActive' | 'RevenueSplitRateIsZero' | 'AmmActive' | 'BurnAmountIsZero' | 'BurnAmountGreaterThanAccountTokensAmount' | 'NotInAmmState' | 'InvalidCurveParameters' | 'DeadlineExpired' | 'SlippageToleranceExceeded' | 'InsufficientTokenBalance' | 'OutstandingAmmProvidedSupplyTooLarge' | 'CurveSlopeParametersTooLow' | 'NotEnoughTokenMintedByAmmForThisSale' | 'TargetPatronageRateIsHigherThanCurrentRate' | 'YearlyPatronageRateLimitExceeded' | 'PalletFrozen';
}

/** @name PalletProposalsEngineProposal (606) */
Expand Down

0 comments on commit 6a1be39

Please sign in to comment.