diff --git a/program/src/instruction.rs b/program/src/instruction.rs index f8ccd9a..52ffe40 100644 --- a/program/src/instruction.rs +++ b/program/src/instruction.rs @@ -46,7 +46,7 @@ impl Arbitrary for VestingInstruction { #[derive(Clone, Debug, PartialEq)] pub struct Schedule { // Schedule release time in unix timestamp - pub release_time: u64, + pub time_delta: u64, pub amount: u64, } @@ -131,7 +131,7 @@ impl VestingInstruction { .map(Pubkey::new_from_array) .ok_or(InvalidInstruction)?; let offset = 64; - let release_time = rest + let time_delta = rest .get(offset..offset + 8) .and_then(|slice| slice.try_into().ok()) .map(u64::from_le_bytes) @@ -142,7 +142,7 @@ impl VestingInstruction { .map(u64::from_le_bytes) .ok_or(InvalidInstruction)?; let schedule = Schedule { - release_time, + time_delta, amount, }; Self::Create { @@ -185,7 +185,7 @@ impl VestingInstruction { buf.push(1); buf.extend_from_slice(seeds); buf.extend_from_slice(&mint_address.to_bytes()); - buf.extend_from_slice(&schedule.release_time.to_le_bytes()); + buf.extend_from_slice(&schedule.time_delta.to_le_bytes()); buf.extend_from_slice(&schedule.amount.to_le_bytes()); } &Self::Unlock { seeds } => { @@ -321,7 +321,7 @@ mod test { seeds: [50u8; 32], schedule: Schedule { amount: 42, - release_time: 250, + time_delta: 250, }, mint_address: mint_address.clone(), }; diff --git a/program/src/processor.rs b/program/src/processor.rs index e16b07a..3ef66b1 100644 --- a/program/src/processor.rs +++ b/program/src/processor.rs @@ -139,8 +139,27 @@ impl Processor { let mut total_amount: u64 = 0; + // NOTE: validate time delta to be 0 (unlocked), or a set of predefined values (1 month, 3 months, ...) + let release_time; + match schedule.time_delta { + 0 => { + release_time = 0; + }, + 1 | 100 | 300 => { // TODO: replace for validated values + // Valid time_delta values, do nothing + // TODO: make test advance in time between initialize and unlock + // let clock = Clock::from_account_info(&clock_sysvar_account)?; + // release_time = clock.unix_timestamp as u64 + schedule.time_delta; // TODO: uncomment + release_time = schedule.time_delta; // NOTE: For testing purposes, keeping previous behavior + } + _ => { + msg!("Unsupported time delta"); + return Err(ProgramError::InvalidInstructionData); + } + } + let state_schedule = VestingSchedule { - release_time: schedule.release_time, + release_time: release_time, amount: schedule.amount, }; state_schedule.pack_into_slice(&mut data[VestingScheduleHeader::LEN..]); diff --git a/program/tests/functional.rs b/program/tests/functional.rs index a1e667b..356f9d5 100644 --- a/program/tests/functional.rs +++ b/program/tests/functional.rs @@ -2,12 +2,12 @@ use std::str::FromStr; use solana_program::{hash::Hash, pubkey::Pubkey, rent::Rent, system_program, sysvar}; -use solana_test_framework::ProgramTestContextExtension; use solana_program_test::{processor, ProgramTest, ProgramTestContext}; -use solana_sdk::{account::Account, signature::Keypair, signature::Signer, system_instruction, transaction::Transaction}; +use solana_sdk::{account::Account, signature::Keypair, signature::Signer, system_instruction,transaction::Transaction}; +use solana_test_framework::ProgramTestContextExtension; +use spl_token::{self,instruction::{initialize_account, initialize_mint, mint_to}}; +use token_vesting::instruction::{create, init, initialize_unlock, unlock}; use token_vesting::{entrypoint::process_instruction, instruction::Schedule}; -use token_vesting::instruction::{init, unlock, create, initialize_unlock}; -use spl_token::{self, instruction::{initialize_mint, initialize_account, mint_to}}; #[tokio::test] async fn test_token_vesting() { @@ -94,7 +94,7 @@ async fn test_token_vesting() { let schedule = Schedule { amount: 100, - release_time: 1, + time_delta: 1, }; let test_instructions = [ @@ -134,7 +134,12 @@ async fn test_token_vesting() { Transaction::new_with_payer(&test_instructions, Some(&payer.pubkey())); test_transaction.partial_sign(&[&payer, &source_account], recent_blockhash); - banks_client.process_transaction(test_transaction).await.unwrap(); + // NOTE: we're NOT doing `now() + time_delta` in the program (but we should), that's why this test passes + // TODO: add warp_to_timestamp to correctly test the behaviour + banks_client + .process_transaction(test_transaction) + .await + .unwrap(); } #[tokio::test] @@ -238,7 +243,7 @@ async fn test_token_unlocking() { let schedule = Schedule { amount: 100, - release_time: 0, + time_delta: 0, }; let test_instructions = [