User Protection
The Welsh Street Exchange leverages the security and added user protections of the Stacks blockchain to implement slippage in an innovative way.
Post-Conditions
In Stacks — Post-conditions are transaction-level assertions enforced by the Clarity runtime at commit time. They state what must be true about asset movements (who can send or receive how much of which asset). If any post-condition is violated, the entire transaction aborts with no state changes — no partial swaps, no surprise fees.
Post-conditions are not Clarity code. They are attached to the signed transaction and enforced by nodes when the transaction is processed. This lets us keep contract logic lean while giving users hard, chain-native guarantees.
Stacks API ↔ Contract Runtime
- Client / API (tx building): The wallet or app constructs the transaction and attaches post-conditions using Stacks SDK helpers (e.g.,
makeStandardFungiblePostCondition,makeContractFungiblePostCondition). It broadcasts via the Stacks node API. - Chain / Runtime (enforcement): When our Clarity
swap(or similar) function executes, the VM tracks real asset deltas for principals mentioned in the post-conditions. At the end, it checks those deltas against our declared bounds. If any bound fails, the transaction reverts.
In short: Clarity executes the swap; the Stacks runtime enforces the promises your transaction makes about asset movements.
Slippage (Upper & Lower Bounds)
In the Welsh Street Exchange, the upper and lower bounds of the post-conditions are defined by Slippage. There are no slippage calculations on-chain. Both lower and upper bounds via post-conditions protect the user AND the liquidity pool. Because the liquidity pool is composed of user-provided liquidity, our AMM effectively protects ALL the users.
-
User protection (min-out):
I will spend at most X of token A and I must receive at least Y of token B.
If the pool’s state would result in less than Y, the tx fails safely.
-
Pool / Exchange protection (max-out):
The pool will not send more than Z of token B in this trade.
This prevents a single trade from extracting an outsized windfall—which would otherwise be a loss to liquidity providers. Protecting the pool protects all users because LPs (users) are the owners of the liquidity pool and the rewards pool.
Because post-conditions live on the transaction, these guardrails don’t bloat the contract with extra branching, keeping it lightweight, gas-efficient, and fast.
A Stacks Superpower
On many chains, “slippage” is just a UI field or ad‑hoc contract logic — extra code paths, higher gas, and more audit surface. Stacks elevates execution guarantees to the transaction layer: cryptographically enforced, chain-native, and composable. Builders get lean, auditable code while users get protocol‑level safety rails.
Our AMM uses slippage as upper and lower bounds to protect traders and LPs, delivering clean failure instead of bad fills and keeping our contracts tight, fast, and resilient. It’s not just safer — it’s a better developer and user experience.
Threats & How Post-Conditions Help
-
MEV Sandwiching: If front/back-running pushes price outside your declared bounds, your min‑out / max‑in conditions fail. No toxic fill.
-
Extreme Market Conditions (spikes, liquidity shocks): Rapid swings can’t slip your fill beyond what you allowed. The tx either meets your bounds or safely reverts.
-
Slippage Protection: Encoded directly as post-conditions (“spend ≤ X”, “receive ≥ Y”), enforced by the chain—stronger than UI-only checks.
-
Reasonable Fee Limits: Cap what the treasury/fee contract can collect per tx. If a misconfig would exceed that cap, the tx reverts.
Example 1 — Massive Move
A whale submits a huge swap that is in the mempool, but your quote is based on the previous state. You submit your trade right after.
- Your tx post-conditions (attached by your wallet):
- Spend ≤ 1,000 A (
LessEqualon your standard principal for token A) - Pool must send ≥ 480 B (
GreaterEqualon the AMM contract principal for token B)
- Spend ≤ 1,000 A (
Two possible outcomes at commit time:
-
Whale confirms first → price moves down. Re-evaluating your tx against the new pool state yields only 430 B for your 1,000 A.
- The “pool sends ≥ 480 B” condition fails → transaction reverts.
- You keep your A, pay no fees, no partial fills.
-
Whale confirms after you (or not at all). The current state still supports ≥ 480 B out.
- Both conditions pass → transaction executes and you receive at least your promised amount.
Example 2 — Anti-Windfall
Due to a sudden oracle misread off-chain or a pending arbitrage, your quote could—momentarily—suggest an outsized payout.
- AMM sets a pool-side post-condition for swaps routed through the contract: “Pool will not send more than Z B for this trade.”
Example 3 — Fee Ceiling
The protocol fee is configured as 2% maximum. A misconfiguration or upgrade could try to take more.
- User tx includes a fee-limit post-condition against the treasury contract principal: “Treasury may receive ≤ F units for this transaction.”
TL;DR
- Less on-chain code: Fewer branches and state checks → smaller attack surface.
- Lower gas: Guarantees move out of contract logic into the tx layer.
- Faster execution: Simple, predictable paths in Clarity.
- Better UX: Users and LPs get deterministic, enforceable bounds on price, payout, and fees.
- Enhanced Protection: Protect users and LPs from windfalls, massive moves and extreme volatility