// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)
pragma solidity ^0.8.20;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
function _contextSuffixLength() internal view virtual returns (uint256) {
return 0;
}
}
pragma solidity ^0.8.20;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
import "@openzeppelin/contracts/utils/Context.sol";
contract ERC20 is Context, IERC20, IERC20Metadata {
mapping(address => uint256) internal _balances;
mapping(address => mapping(address => uint256)) private _allowances;
uint256 internal _totalSupply;
uint8 internal constant _decimals = 9;
string private _name;
string private _symbol;
/**
* @dev Sets the values for {name} and {symbol}.
*
* All two of these values are immutable: they can only be set once during
* construction.
*/
constructor(string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
}
/**
* @dev Returns the name of the token.
*/
function name() public view virtual override returns (string memory) {
return _name;
}
/**
* @dev Returns the symbol of the token, usually a shorter version of the
* name.
*/
function symbol() public view virtual override returns (string memory) {
return _symbol;
}
/**
* @dev Returns the number of decimals used to get its user representation.
* For example, if `decimals` equals `2`, a balance of `505` tokens should
* be displayed to a user as `5.05` (`505 / 10 ** 2`).
*
* Tokens usually opt for a value of 18, imitating the relationship between
* Ether and Wei. This is the default value returned by this function, unless
* it's overridden.
*
* NOTE: This information is only used for _display_ purposes: it in
* no way affects any of the arithmetic of the contract, including
* {IERC20-balanceOf} and {IERC20-transfer}.
*/
function decimals() public pure returns (uint8) {
return _decimals;
}
/**
* @dev See {IERC20-totalSupply}.
*/
function totalSupply() public view virtual override returns (uint256) {
return _totalSupply;
}
/**
* @dev See {IERC20-balanceOf}.
*/
function balanceOf(
address account
) public view virtual override returns (uint256) {
return _balances[account];
}
/**
* @dev See {IERC20-transfer}.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - the caller must have a balance of at least `amount`.
*/
function transfer(
address to,
uint256 amount
) public virtual override returns (bool) {
address owner = _msgSender();
_transfer(owner, to, amount);
return true;
}
/**
* @dev See {IERC20-allowance}.
*/
function allowance(
address owner,
address spender
) public view virtual override returns (uint256) {
return _allowances[owner][spender];
}
/**
* @dev See {IERC20-approve}.
*
* NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on
* `transferFrom`. This is semantically equivalent to an infinite approval.
*
* Requirements:
*
* - `spender` cannot be the zero address.
*/
function approve(
address spender,
uint256 amount
) public virtual override returns (bool) {
address owner = _msgSender();
_approve(owner, spender, amount);
return true;
}
/**
* @dev See {IERC20-transferFrom}.
*
* Emits an {Approval} event indicating the updated allowance. This is not
* required by the EIP. See the note at the beginning of {ERC20}.
*
* NOTE: Does not update the allowance if the current allowance
* is the maximum `uint256`.
*
* Requirements:
*
* - `from` and `to` cannot be the zero address.
* - `from` must have a balance of at least `amount`.
* - the caller must have allowance for ``from``'s tokens of at least
* `amount`.
*/
function transferFrom(
address from,
address to,
uint256 amount
) public virtual override returns (bool) {
address spender = _msgSender();
_spendAllowance(from, spender, amount);
_transfer(from, to, amount);
return true;
}
/**
* @dev Atomically increases the allowance granted to `spender` by the caller.
*
* This is an alternative to {approve} that can be used as a mitigation for
* problems described in {IERC20-approve}.
*
* Emits an {Approval} event indicating the updated allowance.
*
* Requirements:
*
* - `spender` cannot be the zero address.
*/
function increaseAllowance(
address spender,
uint256 addedValue
) public virtual returns (bool) {
address owner = _msgSender();
_approve(owner, spender, allowance(owner, spender) + addedValue);
return true;
}
/**
* @dev Atomically decreases the allowance granted to `spender` by the caller.
*
* This is an alternative to {approve} that can be used as a mitigation for
* problems described in {IERC20-approve}.
*
* Emits an {Approval} event indicating the updated allowance.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `spender` must have allowance for the caller of at least
* `subtractedValue`.
*/
function decreaseAllowance(
address spender,
uint256 subtractedValue
) public virtual returns (bool) {
address owner = _msgSender();
uint256 currentAllowance = allowance(owner, spender);
require(
currentAllowance >= subtractedValue,
"ERC20: decreased allowance below zero"
);
unchecked {
_approve(owner, spender, currentAllowance - subtractedValue);
}
return true;
}
/**
* @dev Moves `amount` of tokens from `from` to `to`.
*
* This internal function is equivalent to {transfer}, and can be used to
* e.g. implement automatic token fees, slashing mechanisms, etc.
*
* Emits a {Transfer} event.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `from` must have a balance of at least `amount`.
*/
function _transfer(
address from,
address to,
uint256 amount
) internal virtual {
require(from != address(0), "ERC20: transfer from the zero address");
uint256 fromBalance = _balances[from];
require(
fromBalance >= amount,
"ERC20: transfer amount exceeds balance"
);
unchecked {
_balances[from] = fromBalance - amount;
// Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by
// decrementing then incrementing.
_balances[to] += amount;
}
emit Transfer(from, to, amount);
}
/** @dev Creates `amount` tokens and assigns them to `account`, increasing
* the total supply.
*
* Emits a {Transfer} event with `from` set to the zero address.
*
* Requirements:
*
* - `account` cannot be the zero address.
*/
function _mint(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: mint to the zero address");
_totalSupply += amount;
unchecked {
// Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.
_balances[account] += amount;
}
emit Transfer(address(0), account, amount);
}
/**
* @dev Erases `amount` tokens from `account`, reducing the
* total supply.
*
* Emits a {Transfer} event with `to` set to the zero address.
*
* Requirements:
*
* - `account` cannot be the zero address.
* - `account` must have at least `amount` tokens.
*/
function _burn(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: burn from the zero address");
uint256 accountBalance = _balances[account];
require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
unchecked {
_balances[account] = accountBalance - amount;
// Overflow not possible: amount <= accountBalance <= totalSupply.
_totalSupply -= amount;
}
emit Transfer(account, address(0), amount);
}
/**
* @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.
*
* This internal function is equivalent to `approve`, and can be used to
* e.g. set automatic allowances for certain subsystems, etc.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `owner` cannot be the zero address.
* - `spender` cannot be the zero address.
*/
function _approve(
address owner,
address spender,
uint256 amount
) internal virtual {
require(owner != address(0), "ERC20: approve from the zero address");
require(spender != address(0), "ERC20: approve to the zero address");
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
/**
* @dev Updates `owner` s allowance for `spender` based on spent `amount`.
*
* Does not update the allowance amount in case of infinite allowance.
* Revert if not enough allowance is available.
*
* Might emit an {Approval} event.
*/
function _spendAllowance(
address owner,
address spender,
uint256 amount
) internal virtual {
uint256 currentAllowance = allowance(owner, spender);
if (currentAllowance != type(uint256).max) {
require(
currentAllowance >= amount,
"ERC20: insufficient allowance"
);
unchecked {
_approve(owner, spender, currentAllowance - amount);
}
}
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import "./lib/Ownable.sol";
uint constant levelsCount = 6;
uint constant bcgroundsCount = 6;
uint8 constant pixelsCount = 32;
uint constant seedLevel2 = 11;
uint constant seedLevel3 = 22;
uint constant seedLevel4 = 33;
uint constant seedLevel5 = 44;
uint constant seedLevel6 = 56;
string constant description = "A collection of PEPis, an inscriptions ERC-20i collection. 6 different levels from egg mass to a fully grown Pepe. Which one is yours?$PEPI is a unique, fully on-chain art project built on the innovative new ERC-20i format with inscription metadata. Each portion of tokens resembles a seed that generates unique 32x32 dynamic images of Pepe stored on-chain, depending on the wallet's token balance.";
string constant web = "https://pepe-erc20i.vip/";
struct ItemData {
uint lvl; // starts 1
string background;
uint body; // number or 0
string bodyColor;
uint cloth; // number or 0
uint eyes; // number or 0
uint mouth; // number or 0
uint accessory; // number or 0
uint hat; // number or 0
uint ears; // number or 0
}
struct Rect {
uint8 x;
uint8 y;
uint8 width;
uint8 height;
}
struct RectColored {
uint8 x;
uint8 y;
uint8 width;
uint8 height;
uint24 color;
}
struct FileData {
uint lvl;
uint file;
Rect[] rects;
}
struct FileDataColored {
uint lvl;
uint file;
RectColored[] rects;
}
struct ColorsData {
string[] lvl0;
string[] lvl1;
string[] lvl2;
string[] lvl3;
string[] lvl4;
}
struct SeedData {
uint seed;
uint seed2;
uint extra;
}
struct Rand {
uint seed;
uint seed2;
uint extra;
uint nonce;
uint nonce2;
}
library RandLib {
function next(Rand memory rnd) internal pure returns (uint) {
return
uint(
keccak256(
abi.encodePacked(rnd.seed + rnd.nonce++ - 1, rnd.extra)
)
);
}
function next2(Rand memory rnd) internal pure returns (uint) {
return uint(keccak256(abi.encodePacked(rnd.seed2 + rnd.nonce2++ - 1)));
}
function random_value(uint nonce) internal view returns (uint) {
return
uint256(
keccak256(
abi.encodePacked(
block.timestamp,
msg.sender,
nonce,
block.number
)
)
);
}
function lvl(Rand memory rnd) internal pure returns (uint) {
if (rnd.seed < seedLevel2) return 0;
if (rnd.seed < seedLevel3) return 1;
if (rnd.seed < seedLevel4) return 2;
if (rnd.seed < seedLevel5) return 3;
if (rnd.seed < seedLevel6) return 4;
return 5;
}
function random(
string[] memory data,
Rand memory rnd
) internal pure returns (string memory) {
return data[randomIndex(data, rnd)];
}
function random2(
string[] memory data,
Rand memory rnd
) internal pure returns (string memory) {
return data[randomIndex2(data, rnd)];
}
function randomIndex(
string[] memory data,
Rand memory rnd
) internal pure returns (uint) {
return next(rnd) % data.length;
}
function randomIndex2(
string[] memory data,
Rand memory rnd
) internal pure returns (uint) {
return next2(rnd) % data.length;
}
}
library ColorConvert {
function toSvgColor(uint24 value) internal pure returns (string memory) {
return string(abi.encodePacked("#", toHex(value)));
}
function toHex(uint24 value) internal pure returns (bytes memory) {
bytes memory buffer = new bytes(6);
for (uint i = 0; i < 3; ++i) {
buffer[5 - i * 2] = hexChar(uint8(value) & 0x0f);
buffer[4 - i * 2] = hexChar((uint8(value) >> 4) & 0x0f);
value >>= 8;
}
return buffer;
}
function hexChar(uint8 value) internal pure returns (bytes1) {
if (value < 10) return bytes1(uint8(48 + (uint(value) % 10)));
return bytes1(uint8(65 + uint256((value - 10) % 6)));
}
}
library LayersLib {
function setLayers(
mapping(uint => mapping(uint => Rect[])) storage rects,
FileData[] calldata data,
uint8[levelsCount] storage counts
) internal {
for (uint i = 0; i < data.length; ++i) {
setFile(rects, data[i], counts);
}
}
function setLayers(
mapping(uint => mapping(uint => RectColored[])) storage rects,
FileDataColored[] calldata data,
uint8[levelsCount] storage counts
) internal {
for (uint i = 0; i < data.length; ++i) {
setFile(rects, data[i], counts);
}
}
function setFile(
mapping(uint => mapping(uint => Rect[])) storage rects,
FileData calldata input,
uint8[levelsCount] storage counts
) internal {
Rect[] storage storageFile = rects[input.lvl - 1][input.file - 1];
if (storageFile.length > 0) delete rects[input.lvl - 1][input.file - 1];
else ++counts[input.lvl - 1];
for (uint i = 0; i < input.rects.length; ++i) {
storageFile.push(input.rects[i]);
}
}
function setFile(
mapping(uint => mapping(uint => RectColored[])) storage rects,
FileDataColored calldata input,
uint8[levelsCount] storage counts
) internal {
RectColored[] storage storageFile = rects[input.lvl - 1][
input.file - 1
];
if (storageFile.length > 0) delete rects[input.lvl - 1][input.file - 1];
else ++counts[input.lvl - 1];
for (uint i = 0; i < input.rects.length; ++i) {
storageFile.push(input.rects[i]);
}
}
function getLvl(
mapping(uint => mapping(uint => Rect[])) storage rects,
uint lvl
) internal view returns (mapping(uint => Rect[]) storage) {
return rects[lvl];
}
function to_lvl_1(uint l) internal pure returns (uint) {
if (l > 0) --l;
return l;
}
}
library Converter {
function toString(uint value) internal pure returns (string memory) {
if (value == 0) {
return "0";
}
uint temp = value;
uint digits;
while (temp != 0) {
digits++;
temp /= 10;
}
bytes memory buffer = new bytes(digits);
while (value != 0) {
digits -= 1;
buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
value /= 10;
}
return string(buffer);
}
}
library RectLib {
using RectLib for Rect;
using RectLib for RectColored;
using RandLib for Rand;
using RandLib for string[];
using Converter for uint8;
using ColorConvert for uint24;
function toSvg(
Rect memory r,
string memory color
) internal pure returns (string memory) {
return
string(
abi.encodePacked(
"<rect x='",
r.x.toString(),
"' y='",
r.y.toString(),
"' width='",
r.width.toString(),
"' height='",
r.height.toString(),
"' fill='",
color,
"'/>"
)
);
}
function toSvg(RectColored memory r) internal pure returns (string memory) {
return
string(
abi.encodePacked(
"<rect x='",
r.x.toString(),
"' y='",
r.y.toString(),
"' width='",
r.width.toString(),
"' height='",
r.height.toString(),
"' fill='",
r.color.toSvgColor(),
"'/>"
)
);
}
function toSvg(
Rect[] storage rects,
string[] storage colors,
Rand memory rnd
) internal view returns (string memory) {
string memory res;
for (uint i = 0; i < rects.length; ++i) {
res = string(
abi.encodePacked(res, rects[i].toSvg(colors.random(rnd)))
);
}
return res;
}
function toSvg(
Rect[] storage rects,
string memory color
) internal view returns (string memory) {
string memory res;
for (uint i = 0; i < rects.length; ++i) {
res = string(abi.encodePacked(res, rects[i].toSvg(color)));
}
return res;
}
function toSvg(
RectColored[] storage rects
) internal view returns (string memory) {
string memory res;
for (uint i = 0; i < rects.length; ++i) {
res = string(abi.encodePacked(res, rects[i].toSvg()));
}
return res;
}
}
contract Generator is Ownable {
using LayersLib for mapping(uint => mapping(uint => Rect[]));
using LayersLib for mapping(uint => mapping(uint => RectColored[]));
using LayersLib for mapping(uint => string[]);
using LayersLib for uint;
using RectLib for Rect;
using RectLib for Rect[];
using RectLib for RectColored;
using RectLib for RectColored[];
using RandLib for Rand;
using RandLib for string[];
using Converter for uint;
using Converter for uint8;
using ColorConvert for uint24;
uint8[levelsCount] bodyLevelCounts;
uint8[levelsCount] clothLevelCounts;
uint8[levelsCount] eyesLevelCounts;
uint8[levelsCount] mouthLevelCounts;
uint8[levelsCount] accessoryLevelCounts;
uint8[levelsCount] hatLevelCounts;
uint8[levelsCount] earsLevelCounts;
mapping(uint => mapping(uint => Rect[])) bodies;
mapping(uint => mapping(uint => RectColored[])) cloths;
mapping(uint => mapping(uint => RectColored[])) eyes;
mapping(uint => mapping(uint => RectColored[])) mouths;
mapping(uint => mapping(uint => RectColored[])) accessories;
mapping(uint => mapping(uint => RectColored[])) hats;
mapping(uint => mapping(uint => RectColored[])) ears;
string[] private backgroundColors = [
"#c37100",
"#db4161",
"#9aeb00",
"#9241f3",
"#5182ff",
"#a2a2a2",
"#fff392"
];
string[] private skin_colors = [
// Greens
"#538234",
"#49a269",
"#67d487",
"#4b9540",
"#538234",
"#49a269",
"#67d487",
"#4b9540",
"#538234",
"#49a269",
"#67d487",
"#4b9540",
"#538234",
"#49a269",
"#67d487",
"#4b9540",
"#538234",
"#49a269",
"#67d487",
"#4b9540",
"#538234",
"#49a269",
"#67d487",
"#4b9540",
"#538234",
"#49a269",
"#67d487",
"#4b9540",
// Browns and Yellows
"#794100",
"#8a8a00",
"#b6a41d",
"#dcc724",
// Blues
"#4192c3",
"#61a2ff",
"#61d3e3",
"#a271ff",
// Reds, Oranges, and Pinks
"#d44f06",
"#cf458c",
"#d4a37c",
"#FFC0CB",
"#800080",
"#8F00FF"
];
constructor() {}
function setBodies(FileData[] calldata data) external onlyOwner {
bodies.setLayers(data, bodyLevelCounts);
}
function setCloths(FileDataColored[] calldata data) external onlyOwner {
cloths.setLayers(data, clothLevelCounts);
}
function setEyes(FileDataColored[] calldata data) external onlyOwner {
eyes.setLayers(data, eyesLevelCounts);
}
function setMouths(FileDataColored[] calldata data) external onlyOwner {
mouths.setLayers(data, mouthLevelCounts);
}
function setAccessories(
FileDataColored[] calldata data
) external onlyOwner {
accessories.setLayers(data, accessoryLevelCounts);
}
function setHats(FileDataColored[] calldata data) external onlyOwner {
hats.setLayers(data, hatLevelCounts);
}
function setEars(FileDataColored[] calldata data) external onlyOwner {
ears.setLayers(data, earsLevelCounts);
}
// DATA
function getItemData(
SeedData calldata seed_data
) external view returns (ItemData memory) {
Rand memory rnd = Rand(
seed_data.seed,
seed_data.seed2,
seed_data.extra,
0,
0
);
ItemData memory data;
data.lvl = rnd.lvl() + 1;
setBcGround(data, rnd);
setBody(data, rnd);
setCloth(data, rnd);
setEyes(data, rnd);
setMouth(data, rnd);
setAccessory(data, rnd);
setHat(data, rnd);
setEars(data, rnd);
// limits
if (data.lvl == 1) {
if (data.mouth == 9) {
if (data.accessory >= 7 && data.accessory <= 9)
data.accessory = 0;
}
if (data.eyes == 5) {
if ((data.accessory >= 10 && data.accessory <= 13))
data.accessory = 0;
}
}
if (data.lvl == 2) {
if (data.hat >= 25 && data.hat <= 28) data.ears = 0;
}
if (data.lvl == 3) {
if (data.mouth == 9) {
if (data.accessory == 1 || data.accessory == 2)
data.accessory = 0;
}
if (data.eyes == 5) {
if (
data.accessory == 3 ||
data.accessory == 6 ||
(data.accessory >= 15 && data.accessory <= 20)
) data.accessory = 0;
}
if (data.hat >= 44 && data.hat <= 47) data.ears = 0;
}
if (data.lvl == 4) {
if (data.eyes == 5) {
if (
data.accessory == 1 ||
data.accessory == 5 ||
(data.accessory >= 8 && data.accessory <= 13) ||
(data.accessory >= 14 && data.accessory <= 19) ||
(data.accessory >= 20 && data.accessory <= 25)
) data.accessory = 0;
}
if (data.accessory == 5) {
if (
data.eyes == 5 ||
data.accessory == 9 ||
data.accessory == 10
) data.eyes = 0;
}
if (data.hat >= 54 && data.hat <= 57) data.ears = 0;
}
if (data.lvl == 5) {
if (data.mouth == 9) {
if (
data.accessory == 44 ||
(data.accessory >= 20 && data.accessory <= 25)
) data.accessory = 0;
}
if (data.eyes == 5) {
if (
(data.accessory >= 8 && data.accessory <= 13) ||
(data.accessory >= 14 && data.accessory <= 19) ||
(data.accessory >= 26 && data.accessory <= 31) ||
(data.accessory >= 32 && data.accessory <= 37)
) data.accessory = 0;
}
if (data.hat == 49) {
if (
data.accessory == 2 ||
data.accessory == 5 ||
data.accessory == 6 ||
data.accessory == 44 ||
(data.accessory >= 20 && data.accessory <= 25) ||
(data.accessory >= 38 && data.accessory <= 43)
) data.accessory = 0;
}
if (data.hat >= 70 && data.hat <= 73) data.ears = 0;
}
if (data.lvl == 6) {
if (data.mouth == 6) {
if (
(data.accessory >= 63 && data.accessory <= 65) ||
(data.accessory >= 69 && data.accessory <= 71)
) data.accessory = 0;
}
if (data.mouth == 9) {
if (
data.accessory == 3 ||
data.accessory == 48 ||
data.accessory == 55 ||
(data.accessory >= 30 && data.accessory <= 35) ||
(data.accessory >= 36 && data.accessory <= 41) ||
(data.accessory >= 49 && data.accessory <= 54) ||
(data.accessory >= 57 && data.accessory <= 59) ||
(data.accessory >= 63 && data.accessory <= 65) ||
(data.accessory >= 69 && data.accessory <= 71) ||
(data.accessory >= 75 && data.accessory <= 77)
) data.accessory = 0;
}
if (data.mouth == 10) {
if (
(data.accessory >= 69 && data.accessory <= 71) ||
(data.accessory >= 75 && data.accessory <= 77)
) data.accessory = 0;
}
if (data.eyes == 5) {
if (
data.accessory == 17 ||
(data.accessory >= 5 && data.accessory <= 10) ||
(data.accessory >= 11 && data.accessory <= 16) ||
(data.accessory >= 18 && data.accessory <= 23) ||
(data.accessory >= 42 && data.accessory <= 47) ||
(data.accessory >= 72 && data.accessory <= 74) ||
(data.accessory >= 69 && data.accessory <= 71) ||
(data.accessory >= 63 && data.accessory <= 65)
) data.accessory = 0;
}
if (data.hat == 50) {
if (
data.accessory == 2 ||
data.accessory == 17 ||
data.accessory == 48 ||
data.accessory == 55 ||
(data.accessory >= 24 && data.accessory <= 29) ||
(data.accessory >= 30 && data.accessory <= 35) ||
(data.accessory >= 36 && data.accessory <= 41)
) data.accessory = 0;
}
if (data.hat >= 72 && data.hat <= 72) data.ears = 0;
}
if (data.eyes == 12) {
if (data.lvl == 2) {
if (data.accessory >= 10 && data.accessory <= 13)
data.accessory = 0;
}
if (data.lvl == 3) {
if (
data.accessory >= 6 ||
(data.accessory >= 15 && data.accessory <= 20)
) data.accessory = 0;
}
if (data.lvl == 4) {
if (
data.accessory >= 5 ||
(data.accessory >= 8 && data.accessory <= 19)
) data.accessory = 0;
}
if (data.lvl == 5) {
if (
(data.accessory >= 26 && data.accessory <= 31) ||
(data.accessory >= 14 && data.accessory <= 19)
) data.accessory = 0;
}
if (data.lvl == 6) {
if (
(data.accessory >= 11 && data.accessory <= 23) ||
(data.accessory >= 42 && data.accessory <= 47)
) data.accessory = 0;
}
}
return data;
}
function setBcGround(ItemData memory data, Rand memory rnd) private view {
data.background = backgroundColors.random2(rnd);
}
function setBody(ItemData memory data, Rand memory rnd) private view {
uint count = bodyLevelCounts[data.lvl - 1];
if (count == 0) return;
data.body = 1 + (rnd.next() % count);
data.bodyColor = skin_colors.random2(rnd);
}
function setCloth(ItemData memory data, Rand memory rnd) private view {
uint count = clothLevelCounts[data.lvl - 1];
if (count == 0) return;
if (!(rnd.next() % 100 < 60)) return;
data.cloth = 1 + (rnd.next() % count);
}
function setEyes(ItemData memory data, Rand memory rnd) private view {
uint count = eyesLevelCounts[data.lvl - 1];
if (count == 0) return;
data.eyes = 1 + (rnd.next() % count);
}
function setMouth(ItemData memory data, Rand memory rnd) private view {
uint count = mouthLevelCounts[data.lvl - 1];
if (count == 0) return;
data.mouth = 1 + (rnd.next() % count);
}
function setAccessory(ItemData memory data, Rand memory rnd) private view {
uint count = accessoryLevelCounts[data.lvl - 1];
if (count == 0) return;
if (!(rnd.next() % 100 < 37)) return;
data.accessory = 1 + (rnd.next() % count);
}
function setHat(ItemData memory data, Rand memory rnd) private view {
uint count = hatLevelCounts[data.lvl - 1];
if (count == 0) return;
if (!(rnd.next() % 100 < 37)) return;
data.hat = 1 + (rnd.next() % count);
}
function setEars(ItemData memory data, Rand memory rnd) private view {
uint count = earsLevelCounts[data.lvl - 1];
if (count == 0) return;
if (!(rnd.next() % 100 < 3)) return;
data.ears = 1 + (rnd.next() % count);
}
// META
function getMeta(
SeedData calldata seed_data
) external view returns (string memory) {
ItemData memory data = this.getItemData(seed_data);
bytes memory lvl = abi.encodePacked('"level":', data.lvl.toString());
bytes memory background = abi.encodePacked(
',"background":"',
data.background,
'"'
);
bytes memory body = abi.encodePacked(
',"bodyColor":"',
data.bodyColor,
'"'
);
bytes memory cloth = abi.encodePacked(
',"clothes":',
data.cloth.toString()
);
bytes memory eyes = abi.encodePacked(',"eyes":', data.eyes.toString());
bytes memory mouth = abi.encodePacked(
',"mouth":',
data.mouth.toString()
);
bytes memory accessory = abi.encodePacked(
',"accessory":',
data.accessory.toString()
);
bytes memory hat = abi.encodePacked(
',"Head Item":',
data.hat.toString()
);
bytes memory ears = abi.encodePacked(',"ears":', data.ears.toString());
bytes memory web_text = abi.encodePacked(',"web":"', web, '"');
bytes memory description_text = abi.encodePacked(
',"description":"',
description,
'"'
);
return
string(
abi.encodePacked(
"{",
abi.encodePacked(
lvl,
background,
body,
cloth,
eyes,
mouth,
accessory,
hat,
ears
),
web_text,
description_text,
"}"
)
);
}
// SVG
function getSvg(
SeedData calldata seed_data
) external view returns (string memory) {
return toSvg(this.getItemData(seed_data));
}
function toSvg(ItemData memory data) private view returns (string memory) {
require(data.lvl > 0, "lvl is zero");
bytes memory svgStart = abi.encodePacked(
"<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0",
" ",
pixelsCount.toString(),
" ",
pixelsCount.toString(),
"'>"
);
return
string(
abi.encodePacked(
svgStart,
backgroundSvg(data),
bodySvg(data),
clothSvg(data),
earsSvg(data),
mouthSvg(data),
eyesSvg(data),
accessorySvg(data),
hatSvg(data),
"</svg>"
)
);
}
function backgroundSvg(
ItemData memory data
) private pure returns (string memory) {
Rect memory r = Rect(0, 0, pixelsCount, pixelsCount);
return r.toSvg(data.background);
}
function bodySvg(
ItemData memory data
) private view returns (string memory) {
if (data.body == 0) return "";
return bodies[data.lvl - 1][data.body - 1].toSvg(data.bodyColor);
}
function clothSvg(
ItemData memory data
) private view returns (string memory) {
if (data.cloth == 0) return "";
return cloths[data.lvl - 1][data.cloth - 1].toSvg();
}
function eyesSvg(
ItemData memory data
) private view returns (string memory) {
if (data.eyes == 0) return "";
return eyes[data.lvl - 1][data.eyes - 1].toSvg();
}
function mouthSvg(
ItemData memory data
) private view returns (string memory) {
if (data.mouth == 0) return "";
return mouths[data.lvl - 1][data.mouth - 1].toSvg();
}
function accessorySvg(
ItemData memory data
) private view returns (string memory) {
if (data.accessory == 0) return "";
return accessories[data.lvl - 1][data.accessory - 1].toSvg();
}
function hatSvg(ItemData memory data) private view returns (string memory) {
if (data.hat == 0) return "";
return hats[data.lvl - 1][data.hat - 1].toSvg();
}
function earsSvg(
ItemData memory data
) private view returns (string memory) {
if (data.ears == 0) return "";
return ears[data.lvl - 1][data.ears - 1].toSvg();
}
}
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.20;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the value of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the value of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves a `value` amount of tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 value) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets a `value` amount of tokens as the allowance of `spender` over the
* caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 value) external returns (bool);
/**
* @dev Moves a `value` amount of tokens from `from` to `to` using the
* allowance mechanism. `value` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(address from, address to, uint256 value) external returns (bool);
}
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (token/ERC20/extensions/IERC20Metadata.sol)
pragma solidity ^0.8.20;
import {IERC20} from "../IERC20.sol";
/**
* @dev Interface for the optional metadata functions from the ERC20 standard.
*/
interface IERC20Metadata is IERC20 {
/**
* @dev Returns the name of the token.
*/
function name() external view returns (string memory);
/**
* @dev Returns the symbol of the token.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the decimals places of the token.
*/
function decimals() external view returns (uint8);
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
contract Ownable {
address _owner;
event RenounceOwnership();
constructor() {
_owner = msg.sender;
}
modifier onlyOwner() {
require(_owner == msg.sender, "only owner");
_;
}
function owner() external view virtual returns (address) {
return _owner;
}
function ownerRenounce() public onlyOwner {
_owner = address(0);
emit RenounceOwnership();
}
function transferOwnership(address newOwner) external onlyOwner {
_owner = newOwner;
}
}
//https://twitter.com/Pepi_ERC20i
//https://t.me/pepe_ERC20i
//https://pepe-erc20i.vip/
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.21;
import "./Erc20.sol";
import "./PoolCreatableErc20i.sol";
import "../Generator.sol";
library ExtraSeedLibrary {
function extra(
address account,
uint extraSeed
) internal pure returns (uint256) {
return uint(keccak256(abi.encodePacked(account, extraSeed)));
}
}
abstract contract Mushrooms is PoolCreatableErc20i {
using ExtraSeedLibrary for address;
mapping(address owner => uint) _counts;
mapping(address owner => mapping(uint index => SeedData seed_data)) _ownedTokens;
mapping(address owner => mapping(uint tokenId => uint)) _ownedTokensIndex;
mapping(address owner => mapping(uint => bool)) _owns;
mapping(address owner => SeedData seed_data) _spores;
mapping(uint index => address user) _holderList;
mapping(address user => uint index) _holderListIndexes;
uint _mushroomsTotalCount;
uint _holdersCount;
uint _sporesTotalCount;
uint _random_nonce;
event OnMushroomTransfer(
address indexed from,
address indexed to,
SeedData seed_data
);
event OnSporesGrow(address indexed holder, SeedData seed_data);
event OnSporesShrink(address indexed holder, SeedData seed_data);
constructor()
PoolCreatableErc20i("PEPi", "PEPI", msg.sender)
{}
modifier holder_calculate(address acc1, address acc2) {
bool before1 = _isHolder(acc1);
bool before2 = _isHolder(acc2);
_;
bool after1 = _isHolder(acc1);
bool after2 = _isHolder(acc2);
if (!before1 && after1) _addHolder(acc1);
if (before1 && !after1) _removeHolder(acc1);
if (!before2 && after2) _addHolder(acc2);
if (before2 && !after2) _removeHolder(acc2);
}
function _isHolder(address account) private view returns (bool) {
if (
account == address(this) ||
account == _pool ||
account == address(0)
) return false;
return (_spores[account].seed + this.mushroomCount(account)) > 0;
}
function trySeedTransfer(
address from,
address to,
uint amount
) internal holder_calculate(from, to) {
if (from == address(this)) return;
uint seed = amount / (10 ** decimals());
if (seed > 0 && from != _pool && to != _pool) {
// transfer growing mushroom
if (_spores[from].seed == seed && !_owns[to][seed]) {
SeedData memory data = _spores[from];
_removeSeedCount(from, seed);
_addTokenToOwnerEnumeration(to, data);
emit OnMushroomTransfer(from, to, data);
return;
}
// transfer collected mushroom
if (_owns[from][seed] && !_owns[to][seed]) {
SeedData memory data = _ownedTokens[from][
_ownedTokensIndex[from][seed]
];
_removeTokenFromOwnerEnumeration(from, seed);
_addTokenToOwnerEnumeration(to, data);
emit OnMushroomTransfer(from, to, data);
return;
}
}
// transfer spores
uint lastBalanceFromSeed = _balances[from] / (10 ** decimals());
uint newBalanceFromSeed = (_balances[from] - amount) /
(10 ** decimals());
_removeSeedCount(from, lastBalanceFromSeed - newBalanceFromSeed);
_addSeedCount(to, seed);
}
function _addHolder(address account) private {
_holderList[_holdersCount] = account;
_holderListIndexes[account] = _holdersCount;
++_holdersCount;
}
function _removeHolder(address account) private {
if (_holdersCount == 0) return;
uint removingIndex = _holderListIndexes[account];
if (removingIndex != _holdersCount - 1) {
address lastHolder = _holderList[_holdersCount - 1];
_holderList[removingIndex] = lastHolder;
_holderListIndexes[lastHolder] = removingIndex;
}
if (_holdersCount > 0) --_holdersCount;
delete _holderListIndexes[account];
delete _holderList[_holdersCount];
}
function getHolderByIndex(uint index) public view returns (address) {
return _holderList[index];
}
function getHoldersList(
uint startIndex,
uint count
) public view returns (address[] memory) {
address[] memory holders = new address[](count);
for (uint i = 0; i < count; ++i)
holders[i] = getHolderByIndex(startIndex + i);
return holders;
}
function _addSeedCount(address account, uint seed) private {
if (seed == 0) return;
if (account == _pool) return;
SeedData memory last = _spores[account];
if (_spores[account].seed == 0)
_spores[account].seed2 = RandLib.random_value(++_random_nonce);
_spores[account].seed += seed;
_spores[account].extra = account.extra(++_random_nonce);
if (last.seed == 0 && _spores[account].seed > 0) ++_sporesTotalCount;
emit OnSporesGrow(account, _spores[account]);
}
function _removeSeedCount(address account, uint seed) private {
if (seed == 0) return;
if (account == _pool) return;
SeedData memory lastSpores = _spores[account];
if (_spores[account].seed >= seed) {
_spores[account].seed -= seed;
_spores[account].extra = account.extra(++_random_nonce);
if (lastSpores.seed > 0 && _spores[account].seed == 0) {
if (_sporesTotalCount > 0) --_sporesTotalCount;
}
emit OnSporesShrink(account, _spores[account]);
return;
}
uint seedRemains = seed - _spores[account].seed;
_spores[account].seed = 0;
_spores[account].extra = account.extra(++_random_nonce);
// remove mushrooms
uint count = _counts[account];
uint removed;
for (uint i = 0; i < count && removed < seedRemains; ++i) {
removed += _removeFirstTokenFromOwner(account);
}
if (removed > seedRemains) {
_spores[account].seed += removed - seedRemains;
_spores[account].extra = account.extra(++_random_nonce);
}
if (lastSpores.seed > 0 && _spores[account].seed == 0) {
if (_sporesTotalCount > 0) --_sporesTotalCount;
}
if (lastSpores.seed == 0 && _spores[account].seed > 0)
++_sporesTotalCount;
emit OnSporesShrink(account, _spores[account]);
}
function _addTokenToOwnerEnumeration(
address to,
SeedData memory data
) private {
if (to == _pool) return;
++_counts[to];
++_mushroomsTotalCount;
uint length = _counts[to] - 1;
_ownedTokens[to][length] = data;
_ownedTokensIndex[to][data.seed] = length;
_owns[to][data.seed] = true;
}
function _removeTokenFromOwnerEnumeration(address from, uint seed) private {
if (from == _pool) return;
if (_counts[from] > 0) --_counts[from];
if (_mushroomsTotalCount > 0) --_mushroomsTotalCount;
_owns[from][seed] = false;
uint lastTokenIndex = _counts[from];
uint tokenIndex = _ownedTokensIndex[from][seed];
SeedData memory data = _ownedTokens[from][tokenIndex];
// When the token to delete is the last token, the swap operation is unnecessary
if (tokenIndex != lastTokenIndex) {
SeedData memory lastTokenId = _ownedTokens[from][lastTokenIndex];
_ownedTokens[from][tokenIndex] = lastTokenId; // Move the last token to the slot of the to-delete token
_ownedTokensIndex[from][lastTokenId.seed] = tokenIndex; // Update the moved token's index
}
delete _ownedTokensIndex[from][data.seed];
delete _ownedTokens[from][lastTokenIndex];
}
function _removeFirstTokenFromOwner(address owner) private returns (uint) {
uint count = _counts[owner];
if (count == 0) return 0;
uint seed = _ownedTokens[owner][0].seed;
_removeTokenFromOwnerEnumeration(owner, seed);
return seed;
}
function isOwnerOf(address owner, uint seed) external view returns (bool) {
return _owns[owner][seed];
}
function sporesDegree(
address owner
) external view returns (SeedData memory data) {
return _spores[owner];
}
function mushroomCount(address owner) external view returns (uint) {
return _counts[owner];
}
function mushroomOfOwnerByIndex(
address owner,
uint index
) external view returns (SeedData memory data) {
return _ownedTokens[owner][index];
}
function mushroomsTotalCount() external view returns (uint) {
return _mushroomsTotalCount;
}
function holdersCount() external view returns (uint) {
return _holdersCount;
}
function sporesTotalCount() external view returns (uint) {
return _sporesTotalCount;
}
function getHolderIndex(address account) external view returns (uint) {
return _holderListIndexes[account];
}
}
contract Pepi is Mushrooms, Generator {
uint constant _startTotalSupply = 13370 * (10 ** _decimals);
uint constant _startMaxBuyCount = (_startTotalSupply * 5) / 10000;
uint constant _addMaxBuyPercentPerSec = 5; // 100%=_addMaxBuyPrecesion add 0.005%/second
uint constant _addMaxBuyPrecesion = 100000;
constructor() {
_mint(msg.sender, _startTotalSupply);
}
modifier maxBuyLimit(uint256 amount) {
require(amount <= maxBuy(), "max buy limit");
_;
}
function maxBuy() public view returns (uint256) {
if (!isStarted()) return _startTotalSupply;
uint256 count = _startMaxBuyCount +
(_startTotalSupply *
(block.timestamp - _startTime) *
_addMaxBuyPercentPerSec) /
_addMaxBuyPrecesion;
if (count > _startTotalSupply) count = _startTotalSupply;
return count;
}
function _transfer(
address from,
address to,
uint256 amount
) internal override {
if (isStarted()) {
trySeedTransfer(from, to, amount);
} else {
require(from == _owner || to == _owner, "not started");
}
// allow burning
if (to == address(0)) {
_burn(from, amount);
return;
}
// system transfers
if (from == address(this)) {
super._transfer(from, to, amount);
return;
}
if (_feeLocked) {
super._transfer(from, to, amount);
return;
} else {
if (from == _pool) {
buy(to, amount);
return;
}
}
super._transfer(from, to, amount);
}
function buy(
address to,
uint256 amount
) private maxBuyLimit(amount) lockFee {
super._transfer(_pool, to, amount);
}
function burnCount() public view returns (uint256) {
return _startTotalSupply - totalSupply();
}
}
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.21;
import "./Erc20.sol";
abstract contract PoolCreatableErc20i is ERC20 {
address internal _pool;
uint256 internal _startTime;
bool internal _feeLocked;
address immutable _pairCreator;
constructor(
string memory name_,
string memory symbol_,
address pairCreator
) ERC20(name_, symbol_) {
_pairCreator = pairCreator;
}
modifier lockFee() {
_feeLocked = true;
_;
_feeLocked = false;
}
function launch(address poolAddress) external payable {
require(msg.sender == _pairCreator);
require(!isStarted());
_pool = poolAddress;
_startTime = block.timestamp;
}
function isStarted() internal view returns (bool) {
return _pool != address(0);
}
function pool() external view returns (address) {
return _pool;
}
}
{
"compilationTarget": {
"contracts/token/Pepi.sol": "Pepi"
},
"evmVersion": "paris",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"owner","type":"address"},{"indexed":true,"internalType":"address","name":"spender","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"components":[{"internalType":"uint256","name":"seed","type":"uint256"},{"internalType":"uint256","name":"seed2","type":"uint256"},{"internalType":"uint256","name":"extra","type":"uint256"}],"indexed":false,"internalType":"struct SeedData","name":"seed_data","type":"tuple"}],"name":"OnMushroomTransfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"holder","type":"address"},{"components":[{"internalType":"uint256","name":"seed","type":"uint256"},{"internalType":"uint256","name":"seed2","type":"uint256"},{"internalType":"uint256","name":"extra","type":"uint256"}],"indexed":false,"internalType":"struct SeedData","name":"seed_data","type":"tuple"}],"name":"OnSporesGrow","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"holder","type":"address"},{"components":[{"internalType":"uint256","name":"seed","type":"uint256"},{"internalType":"uint256","name":"seed2","type":"uint256"},{"internalType":"uint256","name":"extra","type":"uint256"}],"indexed":false,"internalType":"struct SeedData","name":"seed_data","type":"tuple"}],"name":"OnSporesShrink","type":"event"},{"anonymous":false,"inputs":[],"name":"RenounceOwnership","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"from","type":"address"},{"indexed":true,"internalType":"address","name":"to","type":"address"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"spender","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"burnCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"subtractedValue","type":"uint256"}],"name":"decreaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getHolderByIndex","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"getHolderIndex","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"startIndex","type":"uint256"},{"internalType":"uint256","name":"count","type":"uint256"}],"name":"getHoldersList","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"seed","type":"uint256"},{"internalType":"uint256","name":"seed2","type":"uint256"},{"internalType":"uint256","name":"extra","type":"uint256"}],"internalType":"struct SeedData","name":"seed_data","type":"tuple"}],"name":"getItemData","outputs":[{"components":[{"internalType":"uint256","name":"lvl","type":"uint256"},{"internalType":"string","name":"background","type":"string"},{"internalType":"uint256","name":"body","type":"uint256"},{"internalType":"string","name":"bodyColor","type":"string"},{"internalType":"uint256","name":"cloth","type":"uint256"},{"internalType":"uint256","name":"eyes","type":"uint256"},{"internalType":"uint256","name":"mouth","type":"uint256"},{"internalType":"uint256","name":"accessory","type":"uint256"},{"internalType":"uint256","name":"hat","type":"uint256"},{"internalType":"uint256","name":"ears","type":"uint256"}],"internalType":"struct ItemData","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"seed","type":"uint256"},{"internalType":"uint256","name":"seed2","type":"uint256"},{"internalType":"uint256","name":"extra","type":"uint256"}],"internalType":"struct SeedData","name":"seed_data","type":"tuple"}],"name":"getMeta","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"seed","type":"uint256"},{"internalType":"uint256","name":"seed2","type":"uint256"},{"internalType":"uint256","name":"extra","type":"uint256"}],"internalType":"struct SeedData","name":"seed_data","type":"tuple"}],"name":"getSvg","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"holdersCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"uint256","name":"addedValue","type":"uint256"}],"name":"increaseAllowance","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"seed","type":"uint256"}],"name":"isOwnerOf","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"poolAddress","type":"address"}],"name":"launch","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"maxBuy","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"mushroomCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"mushroomOfOwnerByIndex","outputs":[{"components":[{"internalType":"uint256","name":"seed","type":"uint256"},{"internalType":"uint256","name":"seed2","type":"uint256"},{"internalType":"uint256","name":"extra","type":"uint256"}],"internalType":"struct SeedData","name":"data","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mushroomsTotalCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ownerRenounce","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"pool","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"lvl","type":"uint256"},{"internalType":"uint256","name":"file","type":"uint256"},{"components":[{"internalType":"uint8","name":"x","type":"uint8"},{"internalType":"uint8","name":"y","type":"uint8"},{"internalType":"uint8","name":"width","type":"uint8"},{"internalType":"uint8","name":"height","type":"uint8"},{"internalType":"uint24","name":"color","type":"uint24"}],"internalType":"struct RectColored[]","name":"rects","type":"tuple[]"}],"internalType":"struct FileDataColored[]","name":"data","type":"tuple[]"}],"name":"setAccessories","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"lvl","type":"uint256"},{"internalType":"uint256","name":"file","type":"uint256"},{"components":[{"internalType":"uint8","name":"x","type":"uint8"},{"internalType":"uint8","name":"y","type":"uint8"},{"internalType":"uint8","name":"width","type":"uint8"},{"internalType":"uint8","name":"height","type":"uint8"}],"internalType":"struct Rect[]","name":"rects","type":"tuple[]"}],"internalType":"struct FileData[]","name":"data","type":"tuple[]"}],"name":"setBodies","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"lvl","type":"uint256"},{"internalType":"uint256","name":"file","type":"uint256"},{"components":[{"internalType":"uint8","name":"x","type":"uint8"},{"internalType":"uint8","name":"y","type":"uint8"},{"internalType":"uint8","name":"width","type":"uint8"},{"internalType":"uint8","name":"height","type":"uint8"},{"internalType":"uint24","name":"color","type":"uint24"}],"internalType":"struct RectColored[]","name":"rects","type":"tuple[]"}],"internalType":"struct FileDataColored[]","name":"data","type":"tuple[]"}],"name":"setCloths","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"lvl","type":"uint256"},{"internalType":"uint256","name":"file","type":"uint256"},{"components":[{"internalType":"uint8","name":"x","type":"uint8"},{"internalType":"uint8","name":"y","type":"uint8"},{"internalType":"uint8","name":"width","type":"uint8"},{"internalType":"uint8","name":"height","type":"uint8"},{"internalType":"uint24","name":"color","type":"uint24"}],"internalType":"struct RectColored[]","name":"rects","type":"tuple[]"}],"internalType":"struct FileDataColored[]","name":"data","type":"tuple[]"}],"name":"setEars","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"lvl","type":"uint256"},{"internalType":"uint256","name":"file","type":"uint256"},{"components":[{"internalType":"uint8","name":"x","type":"uint8"},{"internalType":"uint8","name":"y","type":"uint8"},{"internalType":"uint8","name":"width","type":"uint8"},{"internalType":"uint8","name":"height","type":"uint8"},{"internalType":"uint24","name":"color","type":"uint24"}],"internalType":"struct RectColored[]","name":"rects","type":"tuple[]"}],"internalType":"struct FileDataColored[]","name":"data","type":"tuple[]"}],"name":"setEyes","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"lvl","type":"uint256"},{"internalType":"uint256","name":"file","type":"uint256"},{"components":[{"internalType":"uint8","name":"x","type":"uint8"},{"internalType":"uint8","name":"y","type":"uint8"},{"internalType":"uint8","name":"width","type":"uint8"},{"internalType":"uint8","name":"height","type":"uint8"},{"internalType":"uint24","name":"color","type":"uint24"}],"internalType":"struct RectColored[]","name":"rects","type":"tuple[]"}],"internalType":"struct FileDataColored[]","name":"data","type":"tuple[]"}],"name":"setHats","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"lvl","type":"uint256"},{"internalType":"uint256","name":"file","type":"uint256"},{"components":[{"internalType":"uint8","name":"x","type":"uint8"},{"internalType":"uint8","name":"y","type":"uint8"},{"internalType":"uint8","name":"width","type":"uint8"},{"internalType":"uint8","name":"height","type":"uint8"},{"internalType":"uint24","name":"color","type":"uint24"}],"internalType":"struct RectColored[]","name":"rects","type":"tuple[]"}],"internalType":"struct FileDataColored[]","name":"data","type":"tuple[]"}],"name":"setMouths","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"sporesDegree","outputs":[{"components":[{"internalType":"uint256","name":"seed","type":"uint256"},{"internalType":"uint256","name":"seed2","type":"uint256"},{"internalType":"uint256","name":"extra","type":"uint256"}],"internalType":"struct SeedData","name":"data","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"sporesTotalCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transfer","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"transferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]