From ef775a966d54c09b00302d1c53fdf1e5b553a035 Mon Sep 17 00:00:00 2001 From: Brian <90539204+Brean0@users.noreply.github.com> Date: Fri, 4 Aug 2023 21:00:07 -0500 Subject: [PATCH 01/13] Revert "Revert "Bean Eth Price"" --- protocol/abi/Beanstalk.json | 14 +- .../contracts/beanstalk/init/InitDiamond.sol | 1 + .../ecosystem/price/BeanstalkPrice.sol | 13 +- .../contracts/ecosystem/price/WellPrice.sol | 80 ++++ protocol/scripts/impersonate.js | 18 +- protocol/test/LegacyClaim.test.js | 3 - protocol/test/beanstalkPrice.test.js | 383 ++++++++++++++++++ protocol/test/utils/constants.js | 3 +- protocol/test/utils/helpers.js | 11 + 9 files changed, 509 insertions(+), 17 deletions(-) create mode 100644 protocol/contracts/ecosystem/price/WellPrice.sol create mode 100644 protocol/test/beanstalkPrice.test.js diff --git a/protocol/abi/Beanstalk.json b/protocol/abi/Beanstalk.json index 175157c655..5f4e26d711 100644 --- a/protocol/abi/Beanstalk.json +++ b/protocol/abi/Beanstalk.json @@ -4375,9 +4375,9 @@ }, { "indexed": false, - "internalType": "int128", + "internalType": "int96", "name": "stem", - "type": "int128" + "type": "int96" }, { "indexed": false, @@ -5692,7 +5692,7 @@ "type": "address" } ], - "name": "getLastStem", + "name": "getLastMowedStem", "outputs": [ { "internalType": "int96", @@ -6025,9 +6025,9 @@ "name": "seasonToStem", "outputs": [ { - "internalType": "int128", + "internalType": "int96", "name": "stem", - "type": "int128" + "type": "int96" } ], "stateMutability": "view", @@ -6057,9 +6057,9 @@ "name": "stemTipForToken", "outputs": [ { - "internalType": "int128", + "internalType": "int96", "name": "_stemTip", - "type": "int128" + "type": "int96" } ], "stateMutability": "view", diff --git a/protocol/contracts/beanstalk/init/InitDiamond.sol b/protocol/contracts/beanstalk/init/InitDiamond.sol index 3e24f537e4..9ff5b506d6 100644 --- a/protocol/contracts/beanstalk/init/InitDiamond.sol +++ b/protocol/contracts/beanstalk/init/InitDiamond.sol @@ -56,6 +56,7 @@ contract InitDiamond { s.season.withdrawSeasons = 25; s.season.period = C.getSeasonPeriod(); s.season.timestamp = block.timestamp; + s.season.stemStartSeason = 0; s.season.start = s.season.period > 0 ? (block.timestamp / s.season.period) * s.season.period : block.timestamp; diff --git a/protocol/contracts/ecosystem/price/BeanstalkPrice.sol b/protocol/contracts/ecosystem/price/BeanstalkPrice.sol index c2b8efff55..b580217850 100644 --- a/protocol/contracts/ecosystem/price/BeanstalkPrice.sol +++ b/protocol/contracts/ecosystem/price/BeanstalkPrice.sol @@ -3,8 +3,10 @@ pragma solidity =0.7.6; pragma experimental ABIEncoderV2; import "./CurvePrice.sol"; +import {WellPrice, C, SafeMath} from "./WellPrice.sol"; -contract BeanstalkPrice is CurvePrice { +contract BeanstalkPrice is CurvePrice, WellPrice { + using SafeMath for uint256; struct Prices { uint256 price; @@ -14,15 +16,16 @@ contract BeanstalkPrice is CurvePrice { } function price() external view returns (Prices memory p) { - p.ps = new P.Pool[](1); + p.ps = new P.Pool[](2); p.ps[0] = getCurve(); + p.ps[1] = getConstantProductWell(C.BEAN_ETH_WELL); - + // assumes that liquidity and prices on all pools uses the same precision. for (uint256 i = 0; i < p.ps.length; i++) { - p.price += p.ps[i].price * p.ps[i].liquidity; + p.price += p.ps[i].price.mul(p.ps[i].liquidity); p.liquidity += p.ps[i].liquidity; p.deltaB += p.ps[i].deltaB; } - p.price /= p.liquidity; + p.price = p.price.div(p.liquidity); } } \ No newline at end of file diff --git a/protocol/contracts/ecosystem/price/WellPrice.sol b/protocol/contracts/ecosystem/price/WellPrice.sol new file mode 100644 index 0000000000..2e61480edf --- /dev/null +++ b/protocol/contracts/ecosystem/price/WellPrice.sol @@ -0,0 +1,80 @@ +//SPDX-License-Identifier: MIT +pragma solidity =0.7.6; +pragma experimental ABIEncoderV2; + +import {P} from "./P.sol"; +import {SafeMath} from "@openzeppelin/contracts/math/SafeMath.sol"; +import {IWell, IERC20} from "../../interfaces/basin/IWell.sol"; +import {IBeanstalkWellFunction} from "../../interfaces/basin/IBeanstalkWellFunction.sol"; +import {LibUsdOracle} from "../../libraries/Oracle/LibUsdOracle.sol"; +import {LibWellMinting} from "../../libraries/Minting/LibWellMinting.sol"; +import {LibWell} from "../../libraries/Well/LibWell.sol"; +import {C} from "../../C.sol"; + +interface IBEANSTALK { + function bdv(address token, uint256 amount) external view returns (uint256); + + function poolDeltaB(address pool) external view returns (int256); +} + +interface dec{ + function decimals() external view returns (uint256); +} + +contract WellPrice { + + using SafeMath for uint256; + + address private constant BEANSTALK = 0xC1E088fC1323b20BCBee9bd1B9fC9546db5624C5; + uint256 private constant WELL_DECIMALS = 1e18; + uint256 private constant PRICE_PRECISION = 1e6; + + struct Pool { + address pool; + address[2] tokens; + uint256[2] balances; + uint256 price; + uint256 liquidity; + int256 deltaB; + uint256 lpUsd; + uint256 lpBdv; + } + + function getConstantProductWell(address wellAddress) public view returns (P.Pool memory pool) { + IWell well = IWell(wellAddress); + pool.pool = wellAddress; + + IERC20[] memory wellTokens = well.tokens(); + pool.tokens = [address(wellTokens[0]), address(wellTokens[1])]; + + { + uint256[] memory wellBalances = well.getReserves(); + pool.balances = [wellBalances[0], wellBalances[1]]; + } + + uint256 beanIndex = LibWell.getBeanIndex(wellTokens); + uint256 tknIndex = beanIndex == 0 ? 1 : 0; + + // swap 1 bean of the opposite asset to get the usd price + // price = amtOut/tknOutPrice + pool.price = + well.getSwapOut(wellTokens[beanIndex], wellTokens[tknIndex], 1e6) // 1e18 + .mul(PRICE_PRECISION) // 1e6 + .div(LibUsdOracle.getUsdPrice(address(wellTokens[tknIndex]))); // 1e18 + + // liquidity is calculated by beanAmt * beanPrice * 2 + pool.liquidity = + pool.balances[beanIndex] // 1e6 + .mul(pool.price) // 1e6 + .div(PRICE_PRECISION) + .mul(2); + + pool.deltaB = IBEANSTALK(BEANSTALK).poolDeltaB(wellAddress); + + pool.lpUsd = pool.liquidity.mul(WELL_DECIMALS).div(IERC20(wellAddress).totalSupply()); + + pool.lpBdv = IBEANSTALK(BEANSTALK).bdv(wellAddress, WELL_DECIMALS); + + } + +} diff --git a/protocol/scripts/impersonate.js b/protocol/scripts/impersonate.js index 0892032029..f603ed405e 100644 --- a/protocol/scripts/impersonate.js +++ b/protocol/scripts/impersonate.js @@ -24,8 +24,10 @@ const { ETH_USDC_UNISWAP_V3, ETH_USDT_UNISWAP_V3, USDT, - ETH_USD_CHAINLINK_AGGREGATOR + ETH_USD_CHAINLINK_AGGREGATOR, + BEAN_ETH_WELL } = require('../test/utils/constants'); +const { deployWell } = require('../utils/well.js'); const { impersonateSigner, mintEth } = require('../utils'); const { getSigner } = '../utils' @@ -95,6 +97,8 @@ async function weth() { WETH, JSON.parse(tokenJson).deployedBytecode, ]); + const weth = await ethers.getContractAt("MockToken", WETH); + await weth.setDecimals(18); } async function router() { @@ -268,6 +272,15 @@ async function ethUsdtUniswap() { ]); } +async function beanEthWell() { + const well = await deployWell([BEAN, WETH]); + const bytecode = await ethers.provider.getCode(well.address) + await network.provider.send("hardhat_setCode", [ + BEAN_ETH_WELL, + bytecode, + ]); +} + async function ethUsdChainlinkAggregator() { let chainlinkAggregatorJson = fs.readFileSync(`./artifacts/contracts/mocks/chainlink/MockChainlinkAggregator.sol/MockChainlinkAggregator.json`); @@ -279,6 +292,8 @@ async function ethUsdChainlinkAggregator() { await ethUsdChainlinkAggregator.setDecimals(6) } + + exports.impersonateRouter = router exports.impersonateBean = bean exports.impersonateCurve = curve @@ -295,3 +310,4 @@ exports.impersonateEthUsdcUniswap = ethUsdcUniswap exports.impersonateEthUsdtUniswap = ethUsdtUniswap exports.impersonateBeanstalk = impersonateBeanstalk exports.impersonateEthUsdChainlinkAggregator = ethUsdChainlinkAggregator +exports.impersonateBeanEthWell = beanEthWell diff --git a/protocol/test/LegacyClaim.test.js b/protocol/test/LegacyClaim.test.js index 0d3078d718..309bb29189 100644 --- a/protocol/test/LegacyClaim.test.js +++ b/protocol/test/LegacyClaim.test.js @@ -9,8 +9,6 @@ const { upgradeWithNewFacets } = require("../scripts/diamond"); describe("Legacy Claim", async function () { before(async function () { - console.log("startup stuff"); - try { await network.provider.request({ method: "hardhat_reset", @@ -47,7 +45,6 @@ describe("Legacy Claim", async function () { this.diamond = BEANSTALK; - console.log("this.diamond: ", this.diamond); // this.season = await ethers.getContractAt("MockSeasonFacet", this.diamond); diff --git a/protocol/test/beanstalkPrice.test.js b/protocol/test/beanstalkPrice.test.js new file mode 100644 index 0000000000..98219b1ebb --- /dev/null +++ b/protocol/test/beanstalkPrice.test.js @@ -0,0 +1,383 @@ +const { expect } = require('chai'); +const { deploy } = require('../scripts/deploy.js') +const { EXTERNAL } = require('./utils/balances.js') +const { to18, to6, advanceTime } = require('./utils/helpers.js') +const { BEAN, BEANSTALK, BEAN_3_CURVE, THREE_CURVE, THREE_POOL, WETH, STABLE_FACTORY, BEAN_ETH_WELL } = require('./utils/constants') +const { takeSnapshot, revertToSnapshot } = require("./utils/snapshot"); +const { deployWell, setReserves, whitelistWell } = require('../utils/well.js'); +const { setEthUsdPrice, setEthUsdcPrice, setEthUsdtPrice } = require('../scripts/usdOracle.js'); +const { getBeanstalk } = require('../utils/contracts.js'); +const { impersonateBeanEthWell } = require('../scripts/impersonate.js') +const fs = require('fs'); + +let user, user2, owner; +let userAddress, ownerAddress, user2Address; + +describe('BeanstalkPrice', function () { + before(async function () { + + [owner, user] = await ethers.getSigners(); + const contracts = await deploy("Test", false, true); + ownerAddress = contracts.account; + userAddress = user.address; + this.diamond = contracts.beanstalkDiamond; + this.beanstalk = await getBeanstalk(this.diamond.address); + this.curve = await ethers.getContractAt('CurveFacet', this.diamond.address) + await impersonateBeanEthWell() + this.well = await ethers.getContractAt("IWell", BEAN_ETH_WELL); + this.wellToken = await ethers.getContractAt("IERC20", this.well.address) + this.threeCurve = await ethers.getContractAt('MockToken', THREE_CURVE) + this.threePool = await ethers.getContractAt('Mock3Curve', THREE_POOL) + this.beanThreeCurve = await ethers.getContractAt('MockMeta3Curve', BEAN_3_CURVE); + this.season = await ethers.getContractAt('MockSeasonFacet', this.diamond.address); + this.bean = await ethers.getContractAt("MockToken", BEAN); + + await this.bean.connect(user).approve(this.diamond.address, ethers.constants.MaxUint256) + await this.bean.connect(user).approve(this.beanThreeCurve.address, ethers.constants.MaxUint256); + await this.bean.mint(userAddress, to6('10000000000')) + + await this.threeCurve.mint(userAddress, to18('10000000000')) + await this.threePool.set_virtual_price(to18('1')) + await this.threeCurve.connect(user).approve(this.beanThreeCurve.address, ethers.constants.MaxUint256) + + await this.bean.mint(ownerAddress, to6('1000000000')) + await this.wellToken.connect(owner).approve(this.beanstalk.address, ethers.constants.MaxUint256) + await this.bean.connect(owner).approve(this.beanstalk.address, ethers.constants.MaxUint256) + + await this.beanThreeCurve.set_A_precise('1000') + await this.beanThreeCurve.set_virtual_price(ethers.utils.parseEther('1')) + await this.beanThreeCurve.connect(user).approve(this.threeCurve.address, ethers.constants.MaxUint256) + await this.beanThreeCurve.connect(user).approve(this.diamond.address, ethers.constants.MaxUint256) + await this.threeCurve.connect(user).approve(this.diamond.address, ethers.constants.MaxUint256) + + this.result = await this.curve.connect(user).addLiquidity( + BEAN_3_CURVE, + STABLE_FACTORY, + [to6('500000'), to18('500000')], + to18('0'), + EXTERNAL, + EXTERNAL + ) + + this.result = await this.curve.connect(user).addLiquidity( + BEAN_3_CURVE, + STABLE_FACTORY, + [to6('500000'), to18('500000')], + to18('0'), + EXTERNAL, + EXTERNAL + ) + + await setEthUsdPrice('999.998018') + await setEthUsdcPrice('1000') + await setEthUsdtPrice('1000') + + await setReserves( + owner, + this.well, + [to6('1000000'), to18('1000')] + ); + + await setReserves( + owner, + this.well, + [to6('1000000'), to18('1000')] + ); + + await whitelistWell(this.well.address, '10000', to6('4')); + await this.season.captureWellE(this.well.address); + + const BeanstalkPrice = await ethers.getContractFactory('BeanstalkPrice'); + const _beanstalkPrice = await BeanstalkPrice.deploy(); + await _beanstalkPrice.deployed(); + this.beanstalkPrice = await ethers.getContractAt('BeanstalkPrice', _beanstalkPrice.address); + + }); + + beforeEach(async function () { + snapshotId = await takeSnapshot(); + }); + + afterEach(async function () { + await revertToSnapshot(snapshotId); + }); + + describe("Price", async function () { + it('deltaB = 0', async function () { + const p = await this.beanstalkPrice.price() + // price is within +/- 1 due to curve rounding + expect(p.price).to.equal('999999'); + expect(p.liquidity).to.equal('3999997000000'); + expect(p.deltaB).to.be.eq('0'); + }) + + it('deltaB > 0, curve only', async function () { + this.result = await this.curve.connect(user).addLiquidity( + BEAN_3_CURVE, + STABLE_FACTORY, + [to6('0'), to18('100000')], + to18('0'), + EXTERNAL, + EXTERNAL + ) + const p = await this.beanstalkPrice.price() + const c = await this.beanstalkPrice.getCurve() + const w = await this.beanstalkPrice.getConstantProductWell(this.well.address) + + expect(p.price).to.equal('1004479'); + expect(p.liquidity).to.equal('4108727000000'); + expect(p.deltaB).to.equal('49891561002'); + + expect(c.price).to.equal('1008729'); + expect(c.liquidity).to.equal('2108729000000'); + expect(c.deltaB).to.equal('49891561002'); + + expect(w.price).to.equal('999999'); + expect(w.liquidity).to.equal('1999998000000'); + expect(w.deltaB).to.equal('0'); + }) + + it('deltaB > 0, wells only', async function () { + await advanceTime(1800) + await setReserves( + owner, + this.well, + [to6('500000'), to18('1000')] + ); + await advanceTime(1800) + await user.sendTransaction({ + to: beanstalk.address, + value: 0 + }) + + const p = await this.beanstalkPrice.price() + const c = await this.beanstalkPrice.getCurve() + const w = await this.beanstalkPrice.getConstantProductWell(this.well.address) + + expect(p.price).to.equal('1499997'); + expect(p.liquidity).to.equal('3999995000000'); + expect(p.deltaB).to.equal('133679332828'); + + expect(c.price).to.equal('999999'); + expect(c.liquidity).to.equal('1999999000000'); + expect(c.deltaB).to.equal('0'); + + expect(w.price).to.equal('1999996'); + expect(w.liquidity).to.equal('1999996000000'); + expect(w.deltaB).to.equal('133679332828'); + }) + + it('deltaB > 0, wells and curve', async function () { + this.result = await this.curve.connect(user).addLiquidity( + BEAN_3_CURVE, + STABLE_FACTORY, + [to6('0'), to18('100000')], + to18('0'), + EXTERNAL, + EXTERNAL + ) + await advanceTime(1800) + await setReserves( + owner, + this.well, + [to6('500000'), to18('1000')] + ); + await advanceTime(1800) + await user.sendTransaction({ + to: beanstalk.address, + value: 0 + }) + + const p = await this.beanstalkPrice.price() + const c = await this.beanstalkPrice.getCurve() + const w = await this.beanstalkPrice.getConstantProductWell(this.well.address) + + expect(p.price).to.equal('1491246'); + expect(p.liquidity).to.equal('4108725000000'); + expect(p.deltaB).to.equal('183543345294'); + + expect(c.price).to.equal('1008729'); + expect(c.liquidity).to.equal('2108729000000'); + expect(c.deltaB).to.equal('49891561002'); + + expect(w.price).to.equal('1999996'); + expect(w.liquidity).to.equal('1999996000000'); + expect(w.deltaB).to.equal('133651784292'); + }) + + it('deltaB < 0, curve only', async function () { + this.result = await this.curve.connect(user).addLiquidity( + BEAN_3_CURVE, + STABLE_FACTORY, + [to6('100000'), to18('0')], + to18('0'), + EXTERNAL, + EXTERNAL + ) + + // ~500 beans need be to be bought to get back to peg + const p = await this.beanstalkPrice.price() + const c = await this.beanstalkPrice.getCurve() + const w = await this.beanstalkPrice.getConstantProductWell(this.well.address) + + expect(p.price).to.equal('995576'); + expect(p.liquidity).to.equal('4090478600000'); + expect(p.deltaB).to.equal('-50108438998'); + + expect(c.price).to.equal('991346'); + expect(c.liquidity).to.equal('2090480600000'); + expect(c.deltaB).to.equal('-50108438998'); + + expect(w.price).to.equal('999999'); + expect(w.liquidity).to.equal('1999998000000'); + expect(w.deltaB).to.equal('0'); + + }) + + it('deltaB < 0, wells only', async function () { + await advanceTime(1800) + await setReserves( + owner, + this.well, + [to6('2000000'), to18('1000')] + ); + await advanceTime(1800) + await user.sendTransaction({ + to: beanstalk.address, + value: 0 + }) + + const p = await this.beanstalkPrice.price() + const c = await this.beanstalkPrice.getCurve() + const w = await this.beanstalkPrice.getConstantProductWell(this.well.address) + + expect(p.price).to.equal('749999'); + expect(p.liquidity).to.equal('3999995000000'); + expect(p.deltaB).to.equal('-224612602483'); + + expect(c.price).to.equal('999999'); + expect(c.liquidity).to.equal('1999999000000'); + expect(c.deltaB).to.equal('0'); + + expect(w.price).to.equal('499999'); + expect(w.liquidity).to.equal('1999996000000'); + expect(w.deltaB).to.equal('-224612602483'); + }) + + it('deltaB < 0, wells and curve', async function () { + this.result = await this.curve.connect(user).addLiquidity( + BEAN_3_CURVE, + STABLE_FACTORY, + [to6('100000'), to18('0')], + to18('0'), + EXTERNAL, + EXTERNAL + ) + await advanceTime(1800) + await setReserves( + owner, + this.well, + [to6('2000000'), to18('1000')] + ); + await advanceTime(1800) + await user.sendTransaction({ + to: beanstalk.address, + value: 0 + }) + + const p = await this.beanstalkPrice.price() + const c = await this.beanstalkPrice.getCurve() + const w = await this.beanstalkPrice.getConstantProductWell(this.well.address) + + expect(p.price).to.equal('751106'); + expect(p.liquidity).to.equal('4090476600000'); + expect(p.deltaB).to.be.within('-274563881303', '-274485381948') + + expect(c.price).to.equal('991346'); + expect(c.liquidity).to.equal('2090480600000'); + expect(c.deltaB).to.equal('-50108438998'); + + expect(w.price).to.equal('499999'); + expect(w.liquidity).to.equal('1999996000000'); + expect(w.deltaB).to.equal('-224376942950'); + }) + + it('well deltaB > 0, curve deltaB < 0', async function () { + this.result = await this.curve.connect(user).addLiquidity( + BEAN_3_CURVE, + STABLE_FACTORY, + [to6('100000'), to18('0')], + to18('0'), + EXTERNAL, + EXTERNAL + ) + await advanceTime(1800) + await setReserves( + owner, + this.well, + [to6('500000'), to18('1000')] + ); + await advanceTime(1800) + await user.sendTransaction({ + to: beanstalk.address, + value: 0 + }) + + const p = await this.beanstalkPrice.price() + const c = await this.beanstalkPrice.getCurve() + const w = await this.beanstalkPrice.getConstantProductWell(this.well.address) + + expect(p.price).to.equal('1484514'); + expect(p.liquidity).to.equal('4090476600000'); + expect(p.deltaB).to.equal('83488280312'); + + expect(c.price).to.equal('991346'); + expect(c.liquidity).to.equal('2090480600000'); + expect(c.deltaB).to.equal('-50108438998'); + + expect(w.price).to.equal('1999996'); + expect(w.liquidity).to.equal('1999996000000'); + expect(w.deltaB).to.be.within('133569202852','133596719310'); + }) + + it('well deltaB < 0, curve deltaB > 0', async function () { + this.result = await this.curve.connect(user).addLiquidity( + BEAN_3_CURVE, + STABLE_FACTORY, + [to6('0'), to18('100000')], + to18('0'), + EXTERNAL, + EXTERNAL + ) + await advanceTime(1800) + await setReserves( + owner, + this.well, + [to6('2000000'), to18('1000')] + ); + await advanceTime(1800) + await user.sendTransaction({ + to: beanstalk.address, + value: 0 + }) + + const p = await this.beanstalkPrice.price() + const c = await this.beanstalkPrice.getCurve() + const w = await this.beanstalkPrice.getConstantProductWell(this.well.address) + + expect(p.price).to.equal('761095'); + expect(p.liquidity).to.equal('4108725000000'); + expect(p.deltaB).to.be.within('-174485381948','-174406936344'); + + expect(c.price).to.equal('1008729'); + expect(c.liquidity).to.equal('2108729000000'); + expect(c.deltaB).to.equal('49891561002'); + + expect(w.price).to.equal('499999'); + expect(w.liquidity).to.equal('1999996000000'); + expect(w.deltaB).to.equal('-224298497346'); + }) + + }); + +}); diff --git a/protocol/test/utils/constants.js b/protocol/test/utils/constants.js index 614e48a26b..20d6899b0b 100644 --- a/protocol/test/utils/constants.js +++ b/protocol/test/utils/constants.js @@ -46,5 +46,6 @@ module.exports = { DEPOT_DEPLOYER: '0x058a783D98cDBB78d403c6B613C17d6b96f20d06', ETH_USDT_UNISWAP_V3: '0x4e68Ccd3E89f51C3074ca5072bbAC773960dFa36', ETH_USD_CHAINLINK_AGGREGATOR: '0x5f4eC3Df9cbd43714FE2740f5E3616155c5b8419', - BEANSTALK_PUMP: '0xc4AD29ba4B3c580e6D59105FFf484999997675Ff' + BEANSTALK_PUMP: '0xc4AD29ba4B3c580e6D59105FFf484999997675Ff', + BEAN_ETH_WELL: '0x9bAaB117304f7D6517048e371025dB8f89a8DbE5' } diff --git a/protocol/test/utils/helpers.js b/protocol/test/utils/helpers.js index bdba8d9cf4..7d28cd74e9 100644 --- a/protocol/test/utils/helpers.js +++ b/protocol/test/utils/helpers.js @@ -42,6 +42,16 @@ function toX(amount, x) { return ethers.utils.parseUnits(amount,x); } +async function advanceTime(time) { + let timestamp = (await ethers.provider.getBlock('latest')).timestamp; + timestamp += time + await hre.network.provider.request({ + method: "evm_setNextBlockTimestamp", + params: [timestamp], + }); +} + + exports.toBean = toBean exports.toStalk = toStalk exports.toEther = toEther @@ -50,4 +60,5 @@ exports.to6 = to6 exports.parseJson = parseJson exports.getEthSpentOnGas = getEthSpentOnGas exports.incrementTime = incrementTime +exports.advanceTime = advanceTime exports.toX = toX \ No newline at end of file From 9a2de4685db836892c5060303d77fd049f932708 Mon Sep 17 00:00:00 2001 From: Brean0 Date: Fri, 4 Aug 2023 21:06:52 -0500 Subject: [PATCH 02/13] changed multiplication before division --- protocol/contracts/ecosystem/price/WellPrice.sol | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/protocol/contracts/ecosystem/price/WellPrice.sol b/protocol/contracts/ecosystem/price/WellPrice.sol index 2e61480edf..7c785bd66d 100644 --- a/protocol/contracts/ecosystem/price/WellPrice.sol +++ b/protocol/contracts/ecosystem/price/WellPrice.sol @@ -66,8 +66,8 @@ contract WellPrice { pool.liquidity = pool.balances[beanIndex] // 1e6 .mul(pool.price) // 1e6 - .div(PRICE_PRECISION) - .mul(2); + .mul(2) + .div(PRICE_PRECISION); pool.deltaB = IBEANSTALK(BEANSTALK).poolDeltaB(wellAddress); From e63719a166b96fc8cc3897bc495b16dc6432cc5f Mon Sep 17 00:00:00 2001 From: Brean0 Date: Sat, 5 Aug 2023 13:44:57 -0500 Subject: [PATCH 03/13] public -> external --- protocol/contracts/ecosystem/price/WellPrice.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/protocol/contracts/ecosystem/price/WellPrice.sol b/protocol/contracts/ecosystem/price/WellPrice.sol index 7c785bd66d..6a5e56fad2 100644 --- a/protocol/contracts/ecosystem/price/WellPrice.sol +++ b/protocol/contracts/ecosystem/price/WellPrice.sol @@ -40,7 +40,7 @@ contract WellPrice { uint256 lpBdv; } - function getConstantProductWell(address wellAddress) public view returns (P.Pool memory pool) { + function getConstantProductWell(address wellAddress) external view returns (P.Pool memory pool) { IWell well = IWell(wellAddress); pool.pool = wellAddress; From 99019932e1b073c61abe428e6c27955a08bdeacc Mon Sep 17 00:00:00 2001 From: Brean0 Date: Sat, 5 Aug 2023 13:45:47 -0500 Subject: [PATCH 04/13] revert --- protocol/contracts/ecosystem/price/WellPrice.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/protocol/contracts/ecosystem/price/WellPrice.sol b/protocol/contracts/ecosystem/price/WellPrice.sol index 6a5e56fad2..7c785bd66d 100644 --- a/protocol/contracts/ecosystem/price/WellPrice.sol +++ b/protocol/contracts/ecosystem/price/WellPrice.sol @@ -40,7 +40,7 @@ contract WellPrice { uint256 lpBdv; } - function getConstantProductWell(address wellAddress) external view returns (P.Pool memory pool) { + function getConstantProductWell(address wellAddress) public view returns (P.Pool memory pool) { IWell well = IWell(wellAddress); pool.pool = wellAddress; From aabd852b6a57f5fd6c822186d8e4cfc9241ae9ed Mon Sep 17 00:00:00 2001 From: Brean0 Date: Sat, 5 Aug 2023 13:47:29 -0500 Subject: [PATCH 05/13] remove unneeded brackets --- protocol/contracts/ecosystem/price/WellPrice.sol | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/protocol/contracts/ecosystem/price/WellPrice.sol b/protocol/contracts/ecosystem/price/WellPrice.sol index 7c785bd66d..e61448f3db 100644 --- a/protocol/contracts/ecosystem/price/WellPrice.sol +++ b/protocol/contracts/ecosystem/price/WellPrice.sol @@ -47,10 +47,8 @@ contract WellPrice { IERC20[] memory wellTokens = well.tokens(); pool.tokens = [address(wellTokens[0]), address(wellTokens[1])]; - { - uint256[] memory wellBalances = well.getReserves(); - pool.balances = [wellBalances[0], wellBalances[1]]; - } + uint256[] memory wellBalances = well.getReserves(); + pool.balances = [wellBalances[0], wellBalances[1]]; uint256 beanIndex = LibWell.getBeanIndex(wellTokens); uint256 tknIndex = beanIndex == 0 ? 1 : 0; From f15a2f2a594ee575b737d5d2d4f03b06cef692e3 Mon Sep 17 00:00:00 2001 From: Brean0 Date: Sat, 5 Aug 2023 14:09:05 -0500 Subject: [PATCH 06/13] add check that LibUsdOracle.getUsdPrice returns a value --- protocol/contracts/ecosystem/price/WellPrice.sol | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/protocol/contracts/ecosystem/price/WellPrice.sol b/protocol/contracts/ecosystem/price/WellPrice.sol index e61448f3db..d2464e02ed 100644 --- a/protocol/contracts/ecosystem/price/WellPrice.sol +++ b/protocol/contracts/ecosystem/price/WellPrice.sol @@ -55,10 +55,16 @@ contract WellPrice { // swap 1 bean of the opposite asset to get the usd price // price = amtOut/tknOutPrice - pool.price = + uint256 assetPrice = LibUsdOracle.getUsdPrice(address(wellTokens[tknIndex])); + if(assetPrice > 0) { + pool.price = well.getSwapOut(wellTokens[beanIndex], wellTokens[tknIndex], 1e6) // 1e18 - .mul(PRICE_PRECISION) // 1e6 - .div(LibUsdOracle.getUsdPrice(address(wellTokens[tknIndex]))); // 1e18 + .mul(PRICE_PRECISION) // 1e6 + .div(LibUsdOracle.getUsdPrice(address(wellTokens[tknIndex]))); // 1e18 + } else { + revert("WellPrice: price is 0"); + } + // liquidity is calculated by beanAmt * beanPrice * 2 pool.liquidity = From 579c51d2725cf213e3b0e00b4ed4c2b80db71c05 Mon Sep 17 00:00:00 2001 From: Brean0 Date: Sat, 5 Aug 2023 14:14:59 -0500 Subject: [PATCH 07/13] return 0 rather than reverting --- protocol/contracts/ecosystem/price/WellPrice.sol | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/protocol/contracts/ecosystem/price/WellPrice.sol b/protocol/contracts/ecosystem/price/WellPrice.sol index d2464e02ed..95d126f2db 100644 --- a/protocol/contracts/ecosystem/price/WellPrice.sol +++ b/protocol/contracts/ecosystem/price/WellPrice.sol @@ -62,7 +62,8 @@ contract WellPrice { .mul(PRICE_PRECISION) // 1e6 .div(LibUsdOracle.getUsdPrice(address(wellTokens[tknIndex]))); // 1e18 } else { - revert("WellPrice: price is 0"); + // cannnot determine a price for bean if the other asset that bean is trading against is 0. + pool.price = 0; } From d4788c6f721e23ea05f5e4d61ca218c2775504ff Mon Sep 17 00:00:00 2001 From: Brean0 Date: Sat, 5 Aug 2023 15:11:34 -0500 Subject: [PATCH 08/13] assetPrice --- protocol/contracts/ecosystem/price/WellPrice.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/protocol/contracts/ecosystem/price/WellPrice.sol b/protocol/contracts/ecosystem/price/WellPrice.sol index 95d126f2db..871d25e554 100644 --- a/protocol/contracts/ecosystem/price/WellPrice.sol +++ b/protocol/contracts/ecosystem/price/WellPrice.sol @@ -60,7 +60,7 @@ contract WellPrice { pool.price = well.getSwapOut(wellTokens[beanIndex], wellTokens[tknIndex], 1e6) // 1e18 .mul(PRICE_PRECISION) // 1e6 - .div(LibUsdOracle.getUsdPrice(address(wellTokens[tknIndex]))); // 1e18 + .div(assetPrice); // 1e18 } else { // cannnot determine a price for bean if the other asset that bean is trading against is 0. pool.price = 0; From 12afa2241df65b482ad0c2db74c23cbf2f217408 Mon Sep 17 00:00:00 2001 From: Brean0 Date: Sun, 6 Aug 2023 09:26:45 -0500 Subject: [PATCH 09/13] better comments, using Snakecase for beanstalk --- .../contracts/ecosystem/price/WellPrice.sol | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/protocol/contracts/ecosystem/price/WellPrice.sol b/protocol/contracts/ecosystem/price/WellPrice.sol index 871d25e554..4282aceb12 100644 --- a/protocol/contracts/ecosystem/price/WellPrice.sol +++ b/protocol/contracts/ecosystem/price/WellPrice.sol @@ -11,7 +11,7 @@ import {LibWellMinting} from "../../libraries/Minting/LibWellMinting.sol"; import {LibWell} from "../../libraries/Well/LibWell.sol"; import {C} from "../../C.sol"; -interface IBEANSTALK { +interface IBeanstalk { function bdv(address token, uint256 amount) external view returns (uint256); function poolDeltaB(address pool) external view returns (int256); @@ -25,7 +25,7 @@ contract WellPrice { using SafeMath for uint256; - address private constant BEANSTALK = 0xC1E088fC1323b20BCBee9bd1B9fC9546db5624C5; + IBeanstalk private constant BEANSTALK = IBeanstalk(0xC1E088fC1323b20BCBee9bd1B9fC9546db5624C5); uint256 private constant WELL_DECIMALS = 1e18; uint256 private constant PRICE_PRECISION = 1e6; @@ -55,7 +55,7 @@ contract WellPrice { // swap 1 bean of the opposite asset to get the usd price // price = amtOut/tknOutPrice - uint256 assetPrice = LibUsdOracle.getUsdPrice(address(wellTokens[tknIndex])); + uint256 assetPrice = LibUsdOracle.getUsdPrice(pool.tokens[tknIndex]); if(assetPrice > 0) { pool.price = well.getSwapOut(wellTokens[beanIndex], wellTokens[tknIndex], 1e6) // 1e18 @@ -65,21 +65,18 @@ contract WellPrice { // cannnot determine a price for bean if the other asset that bean is trading against is 0. pool.price = 0; } - - // liquidity is calculated by beanAmt * beanPrice * 2 + // liquidity is calculated by getting the usd value of the bean portion of the pool, + // and multiplying by 2 to get the total liquidity of the pool. pool.liquidity = pool.balances[beanIndex] // 1e6 .mul(pool.price) // 1e6 .mul(2) .div(PRICE_PRECISION); - - pool.deltaB = IBEANSTALK(BEANSTALK).poolDeltaB(wellAddress); - + + pool.deltaB = BEANSTALK.poolDeltaB(wellAddress); pool.lpUsd = pool.liquidity.mul(WELL_DECIMALS).div(IERC20(wellAddress).totalSupply()); - - pool.lpBdv = IBEANSTALK(BEANSTALK).bdv(wellAddress, WELL_DECIMALS); - + pool.lpBdv = BEANSTALK.bdv(wellAddress, WELL_DECIMALS); } } From 5a33b28d42cab403299f91f555ee456c9ea1e43b Mon Sep 17 00:00:00 2001 From: Brean0 Date: Sun, 6 Aug 2023 09:29:49 -0500 Subject: [PATCH 10/13] remove unneeded comments --- protocol/contracts/ecosystem/price/WellPrice.sol | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/protocol/contracts/ecosystem/price/WellPrice.sol b/protocol/contracts/ecosystem/price/WellPrice.sol index 4282aceb12..ef978fdd51 100644 --- a/protocol/contracts/ecosystem/price/WellPrice.sol +++ b/protocol/contracts/ecosystem/price/WellPrice.sol @@ -58,9 +58,9 @@ contract WellPrice { uint256 assetPrice = LibUsdOracle.getUsdPrice(pool.tokens[tknIndex]); if(assetPrice > 0) { pool.price = - well.getSwapOut(wellTokens[beanIndex], wellTokens[tknIndex], 1e6) // 1e18 - .mul(PRICE_PRECISION) // 1e6 - .div(assetPrice); // 1e18 + well.getSwapOut(wellTokens[beanIndex], wellTokens[tknIndex], 1e6) + .mul(PRICE_PRECISION) + .div(assetPrice); } else { // cannnot determine a price for bean if the other asset that bean is trading against is 0. pool.price = 0; @@ -69,11 +69,11 @@ contract WellPrice { // liquidity is calculated by getting the usd value of the bean portion of the pool, // and multiplying by 2 to get the total liquidity of the pool. pool.liquidity = - pool.balances[beanIndex] // 1e6 - .mul(pool.price) // 1e6 + pool.balances[beanIndex] + .mul(pool.price) .mul(2) .div(PRICE_PRECISION); - + pool.deltaB = BEANSTALK.poolDeltaB(wellAddress); pool.lpUsd = pool.liquidity.mul(WELL_DECIMALS).div(IERC20(wellAddress).totalSupply()); pool.lpBdv = BEANSTALK.bdv(wellAddress, WELL_DECIMALS); From d9c9dfdf704be27bf74fb82be48555a0d82716b5 Mon Sep 17 00:00:00 2001 From: publius Date: Mon, 7 Aug 2023 01:44:58 +0200 Subject: [PATCH 11/13] fix deltaB function --- .../contracts/ecosystem/price/WellPrice.sol | 20 +++++++++++++++++-- protocol/utils/well.js | 10 +++++----- 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/protocol/contracts/ecosystem/price/WellPrice.sol b/protocol/contracts/ecosystem/price/WellPrice.sol index ef978fdd51..244831bc27 100644 --- a/protocol/contracts/ecosystem/price/WellPrice.sol +++ b/protocol/contracts/ecosystem/price/WellPrice.sol @@ -4,7 +4,7 @@ pragma experimental ABIEncoderV2; import {P} from "./P.sol"; import {SafeMath} from "@openzeppelin/contracts/math/SafeMath.sol"; -import {IWell, IERC20} from "../../interfaces/basin/IWell.sol"; +import {Call, IWell, IERC20} from "../../interfaces/basin/IWell.sol"; import {IBeanstalkWellFunction} from "../../interfaces/basin/IBeanstalkWellFunction.sol"; import {LibUsdOracle} from "../../libraries/Oracle/LibUsdOracle.sol"; import {LibWellMinting} from "../../libraries/Minting/LibWellMinting.sol"; @@ -74,9 +74,25 @@ contract WellPrice { .mul(2) .div(PRICE_PRECISION); - pool.deltaB = BEANSTALK.poolDeltaB(wellAddress); + pool.deltaB = getDeltaB(wellAddress, wellTokens, wellBalances); pool.lpUsd = pool.liquidity.mul(WELL_DECIMALS).div(IERC20(wellAddress).totalSupply()); pool.lpBdv = BEANSTALK.bdv(wellAddress, WELL_DECIMALS); } + function getDeltaB(address well, IERC20[] memory tokens, uint256[] memory reserves) internal view returns (int256 deltaB) { + Call memory wellFunction = IWell(well).wellFunction(); + (uint256[] memory ratios, uint256 beanIndex, bool success) = LibWell.getRatiosAndBeanIndex(tokens); + // If the USD Oracle oracle call fails, we can't compute deltaB + if(!success) return 0; + + uint256 beansAtPeg = IBeanstalkWellFunction(wellFunction.target).calcReserveAtRatioLiquidity( + reserves, + beanIndex, + ratios, + wellFunction.data + ); + + deltaB = int256(beansAtPeg) - int256(reserves[beanIndex]); + } + } diff --git a/protocol/utils/well.js b/protocol/utils/well.js index 8d6fce4b9e..8ce3638fdd 100644 --- a/protocol/utils/well.js +++ b/protocol/utils/well.js @@ -100,7 +100,7 @@ async function deployWell(tokens, verbose = false, salt = ethers.constants.HashZ if (verbose) console.log("Deployed Aquifer", aquifer.address); const wellFunction = await deployWellContract('ConstantProduct2'); if (verbose) console.log("Deployed Well Function", wellFunction.address); - const pump = await deployGeoEmaAndCumSmaPump() + const pump = await deployMultiFlowPump() if (verbose) console.log("Deployed Pump", pump.address); const immutableData = await encodeWellImmutableData( @@ -205,8 +205,8 @@ async function deployMockPump() { return await ethers.getContractAt('MockPump', BEANSTALK_PUMP) } -async function deployGeoEmaAndCumSmaPump() { - pump = await (await getWellContractFactory('GeoEmaAndCumSmaPump')).deploy( +async function deployMultiFlowPump() { + pump = await (await getWellContractFactory('MultiFlowPump')).deploy( '0x3ffe0000000000000000000000000000', // 0.5 '0x3ffd555555555555553cbcd83d925070', // 0.333333333333333333 12, @@ -218,7 +218,7 @@ async function deployGeoEmaAndCumSmaPump() { BEANSTALK_PUMP, await ethers.provider.getCode(pump.address), ]); - return await getWellContractAt('GeoEmaAndCumSmaPump', BEANSTALK_PUMP) + return await getWellContractAt('MultiFlowPump', BEANSTALK_PUMP) } async function deployMockWell() { @@ -229,7 +229,7 @@ async function deployMockWell() { let well = await (await ethers.getContractFactory('MockSetComponentsWell', await getWellDeployer())).deploy() await well.deployed() - pump = await deployGeoEmaAndCumSmaPump() + pump = await deployMultiFlowPump() await well.setPumps([[pump.address, '0x']]) await well.setWellFunction([wellFunction.address, '0x']) From bf3b8dbeb70f0989c5696a9d959f51905b3cc7b4 Mon Sep 17 00:00:00 2001 From: Brean0 Date: Sun, 6 Aug 2023 22:11:05 -0500 Subject: [PATCH 12/13] fix tests --- protocol/abi/Beanstalk.json | 106 +++++++++++++-------------- protocol/test/Silo.test.js | 7 +- protocol/test/beanstalkPrice.test.js | 24 +++--- 3 files changed, 69 insertions(+), 68 deletions(-) diff --git a/protocol/abi/Beanstalk.json b/protocol/abi/Beanstalk.json index 5f4e26d711..36db529a39 100644 --- a/protocol/abi/Beanstalk.json +++ b/protocol/abi/Beanstalk.json @@ -4484,6 +4484,59 @@ "stateMutability": "payable", "type": "function" }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + }, + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + } + ], + "name": "getAmountOut", + "outputs": [ + { + "internalType": "uint256", + "name": "amountOut", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "tokenIn", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenOut", + "type": "address" + } + ], + "name": "getMaxAmountIn", + "outputs": [ + { + "internalType": "uint256", + "name": "amountIn", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, { "anonymous": false, "inputs": [ @@ -4570,59 +4623,6 @@ "stateMutability": "payable", "type": "function" }, - { - "inputs": [ - { - "internalType": "address", - "name": "tokenIn", - "type": "address" - }, - { - "internalType": "address", - "name": "tokenOut", - "type": "address" - }, - { - "internalType": "uint256", - "name": "amountIn", - "type": "uint256" - } - ], - "name": "getAmountOut", - "outputs": [ - { - "internalType": "uint256", - "name": "amountOut", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "tokenIn", - "type": "address" - }, - { - "internalType": "address", - "name": "tokenOut", - "type": "address" - } - ], - "name": "getMaxAmountIn", - "outputs": [ - { - "internalType": "uint256", - "name": "amountIn", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, { "inputs": [ { diff --git a/protocol/test/Silo.test.js b/protocol/test/Silo.test.js index 92cd72c0b4..9b37610afc 100644 --- a/protocol/test/Silo.test.js +++ b/protocol/test/Silo.test.js @@ -382,9 +382,10 @@ describe('Silo', function () { depositID4 = '0x1BEA3CcD22F4EBd3d37d731BA31Eeca95713716DFFF000000000000000000111'; expect(await this.metadata.uri(depositID4)).to.eq(depositmetadata); - depositmetadata = await fs.readFileSync(__dirname + '/data/base64EncodedImageBeanEth.txt', 'utf-8'); - depositID5 = '0x9bAaB117304f7D6517048e371025dB8f89a8DbE5FFFFFFFFFFFFF00000000002'; - expect(await this.metadata.uri(depositID5)).to.eq(depositmetadata); + // TODO: reimplement once basin addresses are deployed. + // depositmetadata = await fs.readFileSync(__dirname + '/data/base64EncodedImageBeanEth.txt', 'utf-8'); + // depositID5 = '0x9bAaB117304f7D6517048e371025dB8f89a8DbE5FFFFFFFFFFFFF00000000002'; + // expect(await this.metadata.uri(depositID5)).to.eq(depositmetadata); }); diff --git a/protocol/test/beanstalkPrice.test.js b/protocol/test/beanstalkPrice.test.js index 98219b1ebb..708860176c 100644 --- a/protocol/test/beanstalkPrice.test.js +++ b/protocol/test/beanstalkPrice.test.js @@ -156,7 +156,7 @@ describe('BeanstalkPrice', function () { expect(p.price).to.equal('1499997'); expect(p.liquidity).to.equal('3999995000000'); - expect(p.deltaB).to.equal('133679332828'); + expect(p.deltaB).to.equal('500000000000'); expect(c.price).to.equal('999999'); expect(c.liquidity).to.equal('1999999000000'); @@ -164,7 +164,7 @@ describe('BeanstalkPrice', function () { expect(w.price).to.equal('1999996'); expect(w.liquidity).to.equal('1999996000000'); - expect(w.deltaB).to.equal('133679332828'); + expect(w.deltaB).to.equal('500000000000'); }) it('deltaB > 0, wells and curve', async function () { @@ -194,7 +194,7 @@ describe('BeanstalkPrice', function () { expect(p.price).to.equal('1491246'); expect(p.liquidity).to.equal('4108725000000'); - expect(p.deltaB).to.equal('183543345294'); + expect(p.deltaB).to.equal('549891561002'); expect(c.price).to.equal('1008729'); expect(c.liquidity).to.equal('2108729000000'); @@ -202,7 +202,7 @@ describe('BeanstalkPrice', function () { expect(w.price).to.equal('1999996'); expect(w.liquidity).to.equal('1999996000000'); - expect(w.deltaB).to.equal('133651784292'); + expect(w.deltaB).to.equal('500000000000'); }) it('deltaB < 0, curve only', async function () { @@ -253,7 +253,7 @@ describe('BeanstalkPrice', function () { expect(p.price).to.equal('749999'); expect(p.liquidity).to.equal('3999995000000'); - expect(p.deltaB).to.equal('-224612602483'); + expect(p.deltaB).to.equal('-1000000000000'); expect(c.price).to.equal('999999'); expect(c.liquidity).to.equal('1999999000000'); @@ -261,7 +261,7 @@ describe('BeanstalkPrice', function () { expect(w.price).to.equal('499999'); expect(w.liquidity).to.equal('1999996000000'); - expect(w.deltaB).to.equal('-224612602483'); + expect(w.deltaB).to.equal('-1000000000000'); }) it('deltaB < 0, wells and curve', async function () { @@ -291,7 +291,7 @@ describe('BeanstalkPrice', function () { expect(p.price).to.equal('751106'); expect(p.liquidity).to.equal('4090476600000'); - expect(p.deltaB).to.be.within('-274563881303', '-274485381948') + expect(p.deltaB).to.be.eq('-1050108438998') expect(c.price).to.equal('991346'); expect(c.liquidity).to.equal('2090480600000'); @@ -299,7 +299,7 @@ describe('BeanstalkPrice', function () { expect(w.price).to.equal('499999'); expect(w.liquidity).to.equal('1999996000000'); - expect(w.deltaB).to.equal('-224376942950'); + expect(w.deltaB).to.equal('-1000000000000'); }) it('well deltaB > 0, curve deltaB < 0', async function () { @@ -329,7 +329,7 @@ describe('BeanstalkPrice', function () { expect(p.price).to.equal('1484514'); expect(p.liquidity).to.equal('4090476600000'); - expect(p.deltaB).to.equal('83488280312'); + expect(p.deltaB).to.equal('449891561002'); expect(c.price).to.equal('991346'); expect(c.liquidity).to.equal('2090480600000'); @@ -337,7 +337,7 @@ describe('BeanstalkPrice', function () { expect(w.price).to.equal('1999996'); expect(w.liquidity).to.equal('1999996000000'); - expect(w.deltaB).to.be.within('133569202852','133596719310'); + expect(w.deltaB).to.be.eq('500000000000'); }) it('well deltaB < 0, curve deltaB > 0', async function () { @@ -367,7 +367,7 @@ describe('BeanstalkPrice', function () { expect(p.price).to.equal('761095'); expect(p.liquidity).to.equal('4108725000000'); - expect(p.deltaB).to.be.within('-174485381948','-174406936344'); + expect(p.deltaB).to.be.eq('-950108438998'); expect(c.price).to.equal('1008729'); expect(c.liquidity).to.equal('2108729000000'); @@ -375,7 +375,7 @@ describe('BeanstalkPrice', function () { expect(w.price).to.equal('499999'); expect(w.liquidity).to.equal('1999996000000'); - expect(w.deltaB).to.equal('-224298497346'); + expect(w.deltaB).to.equal('-1000000000000'); }) }); From ce25909004c5f7fe77b7d82def3a44c320742a03 Mon Sep 17 00:00:00 2001 From: publius Date: Mon, 7 Aug 2023 11:57:43 +0200 Subject: [PATCH 13/13] Update Well deploy address --- protocol/contracts/mocks/well/MockSetComponentsWell.sol | 4 ++++ protocol/utils/well.js | 8 +++++++- 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/protocol/contracts/mocks/well/MockSetComponentsWell.sol b/protocol/contracts/mocks/well/MockSetComponentsWell.sol index 829bda1622..b4b1188a3f 100644 --- a/protocol/contracts/mocks/well/MockSetComponentsWell.sol +++ b/protocol/contracts/mocks/well/MockSetComponentsWell.sol @@ -21,6 +21,10 @@ contract MockSetComponentsWell is MockToken { _reserves = new uint256[](2); } + function init() external { + _reserves = new uint256[](2); + } + Call[] public _pumps; Call public _wellFunction; diff --git a/protocol/utils/well.js b/protocol/utils/well.js index 8ce3638fdd..da72021ea1 100644 --- a/protocol/utils/well.js +++ b/protocol/utils/well.js @@ -1,5 +1,5 @@ const fs = require('fs'); -const { BEAN, WETH, BEANSTALK_PUMP } = require('../test/utils/constants'); +const { BEAN, WETH, BEANSTALK_PUMP, BEAN_ETH_WELL } = require('../test/utils/constants'); const { to6, to18 } = require('../test/utils/helpers'); const { getBeanstalk } = require('./contracts'); const { mintEth } = require('./mint'); @@ -228,6 +228,12 @@ async function deployMockWell() { let well = await (await ethers.getContractFactory('MockSetComponentsWell', await getWellDeployer())).deploy() await well.deployed() + await network.provider.send("hardhat_setCode", [ + BEAN_ETH_WELL, + await ethers.provider.getCode(well.address), + ]); + well = await ethers.getContractAt('MockSetComponentsWell', BEAN_ETH_WELL) + await well.init() pump = await deployMultiFlowPump()