Concepts

The BentoBox is a vault that holds tokens and generate yield from flash loans and strategies for any protocol built on top of it.

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.

Concepts

Single vault

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.

MasterContracts and clones

Flash Loans

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.

Strategies

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.

Amounts and shares

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.

Batching

The batch function allows the batching of multiple BentoBox function calls in a single transaction.

Supported Tokens

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.

Minimum Token Balance

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.

Multiple protocols and Master Contracts

Any protocol can use BentoBox as it's storage of funds. The contract just needs to implement the init function.

Approval of protocols (master contracts) not tokens

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.

Functions

Public Variables

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

View Functions

The domainSeparator function returns the domain separator.

Permit

Calls the permit function on a token confirming to EIP-2612.

Approval Function

The 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 Withdrawal Functions

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 permit function.

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.

function deposit

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.

Inputs: 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 amount when share is 0.

Outputs: 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

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.

The transferMultiple function does a one-to-many transfer in a more gas efficient manner. Other complicated transfers can be composed through batch.

Batch Function

The batch function allows for executing multiple actions on the BentoBox contract in a single transaction.

Security

Free token units due to rounding (fixed)

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.