Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Master fix member channel nft proceeds effectively credited #3763

Conversation

ignazio-bovo
Copy link
Contributor

@ignazio-bovo ignazio-bovo commented May 18, 2022

fixes #3762

No code has been lost, it is just that changes in #3650 have never been implemented. Royalty payment was working correctly however

Changes
  1. there is a test to check the above violation (NFT owned by channel, channel owned by member, and reward account not set) for each of the possible nft revenue event:
  • Auction, both english and open use the same complete_auction internal logic hence they can be treated as equal in this respect
  • Buy Now
  • Accept NFT Offer
  1. ensure_owner_account_id has been renamed to ensure_nft_owner_account_id and internally uses ensure_reward_account, effectively implementing the business logic desired: Revising destination of proceeds in NFT transactions #3650
  2. same thing as build_royalty_payment which worked correctly already, I just refactored it by reusing the ensure_reward_account method

@vercel
Copy link

vercel bot commented May 18, 2022

The latest updates on your projects. Learn more about Vercel for Git ↗︎

1 Ignored Deployment
Name Status Preview Updated
pioneer-testnet ⬜️ Ignored (Inspect) May 19, 2022 at 9:30AM (UTC)

@ignazio-bovo ignazio-bovo requested a review from bedeho May 18, 2022 16:35
Copy link
Member

@bedeho bedeho left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Overall looks good, but lets have @Lezek123 also review.

In various places we do channel_by_id reads inside various methods, and if these are called at the wrong time, where the channel is not guaranteed to exist, then this will create storage side-effect in such methods, so this is a bit risky in terms of future maintainers. It would be safer to just pass in channel objects directly to such methods, and then to read such objects in extrinsic scope using channel_by_id(video.channel_id) after it has been established that the video exists. This is less likely to break in the future.

.reward_account
.ok_or_else(|| Error::<T>::RewardAccountIsNotSet.into()),
NftOwner::ChannelOwner => {
let channel = Self::ensure_channel_exists(&channel_id)?;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  1. This method needs a better name, lets call it ensure_nft_owner_has_beneficiary_account.
  2. It should not fail statically on reading channel from storage, please see general comment in primary review comment. Hence make channel a method parameter which is read using video.channel_id infallibly in extrinsic scope after video has been confirmed to exist.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

addressed in 8d223f3

.ok_or_else(|| Error::<T>::RewardAccountIsNotSet.into()),
NftOwner::ChannelOwner => {
let channel = Self::ensure_channel_exists(&channel_id)?;
Self::ensure_reward_account(&channel)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we rename ensure_reward_account to ensure_channel_has_beneficiary_account.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

addressed in 8d223f3

Copy link
Member

@bedeho bedeho left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM.

@ignazio-bovo ignazio-bovo changed the base branch from master to rhodes-update-1 May 19, 2022 08:07
@mnaamani
Copy link
Contributor

Please apply cargo fmt: cargo-fmt --all to fix code formatting checks

Copy link
Contributor

@Lezek123 Lezek123 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The change looks ok, but I think in general the nft tests need some refactorization (probably not as part of this PR though).

There are quite a lot of combinations that need to be tested in order to make sure everything works as expected:

Ways to buy/acquire nft:

  • through open auction (winner picked)
  • through open auction (buy now price hit)
  • through english auction (settle)
  • through english auction (buy now price hit)
  • through accept_incoming_offer
  • through buy_nft

For each of those we can have any combination of:

NFT owner beeing:

  • a member
  • a member channel w/ reward account set (original issuer)
  • a member channel w/ reward account not set (original issuer)
  • a curator channel w/ reward account set (original issuer)
  • a curator channel w/ reward account not set (original issuer)

Video owner (royalty reciever) beeing:

  • a member channel w/ reward account set
  • a member channel w/ reward account not set
  • a curator channel w/ reward account set
  • a curator channel w/ reward account not set

If we wanted to test all possible combinations, that's 48 separate test cases (assuming we always use Some(_) royalty to test that part too).

Manually writing each test case would be quite cumbersome, but I think it would be possible to make some shared setup for initializing and testing all possible channel / nft owners and just have one test like buy_nft_all_combinations_ok for each of the 6 ways the nft can be acquired.

Some mock code example to ilustrate what I have in mind:

let channels = [
            {
                sender: DEFAULT_MEMBER_ACCOUNT_ID,
                actor: ContentActor::Member(DEFAULT_MEMBER_ID))
                reward_account: None,
                expected_royalty_dst: DEFAULT_MEMBER_ACCOUNT_ID,
            },
            {
                sender: DEFAULT_MEMBER_ACCOUNT_ID,
                actor: ContentActor::Member(DEFAULT_MEMBER_ID))
                reward_account: Some(DEFAULT_MEMBER_CHANNEL_REWARD_ACCOUNT_ID),
                expected_royalty_dst: DEFAULT_MEMBER_CHANNEL_REWARD_ACCOUNT_ID,
            },
            {
                sender: DEFAULT_CURATOR_ACCOUNT_ID,
                actor: ContentActor::Curator(group_id, DEFAULT_CURATOR_ID))
                reward_account: None,
                expected_royalty_dst: None,
            },
            {
                sender: DEFAULT_CURATOR_ACCOUNT_ID,
                actor: ContentActor::Curator(group_id, DEFAULT_CURATOR_ID))
                reward_account: Some(DEFAULT_CURATOR_CHANNEL_REWARD_ACCOUNT_ID),
                expected_royalty_dst: DEFAULT_CURATOR_CHANNEL_REWARD_ACCOUNT_ID,
            },            
]

Now for each of channels you want to setup the nft owner to be either the original channel, or OTHER_MEMBER.

If the owner is the channel then expected_payment_dst = expected_royalty_dst, otherwise expected_payment_dst = OTHER_MEMBER_ACCOUNT_ID.

You could reuse a setup like this (creating channel, issuing nft w/ a specific owner) and final assertions for all 6 scenarios through which the nft can be acquired, making the number of test smaller and the tests themselves quite clear and complete.

Comment on lines +240 to +243
CreateChannelFixture::default()
.with_sender(DEFAULT_CURATOR_ACCOUNT_ID)
.with_actor(curator_actor)
.call();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The method name should be accept_incoming_offer_with_no_reward_account_burns_token_with_curator_owner_channel

@mnaamani mnaamani merged commit fc93b65 into Joystream:rhodes-update-1 May 19, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

NFT Channel with no reward account and member owned has funds burned
4 participants