From d39acc602a25d1cd4d351bf016d43c2d646b2081 Mon Sep 17 00:00:00 2001 From: Dan Shields Date: Wed, 24 Aug 2022 21:40:07 -0600 Subject: [PATCH 1/6] template -> kickback pallet start work on basic parts needed --- Cargo.lock | 30 +++++----- Cargo.toml | 2 +- pallets/{template => kickback}/Cargo.toml | 14 +++-- pallets/{template => kickback}/README.md | 0 .../src/benchmarking.rs | 2 +- pallets/{template => kickback}/src/lib.rs | 56 ++++++++++++++++--- pallets/{template => kickback}/src/mock.rs | 6 +- pallets/{template => kickback}/src/tests.rs | 6 +- runtime/Cargo.toml | 12 ++-- runtime/src/lib.rs | 13 ++--- 10 files changed, 91 insertions(+), 50 deletions(-) rename pallets/{template => kickback}/Cargo.toml (79%) rename pallets/{template => kickback}/README.md (100%) rename pallets/{template => kickback}/src/benchmarking.rs (91%) rename pallets/{template => kickback}/src/lib.rs (64%) rename pallets/{template => kickback}/src/mock.rs (93%) rename pallets/{template => kickback}/src/tests.rs (65%) diff --git a/Cargo.lock b/Cargo.lock index a5ddfdb..88a6e37 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3791,9 +3791,9 @@ dependencies = [ "pallet-aura", "pallet-balances", "pallet-grandpa", + "pallet-kickback", "pallet-randomness-collective-flip", "pallet-sudo", - "pallet-template", "pallet-timestamp", "pallet-transaction-payment", "pallet-transaction-payment-rpc-runtime-api", @@ -4047,6 +4047,20 @@ dependencies = [ "sp-std", ] +[[package]] +name = "pallet-kickback" +version = "4.0.0-dev" +dependencies = [ + "frame-benchmarking", + "frame-support", + "frame-system", + "parity-scale-codec", + "scale-info", + "sp-core", + "sp-io", + "sp-runtime", +] + [[package]] name = "pallet-randomness-collective-flip" version = "4.0.0-dev" @@ -4096,20 +4110,6 @@ dependencies = [ "sp-std", ] -[[package]] -name = "pallet-template" -version = "4.0.0-dev" -dependencies = [ - "frame-benchmarking", - "frame-support", - "frame-system", - "parity-scale-codec", - "scale-info", - "sp-core", - "sp-io", - "sp-runtime", -] - [[package]] name = "pallet-timestamp" version = "4.0.0-dev" diff --git a/Cargo.toml b/Cargo.toml index 538fd8d..8adeda2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,7 @@ [workspace] members = [ "node", - "pallets/template", + "pallets/kickback", "runtime", ] [profile.release] diff --git a/pallets/template/Cargo.toml b/pallets/kickback/Cargo.toml similarity index 79% rename from pallets/template/Cargo.toml rename to pallets/kickback/Cargo.toml index ff7d85b..b3f7a48 100644 --- a/pallets/template/Cargo.toml +++ b/pallets/kickback/Cargo.toml @@ -1,13 +1,15 @@ [package] -name = "pallet-template" +name = "pallet-kickback" version = "4.0.0-dev" -description = "FRAME pallet template for defining custom runtime logic." -authors = ["Substrate DevHub "] -homepage = "https://substrate.io" +description = "substrate skin-in-the-game event management." +keywords = ["kickback", "substrate", "DAO", "Cryptorado"] +authors = ["Cryptorado Community "] +homepage = "https://cryptorado.org" +repository = "https://github.com/Cryptorado-Community/sunshine-reboot/" +license = "GPL-3.0-or-later WITH Classpath-exception-2.0" + edition = "2021" -license = "Unlicense" publish = false -repository = "https://github.com/substrate-developer-hub/substrate-node-template/" [package.metadata.docs.rs] targets = ["x86_64-unknown-linux-gnu"] diff --git a/pallets/template/README.md b/pallets/kickback/README.md similarity index 100% rename from pallets/template/README.md rename to pallets/kickback/README.md diff --git a/pallets/template/src/benchmarking.rs b/pallets/kickback/src/benchmarking.rs similarity index 91% rename from pallets/template/src/benchmarking.rs rename to pallets/kickback/src/benchmarking.rs index d496a9f..8bcf0ba 100644 --- a/pallets/template/src/benchmarking.rs +++ b/pallets/kickback/src/benchmarking.rs @@ -1,4 +1,4 @@ -//! Benchmarking setup for pallet-template +//! Benchmarking setup for pallet-kickback use super::*; diff --git a/pallets/template/src/lib.rs b/pallets/kickback/src/lib.rs similarity index 64% rename from pallets/template/src/lib.rs rename to pallets/kickback/src/lib.rs index f1519ef..4e37bab 100644 --- a/pallets/template/src/lib.rs +++ b/pallets/kickback/src/lib.rs @@ -1,10 +1,17 @@ +//! # Kickback Pallet +//! This pallet implements the [Kickback protocol](https://github.com/wearekickback) for event management via skin-in-the-game incentives. +//! +//! ## Overview +//! +//! To be admitted to enter an event, an event-specific deposit must be reserved from an account. +//! +//! ### Terminology +//! - [`Organizer`] - the account that configures an event. +//! - [`RsvpList`] - a [`BoundedVec`] of those who have reserved funds, that is limited to [`MaxAttendeeCount`] in size. +//! - [`AttendanceOracle`] - the [origin](https://docs.substrate.io/build/origins/) that is solely allowed to determine who did and did not attend and event. +//! #![cfg_attr(not(feature = "std"), no_std)] -/// Edit this file to define custom logic or remove it if it is not needed. -/// Learn more about FRAME and the core library of Substrate FRAME pallets: -/// -pub use pallet::*; - #[cfg(test)] mod mock; @@ -14,10 +21,25 @@ mod tests; #[cfg(feature = "runtime-benchmarks")] mod benchmarking; +use frame_support::pallet_prelude::*; +use frame_system::pallet_prelude::*; + +pub use pallet::*; + +/// The balance type of this pallet. +pub type BalanceOf = + <::Currency as Currency<::AccountId>>::Balance; + +type PositiveImbalanceOf = <::Currency as Currency< + ::AccountId, +>>::PositiveImbalance; +type NegativeImbalanceOf = <::Currency as Currency< + ::AccountId, +>>::NegativeImbalance; + #[frame_support::pallet] pub mod pallet { - use frame_support::pallet_prelude::*; - use frame_system::pallet_prelude::*; + use super::*; #[pallet::pallet] #[pallet::generate_store(pub(super) trait Store)] @@ -26,8 +48,18 @@ pub mod pallet { /// Configure the pallet by specifying the parameters and types on which it depends. #[pallet::config] pub trait Config: frame_system::Config { - /// Because this pallet emits events, it depends on the runtime's definition of an event. + /// The overarching event type. type Event: From> + IsType<::Event>; + + /// The currency used for deposits. + type Currency: ReservableCurrency; + + /// The origin that can determine attendance of those on the RSVP list. + type AttendanceOracle: EnsureOrigin; + + /// The maximum number of attendees per event. + #[pallet::constant] + type MaxAttendeeCount: Get; } // The pallet's runtime storage items. @@ -38,6 +70,14 @@ pub mod pallet { // https://docs.substrate.io/main-docs/build/runtime-storage/#declaring-storage-items pub type Something = StorageValue<_, u32>; + // The pallet's runtime storage items. + // https://docs.substrate.io/main-docs/build/runtime-storage/ + #[pallet::storage] + #[pallet::getter(fn something)] + // Learn more about declaring storage items: + // https://docs.substrate.io/main-docs/build/runtime-storage/#declaring-storage-items + pub type Something = StorageValue<_, u32>; + // Pallets use events to inform users when important changes are made. // https://docs.substrate.io/main-docs/build/events-errors/ #[pallet::event] diff --git a/pallets/template/src/mock.rs b/pallets/kickback/src/mock.rs similarity index 93% rename from pallets/template/src/mock.rs rename to pallets/kickback/src/mock.rs index e03f37b..ca7ca21 100644 --- a/pallets/template/src/mock.rs +++ b/pallets/kickback/src/mock.rs @@ -1,4 +1,4 @@ -use crate as pallet_template; +use crate as pallet_kickback; use frame_support::traits::{ConstU16, ConstU64}; use frame_system as system; use sp_core::H256; @@ -18,7 +18,7 @@ frame_support::construct_runtime!( UncheckedExtrinsic = UncheckedExtrinsic, { System: frame_system, - TemplateModule: pallet_template, + Kickback: pallet_kickback, } ); @@ -49,7 +49,7 @@ impl system::Config for Test { type MaxConsumers = frame_support::traits::ConstU32<16>; } -impl pallet_template::Config for Test { +impl pallet_kickback::Config for Test { type Event = Event; } diff --git a/pallets/template/src/tests.rs b/pallets/kickback/src/tests.rs similarity index 65% rename from pallets/template/src/tests.rs rename to pallets/kickback/src/tests.rs index 2205658..94a05ac 100644 --- a/pallets/template/src/tests.rs +++ b/pallets/kickback/src/tests.rs @@ -5,9 +5,9 @@ use frame_support::{assert_noop, assert_ok}; fn it_works_for_default_value() { new_test_ext().execute_with(|| { // Dispatch a signed extrinsic. - assert_ok!(TemplateModule::do_something(Origin::signed(1), 42)); + assert_ok!(Kickback::do_something(Origin::signed(1), 42)); // Read pallet storage and assert an expected result. - assert_eq!(TemplateModule::something(), Some(42)); + assert_eq!(Kickback::something(), Some(42)); }); } @@ -15,6 +15,6 @@ fn it_works_for_default_value() { fn correct_error_for_none_value() { new_test_ext().execute_with(|| { // Ensure the expected error is thrown when no value is present. - assert_noop!(TemplateModule::cause_error(Origin::signed(1)), Error::::NoneValue); + assert_noop!(Kickback::cause_error(Origin::signed(1)), Error::::NoneValue); }); } diff --git a/runtime/Cargo.toml b/runtime/Cargo.toml index 8a0d110..8eb81ff 100644 --- a/runtime/Cargo.toml +++ b/runtime/Cargo.toml @@ -51,7 +51,7 @@ frame-system-benchmarking = { version = "4.0.0-dev", default-features = false, g hex-literal = { version = "0.3.4", optional = true } # Local Dependencies -pallet-template = { version = "4.0.0-dev", default-features = false, path = "../pallets/template" } +pallet-kickback = { version = "4.0.0-dev", default-features = false, path = "../pallets/kickback" } [build-dependencies] substrate-wasm-builder = { version = "5.0.0-dev", git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.28" } @@ -60,7 +60,6 @@ substrate-wasm-builder = { version = "5.0.0-dev", git = "https://github.com/pari default = ["std"] std = [ "codec/std", - "scale-info/std", "frame-executive/std", "frame-support/std", "frame-system-rpc-runtime-api/std", @@ -68,12 +67,13 @@ std = [ "pallet-aura/std", "pallet-balances/std", "pallet-grandpa/std", + "pallet-kickback/std", "pallet-randomness-collective-flip/std", "pallet-sudo/std", - "pallet-template/std", "pallet-timestamp/std", "pallet-transaction-payment-rpc-runtime-api/std", "pallet-transaction-payment/std", + "scale-info/std", "sp-api/std", "sp-block-builder/std", "sp-consensus-aura/std", @@ -94,20 +94,20 @@ runtime-benchmarks = [ "hex-literal", "pallet-balances/runtime-benchmarks", "pallet-grandpa/runtime-benchmarks", - "pallet-template/runtime-benchmarks", + "pallet-kickback/runtime-benchmarks", "pallet-timestamp/runtime-benchmarks", "sp-runtime/runtime-benchmarks", ] try-runtime = [ "frame-executive/try-runtime", - "frame-try-runtime", "frame-system/try-runtime", + "frame-try-runtime", "pallet-aura/try-runtime", "pallet-balances/try-runtime", "pallet-grandpa/try-runtime", + "pallet-kickback/try-runtime", "pallet-randomness-collective-flip/try-runtime", "pallet-sudo/try-runtime", - "pallet-template/try-runtime", "pallet-timestamp/try-runtime", "pallet-transaction-payment/try-runtime", ] diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index b43fbde..9c37d56 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -43,8 +43,8 @@ use pallet_transaction_payment::CurrencyAdapter; pub use sp_runtime::BuildStorage; pub use sp_runtime::{Perbill, Permill}; -/// Import the template pallet. -pub use pallet_template; +/// Import the local pallets. +pub use pallet_kickback; /// An index to a block. pub type BlockNumber = u32; @@ -265,8 +265,8 @@ impl pallet_sudo::Config for Runtime { type Call = Call; } -/// Configure the pallet-template in pallets/template. -impl pallet_template::Config for Runtime { +/// Configure the kickback pallet. +impl pallet_kickback::Config for Runtime { type Event = Event; } @@ -286,8 +286,7 @@ construct_runtime!( Balances: pallet_balances, TransactionPayment: pallet_transaction_payment, Sudo: pallet_sudo, - // Include the custom logic from the pallet-template in the runtime. - TemplateModule: pallet_template, + Kickback: pallet_kickback, } ); @@ -332,7 +331,7 @@ mod benches { [frame_system, SystemBench::] [pallet_balances, Balances] [pallet_timestamp, Timestamp] - [pallet_template, TemplateModule] + [pallet_kickback, Kickback] ); } From f6b6043d431048241e46c89c25c71b4e1becaca4 Mon Sep 17 00:00:00 2001 From: Dan Shields Date: Thu, 25 Aug 2022 10:45:14 -0600 Subject: [PATCH 2/6] passes check rust-analyzer working --- Cargo.lock | 73 +++++++++++++++++++------------------ pallets/kickback/src/lib.rs | 21 +++++++---- runtime/src/lib.rs | 10 +++++ 3 files changed, 61 insertions(+), 43 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 88a6e37..b36f42a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -191,10 +191,11 @@ dependencies = [ [[package]] name = "async-io" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5e18f61464ae81cde0a23e713ae8fd299580c54d697a35820cfd0625b8b0e07" +checksum = "0ab006897723d9352f63e2b13047177c3982d8d79709d713ce7747a8f19fd1b0" dependencies = [ + "autocfg", "concurrent-queue", "futures-lite", "libc", @@ -219,11 +220,12 @@ dependencies = [ [[package]] name = "async-process" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf2c06e30a24e8c78a3987d07f0930edf76ef35e027e7bdb063fccafdad1f60c" +checksum = "02111fd8655a613c25069ea89fc8d9bb89331fa77486eb3bc059ee757cfa481c" dependencies = [ "async-io", + "autocfg", "blocking", "cfg-if", "event-listener", @@ -569,9 +571,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.10.0" +version = "3.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "37ccbd214614c6783386c1af30caf03192f17891059cecc394b4fb119e363de3" +checksum = "c1ad822118d20d2c234f427000d5acc36eabe1e29a348c89b63dd60b13f28e5d" [[package]] name = "byte-slice-cast" @@ -858,9 +860,9 @@ dependencies = [ [[package]] name = "cpufeatures" -version = "0.2.2" +version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "59a6001667ab124aebae2a495118e11d30984c3a653e99d86d58971708cf5e4b" +checksum = "dc948ebb96241bb40ab73effeb80d9f93afaad49359d159a5e61be51619fe813" dependencies = [ "libc", ] @@ -1334,9 +1336,9 @@ dependencies = [ [[package]] name = "either" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f107b87b6afc2a64fd13cac55fe06d6c8859f12d4b14cbcdd2c67d0976781be" +checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" [[package]] name = "elliptic-curve" @@ -2275,9 +2277,9 @@ dependencies = [ [[package]] name = "iana-time-zone" -version = "0.1.45" +version = "0.1.46" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ef5528d9c2817db4e10cc78f8d4c8228906e5854f389ff6b076cee3572a09d35" +checksum = "ad2bfd338099682614d3ee3fe0cd72e0b6a41ca6a87f6a74a3bd593c91650501" dependencies = [ "android_system_properties", "core-foundation-sys", @@ -4356,9 +4358,9 @@ checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" [[package]] name = "pest" -version = "2.2.1" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69486e2b8c2d2aeb9762db7b4e00b0331156393555cff467f4163ff06821eef8" +checksum = "4b0560d531d1febc25a3c9398a62a71256c0178f2e3443baedd9ad4bb8c9deb4" dependencies = [ "thiserror", "ucd-trie", @@ -4366,9 +4368,9 @@ dependencies = [ [[package]] name = "pest_derive" -version = "2.2.1" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b13570633aff33c6d22ce47dd566b10a3b9122c2fe9d8e7501895905be532b91" +checksum = "905708f7f674518498c1f8d644481440f476d39ca6ecae83319bba7c6c12da91" dependencies = [ "pest", "pest_generator", @@ -4376,9 +4378,9 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.2.1" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3c567e5702efdc79fb18859ea74c3eb36e14c43da7b8c1f098a4ed6514ec7a0" +checksum = "5803d8284a629cc999094ecd630f55e91b561a1d1ba75e233b00ae13b91a69ad" dependencies = [ "pest", "pest_meta", @@ -4389,9 +4391,9 @@ dependencies = [ [[package]] name = "pest_meta" -version = "2.2.1" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5eb32be5ee3bbdafa8c7a18b0a8a8d962b66cfa2ceee4037f49267a50ee821fe" +checksum = "1538eb784f07615c6d9a8ab061089c6c54a344c5b4301db51990ca1c241e8c04" dependencies = [ "once_cell", "pest", @@ -4460,10 +4462,11 @@ checksum = "e8d0eef3571242013a0d5dc84861c3ae4a652e56e12adf8bdc26ff5f8cb34c94" [[package]] name = "polling" -version = "2.2.0" +version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "685404d509889fade3e86fe3a5803bca2ec09b0c0778d5ada6ec8bf7a8de5259" +checksum = "899b00b9c8ab553c743b3e11e87c5c7d423b2a2de229ba95b24a756344748011" dependencies = [ + "autocfg", "cfg-if", "libc", "log", @@ -5072,9 +5075,9 @@ dependencies = [ [[package]] name = "rustix" -version = "0.35.8" +version = "0.35.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d2b64e76b8da597d38473a277e87b91c3747d0cf9922be989e68fc1c046adf9" +checksum = "72c825b8aa8010eb9ee99b75f05e10180b9278d161583034d7574c9d617aeada" dependencies = [ "bitflags", "errno", @@ -5484,7 +5487,7 @@ dependencies = [ "once_cell", "parity-scale-codec", "parity-wasm 0.42.2", - "rustix 0.35.8", + "rustix 0.35.9", "sc-allocator", "sc-executor-common", "sp-runtime-interface", @@ -6143,9 +6146,9 @@ dependencies = [ [[package]] name = "security-framework" -version = "2.6.1" +version = "2.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dc14f172faf8a0194a3aded622712b0de276821addc574fa54fc0a1167e10dc" +checksum = "2bc1bb97804af6631813c55739f771071e0f2ed33ee20b68c86ec505d906356c" dependencies = [ "bitflags", "core-foundation", @@ -6199,18 +6202,18 @@ checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" [[package]] name = "serde" -version = "1.0.143" +version = "1.0.144" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53e8e5d5b70924f74ff5c6d64d9a5acd91422117c60f48c4e07855238a254553" +checksum = "0f747710de3dcd43b88c9168773254e809d8ddbdf9653b84e2554ab219f17860" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.143" +version = "1.0.144" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d3d8e8de557aee63c26b85b947f5e59b690d0454c753f3adeb5cd7835ab88391" +checksum = "94ed3a816fb1d101812f83e789f888322c34e291f894f19590dc310963e87a00" dependencies = [ "proc-macro2", "quote", @@ -6219,9 +6222,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.83" +version = "1.0.85" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "38dd04e3c8279e75b31ef29dbdceebfe5ad89f4d0937213c53f7d49d01b3d5a7" +checksum = "e55a28e3aaef9d5ce0506d0a14dbba8054ddc7e499ef522dd8b26859ec9d4a44" dependencies = [ "itoa 1.0.3", "ryu", @@ -7083,9 +7086,9 @@ checksum = "6e63cff320ae2c57904679ba7cb63280a3dc4613885beafb148ee7bf9aa9042d" [[package]] name = "ss58-registry" -version = "1.25.0" +version = "1.28.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a039906277e0d8db996cd9d1ef19278c10209d994ecfc1025ced16342873a17c" +checksum = "1c8a1e645fa0bd3e81a90e592a677f7ada3182ac338c4a71cd9ec0ba911f6abb" dependencies = [ "Inflector", "num-format", diff --git a/pallets/kickback/src/lib.rs b/pallets/kickback/src/lib.rs index 4e37bab..6b36815 100644 --- a/pallets/kickback/src/lib.rs +++ b/pallets/kickback/src/lib.rs @@ -24,6 +24,19 @@ mod benchmarking; use frame_support::pallet_prelude::*; use frame_system::pallet_prelude::*; +use frame_support::{ + codec::{Decode, Encode, MaxEncodedLen}, + dispatch::{ + DispatchError, DispatchResult, DispatchResultWithPostInfo, Dispatchable, GetDispatchInfo, + PostDispatchInfo, + }, + ensure, + scale_info::TypeInfo, + traits::{ + Currency, ReservableCurrency, EnsureOrigin + } +}; + pub use pallet::*; /// The balance type of this pallet. @@ -70,14 +83,6 @@ pub mod pallet { // https://docs.substrate.io/main-docs/build/runtime-storage/#declaring-storage-items pub type Something = StorageValue<_, u32>; - // The pallet's runtime storage items. - // https://docs.substrate.io/main-docs/build/runtime-storage/ - #[pallet::storage] - #[pallet::getter(fn something)] - // Learn more about declaring storage items: - // https://docs.substrate.io/main-docs/build/runtime-storage/#declaring-storage-items - pub type Something = StorageValue<_, u32>; - // Pallets use events to inform users when important changes are made. // https://docs.substrate.io/main-docs/build/events-errors/ #[pallet::event] diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index 9c37d56..55f5662 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -23,6 +23,8 @@ use sp_std::prelude::*; use sp_version::NativeVersion; use sp_version::RuntimeVersion; +use frame_system::{EnsureRoot, EnsureSigned}; + // A few exports that help ease life for downstream crates. pub use frame_support::{ construct_runtime, parameter_types, @@ -265,9 +267,17 @@ impl pallet_sudo::Config for Runtime { type Call = Call; } +parameter_types! { + pub const MaxAttendeeCount: u32 = 1000; +} + + /// Configure the kickback pallet. impl pallet_kickback::Config for Runtime { type Event = Event; + type Currency = Balances; + type AttendanceOracle = EnsureRoot; + type MaxAttendeeCount = MaxAttendeeCount; } // Create the runtime by composing the FRAME pallets that were previously configured. From f03b2e592d08cb312eb465c1e9243d4b85573775 Mon Sep 17 00:00:00 2001 From: Dan Shields Date: Thu, 25 Aug 2022 10:46:42 -0600 Subject: [PATCH 3/6] fmt --- pallets/kickback/README.md | 1 - pallets/kickback/src/lib.rs | 15 +++++++-------- runtime/src/lib.rs | 1 - 3 files changed, 7 insertions(+), 10 deletions(-) delete mode 100644 pallets/kickback/README.md diff --git a/pallets/kickback/README.md b/pallets/kickback/README.md deleted file mode 100644 index 8d751a4..0000000 --- a/pallets/kickback/README.md +++ /dev/null @@ -1 +0,0 @@ -License: Unlicense \ No newline at end of file diff --git a/pallets/kickback/src/lib.rs b/pallets/kickback/src/lib.rs index 6b36815..65fd237 100644 --- a/pallets/kickback/src/lib.rs +++ b/pallets/kickback/src/lib.rs @@ -3,13 +3,14 @@ //! //! ## Overview //! -//! To be admitted to enter an event, an event-specific deposit must be reserved from an account. -//! +//! To be admitted to enter an event, an event-specific deposit must be reserved from an account. +//! //! ### Terminology //! - [`Organizer`] - the account that configures an event. -//! - [`RsvpList`] - a [`BoundedVec`] of those who have reserved funds, that is limited to [`MaxAttendeeCount`] in size. -//! - [`AttendanceOracle`] - the [origin](https://docs.substrate.io/build/origins/) that is solely allowed to determine who did and did not attend and event. -//! +//! - [`RsvpList`] - a [`BoundedVec`] of those who have reserved funds, that is limited to +//! [`MaxAttendeeCount`] in size. +//! - [`AttendanceOracle`] - the [origin](https://docs.substrate.io/build/origins/) that is solely +//! allowed to determine who did and did not attend and event. #![cfg_attr(not(feature = "std"), no_std)] #[cfg(test)] @@ -32,9 +33,7 @@ use frame_support::{ }, ensure, scale_info::TypeInfo, - traits::{ - Currency, ReservableCurrency, EnsureOrigin - } + traits::{Currency, EnsureOrigin, ReservableCurrency}, }; pub use pallet::*; diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index 55f5662..e4c4e67 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -271,7 +271,6 @@ parameter_types! { pub const MaxAttendeeCount: u32 = 1000; } - /// Configure the kickback pallet. impl pallet_kickback::Config for Runtime { type Event = Event; From e13cc1e144e4b8782f479925fd609630e17af070 Mon Sep 17 00:00:00 2001 From: Dan Shields Date: Thu, 25 Aug 2022 14:45:44 -0600 Subject: [PATCH 4/6] progress NOT building --- Cargo.lock | 1 + pallets/kickback/Cargo.toml | 8 +- pallets/kickback/src/lib.rs | 212 +++++++++++++++++++++++----------- pallets/kickback/src/types.rs | 122 +++++++++++++++++++ runtime/src/lib.rs | 11 +- 5 files changed, 276 insertions(+), 78 deletions(-) create mode 100644 pallets/kickback/src/types.rs diff --git a/Cargo.lock b/Cargo.lock index b36f42a..ff12995 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4061,6 +4061,7 @@ dependencies = [ "sp-core", "sp-io", "sp-runtime", + "sp-std", ] [[package]] diff --git a/pallets/kickback/Cargo.toml b/pallets/kickback/Cargo.toml index b3f7a48..15731a1 100644 --- a/pallets/kickback/Cargo.toml +++ b/pallets/kickback/Cargo.toml @@ -15,13 +15,13 @@ publish = false targets = ["x86_64-unknown-linux-gnu"] [dependencies] -codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = [ - "derive", -] } -scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } +codec = { package = "parity-scale-codec", version = "3.0.0", default-features = false, features = ["derive"] } frame-benchmarking = { version = "4.0.0-dev", default-features = false, optional = true, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.28" } frame-support = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.28" } frame-system = { version = "4.0.0-dev", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.28" } +scale-info = { version = "2.1.1", default-features = false, features = ["derive"] } +sp-std = { version = "4.0.0", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.28" } +sp-runtime = { version = "6.0.0", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.28" } [dev-dependencies] sp-core = { version = "6.0.0", default-features = false, git = "https://github.com/paritytech/substrate.git", branch = "polkadot-v0.9.28" } diff --git a/pallets/kickback/src/lib.rs b/pallets/kickback/src/lib.rs index 65fd237..44cb079 100644 --- a/pallets/kickback/src/lib.rs +++ b/pallets/kickback/src/lib.rs @@ -1,16 +1,30 @@ //! # Kickback Pallet -//! This pallet implements the [Kickback protocol](https://github.com/wearekickback) for event management via skin-in-the-game incentives. +//! +//! This pallet implements the [Kickback protocol](https://github.com/wearekickback) for meeting management via skin-in-the-game incentives. //! //! ## Overview //! -//! To be admitted to enter an event, an event-specific deposit must be reserved from an account. +//! To be admitted to an meeting, an per-meeting deposit must be reserved from an account. //! //! ### Terminology -//! - [`Organizer`] - the account that configures an event. -//! - [`RsvpList`] - a [`BoundedVec`] of those who have reserved funds, that is limited to -//! [`MaxAttendeeCount`] in size. -//! - [`AttendanceOracle`] - the [origin](https://docs.substrate.io/build/origins/) that is solely -//! allowed to determine who did and did not attend and event. +//! - [`MeetingDetails`]: Metadata of a specific meeting. +//! - [`Meetings`]: a [`BoundedVec`] of meeting details that is limited to [`MaxMeetingCount`] in +//! size. +//! - [`DepositorsOf`]: a [`BoundedVec`] of accounts that have deposited for a specific meeting that is +//! limited to [`MaxAttendeeCount`] in size. +//! +//! ## Considerations +//! +//! **Note:** No meeting details are stored on-chain, only the token deposits and incentives are +//! reasoned about in this pallet. +//! +//! All [`MeetingDetails`] include arbitrary meeting details that must be available on an [IPFS](https://ipfs.io) network and have a valid [`Cid`] to access them. +//! This cannot be mutated once established for a meeting to ensure that all attendees have a common +//! view of the meeting's information (time, location, requirements other than a deposit to be +//! admitted, etc.). Most users will want this information to point to a static dApp +//! that is integrated with this pallet and the network it's hosted on to RSVP for a specific +//! meeting. This could also simply be linking to a JSON file that could be consumed in a dApp to +//! interact with this pallet. #![cfg_attr(not(feature = "std"), no_std)] #[cfg(test)] @@ -21,40 +35,26 @@ mod tests; #[cfg(feature = "runtime-benchmarks")] mod benchmarking; +mod types; use frame_support::pallet_prelude::*; use frame_system::pallet_prelude::*; -use frame_support::{ - codec::{Decode, Encode, MaxEncodedLen}, - dispatch::{ - DispatchError, DispatchResult, DispatchResultWithPostInfo, Dispatchable, GetDispatchInfo, - PostDispatchInfo, - }, - ensure, - scale_info::TypeInfo, - traits::{Currency, EnsureOrigin, ReservableCurrency}, -}; +use frame_support::traits::{Currency, ReservableCurrency}; pub use pallet::*; +pub use types::*; /// The balance type of this pallet. pub type BalanceOf = <::Currency as Currency<::AccountId>>::Balance; -type PositiveImbalanceOf = <::Currency as Currency< - ::AccountId, ->>::PositiveImbalance; -type NegativeImbalanceOf = <::Currency as Currency< - ::AccountId, ->>::NegativeImbalance; - #[frame_support::pallet] pub mod pallet { use super::*; #[pallet::pallet] - #[pallet::generate_store(pub(super) trait Store)] + #[pallet::generate_store(pub trait Store)] pub struct Pallet(_); /// Configure the pallet by specifying the parameters and types on which it depends. @@ -63,42 +63,75 @@ pub mod pallet { /// The overarching event type. type Event: From> + IsType<::Event>; + /// Identifier for a specific Meeting. + type MeetingId: Parameter + + Default + + Copy + + MaybeSerializeDeserialize + + MaxEncodedLen + + TypeInfo; + /// The currency used for deposits. type Currency: ReservableCurrency; - /// The origin that can determine attendance of those on the RSVP list. - type AttendanceOracle: EnsureOrigin; + /// The maximum number of meetings. + #[pallet::constant] + type MaxMeetingCount: Get; - /// The maximum number of attendees per event. + /// The maximum number of attendees per meeting. #[pallet::constant] type MaxAttendeeCount: Get; } - // The pallet's runtime storage items. - // https://docs.substrate.io/main-docs/build/runtime-storage/ + // TODO: is this a useful storage item for lookup? Or just use Meetings + // /// The current set of active meetings. + // #[pallet::storage] + // #[pallet::getter(fn active_meetings)] + // pub type ActiveMeetings = + // StorageValue<_, BoundedVec, ValueQuery>; + #[pallet::storage] - #[pallet::getter(fn something)] - // Learn more about declaring storage items: - // https://docs.substrate.io/main-docs/build/runtime-storage/#declaring-storage-items - pub type Something = StorageValue<_, u32>; + #[pallet::getter(fn meetings)] + /// The list of all unsettled meeting details. + pub type Meetings = StorageMap< + _, + Blake2_128Concat, + T::MeetingId, + MeetingDetails, T::AccountId>, + OptionQuery, + >; + + #[pallet::storage] + #[pallet::getter(fn depositors_of)] + /// All accounts that have deposited fund for a specific meeting. + pub type DepositorsOf = StorageMap< + _, + Blake2_128Concat, + T::MeetingId, + BoundedVec, T::MaxAttendeeCount>, + ValueQuery, + >; // Pallets use events to inform users when important changes are made. // https://docs.substrate.io/main-docs/build/events-errors/ #[pallet::event] - #[pallet::generate_deposit(pub(super) fn deposit_event)] + #[pallet::generate_deposit(pub fn deposit_event)] pub enum Event { - /// Event documentation should end with an array that provides descriptive names for event - /// parameters. [something, who] - SomethingStored(u32, T::AccountId), - } + /// A deposit for a meeting has been reserved for and account. [who, meeting] + RsvpDeposit { meeting: T::MeetingId, who: T::AccountId, deposit: BalanceOf }, + } // Errors inform users that something went wrong. #[pallet::error] pub enum Error { - /// Error names should be descriptive. - NoneValue, - /// Errors should have helpful documentation associated with them. - StorageOverflow, + /// The signing account has no permission to do the operation. + NoPermission, + /// The signing account has already RSVPEd for this meeting. + AlreadyRsvped, + /// The meeting has reached capacity. + TooManyRsvped, + /// The given MeetingID is unknown. + Unknown, } // Dispatchable functions allows users to interact with the pallet and invoke state changes. @@ -106,41 +139,88 @@ pub mod pallet { // Dispatchable functions must be annotated with a weight and must return a DispatchResult. #[pallet::call] impl Pallet { - /// An example dispatchable that takes a singles value as a parameter, writes the value to - /// storage and emits an event. This function must be dispatched by a signed extrinsic. + /// Cancel a meeting, refunding all those that RSVPed. Origin of this call must be from the + /// `host`. #[pallet::weight(10_000 + T::DbWeight::get().writes(1))] - pub fn do_something(origin: OriginFor, something: u32) -> DispatchResult { + pub fn create(origin: OriginFor, details: MeetingDetails) -> DispatchResult { // Check that the extrinsic was signed and get the signer. // This function will return an error if the extrinsic is not signed. // https://docs.substrate.io/main-docs/build/origins/ let who = ensure_signed(origin)?; // Update storage. - >::put(something); - // Emit an event. - Self::deposit_event(Event::SomethingStored(something, who)); - // Return a successful DispatchResultWithPostInfo Ok(()) } - /// An example dispatchable that may throw a custom error. - #[pallet::weight(10_000 + T::DbWeight::get().reads_writes(1,1))] - pub fn cause_error(origin: OriginFor) -> DispatchResult { - let _who = ensure_signed(origin)?; - - // Read a value from storage. - match >::get() { - // Return an error if the value has not been set. - None => return Err(Error::::NoneValue.into()), - Some(old) => { - // Increment the value read from storage; will error in the event of overflow. - let new = old.checked_add(1).ok_or(Error::::StorageOverflow)?; - // Update the value in storage with the incremented result. - >::put(new); - Ok(()) - }, + /// Return the deposit (if any) of an asset account. + /// + /// The origin must be Signed. + /// + /// - `id`: The identifier of the asset for the account to be created. + /// - `allow_burn`: If `true` then assets may be destroyed in order to complete the refund. + /// + /// Emits `Refunded` event when successful. + #[pallet::weight(10_000 + T::DbWeight::get().writes(1))] + pub fn refund( + origin: OriginFor, + #[pallet::compact] id: T::MeetingId, + who: T::AccountId, + ) -> DispatchResult { + Ok(()) + } + /// Return the deposit (if any) of an asset account. + /// + /// The origin must be Signed. + /// + /// - `id`: The identifier of the asset for the account to be created. + /// - `allow_burn`: If `true` then assets may be destroyed in order to complete the refund. + /// + /// Emits `Refunded` event when successful. + #[pallet::weight(10_000 + T::DbWeight::get().writes(1))] + pub fn rsvp( + origin: OriginFor, + #[pallet::compact] id: T::MeetingId, + who: T::AccountId, + ) -> DispatchResult { + let who = ensure_signed(origin)?; + + if let Some(meet) = >::get(id) { + let deposit = meet.deposit; + // deposited is a vec of AttendeeDetails + >::try_mutate(&meet, |depositors| ->{ + DispatchResult { + let pos = depositors.binary_search_by_key(&who, |&(a, b)| who).err().ok_or(Error::::AlreadyRsvped)?; + attendees + .try_insert(pos, who.clone()) + .map_err(|_| Error::::TooManyRsvped)?; + Ok(()) + })?; + + Self::deposit_event(Event::RsvpDeposit { meeting: id.into(), who: who.into(), deposit: deposit.into()}); + } } + + Ok(()) + } + /// Cancel a meeting, refunding all those that RSVPed. Origin of this call must be from the + /// `host`. + #[pallet::weight(10_000 + T::DbWeight::get().writes(1))] + pub fn cancel(origin: OriginFor, id: T::MeetingId) -> DispatchResult { + let who = ensure_signed(origin)?; + + // Update storage. + + Ok(()) } } } + +impl Pallet { + + /// Account deposits funds and is added to the Deposited list. + fn do_rsvp(who &T::AccountId, depositors: &BoundedVec, T::MaxAttendeeCount>, deposit: &BalanceOf){ + T::Currency::reserve(&who, deposit)?; + + } +} \ No newline at end of file diff --git a/pallets/kickback/src/types.rs b/pallets/kickback/src/types.rs new file mode 100644 index 0000000..36a255c --- /dev/null +++ b/pallets/kickback/src/types.rs @@ -0,0 +1,122 @@ +// This file is part of Substrate. + +// Copyright (C) 2022 Parity Technologies (UK) Ltd. +// SPDX-License-Identifier: Apache-2.0 + +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use codec::{Decode, Encode, MaxEncodedLen}; +use frame_support::{traits::ConstU32, BoundedVec}; +use scale_info::TypeInfo; +use sp_runtime::RuntimeDebug; +use sp_std::{convert::TryInto, prelude::*}; + +/// The metadata around a meeting instance, requires a [`Cid`]. +#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, MaxEncodedLen, TypeInfo)] +pub struct MeetingDetails { + /// the host account of the event. + pub host: AccountId, + /// The CID of meeting information and metadata. + pub cid: Cid, + /// The deposit required to attend the meeting. + pub deposit: Balance, + /// The maximum number of attendees for this event + pub capacity: Get, +} + +/// The metadata around a meeting instance, requires a [`Cid`]. +#[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, MaxEncodedLen, TypeInfo)] +pub struct AttendeeDetails { + /// the account of the attendee. + pub id: AccountId, + /// Record indicating if the host of a meeting counted attested to this account's attendance. + pub attended: bool, +} + +/// A Multihash instance that only supports the basic functionality and no hashing. +#[derive( + Clone, PartialEq, Eq, PartialOrd, Ord, RuntimeDebug, Encode, Decode, TypeInfo, MaxEncodedLen, +)] +pub struct Multihash { + /// The code of the Multihash. + pub code: u64, + /// The digest. + pub digest: BoundedVec>, // 4 byte dig size + 64 bytes hash digest +} + +impl Multihash { + /// Returns the size of the digest. + pub fn size(&self) -> usize { + self.digest.len() + } +} + +/// The version of the CID. +#[derive( + Clone, + Copy, + PartialEq, + Eq, + PartialOrd, + Ord, + RuntimeDebug, + Encode, + Decode, + TypeInfo, + MaxEncodedLen, +)] +pub enum Version { + /// CID version 0. + V0, + /// CID version 1. + V1, +} + +/// Representation of a CID. +/// +/// The generic is about the allocated size of the multihash. +#[derive( + Clone, PartialEq, Eq, PartialOrd, Ord, RuntimeDebug, Encode, Decode, TypeInfo, MaxEncodedLen, +)] +pub struct Cid { + /// The version of CID. + pub version: Version, + /// The codec of CID. + pub codec: u64, + /// The multihash of CID. + pub hash: Multihash, +} + +// https://docs.filebase.com/storage-networks/ipfs/ipfs-cids +// CIDv0 CIDs are 46 characters long and always start with the characters “Qm”. +// The first few bytes of a CIDv1 CID can be used to interpret the remainder of the CID and provide +// information about how to decode the content once it has been fetched from IPFS. + +impl Cid { + /// Creates a new CIDv0. + pub fn new_v0(sha2_256_digest: impl Into>) -> Self { + /// DAG-PB multicodec code + const DAG_PB: u64 = 0x70; + /// The SHA_256 multicodec code + const SHA2_256: u64 = 0x12; + + let digest = sha2_256_digest.into(); + assert_eq!(digest.len(), 32); + + Self { + version: Version::V0, + codec: DAG_PB, + hash: Multihash { code: SHA2_256, digest: digest.try_into().expect("msg") }, + } + } +} diff --git a/runtime/src/lib.rs b/runtime/src/lib.rs index e4c4e67..3ab9135 100644 --- a/runtime/src/lib.rs +++ b/runtime/src/lib.rs @@ -23,8 +23,6 @@ use sp_std::prelude::*; use sp_version::NativeVersion; use sp_version::RuntimeVersion; -use frame_system::{EnsureRoot, EnsureSigned}; - // A few exports that help ease life for downstream crates. pub use frame_support::{ construct_runtime, parameter_types, @@ -267,16 +265,13 @@ impl pallet_sudo::Config for Runtime { type Call = Call; } -parameter_types! { - pub const MaxAttendeeCount: u32 = 1000; -} - /// Configure the kickback pallet. impl pallet_kickback::Config for Runtime { type Event = Event; type Currency = Balances; - type AttendanceOracle = EnsureRoot; - type MaxAttendeeCount = MaxAttendeeCount; + type MeetingId = u64; + type MaxMeetingCount = ConstU32<100>; + type MaxAttendeeCount = ConstU32<10000>; } // Create the runtime by composing the FRAME pallets that were previously configured. From 81b340ba8aa0a8c80f75c515ac311e09f250a377 Mon Sep 17 00:00:00 2001 From: Dan Shields Date: Fri, 26 Aug 2022 15:08:28 -0600 Subject: [PATCH 5/6] progress, check is working --- pallets/kickback/src/lib.rs | 159 ++++++++++++++++++++-------------- pallets/kickback/src/types.rs | 12 +-- 2 files changed, 102 insertions(+), 69 deletions(-) diff --git a/pallets/kickback/src/lib.rs b/pallets/kickback/src/lib.rs index 44cb079..9c864c5 100644 --- a/pallets/kickback/src/lib.rs +++ b/pallets/kickback/src/lib.rs @@ -10,8 +10,10 @@ //! - [`MeetingDetails`]: Metadata of a specific meeting. //! - [`Meetings`]: a [`BoundedVec`] of meeting details that is limited to [`MaxMeetingCount`] in //! size. -//! - [`DepositorsOf`]: a [`BoundedVec`] of accounts that have deposited for a specific meeting that is -//! limited to [`MaxAttendeeCount`] in size. +//! - [`DepositorsOf`]: a [`BoundedVec`] of accounts that have deposited for a specific meeting that +//! is limited to [`MaxAttendeeCount`] in size. +//! - `Attest`: to attest to a specific attendee being present at an event. +//! - `Settle`: to //! //! ## Considerations //! @@ -19,12 +21,12 @@ //! reasoned about in this pallet. //! //! All [`MeetingDetails`] include arbitrary meeting details that must be available on an [IPFS](https://ipfs.io) network and have a valid [`Cid`] to access them. -//! This cannot be mutated once established for a meeting to ensure that all attendees have a common -//! view of the meeting's information (time, location, requirements other than a deposit to be -//! admitted, etc.). Most users will want this information to point to a static dApp -//! that is integrated with this pallet and the network it's hosted on to RSVP for a specific -//! meeting. This could also simply be linking to a JSON file that could be consumed in a dApp to -//! interact with this pallet. +//! The [`MeetingDetails`] cannot be mutated once established for a meeting to ensure that all +//! attendees have a common view of the meeting's information (deposit, time, location, additional +//! requirements to a deposit to be admitted, etc.). Most users will want this information to point +//! to a static dApp that is integrated with this pallet and the network it's hosted on to RSVP for +//! a specific meeting. This could also simply be linking to a JSON file that could be consumed in a +//! dApp to interact with this pallet. #![cfg_attr(not(feature = "std"), no_std)] #[cfg(test)] @@ -83,32 +85,36 @@ pub mod pallet { type MaxAttendeeCount: Get; } - // TODO: is this a useful storage item for lookup? Or just use Meetings - // /// The current set of active meetings. - // #[pallet::storage] - // #[pallet::getter(fn active_meetings)] - // pub type ActiveMeetings = - // StorageValue<_, BoundedVec, ValueQuery>; - + /// The list of all unsettled meeting details. #[pallet::storage] #[pallet::getter(fn meetings)] - /// The list of all unsettled meeting details. pub type Meetings = StorageMap< _, - Blake2_128Concat, + Twox64Concat, T::MeetingId, MeetingDetails, T::AccountId>, OptionQuery, >; + /// The list of all those RSVPed to a meeting. #[pallet::storage] - #[pallet::getter(fn depositors_of)] - /// All accounts that have deposited fund for a specific meeting. - pub type DepositorsOf = StorageMap< + #[pallet::getter(fn rsvped)] + pub type Rsvped = StorageMap< _, - Blake2_128Concat, + Twox64Concat, T::MeetingId, - BoundedVec, T::MaxAttendeeCount>, + BoundedVec, + ValueQuery, + >; + + /// The list of all host confirmed attendees to a meeting. + #[pallet::storage] + #[pallet::getter(fn attended)] + pub type Attended = StorageMap< + _, + Twox64Concat, + T::MeetingId, + BoundedVec, ValueQuery, >; @@ -118,19 +124,23 @@ pub mod pallet { #[pallet::generate_deposit(pub fn deposit_event)] pub enum Event { /// A deposit for a meeting has been reserved for and account. [who, meeting] - RsvpDeposit { meeting: T::MeetingId, who: T::AccountId, deposit: BalanceOf }, - } + DepositReceived { meeting: T::MeetingId, attendee: T::AccountId, deposit: BalanceOf }, + } // Errors inform users that something went wrong. #[pallet::error] pub enum Error { /// The signing account has no permission to do the operation. NoPermission, + /// The meeting doesn't exist. + MeetingNotFound, + /// The account balance is insufficient for the required deposit. + InsufficientFunds, /// The signing account has already RSVPEd for this meeting. AlreadyRsvped, /// The meeting has reached capacity. - TooManyRsvped, - /// The given MeetingID is unknown. + CapacityReached, + /// The given MeetingId is unknown. Unknown, } @@ -142,7 +152,10 @@ pub mod pallet { /// Cancel a meeting, refunding all those that RSVPed. Origin of this call must be from the /// `host`. #[pallet::weight(10_000 + T::DbWeight::get().writes(1))] - pub fn create(origin: OriginFor, details: MeetingDetails) -> DispatchResult { + pub fn create( + origin: OriginFor, + details: MeetingDetails, T::AccountId>, + ) -> DispatchResult { // Check that the extrinsic was signed and get the signer. // This function will return an error if the extrinsic is not signed. // https://docs.substrate.io/main-docs/build/origins/ @@ -164,45 +177,16 @@ pub mod pallet { #[pallet::weight(10_000 + T::DbWeight::get().writes(1))] pub fn refund( origin: OriginFor, - #[pallet::compact] id: T::MeetingId, - who: T::AccountId, - ) -> DispatchResult { - Ok(()) - } - /// Return the deposit (if any) of an asset account. - /// - /// The origin must be Signed. - /// - /// - `id`: The identifier of the asset for the account to be created. - /// - `allow_burn`: If `true` then assets may be destroyed in order to complete the refund. - /// - /// Emits `Refunded` event when successful. - #[pallet::weight(10_000 + T::DbWeight::get().writes(1))] - pub fn rsvp( - origin: OriginFor, - #[pallet::compact] id: T::MeetingId, + id: T::MeetingId, who: T::AccountId, ) -> DispatchResult { let who = ensure_signed(origin)?; - if let Some(meet) = >::get(id) { - let deposit = meet.deposit; - // deposited is a vec of AttendeeDetails - >::try_mutate(&meet, |depositors| ->{ - DispatchResult { - let pos = depositors.binary_search_by_key(&who, |&(a, b)| who).err().ok_or(Error::::AlreadyRsvped)?; - attendees - .try_insert(pos, who.clone()) - .map_err(|_| Error::::TooManyRsvped)?; - Ok(()) - })?; - - Self::deposit_event(Event::RsvpDeposit { meeting: id.into(), who: who.into(), deposit: deposit.into()}); - } - } + // Update storage. Ok(()) } + /// Cancel a meeting, refunding all those that RSVPed. Origin of this call must be from the /// `host`. #[pallet::weight(10_000 + T::DbWeight::get().writes(1))] @@ -213,14 +197,61 @@ pub mod pallet { Ok(()) } + + /// Return the deposit (if any) of an asset account. + /// + /// The origin must be Signed. + /// + /// - `id`: The identifier of the asset for the account to be created. + /// - `allow_burn`: If `true` then assets may be destroyed in order to complete the refund. + /// + /// Emits `Refunded` event when successful. + #[pallet::weight(10_000 + T::DbWeight::get().writes(1))] + pub fn rsvp(origin: OriginFor, id: T::MeetingId) -> DispatchResult { + let attendee = ensure_signed(origin)?; + let meeting = >::get(id).ok_or(Error::::MeetingNotFound)?; + let deposit = meeting.deposit; + Self::do_rsvp(&id, &attendee, deposit)?; // + Self::deposit_event(Event::DepositReceived { meeting: id, attendee: attendee, deposit: deposit }); + + Ok(()) + } } } impl Pallet { + /// Reserve a specific meeting deposit for an attendee and add them to the RSVP list. + fn do_rsvp(id: &T::MeetingId, attendee: &T::AccountId, deposit: BalanceOf) -> DispatchResult { + // TODO: consider new storage item for list of deposits, something like: + // >::insert(&who, deposit); + >::try_mutate(id, |rsvps| -> DispatchResult { + let pos = rsvps.binary_search(attendee).err().ok_or(Error::::AlreadyRsvped)?; - /// Account deposits funds and is added to the Deposited list. - fn do_rsvp(who &T::AccountId, depositors: &BoundedVec, T::MaxAttendeeCount>, deposit: &BalanceOf){ - T::Currency::reserve(&who, deposit)?; + rsvps + .try_insert(pos, attendee.clone()) + .map_err(|_| Error::::CapacityReached)?; // TODO capacity needs a check that it's less than BoundedVec max MaxAttendeeCount + + T::Currency::reserve(&attendee, deposit) + .map_err(|_| Error::::InsufficientFunds)?; - } -} \ No newline at end of file + Ok(()) + })?; + + Ok(()) + } + + // /// Remove a user from the alliance member set. + // fn remove_member(who: &T::AccountId, role: MemberRole) -> DispatchResult { + // >::try_mutate(role, |members| -> DispatchResult { + // let pos = members.binary_search(who).ok().ok_or(Error::::NotMember)?; + // members.remove(pos); + // Ok(()) + // })?; + + // if matches!(role, MemberRole::Founder | MemberRole::Fellow) { + // let members = Self::votable_members_sorted(); + // T::MembershipChanged::change_members_sorted(&[], &[who.clone()], &members[..]); + // } + // Ok(()) + // } +} diff --git a/pallets/kickback/src/types.rs b/pallets/kickback/src/types.rs index 36a255c..3fc18a7 100644 --- a/pallets/kickback/src/types.rs +++ b/pallets/kickback/src/types.rs @@ -26,19 +26,21 @@ use sp_std::{convert::TryInto, prelude::*}; pub struct MeetingDetails { /// the host account of the event. pub host: AccountId, - /// The CID of meeting information and metadata. + /// The CID of meeting information, dApp interface, and/or and metadata. pub cid: Cid, /// The deposit required to attend the meeting. pub deposit: Balance, /// The maximum number of attendees for this event - pub capacity: Get, + pub capacity: u32, } -/// The metadata around a meeting instance, requires a [`Cid`]. +/// The list of attendees and data related to them. #[derive(Clone, Encode, Decode, Eq, PartialEq, RuntimeDebug, MaxEncodedLen, TypeInfo)] -pub struct AttendeeDetails { - /// the account of the attendee. +pub struct RsvpOf { + /// The account of the attendee. pub id: AccountId, + /// The deposit reserved byt this attendee for a meeting. + pub deposited: Balance, /// Record indicating if the host of a meeting counted attested to this account's attendance. pub attended: bool, } From 6dba1e4a4ab1ed396353fa29e453dad6bc7cf42e Mon Sep 17 00:00:00 2001 From: Dan Shields Date: Fri, 26 Aug 2022 15:27:29 -0600 Subject: [PATCH 6/6] update lock for anyhow error --- Cargo.lock | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ff12995..a552ea9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3380,9 +3380,9 @@ dependencies = [ [[package]] name = "lz4" -version = "1.23.3" +version = "1.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4edcb94251b1c375c459e5abe9fb0168c1c826c3370172684844f8f3f8d1a885" +checksum = "7e9e2dd86df36ce760a60f6ff6ad526f7ba1f14ba0356f8254fb6905e6494df1" dependencies = [ "libc", "lz4-sys", @@ -3390,9 +3390,9 @@ dependencies = [ [[package]] name = "lz4-sys" -version = "1.9.3" +version = "1.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7be8908e2ed6f31c02db8a9fa962f03e36c53fbfde437363eae3306b85d7e17" +checksum = "57d27b317e207b10f69f5e75494119e391a96f48861ae870d1da6edac98ca900" dependencies = [ "cc", "libc", @@ -6425,9 +6425,9 @@ dependencies = [ [[package]] name = "socket2" -version = "0.4.4" +version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "66d72b759436ae32898a2af0a14218dbf55efde3feeb170eb623637db85ee1e0" +checksum = "10c98bba371b9b22a71a9414e420f92ddeb2369239af08200816169d5e2dd7aa" dependencies = [ "libc", "winapi",