git.delta.rocks / unique-network / refs/commits / 18ed55433818

difftreelog

Merge branch 'develop' into tests/eth-helpers

Max Andreev2022-12-21parents: #994aeb1 #ccd7200.patch.diff
in: master

2 files changed

modifiedREADME.mddiffbeforeafterboth
before · README.md
1# Unique Parachain23## Project Description45The Unique Pallet is the core of NFT functionality. Like ERC-721 standard in Ethereum ecosystem, this pallet provides the6basement for creating collections of unique non-divisible things, also called Non Fungible Tokens (NFTs), minting NFT of7a given Collection, and managing their ownership.89The pallet also enables storing NFT properties. Though (according to ERC-721) NFT properties belong to logic of a10concrete application that operates a Collection, so purposefully the NFT Tracking Module does not have any knowledge11about properties except their byte size leaving application logic out to be controlled by Smart Contracts.1213The Unique Chain also provides:1415-   Smart Contracts Pallet and example smart contract that interacts with Unique Runtime16-   ERC-1155 Functionality (currently PoC as Re-Fungible tokens, i.e. items that are still unique, but that can be split17    between multiple users)18-   Variety of economic options for dapp producers to choose from to create freemium games and other ways to attract19    users. As a step one, we implemented an economic model when a collection sponsor can be set to pay for collection20    Transfer transactions.2122Wider Unique Ecosystem (most of it was developed during Hackusama):2324-   [SubstraPunks Game hosted on IPFS](https://github.com/UniqueNetwork/substrapunks)25-   [Unique Wallet and UI](https://wallet.unique.network)26-   [NFT Asset for Unity Framework](https://github.com/usetech-llc/nft_unity)2728Please see our [walk-through instructions](doc/hackusama_walk_through.md) to try everything out!2930## Application Development3132If you are building an application that operates NFT tokens, use [this document](doc/application_development.md).333435## Building3637Building Unique chain requires special versions of Rust and toolchain. We don't use the most recent versions of everything38so that we can keep the builds stable.39401. Install Rust:4142```bash43sudo apt-get install git curl libssl-dev llvm pkg-config libclang-dev clang make cmake protobuf-compiler44curl https://sh.rustup.rs -sSf | sh45```46472. Remove all installed toolchains with `rustup toolchain list` and `rustup toolchain uninstall <toolchain>`.48493. Install toolchain nightly-2022-10-09 and make it default:5051```bash52rustup toolchain install nightly-2022-10-0953rustup default nightly-2022-10-0954```55564. Add wasm target for nightly toolchain:5758```bash59rustup target add wasm32-unknown-unknown --toolchain nightly-2022-10-0960```61625. Build:6364Opal65```bash66cargo build --release67```68Quartz69```bash70cargo build --features=quartz-runtime --release71```72Unique73```bash74cargo build --features=unique-runtime --release75```7677## Building as Parachain locally7879Note: checkout this project and all related projects (see below) in the sibling folders (both under the same folder)8081### Polkadot launch utility8283```84git clone https://github.com/UniqueNetwork/polkadot-launch.git85git checkout feature/runtime-upgrade-testing86```8788### Build relay8990```91git clone https://github.com/paritytech/polkadot.git92cd polkadot93git checkout release-v0.9.3394cargo build --release95```9697### Build Unique parachain9899Run in the root of this project:100```101cargo build --release102```103104### Build Acala parachain (optional, full config only)105106```107git clone https://github.com/AcalaNetwork/Acala108cd Acala109git checkout 54db3acd409a0b787f116f20e163a3b24101ce38110make build-release111```112113## Running as Parachain locally114115```116./launch-testnet.sh117```118119Optional, full setup with Acala and Statemint120```121./launch-testnet-full.sh122```123124## Run Integration Tests1251261. Install all needed dependecies127```128cd tests129yarn install130```1311322. Run tests133```134yarn test135```136137138## Code Formatting139140### Apply formatting and clippy fixes141```bash142cargo clippy143cargo fmt144```145146### Format tests147```bash148pushd tests && yarn fix ; popd149```150151### Check code style in tests152```bash153cd tests && yarn eslint --ext .ts,.js src/154```155156157## Karura token transfer158159To get started, you need to open inbound and outbound hrmp channels.160161### Next, we need to register our asset at Karura.162```163assetRegistry -> registerForeignAsset(location, metadata)164location:165	V0(X2(Parent, Parachain(PARA_ID)))166metadata:167	name         QTZ168	symbol       QTZ169	decimals     18170minimalBalance	 1171```172173### Next, we can send tokens from Quartz to Karura:174```175polkadotXcm -> reserveTransferAssets176dest:177	V0(X2(Parent, Parachain(<KARURA_PARA_ID>)))178beneficiary:179	X1(AccountId(Any, <ACCOUNT>))180assets:181	V1(Concrete(0,Here), Fungible(<AMOUNT>))182feeAssetItem:183	0184weightLimit:185	<LIMIT>186```187188The result will be displayed in ChainState189tokens -> accounts190191### To send tokens from Karura to Quartz:192```193xtokens -> transfer194195currencyId:196	ForeignAsset197		<TOKEN_ID>198199amount:200		<AMOUNT>201dest:202	V1203	(204		Parents:1,205		X2(Parachain(<KARURA_PARA_ID>), AccountId(Any, <ACCOUNT>)206	)207destWeight:208	<WEIGHT>209```
after · README.md
1# Unique Parachain23## Project Description45The Unique Pallet is the core of NFT functionality. Like ERC-721 standard in Ethereum ecosystem, this pallet provides the6basement for creating collections of unique non-divisible things, also called Non Fungible Tokens (NFTs), minting NFT of7a given Collection, and managing their ownership.89The pallet also enables storing NFT properties. Though (according to ERC-721) NFT properties belong to logic of a10concrete application that operates a Collection, so purposefully the NFT Tracking Module does not have any knowledge11about properties except their byte size leaving application logic out to be controlled by Smart Contracts.1213The Unique Chain also provides:1415-   Smart Contracts Pallet and example smart contract that interacts with Unique Runtime16-   ERC-1155 Functionality (currently PoC as Re-Fungible tokens, i.e. items that are still unique, but that can be split17    between multiple users)18-   Variety of economic options for dapp producers to choose from to create freemium games and other ways to attract19    users. As a step one, we implemented an economic model when a collection sponsor can be set to pay for collection20    Transfer transactions.2122Wider Unique Ecosystem (most of it was developed during Hackusama):2324-   [SubstraPunks Game hosted on IPFS](https://github.com/UniqueNetwork/substrapunks)25-   [Unique Wallet and UI](https://wallet.unique.network)26-   [NFT Asset for Unity Framework](https://github.com/usetech-llc/nft_unity)2728Please see our [walk-through instructions](doc/hackusama_walk_through.md) to try everything out!2930## Application Development3132If you are building an application that operates NFT tokens, use [this document](doc/application_development.md).333435## Building3637Building Unique chain requires special versions of Rust and toolchain. We don't use the most recent versions of everything38so that we can keep the builds stable.39401. Install Rust:4142```bash43sudo apt-get install git curl libssl-dev llvm pkg-config libclang-dev clang make cmake protobuf-compiler44curl https://sh.rustup.rs -sSf | sh45```46472. Remove all installed toolchains with `rustup toolchain list` and `rustup toolchain uninstall <toolchain>`.48493. Install toolchain nightly-2022-10-09 and make it default:5051```bash52rustup toolchain install nightly-2022-10-0953rustup default nightly-2022-10-0954```55564. Add wasm target for nightly toolchain:5758```bash59rustup target add wasm32-unknown-unknown --toolchain nightly-2022-10-0960```61625. Build:6364Opal65```bash66cargo build --release67```68Quartz69```bash70cargo build --features=quartz-runtime --release71```72Unique73```bash74cargo build --features=unique-runtime --release75```7677## Building as Parachain locally7879Note: checkout this project and all related projects (see below) in the sibling folders (both under the same folder)8081### Polkadot launch utility8283```84git clone https://github.com/UniqueNetwork/polkadot-launch.git85git checkout unique-network86```8788### Build relay8990```91git clone https://github.com/paritytech/polkadot.git92cd polkadot93git checkout release-v0.9.3394cargo build --release95```9697### Build Unique parachain9899Run in the root of this project:100```101cargo build --release102```103104### Build Acala parachain (optional, full config only)105106```107git clone https://github.com/AcalaNetwork/Acala108cd Acala109git checkout 54db3acd409a0b787f116f20e163a3b24101ce38110make build-release111```112113## Running as Parachain locally114115```116./launch-testnet.sh117```118119Optional, full setup with Acala and Statemint120```121./launch-testnet-full.sh122```123124## Run Integration Tests1251261. Install all needed dependecies127```128cd tests129yarn install130```1311322. Run tests133```134yarn test135```136137138## Code Formatting139140### Apply formatting and clippy fixes141```bash142cargo clippy143cargo fmt144```145146### Format tests147```bash148pushd tests && yarn fix ; popd149```150151### Check code style in tests152```bash153cd tests && yarn eslint --ext .ts,.js src/154```155156157## Karura token transfer158159To get started, you need to open inbound and outbound hrmp channels.160161### Next, we need to register our asset at Karura.162```163assetRegistry -> registerForeignAsset(location, metadata)164location:165	V0(X2(Parent, Parachain(PARA_ID)))166metadata:167	name         QTZ168	symbol       QTZ169	decimals     18170minimalBalance	 1171```172173### Next, we can send tokens from Quartz to Karura:174```175polkadotXcm -> reserveTransferAssets176dest:177	V0(X2(Parent, Parachain(<KARURA_PARA_ID>)))178beneficiary:179	X1(AccountId(Any, <ACCOUNT>))180assets:181	V1(Concrete(0,Here), Fungible(<AMOUNT>))182feeAssetItem:183	0184weightLimit:185	<LIMIT>186```187188The result will be displayed in ChainState189tokens -> accounts190191### To send tokens from Karura to Quartz:192```193xtokens -> transfer194195currencyId:196	ForeignAsset197		<TOKEN_ID>198199amount:200		<AMOUNT>201dest:202	V1203	(204		Parents:1,205		X2(Parachain(<KARURA_PARA_ID>), AccountId(Any, <ACCOUNT>)206	)207destWeight:208	<WEIGHT>209```
modifiedpallets/app-promotion/src/lib.rsdiffbeforeafterboth
--- a/pallets/app-promotion/src/lib.rs
+++ b/pallets/app-promotion/src/lib.rs
@@ -598,12 +598,20 @@
 			PreviousCalculatedRecord::<T>::set(None);
 
 			{
+				// Address handled in the last payout loop iteration (below)
 				let last_id = RefCell::new(None);
+				// Reward balance for the address in the iteration
 				let income_acc = RefCell::new(BalanceOf::<T>::default());
+				// Staked balance for the address in the iteration (before stake is recalculated)
 				let amount_acc = RefCell::new(BalanceOf::<T>::default());
 
-				// this closure is used to perform some of the actions if we break the loop because we reached the number of stakers for recalculation,
-				// but there were unrecalculated records in the storage.
+				// This closure is used to finalize handling single staker address in each of the two conditions: (1) when we break out of the payout
+				// loop because we reached the number of stakes for rewarding, (2) When all stakes by the single address are handled and the payout
+				// loop switches to handling the next staker address:
+				//   1. Transfer full reward amount to the payee
+				//   2. Lock the reward in staking lock
+				//   3. Update TotalStaked amount
+				//   4. Issue StakingRecalculation event
 				let flush_stake = || -> DispatchResult {
 					if let Some(last_id) = &*last_id.borrow() {
 						if !income_acc.borrow().is_zero() {
@@ -635,16 +643,27 @@
 					Ok(())
 				};
 
+				// Reward payment loop. Should loop for no more than config.max_stakers_per_calculation
+				// iterations in one extrinsic call
+				//
+				// stakers_number - keeps the remaining number of iterations (staker addresses to handle)
+				// next_recalc_block_for_stake - is taken from the state and stores the starting relay block from which reward should be paid out
+				// income_acc - stores the reward amount to pay to the staker address (accumulates over all address stake records)
 				while let Some((
 					(current_id, staked_block),
 					(amount, next_recalc_block_for_stake),
 				)) = storage_iterator.next()
 				{
+					// last_id is not equal current_id when we switch to handling a new staker address
+					// or just start handling the very first address. In the latter case last_id will be None and
+					// flush_stake will do nothing
 					if last_id.borrow().as_ref() != Some(&current_id) {
 						flush_stake()?;
 						*last_id.borrow_mut() = Some(current_id.clone());
 						stakers_number -= 1;
 					};
+
+					// Increase accumulated reward for current address and update current staking record, i.e. (address, staked_block) -> amount
 					if current_recalc_block >= next_recalc_block_for_stake {
 						*amount_acc.borrow_mut() += amount;
 						Self::recalculate_and_insert_stake(
@@ -659,8 +678,10 @@
 						);
 					}
 
+					// Break out if we reached the address limit
 					if stakers_number == 0 {
 						if storage_iterator.next().is_some() {
+							// Save the last calculated record to pick up in the next extrinsic call
 							PreviousCalculatedRecord::<T>::set(Some((current_id, staked_block)));
 						}
 						break;
@@ -834,6 +855,8 @@
 		income - base
 	}
 
+	/// Get relay block number rounded down to multiples of config.recalculation_interval.
+	/// We need it to reward stakers in integer parts of recalculation_interval
 	fn get_current_recalc_block(
 		current_relay_block: T::BlockNumber,
 		config: &PalletConfiguration<T>,