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

Fixed mint bug and small improvements #18

Merged
merged 7 commits into from
Sep 22, 2022
Merged

Fixed mint bug and small improvements #18

merged 7 commits into from
Sep 22, 2022

Conversation

ferencdg
Copy link
Contributor

  1. Fixed mint bug
  2. Changed swap path in reapReward to omit WAvax for Stargate
  3. Changed ERC20 methods to their safe version
  4. Fixed up failing testcases
  5. Fixed some grammar mistakes, auto-ordered imports
  6. Excluded typechain files from prettier

Daniel Graczer added 4 commits September 21, 2022 17:11
Details:
1. Fixed mint bug
2. Changed swap path in reapReward to omit WAvax for Stargate
3. Changed ERC20 methods to their safe version
4. Fixed up failing testcases
5. Fixed some grammar mistakes, auto-ordered imports
@@ -170,7 +170,6 @@ contract Stargate is UUPSUpgradeable, StrategyOwnablePausableBaseUpgradeable {

address[] memory path = new address[](3);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

fixing this...

Copy link
Contributor

@nnoln nnoln left a comment

Choose a reason for hiding this comment

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

minting fix looks legit

Openzeppelin has a bug in the safeApprove, we will need to write our own
OpenZeppelin/openzeppelin-contracts#2219
We still use safeApprove in cases where we are sure the subsequent
transferFrom switches the approve balance back to 0.
@@ -11,12 +11,12 @@ contract PercentageAllocation is
{
// solhint-disable-next-line const-name-snakecase
string public constant name =
"block42.percentage_allocation_portfolio.percentage_allocation_portfolio_v1.0.0";
"block42.percentage_allocation_portfolio.percentage_allocation_portfolio_v1.0.1";
Copy link
Contributor

Choose a reason for hiding this comment

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

We're not block42 anymore.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

true, but we are going to move away from brokkr soon as part of the rebranding

Copy link
Contributor

Choose a reason for hiding this comment

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

We're Brokkr at the moment. When we decide to change our name to something else, then all names should be changed accordingly. Possibility of name change doesn't mean that it's okay to use wrong company name. It can confuse users as well. What is the benefit of using wrong company name?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

changed it, as according to Paul rebranding might take long time

await this.usdc.connect(this.user0).approve(this.portfolio.address, ethers.utils.parseUnits("3000", 6))
await this.portfolio.connect(this.user0).deposit(ethers.utils.parseUnits("3000", 6), this.user0.address, [])

await this.investmentToken.connect(this.user0).approve(this.portfolio.address, ethers.utils.parseUnits("3000", 6))
Copy link
Contributor

Choose a reason for hiding this comment

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

await this.investmentToken.connect(this.user0).approve(this.portfolio.address, availableTokenBalance)?

@@ -202,13 +227,13 @@ export function testWithdraw() {
await this.usdc.connect(this.user1).approve(this.strategy.address, ethers.utils.parseUnits("30", 6))
await this.strategy.connect(this.user1).deposit(ethers.utils.parseUnits("30", 6), this.user1.address, [])

// The first user withdraws.
// The first user partial withdraws.
Copy link
Contributor

Choose a reason for hiding this comment

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

partial -> partially

await this.investmentToken.connect(this.user0).approve(this.strategy.address, ethers.utils.parseUnits("15", 6))
await expect(this.strategy.connect(this.user0).withdraw(ethers.utils.parseUnits("15", 6), this.user0.address, []))
.to.emit(this.strategy, "Withdrawal")
.withArgs(this.user0.address, this.user0.address, ethers.utils.parseUnits("15", 6))

// The second user withdraws.
// The second user partial withdraws.
Copy link
Contributor

Choose a reason for hiding this comment

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

partial -> partially

@@ -90,7 +90,7 @@ contract Stargate is UUPSUpgradeable, StrategyOwnablePausableBaseUpgradeable {
uint256 lpBalanceBefore = strategyStorage.lpToken.balanceOf(
address(this)
);
strategyStorage.poolDepositToken.approve(
strategyStorage.poolDepositToken.safeApprove(
Copy link
Contributor

Choose a reason for hiding this comment

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

This is deprecated. What is point of using this one? They recommend to use safe increase/decrease allowance. Or we can set it to 0 afterward. (approve(100), deposit(100), approve(0)).

Copy link
Contributor Author

@ferencdg ferencdg Sep 22, 2022

Choose a reason for hiding this comment

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

  1. safeApprove is actually very useful, because the ERC20 standard doesn't specify what should happen when 'approve' failes. Throwing exception or returning to false is equilly legit. safeApprove makes sure that if false is returned, it will throw. That way you don't need to check the return value of it and rethrow.

  2. You are correct that safeApprove is depricated, but that is because it has an additional 'feautre' that tries to guard against this vulnerability: https://www.adrianhetman.com/unboxing-erc20-approve-issues/. Most people don't need that feautre and they complained in the oppenzeppelin jira. In fact I had to use approve in some places in our code, otherwise it would have failed.

  3. I agree that using increase/decrease allowance would be the best because that is not affected by the frontrunning issue above. However that would also require an allowance check before which will take up some gas.

  4. I think this case
    approve(100)
    deposit(100)
    approve(0)

We don't need to approve(0) at the end, as deposit will set the approval back to 0 (by calling transferFrom internally)

  1. We have an option to write our own safeApprove method, that doesn't have the front-running check. It has pros and cons.

Let's talk about this offline and find a way on how to handle approve in the future. After we found a solution, I will change it to the right one.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

most ERC20 approve can never fail btw, so we might also just check those tokens and then we can use approve

Copy link
Contributor

Choose a reason for hiding this comment

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

Thanks for the explanation. approve(0) was safety guard but you can ignore this.

@@ -15,6 +15,7 @@ contract TraderJoeV2 is
{
using SafeERC20Upgradeable for IInvestmentToken;
using SafeERC20Upgradeable for IERC20Upgradeable;
using SafeERC20Upgradeable for ITraderJoePair;
Copy link
Contributor

Choose a reason for hiding this comment

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

This line is not added to TraderJoe.sol.

const investableLength = (await this.portfolio.getInvestables()).length

if (investableLength <= 1) {
return
}

// Set target allocations 100% to the first investable and 0% to the others. e.g. [100%, 0%, 0%]
// Set target allocations 100% to the first investable and 0% to the others. [100%, 0%, 0%]
Copy link
Contributor

Choose a reason for hiding this comment

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

Allocations in this file are all just examples. It's dependent on portfolio. A portfolio that has four investables will have different allocation.

await this.investmentToken.connect(this.user0).approve(this.strategy.address, ethers.utils.parseUnits("30", 6))
await expect(this.strategy.connect(this.user0).withdraw(ethers.utils.parseUnits("30", 6), this.user0.address, []))
// The first user fully withdraws.
let investmentTokenBalance = await this.investmentToken.balanceOf(this.user0.address)
Copy link
Contributor

Choose a reason for hiding this comment

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

Only here is investmentTokenBalance and others are all availableTokenBalance.

@ferencdg ferencdg merged commit 7fab122 into main Sep 22, 2022
@ferencdg ferencdg deleted the mint-fix branch September 22, 2022 11:39
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.

3 participants