1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
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
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
use array_const_fn_init::array_const_fn_init;
use const_crypto::ed25519;
use solana_program::{pubkey, pubkey::Pubkey};

/// The unix timestamp after which mining can begin.
/// TODO decide a new date
// Tentative time
// Thursday, August 15, 2024 3:00:00 AM GMT
// pub const START_AT: i64 = 1723690800;

// Test Start Time
// Date and time (GMT): Sunday, July 14, 2024 10:00:00 AM
pub const START_AT: i64 = 1720951200;

/// The unix timestamp after which mining will stop.
/// TODO decide a new date
// Tentative time
// Wednesday, August 15, 2074 3:00:00 AM GMT
// pub const END_AT: i64 = 3301527600;

// Test End Time
// Date and time (GMT): Monday, July 15, 2024 10:00:00 AM
// pub const END_AT: i64 = 1721037600;
// Date and time (GMT): Wednesday, July 31, 2024 10:00:00 AM
pub const END_AT: i64 = 1722420000;

// Test initializer (mac::id.json)
// pub const INITIALIZER_ADDRESS: Pubkey = pubkey!("Ac2ev4ofDx61tuSJCgq9ToSBfVwHD2a1FVJf6p7TAqiB");
// Test initializer (mac&hp::test-id.json)
pub const INITIALIZER_ADDRESS: Pubkey = pubkey!("4ALL9EAVHpv7ioJF95ktDLtrHUEJezPuFxTFFMy3fpSy");

/// The authority allowed to initialize the program.
// pub const INITIALIZER_ADDRESS: Pubkey = pubkey!("staryJacbXodPh4WfwVtgA5jkJhvsMHERtkdttnLEHc");

/// The base reward rate to intialize the program with.
// pub const INITIAL_BASE_REWARD_RATE: u64 = BASE_REWARD_RATE_MIN_THRESHOLD;
// pub const INITIAL_BASE_REWARD_RATE: u64 = 2u64.pow(7);
pub const INITIAL_BASE_REWARD_RATE: u64 = 2u64.pow(8);

/// The minimum allowed base reward rate, at which point the min difficulty should be increased
pub const BASE_REWARD_RATE_MIN_THRESHOLD: u64 = 2u64.pow(5);

/// The maximum allowed base reward rate, at which point the min difficulty should be decreased.
// pub const BASE_REWARD_RATE_MAX_THRESHOLD: u64 = 2u64.pow(8);
// pub const BASE_REWARD_RATE_MAX_THRESHOLD: u64 = 2u64.pow(10);
pub const BASE_REWARD_RATE_MAX_THRESHOLD: u64 = 2u64.pow(16);

/// The spam/liveness tolerance in seconds.
pub const TOLERANCE: i64 = 5;

/// The minimum difficulty to initialize the program with.
// pub const INITIAL_MIN_DIFFICULTY: u32 = 1;
// pub const INITIAL_MIN_DIFFICULTY: u32 = 5;
// pub const INITIAL_MIN_DIFFICULTY: u32 = 7;
pub const INITIAL_MIN_DIFFICULTY: u32 = 8;

/// The decimal precision of the Marsh token.
/// There are 1 billion indivisible units per Marsh (called "raindrops").
pub const TOKEN_DECIMALS: u8 = 9;

/// The decimal precision of the legacy Mars(h) token.
pub const TOKEN_DECIMALS_V1: u8 = 8;

/// One Marsh token, denominated in indivisible units.
pub const ONE_MARSH: u64 = 10u64.pow(TOKEN_DECIMALS as u32);

/// Ten MARSH token
// pub const TEN_MARSH: u64 = ONE_MARSH.saturating_mul(10);
pub const TEN_MARSH: u64 = ONE_MARSH * 10;

/// The duration of one minute, in seconds.
pub const ONE_MINUTE: i64 = 60;

/// The number of minutes in a program epoch.
pub const EPOCH_MINUTES: i64 = 1;

/// The duration of a program epoch, in seconds.
// pub const EPOCH_DURATION: i64 = ONE_MINUTE.saturating_mul(EPOCH_MINUTES);
pub const EPOCH_DURATION: i64 = ONE_MINUTE * EPOCH_MINUTES;

/// The maximum token supply (50 million).
// pub const MAX_SUPPLY: u64 = ONE_MARSH.saturating_mul(50_000_000);
pub const MAX_SUPPLY: u64 = ONE_MARSH * 50_000_000;

/// The target quantity of MARSH to be mined per epoch.
// pub const TARGET_EPOCH_REWARDS: u64 = ONE_MARSH.saturating_mul(EPOCH_MINUTES as u64);
// pub const TARGET_EPOCH_REWARDS: u64 = TEN_MARSH.saturating_mul(EPOCH_MINUTES as u64);
pub const TARGET_EPOCH_REWARDS: u64 = TEN_MARSH * EPOCH_MINUTES as u64;

/// The maximum quantity of MARSH that can be mined per epoch.
/// Inflation rate ≈ 10 MARSH / min (min 0, max 8)
// pub const MAX_EPOCH_REWARDS: u64 = TARGET_EPOCH_REWARDS.saturating_mul(BUS_COUNT as u64);
pub const MAX_EPOCH_REWARDS: u64 = TARGET_EPOCH_REWARDS * BUS_COUNT as u64;

/// The quantity of MARSH each bus is allowed to issue per epoch.
// pub const BUS_EPOCH_REWARDS: u64 = MAX_EPOCH_REWARDS.saturating_div(BUS_COUNT as u64);
pub const BUS_EPOCH_REWARDS: u64 = MAX_EPOCH_REWARDS / BUS_COUNT as u64;

/// The number of bus accounts, for parallelizing mine operations.
pub const BUS_COUNT: usize = 8;

/// The smoothing factor for reward rate changes. The reward rate cannot change by more or less
/// than a factor of this constant from one epoch to the next.
pub const SMOOTHING_FACTOR: u64 = 2;

// Assert MAX_EPOCH_REWARDS is evenly divisible by BUS_COUNT.
static_assertions::const_assert!(
    (MAX_EPOCH_REWARDS / BUS_COUNT as u64) * BUS_COUNT as u64 == MAX_EPOCH_REWARDS
);

/// The seed of the bus account PDA.
pub const BUS: &[u8] = b"bus";

/// The seed of the config account PDA.
pub const CONFIG: &[u8] = b"config";

/// The seed of the metadata account PDA.
pub const METADATA: &[u8] = b"metadata";

/// The seed of the mint account PDA.
pub const MINT: &[u8] = b"mint";

/// The seed of proof account PDAs.
pub const PROOF: &[u8] = b"proof";

/// The seed of the treasury account PDA.
pub const TREASURY: &[u8] = b"treasury";

/// Noise for deriving the mint pda.
// mint noise: Mirascapians, big-endian: [77, 105, 114, 97, 115, 99, 97, 112, 105, 97, 110, 115]
// nonce: 92596813, big-endian: [5, 132, 234, 77]
// Mirascapians concat(+) nonce
/// Noise for deriving the mint pda.
pub const MINT_NOISE: [u8; 16] = [
    77, 105, 114, 97, 115, 99, 97, 112, 105, 97, 110, 115, 5, 132, 234, 77,
];

/// The name for token metadata.
pub const METADATA_NAME: &str = "Marsh";

/// The ticker symbol for token metadata.
pub const METADATA_SYMBOL: &str = "MARSH";

/// The uri for token metdata.
pub const METADATA_URI: &str = "https://github.com/miraland-labs/resources/blob/main/metadata/marsh.json";

/// Program id for const pda derivations
const PROGRAM_ID: [u8; 32] = unsafe { *(&crate::id() as *const Pubkey as *const [u8; 32]) };

/// The addresses of the bus accounts.
pub const BUS_ADDRESSES: [Pubkey; BUS_COUNT] = array_const_fn_init![const_bus_address; 8];

/// Function to derive const bus addresses.
const fn const_bus_address(i: usize) -> Pubkey {
    Pubkey::new_from_array(ed25519::derive_program_address(&[BUS, &[i as u8]], &PROGRAM_ID).0)
}

/// The address of the config account.
pub const CONFIG_ADDRESS: Pubkey =
    Pubkey::new_from_array(ed25519::derive_program_address(&[CONFIG], &PROGRAM_ID).0);

/// The address of the mint metadata account.
pub const METADATA_ADDRESS: Pubkey = Pubkey::new_from_array(
    ed25519::derive_program_address(
        &[
            METADATA,
            unsafe { &*(&mpl_token_metadata::ID as *const Pubkey as *const [u8; 32]) },
            unsafe { &*(&MINT_ADDRESS as *const Pubkey as *const [u8; 32]) },
        ],
        unsafe { &*(&mpl_token_metadata::ID as *const Pubkey as *const [u8; 32]) },
    )
    .0,
);

// MI
// Marsh mint address: MARSs8nkDeZrr3D9V7wzap5kiWtmQJ131f8xf61ZZrW
/// The address of the mint account.
pub const MINT_ADDRESS: Pubkey =
    Pubkey::new_from_array(ed25519::derive_program_address(&[MINT, &MINT_NOISE], &PROGRAM_ID).0);

/// The address of the legacy Mars(h) mint account.
pub const MINT_V1_ADDRESS: Pubkey = pubkey!("7RAV5UPRTzxn46kLeA8MiJsdNy9VKc5fip8FWEgTpTHh");

/// The address of the treasury account.
pub const TREASURY_ADDRESS: Pubkey =
    Pubkey::new_from_array(ed25519::derive_program_address(&[TREASURY], &PROGRAM_ID).0);

/// The bump of the treasury account, for cpis.
pub const TREASURY_BUMP: u8 = ed25519::derive_program_address(&[TREASURY], &PROGRAM_ID).1;

/// The address of the treasury token account.
pub const TREASURY_TOKENS_ADDRESS: Pubkey = Pubkey::new_from_array(
    ed25519::derive_program_address(
        &[
            unsafe { &*(&TREASURY_ADDRESS as *const Pubkey as *const [u8; 32]) },
            unsafe { &*(&spl_token::id() as *const Pubkey as *const [u8; 32]) },
            unsafe { &*(&MINT_ADDRESS as *const Pubkey as *const [u8; 32]) },
        ],
        unsafe { &*(&spl_associated_token_account::id() as *const Pubkey as *const [u8; 32]) },
    )
    .0,
);

/// The address of the CU-optimized Solana noop program.
pub const NOOP_PROGRAM_ID: Pubkey = pubkey!("noop8ytexvkpCuqbf6FB89BSuNemHtPRqaNC31GWivW");