Last active
February 20, 2025 09:28
-
-
Save shobhitic/bd803916d148800b108cc1534ecb090c to your computer and use it in GitHub Desktop.
Rentable NFT with ERC 4907 on Ethereal, Polygon, and other EVM chains - https://youtu.be/t1ZB0-UwWB0
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// SPDX-License-Identifier: CC0-1.0 | |
pragma solidity ^0.8.0; | |
import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; | |
import "./IERC4907.sol"; | |
contract ERC4907 is ERC721, IERC4907 { | |
struct UserInfo | |
{ | |
address user; // address of user role | |
uint64 expires; // unix timestamp, user expires | |
} | |
mapping (uint256 => UserInfo) internal _users; | |
constructor(string memory name_, string memory symbol_) ERC721(name_, symbol_) {} | |
/// @notice set the user and expires of an NFT | |
/// @dev The zero address indicates there is no user | |
/// Throws if `tokenId` is not valid NFT | |
/// @param user The new user of the NFT | |
/// @param expires UNIX timestamp, The new user could use the NFT before expires | |
function setUser(uint256 tokenId, address user, uint64 expires) public override virtual{ | |
require(_isApprovedOrOwner(msg.sender, tokenId), "ERC4907: transfer caller is not owner nor approved"); | |
UserInfo storage info = _users[tokenId]; | |
// require(info.expires < block.timestamp, "Already rented to someone"); | |
info.user = user; | |
info.expires = expires; | |
emit UpdateUser(tokenId, user, expires); | |
} | |
/// @notice Get the user address of an NFT | |
/// @dev The zero address indicates that there is no user or the user is expired | |
/// @param tokenId The NFT to get the user address for | |
/// @return The user address for this NFT | |
function userOf(uint256 tokenId) public view override virtual returns(address){ | |
if (uint256(_users[tokenId].expires) >= block.timestamp) { | |
return _users[tokenId].user; | |
} else { | |
return ownerOf(tokenId); | |
} | |
} | |
/// @notice Get the user expires of an NFT | |
/// @dev The zero value indicates that there is no user | |
/// @param tokenId The NFT to get the user expires for | |
/// @return The user expires for this NFT | |
function userExpires(uint256 tokenId) public view override virtual returns(uint256){ | |
if (uint256(_users[tokenId].expires) >= block.timestamp) { | |
return _users[tokenId].expires; | |
} else { | |
return 115792089237316195423570985008687907853269984665640564039457584007913129639935; | |
} | |
} | |
/// @dev See {IERC165-supportsInterface}. | |
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { | |
return interfaceId == type(IERC4907).interfaceId || super.supportsInterface(interfaceId); | |
} | |
function _beforeTokenTransfer( | |
address from, | |
address to, | |
uint256 tokenId | |
) internal virtual override{ | |
super._beforeTokenTransfer(from, to, tokenId); | |
if (from != to && _users[tokenId].user != address(0)) { | |
delete _users[tokenId]; | |
emit UpdateUser(tokenId, address(0), 0); | |
} | |
} | |
function mint(uint256 tokenId) public { | |
// this is the mint function that you need to customize for yourself | |
_mint(msg.sender, tokenId); | |
} | |
function time() public view returns (uint256) { | |
return block.timestamp; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// SPDX-License-Identifier: CC0-1.0 | |
pragma solidity ^0.8.0; | |
interface IERC4907 { | |
// Logged when the user of an NFT is changed or expires is changed | |
/// @notice Emitted when the `user` of an NFT or the `expires` of the `user` is changed | |
/// The zero address for user indicates that there is no user address | |
event UpdateUser(uint256 indexed tokenId, address indexed user, uint64 expires); | |
/// @notice set the user and expires of an NFT | |
/// @dev The zero address indicates there is no user | |
/// Throws if `tokenId` is not valid NFT | |
/// @param user The new user of the NFT | |
/// @param expires UNIX timestamp, The new user could use the NFT before expires | |
function setUser(uint256 tokenId, address user, uint64 expires) external; | |
/// @notice Get the user address of an NFT | |
/// @dev The zero address indicates that there is no user or the user is expired | |
/// @param tokenId The NFT to get the user address for | |
/// @return The user address for this NFT | |
function userOf(uint256 tokenId) external view returns(address); | |
/// @notice Get the user expires of an NFT | |
/// @dev The zero value indicates that there is no user | |
/// @param tokenId The NFT to get the user expires for | |
/// @return The user expires for this NFT | |
function userExpires(uint256 tokenId) external view returns(uint256); | |
} |
There was recently a breaking update to _beforeTokenTransfer, so now it needs 4 variables to be overridden correctly. Have a look at this thread: trufflesuite/truffle#5715
yed you are right , it needs to be fixed
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
There was recently a breaking update to _beforeTokenTransfer, so now it needs 4 variables to be overridden correctly. Have a look at this thread: trufflesuite/truffle#5715