Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Conversation

kumaryash90
Copy link
Member

No description provided.

@kumaryash90 kumaryash90 marked this pull request as draft March 11, 2024 19:38
@kumaryash90 kumaryash90 changed the title gas benchmarks for tokenerc721 [Do Not Merge] benchmark tokenerc721 alt Mar 11, 2024
function initialize(
address _defaultAdmin,
string memory _name,
string memory _symbol,

Check notice

Code scanning / Slither

Local variable shadowing

TokenERC721Alt.initialize(address,string,string,string,address[],address,uint128)._symbol (contracts/prebuilts/token/TokenERC721Alt.sol#108) shadows: - ERC721Upgradeable._symbol (lib/openzeppelin-contracts-upgradeable/contracts/token/ERC721/ERC721Upgradeable.sol#28) (state variable)
/// @dev Initializes the contract, like a constructor.
function initialize(
address _defaultAdmin,
string memory _name,

Check notice

Code scanning / Slither

Local variable shadowing

TokenERC721Alt.initialize(address,string,string,string,address[],address,uint128)._name (contracts/prebuilts/token/TokenERC721Alt.sol#107) shadows: - ERC721Upgradeable._name (lib/openzeppelin-contracts-upgradeable/contracts/token/ERC721/ERC721Upgradeable.sol#25) (state variable) - EIP712Upgradeable._name (lib/openzeppelin-contracts-upgradeable/contracts/utils/cryptography/EIP712Upgradeable.sol#44) (state variable)
Comment on lines +48 to +375
contract TokenERC721Alt is
Initializable,
IThirdwebContract,
IOwnable,
IRoyalty,
ReentrancyGuardUpgradeable,
EIP712Upgradeable,
ERC2771ContextUpgradeable,
Multicall,
AccessControlEnumerableUpgradeable,
ERC721EnumerableUpgradeable,
ITokenERC721Alt,
NFTMetadata
{
using ECDSAUpgradeable for bytes32;
using StringsUpgradeable for uint256;

bytes32 private constant MODULE_TYPE = bytes32("TokenERC721");
uint256 private constant VERSION = 1;

bytes32 private constant TYPEHASH =
keccak256("MintRequest(address to,uint128 validityStartTimestamp,uint128 validityEndTimestamp,bytes32 uid)");

/// @dev Only TRANSFER_ROLE holders can have tokens transferred from or to them, during restricted transfers.
bytes32 private constant TRANSFER_ROLE = keccak256("TRANSFER_ROLE");
/// @dev Only MINTER_ROLE holders can sign off on `MintRequest`s.
bytes32 private constant MINTER_ROLE = keccak256("MINTER_ROLE");
/// @dev Only METADATA_ROLE holders can update NFT metadata.
bytes32 private constant METADATA_ROLE = keccak256("METADATA_ROLE");

/// @dev Max bps in the thirdweb system
uint256 private constant MAX_BPS = 10_000;

/// @dev Owner of the contract (purpose: OpenSea compatibility, etc.)
address private _owner;

/// @dev The token ID of the next token to mint.
uint256 public nextTokenIdToMint;

/// @dev The recipient of who gets the royalty.
address private royaltyRecipient;

/// @dev The percentage of royalty how much royalty in basis points.
uint128 private royaltyBps;

/// @dev Contract level metadata.
string public contractURI;

/// @dev Mapping from mint request UID => whether the mint request is processed.
mapping(bytes32 => bool) private minted;

/// @dev Token ID => royalty recipient and bps for token
mapping(uint256 => RoyaltyInfo) private royaltyInfoForToken;

constructor() initializer {}

/// @dev Initializes the contract, like a constructor.
function initialize(
address _defaultAdmin,
string memory _name,
string memory _symbol,
string memory _contractURI,
address[] memory _trustedForwarders,
address _royaltyRecipient,
uint128 _royaltyBps
) external initializer {
// Initialize inherited contracts, most base-like -> most derived.
__ReentrancyGuard_init();
__EIP712_init("TokenERC721", "1");
__ERC2771Context_init(_trustedForwarders);
__ERC721_init(_name, _symbol);

// Initialize this contract's state.
royaltyRecipient = _royaltyRecipient;
royaltyBps = _royaltyBps;
contractURI = _contractURI;

_owner = _defaultAdmin;
_setupRole(DEFAULT_ADMIN_ROLE, _defaultAdmin);
_setupRole(MINTER_ROLE, _defaultAdmin);

_setupRole(METADATA_ROLE, _defaultAdmin);
_setRoleAdmin(METADATA_ROLE, METADATA_ROLE);

_setupRole(TRANSFER_ROLE, _defaultAdmin);
_setupRole(TRANSFER_ROLE, address(0));

emit DefaultRoyalty(_royaltyRecipient, _royaltyBps);
}

/// ===== Public functions =====

/// @dev Returns the module type of the contract.
function contractType() external pure returns (bytes32) {
return MODULE_TYPE;
}

/// @dev Returns the version of the contract.
function contractVersion() external pure returns (uint8) {
return uint8(VERSION);
}

/**
* @dev Returns the address of the current owner.
*/
function owner() public view returns (address) {
return hasRole(DEFAULT_ADMIN_ROLE, _owner) ? _owner : address(0);
}

/// @dev Verifies that a mint request is signed by an account holding MINTER_ROLE (at the time of the function call).
function verify(MintRequest calldata _req, bytes calldata _signature) public view returns (bool, address) {
address signer = recoverAddress(_req, _signature);
return (!minted[_req.uid] && hasRole(MINTER_ROLE, signer), signer);
}

/// @dev Returns the URI for a tokenId
function tokenURI(uint256 _tokenId) public view override returns (string memory) {
return _tokenURI[_tokenId];
}

/// @dev Lets an account with MINTER_ROLE mint an NFT.
function mintTo(address _to, string calldata _uri) external nonReentrant onlyRole(MINTER_ROLE) returns (uint256) {
// `_mintTo` is re-used. `mintTo` just adds a minter role check.
return _mintTo(_to);
}

/// ===== External functions =====

/// @dev See EIP-2981
function royaltyInfo(
uint256 tokenId,
uint256 salePrice
) external view virtual returns (address receiver, uint256 royaltyAmount) {
(address recipient, uint256 bps) = getRoyaltyInfoForToken(tokenId);
receiver = recipient;
royaltyAmount = (salePrice * bps) / MAX_BPS;
}

/// @dev Mints an NFT according to the provided mint request.
function mintWithSignature(
MintRequest calldata _req,
bytes calldata _signature
) external payable nonReentrant returns (uint256 tokenIdMinted) {
address signer = verifyRequest(_req, _signature);
address receiver = _req.to;

tokenIdMinted = _mintTo(receiver);

// if (_req.to != address(0)) {
// royaltyInfoForToken[tokenIdMinted] = RoyaltyInfo({ recipient: _req.to, bps: 100 });
// }

// collectPrice(_req);

emit TokensMintedWithSignature(signer, receiver, tokenIdMinted, _req);
}

/// @dev Collects and distributes the primary sale value of tokens being claimed.
function collectPrice(MintRequest calldata _req) internal {
if (_req.uid != bytes32(0)) {
require(_req.uid != bytes32(0), "!Value");
return;
}
}

// ===== Setter functions =====

/// @dev Lets a module admin update the royalty bps and recipient.
function setDefaultRoyaltyInfo(
address _royaltyRecipient,
uint256 _royaltyBps
) external onlyRole(DEFAULT_ADMIN_ROLE) {
require(_royaltyBps <= MAX_BPS, "exceed royalty bps");

royaltyRecipient = _royaltyRecipient;
royaltyBps = uint128(_royaltyBps);

emit DefaultRoyalty(_royaltyRecipient, _royaltyBps);
}

/// @dev Lets a module admin set the royalty recipient for a particular token Id.
function setRoyaltyInfoForToken(
uint256 _tokenId,
address _recipient,
uint256 _bps
) external onlyRole(DEFAULT_ADMIN_ROLE) {
require(_bps <= MAX_BPS, "exceed royalty bps");

royaltyInfoForToken[_tokenId] = RoyaltyInfo({ recipient: _recipient, bps: _bps });

emit RoyaltyForToken(_tokenId, _recipient, _bps);
}

/// @dev Lets a module admin set a new owner for the contract. The new owner must be a module admin.
function setOwner(address _newOwner) external onlyRole(DEFAULT_ADMIN_ROLE) {
require(hasRole(DEFAULT_ADMIN_ROLE, _newOwner), "new owner not module admin.");
address _prevOwner = _owner;
_owner = _newOwner;

emit OwnerUpdated(_prevOwner, _newOwner);
}

/// @dev Lets a module admin set the URI for contract-level metadata.
function setContractURI(string calldata _uri) external onlyRole(DEFAULT_ADMIN_ROLE) {
contractURI = _uri;
}

/// ===== Getter functions =====

/// @dev Returns the platform fee bps and recipient.
function getDefaultRoyaltyInfo() external view returns (address, uint16) {
return (royaltyRecipient, uint16(royaltyBps));
}

/// @dev Returns the royalty recipient for a particular token Id.
function getRoyaltyInfoForToken(uint256 _tokenId) public view returns (address, uint16) {
RoyaltyInfo memory royaltyForToken = royaltyInfoForToken[_tokenId];

return
royaltyForToken.recipient == address(0)
? (royaltyRecipient, uint16(royaltyBps))
: (royaltyForToken.recipient, uint16(royaltyForToken.bps));
}

/// ===== Internal functions =====

/// @dev Mints an NFT to `to`
function _mintTo(address _to) internal returns (uint256 tokenIdToMint) {
tokenIdToMint = nextTokenIdToMint;
nextTokenIdToMint += 1;

_safeMint(_to, tokenIdToMint);

emit TokensMinted(_to, tokenIdToMint, "");
}

/// @dev Returns the address of the signer of the mint request.
function recoverAddress(MintRequest calldata _req, bytes calldata _signature) private view returns (address) {
return _hashTypedDataV4(keccak256(_encodeRequest(_req))).recover(_signature);
}

/// @dev Resolves 'stack too deep' error in `recoverAddress`.
function _encodeRequest(MintRequest calldata _req) private pure returns (bytes memory) {
return abi.encode(TYPEHASH, _req.to, _req.validityStartTimestamp, _req.validityEndTimestamp, _req.uid);
}

/// @dev Verifies that a mint request is valid.
function verifyRequest(MintRequest calldata _req, bytes calldata _signature) internal returns (address) {
(bool success, address signer) = verify(_req, _signature);
require(success, "invalid signature");

require(
_req.validityStartTimestamp <= block.timestamp && _req.validityEndTimestamp >= block.timestamp,
"request expired"
);
require(_req.to != address(0), "recipient undefined");

minted[_req.uid] = true;

return signer;
}

/// ===== Low-level overrides =====

/// @dev Burns `tokenId`. See {ERC721-_burn}.
function burn(uint256 tokenId) public virtual {
//solhint-disable-next-line max-line-length
require(_isApprovedOrOwner(_msgSender(), tokenId), "ERC721Burnable: caller is not owner nor approved");
_burn(tokenId);
}

/// @dev See {ERC721-_beforeTokenTransfer}.
function _beforeTokenTransfer(
address from,
address to,
uint256 tokenId,
uint256 batchSize
) internal virtual override(ERC721EnumerableUpgradeable) {
super._beforeTokenTransfer(from, to, tokenId, batchSize);

// if transfer is restricted on the contract, we still want to allow burning and minting
if (!hasRole(TRANSFER_ROLE, address(0)) && from != address(0) && to != address(0)) {
require(hasRole(TRANSFER_ROLE, from) || hasRole(TRANSFER_ROLE, to), "restricted to TRANSFER_ROLE holders");
}
}

/// @dev Returns whether metadata can be set in the given execution context.
function _canSetMetadata() internal view virtual override returns (bool) {
return hasRole(METADATA_ROLE, _msgSender());
}

/// @dev Returns whether metadata can be frozen in the given execution context.
function _canFreezeMetadata() internal view virtual override returns (bool) {
return hasRole(METADATA_ROLE, _msgSender());
}

function supportsInterface(
bytes4 interfaceId
)
public
view
virtual
override(AccessControlEnumerableUpgradeable, ERC721EnumerableUpgradeable, IERC165Upgradeable, IERC165)
returns (bool)
{
return super.supportsInterface(interfaceId) || interfaceId == type(IERC2981Upgradeable).interfaceId;
}

function _msgSender()
internal
view
virtual
override(ContextUpgradeable, ERC2771ContextUpgradeable, Multicall)
returns (address sender)
{
return ERC2771ContextUpgradeable._msgSender();
}

function _msgData()
internal
view
virtual
override(ContextUpgradeable, ERC2771ContextUpgradeable)
returns (bytes calldata)
{
return ERC2771ContextUpgradeable._msgData();
}
}

Check warning

Code scanning / Slither

Missing inheritance

TokenERC721Alt (contracts/prebuilts/token/TokenERC721Alt.sol#48-375) should inherit from IBurnableERC721 (contracts/extension/interface/IBurnableERC721.sol#6-15)
Copy link

codecov bot commented Mar 11, 2024

Codecov Report

Attention: Patch coverage is 51.42857% with 34 lines in your changes are missing coverage. Please review.

Project coverage is 64.58%. Comparing base (90ca7b4) to head (1491165).

Files Patch % Lines
contracts/prebuilts/token/TokenERC721Alt.sol 51.42% 34 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #625      +/-   ##
==========================================
- Coverage   64.72%   64.58%   -0.14%     
==========================================
  Files         216      217       +1     
  Lines        6702     6772      +70     
==========================================
+ Hits         4338     4374      +36     
- Misses       2364     2398      +34     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant