profile
viewpoint
Mazdak Farrokhzad Centril @PolymathNetwork Sweden Compiler engineer and former Rust Language and Release team member.

AltSysrq/proptest 677

Hypothesis-like property testing for Rust

Centril/dbg 5

Implementation of https://github.com/rust-lang/rfcs/pull/2173 in stable rust

Centril/firefox-line 4

Rewrite of Mozilla Labs Prospector Oneliner 2 with Addons SDK

Centril/aTetria 2

Initial push of Framework + Model + input processors.

Centril/android-numberpicker 1

A backport of the Android 4.2 NumberPicker

Centril/bin-util 1

small utility scripts, mostly git related.

Centril/consensusbot 1

Next gen rfcbot

Centril/android-project-template 0

template project for android.

Centril/areweasyncyet.rs 0

Are we async yet?

create barnchPolymathNetwork/Polymesh

branch : develop-docs

created branch time in an hour

Pull request review commentPolymathNetwork/Polymesh

MESH-1234: Allow GC to issue & revoke a CDD claim

 decl_module! {             }         } +        /// Assuming this is executed by the GC voting majority, adds a new cdd claim record.+        #[weight = 950_000_000]+        pub fn gc_add_cdd_claim(+            origin,+            target: IdentityId,+            expiry: Option<T::Moment>,+        ) -> DispatchResult {+            T::GCVotingMajorityOrigin::ensure_origin(origin)?;+            Self::base_add_cdd_claim(target, Claim::CustomerDueDiligence([0; 32].into()), GC_DID, expiry)

I've applied your suggestion; thanks for the tip!

Centril

comment created time in 4 hours

PullRequestReviewEvent

push eventPolymathNetwork/Polymesh

Mazdak Farrokhzad

commit sha 5912d624144eecfbf125695146c21faea6305e70

mesh-1234: allow GC to issue CDD claim

view details

push time in 4 hours

PullRequestReviewEvent

create barnchPolymathNetwork/Polymesh

branch : mesh-1234

created branch time in 5 hours

Pull request review commentPolymathNetwork/Polymesh

MESH-1281 (Pips expiry) & MESH-1266 (Test warnings)

 pub struct PolymeshVotes<IdentityId, BlockNumber> {     pub nays: Vec<IdentityId>,     /// The hard end time of this vote.     pub end: BlockNumber,+    /// The time **at** which the proposal is expired.+    pub expiry: Option<BlockNumber>, } +// Fool `decl_storage!` below into not strip the `Option` in the genesis config.+use Option as Maybe;

Converted to enum MaybeBlock { ... }

Centril

comment created time in 6 hours

PullRequestReviewEvent

push eventPolymathNetwork/Polymesh

Mazdak Farrokhzad

commit sha fa72c14acb9bb8a634688b6e3642b0d25f2c63bb

Maybe -> enum MaybeBlock

view details

push time in 6 hours

Pull request review commentPolymathNetwork/Polymesh

MESH-1281 (Pips expiry) & MESH-1266 (Test warnings)

 decl_module! {             let did = Context::current_identity_or::<Identity<T>>(&who)?;              let voting = Self::voting(&proposal).ok_or(Error::<T, I>::NoSuchProposal)?;++            // Ensure proposal hasn't expired. If it has, prune the proposal and bail.+            let now = system::Module::<T>::block_number();+            Self::ensure_not_expired(&proposal, voting.expiry, now)?;+             // POLYMESH-NOTE- Change specific to Polymesh             ensure!(T::MotionDuration::get() > Zero::zero(), Error::<T, I>::NotAllowed);             ensure!(voting.index == index, Error::<T, I>::MismatchedVotingIndex);-            ensure!(system::Module::<T>::block_number() >= voting.end, Error::<T, I>::TooEarly);+            ensure!(now >= voting.end, Error::<T, I>::TooEarly);

Renamed

Centril

comment created time in 8 hours

PullRequestReviewEvent

push eventPolymathNetwork/Polymesh

Mazdak Farrokhzad

commit sha 0fb06bc4c4f3bf197a0f1a727c1070a83d679dd7

committee: TooEarly -> CloseBeforeVoteEnd

view details

push time in 8 hours

push eventPolymathNetwork/Polymesh

Mazdak Farrokhzad

commit sha 4812dff0465931ea016004ca8770cdf77f8f5906

MESH-1255/Staking: Pull in some substrate-rc6 changes (#613) * mesh-1255: copy-in staking/fuzzer * mesh-1255: copy-in staking/reward-curve * mesh-1255: un-copy 'reward-curve' crate * mesh-1255: copy-in staking/src Co-authored-by: Satyam Agrawal <satyam0499@gmail.com>

view details

Mazdak Farrokhzad

commit sha 8500cbb47915c42e7e2dbf7b92cb05b6e575fcf6

mesh-1255/transaction-payment: bring in some rc6 changes (#624) Co-authored-by: poly-auto-merge[bot] <65769705+poly-auto-merge[bot]@users.noreply.github.com>

view details

Mazdak Farrokhzad

commit sha 7b7ae562f269658d866f54aea5124097898e48ba

mesh-1255/balances: pull in substrate rc6 changes (#627) Co-authored-by: Satyam Agrawal <satyam0499@gmail.com>

view details

Vladimir Komendantskiy

commit sha 1d80a3c9391673bc90e27182024e2bf8c1682407

Mesh 1079/permission type (#489) * SigningItem renamed to SigningKey * fn name fix * fmt * signing_item.rs -> signing_key.rs * changed permissions to have a structure of 3 subsets * UT fixes * more UT fixes * schema and UT corrections * UT fixes * corrected initial permissions * undone making Debug std-only * review comments * typo fix and a few more test cases * fix for the fix * fmt and review comment * replaced LinkedKeyInfo with IdentityId in the map of primary keys * secondary key linkage * typo and format fixes * separate maps for storing account and identity key links * identifier name updates * fixed failing identity test * commented out a failing test * renamed account to identity map in JS * removed the identity secondary key mapping * removed the Option type from the key to identity map * removed LinkedKeyInfo schema definition * permissions pallet * ensure_permissions * calling ensure_permissions instead of ensure_signed * rewrote the permissions pallet without origin * calling ensure_call_permissions in every identity extrinsic * defined the call permission check in identity pallet * removed is_signer_authorized_with_permissions and has_permissions * fmt * fixed unit test and added permission check in testnet-v1 * PermissionChecker impl in unit tests * extrinsic check fix * debugging fee_details * minor test fix * removed debug code and corrected auth_id in fee_details test * using get_last_auth_id in multisig tests * applied get_next_auth_id where possible * fixed the frozen secondary keys issue * WIP on tests * implemented empty permissions by default * WIP on multisig tests * cleaned up permission checks in multisig * WIP on balances tests * asset and basic-sto extrinsic permissions * permission checks in pallets * added a utility function for a common permission check usecase * cleanup and using ensure_origin_call_permissions utility function * corrected Permissions after merge * redefined the subset type as a newtype for polkadot js compatibility * API permission types * lint and test fixes * added an API type for SecondaryKey * UT fixes * schema workarounds * generalised iterator parameter types * identity runtime upgrade * runtime upgrade * runtime upgrade fixups * use the trait type parameter name * removed unused variable * TODO about migrate_from * todo * named self * derived Migrate for Identity * migrate from Vec<Permission> to Permissions * review comments * schema update * schema fix * aggregating both primary and secondary identities in permission checks * portfolio permission check template * compute secondary keys during the call permission check * portfolio permissions are checked * test fix * test fix * restricted unknown CLI test errors to types only * fixing submodule removal * readded settlement pallet * removed duplicate module path * removed more duplicate module paths * fixed cargo errors * merge fixes * test import fixes * fixed asset test * batch call metadata WIP * set batched and relayed call metadata * set multisig and forwarded identity call metadata * removed old LinkedKeyInfo field access from CLI tests * updated secondary key creation in CLI tests * cleanup * CLI total permissions fix * fixed CLI test 4_permission_management * fixed settlement CLI tests Co-authored-by: Adam Dossa <adam.dossa@gmail.com> Co-authored-by: Mudit Gupta <guptamudit@ymail.com>

view details

Mudit Gupta

commit sha 2efd6dbc58cdf1411ffaa60aa4ad1b28c8e67acb

Use vector in settlement extrinsics (#629) * use vector in extrinsics * fixed tests Co-authored-by: poly-auto-merge[bot] <65769705+poly-auto-merge[bot]@users.noreply.github.com>

view details

Mudit Gupta

commit sha 97ee18e0527fb53dc84bf5de4671d7b3d377612b

Update polymesh_schema.json

view details

Mazdak Farrokhzad

commit sha dd151534c247cb5d578b6a22af6c3e6e85b2e9bb

pips + committee: prepare storage wrt. expiry

view details

Mazdak Farrokhzad

commit sha e0b258e849bd050a16451ae967aac46df84b5221

drive-by: cleanup warnings in tests

view details

Mazdak Farrokhzad

commit sha ea9e5a6f0bc501027ced3f96a4cf5e50f183e700

pips: implement expiry scheduling

view details

Mazdak Farrokhzad

commit sha b81f53f247eba51f53bff49df6491dd02c6c2034

committee: implement expiry

view details

Mazdak Farrokhzad

commit sha 6cc66c3ce63eec0c734b51bcfd393e7c52fa14c9

cleanup more warnings

view details

push time in 8 hours

Pull request review commentPolymathNetwork/Polymesh

[WIP] MESH-1094/Implement a new PrimaryIssuance pallet which wraps up some of the STO functionality

 decl_module! {             ensure!(<PortfolioAssetBalances<T>>::contains_key(offering_portfolio, offering_asset), Error::<T>::InvalidPortfolio);             let asset_balance = <PortfolioAssetBalances<T>>::get(offering_portfolio, offering_asset); +            ensure!(tiers.len() > 0, Error::<T>::InvalidPriceTiers);+            ensure!(tiers.iter().all(|t| t.total > 0.into()), Error::<T>::InvalidPriceTiers);
            ensure!(
                tiers.len() > 0 && tiers.iter().all(|t| t.total > 0.into()),
                Error::<T>::InvalidPriceTiers
            );
CJP10

comment created time in 9 hours

PullRequestReviewEvent

push eventPolymathNetwork/Polymesh

Mazdak Farrokhzad

commit sha 133e130d4a66f6a06dd88244d17eb9fe03766379

Clarify note re. `Committee::vote_or_propose`. Co-authored-by: Satyam Agrawal <satyam0499@gmail.com>

view details

push time in 3 days

Pull request review commentPolymathNetwork/Polymesh

MESH-1281 (Pips expiry) & MESH-1266 (Test warnings)

 impl<T: Trait<I>, I: Instance> Module<T, I> {     /// Accepts or rejects the proposal if its threshold is satisfied.     fn check_proposal_threshold(proposal: T::Hash) {         if let Some(voting) = Self::voting(&proposal) {+            // Make sure we don't have an expired proposal at this point.+            if let Err(_) = Self::ensure_not_expired(+                &proposal,+                voting.expiry,+                system::Module::<T>::block_number(),+            ) {

Sure, but I don't think that makes anything clearer. Direct pattern matching both highlights the pattern as is more efficient to compile (no inlining necessary on LLVM's part).

Centril

comment created time in 3 days

PullRequestReviewEvent

Pull request review commentPolymathNetwork/Polymesh

[WIP] MESH-1094/Implement a new PrimaryIssuance pallet which wraps up some of the STO functionality

+// Copyright (c) 2020 Polymath++//! # STO Module+//!+//! This is a proof of concept module. It is not meant to be used in the real world in its' current state.++#![cfg_attr(not(feature = "std"), no_std)]+#![recursion_limit = "256"]++use codec::{Decode, Encode};+use frame_support::{+    decl_error, decl_event, decl_module, decl_storage, dispatch::DispatchResult, ensure,+};+use frame_system::ensure_signed;+use pallet_identity as identity;+use pallet_portfolio::{self as portfolio, PortfolioAssetBalances, Trait as PortfolioTrait};+use pallet_settlement::{+    self as settlement, Leg, SettlementType, Trait as SettlementTrait, VenueInfo, VenueType,+};+use pallet_timestamp::{self as timestamp, Trait as TimestampTrait};+use polymesh_common_utilities::{+    constants::currency::*,+    traits::{asset::Trait as AssetTrait, identity::Trait as IdentityTrait, CommonTrait},+    Context,+};+use polymesh_primitives::{IdentityId, PortfolioId, Ticker};+use sp_runtime::traits::{CheckedAdd, CheckedMul, Saturating};+use sp_std::{collections::btree_set::BTreeSet, iter, prelude::*};++type Identity<T> = identity::Module<T>;+type Settlement<T> = settlement::Module<T>;+type Timestamp<T> = timestamp::Module<T>;++/// Details about the Fundraiser+#[cfg_attr(feature = "std", derive(Debug))]+#[derive(Encode, Decode, Default, Clone, PartialEq, Eq, PartialOrd, Ord)]+pub struct Fundraiser<Balance, Moment> {+    /// Portfolio containing the asset being offered+    pub offering_portfolio: PortfolioId,+    /// Asset being offered+    pub offering_asset: Ticker,+    /// Asset to receive payment in+    pub raising_asset: Ticker,+    /// Tiers of the fundraiser.+    /// Each tier has a set amount of tokens available at a fixed price.+    /// The sum of the tiers is the total amount available in this fundraiser.+    pub tiers: Vec<FundraiserTier<Balance>>,+    /// Id of the venue to use for this fundraise+    pub venue_id: u64,+    /// Start of the fundraiser+    pub start: Moment,+    /// End of the fundraiser+    pub end: Option<Moment>,+    /// Fundraiser is frozen+    pub frozen: bool,+}++/// Single tier of a tiered pricing model+#[cfg_attr(feature = "std", derive(Debug))]+#[derive(Encode, Decode, Default, Clone, PartialEq, Eq, PartialOrd, Ord)]+pub struct PriceTier<Balance> {+    amount: Balance,+    price: Balance,+}++/// Single price tier of a `Fundraiser`.+/// Similar to a `PriceTier` but with an extra field `remaining` for tracking the amount available in a tier.+#[cfg_attr(feature = "std", derive(Debug))]+#[derive(Encode, Decode, Default, Clone, PartialEq, Eq, PartialOrd, Ord)]+pub struct FundraiserTier<Balance> {+    inner: PriceTier<Balance>,+    remaining: Balance,+}++impl<Balance: From<u8>> Into<FundraiserTier<Balance>> for PriceTier<Balance> {+    fn into(self) -> FundraiserTier<Balance> {+        FundraiserTier {+            inner: self,+            remaining: Balance::from(0),+        }+    }+}++pub trait Trait:+    frame_system::Trait+    + CommonTrait+    + IdentityTrait+    + SettlementTrait+    + TimestampTrait+    + PortfolioTrait+{+    /// The overarching event type.+    type Event: From<Event<Self>> + Into<<Self as frame_system::Trait>::Event>;+}++decl_event!(+    pub enum Event<T>+    where+        Balance = <T as CommonTrait>::Balance,+        Moment = <T as TimestampTrait>::Moment,+    {+        /// A new fundraiser has been created+        /// (primary issuance agent, fundraiser)+        FundraiserCreated(IdentityId, Fundraiser<Balance, Moment>),+        /// An investor invested in the fundraiser+        /// (offering token, raise token, offering_token_amount, raise_token_amount, fundraiser_id)+        FundsRaised(IdentityId, Ticker, Ticker, Balance, Balance, u64),+    }+);++decl_error! {+    /// Errors for the Settlement module.+    pub enum Error for Module<T: Trait> {+        /// Sender does not have required permissions+        Unauthorized,+        /// An arithmetic operation overflowed+        Overflow,+        /// Not enough tokens left for sale+        InsufficientTokensRemaining,+        /// Fundraiser not found+        FundraiserNotFound,+        /// Fundraiser is frozen+        FundraiserFrozen,+        // Interacting with a fundraiser past the end `Moment`.+        FundraiserExpired,+        // Interacting with a fundraiser before the start `Moment`.+        FundraiserNotStated,+        // Using an invalid venue+        InvalidVenue,+        // Using an invalid portfolio+        InvalidPortfolio,+    }+}++decl_storage! {+    trait Store for Module<T: Trait> as StoCapped {+        /// All fundraisers that are currently running. (ticker, fundraiser_id) -> Fundraiser+        Fundraisers get(fn fundraisers): double_map hasher(blake2_128_concat) Ticker, hasher(twox_64_concat) u64 => Fundraiser<T::Balance, T::Moment>;+        /// Total fundraisers created for a token+        FundraiserCount get(fn fundraiser_count): map hasher(twox_64_concat) Ticker => u64;+    }+}++decl_module! {+    pub struct Module<T: Trait> for enum Call where origin: T::Origin {+        type Error = Error<T>;++        fn deposit_event() = default;++        /// Create a new offering. A fixed amount of pre-minted tokens are put up for sale at the specified tiered rate.+        #[weight = 800_000_000]+        pub fn create_fundraiser(+            origin,+            offering_portfolio: PortfolioId,+            offering_asset: Ticker,+            raising_asset: Ticker,+            tiers: Vec<PriceTier<T::Balance>>,+            venue_id: u64,+            start: Option<T::Moment>,+            end: Option<T::Moment>,+        ) -> DispatchResult {+            let sender = ensure_signed(origin)?;+            let did = Context::current_identity_or::<Identity<T>>(&sender)?;+            ensure!(T::Asset::primary_issuance_agent(&offering_asset) == did, Error::<T>::Unauthorized);++            ensure!(VenueInfo::contains_key(venue_id), Error::<T>::InvalidVenue);+            let venue = VenueInfo::get(venue_id);++            ensure!(venue.creator == did, Error::<T>::InvalidVenue);+            ensure!(venue.venue_type == VenueType::Sto, Error::<T>::InvalidVenue);++            ensure!(offering_portfolio.did == did, Error::<T>::InvalidPortfolio);+            ensure!(<PortfolioAssetBalances<T>>::contains_key(offering_portfolio, offering_asset), Error::<T>::InvalidPortfolio);+            let asset_balance = <PortfolioAssetBalances<T>>::get(offering_portfolio, offering_asset);++            let offering_amount: T::Balance = tiers+                .iter()+                .map(|t| t.amount)+                .fold(0.into(), |x, total| total + x);

Seems like something we can & should implement? Open-coding this fold everytime seems suboptimal.

CJP10

comment created time in 4 days

PullRequestReviewEvent

push eventPolymathNetwork/Polymesh

Mazdak Farrokhzad

commit sha 2c02a3ed85814c5a10203fd7d92ddda25dfcf014

committee: implement expiry

view details

push time in 4 days

PullRequestReviewEvent

create barnchPolymathNetwork/Polymesh

branch : pips-expiry-prep

created branch time in 4 days

Pull request review commentPolymathNetwork/Polymesh

MESH-1277/ Add `add_investor_uniqueness_claim()` dispatchable

 decl_module! {             <RevokeOffChainAuthorization<T>>::insert((signer, auth), true);             Ok(())         }++        /// Add `Claim::InvestorUniqueness` claim for a given target identity.+        ///+        /// # <weight>+        ///  Weight of the this extrinsic is depend on the computation that used to validate+        ///  the proof of claim and that will be constant and not depend on the user inputs.+        /// # </weight>+        ///+        /// # Arguments+        /// * origin - Who provides the claim to the user, In this case user's account id as user provide+        /// this claim to itself.+        /// * target - IdentityId whom claim get assigned.+        /// * claim - `InvestorUniqueness` claim details.+        /// * proof - To validate the self attestation.+        /// * expiry - Expiry of claim.+        ///+        /// # Errors+        /// * `DidMustAlreadyExist` Target should already been a part of the ecosystem.+        /// * `ClaimVariantNotAllowed` When origin trying to pass claim variant other than `InvestorUniqueness`.+        /// * `ConfidentialScopeClaimNotAllowed` When issuer is different from target or CDD_ID is invalid for given user.+        /// * `InvalidScopeClaim1 When proof is invalid.+        #[weight = 7_500_000_000]+        pub fn add_investor_uniqueness_claim(origin, target: IdentityId, claim: Claim, proof: InvestorZKProofData, expiry: Option<T::Moment>) -> DispatchResult {+            // Validate whether the origin is signed or not. Also validate whether the given IdentityId (i.e target) has+            // already been in the system or not.+            let issuer = Self::ensure_signer_and_validate_claim_target(origin, target)?;++            // Validate proof and add claim only when the claim variant is `InvestorUniqueness` only+            // otherwise throw and error.+            match &claim {

If there's no else / _ branch then if let reduces 1 level of indentation and lets you omit the _ => ... arm, which improves readability, so I'd say always go for it.

The case for if let ... else is less clear. I usually try both to see which one rustfmt wants to format more nicely (e.g., will the 1 indent level make a difference in terms of keeping everything on one line?) according to my own subjective taste.

However, there's a good case for match and avoiding _ when its critical that you be notified of more variants by compile errors (often used in rustc to avoid surprises at runtime).

satyamakgec

comment created time in 4 days

PullRequestReviewEvent

Pull request review commentPolymathNetwork/Polymesh

MESH-1277/ Add `add_investor_uniqueness_claim()` dispatchable

 decl_module! {             claim: Claim,             expiry: Option<T::Moment>,         ) -> DispatchResult {-            let sender = ensure_signed(origin)?;-            let issuer = Context::current_identity_or::<Self>(&sender)?;-            ensure!(<DidRecords<T>>::contains_key(target), Error::<T>::DidMustAlreadyExist);+            // Validate whether the origin is signed or not. Also validate whether the given IdentityId (i.e target) has+            // already been in the system or not.

Doesn't particularly add value to repeat the doc comment on every use imo.

satyamakgec

comment created time in 4 days

Pull request review commentPolymathNetwork/Polymesh

MESH-1277/ Add `add_investor_uniqueness_claim()` dispatchable

 impl<T: Trait> Module<T> {             Self::unlink_key_from_did(&signer, did)         }     }++    /// Validate whether the origin is signed or not. Also validate whether the given IdentityId (i.e target) has+    /// already been in the system or not.+    fn ensure_signer_and_validate_claim_target(
    fn ensure_signed_and_validate_claim_target(
satyamakgec

comment created time in 4 days

Pull request review commentPolymathNetwork/Polymesh

MESH-1277/ Add `add_investor_uniqueness_claim()` dispatchable

 impl<T: Trait> Module<T> {             Self::unlink_key_from_did(&signer, did)         }     }++    /// Validate whether the origin is signed or not. Also validate whether the given IdentityId (i.e target) has+    /// already been in the system or not.
    /// Ensure that the origin is signed and that the given `target` is already in the system.
satyamakgec

comment created time in 4 days

Pull request review commentPolymathNetwork/Polymesh

MESH-1277/ Add `add_investor_uniqueness_claim()` dispatchable

 impl Claim { /// Claim type represent the claim without its data. /// /// # TODO-/// - Could we use `std::mem::Discriminat`?+/// - Could we use `std::mem::Discriminant`?

mem::Discriminant is not something you can match on, but PartialEq of two Claims is sufficient, then yes, you can.

satyamakgec

comment created time in 4 days

Pull request review commentPolymathNetwork/Polymesh

MESH-1277/ Add `add_investor_uniqueness_claim()` dispatchable

 pub enum Claim {     Exempted(#[migrate] Scope),     /// User is Blocked     Blocked(#[migrate] Scope),-    /// Confidential Scope claim-    InvestorZKProof(#[migrate] Scope, ScopeId, CddId, InvestorZKProofData),+    /// Confidential claim that will allow an investor to justify that it's identity can be+    /// a potential asset holder of given `scope`.+    ///+    /// This claim is mandatory to have for an investor. It will help issuer to apply compliance rules+    /// on the `ScopeId` instead of investor identityId as ScopeId is unique at investor entity level+    /// for a given scope (always be a Ticker).
    /// All investors must have this claim, which will help the issuer apply compliance rules
    /// on the `ScopeId` instead of the investor's `IdentityId`, as `ScopeId` is unique at the investor entity level
    /// for a given scope (will always be a `Ticker`).
satyamakgec

comment created time in 4 days

Pull request review commentPolymathNetwork/Polymesh

MESH-1277/ Add `add_investor_uniqueness_claim()` dispatchable

 decl_module! {             <RevokeOffChainAuthorization<T>>::insert((signer, auth), true);             Ok(())         }++        /// Add `Claim::InvestorUniqueness` claim for a given target identity.+        ///+        /// # <weight>+        ///  Weight of the this extrinsic is depend on the computation that used to validate+        ///  the proof of claim and that will be constant and not depend on the user inputs.+        /// # </weight>+        ///+        /// # Arguments+        /// * origin - Who provides the claim to the user, In this case user's account id as user provide+        /// this claim to itself.+        /// * target - IdentityId whom claim get assigned.
        /// * target - `IdentityId` to which the claim gets assigned.
satyamakgec

comment created time in 4 days

Pull request review commentPolymathNetwork/Polymesh

MESH-1277/ Add `add_investor_uniqueness_claim()` dispatchable

 decl_module! {             <RevokeOffChainAuthorization<T>>::insert((signer, auth), true);             Ok(())         }++        /// Add `Claim::InvestorUniqueness` claim for a given target identity.+        ///+        /// # <weight>+        ///  Weight of the this extrinsic is depend on the computation that used to validate+        ///  the proof of claim and that will be constant and not depend on the user inputs.+        /// # </weight>+        ///+        /// # Arguments+        /// * origin - Who provides the claim to the user, In this case user's account id as user provide+        /// this claim to itself.+        /// * target - IdentityId whom claim get assigned.+        /// * claim - `InvestorUniqueness` claim details.+        /// * proof - To validate the self attestation.+        /// * expiry - Expiry of claim.+        ///+        /// # Errors+        /// * `DidMustAlreadyExist` Target should already been a part of the ecosystem.+        /// * `ClaimVariantNotAllowed` When origin trying to pass claim variant other than `InvestorUniqueness`.+        /// * `ConfidentialScopeClaimNotAllowed` When issuer is different from target or CDD_ID is invalid for given user.+        /// * `InvalidScopeClaim1 When proof is invalid.
        /// * `InvalidScopeClaim` When proof is invalid.
satyamakgec

comment created time in 4 days

Pull request review commentPolymathNetwork/Polymesh

MESH-1277/ Add `add_investor_uniqueness_claim()` dispatchable

 decl_module! {             <RevokeOffChainAuthorization<T>>::insert((signer, auth), true);             Ok(())         }++        /// Add `Claim::InvestorUniqueness` claim for a given target identity.+        ///+        /// # <weight>+        ///  Weight of the this extrinsic is depend on the computation that used to validate+        ///  the proof of claim and that will be constant and not depend on the user inputs.+        /// # </weight>+        ///+        /// # Arguments+        /// * origin - Who provides the claim to the user, In this case user's account id as user provide
        /// * origin - Who provides the claim to the user? In this case, it's the user's account id as the user provides
satyamakgec

comment created time in 4 days

Pull request review commentPolymathNetwork/Polymesh

MESH-1277/ Add `add_investor_uniqueness_claim()` dispatchable

 decl_module! {             <RevokeOffChainAuthorization<T>>::insert((signer, auth), true);             Ok(())         }++        /// Add `Claim::InvestorUniqueness` claim for a given target identity.+        ///+        /// # <weight>+        ///  Weight of the this extrinsic is depend on the computation that used to validate+        ///  the proof of claim and that will be constant and not depend on the user inputs.
        ///  Weight of the this extrinsic is depend on the computation used to validate
        ///  the proof of claim, which will be a constant independent of user inputs.
satyamakgec

comment created time in 4 days

PullRequestReviewEvent
PullRequestReviewEvent
PullRequestReviewEvent

delete branch PolymathNetwork/Polymesh

delete branch : mesh-1255-balances

delete time in 4 days

Pull request review commentPolymathNetwork/Polymesh

[WIP] MESH-1094/Implement a new PrimaryIssuance pallet which wraps up some of the STO functionality

+// Copyright (c) 2020 Polymath++//! # STO Module+//!+//! This is a proof of concept module. It is not meant to be used in the real world in its' current state.++#![cfg_attr(not(feature = "std"), no_std)]+#![recursion_limit = "256"]++use codec::{Decode, Encode};+use frame_support::{+    decl_error, decl_event, decl_module, decl_storage, dispatch::DispatchResult, ensure,+};+use frame_system::ensure_signed;+use pallet_identity as identity;+use pallet_portfolio::{self as portfolio, PortfolioAssetBalances, Trait as PortfolioTrait};+use pallet_settlement::{+    self as settlement, Leg, SettlementType, Trait as SettlementTrait, VenueInfo, VenueType,+};+use pallet_timestamp::{self as timestamp, Trait as TimestampTrait};+use polymesh_common_utilities::{+    constants::currency::*,+    traits::{asset::Trait as AssetTrait, identity::Trait as IdentityTrait, CommonTrait},+    Context,+};+use polymesh_primitives::{IdentityId, PortfolioId, Ticker};+use sp_runtime::traits::{CheckedAdd, CheckedMul, Saturating};+use sp_std::{collections::btree_set::BTreeSet, iter, prelude::*};++type Identity<T> = identity::Module<T>;+type Settlement<T> = settlement::Module<T>;+type Timestamp<T> = timestamp::Module<T>;++/// Details about the Fundraiser+#[cfg_attr(feature = "std", derive(Debug))]+#[derive(Encode, Decode, Default, Clone, PartialEq, Eq, PartialOrd, Ord)]+pub struct Fundraiser<Balance, Moment> {+    /// Portfolio containing the asset being offered+    pub offering_portfolio: PortfolioId,+    /// Asset being offered+    pub offering_asset: Ticker,+    /// Asset to receive payment in+    pub raising_asset: Ticker,+    /// Tiers of the fundraiser.+    /// Each tier has a set amount of tokens available at a fixed price.+    /// The sum of the tiers is the total amount available in this fundraiser.+    pub tiers: Vec<FundraiserTier<Balance>>,+    /// Id of the venue to use for this fundraise+    pub venue_id: u64,+    /// Start of the fundraiser+    pub start: Moment,+    /// End of the fundraiser+    pub end: Option<Moment>,+    /// Fundraiser is frozen+    pub frozen: bool,+}++/// Single tier of a tiered pricing model+#[cfg_attr(feature = "std", derive(Debug))]+#[derive(Encode, Decode, Default, Clone, PartialEq, Eq, PartialOrd, Ord)]+pub struct PriceTier<Balance> {+    amount: Balance,+    price: Balance,+}++/// Single price tier of a `Fundraiser`.+/// Similar to a `PriceTier` but with an extra field `remaining` for tracking the amount available in a tier.+#[cfg_attr(feature = "std", derive(Debug))]+#[derive(Encode, Decode, Default, Clone, PartialEq, Eq, PartialOrd, Ord)]+pub struct FundraiserTier<Balance> {+    inner: PriceTier<Balance>,+    remaining: Balance,+}++impl<Balance: From<u8>> Into<FundraiserTier<Balance>> for PriceTier<Balance> {+    fn into(self) -> FundraiserTier<Balance> {+        FundraiserTier {+            inner: self,+            remaining: Balance::from(0),+        }+    }+}++pub trait Trait:+    frame_system::Trait+    + CommonTrait+    + IdentityTrait+    + SettlementTrait+    + TimestampTrait+    + PortfolioTrait+{+    /// The overarching event type.+    type Event: From<Event<Self>> + Into<<Self as frame_system::Trait>::Event>;+}++decl_event!(+    pub enum Event<T>+    where+        Balance = <T as CommonTrait>::Balance,+        Moment = <T as TimestampTrait>::Moment,+    {+        /// A new fundraiser has been created+        /// (primary issuance agent, fundraiser)+        FundraiserCreated(IdentityId, Fundraiser<Balance, Moment>),+        /// An investor invested in the fundraiser+        /// (offering token, raise token, offering_token_amount, raise_token_amount, fundraiser_id)+        FundsRaised(IdentityId, Ticker, Ticker, Balance, Balance, u64),+    }+);++decl_error! {+    /// Errors for the Settlement module.+    pub enum Error for Module<T: Trait> {+        /// Sender does not have required permissions+        Unauthorized,+        /// An arithmetic operation overflowed+        Overflow,+        /// Not enough tokens left for sale+        InsufficientTokensRemaining,+        /// Fundraiser not found+        FundraiserNotFound,+        /// Fundraiser is frozen+        FundraiserFrozen,+        // Interacting with a fundraiser past the end `Moment`.+        FundraiserExpired,+        // Interacting with a fundraiser before the start `Moment`.+        FundraiserNotStated,+        // Using an invalid venue+        InvalidVenue,+        // Using an invalid portfolio+        InvalidPortfolio,+    }+}++decl_storage! {+    trait Store for Module<T: Trait> as StoCapped {+        /// All fundraisers that are currently running. (ticker, fundraiser_id) -> Fundraiser+        Fundraisers get(fn fundraisers): double_map hasher(blake2_128_concat) Ticker, hasher(twox_64_concat) u64 => Fundraiser<T::Balance, T::Moment>;+        /// Total fundraisers created for a token+        FundraiserCount get(fn fundraiser_count): map hasher(twox_64_concat) Ticker => u64;+    }+}++decl_module! {+    pub struct Module<T: Trait> for enum Call where origin: T::Origin {+        type Error = Error<T>;++        fn deposit_event() = default;++        /// Create a new offering. A fixed amount of pre-minted tokens are put up for sale at the specified tiered rate.+        #[weight = 800_000_000]+        pub fn create_fundraiser(+            origin,+            offering_portfolio: PortfolioId,+            offering_asset: Ticker,+            raising_asset: Ticker,+            tiers: Vec<PriceTier<T::Balance>>,+            venue_id: u64,+            start: Option<T::Moment>,+            end: Option<T::Moment>,+        ) -> DispatchResult {+            let sender = ensure_signed(origin)?;+            let did = Context::current_identity_or::<Identity<T>>(&sender)?;+            ensure!(T::Asset::primary_issuance_agent(&offering_asset) == did, Error::<T>::Unauthorized);++            ensure!(VenueInfo::contains_key(venue_id), Error::<T>::InvalidVenue);+            let venue = VenueInfo::get(venue_id);++            ensure!(venue.creator == did, Error::<T>::InvalidVenue);+            ensure!(venue.venue_type == VenueType::Sto, Error::<T>::InvalidVenue);++            ensure!(offering_portfolio.did == did, Error::<T>::InvalidPortfolio);+            ensure!(<PortfolioAssetBalances<T>>::contains_key(offering_portfolio, offering_asset), Error::<T>::InvalidPortfolio);+            let asset_balance = <PortfolioAssetBalances<T>>::get(offering_portfolio, offering_asset);++            let offering_amount: T::Balance = tiers+                .iter()+                .map(|t| t.amount)+                .fold(0.into(), |x, total| total + x);++            ensure!(offering_amount >= asset_balance, Error::<T>::InsufficientTokensRemaining);++            // Sort by price+            tiers.sort_by(|a, b| a.price.cmp(&b.price));++            // TODO: Take custodial ownership of $sell_amount of $offering_token from primary issuance agent?+            let fundraiser_id = Self::fundraiser_count(offering_asset) + 1;+            // TODO revise the defaults+            let fundraiser = Fundraiser {+                    offering_portfolio,+                    offering_asset,+                    raising_asset,+                    tiers: tiers.into_iter().map(Into::into).collect(),+                    venue_id,+                    start: start.unwrap_or(Timestamp::<T>::get()),+                    end,+                    frozen: false,+                };+            <FundraiserCount>::insert(offering_asset, fundraiser_id);+            <Fundraisers<T>>::insert(+                offering_asset,+                fundraiser_id,+                fundraiser+            );+            Self::deposit_event(+                RawEvent::FundraiserCreated(did, fundraiser)+            );+            Ok(())+        }++        /// Purchase tokens from an ongoing offering.+        #[weight = 2_000_000_000]+        pub fn invest(origin, portfolio: PortfolioId, offering_asset: Ticker, fundraiser_id: u64, offering_token_amount: T::Balance, max_price: T::Balance) -> DispatchResult {+            let sender = ensure_signed(origin.clone())?;+            let did = Context::current_identity_or::<Identity<T>>(&sender)?;++            ensure!(<Fundraisers<T>>::contains_key(offering_asset, fundraiser_id), Error::<T>::FundraiserNotFound);+            let fundraiser = <Fundraisers<T>>::get(offering_asset, fundraiser_id);

Let's make the map an Option<_> too?

CJP10

comment created time in 5 days

Pull request review commentPolymathNetwork/Polymesh

[WIP] MESH-1094/Implement a new PrimaryIssuance pallet which wraps up some of the STO functionality

+// Copyright (c) 2020 Polymath++//! # STO Module+//!+//! This is a proof of concept module. It is not meant to be used in the real world in its' current state.++#![cfg_attr(not(feature = "std"), no_std)]+#![recursion_limit = "256"]++use codec::{Decode, Encode};+use frame_support::{+    decl_error, decl_event, decl_module, decl_storage, dispatch::DispatchResult, ensure,+};+use frame_system::ensure_signed;+use pallet_identity as identity;+use pallet_portfolio::{self as portfolio, PortfolioAssetBalances, Trait as PortfolioTrait};+use pallet_settlement::{+    self as settlement, Leg, SettlementType, Trait as SettlementTrait, VenueInfo, VenueType,+};+use pallet_timestamp::{self as timestamp, Trait as TimestampTrait};+use polymesh_common_utilities::{+    constants::currency::*,+    traits::{asset::Trait as AssetTrait, identity::Trait as IdentityTrait, CommonTrait},+    Context,+};+use polymesh_primitives::{IdentityId, PortfolioId, Ticker};+use sp_runtime::traits::{CheckedAdd, CheckedMul, Saturating};+use sp_std::{collections::btree_set::BTreeSet, iter, prelude::*};++type Identity<T> = identity::Module<T>;+type Settlement<T> = settlement::Module<T>;+type Timestamp<T> = timestamp::Module<T>;++/// Details about the Fundraiser+#[cfg_attr(feature = "std", derive(Debug))]+#[derive(Encode, Decode, Default, Clone, PartialEq, Eq, PartialOrd, Ord)]+pub struct Fundraiser<Balance, Moment> {+    /// Portfolio containing the asset being offered+    pub offering_portfolio: PortfolioId,+    /// Asset being offered+    pub offering_asset: Ticker,+    /// Asset to receive payment in+    pub raising_asset: Ticker,+    /// Tiers of the fundraiser.+    /// Each tier has a set amount of tokens available at a fixed price.+    /// The sum of the tiers is the total amount available in this fundraiser.+    pub tiers: Vec<FundraiserTier<Balance>>,+    /// Id of the venue to use for this fundraise+    pub venue_id: u64,+    /// Start of the fundraiser+    pub start: Moment,+    /// End of the fundraiser+    pub end: Option<Moment>,+    /// Fundraiser is frozen+    pub frozen: bool,+}++/// Single tier of a tiered pricing model+#[cfg_attr(feature = "std", derive(Debug))]+#[derive(Encode, Decode, Default, Clone, PartialEq, Eq, PartialOrd, Ord)]+pub struct PriceTier<Balance> {+    amount: Balance,+    price: Balance,+}++/// Single price tier of a `Fundraiser`.+/// Similar to a `PriceTier` but with an extra field `remaining` for tracking the amount available in a tier.+#[cfg_attr(feature = "std", derive(Debug))]+#[derive(Encode, Decode, Default, Clone, PartialEq, Eq, PartialOrd, Ord)]+pub struct FundraiserTier<Balance> {+    inner: PriceTier<Balance>,+    remaining: Balance,+}++impl<Balance: From<u8>> Into<FundraiserTier<Balance>> for PriceTier<Balance> {+    fn into(self) -> FundraiserTier<Balance> {+        FundraiserTier {+            inner: self,+            remaining: Balance::from(0),+        }+    }+}++pub trait Trait:+    frame_system::Trait+    + CommonTrait+    + IdentityTrait+    + SettlementTrait+    + TimestampTrait+    + PortfolioTrait+{+    /// The overarching event type.+    type Event: From<Event<Self>> + Into<<Self as frame_system::Trait>::Event>;+}++decl_event!(+    pub enum Event<T>+    where+        Balance = <T as CommonTrait>::Balance,+        Moment = <T as TimestampTrait>::Moment,+    {+        /// A new fundraiser has been created+        /// (primary issuance agent, fundraiser)+        FundraiserCreated(IdentityId, Fundraiser<Balance, Moment>),+        /// An investor invested in the fundraiser+        /// (offering token, raise token, offering_token_amount, raise_token_amount, fundraiser_id)+        FundsRaised(IdentityId, Ticker, Ticker, Balance, Balance, u64),+    }+);++decl_error! {+    /// Errors for the Settlement module.+    pub enum Error for Module<T: Trait> {+        /// Sender does not have required permissions+        Unauthorized,+        /// An arithmetic operation overflowed+        Overflow,+        /// Not enough tokens left for sale+        InsufficientTokensRemaining,+        /// Fundraiser not found+        FundraiserNotFound,+        /// Fundraiser is frozen+        FundraiserFrozen,+        // Interacting with a fundraiser past the end `Moment`.+        FundraiserExpired,+        // Interacting with a fundraiser before the start `Moment`.+        FundraiserNotStated,+        // Using an invalid venue+        InvalidVenue,+        // Using an invalid portfolio+        InvalidPortfolio,+    }+}++decl_storage! {+    trait Store for Module<T: Trait> as StoCapped {+        /// All fundraisers that are currently running. (ticker, fundraiser_id) -> Fundraiser+        Fundraisers get(fn fundraisers): double_map hasher(blake2_128_concat) Ticker, hasher(twox_64_concat) u64 => Fundraiser<T::Balance, T::Moment>;+        /// Total fundraisers created for a token+        FundraiserCount get(fn fundraiser_count): map hasher(twox_64_concat) Ticker => u64;+    }+}++decl_module! {+    pub struct Module<T: Trait> for enum Call where origin: T::Origin {+        type Error = Error<T>;++        fn deposit_event() = default;++        /// Create a new offering. A fixed amount of pre-minted tokens are put up for sale at the specified tiered rate.+        #[weight = 800_000_000]+        pub fn create_fundraiser(+            origin,+            offering_portfolio: PortfolioId,+            offering_asset: Ticker,+            raising_asset: Ticker,+            tiers: Vec<PriceTier<T::Balance>>,+            venue_id: u64,+            start: Option<T::Moment>,+            end: Option<T::Moment>,+        ) -> DispatchResult {+            let sender = ensure_signed(origin)?;+            let did = Context::current_identity_or::<Identity<T>>(&sender)?;+            ensure!(T::Asset::primary_issuance_agent(&offering_asset) == did, Error::<T>::Unauthorized);++            ensure!(VenueInfo::contains_key(venue_id), Error::<T>::InvalidVenue);+            let venue = VenueInfo::get(venue_id);++            ensure!(venue.creator == did, Error::<T>::InvalidVenue);+            ensure!(venue.venue_type == VenueType::Sto, Error::<T>::InvalidVenue);++            ensure!(offering_portfolio.did == did, Error::<T>::InvalidPortfolio);+            ensure!(<PortfolioAssetBalances<T>>::contains_key(offering_portfolio, offering_asset), Error::<T>::InvalidPortfolio);+            let asset_balance = <PortfolioAssetBalances<T>>::get(offering_portfolio, offering_asset);++            let offering_amount: T::Balance = tiers+                .iter()+                .map(|t| t.amount)+                .fold(0.into(), |x, total| total + x);++            ensure!(offering_amount >= asset_balance, Error::<T>::InsufficientTokensRemaining);++            // Sort by price+            tiers.sort_by(|a, b| a.price.cmp(&b.price));++            // TODO: Take custodial ownership of $sell_amount of $offering_token from primary issuance agent?+            let fundraiser_id = Self::fundraiser_count(offering_asset) + 1;+            // TODO revise the defaults+            let fundraiser = Fundraiser {+                    offering_portfolio,+                    offering_asset,+                    raising_asset,+                    tiers: tiers.into_iter().map(Into::into).collect(),+                    venue_id,+                    start: start.unwrap_or(Timestamp::<T>::get()),+                    end,+                    frozen: false,+                };+            <FundraiserCount>::insert(offering_asset, fundraiser_id);+            <Fundraisers<T>>::insert(+                offering_asset,+                fundraiser_id,+                fundraiser+            );+            Self::deposit_event(+                RawEvent::FundraiserCreated(did, fundraiser)+            );+            Ok(())+        }++        /// Purchase tokens from an ongoing offering.

Let's elaborate here too?

CJP10

comment created time in 5 days

Pull request review commentPolymathNetwork/Polymesh

[WIP] MESH-1094/Implement a new PrimaryIssuance pallet which wraps up some of the STO functionality

+// Copyright (c) 2020 Polymath++//! # STO Module+//!+//! This is a proof of concept module. It is not meant to be used in the real world in its' current state.++#![cfg_attr(not(feature = "std"), no_std)]+#![recursion_limit = "256"]++use codec::{Decode, Encode};+use frame_support::{+    decl_error, decl_event, decl_module, decl_storage, dispatch::DispatchResult, ensure,+};+use frame_system::ensure_signed;+use pallet_identity as identity;+use pallet_portfolio::{self as portfolio, PortfolioAssetBalances, Trait as PortfolioTrait};+use pallet_settlement::{+    self as settlement, Leg, SettlementType, Trait as SettlementTrait, VenueInfo, VenueType,+};+use pallet_timestamp::{self as timestamp, Trait as TimestampTrait};+use polymesh_common_utilities::{+    constants::currency::*,+    traits::{asset::Trait as AssetTrait, identity::Trait as IdentityTrait, CommonTrait},+    Context,+};+use polymesh_primitives::{IdentityId, PortfolioId, Ticker};+use sp_runtime::traits::{CheckedAdd, CheckedMul, Saturating};+use sp_std::{collections::btree_set::BTreeSet, iter, prelude::*};++type Identity<T> = identity::Module<T>;+type Settlement<T> = settlement::Module<T>;+type Timestamp<T> = timestamp::Module<T>;++/// Details about the Fundraiser+#[cfg_attr(feature = "std", derive(Debug))]+#[derive(Encode, Decode, Default, Clone, PartialEq, Eq, PartialOrd, Ord)]+pub struct Fundraiser<Balance, Moment> {+    /// Portfolio containing the asset being offered+    pub offering_portfolio: PortfolioId,+    /// Asset being offered+    pub offering_asset: Ticker,+    /// Asset to receive payment in+    pub raising_asset: Ticker,+    /// Tiers of the fundraiser.+    /// Each tier has a set amount of tokens available at a fixed price.+    /// The sum of the tiers is the total amount available in this fundraiser.+    pub tiers: Vec<FundraiserTier<Balance>>,+    /// Id of the venue to use for this fundraise+    pub venue_id: u64,+    /// Start of the fundraiser+    pub start: Moment,+    /// End of the fundraiser+    pub end: Option<Moment>,+    /// Fundraiser is frozen+    pub frozen: bool,+}++/// Single tier of a tiered pricing model+#[cfg_attr(feature = "std", derive(Debug))]+#[derive(Encode, Decode, Default, Clone, PartialEq, Eq, PartialOrd, Ord)]+pub struct PriceTier<Balance> {+    amount: Balance,+    price: Balance,+}++/// Single price tier of a `Fundraiser`.+/// Similar to a `PriceTier` but with an extra field `remaining` for tracking the amount available in a tier.+#[cfg_attr(feature = "std", derive(Debug))]+#[derive(Encode, Decode, Default, Clone, PartialEq, Eq, PartialOrd, Ord)]+pub struct FundraiserTier<Balance> {+    inner: PriceTier<Balance>,+    remaining: Balance,+}++impl<Balance: From<u8>> Into<FundraiserTier<Balance>> for PriceTier<Balance> {+    fn into(self) -> FundraiserTier<Balance> {+        FundraiserTier {+            inner: self,+            remaining: Balance::from(0),+        }+    }+}++pub trait Trait:+    frame_system::Trait+    + CommonTrait+    + IdentityTrait+    + SettlementTrait+    + TimestampTrait+    + PortfolioTrait+{+    /// The overarching event type.+    type Event: From<Event<Self>> + Into<<Self as frame_system::Trait>::Event>;+}++decl_event!(+    pub enum Event<T>+    where+        Balance = <T as CommonTrait>::Balance,+        Moment = <T as TimestampTrait>::Moment,+    {+        /// A new fundraiser has been created+        /// (primary issuance agent, fundraiser)+        FundraiserCreated(IdentityId, Fundraiser<Balance, Moment>),+        /// An investor invested in the fundraiser+        /// (offering token, raise token, offering_token_amount, raise_token_amount, fundraiser_id)+        FundsRaised(IdentityId, Ticker, Ticker, Balance, Balance, u64),+    }+);++decl_error! {+    /// Errors for the Settlement module.+    pub enum Error for Module<T: Trait> {+        /// Sender does not have required permissions+        Unauthorized,+        /// An arithmetic operation overflowed+        Overflow,+        /// Not enough tokens left for sale+        InsufficientTokensRemaining,+        /// Fundraiser not found+        FundraiserNotFound,+        /// Fundraiser is frozen+        FundraiserFrozen,+        // Interacting with a fundraiser past the end `Moment`.+        FundraiserExpired,+        // Interacting with a fundraiser before the start `Moment`.+        FundraiserNotStated,+        // Using an invalid venue+        InvalidVenue,+        // Using an invalid portfolio+        InvalidPortfolio,+    }+}++decl_storage! {+    trait Store for Module<T: Trait> as StoCapped {+        /// All fundraisers that are currently running. (ticker, fundraiser_id) -> Fundraiser+        Fundraisers get(fn fundraisers): double_map hasher(blake2_128_concat) Ticker, hasher(twox_64_concat) u64 => Fundraiser<T::Balance, T::Moment>;+        /// Total fundraisers created for a token+        FundraiserCount get(fn fundraiser_count): map hasher(twox_64_concat) Ticker => u64;+    }+}++decl_module! {+    pub struct Module<T: Trait> for enum Call where origin: T::Origin {+        type Error = Error<T>;++        fn deposit_event() = default;++        /// Create a new offering. A fixed amount of pre-minted tokens are put up for sale at the specified tiered rate.

If we can elaborate in the documentation re. all the errors and conditions it would be good I think.

CJP10

comment created time in 5 days

Pull request review commentPolymathNetwork/Polymesh

[WIP] MESH-1094/Implement a new PrimaryIssuance pallet which wraps up some of the STO functionality

+// Copyright (c) 2020 Polymath++//! # STO Module+//!+//! This is a proof of concept module. It is not meant to be used in the real world in its' current state.++#![cfg_attr(not(feature = "std"), no_std)]+#![recursion_limit = "256"]++use codec::{Decode, Encode};+use frame_support::{+    decl_error, decl_event, decl_module, decl_storage, dispatch::DispatchResult, ensure,+};+use frame_system::ensure_signed;+use pallet_identity as identity;+use pallet_portfolio::{self as portfolio, PortfolioAssetBalances, Trait as PortfolioTrait};+use pallet_settlement::{+    self as settlement, Leg, SettlementType, Trait as SettlementTrait, VenueInfo, VenueType,+};+use pallet_timestamp::{self as timestamp, Trait as TimestampTrait};+use polymesh_common_utilities::{+    constants::currency::*,+    traits::{asset::Trait as AssetTrait, identity::Trait as IdentityTrait, CommonTrait},+    Context,+};+use polymesh_primitives::{IdentityId, PortfolioId, Ticker};+use sp_runtime::traits::{CheckedAdd, CheckedMul, Saturating};+use sp_std::{collections::btree_set::BTreeSet, iter, prelude::*};++type Identity<T> = identity::Module<T>;+type Settlement<T> = settlement::Module<T>;+type Timestamp<T> = timestamp::Module<T>;++/// Details about the Fundraiser+#[cfg_attr(feature = "std", derive(Debug))]+#[derive(Encode, Decode, Default, Clone, PartialEq, Eq, PartialOrd, Ord)]+pub struct Fundraiser<Balance, Moment> {+    /// Portfolio containing the asset being offered+    pub offering_portfolio: PortfolioId,+    /// Asset being offered+    pub offering_asset: Ticker,+    /// Asset to receive payment in+    pub raising_asset: Ticker,+    /// Tiers of the fundraiser.+    /// Each tier has a set amount of tokens available at a fixed price.+    /// The sum of the tiers is the total amount available in this fundraiser.+    pub tiers: Vec<FundraiserTier<Balance>>,+    /// Id of the venue to use for this fundraise+    pub venue_id: u64,+    /// Start of the fundraiser+    pub start: Moment,+    /// End of the fundraiser+    pub end: Option<Moment>,+    /// Fundraiser is frozen+    pub frozen: bool,+}++/// Single tier of a tiered pricing model+#[cfg_attr(feature = "std", derive(Debug))]+#[derive(Encode, Decode, Default, Clone, PartialEq, Eq, PartialOrd, Ord)]+pub struct PriceTier<Balance> {+    amount: Balance,+    price: Balance,+}++/// Single price tier of a `Fundraiser`.+/// Similar to a `PriceTier` but with an extra field `remaining` for tracking the amount available in a tier.+#[cfg_attr(feature = "std", derive(Debug))]+#[derive(Encode, Decode, Default, Clone, PartialEq, Eq, PartialOrd, Ord)]+pub struct FundraiserTier<Balance> {+    inner: PriceTier<Balance>,+    remaining: Balance,+}++impl<Balance: From<u8>> Into<FundraiserTier<Balance>> for PriceTier<Balance> {+    fn into(self) -> FundraiserTier<Balance> {+        FundraiserTier {+            inner: self,+            remaining: Balance::from(0),+        }+    }+}++pub trait Trait:+    frame_system::Trait+    + CommonTrait+    + IdentityTrait+    + SettlementTrait+    + TimestampTrait+    + PortfolioTrait+{+    /// The overarching event type.+    type Event: From<Event<Self>> + Into<<Self as frame_system::Trait>::Event>;+}++decl_event!(+    pub enum Event<T>+    where+        Balance = <T as CommonTrait>::Balance,+        Moment = <T as TimestampTrait>::Moment,+    {+        /// A new fundraiser has been created+        /// (primary issuance agent, fundraiser)+        FundraiserCreated(IdentityId, Fundraiser<Balance, Moment>),+        /// An investor invested in the fundraiser+        /// (offering token, raise token, offering_token_amount, raise_token_amount, fundraiser_id)+        FundsRaised(IdentityId, Ticker, Ticker, Balance, Balance, u64),+    }+);++decl_error! {+    /// Errors for the Settlement module.+    pub enum Error for Module<T: Trait> {+        /// Sender does not have required permissions+        Unauthorized,+        /// An arithmetic operation overflowed+        Overflow,+        /// Not enough tokens left for sale+        InsufficientTokensRemaining,+        /// Fundraiser not found+        FundraiserNotFound,+        /// Fundraiser is frozen+        FundraiserFrozen,+        // Interacting with a fundraiser past the end `Moment`.+        FundraiserExpired,+        // Interacting with a fundraiser before the start `Moment`.+        FundraiserNotStated,+        // Using an invalid venue+        InvalidVenue,+        // Using an invalid portfolio+        InvalidPortfolio,+    }+}++decl_storage! {+    trait Store for Module<T: Trait> as StoCapped {+        /// All fundraisers that are currently running. (ticker, fundraiser_id) -> Fundraiser+        Fundraisers get(fn fundraisers): double_map hasher(blake2_128_concat) Ticker, hasher(twox_64_concat) u64 => Fundraiser<T::Balance, T::Moment>;+        /// Total fundraisers created for a token+        FundraiserCount get(fn fundraiser_count): map hasher(twox_64_concat) Ticker => u64;+    }+}++decl_module! {+    pub struct Module<T: Trait> for enum Call where origin: T::Origin {+        type Error = Error<T>;++        fn deposit_event() = default;++        /// Create a new offering. A fixed amount of pre-minted tokens are put up for sale at the specified tiered rate.+        #[weight = 800_000_000]+        pub fn create_fundraiser(+            origin,+            offering_portfolio: PortfolioId,+            offering_asset: Ticker,+            raising_asset: Ticker,+            tiers: Vec<PriceTier<T::Balance>>,+            venue_id: u64,+            start: Option<T::Moment>,+            end: Option<T::Moment>,+        ) -> DispatchResult {+            let sender = ensure_signed(origin)?;+            let did = Context::current_identity_or::<Identity<T>>(&sender)?;+            ensure!(T::Asset::primary_issuance_agent(&offering_asset) == did, Error::<T>::Unauthorized);++            ensure!(VenueInfo::contains_key(venue_id), Error::<T>::InvalidVenue);+            let venue = VenueInfo::get(venue_id);++            ensure!(venue.creator == did, Error::<T>::InvalidVenue);+            ensure!(venue.venue_type == VenueType::Sto, Error::<T>::InvalidVenue);++            ensure!(offering_portfolio.did == did, Error::<T>::InvalidPortfolio);+            ensure!(<PortfolioAssetBalances<T>>::contains_key(offering_portfolio, offering_asset), Error::<T>::InvalidPortfolio);+            let asset_balance = <PortfolioAssetBalances<T>>::get(offering_portfolio, offering_asset);++            let offering_amount: T::Balance = tiers+                .iter()+                .map(|t| t.amount)+                .fold(0.into(), |x, total| total + x);++            ensure!(offering_amount >= asset_balance, Error::<T>::InsufficientTokensRemaining);++            // Sort by price+            tiers.sort_by(|a, b| a.price.cmp(&b.price));++            // TODO: Take custodial ownership of $sell_amount of $offering_token from primary issuance agent?+            let fundraiser_id = Self::fundraiser_count(offering_asset) + 1;+            // TODO revise the defaults+            let fundraiser = Fundraiser {+                    offering_portfolio,+                    offering_asset,+                    raising_asset,+                    tiers: tiers.into_iter().map(Into::into).collect(),+                    venue_id,+                    start: start.unwrap_or(Timestamp::<T>::get()),+                    end,+                    frozen: false,+                };+            <FundraiserCount>::insert(offering_asset, fundraiser_id);
            FundraiserCount::insert(offering_asset, fundraiser_id);
CJP10

comment created time in 5 days

Pull request review commentPolymathNetwork/Polymesh

[WIP] MESH-1094/Implement a new PrimaryIssuance pallet which wraps up some of the STO functionality

+// Copyright (c) 2020 Polymath++//! # STO Module+//!+//! This is a proof of concept module. It is not meant to be used in the real world in its' current state.++#![cfg_attr(not(feature = "std"), no_std)]+#![recursion_limit = "256"]++use codec::{Decode, Encode};+use frame_support::{+    decl_error, decl_event, decl_module, decl_storage, dispatch::DispatchResult, ensure,+};+use frame_system::ensure_signed;+use pallet_identity as identity;+use pallet_portfolio::{self as portfolio, PortfolioAssetBalances, Trait as PortfolioTrait};+use pallet_settlement::{+    self as settlement, Leg, SettlementType, Trait as SettlementTrait, VenueInfo, VenueType,+};+use pallet_timestamp::{self as timestamp, Trait as TimestampTrait};+use polymesh_common_utilities::{+    constants::currency::*,+    traits::{asset::Trait as AssetTrait, identity::Trait as IdentityTrait, CommonTrait},+    Context,+};+use polymesh_primitives::{IdentityId, PortfolioId, Ticker};+use sp_runtime::traits::{CheckedAdd, CheckedMul, Saturating};+use sp_std::{collections::btree_set::BTreeSet, iter, prelude::*};++type Identity<T> = identity::Module<T>;+type Settlement<T> = settlement::Module<T>;+type Timestamp<T> = timestamp::Module<T>;++/// Details about the Fundraiser+#[cfg_attr(feature = "std", derive(Debug))]+#[derive(Encode, Decode, Default, Clone, PartialEq, Eq, PartialOrd, Ord)]+pub struct Fundraiser<Balance, Moment> {+    /// Portfolio containing the asset being offered+    pub offering_portfolio: PortfolioId,+    /// Asset being offered+    pub offering_asset: Ticker,+    /// Asset to receive payment in+    pub raising_asset: Ticker,+    /// Tiers of the fundraiser.+    /// Each tier has a set amount of tokens available at a fixed price.+    /// The sum of the tiers is the total amount available in this fundraiser.+    pub tiers: Vec<FundraiserTier<Balance>>,+    /// Id of the venue to use for this fundraise+    pub venue_id: u64,+    /// Start of the fundraiser+    pub start: Moment,+    /// End of the fundraiser+    pub end: Option<Moment>,+    /// Fundraiser is frozen+    pub frozen: bool,+}++/// Single tier of a tiered pricing model+#[cfg_attr(feature = "std", derive(Debug))]+#[derive(Encode, Decode, Default, Clone, PartialEq, Eq, PartialOrd, Ord)]+pub struct PriceTier<Balance> {+    amount: Balance,+    price: Balance,+}++/// Single price tier of a `Fundraiser`.+/// Similar to a `PriceTier` but with an extra field `remaining` for tracking the amount available in a tier.+#[cfg_attr(feature = "std", derive(Debug))]+#[derive(Encode, Decode, Default, Clone, PartialEq, Eq, PartialOrd, Ord)]+pub struct FundraiserTier<Balance> {+    inner: PriceTier<Balance>,+    remaining: Balance,+}++impl<Balance: From<u8>> Into<FundraiserTier<Balance>> for PriceTier<Balance> {+    fn into(self) -> FundraiserTier<Balance> {+        FundraiserTier {+            inner: self,+            remaining: Balance::from(0),+        }+    }+}++pub trait Trait:+    frame_system::Trait+    + CommonTrait+    + IdentityTrait+    + SettlementTrait+    + TimestampTrait+    + PortfolioTrait+{+    /// The overarching event type.+    type Event: From<Event<Self>> + Into<<Self as frame_system::Trait>::Event>;+}++decl_event!(+    pub enum Event<T>+    where+        Balance = <T as CommonTrait>::Balance,+        Moment = <T as TimestampTrait>::Moment,+    {+        /// A new fundraiser has been created+        /// (primary issuance agent, fundraiser)+        FundraiserCreated(IdentityId, Fundraiser<Balance, Moment>),+        /// An investor invested in the fundraiser+        /// (offering token, raise token, offering_token_amount, raise_token_amount, fundraiser_id)+        FundsRaised(IdentityId, Ticker, Ticker, Balance, Balance, u64),+    }+);++decl_error! {+    /// Errors for the Settlement module.+    pub enum Error for Module<T: Trait> {+        /// Sender does not have required permissions+        Unauthorized,+        /// An arithmetic operation overflowed+        Overflow,+        /// Not enough tokens left for sale+        InsufficientTokensRemaining,+        /// Fundraiser not found+        FundraiserNotFound,+        /// Fundraiser is frozen+        FundraiserFrozen,+        // Interacting with a fundraiser past the end `Moment`.+        FundraiserExpired,+        // Interacting with a fundraiser before the start `Moment`.+        FundraiserNotStated,+        // Using an invalid venue+        InvalidVenue,+        // Using an invalid portfolio+        InvalidPortfolio,+    }+}++decl_storage! {+    trait Store for Module<T: Trait> as StoCapped {+        /// All fundraisers that are currently running. (ticker, fundraiser_id) -> Fundraiser+        Fundraisers get(fn fundraisers): double_map hasher(blake2_128_concat) Ticker, hasher(twox_64_concat) u64 => Fundraiser<T::Balance, T::Moment>;+        /// Total fundraisers created for a token+        FundraiserCount get(fn fundraiser_count): map hasher(twox_64_concat) Ticker => u64;+    }+}++decl_module! {+    pub struct Module<T: Trait> for enum Call where origin: T::Origin {+        type Error = Error<T>;++        fn deposit_event() = default;++        /// Create a new offering. A fixed amount of pre-minted tokens are put up for sale at the specified tiered rate.+        #[weight = 800_000_000]+        pub fn create_fundraiser(+            origin,+            offering_portfolio: PortfolioId,+            offering_asset: Ticker,+            raising_asset: Ticker,+            tiers: Vec<PriceTier<T::Balance>>,+            venue_id: u64,+            start: Option<T::Moment>,+            end: Option<T::Moment>,+        ) -> DispatchResult {+            let sender = ensure_signed(origin)?;+            let did = Context::current_identity_or::<Identity<T>>(&sender)?;+            ensure!(T::Asset::primary_issuance_agent(&offering_asset) == did, Error::<T>::Unauthorized);++            ensure!(VenueInfo::contains_key(venue_id), Error::<T>::InvalidVenue);+            let venue = VenueInfo::get(venue_id);++            ensure!(venue.creator == did, Error::<T>::InvalidVenue);+            ensure!(venue.venue_type == VenueType::Sto, Error::<T>::InvalidVenue);++            ensure!(offering_portfolio.did == did, Error::<T>::InvalidPortfolio);+            ensure!(<PortfolioAssetBalances<T>>::contains_key(offering_portfolio, offering_asset), Error::<T>::InvalidPortfolio);+            let asset_balance = <PortfolioAssetBalances<T>>::get(offering_portfolio, offering_asset);++            let offering_amount: T::Balance = tiers+                .iter()+                .map(|t| t.amount)+                .fold(0.into(), |x, total| total + x);++            ensure!(offering_amount >= asset_balance, Error::<T>::InsufficientTokensRemaining);++            // Sort by price+            tiers.sort_by(|a, b| a.price.cmp(&b.price));
            // (Stable) sort by price.
            tiers.sort_by_key(|a| a.price);
CJP10

comment created time in 5 days

Pull request review commentPolymathNetwork/Polymesh

[WIP] MESH-1094/Implement a new PrimaryIssuance pallet which wraps up some of the STO functionality

+// Copyright (c) 2020 Polymath++//! # STO Module+//!+//! This is a proof of concept module. It is not meant to be used in the real world in its' current state.++#![cfg_attr(not(feature = "std"), no_std)]+#![recursion_limit = "256"]++use codec::{Decode, Encode};+use frame_support::{+    decl_error, decl_event, decl_module, decl_storage, dispatch::DispatchResult, ensure,+};+use frame_system::ensure_signed;+use pallet_identity as identity;+use pallet_portfolio::{self as portfolio, PortfolioAssetBalances, Trait as PortfolioTrait};+use pallet_settlement::{+    self as settlement, Leg, SettlementType, Trait as SettlementTrait, VenueInfo, VenueType,+};+use pallet_timestamp::{self as timestamp, Trait as TimestampTrait};+use polymesh_common_utilities::{+    constants::currency::*,+    traits::{asset::Trait as AssetTrait, identity::Trait as IdentityTrait, CommonTrait},+    Context,+};+use polymesh_primitives::{IdentityId, PortfolioId, Ticker};+use sp_runtime::traits::{CheckedAdd, CheckedMul, Saturating};+use sp_std::{collections::btree_set::BTreeSet, iter, prelude::*};++type Identity<T> = identity::Module<T>;+type Settlement<T> = settlement::Module<T>;+type Timestamp<T> = timestamp::Module<T>;++/// Details about the Fundraiser+#[cfg_attr(feature = "std", derive(Debug))]+#[derive(Encode, Decode, Default, Clone, PartialEq, Eq, PartialOrd, Ord)]+pub struct Fundraiser<Balance, Moment> {+    /// Portfolio containing the asset being offered+    pub offering_portfolio: PortfolioId,+    /// Asset being offered+    pub offering_asset: Ticker,+    /// Asset to receive payment in+    pub raising_asset: Ticker,+    /// Tiers of the fundraiser.+    /// Each tier has a set amount of tokens available at a fixed price.+    /// The sum of the tiers is the total amount available in this fundraiser.+    pub tiers: Vec<FundraiserTier<Balance>>,+    /// Id of the venue to use for this fundraise+    pub venue_id: u64,+    /// Start of the fundraiser+    pub start: Moment,+    /// End of the fundraiser+    pub end: Option<Moment>,+    /// Fundraiser is frozen+    pub frozen: bool,+}++/// Single tier of a tiered pricing model+#[cfg_attr(feature = "std", derive(Debug))]+#[derive(Encode, Decode, Default, Clone, PartialEq, Eq, PartialOrd, Ord)]+pub struct PriceTier<Balance> {+    amount: Balance,+    price: Balance,+}++/// Single price tier of a `Fundraiser`.+/// Similar to a `PriceTier` but with an extra field `remaining` for tracking the amount available in a tier.+#[cfg_attr(feature = "std", derive(Debug))]+#[derive(Encode, Decode, Default, Clone, PartialEq, Eq, PartialOrd, Ord)]+pub struct FundraiserTier<Balance> {+    inner: PriceTier<Balance>,+    remaining: Balance,+}++impl<Balance: From<u8>> Into<FundraiserTier<Balance>> for PriceTier<Balance> {+    fn into(self) -> FundraiserTier<Balance> {+        FundraiserTier {+            inner: self,+            remaining: Balance::from(0),+        }+    }+}++pub trait Trait:+    frame_system::Trait+    + CommonTrait+    + IdentityTrait+    + SettlementTrait+    + TimestampTrait+    + PortfolioTrait+{+    /// The overarching event type.+    type Event: From<Event<Self>> + Into<<Self as frame_system::Trait>::Event>;+}++decl_event!(+    pub enum Event<T>+    where+        Balance = <T as CommonTrait>::Balance,+        Moment = <T as TimestampTrait>::Moment,+    {+        /// A new fundraiser has been created+        /// (primary issuance agent, fundraiser)+        FundraiserCreated(IdentityId, Fundraiser<Balance, Moment>),+        /// An investor invested in the fundraiser+        /// (offering token, raise token, offering_token_amount, raise_token_amount, fundraiser_id)+        FundsRaised(IdentityId, Ticker, Ticker, Balance, Balance, u64),+    }+);++decl_error! {+    /// Errors for the Settlement module.+    pub enum Error for Module<T: Trait> {+        /// Sender does not have required permissions+        Unauthorized,+        /// An arithmetic operation overflowed+        Overflow,+        /// Not enough tokens left for sale+        InsufficientTokensRemaining,+        /// Fundraiser not found+        FundraiserNotFound,+        /// Fundraiser is frozen+        FundraiserFrozen,+        // Interacting with a fundraiser past the end `Moment`.+        FundraiserExpired,+        // Interacting with a fundraiser before the start `Moment`.+        FundraiserNotStated,+        // Using an invalid venue+        InvalidVenue,+        // Using an invalid portfolio+        InvalidPortfolio,+    }+}++decl_storage! {+    trait Store for Module<T: Trait> as StoCapped {+        /// All fundraisers that are currently running. (ticker, fundraiser_id) -> Fundraiser+        Fundraisers get(fn fundraisers): double_map hasher(blake2_128_concat) Ticker, hasher(twox_64_concat) u64 => Fundraiser<T::Balance, T::Moment>;+        /// Total fundraisers created for a token+        FundraiserCount get(fn fundraiser_count): map hasher(twox_64_concat) Ticker => u64;+    }+}++decl_module! {+    pub struct Module<T: Trait> for enum Call where origin: T::Origin {+        type Error = Error<T>;++        fn deposit_event() = default;++        /// Create a new offering. A fixed amount of pre-minted tokens are put up for sale at the specified tiered rate.+        #[weight = 800_000_000]+        pub fn create_fundraiser(+            origin,+            offering_portfolio: PortfolioId,+            offering_asset: Ticker,+            raising_asset: Ticker,+            tiers: Vec<PriceTier<T::Balance>>,+            venue_id: u64,+            start: Option<T::Moment>,+            end: Option<T::Moment>,+        ) -> DispatchResult {+            let sender = ensure_signed(origin)?;+            let did = Context::current_identity_or::<Identity<T>>(&sender)?;+            ensure!(T::Asset::primary_issuance_agent(&offering_asset) == did, Error::<T>::Unauthorized);++            ensure!(VenueInfo::contains_key(venue_id), Error::<T>::InvalidVenue);+            let venue = VenueInfo::get(venue_id);++            ensure!(venue.creator == did, Error::<T>::InvalidVenue);+            ensure!(venue.venue_type == VenueType::Sto, Error::<T>::InvalidVenue);++            ensure!(offering_portfolio.did == did, Error::<T>::InvalidPortfolio);+            ensure!(<PortfolioAssetBalances<T>>::contains_key(offering_portfolio, offering_asset), Error::<T>::InvalidPortfolio);+            let asset_balance = <PortfolioAssetBalances<T>>::get(offering_portfolio, offering_asset);

If we use Option<_> in the map we can make this code nicer too.

CJP10

comment created time in 5 days

Pull request review commentPolymathNetwork/Polymesh

[WIP] MESH-1094/Implement a new PrimaryIssuance pallet which wraps up some of the STO functionality

+// Copyright (c) 2020 Polymath++//! # STO Module+//!+//! This is a proof of concept module. It is not meant to be used in the real world in its' current state.++#![cfg_attr(not(feature = "std"), no_std)]+#![recursion_limit = "256"]++use codec::{Decode, Encode};+use frame_support::{+    decl_error, decl_event, decl_module, decl_storage, dispatch::DispatchResult, ensure,+};+use frame_system::ensure_signed;+use pallet_identity as identity;+use pallet_portfolio::{self as portfolio, PortfolioAssetBalances, Trait as PortfolioTrait};+use pallet_settlement::{+    self as settlement, Leg, SettlementType, Trait as SettlementTrait, VenueInfo, VenueType,+};+use pallet_timestamp::{self as timestamp, Trait as TimestampTrait};+use polymesh_common_utilities::{+    constants::currency::*,+    traits::{asset::Trait as AssetTrait, identity::Trait as IdentityTrait, CommonTrait},+    Context,+};+use polymesh_primitives::{IdentityId, PortfolioId, Ticker};+use sp_runtime::traits::{CheckedAdd, CheckedMul, Saturating};+use sp_std::{collections::btree_set::BTreeSet, iter, prelude::*};++type Identity<T> = identity::Module<T>;+type Settlement<T> = settlement::Module<T>;+type Timestamp<T> = timestamp::Module<T>;++/// Details about the Fundraiser+#[cfg_attr(feature = "std", derive(Debug))]+#[derive(Encode, Decode, Default, Clone, PartialEq, Eq, PartialOrd, Ord)]+pub struct Fundraiser<Balance, Moment> {+    /// Portfolio containing the asset being offered+    pub offering_portfolio: PortfolioId,+    /// Asset being offered+    pub offering_asset: Ticker,+    /// Asset to receive payment in+    pub raising_asset: Ticker,+    /// Tiers of the fundraiser.+    /// Each tier has a set amount of tokens available at a fixed price.+    /// The sum of the tiers is the total amount available in this fundraiser.+    pub tiers: Vec<FundraiserTier<Balance>>,+    /// Id of the venue to use for this fundraise+    pub venue_id: u64,+    /// Start of the fundraiser+    pub start: Moment,+    /// End of the fundraiser+    pub end: Option<Moment>,+    /// Fundraiser is frozen+    pub frozen: bool,+}++/// Single tier of a tiered pricing model+#[cfg_attr(feature = "std", derive(Debug))]+#[derive(Encode, Decode, Default, Clone, PartialEq, Eq, PartialOrd, Ord)]+pub struct PriceTier<Balance> {+    amount: Balance,+    price: Balance,+}++/// Single price tier of a `Fundraiser`.+/// Similar to a `PriceTier` but with an extra field `remaining` for tracking the amount available in a tier.+#[cfg_attr(feature = "std", derive(Debug))]+#[derive(Encode, Decode, Default, Clone, PartialEq, Eq, PartialOrd, Ord)]+pub struct FundraiserTier<Balance> {+    inner: PriceTier<Balance>,+    remaining: Balance,+}++impl<Balance: From<u8>> Into<FundraiserTier<Balance>> for PriceTier<Balance> {

Do you get coherence problems if you impl From instead?

CJP10

comment created time in 5 days

Pull request review commentPolymathNetwork/Polymesh

[WIP] MESH-1094/Implement a new PrimaryIssuance pallet which wraps up some of the STO functionality

 decl_error! { decl_storage! {     trait Store for Module<T: Trait> as StoCapped {         /// Info about a venue. venue_id -> venue_details-        VenueInfo get(fn venue_info): map hasher(twox_64_concat) u64 => Venue;+        pub VenueInfo get(fn venue_info): map hasher(twox_64_concat) u64 => Venue;
        pub VenueInfo get(fn venue_info): map hasher(twox_64_concat) u64 => Option<Venue>;

Will generally make the other code nicer.

CJP10

comment created time in 5 days

Pull request review commentPolymathNetwork/Polymesh

[WIP] MESH-1094/Implement a new PrimaryIssuance pallet which wraps up some of the STO functionality

+// Copyright (c) 2020 Polymath++//! # STO Module+//!+//! This is a proof of concept module. It is not meant to be used in the real world in its' current state.++#![cfg_attr(not(feature = "std"), no_std)]+#![recursion_limit = "256"]++use codec::{Decode, Encode};+use frame_support::{+    decl_error, decl_event, decl_module, decl_storage, dispatch::DispatchResult, ensure,+};+use frame_system::ensure_signed;+use pallet_identity as identity;+use pallet_portfolio::{self as portfolio, PortfolioAssetBalances, Trait as PortfolioTrait};+use pallet_settlement::{+    self as settlement, Leg, SettlementType, Trait as SettlementTrait, VenueInfo, VenueType,+};+use pallet_timestamp::{self as timestamp, Trait as TimestampTrait};+use polymesh_common_utilities::{+    constants::currency::*,+    traits::{asset::Trait as AssetTrait, identity::Trait as IdentityTrait, CommonTrait},+    Context,+};+use polymesh_primitives::{IdentityId, PortfolioId, Ticker};+use sp_runtime::traits::{CheckedAdd, CheckedMul, Saturating};+use sp_std::{collections::btree_set::BTreeSet, iter, prelude::*};++type Identity<T> = identity::Module<T>;+type Settlement<T> = settlement::Module<T>;+type Timestamp<T> = timestamp::Module<T>;++/// Details about the Fundraiser+#[cfg_attr(feature = "std", derive(Debug))]+#[derive(Encode, Decode, Default, Clone, PartialEq, Eq, PartialOrd, Ord)]+pub struct Fundraiser<Balance, Moment> {+    /// Portfolio containing the asset being offered+    pub offering_portfolio: PortfolioId,+    /// Asset being offered+    pub offering_asset: Ticker,+    /// Asset to receive payment in+    pub raising_asset: Ticker,+    /// Tiers of the fundraiser.+    /// Each tier has a set amount of tokens available at a fixed price.+    /// The sum of the tiers is the total amount available in this fundraiser.+    pub tiers: Vec<FundraiserTier<Balance>>,+    /// Id of the venue to use for this fundraise+    pub venue_id: u64,+    /// Start of the fundraiser+    pub start: Moment,+    /// End of the fundraiser+    pub end: Option<Moment>,+    /// Fundraiser is frozen+    pub frozen: bool,+}++/// Single tier of a tiered pricing model+#[cfg_attr(feature = "std", derive(Debug))]+#[derive(Encode, Decode, Default, Clone, PartialEq, Eq, PartialOrd, Ord)]+pub struct PriceTier<Balance> {+    amount: Balance,+    price: Balance,+}++/// Single price tier of a `Fundraiser`.+/// Similar to a `PriceTier` but with an extra field `remaining` for tracking the amount available in a tier.+#[cfg_attr(feature = "std", derive(Debug))]+#[derive(Encode, Decode, Default, Clone, PartialEq, Eq, PartialOrd, Ord)]+pub struct FundraiserTier<Balance> {+    inner: PriceTier<Balance>,+    remaining: Balance,+}++impl<Balance: From<u8>> Into<FundraiserTier<Balance>> for PriceTier<Balance> {+    fn into(self) -> FundraiserTier<Balance> {+        FundraiserTier {+            inner: self,+            remaining: Balance::from(0),+        }+    }+}++pub trait Trait:+    frame_system::Trait+    + CommonTrait+    + IdentityTrait+    + SettlementTrait+    + TimestampTrait+    + PortfolioTrait+{+    /// The overarching event type.+    type Event: From<Event<Self>> + Into<<Self as frame_system::Trait>::Event>;+}++decl_event!(+    pub enum Event<T>+    where+        Balance = <T as CommonTrait>::Balance,+        Moment = <T as TimestampTrait>::Moment,+    {+        /// A new fundraiser has been created+        /// (primary issuance agent, fundraiser)+        FundraiserCreated(IdentityId, Fundraiser<Balance, Moment>),+        /// An investor invested in the fundraiser+        /// (offering token, raise token, offering_token_amount, raise_token_amount, fundraiser_id)+        FundsRaised(IdentityId, Ticker, Ticker, Balance, Balance, u64),+    }+);++decl_error! {+    /// Errors for the Settlement module.+    pub enum Error for Module<T: Trait> {+        /// Sender does not have required permissions+        Unauthorized,+        /// An arithmetic operation overflowed+        Overflow,+        /// Not enough tokens left for sale+        InsufficientTokensRemaining,+        /// Fundraiser not found+        FundraiserNotFound,+        /// Fundraiser is frozen+        FundraiserFrozen,+        // Interacting with a fundraiser past the end `Moment`.+        FundraiserExpired,+        // Interacting with a fundraiser before the start `Moment`.+        FundraiserNotStated,+        // Using an invalid venue+        InvalidVenue,+        // Using an invalid portfolio+        InvalidPortfolio,+    }+}++decl_storage! {+    trait Store for Module<T: Trait> as StoCapped {+        /// All fundraisers that are currently running. (ticker, fundraiser_id) -> Fundraiser+        Fundraisers get(fn fundraisers): double_map hasher(blake2_128_concat) Ticker, hasher(twox_64_concat) u64 => Fundraiser<T::Balance, T::Moment>;+        /// Total fundraisers created for a token+        FundraiserCount get(fn fundraiser_count): map hasher(twox_64_concat) Ticker => u64;+    }+}++decl_module! {+    pub struct Module<T: Trait> for enum Call where origin: T::Origin {+        type Error = Error<T>;++        fn deposit_event() = default;++        /// Create a new offering. A fixed amount of pre-minted tokens are put up for sale at the specified tiered rate.+        #[weight = 800_000_000]+        pub fn create_fundraiser(+            origin,+            offering_portfolio: PortfolioId,+            offering_asset: Ticker,+            raising_asset: Ticker,+            tiers: Vec<PriceTier<T::Balance>>,+            venue_id: u64,+            start: Option<T::Moment>,+            end: Option<T::Moment>,+        ) -> DispatchResult {+            let sender = ensure_signed(origin)?;+            let did = Context::current_identity_or::<Identity<T>>(&sender)?;+            ensure!(T::Asset::primary_issuance_agent(&offering_asset) == did, Error::<T>::Unauthorized);++            ensure!(VenueInfo::contains_key(venue_id), Error::<T>::InvalidVenue);+            let venue = VenueInfo::get(venue_id);++            ensure!(venue.creator == did, Error::<T>::InvalidVenue);+            ensure!(venue.venue_type == VenueType::Sto, Error::<T>::InvalidVenue);
            let venue = VenueInfo::get(venue_id)
                .filter(|v| v.creator == did && v.venue_type == VenueType::Sto)
                .ok_or(Error::<T>::InvalidVenue)?;
CJP10

comment created time in 5 days

Pull request review commentPolymathNetwork/Polymesh

[WIP] MESH-1094/Implement a new PrimaryIssuance pallet which wraps up some of the STO functionality

+// Copyright (c) 2020 Polymath++//! # STO Module+//!+//! This is a proof of concept module. It is not meant to be used in the real world in its' current state.++#![cfg_attr(not(feature = "std"), no_std)]+#![recursion_limit = "256"]++use codec::{Decode, Encode};+use frame_support::{+    decl_error, decl_event, decl_module, decl_storage, dispatch::DispatchResult, ensure,+};+use frame_system::ensure_signed;+use pallet_identity as identity;+use pallet_portfolio::{self as portfolio, PortfolioAssetBalances, Trait as PortfolioTrait};+use pallet_settlement::{+    self as settlement, Leg, SettlementType, Trait as SettlementTrait, VenueInfo, VenueType,+};+use pallet_timestamp::{self as timestamp, Trait as TimestampTrait};+use polymesh_common_utilities::{+    constants::currency::*,+    traits::{asset::Trait as AssetTrait, identity::Trait as IdentityTrait, CommonTrait},+    Context,+};+use polymesh_primitives::{IdentityId, PortfolioId, Ticker};+use sp_runtime::traits::{CheckedAdd, CheckedMul, Saturating};+use sp_std::{collections::btree_set::BTreeSet, iter, prelude::*};++type Identity<T> = identity::Module<T>;+type Settlement<T> = settlement::Module<T>;+type Timestamp<T> = timestamp::Module<T>;++/// Details about the Fundraiser+#[cfg_attr(feature = "std", derive(Debug))]+#[derive(Encode, Decode, Default, Clone, PartialEq, Eq, PartialOrd, Ord)]+pub struct Fundraiser<Balance, Moment> {+    /// Portfolio containing the asset being offered+    pub offering_portfolio: PortfolioId,+    /// Asset being offered+    pub offering_asset: Ticker,+    /// Asset to receive payment in+    pub raising_asset: Ticker,+    /// Tiers of the fundraiser.+    /// Each tier has a set amount of tokens available at a fixed price.+    /// The sum of the tiers is the total amount available in this fundraiser.+    pub tiers: Vec<FundraiserTier<Balance>>,+    /// Id of the venue to use for this fundraise+    pub venue_id: u64,+    /// Start of the fundraiser+    pub start: Moment,+    /// End of the fundraiser+    pub end: Option<Moment>,+    /// Fundraiser is frozen+    pub frozen: bool,+}++/// Single tier of a tiered pricing model+#[cfg_attr(feature = "std", derive(Debug))]+#[derive(Encode, Decode, Default, Clone, PartialEq, Eq, PartialOrd, Ord)]+pub struct PriceTier<Balance> {+    amount: Balance,+    price: Balance,

Let's document these?

CJP10

comment created time in 5 days

Pull request review commentPolymathNetwork/Polymesh

[WIP] MESH-1094/Implement a new PrimaryIssuance pallet which wraps up some of the STO functionality

+// Copyright (c) 2020 Polymath++//! # STO Module+//!+//! This is a proof of concept module. It is not meant to be used in the real world in its' current state.++#![cfg_attr(not(feature = "std"), no_std)]+#![recursion_limit = "256"]++use codec::{Decode, Encode};+use frame_support::{+    decl_error, decl_event, decl_module, decl_storage, dispatch::DispatchResult, ensure,+};+use frame_system::ensure_signed;+use pallet_identity as identity;+use pallet_portfolio::{self as portfolio, PortfolioAssetBalances, Trait as PortfolioTrait};+use pallet_settlement::{+    self as settlement, Leg, SettlementType, Trait as SettlementTrait, VenueInfo, VenueType,+};+use pallet_timestamp::{self as timestamp, Trait as TimestampTrait};+use polymesh_common_utilities::{+    constants::currency::*,+    traits::{asset::Trait as AssetTrait, identity::Trait as IdentityTrait, CommonTrait},+    Context,+};+use polymesh_primitives::{IdentityId, PortfolioId, Ticker};+use sp_runtime::traits::{CheckedAdd, CheckedMul, Saturating};+use sp_std::{collections::btree_set::BTreeSet, iter, prelude::*};++type Identity<T> = identity::Module<T>;+type Settlement<T> = settlement::Module<T>;+type Timestamp<T> = timestamp::Module<T>;++/// Details about the Fundraiser+#[cfg_attr(feature = "std", derive(Debug))]+#[derive(Encode, Decode, Default, Clone, PartialEq, Eq, PartialOrd, Ord)]+pub struct Fundraiser<Balance, Moment> {+    /// Portfolio containing the asset being offered+    pub offering_portfolio: PortfolioId,+    /// Asset being offered+    pub offering_asset: Ticker,+    /// Asset to receive payment in+    pub raising_asset: Ticker,+    /// Tiers of the fundraiser.+    /// Each tier has a set amount of tokens available at a fixed price.+    /// The sum of the tiers is the total amount available in this fundraiser.+    pub tiers: Vec<FundraiserTier<Balance>>,+    /// Id of the venue to use for this fundraise+    pub venue_id: u64,+    /// Start of the fundraiser+    pub start: Moment,+    /// End of the fundraiser+    pub end: Option<Moment>,+    /// Fundraiser is frozen+    pub frozen: bool,+}++/// Single tier of a tiered pricing model+#[cfg_attr(feature = "std", derive(Debug))]+#[derive(Encode, Decode, Default, Clone, PartialEq, Eq, PartialOrd, Ord)]+pub struct PriceTier<Balance> {+    amount: Balance,+    price: Balance,+}++/// Single price tier of a `Fundraiser`.+/// Similar to a `PriceTier` but with an extra field `remaining` for tracking the amount available in a tier.+#[cfg_attr(feature = "std", derive(Debug))]+#[derive(Encode, Decode, Default, Clone, PartialEq, Eq, PartialOrd, Ord)]+pub struct FundraiserTier<Balance> {+    inner: PriceTier<Balance>,+    remaining: Balance,+}++impl<Balance: From<u8>> Into<FundraiserTier<Balance>> for PriceTier<Balance> {+    fn into(self) -> FundraiserTier<Balance> {+        FundraiserTier {+            inner: self,+            remaining: Balance::from(0),+        }+    }+}++pub trait Trait:+    frame_system::Trait+    + CommonTrait+    + IdentityTrait+    + SettlementTrait+    + TimestampTrait+    + PortfolioTrait+{+    /// The overarching event type.+    type Event: From<Event<Self>> + Into<<Self as frame_system::Trait>::Event>;+}++decl_event!(+    pub enum Event<T>+    where+        Balance = <T as CommonTrait>::Balance,+        Moment = <T as TimestampTrait>::Moment,+    {+        /// A new fundraiser has been created+        /// (primary issuance agent, fundraiser)+        FundraiserCreated(IdentityId, Fundraiser<Balance, Moment>),+        /// An investor invested in the fundraiser+        /// (offering token, raise token, offering_token_amount, raise_token_amount, fundraiser_id)+        FundsRaised(IdentityId, Ticker, Ticker, Balance, Balance, u64),+    }+);++decl_error! {+    /// Errors for the Settlement module.+    pub enum Error for Module<T: Trait> {+        /// Sender does not have required permissions+        Unauthorized,+        /// An arithmetic operation overflowed+        Overflow,+        /// Not enough tokens left for sale+        InsufficientTokensRemaining,+        /// Fundraiser not found+        FundraiserNotFound,+        /// Fundraiser is frozen+        FundraiserFrozen,+        // Interacting with a fundraiser past the end `Moment`.+        FundraiserExpired,+        // Interacting with a fundraiser before the start `Moment`.+        FundraiserNotStated,+        // Using an invalid venue+        InvalidVenue,+        // Using an invalid portfolio+        InvalidPortfolio,+    }+}++decl_storage! {+    trait Store for Module<T: Trait> as StoCapped {+        /// All fundraisers that are currently running. (ticker, fundraiser_id) -> Fundraiser+        Fundraisers get(fn fundraisers): double_map hasher(blake2_128_concat) Ticker, hasher(twox_64_concat) u64 => Fundraiser<T::Balance, T::Moment>;+        /// Total fundraisers created for a token+        FundraiserCount get(fn fundraiser_count): map hasher(twox_64_concat) Ticker => u64;+    }+}++decl_module! {+    pub struct Module<T: Trait> for enum Call where origin: T::Origin {+        type Error = Error<T>;++        fn deposit_event() = default;++        /// Create a new offering. A fixed amount of pre-minted tokens are put up for sale at the specified tiered rate.+        #[weight = 800_000_000]+        pub fn create_fundraiser(+            origin,+            offering_portfolio: PortfolioId,+            offering_asset: Ticker,+            raising_asset: Ticker,+            tiers: Vec<PriceTier<T::Balance>>,+            venue_id: u64,+            start: Option<T::Moment>,+            end: Option<T::Moment>,+        ) -> DispatchResult {+            let sender = ensure_signed(origin)?;+            let did = Context::current_identity_or::<Identity<T>>(&sender)?;+            ensure!(T::Asset::primary_issuance_agent(&offering_asset) == did, Error::<T>::Unauthorized);++            ensure!(VenueInfo::contains_key(venue_id), Error::<T>::InvalidVenue);+            let venue = VenueInfo::get(venue_id);++            ensure!(venue.creator == did, Error::<T>::InvalidVenue);+            ensure!(venue.venue_type == VenueType::Sto, Error::<T>::InvalidVenue);++            ensure!(offering_portfolio.did == did, Error::<T>::InvalidPortfolio);+            ensure!(<PortfolioAssetBalances<T>>::contains_key(offering_portfolio, offering_asset), Error::<T>::InvalidPortfolio);+            let asset_balance = <PortfolioAssetBalances<T>>::get(offering_portfolio, offering_asset);++            let offering_amount: T::Balance = tiers+                .iter()+                .map(|t| t.amount)+                .fold(0.into(), |x, total| total + x);
                .sum();
CJP10

comment created time in 5 days

Pull request review commentPolymathNetwork/Polymesh

[WIP] MESH-1094/Implement a new PrimaryIssuance pallet which wraps up some of the STO functionality

+// Copyright (c) 2020 Polymath++//! # STO Module+//!+//! This is a proof of concept module. It is not meant to be used in the real world in its' current state.++#![cfg_attr(not(feature = "std"), no_std)]+#![recursion_limit = "256"]++use codec::{Decode, Encode};+use frame_support::{+    decl_error, decl_event, decl_module, decl_storage, dispatch::DispatchResult, ensure,+};+use frame_system::ensure_signed;+use pallet_identity as identity;+use pallet_portfolio::{self as portfolio, PortfolioAssetBalances, Trait as PortfolioTrait};+use pallet_settlement::{+    self as settlement, Leg, SettlementType, Trait as SettlementTrait, VenueInfo, VenueType,+};+use pallet_timestamp::{self as timestamp, Trait as TimestampTrait};+use polymesh_common_utilities::{+    constants::currency::*,+    traits::{asset::Trait as AssetTrait, identity::Trait as IdentityTrait, CommonTrait},+    Context,+};+use polymesh_primitives::{IdentityId, PortfolioId, Ticker};+use sp_runtime::traits::{CheckedAdd, CheckedMul, Saturating};+use sp_std::{collections::btree_set::BTreeSet, iter, prelude::*};++type Identity<T> = identity::Module<T>;+type Settlement<T> = settlement::Module<T>;+type Timestamp<T> = timestamp::Module<T>;++/// Details about the Fundraiser+#[cfg_attr(feature = "std", derive(Debug))]+#[derive(Encode, Decode, Default, Clone, PartialEq, Eq, PartialOrd, Ord)]+pub struct Fundraiser<Balance, Moment> {+    /// Portfolio containing the asset being offered+    pub offering_portfolio: PortfolioId,+    /// Asset being offered+    pub offering_asset: Ticker,+    /// Asset to receive payment in+    pub raising_asset: Ticker,+    /// Tiers of the fundraiser.+    /// Each tier has a set amount of tokens available at a fixed price.+    /// The sum of the tiers is the total amount available in this fundraiser.+    pub tiers: Vec<FundraiserTier<Balance>>,+    /// Id of the venue to use for this fundraise+    pub venue_id: u64,+    /// Start of the fundraiser+    pub start: Moment,+    /// End of the fundraiser+    pub end: Option<Moment>,+    /// Fundraiser is frozen+    pub frozen: bool,+}++/// Single tier of a tiered pricing model+#[cfg_attr(feature = "std", derive(Debug))]+#[derive(Encode, Decode, Default, Clone, PartialEq, Eq, PartialOrd, Ord)]+pub struct PriceTier<Balance> {+    amount: Balance,+    price: Balance,+}++/// Single price tier of a `Fundraiser`.+/// Similar to a `PriceTier` but with an extra field `remaining` for tracking the amount available in a tier.+#[cfg_attr(feature = "std", derive(Debug))]+#[derive(Encode, Decode, Default, Clone, PartialEq, Eq, PartialOrd, Ord)]+pub struct FundraiserTier<Balance> {+    inner: PriceTier<Balance>,+    remaining: Balance,

And these?

CJP10

comment created time in 5 days

PullRequestReviewEvent
PullRequestReviewEvent

delete branch PolymathNetwork/Polymesh

delete branch : mesh-1255-tx-pay

delete time in 5 days

delete branch PolymathNetwork/Polymesh

delete branch : mesh-1255-staking

delete time in 5 days

push eventPolymathNetwork/Polymesh

Mazdak Farrokhzad

commit sha 4812dff0465931ea016004ca8770cdf77f8f5906

MESH-1255/Staking: Pull in some substrate-rc6 changes (#613) * mesh-1255: copy-in staking/fuzzer * mesh-1255: copy-in staking/reward-curve * mesh-1255: un-copy 'reward-curve' crate * mesh-1255: copy-in staking/src Co-authored-by: Satyam Agrawal <satyam0499@gmail.com>

view details

Mazdak Farrokhzad

commit sha 73c1ad2611407b3d48fd47cafc3e193db122fea1

Merge branch 'develop' into mesh-1255-tx-pay

view details

push time in 5 days

create barnchPolymathNetwork/Polymesh

branch : mesh-1255-balances

created branch time in 5 days

Pull request review commentPolymathNetwork/Polymesh

MESH-1255/Staking: Pull in some substrate-rc6 changes

 pub mod weight {     } } +pub trait WeightInfo {+    fn bond(u: u32) -> Weight;+    fn bond_extra(u: u32) -> Weight;+    fn unbond(u: u32) -> Weight;+    fn withdraw_unbonded_update(s: u32) -> Weight;+    fn withdraw_unbonded_kill(s: u32) -> Weight;+    fn validate(u: u32) -> Weight;+    fn nominate(n: u32) -> Weight;+    fn chill(u: u32) -> Weight;+    fn set_payee(u: u32) -> Weight;+    fn set_controller(u: u32) -> Weight;+    fn set_validator_count(c: u32) -> Weight;+    fn force_no_eras(i: u32) -> Weight;+    fn force_new_era(i: u32) -> Weight;+    fn force_new_era_always(i: u32) -> Weight;+    fn set_invulnerables(v: u32) -> Weight;+    fn force_unstake(s: u32) -> Weight;+    fn cancel_deferred_slash(s: u32) -> Weight;+    fn payout_stakers(n: u32) -> Weight;+    fn payout_stakers_alive_controller(n: u32) -> Weight;+    fn rebond(l: u32) -> Weight;+    fn set_history_depth(e: u32) -> Weight;+    fn reap_stash(s: u32) -> Weight;+    fn new_era(v: u32, n: u32) -> Weight;+    fn do_slash(l: u32) -> Weight;+    fn payout_all(v: u32, n: u32) -> Weight;+    fn submit_solution_initial(v: u32, n: u32, a: u32, w: u32) -> Weight;+    fn submit_solution_better(v: u32, n: u32, a: u32, w: u32) -> Weight;+    fn submit_solution_weaker(v: u32, n: u32) -> Weight;+}++impl WeightInfo for () {+    fn bond(_u: u32) -> Weight {+        1_000_000_000+    }+    fn bond_extra(_u: u32) -> Weight {+        1_000_000_000+    }+    fn unbond(_u: u32) -> Weight {+        1_000_000_000+    }+    fn withdraw_unbonded_update(_s: u32) -> Weight {+        1_000_000_000+    }+    fn withdraw_unbonded_kill(_s: u32) -> Weight {+        1_000_000_000+    }+    fn validate(_u: u32) -> Weight {+        1_000_000_000+    }+    fn nominate(_n: u32) -> Weight {+        1_000_000_000+    }+    fn chill(_u: u32) -> Weight {+        1_000_000_000+    }+    fn set_payee(_u: u32) -> Weight {+        1_000_000_000+    }+    fn set_controller(_u: u32) -> Weight {+        1_000_000_000+    }+    fn set_validator_count(_c: u32) -> Weight {+        1_000_000_000+    }+    fn force_no_eras(_i: u32) -> Weight {+        1_000_000_000+    }+    fn force_new_era(_i: u32) -> Weight {+        1_000_000_000+    }+    fn force_new_era_always(_i: u32) -> Weight {+        1_000_000_000+    }+    fn set_invulnerables(_v: u32) -> Weight {+        1_000_000_000+    }+    fn force_unstake(_s: u32) -> Weight {+        1_000_000_000+    }+    fn cancel_deferred_slash(_s: u32) -> Weight {+        1_000_000_000+    }+    fn payout_stakers(_n: u32) -> Weight {+        1_000_000_000+    }+    fn payout_stakers_alive_controller(_n: u32) -> Weight {+        1_000_000_000+    }+    fn rebond(_l: u32) -> Weight {+        1_000_000_000+    }+    fn set_history_depth(_e: u32) -> Weight {+        1_000_000_000+    }+    fn reap_stash(_s: u32) -> Weight {+        1_000_000_000+    }+    fn new_era(_v: u32, _n: u32) -> Weight {+        1_000_000_000+    }+    fn do_slash(_l: u32) -> Weight {+        1_000_000_000+    }+    fn payout_all(_v: u32, _n: u32) -> Weight {+        1_000_000_000+    }+    fn submit_solution_initial(_v: u32, _n: u32, _a: u32, _w: u32) -> Weight {+        1_000_000_000+    }+    fn submit_solution_better(_v: u32, _n: u32, _a: u32, _w: u32) -> Weight {+        1_000_000_000+    }+    fn submit_solution_weaker(_v: u32, _n: u32) -> Weight {+        1_000_000_000+    }+}+ pub trait Trait:     frame_system::Trait + SendTransactionTypes<Call<Self>> + pallet_babe::Trait + IdentityTrait {     /// The staking balance.-    type Currency: LockableCurrency<Self::AccountId, Moment = Self::BlockNumber>-        + BlockRewardsReserveCurrency<BalanceOf<Self>, NegativeImbalanceOf<Self>>;+    type Currency: LockableCurrency<Self::AccountId, Moment = Self::BlockNumber>;

Ah, I see; let's bring it up on the grooming/standup. :)

Centril

comment created time in 5 days

PullRequestReviewEvent

push eventPolymathNetwork/Polymesh

Mazdak Farrokhzad

commit sha c8d38b8070f93f0524ea16e19a867132654f2aa6

mesh-1255: copy-in staking/src

view details

push time in 5 days

push eventPolymathNetwork/Polymesh

Mazdak Farrokhzad

commit sha 078fe80a20ea0fb129aedc7fb186890567ac4a0d

Schema: fix `Vote`'s definition due to changes (#622)

view details

Joel Moore

commit sha 03a92abc24d1c06324581a43156e5260830719de

Mesh 1106/reserve currency ticker symbols on genesis (#598) * added country currencies json file * working on reserving currency tickers * made change to chain spec and asset module * added currency symbols to chain_spec and made minor changes * made changes to chain_spec and asset module * added FiatTickerReservation Systematic User * fixed linting issue * created function for currency symbol conversion in chain_spec and made minor changes * minor change * fixed linting issue * minor change * moved FiatCurrency Struct to chain_spec and optimized currency_codes function * minor changes and linting * aded POLY and POLYX to currency_symbols file * Empty commit to trigger build * rerun CI * minor changes * minor change Co-authored-by: Claus Strommer <claus@polymath.network> Co-authored-by: poly-auto-merge[bot] <65769705+poly-auto-merge[bot]@users.noreply.github.com>

view details

Mazdak Farrokhzad

commit sha 85017a18cafc84863688521f2577b8c849c95ed5

AssetIdentifier::isin: remove allocation (#621) Co-authored-by: Adam Dossa <adam.dossa@gmail.com>

view details

Mazdak Farrokhzad

commit sha 807d651f2fa689668c7d38f3ac501745e5e5814d

mesh-1255: copy-in staking/fuzzer

view details

Mazdak Farrokhzad

commit sha 56c3a0897a2df0ab6281c9ffe29ff9faf4f11b99

mesh-1255: copy-in staking/reward-curve

view details

Mazdak Farrokhzad

commit sha d0aaf31bfe3f254018076450fa503469639c2dd6

mesh-1255: un-copy 'reward-curve' crate

view details

Mazdak Farrokhzad

commit sha 20517f1f53775fcff205f19df183416a6c0b4c90

mesh-1255: copy-in staking/src

view details

push time in 5 days

Pull request review commentPolymathNetwork/Polymesh

MESH-1255/Staking: Pull in some substrate-rc6 changes

 pub mod weight {     } } +pub trait WeightInfo {+    fn bond(u: u32) -> Weight;+    fn bond_extra(u: u32) -> Weight;+    fn unbond(u: u32) -> Weight;+    fn withdraw_unbonded_update(s: u32) -> Weight;+    fn withdraw_unbonded_kill(s: u32) -> Weight;+    fn validate(u: u32) -> Weight;+    fn nominate(n: u32) -> Weight;+    fn chill(u: u32) -> Weight;+    fn set_payee(u: u32) -> Weight;+    fn set_controller(u: u32) -> Weight;+    fn set_validator_count(c: u32) -> Weight;+    fn force_no_eras(i: u32) -> Weight;+    fn force_new_era(i: u32) -> Weight;+    fn force_new_era_always(i: u32) -> Weight;+    fn set_invulnerables(v: u32) -> Weight;+    fn force_unstake(s: u32) -> Weight;+    fn cancel_deferred_slash(s: u32) -> Weight;+    fn payout_stakers(n: u32) -> Weight;+    fn payout_stakers_alive_controller(n: u32) -> Weight;+    fn rebond(l: u32) -> Weight;+    fn set_history_depth(e: u32) -> Weight;+    fn reap_stash(s: u32) -> Weight;+    fn new_era(v: u32, n: u32) -> Weight;+    fn do_slash(l: u32) -> Weight;+    fn payout_all(v: u32, n: u32) -> Weight;+    fn submit_solution_initial(v: u32, n: u32, a: u32, w: u32) -> Weight;+    fn submit_solution_better(v: u32, n: u32, a: u32, w: u32) -> Weight;+    fn submit_solution_weaker(v: u32, n: u32) -> Weight;+}++impl WeightInfo for () {+    fn bond(_u: u32) -> Weight {+        1_000_000_000+    }+    fn bond_extra(_u: u32) -> Weight {+        1_000_000_000+    }+    fn unbond(_u: u32) -> Weight {+        1_000_000_000+    }+    fn withdraw_unbonded_update(_s: u32) -> Weight {+        1_000_000_000+    }+    fn withdraw_unbonded_kill(_s: u32) -> Weight {+        1_000_000_000+    }+    fn validate(_u: u32) -> Weight {+        1_000_000_000+    }+    fn nominate(_n: u32) -> Weight {+        1_000_000_000+    }+    fn chill(_u: u32) -> Weight {+        1_000_000_000+    }+    fn set_payee(_u: u32) -> Weight {+        1_000_000_000+    }+    fn set_controller(_u: u32) -> Weight {+        1_000_000_000+    }+    fn set_validator_count(_c: u32) -> Weight {+        1_000_000_000+    }+    fn force_no_eras(_i: u32) -> Weight {+        1_000_000_000+    }+    fn force_new_era(_i: u32) -> Weight {+        1_000_000_000+    }+    fn force_new_era_always(_i: u32) -> Weight {+        1_000_000_000+    }+    fn set_invulnerables(_v: u32) -> Weight {+        1_000_000_000+    }+    fn force_unstake(_s: u32) -> Weight {+        1_000_000_000+    }+    fn cancel_deferred_slash(_s: u32) -> Weight {+        1_000_000_000+    }+    fn payout_stakers(_n: u32) -> Weight {+        1_000_000_000+    }+    fn payout_stakers_alive_controller(_n: u32) -> Weight {+        1_000_000_000+    }+    fn rebond(_l: u32) -> Weight {+        1_000_000_000+    }+    fn set_history_depth(_e: u32) -> Weight {+        1_000_000_000+    }+    fn reap_stash(_s: u32) -> Weight {+        1_000_000_000+    }+    fn new_era(_v: u32, _n: u32) -> Weight {+        1_000_000_000+    }+    fn do_slash(_l: u32) -> Weight {+        1_000_000_000+    }+    fn payout_all(_v: u32, _n: u32) -> Weight {+        1_000_000_000+    }+    fn submit_solution_initial(_v: u32, _n: u32, _a: u32, _w: u32) -> Weight {+        1_000_000_000+    }+    fn submit_solution_better(_v: u32, _n: u32, _a: u32, _w: u32) -> Weight {+        1_000_000_000+    }+    fn submit_solution_weaker(_v: u32, _n: u32) -> Weight {+        1_000_000_000+    }+}+ pub trait Trait:     frame_system::Trait + SendTransactionTypes<Call<Self>> + pallet_babe::Trait + IdentityTrait {     /// The staking balance.-    type Currency: LockableCurrency<Self::AccountId, Moment = Self::BlockNumber>-        + BlockRewardsReserveCurrency<BalanceOf<Self>, NegativeImbalanceOf<Self>>;+    type Currency: LockableCurrency<Self::AccountId, Moment = Self::BlockNumber>;

If things compile without the extra bound then it must be unused.

Centril

comment created time in 5 days

PullRequestReviewEvent

push eventPolymathNetwork/Polymesh

Mazdak Farrokhzad

commit sha f68ec87b165f6207e789a098be9626517c6facde

fixup

view details

push time in 5 days

push eventPolymathNetwork/Polymesh

Mazdak Farrokhzad

commit sha 5c2a33ad76c247a2b7ce4aa0926f251105d75789

fixup

view details

push time in 5 days

push eventPolymathNetwork/Polymesh

Mazdak Farrokhzad

commit sha 666672266ccd5abca7e985109db098df60d87948

fixup

view details

push time in 5 days

push eventPolymathNetwork/Polymesh

Mazdak Farrokhzad

commit sha d0793e8bea2ad1df319cf0914f4332627b84b90b

fixup

view details

push time in 5 days

push eventPolymathNetwork/Polymesh

Mazdak Farrokhzad

commit sha 1ee8617955517cc3ffdf22f56f65d3124c3a2884

fixup

view details

push time in 5 days

push eventPolymathNetwork/Polymesh

Mazdak Farrokhzad

commit sha 4ca20d3e2441bbc1ba8be83356f9b18a5f4edb32

fixup

view details

Mazdak Farrokhzad

commit sha 08b09d4209c4e04e55721ce3d3c48c7f236c64a4

fixup

view details

push time in 5 days

Pull request review commentPolymathNetwork/Polymesh

MESH-1255/Staking: Pull in some substrate-rc6 changes

 decl_module! {             ).expect(                 "An unsigned solution can only be submitted by validators; A validator should \                 always produce correct solutions, else this block should not be imported, thus \-                effectively depriving the validators from their authoring reward. Hence, this panic-                is expected."+				effectively depriving the validators from their authoring reward. Hence, this panic

Odd; these didn't show up in VSCode :/

Centril

comment created time in 5 days

PullRequestReviewEvent

delete branch PolymathNetwork/Polymesh

delete branch : MESH-1261

delete time in 5 days

Pull request review commentPolymathNetwork/Polymesh

MESH-1255/Transaction Payment: Pull in some substrate-rc6 changes

 where         info: &DispatchInfoOf<T::Call>,         len: usize,     ) -> Result<(BalanceOf<T>, Option<NegativeImbalanceOf<T>>), TransactionValidityError> {-        let fee = Module::<T>::compute_fee(len as u32, info, 0u32.into());+        let tip = self.0;+        let fee = Module::<T>::compute_fee(len as u32, info, tip);          // Only mess with balances if fee is not zero.         if fee.is_zero() {             return Ok((fee, None));         }          if let Some(payer_key) = T::CddHandler::get_valid_payer(call, &who)? {-            let imbalance = T::Currency::withdraw(-                &payer_key,-                fee,-                WithdrawReason::TransactionPayment.into(),-                ExistenceRequirement::KeepAlive,-            )-            .map_err(|_| InvalidTransaction::Payment)?;+            let reason = if tip.is_zero() {+                WithdrawReason::TransactionPayment.into()+            } else {+                WithdrawReason::TransactionPayment | WithdrawReason::Tip

Yep, already fixed :)

Centril

comment created time in 5 days

PullRequestReviewEvent

push eventPolymathNetwork/Polymesh

Mazdak Farrokhzad

commit sha 21bc72820b17986d73130b4823beaa1056246f36

mesh-1255/transaction-payment: bring in some rc6 changes

view details

push time in 5 days

push eventPolymathNetwork/Polymesh

Mazdak Farrokhzad

commit sha c6a297341aa3c3e4e29b4f8d3d5d6196816379a9

fixup

view details

push time in 5 days

Pull request review commentPolymathNetwork/Polymesh

MESH-1255/Transaction Payment: Pull in some substrate-rc6 changes

 use sp_runtime::{         InvalidTransaction, TransactionPriority, TransactionValidity, TransactionValidityError,         ValidTransaction,     },-    FixedI128, FixedPointNumber, FixedPointOperand, Perquintill,+    FixedPointNumber, FixedPointOperand, FixedU128, Perquintill, }; use sp_std::prelude::*;  /// Fee multiplier.-pub type Multiplier = FixedI128;+pub type Multiplier = FixedU128;

We decided it was not necessary on a meeting.

Centril

comment created time in 5 days

PullRequestReviewEvent

push eventPolymathNetwork/Polymesh

Mazdak Farrokhzad

commit sha dc11a4b432ec91d29741a40eac0fb04d09100f86

fixup

view details

push time in 5 days

push eventPolymathNetwork/Polymesh

Mazdak Farrokhzad

commit sha ed87b2a8c07576b79aced6508e6634a1145e9a9f

fixup

view details

push time in 5 days

push eventPolymathNetwork/Polymesh

Mazdak Farrokhzad

commit sha 81b5bee08d1bdd525db000eb1b5c5f6797a252ae

fixup

view details

push time in 5 days

push eventPolymathNetwork/Polymesh

Mazdak Farrokhzad

commit sha be5530f13f52eb92489b81be6dbcd283c51a7354

fixup

view details

push time in 5 days

push eventPolymathNetwork/Polymesh

Mazdak Farrokhzad

commit sha ec43fbf3187e026ae800bb59a7677ddd789630fa

fixup

view details

push time in 5 days

push eventPolymathNetwork/Polymesh

Mazdak Farrokhzad

commit sha c9c0aa018d1c6bae89e86c66870eeb7658ecd511

fixup

view details

push time in 5 days

Pull request review commentPolymathNetwork/Polymesh

Verify zk proof during claim addition

 use crate::{-    scalar_blake2_from_bytes, CddId, Claim, Context, IdentityId, InvestorZKProofData, Proposition,-    Ticker,+    scalar_blake2_from_bytes, CddId, Claim, IdentityId, InvestorZKProofData, Scope, Ticker, }; use cryptography::claim_proofs::ProofPublicKey; use curve25519_dalek::{ristretto::CompressedRistretto, scalar::Scalar};  // ZKProofs claims // ========================================================= -/// Proposition that checks if any of its internal claims exists in context.+/// Data structure used to check if any of its internal claims exist in context. #[derive(Clone)] #[cfg_attr(feature = "std", derive(Debug))]-pub struct ValidProofOfInvestorProposition {-    /// The Investor proof should be associated to this ticker.-    pub ticker: Ticker,-}--impl Proposition for ValidProofOfInvestorProposition {-    /// Evaluate proposition against `context`.-    fn evaluate(&self, context: &Context) -> bool {-        context-            .claims-            .iter()-            .any(|claim| self.evaluate_claim(claim, context))-    }-}+pub struct ValidProofOfInvestor; -impl ValidProofOfInvestorProposition {+impl ValidProofOfInvestor {     /// Evaluates if the claim is a valid proof.-    fn evaluate_claim(&self, claim: &Claim, context: &Context) -> bool {+    pub fn evaluate_claim(claim: &Claim, id: &IdentityId) -> bool {         match claim {-            Claim::InvestorZKProof(ref _ticker_scope, ref scope_id, ref cdd_id, ref proof) => {-                let message = InvestorZKProofData::make_message(&context.id, &self.ticker);-                Self::verify_proof(cdd_id, &context.id, scope_id, &self.ticker, proof, &message)+            Claim::InvestorZKProof(ref scope, scope_id, cdd_id, proof) => {+                if let Scope::Ticker(ticker) = scope {+                    let message = InvestorZKProofData::make_message(id, ticker);+                    return Self::verify_proof(cdd_id, id, scope_id, ticker, proof, &message);+                }+                false
            Claim::InvestorZKProof(Scope::Ticker(ticker), scope_id, cdd_id, proof) => {
                let message = InvestorZKProofData::make_message(id, ticker);
                return Self::verify_proof(cdd_id, id, scope_id, ticker, proof, &message);
satyamakgec

comment created time in 5 days

PullRequestReviewEvent

Pull request review commentPolymathNetwork/Polymesh

MESH-1255/Transaction Payment: Pull in some substrate-rc6 changes

 where         info: &DispatchInfoOf<T::Call>,         len: usize,     ) -> Result<(BalanceOf<T>, Option<NegativeImbalanceOf<T>>), TransactionValidityError> {-        let fee = Module::<T>::compute_fee(len as u32, info, 0u32.into());+        let tip = self.0;

@satyamakgec So AIUI, we want to revert all the changes in this function?

Centril

comment created time in 6 days

PullRequestReviewEvent

pull request commentPolymathNetwork/Polymesh

[WIP] MESH-1255/im-online: Pull in some substrate-rc6 changes

The diff from https://github.com/paritytech/substrate/compare/v2.0.0-rc4...v2.0.0-rc6#diff-8fd54810abd2bd459e2decb6bffe9865 indicates that there were no useful/functional changes from rc4..rc6 in im-online, so I'll close this.

Centril

comment created time in 6 days

push eventPolymathNetwork/Polymesh

Mazdak Farrokhzad

commit sha 6a0441ca2f8fbb6888af09825f0859eda878d664

fixup

view details

push time in 6 days

push eventPolymathNetwork/Polymesh

Mazdak Farrokhzad

commit sha 955b8280e167aa9bbd75f6cc22848a2654dda6ab

fixup

view details

push time in 6 days

push eventPolymathNetwork/Polymesh

Mazdak Farrokhzad

commit sha 82542b45f99e0bf9c2e9af9960c3870894bab9cf

fixup

view details

push time in 6 days

create barnchPolymathNetwork/Polymesh

branch : mesh-1255-im-online

created branch time in 6 days

Pull request review commentPolymathNetwork/Polymesh

MESH-1255/Transaction Payment: Pull in some substrate-rc6 changes

 use sp_runtime::{         InvalidTransaction, TransactionPriority, TransactionValidity, TransactionValidityError,         ValidTransaction,     },-    FixedI128, FixedPointNumber, FixedPointOperand, Perquintill,+    FixedPointNumber, FixedPointOperand, FixedU128, Perquintill, }; use sp_std::prelude::*;  /// Fee multiplier.-pub type Multiplier = FixedI128;+pub type Multiplier = FixedU128;

This is used in the only storage item; should we write a migration?

Centril

comment created time in 6 days

PullRequestReviewEvent
more