Skip to content
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
701 changes: 701 additions & 0 deletions HARDCODE_LAUNCH_DELAY.md

Large diffs are not rendered by default.

2 changes: 0 additions & 2 deletions src/lbry_fun/lbry_fun.did
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ type CreateTokenParams = record {
secondary_token_description : text;
secondary_token_name : text;
primary_token_symbol : text;
launch_delay_seconds : nat64;
primary_logo : text;
halving_step : nat64;
primary_token_description : text;
Expand Down Expand Up @@ -120,7 +119,6 @@ service : () -> {
float64,
nat64,
nat64,
nat64,
) -> (Result);
// Phase 2: Execute the deployment with the given ID
execute_token_deployment : (nat64) -> (Result_1);
Expand Down
5 changes: 4 additions & 1 deletion src/lbry_fun/src/deployment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ use std::{borrow::Cow, cell::RefCell};

type Memory = VirtualMemory<DefaultMemoryImpl>;

/// Launch delay enforced for all tokens to prevent bot sniping and ensure fair launch.
/// Fixed at 24 hours (86400 seconds) to give all users equal opportunity to participate.
pub const LAUNCH_DELAY_SECONDS: u64 = 86400;

// Memory IDs for stable structures
pub const DEPLOYMENTS_MEM_ID: MemoryId = MemoryId::new(10);
pub const USER_ACTIVE_DEPLOYMENTS_MEM_ID: MemoryId = MemoryId::new(11);
Expand Down Expand Up @@ -39,7 +43,6 @@ pub struct CreateTokenParams {
pub threshold_multiplier: f64,
pub initial_reward_per_burn_unit: u64,
pub distribution_interval_seconds: u64,
pub launch_delay_seconds: u64,
}

#[derive(CandidType, Deserialize, Clone, Debug)]
Expand Down
5 changes: 2 additions & 3 deletions src/lbry_fun/src/deployment_execution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,6 @@ pub async fn execute_deployment_safe(deployment_id: u64) -> Result<u64, String>
Some(get_principal(&secondary_token_id)),
Some(tokenomics_canister_id),
params.distribution_interval_seconds,
params.launch_delay_seconds,
Some(token_id), // Pass the correct token_id
)
.await?;
Expand Down Expand Up @@ -237,10 +236,10 @@ pub async fn execute_deployment_safe(deployment_id: u64) -> Result<u64, String>
threshold_multiplier: params.threshold_multiplier,
initial_reward_per_burn_unit: params.initial_reward_per_burn_unit,
distribution_interval_seconds: params.distribution_interval_seconds,
launch_delay_seconds: params.launch_delay_seconds,
launch_delay_seconds: crate::deployment::LAUNCH_DELAY_SECONDS,
caller,
created_time: ic_cdk::api::time(),
launched_at: ic_cdk::api::time() + params.launch_delay_seconds * 1_000_000_000,
launched_at: ic_cdk::api::time() + crate::deployment::LAUNCH_DELAY_SECONDS * 1_000_000_000,
codebase_version: crate::CODEBASE_VERSION.to_string(),
};

Expand Down
13 changes: 1 addition & 12 deletions src/lbry_fun/src/deployment_updates.rs
Original file line number Diff line number Diff line change
Expand Up @@ -404,18 +404,7 @@ async fn validate_deployment_params(params: &CreateTokenParams) -> Result<(), St
if params.threshold_multiplier < 1.0 || params.threshold_multiplier > 10.0 {
return Err("Threshold multiplier must be between 1.0 and 10.0".to_string());
}

// Launch delay validation (sent as seconds: 1 second to 30 days)
const MIN_LAUNCH_DELAY: u64 = 1;
const MAX_LAUNCH_DELAY: u64 = 2_592_000; // 30 days in seconds

if params.launch_delay_seconds < MIN_LAUNCH_DELAY {
return Err("Launch delay must be at least 1 second".to_string());
}
if params.launch_delay_seconds > MAX_LAUNCH_DELAY {
return Err("Launch delay cannot exceed 30 days".to_string());
}


// Distribution interval validation (sent as seconds, min 60)
if params.distribution_interval_seconds < 60 {
return Err("Distribution interval must be at least 60 seconds".to_string());
Expand Down
11 changes: 5 additions & 6 deletions src/lbry_fun/src/update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ async fn create_token(
threshold_multiplier: f64,
initial_reward_per_burn_unit: u64,
distribution_interval_seconds: u64,
launch_delay_seconds: u64,
) -> Result<String, String> {
// Use the new two-phase deployment system internally
let params = CreateTokenParams {
Expand All @@ -63,7 +62,6 @@ async fn create_token(
threshold_multiplier,
initial_reward_per_burn_unit,
distribution_interval_seconds,
launch_delay_seconds,
};

// Phase 1: Initiate deployment
Expand Down Expand Up @@ -217,12 +215,13 @@ pub async fn install_icp_swap_wasm_on_existing_canister(
secondary_token_id: Option<Principal>,
tokenomics_canister_id: Option<Principal>,
distribution_interval_seconds: u64,
launch_delay_seconds: u64,
token_id: Option<u64>, // Add token_id parameter
) -> Result<(), String> {
// Calculate launch_time from current time + delay
let launch_time = if launch_delay_seconds > 0 {
Some(ic_cdk::api::time() / 1_000_000_000 + launch_delay_seconds)
// Use hardcoded 24-hour launch delay
use crate::deployment::LAUNCH_DELAY_SECONDS;

let launch_time = if LAUNCH_DELAY_SECONDS > 0 {
Some(ic_cdk::api::time() / 1_000_000_000 + LAUNCH_DELAY_SECONDS)
} else {
None
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -231,9 +231,9 @@ const TokenomicsTab: React.FC = () => {
<div className="flex justify-between items-center">
<span className="text-gray-400 flex items-center gap-1">
launch_delay:
<TooltipIcon text="Time after creation before minting/burning becomes active. Allows time for initial liquidity setup." />
<TooltipIcon text="Time after creation before minting/burning becomes active. Fixed at 24 hours to prevent bot sniping." />
</span>
<span className="text-white">{formatTimeInterval(tokenConfig.launch_delay_seconds)}</span>
<span className="text-white">{formatTimeInterval(tokenConfig.launch_delay_seconds)} [fixed]</span>
</div>

{/* Metadata */}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,6 @@ export interface TokenFormValues {
threshold_multiplier: string;
initial_reward_per_burn_unit: string;
distribution_interval_seconds: string;
launch_delay_seconds: string;
}

interface FormErrors {
Expand Down Expand Up @@ -91,7 +90,6 @@ const TerminalCreateToken: React.FC = () => {
threshold_multiplier: '1.5',
initial_reward_per_burn_unit: '1',
distribution_interval_seconds: '3600',
launch_delay_seconds: '86400',
});

// Validation logic
Expand Down Expand Up @@ -178,16 +176,6 @@ const TerminalCreateToken: React.FC = () => {
newErrors.threshold_multiplier = 'Must be between 1 and 10';
}

// Validate launch delay
const launchDelay = parseInt(form.launch_delay_seconds);
if (!form.launch_delay_seconds || isNaN(launchDelay)) {
newErrors.launch_delay_seconds = 'Launch delay is required';
} else if (launchDelay < 1) {
newErrors.launch_delay_seconds = 'Launch delay must be at least 1 second';
} else if (launchDelay > 2592000) { // 30 days in seconds
newErrors.launch_delay_seconds = 'Launch delay cannot exceed 30 days';
}

setErrors(newErrors);
setWarnings(newWarnings);
}, [form]);
Expand Down Expand Up @@ -300,7 +288,6 @@ const TerminalCreateToken: React.FC = () => {
threshold_multiplier: parseFloat(form.threshold_multiplier),
initial_reward_per_burn_unit: BigInt(Math.floor(parseFloat(form.initial_reward_per_burn_unit) * Number(TokenConversionService.getE8S()))),
distribution_interval_seconds: BigInt(form.distribution_interval_seconds),
launch_delay_seconds: BigInt(form.launch_delay_seconds)
};

// Phase 1: Initiate deployment
Expand Down Expand Up @@ -340,25 +327,6 @@ const TerminalCreateToken: React.FC = () => {
{ value: '86400', label: '24_hours' },
];

const launchDelayOptions = [
{ value: '1', label: '1_second' },
{ value: '60', label: '1_minute' },
{ value: '300', label: '5_minutes' },
{ value: '900', label: '15_minutes' },
{ value: '1800', label: '30_minutes' },
{ value: '3600', label: '1_hour' },
{ value: '7200', label: '2_hours' },
{ value: '14400', label: '4_hours' },
{ value: '28800', label: '8_hours' },
{ value: '43200', label: '12_hours' },
{ value: '86400', label: '24_hours [default]' },
{ value: '172800', label: '2_days' },
{ value: '259200', label: '3_days' },
{ value: '604800', label: '7_days' },
{ value: '1209600', label: '14_days' },
{ value: '2592000', label: '30_days' },
];

return (
<div className="bg-black border border-white/30 font-mono text-sm p-4">
{/* Header */}
Expand Down Expand Up @@ -689,20 +657,15 @@ const TerminalCreateToken: React.FC = () => {
options={distributionIntervalOptions}
/>
<div className="text-gray-600 text-xs mt-1 font-mono mt-1">Cannot be changed after creation.</div>

<div className="flex items-center mb-1 mt-4">
<span className="text-gray-400 text-xs">launch_delay</span>
<TooltipIcon
text="Time delay before trading opens after token creation. During this period, only the creator can view token details. DEFAULT: 24 hours. Min: 1 second, Max: 30 days."
/>

<div className="text-gray-400 text-xs mt-4 font-mono">
<div className="flex items-center mb-1">
<span>launch_delay</span>
<TooltipIcon text="Time delay before trading opens after token creation. Fixed at 24 hours to prevent bot sniping." />
</div>
<div className="text-white">24_hours [fixed]</div>
<div className="text-gray-600 text-xs mt-1">Trading will be enabled 24 hours after creation.</div>
</div>
<TerminalSelect
label=""
value={form.launch_delay_seconds}
onChange={(v) => updateForm('launch_delay_seconds', v)}
options={launchDelayOptions}
/>
<div className="text-gray-600 text-xs mt-1 font-mono mt-1">[INFO] Trading will be enabled after this delay. Default (24 hours) prevents bot sniping.</div>
</div>
)}
</div>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -79,8 +79,7 @@ const createToken = createAsyncThunk<
BigInt(formData.halving_step),
formData.threshold_multiplier,
BigInt(formData.initial_reward_per_burn_unit),
BigInt(formData.distribution_interval_seconds),
BigInt(formData.launch_delay_seconds)
BigInt(formData.distribution_interval_seconds)
);

if ("Ok" in result) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,7 @@ const persistDeployment = (deployment: DeploymentRecord) => {
initial_secondary_burn: deployment.params.initial_secondary_burn.toString(),
halving_step: deployment.params.halving_step.toString(),
initial_reward_per_burn_unit: deployment.params.initial_reward_per_burn_unit.toString(),
distribution_interval_seconds: deployment.params.distribution_interval_seconds.toString(),
launch_delay_seconds: deployment.params.launch_delay_seconds.toString()
distribution_interval_seconds: deployment.params.distribution_interval_seconds.toString()
}
},
expires: Date.now() + DEPLOYMENT_TTL
Expand Down Expand Up @@ -79,8 +78,7 @@ const loadPersistedDeployments = (): DeploymentRecord[] => {
initial_secondary_burn: BigInt(deployment.params.initial_secondary_burn),
halving_step: BigInt(deployment.params.halving_step),
initial_reward_per_burn_unit: BigInt(deployment.params.initial_reward_per_burn_unit),
distribution_interval_seconds: BigInt(deployment.params.distribution_interval_seconds),
launch_delay_seconds: BigInt(deployment.params.launch_delay_seconds)
distribution_interval_seconds: BigInt(deployment.params.distribution_interval_seconds)
}
});
} else {
Expand Down
4 changes: 3 additions & 1 deletion src/lbry_fun_frontend/src/types/deployment.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
import { Principal } from '@dfinity/principal';

// Launch delay constant (24 hours hardcoded)
export const LAUNCH_DELAY_SECONDS = 86400n;

// Token creation parameters
export interface CreateTokenParams {
primary_token_name: string;
Expand All @@ -17,7 +20,6 @@ export interface CreateTokenParams {
threshold_multiplier: number;
initial_reward_per_burn_unit: bigint;
distribution_interval_seconds: bigint;
launch_delay_seconds: bigint;
}

// Backend deployment info (from get_my_deployments)
Expand Down
24 changes: 2 additions & 22 deletions tests/unit/test_deployment_validation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -190,25 +190,7 @@ fn test_deployment_parameter_validation() {
},
"Threshold multiplier must be between 1.0 and 10.0"
),

// Launch delay validation tests
(
"launch_delay_too_low",
CreateTokenParams {
launch_delay_seconds: 0, // Less than 1 second
..default_params()
},
"Launch delay must be at least 1 second"
),
(
"launch_delay_too_high",
CreateTokenParams {
launch_delay_seconds: 2_592_001, // More than 30 days
..default_params()
},
"Launch delay cannot exceed 30 days"
),


// Distribution interval validation tests
(
"distribution_interval_too_low",
Expand Down Expand Up @@ -306,11 +288,10 @@ fn default_params() -> CreateTokenParams {
threshold_multiplier: 1.5,
initial_reward_per_burn_unit: 100_000_000, // 1 token in E8S
distribution_interval_seconds: 3600,
launch_delay_seconds: 86400,
}
}

#[derive(Clone)]
#[derive(Clone, candid::CandidType, candid::Deserialize)]
struct CreateTokenParams {
pub primary_token_name: String,
pub primary_token_symbol: String,
Expand All @@ -327,5 +308,4 @@ struct CreateTokenParams {
pub threshold_multiplier: f64,
pub initial_reward_per_burn_unit: u64,
pub distribution_interval_seconds: u64,
pub launch_delay_seconds: u64,
}