julien/lovepublic Fork 0
a34c2e887f1d3af813774b021d2c9bfc47d4ac10
Commits
Clone
git clone https://git.rickub.com/julien/love.git
git clone ssh://git@rickub.com/julien/love.git

Host key fingerprint (ed25519): SHA256:iycHnxEyq0Q7uyVpB7JlznP0G7JrTPXLYRcAU5CSLhc — verify it before your first connect.

Love.sol · 118 lines · 5.7 KBSolidity Blame HistoryRaw
add love contract 9bf25a7 julienbrg 11h ago1// SPDX-License-Identifier: MIT
2pragma solidity ^0.8.30;
3
read weth from the registry instead of a constructor arg ffa4716 julienbrg 8h ago4import {IWETH} from "./IWETH.sol";
5import {WETHRegistry} from "./WETHRegistry.sol";
make love an erc20 with public mint 4c8048e julienbrg 11h ago6import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
Merge 3-peg-love-to-weth into main ce13509 rickub 9h ago7import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
8import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
add love contract 9bf25a7 julienbrg 11h ago9
make love an erc20 with public mint 4c8048e julienbrg 11h ago10/// @title Love
Merge 3-peg-love-to-weth into main ce13509 rickub 9h ago11/// @author Julien Béranger
12/// @notice An ERC-20 pegged to wETH at a fixed rate of 100000 LOVE per wETH.
13/// Every LOVE in circulation is backed by wETH held by this contract:
14/// supply only moves through `deposit` and `withdraw`, and both are
15/// permissionless.
16/// @dev There is no mint entrypoint, no owner and no upgrade path, so the peg
17/// cannot be diluted. `totalSupply() == WETH.balanceOf(address(this)) * RATE`
18/// holds after every call; wETH transferred straight to this contract
19/// raises the backing and is not redeemable.
make love an erc20 with public mint 4c8048e julienbrg 11h ago20contract Love is ERC20 {
Merge 3-peg-love-to-weth into main ce13509 rickub 9h ago21 using SafeERC20 for IERC20;
add love contract 9bf25a7 julienbrg 11h ago22
Merge 3-peg-love-to-weth into main ce13509 rickub 9h ago23 /// @notice LOVE minted per unit of wETH, and burned per unit released.
24 uint256 public constant RATE = 100_000;
25
read weth from the registry instead of a constructor arg ffa4716 julienbrg 8h ago26 /// @notice The registry this token asks which wETH to peg to.
27 /// @dev `WETHRegistry` takes no constructor arguments, so CREATE2 puts it
28 /// at this address on every chain. Asking it at construction time,
29 /// rather than taking wETH as a constructor argument, is what keeps
30 /// this contract's creation code byte-identical everywhere — and so
31 /// what gives LOVE one address on every chain instead of one per wETH
32 /// deployment.
33 ///
34 /// Derived from the registry's creation code, which means it moves if
35 /// `WETHRegistry`, the solc version or the optimizer settings change.
36 /// `LoveRegistryAddressTest` recomputes it and fails if this constant
37 /// has drifted.
38 address public constant REGISTRY = 0x9Cf17430fEdEC487518416D1Cdc849b1eE9CDbA3;
39
Merge 3-peg-love-to-weth into main ce13509 rickub 9h ago40 /// @notice The wETH this token is pegged to and collateralised with.
read weth from the registry instead of a constructor arg ffa4716 julienbrg 8h ago41 /// @dev Read once from the registry and immutable thereafter. The registry
42 /// is itself write-once, so nothing can move the token under the peg.
Merge 3-peg-love-to-weth into main ce13509 rickub 9h ago43 IERC20 public immutable WETH;
44
45 /// @notice Thrown when a withdrawal amount is not a multiple of `RATE`.
46 /// @param loveAmount The rejected LOVE amount.
47 /// @param rate The rate it has to be a multiple of.
48 error AmountNotDivisibleByRate(uint256 loveAmount, uint256 rate);
49
read weth from the registry instead of a constructor arg ffa4716 julienbrg 8h ago50 /// @notice Thrown when there is no registry on this chain yet.
51 /// @param registry The address the registry would be at.
52 error RegistryNotDeployed(address registry);
53
54 /// @notice Thrown when the registry exists but holds no wETH yet.
55 /// @param registry The registry that was asked.
56 error WethNotRegistered(address registry);
57
Merge 3-peg-love-to-weth into main ce13509 rickub 9h ago58 /// @notice Emitted when wETH is locked and LOVE minted.
59 /// @param account The depositor, who pays the wETH and receives the LOVE.
60 /// @param wethAmount The wETH pulled in.
61 /// @param loveAmount The LOVE minted, `wethAmount * RATE`.
62 event Deposit(address indexed account, uint256 wethAmount, uint256 loveAmount);
63
64 /// @notice Emitted when LOVE is burned and wETH released.
65 /// @param account The redeemer, who burns the LOVE and receives the wETH.
66 /// @param loveAmount The LOVE burned.
67 /// @param wethAmount The wETH released, `loveAmount / RATE`.
68 event Withdraw(address indexed account, uint256 loveAmount, uint256 wethAmount);
69
read weth from the registry instead of a constructor arg ffa4716 julienbrg 8h ago70 /// @notice Peg to whatever wETH the registry has accepted on this chain.
71 /// @dev Takes no arguments on purpose. Anything passed in here would land
72 /// in the creation code and give the token a different address on
73 /// every chain whose wETH sits elsewhere, which is exactly what this
74 /// design exists to avoid.
75 ///
76 /// Reverts when the registry is missing or empty, so a chain with no
77 /// reviewed wETH gets no half-configured token: deploy the registry
78 /// and register wETH first, then deploy this.
79 constructor() ERC20("Love", "LOVE") {
80 if (REGISTRY.code.length == 0) revert RegistryNotDeployed(REGISTRY);
81
82 IWETH registered = WETHRegistry(payable(REGISTRY)).weth();
83 if (address(registered) == address(0)) revert WethNotRegistered(REGISTRY);
84
85 WETH = IERC20(address(registered));
Merge 3-peg-love-to-weth into main ce13509 rickub 9h ago86 }
87
88 /// @notice Lock `wethAmount` wETH and mint `wethAmount * RATE` LOVE to the caller.
89 /// @dev The caller must have approved this contract for `wethAmount` first.
90 /// Reverts on overflow of `wethAmount * RATE`, and on the wETH transfer
91 /// failing for want of balance or allowance.
92 /// @param wethAmount The wETH to lock, in wei.
93 function deposit(uint256 wethAmount) external {
94 uint256 loveAmount = wethAmount * RATE;
95
96 WETH.safeTransferFrom(msg.sender, address(this), wethAmount);
97 _mint(msg.sender, loveAmount);
98
99 emit Deposit(msg.sender, wethAmount, loveAmount);
100 }
101
102 /// @notice Burn `loveAmount` LOVE and release `loveAmount / RATE` wETH to the caller.
103 /// @dev Reverts with `AmountNotDivisibleByRate` unless `loveAmount` is a
104 /// multiple of `RATE`, so the peg never rounds against the caller or
105 /// the remaining holders. LOVE is burned before the wETH leaves, and
106 /// the burn already caps the amount at the caller's balance.
107 /// @param loveAmount The LOVE to burn, a multiple of `RATE`.
108 function withdraw(uint256 loveAmount) external {
109 if (loveAmount % RATE != 0) revert AmountNotDivisibleByRate(loveAmount, RATE);
110
111 uint256 wethAmount = loveAmount / RATE;
112
113 _burn(msg.sender, loveAmount);
114 WETH.safeTransfer(msg.sender, wethAmount);
115
116 emit Withdraw(msg.sender, loveAmount, wethAmount);
add love contract 9bf25a7 julienbrg 11h ago117 }
118}