Secrets are random 32-byte values that serve as the cryptographic key to unlock funds in atomic cross-chain swaps. They are the core security primitive that ensures only authorized parties can claim tokens from escrow contracts.
A secret acts like a password that locks your funds. The hash of the secret is public (the lock), but the secret itself remains private until you choose to reveal it.
// From src/domains/hash-lock/hash-lock.ts:17-24import { keccak256 } from 'ethers'public static hashSecret(secret: string): string { assert( isHexBytes(secret) && getBytesCount(secret) === 32n, 'secret length must be 32 bytes hex encoded' ) return keccak256(secret)}
Keccak256 is the same hash function used throughout Ethereum. It’s a one-way function: given a hash, it’s computationally infeasible to find the original secret without trying all possibilities.
Create Order: Submit order with hash lock (secret hash, not secret)
Wait for Escrows: Resolver deploys source and destination escrows
Verify Escrows: Check that escrows are correctly deployed
Submit Secrets: Reveal secrets to the 1inch relayer
Swap Executes: Resolver claims source tokens, user receives destination tokens
import { OrderStatus } from '@1inch/cross-chain-sdk'// After creating and submitting order...while (true) { // Check which fills are ready for secrets const secretsToShare = await sdk.getReadyToAcceptSecretFills(orderHash) if (secretsToShare.fills.length) { for (const { idx } of secretsToShare.fills) { // Reveal the secret for this fill await sdk.submitSecret(orderHash, secrets[idx]) console.log(`Submitted secret ${idx}`) } } // Check if swap is complete const { status } = await sdk.getOrderStatus(orderHash) if ( status === OrderStatus.Executed || status === OrderStatus.Expired || status === OrderStatus.Refunded ) { break } await sleep(1000)}
Always verify escrow deployments before submitting secrets:
const secretsToShare = await sdk.getReadyToAcceptSecretFills(orderHash)for (const { idx, srcEscrow, dstEscrow } of secretsToShare.fills) { // Additional verification (recommended for production) // 1. Verify escrow addresses match expected contracts const expectedSrcEscrow = calculateExpectedEscrowAddress(/* params */) if (srcEscrow !== expectedSrcEscrow) { console.error('Source escrow address mismatch!') continue } // 2. Verify escrow has correct amount const escrowBalance = await getEscrowBalance(dstEscrow) if (escrowBalance < expectedAmount) { console.error('Insufficient escrow balance!') continue } // 3. Submit secret only after verification await sdk.submitSecret(orderHash, secrets[idx])}
The SDK’s getReadyToAcceptSecretFills() performs basic checks, but production applications should implement additional verification logic specific to their security requirements.