From 4605d5918f6a06c5ed0ed4e0b46b3959408df953 Mon Sep 17 00:00:00 2001 From: pizzaman1337 Date: Fri, 30 Aug 2024 09:20:06 -0600 Subject: [PATCH 01/36] WIP genDiamondCut --- protocol/scripts/genDiamondCut.js | 93 +++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 protocol/scripts/genDiamondCut.js diff --git a/protocol/scripts/genDiamondCut.js b/protocol/scripts/genDiamondCut.js new file mode 100644 index 000000000..61f96c119 --- /dev/null +++ b/protocol/scripts/genDiamondCut.js @@ -0,0 +1,93 @@ +const ethers = require("ethers"); + +async function generateDiamondCut(existingFacets, newFacets) { + const cuts = []; + + // Helper function to convert selector strings to bytes4 + const selectorToBytes4 = (selector) => { + return selector.slice(0, 10); // Assuming selectors are already in '0x' format + }; + + // Process existing facets + const existingSelectors = new Set(); + existingFacets.forEach(facet => { + facet.selectors.forEach(selector => { + existingSelectors.add(selectorToBytes4(selector)); + }); + }); + + // Process new facets + for (const newFacet of newFacets) { + const facetCut = { + facetAddress: newFacet.facetAddress, + action: 0, // 0 for Add, 1 for Replace, 2 for Remove + functionSelectors: [] + }; + + newFacet.selectors.forEach(selector => { + const bytes4Selector = selectorToBytes4(selector); + if (existingSelectors.has(bytes4Selector)) { + facetCut.action = 1; // Replace + } else { + facetCut.action = 0; // Add + } + facetCut.functionSelectors.push(bytes4Selector); + existingSelectors.delete(bytes4Selector); + }); + + if (facetCut.functionSelectors.length > 0) { + cuts.push(facetCut); + } + } + + // Handle removed selectors + if (existingSelectors.size > 0) { + cuts.push({ + facetAddress: '0x0000000000000000000000000000000000000000', + action: 2, // Remove + functionSelectors: Array.from(existingSelectors) + }); + } + + return cuts; +} + +async function processDiamondCut(existingFacets, newFacets) { + try { + const diamondCut = await generateDiamondCut(existingFacets, newFacets); + const encoded = ethers.utils.defaultAbiCoder.encode( + ["tuple(address facetAddress, uint8 action, bytes4[] functionSelectors)[]"], + [diamondCut] + ); + process.stdout.write(encoded); + } catch (error) { + console.error(error); + process.exit(1); + } +} + +// Example usage +const existingFacets = [ + { + facetAddress: '0x1111111111111111111111111111111111111111', + selectors: ['0x12345678', '0x23456789'] + } +]; + +const newFacets = [ + { + facetAddress: '0x2222222222222222222222222222222222222222', + selectors: ['0x12345678', '0x34567890'] + }, + { + facetAddress: '0x3333333333333333333333333333333333333333', + selectors: ['0x45678901', '0x56789012'] + } +]; + +processDiamondCut(existingFacets, newFacets) + .then(() => process.exit(0)) + .catch((error) => { + console.error(error); + process.exit(1); + }); \ No newline at end of file From 5ee1d551afd36ff325569b9a07dc6d755a808905 Mon Sep 17 00:00:00 2001 From: pizzaman1337 Date: Sun, 1 Sep 2024 07:59:23 -0600 Subject: [PATCH 02/36] Data passed between JS<>sol too large --- protocol/scripts/genDiamondCut.js | 74 ++--- protocol/test/foundry/silo/Oracle.t.sol | 8 + .../test/foundry/utils/BeanstalkDeployer.sol | 253 ++++++++++++++++-- 3 files changed, 282 insertions(+), 53 deletions(-) diff --git a/protocol/scripts/genDiamondCut.js b/protocol/scripts/genDiamondCut.js index 61f96c119..9482f01c9 100644 --- a/protocol/scripts/genDiamondCut.js +++ b/protocol/scripts/genDiamondCut.js @@ -2,6 +2,8 @@ const ethers = require("ethers"); async function generateDiamondCut(existingFacets, newFacets) { const cuts = []; + + // console.log("Generating diamond cut..."); // Helper function to convert selector strings to bytes4 const selectorToBytes4 = (selector) => { @@ -9,51 +11,69 @@ async function generateDiamondCut(existingFacets, newFacets) { }; // Process existing facets - const existingSelectors = new Set(); + const existingSelectors = new Map(); existingFacets.forEach(facet => { facet.selectors.forEach(selector => { - existingSelectors.add(selectorToBytes4(selector)); + existingSelectors.set(selectorToBytes4(selector), facet.facetAddress); }); }); + // console.log(`Found ${existingSelectors.size} existing selectors`); + // console.log("existing selectors: ", Array.from(existingSelectors.keys())); + // Process new facets for (const newFacet of newFacets) { - const facetCut = { - facetAddress: newFacet.facetAddress, - action: 0, // 0 for Add, 1 for Replace, 2 for Remove - functionSelectors: [] - }; + const addSelectors = []; + const replaceSelectors = []; newFacet.selectors.forEach(selector => { const bytes4Selector = selectorToBytes4(selector); if (existingSelectors.has(bytes4Selector)) { - facetCut.action = 1; // Replace + replaceSelectors.push(bytes4Selector); } else { - facetCut.action = 0; // Add + addSelectors.push(bytes4Selector); } - facetCut.functionSelectors.push(bytes4Selector); existingSelectors.delete(bytes4Selector); }); - if (facetCut.functionSelectors.length > 0) { - cuts.push(facetCut); + if (addSelectors.length > 0) { + cuts.push({ + facetAddress: newFacet.facetAddress, + action: 0, // Add + functionSelectors: addSelectors + }); + } + + if (replaceSelectors.length > 0) { + cuts.push({ + facetAddress: newFacet.facetAddress, + action: 1, // Replace + functionSelectors: replaceSelectors + }); } } + // console.log(`Found ${existingSelectors.size} removed selectors`); + // Handle removed selectors if (existingSelectors.size > 0) { cuts.push({ facetAddress: '0x0000000000000000000000000000000000000000', action: 2, // Remove - functionSelectors: Array.from(existingSelectors) + functionSelectors: Array.from(existingSelectors.keys()) }); } + // console.log(`Generated ${cuts.length} cuts`); + // console.log("final cuts: ", cuts); + return cuts; } -async function processDiamondCut(existingFacets, newFacets) { +async function processDiamondCut(existingFacetsJson, newFacetsJson) { try { + const existingFacets = JSON.parse(existingFacetsJson); + const newFacets = JSON.parse(newFacetsJson); const diamondCut = await generateDiamondCut(existingFacets, newFacets); const encoded = ethers.utils.defaultAbiCoder.encode( ["tuple(address facetAddress, uint8 action, bytes4[] functionSelectors)[]"], @@ -66,26 +86,14 @@ async function processDiamondCut(existingFacets, newFacets) { } } -// Example usage -const existingFacets = [ - { - facetAddress: '0x1111111111111111111111111111111111111111', - selectors: ['0x12345678', '0x23456789'] - } -]; - -const newFacets = [ - { - facetAddress: '0x2222222222222222222222222222222222222222', - selectors: ['0x12345678', '0x34567890'] - }, - { - facetAddress: '0x3333333333333333333333333333333333333333', - selectors: ['0x45678901', '0x56789012'] - } -]; +// Get command line arguments +const args = process.argv.slice(2); +if (args.length !== 2) { + console.error("Usage: node genDiamondCut.js "); + process.exit(1); +} -processDiamondCut(existingFacets, newFacets) +processDiamondCut(args[0], args[1]) .then(() => process.exit(0)) .catch((error) => { console.error(error); diff --git a/protocol/test/foundry/silo/Oracle.t.sol b/protocol/test/foundry/silo/Oracle.t.sol index e6250e350..666c3de3c 100644 --- a/protocol/test/foundry/silo/Oracle.t.sol +++ b/protocol/test/foundry/silo/Oracle.t.sol @@ -8,6 +8,7 @@ import {MockChainlinkAggregator} from "contracts/mocks/chainlink/MockChainlinkAg import {MockToken} from "contracts/mocks/MockToken.sol"; import {LSDChainlinkOracle} from "contracts/ecosystem/oracles/LSDChainlinkOracle.sol"; import {LibChainlinkOracle} from "contracts/libraries/Oracle/LibChainlinkOracle.sol"; +import "forge-std/console.sol"; /** * @notice Tests the functionality of the Oracles. @@ -260,6 +261,13 @@ contract OracleTest is TestHelper { assertEq(priceWBTC, 0.00002e8); // adjusted to 8 decimals } + function testForkMainnetWBTCOracle() public { + // fork mainnet and upgrade all facets + forkMainnetAndUpgradeAllFacets(); + + console.log("WBTC Price: ", OracleFacet(BEANSTALK).getUsdTokenPrice(WBTC)); + } + function setupUniswapWBTCOracleImplementation() public { vm.prank(BEANSTALK); bs.updateOracleImplementationForToken( diff --git a/protocol/test/foundry/utils/BeanstalkDeployer.sol b/protocol/test/foundry/utils/BeanstalkDeployer.sol index 3f3c3d7bf..f9ed49222 100644 --- a/protocol/test/foundry/utils/BeanstalkDeployer.sol +++ b/protocol/test/foundry/utils/BeanstalkDeployer.sol @@ -21,6 +21,11 @@ import {MockSeasonFacet, SeasonFacet} from "contracts/mocks/mockFacets/MockSeaso import {MockSiloFacet, SiloFacet} from "contracts/mocks/mockFacets/MockSiloFacet.sol"; import {MockPipelineConvertFacet, PipelineConvertFacet} from "contracts/mocks/mockFacets/MockPipelineConvertFacet.sol"; import {SeasonGettersFacet} from "contracts/beanstalk/sun/SeasonFacet/SeasonGettersFacet.sol"; +import {DiamondCutFacet} from "contracts/beanstalk/diamond/DiamondCutFacet.sol"; +import {IDiamondLoupe} from "contracts/interfaces/IDiamondLoupe.sol"; + +import {IMockFBeanstalk} from "contracts/interfaces/IMockFBeanstalk.sol"; +import "forge-std/console.sol"; /** * @title TestHelper @@ -61,6 +66,7 @@ contract BeanstalkDeployer is Utils { "PipelineConvertFacet" // MockPipelineConvertFacet ]; address[] facetAddresses; + string[] facetNames; IDiamondCut.FacetCutAction[] cutActions; @@ -75,7 +81,31 @@ contract BeanstalkDeployer is Utils { vm.label(BEANSTALK, "Beanstalk"); // Create cuts. + setupFacetAddresses(mock); + + IDiamondCut.FacetCut[] memory cut = _multiCut(facets, facetAddresses, cutActions); + d = deployDiamondAtAddress(deployer, BEANSTALK); + + // if mocking, set the diamond address to + // the canonical beanstalk address. + address initDiamondAddress; + if (mock) { + initDiamondAddress = address(new MockInitDiamond()); + } else { + initDiamondAddress = address(new InitDiamond()); + } + vm.prank(deployer); + IDiamondCut(address(d)).diamondCut( + cut, + initDiamondAddress, + abi.encodeWithSignature("init()") + ); + + if (verbose) console.log("Diamond deployed at: ", address(d)); + } + + function setupFacetAddresses(bool mock) internal { // Facets that require external libraries need to be deployed by // `address(new Facet())` // otherwise, use deployCode() to speed up test compiles. @@ -86,10 +116,12 @@ contract BeanstalkDeployer is Utils { if (keccak256(abi.encode(facetName)) == keccak256(abi.encode("SeasonGettersFacet"))) { facetAddresses.push(address(new SeasonGettersFacet())); } else { + console.log("deployCode facet: ", facetName); facetAddresses.push(address(deployCode(facetName))); } cutActions.push(IDiamondCut.FacetCutAction.Add); + facetNames.push(facetName); } // Deploy mock only facets. @@ -97,6 +129,7 @@ contract BeanstalkDeployer is Utils { facetAddresses.push(address(new MockAttackFacet())); facets.push("MockAttackFacet"); cutActions.push(IDiamondCut.FacetCutAction.Add); + facetNames.push("MockAttackFacet"); } for (uint i; i < mockFacets.length; i++) { @@ -148,27 +181,8 @@ contract BeanstalkDeployer is Utils { facets.push(facet); cutActions.push(IDiamondCut.FacetCutAction.Add); + facetNames.push(facet); } - IDiamondCut.FacetCut[] memory cut = _multiCut(facets, facetAddresses, cutActions); - d = deployDiamondAtAddress(deployer, BEANSTALK); - - // if mocking, set the diamond address to - // the canonical beanstalk address. - address initDiamondAddress; - if (mock) { - initDiamondAddress = address(new MockInitDiamond()); - } else { - initDiamondAddress = address(new InitDiamond()); - } - - vm.prank(deployer); - IDiamondCut(address(d)).diamondCut( - cut, - initDiamondAddress, - abi.encodeWithSignature("init()") - ); - - if (verbose) console.log("Diamond deployed at: ", address(d)); } /** @@ -210,6 +224,105 @@ contract BeanstalkDeployer is Utils { vm.stopPrank(); } + // useful for debugging which facets are erroring by adding logs to LibDiamond and deploying after forking + function upgradeDiamondFacet() internal { + string[] memory _facetNames = new string[](1); + _facetNames[0] = "DiamondCutFacet"; + address[] memory newFacetAddresses = new address[](1); + newFacetAddresses[0] = address(new DiamondCutFacet()); + + IDiamondCut.FacetCutAction[] memory facetCutActions = new IDiamondCut.FacetCutAction[](1); + facetCutActions[0] = IDiamondCut.FacetCutAction.Replace; + + // upgrade just the diamond cut facet + upgradeWithNewFacets( + BEANSTALK, // upgrading beanstalk. + IMockFBeanstalk(BEANSTALK).owner(), // fetch beanstalk owner. + _facetNames, + newFacetAddresses, + facetCutActions, + address(new EmptyInitContract()), // deploy the ReseedL2Migration. + abi.encodeWithSignature("init()"), // call init. + new bytes4[](0) + ); + console.log("done upgrading diamond cut facet"); + } + + /** + * @notice Forks mainnet at a given block, + */ + function forkMainnetAndUpgradeAllFacets() internal { + vm.createSelectFork(vm.envString("FORKING_RPC"), 20641000); + + setupFacetAddresses(true); + + upgradeDiamondFacet(); + + // the idea is to add/upgrade all the facets/mock facets that are in the constants at the top of this file + // get the list of all current selectors + IDiamondLoupe.Facet[] memory currentFacets = IDiamondLoupe(BEANSTALK).facets(); + bytes4[] memory currentSelectors = new bytes4[](1000); + uint256 selectorsCounter = 0; + for (uint256 i = 0; i < currentFacets.length; i++) { + // loop through all selectors in the facet + bytes4[] memory selectors = IDiamondLoupe(BEANSTALK).facetFunctionSelectors( + currentFacets[i].facetAddress + ); + for (uint256 j = 0; j < selectors.length; j++) { + // add the selector to the currentSelectors array + currentSelectors[selectorsCounter++] = selectors[j]; + } + } + assembly { + mstore(currentSelectors, selectorsCounter) + } + // generated list of all the new selectors + + IDiamondLoupe.Facet[] memory newFacets = new IDiamondLoupe.Facet[](facetAddresses.length); + + // was goigng to originally make one large diamond cut, but kept getting EvmError: MemoryOOG + // so instead, we make multiple diamond cuts, one for each facet + uint256 facetAddressesLength = facetAddresses.length; + + bytes4[][] memory functionSelectorsArray = _generateMultiSelectors(facetNames); + for (uint256 i = 0; i < facetNames.length; i++) { + IDiamondLoupe.Facet memory facet = IDiamondLoupe.Facet( + facetAddresses[i], + functionSelectorsArray[i] + ); + newFacets[i] = facet; + } + + assembly { + mstore(newFacets, facetAddressesLength) + } + + // generate new Facets + + IDiamondCut.FacetCut[] memory cut = generateDiamondCut(currentFacets, newFacets); + + // log all cuts + for (uint256 i = 0; i < cut.length; i++) { + console.log("cut: ", cut[i].facetAddress); + if (cut[i].action == IDiamondCut.FacetCutAction.Add) { + console.log("action: Add"); + } else if (cut[i].action == IDiamondCut.FacetCutAction.Replace) { + console.log("action: Replace"); + } else if (cut[i].action == IDiamondCut.FacetCutAction.Remove) { + console.log("action: Remove"); + } + // loop through and log cut[i].functionSelectors + for (uint256 j = 0; j < cut[i].functionSelectors.length; j++) { + console.log("selector: "); + console.logBytes4(cut[i].functionSelectors[j]); + } + } + + vm.startPrank(IMockFBeanstalk(BEANSTALK).owner()); + IDiamondCut(BEANSTALK).diamondCut(cut, address(0), new bytes(0)); + vm.stopPrank(); + } + //////////////////////// Deploy ///////////////////////// /** @@ -292,6 +405,106 @@ contract BeanstalkDeployer is Utils { cmd[i + 2] = _facetNames[i]; } bytes memory res = vm.ffi(cmd); + console.log("got command back"); + // log bytes length + console.log("res length: ", res.length); selectorsArray = abi.decode(res, (bytes4[][])); + console.log("decoded"); } + + function generateDiamondCut( + IDiamondLoupe.Facet[] memory _existingFacets, + IDiamondLoupe.Facet[] memory _newFacets + ) internal returns (IDiamondCut.FacetCut[] memory) { + // Encode the existing facets + string memory existingFacetsJson = _encodeFacetsToJson(_existingFacets); + + // Encode the new facets + string memory newFacetsJson = _encodeFacetsToJson(_newFacets); + + // Prepare the command to run the Node.js script + string[] memory cmd = new string[](4); + cmd[0] = "node"; + cmd[1] = "scripts/genDiamondCut.js"; + cmd[2] = existingFacetsJson; + cmd[3] = newFacetsJson; + + // Run the script and get the result + bytes memory res = vm.ffi(cmd); + console.log("Diamond cut generated"); + + // Decode the result + IDiamondCut.FacetCut[] memory diamondCut = abi.decode(res, (IDiamondCut.FacetCut[])); + console.log("Diamond cut decoded"); + + return diamondCut; + } + + function _encodeFacetsToJson( + IDiamondLoupe.Facet[] memory _facets + ) internal pure returns (string memory) { + string memory json = "["; + for (uint i = 0; i < _facets.length; i++) { + if (i > 0) json = string(abi.encodePacked(json, ",")); + json = string( + abi.encodePacked( + json, + '{"facetAddress":"', + _addressToString(_facets[i].facetAddress), + '","selectors":[' + ) + ); + for (uint j = 0; j < _facets[i].functionSelectors.length; j++) { + if (j > 0) json = string(abi.encodePacked(json, ",")); + json = string( + abi.encodePacked( + json, + '"', + _bytes4ToString(_facets[i].functionSelectors[j]), + '"' + ) + ); + } + json = string(abi.encodePacked(json, "]}")); + } + json = string(abi.encodePacked(json, "]")); + return json; + } + + function _addressToString(address _addr) internal pure returns (string memory) { + bytes memory s = new bytes(42); + s[0] = "0"; + s[1] = "x"; + for (uint i = 0; i < 20; i++) { + bytes1 b = bytes1(uint8(uint(uint160(_addr)) / (2 ** (8 * (19 - i))))); + bytes1 hi = bytes1(uint8(b) / 16); + bytes1 lo = bytes1(uint8(b) - 16 * uint8(hi)); + s[2 + 2 * i] = _char(hi); + s[2 + 2 * i + 1] = _char(lo); + } + return string(s); + } + + function _bytes4ToString(bytes4 _bytes) internal pure returns (string memory) { + bytes memory s = new bytes(10); + s[0] = "0"; + s[1] = "x"; + for (uint i = 0; i < 4; i++) { + bytes1 b = _bytes[i]; + bytes1 hi = bytes1(uint8(b) / 16); + bytes1 lo = bytes1(uint8(b) - 16 * uint8(hi)); + s[2 + 2 * i] = _char(hi); + s[2 + 2 * i + 1] = _char(lo); + } + return string(s); + } + + function _char(bytes1 b) internal pure returns (bytes1 c) { + if (uint8(b) < 10) return bytes1(uint8(b) + 0x30); + else return bytes1(uint8(b) + 0x57); + } +} + +contract EmptyInitContract { + function init() external {} } From 3d876e00bd2045f8100eab8d8714be8fa52a38a1 Mon Sep 17 00:00:00 2001 From: pizzaman1337 Date: Mon, 2 Sep 2024 17:44:55 -0600 Subject: [PATCH 03/36] Initial working version of mainnet fork testing --- protocol/scripts/genDiamondCut.js | 17 +- protocol/scripts/genSelectors.js | 98 +++- protocol/test/foundry/silo/Oracle.t.sol | 11 +- .../test/foundry/utils/BeanstalkDeployer.sol | 458 +++++++++++++----- 4 files changed, 429 insertions(+), 155 deletions(-) diff --git a/protocol/scripts/genDiamondCut.js b/protocol/scripts/genDiamondCut.js index 9482f01c9..62265b0e8 100644 --- a/protocol/scripts/genDiamondCut.js +++ b/protocol/scripts/genDiamondCut.js @@ -75,10 +75,19 @@ async function processDiamondCut(existingFacetsJson, newFacetsJson) { const existingFacets = JSON.parse(existingFacetsJson); const newFacets = JSON.parse(newFacetsJson); const diamondCut = await generateDiamondCut(existingFacets, newFacets); - const encoded = ethers.utils.defaultAbiCoder.encode( - ["tuple(address facetAddress, uint8 action, bytes4[] functionSelectors)[]"], - [diamondCut] - ); + + // Compact encoding + let encoded = ethers.utils.hexlify(ethers.utils.pack(['uint256'], [diamondCut.length])); + + for (const cut of diamondCut) { + encoded += ethers.utils.hexlify(cut.facetAddress).slice(2); + encoded += ethers.utils.hexZeroPad(ethers.utils.hexlify(cut.action), 1).slice(2); + encoded += ethers.utils.hexZeroPad(ethers.utils.hexlify(cut.functionSelectors.length), 2).slice(2); + for (const selector of cut.functionSelectors) { + encoded += selector.slice(2); + } + } + process.stdout.write(encoded); } catch (error) { console.error(error); diff --git a/protocol/scripts/genSelectors.js b/protocol/scripts/genSelectors.js index 2caf11d99..1c492817e 100644 --- a/protocol/scripts/genSelectors.js +++ b/protocol/scripts/genSelectors.js @@ -1,31 +1,91 @@ const ethers = require("ethers"); const path = require("path/posix"); +const fs = require("fs"); const args = process.argv.slice(2); -async function printSelectors(contractName, artifactFolderPath = "../out") { - const contractFilePath = path.join(artifactFolderPath,`${contractName}.sol`,`${contractName}.json`); - const contractArtifact = require(contractFilePath); +function log(message) { + // turn logging on or off by commenting out this following line + // fs.appendFileSync('genSelectors.log', message + '\n'); +} + +async function printSelectors(contractName, artifactFolderPath = "out") { + try { + const contractFilePath = path.join( + process.cwd(), + artifactFolderPath, + `${contractName}.sol`, + `${contractName}.json` + ); + log(`Looking for contract at: ${contractFilePath}`); + + if (!fs.existsSync(contractFilePath)) { + log(`Contract file not found: ${contractFilePath}`); + return []; + } + + const contractArtifact = JSON.parse(fs.readFileSync(contractFilePath, "utf8")); + log(`Contract artifact loaded for ${contractName}`); + + if (!contractArtifact.methodIdentifiers) { + log(`No method identifiers found for ${contractName}`); + return []; + } + + const selectors = Object.values(contractArtifact.methodIdentifiers); + log(`Found ${selectors.length} selectors for ${contractName}`); - // Use map to prepend '0x' to each element, return selectors. - return Object.values(contractArtifact.methodIdentifiers).map(element => '0x' + element); + return selectors; + } catch (error) { + log(`Error in printSelectors for ${contractName}: ${error.message}`); + return []; + } } -async function processContracts(contractNames, defaultArtifactFolderPath = "../out") { - const promises = contractNames.map(contractName => - printSelectors(contractName, defaultArtifactFolderPath) - ); +async function processContracts(contractNames, defaultArtifactFolderPath = "./out/") { + try { + log(`Current working directory: ${process.cwd()}`); + + log(`Processing contracts: ${contractNames.join(", ")}`); + + const promises = contractNames.map((contractName) => + printSelectors(contractName, defaultArtifactFolderPath) + ); + + const results = await Promise.all(promises); + log(`All selectors retrieved. Number of contracts processed: ${results.length}`); + + // Compact encoding + let encoded = ethers.utils.hexZeroPad(ethers.BigNumber.from(results.length).toHexString(), 32); + log(`Encoded number of contracts: ${encoded}`); + + for (const selectors of results) { + encoded += ethers.utils + .hexZeroPad(ethers.BigNumber.from(selectors.length).toHexString(), 2) + .slice(2); + log(`Encoded number of selectors for a contract: ${encoded.slice(-4)}`); + for (const selector of selectors) { + encoded += selector; + log(`Encoded selector: ${selector}`); + } + } - // Wait for all printSelectors calls to complete - const results = await Promise.all(promises); - const coded = ethers.utils.defaultAbiCoder.encode(["bytes4[][]"], [results]); - process.stdout.write(coded) + log(`Final encoded data: ${encoded}`); + return encoded; + } catch (error) { + log(`Error in processContracts: ${error.message}`); + return "0x"; + } } -// We recommend this pattern to be able to use async/await everywhere processContracts(args) -.then(() => process.exit(0)) -.catch((error) => { - console.error(error); - process.exit(1); -}); \ No newline at end of file + .then((encoded) => { + log(`Writing to stdout: ${encoded}`); + process.stdout.write(encoded); + process.exit(0); + }) + .catch((error) => { + log(`Fatal error: ${error.message}`); + console.error(error); + process.exit(1); + }); diff --git a/protocol/test/foundry/silo/Oracle.t.sol b/protocol/test/foundry/silo/Oracle.t.sol index 666c3de3c..d213308ea 100644 --- a/protocol/test/foundry/silo/Oracle.t.sol +++ b/protocol/test/foundry/silo/Oracle.t.sol @@ -8,7 +8,6 @@ import {MockChainlinkAggregator} from "contracts/mocks/chainlink/MockChainlinkAg import {MockToken} from "contracts/mocks/MockToken.sol"; import {LSDChainlinkOracle} from "contracts/ecosystem/oracles/LSDChainlinkOracle.sol"; import {LibChainlinkOracle} from "contracts/libraries/Oracle/LibChainlinkOracle.sol"; -import "forge-std/console.sol"; /** * @notice Tests the functionality of the Oracles. @@ -262,10 +261,12 @@ contract OracleTest is TestHelper { } function testForkMainnetWBTCOracle() public { - // fork mainnet and upgrade all facets - forkMainnetAndUpgradeAllFacets(); + forkMainnetAndUpgradeAllFacets(20641000); - console.log("WBTC Price: ", OracleFacet(BEANSTALK).getUsdTokenPrice(WBTC)); + setupUniswapWBTCOracleImplementation(); + + uint256 priceWBTC = OracleFacet(BEANSTALK).getUsdTokenPrice(WBTC); + assertEq(priceWBTC, 16); // adjusted to 8 decimals. This is clearly not enough precision for WBTC and needs to be increased. } function setupUniswapWBTCOracleImplementation() public { @@ -276,7 +277,7 @@ contract OracleTest is TestHelper { WBTC_USDC_03_POOL, bytes4(0), bytes1(0x02), - abi.encode(LibChainlinkOracle.FOUR_HOUR_TIMEOUT) + abi.encode(LibChainlinkOracle.FOUR_DAY_TIMEOUT) ) ); diff --git a/protocol/test/foundry/utils/BeanstalkDeployer.sol b/protocol/test/foundry/utils/BeanstalkDeployer.sol index f9ed49222..5811b2daf 100644 --- a/protocol/test/foundry/utils/BeanstalkDeployer.sol +++ b/protocol/test/foundry/utils/BeanstalkDeployer.sol @@ -20,6 +20,9 @@ import {MockConvertFacet, ConvertFacet} from "contracts/mocks/mockFacets/MockCon import {MockSeasonFacet, SeasonFacet} from "contracts/mocks/mockFacets/MockSeasonFacet.sol"; import {MockSiloFacet, SiloFacet} from "contracts/mocks/mockFacets/MockSiloFacet.sol"; import {MockPipelineConvertFacet, PipelineConvertFacet} from "contracts/mocks/mockFacets/MockPipelineConvertFacet.sol"; +import {MockFertilizerFacet, FertilizerFacet} from "contracts/mocks/mockFacets/MockFertilizerFacet.sol"; +import {MockWhitelistFacet, WhitelistFacet} from "contracts/mocks/mockFacets/MockWhitelistFacet.sol"; +import {MockFieldFacet, FieldFacet} from "contracts/mocks/mockFacets/MockFieldFacet.sol"; import {SeasonGettersFacet} from "contracts/beanstalk/sun/SeasonFacet/SeasonGettersFacet.sol"; import {DiamondCutFacet} from "contracts/beanstalk/diamond/DiamondCutFacet.sol"; import {IDiamondLoupe} from "contracts/interfaces/IDiamondLoupe.sol"; @@ -65,8 +68,10 @@ contract BeanstalkDeployer is Utils { "SeasonFacet", // MockSeasonFacet "PipelineConvertFacet" // MockPipelineConvertFacet ]; - address[] facetAddresses; - string[] facetNames; + address[] initialDeployFacetAddresses; + string[] initialDeploFacetNames; + address[] upgradeFacetAddresses; + string[] upgradeFacetNames; IDiamondCut.FacetCutAction[] cutActions; @@ -81,9 +86,13 @@ contract BeanstalkDeployer is Utils { vm.label(BEANSTALK, "Beanstalk"); // Create cuts. - setupFacetAddresses(mock); + setupFacetAddresses(mock, true, false); - IDiamondCut.FacetCut[] memory cut = _multiCut(facets, facetAddresses, cutActions); + IDiamondCut.FacetCut[] memory cut = _multiCut( + initialDeploFacetNames, + initialDeployFacetAddresses, + cutActions + ); d = deployDiamondAtAddress(deployer, BEANSTALK); // if mocking, set the diamond address to @@ -105,7 +114,12 @@ contract BeanstalkDeployer is Utils { if (verbose) console.log("Diamond deployed at: ", address(d)); } - function setupFacetAddresses(bool mock) internal { + function setupFacetAddresses(bool mock, bool attack, bool includeUpgradeFacetsOnly) internal { + address[] memory facetAddresses = new address[](100); + string[] memory facetNames = new string[](100); + + uint256 facetCounter; + // Facets that require external libraries need to be deployed by // `address(new Facet())` // otherwise, use deployCode() to speed up test compiles. @@ -113,23 +127,38 @@ contract BeanstalkDeployer is Utils { // for facets with external libraries, deploy the facet, // rather than deploying using the bytecode. string memory facetName = facets[i]; + + if ( + includeUpgradeFacetsOnly && + (keccak256(abi.encodePacked(facetName)) == + keccak256(abi.encodePacked("OwnershipFacet")) || + keccak256(abi.encodePacked(facetName)) == + keccak256(abi.encodePacked("PauseFacet")) || + keccak256(abi.encodePacked(facetName)) == + keccak256(abi.encodePacked("DiamondCutFacet")) || + keccak256(abi.encodePacked(facetName)) == + keccak256(abi.encodePacked("DiamondCutFacet"))) + ) { + continue; + } + if (keccak256(abi.encode(facetName)) == keccak256(abi.encode("SeasonGettersFacet"))) { - facetAddresses.push(address(new SeasonGettersFacet())); + facetAddresses[facetCounter++] = address(new SeasonGettersFacet()); } else { - console.log("deployCode facet: ", facetName); - facetAddresses.push(address(deployCode(facetName))); + facetAddresses[facetCounter++] = address(deployCode(facetName)); } cutActions.push(IDiamondCut.FacetCutAction.Add); - facetNames.push(facetName); + // facetNames.push(facetName); + facetNames[facetCounter - 1] = facetName; } // Deploy mock only facets. - if (mock) { - facetAddresses.push(address(new MockAttackFacet())); - facets.push("MockAttackFacet"); + if (mock && attack) { + // facetAddresses.push(address(new MockAttackFacet())); + facetAddresses[facetCounter++] = address(new MockAttackFacet()); cutActions.push(IDiamondCut.FacetCutAction.Add); - facetNames.push("MockAttackFacet"); + facetNames[facetCounter - 1] = "MockAttackFacet"; } for (uint i; i < mockFacets.length; i++) { @@ -159,6 +188,24 @@ contract BeanstalkDeployer is Utils { } else { facetAddress = address(new SeasonFacet()); } + } else if (hashedName == keccak256(abi.encode("FertilizerFacet"))) { + if (mock) { + facetAddress = address(new MockFertilizerFacet()); + } else { + facetAddress = address(new FertilizerFacet()); + } + } else if (hashedName == keccak256(abi.encode("WhitelistFacet"))) { + if (mock) { + facetAddress = address(new MockWhitelistFacet()); + } else { + facetAddress = address(new WhitelistFacet()); + } + } else if (hashedName == keccak256(abi.encode("FieldFacet"))) { + if (mock) { + facetAddress = address(new MockFieldFacet()); + } else { + facetAddress = address(new FieldFacet()); + } } else if (hashedName == keccak256(abi.encode("SiloFacet"))) { if (mock) { facetAddress = address(new MockSiloFacet()); @@ -175,13 +222,24 @@ contract BeanstalkDeployer is Utils { facetAddress = address(deployCode(facet)); } - facetAddresses.push(facetAddress); - - // append the facet name to the facets array. - facets.push(facet); + facetAddresses[facetCounter++] = facetAddress; cutActions.push(IDiamondCut.FacetCutAction.Add); - facetNames.push(facet); + facetNames[facetCounter - 1] = facet; + } + + // update array lengths + assembly { + mstore(facetAddresses, facetCounter) + mstore(facetNames, facetCounter) + } + + if (includeUpgradeFacetsOnly) { + upgradeFacetAddresses = facetAddresses; + upgradeFacetNames = facetNames; + } else { + initialDeployFacetAddresses = facetAddresses; + initialDeploFacetNames = facetNames; } } @@ -225,7 +283,7 @@ contract BeanstalkDeployer is Utils { } // useful for debugging which facets are erroring by adding logs to LibDiamond and deploying after forking - function upgradeDiamondFacet() internal { + /*function upgradeDiamondFacet() internal { string[] memory _facetNames = new string[](1); _facetNames[0] = "DiamondCutFacet"; address[] memory newFacetAddresses = new address[](1); @@ -245,18 +303,17 @@ contract BeanstalkDeployer is Utils { abi.encodeWithSignature("init()"), // call init. new bytes4[](0) ); - console.log("done upgrading diamond cut facet"); - } + }*/ /** * @notice Forks mainnet at a given block, */ - function forkMainnetAndUpgradeAllFacets() internal { - vm.createSelectFork(vm.envString("FORKING_RPC"), 20641000); + function forkMainnetAndUpgradeAllFacets(uint256 blockNumber) internal { + vm.createSelectFork(vm.envString("FORKING_RPC"), blockNumber); - setupFacetAddresses(true); + setupFacetAddresses(true, false, true); - upgradeDiamondFacet(); + // upgradeDiamondFacet(); // the idea is to add/upgrade all the facets/mock facets that are in the constants at the top of this file // get the list of all current selectors @@ -276,18 +333,18 @@ contract BeanstalkDeployer is Utils { assembly { mstore(currentSelectors, selectorsCounter) } - // generated list of all the new selectors - IDiamondLoupe.Facet[] memory newFacets = new IDiamondLoupe.Facet[](facetAddresses.length); + // generated list of all the new facets + IDiamondLoupe.Facet[] memory newFacets = new IDiamondLoupe.Facet[]( + upgradeFacetAddresses.length + ); - // was goigng to originally make one large diamond cut, but kept getting EvmError: MemoryOOG - // so instead, we make multiple diamond cuts, one for each facet - uint256 facetAddressesLength = facetAddresses.length; + uint256 facetAddressesLength = upgradeFacetAddresses.length; - bytes4[][] memory functionSelectorsArray = _generateMultiSelectors(facetNames); - for (uint256 i = 0; i < facetNames.length; i++) { + bytes4[][] memory functionSelectorsArray = _generateMultiSelectors(upgradeFacetNames); + for (uint256 i = 0; i < upgradeFacetNames.length; i++) { IDiamondLoupe.Facet memory facet = IDiamondLoupe.Facet( - facetAddresses[i], + upgradeFacetAddresses[i], functionSelectorsArray[i] ); newFacets[i] = facet; @@ -297,28 +354,11 @@ contract BeanstalkDeployer is Utils { mstore(newFacets, facetAddressesLength) } - // generate new Facets - + // generate the diamond cut required to upgrade all facets IDiamondCut.FacetCut[] memory cut = generateDiamondCut(currentFacets, newFacets); - // log all cuts - for (uint256 i = 0; i < cut.length; i++) { - console.log("cut: ", cut[i].facetAddress); - if (cut[i].action == IDiamondCut.FacetCutAction.Add) { - console.log("action: Add"); - } else if (cut[i].action == IDiamondCut.FacetCutAction.Replace) { - console.log("action: Replace"); - } else if (cut[i].action == IDiamondCut.FacetCutAction.Remove) { - console.log("action: Remove"); - } - // loop through and log cut[i].functionSelectors - for (uint256 j = 0; j < cut[i].functionSelectors.length; j++) { - console.log("selector: "); - console.logBytes4(cut[i].functionSelectors[j]); - } - } - vm.startPrank(IMockFBeanstalk(BEANSTALK).owner()); + // perform the diamond cut (upgrades Beanstalk) IDiamondCut(BEANSTALK).diamondCut(cut, address(0), new bytes(0)); vm.stopPrank(); } @@ -404,104 +444,268 @@ contract BeanstalkDeployer is Utils { for (uint i = 0; i < _facetNames.length; i++) { cmd[i + 2] = _facetNames[i]; } + // be aware of cases where the response may be very large, which can break the EVM bytes memory res = vm.ffi(cmd); - console.log("got command back"); - // log bytes length - console.log("res length: ", res.length); - selectorsArray = abi.decode(res, (bytes4[][])); - console.log("decoded"); + + if (res.length > 0) { + selectorsArray = _decodeCompactSelectors(res); + } else { + selectorsArray = new bytes4[][](0); + } } - function generateDiamondCut( - IDiamondLoupe.Facet[] memory _existingFacets, - IDiamondLoupe.Facet[] memory _newFacets - ) internal returns (IDiamondCut.FacetCut[] memory) { - // Encode the existing facets - string memory existingFacetsJson = _encodeFacetsToJson(_existingFacets); + function _decodeCompactSelectors(bytes memory data) internal pure returns (bytes4[][] memory) { + uint256 pointer = 0; + uint256 numContracts = uint256(bytes32(slice(data, pointer, 32))); + pointer += 32; - // Encode the new facets - string memory newFacetsJson = _encodeFacetsToJson(_newFacets); + bytes4[][] memory selectorsArray = new bytes4[][](numContracts); - // Prepare the command to run the Node.js script - string[] memory cmd = new string[](4); - cmd[0] = "node"; - cmd[1] = "scripts/genDiamondCut.js"; - cmd[2] = existingFacetsJson; - cmd[3] = newFacetsJson; + for (uint256 i = 0; i < numContracts; i++) { + uint16 numSelectors = uint16(bytes2(slice(data, pointer, 2))); + pointer += 2; - // Run the script and get the result - bytes memory res = vm.ffi(cmd); - console.log("Diamond cut generated"); + bytes4[] memory selectors = new bytes4[](numSelectors); + for (uint256 j = 0; j < numSelectors; j++) { + selectors[j] = bytes4(slice(data, pointer, 4)); + pointer += 4; + } - // Decode the result - IDiamondCut.FacetCut[] memory diamondCut = abi.decode(res, (IDiamondCut.FacetCut[])); - console.log("Diamond cut decoded"); + selectorsArray[i] = selectors; + } - return diamondCut; + return selectorsArray; } - function _encodeFacetsToJson( - IDiamondLoupe.Facet[] memory _facets - ) internal pure returns (string memory) { - string memory json = "["; - for (uint i = 0; i < _facets.length; i++) { - if (i > 0) json = string(abi.encodePacked(json, ",")); - json = string( - abi.encodePacked( - json, - '{"facetAddress":"', - _addressToString(_facets[i].facetAddress), - '","selectors":[' - ) + function generateDiamondCut( + IDiamondLoupe.Facet[] memory currentFacets, + IDiamondLoupe.Facet[] memory newFacets + ) internal pure returns (IDiamondCut.FacetCut[] memory) { + // Use a dynamic array for cuts + IDiamondCut.FacetCut[] memory cuts = new IDiamondCut.FacetCut[](0); + + // Create arrays to store all selectors and their corresponding new facet addresses + bytes4[] memory allSelectors = new bytes4[](0); + address[] memory allNewFacetAddresses = new address[](0); + + // Populate the arrays with data from newFacets + for (uint256 i = 0; i < newFacets.length; i++) { + for (uint256 j = 0; j < newFacets[i].functionSelectors.length; j++) { + allSelectors = appendToBytes4Array(allSelectors, newFacets[i].functionSelectors[j]); + allNewFacetAddresses = appendToAddressArray( + allNewFacetAddresses, + newFacets[i].facetAddress + ); + } + } + + // Process removals and replacements + for (uint256 i = 0; i < currentFacets.length; i++) { + bytes4[] memory selectorsToRemove = new bytes4[]( + currentFacets[i].functionSelectors.length ); - for (uint j = 0; j < _facets[i].functionSelectors.length; j++) { - if (j > 0) json = string(abi.encodePacked(json, ",")); - json = string( - abi.encodePacked( - json, - '"', - _bytes4ToString(_facets[i].functionSelectors[j]), - '"' + bytes4[] memory selectorsToReplace = new bytes4[]( + currentFacets[i].functionSelectors.length + ); + uint256 removeCount = 0; + uint256 replaceCount = 0; + + for (uint256 j = 0; j < currentFacets[i].functionSelectors.length; j++) { + bytes4 selector = currentFacets[i].functionSelectors[j]; + (bool found, address newFacetAddress) = findNewFacetAddress( + selector, + allSelectors, + allNewFacetAddresses + ); + + if (!found) { + selectorsToRemove[removeCount] = selector; + removeCount++; + } else if (newFacetAddress != currentFacets[i].facetAddress) { + selectorsToReplace[replaceCount] = selector; + replaceCount++; + } + } + + if (removeCount > 0) { + bytes4[] memory finalSelectorsToRemove = new bytes4[](removeCount); + for (uint256 j = 0; j < removeCount; j++) { + finalSelectorsToRemove[j] = selectorsToRemove[j]; + } + cuts = appendToCuts( + cuts, + IDiamondCut.FacetCut( + address(0), + IDiamondCut.FacetCutAction.Remove, + finalSelectorsToRemove + ) + ); + } + + if (replaceCount > 0) { + bytes4[] memory finalSelectorsToReplace = new bytes4[](replaceCount); + for (uint256 j = 0; j < replaceCount; j++) { + finalSelectorsToReplace[j] = selectorsToReplace[j]; + } + (, address newFacetAddress) = findNewFacetAddress( + finalSelectorsToReplace[0], + allSelectors, + allNewFacetAddresses + ); + cuts = appendToCuts( + cuts, + IDiamondCut.FacetCut( + newFacetAddress, + IDiamondCut.FacetCutAction.Replace, + finalSelectorsToReplace ) ); } - json = string(abi.encodePacked(json, "]}")); } - json = string(abi.encodePacked(json, "]")); - return json; + + // Process additions + for (uint256 i = 0; i < newFacets.length; i++) { + bytes4[] memory selectorsToAdd = new bytes4[](newFacets[i].functionSelectors.length); + uint256 addCount = 0; + + for (uint256 j = 0; j < newFacets[i].functionSelectors.length; j++) { + bytes4 selector = newFacets[i].functionSelectors[j]; + bool isNewSelector = true; + for (uint256 k = 0; k < currentFacets.length; k++) { + if (contains(currentFacets[k].functionSelectors, selector)) { + isNewSelector = false; + break; + } + } + if (isNewSelector) { + selectorsToAdd[addCount] = selector; + addCount++; + } + } + + if (addCount > 0) { + bytes4[] memory finalSelectorsToAdd = new bytes4[](addCount); + for (uint256 j = 0; j < addCount; j++) { + finalSelectorsToAdd[j] = selectorsToAdd[j]; + } + cuts = appendToCuts( + cuts, + IDiamondCut.FacetCut( + newFacets[i].facetAddress, + IDiamondCut.FacetCutAction.Add, + finalSelectorsToAdd + ) + ); + } + } + + return cuts; + } + + function findNewFacetAddress( + bytes4 selector, + bytes4[] memory allSelectors, + address[] memory allNewFacetAddresses + ) internal pure returns (bool, address) { + for (uint256 i = 0; i < allSelectors.length; i++) { + if (allSelectors[i] == selector) { + return (true, allNewFacetAddresses[i]); + } + } + return (false, address(0)); + } + + // these append functions are not ideal in terms for gas/performance, but they are convenient for testing + function appendToBytes4Array( + bytes4[] memory array, + bytes4 element + ) internal pure returns (bytes4[] memory) { + bytes4[] memory newArray = new bytes4[](array.length + 1); + for (uint256 i = 0; i < array.length; i++) { + newArray[i] = array[i]; + } + newArray[array.length] = element; + return newArray; } - function _addressToString(address _addr) internal pure returns (string memory) { - bytes memory s = new bytes(42); - s[0] = "0"; - s[1] = "x"; - for (uint i = 0; i < 20; i++) { - bytes1 b = bytes1(uint8(uint(uint160(_addr)) / (2 ** (8 * (19 - i))))); - bytes1 hi = bytes1(uint8(b) / 16); - bytes1 lo = bytes1(uint8(b) - 16 * uint8(hi)); - s[2 + 2 * i] = _char(hi); - s[2 + 2 * i + 1] = _char(lo); + function appendToAddressArray( + address[] memory array, + address element + ) internal pure returns (address[] memory) { + address[] memory newArray = new address[](array.length + 1); + for (uint256 i = 0; i < array.length; i++) { + newArray[i] = array[i]; } - return string(s); + newArray[array.length] = element; + return newArray; } - function _bytes4ToString(bytes4 _bytes) internal pure returns (string memory) { - bytes memory s = new bytes(10); - s[0] = "0"; - s[1] = "x"; - for (uint i = 0; i < 4; i++) { - bytes1 b = _bytes[i]; - bytes1 hi = bytes1(uint8(b) / 16); - bytes1 lo = bytes1(uint8(b) - 16 * uint8(hi)); - s[2 + 2 * i] = _char(hi); - s[2 + 2 * i + 1] = _char(lo); + function appendToCuts( + IDiamondCut.FacetCut[] memory cuts, + IDiamondCut.FacetCut memory newCut + ) internal pure returns (IDiamondCut.FacetCut[] memory) { + IDiamondCut.FacetCut[] memory newCuts = new IDiamondCut.FacetCut[](cuts.length + 1); + for (uint i = 0; i < cuts.length; i++) { + newCuts[i] = cuts[i]; } - return string(s); + newCuts[cuts.length] = newCut; + return newCuts; } - function _char(bytes1 b) internal pure returns (bytes1 c) { - if (uint8(b) < 10) return bytes1(uint8(b) + 0x30); - else return bytes1(uint8(b) + 0x57); + function contains(bytes4[] memory array, bytes4 value) internal pure returns (bool) { + for (uint256 i = 0; i < array.length; i++) { + if (array[i] == value) { + return true; + } + } + return false; + } + + function _decodeDiamondCut( + bytes memory data + ) internal pure returns (IDiamondCut.FacetCut[] memory) { + uint256 pointer = 0; + uint256 numCuts = uint256(bytes32(slice(data, pointer, 32))); + pointer += 32; + + IDiamondCut.FacetCut[] memory cuts = new IDiamondCut.FacetCut[](numCuts); + + for (uint256 i = 0; i < numCuts; i++) { + address facetAddress = address(bytes20(slice(data, pointer, 20))); + pointer += 20; + + uint8 action = uint8(slice(data, pointer, 1)[0]); + pointer += 1; + + uint16 numSelectors = uint16(bytes2(slice(data, pointer, 2))); + pointer += 2; + + bytes4[] memory selectors = new bytes4[](numSelectors); + for (uint256 j = 0; j < numSelectors; j++) { + selectors[j] = bytes4(slice(data, pointer, 4)); + pointer += 4; + } + + cuts[i] = IDiamondCut.FacetCut( + facetAddress, + IDiamondCut.FacetCutAction(action), + selectors + ); + } + + return cuts; + } + + function slice( + bytes memory data, + uint256 start, + uint256 length + ) internal pure returns (bytes memory) { + bytes memory result = new bytes(length); + for (uint256 i = 0; i < length; i++) { + result[i] = data[start + i]; + } + return result; } } From 571faab912de246cfb5d6d09f07fa86dbaecad7b Mon Sep 17 00:00:00 2001 From: nickkatsios Date: Tue, 3 Sep 2024 11:01:47 +0300 Subject: [PATCH 04/36] fix: mint bean sided liquidity to the l2 bcm --- .../beanstalk/init/reseed/L2/ReseedBean.sol | 20 +++++++++++++ protocol/reseed/reseed3.js | 30 ++++++------------- 2 files changed, 29 insertions(+), 21 deletions(-) diff --git a/protocol/contracts/beanstalk/init/reseed/L2/ReseedBean.sol b/protocol/contracts/beanstalk/init/reseed/L2/ReseedBean.sol index f61ff3265..c5642d92d 100644 --- a/protocol/contracts/beanstalk/init/reseed/L2/ReseedBean.sol +++ b/protocol/contracts/beanstalk/init/reseed/L2/ReseedBean.sol @@ -122,6 +122,9 @@ contract ReseedBean { bytes32 internal constant FERTILIZER_PROXY_SALT = 0x0000000000000000000000000000000000000000000000000000000000000000; + // BCM (TODO: Replace with actual L2 address) + address internal constant L2_BCM = address(0xa9bA2C40b263843C04d344727b954A545c81D043); + /** * @notice deploys bean, unripe bean, unripe lp, and wells. * @dev mints bean assets to the beanstalk contract, @@ -132,6 +135,9 @@ contract ReseedBean { uint256 beanSupply, uint256 internalUrBeanSupply, uint256 internalUnripeLpSupply, + uint256 wethBeans, + uint256 wstEthBeans, + uint256 stableBeans, ExternalUnripeHolders[] calldata urBean, ExternalUnripeHolders[] calldata urBeanLP, address fertImplementation @@ -145,6 +151,8 @@ contract ReseedBean { deployUnripeLP(internalUnripeLpSupply, urBeanLP); // wells are deployed as ERC1967Proxies in order to allow for future upgrades. deployUpgradableWells(address(bean)); + // mint beans to the bcm according to the amounts in the l1 wells. + mintBeansToBCM(bean, wethBeans, wstEthBeans, stableBeans); } function deployFertilizerProxy(address fertImplementation) internal { @@ -162,6 +170,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), diff --git a/protocol/reseed/reseed3.js b/protocol/reseed/reseed3.js index f5be2ffd1..891d30098 100644 --- a/protocol/reseed/reseed3.js +++ b/protocol/reseed/reseed3.js @@ -28,37 +28,22 @@ async function reseed3(account, L2Beanstalk, deployBasin = true, fertilizerImple console.log("-----------------------------------"); console.log("reseed3: deploy bean tokens.\n"); [beanSupply, unripeBeanSupply, unripeLpSupply] = JSON.parse(await fs.readFileSync(INIT_SUPPLY)); - [ethInBeanEthWell, wstEthInBeanWstEthWell, stableInBeanStableWell] = JSON.parse( + [balancesBeanEthWell, balancesInBeanWstEthWell, balancesInBeanStableWell] = JSON.parse( await fs.readFileSync(INIT_WELL_BALANCES) ); [urBean, urBeanLP] = JSON.parse(await fs.readFileSync(EXTERNAL_UNRIPE)); - // mint: - let weth, wsteth, stable, owner; - let approver = account; - if (mock) { - // Deploy mock tokens - weth = await deployMockToken("WETH", "WETH"); - wsteth = await deployMockToken("wstETH", "wstETH"); - stable = await deployMockToken("USDC", "USDC"); - owner = await impersonateSigner(account.address); - approver = owner; - await weth.mint(account.address, ethInBeanEthWell[0]); - await wsteth.mint(account.address, wstEthInBeanWstEthWell[0]); - await stable.mint(account.address, stableInBeanStableWell[0]); - } else { - // TODO: Replace with actual token addresses on the L2 - weth = await ethers.getContractAt("IERC20", L2_WETH); - wsteth = await ethers.getContractAt("IERC20", L2_WEETH); - stable = await ethers.getContractAt("IERC20", L2_WBTC); - } - if (deployBasin) { [uWell, stable2] = await deployBasinV1_2Components(); console.log("uWell:", uWell.address); console.log("stable2:", stable2.address); } + // get the bean sided liquidity from the L1 wells to mint it to the bcm. + const beansInBeanEthWell = balancesBeanEthWell[0]; + const beansInBeanWstEthWell = balancesInBeanWstEthWell[0]; + const beansInBeanStableWell = balancesInBeanStableWell[0]; + // call init: await upgradeWithNewFacets({ diamondAddress: L2Beanstalk, @@ -68,6 +53,9 @@ async function reseed3(account, L2Beanstalk, deployBasin = true, fertilizerImple beanSupply, unripeBeanSupply, unripeLpSupply, + beansInBeanEthWell, + beansInBeanWstEthWell, + beansInBeanStableWell, urBean, urBeanLP, fertilizerImplementation From b1445066c8f3b5dc9a851fcc069e9d2f955c6e08 Mon Sep 17 00:00:00 2001 From: nickkatsios Date: Tue, 3 Sep 2024 11:41:53 +0300 Subject: [PATCH 05/36] fix: temp if ladder incorrect value for delta=1 --- protocol/contracts/libraries/LibDibbler.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/protocol/contracts/libraries/LibDibbler.sol b/protocol/contracts/libraries/LibDibbler.sol index 5e360f778..5da2d217c 100644 --- a/protocol/contracts/libraries/LibDibbler.sol +++ b/protocol/contracts/libraries/LibDibbler.sol @@ -249,7 +249,7 @@ library LibDibbler { return TEMPERATURE_PRECISION; } else { // delta == 1 - return _scaleTemperature(279415312704); + return _scaleTemperature(76079978576); } } else { if (delta == 2) { From a61918825a0b59cfd5212f1b053400979c3ef11b Mon Sep 17 00:00:00 2001 From: pizzaman1337 Date: Tue, 3 Sep 2024 11:40:32 -0600 Subject: [PATCH 06/36] Add another uniswap/chainlink oracle test --- .../libraries/Oracle/LibUsdOracle.sol | 15 ++++--- protocol/test/foundry/silo/Oracle.t.sol | 45 ++++++++++++++++++- .../test/foundry/utils/OracleDeployer.sol | 2 + 3 files changed, 55 insertions(+), 7 deletions(-) diff --git a/protocol/contracts/libraries/Oracle/LibUsdOracle.sol b/protocol/contracts/libraries/Oracle/LibUsdOracle.sol index 1e05a576e..07113803b 100644 --- a/protocol/contracts/libraries/Oracle/LibUsdOracle.sol +++ b/protocol/contracts/libraries/Oracle/LibUsdOracle.sol @@ -14,6 +14,7 @@ import {Implementation} from "contracts/beanstalk/storage/System.sol"; import {AppStorage} from "contracts/beanstalk/storage/AppStorage.sol"; import {LibRedundantMath256} from "contracts/libraries/LibRedundantMath256.sol"; import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; +import {IChainlinkAggregator} from "contracts/interfaces/chainlink/IChainlinkAggregator.sol"; interface IERC20Decimals { function decimals() external view returns (uint8); @@ -124,14 +125,16 @@ library LibUsdOracle { lookback ); - // if token decimals != 0, Beanstalk is attempting to query the USD/TOKEN price, and - // thus the price needs to be inverted. + // Calculate USD per token + uint256 usdPerToken = (tokenPrice * chainlinkTokenPrice) / 1e6; + if (tokenDecimals != 0) { - tokenPrice = (10 ** (6 + tokenDecimals)) / tokenPrice; - return (tokenPrice * chainlinkTokenPrice) / (10 ** tokenDecimals); + // Calculate token per USD, 1e12 because precision of chainlink/uniswap is each 1e6 + uint256 tokenPerUsd = 1e12 / usdPerToken; + return tokenPerUsd; } else { - // return the TOKEN/USD price. - return (tokenPrice * chainlinkTokenPrice) / CHAINLINK_DENOMINATOR; + // Return the TOKEN/USD price + return usdPerToken; } } diff --git a/protocol/test/foundry/silo/Oracle.t.sol b/protocol/test/foundry/silo/Oracle.t.sol index d213308ea..5466e8f16 100644 --- a/protocol/test/foundry/silo/Oracle.t.sol +++ b/protocol/test/foundry/silo/Oracle.t.sol @@ -266,7 +266,23 @@ contract OracleTest is TestHelper { setupUniswapWBTCOracleImplementation(); uint256 priceWBTC = OracleFacet(BEANSTALK).getUsdTokenPrice(WBTC); - assertEq(priceWBTC, 16); // adjusted to 8 decimals. This is clearly not enough precision for WBTC and needs to be increased. + assertEq(priceWBTC, 16); // $1 buys 1683 satoshi at BTC price of 6148186669379 per USDC and USDC 99993272, but 16 is 6 decimal precision + } + + function testForkMainnetAAVEOracle() public { + forkMainnetAndUpgradeAllFacets(20666000); + + setupUniswapAaveOracleImplementation(); + + uint256 priceAAVE = OracleFacet(BEANSTALK).getUsdTokenPrice(AAVE); + assertEq(priceAAVE, 7478); + // chainlink price: 2541090000 (2541 usd per weth at 6 decimals) + // uniswap price: 52620 (0.052620 WETH per AAVE at 6 decimals) + // these multiplied together: 133712155800000 (12 decimal precision) + // but inverse is needed, so 1e12/133712155800000 = 0.007478751607 + // and 0.007478751607 at 6 decimal precision is 7479 + + // approx expected result for $133.71 - 7478872186074340 } function setupUniswapWBTCOracleImplementation() public { @@ -293,4 +309,31 @@ contract OracleTest is TestHelper { ) ); } + + // AAVE:WETH is the highest volume non-memcoin/non-stablecoin pair on uniswap as of the time of writing + function setupUniswapAaveOracleImplementation() internal { + vm.prank(BEANSTALK); + bs.updateOracleImplementationForToken( + AAVE, + IMockFBeanstalk.Implementation( + AAVE_ETH_03_POOL, + bytes4(0), + bytes1(0x02), + abi.encode(LibChainlinkOracle.FOUR_DAY_TIMEOUT) + ) + ); + + // also uniswap relies on having a chainlink oracle for the token that's trading against the uniswap target token + // in the case of AAVE/ETH, eth is the token that needs to be looked up against chainlink + vm.prank(BEANSTALK); + bs.updateOracleImplementationForToken( + WETH, + IMockFBeanstalk.Implementation( + ETH_USD_CHAINLINK_PRICE_AGGREGATOR, // note this is using eth instead of weth + bytes4(0), + bytes1(0x01), + abi.encode(LibChainlinkOracle.FOUR_DAY_TIMEOUT) + ) + ); + } } diff --git a/protocol/test/foundry/utils/OracleDeployer.sol b/protocol/test/foundry/utils/OracleDeployer.sol index 61d2cab39..6716bae8d 100644 --- a/protocol/test/foundry/utils/OracleDeployer.sol +++ b/protocol/test/foundry/utils/OracleDeployer.sol @@ -63,7 +63,9 @@ contract OracleDeployer is Utils { ////////// UNISWAP ////////// address constant WBTC_USDC_03_POOL = address(0x99ac8cA7087fA4A2A1FB6357269965A2014ABc35); + address constant AAVE_ETH_03_POOL = address(0x5aB53EE1d50eeF2C1DD3d5402789cd27bB52c1bB); address constant WBTC = address(0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599); + address constant AAVE = address(0x7Fc66500c84A76Ad7e9c93437bFc5Ac33E2DDaE9); // new uniswap pools should be appended here. address[][] public pools = [ From 85369ac1da6a9d4977a63c895a977a2a44ff5e44 Mon Sep 17 00:00:00 2001 From: pizzaman1337 Date: Tue, 3 Sep 2024 12:09:24 -0600 Subject: [PATCH 07/36] Update LibUsdOracle to match dr-t-remediations --- .../libraries/Oracle/LibUsdOracle.sol | 40 ++++++++++--------- protocol/test/foundry/silo/Oracle.t.sol | 35 +++++++++++++++- .../test/foundry/utils/OracleDeployer.sol | 1 + 3 files changed, 56 insertions(+), 20 deletions(-) diff --git a/protocol/contracts/libraries/Oracle/LibUsdOracle.sol b/protocol/contracts/libraries/Oracle/LibUsdOracle.sol index 07113803b..53f059c50 100644 --- a/protocol/contracts/libraries/Oracle/LibUsdOracle.sol +++ b/protocol/contracts/libraries/Oracle/LibUsdOracle.sol @@ -14,7 +14,6 @@ import {Implementation} from "contracts/beanstalk/storage/System.sol"; import {AppStorage} from "contracts/beanstalk/storage/AppStorage.sol"; import {LibRedundantMath256} from "contracts/libraries/LibRedundantMath256.sol"; import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; -import {IChainlinkAggregator} from "contracts/interfaces/chainlink/IChainlinkAggregator.sol"; interface IERC20Decimals { function decimals() external view returns (uint8); @@ -29,7 +28,7 @@ interface IERC20Decimals { library LibUsdOracle { using LibRedundantMath256 for uint256; - uint256 constant CHAINLINK_DENOMINATOR = 1e6; + uint256 constant UNISWAP_DENOMINATOR = 1e6; function getUsdPrice(address token) internal view returns (uint256) { return getUsdPrice(token, 0); @@ -104,38 +103,41 @@ library LibUsdOracle { } // get twap from the `chainlinkToken` to `token` - // exchange 1 `chainlinkToken` for `token` + // exchange 1 `token` for `chainlinkToken`. tokenPrice = LibUniswapOracle.getTwap( lookback == 0 ? LibUniswapOracle.FIFTEEN_MINUTES : uint32(lookback), oracleImpl.target, token, chainlinkToken, - uint128(10 ** IERC20Decimals(token).decimals()) + tokenDecimals == 0 + ? uint128(10 ** IERC20Decimals(token).decimals()) + : uint128(10 ** tokenDecimals) ); // call chainlink oracle from the OracleImplmentation contract - Implementation memory chainlinkOracleImpl = s.sys.oracleImplementation[chainlinkToken]; - address chainlinkOraclePriceAddress = chainlinkOracleImpl.target; + Implementation memory chainlinkOracle = s.sys.oracleImplementation[chainlinkToken]; - uint32 timeout = abi.decode(oracleImpl.data, (uint32)); + // return the CL_TOKEN/USD or USD/CL_TOKEN, depending on `tokenDecimals`. + uint256 chainlinkTokenDecimals = IERC20Decimals(chainlinkToken).decimals(); uint256 chainlinkTokenPrice = LibChainlinkOracle.getTokenPrice( - chainlinkOraclePriceAddress, - timeout, - 0, + chainlinkOracle.target, + abi.decode(chainlinkOracle.data, (uint256)), // timeout + tokenDecimals == 0 ? tokenDecimals : chainlinkTokenDecimals, lookback ); - // Calculate USD per token - uint256 usdPerToken = (tokenPrice * chainlinkTokenPrice) / 1e6; - + // if token decimals != 0, Beanstalk is attempting to query the USD/TOKEN price, and + // thus the price needs to be inverted. if (tokenDecimals != 0) { - // Calculate token per USD, 1e12 because precision of chainlink/uniswap is each 1e6 - uint256 tokenPerUsd = 1e12 / usdPerToken; - return tokenPerUsd; - } else { - // Return the TOKEN/USD price - return usdPerToken; + // invert tokenPrice (to get CL_TOKEN/TOKEN). + // `tokenPrice` has 6 decimal precision (see {LibUniswapOracle.getTwap}). + tokenPrice = 1e12 / tokenPrice; + // return the USD/TOKEN price. + // 1e6 * 1e`n` / 1e`n` = 1e6 } + + // return the TOKEN/USD price. + return (tokenPrice * chainlinkTokenPrice) / UNISWAP_DENOMINATOR; } // If the oracle implementation address is not set, use the current contract. diff --git a/protocol/test/foundry/silo/Oracle.t.sol b/protocol/test/foundry/silo/Oracle.t.sol index 5466e8f16..9d1960684 100644 --- a/protocol/test/foundry/silo/Oracle.t.sol +++ b/protocol/test/foundry/silo/Oracle.t.sol @@ -281,8 +281,15 @@ contract OracleTest is TestHelper { // these multiplied together: 133712155800000 (12 decimal precision) // but inverse is needed, so 1e12/133712155800000 = 0.007478751607 // and 0.007478751607 at 6 decimal precision is 7479 + } + + function testForkMainnetWSTETHOracle() public { + forkMainnetAndUpgradeAllFacets(20666000); + + setupUniswapWstethOracleImplementation(); - // approx expected result for $133.71 - 7478872186074340 + uint256 priceWSTET = OracleFacet(BEANSTALK).getUsdTokenPrice(WSTETH); + assertEq(priceWSTET, 7478); } function setupUniswapWBTCOracleImplementation() public { @@ -336,4 +343,30 @@ contract OracleTest is TestHelper { ) ); } + + function setupUniswapWstethOracleImplementation() internal { + vm.prank(BEANSTALK); + bs.updateOracleImplementationForToken( + WSTETH, + IMockFBeanstalk.Implementation( + WSTETH_ETH_001_POOL, + bytes4(0), + bytes1(0x02), + abi.encode(LibChainlinkOracle.FOUR_DAY_TIMEOUT) + ) + ); + + // also uniswap relies on having a chainlink oracle for the token that's trading against the uniswap target token + // in the case of AAVE/ETH, eth is the token that needs to be looked up against chainlink + vm.prank(BEANSTALK); + bs.updateOracleImplementationForToken( + WETH, + IMockFBeanstalk.Implementation( + ETH_USD_CHAINLINK_PRICE_AGGREGATOR, // note this is using eth instead of weth + bytes4(0), + bytes1(0x01), + abi.encode(LibChainlinkOracle.FOUR_DAY_TIMEOUT) + ) + ); + } } diff --git a/protocol/test/foundry/utils/OracleDeployer.sol b/protocol/test/foundry/utils/OracleDeployer.sol index 6716bae8d..039879651 100644 --- a/protocol/test/foundry/utils/OracleDeployer.sol +++ b/protocol/test/foundry/utils/OracleDeployer.sol @@ -64,6 +64,7 @@ contract OracleDeployer is Utils { address constant WBTC_USDC_03_POOL = address(0x99ac8cA7087fA4A2A1FB6357269965A2014ABc35); address constant AAVE_ETH_03_POOL = address(0x5aB53EE1d50eeF2C1DD3d5402789cd27bB52c1bB); + address constant WSTETH_ETH_001_POOL = address(0x109830a1AAaD605BbF02a9dFA7B0B92EC2FB7dAa); address constant WBTC = address(0x2260FAC5E5542a773Aa44fBCfeDf7C193bc2C599); address constant AAVE = address(0x7Fc66500c84A76Ad7e9c93437bFc5Ac33E2DDaE9); From 4d5a89331832c80c6f4c62d1955d76c3419fce98 Mon Sep 17 00:00:00 2001 From: pizzaman1337 Date: Tue, 3 Sep 2024 12:12:18 -0600 Subject: [PATCH 08/36] Updates --- protocol/contracts/libraries/Oracle/LibUsdOracle.sol | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/protocol/contracts/libraries/Oracle/LibUsdOracle.sol b/protocol/contracts/libraries/Oracle/LibUsdOracle.sol index 4772385e3..42e443d52 100644 --- a/protocol/contracts/libraries/Oracle/LibUsdOracle.sol +++ b/protocol/contracts/libraries/Oracle/LibUsdOracle.sol @@ -132,13 +132,9 @@ library LibUsdOracle { // invert tokenPrice (to get CL_TOKEN/TOKEN). // `tokenPrice` has 6 decimal precision (see {LibUniswapOracle.getTwap}). tokenPrice = 1e12 / tokenPrice; - // return the USD/TOKEN price. - // 1e6 * 1e`n` / 1e`n` = 1e6 - return (tokenPrice * chainlinkTokenPrice) / (10 ** chainlinkTokenDecimals); - } else { - // return the TOKEN/USD price. - return (tokenPrice * chainlinkTokenPrice) / UNISWAP_DENOMINATOR; } + // return the TOKEN/USD price. + return (tokenPrice * chainlinkTokenPrice) / UNISWAP_DENOMINATOR; } // If the oracle implementation address is not set, use the current contract. From 35ae18a7e6fa3d34ab9e72afe6a6b11d522e88ab Mon Sep 17 00:00:00 2001 From: pizzaman1337 Date: Tue, 3 Sep 2024 13:09:28 -0600 Subject: [PATCH 09/36] Quick commit while it works --- .../contracts/libraries/Oracle/LibUsdOracle.sol | 16 ++++++++++++++-- protocol/test/foundry/silo/Oracle.t.sol | 16 ++++++++-------- 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/protocol/contracts/libraries/Oracle/LibUsdOracle.sol b/protocol/contracts/libraries/Oracle/LibUsdOracle.sol index 42e443d52..b7117771c 100644 --- a/protocol/contracts/libraries/Oracle/LibUsdOracle.sol +++ b/protocol/contracts/libraries/Oracle/LibUsdOracle.sol @@ -14,6 +14,7 @@ import {Implementation} from "contracts/beanstalk/storage/System.sol"; import {AppStorage} from "contracts/beanstalk/storage/AppStorage.sol"; import {LibRedundantMath256} from "contracts/libraries/LibRedundantMath256.sol"; import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; +import "forge-std/console.sol"; interface IERC20Decimals { function decimals() external view returns (uint8); @@ -126,14 +127,25 @@ library LibUsdOracle { lookback ); + console.log("tokenDecimals: ", tokenDecimals); + console.log("tokenPrice: ", tokenPrice); + console.log("chainlinkTokenPrice: ", chainlinkTokenPrice); + // if token decimals != 0, Beanstalk is attempting to query the USD/TOKEN price, and // thus the price needs to be inverted. if (tokenDecimals != 0) { // invert tokenPrice (to get CL_TOKEN/TOKEN). // `tokenPrice` has 6 decimal precision (see {LibUniswapOracle.getTwap}). - tokenPrice = 1e12 / tokenPrice; + + tokenPrice = (1e6 * (10 ** tokenDecimals)) / tokenPrice; + console.log("tokenPrice after inversion: ", tokenPrice); + // return the TOKEN/USD price. + uint256 finalPrice = (tokenPrice * chainlinkTokenPrice) / + (10 ** chainlinkTokenDecimals); + console.log("finalPrice: ", finalPrice); + return finalPrice; } - // return the TOKEN/USD price. + return (tokenPrice * chainlinkTokenPrice) / UNISWAP_DENOMINATOR; } diff --git a/protocol/test/foundry/silo/Oracle.t.sol b/protocol/test/foundry/silo/Oracle.t.sol index 9d1960684..56ef4f086 100644 --- a/protocol/test/foundry/silo/Oracle.t.sol +++ b/protocol/test/foundry/silo/Oracle.t.sol @@ -266,7 +266,7 @@ contract OracleTest is TestHelper { setupUniswapWBTCOracleImplementation(); uint256 priceWBTC = OracleFacet(BEANSTALK).getUsdTokenPrice(WBTC); - assertEq(priceWBTC, 16); // $1 buys 1683 satoshi at BTC price of 6148186669379 per USDC and USDC 99993272, but 16 is 6 decimal precision + assertEq(priceWBTC, 1684); // $1 buys 1683 satoshi at BTC price of 6148186669379 per USDC and USDC 99993272, but 16 is 6 decimal precision } function testForkMainnetAAVEOracle() public { @@ -275,7 +275,7 @@ contract OracleTest is TestHelper { setupUniswapAaveOracleImplementation(); uint256 priceAAVE = OracleFacet(BEANSTALK).getUsdTokenPrice(AAVE); - assertEq(priceAAVE, 7478); + assertEq(priceAAVE, 7478751606516229); // chainlink price: 2541090000 (2541 usd per weth at 6 decimals) // uniswap price: 52620 (0.052620 WETH per AAVE at 6 decimals) // these multiplied together: 133712155800000 (12 decimal precision) @@ -283,14 +283,14 @@ contract OracleTest is TestHelper { // and 0.007478751607 at 6 decimal precision is 7479 } - function testForkMainnetWSTETHOracle() public { - forkMainnetAndUpgradeAllFacets(20666000); + // function testForkMainnetWSTETHOracle() public { + // forkMainnetAndUpgradeAllFacets(20666000); - setupUniswapWstethOracleImplementation(); + // setupUniswapWstethOracleImplementation(); - uint256 priceWSTET = OracleFacet(BEANSTALK).getUsdTokenPrice(WSTETH); - assertEq(priceWSTET, 7478); - } + // uint256 priceWSTET = OracleFacet(BEANSTALK).getUsdTokenPrice(WSTETH); + // assertEq(priceWSTET, 7478); + // } function setupUniswapWBTCOracleImplementation() public { vm.prank(BEANSTALK); From cdfe4c7c95ab9735727c9d47a551a6e1d492cd8b Mon Sep 17 00:00:00 2001 From: pizzaman1337 Date: Tue, 3 Sep 2024 13:18:06 -0600 Subject: [PATCH 10/36] Cleanup --- .../contracts/libraries/Oracle/LibUsdOracle.sol | 16 ++-------------- protocol/test/foundry/silo/Oracle.t.sol | 2 +- 2 files changed, 3 insertions(+), 15 deletions(-) diff --git a/protocol/contracts/libraries/Oracle/LibUsdOracle.sol b/protocol/contracts/libraries/Oracle/LibUsdOracle.sol index b7117771c..bf53bd0e8 100644 --- a/protocol/contracts/libraries/Oracle/LibUsdOracle.sol +++ b/protocol/contracts/libraries/Oracle/LibUsdOracle.sol @@ -14,7 +14,6 @@ import {Implementation} from "contracts/beanstalk/storage/System.sol"; import {AppStorage} from "contracts/beanstalk/storage/AppStorage.sol"; import {LibRedundantMath256} from "contracts/libraries/LibRedundantMath256.sol"; import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; -import "forge-std/console.sol"; interface IERC20Decimals { function decimals() external view returns (uint8); @@ -127,23 +126,12 @@ library LibUsdOracle { lookback ); - console.log("tokenDecimals: ", tokenDecimals); - console.log("tokenPrice: ", tokenPrice); - console.log("chainlinkTokenPrice: ", chainlinkTokenPrice); - // if token decimals != 0, Beanstalk is attempting to query the USD/TOKEN price, and // thus the price needs to be inverted. if (tokenDecimals != 0) { - // invert tokenPrice (to get CL_TOKEN/TOKEN). - // `tokenPrice` has 6 decimal precision (see {LibUniswapOracle.getTwap}). - + // invert tokenPrice, taking tokenDecimals into account. tokenPrice = (1e6 * (10 ** tokenDecimals)) / tokenPrice; - console.log("tokenPrice after inversion: ", tokenPrice); - // return the TOKEN/USD price. - uint256 finalPrice = (tokenPrice * chainlinkTokenPrice) / - (10 ** chainlinkTokenDecimals); - console.log("finalPrice: ", finalPrice); - return finalPrice; + return (tokenPrice * chainlinkTokenPrice) / (10 ** chainlinkTokenDecimals); } return (tokenPrice * chainlinkTokenPrice) / UNISWAP_DENOMINATOR; diff --git a/protocol/test/foundry/silo/Oracle.t.sol b/protocol/test/foundry/silo/Oracle.t.sol index 56ef4f086..0a051f7d4 100644 --- a/protocol/test/foundry/silo/Oracle.t.sol +++ b/protocol/test/foundry/silo/Oracle.t.sol @@ -63,7 +63,7 @@ contract OracleTest is TestHelper { WBTC, 0 ); - assertEq(usdTokenPriceFromExternal, 0.00002e6, "usdTokenPriceFromExternal"); + assertEq(usdTokenPriceFromExternal, 0.00002e8, "usdTokenPriceFromExternal"); // e8 because wbtc has 8 decimals } /** From 1f999183d33918e83a260cf8bcddc1e7297f8d3d Mon Sep 17 00:00:00 2001 From: pizzaman1337 Date: Tue, 3 Sep 2024 13:21:57 -0600 Subject: [PATCH 11/36] WSTETH test --- protocol/test/foundry/silo/Oracle.t.sol | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/protocol/test/foundry/silo/Oracle.t.sol b/protocol/test/foundry/silo/Oracle.t.sol index 0a051f7d4..96d61b9a8 100644 --- a/protocol/test/foundry/silo/Oracle.t.sol +++ b/protocol/test/foundry/silo/Oracle.t.sol @@ -283,14 +283,14 @@ contract OracleTest is TestHelper { // and 0.007478751607 at 6 decimal precision is 7479 } - // function testForkMainnetWSTETHOracle() public { - // forkMainnetAndUpgradeAllFacets(20666000); + function testForkMainnetWSTETHOracle() public { + forkMainnetAndUpgradeAllFacets(20666000); - // setupUniswapWstethOracleImplementation(); + setupUniswapWstethOracleImplementation(); - // uint256 priceWSTET = OracleFacet(BEANSTALK).getUsdTokenPrice(WSTETH); - // assertEq(priceWSTET, 7478); - // } + uint256 priceWSTETH = OracleFacet(BEANSTALK).getUsdTokenPrice(WSTETH); + assertEq(priceWSTETH, 334243752683826); + } function setupUniswapWBTCOracleImplementation() public { vm.prank(BEANSTALK); From 1b6fbd5c098e35ddbd7b8f2821834dbf145fc8d9 Mon Sep 17 00:00:00 2001 From: pizzaman1337 Date: Tue, 3 Sep 2024 20:55:08 -0600 Subject: [PATCH 12/36] Fix LibWhitelist.verifyOracleImplementation() is inconsistent with LibUsdOracle.sol --- .../contracts/libraries/Silo/LibWhitelist.sol | 3 +++ protocol/test/foundry/silo/Oracle.t.sol | 16 ++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/protocol/contracts/libraries/Silo/LibWhitelist.sol b/protocol/contracts/libraries/Silo/LibWhitelist.sol index cd12a51a7..f1475b0f6 100644 --- a/protocol/contracts/libraries/Silo/LibWhitelist.sol +++ b/protocol/contracts/libraries/Silo/LibWhitelist.sol @@ -347,6 +347,9 @@ library LibWhitelist { abi.encodeWithSelector(0x0dfe1681) ); } else { + if (oracleImplementation.target == address(0)) + oracleImplementation.target = address(this); + // verify you passed in a callable oracle selector (success, returnData) = oracleImplementation.target.call( abi.encodeWithSelector( diff --git a/protocol/test/foundry/silo/Oracle.t.sol b/protocol/test/foundry/silo/Oracle.t.sol index e6250e350..9805ef54c 100644 --- a/protocol/test/foundry/silo/Oracle.t.sol +++ b/protocol/test/foundry/silo/Oracle.t.sol @@ -8,6 +8,7 @@ import {MockChainlinkAggregator} from "contracts/mocks/chainlink/MockChainlinkAg import {MockToken} from "contracts/mocks/MockToken.sol"; import {LSDChainlinkOracle} from "contracts/ecosystem/oracles/LSDChainlinkOracle.sol"; import {LibChainlinkOracle} from "contracts/libraries/Oracle/LibChainlinkOracle.sol"; +import {IMockFBeanstalk} from "contracts/interfaces/IMockFBeanstalk.sol"; /** * @notice Tests the functionality of the Oracles. @@ -208,6 +209,21 @@ contract OracleTest is TestHelper { assertEq(oracleImplementation.target, WBTC_USD_CHAINLINK_PRICE_AGGREGATOR); } + function testZeroAddressOracleImplementationTarget() public { + vm.prank(BEANSTALK); + // exersizes address 0 and bytes 0x00, although there's no current way to whitelist something with these values. + vm.expectRevert("Whitelist: Invalid Oracle Implementation"); + bs.updateOracleImplementationForToken( + WBTC, + IMockFBeanstalk.Implementation( + address(0), + IMockFBeanstalk.getUsdTokenPriceFromExternal.selector, + bytes1(0x00), + abi.encode(LibChainlinkOracle.FOUR_HOUR_TIMEOUT) + ) + ); + } + function testGetTokenPrice() public { // change encode type to 0x02 for wbtc: vm.prank(BEANSTALK); From d29e0a8bc8d00c7d6e79843e24c2aa0d33f61693 Mon Sep 17 00:00:00 2001 From: nickkatsios Date: Wed, 4 Sep 2024 13:17:11 +0300 Subject: [PATCH 13/36] update active field in l1 receiver facet --- protocol/contracts/beanstalk/migration/L1RecieverFacet.sol | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/protocol/contracts/beanstalk/migration/L1RecieverFacet.sol b/protocol/contracts/beanstalk/migration/L1RecieverFacet.sol index 2efaee60c..ac21569b2 100644 --- a/protocol/contracts/beanstalk/migration/L1RecieverFacet.sol +++ b/protocol/contracts/beanstalk/migration/L1RecieverFacet.sol @@ -392,14 +392,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 confirm 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]; From 0900903b1480c0f6c426b21f8d0a7ee23a4e63d8 Mon Sep 17 00:00:00 2001 From: nickkatsios Date: Wed, 4 Sep 2024 13:19:04 +0300 Subject: [PATCH 14/36] typo fix --- protocol/contracts/beanstalk/migration/L1RecieverFacet.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/protocol/contracts/beanstalk/migration/L1RecieverFacet.sol b/protocol/contracts/beanstalk/migration/L1RecieverFacet.sol index ac21569b2..7f8e3d93f 100644 --- a/protocol/contracts/beanstalk/migration/L1RecieverFacet.sol +++ b/protocol/contracts/beanstalk/migration/L1RecieverFacet.sol @@ -393,7 +393,7 @@ contract L1RecieverFacet is ReentrancyGuard { /** * @notice adds the migrated plots to the account. - * @dev active field is hardcoded here to confirm with L1 field id. + * @dev active field is hardcoded here to conform with L1 field id. */ function addMigratedPlotsToAccount( address reciever, From a58d1cc60ede39c434155d2082d48892f1707fb0 Mon Sep 17 00:00:00 2001 From: pizzaman1337 Date: Wed, 4 Sep 2024 10:41:56 -0600 Subject: [PATCH 15/36] Remove unused storage vars --- protocol/contracts/beanstalk/storage/System.sol | 2 -- 1 file changed, 2 deletions(-) diff --git a/protocol/contracts/beanstalk/storage/System.sol b/protocol/contracts/beanstalk/storage/System.sol index 4bd18c879..6220bc01f 100644 --- a/protocol/contracts/beanstalk/storage/System.sol +++ b/protocol/contracts/beanstalk/storage/System.sol @@ -48,7 +48,6 @@ struct System { uint256 reentrantStatus; uint256 farmingStatus; address ownerCandidate; - uint256 plenty; uint128 soil; uint128 beanSown; uint256 activeField; @@ -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; From b02a9c383e404e6657b489d98d3358219a182153 Mon Sep 17 00:00:00 2001 From: Brean0 Date: Wed, 4 Sep 2024 20:24:33 +0200 Subject: [PATCH 16/36] add podOrder migration --- .../beanstalk/migration/L1RecieverFacet.sol | 79 ++++++++++++++++++- .../contracts/beanstalk/storage/System.sol | 1 + 2 files changed, 78 insertions(+), 2 deletions(-) diff --git a/protocol/contracts/beanstalk/migration/L1RecieverFacet.sol b/protocol/contracts/beanstalk/migration/L1RecieverFacet.sol index 2efaee60c..5ede0a3a2 100644 --- a/protocol/contracts/beanstalk/migration/L1RecieverFacet.sol +++ b/protocol/contracts/beanstalk/migration/L1RecieverFacet.sol @@ -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"; @@ -20,6 +19,8 @@ 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"; /** * @author Brean @@ -29,7 +30,7 @@ import {IFertilizer} from "contracts/interfaces/IFertilizer.sol"; * in order to migrate their deposits, plots, fertilizer, and internal balances to L2. **/ -contract L1RecieverFacet is ReentrancyGuard { +contract L1RecieverFacet is ReentrancyGuard, Order { // todo: update with correct external beans once L1 Beanstalk has been paused. uint256 constant EXTERNAL_L1_BEANS = 1000000e6; @@ -45,9 +46,16 @@ contract L1RecieverFacet is ReentrancyGuard { 0xf93c255615938ba5f00fac3b427da6dfa313b4d75eff216bbec62dbea2e629a2; bytes32 internal constant FERTILIZER_MERKLE_ROOT = 0x02ec4c26c5d970fef9bc46f5fc160788669d465da31e9edd37aded2b1c95b6c2; + bytes32 internal constant PODLISTING_ORDER_MERKLE_ROOT = + 0x02ec4c26c5d970fef9bc46f5fc160788669d465da31e9edd37aded2b1c95b6c2; uint160 internal constant OFFSET = uint160(0x1111000000000000000000000000000000001111); + struct L1PodOrder { + Order.PodOrder podOrder; + uint256 beanAmount; + } + /** * @notice emitted when L1 Beans are migrated to L2. */ @@ -95,6 +103,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. */ @@ -288,6 +298,35 @@ 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, and will need to be recreated. + */ + function issueOrdersAndListings( + 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.migratedPodOrdersAndListings, "L2Migration: Orders have been migrated"); + + // verify order validity: + require(verifyOrderProof(owner, orders, proof), "L2Migration: Invalid Listing And Order"); + + // add migrated orders to account. + addPodOrders(reciever, orders); + + // set migrated order to true. + account.migratedPodOrdersAndListings = true; + + emit L1OrdersMigrated(owner, reciever, orders); + } + //////////// MERKLE PROOF VERIFICATION //////////// /** @@ -362,6 +401,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, FERTILIZER_MERKLE_ROOT, leaf); + } + //////////// MIGRATION HELPERS //////////// /** @@ -440,6 +490,31 @@ contract L1RecieverFacet is ReentrancyGuard { } } + 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 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; } diff --git a/protocol/contracts/beanstalk/storage/System.sol b/protocol/contracts/beanstalk/storage/System.sol index 4bd18c879..ef61c57a9 100644 --- a/protocol/contracts/beanstalk/storage/System.sol +++ b/protocol/contracts/beanstalk/storage/System.sol @@ -410,6 +410,7 @@ struct MigrationData { bool migratedPlots; bool migratedFert; bool migratedInternalBalances; + bool migratedPodOrdersAndListings; } /** From d7167d2b9ab04e0636d38b5e2c1e93e0ba963288 Mon Sep 17 00:00:00 2001 From: pizzaman1337 Date: Wed, 4 Sep 2024 15:14:47 -0600 Subject: [PATCH 17/36] Add measure gas used hardhat task to evaluate L2 deployment cost --- protocol/hardhat.config.js | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/protocol/hardhat.config.js b/protocol/hardhat.config.js index 56feee005..0e005e29e 100644 --- a/protocol/hardhat.config.js +++ b/protocol/hardhat.config.js @@ -123,6 +123,34 @@ task("reseedL2", async () => { }); }); +// example usage: +// npx hardhat measureGasUsed --start 244125439 --end 244125766 --network localhost +// currently reseed uses 3381686192 gas on Arbitrum +task("measureGasUsed") + .addParam("start", "The start block to measure gas used from") + .addParam("end", "The end block to measure gas used to") + .setAction(async (args, hre) => { + const provider = hre.ethers.provider; + // Convert string inputs to numbers + const startBlock = parseInt(args.start, 10); + const endBlock = parseInt(args.end, 10); + if (isNaN(startBlock) || isNaN(endBlock)) { + throw new Error("Invalid block numbers provided. Please ensure they are valid integers."); + } + + let totalGasUsed = hre.ethers.BigNumber.from(0); + + // Iterate through all blocks and sum up the gas used + for (let i = startBlock; i <= endBlock; i++) { + const block = await provider.getBlock(i); + totalGasUsed = totalGasUsed.add(block.gasUsed); + } + + console.log( + `Total gas used between blocks ${startBlock} and ${endBlock}: ${totalGasUsed.toString()}` + ); + }); + task("diamondABI", "Generates ABI file for diamond, includes all ABIs of facets", async () => { // The path (relative to the root of `protocol` directory) where all modules sit. const modulesDir = path.join("contracts", "beanstalk"); From caff3571fbb4a7dd7360d4076eda7367bbc62e63 Mon Sep 17 00:00:00 2001 From: nickkatsios Date: Thu, 5 Sep 2024 15:54:19 +0300 Subject: [PATCH 18/36] remove libethusdoracle --- .../beanstalk/barn/FertilizerFacet.sol | 2 +- .../libraries/Oracle/LibEthUsdOracle.sol | 77 ------------------- .../libraries/Oracle/LibUsdOracle.sol | 1 - .../mocks/mockFacets/MockSeasonFacet.sol | 1 - .../test/hardhat/ChainlinkTwapOracle.test.js | 7 -- 5 files changed, 1 insertion(+), 87 deletions(-) delete mode 100644 protocol/contracts/libraries/Oracle/LibEthUsdOracle.sol diff --git a/protocol/contracts/beanstalk/barn/FertilizerFacet.sol b/protocol/contracts/beanstalk/barn/FertilizerFacet.sol index d236ab008..643b73a6c 100644 --- a/protocol/contracts/beanstalk/barn/FertilizerFacet.sol +++ b/protocol/contracts/beanstalk/barn/FertilizerFacet.sol @@ -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 diff --git a/protocol/contracts/libraries/Oracle/LibEthUsdOracle.sol b/protocol/contracts/libraries/Oracle/LibEthUsdOracle.sol deleted file mode 100644 index a8ad63fec..000000000 --- a/protocol/contracts/libraries/Oracle/LibEthUsdOracle.sol +++ /dev/null @@ -1,77 +0,0 @@ -/** - * SPDX-License-Identifier: MIT - **/ - -pragma solidity ^0.8.20; - -import {LibChainlinkOracle} from "./LibChainlinkOracle.sol"; -import {LibRedundantMath256} from "contracts/libraries/LibRedundantMath256.sol"; -import {LibAppStorage, AppStorage} from "contracts/libraries/LibAppStorage.sol"; -import {C} from "contracts/C.sol"; -import {LibOracleHelpers} from "contracts/libraries/Oracle/LibOracleHelpers.sol"; - -/** - * @title Eth Usd Oracle Library - * @notice Contains functionalty to fetch a manipulation resistant ETH/USD or USD/ETH price. - * @dev - * The Oracle uses the ETH/USD or USD/ETH Chainlink Oracle to fetch the price. - * The oracle will fail (return 0) if the Chainlink Oracle is broken or frozen (See: {LibChainlinkOracle}). - **/ -library LibEthUsdOracle { - using LibRedundantMath256 for uint256; - - address constant ETH_USD_CHAINLINK_PRICE_AGGREGATOR = - 0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419; - - uint256 constant ETH_DECIMALS = 18; - - /** - * @dev Returns the instantaneous USD/ETH price - * Return value has 18 decimal precision. - * Returns 0 if the USD/ETH Chainlink Oracle is broken or frozen. - **/ - function getUsdEthPrice() internal view returns (uint256) { - return getUsdEthPrice(0); - } - - /** - * @dev Returns the USD/ETH price with the option of using a TWA lookback. - * Use `lookback = 0` for the instantaneous price. `lookback > 0` for a TWAP. - * Return value has 18 decimal precision. - * Returns 0 if the USD/ETH Chainlink Oracle is broken or frozen. - **/ - function getUsdEthPrice(uint256 lookback) internal view returns (uint256) { - return - LibChainlinkOracle.getTokenPrice( - ETH_USD_CHAINLINK_PRICE_AGGREGATOR, - LibChainlinkOracle.FOUR_HOUR_TIMEOUT, - ETH_DECIMALS, - lookback - ); - } - - /** - * @dev Returns the instantaneous ETH/USD price - * Return value has 6 decimal precision. - * Returns 0 if the ETH/USD Chainlink Oracle is broken or frozen. - **/ - function getEthUsdPrice() internal view returns (uint256) { - return getEthUsdPrice(0); - } - - /** - * @dev Returns the ETH/USD price with the option of using a TWA lookback. - * Use `lookback = 0` for the instantaneous price. `lookback > 0` for a TWAP. - * Return value has 6 decimal precision. - * Returns 0 if the ETH/USD Chainlink Oracle is broken or frozen. - **/ - function getEthUsdPrice(uint256 lookback) internal view returns (uint256) { - return - LibChainlinkOracle.getTokenPrice( - ETH_USD_CHAINLINK_PRICE_AGGREGATOR, - LibChainlinkOracle.FOUR_HOUR_TIMEOUT, - 0, - lookback - ); - } -} diff --git a/protocol/contracts/libraries/Oracle/LibUsdOracle.sol b/protocol/contracts/libraries/Oracle/LibUsdOracle.sol index 4772385e3..7ee8075fb 100644 --- a/protocol/contracts/libraries/Oracle/LibUsdOracle.sol +++ b/protocol/contracts/libraries/Oracle/LibUsdOracle.sol @@ -5,7 +5,6 @@ pragma solidity ^0.8.20; import {C} from "contracts/C.sol"; -import {LibEthUsdOracle} from "./LibEthUsdOracle.sol"; import {LibUniswapOracle} from "./LibUniswapOracle.sol"; import {LibChainlinkOracle} from "./LibChainlinkOracle.sol"; import {IUniswapV3PoolImmutables} from "@uniswap/v3-core/contracts/interfaces/IUniswapV3Pool.sol"; diff --git a/protocol/contracts/mocks/mockFacets/MockSeasonFacet.sol b/protocol/contracts/mocks/mockFacets/MockSeasonFacet.sol index 882c152cf..71ea37558 100644 --- a/protocol/contracts/mocks/mockFacets/MockSeasonFacet.sol +++ b/protocol/contracts/mocks/mockFacets/MockSeasonFacet.sol @@ -11,7 +11,6 @@ import {IERC1155} from "@openzeppelin/contracts/token/ERC1155/IERC1155.sol"; import "../MockToken.sol"; import "contracts/libraries/LibBytes.sol"; import {LibChainlinkOracle} from "contracts/libraries/Oracle/LibChainlinkOracle.sol"; -import {LibEthUsdOracle} from "contracts/libraries/Oracle/LibEthUsdOracle.sol"; import {LibUsdOracle} from "contracts/libraries/Oracle/LibUsdOracle.sol"; import {LibAppStorage} from "contracts/libraries/LibAppStorage.sol"; import {LibRedundantMathSigned256} from "contracts/libraries/LibRedundantMathSigned256.sol"; diff --git a/protocol/test/hardhat/ChainlinkTwapOracle.test.js b/protocol/test/hardhat/ChainlinkTwapOracle.test.js index 31015bcd6..faaf33e6e 100644 --- a/protocol/test/hardhat/ChainlinkTwapOracle.test.js +++ b/protocol/test/hardhat/ChainlinkTwapOracle.test.js @@ -17,13 +17,6 @@ async function setToSecondsAfterHour(seconds = 0) { await network.provider.send("evm_setNextBlockTimestamp", [hourTimestamp]); } -async function checkPriceWithError(price, error = "1000000") { - expect(await mockBeanstalk.getEthUsdPrice()).to.be.within( - to6(price).sub(toBN(error).div("2")), - to6(price).add(toBN(error).div("2")) - ); // Expected Rounding error -} - describe("TWAP Chainlink Oracle", function () { before(async function () { [owner, user, user2] = await ethers.getSigners(); From ac157968a1d5d1b3baf0b328500ff6e81c6dcca2 Mon Sep 17 00:00:00 2001 From: pizzaman1337 Date: Thu, 5 Sep 2024 11:22:43 -0600 Subject: [PATCH 19/36] Disallow zero address oracle implementations --- .../libraries/Oracle/LibUsdOracle.sol | 7 +++-- .../contracts/libraries/Silo/LibWhitelist.sol | 4 +-- protocol/test/foundry/silo/Oracle.t.sol | 2 +- protocol/test/foundry/silo/Whitelist.t.sol | 27 ++++++++++++++++--- 4 files changed, 30 insertions(+), 10 deletions(-) diff --git a/protocol/contracts/libraries/Oracle/LibUsdOracle.sol b/protocol/contracts/libraries/Oracle/LibUsdOracle.sol index 4772385e3..05c2f5899 100644 --- a/protocol/contracts/libraries/Oracle/LibUsdOracle.sol +++ b/protocol/contracts/libraries/Oracle/LibUsdOracle.sol @@ -141,11 +141,10 @@ library LibUsdOracle { } } - // If the oracle implementation address is not set, use the current contract. - address target = oracleImpl.target; - if (target == address(0)) target = address(this); + // Non-zero addresses are enforced in verifyOracleImplementation, this is just an extra check. + if (oracleImpl.target == address(0)) return 0; - (bool success, bytes memory data) = target.staticcall( + (bool success, bytes memory data) = oracleImpl.target.staticcall( abi.encodeWithSelector(oracleImpl.selector, tokenDecimals, lookback, oracleImpl.data) ); diff --git a/protocol/contracts/libraries/Silo/LibWhitelist.sol b/protocol/contracts/libraries/Silo/LibWhitelist.sol index f1475b0f6..5d81f9d3c 100644 --- a/protocol/contracts/libraries/Silo/LibWhitelist.sol +++ b/protocol/contracts/libraries/Silo/LibWhitelist.sol @@ -347,8 +347,8 @@ library LibWhitelist { abi.encodeWithSelector(0x0dfe1681) ); } else { - if (oracleImplementation.target == address(0)) - oracleImplementation.target = address(this); + // external oracles must have a target address + require(oracleImplementation.target != address(0), "Whitelist: Invalid Target Address"); // verify you passed in a callable oracle selector (success, returnData) = oracleImplementation.target.call( diff --git a/protocol/test/foundry/silo/Oracle.t.sol b/protocol/test/foundry/silo/Oracle.t.sol index 9805ef54c..7a0c33293 100644 --- a/protocol/test/foundry/silo/Oracle.t.sol +++ b/protocol/test/foundry/silo/Oracle.t.sol @@ -212,7 +212,7 @@ contract OracleTest is TestHelper { function testZeroAddressOracleImplementationTarget() public { vm.prank(BEANSTALK); // exersizes address 0 and bytes 0x00, although there's no current way to whitelist something with these values. - vm.expectRevert("Whitelist: Invalid Oracle Implementation"); + vm.expectRevert("Whitelist: Invalid Target Address"); bs.updateOracleImplementationForToken( WBTC, IMockFBeanstalk.Implementation( diff --git a/protocol/test/foundry/silo/Whitelist.t.sol b/protocol/test/foundry/silo/Whitelist.t.sol index 89aaf177c..4cb4e5642 100644 --- a/protocol/test/foundry/silo/Whitelist.t.sol +++ b/protocol/test/foundry/silo/Whitelist.t.sol @@ -148,6 +148,27 @@ contract WhitelistTest is TestHelper { bytes4 oSelector = bytes4(keccak256(abi.encode(i))); vm.expectRevert("Whitelist: Invalid Oracle Implementation"); + bs.whitelistToken( + token, + IMockFBeanstalk.wellBdv.selector, + 0, + 0, + bytes1(0x01), + 0, + 0, + IMockFBeanstalk.Implementation(BEANSTALK, oSelector, bytes1(0), new bytes(0)), + IMockFBeanstalk.Implementation(BEANSTALK, gpSelector, bytes1(0), new bytes(0)), + IMockFBeanstalk.Implementation(BEANSTALK, lwSelector, bytes1(0), new bytes(0)) + ); + } + + function test_whitelistRevertZeroTargetOracleImplementation(uint i) public prank(BEANSTALK) { + address token = address(new MockWellToken()); + bytes4 gpSelector = IMockFBeanstalk.defaultGaugePointFunction.selector; + bytes4 lwSelector = IMockFBeanstalk.maxWeight.selector; + bytes4 oSelector = bytes4(keccak256(abi.encode(i))); + + vm.expectRevert("Whitelist: Invalid Target Address"); bs.whitelistToken( token, IMockFBeanstalk.wellBdv.selector, @@ -175,9 +196,9 @@ contract WhitelistTest is TestHelper { bytes1(0), 0, 0, - IMockFBeanstalk.Implementation(address(0), bytes4(0), bytes1(0x01), new bytes(0)), - IMockFBeanstalk.Implementation(address(0), gpSelector, bytes1(0), new bytes(0)), - IMockFBeanstalk.Implementation(address(0), lwSelector, bytes1(0), new bytes(0)) + IMockFBeanstalk.Implementation(BEANSTALK, bytes4(0), bytes1(0x01), new bytes(0)), + IMockFBeanstalk.Implementation(BEANSTALK, gpSelector, bytes1(0x01), new bytes(0)), + IMockFBeanstalk.Implementation(BEANSTALK, lwSelector, bytes1(0x01), new bytes(0)) ); } From ab27f6aa65b872188f47459745de09e90d13e0ff Mon Sep 17 00:00:00 2001 From: nickkatsios Date: Fri, 6 Sep 2024 12:21:37 +0300 Subject: [PATCH 20/36] set excessFeeRefundAddress to l2 receiver --- protocol/contracts/beanstalk/migration/L2MigrationFacet.sol | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/protocol/contracts/beanstalk/migration/L2MigrationFacet.sol b/protocol/contracts/beanstalk/migration/L2MigrationFacet.sol index ba711afbd..9e927391d 100644 --- a/protocol/contracts/beanstalk/migration/L2MigrationFacet.sol +++ b/protocol/contracts/beanstalk/migration/L2MigrationFacet.sol @@ -77,7 +77,7 @@ contract L2MigrationFacet is ReentrancyGuard { L2Beanstalk, 0, maxSubmissionCost, - msg.sender, + reciever, // excessFeeRefundAddress msg.sender, maxGas, gasPriceBid, @@ -114,8 +114,8 @@ contract L2MigrationFacet is ReentrancyGuard { L2Beanstalk, 0, maxSubmissionCost, - msg.sender, - msg.sender, + receiver, // excessFeeRefundAddress + msg.sender, maxGas, gasPriceBid, data From a993932faec30be507f59e4e70819906e21820f8 Mon Sep 17 00:00:00 2001 From: nickkatsios Date: Fri, 6 Sep 2024 09:27:16 +0000 Subject: [PATCH 21/36] prettier auto formatting changes --- protocol/contracts/beanstalk/migration/L2MigrationFacet.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/protocol/contracts/beanstalk/migration/L2MigrationFacet.sol b/protocol/contracts/beanstalk/migration/L2MigrationFacet.sol index 9e927391d..ebaecd867 100644 --- a/protocol/contracts/beanstalk/migration/L2MigrationFacet.sol +++ b/protocol/contracts/beanstalk/migration/L2MigrationFacet.sol @@ -115,7 +115,7 @@ contract L2MigrationFacet is ReentrancyGuard { 0, maxSubmissionCost, receiver, // excessFeeRefundAddress - msg.sender, + msg.sender, maxGas, gasPriceBid, data From 0644fd62bb69cb63db8101ca8474985878483917 Mon Sep 17 00:00:00 2001 From: Brean0 Date: Fri, 6 Sep 2024 14:26:23 +0200 Subject: [PATCH 22/36] add pod order migration test. --- .../beanstalk/migration/L1RecieverFacet.sol | 40 +++++++--- .../contracts/beanstalk/storage/System.sol | 2 +- .../beanstalk-3/beanstalk-3-Contracts.js | 49 +++++++++++- .../beanstalk-3/data/inputs/PodOrders.json | 47 +++++++++++ .../data/merkle/podOrder_tree.json | 78 +++++++++++++++++++ .../test/foundry/Migration/L1Reciever.t.sol | 72 ++++++++++++++++- 6 files changed, 272 insertions(+), 16 deletions(-) create mode 100644 protocol/scripts/beanstalk-3/data/inputs/PodOrders.json create mode 100644 protocol/scripts/beanstalk-3/data/merkle/podOrder_tree.json diff --git a/protocol/contracts/beanstalk/migration/L1RecieverFacet.sol b/protocol/contracts/beanstalk/migration/L1RecieverFacet.sol index 5ede0a3a2..1f5119b08 100644 --- a/protocol/contracts/beanstalk/migration/L1RecieverFacet.sol +++ b/protocol/contracts/beanstalk/migration/L1RecieverFacet.sol @@ -30,7 +30,7 @@ import {Listing} from "contracts/beanstalk/market/MarketplaceFacet/Listing.sol"; * in order to migrate their deposits, plots, fertilizer, and internal balances to L2. **/ -contract L1RecieverFacet is ReentrancyGuard, Order { +contract L1RecieverFacet is ReentrancyGuard { // todo: update with correct external beans once L1 Beanstalk has been paused. uint256 constant EXTERNAL_L1_BEANS = 1000000e6; @@ -47,7 +47,7 @@ contract L1RecieverFacet is ReentrancyGuard, Order { bytes32 internal constant FERTILIZER_MERKLE_ROOT = 0x02ec4c26c5d970fef9bc46f5fc160788669d465da31e9edd37aded2b1c95b6c2; bytes32 internal constant PODLISTING_ORDER_MERKLE_ROOT = - 0x02ec4c26c5d970fef9bc46f5fc160788669d465da31e9edd37aded2b1c95b6c2; + 0x4a000e44e0820fdb1ef4194538de1404629221d77e7c920fa8c000ce5902d503; uint160 internal constant OFFSET = uint160(0x1111000000000000000000000000000000001111); @@ -300,9 +300,11 @@ contract L1RecieverFacet is ReentrancyGuard, Order { /** * @notice Recreates the PodOrders for contract addresses. - * @dev Listings are not migrated from contracts, and will need to be recreated. + * @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 issueOrdersAndListings( + function issuePodOrders( address owner, L1PodOrder[] memory orders, bytes32[] calldata proof @@ -313,16 +315,16 @@ contract L1RecieverFacet is ReentrancyGuard, Order { account.reciever != address(0) && account.reciever == reciever, "L2Migration: Invalid Reciever" ); - require(!account.migratedPodOrdersAndListings, "L2Migration: Orders have been migrated"); + require(!account.migratedPodOrders, "L2Migration: Orders have been migrated"); // verify order validity: - require(verifyOrderProof(owner, orders, proof), "L2Migration: Invalid Listing And Order"); + require(verifyOrderProof(owner, orders, proof), "L2Migration: Invalid Order"); // add migrated orders to account. addPodOrders(reciever, orders); // set migrated order to true. - account.migratedPodOrdersAndListings = true; + account.migratedPodOrders = true; emit L1OrdersMigrated(owner, reciever, orders); } @@ -409,7 +411,7 @@ contract L1RecieverFacet is ReentrancyGuard, Order { bytes32 leaf = keccak256( bytes.concat(keccak256(abi.encode(owner, keccak256(abi.encode(owner, orders))))) ); - return MerkleProof.verify(proof, FERTILIZER_MERKLE_ROOT, leaf); + return MerkleProof.verify(proof, PODLISTING_ORDER_MERKLE_ROOT, leaf); } //////////// MIGRATION HELPERS //////////// @@ -490,6 +492,10 @@ contract L1RecieverFacet is ReentrancyGuard, Order { } } + /** + * @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. @@ -499,7 +505,7 @@ contract L1RecieverFacet is ReentrancyGuard, Order { bytes32 id = _getOrderId(orders[i].podOrder); s.sys.podOrders[id] = orders[i].beanAmount; - emit PodOrderCreated( + emit Order.PodOrderCreated( orders[i].podOrder.orderer, id, orders[i].beanAmount, @@ -558,4 +564,20 @@ contract L1RecieverFacet is ReentrancyGuard, Order { 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 + ) + ); + } } diff --git a/protocol/contracts/beanstalk/storage/System.sol b/protocol/contracts/beanstalk/storage/System.sol index ef61c57a9..f9c27c672 100644 --- a/protocol/contracts/beanstalk/storage/System.sol +++ b/protocol/contracts/beanstalk/storage/System.sol @@ -410,7 +410,7 @@ struct MigrationData { bool migratedPlots; bool migratedFert; bool migratedInternalBalances; - bool migratedPodOrdersAndListings; + bool migratedPodOrders; } /** diff --git a/protocol/scripts/beanstalk-3/beanstalk-3-Contracts.js b/protocol/scripts/beanstalk-3/beanstalk-3-Contracts.js index f9364bdd5..5342a0166 100644 --- a/protocol/scripts/beanstalk-3/beanstalk-3-Contracts.js +++ b/protocol/scripts/beanstalk-3/beanstalk-3-Contracts.js @@ -8,6 +8,7 @@ const DEPOSITS = "./scripts/beanstalk-3/data/inputs/Deposits.json"; const PLOTS = "./scripts/beanstalk-3/data/inputs/Plots.json"; const INTERNAL_BALS = "./scripts/beanstalk-3/data/inputs/InternalBalances.json"; const FERTILIZERS = "./scripts/beanstalk-3/data/inputs/Fertilizers.json"; +const POD_ORDERS = "./scripts/beanstalk-3/data/inputs/PodOrders.json"; function getDepositMerkleRoot(verbose = false) { const accounts = JSON.parse(fs.readFileSync(DEPOSITS)); @@ -173,7 +174,47 @@ function getFertMerkleRoot(verbose = false) { ); } -getDepositMerkleRoot(false); -getPlotMerkleRoot(false); -getInternalBalMerkleRoot(false); -getFertMerkleRoot(false); +function getPodOrderMerkleRoot(verbose = false) { + const accounts = JSON.parse(fs.readFileSync(POD_ORDERS)); + let data = []; + let encodedData = ""; + let orderStruct = ["address", "tuple(tuple(address,uint256,uint24,uint256,uint256),uint256)[]"]; + for (let i = 0; i < accounts.length; i++) { + encodedData = ethers.utils.defaultAbiCoder.encode(orderStruct, accounts[i]); + // hash encoded data: + encodedData = ethers.utils.keccak256(encodedData); + data[i] = [accounts[i][0], encodedData]; + } + const tree = StandardMerkleTree.of(data, ["address", "bytes32"]); + + // (3) + console.log("PodOrder Merkle Root:", tree.root); + + // (4) + const treeData = tree.dump(); + const treeWithProofs = { + tree: treeData, + proofs: {} + }; + + for (const [i, v] of tree.entries()) { + const proof = tree.getProof(i); + treeWithProofs.proofs[v[0]] = proof; // Use the address as the key + + if (verbose) { + console.log("Value:", v); + console.log("Proof:", proof); + } + } + + fs.writeFileSync( + "./scripts/beanstalk-3/data/merkle/podOrder_tree.json", + JSON.stringify(treeWithProofs, null, 2) + ); +} + +// getDepositMerkleRoot(false); +// getPlotMerkleRoot(false); +// getInternalBalMerkleRoot(false); +// getFertMerkleRoot(false); +getPodOrderMerkleRoot(false); diff --git a/protocol/scripts/beanstalk-3/data/inputs/PodOrders.json b/protocol/scripts/beanstalk-3/data/inputs/PodOrders.json new file mode 100644 index 000000000..f7f6396b5 --- /dev/null +++ b/protocol/scripts/beanstalk-3/data/inputs/PodOrders.json @@ -0,0 +1,47 @@ +[ + [ + "0x000000009d3a9e5C7c620514e1f36905C4Eb91e1", + [ + [ + ["0x000000009d3a9e5C7c620514e1f36905C4Eb91e1", "1", "100000", "1000000000000", "1000000"], + "1000000" + ] + ] + ], + [ + "0x000000009d3a9e5c7C620514e1F36905C4eB91E2", + [ + [ + ["0x000000009d3a9e5c7C620514e1F36905C4eB91E2", "1", "100000", "1000000000000", "1000000"], + "1000000" + ] + ] + ], + [ + "0x000000009D3a9E5c7C620514E1f36905c4eb91E3", + [ + [ + ["0x000000009D3a9E5c7C620514E1f36905c4eb91E3", "1", "100000", "1000000000000", "1000000"], + "1000000" + ] + ] + ], + [ + "0x000000009d3a9e5C7C620514E1F36905c4eb91e4", + [ + [ + ["0x000000009d3a9e5C7C620514E1F36905c4eb91e4", "1", "100000", "1000000000000", "1000000"], + "1000000" + ] + ] + ], + [ + "0x000000009D3a9E5c7C620514E1F36905C4eb91e5", + [ + [ + ["0x000000009D3a9E5c7C620514E1F36905C4eb91e5", "1", "100000", "1000000000000", "1000000"], + "1000000" + ] + ] + ] +] diff --git a/protocol/scripts/beanstalk-3/data/merkle/podOrder_tree.json b/protocol/scripts/beanstalk-3/data/merkle/podOrder_tree.json new file mode 100644 index 000000000..da67159ac --- /dev/null +++ b/protocol/scripts/beanstalk-3/data/merkle/podOrder_tree.json @@ -0,0 +1,78 @@ +{ + "tree": { + "format": "standard-v1", + "leafEncoding": ["address", "bytes32"], + "tree": [ + "0x4a000e44e0820fdb1ef4194538de1404629221d77e7c920fa8c000ce5902d503", + "0xa6964a2a4ef727ac9201c69e83d4b6f1f70aa4bfd4415ebd959f171bdd1fcc30", + "0x9dc791f184484213529aa44fad0074c356eb252777a3c9b0516efaf0fd740650", + "0x7f22f1b3570ee253f90b9b5b130bb90a9bba994f9820f43820eb1257850467ea", + "0xe7d5a9eada9ddd23ca981cb62c1c0668339becddfdd69c463ae63ee3ebbdf50f", + "0xd65881c8ba79e4cd344ebcb1c500af5641ed08bb790042f18c888ced1b5b933c", + "0xcc4f9b28099f4211e2dc38f90ee8338ea1d97890b183e8b135408cd67cf7e3ca", + "0xa84b1c452b78b2a3abdc6ab83c128366592c5de1369e388ddee018c03fc36add", + "0x9887e2354e3cdb5d01aff524d71607cfdf3c4293c6f5711c806277fee5ad2063" + ], + "values": [ + { + "value": [ + "0x000000009d3a9e5C7c620514e1f36905C4Eb91e1", + "0x22a49133ec57fc5ffc4cf746ed3c681a3bb37da800b7a4729cbddc0b5cfc836f" + ], + "treeIndex": 6 + }, + { + "value": [ + "0x000000009d3a9e5c7C620514e1F36905C4eB91E2", + "0xf7ff58a83723d032bd22fb816b82dbe1499703857b6b8d6b76ec9585eec6f395" + ], + "treeIndex": 5 + }, + { + "value": [ + "0x000000009D3a9E5c7C620514E1f36905c4eb91E3", + "0x8054ec9b6a962049d270110f29b859433a304c8b75ba2e552c4021620250adaa" + ], + "treeIndex": 8 + }, + { + "value": [ + "0x000000009d3a9e5C7C620514E1F36905c4eb91e4", + "0x315d7a785df6f8efa63caae484bf8edbdfc24f797606f32b3da817a313a4aeb9" + ], + "treeIndex": 7 + }, + { + "value": [ + "0x000000009D3a9E5c7C620514E1F36905C4eb91e5", + "0x6c11c09e7e2ed81dd91f7fd89201d9b1950f7b0f45f011e60476ce58b3000173" + ], + "treeIndex": 4 + } + ] + }, + "proofs": { + "0x000000009d3a9e5C7c620514e1f36905C4Eb91e1": [ + "0xd65881c8ba79e4cd344ebcb1c500af5641ed08bb790042f18c888ced1b5b933c", + "0xa6964a2a4ef727ac9201c69e83d4b6f1f70aa4bfd4415ebd959f171bdd1fcc30" + ], + "0x000000009d3a9e5c7C620514e1F36905C4eB91E2": [ + "0xcc4f9b28099f4211e2dc38f90ee8338ea1d97890b183e8b135408cd67cf7e3ca", + "0xa6964a2a4ef727ac9201c69e83d4b6f1f70aa4bfd4415ebd959f171bdd1fcc30" + ], + "0x000000009D3a9E5c7C620514E1f36905c4eb91E3": [ + "0xa84b1c452b78b2a3abdc6ab83c128366592c5de1369e388ddee018c03fc36add", + "0xe7d5a9eada9ddd23ca981cb62c1c0668339becddfdd69c463ae63ee3ebbdf50f", + "0x9dc791f184484213529aa44fad0074c356eb252777a3c9b0516efaf0fd740650" + ], + "0x000000009d3a9e5C7C620514E1F36905c4eb91e4": [ + "0x9887e2354e3cdb5d01aff524d71607cfdf3c4293c6f5711c806277fee5ad2063", + "0xe7d5a9eada9ddd23ca981cb62c1c0668339becddfdd69c463ae63ee3ebbdf50f", + "0x9dc791f184484213529aa44fad0074c356eb252777a3c9b0516efaf0fd740650" + ], + "0x000000009D3a9E5c7C620514E1F36905C4eb91e5": [ + "0x7f22f1b3570ee253f90b9b5b130bb90a9bba994f9820f43820eb1257850467ea", + "0x9dc791f184484213529aa44fad0074c356eb252777a3c9b0516efaf0fd740650" + ] + } +} diff --git a/protocol/test/foundry/Migration/L1Reciever.t.sol b/protocol/test/foundry/Migration/L1Reciever.t.sol index 1f7194b2b..9b5907ce6 100644 --- a/protocol/test/foundry/Migration/L1Reciever.t.sol +++ b/protocol/test/foundry/Migration/L1Reciever.t.sol @@ -4,6 +4,7 @@ pragma abicoder v2; import {TestHelper, LibTransfer, C, IMockFBeanstalk} from "test/foundry/utils/TestHelper.sol"; import {L1RecieverFacet} from "contracts/beanstalk/migration/L1RecieverFacet.sol"; +import {Order} from "contracts/beanstalk/market/MarketplaceFacet/Order.sol"; import {LibBytes} from "contracts/Libraries/LibBytes.sol"; /** @@ -14,7 +15,7 @@ interface IERC1555 { function balanceOf(address account, uint256 id) external view returns (uint256); } -contract L1RecieverFacetTest is TestHelper { +contract L1RecieverFacetTest is Order, TestHelper { // contracts for testing: address constant OWNER = address(0x000000009d3a9e5C7c620514e1f36905C4Eb91e1); address constant RECIEVER = address(0x000000009D3a9E5c7C620514E1F36905C4eb91e5); @@ -117,6 +118,35 @@ contract L1RecieverFacetTest is TestHelper { L1RecieverFacet(BEANSTALK).issueFertilizer(owner, ids, amounts, lastBpf, proof); } + function test_L2MigratePodOrder() public { + bs.setRecieverForL1Migration(address(0x000000009d3a9e5C7C620514E1F36905c4eb91e4), RECIEVER); + + ( + address owner, + L1RecieverFacet.L1PodOrder[] memory podOrders, + bytes32[] memory proof + ) = getMockPodOrder(); + + vm.prank(RECIEVER); + L1RecieverFacet(BEANSTALK).issuePodOrders( + address(0x000000009d3a9e5C7C620514E1F36905c4eb91e4), + podOrders, + proof + ); + + // update pod order with reciever to verify id: + podOrders[0].podOrder.orderer = RECIEVER; + + bytes32 id = _getOrderId(podOrders[0].podOrder); + + assertEq(bs.getPodOrder(id), podOrders[0].beanAmount); + + // verify user cannot migrate afterwords. + vm.expectRevert("L2Migration: Orders have been migrated"); + vm.prank(RECIEVER); + L1RecieverFacet(BEANSTALK).issuePodOrders(owner, podOrders, proof); + } + /** * @notice verifies only the owner or bridge can call the migration functions. */ @@ -174,7 +204,7 @@ contract L1RecieverFacetTest is TestHelper { L1RecieverFacet(BEANSTALK).issueInternalBalances(owner, tokens, amounts, proof); } - function test_L2MigrateInvalidInternalFert() public { + function test_L2MigrateInvalidFert() public { bs.setRecieverForL1Migration(OWNER, RECIEVER); ( @@ -193,6 +223,24 @@ contract L1RecieverFacetTest is TestHelper { L1RecieverFacet(BEANSTALK).issueFertilizer(owner, ids, amounts, lastBpf, proof); } + function test_L2MigrateInvalidPodOrder() public { + bs.setRecieverForL1Migration(OWNER, RECIEVER); + + ( + address owner, + L1RecieverFacet.L1PodOrder[] memory podOrders, + bytes32[] memory proof + ) = getMockPodOrder(); + + // update pod orderer + podOrders[0].podOrder.orderer = RECIEVER; + + // verify user cannot migrate afterwords. + vm.expectRevert("L2Migration: Invalid Order"); + vm.prank(RECIEVER); + L1RecieverFacet(BEANSTALK).issuePodOrders(owner, podOrders, proof); + } + // test helpers function getMockDepositData() internal @@ -278,6 +326,26 @@ contract L1RecieverFacetTest is TestHelper { return (account, ids, amounts, lastBpf, proof); } + function getMockPodOrder() + internal + returns (address, L1RecieverFacet.L1PodOrder[] memory, bytes32[] memory) + { + address account = address(0x000000009d3a9e5C7C620514E1F36905c4eb91e4); + + L1RecieverFacet.L1PodOrder[] memory podOrders = new L1RecieverFacet.L1PodOrder[](1); + podOrders[0] = L1RecieverFacet.L1PodOrder( + Order.PodOrder(account, 1, 100000, 1000000000000, 1000000), + 1000000 + ); + + bytes32[] memory proof = new bytes32[](3); + proof[0] = bytes32(0x9887e2354e3cdb5d01aff524d71607cfdf3c4293c6f5711c806277fee5ad2063); + proof[1] = bytes32(0xe7d5a9eada9ddd23ca981cb62c1c0668339becddfdd69c463ae63ee3ebbdf50f); + proof[2] = bytes32(0x9dc791f184484213529aa44fad0074c356eb252777a3c9b0516efaf0fd740650); + + return (account, podOrders, proof); + } + /** * @notice Utility function that converts the address in the L1 that submitted a tx to * the inbox to the msg.sender viewed in the L2 From 6f9be46aaba7ab141e28649c2bd92ecaf731395c Mon Sep 17 00:00:00 2001 From: nickkatsios Date: Fri, 6 Sep 2024 17:18:37 +0300 Subject: [PATCH 23/36] misc price related changes --- protocol/foundry.toml | 1 - protocol/reseed/data/mocks/r9-whitelist-mock.json | 4 ++-- protocol/reseed/reseed9.js | 4 ++-- protocol/reseed/reseedAddLiquidityAndTransfer.js | 1 - protocol/reseed/reseedL2.js | 5 +++-- protocol/test/foundry/Migration/ReseedState.t.sol | 15 +++++++++++++++ 6 files changed, 22 insertions(+), 8 deletions(-) diff --git a/protocol/foundry.toml b/protocol/foundry.toml index 5b8533466..363560bbe 100644 --- a/protocol/foundry.toml +++ b/protocol/foundry.toml @@ -45,7 +45,6 @@ ignored_warnings_from = [ gas_reports = ['*'] # Cache to `$HOME/.foundry/cache//`. no_storage_caching = false -no_match_contract = "ReseedStateTest" [profile.differential] match_test = "testDiff" diff --git a/protocol/reseed/data/mocks/r9-whitelist-mock.json b/protocol/reseed/data/mocks/r9-whitelist-mock.json index a2931084a..12e63e357 100644 --- a/protocol/reseed/data/mocks/r9-whitelist-mock.json +++ b/protocol/reseed/data/mocks/r9-whitelist-mock.json @@ -57,7 +57,7 @@ ["0x0000000000000000000000000000000000000000", "0x00000000", "0x00", "0x00"] ], [ - "0xBEA00ebA46820994d24E45dffc5c006bBE35FD89", + "0xBEA00A3F7aaF99476862533Fe7DcA4b50f6158cB", "0x82aF49447D8a07e3bd95BD0d56f35241523fBab1", [ "0xc84c7727", @@ -72,7 +72,7 @@ ["0x0000000000000000000000000000000000000000", "0xd8317c71", "0x00", "0x00"], ["0x0000000000000000000000000000000000000000", "0xa8b0bb83", "0x00", "0x00"] ], - ["0xBEA00ebA46820994d24E45dffc5c006bBE35FD89", true, true, true, true], + ["0xBEA00A3F7aaF99476862533Fe7DcA4b50f6158cB", true, true, true, true], [ "0x639Fe6ab55C921f74e7fac1ee960C0B6293ba612", "0x00000000", diff --git a/protocol/reseed/reseed9.js b/protocol/reseed/reseed9.js index 35269825f..a5ada352c 100644 --- a/protocol/reseed/reseed9.js +++ b/protocol/reseed/reseed9.js @@ -2,13 +2,13 @@ const { upgradeWithNewFacets } = require("../scripts/diamond.js"); const { deployContract } = require("../scripts/contracts"); const fs = require("fs"); -async function reseed9(account, L2Beanstalk, mock = false) { +async function reseed9(account, L2Beanstalk, mock = true) { console.log("-----------------------------------"); console.log("reseed9: whitelist tokens.\n"); // Files let whitelistSettingsPath; - if (mock) { + if (true) { whitelistSettingsPath = "./reseed/data/mocks/r9-whitelist-mock.json"; } else { whitelistSettingsPath = "./reseed/data/r9-whitelist.json"; diff --git a/protocol/reseed/reseedAddLiquidityAndTransfer.js b/protocol/reseed/reseedAddLiquidityAndTransfer.js index f95d5eae5..bff545055 100644 --- a/protocol/reseed/reseedAddLiquidityAndTransfer.js +++ b/protocol/reseed/reseedAddLiquidityAndTransfer.js @@ -43,7 +43,6 @@ async function reseedAddLiquidityAndTransfer(account, L2Beanstalk, mock = true, console.log("-----------------------------------"); console.log("add liquidity to wells and transfers to l2 beanstalk.\n"); - // todo: update bean address once finalized. await impersonateToken("0xBEA0005B8599265D41256905A9B3073D397812E4", 6); const bean = await ethers.getContractAt( "MockToken", diff --git a/protocol/reseed/reseedL2.js b/protocol/reseed/reseedL2.js index 365b2f516..1a440ded8 100644 --- a/protocol/reseed/reseedL2.js +++ b/protocol/reseed/reseedL2.js @@ -32,7 +32,8 @@ async function reseedL2({ start = 0, end = 11, setState = true, - deployBasin = true + deployBasin = false, + addLiquidity = true }) { if (convertData) parseBeanstalkData(); // delete prev gas report @@ -117,7 +118,7 @@ async function reseedL2({ } } // adds liquidity to wells and transfer well LP tokens to l2 beanstalk: - await reseedAddLiquidityAndTransfer(l2owner, l2BeanstalkAddress, true); + if (addLiquidity) await reseedAddLiquidityAndTransfer(l2owner, l2BeanstalkAddress, true); console.log("Reseed successful."); } diff --git a/protocol/test/foundry/Migration/ReseedState.t.sol b/protocol/test/foundry/Migration/ReseedState.t.sol index 722d8c216..bc95b7324 100644 --- a/protocol/test/foundry/Migration/ReseedState.t.sol +++ b/protocol/test/foundry/Migration/ReseedState.t.sol @@ -11,6 +11,12 @@ import {Deposit} from "contracts/beanstalk/storage/Account.sol"; import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; import {IWell} from "contracts/interfaces/basin/IWell.sol"; import "forge-std/StdUtils.sol"; +import {BeanstalkPrice, WellPrice} from "contracts/ecosystem/price/BeanstalkPrice.sol"; +import {P} from "contracts/ecosystem/price/P.sol"; + +interface IBeanstalkPrice { + function price() external view returns (P.Prices memory p); +} /** * @notice Verfifies state and functionality of the new L2 Beanstalk @@ -19,6 +25,7 @@ contract ReseedStateTest is TestHelper { // contracts for testing: address constant L2_BEANSTALK = address(0xD1A0060ba708BC4BCD3DA6C37EFa8deDF015FB70); address constant FERTILIZER = address(0xC59f881074Bf039352C227E21980317e6b969c8A); + address constant BEANSTALK_PRICE = address(0xEfE94bE746681ed73DfD15F932f9a8e8ffDdEE56); uint256 constant FIELD_ID = 0; @@ -64,9 +71,17 @@ contract ReseedStateTest is TestHelper { accountNumber = parseAccounts(numAccounts); console.log("Number of accounts: ", accountNumber); l2Beanstalk = IMockFBeanstalk(L2_BEANSTALK); + // skip(100_000_000); // l2Beanstalk.gm(address(this), 1); } + // LibUsdOracle: 0x5003dF9E48dA96e4B4390373c8ae70EbFA5415A7 + function test_beanstalkPrice() public { + // Get beanstalk price + IBeanstalkPrice beanstalkPrice = IBeanstalkPrice(BEANSTALK_PRICE); + P.Prices memory prices = beanstalkPrice.price(); + } + ////////////////// WhiteListed Tokens ////////////////// function test_whiteListedTokens() public { From fbdd4e22f908c95b5ebf49ecdb0b0ca5b2973f13 Mon Sep 17 00:00:00 2001 From: nickkatsios Date: Sun, 8 Sep 2024 19:26:14 +0300 Subject: [PATCH 24/36] update wells package --- protocol/package.json | 2 +- yarn.lock | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/protocol/package.json b/protocol/package.json index f08681859..5fa3625fe 100644 --- a/protocol/package.json +++ b/protocol/package.json @@ -44,7 +44,7 @@ }, "dependencies": { "@beanstalk/wells": "0.4.1", - "@beanstalk/wells1.2": "npm:@beanstalk/wells@1.2.0-prerelease3", + "@beanstalk/wells1.2": "npm:@beanstalk/wells@1.2.0", "@ethereum-waffle/chai": "4.0.10", "@nomicfoundation/hardhat-network-helpers": "^1.0.7", "@openzeppelin/contracts": "5.0.2", diff --git a/yarn.lock b/yarn.lock index 300ba2338..cc6988a6e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2082,7 +2082,7 @@ __metadata: resolution: "@beanstalk/protocol@workspace:protocol" dependencies: "@beanstalk/wells": "npm:0.4.1" - "@beanstalk/wells1.2": "npm:@beanstalk/wells@1.2.0-prerelease3" + "@beanstalk/wells1.2": "npm:@beanstalk/wells@1.2.0" "@ethereum-waffle/chai": "npm:4.0.10" "@nomicfoundation/hardhat-network-helpers": "npm:^1.0.10" "@nomiclabs/hardhat-ethers": "npm:^2.2.1" @@ -2245,10 +2245,10 @@ __metadata: languageName: unknown linkType: soft -"@beanstalk/wells1.2@npm:@beanstalk/wells@1.2.0-prerelease3": - version: 1.2.0-prerelease3 - resolution: "@beanstalk/wells@npm:1.2.0-prerelease3" - checksum: 10/b824397cbaa938f1526047965f921008f565bb8832011bf9768b69b378dd012529a2c621f537de84bd6a14791b8f675f388094b409185e87f010a8fc54cc06a0 +"@beanstalk/wells1.2@npm:@beanstalk/wells@1.2.0": + version: 1.2.0 + resolution: "@beanstalk/wells@npm:1.2.0" + checksum: 10/670516484f77de10e45ed30ebbbd8b076eeb70dd8a5e26950d3547bf7b2cd43713baa90fab44c7ac56d1f9e9be77d38883901d3aa1e34830eb6e1119ad3ba56f languageName: node linkType: hard From 4ef845830d8f5648e1e3700af663282e08fac485 Mon Sep 17 00:00:00 2001 From: nickkatsios Date: Mon, 9 Sep 2024 12:50:32 +0300 Subject: [PATCH 25/36] update STALK_BDV_PRECISION --- protocol/contracts/libraries/LibGauge.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/protocol/contracts/libraries/LibGauge.sol b/protocol/contracts/libraries/LibGauge.sol index c478f6e05..33c8517db 100644 --- a/protocol/contracts/libraries/LibGauge.sol +++ b/protocol/contracts/libraries/LibGauge.sol @@ -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. From bdc8266be534035108da44dcb05ecb4164746693 Mon Sep 17 00:00:00 2001 From: nickkatsios Date: Mon, 9 Sep 2024 13:35:13 +0300 Subject: [PATCH 26/36] fix calculateTokenBeanPriceFromReserves --- protocol/contracts/libraries/Well/LibWell.sol | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/protocol/contracts/libraries/Well/LibWell.sol b/protocol/contracts/libraries/Well/LibWell.sol index b6b87c454..9ace4ad84 100644 --- a/protocol/contracts/libraries/Well/LibWell.sol +++ b/protocol/contracts/libraries/Well/LibWell.sol @@ -272,6 +272,12 @@ library LibWell { } } + /** + * @notice Calculates the token price in terms of Bean by increasing + * the bean reserves of the given well by 1 and recaclulating the new reserves, + * while maintaining the same liquidity levels. + * This essentially simulates a swap of 1 Bean for the non bean token and quotes the price. + */ function calculateTokenBeanPriceFromReserves( address well, uint256 beanIndex, @@ -293,12 +299,9 @@ library LibWell { lpTokenSupply, wellFunction.data ); - uint256 delta; - if (nonBeanIndex == 1) { - delta = oldReserve - newReserve; - } else { - delta = newReserve - oldReserve; - } + // Measure the delta of the non bean reserve. + // Due to the invariant of the well function, old reserve > new reserve. + uint256 delta = oldReserve - newReserve; price = (10 ** (IERC20Decimals(nonBeanToken).decimals() + 6)) / delta; } From a901c0e76b16f21c81aead48a3d27e6ed24ba4f6 Mon Sep 17 00:00:00 2001 From: nickkatsios Date: Mon, 9 Sep 2024 17:24:26 +0300 Subject: [PATCH 27/36] add data for external unripe bean and lp holders, move pod marketplace data to correct folder --- .../exports/externalHolders/beanHolders.csv | 181 +++++++++++++++++ .../externalHolders/unripeBeanHolders.csv | 47 +++++ .../externalHolders/unripeLpHolders.csv | 24 +++ .../mocks/r3/L2_external_unripe_balances.json | 10 - .../mocks/{r2 => r3}/pod-listings-mock.json | 0 .../mocks/{r2 => r3}/pod-orders-mock.json | 0 .../data/r2/L2_external_unripe_balances.json | 186 ++++++++++++++++++ .../r2/L2_external_unripe_lp_balances.json | 25 +++ .../{mocks/r3 => r2}/L2_initial_supply.json | 0 .../{mocks/r3 => r2}/L2_well_balances.json | 0 .../data/r3/L2_external_unripe_balances.json | 10 - .../reseed/data/r3/L2_initial_supply.json | 1 - protocol/reseed/data/r3/L2_well_balances.json | 5 - .../reseed/data/{r2 => r3}/pod-listings.json | 0 .../reseed/data/{r2 => r3}/pod-orders.json | 0 .../dataConverts/convertExternalHolders.js | 21 ++ protocol/reseed/reseed2.js | 14 +- protocol/reseed/reseed3.js | 4 +- protocol/reseed/reseedL2.js | 17 +- 19 files changed, 509 insertions(+), 36 deletions(-) create mode 100644 protocol/reseed/data/exports/externalHolders/beanHolders.csv create mode 100644 protocol/reseed/data/exports/externalHolders/unripeBeanHolders.csv create mode 100644 protocol/reseed/data/exports/externalHolders/unripeLpHolders.csv delete mode 100644 protocol/reseed/data/mocks/r3/L2_external_unripe_balances.json rename protocol/reseed/data/mocks/{r2 => r3}/pod-listings-mock.json (100%) rename protocol/reseed/data/mocks/{r2 => r3}/pod-orders-mock.json (100%) create mode 100644 protocol/reseed/data/r2/L2_external_unripe_balances.json create mode 100644 protocol/reseed/data/r2/L2_external_unripe_lp_balances.json rename protocol/reseed/data/{mocks/r3 => r2}/L2_initial_supply.json (100%) rename protocol/reseed/data/{mocks/r3 => r2}/L2_well_balances.json (100%) delete mode 100644 protocol/reseed/data/r3/L2_external_unripe_balances.json delete mode 100644 protocol/reseed/data/r3/L2_initial_supply.json delete mode 100644 protocol/reseed/data/r3/L2_well_balances.json rename protocol/reseed/data/{r2 => r3}/pod-listings.json (100%) rename protocol/reseed/data/{r2 => r3}/pod-orders.json (100%) create mode 100644 protocol/reseed/dataConverts/convertExternalHolders.js diff --git a/protocol/reseed/data/exports/externalHolders/beanHolders.csv b/protocol/reseed/data/exports/externalHolders/beanHolders.csv new file mode 100644 index 000000000..f0bbb0aa1 --- /dev/null +++ b/protocol/reseed/data/exports/externalHolders/beanHolders.csv @@ -0,0 +1,181 @@ +account,balance +0xc1e088fc1323b20bcbee9bd1b9fc9546db5624c5,33161330588151 +0xbea0000113b0d182f4064c86b71c315389e4715d,14334525518260 +0x66efac6e6d58d4058cf017e66a0039315a3eb29c,2453000000000 +0xbea0e11282e2bb5893bece110cf199501e872bad,110674154956 +0xc9c32cd16bf7efb85ff14e0c8603cc90f6f2ee49,81254060564 +0x21de18b6a8f78ede6d16c50a167f6b222dc08df7,80522986118 +0x43b9f935c798522aaacb2bfea2f407ce5a291e9d,80400000000 +0x25c1278454254f783ef8760987db8de0268c6cbe,15896705546 +0x87c5e5413d60e1419fd70b17c6d299aa107efb49,12249000000 +0x23e59a5b174ab23b4d6b8a1b44e60b611b0397b6,10500617337 +0x498b859d2e59958e209d7dd262324c8d31b12b12,10154884037 +0xbd01f3494ff4f5b6aca5689cc6220e68d684f146,8076504768 +0xe68cf6eb200759349f5a367b38d6453727fd5e9a,7443525537 +0x7119f398b6c06095c6e8964c1f58e7c1baa79e18,5800000000 +0xbfe4ec1b5906d4be89c3f6942d1c6b04b19de79e,5707669485 +0xc18bab9f644187505f391e394768949793e9894f,5253544581 +0x87f4ca3e6768075ed87a8c4473890320af14ccf0,4039961627 +0x4cc19a7a359f2ff54ff087f03b6887f436f08c11,3878850000 +0x103cba62b51f02310f8ea33a624b948b6c1454bf,3000000000 +0xa4f6638cde88f245b75670b510fd8e46fafd1678,2518835194 +0x94f335a00f00d79b26336fa1c77bab6ae96f08c5,2321368905 +0x1b15ed3612cd3077ba4437a1e2b924c33d4de0f9,2082981694 +0x7c27a1f60b5229340bc57449cfb91ca496c3c1c1,1878848136 +0x979fee925e1d2531b8efa247c42e64fd1d670241,1502525730 +0xd67acddb195e31ad9e09f2cbc8d7f7891a6d44bf,1466680000 +0x47e6b4a6cb47eb7c7d30820c7c460183cf7abd5b,1000000000 +0x19a4fe7d0c76490cca77b45580846cdb38b9a406,992594251 +0x558c4aff233f17ac0d25335410faea0453328da8,926096318 +0xba27669908796b306f00df72e3041e6c41f32b4f,875840231 +0x11dd6f9e1a7bb35a61fada4aec645f603050783e,812842419 +0x2e6cbcfa99c5c164b0af573bc5b07c8bed18c872,704692374 +0xf2d47e78dea8e0f96902c85902323d2a2012b0c0,667305944 +0x251fae8f687545bdd462ba4fcdd7581051740463,581979838 +0xc8d71db19694312177b99fb5d15a1d295b22671a,503360000 +0x12b1c89124af9b720c1e3e8e31492d66662bf040,499897010 +0x87316f7261e140273f5fc4162da578389070879f,469224030 +0x7d6d548fad925c3b2f0a500b290557c7be424c12,427770050 +0xd53adf794e2915b4f414be1ab2282ca8da56dcfd,415462447 +0xcbd7712d9335a7a38f35b38d5dc9b5970f04e8fd,348815519 +0xd2f2f6b0f48e7a12496d8c9f7a2c18e6b76e49e0,341572105 +0xdecaf1d3c1b16e1ff8bc8fdc8d80d286d335e32e,334700488 +0xc0c0514363049224093ec8b610c00f292d80b621,256688000 +0x6eeca4051666ece16df7a7a2e3948119c98a002e,256186307 +0x30cb1e845f6c03b988ec677a75700e70a019e2e4,253222101 +0x6cc9b3940eb6d94cad1a25c437d9be966af821e3,252740579 +0x414a26eaa23583715d71b3294f0bf5eabdd2eaa8,248479164 +0xe65caecfe1626bf65f66fb4ec3c5d588a90022cb,234894994 +0x06470cc9f84375233d7fac12c6fce199ce632dd6,210942792 +0x58737a9b0a8a5c8a2559c457fcc9e923f9d99fb7,210411000 +0x82f402847051bddaab0f5d4b481417281837c424,194562223 +0x71b49dd7e69cd8a1e81f7a1e3012c7c12195b7f9,184893677 +0xdff58819ab64c79d5276e4052d3e74aca493658d,174333575 +0x9008d19f58aabd9ed0d60971565aa8510560ab41,141825758 +0x77ab999d1e9f152156b4411e1f3e2a42dab8cd6d,141020150 +0x072fa8a20fa621665b94745a8075073ceadfe1dc,135661772 +0xe4452cb39ad3faa39434b9d768677b34dc90d5dc,120489386 +0xb4a939498e00fc637ea6d23dacf1256539c503e3,116750712 +0xd5ae1639e5ef6ecf241389894a289a7c0c398241,113870222 +0x38c5ca4ee678d4f9d8d94a7f238e2700a8978b36,112679026 +0x75a158b6939d9abc27b5e3ea9e79c11302cec60c,111566830 +0x202eca424a8db90924a4daa3e6bcecd9311f668e,109321301 +0x7d6a2f6d7c2f7dd51c47b5ea9faa3ae208185ec7,100000000 +0xcb026b53c4674637663e85603e95ae539bd1bd2a,100000000 +0xb47959506850b9b34a8f345179ed1c932aaa8bfa,96540240 +0x9f1f4714d07859dd4c8d1312881a0700ed1c2a7e,87535611 +0xacc53f19851ce116d52b730aee8772f7bd568821,84269970 +0x9ae3821d72b53f767f5b72c9630ce864c54c09bc,80000000 +0x575c9606cfccf6f93d2e5a0c37d2c7696bcab132,77529516 +0x9821aac07d0724c69835367d596352aaf09c309c,76096126 +0xde975401d53178cdf36e1301da633a8f82c33cef,70408755 +0x3c58492ad9cad0d9f8570a80b6a1f02c0c1da2c5,70301838 +0x46387563927595f5ef11952f74dcc2ce2e871e73,61000195 +0x88f667664e61221160ddc0414868ef2f40e83324,54207252 +0xdb2480a43c79126f93bd5a825dc0cba46d7c0612,50116489 +0xaa4f23a13f25e88ba710243dd59305f382376252,49703615 +0x88fff68c3ee825a7a59f20bfea3c80d1ac09bef1,48278967 +0x7df40fde5e8680c45bfedafcf61dd6962e688562,47939000 +0x7e1ca6d381e2784db210442bfc3e2b1451f773fd,46637594 +0x047b22bfe547d29843c825dbcbd9e0168649d631,46303468 +0xf662972ff1a9d77dcdfba640c1d01fa9d6e4fb73,42183000 +0x8521cfdfd0fd1ac18520fa8f262eb948d4420c8a,42000000 +0x0716a17fbaee714f1e6ab0f9d59edbc5f09815c0,42000000 +0x23caea94eb856767cf71a30824d72ed5b93aa365,36518180 +0x876133657f5356e376b7ae27d251444727ce9488,35054599 +0xa7194f754b5befc3277d6bfa258028450da654ba,33043500 +0x4779c6a1cb190221fc152af4b6adb2ea5c5dbd88,29137817 +0xe4000004000bd8006e00720000d27d1fa000d43e,29031846 +0xb5d0374f0c35cf84f495121f5d29ea9275414de8,28362442 +0x548e13ddc5e2c6bc9456648a9a487da335b6ec25,27891707 +0x3789c64cc3a8120a93e9483d526d44be7305e455,27891707 +0x87a774178d49c919be273f1022de2ae106e2581e,26000000 +0x58d37a1f4f38f20e841e17e7c610eb494cc1f8de,25950320 +0x87263a1ac2c342a516989124d0dba63df6d0e790,23288715 +0x4af7c12c7e210f4cb8f2d8e340aaadae05a9f655,23271000 +0xcdea6a23b9383a88e246975ad3f38778ee0e81fc,23049092 +0x7a68a90a71413e12db9cc23fac37e9608ca48f48,22715605 +0xf9563a8dab33f6beab2abc34631c4eaf9ecc8b99,20907127 +0x6691fb80b87b89e3ea3e7c9a4b19fdb2d75c6aad,20103791 +0xa50a686bcfcdd1eb5b052c6e22c370ea1153cc15,18099438 +0x6b99a6c6081068aa46a420fdb6cfbe906320fa2d,17626050 +0xee98b8ac30896ba4b3c0d34b28536636b770d5f7,17014350 +0xc99a41144b5de2a9d0c3cc5338f8f94912352999,16559396 +0x769a8fd17ecb067a88744eee3eef1059c79df206,15211005 +0x8d97775623368f833f8fa82209e220f1c60508ea,15000000 +0xc4ff293174198e9aeb8f655673100eeedcbbfb1a,14680787 +0x00f244126b1f29b50d45464f08de883f1ff2fb7c,14234465 +0x64707d044389a2c00f5296b93ad3a7f6fd073bee,12682814 +0x1125eac5f713503e2b7cb2299027960ce1aa5d42,12633543 +0x54c04c9bf5af0bc3096cb0af24c4fa8379a2915e,12388488 +0xdf9c4a067279857b463817ef773fe189c77e1686,12000000 +0x78320e6082f9e831dd3057272f553e143dfe5b9c,11510958 +0x63b98c09120e4ef75b4c122d79b39875f28a6fcc,11500608 +0x682864c9bc8747c804a6137d6f0e8e087f49089e,11048400 +0x905eafe9434fabacaf10d1490fcd0d1eb9b85fc8,11000000 +0x961ea5962b8608dafd037f303a5fb4a4fd81bac7,10182124 +0x795781de02f10d8343baf897fbb4e6a755b4ecb9,10081325 +0xaf7ed02de4b8a8967b996df3b8bf28917b92edcd,9324600 +0x854e4406b9c2cfdc36a8992f1718e09e5f0d2371,9104148 +0x41cc24b4e568715f33fe803a6c3419708205304d,7566819 +0xc52a0b002ac4e62be0d269a948e55d126a48c767,6891274 +0x99bfdb688d53891d6e9e716eace90fa233a83500,6690000 +0xf8d5708b32616b6c85c97f5a9c344e6b7076fe98,6227809 +0x729ad565b305be00729e0a5677401dca268e6d8a,6101062 +0x9b1ac8e6d08053c55713d9aa8fde1c53e9a929e2,6056743 +0x4088e870e785320413288c605fd1bd6bd9d5bdae,5674104 +0x0da2a82ed2c387d1751ccbaf999a80b65bdb269e,4579053 +0x39041f1b366fe33f9a5a79de5120f2aee2577ebc,4255327 +0xd130ab894366e4376b1afe3d52638a1087be17f4,4006187 +0xbb11017d4bcb67cf083b13b5bcdb4fe121038227,3735321 +0xb6cc924486681a1ca489639200dceb4c41c283d3,3551588 +0x00ca340d789f00d4c978b236606c3105a09254f8,2995098 +0x3aa228a80f50763045bdfc45012da124bd0a6809,2130668 +0x00000000009726632680fb29d3f7a9734e3010e2,2130169 +0x7b5fe7af8315acb2e37b1f343cf6f4b225fa9878,2077799 +0x8a9c930896e453ca3d87f1918996423a589dd529,2011323 +0xc5581f1ae61e34391824779d505ca127a4566737,1816599 +0x4282341588f94c158bfaa40ae2c9f3abfdac647f,1795049 +0x7c28e0977f72c5d08d5e1ac7d52a34db378282b3,1748864 +0x995d1e4e2807ef2a8d7614b607a89be096313916,1645609 +0x4a183b7ed67b9e14b3f45abfb2cf44ed22c29e54,1271235 +0xc12df5f402a8b8beaea49ed9bad9c95fccbfe907,1173526 +0x9249e360dc6f4d2871187acde4fe38d4e13a7703,1058540 +0x9ec255f1af4d3e4a813aadab8ff0497398037d56,1009677 +0x155e6c85fa47a7244b04f3bafa549b55f1909f93,1000000 +0x5c9d09716404556646b0b4567cb4621c18581f94,972133 +0x80b9aa22ccda52f40be998eeb19db4d08fafec3e,922454 +0xb01f8f528702d411d24c9bb8cc0e2fff779ec013,889690 +0x5ec6bc92395bfe4dfb8f45cb129ac0c2f290f23d,796853 +0x5853ed4f26a3fcea565b3fbc698bb19cdf6deb85,751575 +0xb32d57f94542ebfad5073adf62d70d812ddba0a5,268375 +0x88ad88c5b3beae06a248e286d1ed08c27e8b043b,254632 +0x8e8ae083ac4455108829789e8acb4dbdde330e2e,200000 +0x8d4122ffe442de3574871b9648868c1c3396a0af,186429 +0x820a2943762236e27a3a2c6ea1024117518895a5,100000 +0x0ce72b7dde6ea0e9e8feeb634fcd9245e81d34f3,86451 +0x6d11937490234176e6229c4b80b27fedf237465f,66150 +0x14567c85977847836c17dd609a9bd767f3f03b51,60422 +0xdd9f24efc84d93deef3c8745c837ab63e80abd27,58177 +0x542a94e6f4d9d15aae550f7097d089f273e38f85,32581 +0x19cf79e47c31464ac0b686913e02e2e70c01bd5c,9019 +0xb1f0e758951a02b24d04dd211d0424445ae04c5c,8764 +0x18ad8a3387aac16c794f3b14451c591fef0344fe,6488 +0x40ca67ba095c038b711ad37bbebad8a586ae6f38,2252 +0xc1fe2bb036e3fc9eddcc83304dbe752881087cdf,98 +0x4c366e92d46796d14d658e690de9b1f54bfb632f,70 +0x5c2e7837a5dc5d07c6977bfedb46a1f3ec6a5a77,58 +0x6e93e171c5223493ad5434ac406140e89bd606de,33 +0xe6b1de575e7e610889ea21024834e120f92033a3,11 +0x22a956c4755d8c4294b358dc346e74250e175622,5 +0x3face0004bc1003b9d0672e7b23134cb80115fb6,2 +0x9edaff6744d6f539298cddd8c0171b774be2b86d,2 +0x0b3f6d4a5d6835137ccb2c1248f5a7d882c0dbda,1 +0xf0d4c12a5768d806021f80a262b4d39d26c58b8d,1 +0xe2dc368cf962426efa08b60c9570b19618b5e672,1 +0x7122db0ebe4eb9b434a9f2ffe6760bc03bfbd0e0,1 +0x1111111254eeb25477b68fb85ed929f73a960582,1 +0x1136b25047e142fa3018184793aec68fbb173ce4,1 +0x3208684f96458c540eb08f6f01b9e9afb2b7d4f0,1 +0x92f3f71cef740ed5784874b8c70ff87ecdf33588,1 +0xe37e799d5077682fa0a244d46e5649f71457bd09,1 diff --git a/protocol/reseed/data/exports/externalHolders/unripeBeanHolders.csv b/protocol/reseed/data/exports/externalHolders/unripeBeanHolders.csv new file mode 100644 index 000000000..c101902f4 --- /dev/null +++ b/protocol/reseed/data/exports/externalHolders/unripeBeanHolders.csv @@ -0,0 +1,47 @@ +account,balance +0xc1e088fc1323b20bcbee9bd1b9fc9546db5624c5,107919824635094 +0x9f64674cab93986254c6329c4521c4f9737af864,412635026949 +0xc65f06b01e114414aac120d54a2e56d2b75b1f85,149041834672 +0x8afcd552709bac70a470ec1d137d535bfa4fadee,78365538823 +0x253ab8294bf3fb6ab6439abc9bc7081504db9bff,44573289187 +0x79645bfb4ef32902f4ee436a23e4a10a50789e54,24273580464 +0x2be2273452ce4c80c0f9e9180d3f0d6eedfa7923,17411461677 +0x0bfd9fc73c82be0558f3a651f10a8bd8c784f45e,15927533063 +0xe7baf7af12e6b18c8cdd32292c6f06840cf71442,14586805595 +0xa82240bb0291a8ef6e46a4f6b8abf4737b0b5257,10000000000 +0x044c53d8576d4d700e6327c954f88388ee03b8db,9655048867 +0xaa4f23a13f25e88ba710243dd59305f382376252,8798351793 +0x3c7cfaf3680953f8ca3c7e319ac2a4c35870e86c,6416085500 +0x23444f470c8760bef7424c457c30dc2d4378974b,5670131987 +0xb8da309775c696576d26ef7d25b68c103a9ab0d5,5240156695 +0xaf616daba40f81b75af5373294d4dbe29dd0e0f6,4334685782 +0x1860a5c708c1e982e293aa4338bdbcafb7cb90ac,4269000000 +0x8687c54f8a431134cde94ae3782cb7cba9963d12,3640000000 +0x93be7761f4c7153bc462a50f9eb5eb424c39c2cd,2368110074 +0x82fcd7cd3151b0ab9e4c00629f123d45ad17fa73,2105369400 +0xf658305d26c8df03e9ed3ff7c7287f7233de472d,1866470834 +0xcd5561b1be55c1fa4bba4749919a03219497b6ef,1309882178 +0x9821aac07d0724c69835367d596352aaf09c309c,1005037990 +0x575c9606cfccf6f93d2e5a0c37d2c7696bcab132,983699606 +0xd8d1fa915826a24d6103e8d0fa04020c4ebc0c5e,936175040 +0x8bea73aac4f7ef9daded46359a544f0bb2d1364f,882175040 +0xb9488bb4f6b57093eaa9a0cf0d722ed61e8039ac,795009391 +0xf05b641229bb2aa63b205ad8b423a390f7ef05a7,726877197 +0x9142a918df6208ae1be65e2be0ea9dad6067155e,567271172 +0x76e3d82b0c49f1c921d8c1093cd91c20ba23740d,510000000 +0x9b0f5ccc13fa9fc22ab6c4766e419bb2a881eb1b,496000000 +0x24294915f8b5831d710d40c277916edc0fa0ec39,336422082 +0xb1d47d39c3bb868e5e4be068b7057d4caad0b31c,295066819 +0x4b9184df8fa9f3fc008fcde7e7bbf7208ef5118d,100000000 +0x3d93420aa8512e2bc7d77cb9352d752881706638,95422611 +0xc42593f89d4b6647bff86fa309c72d5e93a9405c,50000000 +0xf2f65a8a44f0bb1a634a85b1a4eb4be4d69769b6,12568525 +0xc896e266368d3eb26219c5cc74a4941339218d86,957695 +0x542a94e6f4d9d15aae550f7097d089f273e38f85,138988 +0x40ca67ba095c038b711ad37bbebad8a586ae6f38,62697 +0x1397c24478cbe0a54572adec2a333f87ad75ac02,43337 +0xa6a0bed0732c49bd847b4b308daac15640f1ec6e,7802 +0xf8fdcac2c64ba5e0459f67b9610bd3eda11f04ba,5894 +0xd67acddb195e31ad9e09f2cbc8d7f7891a6d44bf,276 +0x3dd413fd4d03b1d8fd2c9ed34553f7dec3b26f5c,9 +0xd970ba10ed5e88b678cd39fa37daa765f6948733,1 diff --git a/protocol/reseed/data/exports/externalHolders/unripeLpHolders.csv b/protocol/reseed/data/exports/externalHolders/unripeLpHolders.csv new file mode 100644 index 000000000..c09ca9f11 --- /dev/null +++ b/protocol/reseed/data/exports/externalHolders/unripeLpHolders.csv @@ -0,0 +1,24 @@ +account,balance +0xc1e088fc1323b20bcbee9bd1b9fc9546db5624c5,68338152592140 +0x1085057e6d9ad66e73d3cc788079155660264152,203120992714 +0xe6f00dde5f7622298c16a9e39b471d1c1c2de250,120581249548 +0x8fe7261b58a691e40f7a21d38d27965e2d3afd6e,58799943357 +0xaf616daba40f81b75af5373294d4dbe29dd0e0f6,49387419081 +0xf658305d26c8df03e9ed3ff7c7287f7233de472d,32130269456 +0xc6ac7c7acabc3585cfe16478fd4d22c1e8dc3c57,20951803116 +0xd8388ad2ff4c781903b6d9f17a60daf4e919f2ce,18909808200 +0x52c9a7e7d265a09db125b7369bc7487c589a7604,13915586466 +0xb33cb651648a99f2ffff076fd3f645fac24d460f,9737535811 +0xf2f65a8a44f0bb1a634a85b1a4eb4be4d69769b6,7652021349 +0x0bfd9fc73c82be0558f3a651f10a8bd8c784f45e,6863712510 +0x9821aac07d0724c69835367d596352aaf09c309c,6757145778 +0x5f683bd8e397e11858dab751eca248e5b2afc522,6104281597 +0x9142a918df6208ae1be65e2be0ea9dad6067155e,2986538692 +0x7f538566f85310c901172142e8a9a892f0eaf946,2951663131 +0x575c9606cfccf6f93d2e5a0c37d2c7696bcab132,2356468230 +0x76e3d82b0c49f1c921d8c1093cd91c20ba23740d,2233000000 +0xa86e29ad86d690f8b5a6a632cab8405d40a319fa,1755275296 +0xb9488bb4f6b57093eaa9a0cf0d722ed61e8039ac,651392713 +0xd45accf4512af9ceac4c3ab0e770f54212cdf9ac,500000000 +0x542a94e6f4d9d15aae550f7097d089f273e38f85,614013 +0x40ca67ba095c038b711ad37bbebad8a586ae6f38,605736 diff --git a/protocol/reseed/data/mocks/r3/L2_external_unripe_balances.json b/protocol/reseed/data/mocks/r3/L2_external_unripe_balances.json deleted file mode 100644 index f9d85971d..000000000 --- a/protocol/reseed/data/mocks/r3/L2_external_unripe_balances.json +++ /dev/null @@ -1,10 +0,0 @@ -[ - [ - ["0x000000009d3a9e5c7c620514e1f36905c4eb91e5", "1000000"], - ["0x000000009d3a9e5c7c620514e1f36905c4eb91e5", "1000000"] - ], - [ - ["0x000000009d3a9e5c7c620514e1f36905c4eb91e5", "1000000"], - ["0x000000009d3a9e5c7c620514e1f36905c4eb91e5", "1000000"] - ] -] \ No newline at end of file diff --git a/protocol/reseed/data/mocks/r2/pod-listings-mock.json b/protocol/reseed/data/mocks/r3/pod-listings-mock.json similarity index 100% rename from protocol/reseed/data/mocks/r2/pod-listings-mock.json rename to protocol/reseed/data/mocks/r3/pod-listings-mock.json diff --git a/protocol/reseed/data/mocks/r2/pod-orders-mock.json b/protocol/reseed/data/mocks/r3/pod-orders-mock.json similarity index 100% rename from protocol/reseed/data/mocks/r2/pod-orders-mock.json rename to protocol/reseed/data/mocks/r3/pod-orders-mock.json diff --git a/protocol/reseed/data/r2/L2_external_unripe_balances.json b/protocol/reseed/data/r2/L2_external_unripe_balances.json new file mode 100644 index 000000000..1fda71341 --- /dev/null +++ b/protocol/reseed/data/r2/L2_external_unripe_balances.json @@ -0,0 +1,186 @@ +[ + [ + "0xc1e088fc1323b20bcbee9bd1b9fc9546db5624c5", + "107919824635094" + ], + [ + "0x9f64674cab93986254c6329c4521c4f9737af864", + "412635026949" + ], + [ + "0xc65f06b01e114414aac120d54a2e56d2b75b1f85", + "149041834672" + ], + [ + "0x8afcd552709bac70a470ec1d137d535bfa4fadee", + "78365538823" + ], + [ + "0x253ab8294bf3fb6ab6439abc9bc7081504db9bff", + "44573289187" + ], + [ + "0x79645bfb4ef32902f4ee436a23e4a10a50789e54", + "24273580464" + ], + [ + "0x2be2273452ce4c80c0f9e9180d3f0d6eedfa7923", + "17411461677" + ], + [ + "0x0bfd9fc73c82be0558f3a651f10a8bd8c784f45e", + "15927533063" + ], + [ + "0xe7baf7af12e6b18c8cdd32292c6f06840cf71442", + "14586805595" + ], + [ + "0xa82240bb0291a8ef6e46a4f6b8abf4737b0b5257", + "10000000000" + ], + [ + "0x044c53d8576d4d700e6327c954f88388ee03b8db", + "9655048867" + ], + [ + "0xaa4f23a13f25e88ba710243dd59305f382376252", + "8798351793" + ], + [ + "0x3c7cfaf3680953f8ca3c7e319ac2a4c35870e86c", + "6416085500" + ], + [ + "0x23444f470c8760bef7424c457c30dc2d4378974b", + "5670131987" + ], + [ + "0xb8da309775c696576d26ef7d25b68c103a9ab0d5", + "5240156695" + ], + [ + "0xaf616daba40f81b75af5373294d4dbe29dd0e0f6", + "4334685782" + ], + [ + "0x1860a5c708c1e982e293aa4338bdbcafb7cb90ac", + "4269000000" + ], + [ + "0x8687c54f8a431134cde94ae3782cb7cba9963d12", + "3640000000" + ], + [ + "0x93be7761f4c7153bc462a50f9eb5eb424c39c2cd", + "2368110074" + ], + [ + "0x82fcd7cd3151b0ab9e4c00629f123d45ad17fa73", + "2105369400" + ], + [ + "0xf658305d26c8df03e9ed3ff7c7287f7233de472d", + "1866470834" + ], + [ + "0xcd5561b1be55c1fa4bba4749919a03219497b6ef", + "1309882178" + ], + [ + "0x9821aac07d0724c69835367d596352aaf09c309c", + "1005037990" + ], + [ + "0x575c9606cfccf6f93d2e5a0c37d2c7696bcab132", + "983699606" + ], + [ + "0xd8d1fa915826a24d6103e8d0fa04020c4ebc0c5e", + "936175040" + ], + [ + "0x8bea73aac4f7ef9daded46359a544f0bb2d1364f", + "882175040" + ], + [ + "0xb9488bb4f6b57093eaa9a0cf0d722ed61e8039ac", + "795009391" + ], + [ + "0xf05b641229bb2aa63b205ad8b423a390f7ef05a7", + "726877197" + ], + [ + "0x9142a918df6208ae1be65e2be0ea9dad6067155e", + "567271172" + ], + [ + "0x76e3d82b0c49f1c921d8c1093cd91c20ba23740d", + "510000000" + ], + [ + "0x9b0f5ccc13fa9fc22ab6c4766e419bb2a881eb1b", + "496000000" + ], + [ + "0x24294915f8b5831d710d40c277916edc0fa0ec39", + "336422082" + ], + [ + "0xb1d47d39c3bb868e5e4be068b7057d4caad0b31c", + "295066819" + ], + [ + "0x4b9184df8fa9f3fc008fcde7e7bbf7208ef5118d", + "100000000" + ], + [ + "0x3d93420aa8512e2bc7d77cb9352d752881706638", + "95422611" + ], + [ + "0xc42593f89d4b6647bff86fa309c72d5e93a9405c", + "50000000" + ], + [ + "0xf2f65a8a44f0bb1a634a85b1a4eb4be4d69769b6", + "12568525" + ], + [ + "0xc896e266368d3eb26219c5cc74a4941339218d86", + "957695" + ], + [ + "0x542a94e6f4d9d15aae550f7097d089f273e38f85", + "138988" + ], + [ + "0x40ca67ba095c038b711ad37bbebad8a586ae6f38", + "62697" + ], + [ + "0x1397c24478cbe0a54572adec2a333f87ad75ac02", + "43337" + ], + [ + "0xa6a0bed0732c49bd847b4b308daac15640f1ec6e", + "7802" + ], + [ + "0xf8fdcac2c64ba5e0459f67b9610bd3eda11f04ba", + "5894" + ], + [ + "0xd67acddb195e31ad9e09f2cbc8d7f7891a6d44bf", + "276" + ], + [ + "0x3dd413fd4d03b1d8fd2c9ed34553f7dec3b26f5c", + "9" + ], + [ + "0xd970ba10ed5e88b678cd39fa37daa765f6948733", + "1" + ] +] \ No newline at end of file diff --git a/protocol/reseed/data/r2/L2_external_unripe_lp_balances.json b/protocol/reseed/data/r2/L2_external_unripe_lp_balances.json new file mode 100644 index 000000000..5048f2022 --- /dev/null +++ b/protocol/reseed/data/r2/L2_external_unripe_lp_balances.json @@ -0,0 +1,25 @@ +[ + ["0xc1e088fc1323b20bcbee9bd1b9fc9546db5624c5", "68338152592140"], + ["0x1085057e6d9ad66e73d3cc788079155660264152", "203120992714"], + ["0xe6f00dde5f7622298c16a9e39b471d1c1c2de250", "120581249548"], + ["0x8fe7261b58a691e40f7a21d38d27965e2d3afd6e", "58799943357"], + ["0xaf616daba40f81b75af5373294d4dbe29dd0e0f6", "49387419081"], + ["0xf658305d26c8df03e9ed3ff7c7287f7233de472d", "32130269456"], + ["0xc6ac7c7acabc3585cfe16478fd4d22c1e8dc3c57", "20951803116"], + ["0xd8388ad2ff4c781903b6d9f17a60daf4e919f2ce", "18909808200"], + ["0x52c9a7e7d265a09db125b7369bc7487c589a7604", "13915586466"], + ["0xb33cb651648a99f2ffff076fd3f645fac24d460f", "9737535811"], + ["0xf2f65a8a44f0bb1a634a85b1a4eb4be4d69769b6", "7652021349"], + ["0x0bfd9fc73c82be0558f3a651f10a8bd8c784f45e", "6863712510"], + ["0x9821aac07d0724c69835367d596352aaf09c309c", "6757145778"], + ["0x5f683bd8e397e11858dab751eca248e5b2afc522", "6104281597"], + ["0x9142a918df6208ae1be65e2be0ea9dad6067155e", "2986538692"], + ["0x7f538566f85310c901172142e8a9a892f0eaf946", "2951663131"], + ["0x575c9606cfccf6f93d2e5a0c37d2c7696bcab132", "2356468230"], + ["0x76e3d82b0c49f1c921d8c1093cd91c20ba23740d", "2233000000"], + ["0xa86e29ad86d690f8b5a6a632cab8405d40a319fa", "1755275296"], + ["0xb9488bb4f6b57093eaa9a0cf0d722ed61e8039ac", "651392713"], + ["0xd45accf4512af9ceac4c3ab0e770f54212cdf9ac", "500000000"], + ["0x542a94e6f4d9d15aae550f7097d089f273e38f85", "614013"], + ["0x40ca67ba095c038b711ad37bbebad8a586ae6f38", "605736"] +] diff --git a/protocol/reseed/data/mocks/r3/L2_initial_supply.json b/protocol/reseed/data/r2/L2_initial_supply.json similarity index 100% rename from protocol/reseed/data/mocks/r3/L2_initial_supply.json rename to protocol/reseed/data/r2/L2_initial_supply.json diff --git a/protocol/reseed/data/mocks/r3/L2_well_balances.json b/protocol/reseed/data/r2/L2_well_balances.json similarity index 100% rename from protocol/reseed/data/mocks/r3/L2_well_balances.json rename to protocol/reseed/data/r2/L2_well_balances.json diff --git a/protocol/reseed/data/r3/L2_external_unripe_balances.json b/protocol/reseed/data/r3/L2_external_unripe_balances.json deleted file mode 100644 index f9d85971d..000000000 --- a/protocol/reseed/data/r3/L2_external_unripe_balances.json +++ /dev/null @@ -1,10 +0,0 @@ -[ - [ - ["0x000000009d3a9e5c7c620514e1f36905c4eb91e5", "1000000"], - ["0x000000009d3a9e5c7c620514e1f36905c4eb91e5", "1000000"] - ], - [ - ["0x000000009d3a9e5c7c620514e1f36905c4eb91e5", "1000000"], - ["0x000000009d3a9e5c7c620514e1f36905c4eb91e5", "1000000"] - ] -] \ No newline at end of file diff --git a/protocol/reseed/data/r3/L2_initial_supply.json b/protocol/reseed/data/r3/L2_initial_supply.json deleted file mode 100644 index 8205bcacd..000000000 --- a/protocol/reseed/data/r3/L2_initial_supply.json +++ /dev/null @@ -1 +0,0 @@ -["10000000000", "10000000000", "10000000000"] diff --git a/protocol/reseed/data/r3/L2_well_balances.json b/protocol/reseed/data/r3/L2_well_balances.json deleted file mode 100644 index 7e9a48bab..000000000 --- a/protocol/reseed/data/r3/L2_well_balances.json +++ /dev/null @@ -1,5 +0,0 @@ -[ - ["1000000000", "10000000000000"], - ["1000000000", "1000000000000"], - ["1000000000", "1000000000"] -] diff --git a/protocol/reseed/data/r2/pod-listings.json b/protocol/reseed/data/r3/pod-listings.json similarity index 100% rename from protocol/reseed/data/r2/pod-listings.json rename to protocol/reseed/data/r3/pod-listings.json diff --git a/protocol/reseed/data/r2/pod-orders.json b/protocol/reseed/data/r3/pod-orders.json similarity index 100% rename from protocol/reseed/data/r2/pod-orders.json rename to protocol/reseed/data/r3/pod-orders.json diff --git a/protocol/reseed/dataConverts/convertExternalHolders.js b/protocol/reseed/dataConverts/convertExternalHolders.js new file mode 100644 index 000000000..f4d0cbefe --- /dev/null +++ b/protocol/reseed/dataConverts/convertExternalHolders.js @@ -0,0 +1,21 @@ +const fs = require("fs"); + +function parseExternalHolders(inputFilePath, outputFilePath, contractAccounts) { + try { + const data = fs.readFileSync(inputFilePath, "utf8"); + const rows = data.trim().split("\n"); + const result = rows + .map((row) => row.split(",")) // Split each row by comma to get [address, balance] + .filter(([address]) => !contractAccounts.includes(address)) // Exclude contract accounts + .map(([address, balance]) => [address.trim(), balance.trim()]); // Trim any excess spaces + // Write the result to the output file as JSON + // Remove the first entry in the array as it is the header + result.shift(); + fs.writeFileSync(outputFilePath, JSON.stringify(result, null, 2)); + console.log("External holders JSON parsed successfully."); + } catch (err) { + console.error("Error:", err); + } +} + +exports.parseExternalHolders = parseExternalHolders; diff --git a/protocol/reseed/reseed2.js b/protocol/reseed/reseed2.js index bb9cd35d2..c72117189 100644 --- a/protocol/reseed/reseed2.js +++ b/protocol/reseed/reseed2.js @@ -14,9 +14,10 @@ const { const { deployBasinV1_2Components, deployUpgradeableWell } = require("../scripts/basinV1_2.js"); // Files -const INIT_SUPPLY = "./reseed/data/mocks/r3/L2_initial_supply.json"; -const INIT_WELL_BALANCES = "./reseed/data/mocks/r3/L2_well_balances.json"; -const EXTERNAL_UNRIPE = "./reseed/data/mocks/r3/L2_external_unripe_balances.json"; +const INIT_SUPPLY = "./reseed/data/r2/L2_initial_supply.json"; +const INIT_WELL_BALANCES = "./reseed/data/r2/L2_well_balances.json"; +const EXTERNAL_UNRIPE_BEAN = "./reseed/data/r2/L2_external_unripe_balances.json"; +const EXTERNAL_UNRIPE_BEAN_LP = "./reseed/data/r2/L2_external_unripe_lp_balances.json"; /** * reseed8 approves beanstalk to use the BCM's wsteth, eth, and a stablecoin, @@ -31,7 +32,8 @@ async function reseed2(account, L2Beanstalk, deployBasin = true, fertilizerImple [ethInBeanEthWell, wstEthInBeanWstEthWell, stableInBeanStableWell] = JSON.parse( await fs.readFileSync(INIT_WELL_BALANCES) ); - [urBean, urBeanLP] = JSON.parse(await fs.readFileSync(EXTERNAL_UNRIPE)); + externalUrBean = JSON.parse(await fs.readFileSync(EXTERNAL_UNRIPE_BEAN)); + externalUrBeanLP = JSON.parse(await fs.readFileSync(EXTERNAL_UNRIPE_BEAN_LP)); // mint: let weth, wsteth, stable, owner; @@ -68,8 +70,8 @@ async function reseed2(account, L2Beanstalk, deployBasin = true, fertilizerImple beanSupply, unripeBeanSupply, unripeLpSupply, - urBean, - urBeanLP, + externalUrBean, + externalUrBeanLP, fertilizerImplementation ], bip: false, diff --git a/protocol/reseed/reseed3.js b/protocol/reseed/reseed3.js index 6d59dd383..1c68eee13 100644 --- a/protocol/reseed/reseed3.js +++ b/protocol/reseed/reseed3.js @@ -9,8 +9,8 @@ async function reseed3(account, L2Beanstalk, mock) { let podListingsPath; let podOrdersPath; if (mock) { - podListingsPath = "./reseed/data/mocks/r2/pod-listings-mock.json"; - podOrdersPath = "./reseed/data/mocks/r2/pod-orders-mock.json"; + podListingsPath = "./reseed/data/mocks/r3/pod-listings-mock.json"; + podOrdersPath = "./reseed/data/mocks/r3/pod-orders-mock.json"; } else { podListingsPath = "./reseed/data/r2/pod-listings.json"; podOrdersPath = "./reseed/data/r2/pod-orders.json"; diff --git a/protocol/reseed/reseedL2.js b/protocol/reseed/reseedL2.js index 365b2f516..22dc3ef42 100644 --- a/protocol/reseed/reseedL2.js +++ b/protocol/reseed/reseedL2.js @@ -5,6 +5,7 @@ const { parseDeposits } = require("./dataConverts/convertDeposits.js"); const { parseFertilizer } = require("./dataConverts/convertFert.js"); const { parsePodMarketplace } = require("./dataConverts/convertPodMarketplace.js"); const { parseGlobals } = require("./dataConverts/convertGlobal.js"); +const { parseExternalHolders } = require("./dataConverts/convertExternalHolders.js"); const { reseedDeployL2Beanstalk } = require("./reseedDeployL2Beanstalk.js"); const { reseed2 } = require("./reseed2.js"); const { reseed3 } = require("./reseed3.js"); @@ -147,6 +148,8 @@ function parseBeanstalkData() { const storageFertPath = `./reseed/data/exports/storage-fertilizer${BLOCK_NUMBER}.json`; const storageSystemPath = `./reseed/data/exports/storage-system${BLOCK_NUMBER}.json`; const marketPath = "./reseed/data/exports/market-info20330000.json"; + const externalUnripeHoldersPath = "./reseed/data/exports/externalHolders/unripeBeanHolders.csv"; + const externalUnripeLpHoldersPath = "./reseed/data/exports/externalHolders/unripeLpHolders.csv"; parseGlobals(storageSystemPath, "./reseed/data/global.json"); parseAccountStatus(storageAccountsPath, "./reseed/data/r7-account-status.json", contractAccounts); parseInternalBalances( @@ -159,8 +162,18 @@ function parseBeanstalkData() { parseField(storageAccountsPath, "./reseed/data/r4-field.json", contractAccounts); parsePodMarketplace( marketPath, - "./reseed/data/r2/pod-listings.json", - "./reseed/data/r2/pod-orders.json" + "./reseed/data/r3/pod-listings.json", + "./reseed/data/r3/pod-orders.json" + ); + parseExternalHolders( + externalUnripeHoldersPath, + "./reseed/data/r2/L2_external_unripe_balances.json", + contractAccounts + ); + parseExternalHolders( + externalUnripeLpHoldersPath, + "./reseed/data/r2/L2_external_unripe_lp_balances.json", + contractAccounts ); } From 8d82ff8e29670ae3e326c87a0c7bdb5755241363 Mon Sep 17 00:00:00 2001 From: nickkatsios Date: Tue, 10 Sep 2024 11:38:37 +0300 Subject: [PATCH 28/36] add getWellTwaUsdLiquidityFromReserves decimals fix --- protocol/contracts/libraries/Well/LibWell.sol | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/protocol/contracts/libraries/Well/LibWell.sol b/protocol/contracts/libraries/Well/LibWell.sol index b6b87c454..f5c30ee46 100644 --- a/protocol/contracts/libraries/Well/LibWell.sol +++ b/protocol/contracts/libraries/Well/LibWell.sol @@ -162,8 +162,15 @@ library LibWell { // if the function reaches here, then this is called outside the sunrise function // (i.e, seasonGetterFacet.getLiquidityToSupplyRatio()).We use LibUsdOracle // to get the price. This should never be reached during sunrise and thus - // should not impact gas. - return LibUsdOracle.getTokenPrice(token).mul(twaReserves[j]).div(1e6); + // should not impact gas. + // LibUsdOracle returns the price with 6 decimal precision. + // This is canceled out by dividing by 1e6. + // This block is then used in calcLPToSupplyRatio that assumes 18 decimal precision, + // so we need to account for whitelisted tokens that have less than 18 decimals by multiplying the + // precision difference. + + uint8 tokenDecimals = IERC20Decimals(token).decimals(); + return LibUsdOracle.getTokenPrice(token).mul(twaReserves[j]).div(1e6).mul(10**(18 - tokenDecimals)); } /** From 95e25f4beb0b386f4a895480b70e0eaad5bd5db5 Mon Sep 17 00:00:00 2001 From: nickkatsios Date: Tue, 10 Sep 2024 11:45:43 +0300 Subject: [PATCH 29/36] clarify function in comment --- protocol/contracts/libraries/Well/LibWell.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/protocol/contracts/libraries/Well/LibWell.sol b/protocol/contracts/libraries/Well/LibWell.sol index f5c30ee46..78c98ccd1 100644 --- a/protocol/contracts/libraries/Well/LibWell.sol +++ b/protocol/contracts/libraries/Well/LibWell.sol @@ -165,7 +165,7 @@ library LibWell { // should not impact gas. // LibUsdOracle returns the price with 6 decimal precision. // This is canceled out by dividing by 1e6. - // This block is then used in calcLPToSupplyRatio that assumes 18 decimal precision, + // This return value is then used in LibEvaluate.calcLPToSupplyRatio that assumes 18 decimal precision, // so we need to account for whitelisted tokens that have less than 18 decimals by multiplying the // precision difference. From 5297b6f5f3cb1b68a2854a8e5cf760d1081e6cff Mon Sep 17 00:00:00 2001 From: nickkatsios Date: Tue, 10 Sep 2024 08:49:16 +0000 Subject: [PATCH 30/36] prettier auto formatting changes --- protocol/contracts/libraries/Well/LibWell.sol | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/protocol/contracts/libraries/Well/LibWell.sol b/protocol/contracts/libraries/Well/LibWell.sol index 78c98ccd1..34ee6ab8d 100644 --- a/protocol/contracts/libraries/Well/LibWell.sol +++ b/protocol/contracts/libraries/Well/LibWell.sol @@ -162,15 +162,18 @@ library LibWell { // if the function reaches here, then this is called outside the sunrise function // (i.e, seasonGetterFacet.getLiquidityToSupplyRatio()).We use LibUsdOracle // to get the price. This should never be reached during sunrise and thus - // should not impact gas. + // should not impact gas. // LibUsdOracle returns the price with 6 decimal precision. // This is canceled out by dividing by 1e6. // This return value is then used in LibEvaluate.calcLPToSupplyRatio that assumes 18 decimal precision, - // so we need to account for whitelisted tokens that have less than 18 decimals by multiplying the + // so we need to account for whitelisted tokens that have less than 18 decimals by multiplying the // precision difference. uint8 tokenDecimals = IERC20Decimals(token).decimals(); - return LibUsdOracle.getTokenPrice(token).mul(twaReserves[j]).div(1e6).mul(10**(18 - tokenDecimals)); + return + LibUsdOracle.getTokenPrice(token).mul(twaReserves[j]).div(1e6).mul( + 10 ** (18 - tokenDecimals) + ); } /** From 2107a15879119b3c95c8295eafc10435b0972bfc Mon Sep 17 00:00:00 2001 From: nickkatsios Date: Tue, 10 Sep 2024 13:03:34 +0300 Subject: [PATCH 31/36] deploy L1RecieverFacet in reseed10 --- protocol/reseed/reseed10.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/protocol/reseed/reseed10.js b/protocol/reseed/reseed10.js index 43b193a2d..65a703b1b 100644 --- a/protocol/reseed/reseed10.js +++ b/protocol/reseed/reseed10.js @@ -30,7 +30,8 @@ async function reseed10(account, L2Beanstalk, mock, verbose = true) { "FertilizerFacet", // BARN "UnripeFacet", "EnrootFacet", - "PauseFacet" // DIAMOND + "PauseFacet", // DIAMOND + "L1RecieverFacet" // MIGRATION ]; // A list of public libraries that need to be deployed separately. From 030dfe26f752a37045d79145adf96971a2a8a95f Mon Sep 17 00:00:00 2001 From: nickkatsios Date: Tue, 10 Sep 2024 13:04:25 +0300 Subject: [PATCH 32/36] remove bean holders --- .../exports/externalHolders/beanHolders.csv | 181 ------------------ 1 file changed, 181 deletions(-) delete mode 100644 protocol/reseed/data/exports/externalHolders/beanHolders.csv diff --git a/protocol/reseed/data/exports/externalHolders/beanHolders.csv b/protocol/reseed/data/exports/externalHolders/beanHolders.csv deleted file mode 100644 index f0bbb0aa1..000000000 --- a/protocol/reseed/data/exports/externalHolders/beanHolders.csv +++ /dev/null @@ -1,181 +0,0 @@ -account,balance -0xc1e088fc1323b20bcbee9bd1b9fc9546db5624c5,33161330588151 -0xbea0000113b0d182f4064c86b71c315389e4715d,14334525518260 -0x66efac6e6d58d4058cf017e66a0039315a3eb29c,2453000000000 -0xbea0e11282e2bb5893bece110cf199501e872bad,110674154956 -0xc9c32cd16bf7efb85ff14e0c8603cc90f6f2ee49,81254060564 -0x21de18b6a8f78ede6d16c50a167f6b222dc08df7,80522986118 -0x43b9f935c798522aaacb2bfea2f407ce5a291e9d,80400000000 -0x25c1278454254f783ef8760987db8de0268c6cbe,15896705546 -0x87c5e5413d60e1419fd70b17c6d299aa107efb49,12249000000 -0x23e59a5b174ab23b4d6b8a1b44e60b611b0397b6,10500617337 -0x498b859d2e59958e209d7dd262324c8d31b12b12,10154884037 -0xbd01f3494ff4f5b6aca5689cc6220e68d684f146,8076504768 -0xe68cf6eb200759349f5a367b38d6453727fd5e9a,7443525537 -0x7119f398b6c06095c6e8964c1f58e7c1baa79e18,5800000000 -0xbfe4ec1b5906d4be89c3f6942d1c6b04b19de79e,5707669485 -0xc18bab9f644187505f391e394768949793e9894f,5253544581 -0x87f4ca3e6768075ed87a8c4473890320af14ccf0,4039961627 -0x4cc19a7a359f2ff54ff087f03b6887f436f08c11,3878850000 -0x103cba62b51f02310f8ea33a624b948b6c1454bf,3000000000 -0xa4f6638cde88f245b75670b510fd8e46fafd1678,2518835194 -0x94f335a00f00d79b26336fa1c77bab6ae96f08c5,2321368905 -0x1b15ed3612cd3077ba4437a1e2b924c33d4de0f9,2082981694 -0x7c27a1f60b5229340bc57449cfb91ca496c3c1c1,1878848136 -0x979fee925e1d2531b8efa247c42e64fd1d670241,1502525730 -0xd67acddb195e31ad9e09f2cbc8d7f7891a6d44bf,1466680000 -0x47e6b4a6cb47eb7c7d30820c7c460183cf7abd5b,1000000000 -0x19a4fe7d0c76490cca77b45580846cdb38b9a406,992594251 -0x558c4aff233f17ac0d25335410faea0453328da8,926096318 -0xba27669908796b306f00df72e3041e6c41f32b4f,875840231 -0x11dd6f9e1a7bb35a61fada4aec645f603050783e,812842419 -0x2e6cbcfa99c5c164b0af573bc5b07c8bed18c872,704692374 -0xf2d47e78dea8e0f96902c85902323d2a2012b0c0,667305944 -0x251fae8f687545bdd462ba4fcdd7581051740463,581979838 -0xc8d71db19694312177b99fb5d15a1d295b22671a,503360000 -0x12b1c89124af9b720c1e3e8e31492d66662bf040,499897010 -0x87316f7261e140273f5fc4162da578389070879f,469224030 -0x7d6d548fad925c3b2f0a500b290557c7be424c12,427770050 -0xd53adf794e2915b4f414be1ab2282ca8da56dcfd,415462447 -0xcbd7712d9335a7a38f35b38d5dc9b5970f04e8fd,348815519 -0xd2f2f6b0f48e7a12496d8c9f7a2c18e6b76e49e0,341572105 -0xdecaf1d3c1b16e1ff8bc8fdc8d80d286d335e32e,334700488 -0xc0c0514363049224093ec8b610c00f292d80b621,256688000 -0x6eeca4051666ece16df7a7a2e3948119c98a002e,256186307 -0x30cb1e845f6c03b988ec677a75700e70a019e2e4,253222101 -0x6cc9b3940eb6d94cad1a25c437d9be966af821e3,252740579 -0x414a26eaa23583715d71b3294f0bf5eabdd2eaa8,248479164 -0xe65caecfe1626bf65f66fb4ec3c5d588a90022cb,234894994 -0x06470cc9f84375233d7fac12c6fce199ce632dd6,210942792 -0x58737a9b0a8a5c8a2559c457fcc9e923f9d99fb7,210411000 -0x82f402847051bddaab0f5d4b481417281837c424,194562223 -0x71b49dd7e69cd8a1e81f7a1e3012c7c12195b7f9,184893677 -0xdff58819ab64c79d5276e4052d3e74aca493658d,174333575 -0x9008d19f58aabd9ed0d60971565aa8510560ab41,141825758 -0x77ab999d1e9f152156b4411e1f3e2a42dab8cd6d,141020150 -0x072fa8a20fa621665b94745a8075073ceadfe1dc,135661772 -0xe4452cb39ad3faa39434b9d768677b34dc90d5dc,120489386 -0xb4a939498e00fc637ea6d23dacf1256539c503e3,116750712 -0xd5ae1639e5ef6ecf241389894a289a7c0c398241,113870222 -0x38c5ca4ee678d4f9d8d94a7f238e2700a8978b36,112679026 -0x75a158b6939d9abc27b5e3ea9e79c11302cec60c,111566830 -0x202eca424a8db90924a4daa3e6bcecd9311f668e,109321301 -0x7d6a2f6d7c2f7dd51c47b5ea9faa3ae208185ec7,100000000 -0xcb026b53c4674637663e85603e95ae539bd1bd2a,100000000 -0xb47959506850b9b34a8f345179ed1c932aaa8bfa,96540240 -0x9f1f4714d07859dd4c8d1312881a0700ed1c2a7e,87535611 -0xacc53f19851ce116d52b730aee8772f7bd568821,84269970 -0x9ae3821d72b53f767f5b72c9630ce864c54c09bc,80000000 -0x575c9606cfccf6f93d2e5a0c37d2c7696bcab132,77529516 -0x9821aac07d0724c69835367d596352aaf09c309c,76096126 -0xde975401d53178cdf36e1301da633a8f82c33cef,70408755 -0x3c58492ad9cad0d9f8570a80b6a1f02c0c1da2c5,70301838 -0x46387563927595f5ef11952f74dcc2ce2e871e73,61000195 -0x88f667664e61221160ddc0414868ef2f40e83324,54207252 -0xdb2480a43c79126f93bd5a825dc0cba46d7c0612,50116489 -0xaa4f23a13f25e88ba710243dd59305f382376252,49703615 -0x88fff68c3ee825a7a59f20bfea3c80d1ac09bef1,48278967 -0x7df40fde5e8680c45bfedafcf61dd6962e688562,47939000 -0x7e1ca6d381e2784db210442bfc3e2b1451f773fd,46637594 -0x047b22bfe547d29843c825dbcbd9e0168649d631,46303468 -0xf662972ff1a9d77dcdfba640c1d01fa9d6e4fb73,42183000 -0x8521cfdfd0fd1ac18520fa8f262eb948d4420c8a,42000000 -0x0716a17fbaee714f1e6ab0f9d59edbc5f09815c0,42000000 -0x23caea94eb856767cf71a30824d72ed5b93aa365,36518180 -0x876133657f5356e376b7ae27d251444727ce9488,35054599 -0xa7194f754b5befc3277d6bfa258028450da654ba,33043500 -0x4779c6a1cb190221fc152af4b6adb2ea5c5dbd88,29137817 -0xe4000004000bd8006e00720000d27d1fa000d43e,29031846 -0xb5d0374f0c35cf84f495121f5d29ea9275414de8,28362442 -0x548e13ddc5e2c6bc9456648a9a487da335b6ec25,27891707 -0x3789c64cc3a8120a93e9483d526d44be7305e455,27891707 -0x87a774178d49c919be273f1022de2ae106e2581e,26000000 -0x58d37a1f4f38f20e841e17e7c610eb494cc1f8de,25950320 -0x87263a1ac2c342a516989124d0dba63df6d0e790,23288715 -0x4af7c12c7e210f4cb8f2d8e340aaadae05a9f655,23271000 -0xcdea6a23b9383a88e246975ad3f38778ee0e81fc,23049092 -0x7a68a90a71413e12db9cc23fac37e9608ca48f48,22715605 -0xf9563a8dab33f6beab2abc34631c4eaf9ecc8b99,20907127 -0x6691fb80b87b89e3ea3e7c9a4b19fdb2d75c6aad,20103791 -0xa50a686bcfcdd1eb5b052c6e22c370ea1153cc15,18099438 -0x6b99a6c6081068aa46a420fdb6cfbe906320fa2d,17626050 -0xee98b8ac30896ba4b3c0d34b28536636b770d5f7,17014350 -0xc99a41144b5de2a9d0c3cc5338f8f94912352999,16559396 -0x769a8fd17ecb067a88744eee3eef1059c79df206,15211005 -0x8d97775623368f833f8fa82209e220f1c60508ea,15000000 -0xc4ff293174198e9aeb8f655673100eeedcbbfb1a,14680787 -0x00f244126b1f29b50d45464f08de883f1ff2fb7c,14234465 -0x64707d044389a2c00f5296b93ad3a7f6fd073bee,12682814 -0x1125eac5f713503e2b7cb2299027960ce1aa5d42,12633543 -0x54c04c9bf5af0bc3096cb0af24c4fa8379a2915e,12388488 -0xdf9c4a067279857b463817ef773fe189c77e1686,12000000 -0x78320e6082f9e831dd3057272f553e143dfe5b9c,11510958 -0x63b98c09120e4ef75b4c122d79b39875f28a6fcc,11500608 -0x682864c9bc8747c804a6137d6f0e8e087f49089e,11048400 -0x905eafe9434fabacaf10d1490fcd0d1eb9b85fc8,11000000 -0x961ea5962b8608dafd037f303a5fb4a4fd81bac7,10182124 -0x795781de02f10d8343baf897fbb4e6a755b4ecb9,10081325 -0xaf7ed02de4b8a8967b996df3b8bf28917b92edcd,9324600 -0x854e4406b9c2cfdc36a8992f1718e09e5f0d2371,9104148 -0x41cc24b4e568715f33fe803a6c3419708205304d,7566819 -0xc52a0b002ac4e62be0d269a948e55d126a48c767,6891274 -0x99bfdb688d53891d6e9e716eace90fa233a83500,6690000 -0xf8d5708b32616b6c85c97f5a9c344e6b7076fe98,6227809 -0x729ad565b305be00729e0a5677401dca268e6d8a,6101062 -0x9b1ac8e6d08053c55713d9aa8fde1c53e9a929e2,6056743 -0x4088e870e785320413288c605fd1bd6bd9d5bdae,5674104 -0x0da2a82ed2c387d1751ccbaf999a80b65bdb269e,4579053 -0x39041f1b366fe33f9a5a79de5120f2aee2577ebc,4255327 -0xd130ab894366e4376b1afe3d52638a1087be17f4,4006187 -0xbb11017d4bcb67cf083b13b5bcdb4fe121038227,3735321 -0xb6cc924486681a1ca489639200dceb4c41c283d3,3551588 -0x00ca340d789f00d4c978b236606c3105a09254f8,2995098 -0x3aa228a80f50763045bdfc45012da124bd0a6809,2130668 -0x00000000009726632680fb29d3f7a9734e3010e2,2130169 -0x7b5fe7af8315acb2e37b1f343cf6f4b225fa9878,2077799 -0x8a9c930896e453ca3d87f1918996423a589dd529,2011323 -0xc5581f1ae61e34391824779d505ca127a4566737,1816599 -0x4282341588f94c158bfaa40ae2c9f3abfdac647f,1795049 -0x7c28e0977f72c5d08d5e1ac7d52a34db378282b3,1748864 -0x995d1e4e2807ef2a8d7614b607a89be096313916,1645609 -0x4a183b7ed67b9e14b3f45abfb2cf44ed22c29e54,1271235 -0xc12df5f402a8b8beaea49ed9bad9c95fccbfe907,1173526 -0x9249e360dc6f4d2871187acde4fe38d4e13a7703,1058540 -0x9ec255f1af4d3e4a813aadab8ff0497398037d56,1009677 -0x155e6c85fa47a7244b04f3bafa549b55f1909f93,1000000 -0x5c9d09716404556646b0b4567cb4621c18581f94,972133 -0x80b9aa22ccda52f40be998eeb19db4d08fafec3e,922454 -0xb01f8f528702d411d24c9bb8cc0e2fff779ec013,889690 -0x5ec6bc92395bfe4dfb8f45cb129ac0c2f290f23d,796853 -0x5853ed4f26a3fcea565b3fbc698bb19cdf6deb85,751575 -0xb32d57f94542ebfad5073adf62d70d812ddba0a5,268375 -0x88ad88c5b3beae06a248e286d1ed08c27e8b043b,254632 -0x8e8ae083ac4455108829789e8acb4dbdde330e2e,200000 -0x8d4122ffe442de3574871b9648868c1c3396a0af,186429 -0x820a2943762236e27a3a2c6ea1024117518895a5,100000 -0x0ce72b7dde6ea0e9e8feeb634fcd9245e81d34f3,86451 -0x6d11937490234176e6229c4b80b27fedf237465f,66150 -0x14567c85977847836c17dd609a9bd767f3f03b51,60422 -0xdd9f24efc84d93deef3c8745c837ab63e80abd27,58177 -0x542a94e6f4d9d15aae550f7097d089f273e38f85,32581 -0x19cf79e47c31464ac0b686913e02e2e70c01bd5c,9019 -0xb1f0e758951a02b24d04dd211d0424445ae04c5c,8764 -0x18ad8a3387aac16c794f3b14451c591fef0344fe,6488 -0x40ca67ba095c038b711ad37bbebad8a586ae6f38,2252 -0xc1fe2bb036e3fc9eddcc83304dbe752881087cdf,98 -0x4c366e92d46796d14d658e690de9b1f54bfb632f,70 -0x5c2e7837a5dc5d07c6977bfedb46a1f3ec6a5a77,58 -0x6e93e171c5223493ad5434ac406140e89bd606de,33 -0xe6b1de575e7e610889ea21024834e120f92033a3,11 -0x22a956c4755d8c4294b358dc346e74250e175622,5 -0x3face0004bc1003b9d0672e7b23134cb80115fb6,2 -0x9edaff6744d6f539298cddd8c0171b774be2b86d,2 -0x0b3f6d4a5d6835137ccb2c1248f5a7d882c0dbda,1 -0xf0d4c12a5768d806021f80a262b4d39d26c58b8d,1 -0xe2dc368cf962426efa08b60c9570b19618b5e672,1 -0x7122db0ebe4eb9b434a9f2ffe6760bc03bfbd0e0,1 -0x1111111254eeb25477b68fb85ed929f73a960582,1 -0x1136b25047e142fa3018184793aec68fbb173ce4,1 -0x3208684f96458c540eb08f6f01b9e9afb2b7d4f0,1 -0x92f3f71cef740ed5784874b8c70ff87ecdf33588,1 -0xe37e799d5077682fa0a244d46e5649f71457bd09,1 From 148cd6c84dbf0e3f72ff974afda7ec809f678f4f Mon Sep 17 00:00:00 2001 From: nickkatsios Date: Tue, 10 Sep 2024 16:08:53 +0300 Subject: [PATCH 33/36] Set only individual receiver internal balance in L1RecieverFacet --- .../contracts/beanstalk/migration/L1RecieverFacet.sol | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/protocol/contracts/beanstalk/migration/L1RecieverFacet.sol b/protocol/contracts/beanstalk/migration/L1RecieverFacet.sol index 1f5119b08..e18e895d7 100644 --- a/protocol/contracts/beanstalk/migration/L1RecieverFacet.sol +++ b/protocol/contracts/beanstalk/migration/L1RecieverFacet.sol @@ -21,6 +21,7 @@ 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 @@ -462,6 +463,9 @@ 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, @@ -469,7 +473,9 @@ contract L1RecieverFacet is ReentrancyGuard { 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])); } } From 940c4a541e2eef14c3152a8f003a58062edbf3d2 Mon Sep 17 00:00:00 2001 From: nickkatsios Date: Tue, 10 Sep 2024 13:17:06 +0000 Subject: [PATCH 34/36] prettier auto formatting changes --- protocol/contracts/beanstalk/migration/L1RecieverFacet.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/protocol/contracts/beanstalk/migration/L1RecieverFacet.sol b/protocol/contracts/beanstalk/migration/L1RecieverFacet.sol index e18e895d7..4ca9bcfe3 100644 --- a/protocol/contracts/beanstalk/migration/L1RecieverFacet.sol +++ b/protocol/contracts/beanstalk/migration/L1RecieverFacet.sol @@ -464,7 +464,7 @@ 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, + * we do not need to update global internal balances here, * only balances for the individual account. */ function addMigratedInternalBalancesToAccount( From 92a65bb3ed2aaff5ed8adf8e7b6e90184922ee59 Mon Sep 17 00:00:00 2001 From: nickkatsios Date: Wed, 11 Sep 2024 10:51:01 +0300 Subject: [PATCH 35/36] add 0 liquidity to update well pumps --- protocol/reseed/reseedAddLiquidityAndTransfer.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/protocol/reseed/reseedAddLiquidityAndTransfer.js b/protocol/reseed/reseedAddLiquidityAndTransfer.js index bff545055..45f289a34 100644 --- a/protocol/reseed/reseedAddLiquidityAndTransfer.js +++ b/protocol/reseed/reseedAddLiquidityAndTransfer.js @@ -63,12 +63,12 @@ async function reseedAddLiquidityAndTransfer(account, L2Beanstalk, mock = true, await token.connect(account).approve(well.address, MAX_UINT256); await bean.connect(account).approve(well.address, MAX_UINT256); // add liquidity to well, to L2 Beanstalk: - console.log(`Adding liquidity to ${WellAddresses[i]} and performing a swap to update the well pump.`); + console.log(`Adding liquidity to ${WellAddresses[i]} and performing an update to the well pump.`); await well .connect(account) .addLiquidity([beanAmounts[i], nonBeanAmounts[i]], 0, L2Beanstalk, MAX_UINT256); - // perform a swap to update the well pumps and avoid "NotInitialized" error. - await well.connect(account).swapFrom(bean.address, token.address, to6("1"), 0, account.address, MAX_UINT256); + // perform a 0 liq addition to update the well pumps and avoid "NotInitialized" error. + await well.connect(account).addLiquidity([0, 0], 0, L2Beanstalk, MAX_UINT256); } } From f6cce8d40482f865118241bfa13bfb0ccfc7a273 Mon Sep 17 00:00:00 2001 From: nickkatsios Date: Wed, 11 Sep 2024 11:05:18 +0300 Subject: [PATCH 36/36] update decimal fix --- protocol/contracts/libraries/Well/LibWell.sol | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/protocol/contracts/libraries/Well/LibWell.sol b/protocol/contracts/libraries/Well/LibWell.sol index 34ee6ab8d..65aa88acf 100644 --- a/protocol/contracts/libraries/Well/LibWell.sol +++ b/protocol/contracts/libraries/Well/LibWell.sol @@ -163,17 +163,15 @@ library LibWell { // (i.e, seasonGetterFacet.getLiquidityToSupplyRatio()).We use LibUsdOracle // to get the price. This should never be reached during sunrise and thus // should not impact gas. - // LibUsdOracle returns the price with 6 decimal precision. - // This is canceled out by dividing by 1e6. - // This return value is then used in LibEvaluate.calcLPToSupplyRatio that assumes 18 decimal precision, - // so we need to account for whitelisted tokens that have less than 18 decimals by multiplying the - // precision difference. + // LibUsdOracle returns the price with 1e6 precision. + // twaReserves has the same decimal precision as the token. + // The return value is then used in LibEvaluate.calcLPToSupplyRatio that assumes 18 decimal precision, + // so we need to account for whitelisted tokens that have less than 18 decimals by dividing the + // precision by the token decimals. + // Here tokenUsd = 1 so 1e6 * 1eN * 1e12 / 1eN = 1e18. uint8 tokenDecimals = IERC20Decimals(token).decimals(); - return - LibUsdOracle.getTokenPrice(token).mul(twaReserves[j]).div(1e6).mul( - 10 ** (18 - tokenDecimals) - ); + return LibUsdOracle.getTokenPrice(token).mul(twaReserves[j]).mul(1e12).div(10 ** tokenDecimals); } /**