CONFIDENTIAL -- INSTRUCTOR USE ONLY

A13: DeFi Builder

Answer Key & Expected Results

Note: All calculations below assume initial reserves of 100,000 Token A and 100,000 Token B (k = 10,000,000,000). Student results will match these numbers if they use the recommended amounts. Minor rounding differences are expected due to Solidity integer division (always rounds down).

Expected Swap Results

The constant-product formula gives: amountOut = (reserveOut * amountIn) / (reserveIn + amountIn)

Initial State (After Adding Liquidity)
Field Value
Reserve A 100,000
Reserve B 100,000
k = Reserve A × Reserve B 10,000,000,000
Price (B per A) 1.0000
Swap 1: Small Swap (1,000 Token A → Token B)
Calculation:
amountOut = (100,000 × 1,000) / (100,000 + 1,000)
amountOut = 100,000,000 / 101,000
amountOut = 990 (integer division, rounds down from 990.099...)
Field Value
Amount In (Token A) 1,000
Amount Out (Token B) 990
Reserve A (after) 101,000
Reserve B (after) 99,010
k (after) 101,000 × 99,010 = 9,999,010,000
Effective Price (B per A) 990 / 1,000 = 0.9900
Price Impact -1.0% (paid 1% worse than initial 1:1 rate)
Grading: Accept amountOut of 990. k will be slightly less than 10B due to integer rounding -- this is correct behaviour, not an error. The "lost" value (990.099... rounds to 990) stays in the pool as a tiny implicit fee.
Swap 2: Medium Swap (10,000 Token A → Token B)
Calculation: (using post-Swap-1 reserves)
amountOut = (99,010 × 10,000) / (101,000 + 10,000)
amountOut = 990,100,000 / 111,000
amountOut = 8,919 (rounds down from 8,919.82...)
Field Value
Amount In (Token A) 10,000
Amount Out (Token B) 8,919
Reserve A (after) 111,000
Reserve B (after) 90,091
k (after) 111,000 × 90,091 = 10,000,101,000
Effective Price (B per A) 8,919 / 10,000 = 0.8919
Price Impact -10.8% from initial 1:1 rate
Grading: Accept amountOut in range 8,918-8,920. Key insight students should note: this medium swap gives a much worse effective price than the small swap (0.89 vs 0.99). This demonstrates price impact scaling with trade size.
Swap 3: Large Swap (50,000 Token A → Token B)
Calculation: (using post-Swap-2 reserves)
amountOut = (90,091 × 50,000) / (111,000 + 50,000)
amountOut = 4,504,550,000 / 161,000
amountOut = 27,978 (rounds down from 27,978.57...)
Field Value
Amount In (Token A) 50,000
Amount Out (Token B) 27,978
Reserve A (after) 161,000
Reserve B (after) 62,113
k (after) 161,000 × 62,113 = 10,000,193,000
Effective Price (B per A) 27,978 / 50,000 = 0.5596
Price Impact -44.0% from initial 1:1 rate
Grading: Accept amountOut in range 27,977-27,979. This swap dramatically demonstrates how large trades move the price. The effective price (0.56) is nearly half the initial rate. Students should recognise this as the core lesson about liquidity depth and slippage.
Swap 4: Reverse Swap (10,000 Token B → Token A)
Calculation: (using post-Swap-3 reserves)
amountOut = (161,000 × 10,000) / (62,113 + 10,000)
amountOut = 1,610,000,000 / 72,113
amountOut = 22,326 (rounds down from 22,326.06...)
Field Value
Amount In (Token B) 10,000
Amount Out (Token A) 22,326
Reserve A (after) 138,674
Reserve B (after) 72,113
k (after) 138,674 × 72,113 = 9,999,261,362
Effective Price (A per B) 22,326 / 10,000 = 2.2326
Price Impact Token A is now "cheap" relative to B (reserves skewed), so swapping B for A gives more than 1:1
Grading: Accept amountOut in range 22,325-22,327. Key insight: the reverse swap gets a favourable rate because the pool is heavily skewed toward Token A. This demonstrates arbitrage opportunity -- a real trader would buy the "cheap" token.

Complete Results Summary Table

Step Action Amount In Amount Out Reserve A Reserve B k Eff. Price
Initial Add Liquidity 100,000 / 100,000 - 100,000 100,000 10,000,000,000 1.0000
Swap 1 1,000 A → B 1,000 A 990 B 101,000 99,010 9,999,010,000 0.9900
Swap 2 10,000 A → B 10,000 A 8,919 B 111,000 90,091 10,000,101,000 0.8919
Swap 3 50,000 A → B 50,000 A 27,978 B 161,000 62,113 10,000,193,000 0.5596
Swap 4 10,000 B → A 10,000 B 22,326 A 138,674 72,113 9,999,261,362 2.2326*

* Swap 4 price is A per B (reverse direction). All other prices are B per A.

Note on k Variation: The product k is not perfectly constant because Solidity uses integer division (always rounds down). The rounding error accumulates slightly with each swap. In production AMMs like Uniswap, a small fee (0.3%) is added to each swap, which causes k to gradually increase. Our SimpleDEX has no fee, so k only varies due to rounding.

Analysis Question Answers

Q1: Why does a larger swap give a worse effective price?

Expected Answer: The constant-product formula x × y = k means that as you buy more of one token, the remaining supply in the pool decreases, making each additional unit more expensive. A 1,000-token swap only moves the reserves by ~1%, giving a near-1:1 rate (0.99). A 50,000-token swap moves reserves dramatically (~50%), giving a much worse rate (0.56). This is the core concept of price impact or slippage.

Analogy: It is like buying apples at a market. The first few are cheap, but if you try to buy half the market's supply, the price per apple rises sharply because supply is running out.

Grading (1.5 pts): Full credit for explaining that larger trades move reserves more, causing worse rates. Partial credit for noting "bigger = worse price" without mechanism.
Q2: Does x × y = k hold exactly after each swap? Why or why not?

Expected Answer: k is approximately constant but not exact. Small variations occur because Solidity performs integer division, which always rounds down. For example, when the formula gives 990.099 tokens, the contract sends 990 tokens. The 0.099 tokens effectively stay in the pool, slightly changing k. In a real DEX like Uniswap, there is an explicit 0.3% fee that makes k increase over time, benefiting liquidity providers.

Grading (1 pt): Full credit for mentioning integer division / rounding. Accept mention of fees if student connects to real DEXes.
Q3: What happened when you swapped in the reverse direction? Why?

Expected Answer: The reverse swap (B → A) gave a very favourable rate because after three A → B swaps, the pool was heavily skewed: lots of Token A, relatively little Token B. This means Token A was "cheap" and Token B was "expensive" in the pool. Swapping B for A exploits this imbalance -- you get more than 2 Token A per Token B. In the real world, this creates an arbitrage opportunity: traders would buy the cheap token until prices equalise with other markets.

Grading (1.5 pts): Full credit for explaining reserve imbalance and connecting to arbitrage. Partial credit for noting the rate was better without explaining why.

Common Student Mistakes

Deployment Issues:
  • Forgot approve(): Most common error. Swap reverts with "Allowance exceeded" or "transfer amount exceeds allowance". Solution: call approve on the token contract with DEX address and amount before each swap.
  • Wrong token address in DEX constructor: Student passes the DEX address instead of token address. Cannot recover -- must redeploy DEX.
  • Approving the wrong contract: Student approves Token A to spend Token B, or approves their own address instead of the DEX address.
  • Insufficient approval amount: Student approves 1000 but tries to swap 10000. Must approve at least the swap amount.
Worksheet Errors:
  • Using initial reserves for all calculations: Each swap must use the post-previous-swap reserves, not the initial 100,000/100,000.
  • Confusing direction: For the reverse swap, the output is Token A (not B). Students sometimes record it backwards.
  • Expecting exact k: Students flag the slight k variation as an "error" when it is actually correct integer division behaviour.
  • Missing units: Not specifying which token is "in" and which is "out" for each swap.

Bonus Extension Answers

Bonus A: Slippage Protection

Modified swap function:

function swap(address _tokenIn, uint256 _amountIn, uint256 _minOut) external { // ... same logic as before ... uint256 amountOut = (reserveOut * _amountIn) / (reserveIn + _amountIn); require(amountOut >= _minOut, "Slippage too high"); // NEW LINE // ... rest of function ... }

Demonstration:

  • Call swap(tokenA, 10000, 8000) -- succeeds (8,919 > 8,000)
  • Call swap(tokenA, 10000, 9500) -- reverts (actual output < 9,500)
Grading (+5 pts): Full credit for working implementation + demonstration of both success and revert cases. 3-4 pts for working code without revert demo. 1-2 pts for concept understanding without working code.
Bonus B: Simple Escrow

Expected flow:

  1. Deploy Escrow contract with buyer, seller, arbiter addresses and amount
  2. Buyer calls deposit() with the correct ETH value
  3. After simulated delivery, buyer calls confirmDelivery()
  4. Seller receives the ETH

Connection to DEX: Student should explain that escrow provides trust for off-chain delivery while the DEX handles on-chain token swaps. Together they enable trustless commerce: trade tokens on DEX, escrow ETH for physical goods.

Grading (+5 pts): Full credit for complete escrow flow + explanation of how it complements the DEX. 3-4 pts for deployment + partial flow. 1-2 pts for deployment only.

© Joerg Osterrieder 2025-2026. All rights reserved.