| add love contract 9bf25a7 julienbrg 8h ago | 1 | // SPDX-License-Identifier: MIT |
| 2 | pragma solidity ^0.8.30; |
| 3 | |
| make love an erc20 with public mint 4c8048e julienbrg 8h ago | 4 | import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; |
| Merge 3-peg-love-to-weth into main ce13509 rickub 7h ago | 5 | import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; |
| 6 | import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; |
| add love contract 9bf25a7 julienbrg 8h ago | 7 | |
| make love an erc20 with public mint 4c8048e julienbrg 8h ago | 8 | /// @title Love |
| Merge 3-peg-love-to-weth into main ce13509 rickub 7h ago | 9 | /// @author Julien Béranger |
| 10 | /// @notice An ERC-20 pegged to wETH at a fixed rate of 100000 LOVE per wETH. |
| 11 | /// Every LOVE in circulation is backed by wETH held by this contract: |
| 12 | /// supply only moves through `deposit` and `withdraw`, and both are |
| 13 | /// permissionless. |
| 14 | /// @dev There is no mint entrypoint, no owner and no upgrade path, so the peg |
| 15 | /// cannot be diluted. `totalSupply() == WETH.balanceOf(address(this)) * RATE` |
| 16 | /// holds after every call; wETH transferred straight to this contract |
| 17 | /// raises the backing and is not redeemable. |
| make love an erc20 with public mint 4c8048e julienbrg 8h ago | 18 | contract Love is ERC20 { |
| Merge 3-peg-love-to-weth into main ce13509 rickub 7h ago | 19 | using SafeERC20 for IERC20; |
| add love contract 9bf25a7 julienbrg 8h ago | 20 | |
| Merge 3-peg-love-to-weth into main ce13509 rickub 7h ago | 21 | /// @notice LOVE minted per unit of wETH, and burned per unit released. |
| 22 | uint256 public constant RATE = 100_000; |
| 23 | |
| 24 | /// @notice The wETH this token is pegged to and collateralised with. |
| 25 | /// @dev Immutable, and part of the creation code — two chains only give this |
| 26 | /// contract the same CREATE2 address if they share a wETH address. |
| 27 | IERC20 public immutable WETH; |
| 28 | |
| 29 | /// @notice Thrown when a withdrawal amount is not a multiple of `RATE`. |
| 30 | /// @param loveAmount The rejected LOVE amount. |
| 31 | /// @param rate The rate it has to be a multiple of. |
| 32 | error AmountNotDivisibleByRate(uint256 loveAmount, uint256 rate); |
| 33 | |
| 34 | /// @notice Emitted when wETH is locked and LOVE minted. |
| 35 | /// @param account The depositor, who pays the wETH and receives the LOVE. |
| 36 | /// @param wethAmount The wETH pulled in. |
| 37 | /// @param loveAmount The LOVE minted, `wethAmount * RATE`. |
| 38 | event Deposit(address indexed account, uint256 wethAmount, uint256 loveAmount); |
| 39 | |
| 40 | /// @notice Emitted when LOVE is burned and wETH released. |
| 41 | /// @param account The redeemer, who burns the LOVE and receives the wETH. |
| 42 | /// @param loveAmount The LOVE burned. |
| 43 | /// @param wethAmount The wETH released, `loveAmount / RATE`. |
| 44 | event Withdraw(address indexed account, uint256 loveAmount, uint256 wethAmount); |
| 45 | |
| 46 | /// @param weth_ The wETH to peg to. Set once, never changed. |
| 47 | constructor(IERC20 weth_) ERC20("Love", "LOVE") { |
| 48 | WETH = weth_; |
| 49 | } |
| 50 | |
| 51 | /// @notice Lock `wethAmount` wETH and mint `wethAmount * RATE` LOVE to the caller. |
| 52 | /// @dev The caller must have approved this contract for `wethAmount` first. |
| 53 | /// Reverts on overflow of `wethAmount * RATE`, and on the wETH transfer |
| 54 | /// failing for want of balance or allowance. |
| 55 | /// @param wethAmount The wETH to lock, in wei. |
| 56 | function deposit(uint256 wethAmount) external { |
| 57 | uint256 loveAmount = wethAmount * RATE; |
| 58 | |
| 59 | WETH.safeTransferFrom(msg.sender, address(this), wethAmount); |
| 60 | _mint(msg.sender, loveAmount); |
| 61 | |
| 62 | emit Deposit(msg.sender, wethAmount, loveAmount); |
| 63 | } |
| 64 | |
| 65 | /// @notice Burn `loveAmount` LOVE and release `loveAmount / RATE` wETH to the caller. |
| 66 | /// @dev Reverts with `AmountNotDivisibleByRate` unless `loveAmount` is a |
| 67 | /// multiple of `RATE`, so the peg never rounds against the caller or |
| 68 | /// the remaining holders. LOVE is burned before the wETH leaves, and |
| 69 | /// the burn already caps the amount at the caller's balance. |
| 70 | /// @param loveAmount The LOVE to burn, a multiple of `RATE`. |
| 71 | function withdraw(uint256 loveAmount) external { |
| 72 | if (loveAmount % RATE != 0) revert AmountNotDivisibleByRate(loveAmount, RATE); |
| 73 | |
| 74 | uint256 wethAmount = loveAmount / RATE; |
| 75 | |
| 76 | _burn(msg.sender, loveAmount); |
| 77 | WETH.safeTransfer(msg.sender, wethAmount); |
| 78 | |
| 79 | emit Withdraw(msg.sender, loveAmount, wethAmount); |
| add love contract 9bf25a7 julienbrg 8h ago | 80 | } |
| 81 | } |