diff --git a/Cargo.lock b/Cargo.lock index 5f7d3d526..4ca5919a5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5667,6 +5667,20 @@ dependencies = [ "sp-staking", ] +[[package]] +name = "pallet-native-token-management" +version = "0.1.0" +dependencies = [ + "frame-support", + "frame-system", + "log", + "parity-scale-codec", + "scale-info", + "sidechain-domain", + "sp-io", + "sp-native-token-management", +] + [[package]] name = "pallet-partner-chains-session" version = "1.0.0" @@ -9017,6 +9031,7 @@ dependencies = [ "pallet-balances", "pallet-block-rewards", "pallet-grandpa", + "pallet-native-token-management", "pallet-partner-chains-session", "pallet-session-validator-management", "pallet-session-validator-management-benchmarking", diff --git a/Cargo.toml b/Cargo.toml index 3514a6cf9..7ff455f35 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -32,6 +32,7 @@ members = [ "primitives/session-manager", "primitives/sidechain", "partner-chains-cli", + "pallets/native-token-management", "primitives/native-token-management"] resolver = "2" @@ -188,4 +189,5 @@ authority-selection-inherents = { path = "primitives/authority-selection-inheren session-manager = { path = "primitives/session-manager", default-features = false } sp-sidechain = { path = "primitives/sidechain", default-features = false } chain-params = { path = "primitives/chain-params", default-features = false } +pallet-native-token-management = { path = "pallets/native-token-management", default-features = false } sp-native-token-management = { path = "primitives/native-token-management", default-features = false } diff --git a/devnet/.envrc b/devnet/.envrc index d9886ab96..7be5907d2 100644 --- a/devnet/.envrc +++ b/devnet/.envrc @@ -15,6 +15,11 @@ export COMMITTEE_CANDIDATE_ADDRESS=$(jq -r '.addresses.CommitteeCandidateValidat export D_PARAMETER_POLICY_ID=$(jq -r '.mintingPolicies.DParameterPolicy' devnet/addresses.json) export PERMISSIONED_CANDIDATES_POLICY_ID=$(jq -r '.mintingPolicies.PermissionedCandidatesPolicy' devnet/addresses.json) +# native token observability +export PARTNER_CHAIN_NATIVE_TOKEN_POLICY_ID='ada83ddd029614381f00e28de0922ab0dec6983ea9dd29ae20eef9b4' +export PARTNER_CHAIN_NATIVE_TOKEN_ASSET_NAME='5043546f6b656e44656d6f' +export PARTNER_CHAIN_ILLIQUID_SUPPLY_VALIDATOR_ADDRESS='addr_test1wrhvtvx3f0g9wv9rx8kfqc60jva3e07nqujk2cspekv4mqs9rjdvz' + # Preview parameters export CARDANO_SECURITY_PARAMETER=432 export CARDANO_ACTIVE_SLOTS_COEFF=0.05 diff --git a/node/src/staging.rs b/node/src/staging.rs index f8961dbb0..04fc6d190 100644 --- a/node/src/staging.rs +++ b/node/src/staging.rs @@ -2,10 +2,11 @@ use crate::chain_spec::get_account_id_from_seed; use crate::chain_spec::*; use chain_params::SidechainParams; use sc_service::ChainType; -use sidechain_domain::{MainchainAddressHash, UtxoId}; +use sidechain_domain::*; use sidechain_runtime::{ - AccountId, AuraConfig, BalancesConfig, GrandpaConfig, RuntimeGenesisConfig, - SessionCommitteeManagementConfig, SessionConfig, SidechainConfig, SudoConfig, SystemConfig, + AccountId, AuraConfig, BalancesConfig, GrandpaConfig, NativeTokenManagementConfig, + RuntimeGenesisConfig, SessionCommitteeManagementConfig, SessionConfig, SidechainConfig, + SudoConfig, SystemConfig, }; use sp_core::bytes::from_hex; use sp_core::{ed25519, sr25519}; @@ -164,6 +165,18 @@ pub fn staging_genesis( .collect(), main_chain_scripts: read_mainchain_scripts_from_env()?, }, + native_token_management: NativeTokenManagementConfig { + main_chain_scripts: sp_native_token_management::MainChainScripts { + native_token_policy: from_var::("PARTNER_CHAIN_NATIVE_TOKEN_POLICY_ID")?, + native_token_asset_name: from_var::( + "PARTNER_CHAIN_NATIVE_TOKEN_ASSET_NAME", + )?, + illiquid_supply_address: from_var::( + "PARTNER_CHAIN_ILLIQUID_SUPPLY_VALIDATOR_ADDRESS", + )?, + }, + ..Default::default() + }, }; Ok(serde_json::to_value(config).expect("Genesis config must be serialized correctly")) diff --git a/node/src/template_chain_spec.rs b/node/src/template_chain_spec.rs index 997bf7b67..ae122a45a 100644 --- a/node/src/template_chain_spec.rs +++ b/node/src/template_chain_spec.rs @@ -1,9 +1,9 @@ use crate::chain_spec::*; use chain_params::SidechainParams; use sc_service::ChainType; -use sidechain_domain::{MainchainAddressHash, UtxoId}; +use sidechain_domain::{AssetName, MainchainAddress, MainchainAddressHash, PolicyId, UtxoId}; use sidechain_runtime::{ - AuraConfig, BalancesConfig, GrandpaConfig, RuntimeGenesisConfig, + AuraConfig, BalancesConfig, GrandpaConfig, NativeTokenManagementConfig, RuntimeGenesisConfig, SessionCommitteeManagementConfig, SessionConfig, SidechainConfig, SudoConfig, SystemConfig, }; @@ -44,6 +44,18 @@ pub fn chain_spec() -> Result { initial_authorities: vec![], main_chain_scripts: read_mainchain_scripts_from_env()?, }, + native_token_management: NativeTokenManagementConfig { + main_chain_scripts: sp_native_token_management::MainChainScripts { + native_token_policy: from_var::("PARTNER_CHAIN_NATIVE_TOKEN_POLICY_ID")?, + native_token_asset_name: from_var::( + "PARTNER_CHAIN_NATIVE_TOKEN_ASSET_NAME", + )?, + illiquid_supply_address: from_var::( + "PARTNER_CHAIN_ILLIQUID_SUPPLY_VALIDATOR_ADDRESS", + )?, + }, + ..Default::default() + }, }; let genesis_json = serde_json::to_value(runtime_genesis_config) .expect("Genesis config must be serialized correctly"); diff --git a/node/src/testnet.rs b/node/src/testnet.rs index 35815e127..ce04c1713 100644 --- a/node/src/testnet.rs +++ b/node/src/testnet.rs @@ -1,10 +1,11 @@ use crate::chain_spec::*; use chain_params::SidechainParams; use sc_service::ChainType; -use sidechain_domain::{MainchainAddressHash, UtxoId}; +use sidechain_domain::*; use sidechain_runtime::{ - AccountId, AuraConfig, BalancesConfig, GrandpaConfig, RuntimeGenesisConfig, - SessionCommitteeManagementConfig, SessionConfig, SidechainConfig, SudoConfig, SystemConfig, + AccountId, AuraConfig, BalancesConfig, GrandpaConfig, NativeTokenManagementConfig, + RuntimeGenesisConfig, SessionCommitteeManagementConfig, SessionConfig, SidechainConfig, + SudoConfig, SystemConfig, }; use sidechain_slots::SlotsPerEpoch; use sp_core::bytes::from_hex; @@ -204,6 +205,18 @@ pub fn testnet_genesis( .collect(), main_chain_scripts: read_mainchain_scripts_from_env()?, }, + native_token_management: NativeTokenManagementConfig { + main_chain_scripts: sp_native_token_management::MainChainScripts { + native_token_policy: from_var::("PARTNER_CHAIN_NATIVE_TOKEN_POLICY_ID")?, + native_token_asset_name: from_var::( + "PARTNER_CHAIN_NATIVE_TOKEN_ASSET_NAME", + )?, + illiquid_supply_address: from_var::( + "PARTNER_CHAIN_ILLIQUID_SUPPLY_VALIDATOR_ADDRESS", + )?, + }, + ..Default::default() + }, }; Ok(serde_json::to_value(config).expect("Genesis config must be serialized correctly")) diff --git a/pallets/native-token-management/Cargo.toml b/pallets/native-token-management/Cargo.toml new file mode 100644 index 000000000..744820441 --- /dev/null +++ b/pallets/native-token-management/Cargo.toml @@ -0,0 +1,29 @@ +[package] +name = "pallet-native-token-management" +version = "0.1.0" +edition = "2021" +description = "Pallet responsible for handling changes to the illiquid supply of the native token on main chain." + +[dependencies] +frame-support = { workspace = true } +frame-system = { workspace = true } +log = { workspace = true } +parity-scale-codec = { workspace = true } +scale-info = { workspace = true } +sp-native-token-management = { workspace = true, features = ["serde"] } +sidechain-domain = { workspace = true } + +[dev-dependencies] +sp-io = { workspace = true } + +[features] +default = ["std"] +std = [ + "frame-support/std", + "frame-system/std", + "log/std", + "scale-info/std", + "parity-scale-codec/std", + "scale-info/std", + "sp-native-token-management/std" +] diff --git a/pallets/native-token-management/src/lib.rs b/pallets/native-token-management/src/lib.rs new file mode 100644 index 000000000..85cd3b0af --- /dev/null +++ b/pallets/native-token-management/src/lib.rs @@ -0,0 +1,135 @@ +#![cfg_attr(not(feature = "std"), no_std)] + +use frame_support::inherent::IsFatalError; +use frame_support::pallet_prelude::*; +use frame_system::pallet_prelude::*; +pub use pallet::*; +use sidechain_domain::NativeTokenAmount; +use sp_native_token_management::*; + +#[cfg(test)] +mod tests; + +#[cfg(any(test, feature = "mock"))] +mod mock; + +#[derive(Encode, Debug, PartialEq)] +pub enum InherentError { + TokenTransferNotHandled, + IncorrectTokenNumberTransfered, + UnexpectedTokenTransferInherent, +} + +impl IsFatalError for InherentError { + fn is_fatal_error(&self) -> bool { + true + } +} + +/// Interface for user-provided logic to handle native token transfers into the illiquid supply on the main chain. +/// +/// The handler will be called with **the total sum** of transfers since the previous partner chain block. +pub trait TokenTransferHandler { + fn handle_token_transfer(token_amount: NativeTokenAmount) -> DispatchResult; +} + +#[frame_support::pallet] +pub mod pallet { + use super::*; + + #[pallet::pallet] + pub struct Pallet(_); + + #[pallet::config] + pub trait Config: frame_system::Config { + type RuntimeEvent: From> + IsType<::RuntimeEvent>; + + type TokenTransferHandler: TokenTransferHandler; + } + + #[pallet::event] + pub enum Event { + TokensTransfered(NativeTokenAmount), + } + + #[pallet::storage] + pub type MainChainScripts = + StorageValue<_, sp_native_token_management::MainChainScripts, ValueQuery>; + + #[pallet::genesis_config] + #[derive(frame_support::DefaultNoBound)] + pub struct GenesisConfig { + pub main_chain_scripts: sp_native_token_management::MainChainScripts, + pub _marker: PhantomData, + } + + #[pallet::genesis_build] + impl BuildGenesisConfig for GenesisConfig { + fn build(&self) { + MainChainScripts::::put(self.main_chain_scripts.clone()); + } + } + + #[pallet::inherent] + impl ProvideInherent for Pallet { + type Call = Call; + type Error = InherentError; + const INHERENT_IDENTIFIER: InherentIdentifier = INHERENT_IDENTIFIER; + + fn create_inherent(data: &InherentData) -> Option { + Self::get_transfered_tokens_from_inherent_data(data) + .map(|data| Call::transfer_tokens { token_amount: data.token_amount }) + } + + fn check_inherent(call: &Self::Call, data: &InherentData) -> Result<(), Self::Error> { + let Some(token_transfer) = Self::get_transfered_tokens_from_inherent_data(data) else { + return Err(InherentError::UnexpectedTokenTransferInherent); + }; + let Call::transfer_tokens { token_amount } = call else { + unreachable!("There is no other extrinsic in this pallet"); + }; + if token_transfer.token_amount != *token_amount { + return Err(InherentError::IncorrectTokenNumberTransfered); + } + + Ok(()) + } + + fn is_inherent(call: &Self::Call) -> bool { + matches!(call, Call::transfer_tokens { .. }) + } + + fn is_inherent_required(data: &InherentData) -> Result, Self::Error> { + Ok(Self::get_transfered_tokens_from_inherent_data(data) + .map(|_| InherentError::TokenTransferNotHandled)) + } + } + + impl Pallet { + fn get_transfered_tokens_from_inherent_data( + data: &InherentData, + ) -> Option { + data.get_data::(&INHERENT_IDENTIFIER) + .expect("Token transfer data not correctly encoded") + } + } + + #[pallet::call] + impl Pallet { + #[pallet::call_index(0)] + #[pallet::weight((0, DispatchClass::Mandatory))] + pub fn transfer_tokens( + origin: OriginFor, + token_amount: NativeTokenAmount, + ) -> DispatchResult { + ensure_none(origin)?; + T::TokenTransferHandler::handle_token_transfer(token_amount) + } + } + + impl Pallet { + pub fn get_main_chain_scripts() -> sp_native_token_management::MainChainScripts { + MainChainScripts::::get() + } + } +} diff --git a/pallets/native-token-management/src/mock.rs b/pallets/native-token-management/src/mock.rs new file mode 100644 index 000000000..03d1df71e --- /dev/null +++ b/pallets/native-token-management/src/mock.rs @@ -0,0 +1,92 @@ +use crate::mock::sp_runtime::testing::H256; +use crate::DispatchResult; +use crate::TokenTransferHandler; +use frame_support::sp_runtime::traits::BlakeTwo256; +use frame_support::sp_runtime::traits::IdentityLookup; +use frame_support::sp_runtime::BuildStorage; +use frame_support::traits::ConstU16; +use frame_support::traits::ConstU32; +use frame_support::traits::ConstU64; +use frame_support::*; +use sidechain_domain::*; + +use self::mock_pallet::LastTokenTransfer; + +type AccountId = u64; +type Block = frame_system::mocking::MockBlock; + +#[frame_support::pallet] +pub mod mock_pallet { + use frame_support::pallet_prelude::*; + use sidechain_domain::*; + + #[pallet::pallet] + pub struct Pallet(_); + + #[pallet::config] + pub trait Config: frame_system::Config {} + + #[pallet::storage] + pub type LastTokenTransfer = StorageValue<_, NativeTokenAmount, OptionQuery>; +} + +impl TokenTransferHandler for mock_pallet::Pallet { + fn handle_token_transfer(token_amount: NativeTokenAmount) -> DispatchResult { + LastTokenTransfer::::put(token_amount); + Ok(()) + } +} + +frame_support::construct_runtime!( + pub enum Test { + System: frame_system, + NativeTokenManagement: crate::pallet, + Mock: mock_pallet, + } +); + +impl frame_system::Config for Test { + type BaseCallFilter = frame_support::traits::Everything; + type BlockWeights = (); + type BlockLength = (); + type DbWeight = (); + type RuntimeOrigin = RuntimeOrigin; + type RuntimeCall = RuntimeCall; + type Hash = H256; + type Hashing = BlakeTwo256; + type AccountId = AccountId; + type Lookup = IdentityLookup; + type RuntimeEvent = RuntimeEvent; + type BlockHashCount = ConstU64<250>; + type Version = (); + type PalletInfo = PalletInfo; + type AccountData = (); + type OnNewAccount = (); + type OnKilledAccount = (); + type SystemWeightInfo = (); + type SS58Prefix = ConstU16<42>; + type OnSetCode = (); + type MaxConsumers = ConstU32<16>; + type Nonce = u64; + type Block = Block; + type RuntimeTask = RuntimeTask; + type SingleBlockMigrations = (); + type MultiBlockMigrator = (); + type PreInherents = (); + type PostInherents = (); + type PostTransactions = (); +} + +impl crate::pallet::Config for Test { + type RuntimeEvent = RuntimeEvent; + type TokenTransferHandler = Mock; +} + +impl mock_pallet::Config for Test {} + +pub fn new_test_ext() -> sp_io::TestExternalities { + RuntimeGenesisConfig { system: Default::default(), native_token_management: Default::default() } + .build_storage() + .unwrap() + .into() +} diff --git a/pallets/native-token-management/src/tests.rs b/pallets/native-token-management/src/tests.rs new file mode 100644 index 000000000..ed7df10c3 --- /dev/null +++ b/pallets/native-token-management/src/tests.rs @@ -0,0 +1,135 @@ +use self::mock::{RuntimeOrigin, Test}; + use self::mock::NativeTokenManagement; +use crate::mock::mock_pallet; +use crate::mock::new_test_ext; +use crate::*; +use frame_support::traits::UnfilteredDispatchable; + +mod create_inherent { + use super::*; + + #[test] + fn creates_inherent_from_inherent_data() { + new_test_ext().execute_with(|| { + let inherent_data = test_inherent_data(1001); + + let result = NativeTokenManagement::create_inherent(&inherent_data); + + assert_eq!(result, Some(Call::transfer_tokens { token_amount: 1001.into() })) + }) + } + #[test] + fn skips_inherent_if_no_data() { + new_test_ext().execute_with(|| { + let inherent_data = InherentData::new(); + + let result = NativeTokenManagement::create_inherent(&inherent_data); + + assert_eq!(result, None) + }) + } +} + +mod check_inherent { + use super::*; + + #[test] + fn pass_when_inherent_matches_data() { + new_test_ext().execute_with(|| { + let inherent_data = test_inherent_data(1002); + let inherent = Call::transfer_tokens { token_amount: 1002.into() }; + + let result = NativeTokenManagement::check_inherent(&inherent, &inherent_data); + + assert_eq!(result, Ok(())) + }) + } + #[test] + fn fail_when_token_amount_mismatch() { + new_test_ext().execute_with(|| { + let inherent_data = test_inherent_data(1002); + let inherent = Call::transfer_tokens { token_amount: 9999.into() }; + + let result = NativeTokenManagement::check_inherent(&inherent, &inherent_data); + + assert_eq!(result, Err(InherentError::IncorrectTokenNumberTransfered)) + }) + } + #[test] + fn fail_when_unexpected_inherent() { + new_test_ext().execute_with(|| { + let inherent_data = InherentData::new(); + let inherent = Call::transfer_tokens { token_amount: 1002.into() }; + + let result = NativeTokenManagement::check_inherent(&inherent, &inherent_data); + + assert_eq!(result, Err(InherentError::UnexpectedTokenTransferInherent)); + }) + } +} + +mod is_inherent_required { + use super::*; + + #[test] + fn yes_when_data_present() { + new_test_ext().execute_with(|| { + let inherent_data = test_inherent_data(1001); + let error = NativeTokenManagement::is_inherent_required(&inherent_data) + .expect("Check should successfully run.") + .expect("Check should return an error object."); + + assert_eq!(error, InherentError::TokenTransferNotHandled); + }) + } + + #[test] + fn no_when_data_absent() { + new_test_ext().execute_with(|| { + let inherent_data = InherentData::new(); + let result = NativeTokenManagement::is_inherent_required(&inherent_data) + .expect("Check should successfully run."); + + assert!(result.is_none()); + }) + } +} + +mod inherent { + use super::*; + + #[test] + fn succeeds_and_calls_transfer_handler() { + new_test_ext().execute_with(|| { + let inherent: Call = Call::transfer_tokens { token_amount: 1000.into() }; + + let _ = inherent.dispatch_bypass_filter(RuntimeOrigin::none()).unwrap(); + + assert_eq!(mock_pallet::LastTokenTransfer::::get().unwrap().0, 1000) + }) + } + + #[test] + fn fails_when_not_root() { + new_test_ext().execute_with(|| { + let inherent: Call = Call::transfer_tokens { token_amount: 1000.into() }; + + let result = inherent.dispatch_bypass_filter(RuntimeOrigin::signed(Default::default())); + + assert_eq!(result.unwrap_err().error, DispatchError::BadOrigin); + + assert_eq!(mock_pallet::LastTokenTransfer::::get(), None) + }) + } +} + +fn test_inherent_data(token_amount: u128) -> InherentData { + let mut inherent_data = InherentData::new(); + inherent_data + .put_data( + INHERENT_IDENTIFIER, + &TokenTransferData { token_amount: NativeTokenAmount(token_amount) }, + ) + .unwrap(); + inherent_data +} diff --git a/runtime/Cargo.toml b/runtime/Cargo.toml index 4ca22842a..9b9ed0537 100644 --- a/runtime/Cargo.toml +++ b/runtime/Cargo.toml @@ -70,6 +70,7 @@ sidechain-domain = { workspace = true, features = ["serde"] } chain-params = { workspace = true, features = ["serde"] } sidechain-slots = { workspace = true } session-manager = { workspace = true } +pallet-native-token-management = { workspace = true } sp-native-token-management = { workspace = true, features = ["serde"] } [dev-dependencies] @@ -141,6 +142,7 @@ std = [ "sidechain-domain/std", "sp-inherents/std", "chain-params/std", + "pallet-native-token-management/std", "sp-native-token-management/std" ] diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index 39c7c7fef..eb078c1bf 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -16,6 +16,8 @@ use authority_selection_inherents::filter_invalid_candidates::{ use authority_selection_inherents::select_authorities::select_authorities; use chain_params::SidechainParams; use frame_support::genesis_builder_helper::{build_state, get_preset}; +use frame_support::traits::fungible::Balanced; +use frame_support::traits::tokens::Precision; use frame_support::BoundedVec; pub use frame_support::{ construct_runtime, parameter_types, @@ -30,6 +32,7 @@ pub use frame_support::{ PalletId, StorageValue, }; pub use frame_system::Call as SystemCall; +use hex_literal::hex; use opaque::SessionKeys; pub use pallet_balances::Call as BalancesCall; use pallet_grandpa::AuthorityId as GrandpaId; @@ -38,8 +41,8 @@ pub use pallet_timestamp::Call as TimestampCall; use pallet_transaction_payment::{ConstFeeMultiplier, FungibleAdapter, Multiplier}; use session_manager::ValidatorManagementSessionManager; use sidechain_domain::{ - MainchainPublicKey, PermissionedCandidateData, RegistrationData, ScEpochNumber, ScSlotNumber, - StakeDelegation, + MainchainPublicKey, NativeTokenAmount, PermissionedCandidateData, RegistrationData, + ScEpochNumber, ScSlotNumber, StakeDelegation, }; use sp_api::impl_runtime_apis; use sp_consensus_aura::sr25519::AuthorityId as AuraId; @@ -47,6 +50,7 @@ use sp_core::{crypto::KeyTypeId, OpaqueMetadata}; use sp_partner_chains_session::CurrentSessionIndex; #[cfg(any(feature = "std", test))] pub use sp_runtime::BuildStorage; +use sp_runtime::DispatchResult; use sp_runtime::{ create_runtime_str, generic, impl_opaque_keys, traits::{ @@ -317,6 +321,31 @@ impl frame_system::Config for Runtime { type PostTransactions = (); } +pub struct TokenTransferHandler; + +impl pallet_native_token_management::TokenTransferHandler for TokenTransferHandler { + fn handle_token_transfer(token_amount: NativeTokenAmount) -> DispatchResult { + // Mint the "transfered" tokens into a dummy address. + // This is done for visibility in tests only. + // Despite using the `Balances` pallet to do the transfer here, the account balance + // is stored (and can be observed) in the `System` pallet's storage. + let _ = Balances::deposit( + &AccountId::from(hex!( + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa" + )), + token_amount.0.into(), + Precision::Exact, + )?; + log::info!("💸 Registered transfer of {} native tokens", token_amount.0); + Ok(()) + } +} + +impl pallet_native_token_management::Config for Runtime { + type RuntimeEvent = RuntimeEvent; + type TokenTransferHandler = TokenTransferHandler; +} + impl pallet_aura::Config for Runtime { type AuthorityId = AuraId; type DisabledValidators = (); @@ -484,6 +513,7 @@ construct_runtime!( BlockRewards: pallet_block_rewards, // The order matters!! Session pallet needs to come last for correct initialization order Session: pallet_partner_chains_session, + NativeTokenManagement: pallet_native_token_management, } ); @@ -841,11 +871,7 @@ impl_runtime_apis! { impl sp_native_token_management::NativeTokenManagementApi for Runtime { fn get_main_chain_scripts() -> sp_native_token_management::MainChainScripts { - sp_native_token_management::MainChainScripts { - native_token_policy: Default::default(), - native_token_asset_name: Default::default(), - illiquid_supply_address: Default::default(), - } + NativeTokenManagement::get_main_chain_scripts() } } } diff --git a/staging/.envrc b/staging/.envrc index 92c9d9da5..465fd5b0d 100644 --- a/staging/.envrc +++ b/staging/.envrc @@ -15,6 +15,11 @@ export COMMITTEE_CANDIDATE_ADDRESS=$(jq -r '.addresses.CommitteeCandidateValidat export D_PARAMETER_POLICY_ID=$(jq -r '.mintingPolicies.DParameterPolicy' staging/addresses.json) export PERMISSIONED_CANDIDATES_POLICY_ID=$(jq -r '.mintingPolicies.PermissionedCandidatesPolicy' staging/addresses.json) +# native token observability +export PARTNER_CHAIN_NATIVE_TOKEN_POLICY_ID='ada83ddd029614381f00e28de0922ab0dec6983ea9dd29ae20eef9b4' +export PARTNER_CHAIN_NATIVE_TOKEN_ASSET_NAME='5043546f6b656e44656d6f' +export PARTNER_CHAIN_ILLIQUID_SUPPLY_VALIDATOR_ADDRESS='addr_test1wrhvtvx3f0g9wv9rx8kfqc60jva3e07nqujk2cspekv4mqs9rjdvz' + # Preview parameters export CARDANO_SECURITY_PARAMETER=432 export CARDANO_ACTIVE_SLOTS_COEFF=0.05