KAGURA 神楽

KAGURA is a continuous-time DeFi primitive on Solana. Two on-chain Anchor programs: a tick-attestation registry, and a USDC funding vault that compounds yield every block instead of every hour.

contact: hello@kagura.network
神楽KAGURA/ docs
v0.1.0 · pre-deployment← back to sitegithub →
programs·kagura-core

kagura-core

tick attestation registry. 4 instructions, 2 accounts, 5 errors, 1 event.

program idDbHae1rzcf5U8Jbrp5X9NFTcZfk4z12R2qMNgesmXNnC
size242 kb
anchor0.31.1
featurescpi, idl-build

accounts

KaguraConfig

Global config singleton. Created once with initialize_config.

state.rsrust
1#[account]2#[derive(InitSpace, Debug)]3pub struct KaguraConfig {4    pub authority: Pubkey,5    pub total_protocols: u64,6    pub total_ticks: u128,7    pub created_at: i64,8    pub bump: u8,9}10 11// pda: [b"kagura-config"]

ProtocolRegistration

One per registered protocol. Created with register_protocol.

state.rsrust
1#[account]2#[derive(InitSpace, Debug)]3pub struct ProtocolRegistration {4    pub authority: Pubkey,5    #[max_len(32)]6    pub name: String,7    pub tick_interval_ms: u32,8    pub last_tick_unix_ms: i64,9    pub total_ticks: u64,10    pub paused: bool,11    pub created_at: i64,12    pub bump: u8,13}14 15// pda: [b"kagura-protocol", authority.key().as_ref()]

instructions

initialize_config

Creates the global config pda. Idempotent at the pda level (errors if already initialized).

signaturerust
1pub fn initialize_config(ctx: Context<InitializeConfig>) -> Result<()>2 3#[derive(Accounts)]4pub struct InitializeConfig<'info> {5    #[account(mut)]                                                pub authority: Signer<'info>,6    #[account(init, payer = authority,7              space = 8 + KaguraConfig::INIT_SPACE,8              seeds = [CONFIG_SEED], bump)]                        pub config: Account<'info, KaguraConfig>,9                                                                    pub system_program: Program<'info, System>,10}

register_protocol

Creates a ProtocolRegistration pda for the calling authority.

signaturerust
1pub fn register_protocol(2    ctx: Context<RegisterProtocol>,3    name: String,4    tick_interval_ms: u32,5) -> Result<()>6 7// validation:8//   tick_interval_ms ∈ [50, 60_000]9//   name.len() <= 32

record_tick

Updates the protocol's tick state and returns a TickResult. This is the instruction consumer programs cpi into.

signaturerust
1pub fn record_tick(ctx: Context<RecordTick>) -> Result<TickResult>2 3#[derive(AnchorSerialize, AnchorDeserialize, Clone, Debug)]4pub struct TickResult {5    pub now_unix_ms: i64,6    pub elapsed_ms: u32,7    pub tick_number: u64,8}9 10#[derive(Accounts)]11pub struct RecordTick<'info> {12                                                              pub authority: Signer<'info>,13    #[account(mut, seeds = [CONFIG_SEED], bump = config.bump)]14                                                              pub config: Account<'info, KaguraConfig>,15    #[account(mut, seeds = [PROTOCOL_SEED, authority.key().as_ref()],16              bump = protocol.bump,17              has_one = authority @ KaguraError::Unauthorized)]18                                                              pub protocol: Account<'info, ProtocolRegistration>,19}

set_paused

Toggle the protocol's pause state. While paused, record_tick errors with ProtocolPaused.

signaturerust
1pub fn set_paused(ctx: Context<SetPaused>, paused: bool) -> Result<()>

events

state.rsrust
1#[event]2pub struct TickEmitted {3    pub protocol: Pubkey,4    pub tick_number: u64,5    pub now_unix_ms: i64,6    pub elapsed_ms: u32,7}

errors

codemessage
Unauthorizedauthority mismatch
AlreadyRegisteredprotocol already registered
InvalidTickIntervaltick interval must be between 50 and 60_000 ms
TickTooEarlytick rejected: too soon since last tick
ClockRegressiontick rejected: clock went backwards
ProtocolPausedprotocol is paused
MathOverflowmath overflow

constants

state.rsrust
1pub const CONFIG_SEED: &[u8]   = b"kagura-config";2pub const PROTOCOL_SEED: &[u8] = b"kagura-protocol";3 4pub const MIN_TICK_INTERVAL_MS: u32 = 50;5pub const MAX_TICK_INTERVAL_MS: u32 = 60_000;