Hi all,
As NFTs and DeFi start to converge, there will more commonly be a distinction between the actual owner of an ERC721
token and the functional owner/user.
Examples include:
- staked NFTs
- lending protocols that accept NFTs as collateral
- fractionalized NFTs
Currently, usage in one of those DeFi mechanisms would conflict with ownership verification for gaming, PFPs, art gallery showcases, etc.
Want to start up a thread on a standard ERC interface that could be used to very easily check the âfunctional ownerâ of an NFT held by another smart contract. Hopefully, something like this already exists that I am not aware of.
But if notâŚ
I would propose something very lightweight that could be implemented by contracts with little overhead.
(edit: this is not the final proposed interface, please see below)
interface ERC721Hold {
// emitted when the token is transferred to the contract
event Hold(address indexed _from, uint256 indexed _tokenId);
// emitted when the token is released back to the user
event Release(address indexed _to, uint256 indexed _tokenId);
// returns the functional owner of the held token
function ownerOf(uint256 _tokenID) external view returns (address);
// returns the address to the underlying held ERC721 asset
function asset() external view returns (address);
}
Note: this would also implement ERC165
so applications could easily check a contract for this interface.
Note: the method ownerOf
was intentionally reused from ERC721
so that contracts which fully wrap and tokenize a held NFT position can implement both ERC721
and ERC721Hold
without additional overhead.
Here is some example logic to check for the NFT owner while respecting the ERC721Hold
interface
library {
function getOwner(address addr, uint256 id) public pure returns (address) {
IERC721 token = IERC721(addr);
address owner = token.ownerOf(id);
if (owner.isContract()) {
try IERC165(token_).supportsInterface(0x00000000) returns (bool ret) {
if (ret && IERC721Hold(owner).asset() == addr) {
return IERC721Hold(owner).ownerOf(id);
}
} catch {
return owner;
}
}
return owner;
}
}
Really appreciate any thoughts or feedback!
Thanks all,
Devin