mirror of
https://github.com/lens-protocol/core.git
synced 2026-01-09 14:18:04 -05:00
@@ -228,20 +228,6 @@ abstract contract LensBaseERC721 is ERC165, ILensERC721 {
|
||||
_transfer(from, to, tokenId);
|
||||
}
|
||||
|
||||
function transferFromWithData(
|
||||
address from,
|
||||
address to,
|
||||
uint256 tokenId,
|
||||
bytes memory data
|
||||
) public virtual override {
|
||||
//solhint-disable-next-line max-line-length
|
||||
if (!_isApprovedOrOwner(msg.sender, tokenId)) {
|
||||
revert Errors.NotOwnerOrApproved();
|
||||
}
|
||||
|
||||
_transferWithData(from, to, tokenId, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev See {IERC721-safeTransferFrom}.
|
||||
*/
|
||||
@@ -443,28 +429,6 @@ abstract contract LensBaseERC721 is ERC165, ILensERC721 {
|
||||
emit Transfer(from, to, tokenId);
|
||||
}
|
||||
|
||||
function _transferWithData(address from, address to, uint256 tokenId, bytes memory data) internal virtual {
|
||||
if (ownerOf(tokenId) != from) {
|
||||
revert Errors.InvalidOwner();
|
||||
}
|
||||
if (to == address(0)) {
|
||||
revert Errors.InvalidParameter();
|
||||
}
|
||||
|
||||
_beforeTokenTransferWithData(from, to, tokenId, data);
|
||||
|
||||
// Clear approvals from the previous owner
|
||||
_approve(address(0), tokenId);
|
||||
|
||||
unchecked {
|
||||
--_balances[from];
|
||||
++_balances[to];
|
||||
}
|
||||
_tokenData[tokenId].owner = to;
|
||||
|
||||
emit Transfer(from, to, tokenId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @dev Approve `to` to operate on `tokenId`
|
||||
*
|
||||
@@ -542,11 +506,4 @@ abstract contract LensBaseERC721 is ERC165, ILensERC721 {
|
||||
address to,
|
||||
uint256 tokenId
|
||||
) internal virtual {}
|
||||
|
||||
function _beforeTokenTransferWithData(
|
||||
address from,
|
||||
address to,
|
||||
uint256 tokenId,
|
||||
bytes memory data
|
||||
) internal virtual {}
|
||||
}
|
||||
|
||||
@@ -133,7 +133,35 @@ abstract contract LensProfiles is LensBaseERC721, ERC2981CollectionRoyalties, IL
|
||||
* @dev See {ILensERC721-transferFromWithData}.
|
||||
*/
|
||||
function transferFromKeepingDelegates(address from, address to, uint256 tokenId) external {
|
||||
transferFromWithData(from, to, tokenId, abi.encode(true));
|
||||
//solhint-disable-next-line max-line-length
|
||||
if (!_isApprovedOrOwner(msg.sender, tokenId)) {
|
||||
revert Errors.NotOwnerOrApproved();
|
||||
}
|
||||
|
||||
if (!StorageLib.profileCreatorWhitelisted()[from]) {
|
||||
// Delegates can be maintained on transfer only during mint tx (block) for onboarding UX purposes.
|
||||
revert Errors.NotAllowed();
|
||||
}
|
||||
|
||||
if (ownerOf(tokenId) != from) {
|
||||
revert Errors.InvalidOwner();
|
||||
}
|
||||
if (to == address(0)) {
|
||||
revert Errors.InvalidParameter();
|
||||
}
|
||||
|
||||
_beforeTokenTransferWithoutClearingDelegates(from, to, tokenId);
|
||||
|
||||
// Clear approvals from the previous owner
|
||||
_approve(address(0), tokenId);
|
||||
|
||||
unchecked {
|
||||
--_balances[from];
|
||||
++_balances[to];
|
||||
}
|
||||
_tokenData[tokenId].owner = to;
|
||||
|
||||
emit Transfer(from, to, tokenId);
|
||||
}
|
||||
|
||||
function _hasTokenGuardianEnabled(address wallet) internal view returns (bool) {
|
||||
@@ -156,34 +184,26 @@ abstract contract LensProfiles is LensBaseERC721, ERC2981CollectionRoyalties, IL
|
||||
}
|
||||
|
||||
function _beforeTokenTransfer(address from, address to, uint256 tokenId) internal override whenNotPaused {
|
||||
_beforeTokenTransferProfile(from, to, tokenId, false);
|
||||
}
|
||||
|
||||
function _beforeTokenTransferWithData(
|
||||
address from,
|
||||
address to,
|
||||
uint256 tokenId,
|
||||
bytes memory data
|
||||
) internal override whenNotPaused {
|
||||
bool keepProfileDelegates = abi.decode(data, (bool));
|
||||
|
||||
_beforeTokenTransferProfile(from, to, tokenId, keepProfileDelegates);
|
||||
}
|
||||
|
||||
function _beforeTokenTransferProfile(
|
||||
address from,
|
||||
address to,
|
||||
uint256 tokenId,
|
||||
bool keepProfileDelegates
|
||||
) internal whenNotPaused {
|
||||
if (from != address(0) && _hasTokenGuardianEnabled(from)) {
|
||||
// Cannot transfer profile if the guardian is enabled, except at minting time.
|
||||
revert Errors.GuardianEnabled();
|
||||
}
|
||||
// Switches to new fresh delegated executors configuration (except on minting, as it already has a fresh setup).
|
||||
if (from != address(0) && !keepProfileDelegates) {
|
||||
if (from != address(0)) {
|
||||
ProfileLib.switchToNewFreshDelegatedExecutorsConfig(tokenId);
|
||||
}
|
||||
super._beforeTokenTransfer(from, to, tokenId);
|
||||
}
|
||||
|
||||
function _beforeTokenTransferWithoutClearingDelegates(
|
||||
address from,
|
||||
address to,
|
||||
uint256 tokenId
|
||||
) internal override whenNotPaused {
|
||||
if (from != address(0) && _hasTokenGuardianEnabled(from)) {
|
||||
// Cannot transfer profile if the guardian is enabled, except at minting time.
|
||||
revert Errors.GuardianEnabled();
|
||||
}
|
||||
super._beforeTokenTransfer(from, to, tokenId);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -49,4 +49,6 @@ library Errors {
|
||||
|
||||
// Migration Errors
|
||||
error NotMigrationAdmin();
|
||||
|
||||
error NotAllowed();
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ contract PermissonlessCreator is Ownable {
|
||||
ITokenHandleRegistry public immutable TOKEN_HANDLE_REGISTRY;
|
||||
address immutable LENS_HUB;
|
||||
|
||||
uint256 public profileWithHandleCreationCost = 5 ether;
|
||||
uint256 public profileCreationCost = 5 ether;
|
||||
uint256 public handleCreationCost = 5 ether;
|
||||
|
||||
mapping(address => uint256) public credits;
|
||||
@@ -56,27 +56,26 @@ contract PermissonlessCreator is Ownable {
|
||||
TOKEN_HANDLE_REGISTRY = ITokenHandleRegistry(tokenHandleRegistry);
|
||||
}
|
||||
|
||||
function createProfileOnly(
|
||||
// Payable functions for public
|
||||
|
||||
function createProfile(
|
||||
Types.CreateProfileParams calldata createProfileParams,
|
||||
address[] calldata delegatedExecutors
|
||||
) external onlyCredit returns (uint256) {
|
||||
_checkAndRedeemCredit(msg.sender);
|
||||
) external payable returns (uint256 profileId, uint256 handleId) {
|
||||
if (msg.value != profileCreationCost) {
|
||||
revert InvalidFunds();
|
||||
}
|
||||
return _createProfile(createProfileParams, delegatedExecutors);
|
||||
}
|
||||
|
||||
// We mint the profile to this contract first, then apply delegates if defined
|
||||
// This will not allow to initialize follow modules that require funds from the msg.sender,
|
||||
// but we assume only simple follow modules should be set during profile creation.
|
||||
// Complex ones can be set after the profile is created.
|
||||
address destination = createProfileParams.to;
|
||||
|
||||
uint256 profileId = _createProfile(createProfileParams);
|
||||
profileCreatedOnlyByCredit[profileId] = msg.sender;
|
||||
|
||||
_addDelegatesToProfile(profileId, delegatedExecutors);
|
||||
|
||||
// keep the config if its been set
|
||||
ILensHub(LENS_HUB).transferFromKeepingDelegates(address(this), destination, profileId);
|
||||
|
||||
return profileId;
|
||||
function createHandle(address to, string calldata handle) external payable returns (uint256) {
|
||||
if (msg.value != handleCreationCost) {
|
||||
revert InvalidFunds();
|
||||
}
|
||||
if (handle.length < 5) {
|
||||
revert();
|
||||
}
|
||||
return LENS_HANDLES.mintHandle(to, handle);
|
||||
}
|
||||
|
||||
function createProfileWithHandle(
|
||||
@@ -90,6 +89,18 @@ contract PermissonlessCreator is Ownable {
|
||||
return _createProfileWithHandle(createProfileParams, handle, delegatedExecutors);
|
||||
}
|
||||
|
||||
// Credit functions for apps
|
||||
|
||||
function createProfile_withCredit(
|
||||
Types.CreateProfileParams calldata createProfileParams,
|
||||
address[] calldata delegatedExecutors
|
||||
) external onlyCredit returns (uint256) {
|
||||
_checkAndRedeemCredit(msg.sender);
|
||||
uint256 profileId = _createProfile(createProfileParams, delegatedExecutors);
|
||||
profileCreatedOnlyByCredit[profileId] = msg.sender;
|
||||
return profileId;
|
||||
}
|
||||
|
||||
function createProfileWithHandleCredits(
|
||||
Types.CreateProfileParams calldata createProfileParams,
|
||||
string calldata handle,
|
||||
@@ -99,15 +110,6 @@ contract PermissonlessCreator is Ownable {
|
||||
return _createProfileWithHandle(createProfileParams, handle, delegatedExecutors);
|
||||
}
|
||||
|
||||
function createHandle(address to, string calldata handle) external payable returns (uint256) {
|
||||
if (msg.value != handleCreationCost) {
|
||||
revert InvalidFunds();
|
||||
}
|
||||
_validateHandleAvailable(handle);
|
||||
|
||||
return LENS_HANDLES.mintHandle(to, handle);
|
||||
}
|
||||
|
||||
// some credit addresses will be minting profiles before they have a handle so minting x amount of profiles.
|
||||
// This means onboarding they can mint the handle only and apply it to the profile to avoid the slow onboarding process
|
||||
function createHandleWithCredits(
|
||||
@@ -178,25 +180,53 @@ contract PermissonlessCreator is Ownable {
|
||||
return handleCreationCost;
|
||||
}
|
||||
|
||||
function _createProfile(
|
||||
Types.CreateProfileParams calldata createProfileParams,
|
||||
address[] calldata delegatedExecutors
|
||||
) internal returns (uint256) {
|
||||
uint256 profileId;
|
||||
if (delegatedExecutors.length == 0) {
|
||||
profileId = ILensHub(LENS_HUB).createProfile(createProfileParams);
|
||||
} else {
|
||||
// We mint the profile to this contract first, then apply delegates if defined
|
||||
// This will not allow to initialize follow modules that require funds from the msg.sender,
|
||||
// but we assume only simple follow modules should be set during profile creation.
|
||||
// Complex ones can be set after the profile is created.
|
||||
address destination = createProfileParams.to;
|
||||
|
||||
// Copy the struct from calldata to memory to make it mutable
|
||||
Types.CreateProfileParams memory createProfileParamsMemory = createProfileParams;
|
||||
createProfileParamsMemory.to = address(this);
|
||||
|
||||
profileId = ILensHub(LENS_HUB).createProfile(createProfileParamsMemory);
|
||||
|
||||
_addDelegatesToProfile(profileId, delegatedExecutors);
|
||||
|
||||
// keep the config if its been set
|
||||
ILensHub(LENS_HUB).transferFromKeepingDelegates(address(this), destination, profileId);
|
||||
}
|
||||
return profileId;
|
||||
}
|
||||
|
||||
function _createProfileWithHandle(
|
||||
Types.CreateProfileParams calldata createProfileParamsCalldata,
|
||||
Types.CreateProfileParams calldata createProfileParams,
|
||||
string calldata handle,
|
||||
address[] calldata delegatedExecutors
|
||||
) private returns (uint256 profileId, uint256 handleId) {
|
||||
_validateHandleAvailable(handle);
|
||||
|
||||
// Copy the struct from calldata to memory to make it mutable
|
||||
Types.CreateProfileParams memory createProfileParams = createProfileParamsCalldata;
|
||||
Types.CreateProfileParams memory createProfileParamsMemory = createProfileParams;
|
||||
|
||||
// We mint the handle & profile to this contract first, then link it to the profile and delegates if defined
|
||||
// This will not allow to initialize follow modules that require funds from the msg.sender,
|
||||
// but we assume only simple follow modules should be set during profile creation.
|
||||
// Complex ones can be set after the profile is created.
|
||||
address destination = createProfileParams.to;
|
||||
address destination = createProfileParamsMemory.to;
|
||||
|
||||
createProfileParams.to = address(this);
|
||||
createProfileParamsMemory.to = address(this);
|
||||
|
||||
uint256 _profileId = ILensHub(LENS_HUB).createProfile(createProfileParams);
|
||||
uint256 _profileId = ILensHub(LENS_HUB).createProfile(createProfileParamsMemory);
|
||||
uint256 _handleId = LENS_HANDLES.mintHandle(address(this), handle);
|
||||
|
||||
TOKEN_HANDLE_REGISTRY.link({handleId: _handleId, profileId: _profileId});
|
||||
@@ -211,15 +241,6 @@ contract PermissonlessCreator is Ownable {
|
||||
return (_profileId, _handleId);
|
||||
}
|
||||
|
||||
function _createProfile(Types.CreateProfileParams calldata createProfileParamsCalldata) private returns (uint256) {
|
||||
// Copy the struct from calldata to memory to make it mutable
|
||||
Types.CreateProfileParams memory createProfileParams = createProfileParamsCalldata;
|
||||
|
||||
createProfileParams.to = address(this);
|
||||
|
||||
return ILensHub(LENS_HUB).createProfile(createProfileParams);
|
||||
}
|
||||
|
||||
function _addDelegatesToProfile(uint256 profileId, address[] calldata delegatedExecutors) private {
|
||||
// set delegates if any
|
||||
if (delegatedExecutors.length > 0) {
|
||||
@@ -235,12 +256,6 @@ contract PermissonlessCreator is Ownable {
|
||||
}
|
||||
}
|
||||
|
||||
function _validateHandleAvailable(string calldata handle) private view {
|
||||
if (LENS_HANDLES.exists(uint256(keccak256(bytes(handle))))) {
|
||||
revert HandleAlreadyExists();
|
||||
}
|
||||
}
|
||||
|
||||
function _checkAndRedeemCredit(address from) private {
|
||||
if (credits[from] < 1) {
|
||||
revert InsufficientCredits();
|
||||
|
||||
Reference in New Issue
Block a user