Skip to content
This repository has been archived by the owner on Feb 21, 2024. It is now read-only.

fix: do not burn remaining after matcher payout #105

Merged
merged 1 commit into from
Jun 22, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion pallets/marketplace/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -744,7 +744,8 @@ pub mod pallet {

match requirements.instant_match {
Some(sources) => {
Self::process_matching(once(&Match {
// ignore remaining rewards; do not pay out the matcher which is the same as the one registering
gitsimon marked this conversation as resolved.
Show resolved Hide resolved
let _ = Self::process_matching(once(&Match {
job_id: job_id.clone(),
sources,
}))?;
Expand Down
14 changes: 10 additions & 4 deletions pallets/marketplace/src/mock.rs
Original file line number Diff line number Diff line change
Expand Up @@ -266,16 +266,22 @@ impl<T: Config + mock_pallet::Config, Budget: JobBudget<T>> RewardManager<T>
}

fn pay_matcher_reward(
rewards: Vec<(JobId<T::AccountId>, <T as Config>::Balance)>,
remaining_rewards: Vec<(JobId<T::AccountId>, <T as Config>::Balance)>,
matcher: &T::AccountId,
) -> Result<(), DispatchError> {
mock_pallet::Pallet::deposit_event(mock_pallet::Event::<T>::PayMatcherReward((
rewards.clone(),
remaining_rewards.clone(),
matcher.clone(),
)));
for (job_id, remaining_reward) in rewards.into_iter() {
Budget::unreserve(&job_id, remaining_reward).unwrap();

let mut matcher_reward: T::Balance = 0u8.into();
for (job_id, remaining_reward) in remaining_rewards.into_iter() {
let matcher_fee = FeeManagerImpl::get_matcher_percentage().mul_floor(remaining_reward);
Budget::unreserve(&job_id, matcher_fee)
.map_err(|_| DispatchError::Other("Severe Error: JobBudget::unreserve failed"))?;
matcher_reward += matcher_fee;
}

Ok(())
}

Expand Down
19 changes: 10 additions & 9 deletions pallets/marketplace/src/payments.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ pub trait RewardManager<T: frame_system::Config + Config> {
target: &T::AccountId,
) -> Result<(), DispatchError>;
fn pay_matcher_reward(
rewards: Vec<(JobId<T::AccountId>, <T as Config>::Balance)>,
remaining_rewards: Vec<(JobId<T::AccountId>, <T as Config>::Balance)>,
matcher: &T::AccountId,
) -> Result<(), DispatchError>;
fn refund(job_id: &JobId<T::AccountId>) -> T::Balance;
Expand All @@ -51,7 +51,7 @@ impl<T: frame_system::Config + Config> RewardManager<T> for () {
}

fn pay_matcher_reward(
_rewards: Vec<(JobId<T::AccountId>, <T as Config>::Balance)>,
_remaining_rewards: Vec<(JobId<T::AccountId>, <T as Config>::Balance)>,
_matcher: &T::AccountId,
) -> Result<(), DispatchError> {
Ok(())
Expand Down Expand Up @@ -157,26 +157,27 @@ where
}

fn pay_matcher_reward(
rewards: Vec<(JobId<T::AccountId>, T::Balance)>,
remaining_rewards: Vec<(JobId<T::AccountId>, T::Balance)>,
matcher: &T::AccountId,
) -> Result<(), DispatchError> {
let matcher_fee_percentage = AssetSplit::get_matcher_percentage(); // TODO: fee will be indexed by version in the future

let mut reward: T::Balance = 0u8.into();
for (job_id, remaining_reward) in rewards.into_iter() {
Budget::unreserve(&job_id, remaining_reward)
let mut matcher_reward: T::Balance = 0u8.into();
for (job_id, remaining_reward) in remaining_rewards.into_iter() {
let matcher_fee = matcher_fee_percentage.mul_floor(remaining_reward);
Budget::unreserve(&job_id, matcher_fee)
.map_err(|_| DispatchError::Other("Severe Error: JobBudget::unreserve failed"))?;
reward += matcher_fee_percentage.mul_floor(remaining_reward);
matcher_reward += matcher_fee;
}

let pallet_account: T::AccountId = <T as Config>::PalletId::get().into_account_truncating();

// Extract fee from the matcher reward
let fee_percentage = AssetSplit::get_fee_percentage(); // TODO: fee will be indexed by version in the future
let fee = fee_percentage.mul_floor(reward);
let fee = fee_percentage.mul_floor(matcher_reward);

// Subtract the fee from the reward
let reward_after_fee = reward - fee;
let reward_after_fee = matcher_reward - fee;

// Transfer fees to Acurast fees manager account
let fee_pallet_account: T::AccountId = AssetSplit::pallet_id().into_account_truncating();
Expand Down
28 changes: 24 additions & 4 deletions pallets/marketplace/src/tests.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
#![cfg(test)]

use frame_support::{assert_err, assert_ok, traits::Hooks};
use pallet_acurast::MultiOrigin;
use sp_runtime::Permill;

use pallet_acurast::MultiOrigin;
use pallet_acurast::{
utils::validate_and_extract_attestation, JobModules, JobRegistrationFor, Schedule,
};
use reputation::{BetaReputation, ReputationEngine};

use crate::payments::JobBudget;
use crate::{
mock::*, AdvertisementRestriction, Assignment, Error, ExecutionResult, JobStatus, Match, SLA,
};
Expand Down Expand Up @@ -99,14 +100,19 @@ fn test_match() {
AcurastMarketplace::stored_advertisement_pricing(processor_account_id())
);

let job_id1 = (MultiOrigin::Acurast(alice_account_id()), initial_job_id + 1);
let job_id2 = (MultiOrigin::Acurast(alice_account_id()), initial_job_id + 2);

assert_ok!(Acurast::register(
RuntimeOrigin::signed(alice_account_id()).into(),
registration1.clone(),
));
assert_eq!(12_000_000, AcurastMarketplace::reserved(&job_id1));
assert_ok!(Acurast::register(
RuntimeOrigin::signed(alice_account_id()).into(),
registration2.clone(),
));
assert_eq!(12_000_000, AcurastMarketplace::reserved(&job_id2));
assert_eq!(
Some(JobStatus::Open),
AcurastMarketplace::stored_job_status(
Expand All @@ -119,15 +125,13 @@ fn test_match() {
AcurastMarketplace::stored_storage_capacity(processor_account_id())
);

let job_id1 = (MultiOrigin::Acurast(alice_account_id()), initial_job_id + 1);
let job_match1 = Match {
job_id: job_id1.clone(),
sources: vec![PlannedExecution {
source: processor_account_id(),
start_delay: 0,
}],
};
let job_id2 = (MultiOrigin::Acurast(alice_account_id()), initial_job_id + 2);
let job_match2 = Match {
job_id: job_id2.clone(),
sources: vec![PlannedExecution {
Expand All @@ -150,6 +154,9 @@ fn test_match() {
Some(60_000),
AcurastMarketplace::stored_storage_capacity(processor_account_id())
);
// matcher got payed out already so job budget decreased
assert_eq!(11804000, AcurastMarketplace::reserved(&job_id1));
assert_eq!(11804000, AcurastMarketplace::reserved(&job_id2));

assert_ok!(AcurastMarketplace::acknowledge_match(
RuntimeOrigin::signed(processor_account_id()).into(),
Expand All @@ -171,6 +178,8 @@ fn test_match() {
job_id1.clone(),
ExecutionResult::Success(operation_hash())
));
// job budget decreased by reward worth one execution
assert_eq!(6784000, AcurastMarketplace::reserved(&job_id1));
// average reward only updated at end of job
assert_eq!(None, AcurastMarketplace::average_reward());
// reputation still ~50%
Expand Down Expand Up @@ -211,11 +220,15 @@ fn test_match() {
job_id1.clone(),
ExecutionResult::Success(operation_hash())
));
// job budget decreased by reward worth one execution
assert_eq!(1764000, AcurastMarketplace::reserved(&job_id1));

// pretend time moved on
later(registration1.schedule.end_time + 1);
assert_eq!(4, System::block_number());

assert_eq!(1764000, AcurastMarketplace::reserved(&job_id1));

assert_ok!(AcurastMarketplace::finalize_job(
RuntimeOrigin::signed(processor_account_id()).into(),
job_id1.clone()
Expand Down Expand Up @@ -257,6 +270,10 @@ fn test_match() {
None,
AcurastMarketplace::stored_job_status(&job_id1.0, &job_id1.1),
);
// the remaining budget got refunded
assert_eq!(0, AcurastMarketplace::reserved(&job_id1));
// but job2 still have full budget
assert_eq!(11804000, AcurastMarketplace::reserved(&job_id2));

assert_eq!(
events(),
Expand Down Expand Up @@ -346,7 +363,10 @@ fn test_match() {
}
)),
RuntimeEvent::AcurastMarketplace(crate::Event::JobFinalized(job_id1.clone())),
RuntimeEvent::MockPallet(mock_pallet::Event::RefundReward((job_id1.clone(), 0,))),
RuntimeEvent::MockPallet(mock_pallet::Event::RefundReward((
job_id1.clone(),
1764000
))),
RuntimeEvent::AcurastMarketplace(crate::Event::JobFinalized(job_id1.clone(),)),
]
);
Expand Down