diff --git a/.github/workflows/manual-sol-artifacts.yaml b/.github/workflows/manual-sol-artifacts.yaml index 64711a41..b83b0ed6 100644 --- a/.github/workflows/manual-sol-artifacts.yaml +++ b/.github/workflows/manual-sol-artifacts.yaml @@ -28,7 +28,7 @@ on: type: choice options: - ownable-oracle-vault - - flare-ftso-oracle-price-vault + - sceptre-staked-flare-price-vault - implementations receipt-vault-asset: @@ -84,6 +84,7 @@ jobs: RECEIPT_VAULT_SYMBOL: ${{ inputs.receipt-vault-symbol || '' }} OWNER_ADDRESS: ${{ inputs.owner || '' }} CLONE_FACTORY : ${{ vars[env.clone_factory_name] || '' }} + SCEPTRE_STAKED_FLR_ADDRESS: ${{ vars.SCEPTRE_STAKED_FLR_ADDRESS || '' }} ERC20_PRICE_ORACLE_VAULT_IMPLEMENTATION: ${{ vars[env.erc20_price_oracle_vault_implementation_name] || '' }} DEPLOY_BROADCAST: '1' DEPLOYMENT_KEY: ${{ secrets.CI_PRIVATE_KEY }} diff --git a/contracts/concrete/oracle/FlareFTSOOracle.sol b/contracts/concrete/oracle/FlareFTSOOracle.sol deleted file mode 100644 index 4f0982cf..00000000 --- a/contracts/concrete/oracle/FlareFTSOOracle.sol +++ /dev/null @@ -1,12 +0,0 @@ -// SPDX-License-Identifier: CAL -pragma solidity =0.8.25; - -import {IPriceOracleV1} from "../../interface/IPriceOracleV1.sol"; -import {LibFtsoCurrentPriceUsd} from "rain.flare/src/lib/price/LibFtsoCurrentPriceUsd.sol"; - -contract FlareFTSOOracle is IPriceOracleV1 { - /// @inheritdoc IPriceOracleV1 - function price() external view override returns (uint256) { - return LibFtsoCurrentPriceUsd.ftsoCurrentPriceUsd("FLR", 300); - } -} diff --git a/contracts/concrete/oracle/FtsoCurrentPriceUsdOracle.sol b/contracts/concrete/oracle/FtsoCurrentPriceUsdOracle.sol new file mode 100644 index 00000000..8e4843a0 --- /dev/null +++ b/contracts/concrete/oracle/FtsoCurrentPriceUsdOracle.sol @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: CAL +pragma solidity =0.8.25; + +import {IPriceOracleV1} from "../../interface/IPriceOracleV1.sol"; +import {LibFtsoCurrentPriceUsd} from "rain.flare/lib/price/LibFtsoCurrentPriceUsd.sol"; +import {LibIntOrAString, IntOrAString} from "rain.intorastring/lib/LibIntOrAString.sol"; + +struct FtsoCurrentPriceUsdOracleConfig { + string symbol; + uint256 staleAfter; +} + +contract FtsoCurrentPriceUsdOracle is IPriceOracleV1 { + event Construction(address sender, FtsoCurrentPriceUsdOracleConfig config); + + IntOrAString public immutable iSymbol; + uint256 public immutable iStaleAfter; + + constructor(FtsoCurrentPriceUsdOracleConfig memory config) { + iSymbol = LibIntOrAString.fromString2(config.symbol); + iStaleAfter = config.staleAfter; + + emit Construction(msg.sender, config); + } + + /// @inheritdoc IPriceOracleV1 + function price() external view override returns (uint256) { + return LibFtsoCurrentPriceUsd.ftsoCurrentPriceUsd(LibIntOrAString.toString(iSymbol), iStaleAfter); + } +} diff --git a/contracts/concrete/oracle/SceptreStakedFlrOracle.sol b/contracts/concrete/oracle/SceptreStakedFlrOracle.sol new file mode 100644 index 00000000..2069b856 --- /dev/null +++ b/contracts/concrete/oracle/SceptreStakedFlrOracle.sol @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: CAL +pragma solidity =0.8.25; + +import {IPriceOracleV1} from "../../interface/IPriceOracleV1.sol"; +import {IStakedFlr} from "rain.flare/interface/IStakedFlr.sol"; + +contract SceptreStakedFlrOracle is IPriceOracleV1 { + IStakedFlr public immutable iStakedFlr; + + constructor(IStakedFlr stakedFlr) { + iStakedFlr = stakedFlr; + } + + /// @inheritdoc IPriceOracleV1 + function price() external view override returns (uint256) { + return iStakedFlr.getSharesByPooledFlr(1e18); + } +} diff --git a/contracts/oracle/price/TwoPriceOracle.sol b/contracts/concrete/oracle/TwoPriceOracle.sol similarity index 100% rename from contracts/oracle/price/TwoPriceOracle.sol rename to contracts/concrete/oracle/TwoPriceOracle.sol diff --git a/foundry.toml b/foundry.toml index 82225d27..4dfdf24b 100644 --- a/foundry.toml +++ b/foundry.toml @@ -15,5 +15,7 @@ fuzz.runs = 2056 remappings = [ "rain.factory/=lib/rain.factory/src/", + "rain.intorastring/=lib/rain.interpreter/lib/rain.intorastring/src/", "forge-std/=lib/rain.interpreter/lib/forge-std/src/", + "rain.flare/=lib/rain.flare/src/", ] \ No newline at end of file diff --git a/lib/rain.flare b/lib/rain.flare index 48160f27..24e57b5c 160000 --- a/lib/rain.flare +++ b/lib/rain.flare @@ -1 +1 @@ -Subproject commit 48160f27bbf9a379d0414f63b66cf94205bd79d8 +Subproject commit 24e57b5cd2d8ea59b70089ba1ec8fefd19d12023 diff --git a/script/Deploy.sol b/script/Deploy.sol index ae521ced..746133d0 100644 --- a/script/Deploy.sol +++ b/script/Deploy.sol @@ -9,16 +9,22 @@ import { } from "contracts/concrete/vault/ERC20PriceOracleReceiptVault.sol"; import {VaultConfig} from "contracts/abstract/ReceiptVault.sol"; import {ICloneableFactoryV2} from "rain.factory/interface/ICloneableFactoryV2.sol"; -import {FlareFTSOOracle} from "contracts/concrete/oracle/FlareFTSOOracle.sol"; +import { + FtsoCurrentPriceUsdOracle, + FtsoCurrentPriceUsdOracleConfig +} from "contracts/concrete/oracle/FtsoCurrentPriceUsdOracle.sol"; import { OffchainAssetReceiptVault, ReceiptVaultConstructionConfig } from "contracts/concrete/vault/OffchainAssetReceiptVault.sol"; import {Receipt as ReceiptContract} from "contracts/concrete/receipt/Receipt.sol"; +import {SceptreStakedFlrOracle} from "contracts/concrete/oracle/SceptreStakedFlrOracle.sol"; +import {TwoPriceOracle, TwoPriceOracleConfig} from "contracts/concrete/oracle/TwoPriceOracle.sol"; +import {IStakedFlr} from "rain.flare/interface/IStakedFlr.sol"; bytes32 constant DEPLOYMENT_SUITE_IMPLEMENTATIONS = keccak256("implementations"); bytes32 constant DEPLOYMENT_SUITE_OWNABLE_ORACLE_VAULT = keccak256("ownable-oracle-vault"); -bytes32 constant DEPLOYMENT_SUITE_FLARE_FTSO_ORACLE_PRICE_VAULT = keccak256("flare-ftso-oracle-price-vault"); +bytes32 constant DEPLOYMENT_SUITE_STAKED_FLR_PRICE_VAULT = keccak256("sceptre-staked-flare-price-vault"); /// @title Deploy /// This is intended to be run on every commit by CI to a testnet such as mumbai, @@ -39,15 +45,29 @@ contract Deploy is Script { vm.stopBroadcast(); } - function deployFlareFTSOOraclePriceVault(uint256 deploymentKey) internal { + function deployStakedFlrPriceVault(uint256 deploymentKey) internal { vm.startBroadcast(deploymentKey); + address flareFTSOOracle = address( + new FtsoCurrentPriceUsdOracle( + FtsoCurrentPriceUsdOracleConfig({ + symbol: "FLR", + // 30 mins. + staleAfter: 1800 + }) + ) + ); + address stakedFlr = vm.envAddress("SCEPTRE_STAKED_FLR_ADDRESS"); + address stakedFlrOracle = address(new SceptreStakedFlrOracle(IStakedFlr(stakedFlr))); + address twoPriceOracle = + address(new TwoPriceOracle(TwoPriceOracleConfig({base: flareFTSOOracle, quote: stakedFlrOracle}))); + ICloneableFactoryV2(vm.envAddress("CLONE_FACTORY")).clone( vm.envAddress("ERC20_PRICE_ORACLE_VAULT_IMPLEMENTATION"), abi.encode( ERC20PriceOracleVaultConfig({ - priceOracle: address(new FlareFTSOOracle()), + priceOracle: twoPriceOracle, vaultConfig: VaultConfig({ - asset: vm.envAddress("RECEIPT_VAULT_ASSET"), + asset: stakedFlr, name: vm.envString("RECEIPT_VAULT_NAME"), symbol: vm.envString("RECEIPT_VAULT_SYMBOL") }) @@ -90,8 +110,8 @@ contract Deploy is Script { if (suite == DEPLOYMENT_SUITE_IMPLEMENTATIONS) { deployImplementations(deployerPrivateKey); - } else if (suite == DEPLOYMENT_SUITE_FLARE_FTSO_ORACLE_PRICE_VAULT) { - deployFlareFTSOOraclePriceVault(deployerPrivateKey); + } else if (suite == DEPLOYMENT_SUITE_STAKED_FLR_PRICE_VAULT) { + deployStakedFlrPriceVault(deployerPrivateKey); } else { revert("Unknown deployment suite"); } diff --git a/slither.config.json b/slither.config.json index f84294d2..c081d3af 100644 --- a/slither.config.json +++ b/slither.config.json @@ -1,4 +1,4 @@ { - "detectors_to_exclude": "solc-version,block-timestamp,unused-imports,different-pragma-directives-are-used", + "detectors_to_exclude": "solc-version,block-timestamp,unused-imports,different-pragma-directives-are-used,assembly-usage", "filter_paths": "lib/openzeppelin-contracts,lib/rain.tier.interface,test/,node_modules" } diff --git a/test/foundry/abstract/ERC20PriceOracleReceiptVaultTest.sol b/test/foundry/abstract/ERC20PriceOracleReceiptVaultTest.sol index f2e06837..aab4cb8a 100644 --- a/test/foundry/abstract/ERC20PriceOracleReceiptVaultTest.sol +++ b/test/foundry/abstract/ERC20PriceOracleReceiptVaultTest.sol @@ -11,7 +11,7 @@ import { } from "contracts/concrete/vault/ERC20PriceOracleReceiptVault.sol"; import {LibERC20PriceOracleReceiptVaultCreator} from "../lib/LibERC20PriceOracleReceiptVaultCreator.sol"; import {Receipt as ReceiptContract} from "contracts/concrete/receipt/Receipt.sol"; -import {TwoPriceOracle, TwoPriceOracleConfig} from "contracts/oracle/price/TwoPriceOracle.sol"; +import {TwoPriceOracle, TwoPriceOracleConfig} from "contracts/concrete/oracle/TwoPriceOracle.sol"; import { ChainlinkFeedPriceOracle, ChainlinkFeedPriceOracleConfig diff --git a/contracts/test/ReadWriteTier.sol b/test/foundry/concrete/ReadWriteTier.sol similarity index 100% rename from contracts/test/ReadWriteTier.sol rename to test/foundry/concrete/ReadWriteTier.sol diff --git a/test/foundry/src/concrete/erc20PriceOracle/ERC20PriceOracleReceiptVault.baseRedeem.t.sol b/test/foundry/src/concrete/erc20PriceOracle/ERC20PriceOracleReceiptVault.baseRedeem.t.sol index f09cdd20..5cc1b550 100644 --- a/test/foundry/src/concrete/erc20PriceOracle/ERC20PriceOracleReceiptVault.baseRedeem.t.sol +++ b/test/foundry/src/concrete/erc20PriceOracle/ERC20PriceOracleReceiptVault.baseRedeem.t.sol @@ -3,7 +3,7 @@ pragma solidity =0.8.25; import {ERC20PriceOracleReceiptVault} from "../../../../../contracts/concrete/vault/ERC20PriceOracleReceiptVault.sol"; import {ERC20PriceOracleReceiptVaultTest, Vm} from "test/foundry/abstract/ERC20PriceOracleReceiptVaultTest.sol"; -import {TwoPriceOracle} from "../../../../../contracts/oracle/price/TwoPriceOracle.sol"; +import {TwoPriceOracle} from "../../../../../contracts/concrete/oracle/TwoPriceOracle.sol"; import { LibFixedPointDecimalArithmeticOpenZeppelin, Math diff --git a/test/foundry/src/concrete/erc20PriceOracle/ERC20PriceOracleReceiptVault.baseWithdraw.t.sol b/test/foundry/src/concrete/erc20PriceOracle/ERC20PriceOracleReceiptVault.baseWithdraw.t.sol index 636f3249..85393aac 100644 --- a/test/foundry/src/concrete/erc20PriceOracle/ERC20PriceOracleReceiptVault.baseWithdraw.t.sol +++ b/test/foundry/src/concrete/erc20PriceOracle/ERC20PriceOracleReceiptVault.baseWithdraw.t.sol @@ -3,7 +3,7 @@ pragma solidity =0.8.25; import {ERC20PriceOracleReceiptVault} from "../../../../../contracts/concrete/vault/ERC20PriceOracleReceiptVault.sol"; import {ERC20PriceOracleReceiptVaultTest, Vm} from "test/foundry/abstract/ERC20PriceOracleReceiptVaultTest.sol"; -import {TwoPriceOracle} from "../../../../../contracts/oracle/price/TwoPriceOracle.sol"; +import {TwoPriceOracle} from "../../../../../contracts/concrete/oracle/TwoPriceOracle.sol"; import { LibFixedPointDecimalArithmeticOpenZeppelin, Math diff --git a/test/foundry/src/concrete/erc20PriceOracle/ERC20PriceOracleReceiptVault.construct.t.sol b/test/foundry/src/concrete/erc20PriceOracle/ERC20PriceOracleReceiptVault.construct.t.sol index 9c57a692..8b2b36a8 100644 --- a/test/foundry/src/concrete/erc20PriceOracle/ERC20PriceOracleReceiptVault.construct.t.sol +++ b/test/foundry/src/concrete/erc20PriceOracle/ERC20PriceOracleReceiptVault.construct.t.sol @@ -7,7 +7,7 @@ import { ERC20PriceOracleReceiptVaultConfig } from "../../../../../contracts/concrete/vault/ERC20PriceOracleReceiptVault.sol"; import {ERC20PriceOracleReceiptVaultTest, Vm} from "test/foundry/abstract/ERC20PriceOracleReceiptVaultTest.sol"; -import {TwoPriceOracle} from "../../../../../contracts/oracle/price/TwoPriceOracle.sol"; +import {TwoPriceOracle} from "../../../../../contracts/concrete/oracle/TwoPriceOracle.sol"; contract ERC20PriceOracleReceiptVaultConstructionTest is ERC20PriceOracleReceiptVaultTest { /// Test ERC20PriceOracleReceiptVault is constracted diff --git a/test/foundry/src/concrete/erc20PriceOracle/ERC20PriceOracleReceiptVault.deposit.t.sol b/test/foundry/src/concrete/erc20PriceOracle/ERC20PriceOracleReceiptVault.deposit.t.sol index d04c229c..852bda7d 100644 --- a/test/foundry/src/concrete/erc20PriceOracle/ERC20PriceOracleReceiptVault.deposit.t.sol +++ b/test/foundry/src/concrete/erc20PriceOracle/ERC20PriceOracleReceiptVault.deposit.t.sol @@ -4,7 +4,7 @@ pragma solidity =0.8.25; import {MinShareRatio, ZeroAssetsAmount, ZeroReceiver} from "../../../../../contracts/abstract/ReceiptVault.sol"; import {ERC20PriceOracleReceiptVault} from "../../../../../contracts/concrete/vault/ERC20PriceOracleReceiptVault.sol"; import {ERC20PriceOracleReceiptVaultTest, Vm} from "test/foundry/abstract/ERC20PriceOracleReceiptVaultTest.sol"; -import {TwoPriceOracle} from "../../../../../contracts/oracle/price/TwoPriceOracle.sol"; +import {TwoPriceOracle} from "../../../../../contracts/concrete/oracle/TwoPriceOracle.sol"; import { LibFixedPointDecimalArithmeticOpenZeppelin, Math diff --git a/test/foundry/src/concrete/erc20PriceOracle/ERC20PriceOracleReceiptVault.mint.t.sol b/test/foundry/src/concrete/erc20PriceOracle/ERC20PriceOracleReceiptVault.mint.t.sol index 35f2d3ef..0df54977 100644 --- a/test/foundry/src/concrete/erc20PriceOracle/ERC20PriceOracleReceiptVault.mint.t.sol +++ b/test/foundry/src/concrete/erc20PriceOracle/ERC20PriceOracleReceiptVault.mint.t.sol @@ -4,7 +4,7 @@ pragma solidity =0.8.25; import {MinShareRatio, ZeroAssetsAmount, ZeroReceiver} from "../../../../../contracts/abstract/ReceiptVault.sol"; import {ERC20PriceOracleReceiptVault} from "../../../../../contracts/concrete/vault/ERC20PriceOracleReceiptVault.sol"; import {ERC20PriceOracleReceiptVaultTest, Vm} from "test/foundry/abstract/ERC20PriceOracleReceiptVaultTest.sol"; -import {TwoPriceOracle} from "../../../../../contracts/oracle/price/TwoPriceOracle.sol"; +import {TwoPriceOracle} from "../../../../../contracts/concrete/oracle/TwoPriceOracle.sol"; import { LibFixedPointDecimalArithmeticOpenZeppelin, Math diff --git a/test/foundry/src/concrete/erc20PriceOracle/ERC20PriceOracleReceiptVault.receiptVault.t.sol b/test/foundry/src/concrete/erc20PriceOracle/ERC20PriceOracleReceiptVault.receiptVault.t.sol index ddf8fa2c..cc884c71 100644 --- a/test/foundry/src/concrete/erc20PriceOracle/ERC20PriceOracleReceiptVault.receiptVault.t.sol +++ b/test/foundry/src/concrete/erc20PriceOracle/ERC20PriceOracleReceiptVault.receiptVault.t.sol @@ -4,7 +4,7 @@ pragma solidity =0.8.25; import {MinShareRatio, ZeroAssetsAmount, ZeroReceiver} from "../../../../../contracts/abstract/ReceiptVault.sol"; import {ERC20PriceOracleReceiptVault} from "../../../../../contracts/concrete/vault/ERC20PriceOracleReceiptVault.sol"; import {ERC20PriceOracleReceiptVaultTest, Vm} from "test/foundry/abstract/ERC20PriceOracleReceiptVaultTest.sol"; -import {TwoPriceOracle} from "../../../../../contracts/oracle/price/TwoPriceOracle.sol"; +import {TwoPriceOracle} from "../../../../../contracts/concrete/oracle/TwoPriceOracle.sol"; import { LibFixedPointDecimalArithmeticOpenZeppelin, Math diff --git a/test/foundry/src/concrete/erc20PriceOracle/ERC20PriceOracleReceiptVault.redeem.t.sol b/test/foundry/src/concrete/erc20PriceOracle/ERC20PriceOracleReceiptVault.redeem.t.sol index a6974420..19bd9904 100644 --- a/test/foundry/src/concrete/erc20PriceOracle/ERC20PriceOracleReceiptVault.redeem.t.sol +++ b/test/foundry/src/concrete/erc20PriceOracle/ERC20PriceOracleReceiptVault.redeem.t.sol @@ -3,7 +3,7 @@ pragma solidity =0.8.25; import {ERC20PriceOracleReceiptVault} from "../../../../../contracts/concrete/vault/ERC20PriceOracleReceiptVault.sol"; import {ERC20PriceOracleReceiptVaultTest, Vm} from "test/foundry/abstract/ERC20PriceOracleReceiptVaultTest.sol"; -import {TwoPriceOracle} from "../../../../../contracts/oracle/price/TwoPriceOracle.sol"; +import {TwoPriceOracle} from "../../../../../contracts/concrete/oracle/TwoPriceOracle.sol"; import { LibFixedPointDecimalArithmeticOpenZeppelin, Math diff --git a/test/foundry/src/concrete/erc20PriceOracle/ERC20PriceOracleReceiptVault.withdraw.t.sol b/test/foundry/src/concrete/erc20PriceOracle/ERC20PriceOracleReceiptVault.withdraw.t.sol index ceba4b3c..67623851 100644 --- a/test/foundry/src/concrete/erc20PriceOracle/ERC20PriceOracleReceiptVault.withdraw.t.sol +++ b/test/foundry/src/concrete/erc20PriceOracle/ERC20PriceOracleReceiptVault.withdraw.t.sol @@ -3,7 +3,7 @@ pragma solidity =0.8.25; import {ERC20PriceOracleReceiptVault} from "../../../../../contracts/concrete/vault/ERC20PriceOracleReceiptVault.sol"; import {ERC20PriceOracleReceiptVaultTest, Vm} from "test/foundry/abstract/ERC20PriceOracleReceiptVaultTest.sol"; -import {TwoPriceOracle} from "../../../../../contracts/oracle/price/TwoPriceOracle.sol"; +import {TwoPriceOracle} from "../../../../../contracts/concrete/oracle/TwoPriceOracle.sol"; import { LibFixedPointDecimalArithmeticOpenZeppelin, Math diff --git a/test/foundry/src/concrete/vault/OffchainAssetReceiptVault.roles.t.sol b/test/foundry/src/concrete/vault/OffchainAssetReceiptVault.roles.t.sol index e639e13b..5ad7a80e 100644 --- a/test/foundry/src/concrete/vault/OffchainAssetReceiptVault.roles.t.sol +++ b/test/foundry/src/concrete/vault/OffchainAssetReceiptVault.roles.t.sol @@ -10,7 +10,7 @@ import { } from "contracts/concrete/vault/OffchainAssetReceiptVault.sol"; import {StringsUpgradeable} from "openzeppelin-contracts-upgradeable/contracts/utils/StringsUpgradeable.sol"; import {TestErc20} from "contracts/test/TestErc20.sol"; -import {ReadWriteTier} from "contracts/test/ReadWriteTier.sol"; +import {ReadWriteTier} from "../../../concrete/ReadWriteTier.sol"; contract RolesTest is OffchainAssetReceiptVaultTest { /// Test to checks Admin roles granted