Skip to content

Commit

Permalink
Merge branch 'crt_release' into nara_crt_release
Browse files Browse the repository at this point in the history
  • Loading branch information
ignazio-bovo committed May 4, 2023
2 parents 8e3b824 + 70b0bdd commit 12b8ff5
Show file tree
Hide file tree
Showing 25 changed files with 2,320 additions and 86 deletions.
3 changes: 2 additions & 1 deletion runtime-modules/content/src/benchmarks/benchmarking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1481,7 +1481,8 @@ benchmarks! {
accounts_number: a as u64,
revenue_split_rate: params.revenue_split_rate,
revenue_split: RevenueSplitStateOf::<T>::Inactive,
next_revenue_split_id: 0
next_revenue_split_id: 0,
amm_curve: None,
});
assert_last_event::<T>(
<T as Config>::Event::from(
Expand Down
3 changes: 3 additions & 0 deletions runtime-modules/content/src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -409,5 +409,8 @@ decl_error! {

/// Channel Transfers are blocked during token sales
ChannelTransfersBlockedDuringTokenSales,

/// Channel Transfers are blocked during active AMM
ChannelTransfersBlockedDuringActiveAmm
}
}
72 changes: 71 additions & 1 deletion runtime-modules/content/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ pub mod weights;
use core::marker::PhantomData;
use project_token::traits::PalletToken;
use project_token::types::{
JoyBalanceOf, TokenIssuanceParametersOf, TokenSaleParamsOf, TransfersWithVestingOf,
AmmParams, JoyBalanceOf, TokenIssuanceParametersOf, TokenSaleParamsOf, TransfersWithVestingOf,
UploadContextOf, YearlyRate,
};
use sp_std::vec;
Expand Down Expand Up @@ -185,6 +185,7 @@ pub trait Config:
TokenSaleParamsOf<Self>,
UploadContextOf<Self>,
TransfersWithVestingOf<Self>,
AmmParams,
>;

/// Minimum cashout allowed limit
Expand Down Expand Up @@ -3076,6 +3077,11 @@ decl_module! {
T::ProjectToken::is_sale_unscheduled(token_id),
Error::<T>::ChannelTransfersBlockedDuringTokenSales,
);

ensure!(
!T::ProjectToken::is_amm_active(token_id),
Error::<T>::ChannelTransfersBlockedDuringActiveAmm
);
}

//
Expand Down Expand Up @@ -3757,6 +3763,70 @@ decl_module! {
channel.creator_token_id = None;
});
}

/// Activate Amm functionality for token
#[weight = 100_000_000] // TODO: Adjust weight
pub fn activate_amm(
origin,
actor: ContentActor<T::CuratorGroupId, T::CuratorId, T::MemberId>,
channel_id: T::ChannelId,
params: AmmParams,
) {
let channel = Self::ensure_channel_exists(&channel_id)?;

channel.ensure_has_no_active_transfer::<T>()?;

// Ensure token was issued
let token_id = channel.ensure_creator_token_issued::<T>()?;

// Permissions check
ensure_actor_authorized_to_activate_amm::<T>(
origin,
&actor,
&channel
)?;

// Retrieve member_id based on actor
let member_id = get_member_id_of_actor::<T>(&actor)?;

// Call to ProjectToken
T::ProjectToken::activate_amm(
token_id,
member_id,
params,
)?;

}

/// Deactivate Amm functionality for token
#[weight = 100_000_000] // TODO: Adjust weight
pub fn deactivate_amm(
origin,
actor: ContentActor<T::CuratorGroupId, T::CuratorId, T::MemberId>,
channel_id: T::ChannelId,
) {
let channel = Self::ensure_channel_exists(&channel_id)?;

// Ensure token was issued
let token_id = channel.ensure_creator_token_issued::<T>()?;

// Permissions check
ensure_actor_authorized_to_deactivate_amm::<T>(
origin,
&actor,
&channel
)?;

// Retrieve member_id based on actor
let member_id = get_member_id_of_actor::<T>(&actor)?;

// Call to ProjectToken
T::ProjectToken::deactivate_amm(
token_id,
member_id,
)?;

}
}
}

Expand Down
22 changes: 22 additions & 0 deletions runtime-modules/content/src/permissions/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -713,3 +713,25 @@ pub fn ensure_actor_authorized_to_deissue_creator_token<T: Config>(
ensure_actor_has_channel_permissions::<T>(&sender, actor, channel, &required_permissions)?;
Ok(sender)
}

pub fn ensure_actor_authorized_to_activate_amm<T: Config>(
origin: T::Origin,
actor: &ContentActor<T::CuratorGroupId, T::CuratorId, T::MemberId>,
channel: &Channel<T>,
) -> Result<T::AccountId, DispatchError> {
let sender = ensure_signed(origin)?;
let required_permissions = vec![ChannelActionPermission::AmmControl];
ensure_actor_has_channel_permissions::<T>(&sender, actor, channel, &required_permissions)?;
Ok(sender)
}

pub fn ensure_actor_authorized_to_deactivate_amm<T: Config>(
origin: T::Origin,
actor: &ContentActor<T::CuratorGroupId, T::CuratorId, T::MemberId>,
channel: &Channel<T>,
) -> Result<T::AccountId, DispatchError> {
let sender = ensure_signed(origin)?;
let required_permissions = vec![ChannelActionPermission::AmmControl];
ensure_actor_has_channel_permissions::<T>(&sender, actor, channel, &required_permissions)?;
Ok(sender)
}
2 changes: 2 additions & 0 deletions runtime-modules/content/src/tests/creator_tokens.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
mod activate_amm;
mod claim_patronage_credit;
mod deactivate_amm;
mod deissue;
mod finalize_creator_token_sale;
mod finalize_revenue_split;
Expand Down
157 changes: 157 additions & 0 deletions runtime-modules/content/src/tests/creator_tokens/activate_amm.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
#![cfg(test)]
use crate::tests::fixtures::*;
use crate::tests::mock::*;
use crate::*;

#[test]
fn unsuccessful_activate_amm_non_existing_channel() {
with_default_mock_builder(|| {
run_to_block(1);

ActivateAmmFixture::default()
.call_and_assert(Err(Error::<Test>::ChannelDoesNotExist.into()));
})
}

#[test]
fn unsuccessful_activate_amm_token_not_issued() {
with_default_mock_builder(|| {
ContentTest::with_member_channel().setup();
ActivateAmmFixture::default()
.call_and_assert(Err(Error::<Test>::CreatorTokenNotIssued.into()));
})
}

// Member channel

#[test]
fn unsuccessful_activate_member_channel_creator_token_amm_by_collaborator_without_permissions() {
with_default_mock_builder(|| {
ContentTest::with_member_channel()
.with_all_agent_permissions_except(&[ChannelActionPermission::AmmControl])
.setup();
IssueCreatorTokenFixture::default().call_and_assert(Ok(()));

ActivateAmmFixture::default()
.with_sender(COLLABORATOR_MEMBER_ACCOUNT_ID)
.with_actor(ContentActor::Member(COLLABORATOR_MEMBER_ID))
.call_and_assert(Err(
Error::<Test>::ChannelAgentInsufficientPermissions.into()
));
})
}

#[test]
fn successful_activate_member_channel_creator_token_amm_by_collaborator() {
with_default_mock_builder(|| {
ContentTest::with_member_channel()
.with_agent_permissions(&[ChannelActionPermission::AmmControl])
.setup();
IssueCreatorTokenFixture::default()
.with_initial_allocation_to(COLLABORATOR_MEMBER_ID)
.call_and_assert(Ok(()));
ActivateAmmFixture::default()
.with_sender(COLLABORATOR_MEMBER_ACCOUNT_ID)
.with_actor(ContentActor::Member(COLLABORATOR_MEMBER_ID))
.call_and_assert(Ok(()));
})
}

#[test]
fn successful_activate_member_channel_creator_token_amm_by_owner() {
with_default_mock_builder(|| {
ContentTest::with_member_channel().setup();
IssueCreatorTokenFixture::default().call_and_assert(Ok(()));
ActivateAmmFixture::default().call_and_assert(Ok(()));
})
}

// Curator channel

#[test]
fn unsuccessful_activate_curator_channel_creator_token_amm_by_curator_without_permissions() {
with_default_mock_builder(|| {
ContentTest::with_curator_channel()
.with_all_agent_permissions_except(&[ChannelActionPermission::AmmControl])
.setup();
IssueCreatorTokenFixture::default()
.with_sender(LEAD_ACCOUNT_ID)
.with_actor(ContentActor::Lead)
.call_and_assert(Ok(()));
ActivateAmmFixture::default()
.with_sender(DEFAULT_CURATOR_ACCOUNT_ID)
.with_actor(default_curator_actor())
.call_and_assert(Err(
Error::<Test>::ChannelAgentInsufficientPermissions.into()
));
})
}

#[test]
fn successful_activate_curator_channel_creator_token_amm_by_curator() {
with_default_mock_builder(|| {
ContentTest::with_curator_channel()
.with_agent_permissions(&[ChannelActionPermission::AmmControl])
.setup();
IssueCreatorTokenFixture::default()
.with_sender(LEAD_ACCOUNT_ID)
.with_actor(ContentActor::Lead)
.with_initial_allocation_to(DEFAULT_CURATOR_MEMBER_ID)
.call_and_assert(Ok(()));
ActivateAmmFixture::default()
.with_sender(DEFAULT_CURATOR_ACCOUNT_ID)
.with_actor(default_curator_actor())
.call_and_assert(Ok(()));
})
}

#[test]
fn successful_activate_curator_channel_creator_token_amm_by_lead() {
with_default_mock_builder(|| {
ContentTest::with_curator_channel().setup();
IssueCreatorTokenFixture::default()
.with_sender(LEAD_ACCOUNT_ID)
.with_actor(ContentActor::Lead)
.with_initial_allocation_to(LEAD_MEMBER_ID)
.call_and_assert(Ok(()));
ActivateAmmFixture::default()
.with_sender(LEAD_ACCOUNT_ID)
.with_actor(ContentActor::Lead)
.call_and_assert(Ok(()));
})
}

#[test]
fn unsuccessful_activate_curator_channel_creator_token_amm_with_ongoing_transfer() {
with_default_mock_builder(|| {
ContentTest::with_curator_channel().setup();
IssueCreatorTokenFixture::default()
.with_sender(LEAD_ACCOUNT_ID)
.with_actor(ContentActor::Lead)
.with_initial_allocation_to(LEAD_MEMBER_ID)
.call_and_assert(Ok(()));
InitializeChannelTransferFixture::default()
.with_sender(LEAD_ACCOUNT_ID)
.with_actor(ContentActor::Lead)
.call_and_assert(Ok(()));

ActivateAmmFixture::default()
.with_sender(LEAD_ACCOUNT_ID)
.with_actor(ContentActor::Lead)
.call_and_assert(Err(Error::<Test>::InvalidChannelTransferStatus.into()));
})
}

#[test]
fn unsuccessful_activate_member_channel_creator_token_amm_with_ongoing_transfer() {
with_default_mock_builder(|| {
ContentTest::with_member_channel().setup();
IssueCreatorTokenFixture::default()
.with_initial_allocation_to(LEAD_MEMBER_ID)
.call_and_assert(Ok(()));
InitializeChannelTransferFixture::default().call_and_assert(Ok(()));

ActivateAmmFixture::default()
.call_and_assert(Err(Error::<Test>::InvalidChannelTransferStatus.into()));
})
}
Loading

0 comments on commit 12b8ff5

Please sign in to comment.