Skip to main content

Security & Operational Guidance

Evix is designed with minimal surface area and on-chain enforcement. This page covers best practices for secure integration.

On-Chain Protections

The Evix contract enforces safety checks at the contract level — these cannot be bypassed by the SDK or caller:

ProtectionMechanismError
Deadline enforcementReverts if block.timestamp > deadlineDeadlineExceeded()
Slippage protectionReverts if output < minAmountOutInsufficientOutput(amountOut, minAmountOut)
Input validationReverts if amountIn == 0InvalidAmountIn()
Recipient validationReverts if recipient == address(0)InvalidRecipient()
Pair access controlReverts if pair not allowlistedUnsupportedPair(tokenIn, tokenOut)

Best Practices

Always set minAmountOut

Never use minAmountOut: 0 in production transactions. This leaves the swap completely unprotected against price movement and MEV.

// Bad — no slippage protection
const result = await evix.swap({
...params,
minAmountOut: 0n, // DANGEROUS in production
});

// Good — 0.5% slippage tolerance
const expected = await evix.simulateSwap(params);
const minOut = expected - (expected * 50n) / 10_000n;
const result = await evix.swap({
...params,
minAmountOut: minOut,
});

Use tight deadlines

Short deadlines prevent stale transactions from landing in unfavorable conditions.

Use CaseRecommended Deadline
Trading bots15–30 seconds
Backend services30–60 seconds
User-facing flows60–120 seconds

Simulate before executing

Simulation catches problems before gas is spent:

  • Unsupported pairs
  • Invalid amounts
  • Stale pricing
  • Contract-level reverts
// Always simulate first
const expected = await evix.simulateSwap(params);

// Then execute with the simulation result informing your minAmountOut

Validate recipients

Ensure the recipient address is correctly derived and never user-controlled without validation. A malicious or incorrect recipient means tokens are sent to the wrong address with no recourse.

Maintain deployment mappings

For multi-chain or multi-customer systems, maintain explicit configuration:

const deployments: Record<string, EvixDeployment> = {
"customer-a-base": {
chainId: 8453,
contractAddress: "0x...",
supportedPairs: [["0x...", "0x..."]],
},
"customer-a-arbitrum": {
chainId: 42161,
contractAddress: "0x...",
supportedPairs: [["0x...", "0x..."]],
},
};

Operational Guidance

Token Approvals

Before swapping, the Evix contract must be approved to spend tokenIn:

// Approve exact amount (recommended)
await walletClient.writeContract({
address: tokenIn,
abi: erc20Abi,
functionName: "approve",
args: [evixAddress, amountIn],
});
tip

Consider using exact approvals rather than type(uint256).max to minimize approval surface.

Error Handling

Handle all revert cases explicitly:

try {
const result = await evix.swap(params);
} catch (error) {
if (error.message.includes("DeadlineExceeded")) {
// Transaction was too slow — consider shorter deadlines
} else if (error.message.includes("InsufficientOutput")) {
// Price moved beyond slippage tolerance — re-simulate and retry
} else if (error.message.includes("UnsupportedPair")) {
// Pair not enabled on this deployment — check configuration
}
}

Monitoring

For production integrations, monitor:

  • Swap events — Track execution via the Swap event
  • Revert rates — High revert rates indicate stale pricing or tight slippage
  • Gas costs — Monitor gas consumption across chains
  • Output quality — Compare actual output to simulated output over time