diff --git a/src/DN404.sol b/src/DN404.sol index cb3b355..a92b98f 100644 --- a/src/DN404.sol +++ b/src/DN404.sol @@ -33,6 +33,21 @@ pragma solidity ^0.8.4; /// - The ERC20 token allowances and ERC721 token / operator approvals are separate. /// - For MEV safety, users should NOT have concurrently open orders for the ERC20 and ERC721. abstract contract DN404 { + /*«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-*/ + /* ENUMS */ + /*-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»*/ + + /// @dev Denotes the default skip NFT status. + /// Override `_skipNFTDefault` to return a preferred value (defaults to `HasCode`). + enum SkipNFTDefault { + // `On` if the ERC20 owner has code, else `Off`. + HasCode, + // Skip NFT (ERC20 transfers will NOT trigger NFT minting / burning / transferring). + On, + // NOT skip NFT (ERC20 transfers will trigger NFT minting / burning / transferring). + Off + } + /*«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-*/ /* EVENTS */ /*-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»*/ @@ -309,6 +324,11 @@ abstract contract DN404 { /* CONFIGURABLES */ /*-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»*/ + /// @dev Returns the default mode for the skip NFT status. + function _skipNFTDefault() internal view virtual returns (SkipNFTDefault) { + return SkipNFTDefault.HasCode; + } + /// @dev Returns whether the tokens IDs are from `[1..n]` instead of `[0..n-1]`. function _useOneIndexed() internal pure virtual returns (bool) { return true; @@ -1033,12 +1053,16 @@ abstract contract DN404 { /// Returns false otherwise. function getSkipNFT(address owner) public view virtual returns (bool result) { uint8 flags = _getDN404Storage().addressData[owner].flags; - /// @solidity memory-safe-assembly - assembly { - result := iszero(iszero(and(flags, _ADDRESS_DATA_SKIP_NFT_FLAG))) - if iszero(and(flags, _ADDRESS_DATA_SKIP_NFT_INITIALIZED_FLAG)) { - result := iszero(iszero(extcodesize(owner))) + result = flags & _ADDRESS_DATA_SKIP_NFT_FLAG != 0; + if (flags & _ADDRESS_DATA_SKIP_NFT_INITIALIZED_FLAG == uint256(0)) { + if (_skipNFTDefault() == SkipNFTDefault.HasCode) { + /// @solidity memory-safe-assembly + assembly { + result := iszero(iszero(extcodesize(owner))) + } } + if (_skipNFTDefault() == SkipNFTDefault.On) result = true; + if (_skipNFTDefault() == SkipNFTDefault.Off) result = false; } } diff --git a/src/DN420.sol b/src/DN420.sol index e88c5b7..b72aed4 100644 --- a/src/DN420.sol +++ b/src/DN420.sol @@ -42,6 +42,21 @@ pragma solidity ^0.8.4; /// - The ERC20 token allowances and ERC1155 token / operator approvals are separate. /// - For MEV safety, users should NOT have concurrently open orders for the ERC20 and ERC1155. abstract contract DN420 { + /*«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-*/ + /* ENUMS */ + /*-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»*/ + + /// @dev Denotes the default skip NFT status. + /// Override `_skipNFTDefault` to return a preferred value (defaults to `HasCode`). + enum SkipNFTDefault { + // `On` if the ERC20 owner has code, else `Off`. + HasCode, + // Skip NFT (ERC20 transfers will NOT trigger NFT minting / burning / transferring). + On, + // NOT skip NFT (ERC20 transfers will trigger NFT minting / burning / transferring). + Off + } + /*«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-«-*/ /* EVENTS */ /*-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»*/ @@ -321,6 +336,11 @@ abstract contract DN420 { /* CONFIGURABLES */ /*-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»-»*/ + /// @dev Returns the default mode for the skip NFT status. + function _skipNFTDefault() internal view virtual returns (SkipNFTDefault) { + return SkipNFTDefault.HasCode; + } + /// @dev Returns if direct NFT transfers should be used during ERC20 transfers /// whenever possible, instead of burning and re-minting. function _useDirectTransfersIfPossible() internal view virtual returns (bool) { @@ -986,12 +1006,16 @@ abstract contract DN420 { /// Returns false otherwise. function getSkipNFT(address owner) public view virtual returns (bool result) { uint8 flags = _getDN420Storage().addressData[owner].flags; - /// @solidity memory-safe-assembly - assembly { - result := iszero(iszero(and(flags, _ADDRESS_DATA_SKIP_NFT_FLAG))) - if iszero(and(flags, _ADDRESS_DATA_SKIP_NFT_INITIALIZED_FLAG)) { - result := iszero(iszero(extcodesize(owner))) + result = flags & _ADDRESS_DATA_SKIP_NFT_FLAG != 0; + if (flags & _ADDRESS_DATA_SKIP_NFT_INITIALIZED_FLAG == uint256(0)) { + if (_skipNFTDefault() == SkipNFTDefault.HasCode) { + /// @solidity memory-safe-assembly + assembly { + result := iszero(iszero(extcodesize(owner))) + } } + if (_skipNFTDefault() == SkipNFTDefault.On) result = true; + if (_skipNFTDefault() == SkipNFTDefault.Off) result = false; } }