Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/dr-t-remediations' into reseed-f…
Browse files Browse the repository at this point in the history
…ert-fix
  • Loading branch information
nickkatsios committed Sep 11, 2024
2 parents 1d579af + 24d922e commit 551d1db
Show file tree
Hide file tree
Showing 50 changed files with 1,561 additions and 229 deletions.
2 changes: 1 addition & 1 deletion protocol/contracts/beanstalk/barn/FertilizerFacet.sol
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ contract FertilizerFacet is Invariable, ReentrancyGuard {
/**
* @dev Returns the amount of Fertilizer that can be purchased with `tokenAmountIn` Barn Raise tokens.
* Can be used to help calculate `minFertilizerOut` in `mintFertilizer`.
* `tokenAmountIn` has 18 decimals, `getUsdEthPrice()` has 6 decimals and `fertilizerAmountOut` has 0 decimals.
* `tokenAmountIn` has 18 decimals, `getUsdPrice()` of eth has 6 decimals and `fertilizerAmountOut` has 0 decimals.
*/
function getMintFertilizerOut(
uint256 tokenAmountIn
Expand Down
25 changes: 25 additions & 0 deletions protocol/contracts/beanstalk/init/reseed/L2/ReseedBean.sol
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,12 @@ contract ReseedBean {
bytes32 internal constant FERTILIZER_PROXY_SALT =
0x0000000000000000000000000000000000000000000000000000000000000000;

<<<<<<< reseed-mint-l2-bcm-beans
// BCM (TODO: Replace with actual L2 address)
address internal constant L2_BCM = address(0xa9bA2C40b263843C04d344727b954A545c81D043);
=======
address beanWstethLP;
>>>>>>> dr-t-remediations

/**
* @notice deploys bean, unripe bean, unripe lp, and wells.
Expand All @@ -132,6 +137,9 @@ contract ReseedBean {
uint256 beanSupply,
uint256 internalUrBeanSupply,
uint256 internalUnripeLpSupply,
uint256 wethBeans,
uint256 wstEthBeans,
uint256 stableBeans,
ExternalUnripeHolders[] calldata urBean,
ExternalUnripeHolders[] calldata urBeanLP,
address fertImplementation
Expand All @@ -145,6 +153,10 @@ contract ReseedBean {
BeanstalkERC20 unripeLP = deployUnripeLP(internalUnripeLpSupply, urBeanLP);
// wells are deployed as ERC1967Proxies in order to allow for future upgrades.
deployUpgradableWells(address(bean));
<<<<<<< reseed-mint-l2-bcm-beans
// mint beans to the bcm according to the amounts in the l1 wells.
mintBeansToBCM(bean, wethBeans, wstEthBeans, stableBeans);
=======
// set unripe to underlying tokens.
setUnripeToUnderlyingTokens(address(unripeBean), address(bean), address(unripeLP));
}
Expand All @@ -159,6 +171,7 @@ contract ReseedBean {
s.sys.silo.unripeSettings[unripeBean].underlyingToken = bean;
// set the underlying token of the unripe lp to BeanWstethLP.
s.sys.silo.unripeSettings[unripeLP].underlyingToken = beanWstethLP;
>>>>>>> dr-t-remediations
}

function deployFertilizerProxy(address fertImplementation) internal {
Expand All @@ -176,6 +189,18 @@ contract ReseedBean {
console.log("Fertilizer Proxy implementation: ", fertImplementation);
}

function mintBeansToBCM(
BeanstalkERC20 bean,
uint256 wethBeans,
uint256 wstEthBeans,
uint256 stableBeans
) internal {
// total beans is the sum of the bean sided liquidity in the wells.
// Needed for bcm to add liquidity to the L2 wells after the migration.
uint256 totalBeans = wethBeans + wstEthBeans + stableBeans;
bean.mint(L2_BCM, totalBeans);
}

function deployBean(uint256 supply) internal returns (BeanstalkERC20) {
BeanstalkERC20 bean = new BeanstalkERC20{salt: BEAN_SALT}(
address(this),
Expand Down
112 changes: 108 additions & 4 deletions protocol/contracts/beanstalk/migration/L1RecieverFacet.sol
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

pragma solidity ^0.8.20;

import {C} from "contracts/C.sol";
import {ReentrancyGuard} from "../ReentrancyGuard.sol";
import {Field} from "contracts/beanstalk/storage/Account.sol";
import {LibBytes} from "contracts/libraries/LibBytes.sol";
Expand All @@ -20,6 +19,9 @@ import {LibDiamond} from "contracts/libraries/LibDiamond.sol";
import {LibTransfer} from "contracts/libraries/Token/LibTransfer.sol";
import {IBean} from "contracts/interfaces/IBean.sol";
import {IFertilizer} from "contracts/interfaces/IFertilizer.sol";
import {Order} from "contracts/beanstalk/market/MarketplaceFacet/Order.sol";
import {Listing} from "contracts/beanstalk/market/MarketplaceFacet/Listing.sol";
import {SafeCast} from "@openzeppelin/contracts/utils/math/SafeCast.sol";

/**
* @author Brean
Expand All @@ -45,9 +47,16 @@ contract L1RecieverFacet is ReentrancyGuard {
0xf93c255615938ba5f00fac3b427da6dfa313b4d75eff216bbec62dbea2e629a2;
bytes32 internal constant FERTILIZER_MERKLE_ROOT =
0x02ec4c26c5d970fef9bc46f5fc160788669d465da31e9edd37aded2b1c95b6c2;
bytes32 internal constant PODLISTING_ORDER_MERKLE_ROOT =
0x4a000e44e0820fdb1ef4194538de1404629221d77e7c920fa8c000ce5902d503;

uint160 internal constant OFFSET = uint160(0x1111000000000000000000000000000000001111);

struct L1PodOrder {
Order.PodOrder podOrder;
uint256 beanAmount;
}

/**
* @notice emitted when L1 Beans are migrated to L2.
*/
Expand Down Expand Up @@ -95,6 +104,8 @@ contract L1RecieverFacet is ReentrancyGuard {
uint128 lastBpf
);

event L1OrdersMigrated(address indexed owner, address indexed receiver, L1PodOrder[] orders);

/**
* @notice emitted when an account approves a reciever to recieve their assets.
*/
Expand Down Expand Up @@ -288,6 +299,37 @@ contract L1RecieverFacet is ReentrancyGuard {
emit L1FertilizerMigrated(owner, reciever, fertIds, amounts, lastBpf);
}

/**
* @notice Recreates the PodOrders for contract addresses.
* @dev Listings are not migrated from contracts (as no bean is
* locked, and that the listed plot may have been already filled),
* and will need to be recreated.
*/
function issuePodOrders(
address owner,
L1PodOrder[] memory orders,
bytes32[] calldata proof
) external nonReentrant {
MigrationData storage account = s.sys.l2Migration.account[owner];
address reciever = LibTractor._user();
require(
account.reciever != address(0) && account.reciever == reciever,
"L2Migration: Invalid Reciever"
);
require(!account.migratedPodOrders, "L2Migration: Orders have been migrated");

// verify order validity:
require(verifyOrderProof(owner, orders, proof), "L2Migration: Invalid Order");

// add migrated orders to account.
addPodOrders(reciever, orders);

// set migrated order to true.
account.migratedPodOrders = true;

emit L1OrdersMigrated(owner, reciever, orders);
}

//////////// MERKLE PROOF VERIFICATION ////////////

/**
Expand Down Expand Up @@ -362,6 +404,17 @@ contract L1RecieverFacet is ReentrancyGuard {
return MerkleProof.verify(proof, FERTILIZER_MERKLE_ROOT, leaf);
}

function verifyOrderProof(
address owner,
L1PodOrder[] memory orders,
bytes32[] calldata proof
) public pure returns (bool) {
bytes32 leaf = keccak256(
bytes.concat(keccak256(abi.encode(owner, keccak256(abi.encode(owner, orders)))))
);
return MerkleProof.verify(proof, PODLISTING_ORDER_MERKLE_ROOT, leaf);
}

//////////// MIGRATION HELPERS ////////////

/**
Expand Down Expand Up @@ -392,14 +445,15 @@ contract L1RecieverFacet is ReentrancyGuard {
}

/**
* @notice adds the migrated deposits to the account.
* @notice adds the migrated plots to the account.
* @dev active field is hardcoded here to conform with L1 field id.
*/
function addMigratedPlotsToAccount(
address reciever,
uint256[] calldata index,
uint256[] calldata pods
) internal {
uint256 activeField = s.sys.activeField;
uint256 activeField = 0;
Field storage field = s.accts[reciever].fields[activeField];
for (uint i; i < index.length; i++) {
field.plots[index[i]] = pods[i];
Expand All @@ -410,14 +464,19 @@ contract L1RecieverFacet is ReentrancyGuard {

/**
* @notice adds the migrated internal balances to the account.
* Since global internal balances set in ReseedGlobal also reflect smart contract balances,
* we do not need to update global internal balances here,
* only balances for the individual account.
*/
function addMigratedInternalBalancesToAccount(
address reciever,
address[] calldata tokens,
uint256[] calldata amounts
) internal {
for (uint i; i < tokens.length; i++) {
LibBalance.increaseInternalBalance(reciever, IERC20(tokens[i]), amounts[i]);
IERC20 token = IERC20(tokens[i]);
s.accts[reciever].internalTokenBalance[token] += amounts[i];
emit LibBalance.InternalBalanceChanged(reciever, token, SafeCast.toInt256(amounts[i]));
}
}

Expand All @@ -440,6 +499,35 @@ contract L1RecieverFacet is ReentrancyGuard {
}
}

/**
* @notice adds the migrated pod orders to the account.
* @dev `orderer` is updated to the reciever.
*/
function addPodOrders(address reciever, L1PodOrder[] memory orders) internal {
for (uint i; i < orders.length; i++) {
// change orders[i].podOrder.orderer to the reciever.
orders[i].podOrder.orderer = reciever;

// calculate new order id from new receiver, and set mapping.
bytes32 id = _getOrderId(orders[i].podOrder);
s.sys.podOrders[id] = orders[i].beanAmount;

emit Order.PodOrderCreated(
orders[i].podOrder.orderer,
id,
orders[i].beanAmount,
orders[i].podOrder.fieldId,
orders[i].podOrder.pricePerPod,
orders[i].podOrder.maxPlaceInLine,
orders[i].podOrder.minFillAmount
);

// note: s.sys.orderLockedBeans is not updated, unlike in `_createPodOrder`,
// as the reseed has already included these beans in orderLockedBeans.
// (see {ReseedGlobal.setSilo()})
}
}

function getReciever(address owner) external view returns (address) {
return s.sys.l2Migration.account[owner].reciever;
}
Expand Down Expand Up @@ -483,4 +571,20 @@ contract L1RecieverFacet is ReentrancyGuard {
l2Address = address(uint160(l1Address) + OFFSET);
}
}

/*
* @notice internal orderId
*/
function _getOrderId(Order.PodOrder memory podOrder) internal pure returns (bytes32 id) {
return
keccak256(
abi.encodePacked(
podOrder.orderer,
podOrder.fieldId,
podOrder.pricePerPod,
podOrder.maxPlaceInLine,
podOrder.minFillAmount
)
);
}
}
4 changes: 2 additions & 2 deletions protocol/contracts/beanstalk/migration/L2MigrationFacet.sol
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ contract L2MigrationFacet is ReentrancyGuard {
L2Beanstalk,
0,
maxSubmissionCost,
msg.sender,
reciever, // excessFeeRefundAddress
msg.sender,
maxGas,
gasPriceBid,
Expand Down Expand Up @@ -114,7 +114,7 @@ contract L2MigrationFacet is ReentrancyGuard {
L2Beanstalk,
0,
maxSubmissionCost,
msg.sender,
receiver, // excessFeeRefundAddress
msg.sender,
maxGas,
gasPriceBid,
Expand Down
3 changes: 1 addition & 2 deletions protocol/contracts/beanstalk/storage/System.sol
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ struct System {
uint256 reentrantStatus;
uint256 farmingStatus;
address ownerCandidate;
uint256 plenty;
uint128 soil;
uint128 beanSown;
uint256 activeField;
Expand All @@ -61,7 +60,6 @@ struct System {
mapping(address => bytes) wellOracleSnapshots;
mapping(address => TwaReserves) twaReserves;
mapping(address => uint256) usdTokenPrice;
mapping(uint32 => uint256) sops;
mapping(uint256 => Field) fields;
mapping(uint256 => ConvertCapacity) convertCapacity;
mapping(address => Implementation) oracleImplementation;
Expand Down Expand Up @@ -410,6 +408,7 @@ struct MigrationData {
bool migratedPlots;
bool migratedFert;
bool migratedInternalBalances;
bool migratedPodOrders;
}

/**
Expand Down
2 changes: 1 addition & 1 deletion protocol/contracts/libraries/LibDibbler.sol
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ library LibDibbler {
return TEMPERATURE_PRECISION;
} else {
// delta == 1
return _scaleTemperature(279415312704);
return _scaleTemperature(76079978576);
}
} else {
if (delta == 2) {
Expand Down
2 changes: 1 addition & 1 deletion protocol/contracts/libraries/LibGauge.sol
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ library LibGauge {

// 24 * 30 * 6
// uint256 internal constant TARGET_SEASONS_TO_CATCHUP = 4320; //state
uint256 internal constant STALK_BDV_PRECISION = 1e4;
uint256 internal constant STALK_BDV_PRECISION = 1e10;

/**
* @notice Emitted when the AverageGrownStalkPerBdvPerSeason Updates.
Expand Down
Loading

0 comments on commit 551d1db

Please sign in to comment.