The BentoBox is the main vault that holds all funds, not only for the lending contracts, but also for any future extensions. Anyone can build extensions that use the BentoBox as vault with these benefits:
Once a token is approved for the Vault, any protocol built using BentoBox doesn't need per token approval anymore.
Low flat costs of internal token transfers and advanced transfers such as one-to-many transfers.
Funds of users and protocols are safely separated internally. Only protocols that the user approves can access the user's funds.
Passive income from flash loans.
Potential passive income from strategies.
Placing your tokens in a single vault brings a range of benefits. As more protocols get added to the BentoBox, gas costs will come down, while composability, capital efficiency and flexibility will go up.
Not all tokens are created equal. Some have very high gas costs, some are not quite ERC20 compliant. Once they are stored in the BentoBox, you can use your tokens in any BentoBox enabled protocols. These protocols don't have to worry about any token quirks or handle ETH. The BentoBox takes care of all that. On top of that, tokens in the BentoBox will generate extra returns through flash loans and potentially a token strategy.
Tokens in the BentoBox can be flash loaned. The fee is 0.05% and this fee goes to the share owners in the BentoBox. Multiple assets can be flash loaned at the same time.
ERC3156 wasn't final at release of the BentoBox and the BentoBox is not ERC3156 compliant at this time. The BentoBox uses push instead of pull to get the returned funds. This is for flexibility and security reasons.
The BentoBox has a simple strategy system per token. A strategy is a contract that invests a single token for profit and returns the profit in that same token. The safest strategies would be those that:
Can only ever grow in token amount. Principal is always safe.
Can be deposited and withdraw at will.
Some examples of this would be:
The SushiBar: SUSHI can be invested and held as xSUSHI. See SushiStrategy.sol.
Staking contracts, such as MasterChef and Onsen.
It will be up to the community and the Sushi team to decide which strategies are safe enough to enable. The BentoBox has a hardcoded 2 weeks waiting period for enabling or changing strategies.
When you deposit token in the BentoBox, you receive a number of shares. This represents your shares of the total token amount in the BentoBox. As the amount of tokens grows due to flash loan fees and profit from strategies, you will get your share of that. Simple depositing tokens into the BentoBox can provide returns.
Because of limited precision in the accounting, there will be small rounding differences. For most tokens these will be incredibly small and have no useful value. In the top 100 tokens, currently $XAUT is worth the most for a single accounting unit, at about $0.00185. BentoBox is designed to never round in your favour, because that could be exploited by clever hackers. But because of this, when you deposit 100 tokens and withdraw it straight away, you may only receive for instance 99.9999.
The batch function allows the batching of multiple BentoBox function calls in a single transaction.
While most ERC20 tokens are supported by the BentoBox, there are some tokens that should not be deposited into the BentoBox:
Rebasing tokens are not directly supported. Since rebasing is just a visual (psychological) trick rather than an actual feature, direct support was not added. However, most rebasing tokens could easily be wrapped exposing the underlying balances as an ERC20 token. These could be deposited into the BentoBox without problem.
Tokens where a single 'unit' has significant value. Due to rounding and gas optimizations, it is possible to craft transactions that will give you 'free' units of a token. In case of a token, such as $SUSHI, with 18 decimals, this would be worth about $0.00000000000000001. As long as gas costs are more than this, it's safe. In the case of WBTC, 1 unit is about $0.00033, which still has a safety margin of about 4 orders of magnitude. There may however be some tokens with low or no decimals and a high value that should not be added to the BentoBox.
Tokens where the totalSupply in token units is greater than uint128, which is about 38 decimals. With a maximum of 18 decimals normally used, this would still allow for a totalSupply of 100.000.000.000.000.000.000, which is more than enough. While ERC20 supports uint256, this limit was added to safe on gas.
To prevent a far-fetched grieving attack on the amount to share ratio, a minimum of 1000 shares of each token have to remain in the BentoBox OR it has to be emptied completely. Normally this is an insignificant amount, and even in case of WBTC, it's only $3.30. If you're the last user, you can fully withdraw your shares, so no funds are lost/inaccessible because of this.
Any protocol can use BentoBox as it's storage of funds. The contract just needs to implement the init function.
For every new master contract, each user manually approves the protocol. Once approved, functions of the protocol contract have access to all funds of the user that are not in other protocols. Because this is quite a powerful approval, users tricked into approving a malicious contract could lose a lot of funds. To mitigate this and improve usability, the approval is done through a signed typed data message. A wallet such as Metamask will display the typed data, which includes this message:
Give FULL access to funds in (and approved to) BentoBox?
This will prompt users to the potential effects of the approval. Because some hardware wallets are unable to sign typed data, such as the Ledger, a fallback is available. The Sushi team has the ability to white-list master contracts so they can be approved by a simple contract call.
mapping(IERC20 => mapping(address => uint256)) public balanceOf
The balance of shares per token per user (or contract).
mapping(IERC20 => Rebase) public totals
totals.elastic = actual total token balance in the BentoBox + the balance of tokens sent to the strategy. totals.base = total shares (the sum of all the balances of all users)
mapping(address => uint256) public nonces mapping of nonces for user addresses
mapping(address => bool) public whitelistedMasterContracts returns contracts whitelisted to be approved in the fallback function
domainSeparator function returns the domain separator.
Calls the permit function on a token confirming to EIP-2612.
setMasterContractApproval function allows users to approve all clones of a masterContract to manage their funds using a typed message following the EIP-712 standard.
To approve a master contract
eth_signTypedData_v4 should be called with the appropriate data.
BentoBox also offers a fallback functionality targeted at Ledger devices which only allows approving masterContracts whitelisted by the SushiSwap team. To use the fallback, set the v, r, s values to 0.
Deposit and withdraw functions are used to add and remove funds from the BentoBox. A range of different variants is available. Support for ERC721 permits is also included, by batching a deposit with the
When depositing ETH, use the 0 address (0x0000000000000000000000000000000000000000) and set the amount correctly. ETH will be converted to WETH9 when depositing and back to ETH when withdrawn. Setting a lower amount will cause a loss of ETH. This is not protected to support batch deposits through the batch function.
Once a user approves a masterContract, all clones of that contract can withdraw and deposit for that user.
The deposit function is used to add a BentoBox balance for a token to an address (user or contract). This can be done in 2 ways:
pulling in approved tokens using transferFrom
transfer the tokens onto the BentoBox contract address and use the BentoBox contract address to 'skim' the tokens to the 'to' address.
IERC20 token_ The contract address of the token being deposited. Use
address(0) for ETH.
address from The address the tokens are coming from. Must have permission.
address to The address the BentoBox balance will be assigned to.
uint256 amount The amount of tokens being deposited. Only used if
share is 0.
uint256 share The number of shares worth being deposited. Calculated from
share is 0.
uint256 amountOut The actual amount deposited.
uint256 shareOut The actual shares added.
Note: when the amount is calculated from the share and converting the amount back to share results in less, amount is increased by 1. This is effectively rounding up instead of down, to ensure the amount being added at a minimum matches the value of the shares given.
Transfer functions are used to transfer funds from one account to another within the BentoBox. Once a user approves a masterContract, all clones of that contract can access the user's funds in the BentoBox and transfer them.
transferMultiple function does a one-to-many transfer in a more gas efficient manner. Other complicated transfers can be composed through
The batch function allows for executing multiple actions on the BentoBox contract in a single transaction.
Due to rounding, it may be possible to deposit (or withdraw) a tiny amount of tokens for 'free'. Since these amounts would normally be worth nothing, the gas costs to do this would make this pointless.
However, for tokens where a single 'unit' has significant value this could be problematic. These tokens should not be added to the BentoBox. In practice, this is not an issue for nearly all popular tokens. Some examples, including the worst cases from the CoinGecko top 100 Ethereum tokens:
$SUSHI - 18 decimals - $10 - single unit value is $0.00000000000000001 $WTB - 8 decimals - $33.000 - single unit value is $0.00033 $USDC - 6 decimals - $1 - single unit value is $0.000001 $CEL - 4 decimals - $4,75 - single unit value is $0.000475 $XAUT - 6 decimals - $1.850 - single unit value is $0.001850
As long as gas costs are more than this, it's safe. In the case of WBTC, 1 unit is about $0.00033, which still has a safety margin of about 4 orders of magnitude. There may however be some tokens with low or no decimals and a high value that should not be added to the BentoBox.