diff --git a/contracts/compound/strategies/BeefyERC4626.sol b/contracts/compound/strategies/BeefyERC4626.sol index b7e35c672..70a28efaa 100644 --- a/contracts/compound/strategies/BeefyERC4626.sol +++ b/contracts/compound/strategies/BeefyERC4626.sol @@ -95,7 +95,7 @@ contract BeefyERC4626 is MidasERC4626 { // takes as argument the internal ERC4626 shares to redeem // returns the external BeefyVault shares to withdraw - function convertToBeefyVaultShares(uint256 shares) public returns (uint256) { + function convertToBeefyVaultShares(uint256 shares) public view returns (uint256) { uint256 supply = totalSupply; return supply == 0 ? shares : shares.mulDivUp(beefyVault.balanceOf(address(this)), supply); } diff --git a/contracts/compound/strategies/MidasERC4626.sol b/contracts/compound/strategies/MidasERC4626.sol index 1f479808f..c936df2ed 100644 --- a/contracts/compound/strategies/MidasERC4626.sol +++ b/contracts/compound/strategies/MidasERC4626.sol @@ -76,7 +76,6 @@ abstract contract MidasERC4626 is ERC4626, Ownable, Pausable { address receiver, address owner ) public override returns (uint256 assets) { - uint256 supply = totalSupply; if (msg.sender != owner) { uint256 allowed = allowance[owner][msg.sender]; // Saves gas for limited approvals. diff --git a/contracts/test/AlpacaERC4626Test.t.sol b/contracts/test/AlpacaERC4626Test.t.sol index fc785fa63..883d673b3 100644 --- a/contracts/test/AlpacaERC4626Test.t.sol +++ b/contracts/test/AlpacaERC4626Test.t.sol @@ -247,9 +247,8 @@ contract AlpacaERC4626Test is BaseTest { assertEq(alpacaERC4626.balanceOf(address(this)), erc4626BalBefore - expectedErc4626SharesNeeded, "!erc4626 supply"); // Test that the ERC4626 holds the expected amount of beefy shares - assertEq( - mockVault.balanceOf(address(alpacaERC4626)), - beefyShares - expectedBeefySharesNeeded, + assertTrue( + diff(mockVault.balanceOf(address(alpacaERC4626)), beefyShares - expectedBeefySharesNeeded) <= 1, "!beefy share balance" ); @@ -281,9 +280,8 @@ contract AlpacaERC4626Test is BaseTest { assertEq(alpacaERC4626.balanceOf(address(1)), erc4626BalBefore - expectedErc4626SharesNeeded, "!erc4626 supply"); // Test that the ERC4626 holds the expected amount of beefy shares - assertEq( - mockVault.balanceOf(address(alpacaERC4626)), - beefyShares - expectedBeefySharesNeeded, + assertTrue( + diff(mockVault.balanceOf(address(alpacaERC4626)), beefyShares - expectedBeefySharesNeeded) <= 1, "!beefy share balance" ); diff --git a/contracts/test/BeefyERC4626Test.t.sol b/contracts/test/BeefyERC4626Test.t.sol index 2abb99f87..a6913f108 100644 --- a/contracts/test/BeefyERC4626Test.t.sol +++ b/contracts/test/BeefyERC4626Test.t.sol @@ -1,65 +1,113 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity >=0.4.23; -import "ds-test/test.sol"; import "forge-std/Vm.sol"; -import "./helpers/WithPool.sol"; import "./config/BaseTest.t.sol"; import { ERC20 } from "solmate/tokens/ERC20.sol"; -import { MockERC20 } from "solmate/test/utils/mocks/MockERC20.sol"; import { BeefyERC4626, IBeefyVault } from "../compound/strategies/BeefyERC4626.sol"; -import { MockStrategy } from "./mocks/beefy/MockStrategy.sol"; -import { MockVault } from "./mocks/beefy/MockVault.sol"; -import { IStrategy } from "./mocks/beefy/IStrategy.sol"; import { FixedPointMathLib } from "../utils/FixedPointMathLib.sol"; -contract BeefyERC4626Test is WithPool, BaseTest { +contract BeefyERC4626Test is BaseTest { using FixedPointMathLib for uint256; BeefyERC4626 beefyERC4626; IBeefyVault beefyVault; - address beefyStrategy = 0xEeBcd7E1f008C52fe5804B306832B7DD317e163D; + ERC20 underlyingToken; + uint256 initialBeefyBalance; + uint256 initialBeefySupply; uint256 depositAmount = 100e18; - uint256 withdrawalFee = 10; uint256 BPS_DENOMINATOR = 10_000; - uint256 iniitalBeefyBalance; - uint256 initialBeefySupply; + address alice = address(10); + address bob = address(20); + + struct BeefyVaultConfig { + address beefyVaultAddress; + uint256 withdrawalFee; + } - constructor() - WithPool( - MasterPriceOracle(0xB641c21124546e1c979b4C1EbF13aB00D43Ee8eA), - MockERC20(0x84392649eb0bC1c1532F2180E58Bae4E1dAbd8D6) - ) - {} + BeefyVaultConfig[] public configs; + + constructor() { + // beefy vault for BOMB-BTCB LP + configs.push( + BeefyVaultConfig( + 0x94E85B8E050F3F281CB9597cc0144F1F7AF1fe9B, // old val 0xD2FeCe7Ff1B791F8fE7f35424165abB8BD1671f2 + 10 + ) + ); + // beefy vault for CAKE-BNB LP + configs.push( + BeefyVaultConfig( + 0xb26642B6690E4c4c9A6dAd6115ac149c700C7dfE, // 0x0eD7e52944161450477ee417DE9Cd3a859b14fD0 CAKE-WBNB pair + 10 + ) + ); + // beefy vault for BUSD-BNB LP - + configs.push(BeefyVaultConfig(0xAd61143796D90FD5A61d89D63a546C7dB0a70475, 10)); + // beefy vault for BTCB-ETH LP + configs.push( + BeefyVaultConfig( + 0xEf43E54Bb4221106953951238FC301a1f8939490, // 0xD171B26E4484402de70e3Ea256bE5A2630d7e88D BTCB-ETH pair + 10 + ) + ); + // beefy vault for ETH-BNB LP + configs.push( + BeefyVaultConfig( + 0x0eb78598851D08218d54fCe965ee2bf29C288fac, // 0x74E4716E431f45807DCF19f284c7aA99F18a4fbc WBNB-ETH pair + 10 + ) + ); + // beefy vault for USDC-BUSD LP + configs.push( + BeefyVaultConfig( + 0x9260c62866f36638964551A8f480C3aAAa4693fd, // 0x2354ef4DF11afacb85a5C7f98B624072ECcddbB1 USDC-BUSD pair + 10 + ) + ); + } function setUp() public shouldRun(forChains(BSC_MAINNET)) { - beefyVault = IBeefyVault(0xD2FeCe7Ff1B791F8fE7f35424165abB8BD1671f2); - beefyERC4626 = new BeefyERC4626(underlyingToken, beefyVault, withdrawalFee); - iniitalBeefyBalance = beefyVault.balance(); + // uint8 _configIndexToTest = uint8(block.timestamp % configs.length); + uint8 _configIndexToTest = 2; + emit log_uint(_configIndexToTest); + + beefyVault = IBeefyVault(configs[_configIndexToTest].beefyVaultAddress); + underlyingToken = beefyVault.want(); + beefyERC4626 = new BeefyERC4626(underlyingToken, beefyVault, configs[_configIndexToTest].withdrawalFee); + + initialBeefyBalance = beefyVault.balance(); initialBeefySupply = beefyVault.totalSupply(); - sendUnderlyingToken(100e18, address(this)); - sendUnderlyingToken(100e18, address(1)); } - function deposit(address _owner, uint256 amount) public { - vm.startPrank(_owner); + function deposit(address owner, uint256 amount) public { + // transfer to user exactly amount, check the result + deal(address(underlyingToken), owner, amount); + assertEq(underlyingToken.balanceOf(owner), amount, "the full balance of cakeLP of user should equal amount"); + + vm.startPrank(owner); underlyingToken.approve(address(beefyERC4626), amount); - beefyERC4626.deposit(amount, _owner); + beefyERC4626.deposit(amount, owner); vm.stopPrank(); } - function sendUnderlyingToken(uint256 amount, address recipient) public { - vm.startPrank(0x1083926054069AaD75d7238E9B809b0eF9d94e5B); - underlyingToken.transfer(recipient, amount); + function mint(address owner, uint256 amount) public { + // transfer to user exactly amount, check the result + deal(address(underlyingToken), owner, amount); + assertEq(underlyingToken.balanceOf(owner), amount, "the full balance of cakeLP of user should equal amount"); + + vm.startPrank(owner); + underlyingToken.approve(address(beefyERC4626), amount); + beefyERC4626.mint(beefyERC4626.previewDeposit(amount), owner); vm.stopPrank(); } function increaseAssetsInVault() public { - sendUnderlyingToken(1000e18, address(beefyVault)); + deal(address(underlyingToken), address(beefyVault), 1000e18); beefyVault.earn(); } @@ -72,28 +120,31 @@ contract BeefyERC4626Test is WithPool, BaseTest { function testPreviewDepositAndMintReturnTheSameValue() public shouldRun(forChains(BSC_MAINNET)) { uint256 returnedShares = beefyERC4626.previewDeposit(depositAmount); - assertEq(beefyERC4626.previewMint(returnedShares), depositAmount); + assertTrue(diff(beefyERC4626.previewMint(returnedShares), depositAmount) <= 1, "!same value"); } function testPreviewWithdrawAndRedeemReturnTheSameValue() public shouldRun(forChains(BSC_MAINNET)) { deposit(address(this), depositAmount); uint256 withdrawalAmount = 10e18; uint256 reqShares = beefyERC4626.previewWithdraw(withdrawalAmount); - assertEq(beefyERC4626.previewRedeem(reqShares), withdrawalAmount); + assertTrue(diff(beefyERC4626.previewRedeem(reqShares), withdrawalAmount) <= 1, "!same value"); } function testDeposit() public shouldRun(forChains(BSC_MAINNET)) { - uint256 expectedBeefyShares = (depositAmount * initialBeefySupply) / iniitalBeefyBalance; + uint256 expectedBeefyShares = (depositAmount * initialBeefySupply) / initialBeefyBalance; uint256 expectedErc4626Shares = beefyERC4626.previewDeposit(depositAmount); deposit(address(this), depositAmount); // Test that the actual transfers worked - assertEq(beefyVault.balance(), iniitalBeefyBalance + depositAmount); + assertEq(beefyVault.balance(), initialBeefyBalance + depositAmount); // Test that the balance view calls work - assertEq(beefyERC4626.totalAssets(), depositAmount); - assertEq(beefyERC4626.balanceOfUnderlying(address(this)), depositAmount); + assertTrue(diff(beefyERC4626.totalAssets(), depositAmount) <= 1, "total assets don't match the deposited amount"); + assertTrue( + diff(depositAmount, beefyERC4626.balanceOfUnderlying(address(this))) <= 2, + "Underlying token balance should be almost the same as deposited amount" + ); // Test that we minted the correct amount of token assertEq(beefyERC4626.balanceOf(address(this)), expectedErc4626Shares); @@ -104,9 +155,7 @@ contract BeefyERC4626Test is WithPool, BaseTest { } function testDepositWithIncreasedVaultValue() public shouldRun(forChains(BSC_MAINNET)) { - sendUnderlyingToken(depositAmount, address(this)); - - uint256 oldExpectedBeefyShares = (depositAmount * initialBeefySupply) / iniitalBeefyBalance; + uint256 oldExpectedBeefyShares = (depositAmount * initialBeefySupply) / initialBeefyBalance; uint256 oldExpected4626Shares = beefyERC4626.previewDeposit(depositAmount); deposit(address(this), depositAmount); @@ -132,54 +181,79 @@ contract BeefyERC4626Test is WithPool, BaseTest { } function testMultipleDeposit() public shouldRun(forChains(BSC_MAINNET)) { - uint256 expectedBeefyShares = (depositAmount * initialBeefySupply) / iniitalBeefyBalance; + uint256 expectedBeefyShares = (depositAmount * initialBeefySupply) / initialBeefyBalance; uint256 expectedErc4626Shares = beefyERC4626.previewDeposit(depositAmount); deposit(address(this), depositAmount); - deposit(address(1), depositAmount); + deposit(alice, depositAmount); // Test that the actual transfers worked - assertEq(beefyVault.balance(), iniitalBeefyBalance + depositAmount * 2); + assertEq( + beefyVault.balance(), + initialBeefyBalance + depositAmount * 2, + "mint didn't transfer any tokens from the minter" + ); // Test that the balance view calls work assertTrue( - depositAmount * 2 - beefyERC4626.totalAssets() <= 1, - "Beefy total Assets should be same as sum of deposited amounts" + diff(depositAmount * 2, beefyERC4626.totalAssets()) <= 2, + "Beefy total Assets should be almost the same as sum of deposited amounts" ); assertTrue( - depositAmount - beefyERC4626.balanceOfUnderlying(address(this)) <= 1, - "Underlying token balance should be same as depositied amount" + diff(depositAmount, beefyERC4626.balanceOfUnderlying(address(this))) <= 2, + "Underlying token balance should be almost the same as deposited amount" ); assertTrue( - depositAmount - beefyERC4626.balanceOfUnderlying(address(1)) <= 1, - "Underlying token balance should be same as depositied amount" + diff(depositAmount, beefyERC4626.balanceOfUnderlying(alice)) <= 2, + "Underlying token balance should be almost the same as deposited amount" ); // Test that we minted the correct amount of token - assertEq(beefyERC4626.balanceOf(address(this)), expectedErc4626Shares); - assertEq(beefyERC4626.balanceOf(address(1)), expectedErc4626Shares); - assertEq(beefyERC4626.totalSupply(), expectedErc4626Shares * 2); + assertTrue( + diff(beefyERC4626.balanceOf(address(this)), expectedErc4626Shares) <= 1, + "the minted erc4626 shares don't match the expected shares amount" + ); + assertTrue( + diff(beefyERC4626.balanceOf(alice), expectedErc4626Shares) <= 1, + "the minted erc4626 for shares charlie don't match the expected shares amount" + ); + assertTrue( + diff(beefyERC4626.totalSupply(), expectedErc4626Shares * 2) <= 1, + "the total erc4626 shares don't match the expected shares amount" + ); // Test that the ERC4626 holds the expected amount of beefy shares - assertEq(beefyVault.balanceOf(address(beefyERC4626)), expectedBeefyShares * 2); + assertEq( + beefyVault.balanceOf(address(beefyERC4626)), + expectedBeefyShares * 2, + "the shares minted by the beefy vault don't match the expected amount" + ); // Beefy ERC4626 should not have underlyingToken after deposit assertEq(underlyingToken.balanceOf(address(beefyERC4626)), 0, "Beefy erc4626 locked amount checking"); } function testMint() public shouldRun(forChains(BSC_MAINNET)) { - uint256 expectedBeefyShares = (depositAmount * initialBeefySupply) / iniitalBeefyBalance; + uint256 expectedBeefyShares = (depositAmount * initialBeefySupply) / initialBeefyBalance; uint256 mintAmount = beefyERC4626.previewDeposit(depositAmount); - underlyingToken.approve(address(beefyERC4626), depositAmount); - beefyERC4626.mint(mintAmount, address(this)); + mint(address(this), depositAmount); + // underlyingToken.approve(address(beefyERC4626), depositAmount); + // beefyERC4626.mint(mintAmount, address(this)); // Test that the actual transfers worked - assertEq(beefyVault.balance(), iniitalBeefyBalance + depositAmount); + assertEq( + beefyVault.balance(), + initialBeefyBalance + depositAmount, + "mint didn't transfer any tokens from the minter" + ); // Test that the balance view calls work - assertEq(beefyERC4626.totalAssets(), depositAmount); - assertEq(beefyERC4626.balanceOfUnderlying(address(this)), depositAmount); + assertTrue(diff(beefyERC4626.totalAssets(), depositAmount) <= 1, "total assets don't match the deposited amount"); + assertTrue( + diff(depositAmount, beefyERC4626.balanceOfUnderlying(address(this))) <= 2, + "Underlying token balance should be almost the same as deposited amount" + ); // Test that we minted the correct amount of token assertEq(beefyERC4626.balanceOf(address(this)), mintAmount); @@ -190,52 +264,88 @@ contract BeefyERC4626Test is WithPool, BaseTest { } function testMultipleMint() public shouldRun(forChains(BSC_MAINNET)) { - uint256 expectedBeefyShares = (depositAmount * initialBeefySupply) / iniitalBeefyBalance; + uint256 expectedBeefyShares = (depositAmount * initialBeefySupply) / initialBeefyBalance; uint256 mintAmount = beefyERC4626.previewDeposit(depositAmount); - underlyingToken.approve(address(beefyERC4626), depositAmount); - beefyERC4626.mint(mintAmount, address(this)); + mint(address(this), depositAmount); + // underlyingToken.approve(address(beefyERC4626), depositAmount); + // beefyERC4626.mint(mintAmount, address(this)); // Test that the actual transfers worked - assertEq(beefyVault.balance(), iniitalBeefyBalance + depositAmount); + assertEq( + beefyVault.balance(), + initialBeefyBalance + depositAmount, + "mint didn't transfer any tokens from the minter" + ); // Test that the balance view calls work - assertEq(beefyERC4626.totalAssets(), depositAmount); - assertEq(beefyERC4626.balanceOfUnderlying(address(this)), depositAmount); + assertTrue(diff(beefyERC4626.totalAssets(), depositAmount) <= 1, "total assets don't match the deposited amount"); + assertTrue( + diff(beefyERC4626.balanceOfUnderlying(address(this)), depositAmount) <= 1, + "the assets on the depositor's account don't match the deposited amount" + ); // Test that we minted the correct amount of token - assertEq(beefyERC4626.balanceOf(address(this)), mintAmount); - assertEq(beefyERC4626.totalSupply(), mintAmount); + assertTrue( + diff(beefyERC4626.balanceOf(address(this)), mintAmount) <= 1, + "the minted erc4626 shares don't match the expected shares amount" + ); + assertEq(beefyERC4626.totalSupply(), mintAmount, "the total erc4626 shares don't match the expected shares amount"); // Test that the ERC4626 holds the expected amount of beefy shares - assertEq(beefyVault.balanceOf(address(beefyERC4626)), expectedBeefyShares); + assertEq( + beefyVault.balanceOf(address(beefyERC4626)), + expectedBeefyShares, + "the shares minted by the beefy vault don't match the expected amount" + ); assertTrue(underlyingToken.balanceOf(address(beefyERC4626)) <= 1, "Beefy erc4626 locked amount checking"); - vm.startPrank(address(1)); - underlyingToken.approve(address(beefyERC4626), depositAmount); - beefyERC4626.mint(mintAmount, address(1)); + // vm.startPrank(charlie); + mint(address(alice), depositAmount); + // underlyingToken.approve(address(beefyERC4626), depositAmount); + // beefyERC4626.mint(mintAmount, charlie); // Test that the actual transfers worked - assertEq(beefyVault.balance(), iniitalBeefyBalance + depositAmount + depositAmount); + assertEq( + beefyVault.balance(), + initialBeefyBalance + depositAmount + depositAmount, + "mint didn't transfer any tokens from the minter" + ); // Test that the balance view calls work - assertTrue(depositAmount + depositAmount - beefyERC4626.totalAssets() <= 1); - assertTrue(depositAmount - beefyERC4626.balanceOfUnderlying(address(1)) <= 1); + assertTrue( + diff(beefyERC4626.totalAssets(), depositAmount + depositAmount) <= 2, + "total assets don't match the deposited amount" + ); + assertTrue( + diff(depositAmount, beefyERC4626.balanceOfUnderlying(alice)) <= 1, + "the assets on the depositor's account don't match the deposited amount" + ); // Test that we minted the correct amount of token - assertEq(beefyERC4626.balanceOf(address(1)), mintAmount); - assertEq(beefyERC4626.totalSupply(), mintAmount + mintAmount); + assertTrue( + diff(beefyERC4626.balanceOf(alice), mintAmount) <= 1, + "the minted erc4626 shares don't match the expected shares amount" + ); + assertTrue( + diff(beefyERC4626.totalSupply(), mintAmount + mintAmount) <= 1, + "the total erc4626 shares don't match the expected shares amount" + ); // Test that the ERC4626 holds the expected amount of beefy shares - assertEq(beefyVault.balanceOf(address(beefyERC4626)), expectedBeefyShares * 2); + assertEq( + beefyVault.balanceOf(address(beefyERC4626)), + expectedBeefyShares * 2, + "the shares minted by the beefy vault don't match the expected amount" + ); assertTrue(underlyingToken.balanceOf(address(beefyERC4626)) <= 2, "Beefy erc4626 locked amount checking"); - vm.stopPrank(); + // vm.stopPrank(); } function testWithdraw() public shouldRun(forChains(BSC_MAINNET)) { - uint256 beefyShares = (depositAmount * initialBeefySupply) / iniitalBeefyBalance; + uint256 beefyShares = (depositAmount * initialBeefySupply) / initialBeefyBalance; uint256 withdrawalAmount = 10e18; @@ -253,7 +363,7 @@ contract BeefyERC4626Test is WithPool, BaseTest { // Test that the actual transfers worked assertTrue( - diff(underlyingToken.balanceOf(address(this)), assetBalBefore + withdrawalAmount) <= 1, + diff(underlyingToken.balanceOf(address(this)), assetBalBefore + withdrawalAmount) <= 2, "!user asset bal" ); @@ -276,9 +386,7 @@ contract BeefyERC4626Test is WithPool, BaseTest { } function testWithdrawWithIncreasedVaultValue() public shouldRun(forChains(BSC_MAINNET)) { - sendUnderlyingToken(depositAmount, address(this)); - - uint256 beefyShareBal = (depositAmount * initialBeefySupply) / iniitalBeefyBalance; + uint256 beefyShareBal = (depositAmount * initialBeefySupply) / initialBeefyBalance; deposit(address(this), depositAmount); @@ -320,12 +428,12 @@ contract BeefyERC4626Test is WithPool, BaseTest { } function testMultipleWithdraw() public shouldRun(forChains(BSC_MAINNET)) { - uint256 beefyShares = ((depositAmount * initialBeefySupply) / iniitalBeefyBalance) * 2; + uint256 beefyShares = ((depositAmount * initialBeefySupply) / initialBeefyBalance) * 2; uint256 withdrawalAmount = 10e18; deposit(address(this), depositAmount); - deposit(address(1), depositAmount); + deposit(alice, depositAmount); uint256 assetBalBefore = underlyingToken.balanceOf(address(this)); uint256 erc4626BalBefore = beefyERC4626.balanceOf(address(this)); @@ -339,7 +447,7 @@ contract BeefyERC4626Test is WithPool, BaseTest { // Test that the actual transfers worked assertTrue( - diff(underlyingToken.balanceOf(address(this)), assetBalBefore + withdrawalAmount) <= 1, + diff(underlyingToken.balanceOf(address(this)), assetBalBefore + withdrawalAmount) <= 2, "!user asset bal" ); @@ -347,15 +455,14 @@ contract BeefyERC4626Test is WithPool, BaseTest { // I just couldnt not calculate this properly. i was for some reason always ~ 1 BPS off // uint256 expectedAssetsAfter = depositAmount - (expectedBeefySharesNeeded + (expectedBeefySharesNeeded / 1000)); //assertEq(beefyERC4626.totalAssets(), expectedAssetsAfter, "!erc4626 asset bal"); - assertTrue(depositAmount * 2 - expectedErc4626SharesNeeded - beefyERC4626.totalSupply() < 1, "!totalSupply"); + assertTrue(diff(depositAmount * 2, expectedErc4626SharesNeeded + beefyERC4626.totalSupply()) <= 1, "!totalSupply"); // Test that we burned the right amount of shares assertEq(beefyERC4626.balanceOf(address(this)), erc4626BalBefore - expectedErc4626SharesNeeded, "!erc4626 supply"); // Test that the ERC4626 holds the expected amount of beefy shares - assertEq( - beefyVault.balanceOf(address(beefyERC4626)), - beefyShares - expectedBeefySharesNeeded, + assertTrue( + diff(beefyVault.balanceOf(address(beefyERC4626)), beefyShares - expectedBeefySharesNeeded) <= 1, "!beefy share balance" ); @@ -363,33 +470,32 @@ contract BeefyERC4626Test is WithPool, BaseTest { uint256 totalSupplyBefore = depositAmount * 2 - expectedErc4626SharesNeeded; beefyShares = beefyShares - expectedBeefySharesNeeded; - assetBalBefore = underlyingToken.balanceOf(address(1)); - erc4626BalBefore = beefyERC4626.balanceOf(address(1)); + assetBalBefore = underlyingToken.balanceOf(alice); + erc4626BalBefore = beefyERC4626.balanceOf(alice); expectedErc4626SharesNeeded = beefyERC4626.previewWithdraw(withdrawalAmount); expectedBeefySharesNeeded = expectedErc4626SharesNeeded.mulDivUp( beefyVault.balanceOf(address(beefyERC4626)), beefyERC4626.totalSupply() ); - vm.prank(address(1)); - beefyERC4626.withdraw(10e18, address(1), address(1)); + vm.prank(alice); + beefyERC4626.withdraw(10e18, alice, alice); // Test that the actual transfers worked - assertTrue(diff(underlyingToken.balanceOf(address(1)), assetBalBefore + withdrawalAmount) <= 1, "!user asset bal"); + assertTrue(diff(underlyingToken.balanceOf(alice), assetBalBefore + withdrawalAmount) <= 2, "!user asset bal"); // Test that the balance view calls work // I just couldnt not calculate this properly. i was for some reason always ~ 1 BPS off // uint256 expectedAssetsAfter = depositAmount - (expectedBeefySharesNeeded + (expectedBeefySharesNeeded / 1000)); //assertEq(beefyERC4626.totalAssets(), expectedAssetsAfter, "!erc4626 asset bal"); - assertEq(beefyERC4626.totalSupply(), totalSupplyBefore - expectedErc4626SharesNeeded, "!totalSupply"); + assertTrue(diff(beefyERC4626.totalSupply(), totalSupplyBefore - expectedErc4626SharesNeeded) <= 1, "!totalSupply"); // Test that we burned the right amount of shares - assertEq(beefyERC4626.balanceOf(address(1)), erc4626BalBefore - expectedErc4626SharesNeeded, "!erc4626 supply"); + assertEq(beefyERC4626.balanceOf(alice), erc4626BalBefore - expectedErc4626SharesNeeded, "!erc4626 supply"); // Test that the ERC4626 holds the expected amount of beefy shares - assertEq( - beefyVault.balanceOf(address(beefyERC4626)), - beefyShares - expectedBeefySharesNeeded, + assertTrue( + diff(beefyVault.balanceOf(address(beefyERC4626)), beefyShares - expectedBeefySharesNeeded) <= 1, "!beefy share balance" ); @@ -397,7 +503,7 @@ contract BeefyERC4626Test is WithPool, BaseTest { } function testRedeem() public shouldRun(forChains(BSC_MAINNET)) { - uint256 beefyShares = (depositAmount * initialBeefySupply) / iniitalBeefyBalance; + uint256 beefyShares = (depositAmount * initialBeefySupply) / initialBeefyBalance; uint256 withdrawalAmount = 10e18; uint256 redeemAmount = beefyERC4626.previewWithdraw(withdrawalAmount); @@ -415,7 +521,7 @@ contract BeefyERC4626Test is WithPool, BaseTest { // Test that the actual transfers worked assertTrue( - diff(underlyingToken.balanceOf(address(this)), assetBalBefore + withdrawalAmount) <= 1, + diff(underlyingToken.balanceOf(address(this)), assetBalBefore + withdrawalAmount) <= 2, "!user asset bal" ); @@ -437,13 +543,13 @@ contract BeefyERC4626Test is WithPool, BaseTest { } function testMultipleRedeem() public shouldRun(forChains(BSC_MAINNET)) { - uint256 beefyShares = ((depositAmount * initialBeefySupply) / iniitalBeefyBalance) * 2; + uint256 beefyShares = ((depositAmount * initialBeefySupply) / initialBeefyBalance) * 2; uint256 withdrawalAmount = 10e18; uint256 redeemAmount = beefyERC4626.previewWithdraw(withdrawalAmount); deposit(address(this), depositAmount); - deposit(address(1), depositAmount); + deposit(alice, depositAmount); uint256 assetBalBefore = underlyingToken.balanceOf(address(this)); uint256 erc4626BalBefore = beefyERC4626.balanceOf(address(this)); @@ -456,7 +562,7 @@ contract BeefyERC4626Test is WithPool, BaseTest { // Test that the actual transfers worked assertTrue( - diff(underlyingToken.balanceOf(address(this)), assetBalBefore + withdrawalAmount) <= 1, + diff(underlyingToken.balanceOf(address(this)), assetBalBefore + withdrawalAmount) <= 2, "!user asset bal" ); @@ -464,7 +570,7 @@ contract BeefyERC4626Test is WithPool, BaseTest { // I just couldnt not calculate this properly. i was for some reason always ~ 1 BPS off // uint256 expectedAssetsAfter = depositAmount - (expectedBeefySharesNeeded + (expectedBeefySharesNeeded / 1000)); //assertEq(beefyERC4626.totalAssets(), expectedAssetsAfter, "!erc4626 asset bal"); - assertEq(beefyERC4626.totalSupply(), depositAmount * 2 - redeemAmount, "!totalSupply"); + assertTrue(diff(beefyERC4626.totalSupply(), depositAmount * 2 - redeemAmount) <= 1, "!totalSupply"); // Test that we burned the right amount of shares assertEq(beefyERC4626.balanceOf(address(this)), erc4626BalBefore - redeemAmount, "!erc4626 supply"); @@ -480,26 +586,26 @@ contract BeefyERC4626Test is WithPool, BaseTest { uint256 totalSupplyBefore = depositAmount * 2 - redeemAmount; beefyShares -= expectedBeefySharesNeeded; redeemAmount = beefyERC4626.previewWithdraw(withdrawalAmount); - assetBalBefore = underlyingToken.balanceOf(address(1)); - erc4626BalBefore = beefyERC4626.balanceOf(address(1)); + assetBalBefore = underlyingToken.balanceOf(alice); + erc4626BalBefore = beefyERC4626.balanceOf(alice); expectedBeefySharesNeeded = redeemAmount.mulDivUp( beefyVault.balanceOf(address(beefyERC4626)), beefyERC4626.totalSupply() ); - vm.prank(address(1)); - beefyERC4626.withdraw(10e18, address(1), address(1)); + vm.prank(alice); + beefyERC4626.withdraw(10e18, alice, alice); // Test that the actual transfers worked - assertTrue(diff(underlyingToken.balanceOf(address(1)), assetBalBefore + withdrawalAmount) <= 1, "!user asset bal"); + assertTrue(diff(underlyingToken.balanceOf(alice), assetBalBefore + withdrawalAmount) <= 2, "!user asset bal"); // Test that the balance view calls work // I just couldnt not calculate this properly. i was for some reason always ~ 1 BPS off // uint256 expectedAssetsAfter = depositAmount - (expectedBeefySharesNeeded + (expectedBeefySharesNeeded / 1000)); //assertEq(beefyERC4626.totalAssets(), expectedAssetsAfter, "!erc4626 asset bal"); - assertEq(beefyERC4626.totalSupply(), totalSupplyBefore - redeemAmount, "!totalSupply"); + assertTrue(diff(beefyERC4626.totalSupply(), totalSupplyBefore - redeemAmount) <= 1, "!totalSupply"); // Test that we burned the right amount of shares - assertEq(beefyERC4626.balanceOf(address(1)), erc4626BalBefore - redeemAmount, "!erc4626 supply"); + assertEq(beefyERC4626.balanceOf(alice), erc4626BalBefore - redeemAmount, "!erc4626 supply"); // Test that the ERC4626 holds the expected amount of beefy shares assertEq( @@ -576,63 +682,17 @@ contract BeefyERC4626Test is WithPool, BaseTest { ); assertEq(underlyingToken.balanceOf(address(this)), withdrawAmount + expectedAssets, "!redeem asset bal"); } -} - -contract BeefyERC4626UnitTest is BaseTest { - BeefyERC4626 beefyERC4626; - address cakeLPAddress = 0x84392649eb0bC1c1532F2180E58Bae4E1dAbd8D6; - address beefyStrategyAddress = 0x1083926054069AaD75d7238E9B809b0eF9d94e5B; - address beefyVaultAddress = 0x94E85B8E050F3F281CB9597cc0144F1F7AF1fe9B; - address alice = address(10); - address bob = address(20); - address charlie = address(30); - IBeefyVault beefyVault; - ERC20 cakeLpToken; - - function setUp() public shouldRun(forChains(BSC_MAINNET)) { - beefyVault = IBeefyVault(beefyVaultAddress); - beefyERC4626 = new BeefyERC4626(ERC20(cakeLPAddress), beefyVault, 10); - cakeLpToken = ERC20(cakeLPAddress); - } - - function deposit(address user, uint256 amount) internal { - // transfer to user exactly amount - vm.prank(alice); - cakeLpToken.transfer(user, amount); - assertEq(cakeLpToken.balanceOf(user), amount, "the full balance of cakeLP of user should equal amount"); - - // deposit the full amount to the plugin as user, check the result - vm.startPrank(user); - cakeLpToken.approve(address(beefyERC4626), amount); - beefyERC4626.deposit(amount, user); - vm.stopPrank(); - } - - function mint(address user, uint256 amount) internal { - // transfer to user exactly amount - vm.prank(alice); - cakeLpToken.transfer(user, amount); - assertEq(cakeLpToken.balanceOf(user), amount, "the full balance of cakeLP of user should equal amount"); - - // deposit the full amount to the plugin as user, check the result - vm.startPrank(user); - cakeLpToken.approve(address(beefyERC4626), amount); - beefyERC4626.mint(beefyERC4626.previewDeposit(amount), user); - vm.stopPrank(); - } function testTheBugWithdraw(uint256 amount) public shouldRun(forChains(BSC_MAINNET)) { vm.assume(amount > 100 && amount < 1e19); - vm.prank(beefyStrategyAddress); - cakeLpToken.transfer(alice, 100e18); deposit(bob, amount); // make sure the full amount is deposited and none is left - assertEq(cakeLpToken.balanceOf(bob), 0, "should deposit the full balance of cakeLP of user"); - assertEq(cakeLpToken.balanceOf(address(beefyERC4626)), 0, "should deposit the full balance of cakeLP of user"); + assertEq(underlyingToken.balanceOf(bob), 0, "should deposit the full balance of cakeLP of user"); + assertEq(underlyingToken.balanceOf(address(beefyERC4626)), 0, "should deposit the full balance of cakeLP of user"); // just testing if other users depositing would mess up the calcs - mint(charlie, amount); + mint(alice, amount); // test if the shares of the BeefyERC4626 equal to the assets deposited uint256 beefyERC4626SharesMintedToBob = beefyERC4626.balanceOf(bob); @@ -646,7 +706,7 @@ contract BeefyERC4626UnitTest is BaseTest { vm.startPrank(bob); uint256 assetsToWithdraw = amount / 2; beefyERC4626.withdraw(assetsToWithdraw, bob, bob); - uint256 assetsWithdrawn = cakeLpToken.balanceOf(bob); + uint256 assetsWithdrawn = underlyingToken.balanceOf(bob); assertTrue( diff(assetsWithdrawn, assetsToWithdraw) < 100, "the assets withdrawn must be almost equal to the requested assets to withdraw" @@ -654,7 +714,7 @@ contract BeefyERC4626UnitTest is BaseTest { vm.stopPrank(); } - uint256 lockedFunds = cakeLpToken.balanceOf(address(beefyERC4626)); + uint256 lockedFunds = underlyingToken.balanceOf(address(beefyERC4626)); { emit log_uint(lockedFunds); } @@ -664,19 +724,17 @@ contract BeefyERC4626UnitTest is BaseTest { function testTheBugRedeem(uint256 amount) public shouldRun(forChains(BSC_MAINNET)) { vm.assume(amount > 1e5 && amount < 1e19); - vm.prank(beefyStrategyAddress); - cakeLpToken.transfer(alice, 100e18); - deposit(charlie, amount); + deposit(alice, amount); // make sure the full amount is deposited and none is left - assertEq(cakeLpToken.balanceOf(charlie), 0, "should deposit the full balance of cakeLP of user"); - assertEq(cakeLpToken.balanceOf(address(beefyERC4626)), 0, "should deposit the full balance of cakeLP of user"); + assertEq(underlyingToken.balanceOf(alice), 0, "should deposit the full balance of cakeLP of user"); + assertEq(underlyingToken.balanceOf(address(beefyERC4626)), 0, "should deposit the full balance of cakeLP of user"); // just testing if other users depositing would mess up the calcs mint(bob, amount); // test if the shares of the BeefyERC4626 equal to the assets deposited - uint256 beefyERC4626SharesMintedToCharlie = beefyERC4626.balanceOf(charlie); + uint256 beefyERC4626SharesMintedToCharlie = beefyERC4626.balanceOf(alice); assertEq( beefyERC4626SharesMintedToCharlie, amount, @@ -684,11 +742,11 @@ contract BeefyERC4626UnitTest is BaseTest { ); { - vm.startPrank(charlie); - uint256 beefyERC4626SharesToRedeem = beefyERC4626.balanceOf(charlie); - beefyERC4626.redeem(beefyERC4626SharesToRedeem, charlie, charlie); - uint256 assetsRedeemed = cakeLpToken.balanceOf(charlie); + vm.startPrank(alice); + uint256 beefyERC4626SharesToRedeem = beefyERC4626.balanceOf(alice); uint256 assetsToRedeem = beefyERC4626.previewRedeem(beefyERC4626SharesToRedeem); + beefyERC4626.redeem(beefyERC4626SharesToRedeem, alice, alice); + uint256 assetsRedeemed = underlyingToken.balanceOf(alice); { emit log_uint(assetsRedeemed); emit log_uint(assetsToRedeem); @@ -700,7 +758,7 @@ contract BeefyERC4626UnitTest is BaseTest { vm.stopPrank(); } - uint256 lockedFunds = cakeLpToken.balanceOf(address(beefyERC4626)); + uint256 lockedFunds = underlyingToken.balanceOf(address(beefyERC4626)); { emit log_uint(lockedFunds); } diff --git a/contracts/test/BombE2eTest.t.sol b/contracts/test/BombE2eTest.t.sol index 071dab5ae..ba7640cac 100644 --- a/contracts/test/BombE2eTest.t.sol +++ b/contracts/test/BombE2eTest.t.sol @@ -14,6 +14,7 @@ import { IRedemptionStrategy } from "../liquidators/IRedemptionStrategy.sol"; import { IUniswapV2Router02 } from "../external/uniswap/IUniswapV2Router02.sol"; import { IComptroller } from "../external/compound/IComptroller.sol"; import { FusePoolLensSecondary } from "../FusePoolLensSecondary.sol"; +import { ICErc20 } from "../external/compound/ICErc20.sol"; interface MockXBomb { function getExchangeRate() external returns (uint256); @@ -26,9 +27,6 @@ contract MockBnb is MockERC20 { } contract BombE2eTest is WithPool, BaseTest { - using stdStorage for StdStorage; - StdStorage internal stdstore; - constructor() WithPool( MasterPriceOracle(0xB641c21124546e1c979b4C1EbF13aB00D43Ee8eA), diff --git a/contracts/test/ChainlinkOracleTest.t.sol b/contracts/test/ChainlinkOracleTest.t.sol index c164d9418..98b8af73f 100644 --- a/contracts/test/ChainlinkOracleTest.t.sol +++ b/contracts/test/ChainlinkOracleTest.t.sol @@ -10,7 +10,7 @@ contract ChainlinkOraclesTest is BaseTest { ChainlinkPriceOracleV2 oracle; function setUp() public { - oracle = ChainlinkPriceOracleV2(ap.getAddress("chainlinkOracle")); + oracle = ChainlinkPriceOracleV2(ap.getAddress("ChainlinkPriceOracleV2")); } function testPriceFeed(address testedTokenAddress, address aggregatorAddress) internal returns (uint256 price) { diff --git a/contracts/test/CurveLpTokenLiquidatorNoRegistryTest.t.sol b/contracts/test/CurveLpTokenLiquidatorNoRegistryTest.t.sol index 15a455bd8..3a16314f9 100644 --- a/contracts/test/CurveLpTokenLiquidatorNoRegistryTest.t.sol +++ b/contracts/test/CurveLpTokenLiquidatorNoRegistryTest.t.sol @@ -7,6 +7,7 @@ import { WETH } from "solmate/tokens/WETH.sol"; import "openzeppelin-contracts-upgradeable/contracts/token/ERC20/IERC20Upgradeable.sol"; import { CurveLpTokenLiquidatorNoRegistry } from "../liquidators/CurveLpTokenLiquidatorNoRegistry.sol"; +import { CurveLpTokenPriceOracleNoRegistry } from "../oracles/default/CurveLpTokenPriceOracleNoRegistry.sol"; import "../utils/IW_NATIVE.sol"; import "../external/curve/ICurvePool.sol"; import "./config/BaseTest.t.sol"; diff --git a/contracts/test/TwapOraclesBaseTest.t.sol b/contracts/test/TwapOraclesBaseTest.t.sol index 3146d0155..bdf20514b 100644 --- a/contracts/test/TwapOraclesBaseTest.t.sol +++ b/contracts/test/TwapOraclesBaseTest.t.sol @@ -12,9 +12,9 @@ contract TwapOraclesBaseTest is BaseTest { MasterPriceOracle mpo; function setUp() public { - uniswapV2Factory = IUniswapV2Factory(ap.getAddress("uniswapV2Factory")); - twapPriceOracleFactory = UniswapTwapPriceOracleV2Factory(ap.getAddress("twapOraclesFactory")); - mpo = MasterPriceOracle(ap.getAddress("masterPriceOracle")); + uniswapV2Factory = IUniswapV2Factory(ap.getAddress("IUniswapV2Factory")); + twapPriceOracleFactory = UniswapTwapPriceOracleV2Factory(ap.getAddress("UniswapTwapPriceOracleV2Factory")); + mpo = MasterPriceOracle(ap.getAddress("MasterPriceOracle")); } function getTokenTwapPrice(address tokenAddress, address baseTokenAddress) internal returns (uint256) { diff --git a/contracts/test/UniswapLpTokenTest.t.sol b/contracts/test/UniswapLpTokenTest.t.sol index 90a34a7b9..0708bdae2 100644 --- a/contracts/test/UniswapLpTokenTest.t.sol +++ b/contracts/test/UniswapLpTokenTest.t.sol @@ -17,13 +17,12 @@ contract UniswapLpTokenBaseTest is BaseTest { function setUp() public { wtoken = ap.getAddress("wtoken"); - mpo = MasterPriceOracle(ap.getAddress("masterPriceOracle")); + mpo = MasterPriceOracle(ap.getAddress("MasterPriceOracle")); } function getLpTokenPrice(address lpToken) internal returns (uint256) { if (address(mpo.oracles(lpToken)) == address(0)) { uniswapLpTokenPriceOracle = new UniswapLpTokenPriceOracle(wtoken); // BTCB - IUniswapV2Pair pair = IUniswapV2Pair(lpToken); address[] memory underlyings = new address[](1); IPriceOracle[] memory oracles = new IPriceOracle[](1); diff --git a/contracts/test/config/BaseTest.t.sol b/contracts/test/config/BaseTest.t.sol index 6ffbab2eb..85df0e1ae 100644 --- a/contracts/test/config/BaseTest.t.sol +++ b/contracts/test/config/BaseTest.t.sol @@ -1,68 +1,38 @@ // SPDX-License-Identifier: UNLICENSED pragma solidity >=0.8.0; -import "ds-test/test.sol"; import "forge-std/Vm.sol"; +import "forge-std/Test.sol"; -import { WETH } from "solmate/tokens/WETH.sol"; -import "openzeppelin-contracts-upgradeable/contracts/token/ERC20/IERC20Upgradeable.sol"; - -import { CurveLpTokenPriceOracleNoRegistry } from "../../oracles/default/CurveLpTokenPriceOracleNoRegistry.sol"; -import "../../oracles/default/ChainlinkPriceOracleV2.sol"; -import "../../external/jarvis/ISynthereumLiquidityPool.sol"; -import "../../oracles/MasterPriceOracle.sol"; -import "../../oracles/default/UniswapTwapPriceOracleV2Factory.sol"; import "../../utils/AddressesProvider.sol"; -abstract contract BaseTest is DSTest { - Vm public constant vm = Vm(HEVM_ADDRESS); - +abstract contract BaseTest is Test { uint256 constant BSC_MAINNET = 56; uint256 constant MOONBEAM_MAINNET = 1284; uint256 constant EVMOS_TESTNET = 9000; uint256 constant BSC_CHAPEL = 97; - // TODO instantiate from the deployed delegator/storage address - // when there is an on-chain AddressesProvider instance to use - AddressesProvider ap = new AddressesProvider(); + AddressesProvider public ap; constructor() { - // TODO remove the config code - // when there is an on-chain AddressesProvider instance to use + if (block.chainid == BSC_MAINNET) { + ap = AddressesProvider(0x01c97299b37E66c03419bC4Db24074a89FB36e6d); + } else if (block.chainid == BSC_CHAPEL) { + ap = AddressesProvider(0x38742363597fBaE312B0bdcC351fCc6107E9E27E); + } else if (block.chainid == MOONBEAM_MAINNET) { + ap = AddressesProvider(0x771ee5a72A57f3540E5b9A6A8C226C2a24A70Fae); + } else if (block.chainid == EVMOS_TESTNET) { + ap = AddressesProvider(0xB88C6a114F01a80Dc8465b55067C8D046C2F445A); + } else { + ap = new AddressesProvider(); + } configureAddressesProvider(); } function configureAddressesProvider() internal { if (ap.owner() == address(0)) { ap.initialize(address(this)); - if (block.chainid == BSC_MAINNET) { - // external addresses - ap.setAddress("wtoken", 0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095c); - ap.setAddress("uniswapV2Factory", 0xcA143Ce32Fe78f1f7019d7d551a6402fC5350c73); - - ap.setAddress("bUSD", 0xe9e7CEA3DedcA5984780Bafc599bD69ADd087D56); - - // system addresses - ap.setAddress("masterPriceOracle", 0xC3ABf2cB82C65474CeF8F90f1a4DAe79929B1940); - ap.setAddress("twapOraclesFactory", 0x8853F26C198fd5693E7886C081164E0c3F0a4E51); - ap.setAddress("chainlinkOracle", 0x2B5311De4555506400273CfaAFb4393F01EC2567); - } else if (block.chainid == BSC_CHAPEL) { - // external addresses - ap.setAddress("wtoken", 0xae13d989daC2f0dEbFf460aC112a837C89BAa7cd); - ap.setAddress("uniswapV2Factory", 0xB7926C0430Afb07AA7DEfDE6DA862aE0Bde767bc); - - // system addresses - ap.setAddress("masterPriceOracle", 0xC3ABf2cB82C65474CeF8F90f1a4DAe79929B1940); - ap.setAddress("twapOraclesFactory", 0x944fed08a91983d06f653E9F55Eca995316Ccd3e); - } else if (block.chainid == MOONBEAM_MAINNET) { - // external addresses - ap.setAddress("wtoken", 0xAcc15dC74880C9944775448304B263D191c6077F); - ap.setAddress("uniswapV2Factory", 0x985BcA32293A7A496300a48081947321177a86FD); - - // system addresses - ap.setAddress("masterPriceOracle", 0x14C15B9ec83ED79f23BF71D51741f58b69ff1494); - } } } @@ -80,7 +50,7 @@ abstract contract BaseTest is DSTest { return block.chainid == id0 || block.chainid == id1; } - function diff(uint256 a, uint256 b) internal returns (uint256) { + function diff(uint256 a, uint256 b) internal pure returns (uint256) { if (a > b) { return a - b; } else { diff --git a/lib/ds-test b/lib/ds-test index 2c7dbcc85..9310e879d 160000 --- a/lib/ds-test +++ b/lib/ds-test @@ -1 +1 @@ -Subproject commit 2c7dbcc8586b33f358e3307a443e524490c17666 +Subproject commit 9310e879db8ba3ea6d5c6489a579118fd264a3f5 diff --git a/lib/forge-std b/lib/forge-std index e26ae2954..98256095f 160000 --- a/lib/forge-std +++ b/lib/forge-std @@ -1 +1 @@ -Subproject commit e26ae2954bb6d883643b92760d443dd07f413647 +Subproject commit 98256095f37d83653ba1617d06ccd9604cbd7c6d diff --git a/lib/openzeppelin-contracts b/lib/openzeppelin-contracts index 14ca3aeb7..5a7506565 160000 --- a/lib/openzeppelin-contracts +++ b/lib/openzeppelin-contracts @@ -1 +1 @@ -Subproject commit 14ca3aeb798d9b9be31df86ae7ef8b8f760caa4c +Subproject commit 5a75065659a65e65bb04890192e3a4bcb7917fff diff --git a/lib/openzeppelin-contracts-upgradeable b/lib/openzeppelin-contracts-upgradeable index 9b786055f..2b26001cd 160000 --- a/lib/openzeppelin-contracts-upgradeable +++ b/lib/openzeppelin-contracts-upgradeable @@ -1 +1 @@ -Subproject commit 9b786055f3b423c8fc4b7fdf790954280ef6bb5b +Subproject commit 2b26001cdd1bcac507fcd4015de70059acc1ee5f diff --git a/lib/solmate b/lib/solmate index 4197b521e..3c738133a 160000 --- a/lib/solmate +++ b/lib/solmate @@ -1 +1 @@ -Subproject commit 4197b521ef3eb81f675d35e64b7b597b24d33500 +Subproject commit 3c738133a0c1697096d63d28ef7a8ef298f9af6b