# Keys, Wallets, Testnets and Layer 2s — Blockchain & Smart Contracts (Solidity)

Source: https://www.geekswithgeeks.com/en/solidity/b-wallets

> Understand key management, signatures, testnets and scaling networks.

## Your keys, your responsibility

An EOA is controlled by a **private key**, a 256-bit secret. The **public key** is derived from it with elliptic-curve cryptography (secp256k1), and the **address** is derived from the public key's Keccak-256 hash. Signing a transaction proves control without revealing the key. **Wallets** such as MetaMask, Rabby or hardware wallets store keys, usually generated from a **seed phrase** (12 or 24 words, BIP-39) that can restore every account; anyone with the seed phrase controls the funds, and nobody can recover it if it is lost. **Smart contract wallets** such as **Safe** multisigs require several signers, and **account abstraction** (ERC-4337, and EIP-7702 for EOAs) enables features like social recovery, spending limits and sponsored gas. For development, use **testnets** such as **Sepolia**, with free test ether from faucets, and local chains (Anvil or Hardhat Network). **Layer 2 rollups** execute transactions off the main chain and post compressed data and proofs to Ethereum: **optimistic rollups** assume validity with a challenge period, while **zero-knowledge rollups** post validity proofs. Never paste a private key or seed phrase into a website, chat or repository.

## Signing and verifying a message

Recovering a signer's address in Solidity with ECDSA from OpenZeppelin.

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

import {ECDSA} from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
import {MessageHashUtils} from "@openzeppelin/contracts/utils/cryptography/MessageHashUtils.sol";

contract SignatureCheck {
    using ECDSA for bytes32;

    /// Returns true if `signature` was produced by `expectedSigner` over `message`
    /// using the standard "\x19Ethereum Signed Message" prefix (personal_sign).
    function isSignedBy(string calldata message, bytes calldata signature, address expectedSigner)
        external
        pure
        returns (bool)
    {
        bytes32 digest = MessageHashUtils.toEthSignedMessageHash(bytes(message));
        return digest.recover(signature) == expectedSigner;
    }
}

// In practice, include a nonce, a deadline and the chain id in signed data
// (for example with EIP-712 typed data) to prevent replay.
```

## Separate keys by risk

Use a fresh development wallet with only testnet funds for coding, a hardware wallet for real funds, and a multisig for anything controlling production contracts or treasuries.

**Quiz:** What happens if you lose your seed phrase and your device?

- [ ] The network resets your password
- [ ] The exchange restores it automatically
- [x] You lose access to the accounts; there is no central recovery
- [ ] You can recover it from your address

*Answer:* You lose access to the accounts; there is no central recovery. Self-custodied keys cannot be recovered without the seed phrase or a recovery mechanism you set up.
