diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 03a228fb..3cbba972 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -52,7 +52,6 @@ jobs: - name: Install dependencies run: yarn install --frozen-lockfile --network-concurrency 1 - name: Run eslint - continue-on-error: true run: yarn run eslint solhint: name: Run solhint @@ -68,8 +67,23 @@ jobs: - name: Install dependencies run: yarn install --frozen-lockfile --network-concurrency 1 - name: Run solhint - continue-on-error: true run: yarn run solhint contracts/**/*.sol + slither: + name: Run slither + runs-on: ubuntu-latest + steps: + - name: Checkout Code + uses: actions/checkout@v3 + - name: Install Slither + run: sudo pip3 install slither-analyzer + - name: Show Slither Version + run: slither --version + - name: Install Foundry + uses: foundry-rs/foundry-toolchain@v1 + - name: Show Forge Version + run: forge --version + - name: Run slither + run: slither --compile-force-framework forge --foundry-out-directory foundry-out . publish: name: Publish to NPM (dry run) runs-on: ubuntu-latest diff --git a/BUILD.md b/BUILD.md new file mode 100644 index 00000000..d0cd156b --- /dev/null +++ b/BUILD.md @@ -0,0 +1,50 @@ +# Build and Test Information + +## Install + +Install dependencies: + +``` +yarn install +sudo pip3 install slither-analyzer +``` + +## Build and Test + +To build and test the contracts: + +``` +forge test -vvv +yarn test +``` + +## Solidity Linter + +To execute solhint: + +``` +yarn run solhint contracts/**/*.sol +``` + +To resolve formatting issues: + +``` +npx prettier --write --plugin=prettier-plugin-solidity 'contracts/**/*.sol' +``` + + +## Static Code Analysis + +To run slither: + +``` +slither --compile-force-framework forge --foundry-out-directory foundry-out . +``` + +## Test Coverage + +To check the test coverage based on Foundry tests use: + + ``` + forge coverage + ``` diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index dd63a037..56f50305 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -58,12 +58,19 @@ git pull upstream main git checkout -b ``` -6. Be sure to run the tests and set up the relevant linters to ensure all GitHub checks pass (see GitHub issues: https://docs.github.com/en/issues/tracking-your-work-with-issues/about-issues for more information). +6. Be sure to run the tests and set up the relevant linters to ensure all GitHub checks pass (see GitHub issues: https://docs.github.com/en/issues/tracking-your-work-with-issues/about-issues, and [build information](BUILD.md) for more information). New test code should use Foundry tests and not Hardhat. ``` +forge test -vvv yarn test ``` +Test coverage for all new code must be 100%. To check your test coverage: + + ``` + forge coverage + ``` + 7. Add and commit your changes, including a comprehensive commit message summarising your changes, then push changes to your fork. (e.g. Fixed formatting issue with ImmutableERC721MintByID.sol) ``` diff --git a/README.md b/README.md index edfcf85c..54ac15b5 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,8 @@ Immutable Contracts is a library of smart contracts targeted at developers who w - Smart Contract Wallets +- Random Number Generation + These contracts are feature-rich and are the recommended standard on Immutable zkEVM intended for all users and partners within the ecosystem. ## Setup @@ -77,6 +79,10 @@ const mintTransaction = await client.populateMint(receiver, 1); const tx = await signer.sendTransaction(mintTransaction); ``` +## Build and Test + +Information about how to build and test the contracts can be found in our [build information](BUILD.md). + ## Contribution We aim to build robust and feature-rich standards to help all developers onboard and build their projects on Immuable zkEVM, and we welcome any and all feedback and contributions to this repository! See our [contribution guideline](CONTRIBUTING.md) for more details on opening Github issues, pull requests requesting features, minor security vulnerabilities and providing general feedback. diff --git a/clients/erc20.ts b/clients/erc20.ts index 9eafe565..82ed985b 100644 --- a/clients/erc20.ts +++ b/clients/erc20.ts @@ -29,7 +29,7 @@ export class ERC20Client { public async balanceOf( provider: Provider, account: PromiseOrValue, - overrides: CallOverrides = {} + overrides: CallOverrides = {}, ): Promise { return this.contract.connect(provider).balanceOf(account, overrides); } @@ -41,7 +41,7 @@ export class ERC20Client { provider: Provider, owner: PromiseOrValue, spender: PromiseOrValue, - overrides: CallOverrides = {} + overrides: CallOverrides = {}, ): Promise { return this.contract.connect(provider).allowance(owner, spender, overrides); } @@ -52,7 +52,7 @@ export class ERC20Client { public async populateTransfer( to: PromiseOrValue, amount: PromiseOrValue, - overrides: Overrides & { from?: PromiseOrValue } = {} + overrides: Overrides & { from?: PromiseOrValue } = {}, ): Promise { return this.contract.populateTransaction.transfer(to, amount, { ...defaultGasOverrides, ...overrides }); } @@ -63,7 +63,7 @@ export class ERC20Client { public async populateApprove( spender: PromiseOrValue, amount: PromiseOrValue, - overrides: Overrides & { from?: PromiseOrValue } = {} + overrides: Overrides & { from?: PromiseOrValue } = {}, ): Promise { return this.contract.populateTransaction.approve(spender, amount, { ...defaultGasOverrides, ...overrides }); } @@ -75,7 +75,7 @@ export class ERC20Client { from: PromiseOrValue, to: PromiseOrValue, amount: PromiseOrValue, - overrides: Overrides & { from?: PromiseOrValue } = {} + overrides: Overrides & { from?: PromiseOrValue } = {}, ): Promise { return this.contract.populateTransaction.transferFrom(from, to, amount, { ...defaultGasOverrides, ...overrides }); } diff --git a/clients/erc721-mint-by-id.ts b/clients/erc721-mint-by-id.ts index 40b20eb8..0b8c7c84 100644 --- a/clients/erc721-mint-by-id.ts +++ b/clients/erc721-mint-by-id.ts @@ -50,7 +50,7 @@ export class ERC721MintByIDClient { public async balanceOf( provider: Provider, owner: PromiseOrValue, - overrides: CallOverrides = {} + overrides: CallOverrides = {}, ): Promise { return await this.contract.connect(provider).balanceOf(owner, overrides); } @@ -82,7 +82,7 @@ export class ERC721MintByIDClient { public async getApproved( provider: Provider, tokenId: PromiseOrValue, - overrides: CallOverrides = {} + overrides: CallOverrides = {}, ): Promise { return await this.contract.connect(provider).getApproved(tokenId, overrides); } @@ -93,7 +93,7 @@ export class ERC721MintByIDClient { public async getRoleAdmin( provider: Provider, role: PromiseOrValue, - overrides: CallOverrides = {} + overrides: CallOverrides = {}, ): Promise { return await this.contract.connect(provider).getRoleAdmin(role, overrides); } @@ -105,7 +105,7 @@ export class ERC721MintByIDClient { provider: Provider, role: PromiseOrValue, index: PromiseOrValue, - overrides: CallOverrides = {} + overrides: CallOverrides = {}, ): Promise { return await this.contract.connect(provider).getRoleMember(role, index, overrides); } @@ -116,7 +116,7 @@ export class ERC721MintByIDClient { public async getRoleMemberCount( provider: Provider, role: PromiseOrValue, - overrides: CallOverrides = {} + overrides: CallOverrides = {}, ): Promise { return await this.contract.connect(provider).getRoleMemberCount(role, overrides); } @@ -128,7 +128,7 @@ export class ERC721MintByIDClient { provider: Provider, role: PromiseOrValue, account: PromiseOrValue, - overrides: CallOverrides = {} + overrides: CallOverrides = {}, ): Promise { return await this.contract.connect(provider).hasRole(role, account, overrides); } @@ -140,7 +140,7 @@ export class ERC721MintByIDClient { provider: Provider, owner: PromiseOrValue, operator: PromiseOrValue, - overrides: CallOverrides = {} + overrides: CallOverrides = {}, ): Promise { return await this.contract.connect(provider).isApprovedForAll(owner, operator, overrides); } @@ -158,7 +158,7 @@ export class ERC721MintByIDClient { public async ownerOf( provider: Provider, tokenId: PromiseOrValue, - overrides: CallOverrides = {} + overrides: CallOverrides = {}, ): Promise { return await this.contract.connect(provider).ownerOf(tokenId, overrides); } @@ -171,7 +171,7 @@ export class ERC721MintByIDClient { public async nonces( provider: Provider, tokenId: PromiseOrValue, - overrides: CallOverrides = {} + overrides: CallOverrides = {}, ): Promise { return await this.contract.connect(provider).nonces(tokenId, overrides); } @@ -190,7 +190,7 @@ export class ERC721MintByIDClient { provider: Provider, _tokenId: PromiseOrValue, _salePrice: PromiseOrValue, - overrides: CallOverrides = {} + overrides: CallOverrides = {}, ): Promise<[string, BigNumber]> { return await this.contract.connect(provider).royaltyInfo(_tokenId, _salePrice, overrides); } @@ -208,7 +208,7 @@ export class ERC721MintByIDClient { public async tokenURI( provider: Provider, tokenId: PromiseOrValue, - overrides: CallOverrides = {} + overrides: CallOverrides = {}, ): Promise { return await this.contract.connect(provider).tokenURI(tokenId, overrides); } @@ -232,7 +232,7 @@ export class ERC721MintByIDClient { tokenId: PromiseOrValue, overrides: Overrides & { from?: PromiseOrValue; - } = {} + } = {}, ): Promise { return await this.contract.populateTransaction.approve(to, tokenId, { ...defaultGasOverrides, ...overrides }); } @@ -249,7 +249,7 @@ export class ERC721MintByIDClient { tokenId: PromiseOrValue, deadline: PromiseOrValue, sig: PromiseOrValue, - overrides: CallOverrides = {} + overrides: CallOverrides = {}, ): Promise { return await this.contract.populateTransaction.permit(spender, tokenId, deadline, sig, { ...defaultGasOverrides, @@ -264,7 +264,7 @@ export class ERC721MintByIDClient { tokenId: PromiseOrValue, overrides: Overrides & { from?: PromiseOrValue; - } = {} + } = {}, ): Promise { return await this.contract.populateTransaction.burn(tokenId, { ...defaultGasOverrides, ...overrides }); } @@ -276,7 +276,7 @@ export class ERC721MintByIDClient { tokenIds: PromiseOrValue[], overrides: Overrides & { from?: PromiseOrValue; - } = {} + } = {}, ): Promise { return await this.contract.populateTransaction.burnBatch(tokenIds, { ...defaultGasOverrides, ...overrides }); } @@ -288,7 +288,7 @@ export class ERC721MintByIDClient { user: PromiseOrValue, overrides: Overrides & { from?: PromiseOrValue; - } = {} + } = {}, ): Promise { return await this.contract.populateTransaction.grantMinterRole(user, { ...defaultGasOverrides, ...overrides }); } @@ -301,7 +301,7 @@ export class ERC721MintByIDClient { account: PromiseOrValue, overrides: Overrides & { from?: PromiseOrValue; - } = {} + } = {}, ): Promise { return await this.contract.populateTransaction.grantRole(role, account, { ...defaultGasOverrides, ...overrides }); } @@ -314,7 +314,7 @@ export class ERC721MintByIDClient { tokenId: PromiseOrValue, overrides: Overrides & { from?: PromiseOrValue; - } = {} + } = {}, ): Promise { return await this.contract.populateTransaction.mint(to, tokenId, { ...defaultGasOverrides, ...overrides }); } @@ -326,7 +326,7 @@ export class ERC721MintByIDClient { mints: IDMint[], overrides: Overrides & { from?: PromiseOrValue; - } = {} + } = {}, ): Promise { return await this.contract.populateTransaction.safeMintBatch(mints, { ...defaultGasOverrides, ...overrides }); } @@ -339,7 +339,7 @@ export class ERC721MintByIDClient { tokenId: PromiseOrValue, overrides: Overrides & { from?: PromiseOrValue; - } = {} + } = {}, ): Promise { return await this.contract.populateTransaction.safeBurn(owner, tokenId, { ...defaultGasOverrides, ...overrides }); } @@ -351,7 +351,7 @@ export class ERC721MintByIDClient { burns: IDBurn[], overrides: Overrides & { from?: PromiseOrValue; - } = {} + } = {}, ): Promise { return await this.contract.populateTransaction.safeBurnBatch(burns, { ...defaultGasOverrides, ...overrides }); } @@ -364,7 +364,7 @@ export class ERC721MintByIDClient { account: PromiseOrValue, overrides: Overrides & { from?: PromiseOrValue; - } = {} + } = {}, ): Promise { return await this.contract.populateTransaction.renounceRole(role, account, { ...defaultGasOverrides, @@ -379,7 +379,7 @@ export class ERC721MintByIDClient { user: PromiseOrValue, overrides: Overrides & { from?: PromiseOrValue; - } = {} + } = {}, ): Promise { return await this.contract.populateTransaction.revokeMinterRole(user, { ...defaultGasOverrides, ...overrides }); } @@ -392,7 +392,7 @@ export class ERC721MintByIDClient { account: PromiseOrValue, overrides: Overrides & { from?: PromiseOrValue; - } = {} + } = {}, ): Promise { return await this.contract.populateTransaction.revokeRole(role, account, { ...defaultGasOverrides, ...overrides }); } @@ -404,7 +404,7 @@ export class ERC721MintByIDClient { transfers: TransferRequest, overrides: Overrides & { from?: PromiseOrValue; - } = {} + } = {}, ): Promise { return await this.contract.populateTransaction.safeTransferFromBatch(transfers, { ...defaultGasOverrides, @@ -421,7 +421,7 @@ export class ERC721MintByIDClient { tokenId: PromiseOrValue, overrides: Overrides & { from?: PromiseOrValue; - } = {} + } = {}, ): Promise { return await this.contract.populateTransaction["safeTransferFrom(address,address,uint256)"](from, to, tokenId, { ...defaultGasOverrides, @@ -439,14 +439,14 @@ export class ERC721MintByIDClient { data: PromiseOrValue, overrides: Overrides & { from?: PromiseOrValue; - } = {} + } = {}, ): Promise { return await this.contract.populateTransaction["safeTransferFrom(address,address,uint256,bytes)"]( from, to, tokenId, data, - { ...defaultGasOverrides, ...overrides } + { ...defaultGasOverrides, ...overrides }, ); } @@ -458,7 +458,7 @@ export class ERC721MintByIDClient { approved: PromiseOrValue, overrides: Overrides & { from?: PromiseOrValue; - } = {} + } = {}, ): Promise { return await this.contract.populateTransaction.setApprovalForAll(operator, approved, { ...defaultGasOverrides, @@ -473,7 +473,7 @@ export class ERC721MintByIDClient { baseURI_: PromiseOrValue, overrides: Overrides & { from?: PromiseOrValue; - } = {} + } = {}, ): Promise { return await this.contract.populateTransaction.setBaseURI(baseURI_, { ...defaultGasOverrides, ...overrides }); } @@ -485,7 +485,7 @@ export class ERC721MintByIDClient { _contractURI: PromiseOrValue, overrides: Overrides & { from?: PromiseOrValue; - } = {} + } = {}, ): Promise { return await this.contract.populateTransaction.setContractURI(_contractURI, { ...defaultGasOverrides, @@ -501,7 +501,7 @@ export class ERC721MintByIDClient { feeNumerator: PromiseOrValue, overrides: Overrides & { from?: PromiseOrValue; - } = {} + } = {}, ): Promise { return await this.contract.populateTransaction.setDefaultRoyaltyReceiver(receiver, feeNumerator, { ...defaultGasOverrides, @@ -518,7 +518,7 @@ export class ERC721MintByIDClient { feeNumerator: PromiseOrValue, overrides: Overrides & { from?: PromiseOrValue; - } = {} + } = {}, ): Promise { return await this.contract.populateTransaction.setNFTRoyaltyReceiver(tokenId, receiver, feeNumerator, { ...defaultGasOverrides, @@ -535,7 +535,7 @@ export class ERC721MintByIDClient { feeNumerator: PromiseOrValue, overrides: Overrides & { from?: PromiseOrValue; - } = {} + } = {}, ): Promise { return await this.contract.populateTransaction.setNFTRoyaltyReceiverBatch(tokenIds, receiver, feeNumerator, { ...defaultGasOverrides, diff --git a/clients/erc721.ts b/clients/erc721.ts index 84557907..c7a0f24f 100644 --- a/clients/erc721.ts +++ b/clients/erc721.ts @@ -58,7 +58,7 @@ export class ERC721Client { public async balanceOf( provider: Provider, owner: PromiseOrValue, - overrides: CallOverrides = {} + overrides: CallOverrides = {}, ): Promise { return await this.contract.connect(provider).balanceOf(owner, overrides); } @@ -83,7 +83,7 @@ export class ERC721Client { */ public async eip712Domain( provider: Provider, - overrides: CallOverrides = {} + overrides: CallOverrides = {}, ): Promise< [string, string, string, BigNumber, string, string, BigNumber[]] & { fields: string; @@ -111,7 +111,7 @@ export class ERC721Client { public async getApproved( provider: Provider, tokenId: PromiseOrValue, - overrides: CallOverrides = {} + overrides: CallOverrides = {}, ): Promise { return await this.contract.connect(provider).getApproved(tokenId, overrides); } @@ -122,7 +122,7 @@ export class ERC721Client { public async getRoleAdmin( provider: Provider, role: PromiseOrValue, - overrides: CallOverrides = {} + overrides: CallOverrides = {}, ): Promise { return await this.contract.connect(provider).getRoleAdmin(role, overrides); } @@ -134,7 +134,7 @@ export class ERC721Client { provider: Provider, role: PromiseOrValue, index: PromiseOrValue, - overrides: CallOverrides = {} + overrides: CallOverrides = {}, ): Promise { return await this.contract.connect(provider).getRoleMember(role, index, overrides); } @@ -145,7 +145,7 @@ export class ERC721Client { public async getRoleMemberCount( provider: Provider, role: PromiseOrValue, - overrides: CallOverrides = {} + overrides: CallOverrides = {}, ): Promise { return await this.contract.connect(provider).getRoleMemberCount(role, overrides); } @@ -157,7 +157,7 @@ export class ERC721Client { provider: Provider, role: PromiseOrValue, account: PromiseOrValue, - overrides: CallOverrides = {} + overrides: CallOverrides = {}, ): Promise { return await this.contract.connect(provider).hasRole(role, account, overrides); } @@ -169,7 +169,7 @@ export class ERC721Client { provider: Provider, owner: PromiseOrValue, operator: PromiseOrValue, - overrides: CallOverrides = {} + overrides: CallOverrides = {}, ): Promise { return await this.contract.connect(provider).isApprovedForAll(owner, operator, overrides); } @@ -187,7 +187,7 @@ export class ERC721Client { public async ownerOf( provider: Provider, tokenId: PromiseOrValue, - overrides: CallOverrides = {} + overrides: CallOverrides = {}, ): Promise { return await this.contract.connect(provider).ownerOf(tokenId, overrides); } @@ -200,7 +200,7 @@ export class ERC721Client { public async nonces( provider: Provider, tokenId: PromiseOrValue, - overrides: CallOverrides = {} + overrides: CallOverrides = {}, ): Promise { return await this.contract.connect(provider).nonces(tokenId, overrides); } @@ -219,7 +219,7 @@ export class ERC721Client { provider: Provider, _tokenId: PromiseOrValue, _salePrice: PromiseOrValue, - overrides: CallOverrides = {} + overrides: CallOverrides = {}, ): Promise<[string, BigNumber]> { return await this.contract.connect(provider).royaltyInfo(_tokenId, _salePrice, overrides); } @@ -237,7 +237,7 @@ export class ERC721Client { public async tokenURI( provider: Provider, tokenId: PromiseOrValue, - overrides: CallOverrides = {} + overrides: CallOverrides = {}, ): Promise { return await this.contract.connect(provider).tokenURI(tokenId, overrides); } @@ -261,7 +261,7 @@ export class ERC721Client { tokenId: PromiseOrValue, overrides: Overrides & { from?: PromiseOrValue; - } = {} + } = {}, ): Promise { return await this.contract.populateTransaction.approve(to, tokenId, { ...defaultGasOverrides, ...overrides }); } @@ -278,7 +278,7 @@ export class ERC721Client { tokenId: PromiseOrValue, deadline: PromiseOrValue, sig: PromiseOrValue, - overrides: CallOverrides = {} + overrides: CallOverrides = {}, ): Promise { return await this.contract.populateTransaction.permit(spender, tokenId, deadline, sig, { ...defaultGasOverrides, @@ -293,7 +293,7 @@ export class ERC721Client { tokenId: PromiseOrValue, overrides: Overrides & { from?: PromiseOrValue; - } = {} + } = {}, ): Promise { return await this.contract.populateTransaction.burn(tokenId, { ...defaultGasOverrides, ...overrides }); } @@ -305,7 +305,7 @@ export class ERC721Client { tokenIds: PromiseOrValue[], overrides: Overrides & { from?: PromiseOrValue; - } = {} + } = {}, ): Promise { return await this.contract.populateTransaction.burnBatch(tokenIds, { ...defaultGasOverrides, ...overrides }); } @@ -318,7 +318,7 @@ export class ERC721Client { tokenId: PromiseOrValue, overrides: Overrides & { from?: PromiseOrValue; - } = {} + } = {}, ): Promise { return await this.contract.populateTransaction.safeBurn(owner, tokenId, { ...defaultGasOverrides, ...overrides }); } @@ -330,7 +330,7 @@ export class ERC721Client { burns: IDBurn[], overrides: Overrides & { from?: PromiseOrValue; - } = {} + } = {}, ): Promise { return await this.contract.populateTransaction.safeBurnBatch(burns, { ...defaultGasOverrides, ...overrides }); } @@ -342,7 +342,7 @@ export class ERC721Client { user: PromiseOrValue, overrides: Overrides & { from?: PromiseOrValue; - } = {} + } = {}, ): Promise { return await this.contract.populateTransaction.grantMinterRole(user, { ...defaultGasOverrides, ...overrides }); } @@ -355,7 +355,7 @@ export class ERC721Client { account: PromiseOrValue, overrides: Overrides & { from?: PromiseOrValue; - } = {} + } = {}, ): Promise { return await this.contract.populateTransaction.grantRole(role, account, { ...defaultGasOverrides, ...overrides }); } @@ -368,7 +368,7 @@ export class ERC721Client { tokenId: PromiseOrValue, overrides: Overrides & { from?: PromiseOrValue; - } = {} + } = {}, ): Promise { return await this.contract.populateTransaction.mint(to, tokenId, { ...defaultGasOverrides, ...overrides }); } @@ -381,7 +381,7 @@ export class ERC721Client { tokenId: PromiseOrValue, overrides: Overrides & { from?: PromiseOrValue; - } = {} + } = {}, ): Promise { return await this.contract.populateTransaction.safeMint(to, tokenId, { ...defaultGasOverrides, ...overrides }); } @@ -394,7 +394,7 @@ export class ERC721Client { quantity: PromiseOrValue, overrides: Overrides & { from?: PromiseOrValue; - } = {} + } = {}, ): Promise { return await this.contract.populateTransaction.mintByQuantity(to, quantity, { ...defaultGasOverrides, @@ -410,7 +410,7 @@ export class ERC721Client { quantity: PromiseOrValue, overrides: Overrides & { from?: PromiseOrValue; - } = {} + } = {}, ): Promise { return await this.contract.populateTransaction.safeMintByQuantity(to, quantity, { ...defaultGasOverrides, @@ -425,7 +425,7 @@ export class ERC721Client { mints: Mint[], overrides: Overrides & { from?: PromiseOrValue; - } = {} + } = {}, ): Promise { return await this.contract.populateTransaction.mintBatchByQuantity(mints, { ...defaultGasOverrides, ...overrides }); } @@ -437,7 +437,7 @@ export class ERC721Client { mints: Mint[], overrides: Overrides & { from?: PromiseOrValue; - } = {} + } = {}, ): Promise { return await this.contract.populateTransaction.safeMintBatchByQuantity(mints, { ...defaultGasOverrides, @@ -452,7 +452,7 @@ export class ERC721Client { mints: IDMint[], overrides: Overrides & { from?: PromiseOrValue; - } = {} + } = {}, ): Promise { return await this.contract.populateTransaction.mintBatch(mints, { ...defaultGasOverrides, ...overrides }); } @@ -464,7 +464,7 @@ export class ERC721Client { mints: IDMint[], overrides: Overrides & { from?: PromiseOrValue; - } = {} + } = {}, ): Promise { return await this.contract.populateTransaction.safeMintBatch(mints, { ...defaultGasOverrides, ...overrides }); } @@ -477,7 +477,7 @@ export class ERC721Client { account: PromiseOrValue, overrides: Overrides & { from?: PromiseOrValue; - } = {} + } = {}, ): Promise { return await this.contract.populateTransaction.renounceRole(role, account, { ...defaultGasOverrides, @@ -492,7 +492,7 @@ export class ERC721Client { user: PromiseOrValue, overrides: Overrides & { from?: PromiseOrValue; - } = {} + } = {}, ): Promise { return await this.contract.populateTransaction.revokeMinterRole(user, { ...defaultGasOverrides, ...overrides }); } @@ -505,7 +505,7 @@ export class ERC721Client { account: PromiseOrValue, overrides: Overrides & { from?: PromiseOrValue; - } = {} + } = {}, ): Promise { return await this.contract.populateTransaction.revokeRole(role, account, { ...defaultGasOverrides, ...overrides }); } @@ -517,7 +517,7 @@ export class ERC721Client { transfers: TransferRequest, overrides: Overrides & { from?: PromiseOrValue; - } = {} + } = {}, ): Promise { return await this.contract.populateTransaction.safeTransferFromBatch(transfers, { ...defaultGasOverrides, @@ -534,7 +534,7 @@ export class ERC721Client { tokenId: PromiseOrValue, overrides: Overrides & { from?: PromiseOrValue; - } = {} + } = {}, ): Promise { return await this.contract.populateTransaction["safeTransferFrom(address,address,uint256)"](from, to, tokenId, { ...defaultGasOverrides, @@ -552,14 +552,14 @@ export class ERC721Client { data: PromiseOrValue, overrides: Overrides & { from?: PromiseOrValue; - } = {} + } = {}, ): Promise { return await this.contract.populateTransaction["safeTransferFrom(address,address,uint256,bytes)"]( from, to, tokenId, data, - { ...defaultGasOverrides, ...overrides } + { ...defaultGasOverrides, ...overrides }, ); } @@ -571,7 +571,7 @@ export class ERC721Client { approved: PromiseOrValue, overrides: Overrides & { from?: PromiseOrValue; - } = {} + } = {}, ): Promise { return await this.contract.populateTransaction.setApprovalForAll(operator, approved, { ...defaultGasOverrides, @@ -586,7 +586,7 @@ export class ERC721Client { baseURI_: PromiseOrValue, overrides: Overrides & { from?: PromiseOrValue; - } = {} + } = {}, ): Promise { return await this.contract.populateTransaction.setBaseURI(baseURI_, { ...defaultGasOverrides, ...overrides }); } @@ -598,7 +598,7 @@ export class ERC721Client { _contractURI: PromiseOrValue, overrides: Overrides & { from?: PromiseOrValue; - } = {} + } = {}, ): Promise { return await this.contract.populateTransaction.setContractURI(_contractURI, { ...defaultGasOverrides, @@ -614,7 +614,7 @@ export class ERC721Client { feeNumerator: PromiseOrValue, overrides: Overrides & { from?: PromiseOrValue; - } = {} + } = {}, ): Promise { return await this.contract.populateTransaction.setDefaultRoyaltyReceiver(receiver, feeNumerator, { ...defaultGasOverrides, @@ -631,7 +631,7 @@ export class ERC721Client { feeNumerator: PromiseOrValue, overrides: Overrides & { from?: PromiseOrValue; - } = {} + } = {}, ): Promise { return await this.contract.populateTransaction.setNFTRoyaltyReceiver(tokenId, receiver, feeNumerator, { ...defaultGasOverrides, @@ -648,7 +648,7 @@ export class ERC721Client { feeNumerator: PromiseOrValue, overrides: Overrides & { from?: PromiseOrValue; - } = {} + } = {}, ): Promise { return await this.contract.populateTransaction.setNFTRoyaltyReceiverBatch(tokenIds, receiver, feeNumerator, { ...defaultGasOverrides, diff --git a/contracts/access/IERC173.sol b/contracts/access/IERC173.sol index d07301a1..373d9bec 100644 --- a/contracts/access/IERC173.sol +++ b/contracts/access/IERC173.sol @@ -1,7 +1,8 @@ //SPDX-License-Identifier: Apache 2.0 +// solhint-disable compiler-version pragma solidity ^0.8.0; -import "@openzeppelin/contracts/utils/introspection/ERC165.sol"; +import {IERC165} from "@openzeppelin/contracts/utils/introspection/ERC165.sol"; interface IERC173 is IERC165 { /// @dev This emits when ownership of a contract changes. diff --git a/contracts/allowlist/IWalletProxy.sol b/contracts/allowlist/IWalletProxy.sol index 087d906b..c4c1b20e 100644 --- a/contracts/allowlist/IWalletProxy.sol +++ b/contracts/allowlist/IWalletProxy.sol @@ -6,6 +6,6 @@ pragma solidity 0.8.19; /// Interface for Passport Wallet's proxy contract. interface IWalletProxy { // Returns the current implementation address used by the proxy contract - // solhint-disable-next-line var-name-mixedcase + // solhint-disable-next-line func-name-mixedcase function PROXY_getImplementation() external view returns (address); } diff --git a/contracts/allowlist/OperatorAllowlistEnforced.sol b/contracts/allowlist/OperatorAllowlistEnforced.sol index 344d7d11..dc31fe0b 100644 --- a/contracts/allowlist/OperatorAllowlistEnforced.sol +++ b/contracts/allowlist/OperatorAllowlistEnforced.sol @@ -1,5 +1,6 @@ // Copyright Immutable Pty Ltd 2018 - 2023 // SPDX-License-Identifier: Apache 2.0 +// slither-disable-start calls-loop pragma solidity 0.8.19; // Allowlist Registry @@ -108,3 +109,4 @@ abstract contract OperatorAllowlistEnforced is AccessControlEnumerable, Operator operatorAllowlist = IOperatorAllowlist(_operatorAllowlist); } } +// slither-disable-end calls-loop diff --git a/contracts/allowlist/OperatorAllowlistUpgradeable.sol b/contracts/allowlist/OperatorAllowlistUpgradeable.sol index 39cc705f..af397f25 100644 --- a/contracts/allowlist/OperatorAllowlistUpgradeable.sol +++ b/contracts/allowlist/OperatorAllowlistUpgradeable.sol @@ -40,13 +40,13 @@ contract OperatorAllowlistUpgradeable is bytes32 public constant UPGRADE_ROLE = bytes32("UPGRADE_ROLE"); /// @notice Mapping of Allowlisted addresses - mapping(address => bool) private addressAllowlist; + mapping(address aContract => bool allowed) private addressAllowlist; /// @notice Mapping of Allowlisted implementation addresses - mapping(address => bool) private addressImplementationAllowlist; + mapping(address impl => bool allowed) private addressImplementationAllowlist; /// @notice Mapping of Allowlisted bytecodes - mapping(bytes32 => bool) private bytecodeAllowlist; + mapping(bytes32 bytecodeHash => bool allowed) private bytecodeAllowlist; /// ===== Initializer ===== @@ -82,6 +82,7 @@ contract OperatorAllowlistUpgradeable is */ function removeAddressesFromAllowlist(address[] calldata addressTargets) external onlyRole(REGISTRAR_ROLE) { for (uint256 i; i < addressTargets.length; i++) { + // slither-disable-next-line costly-loop delete addressAllowlist[addressTargets[i]]; emit AddressAllowlistChanged(addressTargets[i], false); } @@ -98,6 +99,7 @@ contract OperatorAllowlistUpgradeable is function addWalletToAllowlist(address walletAddr) external onlyRole(REGISTRAR_ROLE) { // get bytecode of wallet bytes32 codeHash; + // solhint-disable-next-line no-inline-assembly assembly { codeHash := extcodehash(walletAddr) } @@ -117,6 +119,7 @@ contract OperatorAllowlistUpgradeable is function removeWalletFromAllowlist(address walletAddr) external onlyRole(REGISTRAR_ROLE) { // get bytecode of wallet bytes32 codeHash; + // solhint-disable-next-line no-inline-assembly assembly { codeHash := extcodehash(walletAddr) } @@ -141,6 +144,7 @@ contract OperatorAllowlistUpgradeable is // Check if caller is a Allowlisted smart contract wallet bytes32 codeHash; + // solhint-disable-next-line no-inline-assembly assembly { codeHash := extcodehash(target) } @@ -165,8 +169,12 @@ contract OperatorAllowlistUpgradeable is } // Override the _authorizeUpgrade function + // solhint-disable-next-line no-empty-blocks function _authorizeUpgrade(address newImplementation) internal override onlyRole(UPGRADE_ROLE) {} /// @notice storage gap for additional variables for upgrades - uint256[20] __OperatorAllowlistUpgradeableGap; + // slither-disable-start unused-state + // solhint-disable-next-line var-name-mixedcase + uint256[20] private __OperatorAllowlistUpgradeableGap; + // slither-disable-end unused-state } diff --git a/contracts/bridge/x/Core.sol b/contracts/bridge/x/Core.sol index 85cacf62..e936afee 100644 --- a/contracts/bridge/x/Core.sol +++ b/contracts/bridge/x/Core.sol @@ -1,8 +1,8 @@ // SPDX-License-Identifier: MIT +// solhint-disable compiler-version pragma solidity ^0.8.11; interface Core { - function announceAvailabilityVerifierRemovalIntent(address) external; function announceVerifierRemovalIntent(address) external; function getRegisteredAvailabilityVerifiers() external; @@ -84,12 +84,7 @@ interface Core { uint256 vaultId ) external view returns (uint256 balance); - function depositNft( - uint256 starkKey, - uint256 assetType, - uint256 vaultId, - uint256 tokenId - ) external; + function depositNft(uint256 starkKey, uint256 assetType, uint256 vaultId, uint256 tokenId) external; function getCancellationRequest( uint256 starkKey, @@ -97,50 +92,19 @@ interface Core { uint256 vaultId ) external view returns (uint256 request); - function depositERC20( - uint256 starkKey, - uint256 assetType, - uint256 vaultId, - uint256 quantizedAmount - ) external; + function depositERC20(uint256 starkKey, uint256 assetType, uint256 vaultId, uint256 quantizedAmount) external; - function depositEth( - uint256 starkKey, - uint256 assetType, - uint256 vaultId - ) external payable; + function depositEth(uint256 starkKey, uint256 assetType, uint256 vaultId) external payable; - function deposit( - uint256 starkKey, - uint256 assetType, - uint256 vaultId, - uint256 quantizedAmount - ) external; + function deposit(uint256 starkKey, uint256 assetType, uint256 vaultId, uint256 quantizedAmount) external; - function deposit( - uint256 starkKey, - uint256 assetType, - uint256 vaultId - ) external payable; + function deposit(uint256 starkKey, uint256 assetType, uint256 vaultId) external payable; - function depositCancel( - uint256 starkKey, - uint256 assetId, - uint256 vaultId - ) external; + function depositCancel(uint256 starkKey, uint256 assetId, uint256 vaultId) external; - function depositReclaim( - uint256 starkKey, - uint256 assetId, - uint256 vaultId - ) external; + function depositReclaim(uint256 starkKey, uint256 assetId, uint256 vaultId) external; - function depositNftReclaim( - uint256 starkKey, - uint256 assetType, - uint256 vaultId, - uint256 tokenId - ) external; + function depositNftReclaim(uint256 starkKey, uint256 assetType, uint256 vaultId, uint256 tokenId) external; event LogWithdrawalPerformed( uint256 ownerKey, @@ -177,24 +141,13 @@ interface Core { event LogMintableWithdrawalAllowed(uint256 ownerKey, uint256 assetId, uint256 quantizedAmount); - function getWithdrawalBalance(uint256 ownerKey, uint256 assetId) - external - view - returns (uint256 balance); + function getWithdrawalBalance(uint256 ownerKey, uint256 assetId) external view returns (uint256 balance); function withdraw(uint256 ownerKey, uint256 assetType) external; - function withdrawNft( - uint256 ownerKey, - uint256 assetType, - uint256 tokenId - ) external ; + function withdrawNft(uint256 ownerKey, uint256 assetType, uint256 tokenId) external; - function withdrawAndMint( - uint256 ownerKey, - uint256 assetType, - bytes calldata mintingBlob - ) external; + function withdrawAndMint(uint256 ownerKey, uint256 assetType, bytes calldata mintingBlob) external; function getVaultRoot() external view returns (uint256 root); function getVaultTreeHeight() external view returns (uint256 height); @@ -224,12 +177,7 @@ interface Core { function getQuantum(uint256 presumedAssetType) external view returns (uint256 quantum); - function escape( - uint256 starkKey, - uint256 vaultId, - uint256 assetId, - uint256 quantizedAmount - ) external; + function escape(uint256 starkKey, uint256 vaultId, uint256 assetId, uint256 quantizedAmount) external; event LogFullWithdrawalRequest(uint256 starkKey, uint256 vaultId); @@ -237,26 +185,13 @@ interface Core { function freezeRequest(uint256 starkKey, uint256 vaultId) external; - event LogRootUpdate( - uint256 sequenceNumber, - uint256 batchId, - uint256 vaultRoot, - uint256 orderRoot - ); + event LogRootUpdate(uint256 sequenceNumber, uint256 batchId, uint256 vaultRoot, uint256 orderRoot); event LogStateTransitionFact(bytes32 stateTransitionFact); - event LogVaultBalanceChangeApplied( - address ethKey, - uint256 assetId, - uint256 vaultId, - int256 quantizedAmountChange - ); + event LogVaultBalanceChangeApplied(address ethKey, uint256 assetId, uint256 vaultId, int256 quantizedAmountChange); function updateState(uint256[] calldata publicInput, uint256[] calldata applicationData) external; - function getFullWithdrawalRequest(uint256 starkKey, uint256 vaultId) - external - view - returns (uint256 res); -} \ No newline at end of file + function getFullWithdrawalRequest(uint256 starkKey, uint256 vaultId) external view returns (uint256 res); +} diff --git a/contracts/bridge/x/Registration.sol b/contracts/bridge/x/Registration.sol index 70b0c2ee..52cd0fb2 100644 --- a/contracts/bridge/x/Registration.sol +++ b/contracts/bridge/x/Registration.sol @@ -1,10 +1,11 @@ // SPDX-License-Identifier: MIT +// solhint-disable compiler-version pragma solidity ^0.8.11; -import { Core } from "./Core.sol"; +import {Core} from "./Core.sol"; contract Registration { - Core public imx; + Core public immutable imx; constructor(Core _imx) { imx = _imx; @@ -80,4 +81,4 @@ contract Registration { function isRegistered(uint256 starkKey) public view returns (bool) { return imx.getEthKey(starkKey) != address(0); } -} \ No newline at end of file +} diff --git a/contracts/mocks/MockDisguisedEOA.sol b/contracts/mocks/MockDisguisedEOA.sol index 3056b1ba..eeff046b 100644 --- a/contracts/mocks/MockDisguisedEOA.sol +++ b/contracts/mocks/MockDisguisedEOA.sol @@ -1,16 +1,21 @@ -pragma solidity ^0.8.0; +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; -import "@openzeppelin/contracts/token/ERC721/IERC721.sol"; +import {IERC721} from "@openzeppelin/contracts/token/ERC721/IERC721.sol"; // Used in CREATE2 vector contract MockDisguisedEOA { - IERC721 public tokenAddress; + IERC721 public immutable tokenAddress; constructor(IERC721 _tokenAddress) { tokenAddress = _tokenAddress; } + /// @notice This code is only for testing purposes. Do not use similar + /// @notice constructions in production code as they are open to attack. + /// @dev For details see: https://github.com/crytic/slither/wiki/Detector-Documentation#arbitrary-from-in-transferfrom function executeTransfer(address from, address recipient, uint256 _tokenId) external { + // slither-disable-next-line arbitrary-send-erc20 tokenAddress.transferFrom(from, recipient, _tokenId); } } diff --git a/contracts/mocks/MockEIP1271Wallet.sol b/contracts/mocks/MockEIP1271Wallet.sol index 8e12269d..65824c99 100644 --- a/contracts/mocks/MockEIP1271Wallet.sol +++ b/contracts/mocks/MockEIP1271Wallet.sol @@ -1,12 +1,14 @@ -pragma solidity ^0.8.0; +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; -import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; -import "@openzeppelin/contracts/interfaces/IERC1271.sol"; +import {ECDSA} from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; +import {IERC1271} from "@openzeppelin/contracts/interfaces/IERC1271.sol"; contract MockEIP1271Wallet is IERC1271 { - address public owner; + address public immutable owner; constructor(address _owner) { + // slither-disable-next-line missing-zero-check owner = _owner; } diff --git a/contracts/mocks/MockFactory.sol b/contracts/mocks/MockFactory.sol index 854b2f73..67858771 100644 --- a/contracts/mocks/MockFactory.sol +++ b/contracts/mocks/MockFactory.sol @@ -1,4 +1,5 @@ -pragma solidity ^0.8.0; +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; import {Create2} from "@openzeppelin/contracts/utils/Create2.sol"; @@ -8,6 +9,7 @@ contract MockFactory { } function deploy(bytes32 salt, bytes memory code) public { + // slither-disable-next-line unused-return Create2.deploy(0, salt, code); } } diff --git a/contracts/mocks/MockMarketplace.sol b/contracts/mocks/MockMarketplace.sol index cf7cb981..545a89c8 100644 --- a/contracts/mocks/MockMarketplace.sol +++ b/contracts/mocks/MockMarketplace.sol @@ -1,11 +1,14 @@ -pragma solidity ^0.8.0; +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; -import "@openzeppelin/contracts/token/ERC721/IERC721.sol"; -import "@openzeppelin/contracts/interfaces/IERC2981.sol"; +import {IERC721} from "@openzeppelin/contracts/token/ERC721/IERC721.sol"; +import {IERC2981} from "@openzeppelin/contracts/interfaces/IERC2981.sol"; contract MockMarketplace { - IERC721 public tokenAddress; - IERC2981 public royaltyAddress; + error ZeroAddress(); + + IERC721 public immutable tokenAddress; + IERC2981 public immutable royaltyAddress; constructor(address _tokenAddress) { tokenAddress = IERC721(_tokenAddress); @@ -16,7 +19,11 @@ contract MockMarketplace { tokenAddress.transferFrom(msg.sender, recipient, _tokenId); } + /// @notice This code is only for testing purposes. Do not use similar + /// @notice constructions in production code as they are open to attack. + /// @dev For details see: https://github.com/crytic/slither/wiki/Detector-Documentation#arbitrary-from-in-transferfrom function executeTransferFrom(address from, address to, uint256 _tokenId) public { + // slither-disable-next-line arbitrary-send-erc20 tokenAddress.transferFrom(from, to, _tokenId); } @@ -24,12 +31,23 @@ contract MockMarketplace { tokenAddress.setApprovalForAll(operator, approved); } + /// @notice This code is only for testing purposes. Do not use similar + /// @notice constructions in production code as they are open to attack. + /// @dev For details see: https://github.com/crytic/slither/wiki/Detector-Documentation#arbitrary-from-in-transferfrom function executeTransferRoyalties(address from, address recipient, uint256 _tokenId, uint256 price) public payable { + if (from == address(0)) { + revert ZeroAddress(); + } + // solhint-disable-next-line custom-errors require(msg.value == price, "insufficient msg.value"); (address receiver, uint256 royaltyAmount) = royaltyAddress.royaltyInfo(_tokenId, price); + if (receiver == address(0)) { + revert ZeroAddress(); + } uint256 sellerAmt = msg.value - royaltyAmount; payable(receiver).transfer(royaltyAmount); payable(from).transfer(sellerAmt); + // slither-disable-next-line arbitrary-send-erc20 tokenAddress.transferFrom(from, recipient, _tokenId); } } diff --git a/contracts/mocks/MockOnReceive.sol b/contracts/mocks/MockOnReceive.sol index aa40379b..9ba4bab5 100644 --- a/contracts/mocks/MockOnReceive.sol +++ b/contracts/mocks/MockOnReceive.sol @@ -1,11 +1,13 @@ -pragma solidity ^0.8.0; +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; -import "@openzeppelin/contracts/token/ERC721/IERC721.sol"; +import {IERC721} from "@openzeppelin/contracts/token/ERC721/IERC721.sol"; contract MockOnReceive { - IERC721 public tokenAddress; - address private recipient; + IERC721 public immutable tokenAddress; + address private immutable recipient; + // slither-disable-next-line missing-zero-check constructor(IERC721 _tokenAddress, address _recipient) { tokenAddress = _tokenAddress; recipient = _recipient; @@ -13,10 +15,10 @@ contract MockOnReceive { // Attempt to transfer token to another address on receive function onERC721Received( - address operator, - address from, + address /* operator */, + address /* from */, uint256 tokenId, - bytes calldata data + bytes calldata /* data */ ) public returns (bytes4) { tokenAddress.transferFrom(address(this), recipient, tokenId); return this.onERC721Received.selector; diff --git a/contracts/mocks/MockWallet.sol b/contracts/mocks/MockWallet.sol index 5f42c422..f152f2d6 100644 --- a/contracts/mocks/MockWallet.sol +++ b/contracts/mocks/MockWallet.sol @@ -1,14 +1,19 @@ -pragma solidity ^0.8.0; +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; -import "@openzeppelin/contracts/token/ERC721/IERC721.sol"; -import "@openzeppelin/contracts/token/ERC1155/IERC1155.sol"; +import {IERC721} from "@openzeppelin/contracts/token/ERC721/IERC721.sol"; +import {IERC1155} from "@openzeppelin/contracts/token/ERC1155/IERC1155.sol"; contract MockWallet { event Received(address, address, uint256, uint256, bytes); event ReceivedBatch(address, address, uint256[], uint256[], bytes); + /// @notice This code is only for testing purposes. Do not use similar + /// @notice constructions in production code as they are open to attack. + /// @dev For details see: https://github.com/crytic/slither/wiki/Detector-Documentation#arbitrary-from-in-transferfrom function transferNFT(address token, address from, address to, uint256 tokenId) external { + // slither-disable-next-line arbitrary-send-erc20 IERC721(token).transferFrom(from, to, tokenId); } diff --git a/contracts/mocks/MockWalletFactory.sol b/contracts/mocks/MockWalletFactory.sol index 2871a9ff..b5524ce7 100644 --- a/contracts/mocks/MockWalletFactory.sol +++ b/contracts/mocks/MockWalletFactory.sol @@ -1,7 +1,8 @@ -pragma solidity ^0.8.0; +// SPDX-License-Identifier: MIT +pragma solidity 0.8.19; contract MockWalletFactory { - bytes private constant walletCreationCode = + bytes private constant WALLET_CREATION_CODE = hex"608060405234801561001057600080fd5b5060405161029f38038061029f8339818101604052810190610032919061009e565b803055506100cb565b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061006b82610040565b9050919050565b61007b81610060565b811461008657600080fd5b50565b60008151905061009881610072565b92915050565b6000602082840312156100b4576100b361003b565b5b60006100c284828501610089565b91505092915050565b6101c5806100da6000396000f3fe6080604052600436106100225760003560e01c806390611127146100a857610076565b36610076573373ffffffffffffffffffffffffffffffffffffffff16347f606834f57405380c4fb88d1f4850326ad3885f014bab3b568dfbf7a041eef73860405161006c90610113565b60405180910390a3005b60006100806100d3565b90503660008037600080366000845af43d6000803e80600081146100a3573d6000f35b3d6000fd5b3480156100b457600080fd5b506100bd6100d3565b6040516100ca9190610174565b60405180910390f35b60003054905090565b600082825260208201905092915050565b50565b60006100fd6000836100dc565b9150610108826100ed565b600082019050919050565b6000602082019050818103600083015261012c816100f0565b9050919050565b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b600061015e82610133565b9050919050565b61016e81610153565b82525050565b60006020820190506101896000830184610165565b9291505056fea2646970667358221220d43fa02972046db2bc81804ebf600d5b46b97e55c738ea899a28224e111b588564736f6c63430008110033"; function getAddress(address _mainModule, bytes32 _salt) public view returns (address _address) { @@ -10,18 +11,21 @@ contract MockWalletFactory { bytes1(0xff), address(this), _salt, - keccak256(abi.encodePacked(walletCreationCode, uint256(uint160(_mainModule)))) + keccak256(abi.encodePacked(WALLET_CREATION_CODE, uint256(uint160(_mainModule)))) ) ); return address(uint160(uint256(_hash))); } + // slither-disable-next-line locked-ether function deploy(address _mainModule, bytes32 _salt) public payable returns (address _contract) { - bytes memory code = abi.encodePacked(walletCreationCode, uint256(uint160(_mainModule))); + bytes memory code = abi.encodePacked(WALLET_CREATION_CODE, uint256(uint160(_mainModule))); + // solhint-disable-next-line no-inline-assembly assembly { _contract := create2(callvalue(), add(code, 32), mload(code), _salt) } // check deployment success + // solhint-disable-next-line custom-errors require(_contract != address(0), "WalletFactory: deployment failed"); } } diff --git a/contracts/payment-splitter/PaymentSplitter.sol b/contracts/payment-splitter/PaymentSplitter.sol index c2f2e48d..adc9ae50 100644 --- a/contracts/payment-splitter/PaymentSplitter.sol +++ b/contracts/payment-splitter/PaymentSplitter.sol @@ -4,9 +4,9 @@ pragma solidity 0.8.19; import {SafeERC20, IERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol"; import {Address} from "@openzeppelin/contracts/utils/Address.sol"; -import {Context} from "@openzeppelin/contracts/utils/Context.sol"; import {AccessControlEnumerable} from "@openzeppelin/contracts/access/AccessControlEnumerable.sol"; import {IPaymentSplitterErrors} from "../errors/PaymentSplitterErrors.sol"; +import {ReentrancyGuard} from "@openzeppelin/contracts/security/ReentrancyGuard.sol"; /** * @title PaymentSplitter @@ -15,7 +15,7 @@ import {IPaymentSplitterErrors} from "../errors/PaymentSplitterErrors.sol"; * * Implementation is based on openzeppelin/PaymentSplitter smart contract */ -contract PaymentSplitter is AccessControlEnumerable, IPaymentSplitterErrors { +contract PaymentSplitter is AccessControlEnumerable, IPaymentSplitterErrors, ReentrancyGuard { /// @notice Emitted when the payees list is updated event PayeeAdded(address account, uint256 shares); @@ -38,7 +38,7 @@ contract PaymentSplitter is AccessControlEnumerable, IPaymentSplitterErrors { uint256 private _totalShares; /// @notice the number of shares held by each payee - mapping(address => uint256) private _shares; + mapping(address payee => uint256 numberOfShares) private _shares; /// @notice the address of the payees address payable[] private _payees; @@ -93,13 +93,16 @@ contract PaymentSplitter is AccessControlEnumerable, IPaymentSplitterErrors { * @param token The address of the ERC20 token to be removed */ function removeFromAllowlist(IERC20 token) external onlyRole(TOKEN_REGISTRAR_ROLE) { - for (uint256 index; index < allowedERC20List.length; index++) { + uint256 allowlistLength = allowedERC20List.length; + // slither-disable-start costly-loop + for (uint256 index; index < allowlistLength; index++) { if (allowedERC20List[index] == token) { allowedERC20List[index] = allowedERC20List[allowedERC20List.length - 1]; allowedERC20List.pop(); break; } } + // slither-disable-end costly-loop } /** @@ -157,10 +160,12 @@ contract PaymentSplitter is AccessControlEnumerable, IPaymentSplitterErrors { * percentage of the total shares and their previous withdrawals. `token` must be the address of an IERC20 * contract. */ - function releaseAll() public virtual onlyRole(RELEASE_FUNDS_ROLE) { + function releaseAll() public virtual nonReentrant onlyRole(RELEASE_FUNDS_ROLE) { + uint256 numPayees = _payees.length; uint256 startBalance = address(this).balance; + // slither-disable-start calls-loop if (startBalance > 0) { - for (uint256 payeeIndex = 0; payeeIndex < _payees.length; payeeIndex++) { + for (uint256 payeeIndex = 0; payeeIndex < numPayees; payeeIndex++) { address payable account = _payees[payeeIndex]; uint256 nativePaymentAmount = _pendingPayment(account, startBalance); Address.sendValue(account, nativePaymentAmount); @@ -172,7 +177,7 @@ contract PaymentSplitter is AccessControlEnumerable, IPaymentSplitterErrors { IERC20 erc20 = allowedERC20List[tokenIndex]; uint256 startBalanceERC20 = erc20.balanceOf(address(this)); if (startBalanceERC20 > 0) { - for (uint256 payeeIndex = 0; payeeIndex < _payees.length; payeeIndex++) { + for (uint256 payeeIndex = 0; payeeIndex < numPayees; payeeIndex++) { address account = _payees[payeeIndex]; uint256 erc20PaymentAmount = _pendingPayment(account, startBalanceERC20); SafeERC20.safeTransfer(erc20, account, erc20PaymentAmount); @@ -180,6 +185,7 @@ contract PaymentSplitter is AccessControlEnumerable, IPaymentSplitterErrors { } } } + // slither-disable-end calls-loop } /** @@ -199,16 +205,21 @@ contract PaymentSplitter is AccessControlEnumerable, IPaymentSplitterErrors { revert PaymentSplitterNoPayeesAdded(); } - for (uint256 i = 0; i < _payees.length; i++) { + uint256 numPayees = _payees.length; + // slither-disable-start costly-loop + for (uint256 i = 0; i < numPayees; i++) { delete _shares[_payees[i]]; } + // slither-disable-end costly-loop delete _payees; - _totalShares = 0; + uint256 localTotalShares = 0; for (uint256 i = 0; i < payees.length; i++) { + localTotalShares += shares_[i]; _addPayee(payees[i], shares_[i]); } + _totalShares = localTotalShares; } /** @@ -227,7 +238,8 @@ contract PaymentSplitter is AccessControlEnumerable, IPaymentSplitterErrors { * @param token The address of the ERC20 token to be added */ function addToAllowlist(IERC20 token) internal onlyRole(TOKEN_REGISTRAR_ROLE) { - for (uint256 index; index < allowedERC20List.length; index++) { + uint256 allowListLength = allowedERC20List.length; + for (uint256 index; index < allowListLength; index++) { if (allowedERC20List[index] == token) { return; } @@ -263,7 +275,6 @@ contract PaymentSplitter is AccessControlEnumerable, IPaymentSplitterErrors { _payees.push(account); _shares[account] = shares_; - _totalShares = _totalShares + shares_; emit PayeeAdded(account, shares_); } } diff --git a/contracts/random/RandomSeedProvider.sol b/contracts/random/RandomSeedProvider.sol index 030db53c..581b19f7 100644 --- a/contracts/random/RandomSeedProvider.sol +++ b/contracts/random/RandomSeedProvider.sol @@ -135,6 +135,7 @@ contract RandomSeedProvider is AccessControlEnumerableUpgradeable, UUPSUpgradeab * @param _offchainRandomSource Address of contract that is an off-chain random source. */ function setOffchainRandomSource(address _offchainRandomSource) external onlyRole(RANDOM_ADMIN_ROLE) { + // slither-disable-next-line missing-zero-check randomSource = _offchainRandomSource; emit OffchainRandomSourceSet(_offchainRandomSource); } @@ -176,7 +177,7 @@ contract RandomSeedProvider is AccessControlEnumerableUpgradeable, UUPSUpgradeab * @return _randomFulfilmentIndex The index for the game contract to present to fetch the next random value. * @return _randomSource Indicates that an on-chain source was used, or is the address of an off-chain source. */ - // slither-disable-next-line reentrancy-benign + // slither-disable-next-line reentrancy-benign, reentrancy-no-eth function requestRandomSeed() external returns (uint256 _randomFulfilmentIndex, address _randomSource) { if (randomSource == ONCHAIN || !approvedForOffchainRandom[msg.sender]) { // Generate a value for this block if one has not been generated yet. This @@ -190,12 +191,13 @@ contract RandomSeedProvider is AccessControlEnumerableUpgradeable, UUPSUpgradeab _randomSource = ONCHAIN; } else { // Limit how often off-chain random numbers are requested to a maximum of once per block. + // slither-disable-next-line incorrect-equality if (lastBlockOffchainRequest == block.number) { _randomFulfilmentIndex = prevOffchainRandomRequest; } else { + lastBlockOffchainRequest = block.number; _randomFulfilmentIndex = IOffchainRandomSource(randomSource).requestOffchainRandom(); prevOffchainRandomRequest = _randomFulfilmentIndex; - lastBlockOffchainRequest = block.number; } _randomSource = randomSource; } @@ -235,6 +237,7 @@ contract RandomSeedProvider is AccessControlEnumerableUpgradeable, UUPSUpgradeab */ function isRandomSeedReady(uint256 _randomFulfilmentIndex, address _randomSource) external view returns (bool) { if (_randomSource == ONCHAIN) { + // slither-disable-next-line incorrect-equality if (lastBlockRandomGenerated == block.number) { return _randomFulfilmentIndex < nextRandomIndex; } else { @@ -261,6 +264,7 @@ contract RandomSeedProvider is AccessControlEnumerableUpgradeable, UUPSUpgradeab */ function _generateNextRandomOnChain() private { // Onchain random values can only be generated once per block. + // slither-disable-next-line incorrect-equality if (lastBlockRandomGenerated == block.number) { return; } diff --git a/contracts/random/RandomValues.sol b/contracts/random/RandomValues.sol index 5031182d..9b29e61f 100644 --- a/contracts/random/RandomValues.sol +++ b/contracts/random/RandomValues.sol @@ -20,13 +20,13 @@ abstract contract RandomValues { struct RandomRequest { // Id to match the random seed provider requests and responses. uint256 fulfilmentId; - // Number of words requested. Retaining the size ensures the correct + // Number of words requested. Retaining the size ensures the correct // number of words are returned. uint16 size; // Source of the random value: which off-chain, or the on-chain provider // will provide the random values. Retaining the source allows for upgrade - // of sources inside the random seed provider contract. - address source; + // of sources inside the random seed provider contract. + address source; } /// @notice Status of a random request @@ -92,13 +92,15 @@ abstract contract RandomValues { * @param _randomRequestId The value returned by _requestRandomValueCreation. * @return _randomValues An array of random values. */ - function _fetchRandomValues( - uint256 _randomRequestId - ) internal returns (bytes32[] memory _randomValues) { + // slither-disable-next-line reentrancy-benign + function _fetchRandomValues(uint256 _randomRequestId) internal returns (bytes32[] memory _randomValues) { RandomRequest memory request = randCreationRequests[_randomRequestId]; if (request.size == 0) { revert RandomValuesPreviouslyFetched(); } + // Prevent random values from being re-fetched. This reduces the probability + // that a game will mistakenly re-use the same random values for two purposes. + delete randCreationRequests[_randomRequestId]; // Request the random seed. If not enough time has elapsed yet, this call will revert. bytes32 randomSeed = randomSeedProvider.getRandomSeed(request.fulfilmentId, request.source); @@ -115,17 +117,13 @@ abstract contract RandomValues { for (uint256 i = 0; i < request.size; i++) { _randomValues[i] = keccak256(abi.encodePacked(seed, i)); } - - // Prevent random values from being re-fetched. This reduces the probability - // that a game will mistakenly re-use the same random values for two purposes. - delete randCreationRequests[_randomRequestId]; } /** * @notice Check whether a set of random values are ready to be fetched * @dev If this function returns true then it is safe to call _fetchRandom or _fetchRandomValues. * @param _randomRequestId The value returned by _requestRandomValueCreation. - * @return RequestStatus indicates whether the random values are still be generated, are ready + * @return RequestStatus indicates whether the random values are still be generated, are ready * to be fetched, or whether they have already been fetched and are no longer available. */ function _isRandomValueReady(uint256 _randomRequestId) internal view returns (RequestStatus) { @@ -133,8 +131,10 @@ abstract contract RandomValues { if (request.size == 0) { return RequestStatus.ALREADY_FETCHED; } - return randomSeedProvider.isRandomSeedReady(request.fulfilmentId, request.source) ? - RequestStatus.READY : RequestStatus.IN_PROGRESS; + return + randomSeedProvider.isRandomSeedReady(request.fulfilmentId, request.source) + ? RequestStatus.READY + : RequestStatus.IN_PROGRESS; } // slither-disable-next-line unused-state,naming-convention diff --git a/contracts/random/offchainsources/SourceAdaptorBase.sol b/contracts/random/offchainsources/SourceAdaptorBase.sol index a8382a21..693c14d9 100644 --- a/contracts/random/offchainsources/SourceAdaptorBase.sol +++ b/contracts/random/offchainsources/SourceAdaptorBase.sol @@ -33,8 +33,8 @@ abstract contract SourceAdaptorBase is AccessControlEnumerable, IOffchainRandomS } /** - * @notice Callback called when random words are returned by the VRF. - * @dev Assumes external function that calls this checks that the random values are coming + * @notice Callback called when random words are returned by the VRF. + * @dev Assumes external function that calls this checks that the random values are coming * @dev from the VRF. * @dev NOTE that Chainlink assumes that this function will not fail. * @param _requestId is the fulfilment index. @@ -42,7 +42,7 @@ abstract contract SourceAdaptorBase is AccessControlEnumerable, IOffchainRandomS */ function _fulfillRandomWords(uint256 _requestId, uint256[] memory _randomWords) internal { // NOTE: This function call is not allowed to fail. However, if one word is requested - // and some other number of words has been returned, then maybe the source has been + // and some other number of words has been returned, then maybe the source has been // compromised. Reverting the call is more likely to draw attention to the issue than // emitting an event. if (_randomWords.length != 1) { @@ -54,7 +54,9 @@ abstract contract SourceAdaptorBase is AccessControlEnumerable, IOffchainRandomS /** * @inheritdoc IOffchainRandomSource */ - function getOffchainRandom(uint256 _fulfilmentIndex) external override(IOffchainRandomSource) view returns (bytes32 _randomValue) { + function getOffchainRandom( + uint256 _fulfilmentIndex + ) external view override(IOffchainRandomSource) returns (bytes32 _randomValue) { bytes32 rand = randomOutput[_fulfilmentIndex]; if (rand == bytes32(0)) { revert WaitForRandom(); @@ -65,7 +67,9 @@ abstract contract SourceAdaptorBase is AccessControlEnumerable, IOffchainRandomS /** * @inheritdoc IOffchainRandomSource */ - function isOffchainRandomReady(uint256 _fulfilmentIndex) external override(IOffchainRandomSource) view returns (bool) { + function isOffchainRandomReady( + uint256 _fulfilmentIndex + ) external view override(IOffchainRandomSource) returns (bool) { return randomOutput[_fulfilmentIndex] != bytes32(0); } } diff --git a/contracts/random/offchainsources/chainlink/ChainlinkSourceAdaptor.sol b/contracts/random/offchainsources/chainlink/ChainlinkSourceAdaptor.sol index f75b7138..6d44445c 100644 --- a/contracts/random/offchainsources/chainlink/ChainlinkSourceAdaptor.sol +++ b/contracts/random/offchainsources/chainlink/ChainlinkSourceAdaptor.sol @@ -15,7 +15,7 @@ import {IOffchainRandomSource} from "../IOffchainRandomSource.sol"; */ contract ChainlinkSourceAdaptor is VRFConsumerBaseV2, SourceAdaptorBase { /// @notice Log config changes. - event ConfigChanges( bytes32 _keyHash, uint64 _subId, uint32 _callbackGasLimit); + event ConfigChanges(bytes32 _keyHash, uint64 _subId, uint32 _callbackGasLimit); /// @notice Relates to key that must sign the proof. bytes32 public keyHash; diff --git a/contracts/random/offchainsources/chainlink/VRFConsumerBaseV2.sol b/contracts/random/offchainsources/chainlink/VRFConsumerBaseV2.sol index 68ec51cd..40e02eff 100644 --- a/contracts/random/offchainsources/chainlink/VRFConsumerBaseV2.sol +++ b/contracts/random/offchainsources/chainlink/VRFConsumerBaseV2.sol @@ -1,12 +1,11 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.19; -// Code from Chainlink's repo. +// Code from Chainlink's repo. // This file has been copied here that than installing the chainlink contracts // using the following command to dependency clashes. // npm install @chainlink/contracts - /** **************************************************************************** * @notice Interface for contracts using VRF randomness * ***************************************************************************** @@ -101,41 +100,41 @@ pragma solidity 0.8.19; * @dev and so remains effective only in the case of unmodified oracle software). */ abstract contract VRFConsumerBaseV2 { - error OnlyCoordinatorCanFulfill(address have, address want); - // solhint-disable-next-line chainlink-solidity/prefix-immutable-variables-with-i - address private immutable vrfCoordinator; + error OnlyCoordinatorCanFulfill(address have, address want); + // solhint-disable-next-line chainlink-solidity/prefix-immutable-variables-with-i + address private immutable vrfCoordinator; - /** - * @param _vrfCoordinator address of VRFCoordinator contract - */ - constructor(address _vrfCoordinator) { - vrfCoordinator = _vrfCoordinator; - } + /** + * @param _vrfCoordinator address of VRFCoordinator contract + */ + constructor(address _vrfCoordinator) { + vrfCoordinator = _vrfCoordinator; + } - /** - * @notice fulfillRandomness handles the VRF response. Your contract must - * @notice implement it. See "SECURITY CONSIDERATIONS" above for important - * @notice principles to keep in mind when implementing your fulfillRandomness - * @notice method. - * - * @dev VRFConsumerBaseV2 expects its subcontracts to have a method with this - * @dev signature, and will call it once it has verified the proof - * @dev associated with the randomness. (It is triggered via a call to - * @dev rawFulfillRandomness, below.) - * - * @param requestId The Id initially returned by requestRandomness - * @param randomWords the VRF output expanded to the requested number of words - */ - // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore - function fulfillRandomWords(uint256 requestId, uint256[] memory randomWords) internal virtual; + /** + * @notice fulfillRandomness handles the VRF response. Your contract must + * @notice implement it. See "SECURITY CONSIDERATIONS" above for important + * @notice principles to keep in mind when implementing your fulfillRandomness + * @notice method. + * + * @dev VRFConsumerBaseV2 expects its subcontracts to have a method with this + * @dev signature, and will call it once it has verified the proof + * @dev associated with the randomness. (It is triggered via a call to + * @dev rawFulfillRandomness, below.) + * + * @param requestId The Id initially returned by requestRandomness + * @param randomWords the VRF output expanded to the requested number of words + */ + // solhint-disable-next-line chainlink-solidity/prefix-internal-functions-with-underscore + function fulfillRandomWords(uint256 requestId, uint256[] memory randomWords) internal virtual; - // rawFulfillRandomness is called by VRFCoordinator when it receives a valid VRF - // proof. rawFulfillRandomness then calls fulfillRandomness, after validating - // the origin of the call - function rawFulfillRandomWords(uint256 requestId, uint256[] memory randomWords) external { - if (msg.sender != vrfCoordinator) { - revert OnlyCoordinatorCanFulfill(msg.sender, vrfCoordinator); + // rawFulfillRandomness is called by VRFCoordinator when it receives a valid VRF + // proof. rawFulfillRandomness then calls fulfillRandomness, after validating + // the origin of the call + function rawFulfillRandomWords(uint256 requestId, uint256[] memory randomWords) external { + if (msg.sender != vrfCoordinator) { + revert OnlyCoordinatorCanFulfill(msg.sender, vrfCoordinator); + } + fulfillRandomWords(requestId, randomWords); } - fulfillRandomWords(requestId, randomWords); - } } diff --git a/contracts/random/offchainsources/supra/ISupraRouter.sol b/contracts/random/offchainsources/supra/ISupraRouter.sol index d02f0f79..c4d2c26a 100644 --- a/contracts/random/offchainsources/supra/ISupraRouter.sol +++ b/contracts/random/offchainsources/supra/ISupraRouter.sol @@ -6,7 +6,6 @@ pragma solidity 0.8.19; */ interface ISupraRouter { - function generateRequest( string memory _functionSig, uint8 _rngCount, diff --git a/contracts/random/offchainsources/supra/SupraSourceAdaptor.sol b/contracts/random/offchainsources/supra/SupraSourceAdaptor.sol index aa3eb9ff..4da85674 100644 --- a/contracts/random/offchainsources/supra/SupraSourceAdaptor.sol +++ b/contracts/random/offchainsources/supra/SupraSourceAdaptor.sol @@ -34,20 +34,20 @@ contract SupraSourceAdaptor is SourceAdaptorBase { address _vrfCoordinator, address _subscription ) SourceAdaptorBase(_roleAdmin, _configAdmin, _vrfCoordinator) { + // slither-disable-next-line missing-zero-check subscriptionAccount = _subscription; } - /** * @notice Change the subscription account address. * @param _subscription The address of the new subscription. */ function setSubscription(address _subscription) external onlyRole(CONFIG_ADMIN_ROLE) { + // slither-disable-next-line missing-zero-check subscriptionAccount = _subscription; emit SubscriptionChange(subscriptionAccount); } - /** * @inheritdoc IOffchainRandomSource */ @@ -62,7 +62,7 @@ contract SupraSourceAdaptor is SourceAdaptorBase { } /** - * @notice Callback called when random words are returned by the VRF. + * @notice Callback called when random words are returned by the VRF. * @param _requestId is the fulfilment index. * @param _randomWords are the random values from the VRF. */ diff --git a/contracts/test/allowlist/OperatorAllowlist.sol b/contracts/test/allowlist/OperatorAllowlist.sol index b1d62caa..40fae9af 100644 --- a/contracts/test/allowlist/OperatorAllowlist.sol +++ b/contracts/test/allowlist/OperatorAllowlist.sol @@ -14,6 +14,7 @@ import {IOperatorAllowlist} from "../../allowlist/IOperatorAllowlist.sol"; // Interface to retrieve the implemention stored inside the Proxy contract interface IProxy { // Returns the current implementation address used by the proxy contract + // solhint-disable-next-line func-name-mixedcase function PROXY_getImplementation() external view returns (address); } @@ -31,13 +32,13 @@ contract OperatorAllowlist is ERC165, AccessControl, IOperatorAllowlist { bytes32 public constant REGISTRAR_ROLE = bytes32("REGISTRAR_ROLE"); /// @notice Mapping of Allowlisted addresses - mapping(address => bool) private addressAllowlist; + mapping(address aContract => bool allowed) private addressAllowlist; /// @notice Mapping of Allowlisted implementation addresses - mapping(address => bool) private addressImplementationAllowlist; + mapping(address impl => bool allowed) private addressImplementationAllowlist; /// @notice Mapping of Allowlisted bytecodes - mapping(bytes32 => bool) private bytecodeAllowlist; + mapping(bytes32 bytecodeHash => bool allowed) private bytecodeAllowlist; /// ===== Events ===== @@ -92,6 +93,7 @@ contract OperatorAllowlist is ERC165, AccessControl, IOperatorAllowlist { function addWalletToAllowlist(address walletAddr) external onlyRole(REGISTRAR_ROLE) { // get bytecode of wallet bytes32 codeHash; + // solhint-disable-next-line no-inline-assembly assembly { codeHash := extcodehash(walletAddr) } @@ -111,6 +113,7 @@ contract OperatorAllowlist is ERC165, AccessControl, IOperatorAllowlist { function removeWalletFromAllowlist(address walletAddr) external onlyRole(REGISTRAR_ROLE) { // get bytecode of wallet bytes32 codeHash; + // solhint-disable-next-line no-inline-assembly assembly { codeHash := extcodehash(walletAddr) } @@ -151,6 +154,7 @@ contract OperatorAllowlist is ERC165, AccessControl, IOperatorAllowlist { // Check if caller is a Allowlisted smart contract wallet bytes32 codeHash; + // solhint-disable-next-line no-inline-assembly assembly { codeHash := extcodehash(target) } diff --git a/contracts/token/erc1155/abstract/ERC1155Permit.Sol b/contracts/token/erc1155/abstract/ERC1155Permit.Sol index 04304c7e..7d90d3f6 100644 --- a/contracts/token/erc1155/abstract/ERC1155Permit.Sol +++ b/contracts/token/erc1155/abstract/ERC1155Permit.Sol @@ -34,7 +34,7 @@ abstract contract ERC1155Permit is ERC1155Burnable, EIP712, IERC1155Permit, IImm return; } - address recoveredSigner; + address recoveredSigner = address(0); // EOA signature validation if (sig.length == 64) { @@ -129,6 +129,7 @@ abstract contract ERC1155Permit is ERC1155Burnable, EIP712, IERC1155Permit, IImm * @return True if the signature is valid according to EIP-1271, otherwise false. */ function _isValidERC1271Signature(address spender, bytes32 digest, bytes memory sig) private view returns(bool) { + // slither-disable-next-line low-level-calls (bool success, bytes memory res) = spender.staticcall( abi.encodeWithSelector( IERC1271.isValidSignature.selector, diff --git a/contracts/token/erc1155/abstract/IERC1155Permit.sol b/contracts/token/erc1155/abstract/IERC1155Permit.sol index f63bd7de..8dfe34f5 100644 --- a/contracts/token/erc1155/abstract/IERC1155Permit.sol +++ b/contracts/token/erc1155/abstract/IERC1155Permit.sol @@ -6,5 +6,7 @@ pragma solidity 0.8.19; interface IERC1155Permit { function permit(address owner, address spender, bool approved, uint256 deadline, bytes memory sig) external; function nonces(address owner) external view returns (uint256); + + // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view returns (bytes32); } diff --git a/contracts/token/erc1155/abstract/ImmutableERC1155Base.sol b/contracts/token/erc1155/abstract/ImmutableERC1155Base.sol index d4e818cd..02c81796 100644 --- a/contracts/token/erc1155/abstract/ImmutableERC1155Base.sol +++ b/contracts/token/erc1155/abstract/ImmutableERC1155Base.sol @@ -2,20 +2,13 @@ // SPDX-License-Identifier: Apache 2.0 pragma solidity 0.8.19; -import "../../../token/erc1155/abstract/ERC1155Permit.Sol"; +import {ERC1155, ERC1155Permit} from "../../../token/erc1155/abstract/ERC1155Permit.Sol"; // Allowlist -import "@openzeppelin/contracts/token/common/ERC2981.sol"; -import "../../../allowlist/OperatorAllowlistEnforced.sol"; +import {ERC2981} from "@openzeppelin/contracts/token/common/ERC2981.sol"; +import {OperatorAllowlistEnforced} from "../../../allowlist/OperatorAllowlistEnforced.sol"; -// Utils -import "@openzeppelin/contracts/utils/structs/BitMaps.sol"; - -abstract contract ImmutableERC1155Base is - OperatorAllowlistEnforced, - ERC1155Permit, - ERC2981 -{ +abstract contract ImmutableERC1155Base is OperatorAllowlistEnforced, ERC1155Permit, ERC2981 { /// @dev Contract level metadata string public contractURI; @@ -26,7 +19,7 @@ abstract contract ImmutableERC1155Base is bytes32 public constant MINTER_ROLE = bytes32("MINTER_ROLE"); /// @dev mapping of each token id supply - mapping(uint256 => uint256) private _totalSupply; + mapping(uint256 tokenId => uint256 totalSupply) private _totalSupply; /** * @dev Grants `DEFAULT_ADMIN_ROLE` to the supplied `owner` address @@ -67,7 +60,7 @@ abstract contract ImmutableERC1155Base is * @param tokenId The token identifier to set the royalty receiver for. * @param receiver The address of the royalty receiver * @param feeNumerator The royalty fee numerator - */ + */ function setNFTRoyaltyReceiver( uint256 tokenId, address receiver, @@ -81,13 +74,13 @@ abstract contract ImmutableERC1155Base is * @param tokenIds The token identifiers to set the royalty receiver for. * @param receiver The address of the royalty receiver * @param feeNumerator The royalty fee numerator - */ + */ function setNFTRoyaltyReceiverBatch( uint256[] calldata tokenIds, address receiver, uint96 feeNumerator ) public onlyRole(MINTER_ROLE) { - for (uint i = 0; i < tokenIds.length; i++) { + for (uint256 i = 0; i < tokenIds.length; i++) { _setTokenRoyalty(tokenIds[i], receiver, feeNumerator); } } @@ -122,8 +115,8 @@ abstract contract ImmutableERC1155Base is * @param baseURI_ The base URI for all tokens */ function setBaseURI(string memory baseURI_) public onlyRole(DEFAULT_ADMIN_ROLE) { - _setURI(baseURI_); - _baseURI = baseURI_; + _setURI(baseURI_); + _baseURI = baseURI_; } /// @dev Allows admin to set the contract URI @@ -154,13 +147,7 @@ abstract contract ImmutableERC1155Base is */ function supportsInterface( bytes4 interfaceId - ) - public - view - virtual - override(ERC1155Permit, ERC2981, OperatorAllowlistEnforced) - returns (bool) - { + ) public view virtual override(ERC1155Permit, ERC2981, OperatorAllowlistEnforced) returns (bool) { return super.supportsInterface(interfaceId); } @@ -239,6 +226,7 @@ abstract contract ImmutableERC1155Base is uint256 id = ids[i]; uint256 amount = amounts[i]; uint256 supply = _totalSupply[id]; + // solhint-disable-next-line custom-errors, reason-string require(supply >= amount, "ERC1155: burn amount exceeds totalSupply"); unchecked { _totalSupply[id] = supply - amount; @@ -255,7 +243,13 @@ abstract contract ImmutableERC1155Base is * @param value The amount to transfer. * @param data Additional data with no specified format, sent in call to `to`. */ - function _safeTransferFrom(address from, address to, uint256 id, uint256 value, bytes memory data) internal override validateTransfer(from, to) { + function _safeTransferFrom( + address from, + address to, + uint256 id, + uint256 value, + bytes memory data + ) internal override validateTransfer(from, to) { super._safeTransferFrom(from, to, id, value, data); } @@ -267,9 +261,13 @@ abstract contract ImmutableERC1155Base is * @param values The amounts to transfer per token id. * @param data Additional data with no specified format, sent in call to `to`. */ - function _safeBatchTransferFrom(address from, address to, uint256[] memory ids, uint256[] memory values, bytes memory data) internal override validateTransfer(from, to) { + function _safeBatchTransferFrom( + address from, + address to, + uint256[] memory ids, + uint256[] memory values, + bytes memory data + ) internal override validateTransfer(from, to) { super._safeBatchTransferFrom(from, to, ids, values, data); } - - } diff --git a/contracts/token/erc1155/preset/draft-ImmutableERC1155.sol b/contracts/token/erc1155/preset/draft-ImmutableERC1155.sol index de6469ed..8658f7dd 100644 --- a/contracts/token/erc1155/preset/draft-ImmutableERC1155.sol +++ b/contracts/token/erc1155/preset/draft-ImmutableERC1155.sol @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache 2.0 pragma solidity 0.8.19; -import "../abstract/ImmutableERC1155Base.sol"; +import {ImmutableERC1155Base} from "../abstract/ImmutableERC1155Base.sol"; /** * @title draft-ImmutableERC1155 @@ -12,7 +12,7 @@ import "../abstract/ImmutableERC1155Base.sol"; */ contract ImmutableERC1155 is ImmutableERC1155Base { - /// ===== Constructor ===== + /// ===== Constructor ===== /** * @notice Grants `DEFAULT_ADMIN_ROLE` to the supplied `owner` address @@ -30,9 +30,7 @@ contract ImmutableERC1155 is ImmutableERC1155Base { address _operatorAllowlist, address _receiver, uint96 _feeNumerator - ) - ImmutableERC1155Base(owner, name_, baseURI_, contractURI_, _operatorAllowlist, _receiver, _feeNumerator) - {} + ) ImmutableERC1155Base(owner, name_, baseURI_, contractURI_, _operatorAllowlist, _receiver, _feeNumerator) {} /// ===== External functions ===== @@ -40,7 +38,12 @@ contract ImmutableERC1155 is ImmutableERC1155Base { super._mint(to, id, value, data); } - function safeMintBatch(address to, uint256[] calldata ids, uint256[] calldata values, bytes memory data) external onlyRole(MINTER_ROLE) { + function safeMintBatch( + address to, + uint256[] calldata ids, + uint256[] calldata values, + bytes memory data + ) external onlyRole(MINTER_ROLE) { super._mintBatch(to, ids, values, data); } } diff --git a/contracts/token/erc20/ImmutableERC20.sol b/contracts/token/erc20/ImmutableERC20.sol index 5f2aa894..31e8bb34 100644 --- a/contracts/token/erc20/ImmutableERC20.sol +++ b/contracts/token/erc20/ImmutableERC20.sol @@ -1,7 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity 0.8.19; -import "@openzeppelin/contracts/token/ERC20/ERC20.sol"; +import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol"; contract ImmutableERC20 is ERC20 { constructor(string memory name_, string memory symbol_) ERC20(name_, symbol_) {} diff --git a/contracts/token/erc721/abstract/ERC721Hybrid.sol b/contracts/token/erc721/abstract/ERC721Hybrid.sol index 0a5b136e..5580030a 100644 --- a/contracts/token/erc721/abstract/ERC721Hybrid.sol +++ b/contracts/token/erc721/abstract/ERC721Hybrid.sol @@ -2,8 +2,8 @@ // SPDX-License-Identifier: Apache 2.0 pragma solidity 0.8.19; -import "@openzeppelin/contracts/token/ERC721/ERC721.sol"; -import "@openzeppelin/contracts/utils/structs/BitMaps.sol"; +import {ERC721} from "@openzeppelin/contracts/token/ERC721/ERC721.sol"; +import {BitMaps} from "@openzeppelin/contracts/utils/structs/BitMaps.sol"; import {ERC721Psi, ERC721PsiBurnable} from "../erc721psi/ERC721PsiBurnable.sol"; // Errors import {IImmutableERC721Errors} from "../../../errors/Errors.sol"; @@ -56,16 +56,16 @@ abstract contract ERC721Hybrid is ERC721PsiBurnable, ERC721, IImmutableERC721Err /** @notice allows caller to burn multiple tokens by id * @param tokenIDs an array of token ids - */ + */ function burnBatch(uint256[] calldata tokenIDs) external { - for (uint i = 0; i < tokenIDs.length; i++) { + for (uint256 i = 0; i < tokenIDs.length; i++) { burn(tokenIDs[i]); } } /** @notice burns the specified token id * @param tokenId the id of the token to burn - */ + */ function burn(uint256 tokenId) public virtual { if (!_isApprovedOrOwner(_msgSender(), tokenId)) { revert IImmutableERC721NotOwnerOrOperator(tokenId); @@ -76,7 +76,7 @@ abstract contract ERC721Hybrid is ERC721PsiBurnable, ERC721, IImmutableERC721Err /** @notice Burn a token, checking the owner of the token against the parameter first. * @param owner the owner of the token * @param tokenId the id of the token to burn - */ + */ function safeBurn(address owner, uint256 tokenId) public virtual { address currentOwner = ownerOf(tokenId); if (currentOwner != owner) { @@ -92,7 +92,7 @@ abstract contract ERC721Hybrid is ERC721PsiBurnable, ERC721, IImmutableERC721Err function mintBatchByQuantityThreshold() public pure virtual returns (uint256) { return 2 ** 128; } - + /** @notice checks to see if tokenID exists in the collection * @param tokenId the id of the token to check **/ @@ -103,7 +103,7 @@ abstract contract ERC721Hybrid is ERC721PsiBurnable, ERC721, IImmutableERC721Err /** @notice Overwritten functions with combined implementations, supply for the collection is summed as they * are tracked differently by each minting strategy */ - function balanceOf(address owner) public view virtual override(ERC721, ERC721Psi) returns (uint) { + function balanceOf(address owner) public view virtual override(ERC721, ERC721Psi) returns (uint256) { return ERC721.balanceOf(owner) + ERC721Psi.balanceOf(owner); } @@ -113,7 +113,7 @@ abstract contract ERC721Hybrid is ERC721PsiBurnable, ERC721, IImmutableERC721Err function totalSupply() public view override(ERC721PsiBurnable) returns (uint256) { return ERC721PsiBurnable.totalSupply() + _idMintTotalSupply; } - + /** @notice refer to erc721 or erc721psi */ function ownerOf(uint256 tokenId) public view virtual override(ERC721, ERC721Psi) returns (address) { if (tokenId < mintBatchByQuantityThreshold()) { @@ -216,7 +216,7 @@ abstract contract ERC721Hybrid is ERC721PsiBurnable, ERC721, IImmutableERC721Err /** @notice mints number of tokens specified to the address given via erc721psi * @param to the address to mint to * @param quantity the number of tokens to mint - */ + */ function _mintByQuantity(address to, uint256 quantity) internal { ERC721Psi._mint(to, quantity); } @@ -224,16 +224,16 @@ abstract contract ERC721Hybrid is ERC721PsiBurnable, ERC721, IImmutableERC721Err /** @notice safe mints number of tokens specified to the address given via erc721psi * @param to the address to mint to * @param quantity the number of tokens to mint - */ + */ function _safeMintByQuantity(address to, uint256 quantity) internal { ERC721Psi._safeMint(to, quantity); } /** @notice mints number of tokens specified to a multiple specified addresses via erc721psi * @param mints an array of mint requests - */ + */ function _mintBatchByQuantity(Mint[] calldata mints) internal { - for (uint i = 0; i < mints.length; i++) { + for (uint256 i = 0; i < mints.length; i++) { Mint calldata m = mints[i]; _mintByQuantity(m.to, m.quantity); } @@ -241,19 +241,18 @@ abstract contract ERC721Hybrid is ERC721PsiBurnable, ERC721, IImmutableERC721Err /** @notice safe mints number of tokens specified to a multiple specified addresses via erc721psi * @param mints an array of mint requests - */ + */ function _safeMintBatchByQuantity(Mint[] calldata mints) internal { - for (uint i = 0; i < mints.length; i++) { + for (uint256 i = 0; i < mints.length; i++) { Mint calldata m = mints[i]; _safeMintByQuantity(m.to, m.quantity); } } - /** @notice safe mints number of tokens specified to a multiple specified addresses via erc721 * @param to the address to mint to * @param tokenId the id of the token to mint - */ + */ function _mintByID(address to, uint256 tokenId) internal { if (tokenId >= mintBatchByQuantityThreshold()) { revert IImmutableERC721IDAboveThreshold(tokenId); @@ -262,7 +261,7 @@ abstract contract ERC721Hybrid is ERC721PsiBurnable, ERC721, IImmutableERC721Err if (_burnedTokens.get(tokenId)) { revert IImmutableERC721TokenAlreadyBurned(tokenId); } - + _idMintTotalSupply++; ERC721._mint(to, tokenId); } @@ -281,25 +280,25 @@ abstract contract ERC721Hybrid is ERC721PsiBurnable, ERC721, IImmutableERC721Err } _idMintTotalSupply++; - ERC721._safeMint(to, tokenId); + ERC721._safeMint(to, tokenId); } - /** @notice mints multiple tokens by id to a specified address via erc721 + /** @notice mints multiple tokens by id to a specified address via erc721 * @param to the address to mint to * @param tokenIds the ids of the tokens to mint */ function _mintBatchByID(address to, uint256[] calldata tokenIds) internal { - for (uint i = 0; i < tokenIds.length; i++) { + for (uint256 i = 0; i < tokenIds.length; i++) { _mintByID(to, tokenIds[i]); } } - /** @notice safe mints multiple tokens by id to a specified address via erc721 + /** @notice safe mints multiple tokens by id to a specified address via erc721 * @param to the address to mint to * @param tokenIds the ids of the tokens to mint **/ function _safeMintBatchByID(address to, uint256[] calldata tokenIds) internal { - for (uint i = 0; i < tokenIds.length; i++) { + for (uint256 i = 0; i < tokenIds.length; i++) { _safeMintByID(to, tokenIds[i]); } } @@ -308,7 +307,7 @@ abstract contract ERC721Hybrid is ERC721PsiBurnable, ERC721, IImmutableERC721Err * @param mints an array of mint requests */ function _mintBatchByIDToMultiple(IDMint[] calldata mints) internal { - for (uint i = 0; i < mints.length; i++) { + for (uint256 i = 0; i < mints.length; i++) { IDMint calldata m = mints[i]; _mintBatchByID(m.to, m.tokenIds); } @@ -318,19 +317,19 @@ abstract contract ERC721Hybrid is ERC721PsiBurnable, ERC721, IImmutableERC721Err * @param mints an array of mint requests */ function _safeMintBatchByIDToMultiple(IDMint[] calldata mints) internal { - for (uint i = 0; i < mints.length; i++) { + for (uint256 i = 0; i < mints.length; i++) { IDMint calldata m = mints[i]; _safeMintBatchByID(m.to, m.tokenIds); } } /** @notice batch burn a tokens by id, checking the owner of the token against the parameter first. - * @param burns array of burn requests - */ + * @param burns array of burn requests + */ function _safeBurnBatch(IDBurn[] calldata burns) internal { - for (uint i = 0; i < burns.length; i++) { + for (uint256 i = 0; i < burns.length; i++) { IDBurn calldata b = burns[i]; - for (uint j = 0; j < b.tokenIds.length; j++) { + for (uint256 j = 0; j < b.tokenIds.length; j++) { safeBurn(b.owner, b.tokenIds[j]); } } @@ -353,6 +352,7 @@ abstract contract ERC721Hybrid is ERC721PsiBurnable, ERC721, IImmutableERC721Err if (tokenId < mintBatchByQuantityThreshold()) { ERC721._burn(tokenId); _burnedTokens.set(tokenId); + // slither-disable-next-line costly-loop _idMintTotalSupply--; } else { ERC721PsiBurnable._burn(tokenId); @@ -388,6 +388,7 @@ abstract contract ERC721Hybrid is ERC721PsiBurnable, ERC721, IImmutableERC721Err /** @notice overriding erc721 and erc721psi _safemint, super calls the `_safeMint` method of * the erc721 implementation due to inheritance linearisation. Refer to erc721 */ + // slither-disable-next-line dead-code function _safeMint(address to, uint256 tokenId) internal virtual override(ERC721, ERC721Psi) { super._safeMint(to, tokenId); } @@ -433,8 +434,8 @@ abstract contract ERC721Hybrid is ERC721PsiBurnable, ERC721, IImmutableERC721Err /** * @inheritdoc ERC721 */ + // slither-disable-next-line dead-code function _baseURI() internal view virtual override(ERC721, ERC721Psi) returns (string memory) { return ERC721._baseURI(); } - -} \ No newline at end of file +} diff --git a/contracts/token/erc721/abstract/ERC721HybridPermit.sol b/contracts/token/erc721/abstract/ERC721HybridPermit.sol index 3e64466a..cd6946fa 100644 --- a/contracts/token/erc721/abstract/ERC721HybridPermit.sol +++ b/contracts/token/erc721/abstract/ERC721HybridPermit.sol @@ -2,13 +2,13 @@ // SPDX-License-Identifier: Apache 2.0 pragma solidity 0.8.19; -import "@openzeppelin/contracts/access/Ownable.sol"; -import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; -import "@openzeppelin/contracts/utils/cryptography/EIP712.sol"; -import "@openzeppelin/contracts/interfaces/IERC1271.sol"; -import "solidity-bytes-utils/contracts/BytesLib.sol"; -import "./IERC4494.sol"; -import "./ERC721Hybrid.sol"; +import {ECDSA} from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; +import {EIP712} from "@openzeppelin/contracts/utils/cryptography/EIP712.sol"; +import {IERC1271} from "@openzeppelin/contracts/interfaces/IERC1271.sol"; +import {IERC165} from "@openzeppelin/contracts/utils/introspection/ERC165.sol"; +import {BytesLib} from "solidity-bytes-utils/contracts/BytesLib.sol"; +import {IERC4494} from "./IERC4494.sol"; +import {ERC721Hybrid} from "./ERC721Hybrid.sol"; /** * @title ERC721HybridPermit: An extension of the ERC721Hybrid NFT standard that supports off-chain approval via permits. @@ -19,7 +19,7 @@ abstract contract ERC721HybridPermit is ERC721Hybrid, IERC4494, EIP712 { /** @notice mapping used to keep track of nonces of each token ID for validating * signatures */ - mapping(uint256 => uint256) private _nonces; + mapping(uint256 tokenId => uint256 nonce) private _nonces; /** @dev the unique identifier for the permit struct to be EIP 712 compliant */ bytes32 private constant _PERMIT_TYPEHASH = @@ -60,6 +60,7 @@ abstract contract ERC721HybridPermit is ERC721Hybrid, IERC4494, EIP712 { * @notice Returns the domain separator used in the encoding of the signature for permits, as defined by EIP-712 * @return the bytes32 domain separator */ + // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view override returns (bytes32) { return _domainSeparatorV4(); } @@ -87,6 +88,7 @@ abstract contract ERC721HybridPermit is ERC721Hybrid, IERC4494, EIP712 { } function _permit(address spender, uint256 tokenId, uint256 deadline, bytes memory sig) internal virtual { + // solhint-disable-next-line not-rely-on-time if (deadline < block.timestamp) { revert PermitExpired(); } @@ -99,7 +101,7 @@ abstract contract ERC721HybridPermit is ERC721Hybrid, IERC4494, EIP712 { return; } - address recoveredSigner; + address recoveredSigner = address(0); // EOA signature validation if (sig.length == 64) { @@ -152,6 +154,7 @@ abstract contract ERC721HybridPermit is ERC721Hybrid, IERC4494, EIP712 { * @return True if the signature is valid according to EIP-1271, otherwise false. */ function _isValidERC1271Signature(address spender, bytes32 digest, bytes memory sig) private view returns (bool) { + // slither-disable-next-line low-level-calls (bool success, bytes memory res) = spender.staticcall( abi.encodeWithSelector(IERC1271.isValidSignature.selector, digest, sig) ); diff --git a/contracts/token/erc721/abstract/ERC721Permit.sol b/contracts/token/erc721/abstract/ERC721Permit.sol index 99026027..321f4c7b 100644 --- a/contracts/token/erc721/abstract/ERC721Permit.sol +++ b/contracts/token/erc721/abstract/ERC721Permit.sol @@ -2,13 +2,12 @@ // SPDX-License-Identifier: Apache 2.0 pragma solidity 0.8.19; -import "@openzeppelin/contracts/access/Ownable.sol"; -import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; -import "@openzeppelin/contracts/utils/cryptography/EIP712.sol"; -import "@openzeppelin/contracts/interfaces/IERC1271.sol"; -import "solidity-bytes-utils/contracts/BytesLib.sol"; -import "./IERC4494.sol"; -import "@openzeppelin/contracts/token/ERC721/extensions/ERC721Burnable.sol"; +import {ECDSA} from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; +import {EIP712} from "@openzeppelin/contracts/utils/cryptography/EIP712.sol"; +import {IERC1271} from "@openzeppelin/contracts/interfaces/IERC1271.sol"; +import {BytesLib} from "solidity-bytes-utils/contracts/BytesLib.sol"; +import {IERC4494} from "./IERC4494.sol"; +import {ERC721, ERC721Burnable, IERC165} from "@openzeppelin/contracts/token/ERC721/extensions/ERC721Burnable.sol"; // Errors import {IImmutableERC721Errors} from "../../../errors/Errors.sol"; @@ -17,30 +16,26 @@ import {IImmutableERC721Errors} from "../../../errors/Errors.sol"; * @dev This contract implements ERC-4494 as well, allowing tokens to be approved via off-chain signed messages. */ -abstract contract ERC721Permit is ERC721Burnable, IERC4494, EIP712, IImmutableERC721Errors{ - +abstract contract ERC721Permit is ERC721Burnable, IERC4494, EIP712, IImmutableERC721Errors { /** @notice mapping used to keep track of nonces of each token ID for validating * signatures */ - mapping(uint256 => uint256) private _nonces; - + mapping(uint256 tokenId => uint256 nonce) private _nonces; /** @dev the unique identifier for the permit struct to be EIP 712 compliant */ - bytes32 private constant _PERMIT_TYPEHASH = keccak256( - abi.encodePacked( - "Permit(", + bytes32 private constant _PERMIT_TYPEHASH = + keccak256( + abi.encodePacked( + "Permit(", "address spender," "uint256 tokenId," "uint256 nonce," "uint256 deadline" - ")" - ) - ); + ")" + ) + ); - constructor(string memory name, string memory symbol) - ERC721(name, symbol) - EIP712(name, "1") - {} + constructor(string memory name, string memory symbol) ERC721(name, symbol) EIP712(name, "1") {} /** * @notice Function to approve by way of owner signature @@ -49,12 +44,7 @@ abstract contract ERC721Permit is ERC721Burnable, IERC4494, EIP712, IImmutableER * @param deadline a timestamp expiry for the permit * @param sig a traditional or EIP-2098 signature */ - function permit( - address spender, - uint256 tokenId, - uint256 deadline, - bytes memory sig - ) external override { + function permit(address spender, uint256 tokenId, uint256 deadline, bytes memory sig) external override { _permit(spender, tokenId, deadline, sig); } @@ -63,9 +53,7 @@ abstract contract ERC721Permit is ERC721Burnable, IERC4494, EIP712, IImmutableER * @param tokenId The ID of the token for which to retrieve the nonce. * @return Current nonce of the given token. */ - function nonces( - uint256 tokenId - ) external view returns (uint256) { + function nonces(uint256 tokenId) external view returns (uint256) { return _nonces[tokenId]; } @@ -73,6 +61,7 @@ abstract contract ERC721Permit is ERC721Burnable, IERC4494, EIP712, IImmutableER * @notice Returns the domain separator used in the encoding of the signature for permits, as defined by EIP-712 * @return the bytes32 domain separator */ + // solhint-disable-next-line func-name-mixedcase function DOMAIN_SEPARATOR() external view override returns (bytes32) { return _domainSeparatorV4(); } @@ -82,16 +71,10 @@ abstract contract ERC721Permit is ERC721Burnable, IERC4494, EIP712, IImmutableER * @param interfaceId The interface identifier, which is a 4-byte selector. * @return True if the contract implements `interfaceId` and the call doesn't revert, otherwise false. */ - function supportsInterface(bytes4 interfaceId) - public - view - virtual - override(IERC165, ERC721) - returns (bool) - { - return - interfaceId == type(IERC4494).interfaceId || // 0x5604e225 - super.supportsInterface(interfaceId); + function supportsInterface(bytes4 interfaceId) public view virtual override(IERC165, ERC721) returns (bool) { + return + interfaceId == type(IERC4494).interfaceId || // 0x5604e225 + super.supportsInterface(interfaceId); } /** @@ -100,21 +83,13 @@ abstract contract ERC721Permit is ERC721Burnable, IERC4494, EIP712, IImmutableER * @param to The address to which the token is being transferred. * @param tokenId The ID of the token being transferred. */ - function _transfer( - address from, - address to, - uint256 tokenId - ) internal virtual override(ERC721){ + function _transfer(address from, address to, uint256 tokenId) internal virtual override(ERC721) { _nonces[tokenId]++; super._transfer(from, to, tokenId); } - function _permit( - address spender, - uint256 tokenId, - uint256 deadline, - bytes memory sig - ) internal virtual { + function _permit(address spender, uint256 tokenId, uint256 deadline, bytes memory sig) internal virtual { + // solhint-disable-next-line not-rely-on-time if (deadline < block.timestamp) { revert PermitExpired(); } @@ -127,7 +102,7 @@ abstract contract ERC721Permit is ERC721Burnable, IERC4494, EIP712, IImmutableER return; } - address recoveredSigner; + address recoveredSigner = address(0); // EOA signature validation if (sig.length == 64) { @@ -158,22 +133,8 @@ abstract contract ERC721Permit is ERC721Burnable, IERC4494, EIP712, IImmutableER * @param deadline The deadline until which the permit is valid. * @return A bytes32 digest, EIP-712 compliant, that serves as a unique identifier for the permit. */ - function _buildPermitDigest( - address spender, - uint256 tokenId, - uint256 deadline - ) internal view returns (bytes32) { - return _hashTypedDataV4( - keccak256( - abi.encode( - _PERMIT_TYPEHASH, - spender, - tokenId, - _nonces[tokenId], - deadline - ) - ) - ); + function _buildPermitDigest(address spender, uint256 tokenId, uint256 deadline) internal view returns (bytes32) { + return _hashTypedDataV4(keccak256(abi.encode(_PERMIT_TYPEHASH, spender, tokenId, _nonces[tokenId], deadline))); } /** @@ -182,7 +143,7 @@ abstract contract ERC721Permit is ERC721Burnable, IERC4494, EIP712, IImmutableER * @param tokenId The token id. * @return True if the signature is from an approved operator or owner, otherwise false. */ - function _isValidEOASignature(address recoveredSigner, uint256 tokenId) private view returns(bool) { + function _isValidEOASignature(address recoveredSigner, uint256 tokenId) private view returns (bool) { return recoveredSigner != address(0) && _isApprovedOrOwner(recoveredSigner, tokenId); } @@ -193,13 +154,10 @@ abstract contract ERC721Permit is ERC721Burnable, IERC4494, EIP712, IImmutableER * @param sig The actual signature bytes. * @return True if the signature is valid according to EIP-1271, otherwise false. */ - function _isValidERC1271Signature(address spender, bytes32 digest, bytes memory sig) private view returns(bool) { + function _isValidERC1271Signature(address spender, bytes32 digest, bytes memory sig) private view returns (bool) { + // slither-disable-next-line low-level-calls (bool success, bytes memory res) = spender.staticcall( - abi.encodeWithSelector( - IERC1271.isValidSignature.selector, - digest, - sig - ) + abi.encodeWithSelector(IERC1271.isValidSignature.selector, digest, sig) ); if (success && res.length == 32) { diff --git a/contracts/token/erc721/abstract/IERC4494.sol b/contracts/token/erc721/abstract/IERC4494.sol index 37b7023d..89754fef 100644 --- a/contracts/token/erc721/abstract/IERC4494.sol +++ b/contracts/token/erc721/abstract/IERC4494.sol @@ -2,29 +2,30 @@ // SPDX-License-Identifier: Apache 2.0 pragma solidity 0.8.19; -import "@openzeppelin/contracts/interfaces/IERC165.sol"; +import {IERC165} from "@openzeppelin/contracts/interfaces/IERC165.sol"; /// /// @dev Interface for token permits for ERC721 /// interface IERC4494 is IERC165 { - /// ERC165 bytes to add to interface array - set in parent contract - /// - /// _INTERFACE_ID_ERC4494 = 0x5604e225 + /// ERC165 bytes to add to interface array - set in parent contract + /// + /// _INTERFACE_ID_ERC4494 = 0x5604e225 - /// @notice Function to approve by way of owner signature - /// @param spender the address to approve - /// @param tokenId the index of the NFT to approve the spender on - /// @param deadline a timestamp expiry for the permit - /// @param sig a traditional or EIP-2098 signature - function permit(address spender, uint256 tokenId, uint256 deadline, bytes memory sig) external; + /// @notice Function to approve by way of owner signature + /// @param spender the address to approve + /// @param tokenId the index of the NFT to approve the spender on + /// @param deadline a timestamp expiry for the permit + /// @param sig a traditional or EIP-2098 signature + function permit(address spender, uint256 tokenId, uint256 deadline, bytes memory sig) external; - /// @notice Returns the nonce of an NFT - useful for creating permits - /// @param tokenId the index of the NFT to get the nonce of - /// @return the uint256 representation of the nonce - function nonces(uint256 tokenId) external view returns(uint256); + /// @notice Returns the nonce of an NFT - useful for creating permits + /// @param tokenId the index of the NFT to get the nonce of + /// @return the uint256 representation of the nonce + function nonces(uint256 tokenId) external view returns (uint256); - /// @notice Returns the domain separator used in the encoding of the signature for permits, as defined by EIP-712 - /// @return the bytes32 domain separator - function DOMAIN_SEPARATOR() external view returns(bytes32); + /// @notice Returns the domain separator used in the encoding of the signature for permits, as defined by EIP-712 + /// @return the bytes32 domain separator + // solhint-disable-next-line func-name-mixedcase + function DOMAIN_SEPARATOR() external view returns (bytes32); } diff --git a/contracts/token/erc721/abstract/ImmutableERC721Base.sol b/contracts/token/erc721/abstract/ImmutableERC721Base.sol index 900719ee..fd495799 100644 --- a/contracts/token/erc721/abstract/ImmutableERC721Base.sol +++ b/contracts/token/erc721/abstract/ImmutableERC721Base.sol @@ -3,16 +3,15 @@ pragma solidity 0.8.19; // Token -import "./ERC721Permit.sol"; +import {ERC721Permit, ERC721, ERC721Burnable} from "./ERC721Permit.sol"; // Allowlist -import "@openzeppelin/contracts/token/common/ERC2981.sol"; -import "../../../allowlist/OperatorAllowlistEnforced.sol"; +import {ERC2981} from "@openzeppelin/contracts/token/common/ERC2981.sol"; +import {OperatorAllowlistEnforced} from "../../../allowlist/OperatorAllowlistEnforced.sol"; // Utils -import "@openzeppelin/contracts/utils/structs/BitMaps.sol"; -import { AccessControlEnumerable, MintingAccessControl } from "./MintingAccessControl.sol"; - +import {BitMaps} from "@openzeppelin/contracts/utils/structs/BitMaps.sol"; +import {AccessControlEnumerable, MintingAccessControl} from "./MintingAccessControl.sol"; /* ImmutableERC721Base is an abstract contract that offers minimum preset functionality without @@ -20,12 +19,7 @@ import { AccessControlEnumerable, MintingAccessControl } from "./MintingAccessCo own minting functionality to meet the needs of the inheriting contract. */ -abstract contract ImmutableERC721Base is - OperatorAllowlistEnforced, - MintingAccessControl, - ERC721Permit, - ERC2981 -{ +abstract contract ImmutableERC721Base is OperatorAllowlistEnforced, MintingAccessControl, ERC721Permit, ERC2981 { using BitMaps for BitMaps.BitMap; /// ===== State Variables ===== @@ -58,7 +52,7 @@ abstract contract ImmutableERC721Base is } /// @notice A mapping of tokens that have been burned to prevent re-minting - BitMaps.BitMap _burnedTokens; + BitMaps.BitMap private _burnedTokens; /// ===== Constructor ===== @@ -96,7 +90,7 @@ abstract contract ImmutableERC721Base is * @param receiver the address to receive the royalty * @param feeNumerator the royalty fee numerator * @dev This can only be called by the an admin. See ERC2981 for more details on _setDefaultRoyalty - */ + */ function setDefaultRoyaltyReceiver(address receiver, uint96 feeNumerator) public onlyRole(DEFAULT_ADMIN_ROLE) { _setDefaultRoyalty(receiver, feeNumerator); } @@ -106,7 +100,7 @@ abstract contract ImmutableERC721Base is * @param receiver the address to receive the royalty * @param feeNumerator the royalty fee numerator * @dev This can only be called by the a minter. See ERC2981 for more details on _setTokenRoyalty - */ + */ function setNFTRoyaltyReceiver( uint256 tokenId, address receiver, @@ -120,13 +114,13 @@ abstract contract ImmutableERC721Base is * @param receiver the address to receive the royalty * @param feeNumerator the royalty fee numerator * @dev This can only be called by the a minter. See ERC2981 for more details on _setTokenRoyalty - */ + */ function setNFTRoyaltyReceiverBatch( uint256[] calldata tokenIds, address receiver, uint96 feeNumerator ) public onlyRole(MINTER_ROLE) { - for (uint i = 0; i < tokenIds.length; i++) { + for (uint256 i = 0; i < tokenIds.length; i++) { _setTokenRoyalty(tokenIds[i], receiver, feeNumerator); } } @@ -138,6 +132,7 @@ abstract contract ImmutableERC721Base is function burn(uint256 tokenId) public override(ERC721Burnable) { super.burn(tokenId); _burnedTokens.set(tokenId); + // slither-disable-next-line costly-loop _totalSupply--; } @@ -158,9 +153,9 @@ abstract contract ImmutableERC721Base is * @param burns list of burn requests including token id and owner address */ function _safeBurnBatch(IDBurn[] calldata burns) public virtual { - for (uint i = 0; i < burns.length; i++) { + for (uint256 i = 0; i < burns.length; i++) { IDBurn calldata b = burns[i]; - for (uint j = 0; j < b.tokenIds.length; j++) { + for (uint256 j = 0; j < b.tokenIds.length; j++) { safeBurn(b.owner, b.tokenIds[j]); } } @@ -192,7 +187,7 @@ abstract contract ImmutableERC721Base is /** @notice Returns the supported interfaces * @param interfaceId the interface to check for support - */ + */ function supportsInterface( bytes4 interfaceId ) @@ -240,12 +235,12 @@ abstract contract ImmutableERC721Base is if (mintRequest.to == address(0)) { revert IImmutableERC721SendingToZerothAddress(); } - + + // slither-disable-next-line costly-loop _totalSupply = _totalSupply + mintRequest.tokenIds.length; for (uint256 j = 0; j < mintRequest.tokenIds.length; j++) { _mint(mintRequest.to, mintRequest.tokenIds[j]); } - } /** @notice safe mints a batch of tokens with specified ids to a specified address @@ -259,6 +254,7 @@ abstract contract ImmutableERC721Base is for (uint256 j; j < mintRequest.tokenIds.length; j++) { _safeMint(mintRequest.to, mintRequest.tokenIds[j]); } + // slither-disable-next-line costly-loop _totalSupply = _totalSupply + mintRequest.tokenIds.length; } @@ -290,5 +286,4 @@ abstract contract ImmutableERC721Base is function _baseURI() internal view virtual override(ERC721) returns (string memory) { return baseURI; } - } diff --git a/contracts/token/erc721/abstract/ImmutableERC721HybridBase.sol b/contracts/token/erc721/abstract/ImmutableERC721HybridBase.sol index 534d12bc..b4285487 100644 --- a/contracts/token/erc721/abstract/ImmutableERC721HybridBase.sol +++ b/contracts/token/erc721/abstract/ImmutableERC721HybridBase.sol @@ -2,21 +2,24 @@ // SPDX-License-Identifier: Apache 2.0 pragma solidity 0.8.19; -import { AccessControlEnumerable, MintingAccessControl } from "./MintingAccessControl.sol"; -import { ERC2981 } from "@openzeppelin/contracts/token/common/ERC2981.sol"; -import { OperatorAllowlistEnforced } from "../../../allowlist/OperatorAllowlistEnforced.sol"; -import { ERC721HybridPermit } from "./ERC721HybridPermit.sol"; -import { ERC721Hybrid } from "./ERC721Hybrid.sol"; - -abstract contract ImmutableERC721HybridBase is OperatorAllowlistEnforced, MintingAccessControl, ERC2981, ERC721HybridPermit { +import {AccessControlEnumerable, MintingAccessControl} from "./MintingAccessControl.sol"; +import {ERC2981} from "@openzeppelin/contracts/token/common/ERC2981.sol"; +import {OperatorAllowlistEnforced} from "../../../allowlist/OperatorAllowlistEnforced.sol"; +import {ERC721HybridPermit} from "./ERC721HybridPermit.sol"; +import {ERC721Hybrid} from "./ERC721Hybrid.sol"; +abstract contract ImmutableERC721HybridBase is + OperatorAllowlistEnforced, + MintingAccessControl, + ERC2981, + ERC721HybridPermit +{ /// @notice Contract level metadata string public contractURI; /// @notice Common URIs for individual token URIs string public baseURI; - /** * @notice Grants `DEFAULT_ADMIN_ROLE` to the supplied `owner` address * @param owner_ The address to grant the `DEFAULT_ADMIN_ROLE` to @@ -38,7 +41,7 @@ abstract contract ImmutableERC721HybridBase is OperatorAllowlistEnforced, Mintin address operatorAllowlist_, address receiver_, uint96 feeNumerator_ - )ERC721HybridPermit(name_, symbol_) { + ) ERC721HybridPermit(name_, symbol_) { // Initialize state variables _grantRole(DEFAULT_ADMIN_ROLE, owner_); _setDefaultRoyalty(receiver_, feeNumerator_); @@ -119,7 +122,7 @@ abstract contract ImmutableERC721HybridBase is OperatorAllowlistEnforced, Mintin function setDefaultRoyaltyReceiver(address receiver, uint96 feeNumerator) public onlyRole(DEFAULT_ADMIN_ROLE) { _setDefaultRoyalty(receiver, feeNumerator); } - + /** @notice Set the royalty receiver address for a specific tokenId * @param tokenId the token to set the royalty for * @param receiver the address to receive the royalty @@ -139,13 +142,13 @@ abstract contract ImmutableERC721HybridBase is OperatorAllowlistEnforced, Mintin * @param receiver the address to receive the royalty * @param feeNumerator the royalty fee numerator * @dev This can only be called by the a minter. See ERC2981 for more details on _setTokenRoyalty - */ + */ function setNFTRoyaltyReceiverBatch( uint256[] calldata tokenIds, address receiver, uint96 feeNumerator ) public onlyRole(MINTER_ROLE) { - for (uint i = 0; i < tokenIds.length; i++) { + for (uint256 i = 0; i < tokenIds.length; i++) { _setTokenRoyalty(tokenIds[i], receiver, feeNumerator); } } diff --git a/contracts/token/erc721/abstract/MintingAccessControl.sol b/contracts/token/erc721/abstract/MintingAccessControl.sol index a363a1d4..53564302 100644 --- a/contracts/token/erc721/abstract/MintingAccessControl.sol +++ b/contracts/token/erc721/abstract/MintingAccessControl.sol @@ -5,11 +5,10 @@ pragma solidity 0.8.19; import {AccessControlEnumerable} from "@openzeppelin/contracts/access/AccessControlEnumerable.sol"; abstract contract MintingAccessControl is AccessControlEnumerable { - /// @notice Role to mint tokens bytes32 public constant MINTER_ROLE = bytes32("MINTER_ROLE"); - /** @notice Allows admin grant `user` `MINTER` role + /** @notice Allows admin grant `user` `MINTER` role * @param user The address to grant the `MINTER` role to */ function grantMinterRole(address user) public onlyRole(DEFAULT_ADMIN_ROLE) { @@ -23,7 +22,7 @@ abstract contract MintingAccessControl is AccessControlEnumerable { revokeRole(MINTER_ROLE, user); } - /** @notice Returns the addresses which have DEFAULT_ADMIN_ROLE */ + /** @notice Returns the addresses which have DEFAULT_ADMIN_ROLE */ function getAdmins() public view returns (address[] memory) { uint256 adminCount = getRoleMemberCount(DEFAULT_ADMIN_ROLE); address[] memory admins = new address[](adminCount); diff --git a/contracts/token/erc721/erc721psi/ERC721Psi.sol b/contracts/token/erc721/erc721psi/ERC721Psi.sol index d87f55ca..6475fdfc 100644 --- a/contracts/token/erc721/erc721psi/ERC721Psi.sol +++ b/contracts/token/erc721/erc721psi/ERC721Psi.sol @@ -11,7 +11,7 @@ - npm: https://www.npmjs.com/package/erc721psi */ - +// solhint-disable pragma solidity 0.8.19; import "@openzeppelin/contracts/token/ERC721/IERC721.sol"; @@ -96,7 +96,7 @@ contract ERC721Psi is Context, ERC165, IERC721, IERC721Metadata { function balanceOf(address owner) public view virtual override returns (uint) { require(owner != address(0), "ERC721Psi: balance query for the zero address"); - uint count; + uint count = 0; for (uint i = _startTokenId(); i < _nextTokenId(); ++i) { if (_exists(i)) { if (owner == ownerOf(i)) { @@ -150,6 +150,7 @@ contract ERC721Psi is Context, ERC165, IERC721, IERC721Metadata { * token will be the concatenation of the `baseURI` and the `tokenId`. Empty * by default, can be overriden in child contracts. */ + // slither-disable-next-line dead-code function _baseURI() internal view virtual returns (string memory) { return ""; } @@ -412,6 +413,7 @@ contract ERC721Psi is Context, ERC165, IERC721, IERC721Metadata { if (to.isContract()) { r = true; for (uint256 tokenId = startTokenId; tokenId < startTokenId + quantity; tokenId++) { + // slither-disable-start calls-loop try IERC721Receiver(to).onERC721Received(_msgSender(), from, tokenId, _data) returns (bytes4 retval) { r = r && retval == IERC721Receiver.onERC721Received.selector; } catch (bytes memory reason) { @@ -423,6 +425,7 @@ contract ERC721Psi is Context, ERC165, IERC721, IERC721Metadata { } } } + // slither-disable-end calls-loop } return r; } else { @@ -450,6 +453,7 @@ contract ERC721Psi is Context, ERC165, IERC721, IERC721Metadata { * transferred to `to`. * - When `from` is zero, `tokenId` will be minted for `to`. */ + // solhint-disable-next-line no-empty-blocks function _beforeTokenTransfers(address from, address to, uint256 startTokenId, uint256 quantity) internal virtual {} /** @@ -464,5 +468,6 @@ contract ERC721Psi is Context, ERC165, IERC721, IERC721Metadata { * - when `from` and `to` are both non-zero. * - `from` and `to` are never both zero. */ + // solhint-disable-next-line no-empty-blocks function _afterTokenTransfers(address from, address to, uint256 startTokenId, uint256 quantity) internal virtual {} } diff --git a/contracts/token/erc721/erc721psi/ERC721PsiBurnable.sol b/contracts/token/erc721/erc721psi/ERC721PsiBurnable.sol index daee96b5..bd96169d 100644 --- a/contracts/token/erc721/erc721psi/ERC721PsiBurnable.sol +++ b/contracts/token/erc721/erc721psi/ERC721PsiBurnable.sol @@ -11,8 +11,8 @@ */ pragma solidity 0.8.19; -import "solidity-bits/contracts/BitMaps.sol"; -import "./ERC721Psi.sol"; +import {BitMaps} from "solidity-bits/contracts/BitMaps.sol"; +import {ERC721Psi} from "./ERC721Psi.sol"; abstract contract ERC721PsiBurnable is ERC721Psi { using BitMaps for BitMaps.BitMap; diff --git a/contracts/token/erc721/preset/ImmutableERC721.sol b/contracts/token/erc721/preset/ImmutableERC721.sol index 43e63187..c2caf870 100644 --- a/contracts/token/erc721/preset/ImmutableERC721.sol +++ b/contracts/token/erc721/preset/ImmutableERC721.sol @@ -2,8 +2,7 @@ // SPDX-License-Identifier: Apache 2.0 pragma solidity 0.8.19; -import { MintingAccessControl } from "../abstract/MintingAccessControl.sol"; -import { ImmutableERC721HybridBase } from "../abstract/ImmutableERC721HybridBase.sol"; +import {ImmutableERC721HybridBase} from "../abstract/ImmutableERC721HybridBase.sol"; contract ImmutableERC721 is ImmutableERC721HybridBase { /// ===== Constructor ===== @@ -88,7 +87,7 @@ contract ImmutableERC721 is ImmutableERC721HybridBase { function safeMintBatchByQuantity(Mint[] calldata mints) external onlyRole(MINTER_ROLE) { _safeMintBatchByQuantity(mints); } - + /** @notice Allows minter to safe mint a number of tokens by ID to a number of specified * addresses with hooks and checks. Check ERC721Hybrid for details on _mintBatchByIDToMultiple * @param mints the list of IDMint struct containing the to, and tokenIds @@ -121,7 +120,7 @@ contract ImmutableERC721 is ImmutableERC721HybridBase { revert IImmutableERC721MismatchedTransferLengths(); } - for (uint i = 0; i < tr.tokenIds.length; i++) { + for (uint256 i = 0; i < tr.tokenIds.length; i++) { safeTransferFrom(tr.from, tr.tos[i], tr.tokenIds[i]); } } diff --git a/contracts/token/erc721/preset/ImmutableERC721MintByID.sol b/contracts/token/erc721/preset/ImmutableERC721MintByID.sol index 182b387f..5259112f 100644 --- a/contracts/token/erc721/preset/ImmutableERC721MintByID.sol +++ b/contracts/token/erc721/preset/ImmutableERC721MintByID.sol @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache 2.0 pragma solidity 0.8.19; -import "../abstract/ImmutableERC721Base.sol"; +import {ImmutableERC721Base} from "../abstract/ImmutableERC721Base.sol"; contract ImmutableERC721MintByID is ImmutableERC721Base { /// ===== Constructor ===== @@ -29,10 +29,18 @@ contract ImmutableERC721MintByID is ImmutableERC721Base { address royaltyReceiver_, uint96 feeNumerator_ ) - ImmutableERC721Base(owner_, name_, symbol_, baseURI_, contractURI_, operatorAllowlist_, royaltyReceiver_, feeNumerator_) + ImmutableERC721Base( + owner_, + name_, + symbol_, + baseURI_, + contractURI_, + operatorAllowlist_, + royaltyReceiver_, + feeNumerator_ + ) {} - /** @notice Allows minter to mint `tokenID` to `to` * @param to the address to mint the token to * @param tokenID the ID of the token to mint @@ -76,7 +84,7 @@ contract ImmutableERC721MintByID is ImmutableERC721Base { * @param tokenIDs an array of token IDs to burn */ function burnBatch(uint256[] calldata tokenIDs) external { - for (uint i = 0; i < tokenIDs.length; i++) { + for (uint256 i = 0; i < tokenIDs.length; i++) { burn(tokenIDs[i]); } } @@ -98,7 +106,7 @@ contract ImmutableERC721MintByID is ImmutableERC721Base { revert IImmutableERC721MismatchedTransferLengths(); } - for (uint i = 0; i < tr.tokenIds.length; i++) { + for (uint256 i = 0; i < tr.tokenIds.length; i++) { safeTransferFrom(tr.from, tr.tos[i], tr.tokenIds[i]); } } diff --git a/contracts/token/erc721/x/Asset.sol b/contracts/token/erc721/x/Asset.sol index 9386a1cc..0f4edda4 100644 --- a/contracts/token/erc721/x/Asset.sol +++ b/contracts/token/erc721/x/Asset.sol @@ -1,9 +1,11 @@ // SPDX-License-Identifier: MIT +// solhint-disable compiler-version pragma solidity ^0.8.4; -import { ERC721 } from "@openzeppelin/contracts/token/ERC721/ERC721.sol"; -import { Mintable } from "./Mintable.sol"; +import {ERC721} from "@openzeppelin/contracts/token/ERC721/ERC721.sol"; +import {Mintable} from "./Mintable.sol"; +// slither-disable-start missing-inheritance contract Asset is ERC721, Mintable { constructor( address _owner, @@ -12,11 +14,8 @@ contract Asset is ERC721, Mintable { address _imx ) ERC721(_name, _symbol) Mintable(_owner, _imx) {} - function _mintFor( - address user, - uint256 id, - bytes memory - ) internal override { + function _mintFor(address user, uint256 id, bytes memory) internal override { _safeMint(user, id); } -} \ No newline at end of file +} +// slither-disable-end missing-inheritance diff --git a/contracts/token/erc721/x/IMintable.sol b/contracts/token/erc721/x/IMintable.sol index ea0229ca..d458f07d 100644 --- a/contracts/token/erc721/x/IMintable.sol +++ b/contracts/token/erc721/x/IMintable.sol @@ -1,10 +1,7 @@ // SPDX-License-Identifier: MIT +// solhint-disable compiler-version pragma solidity ^0.8.4; interface IMintable { - function mintFor( - address to, - uint256 quantity, - bytes calldata mintingBlob - ) external; -} \ No newline at end of file + function mintFor(address to, uint256 quantity, bytes calldata mintingBlob) external; +} diff --git a/contracts/token/erc721/x/Mintable.sol b/contracts/token/erc721/x/Mintable.sol index d20eb2dc..0f8987ab 100644 --- a/contracts/token/erc721/x/Mintable.sol +++ b/contracts/token/erc721/x/Mintable.sol @@ -1,13 +1,14 @@ // SPDX-License-Identifier: MIT +// solhint-disable compiler-version, custom-errors, reason-string pragma solidity ^0.8.4; -import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; -import { IMintable } from "./IMintable.sol"; -import { Minting } from "./utils/Minting.sol"; +import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; +import {IMintable} from "./IMintable.sol"; +import {Minting} from "./utils/Minting.sol"; abstract contract Mintable is Ownable, IMintable { - address public imx; - mapping(uint256 => bytes) public blueprints; + address public immutable imx; + mapping(uint256 id => bytes blueprint) public blueprints; event AssetMinted(address to, uint256 id, bytes blueprint); @@ -22,11 +23,7 @@ abstract contract Mintable is Ownable, IMintable { _; } - function mintFor( - address user, - uint256 quantity, - bytes calldata mintingBlob - ) external override onlyOwnerOrIMX { + function mintFor(address user, uint256 quantity, bytes calldata mintingBlob) external override onlyOwnerOrIMX { require(quantity == 1, "Mintable: invalid quantity"); (uint256 id, bytes memory blueprint) = Minting.split(mintingBlob); _mintFor(user, id, blueprint); @@ -34,9 +31,5 @@ abstract contract Mintable is Ownable, IMintable { emit AssetMinted(user, id, blueprint); } - function _mintFor( - address to, - uint256 id, - bytes memory blueprint - ) internal virtual; -} \ No newline at end of file + function _mintFor(address to, uint256 id, bytes memory blueprint) internal virtual; +} diff --git a/contracts/token/erc721/x/utils/Bytes.sol b/contracts/token/erc721/x/utils/Bytes.sol index ae0c3013..fad2514d 100644 --- a/contracts/token/erc721/x/utils/Bytes.sol +++ b/contracts/token/erc721/x/utils/Bytes.sol @@ -1,6 +1,8 @@ // SPDX-License-Identifier: MIT +// solhint-disable compiler-version, custom-errors, reason-string pragma solidity ^0.8.4; +// slither-disable-start dead-code library Bytes { /** * @dev Converts a `uint256` to a `string`. @@ -27,8 +29,6 @@ library Bytes { return string(buffer); } - bytes constant alphabet = "0123456789abcdef"; - /** * Index Of * @@ -45,11 +45,7 @@ library Bytes { * @return int The position of the needle starting from 0 and returning -1 * in the case of no matches found */ - function indexOf( - bytes memory _base, - string memory _value, - uint256 _offset - ) internal pure returns (int256) { + function indexOf(bytes memory _base, string memory _value, uint256 _offset) internal pure returns (int256) { bytes memory _valueBytes = bytes(_value); assert(_valueBytes.length == 1); @@ -89,4 +85,5 @@ library Bytes { } return result; } -} \ No newline at end of file +} +// slither-disable-end dead-code diff --git a/contracts/token/erc721/x/utils/Minting.sol b/contracts/token/erc721/x/utils/Minting.sol index ae5fe076..c87776d6 100644 --- a/contracts/token/erc721/x/utils/Minting.sol +++ b/contracts/token/erc721/x/utils/Minting.sol @@ -1,17 +1,14 @@ // SPDX-License-Identifier: MIT +// solhint-disable compiler-version, custom-errors pragma solidity ^0.8.4; -import { Bytes } from "./Bytes.sol"; +import {Bytes} from "./Bytes.sol"; library Minting { // Split the minting blob into token_id and blueprint portions // {token_id}:{blueprint} - function split(bytes calldata blob) - internal - pure - returns (uint256, bytes memory) - { + function split(bytes calldata blob) internal pure returns (uint256, bytes memory) { int256 index = Bytes.indexOf(blob, ":", 0); require(index >= 0, "Separator must exist"); // Trim the { and } from the parameters @@ -23,4 +20,4 @@ library Minting { bytes calldata blueprint = blob[uint256(index) + 2:blob.length - 1]; return (tokenID, blueprint); } -} \ No newline at end of file +} diff --git a/contracts/trading/seaport/ImmutableSeaport.sol b/contracts/trading/seaport/ImmutableSeaport.sol index 3b37bfa9..8b1ea8ed 100644 --- a/contracts/trading/seaport/ImmutableSeaport.sol +++ b/contracts/trading/seaport/ImmutableSeaport.sol @@ -1,23 +1,13 @@ // Copyright (c) Immutable Pty Ltd 2018 - 2023 // SPDX-License-Identifier: Apache-2 +// solhint-disable compiler-version pragma solidity 0.8.17; -import { Consideration } from "seaport-core/src/lib/Consideration.sol"; -import { - AdvancedOrder, - BasicOrderParameters, - CriteriaResolver, - Execution, - Fulfillment, - FulfillmentComponent, - Order, - OrderComponents -} from "seaport-types/src/lib/ConsiderationStructs.sol"; -import { OrderType } from "seaport-types/src/lib/ConsiderationEnums.sol"; -import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; -import { - ImmutableSeaportEvents -} from "./interfaces/ImmutableSeaportEvents.sol"; +import {Consideration} from "seaport-core/src/lib/Consideration.sol"; +import {AdvancedOrder, BasicOrderParameters, CriteriaResolver, Execution, Fulfillment, FulfillmentComponent, Order} from "seaport-types/src/lib/ConsiderationStructs.sol"; +import {OrderType} from "seaport-types/src/lib/ConsiderationEnums.sol"; +import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; +import {ImmutableSeaportEvents} from "./interfaces/ImmutableSeaportEvents.sol"; /** * @title ImmutableSeaport @@ -29,13 +19,10 @@ import { * spent (the "offer") along with an arbitrary number of items that must * be received back by the indicated recipients (the "consideration"). */ -contract ImmutableSeaport is - Consideration, - Ownable, - ImmutableSeaportEvents -{ +contract ImmutableSeaport is Consideration, Ownable, ImmutableSeaportEvents { // Mapping to store valid ImmutableZones - this allows for multiple Zones // to be active at the same time, and can be expired or added on demand. + // solhint-disable-next-line named-parameters-mapping mapping(address => bool) public allowedZones; error OrderNotRestricted(); @@ -51,10 +38,7 @@ contract ImmutableSeaport is * @param owner The address of the owner of this contract. Specified in the * constructor to be CREATE2 / CREATE3 compatible. */ - constructor( - address conduitController, - address owner - ) Consideration(conduitController) Ownable() { + constructor(address conduitController, address owner) Consideration(conduitController) Ownable() { // Transfer ownership to the address specified in the constructor _transferOwnership(owner); } @@ -84,6 +68,7 @@ contract ImmutableSeaport is * * @return The name of this contract as a string. */ + // slither-disable-next-line dead-code function _nameString() internal pure override returns (string memory) { // Return the name of the contract. return "ImmutableSeaport"; @@ -127,10 +112,7 @@ contract ImmutableSeaport is BasicOrderParameters calldata parameters ) public payable virtual override returns (bool fulfilled) { // All restricted orders are captured using this method - if ( - uint(parameters.basicOrderType) % 4 != 2 && - uint(parameters.basicOrderType) % 4 != 3 - ) { + if (uint256(parameters.basicOrderType) % 4 != 2 && uint256(parameters.basicOrderType) % 4 != 3) { revert OrderNotRestricted(); } @@ -167,14 +149,12 @@ contract ImmutableSeaport is * @return fulfilled A boolean indicating whether the order has been * successfully fulfilled. */ + // solhint-disable-next-line func-name-mixedcase function fulfillBasicOrder_efficient_6GL6yc( BasicOrderParameters calldata parameters ) public payable virtual override returns (bool fulfilled) { // All restricted orders are captured using this method - if ( - uint(parameters.basicOrderType) % 4 != 2 && - uint(parameters.basicOrderType) % 4 != 3 - ) { + if (uint256(parameters.basicOrderType) % 4 != 2 && uint256(parameters.basicOrderType) % 4 != 3) { revert OrderNotRestricted(); } @@ -288,13 +268,7 @@ contract ImmutableSeaport is _rejectIfZoneInvalid(advancedOrder.parameters.zone); - return - super.fulfillAdvancedOrder( - advancedOrder, - criteriaResolvers, - fulfillerConduitKey, - recipient - ); + return super.fulfillAdvancedOrder(advancedOrder, criteriaResolvers, fulfillerConduitKey, recipient); } /** @@ -370,10 +344,7 @@ contract ImmutableSeaport is payable virtual override - returns ( - bool[] memory, - /* availableOrders */ Execution[] memory /* executions */ - ) + returns (bool[] memory, /* availableOrders */ Execution[] memory /* executions */) { for (uint256 i = 0; i < orders.length; i++) { Order memory order = orders[i]; @@ -499,18 +470,13 @@ contract ImmutableSeaport is payable virtual override - returns ( - bool[] memory, - /* availableOrders */ Execution[] memory /* executions */ - ) + returns (bool[] memory, /* availableOrders */ Execution[] memory /* executions */) { for (uint256 i = 0; i < advancedOrders.length; i++) { AdvancedOrder memory advancedOrder = advancedOrders[i]; if ( - advancedOrder.parameters.orderType != - OrderType.FULL_RESTRICTED && - advancedOrder.parameters.orderType != - OrderType.PARTIAL_RESTRICTED + advancedOrder.parameters.orderType != OrderType.FULL_RESTRICTED && + advancedOrder.parameters.orderType != OrderType.PARTIAL_RESTRICTED ) { revert OrderNotRestricted(); } @@ -568,13 +534,7 @@ contract ImmutableSeaport is * @custom:name fulfillments */ Fulfillment[] calldata fulfillments - ) - public - payable - virtual - override - returns (Execution[] memory /* executions */) - { + ) public payable virtual override returns (Execution[] memory /* executions */) { for (uint256 i = 0; i < orders.length; i++) { Order memory order = orders[i]; if ( @@ -655,20 +615,12 @@ contract ImmutableSeaport is */ Fulfillment[] calldata fulfillments, address recipient - ) - public - payable - virtual - override - returns (Execution[] memory /* executions */) - { + ) public payable virtual override returns (Execution[] memory /* executions */) { for (uint256 i = 0; i < advancedOrders.length; i++) { AdvancedOrder memory advancedOrder = advancedOrders[i]; if ( - advancedOrder.parameters.orderType != - OrderType.FULL_RESTRICTED && - advancedOrder.parameters.orderType != - OrderType.PARTIAL_RESTRICTED + advancedOrder.parameters.orderType != OrderType.FULL_RESTRICTED && + advancedOrder.parameters.orderType != OrderType.PARTIAL_RESTRICTED ) { revert OrderNotRestricted(); } @@ -676,12 +628,6 @@ contract ImmutableSeaport is _rejectIfZoneInvalid(advancedOrder.parameters.zone); } - return - super.matchAdvancedOrders( - advancedOrders, - criteriaResolvers, - fulfillments, - recipient - ); + return super.matchAdvancedOrders(advancedOrders, criteriaResolvers, fulfillments, recipient); } } diff --git a/contracts/trading/seaport/conduit/ConduitController.sol b/contracts/trading/seaport/conduit/ConduitController.sol index 11c02ae3..615bdb76 100644 --- a/contracts/trading/seaport/conduit/ConduitController.sol +++ b/contracts/trading/seaport/conduit/ConduitController.sol @@ -1,4 +1,5 @@ // SPDX-License-Identifier: MIT +// solhint-disable pragma solidity 0.8.14; -import { ConduitController } from "seaport-core/src/conduit/ConduitController.sol"; +import {ConduitController} from "seaport-core/src/conduit/ConduitController.sol"; diff --git a/contracts/trading/seaport/interfaces/ImmutableSeaportEvents.sol b/contracts/trading/seaport/interfaces/ImmutableSeaportEvents.sol index d57fa0c4..2000cb9b 100644 --- a/contracts/trading/seaport/interfaces/ImmutableSeaportEvents.sol +++ b/contracts/trading/seaport/interfaces/ImmutableSeaportEvents.sol @@ -1,5 +1,6 @@ // Copyright (c) Immutable Pty Ltd 2018 - 2023 // SPDX-License-Identifier: Apache-2 +// solhint-disable compiler-version pragma solidity 0.8.17; /** diff --git a/contracts/trading/seaport/test/SeaportTestContracts.sol b/contracts/trading/seaport/test/SeaportTestContracts.sol index 1e66da80..e9e6cf32 100644 --- a/contracts/trading/seaport/test/SeaportTestContracts.sol +++ b/contracts/trading/seaport/test/SeaportTestContracts.sol @@ -1,5 +1,6 @@ // Copyright (c) Immutable Pty Ltd 2018 - 2023 // SPDX-License-Identifier: Apache-2 +// solhint-disable pragma solidity >=0.8.4; /** diff --git a/contracts/trading/seaport/validators/ReadOnlyOrderValidator.sol b/contracts/trading/seaport/validators/ReadOnlyOrderValidator.sol index 8a823c82..d48f145b 100644 --- a/contracts/trading/seaport/validators/ReadOnlyOrderValidator.sol +++ b/contracts/trading/seaport/validators/ReadOnlyOrderValidator.sol @@ -1,4 +1,5 @@ // SPDX-License-Identifier: MIT +// solhint-disable pragma solidity 0.8.17; -import { ReadOnlyOrderValidator } from "seaport/contracts/helpers/order-validator/lib/ReadOnlyOrderValidator.sol"; +import {ReadOnlyOrderValidator} from "seaport/contracts/helpers/order-validator/lib/ReadOnlyOrderValidator.sol"; diff --git a/contracts/trading/seaport/validators/SeaportValidator.sol b/contracts/trading/seaport/validators/SeaportValidator.sol index b431bcb4..672acfa9 100644 --- a/contracts/trading/seaport/validators/SeaportValidator.sol +++ b/contracts/trading/seaport/validators/SeaportValidator.sol @@ -1,4 +1,5 @@ // SPDX-License-Identifier: MIT +// solhint-disable pragma solidity 0.8.17; -import { SeaportValidator } from "seaport/contracts/helpers/order-validator/SeaportValidator.sol"; +import {SeaportValidator} from "seaport/contracts/helpers/order-validator/SeaportValidator.sol"; diff --git a/contracts/trading/seaport/validators/SeaportValidatorHelper.sol b/contracts/trading/seaport/validators/SeaportValidatorHelper.sol index 0334c9cd..eb83ef96 100644 --- a/contracts/trading/seaport/validators/SeaportValidatorHelper.sol +++ b/contracts/trading/seaport/validators/SeaportValidatorHelper.sol @@ -1,4 +1,5 @@ // SPDX-License-Identifier: MIT +// solhint-disable pragma solidity 0.8.17; -import { SeaportValidatorHelper } from "seaport/contracts/helpers/order-validator/lib/SeaportValidatorHelper.sol"; +import {SeaportValidatorHelper} from "seaport/contracts/helpers/order-validator/lib/SeaportValidatorHelper.sol"; diff --git a/contracts/trading/seaport/zones/ImmutableSignedZone.sol b/contracts/trading/seaport/zones/ImmutableSignedZone.sol index 87140c62..9b95c0eb 100644 --- a/contracts/trading/seaport/zones/ImmutableSignedZone.sol +++ b/contracts/trading/seaport/zones/ImmutableSignedZone.sol @@ -1,21 +1,17 @@ // Copyright (c) Immutable Pty Ltd 2018 - 2023 // SPDX-License-Identifier: Apache-2 +// solhint-disable compiler-version pragma solidity 0.8.17; -import { - ZoneParameters, - Schema, - ReceivedItem -} from "seaport-types/src/lib/ConsiderationStructs.sol"; -import { ZoneInterface } from "seaport/contracts/interfaces/ZoneInterface.sol"; -import { SIP7Interface } from "./interfaces/SIP7Interface.sol"; -import { SIP7EventsAndErrors } from "./interfaces/SIP7EventsAndErrors.sol"; -import { SIP6EventsAndErrors } from "./interfaces/SIP6EventsAndErrors.sol"; -import { SIP5Interface } from "./interfaces/SIP5Interface.sol"; -import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; -import { ECDSA } from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; -import { Strings } from "@openzeppelin/contracts/utils/Strings.sol"; -import { ERC165 } from "@openzeppelin/contracts/utils/introspection/ERC165.sol"; +import {ZoneParameters, Schema, ReceivedItem} from "seaport-types/src/lib/ConsiderationStructs.sol"; +import {ZoneInterface} from "seaport/contracts/interfaces/ZoneInterface.sol"; +import {SIP7Interface} from "./interfaces/SIP7Interface.sol"; +import {SIP7EventsAndErrors} from "./interfaces/SIP7EventsAndErrors.sol"; +import {SIP6EventsAndErrors} from "./interfaces/SIP6EventsAndErrors.sol"; +import {SIP5Interface} from "./interfaces/SIP5Interface.sol"; +import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; +import {ECDSA} from "@openzeppelin/contracts/utils/cryptography/ECDSA.sol"; +import {ERC165} from "@openzeppelin/contracts/utils/introspection/ERC165.sol"; /** * @title ImmutableSignedZone @@ -82,8 +78,7 @@ contract ImmutableSignedZone is ")" ); - bytes32 internal constant RECEIVED_ITEM_TYPEHASH = - keccak256(RECEIVED_ITEM_BYTES); + bytes32 internal constant RECEIVED_ITEM_TYPEHASH = keccak256(RECEIVED_ITEM_BYTES); bytes32 internal constant CONSIDERATION_TYPEHASH = keccak256(abi.encodePacked(CONSIDERATION_BYTES, RECEIVED_ITEM_BYTES)); @@ -93,11 +88,16 @@ contract ImmutableSignedZone is uint8 internal immutable _ACCEPTED_SIP6_VERSION = 0; /// @dev The name for this zone returned in getSeaportMetadata(). + // solhint-disable-next-line var-name-mixedcase string private _ZONE_NAME; + // slither-disable-start immutable-states + // solhint-disable-next-line var-name-mixedcase bytes32 internal _NAME_HASH; + // slither-disable-end immutable-states /// @dev The allowed signers. + // solhint-disable-next-line named-parameters-mapping mapping(address => SignerInfo) private _signers; /// @dev The API endpoint where orders for this zone can be signed. @@ -118,12 +118,7 @@ contract ImmutableSignedZone is * @param owner The address of the owner of this contract. Specified in the * constructor to be CREATE2 / CREATE3 compatible. */ - constructor( - string memory zoneName, - string memory apiEndpoint, - string memory documentationURI, - address owner - ) { + constructor(string memory zoneName, string memory apiEndpoint, string memory documentationURI, address owner) { // Set the zone name. _ZONE_NAME = zoneName; // set name hash @@ -218,10 +213,7 @@ contract ImmutableSignedZone is // Revert with an error if the extraData does not have valid length. if (extraData.length < 93) { - revert InvalidExtraData( - "extraData length must be at least 93 bytes", - orderHash - ); + revert InvalidExtraData("extraData length must be at least 93 bytes", orderHash); } // Revert if SIP6 version is not accepted (0) @@ -244,7 +236,9 @@ contract ImmutableSignedZone is bytes calldata context = extraData[93:]; // Revert if expired. + // solhint-disable-next-line not-rely-on-time if (block.timestamp > expiration) { + // solhint-disable-next-line not-rely-on-time revert SignatureExpired(block.timestamp, expiration, orderHash); } @@ -254,46 +248,23 @@ contract ImmutableSignedZone is // Revert unless // Expected fulfiller is 0 address (any fulfiller) or // Expected fulfiller is the same as actual fulfiller - if ( - expectedFulfiller != address(0) && - expectedFulfiller != actualFulfiller - ) { - revert InvalidFulfiller( - expectedFulfiller, - actualFulfiller, - orderHash - ); + if (expectedFulfiller != address(0) && expectedFulfiller != actualFulfiller) { + revert InvalidFulfiller(expectedFulfiller, actualFulfiller, orderHash); } // validate supported substandards (3,4) - _validateSubstandards( - context, - _deriveConsiderationHash(zoneParameters.consideration), - zoneParameters - ); + _validateSubstandards(context, _deriveConsiderationHash(zoneParameters.consideration), zoneParameters); // Derive the signedOrder hash - bytes32 signedOrderHash = _deriveSignedOrderHash( - expectedFulfiller, - expiration, - orderHash, - context - ); + bytes32 signedOrderHash = _deriveSignedOrderHash(expectedFulfiller, expiration, orderHash, context); // Derive the EIP-712 digest using the domain separator and signedOrder // hash through openzepplin helper - bytes32 digest = ECDSA.toTypedDataHash( - _domainSeparator(), - signedOrderHash - ); + bytes32 digest = ECDSA.toTypedDataHash(_domainSeparator(), signedOrderHash); // Recover the signer address from the digest and signature. // Pass in R and VS from compact signature (ERC2098) - address recoveredSigner = ECDSA.recover( - digest, - bytes32(signature[0:32]), - bytes32(signature[32:64]) - ); + address recoveredSigner = ECDSA.recover(digest, bytes32(signature[0:32]), bytes32(signature[32:64])); // Revert if the signer is not active // !This also reverts if the digest constructed on serverside is incorrect @@ -314,10 +285,7 @@ contract ImmutableSignedZone is * @return The domain separator. */ function _domainSeparator() internal view returns (bytes32) { - return - block.chainid == _CHAIN_ID - ? _DOMAIN_SEPARATOR - : _deriveDomainSeparator(); + return block.chainid == _CHAIN_ID ? _DOMAIN_SEPARATOR : _deriveDomainSeparator(); } /** @@ -340,14 +308,7 @@ contract ImmutableSignedZone is schemas[0].id = 7; schemas[0].metadata = abi.encode( - keccak256( - abi.encode( - _domainSeparator(), - _sip7APIEndpoint, - _getSupportedSubstandards(), - _documentationURI - ) - ) + keccak256(abi.encode(_domainSeparator(), _sip7APIEndpoint, _getSupportedSubstandards(), _documentationURI)) ); } @@ -356,21 +317,8 @@ contract ImmutableSignedZone is * * @return domainSeparator The derived domain separator. */ - function _deriveDomainSeparator() - internal - view - returns (bytes32 domainSeparator) - { - return - keccak256( - abi.encode( - _EIP_712_DOMAIN_TYPEHASH, - _NAME_HASH, - _VERSION_HASH, - block.chainid, - address(this) - ) - ); + function _deriveDomainSeparator() internal view returns (bytes32 domainSeparator) { + return keccak256(abi.encode(_EIP_712_DOMAIN_TYPEHASH, _NAME_HASH, _VERSION_HASH, block.chainid, address(this))); } /** @@ -378,9 +326,7 @@ contract ImmutableSignedZone is * * @param newApiEndpoint The new API endpoint. */ - function updateAPIEndpoint( - string calldata newApiEndpoint - ) external override onlyOwner { + function updateAPIEndpoint(string calldata newApiEndpoint) external override onlyOwner { // Update to the new API endpoint. _sip7APIEndpoint = newApiEndpoint; } @@ -432,11 +378,7 @@ contract ImmutableSignedZone is // revert if order hash in context and payload do not match bytes32 expectedConsiderationHash = bytes32(context[0:32]); if (expectedConsiderationHash != actualConsiderationHash) { - revert SubstandardViolation( - 3, - "invalid consideration hash", - zoneParameters.orderHash - ); + revert SubstandardViolation(3, "invalid consideration hash", zoneParameters.orderHash); } // substandard 4 - validate order hashes actual match expected @@ -452,28 +394,15 @@ contract ImmutableSignedZone is } // compute expected order hashes array based on context bytes - bytes32[] memory expectedOrderHashes = new bytes32[]( - orderHashesBytes.length / 32 - ); + bytes32[] memory expectedOrderHashes = new bytes32[](orderHashesBytes.length / 32); for (uint256 i = 0; i < orderHashesBytes.length / 32; i++) { - expectedOrderHashes[i] = bytes32( - orderHashesBytes[i * 32:i * 32 + 32] - ); + expectedOrderHashes[i] = bytes32(orderHashesBytes[i * 32:i * 32 + 32]); } // revert if order hashes in context and payload do not match // every expected order hash need to exist in fulfilling order hashes - if ( - !_everyElementExists( - expectedOrderHashes, - zoneParameters.orderHashes - ) - ) { - revert SubstandardViolation( - 4, - "invalid order hashes", - zoneParameters.orderHash - ); + if (!_everyElementExists(expectedOrderHashes, zoneParameters.orderHashes)) { + revert SubstandardViolation(4, "invalid order hashes", zoneParameters.orderHash); } } @@ -483,11 +412,7 @@ contract ImmutableSignedZone is * @return substandards array of substandards supported * */ - function _getSupportedSubstandards() - internal - pure - returns (uint256[] memory substandards) - { + function _getSupportedSubstandards() internal pure returns (uint256[] memory substandards) { // support substandards 3 and 4 substandards = new uint256[](2); substandards[0] = 3; @@ -513,13 +438,7 @@ contract ImmutableSignedZone is ) internal view returns (bytes32 signedOrderHash) { // Derive the signed order hash. signedOrderHash = keccak256( - abi.encode( - _SIGNED_ORDER_TYPEHASH, - fulfiller, - expiration, - orderHash, - keccak256(context) - ) + abi.encode(_SIGNED_ORDER_TYPEHASH, fulfiller, expiration, orderHash, keccak256(context)) ); } @@ -527,9 +446,7 @@ contract ImmutableSignedZone is * @dev Derive the EIP712 consideration hash based on received item array * @param consideration expected consideration array */ - function _deriveConsiderationHash( - ReceivedItem[] calldata consideration - ) internal pure returns (bytes32) { + function _deriveConsiderationHash(ReceivedItem[] calldata consideration) internal pure returns (bytes32) { uint256 numberOfItems = consideration.length; bytes32[] memory considerationHashes = new bytes32[](numberOfItems); for (uint256 i; i < numberOfItems; i++) { @@ -544,13 +461,7 @@ contract ImmutableSignedZone is ) ); } - return - keccak256( - abi.encode( - CONSIDERATION_TYPEHASH, - keccak256(abi.encodePacked(considerationHashes)) - ) - ); + return keccak256(abi.encode(CONSIDERATION_TYPEHASH, keccak256(abi.encodePacked(considerationHashes)))); } /** @@ -560,10 +471,7 @@ contract ImmutableSignedZone is * @param array1 subset array * @param array2 superset array */ - function _everyElementExists( - bytes32[] memory array1, - bytes32[] calldata array2 - ) internal pure returns (bool) { + function _everyElementExists(bytes32[] memory array1, bytes32[] calldata array2) internal pure returns (bool) { // cache the length in memory for loop optimisation uint256 array1Size = array1.length; uint256 array2Size = array2.length; @@ -601,11 +509,7 @@ contract ImmutableSignedZone is return true; } - function supportsInterface( - bytes4 interfaceId - ) public view override(ERC165, ZoneInterface) returns (bool) { - return - interfaceId == type(ZoneInterface).interfaceId || - super.supportsInterface(interfaceId); + function supportsInterface(bytes4 interfaceId) public view override(ERC165, ZoneInterface) returns (bool) { + return interfaceId == type(ZoneInterface).interfaceId || super.supportsInterface(interfaceId); } } diff --git a/contracts/trading/seaport/zones/interfaces/SIP5Interface.sol b/contracts/trading/seaport/zones/interfaces/SIP5Interface.sol index 9da10294..1f994f23 100644 --- a/contracts/trading/seaport/zones/interfaces/SIP5Interface.sol +++ b/contracts/trading/seaport/zones/interfaces/SIP5Interface.sol @@ -1,8 +1,9 @@ // Copyright (c) Immutable Pty Ltd 2018 - 2023 // SPDX-License-Identifier: Apache-2 +// solhint-disable compiler-version pragma solidity 0.8.17; -import { Schema } from "seaport-types/src/lib/ConsiderationStructs.sol"; +import {Schema} from "seaport-types/src/lib/ConsiderationStructs.sol"; /** * @dev SIP-5: Contract Metadata Interface for Seaport Contracts @@ -21,8 +22,5 @@ interface SIP5Interface { * @return name The contract name * @return schemas The supported SIPs */ - function getSeaportMetadata() - external - view - returns (string memory name, Schema[] memory schemas); + function getSeaportMetadata() external view returns (string memory name, Schema[] memory schemas); } diff --git a/contracts/trading/seaport/zones/interfaces/SIP6EventsAndErrors.sol b/contracts/trading/seaport/zones/interfaces/SIP6EventsAndErrors.sol index 338b3b27..3a9f82a4 100644 --- a/contracts/trading/seaport/zones/interfaces/SIP6EventsAndErrors.sol +++ b/contracts/trading/seaport/zones/interfaces/SIP6EventsAndErrors.sol @@ -1,5 +1,6 @@ // Copyright (c) Immutable Pty Ltd 2018 - 2023 // SPDX-License-Identifier: Apache-2 +// solhint-disable compiler-version pragma solidity 0.8.17; /** diff --git a/contracts/trading/seaport/zones/interfaces/SIP7EventsAndErrors.sol b/contracts/trading/seaport/zones/interfaces/SIP7EventsAndErrors.sol index 75555db0..13a2481e 100644 --- a/contracts/trading/seaport/zones/interfaces/SIP7EventsAndErrors.sol +++ b/contracts/trading/seaport/zones/interfaces/SIP7EventsAndErrors.sol @@ -1,5 +1,6 @@ // Copyright (c) Immutable Pty Ltd 2018 - 2023 // SPDX-License-Identifier: Apache-2 +// solhint-disable compiler-version pragma solidity 0.8.17; /** @@ -43,29 +44,17 @@ interface SIP7EventsAndErrors { /** * @dev Revert with an error when the signature has expired. */ - error SignatureExpired( - uint256 currentTimestamp, - uint256 expiration, - bytes32 orderHash - ); + error SignatureExpired(uint256 currentTimestamp, uint256 expiration, bytes32 orderHash); /** * @dev Revert with an error if the fulfiller does not match. */ - error InvalidFulfiller( - address expectedFulfiller, - address actualFulfiller, - bytes32 orderHash - ); + error InvalidFulfiller(address expectedFulfiller, address actualFulfiller, bytes32 orderHash); /** * @dev Revert with an error if a substandard validation fails */ - error SubstandardViolation( - uint256 substandardId, - string reason, - bytes32 orderHash - ); + error SubstandardViolation(uint256 substandardId, string reason, bytes32 orderHash); /** * @dev Revert with an error if supplied order extraData is invalid diff --git a/contracts/trading/seaport/zones/interfaces/SIP7Interface.sol b/contracts/trading/seaport/zones/interfaces/SIP7Interface.sol index 47a16551..ce9509f5 100644 --- a/contracts/trading/seaport/zones/interfaces/SIP7Interface.sol +++ b/contracts/trading/seaport/zones/interfaces/SIP7Interface.sol @@ -1,5 +1,6 @@ // Copyright (c) Immutable Pty Ltd 2018 - 2023 // SPDX-License-Identifier: Apache-2 +// solhint-disable compiler-version pragma solidity 0.8.17; /** diff --git a/package.json b/package.json index 68f4eb7c..c47bebdb 100644 --- a/package.json +++ b/package.json @@ -13,9 +13,9 @@ "compile": "hardhat compile", "build": "tsc", "test": "hardhat test", - "prettier:solidity": "./node_modules/.bin/prettier --write contracts/**/*.sol", + "prettier:solidity": "./node_modules/.bin/prettier --write --plugin=prettier-plugin-solidity contracts/**/*.sol", "lint": "eslint . --ext .ts,.tsx --fix && solhint --config ./.solhint.json contracts/**/*.sol", - "eslint": "eslint . --ext .ts,.tsx", + "eslint": "eslint clients --ext .ts,.tsx", "solhint": "solhint --config ./.solhint.json", "clean": "hardhat clean", "coverage": "hardhat coverage" diff --git a/slither.config.json b/slither.config.json new file mode 100644 index 00000000..fb7474f2 --- /dev/null +++ b/slither.config.json @@ -0,0 +1,6 @@ +{ + "detectors_to_exclude": "naming-convention, solc-version, similar-names, timestamp, assembly", + + "filter_paths": "lib" +} + diff --git a/test/utils/DeploySCW.sol b/test/utils/DeploySCW.sol index e7dfe61b..e5ccb736 100644 --- a/test/utils/DeploySCW.sol +++ b/test/utils/DeploySCW.sol @@ -1,10 +1,10 @@ // SPDX-License-Identifier: Apache 2.0 -pragma solidity ^0.8.19; +pragma solidity 0.8.19; import "forge-std/Test.sol"; -import {MockWallet} from "../../../contracts/mocks/MockWallet.sol"; -import {MockWalletFactory} from "../../../contracts/mocks/MockWalletFactory.sol"; +import {MockWallet} from "../../contracts/mocks/MockWallet.sol"; +import {MockWalletFactory} from "../../contracts/mocks/MockWalletFactory.sol"; contract DeploySCWallet is Test { MockWallet public mockWalletModule; diff --git a/yarn.lock b/yarn.lock index 5eec4976..632dc7eb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -30,9 +30,9 @@ js-tokens "^4.0.0" "@babel/runtime@^7.4.4": - version "7.23.8" - resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.23.8.tgz#8ee6fe1ac47add7122902f257b8ddf55c898f650" - integrity sha512-Y7KbAP984rn1VGMbGqKmBLio9V7y5Je9GvU4rQPCPinCyNfUcToxIXl06d59URp/F3LwinvODxab5N/G6qggkw== + version "7.23.9" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.23.9.tgz#47791a15e4603bb5f905bc0753801cf21d6345f7" + integrity sha512-0CX6F+BI2s9dkUqr08KFrAIZgNFj75rdBU/DjCyYLIaV/quFjkk6T+EJ2LkZHyZTbEV4L5p97mNkUsHl2wLFAw== dependencies: regenerator-runtime "^0.14.0" @@ -780,24 +780,19 @@ tweetnacl "^1.0.3" tweetnacl-util "^0.15.1" -"@noble/curves@1.1.0", "@noble/curves@~1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.1.0.tgz#f13fc667c89184bc04cccb9b11e8e7bae27d8c3d" - integrity sha512-091oBExgENk/kGj3AZmtBDMpxQPDtxQABR2B9lb1JbVTs6ytdzZNwvhxQ4MWasRNEzlbEH8jCWFCwhF/Obj5AA== +"@noble/curves@1.3.0", "@noble/curves@~1.3.0": + version "1.3.0" + resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.3.0.tgz#01be46da4fd195822dab821e72f71bf4aeec635e" + integrity sha512-t01iSXPuN+Eqzb4eBX0S5oubSqXbK/xXa1Ne18Hj8f9pStxztHCE2gfboSp/dZRLSqfuLpRK2nDXDK+W9puocA== dependencies: - "@noble/hashes" "1.3.1" + "@noble/hashes" "1.3.3" "@noble/hashes@1.2.0", "@noble/hashes@~1.2.0": version "1.2.0" resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.2.0.tgz#a3150eeb09cc7ab207ebf6d7b9ad311a9bdbed12" integrity sha512-FZfhjEDbT5GRswV3C6uvLPHMiVD6lQBmpoX5+eSiPaMTXte/IKqI5dykDxzZB/WBeK/CDuQRBWarPdi3FNY2zQ== -"@noble/hashes@1.3.1": - version "1.3.1" - resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.1.tgz#8831ef002114670c603c458ab8b11328406953a9" - integrity sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA== - -"@noble/hashes@~1.3.0", "@noble/hashes@~1.3.1": +"@noble/hashes@1.3.3", "@noble/hashes@~1.3.2": version "1.3.3" resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.3.tgz#39908da56a4adc270147bb07968bf3b16cfe1699" integrity sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA== @@ -1159,7 +1154,7 @@ path-browserify "^1.0.0" url "^0.11.0" -"@scure/base@~1.1.0": +"@scure/base@~1.1.0", "@scure/base@~1.1.4": version "1.1.5" resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.5.tgz#1d85d17269fe97694b9c592552dd9e5e33552157" integrity sha512-Brj9FiG2W1MRQSTB212YVPRrcbjkv48FoZi/u4l/zds/ieRrqsh7aUf6CLwkAq61oKXr/ZlTzlY66gLIj3TFTQ== @@ -1173,14 +1168,14 @@ "@noble/secp256k1" "~1.7.0" "@scure/base" "~1.1.0" -"@scure/bip32@1.3.1": - version "1.3.1" - resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.3.1.tgz#7248aea723667f98160f593d621c47e208ccbb10" - integrity sha512-osvveYtyzdEVbt3OfwwXFr4P2iVBL5u1Q3q4ONBfDY/UpOuXmOlbgwc1xECEboY8wIays8Yt6onaWMUdUbfl0A== +"@scure/bip32@1.3.3": + version "1.3.3" + resolved "https://registry.yarnpkg.com/@scure/bip32/-/bip32-1.3.3.tgz#a9624991dc8767087c57999a5d79488f48eae6c8" + integrity sha512-LJaN3HwRbfQK0X1xFSi0Q9amqOgzQnnDngIt+ZlsBC3Bm7/nE7K0kwshZHyaru79yIVRv/e1mQAjZyuZG6jOFQ== dependencies: - "@noble/curves" "~1.1.0" - "@noble/hashes" "~1.3.1" - "@scure/base" "~1.1.0" + "@noble/curves" "~1.3.0" + "@noble/hashes" "~1.3.2" + "@scure/base" "~1.1.4" "@scure/bip39@1.1.1": version "1.1.1" @@ -1190,13 +1185,13 @@ "@noble/hashes" "~1.2.0" "@scure/base" "~1.1.0" -"@scure/bip39@1.2.1": - version "1.2.1" - resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.2.1.tgz#5cee8978656b272a917b7871c981e0541ad6ac2a" - integrity sha512-Z3/Fsz1yr904dduJD0NpiyRHhRYHdcnyh73FZWiV+/qhWi83wNJ3NWolYqCEN+ZWsUz2TWwajJggcRE9r1zUYg== +"@scure/bip39@1.2.2": + version "1.2.2" + resolved "https://registry.yarnpkg.com/@scure/bip39/-/bip39-1.2.2.tgz#f3426813f4ced11a47489cbcf7294aa963966527" + integrity sha512-HYf9TUXG80beW+hGAt3TRM8wU6pQoYur9iNypTROm42dorCGmLnFe3eWjz3gOq6G62H2WRh0FCzAR1PI+29zIA== dependencies: - "@noble/hashes" "~1.3.0" - "@scure/base" "~1.1.0" + "@noble/hashes" "~1.3.2" + "@scure/base" "~1.1.4" "@sentry/core@5.30.0": version "5.30.0" @@ -1290,6 +1285,11 @@ resolved "https://registry.yarnpkg.com/@solidity-parser/parser/-/parser-0.17.0.tgz#52a2fcc97ff609f72011014e4c5b485ec52243ef" integrity sha512-Nko8R0/kUo391jsEHHxrGM07QFdnPGvlmox4rmH0kNiNAashItAilhy4Mv4pK5gQmW5f4sXAF58fwJbmlkGcVw== +"@solidity-parser/parser@^0.18.0": + version "0.18.0" + resolved "https://registry.yarnpkg.com/@solidity-parser/parser/-/parser-0.18.0.tgz#8e77a02a09ecce957255a2f48c9a7178ec191908" + integrity sha512-yfORGUIPgLck41qyN7nbwJRAx17/jAIXCTanHOJZhB6PJ1iAk/84b/xlsVKFSyNyLXIj0dhppoE0+CRws7wlzA== + "@szmarczak/http-timer@^4.0.5": version "4.0.6" resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-4.0.6.tgz#b4a914bb62e7c272d4e5989fe4440f812ab1d807" @@ -1589,9 +1589,9 @@ form-data "^4.0.0" "@types/node@*": - version "20.11.5" - resolved "https://registry.yarnpkg.com/@types/node/-/node-20.11.5.tgz#be10c622ca7fcaa3cf226cf80166abc31389d86e" - integrity sha512-g557vgQjUUfN76MZAN/dt1z3dzcUsimuysco0KeluHgrPdJXkP/XdAURgyO2W9fZWHRtRBiVKzKn8vyOAwlG+w== + version "20.11.14" + resolved "https://registry.yarnpkg.com/@types/node/-/node-20.11.14.tgz#9fdc9c2550c2f6693508ca4530f821474c4ee3bb" + integrity sha512-w3yWCcwULefjP9DmDDsgUskrMoOy5Z8MiwKHr1FvqGPtx7CvJzQvxD7eKpxNtklQxLruxSXWddyeRtyud0RcXQ== dependencies: undici-types "~5.26.4" @@ -1611,9 +1611,9 @@ integrity sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ== "@types/node@^18.17.14": - version "18.19.8" - resolved "https://registry.yarnpkg.com/@types/node/-/node-18.19.8.tgz#c1e42b165e5a526caf1f010747e0522cb2c9c36a" - integrity sha512-g1pZtPhsvGVTwmeVoexWZLTQaOvXwoSq//pTL0DHeNzUDrFnir4fgETdhjhIxjVnN+hKOuh98+E1eMLnUXstFg== + version "18.19.12" + resolved "https://registry.yarnpkg.com/@types/node/-/node-18.19.12.tgz#21c85d96a30ee5327621b36fe82e3d049048333d" + integrity sha512-uLcpWEAvatBEubmgCMzWforZbAu1dT9syweWnU3/DNwbeUBq2miP5nG8Y4JL9MDMKWt+7Yv1CSvA8xELdEl54w== dependencies: undici-types "~5.26.4" @@ -1775,7 +1775,7 @@ abortcontroller-polyfill@^1.7.3, abortcontroller-polyfill@^1.7.5: resolved "https://registry.yarnpkg.com/abortcontroller-polyfill/-/abortcontroller-polyfill-1.7.5.tgz#6738495f4e901fbb57b6c0611d0c75f76c485bed" integrity sha512-JMJ5soJWP18htbbxJjG7bG6yuI6pRhgJ0scHHTfkUjf6wjP912xZWvM+A4sJK3gqd9E8fcPbDnOefbA9Th/FIQ== -abstract-level@^1.0.0, abstract-level@^1.0.2, abstract-level@^1.0.3: +abstract-level@^1.0.0, abstract-level@^1.0.2, abstract-level@^1.0.3, abstract-level@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/abstract-level/-/abstract-level-1.0.4.tgz#3ad8d684c51cc9cbc9cf9612a7100b716c414b57" integrity sha512-eUP/6pbXBkMbXFdx4IH2fVgvB7M0JvR7/lIL33zcs0IBcwjdzSSl31TOJsaCzmKSSDF9h8QYSOJux4Nd4YJqFg== @@ -1900,6 +1900,13 @@ amdefine@>=0.0.4: resolved "https://registry.yarnpkg.com/amdefine/-/amdefine-1.0.1.tgz#4a5282ac164729e93619bcfd3ad151f817ce91f5" integrity sha512-S2Hw0TtNkMJhIabBwIojKL9YHO5T0n5eNqWJ7Lrlel/zDbftQpxpapi8tZs3X1HWa+u+QeydGmzzNU0m09+Rcg== +ansi-align@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/ansi-align/-/ansi-align-3.0.1.tgz#0cdf12e111ace773a86e9a1fad1225c43cb19a59" + integrity sha512-IOfwwBF5iczOjp/WeY4YxyjqAFMQoZufdQWDd19SEExbVLNXqvpzSJ/M7Za4/sCPmQ0+GRquoA7bGcINcxew6w== + dependencies: + string-width "^4.1.0" + ansi-colors@4.1.1: version "4.1.1" resolved "https://registry.yarnpkg.com/ansi-colors/-/ansi-colors-4.1.1.tgz#cbb9ae256bf750af1eab344f229aa27fe94ba348" @@ -2166,9 +2173,9 @@ aws4@^1.8.0: integrity sha512-NmWvPnx0F1SfrQbYwOi7OeaNGokp9XhzNioJ/CSBs8Qa4vxug81mhJEAVZwxXuBmYB5KDRfMq/F3RR0BIU7sWg== axios@^1.5.1: - version "1.6.5" - resolved "https://registry.yarnpkg.com/axios/-/axios-1.6.5.tgz#2c090da14aeeab3770ad30c3a1461bc970fb0cd8" - integrity sha512-Ii012v05KEVuUoFWmMW/UQv9aRIc3ZwkWDcM+h5Il8izZCtRVpDUfwpoFf7eOtajT3QiGR4yDUx7lPqHJULgbg== + version "1.6.7" + resolved "https://registry.yarnpkg.com/axios/-/axios-1.6.7.tgz#7b48c2e27c96f9c68a2f8f31e2ab19f59b06b0a7" + integrity sha512-/hDJGff6/c7u0hDkvkGxR/oy6CbCs8ziCsC7SqmhjfozqiJGc8Z11wrv9z9lYfY4K8l+H9TpjcMDX0xOZmx+RA== dependencies: follow-redirects "^1.15.4" form-data "^4.0.0" @@ -2309,6 +2316,20 @@ boolbase@^1.0.0: resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" integrity sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww== +boxen@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/boxen/-/boxen-5.1.2.tgz#788cb686fc83c1f486dfa8a40c68fc2b831d2b50" + integrity sha512-9gYgQKXx+1nP8mP7CzFyaUARhg7D3n1dF/FnErWmu9l6JvGpNUN278h0aSb+QjoiKSWG+iZ3uHrcqk0qrY9RQQ== + dependencies: + ansi-align "^3.0.0" + camelcase "^6.2.0" + chalk "^4.1.0" + cli-boxes "^2.2.1" + string-width "^4.2.2" + type-fest "^0.20.2" + widest-line "^3.1.0" + wrap-ansi "^7.0.0" + brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" @@ -2508,7 +2529,7 @@ camelcase@^4.1.0: resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-4.1.0.tgz#d545635be1e33c542649c69173e5de6acfae34dd" integrity sha512-FxAv7HpHrXbh3aPo4o2qxHay2lkLY3x5Mw3KeE4KQE8ysVfziWeRZDwcjauvwBSGEC/nXUPzZy8zeh4HokqOnw== -camelcase@^6.0.0: +camelcase@^6.0.0, camelcase@^6.2.0: version "6.3.0" resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== @@ -2704,6 +2725,11 @@ clean-stack@^2.0.0: resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== +cli-boxes@^2.2.1: + version "2.2.1" + resolved "https://registry.yarnpkg.com/cli-boxes/-/cli-boxes-2.2.1.tgz#ddd5035d25094fce220e9cab40a45840a440318f" + integrity sha512-y4coMcylgSCdVinjiDBuR8PCC2bLjyGTwEmPb9NHR/QaNU6EUOXcTY/s6VjGMD6ENSEaeQYHCY0GNGS5jfMwPw== + cli-table3@^0.5.0: version "0.5.1" resolved "https://registry.yarnpkg.com/cli-table3/-/cli-table3-0.5.1.tgz#0252372d94dfc40dbd8df06005f48f31f656f202" @@ -3239,9 +3265,9 @@ dot-case@^2.1.0: no-case "^2.2.0" dotenv@^16.0.3: - version "16.3.2" - resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.3.2.tgz#3cb611ce5a63002dbabf7c281bc331f69d28f03f" - integrity sha512-HTlk5nmhkm8F6JcdXvHIzaorzCoziNQT9mGxLPVXW8wJF1TiGSL60ZGB4gHWabHOaMmWmhvk2/lPHfnBiT78AQ== + version "16.4.1" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.4.1.tgz#1d9931f1d3e5d2959350d1250efab299561f7f11" + integrity sha512-CjA3y+Dr3FyFDOAMnxZEGtnW9KBR2M0JvvUtXNW+dYJL5ROWxP9DUHCwgFqpMk0OXCc0ljhaNTr2w/kutYIcHQ== "ds-test@github:dapphub/ds-test": version "1.0.0" @@ -3835,14 +3861,14 @@ ethereum-cryptography@^1.0.3: "@scure/bip39" "1.1.1" ethereum-cryptography@^2.0.0, ethereum-cryptography@^2.1.2: - version "2.1.2" - resolved "https://registry.yarnpkg.com/ethereum-cryptography/-/ethereum-cryptography-2.1.2.tgz#18fa7108622e56481157a5cb7c01c0c6a672eb67" - integrity sha512-Z5Ba0T0ImZ8fqXrJbpHcbpAvIswRte2wGNR/KePnu8GbbvgJ47lMxT/ZZPG6i9Jaht4azPDop4HaM00J0J59ug== + version "2.1.3" + resolved "https://registry.yarnpkg.com/ethereum-cryptography/-/ethereum-cryptography-2.1.3.tgz#1352270ed3b339fe25af5ceeadcf1b9c8e30768a" + integrity sha512-BlwbIL7/P45W8FGW2r7LGuvoEZ+7PWsniMvQ4p5s2xCyw9tmaDlpfsN9HjAucbF+t/qpVHwZUisgfK24TCW8aA== dependencies: - "@noble/curves" "1.1.0" - "@noble/hashes" "1.3.1" - "@scure/bip32" "1.3.1" - "@scure/bip39" "1.2.1" + "@noble/curves" "1.3.0" + "@noble/hashes" "1.3.3" + "@scure/bip32" "1.3.3" + "@scure/bip39" "1.2.2" ethereum-waffle@^4.0.10: version "4.0.10" @@ -4091,9 +4117,9 @@ fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6: integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== fastq@^1.6.0: - version "1.16.0" - resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.16.0.tgz#83b9a9375692db77a822df081edb6a9cf6839320" - integrity sha512-ifCoaXsDrsdkWTtiNJX5uzHDsrck5TzfKKDcuFFTIrrc/BS076qgEIfoIy1VeZqViznfKiysPYTh/QeHtnIsYA== + version "1.17.0" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.17.0.tgz#ca5e1a90b5e68f97fc8b61330d5819b82f5fab03" + integrity sha512-zGygtijUMT7jnk3h26kUms3BkSDp4IfIKjmnqI2tvx6nuBfiF1UqOxbnLfzdv+apBy+53oaImsKtMw/xYbW+1w== dependencies: reusify "^1.0.4" @@ -4673,18 +4699,18 @@ har-validator@~5.1.3: har-schema "^2.0.0" hardhat-gas-reporter@^1.0.9: - version "1.0.9" - resolved "https://registry.yarnpkg.com/hardhat-gas-reporter/-/hardhat-gas-reporter-1.0.9.tgz#9a2afb354bc3b6346aab55b1c02ca556d0e16450" - integrity sha512-INN26G3EW43adGKBNzYWOlI3+rlLnasXTwW79YNnUhXPDa+yHESgt639dJEs37gCjhkbNKcRRJnomXEuMFBXJg== + version "1.0.10" + resolved "https://registry.yarnpkg.com/hardhat-gas-reporter/-/hardhat-gas-reporter-1.0.10.tgz#ebe5bda5334b5def312747580cd923c2b09aef1b" + integrity sha512-02N4+So/fZrzJ88ci54GqwVA3Zrf0C9duuTyGt0CFRIh/CdNwbnTgkXkRfojOMLBQ+6t+lBIkgbsOtqMvNwikA== dependencies: array-uniq "1.0.3" eth-gas-reporter "^0.2.25" sha1 "^1.1.1" hardhat@^2.12.7, hardhat@^2.17.3: - version "2.19.4" - resolved "https://registry.yarnpkg.com/hardhat/-/hardhat-2.19.4.tgz#5112c30295d8be2e18e55d847373c50483ed1902" - integrity sha512-fTQJpqSt3Xo9Mn/WrdblNGAfcANM6XC3tAEi6YogB4s02DmTf93A8QsGb8uR0KR8TFcpcS8lgiW4ugAIYpnbrQ== + version "2.19.5" + resolved "https://registry.yarnpkg.com/hardhat/-/hardhat-2.19.5.tgz#6017c35ae2844b669e9bcc84c3d05346d4ef031c" + integrity sha512-vx8R7zWCYVgM56vA6o0Wqx2bIIptkN4TMs9QwDqZVNGRhMzBfzqUeEYbp+69gxWp1neg2V2nYQUaaUv7aom1kw== dependencies: "@ethersproject/abi" "^5.1.2" "@metamask/eth-sig-util" "^4.0.0" @@ -4705,6 +4731,7 @@ hardhat@^2.12.7, hardhat@^2.17.3: adm-zip "^0.4.16" aggregate-error "^3.0.0" ansi-escapes "^4.3.0" + boxen "^5.1.2" chalk "^2.4.2" chokidar "^3.4.0" ci-info "^2.0.0" @@ -4954,9 +4981,9 @@ ieee754@^1.1.13, ieee754@^1.2.1: integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA== ignore@^5.1.1, ignore@^5.2.0, ignore@^5.2.4: - version "5.3.0" - resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.0.tgz#67418ae40d34d6999c95ff56016759c718c82f78" - integrity sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg== + version "5.3.1" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.1.tgz#5073e554cd42c5b33b394375f538b8593e34d4ef" + integrity sha512-5Fytz/IraMjqpwfd34ke28PTVMjZjJG2MPn5t7OE4eUCUNf8BAa7b5WUS9/Qvr6mwOQS7Mk6vdsMno5he+T8Xw== immediate@^3.2.3: version "3.3.0" @@ -4969,9 +4996,9 @@ immediate@~3.2.3: integrity sha512-RrGCXRm/fRVqMIhqXrGEX9rRADavPiDFSoMb/k64i9XMk8uH4r/Omi5Ctierj6XzNecwDbO4WuFbDD1zmpl3Tg== immutable@^4.0.0-rc.12: - version "4.3.4" - resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.3.4.tgz#2e07b33837b4bb7662f288c244d1ced1ef65a78f" - integrity sha512-fsXeu4J4i6WNWSikpI88v/PcVflZz+6kMhUfIwc5SY+poQRPnaf5V7qds6SUyUN3cVxEzuCab7QIoLOQ+DQ1wA== + version "4.3.5" + resolved "https://registry.yarnpkg.com/immutable/-/immutable-4.3.5.tgz#f8b436e66d59f99760dc577f5c99a4fd2a5cc5a0" + integrity sha512-8eabxkth9gZatlwl5TBuJnCsoTADlL6ftEr7A4qgdaTsPyreilDSnUk57SO+jfKcNtxPa22U5KK6DSeAYhpBJw== import-fresh@^3.2.1, import-fresh@^3.3.0: version "3.3.0" @@ -5564,10 +5591,11 @@ level-ws@^2.0.0: xtend "^4.0.1" level@^8.0.0: - version "8.0.0" - resolved "https://registry.yarnpkg.com/level/-/level-8.0.0.tgz#41b4c515dabe28212a3e881b61c161ffead14394" - integrity sha512-ypf0jjAk2BWI33yzEaaotpq7fkOPALKAgDBxggO6Q9HGX2MRXn0wbP1Jn/tJv1gtL867+YOjOB49WaUF3UoJNQ== + version "8.0.1" + resolved "https://registry.yarnpkg.com/level/-/level-8.0.1.tgz#737161db1bc317193aca4e7b6f436e7e1df64379" + integrity sha512-oPBGkheysuw7DmzFQYyFe8NAia5jFLAgEnkgWnK3OXAuJr8qFT+xBQIwokAZPME2bhPFzS8hlYcL16m8UZrtwQ== dependencies: + abstract-level "^1.0.4" browser-level "^1.0.1" classic-level "^1.2.0" @@ -5727,9 +5755,9 @@ lru-cache@^6.0.0: yallist "^4.0.0" "lru-cache@^9.1.1 || ^10.0.0": - version "10.1.0" - resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.1.0.tgz#2098d41c2dc56500e6c88584aa656c84de7d0484" - integrity sha512-/1clY/ui8CzjKFyjdvwPWJUYKiFVXG2I2cY0ssG7h4+hwk+XOIX7ZSG9Q7TW8TW3Kp3BUSqgFWBLgL4PJ+Blag== + version "10.2.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.2.0.tgz#0bd445ca57363465900f4d1f9bd8db343a4d95c3" + integrity sha512-2bIM8x+VAf6JT4bKAljS1qUWgMsqZRPGJS6FSahIMPVvctcNhyVp7AJu7quxOW9jwkryBReKZY5tY5JYv2n/7Q== lru_map@^0.3.3: version "0.3.3" @@ -5983,7 +6011,7 @@ mnemonist@^0.38.0: dependencies: obliterator "^2.0.0" -mocha@10.2.0, mocha@^10.0.0, mocha@^10.2.0: +mocha@^10.0.0, mocha@^10.2.0: version "10.2.0" resolved "https://registry.yarnpkg.com/mocha/-/mocha-10.2.0.tgz#1fd4a7c32ba5ac372e03a17eef435bd00e5c68b8" integrity sha512-IDY7fl/BecMwFHzoqF2sg/SHHANeBoMMXFlS9r0OXKDssYE1M5O43wUY/9BVPeIvfH2zmEbBfseqN9gBQZzXkg== @@ -7498,12 +7526,12 @@ solidity-comments-extractor@^0.0.8: integrity sha512-htM7Vn6LhHreR+EglVMd2s+sZhcXAirB1Zlyrv5zBuTxieCvjfnRpd7iZk75m/u6NOlEyQ94C6TWbBn2cY7w8g== solidity-coverage@^0.8.4: - version "0.8.5" - resolved "https://registry.yarnpkg.com/solidity-coverage/-/solidity-coverage-0.8.5.tgz#64071c3a0c06a0cecf9a7776c35f49edc961e875" - integrity sha512-6C6N6OV2O8FQA0FWA95FdzVH+L16HU94iFgg5wAFZ29UpLFkgNI/DRR2HotG1bC0F4gAc/OMs2BJI44Q/DYlKQ== + version "0.8.6" + resolved "https://registry.yarnpkg.com/solidity-coverage/-/solidity-coverage-0.8.6.tgz#c7b18dc9edfeba11064726c37d96265f689c9478" + integrity sha512-vV03mA/0nNMskOdVwNarUcqk0N/aYdelxAbf6RZ5l84FcYHbqDTr2JXyeYMp4bT48qHtAQjnKrygW1FrECyWNw== dependencies: "@ethersproject/abi" "^5.0.9" - "@solidity-parser/parser" "^0.16.0" + "@solidity-parser/parser" "^0.18.0" chalk "^2.4.2" death "^1.1.0" detect-port "^1.3.0" @@ -7514,7 +7542,7 @@ solidity-coverage@^0.8.4: globby "^10.0.1" jsonschema "^1.2.4" lodash "^4.17.15" - mocha "10.2.0" + mocha "^10.2.0" node-emoji "^1.10.0" pify "^4.0.1" recursive-readdir "^2.2.2" @@ -7552,9 +7580,9 @@ spdx-correct@^3.0.0: spdx-license-ids "^3.0.0" spdx-exceptions@^2.1.0: - version "2.3.0" - resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz#3f28ce1a77a00372683eade4a433183527a2163d" - integrity sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A== + version "2.4.0" + resolved "https://registry.yarnpkg.com/spdx-exceptions/-/spdx-exceptions-2.4.0.tgz#c07a4ede25b16e4f78e6707bbd84b15a45c19c1b" + integrity sha512-hcjppoJ68fhxA/cjbN4T8N6uCUejN8yFw69ttpqtBeCbF3u13n7mb31NB9jKwGTTWWnt9IbRA/mf1FprYS8wfw== spdx-expression-parse@^3.0.0: version "3.0.1" @@ -7611,7 +7639,7 @@ string-format@^2.0.0: resolved "https://registry.yarnpkg.com/string-format/-/string-format-2.0.0.tgz#f2df2e7097440d3b65de31b6d40d54c96eaffb9b" integrity sha512-bbEs3scLeYNXLecRRuk6uJxdXUSj6le/8rNPHChIJTn2V79aXVTR1EH2OH5zLKKoz0V02fOUKZZcw01pLUShZA== -"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: +"string-width-cjs@npm:string-width@^4.2.0", string-width@^4.0.0, string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.2, string-width@^4.2.3: version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -8855,6 +8883,13 @@ which@^2.0.1: dependencies: isexe "^2.0.0" +widest-line@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/widest-line/-/widest-line-3.1.0.tgz#8292333bbf66cb45ff0de1603b136b7ae1496eca" + integrity sha512-NsmoXalsWVDMGupxZ5R08ka9flZjjiLvHVAWYOKtiKM8ujtZWr9cRffak+uSE48+Ob8ObalXpwyeUiyDD6QFgg== + dependencies: + string-width "^4.0.0" + window-size@^0.2.0: version "0.2.0" resolved "https://registry.yarnpkg.com/window-size/-/window-size-0.2.0.tgz#b4315bb4214a3d7058ebeee892e13fa24d98b075"