Skip to content

Commit

Permalink
Move registry logic to separate contracts, restructure files to match…
Browse files Browse the repository at this point in the history
… OZ, added tests for air drop. Removed extra test contracts, setup foundry.toml to support upgradeable contracts.
  • Loading branch information
BillSchumacher committed Mar 26, 2024
1 parent 8c3440c commit 14f92d3
Show file tree
Hide file tree
Showing 33 changed files with 1,807 additions and 353 deletions.
61 changes: 0 additions & 61 deletions packages/foundry/contracts/HelloWorld.sol

This file was deleted.

4 changes: 0 additions & 4 deletions packages/foundry/contracts/extensions/ERC20AirDropErrors.sol

This file was deleted.

41 changes: 41 additions & 0 deletions packages/foundry/contracts/token/BurnToken.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.25;

import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import {ERC20MintRegistry} from "./ERC20/extensions/ERC20MintRegistry.sol";
import {ERC20BurnRegistry} from "./ERC20/extensions/ERC20BurnRegistry.sol";
import {ERC20AirDropMint} from "./ERC20/extensions/ERC20AirDropMint.sol";
import {ERC20AirDropTransfer} from "./ERC20/extensions/ERC20AirDropTransfer.sol";

/// @title A token for testing.
/// @author BillSchumacher
/// @custom:security-contact [email protected]
contract BurnToken is
ERC20,
ERC20MintRegistry,
ERC20BurnRegistry,
ERC20AirDropMint,
ERC20AirDropTransfer
{
constructor(
string memory name,
string memory symbol
) payable ERC20(name, symbol) {}

function balanceOf(address account)
public
view
override(ERC20, ERC20BurnRegistry)
returns (uint256)
{
return ERC20BurnRegistry.balanceOf(account);
}

function afterAirDropMint(
address account,
uint256 value
) internal override {
updateMintRegistry(account, value);
super.afterAirDropMint(account, value);
}
}
Original file line number Diff line number Diff line change
@@ -1,17 +1,18 @@
//SPDX-License-Identifier: MIT
pragma solidity >=0.8.0 <0.9.0;
// SPDX-License-Identifier: MIT
pragma solidity 0.8.25;

import "./extensions/ERC20MintRegistry.sol";
import "./extensions/ERC20BurnRegistry.sol";
import "./extensions/ERC20ProofOfBurn.sol";
import "../extensions/ERC20MintRegistry.sol";
import "../extensions/ERC20BurnRegistry.sol";
import "../extensions/ERC20ProofOfBurn.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Capped.sol";
import "./extensions/ERC20ProofOfBurner.sol";
import "./extensions/ERC20ProofOfMint.sol";
import "./extensions/ERC20ProofOfMinter.sol";
import "../extensions/ERC20ProofOfBurner.sol";
import "../extensions/ERC20ProofOfMint.sol";
import "../extensions/ERC20ProofOfMinter.sol";

/// @title Example implementation contract for extensions.
/// @author BillSchumacher
contract BurntMintyBurny is
/// @custom:security-contact [email protected]
contract ERC20BurntMintyBurny is
ERC20ProofOfBurn,
ERC20ProofOfBurner,
ERC20ProofOfMint,
Expand All @@ -37,7 +38,7 @@ contract BurntMintyBurny is

function mintRatio()
public
view
pure
override(
ERC20ProofOfBurn,
ERC20ProofOfBurner,
Expand All @@ -46,6 +47,11 @@ contract BurntMintyBurny is
)
returns (uint256)
{
// Just for coverage...
ERC20ProofOfBurn.mintRatio();
ERC20ProofOfBurner.mintRatio();
ERC20ProofOfMint.mintRatio();
ERC20ProofOfMinter.mintRatio();
return 5000;
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,18 @@
//SPDX-License-Identifier: MIT
pragma solidity >=0.8.0 <0.9.0;
// SPDX-License-Identifier: MIT
pragma solidity 0.8.25;

import "./extensions/ERC20MintRegistry.sol";
import "./extensions/ERC20BurnRegistry.sol";
import "../extensions/ERC20MintRegistry.sol";
import "../extensions/ERC20BurnRegistry.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Capped.sol";

/// @title Example implementation contract for extensions.
/// @author BillSchumacher
contract MintyBurny is ERC20MintRegistry, ERC20BurnRegistry, ERC20Capped {
/// @custom:security-contact [email protected]
contract ERC20MintyBurny is
ERC20MintRegistry,
ERC20BurnRegistry,
ERC20Capped
{
constructor() ERC20("MintyBurny", "MB") ERC20Capped(2 ** 254) {
mint(1000000 * 10 ** decimals());
burn(500000 * 10 ** decimals());
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.25;

error ERC20AirDropMismatch(uint256 addresses, uint256 values);
Original file line number Diff line number Diff line change
@@ -1,14 +1,23 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
pragma solidity 0.8.25;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "./ERC20AirDropErrors.sol";

/// @title Air drop support for ERC20 tokens, using minting.
/// @author BillSchumacher
/// @custom:security-contact [email protected]
abstract contract ERC20AirDropMint is ERC20 {
event AirDropMint(address indexed to, uint256 value);

function beforeAirDropMint() internal virtual {}
function afterAirDropMint() internal virtual {}
function beforeAirDropMint(
address account,
uint256 value
) internal virtual {}
function afterAirDropMint(
address account,
uint256 value
) internal virtual {}

/// @notice Airdrop tokens to the given addresses via minting.
/// @dev Airdrop tokens to the given addresses via minting.
Expand All @@ -19,13 +28,13 @@ abstract contract ERC20AirDropMint is ERC20 {
uint256 value
) public virtual {
uint256 len = addresses.length;
beforeAirDropMint();
for (uint256 i; i < len; i++) {
for (uint256 i; i < len; ++i) {
address to = addresses[i];
beforeAirDropMint(to, value);
_mint(to, value);
emit AirDropMint(to, value);
afterAirDropMint(to, value);
}
afterAirDropMint();
}

/// @notice Airdrop tokens to the given addresses via minting split evenly.
Expand All @@ -37,14 +46,14 @@ abstract contract ERC20AirDropMint is ERC20 {
uint256 value
) public virtual {
uint256 len = addresses.length;
beforeAirDropMint();
uint256 splitValue = value / len;
for (uint256 i; i < len; i++) {
for (uint256 i; i < len; ++i) {
address to = addresses[i];
beforeAirDropMint(to, splitValue);
_mint(to, splitValue);
emit AirDropMint(to, splitValue);
afterAirDropMint(to, splitValue);
}
afterAirDropMint();
}

/// @notice Airdrop tokens to the given addresses.
Expand All @@ -60,13 +69,14 @@ abstract contract ERC20AirDropMint is ERC20 {
if (len != valLen) {
revert ERC20AirDropMismatch(len, valLen);
}
beforeAirDropMint();
for (uint256 i; i < len; i++) {
for (uint256 i; i < len; ++i) {
address to = addresses[i];
uint256 value = values[i];

beforeAirDropMint(to, value);
_mint(to, value);
afterAirDropMint(to, value);
emit AirDropMint(to, value);
}
afterAirDropMint();
}
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
pragma solidity 0.8.25;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "./ERC20AirDropErrors.sol";

/// @title Air drop support for ERC20 tokens, using transfers.
/// @author BillSchumacher
/// @custom:security-contact [email protected]
abstract contract ERC20AirDropTransfer is ERC20 {
event AirDropTransfer(
address indexed from, address indexed to, uint256 value
Expand All @@ -23,7 +26,7 @@ abstract contract ERC20AirDropTransfer is ERC20 {
beforeAirDropTransfer();
uint256 len = addresses.length;
address sender = msg.sender;
for (uint256 i; i < len; i++) {
for (uint256 i; i < len; ++i) {
address addr = addresses[i];
_transfer(sender, addr, value);
emit AirDropTransfer(sender, addr, value);
Expand All @@ -43,7 +46,7 @@ abstract contract ERC20AirDropTransfer is ERC20 {
uint256 len = addresses.length;
address sender = msg.sender;
uint256 splitValue = value / len;
for (uint256 i; i < len; i++) {
for (uint256 i; i < len; ++i) {
address addr = addresses[i];
_transfer(sender, addr, splitValue);
emit AirDropTransfer(sender, addr, splitValue);
Expand All @@ -66,7 +69,7 @@ abstract contract ERC20AirDropTransfer is ERC20 {
}
address sender = msg.sender;
beforeAirDropTransfer();
for (uint256 i; i < len; i++) {
for (uint256 i; i < len; ++i) {
address addr = addresses[i];
uint256 value = values[i];
_transfer(sender, addr, value);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
// SPDX-License-Identifier: MIT
pragma solidity 0.8.25;

import "@openzeppelin/contracts/token/ERC20/ERC20.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol";
import {TokenBurnRegistry} from "../../common/TokenBurnRegistry.sol";

/// @title A smart contract that allows burning tokens and tracking the burned tokens.
/// @author BillSchumacher
/// @custom:security-contact [email protected]
abstract contract ERC20BurnRegistry is
ERC20,
ERC20Burnable,
TokenBurnRegistry
{
uint256 private _zeroAddress;

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

/// @dev Update the burn registry.
/// @param account (address) - the address of the account.
/// @param value (uint256) - the amount of tokens to burn.
function updateBurnRegistry(
address account,
uint256 value
) internal virtual override {
_zeroAddress += value;
super.updateBurnRegistry(account, value);
}

/// @notice Destroys a `value` amount of tokens from your balance.
/// @dev Destroys a `value` amount of tokens from the caller.
/// See {ERC20-_burn}.
/// @param value (uint256) - the amount of tokens to burn.
function burn(uint256 value) public virtual override {
address sender = _msgSender();
_burn(sender, value);
updateBurnRegistry(sender, value);
}

/// @notice Destroys a `value` amount of tokens from `account`, deducting from your allowance.
/// @dev Destroys a `value` amount of tokens from `account`, deducting from the caller's allowance.
/// See {ERC20-_burn} and {ERC20-allowance}.
/// @inheritdoc ERC20Burnable
/// @param account (address) - the address of the account.
/// @param value (uint256) - the amount of tokens to burn.
function burnFrom(address account, uint256 value) public virtual override {
_spendAllowance(account, _msgSender(), value);
_burn(account, value);
updateBurnRegistry(account, value);
}
}
Loading

0 comments on commit 14f92d3

Please sign in to comment.