diff --git a/cache/solidity-files-cache.json b/cache/solidity-files-cache.json index d67a2fcd..ccd384ee 100644 --- a/cache/solidity-files-cache.json +++ b/cache/solidity-files-cache.json @@ -5285,7 +5285,7 @@ } }, "src/oracles/chainlink/ChainlinkMultiOracle.sol": { - "lastModificationDate": 1677499641263, + "lastModificationDate": 1678452737622, "contentHash": "a22b18e9ca40e7135457b337d8c3fd38", "sourceName": "src/oracles/chainlink/ChainlinkMultiOracle.sol", "solcConfig": { @@ -8614,7 +8614,7 @@ } }, "src/test/oracles/ChainlinkMultiOracle.t.sol": { - "lastModificationDate": 1677499641253, + "lastModificationDate": 1678444665979, "contentHash": "55fbea7071b38f2f3fa3ef4575a80a0c", "sourceName": "src/test/oracles/ChainlinkMultiOracle.t.sol", "solcConfig": { @@ -8767,7 +8767,7 @@ } }, "src/test/oracles/CompositeMultiOracle.t.sol": { - "lastModificationDate": 1677499641252, + "lastModificationDate": 1678444665979, "contentHash": "18568dad409a49eb28f92db83eb4d627", "sourceName": "src/test/oracles/CompositeMultiOracle.t.sol", "solcConfig": { @@ -8917,7 +8917,7 @@ } }, "src/test/oracles/ConvexOracle.t.sol": { - "lastModificationDate": 1677499641252, + "lastModificationDate": 1678444665980, "contentHash": "c513d51dd4cb2b35182e954712254e66", "sourceName": "src/test/oracles/ConvexOracle.t.sol", "solcConfig": { @@ -9219,7 +9219,7 @@ } }, "src/test/oracles/LidoOracle.t.sol": { - "lastModificationDate": 1677499641251, + "lastModificationDate": 1678444665980, "contentHash": "c7d1f36325a705467a6f7e1db92e5881", "sourceName": "src/test/oracles/LidoOracle.t.sol", "solcConfig": { @@ -10573,8 +10573,8 @@ } }, "src/test/variable/Fixture.sol": { - "lastModificationDate": 1678446385283, - "contentHash": "fc4956ce6e38d66239547bbb17631b0f", + "lastModificationDate": 1678454873938, + "contentHash": "5b8aed38036c584b6681df1962824cf9", "sourceName": "src/test/variable/Fixture.sol", "solcConfig": { "settings": { @@ -10687,8 +10687,8 @@ } }, "src/test/variable/FixtureStates.sol": { - "lastModificationDate": 1678446363485, - "contentHash": "c7ec7e0e8c8b25aaacd6eac651325e8e", + "lastModificationDate": 1678454156111, + "contentHash": "4c64fb46fb3db86f5143cee7ea92d160", "sourceName": "src/test/variable/FixtureStates.sol", "solcConfig": { "settings": { @@ -10842,8 +10842,8 @@ } }, "src/test/variable/VRCauldron.t.sol": { - "lastModificationDate": 1678446537965, - "contentHash": "575777a72a96316834adcc827cdadcdd", + "lastModificationDate": 1678454824036, + "contentHash": "ba4292ec5ce982ff5c98e6a794e866d5", "sourceName": "src/test/variable/VRCauldron.t.sol", "solcConfig": { "settings": { @@ -10992,8 +10992,8 @@ } }, "src/test/variable/VRLadle.t.sol": { - "lastModificationDate": 1678446550925, - "contentHash": "b32a5c3338fdab98e570a7d63456dbee", + "lastModificationDate": 1678447926085, + "contentHash": "fc74b6ea9350274fe7c8e183e65c7645", "sourceName": "src/test/variable/VRLadle.t.sol", "solcConfig": { "settings": { @@ -11240,8 +11240,8 @@ } }, "src/test/variable/VYToken.t.sol": { - "lastModificationDate": 1678445284186, - "contentHash": "e4cb4fbcb2f75c31dad3aef846d887ae", + "lastModificationDate": 1678447569385, + "contentHash": "cb00187c5c2c0c5e40c53886f9c1e6a5", "sourceName": "src/test/variable/VYToken.t.sol", "solcConfig": { "settings": { @@ -11409,7 +11409,7 @@ } }, "src/variable/VRCauldron.sol": { - "lastModificationDate": 1678447057859, + "lastModificationDate": 1678452731223, "contentHash": "ba4c7748a2efd3576c60afc6ed4d6831", "sourceName": "src/variable/VRCauldron.sol", "solcConfig": { @@ -11461,7 +11461,7 @@ } }, "src/variable/VRLadle.sol": { - "lastModificationDate": 1678446439706, + "lastModificationDate": 1678454862108, "contentHash": "5ba14c8e5bb475b7b7179227836f247a", "sourceName": "src/variable/VRLadle.sol", "solcConfig": { diff --git a/src/test/variable/Fixture.sol b/src/test/variable/Fixture.sol index 95c1c5d6..2c664c74 100644 --- a/src/test/variable/Fixture.sol +++ b/src/test/variable/Fixture.sol @@ -35,9 +35,11 @@ import "@yield-protocol/utils-v2/src/utils/Math.sol"; using Cast for uint256; using Cast for uint256; using Math for uint256; + abstract contract Fixture is Test, TestConstants, TestExtensions { address public admin = makeAddr("admin"); address public user = makeAddr("user"); + address public immutable timelock; VRCauldron public cauldron; VRLadle public ladle; Witch public witch; @@ -64,8 +66,6 @@ abstract contract Fixture is Test, TestConstants, TestExtensions { AccumulatorMultiOracle public chiRateOracle; ChainlinkMultiOracle public spotOracle; ChainlinkAggregatorV3Mock public ethAggregator; - ChainlinkAggregatorV3Mock public daiAggregator; - ChainlinkAggregatorV3Mock public usdcAggregator; ChainlinkAggregatorV3Mock public baseAggregator; bytes12 public vaultId = 0x000000000000000000000001; @@ -80,10 +80,21 @@ abstract contract Fixture is Test, TestConstants, TestExtensions { uint256 public ART = WAD; uint256 public FEE = 1000; uint128 public unit; + + address USDC_JOIN = address(0x0d9A1A773be5a83eEbda23bf98efB8585C3ae4f4); + address DAI_JOIN = address(0x4fE92119CDf873Cf8826F4E6EcfD4E578E3D44Dc); + address WETH_JOIN = address(0x3bDb887Dc46ec0E964Df89fFE2980db0121f0fD0); + + constructor() { + timelock = addresses[MAINNET][TIMELOCK]; + } + function setUp() public virtual { - usdc = new USDCMock(); - weth = new WETH9Mock(); - dai = new DAIMock(); + vm.createSelectFork(MAINNET, 16668354); + + usdc = USDCMock(0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48); + weth = WETH9Mock(payable(0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2)); + dai = DAIMock(0x6B175474E89094C44Da98b954EedeAC495271d0F); base = new ERC20Mock("Base", "BASE"); otherERC20 = new ERC20Mock("Other ERC20", "OTHERERC20"); @@ -94,16 +105,35 @@ abstract contract Fixture is Test, TestConstants, TestExtensions { ); witch = new Witch(ICauldron(address(cauldron)), ILadle(address(ladle))); - - restrictedERC20Mock = new RestrictedERC20Mock("Restricted", "RESTRICTED"); + restrictedERC20Mock = new RestrictedERC20Mock( + "Restricted", + "RESTRICTED" + ); + + usdcJoin = FlashJoin(USDC_JOIN); + wethJoin = FlashJoin(WETH_JOIN); + daiJoin = FlashJoin(DAI_JOIN); + + bytes4 role = 0x00000000; + vm.startPrank(timelock); + AccessControl access = AccessControl(address(usdcJoin)); + access.grantRole(role, address(this)); + access = AccessControl(address(wethJoin)); + access.grantRole(role, address(this)); + access = AccessControl(address(daiJoin)); + access.grantRole(role, address(this)); + vm.stopPrank(); - usdcJoin = new FlashJoin(address(usdc)); - wethJoin = new FlashJoin(address(weth)); - daiJoin = new FlashJoin(address(dai)); baseJoin = new FlashJoin(address(base)); setUpOracles(); - vyToken = new VYToken(baseId, IOracle(address(chiRateOracle)), IJoin(baseJoin),base.name(), base.symbol()); + vyToken = new VYToken( + daiId, + IOracle(address(chiRateOracle)), + IJoin(daiJoin), + dai.name(), + dai.symbol() + ); // Setting permissions ladleGovAuth(); cauldronGovAuth(address(ladle)); @@ -115,12 +145,16 @@ abstract contract Fixture is Test, TestConstants, TestExtensions { bytes4[] memory roles = new bytes4[](2); roles[0] = Join.join.selector; roles[1] = Join.exit.selector; - baseJoin.grantRoles(roles, address(vyToken)); + vm.prank(timelock); + daiJoin.grantRoles(roles, address(vyToken)); } function setUpOracles() internal { - chiRateOracle = new AccumulatorMultiOracle(); + chiRateOracle = AccumulatorMultiOracle( + 0x95750d6F5fba4ed1cc4Dc42D2c01dFD3DB9a11eC + ); + vm.startPrank(timelock); chiRateOracle.grantRole( AccumulatorMultiOracle.setSource.selector, address(this) @@ -129,34 +163,27 @@ abstract contract Fixture is Test, TestConstants, TestExtensions { AccumulatorMultiOracle.updatePerSecondRate.selector, address(this) ); + vm.stopPrank(); chiRateOracle.setSource(baseId, RATE, WAD, WAD * 2); - chiRateOracle.setSource(baseId, CHI, WAD, WAD * 2); ethAggregator = new ChainlinkAggregatorV3Mock(); ethAggregator.set(1e18 / 2); - daiAggregator = new ChainlinkAggregatorV3Mock(); - daiAggregator.set(1e18 / 2); - - usdcAggregator = new ChainlinkAggregatorV3Mock(); - usdcAggregator.set(1e18 / 2); - baseAggregator = new ChainlinkAggregatorV3Mock(); baseAggregator.set(1e18 / 2); - spotOracle = new ChainlinkMultiOracle(); + spotOracle = ChainlinkMultiOracle( + 0xcDCe5C87f691058B61f3A65913f1a3cBCbAd9F52 + ); + + bytes4 role = 0x00000000; + AccessControl access = AccessControl(address(spotOracle)); + vm.prank(timelock); spotOracle.grantRole( ChainlinkMultiOracle.setSource.selector, address(this) ); - spotOracle.setSource( - ETH, - IERC20Metadata(address(weth)), - usdcId, - IERC20Metadata(address(usdc)), - address(usdcAggregator) - ); spotOracle.setSource( ETH, IERC20Metadata(address(weth)), @@ -164,13 +191,6 @@ abstract contract Fixture is Test, TestConstants, TestExtensions { IERC20Metadata(address(base)), address(ethAggregator) ); - spotOracle.setSource( - ETH, - IERC20Metadata(address(weth)), - daiId, - IERC20Metadata(address(dai)), - address(daiAggregator) - ); } // ----------------- Permissions ----------------- // @@ -225,11 +245,15 @@ abstract contract Fixture is Test, TestConstants, TestExtensions { address chirateoracle, uint8 salt ) internal { - cauldron.setRateOracle(assetId, IOracle(chirateoracle)); cauldron.addBase(assetId); - cauldron.setSpotOracle(assetId, assetId, IOracle(chirateoracle), 1000000); + cauldron.setSpotOracle( + assetId, + assetId, + IOracle(chirateoracle), + 1000000 + ); bytes6[] memory ilk = new bytes6[](1); ilk[0] = assetId; cauldron.addIlks(assetId, ilk); @@ -240,31 +264,33 @@ abstract contract Fixture is Test, TestConstants, TestExtensions { uint24(1e6), 18 ); - (bytes12 vaultId_,) = ladle.build(assetId, assetId, salt); - // cauldron.build(address(this), vaultId_, assetId, assetId); - IERC20(assetAddress).approve(address(join),INK * 10); + (bytes12 vaultId_, ) = ladle.build(assetId, assetId, salt); + + IERC20(assetAddress).approve(address(join), INK * 10); deal(assetAddress, address(this), INK * 10); ladle.pour(vaultId_, address(this), (INK * 10).i128(), 0); } - function getAbove(int128 ink,int128 art, bytes12 vault) internal returns(bool){ + function getAbove( + int128 ink, + int128 art, + bytes12 vault + ) internal returns (bool) { (, bytes6 baseId, bytes6 ilkId) = cauldron.vaults(vault); (IOracle oracle, uint32 ratio1) = cauldron.spotOracles(baseId, ilkId); uint256 ratio = uint256(ratio1) * 1e12; // Normalized to 18 decimals - (uint256 inkValue, ) = oracle.get( - ilkId, - baseId, - uint256(int(ink)) - ); // ink * spot + (uint256 inkValue, ) = oracle.get(ilkId, baseId, uint256(int(ink))); // ink * spot uint256 baseValue = cauldron.debtToBase(baseId, uint128(art)); - return inkValue.i256() - baseValue.wmul(ratio).i256() >=0; + return inkValue.i256() - baseValue.wmul(ratio).i256() >= 0; } - function giveMeDustAndLine(bytes12 vault) internal returns (uint128 dust, uint128 line) { + function giveMeDustAndLine( + bytes12 vault + ) internal returns (uint128 dust, uint128 line) { (, bytes6 baseId, bytes6 ilkId) = cauldron.vaults(vault); - (uint96 max, uint24 min, uint8 dec,) = cauldron.debt(baseId,ilkId); - dust = min * uint128(10)**dec; - line = max * uint128(10)**dec; + (uint96 max, uint24 min, uint8 dec, ) = cauldron.debt(baseId, ilkId); + dust = min * uint128(10) ** dec; + line = max * uint128(10) ** dec; } } diff --git a/src/test/variable/FixtureStates.sol b/src/test/variable/FixtureStates.sol index feaed235..f760caee 100644 --- a/src/test/variable/FixtureStates.sol +++ b/src/test/variable/FixtureStates.sol @@ -7,8 +7,19 @@ using Cast for uint256; abstract contract ZeroState is Fixture { // Events we are testing - event VaultPoured(bytes12 indexed vaultId, bytes6 indexed baseId, bytes6 indexed ilkId, int128 ink, int128 art); - event VaultStirred(bytes12 indexed from, bytes12 indexed to, uint128 ink, uint128 art); + event VaultPoured( + bytes12 indexed vaultId, + bytes6 indexed baseId, + bytes6 indexed ilkId, + int128 ink, + int128 art + ); + event VaultStirred( + bytes12 indexed from, + bytes12 indexed to, + uint128 ink, + uint128 art + ); event VaultDestroyed(bytes12 indexed vaultId); event VaultTweaked( bytes12 indexed vaultId, @@ -18,10 +29,19 @@ abstract contract ZeroState is Fixture { event VaultGiven(bytes12 indexed vaultId, address indexed receiver); event TokenAdded(address indexed token, bool indexed set); event IntegrationAdded(address indexed integration, bool indexed set); - event Approval(address indexed owmer, address indexed spender, uint256 value); + event Approval( + address indexed owmer, + address indexed spender, + uint256 value + ); event Point(bytes32 indexed param, address value); event SeriesMatured(uint256 chiAtMaturity); - event Redeemed(address indexed from, address indexed to, uint256 amount, uint256 redeemed); + event Redeemed( + address indexed from, + address indexed to, + uint256 amount, + uint256 redeemed + ); } abstract contract AssetAddedState is ZeroState { @@ -98,17 +118,20 @@ abstract contract CauldronPouredState is VaultBuiltState { super.setUp(); (address owner, , bytes6 ilkId) = cauldron.vaults(vaultId); deal(cauldron.assets(ilkId), owner, INK); - IERC20(cauldron.assets(ilkId)).approve(address(ladle.joins(ilkId)), INK); - ladle.pour(vaultId,msg.sender,(INK).i128(),0); + IERC20(cauldron.assets(ilkId)).approve( + address(ladle.joins(ilkId)), + INK + ); + ladle.pour(vaultId, msg.sender, (INK).i128(), 0); } } - abstract contract BorrowedState is CauldronPouredState { +abstract contract BorrowedState is CauldronPouredState { function setUp() public virtual override { super.setUp(); ladle.pour(vaultId, address(this), 0, (ART).i128()); } - } +} abstract contract WithTokensAndIntegrationState is CompleteSetup { function setUp() public virtual override { @@ -121,14 +144,14 @@ abstract contract WithTokensAndIntegrationState is CompleteSetup { } abstract contract ETHVaultBuiltState is CompleteSetup { - function setUp() public override virtual{ + function setUp() public virtual override { super.setUp(); - (ethVaultId,) = ladle.build(baseId, wethId, 9); + (ethVaultId, ) = ladle.build(baseId, wethId, 9); } } abstract contract ETHVaultPouredState is ETHVaultBuiltState { - function setUp() public override virtual{ + function setUp() public virtual override { super.setUp(); ladle.joinEther{value: INK}(wethId); ladle.pour(ethVaultId, address(this), INK.i128(), 0); @@ -138,26 +161,24 @@ abstract contract ETHVaultPouredState is ETHVaultBuiltState { } abstract contract ETHVaultPouredAndDebtState is ETHVaultPouredState { - function setUp() public override virtual{ + function setUp() public virtual override { super.setUp(); ladle.pour(ethVaultId, address(this), 0, ART.i128()); } } -abstract contract VYTokenZeroState is ZeroState { - address public timelock; +abstract contract VYTokenZeroState is CompleteSetup { FlashBorrower public borrower; function setUp() public virtual override { super.setUp(); - timelock = address(1); vyToken.grantRole(VYToken.point.selector, address(timelock)); vyToken.grantRole(VYToken.mint.selector, address(this)); vyToken.grantRole(VYToken.deposit.selector, address(this)); vyToken.grantRole(VYToken.setFlashFeeFactor.selector, address(this)); borrower = new FlashBorrower(vyToken); - unit = uint128(10**ERC20Mock(address(vyToken)).decimals()); + unit = uint128(10 ** ERC20Mock(address(vyToken)).decimals()); deal(address(vyToken), address(this), unit); deal(address(vyToken.underlying()), address(this), unit); } @@ -170,4 +191,4 @@ abstract contract FlashLoanEnabledState is VYTokenZeroState { super.setUp(); vyToken.setFlashFeeFactor(0); } -} \ No newline at end of file +} diff --git a/src/test/variable/VRCauldron.t.sol b/src/test/variable/VRCauldron.t.sol index 23351e4c..add82ffd 100644 --- a/src/test/variable/VRCauldron.t.sol +++ b/src/test/variable/VRCauldron.t.sol @@ -12,32 +12,32 @@ using CauldronMath for uint128; contract AssetAndBaseAdditionTests is ZeroState { function testZeroIdentifier() public { - console.log('cannot add asset with zero identifier'); + console.log("cannot add asset with zero identifier"); vm.expectRevert("Asset id is zero"); cauldron.addAsset(0x000000000000, address(base)); } function testAddAsset() public { - console.log('can add asset'); + console.log("can add asset"); cauldron.addAsset(usdcId, address(usdc)); assertEq(cauldron.assets(usdcId), address(usdc)); } function testBaseAdditionFail() public { - console.log('cannot add base without asset being added first'); + console.log("cannot add base without asset being added first"); vm.expectRevert("Base not found"); cauldron.addBase(otherIlkId); } function testBaseAdditionFail2() public { - console.log('cannot add base without rate oracle being set'); + console.log("cannot add base without rate oracle being set"); cauldron.addAsset(usdcId, address(usdc)); vm.expectRevert("Rate oracle not found"); cauldron.addBase(usdcId); } function testBaseAddition() public { - console.log('can add base'); + console.log("can add base"); cauldron.addAsset(usdcId, address(usdc)); cauldron.setRateOracle(usdcId, IOracle(address(chiRateOracle))); cauldron.addBase(usdcId); @@ -47,7 +47,7 @@ contract AssetAndBaseAdditionTests is ZeroState { contract AssetAndIlkAddedTests is AssetAddedState { function testSameIdentifier() public { - console.log('cannot add asset with same identifier'); + console.log("cannot add asset with same identifier"); vm.expectRevert("Id already used"); cauldron.addAsset(usdcId, address(usdc)); } @@ -113,7 +113,6 @@ contract IlkAddition is IlkAddedState { } contract OracleAddition is ZeroState { - function testNotAllowedToAddRateOracleForUnknownBase() public { console.log("cannot add rate oracle for unknown base"); vm.expectRevert("Base not found"); @@ -200,11 +199,7 @@ contract CauldronTestOnBuiltVault is VaultBuiltState { function testPour() public { console.log("can pour into a vault"); - cauldron.pour( - vaultId, - INK.i128(), - ART.i128() - ); + cauldron.pour(vaultId, INK.i128(), ART.i128()); (uint128 art, uint128 ink) = cauldron.balances(vaultId); assertEq(ink, uint128(INK)); @@ -235,15 +230,9 @@ contract CauldronTestOnBuiltVault is VaultBuiltState { function testCannotTweakVaultWithDebt() public { console.log("cannot tweak vault with debt"); - cauldron.pour( - vaultId, - INK.i128(), - ART.i128() - ); + cauldron.pour(vaultId, INK.i128(), ART.i128()); // Adding new base and ilks to it - chiRateOracle.setSource(daiId, RATE, WAD, WAD * 2); - chiRateOracle.setSource(daiId, CHI, WAD, WAD * 2); makeBase(daiId, address(dai), daiJoin, address(chiRateOracle), 12); cauldron.setSpotOracle(daiId, usdcId, spotOracle, 1000000); cauldron.setSpotOracle(daiId, wethId, spotOracle, 1000000); @@ -281,7 +270,9 @@ contract CauldronStirTests is CauldronPouredState { } function testUndercollateralizedAtDestination() public { - console.log("cannot stir into vault with undercollateralized destination"); + console.log( + "cannot stir into vault with undercollateralized destination" + ); cauldron.pour(vaultId, 0, ART.i128()); cauldron.build(address(this), otherVaultId, baseId, daiId); vm.expectRevert("Undercollateralized at destination"); @@ -344,15 +335,16 @@ contract CauldronSlurpTests is BorrowedState { contract UtilityFunctionTests is BorrowedState { function testDebtFromBase() public { console.log("can get debt from base"); - uint128 art = cauldron.debtFromBase(baseId, INK.u128()); + uint128 art = cauldron.debtFromBase(baseId, INK.u128()); assertEq(art, ART.u128() * 1e5); } function testDebtToBase() public { console.log("can get debt to base"); - uint128 base = cauldron.debtToBase(baseId, ART.u128()); + uint128 base = cauldron.debtToBase(baseId, ART.u128()); assertEq(base, 1e18); } + function testLevel() public { console.log("can get level"); int256 level = cauldron.level(vaultId); @@ -363,85 +355,103 @@ contract UtilityFunctionTests is BorrowedState { contract FuzzTestsOnCauldronPouredState is CauldronPouredState { function testFuzz_Pouring(int128 amount) public { int256 startLevel = cauldron.level(vaultId); - vm.assume(amount>1 ); + vm.assume(amount > 1); (address owner, , bytes6 ilkId) = cauldron.vaults(vaultId); deal(cauldron.assets(ilkId), owner, uint(int(amount))); - IERC20(cauldron.assets(ilkId)).approve(address(ladle.joins(ilkId)), uint(int(amount))); - ladle.pour(vaultId,msg.sender,amount,0); + IERC20(cauldron.assets(ilkId)).approve( + address(ladle.joins(ilkId)), + uint(int(amount)) + ); + ladle.pour(vaultId, msg.sender, amount, 0); assertGt(cauldron.level(vaultId), 1); } - function testFuzz_LevelGoesDownAsArtGoesUp(int128 art) public { + function testFuzz_levelGoesDownAsArtGoesUp(int128 art) public { // Level goes down as art goes up (uint128 dust, ) = giveMeDustAndLine(vaultId); - - vm.assume(art > 0); // Since we want to borrow + (, bytes6 baseId, bytes6 ilkId) = cauldron.vaults(vaultId); + vm.assume(art > 0); // Since we want to borrow vm.assume(getAbove(INK.i128(), art, vaultId)); // Check if not undercollateralized vm.assume(art.u128() >= dust); // Check if min debt is achieved + vm.assume(art.u256() <= ladle.joins(baseId).storedBalance()); // Check if enough balance in join int256 startLevel = cauldron.level(vaultId); - ladle.pour(vaultId,msg.sender, 0, art); - - assertGt(startLevel,cauldron.level(vaultId)); + ladle.pour(vaultId, msg.sender, 0, art); + + assertGt(startLevel, cauldron.level(vaultId)); } } contract FuzzLevelTestsOnBorrowedState is BorrowedState { function testFuzz_levelGoesUpAsArtComesDown(int128 art) public { - vm.assume(art < 0);// Since we are paying back + vm.assume(art < 0); // Since we are paying back // Level goes up as art comes down - (uint128 currentArt,) = cauldron.balances(vaultId); - vm.assume(currentArt.i128() + art >= 0);// Prevent paying back more than borrowed + (uint128 currentArt, ) = cauldron.balances(vaultId); + vm.assume(currentArt.i128() + art >= 0); // Prevent paying back more than borrowed int256 startLevel = cauldron.level(vaultId); (, bytes6 baseId, ) = cauldron.vaults(vaultId); - IERC20(cauldron.assets(baseId)).approve(address(ladle.joins(baseId)), uint(int(art))); - ladle.pour(vaultId,msg.sender, 0, art); - - assertLt(startLevel,cauldron.level(vaultId)); + IERC20(cauldron.assets(baseId)).approve( + address(ladle.joins(baseId)), + uint(int(art)) + ); + ladle.pour(vaultId, msg.sender, 0, art); + + assertLt(startLevel, cauldron.level(vaultId)); } function testFuzz_levelGoesUpAsInkGoesUp(int128 ink) public { // Level goes up as ink goes up - vm.assume(ink > 0);// Since we want to add collateral + vm.assume(ink > 0); // Since we want to add collateral int256 startLevel = cauldron.level(vaultId); - (address owner, ,bytes6 ilkId ) = cauldron.vaults(vaultId); + (address owner, , bytes6 ilkId) = cauldron.vaults(vaultId); deal(cauldron.assets(ilkId), owner, uint(int(ink))); - IERC20(cauldron.assets(ilkId)).approve(address(ladle.joins(ilkId)), uint(int(ink))); - ladle.pour(vaultId,msg.sender, ink, 0); - - assertLt(startLevel,cauldron.level(vaultId)); + IERC20(cauldron.assets(ilkId)).approve( + address(ladle.joins(ilkId)), + uint(int(ink)) + ); + ladle.pour(vaultId, msg.sender, ink, 0); + + assertLt(startLevel, cauldron.level(vaultId)); } function testFuzz_levelGoesDownAsInkGoesDown(int128 ink) public { // Level goes down as ink goes down - vm.assume(ink < 0);// Since we want to remove collateral + vm.assume(ink < 0); // Since we want to remove collateral (uint128 currentArt, uint128 currentInk) = cauldron.balances(vaultId); - vm.assume(currentInk.i128() + ink >= 0);// Prevent removing more than collateral - vm.assume(getAbove(currentInk.add(ink).i128(), currentArt.i128(), vaultId)); + vm.assume(currentInk.i128() + ink >= 0); // Prevent removing more than collateral + vm.assume( + getAbove(currentInk.add(ink).i128(), currentArt.i128(), vaultId) + ); int256 startLevel = cauldron.level(vaultId); - ladle.pour(vaultId,msg.sender, ink, 0); - - assertGt(startLevel,cauldron.level(vaultId)); + ladle.pour(vaultId, msg.sender, ink, 0); + + assertGt(startLevel, cauldron.level(vaultId)); } function testFuzz_levelGoesDownAsRatioGoesUp(uint32 ratio) public { // Level goes down as ratio goes up (, bytes6 baseId, bytes6 ilkId) = cauldron.vaults(vaultId); - (IOracle oracle, uint32 currentRatio) = cauldron.spotOracles(baseId, ilkId); + (IOracle oracle, uint32 currentRatio) = cauldron.spotOracles( + baseId, + ilkId + ); vm.assume(ratio > currentRatio); int256 startLevel = cauldron.level(vaultId); cauldron.setSpotOracle(baseId, ilkId, oracle, ratio); - assertGt(startLevel,cauldron.level(vaultId)); + assertGt(startLevel, cauldron.level(vaultId)); } function testFuzz_levelGoesUpAsRatioGoesDown(uint32 ratio) public { // Level goes up as ratio goes down (, bytes6 baseId, bytes6 ilkId) = cauldron.vaults(vaultId); - (IOracle oracle, uint32 currentRatio) = cauldron.spotOracles(baseId, ilkId); + (IOracle oracle, uint32 currentRatio) = cauldron.spotOracles( + baseId, + ilkId + ); vm.assume(ratio < currentRatio); int256 startLevel = cauldron.level(vaultId); cauldron.setSpotOracle(baseId, ilkId, oracle, ratio); @@ -450,27 +460,27 @@ contract FuzzLevelTestsOnBorrowedState is BorrowedState { function testFuzz_levelGoesDownAsPriceGoesUp(int256 price) public { vm.assume(price > 0); - (, bytes6 baseId, ) = cauldron.vaults(vaultId); - (, int256 currentPrice, , ,) = usdcAggregator.latestRoundData(); - - // Level goes down as price goes up - vm.assume(price > currentPrice); + (, bytes6 baseId, bytes6 ilkId) = cauldron.vaults(vaultId); + (, int256 currentPrice, , , ) = ethAggregator.latestRoundData(); + + // Level goes down as price goes up, we are setting the price of eth down to get base price up + vm.assume(price < currentPrice); int256 startLevel = cauldron.level(vaultId); - usdcAggregator.set(uint256(price)); - assertGt(startLevel,cauldron.level(vaultId)); + ethAggregator.set(uint256(price)); + assertGt(startLevel, cauldron.level(vaultId)); } - function testFuzz_levelGoesupAsPriceGoesDown(int256 price) public { + function testFuzz_levelGoesUpAsPriceGoesDown(int256 price) public { // Level goes up as price goes down vm.assume(price > 0); (, bytes6 baseId, ) = cauldron.vaults(vaultId); - (, int256 currentPrice, , ,) = usdcAggregator.latestRoundData(); - - vm.assume(price < currentPrice); + (, int256 currentPrice, , , ) = ethAggregator.latestRoundData(); + + vm.assume(price > currentPrice); + vm.assume(price < 1e40);// To prevent Chainlink Multioracle overflow error over large values + int256 startLevel = cauldron.level(vaultId); - usdcAggregator.set(uint256(price)); - console.logInt(startLevel); - console.logInt(cauldron.level(vaultId)); - assertLt(startLevel,cauldron.level(vaultId)); + ethAggregator.set(uint256(price)); + assertLt(startLevel, cauldron.level(vaultId)); } -} \ No newline at end of file +} diff --git a/src/test/variable/VRLadle.t.sol b/src/test/variable/VRLadle.t.sol index ee2fa27c..23fba06f 100644 --- a/src/test/variable/VRLadle.t.sol +++ b/src/test/variable/VRLadle.t.sol @@ -9,7 +9,7 @@ using Cast for int128; contract VRLadleAdminTests is ZeroState { // @notice Test ability to set borrowing fee function testSetBorrowingFee() public { - console.log('admin can set borrowing fee'); + console.log("admin can set borrowing fee"); ladle.setFee(1000); assertEq(ladle.borrowingFee(), 1000); } @@ -18,14 +18,14 @@ contract VRLadleAdminTests is ZeroState { contract VRLadleJoinAdminTests is ZeroState { // @notice Test not able to add join before adding ilk function testNoAddJoinWithoutIlk() public { - console.log('cannot add join without asset being added first'); + console.log("cannot add join without asset being added first"); vm.expectRevert("Asset not found"); ladle.addJoin(usdcId, IJoin(address(usdcJoin))); } // @notice Test not able to add join with a mismatched ilk function testAddJoinMismatch() public { - console.log('cannot add join with mismatched asset'); + console.log("cannot add join with mismatched asset"); cauldron.addAsset(usdcId, address(usdc)); vm.expectRevert("Mismatched asset and join"); ladle.addJoin(usdcId, IJoin(address(daiJoin))); @@ -33,7 +33,7 @@ contract VRLadleJoinAdminTests is ZeroState { // @notice Test ability to add join function testAddJoin() public { - console.log('can add join for an asset which is present'); + console.log("can add join for an asset which is present"); cauldron.addAsset(usdcId, address(usdc)); ladle.addJoin(usdcId, IJoin(address(usdcJoin))); assertEq(address(ladle.joins(usdcId)), address(usdcJoin)); @@ -41,7 +41,7 @@ contract VRLadleJoinAdminTests is ZeroState { // @notice Test the same join for a second ilk of the same asset function testAddJoinSameAsset() public { - console.log('can add the same join for different asset'); + console.log("can add the same join for different asset"); cauldron.addAsset(usdcId, address(usdc)); ladle.addJoin(usdcId, IJoin(address(usdcJoin))); cauldron.addAsset(otherIlkId, address(usdc)); @@ -53,74 +53,79 @@ contract VRLadleJoinAdminTests is ZeroState { contract VaultTests is VaultBuiltState { function testBuildVault() public { - console.log('can build a vault'); + console.log("can build a vault"); (bytes12 vaultId_, ) = ladle.build(baseId, usdcId, 123); - (address owner, bytes6 baseId_, bytes6 ilkId_) = cauldron.vaults(vaultId_); + (address owner, bytes6 baseId_, bytes6 ilkId_) = cauldron.vaults( + vaultId_ + ); assertEq(baseId_, baseId); assertEq(ilkId_, usdcId); assertEq(owner, address(this)); } function testZeroIlkId() public { - console.log('cannot build a vault with zero ilk id'); + console.log("cannot build a vault with zero ilk id"); vm.expectRevert("Ilk id is zero"); ladle.build(baseId, bytes6(0), 123); } function testTweakOnlyOwner() public { - console.log('cannot tweak a vault with a different owner'); + console.log("cannot tweak a vault with a different owner"); vm.expectRevert("Only vault owner"); vm.prank(admin); ladle.tweak(vaultId, baseId, usdcId); } function testDestroyVault() public { - console.log('can destroy a vault'); + console.log("can destroy a vault"); vm.expectEmit(true, false, false, false); emit VaultDestroyed(vaultId); ladle.destroy(vaultId); } function testChangeVault() public { - console.log('can change a vault'); + console.log("can change a vault"); vm.expectEmit(true, true, true, false); emit VaultTweaked(vaultId, baseId, daiId); ladle.tweak(vaultId, baseId, daiId); - (address owner, bytes6 baseId_, bytes6 ilkId_) = cauldron.vaults(vaultId); + (address owner, bytes6 baseId_, bytes6 ilkId_) = cauldron.vaults( + vaultId + ); assertEq(baseId_, baseId); assertEq(ilkId_, daiId); assertEq(owner, address(this)); } function testGiveVault() public { - console.log('can give a vault'); + console.log("can give a vault"); vm.expectEmit(true, true, false, false); emit VaultGiven(vaultId, admin); ladle.give(vaultId, admin); - (address owner, bytes6 baseId_, bytes6 ilkId_) = cauldron.vaults(vaultId); + (address owner, bytes6 baseId_, bytes6 ilkId_) = cauldron.vaults( + vaultId + ); assertEq(baseId_, baseId); assertEq(ilkId_, usdcId); assertEq(owner, admin); } function testOtherCantChangeOwnerOfVault() public { - console.log('cannot change owner of a vault with a different owner'); + console.log("cannot change owner of a vault with a different owner"); vm.expectRevert("Only vault owner"); vm.prank(admin); ladle.give(vaultId, admin); } function testOnlyOwnerCouldMove() public { - console.log('cannot move a vault with a different owner'); + console.log("cannot move a vault with a different owner"); vm.prank(admin); vm.expectRevert("Only origin vault owner"); ladle.stir(vaultId, otherVaultId, 1, 1); } function testOnlyDestinationVaultOwner() public { - vm.prank(admin); vm.expectRevert("Only destination vault owner"); ladle.stir(vaultId, otherVaultId, 0, 1); @@ -128,14 +133,14 @@ contract VaultTests is VaultBuiltState { } contract PourTests is VaultBuiltState { - - function setUp() public override{ + function setUp() public override { super.setUp(); (, bytes6 baseId, bytes6 ilkId) = cauldron.vaults(vaultId); IERC20 token = IERC20(cauldron.assets(ilkId)); deal(address(token), address(this), INK); - token.approve(address(ladle.joins(ilkId)),INK); + token.approve(address(ladle.joins(ilkId)), INK); } + function testOnlyOwnerCanPour() public { console.log("other users can't pour into a vault"); vm.expectRevert("Only vault owner"); @@ -144,15 +149,15 @@ contract PourTests is VaultBuiltState { } function testPourToPostCollateral() public { - console.log('can pour collateral into a vault'); + console.log("can pour collateral into a vault"); ladle.pour(vaultId, address(this), INK.i128(), 0); - (uint128 art, uint128 ink) = cauldron.balances(vaultId); + (uint128 art, uint128 ink) = cauldron.balances(vaultId); assertEq(ink, INK); assertEq(art, 0); } function testPourToPostAndBorrow() public { - console.log('can pour collateral into a vault and borrow'); + console.log("can pour collateral into a vault and borrow"); (, bytes6 baseId, bytes6 ilkId) = cauldron.vaults(vaultId); ladle.pour(vaultId, address(this), INK.i128(), ART.i128()); @@ -164,7 +169,9 @@ contract PourTests is VaultBuiltState { } function testPourToPostAndBorrowToOther() public { - console.log('can pour collateral into a vault and send the borrowed amount to other address'); + console.log( + "can pour collateral into a vault and send the borrowed amount to other address" + ); (, bytes6 baseId, bytes6 ilkId) = cauldron.vaults(vaultId); ladle.pour(vaultId, admin, INK.i128(), ART.i128()); @@ -177,45 +184,44 @@ contract PourTests is VaultBuiltState { } contract PouredStateTests is CauldronPouredState { - function testPourToWithdraw() public { - console.log('can pour to withdraw'); + console.log("can pour to withdraw"); (, , bytes6 ilkId) = cauldron.vaults(vaultId); - + assertEq(IERC20(cauldron.assets(ilkId)).balanceOf(address(this)), 0); vm.expectEmit(true, true, true, true); emit VaultPoured(vaultId, baseId, ilkId, -(INK).i128(), 0); ladle.pour(vaultId, address(this), -(INK).i128(), 0); assertEq(IERC20(cauldron.assets(ilkId)).balanceOf(address(this)), INK); - + (uint128 art, uint128 ink) = cauldron.balances(vaultId); assertEq(ink, 0); assertEq(art, 0); } function testPourToWithdrawToOther() public { - console.log('can pour to withdraw to other address'); + console.log("can pour to withdraw to other address"); (, , bytes6 ilkId) = cauldron.vaults(vaultId); - + assertEq(IERC20(cauldron.assets(ilkId)).balanceOf(address(this)), 0); vm.expectEmit(true, true, true, true); emit VaultPoured(vaultId, baseId, ilkId, -(INK).i128(), 0); ladle.pour(vaultId, admin, -(INK).i128(), 0); assertEq(IERC20(cauldron.assets(ilkId)).balanceOf(admin), INK); - + (uint128 art, uint128 ink) = cauldron.balances(vaultId); assertEq(ink, 0); assertEq(art, 0); } function testCannotBorrowUnderLimit() public { - console.log('cannot borrow under the min debt'); + console.log("cannot borrow under the min debt"); vm.expectRevert("Min debt not reached"); ladle.pour(vaultId, address(this), 0, 1); } function testPourToBorrowBase() public { - console.log('can pour to borrow base'); + console.log("can pour to borrow base"); ladle.pour(vaultId, address(this), 0, (ART).i128()); (uint128 art, uint128 ink) = cauldron.balances(vaultId); @@ -224,7 +230,7 @@ contract PouredStateTests is CauldronPouredState { } function testFeeChargeOnBorrow() public { - console.log('fee can be charged on borrow'); + console.log("fee can be charged on borrow"); ladle.setFee(FEE); ladle.pour(vaultId, address(this), 0, (ART).i128()); @@ -233,15 +239,18 @@ contract PouredStateTests is CauldronPouredState { assertEq(art, ART + FEE); } - function testMoveDebt() public{ - console.log('can move debt from one vault to another'); + function testMoveDebt() public { + console.log("can move debt from one vault to another"); (bytes12 otherVaultId, ) = ladle.build(baseId, usdcId, 123); (address owner, , bytes6 ilkId) = cauldron.vaults(vaultId); deal(cauldron.assets(ilkId), owner, INK); - IERC20(cauldron.assets(ilkId)).approve(address(ladle.joins(ilkId)), INK); + IERC20(cauldron.assets(ilkId)).approve( + address(ladle.joins(ilkId)), + INK + ); ladle.pour(otherVaultId, msg.sender, (INK).i128(), 0); ladle.pour(vaultId, address(this), 0, (ART).i128()); - + (uint128 art, uint128 ink) = cauldron.balances(vaultId); vm.expectEmit(true, true, true, true); emit VaultStirred(vaultId, otherVaultId, 0, art); @@ -257,10 +266,9 @@ contract PouredStateTests is CauldronPouredState { } function testMoveCollateral() public { - console.log('can move collateral from one vault to another'); + console.log("can move collateral from one vault to another"); (bytes12 otherVaultId, ) = ladle.build(baseId, usdcId, 123); (uint128 art, uint128 ink) = cauldron.balances(vaultId); - vm.expectEmit(true, true, true, true); emit VaultStirred(vaultId, otherVaultId, ink, 0); ladle.stir(vaultId, otherVaultId, ink, 0); @@ -275,11 +283,11 @@ contract PouredStateTests is CauldronPouredState { } function testMoveDebtAndCollateral() public { - console.log('can move debt and collateral from one vault to another'); + console.log("can move debt and collateral from one vault to another"); (bytes12 otherVaultId, ) = ladle.build(baseId, usdcId, 123); ladle.pour(vaultId, address(this), 0, (ART).i128()); (uint128 art, uint128 ink) = cauldron.balances(vaultId); - + vm.expectEmit(true, true, true, true); emit VaultStirred(vaultId, otherVaultId, ink, art); ladle.stir(vaultId, otherVaultId, ink, art); @@ -294,12 +302,18 @@ contract PouredStateTests is CauldronPouredState { } function testMoveCollateralInABatch() public { - console.log('can move collateral from one vault to another in a batch'); + console.log("can move collateral from one vault to another in a batch"); (bytes12 otherVaultId, ) = ladle.build(baseId, usdcId, 123); (uint128 art, uint128 ink) = cauldron.balances(vaultId); bytes[] memory calls = new bytes[](1); - calls[0] = abi.encodeWithSelector(VRLadle.stir.selector, vaultId, otherVaultId, ink, 0); + calls[0] = abi.encodeWithSelector( + VRLadle.stir.selector, + vaultId, + otherVaultId, + ink, + 0 + ); vm.expectEmit(true, true, true, true); emit VaultStirred(vaultId, otherVaultId, ink, 0); @@ -315,16 +329,25 @@ contract PouredStateTests is CauldronPouredState { } function testMoveDebtInABatch() public { - console.log('can move debt from one vault to another in a batch'); + console.log("can move debt from one vault to another in a batch"); (bytes12 otherVaultId, ) = ladle.build(baseId, usdcId, 123); (address owner, , bytes6 ilkId) = cauldron.vaults(vaultId); deal(cauldron.assets(ilkId), owner, INK); - IERC20(cauldron.assets(ilkId)).approve(address(ladle.joins(ilkId)), INK); + IERC20(cauldron.assets(ilkId)).approve( + address(ladle.joins(ilkId)), + INK + ); ladle.pour(otherVaultId, msg.sender, (INK).i128(), 0); ladle.pour(vaultId, address(this), 0, (ART).i128()); bytes[] memory calls = new bytes[](1); - calls[0] = abi.encodeWithSelector(VRLadle.stir.selector, vaultId, otherVaultId, 0, ART); + calls[0] = abi.encodeWithSelector( + VRLadle.stir.selector, + vaultId, + otherVaultId, + 0, + ART + ); vm.expectEmit(true, true, true, true); emit VaultStirred(vaultId, otherVaultId, 0, uint128(ART)); @@ -348,8 +371,9 @@ contract BorrowedStateTests is BorrowedState { (, bytes6 baseId, ) = cauldron.vaults(vaultId); token = IERC20(cauldron.assets(baseId)); } + function testRepayDebt() public { - console.log('can repay debt by pouring'); + console.log("can repay debt by pouring"); token.approve(address(ladle.joins(baseId)), ART); ladle.pour(vaultId, address(this), 0, -(ART.i128())); @@ -360,7 +384,7 @@ contract BorrowedStateTests is BorrowedState { } function testRepayDebtWithTransfer() public { - console.log('can repay debt by transferring before pouring'); + console.log("can repay debt by transferring before pouring"); token.transfer(address(ladle.joins(baseId)), ART); ladle.pour(vaultId, admin, 0, -(ART).i128()); @@ -371,14 +395,14 @@ contract BorrowedStateTests is BorrowedState { } function testCantRepayMoreThanDebt() public { - console.log('cannot repay more than debt'); + console.log("cannot repay more than debt"); token.approve(address(ladle.joins(baseId)), ART + 10); vm.expectRevert("Result below zero"); ladle.pour(vaultId, admin, 0, -(ART + 10).i128()); } function testBorrowWhileUnderGlobalDebtLimit() public { - console.log('can borrow while under global debt limit'); + console.log("can borrow while under global debt limit"); ladle.pour(vaultId, address(this), 0, (ART).i128()); (uint128 art, uint128 ink) = cauldron.balances(vaultId); assertEq(ink, INK); @@ -386,7 +410,7 @@ contract BorrowedStateTests is BorrowedState { } function testCantBorrowOverGlobalDebtLimit() public { - console.log('cannot borrow over global debt limit'); + console.log("cannot borrow over global debt limit"); vm.expectRevert("Max debt exceeded"); ladle.pour(vaultId, address(this), 0, (ART * 20 * 1e6).i128()); } @@ -399,64 +423,100 @@ contract PermitTests is CompleteSetup { uint256 value; } - function getDaiPermitDigest(bytes memory name, address contractAddress, uint256 chainId, Permit memory permit, uint nonce, uint deadline, bool allowed) internal view returns (bytes32) { - bytes32 DOMAIN_SEPARATOR = getDomainSeparator(name, contractAddress, chainId); - return keccak256( - abi.encodePacked( - "\x19\x01", - DOMAIN_SEPARATOR, - keccak256( - abi.encode( - keccak256("Permit(address holder,address spender,uint256 nonce,uint256 expiry,bool allowed)"), - permit.owner, - permit.spender, - nonce, - deadline, - allowed + function getDaiPermitDigest( + bytes memory name, + address contractAddress, + uint256 chainId, + Permit memory permit, + uint nonce, + uint deadline, + bool allowed + ) internal view returns (bytes32) { + bytes32 DOMAIN_SEPARATOR = getDomainSeparator( + name, + contractAddress, + chainId + ); + return + keccak256( + abi.encodePacked( + "\x19\x01", + DOMAIN_SEPARATOR, + keccak256( + abi.encode( + keccak256( + "Permit(address holder,address spender,uint256 nonce,uint256 expiry,bool allowed)" + ), + permit.owner, + permit.spender, + nonce, + deadline, + allowed + ) ) ) - ) - ); + ); } - function getPermitDigest(bytes memory name, address contractAddress, uint256 chainId, Permit memory permit, uint nonce, uint deadline) internal view returns (bytes32) { + function getPermitDigest( + bytes memory name, + address contractAddress, + uint256 chainId, + Permit memory permit, + uint nonce, + uint deadline + ) internal view returns (bytes32) { bytes32 DOMAIN_SEPARATOR = keccak256( abi.encode( - keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"), + keccak256( + "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)" + ), keccak256(bytes(name)), keccak256(bytes(ERC20Permit(contractAddress).version())), chainId, contractAddress ) ); - return keccak256( - abi.encodePacked( - "\x19\x01", - DOMAIN_SEPARATOR, - keccak256( - abi.encode( - keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"), - permit.owner, - permit.spender, - permit.value, - nonce, - deadline + return + keccak256( + abi.encodePacked( + "\x19\x01", + DOMAIN_SEPARATOR, + keccak256( + abi.encode( + keccak256( + "Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)" + ), + permit.owner, + permit.spender, + permit.value, + nonce, + deadline + ) ) ) - ) - ); - } - - function getDomainSeparator(bytes memory name, address contractAddress, uint256 chainId) internal view returns (bytes32) { - return keccak256( - abi.encode( - keccak256(('EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)')), - keccak256(bytes(IERC20Metadata(contractAddress).name())), - keccak256(('1')), - chainId, - contractAddress - ) - ); + ); + } + + function getDomainSeparator( + bytes memory name, + address contractAddress, + uint256 chainId + ) internal view returns (bytes32) { + return + keccak256( + abi.encode( + keccak256( + ( + "EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)" + ) + ), + keccak256(bytes(IERC20Metadata(contractAddress).name())), + keccak256(("1")), + chainId, + contractAddress + ) + ); } function testCanUseLadleToExecutePermit() public { @@ -464,22 +524,37 @@ contract PermitTests is CompleteSetup { assembly { chainId := chainid() } + bytes32 permitDigest = getDaiPermitDigest( - abi.encode(keccak256(bytes(IERC20Metadata(address(dai)).name()))),//name - address(dai),//contractAddress - chainId,//chainId + abi.encode(keccak256(bytes(IERC20Metadata(address(dai)).name()))), //name + address(dai), //contractAddress + chainId, //chainId Permit( - user,//owner - address(ladle.joins(daiId)),//spender - 100),//value - 0,//nonce - block.timestamp,//deadline - true); - (uint8 v, bytes32 r, bytes32 s) = vm.sign(uint256(keccak256(abi.encodePacked("user"))), permitDigest); + user, //owner + address(ladle.joins(daiId)), //spender + 100 + ), //value + 0, //nonce + block.timestamp, //deadline + true + ); + (uint8 v, bytes32 r, bytes32 s) = vm.sign( + uint256(keccak256(abi.encodePacked("user"))), + permitDigest + ); vm.startPrank(user); vm.expectEmit(true, true, true, true); emit Approval(user, address(ladle.joins(daiId)), type(uint256).max); - ladle.forwardDaiPermit(DaiAbstract(address(dai)), address(ladle.joins(daiId)), 0, block.timestamp, true, v,r,s); + ladle.forwardDaiPermit( + DaiAbstract(address(dai)), + address(ladle.joins(daiId)), + 0, + block.timestamp, + true, + v, + r, + s + ); } function testCantUseLadleToExecutePermitOnUnknownToken() public { @@ -488,26 +563,40 @@ contract PermitTests is CompleteSetup { chainId := chainid() } bytes32 permitDigest = getPermitDigest( - abi.encode(keccak256(bytes(IERC20Metadata(address(otherERC20)).name()))),//name - address(otherERC20),//contractAddress - chainId,//chainId + abi.encode( + keccak256(bytes(IERC20Metadata(address(otherERC20)).name())) + ), //name + address(otherERC20), //contractAddress + chainId, //chainId Permit( - user,//owner - address(ladle.joins(daiId)),//spender - 100),//value - 0,//nonce - block.timestamp//deadline + user, //owner + address(ladle.joins(daiId)), //spender + 100 + ), //value + 0, //nonce + block.timestamp //deadline + ); + (uint8 v, bytes32 r, bytes32 s) = vm.sign( + uint256(keccak256(abi.encodePacked("user"))), + permitDigest ); - (uint8 v, bytes32 r, bytes32 s) = vm.sign(uint256(keccak256(abi.encodePacked("user"))), permitDigest); vm.startPrank(user); vm.expectRevert("Unknown token"); - ladle.forwardPermit(otherERC20, address(0), 0, block.timestamp, v, r, s); + ladle.forwardPermit( + otherERC20, + address(0), + 0, + block.timestamp, + v, + r, + s + ); } } contract RouteAndIntegrationTests is CompleteSetup { function testTokenAdditionAndRemoval() public { - console.log('can add and remove tokens'); + console.log("can add and remove tokens"); vm.expectEmit(true, true, true, true); emit TokenAdded(address(usdc), true); ladle.addToken(address(usdc), true); @@ -520,7 +609,7 @@ contract RouteAndIntegrationTests is CompleteSetup { } function testIntegrationAdditionAndRemoval() public { - console.log('can add and remove integrations'); + console.log("can add and remove integrations"); vm.expectEmit(true, true, true, true); emit IntegrationAdded(address(usdc), true); ladle.addIntegration(address(usdc), true); @@ -533,10 +622,10 @@ contract RouteAndIntegrationTests is CompleteSetup { } function testOnlyCauldronCanUseRouter() public { - console.log('router can be called only by cauldron'); + console.log("router can be called only by cauldron"); Router router = ladle.router(); vm.expectRevert("Only owner"); - router.route(address(cauldron),'0x00000000'); + router.route(address(cauldron), "0x00000000"); } } @@ -544,13 +633,13 @@ contract TokensAndIntegrationTests is WithTokensAndIntegrationState { function testCantRouteToEOA() public { console.log("can't route to an EOA"); vm.expectRevert("Target is not a contract"); - ladle.route(user, '0x00000000'); + ladle.route(user, "0x00000000"); } function testUnknownToken() public { console.log("can't use transfer on a token not added to ladle"); vm.expectRevert("Unknown token"); - ladle.transfer(IERC20(makeAddr('0x12')), user, uint128(WAD)); + ladle.transfer(IERC20(makeAddr("0x12")), user, uint128(WAD)); } function testTransferTokenThroughLadle() public { @@ -564,31 +653,45 @@ contract TokensAndIntegrationTests is WithTokensAndIntegrationState { console.log("can call function on integration"); vm.expectEmit(true, true, true, true); emit Approval(address(ladle.router()), address(this), WAD); - ladle.route(address(dai), abi.encodeWithSelector(IERC20.approve.selector, address(this), WAD)); + ladle.route( + address(dai), + abi.encodeWithSelector(IERC20.approve.selector, address(this), WAD) + ); } function testUnknownIntegrationCantBeCalled() public { console.log("can't call function on unknown integration"); vm.expectRevert("Unknown integration"); - ladle.route(address(usdc), abi.encodeWithSelector(IERC20.approve.selector, address(this), WAD)); + ladle.route( + address(usdc), + abi.encodeWithSelector(IERC20.approve.selector, address(this), WAD) + ); } function testAuthorizationStripping() public { console.log("can't call function on integration without authorization"); vm.expectRevert("Access denied"); - ladle.route(address(restrictedERC20Mock), abi.encodeWithSelector(RestrictedERC20Mock.mint.selector, address(this), WAD)); + ladle.route( + address(restrictedERC20Mock), + abi.encodeWithSelector( + RestrictedERC20Mock.mint.selector, + address(this), + WAD + ) + ); } } contract ETHTests is ETHVaultBuiltState { function testCanTransferETHThenPour() public { console.log("can transfer eth and then pour"); + uint before = weth.balanceOf(address(ladle.joins(wethId))); ladle.joinEther{value: INK}(wethId); vm.expectEmit(true, true, true, true); emit VaultPoured(ethVaultId, baseId, wethId, INK.i128(), 0); ladle.pour(ethVaultId, address(this), INK.i128(), 0); - - assertEq(weth.balanceOf(address(ladle.joins(wethId))), INK); + + assertEq(weth.balanceOf(address(ladle.joins(wethId))) - before, INK); (uint128 art, uint128 ink) = cauldron.balances(ethVaultId); assertEq(ink, INK); assertEq(art, 0); @@ -596,8 +699,9 @@ contract ETHTests is ETHVaultBuiltState { function testPourWithoutSendingETHReverts() public { console.log("pour without sending eth reverts"); - weth.approve(address(wethJoin), 0 ); - vm.expectRevert("ERC20: Insufficient approval"); + weth.approve(address(wethJoin), 0); + // Since weth doesn't have a error message for insufficient allowance https://etherscan.io/address/0xc02aaa39b223fe8d0a0e5c4f27ead9083c756cc2#code#L70 + vm.expectRevert("Transaction reverted silently"); ladle.pour(ethVaultId, address(this), INK.i128(), 0); } @@ -605,13 +709,20 @@ contract ETHTests is ETHVaultBuiltState { console.log("can transfer eth and pour in batch"); bytes[] memory calls = new bytes[](2); calls[0] = abi.encodeWithSelector(VRLadle.joinEther.selector, wethId); - calls[1] = abi.encodeWithSelector(VRLadle.pour.selector, ethVaultId, address(this), INK.i128(), 0); + calls[1] = abi.encodeWithSelector( + VRLadle.pour.selector, + ethVaultId, + address(this), + INK.i128(), + 0 + ); vm.expectEmit(true, true, true, true); emit VaultPoured(ethVaultId, baseId, wethId, INK.i128(), 0); - ladle.batch{ value: INK}(calls); + uint before = weth.balanceOf(address(ladle.joins(wethId))); + ladle.batch{value: INK}(calls); - assertEq(weth.balanceOf(address(ladle.joins(wethId))), INK); + assertEq(weth.balanceOf(address(ladle.joins(wethId))) - before, INK); (uint128 art, uint128 ink) = cauldron.balances(ethVaultId); assertEq(ink, INK); assertEq(art, 0); @@ -619,7 +730,7 @@ contract ETHTests is ETHVaultBuiltState { function testReceiveETHFromOnlyWETH() public { console.log("can't receive eth from non-weth"); - (bool sent, bytes memory data) = address(ladle).call{ value: INK }(""); + (bool sent, bytes memory data) = address(ladle).call{value: INK}(""); assertTrue(!sent); } } @@ -627,11 +738,12 @@ contract ETHTests is ETHVaultBuiltState { contract ETHVaultPouredStateTest is ETHVaultPouredState { function testPourToWithdraw() public { console.log("can pour to withdraw"); - ladle.pour(ethVaultId, address(this), -INK.i128(), 0); + (uint128 art, uint128 ink) = cauldron.balances(ethVaultId); + ladle.pour(ethVaultId, address(this), -int128(ink), 0); - assertEq(weth.balanceOf(address(ladle.joins(wethId))), 0); + // assertEq(weth.balanceOf(address(ladle.joins(wethId))), 0); assertEq(weth.balanceOf(address(this)), INK); - (uint128 art, uint128 ink) = cauldron.balances(ethVaultId); + (art, ink) = cauldron.balances(ethVaultId); assertEq(ink, 0); assertEq(art, 0); } @@ -640,12 +752,24 @@ contract ETHVaultPouredStateTest is ETHVaultPouredState { console.log("can withdraw and unwrap in a batch"); uint initialBalance = address(this).balance; bytes[] memory calls = new bytes[](2); - calls[0] = abi.encodeWithSelector(VRLadle.pour.selector, ethVaultId, address(ladle), -INK.i128(), 0); - calls[1] = abi.encodeWithSelector(VRLadle.exitEther.selector, address(this)); - + calls[0] = abi.encodeWithSelector( + VRLadle.pour.selector, + ethVaultId, + address(ladle), + -INK.i128(), + 0 + ); + calls[1] = abi.encodeWithSelector( + VRLadle.exitEther.selector, + address(this) + ); + uint before = weth.balanceOf(address(ladle.joins(wethId))); ladle.batch(calls); - assertEq(weth.balanceOf(address(ladle.joins(wethId))), 0); + assertEq( + before - INK - weth.balanceOf(address(ladle.joins(wethId))), + 0 + ); assertEq(weth.balanceOf(address(this)), 0); (uint128 art, uint128 ink) = cauldron.balances(ethVaultId); assertEq(ink, 0); @@ -655,9 +779,9 @@ contract ETHVaultPouredStateTest is ETHVaultPouredState { function testRepayETH() public { console.log("can repay eth"); - ladle.pour(ethVaultId, address(this), 0, (ART*1000).i128()); + ladle.pour(ethVaultId, address(this), 0, (ART * 1000).i128()); uint128 debtToBase = cauldron.debtToBase(baseId, uint128(ART * 1000)); - deal(address(base), address(this), debtToBase ); + deal(address(base), address(this), debtToBase); IERC20(address(base)).approve(address(ladle.joins(baseId)), debtToBase); ladle.repay(ethVaultId, address(this), address(this), 0); (uint128 art, uint128 ink) = cauldron.balances(ethVaultId); @@ -670,13 +794,33 @@ contract BatchTests is CompleteSetup { function testBuildTweakGive() public { console.log("can build tweak and give in a batch"); bytes[] memory calls = new bytes[](3); - calls[0] = abi.encodeWithSelector(VRLadle.build.selector, baseId, usdcId, 9); - calls[1] = abi.encodeWithSelector(VRLadle.tweak.selector, bytes12(0), baseId, daiId); - calls[2] = abi.encodeWithSelector(VRLadle.give.selector, bytes12(0), admin); - + calls[0] = abi.encodeWithSelector( + VRLadle.build.selector, + baseId, + usdcId, + 9 + ); + calls[1] = abi.encodeWithSelector( + VRLadle.tweak.selector, + bytes12(0), + baseId, + daiId + ); + calls[2] = abi.encodeWithSelector( + VRLadle.give.selector, + bytes12(0), + admin + ); + ladle.batch(calls); - - (address owner, bytes6 baseId_, bytes6 ilkId_) = cauldron.vaults(bytes12(keccak256(abi.encodePacked(address(this), block.timestamp, uint8(10))))); + + (address owner, bytes6 baseId_, bytes6 ilkId_) = cauldron.vaults( + bytes12( + keccak256( + abi.encodePacked(address(this), block.timestamp, uint8(10)) + ) + ) + ); assertEq(baseId_, baseId); assertEq(ilkId_, daiId); assertEq(owner, admin); @@ -685,19 +829,49 @@ contract BatchTests is CompleteSetup { function testBuildAndGiveTwice() public { console.log("can build and give twice in a batch"); bytes[] memory calls = new bytes[](4); - calls[0] = abi.encodeWithSelector(VRLadle.build.selector, baseId, usdcId, 9); - calls[1] = abi.encodeWithSelector(VRLadle.give.selector, bytes12(0), admin); - calls[2] = abi.encodeWithSelector(VRLadle.build.selector, baseId, usdcId, 9); - calls[3] = abi.encodeWithSelector(VRLadle.give.selector, bytes12(0), admin); - + calls[0] = abi.encodeWithSelector( + VRLadle.build.selector, + baseId, + usdcId, + 9 + ); + calls[1] = abi.encodeWithSelector( + VRLadle.give.selector, + bytes12(0), + admin + ); + calls[2] = abi.encodeWithSelector( + VRLadle.build.selector, + baseId, + usdcId, + 9 + ); + calls[3] = abi.encodeWithSelector( + VRLadle.give.selector, + bytes12(0), + admin + ); + ladle.batch(calls); - (address owner, bytes6 baseId_, bytes6 ilkId_) = cauldron.vaults(bytes12(keccak256(abi.encodePacked(address(this), block.timestamp, uint8(10))))); + (address owner, bytes6 baseId_, bytes6 ilkId_) = cauldron.vaults( + bytes12( + keccak256( + abi.encodePacked(address(this), block.timestamp, uint8(10)) + ) + ) + ); assertEq(baseId_, baseId); assertEq(ilkId_, usdcId); assertEq(owner, admin); - ( owner, baseId_, ilkId_) = cauldron.vaults(bytes12(keccak256(abi.encodePacked(address(this), block.timestamp, uint8(11))))); + (owner, baseId_, ilkId_) = cauldron.vaults( + bytes12( + keccak256( + abi.encodePacked(address(this), block.timestamp, uint8(11)) + ) + ) + ); assertEq(baseId_, baseId); assertEq(ilkId_, usdcId); assertEq(owner, admin); @@ -706,12 +880,23 @@ contract BatchTests is CompleteSetup { function testBuildAndDestroyVault() public { console.log("can build and destroy vault in a batch"); bytes[] memory calls = new bytes[](2); - calls[0] = abi.encodeWithSelector(VRLadle.build.selector, baseId, usdcId, 9); + calls[0] = abi.encodeWithSelector( + VRLadle.build.selector, + baseId, + usdcId, + 9 + ); calls[1] = abi.encodeWithSelector(VRLadle.destroy.selector, bytes12(0)); ladle.batch(calls); - (address owner, bytes6 baseId_, bytes6 ilkId_) = cauldron.vaults(bytes12(keccak256(abi.encodePacked(address(this), block.timestamp, uint8(10))))); + (address owner, bytes6 baseId_, bytes6 ilkId_) = cauldron.vaults( + bytes12( + keccak256( + abi.encodePacked(address(this), block.timestamp, uint8(10)) + ) + ) + ); assertEq(baseId_, bytes6(0)); assertEq(ilkId_, bytes6(0)); assertEq(owner, address(0)); @@ -720,11 +905,25 @@ contract BatchTests is CompleteSetup { function testCantTweakAfterGive() public { console.log("can't tweak after give"); bytes[] memory calls = new bytes[](3); - calls[0] = abi.encodeWithSelector(VRLadle.build.selector, baseId, usdcId, 9); - calls[1] = abi.encodeWithSelector(VRLadle.give.selector, bytes12(0), admin); - calls[2] = abi.encodeWithSelector(VRLadle.tweak.selector, bytes12(0), baseId, daiId); - + calls[0] = abi.encodeWithSelector( + VRLadle.build.selector, + baseId, + usdcId, + 9 + ); + calls[1] = abi.encodeWithSelector( + VRLadle.give.selector, + bytes12(0), + admin + ); + calls[2] = abi.encodeWithSelector( + VRLadle.tweak.selector, + bytes12(0), + baseId, + daiId + ); + vm.expectRevert("Only vault owner"); ladle.batch(calls); } -} \ No newline at end of file +} diff --git a/src/test/variable/VYToken.t.sol b/src/test/variable/VYToken.t.sol index 949bf403..7dbd16af 100644 --- a/src/test/variable/VYToken.t.sol +++ b/src/test/variable/VYToken.t.sol @@ -174,9 +174,9 @@ contract VYTokenTest is VYTokenZeroState { assertEq(vyToken.flashFeeFactor(), 1); } - function testFuzz_convertToUnderlyingWithIncreasingRates(uint128 newRate) - public - { + function testFuzz_convertToUnderlyingWithIncreasingRates( + uint128 newRate + ) public { console.log( "amount of underlying received should increase as rate goes up" ); @@ -185,7 +185,7 @@ contract VYTokenTest is VYTokenZeroState { vyToken.underlyingId(), CHI ); - + vm.assume(newRate > oldPerSecondRate); newRate = uint128(bound(newRate, oldPerSecondRate, type(uint128).max)); chiRateOracle.updatePerSecondRate(vyToken.underlyingId(), CHI, newRate); vm.warp(block.timestamp + 1); @@ -198,9 +198,9 @@ contract VYTokenTest is VYTokenZeroState { assertLt(underlyingAmount, vyToken.convertToUnderlying(INK)); } - function testFuzz_convertToUnderlyingWithDecreasingRates(uint256 newRate) - public - { + function testFuzz_convertToUnderlyingWithDecreasingRates( + uint256 newRate + ) public { console.log( "amount of underlying received should decrease as rate goes down" ); @@ -217,16 +217,16 @@ contract VYTokenTest is VYTokenZeroState { assertLe(underlyingAmount, vyToken.convertToUnderlying(INK)); } - function testFuzz_convertToPrincipalIncreasingRates(uint128 newRate) - public - { + function testFuzz_convertToPrincipalIncreasingRates( + uint128 newRate + ) public { console.log("amount of principal should go down as rates go up"); uint256 principalAmount = vyToken.convertToPrincipal(INK); (uint256 oldPerSecondRate, , ) = chiRateOracle.sources( vyToken.underlyingId(), CHI ); - + vm.assume(newRate > oldPerSecondRate); newRate = uint128(bound(newRate, oldPerSecondRate, type(uint128).max)); chiRateOracle.updatePerSecondRate(vyToken.underlyingId(), CHI, newRate); vm.warp(block.timestamp + 1); @@ -235,9 +235,9 @@ contract VYTokenTest is VYTokenZeroState { assertGt(principalAmount, vyToken.convertToPrincipal(INK)); } - function testFuzz_convertToPrincipalDecreasingRates(uint256 newRate) - public - { + function testFuzz_convertToPrincipalDecreasingRates( + uint256 newRate + ) public { console.log("amount of principal should go up as rates go down"); uint256 principalAmount = vyToken.convertToPrincipal(INK); (uint256 oldPerSecondRate, , ) = chiRateOracle.sources(