Proposed: July 3, 2023
Status: Passed
Link: Snapshot
Beanstalk Farms
Proposer Wallet: 0xf9d183af486a973b7921ceb5fdc9908d12aab440
Currently there is a Withdrawal Freeze that lasts from the time of Withdrawal until the end of the Season. This provides an unnecessarily complex UX as Farmers are forced to perform 2 on-chain actions at different times (Withdraw then Claim). For example, this limits the potential for using Deposits throughout DeFi via Pipeline as Deposits cannot atomically be swapped for the underlying. Furthermore, the supply overhang creates an economic inefficiency for Beanstalk and the lockup release at the same time creates an economic disadvantage for small Farmers when exiting the Silo.
If the Withdrawal Freeze is removed with no changes to Earned Bean distribution, Beanstalk becomes susceptible to an attack where an account can Deposit whitelisted assets in the Silo, call gm
and Withdraw the assets in the same transaction, gaining risk-free Bean seigniorage in the process.
The Seeds per BDV reward for a whitelisted asset is static and can only be set upon whitelisting. This makes it such that (1) Seeds per BDV rewards cannot easily be updated via BIP and (2) no system for autonomously updating Seeds per BDV rewards can exist.
Indexing Deposits by Season results in scenarios where Farmers may forfeit Stalk when Converting from a whitelisted asset to another with a lower Seeds per BDV.
Seeds are implemented without decimals, limiting the economic flexibility of Silo incentives.
Currently Beanstalk does not have a gas efficient way to read the total Deposited BDV in the Silo. In a future Seed Gauge System, Beanstalk may need to calculate average Seeds per BDV across all Deposited assets.
Currently Beanstalk rewards 2 and 4 Seeds per BDV for urBEAN Deposits and urBEAN3CRV Deposits, respectively. There is a significant amount of Deposited urBEAN3CRV that could be Converted to repeg the Bean price. Beanstalk does not benefit from incentivizing Farmers to keep their Unripe assets in the Silo. Furthermore, the excessive accrual of Grown Stalk to Unripe asset holders during this extended period without Bean minting continues to make new Deposits less attractive.
Silo Deposits do not implement any standard interface, significantly limiting the composability of Bean's positive carry. Protocols such as Tractor, Depot, etc. need to implement Deposit specific functionality in order to support them. Protocols such as Seaport do not support Deposits.
Remove the Withdrawal Freeze entirely, allowing Farmers to Withdraw assets in the Silo directly to Circulating or Farm balances in a single transaction.
withdrawDeposit(s)
to send the Withdrawn assets to Farm or Circulating balances using LibTransfer.sendToken
, instead of creating a Withdrawal.claimWithdrawal(s)
to a new LegacyClaimWithdrawalFacet
to be used by Farmers that have unclaimed Withdrawals at the time of this upgrade.Revise the distribution of Earned Beans such that they Vest after the Vesting Period after the gm
function is called. Set the Vesting Period to 10 blocks.
In practice, this means that a Farmer who Mows their Grown Stalk during the Vesting Period will be credited with that Stalk when Earned Beans are distributed next.
earnedBeans
into two uint128
variables: earnedBeans
and newEarnedStalk
.rewardToSilo
, set newEarnedStalk = amount.mul(C.getStalkperBean())
(i.e., the number of new Earned Stalk is equal to the number of Beans rewarded to the Silo)._balanceOfEarnedBeans
to properly exclude vesting Earned Stalk when computing a Farmer's Stalk balance.Introduce Stems for each token on the Deposit Whitelist, where Stems represent the Stalk Grown per BDV of Deposited value. This value starts at 0 at the time of Stem deployment (the Silo V3 BIP), or when a new token is added to the Deposit Whitelist.
Index Deposits based on Stems instead of by Season. A higher Stem count corresponds to an older Deposit. Storing Deposits based on Seasons does not allow for flexibility in Seeds per BDV values. With Stems, Seeds per BDV values can now be changed via governance and can have up to 6 decimals.
Store the total Deposited BDV of each whitelisted asset in the Silo. This enables future work on a Seed Gauge System that could need to calculate the average Seeds per BDV across all Deposited assets.
Storing Deposits based on Stems enables the cleanup of the Silo V1 and V2 storage systems into a single storage method that supports ERC-1155s. This requires a migration function (mowAndMigrate
), in which Farmers submit all of their Deposits and the function that verifies their existence, removes them from the old storage slots, and migrates them into the Stem-based slots with ERC-1155 support.
A gas-saving migration function (mowAndMigrateNoDeposits
) is available for accounts with no current Deposits.
As a result of the Stems migration, Farmers can now mow
their Grown Stalk for each individual whitelisted asset. mowMultiple
is added to allow Farmers to Mow their Grown Stalk for multiple whitelisted assets at once.
There are no penalties for waiting to migrate from Silo V2 (or V1) to Silo V3, but an account must be migrated in order to interact with the Silo again after the commitment of the Silo V3 BIP.
stalkEarnedPerSeason
level, such that Seeds can now have up to 6 decimals.SiloFacet
, ConvertFacet
and other facet functions from using Seeds to Stems.mowAndMigrate
and mowAndMigrateNoDeposits
migration functions that migrate an account from Silo V2 (or V1) to Silo V3. SiloFacet
logic into SiloFacet
, MigrationFacet
and ApprovalFacet
to reduce the SiloFacet
size.token
input to mow
and introduce mowMultiple
in SiloFacet
.Set the Seeds per BDV for both urBEAN and urBEAN3CRV to 0.
The Beanstalk DAO expressed a preference for setting the Unripe Seeds per BDV rewards to be equal in Temp-Check-1, and specifically expressed a preference for them both being set to 0 in Temp-Check-2.
Implement Silo Deposits using the ERC-1155 standard. ERC-1155s support an id
and a value
, matching the semi-fungible nature of Silo Deposits wherein they are non-fungible across Stems and fungible within the same number of Stems.
The ERC-20 and ERC-721 standards would not suffice for Silo Deposits:
id
.ERC-1155 tokens will be distributed to Farmers upon mowAndMigrate
.
id
is the concatenation of the token address (20 bytes) and the Stem of the Deposit (12 bytes). The value
is the number of tokens.MetadataFacet
, which contains on-chain metadata for each ERC-1155 token.Adding the ability to send Withdrawn assets directly to the Farmer's Farm or Circulating balance without the need for a separate transaction reduces the friction of interacting with Beanstalk.
Introducing a LegacyClaimWithdrawalFacet
facilitates backwards compatibility for Farmers with unclaimed Withdrawals at the time of this upgrade.
Implementing Stems allows for Seeds per BDV to be changed via governance and set with greater precision, improving the economic flexibility of Silo incentives.
Providing a way for Beanstalk to calculate the average Seeds per BDV across all Deposited assets in a gas-efficient manner can be used to facilitate a future Seed Gauge System.
Allowing Farmers to mow
or mowMultiple
with distinct whitelisted assets increases the customizability of interacting with the Silo.
Implementing Silo Deposits as ERC-1155 tokens improves the composability of Beanstalk.
Improving the composability of Beanstalk and reducing the number of separate transactions required to interact with it improves the user experience and utility of Beanstalk and Beans.
Removing the Withdrawal Freeze with no changes to Earned Bean distribution would create the opportunity to receive Bean seigniorage without taking on any exposure to the Bean price. Implementing a vesting period for Earned Beans mitigates this attack vector. In addition, a vesting period requires any related multi-block MEV attack to sustain the attack over at least that many blocks.
Improving the efficiency of the Silo and customizability of Seeds per BDV rewards improves the utility of Beanstalk and Beans.
Eliminating situations where Stalk is unnecessarily forfeited during Conversions reduces the friction of interacting with Beanstalk.
There is an incentive not to Convert urBEAN3CRV to urBEAN given the loss of Seeds. Unripe Seed Parity reduces the incentive not to Convert urBEAN3CRV to urBEAN dramatically. Given that the potential sellable Beans to due to the Chop Penalty is so small compared to the liquidity in the pool, Beanstalk should incentivize more Converts from urBEAN3CRV to urBEAN. This should significantly contribute to peg maintenance in the short term.
There is no need to use Seeds per BDV rewards to create opportunity cost associated with Withdrawing and Redepositing Unripe assets. Excessive Grown Stalk per BDV Deposited associated with Unripe assets is likely hurting Beanstalk's ability to attract new Depositors.
The positive carry of Beans is generally not accessible in DeFi given the lack of composability with Silo Deposits. Improving the composability of Silo Deposits by tokenizing them as ERC-1155s improves the user experience and utility of Beanstalk and Beans.
The init
function on the following InitBipNewSilo
contract is called:
The following SiloFacet
is removed from Beanstalk:
The following SiloFacet
is added to Beanstalk:
SiloFacet
Function ChangesName | Selector | Action | Type | New Functionality |
---|---|---|---|---|
balanceOf |
0x00fdd58e |
Add | View | ✓ |
balanceOfBatch |
0x4e1273f4 |
Add | View | ✓ |
balanceOfEarnedBeans |
0x3e465a2e |
Replace | View | |
balanceOfEarnedSeeds |
0x602aa123 |
Remove | View | |
balanceOfEarnedStalk |
0x341b94d5 |
Replace | View | |
balanceOfGrownStalk |
0x249564aa |
Remove | View | ✓ |
balanceOfGrownStalk |
0x8915ba24 |
Add | View | ✓ |
balanceOfPlenty |
0x896651e8 |
Replace | View | ✓ |
balanceOfRainRoots |
0x69fbad94 |
Replace | View | |
balanceOfRoots |
0xba39dc02 |
Replace | View | |
balanceOfSeeds |
0x4916bc72 |
Remove | View | |
balanceOfSop |
0xa7bf680f |
Replace | View | |
balanceOfStalk |
0x8eeae310 |
Replace | View | |
claimPlenty |
0x45947ba9 |
Replace | Call | |
deposit |
0xf19ed6be |
Replace | Call | |
getDeposit |
0x8a6a7eb4 |
Remove | View | |
getDeposit |
0x61449212 |
Add | View | |
getDepositId |
0x98f2b8ad |
Add | View | ✓ |
getSeedsPerToken |
0x9f9962e4 |
Add | View | ✓ |
getTotalDeposited |
0x0c9c31bd |
Replace | View | |
getTotalDepositedBDV |
0x9d6a924e |
Add | View | ✓ |
grownStalkForDeposit |
0x3a1b0606 |
Add | View | ✓ |
inVestingPeriod |
0x0b2939d1 |
Add | View | ✓ |
lastSeasonOfPlenty |
0xbe6547d2 |
Replace | View | |
lastUpdate |
0xcb03fb1e |
Replace | View | |
migrationNeeded |
0xc38b3c18 |
Add | View | ✓ |
update |
0x1c1b8772 |
Remove | Call | |
mow |
0x150d5173 |
Add | Call | ✓ |
mowMultiple |
0x7d44f5bb |
Add | Call | ✓ |
plant |
0x779b3c5c |
Replace | Call | |
safeBatchTransferFrom |
0x2eb2c2d6 |
Add | Call | ✓ |
safeTransferFrom |
0xf242432a |
Add | Call | ✓ |
seasonToStem |
0x896ab1c6 |
Add | View | ✓ |
stemStartSeason |
0xbc771977 |
Add | View | ✓ |
stemTipForToken |
0xabed2d41 |
Add | View | ✓ |
tokenSettings |
0xe923e8d4 |
Replace | View | |
totalEarnedBeans |
0xfd9de166 |
Replace | View | |
totalRoots |
0x46544166 |
Replace | View | |
totalSeeds |
0xd8bd0d9d |
Remove | View | |
totalStalk |
0x7b52fadf |
Replace | View | |
transferDeposit |
0x9e32d261 |
Remove | Call | ✓ |
transferDeposit |
0x081d77ba |
Add | Call | ✓ |
transferDeposits |
0x0d2615b1 |
Remove | Call | ✓ |
transferDeposits |
0xc56411f6 |
Add | Call | ✓ |
withdrawDeposit |
0x7af9a0ce |
Remove | Call | |
withdrawDeposit |
0xe348f82b |
Add | Call | ✓ |
withdrawDeposits |
0xb189d9c8 |
Remove | Call | |
withdrawDeposits |
0x27e047f1 |
Add | Call | ✓ |
withdrawFreeze |
0x55926690 |
Remove | View |
SiloFacet
Event ChangesName | Change |
---|---|
AddDeposit |
Updated to reflect new Deposit accounting system |
AddWithdrawal |
Removed |
RemoveDeposit |
Updated to reflect new Deposit accounting system |
RemoveDeposits |
Updated to reflect new Deposit accounting system |
SeedsBalanceChanged |
Removed |
TransferBatch |
Emitted when multiple Deposits are removed or transferred |
TransferSingle |
Emitted when a Deposit is created, removed or transferred |
The following LegacyClaimWithdrawalFacet
is added to Beanstalk:
LegacyClaimWithdrawalFacet
Function ChangesName | Selector | Action | Type | New Functionality |
---|---|---|---|---|
claimWithdrawal |
0x488e94dc |
Replace | Call | |
claimWithdrawals |
0x764a9874 |
Replace | Call | |
getTotalWithdrawn |
0xb1c7a20f |
Replace | View | |
getWithdrawal |
0xe23c96a4 |
Replace | View |
LegacyClaimWithdrawalFacet
Event ChangesNone.
The following SeasonFacet
is removed from Beanstalk:
The following SeasonFacet
is added to Beanstalk:
SeasonFacet
Function ChangesName | Selector | Action | Type | New Functionality |
---|---|---|---|---|
abovePeg |
0x2a27c499 |
Replace | View | |
gm |
0x64ee4b80 |
Replace | Call | |
paused |
0x5c975abb |
Replace | View | |
plentyPerRoot |
0xe60d7a83 |
Replace | View | |
poolDeltaB |
0x471bcdbe |
Replace | View | |
rain |
0x43def26e |
Replace | View | |
season |
0xc50b0fb0 |
Replace | View | |
seasonTime |
0xca7b7d7b |
Replace | View | |
sunrise |
0xfc06d2a6 |
Replace | Call | |
sunriseBlock |
0x3b2ecb70 |
Replace | View | |
time |
0x16ada547 |
Replace | View | |
totalDeltaB |
0x06c499d8 |
Replace | View | |
weather |
0x686b6159 |
Replace | View |
SeasonFacet
Event ChangesNone.
The following MigrationFacet
is added to Beanstalk:
MigrationFacet
Function ChangesName | Selector | Action | Type | New Functionality |
---|---|---|---|---|
balanceOfGrownStalkUpToStemsDeployment |
0x505f43ea |
Add | View | ✓ |
balanceOfLegacySeeds |
0x1be2cfd8 |
Add | View | ✓ |
getDepositLegacy |
0xa9be1acb |
Add | View | ✓ |
mowAndMigrate |
0x1f4f3d55 |
Add | Call | ✓ |
mowAndMigrateNoDeposits |
0xaed942e9 |
Add | Call | ✓ |
MigrationFacet
Event ChangesNone.
The following ApprovalFacet
is added to Beanstalk:
ApprovalFacet
Function ChangesName | Selector | Action | Type | New Functionality |
---|---|---|---|---|
approveDeposit |
0x1302afc2 |
Replace | Call | |
decreaseDepositAllowance |
0xd9ee1269 |
Replace | Call | |
depositAllowance |
0x2a6a8ef5 |
Replace | View | |
depositPermitDomainSeparator |
0x8966e0ff |
Replace | View | |
depositPermitNonces |
0x843bc425 |
Replace | View | |
increaseDepositAllowance |
0x5793e485 |
Replace | Call | |
isApprovedForAll |
0xe985e9c5 |
Add | View | ✓ |
permitDeposit |
0x120b5702 |
Replace | Call | |
permitDeposits |
0xd5770dc7 |
Replace | Call | |
setApprovalForAll |
0xa22cb465 |
Add | Call | ✓ |
ApprovalFacet
Event ChangesName | Change |
---|---|
ApprovalForAll |
New event |
The following ConvertFacet
is removed from Beanstalk:
The following ConvertFacet
is added to Beanstalk:
ConvertFacet
Function ChangesName | Selector | Action | Type | New Functionality |
---|---|---|---|---|
convert |
0x3b2a1b28 |
Remove | Call | |
convert |
0xb362a6e8 |
Add | Call | ✓ |
enrootDeposit |
0xd5d2ea8c |
Remove | Call | |
enrootDeposit |
0x0b58f073 |
Add | Call | ✓ |
enrootDeposits |
0x83b9e85d |
Remove | Call | |
enrootDeposits |
0x88fcd169 |
Add | Call | ✓ |
getAmountOut |
0x4aa06652 |
Replace | View | |
getMaxAmountIn |
0x24dd285c |
Replace | View |
ConvertFacet
Event ChangesName | Change |
---|---|
RemoveDeposit |
New event |
RemoveDeposits |
Updated to reflect new Deposit accounting system |
TransferBatch |
New event |
The following WhitelistFacet
is removed from Beanstalk:
The following WhitelistFacet
is added to Beanstalk:
WhitelistFacet
Function ChangesName | Selector | Action | Type | New Functionality |
---|---|---|---|---|
dewhitelistToken |
0x86b40a1b |
Replace | Call | |
updateStalkPerBdvPerSeasonForToken |
0xf18d9ed0 |
Add | Call | ✓ |
whitelistToken |
0xd8a6aafe |
Replace | Call | ✓ |
WhitelistFacet
Event ChangesName | Change |
---|---|
UpdatedStalkPerBdvPerSeason |
New event |
WhitelistToken |
Updated to reflect new Deposit accounting system |
The following MetadataFacet
is added to Beanstalk:
MetadataFacet
Function ChangesName | Selector | Action | Type | New Functionality |
---|---|---|---|---|
imageURI |
0x8f742d16 |
Add | View | ✓ |
uri |
0x0e89341c |
Add | View | ✓ |
MetadataFacet
Event ChangesNone.
The following TokenFacet
(s) are being removed from Beanstalk:
The following TokenFacet
is added to Beanstalk:
TokenFacet
Function ChangesName | Selector | Action | Type | New Functionality |
---|---|---|---|---|
approveToken |
0xda3e3397 |
Replace | Call | |
decreaseTokenAllowance |
0x0bc33ce4 |
Replace | Call | |
getAllBalance |
0xfdb28811 |
Replace | View | |
getAllBalances |
0xb6fc38f9 |
Replace | View | |
getBalance |
0xd4fac45d |
Replace | View | |
getBalances |
0x6a385ae9 |
Replace | View | |
getExternalBalance |
0x4667fa3d |
Replace | View | |
getExternalBalances |
0xc3714723 |
Replace | View | |
getInternalBalance |
0x8a65d2e0 |
Replace | View | |
getInternalBalances |
0xa98edb17 |
Replace | View | |
increaseTokenAllowance |
0xb39062e6 |
Replace | Call | |
onERC1155BatchReceived |
0xbc197c81 |
Add | View | ✓ |
onERC1155Received |
0xf23a6e61 |
Add | View | ✓ |
permitToken |
0x7c516e94 |
Replace | Call | |
tokenAllowance |
0x8e8758d8 |
Replace | View | |
tokenPermitDomainSeparator |
0x1f351f6a |
Replace | View | |
tokenPermitNonces |
0x4edcab2d |
Replace | View | |
transferInternalTokenFrom |
0xd3f4ec6f |
Replace | Call | |
transferToken |
0x6204aa43 |
Replace | Call | |
unwrapEth |
0xbd32fac3 |
Replace | Call | |
wrapEth |
0x1c059365 |
Replace | Call |
TokenFacet
Event ChangesNone.
None.
The commit hash of this BIP is 9f286e1f1b1e67bc40d35aaf4b16e5c6d83ebdd9.
Halborn has performed an audit of this BIP up to commit hash 24bf3d33355f516648b02780b4b232181afde200. You can view the final audit report here.
Changes between the two commits:
stem
type in the RemoveDeposit(s)
event signatures in ConvertFacet
from int128
to int96
;seasonToStem
and stemTipPerToken
from int128
to int96
; andSilo.sol
import removed from ConvertFacet
.Immediately upon commitment.