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

Feature/farming interface for frontend #12

Merged
merged 4 commits into from
Oct 19, 2022

Conversation

HyunggyuJang
Copy link
Collaborator

@HyunggyuJang HyunggyuJang commented Oct 18, 2022

to proceed with implementing farming function for the interface side (client),
we need deployed farming contract (just you can deploy with interface. you don’t need to make full contract. so that implementation would be much easier. when it comes to farming if we could stake/unstake tokens, it would be enough features. )

By @SamuraiT

This PR provides skeleton of farming contract for that.

@@ -47,7 +47,7 @@ pub struct Data {
pub lp_tokens: Vec<AccountId>,

/// Address of each `rewarder` contract in MasterChef.
pub rewarders: Vec<AccountId>,
pub rewarders: Vec<Option<AccountId>>,
Copy link
Member

Choose a reason for hiding this comment

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

I don't think there is a reason to store None values.
Best solution would be to store Hashmap<(id: u32, rewarder: AccountId), ()>
So you can easily check if an rewarder exist
Or Hashmap<id: u32, rewarder: AccountId> and only store where is is a rewarder (it will be None if id is not existing)
Id can be the pool id that will be stored (so pool_id +1)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Agree, I'll work on that using Hashmap as you suggested. For now, let me deploy it to Shibuya, and I'll reflect this change later.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Fixed as of 8e2dd3a

.checked_add(alloc_point)
.ok_or(FarmingError::AddOverflow2)?;
self.data::<Data>().lp_tokens.push(lp_token);
self.data::<Data>().rewarders.push(rewarder);
Copy link
Member

Choose a reason for hiding this comment

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

save to storage only if Some()

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

It was to align with proper pool id, but as you pointed out above, I'll change it using Hashmap structure.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Fixed as of 8e2dd3a

let lp_token = self
.get_lp_token(pool_id)
.ok_or(FarmingError::PoolNotFound2)?;
PSP22Ref::transfer_from(
Copy link
Member

Choose a reason for hiding this comment

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

You should allow reentrancy for this or it will not work:

        PSP22Ref::transfer_from_builder(&lp_token, Self::env().caller(), Self::env().account_id(), value, Vec::<u8>::new())
            .call_flags(CallFlags::default().set_allow_reentry(true))
            .fire()
            .unwrap()?;

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Ah, I missed that! Thanks a lot. Will fix it

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Think we don't need to allow reentrancy. Pair contract only calls itself rather than transfer_from caller. Hence, we shouldn't allow reentrancy actually in this case.

Copy link
Member

Choose a reason for hiding this comment

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

Yes I need to update in Pair contract. But here it is still relevant

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

So, from the pair contract, you will callback the caller. But for what?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Since it is LP token, the pair contract is the implementation.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Ah, not the farming contract itself, the caller for deposit might call back the operator part of before_received: https://github.com/Supercolony-net/openbrush-contracts/blob/dc666f08c4e3bec2bf6057bb083cbf5223a28063/contracts/src/traits/psp22/psp22.rs#L160. So we need to allow reentrancy, is it correct?

If it were the case, still think we don't need to allow reentrancy.

Copy link
Member

@PierreOssun PierreOssun Oct 19, 2022

Choose a reason for hiding this comment

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

It's working for Pair because transfer_from is overridden and there is no _do_safe_transfer_check

But other PSP22 implementation might impl the default Internal Trait - in this one there is _do_safe_transfer_check that will do a callback and will panic if we didn't allow reentrancy with flags.

Now you can still keep it like this (as LP are Pair contract) but it will not be compatible with standard psp22

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Yes, exactly. For this function, I think we'd better not to allow reentrancy to suppress from using invalid LP tokens.

Copy link
Collaborator Author

@HyunggyuJang HyunggyuJang Oct 19, 2022

Choose a reason for hiding this comment

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

A note for myself:

Ah, not the farming contract itself, the caller for deposit might call back the operator part of before_received: https://github.com/Supercolony-net/openbrush-contracts/blob/dc666f08c4e3bec2bf6057bb083cbf5223a28063/contracts/src/traits/psp22/psp22.rs#L160. So we need to allow reentrancy, is it correct?

Is generally correct, but is not what happening in this situation. For the foregoing issue, the to of transfer_from is the contract itself, hence, if the PSP22 implementation is default one, then _do_safe_transfer_check calls before_received with to as a callee.
Plus, reentrancy check happens even before checking whether the callee has specified method or not, hence from foregoing context, it will raise an error saying reentrancy is not allowed.

@HyunggyuJang HyunggyuJang merged commit 9ba71f6 into feature/farming-contract Oct 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.

2 participants