编译器
0.8.25+commit.b61c2a91
文件 1 的 16:Base64.sol
pragma solidity ^0.8.20;
library Base64 {
string internal constant _TABLE = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
string internal constant _TABLE_URL = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
function encode(bytes memory data) internal pure returns (string memory) {
return _encode(data, _TABLE, true);
}
function encodeURL(bytes memory data) internal pure returns (string memory) {
return _encode(data, _TABLE_URL, false);
}
function _encode(bytes memory data, string memory table, bool withPadding) private pure returns (string memory) {
if (data.length == 0) return "";
uint256 resultLength = withPadding ? 4 * ((data.length + 2) / 3) : (4 * data.length + 2) / 3;
string memory result = new string(resultLength);
assembly ("memory-safe") {
let tablePtr := add(table, 1)
let resultPtr := add(result, 0x20)
let dataPtr := data
let endPtr := add(data, mload(data))
let afterPtr := add(endPtr, 0x20)
let afterCache := mload(afterPtr)
mstore(afterPtr, 0x00)
for {
} lt(dataPtr, endPtr) {
} {
dataPtr := add(dataPtr, 3)
let input := mload(dataPtr)
mstore8(resultPtr, mload(add(tablePtr, and(shr(18, input), 0x3F))))
resultPtr := add(resultPtr, 1)
mstore8(resultPtr, mload(add(tablePtr, and(shr(12, input), 0x3F))))
resultPtr := add(resultPtr, 1)
mstore8(resultPtr, mload(add(tablePtr, and(shr(6, input), 0x3F))))
resultPtr := add(resultPtr, 1)
mstore8(resultPtr, mload(add(tablePtr, and(input, 0x3F))))
resultPtr := add(resultPtr, 1)
}
mstore(afterPtr, afterCache)
if withPadding {
switch mod(mload(data), 3)
case 1 {
mstore8(sub(resultPtr, 1), 0x3d)
mstore8(sub(resultPtr, 2), 0x3d)
}
case 2 {
mstore8(sub(resultPtr, 1), 0x3d)
}
}
}
return result;
}
}
文件 2 的 16:Canvas.sol
pragma solidity ^0.8.25;
import "../lib/StringConverter.sol";
import "./Rects.sol";
import "../lib/Ownable.sol";
uint constant CANVAS_SIZE = 32;
uint constant CHUNK_SIZE = 8;
uint constant MAX_CHUNKS_TO_UPDATE = 2;
struct Pixel {
uint x;
uint y;
string color;
}
library PixelLibrary {
function to_rect(
Pixel memory pixel
) internal pure returns (Rect memory svg) {
return Rect(pixel.x, pixel.y, 1, 1, pixel.color);
}
}
struct PixelData {
Pixel pixel;
address owner;
bool minted;
}
struct Chunk {
uint x;
uint y;
}
abstract contract Canvas is Ownable {
using RectLibrary for Rect;
using PixelLibrary for Pixel;
mapping(uint x => mapping(uint y => PixelData data)) data;
mapping(uint x => mapping(uint y => string chunk)) chunks;
uint32[] chunks_to_update;
modifier chunks_late_update() {
_;
if (chunks_to_update.length == 0) return;
for (
uint i = 0;
chunks_to_update.length > 0 && i < MAX_CHUNKS_TO_UPDATE;
++i
) {
(uint chunk_x, uint chunk_y) = id_to_chunk(
chunks_to_update[chunks_to_update.length - 1]
);
calculate_chunk(chunk_x, chunk_y);
chunks_to_update.pop();
}
if (chunks_to_update.length == 0) delete chunks_to_update;
}
function get_chunks_for_update()
public
view
returns (Chunk[] memory chunks)
{
chunks = new Chunk[](chunks_to_update.length);
if (chunks_to_update.length == 0) return chunks;
for (uint i = 0; i < chunks_to_update.length; ++i) {
(uint chunk_x, uint chunk_y) = id_to_chunk(chunks_to_update[i]);
chunks[i] = Chunk(chunk_x, chunk_y);
}
}
function size() public pure returns (uint x, uint y) {
return (CANVAS_SIZE, CANVAS_SIZE);
}
function get_pixel_data(
uint x,
uint y
) public view returns (PixelData memory) {
return data[x][y];
}
function get_svg() public view returns (string memory) {
return
string(
abi.encodePacked(
"<svg xmlns='http://www.w3.org/2000/svg' ",
"viewBox='0 0 ",
StringConverter.to_string(CANVAS_SIZE),
" ",
StringConverter.to_string(CANVAS_SIZE),
"' fill='none'>",
get_all_chunks(),
"</svg>"
)
);
}
function get_pixel_svg(
string memory color
) internal pure returns (bytes memory) {
return
abi.encodePacked(
"<svg xmlns='http://www.w3.org/2000/svg' ",
"viewBox='0 0 ",
StringConverter.to_string(CANVAS_SIZE),
" ",
StringConverter.to_string(CANVAS_SIZE),
"' fill='none'>",
Rect(0, 0, CANVAS_SIZE, CANVAS_SIZE, color).to_svg(),
"'>",
"</svg>"
);
}
function get_all_chunks() private view returns (string memory) {
bytes memory str;
uint x;
uint y;
for (y = 0; y < CANVAS_SIZE / CHUNK_SIZE; ++y) {
for (x = 0; x < CANVAS_SIZE / CHUNK_SIZE; ++x) {
str = abi.encodePacked(str, chunks[x][y]);
}
}
return string(str);
}
function get_svg_internal() private view returns (bytes memory) {
uint x;
uint y;
bytes memory str;
for (x = 0; x < CANVAS_SIZE; ++x) {
for (y = 0; y < CANVAS_SIZE; ++y) {
PixelData memory d = data[x][y];
Rect memory rect = d.minted
? d.pixel.to_rect()
: Rect(x, y, 1, 1, "aaaaaa");
str = abi.encodePacked(str, rect.to_svg());
}
}
return str;
}
function upload_shit(Pixel[] calldata pixels) external onlyOwner {
uint i;
for (i = 0; i < pixels.length; ++i) {
data[pixels[i].x][pixels[i].y].pixel = pixels[i];
(uint chunk_x, uint chunk_y) = get_chunk(pixels[i].x, pixels[i].y);
add_chunk_to_update(chunk_x, chunk_y);
}
calculate_all_chunks();
}
function get_chunk(
uint x,
uint y
) public pure returns (uint hunk_x, uint chunk_y) {
return (x / CHUNK_SIZE, y / CHUNK_SIZE);
}
function calculate_chunk(uint chunk_x, uint chunk_y) public {
chunks[chunk_x][chunk_y] = _calculate_chunk(chunk_x, chunk_y);
}
function calculate_chunks(Chunk[] calldata chunks) public {
for (uint i = 0; i < chunks.length; ++i) {
calculate_chunk(chunks[i].x, chunks[i].y);
remove_chunk_from_update(chunks[i].x, chunks[i].y);
}
}
function calculate_all_chunks() public {
if (chunks_to_update.length == 0) return;
for (uint i = 0; i < chunks_to_update.length; ++i) {
(uint chunk_x, uint chunk_y) = id_to_chunk(chunks_to_update[i]);
calculate_chunk(chunk_x, chunk_y);
}
delete chunks_to_update;
}
function _calculate_chunk(
uint chunk_x,
uint chunk_y
) private view returns (string memory) {
bytes memory str;
uint x;
uint y;
for (y = chunk_y * CHUNK_SIZE; y < (chunk_y + 1) * CHUNK_SIZE; ++y) {
for (
x = chunk_x * CHUNK_SIZE;
x < (chunk_x + 1) * CHUNK_SIZE;
++x
) {
PixelData memory d = data[x][y];
Rect memory rect = d.minted
? d.pixel.to_rect()
: Rect(x, y, 1, 1, "aaaaaa");
str = abi.encodePacked(str, rect.to_svg());
}
}
return string(str);
}
function _set_pixel_owner(uint x, uint y, address owner) internal {
data[x][y].owner = owner;
if (owner != address(0)) data[x][y].minted = true;
(uint chunk_x, uint chunk_y) = get_chunk(x, y);
add_chunk_to_update(chunk_x, chunk_y);
}
function _burn_pixel(uint x, uint y) internal {
delete data[x][y];
(uint chunk_x, uint chunk_y) = get_chunk(x, y);
add_chunk_to_update(chunk_x, chunk_y);
}
function pixel_to_id(
uint pixel_x,
uint pixel_y
) internal pure returns (uint32 pixel_id) {
return uint32(pixel_y * CANVAS_SIZE + pixel_x);
}
function id_to_chunk(
uint32 pixel_id
) internal pure returns (uint chunk_x, uint chunk_y) {
chunk_x = pixel_id % (CANVAS_SIZE / CHUNK_SIZE);
chunk_y = pixel_id / (CANVAS_SIZE / CHUNK_SIZE);
}
function chunk_to_id(
uint chunk_x,
uint chunk_y
) internal pure returns (uint32) {
return uint32(chunk_y * (CANVAS_SIZE / CHUNK_SIZE) + chunk_x);
}
function add_chunk_to_update(uint chunk_x, uint chunk_y) public {
uint32 value = chunk_to_id(chunk_x, chunk_y);
for (uint i = 0; i < chunks_to_update.length; i++) {
if (chunks_to_update[i] == value) {
return;
}
}
chunks_to_update.push(value);
}
function remove_chunk_from_update(uint chunk_x, uint chunk_y) public {
uint32 value = chunk_to_id(chunk_x, chunk_y);
for (uint i = 0; i < chunks_to_update.length; i++) {
if (chunks_to_update[i] == value) {
chunks_to_update[i] = chunks_to_update[
chunks_to_update.length - 1
];
chunks_to_update.pop();
return;
}
}
}
function get_pixel_owner(
uint32 pixel_id
) internal view virtual returns (address);
}
文件 3 的 16:ERC20Token.sol
pragma solidity ^0.8.25;
import "./IERC20.sol";
import "./IERC20Events.sol";
abstract contract ERC20Token is IERC20 {
string internal constant _name = "Piece of Shit";
string internal constant _symbol = "POS";
uint internal constant _decimals = 9;
uint internal constant _totalIds = 1024;
uint internal constant _totalSupply = _totalIds * 10 * 10 ** _decimals;
address internal pool;
uint256 constant _startMaxBuyCount = (_totalSupply * 5) / 10000;
uint256 constant _addMaxBuyPercentPerSec = 5;
uint256 constant _addMaxBuyPrecesion = 100000;
uint256 internal _startTime;
mapping(address => mapping(address => uint)) internal _allowance;
mapping(address => uint) internal _balanceOf;
constructor() {
_balanceOf[msg.sender] = _totalSupply;
}
function name() public view virtual returns (string memory) {
return _name;
}
function maxBuy() public view returns (uint256) {
if (!erc20_started()) return _totalSupply;
uint256 count = _startMaxBuyCount +
(_totalSupply *
(block.timestamp - _startTime) *
_addMaxBuyPercentPerSec) /
_addMaxBuyPrecesion;
if (count > _totalSupply) count = _totalSupply;
return count;
}
function dev_address() internal view virtual returns (address);
function _start_erc20(address pool_address) internal {
pool = pool_address;
_startTime = block.timestamp;
}
function erc20_started() public view returns (bool) {
return pool != address(0);
}
function symbol() public view virtual returns (string memory) {
return _symbol;
}
function decimals() public view virtual returns (uint) {
return _decimals;
}
function totalSupply() public pure override returns (uint) {
return _totalSupply;
}
function balanceOf_erc20(address account) public view returns (uint) {
return _balanceOf[account];
}
function allowance(
address owner,
address spender
) public view override returns (uint) {
return _allowance[owner][spender];
}
function _approve_erc20(
address spender,
uint amount
) internal returns (bool) {
_allowance[msg.sender][spender] = amount;
IERC20Events.emitApproval(msg.sender, spender, amount);
return true;
}
function _spendAllowance(
address owner,
address spender,
uint amount
) internal virtual {
require(
_allowance[owner][spender] >= amount,
"TOKEN: insufficient allowance"
);
_allowance[owner][spender] -= amount;
}
function approve_erc20(address spender, uint amount) public returns (bool) {
_allowance[msg.sender][spender] = amount;
IERC20Events.emitApproval(msg.sender, spender, amount);
return true;
}
function _transfer_erc20(
address from,
address to,
uint256 amount
) internal {
if (
!erc20_started() &&
(from == address(0) ||
from == address(this) ||
from == dev_address() ||
to == dev_address())
) {
_balanceOf[from] -= amount;
unchecked {
_balanceOf[to] += amount;
}
IERC20Events.emitTransfer(from, to, amount);
return;
}
require(erc20_started(), "token not started");
if (from == pool) {
require(amount <= maxBuy(), "max buy");
}
_balanceOf[from] -= amount;
unchecked {
_balanceOf[to] += amount;
}
IERC20Events.emitTransfer(from, to, amount);
}
}
文件 4 的 16:ERC721Events.sol
pragma solidity ^0.8.25;
library ERC721Events {
event Transfer(
address indexed _from,
address indexed _to,
uint indexed _tokenId
);
event Approval(
address indexed _owner,
address indexed _approved,
uint indexed _tokenId
);
event ApprovalForAll(
address indexed _owner,
address indexed _operator,
bool _approved
);
function emitTransfer(address _from, address _to, uint _tokenId) internal {
emit Transfer(_from, _to, _tokenId);
}
function emitApproval(
address _owner,
address _approve,
uint _tokenId
) internal {
emit Approval(_owner, _approve, _tokenId);
}
function emitApprovalForAll(
address _owner,
address _operator,
bool _approved
) internal {
emit ApprovalForAll(_owner, _operator, _approved);
}
}
文件 5 的 16:ERC721Token.sol
pragma solidity ^0.8.25;
import "./IERC721.sol";
import "./ERC721Events.sol";
import "./IERC721TokenReceiver.sol";
import "../../canvas/Canvas.sol";
import "@openzeppelin/contracts/utils/Base64.sol";
import "../../lib/StringConverter.sol";
import "../../lib/String.sol";
uint32 constant MAX_MINTED_TOKENS_COUNT = 1024;
abstract contract ERC721Token is IERC721, Canvas {
mapping(uint256 tokenId => address) public ownerOf;
mapping(uint256 => address) private _nftApprovals;
mapping(address => uint32[]) public ownedNFTs;
mapping(address account => uint count) public balanceOfNft;
mapping(uint32 => uint256) private idToIndex;
mapping(address => mapping(address => bool)) private _operatorApprovals;
uint32 public minted;
uint32 public mint_seed;
error UnsupportedReceiver();
constructor() {
minted = 1;
ERC721Events.emitTransfer(address(0), address(this), 1);
ownerOf[1] = address(this);
}
function pool_address() public view virtual returns (address);
function _transfer_erc721(
address from,
address to,
uint32 tokenId
) internal {
if (to == pool_address()) {
_burn_erc721(from, tokenId);
return;
}
_transfer_erc721_internal(from, to, tokenId);
}
function _transfer_erc721_internal(
address from,
address to,
uint32 tokenId
) private {
require(from == ownerOf[tokenId], "ERC721: Incorrect owner");
delete _nftApprovals[tokenId];
ownerOf[tokenId] = to;
(uint x, uint y) = nft_id_to_pixel(tokenId);
_set_pixel_owner(x, y, to);
_updateOwnedNFTs(from, to, tokenId, false);
ERC721Events.emitTransfer(from, to, tokenId);
}
function _burn_erc721(address from, uint32 tokenId) internal {
require(from == ownerOf[tokenId], "ERC721: Incorrect owner");
delete _nftApprovals[tokenId];
ownerOf[tokenId] = address(0);
(uint x, uint y) = nft_id_to_pixel(tokenId);
_set_pixel_owner(x, y, address(0));
_burn_pixel(x, y);
_updateOwnedNFTs(from, address(0), tokenId, true);
ERC721Events.emitTransfer(from, address(0), tokenId);
}
function safeTransferFrom(
address from,
address to,
uint256 tokenId
) public payable virtual;
function safeTransferFrom(
address from,
address to,
uint256 tokenId,
bytes memory data
) public payable virtual;
function getApproved(uint256 tokenId) public view returns (address) {
if (ownerOf[tokenId] == address(0)) revert();
return _nftApprovals[tokenId];
}
function isApprovedForAll(
address owner,
address operator
) public view override returns (bool) {
return _operatorApprovals[owner][operator];
}
function setApprovalForAll(
address operator,
bool approved
) public override {
_operatorApprovals[msg.sender][operator] = approved;
ERC721Events.emitApprovalForAll(msg.sender, operator, approved);
}
function approve_erc721(
address spender,
uint256 tokenId
) internal returns (bool) {
address owner = ownerOf[tokenId];
if (owner == address(0)) return false;
if (msg.sender != owner && !isApprovedForAll(owner, msg.sender))
revert("TOKEN: You are not approved");
_nftApprovals[tokenId] = spender;
ERC721Events.emitApproval(owner, spender, tokenId);
return true;
}
function picture_pixels_state() internal view returns (string memory) {
return
string(
abi.encodePacked(
StringConverter.to_string(minted > 0 ? minted - 1 : minted),
"/",
StringConverter.to_string(MAX_MINTED_TOKENS_COUNT)
)
);
}
function picture_meta() private view returns (bytes memory) {
return
abi.encodePacked(
'{"name": "Shit Painting", "description": "Own a piece of Doge\'s shit on the blockchain. A piece of pure decentralized art online that no one can take down or steal from its collective owners.", "attributes": [{"trait_type": "Pixels", "value": "',
picture_pixels_state(),
'"}], "image": "data:image/svg+xml;base64,',
Base64.encode(bytes(get_svg())),
'"}'
);
}
function pixel_meta(uint32 tokenId) private view returns (bytes memory) {
(uint x, uint y) = nft_id_to_pixel(tokenId);
PixelData memory data = get_pixel_data(x, y);
return
abi.encodePacked(
abi.encodePacked(
'{"name": "',
pixel_string_name(data),
" #",
StringConverter.to_string(tokenId),
'", "description": "',
pixel_string_description(data)
),
'", "attributes": [{"trait_type": "Color", "value": "#',
data.pixel.color,
'"},',
'{"trait_type": "X", "value": "',
StringConverter.to_string(x),
'"},',
'{"trait_type": "Y", "value": "',
StringConverter.to_string(y),
'"}',
'], "image": "data:image/svg+xml;base64,',
Base64.encode(bytes(get_pixel_svg(data.pixel.color))),
'"}'
);
}
function pixel_string_description(
PixelData memory data
) private pure returns (bytes memory) {
if (
StringLib.equals(data.pixel.color, "FFD777") ||
StringLib.equals(data.pixel.color, "EBA61E")
) return "This is a piece of Doge.";
if (
StringLib.equals(data.pixel.color, "7B542B") ||
StringLib.equals(data.pixel.color, "583231")
) return "This is a piece of shit.";
if (
StringLib.equals(data.pixel.color, "E1D293") ||
StringLib.equals(data.pixel.color, "E1d293 ") ||
StringLib.equals(data.pixel.color, "F2E29d ")
) return "This is a piece of sand.";
if (StringLib.equals(data.pixel.color, "B98552"))
return "This is a piece of Doge's penis.";
if (StringLib.equals(data.pixel.color, "6D570D"))
return "This is a piece of Doge's foot.";
if (StringLib.equals(data.pixel.color, "82BDD0"))
return "This is a piece of sky.";
return "Piece";
}
function pixel_string_name(
PixelData memory data
) private pure returns (bytes memory) {
if (
StringLib.equals(data.pixel.color, "FFD777") ||
StringLib.equals(data.pixel.color, "EBA61E")
) return "Piece of Doge";
if (
StringLib.equals(data.pixel.color, "7B542B") ||
StringLib.equals(data.pixel.color, "583231")
) return "Piece of Shit";
if (
StringLib.equals(data.pixel.color, "E1D293") ||
StringLib.equals(data.pixel.color, "E1d293 ") ||
StringLib.equals(data.pixel.color, "F2E29d ")
) return "Piece of Sand";
if (StringLib.equals(data.pixel.color, "B98552"))
return "Piece of Doge's penis";
if (StringLib.equals(data.pixel.color, "6D570D"))
return "Piece of Doge's foot";
if (StringLib.equals(data.pixel.color, "82BDD0")) return "Piece of Sky";
return "Piece";
}
function tokenURI(
uint256 tokenId
) public view virtual returns (string memory) {
return
string(
abi.encodePacked(
"data:application/json;base64,",
Base64.encode(
tokenId == 1
? picture_meta()
: pixel_meta(uint32(tokenId))
)
)
);
}
function toString(uint256 value) internal pure returns (string memory) {
if (value == 0) {
return "0";
}
uint256 temp = value;
uint256 digits;
while (temp != 0) {
digits++;
temp /= 10;
}
bytes memory buffer = new bytes(digits);
while (value != 0) {
digits -= 1;
buffer[digits] = bytes1(uint8(value % 10) + 48);
value /= 10;
}
return string(buffer);
}
function _updateOwnedNFTs(
address from,
address to,
uint32 tokenId,
bool burn
) internal {
uint256 index = idToIndex[tokenId];
uint32[] storage nftArray = ownedNFTs[from];
uint256 len = nftArray.length;
uint32 lastTokenId = nftArray[len - 1];
nftArray[index] = lastTokenId;
nftArray.pop();
if (len - 1 != 0) {
idToIndex[lastTokenId] = index;
}
--balanceOfNft[from];
if (!burn) {
++balanceOfNft[to];
ownedNFTs[to].push(tokenId);
idToIndex[tokenId] = ownedNFTs[to].length - 1;
} else {
idToIndex[tokenId] = 0;
if (minted > 0) --minted;
}
}
function get_pixel_data_by_id(
uint32 token_id
) public view returns (PixelData memory) {
(uint x, uint y) = nft_id_to_pixel(token_id);
return get_pixel_data(x, y);
}
function _try_mint_nft_limit() internal virtual returns (bool) {
if (rand() % 10 == 0) return false;
return true;
}
function _try_mint_nft(address to) internal {
if (to == pool_address()) return;
if (_try_mint_nft_limit()) return;
uint32 id = _next_mint_erc721_id();
if (ownerOf[id] != address(0)) return;
_mint_erc721(to, id);
}
function _mint_erc721(address to, uint32 tokenId) internal {
unchecked {
minted++;
}
ownerOf[tokenId] = to;
idToIndex[tokenId] = ownedNFTs[to].length;
ownedNFTs[to].push(tokenId);
++balanceOfNft[to];
(uint x, uint y) = nft_id_to_pixel(tokenId);
_set_pixel_owner(x, y, to);
ERC721Events.emitTransfer(address(0), to, tokenId);
}
function _try_mint_nft_batch(address to, uint256 amount) internal {
if (amount == 0) return;
uint i;
for (i = 0; i < amount; ++i) {
_try_mint_nft(to);
}
}
function _next_mint_erc721_id() internal returns (uint32) {
return
uint32(
2 +
(uint(
keccak256(
abi.encodePacked(++mint_seed, block.timestamp)
)
) % MAX_MINTED_TOKENS_COUNT)
);
}
function rand() private returns (uint) {
return uint(keccak256(abi.encodePacked(++mint_seed, msg.sender)));
}
function nft_id_to_pixel(
uint32 token_id
) public pure returns (uint x, uint y) {
x = (token_id - 2) % CANVAS_SIZE;
y = (token_id - 2) / CANVAS_SIZE;
}
function get_pixel_owner(
uint32 pixel_id
) internal view override returns (address) {
return ownerOf[pixel_id];
}
}
文件 6 的 16:HasDev.sol
pragma solidity ^0.8.25;
contract HasDev {
address public dev;
constructor() {
dev = msg.sender;
}
modifier onlyDev() {
require(msg.sender == dev, "Not the developer");
_;
}
function changeDev(address newDev) public onlyDev {
dev = newDev;
}
}
文件 7 的 16:IERC165.sol
pragma solidity ^0.8.25;
interface IERC165 {
function supportsInterface(bytes4 interfaceID) external view returns (bool);
}
文件 8 的 16:IERC20.sol
pragma solidity ^0.8.25;
interface IERC20 {
function balanceOf(address account) external view returns (uint256);
function totalSupply() external view returns (uint256);
function transfer(address to, uint256 value) external returns (bool);
function allowance(
address owner,
address spender
) external view returns (uint256);
function approve(address spender, uint256 value) external returns (bool);
function transferFrom(
address from,
address to,
uint256 value
) external returns (bool);
}
文件 9 的 16:IERC20Events.sol
pragma solidity ^0.8.25;
library IERC20Events {
event Transfer(address indexed from, address indexed to, uint amount);
event Approval(
address indexed owner,
address indexed spender,
uint256 value
);
function emitTransfer(address _from, address _to, uint _amount) internal {
emit Transfer(_from, _to, _amount);
}
function emitApproval(
address _owner,
address _spender,
uint _value
) internal {
emit Approval(_owner, _spender, _value);
}
}
文件 10 的 16:IERC721.sol
pragma solidity ^0.8.25;
interface IERC721 {
function balanceOf(address account) external view returns (uint256);
function ownerOf(uint256 _tokenId) external view returns (address);
function safeTransferFrom(
address _from,
address _to,
uint256 _tokenId,
bytes memory data
) external payable;
function safeTransferFrom(
address _from,
address _to,
uint256 _tokenId
) external payable;
function setApprovalForAll(address _operator, bool _approved) external;
function getApproved(uint256 _tokenId) external view returns (address);
function isApprovedForAll(
address _owner,
address _operator
) external view returns (bool);
function approve(address spender, uint256 value) external returns (bool);
function transferFrom(
address from,
address to,
uint256 value
) external returns (bool);
}
文件 11 的 16:IERC721TokenReceiver.sol
pragma solidity ^0.8.25;
interface IERC721TokenReceiver {
function onERC721Received(
address _operator,
address _from,
uint256 _tokenId,
bytes memory _data
) external returns (bytes4);
}
文件 12 的 16:Ownable.sol
pragma solidity ^0.8.23;
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;
}
}
文件 13 的 16:PieceOfShit.sol
pragma solidity ^0.8.25;
import "../lib/HasDev.sol";
import "./ERC20/ERC20Token.sol";
import "./ERC721/ERC721Token.sol";
import "./ERC165/IERC165.sol";
interface ITOKEN is IERC20, IERC721 {
function balanceOf(
address account
) external view override(IERC20, IERC721) returns (uint256);
function approve(
address spender,
uint256 value
) external override(IERC20, IERC721) returns (bool);
function transferFrom(
address from,
address to,
uint256 value
) external override(IERC20, IERC721) returns (bool);
}
contract PieceOfShit is ERC20Token, ERC721Token, IERC165, HasDev {
uint internal constant ONE = 10 ** _decimals;
bool public nft_interface_supports;
function start_erc20(address pool_address) external onlyDev {
_start_erc20(pool_address);
}
function toggleNFTinterface() public onlyDev {
nft_interface_supports = !nft_interface_supports;
}
function balanceOf(
address account
) public view override(IERC20, IERC721) returns (uint256) {
return balanceOf_erc20(account);
}
function approve(
address spender,
uint amount
) public override(IERC20, IERC721) returns (bool) {
approve_erc20(spender, amount);
uint token_id = amount / ONE;
address owner = ownerOf[token_id];
if (amount > balanceOf(msg.sender) || owner != address(0))
setApprovalForAll(spender, true);
else approve_erc721(spender, token_id);
return true;
}
function transfer(
address to,
uint amount
) public override chunks_late_update returns (bool) {
if (ownerOf[amount] == msg.sender) {
_transfer_erc721(msg.sender, to, uint32(amount));
_transfer_erc20(msg.sender, to, 10 ** _decimals);
return true;
}
_transfer_m1(msg.sender, to, amount);
return true;
}
function _transfer_m1(
address from,
address to,
uint amount
) internal virtual {
require(
_balanceOf[from] >= amount,
"ERCM1: transfer amount exceeds balance"
);
uint256 fromDecimalsPre = _balanceOf[from] % ONE;
uint256 toDecimalsPre = _balanceOf[to] % ONE;
_transfer_erc20(from, to, amount);
uint256 fromDecimalsPost = _balanceOf[from] % ONE;
uint256 toDecimalsPost = _balanceOf[to] % ONE;
uint32[] storage ownedNFTsArray = ownedNFTs[from];
if (fromDecimalsPre < fromDecimalsPost) {
if (ownedNFTsArray.length > 0) {
_burn_erc721(from, ownedNFTsArray[0]);
}
}
if (toDecimalsPre > toDecimalsPost && from == pool && to != pool) {
_try_mint_nft(to);
}
if (from == dev && !erc20_started()) return;
uint amountInTokens = amount / ONE;
if (amountInTokens == 0) return;
uint balanceTokens = _balanceOf[from] / ONE;
if (from == pool) {
uint len = ownedNFTsArray.length;
len = amountInTokens < len ? amountInTokens : len;
for (uint i = 0; i < len; i++) {
_transfer_erc721(from, to, ownedNFTsArray[0]);
}
amountInTokens -= len;
len = amountInTokens < len ? amountInTokens : len;
_try_mint_nft_batch(to, amountInTokens - len);
return;
}
if (to == pool) {
if (balanceTokens >= ownedNFTsArray.length) {
amountInTokens = 0;
}
uint len = ownedNFTsArray.length;
len = amountInTokens < len ? amountInTokens : len;
for (uint i = 0; i < len; i++) {
_burn_erc721(from, ownedNFTsArray[0]);
}
return;
}
uint len = amountInTokens;
if (len > ownedNFTsArray.length) len = ownedNFTsArray.length;
if (balanceTokens >= len) return;
len -= balanceTokens;
for (uint i = 0; i < len; i++) {
_transfer_erc721(from, to, ownedNFTsArray[0]);
}
}
function transferFrom(
address from,
address to,
uint amount
) public override(IERC20, IERC721) returns (bool) {
uint token_id = amount / ONE;
address owner = ownerOf[token_id];
if (owner == from) {
require(
msg.sender == from ||
msg.sender == getApproved(amount) ||
isApprovedForAll(from, msg.sender),
"TOKEN: You don't have the right"
);
_transfer_erc721(from, to, uint32(amount));
_transfer_erc20(from, to, ONE);
return true;
}
_spendAllowance(from, msg.sender, amount);
_transfer_m1(from, to, amount);
return true;
}
function safeTransferFrom(
address from,
address to,
uint256 tokenId
) public payable override {
require(
msg.sender == from ||
msg.sender == getApproved(tokenId) ||
isApprovedForAll(from, msg.sender),
"TOKEN: You don't have the right"
);
_transfer_erc721(from, to, uint32(tokenId));
_transfer_erc20(from, to, ONE);
if (
to.code.length != 0 &&
IERC721TokenReceiver(to).onERC721Received(
msg.sender,
from,
tokenId,
""
) !=
IERC721TokenReceiver.onERC721Received.selector
) {
revert UnsupportedReceiver();
}
}
function safeTransferFrom(
address from,
address to,
uint256 tokenId,
bytes memory data
) public payable override {
require(
msg.sender == from ||
msg.sender == getApproved(tokenId) ||
isApprovedForAll(from, msg.sender),
"TOKEN: You don't have the right"
);
_transfer_erc721(from, to, uint32(tokenId));
_transfer_erc20(from, to, ONE);
if (
to.code.length != 0 &&
IERC721TokenReceiver(to).onERC721Received(
msg.sender,
from,
tokenId,
data
) !=
IERC721TokenReceiver.onERC721Received.selector
) {
revert UnsupportedReceiver();
}
}
function supportsInterface(
bytes4 interfaceId
) public view override returns (bool) {
return
(nft_interface_supports && interfaceId == 0x80ac58cd) ||
interfaceId == 0x01ffc9a7 ||
interfaceId == 0x36372b07;
}
function pool_address() public view override returns (address) {
return pool;
}
function dev_address() internal view override returns (address) {
return dev;
}
}
文件 14 的 16:Rects.sol
pragma solidity ^0.8.25;
import "../lib/StringConverter.sol";
struct Rect {
uint x;
uint y;
uint width;
uint height;
string color;
}
library RectLibrary {
using RectLibrary for Rect;
using RectLibrary for Rect[];
function to_svg(
Rect memory rect
) internal pure returns (string memory svg) {
return
string(
abi.encodePacked(
"<rect fill='#",
rect.color,
"' x='",
StringConverter.to_string(rect.x),
"' y='",
StringConverter.to_string(rect.y),
"' width='",
StringConverter.to_string(rect.width),
"' height='",
StringConverter.to_string(rect.height),
"'/>"
)
);
}
function to_svg(Rect[] memory rects) internal pure returns (string memory) {
string memory res;
for (uint i = 0; i < rects.length; ++i) {
res = string(abi.encodePacked(res, rects[i].to_svg()));
}
return res;
}
function to_svg(
Rect[] storage rects
) internal view returns (string memory res) {
for (uint i = 0; i < rects.length; ++i) {
res = string(abi.encodePacked(res, rects[i].to_svg()));
}
return res;
}
}
文件 15 的 16:String.sol
pragma solidity ^0.8.21;
library StringLib {
function equals(
string memory s1,
string memory s2
) internal pure returns (bool) {
return (keccak256(abi.encodePacked((s1))) ==
keccak256(abi.encodePacked((s2))));
}
}
文件 16 的 16:StringConverter.sol
pragma solidity ^0.8.25;
library StringConverter {
function to_string(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);
}
}
{
"compilationTarget": {
"contracts/token/PieceOfShit.sol": "PieceOfShit"
},
"evmVersion": "paris",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": []
}
[{"inputs":[],"name":"UnsupportedReceiver","type":"error"},{"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":"_owner","type":"address"},{"indexed":true,"internalType":"address","name":"_approved","type":"address"},{"indexed":true,"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"Approval","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_owner","type":"address"},{"indexed":true,"internalType":"address","name":"_operator","type":"address"},{"indexed":false,"internalType":"bool","name":"_approved","type":"bool"}],"name":"ApprovalForAll","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":"amount","type":"uint256"}],"name":"Transfer","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_from","type":"address"},{"indexed":true,"internalType":"address","name":"_to","type":"address"},{"indexed":true,"internalType":"uint256","name":"_tokenId","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[{"internalType":"uint256","name":"chunk_x","type":"uint256"},{"internalType":"uint256","name":"chunk_y","type":"uint256"}],"name":"add_chunk_to_update","outputs":[],"stateMutability":"nonpayable","type":"function"},{"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":"spender","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"approve_erc20","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":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOfNft","outputs":[{"internalType":"uint256","name":"count","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"balanceOf_erc20","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"calculate_all_chunks","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"chunk_x","type":"uint256"},{"internalType":"uint256","name":"chunk_y","type":"uint256"}],"name":"calculate_chunk","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"components":[{"internalType":"uint256","name":"x","type":"uint256"},{"internalType":"uint256","name":"y","type":"uint256"}],"internalType":"struct Chunk[]","name":"chunks","type":"tuple[]"}],"name":"calculate_chunks","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"newDev","type":"address"}],"name":"changeDev","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"dev","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"erc20_started","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"x","type":"uint256"},{"internalType":"uint256","name":"y","type":"uint256"}],"name":"get_chunk","outputs":[{"internalType":"uint256","name":"hunk_x","type":"uint256"},{"internalType":"uint256","name":"chunk_y","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"get_chunks_for_update","outputs":[{"components":[{"internalType":"uint256","name":"x","type":"uint256"},{"internalType":"uint256","name":"y","type":"uint256"}],"internalType":"struct Chunk[]","name":"chunks","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"x","type":"uint256"},{"internalType":"uint256","name":"y","type":"uint256"}],"name":"get_pixel_data","outputs":[{"components":[{"components":[{"internalType":"uint256","name":"x","type":"uint256"},{"internalType":"uint256","name":"y","type":"uint256"},{"internalType":"string","name":"color","type":"string"}],"internalType":"struct Pixel","name":"pixel","type":"tuple"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"bool","name":"minted","type":"bool"}],"internalType":"struct PixelData","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"token_id","type":"uint32"}],"name":"get_pixel_data_by_id","outputs":[{"components":[{"components":[{"internalType":"uint256","name":"x","type":"uint256"},{"internalType":"uint256","name":"y","type":"uint256"},{"internalType":"string","name":"color","type":"string"}],"internalType":"struct Pixel","name":"pixel","type":"tuple"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"bool","name":"minted","type":"bool"}],"internalType":"struct PixelData","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"get_svg","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"operator","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxBuy","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"mint_seed","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minted","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"token_id","type":"uint32"}],"name":"nft_id_to_pixel","outputs":[{"internalType":"uint256","name":"x","type":"uint256"},{"internalType":"uint256","name":"y","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[],"name":"nft_interface_supports","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"ownedNFTs","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ownerRenounce","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"pool_address","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"chunk_x","type":"uint256"},{"internalType":"uint256","name":"chunk_y","type":"uint256"}],"name":"remove_chunk_from_update","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"tokenId","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"operator","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"size","outputs":[{"internalType":"uint256","name":"x","type":"uint256"},{"internalType":"uint256","name":"y","type":"uint256"}],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"address","name":"pool_address","type":"address"}],"name":"start_erc20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"symbol","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"toggleNFTinterface","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"tokenId","type":"uint256"}],"name":"tokenURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"pure","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"},{"inputs":[{"components":[{"internalType":"uint256","name":"x","type":"uint256"},{"internalType":"uint256","name":"y","type":"uint256"},{"internalType":"string","name":"color","type":"string"}],"internalType":"struct Pixel[]","name":"pixels","type":"tuple[]"}],"name":"upload_shit","outputs":[],"stateMutability":"nonpayable","type":"function"}]