From 20add176c8eb8abda68085f4e203653609f35473 Mon Sep 17 00:00:00 2001 From: Daniel Lima Date: Tue, 23 Apr 2024 16:53:44 -0300 Subject: [PATCH 1/8] ON-815: Direct Rentals --- contracts/NftRentalMarketplace.sol | 36 +++ .../libraries/LibNftRentalMarketplace.sol | 87 +++++++ test/NftRentalMarketplace.test.ts | 230 +++++++++++++++++- utils/types.ts | 10 + 4 files changed, 359 insertions(+), 4 deletions(-) diff --git a/contracts/NftRentalMarketplace.sol b/contracts/NftRentalMarketplace.sol index 464cfea..cf66c13 100644 --- a/contracts/NftRentalMarketplace.sol +++ b/contracts/NftRentalMarketplace.sol @@ -5,6 +5,7 @@ pragma solidity 0.8.9; import { IERC721 } from '@openzeppelin/contracts/token/ERC721/IERC721.sol'; import { IERC20 } from '@openzeppelin/contracts/token/ERC20/IERC20.sol'; import { IERC7432VaultExtension } from './interfaces/IERC7432VaultExtension.sol'; +import { IERC7432 } from './interfaces/IERC7432.sol'; import { ERC165Checker } from '@openzeppelin/contracts/utils/introspection/ERC165Checker.sol'; import { IOriumMarketplaceRoyalties } from './interfaces/IOriumMarketplaceRoyalties.sol'; import { OwnableUpgradeable } from '@openzeppelin/contracts-upgradeable/access/OwnableUpgradeable.sol'; @@ -240,6 +241,41 @@ contract NftRentalMarketplace is Initializable, OwnableUpgradeable, PausableUpgr emit RentalEnded(_offer.lender, _offer.nonce); } + /** + * @notice Withdraws the NFT from roles registry. + * @dev Can only be called by the token owner. + * @param _tokenAddresses The NFT tokenAddresses. + * @param _tokenIds The NFT tokenIds. + */ + function batchWithdraw( + address[] calldata _tokenAddresses, + uint256[] calldata _tokenIds + ) external whenNotPaused { + LibNftRentalMarketplace.batchWithdraw(oriumMarketplaceRoyalties, _tokenAddresses, _tokenIds); + } + + /** + * @notice batchGrantRole grant role in a single transaction. + * @param _params The array of role params. + */ + function batchGrantRole(IERC7432.Role[] calldata _params) external whenNotPaused { + LibNftRentalMarketplace.batchGrantRole(_params, oriumMarketplaceRoyalties); + } + + /** + * @notice batchRevokeRole revokes role in a single transaction. + * @dev owner will be msg.sender and it must approve the marketplace to revoke the roles. + * @param _tokenAddresses The array of tokenAddresses + * @param _tokenIds The array of tokenIds + */ + function batchRevokeRole( + address[] memory _tokenAddresses, + uint256[] memory _tokenIds, + bytes32[] memory _roleIds + ) external whenNotPaused { + LibNftRentalMarketplace.batchRevokeRole(_tokenAddresses, _tokenIds, _roleIds, oriumMarketplaceRoyalties); + } + /** ######### Internals ########### **/ /** diff --git a/contracts/libraries/LibNftRentalMarketplace.sol b/contracts/libraries/LibNftRentalMarketplace.sol index 9693189..0879386 100644 --- a/contracts/libraries/LibNftRentalMarketplace.sol +++ b/contracts/libraries/LibNftRentalMarketplace.sol @@ -270,4 +270,91 @@ library LibNftRentalMarketplace { IERC7432(_rolesRegsitry).revokeRole(_tokenAddress, _tokenId, _roleIds[i]); } } + + /** + * @notice Withdraws tokens from registry + * @dev Can only be called by the token owner. + * @param _oriumMarketplaceRoyaltiesAddress The address of the OriumMarketplaceRoyalties contract. + * @param _tokenAddresses The NFT tokenAddresses. + * @param _tokenIds The NFT tokenIds. + */ + function batchWithdraw( + address _oriumMarketplaceRoyaltiesAddress, + address[] calldata _tokenAddresses, + uint256[] calldata _tokenIds + ) external { + require(_tokenAddresses.length == _tokenIds.length, 'OriumNftMarketplace: arrays length mismatch'); + for (uint256 i = 0; i < _tokenAddresses.length; i++) { + address _rolesRegistry = IOriumMarketplaceRoyalties(_oriumMarketplaceRoyaltiesAddress).nftRolesRegistryOf( + _tokenAddresses[i] + ); + require( + msg.sender == IERC7432VaultExtension(_rolesRegistry).ownerOf(_tokenAddresses[i], _tokenIds[i]), + "OriumNftMarketplace: sender is not the token's owner" + ); + IERC7432VaultExtension(_rolesRegistry).withdraw(_tokenAddresses[i], _tokenIds[i]); + } + } + + /** + * @notice batchGrantRole grant role in a single transaction. + * @param _params The array of role params. + * @param _oriumMarketplaceRoyalties The Orium marketplace royalties contract address. + */ + function batchGrantRole(IERC7432.Role[] calldata _params, address _oriumMarketplaceRoyalties) external { + for (uint256 i = 0; i < _params.length; i++) { + address _rolesRegistry = IOriumMarketplaceRoyalties(_oriumMarketplaceRoyalties).nftRolesRegistryOf( + _params[i].tokenAddress + ); + require( + msg.sender == + IERC7432VaultExtension(_rolesRegistry).ownerOf(_params[i].tokenAddress, _params[i].tokenId) || + msg.sender == IERC721(_params[i].tokenAddress).ownerOf(_params[i].tokenId), + 'OriumNftMarketplace: sender is not the owner' + ); + + IERC7432(_rolesRegistry).grantRole(_params[i]); + } + } + + /** + * @notice batchRevokeRole revokes role in a single transaction. + * @dev only the owner and recipient can call this function. Be careful as the marketplace have approvals from other users. + * @param _tokenAddresses The array of tokenAddresses + * @param _tokenIds The array of tokenIds + * @param _roleIds The array of roleIds + * @param _oriumMarketplaceRoyalties The Orium marketplace royalties contract address. + */ + function batchRevokeRole( + address[] memory _tokenAddresses, + uint256[] memory _tokenIds, + bytes32[] memory _roleIds, + address _oriumMarketplaceRoyalties + ) external { + require( + _tokenIds.length == _tokenAddresses.length && _tokenIds.length == _roleIds.length, + 'OriumNftMarketplace: arrays length mismatch' + ); + + for (uint256 i = 0; i < _tokenIds.length; i++) { + address _rolesRegistry = IOriumMarketplaceRoyalties(_oriumMarketplaceRoyalties).nftRolesRegistryOf( + _tokenAddresses[i] + ); + require( + IERC7432(_rolesRegistry).isRoleRevocable(_tokenAddresses[i], _tokenIds[i], _roleIds[i]), + 'OriumNftMarketplace: role is not revocable' + ); + require( + IERC7432(_rolesRegistry).roleExpirationDate(_tokenAddresses[i], _tokenIds[i], _roleIds[i]) > + block.timestamp, + 'OriumNftMarketplace: role is expired' + ); + require( + msg.sender == IERC7432(_rolesRegistry).recipientOf(_tokenAddresses[i], _tokenIds[i], _roleIds[i]) || + msg.sender == IERC7432VaultExtension(_rolesRegistry).ownerOf(_tokenAddresses[i], _tokenIds[i]), + "OriumNftMarketplace: sender is not the token's owner or recipient" + ); + IERC7432(_rolesRegistry).revokeRole(_tokenAddresses[i], _tokenIds[i], _roleIds[i]); + } + } } diff --git a/test/NftRentalMarketplace.test.ts b/test/NftRentalMarketplace.test.ts index 5704896..e19a9c8 100644 --- a/test/NftRentalMarketplace.test.ts +++ b/test/NftRentalMarketplace.test.ts @@ -3,10 +3,10 @@ import { ethers } from 'hardhat' import { loadFixture, time } from '@nomicfoundation/hardhat-network-helpers' import { expect } from 'chai' import { toWei } from '../utils/bignumber' -import { RentalOffer, RoyaltyInfo } from '../utils/types' +import { GrantRoleParams, RentalOffer, RoyaltyInfo } from '../utils/types' import { AddressZero, EMPTY_BYTES, ONE_DAY, ONE_HOUR, THREE_MONTHS } from '../utils/constants' import { randomBytes } from 'crypto' -import { USER_ROLE } from '../utils/roles' +import { UNIQUE_ROLE, USER_ROLE } from '../utils/roles' import { MockERC20, MockERC721, @@ -500,7 +500,7 @@ describe('NftRentalMarketplace', () => { }) it("Should NOT cancel a rental offer after deadline's expiration", async () => { // move forward in time to expire the offer - const blockTimestamp = (await ethers.provider.getBlock('latest'))?.timestamp + const blockTimestamp = await time.latest() const timeToMove = rentalOffer.deadline - Number(blockTimestamp) + 1 await ethers.provider.send('evm_increaseTime', [timeToMove]) @@ -553,7 +553,7 @@ describe('NftRentalMarketplace', () => { }) it('Should NOT end a rental if rental is expired', async () => { // move foward in time to expire the offer - const blockTimestamp = (await ethers.provider.getBlock('latest'))?.timestamp + const blockTimestamp = await time.latest() const timeToMove = rentalOffer.deadline - Number(blockTimestamp) + 1 await ethers.provider.send('evm_increaseTime', [timeToMove]) @@ -592,6 +592,228 @@ describe('NftRentalMarketplace', () => { ) }) }) + + describe('Batch Withdraw Tokens', async () => { + it('Should withdraw tokens after rental is ended and rental offer expired', async () => { + await marketplace.connect(borrower).endRental(rentalOffer) + await time.increase(ONE_DAY) + await expect( + marketplace.connect(lender).batchWithdraw([rentalOffer.tokenAddress], [rentalOffer.tokenId]), + ) + .to.emit(mockERC721, 'Transfer') + .withArgs(await rolesRegistry.getAddress(), rentalOffer.lender, rentalOffer.tokenId) + }) + it('Should NOT withdraw tokens if contract is paused', async () => { + await marketplace.connect(operator).pause() + await expect( + marketplace.connect(lender).batchWithdraw([rentalOffer.tokenAddress], [rentalOffer.tokenId]), + ).to.be.revertedWith('Pausable: paused') + }) + it('Should NOT withdraw tokens if array mismatch', async () => { + await expect( + marketplace.connect(lender).batchWithdraw([rentalOffer.tokenAddress], []), + ).to.be.revertedWith('OriumNftMarketplace: arrays length mismatch') + }) + it('Should NOT withdraw tokens if sender is not the owner', async () => { + await expect( + marketplace.connect(borrower).batchWithdraw([rentalOffer.tokenAddress], [rentalOffer.tokenId]), + ).to.be.revertedWith("OriumNftMarketplace: sender is not the token's owner") + }) + }) + }) + }) + }) + + describe('Direct Rentals', async () => { + describe('When tokens are not deposited', async () => { + describe('batchGrantRole', async () => { + let grantRoleParams: GrantRoleParams[] + beforeEach(async () => { + grantRoleParams = [ + { + tokenAddress: await mockERC721.getAddress(), + tokenId, + roleId: UNIQUE_ROLE, + recipient: borrower.address, + expirationDate: Number(await time.latest()) + ONE_DAY, + revocable: true, + data: EMPTY_BYTES, + }, + ] + await rolesRegistry + .connect(lender) + .setRoleApprovalForAll(await mockERC721.getAddress(), await marketplace.getAddress(), true) + await mockERC721.connect(lender).setApprovalForAll(await rolesRegistry.getAddress(), true) + }) + it('Should deposit tokens and grant role', async () => { + await expect(marketplace.connect(lender).batchGrantRole(grantRoleParams)) + .to.emit(rolesRegistry, 'RoleGranted') + .withArgs( + grantRoleParams[0].tokenAddress, + grantRoleParams[0].tokenId, + grantRoleParams[0].roleId, + lender.address, + grantRoleParams[0].recipient, + grantRoleParams[0].expirationDate, + grantRoleParams[0].revocable, + grantRoleParams[0].data, + ) + }) + it('Should only grant role when a tokenId is passed', async () => { + await expect(marketplace.connect(lender).batchGrantRole(grantRoleParams)) + .to.emit(rolesRegistry, 'RoleGranted') + .withArgs( + grantRoleParams[0].tokenAddress, + grantRoleParams[0].tokenId, + grantRoleParams[0].roleId, + lender.address, + grantRoleParams[0].recipient, + grantRoleParams[0].expirationDate, + grantRoleParams[0].revocable, + grantRoleParams[0].data, + ) + }) + it('Should NOT deposit tokens and grant role if contract is paused', async () => { + await marketplace.connect(operator).pause() + await expect(marketplace.connect(lender).batchGrantRole(grantRoleParams)).to.be.revertedWith( + 'Pausable: paused', + ) + }) + it('Should NOT deposit tokens and grant role if caller is not the owner of the tokenId', async () => { + await expect(marketplace.connect(borrower).batchGrantRole(grantRoleParams)).to.revertedWith( + 'OriumNftMarketplace: sender is not the owner', + ) + }) + }) + }) + + describe('When tokens are deposited', async () => { + let grantRoleParams: GrantRoleParams[] + beforeEach(async () => { + grantRoleParams = [ + { + tokenAddress: await mockERC721.getAddress(), + tokenId, + roleId: UNIQUE_ROLE, + recipient: borrower.address, + expirationDate: Number(await time.latest()) + ONE_DAY, + revocable: true, + data: EMPTY_BYTES, + }, + ] + await rolesRegistry + .connect(lender) + .setRoleApprovalForAll(await mockERC721.getAddress(), await marketplace.getAddress(), true) + await mockERC721.connect(lender).setApprovalForAll(await rolesRegistry.getAddress(), true) + await marketplace.connect(lender).batchGrantRole(grantRoleParams) + }) + describe('batchGrantRole', async () => { + it('Should grant role', async () => { + await time.increase(ONE_DAY) + grantRoleParams[0].expirationDate = Number(await time.latest()) + ONE_DAY + await expect(marketplace.connect(lender).batchGrantRole(grantRoleParams)) + .to.emit(rolesRegistry, 'RoleGranted') + .withArgs( + grantRoleParams[0].tokenAddress, + grantRoleParams[0].tokenId, + grantRoleParams[0].roleId, + lender.address, + grantRoleParams[0].recipient, + grantRoleParams[0].expirationDate, + grantRoleParams[0].revocable, + grantRoleParams[0].data, + ) + }) + }) + describe('batchRevokeRole', async () => { + it('Should batch revoke role', async () => { + await expect( + marketplace + .connect(lender) + .batchRevokeRole( + [grantRoleParams[0].tokenAddress], + [grantRoleParams[0].tokenId], + [grantRoleParams[0].roleId], + ), + ) + .to.emit(rolesRegistry, 'RoleRevoked') + .withArgs(grantRoleParams[0].tokenAddress, grantRoleParams[0].tokenId, grantRoleParams[0].roleId) + }) + it('Should NOT batch revoke role if contract is paused', async () => { + await marketplace.connect(operator).pause() + await expect( + marketplace + .connect(lender) + .batchRevokeRole( + [grantRoleParams[0].tokenAddress], + [grantRoleParams[0].tokenId], + [grantRoleParams[0].roleId], + ), + ).to.be.revertedWith('Pausable: paused') + }) + it("Should NOT batch revoke role if array's length are different", async () => { + await expect( + marketplace + .connect(lender) + .batchRevokeRole( + [grantRoleParams[0].tokenAddress], + [grantRoleParams[0].tokenId], + [grantRoleParams[0].roleId, grantRoleParams[0].roleId], + ), + ).to.be.revertedWith('OriumNftMarketplace: arrays length mismatch') + }) + it("Should batch revoke role if sender is token's recipient", async () => { + await expect( + marketplace + .connect(borrower) + .batchRevokeRole( + [grantRoleParams[0].tokenAddress], + [grantRoleParams[0].tokenId], + [grantRoleParams[0].roleId], + ), + ) + .to.emit(rolesRegistry, 'RoleRevoked') + .withArgs(grantRoleParams[0].tokenAddress, grantRoleParams[0].tokenId, grantRoleParams[0].roleId) + }) + it("Should NOT batch revoke role if sender is not token's owner neither recipient", async () => { + await expect( + marketplace + .connect(notOperator) + .batchRevokeRole( + [grantRoleParams[0].tokenAddress], + [grantRoleParams[0].tokenId], + [grantRoleParams[0].roleId], + ), + ).to.be.revertedWith("OriumNftMarketplace: sender is not the token's owner or recipient") + }) + it('Should NOT batch revoke role if role is not revocable', async () => { + grantRoleParams[0].revocable = false + await rolesRegistry.connect(lender).grantRole(grantRoleParams[0]) + await rolesRegistry + .connect(borrower) + .setRoleApprovalForAll(await mockERC721.getAddress(), await marketplace.getAddress(), true) + await expect( + marketplace + .connect(lender) + .batchRevokeRole( + [grantRoleParams[0].tokenAddress], + [grantRoleParams[0].tokenId], + [grantRoleParams[0].roleId], + ), + ).to.be.revertedWith('OriumNftMarketplace: role is not revocable') + }) + it('Should NOT batch revoke role if role is expired', async () => { + await time.increase(ONE_DAY) + await expect( + marketplace + .connect(lender) + .batchRevokeRole( + [grantRoleParams[0].tokenAddress], + [grantRoleParams[0].tokenId], + [grantRoleParams[0].roleId], + ), + ).to.be.revertedWith('OriumNftMarketplace: role is expired') + }) }) }) }) diff --git a/utils/types.ts b/utils/types.ts index 2e436b9..03b3b90 100644 --- a/utils/types.ts +++ b/utils/types.ts @@ -49,3 +49,13 @@ export interface CommitAndGrantRoleParams { revocable: boolean data: string } + +export interface GrantRoleParams { + roleId: string + tokenAddress: string + tokenId: number + recipient: string + expirationDate: number + revocable: boolean + data: string +} From 5956482d732a70f32c192cdca0735e1d37dd75c3 Mon Sep 17 00:00:00 2001 From: Daniel Lima <38267570+karacurt@users.noreply.github.com> Date: Wed, 24 Apr 2024 13:19:52 -0300 Subject: [PATCH 2/8] Update contracts/NftRentalMarketplace.sol MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Ernani São Thiago --- contracts/NftRentalMarketplace.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/NftRentalMarketplace.sol b/contracts/NftRentalMarketplace.sol index cf66c13..6a95228 100644 --- a/contracts/NftRentalMarketplace.sol +++ b/contracts/NftRentalMarketplace.sol @@ -242,7 +242,7 @@ contract NftRentalMarketplace is Initializable, OwnableUpgradeable, PausableUpgr } /** - * @notice Withdraws the NFT from roles registry. + * @notice Withdraws NFTs from roles registry. * @dev Can only be called by the token owner. * @param _tokenAddresses The NFT tokenAddresses. * @param _tokenIds The NFT tokenIds. From 4aa2a0d7a7de43caed93a5e6517454c92eb8f4dd Mon Sep 17 00:00:00 2001 From: Daniel Lima <38267570+karacurt@users.noreply.github.com> Date: Wed, 24 Apr 2024 13:19:57 -0300 Subject: [PATCH 3/8] Update contracts/NftRentalMarketplace.sol MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Ernani São Thiago --- contracts/NftRentalMarketplace.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/NftRentalMarketplace.sol b/contracts/NftRentalMarketplace.sol index 6a95228..8c35216 100644 --- a/contracts/NftRentalMarketplace.sol +++ b/contracts/NftRentalMarketplace.sol @@ -255,7 +255,7 @@ contract NftRentalMarketplace is Initializable, OwnableUpgradeable, PausableUpgr } /** - * @notice batchGrantRole grant role in a single transaction. + * @notice Grants multiple roles. * @param _params The array of role params. */ function batchGrantRole(IERC7432.Role[] calldata _params) external whenNotPaused { From 8757e28c719b06ad9cd1eb9acf15dbe351ef1fb6 Mon Sep 17 00:00:00 2001 From: Daniel Lima <38267570+karacurt@users.noreply.github.com> Date: Wed, 24 Apr 2024 13:20:02 -0300 Subject: [PATCH 4/8] Update contracts/libraries/LibNftRentalMarketplace.sol MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Ernani São Thiago --- contracts/libraries/LibNftRentalMarketplace.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/libraries/LibNftRentalMarketplace.sol b/contracts/libraries/LibNftRentalMarketplace.sol index 0879386..bb9d644 100644 --- a/contracts/libraries/LibNftRentalMarketplace.sol +++ b/contracts/libraries/LibNftRentalMarketplace.sol @@ -297,7 +297,7 @@ library LibNftRentalMarketplace { } /** - * @notice batchGrantRole grant role in a single transaction. + * @notice Grants multiple roles. * @param _params The array of role params. * @param _oriumMarketplaceRoyalties The Orium marketplace royalties contract address. */ From 598b50d1e6ba49f140e61cbf476e5d46bfab56d7 Mon Sep 17 00:00:00 2001 From: Daniel Lima <38267570+karacurt@users.noreply.github.com> Date: Wed, 24 Apr 2024 13:20:08 -0300 Subject: [PATCH 5/8] Update contracts/NftRentalMarketplace.sol MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Ernani São Thiago --- contracts/NftRentalMarketplace.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/NftRentalMarketplace.sol b/contracts/NftRentalMarketplace.sol index 8c35216..880551b 100644 --- a/contracts/NftRentalMarketplace.sol +++ b/contracts/NftRentalMarketplace.sol @@ -263,7 +263,7 @@ contract NftRentalMarketplace is Initializable, OwnableUpgradeable, PausableUpgr } /** - * @notice batchRevokeRole revokes role in a single transaction. + * @notice Revokes multiple roles. * @dev owner will be msg.sender and it must approve the marketplace to revoke the roles. * @param _tokenAddresses The array of tokenAddresses * @param _tokenIds The array of tokenIds From d00979f7569bb2624e8392540ce9a7bd223bf62b Mon Sep 17 00:00:00 2001 From: Daniel Lima <38267570+karacurt@users.noreply.github.com> Date: Wed, 24 Apr 2024 13:20:14 -0300 Subject: [PATCH 6/8] Update contracts/libraries/LibNftRentalMarketplace.sol MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Ernani São Thiago --- contracts/libraries/LibNftRentalMarketplace.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/libraries/LibNftRentalMarketplace.sol b/contracts/libraries/LibNftRentalMarketplace.sol index bb9d644..c188b5a 100644 --- a/contracts/libraries/LibNftRentalMarketplace.sol +++ b/contracts/libraries/LibNftRentalMarketplace.sol @@ -318,7 +318,7 @@ library LibNftRentalMarketplace { } /** - * @notice batchRevokeRole revokes role in a single transaction. + * @notice Revokes multiple roles. * @dev only the owner and recipient can call this function. Be careful as the marketplace have approvals from other users. * @param _tokenAddresses The array of tokenAddresses * @param _tokenIds The array of tokenIds From 8989646d459ea6bf11087aa4ff2eb349f00ddb03 Mon Sep 17 00:00:00 2001 From: Daniel Lima <38267570+karacurt@users.noreply.github.com> Date: Wed, 24 Apr 2024 13:20:20 -0300 Subject: [PATCH 7/8] Update contracts/libraries/LibNftRentalMarketplace.sol MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Ernani São Thiago --- contracts/libraries/LibNftRentalMarketplace.sol | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/contracts/libraries/LibNftRentalMarketplace.sol b/contracts/libraries/LibNftRentalMarketplace.sol index c188b5a..8ffe7c3 100644 --- a/contracts/libraries/LibNftRentalMarketplace.sol +++ b/contracts/libraries/LibNftRentalMarketplace.sol @@ -319,7 +319,7 @@ library LibNftRentalMarketplace { /** * @notice Revokes multiple roles. - * @dev only the owner and recipient can call this function. Be careful as the marketplace have approvals from other users. + * @dev only the owner and recipient can call this function. Be careful as the marketplace receives role approvals from other users. * @param _tokenAddresses The array of tokenAddresses * @param _tokenIds The array of tokenIds * @param _roleIds The array of roleIds From f669f79179f3f481c99967afc011d18023bffc83 Mon Sep 17 00:00:00 2001 From: Daniel Lima Date: Wed, 24 Apr 2024 13:23:34 -0300 Subject: [PATCH 8/8] ON-815: PR fixes --- contracts/libraries/LibNftRentalMarketplace.sol | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/contracts/libraries/LibNftRentalMarketplace.sol b/contracts/libraries/LibNftRentalMarketplace.sol index 8ffe7c3..64df336 100644 --- a/contracts/libraries/LibNftRentalMarketplace.sol +++ b/contracts/libraries/LibNftRentalMarketplace.sol @@ -226,7 +226,7 @@ library LibNftRentalMarketplace { /** * @notice Validates the cancel rental offer params. * @dev This function is used to validate the cancel rental offer params. - * @param _isCreated Whether the offer is created + * @param _isCreated Whether the offer is created * @param _lender The lender address * @param _nonceDeadline The nonce deadline */ @@ -307,9 +307,9 @@ library LibNftRentalMarketplace { _params[i].tokenAddress ); require( - msg.sender == - IERC7432VaultExtension(_rolesRegistry).ownerOf(_params[i].tokenAddress, _params[i].tokenId) || - msg.sender == IERC721(_params[i].tokenAddress).ownerOf(_params[i].tokenId), + msg.sender == IERC721(_params[i].tokenAddress).ownerOf(_params[i].tokenId) || + msg.sender == + IERC7432VaultExtension(_rolesRegistry).ownerOf(_params[i].tokenAddress, _params[i].tokenId), 'OriumNftMarketplace: sender is not the owner' ); @@ -350,8 +350,8 @@ library LibNftRentalMarketplace { 'OriumNftMarketplace: role is expired' ); require( - msg.sender == IERC7432(_rolesRegistry).recipientOf(_tokenAddresses[i], _tokenIds[i], _roleIds[i]) || - msg.sender == IERC7432VaultExtension(_rolesRegistry).ownerOf(_tokenAddresses[i], _tokenIds[i]), + msg.sender == IERC7432VaultExtension(_rolesRegistry).ownerOf(_tokenAddresses[i], _tokenIds[i]) || + msg.sender == IERC7432(_rolesRegistry).recipientOf(_tokenAddresses[i], _tokenIds[i], _roleIds[i]), "OriumNftMarketplace: sender is not the token's owner or recipient" ); IERC7432(_rolesRegistry).revokeRole(_tokenAddresses[i], _tokenIds[i], _roleIds[i]);