# DeFi Building Blocks and Layer 2s — Blockchain & Smart Contracts (Solidity)

Source: https://www.geekswithgeeks.com/en/solidity/g-defi

> Understand AMMs, lending, stablecoins and scaling, and their risks.

## Decentralised finance in brief

**DeFi** composes contracts into financial services. **Automated market makers (AMMs)** such as Uniswap hold pools of two tokens and price trades with a formula; the classic **constant product** model keeps `x * y = k`, so buying one token raises its price, with **slippage** growing for larger trades; liquidity providers earn fees but face **impermanent loss** when prices move. **Lending protocols** (such as Aave and Compound) let users deposit collateral and borrow other assets, with **liquidations** when collateral value falls below a threshold, relying on oracles. **Stablecoins** track a currency through fiat reserves (USDC), crypto over-collateralisation (DAI and its successors) or other mechanisms, some of which have failed spectacularly. **ERC-4626** standardises yield-bearing **vaults** with shares. **Flash loans** lend any amount within a single transaction if repaid, useful for arbitrage and, unfortunately, for attacks. **Layer 2 rollups** reduce fees for all of these, and since the **Dencun** upgrade (2024), rollups post data in cheaper **blobs**. DeFi carries smart contract, oracle, liquidity, governance, regulatory and counterparty risks; this course teaches the technology, not investment advice.

## Constant-product swap math

Output amount for an x*y=k pool with a 0.3% fee, as in Uniswap v2.

```solidity
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;

library ConstantProduct {
    error InsufficientLiquidity();
    error InsufficientInput();

    /// Given amountIn of token A and reserves (reserveIn, reserveOut),
    /// returns how much token B the pool gives out after a 0.3% fee.
    function getAmountOut(uint256 amountIn, uint256 reserveIn, uint256 reserveOut)
        internal
        pure
        returns (uint256 amountOut)
    {
        if (amountIn == 0) revert InsufficientInput();
        if (reserveIn == 0 || reserveOut == 0) revert InsufficientLiquidity();
        uint256 amountInWithFee = amountIn * 997;                    // 0.3% fee kept in the pool
        uint256 numerator = amountInWithFee * reserveOut;
        uint256 denominator = reserveIn * 1000 + amountInWithFee;
        amountOut = numerator / denominator;                          // rounds down in the pool's favour
    }
}

// Example: reserves 1,000 A and 1,000 B, swap in 100 A:
//   out = 100*997*1000 / (1000*1000 + 100*997) = 99,700,000 / 1,099,700 ≈ 90.66 B
// The ideal price ignoring slippage and fees would give 100 B.
// A router should also take a minAmountOut (slippage limit) and a deadline from the user.
```

## Always set slippage limits

A swap without a minimum output amount can be sandwiched by bots: they buy before you and sell after you, and you receive far less. Slippage limits and deadlines protect users.

**Quiz:** In a constant-product AMM, what happens to the price of token B as you buy more of it in one trade?

- [x] It rises, so larger trades get worse average prices (slippage)
- [ ] It stays the same
- [ ] It falls
- [ ] Trading stops

*Answer:* It rises, so larger trades get worse average prices (slippage). x*y=k makes each additional unit more expensive as reserves of B shrink.
