use alloy_primitives::{aliases::I24, aliases::U24, keccak256, Address, B256};
use alloy_sol_types::SolValue;
pub fn compute(
deployer: Address,
init_code_hash: B256,
token_a: Address,
token_b: Address,
tick_spacing: i32,
) -> Address {
debug_assert!(token_a != token_b, "pool_address::compute requires distinct tokens");
let (token0, token1) = if token_a < token_b { (token_a, token_b) } else { (token_b, token_a) };
const I24_MIN: i32 = -(1 << 23);
const I24_MAX: i32 = (1 << 23) - 1;
debug_assert!(
(I24_MIN..=I24_MAX).contains(&tick_spacing),
"tick_spacing must fit in int24 (-2^23 ..= 2^23 - 1)",
);
let tick_spacing_raw = U24::from((tick_spacing as u32) & 0x00ff_ffff);
let tick_spacing = I24::from_raw(tick_spacing_raw);
let salt = keccak256((token0, token1, tick_spacing).abi_encode());
deployer.create2(salt, init_code_hash)
}
#[cfg(test)]
mod tests {
use super::*;
use alloy_primitives::{address, b256};
const DEPLOYER: Address = address!("8BBDc15759a8eCf99A92E004E0C64ea9A5142d59");
const INIT_CODE_HASH: B256 =
b256!("c701ee63862761c31d620a4a083c61bdc1e81761e6b9c9267fd19afd22e0821d");
const USDC_E: Address = address!("29219dD400f2Bf60E5a23d13Be72B486D4038894");
const WS: Address = address!("039e2fb66102314Ce7b64Ce5CE3E5183bc94aD38");
const USDCE_WS_TS50_POOL: Address = address!("324963c267C354c7660Ce8CA3F5f167E05649970");
#[test]
fn canonical_shadow_sonic_usdce_ws_tickspacing_50_matches_pool() {
let pool = compute(DEPLOYER, INIT_CODE_HASH, USDC_E, WS, 50);
assert_eq!(pool, USDCE_WS_TS50_POOL);
}
#[test]
fn token_order_does_not_change_result() {
let forward = compute(DEPLOYER, INIT_CODE_HASH, USDC_E, WS, 50);
let reversed = compute(DEPLOYER, INIT_CODE_HASH, WS, USDC_E, 50);
assert_eq!(forward, reversed);
assert_eq!(forward, USDCE_WS_TS50_POOL);
}
#[test]
fn different_tick_spacing_yields_different_address() {
let p50 = compute(DEPLOYER, INIT_CODE_HASH, USDC_E, WS, 50);
let p100 = compute(DEPLOYER, INIT_CODE_HASH, USDC_E, WS, 100);
assert_ne!(p50, p100);
}
#[test]
#[cfg(debug_assertions)]
#[should_panic(expected = "distinct tokens")]
fn identical_tokens_panics_in_debug() {
let _ = compute(DEPLOYER, INIT_CODE_HASH, USDC_E, USDC_E, 50);
}
}