71 lines
2.1 KiB
Solidity
71 lines
2.1 KiB
Solidity
// SPDX-License-Identifier: MIT
|
|
pragma solidity ^0.8.20;
|
|
|
|
import "@openzeppelin-contracts/token/ERC20/extensions/ERC20Permit.sol";
|
|
|
|
contract Reserve is ERC20Permit {
|
|
address private immutable _owner;
|
|
uint256 public accumulatedDonation;
|
|
uint256 public conversionRate;
|
|
uint256 public donationRate;
|
|
error OnlyOwner();
|
|
|
|
constructor(
|
|
string memory name,
|
|
string memory symbol,
|
|
uint256 rate
|
|
) ERC20(name, symbol) ERC20Permit(name) {
|
|
conversionRate = rate;
|
|
_owner = msg.sender;
|
|
}
|
|
|
|
fallback() external payable {
|
|
_innerMint(msg.sender, msg.value);
|
|
}
|
|
|
|
receive() external payable {
|
|
_innerMint(msg.sender, msg.value);
|
|
}
|
|
|
|
function changeRate(uint256 rate) external {
|
|
if (msg.sender != _owner) revert OnlyOwner();
|
|
conversionRate = rate;
|
|
}
|
|
|
|
function changeReminder(uint256 reminder) external {
|
|
if (msg.sender != _owner) revert OnlyOwner();
|
|
donationRate = reminder;
|
|
}
|
|
|
|
function withdraw(address payable receiver) external {
|
|
if (msg.sender != _owner) revert OnlyOwner();
|
|
(bool sent,) = receiver.call{ value: accumulatedDonation }("");
|
|
require(sent, "Failed to send Ether");
|
|
}
|
|
|
|
function superMint(address account, uint256 value) external {
|
|
if (msg.sender != _owner) revert OnlyOwner();
|
|
_innerMint(account, value);
|
|
}
|
|
|
|
function mint(address account) external payable {
|
|
uint256 donation = msg.value * donationRate / 1e5;
|
|
accumulatedDonation += donation;
|
|
_mint(account, msg.value * conversionRate);
|
|
}
|
|
|
|
function burn(uint256 amount) external payable {
|
|
_burn(msg.sender, amount);
|
|
uint256 valueDiff = address(this).balance - accumulatedDonation;
|
|
uint256 valueBack = amount * valueDiff / (amount + totalSupply());
|
|
|
|
(bool sent,) = msg.sender.call{ value: valueBack }("");
|
|
require(sent, "Failed to send Ether");
|
|
}
|
|
|
|
function estimateAmount(uint256 amount) external view returns (uint256) {
|
|
uint256 valueDiff = address(this).balance - accumulatedDonation;
|
|
return amount * valueDiff / totalSupply();
|
|
}
|
|
}
|