编译器
0.8.26+commit.8a97fa7a
文件 1 的 25:Context.sol
pragma solidity ^0.8.20;
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;
}
}
文件 2 的 25:Create2.sol
pragma solidity ^0.8.20;
library Create2 {
error Create2InsufficientBalance(uint256 balance, uint256 needed);
error Create2EmptyBytecode();
error Create2FailedDeployment();
function deploy(uint256 amount, bytes32 salt, bytes memory bytecode) internal returns (address addr) {
if (address(this).balance < amount) {
revert Create2InsufficientBalance(address(this).balance, amount);
}
if (bytecode.length == 0) {
revert Create2EmptyBytecode();
}
assembly {
addr := create2(amount, add(bytecode, 0x20), mload(bytecode), salt)
}
if (addr == address(0)) {
revert Create2FailedDeployment();
}
}
function computeAddress(bytes32 salt, bytes32 bytecodeHash) internal view returns (address) {
return computeAddress(salt, bytecodeHash, address(this));
}
function computeAddress(bytes32 salt, bytes32 bytecodeHash, address deployer) internal pure returns (address addr) {
assembly {
let ptr := mload(0x40)
mstore(add(ptr, 0x40), bytecodeHash)
mstore(add(ptr, 0x20), salt)
mstore(ptr, deployer)
let start := add(ptr, 0x0b)
mstore8(start, 0xff)
addr := keccak256(start, 85)
}
}
}
文件 3 的 25:ECDSA.sol
pragma solidity ^0.8.20;
library ECDSA {
enum RecoverError {
NoError,
InvalidSignature,
InvalidSignatureLength,
InvalidSignatureS
}
error ECDSAInvalidSignature();
error ECDSAInvalidSignatureLength(uint256 length);
error ECDSAInvalidSignatureS(bytes32 s);
function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError, bytes32) {
if (signature.length == 65) {
bytes32 r;
bytes32 s;
uint8 v;
assembly {
r := mload(add(signature, 0x20))
s := mload(add(signature, 0x40))
v := byte(0, mload(add(signature, 0x60)))
}
return tryRecover(hash, v, r, s);
} else {
return (address(0), RecoverError.InvalidSignatureLength, bytes32(signature.length));
}
}
function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
(address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, signature);
_throwError(error, errorArg);
return recovered;
}
function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError, bytes32) {
unchecked {
bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
uint8 v = uint8((uint256(vs) >> 255) + 27);
return tryRecover(hash, v, r, s);
}
}
function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {
(address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, r, vs);
_throwError(error, errorArg);
return recovered;
}
function tryRecover(
bytes32 hash,
uint8 v,
bytes32 r,
bytes32 s
) internal pure returns (address, RecoverError, bytes32) {
if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
return (address(0), RecoverError.InvalidSignatureS, s);
}
address signer = ecrecover(hash, v, r, s);
if (signer == address(0)) {
return (address(0), RecoverError.InvalidSignature, bytes32(0));
}
return (signer, RecoverError.NoError, bytes32(0));
}
function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {
(address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, v, r, s);
_throwError(error, errorArg);
return recovered;
}
function _throwError(RecoverError error, bytes32 errorArg) private pure {
if (error == RecoverError.NoError) {
return;
} else if (error == RecoverError.InvalidSignature) {
revert ECDSAInvalidSignature();
} else if (error == RecoverError.InvalidSignatureLength) {
revert ECDSAInvalidSignatureLength(uint256(errorArg));
} else if (error == RecoverError.InvalidSignatureS) {
revert ECDSAInvalidSignatureS(errorArg);
}
}
}
文件 4 的 25:ERC20Events.sol
pragma solidity ^0.8.26;
library ERC20Events {
event Approval(address indexed owner, address indexed spender, uint256 value);
event Transfer(address indexed from, address indexed to, uint256 amount);
}
文件 5 的 25:ERC4D.sol
pragma solidity ^0.8.26;
import {IERC404} from "../interfaces/IERC404.sol";
import {PackedDoubleEndedQueue} from "./PackedDoubleEndedQueue.sol";
import {ERC6551Account} from "./ERC6551Account.sol";
import {ERC6551Registry} from "./ERC6551Registry.sol";
import {ERC721Events} from "./ERC721Events.sol";
import {ERC20Events} from "./ERC20Events.sol";
import {IERC721Receiver} from "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol";
import {IERC165} from "@openzeppelin/contracts/interfaces/IERC165.sol";
abstract contract ERC4D is IERC404 {
using PackedDoubleEndedQueue for PackedDoubleEndedQueue.Uint16Deque;
PackedDoubleEndedQueue.Uint16Deque private _storedERC721Ids;
string public name;
string public symbol;
uint8 public immutable decimals;
uint256 public immutable units;
uint256 public totalSupply;
uint256 public minted;
uint256 internal immutable _INITIAL_CHAIN_ID;
bytes32 internal immutable _INITIAL_DOMAIN_SEPARATOR;
mapping(address => uint256) public balanceOf;
mapping(address => mapping(address => uint256)) public allowance;
mapping(uint256 => address) public getApproved;
mapping(address => mapping(address => bool)) public isApprovedForAll;
mapping(uint256 => uint256) internal _ownedData;
mapping(address => uint16[]) internal _owned;
mapping(address => bool) internal _erc721TransferExempt;
mapping(address => uint256) public nonces;
uint256 private constant _BITMASK_ADDRESS = (1 << 160) - 1;
uint256 private constant _BITMASK_OWNED_INDEX = ((1 << 96) - 1) << 160;
uint256 public constant ID_ENCODING_PREFIX = 1 << 255;
struct dddd_setup {
ERC6551Account implementation;
ERC6551Registry registry;
bytes32 salt;
}
dddd_setup[] public setup;
mapping(uint256 => uint256) public nft_setup_set;
constructor(string memory name_, string memory symbol_, uint8 decimals_) {
name = name_;
symbol = symbol_;
if (decimals_ < 18) {
revert DecimalsTooLow();
}
decimals = decimals_;
units = 10 ** decimals;
_INITIAL_CHAIN_ID = block.chainid;
_INITIAL_DOMAIN_SEPARATOR = _computeDomainSeparator();
}
function account(uint256 id_) public view returns (address) {
dddd_setup memory s = setup[nft_setup_set[id_]];
return s.registry.account(address(s.implementation), s.salt, block.chainid, address(this), id_);
}
function execute(uint256 id_, address to, uint256 value, bytes calldata data, uint8 operation)
external
payable
returns (bytes memory result)
{
return ERC6551Account(payable(account(id_))).execute(to, value, data, operation);
}
function ownerOf(uint256 id_) public view virtual returns (address erc721Owner) {
id_ += ID_ENCODING_PREFIX;
erc721Owner = _getOwnerOf(id_);
if (!_isValidTokenId(id_)) {
revert InvalidTokenId();
}
if (erc721Owner == address(0)) {
revert NotFound();
}
}
function owned(address owner_) public view virtual returns (uint256[] memory) {
uint256[] memory ownedAsU256 = new uint256[](_owned[owner_].length);
for (uint256 i = 0; i < _owned[owner_].length;) {
ownedAsU256[i] = _owned[owner_][i];
unchecked {
++i;
}
}
return ownedAsU256;
}
function erc721BalanceOf(address owner_) public view virtual returns (uint256) {
return _owned[owner_].length;
}
function erc20BalanceOf(address owner_) public view virtual returns (uint256) {
return balanceOf[owner_];
}
function erc20TotalSupply() public view virtual returns (uint256) {
return totalSupply;
}
function erc721TotalSupply() public view virtual returns (uint256) {
return minted;
}
function getERC721QueueLength() public view virtual returns (uint256) {
return _storedERC721Ids.length();
}
function getERC721TokensInQueue(uint256 start_, uint256 count_) public view virtual returns (uint256[] memory) {
uint256[] memory tokensInQueue = new uint256[](count_);
for (uint256 i = start_; i < start_ + count_;) {
tokensInQueue[i - start_] = _storedERC721Ids.at(i);
unchecked {
++i;
}
}
return tokensInQueue;
}
function tokenURI(uint256 id_) public view virtual returns (string memory);
function approve(address spender_, uint256 valueOrId_) public virtual returns (bool) {
if (valueOrId_ >= ID_ENCODING_PREFIX) {
return erc20Approve(spender_, valueOrId_);
}
if (_isValidTokenId(valueOrId_ + ID_ENCODING_PREFIX)) {
bool auth = erc721Approve(spender_, valueOrId_);
if (!auth) return erc20Approve(spender_, valueOrId_);
} else {
return erc20Approve(spender_, valueOrId_);
}
return true;
}
function erc721Approve(address spender_, uint256 id_) public virtual returns (bool) {
id_ += ID_ENCODING_PREFIX;
address erc721Owner = _getOwnerOf(id_);
if (msg.sender != erc721Owner && !isApprovedForAll[erc721Owner][msg.sender]) {
return false;
}
getApproved[id_] = spender_;
emit ERC721Events.Approval(erc721Owner, spender_, id_ - ID_ENCODING_PREFIX);
return true;
}
function erc20Approve(address spender_, uint256 value_) public virtual returns (bool) {
if (spender_ == address(0)) {
revert InvalidSpender();
}
allowance[msg.sender][spender_] = value_;
emit ERC20Events.Approval(msg.sender, spender_, value_);
return true;
}
function setApprovalForAll(address operator_, bool approved_) public virtual {
if (operator_ == address(0)) {
revert InvalidOperator();
}
isApprovedForAll[msg.sender][operator_] = approved_;
emit ERC721Events.ApprovalForAll(msg.sender, operator_, approved_);
}
function transferFrom(address from_, address to_, uint256 valueOrId_) public virtual returns (bool) {
if (_isValidTokenId(valueOrId_ + ID_ENCODING_PREFIX)) {
if (from_ != _getOwnerOf(valueOrId_ + ID_ENCODING_PREFIX)) {
return erc20TransferFrom(from_, to_, valueOrId_);
} else {
erc721TransferFrom(from_, to_, valueOrId_);
}
} else {
return erc20TransferFrom(from_, to_, valueOrId_);
}
return true;
}
function erc721TransferFrom(address from_, address to_, uint256 id_) public virtual {
id_ += ID_ENCODING_PREFIX;
if (from_ == address(0)) {
revert InvalidSender();
}
if (to_ == address(0)) {
revert InvalidRecipient();
}
if (from_ != _getOwnerOf(id_)) {
revert Unauthorized();
}
if (msg.sender != from_ && !isApprovedForAll[from_][msg.sender] && msg.sender != getApproved[id_]) {
revert Unauthorized();
}
if (erc721TransferExempt(to_)) {
revert RecipientIsERC721TransferExempt();
}
_transferERC20(from_, to_, units);
_transferERC721(from_, to_, id_);
}
function erc20TransferFrom(address from_, address to_, uint256 value_) public virtual returns (bool) {
if (from_ == address(0)) {
revert InvalidSender();
}
if (to_ == address(0)) {
revert InvalidRecipient();
}
uint256 allowed = allowance[from_][msg.sender];
if (allowed != type(uint256).max) {
allowance[from_][msg.sender] = allowed - value_;
}
return _transferERC20WithERC721(from_, to_, value_);
}
function transfer(address to_, uint256 value_) public virtual returns (bool) {
if (to_ == address(0)) {
revert InvalidRecipient();
}
return _transferERC20WithERC721(msg.sender, to_, value_);
}
function safeTransferFrom(address from_, address to_, uint256 id_) public virtual {
safeTransferFrom(from_, to_, id_, "");
}
function safeTransferFrom(address from_, address to_, uint256 id_, bytes memory data_) public virtual {
if (!_isValidTokenId(id_ + ID_ENCODING_PREFIX)) {
revert InvalidTokenId();
}
transferFrom(from_, to_, id_);
if (
to_.code.length != 0
&& IERC721Receiver(to_).onERC721Received(msg.sender, from_, id_, data_)
!= IERC721Receiver.onERC721Received.selector
) {
revert UnsafeRecipient();
}
}
function permit(
address owner_,
address spender_,
uint256 value_,
uint256 deadline_,
uint8 v_,
bytes32 r_,
bytes32 s_
) public virtual {
if (deadline_ < block.timestamp) {
revert PermitDeadlineExpired();
}
if (_isValidTokenId(value_)) {
revert InvalidApproval();
}
if (spender_ == address(0)) {
revert InvalidSpender();
}
unchecked {
address recoveredAddress = ecrecover(
keccak256(
abi.encodePacked(
"\x19\x01",
DOMAIN_SEPARATOR(),
keccak256(
abi.encode(
keccak256(
"Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)"
),
owner_,
spender_,
value_,
nonces[owner_]++,
deadline_
)
)
)
),
v_,
r_,
s_
);
if (recoveredAddress == address(0) || recoveredAddress != owner_) {
revert InvalidSigner();
}
allowance[recoveredAddress][spender_] = value_;
}
emit ERC20Events.Approval(owner_, spender_, value_);
}
function DOMAIN_SEPARATOR() public view virtual returns (bytes32) {
return block.chainid == _INITIAL_CHAIN_ID ? _INITIAL_DOMAIN_SEPARATOR : _computeDomainSeparator();
}
function supportsInterface(bytes4 interfaceId) public view virtual returns (bool) {
return interfaceId == type(IERC404).interfaceId || interfaceId == type(IERC165).interfaceId;
}
function setSelfERC721TransferExempt(bool state_) public virtual {
_setERC721TransferExempt(msg.sender, state_);
}
function erc721TransferExempt(address target_) public view virtual returns (bool) {
return target_ == address(0) || _erc721TransferExempt[target_];
}
function _isValidTokenId(uint256 id_) internal pure returns (bool) {
return id_ > ID_ENCODING_PREFIX && id_ != type(uint256).max;
}
function _computeDomainSeparator() internal view virtual returns (bytes32) {
return keccak256(
abi.encode(
keccak256("EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"),
keccak256(bytes(name)),
keccak256("1"),
block.chainid,
address(this)
)
);
}
function _transferERC20(address from_, address to_, uint256 value_) internal virtual {
if (from_ == address(0)) {
totalSupply += value_;
} else {
balanceOf[from_] -= value_;
}
unchecked {
balanceOf[to_] += value_;
}
emit ERC20Events.Transfer(from_, to_, value_);
}
function _transferERC721(address from_, address to_, uint256 id_) internal virtual {
if (from_ != address(0)) {
delete getApproved[id_];
uint256 updatedId = ID_ENCODING_PREFIX + _owned[from_][_owned[from_].length - 1];
if (updatedId != id_) {
uint256 updatedIndex = _getOwnedIndex(id_);
_owned[from_][updatedIndex] = uint16(updatedId);
_setOwnedIndex(updatedId, updatedIndex);
}
_owned[from_].pop();
}
if (to_ != address(0)) {
_setOwnerOf(id_, to_);
_owned[to_].push(uint16(id_));
_setOwnedIndex(id_, _owned[to_].length - 1);
} else {
delete _ownedData[id_];
}
emit ERC721Events.Transfer(from_, to_, id_ - ID_ENCODING_PREFIX);
}
function _transferERC20WithERC721(address from_, address to_, uint256 value_) internal virtual returns (bool) {
uint256 erc20BalanceOfSenderBefore = erc20BalanceOf(from_);
uint256 erc20BalanceOfReceiverBefore = erc20BalanceOf(to_);
_transferERC20(from_, to_, value_);
bool isFromERC721TransferExempt = erc721TransferExempt(from_);
bool isToERC721TransferExempt = erc721TransferExempt(to_);
if (isFromERC721TransferExempt && isToERC721TransferExempt) {
} else if (isFromERC721TransferExempt) {
uint256 tokensToRetrieveOrMint = (balanceOf[to_] / units) - (erc20BalanceOfReceiverBefore / units);
for (uint256 i = 0; i < tokensToRetrieveOrMint;) {
_retrieveOrMintERC721(to_);
unchecked {
++i;
}
}
} else if (isToERC721TransferExempt) {
uint256 tokensToWithdrawAndStore = (erc20BalanceOfSenderBefore / units) - (balanceOf[from_] / units);
for (uint256 i = 0; i < tokensToWithdrawAndStore;) {
_withdrawAndStoreERC721(from_);
unchecked {
++i;
}
}
} else {
uint256 nftsToTransfer = value_ / units;
for (uint256 i = 0; i < nftsToTransfer;) {
uint256 indexOfLastToken = _owned[from_].length - 1;
uint256 tokenId = ID_ENCODING_PREFIX + _owned[from_][indexOfLastToken];
_transferERC721(from_, to_, tokenId);
unchecked {
++i;
}
}
if (erc20BalanceOfSenderBefore / units - erc20BalanceOf(from_) / units > nftsToTransfer) {
_withdrawAndStoreERC721(from_);
}
if (erc20BalanceOf(to_) / units - erc20BalanceOfReceiverBefore / units > nftsToTransfer) {
_retrieveOrMintERC721(to_);
}
}
return true;
}
function _mintERC20(address to_, uint256 value_) internal virtual {
if (to_ == address(0)) {
revert InvalidRecipient();
}
if (totalSupply + value_ > ID_ENCODING_PREFIX) {
revert MintLimitReached();
}
_transferERC20WithERC721(address(0), to_, value_);
}
function _retrieveOrMintERC721(address to_) internal virtual {
if (to_ == address(0)) {
revert InvalidRecipient();
}
uint256 id;
if (!_storedERC721Ids.empty()) {
id = ID_ENCODING_PREFIX + _storedERC721Ids.popBack();
} else {
++minted;
if (minted == type(uint256).max) {
revert MintLimitReached();
}
id = ID_ENCODING_PREFIX + minted;
uint256 sl = setup.length - 1;
nft_setup_set[minted] = sl;
_createAccount(sl, minted);
}
address erc721Owner = _getOwnerOf(id);
if (erc721Owner != address(0)) {
revert AlreadyExists();
}
_transferERC721(erc721Owner, to_, id);
}
function _withdrawAndStoreERC721(address from_) internal virtual {
if (from_ == address(0)) {
revert InvalidSender();
}
uint256 id = ID_ENCODING_PREFIX + _owned[from_][_owned[from_].length - 1];
_transferERC721(from_, address(0), id);
_storedERC721Ids.pushFront(uint16(id));
}
function _setERC721TransferExempt(address target_, bool state_) internal virtual {
if (target_ == address(0)) {
revert InvalidExemption();
}
if (state_) {
_clearERC721Balance(target_);
} else {
_reinstateERC721Balance(target_);
}
_erc721TransferExempt[target_] = state_;
}
function _reinstateERC721Balance(address target_) private {
uint256 expectedERC721Balance = erc20BalanceOf(target_) / units;
uint256 actualERC721Balance = erc721BalanceOf(target_);
for (uint256 i = 0; i < expectedERC721Balance - actualERC721Balance;) {
_retrieveOrMintERC721(target_);
unchecked {
++i;
}
}
}
function _clearERC721Balance(address target_) private {
uint256 erc721Balance = erc721BalanceOf(target_);
for (uint256 i = 0; i < erc721Balance;) {
_withdrawAndStoreERC721(target_);
unchecked {
++i;
}
}
}
function _getOwnerOf(uint256 id_) internal view virtual returns (address ownerOf_) {
uint256 data = _ownedData[id_];
assembly {
ownerOf_ := and(data, _BITMASK_ADDRESS)
}
}
function _setOwnerOf(uint256 id_, address owner_) internal virtual {
uint256 data = _ownedData[id_];
assembly {
data := add(and(data, _BITMASK_OWNED_INDEX), and(owner_, _BITMASK_ADDRESS))
}
_ownedData[id_] = data;
}
function _getOwnedIndex(uint256 id_) internal view virtual returns (uint256 ownedIndex_) {
uint256 data = _ownedData[id_];
assembly {
ownedIndex_ := shr(160, data)
}
}
function _setOwnedIndex(uint256 id_, uint256 index_) internal virtual {
uint256 data = _ownedData[id_];
if (index_ > _BITMASK_OWNED_INDEX >> 160) {
revert OwnedIndexOverflow();
}
assembly {
data := add(and(data, _BITMASK_ADDRESS), and(shl(160, index_), _BITMASK_OWNED_INDEX))
}
_ownedData[id_] = data;
}
function _createAccount(uint256 setupId_, uint256 tokenId_) internal virtual {
dddd_setup memory s = setup[setupId_];
try s.registry.createAccount(address(s.implementation), s.salt, block.chainid, address(this), tokenId_) {}
catch {}
}
}
文件 6 的 25:ERC5D.sol
pragma solidity ^0.8.26;
import {ERC4D} from "./libs/ERC4D.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import {ERC6551Registry} from "./libs/ERC6551Registry.sol";
import {ERC6551Account} from "./libs/ERC6551Account.sol";
import {Strings} from "@openzeppelin/contracts/utils/Strings.sol";
contract ERC5D is Ownable, ERC4D {
string public dataURI;
bool public launched;
uint256 public maxWallet;
constructor(
string memory name_,
string memory symbol_,
uint8 decimals_,
uint256 supply721_,
ERC6551Registry registry_,
ERC6551Account implementation_,
bytes32 salt_
) ERC4D(name_, symbol_, decimals_) Ownable(_msgSender()) {
_setERC721TransferExempt(address(this), true);
_setERC721TransferExempt(_msgSender(), true);
setup.push(dddd_setup({implementation: implementation_, registry: registry_, salt: salt_}));
_mintERC20(_msgSender(), supply721_ * units);
maxWallet = erc20TotalSupply() / 100;
}
function tokenURI(uint256 id) public view override returns (string memory) {
uint8 seed = uint8(bytes1(keccak256(abi.encodePacked(id))));
string memory image;
string memory color;
if (seed <= 100) {
image = "1.jpg";
color = "Pink";
} else if (seed <= 160) {
image = "2.jpg";
color = "Gray";
} else if (seed <= 210) {
image = "3.jpg";
color = "Green";
} else if (seed <= 240) {
image = "4.jpg";
color = "Yellow";
} else if (seed <= 255) {
image = "5.jpg";
color = "Orange";
}
string memory jsonPreImage = string.concat(
string.concat(
string.concat('{"name": "Memento #', Strings.toString(id)),
'","description":"A collection of 10,000 Replicants on ERC5D: optimized ERC4D with lower fees, Uniswap V3, and fixed tokenURI for NFTs.","external_url":"https://memento.build","image":"'
),
string.concat(dataURI, image)
);
string memory jsonPostImage = string.concat('","attributes":[{"trait_type":"Color","value":"', color);
string memory jsonPostTraits = '"}]}';
return string.concat(
"data:application/json;utf8,", string.concat(string.concat(jsonPreImage, jsonPostImage), jsonPostTraits)
);
}
function updateURI(string memory uri) external onlyOwner {
dataURI = uri;
}
function setERC721TransferExempt(address account_, bool value_) external onlyOwner {
_setERC721TransferExempt(account_, value_);
}
function upgrade6551Setup(uint256 setupId_, uint256 tokenId_) external {
if (_msgSender() != _getOwnerOf(tokenId_)) {
revert Unauthorized();
}
require(setupId_ < setup.length, "Invalid setup");
nft_setup_set[tokenId_] = setupId_;
_createAccount(setupId_, tokenId_);
}
function launch() external onlyOwner {
launched = true;
}
function _transferERC20WithERC721(address from_, address to_, uint256 value_) internal override returns (bool) {
if ((_erc721TransferExempt[_msgSender()] || _erc721TransferExempt[from_]) && !launched) {
return super._transferERC20WithERC721(from_, to_, value_);
}
require(launched, "Not launched yet");
uint256 bal = erc20BalanceOf(to_);
require(bal + value_ <= maxWallet, "Max wallet limit exceeded");
return super._transferERC20WithERC721(from_, to_, value_);
}
function setSelfERC721TransferExempt(bool state_) public override {
require(launched, "Not launched yet");
super.setSelfERC721TransferExempt(state_);
}
function removeLimits() external onlyOwner {
maxWallet = erc20TotalSupply();
}
}
文件 7 的 25:ERC6551Account.sol
pragma solidity ^0.8.26;
import {IERC165} from "@openzeppelin/contracts/interfaces/IERC165.sol";
import {IERC1271} from "@openzeppelin/contracts/interfaces/IERC1271.sol";
import {IERC721Receiver} from "@openzeppelin/contracts/token/ERC721/IERC721Receiver.sol";
import {IERC1155Receiver} from "@openzeppelin/contracts/token/ERC1155/IERC1155Receiver.sol";
import {IERC6551Account} from "../interfaces/IERC6551Account.sol";
import {IERC6551Executable} from "../interfaces/IERC6551Executable.sol";
import {IERC404} from "../interfaces/IERC404.sol";
import {ERC6551AccountLib} from "./ERC6551AccountLib.sol";
import {SignatureChecker} from "@openzeppelin/contracts/utils/cryptography/SignatureChecker.sol";
contract ERC6551Account is IERC165, IERC1271, IERC6551Account, IERC6551Executable, IERC721Receiver, IERC1155Receiver {
uint256 public state;
receive() external payable {}
function execute(address to, uint256 value, bytes calldata data, uint8 operation)
external
payable
virtual
returns (bytes memory result)
{
require(_isValidSigner(msg.sender), "Invalid signer");
require(operation == 0, "Only call operations are supported");
++state;
bool success;
(success, result) = to.call{value: value}(data);
if (!success) {
assembly {
revert(add(result, 32), mload(result))
}
}
}
function isValidSigner(address signer, bytes calldata) external view virtual returns (bytes4) {
if (_isValidSigner(signer)) {
return IERC6551Account.isValidSigner.selector;
}
return bytes4(0);
}
function isValidSignature(bytes32 hash, bytes memory signature) external view virtual returns (bytes4 magicValue) {
bool isValid = SignatureChecker.isValidSignatureNow(owner(), hash, signature);
if (isValid) {
return IERC1271.isValidSignature.selector;
}
return bytes4(0);
}
function onERC721Received(address, address, uint256 receivedTokenId, bytes memory)
external
view
virtual
returns (bytes4)
{
_revertIfOwnershipCycle(msg.sender, receivedTokenId);
return IERC721Receiver.onERC721Received.selector;
}
function onERC1155Received(address, address, uint256, uint256, bytes memory)
external
view
virtual
returns (bytes4)
{
return IERC1155Receiver.onERC1155Received.selector;
}
function onERC1155BatchReceived(address, address, uint256[] memory, uint256[] memory, bytes memory)
external
pure
virtual
returns (bytes4)
{
return IERC1155Receiver.onERC1155BatchReceived.selector;
}
function supportsInterface(bytes4 interfaceId) public pure virtual returns (bool) {
return (
interfaceId == type(IERC6551Account).interfaceId || interfaceId == type(IERC6551Executable).interfaceId
|| interfaceId == type(IERC1155Receiver).interfaceId || interfaceId == type(IERC721Receiver).interfaceId
|| interfaceId == type(IERC165).interfaceId
);
}
function token() public view virtual override returns (uint256, address, uint256) {
return ERC6551AccountLib.token();
}
function owner() public view virtual returns (address) {
(uint256 chainId, address contractAddress, uint256 tokenId) = token();
if (chainId != block.chainid) return address(0);
return IERC404(contractAddress).ownerOf(tokenId);
}
function _isValidSigner(address signer) internal view virtual returns (bool) {
return signer == owner();
}
function _revertIfOwnershipCycle(address receivedTokenAddress, uint256 receivedTokenId) internal view virtual {
(uint256 _chainId, address _contractAddress, uint256 _tokenId) = token();
require(
_chainId != block.chainid || receivedTokenAddress != _contractAddress || receivedTokenId != _tokenId,
"Cannot own yourself"
);
address currentOwner = owner();
require(currentOwner != address(this), "Token in ownership chain");
uint256 depth = 0;
while (currentOwner.code.length > 0) {
try IERC6551Account(payable(currentOwner)).token() returns (
uint256 chainId, address contractAddress, uint256 tokenId
) {
require(
chainId != block.chainid || contractAddress != receivedTokenAddress || tokenId != receivedTokenId,
"Token in ownership chain"
);
currentOwner = IERC404(contractAddress).ownerOf(tokenId);
require(currentOwner != address(this), "Token in ownership chain");
} catch {
break;
}
unchecked {
++depth;
}
if (depth == 5) revert("Ownership chain too deep");
}
}
}
文件 8 的 25:ERC6551AccountLib.sol
pragma solidity ^0.8.26;
import {ERC6551BytecodeLib} from "./ERC6551BytecodeLib.sol";
import {Create2} from "@openzeppelin/contracts/utils/Create2.sol";
library ERC6551AccountLib {
function computeAddress(
address registry,
address _implementation,
bytes32 _salt,
uint256 chainId,
address tokenContract,
uint256 tokenId
) internal pure returns (address) {
bytes32 bytecodeHash =
keccak256(ERC6551BytecodeLib.getCreationCode(_implementation, _salt, chainId, tokenContract, tokenId));
return Create2.computeAddress(_salt, bytecodeHash, registry);
}
function isERC6551Account(address account, address expectedImplementation, address registry)
internal
view
returns (bool)
{
if (account.code.length != 0xAD) return false;
address _implementation = implementation(account);
if (_implementation.code.length == 0) return false;
if (_implementation != expectedImplementation) return false;
(bytes32 _salt, uint256 chainId, address tokenContract, uint256 tokenId) = context(account);
return account == computeAddress(registry, _implementation, _salt, chainId, tokenContract, tokenId);
}
function implementation(address account) internal view returns (address _implementation) {
assembly {
extcodecopy(account, 0xC, 0xA, 0x14)
_implementation := mload(0x00)
}
}
function implementation() internal view returns (address _implementation) {
return implementation(address(this));
}
function token(address account) internal view returns (uint256, address, uint256) {
bytes memory encodedData = new bytes(0x60);
assembly {
extcodecopy(account, add(encodedData, 0x20), 0x4d, 0x60)
}
return abi.decode(encodedData, (uint256, address, uint256));
}
function token() internal view returns (uint256, address, uint256) {
return token(address(this));
}
function salt(address account) internal view returns (bytes32) {
bytes memory encodedData = new bytes(0x20);
assembly {
extcodecopy(account, add(encodedData, 0x20), 0x2d, 0x20)
}
return abi.decode(encodedData, (bytes32));
}
function salt() internal view returns (bytes32) {
return salt(address(this));
}
function context(address account) internal view returns (bytes32, uint256, address, uint256) {
bytes memory encodedData = new bytes(0x80);
assembly {
extcodecopy(account, add(encodedData, 0x20), 0x2D, 0x80)
}
return abi.decode(encodedData, (bytes32, uint256, address, uint256));
}
function context() internal view returns (bytes32, uint256, address, uint256) {
return context(address(this));
}
}
文件 9 的 25:ERC6551BytecodeLib.sol
pragma solidity ^0.8.26;
library ERC6551BytecodeLib {
function getCreationCode(
address implementation,
bytes32 salt,
uint256 chainId,
address tokenContract,
uint256 tokenId
) internal pure returns (bytes memory result) {
assembly {
result := mload(0x40)
mstore(add(result, 0xb7), tokenId)
mstore(add(result, 0x97), shr(96, shl(96, tokenContract)))
mstore(add(result, 0x77), chainId)
mstore(add(result, 0x57), salt)
mstore(add(result, 0x37), 0x5af43d82803e903d91602b57fd5bf3)
mstore(add(result, 0x28), implementation)
mstore(add(result, 0x14), 0x3d60ad80600a3d3981f3363d3d373d3d3d363d73)
mstore(result, 0xb7)
mstore(0x40, add(result, 0xd7))
}
}
function computeAddress(bytes32 salt, bytes32 bytecodeHash, address deployer)
internal
pure
returns (address result)
{
assembly {
result := mload(0x40)
mstore8(result, 0xff)
mstore(add(result, 0x35), bytecodeHash)
mstore(add(result, 0x01), shl(96, deployer))
mstore(add(result, 0x15), salt)
result := keccak256(result, 0x55)
}
}
}
文件 10 的 25:ERC6551Registry.sol
pragma solidity ^0.8.26;
import {IERC6551Registry} from "../interfaces/IERC6551Registry.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
contract ERC6551Registry is IERC6551Registry, Ownable(msg.sender) {
function createAccount(
address implementation,
bytes32 salt,
uint256 chainId,
address tokenContract,
uint256 tokenId
) external onlyOwner returns (address) {
assembly {
pop(chainId)
calldatacopy(0x8c, 0x24, 0x80)
mstore(0x6c, 0x5af43d82803e903d91602b57fd5bf3)
mstore(0x5d, implementation)
mstore(0x49, 0x3d60ad80600a3d3981f3363d3d373d3d3d363d73)
mstore8(0x00, 0xff)
mstore(0x35, keccak256(0x55, 0xb7))
mstore(0x01, shl(96, address()))
mstore(0x15, salt)
let computed := keccak256(0x00, 0x55)
if iszero(extcodesize(computed)) {
let deployed := create2(0, 0x55, 0xb7, salt)
if iszero(deployed) {
mstore(0x00, 0x20188a59)
revert(0x1c, 0x04)
}
mstore(0x6c, deployed)
log4(
0x6c,
0x60,
0x79f19b3655ee38b1ce526556b7731a20c8f218fbda4a3990b6cc4172fdf88722,
implementation,
tokenContract,
tokenId
)
return(0x6c, 0x20)
}
mstore(0x00, shr(96, shl(96, computed)))
return(0x00, 0x20)
}
}
function cid() external view returns (uint256) {
return block.chainid;
}
function account(address implementation, bytes32 salt, uint256 chainId, address tokenContract, uint256 tokenId)
external
view
returns (address)
{
assembly {
pop(chainId)
pop(tokenContract)
pop(tokenId)
calldatacopy(0x8c, 0x24, 0x80)
mstore(0x6c, 0x5af43d82803e903d91602b57fd5bf3)
mstore(0x5d, implementation)
mstore(0x49, 0x3d60ad80600a3d3981f3363d3d373d3d3d363d73)
mstore8(0x00, 0xff)
mstore(0x35, keccak256(0x55, 0xb7))
mstore(0x01, shl(96, address()))
mstore(0x15, salt)
mstore(0x00, shr(96, shl(96, keccak256(0x00, 0x55))))
return(0x00, 0x20)
}
}
}
文件 11 的 25:ERC721Events.sol
pragma solidity ^0.8.26;
library ERC721Events {
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);
event Approval(address indexed owner, address indexed spender, uint256 indexed id);
event Transfer(address indexed from, address indexed to, uint256 indexed id);
}
文件 12 的 25:IERC1155Receiver.sol
pragma solidity ^0.8.20;
import {IERC165} from "../../utils/introspection/IERC165.sol";
interface IERC1155Receiver is IERC165 {
function onERC1155Received(
address operator,
address from,
uint256 id,
uint256 value,
bytes calldata data
) external returns (bytes4);
function onERC1155BatchReceived(
address operator,
address from,
uint256[] calldata ids,
uint256[] calldata values,
bytes calldata data
) external returns (bytes4);
}
文件 13 的 25:IERC1271.sol
pragma solidity ^0.8.20;
interface IERC1271 {
function isValidSignature(bytes32 hash, bytes memory signature) external view returns (bytes4 magicValue);
}
文件 14 的 25:IERC165.sol
pragma solidity ^0.8.20;
import {IERC165} from "../utils/introspection/IERC165.sol";
文件 15 的 25:IERC404.sol
pragma solidity ^0.8.26;
import {IERC165} from "@openzeppelin/contracts/interfaces/IERC165.sol";
interface IERC404 is IERC165 {
error NotFound();
error InvalidTokenId();
error AlreadyExists();
error InvalidRecipient();
error InvalidSender();
error InvalidSpender();
error InvalidOperator();
error UnsafeRecipient();
error RecipientIsERC721TransferExempt();
error Unauthorized();
error InsufficientAllowance();
error DecimalsTooLow();
error PermitDeadlineExpired();
error InvalidSigner();
error InvalidApproval();
error OwnedIndexOverflow();
error MintLimitReached();
error InvalidExemption();
function name() external view returns (string memory);
function symbol() external view returns (string memory);
function decimals() external view returns (uint8);
function totalSupply() external view returns (uint256);
function erc20TotalSupply() external view returns (uint256);
function erc721TotalSupply() external view returns (uint256);
function balanceOf(address owner_) external view returns (uint256);
function erc721BalanceOf(address owner_) external view returns (uint256);
function erc20BalanceOf(address owner_) external view returns (uint256);
function erc721TransferExempt(address account_) external view returns (bool);
function isApprovedForAll(address owner_, address operator_) external view returns (bool);
function allowance(address owner_, address spender_) external view returns (uint256);
function owned(address owner_) external view returns (uint256[] memory);
function ownerOf(uint256 id_) external view returns (address erc721Owner);
function tokenURI(uint256 id_) external view returns (string memory);
function approve(address spender_, uint256 valueOrId_) external returns (bool);
function erc20Approve(address spender_, uint256 value_) external returns (bool);
function erc721Approve(address spender_, uint256 id_) external returns (bool);
function setApprovalForAll(address operator_, bool approved_) external;
function transferFrom(address from_, address to_, uint256 valueOrId_) external returns (bool);
function erc20TransferFrom(address from_, address to_, uint256 value_) external returns (bool);
function erc721TransferFrom(address from_, address to_, uint256 id_) external;
function transfer(address to_, uint256 amount_) external returns (bool);
function getERC721QueueLength() external view returns (uint256);
function getERC721TokensInQueue(uint256 start_, uint256 count_) external view returns (uint256[] memory);
function setSelfERC721TransferExempt(bool state_) external;
function safeTransferFrom(address from_, address to_, uint256 id_) external;
function safeTransferFrom(address from_, address to_, uint256 id_, bytes calldata data_) external;
function DOMAIN_SEPARATOR() external view returns (bytes32);
function permit(
address owner_,
address spender_,
uint256 value_,
uint256 deadline_,
uint8 v_,
bytes32 r_,
bytes32 s_
) external;
}
文件 16 的 25:IERC6551Account.sol
pragma solidity ^0.8.26;
interface IERC6551Account {
receive() external payable;
function token() external view returns (uint256 chainId, address tokenContract, uint256 tokenId);
function state() external view returns (uint256);
function isValidSigner(address signer, bytes calldata context) external view returns (bytes4 magicValue);
}
文件 17 的 25:IERC6551Executable.sol
pragma solidity ^0.8.26;
interface IERC6551Executable {
function execute(address to, uint256 value, bytes calldata data, uint8 operation)
external
payable
returns (bytes memory);
}
文件 18 的 25:IERC6551Registry.sol
pragma solidity ^0.8.26;
interface IERC6551Registry {
event ERC6551AccountCreated(
address account,
address indexed implementation,
bytes32 salt,
uint256 chainId,
address indexed tokenContract,
uint256 indexed tokenId
);
error AccountCreationFailed();
function createAccount(
address implementation,
bytes32 salt,
uint256 chainId,
address tokenContract,
uint256 tokenId
) external returns (address account);
function account(address implementation, bytes32 salt, uint256 chainId, address tokenContract, uint256 tokenId)
external
view
returns (address account);
}
文件 19 的 25:IERC721Receiver.sol
pragma solidity ^0.8.20;
interface IERC721Receiver {
function onERC721Received(
address operator,
address from,
uint256 tokenId,
bytes calldata data
) external returns (bytes4);
}
文件 20 的 25:Math.sol
pragma solidity ^0.8.20;
library Math {
error MathOverflowedMulDiv();
enum Rounding {
Floor,
Ceil,
Trunc,
Expand
}
function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
uint256 c = a + b;
if (c < a) return (false, 0);
return (true, c);
}
}
function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b > a) return (false, 0);
return (true, a - b);
}
}
function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (a == 0) return (true, 0);
uint256 c = a * b;
if (c / a != b) return (false, 0);
return (true, c);
}
}
function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b == 0) return (false, 0);
return (true, a / b);
}
}
function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
unchecked {
if (b == 0) return (false, 0);
return (true, a % b);
}
}
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return a > b ? a : b;
}
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return a < b ? a : b;
}
function average(uint256 a, uint256 b) internal pure returns (uint256) {
return (a & b) + (a ^ b) / 2;
}
function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
if (b == 0) {
return a / b;
}
return a == 0 ? 0 : (a - 1) / b + 1;
}
function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
unchecked {
uint256 prod0 = x * y;
uint256 prod1;
assembly {
let mm := mulmod(x, y, not(0))
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
if (prod1 == 0) {
return prod0 / denominator;
}
if (denominator <= prod1) {
revert MathOverflowedMulDiv();
}
uint256 remainder;
assembly {
remainder := mulmod(x, y, denominator)
prod1 := sub(prod1, gt(remainder, prod0))
prod0 := sub(prod0, remainder)
}
uint256 twos = denominator & (0 - denominator);
assembly {
denominator := div(denominator, twos)
prod0 := div(prod0, twos)
twos := add(div(sub(0, twos), twos), 1)
}
prod0 |= prod1 * twos;
uint256 inverse = (3 * denominator) ^ 2;
inverse *= 2 - denominator * inverse;
inverse *= 2 - denominator * inverse;
inverse *= 2 - denominator * inverse;
inverse *= 2 - denominator * inverse;
inverse *= 2 - denominator * inverse;
inverse *= 2 - denominator * inverse;
result = prod0 * inverse;
return result;
}
}
function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {
uint256 result = mulDiv(x, y, denominator);
if (unsignedRoundsUp(rounding) && mulmod(x, y, denominator) > 0) {
result += 1;
}
return result;
}
function sqrt(uint256 a) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
uint256 result = 1 << (log2(a) >> 1);
unchecked {
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
return min(result, a / result);
}
}
function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = sqrt(a);
return result + (unsignedRoundsUp(rounding) && result * result < a ? 1 : 0);
}
}
function log2(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 128;
}
if (value >> 64 > 0) {
value >>= 64;
result += 64;
}
if (value >> 32 > 0) {
value >>= 32;
result += 32;
}
if (value >> 16 > 0) {
value >>= 16;
result += 16;
}
if (value >> 8 > 0) {
value >>= 8;
result += 8;
}
if (value >> 4 > 0) {
value >>= 4;
result += 4;
}
if (value >> 2 > 0) {
value >>= 2;
result += 2;
}
if (value >> 1 > 0) {
result += 1;
}
}
return result;
}
function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log2(value);
return result + (unsignedRoundsUp(rounding) && 1 << result < value ? 1 : 0);
}
}
function log10(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >= 10 ** 64) {
value /= 10 ** 64;
result += 64;
}
if (value >= 10 ** 32) {
value /= 10 ** 32;
result += 32;
}
if (value >= 10 ** 16) {
value /= 10 ** 16;
result += 16;
}
if (value >= 10 ** 8) {
value /= 10 ** 8;
result += 8;
}
if (value >= 10 ** 4) {
value /= 10 ** 4;
result += 4;
}
if (value >= 10 ** 2) {
value /= 10 ** 2;
result += 2;
}
if (value >= 10 ** 1) {
result += 1;
}
}
return result;
}
function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log10(value);
return result + (unsignedRoundsUp(rounding) && 10 ** result < value ? 1 : 0);
}
}
function log256(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 16;
}
if (value >> 64 > 0) {
value >>= 64;
result += 8;
}
if (value >> 32 > 0) {
value >>= 32;
result += 4;
}
if (value >> 16 > 0) {
value >>= 16;
result += 2;
}
if (value >> 8 > 0) {
result += 1;
}
}
return result;
}
function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log256(value);
return result + (unsignedRoundsUp(rounding) && 1 << (result << 3) < value ? 1 : 0);
}
}
function unsignedRoundsUp(Rounding rounding) internal pure returns (bool) {
return uint8(rounding) % 2 == 1;
}
}
文件 21 的 25:Ownable.sol
pragma solidity ^0.8.20;
import {Context} from "../utils/Context.sol";
abstract contract Ownable is Context {
address private _owner;
error OwnableUnauthorizedAccount(address account);
error OwnableInvalidOwner(address owner);
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
constructor(address initialOwner) {
if (initialOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(initialOwner);
}
modifier onlyOwner() {
_checkOwner();
_;
}
function owner() public view virtual returns (address) {
return _owner;
}
function _checkOwner() internal view virtual {
if (owner() != _msgSender()) {
revert OwnableUnauthorizedAccount(_msgSender());
}
}
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
function transferOwnership(address newOwner) public virtual onlyOwner {
if (newOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(newOwner);
}
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
文件 22 的 25:PackedDoubleEndedQueue.sol
pragma solidity ^0.8.26;
library PackedDoubleEndedQueue {
uint128 constant SLOT_MASK = (1 << 64) - 1;
uint128 constant INDEX_MASK = SLOT_MASK << 64;
uint256 constant SLOT_DATA_MASK = (1 << 16) - 1;
error QueueEmpty();
error QueueFull();
error QueueOutOfBounds();
error InvalidSlot();
struct Uint16Deque {
uint64 _beginIndex;
uint64 _beginSlot;
uint64 _endIndex;
uint64 _endSlot;
mapping(uint64 index => uint256) _data;
}
function popBack(Uint16Deque storage deque) internal returns (uint16 value) {
unchecked {
uint64 backIndex = deque._endIndex;
uint64 backSlot = deque._endSlot;
if (backIndex == deque._beginIndex && backSlot == deque._beginSlot) {
revert QueueEmpty();
}
if (backSlot == 0) {
--backIndex;
backSlot = 15;
} else {
--backSlot;
}
uint256 data = deque._data[backIndex];
value = _getEntry(data, backSlot);
deque._data[backIndex] = _setData(data, backSlot, 0);
deque._endIndex = backIndex;
deque._endSlot = backSlot;
}
}
function pushFront(Uint16Deque storage deque, uint16 value_) internal {
unchecked {
uint64 frontIndex = deque._beginIndex;
uint64 frontSlot = deque._beginSlot;
if (frontSlot == 0) {
--frontIndex;
frontSlot = 15;
} else {
--frontSlot;
}
if (frontIndex == deque._endIndex && frontSlot == deque._endSlot) {
revert QueueFull();
}
deque._data[frontIndex] = _setData(deque._data[frontIndex], frontSlot, value_);
deque._beginIndex = frontIndex;
deque._beginSlot = frontSlot;
}
}
function at(Uint16Deque storage deque, uint256 index_) internal view returns (uint16 value) {
if (index_ >= length(deque) * 16) revert QueueOutOfBounds();
unchecked {
return _getEntry(
deque._data[deque._beginIndex + uint64(deque._beginSlot + (index_ % 16)) / 16 + uint64(index_ / 16)],
uint64(((deque._beginSlot + index_) % 16))
);
}
}
function length(Uint16Deque storage deque) internal view returns (uint256) {
unchecked {
return (16 - deque._beginSlot) + deque._endSlot + deque._endIndex * 16 - deque._beginIndex * 16 - 16;
}
}
function empty(Uint16Deque storage deque) internal view returns (bool) {
return deque._endSlot == deque._beginSlot && deque._endIndex == deque._beginIndex;
}
function _setData(uint256 data_, uint64 slot_, uint16 value) private pure returns (uint256) {
return (data_ & (~_getSlotMask(slot_))) + (uint256(value) << (16 * slot_));
}
function _getEntry(uint256 data, uint64 slot_) private pure returns (uint16) {
return uint16((data & _getSlotMask(slot_)) >> (16 * slot_));
}
function _getSlotMask(uint64 slot_) private pure returns (uint256) {
return SLOT_DATA_MASK << (slot_ * 16);
}
}
文件 23 的 25:SignatureChecker.sol
pragma solidity ^0.8.20;
import {ECDSA} from "./ECDSA.sol";
import {IERC1271} from "../../interfaces/IERC1271.sol";
library SignatureChecker {
function isValidSignatureNow(address signer, bytes32 hash, bytes memory signature) internal view returns (bool) {
(address recovered, ECDSA.RecoverError error, ) = ECDSA.tryRecover(hash, signature);
return
(error == ECDSA.RecoverError.NoError && recovered == signer) ||
isValidERC1271SignatureNow(signer, hash, signature);
}
function isValidERC1271SignatureNow(
address signer,
bytes32 hash,
bytes memory signature
) internal view returns (bool) {
(bool success, bytes memory result) = signer.staticcall(
abi.encodeCall(IERC1271.isValidSignature, (hash, signature))
);
return (success &&
result.length >= 32 &&
abi.decode(result, (bytes32)) == bytes32(IERC1271.isValidSignature.selector));
}
}
文件 24 的 25:SignedMath.sol
pragma solidity ^0.8.20;
library SignedMath {
function max(int256 a, int256 b) internal pure returns (int256) {
return a > b ? a : b;
}
function min(int256 a, int256 b) internal pure returns (int256) {
return a < b ? a : b;
}
function average(int256 a, int256 b) internal pure returns (int256) {
int256 x = (a & b) + ((a ^ b) >> 1);
return x + (int256(uint256(x) >> 255) & (a ^ b));
}
function abs(int256 n) internal pure returns (uint256) {
unchecked {
return uint256(n >= 0 ? n : -n);
}
}
}
文件 25 的 25:Strings.sol
pragma solidity ^0.8.20;
import {Math} from "./math/Math.sol";
import {SignedMath} from "./math/SignedMath.sol";
library Strings {
bytes16 private constant HEX_DIGITS = "0123456789abcdef";
uint8 private constant ADDRESS_LENGTH = 20;
error StringsInsufficientHexLength(uint256 value, uint256 length);
function toString(uint256 value) internal pure returns (string memory) {
unchecked {
uint256 length = Math.log10(value) + 1;
string memory buffer = new string(length);
uint256 ptr;
assembly {
ptr := add(buffer, add(32, length))
}
while (true) {
ptr--;
assembly {
mstore8(ptr, byte(mod(value, 10), HEX_DIGITS))
}
value /= 10;
if (value == 0) break;
}
return buffer;
}
}
function toStringSigned(int256 value) internal pure returns (string memory) {
return string.concat(value < 0 ? "-" : "", toString(SignedMath.abs(value)));
}
function toHexString(uint256 value) internal pure returns (string memory) {
unchecked {
return toHexString(value, Math.log256(value) + 1);
}
}
function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
uint256 localValue = value;
bytes memory buffer = new bytes(2 * length + 2);
buffer[0] = "0";
buffer[1] = "x";
for (uint256 i = 2 * length + 1; i > 1; --i) {
buffer[i] = HEX_DIGITS[localValue & 0xf];
localValue >>= 4;
}
if (localValue != 0) {
revert StringsInsufficientHexLength(value, length);
}
return string(buffer);
}
function toHexString(address addr) internal pure returns (string memory) {
return toHexString(uint256(uint160(addr)), ADDRESS_LENGTH);
}
function equal(string memory a, string memory b) internal pure returns (bool) {
return bytes(a).length == bytes(b).length && keccak256(bytes(a)) == keccak256(bytes(b));
}
}
{
"compilationTarget": {
"src/ERC5D.sol": "ERC5D"
},
"evmVersion": "paris",
"libraries": {},
"metadata": {
"bytecodeHash": "ipfs"
},
"optimizer": {
"enabled": true,
"runs": 200
},
"remappings": [
":@openzeppelin/=lib/openzeppelin-contracts/",
":@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/",
":ds-test/=lib/openzeppelin-contracts/lib/forge-std/lib/ds-test/src/",
":erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
":forge-std/=lib/forge-std/src/",
":openzeppelin-contracts/=lib/openzeppelin-contracts/"
]
}
[{"inputs":[{"internalType":"string","name":"name_","type":"string"},{"internalType":"string","name":"symbol_","type":"string"},{"internalType":"uint8","name":"decimals_","type":"uint8"},{"internalType":"uint256","name":"supply721_","type":"uint256"},{"internalType":"contract ERC6551Registry","name":"registry_","type":"address"},{"internalType":"contract ERC6551Account","name":"implementation_","type":"address"},{"internalType":"bytes32","name":"salt_","type":"bytes32"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AlreadyExists","type":"error"},{"inputs":[],"name":"DecimalsTooLow","type":"error"},{"inputs":[],"name":"InsufficientAllowance","type":"error"},{"inputs":[],"name":"InvalidApproval","type":"error"},{"inputs":[],"name":"InvalidExemption","type":"error"},{"inputs":[],"name":"InvalidOperator","type":"error"},{"inputs":[],"name":"InvalidRecipient","type":"error"},{"inputs":[],"name":"InvalidSender","type":"error"},{"inputs":[],"name":"InvalidSigner","type":"error"},{"inputs":[],"name":"InvalidSpender","type":"error"},{"inputs":[],"name":"InvalidTokenId","type":"error"},{"inputs":[],"name":"MintLimitReached","type":"error"},{"inputs":[],"name":"NotFound","type":"error"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"name":"OwnableInvalidOwner","type":"error"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"name":"OwnableUnauthorizedAccount","type":"error"},{"inputs":[],"name":"OwnedIndexOverflow","type":"error"},{"inputs":[],"name":"PermitDeadlineExpired","type":"error"},{"inputs":[],"name":"QueueEmpty","type":"error"},{"inputs":[],"name":"QueueFull","type":"error"},{"inputs":[],"name":"QueueOutOfBounds","type":"error"},{"inputs":[],"name":"RecipientIsERC721TransferExempt","type":"error"},{"inputs":[],"name":"Unauthorized","type":"error"},{"inputs":[],"name":"UnsafeRecipient","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":"spender","type":"address"},{"indexed":true,"internalType":"uint256","name":"id","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":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","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":"id","type":"uint256"}],"name":"Transfer","type":"event"},{"inputs":[],"name":"DOMAIN_SEPARATOR","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"ID_ENCODING_PREFIX","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id_","type":"uint256"}],"name":"account","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"allowance","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender_","type":"address"},{"internalType":"uint256","name":"valueOrId_","type":"uint256"}],"name":"approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"balanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"dataURI","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"decimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"spender_","type":"address"},{"internalType":"uint256","name":"value_","type":"uint256"}],"name":"erc20Approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner_","type":"address"}],"name":"erc20BalanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"erc20TotalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from_","type":"address"},{"internalType":"address","name":"to_","type":"address"},{"internalType":"uint256","name":"value_","type":"uint256"}],"name":"erc20TransferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"spender_","type":"address"},{"internalType":"uint256","name":"id_","type":"uint256"}],"name":"erc721Approve","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"owner_","type":"address"}],"name":"erc721BalanceOf","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"erc721TotalSupply","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"target_","type":"address"}],"name":"erc721TransferExempt","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"from_","type":"address"},{"internalType":"address","name":"to_","type":"address"},{"internalType":"uint256","name":"id_","type":"uint256"}],"name":"erc721TransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"id_","type":"uint256"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"},{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"uint8","name":"operation","type":"uint8"}],"name":"execute","outputs":[{"internalType":"bytes","name":"result","type":"bytes"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"getApproved","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getERC721QueueLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"start_","type":"uint256"},{"internalType":"uint256","name":"count_","type":"uint256"}],"name":"getERC721TokensInQueue","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"address","name":"","type":"address"}],"name":"isApprovedForAll","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"launch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"launched","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxWallet","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"minted","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"name","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"nft_setup_set","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"nonces","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner_","type":"address"}],"name":"owned","outputs":[{"internalType":"uint256[]","name":"","type":"uint256[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id_","type":"uint256"}],"name":"ownerOf","outputs":[{"internalType":"address","name":"erc721Owner","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"owner_","type":"address"},{"internalType":"address","name":"spender_","type":"address"},{"internalType":"uint256","name":"value_","type":"uint256"},{"internalType":"uint256","name":"deadline_","type":"uint256"},{"internalType":"uint8","name":"v_","type":"uint8"},{"internalType":"bytes32","name":"r_","type":"bytes32"},{"internalType":"bytes32","name":"s_","type":"bytes32"}],"name":"permit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"removeLimits","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from_","type":"address"},{"internalType":"address","name":"to_","type":"address"},{"internalType":"uint256","name":"id_","type":"uint256"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"from_","type":"address"},{"internalType":"address","name":"to_","type":"address"},{"internalType":"uint256","name":"id_","type":"uint256"},{"internalType":"bytes","name":"data_","type":"bytes"}],"name":"safeTransferFrom","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"operator_","type":"address"},{"internalType":"bool","name":"approved_","type":"bool"}],"name":"setApprovalForAll","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"account_","type":"address"},{"internalType":"bool","name":"value_","type":"bool"}],"name":"setERC721TransferExempt","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bool","name":"state_","type":"bool"}],"name":"setSelfERC721TransferExempt","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"setup","outputs":[{"internalType":"contract ERC6551Account","name":"implementation","type":"address"},{"internalType":"contract ERC6551Registry","name":"registry","type":"address"},{"internalType":"bytes32","name":"salt","type":"bytes32"}],"stateMutability":"view","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":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"tokenURI","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":"value_","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":"valueOrId_","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":[],"name":"units","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"uri","type":"string"}],"name":"updateURI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"setupId_","type":"uint256"},{"internalType":"uint256","name":"tokenId_","type":"uint256"}],"name":"upgrade6551Setup","outputs":[],"stateMutability":"nonpayable","type":"function"}]