beefyfinance / beefy-contracts Goto Github PK
View Code? Open in Web Editor NEWPublic repo for the community devs to advance the Beefy protocol.
Home Page: https://app.beefy.finance
Public repo for the community devs to advance the Beefy protocol.
Home Page: https://app.beefy.finance
Hi!
I used to zap FUSE to ELON-FUSE LP, but now tx wants 9,5 mln gas and failed
https://explorer.fuse.io/tx/0x4817536145ba4ecdbf34ab0b42b6df31ce366f0212957b87fcfe3650b94a197e/internal-transactions
previos tx
https://explorer.fuse.io/tx/0x7bf560f77b4326f6b8385d5fc574199e4ae5244014d9a1b844027738844b38a1/token-transfers
Probably other vaults affected as well.
Plz, fix this.
BSCScan has a verification API now, just like etherscan. It would be good to add verification into the deploy pipeline.
What do we think about adding a check to see if a strat is paused and from that state, don't charge a withdrawal fee.
There are three times where the strats are paused and I think this handles all of them:
function withdraw(uint256 _amount) external {
...
if (tx.origin == owner() || paused()) {
IERC20(lpPair).safeTransfer(vault, pairBal);
} else {
uint256 withdrawalFee = pairBal.mul(WITHDRAWAL_FEE).div(WITHDRAWAL_MAX);
IERC20(lpPair).safeTransfer(vault, pairBal.sub(withdrawalFee));
}
}
If we like it, I can add it to all strats.
There are sometimes where we're pushing an experimental vault. Or for a few different reasons, we might want to have a temporary cap on deposits.
The goal would be to have a reusable contract that lets strategies have a cap for the first x blocks of their existence.
This would prevent people from apeing $5M into something experimental.
BSC is getting expensive and there's more need to optimize.
We're currently doing a bunch of swaps and ERC20 transactions with each harvest()
call. We could just send it all as one to a BatchFees contract and have a public distribute()
call there which would divide everything once per day for example.
This would also remove logic from the strat
I noticed a few DApps now make use of a new spending permission system outlined in EIP-2612, which involves signing a message in your wallet instead of a separate approval transaction (more details here: https://soliditydeveloper.com/erc20-permit).
Obviously, the token being spent must support this approval style, namely, it must implement the following three methods:
function permit(address owner, address spender, uint value, uint deadline, uint8 v, bytes32 r, bytes32 s) external
function nonces(address owner) external view returns (uint)
function DOMAIN_SEPARATOR() external view returns (bytes32)
It does appear that at least SpiritSwap LP tokens on Fantom DO implement this approval style (for example, the USDC-fUSDT pair. Not sure if this only goes for newer pairs and what other exchanges have implemented this, but I will do some research and add a list here.
Of course, the app would need some updates as well in order to support this approval style (and autodetect when it is available), but more importantly, the vaults would need to support this first. I found a possible implementation on a YieldYak vault (license is MIT):
/**
* @notice Deposit using Permit
* @param amount Amount of tokens to deposit
* @param deadline The time at which to expire the signature
* @param v The recovery byte of the signature
* @param r Half of the ECDSA signature pair
* @param s Half of the ECDSA signature pair
*/
function depositWithPermit(
uint256 amount,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external override {
depositToken.permit(msg.sender, address(this), amount, deadline, v, r, s);
_deposit(msg.sender, amount);
}
A potential depositAllWithPermit()
function would look similar.
In the app, the following steps would be required:
want
) supports EIP-2612 approvals.deposit(amount)
or depositAll()
, call the _WithPermit
version, using the appropriate parameters.While I don't think this saves any gas or transaction fees (after all, the permit()
function still calls approve()
, and must additionally decode the signed message), it is a nice quality-of-life improvement and does improve security, since no permanent approvals are required.
Would it be possible to include this in the next iteration of the vault contract?
We are growing and so is our need to distribute responsibility over fund management and upgrades.
Initially the team went with a simple account owning everything for simplicity, because there was no ecosystem on BSC and little live implementations of multisig.
At this point all of those things have changed, so moving our operations to use a multisig with 4-6 community members seems like a good next step.
We can move vault upgrades and other functionality to use the same multisig. But starting with the Treasury seems good.
It seems that since yesterday all the Fortube vaults that attempted a harvest have failed. The error that the transactions get is 'Fail with error 'DEMAX PLATFORM : CHECK DGAS/TOKEN VALUE FROM FAIL'
There is almost no liquidity on any exchange for FOR, so that might be the issue
Last week I proposed a candidate upgrade for the STAX-CAKE/NAR-CAKE/NYA-CAKE vaults to decrease their slippage. For some reason the upgrade didn't work and with the app + api issues that followed, I wasn't able to focus on them.
Even though they're pretty small vaults, it would be good to make sure we deliver the APY that we display. Debugging what went wrong and/or proposing a candidate with the correct custom routes would make this happen.
We can't accurately predict which vaults are going to be the most popular. We also can't predict which vaults will be able to sustain their APYs over the long run. This creates suboptimal fees, because the callFee sometimes ends up being way too high. Beefy is paying to third parties to harvest its vaults, and sometimes it's paying way too much. This makes it so that some vaults are harvested every 2-3 minutes. That harvesting frequency doesn't provide much value to the user and it would better go somewhere else.
If we had a range of 0.05%-0.5% and we could move the callFee within that range. We could decrease how much we pay on profitable vaults, and increase it in some other vaults if it's required. It would be great if the extra % goes to the treasury for example, to help pay for more development/marketing/etc.
We have close to 150 vaults and growing. There are times when we have to upgrade multiple vaults at a time, and there might come a time when we have to upgrade +50 in a short period of time. An example would be if we have to change the BIFI rewards pool address, or the treasury address, or add an improvement to all strats.
Right now the process to upgrade a strategy is as follows: When the approval time has passed and the candidate is ready
to replace the old strat, we first do a dry run of the upgrade using a ganache localnet.
We check that:
1- Balances are transfered correctly.
2- We can deposit/withdraw.
3- Harvests can happen and generate earnings for stakers.
If everything looks good, we run the upgrade on mainnet.
This is quite slow to do. And if we have to do it for several vaults in a row, we could miss a detail somewhere.
Having an automated test that does this checks would increase our comfort when upgrading vaults. Some of these vaults have $10M-$20M and those numbers are only going to get larger.
It would still be a good idea to run the manual runs at first, but the automated tests would still be very beneficial. The good thing is that these are integration tests which could be re-used for 100% of our vaults.
The test at VaultUpgrade.test.js would have to receive a vault address and:
yarn net
.To protect from front-running on harvest we gonna check transaction's gas price tx.gasprice
to be less than current BSC gasprice value.
We also need to make it upgradable in case of Binance will change it as it was before from 20 to 15, and then to 10.
And to not update every single contract we can have 1 GasPrice contract deployed where other contracts will read price from.
GasPrice contract might look like this, owned by cowllector:
contract GasPrice is Ownable {
uint public maxGasPrice = 10 gwei;
event NewMaxGasPrice(uint oldPrice, uint newPrice);
function setMaxGasPrice(uint _maxGasPrice) external onlyOwner {
emit NewMaxGasPrice(maxGasPrice, _maxGasPrice);
maxGasPrice = _maxGasPrice;
}
}
Then we have GasThrottler
contract that has gasThrottle
modifier checking that tx.gasprice <= max price.
Contract which needs to limit gas will extend from it and add modifier on needed functions.
interface IGasPrice {
function maxGasPrice() external returns (uint);
}
contract GasThrottler {
address gasprice = address(0x230562106833b3618A053e6fe0bdC8fDBb59eb12);
modifier gasThrottle() {
require(tx.gasprice <= IGasPrice(gasprice).maxGasPrice(), "gas is too high!");
_;
}
}
I guess we can hardcode GasPrice address here and i don't see use cases when it's needed to be configurable.
We might need HecoGasThrottler, AvaxGasThrottler and so on in the future though.
And finally new Strategies will extend GasThrottler
and add gasThrottle
modifier on harvest().
contract StrategyLP is GasThrottler {
function harvest() external gasThrottle {
...
}
}
I've deployed these 2 contracts if someone wants to test.
GasPrice without owner
https://bscscan.com/address/0x230562106833b3618A053e6fe0bdC8fDBb59eb12#code
TestStrategy with empty harvest
https://bscscan.com/address/0x5675d63494EDDa594727033864F1bca375736191#code
encountered an issue pertaining to this line with the current beets-cre8r vault:
I setup the vault to accept beets outputs in case they were eventually bribed for by cre8r. however, while current beets emissions are nominally zero, because of "rounding error" (according to beets admin) 1gwei beets is emitted every day or so. because the strat contract tries to swap beets whenever beets > 0, when it detects 1gwei beets it tries to trade, and as a consequence throws.
its unclear what a solution might be. any lower bound on trade would be arbitrary since its difficult to predict the price range at which the want token will swap against beets (it could be that a really really cheap token does in fact swap for 1 gwei beets in the future).
https://moonscan.io/address/0xeccb80e860561ca9ffb183a557f32cc90b05d3c3#readContract
This is the Beefy Strategy contract deployed on Moonbeam network and its abi is a bit different from others.
Means that you are not supporting some of the read methods from the upgraded versions.
Just want to make sure.
The initial LP strategies had unit tests for all functions and integration tests for the normal flows. As we've deployed more variations for different platforms, given the number of contracts we deploy, and how similar everything is, we've come to rely more and more on manual testing of flows.
There are some small mistakes that might go unnoticed. Some small discrepancies in pricePerFullShare for example. New entrants diminishing the share of previous users, etc that we might not catch with manual tests.
Even though the number of strats deployed keeps growing, we need to not only maintain, but increase the safety of our vaults. A great thing is that all of our vaults share the same interface, so we could have a single suite of tests that check all the usual cases. As time goes on we can build upon the starting suite.
Once we have this tests, strategists can run it on their vaults before submitting for review. Reviewers can also run it on all vaults before being displayed on the app.
Some tests that could be included:
Some unit tests on vault's basic features would be good as well. Stress testing the shares math for example.
Right now we have to deploy vault/strategy pairs one at a time. This is because predictAddresses fails to predict correctly if you try to do multiple deploys in a row.
I don't exactly know why it is that it fails to predict the correct future addresses, it might be that the nonce remains cached with a call to getSigners().
If we could chain deployments, it would make it easier to launch 5-10 vaults at the same time.
Our strategies always send a 0 as amountOutMin
when swapping. This means that we're accepting any slippage that the exchange offers.
This means that our vaults are:
the link for vault in 5. Update the app
is pointing to the archived repo
At the moment zapNativeToToken() breaks when trying to handle custom routes that don't go through native.
It also can't handle acquiring LPs that are not from a Uniswap fork, for example Curve LPs
Hello, I want to offer myself to build a vault for cake built on top of project pools.
They have higher APRs than CAKE->CAKE so it could be a nice addition.
Do you accept strategies from new contributors?
If so I will get started but I want to make sure and not waste time
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.