From 71bda25309c1ae39e5a5c31094a527838276dd57 Mon Sep 17 00:00:00 2001 From: Sunny Vempati <5723490+sunnyvempati@users.noreply.github.com> Date: Fri, 17 Jan 2025 10:56:31 -0600 Subject: [PATCH] add submitter --- packages/protocol/cannonfile.sepolia.toml | 4 +- packages/protocol/cannonfile.test.toml | 2 +- packages/protocol/cannonfile.toml | 4 +- packages/protocol/src/vault/Vault.sol | 11 ++- .../protocol/test/Vault/Vault.duration.t.sol | 3 +- .../test/Vault/Vault.priceSubmitter.t.sol | 90 +++++++++++++++++++ 6 files changed, 107 insertions(+), 7 deletions(-) create mode 100644 packages/protocol/test/Vault/Vault.priceSubmitter.t.sol diff --git a/packages/protocol/cannonfile.sepolia.toml b/packages/protocol/cannonfile.sepolia.toml index 7f26da9c..e10ad7df 100644 --- a/packages/protocol/cannonfile.sepolia.toml +++ b/packages/protocol/cannonfile.sepolia.toml @@ -88,7 +88,7 @@ highlight=true highlight=true artifact="Vault" from="<%= settings.owner %>" -args=[ "<%= settings.vault1Name %>", "<%= settings.vault1Symbol %>", "<%= FoilYin.address %>", "<%= imports.wstETH.contracts.Token.address %>", "<%= parseEther(settings.lowerBoundMultiplier) %>", "<%= parseEther(settings.upperBoundMultiplier) %>", "<%= settings.duration %>", "0", "<%= settings.totalVaults %>" ] +args=[ "<%= settings.vault1Name %>", "<%= settings.vault1Symbol %>", "<%= FoilYin.address %>", "<%= imports.wstETH.contracts.Token.address %>", "<%= parseEther(settings.lowerBoundMultiplier) %>", "<%= parseEther(settings.upperBoundMultiplier) %>", "<%= settings.duration %>", "0", "<%= settings.totalVaults %>", "<%= settings.owner %>" ] depends = ['router.FoilYin', 'pull.wstETH', 'var.settings'] [invoke.initializeMarketForVaultYin] @@ -110,7 +110,7 @@ depends=["deploy.VaultYin"] highlight=true artifact="Vault" from="<%= settings.owner %>" -args=[ "<%= settings.vault2Name %>", "<%= settings.vault2Symbol %>", "<%= FoilYang.address %>", "<%= imports.wstETH.contracts.Token.address %>", "<%= parseEther(settings.lowerBoundMultiplier) %>", "<%= parseEther(settings.upperBoundMultiplier) %>", "<%= settings.duration %>", "1", "<%= settings.totalVaults %>" ] +args=[ "<%= settings.vault2Name %>", "<%= settings.vault2Symbol %>", "<%= FoilYang.address %>", "<%= imports.wstETH.contracts.Token.address %>", "<%= parseEther(settings.lowerBoundMultiplier) %>", "<%= parseEther(settings.upperBoundMultiplier) %>", "<%= settings.duration %>", "1", "<%= settings.totalVaults %>", "<%= settings.owner %>" ] depends = ['router.FoilYang', 'pull.wstETH', 'var.settings'] [invoke.initializeMarketForVaultYang] diff --git a/packages/protocol/cannonfile.test.toml b/packages/protocol/cannonfile.test.toml index ab93044d..c344f6d3 100644 --- a/packages/protocol/cannonfile.test.toml +++ b/packages/protocol/cannonfile.test.toml @@ -113,5 +113,5 @@ highlight=true [deploy.Vault] artifact="Vault" from="<%= settings.owner2 %>" -args=[ "<%= settings.vaultName %>", "<%= settings.vaultSymbol %>", "<%= Foil.address %>", "<%= CollateralAsset.Token.address %>", "<%= parseEther(settings.lowerBoundMultiplier) %>", "<%= parseEther(settings.upperBoundMultiplier) %>", "<%= settings.duration %>", "0", "<%= settings.totalVaults %>" ] +args=[ "<%= settings.vaultName %>", "<%= settings.vaultSymbol %>", "<%= Foil.address %>", "<%= CollateralAsset.Token.address %>", "<%= parseEther(settings.lowerBoundMultiplier) %>", "<%= parseEther(settings.upperBoundMultiplier) %>", "<%= settings.duration %>", "0", "<%= settings.totalVaults %>", "<%= settings.owner2 %>" ] depends = ['router.Foil', 'clone.CollateralAsset', 'var.settings'] diff --git a/packages/protocol/cannonfile.toml b/packages/protocol/cannonfile.toml index 61887091..21127f01 100644 --- a/packages/protocol/cannonfile.toml +++ b/packages/protocol/cannonfile.toml @@ -100,7 +100,7 @@ highlight=true highlight=true artifact="Vault" from="<%= settings.owner %>" -args=[ "<%= settings.vault1Name %>", "<%= settings.vault1Symbol %>", "<%= FoilYin.address %>", "<%= CollateralAsset.Token.address %>", "<%= parseEther(settings.lowerBoundMultiplier) %>", "<%= parseEther(settings.upperBoundMultiplier) %>", "<%= settings.duration %>", "0", "<%= settings.totalVaults %>" ] +args=[ "<%= settings.vault1Name %>", "<%= settings.vault1Symbol %>", "<%= FoilYin.address %>", "<%= CollateralAsset.Token.address %>", "<%= parseEther(settings.lowerBoundMultiplier) %>", "<%= parseEther(settings.upperBoundMultiplier) %>", "<%= settings.duration %>", "0", "<%= settings.totalVaults %>", "<%= settings.owner %>" ] depends = ['router.FoilYin', 'clone.CollateralAsset', 'var.settings'] [invoke.initializeMarketForVault1] @@ -122,7 +122,7 @@ depends=["deploy.VaultYin", "clone.BondCurrency"] highlight=true artifact="Vault" from="<%= settings.owner %>" -args=[ "<%= settings.vault2Name %>", "<%= settings.vault2Symbol %>", "<%= FoilYang.address %>", "<%= CollateralAsset.Token.address %>", "<%= parseEther(settings.lowerBoundMultiplier) %>", "<%= parseEther(settings.upperBoundMultiplier) %>", "<%= settings.duration %>", "1", "<%= settings.totalVaults %>" ] +args=[ "<%= settings.vault2Name %>", "<%= settings.vault2Symbol %>", "<%= FoilYang.address %>", "<%= CollateralAsset.Token.address %>", "<%= parseEther(settings.lowerBoundMultiplier) %>", "<%= parseEther(settings.upperBoundMultiplier) %>", "<%= settings.duration %>", "1", "<%= settings.totalVaults %>", "<%= settings.owner %>" ] depends = ['router.FoilYang', 'clone.CollateralAsset', 'var.settings'] [invoke.initializeMarketForVault2] diff --git a/packages/protocol/src/vault/Vault.sol b/packages/protocol/src/vault/Vault.sol index a8f48206..3f8528c9 100644 --- a/packages/protocol/src/vault/Vault.sol +++ b/packages/protocol/src/vault/Vault.sol @@ -88,6 +88,11 @@ contract Vault is IVault, ERC20, ERC165, ReentrancyGuardUpgradeable { bool __VAULT_HALTED; + /** + * only address that has permission to submit market settlement prices + */ + address public settlementPriceSubmitter; + constructor( string memory _name, string memory _symbol, @@ -97,7 +102,8 @@ contract Vault is IVault, ERC20, ERC165, ReentrancyGuardUpgradeable { uint256 _upperBoundMultiplier, uint256 _duration, uint256 _vaultIndex, - uint256 _totalVaults + uint256 _totalVaults, + address _settlementPriceSubmitter ) ERC20(_name, _symbol) { market = IFoil(_marketAddress); collateralAsset = IERC20(_collateralAssetAddress); @@ -108,6 +114,7 @@ contract Vault is IVault, ERC20, ERC165, ReentrancyGuardUpgradeable { lowerBoundMultiplier = _lowerBoundMultiplier; upperBoundMultiplier = _upperBoundMultiplier; vaultInitializer = msg.sender; + settlementPriceSubmitter = _settlementPriceSubmitter; } /// @notice initializes the first epoch @@ -142,6 +149,8 @@ contract Vault is IVault, ERC20, ERC165, ReentrancyGuardUpgradeable { uint256 epochId, uint160 price ) external returns (bytes32 assertionId) { + require(msg.sender == settlementPriceSubmitter, "Not authorized"); + (, , , , IFoilStructs.MarketParams memory marketParams) = market .getMarket(); IERC20 bondCurrency = IERC20(marketParams.bondCurrency); diff --git a/packages/protocol/test/Vault/Vault.duration.t.sol b/packages/protocol/test/Vault/Vault.duration.t.sol index 03fb34f8..e5e14009 100644 --- a/packages/protocol/test/Vault/Vault.duration.t.sol +++ b/packages/protocol/test/Vault/Vault.duration.t.sol @@ -48,7 +48,8 @@ contract VaultDurationTest is TestVault { 1732050807568877200, //sqrt(3) duration, vaultIndex, - totalVaults + totalVaults, + vaultOwner ) ); vm.stopPrank(); diff --git a/packages/protocol/test/Vault/Vault.priceSubmitter.t.sol b/packages/protocol/test/Vault/Vault.priceSubmitter.t.sol new file mode 100644 index 00000000..4c2841cf --- /dev/null +++ b/packages/protocol/test/Vault/Vault.priceSubmitter.t.sol @@ -0,0 +1,90 @@ +// SPDX-License-Identifier: MIT +pragma solidity >=0.8.2 <0.9.0; + +import "forge-std/Test.sol"; +import "cannon-std/Cannon.sol"; +import {IFoil} from "../../src/market/interfaces/IFoil.sol"; +import {IMintableToken} from "../../src/market/external/IMintableToken.sol"; +import {IUMASettlementModule} from "../../src/market/interfaces/IUMASettlementModule.sol"; +import {TestVault} from "../helpers/TestVault.sol"; +import {TestUser} from "../helpers/TestUser.sol"; +import {IVault} from "../../src/vault/interfaces/IVault.sol"; +import {IFoilStructs} from "../../src/market/interfaces/IFoilStructs.sol"; + +contract VaultPriceSubmitterTest is TestVault { + using Cannon for Vm; + + IFoil foil; + IVault vault; + IMintableToken collateralAsset; + + uint160 initialSqrtPriceX96 = 250541448375047946302209916928; // 10 + uint256 epochStartTime; + + address lp1; + address lp2; + function setUp() public { + lp1 = TestUser.createUser("LP1", 100_000 ether); + lp2 = TestUser.createUser("LP2", 100_000 ether); + + (foil, vault, collateralAsset) = initializeVault( + new address[](0), + 100 ether, + 10_000 + ); + + vm.prank(lp1); + vault.requestDeposit(10 ether); + + vm.prank(lp2); + vault.requestDeposit(1 ether); + + epochStartTime = block.timestamp + 60; + vm.prank(vaultOwner); + vault.initializeFirstEpoch(initialSqrtPriceX96); + + vault.deposit(0, lp1); + vault.deposit(0, lp2); + + vm.prank(lp1); + vault.requestRedeem(5 ether); + + vm.warp(epochStartTime + 30 days); + } + + function test_reverts_when_not_settlement_price_submitter() public { + (, , , , IFoilStructs.MarketParams memory marketParams) = foil + .getMarket(); + + IMintableToken bondCurrency = IMintableToken( + vm.getAddress("BondCurrency.Token") + ); + bondCurrency.mint(marketParams.bondAmount * 2, lp1); + + bondCurrency.approve(address(vault), marketParams.bondAmount); + vm.expectRevert("Not authorized"); + vm.prank(lp1); + vault.submitMarketSettlementPrice(1, initialSqrtPriceX96); + } + + function test_works_when_settlement_price_submitter() public { + (, , , , IFoilStructs.MarketParams memory marketParams) = foil + .getMarket(); + + IMintableToken bondCurrency = IMintableToken( + vm.getAddress("BondCurrency.Token") + ); + bondCurrency.mint(marketParams.bondAmount * 2, vaultOwner); + vm.startPrank(vaultOwner); + bondCurrency.approve(address(vault), marketParams.bondAmount); + vm.expectEmit(true, true, true, true, address(foil)); + emit IUMASettlementModule.SettlementSubmitted( + 1, + vaultOwner, + initialSqrtPriceX96, + block.timestamp + ); + vault.submitMarketSettlementPrice(1, initialSqrtPriceX96); + vm.stopPrank(); + } +}