eth_twc_sdk/
config.rs

1//! コントラクトアドレスと CREATE2 / EIP-712 の固定パラメータ。
2//!
3//! **デプロイ先アドレス**は EIP-2470 Singleton Factory による CREATE2 の決定論アドレスです(`contracts/TWC_CREATE2.md` 参照)。
4//!
5//! `integration-test` フィーチャー有効時のみ、[`transfer_with_commitment_address`] が環境変数 `ETH_TWC_CONTRACT_ADDRESS` を参照します(Anvil 結合テスト用)。
6//!
7//! `test-config` 有効時は単体テスト用の固定アドレスになります。
8
9#[cfg(feature = "integration-test")]
10use std::sync::OnceLock;
11
12use alloy::primitives::{address, Address};
13
14/// 未設定を表すゼロアドレス。
15pub const ZERO_TRANSFER_ADDRESS: Address = address!("0x0000000000000000000000000000000000000000");
16
17/// 既定 EIP-712 `name`(`TransferWithCommitment` コンストラクタと一致させる)。
18pub const EIP712_DOMAIN_NAME: &str = "TransferWithCommitment";
19
20/// 既定 EIP-712 `version`。
21pub const EIP712_DOMAIN_VERSION: &str = "1";
22
23#[cfg(not(feature = "integration-test"))]
24const COMPILE_TIME_TWC: Address = {
25    #[cfg(feature = "test-config")]
26    {
27        address!("0x2222222222222222222222222222222222222222")
28    }
29    #[cfg(not(feature = "test-config"))]
30    {
31        // contracts/TWC_CREATE2.md — default Foundry profile + default ctor args
32        address!("0x5C260DD537A9c23Bbd42493e59F3CeA7da2DbC71")
33    }
34};
35
36#[cfg(feature = "integration-test")]
37static INTEGRATION_TWC: OnceLock<Address> = OnceLock::new();
38
39/// 実行時に解決する `TransferWithCommitment` のデプロイアドレス。
40///
41/// - **通常ビルド** — [`TRANSFER_WITH_COMMITMENT_ADDRESS`] と一致(`integration-test` 以外)。
42/// - **`integration-test`** — 初回アクセス時に `ETH_TWC_CONTRACT_ADDRESS` をパース。未設定・不正ならゼロアドレス扱い。
43#[inline]
44pub fn transfer_with_commitment_address() -> Address {
45    #[cfg(feature = "integration-test")]
46    {
47        *INTEGRATION_TWC.get_or_init(|| {
48            std::env::var("ETH_TWC_CONTRACT_ADDRESS")
49                .ok()
50                .and_then(|s| s.parse().ok())
51                .unwrap_or(ZERO_TRANSFER_ADDRESS)
52        })
53    }
54    #[cfg(not(feature = "integration-test"))]
55    {
56        COMPILE_TIME_TWC
57    }
58}
59
60/// `TransferWithCommitment` の決定論アドレス(コンパイル時定数)。
61///
62/// `integration-test` 有効時はプレースホルダ(ゼロ)。実アドレスは [`transfer_with_commitment_address`] を使ってください。
63#[cfg(not(feature = "integration-test"))]
64pub const TRANSFER_WITH_COMMITMENT_ADDRESS: Address = COMPILE_TIME_TWC;
65
66#[cfg(feature = "integration-test")]
67pub const TRANSFER_WITH_COMMITMENT_ADDRESS: Address = ZERO_TRANSFER_ADDRESS;
68
69/// [`transfer_with_commitment_address`] がゼロでないことを検証する(`integration-test` で未設定 env のときなど)。
70#[inline]
71pub fn assert_transfer_contract_configured() -> Result<(), crate::SdkError> {
72    if transfer_with_commitment_address() == ZERO_TRANSFER_ADDRESS {
73        return Err(crate::SdkError::ContractNotConfigured);
74    }
75    Ok(())
76}
77
78#[cfg(test)]
79mod tests {
80    use super::*;
81
82    #[test]
83    #[cfg(not(feature = "test-config"))]
84    #[cfg(not(feature = "integration-test"))]
85    fn transfer_with_commitment_address_is_deterministic_create2() {
86        assert_eq!(
87            transfer_with_commitment_address(),
88            address!("0x5C260DD537A9c23Bbd42493e59F3CeA7da2DbC71")
89        );
90    }
91
92    #[test]
93    #[cfg(not(feature = "test-config"))]
94    #[cfg(not(feature = "integration-test"))]
95    fn assert_transfer_contract_configured_ok_by_default() {
96        assert!(assert_transfer_contract_configured().is_ok());
97    }
98
99    #[test]
100    #[cfg(feature = "test-config")]
101    fn test_config_uses_non_zero_contract_address() {
102        assert_ne!(transfer_with_commitment_address(), ZERO_TRANSFER_ADDRESS);
103    }
104
105    #[test]
106    #[cfg(feature = "test-config")]
107    fn assert_transfer_contract_configured_ok_under_test_config() {
108        assert!(assert_transfer_contract_configured().is_ok());
109    }
110}