diff --git a/.gitmodules b/.gitmodules index 3b5c40e05..5414dbf97 100644 --- a/.gitmodules +++ b/.gitmodules @@ -7,3 +7,6 @@ [submodule "stable-asset"] path = ecosystem-modules/stable-asset url = https://github.com/nutsfinance/stable-asset.git +[submodule "pint"] + path = ecosystem-modules/pint + url = https://github.com/ChainSafe/PINT.git diff --git a/Cargo.lock b/Cargo.lock index 360a8ad41..ab8e447d8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5149,19 +5149,24 @@ dependencies = [ "orml-xcm", "orml-xcm-support", "orml-xtokens", + "pallet-asset-index", "pallet-aura", "pallet-authorship", "pallet-balances", "pallet-bounties", "pallet-collective", + "pallet-committee", "pallet-democracy", "pallet-elections-phragmen", "pallet-indices", + "pallet-local-treasury", "pallet-membership", "pallet-multisig", "pallet-offences", + "pallet-price-feed", "pallet-proxy", "pallet-recovery", + "pallet-saft-registry", "pallet-scheduler", "pallet-session", "pallet-sudo", @@ -5175,6 +5180,7 @@ dependencies = [ "parachain-info", "parity-scale-codec", "polkadot-parachain", + "primitives", "runtime-common", "serde", "serde_json", @@ -6722,6 +6728,25 @@ dependencies = [ "stable_deref_trait", ] +[[package]] +name = "pallet-asset-index" +version = "0.0.1" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "orml-traits", + "pallet-chainlink-feed", + "pallet-price-feed", + "parity-scale-codec", + "polkadot-parachain", + "primitives", + "serde", + "sp-core", + "xcm", + "xcm-executor", +] + [[package]] name = "pallet-aura" version = "4.0.0-dev" @@ -6917,6 +6942,22 @@ dependencies = [ "sp-std", ] +[[package]] +name = "pallet-chainlink-feed" +version = "0.1.0" +source = "git+https://github.com/smartcontractkit/chainlink-polkadot?branch=polkadot-v0.9.9#79107694e226c94301d3479f3f96a88892f917f2" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "parity-scale-codec", + "serde", + "sp-arithmetic", + "sp-core", + "sp-runtime", + "sp-std", +] + [[package]] name = "pallet-collective" version = "4.0.0-dev" @@ -6933,6 +6974,17 @@ dependencies = [ "sp-std", ] +[[package]] +name = "pallet-committee" +version = "0.0.1" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "log", + "parity-scale-codec", +] + [[package]] name = "pallet-democracy" version = "4.0.0-dev" @@ -7072,6 +7124,16 @@ dependencies = [ "sp-std", ] +[[package]] +name = "pallet-local-treasury" +version = "0.0.1" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "parity-scale-codec", +] + [[package]] name = "pallet-membership" version = "4.0.0-dev" @@ -7204,6 +7266,19 @@ dependencies = [ "sp-std", ] +[[package]] +name = "pallet-price-feed" +version = "0.0.1" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "pallet-chainlink-feed", + "parity-scale-codec", + "primitives", + "serde", +] + [[package]] name = "pallet-proxy" version = "4.0.0-dev" @@ -7233,6 +7308,19 @@ dependencies = [ "sp-std", ] +[[package]] +name = "pallet-saft-registry" +version = "0.0.1" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "pallet-asset-index", + "parity-scale-codec", + "primitives", + "xcm", +] + [[package]] name = "pallet-scheduler" version = "4.0.0-dev" @@ -9018,6 +9106,17 @@ dependencies = [ "uint", ] +[[package]] +name = "primitives" +version = "0.0.1" +dependencies = [ + "frame-support", + "frame-system", + "parity-scale-codec", + "serde", + "xcm", +] + [[package]] name = "primitives-proc-macro" version = "1.4.1" diff --git a/Cargo.toml b/Cargo.toml index 3716b0bfd..8dc8c57fc 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -28,7 +28,7 @@ members = [ "orml/nft", "orml/oracle", "orml/oracle/rpc", - "orml/oracle/rpc/runtime-api", + "orml/oracle/rpc/runtime-api", "orml/rewards", "orml/tokens", "orml/traits", @@ -47,6 +47,9 @@ members = [ "ecosystem-modules/compound-cash", "ecosystem-modules/stable-asset/lib/stable-asset", ] +exclude = [ + "ecosystem-modules/pint" +] resolver = "2" @@ -300,3 +303,10 @@ pallet-beefy = { git = "https://github.com/paritytech//grandpa-bridge-gadget", r beefy-primitives = { git = "https://github.com/paritytech//grandpa-bridge-gadget", rev = "f40c0ab7b327e874d5c8d699bfa5d762f1759ee0" } beefy-gadget = { git = "https://github.com/paritytech//grandpa-bridge-gadget", rev = "f40c0ab7b327e874d5c8d699bfa5d762f1759ee0" } beefy-gadget-rpc = { git = "https://github.com/paritytech//grandpa-bridge-gadget", rev = "f40c0ab7b327e874d5c8d699bfa5d762f1759ee0" } + +[patch."https://github.com/open-web3-stack/open-runtime-module-library"] +orml-currencies = { path = "./orml/currencies" } +orml-tokens = { path = "./orml/tokens" } +orml-xtokens = { path = "./orml/xtokens" } +orml-xcm-support = { path = "./orml/xcm-support" } +orml-traits = { path = "./orml/traits" } diff --git a/ecosystem-modules/pint b/ecosystem-modules/pint new file mode 160000 index 000000000..40d4eec2b --- /dev/null +++ b/ecosystem-modules/pint @@ -0,0 +1 @@ +Subproject commit 40d4eec2b3a8f580631d82e1664a5c2411666964 diff --git a/node/service/src/chain_spec/mandala.rs b/node/service/src/chain_spec/mandala.rs index 1f7abfd9a..d962c9dc6 100644 --- a/node/service/src/chain_spec/mandala.rs +++ b/node/service/src/chain_spec/mandala.rs @@ -237,9 +237,9 @@ fn testnet_genesis( CollatorSelectionConfig, DexConfig, EVMConfig, EnabledTradingPairs, FinancialCouncilMembershipConfig, GeneralCouncilMembershipConfig, HomaCouncilMembershipConfig, IndicesConfig, NativeTokenExistentialDeposit, OperatorMembershipAcalaConfig, OperatorMembershipBandConfig, OrmlNFTConfig, ParachainInfoConfig, Period, - RenVmBridgeConfig, SessionConfig, SessionKeys, SessionManagerConfig, StakingPoolConfig, StarportConfig, - SudoConfig, SystemConfig, TechnicalCommitteeMembershipConfig, TokensConfig, VestingConfig, ACA, AUSD, DOT, - LDOT, RENBTC, + PintCommitteeConfig, RenVmBridgeConfig, SessionConfig, SessionKeys, SessionManagerConfig, StakingPoolConfig, + StarportConfig, SudoConfig, SystemConfig, TechnicalCommitteeMembershipConfig, TokensConfig, VestingConfig, ACA, + AUSD, DOT, LDOT, RENBTC, }; let existential_deposit = NativeTokenExistentialDeposit::get(); @@ -366,7 +366,7 @@ fn testnet_genesis( }, evm: EVMConfig { accounts: evm_genesis_accounts, - treasury: root_key, + treasury: root_key.clone(), }, staking_pool: StakingPoolConfig { staking_pool_params: module_staking_pool::Params { @@ -430,6 +430,12 @@ fn testnet_genesis( aura: Default::default(), aura_ext: Default::default(), parachain_system: Default::default(), + + // pint configs + pint_committee: PintCommitteeConfig { + council_members: vec![root_key], + ..Default::default() + }, } } @@ -444,9 +450,9 @@ fn mandala_genesis( CdpEngineConfig, CdpTreasuryConfig, CollatorSelectionConfig, DexConfig, EVMConfig, EnabledTradingPairs, FinancialCouncilMembershipConfig, GeneralCouncilMembershipConfig, HomaCouncilMembershipConfig, IndicesConfig, NativeTokenExistentialDeposit, OperatorMembershipAcalaConfig, OperatorMembershipBandConfig, OrmlNFTConfig, - ParachainInfoConfig, Period, RenVmBridgeConfig, SessionConfig, SessionKeys, SessionManagerConfig, - StakingPoolConfig, StarportConfig, SudoConfig, SystemConfig, TechnicalCommitteeMembershipConfig, TokensConfig, - VestingConfig, ACA, AUSD, DOT, LDOT, RENBTC, + ParachainInfoConfig, Period, PintCommitteeConfig, RenVmBridgeConfig, SessionConfig, SessionKeys, + SessionManagerConfig, StakingPoolConfig, StarportConfig, SudoConfig, SystemConfig, + TechnicalCommitteeMembershipConfig, TokensConfig, VestingConfig, ACA, AUSD, DOT, LDOT, RENBTC, }; let existential_deposit = NativeTokenExistentialDeposit::get(); @@ -578,7 +584,7 @@ fn mandala_genesis( }, evm: EVMConfig { accounts: evm_genesis_accounts, - treasury: root_key, + treasury: root_key.clone(), }, staking_pool: StakingPoolConfig { staking_pool_params: module_staking_pool::Params { @@ -659,5 +665,11 @@ fn mandala_genesis( aura: Default::default(), aura_ext: Default::default(), parachain_system: Default::default(), + + // pint configs + pint_committee: PintCommitteeConfig { + council_members: vec![root_key], + ..Default::default() + }, } } diff --git a/primitives/src/currency.rs b/primitives/src/currency.rs index 68e7112f6..8b47050cf 100644 --- a/primitives/src/currency.rs +++ b/primitives/src/currency.rs @@ -200,6 +200,7 @@ create_currency_id! { // 150: Reserved for CASH // 168 - 255: Kusama parachain tokens BNC("Bifrost Native Token", 12) = 168, + PINT("PINT", 12) = 169, } } diff --git a/runtime/karura/src/lib.rs b/runtime/karura/src/lib.rs index 1edcb66c2..b3ea0164b 100644 --- a/runtime/karura/src/lib.rs +++ b/runtime/karura/src/lib.rs @@ -744,6 +744,7 @@ parameter_type_with_key! { TokenSymbol::LDOT | TokenSymbol::RENBTC | TokenSymbol::KAR | + TokenSymbol::PINT | TokenSymbol::CASH => Balance::max_value() // unsupported }, CurrencyId::DexShare(dex_share_0, _) => { diff --git a/runtime/mandala/Cargo.toml b/runtime/mandala/Cargo.toml index e87523e38..631396e7b 100644 --- a/runtime/mandala/Cargo.toml +++ b/runtime/mandala/Cargo.toml @@ -132,6 +132,13 @@ ecosystem-starport = { path = "../../ecosystem-modules/starport", default-featur ecosystem-compound-cash = { path = "../../ecosystem-modules/compound-cash", default-features = false } chainbridge = { git = "https://github.com/AcalaNetwork/chainbridge-substrate", default-features = false } +pint-asset-index = { path = "../../ecosystem-modules/pint/pallets/asset-index", package = "pallet-asset-index", default-features = false } +pint-committee = { path = "../../ecosystem-modules/pint/pallets/committee", package = "pallet-committee", default-features = false } +pint-local-treasury = { path = "../../ecosystem-modules/pint/pallets/local-treasury", package = "pallet-local-treasury", default-features = false } +pint-price-feed = { path = "../../ecosystem-modules/pint/pallets/price-feed", package = "pallet-price-feed", default-features = false } +pint-saft-registry = { path = "../../ecosystem-modules/pint/pallets/saft-registry", package = "pallet-saft-registry", default-features = false } +pint-primitives = { path = "../../ecosystem-modules/pint/primitives/primitives", package = "primitives", default-features = false } + [build-dependencies] substrate-wasm-builder = { git = "https://github.com/paritytech/substrate", branch = "polkadot-v0.9.9" } @@ -266,6 +273,13 @@ std = [ "ecosystem-starport/std", "ecosystem-compound-cash/std", "chainbridge/std", + + "pint-committee/std", + "pint-saft-registry/std", + "pint-asset-index/std", + "pint-local-treasury/std", + "pint-primitives/std", + "pint-price-feed/std" ] runtime-benchmarks = [ "frame-benchmarking", @@ -288,6 +302,13 @@ runtime-benchmarks = [ "module-homa-lite/runtime-benchmarks", "sp-api/disable-logging", + + "pint-committee/runtime-benchmarks", + "pint-saft-registry/runtime-benchmarks", + "pint-asset-index/runtime-benchmarks", + "pint-local-treasury/runtime-benchmarks", + "pint-price-feed/runtime-benchmarks", + "pint-primitives/runtime-benchmarks" ] # When enabled, the runtime api will not be build. # diff --git a/runtime/mandala/src/lib.rs b/runtime/mandala/src/lib.rs index 953b833b9..c9eb77eaf 100644 --- a/runtime/mandala/src/lib.rs +++ b/runtime/mandala/src/lib.rs @@ -125,6 +125,14 @@ pub use runtime_common::{ /// Import the stable_asset pallet. pub use nutsfinance_stable_asset; +/// Import the PINT pallets +pub use pint_asset_index; +pub use pint_committee; +pub use pint_local_treasury; +pub use pint_price_feed; +pub use pint_primitives; +pub use pint_saft_registry; + mod authority; mod benchmarking; pub mod constants; @@ -177,6 +185,7 @@ parameter_types! { // Ecosystem modules pub const StarportPalletId: PalletId = PalletId(*b"aca/stpt"); pub const StableAssetPalletId: PalletId = PalletId(*b"nuts/sta"); + pub const PintTreasuryPalletId: PalletId = PalletId(*b"pint/trs"); } pub fn get_all_module_accounts() -> Vec { @@ -799,7 +808,9 @@ parameter_type_with_key! { TokenSymbol::LKSM | TokenSymbol::RENBTC | TokenSymbol::ACA | - TokenSymbol::CASH => Balance::max_value() // unsupported + TokenSymbol::CASH => Balance::max_value(), // unsupported + + TokenSymbol::PINT => 1, // TODO: update this before we enable PINT }, CurrencyId::DexShare(dex_share_0, _) => { let currency_id_0: CurrencyId = (*dex_share_0).into(); @@ -1882,6 +1893,139 @@ impl nutsfinance_stable_asset::Config for Runtime { type EnsurePoolAssetId = EnsurePoolAssetId; } +// PINT pallet implementations + +// This is required in order to make `CurrencyId` usable within PINT's runtime-benchmarks +#[cfg(feature = "runtime-benchmarks")] +impl pint_primitives::MaybeAssetIdConvert for Runtime { + fn try_convert(value: u8) -> Option { + use sp_std::convert::TryFrom; + // only use `CurrencyId::Token` + TokenSymbol::try_from(value).ok().map(CurrencyId::Token) + } +} + +// This is currently required to satisfy PINT's chainlink dependency for benchmarks +#[cfg(feature = "runtime-benchmarks")] +struct PriceFeedBenchmarks; +#[cfg(feature = "runtime-benchmarks")] +impl pint_price_feed::traits::PriceFeedBenchmarks for PriceFeedBenchmarks { + fn create_feed(_: AccountId, _: CurrencyId) -> frame_support::dispatch::DispatchResultWithPostInfo { + Ok(().into()) + } +} + +parameter_types! { + pub const MinCouncilVotes: usize = 1; + pub const ProposalSubmissionPeriod: BlockNumber = 10 * MINUTES; + pub const MinimumRedemption: u32 = 0; + pub const WithdrawalPeriod: BlockNumber = 10 * MINUTES; + pub const LockupPeriod: BlockNumber = 5 * MINUTES; + pub const IndexTokenLockIdentifier: LockIdentifier = *b"pint/lck"; + pub const BaseWithdrawalFee: pint_primitives::fee::FeeRate = pint_primitives::fee::FeeRate{ numerator: 3, denominator: 1_000,}; + pub const AssetIndexStringLimit: u32 = 50; + pub const PINTAssetId: CurrencyId = CurrencyId::Token(TokenSymbol::PINT); + pub const MaxActiveDeposits: u32 = 50; + pub const MaxDecimals: u8 = 18; +} + +type PintGovernanceOrigin = frame_system::EnsureOneOf< + AccountId, + pint_committee::EnsureApprovedByCommittee, + frame_system::EnsureRoot, +>; + +impl pint_saft_registry::Config for Runtime { + type AdminOrigin = pint_committee::EnsureApprovedByCommittee; + type AssetRecorder = AssetIndex; + #[cfg(feature = "runtime-benchmarks")] + type AssetRecorderBenchmarks = AssetIndex; + type Balance = Balance; + type AssetId = CurrencyId; + type Event = Event; + type WeightInfo = (); +} + +impl pint_local_treasury::Config for Runtime { + type AdminOrigin = pint_committee::EnsureApprovedByCommittee; + type PalletId = TreasuryPalletId; + type Currency = Balances; + type Event = Event; + type WeightInfo = (); +} + +impl pint_committee::Config for Runtime { + type Origin = Origin; + type Action = Call; + type ProposalNonce = u32; + type ProposalSubmissionPeriod = ProposalSubmissionPeriod; + type VotingPeriod = VotingPeriod; + type MinCouncilVotes = MinCouncilVotes; + type ProposalSubmissionOrigin = pint_committee::EnsureMember; + type ProposalExecutionOrigin = pint_committee::EnsureMember; + type ApprovedByCommitteeOrigin = PintGovernanceOrigin; + type Event = Event; + type WeightInfo = (); +} + +impl pint_asset_index::Config for Runtime { + type AdminOrigin = pint_committee::EnsureApprovedByCommittee; + type IndexToken = Balances; + type Balance = Balance; + type MaxActiveDeposits = MaxActiveDeposits; + type MaxDecimals = MaxDecimals; + type RedemptionFee = (); + type LockupPeriod = LockupPeriod; + type IndexTokenLockIdentifier = IndexTokenLockIdentifier; + type MinimumRedemption = MinimumRedemption; + type WithdrawalPeriod = WithdrawalPeriod; + type RemoteAssetManager = MockRemoteAssetManager; + type AssetId = CurrencyId; + type SelfAssetId = PINTAssetId; + type Currency = Currencies; + type PriceFeed = AggregatedDataProvider; + #[cfg(feature = "runtime-benchmarks")] + type PriceFeedBenchmarks = PriceFeedBenchmarks; + type SaftRegistry = SaftRegistry; + type BaseWithdrawalFee = BaseWithdrawalFee; + type TreasuryPalletId = TreasuryPalletId; + type Event = Event; + type StringLimit = AssetIndexStringLimit; + type WeightInfo = (); +} + +// Wrapper for the `AggregatedDataProvider` until chainlink pallet is supported +impl pint_price_feed::PriceFeed for AggregatedDataProvider { + fn get_price(base: CurrencyId) -> Result { + >::get(&base) + .ok_or_else(|| module_prices::Error::::AccessPriceFailed.into()) + } + fn get_relative_price_pair( + base: CurrencyId, + quote: CurrencyId, + ) -> Result, sp_runtime::DispatchError> { + use frame_support::sp_runtime::traits::CheckedDiv; + let base_price = Self::get_price(base.clone())?; + let quote_price = Self::get_price(quote.clone())?; + let price = base_price + .checked_div("e_price) + .ok_or(module_prices::Error::::AccessPriceFailed)?; + Ok(pint_price_feed::AssetPricePair::new(base, quote, price)) + } +} + +/// Remote Asset manager that does nothing +pub struct MockRemoteAssetManager; +impl pint_primitives::traits::RemoteAssetManager for MockRemoteAssetManager { + fn transfer_asset(_: AccountId, _: CurrencyId, _: Balance) -> DispatchResult { + Ok(()) + } + + fn deposit(_: CurrencyId, _: Balance) {} + + fn announce_withdrawal(_: CurrencyId, _: Balance) {} +} + impl cumulus_pallet_aura_ext::Config for Runtime {} /// The address format for describing accounts. @@ -2038,6 +2182,12 @@ construct_runtime! { // Stable asset StableAsset: nutsfinance_stable_asset::{Pallet, Call, Storage, Event} = 200, + // PINT + AssetIndex: pint_asset_index::{Pallet, Call, Storage, Event} = 210, + PintCommittee: pint_committee::{Pallet, Call, Storage, Origin, Event, Config} = 211, + PintLocalTreasury: pint_local_treasury::{Pallet, Call, Storage, Event} = 212, + SaftRegistry: pint_saft_registry::{Pallet, Call, Storage, Event} = 213, + // Dev Sudo: pallet_sudo::{Pallet, Call, Config, Storage, Event} = 255, }