Struct clockwork_network_program::state::Fee
source · pub struct Fee {
pub distributable_balance: u64,
pub worker: Pubkey,
}
Expand description
Escrows the lamport balance owed to a particular worker.
Fields§
§distributable_balance: u64
The number of lamports that are distributable for this epoch period.
worker: Pubkey
The worker who received the fees.
Implementations§
source§impl Fee
impl Fee
sourcepub fn pubkey(worker: Pubkey) -> Pubkey
pub fn pubkey(worker: Pubkey) -> Pubkey
Derive the pubkey of a fee account.
Examples found in repository?
More examples
src/instructions/registry_epoch_kickoff.rs (line 79)
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117
pub fn handler(ctx: Context<RegistryEpochKickoff>) -> Result<ThreadResponse> {
// Get accounts.
let config = &ctx.accounts.config;
let registry = &mut ctx.accounts.registry;
let snapshot = &ctx.accounts.snapshot;
let thread = &ctx.accounts.thread;
// Lock the registry
registry.locked = true;
// Setup the next kickoff instruction to use the next snapshot.
let kickoff_instruction = Some(InstructionData {
program_id: crate::ID,
accounts: vec![
AccountMetaData::new_readonly(config.key(), false),
AccountMetaData::new(registry.key(), false),
AccountMetaData::new_readonly(
Snapshot::pubkey(snapshot.id.checked_add(1).unwrap()),
false,
),
AccountMetaData::new_readonly(thread.key(), true),
],
data: anchor_sighash("registry_epoch_kickoff").to_vec(),
});
// Build the next instruction for thread.
let next_instruction = if snapshot.total_frames.gt(&0) {
// The current snapshot has frames. Distribute fees collected by workers.
Some(InstructionData {
program_id: crate::ID,
accounts: vec![
AccountMetaData::new_readonly(config.key(), false),
AccountMetaData::new(Fee::pubkey(Worker::pubkey(0)), false),
AccountMetaData::new_readonly(registry.key(), false),
AccountMetaData::new_readonly(snapshot.key(), false),
AccountMetaData::new_readonly(SnapshotFrame::pubkey(snapshot.key(), 0), false),
AccountMetaData::new_readonly(thread.key(), true),
AccountMetaData::new(Worker::pubkey(0), false),
],
data: anchor_sighash("worker_fees_distribute").to_vec(),
})
} else if registry.total_workers.gt(&0) {
// The registry has workers. Begin delegating stakes to workers.
Some(InstructionData {
program_id: crate::ID,
accounts: vec![
AccountMetaData::new_readonly(config.key(), false),
AccountMetaData::new_readonly(registry.key(), false),
AccountMetaData::new_readonly(thread.key(), true),
AccountMetaData::new_readonly(Worker::pubkey(0), false),
],
data: anchor_sighash("worker_delegations_stake").to_vec(),
})
} else {
// Cutover to the next epoch.
Some(InstructionData {
program_id: crate::ID,
accounts: vec![
AccountMetaData::new_readonly(config.key(), false),
AccountMetaData::new(registry.key(), false),
AccountMetaData::new_readonly(thread.key(), true),
],
data: anchor_sighash("registry_epoch_cutover").to_vec(),
})
};
Ok(ThreadResponse {
kickoff_instruction,
next_instruction,
})
}
src/instructions/fee_distribute.rs (line 149)
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176
pub fn handler(ctx: Context<FeeDistribute>) -> Result<ThreadResponse> {
// Get accounts
let config = &ctx.accounts.config;
let delegation = &mut ctx.accounts.delegation;
let fee = &mut ctx.accounts.fee;
let registry = &ctx.accounts.registry;
let snapshot = &ctx.accounts.snapshot;
let snapshot_entry = &ctx.accounts.snapshot_entry;
let snapshot_frame = &ctx.accounts.snapshot_frame;
let thread = &ctx.accounts.thread;
let worker = &ctx.accounts.worker;
// Calculate the balance of this particular delegation, based on the weight of its stake with this worker.
let distribution_balance = if snapshot_frame.stake_amount.gt(&0) {
fee.distributable_balance
.checked_mul(snapshot_entry.stake_amount)
.unwrap()
.checked_div(snapshot_frame.stake_amount)
.unwrap()
} else {
0
};
// Transfer yield to the worker.
**fee.to_account_info().try_borrow_mut_lamports()? = fee
.to_account_info()
.lamports()
.checked_sub(distribution_balance)
.unwrap();
**delegation.to_account_info().try_borrow_mut_lamports()? = delegation
.to_account_info()
.lamports()
.checked_add(distribution_balance)
.unwrap();
// Increment the delegation's yield balance.
delegation.yield_balance = delegation
.yield_balance
.checked_add(distribution_balance)
.unwrap();
// Build the next instruction for the thread.
let next_instruction = if snapshot_entry
.id
.checked_add(1)
.unwrap()
.lt(&snapshot_frame.total_entries)
{
// This frame has more entries. Move on to the next one.
let next_delegation_pubkey =
Delegation::pubkey(worker.key(), delegation.id.checked_add(1).unwrap());
let next_snapshot_entry_pubkey = SnapshotEntry::pubkey(
snapshot_frame.key(),
snapshot_entry.id.checked_add(1).unwrap(),
);
Some(InstructionData {
program_id: crate::ID,
accounts: vec![
AccountMetaData::new_readonly(config.key(), false),
AccountMetaData::new(next_delegation_pubkey, false),
AccountMetaData::new(fee.key(), false),
AccountMetaData::new_readonly(registry.key(), false),
AccountMetaData::new_readonly(snapshot.key(), false),
AccountMetaData::new_readonly(snapshot_frame.key(), false),
AccountMetaData::new_readonly(next_snapshot_entry_pubkey, false),
AccountMetaData::new_readonly(thread.key(), true),
AccountMetaData::new_readonly(worker.key(), false),
],
data: anchor_sighash("fee_distribute").to_vec(),
})
} else if snapshot_frame
.id
.checked_add(1)
.unwrap()
.lt(&snapshot.total_frames)
{
// This frame has no more entries. Move on to the next worker.
let next_worker_pubkey = Worker::pubkey(worker.id.checked_add(1).unwrap());
let next_snapshot_frame_pubkey =
SnapshotFrame::pubkey(snapshot.key(), snapshot_frame.id.checked_add(1).unwrap());
Some(InstructionData {
program_id: crate::ID,
accounts: vec![
AccountMetaData::new_readonly(config.key(), false),
AccountMetaData::new(Fee::pubkey(next_worker_pubkey), false),
AccountMetaData::new_readonly(registry.key(), false),
AccountMetaData::new_readonly(snapshot.key(), false),
AccountMetaData::new_readonly(next_snapshot_frame_pubkey, false),
AccountMetaData::new_readonly(thread.key(), true),
AccountMetaData::new(next_worker_pubkey, false),
],
data: anchor_sighash("worker_fees_distribute").to_vec(),
})
} else {
// This frame has no more entires and it is the last frame. Move on to staking delegations.
Some(InstructionData {
program_id: crate::ID,
accounts: vec![
AccountMetaData::new_readonly(config.key(), false),
AccountMetaData::new_readonly(registry.key(), false),
AccountMetaData::new_readonly(thread.key(), true),
AccountMetaData::new_readonly(Worker::pubkey(0), false),
],
data: anchor_sighash("worker_delegations_stake").to_vec(),
})
};
Ok(ThreadResponse {
next_instruction,
..ThreadResponse::default()
})
}
src/instructions/worker_fees_distribute.rs (line 124)
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164
pub fn handler(ctx: Context<WorkerDistributeFees>) -> Result<ThreadResponse> {
// Get accounts.
let config = &ctx.accounts.config;
let fee = &mut ctx.accounts.fee;
let registry = &ctx.accounts.registry;
let snapshot = &ctx.accounts.snapshot;
let snapshot_frame = &ctx.accounts.snapshot_frame;
let thread = &ctx.accounts.thread;
let worker = &mut ctx.accounts.worker;
// Calculate the fee account's usuable balance.
let fee_lamport_balance = fee.to_account_info().lamports();
let fee_data_len = 8 + fee.try_to_vec()?.len();
let fee_rent_balance = Rent::get().unwrap().minimum_balance(fee_data_len);
let fee_usable_balance = fee_lamport_balance.checked_sub(fee_rent_balance).unwrap();
// Calculate the commission to be retained by the worker.
let commission_balance = fee_usable_balance
.checked_mul(worker.commission_rate)
.unwrap()
.checked_div(100)
.unwrap();
// Transfer commission to the worker.
**fee.to_account_info().try_borrow_mut_lamports()? = fee
.to_account_info()
.lamports()
.checked_sub(commission_balance)
.unwrap();
**worker.to_account_info().try_borrow_mut_lamports()? = worker
.to_account_info()
.lamports()
.checked_add(commission_balance)
.unwrap();
// Increment the worker's commission balance.
worker.commission_balance = worker
.commission_balance
.checked_add(commission_balance)
.unwrap();
// Record the balance that is distributable to delegations.
fee.distributable_balance = fee_usable_balance.checked_sub(commission_balance).unwrap();
// Build next instruction for the thread.
let next_instruction = if snapshot_frame.total_entries.gt(&0) {
// This snapshot frame has entries. Distribute fees to the delegations associated with the entries.
let delegation_pubkey = Delegation::pubkey(worker.key(), 0);
let snapshot_entry_pubkey = SnapshotEntry::pubkey(snapshot_frame.key(), 0);
Some(InstructionData {
program_id: crate::ID,
accounts: vec![
AccountMetaData::new_readonly(config.key(), false),
AccountMetaData::new(delegation_pubkey, false),
AccountMetaData::new(fee.key(), false),
AccountMetaData::new_readonly(registry.key(), false),
AccountMetaData::new_readonly(snapshot.key(), false),
AccountMetaData::new_readonly(snapshot_frame.key(), false),
AccountMetaData::new_readonly(snapshot_entry_pubkey.key(), false),
AccountMetaData::new_readonly(thread.key(), true),
AccountMetaData::new_readonly(worker.key(), false),
],
data: anchor_sighash("fee_distribute").to_vec(),
})
} else if snapshot_frame
.id
.checked_add(1)
.unwrap()
.lt(&snapshot.total_frames)
{
// This frame has no entries. Move on to the next frame.
let next_worker_pubkey = Worker::pubkey(worker.id.checked_add(1).unwrap());
let next_snapshot_frame_pubkey =
SnapshotFrame::pubkey(snapshot.key(), snapshot_frame.id.checked_add(1).unwrap());
Some(InstructionData {
program_id: crate::ID,
accounts: vec![
AccountMetaData::new_readonly(config.key(), false),
AccountMetaData::new(Fee::pubkey(next_worker_pubkey), false),
AccountMetaData::new_readonly(registry.key(), false),
AccountMetaData::new_readonly(snapshot.key(), false),
AccountMetaData::new_readonly(next_snapshot_frame_pubkey, false),
AccountMetaData::new_readonly(thread.key(), true),
AccountMetaData::new(next_worker_pubkey, false),
],
data: anchor_sighash("worker_fees_distribute").to_vec(),
})
} else if registry.total_unstakes.gt(&0) {
// This frame has no entries and it is the last frame. Move on to processing unstake requests.
Some(InstructionData {
program_id: crate::ID,
accounts: vec![
AccountMetaData::new_readonly(config.key(), false),
AccountMetaData::new_readonly(registry.key(), false),
AccountMetaData::new_readonly(thread.key(), true),
AccountMetaData::new_readonly(Unstake::pubkey(0), false),
],
data: anchor_sighash("unstake_preprocess").to_vec(),
})
} else {
// This frame has no entries and it is the last frame.
// The registry has no unstake requests, so we can move on to staking delegations.
Some(InstructionData {
program_id: crate::ID,
accounts: vec![
AccountMetaData::new_readonly(config.key(), false),
AccountMetaData::new_readonly(registry.key(), false),
AccountMetaData::new_readonly(thread.key(), true),
AccountMetaData::new_readonly(Worker::pubkey(0), false),
],
data: anchor_sighash("worker_delegations_stake").to_vec(),
})
};
Ok(ThreadResponse {
next_instruction,
..ThreadResponse::default()
})
}
Trait Implementations§
source§impl AccountDeserialize for Fee
impl AccountDeserialize for Fee
source§fn try_deserialize(buf: &mut &[u8]) -> Result<Self>
fn try_deserialize(buf: &mut &[u8]) -> Result<Self>
Deserializes previously initialized account data. Should fail for all
uninitialized accounts, where the bytes are zeroed. Implementations
should be unique to a particular account type so that one can never
successfully deserialize the data of one account type into another.
For example, if the SPL token program were to implement this trait,
it should be impossible to deserialize a
Mint
account into a token
Account
. Read more