Skip to content

Commit

Permalink
Merge pull request #1085 from thesandboxgame/task/add-trusted-forward…
Browse files Browse the repository at this point in the history
…er-operator-filter

Added trusted forwarder test cases for operator filter and royalties
  • Loading branch information
atkinsonholly authored Aug 9, 2023
2 parents fe14acc + 16c79fe commit 8ebe273
Show file tree
Hide file tree
Showing 18 changed files with 664 additions and 82 deletions.
185 changes: 179 additions & 6 deletions packages/asset/test/Asset.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import {
RoyaltyMultiRecipientsInterfaceId,
RoyaltyUGCInterfaceId,
} from './utils/interfaceIds';
import {BigNumber} from 'ethers';
const zeroAddress = '0x0000000000000000000000000000000000000000';

describe('Base Asset Contract (/packages/asset/contracts/Asset.sol)', function () {
Expand Down Expand Up @@ -1002,15 +1003,15 @@ describe('Base Asset Contract (/packages/asset/contracts/Asset.sol)', function (
const {
operatorFilterRegistry,
assetAdmin,
trustedForwarder,
TrustedForwarder,
filterOperatorSubscription,
RoyaltyManagerContract,
} = await setupOperatorFilter();
const AssetFactory = await ethers.getContractFactory('Asset');
const Asset = await upgrades.deployProxy(
AssetFactory,
[
trustedForwarder.address,
TrustedForwarder.address,
assetAdmin.address,
'ipfs://',
filterOperatorSubscription.address,
Expand Down Expand Up @@ -1045,15 +1046,15 @@ describe('Base Asset Contract (/packages/asset/contracts/Asset.sol)', function (
it('should revert when registry is set zero and subscription is set zero', async function () {
const {
assetAdmin,
trustedForwarder,
TrustedForwarder,
filterOperatorSubscription,
RoyaltyManagerContract,
} = await setupOperatorFilter();
const AssetFactory = await ethers.getContractFactory('Asset');
const Asset = await upgrades.deployProxy(
AssetFactory,
[
trustedForwarder.address,
TrustedForwarder.address,
assetAdmin.address,
'ipfs://',
filterOperatorSubscription.address,
Expand All @@ -1076,7 +1077,7 @@ describe('Base Asset Contract (/packages/asset/contracts/Asset.sol)', function (
it('should revert when registry is set and subscription is set by non-admin', async function () {
const {
assetAdmin,
trustedForwarder,
TrustedForwarder,
filterOperatorSubscription,
RoyaltyManagerContract,
operatorFilterRegistry,
Expand All @@ -1087,7 +1088,49 @@ describe('Base Asset Contract (/packages/asset/contracts/Asset.sol)', function (
const Asset = await upgrades.deployProxy(
AssetFactory,
[
trustedForwarder.address,
TrustedForwarder.address,
assetAdmin.address,
'ipfs://',
filterOperatorSubscription.address,
RoyaltyManagerContract.address,
],
{
initializer: 'initialize',
}
);

await expect(
Asset.connect(user1).setOperatorRegistry(
operatorFilterRegistry.address
)
).to.be.revertedWith(
`AccessControl: account ${user1.address.toLocaleLowerCase()} is missing role ${defaultAdminRole}`
);

await expect(
Asset.connect(user1).registerAndSubscribe(
filterOperatorSubscription.address,
true
)
).to.be.revertedWith(
`AccessControl: account ${user1.address.toLocaleLowerCase()} is missing role ${defaultAdminRole}`
);
});
it('should not revert when registry is set and subscription is set by admin through trusted forwarder', async function () {
const {
assetAdmin,
TrustedForwarder,
filterOperatorSubscription,
RoyaltyManagerContract,
operatorFilterRegistry,
defaultAdminRole,
user1,
} = await setupOperatorFilter();
const AssetFactory = await ethers.getContractFactory('Asset');
const Asset = await upgrades.deployProxy(
AssetFactory,
[
TrustedForwarder.address,
assetAdmin.address,
'ipfs://',
filterOperatorSubscription.address,
Expand Down Expand Up @@ -1651,6 +1694,30 @@ describe('Base Asset Contract (/packages/asset/contracts/Asset.sol)', function (
).to.be.revertedWith;
});

it('it should not be able to setApprovalForAll trusted forwarder if black listed', async function () {
const {
operatorFilterRegistryAsSubscription,
filterOperatorSubscription,
users,
TrustedForwarder,
} = await setupOperatorFilter();

const TrustedForwarderCodeHash =
await operatorFilterRegistryAsSubscription.codeHashOf(
TrustedForwarder.address
);

await operatorFilterRegistryAsSubscription.updateCodeHash(
filterOperatorSubscription.address,
TrustedForwarderCodeHash,
true
);

await expect(
users[1].Asset.setApprovalForAll(TrustedForwarder.address, true)
).to.be.revertedWithCustomError;
});

it('it should be able to setApprovalForAll blacklisted market places after they are removed from the blacklist ', async function () {
const {
mockMarketPlace1,
Expand Down Expand Up @@ -1755,6 +1822,54 @@ describe('Base Asset Contract (/packages/asset/contracts/Asset.sol)', function (
).to.be.revertedWithCustomError;
});

it('it should be able to transfer through trusted forwarder after it is blacklisted', async function () {
const {
Asset,
users,
operatorFilterRegistryAsSubscription,
filterOperatorSubscription,
TrustedForwarder,
} = await setupOperatorFilter();
await Asset.mintWithoutMinterRole(users[0].address, 1, 2);

await operatorFilterRegistryAsSubscription.updateOperator(
filterOperatorSubscription.address,
TrustedForwarder.address,
true
);

const data = await Asset.connect(
users[0].Asset.signer
).populateTransaction[
'safeTransferFrom(address,address,uint256,uint256,bytes)'
](users[0].address, users[1].address, 1, 1, '0x');

await TrustedForwarder.execute({...data, value: BigNumber.from(0)});

expect(await Asset.balanceOf(users[1].address, 1)).to.be.equal(1);
});

it('it should not be able to transfer through trusted forwarder after if sender is blacklisted', async function () {
const {Asset, users, TrustedForwarder, mockMarketPlace1} =
await setupOperatorFilter();
await Asset.mintWithoutMinterRole(users[0].address, 1, 2);

await users[0].Asset.setApprovalForAllWithoutFilter(
mockMarketPlace1.address,
true
);

const data = await Asset.connect(
ethers.provider.getSigner(mockMarketPlace1.address)
).populateTransaction[
'safeTransferFrom(address,address,uint256,uint256,bytes)'
](users[0].address, users[1].address, 1, 1, '0x');

await expect(
TrustedForwarder.execute({...data, value: BigNumber.from(0)})
).to.be.revertedWith('Call execution failed');
});

it('it should be able to transfer through non blacklisted market places', async function () {
const {mockMarketPlace3, Asset, users} = await setupOperatorFilter();
await Asset.mintWithoutMinterRole(users[0].address, 1, 1);
Expand Down Expand Up @@ -2068,6 +2183,64 @@ describe('Base Asset Contract (/packages/asset/contracts/Asset.sol)', function (
expect(await Asset.balanceOf(users[1].address, 1)).to.be.equal(1);
expect(await Asset.balanceOf(users[1].address, 2)).to.be.equal(1);
});
it('should be able to batch transfer through trusted forwarder if it is black listed', async function () {
const {
Asset,
users,
operatorFilterRegistryAsSubscription,
filterOperatorSubscription,
TrustedForwarder,
} = await setupOperatorFilter();
const TrustedForwarderCodeHash =
await operatorFilterRegistryAsSubscription.codeHashOf(
TrustedForwarder.address
);
await Asset.mintWithoutMinterRole(users[0].address, 1, 1);
await Asset.mintWithoutMinterRole(users[0].address, 2, 1);

await operatorFilterRegistryAsSubscription.updateCodeHash(
filterOperatorSubscription.address,
TrustedForwarderCodeHash,
true
);

await operatorFilterRegistryAsSubscription.updateOperator(
filterOperatorSubscription.address,
TrustedForwarder.address,
true
);
const data = await Asset.connect(
users[0].Asset.signer
).populateTransaction[
'safeBatchTransferFrom(address,address,uint256[],uint256[],bytes)'
](users[0].address, users[1].address, [1, 2], [1, 1], '0x');

await TrustedForwarder.execute({...data, value: BigNumber.from(0)});
expect(await Asset.balanceOf(users[1].address, 1)).to.be.equal(1);
expect(await Asset.balanceOf(users[1].address, 2)).to.be.equal(1);
});
it('should not be able to batch transfer through trusted forwarder if the sender is black listed', async function () {
const {Asset, users, TrustedForwarder, mockMarketPlace1} =
await setupOperatorFilter();

await Asset.mintWithoutMinterRole(users[0].address, 1, 1);
await Asset.mintWithoutMinterRole(users[0].address, 2, 1);

await users[0].Asset.setApprovalForAllWithoutFilter(
mockMarketPlace1.address,
true
);

const data = await Asset.connect(
ethers.provider.getSigner(mockMarketPlace1.address)
).populateTransaction[
'safeBatchTransferFrom(address,address,uint256[],uint256[],bytes)'
](users[0].address, users[1].address, [1, 2], [1, 1], '0x');

await expect(
TrustedForwarder.execute({...data, value: BigNumber.from(0)})
).to.be.revertedWith('Call execution failed');
});
});
});
});
78 changes: 78 additions & 0 deletions packages/asset/test/AssetRoyalty.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,84 @@ describe('Asset Royalties', function () {
);
});

it('should revert split ERC20 using EIP2981 using non trusted forwarder', async function () {
const {
Asset,
ERC20,
mockMarketplace,
ERC20AsBuyer,
seller,
buyer,
commonRoyaltyReceiver,
creator,
AssetAsSeller,
RoyaltyManagerContract,
assetAsMinter,
NonTrustedForwarder,
} = await assetRoyaltyDistribution();

const id = generateAssetId(creator.address, 1);
await assetAsMinter.mint(seller.address, id, 1, '0x');
await ERC20.mint(buyer.address, 1000000);
await ERC20AsBuyer.approve(mockMarketplace.address, 1000000);
await AssetAsSeller.setApprovalForAll(mockMarketplace.address, true);
expect(await Asset.balanceOf(seller.address, id)).to.be.equals(1);
await mockMarketplace.distributeRoyaltyEIP2981(
1000000,
ERC20.address,
Asset.address,
id,
buyer.address,
seller.address,
true
);
const splitter = await RoyaltyManagerContract._creatorRoyaltiesSplitter(
creator.address
);

const assetRoyaltyBPS = await RoyaltyManagerContract.getContractRoyalty(
Asset.address
);

const splitterContract = await ethers.getContractAt(
splitterAbi,
splitter
);

const balance = await ERC20.balanceOf(splitter);

expect(balance).to.be.equal(1000000 * (assetRoyaltyBPS / 10000));

const data = await splitterContract
.connect(creator.address)
.populateTransaction['splitERC20Tokens(address)'](ERC20.address);

await expect(
NonTrustedForwarder.execute({...data, value: BigNumber.from(0)})
).to.be.revertedWith('Call execution failed');

const balanceCreator = await ERC20.balanceOf(creator.address);
const balanceCommonRoyaltyReceiver = await ERC20.balanceOf(
commonRoyaltyReceiver.address
);

const newbalance = await ERC20.balanceOf(splitter);

expect(newbalance).to.be.equal(1000000 * (assetRoyaltyBPS / 10000));

expect(balanceCreator).to.be.equal(0);
expect(balanceCommonRoyaltyReceiver).to.be.equal(0);
});

it('should get trusted forwarder from Royalty Manager', async function () {
const {RoyaltyManagerContract, TrustedForwarder} =
await assetRoyaltyDistribution();

expect(await RoyaltyManagerContract.getTrustedForwarder()).to.be.equal(
TrustedForwarder.address
);
});

it('should split ERC20 using RoyaltyEngine', async function () {
const {
Asset,
Expand Down
Loading

1 comment on commit 8ebe273

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coverage for this commit

97.23%

Coverage Report
FileStmtsBranchesFuncsLinesUncovered Lines
packages/asset/contracts
   Asset.sol94.53%89.58%96.43%98.08%108, 193, 298, 298–299, 70
   AssetCreate.sol93.42%75%100%100%125, 127, 160, 266, 64
   AssetReveal.sol96.60%87.50%100%100%138, 170, 365, 406, 68
   AuthSuperValidator.sol100%100%100%100%
   Catalyst.sol94.81%91.94%95.24%98.08%133, 135, 148, 160, 231, 88
packages/asset/contracts/interfaces
   IAsset.sol100%100%100%100%
   IAssetCreate.sol100%100%100%100%
   IAssetReveal.sol100%100%100%100%
   ICatalyst.sol100%100%100%100%
   ITokenUtils.sol100%100%100%100%
packages/asset/contracts/libraries
   TokenIdUtils.sol100%100%100%100%
packages/dependency-metatx/contracts
   ERC2771Handler.sol100%100%100%100%
   ERC2771HandlerAbstract.sol100%100%100%100%
   ERC2771HandlerUpgradeable.sol95.45%83.33%100%100%43
packages/dependency-metatx/contracts/test
   ERC2771HandlerTest.sol100%100%100%100%
   ERC2771HandlerUpgradeableTest.sol100%100%100%100%
   MockTrustedForwarder.sol0%0%0%0%15, 18–19, 19, 19–20
packages/dependency-operator-filter/contracts
   OperatorFiltererUpgradeable.sol88.64%85%100%90%14, 48–49, 58–59
   OperatorFilterSubscription.sol60%50%100%50%18–19
packages/dependency-operator-filter/contracts/interfaces
   IOperatorFilterRegistry.sol100%100%100%100%
packages/dependency-royalty-management/contracts
   MultiRoyaltyDistributor.sol88.71%62.50%100%97.44%101, 108, 41, 41, 41, 41, 70
   RoyaltyDistributor.sol90.91%50%100%100%44
   RoyaltyManager.sol96%86.36%100%100%100, 44, 94
   RoyaltySplitter.sol90.91%75%92.31%95.89%107, 147, 167, 176, 191, 228, 56, 63, 78
packages/dependency-royalty-management/contracts/interfaces
   IERC20Approve.sol100%100%100%100%
   IMultiRoyaltyDistributor.sol100%100%100%100%
   IMultiRoyaltyRecipients.sol100%100%100%100%
   IRoyaltyManager.sol100%100%100%100%
   IRoyaltyUGC.sol100%100%100%100%

Please sign in to comment.