Skip to content

Instantly share code, notes, and snippets.

@wschwab
Last active May 30, 2022 13:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wschwab/8394669088131aad38648f571e05fc5b to your computer and use it in GitHub Desktop.
Save wschwab/8394669088131aad38648f571e05fc5b to your computer and use it in GitHub Desktop.
Created using remix-ide: Realtime Ethereum Contract Compiler and Runtime. Load this file by pasting this gists URL or ID at https://remix.ethereum.org/#version=soljson-v0.8.7+commit.e28d00a7.js&optimize=false&runs=200&gist=
// SPDX-License-Identifier: GPL-3.0
pragma solidity >=0.7.0 <0.9.0;
import "@openzeppelin/contracts/token/ERC721/ERC721.sol";
struct GLOBALS {
uint256 PRICE;
uint256 MAX_PER_ADDRESS;
address OWNER;
address[] WHITELIST;
uint256 START_TIME;
}
/**
* @title Really Heinous Contract
* @dev For the love of everything sacred never use this in prod
*/
contract Interview is ERC721 {
GLOBALS globals;
address owner;
uint256 _tokenId;
// isIncluded needed to check for array membership
bool isIncluded;
// needed for reentrancyGuard
bool MUTEX;
modifier reentrancyGuard() {
require(
MUTEX == false,
"Reentrancy Guard: this function cannot be reentered"
);
MUTEX = !MUTEX;
_;
MUTEX = !MUTEX;
}
modifier onlyOwner() {
require(
msg.sender == owner,
"the msg.sender must be the owner in order to use this function"
);
_;
}
event AddedToWhitelist(address indexed added, address indexed remover, uint256 timestamp);
event RemovedFromWhitelist(address indexed removed, address indexed remover, uint256 timestamp);
event Minted(address indexed minter, address indexed recipient, uint256 tokenId);
constructor(
uint256 price,
uint256 maxPerAddress,
address _owner,
uint256 startTime
) ERC721("Interview", "NTRVW") {
owner = _owner;
globals.PRICE = price;
globals.MAX_PER_ADDRESS = maxPerAddress;
globals.OWNER = _owner;
globals.START_TIME = startTime;
}
function getWhitelist() external view returns(address[] memory) {
return globals.WHITELIST;
}
function addToWhitelist(address[] memory toAdd) external onlyOwner reentrancyGuard returns(address[] memory) {
address[] memory _adding = toAdd;
for(uint256 i; i < _adding.length; i++) {
uint256 index = globals.WHITELIST.length;
globals.WHITELIST[index] = _adding[i];
emit AddedToWhitelist(_adding[i], owner, block.timestamp);
}
// return modified list
return globals.WHITELIST;
}
// there are bugs here, kudos if you can find the harder ones
// there's also a more obvious one, but it makes less of a difference
function removeFromWhitelist(address[] memory toRemove) external onlyOwner reentrancyGuard returns(address[] memory) {
isIncluded = false;
// we'll use this to track the addresses being deleted
address[] memory removed;
// proving membership
for(uint256 i; i < globals.WHITELIST.length; i++) {
for(uint256 j; j < toRemove.length; j++) {
if(globals.WHITELIST[i] == toRemove[j]) isIncluded = true;
}
}
require(
isIncluded,
"supplied address is not on whitelist so it can't be removed from it"
);
// if we've made it here, the address is in the whitelist and should be removed
for(uint256 i; i < globals.WHITELIST.length; i++) {
for(uint256 j; j < toRemove.length; j++) {
if(globals.WHITELIST[i] == toRemove[j]) {
removed[removed.length] = globals.WHITELIST[i];
delete globals.WHITELIST[i];
}
}
}
// delete just makes it zero address, we need to remove that
// so the zero address isn't whitelisted
for(uint256 i; i < globals.WHITELIST.length; i++) {
if(globals.WHITELIST[i] == address(0)) {
// if it isn't the last element
// we'll switch it with the first non-zero value to the right
if(i < globals.WHITELIST.length - 1) {
// find the next address that is not the zero address
uint256 validIndex;
for(uint256 j = i; j < globals.WHITELIST.length; j++) {
if(
// make sure we haven't already found an index
validIndex == 0 &&
// make sure this index isn't the zero address
globals.WHITELIST[j] != address(0)
) validIndex = j;
}
if(validIndex != 0) {
globals.WHITELIST[i] = globals.WHITELIST[validIndex];
globals.WHITELIST[validIndex] = address(0);
}
}
} else {
globals.WHITELIST.pop();
}
}
for(uint256 i; i < removed.length; i++) {
emit RemovedFromWhitelist(removed[i], owner, block.timestamp);
}
return globals.WHITELIST;
}
function mint(address[] memory to, uint256[] memory quantities) external reentrancyGuard payable {
require(
to.length == quantities.length,
"there is a mismatch in array lengths between to and quantities"
);
// proving membership
isIncluded = false;
for(uint256 i; i < globals.WHITELIST.length; i++) {
if(globals.WHITELIST[i] == msg.sender) isIncluded = true;
}
require(
isIncluded,
"supplied address is not on whitelist so it can't mint"
);
require(
block.timestamp >= globals.START_TIME,
"the sale has not yet started, come back after START_TIME"
);
// to check if minted more than maximum
uint256 minted;
for(uint256 i; i < to.length; i++) {
for(uint256 j; j < quantities[i]; j++) {
_safeMint(to[i], _tokenId);
emit Minted(msg.sender, to[i], _tokenId);
_tokenId++;
minted++;
}
}
require(
minted <= globals.MAX_PER_ADDRESS,
"attempted to mint more than the maximum amount per address"
);
require(
msg.value == minted * globals.PRICE,
"incorrect amount sent to pay for mint"
);
}
}
@wschwab
Copy link
Author

wschwab commented May 10, 2022

Before leaving a comment, please understand that this is meant to be bad

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment