mirror of
https://github.com/serai-dex/serai.git
synced 2025-12-08 12:19:24 +00:00
Tokens pallet (#243)
* Use Monero-compatible additional TX keys This still sends a fingerprinting flare up if you send to a subaddress which needs to be fixed. Despite that, Monero no should no longer fail to scan TXs from monero-serai regarding additional keys. Previously it failed becuase we supplied one key as THE key, and n-1 as additional. Monero expects n for additional. This does correctly select when to use THE key versus when to use the additional key when sending. That removes the ability for recipients to fingerprint monero-serai by receiving to a standard address yet needing to use an additional key. * Add tokens_primitives Moves OutInstruction from in-instructions. Turns Destination into OutInstruction. * Correct in-instructions DispatchClass * Add initial tokens pallet * Don't allow pallet addresses to equal identity * Add support for InInstruction::transfer Requires a cargo update due to modifications made to serai-dex/substrate. Successfully mints a token to a SeraiAddress. * Bind InInstructions to an amount * Add a call filter to the runtime Prevents worrying about calls to the assets pallet/generally tightens things up. * Restore Destination It was meged into OutInstruction, yet it didn't make sense for OutInstruction to contain a SeraiAddress. Also deletes the excessively dated Scenarios doc. * Split PublicKey/SeraiAddress Lets us define a custom Display/ToString for SeraiAddress. Also resolves an oddity where PublicKey would be encoded as String, not [u8; 32]. * Test burning tokens/retrieving OutInstructions Modularizes processor_coinUpdates into a shared testing utility. * Misc lint * Don't use PolkadotExtrinsicParams
This commit is contained in:
@@ -41,6 +41,7 @@ pallet-balances = { git = "https://github.com/serai-dex/substrate", default-feat
|
||||
pallet-assets = { git = "https://github.com/serai-dex/substrate", default-features = false }
|
||||
pallet-transaction-payment = { git = "https://github.com/serai-dex/substrate", default-features = false }
|
||||
|
||||
tokens-pallet = { path = "../tokens/pallet", default-features = false }
|
||||
in-instructions-pallet = { path = "../in-instructions/pallet", default-features = false }
|
||||
|
||||
validator-sets-pallet = { path = "../validator-sets/pallet", default-features = false }
|
||||
@@ -78,9 +79,10 @@ std = [
|
||||
"serai-primitives/std",
|
||||
|
||||
"pallet-balances/std",
|
||||
"pallet-assets/std",
|
||||
"pallet-transaction-payment/std",
|
||||
|
||||
"pallet-assets/std",
|
||||
"tokens-pallet/std",
|
||||
"in-instructions-pallet/std",
|
||||
|
||||
"validator-sets-pallet/std",
|
||||
|
||||
@@ -16,6 +16,7 @@ pub use pallet_balances as balances;
|
||||
pub use pallet_transaction_payment as transaction_payment;
|
||||
|
||||
pub use pallet_assets as assets;
|
||||
pub use tokens_pallet as tokens;
|
||||
pub use in_instructions_pallet as in_instructions;
|
||||
|
||||
pub use validator_sets_pallet as validator_sets;
|
||||
@@ -33,15 +34,15 @@ use sp_version::NativeVersion;
|
||||
|
||||
use sp_runtime::{
|
||||
create_runtime_str, generic, impl_opaque_keys, KeyTypeId,
|
||||
traits::{Convert, OpaqueKeys, IdentityLookup, BlakeTwo256, Block as BlockT},
|
||||
traits::{Convert, OpaqueKeys, BlakeTwo256, Block as BlockT},
|
||||
transaction_validity::{TransactionSource, TransactionValidity},
|
||||
ApplyExtrinsicResult, Perbill,
|
||||
};
|
||||
|
||||
use primitives::{PublicKey, Signature, SeraiAddress, Coin};
|
||||
use primitives::{PublicKey, SeraiAddress, AccountLookup, Signature, SubstrateAmount, Coin};
|
||||
|
||||
use support::{
|
||||
traits::{ConstU8, ConstU32, ConstU64},
|
||||
traits::{ConstU8, ConstU32, ConstU64, Contains},
|
||||
weights::{
|
||||
constants::{RocksDbWeight, WEIGHT_REF_TIME_PER_SECOND},
|
||||
IdentityFee, Weight,
|
||||
@@ -56,14 +57,6 @@ use session::PeriodicSessions;
|
||||
/// An index to a block.
|
||||
pub type BlockNumber = u32;
|
||||
|
||||
/// Balance of an account.
|
||||
// Distinct from serai-primitives Amount due to Substrate's requirements on this type.
|
||||
// If Amount could be dropped in here, it would be.
|
||||
// While Amount could have all the necessary traits implemented, not only are they many, yet it'd
|
||||
// make Amount a larger type, providing more operations than desired.
|
||||
// The current type's minimalism sets clear bounds on usage.
|
||||
pub type Balance = u64;
|
||||
|
||||
/// Index of a transaction in the chain, for a given account.
|
||||
pub type Index = u32;
|
||||
|
||||
@@ -104,10 +97,10 @@ pub const VERSION: RuntimeVersion = RuntimeVersion {
|
||||
// 1 MB
|
||||
pub const BLOCK_SIZE: u32 = 1024 * 1024;
|
||||
// 6 seconds
|
||||
pub const TARGET_BLOCK_TIME: u64 = 6000;
|
||||
pub const TARGET_BLOCK_TIME: u64 = 6;
|
||||
|
||||
/// Measured in blocks.
|
||||
pub const MINUTES: BlockNumber = 60_000 / (TARGET_BLOCK_TIME as BlockNumber);
|
||||
pub const MINUTES: BlockNumber = 60 / (TARGET_BLOCK_TIME as BlockNumber);
|
||||
pub const HOURS: BlockNumber = MINUTES * 60;
|
||||
pub const DAYS: BlockNumber = HOURS * 24;
|
||||
|
||||
@@ -134,13 +127,44 @@ parameter_types! {
|
||||
);
|
||||
}
|
||||
|
||||
pub struct CallFilter;
|
||||
impl Contains<RuntimeCall> for CallFilter {
|
||||
fn contains(call: &RuntimeCall) -> bool {
|
||||
if let RuntimeCall::Balances(call) = call {
|
||||
return matches!(call, balances::Call::transfer { .. } | balances::Call::transfer_all { .. });
|
||||
}
|
||||
|
||||
if let RuntimeCall::Assets(call) = call {
|
||||
return matches!(
|
||||
call,
|
||||
assets::Call::approve_transfer { .. } |
|
||||
assets::Call::cancel_approval { .. } |
|
||||
assets::Call::transfer { .. } |
|
||||
assets::Call::transfer_approved { .. }
|
||||
);
|
||||
}
|
||||
if let RuntimeCall::Tokens(call) = call {
|
||||
return matches!(call, tokens::Call::burn { .. });
|
||||
}
|
||||
if let RuntimeCall::InInstructions(call) = call {
|
||||
return matches!(call, in_instructions::Call::update { .. });
|
||||
}
|
||||
|
||||
if let RuntimeCall::ValidatorSets(call) = call {
|
||||
return matches!(call, validator_sets::Call::vote { .. });
|
||||
}
|
||||
|
||||
false
|
||||
}
|
||||
}
|
||||
|
||||
impl system::Config for Runtime {
|
||||
type BaseCallFilter = support::traits::Everything;
|
||||
type BaseCallFilter = CallFilter;
|
||||
type BlockWeights = BlockWeights;
|
||||
type BlockLength = BlockLength;
|
||||
type AccountId = SeraiAddress;
|
||||
type AccountId = PublicKey;
|
||||
type RuntimeCall = RuntimeCall;
|
||||
type Lookup = IdentityLookup<SeraiAddress>;
|
||||
type Lookup = AccountLookup;
|
||||
type Index = Index;
|
||||
type BlockNumber = BlockNumber;
|
||||
type Hash = Hash;
|
||||
@@ -157,7 +181,7 @@ impl system::Config for Runtime {
|
||||
type OnKilledAccount = ();
|
||||
type OnSetCode = ();
|
||||
|
||||
type AccountData = balances::AccountData<Balance>;
|
||||
type AccountData = balances::AccountData<SubstrateAmount>;
|
||||
type SystemWeightInfo = ();
|
||||
type SS58Prefix = SS58Prefix; // TODO: Remove for Bech32m
|
||||
|
||||
@@ -168,7 +192,7 @@ impl balances::Config for Runtime {
|
||||
type MaxLocks = ConstU32<50>;
|
||||
type MaxReserves = ();
|
||||
type ReserveIdentifier = [u8; 8];
|
||||
type Balance = Balance;
|
||||
type Balance = SubstrateAmount;
|
||||
type RuntimeEvent = RuntimeEvent;
|
||||
type DustRemoval = ();
|
||||
type ExistentialDeposit = ConstU64<500>;
|
||||
@@ -176,9 +200,18 @@ impl balances::Config for Runtime {
|
||||
type WeightInfo = balances::weights::SubstrateWeight<Runtime>;
|
||||
}
|
||||
|
||||
impl transaction_payment::Config for Runtime {
|
||||
type RuntimeEvent = RuntimeEvent;
|
||||
type OnChargeTransaction = CurrencyAdapter<Balances, ()>;
|
||||
type OperationalFeeMultiplier = ConstU8<5>;
|
||||
type WeightToFee = IdentityFee<SubstrateAmount>;
|
||||
type LengthToFee = IdentityFee<SubstrateAmount>;
|
||||
type FeeMultiplierUpdate = ();
|
||||
}
|
||||
|
||||
impl assets::Config for Runtime {
|
||||
type RuntimeEvent = RuntimeEvent;
|
||||
type Balance = Balance;
|
||||
type Balance = SubstrateAmount;
|
||||
type Currency = Balances;
|
||||
|
||||
type AssetId = Coin;
|
||||
@@ -186,8 +219,8 @@ impl assets::Config for Runtime {
|
||||
type StringLimit = ConstU32<32>;
|
||||
|
||||
// Don't allow anyone to create assets
|
||||
type CreateOrigin = support::traits::AsEnsureOriginWithArg<system::EnsureNever<SeraiAddress>>;
|
||||
type ForceOrigin = system::EnsureRoot<SeraiAddress>;
|
||||
type CreateOrigin = support::traits::AsEnsureOriginWithArg<system::EnsureNever<PublicKey>>;
|
||||
type ForceOrigin = system::EnsureRoot<PublicKey>;
|
||||
|
||||
// Don't charge fees nor kill accounts
|
||||
type RemoveItemsLimit = ConstU32<0>;
|
||||
@@ -207,13 +240,8 @@ impl assets::Config for Runtime {
|
||||
type BenchmarkHelper = ();
|
||||
}
|
||||
|
||||
impl transaction_payment::Config for Runtime {
|
||||
impl tokens::Config for Runtime {
|
||||
type RuntimeEvent = RuntimeEvent;
|
||||
type OnChargeTransaction = CurrencyAdapter<Balances, ()>;
|
||||
type OperationalFeeMultiplier = ConstU8<5>;
|
||||
type WeightToFee = IdentityFee<Balance>;
|
||||
type LengthToFee = IdentityFee<Balance>;
|
||||
type FeeMultiplierUpdate = ();
|
||||
}
|
||||
|
||||
impl in_instructions::Config for Runtime {
|
||||
@@ -236,7 +264,7 @@ impl validator_sets::Config for Runtime {
|
||||
|
||||
impl session::Config for Runtime {
|
||||
type RuntimeEvent = RuntimeEvent;
|
||||
type ValidatorId = SeraiAddress;
|
||||
type ValidatorId = PublicKey;
|
||||
type ValidatorIdOf = IdentityValidatorIdOf;
|
||||
type ShouldEndSession = Sessions;
|
||||
type NextSessionRotation = Sessions;
|
||||
@@ -283,6 +311,7 @@ construct_runtime!(
|
||||
TransactionPayment: transaction_payment,
|
||||
|
||||
Assets: assets,
|
||||
Tokens: tokens,
|
||||
InInstructions: in_instructions,
|
||||
|
||||
ValidatorSets: validator_sets,
|
||||
@@ -381,31 +410,31 @@ sp_api::impl_runtime_apis! {
|
||||
}
|
||||
|
||||
fn validators() -> Vec<PublicKey> {
|
||||
Session::validators()
|
||||
Session::validators().drain(..).map(Into::into).collect()
|
||||
}
|
||||
}
|
||||
|
||||
impl frame_system_rpc_runtime_api::AccountNonceApi<Block, SeraiAddress, Index> for Runtime {
|
||||
fn account_nonce(account: SeraiAddress) -> Index {
|
||||
impl frame_system_rpc_runtime_api::AccountNonceApi<Block, PublicKey, Index> for Runtime {
|
||||
fn account_nonce(account: PublicKey) -> Index {
|
||||
System::account_nonce(account)
|
||||
}
|
||||
}
|
||||
|
||||
impl pallet_transaction_payment_rpc_runtime_api::TransactionPaymentApi<
|
||||
Block,
|
||||
Balance
|
||||
SubstrateAmount
|
||||
> for Runtime {
|
||||
fn query_info(
|
||||
uxt: <Block as BlockT>::Extrinsic,
|
||||
len: u32,
|
||||
) -> pallet_transaction_payment_rpc_runtime_api::RuntimeDispatchInfo<Balance> {
|
||||
) -> pallet_transaction_payment_rpc_runtime_api::RuntimeDispatchInfo<SubstrateAmount> {
|
||||
TransactionPayment::query_info(uxt, len)
|
||||
}
|
||||
|
||||
fn query_fee_details(
|
||||
uxt: <Block as BlockT>::Extrinsic,
|
||||
len: u32,
|
||||
) -> transaction_payment::FeeDetails<Balance> {
|
||||
) -> transaction_payment::FeeDetails<SubstrateAmount> {
|
||||
TransactionPayment::query_fee_details(uxt, len)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user