You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
* @dev use donate() instead of direct transfer() to store the balance in assetBalance
* @param _asset asset address
* @param _amount amount to donate to pool
*/
function donate(address_asset, uint256_amount) external {
pool.transferToPool(_asset, msg.sender, _amount);
transferToPool is used in order to transfer the tokens from the user to the pool. This function takes care of the internal accounting inside the MarginPool contract and updates the assetBalance accordingly:
We believe that the farm function was intended to be the one that would allow a designated farm account to withdraw the funds that were donated into the pool (ie. the difference between what is in the contract and assetBalance):
However, the issue is that because transferToPool also updates the internal accounting in the assetBalance mapping, the require at line L176 in MarginPool contract will fail for any value of _amount higher than 0. Because the difference between the funds in the contract (externalBalance ) and the amount accounted in the assetBalance mapping (storedBalance) will be 0 (*). This leads to the situation where the donated funds are stuck in the contract:
require(_amount <= externalBalance.sub(storedBalance), "MarginPool: amount to farm exceeds limit");
(*) this is true as long as users follow the recommendation in the donate documentation and only send transfers via this function. Any tokens sent directly to the MarginPool by use of transfer can actually be withdrawn / farmed.
Recommendation
Since this is a live contract and other systems might already be aware of the external donate function, it might make sense to just do a ERC20Interface(_asset).safeTransfer call directly, without calling the transferToPool. This way, when the farm function is called, the ERC20Interface(_asset).balanceOf call in MarginPool contract will indeed be higher than the assetBalance[_asset] and the difference can be farmed.
After further discussion with the development team, we understood the purpose of the donate method was to add funds to the protocol when it is under collateralized to cover for the missing funds. Anyone can call this method because they plan to have an emergency plan to add funds in the vault.
The text was updated successfully, but these errors were encountered:
Description
donate
function seems to allow users to donate an_amount
of tokens of_asset
to the margin pool:review-opyn-gamma-2021-08/code/contracts/core/Controller.sol
Lines 316 to 322 in 879977f
transferToPool
is used in order to transfer the tokens from the user to the pool. This function takes care of the internal accounting inside theMarginPool
contract and updates theassetBalance
accordingly:review-opyn-gamma-2021-08/code/contracts/core/MarginPool.sol
Lines 74 to 83 in 879977f
We believe that the
farm
function was intended to be the one that would allow a designated farm account to withdraw the funds that were donated into the pool (ie. the difference between what is in the contract andassetBalance
):review-opyn-gamma-2021-08/code/contracts/core/MarginPool.sol
Lines 173 to 178 in 879977f
However, the issue is that because
transferToPool
also updates the internal accounting in theassetBalance
mapping, therequire
at line L176 inMarginPool
contract will fail for any value of_amount
higher than 0. Because the difference between the funds in the contract (externalBalance
) and the amount accounted in theassetBalance
mapping (storedBalance
) will be 0 (*). This leads to the situation where the donated funds are stuck in the contract:review-opyn-gamma-2021-08/code/contracts/core/MarginPool.sol
Line 176 in 879977f
(*) this is true as long as users follow the recommendation in the
donate
documentation and only send transfers via this function. Any tokens sent directly to theMarginPool
by use oftransfer
can actually be withdrawn / farmed.Recommendation
Since this is a live contract and other systems might already be aware of the external
donate
function, it might make sense to just do aERC20Interface(_asset).safeTransfer
call directly, without calling thetransferToPool
. This way, when thefarm
function is called, theERC20Interface(_asset).balanceOf
call inMarginPool
contract will indeed be higher than theassetBalance[_asset]
and the difference can be farmed.After further discussion with the development team, we understood the purpose of the
donate
method was to add funds to the protocol when it is under collateralized to cover for the missing funds. Anyone can call this method because they plan to have an emergency plan to add funds in the vault.The text was updated successfully, but these errors were encountered: