cow_chains/contracts.rs
1//! Per-chain `CoW` Protocol contract addresses.
2//!
3//! All contracts use the same address across EVM chains thanks to
4//! deterministic `CREATE2` deployment. This module defines the canonical
5//! addresses as constants and provides per-chain/per-env lookup functions.
6//!
7//! # Key constants
8//!
9//! | Constant | Address |
10//! |---|---|
11//! | [`SETTLEMENT_CONTRACT`] | `0x9008D19f…0560ab41` |
12//! | [`VAULT_RELAYER`] | `0xC92E8bdf…BFE0110` |
13//! | [`COMPOSABLE_COW`] | `0xfdaFc9d1…013b74` |
14//! | [`EXTENSIBLE_FALLBACK_HANDLER`] | `0x2f55e8b2…605bF5` |
15//! | [`BUY_ETH_ADDRESS`] | `0xEeee…EeEe` (buy native currency sentinel) |
16
17use alloy_primitives::{Address, B256, keccak256};
18
19use super::chain::SupportedChainId;
20
21/// The `CoW` Protocol `GPv2Settlement` contract address.
22///
23/// Identical on all supported chains.
24/// `0x9008D19f58AAbD9eD0D60971565AA8510560ab41`
25pub const SETTLEMENT_CONTRACT: Address = Address::new([
26 0x90, 0x08, 0xd1, 0x9f, 0x58, 0xaa, 0xbd, 0x9e, 0xd0, 0xd6, 0x09, 0x71, 0x56, 0x5a, 0xa8, 0x51,
27 0x05, 0x60, 0xab, 0x41,
28]);
29
30/// The `CoW` Protocol Vault Relayer contract address.
31///
32/// Identical on all supported chains.
33/// `0xC92E8bdf79f0507f65a392b0ab4667716BFE0110`
34pub const VAULT_RELAYER: Address = Address::new([
35 0xc9, 0x2e, 0x8b, 0xdf, 0x79, 0xf0, 0x50, 0x7f, 0x65, 0xa3, 0x92, 0xb0, 0xab, 0x46, 0x67, 0x71,
36 0x6b, 0xfe, 0x01, 0x10,
37]);
38
39/// The production `EthFlow` contract address.
40///
41/// Identical on all supported chains.
42/// `0xba3cb449bd2b4adddbc894d8697f5170800eadec`
43pub const ETH_FLOW_PROD: Address = Address::new([
44 0xba, 0x3c, 0xb4, 0x49, 0xbd, 0x2b, 0x4a, 0xdd, 0xdb, 0xc8, 0x94, 0xd8, 0x69, 0x7f, 0x51, 0x70,
45 0x80, 0x0e, 0xad, 0xec,
46]);
47
48/// The staging (barn) `EthFlow` contract address.
49///
50/// `0x04501b9b1d52e67f6862d157e00d13419d2d6e95`
51pub const ETH_FLOW_STAGING: Address = Address::new([
52 0x04, 0x50, 0x1b, 0x9b, 0x1d, 0x52, 0xe6, 0x7f, 0x68, 0x62, 0xd1, 0x57, 0xe0, 0x0d, 0x13, 0x41,
53 0x9d, 0x2d, 0x6e, 0x95,
54]);
55
56/// The `ExtensibleFallbackHandler` contract address.
57///
58/// Used by `Safe` wallets to enable custom EIP-712 domain verifiers
59/// (such as `ComposableCow`-based conditional orders).
60/// Identical on all supported chains.
61/// `0x2f55e8b20D0B9FEFA187AA7d00B6Cbe563605bF5`
62pub const EXTENSIBLE_FALLBACK_HANDLER: Address = Address::new([
63 0x2f, 0x55, 0xe8, 0xb2, 0x0d, 0x0b, 0x9f, 0xef, 0xa1, 0x87, 0xaa, 0x7d, 0x00, 0xb6, 0xcb, 0xe5,
64 0x63, 0x60, 0x5b, 0xf5,
65]);
66
67/// The staging `CoW` Protocol `GPv2Settlement` contract address.
68///
69/// Used on the barn (staging) environment.
70/// `0xf553d092b50bdcbddeD1A99aF2cA29FBE5E2CB13`
71pub const SETTLEMENT_CONTRACT_STAGING: Address = Address::new([
72 0xf5, 0x53, 0xd0, 0x92, 0xb5, 0x0b, 0xdc, 0xbd, 0xde, 0xd1, 0xa9, 0x9a, 0xf2, 0xca, 0x29, 0xfb,
73 0xe5, 0xe2, 0xcb, 0x13,
74]);
75
76/// The staging `CoW` Protocol Vault Relayer contract address.
77///
78/// Used on the barn (staging) environment.
79/// `0xC7242d167563352E2BCA4d71C043fbe542DB8FB2`
80pub const VAULT_RELAYER_STAGING: Address = Address::new([
81 0xc7, 0x24, 0x2d, 0x16, 0x75, 0x63, 0x35, 0x2e, 0x2b, 0xca, 0x4d, 0x71, 0xc0, 0x43, 0xfb, 0xe5,
82 0x42, 0xdb, 0x8f, 0xb2,
83]);
84
85/// The staging (barn) `EthFlow` contract address.
86///
87/// `0xb37aDD6AC288BD3825a901Cba6ec65A89f31B8CC`
88pub const BARN_ETH_FLOW: Address = Address::new([
89 0xb3, 0x7a, 0xdd, 0x6a, 0xc2, 0x88, 0xbd, 0x38, 0x25, 0xa9, 0x01, 0xcb, 0xa6, 0xec, 0x65, 0xa8,
90 0x9f, 0x31, 0xb8, 0xcc,
91]);
92
93/// The `ComposableCow` factory contract address.
94///
95/// Same address on all supported chains.
96/// `0xfdaFc9d1902f4e0b84f65F49f244b32b31013b74`
97pub const COMPOSABLE_COW: Address = Address::new([
98 0xfd, 0xaf, 0xc9, 0xd1, 0x90, 0x2f, 0x4e, 0x0b, 0x84, 0xf6, 0x5f, 0x49, 0xf2, 0x44, 0xb3, 0x2b,
99 0x31, 0x01, 0x3b, 0x74,
100]);
101
102/// Marker address to indicate that an order is buying Ether (native currency).
103///
104/// This address only has special meaning in the `buyToken` field.
105/// `0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE`
106pub const BUY_ETH_ADDRESS: Address = Address::new([0xee; 20]);
107
108/// The `CREATE2` deployer contract address.
109///
110/// Used by the hardhat-deploy library for deterministic deployments.
111/// Same on all EVM chains.
112/// `0x4e59b44847b379578588920ca78fbf26c0b4956c`
113pub const DEPLOYER_CONTRACT: Address = Address::new([
114 0x4e, 0x59, 0xb4, 0x48, 0x47, 0xb3, 0x79, 0x57, 0x85, 0x88, 0x92, 0x0c, 0xa7, 0x8f, 0xbf, 0x26,
115 0xc0, 0xb4, 0x95, 0x6c,
116]);
117
118/// The deterministic deployment salt.
119///
120/// `ethers.utils.formatBytes32String("Mattresses in Berlin!")`
121pub const SALT: &str = "0x4d61747472657373657320696e204265726c696e210000000000000000000000";
122
123/// Maximum valid-to epoch value (`u32::MAX`).
124///
125/// Used as the `validTo` timestamp for `EthFlow` orders where the actual
126/// deadline is controlled by the contract rather than the order expiry.
127pub const MAX_VALID_TO_EPOCH: u32 = u32::MAX;
128
129/// Return the production settlement contract address for `chain`.
130///
131/// Currently the same for all supported chains (deterministic deployment).
132///
133/// # Parameters
134///
135/// * `_chain` — the target chain (unused — address is identical across chains).
136///
137/// # Returns
138///
139/// [`SETTLEMENT_CONTRACT`] address.
140#[must_use]
141pub const fn settlement_contract(_chain: SupportedChainId) -> Address {
142 SETTLEMENT_CONTRACT
143}
144
145/// Return the vault relayer contract address for `chain`.
146///
147/// Currently the same for all supported chains.
148///
149/// # Arguments
150///
151/// * `_chain` — the target chain (unused — address is identical across chains).
152///
153/// # Returns
154///
155/// [`VAULT_RELAYER`] address.
156#[must_use]
157pub const fn vault_relayer(_chain: SupportedChainId) -> Address {
158 VAULT_RELAYER
159}
160
161/// Return the settlement contract address for `chain` in a given
162/// environment.
163///
164/// Returns [`SETTLEMENT_CONTRACT`] for [`Env::Prod`](super::chain::Env::Prod)
165/// and [`SETTLEMENT_CONTRACT_STAGING`] for
166/// [`Env::Staging`](super::chain::Env::Staging).
167///
168/// # Parameters
169///
170/// * `_chain` — the target chain (unused).
171/// * `env` — the orderbook environment.
172///
173/// # Returns
174///
175/// The settlement contract [`Address`] for the given environment.
176#[must_use]
177pub const fn settlement_contract_for_env(
178 _chain: SupportedChainId,
179 env: super::chain::Env,
180) -> Address {
181 match env {
182 super::chain::Env::Prod => SETTLEMENT_CONTRACT,
183 super::chain::Env::Staging => SETTLEMENT_CONTRACT_STAGING,
184 }
185}
186
187/// Return the vault relayer contract address for `chain` in a given
188/// environment.
189///
190/// # Arguments
191///
192/// * `_chain` — the target chain (unused).
193/// * `env` — the orderbook environment.
194///
195/// # Returns
196///
197/// The vault relayer [`Address`] for the given environment.
198#[must_use]
199pub const fn vault_relayer_for_env(_chain: SupportedChainId, env: super::chain::Env) -> Address {
200 match env {
201 super::chain::Env::Prod => VAULT_RELAYER,
202 super::chain::Env::Staging => VAULT_RELAYER_STAGING,
203 }
204}
205
206/// Return the `EthFlow` contract address for `chain` in a given environment.
207///
208/// # Arguments
209///
210/// * `_chain` — the target chain (unused).
211/// * `env` — the orderbook environment.
212///
213/// # Returns
214///
215/// The `EthFlow` contract [`Address`] for the given environment.
216#[must_use]
217pub const fn eth_flow_for_env(_chain: SupportedChainId, env: super::chain::Env) -> Address {
218 match env {
219 super::chain::Env::Prod => ETH_FLOW_PROD,
220 super::chain::Env::Staging => BARN_ETH_FLOW,
221 }
222}
223
224/// Return the `ComposableCow` contract address for `chain`.
225///
226/// Currently the same for all supported chains.
227///
228/// # Arguments
229///
230/// * `_chain` — the target chain (unused — address is identical across chains).
231///
232/// # Returns
233///
234/// [`COMPOSABLE_COW`] address.
235#[must_use]
236pub const fn composable_cow(_chain: SupportedChainId) -> Address {
237 COMPOSABLE_COW
238}
239
240/// Return the `ExtensibleFallbackHandler` contract address for `chain`.
241///
242/// Currently the same for all supported chains.
243///
244/// # Arguments
245///
246/// * `_chain` — the target chain (unused — address is identical across chains).
247///
248/// # Returns
249///
250/// [`EXTENSIBLE_FALLBACK_HANDLER`] address.
251#[must_use]
252pub const fn extensible_fallback_handler(_chain: SupportedChainId) -> Address {
253 EXTENSIBLE_FALLBACK_HANDLER
254}
255
256// ── Per-chain address map accessors ───────────��─────────────────────────────
257//
258// The TypeScript SDK exposes `Record<SupportedChainId, string>` maps. In Rust,
259// since all addresses are identical across chains, we provide lookup functions
260// that mirror the TS `COMPOSABLE_COW_CONTRACT_ADDRESS[chainId]` pattern.
261
262/// Return the `ComposableCow` contract address for a given chain.
263///
264/// Mirrors `COMPOSABLE_COW_CONTRACT_ADDRESS[chainId]` from the `TypeScript` SDK.
265/// Currently returns the same address for all supported chains.
266///
267/// # Arguments
268///
269/// * `_chain` — the target chain (unused — address is identical across chains).
270///
271/// # Returns
272///
273/// [`COMPOSABLE_COW`] address.
274#[must_use]
275pub const fn composable_cow_contract_address(_chain: SupportedChainId) -> Address {
276 COMPOSABLE_COW
277}
278
279/// Return the `CoW` Protocol settlement contract address for a given chain.
280///
281/// Mirrors `COW_PROTOCOL_SETTLEMENT_CONTRACT_ADDRESS[chainId]` from the `TypeScript` SDK.
282///
283/// # Arguments
284///
285/// * `_chain` — the target chain (unused — address is identical across chains).
286///
287/// # Returns
288///
289/// [`SETTLEMENT_CONTRACT`] address.
290#[must_use]
291pub const fn cow_protocol_settlement_contract_address(_chain: SupportedChainId) -> Address {
292 SETTLEMENT_CONTRACT
293}
294
295/// Return the `CoW` Protocol Vault Relayer address for a given chain.
296///
297/// Mirrors `COW_PROTOCOL_VAULT_RELAYER_ADDRESS[chainId]` from the `TypeScript` SDK.
298///
299/// # Arguments
300///
301/// * `_chain` — the target chain (unused — address is identical across chains).
302///
303/// # Returns
304///
305/// [`VAULT_RELAYER`] address.
306#[must_use]
307pub const fn cow_protocol_vault_relayer_address(_chain: SupportedChainId) -> Address {
308 VAULT_RELAYER
309}
310
311/// Return the staging `CoW` Protocol Vault Relayer address for a given chain.
312///
313/// Mirrors `COW_PROTOCOL_VAULT_RELAYER_ADDRESS_STAGING[chainId]` from the `TypeScript` SDK.
314///
315/// # Arguments
316///
317/// * `_chain` — the target chain (unused — address is identical across chains).
318///
319/// # Returns
320///
321/// [`VAULT_RELAYER_STAGING`] address.
322#[must_use]
323pub const fn cow_protocol_vault_relayer_address_staging(_chain: SupportedChainId) -> Address {
324 VAULT_RELAYER_STAGING
325}
326
327/// Return the `ExtensibleFallbackHandler` contract address for a given chain.
328///
329/// Mirrors `EXTENSIBLE_FALLBACK_HANDLER_CONTRACT_ADDRESS[chainId]` from the `TypeScript` SDK.
330///
331/// # Arguments
332///
333/// * `_chain` — the target chain (unused — address is identical across chains).
334///
335/// # Returns
336///
337/// [`EXTENSIBLE_FALLBACK_HANDLER`] address.
338#[must_use]
339pub const fn extensible_fallback_handler_contract_address(_chain: SupportedChainId) -> Address {
340 EXTENSIBLE_FALLBACK_HANDLER
341}
342
343// ── CREATE2 deterministic deployment ────────────────────────────────────────
344
345/// Compute the deterministic `CREATE2` deployment address for a contract.
346///
347/// Uses the canonical [`DEPLOYER_CONTRACT`] and [`SALT`] values from the
348/// `CoW` Protocol deployment tooling.
349///
350/// Mirrors `deterministicDeploymentAddress` from the `TypeScript` `contracts-ts` package.
351///
352/// # Arguments
353///
354/// * `bytecode` - The contract creation bytecode (init code).
355/// * `constructor_args` - ABI-encoded constructor arguments to append to the bytecode.
356///
357/// # Example
358///
359/// ```
360/// use cow_chains::contracts::deterministic_deployment_address;
361///
362/// let addr = deterministic_deployment_address(&[0xfe], &[]);
363/// assert!(!addr.is_zero());
364/// ```
365#[must_use]
366#[allow(clippy::expect_used, reason = "SALT is a compile-time constant, decode cannot fail")]
367pub fn deterministic_deployment_address(bytecode: &[u8], constructor_args: &[u8]) -> Address {
368 let salt_bytes = B256::from_slice(
369 &alloy_primitives::hex::decode(SALT.trim_start_matches("0x"))
370 .expect("SALT is always valid hex"),
371 );
372
373 // init_code = bytecode ++ constructor_args
374 let mut init_code = Vec::with_capacity(bytecode.len() + constructor_args.len());
375 init_code.extend_from_slice(bytecode);
376 init_code.extend_from_slice(constructor_args);
377 let init_code_hash = keccak256(&init_code);
378
379 // CREATE2: keccak256(0xff ++ deployer ++ salt ++ keccak256(init_code))[12..]
380 let mut buf = [0u8; 1 + 20 + 32 + 32];
381 buf[0] = 0xff;
382 buf[1..21].copy_from_slice(DEPLOYER_CONTRACT.as_slice());
383 buf[21..53].copy_from_slice(salt_bytes.as_slice());
384 buf[53..85].copy_from_slice(init_code_hash.as_slice());
385 let hash = keccak256(buf);
386 Address::from_slice(&hash[12..])
387}
388
389// ── EIP-1967 proxy storage slots ────────────────────────────────────────────
390
391/// EIP-1967 storage slot for the implementation address.
392///
393/// `bytes32(uint256(keccak256("eip1967.proxy.implementation")) - 1)`
394pub const IMPLEMENTATION_STORAGE_SLOT: &str =
395 "0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc";
396
397/// EIP-1967 storage slot for the proxy admin/owner address.
398///
399/// `bytes32(uint256(keccak256("eip1967.proxy.admin")) - 1)`
400pub const OWNER_STORAGE_SLOT: &str =
401 "0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103";
402
403/// Build `eth_getStorageAt` calldata to read the EIP-1967 implementation address.
404///
405/// Returns `(proxy_address, storage_slot)` — pass these to an `eth_getStorageAt`
406/// JSON-RPC call to retrieve the implementation address of an EIP-1967 proxy.
407///
408/// Mirrors `implementationAddress` from the `TypeScript` `contracts-ts` package.
409/// The `TypeScript` version makes a live RPC call; this Rust version returns the
410/// parameters so callers can use their preferred provider.
411///
412/// # Example
413///
414/// ```
415/// use alloy_primitives::Address;
416/// use cow_chains::contracts::implementation_address_slot;
417///
418/// let proxy = Address::ZERO;
419/// let (addr, slot) = implementation_address_slot(proxy);
420/// assert_eq!(addr, proxy);
421/// assert!(slot.starts_with("0x360894a1"));
422/// ```
423#[must_use]
424pub const fn implementation_address_slot(proxy: Address) -> (Address, &'static str) {
425 (proxy, IMPLEMENTATION_STORAGE_SLOT)
426}
427
428/// Build `eth_getStorageAt` calldata to read the EIP-1967 admin/owner address.
429///
430/// Returns `(proxy_address, storage_slot)` — pass these to an `eth_getStorageAt`
431/// JSON-RPC call to retrieve the owner address of an EIP-1967 proxy.
432///
433/// Mirrors `ownerAddress` from the `TypeScript` `contracts-ts` package.
434///
435/// # Example
436///
437/// ```
438/// use alloy_primitives::Address;
439/// use cow_chains::contracts::owner_address_slot;
440///
441/// let proxy = Address::ZERO;
442/// let (addr, slot) = owner_address_slot(proxy);
443/// assert_eq!(addr, proxy);
444/// assert!(slot.starts_with("0xb53127684a"));
445/// ```
446#[must_use]
447pub const fn owner_address_slot(proxy: Address) -> (Address, &'static str) {
448 (proxy, OWNER_STORAGE_SLOT)
449}
450
451#[cfg(test)]
452mod tests {
453 use super::{super::chain::Env, *};
454
455 #[test]
456 fn all_contract_addresses_are_nonzero() {
457 assert!(!SETTLEMENT_CONTRACT.is_zero());
458 assert!(!VAULT_RELAYER.is_zero());
459 assert!(!ETH_FLOW_PROD.is_zero());
460 assert!(!ETH_FLOW_STAGING.is_zero());
461 assert!(!EXTENSIBLE_FALLBACK_HANDLER.is_zero());
462 assert!(!SETTLEMENT_CONTRACT_STAGING.is_zero());
463 assert!(!VAULT_RELAYER_STAGING.is_zero());
464 assert!(!BARN_ETH_FLOW.is_zero());
465 assert!(!COMPOSABLE_COW.is_zero());
466 assert!(!DEPLOYER_CONTRACT.is_zero());
467 }
468
469 #[test]
470 fn buy_eth_address_is_all_ee() {
471 assert_eq!(BUY_ETH_ADDRESS, Address::new([0xee; 20]));
472 }
473
474 #[test]
475 fn prod_and_staging_addresses_differ() {
476 assert_ne!(SETTLEMENT_CONTRACT, SETTLEMENT_CONTRACT_STAGING);
477 assert_ne!(VAULT_RELAYER, VAULT_RELAYER_STAGING);
478 assert_ne!(ETH_FLOW_PROD, ETH_FLOW_STAGING);
479 }
480
481 #[test]
482 fn settlement_for_env_branches() {
483 let chain = SupportedChainId::Mainnet;
484 assert_eq!(settlement_contract_for_env(chain, Env::Prod), SETTLEMENT_CONTRACT);
485 assert_eq!(settlement_contract_for_env(chain, Env::Staging), SETTLEMENT_CONTRACT_STAGING);
486 }
487
488 #[test]
489 fn vault_relayer_for_env_branches() {
490 let chain = SupportedChainId::Mainnet;
491 assert_eq!(vault_relayer_for_env(chain, Env::Prod), VAULT_RELAYER);
492 assert_eq!(vault_relayer_for_env(chain, Env::Staging), VAULT_RELAYER_STAGING);
493 }
494
495 #[test]
496 fn eth_flow_for_env_branches() {
497 let chain = SupportedChainId::Mainnet;
498 assert_eq!(eth_flow_for_env(chain, Env::Prod), ETH_FLOW_PROD);
499 assert_eq!(eth_flow_for_env(chain, Env::Staging), BARN_ETH_FLOW);
500 }
501
502 #[test]
503 fn per_chain_lookups_return_correct_addresses() {
504 let chain = SupportedChainId::Mainnet;
505 assert_eq!(settlement_contract(chain), SETTLEMENT_CONTRACT);
506 assert_eq!(vault_relayer(chain), VAULT_RELAYER);
507 assert_eq!(composable_cow(chain), COMPOSABLE_COW);
508 assert_eq!(extensible_fallback_handler(chain), EXTENSIBLE_FALLBACK_HANDLER);
509 assert_eq!(composable_cow_contract_address(chain), COMPOSABLE_COW);
510 assert_eq!(cow_protocol_settlement_contract_address(chain), SETTLEMENT_CONTRACT);
511 assert_eq!(cow_protocol_vault_relayer_address(chain), VAULT_RELAYER);
512 assert_eq!(cow_protocol_vault_relayer_address_staging(chain), VAULT_RELAYER_STAGING);
513 assert_eq!(
514 extensible_fallback_handler_contract_address(chain),
515 EXTENSIBLE_FALLBACK_HANDLER
516 );
517 }
518
519 #[test]
520 fn deterministic_deployment_is_deterministic() {
521 let a1 = deterministic_deployment_address(&[0xfe], &[]);
522 let a2 = deterministic_deployment_address(&[0xfe], &[]);
523 assert_eq!(a1, a2);
524 assert!(!a1.is_zero());
525 }
526
527 #[test]
528 fn deterministic_deployment_varies_with_bytecode() {
529 let a = deterministic_deployment_address(&[0xfe], &[]);
530 let b = deterministic_deployment_address(&[0xff], &[]);
531 assert_ne!(a, b);
532 }
533
534 #[test]
535 fn deterministic_deployment_varies_with_args() {
536 let a = deterministic_deployment_address(&[0xfe], &[]);
537 let b = deterministic_deployment_address(&[0xfe], &[0x01]);
538 assert_ne!(a, b);
539 }
540
541 #[test]
542 fn implementation_slot_returns_proxy_and_slot() {
543 let proxy = Address::ZERO;
544 let (addr, slot) = implementation_address_slot(proxy);
545 assert_eq!(addr, proxy);
546 assert_eq!(slot, IMPLEMENTATION_STORAGE_SLOT);
547 }
548
549 #[test]
550 fn owner_slot_returns_proxy_and_slot() {
551 let proxy = Address::ZERO;
552 let (addr, slot) = owner_address_slot(proxy);
553 assert_eq!(addr, proxy);
554 assert_eq!(slot, OWNER_STORAGE_SLOT);
555 }
556
557 #[test]
558 fn max_valid_to_epoch_is_u32_max() {
559 assert_eq!(MAX_VALID_TO_EPOCH, u32::MAX);
560 }
561
562 #[test]
563 fn salt_is_valid_hex() {
564 let stripped = SALT.trim_start_matches("0x");
565 assert!(alloy_primitives::hex::decode(stripped).is_ok());
566 assert_eq!(stripped.len(), 64);
567 }
568}