Skip to content

Commit

Permalink
Update upgradeables, deployed MintyBurnyRegistry,HotDog, and ChillyDog.
Browse files Browse the repository at this point in the history
  • Loading branch information
BillSchumacher committed Apr 7, 2024
1 parent 5b88dfe commit 0ef85ee
Show file tree
Hide file tree
Showing 35 changed files with 2,469 additions and 151 deletions.
3 changes: 1 addition & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,5 @@
"lint-staged": "~13.2.2",
"next": "~14.0.4",
"vercel": "~32.4.1"
},
"packageManager": "[email protected]"
}
}
133 changes: 133 additions & 0 deletions packages/foundry/contracts/token/ChillyDog.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.25;

import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import {ERC20Burnable} from
"@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol";
import {IMultiTokenBurnRegistry} from "./common/IMultiTokenBurnRegistry.sol";
import {IMultiTokenMintRegistry} from "./common/IMultiTokenMintRegistry.sol";
import {IERC20CustomErrors} from "./ERC20/extensions/IERC20CustomErrors.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import "./ERC20/extensions/ERC20ProofOfMint.sol";

/// @title An ERC20 token supporting an external registry.
/// @author BillSchumacher
/// @custom:security-contact [email protected]
contract ChillyDog is ERC20, Ownable, ERC20ProofOfMint, ERC20Burnable {
address private _registry;
uint256 private _lastFee;
uint256 private _zeroAddress;
uint256 private _mintFee = 0.01 ether;
string private _description;

error InsufficientMintFee(uint256 mintFee, uint256 msgValue);

constructor(
address registry_,
address[] memory contractAddresses
)
ERC20("Chilly Dog", "BRRRR")
Ownable(msg.sender)
ERC20ProofOfMint(contractAddresses)
{
_registry = registry_;
}

/// @inheritdoc ERC20
function balanceOf(address account)
public
view
virtual
override
returns (uint256)
{
if (account == address(0)) return _zeroAddress;
return ERC20.balanceOf(account);
}

/// @notice Get the description of the token.
/// @dev Returns the description of the token.
/// @return (string) - the description of the token.
function description() public view returns (string memory) {
return _description;
}

/// @notice Set the description of the token.
/// @dev Set the description of the token.
/// @param desc (string) - the description of the token.
function setDesc(string calldata desc) public onlyOwner {
_description = desc;
}

/// @inheritdoc ERC20
function _update(
address from,
address to,
uint256 value
) internal virtual override(ERC20) {
ERC20._update(from, to, value);
if (to == address(0)) {
_zeroAddress += value;
this._updateBurnRegistry(from, value);
}
if (from == address(0)) {
this._updateMintRegistry(to, value);
}
}

/// @notice Get the current fee to mint tokens.
/// @dev Returns the current fee to mint tokens.
/// @return (uint256) - the current fee to mint tokens.
function getMintFee() public view returns (uint256) {
return _mintFee;
}

/// @inheritdoc ERC20ProofOfMint
function beforeMintMinted(
address sender,
address account
) internal override {
uint256 currentMintFee = _mintFee;
uint256 sentValue = msg.value;
if (sentValue < currentMintFee) {
revert InsufficientMintFee(currentMintFee, sentValue);
}
_mintFee = currentMintFee * 1001 / 1000;
sender;
account;
}

/// @dev Update the burn registry.
/// @param account (address) - the address of the account.
/// @param value (uint256) - the amount of tokens to burn.beforeMintMintedbeforeMintMinted
function _updateBurnRegistry(address account, uint256 value) external {
if (msg.sender != address(this)) {
revert OwnableUnauthorizedAccount(msg.sender);
}
//_registry.call(abi.encodeWithSignature("updateBurnRegistry(address,uint256)", account, value));
IMultiTokenBurnRegistry(_registry).updateBurnRegistry(account, value);
}

/// @dev Update the mint registry.
/// @param account (address) - the address of the account.
/// @param value (uint256) - the amount of tokens to mint.
function _updateMintRegistry(address account, uint256 value) external {
if (msg.sender != address(this)) {
revert OwnableUnauthorizedAccount(msg.sender);
}
//_registry.call(abi.encodeWithSignature("updateMintRegistry(address,uint256)", account, value));
IMultiTokenMintRegistry(_registry).updateMintRegistry(account, value);
}

/// @notice Allows the token to receive ether.
receive() external payable {}

/// @notice Allows the token to withdraw ether.
/// @dev Allows the token to withdraw ether.
function withdraw() public onlyOwner {
uint256 value = address(this).balance;
address to = owner();
(bool success,) = to.call{value: value}("");
if (!success) revert IERC20CustomErrors.ERC20TransferFailed(to, value);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.25;

import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import {Context} from "@openzeppelin/contracts/utils/Context.sol";

/// @title An extension to support an external burning registry.
/// @author BillSchumacher
/// @custom:security-contact [email protected]
abstract contract ERC20ExternalBurnRegistry is Context, ERC20 {
address internal _burnRegistry;

constructor(address memory burnRegistry_) {
_burnRegistry = burnRegistry_;
}

/// @notice Get the burn registry address.
/// @dev Returns the burn registry address.
/// @return (address) - the burn registry address.
function burnRegistry() public view returns (address) {
return _burnRegistry;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.25;

import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import {Context} from "@openzeppelin/contracts/utils/Context.sol";

/// @title An extension to support an external minting registry.
/// @author BillSchumacher
/// @custom:security-contact [email protected]
abstract contract ERC20ExternalMintRegistry is Context, ERC20 {
address internal _mintRegistry;

constructor(address memory mintRegistry_) {
_mintRegistry = mintRegistry_;
}

/// @notice Get the mint registry address.
/// @dev Returns the mint registry address.
/// @return (address) - the mint registry address.
function mintRegistry() public view returns (address) {
return _mintRegistry;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.25;

import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import {Context} from "@openzeppelin/contracts/utils/Context.sol";
import {NoTokensToMint} from "./ERC20MintyBurnyErrors.sol";
import {ERC20ExternalBurnRegistry} from "./ERC20ExternalBurnRegistry.sol";
import {IMultiTokenBurnRegistry} from "./common/IMultiTokenBurnRegistry.sol";

/// @title A smart contract that checks for burned tokens and mints new tokens based on the burned tokens.
/// @custom:requires burnerContracts to implement ERC20BurnRegistry
/// @author BillSchumacher
/// @custom:security-contact [email protected]
abstract contract ERC20ProofOfRegistryBurner is
Context,
ERC20,
ERC20ExternalBurnRegistry
{
mapping(address => uint256) private _lastBurnerBurned;
address[] internal _burnerContracts;

constructor(address[] memory burnerContracts) {
_burnerContracts = burnerContracts;
}

/// @notice Get the last amount of tokens that were burned.
/// @dev Returns the last amount of tokens that were burned.
/// @return (uint256) - the last amount of tokens that were burned.
function lastBurnerBurned() public view returns (uint256) {
return _lastBurnerBurned[_msgSender()];
}

/// @dev Set the last amount of tokens that were burned. Override to customize.
/// @param value (uint256) - the last amount of tokens that were burned.
function setLastBurnerBurned(uint256 value) internal virtual {
_lastBurnerBurned[_msgSender()] = value;
}

/// @notice Get the amount of tokens eligible to be minted.
/// @dev Returns the amount of tokens eligible to be minted.
/// @return balance (uint256) - the amount of tokens eligible to be minted.
function getCurrentBurnerBurned()
public
payable
virtual
returns (uint256 balance)
{
address[] memory eligibleBurnerContracts = _burnerContracts;
uint256 contractLength = eligibleBurnerContracts.length;
address sender = _msgSender();
IMultiTokenBurnRegistry registryContract =
IMultiTokenBurnRegistry(_burnRegistry);
for (uint256 i; i < contractLength;) {
balance +=
registryContract.burnedFrom(eligibleBurnerContracts[i], sender);
unchecked {
++i;
}
}
return balance;
}

/// @notice Get the ratio of tokens to mint.
/// @dev Returns the ratio of tokens to mint. Override to customize. Divided by 10000. 5000 = 0.5 (default)
/// @return (uint256) - the ratio of tokens to mint.
function mintRatio() public pure virtual returns (uint256) {
return 5000;
}

/// @notice Get the ratio of tokens to mint for ProofOfBurner.
/// @dev Returns the ratio of tokens to mint for ProofOfBurner. Override to customize. Divided by 10000. 5000 = 0.5 (default)
/// @return (uint256) - the ratio of tokens to mint.
function mintBurnerRatio() public view virtual returns (uint256) {
return mintRatio();
}

/// @dev Handle access control, accounting, and any conditions here before minting, revert if failed.
/// @param sender (address) - the address of the sender.
/// @param account (address) - the address of the account.
function beforeMintBurnerBurned(
address sender,
address account
) internal virtual {}

/// @dev Update the mint registry or perform other accounting. Override to customize.
/// @param account (address) - the address of the account.
/// @param value (uint256) - the amount of tokens minted.
function afterMintBurnerBurned(
address account,
uint256 value
) internal virtual {}

/// @dev Mints the burned tokens for the configured contracts and addresses.
/// @param account (address) - the address of the account.
/// @return (uint256) - the amount of tokens minted.
function _doMintBurnerBurned(address account)
internal
virtual
returns (uint256)
{
uint256 balance = getCurrentBurnerBurned();
uint256 tokensLastBurned = lastBurnerBurned();
if (balance <= tokensLastBurned) {
revert NoTokensToMint();
}
uint256 tokens =
(balance - tokensLastBurned) * mintBurnerRatio() / 10000;
setLastBurnerBurned(balance);
_mint(account, tokens);
return tokens;
}

/// @notice Mints the burned tokens for the configured contracts and burner.
/// @dev Mints the burned tokens for the configured contracts and burner.
/// @return tokens (uint256) - the amount of tokens minted.
function mintBurnerBurned()
public
payable
virtual
returns (uint256 tokens)
{
address sender = _msgSender();
beforeMintBurnerBurned(sender, sender);
tokens = _doMintBurnerBurned(sender);
afterMintBurnerBurned(sender, tokens);
return tokens;
}

/// @notice Mints the burned tokens for the configured contracts and burner.
/// @dev Mints the burned tokens for the configured contracts and burner.
/// @return tokens (uint256) - the amount of tokens minted.
function mintBurnerBurnedFor(address account)
public
payable
virtual
returns (uint256 tokens)
{
address sender = _msgSender();
beforeMintBurnerBurned(sender, account);
tokens = _doMintBurnerBurned(account);
afterMintBurnerBurned(account, tokens);
return tokens;
}
}
Loading

0 comments on commit 0ef85ee

Please sign in to comment.