Beanstalk is a permissionless fiat stablecoin protocol built on Ethereum.
Technical documentation is a WIP. Current draft is available here.
A comprehensive list of contracts related to Beanstalk is available here.
Contract | Address |
---|---|
Beanstalk | 0xC1E088fC1323b20BCBee9bd1B9fC9546db5624C5 |
Bean | 0xBEA0000029AD1c77D3d5D23Ba2D8893dB9d1Efab |
Curve BEAN:3CRV Metapool | 0xc9C32cd16Bf7eFB85Ff14e0c8603cc90F6F2eE49 |
Unripe Bean ERC-20 token | 0x1BEA0050E63e05FBb5D8BA2f10cf5800B6224449 |
Unripe BEAN:3CRV LP token | 0x1BEA3CcD22F4EBd3d37d731BA31Eeca95713716D |
Fertilizer ERC-1155 token | 0x402c84de2ce49af88f5e2ef3710ff89bfed36cb6 |
Fertilizer Admin | 0xfECB01359263C12Aa9eD838F878A596F0064aa6e |
Fertilizer Implementation | 0x39cdAf9Dc6057Fd7Ae81Aaed64D7A062aAf452fD |
Beanstalk Price Contract | 0xA57289161FF18D67A68841922264B317170b0b81 |
Beanstalk Contract Owner (BCM) | 0xa9bA2C40b263843C04d344727b954A545c81D043 |
Beanstalk Farms Multisig | 0x21DE18B6A8f78eDe6D16C50A167f6B222DC08DF7 |
Bean Sprout Multisig | 0xb7ab3f0667eFF5e2299d39C23Aa0C956e8982235 |
BeaNFT Genesis | 0xa755A670Aaf1FeCeF2bea56115E65e03F7722A79 |
BeaNFT Winter | 0x459895483556dad32526efa461f75e33e458d9e9 |
The Beanstalk smart contract is a multi-facet proxy as it implements EIP-2535. Thus, the Beanstalk contract pulls in functions from a variety of different contracts (called facets in the EIP-2535 documentation) that are all capable of sharing the same state object.
The following are the different facets Beanstalk uses:
The following facets are part of the diamond functionality:
Contract | Address |
---|---|
DiamondCutFacet | 0xDFeFF7592915bea8D040499E961E332BD453C249 |
DiamondLoupeFacet | 0xB51D5C699B749E0382e257244610039dDB272Da0 |
OwnershipFacet | 0x5D45283Ff53aabDb93693095039b489Af8b18Cf7 |
The Beanstalk DAO partnered with Immunefi to launch a bug bounty program with rewards up to 1.1M Beans.
You can find the bug bounty program and submit bug reports here.
- clone the repository
- run
cd protocol
to enter the protocol repository - run
npm install
- run
npx hardhat compile
We elect to use anvil
instead of hardhat
for local node forking as anvil
is considerably faster than hardhat
and properly caches the blockchain locally
- ensure you are in the
/protocol
repository - Install Foundry
curl -L https://foundry.paradigm.xyz | bash
& reopen terminal - Run
foundryup
to ensure latest version - Start a locally forked node with the following command:
anvil --fork-url <FORK_RPC> --fork-block-number <BLOCK_NUMBER> --chain-id 1337
For <FORK_RPC>
, use an Alchemy or Infura RPC URL.
For <BLOCK_NUMBER>
, we currently use 15128715
, but you are welcome to use any block after Replant2
It should be very clear if the node starts up properly.
Note: anvil will cache the blockchain provided that BLOCK_NUMBER
does NOT change. Given this, we recommend picking a block and sticking to it.
- ensure that you have a localhost
- run
npx hardhat replant --network localhost
- make sure you are in the
protocol
repository - run
npm test
to run all coverage tests - run
npx hardhat coverage
to run all coverage tests and generate a coverage report
As Beanstalk implements EIP-2535, Beanstalk is upgraded through a diamondCut
function call.
There are two different ways a diamondCut
can apply code to Beanstalk:
- adding/replacing/removing functions
- Functions being added/replaced are implemented in smart contracts referred to as
facets
. Facets are no different than a normal smart contract with callable functions. In order to share a state, Facets can only define 1 internal state variable: TheAppStorage
struct defined inAppStorage.sol
.
- Functions being added/replaced are implemented in smart contracts referred to as
- calling the
init
function of a smart contract- This is a one time action and will be called when the
diamondCut
is executed. There can be 1init
call perdiamondCut
.
- This is a one time action and will be called when the
For this tutorial, we are going to create a new facet called SampleFacet
. In your own implementation replace iterations of the word Sample
with the name of the Facet you want to create.
- make sure you are in the
protocol
repository - in
protocol/farm/facets/
, create a new folder calledSampleFacet
- within the
SampleFacet
folder create a file calledSampleFacet.sol
. - implement your faucet. You can use
SampleFacet.sol
inprotocol/samples
as a template for a basis faucet. Note that facets can only haveAppStorage
as an internal state variable or there will be issues with accessingAppStorage
. - modify the
deploy
function inscripts/deploy
to include your new facet, so that thefaucet
will be deployed with the Beanstalk diamond.
There are a couple of steps that must be done before we can fork mainnet and upgrade Bips/test Bip upgrades
-
include the following code in the networks section of the hardhat.config.js, where ALCHEMY_URL is your mainnet url. We recommend using Alchemy for this. The blockNumber is optional, but we recommend to be one that is close to the current block number but not too close.
forking: { url: <RPC_URL>, blockNumber: <BLOCK_NUMBER> },
localhost: { chainId: 1337, url: "http://127.0.0.1:8545", forking: { url: <RPC_URL>, blockNumber: <BLOCK_NUMBER> }, },
-
include as in imports section
const BEANSTALK = "0xC1E088fC1323b20BCBee9bd1B9fC9546db5624C5"; const ownerFacet = await ethers.getContractAt('OwnershipFacet', BEANSTALK); const owner = await ownerFacet.owner(); const { upgradeWithNewFacets } = require('./scripts/diamond.js')
-
Lastly, include the tasks required for upgrading above module.exports:
task("upgrade", "Commits a bip", async() => { await hre.network.provider.request({ method: "hardhat_impersonateAccount", params: [owner], }); const account = await ethers.getSigner(owner) await upgradeWithNewFacets({ diamondAddress: BEANSTALK, facetNames: [], initFacetName: 'InitEmpty', initArgs: [], bip: false, verbose: true, account: account }); })
-
(this is an example of what bip11 deployment looked like):
await upgradeWithNewFacets({ diamondAddress: BEANSTALK, initFacetName: 'InitBip11', facetNames: ['MarketplaceFacet'], libraryNames: ["LibClaim"], facetLibraries: { "MarketplaceFacet": ["LibClaim"], }, bip: false, verbose: true, account: account });
-
Spin up your mainnet fork node with:
npx hardhat node
-
In another console, execute your tasks by running
npx hardhat upgrade --network localhost
where
upgrade
is where you put the name of your task, in the example above it was named upgrade. -
Now you can test your changes using your local blockchain node that should now have the latest version of beanstalk that you upgraded.
Code Version: 2.0.0
Whitepaper Version 2.0.0