Skip to content

Commit

Permalink
EBIP-19: Misc Bug Fixes 2 (#1148)
Browse files Browse the repository at this point in the history
  • Loading branch information
Brean0 authored Oct 14, 2024
2 parents d938ad7 + a26664d commit 37635af
Show file tree
Hide file tree
Showing 27 changed files with 560 additions and 55 deletions.
56 changes: 56 additions & 0 deletions protocol/abi/Beanstalk.json
Original file line number Diff line number Diff line change
Expand Up @@ -5060,6 +5060,49 @@
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
"internalType": "uint256",
"name": "blockNumber",
"type": "uint256"
}
],
"name": "getUsedConvertCapacity",
"outputs": [
{
"components": [
{
"internalType": "uint256",
"name": "overallConvertCapacityUsed",
"type": "uint256"
},
{
"components": [
{
"internalType": "address",
"name": "well",
"type": "address"
},
{
"internalType": "uint256",
"name": "wellConvertCapacityUsed",
"type": "uint256"
}
],
"internalType": "struct ConvertGettersFacet.WellConvertCapacityUsed[]",
"name": "wellConvertCapacityUsed",
"type": "tuple[]"
}
],
"internalType": "struct ConvertGettersFacet.ConvertCapacityUsed",
"name": "",
"type": "tuple"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [
{
Expand Down Expand Up @@ -10228,6 +10271,19 @@
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "l2BlockNumber",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "paused",
Expand Down
13 changes: 13 additions & 0 deletions protocol/abi/MockBeanstalk.json
Original file line number Diff line number Diff line change
Expand Up @@ -9566,6 +9566,19 @@
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "l2BlockNumber",
"outputs": [
{
"internalType": "uint256",
"name": "",
"type": "uint256"
}
],
"stateMutability": "view",
"type": "function"
},
{
"inputs": [],
"name": "paused",
Expand Down
72 changes: 72 additions & 0 deletions protocol/contracts/beanstalk/init/InitMultFlowPumpUpgrade.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
/*
SPDX-License-Identifier: MIT
*/

pragma solidity ^0.8.20;

import {IAquifer} from "contracts/interfaces/basin/IAquifer.sol";
import {IWell, Call, IERC20} from "contracts/interfaces/basin/IWell.sol";
import {LibWhitelistedTokens} from "contracts/libraries/Silo/LibWhitelistedTokens.sol";
import {LibWellDeployer} from "contracts/libraries/Basin/LibWellDeployer.sol";
import {AppStorage} from "contracts/beanstalk/storage/AppStorage.sol";

interface IWellUpgradeable {
function upgradeTo(address implementation) external;
}

/**
* @author Brean
* @title InitMultiFlowPumpUpgrade upgrades the Whitelisted Wells to use the new MultiFlowPump.
**/
contract InitMultiFlowPumpUpgrade {
address internal constant MULTI_FLOW_PUMP_V1_2_1 = 0xBA150002660BbCA20675D1C1535Cd76C98A95b13;
address internal constant U_WELL_IMPLEMENTATION =
address(0xBA510995783111be5301d93CCfD5dE4e3B28e50B);
address internal constant AQUIFER = address(0xBA51AAAa8C2f911AE672e783707Ceb2dA6E97521);
address internal constant CP2_WELL_FUNCTION =
address(0xBA15000450Bf6d48ec50BD6327A9403E401b72b4);
address internal constant BEAN_USDC = address(0xBea00ee04D8289aEd04f92EA122a96dC76A91bd7);
address internal constant BEAN_USDT = address(0xbEA00fF437ca7E8354B174339643B4d1814bED33);

AppStorage internal s;

function init() external {
address[] memory wells = LibWhitelistedTokens.getWhitelistedWellLpTokens();

for (uint256 i; i < wells.length; i++) {
IWell well = IWell(wells[i]);
// fetch the well's immutable and init data
IERC20[] memory tokens = well.tokens();
Call memory wellFunction = well.wellFunction();
Call[] memory pumps = well.pumps();

// replace the pump addresses with the new MultiFlowPump address
pumps[0].target = MULTI_FLOW_PUMP_V1_2_1;

// if the well is not USDC or USDT, set the well function to CP2_WELL_FUNCTION
if (wells[i] != BEAN_USDC && wells[i] != BEAN_USDT) {
wellFunction.target = CP2_WELL_FUNCTION;
}

// encode the immutable and init data
(bytes memory immutableData, bytes memory initData) = LibWellDeployer
.encodeWellDeploymentData(AQUIFER, tokens, wellFunction, pumps);

// deploy the new well:
address minimalProxyWell = IAquifer(AQUIFER).boreWell(
U_WELL_IMPLEMENTATION,
immutableData,
initData,
bytes32("1")
);

// upgrade the well to the new implementation
IWellUpgradeable(wells[i]).upgradeTo(minimalProxyWell);
// call add liquidity to start the pump.
well.sync(address(this), 0);

// delete the well Oracle snapshot.
delete s.sys.wellOracleSnapshots[wells[i]];
}
}
}
45 changes: 43 additions & 2 deletions protocol/contracts/beanstalk/silo/ConvertGettersFacet.sol
Original file line number Diff line number Diff line change
Expand Up @@ -9,13 +9,24 @@ import {LibRedundantMath256} from "contracts/libraries/LibRedundantMath256.sol";
import {LibConvert} from "contracts/libraries/Convert/LibConvert.sol";
import {LibWellMinting} from "contracts/libraries/Minting/LibWellMinting.sol";
import {LibDeltaB} from "contracts/libraries/Oracle/LibDeltaB.sol";
import {LibArbitrum} from "contracts/libraries/LibArbitrum.sol";
import {LibWhitelistedTokens} from "contracts/libraries/Silo/LibWhitelistedTokens.sol";

/**
* @author Publius
* @title ConvertGettersFacet contains view functions related to converting Deposited assets.
**/
contract ConvertGettersFacet {
using LibRedundantMath256 for uint256;
struct WellConvertCapacityUsed {
address well;
uint256 wellConvertCapacityUsed;
}

struct ConvertCapacityUsed {
uint256 overallConvertCapacityUsed;
WellConvertCapacityUsed[] wellConvertCapacityUsed;
}

/**
* @notice Returns the maximum amount that can be converted of `tokenIn` to `tokenOut`.
Expand Down Expand Up @@ -93,7 +104,7 @@ contract ConvertGettersFacet {
uint256 _overallCappedDeltaB = LibConvert.abs(LibDeltaB.overallCappedDeltaB());
uint256 overallConvertCapacityUsed = s
.sys
.convertCapacity[block.number]
.convertCapacity[LibArbitrum.blockNumber()]
.overallConvertCapacityUsed;
return
overallConvertCapacityUsed > _overallCappedDeltaB
Expand All @@ -110,10 +121,40 @@ contract ConvertGettersFacet {
AppStorage storage s = LibAppStorage.diamondStorage();
return
LibConvert.abs(LibDeltaB.cappedReservesDeltaB(well)).sub(
s.sys.convertCapacity[block.number].wellConvertCapacityUsed[well]
s.sys.convertCapacity[LibArbitrum.blockNumber()].wellConvertCapacityUsed[well]
);
}

/**
* @notice Returns the used convert capacity information at a specific block number.
* @param blockNumber the block number to get the used convert capacity for
*/
function getUsedConvertCapacity(
uint256 blockNumber
) external view returns (ConvertCapacityUsed memory) {
AppStorage storage s = LibAppStorage.diamondStorage();
address[] memory tokens = LibWhitelistedTokens.getWhitelistedWellLpTokens();
ConvertCapacityUsed memory usedConvertCapacity;
usedConvertCapacity.wellConvertCapacityUsed = new WellConvertCapacityUsed[](tokens.length);
for (uint i; i < tokens.length; i++) {
address well = tokens[i];
uint256 wellConvertCapacityUsed = s
.sys
.convertCapacity[blockNumber]
.wellConvertCapacityUsed[well];

WellConvertCapacityUsed memory wellConvertCapacityUsedStruct;
wellConvertCapacityUsedStruct.well = well;
wellConvertCapacityUsedStruct.wellConvertCapacityUsed = wellConvertCapacityUsed;
usedConvertCapacity.wellConvertCapacityUsed[i] = wellConvertCapacityUsedStruct;
}
usedConvertCapacity.overallConvertCapacityUsed = s
.sys
.convertCapacity[blockNumber]
.overallConvertCapacityUsed;
return usedConvertCapacity;
}

/**
* @notice Calculates the bdv penalized by a convert.
* @dev See {LibConvert.calculateStalkPenalty}.
Expand Down
3 changes: 2 additions & 1 deletion protocol/contracts/beanstalk/sun/SeasonFacet/SeasonFacet.sol
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {Invariable} from "contracts/beanstalk/Invariable.sol";
import {LibTractor} from "contracts/libraries/LibTractor.sol";
import {LibRedundantMath256} from "contracts/libraries/LibRedundantMath256.sol";
import {IBean} from "contracts/interfaces/IBean.sol";
import {LibArbitrum} from "contracts/libraries/LibArbitrum.sol";

/**
* @title SeasonFacet
Expand Down Expand Up @@ -102,7 +103,7 @@ contract SeasonFacet is Invariable, Weather {
function stepSeason() private returns (uint32 season) {
s.sys.season.current += 1;
season = s.sys.season.current;
s.sys.season.sunriseBlock = uint64(block.number); // Note: will overflow after 2^64 blocks.
s.sys.season.sunriseBlock = uint64(LibArbitrum.blockNumber()); // Note: will overflow after 2^64 blocks.
emit Sunrise(season);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import {LibRedundantMath256} from "contracts/libraries/LibRedundantMath256.sol";
import {LibDeltaB} from "contracts/libraries/Oracle/LibDeltaB.sol";
import {LibFlood} from "contracts/libraries/Silo/LibFlood.sol";
import {BeanstalkERC20} from "contracts/tokens/ERC20/BeanstalkERC20.sol";
import {LibArbitrum} from "contracts/libraries/LibArbitrum.sol";

/**
* @title SeasonGettersFacet
Expand Down Expand Up @@ -297,4 +298,8 @@ contract SeasonGettersFacet {
{
return LibFlood.getWellsByDeltaB();
}

function l2BlockNumber() external view returns (uint256) {
return LibArbitrum.blockNumber();
}
}
16 changes: 16 additions & 0 deletions protocol/contracts/ecosystem/arbitrum/ArbSys.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.20;

import {LibArbitrum} from "contracts/libraries/LibArbitrum.sol";

/**
* @title ArbSys
* @author Brean
* @notice ArbSys is a precompile for the Arbitrum network that provides the current block number.
*/
contract ArbSys {
function arbBlockNumber() external view returns (uint256) {
return LibArbitrum.blockNumber();
}
}
2 changes: 2 additions & 0 deletions protocol/contracts/interfaces/IMockFBeanstalk.sol
Original file line number Diff line number Diff line change
Expand Up @@ -2166,4 +2166,6 @@ interface IMockFBeanstalk {
function woohoo() external pure returns (uint256);

function wrapEth(uint256 amount, uint8 mode) external payable;

function l2BlockNumber() external view returns (uint256);
}
22 changes: 22 additions & 0 deletions protocol/contracts/interfaces/basin/IWellUpgradeable.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.20;

import {IWell} from "contracts/interfaces/basin/IWell.sol";

/**
* @title IWell is the interface for the Well contract.
*
* In order for a Well to be verified using a permissionless on-chain registry, a Well Implementation should:
* - Not be able to self-destruct (Aquifer's registry would be vulnerable to a metamorphic contract attack)
* - Not be able to change its tokens, Well Function, Pumps and Well Data
*/
interface IWellUpgradeable is IWell {
function init(string memory name, string memory symbol) external;

function initNoWellToken() external;

function upgradeTo(address newImplementation) external;

function upgradeToAndCall(address newImplementation, bytes memory data) external;
}
51 changes: 51 additions & 0 deletions protocol/contracts/libraries/Basin/LibWellDeployer.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.20;

import {IWell, Call, IERC20} from "contracts/interfaces/basin/IWell.sol";
import {IWellUpgradeable} from "contracts/interfaces/basin/IWellUpgradeable.sol";

/**
* @title LibWellDeployer
* @author Brean
* @notice LibWellDeployer provides helper functions for deploying Wells with Aquifers.
*/
library LibWellDeployer {
/**
* @notice Encode the Well's immutable data.
*/
function encodeWellDeploymentData(
address _aquifer,
IERC20[] memory _tokens,
Call memory _wellFunction,
Call[] memory _pumps
) internal pure returns (bytes memory immutableData, bytes memory initData) {
immutableData = encodeWellImmutableData(_aquifer, _tokens, _wellFunction, _pumps);
initData = abi.encodeWithSelector(IWellUpgradeable.initNoWellToken.selector);
}

function encodeWellImmutableData(
address _aquifer,
IERC20[] memory _tokens,
Call memory _wellFunction,
Call[] memory _pumps
) internal pure returns (bytes memory immutableData) {
immutableData = abi.encodePacked(
_aquifer, // aquifer address
_tokens.length, // number of tokens
_wellFunction.target, // well function address
_wellFunction.data.length, // well function data length
_pumps.length, // number of pumps
_tokens, // tokens array
_wellFunction.data // well function data (bytes)
);
for (uint256 i; i < _pumps.length; ++i) {
immutableData = abi.encodePacked(
immutableData, // previously packed pumps
_pumps[i].target, // pump address
_pumps[i].data.length, // pump data length
_pumps[i].data // pump data (bytes)
);
}
}
}
5 changes: 3 additions & 2 deletions protocol/contracts/libraries/Convert/LibConvert.sol
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import {LibTokenSilo} from "contracts/libraries/Silo/LibTokenSilo.sol";
import {GerminationSide} from "contracts/beanstalk/storage/System.sol";
import {LibBytes} from "contracts/libraries/LibBytes.sol";
import {SafeCast} from "@openzeppelin/contracts/utils/math/SafeCast.sol";
import {LibArbitrum} from "contracts/libraries/LibArbitrum.sol";

/**
* @title LibConvert
Expand Down Expand Up @@ -235,7 +236,7 @@ library LibConvert {
);

// Update penalties in storage.
ConvertCapacity storage convertCap = s.sys.convertCapacity[block.number];
ConvertCapacity storage convertCap = s.sys.convertCapacity[LibArbitrum.blockNumber()];
convertCap.overallConvertCapacityUsed = convertCap.overallConvertCapacityUsed.add(
overallConvertCapacityUsed
);
Expand Down Expand Up @@ -318,7 +319,7 @@ library LibConvert {
) internal view returns (uint256 cumulativePenalty, PenaltyData memory pdCapacity) {
AppStorage storage s = LibAppStorage.diamondStorage();

ConvertCapacity storage convertCap = s.sys.convertCapacity[block.number];
ConvertCapacity storage convertCap = s.sys.convertCapacity[LibArbitrum.blockNumber()];

// first check overall convert capacity, if none remaining then full penalty for amount in direction of peg
if (convertCap.overallConvertCapacityUsed >= overallCappedDeltaB) {
Expand Down
Loading

0 comments on commit 37635af

Please sign in to comment.