§ 01
What your signature commits you to.
The struct below is the whole agreement. It is hashed with the domain separator for Kryptis v1, signed in your wallet, and goes no further than the matching engine until someone takes the other side.
Yes, the domain still says Kryptis. The contract predates the rename and touching that string would invalidate every signature already produced against it. It moves at the next deploy, not before.
The typed data
struct Intent {
address trader; // must equal msg.sender
address tokenIn;
address tokenOut;
uint256 amountIn;
uint256 minAmountOut; // your floor, enforced on-chain
uint256 slippageBps; // must be 0
uint256 deadline;
uint256 nonce; // strictly increasing
}
The quote, decimal-aware
function quote(address tokenIn, address tokenOut, uint256 amountIn)
public view returns (uint256)
{
uint256 pIn = priceUsd8[tokenIn];
uint256 pOut = priceUsd8[tokenOut];
if (pIn == 0 || pOut == 0) revert NoPrice();
uint8 dIn = IERC20Metadata(tokenIn).decimals();
uint8 dOut = IERC20Metadata(tokenOut).decimals();
return (amountIn * pIn * (10 ** uint256(dOut)))
/ (pOut * (10 ** uint256(dIn)));
}
Settlement — every branch is a revert
function executeIntent(
Intent calldata intent,
bytes calldata signature,
bytes calldata proof
) external nonReentrant returns (bytes32 intentHash, uint256 amountOut) {
if (intent.amountIn == 0) revert ZeroAmount();
if (intent.tokenIn == intent.tokenOut) revert SameToken();
if (block.timestamp > intent.deadline) revert Expired();
if (intent.trader != msg.sender) revert Unauthorized();
if (intent.nonce <= usedNonces[intent.trader]) revert NonceUsed();
if (intent.slippageBps != 0) revert Slippage();
intentHash = hashIntent(intent);
if (settled[intentHash]) revert AlreadySettled();
address signer = ECDSA.recover(intentHash, signature);
if (signer != intent.trader) revert BadSignature();
if (!_verifyAttestation(proof, intentHash)) revert InvalidProof();
amountOut = quote(intent.tokenIn, intent.tokenOut, intent.amountIn);
if (amountOut < intent.minAmountOut) revert Slippage();
if (IERC20(intent.tokenOut).balanceOf(address(this)) < amountOut)
revert InsufficientLiquidity();
usedNonces[intent.trader] = intent.nonce;
settled[intentHash] = true;
IERC20(intent.tokenIn).safeTransferFrom(intent.trader, address(this), intent.amountIn);
IERC20(intent.tokenOut).safeTransfer(intent.trader, amountOut);
emit IntentSettled(intentHash, intent.trader, intent.tokenIn,
intent.tokenOut, intent.amountIn, amountOut);
}
KryptisIntentPool · Solidity 0.8.24 · domain Kryptis v1