diff --git a/.gas_reports/3fab586d8f77266bf79226b17cbc65cb867689e6.json b/.gas_reports/3fab586d8f77266bf79226b17cbc65cb867689e6.json
new file mode 100644
index 000000000..34d51fde5
--- /dev/null
+++ b/.gas_reports/3fab586d8f77266bf79226b17cbc65cb867689e6.json
@@ -0,0 +1,509 @@
+{
+ "commitHash": "3fab586d8f77266bf79226b17cbc65cb867689e6",
+ "contractReports": {
+ "ConduitControllerMock": {
+ "name": "ConduitControllerMock",
+ "methods": [
+ {
+ "method": "createConduit",
+ "min": 218710,
+ "max": 225954,
+ "avg": 223418,
+ "calls": 6
+ }
+ ],
+ "bytecodeSize": 10231,
+ "deployedBytecodeSize": 7165
+ },
+ "EIP1271Wallet": {
+ "name": "EIP1271Wallet",
+ "methods": [
+ {
+ "method": "approveNFT",
+ "min": null,
+ "max": null,
+ "avg": 49640,
+ "calls": 14
+ },
+ {
+ "method": "registerDigest",
+ "min": 22220,
+ "max": 44132,
+ "avg": 36828,
+ "calls": 3
+ },
+ {
+ "method": "revertWithMessage",
+ "min": null,
+ "max": null,
+ "avg": 21658,
+ "calls": 1
+ },
+ {
+ "method": "setValid",
+ "min": 21682,
+ "max": 43594,
+ "avg": 32638,
+ "calls": 2
+ }
+ ],
+ "bytecodeSize": 2648,
+ "deployedBytecodeSize": 2475
+ },
+ "ExcessReturnDataRecipient": {
+ "name": "ExcessReturnDataRecipient",
+ "methods": [
+ {
+ "method": "setRevertDataSize",
+ "min": null,
+ "max": null,
+ "avg": 43431,
+ "calls": 2
+ }
+ ],
+ "bytecodeSize": 1939,
+ "deployedBytecodeSize": 1912
+ },
+ "LocalConduit": {
+ "name": "LocalConduit",
+ "methods": [
+ {
+ "method": "execute",
+ "min": 77373,
+ "max": 2305522,
+ "avg": 472457,
+ "calls": 6
+ },
+ {
+ "method": "executeBatch1155",
+ "min": null,
+ "max": null,
+ "avg": 97123,
+ "calls": 1
+ },
+ {
+ "method": "executeWithBatch1155",
+ "min": 97570,
+ "max": 361441,
+ "avg": 228655,
+ "calls": 4
+ },
+ {
+ "method": "updateChannel",
+ "min": null,
+ "max": null,
+ "avg": 45782,
+ "calls": 1
+ }
+ ],
+ "bytecodeSize": 3071,
+ "deployedBytecodeSize": 3030
+ },
+ "LocalConduitController": {
+ "name": "LocalConduitController",
+ "methods": [
+ {
+ "method": "acceptOwnership",
+ "min": null,
+ "max": null,
+ "avg": 32543,
+ "calls": 1
+ },
+ {
+ "method": "cancelOwnershipTransfer",
+ "min": null,
+ "max": null,
+ "avg": 27927,
+ "calls": 1
+ },
+ {
+ "method": "createConduit",
+ "min": 676690,
+ "max": 676858,
+ "avg": 676814,
+ "calls": 53
+ },
+ {
+ "method": "transferOwnership",
+ "min": null,
+ "max": null,
+ "avg": 50233,
+ "calls": 2
+ },
+ {
+ "method": "updateChannel",
+ "min": 34369,
+ "max": 120903,
+ "avg": 117103,
+ "calls": 71
+ }
+ ],
+ "bytecodeSize": 12007,
+ "deployedBytecodeSize": 8660
+ },
+ "PausableZone": {
+ "name": "PausableZone",
+ "methods": [
+ {
+ "method": "cancelOrders",
+ "min": null,
+ "max": null,
+ "avg": 63417,
+ "calls": 1
+ }
+ ],
+ "bytecodeSize": 6266,
+ "deployedBytecodeSize": 6162
+ },
+ "PausableZoneController": {
+ "name": "PausableZoneController",
+ "methods": [
+ {
+ "method": "acceptOwnership",
+ "min": null,
+ "max": null,
+ "avg": 28938,
+ "calls": 1
+ },
+ {
+ "method": "assignOperator",
+ "min": null,
+ "max": null,
+ "avg": 50908,
+ "calls": 1
+ },
+ {
+ "method": "assignPauser",
+ "min": null,
+ "max": null,
+ "avg": 47183,
+ "calls": 1
+ },
+ {
+ "method": "cancelOrders",
+ "min": null,
+ "max": null,
+ "avg": 71965,
+ "calls": 1
+ },
+ {
+ "method": "cancelOwnershipTransfer",
+ "min": null,
+ "max": null,
+ "avg": 24574,
+ "calls": 1
+ },
+ {
+ "method": "createZone",
+ "min": null,
+ "max": null,
+ "avg": 1297539,
+ "calls": 31
+ },
+ {
+ "method": "executeMatchAdvancedOrders",
+ "min": null,
+ "max": null,
+ "avg": 288329,
+ "calls": 2
+ },
+ {
+ "method": "executeMatchOrders",
+ "min": null,
+ "max": null,
+ "avg": 281910,
+ "calls": 2
+ },
+ {
+ "method": "pause",
+ "min": 49978,
+ "max": 52108,
+ "avg": 51043,
+ "calls": 4
+ },
+ {
+ "method": "transferOwnership",
+ "min": null,
+ "max": null,
+ "avg": 47206,
+ "calls": 2
+ }
+ ],
+ "bytecodeSize": 19205,
+ "deployedBytecodeSize": 12730
+ },
+ "Reenterer": {
+ "name": "Reenterer",
+ "methods": [
+ {
+ "method": "prepare",
+ "min": 49244,
+ "max": 2331413,
+ "avg": 1060118,
+ "calls": 26
+ }
+ ],
+ "bytecodeSize": 2594,
+ "deployedBytecodeSize": 2567
+ },
+ "Seaport": {
+ "name": "Seaport",
+ "methods": [
+ {
+ "method": "cancel",
+ "min": 39254,
+ "max": 56426,
+ "avg": 52037,
+ "calls": 16
+ },
+ {
+ "method": "fulfillAdvancedOrder",
+ "min": 95544,
+ "max": 226315,
+ "avg": 160995,
+ "calls": 194
+ },
+ {
+ "method": "fulfillAvailableAdvancedOrders",
+ "min": 147377,
+ "max": 331956,
+ "avg": 212398,
+ "calls": 30
+ },
+ {
+ "method": "fulfillAvailableOrders",
+ "min": 162397,
+ "max": 214514,
+ "avg": 201310,
+ "calls": 21
+ },
+ {
+ "method": "fulfillBasicOrder",
+ "min": 88581,
+ "max": 1630460,
+ "avg": 599932,
+ "calls": 187
+ },
+ {
+ "method": "fulfillBasicOrder_efficient_6GL6yc",
+ "min": 88169,
+ "max": 109207,
+ "avg": 98688,
+ "calls": 6
+ },
+ {
+ "method": "fulfillOrder",
+ "min": 118404,
+ "max": 225043,
+ "avg": 178515,
+ "calls": 108
+ },
+ {
+ "method": "incrementCounter",
+ "min": null,
+ "max": null,
+ "avg": 45076,
+ "calls": 6
+ },
+ {
+ "method": "matchAdvancedOrders",
+ "min": 178311,
+ "max": 299621,
+ "avg": 248810,
+ "calls": 72
+ },
+ {
+ "method": "matchOrders",
+ "min": 156684,
+ "max": 343360,
+ "avg": 261700,
+ "calls": 151
+ },
+ {
+ "method": "validate",
+ "min": 51276,
+ "max": 81993,
+ "avg": 71597,
+ "calls": 29
+ }
+ ],
+ "bytecodeSize": 25853,
+ "deployedBytecodeSize": 23963
+ },
+ "SeaportRouter": {
+ "name": "SeaportRouter",
+ "methods": [
+ {
+ "method": "fulfillAvailableAdvancedOrders",
+ "min": 179579,
+ "max": 305411,
+ "avg": 220429,
+ "calls": 8
+ }
+ ],
+ "bytecodeSize": 7172,
+ "deployedBytecodeSize": 6759
+ },
+ "TestContractOfferer": {
+ "name": "TestContractOfferer",
+ "methods": [
+ {
+ "method": "activate",
+ "min": 201532,
+ "max": 246646,
+ "avg": 205405,
+ "calls": 34
+ },
+ {
+ "method": "extendAvailable",
+ "min": null,
+ "max": null,
+ "avg": 50724,
+ "calls": 1
+ },
+ {
+ "method": "extendRequired",
+ "min": null,
+ "max": null,
+ "avg": 45800,
+ "calls": 1
+ }
+ ],
+ "bytecodeSize": 8697,
+ "deployedBytecodeSize": 8505
+ },
+ "TestContractOffererNativeToken": {
+ "name": "TestContractOffererNativeToken",
+ "methods": [
+ {
+ "method": "activate",
+ "min": null,
+ "max": null,
+ "avg": 139191,
+ "calls": 1
+ }
+ ],
+ "bytecodeSize": 6880,
+ "deployedBytecodeSize": 6709
+ },
+ "TestERC1155": {
+ "name": "TestERC1155",
+ "methods": [
+ {
+ "method": "mint",
+ "min": 47221,
+ "max": 49901,
+ "avg": 49492,
+ "calls": 290
+ },
+ {
+ "method": "setApprovalForAll",
+ "min": 26095,
+ "max": 45995,
+ "avg": 45490,
+ "calls": 552
+ }
+ ],
+ "bytecodeSize": 4147,
+ "deployedBytecodeSize": 4120
+ },
+ "TestERC20": {
+ "name": "TestERC20",
+ "methods": [
+ {
+ "method": "approve",
+ "min": 28908,
+ "max": 46272,
+ "avg": 45753,
+ "calls": 266
+ },
+ {
+ "method": "blockTransfer",
+ "min": 21993,
+ "max": 43905,
+ "avg": 32949,
+ "calls": 4
+ },
+ {
+ "method": "mint",
+ "min": 34012,
+ "max": 68476,
+ "avg": 67281,
+ "calls": 128
+ },
+ {
+ "method": "setNoReturnData",
+ "min": 21939,
+ "max": 43851,
+ "avg": 32895,
+ "calls": 2
+ }
+ ],
+ "bytecodeSize": 5835,
+ "deployedBytecodeSize": 4743
+ },
+ "TestERC721": {
+ "name": "TestERC721",
+ "methods": [
+ {
+ "method": "mint",
+ "min": 51478,
+ "max": 68782,
+ "avg": 65781,
+ "calls": 293
+ },
+ {
+ "method": "setApprovalForAll",
+ "min": 26180,
+ "max": 46080,
+ "avg": 45517,
+ "calls": 496
+ }
+ ],
+ "bytecodeSize": 5154,
+ "deployedBytecodeSize": 4413
+ },
+ "TestInvalidContractOfferer": {
+ "name": "TestInvalidContractOfferer",
+ "methods": [
+ {
+ "method": "activate",
+ "min": 201568,
+ "max": 201580,
+ "avg": 201574,
+ "calls": 2
+ }
+ ],
+ "bytecodeSize": 8132,
+ "deployedBytecodeSize": 7947
+ },
+ "TestInvalidContractOffererRatifyOrder": {
+ "name": "TestInvalidContractOffererRatifyOrder",
+ "methods": [
+ {
+ "method": "activate",
+ "min": null,
+ "max": null,
+ "avg": 201571,
+ "calls": 1
+ }
+ ],
+ "bytecodeSize": 8194,
+ "deployedBytecodeSize": 8002
+ },
+ "TransferHelper": {
+ "name": "TransferHelper",
+ "methods": [
+ {
+ "method": "bulkTransfer",
+ "min": 78155,
+ "max": 1469324,
+ "avg": 644677,
+ "calls": 3
+ }
+ ],
+ "bytecodeSize": 4207,
+ "deployedBytecodeSize": 3903
+ }
+ }
+}
\ No newline at end of file
diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml
new file mode 100644
index 000000000..76fc280cf
--- /dev/null
+++ b/.github/workflows/docs.yml
@@ -0,0 +1,22 @@
+name: Publish Docs to Central Repository
+on:
+ release:
+ types: [created]
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v2
+ - name: Copy developer docs to repository
+ if: github.ref == 'refs/heads/main'
+ uses: nkoppel/push-files-to-another-repository@v1.1.1
+ env:
+ API_TOKEN_GITHUB: ${{ secrets.API_TOKEN_GITHUB }}
+ with:
+ source-files: "docs/"
+ destination-username: "ProjectOpenSea"
+ destination-repository: "developer-docs"
+ destination-directory: "seaport"
+ destination-branch: "main"
+ commit-username: "ProjectOpenSea-seaport"
+ commit-message: "Latest docs from seaport"
\ No newline at end of file
diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml
deleted file mode 100644
index 225f0b318..000000000
--- a/.github/workflows/publish.yml
+++ /dev/null
@@ -1,18 +0,0 @@
-name: Publish Package to npmjs
-on:
- release:
- types: [created]
-jobs:
- build:
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v2
- - uses: actions/setup-node@v2
- with:
- node-version: "16.x"
- registry-url: "https://registry.npmjs.org"
- - run: grep -RiIln 'openzeppelin-contracts' src | xargs sed -i 's/openzeppelin\-contracts/@openzeppelin\/contracts/g'
- - run: yarn
- - run: npm publish --access public
- env:
- NODE_AUTH_TOKEN: ${{ secrets.NPM_TOKEN }}
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index b639456e7..b47597b37 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -18,7 +18,7 @@ jobs:
strategy:
matrix:
- node-version: [16.15.1]
+ node-version: [18.15.0]
steps:
- uses: actions/checkout@v3
@@ -36,7 +36,7 @@ jobs:
strategy:
matrix:
- node-version: [16.15.1]
+ node-version: [18.15.0]
steps:
- uses: actions/checkout@v3
@@ -54,7 +54,7 @@ jobs:
strategy:
matrix:
- node-version: [16.15.1]
+ node-version: [18.15.0]
steps:
- uses: actions/checkout@v3
@@ -73,7 +73,7 @@ jobs:
strategy:
matrix:
- node-version: [16.15.1]
+ node-version: [18.15.0]
env:
REFERENCE: true
@@ -107,15 +107,41 @@ jobs:
- name: Install forge dependencies
run: forge install
- - name: Precompile reference using 0.8.13 and via-ir=false
+ - name: Precompile reference using 0.8.24 and via-ir=false
run: FOUNDRY_PROFILE=reference forge build
- - name: Precompile optimized using 0.8.17 and via-ir=true
+ - name: Precompile optimized using 0.8.24 and via-ir=true
run: FOUNDRY_PROFILE=optimized forge build
- name: Run tests
run: FOUNDRY_PROFILE=test forge test -vvv
+ forge-ref:
+ name: Run Forge Reference Tests (via_ir = false; fuzz_runs = 5000)
+ runs-on: ubuntu-latest
+ timeout-minutes: 30
+ steps:
+ - uses: actions/checkout@v3
+ with:
+ submodules: recursive
+
+ - name: Install Foundry
+ uses: foundry-rs/foundry-toolchain@v1
+ with:
+ version: nightly
+
+ - name: Install forge dependencies
+ run: forge install
+
+ - name: Precompile reference using 0.8.24 and via-ir=false
+ run: FOUNDRY_PROFILE=reference forge build
+
+ - name: Precompile optimized using 0.8.24 and via-ir=true
+ run: FOUNDRY_PROFILE=optimized forge build
+
+ - name: Run reference tests
+ run: FOUNDRY_PROFILE=reference MOAT_PROFILE=reference forge test -vvv
+
forge-offerers:
name: Run Contract Offerer Forge Tests (via_ir = false; fuzz_runs = 1000)
runs-on: ubuntu-latest
@@ -132,6 +158,12 @@ jobs:
- name: Install forge dependencies
run: forge install
+ - name: Precompile reference using 0.8.24 and via-ir=false
+ run: FOUNDRY_PROFILE=reference forge build
+
+ - name: Precompile optimized using 0.8.24 and via-ir=true
+ run: FOUNDRY_PROFILE=optimized forge build
+
- name: Run tests
run: FOUNDRY_PROFILE=offerers forge test -vvv
@@ -159,28 +191,29 @@ jobs:
files: ./lcov.info
flags: foundry
- coverage:
- name: Run Coverage Tests
- runs-on: ubuntu-latest
-
- strategy:
- matrix:
- node-version: [16.15.1]
-
- steps:
- - uses: actions/checkout@v3
- - name: Use Node.js
- uses: actions/setup-node@v3
- with:
- node-version: ${{ matrix.node-version }}
- cache: "yarn"
- - run: yarn install
- - run: yarn build
- - run: yarn coverage
- - uses: codecov/codecov-action@v3
- with:
- files: ./coverage/lcov.info
- flags: production
+# TODO: work out how to run legacy coverage (also how to run against core)
+# coverage:
+# name: Run Coverage Tests
+# runs-on: ubuntu-latest
+#
+# strategy:
+# matrix:
+# node-version: [18.15.0]
+#
+# steps:
+# - uses: actions/checkout@v3
+# - name: Use Node.js
+# uses: actions/setup-node@v3
+# with:
+# node-version: ${{ matrix.node-version }}
+# cache: "yarn"
+# - run: yarn install
+# - run: yarn build
+# - run: yarn coverage
+# - uses: codecov/codecov-action@v3
+# with:
+# files: ./coverage/lcov.info
+# flags: production
reference-coverage:
name: Run Reference Coverage Tests
@@ -188,7 +221,7 @@ jobs:
strategy:
matrix:
- node-version: [16.15.1]
+ node-version: [18.15.0]
env:
REFERENCE: true
@@ -207,4 +240,4 @@ jobs:
- uses: codecov/codecov-action@v3
with:
files: ./coverage/lcov.info
- flags: reference
\ No newline at end of file
+ flags: reference
diff --git a/.prettierignore b/.prettierignore
index 47a16e0d9..04c0abc60 100644
--- a/.prettierignore
+++ b/.prettierignore
@@ -6,10 +6,15 @@ gasReporterOutput.json
typechain-types/
-lib/ds-test
-lib/forge-std
-lib/murky
-lib/openzeppelin-contracts
-lib/solmate
+lib/ds-test/
+lib/murky/
+lib/seaport-core/
+lib/seaport-types/
+lib/solarray/
+lib/forge-std/
+lib/openzeppelin-contracts/
+lib/seaport-sol/
+lib/solady/
+lib/solmate/
docs/OrderValidator.md
\ No newline at end of file
diff --git a/README.md b/README.md
index b9ede7c15..a59ba6dfe 100644
--- a/README.md
+++ b/README.md
@@ -33,7 +33,13 @@ Seaport is a marketplace protocol for safely and efficiently buying and selling
Seaport is a marketplace protocol for safely and efficiently buying and selling NFTs. Each listing contains an arbitrary number of items that the offerer is willing to give (the "offer") along with an arbitrary number of items that must be received along with their respective receivers (the "consideration").
-See the [documentation](docs/SeaportDocumentation.md), the [interface](contracts/interfaces/SeaportInterface.sol), and the full [interface documentation](https://docs.opensea.io/v2.0/reference/seaport-overview) for more information on Seaport.
+See the [documentation](docs/SeaportDocumentation.md), the [interface](https://github.com/ProjectOpenSea/seaport-types/blob/main/src/interfaces/ConsiderationInterface.sol), and the full [interface documentation](https://docs.opensea.io/docs/seaport) for more information on Seaport.
+
+This repository is also split into smaller repositories for easier use and integration:
+
+- [seaport-core][seaport-core]
+- [seaport-types][seaport-types]
+- [seaport-sol][seaport-sol]
## Deployments
@@ -49,15 +55,15 @@ See the [documentation](docs/SeaportDocumentation.md), the [interface](contracts
0x00000000006c3852cbEf3e08E8dF289169EdE581 |
-| Seaport 1.2 |
+Seaport 1.2* |
0x00000000000006c7676171937C444f6BDe3D6282 |
-| Seaport 1.3 |
+Seaport 1.3* |
0x0000000000000aD24e80fd803C6ac37206a45f15 |
-| Seaport 1.4 |
+Seaport 1.4* |
0x00000000000001ad428e4906aE43D8F9852d0dD6 |
@@ -65,6 +71,10 @@ See the [documentation](docs/SeaportDocumentation.md), the [interface](contracts
0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC |
+| Seaport 1.6 |
+0x0000000000000068F116a894984e2DB1123eB395 |
+
+
| ConduitController |
0x00000000F9490004C11Cef243f5400493c00Ad63 |
@@ -78,15 +88,15 @@ See the [documentation](docs/SeaportDocumentation.md), the [interface](contracts
-> Note: Seaport 1.2 and Seaport 1.3 both contain known limitations; proceed with caution if interacting with them, particularly when utilizing restricted or contract orders.
+> *Note: Seaport 1.2 through 1.4 contain known limitations; proceed with caution if interacting with them, particularly when utilizing restricted or contract orders.
### Deployments By EVM Chain
| Network |
+Seaport 1.6 |
Seaport 1.5 |
-Seaport 1.4 |
Seaport 1.1 |
ConduitController |
SeaportValidator |
@@ -94,11 +104,11 @@ See the [documentation](docs/SeaportDocumentation.md), the [interface](contracts
| Ethereum |
-[0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC](https://etherscan.io/address/0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC#code)
+[0x0000000000000068F116a894984e2DB1123eB395](https://etherscan.io/address/0x0000000000000068F116a894984e2DB1123eB395#code)
|
-[0x00000000000001ad428e4906aE43D8F9852d0dD6](https://etherscan.io/address/0x00000000000001ad428e4906aE43D8F9852d0dD6#code)
+[0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC](https://etherscan.io/address/0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC#code)
|
@@ -116,39 +126,14 @@ See the [documentation](docs/SeaportDocumentation.md), the [interface](contracts
[0x0000f00000627D293Ab4Dfb40082001724dB006F](https://etherscan.io/address/0x0000f00000627D293Ab4Dfb40082001724dB006F#code)
- |
-| Goerli |
-
-[0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC](https://goerli.etherscan.io/address/0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC#code)
-
- |
-
-[0x00000000000001ad428e4906aE43D8F9852d0dD6](https://goerli.etherscan.io/address/0x00000000000001ad428e4906aE43D8F9852d0dD6#code)
-
- |
-
-[0x00000000006c3852cbEf3e08E8dF289169EdE581](https://goerli.etherscan.io/address/0x00000000006c3852cbEf3e08E8dF289169EdE581#code)
-
- |
-
-[0x00000000F9490004C11Cef243f5400493c00Ad63](https://goerli.etherscan.io/address/0x00000000F9490004C11Cef243f5400493c00Ad63#code)
-
- |
-
-[0x00e5F120f500006757E984F1DED400fc00370000](https://goerli.etherscan.io/address/0x00e5F120f500006757E984F1DED400fc00370000#code)
-
- |
-
-[0x0000f00000627D293Ab4Dfb40082001724dB006F](https://goerli.etherscan.io/address/0x0000f00000627D293Ab4Dfb40082001724dB006F#code)
-
|
| Sepolia |
-[0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC](https://sepolia.etherscan.io/address/0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC#code)
+[0x0000000000000068F116a894984e2DB1123eB395](https://sepolia.etherscan.io/address/0x0000000000000068F116a894984e2DB1123eB395#code)
|
-[0x00000000000001ad428e4906aE43D8F9852d0dD6](https://sepolia.etherscan.io/address/0x00000000000001ad428e4906aE43D8F9852d0dD6#code)
+[0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC](https://sepolia.etherscan.io/address/0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC#code)
|
@@ -169,11 +154,11 @@ See the [documentation](docs/SeaportDocumentation.md), the [interface](contracts
|
| Polygon |
-[0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC](https://polygonscan.com/address/0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC#code)
+[0x0000000000000068F116a894984e2DB1123eB395](https://polygonscan.com/address/0x0000000000000068F116a894984e2DB1123eB395#code)
|
-[0x00000000000001ad428e4906aE43D8F9852d0dD6](https://polygonscan.com/address/0x00000000000001ad428e4906aE43D8F9852d0dD6#code)
+[0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC](https://polygonscan.com/address/0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC#code)
|
@@ -192,38 +177,38 @@ See the [documentation](docs/SeaportDocumentation.md), the [interface](contracts
[0x0000f00000627D293Ab4Dfb40082001724dB006F](https://polygonscan.com/address/0x0000f00000627D293Ab4Dfb40082001724dB006F#code)
|
-| Mumbai |
+ |
| Amoy |
-[0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC](https://mumbai.polygonscan.com/address/0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC#code)
+[0x0000000000000068F116a894984e2DB1123eB395](https://www.oklink.com/amoy/address/0x0000000000000068F116a894984e2DB1123eB395#code)
|
-[0x00000000000001ad428e4906aE43D8F9852d0dD6](https://mumbai.polygonscan.com/address/0x00000000000001ad428e4906aE43D8F9852d0dD6#code)
+[0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC](https://www.oklink.com/amoy/address/0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC#code)
|
-[0x00000000006c3852cbEf3e08E8dF289169EdE581](https://mumbai.polygonscan.com/address/0x00000000006c3852cbEf3e08E8dF289169EdE581#code)
+[0x00000000006c3852cbEf3e08E8dF289169EdE581](https://www.oklink.com/amoy/address/0x00000000006c3852cbEf3e08E8dF289169EdE581#code)
|
-[0x00000000F9490004C11Cef243f5400493c00Ad63](https://mumbai.polygonscan.com/address/0x00000000F9490004C11Cef243f5400493c00Ad63#code)
+[0x00000000F9490004C11Cef243f5400493c00Ad63](https://www.oklink.com/amoy/address/0x00000000F9490004C11Cef243f5400493c00Ad63#code)
|
-[0x00e5F120f500006757E984F1DED400fc00370000](https://mumbai.polygonscan.com/address/0x00e5F120f500006757E984F1DED400fc00370000#code)
+[0x00e5F120f500006757E984F1DED400fc00370000](https://www.oklink.com/amoy/address/0x00e5F120f500006757E984F1DED400fc00370000#code)
|
-[0x0000f00000627D293Ab4Dfb40082001724dB006F](https://mumbai.polygonscan.com/address/0x0000f00000627D293Ab4Dfb40082001724dB006F#code)
+[0x0000f00000627D293Ab4Dfb40082001724dB006F](https://www.oklink.com/amoy/address/0x0000f00000627D293Ab4Dfb40082001724dB006F#code)
|
| Optimism |
-[0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC](https://optimistic.etherscan.io/address/0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC#code)
+[0x0000000000000068F116a894984e2DB1123eB395](https://optimistic.etherscan.io/address/0x0000000000000068F116a894984e2DB1123eB395#code)
|
-[0x00000000000001ad428e4906aE43D8F9852d0dD6](https://optimistic.etherscan.io/address/0x00000000000001ad428e4906aE43D8F9852d0dD6#code)
+[0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC](https://optimistic.etherscan.io/address/0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC#code)
|
@@ -242,38 +227,38 @@ See the [documentation](docs/SeaportDocumentation.md), the [interface](contracts
[0x0000f00000627D293Ab4Dfb40082001724dB006F](https://optimistic.etherscan.io/address/0x0000f00000627D293Ab4Dfb40082001724dB006F#code)
|
-| Optimistic Goerli |
+ |
| Optimism Sepolia |
-[0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC](https://goerli-optimism.etherscan.io/address/0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC#code)
+[0x0000000000000068F116a894984e2DB1123eB395](https://sepolia-optimism.etherscan.io/address/0x0000000000000068F116a894984e2DB1123eB395#code)
|
-[0x00000000000001ad428e4906aE43D8F9852d0dD6](https://goerli-optimism.etherscan.io/address/0x00000000000001ad428e4906aE43D8F9852d0dD6#code)
+[0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC](https://sepolia-optimism.etherscan.io/address/0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC#code)
|
-[0x00000000006c3852cbEf3e08E8dF289169EdE581](https://goerli-optimism.etherscan.io/address/0x00000000006c3852cbEf3e08E8dF289169EdE581#code)
+Not deployed
|
-[0x00000000F9490004C11Cef243f5400493c00Ad63](https://goerli-optimism.etherscan.io/address/0x00000000F9490004C11Cef243f5400493c00Ad63#code)
+[0x00000000F9490004C11Cef243f5400493c00Ad63](https://sepolia-optimism.etherscan.io/address/0x00000000F9490004C11Cef243f5400493c00Ad63#code)
|
-[0x00e5F120f500006757E984F1DED400fc00370000](https://goerli-optimism.etherscan.io/address/0x00e5F120f500006757E984F1DED400fc00370000#code)
+[0x00e5F120f500006757E984F1DED400fc00370000](https://sepolia-optimism.etherscan.io/address/0x00e5F120f500006757E984F1DED400fc00370000#code)
|
-[0x0000f00000627D293Ab4Dfb40082001724dB006F](https://goerli-optimism.etherscan.io/address/0x0000f00000627D293Ab4Dfb40082001724dB006F#code)
+[0x0000f00000627D293Ab4Dfb40082001724dB006F](https://sepolia-optimism.etherscan.io/address/0x0000f00000627D293Ab4Dfb40082001724dB006F#code)
|
| Arbitrum |
-[0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC](https://arbiscan.io/address/0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC#code)
+[0x0000000000000068F116a894984e2DB1123eB395](https://arbiscan.io/address/0x0000000000000068F116a894984e2DB1123eB395#code)
|
-[0x00000000000001ad428e4906aE43D8F9852d0dD6](https://arbiscan.io/address/0x00000000000001ad428e4906aE43D8F9852d0dD6#code)
+[0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC](https://arbiscan.io/address/0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC#code)
|
@@ -292,38 +277,38 @@ See the [documentation](docs/SeaportDocumentation.md), the [interface](contracts
[0x0000f00000627D293Ab4Dfb40082001724dB006F](https://arbiscan.io/address/0x0000f00000627D293Ab4Dfb40082001724dB006F#code)
|
-| Arbitrum Goerli |
+ |
| Arbitrum Sepolia |
-[0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC](https://goerli.arbiscan.io/address/0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC#code)
+[0x0000000000000068F116a894984e2DB1123eB395](https://sepolia.arbiscan.io/address/0x0000000000000068F116a894984e2DB1123eB395#code)
|
-[0x00000000000001ad428e4906aE43D8F9852d0dD6](https://goerli.arbiscan.io/address/0x00000000000001ad428e4906aE43D8F9852d0dD6#code)
+[0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC](https://sepolia.arbiscan.io/address/0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC#code)
|
-[0x00000000006c3852cbEf3e08E8dF289169EdE581](https://goerli.arbiscan.io/address/0x00000000006c3852cbEf3e08E8dF289169EdE581#code)
+Not deployed
|
-[0x00000000F9490004C11Cef243f5400493c00Ad63](https://goerli.arbiscan.io/address/0x00000000F9490004C11Cef243f5400493c00Ad63#code)
+[0x00000000F9490004C11Cef243f5400493c00Ad63](https://sepolia.arbiscan.io/address/0x00000000F9490004C11Cef243f5400493c00Ad63#code)
|
-[0x00e5F120f500006757E984F1DED400fc00370000](https://goerli.arbiscan.io/address/0x00e5F120f500006757E984F1DED400fc00370000#code)
+[0x00e5F120f500006757E984F1DED400fc00370000](https://sepolia.arbiscan.io/address/0x00e5F120f500006757E984F1DED400fc00370000#code)
|
-[0x0000f00000627D293Ab4Dfb40082001724dB006F](https://goerli.arbiscan.io/address/0x0000f00000627D293Ab4Dfb40082001724dB006F#code)
+[0x0000f00000627D293Ab4Dfb40082001724dB006F](https://sepolia.arbiscan.io/address/0x0000f00000627D293Ab4Dfb40082001724dB006F#code)
|
| Arbitrum Nova |
-[0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC](https://nova.arbiscan.io/address/0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC#code)
+[0x0000000000000068F116a894984e2DB1123eB395](https://nova.arbiscan.io/address/0x0000000000000068F116a894984e2DB1123eB395#code)
|
-[0x00000000000001ad428e4906aE43D8F9852d0dD6](https://nova.arbiscan.io/address/0x00000000000001ad428e4906aE43D8F9852d0dD6#code)
+[0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC](https://nova.arbiscan.io/address/0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC#code)
|
@@ -342,9 +327,13 @@ See the [documentation](docs/SeaportDocumentation.md), the [interface](contracts
[0x0000f00000627D293Ab4Dfb40082001724dB006F](https://nova.arbiscan.io/address/0x0000f00000627D293Ab4Dfb40082001724dB006F#code)
|
-| Base Goerli |
+ |
| Base |
-[0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC](https://goerli.basescan.org/address/0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC#code)
+[0x0000000000000068F116a894984e2DB1123eB395](https://basescan.org/address/0x0000000000000068F116a894984e2DB1123eB395)
+
+ |
+
+[0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC](https://basescan.org/address/0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC#code)
|
@@ -352,28 +341,49 @@ Not deployed
|
+[0x00000000F9490004C11Cef243f5400493c00Ad63](https://basescan.org/address/0x00000000f9490004c11cef243f5400493c00ad63)
+
+ |
+
+[0x00e5F120f500006757E984F1DED400fc00370000](https://basescan.org/address/0x00e5f120f500006757e984f1ded400fc00370000)
+
+ |
+
+[0x0000f00000627D293Ab4Dfb40082001724dB006F](https://basescan.org/address/0x0000f00000627D293Ab4Dfb40082001724dB006F#code)
+
+ |
+| Base Sepolia |
+
+[0x0000000000000068F116a894984e2DB1123eB395](https://sepolia.basescan.org/address/0x0000000000000068F116a894984e2DB1123eB395#code)
+
+ |
+
+[0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC](https://sepolia.basescan.org/address/0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC#code)
+
+ |
+
Not deployed
|
-[0x00000000F9490004C11Cef243f5400493c00Ad63](https://goerli.basescan.org/address/0x00000000F9490004C11Cef243f5400493c00Ad63#code)
+[0x00000000F9490004C11Cef243f5400493c00Ad63](https://sepolia.basescan.org/address/0x00000000f9490004c11cef243f5400493c00ad63)
|
-[0x00e5F120f500006757E984F1DED400fc00370000](https://goerli.basescan.org/address/0x00e5F120f500006757E984F1DED400fc00370000#code)
+[0x00e5F120f500006757E984F1DED400fc00370000](https://sepolia.basescan.org/address/0x00e5f120f500006757e984f1ded400fc00370000)
|
-[0x0000f00000627D293Ab4Dfb40082001724dB006F](https://goerli.basescan.org/address/0x0000f00000627D293Ab4Dfb40082001724dB006F#code)
+[0x0000f00000627D293Ab4Dfb40082001724dB006F](https://sepolia.basescan.org/address/0x0000f00000627D293Ab4Dfb40082001724dB006F#code)
|
| Avalanche C-Chain |
-[0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC](https://snowtrace.io/address/0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC#code)
+[0x0000000000000068F116a894984e2DB1123eB395](https://snowtrace.io/address/0x0000000000000068F116a894984e2DB1123eB395#code)
|
-[0x00000000000001ad428e4906aE43D8F9852d0dD6](https://snowtrace.io/address/0x00000000000001ad428e4906aE43D8F9852d0dD6#code)
+[0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC](https://snowtrace.io/address/0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC#code)
|
@@ -394,11 +404,11 @@ Not deployed
|
| Avalanche Fuji |
-[0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC](https://testnet.snowtrace.io/address/0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC#code)
+[0x0000000000000068F116a894984e2DB1123eB395](https://testnet.snowtrace.io/address/0x0000000000000068F116a894984e2DB1123eB395#code)
|
-[0x00000000000001ad428e4906aE43D8F9852d0dD6](https://testnet.snowtrace.io/address/0x00000000000001ad428e4906aE43D8F9852d0dD6#code)
+[0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC](https://testnet.snowtrace.io/address/0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC#code)
|
@@ -419,11 +429,11 @@ Not deployed
|
| Gnosis Chain |
-[0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC](https://gnosisscan.io/address/0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC#code)
+[0x0000000000000068F116a894984e2DB1123eB395](https://gnosisscan.io/address/0x0000000000000068F116a894984e2DB1123eB395#code)
|
-[0x00000000000001ad428e4906aE43D8F9852d0dD6](https://gnosisscan.io/address/0x00000000000001ad428e4906aE43D8F9852d0dD6#code)
+[0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC](https://gnosisscan.io/address/0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC#code)
|
@@ -435,7 +445,7 @@ Not deployed
|
-Not deployed
+[0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC](https://gnosisscan.io/address/0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC#code)
|
@@ -444,11 +454,11 @@ Not deployed
|
| Chiado |
-[0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC](https://blockscout.com/gnosis/chiado/address/0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC/contracts#address-tabs)
+[0x0000000000000068F116a894984e2DB1123eB395](https://blockscout.com/gnosis/chiado/address/0x0000000000000068F116a894984e2DB1123eB395/contracts#address-tabs)
|
-Not deployed
+[0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC](https://blockscout.com/gnosis/chiado/address/0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC/contracsts#address-tabs)
|
@@ -469,11 +479,11 @@ Not deployed
|
| BSC |
-[0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC](https://bscscan.com/address/0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC#code)
+[0x0000000000000068F116a894984e2DB1123eB395](https://bscscan.com/address/0x0000000000000068F116a894984e2DB1123eB395#code)
|
-[0x00000000000001ad428e4906aE43D8F9852d0dD6](https://bscscan.com/address/0x00000000000001ad428e4906aE43D8F9852d0dD6#code)
+[0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC](https://bscscan.com/address/0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC#code)
|
@@ -494,11 +504,11 @@ Not deployed
|
| BSC Testnet |
-[0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC](https://testnet.bscscan.com/address/0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC#code)
+[0x0000000000000068F116a894984e2DB1123eB395](https://testnet.bscscan.com/address/0x0000000000000068F116a894984e2DB1123eB395#code)
|
-[0x00000000000001ad428e4906aE43D8F9852d0dD6](https://testnet.bscscan.com/address/0x00000000000001ad428e4906aE43D8F9852d0dD6#code)
+[0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC](https://testnet.bscscan.com/address/0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC#code)
|
@@ -519,11 +529,11 @@ Not deployed
|
| Klaytn |
-[0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC](https://scope.klaytn.com/address/0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC#code)
+[0x0000000000000068F116a894984e2DB1123eB395](https://scope.klaytn.com/address/0x0000000000000068F116a894984e2DB1123eB395#code)
|
-[0x00000000000001ad428e4906aE43D8F9852d0dD6](https://scope.klaytn.com/address/0x00000000000001ad428e4906aE43D8F9852d0dD6#code)
+[0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC](https://scope.klaytn.com/address/0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC#code)
|
@@ -544,11 +554,11 @@ Not deployed
|
| Baobab |
-[0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC](https://baobab.scope.klaytn.com/address/0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC#code)
+[0x0000000000000068F116a894984e2DB1123eB395](https://baobab.scope.klaytn.com/address/0x0000000000000068F116a894984e2DB1123eB395#code)
|
-[0x00000000000001ad428e4906aE43D8F9852d0dD6](https://baobab.scope.klaytn.com/address/0x00000000000001ad428e4906aE43D8F9852d0dD6#code)
+[0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC](https://baobab.scope.klaytn.com/address/0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC#code)
|
@@ -569,11 +579,11 @@ Not deployed
|
| Moonbeam |
-[0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC](https://moonscan.io/address/0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC#code)
+[0x0000000000000068F116a894984e2DB1123eB395](https://moonscan.io/address/0x0000000000000068F116a894984e2DB1123eB395#code)
|
-Not deployed
+[0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC](https://moonscan.io/address/0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC#code)
|
@@ -594,11 +604,11 @@ Not deployed
|
| Moonriver |
-[0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC](https://moonriver.moonscan.io/address/0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC#code)
+[0x0000000000000068F116a894984e2DB1123eB395](https://moonriver.moonscan.io/address/0x0000000000000068F116a894984e2DB1123eB395#code)
|
-Not deployed
+[0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC](https://moonriver.moonscan.io/address/0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC#code)
|
@@ -620,11 +630,11 @@ Not deployed
|
| Canto |
-[0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC](https://evm.explorer.canto.io/address/0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC#code)
+[0x0000000000000068F116a894984e2DB1123eB395](https://evm.explorer.canto.io/address/0x0000000000000068F116a894984e2DB1123eB395#code)
|
-[0x00000000000001ad428e4906aE43D8F9852d0dD6](https://evm.explorer.canto.io/address/0x00000000000001ad428e4906aE43D8F9852d0dD6)
+[0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC](https://evm.explorer.canto.io/address/0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC)
|
@@ -646,11 +656,11 @@ Not deployed
|
| Fantom |
-[0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC](https://ftmscan.com/address/0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC#code)
+[0x0000000000000068F116a894984e2DB1123eB395](https://ftmscan.com/address/0x0000000000000068F116a894984e2DB1123eB395#code)
|
-Not deployed
+[0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC](https://ftmscan.com/address/0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC#code)
|
@@ -672,11 +682,11 @@ Not deployed
|
| Celo |
-[0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC](https://celoscan.io/address/0x00000000000000adc04c56bf30ac9d3c0aaf14dc#code)
+[0x0000000000000068F116a894984e2DB1123eB395](https://celoscan.io/address/0x0000000000000068F116a894984e2DB1123eB395#code)
|
-Not deployed
+[0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC](https://celoscan.io/address/0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC#code)
|
@@ -695,13 +705,58 @@ Not deployed
Not deployed
|
-
-To be deployed on other EVM chains, such as:
+| Zora |
+
+[0x0000000000000068F116a894984e2DB1123eB395](https://explorer.zora.energy/address/0x0000000000000068F116a894984e2DB1123eB395#code)
+
+ |
+
+[0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC](https://explorer.zora.energy/address/0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC#code)
+
+ |
+
+Not deployed
+
+ |
+
+[0x00000000F9490004C11Cef243f5400493c00Ad63](https://explorer.zora.energy/address/0x00000000f9490004c11cef243f5400493c00ad63)
+
+ |
+
+[0x00e5F120f500006757E984F1DED400fc00370000](https://explorer.zora.energy/address/0x00e5f120f500006757e984f1ded400fc00370000)
+
+ |
+
+[0x0000f00000627D293Ab4Dfb40082001724dB006F](https://explorer.zora.energy/address/0x0000f00000627D293Ab4Dfb40082001724dB006F#code)
+
+ |
+| Zora Sepolia |
+
+[0x0000000000000068F116a894984e2DB1123eB395](https://sepolia.explorer.zora.energy/address/0x0000000000000068F116a894984e2DB1123eB395#code)
+
+ |
+
+[0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC](https://sepolia.explorer.zora.energy/address/0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC#code)
-- RSK
-- Boba
-- Aurora
+ |
+
+Not deployed
+
+ |
+
+[0x00000000F9490004C11Cef243f5400493c00Ad63](https://sepolia.explorer.zora.energy/address/0x00000000f9490004c11cef243f5400493c00ad63)
+
+ |
+
+[0x00e5F120f500006757E984F1DED400fc00370000](https://sepolia.explorer.zora.energy/address/0x00e5f120f500006757e984f1ded400fc00370000)
+
+ |
+
+[0x0000f00000627D293Ab4Dfb40082001724dB006F](https://sepolia.explorer.zora.energy/address/0x0000f00000627D293Ab4Dfb40082001724dB006F#code)
+
+ |
+
To deploy to a new EVM chain, follow the [steps outlined here](docs/Deployment.md).
@@ -889,3 +944,6 @@ When making a pull request, ensure that:
[js-library-link]: https://github.com/ProjectOpenSea/seaport-js
[discord-badge]: https://img.shields.io/static/v1?logo=discord&label=discord&message=Join&color=blue
[discord-link]: https://discord.gg/ADXcTXpqry
+[seaport-core]: https://github.com/ProjectOpenSea/seaport-core
+[seaport-types]: https://github.com/ProjectOpenSea/seaport-types
+[seaport-sol]: https://github.com/ProjectOpenSea/seaport-sol
diff --git a/config/.solhintignore b/config/.solhintignore
index 8d4fb4245..b4ac21a5c 100644
--- a/config/.solhintignore
+++ b/config/.solhintignore
@@ -1,6 +1,7 @@
node_modules/
contracts/test/
+contracts/zones/PausableZone.sol
test/
lib/
\ No newline at end of file
diff --git a/contracts/Seaport.sol b/contracts/Seaport.sol
index bea2dc2ae..043a473b3 100644
--- a/contracts/Seaport.sol
+++ b/contracts/Seaport.sol
@@ -1,22 +1,22 @@
// SPDX-License-Identifier: MIT
-pragma solidity 0.8.17;
+pragma solidity 0.8.24;
import { Consideration } from "seaport-core/src/lib/Consideration.sol";
/**
* @title Seaport
- * @custom:version 1.5
+ * @custom:version 1.6
* @author 0age (0age.eth)
* @custom:coauthor d1ll0n (d1ll0n.eth)
* @custom:coauthor transmissions11 (t11s.eth)
* @custom:coauthor James Wenzel (emo.eth)
+ * @custom:coauthor Daniel Viau (snotrocket.eth)
* @custom:contributor Kartik (slokh.eth)
* @custom:contributor LeFevre (lefevre.eth)
* @custom:contributor Joseph Schiarizzi (CupOJoseph.eth)
* @custom:contributor Aspyn Palatnick (stuckinaboot.eth)
* @custom:contributor Stephan Min (stephanm.eth)
* @custom:contributor Ryan Ghods (ralxz.eth)
- * @custom:contributor Daniel Viau (snotrocket.eth)
* @custom:contributor hack3r-0m (hack3r-0m.eth)
* @custom:contributor Diego Estevez (antidiego.eth)
* @custom:contributor Chomtana (chomtana.eth)
diff --git a/contracts/conduit/Conduit.sol b/contracts/conduit/Conduit.sol
index 75fc3ea0f..4eb6490cf 100644
--- a/contracts/conduit/Conduit.sol
+++ b/contracts/conduit/Conduit.sol
@@ -15,4 +15,6 @@ import { Conduit as CoreConduit } from "seaport-core/src/conduit/Conduit.sol";
* approved ERC20/721/1155 tokens to be taken immediately — be extremely
* cautious with what conduits you give token approvals to!*
*/
-contract LocalConduit is CoreConduit {}
+contract LocalConduit is CoreConduit {
+
+}
diff --git a/contracts/conduit/ConduitController.sol b/contracts/conduit/ConduitController.sol
index 27e2b60e0..ad654f87e 100644
--- a/contracts/conduit/ConduitController.sol
+++ b/contracts/conduit/ConduitController.sol
@@ -1,7 +1,9 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
-import { ConduitController as CoreConduitController } from "seaport-core/src/conduit/ConduitController.sol";
+import {
+ ConduitController as CoreConduitController
+} from "seaport-core/src/conduit/ConduitController.sol";
/**
* @title ConduitController
@@ -10,4 +12,6 @@ import { ConduitController as CoreConduitController } from "seaport-core/src/con
* contracts that allow registered callers (or open "channels") to
* transfer approved ERC20/721/1155 tokens on their behalf.
*/
-contract LocalConduitController is CoreConduitController {}
+contract LocalConduitController is CoreConduitController {
+
+}
diff --git a/contracts/helpers/SeaportRouter.sol b/contracts/helpers/SeaportRouter.sol
index 9b1920695..fb63bc2e9 100644
--- a/contracts/helpers/SeaportRouter.sol
+++ b/contracts/helpers/SeaportRouter.sol
@@ -26,20 +26,20 @@ import {
* all consideration items across all listings are native tokens.
*/
contract SeaportRouter is SeaportRouterInterface, ReentrancyGuard {
- /// @dev The allowed v1.4 contract usable through this router.
- address private immutable _SEAPORT_V1_4;
/// @dev The allowed v1.5 contract usable through this router.
address private immutable _SEAPORT_V1_5;
+ /// @dev The allowed v1.6 contract usable through this router.
+ address private immutable _SEAPORT_V1_6;
/**
* @dev Deploy contract with the supported Seaport contracts.
*
- * @param seaportV1point4 The address of the Seaport v1.4 contract.
* @param seaportV1point5 The address of the Seaport v1.5 contract.
+ * @param seaportV1point6 The address of the Seaport v1.6 contract.
*/
- constructor(address seaportV1point4, address seaportV1point5) {
- _SEAPORT_V1_4 = seaportV1point4;
+ constructor(address seaportV1point5, address seaportV1point6) {
_SEAPORT_V1_5 = seaportV1point5;
+ _SEAPORT_V1_6 = seaportV1point6;
}
/**
@@ -218,8 +218,8 @@ contract SeaportRouter is SeaportRouterInterface, ReentrancyGuard {
returns (address[] memory seaportContracts)
{
seaportContracts = new address[](2);
- seaportContracts[0] = _SEAPORT_V1_4;
- seaportContracts[1] = _SEAPORT_V1_5;
+ seaportContracts[0] = _SEAPORT_V1_5;
+ seaportContracts[1] = _SEAPORT_V1_6;
}
/**
@@ -227,7 +227,7 @@ contract SeaportRouter is SeaportRouterInterface, ReentrancyGuard {
*/
function _assertSeaportAllowed(address seaport) internal view {
if (
- _cast(seaport == _SEAPORT_V1_4) | _cast(seaport == _SEAPORT_V1_5) ==
+ _cast(seaport == _SEAPORT_V1_5) | _cast(seaport == _SEAPORT_V1_6) ==
0
) {
revert SeaportNotAllowed(seaport);
diff --git a/contracts/helpers/TransferHelper.sol b/contracts/helpers/TransferHelper.sol
index dba38197a..aa60a3308 100644
--- a/contracts/helpers/TransferHelper.sol
+++ b/contracts/helpers/TransferHelper.sol
@@ -1,14 +1,18 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
-import { IERC721Receiver } from "seaport-types/src/interfaces/IERC721Receiver.sol";
+import {
+ IERC721Receiver
+} from "seaport-types/src/interfaces/IERC721Receiver.sol";
import {
TransferHelperItem,
TransferHelperItemsWithRecipient
} from "seaport-types/src/helpers/TransferHelperStructs.sol";
-import { ConduitItemType } from "seaport-types/src/conduit/lib/ConduitEnums.sol";
+import {
+ ConduitItemType
+} from "seaport-types/src/conduit/lib/ConduitEnums.sol";
import {
ConduitInterface
@@ -18,7 +22,9 @@ import {
ConduitControllerInterface
} from "seaport-types/src/interfaces/ConduitControllerInterface.sol";
-import { ConduitTransfer } from "seaport-types/src/conduit/lib/ConduitStructs.sol";
+import {
+ ConduitTransfer
+} from "seaport-types/src/conduit/lib/ConduitStructs.sol";
import {
TransferHelperInterface
@@ -122,11 +128,14 @@ contract TransferHelper is TransferHelperInterface, TransferHelperErrors {
)
);
- // Declare a variable to store the sum of all items across transfers.
- uint256 sumOfItemsAcrossAllTransfers;
+ // Declare a new array in memory to track each conduit transfer.
+ ConduitTransfer[] memory conduitTransfers;
// Skip overflow checks: all for loops are indexed starting at zero.
unchecked {
+ // Declare a variable to store sum of all items across transfers.
+ uint256 sumOfItemsAcrossAllTransfers;
+
// Iterate over each transfer.
for (uint256 i = 0; i < numTransfers; ++i) {
// Retrieve the transfer in question.
@@ -137,85 +146,21 @@ contract TransferHelper is TransferHelperInterface, TransferHelperErrors {
// Increment totalItems by the number of items in the transfer.
sumOfItemsAcrossAllTransfers += transfer.items.length;
}
+
+ // Assign length totalItems to populate with each conduit transfer.
+ conduitTransfers = new ConduitTransfer[](
+ sumOfItemsAcrossAllTransfers
+ );
}
- // Declare a new array in memory with length totalItems to populate with
- // each conduit transfer.
- ConduitTransfer[] memory conduitTransfers = new ConduitTransfer[](
- sumOfItemsAcrossAllTransfers
+ // Process the conduit transfers and prepare to execute them.
+ _processConduitTransfers(
+ conduitTransfers,
+ transfers,
+ conduit,
+ numTransfers
);
- // Declare an index for storing ConduitTransfers in conduitTransfers.
- uint256 itemIndex;
-
- // Skip overflow checks: all for loops are indexed starting at zero.
- unchecked {
- // Iterate over each transfer.
- for (uint256 i = 0; i < numTransfers; ++i) {
- // Retrieve the transfer in question.
- TransferHelperItemsWithRecipient calldata transfer = transfers[
- i
- ];
-
- // Retrieve the items of the transfer in question.
- TransferHelperItem[] calldata transferItems = transfer.items;
-
- // Ensure recipient is not the zero address.
- _checkRecipientIsNotZeroAddress(transfer.recipient);
-
- // Create a boolean indicating whether validateERC721Receiver
- // is true and recipient is a contract.
- bool callERC721Receiver = transfer.validateERC721Receiver &&
- transfer.recipient.code.length != 0;
-
- // Retrieve the total number of items in the transfer and
- // place on stack.
- uint256 numItemsInTransfer = transferItems.length;
-
- // Iterate over each item in the transfer to create a
- // corresponding ConduitTransfer.
- for (uint256 j = 0; j < numItemsInTransfer; ++j) {
- // Retrieve the item from the transfer.
- TransferHelperItem calldata item = transferItems[j];
-
- if (item.itemType == ConduitItemType.ERC20) {
- // Ensure that the identifier of an ERC20 token is 0.
- if (item.identifier != 0) {
- revert InvalidERC20Identifier();
- }
- }
-
- // If the item is an ERC721 token and
- // callERC721Receiver is true...
- if (item.itemType == ConduitItemType.ERC721) {
- if (callERC721Receiver) {
- // Check if the recipient implements
- // onERC721Received for the given tokenId.
- _checkERC721Receiver(
- conduit,
- transfer.recipient,
- item.identifier
- );
- }
- }
-
- // Create a ConduitTransfer corresponding to each
- // TransferHelperItem.
- conduitTransfers[itemIndex] = ConduitTransfer(
- item.itemType,
- item.token,
- msg.sender,
- transfer.recipient,
- item.identifier,
- item.amount
- );
-
- // Increment the index for storing ConduitTransfers.
- ++itemIndex;
- }
- }
- }
-
// Attempt the external call to transfer tokens via the derived conduit.
try ConduitInterface(conduit).execute(conduitTransfers) returns (
bytes4 conduitMagicValue
@@ -333,6 +278,113 @@ contract TransferHelper is TransferHelperInterface, TransferHelperErrors {
}
}
+ /**
+ * @notice An internal function that prepares conduit transfers.
+ *
+ * @param conduitTransfers The allocated conduit transfers array.
+ * @param transfers The transfers in question.
+ * @param conduit The conduit in question.
+ * @param numTransfers The total number of transfers.
+ */
+ function _processConduitTransfers(
+ ConduitTransfer[] memory conduitTransfers,
+ TransferHelperItemsWithRecipient[] calldata transfers,
+ address conduit,
+ uint256 numTransfers
+ ) internal {
+ // Skip overflow checks: all for loops are indexed starting at zero.
+ unchecked {
+ // Declare index to store ConduitTransfers in conduitTransfers.
+ uint256 itemIndex;
+
+ // Iterate over each transfer.
+ for (uint256 i = 0; i < numTransfers; ++i) {
+ // Retrieve the transfer in question.
+ TransferHelperItemsWithRecipient calldata transfer = transfers[
+ i
+ ];
+
+ // Retrieve the items of the transfer in question.
+ TransferHelperItem[] calldata transferItems = transfer.items;
+
+ // Ensure recipient is not the zero address.
+ _checkRecipientIsNotZeroAddress(transfer.recipient);
+
+ // Create a boolean indicating whether validateERC721Receiver
+ // is true and recipient is a contract.
+ bool callERC721Receiver = transfer.validateERC721Receiver &&
+ transfer.recipient.code.length != 0;
+
+ // Retrieve the total number of items in the transfer and
+ // place on stack.
+ uint256 numItemsInTransfer = transferItems.length;
+
+ // Iterate over each item in the transfer to create a
+ // corresponding ConduitTransfer.
+ for (uint256 j = 0; j < numItemsInTransfer; ++j) {
+ // Retrieve the item from the transfer.
+ TransferHelperItem calldata item = transferItems[j];
+
+ if (item.itemType == ConduitItemType.ERC20) {
+ // Ensure that the identifier of an ERC20 token is 0.
+ if (item.identifier != 0) {
+ revert InvalidERC20Identifier();
+ }
+ }
+
+ // If the item is an ERC721 token and
+ // callERC721Receiver is true...
+ if (item.itemType == ConduitItemType.ERC721) {
+ if (callERC721Receiver) {
+ // Check if the recipient implements
+ // onERC721Received for the given tokenId.
+ _checkERC721Receiver(
+ conduit,
+ transfer.recipient,
+ item.identifier
+ );
+ }
+ }
+
+ // Create a ConduitTransfer corresponding to each
+ // TransferHelperItem.
+ conduitTransfers[itemIndex] = _createConduitTransfer(
+ item,
+ transfer
+ );
+
+ // Increment the index for storing ConduitTransfers.
+ ++itemIndex;
+ }
+ }
+ }
+ }
+
+ /**
+ * @notice Internal view function to create a ConduitTransfer from a
+ * TransferHelperItem and a TransferHelperItemsWithRecipient.
+ *
+ * @param item The item to transfer.
+ * @param transfer The transfer to create a ConduitTransfer from.
+ *
+ * @return conduitTransfer The ConduitTransfer created from the item and
+ * transfer.
+ */
+ function _createConduitTransfer(
+ TransferHelperItem calldata item,
+ TransferHelperItemsWithRecipient calldata transfer
+ ) internal view returns (ConduitTransfer memory conduitTransfer) {
+ return
+ ConduitTransfer(
+ item.itemType,
+ item.token,
+ msg.sender,
+ transfer.recipient,
+ item.identifier,
+ item.amount
+ );
+ }
+
/**
* @notice An internal function that reverts if the passed-in recipient
* is the zero address.
diff --git a/contracts/helpers/navigator/SeaportNavigator.sol b/contracts/helpers/navigator/SeaportNavigator.sol
index 9997b33a3..c8aae71e9 100644
--- a/contracts/helpers/navigator/SeaportNavigator.sol
+++ b/contracts/helpers/navigator/SeaportNavigator.sol
@@ -4,10 +4,6 @@ pragma solidity ^0.8.17;
import {
ConsiderationInterface
} from "seaport-types/src/interfaces/ConsiderationInterface.sol";
-import {
- AdvancedOrder,
- CriteriaResolver
-} from "seaport-types/src/lib/ConsiderationStructs.sol";
import {
SeaportValidatorInterface
@@ -37,16 +33,16 @@ import { HelperInterface } from "./lib/HelperInterface.sol";
* and optionally generate criteria resolvers from provided token IDs.
*/
contract SeaportNavigator is SeaportNavigatorInterface {
- using NavigatorContextLib for NavigatorContext;
using CriteriaHelperLib for uint256[];
+ using NavigatorContextLib for NavigatorContext;
- HelperInterface public immutable requestValidator;
HelperInterface public immutable criteriaHelper;
- HelperInterface public immutable validatorHelper;
- HelperInterface public immutable orderDetailsHelper;
+ HelperInterface public immutable executionsHelper;
HelperInterface public immutable fulfillmentsHelper;
+ HelperInterface public immutable orderDetailsHelper;
+ HelperInterface public immutable requestValidator;
HelperInterface public immutable suggestedActionHelper;
- HelperInterface public immutable executionsHelper;
+ HelperInterface public immutable validatorHelper;
HelperInterface[] public helpers;
diff --git a/contracts/helpers/navigator/lib/CriteriaHelper.sol b/contracts/helpers/navigator/lib/CriteriaHelper.sol
index d132a6748..8cc64945a 100644
--- a/contracts/helpers/navigator/lib/CriteriaHelper.sol
+++ b/contracts/helpers/navigator/lib/CriteriaHelper.sol
@@ -1,10 +1,6 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
-import {
- CriteriaResolver
-} from "seaport-types/src/lib/ConsiderationStructs.sol";
-
import {
NavigatorCriteriaResolverLib
} from "./NavigatorCriteriaResolverLib.sol";
diff --git a/contracts/helpers/navigator/lib/CriteriaHelperLib.sol b/contracts/helpers/navigator/lib/CriteriaHelperLib.sol
index a50a69ac0..6cd661724 100644
--- a/contracts/helpers/navigator/lib/CriteriaHelperLib.sol
+++ b/contracts/helpers/navigator/lib/CriteriaHelperLib.sol
@@ -72,9 +72,12 @@ library CriteriaHelperLib {
function sortByHash(
uint256[] memory tokenIds
) internal pure returns (uint256[] memory sortedIds) {
+ // Instantiate a new array of HashAndIntTuple structs.
HashAndIntTuple[] memory toSort = new HashAndIntTuple[](
tokenIds.length
);
+
+ // Populate the array of HashAndIntTuple structs.
for (uint256 i = 0; i < tokenIds.length; i++) {
toSort[i] = HashAndIntTuple(
tokenIds[i],
@@ -82,8 +85,10 @@ library CriteriaHelperLib {
);
}
+ // Sort the array of HashAndIntTuple structs.
_quickSort(toSort, 0, int256(toSort.length - 1));
+ // Populate the sortedIds array with the sorted token ids.
sortedIds = new uint256[](tokenIds.length);
for (uint256 i = 0; i < tokenIds.length; i++) {
sortedIds[i] = toSort[i].num;
@@ -97,25 +102,52 @@ library CriteriaHelperLib {
function toSortedHashes(
uint256[] memory tokenIds
) internal pure returns (bytes32[] memory hashes) {
+ // Instantiate a new array of hashes.
hashes = new bytes32[](tokenIds.length);
+
+ // Sort the token ids by their hashes.
uint256[] memory ids = sortByHash(tokenIds);
+
+ // Hash each token id and store it in the hashes array.
for (uint256 i; i < ids.length; ++i) {
hashes[i] = keccak256(abi.encode(ids[i]));
}
}
+ /**
+ * @dev This function performs the quick sort algorithm to sort an array of
+ * HashAndIntTuple structs.
+ *
+ * @param arr The array of HashAndIntTuple structs to be sorted.
+ * @param left The starting index of the segment to be sorted.
+ * @param right The ending index of the segment to be sorted.
+ */
function _quickSort(
HashAndIntTuple[] memory arr,
int256 left,
int256 right
) internal pure {
+ // Initialize pointers i and j to the left and right ends of the array
+ // segment.
int256 i = left;
int256 j = right;
+
+ // If the segment has one element or none, it's already sorted.
if (i == j) return;
+
+ // Pick a 'pivot' element from the middle of the list.
bytes32 pivot = arr[uint256(left + (right - left) / 2)].hash;
+
+ // The main loop to rearrange elements around the pivot.
while (i <= j) {
+ // Find an element larger than or equal to the pivot from the left.
while (arr[uint256(i)].hash < pivot) i++;
+
+ // Find an element smaller than or equal to the pivot from the
+ // right.
while (pivot < arr[uint256(j)].hash) j--;
+
+ // Swap the elements at i and j if needed.
if (i <= j) {
(arr[uint256(i)], arr[uint256(j)]) = (
arr[uint256(j)],
@@ -125,7 +157,11 @@ library CriteriaHelperLib {
j--;
}
}
+
+ // Recursively sort the segment before 'j'.
if (left < j) _quickSort(arr, left, j);
+
+ // Recursively sort the segment after 'i'.
if (i < right) _quickSort(arr, i, right);
}
}
diff --git a/contracts/helpers/navigator/lib/HelperItemLib.sol b/contracts/helpers/navigator/lib/HelperItemLib.sol
index 824057f8c..c381856aa 100644
--- a/contracts/helpers/navigator/lib/HelperItemLib.sol
+++ b/contracts/helpers/navigator/lib/HelperItemLib.sol
@@ -17,6 +17,21 @@ library HelperItemLib {
*/
error UnknownItemType();
+ /**
+ * @dev Normalizes the type of a NavigatorOfferItem based on the presence of
+ * criteria. This originated in the context of the fuzz tests in
+ * ./test/foundry/new, where an item might be assigned a pseudorandom
+ * type and a pseudorandom criteria. In this context, it will just
+ * correct an incorrect item type. If the item has criteria, ERC721 and
+ * ERC1155 items will be normalized to ERC721_WITH_CRITERIA and
+ * ERC1155_WITH_CRITERIA, respectively. Reverts with UnknownItemType if
+ * the item type is neither ERC721, ERC721_WITH_CRITERIA, ERC1155, nor
+ * ERC1155_WITH_CRITERIA.
+ *
+ * @param item The NavigatorOfferItem to normalize.
+ *
+ * @return ItemType The normalized item type.
+ */
function normalizeType(
NavigatorOfferItem memory item
) internal pure returns (ItemType) {
@@ -40,6 +55,19 @@ library HelperItemLib {
}
}
+ /**
+ * @dev Normalizes the type of a NavigatorConsiderationItem based on the
+ * presence of criteria. This originated in the context of the fuzz
+ * tests in ./test/foundry/new, where an item might be assigned a
+ * pseudorandom type and a pseudorandom criteriaOrIdentifier. In this
+ * context, it will just correct an incorrect item type. If the item
+ * has criteria, ERC721 and ERC1155 items will be normalized to
+ * ERC721_WITH_CRITERIA and ERC1155_WITH_CRITERIA, respectively.
+ *
+ * @param item The NavigatorConsiderationItem to normalize.
+ *
+ * @return ItemType The normalized item type.
+ */
function normalizeType(
NavigatorConsiderationItem memory item
) internal pure returns (ItemType) {
@@ -66,32 +94,47 @@ library HelperItemLib {
function hasCriteria(
NavigatorOfferItem memory item
) internal pure returns (bool) {
+ // Candidate identifiers are passed in by the caller as an array of
+ // uint256s and converted by Navigator.
return item.candidateIdentifiers.length > 0;
}
function hasCriteria(
NavigatorConsiderationItem memory item
) internal pure returns (bool) {
+ // Candidate identifiers are passed in by the caller as an array of
+ // uint256s and converted by Navigator.
return item.candidateIdentifiers.length > 0;
}
function validate(NavigatorOfferItem memory item) internal pure {
ItemType itemType = item.itemType;
+
+ // If the item has criteria, the item type must be ERC721 or ERC1155.
if (itemType == ItemType.ERC20 || itemType == ItemType.NATIVE) {
- if (item.candidateIdentifiers.length > 0) {
+ if (hasCriteria(item)) {
revert InvalidItemTypeForCandidateIdentifiers();
} else {
return;
}
}
- // If the item has candidate identifiers, the item identifier must be
- // zero for wildcard or one of the candidates.
+
+ // If the item has no candidate identifiers, the item identifier must be
+ // non-zero.
+ //
+ // NOTE: This is only called after `item.hasCriteria()` checks
+ // which ensure that `item.candidateIdentifiers.length > 0` but if it
+ // were used in other contexts, this would prohibit the use of
+ // legitimate 0 identifiers.
if (item.candidateIdentifiers.length == 0 && item.identifier == 0) {
revert InvalidIdentifier(
item.identifier,
item.candidateIdentifiers
);
}
+
+ // If the item has candidate identifiers, the item identifier must be
+ // zero or wildcard for one of the candidates.
if (item.candidateIdentifiers.length > 0) {
bool identifierFound;
for (uint256 i; i < item.candidateIdentifiers.length; i++) {
@@ -111,22 +154,28 @@ library HelperItemLib {
function validate(NavigatorConsiderationItem memory item) internal pure {
ItemType itemType = item.itemType;
+
+ // If the item has criteria, the item type must be ERC721 or ERC1155.
if (itemType == ItemType.ERC20 || itemType == ItemType.NATIVE) {
- if (item.candidateIdentifiers.length > 0) {
+ if (hasCriteria(item)) {
revert InvalidItemTypeForCandidateIdentifiers();
} else {
return;
}
}
- // If the item has candidate identifiers, the item identifier must be
- // zero for wildcard or one of the candidates.
+
+ // If the item has no candidate identifiers, the item identifier must be
+ // non-zero.
if (item.candidateIdentifiers.length == 0 && item.identifier == 0) {
revert InvalidIdentifier(
item.identifier,
item.candidateIdentifiers
);
}
- if (item.candidateIdentifiers.length > 0) {
+
+ // If the item has candidate identifiers, the item identifier must be
+ // zero or wildcard for one of the candidates.
+ if (hasCriteria(item)) {
bool identifierFound;
for (uint256 i; i < item.candidateIdentifiers.length; i++) {
if (item.candidateIdentifiers[i] == item.identifier) {
diff --git a/contracts/helpers/navigator/lib/MerkleLib.sol b/contracts/helpers/navigator/lib/MerkleLib.sol
index f0be29e0a..26a19edb3 100644
--- a/contracts/helpers/navigator/lib/MerkleLib.sol
+++ b/contracts/helpers/navigator/lib/MerkleLib.sol
@@ -6,59 +6,91 @@ pragma solidity ^0.8.17;
* Murky: https://github.com/dmfxyz/murky
*/
library MerkleLib {
+ /**
+ * @dev Computes the Merkle tree hash of two child nodes.
+ *
+ * @param left The hash of the left child node.
+ * @param right The hash of the right child node.
+ *
+ * @return _hash The Merkle tree hash of the two input hashes.
+ */
function merkleHash(
bytes32 left,
bytes32 right
) internal pure returns (bytes32 _hash) {
assembly {
+ // Compare the left and right hash to order them lt(left, right)
+ // returns true if left is less than right
switch lt(left, right)
+ // If left is not less than right, switch the order.
case 0 {
mstore(0x0, right)
mstore(0x20, left)
}
+ // If left is less than right, keep the order.
default {
mstore(0x0, left)
mstore(0x20, right)
}
- _hash := keccak256(0x0, 0x40)
- }
- }
- function xorkleHash(
- bytes32 left,
- bytes32 right
- ) internal pure returns (bytes32 _hash) {
- assembly {
- mstore(0x0, xor(left, right))
- _hash := keccak256(0x0, 0x20)
+ // Compute the keccak256 hash of the 64-byte input (two concatenated
+ // 32-byte hashes) The result is stored in '_hash'
+ _hash := keccak256(0x0, 0x40)
}
}
+ /**
+ * @dev Verifies a Merkle proof.
+ *
+ * @param root The root of the Merkle tree.
+ * @param proof An array containing the Merkle proof hashes.
+ * @param valueToProve The leaf node value to prove membership for.
+ * @param hashLeafPairs A function to hash pairs of leaf nodes.
+ *
+ * @return True if the proof is valid, otherwise false.
+ */
function verifyProof(
bytes32 root,
bytes32[] memory proof,
bytes32 valueToProve,
function(bytes32, bytes32) internal pure returns (bytes32) hashLeafPairs
) internal pure returns (bool) {
- // proof length must be less than max array size
+ // Proof length must be less than max array size.
bytes32 rollingHash = valueToProve;
uint256 length = proof.length;
+
+ // Loop through each proof element to compute the rolling hash.
unchecked {
for (uint i = 0; i < length; ++i) {
rollingHash = hashLeafPairs(rollingHash, proof[i]);
}
}
+
+ // The final rolling hash must equal the Merkle root for the proof to be
+ // valid
return root == rollingHash;
}
+ /**
+ * @dev Computes the Merkle root from an array of leaf node hashes.
+ *
+ * @param data An array containing the leaf node hashes.
+ * @param hashLeafPairs A function to hash pairs of leaf nodes.
+ *
+ * @return The Merkle root.
+ */
function getRoot(
bytes32[] memory data,
function(bytes32, bytes32) internal pure returns (bytes32) hashLeafPairs
) internal pure returns (bytes32) {
require(data.length > 1, "won't generate root for single leaf");
+
+ // Loop until only the Merkle root remains.
while (data.length > 1) {
data = hashLevel(data, hashLeafPairs);
}
+
+ // Return the computed Merkle root.
return data[0];
}
diff --git a/contracts/helpers/navigator/lib/NavigatorAdvancedOrderLib.sol b/contracts/helpers/navigator/lib/NavigatorAdvancedOrderLib.sol
index 2f99fc17b..548a07c84 100644
--- a/contracts/helpers/navigator/lib/NavigatorAdvancedOrderLib.sol
+++ b/contracts/helpers/navigator/lib/NavigatorAdvancedOrderLib.sol
@@ -12,19 +12,25 @@ import {
import { Side } from "seaport-types/src/lib/ConsiderationEnums.sol";
import { CriteriaHelperLib } from "./CriteriaHelperLib.sol";
+
import { HelperItemLib } from "./HelperItemLib.sol";
+
import {
NavigatorAdvancedOrder,
- NavigatorOrderParameters,
+ NavigatorConsiderationItem,
NavigatorOfferItem,
- NavigatorConsiderationItem
+ NavigatorOrderParameters
} from "./SeaportNavigatorTypes.sol";
library NavigatorAdvancedOrderLib {
using CriteriaHelperLib for uint256[];
- using HelperItemLib for NavigatorOfferItem;
using HelperItemLib for NavigatorConsiderationItem;
+ using HelperItemLib for NavigatorOfferItem;
+ /*
+ * @dev Converts an array of AdvancedOrders to an array of
+ * NavigatorAdvancedOrders.
+ */
function fromAdvancedOrders(
AdvancedOrder[] memory orders
) internal pure returns (NavigatorAdvancedOrder[] memory) {
@@ -36,9 +42,13 @@ library NavigatorAdvancedOrderLib {
return helperOrders;
}
+ /*
+ * @dev Converts an AdvancedOrder to a NavigatorAdvancedOrder.
+ */
function fromAdvancedOrder(
AdvancedOrder memory order
) internal pure returns (NavigatorAdvancedOrder memory) {
+ // Copy over the offer items.
NavigatorOfferItem[] memory offerItems = new NavigatorOfferItem[](
order.parameters.offer.length
);
@@ -53,6 +63,8 @@ library NavigatorAdvancedOrderLib {
candidateIdentifiers: new uint256[](0)
});
}
+
+ // Copy over the consideration items.
NavigatorConsiderationItem[]
memory considerationItems = new NavigatorConsiderationItem[](
order.parameters.consideration.length
@@ -93,15 +105,26 @@ library NavigatorAdvancedOrderLib {
});
}
+ /*
+ * @dev Converts an array of NavigatorAdvancedOrders to an array of
+ * AdvancedOrders and an array of CriteriaResolvers.
+ */
function toAdvancedOrder(
NavigatorAdvancedOrder memory order,
uint256 orderIndex
) internal pure returns (AdvancedOrder memory, CriteriaResolver[] memory) {
+ // Create an array of CriteriaResolvers to be populated in the for loop
+ // below. It might be longer than it needs to be, but it gets trimmed in
+ // the assembly block below.
CriteriaResolver[] memory criteriaResolvers = new CriteriaResolver[](
order.parameters.offer.length +
order.parameters.consideration.length
);
uint256 criteriaResolverLen;
+
+ // Copy over the offer items, converting candidate identifiers to a
+ // criteria root if necessary and populating the criteria resolvers
+ // array.
OfferItem[] memory offer = new OfferItem[](
order.parameters.offer.length
);
@@ -138,6 +161,10 @@ library NavigatorAdvancedOrderLib {
});
}
}
+
+ // Copy over the consideration items, converting candidate identifiers
+ // to a criteria root if necessary and populating the criteria resolvers
+ // array.
ConsiderationItem[] memory consideration = new ConsiderationItem[](
order.parameters.consideration.length
);
@@ -178,9 +205,16 @@ library NavigatorAdvancedOrderLib {
});
}
}
+
+ // This just encodes the length of the array that we gradually built up
+ // above. It's just a way of creating an array of arbitrary length. It's
+ // initialized to its longest possible length at the top, then populated
+ // partially or fully in the for loop above. Finally, the length is set
+ // here surgically.
assembly {
mstore(criteriaResolvers, criteriaResolverLen)
}
+
return (
AdvancedOrder({
parameters: OrderParameters({
@@ -207,6 +241,10 @@ library NavigatorAdvancedOrderLib {
);
}
+ /*
+ * @dev Converts an array of NavigatorAdvancedOrders to an array of
+ * AdvancedOrders and an array of CriteriaResolvers.
+ */
function toAdvancedOrders(
NavigatorAdvancedOrder[] memory orders
)
@@ -214,9 +252,15 @@ library NavigatorAdvancedOrderLib {
pure
returns (AdvancedOrder[] memory, CriteriaResolver[] memory)
{
+ // Create an array of AdvancedOrders to be populated in the for loop
+ // below.
AdvancedOrder[] memory advancedOrders = new AdvancedOrder[](
orders.length
);
+
+ // Create an array of CriteriaResolvers to be populated in the for loop
+ // below. It might be longer than it needs to be, but it gets trimmed in
+ // the assembly block below.
uint256 maxCriteriaResolvers;
for (uint256 i; i < orders.length; i++) {
NavigatorOrderParameters memory parameters = orders[i].parameters;
@@ -227,6 +271,9 @@ library NavigatorAdvancedOrderLib {
CriteriaResolver[] memory criteriaResolvers = new CriteriaResolver[](
maxCriteriaResolvers
);
+
+ // Copy over the NavigatorAdvancedOrder[] orders to the AdvancedOrder[]
+ // array, converting and populating the criteria resolvers array.
for (uint256 i = 0; i < orders.length; i++) {
(
AdvancedOrder memory order,
@@ -238,9 +285,16 @@ library NavigatorAdvancedOrderLib {
criteriaResolverIndex++;
}
}
+
+ // This just encodes the length of the array that we gradually built up
+ // above. It's just a way of creating an array of arbitrary length. It's
+ // initialized to its longest possible length at the top, then populated
+ // partially or fully in the for loop above. Finally, the length is set
+ // here surgically.
assembly {
mstore(criteriaResolvers, criteriaResolverIndex)
}
+
return (advancedOrders, criteriaResolvers);
}
}
diff --git a/contracts/helpers/navigator/lib/NavigatorContextLib.sol b/contracts/helpers/navigator/lib/NavigatorContextLib.sol
index a00ea9f0b..5b0fd351c 100644
--- a/contracts/helpers/navigator/lib/NavigatorContextLib.sol
+++ b/contracts/helpers/navigator/lib/NavigatorContextLib.sol
@@ -1,45 +1,43 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
-import {
- ConsiderationInterface
-} from "seaport-types/src/interfaces/ConsiderationInterface.sol";
-
import {
MatchComponent
} from "seaport-sol/src/lib/types/MatchComponentType.sol";
+
import { OrderDetails } from "seaport-sol/src/fulfillments/lib/Structs.sol";
import {
AdvancedOrder,
+ CriteriaResolver,
Execution,
Fulfillment,
- FulfillmentComponent,
- CriteriaResolver
+ FulfillmentComponent
} from "seaport-types/src/lib/ConsiderationStructs.sol";
import {
- NavigatorRequest,
- NavigatorResponse,
NavigatorContext,
- NavigatorOfferItem,
- NavigatorConsiderationItem,
- NavigatorOrderParameters,
- NavigatorAdvancedOrder
+ NavigatorRequest,
+ NavigatorResponse
} from "./SeaportNavigatorTypes.sol";
-import {
- SeaportValidatorInterface,
- ErrorsAndWarnings
-} from "../../order-validator/SeaportValidator.sol";
+import { ErrorsAndWarnings } from "../../order-validator/SeaportValidator.sol";
library NavigatorContextLib {
+ /**
+ * @dev Creates a new NavigatorContext from a NavigatorRequest, which just
+ * means slotting the request into the context's request field and
+ * ignoring the response field.
+ */
function from(
NavigatorRequest memory request
) internal pure returns (NavigatorContext memory context) {
context.request = request;
}
+ /**
+ * @dev Adds an empty response to the context.
+ */
function withEmptyResponse(
NavigatorContext memory context
) internal pure returns (NavigatorContext memory) {
diff --git a/contracts/helpers/navigator/lib/NavigatorDetailsLib.sol b/contracts/helpers/navigator/lib/NavigatorDetailsLib.sol
index 3047208c9..9d05155d1 100644
--- a/contracts/helpers/navigator/lib/NavigatorDetailsLib.sol
+++ b/contracts/helpers/navigator/lib/NavigatorDetailsLib.sol
@@ -2,9 +2,13 @@
pragma solidity ^0.8.17;
import { UnavailableReason } from "seaport-sol/src/SpaceEnums.sol";
+
import { AdvancedOrder } from "seaport-types/src/lib/ConsiderationStructs.sol";
+
import { AdvancedOrderLib } from "seaport-sol/src/lib/AdvancedOrderLib.sol";
+
import { NavigatorContext } from "./SeaportNavigatorTypes.sol";
+
import { OrderAvailabilityLib } from "./OrderAvailabilityLib.sol";
library NavigatorDetailsLib {
diff --git a/contracts/helpers/navigator/lib/NavigatorExecutionsLib.sol b/contracts/helpers/navigator/lib/NavigatorExecutionsLib.sol
index 5941f0829..72b8c0123 100644
--- a/contracts/helpers/navigator/lib/NavigatorExecutionsLib.sol
+++ b/contracts/helpers/navigator/lib/NavigatorExecutionsLib.sol
@@ -5,14 +5,7 @@ import {
ConsiderationInterface
} from "seaport-types/src/interfaces/ConsiderationInterface.sol";
-import {
- AdvancedOrder,
- Execution,
- SpentItem,
- ReceivedItem
-} from "seaport-types/src/lib/ConsiderationStructs.sol";
-
-import { ItemType } from "seaport-types/src/lib/ConsiderationEnums.sol";
+import { Execution } from "seaport-types/src/lib/ConsiderationStructs.sol";
import {
FulfillmentDetails
@@ -22,10 +15,6 @@ import {
ExecutionHelper
} from "seaport-sol/src/executions/ExecutionHelper.sol";
-import { UnavailableReason } from "seaport-sol/src/SpaceEnums.sol";
-
-import { OrderDetails } from "seaport-sol/src/fulfillments/lib/Structs.sol";
-
import { NavigatorContext } from "./SeaportNavigatorTypes.sol";
library NavigatorExecutionsLib {
@@ -44,8 +33,12 @@ library NavigatorExecutionsLib {
function withExecutions(
NavigatorContext memory context
) internal pure returns (NavigatorContext memory) {
+ // Extract the suggested action from the response.
bytes memory callData = context.response.suggestedCallData;
bytes4 _suggestedAction = bytes4(callData);
+
+ // Create a struct to hold details necessary for fulfillment, populated
+ // from the context.
FulfillmentDetails memory fulfillmentDetails = FulfillmentDetails({
orders: context.response.orderDetails,
recipient: payable(context.request.recipient),
@@ -55,12 +48,15 @@ library NavigatorExecutionsLib {
seaport: address(context.request.seaport)
});
+ // Initialize the execution arrays.
Execution[] memory explicitExecutions;
Execution[] memory implicitExecutions;
Execution[] memory implicitExecutionsPre;
Execution[] memory implicitExecutionsPost;
uint256 nativeTokensReturned;
+ // Call the appropriate method on the FulfillmentDetails struct to get
+ // the executions.
if (
_suggestedAction ==
ConsiderationInterface.fulfillAvailableOrders.selector ||
@@ -108,6 +104,8 @@ library NavigatorExecutionsLib {
} else {
revert UnknownAction();
}
+
+ // Add the executions to the response.
context.response.explicitExecutions = explicitExecutions;
context.response.implicitExecutions = implicitExecutions;
context.response.implicitExecutionsPre = implicitExecutionsPre;
diff --git a/contracts/helpers/navigator/lib/NavigatorRequestValidatorLib.sol b/contracts/helpers/navigator/lib/NavigatorRequestValidatorLib.sol
index 77922d9e9..60b192029 100644
--- a/contracts/helpers/navigator/lib/NavigatorRequestValidatorLib.sol
+++ b/contracts/helpers/navigator/lib/NavigatorRequestValidatorLib.sol
@@ -4,6 +4,7 @@ pragma solidity ^0.8.17;
import { AdvancedOrder } from "seaport-types/src/lib/ConsiderationStructs.sol";
import { Type, OrderStructureLib } from "./OrderStructureLib.sol";
+
import { NavigatorContext } from "./SeaportNavigatorTypes.sol";
library NavigatorRequestValidatorLib {
diff --git a/contracts/helpers/navigator/lib/NavigatorSeaportValidatorLib.sol b/contracts/helpers/navigator/lib/NavigatorSeaportValidatorLib.sol
index 5bbe77795..bb8b47597 100644
--- a/contracts/helpers/navigator/lib/NavigatorSeaportValidatorLib.sol
+++ b/contracts/helpers/navigator/lib/NavigatorSeaportValidatorLib.sol
@@ -2,6 +2,7 @@
pragma solidity ^0.8.17;
import { AdvancedOrder } from "seaport-types/src/lib/ConsiderationStructs.sol";
+
import { AdvancedOrderLib } from "seaport-sol/src/lib/AdvancedOrderLib.sol";
import { ErrorsAndWarnings } from "../../order-validator/SeaportValidator.sol";
@@ -11,8 +12,6 @@ import { NavigatorContext } from "./SeaportNavigatorTypes.sol";
library NavigatorSeaportValidatorLib {
using AdvancedOrderLib for AdvancedOrder;
- error ValidatorReverted();
-
/**
* @dev Validate each order using SeaportValidator and add the results to
* the NavigatorResponse.
diff --git a/contracts/helpers/navigator/lib/NavigatorSuggestedActionLib.sol b/contracts/helpers/navigator/lib/NavigatorSuggestedActionLib.sol
index cd30c3440..56d3c6a2b 100644
--- a/contracts/helpers/navigator/lib/NavigatorSuggestedActionLib.sol
+++ b/contracts/helpers/navigator/lib/NavigatorSuggestedActionLib.sol
@@ -7,9 +7,8 @@ import {
import {
AdvancedOrder,
- Execution,
- SpentItem,
- ReceivedItem
+ ReceivedItem,
+ SpentItem
} from "seaport-types/src/lib/ConsiderationStructs.sol";
import { ItemType } from "seaport-types/src/lib/ConsiderationEnums.sol";
@@ -20,15 +19,15 @@ import { OrderDetails } from "seaport-sol/src/fulfillments/lib/Structs.sol";
import { AdvancedOrderLib } from "seaport-sol/src/lib/AdvancedOrderLib.sol";
-import { Family, Structure, OrderStructureLib } from "./OrderStructureLib.sol";
+import { Family, OrderStructureLib, Structure } from "./OrderStructureLib.sol";
import { NavigatorContext } from "./SeaportNavigatorTypes.sol";
library NavigatorSuggestedActionLib {
- using OrderStructureLib for AdvancedOrder;
- using OrderStructureLib for AdvancedOrder[];
using AdvancedOrderLib for AdvancedOrder;
using AdvancedOrderLib for AdvancedOrder[];
+ using OrderStructureLib for AdvancedOrder;
+ using OrderStructureLib for AdvancedOrder[];
/**
* @dev Bad request error: provided orders cannot be fulfilled.
@@ -84,31 +83,64 @@ library NavigatorSuggestedActionLib {
function suggestedCallData(
NavigatorContext memory context
) internal view returns (bytes memory) {
+ // Get the family of the orders (single or combined).
Family family = context.response.orders.getFamily();
- bool invalidOfferItemsLocated = mustUseMatch(context);
+ // `mustUseMatch` returns true if the orders require the use of one of
+ // the match* methods. `mustUseMatch` checks for two things: 1) the
+ // presence of a native token in the offer of one of the orders, and 2)
+ // the presence of an ERC721 in the offer of one of the orders that is
+ // also in the consideration of another order. So,
+ // `containsOrderThatDemandsMatch` means that there's an offer item that
+ // can't be part of a standing order.
+ bool containsOrderThatDemandsMatch = mustUseMatch(context);
+ // Get the structure of the orders (basic, standard, or advanced).
Structure structure = context.response.orders.getStructure(
address(context.request.seaport)
);
- bool hasUnavailable = context.request.maximumFulfilled <
- context.response.orders.length;
+ bool contextHasExcessOrders = context.response.orders.length >
+ context.request.maximumFulfilled;
+
+ bool contextHasUnavailableOrders;
+
+ // Iterate through the orders and check if any of the orders has an
+ // unavailable reason.
for (uint256 i = 0; i < context.response.orderDetails.length; ++i) {
if (
context.response.orderDetails[i].unavailableReason !=
UnavailableReason.AVAILABLE
) {
- hasUnavailable = true;
+ contextHasUnavailableOrders = true;
break;
}
}
- if (hasUnavailable) {
- if (invalidOfferItemsLocated) {
+ // The match* methods are only an option if everything is going to find
+ // a partner (the first half of the if statement below) and if there are
+ // no unavailable orders (the second half of the if statement below).
+ bool cannotMatch = (context
+ .response
+ .unmetConsiderationComponents
+ .length !=
+ 0 ||
+ contextHasExcessOrders);
+
+ bool contextHasExcessOrUnavailableOrders = contextHasExcessOrders ||
+ contextHasUnavailableOrders;
+
+ // If there are excess or unavailable orders, follow this branch.
+ if (contextHasExcessOrUnavailableOrders) {
+ // If there are excess or unavailable orders and the orders could
+ // only be fulfilled using match*, it's a no-go, because every order
+ // must find a partner in the match* methods.
+ if (containsOrderThatDemandsMatch) {
revert InvalidNativeTokenUnavailableCombination();
}
+ // If there are excess or unavailable orders and the orders are
+ // advanced, use fulfillAvailableAdvancedOrders.
if (structure == Structure.ADVANCED) {
return
abi.encodeCall(
@@ -124,6 +156,8 @@ library NavigatorSuggestedActionLib {
)
);
} else {
+ // If there are excess or unavailable orders and the orders are
+ // not advanced, use fulfillAvailableOrders.
return
abi.encodeCall(
ConsiderationInterface.fulfillAvailableOrders,
@@ -138,7 +172,13 @@ library NavigatorSuggestedActionLib {
}
}
- if (family == Family.SINGLE && !invalidOfferItemsLocated) {
+ // If there are no excess or unavailable orders, follow this branch.
+
+ // If the order family is single (just one being fulfilled) and it
+ // doesn't require using match*, use the appropriate fulfill* method.
+ if (family == Family.SINGLE && !containsOrderThatDemandsMatch) {
+ // If the order structure is basic, use
+ // fulfillBasicOrder_efficient_6GL6yc for maximum gas efficiency.
if (structure == Structure.BASIC) {
AdvancedOrder memory order = context.response.orders[0];
return
@@ -153,6 +193,7 @@ library NavigatorSuggestedActionLib {
);
}
+ // If the order structure is standard, use fulfillOrder.
if (structure == Structure.STANDARD) {
return
abi.encodeCall(
@@ -164,6 +205,7 @@ library NavigatorSuggestedActionLib {
);
}
+ // If the order structure is advanced, use fulfillAdvancedOrder.
if (structure == Structure.ADVANCED) {
return
abi.encodeCall(
@@ -178,17 +220,13 @@ library NavigatorSuggestedActionLib {
}
}
- bool cannotMatch = (context
- .response
- .unmetConsiderationComponents
- .length !=
- 0 ||
- hasUnavailable);
-
- if (cannotMatch && invalidOfferItemsLocated) {
+ // This is like saying "if it's not possible to use match* but it's
+ // mandatory to use match*, revert."
+ if (cannotMatch && containsOrderThatDemandsMatch) {
revert CannotFulfillProvidedCombinedOrder();
}
+ // If it's not possible to use match*, use fulfillAvailable*.
if (cannotMatch) {
if (structure == Structure.ADVANCED) {
return
@@ -217,19 +255,19 @@ library NavigatorSuggestedActionLib {
)
);
}
- } else if (invalidOfferItemsLocated) {
+ } else if (containsOrderThatDemandsMatch) {
+ // Here, matching is an option and "containsOrderThatDemandsMatch"
+ // means that match is mandatory, so pick the appropriate match*
+ // method based on structure.
if (structure == Structure.ADVANCED) {
return
abi.encodeCall(
- ConsiderationInterface.fulfillAvailableAdvancedOrders,
+ ConsiderationInterface.matchAdvancedOrders,
(
context.response.orders,
context.response.criteriaResolvers,
- context.response.offerFulfillments,
- context.response.considerationFulfillments,
- context.request.fulfillerConduitKey,
- context.request.recipient,
- context.request.maximumFulfilled
+ context.response.fulfillments,
+ context.request.recipient
)
);
} else {
@@ -243,6 +281,12 @@ library NavigatorSuggestedActionLib {
);
}
} else {
+ // If match* is an option and there are no excess or unavailable
+ // offer items, follow this branch.
+ //
+ // If the structure is advanced, use matchAdvancedOrders or use
+ // fulfillAvailableAdvancedOrders depending on the caller's
+ // preference.
if (structure == Structure.ADVANCED) {
if (context.request.preferMatch) {
return
@@ -272,6 +316,8 @@ library NavigatorSuggestedActionLib {
);
}
} else {
+ // If the structure is not advanced, use matchOrders or
+ // fulfillAvailableOrders depending on the caller's preference.
if (context.request.preferMatch) {
return
abi.encodeCall(
@@ -307,13 +353,23 @@ library NavigatorSuggestedActionLib {
) internal pure returns (bool) {
OrderDetails[] memory orders = context.response.orderDetails;
+ // Iterate through the orders and check if any of the non-contract
+ // orders has a native token in the offer.
for (uint256 i = 0; i < orders.length; ++i) {
OrderDetails memory order = orders[i];
+ // Skip contract orders.
if (order.isContract) {
continue;
}
+ // If the order has a native token in the offer, must use match. If
+ // an order is being passed in that has a native token on the offer
+ // side, then all the fulfill* methods are ruled out, because it's
+ // not possible to create a standing order that offers ETH (WETH
+ // would be required). If an order with native tokens is passed in,
+ // then it necessarily must be coming from a caller who's passing in
+ // a bookend order.
for (uint256 j = 0; j < order.offer.length; ++j) {
if (order.offer[j].itemType == ItemType.NATIVE) {
return true;
@@ -321,30 +377,46 @@ library NavigatorSuggestedActionLib {
}
}
+ // If the caller is the recipient, it's never necessary to use match.
if (context.request.caller == context.request.recipient) {
return false;
}
+ // This basically checks if there's an ERC721 in the offer of one order
+ // that is also in the consideration of another order. If yes, must use
+ // match.
for (uint256 i = 0; i < orders.length; ++i) {
+ // Get the order.
OrderDetails memory order = orders[i];
+ // Iterate over the offer items.
for (uint256 j = 0; j < order.offer.length; ++j) {
+ // Get the item.
SpentItem memory item = order.offer[j];
+ // If the item is not an ERC721, skip it.
if (item.itemType != ItemType.ERC721) {
continue;
}
+ // Iterate over the orders again.
for (uint256 k = 0; k < orders.length; ++k) {
+ // Get an order to compare `orders[i]` against.
OrderDetails memory comparisonOrder = orders[k];
+
+ // Iterate over the consideration items.
for (
uint256 l = 0;
l < comparisonOrder.consideration.length;
++l
) {
+ // Get the consideration item.
ReceivedItem memory considerationItem = comparisonOrder
.consideration[l];
+ // If the consideration item is an ERC721, and the ID is
+ // the same as the offer item, and the token address is
+ // the same as the offer item, must use match.
if (
considerationItem.itemType == ItemType.ERC721 &&
considerationItem.identifier == item.identifier &&
diff --git a/contracts/helpers/navigator/lib/OrderStructureLib.sol b/contracts/helpers/navigator/lib/OrderStructureLib.sol
index 736bcd9db..d176f0060 100644
--- a/contracts/helpers/navigator/lib/OrderStructureLib.sol
+++ b/contracts/helpers/navigator/lib/OrderStructureLib.sol
@@ -4,8 +4,6 @@ pragma solidity ^0.8.17;
import {
AdvancedOrderLib,
ConsiderationItemLib,
- MatchComponent,
- MatchComponentType,
OfferItemLib,
OrderComponentsLib,
OrderLib,
@@ -14,25 +12,18 @@ import {
import {
AdvancedOrder,
- CriteriaResolver,
- Execution,
- Order,
- OrderComponents,
- OrderParameters,
ConsiderationItem,
OfferItem,
- ReceivedItem,
- SpentItem,
- Fulfillment,
- FulfillmentComponent
+ Order,
+ OrderComponents,
+ OrderParameters
} from "seaport-types/src/lib/ConsiderationStructs.sol";
import {
BasicOrderRouteType,
BasicOrderType,
ItemType,
- OrderType,
- Side
+ OrderType
} from "seaport-types/src/lib/ConsiderationEnums.sol";
import {
@@ -101,13 +92,13 @@ enum State {
* for determining which fulfillment method to use.
*/
library OrderStructureLib {
- using OrderLib for Order;
- using OrderComponentsLib for OrderComponents;
- using OrderParametersLib for OrderParameters;
- using OfferItemLib for OfferItem[];
- using ConsiderationItemLib for ConsiderationItem[];
using AdvancedOrderLib for AdvancedOrder;
using AdvancedOrderLib for AdvancedOrder[];
+ using ConsiderationItemLib for ConsiderationItem[];
+ using OfferItemLib for OfferItem[];
+ using OrderComponentsLib for OrderComponents;
+ using OrderLib for Order;
+ using OrderParametersLib for OrderParameters;
function getQuantity(
AdvancedOrder[] memory orders
@@ -129,10 +120,15 @@ library OrderStructureLib {
AdvancedOrder memory order,
ConsiderationInterface seaport
) internal view returns (State) {
+ // Get the counter for the offerer.
uint256 counter = seaport.getCounter(order.parameters.offerer);
+
+ // Use the counter to get the order hash.
bytes32 orderHash = seaport.getOrderHash(
order.parameters.toOrderComponents(counter)
);
+
+ // Use the order hash to get the order status.
(
bool isValidated,
bool isCancelled,
@@ -140,11 +136,18 @@ library OrderStructureLib {
uint256 totalSize
) = seaport.getOrderStatus(orderHash);
- if (totalFilled != 0 && totalSize != 0 && totalFilled == totalSize)
+ if (totalFilled != 0 && totalSize != 0 && totalFilled == totalSize) {
return State.FULLY_FILLED;
- if (totalFilled != 0 && totalSize != 0) return State.PARTIALLY_FILLED;
- if (isCancelled) return State.CANCELLED;
- if (isValidated) return State.VALIDATED;
+ }
+ if (totalFilled != 0 && totalSize != 0) {
+ return State.PARTIALLY_FILLED;
+ }
+ if (isCancelled) {
+ return State.CANCELLED;
+ }
+ if (isValidated) {
+ return State.VALIDATED;
+ }
return State.UNUSED;
}
diff --git a/contracts/helpers/navigator/lib/RequestValidator.sol b/contracts/helpers/navigator/lib/RequestValidator.sol
index a72b0bf26..767e9f4a3 100644
--- a/contracts/helpers/navigator/lib/RequestValidator.sol
+++ b/contracts/helpers/navigator/lib/RequestValidator.sol
@@ -5,10 +5,7 @@ import {
NavigatorRequestValidatorLib
} from "./NavigatorRequestValidatorLib.sol";
-import {
- NavigatorContext,
- NavigatorResponse
-} from "./SeaportNavigatorTypes.sol";
+import { NavigatorContext } from "./SeaportNavigatorTypes.sol";
import { HelperInterface } from "./HelperInterface.sol";
diff --git a/contracts/helpers/navigator/lib/SeaportNavigatorInterface.sol b/contracts/helpers/navigator/lib/SeaportNavigatorInterface.sol
index 013e2d5da..645930e28 100644
--- a/contracts/helpers/navigator/lib/SeaportNavigatorInterface.sol
+++ b/contracts/helpers/navigator/lib/SeaportNavigatorInterface.sol
@@ -1,11 +1,6 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
-import {
- AdvancedOrder,
- CriteriaResolver
-} from "seaport-types/src/lib/ConsiderationStructs.sol";
-
import {
NavigatorRequest,
NavigatorResponse
diff --git a/contracts/helpers/navigator/lib/SeaportNavigatorTypes.sol b/contracts/helpers/navigator/lib/SeaportNavigatorTypes.sol
index 2314f8e36..fa87d827f 100644
--- a/contracts/helpers/navigator/lib/SeaportNavigatorTypes.sol
+++ b/contracts/helpers/navigator/lib/SeaportNavigatorTypes.sol
@@ -1,11 +1,6 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
-import {
- SeaportValidatorInterface,
- ErrorsAndWarnings
-} from "../../order-validator/SeaportValidator.sol";
-
import {
ConsiderationInterface
} from "seaport-types/src/interfaces/ConsiderationInterface.sol";
@@ -14,20 +9,12 @@ import {
AdvancedOrder,
CriteriaResolver,
Execution,
- Order,
- OrderComponents,
- OrderParameters,
- ConsiderationItem,
- OfferItem,
- ReceivedItem,
- SpentItem,
Fulfillment,
FulfillmentComponent
} from "seaport-types/src/lib/ConsiderationStructs.sol";
import {
ItemType,
- Side,
OrderType
} from "seaport-types/src/lib/ConsiderationEnums.sol";
@@ -35,15 +22,17 @@ import {
MatchComponent
} from "seaport-sol/src/lib/types/MatchComponentType.sol";
-import {
- FulfillmentDetails,
- OrderDetails
-} from "seaport-sol/src/fulfillments/lib/Structs.sol";
+import { OrderDetails } from "seaport-sol/src/fulfillments/lib/Structs.sol";
import {
FulfillmentStrategy
} from "seaport-sol/src/fulfillments/lib/FulfillmentLib.sol";
+import {
+ SeaportValidatorInterface,
+ ErrorsAndWarnings
+} from "../../order-validator/SeaportValidator.sol";
+
struct NavigatorAdvancedOrder {
NavigatorOrderParameters parameters;
uint120 numerator;
diff --git a/contracts/helpers/navigator/lib/ValidatorHelper.sol b/contracts/helpers/navigator/lib/ValidatorHelper.sol
index 5a3d813c8..526fb88b2 100644
--- a/contracts/helpers/navigator/lib/ValidatorHelper.sol
+++ b/contracts/helpers/navigator/lib/ValidatorHelper.sol
@@ -9,12 +9,6 @@ import { NavigatorContext } from "./SeaportNavigatorTypes.sol";
import { HelperInterface } from "./HelperInterface.sol";
-import { Order } from "seaport-types/src/lib/ConsiderationStructs.sol";
-
-import {
- SeaportValidatorInterface
-} from "../../order-validator/SeaportValidator.sol";
-
contract ValidatorHelper is HelperInterface {
using NavigatorSeaportValidatorLib for NavigatorContext;
diff --git a/contracts/helpers/order-validator/SeaportValidator.sol b/contracts/helpers/order-validator/SeaportValidator.sol
index d0f57c310..e1a469e7f 100644
--- a/contracts/helpers/order-validator/SeaportValidator.sol
+++ b/contracts/helpers/order-validator/SeaportValidator.sol
@@ -1103,7 +1103,7 @@ contract SeaportValidator is
}
/**
- * @notice Creates a merkle proof for the the targetIndex contained in includedTokens.
+ * @notice Creates a merkle proof for the targetIndex contained in includedTokens.
* @dev `targetIndex` is referring to the index of an element in `includedTokens`.
* `includedTokens` must be sorting in ascending order according to the keccak256 hash of the value.
* @return merkleProof The merkle proof
diff --git a/contracts/helpers/order-validator/lib/Murky.sol b/contracts/helpers/order-validator/lib/Murky.sol
index d49675a3c..123e3cd3b 100644
--- a/contracts/helpers/order-validator/lib/Murky.sol
+++ b/contracts/helpers/order-validator/lib/Murky.sol
@@ -35,11 +35,10 @@ contract Murky {
********************/
/// ascending sort and concat prior to hashing
- function _hashLeafPairs(bytes32 left, bytes32 right)
- internal
- pure
- returns (bytes32 _hash)
- {
+ function _hashLeafPairs(
+ bytes32 left,
+ bytes32 right
+ ) internal pure returns (bytes32 _hash) {
assembly {
switch lt(left, right)
case 0 {
@@ -58,7 +57,9 @@ contract Murky {
* PROOF GENERATION *
********************/
- function _getRoot(uint256[] memory data)
+ function _getRoot(
+ uint256[] memory data
+ )
internal
pure
returns (bytes32 result, ErrorsAndWarnings memory errorsAndWarnings)
@@ -159,7 +160,10 @@ contract Murky {
}
}
- function _getProof(uint256[] memory data, uint256 node)
+ function _getProof(
+ uint256[] memory data,
+ uint256 node
+ )
internal
pure
returns (
@@ -316,11 +320,9 @@ contract Murky {
/**
* Hashes each element of the input array in place using keccak256
*/
- function _processInput(uint256[] memory data)
- private
- pure
- returns (bool sorted)
- {
+ function _processInput(
+ uint256[] memory data
+ ) private pure returns (bool sorted) {
sorted = true;
// Hash inputs with keccak256
@@ -352,11 +354,9 @@ contract Murky {
bytes32 hash;
}
- function _sortUint256ByHash(uint256[] memory values)
- internal
- pure
- returns (uint256[] memory sortedValues)
- {
+ function _sortUint256ByHash(
+ uint256[] memory values
+ ) internal pure returns (uint256[] memory sortedValues) {
HashAndIntTuple[] memory toSort = new HashAndIntTuple[](values.length);
for (uint256 i = 0; i < values.length; i++) {
toSort[i] = HashAndIntTuple(
diff --git a/contracts/helpers/order-validator/lib/ReadOnlyOrderValidator.sol b/contracts/helpers/order-validator/lib/ReadOnlyOrderValidator.sol
index c0d231245..81e6f770c 100644
--- a/contracts/helpers/order-validator/lib/ReadOnlyOrderValidator.sol
+++ b/contracts/helpers/order-validator/lib/ReadOnlyOrderValidator.sol
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT
-pragma solidity 0.8.17;
+pragma solidity ^0.8.24;
import { OrderType } from "seaport-types/src/lib/ConsiderationEnums.sol";
@@ -20,29 +20,14 @@ import {
} from "seaport-core/src/lib/SignatureVerification.sol";
import {
+ _revertOrderAlreadyFilled,
_revertOrderIsCancelled,
- _revertOrderPartiallyFilled,
- _revertOrderAlreadyFilled
+ _revertOrderPartiallyFilled
} from "seaport-types/src/lib/ConsiderationErrors.sol";
import { SeaportInterface } from "seaport-sol/src/SeaportInterface.sol";
import {
- EIP_712_PREFIX,
- EIP712_DigestPayload_size,
- EIP712_DomainSeparator_offset,
- EIP712_OrderHash_offset,
- BulkOrderProof_keyShift,
- BulkOrderProof_keySize,
- BulkOrderProof_lengthAdjustmentBeforeMask,
- BulkOrderProof_lengthRangeAfterMask,
- BulkOrderProof_minSize,
- BulkOrderProof_rangeSize,
- ECDSA_MaxLength,
- OneWordShift,
- ThirtyOneBytes,
- OneWord,
- TwoWords,
BulkOrder_Typehash_Height_One,
BulkOrder_Typehash_Height_Two,
BulkOrder_Typehash_Height_Three,
@@ -66,7 +51,22 @@ import {
BulkOrder_Typehash_Height_TwentyOne,
BulkOrder_Typehash_Height_TwentyTwo,
BulkOrder_Typehash_Height_TwentyThree,
- BulkOrder_Typehash_Height_TwentyFour
+ BulkOrder_Typehash_Height_TwentyFour,
+ BulkOrderProof_keyShift,
+ BulkOrderProof_keySize,
+ BulkOrderProof_lengthAdjustmentBeforeMask,
+ BulkOrderProof_lengthRangeAfterMask,
+ BulkOrderProof_minSize,
+ BulkOrderProof_rangeSize,
+ ECDSA_MaxLength,
+ EIP_712_PREFIX,
+ EIP712_DigestPayload_size,
+ EIP712_DomainSeparator_offset,
+ EIP712_OrderHash_offset,
+ OneWord,
+ OneWordShift,
+ ThirtyOneBytes,
+ TwoWords
} from "seaport-types/src/lib/ConsiderationConstants.sol";
contract ReadOnlyOrderValidator is SignatureVerification {
diff --git a/contracts/helpers/order-validator/lib/SeaportValidatorHelper.sol b/contracts/helpers/order-validator/lib/SeaportValidatorHelper.sol
index 7b23d627c..05aec9ebc 100644
--- a/contracts/helpers/order-validator/lib/SeaportValidatorHelper.sol
+++ b/contracts/helpers/order-validator/lib/SeaportValidatorHelper.sol
@@ -22,7 +22,9 @@ import {
ContractOffererInterface
} from "seaport-types/src/interfaces/ContractOffererInterface.sol";
import { ZoneInterface } from "seaport-types/src/interfaces/ZoneInterface.sol";
-import { GettersAndDerivers } from "seaport-core/src/lib/GettersAndDerivers.sol";
+import {
+ GettersAndDerivers
+} from "seaport-core/src/lib/GettersAndDerivers.sol";
import {
SeaportValidatorInterface
} from "../lib/SeaportValidatorInterface.sol";
@@ -900,7 +902,7 @@ contract SeaportValidatorHelper is Murky {
}
/**
- * @notice Creates a merkle proof for the the targetIndex contained in includedTokens.
+ * @notice Creates a merkle proof for the targetIndex contained in includedTokens.
* @dev `targetIndex` is referring to the index of an element in `includedTokens`.
* `includedTokens` must be sorting in ascending order according to the keccak256 hash of the value.
* @return merkleProof The merkle proof
diff --git a/contracts/helpers/order-validator/lib/SeaportValidatorInterface.sol b/contracts/helpers/order-validator/lib/SeaportValidatorInterface.sol
index 3d0abd321..3cd8c90e6 100644
--- a/contracts/helpers/order-validator/lib/SeaportValidatorInterface.sol
+++ b/contracts/helpers/order-validator/lib/SeaportValidatorInterface.sol
@@ -264,7 +264,7 @@ interface SeaportValidatorInterface {
);
/**
- * @notice Creates a merkle proof for the the targetIndex contained in includedTokens.
+ * @notice Creates a merkle proof for the targetIndex contained in includedTokens.
* @dev `targetIndex` is referring to the index of an element in `includedTokens`.
* `includedTokens` must be sorting in ascending order according to the keccak256 hash of the value.
* @return merkleProof The merkle proof
diff --git a/contracts/interfaces/ImmutableCreate2FactoryInterface.sol b/contracts/interfaces/ImmutableCreate2FactoryInterface.sol
index 73fc22d78..a1bd08a0e 100644
--- a/contracts/interfaces/ImmutableCreate2FactoryInterface.sol
+++ b/contracts/interfaces/ImmutableCreate2FactoryInterface.sol
@@ -93,4 +93,4 @@ interface ImmutableCreate2FactoryInterface {
function hasBeenDeployed(
address deploymentAddress
) external view returns (bool);
-}
\ No newline at end of file
+}
diff --git a/contracts/test/ERC721ReceiverMock.sol b/contracts/test/ERC721ReceiverMock.sol
index 5b528dd00..bb5506cc7 100644
--- a/contracts/test/ERC721ReceiverMock.sol
+++ b/contracts/test/ERC721ReceiverMock.sol
@@ -1,7 +1,9 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
-import { IERC721Receiver } from "seaport-types/src/interfaces/IERC721Receiver.sol";
+import {
+ IERC721Receiver
+} from "seaport-types/src/interfaces/IERC721Receiver.sol";
contract ERC721ReceiverMock is IERC721Receiver {
enum Error {
diff --git a/contracts/test/HashValidationZoneOfferer.sol b/contracts/test/HashValidationZoneOfferer.sol
index d1926140d..56a2315e1 100644
--- a/contracts/test/HashValidationZoneOfferer.sol
+++ b/contracts/test/HashValidationZoneOfferer.sol
@@ -21,6 +21,7 @@ import {
} from "seaport-types/src/interfaces/ContractOffererInterface.sol";
import { ZoneInterface } from "seaport-types/src/interfaces/ZoneInterface.sol";
+
import { OffererZoneFailureReason } from "./OffererZoneFailureReason.sol";
/**
@@ -57,8 +58,11 @@ contract HashValidationZoneOfferer is ContractOffererInterface, ZoneInterface {
uint256 expectedBalance,
uint256 actualBalance
);
+ error HashValidationZoneOffererAuthorizeOrderReverts();
error HashValidationZoneOffererValidateOrderReverts();
error HashValidationZoneOffererRatifyOrderReverts();
+
+ event AuthorizeOrderDataHash(bytes32 dataHash);
event ValidateOrderDataHash(bytes32 dataHash);
struct ItemAmountMutation {
@@ -203,6 +207,7 @@ contract HashValidationZoneOfferer is ContractOffererInterface, ZoneInterface {
address internal _expectedOfferRecipient;
+ mapping(bytes32 => bytes32) public orderHashToAuthorizeOrderDataHash;
mapping(bytes32 => bytes32) public orderHashToValidateOrderDataHash;
// Pass in the null address to expect the fulfiller.
@@ -211,15 +216,72 @@ contract HashValidationZoneOfferer is ContractOffererInterface, ZoneInterface {
}
bool public called = false;
- uint public callCount = 0;
+ uint256 public callCount = 0;
- mapping(bytes32 => OffererZoneFailureReason) public failureReasons;
+ mapping(bytes32 => OffererZoneFailureReason) public authorizeFailureReasons;
+ mapping(bytes32 => OffererZoneFailureReason) public validateFailureReasons;
- function setFailureReason(
+ function setAuthorizeFailureReason(
bytes32 orderHash,
OffererZoneFailureReason newFailureReason
) external {
- failureReasons[orderHash] = newFailureReason;
+ authorizeFailureReasons[orderHash] = newFailureReason;
+ }
+
+ function setValidateFailureReason(
+ bytes32 orderHash,
+ OffererZoneFailureReason newFailureReason
+ ) external {
+ validateFailureReasons[orderHash] = newFailureReason;
+ }
+
+ function authorizeOrder(
+ ZoneParameters calldata zoneParameters
+ ) public returns (bytes4 authorizeOrderReturnValue) {
+ // Get the orderHash from zoneParameters
+ bytes32 orderHash = zoneParameters.orderHash;
+
+ if (
+ authorizeFailureReasons[orderHash] ==
+ OffererZoneFailureReason.Zone_authorizeRevertsMatchReverts
+ ) {
+ revert HashValidationZoneOffererAuthorizeOrderReverts();
+ }
+
+ // Get the length of msg.data
+ uint256 dataLength = msg.data.length;
+
+ // Create a variable to store msg.data in memory
+ bytes memory data;
+
+ // Copy msg.data to memory
+ assembly {
+ let ptr := mload(0x40)
+ calldatacopy(add(ptr, 0x20), 0, dataLength)
+ mstore(ptr, dataLength)
+ data := ptr
+ }
+
+ // Get the hash of msg.data
+ bytes32 calldataHash = keccak256(data);
+
+ // Store callDataHash in orderHashToAuthorizeOrderDataHash
+ orderHashToAuthorizeOrderDataHash[orderHash] = calldataHash;
+
+ // Emit a DataHash event with the hash of msg.data
+ emit AuthorizeOrderDataHash(calldataHash);
+
+ if (
+ authorizeFailureReasons[orderHash] ==
+ OffererZoneFailureReason.Zone_authorizeInvalidMagicValue
+ ) {
+ authorizeOrderReturnValue = bytes4(0x12345678);
+ } else {
+ // Return the selector of authorizeOrder as the magic value.
+ authorizeOrderReturnValue = this.authorizeOrder.selector;
+ }
+
+ return authorizeOrderReturnValue;
}
/**
@@ -237,7 +299,8 @@ contract HashValidationZoneOfferer is ContractOffererInterface, ZoneInterface {
bytes32 orderHash = zoneParameters.orderHash;
if (
- failureReasons[orderHash] == OffererZoneFailureReason.Zone_reverts
+ validateFailureReasons[orderHash] ==
+ OffererZoneFailureReason.Zone_validateReverts
) {
revert HashValidationZoneOffererValidateOrderReverts();
}
@@ -283,8 +346,8 @@ contract HashValidationZoneOfferer is ContractOffererInterface, ZoneInterface {
callCount++;
if (
- failureReasons[orderHash] ==
- OffererZoneFailureReason.Zone_InvalidMagicValue
+ validateFailureReasons[orderHash] ==
+ OffererZoneFailureReason.Zone_validateInvalidMagicValue
) {
validOrderMagicValue = bytes4(0x12345678);
} else {
diff --git a/contracts/test/OffererZoneFailureReason.sol b/contracts/test/OffererZoneFailureReason.sol
index c4ce07d7c..41c325224 100644
--- a/contracts/test/OffererZoneFailureReason.sol
+++ b/contracts/test/OffererZoneFailureReason.sol
@@ -11,6 +11,8 @@ enum OffererZoneFailureReason {
ContractOfferer_ExcessMaximumSpent, // too many maximum spent items
ContractOfferer_IncorrectMaximumSpent, // incorrect (too many, wrong token, etc.) maximum spent items
ContractOfferer_InvalidMagicValue, // Offerer did not return correct magic value
- Zone_reverts, // Zone validateOrder call reverts
- Zone_InvalidMagicValue // Zone validateOrder call returns invalid magic value
+ Zone_authorizeRevertsMatchReverts, // Zone authorizeOrder call reverts, which triggers a top level revert only on match*
+ Zone_validateReverts, // Zone validateOrder call reverts
+ Zone_authorizeInvalidMagicValue, // Zone authorizeOrder call returns invalid magic value
+ Zone_validateInvalidMagicValue // Zone validateOrder call returns invalid magic value
}
diff --git a/contracts/test/TestInvalidZone.sol b/contracts/test/TestInvalidZone.sol
index a822e9a7a..41a32bc6f 100644
--- a/contracts/test/TestInvalidZone.sol
+++ b/contracts/test/TestInvalidZone.sol
@@ -10,6 +10,12 @@ import { ERC165 } from "@openzeppelin/contracts/utils/introspection/ERC165.sol";
import { ZoneInterface } from "seaport-types/src/interfaces/ZoneInterface.sol";
contract TestInvalidZone is ERC165, ZoneInterface {
+ function authorizeOrder(
+ ZoneParameters calldata
+ ) public pure returns (bytes4) {
+ return this.authorizeOrder.selector;
+ }
+
// Returns invalid magic value
function validateOrder(
ZoneParameters calldata
diff --git a/contracts/test/TestPostExecution.sol b/contracts/test/TestPostExecution.sol
index 811cb0056..54ffb6b54 100644
--- a/contracts/test/TestPostExecution.sol
+++ b/contracts/test/TestPostExecution.sol
@@ -17,6 +17,12 @@ import {
} from "seaport-types/src/lib/ConsiderationStructs.sol";
contract TestPostExecution is ERC165, ZoneInterface {
+ function authorizeOrder(
+ ZoneParameters calldata
+ ) public pure returns (bytes4) {
+ return this.authorizeOrder.selector;
+ }
+
function validateOrder(
ZoneParameters calldata zoneParameters
) external view override returns (bytes4 validOrderMagicValue) {
diff --git a/contracts/test/TestTransferValidationZoneOfferer.sol b/contracts/test/TestTransferValidationZoneOfferer.sol
index 2b362d32c..fefb49ddd 100644
--- a/contracts/test/TestTransferValidationZoneOfferer.sol
+++ b/contracts/test/TestTransferValidationZoneOfferer.sol
@@ -60,6 +60,7 @@ contract TestTransferValidationZoneOfferer is
uint256 expectedBalance,
uint256 actualBalance
);
+
event ValidateOrderDataHash(bytes32 dataHash);
receive() external payable {}
@@ -74,7 +75,13 @@ contract TestTransferValidationZoneOfferer is
}
bool public called = false;
- uint public callCount = 0;
+ uint256 public callCount = 0;
+
+ function authorizeOrder(
+ ZoneParameters calldata
+ ) public pure returns (bytes4) {
+ return this.authorizeOrder.selector;
+ }
/**
* @dev Validates that the parties have received the correct items.
diff --git a/contracts/test/TestZone.sol b/contracts/test/TestZone.sol
index a772631d7..1f87ee687 100644
--- a/contracts/test/TestZone.sol
+++ b/contracts/test/TestZone.sol
@@ -9,6 +9,12 @@ import {
} from "seaport-types/src/lib/ConsiderationStructs.sol";
contract TestZone is ERC165, ZoneInterface {
+ function authorizeOrder(
+ ZoneParameters calldata
+ ) public pure returns (bytes4) {
+ return this.authorizeOrder.selector;
+ }
+
function validateOrder(
ZoneParameters calldata zoneParameters
) external pure override returns (bytes4 validOrderMagicValue) {
diff --git a/contracts/test/TypehashDirectory.sol b/contracts/test/TypehashDirectory.sol
index e23dffcb9..80678a759 100644
--- a/contracts/test/TypehashDirectory.sol
+++ b/contracts/test/TypehashDirectory.sol
@@ -1,5 +1,5 @@
// SPDX-License-Identifier: MIT
-pragma solidity 0.8.17;
+pragma solidity ^0.8.17;
import {
FreeMemoryPointerSlot,
diff --git a/contracts/zones/PausableZone.sol b/contracts/zones/PausableZone.sol
index 9d408102f..e0a2da5eb 100644
--- a/contracts/zones/PausableZone.sol
+++ b/contracts/zones/PausableZone.sol
@@ -30,9 +30,9 @@ import { PausableZoneInterface } from "./interfaces/PausableZoneInterface.sol";
* @title PausableZone
* @author cupOJoseph, BCLeFevre, ryanio
* @notice PausableZone is a simple zone implementation that approves every
- * order. It can be self-destructed by its controller to pause
- * restricted orders that have it set as their zone. Note that this zone
- * cannot execute orders that return native tokens to the fulfiller.
+ * order. It can be paused by its controller to pause restricted orders
+ * that have it set as their zone. Note that this zone cannot execute
+ * orders that return native tokens to the fulfiller.
*/
contract PausableZone is
ERC165,
@@ -46,6 +46,9 @@ contract PausableZone is
// Set an operator that can instruct the zone to cancel or execute orders.
address public operator;
+ // Set a boolean indicating whether the zone is paused.
+ bool public isPaused;
+
/**
* @dev Ensure that the caller is either the operator or controller.
*/
@@ -59,6 +62,19 @@ contract PausableZone is
_;
}
+ /**
+ * @dev Ensure that the zone is not paused.
+ */
+ modifier isNotPaused() {
+ // Ensure that the zone is not paused.
+ if (isPaused) {
+ revert ZoneIsPaused();
+ }
+
+ // Continue with function execution.
+ _;
+ }
+
/**
* @dev Ensure that the caller is the controller.
*/
@@ -104,16 +120,14 @@ contract PausableZone is
/**
* @notice Pause this contract, safely stopping orders from using
* the contract as a zone. Restricted orders with this address as a
- * zone will not be fulfillable unless the zone is redeployed to the
- * same address.
+ * zone will no longer be fulfillable.
*/
- function pause(address payee) external override isController {
+ function pause() external override isController {
// Emit an event signifying that the zone is paused.
emit Paused();
- // Destroy the zone, sending any native tokens to the transaction
- // submitter.
- selfdestruct(payable(payee));
+ // Pause the zone.
+ isPaused = true;
}
/**
@@ -161,6 +175,7 @@ contract PausableZone is
payable
override
isOperator
+ isNotPaused
returns (Execution[] memory executions)
{
// Call matchOrders on Seaport and return the sequence of transfers
@@ -202,6 +217,7 @@ contract PausableZone is
payable
override
isOperator
+ isNotPaused
returns (Execution[] memory executions)
{
// Call matchAdvancedOrders on Seaport and return the sequence of
@@ -214,6 +230,12 @@ contract PausableZone is
);
}
+ function authorizeOrder(
+ ZoneParameters calldata
+ ) external view isNotPaused returns (bytes4) {
+ return this.authorizeOrder.selector;
+ }
+
/**
* @notice Check if a given order including extraData is currently valid.
*
@@ -234,7 +256,7 @@ contract PausableZone is
* @custom:name zoneParameters
*/
ZoneParameters calldata
- ) external pure override returns (bytes4 validOrderMagicValue) {
+ ) external view override isNotPaused returns (bytes4 validOrderMagicValue) {
// Return the selector of isValidOrder as the magic value.
validOrderMagicValue = ZoneInterface.validateOrder.selector;
}
diff --git a/contracts/zones/PausableZoneController.sol b/contracts/zones/PausableZoneController.sol
index d506404d9..c55249512 100644
--- a/contracts/zones/PausableZoneController.sol
+++ b/contracts/zones/PausableZoneController.sol
@@ -103,7 +103,7 @@ contract PausableZoneController is
)
);
- // Revert if a zone is currently deployed to the derived address.
+ // Revert if a zone is already deployed to the derived address.
if (derivedAddress.code.length != 0) {
revert ZoneAlreadyExists(derivedAddress);
}
@@ -126,7 +126,7 @@ contract PausableZoneController is
address zone
) external override isPauser returns (bool success) {
// Call pause on the given zone.
- PausableZone(zone).pause(msg.sender);
+ PausableZone(zone).pause();
// Return a boolean indicating the pause was successful.
success = true;
diff --git a/contracts/zones/interfaces/PausableZoneEventsAndErrors.sol b/contracts/zones/interfaces/PausableZoneEventsAndErrors.sol
index bb80f9402..d31185e98 100644
--- a/contracts/zones/interfaces/PausableZoneEventsAndErrors.sol
+++ b/contracts/zones/interfaces/PausableZoneEventsAndErrors.sol
@@ -108,4 +108,9 @@ interface PausableZoneEventsAndErrors {
* the potentialOwner role.
*/
error CallerIsNotPotentialOwner();
+
+ /**
+ * @dev Revert with an error when the zone is paused
+ */
+ error ZoneIsPaused();
}
diff --git a/contracts/zones/interfaces/PausableZoneInterface.sol b/contracts/zones/interfaces/PausableZoneInterface.sol
index 19d5d76d1..bfb553731 100644
--- a/contracts/zones/interfaces/PausableZoneInterface.sol
+++ b/contracts/zones/interfaces/PausableZoneInterface.sol
@@ -88,10 +88,9 @@ interface PausableZoneInterface {
/**
* @notice Pause this contract, safely stopping orders from using
* the contract as a zone. Restricted orders with this address as a
- * zone will not be fulfillable unless the zone is redeployed to the
- * same address.
+ * zone will not be fulfillable unless the zone is unpaused.
*/
- function pause(address payee) external;
+ function pause() external;
/**
* @notice Assign the given address with the ability to operate the zone.
diff --git a/docs/AuditLink.md b/docs/AuditLink.md
new file mode 100644
index 000000000..6271cdbe8
--- /dev/null
+++ b/docs/AuditLink.md
@@ -0,0 +1,10 @@
+---
+title: Audit
+category: 6520398b749af50013f52ff4
+slug: seaport-audit
+parentDocSlug: seaport-overview
+order: 6
+hidden: false
+type: link
+link_url: https://github.com/ProjectOpenSea/seaport/tree/main#audits
+---
diff --git a/docs/Code4rena-Guidelines.md b/docs/Code4rena-Guidelines.md
index 9cea5eae5..4a1749b21 100644
--- a/docs/Code4rena-Guidelines.md
+++ b/docs/Code4rena-Guidelines.md
@@ -86,7 +86,7 @@ A full suite of unit tests using Hardhat and Foundry have been provided in this
## Information:
-[https://docs.opensea.io/v2.0/reference/seaport-overview](https://docs.opensea.io/v2.0/reference/seaport-overview)
+[https://docs.opensea.io/docs/seaport](https://docs.opensea.io/docs/seaport)
### Reference Implementation:
@@ -94,4 +94,4 @@ The reference folder has its own implementation of Seaport which is designed to
## Test contracts
-Test contracts and non-solidity files are explicitly out of scope for the competition, though issues and PRs with any new tests you write as part of your investigation are greatly appreciated.
\ No newline at end of file
+Test contracts and non-solidity files are explicitly out of scope for the competition, though issues and PRs with any new tests you write as part of your investigation are greatly appreciated.
diff --git a/docs/Deployment.md b/docs/Deployment.md
index b2c6c68d9..25f881ea6 100644
--- a/docs/Deployment.md
+++ b/docs/Deployment.md
@@ -1,6 +1,15 @@
+---
+title: Deployment
+category: 6520398b749af50013f52ff4
+slug: seaport-deployment
+parentDocSlug: seaport-overview
+order: 6
+hidden: false
+---
+
# Deploying Seaport
-Seaport 1.5 and the ConduitController can each be deployed to their respective canonical deployment address on all EVM chains using the CREATE2 Factory. Note that a pre-155 transaction with a gas price of 100 gwei (or a manual workaround) is required as part of the deployment process (subsequent transactions can be submitted without these constraints), and that EVM equivalence (particularly consistent CREATE2 address derivation) is required in order to deploy to the canonical cross-chain deployment addresses.
+Seaport 1.6 and the ConduitController can each be deployed to their respective canonical deployment address on all EVM chains using the CREATE2 Factory. Note that a pre-155 transaction with a gas price of 100 gwei (or a manual workaround) is required as part of the deployment process (subsequent transactions can be submitted without these constraints), and that EVM equivalence (particularly consistent CREATE2 address derivation) is required in order to deploy to the canonical cross-chain deployment addresses.
If you are deploying a fork of Seaport, it is *highly* advised that you **supply the canonical conduit controller** as its constructor argument; this allows the Seaport fork to use conduits that are fully interoperable with the canonical Seaport instance. (Better yet, deploy the canonical Seaport instance and use a distinct conduit if needed!)
@@ -32,8 +41,8 @@ If you are deploying a fork of Seaport, it is *highly* advised that you **supply
0x00000000F9490004C11Cef243f5400493c00Ad63 |
- | Seaport 1.5 |
- 0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC |
+ Seaport 1.6 |
+ 0x0000000000000068F116a894984e2DB1123eB395 |
@@ -72,27 +81,27 @@ Once the `IMMUTABLE_CREATE2_FACTORY_ADDRESS` exists, begin to deploy the contrac
cast send --rpc-url ${RPC_URL} --private-key ${PK} 0x0000000000ffe8b47b3e2130213b802212439497 0x64e030870000000000000000000000000000000000000000dc0ef3c792976604960400000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000302760c08060405234620000ea57600090610c9f906001600160401b03603f8301601f1916820181811183821017620000da575b604052828252620023889160208101908484833951902060805260405192839281840192831184841017620000ca575b8339039082f58015620000ba575b6001600160a01b03163f60a05260405161227490816200011482396080518181816102b101528181610bcc0152610d06015260a0518181816102d401528181610c620152610da90152f35b620000c462000106565b6200006f565b620000d4620000ef565b62000061565b620000e4620000ef565b62000031565b600080fd5b50634e487b7160e01b600052604160045260246000fd5b506040513d6000823e3d90fdfe60806040526004361015610013575b600080fd5b60003560e01c8063027cc7641461012b5780630a96ad391461012257806313ad9cab1461011957806314afd79e1461011057806333bc8572146101075780634e3f9580146100fe57806351710e45146100f55780636d435421146100ec5780636e9bfd9f146100e3578063794593bc146100da5780637b37e561146100d15780638b9e028b146100c8578063906c87cc146100bf576393790f44146100b757600080fd5b61000e61126e565b5061000e6111fa565b5061000e61113c565b5061000e610fc8565b5061000e610c8a565b5061000e610b3c565b5061000e6109bf565b5061000e610765565b5061000e6106f3565b5061000e61064f565b5061000e6105db565b5061000e6102fa565b5061000e61027b565b5061000e61017a565b6004359073ffffffffffffffffffffffffffffffffffffffff8216820361000e57565b6024359073ffffffffffffffffffffffffffffffffffffffff8216820361000e57565b503461000e5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261000e576101b2610134565b602435906101bf81611574565b73ffffffffffffffffffffffffffffffffffffffff80911691600083815280602052600360408220015482101561023f5790600360408361023b9661020a9552806020522001611400565b90549060031b1c166040519182918291909173ffffffffffffffffffffffffffffffffffffffff6020820193169052565b0390f35b602484604051907f6ceb340b0000000000000000000000000000000000000000000000000000000082526004820152fd5b600091031261000e57565b503461000e5760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261000e57604080517f000000000000000000000000000000000000000000000000000000000000000081527f00000000000000000000000000000000000000000000000000000000000000006020820152f35b503461000e5760607ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261000e57610332610134565b61033a610157565b90604435918215918215840361000e5761035381611505565b73ffffffffffffffffffffffffffffffffffffffff811690813b1561000e576040517fc4e8fcb500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff841660048201528515156024820152610401926000908290604490829084905af180156105ce575b6105b5575b5073ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b92600484019261043183859073ffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b5491821590806105ae575b1561048157505050600361047d92930161045682826114ce565b54929073ffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b555b005b91949391816105a5575b5061049257005b6104df61047d938560037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600098019201916104ce83546113a4565b90808203610504575b505050611447565b9073ffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b6105766105449161053b61051b61059c9588611400565b905473ffffffffffffffffffffffffffffffffffffffff9160031b1c1690565b92839187611400565b90919082549060031b9173ffffffffffffffffffffffffffffffffffffffff9283811b93849216901b16911916179055565b859073ffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b553880806104d7565b9050153861048b565b508061043c565b806105c26105c892611335565b80610270565b386103da565b6105d6611397565b6103d5565b503461000e5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261000e576020610615610134565b61061e81611574565b73ffffffffffffffffffffffffffffffffffffffff8091166000526000825260016040600020015416604051908152f35b503461000e5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261000e5760206106e861068c610134565b73ffffffffffffffffffffffffffffffffffffffff6106a9610157565b916106b381611574565b166000526000835260046040600020019073ffffffffffffffffffffffffffffffffffffffff16600052602052604060002090565b541515604051908152f35b503461000e5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261000e5773ffffffffffffffffffffffffffffffffffffffff610740610134565b61074981611574565b1660005260006020526020600360406000200154604051908152f35b503461000e5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261000e5761079d610134565b6107a681611574565b61080c6107f360026107d88473ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b015473ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff1690565b33036109765761047f9060007f11a3cf439fb225bfe74225716b6774765670ec1060e3796802e62139d69974da81604051a2610896600261086d8373ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b017fffffffffffffffffffffffff00000000000000000000000000000000000000008154169055565b73ffffffffffffffffffffffffffffffffffffffff3390806108dd60016107d88673ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b169083167fc8894f26f396ce8c004245c8b7cd1b92103a6e4302fcbab883987149ac01b7ec6000604051a46001610935339273ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b019073ffffffffffffffffffffffffffffffffffffffff167fffffffffffffffffffffffff0000000000000000000000000000000000000000825416179055565b6040517f88c3a11500000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff919091166004820152602490fd5b503461000e5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261000e576109f7610134565b6109ff610157565b90610a0981611505565b73ffffffffffffffffffffffffffffffffffffffff808316908115610b095750610a5b6107f360026107d88573ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b8114610ab95761093561047f93926002927f11a3cf439fb225bfe74225716b6774765670ec1060e3796802e62139d69974da6000604051a273ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b506040517fcbc080ca00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff918216600482015291166024820152604490fd5b82602491604051917fa388d263000000000000000000000000000000000000000000000000000000008352166004820152fd5b503461000e5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261000e576040517fff00000000000000000000000000000000000000000000000000000000000000602082019081523060601b7fffffffffffffffffffffffffffffffffffffffff00000000000000000000000016602183015260043560358301527f0000000000000000000000000000000000000000000000000000000000000000605583015273ffffffffffffffffffffffffffffffffffffffff91610c3b81607581015b037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101835282611356565b519020604080519290911673ffffffffffffffffffffffffffffffffffffffff811683523f7f000000000000000000000000000000000000000000000000000000000000000014602083015290f35b503461000e576040807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261000e57600435610cc6610157565b73ffffffffffffffffffffffffffffffffffffffff91828216908115610f9f57338160601c03610f7657610da46107f386516020810190610d8881610c0f7f0000000000000000000000000000000000000000000000000000000000000000883087917fffffffffffffffffffffffffffffffffffffffff000000000000000000000000605594927fff00000000000000000000000000000000000000000000000000000000000000855260601b166001840152601583015260358201520190565b51902073ffffffffffffffffffffffffffffffffffffffff1690565b92833f7f000000000000000000000000000000000000000000000000000000000000000014610f3057947f4397af6128d529b8ae0442f99db1296d5136062597a15bbc61c1b2a6431a7d15610eca838060009961023b989796865180610c9f8082019082821067ffffffffffffffff831117610f23575b6115a0833903908df515610f16575b610e9c610e578973ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b91600183019073ffffffffffffffffffffffffffffffffffffffff167fffffffffffffffffffffffff0000000000000000000000000000000000000000825416179055565b55835173ffffffffffffffffffffffffffffffffffffffff8716815260208101919091529081906040820190565b0390a15194859483167fc8894f26f396ce8c004245c8b7cd1b92103a6e4302fcbab883987149ac01b7ec8287a473ffffffffffffffffffffffffffffffffffffffff1682526020820190565b610f1e611397565b610e2a565b610f2b611305565b610e1b565b85517f6328ccb200000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff85166004820152602490fd5b600485517fcb6e5344000000000000000000000000000000000000000000000000000000008152fd5b600485517f99faaa04000000000000000000000000000000000000000000000000000000008152fd5b503461000e5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261000e57611000610134565b61100981611505565b73ffffffffffffffffffffffffffffffffffffffff9081811660009281845283602052600260408520015416156110ba575061108e600291837f11a3cf439fb225bfe74225716b6774765670ec1060e3796802e62139d69974da81604051a273ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b017fffffffffffffffffffffffff00000000000000000000000000000000000000008154169055604051f35b602490604051907f6b0136160000000000000000000000000000000000000000000000000000000082526004820152fd5b6020908160408183019282815285518094520193019160005b828110611112575050505090565b835173ffffffffffffffffffffffffffffffffffffffff1685529381019392810192600101611104565b503461000e576020807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261000e57611175610134565b9061117f82611574565b73ffffffffffffffffffffffffffffffffffffffff91826000911681528082526003604082200192604051908193808654938481520195845280842093915b8383106111e15761023b866111d5818a0382611356565b604051918291826110eb565b84548116875295810195600194850194909201916111be565b503461000e5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261000e576020611234610134565b61123d81611574565b73ffffffffffffffffffffffffffffffffffffffff8091166000526000825260026040600020015416604051908152f35b503461000e5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261000e5773ffffffffffffffffffffffffffffffffffffffff6112bb610134565b16600052600060205260406000205480156112db57602090604051908152f35b60046040517f4ca82090000000000000000000000000000000000000000000000000000000008152fd5b507f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b67ffffffffffffffff811161134957604052565b611351611305565b604052565b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff82111761134957604052565b506040513d6000823e3d90fd5b600181106113d1577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b80548210156114185760005260206000200190600090565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b8054801561149f577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff019061147c8282611400565b73ffffffffffffffffffffffffffffffffffffffff82549160031b1b1916905555565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603160045260246000fd5b906105446114f692805490680100000000000000008210156114f8575b600182018155611400565b565b611500611305565b6114eb565b61150e81611574565b73ffffffffffffffffffffffffffffffffffffffff809116908160005260006020526001604060002001541633036115435750565b602490604051907fd4ed9a170000000000000000000000000000000000000000000000000000000082526004820152fd5b73ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002054156112db5756fe60a080604052346100235733608052610c7690816100298239608051816103c50152f35b600080fdfe60806040526004361015610013575b600080fd5b6000803560e01c9081634ce34aa21461006657508063899e104c1461005d5780638df25d92146100545763c4e8fcb51461004c57600080fd5b61000e610362565b5061000e61027f565b5061000e6101ab565b346101465760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101465760043567ffffffffffffffff8111610142576100b5903690600401610149565b9133815280602052604081205415610116575b8281106100fa576040517f4ce34aa2000000000000000000000000000000000000000000000000000000008152602090f35b8061011061010b6001938686610532565b6105c4565b016100c8565b807f93daadf2000000000000000000000000000000000000000000000000000000006024925233600452fd5b5080fd5b80fd5b9181601f8401121561000e5782359167ffffffffffffffff831161000e5760208085019460c0850201011161000e57565b9181601f8401121561000e5782359167ffffffffffffffff831161000e576020808501948460051b01011161000e57565b503461000e5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261000e5767ffffffffffffffff60043581811161000e576101fc903690600401610149565b9160243590811161000e5761021590369060040161017a565b919092600033815280602052604081205415610116575b8181106102685761023d8486610acb565b6040517f899e104c000000000000000000000000000000000000000000000000000000008152602090f35b8061027961010b6001938587610532565b0161022c565b503461000e5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261000e5760043567ffffffffffffffff811161000e576102cf90369060040161017a565b33600052600060205260406000205415610316576102ec91610acb565b60206040517f8df25d92000000000000000000000000000000000000000000000000000000008152f35b7f93daadf2000000000000000000000000000000000000000000000000000000006000523360045260246000fd5b73ffffffffffffffffffffffffffffffffffffffff81160361000e57565b503461000e5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261000e5760043561039e81610344565b6024359081151580830361000e5773ffffffffffffffffffffffffffffffffffffffff90817f00000000000000000000000000000000000000000000000000000000000000001633036105085761041f6104188473ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b5460ff1690565b1515146104b657816104a6846104767fae63067d43ac07563b7eb8db6595635fc77f1578a2a5ea06ba91b63e2afa37e29573ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b9060ff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0083541691151516179055565b60405193151584521691602090a2005b506040517f924e341e00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9190911660048201529015156024820152604490fd5b60046040517f6d5769be000000000000000000000000000000000000000000000000000000008152fd5b91908110156105425760c0020190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6004111561057b57565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b35600481101561000e5790565b356105c181610344565b90565b60016105cf826105aa565b6105d881610571565b0361061357806105ed602061061193016105b7565b906105fa604082016105b7565b60a0610608606084016105b7565b92013592610712565b565b600261061e826105aa565b61062781610571565b0361069657600160a08201350361066c5780610648602061061193016105b7565b90610655604082016105b7565b6080610663606084016105b7565b92013592610882565b60046040517fefcc00b1000000000000000000000000000000000000000000000000000000008152fd5b60036106a1826105aa565b6106aa81610571565b036106e857806106bf602061061193016105b7565b6106cb604083016105b7565b6106d7606084016105b7565b90608060a085013594013592610990565b60046040517f7932f1fc000000000000000000000000000000000000000000000000000000008152fd5b9092604051926000947f23b872dd00000000000000000000000000000000000000000000000000000000865280600452816024528260445260208660648180885af1803d15601f3d1160018a51141617163d151581161561077c575b505050505050604052606052565b80863b15151661076e579087959691156107bc57602486887f5f15d672000000000000000000000000000000000000000000000000000000008252600452fd5b156107f657506084947f98891923000000000000000000000000000000000000000000000000000000008552600452602452604452606452fd5b3d610835575b5060a4947ff486bc8700000000000000000000000000000000000000000000000000000000855260045260245260445281606452608452fd5b601f3d0160051c9060051c908060030291808211610869575b505060205a91011061086057856107fc565b833d81803e3d90fd5b8080600392028380020360091c9203020101868061084e565b9092813b1561096257604051926000947f23b872dd000000000000000000000000000000000000000000000000000000008652806004528160245282604452858060648180885af1156108db5750505050604052606052565b8593943d61091e575b5060a4947ff486bc870000000000000000000000000000000000000000000000000000000085526004526024526044526064526001608452fd5b601f3d0160051c9060051c908060030291808211610949575b505060205a91011061086057856108e4565b8080600392028380020360091c92030201018680610937565b507f5f15d6720000000000000000000000000000000000000000000000000000000060005260045260246000fd5b929093833b15610a9d57604051936080519160a0519360c051956000987ff242432a000000000000000000000000000000000000000000000000000000008a528060045281602452826044528360645260a06084528960a452898060c48180895af115610a0d57505050505060805260a05260c052604052606052565b89949550883d610a50575b5060a4957ff486bc87000000000000000000000000000000000000000000000000000000008652600452602452604452606452608452fd5b601f3d0160051c9060051c908060030291808211610a84575b505060205a910110610a7b5786610a18565b843d81803e3d90fd5b8080600392028380020360091c92030201018780610a69565b837f5f15d6720000000000000000000000000000000000000000000000000000000060005260045260246000fd5b90816020907f2eb2c2d600000000000000000000000000000000000000000000000000000000825260005b838110610b095750505050506080604052565b8435820194853590813b156109625760a09182880192833560059181831b948b60c08097608094818301868501351490606085013514169201013584141615610c165789019a890160243760061b9360e0850160a452610104850194600086526040019060c437600080858982865af115610b8a5750505050600101610af6565b869394503d610bcb575b507fafc445e20000000000000000000000000000000000000000000000000000000060005260045260645260849081510190526000fd5b84601f3d01821c911c90600381810292808311610bff575b505050835a910110610bf55784610b94565b3d6000803e3d6000fd5b8080028380020360091c9203020101858080610be3565b7feba2084c0000000000000000000000000000000000000000000000000000000060005260046000fdfea2646970667358221220c5c8d054d9d5df7c3530eab1c32506aad1fcb6772c1457f0da5443ad9e91b4a364736f6c634300080e0033a264697066735822122031e2de61a9e35e9e87d5eef6a36b045a0bab54c4031fd01a0f8138afce3cec3164736f6c634300080e003360a080604052346100235733608052610c7690816100298239608051816103c50152f35b600080fdfe60806040526004361015610013575b600080fd5b6000803560e01c9081634ce34aa21461006657508063899e104c1461005d5780638df25d92146100545763c4e8fcb51461004c57600080fd5b61000e610362565b5061000e61027f565b5061000e6101ab565b346101465760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101465760043567ffffffffffffffff8111610142576100b5903690600401610149565b9133815280602052604081205415610116575b8281106100fa576040517f4ce34aa2000000000000000000000000000000000000000000000000000000008152602090f35b8061011061010b6001938686610532565b6105c4565b016100c8565b807f93daadf2000000000000000000000000000000000000000000000000000000006024925233600452fd5b5080fd5b80fd5b9181601f8401121561000e5782359167ffffffffffffffff831161000e5760208085019460c0850201011161000e57565b9181601f8401121561000e5782359167ffffffffffffffff831161000e576020808501948460051b01011161000e57565b503461000e5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261000e5767ffffffffffffffff60043581811161000e576101fc903690600401610149565b9160243590811161000e5761021590369060040161017a565b919092600033815280602052604081205415610116575b8181106102685761023d8486610acb565b6040517f899e104c000000000000000000000000000000000000000000000000000000008152602090f35b8061027961010b6001938587610532565b0161022c565b503461000e5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261000e5760043567ffffffffffffffff811161000e576102cf90369060040161017a565b33600052600060205260406000205415610316576102ec91610acb565b60206040517f8df25d92000000000000000000000000000000000000000000000000000000008152f35b7f93daadf2000000000000000000000000000000000000000000000000000000006000523360045260246000fd5b73ffffffffffffffffffffffffffffffffffffffff81160361000e57565b503461000e5760407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261000e5760043561039e81610344565b6024359081151580830361000e5773ffffffffffffffffffffffffffffffffffffffff90817f00000000000000000000000000000000000000000000000000000000000000001633036105085761041f6104188473ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b5460ff1690565b1515146104b657816104a6846104767fae63067d43ac07563b7eb8db6595635fc77f1578a2a5ea06ba91b63e2afa37e29573ffffffffffffffffffffffffffffffffffffffff166000526000602052604060002090565b9060ff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0083541691151516179055565b60405193151584521691602090a2005b506040517f924e341e00000000000000000000000000000000000000000000000000000000815273ffffffffffffffffffffffffffffffffffffffff9190911660048201529015156024820152604490fd5b60046040517f6d5769be000000000000000000000000000000000000000000000000000000008152fd5b91908110156105425760c0020190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b6004111561057b57565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b35600481101561000e5790565b356105c181610344565b90565b60016105cf826105aa565b6105d881610571565b0361061357806105ed602061061193016105b7565b906105fa604082016105b7565b60a0610608606084016105b7565b92013592610712565b565b600261061e826105aa565b61062781610571565b0361069657600160a08201350361066c5780610648602061061193016105b7565b90610655604082016105b7565b6080610663606084016105b7565b92013592610882565b60046040517fefcc00b1000000000000000000000000000000000000000000000000000000008152fd5b60036106a1826105aa565b6106aa81610571565b036106e857806106bf602061061193016105b7565b6106cb604083016105b7565b6106d7606084016105b7565b90608060a085013594013592610990565b60046040517f7932f1fc000000000000000000000000000000000000000000000000000000008152fd5b9092604051926000947f23b872dd00000000000000000000000000000000000000000000000000000000865280600452816024528260445260208660648180885af1803d15601f3d1160018a51141617163d151581161561077c575b505050505050604052606052565b80863b15151661076e579087959691156107bc57602486887f5f15d672000000000000000000000000000000000000000000000000000000008252600452fd5b156107f657506084947f98891923000000000000000000000000000000000000000000000000000000008552600452602452604452606452fd5b3d610835575b5060a4947ff486bc8700000000000000000000000000000000000000000000000000000000855260045260245260445281606452608452fd5b601f3d0160051c9060051c908060030291808211610869575b505060205a91011061086057856107fc565b833d81803e3d90fd5b8080600392028380020360091c9203020101868061084e565b9092813b1561096257604051926000947f23b872dd000000000000000000000000000000000000000000000000000000008652806004528160245282604452858060648180885af1156108db5750505050604052606052565b8593943d61091e575b5060a4947ff486bc870000000000000000000000000000000000000000000000000000000085526004526024526044526064526001608452fd5b601f3d0160051c9060051c908060030291808211610949575b505060205a91011061086057856108e4565b8080600392028380020360091c92030201018680610937565b507f5f15d6720000000000000000000000000000000000000000000000000000000060005260045260246000fd5b929093833b15610a9d57604051936080519160a0519360c051956000987ff242432a000000000000000000000000000000000000000000000000000000008a528060045281602452826044528360645260a06084528960a452898060c48180895af115610a0d57505050505060805260a05260c052604052606052565b89949550883d610a50575b5060a4957ff486bc87000000000000000000000000000000000000000000000000000000008652600452602452604452606452608452fd5b601f3d0160051c9060051c908060030291808211610a84575b505060205a910110610a7b5786610a18565b843d81803e3d90fd5b8080600392028380020360091c92030201018780610a69565b837f5f15d6720000000000000000000000000000000000000000000000000000000060005260045260246000fd5b90816020907f2eb2c2d600000000000000000000000000000000000000000000000000000000825260005b838110610b095750505050506080604052565b8435820194853590813b156109625760a09182880192833560059181831b948b60c08097608094818301868501351490606085013514169201013584141615610c165789019a890160243760061b9360e0850160a452610104850194600086526040019060c437600080858982865af115610b8a5750505050600101610af6565b869394503d610bcb575b507fafc445e20000000000000000000000000000000000000000000000000000000060005260045260645260849081510190526000fd5b84601f3d01821c911c90600381810292808311610bff575b505050835a910110610bf55784610b94565b3d6000803e3d6000fd5b8080028380020360091c9203020101858080610be3565b7feba2084c0000000000000000000000000000000000000000000000000000000060005260046000fdfea2646970667358221220c5c8d054d9d5df7c3530eab1c32506aad1fcb6772c1457f0da5443ad9e91b4a364736f6c634300080e003300000000000000000000000000000000000000000000000000
```
-2. Deploy the `Seaport 1.5` contract by submitting:
+2. Deploy the `Seaport 1.6` contract by submitting:
```
-cast send --rpc-url ${RPC_URL} --private-key ${PK} 0x0000000000ffe8b47b3e2130213b802212439497 0x64e030870000000000000000000000000000000000000000d4b6fcc21169b803f25d22100000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000660c6101c060405234620000b9576200001f6200001962000114565b62000151565b604051615f2f9081620006bd823960805181612622015260a05181612646015260c051816125ff015260e0518181816113b80152612430015261010051818181611257015261247f01526101205181818161145e01526124eb015261014051816125ac015261016051816125d3015261018051818181610f1f01528181612144015261226501526101a05181818161218201526122a30152f35b600080fd5b604081019081106001600160401b03821117620000da57604052565b634e487b7160e01b600052604160045260246000fd5b601f909101601f19168101906001600160401b03821190821017620000da57604052565b620065ec60208138039182604051938492620001318285620000f0565b833981010312620000b957516001600160a01b0381168103620000b95790565b60406004916200016062000587565b610120526101005260e05260c05260a0526080524661014052620001b060c0519060805160a0516040519360005281602052604052466060523060805260a0600020926040526000606052608052565b610160526001600160a01b03166101808190528151630a96ad3960e01b815292839182905afa90811562000230575b600091620001fa575b506101a052620001f86001600055565b565b62000220915060403d811162000228575b620002178183620000f0565b81019062000240565b5038620001e8565b503d6200020b565b6200023a62000257565b620001df565b9190826040910312620000b9576020825192015190565b506040513d6000823e3d90fd5b604051906200027382620000be565b60038252565b6040519060a082016001600160401b03811183821017620000da57604052606a8252565b6040519060c082016001600160401b03811183821017620000da576040526084825263656e742960e01b60a0837f436f6e73696465726174696f6e4974656d2875696e7438206974656d5479706560208201527f2c6164647265737320746f6b656e2c75696e74323536206964656e746966696560408201527f724f7243726974657269612c75696e74323536207374617274416d6f756e742c60608201527f75696e7432353620656e64416d6f756e742c616464726573732072656369706960808201520152565b6040519061010082016001600160401b03811183821017620000da5760405260d482527f4b65792c75696e7432353620636f756e7465722900000000000000000000000060e0837f4f72646572436f6d706f6e656e74732861646472657373206f6666657265722c60208201527f61646472657373207a6f6e652c4f666665724974656d5b5d206f666665722c4360408201527f6f6e73696465726174696f6e4974656d5b5d20636f6e73696465726174696f6e60608201527f2c75696e7438206f72646572547970652c75696e74323536207374617274546960808201527f6d652c75696e7432353620656e6454696d652c62797465733332207a6f6e654860a08201527f6173682c75696e743235362073616c742c6279746573333220636f6e6475697460c08201520152565b60405190608082016001600160401b03811183821017620000da576040526052825271766572696679696e67436f6e74726163742960701b6060837f454950373132446f6d61696e28737472696e67206e616d652c737472696e672060208201527f76657273696f6e2c75696e7432353620636861696e49642c616464726573732060408201520152565b9081519160005b83811062000539575050016000815290565b806020809284010151818501520162000527565b6200057862000571949362000571620001f894604051978895602087019062000520565b9062000520565b03601f198101845283620000f0565b6040516200059581620000be565b600781526614d9585c1bdc9d60ca1b6020918201527f32b5c112df393a49218d7552f96b2eeb829dfb4272f4f24eef510a586b85feef91620005d662000264565b8281019062312e3560e81b825251902091620005f162000279565b818101927f4f666665724974656d2875696e7438206974656d547970652c6164647265737384527f20746f6b656e2c75696e74323536206964656e7469666965724f72437269746560408301527f7269612c75696e74323536207374617274416d6f756e742c75696e7432353620606083015269656e64416d6f756e742960b01b6080830152620006816200029d565b92620006b46200069062000366565b936200069b62000495565b838151910120968151902095805184820120956200054d565b80519101209056fe60806040526004361015610023575b361561001957600080fd5b610021614f96565b005b60003560e01c80156100eb57806306fdde031461016957806346423aa7146101605780635b34b9661461015757806379df72bd1461014e57806387201b4114610145578063881477321461013c578063a817440414610133578063a900866b1461012a578063b3a34c4c14610121578063e7acab2414610118578063ed98a5741461010f578063f07ec37314610106578063f2d12b12146100fd578063f47b7740146100f4578063fb0f3ee1146100eb5763fd9f1e100361000e576100e6610f50565b61000e565b506100e66101c8565b506100e6610ec8565b506100e6610df2565b506100e6610d8a565b506100e6610cc2565b506100e6610c05565b506100e6610b81565b506100e6610b17565b506100e6610a60565b506100e66108d6565b506100e66107c6565b506100e661059d565b506100e66104f5565b506100e6610474565b506100e661042e565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc906020828201126101c3576004359167ffffffffffffffff83116101c35782610240920301126101c35760040190565b600080fd5b506101d236610172565b6101243590600382169160021c91600183119234158403610420575b60038111907f0203020301010000000000000000000000000000000000000000000000000000811a9061024c8260a0850260240135887d010102030000000000000000000000000000000000000000000000000000851a888a61121a565b928060051b6101c4013596610260816106a8565b6102b3575050604435602435176102a55761028b9461027e916115b5565b61028661166d565b6159cc565b6102956001600055565b60405160018152602090f35b0390f35b636ab37ce76000526004601cfd5b610286925061028b969161032a916102c96111a8565b9384836102d682956106a8565b6002810361032f5750610325918a6102f060a082016111bf565b6102fc606083016111bf565b60c060e08401359301359173ffffffffffffffffffffffffffffffffffffffff33921690611efe565b611738565b612105565b610338816106a8565b600381036103875750610325918a61035260a082016111bf565b61035e606083016111bf565b60c060e08401359301359173ffffffffffffffffffffffffffffffffffffffff33921690611fff565b806103936004926106a8565b036103dc57610325918a6103a6816111bf565b6103b2606083016111bf565b9073ffffffffffffffffffffffffffffffffffffffff602060408501359401359216903390611efe565b610325918a6103ea816111bf565b6103f6606083016111bf565b9073ffffffffffffffffffffffffffffffffffffffff602060408501359401359216903390611fff565b61042934611d42565b6101ee565b50346101c35760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101c357602080526707536561706f727460475260606020f35b50346101c35760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101c357600435600052600260205260806040600020546040519060ff81161515825260ff8160081c16151560208301526effffffffffffffffffffffffffffff8160101c16604083015260881c6060820152f35b50346101c35760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101c35761052d614f7c565b3360005260016020526020604060002080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff43014060801c018091556040518181527f721c20121297512b72821b97f5326877ea8ecf4bb9948fea5bfcb6453074d37f833392a2604051908152f35b50346101c3577ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc6020813601126101c3576004359067ffffffffffffffff82116101c3576101609082360301126101c35761061263ffffffff6020921661014461060982600401611cd6565b91013590612423565b604051908152f35b9181601f840112156101c35782359167ffffffffffffffff83116101c3576020808501948460051b0101116101c357565b73ffffffffffffffffffffffffffffffffffffffff8116036101c357565b60a435906106768261064b565b565b507f4e487b7100000000000000000000000000000000000000000000000000000000600052602160045260246000fd5b600611156106b257565b610676610678565b60809080516106c8816106a8565b83528173ffffffffffffffffffffffffffffffffffffffff918260208201511660208601526040810151604086015260608101516060860152015116910152565b90815180825260208080930193019160005b828110610729575050505090565b909192938260e0600192604088516107428382516106ba565b8085015173ffffffffffffffffffffffffffffffffffffffff1660a0840152015160c08201520195019392910161071b565b9092916040820191604081528451809352606081019260208096019060005b8181106107b0575050506107ad9394818403910152610709565b90565b8251151586529487019491870191600101610793565b5060e07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101c35767ffffffffffffffff6004358181116101c35761081290369060040161061a565b50506024358181116101c35761082c90369060040161061a565b50506044358181116101c35761084690369060040161061a565b50506064359081116101c35761086090369060040161061a565b505061087961086d610669565b60c43590608435611813565b906102a160405192839283610774565b60207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc8201126101c3576004359067ffffffffffffffff82116101c3576108d29160040161061a565b9091565b50346101c3576108e536610889565b505060046108fb63ffffffff8235168201611aba565b90610904614f7c565b81519060005b82811061091d5760405160018152602090f35b8061092a60019286612988565b51805184608082015161093c81612934565b61094581612934565b14610a4857805173ffffffffffffffffffffffffffffffffffffffff1661096b82614762565b90610980826000526002602052604060002090565b61098a81846158f0565b5061099d610999825460ff1690565b1590565b6109ae575b50505050505b0161090a565b6109f4610a1f928460207ff280791efe782edcf06ce15c8f4dff17601db3b88eb3805a0db7d77faf757f04986060890151516101408a015103610a3b575b015191615199565b60017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00825416179055565b610a2e60405192839283614e56565b0390a138808080806109a2565b610a43614c68565b6109ec565b50506109a8565b9060206107ad928181520190610709565b5060407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101c35760043567ffffffffffffffff8082116101c357610aab368360040161061a565b50506024359081116101c3576102a191610b0391610acc368260040161061a565b5050610afb610ae463ffffffff809416600401615ec5565b92610aed6110db565b926000845216600401611c52565b903392613b96565b604051918291602083526020830190610709565b50346101c35760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101c35773ffffffffffffffffffffffffffffffffffffffff600435610b688161064b565b1660005260036020526020604060002054604051908152f35b507ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc6040813601126101c3576004359067ffffffffffffffff82116101c35760409082360301126101c357610bfb610be363ffffffff602093166004016119cd565b610beb6110db565b9060008252339160243591613f10565b6040519015158152f35b507ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc6080813601126101c3576004359067ffffffffffffffff908183116101c35760a09083360301126101c3576024359081116101c3576102a191610cb091610c71368260040161061a565b5050610ca060643592610c838461064b565b610c9663ffffffff80921660040161186c565b9216600401611a2d565b9133811502019160443591613f10565b60405190151581529081906020820190565b5060a07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101c357600467ffffffffffffffff81358181116101c357610d0d3682850161061a565b5050602435908282116101c357610d263683860161061a565b50506044359283116101c357610d7b61087994610d453686830161061a565b5050610d5963ffffffff8094168201615ec5565b92610d7381610d666110db565b9660008852168301611b44565b951601611b44565b608435933393606435936126d4565b50346101c35760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101c3576020610612600435610dcb8161064b565b73ffffffffffffffffffffffffffffffffffffffff16600052600160205260406000205490565b5060807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101c35767ffffffffffffffff600480358281116101c357610e3d3682840161061a565b5050602435908382116101c357610e563683850161061a565b50506044359384116101c3576102a193610eb0610ebc94610e793684830161061a565b5050610e9f610ea860643595610e8e8761064b565b63ffffffff92838092168501611bf5565b97168301611a2d565b931601611c52565b91338115020192613b96565b60405191829182610a4f565b50346101c35760007ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc3601126101c357610f006125a7565b606060005260205273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166040526303312e3560635260a06000f35b50346101c357610f5f36610889565b90610f68614f7c565b600091825b818110610f925783610f855760405160018152602090f35b610f8d614d23565b610295565b80610fa06001928486614cc8565b94610faa866111bf565b907f6bacc01dbe442496068f7d234edd811f1a5f833243e0aec824f86ab861f3c90d611075611006610fde60208b016111bf565b93610feb60808c01614d16565b60048633148833141715911417179961014061060982611cd6565b9261104a61101e856000526002602052604060002090565b80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000016610100179055565b60405193845273ffffffffffffffffffffffffffffffffffffffff9081169416929081906020820190565b0390a301610f6d565b507f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6040519060a0820182811067ffffffffffffffff8211176110ce57604052565b6110d661107e565b604052565b604051906020820182811067ffffffffffffffff8211176110ce57604052565b604051906040820182811067ffffffffffffffff8211176110ce57604052565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f604051930116820182811067ffffffffffffffff8211176110ce57604052565b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f60209267ffffffffffffffff811161119b575b01160190565b6111a361107e565b611195565b6111b06110fb565b90602082526020828136910137565b356107ad8161064b565b9035907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe1813603018212156101c3570180359067ffffffffffffffff82116101c3576020019181360383136101c357565b959392919094611228614f4e565b61123061155f565b6101643561014435428211154282111761154b57505061020435610264351061153d5793907f00000000000000000000000000000000000000000000000000000000000000006080528060a0526060602460c037604060646101203760e06080908120610160526001610264359081016102a060059290921b918201526102c081019283526024906102e00137610160948360a0528460c052600060e05260009260005b83610204358210156113315790604060019261010060a060208560061b9a818c610284018537858c61028401610120376102a48c0135179d019860e06080208a5201988a8a528b60c08401526102840191013701969392966112d4565b5096509192979690976001610204350160051b610160206060525b836102643588101561138957906102a460a060019301958787528860c082015260408a60061b91610100836102840191013701351796019561134c565b50925095945095925073ffffffffffffffffffffffffffffffffffffffff91501161152f576107ad91611528917f00000000000000000000000000000000000000000000000000000000000000006080528060a052606060c460c03760206101046101203760c0608020600052602060002060e05260016102643560051b610200015261022090816102643560051b0152606060c46102406102643560051b013761036060843561145a8173ffffffffffffffffffffffffffffffffffffffff166000526001602052604060002090565b54967f00000000000000000000000000000000000000000000000000000000000000006080526040608460a037606051610100526101205260a0610144610140376101e09687526101809687608020976102643560051b0191888352336101a06102643560051b015260806101c06102643560051b0152610120826102643560051b01527f9d9af8e38d66c62e2c12f0225249fd9d721c54b83f48d9352c97c6cacdcb6f3160a06102643502938460a435940190a360006060526102643560051b01016040528101906111c9565b908361430d565b6339f3e3fd6000526004601cfd5b63466aa6166000526004601cfd5b6321ccfeb76000526020526040526044601cfd5b7401000000000000000000000000000000000000000060243560c4351760a43560843517171060186101243510166102643560061b61026001610244351461024061022435146020600435141616161561152f57565b608435916101043560e43560c4358315611627579461067695604051957f4ce34aa200000000000000000000000000000000000000000000000000000000875260206004880152600160248801526044870152606486015260848501523360a485015260c484015260e483015261223e565b925092806116366002926106a8565b0361166057928360016106769503611651575b503391614fab565b61165a90611d31565b38611649565b919061067693339161508a565b3460643560006102643560061b815b8181106116bd575050508181116116b0575b61169a81608435611d62565b8082116116a5575050565b610676910333611d62565b6116b8611d22565b61168e565b806102840135948086116116e657906116e08660409303966102a4830135611d62565b0161167c565b638ffff98084526004601cfd5b507f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b9190820391821161173057565b6106766116f3565b919082156117d95760843592610104353360c43560e4355b6117cc575b8360051b6101e40335936102643560061b9060005b82811061177f57505050956106769596611dae565b87876102848301358c856117ab575b918493916117a5936102a46040970135908a611dae565b0161176a565b9891816117bf60409695936117a595611723565b9a9193509193945061178e565b6117d4611d53565b611755565b3392606435608435602435604435611750565b60209067ffffffffffffffff8111611806575b60051b0190565b61180e61107e565b6117ff565b906108d2929163ffffffff9161182f8360043516600401611bf5565b926118408160243516600401611a2d565b6118606118538360443516600401611b44565b9260643516600401611b44565b923381150201946126d4565b90604051610200810160405260806118c68294604060208201602086013760a084018085526118a563ffffffff918284351684016118f5565b6118b68160608401351683016118cb565b60608601528382013516016118cb565b910152565b9060206040519263ffffffff813563ffffffe0601f82011692848401908737168452830101604052565b6118c660609161016081853763ffffffff611917816040840135168301611927565b604086015283820135160161197a565b90641fffffffe082359263ffffffff841660405194818652602093849160051b168601019283928160a0809402910185378086015b83811061196c5750505050604052565b84815293820193810161195c565b90641fffffffe082359263ffffffff841660405194818652602093849160051b168601019283928160c0809402910185378086015b8381106119bf5750505050604052565b8481529382019381016119af565b906040516102008101604052611a13819360a083018084526119f963ffffffff918284351684016118f5565b6001602085015260016040850152602082013516016118cb565b606082015260806040519160208301604052600083520152565b803591600592641fffffffe081851b16604080519060209384848401018252829663ffffffff809216845260005b858110611a6e5750505050505050909150565b8083888093850101351683018551908360a091828401895287608093848484018737820135160101908d60018884351601901b8851928184018a52833782015282828801015201611a5b565b908135641fffffffe08160051b166040805160209384848301018352819663ffffffff809216835260005b858110611af55750505050505050565b808388809385010135168301611b34838851928984016101a085018b52611b2581848b81860135168501016118f5565b8452878a8201351601016118cb565b8382015282828701015201611ae5565b90813591641fffffffe08360051b166040516020928383830101604052819563ffffffff809116835260005b848110611b7f57505050505050565b80611b9587848180958801013516860101611ba1565b82828701015201611b70565b90813591604080519363ffffffff81168552602080641fffffffe08360051b168701019381643fffffffc0869460061b16910185378086015b828110611be75750505052565b848152938301938101611bda565b90813591641fffffffe08360051b166040516020928383830101604052819563ffffffff809116835260005b848110611c3057505050505050565b80611c468784818095880101351686010161186c565b82828701015201611c21565b908135641fffffffe08160051b166040805160209384848301018352819663ffffffff809216835260005b858110611c8d5750505050505050565b808388809385010135168301611cc6838851928984018a52611cb782898184013516830101611ba1565b8452878a820135160101611ba1565b8382015282828701015201611c7d565b9060405161016081016040528092611d16610140918281853763ffffffff611d05816040840135168301611927565b60408601526060820135160161197a565b80606084015251910152565b50638ffff9806000526004601cfd5b6369f958276000526020526024601cfd5b63a61be9f06000526020526024601cfd5b50636ab37ce76000526004601cfd5b611d6b82611d99565b600080808085855af115611d7d575050565b611d85612681565b63bc806b966000526020526040526044601cfd5b15611da057565b6391b3e5146000526004601cfd5b929193949094611dbd83611d99565b611dc781836120f2565b80611ef0575050604051926000947f23b872dd00000000000000000000000000000000000000000000000000000000865280600452816024528260445260208660648180885af1803d15601f3d1160018a51141617163d1515811615611e36575b505050505050604052606052565b80863b151516611e2857908795969115611e5b5786635f15d67287526020526024601cfd5b959192939515611e80575063988919238594526020526040526060526080526084601cfd5b3d611ea3575b5063f486bc87845260205260405260605260805260a05260a4601cfd5b601f3d0160051c9060051c908060030291808211611ed7575b505060205a910110611ece5785611e86565b833d81803e3d90fd5b8080600392028380020360091c92030201018680611ebc565b906106769592949391612359565b919395909294611f0e81836120f2565b80611f375750508460016106769603611f28575b50614fab565b611f3190611d31565b38611f22565b815160649693959394929190602003611fec5760c0906001906040845260208401527f4ce34aa20000000000000000000000000000000000000000000000000000000060408401526020604484015280888401525b02019360027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc48601527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe48501526004840152602483015260448201520152565b5060c08682016001815101809152611f8c565b95909192939461200e86611d99565b61201881836120f2565b806120285750506106769461508a565b90606495969493929160208251146000146120df5760c0906001906040845260208401527f4ce34aa20000000000000000000000000000000000000000000000000000000060408401526020604484015280888401525b02019360037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc48601527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe48501526004840152602483015260448201520152565b5060c0868201600181510180915261207f565b906020820151036121005750565b610676905b90604082510361223a5760208201519160c06064820151026044019260405193602073ffffffffffffffffffffffffffffffffffffffff6000928184927f00000000000000000000000000000000000000000000000000000000000000001674ff00000000000000000000000000000000000000001783528584527f00000000000000000000000000000000000000000000000000000000000000006040526055600b2016976040528180526040860182895af190805191156122215750937f4ce34aa2000000000000000000000000000000000000000000000000000000007fffffffff0000000000000000000000000000000000000000000000000000000060209596160361221557505052565b61221e91612345565b52565b63d13d53d48691612230612681565b526020526024601cfd5b9050565b9060405190602073ffffffffffffffffffffffffffffffffffffffff6101046000938285937f00000000000000000000000000000000000000000000000000000000000000001674ff00000000000000000000000000000000000000001784528785527f00000000000000000000000000000000000000000000000000000000000000006040526055600b20169560405282805282865af1908051911561233657507fffffffff000000000000000000000000000000000000000000000000000000007f4ce34aa20000000000000000000000000000000000000000000000000000000091160361232d575050565b61067691612345565b63d13d53d49150612230612681565b631cf99b266000526020526040526044601cfd5b9060649492939160208251146000146124105760c0906001906040845260208401527f4ce34aa20000000000000000000000000000000000000000000000000000000060408401526020604484015280878401525b02019260017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc48501527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe484015260048301526024820152600060448201520152565b5060c085820160018151018091526123ae565b91909161014081018051917f0000000000000000000000000000000000000000000000000000000000000000604051604083018051928351926020809501906000915b868684106125665750505050506040519160051b8220917f00000000000000000000000000000000000000000000000000000000000000009093606086019481865101906000915b8a83106125245750505050507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08660051b604051209401978851907f00000000000000000000000000000000000000000000000000000000000000008a5282519383528451958552865261018089209852525252565b8380827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0600194510180519089815260e08120875252019201920191906124ae565b80827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0600194510180519088815260c0812087525201920192019190612466565b6000467f0000000000000000000000000000000000000000000000000000000000000000036125f557507f000000000000000000000000000000000000000000000000000000000000000090565b60405190608051907f000000000000000000000000000000000000000000000000000000000000000081527f00000000000000000000000000000000000000000000000000000000000000006020527f0000000000000000000000000000000000000000000000000000000000000000604052466060523060805260a081209260405260605260805290565b3d61268857565b601f3d0160051c60405160051c9080600302918082116126bb575b505060205a9101106126b157565b3d6000803e3d6000fd5b8080600392028380020360091c920302010138806126a3565b93959480939297956126e692866129aa565b93909187519681516127006126fb828b612e96565b613328565b9860009a8b905b8282106127cb5750506000925b8284106127575750505050509461273b949587829861274c575b5081511561273f576136dc565b9190565b61274761338b565b6136dc565b82510382523861272e565b909192939a8a6127738361276c8f8990612988565b5189613408565b61278c8180516080602082511515930151910151141690565b156127a65750506001809101945b019291909a939a612714565b86916127c5916127be85886001979b01038093612988565b528d612988565b5061279a565b90949b6127e7896127e0888598969798612988565b518961339a565b8c6128018280516080602082511515930151910151141690565b1561281d5750506001809101955b01909b949b93929193612707565b879161283a91846001959a03916128348383612988565b52612988565b5061280f565b6128486110ae565b90604051610160810181811067ffffffffffffffff8211176128c7575b604052600080825280602083015260609182604082015282808201528160808201528160a08201528160c08201528160e08201528161010082015281610120820152816101408201528452806020850152604084015280808401526080830152565b6128cf61107e565b612865565b6128dc6110fb565b600181529060203681840137565b906128fc6128f7836117ec565b61111b565b8281527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe061292a82946117ec565b0190602036910137565b600511156106b257565b507f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b60209080511561297c570190565b61298461293e565b0190565b602091815181101561299d575b60051b010190565b6129a561293e565b612995565b9391936000936129b8614f5d565b6000357c400000000000000000000000000000000000000000000000000000000016926129e3612840565b508251936129f0856128ea565b9760205b6001870160051b8110612ac6575050907c4000000000000000000000000000000000000000000000000000000001612a329214612ab9575b83612fb7565b60205b6001840160051b8110612a485750505050565b6020816001928901518015612ab357612aab90828701515186612a7f825173ffffffffffffffffffffffffffffffffffffffff1690565b8287015173ffffffffffffffffffffffffffffffffffffffff165b906060604085015194015194614232565b019050612a35565b50612aab565b612ac1612f94565b612a2c565b808601518215612c5557612ad981614668565b918d82969215612c42578501527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff019382519260a08401519360c08101519060408101519e8f519160800151612b2e81612934565b60048110600052600110179e60005b828110612bd757505050606080925101519485519560005b878110612b6e5750505050505050506020905b016129f4565b80878760a0612b7f60019587612988565b51612bb789898c6080850196612b9788518a83612f61565b9186019889519089518214600014612bc7575050508088525b8751612eef565b8094520190815190525201612b55565b612bd092612f61565b8852612bb0565b8087612be560019385612988565b519c8d600051905110179c612c28878c60808401938c6060612c0987518984612f61565b92019687519087518214600014612c32575050508086525b8551612ea3565b8092525201612b3d565b612c3b92612f61565b8652612c21565b5050935050906000602080930152612b68565b906000602080930152612b68565b939193600093612c71614f5d565b6000357c40000000000000000000000000000000000000000000000000000000001692612c9c612840565b50825193612ca9856128ea565b9760205b6001870160051b8110612d45575050907c4000000000000000000000000000000000000000000000000000000001612cea9214612ab95783612fb7565b60205b6001840160051b8110612d005750505050565b6020816001928901518015612d3f57612d3790828701515186612a7f825173ffffffffffffffffffffffffffffffffffffffff1690565b019050612ced565b50612d37565b808601518215612e7557612d5881614414565b918d82969215612e62578501527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff019382519260a08401519360c08101519060408101519e8f519160800151612dad81612934565b60048110600052600110179e60005b828110612e2657505050606080925101519485519560005b878110612ded5750505050505050506020905b01612cad565b80878760a0612dfe60019587612988565b51612e1689898c6080850196612b9788518a83612f61565b8094520190815190525201612dd4565b8087612e3460019385612988565b519c8d600051905110179c612e58878c60808401938c6060612c0987518984612f61565b8092525201612dbc565b5050935050906000602080930152612de7565b906000602080930152612de7565b8181029291811591840414171561173057565b9190820180921161173057565b929092838103612eb35750505090565b612ec983612ecf93039342039182850390612e83565b93612e83565b8201809211612ee2575b81049015150290565b612eea6116f3565b612ed9565b919092838303612eff5750505090565b600192612f1883612f1e93039342039182850390612e83565b94612e83565b8301809311612f54575b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff830104019015150290565b612f5c6116f3565b612f28565b919091828114612f8e5782818309612f8057612f7c91612e83565b0490565b63c63cf0896000526004601cfd5b50905090565b506312d3f5a36000526004601cfd5b600211156106b257565b516107ad816106a8565b815181519260005b8281106130c05750505060005b828110612fd857505050565b612fe28183612988565b5161301661300260208301516effffffffffffffffffffffffffffff1690565b6effffffffffffffffffffffffffffff1690565b156130b75751606081018051519060005b828110613089575050506040018051519060005b82811061304f575050506001905b01612fcc565b8061306f6130696130636001948651612988565b51612fad565b60031090565b61307a575b0161303b565b61308481866131ba565b613074565b8061309d6130696130636001948651612988565b6130a8575b01613027565b6130b281876131a6565b6130a2565b50600190613049565b6130ca8183612988565b516130df81518781101561317a575b86612988565b51602090613101613002838301516effffffffffffffffffffffffffffff1690565b1561316f57519060409081830151918401519263bfb3f8ce9185015161312681612fa3565b61312f81612fa3565b61315c575b50815183101561315357509161314d91600194936131d7565b01612fbf565b6000526004601cfd5b9050606091500151636088d7de38613134565b50505060019061314d565b613190602084015161318b81612fa3565b613195565b6130d9565b63133c37c66000526020526024601cfd5b63a8930e9a6000526020526040526044601cfd5b63d69293326000526020526040526044601cfd5b61221e826106a8565b906131e191612988565b518051916131ee836106a8565b600383111561324d5761322e8260046040606095019586518015156000146132345761322490878701519060808801519161326a565b14600303906131ce565b01519052565b50608085015151156132245761324861325b565b613224565b6394eb6af66000526004601cfd5b506309bde3396000526004601cfd5b916000928352602090818420918082019181815191600592831b0101905b8184106132a857505050500361329b5750565b6309bde33990526004601cfd5b8351808611821b95865294831894909452604086209392820192613288565b604051906060820182811067ffffffffffffffff82111761331b575b6040528160406132f16110ae565b91600092838152836020820152838382015283606082015283608082015281528260208201520152565b61332361107e565b6132e3565b906133356128f7836117ec565b8281527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe061336382946117ec565b019060005b82811061337457505050565b60209061337f6132c7565b82828501015201613368565b5063d5da9a1b6000526004601cfd5b929190926133a66132c7565b938051156133f557846133d89181519373ffffffffffffffffffffffffffffffffffffffff608086019616865261348a565b6060810151156133e6575050565b60006001928160208701525252565b63375c24c160005260006020526024601cfd5b929190926134146132c7565b938051156134545784613429918151936135d1565b60208401913383526040850152606081015115613444575050565b6000600192526000608082015252565b63375c24c160005260016020526024601cfd5b50637fda72796000526004601cfd5b50634e487b7160005260116020526024601cfd5b9092919260009081928290828351905b8160051b850181106134c957505050505060608293945101526134ba5750565b600114611da057610676613476565b6020909695960190602082515184518110156135c4575b60051b8401015180519060208451015160206040840151920151158251821015176135b9579060209160051b0101519660609081890151998a81019a15908b1060011b171798976000828201528b51871560011461356c57502085189060408b0151610120820151189060208c0151905118171761355f575b9061349a565b613567613467565b613559565b929061012092949750806040915185526020810151602086015201516040840152805160208d0152015160408b01522092602085018281186135af575b50613559565b82519052386135a9565b505050959495613559565b6135cc613467565b6134e0565b9092919260009081928291808051600590811b82015b8084106136035750505050505060608293945101526134ba5750565b6020979697809401938085515187518110156136cf575b841b8701015190808651015191606092828483510151920151158251821015176136c3576000918391871b010151928301998a519b8c81019c15908d1060011b17179a99528b51881560011461368357505060a0902086146135e75761367e613467565b6135e7565b8251815281830151818301526040808401519082015260808084015191015260a0909120965083018481186136b9575b506135e7565b84519052386136b3565b505050509695966135e7565b6136d7613467565b61361a565b9092938151936136eb856128ea565b956136f46111a8565b9180519060005b8281106138ca5750505060005b86811061379a57505061371a90612105565b478061378a575b50613734575b5050506107ad6001600055565b60005b8381106137445750613727565b8061375a61375460019388612988565b51151590565b613765575b01613737565b6137856137728285612988565b518561377e8482612988565b5191615aab565b61375f565b6137949033611d62565b38613721565b6137a48186612988565b516137c461300260208301516effffffffffffffffffffffffffffff1690565b156138b4576137dc6137d6838b612988565b60019052565b51604081015180519060005b82811061384c575050506060809101519081519160005b83811061381457505050506001905b01613708565b8061382160019284612988565b5160a08582019182518061383b575b5001519052016137ff565b61384690858b613944565b38613830565b8061385960019284612988565b51608060608201918251613872575b01519052016137e8565b608081018051908b90526138ab8c61389e8b5173ffffffffffffffffffffffffffffffffffffffff1690565b6101208c0151908561395b565b82820152613868565b508060006138c46001938b612988565b5261380e565b80613925866138db60019486612988565b5180519081516138ea816106a8565b6138f3816106a8565b1561392b575b604061391c602083015173ffffffffffffffffffffffffffffffffffffffff1690565b9101519161395b565b016136fb565b47606083015111156138f95761393f611d22565b6138f9565b63a5f542086000526020526040526060526064601cfd5b9291908351613969816106a8565b613972816106a8565b613a1557505050806139ba6139a1602061067694015173ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff6040830151911617613a08575b60606139ff608083015173ffffffffffffffffffffffffffffffffffffffff1690565b91015190611d62565b613a10611d53565b6139dc565b60018451613a22816106a8565b613a2b816106a8565b03613aab5792610676936040820151613a9e575b602082015173ffffffffffffffffffffffffffffffffffffffff169073ffffffffffffffffffffffffffffffffffffffff6060613a93608086015173ffffffffffffffffffffffffffffffffffffffff1690565b940151931691611dae565b613aa6611d53565b613a3f565b60028451613ab8816106a8565b613ac1816106a8565b03613b2e5783613aeb602061067696015173ffffffffffffffffffffffffffffffffffffffff1690565b608082015173ffffffffffffffffffffffffffffffffffffffff169273ffffffffffffffffffffffffffffffffffffffff60606040850151940151941691611efe565b83613b53602061067696015173ffffffffffffffffffffffffffffffffffffffff1690565b608082015173ffffffffffffffffffffffffffffffffffffffff169273ffffffffffffffffffffffffffffffffffffffff60606040850151940151941691611fff565b9193929081613ba89184519085612c63565b9190805160051b604001937fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082018051907f4b9f2d36e1b4c93de62cc077b00b1a91d84b6c31b4a14e012718dcca230689e760209788835282a152865196613c0f88613328565b9560009889915b818310613c44575050505093613c359487829798613c39575b506136dc565b5090565b825103825238613c2f565b9091929988613c6585613c57818f612988565b518581519101519089613cba565b613c7e8180516080602082511515930151910151141690565b15613c975750506001809101935b019190999299613c16565b8591613cb491613cad8560019699038093612988565b528b612988565b50613c8c565b909192613cc56132c7565b938351158015613eaf575b613ea2575b613cdd6132c7565b90613ce98282866135d1565b81519460609384870193845115613e82575092859288836107ad9996613d168360809a97613e199c61348a565b613d208351612fad565b613d29816106a8565b885190613d35826106a8565b613d3e826106a8565b60ff85519273ffffffffffffffffffffffffffffffffffffffff8c604080613d806139a160208a015173ffffffffffffffffffffffffffffffffffffffff1690565b613da46139a1602086015173ffffffffffffffffffffffffffffffffffffffff1690565b189701519101511894169218161717613e73575b50835182518601511015613e3957505090602083613ded613ddb613dfa9561296e565b5193518c518301518551910397612988565b5151015191015190612988565b5101525b015173ffffffffffffffffffffffffffffffffffffffff1690565b60808351019073ffffffffffffffffffffffffffffffffffffffff169052565b8495939492509060206040613ded85613e54613e659661296e565b519451015188518551910397612988565b510152519086510152613dfe565b613e7c90613eb8565b38613db8565b9750505050505050608060009182602085015201526107ad815160019052565b613eaa613ec9565b613cd5565b50805115613cd0565b63bced929d6000526020526024601cfd5b506398e9db6e6000526004601cfd5b613ee06110fb565b90600182528160005b60209081811015613f0b57602091613eff612840565b90828501015201613ee9565b505050565b92613faa613f7692613fe295613f4060046080835101516005811015613ff1575b613f3a81612934565b14614f6c565b613f8884613f4d83614414565b9098829a9296613f5b613ed8565b96613f658861296e565b52613f6f8761296e565b5086612fb7565b613f7f8561296e565b51519889613ffe565b613fa4613f936128d4565b9183613f9e8461296e565b5261296e565b51615aab565b815173ffffffffffffffffffffffffffffffffffffffff16602083015173ffffffffffffffffffffffffffffffffffffffff16612a9a565b613fec6001600055565b600190565b613ff9610678565b613f31565b60a08082015160c08301519796909593916140176111a8565b9689604086019384515190600095865b8c898d86841061411757505050505050505060809260048487015161404b81612934565b101661410a575b6060809501968751519760005b89811061408e575050505050505050505061407b919250612105565b47806140845750565b6106769033611d62565b806140ea8c8f8b8b8b8f936140bf908c8c6140ac60019c8e51612988565b51968701958651958801958651906141c0565b8092528b830151905281516140d3816106a8565b6140dc816106a8565b156140f0575b50339061395b565b0161405f565b47106140fd575b386140e2565b614105611d22565b6140f7565b614112612f94565b614052565b998561417e9392869798999c6141596141338860019a51612988565b51948551614140816106a8565b15179e8d60608701938451956080890196875190614189565b9052528c61012061391c825173ffffffffffffffffffffffffffffffffffffffff1690565b01908d939291614027565b90939084810361419f5750506107ad9350612f61565b93836141b46107ad97966141ba949686612f61565b93612f61565b90612ea3565b9093908481036141d65750506107ad9350612f61565b93836141b46107ad97966141eb949686612f61565b90612eef565b90815180825260208080930193019160005b828110614211575050505090565b909192938260a08261422660019489516106ba565b01950193929101614203565b929094939160409182519460809182870191875273ffffffffffffffffffffffffffffffffffffffff94856020921682890152838189015286518093528160a089019701936000915b8483106142c95750505050505082828594936142c493867f9d9af8e38d66c62e2c12f0225249fd9d721c54b83f48d9352c97c6cacdcb6f319896036060870152169716956141f1565b0390a3565b90919293949784836001928b5180516142e1816106a8565b8252808401518c168483015285810151868301526060908101519082015201990195949301919061427b565b9092916000938285526002602052604085209283549260ff8460081c166143ef576effffffffffffffffffffffffffffff8460101c166143de5760ff841615614374575b505071010000000000000000000000000000010001909255509091506106769050565b6143806128f78261115f565b9281845236828201116143da579262010001949261067697986020846143d2957fffffffffffffffffffffffffffffff0000000000000000000000000000000000988387013784010152608435615199565b918594614351565b8780fd5b5063ee9e0e6386526020526024601cfd5b50631a51557486526020526024601cfd5b90805b61440b575090565b80910680614403565b80519061442d61099960a084015160c085015190615184565b61465b576effffffffffffffffffffffffffffff92602092848484015116938560408501511693608083016004815161446581612934565b61446e81612934565b146146285786158688111761461b575b519161448983612934565b6001809316158688101661460e575b6144a184614762565b976144b6896000526002602052604060002090565b946144c4610999878c6158f0565b6145ff578554938a60ff8616156145cb575b5050508260881c848115906144f8575b505050508460881b9060101b17179055565b98979893909192936145bb5760101c82168885146145a757818914614589578882910297029702958701968688118789030280910397039181871182841117614543575b80806144e6565b9095919661455a614554848a614400565b82614400565b80150180809204980492049580871190831117614577578061453c565b601190634e487b71600052526024601cfd5b925050508495940194848611858703028091039503388080806144e6565b9397509550505083039383388080806144e6565b50505050839493388080806144e6565b60606145ee6145f7945173ffffffffffffffffffffffffffffffffffffffff1690565b92015191615199565b38808a6144d6565b50600097508796505050505050565b6146166147ce565b614498565b6146236147bf565b61447e565b50919360809396506001915061464795021861464e575b0151906147dd565b9192909190565b6146566147bf565b61463f565b5050600090600090600090565b80519061468561099960a084015160c08501514210904210151690565b61465b576effffffffffffffffffffffffffffff9260209284848401511693856040850151169360808301600481516146bd81612934565b6146c681612934565b1461473657861586881117614729575b51916146e183612934565b6001809316158688101661471c575b6146f984614762565b9761470e896000526002602052604060002090565b946144c4610999878c615953565b6147246147ce565b6146f0565b6147316147bf565b6146d6565b509193608093965060019150614647950218614755575b01519061499c565b61475d6147bf565b61474d565b6060810151516101408201511161153d57806147b973ffffffffffffffffffffffffffffffffffffffff6107ad93511673ffffffffffffffffffffffffffffffffffffffff16600052600160205260406000205490565b90612423565b50635a052b326000526004601cfd5b5063a11b63ff6000526004601cfd5b60609060408282018051516101408401510361498f575b60008061481f614818865173ffffffffffffffffffffffffffffffffffffffff1690565b9786614b6b565b9082895af19361484f8673ffffffffffffffffffffffffffffffffffffffff166000526003602052604060002090565b958654906001978883019055821b189415614981575b61486d615dcd565b9490919586614973575b0180515182518111614965575b6000905b8981831061492f575050505281519083519180518311614921575b91906000925b888385106148ce575050505050526148c057918190565b6148c981614c57565b918190565b90919293966148dd8884612988565b516149156148eb8a8a612988565b518681015187840151106148ff8285614c77565b179260a080910151910151908091149015171590565b171796019291906148a9565b61492a87614c57565b6148a3565b90919761493d898551612988565b5161495b61494b8b88612988565b5188830151898201511092614c77565b1717970190614888565b61496e88614c57565b614884565b61497c88614c57565b614877565b61498a85614c57565b614865565b614997614c68565b6147f4565b60609081810180515161014083015103614b03575b6149d96149d2835173ffffffffffffffffffffffffffffffffffffffff1690565b9483614b6b565b9060008092819282895af193614a0f8673ffffffffffffffffffffffffffffffffffffffff166000526003602052604060002090565b958654906001978883019055821b189415614af9579060409291614a31615dcd565b9590919687614aeb575b0180515182518111614add575b84905b8a818310614ab75750505052825184519281518411614aa9575b9291905b88838510614a80575050505050526148c057918190565b9091929396614a8f8884612988565b51614a9d6148eb8a8a612988565b17179601929190614a69565b614ab288614c57565b614a65565b909198614ac58a8551612988565b51614ad361494b8c88612988565b1717980190614a4b565b614ae689614c57565b614a48565b614af489614c57565b614a3b565b5093505050918190565b614b0b614c68565b6149b1565b91909160408051936020928360e083028701018352818652839160010160051b92838701915b848410614b4557505050505050565b60c060a0879285878c01528460808083893e606083019088013e01930193019291614b36565b9190608490614bd2604051916398919765835260a0601c84019633602086015260806040860152614bbe6060614ba8604084015185890190614bfc565b9283608001828901520151838388010190614bfc565b018094608082016080820152010190614bd7565b010190565b8051603f0163ffffffe0169291610676918491905b829060045afa153d15176101c357565b9081519081815260209283808083019301918460051b0101915b84838210614c29575050505060071b0190565b8160809251805185528281015183860152604080820151908601526060809101519085015201910190614c16565b63939792856000526020526024601cfd5b50632165628a6000526004601cfd5b90815191604081015180156003851116614cb4575b6020809160608401516080850151149060408601511416948451149301519101511416161590565b506040820151600490931460030392614c8c565b9190811015614d09575b60051b810135907ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffea1813603018212156101c3570190565b614d1161293e565b614cd2565b3560058110156101c35790565b5063fed398fc6000526004601cfd5b90815180825260208080930193019160005b828110614d52575050505090565b909192938260a060019287518051614d69816106a8565b82528084015173ffffffffffffffffffffffffffffffffffffffff168483015260408082015190830152606080820151908301526080908101519082015201950193929101614d44565b90815180825260208080930193019160005b828110614dd3575050505090565b909192938260c060019287518051614dea816106a8565b82528084015173ffffffffffffffffffffffffffffffffffffffff9081168584015260408083015190840152606080830151908401526080808301519084015260a091820151169082015201950193929101614dc5565b906005821015614e4e5752565b61221e610678565b90815260406020820152614e8360408201835173ffffffffffffffffffffffffffffffffffffffff169052565b602082015173ffffffffffffffffffffffffffffffffffffffff1660608201526101806040830151614efa614ec6610160928360808701526101a0860190614d32565b60608601517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08683030160a0870152614db3565b93614f0d608082015160c0860190614e41565b60a081015160e085015260c081015191610100928386015260e082015192610120938487015282015192610140938487015282015190850152015191015290565b614f56614f7c565b6002600055565b614f65614f7c565b6003600055565b614f74614f7c565b600201600055565b600160005403614f8857565b637fa8a9876000526004601cfd5b600360005403614fa257565b61067634611d42565b929091833b1561507857604051926000947f23b872dd000000000000000000000000000000000000000000000000000000008652816004528260245283604452858060648180855af1156150055750505050604052606052565b85853d61502c575b5063f486bc879052602052604052606052608052600160a05260a4601cfd5b601f3d0160051c9060051c90806003029180821161505f575b505060205a910110615057578561500d565b3d81803e3d90fd5b8080600392028380020360091c92030201018680615045565b83635f15d6726000526020526024601cfd5b9392919091843b1561517257604051936080519160a0519360c051956000987ff242432a000000000000000000000000000000000000000000000000000000008a528160045282602452836044528460645260a06084528960a452898060c48180855af11561510957505050505060805260a05260c052604052606052565b89893d61512e575b5063f486bc87905260205260405260605260805260a05260a4601cfd5b601f3d0160051c9060051c908060030291808211615159575b505060205a9101106150575786615111565b8080600392028380020360091c92030201018780615147565b84635f15d6726000526020526024601cfd5b9190428111428411151692831561154b575050565b92919033841461531a576151ab6125a7565b936151e882867f19010000000000000000000000000000000000000000000000000000000000006000526002526022526042600020906000602252565b908351926002601f601d860116106102e27fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9d8601101660001461530c5760018085169081604103927fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbf600593880101831c93808952880160209384820151928560238560e81c94019460e31c1690815285845191185283925b8684106152ec575050505050966152e69161067697986152a5604060002092615514565b600052526040600020907f19010000000000000000000000000000000000000000000000000000000000006000526002526022526042600020906000602252565b90615320565b85859101938684821c841b16604060002081528786519118520192615281565b506106769495508190615320565b50509050565b909291926000948580528051957fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0820180519188604103908091600181119687156154aa575b50505085148515151697881561539c575b50505050505050501561538657565b61538e612681565b634f7fb80d6000526004601cfd5b909192939495809798508452604082527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbc8401938451957fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08201976020600060648b519c7f1626ba7e000000000000000000000000000000000000000000000000000000009e8f8c528d520189845afa9a8b615448575b50505050505252523880808080808080615377565b600051036154565780615433565b3b61538e5761549c57606001906041640101000000835160001a1a159114166154875763815e1d646000526004601cfd5b631f003d0a6000525160001a6020526024601cfd5b638baa579f6000526004601cfd5b9091925060408601908151926060880151851a906154e2575b8752845260208360808660015afa508484528a86525251388080615366565b50601b8360ff1c017f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff841683526154c3565b600981106157ac576011811061566857601581106155ca576017811061557f5760177f403be09941a31d05cfc2f896505811353d45d38743288b016630cce39435476a9114027f1d51df90cba8de7637ca3e8fe1e3511d1dc2f23487d05dbdecb781860c21ac1c1890565b60157fbb40bf8cea3a5a716e2b6eb08bbdac8ec159f82f380783db3c56904f15a43d049114027f3bd8cff538aba49a9c374c806d277181e9651624b3e31111bc0624574f8bca1d1890565b6013811061561d5760137f54b3212a178782f104e0d514b41a9a5c4ca9c980bf6597c3cecbf280917e202a9114027f5a4f867d3d458dabecad65f6201ceeaba0096df2d0c491cc32e6ea4e643500171890565b60117f2d7a3ed6dab270fdb8e054b2ad525f0ce2a8b89cc76c17f0965434740f673a559114027fc3939feff011e53ab8c35ca3370aad54c5df1fc2938cd62543174fa6e7d858771890565b600d811061570e57600f81106156c357600f7fcc4886e37eedd9aacd6c1c2c9247197a621a71282e87a7cbc673f3736d9aa1419114027f1da3eed3ecef6ebaa6e5023c057ec2c75150693fd0dac5c90f4a142f9879fde81890565b600d7f8df51df98847160517f5b1186b4bc3f418d98b8a7f17f1292f392d79d600d79e9114027f6b5b04cbae4fcb1a9d78e7b2dfc51a36933d023cf6e347e03d517b472a8525901890565b600b811061576157600b7f32f4e7485d6485f9f6c255929b9905c62ba919758bbe231f231eaeecf33d810c9114027fbb98d87cc12922b83759626c5f07d72266da9702d19ffad6a514c73a89002f5f1890565b60097f6f0ec38c21f6f583ab7f3c5413c773ffd5344c34fde1d390958e438bf667448f9114027fd1d97d1ef5eaa37a4ee5fbf234e6f6d64eb511eb562221cd7edfbdde0848da051890565b6005811061585257600781106158075760077fb58d772fb09b426b9dece637f61ca9065f2b994f1464b51e9207f55f7c8f59489114027f7ff98d9d4e55d876c5cfac10b43c04039522f3ddfb0ea9bfe70c68cfb5c7cc141890565b60057f25d02425402d882d211a7ab774c0ed6eca048c4d03d9af40132475744753b2a39114027f1c19f71958cdd8f081b4c31f7caf5c010b29d12950be2fa1c95070dc47e30b551890565b600381106158a55760037ff3e8417a785f980bdaf134fa0274a6bf891eeb8195cd94b09d2aa651046e28bc9114027fa02eb7ff164c884e5e2c336dc85f81c6a93329d8e9adf214b32729b894de2af11890565b60017f832c58a5b611aadcfa6a082ac9d04bace53d8278387f10040347b7e98eb5b3029114027fbf8e29b89f29ed9b529c154a63038ffca562f8d7cd1e2545dda53a1b582dde301890565b905460ff8160081c16615941576effffffffffffffffffffffffffffff8160101c169081615921575b505050600190565b60881c1115615932575b8080615919565b61593b906159bb565b3861592b565b50631a5155746000526020526024601cfd5b906000905460ff8160081c166159b2576effffffffffffffffffffffffffffff8160101c169081615988575b50505050600190565b60881c111561599857808061597f565b6159a3575b50600090565b6159ac906159bb565b3861599d565b50905050600090565b6310fda3e16000526020526024601cfd5b9190608082019081356159de8161064b565b33141590600460018211911016166159f557505050565b61067692615a236139a16060604051956317b1f94287526020808801528460408801523382880152016111bf565b6080840152606061014461012085013761014060a08401526101e060c0840152615aa6601c61032461026435615a6f60a08202918261016001906101808a019060051b61020001614bec565b6102a0810160e08801528461032082890160006102e08201526102c084016101008b015260016103008201520152019401926111bf565b615d11565b919082519060808201918251926005841015615b66575b615af3602083019473ffffffffffffffffffffffffffffffffffffffff865116331415906004600182119110161690565b15615b1b575090615b0d9160806106769601519085615bf7565b91519263fb5014fc93615d79565b60049194935051615b2b81612934565b615b3481612934565b03615b605761067693615b549184519460808660601b9301519085615b73565b91639397928593615d79565b50505050565b615b6e610678565b615ac2565b9493919260c060a494615be3614bd2946040519663f4dd92ce8852601c88019a1860a088015260a06020880152615bcd6060615bb66040840151878b0190614bfc565b928360a00160408b0152015185838a010190615cc9565b019160a083016060880152838388010190614bd7565b01809460a082016080820152010190615cad565b9392614bd2906101649392604051936317b1f9428552601c85019760208087015260408601523360608601528151608086015260a082015161012086015260c082015190610140918287015260e08301516101608701528160a0870152615c9d604084015193615c886060615c7261018097888c0190614bfc565b9283870160c08c0152015186838b010190615cc9565b019183830160e0890152848389010190614bd7565b0194859182016101008201520101905b612984602092839283815180845260051b948593019101614bec565b8051908183526020928380808401938560051b01019101915b818110615cf35750505060a0020190565b60a090818481835160045afa153d15176101c3578501920191615ce2565b6020909391937fffffffff00000000000000000000000000000000000000000000000000000000845116926000948580938180525af1908251149015615d6a5715615d5a575050565b63fb5014fc90526020526024601cfd5b5063fb5014fc90612230612681565b602090949391947fffffffff00000000000000000000000000000000000000000000000000000000845116926000948580938180525af1908251149015615dc4571561223057505050565b50612230612681565b60009081906080803d109060009081908280918515615e70575b8515615df8575b5050505050929190565b91939750919550602094939480920196604051918360c08302840101604052818352839160010160051b98898401905b8a8410615e4d5750505050615e4293949596509501614b10565b913880808080615dee565b60a083879284878901528181863e60608501518286015201920193019290615e28565b9450909150604081803e5190602051913d81113d8411179485615de75794508093506020915060003e60005191602082813e602051903d8260a0028560071b0186011161ffff83861711179460008052615de7565b908135641fffffffe08160051b169060405191602091828285010160405263ffffffff809116845260005b828110615f005750929450505050565b80615f1685848180958c010135168a01016119cd565b82828801015201615ef056fea164736f6c6343000811000a00000000000000000000000000000000f9490004c11cef243f5400493c00ad630000000000000000000000000000000000000000
+cast send --rpc-url ${RPC_URL} --private-key ${PK} 0x0000000000ffe8b47b3e2130213b802212439497 0x64e030870000000000000000000000000000000000000000d738b7f0bb99901b1c83f2490000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000652f61020060405234620000f7576200001f6200001962000171565b620001ae565b604051615dad908162000762823960805181613c90015260a05181613cb4015260c05181613c6d015260e051818181611252015261200f0152610100518181816112a00152611eba01526101205181818161130b015261208401526101405181613c1d01526101605181613c43015261018051818181610f1601528181612495015261429501526101a0518181816124d301526142d301526101c0518181816104cd01528181611de7015281816127170152818161275c015281816130a401528181613101015261315e01526101e051816104ff0152f35b5f80fd5b634e487b7160e01b5f52604160045260245ffd5b604081019081106001600160401b038211176200012b57604052565b620000fb565b60a081019081106001600160401b038211176200012b57604052565b601f909101601f19168101906001600160401b038211908210176200012b57604052565b6200650f602081380391826040519384926200018e82856200014d565b833981010312620000f757516001600160a01b0381168103620000f75790565b620001b86200063c565b610120526101005260e05260c05260a05260805246610140526200020560c0519060805160a051604051935f5281602052604052466060523060805260a05f20926040525f606052608052565b610160526001600160a01b0390811661018081905260408051630a96ad3960e01b815291829060049082905afa908115620002ca575f9162000293575b506101a05262000251620002f2565b908116156200028157620002658162000308565b90816101c0526101e052156200027757565b600163929eee1455565b604051632aea588760e01b8152600490fd5b620002ba915060403d604011620002c2575b620002b181836200014d565b810190620002d0565b505f62000242565b503d620002a5565b620002e7565b9190826040910312620000f7576020825192015190565b6040513d5f823e3d90fd5b696002601e613d5c3d52f35f52600a60165ff090565b5f80808093600a5a04fa3d156200034f573d6001600160401b0381116200012b576040519062000343601f8201601f1916602001836200014d565b81525f60203d92013e90565b90565b6040519060c082016001600160401b038111838210176200012b576040526084825263656e742960e01b60a0837f436f6e73696465726174696f6e4974656d2875696e7438206974656d5479706560208201527f2c6164647265737320746f6b656e2c75696e74323536206964656e746966696560408201527f724f7243726974657269612c75696e74323536207374617274416d6f756e742c60608201527f75696e7432353620656e64416d6f756e742c616464726573732072656369706960808201520152565b6040519061010082016001600160401b038111838210176200012b5760405260d482527f4b65792c75696e7432353620636f756e7465722900000000000000000000000060e0837f4f72646572436f6d706f6e656e74732861646472657373206f6666657265722c60208201527f61646472657373207a6f6e652c4f666665724974656d5b5d206f666665722c4360408201527f6f6e73696465726174696f6e4974656d5b5d20636f6e73696465726174696f6e60608201527f2c75696e7438206f72646572547970652c75696e74323536207374617274546960808201527f6d652c75696e7432353620656e6454696d652c62797465733332207a6f6e654860a08201527f6173682c75696e743235362073616c742c6279746573333220636f6e6475697460c08201520152565b60405190608082016001600160401b038111838210176200012b576040526052825271766572696679696e67436f6e74726163742960701b6060837f454950373132446f6d61696e28737472696e67206e616d652c737472696e672060208201527f76657273696f6e2c75696e7432353620636861696e49642c616464726573732060408201520152565b908151915f5b838110620005ec575050015f815290565b8060208092840101518185015201620005db565b6200062b620006249493620006246200063a946040519788956020870190620005d5565b90620005d5565b03601f1981018452836200014d565b565b6040516200064a816200010f565b60078152600760208092016614d9585c1bdc9d60ca1b8152209160038260405162000675816200010f565b828152016218971b60e91b81522091604051620006928162000131565b606a8152818101927f4f666665724974656d2875696e7438206974656d547970652c6164647265737384527f20746f6b656e2c75696e74323536206964656e7469666965724f72437269746560408301527f7269612c75696e74323536207374617274416d6f756e742c75696e7432353620606083015269656e64416d6f756e742960b01b60808301526200072662000352565b9262000759620007356200041b565b93620007406200054a565b8381519101209681519020958051848201209562000600565b80519101209056fe60806040526004361015610022575b3615610018575f80fd5b610020611de5565b005b5f3560e01c80156100ec57806306fdde031461013757806346423aa7146101325780635b34b9661461012d5780637423eb3c1461012857806379df72bd1461012357806387201b411461011e5780638814773214610119578063a817440414610114578063a900866b1461010f578063b3a34c4c1461010a578063e7acab2414610105578063ed98a57414610100578063f07ec373146100fb578063f2d12b12146100f6578063f47b7740146100f1578063fb0f3ee1146100ec5763fd9f1e100361000e57610f46565b610191565b610ec2565b610ded565b610d89565b610cc6565b610c0a565b610b8b565b610b24565b610a72565b6108e5565b6107d6565b6105b2565b610493565b6103f0565b610372565b61032e565b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc9060208282011261018d576004359167ffffffffffffffff831161018d57826102409203011261018d5760040190565b5f80fd5b61019a3661013c565b5061012435600381169060021c60018111913415830361032857600382117f0203020301010000000000000000000000000000000000000000000000000000831a61020f8160a0840260240135877d010102030000000000000000000000000000000000000000000000000000881a87611e80565b9490928060051b6101c4013596610225816106b9565b61027557505060443560243517610268576102509461024391612584565b61024b612649565b6126c5565b610258612715565b60405160018152602090f35b0390f35b636ab37ce75f526004601cfd5b61024b925061025096916102bd9161028b611201565b93848361029882956106b9565b600281036102c257506102b8916101043560e4353360843560c4356122a2565b6123b1565b61245b565b6102cb816106b9565b600381036102eb57506102b8916101043560e4353360843560c4356121af565b806102f76004926106b9565b03610312576102b891606435604435608435336024356122a2565b6102b891606435604435608435336024356121af565b34611e70565b3461018d575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261018d57602080526707536561706f727460475260606020f35b3461018d5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261018d576004355f526001602052608060405f20546040519060ff81161515825260ff8160081c16151560208301526effffffffffffffffffffffffffffff8160101c16604083015260881c6060820152f35b3461018d575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261018d5761042661275a565b335f525f602052602060405f2080547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff43014060801c018091556040518181527f721c20121297512b72821b97f5326877ea8ecf4bb9948fea5bfcb6453074d37f833392a2604051908152f35b3461018d575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261018d5763929eee1460018154147f00000000000000000000000000000000000000000000000000000000000000009081156105a9575b5061057f575f8080807f0000000000000000000000000000000000000000000000000000000000000000600a5a04fa3d1561057a573d61053b610536826111c7565b611148565b9081525f60203d92013e5b15610550575f9055005b60046040517f70a4078f000000000000000000000000000000000000000000000000000000008152fd5b610546565b60046040517ff45b98b0000000000000000000000000000000000000000000000000000000008152fd5b9050155f6104f4565b3461018d577ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc60208136011261018d576004359067ffffffffffffffff821161018d5761016090823603011261018d5761062663ffffffff6020921661014461061d82600401615c33565b91013590611245565b604051908152f35b9181601f8401121561018d5782359167ffffffffffffffff831161018d576020808501948460051b01011161018d57565b73ffffffffffffffffffffffffffffffffffffffff81160361018d57565b60a4359061068a8261065f565b565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52602160045260245ffd5b600611156106c357565b61068c565b60809080516106d6816106b9565b83528160208201519173ffffffffffffffffffffffffffffffffffffffff80931660208601526040810151604086015260608101516060860152015116910152565b9081518082526020808093019301915f5b828110610737575050505090565b909192938260e0600192604088516107508382516106c8565b8085015173ffffffffffffffffffffffffffffffffffffffff1660a0840152015160c082015201950193929101610729565b909291604082019160408152845180935260608101926020809601905f5b8181106107c0575050506107bd9394506020818403910152610718565b90565b82511515865294870194918701916001016107a0565b60e07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261018d5767ffffffffffffffff60043581811161018d5761082190369060040161062e565b505060243581811161018d5761083b90369060040161062e565b505060443581811161018d5761085590369060040161062e565b505060643590811161018d5761086f90369060040161062e565b505061088861087c61067d565b60c4359060843561105c565b9061026460405192839283610782565b60207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc82011261018d576004359067ffffffffffffffff821161018d576108e19160040161062e565b9091565b3461018d576108f336610898565b5050600461090b63ffffffff600435166004016115e1565b9061091461275a565b8151905f92361515935b8381106109315760405160018152602090f35b61093b81836116ac565b519081519184608084015161094f816116c0565b610958816116c0565b14610a5757825173ffffffffffffffffffffffffffffffffffffffff169261097f81612dad565b610991815f52600160205260405f2090565b9461099d8a8784612e07565b506109b06109ac875460ff1690565b1590565b6109c4575b50505050600191505b0161091e565b60608301515161014084015103610a5257600195610a0c610a37928460207ff280791efe782edcf06ce15c8f4dff17601db3b88eb3805a0db7d77faf757f0498015191612ec8565b60017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00825416179055565b610a46604051928392836117f1565b0390a15f8080806109b5565b612ebb565b50600191506109be565b9060206107bd928181520190610718565b60407ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261018d5760043567ffffffffffffffff80821161018d57610abc368360040161062e565b505060243590811161018d5761026491610b1091610add368260040161062e565b5050610b08610af563ffffffff8094166004016118e9565b92610afe6111a4565b9216600401611948565b9033926119ce565b604051918291602083526020830190610718565b3461018d5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261018d5773ffffffffffffffffffffffffffffffffffffffff600435610b748161065f565b165f526002602052602060405f2054604051908152f35b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc60408136011261018d576004359067ffffffffffffffff821161018d57604090823603011261018d57610c00610bec63ffffffff60209316600401611aa3565b610bf46111a4565b90339160243591611bf5565b6040519015158152f35b7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc60808136011261018d576004359067ffffffffffffffff9081831161018d5760a090833603011261018d5760243590811161018d5761026491610cb491610c75368260040161062e565b5050610ca460643592610c878461065f565b610c9a63ffffffff809216600401611d2f565b9216600401611426565b9133811502019160443591611bf5565b60405190151581529081906020820190565b60a07ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261018d57600467ffffffffffffffff813581811161018d57610d103682850161062e565b50506024359082821161018d57610d293683860161062e565b505060443592831161018d57610d7a61088894610d483686830161062e565b5050610d5c63ffffffff80941682016118e9565b92610d7281610d696111a4565b961683016114b5565b9516016114b5565b60843593339360643593611514565b3461018d5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261018d576020610626600435610dc98161065f565b73ffffffffffffffffffffffffffffffffffffffff165f525f60205260405f205490565b60807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261018d5767ffffffffffffffff6004803582811161018d57610e373682840161062e565b50506024359083821161018d57610e503683850161062e565b505060443593841161018d5761026493610eaa610eb694610e733684830161062e565b5050610e99610ea260643595610e888761065f565b63ffffffff928380921685016113c7565b97168301611426565b931601611948565b913381150201926119ce565b60405191829182610a61565b3461018d575f7ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261018d57610ef8613c1a565b60605f5260205273ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000166040526303312e3660635260a05ff35b3461018d57610f5436610898565b90610f5d61275a565b5f915f5b818110610f7e5783610f795760405160018152602090f35b613cf0565b80610f8c6001928486611d8e565b94610f9686611dce565b907f6bacc01dbe442496068f7d234edd811f1a5f833243e0aec824f86ab861f3c90d610fef610fc760208a01611dce565b92610fd460808b01611dd8565b60048533148733141715911417179861014061061d82615c33565b91611031611005845f52600160205260405f2090565b80547fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000016610100179055565b60405192835273ffffffffffffffffffffffffffffffffffffffff908116931691602090a301610f61565b906108e1929163ffffffff9161107883600435166004016113c7565b926110898160243516600401611426565b6110a961109c83604435166004016114b5565b92606435166004016114b5565b92338115020194611514565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52604160045260245ffd5b6040519060a0820182811067ffffffffffffffff82111761110257604052565b6110b5565b60405190610160820182811067ffffffffffffffff82111761110257604052565b604051906040820182811067ffffffffffffffff82111761110257604052565b907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f604051930116820182811067ffffffffffffffff82111761110257604052565b67ffffffffffffffff81116111025760051b60200190565b6040516020810181811067ffffffffffffffff821117611102576040525f815290565b67ffffffffffffffff811161110257601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01660200190565b611209611128565b90602082526020828136910137565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52601160045260245ffd5b91909161014081018051917f0000000000000000000000000000000000000000000000000000000000000000604051604083018051928351926020809501905f915b868684106113865750505050506040519160051b8220917f00000000000000000000000000000000000000000000000000000000000000009093606086019481865101905f915b8a83106113445750505050507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08660051b604051209401978851907f00000000000000000000000000000000000000000000000000000000000000008a5282519383528451958552865261018089209852525252565b8380827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0600194510180519089815260e08120875252019201920191906112ce565b80827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0600194510180519088815260c0812087525201920192019190611287565b9081359163ffffffff90641fffffffe08460051b1690604051906020936020848401016040528083971683525f5b84811061140457505050505050565b8061141a87848180958801013516860101611d2f565b828287010152016113f5565b9081359063ffffffff92600593641fffffffe08460051b16906040805191602094858585010183528184981684525f5b8581106114695750505050505050909150565b8083888093850101351683018551908360a091828401895287608093848484018737820135160101908d60018884351601901b8851928184018a52833782015282828801015201611456565b9081359163ffffffff90641fffffffe08460051b1690604051906020936020848401016040528083971683525f5b8481106114f257505050505050565b8061150887848180958801013516860101612879565b828287010152016114e3565b96948093949296611528923615908a6128d4565b93909186519082519261154361153e8585612cee565b612d4b565b98865f5b8b8d8783106115ab5750505050505f5b8481106115735750505050508461156f9495966147a8565b9190565b806115a48b611590868f611589600197896116ac565b5190614665565b61159d88850180936116ac565b528c6116ac565b5001611557565b826115c76001956115cd936115c0848a6116ac565b519061461f565b926116ac565b526115d8818d6116ac565b50018790611547565b9081359163ffffffff641fffffffe08460051b1690604090815190602094858584010184528183981683525f5b85811061161e5750505050505050565b80838880938501013516830161165d838851928984016101a085018b5261164e81848b8186013516850101613046565b8452878a820135160101613078565b838201528282870101520161160e565b7f4e487b71000000000000000000000000000000000000000000000000000000005f52603260045260245ffd5b8051156116a75760200190565b61166d565b80518210156116a75760209160051b010190565b600511156106c357565b5160058110156106c35790565b9081518082526020808093019301915f5b8281106116f6575050505090565b909192938260a06001928751805161170d816106b9565b82528084015173ffffffffffffffffffffffffffffffffffffffff1684830152604080820151908301526060808201519083015260809081015190820152019501939291016116e8565b9081518082526020808093019301915f5b828110611776575050505090565b909192938260c06001928751805161178d816106b9565b82528084015173ffffffffffffffffffffffffffffffffffffffff9081168584015260408083015190840152606080830151908401526080808301519084015260a091820151169082015201950193929101611768565b9060058210156106c35752565b9081526040602082015261181e60408201835173ffffffffffffffffffffffffffffffffffffffff169052565b602082015173ffffffffffffffffffffffffffffffffffffffff1660608201526101806040830151611895611861610160928360808701526101a08601906116d7565b60608601517fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc08683030160a0870152611757565b936118a8608082015160c08601906117e4565b60a081015160e085015260c081015191610100928386015260e082015192610120938487015282015192610140938487015282015190850152015191015290565b9081359163ffffffff90641fffffffe08460051b1690604051906020936020848401016040528083971683525f5b84811061192657505050505050565b8061193c87848180958801013516860101611aa3565b82828701015201611917565b9081359163ffffffff641fffffffe08460051b1690604090815190602094858584010184528183981683525f5b8581106119855750505050505050565b8083888093850101351683016119be838851928984018a526119af82898184013516830101612879565b8452878a820135160101612879565b8382015282828701015201611975565b939290816119e39186519036151590886128d4565b9190805160051b6040017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe082018051907f4b9f2d36e1b4c93de62cc077b00b1a91d84b6c31b4a14e012718dcca230689e76020936020835282a152845190611a4a82612d4b565b955f5b838110611a68575050505083611a649495966147a8565b5090565b80611a87818c611a7a600195876116ac565b5187815191015191614bed565b611a91828b6116ac565b52611a9c818a6116ac565b5001611a4d565b906040516102008101604052611ae9819360a08301808452611acf63ffffffff91828435168401613046565b600160208501526001604085015260208201351601613078565b6060820152608060405191602083016040525f83520152565b611b0a611128565b9060018252815f5b60209081811015611b9557602091611b286110e2565b90611b31611107565b5f81525f828201526060905f60408381840152838084015260809282848201528260a08201528260c08201528260e0820152826101008201528261012082015282610140820152865281858701528501528180850152830152828501015201611b12565b505050565b611ba2611128565b600181529060203681840137565b90611bbd6105368361118c565b8281527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0611beb829461118c565b0190602036910137565b909192611cfd93825192608084015191611c0e836116c0565b611c17836116c0565b60048314611c248161315c565b36151590611c5d611c3583866131d2565b93919290929a611c43611b02565b88611c4d8261169a565b52611c578161169a565b506133d1565b611c698884848c61353b565b611c7a611c74611b9a565b976116c0565b611d0a578593611ca08694611ca8948a94611c9a8e611cb89c819c6136db565b8961383b565b505b88613944565b82611cb28361169a565b52613a36565b815173ffffffffffffffffffffffffffffffffffffffff165b602083015173ffffffffffffffffffffffffffffffffffffffff16906060604085015194015194613b3b565b611d05612715565b600190565b505084965091611ca8611d27611cb895939460808401518961361c565b978894611ca2565b9060405161020081016040526080611d898294604060208201602086013760a08401808552611d6863ffffffff91828435168401613046565b611d79816060840135168301613078565b6060860152838201351601613078565b910152565b91908110156116a75760051b810135907ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffea18136030182121561018d570190565b356107bd8161065f565b35600581101561018d5790565b7f000000000000000000000000000000000000000000000000000000000000000080611e51575b15611e1357565b63929eee14805480159182611e42575b5060031415901516611e3157565b63a61be9f05f52346020526024601cfd5b6002905c03611e31575f611e23565b600263929eee145c0315611e0c5763a61be9f05f52346020526024601cfd5b63a61be9f05f526020526024601cfd5b93929190611e8c6130a2565b611e94613cfd565b6101643561014435428211154282111761219c57505061020435610264351061218f57927f00000000000000000000000000000000000000000000000000000000000000006080528360a0526060602460c037604060646101203760e0608090812061016052600161026435016102043560051b6102a08101919091526102c081019586526024906102e00137610160938260a0528360c0525f60e0525f915f5b8261020435821015611f925790604060019261010060a060208560061b99818b610284018537858b61028401610120376102a48b0135179c019760e0608020895201978989528a60c0840152610284019101370195929195611f35565b509550969590916001610204350160051b610160206060525b8261026435871015611fea5790604060a060019301948686528760c08201526101008960061b610284019101376102a48760061b013517950194611fab565b5092509593505073ffffffffffffffffffffffffffffffffffffffff915011612182577f00000000000000000000000000000000000000000000000000000000000000006080528060a052606060c460c03760206101046101203760c06080205f5260205f2060e0526103c0608435916120818373ffffffffffffffffffffffffffffffffffffffff165f525f60205260405f2090565b547f00000000000000000000000000000000000000000000000000000000000000006080526040608460a03760605161010052856101205260a0610144610140376101e090815261018060808181206102043560051b928301818152336101a08501526101c084019290925261012083850152600161020084015261022083019490945292949060609060c49061024001377f9d9af8e38d66c62e2c12f0225249fd9d721c54b83f48d9352c97c6cacdcb6f3160a06102643502938460a435940190a35f6060526102043560051b010160405261156f61216a61216383613d53565b9483613d9e565b93710100000000000000000000000000000100019055565b6339f3e3fd5f526004601cfd5b63466aa6165f526004601cfd5b6321ccfeb75f526020526040526044601cfd5b9590919293946121be86613e6f565b6121c88183613e83565b806121d857505061068a94613f63565b90606495969493929160208251145f1461228f5760c0906001906040845260208401527f4ce34aa2000000000000000000000000000000000000000000000000000000006040840152602060448401526001888401525b02019360037fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc48601527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe48501526004840152602483015260448201520152565b5060c0868201600181510180915261222f565b919396959092946122b38183613e83565b806122d3575050600186036122cd5761068a949550614071565b85614061565b81519697966064969395939492919060200361238c5760c0906001906040845260208401527f4ce34aa2000000000000000000000000000000000000000000000000000000006040840152602060448401526001888401525b02019360027fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc48601527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe48501526004840152602483015260448201520152565b5060c0868201600181510180915261232c565b919082039182116123ac57565b611218565b919082156124485760843592610104353360c43560e4355b612443578360051b6101e40335936102643560061b905f5b8281106123f6575050509561068a9596614133565b87876102848301358c85612422575b9184939161241c936102a46040970135908a614133565b016123e1565b989181612436604096959361241c9561239f565b9a91935091939450612405565b610268565b33926064356084356024356044356123c9565b604081510361258157602081015160c06064830151026044019060205f73ffffffffffffffffffffffffffffffffffffffff9360405194807f00000000000000000000000000000000000000000000000000000000000000001674ff00000000000000000000000000000000000000001783528484527f00000000000000000000000000000000000000000000000000000000000000006040526055600b2016946040528180526040860182865af15f519015612568577fffffffff000000000000000000000000000000000000000000000000000000007f4ce34aa20000000000000000000000000000000000000000000000000000000091160361256357505060209052565b61543d565b82612571614f3d565b63d13d53d45f526020526024601cfd5b50565b60c43592916101043560e43560843583156126005761068a95966125a784613e6f565b604051957f4ce34aa200000000000000000000000000000000000000000000000000000000875260206004880152600160248801526044870152606486015260848501523360a485015260c484015260e4830152614272565b9195925092806126116002926106b9565b03612631576001850361262b5761068a9394503391614071565b84614061565b9084929161264261068a9596613e6f565b3391613f63565b346064355f6102643560061b5b80821061268d575050818111612688576126728160843561435b565b80821161267d575050565b61068a91033361435b565b6126b8565b9092836102840135938185116126b8576126b18560409303956102a483013561435b565b0190612656565b638ffff9805f526004601cfd5b919060a435908133141590600460018211911016166126e357505050565b61270f92601c83516317b1f9428552600163ffffffff82165263fb5014fc60605260801c930191614390565b5f606052565b7f00000000000000000000000000000000000000000000000000000000000000006127515763929eee1480541561274c5760019055565b5f905d565b5f63929eee145d565b7f0000000000000000000000000000000000000000000000000000000000000000806127b9575b1561278857565b63929eee1480549081156127ae575b506001106127a157565b637fa8a9875f526004601cfd5b5c6127a1575f612797565b63929eee145c1561278157637fa8a9875f526004601cfd5b90813563ffffffff811692604051938085526020641fffffffe0819460051b16860101928392602060a080940291018537602086015b8381106128175750505050604052565b848152938201938101612807565b90813563ffffffff811692604051938085526020641fffffffe0819460051b16860101928392602060c080940291018537602086015b83811061286b5750505050604052565b84815293820193810161285b565b908135916040926040519363ffffffff82168552602080641fffffffe08460051b16870101936020643fffffffc0869560061b1691018537602086015b8381106128c65750505050604052565b8481529382019381016128b6565b939492915f946128e26130ff565b5f357c4000000000000000000000000000000000000000000000000000000000169681519361291085611bb0565b9860205b6001870160051b8110612b5757507c400000000000000000000000000000000000000000000000000000000114612b5257612954908392969594936133d1565b5f946020945b6001850160051b8610612979575050505050501561297457565b614612565b909192939495868a01918251918215612b435788860151938215612ad057878d8b608060046129aa828b51016116ca565b6129b3816116c0565b14612ae75750916109ac91877fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff6129ef9560051c01918a61447b565b612ad0576020850190612a556109ac612a1784516effffffffffffffffffffffffffffff1690565b60408901516effffffffffffffffffffffffffffff1690612a398d8b516145dc565b916effffffffffffffffffffffffffffff80911691168961383b565b612ab957505050907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff612aa5925b01925184611cd1825173ffffffffffffffffffffffffffffffffffffffff1690565b6001602081975b019594939291905061295a565b602093955060019450905f80929b939b5252612aac565b6001935060208093955f80939c949c520152612aac565b915050612afc9295508651908701519061361c565b8093528215612b315750907fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff612aa592612a83565b97600192505f60208093950152612aac565b97602091935060019250612aac565b61446e565b8a81860151612b6688826131d2565b6effffffffffffffffffffffffffffff821660208501529093909291908415612ce1576effffffffffffffffffffffffffffff84166040840152850152805160a08101519160c082015191608001519e8f612bc0816116c0565b600110179e815160400151908151905f925b828410612c6b5750505050606090510151938451945f5b868110612c0157505050505050506020905b01612914565b80612c0e600192846116ac565b516080810160a0612c2182518b896143f9565b92612c4a60608201948c8651865181145f14612c5a5750508086525b8a8c36151592885161442b565b8094520190815190525201612be9565b612c64918c6143f9565b8652612c3d565b90919299612c798b836116ac565b519060048410825110179a608082018051612c95908b8d6143f9565b92606001908a8251948d835187145f1496612cc493600198612cd1575050508084525b8a8c361592865161442b565b8092525201929190612bd2565b612cda926143f9565b8452612cb8565b5050505050602090612bfb565b919082018092116123ac57565b604051906060820182811067ffffffffffffffff821117611102576040525f604083612d256110e2565b838152836020820152838382015283606082015283608082015281528260208201520152565b90612d586105368361118c565b8281527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0612d86829461118c565b01905f5b828110612d9657505050565b602090612da1612cfb565b82828501015201612d8a565b6060810151516101408201511161218f5780612e0173ffffffffffffffffffffffffffffffffffffffff6107bd93511673ffffffffffffffffffffffffffffffffffffffff165f525f60205260405f205490565b90611245565b91905460ff8160081c16612e63576effffffffffffffffffffffffffffff8160101c169081612e3a575b50505050600190565b60881c1115612e4a578080612e31565b612e5357505f90565b6310fda3e15f526020526024601cfd5b50612e6d57505f90565b631a5155745f526020526024601cfd5b91905460ff8160081c16612e63576effffffffffffffffffffffffffffff915060101c16612eab5750600190565b63ee9e0e635f526020526024601cfd5b632165628a5f526004601cfd5b92919033841461304057612eda613c1a565b93612f1482867f19010000000000000000000000000000000000000000000000000000000000005f5260025260225260425f20905f602252565b908351926002601f601d860116106102e27fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9d860110165f146130325760018085169081604103927fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbf60059388010160051c93808952880160209384820151928560238560e81c94019460e31c169081528584519118526001925b8684106130135750505050509661300d9161068a9798612fd160405f209261570a565b5f525260405f20907f19010000000000000000000000000000000000000000000000000000000000005f5260025260225260425f20905f602252565b90614a07565b85859101938684821c841b1660405f2081528786519118520192612fae565b5061068a9495508190614a07565b50509050565b611d8960609161016081853763ffffffff6130688160408401351683016127d1565b6040860152838201351601612825565b9060206040519263ffffffff813563ffffffe0601f82011692848401908737168452830101604052565b7f00000000000000000000000000000000000000000000000000000000000000006130ee5763929eee14805480156130e1576001036127a15760029055565b50805c6127a1576001905d565b63929eee14805c6127a1576001905d565b7f000000000000000000000000000000000000000000000000000000000000000061314b5763929eee148054801561313e576001036127a15760039055565b50805c6127a1576002905d565b63929eee14805c6127a1576002905d565b7f00000000000000000000000000000000000000000000000000000000000000006131ab5763929eee14908154801561319d576001036127a1576002019055565b50815c6127a157600101905d565b63929eee1490815c6127a157600101905d565b90805b6131c9575090565b809106806131c1565b9190918051916131ef6109ac8560a086015160c087015190614d1d565b6133bc576effffffffffffffffffffffffffffff6020816020850151169482604086015116946080820160048151613226816116c0565b61322f816116c0565b146133a35787158789111761339e575191613249836116c0565b600180931615878910166133995761326081612dad565b986132816109ac6132798c5f52600160205260405f2090565b92838d612e07565b61338b5754918960ff841615613357575b5050508060881c918483159260101c1691156132b0575b5050505050565b86979614613343578187146133265786829102950295029385019484861185870302809103958386116132e4575b806132a9565b856132fe926132f8929894959798036131be565b826131be565b8015018091049404928311613315578080806132de565b601190634e487b715f52526024601cfd5b925050508291939201828082119103029003915f808080806132a9565b8103955093505f91508190508080806132a9565b606061337a613383945173ffffffffffffffffffffffffffffffffffffffff1690565b92015191612ec8565b5f8089613292565b505f97508796505050505050565b614d4b565b614d3e565b50505050509250600191021861339e5760019081908290565b5f9350839250829150565b600211156106c357565b81518151925f5b82811061346f575050505f5b8281106133f057505050565b806133fd600192846116ac565b5161343161341d60208301516effffffffffffffffffffffffffffff1690565b6effffffffffffffffffffffffffffff1690565b15613469576134639051604060808201519161344c836116c0565b61345b83606083015187614e36565b015183615d44565b016133e4565b50613463565b61347981836116ac565b518051868110156135285761348e90866116ac565b516020906134b061341d838301516effffffffffffffffffffffffffffff1690565b1561351d57519060409081830151918401519263bfb3f8ce918501516134d5816133c7565b6134de816133c7565b61350a575b5081518310156135025750916134fc9160019493614d74565b016133d8565b5f526004601cfd5b9050606091500151636088d7de5f6134e3565b5050506001906134fc565b6020820151613536816133c7565b614d58565b60a08082015160c0830151604084018051513615985f989597959492895b8381106135d7575050505060809660046080870151613577816116c0565b1016612b52576060948501805151981593905f5b8a811061359f575050505050505050505050565b808a8a8a8a6135cb8b8b8b8b6135b860019b8d516116ac565b51968701958651998801998a5190614e92565b9052015190520161358b565b82888d838551906135e7916116ac565b519d8e516135f4816106b9565b15179d60608101918a8a8d85519460800196875161361196614e92565b905252600101613559565b919091606081019182515161014083015103612ebb575f8061365c613655855173ffffffffffffffffffffffffffffffffffffffff1690565b9685614ed1565b9082885af19361368a8173ffffffffffffffffffffffffffffffffffffffff165f52600260205260405f2090565b9081549160018301905560601b1893156136c25750604001906136b08251825190615c7f565b9390916136bc57525290565b84614f86565b9150506136ce57505f90565b6136d6614f3d565b614f86565b91825190608082015160058110156106c357602083019261372073ffffffffffffffffffffffffffffffffffffffff9283865116331415906004600182119110161690565b61372d575b505050505050565b61381a601c91608061382c980151965f6040519889936301e4d72a85526020808601528860408601523360608601528051608086015260a081015161012086015261014060c08201518187015260e08201516101608701528060a08701526138016040830151936137d76137a761018096878b0190615b45565b80850160c08b01526137c2606087015188838d010190615bb9565b019184830160e08b015286838b010190615ba0565b0193610100928501838901528085890101946137f38689615c03565b016101648101980101604052565b828660401b8d60801b1717910152525160051b9061239f565b9463fb5014fc60605201925116614390565b5f6060525f8080808080613725565b61384d815f52600160205260405f2090565b935f938554948560881c90811561393a57506effffffffffffffffffffffffffffff809660101c1681831461392b578282910292029402019383851190808511818711176138f3575b505b6138b057505060881b9060101b176001179055600190565b92509250505f146138ee576040517f10fda3e10000000000000000000000000000000000000000000000000000000081526004810191909152602490fd5b505f90565b93946138ff86826131be565b80150180910495049380851190861117613919575f613896565b634e487b715f5260116020526024601cfd5b92955050920192828411613898565b9550509293613898565b92919092613950611201565b916040820190815151915f5b8381106139ed5750505050606080910190815151915f5b83811061399c575050505061398991925061245b565b47806139925750565b61068a903361435b565b6139a78183516116ac565b5190858883516139b6816106b9565b6139bf816106b9565b156139da575b906139d491600194339061516a565b01613973565b50504784830151116126885785886139c5565b80613a30876139ff60019486516116ac565b51866080820152613a24895173ffffffffffffffffffffffffffffffffffffffff1690565b6101208a01519161516a565b0161395c565b919091805192608084019182519260058410156106c357613a846020870194613a73865173ffffffffffffffffffffffffffffffffffffffff1690565b331415906004600182119110161690565b15613aaf575050613a9d9061010061270f950151615416565b9290915163fb5014fc5b606052614390565b60049195935051613abf816116c0565b613ac8816116c0565b03613af55761270f93613ae89183519360808560601b9301519086615392565b9290916393979285613aa7565b50505050565b9081518082526020808093019301915f5b828110613b1a575050505090565b909192938260a082613b2f60019489516106c8565b01950193929101613b0c565b9094939173ffffffffffffffffffffffffffffffffffffffff91604090604051956080926080880192885285602092166020890152608060408901528651809352602060a089019701935f915b848310613bd6575050505050508282859493613bd193867f9d9af8e38d66c62e2c12f0225249fd9d721c54b83f48d9352c97c6cacdcb6f31989603606087015216971695613afb565b0390a3565b90919293949784836001928b518051613bee816106b9565b8252808401518c1684830152858101518683015260609081015190820152019901959493019190613b88565b467f000000000000000000000000000000000000000000000000000000000000000003613c65577f000000000000000000000000000000000000000000000000000000000000000090565b6040516080517f00000000000000000000000000000000000000000000000000000000000000005f527f00000000000000000000000000000000000000000000000000000000000000006020527f0000000000000000000000000000000000000000000000000000000000000000604052466060523060805260a05f20916040525f60605260805290565b63fed398fc5f526004601cfd5b7401000000000000000000000000000000000000000060243560c4351760a43560843517171060186101243510166102643560061b61026001610244351461024061022435146020600435141616161561218257565b90815f52600160205260405f2091613d6e3615158483612e7d565b5060ff83541615613d7c5750565b61068a90613d95602463ffffffff610244351601613078565b90608435612ec8565b91905f9260a43591823314159060046001821191101616613dbd575050565b9092506102043560051b90613e5d82608001926301e4d72a8452602060a08201528260c08201523360e082015260843561010082015260606101446101a08301376101e06101408061012084015282015260a06102643502956102a08701610160830152868201935f6103608601526102c08801610180840152806103a06103808701965f8852015263fb5014fc606052609c6103048901930191614390565b5f60605261032482940160801b179052565b15613e7657565b6391b3e5145f526004601cfd5b90602082015103613e915750565b61068a9061245b565b9060649492939160208251145f14613f505760c0906001906040845260208401527f4ce34aa2000000000000000000000000000000000000000000000000000000006040840152602060448401526001878401525b02019260017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc48501527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe4840152600483015260248201525f60448201520152565b5060c08582016001815101809152613eef565b9293919091833b1561405057604051946080519260a0519460c051967ff242432a000000000000000000000000000000000000000000000000000000005f528160045282602452836044528460645260a06084525f60a4525f8060c48180855af115613fe057505050505060805260a05260c0526040525f606052565b883d614004575b5063f486bc875f5260205260405260605260805260a05260a4601cfd5b601f3d0160051c9060051c908060030291808211614037575b505060205a91011061402f5785613fe7565b3d5f803e3d5ffd5b8080600392028380020360091c9203020101868061401d565b83635f15d6725f526020526024601cfd5b6369f958275f526020526024601cfd5b929190833b1561405057604051937f23b872dd000000000000000000000000000000000000000000000000000000005f528160045282602452836044525f8060648180855af1156140c957505050506040525f606052565b843d6140ef575b5063f486bc875f52602052604052606052608052600160a05260a4601cfd5b601f3d0160051c9060051c90806003029180821161411a575b505060205a91011061402f57846140d0565b8080600392028380020360091c92030201018580614108565b9394909461414084613e6f565b61414a8183613e83565b80614264575050604051937f23b872dd000000000000000000000000000000000000000000000000000000005f5280600452816024528260445260205f60648180885af1803d15601f3d1160015f51141617163d15158116156141b7575b5050505050506040525f606052565b80863b1515166141a857908691156141da5785635f15d6725f526020526024601cfd5b908591156141fc575063988919235f526020526040526060526080526084601cfd5b3d614220575b5063f486bc875f526020526040526060525f60805260a05260a4601cfd5b601f3d0160051c9060051c90806003029180821161424b575b505060205a91011061402f5784614202565b8080600392028380020360091c92030201018580614239565b9061068a9592939491613e9a565b60205f61010473ffffffffffffffffffffffffffffffffffffffff9460405195807f00000000000000000000000000000000000000000000000000000000000000001674ff00000000000000000000000000000000000000001784528585527f00000000000000000000000000000000000000000000000000000000000000006040526055600b20169560405282805282865af15f519015612568577fffffffff000000000000000000000000000000000000000000000000000000007f4ce34aa200000000000000000000000000000000000000000000000000000000911603612563575050565b61436482613e6f565b5f80808085855af115614375575050565b61437d614f3d565b63bc806b965f526020526040526044601cfd5b91602091935f91827fffffffff00000000000000000000000000000000000000000000000000000000825116958180525af1905f511490156143dd57156143d45750565b6080526024607cfd5b506143d4614f3d565b818102929181159184041417156123ac57565b919091828114614425578281830961441857614414916143e6565b0490565b63c63cf0895f526004601cfd5b50905090565b9392909384810361443d575050505090565b61445383614459930393420391828503906143e6565b946143e6565b83018093116123ac5781830304019015150290565b6312d3f5a35f526004601cfd5b9193929382519460808601519060058210156106c35760208701936144c473ffffffffffffffffffffffffffffffffffffffff9384875116331415906004600182119110161690565b6144d5575050505050505050600190565b6107bd976145c9836145d293601c956145b5608060409c0151958a8d519d8e6301e4d72a815260208082015201528c6060339101528c608082519101528c61012060a083015191015260a08d61014091829160c08501518382015260e085015161016082015201528d6040830151986145876145576101809b8c850190615b45565b80850160c085015261457260608701518d8387010190615bb9565b019184830160e08501528b8385010190615ba0565b01906101009282018382015289828201019485926145a5848a615c03565b019a6101648c019b830101604052565b8960401b9060801b1717910152525161239f565b60051b9061239f565b9401925116615450565b60808101519060058210156106c35773ffffffffffffffffffffffffffffffffffffffff60206001920151163314159111161790565b63d5da9a1b5f526004601cfd5b92919261462a612cfb565b938251156146545761068a9273ffffffffffffffffffffffffffffffffffffffff869216926155d1565b63375c24c15f525f6020526024601cfd5b92919092614671612cfb565b93805115614796575f92915f925f928091815160059060051b83015b8085106146be575050505050505080916060855101526146aa5750565b600103613919576391b3e5145f526004601cfd5b6020809501948551518751811015614739578190841b88010151908087510151916060928284835101519201511582518210151761478a575f918391871b0101519283019a8c8c518091019d8e9115911060011b17179b9a528c518d8a1560011461473e5750505060a090208718614739575b97969761468d565b6154c1565b83929a5090869160a0945182528b8401518c8301526040918285015183820152608080860151910152338c820152015220968401858118614780575b50614731565b855190525f61477a565b50505050979697614731565b63375c24c15f5260016020526024601cfd5b939190938051926147b884611bb0565b956147c1611201565b90600196600182510160051b6020928360205b8381106149a357505050505f5b878110614871575050506147f49061245b565b4780614861575b5061480d575b505050506107bd612715565b5f5b83811061481c5750614801565b8061483161482b8793896116ac565b51151590565b61483c575b0161480f565b61485c61484982856116ac565b518561485584826116ac565b5191613a36565b614836565b61486b903361435b565b5f6147fb565b61487b81876116ac565b518961489b61341d868401516effffffffffffffffffffffffffffff1690565b1561498f5791906148b56148af838e6116ac565b60019052565b5160408101518051905f5b82811061491f57505050606080910151908151915f5b8381106148e857505050505b016147e1565b9091929394506148f881836116ac565b5183810190815180614918575060a0015190528c949392919085016148d6565b83886156f4565b61492e818394959697936116ac565b5160806060820191825161494d575b0151905201908c949392916148c0565b608081018051908b90526149868d6149798b5173ffffffffffffffffffffffffffffffffffffffff1690565b6101208c0151908561516a565b8282015261493d565b9190505f61499d828d6116ac565b526148e2565b8083015180516060810151806149bf575b5050500184906147d4565b909193504710815115166126b857876149ff918460406149f68b8098015173ffffffffffffffffffffffffffffffffffffffff1690565b9101519161516a565b5f80806149b4565b909291925f80528451947fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08101805190876041035f9060018111958615614b84575b5050851485151516978815614a7d575b505050505050505015614a6857565b614a70614f3d565b634f7fb80d5f526004601cfd5b909192939495809798508452604082527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffbc8401938451957fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc082019760205f60648b519c7f1626ba7e000000000000000000000000000000000000000000000000000000009e8f8c528d520189845afa9a8b614b28575b50505050505252525f80808080808080614a59565b5f5103614b355780614b13565b3b614a7057614b775760600190604164010100000083515f1a1a15911416614b645763815e1d645f526004601cfd5b631f003d0a5f52515f1a6020526024601cfd5b638baa579f5f526004601cfd5b909150604085019081519260608701515f1a90614bbb575b8652835260205f60808560015afa50838352898552525f515f80614a49565b50601b8360ff1c017f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff84168352614b9c565b9192614bf7612cfb565b9380511583511517614d1057614c0b612cfb565b92614c178483876154ce565b8351926060840194855115614d055750614c53614c4b608086015173ffffffffffffffffffffffffffffffffffffffff1690565b8884896155d1565b865193604081015160408601511890602081015160208701511890518651181717614cf55750606084519301928351105f14614cc257509160206060614caf614cbc94614ca0839761169a565b519451905185519103976116ac565b51510151910151906116ac565b51015290565b60609150614cd5614cec9195939561169a565b5160206040614caf885188519003968451906116ac565b51015251905290565b63bced929d5f526020526024601cfd5b965050505050505090565b6398e9db6e5f526004601cfd5b428082111590831116939280614d36575b61219c575050565b508315614d2e565b635a052b325f526004601cfd5b63a11b63ff5f526004601cfd5b63133c37c65f526020526024601cfd5b614d71826106b9565b52565b90614d7e916116ac565b51805191614d8b836106b9565b6003831115614e29576040820180519093908015614dec57927ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe614de692614ddf6060968787015190608088015191615af3565b0190614d68565b01519052565b50608082015151614e24576060927ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe614de692614ddf565b615ae6565b6394eb6af65f526004601cfd5b815192915f5b848110614e4a575050505050565b614e5481836116ac565b518051614e60816106b9565b60036040809301511515600488141517911116614e805750600101614e3c565b8363a8930e9a5f52602052526044601cfd5b959192939490948587145f14614eaf575050506107bd93506143f9565b92919484614ec56107bd98614ecb9497866143f9565b936143f9565b9061442b565b9190608490614f38604051916398919765835260a0601c84019633602086015260806040860152614f246060614f0e604084015185890190615b45565b9283608001828901520151838388010190615b45565b018094608082016080820152010190615ba0565b010190565b3d614f4457565b601f3d0160051c60405160051c908060030291808211614f6d575b505060205a91011061402f57565b8080600392028380020360091c92030201015f80614f5f565b63939792855f526020526024601cfd5b92909260405193815190602092602060c087028801016040528587526020918660010160051b93848901928160010160051b019781810382821002820160010160051b9111975b81851061501a5750505b838310614ff5575050505050565b60a0859183858b01526080908181863e60608501518286015201920192019190614fe7565b9390949197869084838c0152608090818b873e60608087015190818489015288015111615047878961510a565b171799019360a08091019501910194909493929194614fdd565b9290604051938051908185119482808203911002820191602092602060e0820289010160405280885260209060010160051b928389019260010160051b01915b8382106150b057505050505050565b9091929380959782848b015260a090818a853e606083818c018487013e8481015190870151608080870151908901518015911417159111176150f2858861510a565b1717980195949360c0908101939190910191016150a1565b9081519160408101518015600385111661513a575b60208091604085015114948451149301519101511416161590565b5060408201517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe9093019261511f565b9290918351615178816106b9565b615181816106b9565b615216575050506151c56151ac602083015173ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff1690565b73ffffffffffffffffffffffffffffffffffffffff60408301519116176124435780606061520d608061068a94015173ffffffffffffffffffffffffffffffffffffffff1690565b9101519061435b565b90919260018151615226816106b9565b61522f816106b9565b036152a65760408101516124435761068a93615262602083015173ffffffffffffffffffffffffffffffffffffffff1690565b9073ffffffffffffffffffffffffffffffffffffffff606061529b608086015173ffffffffffffffffffffffffffffffffffffffff1690565b940151931691614133565b92600284516152b4816106b9565b6152bd816106b9565b0361532a57836152e7602061068a96015173ffffffffffffffffffffffffffffffffffffffff1690565b608082015173ffffffffffffffffffffffffffffffffffffffff169273ffffffffffffffffffffffffffffffffffffffff606060408501519401519416916122a2565b8361534f602061068a96015173ffffffffffffffffffffffffffffffffffffffff1690565b608082015173ffffffffffffffffffffffffffffffffffffffff169273ffffffffffffffffffffffffffffffffffffffff606060408501519401519416916121af565b9493919260c060a494615402614f38946040519663f4dd92ce8852601c88019a1860a088015260a060208801526153ec60606153d56040840151878b0190615b45565b928360a00160408b0152015185838a010190615bb9565b019160a083016060880152838388010190615ba0565b01809460a082016080820152010190615c03565b916125818360801c9263ffffffff601c818760401c16956317b1f942815201951690615c03565b631cf99b265f526020526040526044601cfd5b925f906020929593827fffffffff00000000000000000000000000000000000000000000000000000000825116968180525af1915f511491156154a95750156154995750600190565b63fb5014fc5f526020526024601cfd5b9050919091156154bc5750615499614f3d565b5f9150565b637fda72795f526004601cfd5b909291925f905f925f9180805160059060051b82015b8084106155005750505050505060608293945101526146aa5750565b6020979697809401938451518651811015614739578190841b8701015190808651015191606092828483510151920151158251821015176155c5575f918391871b010151928301998a519b8c81019c15908d1060011b17179a99528b518c89156001146155795750505060a090208618614739576154e4565b829950905f8493819360a0965184528186015182850152604093848701518582015260808088015191015201528d0152209583018481186155bb575b506154e4565b845190525f6155b5565b505050509695966154e4565b81519294935f93849384929091825b8160051b840181106156015750505050505060608293945101526146aa5750565b6020909796970190855182515110156147395781516020815160051b880101516020815192015160206040840151920151158251821015176156e9579060209160051b0101515f60608201998a519081158d8381011060011b17179b0199528b51871560011461569557506060902086189060408c0151610120820151189060208d01519051181717614739575b906155e0565b9160609397506040826101209351855260208101516020860152015160408401528560808401528c60208251910152015160408c01522093602084018281186156df575b5061568f565b825190525f6156d9565b50505096959661568f565b63a5f542085f526020526040526060526064601cfd5b600981106159a2576011811061585e57601581106157c057601781106157755760177f403be09941a31d05cfc2f896505811353d45d38743288b016630cce39435476a9114027f1d51df90cba8de7637ca3e8fe1e3511d1dc2f23487d05dbdecb781860c21ac1c1890565b60157fbb40bf8cea3a5a716e2b6eb08bbdac8ec159f82f380783db3c56904f15a43d049114027f3bd8cff538aba49a9c374c806d277181e9651624b3e31111bc0624574f8bca1d1890565b601381106158135760137f54b3212a178782f104e0d514b41a9a5c4ca9c980bf6597c3cecbf280917e202a9114027f5a4f867d3d458dabecad65f6201ceeaba0096df2d0c491cc32e6ea4e643500171890565b60117f2d7a3ed6dab270fdb8e054b2ad525f0ce2a8b89cc76c17f0965434740f673a559114027fc3939feff011e53ab8c35ca3370aad54c5df1fc2938cd62543174fa6e7d858771890565b600d811061590457600f81106158b957600f7fcc4886e37eedd9aacd6c1c2c9247197a621a71282e87a7cbc673f3736d9aa1419114027f1da3eed3ecef6ebaa6e5023c057ec2c75150693fd0dac5c90f4a142f9879fde81890565b600d7f8df51df98847160517f5b1186b4bc3f418d98b8a7f17f1292f392d79d600d79e9114027f6b5b04cbae4fcb1a9d78e7b2dfc51a36933d023cf6e347e03d517b472a8525901890565b600b811061595757600b7f32f4e7485d6485f9f6c255929b9905c62ba919758bbe231f231eaeecf33d810c9114027fbb98d87cc12922b83759626c5f07d72266da9702d19ffad6a514c73a89002f5f1890565b60097f6f0ec38c21f6f583ab7f3c5413c773ffd5344c34fde1d390958e438bf667448f9114027fd1d97d1ef5eaa37a4ee5fbf234e6f6d64eb511eb562221cd7edfbdde0848da051890565b60058110615a4857600781106159fd5760077fb58d772fb09b426b9dece637f61ca9065f2b994f1464b51e9207f55f7c8f59489114027f7ff98d9d4e55d876c5cfac10b43c04039522f3ddfb0ea9bfe70c68cfb5c7cc141890565b60057f25d02425402d882d211a7ab774c0ed6eca048c4d03d9af40132475744753b2a39114027f1c19f71958cdd8f081b4c31f7caf5c010b29d12950be2fa1c95070dc47e30b551890565b60038110615a9b5760037ff3e8417a785f980bdaf134fa0274a6bf891eeb8195cd94b09d2aa651046e28bc9114027fa02eb7ff164c884e5e2c336dc85f81c6a93329d8e9adf214b32729b894de2af11890565b60017f832c58a5b611aadcfa6a082ac9d04bace53d8278387f10040347b7e98eb5b3029114027fbf8e29b89f29ed9b529c154a63038ffca562f8d7cd1e2545dda53a1b582dde301890565b6309bde3395f526004601cfd5b9190915f5260209060205f20916020820191602081519160059260051b0101905b818410615b26575050505003615ae657565b8351808611821b9586529483189490945260405f209392820192615b14565b9081519081815260209283808083019301918460051b0101915b84838210615b72575050505060071b0190565b8160809251805185528281015183860152604080820151908601526060809101519085015201910190615b5f565b8051603f0163ffffffe016929161068a91849190615c23565b80519182815260208080808501948660051b01019201925b828110615be5575050505060a00260200190565b60a090818581835160045afa153d151761018d578201930192615bd1565b615c1f602092839283815180845260051b948593019101615c23565b0190565b829060045afa153d151761018d57565b604051906101608201604052615c71610140918281853763ffffffff615c608160408401351683016127d1565b604086015260608201351601612825565b806060840152519082015290565b90915f925f9260603d10915f905f925f905f938615615cdc575b8615615cab575b505050505050929190565b615cc4939495995060209850615cce9650880190614f96565b9590960190615061565b9092175f8080808080615ca0565b509450925060405f803e5f51926020948551943d878201113d8888011117968715615d08575b50615c99565b9450809650849192505f3e5f51908385813e835193808560a0028701013d10908360071b8801013d101761ffff8584171117955f80525f615d02565b815192915f5b848110615d58575050505050565b615d6281836116ac565b518051615d6e816106b9565b60036040809301511515600488141517911116615d8e5750600101615d4a565b8363d69293325f52602052526044601cfdfea164736f6c6343000818000a00000000000000000000000000000000f9490004c11cef243f5400493c00ad630000000000000000000000000000000000
```
3. Validate deployments were successful by checking that `Seaport` is returned:
```
-cast --to-ascii $(cast call --rpc-url ${RPC_URL} 0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC 'name()')
+cast call --rpc-url ${RPC_URL} 0x0000000000000068F116a894984e2DB1123eB395 'name()(string)'
```
## Verifying Seaport and ConduitController
After `Seaport` and `ConduitController` are deployed, they are verified as follows:
1. Ensure that `EXPLORER_API_KEY` and `NETWORK_RPC` are set in `.env` appropriately.
-2. Navigate to the `1.1` release tag on the Seaport repo and build artifacts:
+2. For verifying the `ConduitController`, navigate to the `1.1` release tag on the Seaport repo and build artifacts:
```
git clone https://github.com/ProjectOpenSea/seaport && cd seaport
git checkout 821a049
-yarn build
+yarn install && yarn build
```
3. Verify `ConduitController` by calling:
@@ -101,24 +110,24 @@ yarn build
npx hardhat verify --network verificationNetwork "0x00000000F9490004C11Cef243f5400493c00Ad63"
```
-4. Navigate to the `1.5` release tag on the Seaport repo and clean up existing artifacts:
+4. Navigate to the `1.6` release tag on the [seaport-core](https://github.com/ProjectOpenSea/seaport-core) repo:
```
-git checkout ab3b5cb
-yarn clean
+cd ../ && git clone https://github.com/ProjectOpenSea/seaport-core && cd seaport-core
+git checkout 523097f
```
-5. Open `hardhat.config.ts` and modify the `runs` setting on line 78 to work around a limitation on the max optimization run value on many block explorers (the build artifacts are equivalent):
+5. Open `foundry.toml` and modify the `runs` setting to work around a limitation on the max optimization run value on many block explorers (the build artifacts are equivalent):
```
-runs: 4_294_967_295 => runs: 9_999_999
+optimizer_runs = 4_294_967_295 => optimizer_runs = 9_999_999
```
6. Build artifacts:
```
-yarn build
+forge build
```
-7. Verify `Seaport 1.5` by calling:
+7. Verify `Seaport 1.6` by calling:
```
-npx hardhat verify --network verificationNetwork "0x00000000000000ADc04C56Bf30aC9d3c0aAF14dC" "0x00000000F9490004C11Cef243f5400493c00Ad63"
-```
\ No newline at end of file
+forge verify-contract --chain {chain} 0x0000000000000068F116a894984e2DB1123eB395 src/Seaport.sol:Seaport
+```
diff --git a/docs/FunctionSignatures.md b/docs/FunctionSignatures.md
index cc7e950c9..99789d382 100644
--- a/docs/FunctionSignatures.md
+++ b/docs/FunctionSignatures.md
@@ -1,3 +1,12 @@
+---
+title: Seaport Functions
+category: 6520398b749af50013f52ff4
+slug: seaport-functions
+parentDocSlug: seaport-overview
+order: 4
+hidden: false
+---
+
# Seaport Function Signatures
diff --git a/docs/OrderValidator.md b/docs/OrderValidator.md
index 4e33db979..fcd5a9a74 100644
--- a/docs/OrderValidator.md
+++ b/docs/OrderValidator.md
@@ -1,3 +1,12 @@
+---
+title: Order Validation
+category: 6520398b749af50013f52ff4
+slug: seaport-order-validator
+parentDocSlug: seaport-overview
+order: 3
+hidden: false
+---
+
# Seaport Order Validator
The SeaportValidator contract offers various validation methods to ensure that supplied Seaport orders are being constructed correctly. Most contract calls return an `ErrorsAndWarnings` struct with two `uint16` arrays to help developers debug issues with their orders.
@@ -33,72 +42,72 @@ Special thanks to:
- [horsefacts](https://github.com/horsefacts), who implemented support for a ready-only version of the helper contract
## Errors and Warnings
-| Code | Issue |
-| - | ----------- |
-| 100 | Invalid order format. Ensure offer/consideration follow requirements |
-| 200 | ERC20 identifier must be zero |
-| 201 | ERC20 invalid token |
-| 202 | ERC20 insufficient allowance to conduit |
-| 203 | ERC20 insufficient balance |
-| 300 | ERC721 amount must be one |
-| 301 | ERC721 token is invalid |
-| 302 | ERC721 token with identifier does not exist |
-| 303 | ERC721 not owner of token |
-| 304 | ERC721 conduit not approved |
-| 305 | ERC721 offer item using criteria and more than amount of one requires partial fills |
-| 400 | ERC1155 invalid token |
-| 401 | ERC1155 conduit not approved |
-| 402 | ERC1155 insufficient balance |
-| 500 | Consideration amount must not be zero |
-| 501 | Consideration recipient must not be null address |
-| 502 | Consideration contains extra items |
-| 503 | Private sale cannot be to self |
-| 504 | Zero consideration items |
-| 505 | Duplicate consideration items |
-| 506 | Offerer is not receiving at least one item |
-| 507 | Private Sale Order. Be careful on fulfillment |
-| 508 | Amount velocity is too high. Amount changes over 5% per 30 min if warning and over 50% per 30 min if error |
-| 509 | Amount step large. The steps between each step may be more than expected. Offer items are rounded down and consideration items are rounded up. |
-| 600 | Zero offer items |
-| 601 | Offer amount must not be zero |
-| 602 | More than one offer item |
-| 603 | Native offer item |
-| 604 | Duplicate offer item |
-| 605 | Amount velocity is too high. Amount changes over 5% per 30 min if warning and over 50% per 30 min if error |
-| 606 | Amount step large. The steps between each step may be more than expected. Offer items are rounded down and consideration items are rounded up. |
-| 700 | Primary fee missing |
-| 701 | Primary fee item type incorrect |
-| 702 | Primary fee token incorrect |
-| 703 | Primary fee start amount too low |
-| 704 | Primary fee end amount too low |
-| 705 | Primary fee recipient incorrect |
-| 800 | Order cancelled |
-| 801 | Order fully filled |
-| 802 | Cannot validate status of contract order
-| 900 | End time is before start time |
-| 901 | Order expired |
-| 902 | Order expiration in too long (default 26 weeks) |
-| 903 | Order not active |
-| 904 | Short order duration (default 30 min) |
-| 1000 | Conduit key invalid |
-| 1001 | Conduit does not have canonical Seaport as an open channel |
-| 1100 | Signature invalid |
-| 1101 | Contract orders do not have signatures |
-| 1102 | Signature counter below current counter |
-| 1103 | Signature counter above current counter |
-| 1104 | Signature may be invalid since `totalOriginalConsiderationItems` is not set correctly |
-| 1200 | Creator fee missing |
-| 1201 | Creator fee item type incorrect |
-| 1202 | Creator fee token incorrect |
-| 1203 | Creator fee start amount too low |
-| 1204 | Creator fee end amount too low |
-| 1205 | Creator fee recipient incorrect |
-| 1300 | Native token address must be null address |
-| 1301 | Native token identifier must be zero |
-| 1302 | Native token insufficient balance |
-| 1400 | Zone is invalid |
-| 1401 | Zone rejected order. This order must be fulfilled by the zone. |
-| 1402 | Zone not set. Order unfulfillable |
-| 1500 | Merkle input only has one leaf |
-| 1501 | Merkle input not sorted correctly |
-| 1600 | Contract offerer is invalid |
+| Code | Issue | Type
+| - | ----------- | - |
+| 100 | Invalid order format. Ensure offer/consideration follow requirements | Error |
+| 200 | ERC20 identifier must be zero | Error |
+| 201 | ERC20 invalid token | Error |
+| 202 | ERC20 insufficient allowance to conduit | Error |
+| 203 | ERC20 insufficient balance | Error |
+| 300 | ERC721 amount must be one | Error |
+| 301 | ERC721 token is invalid | Error |
+| 302 | ERC721 token with identifier does not exist | Error |
+| 303 | ERC721 not owner of token | Error |
+| 304 | ERC721 conduit not approved | Error |
+| 305 | ERC721 offer item using criteria and more than amount of one requires partial fills | Error |
+| 400 | ERC1155 invalid token | Error |
+| 401 | ERC1155 conduit not approved | Error |
+| 402 | ERC1155 insufficient balance | Error |
+| 500 | Consideration amount must not be zero | Error |
+| 501 | Consideration recipient must not be null address | Error |
+| 502 | Consideration contains extra items | Error |
+| 503 | Private sale cannot be to self | Error |
+| 504 | Zero consideration items | Warning |
+| 505 | Duplicate consideration items | Warning |
+| 506 | Offerer is not receiving at least one item | Warning |
+| 507 | Private Sale Order. Be careful on fulfillment | Warning |
+| 508 | Amount velocity is too high. Amount changes over 5% per 30 min if warning and over 50% per 30 min if error | Both |
+| 509 | Amount step large. The steps between each step may be more than expected. Offer items are rounded down and consideration items are rounded up. | Warning |
+| 600 | Zero offer items | Warning |
+| 601 | Offer amount must not be zero | Error |
+| 602 | More than one offer item | Warning |
+| 603 | Native offer item | Warning |
+| 604 | Duplicate offer item | Error |
+| 605 | Amount velocity is too high. Amount changes over 5% per 30 min if warning and over 50% per 30 min if error | Both |
+| 606 | Amount step large. The steps between each step may be more than expected. Offer items are rounded down and consideration items are rounded up. | Warning |
+| 700 | Primary fee missing | Error |
+| 701 | Primary fee item type incorrect | Error |
+| 702 | Primary fee token incorrect | Error |
+| 703 | Primary fee start amount too low | Error |
+| 704 | Primary fee end amount too low | Error |
+| 705 | Primary fee recipient incorrect | Error |
+| 800 | Order cancelled | Error |
+| 801 | Order fully filled | Error |
+| 802 | Cannot validate status of contract order | Warning |
+| 900 | End time is before start time | Error |
+| 901 | Order expired | Error |
+| 902 | Order expiration in too long (default 26 weeks) | Warning |
+| 903 | Order not active | Warning |
+| 904 | Short order duration (default 30 min) | Warning |
+| 1000 | Conduit key invalid | Error |
+| 1001 | Conduit does not have canonical Seaport as an open channel | Error |
+| 1100 | Signature invalid | Error |
+| 1101 | Contract orders do not have signatures | Warning |
+| 1102 | Signature counter below current counter | Error |
+| 1103 | Signature counter above current counter | Error |
+| 1104 | Signature may be invalid since `totalOriginalConsiderationItems` is not set correctly | Warning |
+| 1200 | Creator fee missing | Error |
+| 1201 | Creator fee item type incorrect | Error |
+| 1202 | Creator fee token incorrect | Error |
+| 1203 | Creator fee start amount too low | Error |
+| 1204 | Creator fee end amount too low | Error |
+| 1205 | Creator fee recipient incorrect | Error |
+| 1300 | Native token address must be null address | Error |
+| 1301 | Native token identifier must be zero | Error |
+| 1302 | Native token insufficient balance | Error |
+| 1400 | Zone is invalid | Warning |
+| 1401 | Zone rejected order. This order must be fulfilled by the zone. | Warning |
+| 1402 | Zone not set. Order unfulfillable | Error |
+| 1500 | Merkle input only has one leaf | Error |
+| 1501 | Merkle input not sorted correctly | Error |
+| 1600 | Contract offerer is invalid | Warning |
diff --git a/docs/Overview.md b/docs/Overview.md
new file mode 100644
index 000000000..484489387
--- /dev/null
+++ b/docs/Overview.md
@@ -0,0 +1,9 @@
+---
+title: Seaport
+category: 6520398b749af50013f52ff4
+slug: seaport-overview
+order: 0
+hidden: false
+---
+
+Seaport is a marketplace protocol for safely and efficiently buying and selling NFTs. Each listing contains an arbitrary number of items that the offerer is willing to give (the "offer") along with an arbitrary number of items that must be received along with their respective receivers (the "consideration").
\ No newline at end of file
diff --git a/docs/SeaportDiagramLink.md b/docs/SeaportDiagramLink.md
new file mode 100644
index 000000000..ad06497b7
--- /dev/null
+++ b/docs/SeaportDiagramLink.md
@@ -0,0 +1,10 @@
+---
+title: Seaport Diagram
+category: 6520398b749af50013f52ff4
+slug: seaport-diagram
+parentDocSlug: seaport-overview
+order: 5
+hidden: false
+type: link
+link_url: https://github.com/ProjectOpenSea/seaport/blob/main/diagrams/README.md
+---
\ No newline at end of file
diff --git a/docs/SeaportDocumentation.md b/docs/SeaportDocumentation.md
index 7fa55acd4..f9ce6335b 100644
--- a/docs/SeaportDocumentation.md
+++ b/docs/SeaportDocumentation.md
@@ -1,3 +1,12 @@
+---
+title: Interacting with Seaport
+category: 6520398b749af50013f52ff4
+slug: seaport-interactions
+parentDocSlug: seaport-overview
+order: 1
+hidden: false
+---
+
# Seaport Documentation
Documentation around creating orders, fulfillment, and interacting with Seaport.
diff --git a/docs/ZoneDocumentation.md b/docs/ZoneDocumentation.md
index 21294191c..6d493c6b4 100644
--- a/docs/ZoneDocumentation.md
+++ b/docs/ZoneDocumentation.md
@@ -1,3 +1,12 @@
+---
+title: Seaport Zones
+category: 6520398b749af50013f52ff4
+slug: seaport-zones
+parentDocSlug: seaport-overview
+order: 2
+hidden: false
+---
+
# Zone Documentation
The `zone` of the order is an optional secondary account attached to the order with two additional privileges:
diff --git a/foundry.toml b/foundry.toml
index 82ed0b7dd..6fd61494d 100644
--- a/foundry.toml
+++ b/foundry.toml
@@ -1,5 +1,6 @@
[profile.default]
-solc = '0.8.17'
+solc = '0.8.24'
+evm_version='cancun'
src = 'contracts'
out = 'out'
libs = ["node_modules", "lib"]
@@ -37,12 +38,14 @@ runs = 1_000
max_test_rejects = 1_000_000
[profile.reference]
-solc = '0.8.13'
+solc = '0.8.24'
src = 'reference'
+via_ir = false
out = 'reference-out'
script = 'reference'
-# specify something so it doesn't try to compile the 0.8.17 files in test/foundry
-test = 'reference'
+test = 'test/foundry'
+cache_path = 'reference-cache'
+
[profile.optimized]
via_ir = true
@@ -70,10 +73,7 @@ optimizer = false
test = 'test/foundry/new'
[profile.offerers]
-src='offerers'
-test='offerers'
-out = 'offerers-out'
-script = 'offerers'
+test='test/foundry/offerers'
[fmt]
line_length = 80
diff --git a/hardhat-coverage.config.ts b/hardhat-coverage.config.ts
index 03dca0df8..c8d0d1369 100644
--- a/hardhat-coverage.config.ts
+++ b/hardhat-coverage.config.ts
@@ -13,8 +13,9 @@ const config: HardhatUserConfig = {
solidity: {
compilers: [
{
- version: "0.8.17",
+ version: "0.8.24",
settings: {
+ evmVersion: "cancun",
viaIR: false,
optimizer: {
enabled: false,
@@ -25,8 +26,9 @@ const config: HardhatUserConfig = {
},
networks: {
hardhat: {
- blockGasLimit: 30_000_000,
+ blockGasLimit: 300_000_000,
throwOnCallFailures: false,
+ allowUnlimitedContractSize: true,
},
},
gasReporter: {
diff --git a/hardhat.config.ts b/hardhat.config.ts
index b0b032f06..863ba6a32 100644
--- a/hardhat.config.ts
+++ b/hardhat.config.ts
@@ -69,8 +69,9 @@ const config: HardhatUserConfig = {
solidity: {
compilers: [
{
- version: "0.8.17",
+ version: "0.8.24",
settings: {
+ evmVersion: "cancun",
viaIR: true,
optimizer: {
...(process.env.NO_SPECIALIZER
@@ -133,6 +134,7 @@ const config: HardhatUserConfig = {
},
networks: {
hardhat: {
+ hardfork: "cancun",
blockGasLimit: 30_000_000,
throwOnCallFailures: false,
allowUnlimitedContractSize: false,
diff --git a/lib/seaport-core b/lib/seaport-core
index 2f546b9a0..1a0a4758c 160000
--- a/lib/seaport-core
+++ b/lib/seaport-core
@@ -1 +1 @@
-Subproject commit 2f546b9a0d61a70e1632445cbcb108149a9369ae
+Subproject commit 1a0a4758cced1d3de962817cd37c2387fb290eea
diff --git a/lib/seaport-sol b/lib/seaport-sol
index 880e58c80..7b480ce2b 160000
--- a/lib/seaport-sol
+++ b/lib/seaport-sol
@@ -1 +1 @@
-Subproject commit 880e58c80b5a31b6abaea7e7ede6bb26fa07f9e6
+Subproject commit 7b480ce2b5f258f283726c3a001b8bf7a8ae62fc
diff --git a/lib/seaport-types b/lib/seaport-types
index fa8b592f9..b72493221 160000
--- a/lib/seaport-types
+++ b/lib/seaport-types
@@ -1 +1 @@
-Subproject commit fa8b592f991b30ddf10a3b71737c9c1d5e315d10
+Subproject commit b72493221ee1d2f2fb30ed94a3cc535a9028d09f
diff --git a/package.json b/package.json
index 7c5a3acee..dd567da4d 100644
--- a/package.json
+++ b/package.json
@@ -1,24 +1,24 @@
{
"name": "seaport",
- "version": "1.5.0",
+ "version": "1.6.0",
"description": "Seaport is a marketplace protocol for safely and efficiently buying and selling NFTs. Each listing contains an arbitrary number of items that the offerer is willing to give (the \"offer\") along with an arbitrary number of items that must be received along with their respective receivers (the \"consideration\").",
"main": "contracts/Seaport.sol",
"author": "0age",
"license": "MIT",
"private": false,
"engines": {
- "node": ">=16.15.1"
+ "node": ">=18.15.0"
},
"dependencies": {
"@nomicfoundation/hardhat-network-helpers": "^1.0.7",
- "@openzeppelin/contracts": "^4.9.2",
+ "@openzeppelin/contracts": "^4.9.6",
"ethers": "^5.5.3",
"ethers-eip712": "^0.2.0",
- "hardhat": "^2.12.1-ir.0",
+ "hardhat": "^2.21.0",
"merkletreejs": "^0.3.9",
- "seaport-core": "^1.5.0",
- "seaport-sol": "^1.5.0",
- "seaport-types": "^0.0.1",
+ "seaport-core": "1.6.6",
+ "seaport-sol": "1.6.0",
+ "seaport-types": "1.6.3",
"solady": "^0.0.84"
},
"devDependencies": {
@@ -50,7 +50,7 @@
"prettier-plugin-solidity": "^1.1.0",
"scuffed-abi": "^1.0.4",
"solhint": "^3.3.6",
- "solidity-coverage": "^0.8.2",
+ "solidity-coverage": "^0.8.10",
"ts-node": "^10.4.0",
"typechain": "^8.0.0",
"typescript": "^4.5.4"
@@ -105,6 +105,7 @@
"show:headroom": "jq -r '.deployedBytecode' artifacts/contracts/Seaport.sol/Seaport.json | tr -d '\n' | wc -m | awk '{print 24577 - ($1 - 2)/2}'",
"test:forge": "FOUNDRY_PROFILE=reference forge build; FOUNDRY_PROFILE=optimized forge build; FOUNDRY_PROFILE=test forge test -vvv",
"test:forge:lite": "FOUNDRY_PROFILE=reference forge build; FOUNDRY_PROFILE=lite forge test -vvv",
+ "test:forge:ref": "FOUNDRY_PROFILE=reference forge build; FOUNDRY_PROFILE=optimized forge build; FOUNDRY_PROFILE=reference MOAT_PROFILE=reference forge test -vvv",
"build:validator": "hardhat compile --config ./hardhat-validator.config.ts",
"test:validator": "hardhat test --config ./hardhat-validator.config.ts",
"test:fuzz": "forge test --mp test/foundry/new/FuzzMain.t.sol",
diff --git a/reference/ReferenceConsideration.sol b/reference/ReferenceConsideration.sol
index d01b7482f..5cb353efd 100644
--- a/reference/ReferenceConsideration.sol
+++ b/reference/ReferenceConsideration.sol
@@ -28,7 +28,9 @@ import { OrderToExecute } from "./lib/ReferenceConsiderationStructs.sol";
* @author 0age
* @custom:coauthor d1ll0n
* @custom:coauthor transmissions11
- * @custom:version 1.5-reference
+ * @custom:coauthor James Wenzel
+ * @custom:coauthor Daniel Viau
+ * @custom:version 1.6-reference
* @notice Consideration is a generalized native token/ERC20/ERC721/ERC1155
* marketplace. It minimizes external calls to the greatest extent
* possible and provides lightweight methods for common routes as well
diff --git a/reference/conduit/ReferenceConduit.sol b/reference/conduit/ReferenceConduit.sol
index 617558799..db655be09 100644
--- a/reference/conduit/ReferenceConduit.sol
+++ b/reference/conduit/ReferenceConduit.sol
@@ -5,7 +5,9 @@ import {
ConduitInterface
} from "seaport-types/src/interfaces/ConduitInterface.sol";
-import { ConduitItemType } from "seaport-types/src/conduit/lib/ConduitEnums.sol";
+import {
+ ConduitItemType
+} from "seaport-types/src/conduit/lib/ConduitEnums.sol";
import {
ReferenceTokenTransferrer
diff --git a/reference/lib/ReferenceAssertions.sol b/reference/lib/ReferenceAssertions.sol
index 7e6a67290..b83c59eda 100644
--- a/reference/lib/ReferenceAssertions.sol
+++ b/reference/lib/ReferenceAssertions.sol
@@ -1,7 +1,9 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
-import { OrderParameters } from "seaport-types/src/lib/ConsiderationStructs.sol";
+import {
+ OrderParameters
+} from "seaport-types/src/lib/ConsiderationStructs.sol";
import { ReferenceGettersAndDerivers } from "./ReferenceGettersAndDerivers.sol";
@@ -35,7 +37,7 @@ contract ReferenceAssertions is
) ReferenceGettersAndDerivers(conduitController) {}
/**
- * @dev Internal view function to to ensure that the supplied consideration
+ * @dev Internal view function to ensure that the supplied consideration
* array length on a given set of order parameters is not less than the
* original consideration array length for that order and to retrieve
* the current counter for a given order's offerer and zone and use it
diff --git a/reference/lib/ReferenceBasicOrderFulfiller.sol b/reference/lib/ReferenceBasicOrderFulfiller.sol
index 508cf8d20..6ac84bead 100644
--- a/reference/lib/ReferenceBasicOrderFulfiller.sol
+++ b/reference/lib/ReferenceBasicOrderFulfiller.sol
@@ -815,6 +815,15 @@ contract ReferenceBasicOrderFulfiller is ReferenceOrderValidator {
);
}
+ // Determine whether order is restricted and, if so, that it is valid.
+ _assertRestrictedBasicOrderAuthorization(
+ hashes.orderHash,
+ orderType,
+ parameters,
+ offeredItemType,
+ receivedItemType
+ );
+
// Verify and update the status of the derived order.
_validateBasicOrderAndUpdateStatus(
hashes.orderHash,
diff --git a/reference/lib/ReferenceConsiderationBase.sol b/reference/lib/ReferenceConsiderationBase.sol
index 684d3d4de..4ec28ca62 100644
--- a/reference/lib/ReferenceConsiderationBase.sol
+++ b/reference/lib/ReferenceConsiderationBase.sol
@@ -25,7 +25,7 @@ contract ReferenceConsiderationBase is
{
// Declare constants for name, version, and reentrancy sentinel values.
string internal constant _NAME = "Consideration";
- string internal constant _VERSION = "1.5-reference";
+ string internal constant _VERSION = "1.6-reference";
uint256 internal constant _NOT_ENTERED = 1;
uint256 internal constant _ENTERED = 2;
diff --git a/reference/lib/ReferenceConsiderationStructs.sol b/reference/lib/ReferenceConsiderationStructs.sol
index 5d395585c..f90a427a2 100644
--- a/reference/lib/ReferenceConsiderationStructs.sol
+++ b/reference/lib/ReferenceConsiderationStructs.sol
@@ -1,17 +1,52 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
-import { ItemType, OrderType } from "seaport-types/src/lib/ConsiderationEnums.sol";
+import {
+ ItemType,
+ OrderType
+} from "seaport-types/src/lib/ConsiderationEnums.sol";
import {
ReceivedItem,
SpentItem
} from "seaport-types/src/lib/ConsiderationStructs.sol";
-import { ConduitTransfer } from "seaport-types/src/conduit/lib/ConduitStructs.sol";
+import {
+ ConduitTransfer
+} from "seaport-types/src/conduit/lib/ConduitStructs.sol";
// This file should only be used by the Reference Implementation
+/**
+ * @dev A struct used to hold the numerator and denominator of an order in-memory
+ * during validation, before it is written to storage when updating order
+ * status.
+ */
+struct StoredFractions {
+ uint256 storedNumerator;
+ uint256 storedDenominator;
+}
+
+/**
+ * @dev An intermediate struct used to hold information about an order after
+ * validation to prepare for execution.
+ */
+struct OrderValidation {
+ bytes32 orderHash;
+ uint256 newNumerator;
+ uint256 newDenominator;
+ OrderToExecute orderToExecute;
+}
+
+/**
+ * @dev A struct used to hold the parameters used to validate an order.
+ */
+struct OrderValidationParams {
+ bool revertOnInvalid;
+ uint256 maximumFulfilled;
+ address recipient;
+}
+
/**
* @dev A struct used to hold Consideration Indexes and Fulfillment validity.
*/
diff --git a/reference/lib/ReferenceCriteriaResolution.sol b/reference/lib/ReferenceCriteriaResolution.sol
index ceb69772a..e592a436c 100644
--- a/reference/lib/ReferenceCriteriaResolution.sol
+++ b/reference/lib/ReferenceCriteriaResolution.sol
@@ -1,7 +1,11 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
-import { ItemType, Side } from "seaport-types/src/lib/ConsiderationEnums.sol";
+import {
+ ItemType,
+ OrderType,
+ Side
+} from "seaport-types/src/lib/ConsiderationEnums.sol";
import {
AdvancedOrder,
@@ -41,6 +45,7 @@ contract ReferenceCriteriaResolution is CriteriaResolutionErrors {
* that no proof needs to be supplied.
*/
function _applyCriteriaResolvers(
+ AdvancedOrder[] memory advancedOrders,
OrderToExecute[] memory ordersToExecute,
CriteriaResolver[] memory criteriaResolvers
) internal pure {
@@ -171,7 +176,13 @@ contract ReferenceCriteriaResolution is CriteriaResolutionErrors {
if (
_isItemWithCriteria(orderToExecute.spentItems[j].itemType)
) {
- revert UnresolvedOfferCriteria(i, j);
+ if (
+ advancedOrders[i].parameters.orderType !=
+ OrderType.CONTRACT ||
+ orderToExecute.spentItems[j].identifier != 0
+ ) {
+ revert UnresolvedOfferCriteria(i, j);
+ }
}
}
@@ -186,7 +197,13 @@ contract ReferenceCriteriaResolution is CriteriaResolutionErrors {
orderToExecute.receivedItems[j].itemType
)
) {
- revert UnresolvedConsiderationCriteria(i, j);
+ if (
+ advancedOrders[i].parameters.orderType !=
+ OrderType.CONTRACT ||
+ orderToExecute.receivedItems[j].identifier != 0
+ ) {
+ revert UnresolvedConsiderationCriteria(i, j);
+ }
}
}
}
@@ -321,7 +338,16 @@ contract ReferenceCriteriaResolution is CriteriaResolutionErrors {
advancedOrder.parameters.consideration[i].itemType
)
) {
- revert UnresolvedConsiderationCriteria(0, i);
+ if (
+ advancedOrder.parameters.orderType != OrderType.CONTRACT ||
+ advancedOrder
+ .parameters
+ .consideration[i]
+ .identifierOrCriteria !=
+ 0
+ ) {
+ revert UnresolvedConsiderationCriteria(0, i);
+ }
}
}
@@ -334,7 +360,12 @@ contract ReferenceCriteriaResolution is CriteriaResolutionErrors {
if (
_isItemWithCriteria(advancedOrder.parameters.offer[i].itemType)
) {
- revert UnresolvedOfferCriteria(0, i);
+ if (
+ advancedOrder.parameters.orderType != OrderType.CONTRACT ||
+ advancedOrder.parameters.offer[i].identifierOrCriteria != 0
+ ) {
+ revert UnresolvedOfferCriteria(0, i);
+ }
}
}
}
diff --git a/reference/lib/ReferenceExecutor.sol b/reference/lib/ReferenceExecutor.sol
index 2bc513932..6bfbbc8e8 100644
--- a/reference/lib/ReferenceExecutor.sol
+++ b/reference/lib/ReferenceExecutor.sol
@@ -1,13 +1,17 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
-import { ConduitItemType } from "seaport-types/src/conduit/lib/ConduitEnums.sol";
+import {
+ ConduitItemType
+} from "seaport-types/src/conduit/lib/ConduitEnums.sol";
import {
ConduitInterface
} from "seaport-types/src/interfaces/ConduitInterface.sol";
-import { ConduitTransfer } from "seaport-types/src/conduit/lib/ConduitStructs.sol";
+import {
+ ConduitTransfer
+} from "seaport-types/src/conduit/lib/ConduitStructs.sol";
import { ItemType } from "seaport-types/src/lib/ConsiderationEnums.sol";
diff --git a/reference/lib/ReferenceFulfillmentApplier.sol b/reference/lib/ReferenceFulfillmentApplier.sol
index 3bbad4b67..9d7268ddc 100644
--- a/reference/lib/ReferenceFulfillmentApplier.sol
+++ b/reference/lib/ReferenceFulfillmentApplier.sol
@@ -79,12 +79,6 @@ contract ReferenceFulfillmentApplier is
// Skip aggregating offer items if no consideration items are available.
if (considerationItem.amount == 0) {
- // Set the offerer and recipient to null address and item type to a
- // non-native item type if execution amount is zero. This will cause
- // the execution item to be skipped.
- execution.offerer = address(0);
- execution.item.recipient = payable(0);
- execution.item.itemType = ItemType.ERC20;
return execution;
}
@@ -141,11 +135,14 @@ contract ReferenceFulfillmentApplier is
}
// Reuse execution struct with consideration amount and recipient.
+ // Only set the recipient if the item amount is non-zero.
execution.item.amount = considerationItem.amount;
- execution.item.recipient = considerationItem.recipient;
+ if (execution.item.amount != 0) {
+ execution.item.recipient = considerationItem.recipient;
+ }
// Return the final execution that will be triggered for relevant items.
- return execution; // Execution(considerationItem, offerer, conduitKey);
+ return execution; // Execution(execution, offerer, conduitKey);
}
/**
@@ -204,21 +201,6 @@ contract ReferenceFulfillmentApplier is
);
}
- if (execution.item.amount == 0) {
- return
- Execution(
- ReceivedItem(
- ItemType.ERC20,
- address(0),
- 0,
- 0,
- payable(address(0))
- ),
- address(0),
- bytes32(0)
- );
- }
-
return execution;
}
@@ -395,12 +377,21 @@ contract ReferenceFulfillmentApplier is
)
);
- // Return execution for aggregated items provided by the fulfiller.
- execution = Execution(
- receiveConsiderationItem,
- msg.sender,
- fulfillerConduitKey
- );
+ if (receiveConsiderationItem.amount != 0) {
+ // Return execution for aggregated items provided by the fulfiller.
+ execution = Execution(
+ receiveConsiderationItem,
+ msg.sender,
+ fulfillerConduitKey
+ );
+ } else {
+ // Return an empty execution if the received item amount is zero.
+ execution = Execution(
+ receiveConsiderationItem,
+ address(0),
+ bytes32(0)
+ );
+ }
}
/**
diff --git a/reference/lib/ReferenceOrderCombiner.sol b/reference/lib/ReferenceOrderCombiner.sol
index 043051b01..88b03c15c 100644
--- a/reference/lib/ReferenceOrderCombiner.sol
+++ b/reference/lib/ReferenceOrderCombiner.sol
@@ -20,19 +20,22 @@ import {
SpentItem
} from "seaport-types/src/lib/ConsiderationStructs.sol";
+import {
+ SeaportInterface
+} from "seaport-types/src/interfaces/SeaportInterface.sol";
+
import {
AccumulatorStruct,
- OrderToExecute
+ OrderToExecute,
+ StoredFractions,
+ OrderValidation,
+ OrderValidationParams
} from "./ReferenceConsiderationStructs.sol";
import { ReferenceOrderFulfiller } from "./ReferenceOrderFulfiller.sol";
import { ReferenceFulfillmentApplier } from "./ReferenceFulfillmentApplier.sol";
-import {
- SeaportInterface
-} from "seaport-types/src/interfaces/SeaportInterface.sol";
-
/**
* @title OrderCombiner
* @author 0age
@@ -142,14 +145,19 @@ contract ReferenceOrderCombiner is
returns (bool[] memory availableOrders, Execution[] memory executions)
{
// Validate orders, apply amounts, & determine if they use conduits.
- (bytes32[] memory orderHashes, bool containsNonOpen) = _validateOrdersAndPrepareToFulfill(
- advancedOrders,
- ordersToExecute,
- criteriaResolvers,
- false, // Signifies that invalid orders should NOT revert.
- maximumFulfilled,
- recipient
- );
+ (
+ bytes32[] memory orderHashes,
+ bool containsNonOpen
+ ) = _validateOrdersAndPrepareToFulfill(
+ advancedOrders,
+ ordersToExecute,
+ criteriaResolvers,
+ OrderValidationParams(
+ false, // Signifies that invalid orders should NOT revert.
+ maximumFulfilled,
+ recipient
+ )
+ );
// Execute transfers.
(availableOrders, executions) = _executeAvailableFulfillments(
@@ -183,11 +191,7 @@ contract ReferenceOrderCombiner is
* a root of zero indicates that any transferable
* token identifier is valid and that no proof
* needs to be supplied.
- * @param revertOnInvalid A boolean indicating whether to revert on any
- * order being invalid; setting this to false will
- * instead cause the invalid order to be skipped.
- * @param maximumFulfilled The maximum number of orders to fulfill.
- * @param recipient The intended recipient for all received items.
+ * @param orderValidationParams Various order validation params.
*
* @return orderHashes The hashes of the orders being fulfilled.
* @return containsNonOpen A boolean indicating whether any restricted or
@@ -198,65 +202,51 @@ contract ReferenceOrderCombiner is
AdvancedOrder[] memory advancedOrders,
OrderToExecute[] memory ordersToExecute,
CriteriaResolver[] memory criteriaResolvers,
- bool revertOnInvalid,
- uint256 maximumFulfilled,
- address recipient
+ OrderValidationParams memory orderValidationParams
) internal returns (bytes32[] memory orderHashes, bool containsNonOpen) {
// Track the order hash for each order being fulfilled.
orderHashes = new bytes32[](advancedOrders.length);
- // Determine whether or not order matching is underway.
- bool nonMatchFn = msg.sig !=
- SeaportInterface.matchAdvancedOrders.selector &&
- msg.sig != SeaportInterface.matchOrders.selector;
-
// Declare a variable for tracking whether native offer items are
// present on orders that are not contract orders.
bool anyNativeOfferItemsOnNonContractOrders;
+ StoredFractions[] memory storedFractions = new StoredFractions[](
+ advancedOrders.length
+ );
+
// Iterate over each order.
for (uint256 i = 0; i < advancedOrders.length; ++i) {
// Retrieve the current order.
AdvancedOrder memory advancedOrder = advancedOrders[i];
- // Determine if max number orders have already been fulfilled.
- if (maximumFulfilled == 0) {
- // Mark fill fraction as zero as the order will not be used.
- advancedOrder.numerator = 0;
-
- // Mark fill fraction as zero as the order will not be used.
- ordersToExecute[i].numerator = 0;
-
- // Continue iterating through the remaining orders.
- continue;
- }
-
- // Validate it, update status, and determine fraction to fill.
- (
- bytes32 orderHash,
- uint256 numerator,
- uint256 denominator,
- OrderToExecute memory orderToExecute
- ) = _validateOrderAndUpdateStatus(advancedOrder, revertOnInvalid);
+ // Validate the order and determine fraction to fill.
+ OrderValidation memory orderValidation = _validateOrder(
+ advancedOrder,
+ orderValidationParams.revertOnInvalid
+ );
// Do not track hash or adjust prices if order is not fulfilled.
- if (numerator == 0) {
+ if (orderValidation.newNumerator == 0) {
// Mark fill fraction as zero if the order is not fulfilled.
advancedOrder.numerator = 0;
// Mark fill fraction as zero as the order will not be used.
- orderToExecute.numerator = 0;
- ordersToExecute[i] = orderToExecute;
+ orderValidation.orderToExecute.numerator = 0;
+ ordersToExecute[i] = orderValidation.orderToExecute;
// Continue iterating through the remaining orders.
continue;
}
// Otherwise, track the order hash in question.
- orderHashes[i] = orderHash;
+ orderHashes[i] = orderValidation.orderHash;
- // Decrement the number of fulfilled orders.
- maximumFulfilled--;
+ // Store the numerator and denominator for the order status.
+ storedFractions[i] = StoredFractions({
+ storedNumerator: orderValidation.newNumerator,
+ storedDenominator: orderValidation.newDenominator
+ });
{
// Retrieve array of offer items for the order in question.
@@ -281,8 +271,8 @@ contract ReferenceOrderCombiner is
// Retrieve the offer item.
OfferItem memory offerItem = offer[j];
- // Determine if there are any native offer items on non-contract
- // orders.
+ // Determine if there are any native offer items on
+ // non-contract orders.
anyNativeOfferItemsOnNonContractOrders =
anyNativeOfferItemsOnNonContractOrders ||
(offerItem.itemType == ItemType.NATIVE &&
@@ -290,25 +280,25 @@ contract ReferenceOrderCombiner is
// Apply order fill fraction to offer item end amount.
uint256 endAmount = _getFraction(
- numerator,
- denominator,
+ orderValidation.newNumerator,
+ orderValidation.newDenominator,
offerItem.endAmount
);
- // Reuse same fraction if start and end amounts are equal.
+ // Reuse same fraction if start & end amounts are equal.
if (offerItem.startAmount == offerItem.endAmount) {
- // Apply derived amount to both start and end amount.
+ // Apply derived amount to both start & end amount.
offerItem.startAmount = endAmount;
} else {
- // Apply order fill fraction to offer item start amount.
+ // Apply order fill fraction to item start amount.
offerItem.startAmount = _getFraction(
- numerator,
- denominator,
+ orderValidation.newNumerator,
+ orderValidation.newDenominator,
offerItem.startAmount
);
}
- // Update end amount in memory to match the derived amount.
+ // Update end amount in memory to match derived amount.
offerItem.endAmount = endAmount;
// Adjust offer amount using current time; round down.
@@ -321,16 +311,19 @@ contract ReferenceOrderCombiner is
);
// Modify the OrderToExecute Spent Item Amount.
- orderToExecute.spentItems[j].amount = offerItem
- .startAmount;
- // Modify the OrderToExecute Spent Item Original Amount.
- orderToExecute.spentItemOriginalAmounts[j] = offerItem
- .startAmount;
+ orderValidation
+ .orderToExecute
+ .spentItems[j]
+ .amount = offerItem.startAmount;
+ // Modify the OrderToExecute Spent Item Original amount.
+ orderValidation.orderToExecute.spentItemOriginalAmounts[
+ j
+ ] = (offerItem.startAmount);
}
}
{
- // Retrieve array of consideration items for order in question.
+ // Get array of consideration items for order in question.
ConsiderationItem[] memory consideration = (
advancedOrder.parameters.consideration
);
@@ -344,31 +337,27 @@ contract ReferenceOrderCombiner is
// Apply fraction to consideration item end amount.
uint256 endAmount = _getFraction(
- numerator,
- denominator,
+ orderValidation.newNumerator,
+ orderValidation.newDenominator,
considerationItem.endAmount
);
- // Reuse same fraction if start and end amounts are equal.
+ // Reuse same fraction if start & end amounts are equal.
if (
considerationItem.startAmount ==
- considerationItem.endAmount
+ (considerationItem.endAmount)
) {
- // Apply derived amount to both start and end amount.
+ // Apply derived amount to both start & end amount.
considerationItem.startAmount = endAmount;
} else {
- // Apply fraction to consideration item start amount.
+ // Apply fraction to item start amount.
considerationItem.startAmount = _getFraction(
- numerator,
- denominator,
+ orderValidation.newNumerator,
+ orderValidation.newDenominator,
considerationItem.startAmount
);
}
- // TODO: Check with 0. Appears to be no longer in optimized.
- // // Update end amount in memory to match the derived amount.
- // considerationItem.endAmount = endAmount;
-
uint256 currentAmount = (
_locateCurrentAmount(
considerationItem.startAmount,
@@ -382,58 +371,154 @@ contract ReferenceOrderCombiner is
considerationItem.startAmount = currentAmount;
// Modify the OrderToExecute Received item amount.
- orderToExecute
+ orderValidation
+ .orderToExecute
.receivedItems[j]
.amount = considerationItem.startAmount;
- // Modify the OrderToExecute Received item original amount.
- orderToExecute.receivedItemOriginalAmounts[
- j
- ] = considerationItem.startAmount;
+ // Modify OrderToExecute Received item original amount.
+ orderValidation
+ .orderToExecute
+ .receivedItemOriginalAmounts[j] = (
+ considerationItem.startAmount
+ );
}
}
}
- ordersToExecute[i] = orderToExecute;
+ ordersToExecute[i] = orderValidation.orderToExecute;
}
- if (anyNativeOfferItemsOnNonContractOrders && nonMatchFn) {
+ if (
+ anyNativeOfferItemsOnNonContractOrders &&
+ (msg.sig != SeaportInterface.matchAdvancedOrders.selector &&
+ msg.sig != SeaportInterface.matchOrders.selector)
+ ) {
revert InvalidNativeOfferItem();
}
// Apply criteria resolvers to each order as applicable.
- _applyCriteriaResolvers(ordersToExecute, criteriaResolvers);
+ _applyCriteriaResolvers(
+ advancedOrders,
+ ordersToExecute,
+ criteriaResolvers
+ );
- // Emit an event for each order signifying that it has been fulfilled.
- // Iterate over each order.
+ bool someOrderAvailable;
+
+ // Iterate over each order to check authorization status (for restricted
+ // orders), generate orders (for contract orders), and emit events (for
+ // all available orders) signifying that they have been fulfilled.
for (uint256 i = 0; i < advancedOrders.length; ++i) {
// Do not emit an event if no order hash is present.
if (orderHashes[i] == bytes32(0)) {
continue;
}
+ // Determine if max number orders have already been fulfilled.
+ if (orderValidationParams.maximumFulfilled == 0) {
+ orderHashes[i] = bytes32(0);
+ ordersToExecute[i].numerator = 0;
+
+ // Continue iterating through the remaining orders.
+ continue;
+ }
+
// Retrieve parameters for the order in question.
OrderParameters memory orderParameters = (
advancedOrders[i].parameters
);
+ // Ensure restricted orders have valid submitter or pass zone check.
+ (
+ bool valid /* bool checked */,
+
+ ) = _checkRestrictedAdvancedOrderAuthorization(
+ advancedOrders[i],
+ ordersToExecute[i],
+ _shorten(orderHashes, i),
+ orderHashes[i],
+ orderValidationParams.revertOnInvalid
+ );
+
+ if (!valid) {
+ orderHashes[i] = bytes32(0);
+ ordersToExecute[i].numerator = 0;
+ continue;
+ }
+
+ // Update status if the order is still valid or skip if not checked
+ if (orderParameters.orderType != OrderType.CONTRACT) {
+ if (
+ !_updateStatus(
+ orderHashes[i],
+ storedFractions[i].storedNumerator,
+ storedFractions[i].storedDenominator,
+ _revertOnFailedUpdate(
+ orderParameters,
+ orderValidationParams.revertOnInvalid
+ )
+ )
+ ) {
+ orderHashes[i] = bytes32(0);
+ ordersToExecute[i].numerator = 0;
+ continue;
+ }
+ } else {
+ bytes32 orderHash = _getGeneratedOrder(
+ ordersToExecute[i],
+ orderParameters,
+ advancedOrders[i].extraData,
+ orderValidationParams.revertOnInvalid
+ );
+
+ orderHashes[i] = orderHash;
+
+ if (orderHash == bytes32(0)) {
+ ordersToExecute[i].numerator = 0;
+ continue;
+ }
+ }
+
+ // Decrement the number of fulfilled orders.
+ orderValidationParams.maximumFulfilled--;
+
// Get the array of spentItems from the orderToExecute struct.
SpentItem[] memory spentItems = ordersToExecute[i].spentItems;
// Get the array of spent receivedItems from the
// orderToExecute struct.
- ReceivedItem[] memory receivedItems = ordersToExecute[i]
- .receivedItems;
+ ReceivedItem[] memory receivedItems = (
+ ordersToExecute[i].receivedItems
+ );
// Emit an event signifying that the order has been fulfilled.
emit OrderFulfilled(
orderHashes[i],
orderParameters.offerer,
orderParameters.zone,
- recipient,
+ orderValidationParams.recipient,
spentItems,
receivedItems
);
+
+ someOrderAvailable = true;
}
+
+ // Revert if no orders are available.
+ if (!someOrderAvailable) {
+ revert NoSpecifiedOrdersAvailable();
+ }
+ }
+
+ function _shorten(
+ bytes32[] memory orderHashes,
+ uint256 index
+ ) internal pure returns (bytes32[] memory) {
+ bytes32[] memory shortened = new bytes32[](index);
+ for (uint256 i = 0; i < index; i++) {
+ shortened[i] = orderHashes[i];
+ }
+ return shortened;
}
/**
@@ -521,90 +606,32 @@ contract ReferenceOrderCombiner is
totalOfferFulfillments + totalConsiderationFulfillments
);
- // Track number of filtered executions.
- uint256 totalFilteredExecutions = 0;
-
// Iterate over each offer fulfillment.
for (uint256 i = 0; i < totalOfferFulfillments; ++i) {
- // Derive aggregated execution corresponding with fulfillment.
- Execution memory execution = _aggregateAvailable(
+ // Derive aggregated execution corresponding with fulfillment and
+ // assign the execution to the executions array.
+ executions[i] = _aggregateAvailable(
ordersToExecute,
Side.OFFER,
offerFulfillments[i],
fulfillerConduitKey,
recipient
);
-
- // If offerer and recipient on the execution are the same and the
- // execution item has a non-native item type...
- if (
- execution.item.recipient == execution.offerer &&
- execution.item.itemType != ItemType.NATIVE
- ) {
- // Increment total filtered executions.
- ++totalFilteredExecutions;
- } else {
- // Otherwise, assign the execution to the executions array.
- executions[i - totalFilteredExecutions] = execution;
- }
}
// Iterate over each consideration fulfillment.
for (uint256 i = 0; i < totalConsiderationFulfillments; ++i) {
- // Derive aggregated execution corresponding with fulfillment.
- Execution memory execution = _aggregateAvailable(
+ // Derive aggregated execution corresponding with fulfillment and
+ // assign the execution to the executions array.
+ executions[i + totalOfferFulfillments] = _aggregateAvailable(
ordersToExecute,
Side.CONSIDERATION,
considerationFulfillments[i],
fulfillerConduitKey,
address(0) // unused
);
-
- // If offerer and recipient on the execution are the same and the
- // execution item has a non-native item type...
- if (
- execution.item.recipient == execution.offerer &&
- execution.item.itemType != ItemType.NATIVE
- ) {
- // Increment total filtered executions.
- ++totalFilteredExecutions;
- } else {
- // Otherwise, assign the execution to the executions array.
- executions[
- i + totalOfferFulfillments - totalFilteredExecutions
- ] = execution;
- }
}
- // If some number of executions have been filtered...
- if (totalFilteredExecutions != 0) {
- /**
- * The following is highly inefficient, but written this way
- * to show in the most simplest form what the optimized
- * contract is performing inside its assembly.
- */
-
- // Get the total execution length.
- uint256 executionLength = (totalOfferFulfillments +
- totalConsiderationFulfillments) - totalFilteredExecutions;
-
- // Create an array of executions that will be executed.
- Execution[] memory filteredExecutions = new Execution[](
- executionLength
- );
-
- // Create new array from the existing Executions
- for (uint256 i = 0; i < executionLength; ++i) {
- filteredExecutions[i] = executions[i];
- }
-
- // Set the executions array to the newly created array.
- executions = filteredExecutions;
- }
- // Revert if no orders are available.
- if (executions.length == 0) {
- revert NoSpecifiedOrdersAvailable();
- }
// Perform final checks and compress executions into standard and batch.
availableOrders = _performFinalChecksAndExecuteOrders(
advancedOrders,
@@ -664,6 +691,11 @@ contract ReferenceOrderCombiner is
Execution memory execution = executions[i];
ReceivedItem memory item = execution.item;
+ // Skip transfers if the execution amount is zero.
+ if (item.amount == 0) {
+ continue;
+ }
+
// If execution transfers native tokens, reduce value available.
if (item.itemType == ItemType.NATIVE) {
// Ensure that sufficient native tokens are still available.
@@ -709,23 +741,22 @@ contract ReferenceOrderCombiner is
{
// Retrieve offer items.
- OfferItem[] memory offer = parameters.offer;
+ SpentItem[] memory offer = orderToExecute.spentItems;
// Read length of offer array & place on the stack.
uint256 totalOfferItems = offer.length;
// Iterate over each offer item to restore it.
for (uint256 j = 0; j < totalOfferItems; ++j) {
- SpentItem memory offerSpentItem = orderToExecute.spentItems[
- j
- ];
+ SpentItem memory offerSpentItem = offer[j];
// Retrieve remaining amount on the offer item.
uint256 unspentAmount = offerSpentItem.amount;
// Retrieve original amount on the offer item.
- uint256 originalAmount = orderToExecute
- .spentItemOriginalAmounts[j];
+ uint256 originalAmount = (
+ orderToExecute.spentItemOriginalAmounts[j]
+ );
// Transfer to recipient if unspent amount is not zero.
// Note that the transfer will not be reflected in the
@@ -764,21 +795,9 @@ contract ReferenceOrderCombiner is
}
// Restore original amount.
- consideration[j].amount = orderToExecute
- .receivedItemOriginalAmounts[j];
- }
- }
-
- {
- // Get offer items as well.
- SpentItem[] memory offer = (orderToExecute.spentItems);
-
- // Iterate over each consideration item to ensure it is met.
- for (uint256 j = 0; j < offer.length; ++j) {
- // Restore original amount.
- offer[j].amount = orderToExecute.spentItemOriginalAmounts[
- j
- ];
+ consideration[j].amount = (
+ orderToExecute.receivedItemOriginalAmounts[j]
+ );
}
}
}
@@ -845,6 +864,7 @@ contract ReferenceOrderCombiner is
address recipient
) internal pure returns (ReceivedItem memory) {
address payable _recipient;
+
_recipient = payable(recipient);
return
@@ -902,20 +922,24 @@ contract ReferenceOrderCombiner is
address recipient
) internal returns (Execution[] memory executions) {
// Convert Advanced Orders to Orders to Execute
- OrderToExecute[]
- memory ordersToExecute = _convertAdvancedToOrdersToExecute(
- advancedOrders
- );
+ OrderToExecute[] memory ordersToExecute = (
+ _convertAdvancedToOrdersToExecute(advancedOrders)
+ );
// Validate orders, apply amounts, & determine if they utilize conduits.
- (bytes32[] memory orderHashes, bool containsNonOpen) = _validateOrdersAndPrepareToFulfill(
- advancedOrders,
- ordersToExecute,
- criteriaResolvers,
- true, // Signifies that invalid orders should revert.
- advancedOrders.length,
- recipient
- );
+ (
+ bytes32[] memory orderHashes,
+ bool containsNonOpen
+ ) = _validateOrdersAndPrepareToFulfill(
+ advancedOrders,
+ ordersToExecute,
+ criteriaResolvers,
+ OrderValidationParams(
+ true, // Signifies that invalid orders should revert.
+ advancedOrders.length,
+ recipient
+ )
+ );
// Emit OrdersMatched event.
emit OrdersMatched(orderHashes);
@@ -968,49 +992,19 @@ contract ReferenceOrderCombiner is
// Allocate executions by fulfillment and apply them to each execution.
executions = new Execution[](totalFulfillments);
- // Track number of filtered executions.
- uint256 totalFilteredExecutions = 0;
-
// Iterate over each fulfillment.
for (uint256 i = 0; i < totalFulfillments; ++i) {
/// Retrieve the fulfillment in question.
Fulfillment calldata fulfillment = fulfillments[i];
- // Derive the execution corresponding with the fulfillment.
- Execution memory execution = _applyFulfillment(
+ // Derive the execution corresponding with the fulfillment and
+ // assign the execution to the executions array.
+ executions[i] = _applyFulfillment(
ordersToExecute,
fulfillment.offerComponents,
fulfillment.considerationComponents,
i
);
-
- // If offerer and recipient on the execution are the same and the
- // execution item has a non-native item type...
- if (
- execution.item.recipient == execution.offerer &&
- execution.item.itemType != ItemType.NATIVE
- ) {
- // Increment total filtered executions.
- ++totalFilteredExecutions;
- } else {
- // Otherwise, assign the execution to the executions array.
- executions[i - totalFilteredExecutions] = execution;
- }
- }
-
- // If some number of executions have been filtered...
- if (totalFilteredExecutions != 0) {
- uint256 executionLength = totalFulfillments -
- totalFilteredExecutions;
- Execution[] memory filteredExecutions = new Execution[](
- executionLength
- );
- // Create new array from executions.
- for (uint256 i = 0; i < executionLength; ++i) {
- filteredExecutions[i] = executions[i];
- }
-
- executions = filteredExecutions;
}
// Perform final checks and execute orders.
@@ -1026,4 +1020,32 @@ contract ReferenceOrderCombiner is
// Return executions.
return executions;
}
+
+ /**
+ * @dev Internal view function to determine whether a status update failure
+ * should cause a revert or allow a skipped order. The call must revert
+ * if an `authorizeOrder` call has been successfully performed and the
+ * status update cannot be performed, regardless of whether the order
+ * could be otherwise marked as skipped. Note that a revert is not
+ * required on a failed update if the call originates from the zone, as
+ * no `authorizeOrder` call is performed in that case.
+ *
+ * @param orderParameters The order parameters in question.
+ * @param revertOnInvalid A boolean indicating whether the call should
+ * revert for non-restricted order types.
+ *
+ * @return revertOnFailedUpdate A boolean indicating whether the order
+ * should revert on a failed status update.
+ */
+ function _revertOnFailedUpdate(
+ OrderParameters memory orderParameters,
+ bool revertOnInvalid
+ ) internal view returns (bool revertOnFailedUpdate) {
+ OrderType orderType = orderParameters.orderType;
+ address zone = orderParameters.zone;
+ return (revertOnInvalid ||
+ ((orderType == OrderType.FULL_RESTRICTED ||
+ orderType == OrderType.PARTIAL_RESTRICTED) &&
+ zone != msg.sender));
+ }
}
diff --git a/reference/lib/ReferenceOrderFulfiller.sol b/reference/lib/ReferenceOrderFulfiller.sol
index ae2ba5697..2a05cd9b7 100644
--- a/reference/lib/ReferenceOrderFulfiller.sol
+++ b/reference/lib/ReferenceOrderFulfiller.sol
@@ -1,7 +1,10 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
-import { ItemType, OrderType } from "seaport-types/src/lib/ConsiderationEnums.sol";
+import {
+ ItemType,
+ OrderType
+} from "seaport-types/src/lib/ConsiderationEnums.sol";
import {
AdvancedOrder,
@@ -17,7 +20,8 @@ import {
import {
AccumulatorStruct,
FractionData,
- OrderToExecute
+ OrderToExecute,
+ OrderValidation
} from "./ReferenceConsiderationStructs.sol";
import {
@@ -82,13 +86,11 @@ contract ReferenceOrderFulfiller is
bytes32 fulfillerConduitKey,
address recipient
) internal returns (bool) {
- // Validate order, update status, and determine fraction to fill.
- (
- bytes32 orderHash,
- uint256 fillNumerator,
- uint256 fillDenominator,
- OrderToExecute memory orderToExecute
- ) = _validateOrderAndUpdateStatus(advancedOrder, true);
+ // Validate the order and revert if it's invalid.
+ OrderValidation memory orderValidation = _validateOrder(
+ advancedOrder,
+ true
+ );
// Apply criteria resolvers using generated orders and details arrays.
_applyCriteriaResolversAdvanced(advancedOrder, criteriaResolvers);
@@ -97,24 +99,65 @@ contract ReferenceOrderFulfiller is
OrderParameters memory orderParameters = advancedOrder.parameters;
// Perform each item transfer with the appropriate fractional amount.
- orderToExecute = _applyFractionsAndTransferEach(
+ orderValidation.orderToExecute = _applyFractions(
orderParameters,
- fillNumerator,
- fillDenominator,
+ orderValidation.newNumerator,
+ orderValidation.newDenominator
+ );
+
+ // Declare empty bytes32 array.
+ bytes32[] memory priorOrderHashes = new bytes32[](0);
+
+ if (orderParameters.orderType != OrderType.CONTRACT) {
+ // Ensure restricted orders have valid submitter or pass zone check.
+ _assertRestrictedAdvancedOrderAuthorization(
+ advancedOrder,
+ orderValidation.orderToExecute,
+ priorOrderHashes,
+ orderValidation.orderHash,
+ orderParameters.zoneHash,
+ orderParameters.orderType,
+ orderParameters.offerer,
+ orderParameters.zone
+ );
+
+ // Update the order status to reflect the new numerator and denominator.
+ // Revert if the order is not valid.
+ _updateStatus(
+ orderValidation.orderHash,
+ orderValidation.newNumerator,
+ orderValidation.newDenominator,
+ true
+ );
+ } else {
+ bytes32 orderHash = _getGeneratedOrder(
+ orderValidation.orderToExecute,
+ advancedOrder.parameters,
+ advancedOrder.extraData,
+ true
+ );
+
+ orderValidation.orderHash = orderHash;
+ }
+
+ // Transfer each item contained in the order.
+ _transferEach(
+ orderParameters,
+ orderValidation.orderToExecute,
fulfillerConduitKey,
recipient
);
// Declare bytes32 array with this order's hash
- bytes32[] memory priorOrderHashes = new bytes32[](1);
- priorOrderHashes[0] = orderHash;
+ priorOrderHashes = new bytes32[](1);
+ priorOrderHashes[0] = orderValidation.orderHash;
- // Ensure restricted orders have a valid submitter or pass a zone check.
+ // Ensure restricted orders have valid submitter or pass zone check.
_assertRestrictedAdvancedOrderValidity(
advancedOrder,
- orderToExecute,
+ orderValidation.orderToExecute,
priorOrderHashes,
- orderHash,
+ orderValidation.orderHash,
orderParameters.zoneHash,
orderParameters.orderType,
orderParameters.offerer,
@@ -123,65 +166,47 @@ contract ReferenceOrderFulfiller is
// Emit an event signifying that the order has been fulfilled.
emit OrderFulfilled(
- orderHash,
+ orderValidation.orderHash,
orderParameters.offerer,
orderParameters.zone,
recipient,
- orderToExecute.spentItems,
- orderToExecute.receivedItems
+ orderValidation.orderToExecute.spentItems,
+ orderValidation.orderToExecute.receivedItems
);
return true;
}
/**
- * @dev Internal function to transfer each item contained in a given single
- * order fulfillment after applying a respective fraction to the amount
- * being transferred.
+ * @dev Internal view function to apply a respective fraction to the
+ * amount being transferred on each item of an order.
*
* @param orderParameters The parameters for the fulfilled order.
* @param numerator A value indicating the portion of the order
* that should be filled.
* @param denominator A value indicating the total order size.
- * @param fulfillerConduitKey A bytes32 value indicating what conduit, if
- * any, to source the fulfiller's token approvals
- * from. The zero hash signifies that no conduit
- * should be used (and direct approvals set on
- * Consideration).
- * @param recipient The intended recipient for all received items.
- * @return orderToExecute Returns the order of items that are being
+ * @return orderToExecute Returns the order with items that are being
* transferred. This will be used for the
* OrderFulfilled Event.
*/
- function _applyFractionsAndTransferEach(
+ function _applyFractions(
OrderParameters memory orderParameters,
uint256 numerator,
- uint256 denominator,
- bytes32 fulfillerConduitKey,
- address recipient
- ) internal returns (OrderToExecute memory orderToExecute) {
+ uint256 denominator
+ ) internal view returns (OrderToExecute memory orderToExecute) {
// Derive order duration, time elapsed, and time remaining.
// Store in memory to avoid stack too deep issues.
FractionData memory fractionData = FractionData(
numerator,
denominator,
- fulfillerConduitKey,
+ 0, // fulfillerConduitKey is not used here.
orderParameters.startTime,
orderParameters.endTime
);
- // Create the accumulator struct.
- AccumulatorStruct memory accumulatorStruct;
-
- // Get the offerer of the order.
- address offerer = orderParameters.offerer;
-
- // Get the conduitKey of the order
- bytes32 conduitKey = orderParameters.conduitKey;
-
// Create the array to store the spent items for event.
- orderToExecute.spentItems = new SpentItem[](
- orderParameters.offer.length
+ orderToExecute.spentItems = (
+ new SpentItem[](orderParameters.offer.length)
);
// Declare a nested scope to minimize stack depth.
@@ -208,31 +233,19 @@ contract ReferenceOrderFulfiller is
false
);
- // Create Received Item from Offer Item for transfer.
- ReceivedItem memory receivedItem = ReceivedItem(
+ // Create Spent Item for the OrderFulfilled event.
+ orderToExecute.spentItems[i] = SpentItem(
offerItem.itemType,
offerItem.token,
offerItem.identifierOrCriteria,
- amount,
- payable(recipient)
- );
-
- // Create Spent Item for the OrderFulfilled event.
- orderToExecute.spentItems[i] = SpentItem(
- receivedItem.itemType,
- receivedItem.token,
- receivedItem.identifier,
amount
);
-
- // Transfer the item from the offerer to the recipient.
- _transfer(receivedItem, offerer, conduitKey, accumulatorStruct);
}
}
// Create the array to store the received items for event.
- orderToExecute.receivedItems = new ReceivedItem[](
- orderParameters.consideration.length
+ orderToExecute.receivedItems = (
+ new ReceivedItem[](orderParameters.consideration.length)
);
// Declare a nested scope to minimize stack depth.
@@ -252,20 +265,82 @@ contract ReferenceOrderFulfiller is
true
);
- // Create Received Item from Offer item.
- ReceivedItem memory receivedItem = ReceivedItem(
+ // Create Received Item from Offer item & add to structs array.
+ orderToExecute.receivedItems[i] = ReceivedItem(
considerationItem.itemType,
considerationItem.token,
considerationItem.identifierOrCriteria,
amount,
considerationItem.recipient
);
- // Add ReceivedItem to structs array.
- orderToExecute.receivedItems[i] = receivedItem;
+ }
+ }
+
+ // Return the order to execute.
+ return orderToExecute;
+ }
+
+ /**
+ * @dev Internal function to transfer each item contained in a given single
+ * order fulfillment.
+ *
+ * @param orderParameters The parameters for the fulfilled order.
+ * @param orderToExecute The items that are being transferred.
+ * @param fulfillerConduitKey A bytes32 value indicating what conduit, if
+ * any, to source the fulfiller's token approvals
+ * from. The zero hash signifies that no conduit
+ * should be used (and direct approvals set on
+ * Consideration).
+ * @param recipient The intended recipient for all received items.
+ */
+ function _transferEach(
+ OrderParameters memory orderParameters,
+ OrderToExecute memory orderToExecute,
+ bytes32 fulfillerConduitKey,
+ address recipient
+ ) internal {
+ // Create the accumulator struct.
+ AccumulatorStruct memory accumulatorStruct;
+
+ // Get the offerer of the order.
+ address offerer = orderParameters.offerer;
+
+ // Get the conduitKey of the order
+ bytes32 conduitKey = orderParameters.conduitKey;
+
+ // Declare a nested scope to minimize stack depth.
+ {
+ // Iterate over each spent item on the order.
+ for (uint256 i = 0; i < orderToExecute.spentItems.length; ++i) {
+ // Retrieve the spent item.
+ SpentItem memory spentItem = orderToExecute.spentItems[i];
+
+ // Create Received Item from Spent Item for transfer.
+ ReceivedItem memory receivedItem = ReceivedItem(
+ spentItem.itemType,
+ spentItem.token,
+ spentItem.identifier,
+ spentItem.amount,
+ payable(recipient)
+ );
+
+ // Transfer the item from the offerer to the recipient.
+ _transfer(receivedItem, offerer, conduitKey, accumulatorStruct);
+ }
+ }
+
+ // Declare a nested scope to minimize stack depth.
+ {
+ // Iterate over each received item on the order.
+ for (uint256 i = 0; i < orderToExecute.receivedItems.length; ++i) {
+ // Retrieve the received item.
+ ReceivedItem memory receivedItem = (
+ orderToExecute.receivedItems[i]
+ );
if (receivedItem.itemType == ItemType.NATIVE) {
// Ensure that sufficient native tokens are still available.
- if (amount > address(this).balance) {
+ if (receivedItem.amount > address(this).balance) {
revert InsufficientNativeTokensSupplied();
}
}
@@ -274,7 +349,7 @@ contract ReferenceOrderFulfiller is
_transfer(
receivedItem,
msg.sender,
- fractionData.fulfillerConduitKey,
+ fulfillerConduitKey,
accumulatorStruct
);
}
@@ -283,13 +358,11 @@ contract ReferenceOrderFulfiller is
// Trigger any remaining accumulated transfers via call to the conduit.
_triggerIfArmed(accumulatorStruct);
- // If any native token remains after fulfillments...
+ // If any native tokens remain after applying fulfillments...
if (address(this).balance != 0) {
- // return it to the caller.
+ // return them to the caller.
_transferNativeTokens(payable(msg.sender), address(this).balance);
}
- // Return the order to execute.
- return orderToExecute;
}
/**
diff --git a/reference/lib/ReferenceOrderValidator.sol b/reference/lib/ReferenceOrderValidator.sol
index 56bf3180e..4c40b7ada 100644
--- a/reference/lib/ReferenceOrderValidator.sol
+++ b/reference/lib/ReferenceOrderValidator.sol
@@ -1,7 +1,10 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
-import { OrderType, ItemType } from "seaport-types/src/lib/ConsiderationEnums.sol";
+import {
+ OrderType,
+ ItemType
+} from "seaport-types/src/lib/ConsiderationEnums.sol";
import {
AdvancedOrder,
@@ -27,7 +30,10 @@ import {
ReferenceGenerateOrderReturndataDecoder
} from "./ReferenceGenerateOrderReturndataDecoder.sol";
-import { OrderToExecute } from "./ReferenceConsiderationStructs.sol";
+import {
+ OrderToExecute,
+ OrderValidation
+} from "./ReferenceConsiderationStructs.sol";
/**
* @title OrderValidator
@@ -94,9 +100,9 @@ contract ReferenceOrderValidator is
}
/**
- * @dev Internal function to validate an order, determine what portion to
- * fill, and update its status. The desired fill amount is supplied as
- * a fraction, as is the returned amount to fill.
+ * @dev Internal function to validate an order and determine what portion to
+ * fill. The desired fill amount is supplied as a fraction, as is the
+ * returned amount to fill.
*
* @param advancedOrder The order to fulfill as well as the fraction to
* fill. Note that all offer and consideration
@@ -105,23 +111,13 @@ contract ReferenceOrderValidator is
* @param revertOnInvalid A boolean indicating whether to revert if the
* order is invalid due to the time or order status.
*
- * @return orderHash The order hash.
- * @return newNumerator A value indicating the portion of the order that
- * will be filled.
- * @return newDenominator A value indicating the total size of the order.
+ * @return orderValidation The order validation details, including the fill
+ * amount.
*/
- function _validateOrderAndUpdateStatus(
+ function _validateOrder(
AdvancedOrder memory advancedOrder,
bool revertOnInvalid
- )
- internal
- returns (
- bytes32 orderHash,
- uint256 newNumerator,
- uint256 newDenominator,
- OrderToExecute memory orderToExecute
- )
- {
+ ) internal view returns (OrderValidation memory orderValidation) {
// Retrieve the parameters for the order.
OrderParameters memory orderParameters = advancedOrder.parameters;
@@ -134,12 +130,13 @@ contract ReferenceOrderValidator is
)
) {
// Assuming an invalid time and no revert, return zeroed out values.
- return (
- bytes32(0),
- 0,
- 0,
- _convertAdvancedToOrder(orderParameters, 0)
- );
+ return
+ OrderValidation(
+ bytes32(0),
+ 0,
+ 0,
+ _convertAdvancedToOrder(orderParameters, 0)
+ );
}
// Read numerator and denominator from memory and place on the stack.
@@ -154,10 +151,11 @@ contract ReferenceOrderValidator is
}
return
- _getGeneratedOrder(
- orderParameters,
- advancedOrder.extraData,
- revertOnInvalid
+ OrderValidation(
+ bytes32(uint256(1)),
+ 1,
+ 1,
+ _convertAdvancedToOrder(orderParameters, 1)
);
}
@@ -177,34 +175,40 @@ contract ReferenceOrderValidator is
}
// Retrieve current counter and use it w/ parameters to get order hash.
- orderHash = _assertConsiderationLengthAndGetOrderHash(orderParameters);
+ orderValidation.orderHash = (
+ _assertConsiderationLengthAndGetOrderHash(orderParameters)
+ );
// Retrieve the order status using the derived order hash.
- OrderStatus storage orderStatus = _orderStatus[orderHash];
+ OrderStatus storage orderStatus = (
+ _orderStatus[orderValidation.orderHash]
+ );
// Ensure order is fillable and is not cancelled.
if (
+ // Allow partially used orders to be filled.
!_verifyOrderStatus(
- orderHash,
+ orderValidation.orderHash,
orderStatus,
- false, // Allow partially used orders to be filled.
+ false,
revertOnInvalid
)
) {
// Assuming an invalid order status and no revert, return zero fill.
- return (
- orderHash,
- 0,
- 0,
- _convertAdvancedToOrder(orderParameters, 0)
- );
+ return
+ OrderValidation(
+ orderValidation.orderHash,
+ 0,
+ 0,
+ _convertAdvancedToOrder(orderParameters, 0)
+ );
}
// If the order is not already validated, verify the supplied signature.
if (!orderStatus.isValidated) {
_verifySignature(
orderParameters.offerer,
- orderHash,
+ orderValidation.orderHash,
advancedOrder.signature
);
}
@@ -260,6 +264,91 @@ contract ReferenceOrderValidator is
uint256 maxOverhead = type(uint256).max - type(uint120).max;
((filledNumerator + maxOverhead) & (denominator + maxOverhead));
}
+ }
+
+ // Return order hash, new numerator and denominator.
+ return
+ OrderValidation(
+ orderValidation.orderHash,
+ uint120(numerator),
+ uint120(denominator),
+ _convertAdvancedToOrder(orderParameters, uint120(numerator))
+ );
+ }
+
+ /**
+ * @dev Internal function to update an order's status.
+ *
+ * @param orderHash The hash of the order.
+ * @param numerator The numerator of the fraction to fill.
+ * @param denominator The denominator of the fraction to fill.
+ * @param revertOnInvalid Whether to revert on invalid input.
+ *
+ * @return valid A boolean indicating whether the order is valid.
+ */
+ function _updateStatus(
+ bytes32 orderHash,
+ uint256 numerator,
+ uint256 denominator,
+ bool revertOnInvalid
+ ) internal returns (bool valid) {
+ if (numerator == 0) {
+ return false;
+ }
+
+ // Retrieve the order status using the provided order hash.
+ OrderStatus storage orderStatus = _orderStatus[orderHash];
+
+ // Read filled amount as numerator and denominator and put on the stack.
+ uint256 filledNumerator = uint256(orderStatus.numerator);
+ uint256 filledDenominator = uint256(orderStatus.denominator);
+
+ // If order currently has a non-zero denominator it is partially filled.
+ if (filledDenominator != 0) {
+ // if supplied denominator differs from current one...
+ if (filledDenominator != denominator) {
+ // scale current numerator by the supplied denominator, then...
+ filledNumerator *= denominator;
+
+ // the supplied numerator & denominator by current denominator.
+ numerator *= filledDenominator;
+ denominator *= filledDenominator;
+ }
+
+ // Once adjusted, if current+supplied numerator exceeds
+ // denominator...
+ if (filledNumerator + numerator > denominator) {
+ // Revert or return false, which indicates that the order is
+ // invalid.
+ if (revertOnInvalid) {
+ revert OrderAlreadyFilled(orderHash);
+ } else {
+ return false;
+ }
+ }
+
+ // Increment the filled numerator by the new numerator.
+ filledNumerator += numerator;
+
+ // Ensure fractional amounts are below max uint120.
+ if (
+ filledNumerator > type(uint120).max ||
+ denominator > type(uint120).max
+ ) {
+ // Derive greatest common divisor using euclidean algorithm.
+ uint256 scaleDown = _greatestCommonDivisor(
+ filledNumerator,
+ denominator
+ );
+
+ // Scale new filled fractional values down by gcd.
+ filledNumerator = filledNumerator / scaleDown;
+ denominator = denominator / scaleDown;
+
+ // Perform the overflow check a second time.
+ uint256 maxOverhead = type(uint256).max - type(uint120).max;
+ ((filledNumerator + maxOverhead) & (denominator + maxOverhead));
+ }
// Update order status and fill amount, packing struct values.
orderStatus.isValidated = true;
@@ -267,20 +356,16 @@ contract ReferenceOrderValidator is
orderStatus.numerator = uint120(filledNumerator);
orderStatus.denominator = uint120(denominator);
} else {
- // Update order status and fill amount, packing struct values.
+ // If the order currently has a zero denominator, it is not
+ // partially filled. Update the order status and fill amount,
+ // packing struct values.
orderStatus.isValidated = true;
orderStatus.isCancelled = false;
orderStatus.numerator = uint120(numerator);
orderStatus.denominator = uint120(denominator);
}
- // Return order hash, new numerator and denominator.
- return (
- orderHash,
- uint120(numerator),
- uint120(denominator),
- _convertAdvancedToOrder(orderParameters, uint120(numerator))
- );
+ return true;
}
function _callGenerateOrder(
@@ -312,27 +397,19 @@ contract ReferenceOrderValidator is
* identifierOrCriteria = 0, Seaport does not expect a corresponding
* CriteriaResolver, and will revert if one is provided.
*
+ * @param orderToExecute The order to execute.
* @param orderParameters The parameters for the order.
* @param context The context for generating the order.
* @param revertOnInvalid Whether to revert on invalid input.
*
* @return orderHash The order hash.
- * @return numerator The numerator.
- * @return denominator The denominator.
*/
function _getGeneratedOrder(
+ OrderToExecute memory orderToExecute,
OrderParameters memory orderParameters,
bytes memory context,
bool revertOnInvalid
- )
- internal
- returns (
- bytes32 orderHash,
- uint256 numerator,
- uint256 denominator,
- OrderToExecute memory orderToExecute
- )
- {
+ ) internal returns (bytes32 orderHash) {
// Ensure that consideration array length is equal to the total original
// consideration items value.
if (
@@ -343,13 +420,10 @@ contract ReferenceOrderValidator is
}
// Convert offer and consideration to spent and received items.
- (
- SpentItem[] memory originalOfferItems,
- SpentItem[] memory originalConsiderationItems
- ) = _convertToSpent(
- orderParameters.offer,
- orderParameters.consideration
- );
+ SpentItem[] memory originalOfferItems = orderToExecute.spentItems;
+ SpentItem[] memory originalConsiderationItems = _convertToSpent(
+ orderToExecute.receivedItems
+ );
// Create arrays for returned offer and consideration items.
SpentItem[] memory offer;
@@ -398,13 +472,15 @@ contract ReferenceOrderValidator is
}
} else {
// If the call fails, revert or return empty.
- return _revertOrReturnEmpty(revertOnInvalid, orderHash);
+ (orderHash, orderToExecute) = _revertOrReturnEmpty(
+ revertOnInvalid,
+ orderHash
+ );
+ return orderHash;
}
}
{
- orderToExecute = _convertAdvancedToOrder(orderParameters, 1);
-
// Designate lengths.
uint256 originalOfferLength = orderParameters.offer.length;
uint256 newOfferLength = offer.length;
@@ -412,50 +488,13 @@ contract ReferenceOrderValidator is
// Explicitly specified offer items cannot be removed.
if (originalOfferLength > newOfferLength) {
revert InvalidContractOrder(orderHash);
- } else if (newOfferLength > originalOfferLength) {
- {
- // If new offer items are added, extend the original offer.
- OfferItem[] memory extendedOffer = new OfferItem[](
- newOfferLength
- );
- // Copy original offer items to new array.
- for (uint256 i = 0; i < originalOfferLength; ++i) {
- extendedOffer[i] = orderParameters.offer[i];
- }
- // Update order parameters with extended offer.
- orderParameters.offer = extendedOffer;
- }
- {
- // Do the same for ordersToExecute arrays.
- SpentItem[] memory extendedSpent = new SpentItem[](
- newOfferLength
- );
- uint256[]
- memory extendedSpentItemOriginalAmounts = new uint256[](
- newOfferLength
- );
-
- // Copy original spent items to new array.
- for (uint256 i = 0; i < originalOfferLength; ++i) {
- extendedSpent[i] = orderToExecute.spentItems[i];
- extendedSpentItemOriginalAmounts[i] = orderToExecute
- .spentItemOriginalAmounts[i];
- }
-
- // Update order to execute with extended items.
- orderToExecute.spentItems = extendedSpent;
- orderToExecute
- .spentItemOriginalAmounts = extendedSpentItemOriginalAmounts;
- }
-
- {}
}
// Loop through each new offer and ensure the new amounts are at
// least as much as the respective original amounts.
for (uint256 i = 0; i < originalOfferLength; ++i) {
// Designate original and new offer items.
- OfferItem memory originalOffer = orderParameters.offer[i];
+ SpentItem memory originalOffer = orderToExecute.spentItems[i];
SpentItem memory newOffer = offer[i];
// Set returned identifier for criteria-based items with
@@ -466,55 +505,40 @@ contract ReferenceOrderValidator is
// CriteriaResolver.
if (
uint256(originalOffer.itemType) > 3 &&
- originalOffer.identifierOrCriteria == 0
+ originalOffer.identifier == 0
) {
originalOffer.itemType = ItemType(
uint256(originalOffer.itemType) - 2
);
- originalOffer.identifierOrCriteria = newOffer.identifier;
+ originalOffer.identifier = newOffer.identifier;
}
// Ensure the original and generated items are compatible.
if (
- originalOffer.startAmount != originalOffer.endAmount ||
- originalOffer.endAmount > newOffer.amount ||
+ originalOffer.amount > newOffer.amount ||
originalOffer.itemType != newOffer.itemType ||
originalOffer.token != newOffer.token ||
- originalOffer.identifierOrCriteria != newOffer.identifier
+ originalOffer.identifier != newOffer.identifier
) {
revert InvalidContractOrder(orderHash);
}
-
- // Update the original amounts to use the generated amounts.
- originalOffer.startAmount = newOffer.amount;
- originalOffer.endAmount = newOffer.amount;
- orderToExecute.spentItems[i].amount = newOffer.amount;
- orderToExecute.spentItemOriginalAmounts[i] = newOffer.amount;
}
- // Add new offer items if there are more than original.
- for (uint256 i = originalOfferLength; i < newOfferLength; ++i) {
- OfferItem memory originalOffer = orderParameters.offer[i];
- SpentItem memory newOffer = offer[i];
+ orderToExecute.spentItems = offer;
+ orderToExecute.spentItemOriginalAmounts = new uint256[](
+ offer.length
+ );
- originalOffer.itemType = newOffer.itemType;
- originalOffer.token = newOffer.token;
- originalOffer.identifierOrCriteria = newOffer.identifier;
- originalOffer.startAmount = newOffer.amount;
- originalOffer.endAmount = newOffer.amount;
-
- orderToExecute.spentItems[i].itemType = newOffer.itemType;
- orderToExecute.spentItems[i].token = newOffer.token;
- orderToExecute.spentItems[i].identifier = newOffer.identifier;
- orderToExecute.spentItems[i].amount = newOffer.amount;
- orderToExecute.spentItemOriginalAmounts[i] = newOffer.amount;
+ // Add new offer items if there are more than original.
+ for (uint256 i = 0; i < offer.length; ++i) {
+ orderToExecute.spentItemOriginalAmounts[i] = offer[i].amount;
}
}
{
// Designate lengths & memory locations.
- ConsiderationItem[] memory originalConsiderationArray = (
- orderParameters.consideration
+ ReceivedItem[] memory originalConsiderationArray = (
+ orderToExecute.receivedItems
);
uint256 newConsiderationLength = consideration.length;
@@ -526,32 +550,31 @@ contract ReferenceOrderValidator is
// Loop through and check consideration.
for (uint256 i = 0; i < newConsiderationLength; ++i) {
ReceivedItem memory newConsideration = consideration[i];
- ConsiderationItem memory originalConsideration = (
+ ReceivedItem memory originalConsideration = (
originalConsiderationArray[i]
);
if (
uint256(originalConsideration.itemType) > 3 &&
- originalConsideration.identifierOrCriteria == 0
+ originalConsideration.identifier == 0
) {
originalConsideration.itemType = ItemType(
uint256(originalConsideration.itemType) - 2
);
- originalConsideration
- .identifierOrCriteria = newConsideration.identifier;
+ originalConsideration.identifier = (
+ newConsideration.identifier
+ );
}
// All fields must match the originally supplied fields except
// for the amount (which may be reduced by the contract offerer)
// and the recipient if some non-zero address has been provided.
if (
- originalConsideration.startAmount !=
- originalConsideration.endAmount ||
- newConsideration.amount > originalConsideration.endAmount ||
+ newConsideration.amount > originalConsideration.amount ||
originalConsideration.itemType !=
newConsideration.itemType ||
originalConsideration.token != newConsideration.token ||
- originalConsideration.identifierOrCriteria !=
+ originalConsideration.identifier !=
newConsideration.identifier ||
(originalConsideration.recipient != address(0) &&
originalConsideration.recipient !=
@@ -559,66 +582,23 @@ contract ReferenceOrderValidator is
) {
revert InvalidContractOrder(orderHash);
}
-
- // Update the original amounts to use the generated amounts.
- originalConsideration.startAmount = newConsideration.amount;
- originalConsideration.endAmount = newConsideration.amount;
- originalConsideration.recipient = newConsideration.recipient;
-
- orderToExecute.receivedItems[i].amount = newConsideration
- .amount;
- orderToExecute.receivedItems[i].recipient = newConsideration
- .recipient;
- orderToExecute.receivedItemOriginalAmounts[i] = newConsideration
- .amount;
- }
-
- {
- // Shorten original consideration array if longer than new array.
- ConsiderationItem[] memory shortenedConsiderationArray = (
- new ConsiderationItem[](newConsiderationLength)
- );
-
- // Iterate over original consideration array and copy to new.
- for (uint256 i = 0; i < newConsiderationLength; ++i) {
- shortenedConsiderationArray[i] = originalConsiderationArray[
- i
- ];
- }
-
- // Replace original consideration array with new shortend array.
- orderParameters.consideration = shortenedConsiderationArray;
}
- {
- ReceivedItem[] memory shortenedReceivedItems = (
- new ReceivedItem[](newConsiderationLength)
- );
-
- // Iterate over original consideration array and copy to new.
- for (uint256 i = 0; i < newConsiderationLength; ++i) {
- shortenedReceivedItems[i] = orderToExecute.receivedItems[i];
- }
-
- orderToExecute.receivedItems = shortenedReceivedItems;
- }
- uint256[]
- memory shortenedReceivedItemOriginalAmounts = new uint256[](
- newConsiderationLength
- );
+ orderToExecute.receivedItems = consideration;
+ orderToExecute.receivedItemOriginalAmounts = new uint256[](
+ consideration.length
+ );
// Iterate over original consideration array and copy to new.
- for (uint256 i = 0; i < newConsiderationLength; ++i) {
- shortenedReceivedItemOriginalAmounts[i] = orderToExecute
- .receivedItemOriginalAmounts[i];
+ for (uint256 i = 0; i < consideration.length; ++i) {
+ orderToExecute.receivedItemOriginalAmounts[i] = (
+ consideration[i].amount
+ );
}
-
- orderToExecute
- .receivedItemOriginalAmounts = shortenedReceivedItemOriginalAmounts;
}
- // Return the order hash, the numerator, and the denominator.
- return (orderHash, 1, 1, orderToExecute);
+ // Return the order hash.
+ return orderHash;
}
/**
@@ -819,8 +799,6 @@ contract ReferenceOrderValidator is
* @param contractOrderHash The contract order hash.
*
* @return orderHash The order hash.
- * @return numerator The numerator.
- * @return denominator The denominator.
*/
function _revertOrReturnEmpty(
bool revertOnInvalid,
@@ -828,18 +806,13 @@ contract ReferenceOrderValidator is
)
internal
pure
- returns (
- bytes32 orderHash,
- uint256 numerator,
- uint256 denominator,
- OrderToExecute memory emptyOrder
- )
+ returns (bytes32 orderHash, OrderToExecute memory emptyOrder)
{
// If invalid input should not revert...
if (!revertOnInvalid) {
- // Return the contract order hash and zero values for the numerator
+ // Return no contract order hash and zero values for the numerator
// and denominator.
- return (contractOrderHash, 0, 0, emptyOrder);
+ return (bytes32(0), emptyOrder);
}
// Otherwise, revert.
@@ -847,60 +820,29 @@ contract ReferenceOrderValidator is
}
/**
- * @dev Internal pure function to convert both offer and consideration items
- * to spent items.
+ * @dev Internal pure function to convert received items to spent items.
*
- * @param offer The offer items to convert.
* @param consideration The consideration items to convert.
*
- * @return spentItems The converted spent items.
* @return receivedItems The converted received items.
*/
function _convertToSpent(
- OfferItem[] memory offer,
- ConsiderationItem[] memory consideration
- )
- internal
- pure
- returns (
- SpentItem[] memory spentItems,
- SpentItem[] memory receivedItems
- )
- {
- // Create an array of spent items equal to the offer length.
- spentItems = new SpentItem[](offer.length);
-
- // Iterate over each offer item on the order.
- for (uint256 i = 0; i < offer.length; ++i) {
- // Retrieve the offer item.
- OfferItem memory offerItem = offer[i];
-
- // Create spent item for event based on the offer item.
- SpentItem memory spentItem = SpentItem(
- offerItem.itemType,
- offerItem.token,
- offerItem.identifierOrCriteria,
- offerItem.startAmount
- );
-
- // Add to array of spent items.
- spentItems[i] = spentItem;
- }
-
+ ReceivedItem[] memory consideration
+ ) internal pure returns (SpentItem[] memory receivedItems) {
// Create an array of received items equal to the consideration length.
receivedItems = new SpentItem[](consideration.length);
- // Iterate over each consideration item on the order.
+ // Iterate over each received item on the order.
for (uint256 i = 0; i < consideration.length; ++i) {
// Retrieve the consideration item.
- ConsiderationItem memory considerationItem = (consideration[i]);
+ ReceivedItem memory considerationItem = (consideration[i]);
// Create spent item for event based on the consideration item.
SpentItem memory receivedItem = SpentItem(
considerationItem.itemType,
considerationItem.token,
- considerationItem.identifierOrCriteria,
- considerationItem.startAmount
+ considerationItem.identifier,
+ considerationItem.amount
);
// Add to array of received items.
diff --git a/reference/lib/ReferenceReentrancyGuard.sol b/reference/lib/ReferenceReentrancyGuard.sol
index fbca59797..d58dff14b 100644
--- a/reference/lib/ReferenceReentrancyGuard.sol
+++ b/reference/lib/ReferenceReentrancyGuard.sol
@@ -10,9 +10,9 @@ import {
} from "seaport-types/src/interfaces/ReentrancyErrors.sol";
import {
- _ENTERED_AND_ACCEPTING_NATIVE_TOKENS,
- _ENTERED,
- _NOT_ENTERED
+ _ENTERED_AND_ACCEPTING_NATIVE_TOKENS_SSTORE,
+ _ENTERED_SSTORE,
+ _NOT_ENTERED_SSTORE
} from "seaport-types/src/lib/ConsiderationConstants.sol";
/**
@@ -33,7 +33,7 @@ contract ReferenceReentrancyGuard is
*/
constructor() {
// Initialize the reentrancy guard in a cleared state.
- _reentrancyGuard = _NOT_ENTERED;
+ _reentrancyGuard = _NOT_ENTERED_SSTORE;
}
/**
@@ -41,7 +41,7 @@ contract ReferenceReentrancyGuard is
* is not currently set by a previous call.
*/
modifier notEntered() {
- if (_reentrancyGuard != _NOT_ENTERED) {
+ if (_reentrancyGuard != _NOT_ENTERED_SSTORE) {
revert NoReentrantCalls();
}
@@ -56,19 +56,19 @@ contract ReferenceReentrancyGuard is
* be received during execution or not.
*/
modifier nonReentrant(bool acceptNativeTokens) {
- if (_reentrancyGuard != _NOT_ENTERED) {
+ if (_reentrancyGuard != _NOT_ENTERED_SSTORE) {
revert NoReentrantCalls();
}
if (acceptNativeTokens) {
- _reentrancyGuard = _ENTERED_AND_ACCEPTING_NATIVE_TOKENS;
+ _reentrancyGuard = _ENTERED_AND_ACCEPTING_NATIVE_TOKENS_SSTORE;
} else {
- _reentrancyGuard = _ENTERED;
+ _reentrancyGuard = _ENTERED_SSTORE;
}
_;
- _reentrancyGuard = _NOT_ENTERED;
+ _reentrancyGuard = _NOT_ENTERED_SSTORE;
}
/**
@@ -77,7 +77,7 @@ contract ReferenceReentrancyGuard is
*/
function _assertAcceptingNativeTokens() internal view {
// Ensure that the reentrancy guard is not currently set.
- if (_reentrancyGuard != _ENTERED_AND_ACCEPTING_NATIVE_TOKENS) {
+ if (_reentrancyGuard != _ENTERED_AND_ACCEPTING_NATIVE_TOKENS_SSTORE) {
revert InvalidMsgValue(msg.value);
}
}
diff --git a/reference/lib/ReferenceZoneInteraction.sol b/reference/lib/ReferenceZoneInteraction.sol
index aa6e2d03d..c205d5e76 100644
--- a/reference/lib/ReferenceZoneInteraction.sol
+++ b/reference/lib/ReferenceZoneInteraction.sol
@@ -7,7 +7,10 @@ import {
ContractOffererInterface
} from "seaport-types/src/interfaces/ContractOffererInterface.sol";
-import { ItemType, OrderType } from "seaport-types/src/lib/ConsiderationEnums.sol";
+import {
+ ItemType,
+ OrderType
+} from "seaport-types/src/lib/ConsiderationEnums.sol";
import {
AdditionalRecipient,
@@ -30,6 +33,56 @@ import {
* @notice ZoneInteraction contains logic related to interacting with zones.
*/
contract ReferenceZoneInteraction is ZoneInteractionErrors {
+ function _assertRestrictedBasicOrderAuthorization(
+ bytes32 orderHash,
+ OrderType orderType,
+ BasicOrderParameters calldata basicOrderParameters,
+ ItemType offeredItemType,
+ ItemType receivedItemType
+ ) internal {
+ // Create a new array for the hash.
+ bytes32[] memory orderHashes = new bytes32[](0);
+
+ // Convert the order params and types to spent and received items.
+ (
+ SpentItem[] memory offer,
+ ReceivedItem[] memory consideration
+ ) = _convertToSpentAndReceivedItems(
+ basicOrderParameters,
+ offeredItemType,
+ receivedItemType
+ );
+
+ // Order types 2-3 require zone or offerer be caller or zone to approve.
+ // Note that in cases where fulfiller == zone, the restricted order
+ // validation will be skipped.
+ if (
+ (orderType == OrderType.FULL_RESTRICTED ||
+ orderType == OrderType.PARTIAL_RESTRICTED) &&
+ msg.sender != basicOrderParameters.zone
+ ) {
+ // Validate the order with the zone.
+ if (
+ ZoneInterface(basicOrderParameters.zone).authorizeOrder(
+ ZoneParameters({
+ orderHash: orderHash,
+ fulfiller: msg.sender,
+ offerer: basicOrderParameters.offerer,
+ offer: offer,
+ consideration: consideration,
+ extraData: "",
+ orderHashes: orderHashes,
+ startTime: basicOrderParameters.startTime,
+ endTime: basicOrderParameters.endTime,
+ zoneHash: basicOrderParameters.zoneHash
+ })
+ ) != ZoneInterface.authorizeOrder.selector
+ ) {
+ revert InvalidRestrictedOrder(orderHash);
+ }
+ }
+ }
+
/**
* @dev Internal view function to determine if an order has a restricted
* order type and, if so, to ensure that either the offerer or the zone
@@ -62,7 +115,7 @@ contract ReferenceZoneInteraction is ZoneInteractionErrors {
receivedItemType
);
- // Order type 2-3 require zone or offerer be caller or zone to approve.
+ // Order types 2-3 require zone or offerer be caller or zone to approve.
// Note that in cases where fulfiller == zone, the restricted order
// validation will be skipped.
if (
@@ -92,6 +145,128 @@ contract ReferenceZoneInteraction is ZoneInteractionErrors {
}
}
+ /**
+ * @dev Internal function to check if a restricted advanced order is
+ * authorized by its zone or offerer, in cases where the caller is not
+ * the zone or offerer.
+ *
+ * @param advancedOrder The advanced order in question.
+ * @param orderToExecute The order to execute.
+ * @param orderHashes The order hashes of each order supplied
+ * alongside the current order as part of a
+ "match" or "fulfill available" variety of
+ order fulfillment.
+ * @param orderHash The hash of the order to execute.
+ * @param revertOnUnauthorized A boolean indicating whether the function
+ * should revert if the order is invalid.
+ *
+ * @return authorized A boolean indicating whether the order is
+ * authorized by the zone or offerer.
+ * @return checked A boolean indicating whether the order has
+ * been checked for authorization.
+ */
+ function _checkRestrictedAdvancedOrderAuthorization(
+ AdvancedOrder memory advancedOrder,
+ OrderToExecute memory orderToExecute,
+ bytes32[] memory orderHashes,
+ bytes32 orderHash,
+ bool revertOnUnauthorized
+ ) internal returns (bool authorized, bool checked) {
+ // Order types 2-3 require zone or offerer be caller or zone to approve.
+ if (
+ (advancedOrder.parameters.orderType == OrderType.FULL_RESTRICTED ||
+ advancedOrder.parameters.orderType ==
+ OrderType.PARTIAL_RESTRICTED) &&
+ msg.sender != advancedOrder.parameters.zone
+ ) {
+ // Authorize the order.
+ try
+ ZoneInterface(advancedOrder.parameters.zone).authorizeOrder(
+ ZoneParameters({
+ orderHash: orderHash,
+ fulfiller: msg.sender,
+ offerer: advancedOrder.parameters.offerer,
+ offer: orderToExecute.spentItems,
+ consideration: orderToExecute.receivedItems,
+ extraData: advancedOrder.extraData,
+ orderHashes: orderHashes,
+ startTime: advancedOrder.parameters.startTime,
+ endTime: advancedOrder.parameters.endTime,
+ zoneHash: advancedOrder.parameters.zoneHash
+ })
+ )
+ returns (bytes4 selector) {
+ if (selector != ZoneInterface.authorizeOrder.selector) {
+ revert InvalidRestrictedOrder(orderHash);
+ }
+
+ return (true, true);
+ } catch {
+ if (revertOnUnauthorized) {
+ revert InvalidRestrictedOrder(orderHash);
+ }
+
+ return (false, false);
+ }
+ } else {
+ return (true, false);
+ }
+ }
+
+ /**
+ * @dev Internal function to validate that a restricted advanced order is
+ * authorized by its zone or offerer, in cases where the caller is not
+ * the zone or offerer.
+ *
+ * @param advancedOrder The advanced order in question.
+ * @param orderToExecute The order to execute.
+ * @param orderHashes The order hashes of each order supplied
+ * alongside the current order as part of a
+ "match" or "fulfill available" variety of
+ order fulfillment.
+ * @param orderHash The hash of the order to execute.
+ * @param zoneHash The hash to provide upon calling the zone.
+ * @param orderType The type of the order.
+ * @param offerer The offerer in question.
+ * @param zone The zone in question.
+ */
+ function _assertRestrictedAdvancedOrderAuthorization(
+ AdvancedOrder memory advancedOrder,
+ OrderToExecute memory orderToExecute,
+ bytes32[] memory orderHashes,
+ bytes32 orderHash,
+ bytes32 zoneHash,
+ OrderType orderType,
+ address offerer,
+ address zone
+ ) internal {
+ // Order types 2-3 require zone or offerer be caller or zone to approve.
+ if (
+ (orderType == OrderType.FULL_RESTRICTED ||
+ orderType == OrderType.PARTIAL_RESTRICTED) && msg.sender != zone
+ ) {
+ // Authorize the order.
+ if (
+ ZoneInterface(zone).authorizeOrder(
+ ZoneParameters({
+ orderHash: orderHash,
+ fulfiller: msg.sender,
+ offerer: offerer,
+ offer: orderToExecute.spentItems,
+ consideration: orderToExecute.receivedItems,
+ extraData: advancedOrder.extraData,
+ orderHashes: orderHashes,
+ startTime: advancedOrder.parameters.startTime,
+ endTime: advancedOrder.parameters.endTime,
+ zoneHash: zoneHash
+ })
+ ) != ZoneInterface.authorizeOrder.selector
+ ) {
+ revert InvalidRestrictedOrder(orderHash);
+ }
+ }
+ }
+
/**
* @dev Internal view function to determine if a proxy should be utilized
* for a given order and to ensure that the submitter is allowed by the
@@ -117,7 +292,7 @@ contract ReferenceZoneInteraction is ZoneInteractionErrors {
address offerer,
address zone
) internal {
- // Order type 2-3 require zone or offerer be caller or zone to approve.
+ // Order types 2-3 require zone or offerer be caller or zone to approve.
if (
(orderType == OrderType.FULL_RESTRICTED ||
orderType == OrderType.PARTIAL_RESTRICTED) && msg.sender != zone
diff --git a/script/CallNavigator.s.sol b/script/CallNavigator.s.sol
index ce634e533..826be66c5 100644
--- a/script/CallNavigator.s.sol
+++ b/script/CallNavigator.s.sol
@@ -2,26 +2,25 @@
pragma solidity ^0.8.4;
import "forge-std/Script.sol";
-import "forge-std/console.sol";
import {
- SeaportNavigatorInterface,
- NavigatorRequest,
ConsiderationInterface,
+ NavigatorRequest,
+ SeaportNavigatorInterface,
SeaportValidatorInterface
} from "../contracts/helpers/navigator/SeaportNavigator.sol";
import {
NavigatorAdvancedOrder,
- NavigatorOrderParameters,
+ NavigatorConsiderationItem,
NavigatorOfferItem,
- NavigatorConsiderationItem
+ NavigatorOrderParameters
} from "../contracts/helpers/navigator/lib/SeaportNavigatorTypes.sol";
import {
- FulfillmentStrategy,
AggregationStrategy,
FulfillAvailableStrategy,
+ FulfillmentStrategy,
MatchStrategy
} from "seaport-sol/src/fulfillments/lib/FulfillmentLib.sol";
diff --git a/script/NavigatorDeployer.s.sol b/script/NavigatorDeployer.s.sol
index 3246a97b1..b6927d6c1 100644
--- a/script/NavigatorDeployer.s.sol
+++ b/script/NavigatorDeployer.s.sol
@@ -2,44 +2,54 @@
pragma solidity ^0.8.4;
import "forge-std/Script.sol";
+
import "forge-std/console.sol";
import { LibString } from "solady/src/utils/LibString.sol";
import {
- ReadOnlyOrderValidator
-} from "../contracts/helpers/order-validator/lib/ReadOnlyOrderValidator.sol";
+ CriteriaHelper
+} from "../contracts/helpers/navigator/lib/CriteriaHelper.sol";
+
import {
- SeaportValidatorHelper
-} from "../contracts/helpers/order-validator/lib/SeaportValidatorHelper.sol";
+ ExecutionsHelper
+} from "../contracts/helpers/navigator/lib/ExecutionsHelper.sol";
+
import {
- SeaportValidator
-} from "../contracts/helpers/order-validator/SeaportValidator.sol";
+ FulfillmentsHelper
+} from "../contracts/helpers/navigator/lib/FulfillmentsHelper.sol";
+
+import {
+ OrderDetailsHelper
+} from "../contracts/helpers/navigator/lib/OrderDetailsHelper.sol";
+
+import {
+ ReadOnlyOrderValidator
+} from "../contracts/helpers/order-validator/lib/ReadOnlyOrderValidator.sol";
import {
RequestValidator
} from "../contracts/helpers/navigator/lib/RequestValidator.sol";
+
import {
- CriteriaHelper
-} from "../contracts/helpers/navigator/lib/CriteriaHelper.sol";
-import {
- ValidatorHelper
-} from "../contracts/helpers/navigator/lib/ValidatorHelper.sol";
+ SeaportNavigator
+} from "../contracts/helpers/navigator/SeaportNavigator.sol";
+
import {
- OrderDetailsHelper
-} from "../contracts/helpers/navigator/lib/OrderDetailsHelper.sol";
+ SeaportValidator
+} from "../contracts/helpers/order-validator/SeaportValidator.sol";
+
import {
- FulfillmentsHelper
-} from "../contracts/helpers/navigator/lib/FulfillmentsHelper.sol";
+ SeaportValidatorHelper
+} from "../contracts/helpers/order-validator/lib/SeaportValidatorHelper.sol";
+
import {
SuggestedActionHelper
} from "../contracts/helpers/navigator/lib/SuggestedActionHelper.sol";
+
import {
- ExecutionsHelper
-} from "../contracts/helpers/navigator/lib/ExecutionsHelper.sol";
-import {
- SeaportNavigator
-} from "../contracts/helpers/navigator/SeaportNavigator.sol";
+ ValidatorHelper
+} from "../contracts/helpers/navigator/lib/ValidatorHelper.sol";
interface ImmutableCreate2Factory {
function hasBeenDeployed(
@@ -58,11 +68,14 @@ interface ImmutableCreate2Factory {
}
contract NavigatorDeployer is Script {
+ // Set up the immutable create2 factory and conduit controller addresses.
ImmutableCreate2Factory private constant IMMUTABLE_CREATE2_FACTORY =
ImmutableCreate2Factory(0x0000000000FFe8B47B3e2130213B802212439497);
address private constant CONDUIT_CONTROLLER =
0x00000000F9490004C11Cef243f5400493c00Ad63;
+ // Set up the default salt and the salt for the seaport validator and
+ // navigator.
bytes32 private constant DEFAULT_SALT = bytes32(uint256(0x1));
bytes32 private constant SEAPORT_VALIDATOR_SALT =
bytes32(uint256(0x459b42ee5b5e5000d96491ce));
@@ -76,6 +89,8 @@ contract NavigatorDeployer is Script {
pad("Address", 43),
"Initcode hash"
);
+
+ // Deploy the helpers, seaport validator, and navigator.
vm.startBroadcast();
address seaportValidatorHelper = deploy(
"SeaportValidatorHelper",
diff --git a/test/advanced.spec.ts b/test/advanced.spec.ts
index 45b445ba3..32783c7e7 100644
--- a/test/advanced.spec.ts
+++ b/test/advanced.spec.ts
@@ -1,7 +1,7 @@
import { PANIC_CODES } from "@nomicfoundation/hardhat-chai-matchers/panic";
import { loadFixture } from "@nomicfoundation/hardhat-network-helpers";
import { expect } from "chai";
-import { constants } from "ethers";
+import { BigNumber, constants } from "ethers";
import { ethers, network } from "hardhat";
import { deployContract } from "./utils/contracts";
@@ -577,9 +577,9 @@ describe(`Advanced orders (Seaport v${VERSION})`, function () {
) as any,
];
- // ERC1155 criteria based item
- offer[0].itemType = 5;
- offer[0].identifier = offer[0].identifierOrCriteria;
+ // ERC1155 criteria based item (resolved)
+ offer[0].itemType = 3;
+ offer[0].identifier = nftId;
offer[0].amount = offer[0].endAmount;
consideration[0].identifier = consideration[0].identifierOrCriteria;
@@ -587,7 +587,11 @@ describe(`Advanced orders (Seaport v${VERSION})`, function () {
await offererContract
.connect(seller)
- .activateWithCriteria(offer[0], consideration[0], nftId);
+ .activate(offer[0], consideration[0]);
+
+ // ERC1155 criteria based item (unresolved)
+ offer[0].itemType = 5;
+ offer[0].identifier = offer[0].identifierOrCriteria;
const criteriaResolvers = [
buildResolver(0, 0, 0, nftId, proofs[nftId.toString()]),
@@ -1188,87 +1192,6 @@ describe(`Advanced orders (Seaport v${VERSION})`, function () {
return receipt;
});
});
- it("Reverts on contract orders where offer startAmount doesn't equal offer endAmount", async () => {
- // Seller mints nfts
- const { nftId, amount } = await mintAndApprove1155(
- seller,
- marketplaceContract.address,
- 10000
- );
-
- // seller deploys offererContract and approves it for 1155 token
- const offererContract = await deployContract(
- "TestContractOfferer",
- owner,
- marketplaceContract.address
- );
-
- await set1155ApprovalForAll(seller, offererContract.address, true);
-
- const offer = [
- getTestItem1155(nftId, amount.mul(10), amount.mul(10)) as any,
- ];
-
- const consideration = [
- getItemETH(
- amount.mul(1000),
- amount.mul(1000),
- offererContract.address
- ) as any,
- ];
-
- offer[0].identifier = offer[0].identifierOrCriteria;
- offer[0].amount = offer[0].endAmount;
- offer[0].startAmount = offer[0].endAmount.add(1);
-
- consideration[0].identifier = consideration[0].identifierOrCriteria;
- consideration[0].amount = consideration[0].endAmount;
-
- await offererContract
- .connect(seller)
- .activate(offer[0], consideration[0]);
-
- const { order, value } = await createOrder(
- seller,
- zone,
- offer,
- consideration,
- 4 // CONTRACT
- );
-
- const contractOffererNonce =
- await marketplaceContract.getContractOffererNonce(
- offererContract.address
- );
-
- const orderHash =
- offererContract.address.toLowerCase() +
- contractOffererNonce.toHexString().slice(2).padStart(24, "0");
-
- const orderStatus = await marketplaceContract.getOrderStatus(orderHash);
-
- expect({ ...orderStatus }).to.deep.equal(
- buildOrderStatus(false, false, 0, 0)
- );
-
- order.parameters.offerer = offererContract.address;
- order.numerator = 1;
- order.denominator = 1;
- order.signature = "0x";
-
- await expect(
- marketplaceContract
- .connect(buyer)
- .fulfillAdvancedOrder(order, [], toKey(0), buyer.address, {
- value,
- })
- )
- .to.be.revertedWithCustomError(
- marketplaceContract,
- "InvalidContractOrder"
- )
- .withArgs(orderHash);
- });
it("Reverts on contract orders where offer endAmount is greater than offer amount (branch 2)", async () => {
// Seller mints nfts
const { nftId, amount } = await mintAndApprove1155(
@@ -1600,87 +1523,6 @@ describe(`Advanced orders (Seaport v${VERSION})`, function () {
)
.withArgs(orderHash);
});
- it("Reverts on contract orders where consideration startAmount doesn't equal consideration endAmount", async () => {
- // Seller mints nfts
- const { nftId, amount } = await mintAndApprove1155(
- seller,
- marketplaceContract.address,
- 10000
- );
-
- // seller deploys offererContract and approves it for 1155 token
- const offererContract = await deployContract(
- "TestContractOfferer",
- owner,
- marketplaceContract.address
- );
-
- await set1155ApprovalForAll(seller, offererContract.address, true);
-
- const offer = [
- getTestItem1155(nftId, amount.mul(10), amount.mul(10)) as any,
- ];
-
- const consideration = [
- getItemETH(
- amount.mul(1000),
- amount.mul(1000),
- offererContract.address
- ) as any,
- ];
-
- offer[0].identifier = offer[0].identifierOrCriteria;
- offer[0].amount = offer[0].endAmount;
-
- consideration[0].identifier = consideration[0].identifierOrCriteria;
- consideration[0].amount = consideration[0].endAmount;
- consideration[0].startAmount = consideration[0].endAmount.add(1);
-
- await offererContract
- .connect(seller)
- .activate(offer[0], consideration[0]);
-
- const { order, value } = await createOrder(
- seller,
- zone,
- offer,
- consideration,
- 4 // CONTRACT
- );
-
- const contractOffererNonce =
- await marketplaceContract.getContractOffererNonce(
- offererContract.address
- );
-
- const orderHash =
- offererContract.address.toLowerCase() +
- contractOffererNonce.toHexString().slice(2).padStart(24, "0");
-
- const orderStatus = await marketplaceContract.getOrderStatus(orderHash);
-
- expect({ ...orderStatus }).to.deep.equal(
- buildOrderStatus(false, false, 0, 0)
- );
-
- order.parameters.offerer = offererContract.address;
- order.numerator = 1;
- order.denominator = 1;
- order.signature = "0x";
-
- await expect(
- marketplaceContract
- .connect(buyer)
- .fulfillAdvancedOrder(order, [], toKey(0), buyer.address, {
- value,
- })
- )
- .to.be.revertedWithCustomError(
- marketplaceContract,
- "InvalidContractOrder"
- )
- .withArgs(orderHash);
- });
it("Reverts on contract orders where consideration itemType is different from generated itemType", async () => {
// Seller mints nfts
const { nftId, amount } = await mintAndApprove1155(
@@ -2783,12 +2625,7 @@ describe(`Advanced orders (Seaport v${VERSION})`, function () {
.fulfillAdvancedOrder(order, [], toKey(0), buyer.address, {
value,
})
- )
- .to.be.revertedWithCustomError(
- marketplaceContract,
- "InvalidContractOrder"
- )
- .withArgs(orderHash);
+ ).to.be.reverted; // TODO: get revert message bubbled up from the offerer
});
it("Reverts on contract orders where call to generateOrders throws and reverts are skipped", async () => {
// Seller mints nfts
@@ -3633,7 +3470,7 @@ describe(`Advanced orders (Seaport v${VERSION})`, function () {
orderStatus = await marketplaceContract.getOrderStatus(orderHash);
expect({ ...orderStatus }).to.deep.equal(
- buildOrderStatus(true, false, 14, 20)
+ buildOrderStatus(true, false, 140, 200)
);
// Fill remaining; only 3/10ths will be fillable
@@ -3697,7 +3534,7 @@ describe(`Advanced orders (Seaport v${VERSION})`, function () {
orderStatus = await marketplaceContract.getOrderStatus(orderHash);
expect({ ...orderStatus }).to.deep.equal(
- buildOrderStatus(true, false, 40, 40)
+ buildOrderStatus(true, false, 80000, 80000)
);
});
it("Partial fills (standard, additional permutations)", async () => {
@@ -4056,8 +3893,8 @@ describe(`Advanced orders (Seaport v${VERSION})`, function () {
});
it("Simplifies fraction when numerator/denominator would overflow", async () => {
- const numer1 = toBN(2).pow(100);
- const denom1 = toBN(2).pow(101);
+ const numer1 = toBN(2).pow(50);
+ const denom1 = toBN(2).pow(51);
const numer2 = toBN(2).pow(20);
const denom2 = toBN(2).pow(22);
const amt = 8;
@@ -5795,136 +5632,6 @@ describe(`Advanced orders (Seaport v${VERSION})`, function () {
executions
);
});
- it("Match with fewer executions when one party has multiple orders that coincide", async () => {
- const nftId = await mintAndApprove721(
- seller,
- marketplaceContract.address
- );
- const secondNFTId = await mintAndApprove721(
- buyer,
- marketplaceContract.address
- );
-
- const offerOne = [
- getTestItem721(nftId, toBN(1), toBN(1), undefined, testERC721.address),
- ];
-
- const considerationOne = [
- getTestItem20(parseEther("10"), parseEther("10"), seller.address),
- ];
-
- const { order: orderOne, orderHash: orderHashOne } = await createOrder(
- seller,
- zone,
- offerOne,
- considerationOne,
- 0 // FULL_OPEN
- );
-
- const offerTwo = [getTestItem20(parseEther("10"), parseEther("10"))];
-
- const considerationTwo = [
- getTestItem721(
- secondNFTId,
- toBN(1),
- toBN(1),
- seller.address,
- testERC721.address
- ),
- ];
-
- const { order: orderTwo, orderHash: orderHashTwo } = await createOrder(
- seller,
- zone,
- offerTwo,
- considerationTwo,
- 0 // FULL_OPEN
- );
-
- const offerThree = [
- getTestItem721(
- secondNFTId,
- toBN(1),
- toBN(1),
- undefined,
- testERC721.address
- ),
- ];
-
- const considerationThree = [
- getTestItem721(
- nftId,
- toBN(1),
- toBN(1),
- buyer.address,
- testERC721.address
- ),
- ];
-
- const { order: orderThree, orderHash: orderHashThree } =
- await createOrder(
- buyer,
- zone,
- offerThree,
- considerationThree,
- 0 // FULL_OPEN
- );
-
- const fulfillments = [
- [[[1, 0]], [[0, 0]]],
- [[[0, 0]], [[2, 0]]],
- [[[2, 0]], [[1, 0]]],
- ].map(([offerArr, considerationArr]) =>
- toFulfillment(offerArr, considerationArr)
- );
-
- const executions = await simulateAdvancedMatchOrders(
- marketplaceContract,
- [orderOne, orderTwo, orderThree],
- [], // no criteria resolvers
- fulfillments,
- owner,
- 0 // no value
- );
-
- expect(executions.length).to.equal(fulfillments.length - 1);
-
- const tx = marketplaceContract
- .connect(owner)
- .matchAdvancedOrders(
- [orderOne, orderTwo, orderThree],
- [],
- fulfillments,
- ethers.constants.AddressZero,
- {
- value: 0,
- }
- );
- const receipt = await (await tx).wait();
- await checkExpectedEvents(
- tx,
- receipt,
- [
- {
- order: orderOne,
- orderHash: orderHashOne,
- fulfiller: owner.address,
- },
- {
- order: orderTwo,
- orderHash: orderHashTwo,
- fulfiller: owner.address,
- },
- {
- order: orderThree,
- orderHash: orderHashThree,
- fulfiller: owner.address,
- },
- ],
- executions
- );
- return receipt;
- });
it("Does not filter native tokens", async () => {
const nftId = await mintAndApprove721(
seller,
@@ -6772,7 +6479,7 @@ describe(`Advanced orders (Seaport v${VERSION})`, function () {
value
);
- expect(executions.length).to.equal(6);
+ expect(executions.length).to.equal(7);
const tx = marketplaceContract
.connect(owner)
@@ -6795,7 +6502,9 @@ describe(`Advanced orders (Seaport v${VERSION})`, function () {
fulfiller: owner.address,
},
],
- executions
+ executions.filter((execution: any) =>
+ BigNumber.from(execution.item.amount).gt(0)
+ )
);
return receipt;
});
@@ -6860,7 +6569,7 @@ describe(`Advanced orders (Seaport v${VERSION})`, function () {
value
);
- expect(executions.length).to.equal(6);
+ expect(executions.length).to.equal(8);
const tx = marketplaceContract
.connect(owner)
@@ -6883,7 +6592,9 @@ describe(`Advanced orders (Seaport v${VERSION})`, function () {
fulfiller: owner.address,
},
],
- executions
+ executions.filter((execution: any) =>
+ BigNumber.from(execution.item.amount).gt(0)
+ )
);
return receipt;
});
diff --git a/test/findings/AdditionalRecipientsOffByOne.spec.ts b/test/findings/AdditionalRecipientsOffByOne.spec.ts
index 3e89ee365..8a503173b 100644
--- a/test/findings/AdditionalRecipientsOffByOne.spec.ts
+++ b/test/findings/AdditionalRecipientsOffByOne.spec.ts
@@ -1,5 +1,5 @@
import { expect } from "chai";
-import { constants } from "ethers";
+import { Contract, constants } from "ethers";
import { hexZeroPad } from "ethers/lib/utils";
import { network } from "hardhat";
import { getScuffedContract } from "scuffed-abi";
@@ -175,61 +175,70 @@ describe("Additional recipients off by one error allows skipping second consider
let maliciousCallData: string;
before(async () => {
- // True Parameters
- const basicOrderParameters = getBasicOrderParameters(
- 2, // ERC20ForERC721
- order
- );
+ if (!process.env.REFERENCE) {
+ // True Parameters
+ const basicOrderParameters = getBasicOrderParameters(
+ 2, // ERC20ForERC721
+ order
+ );
- basicOrderParameters.additionalRecipients = [];
- basicOrderParameters.signature = basicOrderParameters.signature
- .slice(0, 66)
- .concat(hexZeroPad("0x", 96).slice(2));
- const scuffedContract = getScuffedContract(marketplaceContract);
- const scuffed = scuffedContract.fulfillBasicOrder({
- parameters: basicOrderParameters,
- });
- scuffed.parameters.signature.length.replace(100);
- scuffed.parameters.signature.tail.replace(carol.address);
-
- maliciousCallData = scuffed.encode();
+ basicOrderParameters.additionalRecipients = [];
+ basicOrderParameters.signature = basicOrderParameters.signature
+ .slice(0, 66)
+ .concat(hexZeroPad("0x", 96).slice(2));
+ const abi =
+ require("../../artifacts/seaport-types/src/interfaces/ConsiderationInterface.sol/ConsiderationInterface.json")
+ .abi as any;
+ const scuffedContract = getScuffedContract(
+ new Contract(marketplaceContract.address, abi, bob)
+ );
+ const scuffed = scuffedContract.fulfillBasicOrder({
+ parameters: basicOrderParameters,
+ });
+ scuffed.parameters.signature.length.replace(100);
+ scuffed.parameters.signature.tail.replace(carol.address);
+
+ maliciousCallData = scuffed.encode();
+ }
});
- if (!IS_FIXED) {
- it("Bob fulfills Alice's order using maliciously constructed calldata", async () => {
- await expect(
- bob.sendTransaction({
- to: marketplaceContract.address,
- data: maliciousCallData,
- })
- ).to.emit(marketplaceContract, "OrderFulfilled");
- });
-
- it("Bob receives Alice's NFT, having paid 1000 DAI", async () => {
- expect(await testERC721.ownerOf(1)).to.equal(bob.address);
- expect(await testERC20.balanceOf(bob.address)).to.equal(100);
- });
-
- it("Alice receives 1000 DAI", async () => {
- expect(await testERC20.balanceOf(alice.address)).to.equal(1000);
- });
-
- it("Carol does not receive her DAI", async () => {
- expect(await testERC20.balanceOf(carol.address)).to.equal(0);
- });
- } else {
- it("Bob attempts to fulfill Alice's order with malicious calldata, but the transaction reverts", async () => {
- await expect(
- bob.sendTransaction({
- to: marketplaceContract.address,
- data: maliciousCallData,
- gasLimit: 29_999_999,
- })
- ).to.be.revertedWithCustomError(
- marketplaceContract,
- "MissingOriginalConsiderationItems"
- );
- });
+ if (!process.env.REFERENCE) {
+ if (!IS_FIXED) {
+ it("Bob fulfills Alice's order using maliciously constructed calldata", async () => {
+ await expect(
+ bob.sendTransaction({
+ to: marketplaceContract.address,
+ data: maliciousCallData,
+ })
+ ).to.emit(marketplaceContract, "OrderFulfilled");
+ });
+
+ it("Bob receives Alice's NFT, having paid 1000 DAI", async () => {
+ expect(await testERC721.ownerOf(1)).to.equal(bob.address);
+ expect(await testERC20.balanceOf(bob.address)).to.equal(100);
+ });
+
+ it("Alice receives 1000 DAI", async () => {
+ expect(await testERC20.balanceOf(alice.address)).to.equal(1000);
+ });
+
+ it("Carol does not receive her DAI", async () => {
+ expect(await testERC20.balanceOf(carol.address)).to.equal(0);
+ });
+ } else {
+ it("Bob attempts to fulfill Alice's order with malicious calldata, but the transaction reverts", async () => {
+ await expect(
+ bob.sendTransaction({
+ to: marketplaceContract.address,
+ data: maliciousCallData,
+ gasLimit: 29_999_999,
+ })
+ ).to.be.revertedWithCustomError(
+ marketplaceContract,
+ "MissingOriginalConsiderationItems"
+ );
+ });
+ }
}
});
});
diff --git a/test/foundry/ConsiderationErrors.t.sol b/test/foundry/ConsiderationErrors.t.sol
index 29935b215..f418eea30 100644
--- a/test/foundry/ConsiderationErrors.t.sol
+++ b/test/foundry/ConsiderationErrors.t.sol
@@ -114,18 +114,6 @@ contract ConsiderationErrors is BaseOrderTest, ConsiderationErrorsWrapper {
this.__revertInvalidTime(6, 7);
}
- function test_revertMismatchedFulfillmentOfferAndConsiderationComponents()
- public
- {
- vm.expectRevert(
- abi.encodeWithSignature(
- "MismatchedFulfillmentOfferAndConsiderationComponents(uint256)",
- 8
- )
- );
- this.__revertMismatchedFulfillmentOfferAndConsiderationComponents(8);
- }
-
function test_revertMissingOriginalConsiderationItems() public {
vm.expectRevert(
abi.encodeWithSignature("MissingOriginalConsiderationItems()")
@@ -145,15 +133,6 @@ contract ConsiderationErrors is BaseOrderTest, ConsiderationErrorsWrapper {
this.__revertNoSpecifiedOrdersAvailable();
}
- function test_revertOfferAndConsiderationRequiredOnFulfillment() public {
- vm.expectRevert(
- abi.encodeWithSignature(
- "OfferAndConsiderationRequiredOnFulfillment()"
- )
- );
- this.__revertOfferAndConsiderationRequiredOnFulfillment();
- }
-
function test_revertOrderAlreadyFilled() public {
vm.expectRevert(
abi.encodeWithSignature("OrderAlreadyFilled(bytes32)", someBytes32)
@@ -195,28 +174,6 @@ contract ConsiderationErrors is BaseOrderTest, ConsiderationErrorsWrapper {
this.__revertPartialFillsNotEnabledForOrder();
}
- function test_revertUnresolvedConsiderationCriteria() public {
- vm.expectRevert(
- abi.encodeWithSignature(
- "UnresolvedConsiderationCriteria(uint256,uint256)",
- 9,
- 10
- )
- );
- this.__revertUnresolvedConsiderationCriteria(9, 10);
- }
-
- function test_revertUnresolvedOfferCriteria() public {
- vm.expectRevert(
- abi.encodeWithSignature(
- "UnresolvedOfferCriteria(uint256,uint256)",
- 11,
- 12
- )
- );
- this.__revertUnresolvedOfferCriteria(11, 12);
- }
-
function test_revertUnusedItemParameters() public {
vm.expectRevert(abi.encodeWithSignature("UnusedItemParameters()"));
this.__revertUnusedItemParameters();
diff --git a/test/foundry/FulfillAdvancedOrder.t.sol b/test/foundry/FulfillAdvancedOrder.t.sol
index 14959d4b7..abfccbbfb 100644
--- a/test/foundry/FulfillAdvancedOrder.t.sol
+++ b/test/foundry/FulfillAdvancedOrder.t.sol
@@ -1,8 +1,10 @@
// SPDX-License-Identifier: MIT
-
pragma solidity ^0.8.17;
-import { OrderType, ItemType } from "seaport-types/src/lib/ConsiderationEnums.sol";
+import {
+ OrderType,
+ ItemType
+} from "seaport-types/src/lib/ConsiderationEnums.sol";
import {
ConsiderationInterface
@@ -30,6 +32,7 @@ contract FulfillAdvancedOrder is BaseOrderTest {
using ArithmeticUtil for uint8;
FuzzInputs empty;
+
struct FuzzInputs {
uint256 tokenId;
address zone;
@@ -529,7 +532,7 @@ contract FulfillAdvancedOrder is BaseOrderTest {
address(0)
);
- // Assert six-tenths of the order has been fulfilled.
+ // Assert three-fifths of the order has been fulfilled.
{
(
bool isValidated,
@@ -539,9 +542,9 @@ contract FulfillAdvancedOrder is BaseOrderTest {
) = context.consideration.getOrderStatus(orderHash);
assertTrue(isValidated);
assertFalse(isCancelled);
- assertEq(totalFilled, 6);
+ assertEq(totalFilled, 3);
- assertEq(totalSize, 10);
+ assertEq(totalSize, 5);
assertEq(60, test1155_1.balanceOf(address(this), 1));
}
}
diff --git a/test/foundry/FulfillAvailableAdvancedOrder.t.sol b/test/foundry/FulfillAvailableAdvancedOrder.t.sol
index 84fecde58..4efa707e1 100644
--- a/test/foundry/FulfillAvailableAdvancedOrder.t.sol
+++ b/test/foundry/FulfillAvailableAdvancedOrder.t.sol
@@ -2,7 +2,10 @@
pragma solidity ^0.8.17;
-import { OrderType, ItemType } from "seaport-types/src/lib/ConsiderationEnums.sol";
+import {
+ OrderType,
+ ItemType
+} from "seaport-types/src/lib/ConsiderationEnums.sol";
import {
ConsiderationInterface
@@ -1077,7 +1080,7 @@ contract FulfillAvailableAdvancedOrder is BaseOrderTest {
100
);
- // Assert six-tenths of the offer has been fulfilled.
+ // Assert three-fifths of the offer has been fulfilled.
{
(
bool isValidated,
@@ -1087,9 +1090,9 @@ contract FulfillAvailableAdvancedOrder is BaseOrderTest {
) = context.consideration.getOrderStatus(orderHash);
assertTrue(isValidated);
assertFalse(isCancelled);
- assertEq(totalFilled, 6);
+ assertEq(totalFilled, 3);
- assertEq(totalSize, 10);
+ assertEq(totalSize, 5);
assertEq(60, test1155_1.balanceOf(address(this), 1));
}
}
@@ -1182,7 +1185,7 @@ contract FulfillAvailableAdvancedOrder is BaseOrderTest {
100
);
- // Assert six-tenths of the offer has been fulfilled.
+ // Assert three-fifths of the offer has been fulfilled.
{
(
bool isValidated,
@@ -1192,9 +1195,9 @@ contract FulfillAvailableAdvancedOrder is BaseOrderTest {
) = context.consideration.getOrderStatus(orderHash);
assertTrue(isValidated);
assertFalse(isCancelled);
- assertEq(totalFilled, 6);
+ assertEq(totalFilled, 3);
- assertEq(totalSize, 10);
+ assertEq(totalSize, 5);
assertEq(60, test1155_1.balanceOf(address(this), 1));
}
}
diff --git a/test/foundry/FulfillBasicOrderTest.t.sol b/test/foundry/FulfillBasicOrderTest.t.sol
index d9b71aa4c..32e27503d 100644
--- a/test/foundry/FulfillBasicOrderTest.t.sol
+++ b/test/foundry/FulfillBasicOrderTest.t.sol
@@ -52,6 +52,7 @@ contract FulfillBasicOrderTest is BaseOrderTest, ConsiderationEventsAndErrors {
uint256 salt;
bool useConduit;
}
+
struct Context {
ConsiderationInterface consideration;
FuzzInputsCommon args;
diff --git a/test/foundry/FulfillOrderTest.t.sol b/test/foundry/FulfillOrderTest.t.sol
index 761961d94..5d89226d5 100644
--- a/test/foundry/FulfillOrderTest.t.sol
+++ b/test/foundry/FulfillOrderTest.t.sol
@@ -2,18 +2,21 @@
pragma solidity ^0.8.17;
-import { OrderType, ItemType } from "seaport-types/src/lib/ConsiderationEnums.sol";
+import {
+ ItemType,
+ OrderType
+} from "seaport-types/src/lib/ConsiderationEnums.sol";
import {
ConsiderationInterface
} from "seaport-types/src/interfaces/ConsiderationInterface.sol";
import {
- Order,
- OfferItem,
- OrderParameters,
ConsiderationItem,
- OrderComponents
+ OfferItem,
+ Order,
+ OrderComponents,
+ OrderParameters
} from "seaport-types/src/lib/ConsiderationStructs.sol";
import { BaseOrderTest } from "./utils/BaseOrderTest.sol";
@@ -31,6 +34,7 @@ contract FulfillOrderTest is BaseOrderTest {
uint256 badIdentifier;
address badToken;
+
struct FuzzInputsCommon {
address zone;
uint128 id;
@@ -2548,6 +2552,10 @@ contract FulfillOrderTest is BaseOrderTest {
function fulfillOrderRevertCounterIncremented(
Context memory context
) external stateless {
+ // Roll to a high block to get a blockhash that's high enough to produce
+ // a non-0 value when right shifted by 128 bits.
+ vm.roll(type(uint248).max);
+
test1155_1.mint(bob, 1, 1);
addErc1155OfferItem(1, 1);
addEthConsiderationItem(payable(bob), 1);
diff --git a/test/foundry/FullfillAvailableOrder.t.sol b/test/foundry/FullfillAvailableOrder.t.sol
index 6fd0c5c7d..5ac128d7a 100644
--- a/test/foundry/FullfillAvailableOrder.t.sol
+++ b/test/foundry/FullfillAvailableOrder.t.sol
@@ -2,7 +2,10 @@
pragma solidity ^0.8.17;
-import { OrderType, ItemType } from "seaport-types/src/lib/ConsiderationEnums.sol";
+import {
+ OrderType,
+ ItemType
+} from "seaport-types/src/lib/ConsiderationEnums.sol";
import {
ConsiderationInterface
@@ -30,6 +33,7 @@ contract FulfillAvailableOrder is BaseOrderTest {
using ArithmeticUtil for uint120;
FuzzInputs empty;
+
struct FuzzInputs {
address zone;
uint256 id;
diff --git a/test/foundry/GetterTests.t.sol b/test/foundry/GetterTests.t.sol
index 83563d8aa..8570d4406 100644
--- a/test/foundry/GetterTests.t.sol
+++ b/test/foundry/GetterTests.t.sol
@@ -41,7 +41,7 @@ contract TestGetters is BaseConsiderationTest {
function testGetsCorrectVersion() public {
(string memory version, , ) = consideration.information();
- assertEq(version, "1.5");
+ assertEq(version, "1.6");
}
function testGetCorrectDomainSeparator() public {
diff --git a/test/foundry/MatchAdvancedOrder.t.sol b/test/foundry/MatchAdvancedOrder.t.sol
index c51793336..a2e3a0de3 100644
--- a/test/foundry/MatchAdvancedOrder.t.sol
+++ b/test/foundry/MatchAdvancedOrder.t.sol
@@ -2,7 +2,10 @@
pragma solidity ^0.8.17;
-import { OrderType, ItemType } from "seaport-types/src/lib/ConsiderationEnums.sol";
+import {
+ OrderType,
+ ItemType
+} from "seaport-types/src/lib/ConsiderationEnums.sol";
import {
ConsiderationInterface
@@ -39,6 +42,7 @@ contract MatchAdvancedOrder is BaseOrderTest {
uint128 amount;
bool useConduit;
}
+
struct FuzzInputsAscendingDescending {
address zone;
uint256 id;
@@ -51,11 +55,13 @@ contract MatchAdvancedOrder is BaseOrderTest {
bool useConduit;
uint256 warp;
}
+
struct Context {
ConsiderationInterface consideration;
FuzzInputs args;
ItemType itemType;
}
+
struct ContextAscendingDescending {
ConsiderationInterface consideration;
FuzzInputsAscendingDescending args;
diff --git a/test/foundry/MatchAdvancedOrderUnspentOffer.t.sol b/test/foundry/MatchAdvancedOrderUnspentOffer.t.sol
index 183b40d52..80f19dad4 100644
--- a/test/foundry/MatchAdvancedOrderUnspentOffer.t.sol
+++ b/test/foundry/MatchAdvancedOrderUnspentOffer.t.sol
@@ -40,25 +40,6 @@ contract MatchOrderUnspentOfferTest is BaseOrderTest {
}
}
- /**
- * @dev test that specifying the offerer as the recipient of the considerationItem results in
- * execution filtering for items not specified in the matched order(s)
- * ie: offer nft1, nft2 for erc20
- * fulfiller matches to erc20 offer, nft1 consideration
- * specifies original offerer as recipient of unspent considerations
- * fulfilling does not result in nft2 being transferred at all
- */
- function testFilterOfferItemBySpecifyingOffererAsRecipient() public {
- test(
- this.execFilterOfferItemBySpecifyingOffererAsRecipient,
- Context({ seaport: consideration })
- );
- test(
- this.execFilterOfferItemBySpecifyingOffererAsRecipient,
- Context({ seaport: referenceConsideration })
- );
- }
-
function setUpFilterOfferItemBySpecifyingOffererAsRecipient(
Context memory context
) internal returns (AdvancedOrder[] memory, Fulfillment[] memory) {
@@ -170,34 +151,6 @@ contract MatchOrderUnspentOfferTest is BaseOrderTest {
return (orders, _fulfillments);
}
- function execFilterOfferItemBySpecifyingOffererAsRecipient(
- Context memory context
- ) external stateless {
- (
- AdvancedOrder[] memory orders,
- Fulfillment[] memory _fulfillments
- ) = setUpFilterOfferItemBySpecifyingOffererAsRecipient(context);
- vm.recordLogs();
- context.seaport.matchAdvancedOrders({
- orders: orders,
- criteriaResolvers: new CriteriaResolver[](0),
- fulfillments: _fulfillments,
- recipient: makeAddr("offerer")
- });
- Vm.Log[] memory recordedLogs = vm.getRecordedLogs();
- // ensure that token2 was not transferred at any point
- assertEq(recordedLogs.length, 5);
- // first two are OrderFulfilled events
- assertEq(recordedLogs[0].emitter, address(context.seaport));
- assertEq(recordedLogs[1].emitter, address(context.seaport));
- // next is OrdersMatched event
- assertEq(recordedLogs[2].emitter, address(context.seaport));
- // next is 721_1 transfer
- assertEq(recordedLogs[3].emitter, address(test721_1));
- // last is ERC20 transfer
- assertEq(recordedLogs[4].emitter, address(token1));
- }
-
// TODO: look into sporadic failures here
function xtestSweepRemaining() public {
test(this.execSweepRemaining, Context({ seaport: consideration }));
diff --git a/test/foundry/MatchOrders.t.sol b/test/foundry/MatchOrders.t.sol
index 0fcf6a823..c42f099a7 100644
--- a/test/foundry/MatchOrders.t.sol
+++ b/test/foundry/MatchOrders.t.sol
@@ -2,7 +2,10 @@
pragma solidity ^0.8.17;
-import { OrderType, ItemType } from "seaport-types/src/lib/ConsiderationEnums.sol";
+import {
+ OrderType,
+ ItemType
+} from "seaport-types/src/lib/ConsiderationEnums.sol";
import {
Order,
@@ -23,6 +26,7 @@ import { stdError } from "forge-std/Test.sol";
contract MatchOrders is BaseOrderTest {
using ArithmeticUtil for uint128;
+
struct FuzzInputsCommon {
address zone;
uint256 id;
diff --git a/test/foundry/TransferHelperMultipleRecipientsTest.sol b/test/foundry/TransferHelperMultipleRecipientsTest.sol
index c35ac5415..ee9c3567f 100644
--- a/test/foundry/TransferHelperMultipleRecipientsTest.sol
+++ b/test/foundry/TransferHelperMultipleRecipientsTest.sol
@@ -7,7 +7,9 @@ import {
ConduitInterface
} from "seaport-types/src/interfaces/ConduitInterface.sol";
-import { ConduitItemType } from "seaport-types/src/conduit/lib/ConduitEnums.sol";
+import {
+ ConduitItemType
+} from "seaport-types/src/conduit/lib/ConduitEnums.sol";
import { TransferHelper } from "../../contracts/helpers/TransferHelper.sol";
@@ -46,7 +48,9 @@ import {
TransferHelperErrors
} from "seaport-types/src/interfaces/TransferHelperErrors.sol";
-import { IERC721Receiver } from "seaport-types/src/interfaces/IERC721Receiver.sol";
+import {
+ IERC721Receiver
+} from "seaport-types/src/interfaces/IERC721Receiver.sol";
import {
ERC721ReceiverMock
@@ -64,6 +68,7 @@ import { Strings } from "@openzeppelin/contracts/utils/Strings.sol";
contract TransferHelperMultipleRecipientsTest is BaseOrderTest {
using Strings for uint256;
+
TransferHelper transferHelper;
// Total supply of fungible tokens to be used in tests for all fungible tokens.
uint256 constant TOTAL_FUNGIBLE_TOKENS = 1e6;
diff --git a/test/foundry/TransferHelperSingleRecipientTest.sol b/test/foundry/TransferHelperSingleRecipientTest.sol
index 2ad16b383..064a323d4 100644
--- a/test/foundry/TransferHelperSingleRecipientTest.sol
+++ b/test/foundry/TransferHelperSingleRecipientTest.sol
@@ -7,7 +7,9 @@ import {
ConduitInterface
} from "seaport-types/src/interfaces/ConduitInterface.sol";
-import { ConduitItemType } from "seaport-types/src/conduit/lib/ConduitEnums.sol";
+import {
+ ConduitItemType
+} from "seaport-types/src/conduit/lib/ConduitEnums.sol";
import { TransferHelper } from "../../contracts/helpers/TransferHelper.sol";
@@ -46,7 +48,9 @@ import {
TransferHelperErrors
} from "seaport-types/src/interfaces/TransferHelperErrors.sol";
-import { IERC721Receiver } from "seaport-types/src/interfaces/IERC721Receiver.sol";
+import {
+ IERC721Receiver
+} from "seaport-types/src/interfaces/IERC721Receiver.sol";
import {
ERC721ReceiverMock
diff --git a/test/foundry/new/FractionUtil.t.sol b/test/foundry/new/FractionUtil.t.sol
index 53c74706c..16470468e 100644
--- a/test/foundry/new/FractionUtil.t.sol
+++ b/test/foundry/new/FractionUtil.t.sol
@@ -34,13 +34,13 @@ contract FractionUtilTest is Test {
);
assertEq(
results.finalFilledNumerator,
- 11,
- "Final filled numerator should be 11"
+ 33,
+ "Final filled numerator should be 33"
);
assertEq(
results.finalFilledDenominator,
- 12,
- "Final filled denominator should be 12"
+ 36,
+ "Final filled denominator should be 36"
);
assertEq(
uint256(results.status),
@@ -75,13 +75,13 @@ contract FractionUtilTest is Test {
);
assertEq(
results1.finalFilledNumerator,
- 6,
- "Final filled numerator should be 6"
+ 18,
+ "Final filled numerator should be 18"
);
assertEq(
results1.finalFilledDenominator,
- 6,
- "Final filled denominator should be 6"
+ 18,
+ "Final filled denominator should be 18"
);
assertEq(
uint256(results1.status),
@@ -118,13 +118,13 @@ contract FractionUtilTest is Test {
);
assertEq(
results2.finalFilledNumerator,
- 3,
- "Final filled numerator should be 3"
+ 1,
+ "Final filled numerator should be 1"
);
assertEq(
results2.finalFilledDenominator,
- 3,
- "Final filled denominator should be 3"
+ 1,
+ "Final filled denominator should be 1"
);
assertEq(
uint256(results2.status),
@@ -161,13 +161,13 @@ contract FractionUtilTest is Test {
);
assertEq(
results3.finalFilledNumerator,
- 3,
- "Final filled numerator should be 3"
+ 1,
+ "Final filled numerator should be 1"
);
assertEq(
results3.finalFilledDenominator,
- 3,
- "Final filled denominator should be 3"
+ 1,
+ "Final filled denominator should be 1"
);
assertEq(
uint256(results3.status),
diff --git a/test/foundry/new/FuzzEngine.t.sol b/test/foundry/new/FuzzEngine.t.sol
index e5c2dacbb..87017a3fd 100644
--- a/test/foundry/new/FuzzEngine.t.sol
+++ b/test/foundry/new/FuzzEngine.t.sol
@@ -376,8 +376,10 @@ contract FuzzEngineTest is FuzzEngine {
expectedActions[2] = SeaportInterface.matchOrders.selector;
expectedActions[3] = SeaportInterface.matchAdvancedOrders.selector;
// TODO: undo pended actions (cancel, validate)
- /** expectedActions[4] = SeaportInterface.cancel.selector;
- expectedActions[5] = SeaportInterface.validate.selector; */
+ /**
+ * expectedActions[4] = SeaportInterface.cancel.selector;
+ * expectedActions[5] = SeaportInterface.validate.selector;
+ */
FuzzTestContext memory context = FuzzTestContextLib
.from({
@@ -519,21 +521,23 @@ contract FuzzEngineTest is FuzzEngine {
);
// TODO: undo pended actions (match, cancel, validate)
- /** context = FuzzTestContextLib.from({
- orders: orders,
- seaport: getSeaport(),
- caller: address(this),
- fuzzParams: FuzzParams({ seed: 4 })
- });
- assertEq(context.action(), SeaportInterface.cancel.selector);
-
- context = FuzzTestContextLib.from({
- orders: orders,
- seaport: getSeaport(),
- caller: address(this),
- fuzzParams: FuzzParams({ seed: 5 })
- });
- assertEq(context.action(), SeaportInterface.validate.selector); */
+ /**
+ * context = FuzzTestContextLib.from({
+ * orders: orders,
+ * seaport: getSeaport(),
+ * caller: address(this),
+ * fuzzParams: FuzzParams({ seed: 4 })
+ * });
+ * assertEq(context.action(), SeaportInterface.cancel.selector);
+ *
+ * context = FuzzTestContextLib.from({
+ * orders: orders,
+ * seaport: getSeaport(),
+ * caller: address(this),
+ * fuzzParams: FuzzParams({ seed: 5 })
+ * });
+ * assertEq(context.action(), SeaportInterface.validate.selector);
+ */
}
/// @dev Call exec for a single standard order.
@@ -1723,8 +1727,8 @@ contract FuzzEngineTest is FuzzEngine {
.withChecks(checks)
.withMaximumFulfilled(2);
- context.expectations.expectedZoneCalldataHash = advancedOrders
- .getExpectedZoneCalldataHash(
+ context.expectations.expectedZoneValidateCalldataHashes = advancedOrders
+ .getExpectedZoneValidateCalldataHash(
address(getSeaport()),
address(this),
new CriteriaResolver[](0),
diff --git a/test/foundry/new/FuzzInscribers.t.sol b/test/foundry/new/FuzzInscribers.t.sol
index dcad56752..a0304b9a0 100644
--- a/test/foundry/new/FuzzInscribers.t.sol
+++ b/test/foundry/new/FuzzInscribers.t.sol
@@ -390,7 +390,9 @@ contract FuzzHelpersTest is BaseOrderTest {
keccak256(abi.encodePacked(profile)) ==
keccak256(abi.encodePacked("test")) ||
keccak256(abi.encodePacked(profile)) ==
- keccak256(abi.encodePacked("lite"))
+ keccak256(abi.encodePacked("lite")) ||
+ keccak256(abi.encodePacked(profile)) ==
+ keccak256(abi.encodePacked("reference"))
) {
expectedReadAccessCount = 1;
}
diff --git a/test/foundry/new/SeaportNavigator.t.sol b/test/foundry/new/SeaportNavigator.t.sol
index 1560582b1..631765263 100644
--- a/test/foundry/new/SeaportNavigator.t.sol
+++ b/test/foundry/new/SeaportNavigator.t.sol
@@ -2,18 +2,14 @@
pragma solidity ^0.8.17;
import {
+ AdvancedOrderLib,
+ ConsiderationInterface,
ConsiderationItemLib,
+ CriteriaResolver,
OfferItemLib,
- OrderParametersLib,
OrderComponentsLib,
OrderLib,
- OrderType,
- AdvancedOrderLib,
- ItemType,
- SeaportInterface,
- Side,
- CriteriaResolver,
- ConsiderationInterface
+ OrderParametersLib
} from "seaport-sol/src/SeaportSol.sol";
import {
@@ -25,9 +21,14 @@ import {
AdvancedOrder
} from "seaport-sol/src/SeaportStructs.sol";
+import { ItemType } from "seaport-sol/src/SeaportEnums.sol";
+
import {
- SeaportValidatorInterface
-} from "../../../contracts/helpers/order-validator/SeaportValidator.sol";
+ AggregationStrategy,
+ FulfillAvailableStrategy,
+ FulfillmentStrategy,
+ MatchStrategy
+} from "seaport-sol/src/fulfillments/lib/FulfillmentLib.sol";
import {
NavigatorRequest,
@@ -35,12 +36,6 @@ import {
SeaportNavigator
} from "../../../contracts/helpers/navigator/SeaportNavigator.sol";
-import {
- NavigatorOfferItem,
- NavigatorConsiderationItem,
- NavigatorOrderParameters
-} from "../../../contracts/helpers/navigator/lib/SeaportNavigatorTypes.sol";
-
import {
TokenIdNotFound
} from "../../../contracts/helpers/navigator/lib/CriteriaHelperLib.sol";
@@ -49,34 +44,32 @@ import {
NavigatorAdvancedOrder,
NavigatorAdvancedOrderLib
} from "../../../contracts/helpers/navigator/lib/NavigatorAdvancedOrderLib.sol";
+
import {
OrderStructureLib
} from "../../../contracts/helpers/navigator/lib/OrderStructureLib.sol";
import { BaseOrderTest } from "./BaseOrderTest.sol";
+
import { SeaportValidatorTest } from "./SeaportValidatorTest.sol";
+
import { SeaportNavigatorTest } from "./SeaportNavigatorTest.sol";
-import {
- FulfillmentStrategy,
- AggregationStrategy,
- FulfillAvailableStrategy,
- MatchStrategy
-} from "seaport-sol/src/fulfillments/lib/FulfillmentLib.sol";
+import { TestERC721 } from "../../../contracts/test/TestERC721.sol";
contract SeaportNavigatorTestSuite is
BaseOrderTest,
SeaportValidatorTest,
SeaportNavigatorTest
{
+ using AdvancedOrderLib for AdvancedOrder;
using ConsiderationItemLib for ConsiderationItem;
+ using NavigatorAdvancedOrderLib for NavigatorAdvancedOrder;
using OfferItemLib for OfferItem;
- using OrderParametersLib for OrderParameters;
using OrderComponentsLib for OrderComponents;
using OrderLib for Order;
- using AdvancedOrderLib for AdvancedOrder;
+ using OrderParametersLib for OrderParameters;
using OrderStructureLib for AdvancedOrder;
- using NavigatorAdvancedOrderLib for NavigatorAdvancedOrder;
string constant SINGLE_ERC721_SINGLE_ERC20 = "SINGLE_ERC721_SINGLE_ERC20";
string constant SINGLE_ERC721_WITH_CRITERIA_SINGLE_ERC721_WITH_CRITERIA =
@@ -193,6 +186,7 @@ contract SeaportNavigatorTestSuite is
),
"unexpected suggested calldata"
);
+
assertEq(
res.validationErrors.length,
1,
@@ -203,6 +197,7 @@ contract SeaportNavigatorTestSuite is
4,
"unexpected validationErrors[0].errors length"
);
+
assertEq(
res.validationErrors[0].warnings.length,
1,
@@ -364,6 +359,163 @@ contract SeaportNavigatorTestSuite is
);
}
+ function test_simpleOrderWithNativeReturned() public {
+ NavigatorAdvancedOrder[] memory orders = new NavigatorAdvancedOrder[](
+ 1
+ );
+
+ Order memory order = OrderLib.fromDefault(SINGLE_ERC721).copy();
+ AdvancedOrder memory advancedOrder = order.toAdvancedOrder(
+ 1,
+ 1,
+ "dummy"
+ );
+
+ address offerer = offerer1.addr;
+ OfferItem memory item = advancedOrder.parameters.offer[0];
+ TestERC721(item.token).mint(offerer, item.identifierOrCriteria);
+ vm.prank(offerer);
+ TestERC721(item.token).setApprovalForAll(address(seaport), true);
+
+ ConsiderationItem[] memory consideration = new ConsiderationItem[](1);
+ consideration[0] = ConsiderationItemLib
+ .empty()
+ .withItemType(ItemType.NATIVE)
+ .withToken(address(0))
+ .withAmount(1 ether)
+ .withRecipient(offerer);
+
+ advancedOrder.parameters = advancedOrder
+ .parameters
+ .withTotalConsideration(consideration)
+ .withOfferer(offerer);
+
+ uint256 counter = getSeaport().getCounter(offerer1.addr);
+ bytes32 orderHash = getSeaport().getOrderHash(
+ advancedOrder.parameters.toOrderComponents(counter)
+ );
+ advancedOrder = advancedOrder.withSignature(
+ signOrder(getSeaport(), offerer1.key, orderHash)
+ );
+
+ orders[0] = NavigatorAdvancedOrderLib.fromAdvancedOrder(advancedOrder);
+
+ FulfillmentStrategy memory fulfillmentStrategy = FulfillmentStrategy({
+ aggregationStrategy: AggregationStrategy.MAXIMUM,
+ fulfillAvailableStrategy: FulfillAvailableStrategy.KEEP_ALL,
+ matchStrategy: MatchStrategy.MAX_INCLUSION
+ });
+
+ NavigatorResponse memory res = navigator.prepare(
+ NavigatorRequest({
+ seaport: seaport,
+ validator: validator,
+ orders: orders,
+ caller: address(this),
+ nativeTokensSupplied: 2 ether,
+ fulfillerConduitKey: bytes32(0),
+ recipient: address(this),
+ maximumFulfilled: 1,
+ seed: 0,
+ fulfillmentStrategy: fulfillmentStrategy,
+ criteriaResolvers: new CriteriaResolver[](0),
+ preferMatch: false
+ })
+ );
+
+ assertEq(
+ res.suggestedActionName,
+ "fulfillAdvancedOrder",
+ "unexpected actionName selected"
+ );
+ assertEq(
+ res.suggestedCallData,
+ abi.encodeCall(
+ ConsiderationInterface.fulfillAdvancedOrder,
+ (
+ advancedOrder,
+ new CriteriaResolver[](0),
+ bytes32(0),
+ address(this)
+ )
+ ),
+ "unexpected suggested calldata"
+ );
+
+ if (
+ keccak256(bytes(vm.envOr("FOUNDRY_PROFILE", string("test")))) !=
+ keccak256(bytes(string("reference")))
+ ) {
+ assertEq(
+ res.validationErrors.length,
+ 1,
+ "unexpected validationErrors length"
+ );
+ assertEq(
+ res.validationErrors[0].errors.length,
+ 0,
+ "unexpected validationErrors[0].errors length"
+ );
+ }
+
+ assertEq(res.orderDetails.length, 1, "unexpected orderDetails length");
+ assertEq(
+ res.offerFulfillments.length,
+ 1,
+ "unexpected offerFulfillments length"
+ );
+ assertEq(
+ res.considerationFulfillments.length,
+ 1,
+ "unexpected considerationFulfillments length"
+ );
+ assertEq(res.fulfillments.length, 0, "unexpected fulfillments length");
+ // Specific to match* methods.
+ assertEq(
+ res.unspentOfferComponents.length,
+ 1,
+ "unexpected unspentOfferComponents length"
+ );
+ // Specific to match* methods.
+ assertEq(
+ res.unmetConsiderationComponents.length,
+ 1,
+ "unexpected unmetConsiderationComponents length"
+ );
+ // No fulfillment related stuff in this case, so no explicit executions.
+ assertEq(
+ res.explicitExecutions.length,
+ 0,
+ "unexpected explicitExecutions length"
+ );
+
+ // 2 ether to seaport
+ // ERC721 from seller to buyer
+ // 1 ether from seaport to buyer
+ // 1 ether from buyer to seller
+ assertEq(
+ res.implicitExecutions.length,
+ 4,
+ "unexpected implicitExecutions length"
+ );
+
+ assertEq(
+ res.implicitExecutionsPre.length,
+ 0,
+ "unexpected implicitExecutionsPre length"
+ );
+ assertEq(
+ res.implicitExecutionsPost.length,
+ 0,
+ "unexpected implicitExecutionsPost length"
+ );
+ assertEq(
+ res.nativeTokensReturned,
+ 1 ether,
+ "unexpected nativeTokensReturned amount"
+ );
+ }
+
function test_inferredCriteria() public {
NavigatorAdvancedOrder[] memory orders = new NavigatorAdvancedOrder[](
1
diff --git a/test/foundry/new/SeaportNavigatorTest.sol b/test/foundry/new/SeaportNavigatorTest.sol
index f13f4d274..bc00f11fa 100644
--- a/test/foundry/new/SeaportNavigatorTest.sol
+++ b/test/foundry/new/SeaportNavigatorTest.sol
@@ -1,33 +1,41 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
-import {
- SeaportNavigator
-} from "../../../contracts/helpers/navigator/SeaportNavigator.sol";
-import {
- HelperInterface
-} from "../../../contracts/helpers/navigator/lib/HelperInterface.sol";
-import {
- RequestValidator
-} from "../../../contracts/helpers/navigator/lib/RequestValidator.sol";
import {
CriteriaHelper
} from "../../../contracts/helpers/navigator/lib/CriteriaHelper.sol";
+
import {
- ValidatorHelper
-} from "../../../contracts/helpers/navigator/lib/ValidatorHelper.sol";
+ ExecutionsHelper
+} from "../../../contracts/helpers/navigator/lib/ExecutionsHelper.sol";
+
+import {
+ FulfillmentsHelper
+} from "../../../contracts/helpers/navigator/lib/FulfillmentsHelper.sol";
+
+import {
+ HelperInterface
+} from "../../../contracts/helpers/navigator/lib/HelperInterface.sol";
+
import {
OrderDetailsHelper
} from "../../../contracts/helpers/navigator/lib/OrderDetailsHelper.sol";
+
import {
- FulfillmentsHelper
-} from "../../../contracts/helpers/navigator/lib/FulfillmentsHelper.sol";
+ RequestValidator
+} from "../../../contracts/helpers/navigator/lib/RequestValidator.sol";
+
+import {
+ SeaportNavigator
+} from "../../../contracts/helpers/navigator/SeaportNavigator.sol";
+
import {
SuggestedActionHelper
} from "../../../contracts/helpers/navigator/lib/SuggestedActionHelper.sol";
+
import {
- ExecutionsHelper
-} from "../../../contracts/helpers/navigator/lib/ExecutionsHelper.sol";
+ ValidatorHelper
+} from "../../../contracts/helpers/navigator/lib/ValidatorHelper.sol";
contract SeaportNavigatorTest {
HelperInterface internal requestValidator = new RequestValidator();
@@ -39,6 +47,7 @@ contract SeaportNavigatorTest {
new SuggestedActionHelper();
HelperInterface internal executionsHelper = new ExecutionsHelper();
+ // Initialize the navigator with all its constituent helpers.
SeaportNavigator internal navigator =
new SeaportNavigator(
address(requestValidator),
diff --git a/test/foundry/new/SeaportValidator.t.sol b/test/foundry/new/SeaportValidator.t.sol
index 2f9c50c47..f412d704f 100644
--- a/test/foundry/new/SeaportValidator.t.sol
+++ b/test/foundry/new/SeaportValidator.t.sol
@@ -899,14 +899,14 @@ contract SeaportValidatorTestSuite is BaseOrderTest, SeaportValidatorTest {
right.warnings.length,
"Unexpected number of warnings"
);
- for (uint i = 0; i < left.errors.length; i++) {
+ for (uint256 i = 0; i < left.errors.length; i++) {
assertEq(
left.errors[i].toIssueString(),
right.errors[i].toIssueString(),
"Unexpected error"
);
}
- for (uint i = 0; i < left.warnings.length; i++) {
+ for (uint256 i = 0; i < left.warnings.length; i++) {
assertEq(
left.warnings[i].toIssueString(),
right.warnings[i].toIssueString(),
diff --git a/test/foundry/new/SeaportValidatorTest.sol b/test/foundry/new/SeaportValidatorTest.sol
index b65e27d23..77e9762a8 100644
--- a/test/foundry/new/SeaportValidatorTest.sol
+++ b/test/foundry/new/SeaportValidatorTest.sol
@@ -4,14 +4,9 @@ pragma solidity ^0.8.17;
import { BaseSeaportTest } from "./helpers/BaseSeaportTest.sol";
import {
- ConduitControllerInterface
-} from "seaport-sol/src/ConduitControllerInterface.sol";
-
-import {
- SeaportValidatorHelper,
+ ReadOnlyOrderValidator,
SeaportValidator,
- SeaportValidatorInterface,
- ReadOnlyOrderValidator
+ SeaportValidatorHelper
} from "../../../contracts/helpers/order-validator/SeaportValidator.sol";
contract SeaportValidatorTest is BaseSeaportTest {
@@ -28,6 +23,7 @@ contract SeaportValidatorTest is BaseSeaportTest {
seaportValidatorHelper = new SeaportValidatorHelper();
vm.chainId(chainId);
+ // Initialize the validator.
validator = new SeaportValidator(
address(new ReadOnlyOrderValidator()),
address(seaportValidatorHelper),
diff --git a/test/foundry/new/SelfRestrictedContractOfferer.t.sol b/test/foundry/new/SelfRestrictedContractOfferer.t.sol
index 3b5a50541..5e0ca978b 100644
--- a/test/foundry/new/SelfRestrictedContractOfferer.t.sol
+++ b/test/foundry/new/SelfRestrictedContractOfferer.t.sol
@@ -155,8 +155,6 @@ contract SelfRestrictedContractOffererTest is BaseOrderTest {
Fulfillment[] memory fulfillments
)
{
- erc721s[0].mint(offerer1.addr, 1);
-
AdvancedOrder memory advancedOrder;
OfferItem[] memory offer;
ConsiderationItem[] memory consideration;
@@ -168,6 +166,8 @@ contract SelfRestrictedContractOffererTest is BaseOrderTest {
uint256 considerAmount = 10;
offerer = new ValidationOffererZone(considerAmount + 1);
+ erc721s[0].mint(address(offerer), 1);
+
allocateTokensAndApprovals(address(offerer), type(uint128).max);
uint256 matchAmount = context.exactAmount
diff --git a/test/foundry/new/helpers/DebugUtil.sol b/test/foundry/new/helpers/DebugUtil.sol
index 05b0ec219..77bc39233 100644
--- a/test/foundry/new/helpers/DebugUtil.sol
+++ b/test/foundry/new/helpers/DebugUtil.sol
@@ -43,7 +43,8 @@ struct ContextOutputSelection {
bool basicOrderParameters;
bool testHelpers;
bool checks;
- bool expectedZoneCalldataHash;
+ bool expectedZoneAuthorizeCalldataHashes;
+ bool expectedZoneValidateCalldataHashes;
bool expectedContractOrderCalldataHashes;
bool expectedResults;
bool expectedImplicitExecutions;
@@ -74,7 +75,7 @@ using ExecutionFilterCast for Execution[];
*
* @param context the FuzzTestContext to serialize.
* @param outputSelection a ContextOutputSelection struct containing flags
- that define which FuzzTestContext fields to serialize.
+ * that define which FuzzTestContext fields to serialize.
*/
function dumpContext(
FuzzTestContext memory context,
@@ -236,11 +237,11 @@ function dumpContext(
cast(context.executionState.preExecOrderStatuses)
);
}
- // if (outputSelection.expectedZoneCalldataHash) {
+ // if (outputSelection.expectedZoneValidateCalldataHash) {
// jsonOut = Searializer.tojsonDynArrayBytes32(
// "root",
- // "expectedZoneCalldataHash",
- // context.expectations.expectedZoneCalldataHash
+ // "expectedZoneValidateCalldataHash",
+ // context.expectations.expectedZoneValidateCalldataHash
// );
// }
// if (outputSelection.expectedContractOrderCalldataHashes) {
diff --git a/test/foundry/new/helpers/EIP1271Offerer.sol b/test/foundry/new/helpers/EIP1271Offerer.sol
index 9345db15e..abc9424ce 100644
--- a/test/foundry/new/helpers/EIP1271Offerer.sol
+++ b/test/foundry/new/helpers/EIP1271Offerer.sol
@@ -1,9 +1,11 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.13;
+
import { ERC1155Recipient } from "../../utils/ERC1155Recipient.sol";
contract EIP1271Offerer is ERC1155Recipient {
error EIP1271OffererInvalidSignature(bytes32 digest, bytes signature);
+
bytes4 private constant _EIP_1271_MAGIC_VALUE = 0x1626ba7e;
mapping(bytes32 => bytes32) public digestToSignatureHash;
diff --git a/test/foundry/new/helpers/ExpectedBalances.sol b/test/foundry/new/helpers/ExpectedBalances.sol
index 269d70e08..49cccb188 100644
--- a/test/foundry/new/helpers/ExpectedBalances.sol
+++ b/test/foundry/new/helpers/ExpectedBalances.sol
@@ -59,17 +59,17 @@ struct ERC1155AccountDump {
address account;
uint256[] identifiers;
uint256[] balances;
- // ERC1155IdentifierDump[] identifiers;
}
+// ERC1155IdentifierDump[] identifiers;
struct ERC1155TokenDump {
address token;
ERC1155AccountDump[] accounts;
- // address[] accounts;
- // uint256[][] accountIdentifiers;
- // uint256[][] accountBalances;
- // ERC1155AccountDump[] accounts;
}
+// address[] accounts;
+// uint256[][] accountIdentifiers;
+// uint256[][] accountBalances;
+// ERC1155AccountDump[] accounts;
struct ExpectedBalancesDump {
ERC20TokenDump[] erc20;
@@ -498,6 +498,7 @@ contract ERC721Balances {
EnumerableSet.UintSet touchedIdentifiers;
EnumerableMap.AddressToUintMap accountBalances;
}
+
EnumerableSet.AddressSet private tokens;
mapping(address => TokenData721) private tokenDatas;
diff --git a/test/foundry/new/helpers/FractionUtil.sol b/test/foundry/new/helpers/FractionUtil.sol
index c635b84a7..ae0857f39 100644
--- a/test/foundry/new/helpers/FractionUtil.sol
+++ b/test/foundry/new/helpers/FractionUtil.sol
@@ -119,10 +119,41 @@ library FractionUtil {
status = FractionStatus.WHOLE_FILL;
}
+ uint120 realizedNumerator = uint120(numerator);
+ uint120 realizedDenominator = uint120(denominator);
+
+ filledNumerator = currentStatusNumerator;
+
+ // if supplied denominator differs from current one...
+ if (currentStatusDenominator != denominator) {
+ // scale current numerator by the supplied denominator, then...
+ filledNumerator *= denominator;
+
+ // the supplied numerator & denominator by current denominator.
+ numerator *= currentStatusDenominator;
+ denominator *= currentStatusDenominator;
+ }
+
+ // Increment the filled numerator by the new numerator.
+ filledNumerator += numerator;
+
+ // Ensure fractional amounts are below max uint120.
+ if (
+ filledNumerator > type(uint120).max ||
+ denominator > type(uint120).max
+ ) {
+ // Derive greatest common divisor using euclidean algorithm.
+ uint256 scaleDown = _gcd(filledNumerator, denominator);
+
+ // Scale new filled fractional values down by gcd.
+ filledNumerator = filledNumerator / scaleDown;
+ denominator = denominator / scaleDown;
+ }
+
return
FractionResults({
- realizedNumerator: uint120(numerator),
- realizedDenominator: uint120(denominator),
+ realizedNumerator: realizedNumerator,
+ realizedDenominator: realizedDenominator,
finalFilledNumerator: uint120(filledNumerator),
finalFilledDenominator: uint120(denominator),
originalStatusNumerator: currentStatusNumerator,
diff --git a/test/foundry/new/helpers/FuzzChecks.sol b/test/foundry/new/helpers/FuzzChecks.sol
index 3630c97d4..67482c192 100644
--- a/test/foundry/new/helpers/FuzzChecks.sol
+++ b/test/foundry/new/helpers/FuzzChecks.sol
@@ -116,6 +116,56 @@ abstract contract FuzzChecks is Test {
}
}
+ /**
+ * @dev Check that the zone is getting the right calldata in authorizeOrder.
+ *
+ * @param context A Fuzz test context.
+ */
+ function check_authorizeOrderExpectedDataHash(
+ FuzzTestContext memory context
+ ) public {
+ // Iterate over the orders.
+ for (uint256 i; i < context.executionState.orders.length; i++) {
+ OrderParameters memory order = context
+ .executionState
+ .orders[i]
+ .parameters;
+
+ // If the order is restricted, check the calldata.
+ if (
+ order.orderType == OrderType.FULL_RESTRICTED ||
+ order.orderType == OrderType.PARTIAL_RESTRICTED
+ ) {
+ testZone = payable(order.zone);
+
+ // Each order has a calldata hash, indexed to orders, that is
+ // expected to be returned by the zone.
+ bytes32 expectedCalldataHash = context
+ .expectations
+ .expectedZoneAuthorizeCalldataHashes[i];
+
+ bytes32 orderHash = context
+ .executionState
+ .orderDetails[i]
+ .orderHash;
+
+ // Use order hash to get the expected calldata hash from zone.
+ // TODO: fix this in cases where contract orders are part of
+ // orderHashes (the hash calculation is most likely incorrect).
+ bytes32 actualCalldataHash = HashValidationZoneOfferer(testZone)
+ .orderHashToAuthorizeOrderDataHash(orderHash);
+
+ // Check that the expected calldata hash matches the actual
+ // calldata hash.
+ assertEq(
+ actualCalldataHash,
+ expectedCalldataHash,
+ "check_authorizeOrderExpectedDataHash: actualCalldataHash != expectedCalldataHash"
+ );
+ }
+ }
+ }
+
/**
* @dev Check that the zone is getting the right calldata.
*
@@ -142,7 +192,7 @@ abstract contract FuzzChecks is Test {
// expected to be returned by the zone.
bytes32 expectedCalldataHash = context
.expectations
- .expectedZoneCalldataHash[i];
+ .expectedZoneValidateCalldataHashes[i];
bytes32 orderHash = context
.executionState
diff --git a/test/foundry/new/helpers/FuzzEngineLib.sol b/test/foundry/new/helpers/FuzzEngineLib.sol
index 94b5cd8b3..816fb5ed9 100644
--- a/test/foundry/new/helpers/FuzzEngineLib.sol
+++ b/test/foundry/new/helpers/FuzzEngineLib.sol
@@ -113,7 +113,7 @@ library FuzzEngineLib {
) internal view returns (bytes4[] memory) {
Family family = context.executionState.orders.getFamily();
- bool invalidOfferItemsLocated = mustUseMatch(context);
+ bool containsOrderThatDemandsMatch = mustUseMatch(context);
Structure structure = context.executionState.orders.getStructure(
address(context.seaport)
@@ -136,7 +136,7 @@ library FuzzEngineLib {
}
if (hasUnavailable) {
- if (invalidOfferItemsLocated) {
+ if (containsOrderThatDemandsMatch) {
revert(
"FuzzEngineLib: invalid native token + unavailable combination"
);
@@ -160,7 +160,7 @@ library FuzzEngineLib {
}
}
- if (family == Family.SINGLE && !invalidOfferItemsLocated) {
+ if (family == Family.SINGLE && !containsOrderThatDemandsMatch) {
if (structure == Structure.BASIC) {
bytes4[] memory selectors = new bytes4[](6);
selectors[0] = context.seaport.fulfillOrder.selector;
@@ -204,7 +204,7 @@ library FuzzEngineLib {
bool cannotMatch = (context.executionState.hasRemainders ||
hasUnavailable);
- if (cannotMatch && invalidOfferItemsLocated) {
+ if (cannotMatch && containsOrderThatDemandsMatch) {
revert("FuzzEngineLib: cannot fulfill provided combined order");
}
@@ -227,7 +227,7 @@ library FuzzEngineLib {
//selectors[3] = context.seaport.validate.selector;
return selectors;
}
- } else if (invalidOfferItemsLocated) {
+ } else if (containsOrderThatDemandsMatch) {
if (structure == Structure.ADVANCED) {
bytes4[] memory selectors = new bytes4[](1);
selectors[0] = context.seaport.matchAdvancedOrders.selector;
diff --git a/test/foundry/new/helpers/FuzzExecutor.sol b/test/foundry/new/helpers/FuzzExecutor.sol
index 6d13999b3..cf449d061 100644
--- a/test/foundry/new/helpers/FuzzExecutor.sol
+++ b/test/foundry/new/helpers/FuzzExecutor.sol
@@ -78,8 +78,9 @@ abstract contract FuzzExecutor is Test {
logCall("fulfillOrder", logCalls);
AdvancedOrder memory order = context.executionState.orders[0];
- if (context.executionState.caller != address(0))
+ if (context.executionState.caller != address(0)) {
vm.prank(context.executionState.caller);
+ }
context.returnValues.fulfilled = context.seaport.fulfillOrder{
value: context.executionState.value
}(order.toOrder(), context.executionState.fulfillerConduitKey);
@@ -87,8 +88,9 @@ abstract contract FuzzExecutor is Test {
logCall("fulfillAdvancedOrder", logCalls);
AdvancedOrder memory order = context.executionState.orders[0];
- if (context.executionState.caller != address(0))
+ if (context.executionState.caller != address(0)) {
vm.prank(context.executionState.caller);
+ }
context.returnValues.fulfilled = context
.seaport
.fulfillAdvancedOrder{ value: context.executionState.value }(
@@ -111,8 +113,9 @@ abstract contract FuzzExecutor is Test {
.executionState
.fulfillerConduitKey;
- if (context.executionState.caller != address(0))
+ if (context.executionState.caller != address(0)) {
vm.prank(context.executionState.caller);
+ }
context.returnValues.fulfilled = context.seaport.fulfillBasicOrder{
value: context.executionState.value
}(basicOrderParameters);
@@ -133,8 +136,9 @@ abstract contract FuzzExecutor is Test {
.executionState
.fulfillerConduitKey;
- if (context.executionState.caller != address(0))
+ if (context.executionState.caller != address(0)) {
vm.prank(context.executionState.caller);
+ }
context.returnValues.fulfilled = context
.seaport
.fulfillBasicOrder_efficient_6GL6yc{
@@ -142,8 +146,9 @@ abstract contract FuzzExecutor is Test {
}(basicOrderParameters);
} else if (_action == context.seaport.fulfillAvailableOrders.selector) {
logCall("fulfillAvailableOrders", logCalls);
- if (context.executionState.caller != address(0))
+ if (context.executionState.caller != address(0)) {
vm.prank(context.executionState.caller);
+ }
(
bool[] memory availableOrders,
Execution[] memory executions
@@ -163,8 +168,9 @@ abstract contract FuzzExecutor is Test {
_action == context.seaport.fulfillAvailableAdvancedOrders.selector
) {
logCall("fulfillAvailableAdvancedOrders", logCalls);
- if (context.executionState.caller != address(0))
+ if (context.executionState.caller != address(0)) {
vm.prank(context.executionState.caller);
+ }
(
bool[] memory availableOrders,
Execution[] memory executions
@@ -184,8 +190,9 @@ abstract contract FuzzExecutor is Test {
context.returnValues.executions = executions;
} else if (_action == context.seaport.matchOrders.selector) {
logCall("matchOrders", logCalls);
- if (context.executionState.caller != address(0))
+ if (context.executionState.caller != address(0)) {
vm.prank(context.executionState.caller);
+ }
Execution[] memory executions = context.seaport.matchOrders{
value: context.executionState.value
}(
@@ -196,8 +203,9 @@ abstract contract FuzzExecutor is Test {
context.returnValues.executions = executions;
} else if (_action == context.seaport.matchAdvancedOrders.selector) {
logCall("matchAdvancedOrders", logCalls);
- if (context.executionState.caller != address(0))
+ if (context.executionState.caller != address(0)) {
vm.prank(context.executionState.caller);
+ }
Execution[] memory executions = context.seaport.matchAdvancedOrders{
value: context.executionState.value
}(
@@ -223,15 +231,17 @@ abstract contract FuzzExecutor is Test {
.toOrderComponents(context.executionState.counter);
}
- if (context.executionState.caller != address(0))
+ if (context.executionState.caller != address(0)) {
vm.prank(context.executionState.caller);
+ }
context.returnValues.cancelled = context.seaport.cancel(
orderComponents
);
} else if (_action == context.seaport.validate.selector) {
logCall("validate", logCalls);
- if (context.executionState.caller != address(0))
+ if (context.executionState.caller != address(0)) {
vm.prank(context.executionState.caller);
+ }
context.returnValues.validated = context.seaport.validate(
context.executionState.orders.toOrders()
);
diff --git a/test/foundry/new/helpers/FuzzGenerators.sol b/test/foundry/new/helpers/FuzzGenerators.sol
index a8aaaeb05..54581094b 100644
--- a/test/foundry/new/helpers/FuzzGenerators.sol
+++ b/test/foundry/new/helpers/FuzzGenerators.sol
@@ -161,9 +161,8 @@ library TestStateGenerator {
for (uint256 i; i < totalOrders; ++i) {
UnavailableReason reason = (
context.randRange(0, 1) == 0
- ? UnavailableReason.AVAILABLE // Don't fuzz 5 (maxfulfilled satisfied), since it's a more // of a consequence (to be handled in derivers) than a
- : // target.
- UnavailableReason(
+ ? UnavailableReason.AVAILABLE // Don't fuzz 5 (maxfulfilled satisfied), since it's a more // of a consequence (to be handled in derivers) than a // target.
+ : UnavailableReason(
context.choice(Solarray.uint256s(1, 2, 3, 4, 6))
)
);
@@ -2434,8 +2433,9 @@ function bound(
// Similarly for the UINT256_MAX side. This helps ensure coverage of the
// min/max values.
if (x <= 3 && size > x) return min + x;
- if (x >= type(uint256).max - 3 && size > type(uint256).max - x)
+ if (x >= type(uint256).max - 3 && size > type(uint256).max - x) {
return max - (type(uint256).max - x);
+ }
// Otherwise, wrap x into the range [min, max], i.e. the range is inclusive.
if (x > max) {
diff --git a/test/foundry/new/helpers/FuzzHelpers.sol b/test/foundry/new/helpers/FuzzHelpers.sol
index a277383db..afdb59d79 100644
--- a/test/foundry/new/helpers/FuzzHelpers.sol
+++ b/test/foundry/new/helpers/FuzzHelpers.sol
@@ -355,8 +355,9 @@ library FuzzHelpers {
uint256 totalSize
) = seaport.getOrderStatus(orderHash);
- if (totalFilled != 0 && totalSize != 0 && totalFilled == totalSize)
+ if (totalFilled != 0 && totalSize != 0 && totalFilled == totalSize) {
return State.FULLY_FILLED;
+ }
if (totalFilled != 0 && totalSize != 0) return State.PARTIALLY_FILLED;
if (isCancelled) return State.CANCELLED;
if (isValidated) return State.VALIDATED;
@@ -722,6 +723,50 @@ library FuzzHelpers {
}
}
+ /**
+ * @dev Derive ZoneParameters from a given restricted order and return
+ * the expected calldata hash for the call to authorizeOrder.
+ *
+ * @param orders The restricted orders.
+ * @param seaport The Seaport address.
+ * @param fulfiller The fulfiller.
+ * @param maximumFulfilled The maximum number of orders to fulfill.
+ * @param criteriaResolvers The criteria resolvers.
+ * @param maximumFulfilled The maximum number of orders to fulfill.
+ * @param unavailableReasons The availability status.
+ *
+ * @return calldataHashes The derived calldata hashes.
+ */
+ function getExpectedZoneAuthorizeCalldataHash(
+ AdvancedOrder[] memory orders,
+ address seaport,
+ address fulfiller,
+ CriteriaResolver[] memory criteriaResolvers,
+ uint256 maximumFulfilled,
+ UnavailableReason[] memory unavailableReasons
+ ) internal view returns (bytes32[] memory calldataHashes) {
+ calldataHashes = new bytes32[](orders.length);
+
+ ZoneParameters[] memory zoneParameters = orders
+ .getZoneAuthorizeParameters(
+ fulfiller,
+ maximumFulfilled,
+ seaport,
+ criteriaResolvers,
+ unavailableReasons
+ );
+
+ for (uint256 i; i < zoneParameters.length; ++i) {
+ // Derive the expected calldata hash for the call to authorizeOrder
+ calldataHashes[i] = keccak256(
+ abi.encodeCall(
+ ZoneInterface.authorizeOrder,
+ (zoneParameters[i])
+ )
+ );
+ }
+ }
+
/**
* @dev Derive ZoneParameters from a given restricted order and return
* the expected calldata hash for the call to validateOrder.
@@ -736,7 +781,7 @@ library FuzzHelpers {
*
* @return calldataHashes The derived calldata hashes.
*/
- function getExpectedZoneCalldataHash(
+ function getExpectedZoneValidateCalldataHash(
AdvancedOrder[] memory orders,
address seaport,
address fulfiller,
@@ -746,13 +791,14 @@ library FuzzHelpers {
) internal view returns (bytes32[] memory calldataHashes) {
calldataHashes = new bytes32[](orders.length);
- ZoneParameters[] memory zoneParameters = orders.getZoneParameters(
- fulfiller,
- maximumFulfilled,
- seaport,
- criteriaResolvers,
- unavailableReasons
- );
+ ZoneParameters[] memory zoneParameters = orders
+ .getZoneValidateParameters(
+ fulfiller,
+ maximumFulfilled,
+ seaport,
+ criteriaResolvers,
+ unavailableReasons
+ );
for (uint256 i; i < zoneParameters.length; ++i) {
// Derive the expected calldata hash for the call to validateOrder
@@ -808,6 +854,36 @@ library FuzzHelpers {
.consideration
.toSpentItemArray();
+ // apply criteria resolvers before hashing
+ for (
+ uint256 j = 0;
+ j < context.executionState.criteriaResolvers.length;
+ ++j
+ ) {
+ CriteriaResolver memory resolver = context
+ .executionState
+ .criteriaResolvers[j];
+
+ if (resolver.orderIndex != i) {
+ continue;
+ }
+
+ // NOTE: assumes that all provided resolvers are valid
+ if (resolver.side == Side.OFFER) {
+ minimumReceived[resolver.index].itemType = ItemType(
+ uint256(minimumReceived[resolver.index].itemType) - 2
+ );
+ minimumReceived[resolver.index].identifier = resolver
+ .identifier;
+ } else {
+ maximumSpent[resolver.index].itemType = ItemType(
+ uint256(maximumSpent[resolver.index].itemType) - 2
+ );
+ maximumSpent[resolver.index].identifier = resolver
+ .identifier;
+ }
+ }
+
// Derive the expected calldata hash for the call to generateOrder
calldataHashes[i][0] = keccak256(
abi.encodeCall(
diff --git a/test/foundry/new/helpers/FuzzInscribers.sol b/test/foundry/new/helpers/FuzzInscribers.sol
index 609e60ac7..1ddd2b273 100644
--- a/test/foundry/new/helpers/FuzzInscribers.sol
+++ b/test/foundry/new/helpers/FuzzInscribers.sol
@@ -332,7 +332,9 @@ library FuzzInscribers {
keccak256(abi.encodePacked(profile)) ==
keccak256(abi.encodePacked("test")) ||
keccak256(abi.encodePacked(profile)) ==
- keccak256(abi.encodePacked("lite"))
+ keccak256(abi.encodePacked("lite")) ||
+ keccak256(abi.encodePacked(profile)) ==
+ keccak256(abi.encodePacked("reference"))
) {
expectedReadAccessCount = 1;
}
diff --git a/test/foundry/new/helpers/FuzzMutationSelectorLib.sol b/test/foundry/new/helpers/FuzzMutationSelectorLib.sol
index e85458f08..7d044afc2 100644
--- a/test/foundry/new/helpers/FuzzMutationSelectorLib.sol
+++ b/test/foundry/new/helpers/FuzzMutationSelectorLib.sol
@@ -112,10 +112,10 @@ enum Failure {
InvalidContractOrder_ExcessMaximumSpent, // too many maximum spent items
InvalidContractOrder_IncorrectMaximumSpent, // incorrect (too many, wrong token, etc.) maximum spent items
InvalidContractOrder_InvalidMagicValue, // Offerer did not return correct magic value
- InvalidContractOrder_OfferAmountMismatch, // startAmount != endAmount on contract order offer item
- InvalidContractOrder_ConsiderationAmountMismatch, // startAmount != endAmount on contract order consideration item
- InvalidRestrictedOrder_reverts, // Zone validateOrder call reverts
- InvalidRestrictedOrder_InvalidMagicValue, // Zone validateOrder call returns invalid magic value
+ InvalidRestrictedOrder_authorizeReverts_matchReverts, // Zone authorizeOrder call reverts and triggers a top level match* revert
+ InvalidRestrictedOrder_validateReverts, // Zone validateOrder call reverts
+ InvalidRestrictedOrder_authorizeInvalidMagicValue, // Zone authorizeOrder call returns invalid magic value
+ InvalidRestrictedOrder_validateInvalidMagicValue, // Zone validateOrder call returns invalid magic value
NoContract, // Trying to transfer a token at an address that has no contract
UnusedItemParameters_Token, // Native item with non-zero token
UnusedItemParameters_Identifier, // Native or ERC20 item with non-zero identifier
@@ -347,7 +347,6 @@ library FuzzMutationSelectorLib {
failuresAndFilters[i++] = Failure
.InvalidContractOrder_InsufficientMinimumReceived
.and(Failure.InvalidContractOrder_IncorrectMinimumReceived)
- .and(Failure.InvalidContractOrder_OfferAmountMismatch)
.withOrder(
MutationFilters
.ineligibleWhenNotActiveTimeOrNotContractOrderOrNoOffer
@@ -361,15 +360,22 @@ library FuzzMutationSelectorLib {
failuresAndFilters[i++] = Failure
.InvalidContractOrder_IncorrectMaximumSpent
- .and(Failure.InvalidContractOrder_ConsiderationAmountMismatch)
.withOrder(
MutationFilters
.ineligibleWhenNotActiveTimeOrNotContractOrderOrNoConsideration
);
failuresAndFilters[i++] = Failure
- .InvalidRestrictedOrder_reverts
- .and(Failure.InvalidRestrictedOrder_InvalidMagicValue)
+ .InvalidRestrictedOrder_authorizeReverts_matchReverts
+ .withOrder(
+ MutationFilters
+ .ineligibleWhenFulfillAvailableOrNotAvailableOrNotRestricted
+ );
+
+ failuresAndFilters[i++] = Failure
+ .InvalidRestrictedOrder_authorizeInvalidMagicValue
+ .and(Failure.InvalidRestrictedOrder_validateReverts)
+ .and(Failure.InvalidRestrictedOrder_validateInvalidMagicValue)
.withOrder(
MutationFilters.ineligibleWhenNotAvailableOrNotRestrictedOrder
);
@@ -841,15 +847,14 @@ library FailureDetailsLib {
details_withOrderHash
);
- failureDetailsArray[i++] = ZoneInteractionErrors
- .InvalidContractOrder
+ failureDetailsArray[i++] = HashCalldataContractOfferer
+ .HashCalldataContractOffererGenerateOrderReverts
.selector
.withOrder(
"InvalidContractOrder_generateReverts",
FuzzMutations
- .mutation_invalidContractOrderGenerateReturnsInvalidEncoding
- .selector,
- details_withOrderHash
+ .mutation_invalidContractOrderGenerateReverts
+ .selector
);
failureDetailsArray[i++] = HashCalldataContractOfferer
@@ -917,46 +922,46 @@ library FailureDetailsLib {
details_withOrderHash
);
- failureDetailsArray[i++] = ZoneInteractionErrors
- .InvalidContractOrder
+ failureDetailsArray[i++] = HashValidationZoneOfferer
+ .HashValidationZoneOffererAuthorizeOrderReverts
.selector
.withOrder(
- "InvalidContractOrder_OfferAmountMismatch",
+ "InvalidRestrictedOrder_authorizeReverts_matchReverts",
FuzzMutations
- .mutation_invalidContractOrderOfferAmountMismatch
- .selector,
- details_withOrderHash
+ .mutation_invalidRestrictedOrderAuthorizeRevertsMatchReverts
+ .selector
);
- failureDetailsArray[i++] = ZoneInteractionErrors
- .InvalidContractOrder
+ failureDetailsArray[i++] = HashValidationZoneOfferer
+ .HashValidationZoneOffererValidateOrderReverts
.selector
.withOrder(
- "InvalidContractOrder_ConsiderationAmountMismatch",
- FuzzMutations
- .mutation_invalidContractOrderConsiderationAmountMismatch
- .selector,
- details_withOrderHash
+ "InvalidRestrictedOrder_validateReverts",
+ FuzzMutations.mutation_invalidRestrictedOrderReverts.selector
);
- failureDetailsArray[i++] = HashValidationZoneOfferer
- .HashValidationZoneOffererValidateOrderReverts
+ failureDetailsArray[i++] = ZoneInteractionErrors
+ .InvalidRestrictedOrder
.selector
.withOrder(
- "InvalidRestrictedOrder_reverts",
- FuzzMutations.mutation_invalidRestrictedOrderReverts.selector
+ "InvalidRestrictedOrder_authorizeInvalidMagicValue",
+ FuzzMutations
+ .mutation_invalidRestrictedOrderAuthorizeInvalidMagicValue
+ .selector,
+ details_withOrderHash
);
failureDetailsArray[i++] = ZoneInteractionErrors
.InvalidRestrictedOrder
.selector
.withOrder(
- "InvalidRestrictedOrder_InvalidMagicValue",
+ "InvalidRestrictedOrder_validateInvalidMagicValue",
FuzzMutations
- .mutation_invalidRestrictedOrderInvalidMagicValue
+ .mutation_invalidRestrictedOrderValidateInvalidMagicValue
.selector,
details_withOrderHash
);
+
failureDetailsArray[i++] = TokenTransferrerErrors
.NoContract
.selector
diff --git a/test/foundry/new/helpers/FuzzMutations.sol b/test/foundry/new/helpers/FuzzMutations.sol
index 396df8a75..c58e6681f 100644
--- a/test/foundry/new/helpers/FuzzMutations.sol
+++ b/test/foundry/new/helpers/FuzzMutations.sol
@@ -265,6 +265,22 @@ library MutationFilters {
return ineligibleWhenUnavailable(context, orderIndex);
}
+ function ineligibleWhenFulfillAvailableOrNotAvailableOrNotRestricted(
+ AdvancedOrder memory order,
+ uint256 orderIndex,
+ FuzzTestContext memory context
+ ) internal view returns (bool) {
+ if (ineligibleWhenNotRestrictedOrder(order)) {
+ return true;
+ }
+
+ if (ineligibleWhenFulfillAvailable(context)) {
+ return true;
+ }
+
+ return ineligibleWhenUnavailable(context, orderIndex);
+ }
+
function ineligibleWhenNotActiveTime(
AdvancedOrder memory order
) internal view returns (bool) {
@@ -636,11 +652,11 @@ library MutationFilters {
continue;
}
- AdvancedOrder memory order = context.executionState.previewedOrders[
- i
- ];
+ AdvancedOrder memory order = context.executionState.orders[i];
+
uint256 items = order.parameters.offer.length +
order.parameters.consideration.length;
+
if (items != 0) {
locatedItem = true;
break;
@@ -735,6 +751,26 @@ library MutationFilters {
return true;
}
+ // The target failure can't be triggered if the criteria resolver is
+ // referring to a collection-level criteria item on a contract order.
+ if (
+ context
+ .executionState
+ .orders[criteriaResolver.orderIndex]
+ .parameters
+ .orderType ==
+ OrderType.CONTRACT &&
+ context
+ .executionState
+ .orders[criteriaResolver.orderIndex]
+ .parameters
+ .offer[criteriaResolver.index]
+ .identifierOrCriteria ==
+ 0
+ ) {
+ return true;
+ }
+
return false;
}
@@ -762,6 +798,26 @@ library MutationFilters {
return true;
}
+ // The target failure can't be triggered if the criteria resolver is
+ // referring to a collection-level criteria item on a contract order.
+ if (
+ context
+ .executionState
+ .orders[criteriaResolver.orderIndex]
+ .parameters
+ .orderType ==
+ OrderType.CONTRACT &&
+ context
+ .executionState
+ .orders[criteriaResolver.orderIndex]
+ .parameters
+ .consideration[criteriaResolver.index]
+ .identifierOrCriteria ==
+ 0
+ ) {
+ return true;
+ }
+
return false;
}
@@ -1543,14 +1599,24 @@ library MutationFilters {
uint256 orderIndex,
FuzzTestContext memory context
) internal view returns (bool) {
- // The target failure cannot be triggered in the fulfillAvailable cases
- // because it gets skipped instead. And the match cases cause a
- // MismatchedFulfillmentOfferAndConsiderationComponents(uint256)
- // instead.
- if (
- ineligibleWhenFulfillAvailable(context) ||
- ineligibleWhenMatch(context)
- ) {
+ // The target failure can't be triggered if the order isn't available.
+ if (ineligibleWhenUnavailable(context, orderIndex)) {
+ return true;
+ }
+
+ // The target failure cannot be triggered in fulfillAvailable cases —
+ // they trip a InvalidFulfillmentComponentData error instead. TODO:
+ // perform the mutation on all items that are part of a single
+ // fulfillment element.
+ if (ineligibleWhenFulfillAvailable(context)) {
+ return true;
+ }
+
+ // The target failure cannot be triggered in match cases — they trip a
+ // MismatchedFulfillmentOfferAndConsiderationComponents(uint256) error
+ // instead. TODO: perform the mutation on all items that are part of a
+ // single fulfillment element.
+ if (ineligibleWhenMatch(context)) {
return true;
}
@@ -1586,14 +1652,24 @@ library MutationFilters {
uint256 orderIndex,
FuzzTestContext memory context
) internal view returns (bool) {
- // The target failure cannot be triggered in the fulfillAvailable cases
- // because it gets skipped instead. And the match cases cause a
- // MismatchedFulfillmentOfferAndConsiderationComponents(uint256)
- // instead.
- if (
- ineligibleWhenFulfillAvailable(context) ||
- ineligibleWhenMatch(context)
- ) {
+ // The target failure can't be triggered if the order isn't available.
+ if (ineligibleWhenUnavailable(context, orderIndex)) {
+ return true;
+ }
+
+ // The target failure cannot be triggered in fulfillAvailable cases —
+ // they trip a InvalidFulfillmentComponentData error instead. TODO:
+ // perform the mutation on all items that are part of a single
+ // fulfillment element.
+ if (ineligibleWhenFulfillAvailable(context)) {
+ return true;
+ }
+
+ // The target failure cannot be triggered in match cases — they trip a
+ // MismatchedFulfillmentOfferAndConsiderationComponents(uint256) error
+ // instead. TODO: perform the mutation on all items that are part of a
+ // single fulfillment element.
+ if (ineligibleWhenMatch(context)) {
return true;
}
@@ -1940,6 +2016,26 @@ contract FuzzMutations is Test, FuzzExecutor {
exec(context);
}
+ function mutation_invalidRestrictedOrderAuthorizeRevertsMatchReverts(
+ FuzzTestContext memory context,
+ MutationState memory mutationState
+ ) external {
+ AdvancedOrder memory order = mutationState.selectedOrder;
+ bytes32 orderHash = mutationState.selectedOrderHash;
+
+ // This mutation triggers a revert by setting a failure reason that gets
+ // stored in the HashValidationZone. Note that only
+ // non-fulfillAvailable* functions revert at the seaport level when the
+ // zone reverts on authorize.
+ HashValidationZoneOfferer(payable(order.parameters.zone))
+ .setAuthorizeFailureReason(
+ orderHash,
+ OffererZoneFailureReason.Zone_authorizeRevertsMatchReverts
+ );
+
+ exec(context);
+ }
+
function mutation_invalidRestrictedOrderReverts(
FuzzTestContext memory context,
MutationState memory mutationState
@@ -1948,14 +2044,17 @@ contract FuzzMutations is Test, FuzzExecutor {
bytes32 orderHash = mutationState.selectedOrderHash;
// This mutation triggers a revert by setting a failure reason that gets
- // stored in the HashCalldataContractOfferer.
+ // stored in the HashValidationZoneOfferer.
HashValidationZoneOfferer(payable(order.parameters.zone))
- .setFailureReason(orderHash, OffererZoneFailureReason.Zone_reverts);
+ .setValidateFailureReason(
+ orderHash,
+ OffererZoneFailureReason.Zone_validateReverts
+ );
exec(context);
}
- function mutation_invalidRestrictedOrderInvalidMagicValue(
+ function mutation_invalidRestrictedOrderAuthorizeInvalidMagicValue(
FuzzTestContext memory context,
MutationState memory mutationState
) external {
@@ -1963,11 +2062,29 @@ contract FuzzMutations is Test, FuzzExecutor {
bytes32 orderHash = mutationState.selectedOrderHash;
// This mutation triggers a revert by setting a failure reason that gets
- // stored in the HashCalldataContractOfferer.
+ // stored in the HashValidationZone.
HashValidationZoneOfferer(payable(order.parameters.zone))
- .setFailureReason(
+ .setAuthorizeFailureReason(
+ orderHash,
+ OffererZoneFailureReason.Zone_authorizeInvalidMagicValue
+ );
+
+ exec(context);
+ }
+
+ function mutation_invalidRestrictedOrderValidateInvalidMagicValue(
+ FuzzTestContext memory context,
+ MutationState memory mutationState
+ ) external {
+ AdvancedOrder memory order = mutationState.selectedOrder;
+ bytes32 orderHash = mutationState.selectedOrderHash;
+
+ // This mutation triggers a revert by setting a failure reason that gets
+ // stored in the HashValidationZone.
+ HashValidationZoneOfferer(payable(order.parameters.zone))
+ .setValidateFailureReason(
orderHash,
- OffererZoneFailureReason.Zone_InvalidMagicValue
+ OffererZoneFailureReason.Zone_validateInvalidMagicValue
);
exec(context);
@@ -2279,7 +2396,7 @@ contract FuzzMutations is Test, FuzzExecutor {
}
// Grab the order at the current index.
- AdvancedOrder memory order = context.executionState.previewedOrders[
+ AdvancedOrder memory order = context.executionState.orders[
orderIndex
];
@@ -2943,7 +3060,7 @@ contract FuzzMutations is Test, FuzzExecutor {
// This mutation triggers a revert by modifying the first proof element
// in a criteria resolver's proof array. Seaport will reject a criteria
- // resolver if the the identifiers, criteria, and proof do not
+ // resolver if the identifiers, criteria, and proof do not
// harmonize.
bytes32 firstProofElement = resolver.criteriaProof[0];
@@ -3022,10 +3139,10 @@ contract FuzzMutations is Test, FuzzExecutor {
.executionState
.criteriaResolvers[criteriaResolverIndex];
- OrderDetails memory order = context.executionState.orderDetails[
+ AdvancedOrder memory order = context.executionState.orders[
resolver.orderIndex
];
- resolver.index = order.consideration.length;
+ resolver.index = order.parameters.consideration.length;
exec(context);
}
@@ -3323,6 +3440,29 @@ contract FuzzMutations is Test, FuzzExecutor {
}
}
+ // For basic orders, the additional recipient items also need to be
+ // modified.
+ bytes4 action = context.action();
+ if (
+ action == context.seaport.fulfillBasicOrder.selector ||
+ action ==
+ context.seaport.fulfillBasicOrder_efficient_6GL6yc.selector
+ ) {
+ for (
+ uint256 i = 1;
+ i < order.parameters.consideration.length;
+ i++
+ ) {
+ ConsiderationItem memory item = order.parameters.consideration[
+ i
+ ];
+
+ if (item.itemType == ItemType.NATIVE) {
+ item.token = address(1);
+ }
+ }
+ }
+
_signOrValidateMutatedOrder(context, orderIndex);
exec(context);
@@ -3369,6 +3509,9 @@ contract FuzzMutations is Test, FuzzExecutor {
}
}
+ // Note that additional recipients do not need to be modified as
+ // identifiers for them are automatically set to 0.
+
_signOrValidateMutatedOrder(context, orderIndex);
exec(context);
@@ -3542,22 +3685,14 @@ contract FuzzMutations is Test, FuzzExecutor {
MutationState memory /* mutationState */
) external {
// This mutation works by wiping out all the orders. Seaport reverts if
- // `_executeAvailableFulfillments` finishes its loop and produces no
- // executions.
-
+ // `_validateOrdersAndPrepareToFulfill` finishes its loop and produces
+ // no unskipped orders.
for (uint256 i; i < context.executionState.orders.length; i++) {
AdvancedOrder memory order = context.executionState.orders[i];
- order.parameters.consideration = new ConsiderationItem[](0);
- order.parameters.totalOriginalConsiderationItems = 0;
+ order.parameters.endTime = 0;
_signOrValidateMutatedOrder(context, i);
}
- context.executionState.offerFulfillments = new FulfillmentComponent[][](
- 0
- );
- context
- .executionState
- .considerationFulfillments = new FulfillmentComponent[][](0);
exec(context);
}
diff --git a/test/foundry/new/helpers/FuzzSetup.sol b/test/foundry/new/helpers/FuzzSetup.sol
index b1011a685..886f8021c 100644
--- a/test/foundry/new/helpers/FuzzSetup.sol
+++ b/test/foundry/new/helpers/FuzzSetup.sol
@@ -199,10 +199,10 @@ abstract contract FuzzSetup is Test, AmountDeriverHelper {
}
// Get the expected zone calldata hashes for each order.
- bytes32[] memory calldataHashes = context
+ bytes32[] memory authorizeCalldataHashes = context
.executionState
.orders
- .getExpectedZoneCalldataHash(
+ .getExpectedZoneAuthorizeCalldataHash(
address(context.seaport),
context.executionState.caller,
context.executionState.criteriaResolvers,
@@ -210,8 +210,22 @@ abstract contract FuzzSetup is Test, AmountDeriverHelper {
unavailableReasons
);
- // Provision the expected zone calldata hash array.
- bytes32[] memory expectedZoneCalldataHash = new bytes32[](
+ bytes32[] memory validateCalldataHashes = context
+ .executionState
+ .orders
+ .getExpectedZoneValidateCalldataHash(
+ address(context.seaport),
+ context.executionState.caller,
+ context.executionState.criteriaResolvers,
+ context.executionState.maximumFulfilled,
+ unavailableReasons
+ );
+
+ // Provision the expected zone calldata hash arrays.
+ bytes32[] memory expectedZoneAuthorizeCalldataHashes = new bytes32[](
+ context.executionState.orders.length
+ );
+ bytes32[] memory expectedZoneValidateCalldataHashes = new bytes32[](
context.executionState.orders.length
);
@@ -232,15 +246,26 @@ abstract contract FuzzSetup is Test, AmountDeriverHelper {
order.orderType == OrderType.PARTIAL_RESTRICTED)
) {
registerChecks = true;
- expectedZoneCalldataHash[i] = calldataHashes[i];
+ expectedZoneAuthorizeCalldataHashes[
+ i
+ ] = authorizeCalldataHashes[i];
+ expectedZoneValidateCalldataHashes[i] = validateCalldataHashes[
+ i
+ ];
}
}
context
.expectations
- .expectedZoneCalldataHash = expectedZoneCalldataHash;
+ .expectedZoneAuthorizeCalldataHashes = expectedZoneAuthorizeCalldataHashes;
+ context
+ .expectations
+ .expectedZoneValidateCalldataHashes = expectedZoneValidateCalldataHashes;
if (registerChecks) {
+ context.registerCheck(
+ FuzzChecks.check_authorizeOrderExpectedDataHash.selector
+ );
context.registerCheck(
FuzzChecks.check_validateOrderExpectedDataHash.selector
);
diff --git a/test/foundry/new/helpers/FuzzTestContextLib.sol b/test/foundry/new/helpers/FuzzTestContextLib.sol
index 86cc142a1..72a56b315 100644
--- a/test/foundry/new/helpers/FuzzTestContextLib.sol
+++ b/test/foundry/new/helpers/FuzzTestContextLib.sol
@@ -142,7 +142,8 @@ struct Expectations {
/**
* @dev Expected zone calldata hashes.
*/
- bytes32[] expectedZoneCalldataHash;
+ bytes32[] expectedZoneAuthorizeCalldataHashes;
+ bytes32[] expectedZoneValidateCalldataHashes;
/**
* @dev Expected contract order calldata hashes. Index 0 of the outer array
* corresponds to the generateOrder hash, while index 1 corresponds to
@@ -394,10 +395,35 @@ library FuzzTestContextLib {
Result[] memory results;
bool[] memory available;
Execution[] memory executions;
- bytes32[] memory hashes;
- bytes32[] memory expectedTransferEventHashes;
- bytes32[] memory expectedSeaportEventHashes;
Vm.Log[] memory actualEvents;
+ Expectations memory expectations;
+
+ {
+ bytes32[] memory authorizeHashes;
+ bytes32[] memory validateHashes;
+ bytes32[] memory expectedTransferEventHashes;
+ bytes32[] memory expectedSeaportEventHashes;
+
+ expectations = Expectations({
+ expectedZoneAuthorizeCalldataHashes: authorizeHashes,
+ expectedZoneValidateCalldataHashes: validateHashes,
+ expectedContractOrderCalldataHashes: new bytes32[2][](0),
+ expectedImplicitPreExecutions: new Execution[](0),
+ expectedImplicitPostExecutions: new Execution[](0),
+ expectedExplicitExecutions: new Execution[](0),
+ allExpectedExecutions: new Execution[](0),
+ expectedResults: results,
+ // expectedAvailableOrders: new bool[](0),
+ expectedTransferEventHashes: expectedTransferEventHashes,
+ expectedSeaportEventHashes: expectedSeaportEventHashes,
+ ineligibleOrders: new bool[](orders.length),
+ ineligibleFailures: new bool[](uint256(Failure.length)),
+ expectedImpliedNativeExecutions: 0,
+ expectedNativeTokensReturned: 0,
+ minimumValue: 0,
+ expectedFillFractions: new FractionResults[](orders.length)
+ });
+ }
return
FuzzTestContext({
@@ -422,24 +448,7 @@ library FuzzTestContextLib {
availableOrders: available,
executions: executions
}),
- expectations: Expectations({
- expectedZoneCalldataHash: hashes,
- expectedContractOrderCalldataHashes: new bytes32[2][](0),
- expectedImplicitPreExecutions: new Execution[](0),
- expectedImplicitPostExecutions: new Execution[](0),
- expectedExplicitExecutions: new Execution[](0),
- allExpectedExecutions: new Execution[](0),
- expectedResults: results,
- // expectedAvailableOrders: new bool[](0),
- expectedTransferEventHashes: expectedTransferEventHashes,
- expectedSeaportEventHashes: expectedSeaportEventHashes,
- ineligibleOrders: new bool[](orders.length),
- ineligibleFailures: new bool[](uint256(Failure.length)),
- expectedImpliedNativeExecutions: 0,
- expectedNativeTokensReturned: 0,
- minimumValue: 0,
- expectedFillFractions: new FractionResults[](orders.length)
- }),
+ expectations: expectations,
executionState: ExecutionState({
caller: address(0),
contractOffererNonce: 0,
@@ -1081,8 +1090,9 @@ function bound(
// Similarly for the UINT256_MAX side. This helps ensure coverage of the
// min/max values.
if (x <= 3 && size > x) return min + x;
- if (x >= type(uint256).max - 3 && size > type(uint256).max - x)
+ if (x >= type(uint256).max - 3 && size > type(uint256).max - x) {
return max - (type(uint256).max - x);
+ }
// Otherwise, wrap x into the range [min, max], i.e. the range is inclusive.
if (x > max) {
diff --git a/test/foundry/new/helpers/Searializer.sol b/test/foundry/new/helpers/Searializer.sol
index 1d0477a8e..6b535b93c 100644
--- a/test/foundry/new/helpers/Searializer.sol
+++ b/test/foundry/new/helpers/Searializer.sol
@@ -745,8 +745,13 @@ library Searializer {
tojsonDynArrayBytes4(obj, "checks", value.checks);
tojsonDynArrayBytes32(
obj,
- "expectedZoneCalldataHash",
- value.expectations.expectedZoneCalldataHash
+ "expectedZoneAuthorizeCalldataHashes",
+ value.expectations.expectedZoneAuthorizeCalldataHashes
+ );
+ tojsonDynArrayBytes32(
+ obj,
+ "expectedZoneValidateCalldataHashes",
+ value.expectations.expectedZoneValidateCalldataHashes
);
tojsonDynArrayArray2Bytes32(
obj,
diff --git a/test/foundry/new/helpers/event-utils/EventSerializer.sol b/test/foundry/new/helpers/event-utils/EventSerializer.sol
index f9df92a86..e09e9623d 100644
--- a/test/foundry/new/helpers/event-utils/EventSerializer.sol
+++ b/test/foundry/new/helpers/event-utils/EventSerializer.sol
@@ -21,10 +21,10 @@ struct ERC721TransferEvent {
address from;
address to;
uint256 identifier;
- // bytes32 topicHash;
- // bytes32 dataHash;
- // bytes32 eventHash;
}
+// bytes32 topicHash;
+// bytes32 dataHash;
+// bytes32 eventHash;
struct ERC1155TransferEvent {
string kind;
@@ -34,10 +34,10 @@ struct ERC1155TransferEvent {
address to;
uint256 identifier;
uint256 amount;
- // bytes32 topicHash;
- // bytes32 dataHash;
- // bytes32 eventHash;
}
+// bytes32 topicHash;
+// bytes32 dataHash;
+// bytes32 eventHash;
struct OrderFulfilledEvent {
bytes32 orderHash;
diff --git a/test/foundry/new/helpers/event-utils/ExpectedEventsUtil.sol b/test/foundry/new/helpers/event-utils/ExpectedEventsUtil.sol
index df1e0709f..a03ee1b53 100644
--- a/test/foundry/new/helpers/event-utils/ExpectedEventsUtil.sol
+++ b/test/foundry/new/helpers/event-utils/ExpectedEventsUtil.sol
@@ -116,10 +116,26 @@ library ExpectedEventsUtil {
"ExpectedEventsUtil: executions length mismatch"
);
+ Execution[] memory filteredExecutions = new Execution[](
+ executions.length
+ );
+
+ uint256 filteredExecutionIndex = 0;
+
+ for (uint256 i = 0; i < executions.length; ++i) {
+ if (executions[i].item.amount > 0) {
+ filteredExecutions[filteredExecutionIndex++] = executions[i];
+ }
+ }
+
+ assembly {
+ mstore(filteredExecutions, filteredExecutionIndex)
+ }
+
context.expectations.expectedTransferEventHashes = ArrayHelpers
.filterMapWithArg
.asExecutionsFilterMap()(
- executions,
+ filteredExecutions,
TransferEventsLib.getTransferEventHash,
context
);
@@ -451,13 +467,11 @@ library Casts {
returns (
function(
bytes32[] memory,
- function(
- uint256,
- uint256,
- ReduceInput memory //Vm.Log[] memory)
- ) internal returns (uint256),
+ function(uint256, uint256, ReduceInput memory)
+ internal
+ returns (uint256),
uint256,
- ReduceInput memory //Vm.Log[] memory
+ ReduceInput memory
) internal returns (uint256) fnOut
)
{
diff --git a/test/foundry/new/helpers/event-utils/ForgeEventsLib.sol b/test/foundry/new/helpers/event-utils/ForgeEventsLib.sol
index 84532835d..5b3d94b8b 100644
--- a/test/foundry/new/helpers/event-utils/ForgeEventsLib.sol
+++ b/test/foundry/new/helpers/event-utils/ForgeEventsLib.sol
@@ -80,7 +80,7 @@ library ForgeEventsLib {
bytes32 topic3,
) = getTopics(log);
- MemoryPointer data = toMemoryPointer(log).pptr(32);
+ MemoryPointer data = toMemoryPointer(log).pptrOffset(32);
assembly {
switch topicsCount
case 4 {
@@ -128,10 +128,10 @@ library ForgeEventsLib {
address(uint160(uint256(topic1))),
address(uint160(uint256(topic2))),
uint256(topic3)
- // getForgeTopicsHash(log),
- // getDataHash(log),
- // getForgeEventHash(log)
).serializeERC721TransferEvent(objectKey, valueKey);
+ // getForgeTopicsHash(log),
+ // getDataHash(log),
+ // getForgeEventHash(log)
} else {
ERC20TransferEvent memory eventData;
eventData.kind = "ERC20";
diff --git a/test/foundry/new/helpers/event-utils/TransferEventsLib.sol b/test/foundry/new/helpers/event-utils/TransferEventsLib.sol
index 8fd4e02e5..bef0a43b6 100644
--- a/test/foundry/new/helpers/event-utils/TransferEventsLib.sol
+++ b/test/foundry/new/helpers/event-utils/TransferEventsLib.sol
@@ -86,15 +86,15 @@ library TransferEventsLib {
execution.offerer,
address(item.recipient),
item.identifier
- // getTopicsHash(
- // Transfer.selector, // topic0
- // execution.offerer.toBytes32(), // topic1
- // toBytes32(item.recipient), // topic2
- // bytes32(item.identifier) // topic3
- // ),
- // keccak256(""),
- // getERC721TransferEventHash(execution)
).serializeERC721TransferEvent(objectKey, valueKey);
+ // getTopicsHash(
+ // Transfer.selector, // topic0
+ // execution.offerer.toBytes32(), // topic1
+ // toBytes32(item.recipient), // topic2
+ // bytes32(item.identifier) // topic3
+ // ),
+ // keccak256(""),
+ // getERC721TransferEventHash(execution)
}
if (itemType == ItemType.ERC1155) {
ReceivedItem memory item = execution.item;
@@ -108,15 +108,15 @@ library TransferEventsLib {
address(item.recipient),
item.identifier,
item.amount
- // getTopicsHash(
- // TransferSingle.selector, // topic0
- // _getConduit(execution.conduitKey, context).toBytes32(), // topic1 = operator
- // execution.offerer.toBytes32(), // topic2 = from
- // toBytes32(item.recipient) // topic3 = to
- // ),
- // keccak256(abi.encode(item.identifier, item.amount)), // dataHash
- // getERC1155TransferEventHash(execution, context) // event hash
);
+ // getTopicsHash(
+ // TransferSingle.selector, // topic0
+ // _getConduit(execution.conduitKey, context).toBytes32(), // topic1 = operator
+ // execution.offerer.toBytes32(), // topic2 = from
+ // toBytes32(item.recipient) // topic3 = to
+ // ),
+ // keccak256(abi.encode(item.identifier, item.amount)), // dataHash
+ // getERC1155TransferEventHash(execution, context) // event hash
return eventData.serializeERC1155TransferEvent(objectKey, valueKey);
}
diff --git a/test/foundry/new/helpers/sol/MatchFulfillmentHelper.t.sol b/test/foundry/new/helpers/sol/MatchFulfillmentHelper.t.sol
index d7bf227f3..6fbe73f93 100644
--- a/test/foundry/new/helpers/sol/MatchFulfillmentHelper.t.sol
+++ b/test/foundry/new/helpers/sol/MatchFulfillmentHelper.t.sol
@@ -2001,17 +2001,17 @@ contract MatchFulfillmentHelperTest is BaseOrderTest {
}
OrderParameters memory parameters = order
- .parameters
- .copy()
- .withOfferer(offerer.addr)
- .withStartTime(block.timestamp)
- // Bump the end time by 100 so that the test doesn't try to match the
- // same order twice.
+ .parameters
+ .copy()
+ .withOfferer(offerer.addr)
+ .withStartTime(block.timestamp)
.withEndTime(block.timestamp + 1)
.withTotalOriginalConsiderationItems(
order.parameters.consideration.length
)
.withSalt(salt);
+ // Bump the end time by 100 so that the test doesn't try to match the
+ // same order twice.
OrderComponents memory orderComponents = parameters
.toOrderComponents(seaport.getCounter(offerer.addr))
diff --git a/test/foundry/new/zones/ValidationOffererZone.sol b/test/foundry/new/zones/ValidationOffererZone.sol
index 52f07ad68..47357f246 100644
--- a/test/foundry/new/zones/ValidationOffererZone.sol
+++ b/test/foundry/new/zones/ValidationOffererZone.sol
@@ -27,6 +27,12 @@ contract ValidationOffererZone is ContractOffererInterface, ZoneInterface {
receive() external payable {}
+ function authorizeOrder(
+ ZoneParameters calldata
+ ) public pure returns (bytes4) {
+ return this.authorizeOrder.selector;
+ }
+
/**
* @dev Validates that the parties have received the correct items.
*
diff --git a/test/foundry/offerers/AdjustedAmountOfferer.t.sol b/test/foundry/offerers/AdjustedAmountOfferer.t.sol
index 0cd639dd8..2c8f8bbe6 100644
--- a/test/foundry/offerers/AdjustedAmountOfferer.t.sol
+++ b/test/foundry/offerers/AdjustedAmountOfferer.t.sol
@@ -13,7 +13,10 @@ import {
ConsiderationInterface
} from "seaport-types/src/interfaces/ConsiderationInterface.sol";
-import { OrderType, ItemType } from "seaport-types/src/lib/ConsiderationEnums.sol";
+import {
+ OrderType,
+ ItemType
+} from "seaport-types/src/lib/ConsiderationEnums.sol";
import {
ConsiderationItem,
@@ -195,57 +198,57 @@ contract AdjustedAmountOffererTest is
fulfillAdvanced(context, configureAdvancedOrder());
}
- // make sure altering offer item start/end amount results in falure
-
- function testAlterOfferItem() public {
- setUpOfferer(0, 0);
- setUpNormalOrder(address(offerer));
- offerItems[0].endAmount += 1;
-
- test(this.execAlterOfferItem, Context({ seaport: consideration }));
- test(
- this.execAlterOfferItem,
- Context({ seaport: referenceConsideration })
- );
- }
-
- function execAlterOfferItem(Context memory context) external stateless {
- vm.expectRevert(
- abi.encodeWithSelector(
- InvalidContractOrder.selector,
- uint256(uint160(address(offerer))) << 96
- )
- );
- fulfillAdvanced(context, configureAdvancedOrder());
- }
-
- // make sure altering consideration item start/end amount results in falure
- function testAlterConsiderationItem() public {
- setUpOfferer(0, 0);
- setUpNormalOrder(address(offerer));
- considerationItems[0].endAmount += 1;
-
- test(
- this.execAlterConsiderationItem,
- Context({ seaport: consideration })
- );
- test(
- this.execAlterConsiderationItem,
- Context({ seaport: referenceConsideration })
- );
- }
-
- function execAlterConsiderationItem(
- Context memory context
- ) external stateless {
- vm.expectRevert(
- abi.encodeWithSelector(
- InvalidContractOrder.selector,
- uint256(uint160(address(offerer))) << 96
- )
- );
- fulfillAdvanced(context, configureAdvancedOrder());
- }
+ // NOTE: this behavior has been modified as generateOrder is now called
+ // after amount derivation; the following tests are no longer valid
+ // function testAlterOfferItem() public {
+ // setUpOfferer(0, 0);
+ // setUpNormalOrder(address(offerer));
+ // offerItems[0].endAmount += 1;
+
+ // test(this.execAlterOfferItem, Context({ seaport: consideration }));
+ // test(
+ // this.execAlterOfferItem,
+ // Context({ seaport: referenceConsideration })
+ // );
+ // }
+
+ // function execAlterOfferItem(Context memory context) external stateless {
+ // vm.expectRevert(
+ // abi.encodeWithSelector(
+ // InvalidContractOrder.selector,
+ // uint256(uint160(address(offerer))) << 96
+ // )
+ // );
+ // fulfillAdvanced(context, configureAdvancedOrder());
+ // }
+
+ // // make sure altering consideration item start/end amount results in falure
+ // function testAlterConsiderationItem() public {
+ // setUpOfferer(0, 0);
+ // setUpNormalOrder(address(offerer));
+ // considerationItems[0].endAmount += 1;
+
+ // test(
+ // this.execAlterConsiderationItem, Context({ seaport: consideration })
+ // );
+ // test(
+ // this.execAlterConsiderationItem,
+ // Context({ seaport: referenceConsideration })
+ // );
+ // }
+
+ // function execAlterConsiderationItem(Context memory context)
+ // external
+ // stateless
+ // {
+ // vm.expectRevert(
+ // abi.encodeWithSelector(
+ // InvalidContractOrder.selector,
+ // uint256(uint160(address(offerer))) << 96
+ // )
+ // );
+ // fulfillAdvanced(context, configureAdvancedOrder());
+ // }
function configureAdvancedOrder() internal returns (AdvancedOrder memory) {
return configureAdvancedOrder(1, 1);
diff --git a/test/foundry/offerers/BadOfferer.t.sol b/test/foundry/offerers/BadOfferer.t.sol
index 52ad41f2e..3dd893f60 100644
--- a/test/foundry/offerers/BadOfferer.t.sol
+++ b/test/foundry/offerers/BadOfferer.t.sol
@@ -23,7 +23,10 @@ import {
FulfillmentComponent
} from "seaport-types/src/lib/ConsiderationStructs.sol";
-import { ItemType, OrderType } from "seaport-types/src/lib/ConsiderationEnums.sol";
+import {
+ ItemType,
+ OrderType
+} from "seaport-types/src/lib/ConsiderationEnums.sol";
import {
ZoneInteractionErrors
diff --git a/test/foundry/offerers/ContractOffersNativeTokenOfferItems.t.sol b/test/foundry/offerers/ContractOffersNativeTokenOfferItems.t.sol
index ca9637e48..4e6a38adf 100644
--- a/test/foundry/offerers/ContractOffersNativeTokenOfferItems.t.sol
+++ b/test/foundry/offerers/ContractOffersNativeTokenOfferItems.t.sol
@@ -16,7 +16,10 @@ import {
ConsiderationInterface
} from "seaport-types/src/interfaces/ConsiderationInterface.sol";
-import { ItemType, OrderType } from "seaport-types/src/lib/ConsiderationEnums.sol";
+import {
+ ItemType,
+ OrderType
+} from "seaport-types/src/lib/ConsiderationEnums.sol";
import { ItemType } from "seaport-types/src/lib/ConsiderationEnums.sol";
diff --git a/test/foundry/offerers/TestPoolOffererImpl.t.sol b/test/foundry/offerers/TestPoolOffererImpl.t.sol
index 73aaad6a3..9f9b0458e 100644
--- a/test/foundry/offerers/TestPoolOffererImpl.t.sol
+++ b/test/foundry/offerers/TestPoolOffererImpl.t.sol
@@ -30,6 +30,8 @@ import { TestERC721 } from "../../../contracts/test/TestERC721.sol";
import { TestPoolOfferer } from "./impl/TestPoolOfferer.sol";
+import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
+
contract TestPoolFactoryImpl {
address immutable seaport;
diff --git a/test/foundry/offerers/impl/TestPoolOfferer.sol b/test/foundry/offerers/impl/TestPoolOfferer.sol
index 780b6f950..3baca95da 100644
--- a/test/foundry/offerers/impl/TestPoolOfferer.sol
+++ b/test/foundry/offerers/impl/TestPoolOfferer.sol
@@ -23,9 +23,7 @@ import { IERC721 } from "@openzeppelin/contracts/token/ERC721/IERC721.sol";
import { IERC20 } from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
-import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol";
-
-contract TestPoolOfferer is ERC165, ContractOffererInterface, Ownable {
+contract TestPoolOfferer is ERC165, ContractOffererInterface {
using EnumerableSet for EnumerableSet.UintSet;
error OnlySeaport();
@@ -122,7 +120,8 @@ contract TestPoolOfferer is ERC165, ContractOffererInterface, Ownable {
balance = newBalance;
}
- /** @dev Generate an offer and consideration based on the minimumReceived
+ /**
+ * @dev Generate an offer and consideration based on the minimumReceived
* and maximumSpent arrays.
*
* @param minimumReceived An array of SpentItem structs representing the
@@ -333,7 +332,8 @@ contract TestPoolOfferer is ERC165, ContractOffererInterface, Ownable {
}
}
- /** @dev Generate offer and consideration items based on the number of
+ /**
+ * @dev Generate offer and consideration items based on the number of
* ERC721 tokens offered or requested.
*
* @param minimumReceived An array of SpentItem structs representing the
@@ -462,7 +462,8 @@ contract TestPoolOfferer is ERC165, ContractOffererInterface, Ownable {
}
}
- /** @dev Validates each SpentItem. Ensures that the item type is valid, all
+ /**
+ * @dev Validates each SpentItem. Ensures that the item type is valid, all
* tokens are homogenous, and that the addresses are those we expect.
*
* @param offerItem The item to validate.
@@ -541,23 +542,21 @@ contract TestPoolOfferer is ERC165, ContractOffererInterface, Ownable {
/**
* @dev Transfers the contract's entire ERC20 and ERC721 balances to the
- * contract's owner.
+ * caller. Obviously this is unsafe for production use as there's no access
+ * control.
*/
- function withdrawAll() external onlyOwner {
+ function withdrawAll() external {
// Get the contract's ERC20 balance.
IERC20 ierc20 = IERC20(erc20);
uint256 erc20Balance = ierc20.balanceOf(address(this));
- // Get the contract's owner address.
- address owner = owner();
-
- // Transfer the ERC20 balance to the contract's owner.
- ierc20.transfer(owner, erc20Balance);
+ // Transfer the ERC20 balance to the caller.
+ ierc20.transfer(msg.sender, erc20Balance);
- // Transfer each ERC721 token to the contract's owner.
+ // Transfer each ERC721 token to the caller.
while (tokenIds.length() > 0) {
uint256 tokenId = tokenIds.at(0);
- IERC721(erc721).transferFrom(address(this), owner, tokenId);
+ IERC721(erc721).transferFrom(address(this), msg.sender, tokenId);
// Remove the token from the set.
tokenIds.remove(tokenId);
diff --git a/test/foundry/utils/BaseConsiderationTest.sol b/test/foundry/utils/BaseConsiderationTest.sol
index 6c6e1e310..3bbb50652 100644
--- a/test/foundry/utils/BaseConsiderationTest.sol
+++ b/test/foundry/utils/BaseConsiderationTest.sol
@@ -1,7 +1,9 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;
-import { ConduitController } from "seaport-core/src/conduit/ConduitController.sol";
+import {
+ ConduitController
+} from "seaport-core/src/conduit/ConduitController.sol";
import {
ReferenceConduitController
diff --git a/test/foundry/utils/ConsiderationErrorsWrapper.sol b/test/foundry/utils/ConsiderationErrorsWrapper.sol
index 29a167e05..31a4ac04b 100644
--- a/test/foundry/utils/ConsiderationErrorsWrapper.sol
+++ b/test/foundry/utils/ConsiderationErrorsWrapper.sol
@@ -18,19 +18,15 @@ import {
_revertInvalidNativeOfferItem,
_revertInvalidProof,
_revertInvalidTime,
- _revertMismatchedFulfillmentOfferAndConsiderationComponents,
_revertMissingFulfillmentComponentOnAggregation,
_revertMissingOriginalConsiderationItems,
_revertNoReentrantCalls,
_revertNoSpecifiedOrdersAvailable,
- _revertOfferAndConsiderationRequiredOnFulfillment,
_revertOrderAlreadyFilled,
_revertOrderCriteriaResolverOutOfRange,
_revertOrderIsCancelled,
_revertOrderPartiallyFilled,
_revertPartialFillsNotEnabledForOrder,
- _revertUnresolvedConsiderationCriteria,
- _revertUnresolvedOfferCriteria,
_revertUnusedItemParameters
} from "seaport-types/src/lib/ConsiderationErrors.sol";
@@ -175,21 +171,6 @@ contract ConsiderationErrorsWrapper {
_revertInvalidTime(startTime, endTime);
}
- /**
- * @dev Reverts execution with a
- * "MismatchedFulfillmentOfferAndConsiderationComponents" error message.
- *
- * @param fulfillmentIndex The index of the fulfillment that caused the
- * error.
- */
- function __revertMismatchedFulfillmentOfferAndConsiderationComponents(
- uint256 fulfillmentIndex
- ) external pure {
- _revertMismatchedFulfillmentOfferAndConsiderationComponents(
- fulfillmentIndex
- );
- }
-
/**
* @dev Reverts execution with a "MissingFulfillmentComponentOnAggregation"
* error message.
@@ -226,17 +207,6 @@ contract ConsiderationErrorsWrapper {
_revertNoSpecifiedOrdersAvailable();
}
- /**
- * @dev Reverts execution with a "OfferAndConsiderationRequiredOnFulfillment"
- * error message.
- */
- function __revertOfferAndConsiderationRequiredOnFulfillment()
- external
- pure
- {
- _revertOfferAndConsiderationRequiredOnFulfillment();
- }
-
/**
* @dev Reverts execution with an "OrderAlreadyFilled" error message.
*
@@ -284,27 +254,6 @@ contract ConsiderationErrorsWrapper {
_revertPartialFillsNotEnabledForOrder();
}
- /**
- * @dev Reverts execution with an "UnresolvedConsiderationCriteria" error
- * message.
- */
- function __revertUnresolvedConsiderationCriteria(
- uint256 orderIndex,
- uint256 considerationIndex
- ) external pure {
- _revertUnresolvedConsiderationCriteria(orderIndex, considerationIndex);
- }
-
- /**
- * @dev Reverts execution with an "UnresolvedOfferCriteria" error message.
- */
- function __revertUnresolvedOfferCriteria(
- uint256 orderIndex,
- uint256 offerIndex
- ) external pure {
- _revertUnresolvedOfferCriteria(orderIndex, offerIndex);
- }
-
/**
* @dev Reverts execution with an "UnusedItemParameters" error message.
*/
diff --git a/test/foundry/utils/EIP712MerkleTree.sol b/test/foundry/utils/EIP712MerkleTree.sol
index b8bbd2dff..86f2181d8 100644
--- a/test/foundry/utils/EIP712MerkleTree.sol
+++ b/test/foundry/utils/EIP712MerkleTree.sol
@@ -13,7 +13,9 @@ import {
ConsiderationInterface
} from "seaport-types/src/interfaces/ConsiderationInterface.sol";
-import { OrderComponents } from "seaport-types/src/lib/ConsiderationStructs.sol";
+import {
+ OrderComponents
+} from "seaport-types/src/lib/ConsiderationStructs.sol";
import { Math } from "@openzeppelin/contracts/utils/math/Math.sol";
diff --git a/test/foundry/utils/reentrancy/ReentrantStructs.sol b/test/foundry/utils/reentrancy/ReentrantStructs.sol
index 3752000e7..2f903e05d 100644
--- a/test/foundry/utils/reentrancy/ReentrantStructs.sol
+++ b/test/foundry/utils/reentrancy/ReentrantStructs.sol
@@ -1,5 +1,6 @@
//SPDX-License-Identifier: Unlicense
pragma solidity ^0.8.17;
+
import {
BasicOrderParameters,
OrderComponents,
diff --git a/test/foundry/zone/PostFulfillmentCheck.t.sol b/test/foundry/zone/PreAndPostFulfillmentCheck.t.sol
similarity index 97%
rename from test/foundry/zone/PostFulfillmentCheck.t.sol
rename to test/foundry/zone/PreAndPostFulfillmentCheck.t.sol
index d6a71d1a3..a47583e53 100644
--- a/test/foundry/zone/PostFulfillmentCheck.t.sol
+++ b/test/foundry/zone/PreAndPostFulfillmentCheck.t.sol
@@ -3,15 +3,11 @@ pragma solidity ^0.8.17;
import { BaseOrderTest } from "../utils/BaseOrderTest.sol";
-import { TestZone } from "./impl/TestZone.sol";
-
import {
TestTransferValidationZoneOfferer
} from "seaport/test/TestTransferValidationZoneOfferer.sol";
-import {
- PostFulfillmentStatefulTestZone
-} from "./impl/PostFullfillmentStatefulTestZone.sol";
+import { StatefulTestZone } from "./impl/StatefulTestZone.sol";
import {
AdditionalRecipient,
@@ -34,20 +30,14 @@ import {
ConsiderationInterface
} from "seaport-types/src/interfaces/ConsiderationInterface.sol";
-contract PostFulfillmentCheckTest is BaseOrderTest {
- TestZone zone = new TestZone();
- PostFulfillmentStatefulTestZone statefulZone =
- new PostFulfillmentStatefulTestZone(50);
+contract PreAndPostFulfillmentCheckTest is BaseOrderTest {
+ StatefulTestZone statefulZone = new StatefulTestZone(50);
struct Context {
ConsiderationInterface consideration;
uint8 numOriginalAdditional;
uint8 numTips;
}
- struct EthConsideration {
- address payable recipient;
- uint256 amount;
- }
function test(
function(Context memory) external fn,
@@ -68,7 +58,7 @@ contract PostFulfillmentCheckTest is BaseOrderTest {
address(this),
true
);
- vm.label(address(zone), "TestZone");
+ vm.label(address(statefulZone), "TestZone");
}
function testAscendingAmount() public {
@@ -275,7 +265,8 @@ contract PostFulfillmentCheckTest is BaseOrderTest {
recipient: address(0)
});
- assertTrue(statefulZone.called());
+ assertTrue(statefulZone.authorizeCalled());
+ assertTrue(statefulZone.validateCalled());
}
function testBasicStateful() public {
@@ -453,7 +444,7 @@ contract PostFulfillmentCheckTest is BaseOrderTest {
);
// make new stateful zone with a larger amount so each additional
// recipient can receive
- statefulZone = new PostFulfillmentStatefulTestZone(5000);
+ statefulZone = new StatefulTestZone(5000);
// clear storage array just in case
delete additionalRecipients;
@@ -536,7 +527,8 @@ contract PostFulfillmentCheckTest is BaseOrderTest {
});
// assertions
- assertTrue(statefulZone.called());
+ assertTrue(statefulZone.authorizeCalled());
+ assertTrue(statefulZone.validateCalled());
for (uint256 i = 0; i < allAdditional.length; i++) {
assertEq(
token1.balanceOf(allAdditional[i]),
@@ -625,7 +617,8 @@ contract PostFulfillmentCheckTest is BaseOrderTest {
recipient: address(0),
maximumFulfilled: 1
});
- assertTrue(statefulZone.called());
+ assertTrue(statefulZone.authorizeCalled());
+ assertTrue(statefulZone.validateCalled());
}
function testExecMatchAdvancedOrdersWithConduit() public {
diff --git a/test/foundry/zone/TestTransferValidationZoneFuzz.t.sol b/test/foundry/zone/TestTransferValidationZoneFuzz.t.sol
index 433495bf9..5dbdfd4ef 100644
--- a/test/foundry/zone/TestTransferValidationZoneFuzz.t.sol
+++ b/test/foundry/zone/TestTransferValidationZoneFuzz.t.sol
@@ -95,18 +95,18 @@ contract TestTransferValidationZoneOffererTest is BaseOrderTest {
.saveDefault(SINGLE_721);
OrderComponentsLib
- .empty()
- .withOfferer(offerer1.addr)
- .withZone(address(zone))
- // fill in offer later
- // fill in consideration later
- .withOrderType(OrderType.FULL_RESTRICTED)
- .withStartTime(block.timestamp)
- .withEndTime(block.timestamp + 1)
- .withZoneHash(bytes32(0)) // not strictly necessary
+ .empty()
+ .withOfferer(offerer1.addr)
+ .withZone(address(zone))
+ .withOrderType(OrderType.FULL_RESTRICTED)
+ .withStartTime(block.timestamp)
+ .withEndTime(block.timestamp + 1)
+ .withZoneHash(bytes32(0))
.withSalt(0)
.withConduitKey(conduitKeyOne)
- .saveDefault(VALIDATION_ZONE);
+ .saveDefault(VALIDATION_ZONE); // not strictly necessary
+ // fill in offer later
+ // fill in consideration later
// fill in counter later
}
@@ -347,9 +347,9 @@ contract TestTransferValidationZoneOffererTest is BaseOrderTest {
// Set up event expectations.
if (
+ fuzzPrimeOfferer.addr != fuzzMirrorOfferer.addr
// If the fuzzPrimeOfferer and fuzzMirrorOfferer are the same
// address, then the ERC20 transfers will be filtered.
- fuzzPrimeOfferer.addr != fuzzMirrorOfferer.addr
) {
if (
// When shouldIncludeNativeConsideration is false, there will be
@@ -368,10 +368,12 @@ contract TestTransferValidationZoneOffererTest is BaseOrderTest {
}
if (
- // When considerationItemsPerPrimeOrderCount is 3, there will be
- // exactly one token2 consideration item per orderPairCount.
- // And they'll all get aggregated into a single transfer.
- context.matchArgs.considerationItemsPerPrimeOrderCount >= 3
+ context
+ .matchArgs
+ // When considerationItemsPerPrimeOrderCount is 3, there will be
+ // exactly one token2 consideration item per orderPairCount.
+ // And they'll all get aggregated into a single transfer.
+ .considerationItemsPerPrimeOrderCount >= 3
) {
vm.expectEmit(true, true, false, true, address(token2));
emit Transfer(
@@ -465,7 +467,7 @@ contract TestTransferValidationZoneOffererTest is BaseOrderTest {
}
}
- function xtestFulfillAvailableAdvancedFuzz(
+ function testFulfillAvailableAdvancedFuzz(
FulfillFuzzInputs memory fulfillArgs
) public {
// Limit this value to avoid overflow issues.
@@ -627,6 +629,23 @@ contract TestTransferValidationZoneOffererTest is BaseOrderTest {
if (context.fulfillArgs.shouldUseTransferValidationZone) {
address strangerAddress = address(0xdeafbeef);
+ vm.expectRevert(
+ abi.encodeWithSignature(
+ "InvalidOwner(address,address,address,uint256)",
+ // The expected recipient is either the offer recipient or
+ // the caller, depending on the fuzz args.
+ context.fulfillArgs.shouldSpecifyRecipient
+ ? context.fulfillArgs.offerRecipient
+ : address(this),
+ // The stranger address gets passed into the recipient field
+ // below, so it will be the actual recipient.
+ strangerAddress,
+ address(test721_1),
+ // Should revert on the first call.
+ context.fulfillArgs.tokenId
+ )
+ );
+
// Make the call to Seaport.
context.seaport.fulfillAvailableAdvancedOrders{
value: context.fulfillArgs.excessNativeTokens +
@@ -644,7 +663,7 @@ contract TestTransferValidationZoneOffererTest is BaseOrderTest {
.considerationFulfillmentComponents,
fulfillerConduitKey: bytes32(conduitKey),
recipient: strangerAddress,
- maximumFulfilled: infra.advancedOrders.length
+ maximumFulfilled: context.fulfillArgs.maximumFulfilledCount
});
}
@@ -745,7 +764,8 @@ contract TestTransferValidationZoneOffererTest is BaseOrderTest {
// Check that the zone was called the expected number of times.
if (context.fulfillArgs.shouldUseTransferValidationZone) {
assertTrue(
- zone.callCount() == context.fulfillArgs.maximumFulfilledCount
+ zone.callCount() == context.fulfillArgs.maximumFulfilledCount,
+ "Zone call count incorrect."
);
}
@@ -759,7 +779,8 @@ contract TestTransferValidationZoneOffererTest is BaseOrderTest {
test721_1.ownerOf(context.fulfillArgs.tokenId + i),
context.fulfillArgs.shouldSpecifyRecipient
? context.fulfillArgs.offerRecipient
- : address(this)
+ : address(this),
+ "NFT owner incorrect."
);
}
@@ -773,7 +794,11 @@ contract TestTransferValidationZoneOffererTest is BaseOrderTest {
// Edge case: If the fuzz args pick this address for the
// consideration recipient, then the caller's balance should not
// change.
- assertEq(infra.callerBalanceAfter, infra.callerBalanceBefore);
+ assertEq(
+ infra.callerBalanceAfter,
+ infra.callerBalanceBefore,
+ "Caller balance incorrect (this contract)."
+ );
} else {
// Check that the consideration recipient's native balance was
// increased by the amount * the number of NFTs for sale.
@@ -781,7 +806,8 @@ contract TestTransferValidationZoneOffererTest is BaseOrderTest {
infra.considerationRecipientNativeBalanceAfter,
infra.considerationRecipientNativeBalanceBefore +
context.fulfillArgs.amount *
- context.fulfillArgs.maximumFulfilledCount
+ context.fulfillArgs.maximumFulfilledCount,
+ "Consideration recipient native balance incorrect."
);
// The consideration (amount * maximumFulfilledCount) should be
// spent, and the excessNativeTokens should be returned.
@@ -789,7 +815,8 @@ contract TestTransferValidationZoneOffererTest is BaseOrderTest {
infra.callerBalanceAfter +
context.fulfillArgs.amount *
context.fulfillArgs.maximumFulfilledCount,
- infra.callerBalanceBefore
+ infra.callerBalanceBefore,
+ "Caller balance incorrect."
);
}
} else {
@@ -803,14 +830,16 @@ contract TestTransferValidationZoneOffererTest is BaseOrderTest {
// change.
assertEq(
infra.considerationRecipientToken1BalanceAfter,
- infra.considerationRecipientToken1BalanceBefore
+ infra.considerationRecipientToken1BalanceBefore,
+ "Consideration recipient token1 balance incorrect (this)."
);
} else {
assertEq(
infra.considerationRecipientToken1BalanceAfter,
infra.considerationRecipientToken1BalanceBefore +
context.fulfillArgs.amount *
- context.fulfillArgs.maximumFulfilledCount
+ context.fulfillArgs.maximumFulfilledCount,
+ "Consideration recipient token1 balance incorrect."
);
}
@@ -824,14 +853,16 @@ contract TestTransferValidationZoneOffererTest is BaseOrderTest {
// not change.
assertEq(
infra.considerationRecipientToken2BalanceAfter,
- infra.considerationRecipientToken2BalanceBefore
+ infra.considerationRecipientToken2BalanceBefore,
+ "Consideration recipient token2 balance incorrect (this)."
);
} else {
assertEq(
infra.considerationRecipientToken2BalanceAfter,
infra.considerationRecipientToken2BalanceBefore +
context.fulfillArgs.amount *
- context.fulfillArgs.maximumFulfilledCount
+ context.fulfillArgs.maximumFulfilledCount,
+ "Consideration recipient token2 balance incorrect."
);
}
}
diff --git a/test/foundry/zone/TestZoneCalldataFidelity.t.sol b/test/foundry/zone/TestZoneCalldataFidelity.t.sol
new file mode 100644
index 000000000..29a2446b5
--- /dev/null
+++ b/test/foundry/zone/TestZoneCalldataFidelity.t.sol
@@ -0,0 +1,262 @@
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.17;
+
+import {
+ ConsiderationItemLib,
+ OfferItemLib,
+ OrderParametersLib
+} from "seaport-sol/src/SeaportSol.sol";
+
+import { BaseOrderTest } from "../utils/BaseOrderTest.sol";
+
+import { HashCalldataTestZone } from "./impl/HashCalldataTestZone.sol";
+
+import {
+ AdvancedOrder,
+ ConsiderationItem,
+ CriteriaResolver,
+ ItemType,
+ OfferItem,
+ OrderParameters,
+ ZoneParameters
+} from "seaport-types/src/lib/ConsiderationStructs.sol";
+
+import { OrderType } from "seaport-types/src/lib/ConsiderationEnums.sol";
+
+import {
+ ConsiderationInterface
+} from "seaport-types/src/interfaces/ConsiderationInterface.sol";
+
+contract PreAndPostFulfillmentCheckTest is BaseOrderTest {
+ using ConsiderationItemLib for ConsiderationItem[];
+ using OfferItemLib for OfferItem[];
+ using OrderParametersLib for OrderParameters;
+
+ HashCalldataTestZone testZone = new HashCalldataTestZone();
+
+ struct Context {
+ ConsiderationInterface consideration;
+ TestCase testCase;
+ }
+
+ struct TestCase {
+ uint256 itemType;
+ uint256 offerItemStartingIdentifier;
+ uint256 considerationItemStartingIdentifier;
+ uint256 startAmount;
+ uint256 endAmount;
+ bytes signature;
+ bytes extraData;
+ uint256 recipient;
+ uint256 offerLength;
+ uint256 considerationLength;
+ uint256 orderType;
+ uint256 startTime;
+ uint256 endTime;
+ uint256 zoneHash;
+ uint256 salt;
+ }
+
+ function test(
+ function(Context memory) external fn,
+ Context memory context
+ ) internal {
+ try fn(context) {
+ fail();
+ } catch (bytes memory reason) {
+ assertPass(reason);
+ }
+ }
+
+ function setUp() public override {
+ super.setUp();
+ conduitController.updateChannel(address(conduit), address(this), true);
+ referenceConduitController.updateChannel(
+ address(referenceConduit),
+ address(this),
+ true
+ );
+ vm.label(address(testZone), "TestZone");
+ }
+
+ function testCalldataEquivalence(TestCase memory testCase) public {
+ test(
+ this.execCalldataEquivalence,
+ Context({ consideration: consideration, testCase: testCase })
+ );
+ test(
+ this.execCalldataEquivalence,
+ Context({
+ consideration: referenceConsideration,
+ testCase: testCase
+ })
+ );
+ }
+
+ function execCalldataEquivalence(Context memory context) public stateless {
+ // Bound the test case.
+ TestCase memory testCase = _boundTestCase(context.testCase);
+
+ // Mint the necessary tokens.
+ _mintNecessaryTokens(testCase);
+
+ // Create the params for the advanced order.
+ OrderParameters memory orderParameters = OrderParameters({
+ offerer: address(this),
+ zone: address(testZone),
+ offer: new OfferItem[](testCase.offerLength),
+ consideration: new ConsiderationItem[](
+ testCase.considerationLength
+ ),
+ orderType: OrderType(testCase.orderType),
+ startTime: testCase.startTime,
+ endTime: testCase.endTime,
+ zoneHash: bytes32(testCase.zoneHash),
+ salt: testCase.salt,
+ conduitKey: bytes32(0),
+ totalOriginalConsiderationItems: testCase.considerationLength
+ });
+
+ // Populate the offer and consideration.
+ for (uint256 i = 0; i < testCase.offerLength; i++) {
+ orderParameters.offer[i] = OfferItem({
+ itemType: ItemType(testCase.itemType),
+ token: address(test721_1),
+ identifierOrCriteria: testCase.offerItemStartingIdentifier + i,
+ startAmount: testCase.startAmount,
+ endAmount: testCase.endAmount
+ });
+ }
+
+ for (uint256 i = 0; i < testCase.considerationLength; i++) {
+ orderParameters.consideration[i] = ConsiderationItem({
+ itemType: ItemType(testCase.itemType),
+ token: address(test721_1),
+ identifierOrCriteria: testCase
+ .considerationItemStartingIdentifier + i,
+ startAmount: testCase.startAmount,
+ endAmount: testCase.endAmount,
+ recipient: payable(address(uint160(testCase.recipient)))
+ });
+ }
+
+ // Create the advanced order.
+ AdvancedOrder memory advancedOrder = AdvancedOrder({
+ parameters: orderParameters,
+ numerator: 1,
+ denominator: 1,
+ signature: new bytes(0),
+ extraData: abi.encodePacked(bytes32(testCase.extraData))
+ });
+
+ // Generate the order hash.
+ bytes32 orderHash = context.consideration.getOrderHash(
+ advancedOrder.parameters.toOrderComponents(0)
+ );
+
+ // Create the expected zone parameters.
+ ZoneParameters memory zoneParameters = ZoneParameters({
+ orderHash: orderHash,
+ fulfiller: address(this),
+ offerer: address(this),
+ offer: orderParameters.offer.toSpentItemArray(),
+ consideration: orderParameters.consideration.toReceivedItemArray(),
+ extraData: abi.encodePacked(bytes32(testCase.extraData)),
+ orderHashes: new bytes32[](0),
+ startTime: testCase.startTime,
+ endTime: testCase.endTime,
+ zoneHash: bytes32(testCase.zoneHash)
+ });
+
+ // Hash the zone parameters.
+ bytes32 expectedZoneHash = bytes32(
+ keccak256(abi.encode(zoneParameters))
+ );
+
+ // Send the expectation for authorize to the test zone.
+ testZone.setExpectedAuthorizeCalldataHash(expectedZoneHash);
+
+ // Add the order hash to the zone parameters.
+ zoneParameters.orderHashes = new bytes32[](1);
+ zoneParameters.orderHashes[0] = orderHash;
+
+ // Hash the updated zone parameters.
+ expectedZoneHash = bytes32(keccak256(abi.encode(zoneParameters)));
+
+ // Send the expectation for validate to the test zone.
+ testZone.setExpectedValidateCalldataHash(expectedZoneHash);
+
+ // Fulfill the advanced order.
+ context.consideration.fulfillAdvancedOrder({
+ advancedOrder: advancedOrder,
+ criteriaResolvers: new CriteriaResolver[](0),
+ fulfillerConduitKey: bytes32(0),
+ recipient: payable(address(uint160(testCase.recipient)))
+ });
+ }
+
+ function _boundTestCase(
+ TestCase memory _testCase
+ ) internal view returns (TestCase memory) {
+ TestCase memory testCase = _testCase;
+
+ testCase.itemType = bound(testCase.itemType, 2, 2);
+ testCase.offerItemStartingIdentifier = bound(
+ testCase.offerItemStartingIdentifier,
+ 1,
+ type(uint16).max
+ );
+ testCase.considerationItemStartingIdentifier = bound(
+ testCase.considerationItemStartingIdentifier,
+ type(uint32).max,
+ type(uint64).max
+ );
+ testCase.startAmount = bound(testCase.startAmount, 1, 1);
+ testCase.endAmount = bound(
+ testCase.endAmount,
+ 1,
+ testCase.itemType == 2 ? 1 : 1000
+ );
+ testCase.recipient = bound(testCase.recipient, 10, type(uint160).max);
+ testCase.offerLength = bound(testCase.offerLength, 1, 30);
+ testCase.considerationLength = bound(
+ testCase.considerationLength,
+ 1,
+ 30
+ );
+ testCase.orderType = bound(testCase.orderType, 1, 3); // 0, 4);
+ testCase.startTime = bound(testCase.startTime, 0, 1);
+ testCase.endTime = bound(
+ testCase.endTime,
+ block.timestamp + 1,
+ type(uint256).max
+ );
+
+ return testCase;
+ }
+
+ function _mintNecessaryTokens(TestCase memory testCase) internal {
+ for (uint256 i = 0; i < testCase.offerLength; i++) {
+ test721_1.mint(
+ address(this),
+ testCase.offerItemStartingIdentifier + i
+ );
+ test1155_1.mint(
+ address(this),
+ testCase.offerItemStartingIdentifier + i,
+ testCase.endAmount
+ );
+ }
+ for (uint256 i = 0; i < testCase.considerationLength; i++) {
+ test721_1.mint(
+ address(this),
+ testCase.considerationItemStartingIdentifier + i
+ );
+ test1155_1.mint(
+ address(this),
+ testCase.considerationItemStartingIdentifier + i,
+ testCase.endAmount
+ );
+ }
+ }
+}
diff --git a/test/foundry/zone/UnauthorizedOrderSkip.t.sol b/test/foundry/zone/UnauthorizedOrderSkip.t.sol
new file mode 100644
index 000000000..85d2e23f7
--- /dev/null
+++ b/test/foundry/zone/UnauthorizedOrderSkip.t.sol
@@ -0,0 +1,1665 @@
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.17;
+
+import {
+ ConsiderationItemLib,
+ FulfillmentLib,
+ OfferItemLib,
+ OrderComponentsLib,
+ OrderLib,
+ OrderParametersLib,
+ SeaportArrays
+} from "seaport-sol/src/lib/SeaportStructLib.sol";
+
+import { UnavailableReason } from "seaport-sol/src/SpaceEnums.sol";
+
+import { BaseOrderTest } from "../utils/BaseOrderTest.sol";
+
+import {
+ AdvancedOrder,
+ ConsiderationItem,
+ CriteriaResolver,
+ Fulfillment,
+ FulfillmentComponent,
+ ItemType,
+ OfferItem,
+ Order,
+ OrderComponents,
+ OrderParameters
+} from "seaport-types/src/lib/ConsiderationStructs.sol";
+
+import { OrderType } from "seaport-types/src/lib/ConsiderationEnums.sol";
+
+import {
+ ConsiderationInterface
+} from "seaport-types/src/interfaces/ConsiderationInterface.sol";
+
+import {
+ FulfillAvailableHelper
+} from "seaport-sol/src/fulfillments/available/FulfillAvailableHelper.sol";
+
+import {
+ MatchFulfillmentHelper
+} from "seaport-sol/src/fulfillments/match/MatchFulfillmentHelper.sol";
+
+import { VerboseAuthZone } from "./impl/VerboseAuthZone.sol";
+
+contract UnauthorizedOrderSkipTest is BaseOrderTest {
+ using OfferItemLib for OfferItem;
+ using ConsiderationItemLib for ConsiderationItem;
+ using OrderComponentsLib for OrderComponents;
+ using OrderParametersLib for OrderParameters;
+ using OrderLib for Order;
+
+ MatchFulfillmentHelper matchFulfillmentHelper;
+ FulfillAvailableHelper fulfillAvailableFulfillmentHelper;
+
+ struct Context {
+ ConsiderationInterface seaport;
+ bool isReference;
+ FulfillFuzzInputs fulfillArgs;
+ MatchFuzzInputs matchArgs;
+ }
+
+ struct FulfillFuzzInputs {
+ uint256 tokenId;
+ uint128 amount;
+ uint128 excessNativeTokens;
+ uint256 orderCount;
+ uint256 considerationItemsPerOrderCount;
+ uint256 maximumFulfilledCount;
+ address offerRecipient;
+ address considerationRecipient;
+ bytes32 zoneHash;
+ uint256 salt;
+ bool shouldReturnInvalidMagicValue;
+ bool shouldRevert;
+ bool shouldAggregateFulfillmentComponents;
+ bool shouldUseConduit;
+ bool shouldIncludeNativeConsideration;
+ bool shouldIncludeExcessOfferItems;
+ bool shouldSpecifyRecipient;
+ bool shouldIncludeJunkDataInAdvancedOrder;
+ }
+
+ struct MatchFuzzInputs {
+ uint256 tokenId;
+ uint128 amount;
+ uint128 excessNativeTokens;
+ uint256 orderPairCount;
+ uint256 considerationItemsPerPrimeOrderCount;
+ // This is currently used only as the unspent prime offer item recipient
+ // but would also set the recipient for unspent mirror offer items if
+ // any were added in the test in the future.
+ address unspentPrimeOfferItemRecipient;
+ string primeOfferer;
+ string mirrorOfferer;
+ bytes32 zoneHash;
+ uint256 salt;
+ bool shouldReturnInvalidMagicValue;
+ bool shouldRevert;
+ bool shouldUseConduit;
+ bool shouldIncludeNativeConsideration;
+ bool shouldIncludeExcessOfferItems;
+ bool shouldSpecifyUnspentOfferItemRecipient;
+ bool shouldIncludeJunkDataInAdvancedOrder;
+ }
+
+ // Used for stack depth management.
+ struct MatchAdvancedOrdersInfra {
+ Order[] orders;
+ Fulfillment[] fulfillments;
+ AdvancedOrder[] advancedOrders;
+ CriteriaResolver[] criteriaResolvers;
+ uint256 callerBalanceBefore;
+ uint256 callerBalanceAfter;
+ uint256 primeOffererBalanceBefore;
+ uint256 primeOffererBalanceAfter;
+ }
+
+ // Used for stack depth management.
+ struct FulfillAvailableAdvancedOrdersInfra {
+ AdvancedOrder[] advancedOrders;
+ FulfillmentComponent[][] offerFulfillmentComponents;
+ FulfillmentComponent[][] considerationFulfillmentComponents;
+ CriteriaResolver[] criteriaResolvers;
+ uint256 callerBalanceBefore;
+ uint256 callerBalanceAfter;
+ uint256 considerationRecipientNativeBalanceBefore;
+ uint256 considerationRecipientToken1BalanceBefore;
+ uint256 considerationRecipientToken2BalanceBefore;
+ uint256 considerationRecipientNativeBalanceAfter;
+ uint256 considerationRecipientToken1BalanceAfter;
+ uint256 considerationRecipientToken2BalanceAfter;
+ }
+
+ // Used for stack depth management.
+ struct OrderAndFulfillmentInfra {
+ OfferItem[] offerItemArray;
+ ConsiderationItem[] considerationItemArray;
+ OrderComponents orderComponents;
+ Order[] orders;
+ Fulfillment fulfillment;
+ Fulfillment[] fulfillments;
+ }
+
+ // Used for stack depth management.
+ struct OrderComponentInfra {
+ OrderComponents orderComponents;
+ OrderComponents[] orderComponentsArray;
+ OfferItem[][] offerItemArray;
+ ConsiderationItem[][] considerationItemArray;
+ ConsiderationItem nativeConsiderationItem;
+ ConsiderationItem erc20ConsiderationItemOne;
+ ConsiderationItem erc20ConsiderationItemTwo;
+ }
+
+ event Authorized(bytes32 orderHash);
+ event AuthorizeOrderReverted(bytes32 orderHash);
+ event AuthorizeOrderNonMagicValue(bytes32 orderHash);
+
+ FulfillFuzzInputs emptyFulfill;
+ MatchFuzzInputs emptyMatch;
+
+ Account fuzzPrimeOfferer;
+ Account fuzzMirrorOfferer;
+
+ string constant SINGLE_721 = "single 721";
+ string constant STD_RESTRICTED = "validation zone";
+
+ function test(
+ function(Context memory) external fn,
+ Context memory context
+ ) internal {
+ try fn(context) {
+ fail();
+ } catch (bytes memory reason) {
+ assertPass(reason);
+ }
+ }
+
+ function setUp() public override {
+ super.setUp();
+ matchFulfillmentHelper = new MatchFulfillmentHelper();
+ fulfillAvailableFulfillmentHelper = new FulfillAvailableHelper();
+ // Can this be removed?
+ conduitController.updateChannel(address(conduit), address(this), true);
+ referenceConduitController.updateChannel(
+ address(referenceConduit),
+ address(this),
+ true
+ );
+
+ // create a default consideration for a single 721;
+ // note that it does not have recipient, token or
+ // identifier set
+ ConsiderationItemLib
+ .empty()
+ .withItemType(ItemType.ERC721)
+ .withStartAmount(1)
+ .withEndAmount(1)
+ .saveDefault(SINGLE_721);
+
+ // create a default offerItem for a single 721;
+ // note that it does not have token or identifier set
+ OfferItemLib
+ .empty()
+ .withItemType(ItemType.ERC721)
+ .withStartAmount(1)
+ .withEndAmount(1)
+ .saveDefault(SINGLE_721);
+
+ OrderComponentsLib
+ .empty()
+ .withOfferer(offerer1.addr)
+ .withOrderType(OrderType.FULL_RESTRICTED)
+ .withStartTime(block.timestamp)
+ .withEndTime(block.timestamp + 1)
+ .withZoneHash(bytes32(0))
+ .withSalt(0)
+ .withConduitKey(conduitKeyOne)
+ .saveDefault(STD_RESTRICTED);
+ }
+
+ function testMatchAuthRevertAndInvMagicValue(
+ MatchFuzzInputs memory _matchArgs
+ ) public {
+ _matchArgs = _boundMatchArgs(_matchArgs);
+
+ test(
+ this.execMatch,
+ Context({
+ seaport: consideration,
+ isReference: false,
+ matchArgs: _matchArgs,
+ fulfillArgs: emptyFulfill
+ })
+ );
+ test(
+ this.execMatch,
+ Context({
+ seaport: referenceConsideration,
+ isReference: true,
+ matchArgs: _matchArgs,
+ fulfillArgs: emptyFulfill
+ })
+ );
+ }
+
+ function execMatch(Context memory context) public stateless {
+ // Set up the zone.
+ VerboseAuthZone verboseZone = new VerboseAuthZone(
+ context.matchArgs.shouldReturnInvalidMagicValue,
+ context.matchArgs.shouldRevert
+ );
+
+ vm.label(address(verboseZone), "VerboseZone");
+
+ // Set up the infrastructure for this function in a struct to avoid
+ // stack depth issues.
+ MatchAdvancedOrdersInfra memory infra = MatchAdvancedOrdersInfra({
+ orders: new Order[](context.matchArgs.orderPairCount),
+ fulfillments: new Fulfillment[](context.matchArgs.orderPairCount),
+ advancedOrders: new AdvancedOrder[](
+ context.matchArgs.orderPairCount
+ ),
+ criteriaResolvers: new CriteriaResolver[](0),
+ callerBalanceBefore: 0,
+ callerBalanceAfter: 0,
+ primeOffererBalanceBefore: 0,
+ primeOffererBalanceAfter: 0
+ });
+
+ // The prime offerer is offering NFTs and considering ERC20/Native.
+ fuzzPrimeOfferer = makeAndAllocateAccount(
+ context.matchArgs.primeOfferer
+ );
+ // The mirror offerer is offering ERC20/Native and considering NFTs.
+ fuzzMirrorOfferer = makeAndAllocateAccount(
+ context.matchArgs.mirrorOfferer
+ );
+
+ // Create the orders and fulfuillments.
+ (
+ infra.orders,
+ infra.fulfillments
+ ) = _buildOrdersAndFulfillmentsMirrorOrdersFromFuzzArgs(
+ context,
+ address(verboseZone)
+ );
+
+ // Set up the advanced orders array.
+ infra.advancedOrders = new AdvancedOrder[](infra.orders.length);
+
+ // Convert the orders to advanced orders.
+ for (uint256 i = 0; i < infra.orders.length; i++) {
+ infra.advancedOrders[i] = infra.orders[i].toAdvancedOrder(
+ 1,
+ 1,
+ context.matchArgs.shouldIncludeJunkDataInAdvancedOrder
+ ? bytes(
+ abi.encodePacked(
+ context.matchArgs.salt,
+ context.matchArgs.salt
+ )
+ )
+ : bytes("")
+ );
+ }
+
+ // Store the native token balances before the call for later reference.
+ infra.callerBalanceBefore = address(this).balance;
+ infra.primeOffererBalanceBefore = address(fuzzPrimeOfferer.addr)
+ .balance;
+
+ // Set up expectations for the call.
+ uint256 offererCounter = context.seaport.getCounter(
+ infra.orders[0].parameters.offerer
+ );
+
+ // Set up the first orderHash.
+ bytes32 orderHash = context.seaport.getOrderHash(
+ infra.orders[0].parameters.toOrderComponents(offererCounter)
+ );
+
+ if (context.matchArgs.shouldReturnInvalidMagicValue) {
+ // Expect AuthorizeOrderNonMagicValue event.
+ vm.expectEmit(true, false, false, true, address(verboseZone));
+ emit AuthorizeOrderNonMagicValue(orderHash);
+ vm.expectRevert(
+ abi.encodeWithSignature(
+ "InvalidRestrictedOrder(bytes32)",
+ orderHash
+ )
+ );
+ } else if (context.matchArgs.shouldRevert) {
+ // Expect AuthorizeOrderReverted event.
+ vm.expectEmit(true, false, false, true, address(verboseZone));
+ emit AuthorizeOrderReverted(orderHash);
+ if (context.isReference) {
+ vm.expectRevert(
+ abi.encodeWithSignature(
+ "InvalidRestrictedOrder(bytes32)",
+ orderHash
+ )
+ );
+ } else {
+ vm.expectRevert(
+ abi.encodeWithSignature("OrderNotAuthorized()")
+ );
+ }
+ } else {
+ if (
+ !context.matchArgs.shouldRevert &&
+ !context.matchArgs.shouldReturnInvalidMagicValue
+ ) {
+ bytes32[] memory orderHashesToAuth = new bytes32[](
+ infra.orders.length
+ );
+
+ // Iterate over the orders and authorize them, then set up event expectations.
+ for (uint256 i = 0; i < infra.orders.length; i++) {
+ offererCounter = context.seaport.getCounter(
+ infra.orders[i].parameters.offerer
+ );
+
+ // Set up the orderHash.
+ orderHash = context.seaport.getOrderHash(
+ infra.orders[i].parameters.toOrderComponents(
+ offererCounter
+ )
+ );
+
+ orderHashesToAuth[i] = orderHash;
+
+ // Call `setAuthorizationStatus` on the verboseZone.
+ verboseZone.setAuthorizationStatus(orderHash, true);
+ }
+
+ // Iterate again and set up the expectations for the events.
+ // (Can't call `getOrderHash` between `vm.expectEmit` calls).
+ for (uint256 i = 0; i < orderHashesToAuth.length; i++) {
+ if (orderHashesToAuth[i] != bytes32(0)) {
+ // Expect Authorized event.
+ vm.expectEmit(
+ true,
+ false,
+ false,
+ true,
+ address(verboseZone)
+ );
+ emit Authorized(orderHashesToAuth[i]);
+ }
+ }
+ }
+
+ if (
+ // When shouldIncludeNativeConsideration is false, there will be
+ // exactly one token1 consideration item per orderPairCount. And
+ // they'll all get aggregated into a single transfer.
+ !context.matchArgs.shouldIncludeNativeConsideration
+ ) {
+ // This checks that the ERC20 transfers were all aggregated into
+ // a single transfer.
+ vm.expectEmit(true, true, false, true, address(token1));
+ emit Transfer(
+ address(fuzzMirrorOfferer.addr), // from
+ address(fuzzPrimeOfferer.addr), // to
+ context.matchArgs.amount * context.matchArgs.orderPairCount
+ );
+ }
+
+ if (
+ context
+ .matchArgs
+ // When considerationItemsPerPrimeOrderCount is 3, there will be
+ // exactly one token2 consideration item per orderPairCount.
+ // And they'll all get aggregated into a single transfer.
+ .considerationItemsPerPrimeOrderCount >= 3
+ ) {
+ vm.expectEmit(true, true, false, true, address(token2));
+ emit Transfer(
+ address(fuzzMirrorOfferer.addr), // from
+ address(fuzzPrimeOfferer.addr), // to
+ context.matchArgs.amount * context.matchArgs.orderPairCount
+ );
+ }
+ }
+
+ // Make the call to Seaport.
+ context.seaport.matchAdvancedOrders{
+ value: (context.matchArgs.amount *
+ context.matchArgs.orderPairCount) +
+ context.matchArgs.excessNativeTokens
+ }(
+ infra.advancedOrders,
+ infra.criteriaResolvers,
+ infra.fulfillments,
+ // If shouldSpecifyUnspentOfferItemRecipient is true, send the
+ // unspent offer items to the recipient specified by the fuzz args.
+ // Otherwise, pass in the zero address, which will result in the
+ // unspent offer items being sent to the caller.
+ context.matchArgs.shouldSpecifyUnspentOfferItemRecipient
+ ? address(context.matchArgs.unspentPrimeOfferItemRecipient)
+ : address(0)
+ );
+
+ // If the call should return an invalid magic value or revert, return
+ // early.
+ if (
+ context.matchArgs.shouldReturnInvalidMagicValue ||
+ context.matchArgs.shouldRevert
+ ) {
+ return;
+ }
+
+ // Note the native token balances after the call for later checks.
+ infra.callerBalanceAfter = address(this).balance;
+ infra.primeOffererBalanceAfter = address(fuzzPrimeOfferer.addr).balance;
+
+ // Check that the NFTs were transferred to the expected recipient.
+ for (uint256 i = 0; i < context.matchArgs.orderPairCount; i++) {
+ assertEq(
+ test721_1.ownerOf(context.matchArgs.tokenId + i),
+ fuzzMirrorOfferer.addr
+ );
+ }
+
+ if (context.matchArgs.shouldIncludeExcessOfferItems) {
+ // Check that the excess offer NFTs were transferred to the expected
+ // recipient.
+ for (uint256 i = 0; i < context.matchArgs.orderPairCount; i++) {
+ assertEq(
+ test721_1.ownerOf((context.matchArgs.tokenId + i) * 2),
+ context.matchArgs.shouldSpecifyUnspentOfferItemRecipient
+ ? context.matchArgs.unspentPrimeOfferItemRecipient
+ : address(this)
+ );
+ }
+ }
+
+ if (context.matchArgs.shouldIncludeNativeConsideration) {
+ // Check that ETH is moving from the caller to the prime offerer.
+ // This also checks that excess native tokens are being swept back
+ // to the caller.
+ assertEq(
+ infra.callerBalanceBefore -
+ context.matchArgs.amount *
+ context.matchArgs.orderPairCount,
+ infra.callerBalanceAfter
+ );
+ assertEq(
+ infra.primeOffererBalanceBefore +
+ context.matchArgs.amount *
+ context.matchArgs.orderPairCount,
+ infra.primeOffererBalanceAfter
+ );
+ } else {
+ assertEq(infra.callerBalanceBefore, infra.callerBalanceAfter);
+ }
+ }
+
+ function testFulfillAvailableAuthRevertAndInvMagicValue(
+ FulfillFuzzInputs memory fulfillArgs
+ ) public {
+ fulfillArgs = _boundFulfillArgs(fulfillArgs);
+
+ test(
+ this.execFulfillAvailable,
+ Context(consideration, false, fulfillArgs, emptyMatch)
+ );
+ test(
+ this.execFulfillAvailable,
+ Context(referenceConsideration, true, fulfillArgs, emptyMatch)
+ );
+ }
+
+ function execFulfillAvailable(Context memory context) external stateless {
+ // Set up the infrastructure.
+ FulfillAvailableAdvancedOrdersInfra
+ memory infra = FulfillAvailableAdvancedOrdersInfra({
+ advancedOrders: new AdvancedOrder[](
+ context.fulfillArgs.orderCount
+ ),
+ offerFulfillmentComponents: new FulfillmentComponent[][](
+ context.fulfillArgs.orderCount
+ ),
+ considerationFulfillmentComponents: new FulfillmentComponent[][](
+ context.fulfillArgs.orderCount
+ ),
+ criteriaResolvers: new CriteriaResolver[](0),
+ callerBalanceBefore: address(this).balance,
+ callerBalanceAfter: address(this).balance,
+ considerationRecipientNativeBalanceBefore: context
+ .fulfillArgs
+ .considerationRecipient
+ .balance,
+ considerationRecipientToken1BalanceBefore: token1.balanceOf(
+ context.fulfillArgs.considerationRecipient
+ ),
+ considerationRecipientToken2BalanceBefore: token2.balanceOf(
+ context.fulfillArgs.considerationRecipient
+ ),
+ considerationRecipientNativeBalanceAfter: context
+ .fulfillArgs
+ .considerationRecipient
+ .balance,
+ considerationRecipientToken1BalanceAfter: token1.balanceOf(
+ context.fulfillArgs.considerationRecipient
+ ),
+ considerationRecipientToken2BalanceAfter: token2.balanceOf(
+ context.fulfillArgs.considerationRecipient
+ )
+ });
+
+ // Use a conduit sometimes.
+ bytes32 conduitKey = context.fulfillArgs.shouldUseConduit
+ ? conduitKeyOne
+ : bytes32(0);
+
+ // Mint enough ERC721s to cover the number of NFTs for sale.
+ for (uint256 i; i < context.fulfillArgs.orderCount; i++) {
+ test721_1.mint(offerer1.addr, context.fulfillArgs.tokenId + i);
+ }
+
+ // Mint enough ERC20s to cover price per NFT * NFTs for sale.
+ token1.mint(
+ address(this),
+ context.fulfillArgs.amount * context.fulfillArgs.orderCount
+ );
+ token2.mint(
+ address(this),
+ context.fulfillArgs.amount * context.fulfillArgs.orderCount
+ );
+
+ // Set up the zone.
+ VerboseAuthZone verboseZone = new VerboseAuthZone(
+ context.fulfillArgs.shouldReturnInvalidMagicValue,
+ context.fulfillArgs.shouldRevert
+ );
+
+ vm.label(address(verboseZone), "VerboseZone");
+
+ // Create the orders.
+ infra.advancedOrders = _buildOrdersFromFuzzArgs(
+ context,
+ offerer1.key,
+ address(verboseZone)
+ );
+
+ // Create the fulfillments.
+ if (context.fulfillArgs.shouldAggregateFulfillmentComponents) {
+ (
+ infra.offerFulfillmentComponents,
+ infra.considerationFulfillmentComponents
+ ) = fulfillAvailableFulfillmentHelper
+ .getAggregatedFulfillmentComponents(infra.advancedOrders);
+ } else {
+ (
+ infra.offerFulfillmentComponents,
+ infra.considerationFulfillmentComponents
+ ) = fulfillAvailableFulfillmentHelper.getNaiveFulfillmentComponents(
+ infra.advancedOrders
+ );
+ }
+
+ // Store balances before the call for later comparison.
+ infra.callerBalanceBefore = address(this).balance;
+ infra.considerationRecipientNativeBalanceBefore = address(
+ context.fulfillArgs.considerationRecipient
+ ).balance;
+ infra.considerationRecipientToken1BalanceBefore = token1.balanceOf(
+ context.fulfillArgs.considerationRecipient
+ );
+ infra.considerationRecipientToken2BalanceBefore = token2.balanceOf(
+ context.fulfillArgs.considerationRecipient
+ );
+
+ bytes32[] memory orderHashesThatShouldRevertInAuth = new bytes32[](
+ infra.advancedOrders.length
+ );
+ uint256 skippedOrderCount;
+
+ // Set up expectations for the call.
+ if (context.fulfillArgs.shouldReturnInvalidMagicValue) {
+ uint256 offererCounter = context.seaport.getCounter(
+ infra.advancedOrders[0].parameters.offerer
+ );
+
+ // Set up the orderHash.
+ bytes32 orderHash = context.seaport.getOrderHash(
+ infra.advancedOrders[0].parameters.toOrderComponents(
+ offererCounter
+ )
+ );
+
+ // Expect AuthorizeOrderNonMagicValue event.
+ vm.expectEmit(true, false, false, true, address(verboseZone));
+ emit AuthorizeOrderNonMagicValue(orderHash);
+ vm.expectRevert(
+ abi.encodeWithSignature(
+ "InvalidRestrictedOrder(bytes32)",
+ orderHash
+ )
+ );
+ } else if (context.fulfillArgs.shouldRevert) {
+ bool gotOneKeeper;
+
+ // Iterate over the orders and expect AuthorizeOrderReverted events.
+ for (uint256 i = 0; i < infra.advancedOrders.length; i++) {
+ uint256 offererCounter = context.seaport.getCounter(
+ infra.advancedOrders[i].parameters.offerer
+ );
+
+ // Set up the orderHash.
+ bytes32 orderHash = context.seaport.getOrderHash(
+ infra.advancedOrders[i].parameters.toOrderComponents(
+ offererCounter
+ )
+ );
+
+ if ((uint256(orderHash) % 2) == 0 && gotOneKeeper) {
+ orderHashesThatShouldRevertInAuth[i] = orderHash;
+ skippedOrderCount++;
+ } else {
+ // Auth the order.
+ verboseZone.setAuthorizationStatus(orderHash, true);
+ gotOneKeeper = true;
+ }
+ }
+
+ for (
+ uint256 i = 0;
+ i < context.fulfillArgs.maximumFulfilledCount;
+ i++
+ ) {
+ if (orderHashesThatShouldRevertInAuth[i] != bytes32(0)) {
+ // Expect AuthorizeOrderReverted event.
+ vm.expectEmit(
+ true,
+ false,
+ false,
+ true,
+ address(verboseZone)
+ );
+ emit AuthorizeOrderReverted(
+ orderHashesThatShouldRevertInAuth[i]
+ );
+ }
+ }
+ } else {
+ // This is the happy path (no reverts or invalid magic values).
+ bytes32[] memory orderHashesToAuth = new bytes32[](
+ infra.advancedOrders.length
+ );
+
+ // Iterate over the orders and authorize them, then set up event
+ // expectations.
+ for (
+ uint256 i = 0;
+ i < context.fulfillArgs.maximumFulfilledCount;
+ i++
+ ) {
+ uint256 offererCounter = context.seaport.getCounter(
+ infra.advancedOrders[i].parameters.offerer
+ );
+
+ // Set up the orderHash.
+ bytes32 orderHash = context.seaport.getOrderHash(
+ infra.advancedOrders[i].parameters.toOrderComponents(
+ offererCounter
+ )
+ );
+
+ orderHashesToAuth[i] = orderHash;
+
+ // Auth the order.
+ verboseZone.setAuthorizationStatus(orderHash, true);
+ }
+
+ // Iterate again and set up the expectations for the events.
+ // (Can't call `getOrderHash` between `vm.expectEmit` calls).
+ for (uint256 i = 0; i < orderHashesToAuth.length; i++) {
+ if (orderHashesToAuth[i] != bytes32(0)) {
+ // Expect Authorized event.
+ vm.expectEmit(
+ true,
+ false,
+ false,
+ true,
+ address(verboseZone)
+ );
+ emit Authorized(orderHashesToAuth[i]);
+ }
+ }
+ }
+
+ // This is the happyish path.
+ if (!context.fulfillArgs.shouldReturnInvalidMagicValue) {
+ uint256 eligibleOrders = infra.advancedOrders.length -
+ skippedOrderCount;
+ uint256 expectedFulfilledOrderCount = eligibleOrders <
+ context.fulfillArgs.maximumFulfilledCount
+ ? eligibleOrders
+ : context.fulfillArgs.maximumFulfilledCount;
+
+ if (
+ !context.fulfillArgs.shouldIncludeNativeConsideration &&
+ // If the fuzz args pick this address as the consideration
+ // recipient, then the ERC20 transfers and the native token
+ // transfers will be filtered, so there will be no events.
+ address(context.fulfillArgs.considerationRecipient) !=
+ address(this)
+ ) {
+ // This checks that the ERC20 transfers were not all aggregated
+ // into a single transfer.
+ vm.expectEmit(true, true, false, true, address(token1));
+ emit Transfer(
+ address(this), // from
+ address(context.fulfillArgs.considerationRecipient), // to
+ // The value should in the transfer event should either be
+ // the amount * the number of NFTs for sale (if aggregating) or
+ // the amount (if not aggregating).
+ context.fulfillArgs.amount *
+ (
+ context
+ .fulfillArgs
+ .shouldAggregateFulfillmentComponents
+ ? expectedFulfilledOrderCount
+ : 1
+ )
+ );
+
+ if (context.fulfillArgs.considerationItemsPerOrderCount >= 2) {
+ // This checks that the second consideration item is being
+ // properly handled.
+ vm.expectEmit(true, true, false, true, address(token2));
+ emit Transfer(
+ address(this), // from
+ address(context.fulfillArgs.considerationRecipient), // to
+ context.fulfillArgs.amount *
+ (
+ context
+ .fulfillArgs
+ .shouldAggregateFulfillmentComponents
+ ? expectedFulfilledOrderCount
+ : 1
+ ) // value
+ );
+ }
+ }
+ }
+
+ // Make the call to Seaport. When the fuzz args call for using native
+ // consideration, send enough native tokens to cover the amount per sale
+ // * the number of sales. Otherwise, send just the excess native
+ // tokens.
+ context.seaport.fulfillAvailableAdvancedOrders{
+ value: context.fulfillArgs.excessNativeTokens +
+ (
+ context.fulfillArgs.shouldIncludeNativeConsideration
+ ? context.fulfillArgs.amount *
+ context.fulfillArgs.maximumFulfilledCount
+ : 0
+ )
+ }({
+ advancedOrders: infra.advancedOrders,
+ criteriaResolvers: infra.criteriaResolvers,
+ offerFulfillments: infra.offerFulfillmentComponents,
+ considerationFulfillments: infra.considerationFulfillmentComponents,
+ fulfillerConduitKey: bytes32(conduitKey),
+ // If the fuzz args call for specifying a recipient, pass in the
+ // offer recipient. Otherwise, pass in the null address, which
+ // sets the caller as the recipient.
+ recipient: context.fulfillArgs.shouldSpecifyRecipient
+ ? context.fulfillArgs.offerRecipient
+ : address(0),
+ maximumFulfilled: context.fulfillArgs.maximumFulfilledCount
+ });
+
+ // Return early if the call should return an invalid magic value,
+ // because that triggers a seaport-level revert.
+ if (context.fulfillArgs.shouldReturnInvalidMagicValue) {
+ return;
+ }
+
+ // Store balances after the call for later comparison.
+ infra.callerBalanceAfter = address(this).balance;
+ infra.considerationRecipientNativeBalanceAfter = address(
+ context.fulfillArgs.considerationRecipient
+ ).balance;
+ infra.considerationRecipientToken1BalanceAfter = token1.balanceOf(
+ context.fulfillArgs.considerationRecipient
+ );
+ infra.considerationRecipientToken2BalanceAfter = token2.balanceOf(
+ context.fulfillArgs.considerationRecipient
+ );
+
+ // Check that the NFTs were transferred to the expected recipient.
+ for (
+ uint256 i = 0;
+ i < context.fulfillArgs.maximumFulfilledCount;
+ i++
+ ) {
+ if (orderHashesThatShouldRevertInAuth[i] == bytes32(0)) {
+ // The NFT should be owned according to this snippet if the order
+ // was not skipped.
+ assertEq(
+ test721_1.ownerOf(context.fulfillArgs.tokenId + i),
+ context.fulfillArgs.shouldSpecifyRecipient
+ ? context.fulfillArgs.offerRecipient
+ : address(this),
+ "NFT owner incorrect."
+ );
+ } else {
+ // The NFT should be owned by the original minter if the order
+ // was skipped.
+ assertEq(
+ test721_1.ownerOf(context.fulfillArgs.tokenId + i),
+ offerer1.addr,
+ "NFT owner incorrect."
+ );
+ }
+ }
+
+ {
+ uint256 eligibleOrders = infra.advancedOrders.length -
+ skippedOrderCount;
+ uint256 expectedFulfilledOrderCount = eligibleOrders <
+ context.fulfillArgs.maximumFulfilledCount
+ ? eligibleOrders
+ : context.fulfillArgs.maximumFulfilledCount;
+
+ // Check that the ERC20s or native tokens were transferred to the
+ // expected recipient according to the fuzz args.
+ if (context.fulfillArgs.shouldIncludeNativeConsideration) {
+ if (
+ address(context.fulfillArgs.considerationRecipient) ==
+ address(this)
+ ) {
+ // Edge case: If the fuzz args pick this address for the
+ // consideration recipient, then the caller's balance should not
+ // change.
+ assertEq(
+ infra.callerBalanceAfter,
+ infra.callerBalanceBefore,
+ "Caller balance incorrect (this contract)."
+ );
+ } else {
+ // Check that the consideration recipient's native balance was
+ // increased by the amount * the number of NFTs for sale.
+ assertEq(
+ infra.considerationRecipientNativeBalanceAfter,
+ infra.considerationRecipientNativeBalanceBefore +
+ context.fulfillArgs.amount *
+ expectedFulfilledOrderCount,
+ "Consideration recipient native balance incorrect."
+ );
+ // The consideration (amount * maximumFulfilledCount) should be
+ // spent, and the excessNativeTokens should be returned.
+ assertEq(
+ infra.callerBalanceAfter +
+ context.fulfillArgs.amount *
+ expectedFulfilledOrderCount,
+ infra.callerBalanceBefore,
+ "Caller balance incorrect."
+ );
+ }
+ } else {
+ // The `else` here is the case where no native consieration is used.
+ if (
+ address(context.fulfillArgs.considerationRecipient) ==
+ address(this)
+ ) {
+ // Edge case: If the fuzz args pick this address for the
+ // consideration recipient, then the caller's balance should not
+ // change.
+ assertEq(
+ infra.considerationRecipientToken1BalanceAfter,
+ infra.considerationRecipientToken1BalanceBefore,
+ "Consideration recipient token1 balance incorrect (this)."
+ );
+ } else {
+ assertEq(
+ infra.considerationRecipientToken1BalanceAfter,
+ infra.considerationRecipientToken1BalanceBefore +
+ context.fulfillArgs.amount *
+ expectedFulfilledOrderCount,
+ "Consideration recipient token1 balance incorrect."
+ );
+ }
+
+ if (context.fulfillArgs.considerationItemsPerOrderCount >= 2) {
+ if (
+ address(context.fulfillArgs.considerationRecipient) ==
+ address(this)
+ ) {
+ // Edge case: If the fuzz args pick this address for the
+ // consideration recipient, then the caller's balance should
+ // not change.
+ assertEq(
+ infra.considerationRecipientToken2BalanceAfter,
+ infra.considerationRecipientToken2BalanceBefore,
+ "Consideration recipient token2 balance incorrect (this)."
+ );
+ } else {
+ assertEq(
+ infra.considerationRecipientToken2BalanceAfter,
+ infra.considerationRecipientToken2BalanceBefore +
+ context.fulfillArgs.amount *
+ expectedFulfilledOrderCount,
+ "Consideration recipient token2 balance incorrect."
+ );
+ }
+ }
+ }
+ }
+ }
+
+ ////////////////////////////////////////////////////////////////////////////
+ // //
+ // Pretty much everything below here can be ignored. It's all just very //
+ // lightly modified code from `TestTransferValidationZoneOffererTest`, //
+ // which is pretty stable. //
+ // //
+ ////////////////////////////////////////////////////////////////////////////
+
+ function _buildOrdersFromFuzzArgs(
+ Context memory context,
+ uint256 key,
+ address verboseZoneAddress
+ ) internal view returns (AdvancedOrder[] memory advancedOrders) {
+ // Create the OrderComponents array from the fuzz args.
+ OrderComponents[] memory orderComponents;
+ orderComponents = _buildOrderComponentsArrayFromFuzzArgs(
+ context,
+ verboseZoneAddress
+ );
+
+ // Set up the AdvancedOrder array.
+ AdvancedOrder[] memory _advancedOrders = new AdvancedOrder[](
+ context.fulfillArgs.orderCount
+ );
+
+ // Iterate over the OrderComponents array and build an AdvancedOrder
+ // for each OrderComponents.
+ Order memory order;
+ for (uint256 i = 0; i < orderComponents.length; i++) {
+ if (orderComponents[i].orderType == OrderType.CONTRACT) {
+ revert("Not implemented.");
+ } else {
+ // Create the order.
+ order = _toOrder(context.seaport, orderComponents[i], key);
+ // Convert it to an AdvancedOrder and add it to the array.
+ _advancedOrders[i] = order.toAdvancedOrder(
+ 1,
+ 1,
+ // Reusing salt here for junk data.
+ context.fulfillArgs.shouldIncludeJunkDataInAdvancedOrder
+ ? bytes(
+ abi.encodePacked(
+ context.fulfillArgs.salt,
+ context.fulfillArgs.salt
+ )
+ )
+ : bytes("")
+ );
+ }
+ }
+
+ return _advancedOrders;
+ }
+
+ function _buildOrdersAndFulfillmentsMirrorOrdersFromFuzzArgs(
+ Context memory context,
+ address verboseZoneAddress
+ ) internal returns (Order[] memory, Fulfillment[] memory) {
+ uint256 i;
+
+ // Set up the OrderAndFulfillmentInfra struct.
+ OrderAndFulfillmentInfra memory infra = OrderAndFulfillmentInfra(
+ new OfferItem[](context.matchArgs.orderPairCount),
+ new ConsiderationItem[](context.matchArgs.orderPairCount),
+ OrderComponentsLib.empty(),
+ new Order[](context.matchArgs.orderPairCount * 2),
+ FulfillmentLib.empty(),
+ new Fulfillment[](context.matchArgs.orderPairCount * 2)
+ );
+
+ // Iterate once for each orderPairCount, which is
+ // used as the number of order pairs to make here.
+ for (i = 0; i < context.matchArgs.orderPairCount; i++) {
+ // Mint the NFTs for the prime offerer to sell.
+ test721_1.mint(
+ fuzzPrimeOfferer.addr,
+ context.matchArgs.tokenId + i
+ );
+ test721_1.mint(
+ fuzzPrimeOfferer.addr,
+ (context.matchArgs.tokenId + i) * 2
+ );
+
+ // Build the OfferItem array for the prime offerer's order.
+ infra.offerItemArray = _buildPrimeOfferItemArray(context, i);
+ // Build the ConsiderationItem array for the prime offerer's order.
+ infra.considerationItemArray = _buildPrimeConsiderationItemArray(
+ context
+ );
+
+ // Build the OrderComponents for the prime offerer's order.
+ infra.orderComponents = _buildOrderComponents(
+ context,
+ infra.offerItemArray,
+ infra.considerationItemArray,
+ fuzzPrimeOfferer.addr,
+ verboseZoneAddress
+ );
+
+ // Add the order to the orders array.
+ infra.orders[i] = _toOrder(
+ context.seaport,
+ infra.orderComponents,
+ fuzzPrimeOfferer.key
+ );
+
+ // Build the offerItemArray for the mirror offerer's order.
+ infra.offerItemArray = _buildMirrorOfferItemArray(context);
+
+ // Build the considerationItemArray for the mirror offerer's order.
+ // Note that the consideration on the mirror is always just one NFT,
+ // even if the prime order has an excess item.
+ infra.considerationItemArray = buildMirrorConsiderationItemArray(
+ context,
+ i
+ );
+
+ // Build the OrderComponents for the mirror offerer's order.
+ infra.orderComponents = _buildOrderComponents(
+ context,
+ infra.offerItemArray,
+ infra.considerationItemArray,
+ fuzzMirrorOfferer.addr,
+ verboseZoneAddress
+ );
+
+ // Create the order and add the order to the orders array.
+ infra.orders[i + context.matchArgs.orderPairCount] = _toOrder(
+ context.seaport,
+ infra.orderComponents,
+ fuzzMirrorOfferer.key
+ );
+ }
+
+ bytes32[] memory orderHashes = new bytes32[](
+ context.matchArgs.orderPairCount * 2
+ );
+
+ UnavailableReason[] memory unavailableReasons = new UnavailableReason[](
+ context.matchArgs.orderPairCount * 2
+ );
+
+ // Build fulfillments.
+ (infra.fulfillments, , ) = matchFulfillmentHelper
+ .getMatchedFulfillments(
+ infra.orders,
+ orderHashes,
+ unavailableReasons
+ );
+
+ return (infra.orders, infra.fulfillments);
+ }
+
+ function _buildPrimeOfferItemArray(
+ Context memory context,
+ uint256 i
+ ) internal view returns (OfferItem[] memory _offerItemArray) {
+ // Set up the OfferItem array.
+ OfferItem[] memory offerItemArray = new OfferItem[](
+ context.matchArgs.shouldIncludeExcessOfferItems ? 2 : 1
+ );
+
+ // If the fuzz args call for an excess offer item...
+ if (context.matchArgs.shouldIncludeExcessOfferItems) {
+ // Create the OfferItem array containing the offered item and the
+ // excess item.
+ offerItemArray = SeaportArrays.OfferItems(
+ OfferItemLib
+ .fromDefault(SINGLE_721)
+ .withToken(address(test721_1))
+ .withIdentifierOrCriteria(context.matchArgs.tokenId + i),
+ OfferItemLib
+ .fromDefault(SINGLE_721)
+ .withToken(address(test721_1))
+ .withIdentifierOrCriteria(
+ (context.matchArgs.tokenId + i) * 2
+ )
+ );
+ } else {
+ // Otherwise, create the OfferItem array containing the one offered
+ // item.
+ offerItemArray = SeaportArrays.OfferItems(
+ OfferItemLib
+ .fromDefault(SINGLE_721)
+ .withToken(address(test721_1))
+ .withIdentifierOrCriteria(context.matchArgs.tokenId + i)
+ );
+ }
+
+ return offerItemArray;
+ }
+
+ function _buildPrimeConsiderationItemArray(
+ Context memory context
+ )
+ internal
+ view
+ returns (ConsiderationItem[] memory _considerationItemArray)
+ {
+ // Set up the ConsiderationItem array.
+ ConsiderationItem[]
+ memory considerationItemArray = new ConsiderationItem[](
+ context.matchArgs.considerationItemsPerPrimeOrderCount
+ );
+
+ // Create the consideration items.
+ (
+ ConsiderationItem memory nativeConsiderationItem,
+ ConsiderationItem memory erc20ConsiderationItemOne,
+ ConsiderationItem memory erc20ConsiderationItemTwo
+ ) = _createReusableConsiderationItems(
+ context.matchArgs.amount,
+ fuzzPrimeOfferer.addr
+ );
+
+ if (context.matchArgs.considerationItemsPerPrimeOrderCount == 1) {
+ // If the fuzz args call for native consideration...
+ if (context.matchArgs.shouldIncludeNativeConsideration) {
+ // ...add a native consideration item...
+ considerationItemArray = SeaportArrays.ConsiderationItems(
+ nativeConsiderationItem
+ );
+ } else {
+ // ...otherwise, add an ERC20 consideration item.
+ considerationItemArray = SeaportArrays.ConsiderationItems(
+ erc20ConsiderationItemOne
+ );
+ }
+ } else if (
+ context.matchArgs.considerationItemsPerPrimeOrderCount == 2
+ ) {
+ // If the fuzz args call for native consideration...
+ if (context.matchArgs.shouldIncludeNativeConsideration) {
+ // ...add a native consideration item and an ERC20
+ // consideration item...
+ considerationItemArray = SeaportArrays.ConsiderationItems(
+ nativeConsiderationItem,
+ erc20ConsiderationItemOne
+ );
+ } else {
+ // ...otherwise, add two ERC20 consideration items.
+ considerationItemArray = SeaportArrays.ConsiderationItems(
+ erc20ConsiderationItemOne,
+ erc20ConsiderationItemTwo
+ );
+ }
+ } else {
+ // If the fuzz args call for three consideration items per prime
+ // order, add all three consideration items.
+ considerationItemArray = SeaportArrays.ConsiderationItems(
+ nativeConsiderationItem,
+ erc20ConsiderationItemOne,
+ erc20ConsiderationItemTwo
+ );
+ }
+
+ return considerationItemArray;
+ }
+
+ function _buildOrderComponentsArrayFromFuzzArgs(
+ Context memory context,
+ address verboseZoneAddress
+ ) internal view returns (OrderComponents[] memory _orderComponentsArray) {
+ // Set up the OrderComponentInfra struct.
+ OrderComponentInfra memory orderComponentInfra = OrderComponentInfra(
+ OrderComponentsLib.empty(),
+ new OrderComponents[](context.fulfillArgs.orderCount),
+ new OfferItem[][](context.fulfillArgs.orderCount),
+ new ConsiderationItem[][](context.fulfillArgs.orderCount),
+ ConsiderationItemLib.empty(),
+ ConsiderationItemLib.empty(),
+ ConsiderationItemLib.empty()
+ );
+
+ // Create three different consideration items.
+ (
+ orderComponentInfra.nativeConsiderationItem,
+ orderComponentInfra.erc20ConsiderationItemOne,
+ orderComponentInfra.erc20ConsiderationItemTwo
+ ) = _createReusableConsiderationItems(
+ context.fulfillArgs.amount,
+ context.fulfillArgs.considerationRecipient
+ );
+
+ // Iterate once for each order and create the OfferItems[] and
+ // ConsiderationItems[] for each order.
+ for (uint256 i; i < context.fulfillArgs.orderCount; i++) {
+ // Add a one-element OfferItems[] to the OfferItems[][].
+ orderComponentInfra.offerItemArray[i] = SeaportArrays.OfferItems(
+ OfferItemLib
+ .fromDefault(SINGLE_721)
+ .withToken(address(test721_1))
+ .withIdentifierOrCriteria(context.fulfillArgs.tokenId + i)
+ );
+
+ if (context.fulfillArgs.considerationItemsPerOrderCount == 1) {
+ // If the fuzz args call for native consideration...
+ if (context.fulfillArgs.shouldIncludeNativeConsideration) {
+ // ...add a native consideration item...
+ orderComponentInfra.considerationItemArray[
+ i
+ ] = SeaportArrays.ConsiderationItems(
+ orderComponentInfra.nativeConsiderationItem
+ );
+ } else {
+ // ...otherwise, add an ERC20 consideration item.
+ orderComponentInfra.considerationItemArray[
+ i
+ ] = SeaportArrays.ConsiderationItems(
+ orderComponentInfra.erc20ConsiderationItemOne
+ );
+ }
+ } else if (
+ context.fulfillArgs.considerationItemsPerOrderCount == 2
+ ) {
+ // If the fuzz args call for native consideration...
+ if (context.fulfillArgs.shouldIncludeNativeConsideration) {
+ // ...add a native consideration item and an ERC20
+ // consideration item...
+ orderComponentInfra.considerationItemArray[
+ i
+ ] = SeaportArrays.ConsiderationItems(
+ orderComponentInfra.nativeConsiderationItem,
+ orderComponentInfra.erc20ConsiderationItemOne
+ );
+ } else {
+ // ...otherwise, add two ERC20 consideration items.
+ orderComponentInfra.considerationItemArray[
+ i
+ ] = SeaportArrays.ConsiderationItems(
+ orderComponentInfra.erc20ConsiderationItemOne,
+ orderComponentInfra.erc20ConsiderationItemTwo
+ );
+ }
+ } else {
+ orderComponentInfra.considerationItemArray[i] = SeaportArrays
+ .ConsiderationItems(
+ orderComponentInfra.nativeConsiderationItem,
+ orderComponentInfra.erc20ConsiderationItemOne,
+ orderComponentInfra.erc20ConsiderationItemTwo
+ );
+ }
+ }
+
+ bytes32 conduitKey;
+
+ // Iterate once for each order and create the OrderComponents.
+ for (uint256 i = 0; i < context.fulfillArgs.orderCount; i++) {
+ // if context.fulfillArgs.shouldUseConduit is false: don't use conduits at all.
+ // if context.fulfillArgs.shouldUseConduit is true:
+ // if context.fulfillArgs.tokenId % 2 == 0:
+ // use conduits for some and not for others
+ // if context.fulfillArgs.tokenId % 2 != 0:
+ // use conduits for all
+ // This is plainly deranged, but it allows for conduit use
+ // for all, for some, and none without weighing down the stack.
+ conduitKey = !context
+ .fulfillArgs
+ .shouldIncludeNativeConsideration &&
+ context.fulfillArgs.shouldUseConduit &&
+ (context.fulfillArgs.tokenId % 2 == 0 ? i % 2 == 0 : true)
+ ? conduitKeyOne
+ : bytes32(0);
+
+ // Build the order components.
+ orderComponentInfra.orderComponents = OrderComponentsLib
+ .fromDefault(STD_RESTRICTED)
+ .withOffer(orderComponentInfra.offerItemArray[i])
+ .withConsideration(
+ orderComponentInfra.considerationItemArray[i]
+ )
+ .withZone(verboseZoneAddress)
+ .withZoneHash(context.fulfillArgs.zoneHash)
+ .withConduitKey(conduitKey)
+ .withSalt(context.fulfillArgs.salt % (i + 1)); // Is this dumb?
+
+ // Add the OrderComponents to the OrderComponents[].
+ orderComponentInfra.orderComponentsArray[i] = orderComponentInfra
+ .orderComponents;
+ }
+
+ // Return the OrderComponents[].
+ return orderComponentInfra.orderComponentsArray;
+ }
+
+ function _buildOrderComponents(
+ Context memory context,
+ OfferItem[] memory offerItemArray,
+ ConsiderationItem[] memory considerationItemArray,
+ address offerer,
+ address verboseZoneAddress
+ ) internal view returns (OrderComponents memory _orderComponents) {
+ OrderComponents memory orderComponents = OrderComponentsLib.empty();
+
+ // Create the offer and consideration item arrays.
+ OfferItem[] memory _offerItemArray = offerItemArray;
+ ConsiderationItem[]
+ memory _considerationItemArray = considerationItemArray;
+
+ // Build the OrderComponents for the prime offerer's order.
+ orderComponents = OrderComponentsLib
+ .fromDefault(STD_RESTRICTED)
+ .withOffer(_offerItemArray)
+ .withConsideration(_considerationItemArray)
+ .withZone(verboseZoneAddress)
+ .withOrderType(OrderType.FULL_OPEN)
+ .withConduitKey(
+ context.matchArgs.tokenId % 2 == 0 ? conduitKeyOne : bytes32(0)
+ )
+ .withOfferer(offerer)
+ .withCounter(context.seaport.getCounter(offerer));
+
+ // ... set the zone to the verboseZone and set the order type to
+ // FULL_RESTRICTED.
+ orderComponents = orderComponents
+ .copy()
+ .withZone(verboseZoneAddress)
+ .withOrderType(OrderType.FULL_RESTRICTED);
+
+ return orderComponents;
+ }
+
+ function _toOrder(
+ ConsiderationInterface seaport,
+ OrderComponents memory orderComponents,
+ uint256 pkey
+ ) internal view returns (Order memory order) {
+ bytes32 orderHash = seaport.getOrderHash(orderComponents);
+ bytes memory signature = signOrder(seaport, pkey, orderHash);
+ order = OrderLib
+ .empty()
+ .withParameters(orderComponents.toOrderParameters())
+ .withSignature(signature);
+ }
+
+ function _buildMirrorOfferItemArray(
+ Context memory context
+ ) internal view returns (OfferItem[] memory _offerItemArray) {
+ // Set up the OfferItem array.
+ OfferItem[] memory offerItemArray = new OfferItem[](1);
+
+ // Create some consideration items.
+ (
+ ConsiderationItem memory nativeConsiderationItem,
+ ConsiderationItem memory erc20ConsiderationItemOne,
+ ConsiderationItem memory erc20ConsiderationItemTwo
+ ) = _createReusableConsiderationItems(
+ context.matchArgs.amount,
+ fuzzPrimeOfferer.addr
+ );
+
+ // Convert them to OfferItems.
+ OfferItem memory nativeOfferItem = nativeConsiderationItem
+ .toOfferItem();
+ OfferItem memory erc20OfferItemOne = erc20ConsiderationItemOne
+ .toOfferItem();
+ OfferItem memory erc20OfferItemTwo = erc20ConsiderationItemTwo
+ .toOfferItem();
+
+ if (context.matchArgs.considerationItemsPerPrimeOrderCount == 1) {
+ // If the fuzz args call for native consideration...
+ if (context.matchArgs.shouldIncludeNativeConsideration) {
+ // ...add a native consideration item...
+ offerItemArray = SeaportArrays.OfferItems(nativeOfferItem);
+ } else {
+ // ...otherwise, add an ERC20 consideration item.
+ offerItemArray = SeaportArrays.OfferItems(erc20OfferItemOne);
+ }
+ } else if (
+ context.matchArgs.considerationItemsPerPrimeOrderCount == 2
+ ) {
+ // If the fuzz args call for native consideration...
+ if (context.matchArgs.shouldIncludeNativeConsideration) {
+ // ...add a native consideration item and an ERC20
+ // consideration item...
+ offerItemArray = SeaportArrays.OfferItems(
+ nativeOfferItem,
+ erc20OfferItemOne
+ );
+ } else {
+ // ...otherwise, add two ERC20 consideration items.
+ offerItemArray = SeaportArrays.OfferItems(
+ erc20OfferItemOne,
+ erc20OfferItemTwo
+ );
+ }
+ } else {
+ offerItemArray = SeaportArrays.OfferItems(
+ nativeOfferItem,
+ erc20OfferItemOne,
+ erc20OfferItemTwo
+ );
+ }
+
+ return offerItemArray;
+ }
+
+ function buildMirrorConsiderationItemArray(
+ Context memory context,
+ uint256 i
+ )
+ internal
+ view
+ returns (ConsiderationItem[] memory _considerationItemArray)
+ {
+ // Set up the ConsiderationItem array.
+ ConsiderationItem[]
+ memory considerationItemArray = new ConsiderationItem[](
+ context.matchArgs.considerationItemsPerPrimeOrderCount
+ );
+
+ // Note that the consideration array here will always be just one NFT
+ // so because the second NFT on the offer side is meant to be excess.
+ considerationItemArray = SeaportArrays.ConsiderationItems(
+ ConsiderationItemLib
+ .fromDefault(SINGLE_721)
+ .withToken(address(test721_1))
+ .withIdentifierOrCriteria(context.matchArgs.tokenId + i)
+ .withRecipient(fuzzMirrorOfferer.addr)
+ );
+
+ return considerationItemArray;
+ }
+
+ function _createReusableConsiderationItems(
+ uint256 amount,
+ address recipient
+ )
+ internal
+ view
+ returns (
+ ConsiderationItem memory nativeConsiderationItem,
+ ConsiderationItem memory erc20ConsiderationItemOne,
+ ConsiderationItem memory erc20ConsiderationItemTwo
+ )
+ {
+ // Create a reusable native consideration item.
+ nativeConsiderationItem = ConsiderationItemLib
+ .empty()
+ .withItemType(ItemType.NATIVE)
+ .withIdentifierOrCriteria(0)
+ .withStartAmount(amount)
+ .withEndAmount(amount)
+ .withRecipient(recipient);
+
+ // Create a reusable ERC20 consideration item.
+ erc20ConsiderationItemOne = ConsiderationItemLib
+ .empty()
+ .withItemType(ItemType.ERC20)
+ .withToken(address(token1))
+ .withIdentifierOrCriteria(0)
+ .withStartAmount(amount)
+ .withEndAmount(amount)
+ .withRecipient(recipient);
+
+ // Create a second reusable ERC20 consideration item.
+ erc20ConsiderationItemTwo = ConsiderationItemLib
+ .empty()
+ .withItemType(ItemType.ERC20)
+ .withIdentifierOrCriteria(0)
+ .withToken(address(token2))
+ .withStartAmount(amount)
+ .withEndAmount(amount)
+ .withRecipient(recipient);
+ }
+
+ function _boundMatchArgs(
+ MatchFuzzInputs memory matchArgs
+ ) internal returns (MatchFuzzInputs memory) {
+ // Avoid weird overflow issues.
+ matchArgs.amount = uint128(
+ bound(matchArgs.amount, 1, 0xffffffffffffffff)
+ );
+ // Avoid trying to mint the same token.
+ matchArgs.tokenId = bound(matchArgs.tokenId, 0xff, 0xffffffffffffffff);
+ // Make 2-8 order pairs per call. Each order pair will have 1-2 offer
+ // items on the prime side (depending on whether
+ // shouldIncludeExcessOfferItems is true or false).
+ matchArgs.orderPairCount = bound(matchArgs.orderPairCount, 2, 32);
+ // Use 1-3 (prime) consideration items per order.
+ matchArgs.considerationItemsPerPrimeOrderCount = bound(
+ matchArgs.considerationItemsPerPrimeOrderCount,
+ 1,
+ 3
+ );
+ // To put three items in the consideration, native tokens must be
+ // included.
+ matchArgs.shouldIncludeNativeConsideration =
+ matchArgs.shouldIncludeNativeConsideration ||
+ matchArgs.considerationItemsPerPrimeOrderCount >= 3;
+ // Include some excess native tokens to check that they're ending up
+ // with the caller afterward.
+ matchArgs.excessNativeTokens = uint128(
+ bound(
+ matchArgs.excessNativeTokens,
+ 0,
+ 0xfffffffffffffffffffffffffffff
+ )
+ );
+ // Don't set the offer recipient to the null address, because that's the
+ // way to indicate that the caller should be the recipient.
+ matchArgs.unspentPrimeOfferItemRecipient = _nudgeAddressIfProblematic(
+ address(
+ uint160(
+ bound(
+ uint160(matchArgs.unspentPrimeOfferItemRecipient),
+ 1,
+ type(uint160).max
+ )
+ )
+ )
+ );
+
+ matchArgs.shouldRevert =
+ matchArgs.shouldRevert &&
+ !matchArgs.shouldReturnInvalidMagicValue;
+
+ return matchArgs;
+ }
+
+ function _boundFulfillArgs(
+ FulfillFuzzInputs memory fulfillArgs
+ ) internal returns (FulfillFuzzInputs memory) {
+ // Limit this value to avoid overflow issues.
+ fulfillArgs.amount = uint128(
+ bound(fulfillArgs.amount, 1, 0xffffffffffffffff)
+ );
+ // Limit this value to avoid overflow issues.
+ fulfillArgs.tokenId = bound(fulfillArgs.tokenId, 1, 0xffffffffffffffff);
+ // Create between 4 and 16 orders.
+ fulfillArgs.orderCount = bound(fulfillArgs.orderCount, 4, 32);
+ // Use between 1 and 3 consideration items per order.
+ fulfillArgs.considerationItemsPerOrderCount = bound(
+ fulfillArgs.considerationItemsPerOrderCount,
+ 1,
+ 3
+ );
+ // To put three items in the consideration, native tokens must be
+ // included.
+ fulfillArgs.shouldIncludeNativeConsideration =
+ fulfillArgs.shouldIncludeNativeConsideration ||
+ fulfillArgs.considerationItemsPerOrderCount >= 3;
+ // Fulfill between 2 and the orderCount.
+ fulfillArgs.maximumFulfilledCount = bound(
+ fulfillArgs.maximumFulfilledCount,
+ 2,
+ fulfillArgs.orderCount
+ );
+ // Limit this value to avoid overflow issues.
+ fulfillArgs.excessNativeTokens = uint128(
+ bound(
+ fulfillArgs.excessNativeTokens,
+ 0,
+ 0xfffffffffffffffffffffffffffff
+ )
+ );
+ // Don't set the offer recipient to the null address, because that's the
+ // way to indicate that the caller should be the recipient and because
+ // some tokens refuse to transfer to the null address.
+ fulfillArgs.offerRecipient = _nudgeAddressIfProblematic(
+ address(
+ uint160(
+ bound(
+ uint160(fulfillArgs.offerRecipient),
+ 1,
+ type(uint160).max
+ )
+ )
+ )
+ );
+ // Don't set the consideration recipient to the null address, because
+ // some tokens refuse to transfer to the null address.
+ fulfillArgs.considerationRecipient = _nudgeAddressIfProblematic(
+ address(
+ uint160(
+ bound(
+ uint160(fulfillArgs.considerationRecipient),
+ 1,
+ type(uint160).max
+ )
+ )
+ )
+ );
+
+ fulfillArgs.shouldRevert =
+ fulfillArgs.shouldRevert &&
+ !fulfillArgs.shouldReturnInvalidMagicValue;
+
+ return fulfillArgs;
+ }
+
+ function _nudgeAddressIfProblematic(
+ address _address
+ ) internal returns (address) {
+ bool success;
+ assembly {
+ // Transfer the native token and store if it succeeded or not.
+ success := call(gas(), _address, 1, 0, 0, 0, 0)
+ }
+
+ if (success) {
+ return _address;
+ } else {
+ return address(uint160(_address) + 1);
+ }
+ }
+}
diff --git a/test/foundry/zone/impl/BadZone.sol b/test/foundry/zone/impl/BadZone.sol
index e92b2386d..22400a5b2 100644
--- a/test/foundry/zone/impl/BadZone.sol
+++ b/test/foundry/zone/impl/BadZone.sol
@@ -11,6 +11,12 @@ import { ERC165 } from "@openzeppelin/contracts/utils/introspection/ERC165.sol";
import { ZoneInterface } from "seaport-types/src/interfaces/ZoneInterface.sol";
contract BadZone is ERC165, ZoneInterface {
+ function authorizeOrder(
+ ZoneParameters calldata
+ ) public pure returns (bytes4) {
+ return this.authorizeOrder.selector;
+ }
+
function validateOrder(
ZoneParameters calldata zoneParameters
) external pure returns (bytes4 validOrderMagicValue) {
diff --git a/test/foundry/zone/impl/HashCalldataTestZone.sol b/test/foundry/zone/impl/HashCalldataTestZone.sol
new file mode 100644
index 000000000..6ec35225d
--- /dev/null
+++ b/test/foundry/zone/impl/HashCalldataTestZone.sol
@@ -0,0 +1,104 @@
+//SPDX-License-Identifier: MIT
+pragma solidity ^0.8.13;
+
+import {
+ Schema,
+ ZoneParameters
+} from "seaport-types/src/lib/ConsiderationStructs.sol";
+
+import { ZoneInterface } from "seaport-types/src/interfaces/ZoneInterface.sol";
+
+contract HashCalldataTestZone is ZoneInterface {
+ bytes32 public expectedZoneAuthorizeCalldataHash;
+ bytes32 public expectedZoneValidateCalldataHash;
+
+ function authorizeOrder(
+ ZoneParameters calldata zoneParameters
+ ) public view returns (bytes4) {
+ // Hash the zone parameters.
+ bytes32 _expectedZoneHash = bytes32(
+ keccak256(abi.encode(zoneParameters))
+ );
+
+ if (_expectedZoneHash != expectedZoneAuthorizeCalldataHash) {
+ revert(
+ "Zone calldata hash does not match expected zone hash in authorizeOrder"
+ );
+ }
+
+ // Return the authorizeOrder magic value.
+ return this.authorizeOrder.selector;
+ }
+
+ /**
+ * @dev Validates the order with the given `zoneParameters`. Called by
+ * Consideration whenever any extraData is provided by the caller.
+ *
+ * @param zoneParameters The parameters for the order.
+ *
+ * @return validOrderMagicValue The validOrder magic value.
+ */
+ function validateOrder(
+ ZoneParameters calldata zoneParameters
+ ) external view returns (bytes4 validOrderMagicValue) {
+ // Hash the zone parameters.
+ bytes32 _expectedZoneHash = bytes32(
+ keccak256(abi.encode(zoneParameters))
+ );
+
+ if (_expectedZoneHash != expectedZoneValidateCalldataHash) {
+ revert(
+ "Zone calldata hash does not match expected zone hash in validateOrder"
+ );
+ }
+
+ // Return the validOrderMagicValue.
+ return ZoneInterface.validateOrder.selector;
+ }
+
+ function setExpectedAuthorizeCalldataHash(
+ bytes32 _expectedZoneAuthorizeCalldataHash
+ ) public {
+ expectedZoneAuthorizeCalldataHash = _expectedZoneAuthorizeCalldataHash;
+ }
+
+ function setExpectedValidateCalldataHash(
+ bytes32 _expectedZoneValidateCalldataHash
+ ) public {
+ expectedZoneValidateCalldataHash = _expectedZoneValidateCalldataHash;
+ }
+
+ receive() external payable {}
+
+ function getSeaportMetadata()
+ external
+ pure
+ override(ZoneInterface)
+ returns (string memory name, Schema[] memory schemas)
+ {
+ // Return the metadata.
+ name = "TestCalldataHashContractOfferer";
+ schemas = new Schema[](1);
+ schemas[0].id = 1337;
+ schemas[0].metadata = new bytes(0);
+ }
+
+ /**
+ * @dev Enable accepting ERC1155 tokens via safeTransfer.
+ */
+ function onERC1155Received(
+ address,
+ address,
+ uint256,
+ uint256,
+ bytes calldata
+ ) external pure returns (bytes4) {
+ return this.onERC1155Received.selector;
+ }
+
+ function supportsInterface(
+ bytes4 interfaceId
+ ) public view virtual override(ZoneInterface) returns (bool) {
+ return interfaceId == type(ZoneInterface).interfaceId;
+ }
+}
diff --git a/test/foundry/zone/impl/PostFullfillmentStatefulTestZone.sol b/test/foundry/zone/impl/StatefulTestZone.sol
similarity index 75%
rename from test/foundry/zone/impl/PostFullfillmentStatefulTestZone.sol
rename to test/foundry/zone/impl/StatefulTestZone.sol
index f48cd0a11..d0d0fa0d3 100644
--- a/test/foundry/zone/impl/PostFullfillmentStatefulTestZone.sol
+++ b/test/foundry/zone/impl/StatefulTestZone.sol
@@ -2,8 +2,8 @@
pragma solidity ^0.8.17;
import {
- ZoneParameters,
- Schema
+ Schema,
+ ZoneParameters
} from "seaport-types/src/lib/ConsiderationStructs.sol";
import { ItemType } from "seaport-types/src/lib/ConsiderationEnums.sol";
@@ -12,7 +12,7 @@ import { ERC165 } from "@openzeppelin/contracts/utils/introspection/ERC165.sol";
import { ZoneInterface } from "seaport-types/src/interfaces/ZoneInterface.sol";
-contract PostFulfillmentStatefulTestZone is ERC165, ZoneInterface {
+contract StatefulTestZone is ERC165, ZoneInterface {
error IncorrectAmount(uint256 actual, uint256 expected);
error IncorrectItemType(ItemType actual, ItemType expected);
error IncorrectIdentifier(uint256 actual, uint256 expected);
@@ -23,7 +23,20 @@ contract PostFulfillmentStatefulTestZone is ERC165, ZoneInterface {
amountToCheck = amount;
}
- bool public called = false;
+ bool public authorizeCalled = false;
+ bool public validateCalled = false;
+
+ function authorizeOrder(
+ ZoneParameters calldata zoneParameters
+ ) public returns (bytes4) {
+ _checkZoneParameters(zoneParameters);
+
+ // Set the global called flag to true.
+ authorizeCalled = true;
+
+ // Return the authorizeOrder magic value.
+ return this.authorizeOrder.selector;
+ }
/**
* @dev Validates the order with the given `zoneParameters`. Called by
@@ -36,32 +49,10 @@ contract PostFulfillmentStatefulTestZone is ERC165, ZoneInterface {
function validateOrder(
ZoneParameters calldata zoneParameters
) external returns (bytes4 validOrderMagicValue) {
- // Check that the amount in the offer is correct.
- if (zoneParameters.offer[0].amount != amountToCheck) {
- revert IncorrectAmount(
- zoneParameters.offer[0].amount,
- amountToCheck
- );
- }
-
- // Check that the item type in the consideration is correct.
- if (zoneParameters.consideration[0].itemType != ItemType.ERC721) {
- revert IncorrectIdentifier(
- uint256(zoneParameters.consideration[0].itemType),
- uint256(ItemType.ERC721)
- );
- }
-
- // Check that the token ID in the consideration is correct.
- if (zoneParameters.consideration[0].identifier != 42) {
- revert IncorrectIdentifier(
- zoneParameters.consideration[0].identifier,
- 42
- );
- }
+ _checkZoneParameters(zoneParameters);
// Set the global called flag to true.
- called = true;
+ validateCalled = true;
// Return the validOrderMagicValue.
return ZoneInterface.validateOrder.selector;
@@ -83,7 +74,7 @@ contract PostFulfillmentStatefulTestZone is ERC165, ZoneInterface {
schemas[0].id = 3003;
schemas[0].metadata = new bytes(0);
- return ("PostFulfillmentStatefulTestZone", schemas);
+ return ("StatefulTestZone", schemas);
}
function supportsInterface(
@@ -93,4 +84,32 @@ contract PostFulfillmentStatefulTestZone is ERC165, ZoneInterface {
interfaceId == type(ZoneInterface).interfaceId ||
super.supportsInterface(interfaceId);
}
+
+ function _checkZoneParameters(
+ ZoneParameters calldata zoneParameters
+ ) internal view {
+ // Check that the amount in the offer is correct.
+ if (zoneParameters.offer[0].amount != amountToCheck) {
+ revert IncorrectAmount(
+ zoneParameters.offer[0].amount,
+ amountToCheck
+ );
+ }
+
+ // Check that the item type in the consideration is correct.
+ if (zoneParameters.consideration[0].itemType != ItemType.ERC721) {
+ revert IncorrectItemType(
+ zoneParameters.consideration[0].itemType,
+ ItemType.ERC721
+ );
+ }
+
+ // Check that the token ID in the consideration is correct.
+ if (zoneParameters.consideration[0].identifier != 42) {
+ revert IncorrectIdentifier(
+ zoneParameters.consideration[0].identifier,
+ 42
+ );
+ }
+ }
}
diff --git a/test/foundry/zone/impl/TestZone.sol b/test/foundry/zone/impl/TestZone.sol
index 72eff3683..50fda8a66 100644
--- a/test/foundry/zone/impl/TestZone.sol
+++ b/test/foundry/zone/impl/TestZone.sol
@@ -11,6 +11,12 @@ import { ERC165 } from "@openzeppelin/contracts/utils/introspection/ERC165.sol";
import { ZoneInterface } from "seaport-types/src/interfaces/ZoneInterface.sol";
contract TestZone is ERC165, ZoneInterface {
+ function authorizeOrder(
+ ZoneParameters calldata
+ ) public pure returns (bytes4) {
+ return this.authorizeOrder.selector;
+ }
+
// Called by Consideration whenever any extraData is provided by the caller.
function validateOrder(
ZoneParameters calldata
diff --git a/test/foundry/zone/impl/VerboseAuthZone.sol b/test/foundry/zone/impl/VerboseAuthZone.sol
new file mode 100644
index 000000000..0f64a73eb
--- /dev/null
+++ b/test/foundry/zone/impl/VerboseAuthZone.sol
@@ -0,0 +1,91 @@
+// SPDX-License-Identifier: MIT
+pragma solidity ^0.8.17;
+
+import {
+ Schema,
+ ZoneParameters
+} from "seaport-types/src/lib/ConsiderationStructs.sol";
+
+import { ERC165 } from "@openzeppelin/contracts/utils/introspection/ERC165.sol";
+
+import { ZoneInterface } from "seaport-types/src/interfaces/ZoneInterface.sol";
+
+contract VerboseAuthZone is ERC165, ZoneInterface {
+ // Create a mapping of orderHashes to authorized status.
+ mapping(bytes32 => bool) public orderIsAuthorized;
+
+ bool shouldReturnInvalidMagicValue;
+ bool shouldRevert;
+
+ event Authorized(bytes32 orderHash);
+
+ event AuthorizeOrderReverted(bytes32 orderHash);
+
+ event AuthorizeOrderNonMagicValue(bytes32 orderHash);
+
+ error OrderNotAuthorized();
+
+ constructor(bool _shouldReturnInvalidMagicValue, bool _shouldRevert) {
+ shouldReturnInvalidMagicValue = _shouldReturnInvalidMagicValue;
+ shouldRevert = _shouldRevert;
+ }
+
+ function setAuthorizationStatus(bytes32 orderHash, bool status) public {
+ orderIsAuthorized[orderHash] = status;
+ }
+
+ function authorizeOrder(
+ ZoneParameters calldata zoneParameters
+ ) public returns (bytes4) {
+ if (!orderIsAuthorized[zoneParameters.orderHash]) {
+ if (shouldReturnInvalidMagicValue) {
+ emit AuthorizeOrderNonMagicValue(zoneParameters.orderHash);
+
+ // Return the a value that is not the authorizeOrder magic
+ // value.
+ return bytes4(0x12345678);
+ }
+
+ if (shouldRevert) {
+ emit AuthorizeOrderReverted(zoneParameters.orderHash);
+ revert OrderNotAuthorized();
+ }
+ }
+
+ emit Authorized(zoneParameters.orderHash);
+
+ // Return the authorizeOrder magic value.
+ return this.authorizeOrder.selector;
+ }
+
+ function validateOrder(
+ ZoneParameters calldata /* zoneParameters */
+ ) external pure returns (bytes4 validOrderMagicValue) {
+ // Return the validOrderMagicValue.
+ return ZoneInterface.validateOrder.selector;
+ }
+
+ function getSeaportMetadata()
+ external
+ pure
+ override
+ returns (
+ string memory name,
+ Schema[] memory schemas // map to Seaport Improvement Proposal IDs
+ )
+ {
+ schemas = new Schema[](1);
+ schemas[0].id = 3003;
+ schemas[0].metadata = new bytes(0);
+
+ return ("VerboseAuthZone", schemas);
+ }
+
+ function supportsInterface(
+ bytes4 interfaceId
+ ) public view override(ERC165, ZoneInterface) returns (bool) {
+ return
+ interfaceId == type(ZoneInterface).interfaceId ||
+ super.supportsInterface(interfaceId);
+ }
+}
diff --git a/test/revert.spec.ts b/test/revert.spec.ts
index fd105e6b0..ef7a6e871 100644
--- a/test/revert.spec.ts
+++ b/test/revert.spec.ts
@@ -5629,7 +5629,7 @@ describe(`Reverts (Seaport v${VERSION})`, function () {
ethers.constants.AddressZero,
{
value,
- gasLimit: baseGas.add(74000),
+ gasLimit: baseGas.add(80000),
}
)
).to.be.revertedWithCustomError(
@@ -8168,7 +8168,7 @@ describe(`Reverts (Seaport v${VERSION})`, function () {
)
.withArgs(orderHash);
});
- it("Fulfillment reverts if contract offerer reverts", async () => {
+ it("Fulfillment bubbles up error if contract offerer reverts with data", async () => {
// Contract offerer mints nft
const nftId = await mint721(
offererContract,
@@ -8215,22 +8215,19 @@ describe(`Reverts (Seaport v${VERSION})`, function () {
order.denominator = 1;
order.signature = "0x";
- await expect(
- marketplaceContract
- .connect(buyer)
- .fulfillAdvancedOrder(
- order,
- [],
- toKey(0),
- ethers.constants.AddressZero,
- { value }
- )
- )
- .to.be.revertedWithCustomError(
- marketplaceContract,
- "InvalidContractOrder"
- )
- .withArgs(orderHash);
+ if (!process.env.REFERENCE) {
+ await expect(
+ marketplaceContract
+ .connect(buyer)
+ .fulfillAdvancedOrder(
+ order,
+ [],
+ toKey(0),
+ ethers.constants.AddressZero,
+ { value }
+ )
+ ).to.be.revertedWithCustomError(offererContract, "IntentionalRevert");
+ }
});
it("Fulfillment reverts if contract offerer returns with garbage data", async () => {
// Contract offerer mints nft
@@ -8398,9 +8395,10 @@ describe(`Reverts (Seaport v${VERSION})`, function () {
});
});
+ // TODO: Add this test back in
describe(`Changing chainId`, function () {
// Note: Run this test last in this file as it hacks changing the hre
- it("Reverts on changed chainId", async () => {
+ it.skip("Reverts on changed chainId", async () => {
const nftId = await mintAndApprove721(
seller,
marketplaceContract.address
diff --git a/test/utils/events.ts b/test/utils/events.ts
index d25b43277..aa2ac2d37 100644
--- a/test/utils/events.ts
+++ b/test/utils/events.ts
@@ -1,4 +1,5 @@
-import type { Contract, ContractTransaction } from "ethers";
+import type { ContractTransaction } from "ethers";
+import type { Interface } from "ethers/lib/utils";
type DecodedTransactionEvent = {
eventName: string;
@@ -7,7 +8,7 @@ type DecodedTransactionEvent = {
type EventDecoder = {
eventName: string;
- contract: Contract;
+ contract: { interface: Interface };
};
export async function decodeEvents(
diff --git a/test/utils/helpers.ts b/test/utils/helpers.ts
index 6941cb70c..90f522866 100644
--- a/test/utils/helpers.ts
+++ b/test/utils/helpers.ts
@@ -9,7 +9,7 @@ import type {
Order,
} from "./types";
-export const VERSION = `1.5${process.env.REFERENCE ? "-reference" : ""}`;
+export const VERSION = `1.6${process.env.REFERENCE ? "-reference" : ""}`;
export const minRandom = (min: ethers.BigNumberish) => randomBN(10).add(min);
diff --git a/test/zone.spec.ts b/test/zone.spec.ts
index 4d43217f8..c23dce06a 100644
--- a/test/zone.spec.ts
+++ b/test/zone.spec.ts
@@ -2,6 +2,14 @@ import { loadFixture } from "@nomicfoundation/hardhat-network-helpers";
import { expect } from "chai";
import { ethers, network } from "hardhat";
+import {
+ type ConduitInterface,
+ type ConsiderationInterface,
+ type TestERC721,
+ type TestZone,
+ PausableZoneEventsAndErrors__factory as pausableZoneFactory,
+} from "../typechain-types";
+
import { merkleTree } from "./utils/criteria";
import {
buildResolver,
@@ -18,17 +26,13 @@ import { faucet } from "./utils/faucet";
import { seaportFixture } from "./utils/fixtures";
import { VERSION } from "./utils/helpers";
-import type {
- ConduitInterface,
- ConsiderationInterface,
- TestERC721,
- TestZone,
-} from "../typechain-types";
import type { SeaportFixtures } from "./utils/fixtures";
import type { Contract, Wallet } from "ethers";
const { parseEther } = ethers.utils;
+const pausableZoneInterface = pausableZoneFactory.createInterface();
+
describe(`Zone - PausableZone (Seaport v${VERSION})`, function () {
const { provider } = ethers;
const owner = new ethers.Wallet(randomHex(32), provider);
@@ -605,7 +609,7 @@ describe(`Zone - PausableZone (Seaport v${VERSION})`, function () {
await createZone(pausableZoneController);
});
- it("Assign pauser and self destruct the zone", async () => {
+ it("Assign pauser", async () => {
const pausableZoneControllerFactory = await ethers.getContractFactory(
"PausableZoneController",
owner
@@ -622,12 +626,12 @@ describe(`Zone - PausableZone (Seaport v${VERSION})`, function () {
// Attach to zone
const zone = await zoneContract.attach(zoneAddr);
- // Try to nuke the zone through the deployer before being assigned pauser
+ // Try to pause the zone through the deployer before being assigned pauser
await expect(pausableZoneController.connect(buyer).pause(zoneAddr)).to.be
.reverted;
- // Try to nuke the zone directly before being assigned pauser
- await expect(zone.connect(buyer).pause(zoneAddr)).to.be.reverted;
+ // Try to pause the zone directly before being assigned pauser
+ await expect(zone.connect(buyer).pause()).to.be.reverted;
await expect(
pausableZoneController.connect(buyer).assignPauser(seller.address)
@@ -646,7 +650,7 @@ describe(`Zone - PausableZone (Seaport v${VERSION})`, function () {
// Check pauser owner
expect(await pausableZoneController.pauser()).to.equal(buyer.address);
- // Now as pauser, nuke the zone
+ // Now as pauser, pause the zone
const tx = await pausableZoneController.connect(buyer).pause(zoneAddr);
// Check paused event was emitted
@@ -679,7 +683,7 @@ describe(`Zone - PausableZone (Seaport v${VERSION})`, function () {
);
});
- it("Revert on an order with a pausable zone if zone has been self destructed", async () => {
+ it("Revert on an order with a pausable zone if zone has been paused", async () => {
const pausableZoneControllerFactory = await ethers.getContractFactory(
"PausableZoneController",
owner
@@ -710,20 +714,27 @@ describe(`Zone - PausableZone (Seaport v${VERSION})`, function () {
2
);
- // owner nukes the zone
- pausableZoneController.pause(zoneAddr);
+ // owner pauses the zone
+ const tx = await pausableZoneController.pause(zoneAddr);
+
+ const events = await decodeEvents(tx, [
+ { eventName: "Paused", contract: { interface: pausableZoneInterface } },
+ ]);
+ expect(events.length).to.be.equal(1);
+
+ const [pauseEvent] = events;
+ expect(pauseEvent.eventName).to.equal("Paused");
if (!process.env.REFERENCE) {
await expect(
marketplaceContract.connect(buyer).fulfillOrder(order, toKey(0), {
value,
})
- )
- .to.be.revertedWithCustomError(
- marketplaceContract,
- "InvalidRestrictedOrder"
- )
- .withArgs(orderHash);
+ ).to.be.revertedWithCustomError(
+ // eslint-disable-next-line camelcase
+ { interface: pausableZoneInterface },
+ "ZoneIsPaused"
+ );
} else {
await expect(
marketplaceContract.connect(buyer).fulfillOrder(order, toKey(0), {
@@ -744,7 +755,7 @@ describe(`Zone - PausableZone (Seaport v${VERSION})`, function () {
const zoneAddr = await createZone(pausableZoneController);
- // non owner tries to use pausable deployer to nuke the zone, reverts
+ // non owner tries to use pausable deployer to pause the zone, reverts
await expect(pausableZoneController.connect(buyer).pause(zoneAddr)).to.be
.reverted;
});
diff --git a/yarn.lock b/yarn.lock
index 6b1dca4e3..38b75590e 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -466,137 +466,95 @@
"@nodelib/fs.scandir" "2.1.5"
fastq "^1.6.0"
-"@nomicfoundation/ethereumjs-block@^4.0.0":
- version "4.0.0"
- resolved "https://registry.npmjs.org/@nomicfoundation/ethereumjs-block/-/ethereumjs-block-4.0.0.tgz"
- integrity sha512-bk8uP8VuexLgyIZAHExH1QEovqx0Lzhc9Ntm63nCRKLHXIZkobaFaeCVwTESV7YkPKUk7NiK11s8ryed4CS9yA==
- dependencies:
- "@nomicfoundation/ethereumjs-common" "^3.0.0"
- "@nomicfoundation/ethereumjs-rlp" "^4.0.0"
- "@nomicfoundation/ethereumjs-trie" "^5.0.0"
- "@nomicfoundation/ethereumjs-tx" "^4.0.0"
- "@nomicfoundation/ethereumjs-util" "^8.0.0"
- ethereum-cryptography "0.1.3"
+"@nomicfoundation/edr-darwin-arm64@0.2.1":
+ version "0.2.1"
+ resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-darwin-arm64/-/edr-darwin-arm64-0.2.1.tgz#10c1a07add192583ce8b2d4cc93439f52b390a41"
+ integrity sha512-aMYaRaZVQ/TmyNJIoXf1bU4k0zfinaL9Sy1day4yGlL6eiQPFfRGj9W6TZaZIoYG0XTx/mQWD7dkXJ7LdrleJA==
-"@nomicfoundation/ethereumjs-blockchain@^6.0.0":
- version "6.0.0"
- resolved "https://registry.npmjs.org/@nomicfoundation/ethereumjs-blockchain/-/ethereumjs-blockchain-6.0.0.tgz"
- integrity sha512-pLFEoea6MWd81QQYSReLlLfH7N9v7lH66JC/NMPN848ySPPQA5renWnE7wPByfQFzNrPBuDDRFFULMDmj1C0xw==
- dependencies:
- "@nomicfoundation/ethereumjs-block" "^4.0.0"
- "@nomicfoundation/ethereumjs-common" "^3.0.0"
- "@nomicfoundation/ethereumjs-ethash" "^2.0.0"
- "@nomicfoundation/ethereumjs-rlp" "^4.0.0"
- "@nomicfoundation/ethereumjs-trie" "^5.0.0"
- "@nomicfoundation/ethereumjs-util" "^8.0.0"
- abstract-level "^1.0.3"
- debug "^4.3.3"
- ethereum-cryptography "0.1.3"
- level "^8.0.0"
- lru-cache "^5.1.1"
- memory-level "^1.0.0"
+"@nomicfoundation/edr-darwin-x64@0.2.1":
+ version "0.2.1"
+ resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-darwin-x64/-/edr-darwin-x64-0.2.1.tgz#eaa29d2ba9f91ddb5f59b872c5a54f94a6fe3095"
+ integrity sha512-ma0SLcjHm5L3nPHcKFJB0jv/gKGSKaxr5Z65rurX/eaYUQJ7YGMsb8er9bSCo9rjzOtxf4FoPj3grL3zGpOj8A==
-"@nomicfoundation/ethereumjs-common@^3.0.0":
- version "3.0.0"
- resolved "https://registry.npmjs.org/@nomicfoundation/ethereumjs-common/-/ethereumjs-common-3.0.0.tgz"
- integrity sha512-WS7qSshQfxoZOpHG/XqlHEGRG1zmyjYrvmATvc4c62+gZXgre1ymYP8ZNgx/3FyZY0TWe9OjFlKOfLqmgOeYwA==
- dependencies:
- "@nomicfoundation/ethereumjs-util" "^8.0.0"
- crc-32 "^1.2.0"
+"@nomicfoundation/edr-linux-arm64-gnu@0.2.1":
+ version "0.2.1"
+ resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-linux-arm64-gnu/-/edr-linux-arm64-gnu-0.2.1.tgz#8149db0d742157405effe82d485ea9bfefddc795"
+ integrity sha512-NX3G4pBhRitWrjSGY3HTyCq3wKSm5YqrKVOCNQGl9/jcjSovqxlgzFMiTx4YZCzGntfJ/1om9AI84OWxYJjoDw==
-"@nomicfoundation/ethereumjs-ethash@^2.0.0":
- version "2.0.0"
- resolved "https://registry.npmjs.org/@nomicfoundation/ethereumjs-ethash/-/ethereumjs-ethash-2.0.0.tgz"
- integrity sha512-WpDvnRncfDUuXdsAXlI4lXbqUDOA+adYRQaEezIkxqDkc+LDyYDbd/xairmY98GnQzo1zIqsIL6GB5MoMSJDew==
- dependencies:
- "@nomicfoundation/ethereumjs-block" "^4.0.0"
- "@nomicfoundation/ethereumjs-rlp" "^4.0.0"
- "@nomicfoundation/ethereumjs-util" "^8.0.0"
- abstract-level "^1.0.3"
- bigint-crypto-utils "^3.0.23"
- ethereum-cryptography "0.1.3"
+"@nomicfoundation/edr-linux-arm64-musl@0.2.1":
+ version "0.2.1"
+ resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-linux-arm64-musl/-/edr-linux-arm64-musl-0.2.1.tgz#7d53afe5607eb406d199a199d00209a6304ff07b"
+ integrity sha512-gdQ3QHkt9XRkdtOGQ8fMwS11MXdjLeZgLrqoial4V4qtMaamIMMhVczK+VEvUhD8p7G4BVmp6kmkvcsthmndmw==
-"@nomicfoundation/ethereumjs-evm@^1.0.0":
- version "1.0.0"
- resolved "https://registry.npmjs.org/@nomicfoundation/ethereumjs-evm/-/ethereumjs-evm-1.0.0.tgz"
- integrity sha512-hVS6qRo3V1PLKCO210UfcEQHvlG7GqR8iFzp0yyjTg2TmJQizcChKgWo8KFsdMw6AyoLgLhHGHw4HdlP8a4i+Q==
- dependencies:
- "@nomicfoundation/ethereumjs-common" "^3.0.0"
- "@nomicfoundation/ethereumjs-util" "^8.0.0"
- "@types/async-eventemitter" "^0.2.1"
- async-eventemitter "^0.2.4"
- debug "^4.3.3"
- ethereum-cryptography "0.1.3"
- mcl-wasm "^0.7.1"
- rustbn.js "~0.2.0"
+"@nomicfoundation/edr-linux-x64-gnu@0.2.1":
+ version "0.2.1"
+ resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-linux-x64-gnu/-/edr-linux-x64-gnu-0.2.1.tgz#b762c95368fcb88bbbabba4d8be5380f38967413"
+ integrity sha512-OqabFY37vji6mYbLD9CvG28lja68czeVw58oWByIhFV3BpBu/cyP1oAbhzk3LieylujabS3Ekpvjw2Tkf0A9RQ==
-"@nomicfoundation/ethereumjs-rlp@^4.0.0", "@nomicfoundation/ethereumjs-rlp@^4.0.0-beta.2":
- version "4.0.0"
- resolved "https://registry.npmjs.org/@nomicfoundation/ethereumjs-rlp/-/ethereumjs-rlp-4.0.0.tgz"
- integrity sha512-GaSOGk5QbUk4eBP5qFbpXoZoZUj/NrW7MRa0tKY4Ew4c2HAS0GXArEMAamtFrkazp0BO4K5p2ZCG3b2FmbShmw==
+"@nomicfoundation/edr-linux-x64-musl@0.2.1":
+ version "0.2.1"
+ resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-linux-x64-musl/-/edr-linux-x64-musl-0.2.1.tgz#522448c42bff7d2abd52ddcf11ae6ca3dfdd6db4"
+ integrity sha512-vHfFFK2EPISuQUQge+bdjXamb0EUjfl8srYSog1qfiwyLwLeuSbpyyFzDeITAgPpkkFuedTfJW553K0Hipspyg==
-"@nomicfoundation/ethereumjs-statemanager@^1.0.0":
- version "1.0.0"
- resolved "https://registry.npmjs.org/@nomicfoundation/ethereumjs-statemanager/-/ethereumjs-statemanager-1.0.0.tgz"
- integrity sha512-jCtqFjcd2QejtuAMjQzbil/4NHf5aAWxUc+CvS0JclQpl+7M0bxMofR2AJdtz+P3u0ke2euhYREDiE7iSO31vQ==
- dependencies:
- "@nomicfoundation/ethereumjs-common" "^3.0.0"
- "@nomicfoundation/ethereumjs-rlp" "^4.0.0"
- "@nomicfoundation/ethereumjs-trie" "^5.0.0"
- "@nomicfoundation/ethereumjs-util" "^8.0.0"
- debug "^4.3.3"
- ethereum-cryptography "0.1.3"
- functional-red-black-tree "^1.0.1"
+"@nomicfoundation/edr-win32-arm64-msvc@0.2.1":
+ version "0.2.1"
+ resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-win32-arm64-msvc/-/edr-win32-arm64-msvc-0.2.1.tgz#ccfa443c274e49de93016a1060be810096dc6f1d"
+ integrity sha512-K/mui67RCKxghbSyvhvW3rvyVN1pa9M1Q9APUx1PtWjSSdXDFpqEY1NYsv2syb47Ca8ObJwVMF+LvnB6GvhUOQ==
-"@nomicfoundation/ethereumjs-trie@^5.0.0":
- version "5.0.0"
- resolved "https://registry.npmjs.org/@nomicfoundation/ethereumjs-trie/-/ethereumjs-trie-5.0.0.tgz"
- integrity sha512-LIj5XdE+s+t6WSuq/ttegJzZ1vliwg6wlb+Y9f4RlBpuK35B9K02bO7xU+E6Rgg9RGptkWd6TVLdedTI4eNc2A==
- dependencies:
- "@nomicfoundation/ethereumjs-rlp" "^4.0.0"
- "@nomicfoundation/ethereumjs-util" "^8.0.0"
- ethereum-cryptography "0.1.3"
- readable-stream "^3.6.0"
+"@nomicfoundation/edr-win32-ia32-msvc@0.2.1":
+ version "0.2.1"
+ resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-win32-ia32-msvc/-/edr-win32-ia32-msvc-0.2.1.tgz#822b19d3e67d6dcfa5394cb6a4d55d8bab1b2f26"
+ integrity sha512-HHK0mXEtjvfjJrJlqcYgQCy3lZIXS1KNl2GaP8bwEIuEwx++XxXs/ThLjPepM1nhCGICij8IGy7p3KrkzRelsw==
-"@nomicfoundation/ethereumjs-tx@^4.0.0":
- version "4.0.0"
- resolved "https://registry.npmjs.org/@nomicfoundation/ethereumjs-tx/-/ethereumjs-tx-4.0.0.tgz"
- integrity sha512-Gg3Lir2lNUck43Kp/3x6TfBNwcWC9Z1wYue9Nz3v4xjdcv6oDW9QSMJxqsKw9QEGoBBZ+gqwpW7+F05/rs/g1w==
- dependencies:
- "@nomicfoundation/ethereumjs-common" "^3.0.0"
- "@nomicfoundation/ethereumjs-rlp" "^4.0.0"
- "@nomicfoundation/ethereumjs-util" "^8.0.0"
- ethereum-cryptography "0.1.3"
+"@nomicfoundation/edr-win32-x64-msvc@0.2.1":
+ version "0.2.1"
+ resolved "https://registry.yarnpkg.com/@nomicfoundation/edr-win32-x64-msvc/-/edr-win32-x64-msvc-0.2.1.tgz#7b56ff742b2724779cc9f3385815b394f76de8df"
+ integrity sha512-FY4eQJdj1/y8ST0RyQycx63yr+lvdYNnUkzgWf4X+vPH1lOhXae+L2NDcNCQlTDAfQcD6yz0bkBUkLrlJ8pTww==
-"@nomicfoundation/ethereumjs-util@^8.0.0":
- version "8.0.0"
- resolved "https://registry.npmjs.org/@nomicfoundation/ethereumjs-util/-/ethereumjs-util-8.0.0.tgz"
- integrity sha512-2emi0NJ/HmTG+CGY58fa+DQuAoroFeSH9gKu9O6JnwTtlzJtgfTixuoOqLEgyyzZVvwfIpRueuePb8TonL1y+A==
- dependencies:
- "@nomicfoundation/ethereumjs-rlp" "^4.0.0-beta.2"
+"@nomicfoundation/edr@^0.2.0":
+ version "0.2.1"
+ resolved "https://registry.yarnpkg.com/@nomicfoundation/edr/-/edr-0.2.1.tgz#a3d2a542dcd5dc5a8d757116d52baea05f370531"
+ integrity sha512-Dleau3ItHJh2n85G2J6AIPBoLgu/mOWkmrh26z3VsJE2tp/e00hUk/dqz85ncsVcBYEc6/YOn/DomWu0wSF9tQ==
+ optionalDependencies:
+ "@nomicfoundation/edr-darwin-arm64" "0.2.1"
+ "@nomicfoundation/edr-darwin-x64" "0.2.1"
+ "@nomicfoundation/edr-linux-arm64-gnu" "0.2.1"
+ "@nomicfoundation/edr-linux-arm64-musl" "0.2.1"
+ "@nomicfoundation/edr-linux-x64-gnu" "0.2.1"
+ "@nomicfoundation/edr-linux-x64-musl" "0.2.1"
+ "@nomicfoundation/edr-win32-arm64-msvc" "0.2.1"
+ "@nomicfoundation/edr-win32-ia32-msvc" "0.2.1"
+ "@nomicfoundation/edr-win32-x64-msvc" "0.2.1"
+
+"@nomicfoundation/ethereumjs-common@4.0.4":
+ version "4.0.4"
+ resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-common/-/ethereumjs-common-4.0.4.tgz#9901f513af2d4802da87c66d6f255b510bef5acb"
+ integrity sha512-9Rgb658lcWsjiicr5GzNCjI1llow/7r0k50dLL95OJ+6iZJcVbi15r3Y0xh2cIO+zgX0WIHcbzIu6FeQf9KPrg==
+ dependencies:
+ "@nomicfoundation/ethereumjs-util" "9.0.4"
+
+"@nomicfoundation/ethereumjs-rlp@5.0.4":
+ version "5.0.4"
+ resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-rlp/-/ethereumjs-rlp-5.0.4.tgz#66c95256fc3c909f6fb18f6a586475fc9762fa30"
+ integrity sha512-8H1S3s8F6QueOc/X92SdrA4RDenpiAEqMg5vJH99kcQaCy/a3Q6fgseo75mgWlbanGJXSlAPtnCeG9jvfTYXlw==
+
+"@nomicfoundation/ethereumjs-tx@5.0.4":
+ version "5.0.4"
+ resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-tx/-/ethereumjs-tx-5.0.4.tgz#b0ceb58c98cc34367d40a30d255d6315b2f456da"
+ integrity sha512-Xjv8wAKJGMrP1f0n2PeyfFCCojHd7iS3s/Ab7qzF1S64kxZ8Z22LCMynArYsVqiFx6rzYy548HNVEyI+AYN/kw==
+ dependencies:
+ "@nomicfoundation/ethereumjs-common" "4.0.4"
+ "@nomicfoundation/ethereumjs-rlp" "5.0.4"
+ "@nomicfoundation/ethereumjs-util" "9.0.4"
ethereum-cryptography "0.1.3"
-"@nomicfoundation/ethereumjs-vm@^6.0.0":
- version "6.0.0"
- resolved "https://registry.npmjs.org/@nomicfoundation/ethereumjs-vm/-/ethereumjs-vm-6.0.0.tgz"
- integrity sha512-JMPxvPQ3fzD063Sg3Tp+UdwUkVxMoo1uML6KSzFhMH3hoQi/LMuXBoEHAoW83/vyNS9BxEe6jm6LmT5xdeEJ6w==
- dependencies:
- "@nomicfoundation/ethereumjs-block" "^4.0.0"
- "@nomicfoundation/ethereumjs-blockchain" "^6.0.0"
- "@nomicfoundation/ethereumjs-common" "^3.0.0"
- "@nomicfoundation/ethereumjs-evm" "^1.0.0"
- "@nomicfoundation/ethereumjs-rlp" "^4.0.0"
- "@nomicfoundation/ethereumjs-statemanager" "^1.0.0"
- "@nomicfoundation/ethereumjs-trie" "^5.0.0"
- "@nomicfoundation/ethereumjs-tx" "^4.0.0"
- "@nomicfoundation/ethereumjs-util" "^8.0.0"
- "@types/async-eventemitter" "^0.2.1"
- async-eventemitter "^0.2.4"
- debug "^4.3.3"
+"@nomicfoundation/ethereumjs-util@9.0.4":
+ version "9.0.4"
+ resolved "https://registry.yarnpkg.com/@nomicfoundation/ethereumjs-util/-/ethereumjs-util-9.0.4.tgz#84c5274e82018b154244c877b76bc049a4ed7b38"
+ integrity sha512-sLOzjnSrlx9Bb9EFNtHzK/FJFsfg2re6bsGqinFinH1gCqVfz9YYlXiMWwDM4C/L4ywuHFCYwfKTVr/QHQcU0Q==
+ dependencies:
+ "@nomicfoundation/ethereumjs-rlp" "5.0.4"
ethereum-cryptography "0.1.3"
- functional-red-black-tree "^1.0.1"
- mcl-wasm "^0.7.1"
- rustbn.js "~0.2.0"
"@nomicfoundation/hardhat-chai-matchers@^1.0.5":
version "1.0.5"
@@ -704,10 +662,10 @@
table "^6.8.0"
undici "^5.4.0"
-"@openzeppelin/contracts@^4.9.2":
- version "4.9.2"
- resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-4.9.2.tgz#1cb2d5e4d3360141a17dbc45094a8cad6aac16c1"
- integrity sha512-mO+y6JaqXjWeMh9glYVzVu8HYPGknAAnWyxTRhGeckOruyXQMNnlcW6w/Dx9ftLeIQk6N+ZJFuVmTwF7lEIFrg==
+"@openzeppelin/contracts@^4.9.6":
+ version "4.9.6"
+ resolved "https://registry.yarnpkg.com/@openzeppelin/contracts/-/contracts-4.9.6.tgz#2a880a24eb19b4f8b25adc2a5095f2aa27f39677"
+ integrity sha512-xSmezSupL+y9VkHZJGDoCBpmnB2ogM13ccaYDWqJTfS3dbuHkgjuwDFUmaFauBCboQMGB/S5UqUl2y54X99BmA==
"@rari-capital/solmate@^6.2.0":
version "6.4.0"
@@ -816,6 +774,11 @@
dependencies:
antlr4ts "^0.5.0-alpha.4"
+"@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@^5.0.1":
version "5.0.1"
resolved "https://registry.yarnpkg.com/@szmarczak/http-timer/-/http-timer-5.0.1.tgz#c7c1bf1141cdd4751b0399c8fc7b8b664cd5be3a"
@@ -858,11 +821,6 @@
dependencies:
fs-extra "^9.1.0"
-"@types/async-eventemitter@^0.2.1":
- version "0.2.1"
- resolved "https://registry.npmjs.org/@types/async-eventemitter/-/async-eventemitter-0.2.1.tgz"
- integrity sha512-M2P4Ng26QbAeITiH7w1d7OxtldgfAe0wobpyJzVK/XOb0cUGKU2R4pfAhqcJBXAe2ife5ZOhSv4wk7p+ffURtg==
-
"@types/bn.js@^4.11.3":
version "4.11.6"
resolved "https://registry.npmjs.org/@types/bn.js/-/bn.js-4.11.6.tgz"
@@ -1078,26 +1036,6 @@ abbrev@1, abbrev@1.0.x:
resolved "https://registry.npmjs.org/abbrev/-/abbrev-1.0.9.tgz"
integrity sha512-LEyx4aLEC3x6T0UguF6YILf+ntvmOaWsVfENmIW0E9H09vKlLDGelMjjSm0jkDHALj8A8quZ/HapKNigzwge+Q==
-abort-controller@^3.0.0:
- version "3.0.0"
- resolved "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz"
- integrity sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==
- dependencies:
- event-target-shim "^5.0.0"
-
-abstract-level@^1.0.0, abstract-level@^1.0.2, abstract-level@^1.0.3:
- version "1.0.3"
- resolved "https://registry.npmjs.org/abstract-level/-/abstract-level-1.0.3.tgz"
- integrity sha512-t6jv+xHy+VYwc4xqZMn2Pa9DjcdzvzZmQGRjTFc8spIbRGHgBrEKbPq+rYXc7CCo0lxgYvSgKVg9qZAhpVQSjA==
- dependencies:
- buffer "^6.0.3"
- catering "^2.1.0"
- is-buffer "^2.0.5"
- level-supports "^4.0.0"
- level-transcoder "^1.0.1"
- module-error "^1.0.1"
- queue-microtask "^1.2.3"
-
acorn-jsx@^5.0.0, acorn-jsx@^5.3.2:
version "5.3.2"
resolved "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz"
@@ -1118,11 +1056,6 @@ acorn@^8.4.1, acorn@^8.8.0:
resolved "https://registry.npmjs.org/acorn/-/acorn-8.8.1.tgz"
integrity sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA==
-address@^1.0.1:
- version "1.2.1"
- resolved "https://registry.npmjs.org/address/-/address-1.2.1.tgz"
- integrity sha512-B+6bi5D34+fDYENiH5qOlA0cV2rAGKuWZ9LeyUUehbXy8e0VS9e498yO0Jeeh+iM+6KbfudHTFjXw2MmJD4QRA==
-
adm-zip@^0.4.16:
version "0.4.16"
resolved "https://registry.npmjs.org/adm-zip/-/adm-zip-0.4.16.tgz"
@@ -1173,6 +1106,13 @@ amdefine@>=0.0.4:
resolved "https://registry.npmjs.org/amdefine/-/amdefine-1.0.1.tgz"
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@3.2.3:
version "3.2.3"
resolved "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.3.tgz"
@@ -1363,14 +1303,7 @@ astral-regex@^2.0.0:
resolved "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz"
integrity sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==
-async-eventemitter@^0.2.4:
- version "0.2.4"
- resolved "https://registry.npmjs.org/async-eventemitter/-/async-eventemitter-0.2.4.tgz"
- integrity sha512-pd20BwL7Yt1zwDFy+8MX8F1+WCT8aQeKj0kQnTrH9WaeRETlRamVhD0JtRPmrV4GfOJ2F9CvdQkZeZhnh2TuHw==
- dependencies:
- async "^2.4.0"
-
-async@1.x, async@>=2.6.4, async@^2.4.0:
+async@1.x, async@>=2.6.4:
version "3.2.4"
resolved "https://registry.yarnpkg.com/async/-/async-3.2.4.tgz#2d22e00f8cddeb5fde5dd33522b56d1cf569a81c"
integrity sha512-iAB+JbDEGXhyIUavoDl9WP/Jj106Kz9DEn1DPgYw5ruDn0e3Wgi3sKFm55sASdGBNOQB8F59d9qQ7deqrHA8wQ==
@@ -1407,11 +1340,6 @@ base-x@^3.0.2:
dependencies:
safe-buffer "^5.0.1"
-base64-js@^1.3.1:
- version "1.5.1"
- resolved "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz"
- integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==
-
bcrypt-pbkdf@^1.0.0:
version "1.0.2"
resolved "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz"
@@ -1424,18 +1352,6 @@ bech32@1.1.4:
resolved "https://registry.npmjs.org/bech32/-/bech32-1.1.4.tgz"
integrity sha512-s0IrSOzLlbvX7yp4WBfPITzpAU8sqQcpsmwXDiKwrG4r491vwCO/XpejasRNl0piBMe/DvP4Tz0mIS/X1DPJBQ==
-bigint-crypto-utils@^3.0.23:
- version "3.1.7"
- resolved "https://registry.npmjs.org/bigint-crypto-utils/-/bigint-crypto-utils-3.1.7.tgz"
- integrity sha512-zpCQpIE2Oy5WIQpjC9iYZf8Uh9QqoS51ZCooAcNvzv1AQ3VWdT52D0ksr1+/faeK8HVIej1bxXcP75YcqH3KPA==
- dependencies:
- bigint-mod-arith "^3.1.0"
-
-bigint-mod-arith@^3.1.0:
- version "3.1.2"
- resolved "https://registry.npmjs.org/bigint-mod-arith/-/bigint-mod-arith-3.1.2.tgz"
- integrity sha512-nx8J8bBeiRR+NlsROFH9jHswW5HO8mgfOSqW0AmjicMMvaONDa8AO+5ViKDUUNytBPWiwfvZP4/Bj4Y3lUfvgQ==
-
bignumber.js@^9.0.1:
version "9.1.1"
resolved "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.1.1.tgz"
@@ -1466,6 +1382,20 @@ bn.js@^5.1.2, bn.js@^5.2.0, bn.js@^5.2.1:
resolved "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz"
integrity sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==
+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@^2.0.1:
version "2.0.1"
resolved "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz"
@@ -1485,16 +1415,6 @@ brorand@^1.1.0:
resolved "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz"
integrity sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==
-browser-level@^1.0.1:
- version "1.0.1"
- resolved "https://registry.npmjs.org/browser-level/-/browser-level-1.0.1.tgz"
- integrity sha512-XECYKJ+Dbzw0lbydyQuJzwNXtOpbMSq737qxJN11sIRTErOMShvDpbzTlgju7orJKvx4epULolZAuJGLzCmWRQ==
- dependencies:
- abstract-level "^1.0.2"
- catering "^2.1.1"
- module-error "^1.0.2"
- run-parallel-limit "^1.1.0"
-
browser-stdout@1.3.1:
version "1.3.1"
resolved "https://registry.npmjs.org/browser-stdout/-/browser-stdout-1.3.1.tgz"
@@ -1543,14 +1463,6 @@ buffer-xor@^1.0.3:
resolved "https://registry.yarnpkg.com/buffer-xor/-/buffer-xor-1.0.3.tgz#26e61ed1422fb70dd42e6e36729ed51d855fe8d9"
integrity sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==
-buffer@^6.0.3:
- version "6.0.3"
- resolved "https://registry.yarnpkg.com/buffer/-/buffer-6.0.3.tgz#2ace578459cc8fbe2a70aaa8f52ee63b6a74c6c6"
- integrity sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==
- dependencies:
- base64-js "^1.3.1"
- ieee754 "^1.2.1"
-
builtins@^5.0.1:
version "5.0.1"
resolved "https://registry.npmjs.org/builtins/-/builtins-5.0.1.tgz"
@@ -1558,13 +1470,6 @@ builtins@^5.0.1:
dependencies:
semver "^7.0.0"
-busboy@^1.6.0:
- version "1.6.0"
- resolved "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz"
- integrity sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==
- dependencies:
- streamsearch "^1.1.0"
-
bytes@3.1.2:
version "3.1.2"
resolved "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz"
@@ -1620,7 +1525,7 @@ callsites@^3.0.0:
resolved "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz"
integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==
-camelcase@^6.0.0:
+camelcase@^6.0.0, camelcase@^6.2.0:
version "6.3.0"
resolved "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz"
integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==
@@ -1630,11 +1535,6 @@ caseless@^0.12.0, caseless@~0.12.0:
resolved "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz"
integrity sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==
-catering@^2.1.0, catering@^2.1.1:
- version "2.1.1"
- resolved "https://registry.npmjs.org/catering/-/catering-2.1.1.tgz"
- integrity sha512-K7Qy8O9p76sL3/3m7/zLKbRkyOlSZAgzEaLhyj2mXS8PsCud2Eo4hAb8aLtZqHh0QGqLcb9dlJSu6lHRVENm1w==
-
cbor@^8.1.0:
version "8.1.0"
resolved "https://registry.npmjs.org/cbor/-/cbor-8.1.0.tgz"
@@ -1742,17 +1642,6 @@ cipher-base@^1.0.0, cipher-base@^1.0.1, cipher-base@^1.0.3:
inherits "^2.0.1"
safe-buffer "^5.0.1"
-classic-level@^1.2.0:
- version "1.2.0"
- resolved "https://registry.npmjs.org/classic-level/-/classic-level-1.2.0.tgz"
- integrity sha512-qw5B31ANxSluWz9xBzklRWTUAJ1SXIdaVKTVS7HcTGKOAmExx65Wo5BUICW+YGORe2FOUaDghoI9ZDxj82QcFg==
- dependencies:
- abstract-level "^1.0.2"
- catering "^2.1.0"
- module-error "^1.0.1"
- napi-macros "~2.0.0"
- node-gyp-build "^4.3.0"
-
clean-stack@^2.0.0:
version "2.2.0"
resolved "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz"
@@ -1769,6 +1658,11 @@ cli-barchart@^0.2.3:
string-width "^4.2.3"
term-size "^2.2.1"
+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-cursor@^2.1.0:
version "2.1.0"
resolved "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz"
@@ -1948,11 +1842,6 @@ cosmiconfig@^5.0.7:
js-yaml "^3.13.1"
parse-json "^4.0.0"
-crc-32@^1.2.0:
- version "1.2.2"
- resolved "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz"
- integrity sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==
-
create-hash@^1.1.0, create-hash@^1.1.2, create-hash@^1.2.0:
version "1.2.0"
resolved "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz"
@@ -2042,7 +1931,7 @@ debug@3.2.6:
dependencies:
ms "^2.1.1"
-debug@4, debug@4.3.4, debug@^4.0.1, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.3, debug@^4.3.4:
+debug@4, debug@4.3.4, debug@^4.0.1, debug@^4.1.1, debug@^4.3.1, debug@^4.3.2, debug@^4.3.4:
version "4.3.4"
resolved "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz"
integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==
@@ -2115,14 +2004,6 @@ depd@2.0.0:
resolved "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz"
integrity sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==
-detect-port@^1.3.0:
- version "1.5.1"
- resolved "https://registry.npmjs.org/detect-port/-/detect-port-1.5.1.tgz"
- integrity sha512-aBzdj76lueB6uUst5iAs7+0H/oOjqI5D16XUWxlWMIMROhcM0rfsNVk93zTngq1dDNpoXRr++Sus7ETAExppAQ==
- dependencies:
- address "^1.0.1"
- debug "4"
-
diff@3.5.0:
version "3.5.0"
resolved "https://registry.npmjs.org/diff/-/diff-3.5.0.tgz"
@@ -2764,11 +2645,6 @@ ethjs-util@0.1.6, ethjs-util@^0.1.6:
is-hex-prefixed "1.0.0"
strip-hex-prefix "1.0.0"
-event-target-shim@^5.0.0:
- version "5.0.1"
- resolved "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz"
- integrity sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==
-
evp_bytestokey@^1.0.3:
version "1.0.3"
resolved "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz"
@@ -2947,9 +2823,9 @@ flatted@^3.1.0:
integrity sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==
follow-redirects@^1.12.1:
- version "1.15.2"
- resolved "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz"
- integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==
+ version "1.15.6"
+ resolved "https://registry.yarnpkg.com/follow-redirects/-/follow-redirects-1.15.6.tgz#7f815c0cda4249c74ff09e95ef97c23b5fd0399b"
+ integrity sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==
forever-agent@~0.6.1:
version "0.6.1"
@@ -3079,9 +2955,9 @@ get-caller-file@^2.0.1, get-caller-file@^2.0.5:
integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==
get-func-name@^2.0.0:
- version "2.0.0"
- resolved "https://registry.npmjs.org/get-func-name/-/get-func-name-2.0.0.tgz"
- integrity sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig==
+ version "2.0.2"
+ resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.2.tgz#0d7cf20cd13fda808669ffa88f4ffc7a3943fc41"
+ integrity sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ==
get-intrinsic@^1.0.2, get-intrinsic@^1.1.0, get-intrinsic@^1.1.1, get-intrinsic@^1.1.3:
version "1.1.3"
@@ -3175,6 +3051,17 @@ glob@7.2.0, glob@^7.0.0, glob@^7.1.2, glob@^7.1.3:
once "^1.3.0"
path-is-absolute "^1.0.0"
+glob@8.1.0:
+ version "8.1.0"
+ resolved "https://registry.yarnpkg.com/glob/-/glob-8.1.0.tgz#d388f656593ef708ee3e34640fdfb99a9fd1c33e"
+ integrity sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==
+ dependencies:
+ fs.realpath "^1.0.0"
+ inflight "^1.0.4"
+ inherits "2"
+ minimatch "^5.0.1"
+ once "^1.3.0"
+
glob@^5.0.15:
version "5.0.15"
resolved "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz"
@@ -3306,31 +3193,25 @@ hardhat-gas-reporter@^1.0.7:
eth-gas-reporter "^0.2.25"
sha1 "^1.1.1"
-hardhat@^2.12.1-ir.0:
- version "2.12.1-ir.0"
- resolved "https://registry.yarnpkg.com/hardhat/-/hardhat-2.12.1-ir.0.tgz#4972a0777e5806cce6b54cf258c52570c58d141a"
- integrity sha512-z5TGBaf3tpY92zcDmifPyYdQa1EGuLAcOlmqQUd0wR93Yua8UCdNyZHk+P2PNBJK4sm/DYt5d3DJbaFMN24sog==
+hardhat@^2.21.0:
+ version "2.21.0"
+ resolved "https://registry.yarnpkg.com/hardhat/-/hardhat-2.21.0.tgz#2e23126310a6c77cd7e149e6af1dd67626b7a74f"
+ integrity sha512-8DlJAVJDEVHaV1sh9FLuKLLgCFv9EAJ+M+8IbjSIPgoeNo3ss5L1HgGBMfnI88c7OzMEZkdcuyGoobFeK3Orqw==
dependencies:
"@ethersproject/abi" "^5.1.2"
"@metamask/eth-sig-util" "^4.0.0"
- "@nomicfoundation/ethereumjs-block" "^4.0.0"
- "@nomicfoundation/ethereumjs-blockchain" "^6.0.0"
- "@nomicfoundation/ethereumjs-common" "^3.0.0"
- "@nomicfoundation/ethereumjs-evm" "^1.0.0"
- "@nomicfoundation/ethereumjs-rlp" "^4.0.0"
- "@nomicfoundation/ethereumjs-statemanager" "^1.0.0"
- "@nomicfoundation/ethereumjs-trie" "^5.0.0"
- "@nomicfoundation/ethereumjs-tx" "^4.0.0"
- "@nomicfoundation/ethereumjs-util" "^8.0.0"
- "@nomicfoundation/ethereumjs-vm" "^6.0.0"
+ "@nomicfoundation/edr" "^0.2.0"
+ "@nomicfoundation/ethereumjs-common" "4.0.4"
+ "@nomicfoundation/ethereumjs-tx" "5.0.4"
+ "@nomicfoundation/ethereumjs-util" "9.0.4"
"@nomicfoundation/solidity-analyzer" "^0.1.0"
"@sentry/node" "^5.18.1"
"@types/bn.js" "^5.1.0"
"@types/lru-cache" "^5.1.0"
- abort-controller "^3.0.0"
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"
@@ -3350,7 +3231,6 @@ hardhat@^2.12.1-ir.0:
mnemonist "^0.38.0"
mocha "^10.0.0"
p-map "^4.0.0"
- qs "^6.7.0"
raw-body "^2.4.1"
resolve "1.17.0"
semver "^6.3.0"
@@ -3358,7 +3238,7 @@ hardhat@^2.12.1-ir.0:
source-map-support "^0.5.13"
stacktrace-parser "^0.1.10"
tsort "0.0.1"
- undici "^5.4.0"
+ undici "^5.14.0"
uuid "^8.3.2"
ws "^7.4.6"
@@ -3527,11 +3407,6 @@ iconv-lite@0.4.24, iconv-lite@^0.4.24:
dependencies:
safer-buffer ">= 2.1.2 < 3"
-ieee754@^1.2.1:
- version "1.2.1"
- resolved "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz"
- integrity sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==
-
ignore@^4.0.6:
version "4.0.6"
resolved "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz"
@@ -3663,11 +3538,6 @@ is-buffer@^1.1.5:
resolved "https://registry.yarnpkg.com/is-buffer/-/is-buffer-1.1.6.tgz#efaa2ea9daa0d7ab2ea13a97b2b8ad51fefbe8be"
integrity sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==
-is-buffer@^2.0.5:
- version "2.0.5"
- resolved "https://registry.npmjs.org/is-buffer/-/is-buffer-2.0.5.tgz"
- integrity sha512-i2R6zNFDwgEHJyQUtJEk0XFi1i0dPFn/oqjK3/vPCcDeJvW5NQ83V8QbicfF1SupOaB0h8ntgBC2YiE7dfyctQ==
-
is-callable@^1.1.4, is-callable@^1.2.7:
version "1.2.7"
resolved "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz"
@@ -3999,27 +3869,6 @@ klaw@^1.0.0:
optionalDependencies:
graceful-fs "^4.1.9"
-level-supports@^4.0.0:
- version "4.0.1"
- resolved "https://registry.npmjs.org/level-supports/-/level-supports-4.0.1.tgz"
- integrity sha512-PbXpve8rKeNcZ9C1mUicC9auIYFyGpkV9/i6g76tLgANwWhtG2v7I4xNBUlkn3lE2/dZF3Pi0ygYGtLc4RXXdA==
-
-level-transcoder@^1.0.1:
- version "1.0.1"
- resolved "https://registry.npmjs.org/level-transcoder/-/level-transcoder-1.0.1.tgz"
- integrity sha512-t7bFwFtsQeD8cl8NIoQ2iwxA0CL/9IFw7/9gAjOonH0PWTTiRfY7Hq+Ejbsxh86tXobDQ6IOiddjNYIfOBs06w==
- dependencies:
- buffer "^6.0.3"
- module-error "^1.0.1"
-
-level@^8.0.0:
- version "8.0.0"
- resolved "https://registry.npmjs.org/level/-/level-8.0.0.tgz"
- integrity sha512-ypf0jjAk2BWI33yzEaaotpq7fkOPALKAgDBxggO6Q9HGX2MRXn0wbP1Jn/tJv1gtL867+YOjOB49WaUF3UoJNQ==
- dependencies:
- browser-level "^1.0.1"
- classic-level "^1.2.0"
-
levn@^0.3.0, levn@~0.3.0:
version "0.3.0"
resolved "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz"
@@ -4154,13 +4003,6 @@ lowercase-keys@^3.0.0:
resolved "https://registry.yarnpkg.com/lowercase-keys/-/lowercase-keys-3.0.0.tgz#c5e7d442e37ead247ae9db117a9d0a467c89d4f2"
integrity sha512-ozCC6gdQ+glXOQsveKD0YsDy8DSQFjDTz4zyzEHNV5+JP5D62LmfDZ6o1cycFx9ouG940M5dE8C8CTewdj2YWQ==
-lru-cache@^5.1.1:
- version "5.1.1"
- resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz"
- integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==
- dependencies:
- yallist "^3.0.2"
-
lru-cache@^6.0.0:
version "6.0.0"
resolved "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz"
@@ -4183,11 +4025,6 @@ markdown-table@^1.1.3:
resolved "https://registry.npmjs.org/markdown-table/-/markdown-table-1.1.3.tgz"
integrity sha512-1RUZVgQlpJSPWYbFSpmudq5nHY1doEIv89gBtF0s4gW1GF2XorxcA/70M5vq7rLv0a6mhOUccRsqkwhwLCIQ2Q==
-mcl-wasm@^0.7.1:
- version "0.7.9"
- resolved "https://registry.npmjs.org/mcl-wasm/-/mcl-wasm-0.7.9.tgz"
- integrity sha512-iJIUcQWA88IJB/5L15GnJVnSQJmf/YaxxV6zRavv83HILHaJQb6y0iFyDMdDO0gN8X37tdxmAOrH/P8B6RB8sQ==
-
md5.js@^1.3.4:
version "1.3.5"
resolved "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz"
@@ -4197,15 +4034,6 @@ md5.js@^1.3.4:
inherits "^2.0.1"
safe-buffer "^5.1.2"
-memory-level@^1.0.0:
- version "1.0.0"
- resolved "https://registry.npmjs.org/memory-level/-/memory-level-1.0.0.tgz"
- integrity sha512-UXzwewuWeHBz5krr7EvehKcmLFNoXxGcvuYhC41tRnkrTbJohtS7kVn9akmgirtRygg+f7Yjsfi8Uu5SGSQ4Og==
- dependencies:
- abstract-level "^1.0.0"
- functional-red-black-tree "^1.0.1"
- module-error "^1.0.1"
-
memorystream@^0.3.1:
version "0.3.1"
resolved "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz"
@@ -4287,7 +4115,7 @@ minimalistic-crypto-utils@^1.0.1:
resolved "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz"
integrity sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==
-"minimatch@2 || 3", minimatch@3.0.4, minimatch@5.0.1, minimatch@>=3.0.5, minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.2:
+"minimatch@2 || 3", minimatch@3.0.4, minimatch@5.0.1, minimatch@>=3.0.5, minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.2, minimatch@^5.0.1:
version "7.4.2"
resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-7.4.2.tgz#157e847d79ca671054253b840656720cb733f10f"
integrity sha512-xy4q7wou3vUoC9k1xGTXc+awNdGaGVHtFUaey8tiX4H1QRc04DZ/rmDFwNm2EBsuYEhAZ6SgMmYf3InGY6OauA==
@@ -4345,36 +4173,6 @@ mnemonist@^0.38.0:
dependencies:
obliterator "^2.0.0"
-mocha@7.1.2:
- version "7.1.2"
- resolved "https://registry.npmjs.org/mocha/-/mocha-7.1.2.tgz"
- integrity sha512-o96kdRKMKI3E8U0bjnfqW4QMk12MwZ4mhdBTf+B5a1q9+aq2HRnj+3ZdJu0B/ZhJeK78MgYuv6L8d/rA5AeBJA==
- dependencies:
- ansi-colors "3.2.3"
- browser-stdout "1.3.1"
- chokidar "3.3.0"
- debug "3.2.6"
- diff "3.5.0"
- escape-string-regexp "1.0.5"
- find-up "3.0.0"
- glob "7.1.3"
- growl "1.10.5"
- he "1.2.0"
- js-yaml "3.13.1"
- log-symbols "3.0.0"
- minimatch "3.0.4"
- mkdirp "0.5.5"
- ms "2.1.1"
- node-environment-flags "1.0.6"
- object.assign "4.1.0"
- strip-json-comments "2.0.1"
- supports-color "6.0.0"
- which "1.3.1"
- wide-align "1.1.3"
- yargs "13.3.2"
- yargs-parser "13.1.2"
- yargs-unparser "1.6.0"
-
mocha@^10.0.0:
version "10.1.0"
resolved "https://registry.npmjs.org/mocha/-/mocha-10.1.0.tgz"
@@ -4402,6 +4200,32 @@ mocha@^10.0.0:
yargs-parser "20.2.4"
yargs-unparser "2.0.0"
+mocha@^10.2.0:
+ version "10.3.0"
+ resolved "https://registry.yarnpkg.com/mocha/-/mocha-10.3.0.tgz#0e185c49e6dccf582035c05fa91084a4ff6e3fe9"
+ integrity sha512-uF2XJs+7xSLsrmIvn37i/wnc91nw7XjOQB8ccyx5aEgdnohr7n+rEiZP23WkCYHjilR6+EboEnbq/ZQDz4LSbg==
+ dependencies:
+ ansi-colors "4.1.1"
+ browser-stdout "1.3.1"
+ chokidar "3.5.3"
+ debug "4.3.4"
+ diff "5.0.0"
+ escape-string-regexp "4.0.0"
+ find-up "5.0.0"
+ glob "8.1.0"
+ he "1.2.0"
+ js-yaml "4.1.0"
+ log-symbols "4.1.0"
+ minimatch "5.0.1"
+ ms "2.1.3"
+ serialize-javascript "6.0.0"
+ strip-json-comments "3.1.1"
+ supports-color "8.1.1"
+ workerpool "6.2.1"
+ yargs "16.2.0"
+ yargs-parser "20.2.4"
+ yargs-unparser "2.0.0"
+
mocha@^7.1.1:
version "7.2.0"
resolved "https://registry.npmjs.org/mocha/-/mocha-7.2.0.tgz"
@@ -4432,11 +4256,6 @@ mocha@^7.1.1:
yargs-parser "13.1.2"
yargs-unparser "1.6.0"
-module-error@^1.0.1, module-error@^1.0.2:
- version "1.0.2"
- resolved "https://registry.npmjs.org/module-error/-/module-error-1.0.2.tgz"
- integrity sha512-0yuvsqSCv8LbaOKhnsQ/T5JhyFlCYLPXK3U2sgV10zoKQwzs/MyfuQUOZQ1V/6OCOJsK/TRgNVrPuPDqtdMFtA==
-
ms@2.0.0:
version "2.0.0"
resolved "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz"
@@ -4467,11 +4286,6 @@ nanoid@3.3.3:
resolved "https://registry.npmjs.org/nanoid/-/nanoid-3.3.3.tgz"
integrity sha512-p1sjXuopFs0xg+fPASzQ28agW1oHD7xDsd9Xkf3T15H3c/cifrFHVwrh74PdoklAPi+i7MdRsE47vm2r6JoB+w==
-napi-macros@~2.0.0:
- version "2.0.0"
- resolved "https://registry.npmjs.org/napi-macros/-/napi-macros-2.0.0.tgz"
- integrity sha512-A0xLykHtARfueITVDernsAWdtIMbOJgKgcluwENp3AlsKN/PloyO10HtmoqnFAQAcxPkgZN7wdfPfEd0zNGxbg==
-
natural-compare-lite@^1.4.0:
version "1.4.0"
resolved "https://registry.npmjs.org/natural-compare-lite/-/natural-compare-lite-1.4.0.tgz"
@@ -4526,7 +4340,7 @@ node-fetch@2.6.7, node-fetch@>=2.6.7:
fetch-blob "^3.1.4"
formdata-polyfill "^4.0.10"
-node-gyp-build@^4.2.0, node-gyp-build@^4.3.0:
+node-gyp-build@^4.2.0:
version "4.5.0"
resolved "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.5.0.tgz"
integrity sha512-2iGbaQBV+ITgCz76ZEjmhUKAKVf7xfY1sRl4UiKQspfZMH2h06SyhNsnSVy50cwkFQDGLyif6m/6uFXHkOZ6rg==
@@ -4925,7 +4739,7 @@ punycode@^2.1.0, punycode@^2.1.1:
resolved "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz"
integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==
-qs@^6.4.0, qs@^6.7.0:
+qs@^6.4.0:
version "6.11.0"
resolved "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz"
integrity sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==
@@ -4937,7 +4751,7 @@ qs@~6.5.2:
resolved "https://registry.npmjs.org/qs/-/qs-6.5.3.tgz"
integrity sha512-qxXIEh4pCGfHICj1mAJQ2/2XVZkjCDTcEgfoSQxc/fYivUZxTkk7L3bDBJSoNrEzXI17oUO5Dp07ktqE5KzczA==
-queue-microtask@^1.2.2, queue-microtask@^1.2.3:
+queue-microtask@^1.2.2:
version "1.2.3"
resolved "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz"
integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==
@@ -5219,13 +5033,6 @@ run-async@^2.2.0:
resolved "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz"
integrity sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==
-run-parallel-limit@^1.1.0:
- version "1.1.0"
- resolved "https://registry.npmjs.org/run-parallel-limit/-/run-parallel-limit-1.1.0.tgz"
- integrity sha512-jJA7irRNM91jaKc3Hcl1npHsFLOXOoTkPCUL1JEa1R82O2miplXXRaGdjW/KM/98YQWDhJLiSs793CnXfblJUw==
- dependencies:
- queue-microtask "^1.2.2"
-
run-parallel@^1.1.9:
version "1.2.0"
resolved "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz"
@@ -5233,11 +5040,6 @@ run-parallel@^1.1.9:
dependencies:
queue-microtask "^1.2.2"
-rustbn.js@~0.2.0:
- version "0.2.0"
- resolved "https://registry.npmjs.org/rustbn.js/-/rustbn.js-0.2.0.tgz"
- integrity sha512-4VlvkRUuCJvr2J6Y0ImW7NvTCriMi7ErOAqWk1y69vAdoNIzCF3yPmgeNzx+RQTLEDFq5sHfscn1MwHxP9hNfA==
-
rxjs@^6.4.0:
version "6.6.7"
resolved "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz"
@@ -5311,6 +5113,13 @@ scuffed-abi@^1.0.4:
resolved "https://registry.npmjs.org/scuffed-abi/-/scuffed-abi-1.0.4.tgz"
integrity sha512-1NN2L1j+TMF6+/J2jHcAnhPH8Lwaqu5dlgknZPqejEVFQ8+cvcnXYNbaHtGEXTjSNrQLBGePXicD4oFGqecOnQ==
+seaport-core@1.6.5:
+ version "1.6.5"
+ resolved "https://registry.yarnpkg.com/seaport-core/-/seaport-core-1.6.5.tgz#97c85dd5161e57ec28df6c43c93ee3eb9943ec66"
+ integrity sha512-jpGOpaKpH1B49oOYqAYAAVXN8eGlI/NjE6fYHPYlQaDVx325NS5dpiDDgGLtQZNgQ3EbqrfhfB5KyIbg7owyFg==
+ dependencies:
+ seaport-types "1.6.3"
+
seaport-core@^0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/seaport-core/-/seaport-core-0.0.1.tgz#99db0b605d0fbbfd43ca7a4724e64374ce47f6d4"
@@ -5318,21 +5127,19 @@ seaport-core@^0.0.1:
dependencies:
seaport-types "^0.0.1"
-seaport-core@^1.5.0:
- version "1.5.0"
- resolved "https://registry.yarnpkg.com/seaport-core/-/seaport-core-1.5.0.tgz#1dae19b6c7940b0042be50b6ff070b13da0c5a09"
- integrity sha512-qS5y3+EdW+ostBliVqzAP/b0eceKFNPSe6JsvvxYtkpdb9hVI6Ls2N+rOxQ4LcW2h/yGARAJPk7nxm4I7PRjqQ==
- dependencies:
- seaport-types "^0.0.1"
-
-seaport-sol@^1.5.0:
- version "1.5.3"
- resolved "https://registry.yarnpkg.com/seaport-sol/-/seaport-sol-1.5.3.tgz#ccb0047bcefb7d29bcd379faddf3a5a9902d0c3a"
- integrity sha512-6g91hs15v4zBx/ZN9YD0evhQSDhdMKu83c2CgBgtc517D8ipaYaFO71ZD6V0Z6/I0cwNfuN/ZljcA1J+xXr65A==
+seaport-sol@1.6.0:
+ version "1.6.0"
+ resolved "https://registry.yarnpkg.com/seaport-sol/-/seaport-sol-1.6.0.tgz#2a71ae8da5af9aecffee21767632ef37aaaaee13"
+ integrity sha512-a1FBK1jIeEQXZ9CmQvtmfG0w7CE8nIad89btGg7qrrrtF4j1S0Ilmzpe2Hderap05Uvf3EWS9P/aghDQCNAwkA==
dependencies:
seaport-core "^0.0.1"
seaport-types "^0.0.1"
+seaport-types@1.6.3:
+ version "1.6.3"
+ resolved "https://registry.yarnpkg.com/seaport-types/-/seaport-types-1.6.3.tgz#b9993864517d4f9ecccc6b6daf6ef3f52a114e58"
+ integrity sha512-Rm9dTTEUKmXqMgc5TiRtfX/sFOX6SjKkT9l/spTdRknplYh5tmJ0fMJzbE60pCzV1/Izq0cCua6uvWszo6zOAQ==
+
seaport-types@^0.0.1:
version "0.0.1"
resolved "https://registry.yarnpkg.com/seaport-types/-/seaport-types-0.0.1.tgz#e2a32fe8641853d7dadb1b0232d911d88ccc3f1a"
@@ -5555,16 +5362,15 @@ solidity-comments-extractor@^0.0.7:
resolved "https://registry.npmjs.org/solidity-comments-extractor/-/solidity-comments-extractor-0.0.7.tgz"
integrity sha512-wciNMLg/Irp8OKGrh3S2tfvZiZ0NEyILfcRCXCD4mp7SgK/i9gzLfhY2hY7VMCQJ3kH9UB9BzNdibIVMchzyYw==
-solidity-coverage@^0.8.2:
- version "0.8.2"
- resolved "https://registry.npmjs.org/solidity-coverage/-/solidity-coverage-0.8.2.tgz"
- integrity sha512-cv2bWb7lOXPE9/SSleDO6czkFiMHgP4NXPj+iW9W7iEKLBk7Cj0AGBiNmGX3V1totl9wjPrT0gHmABZKZt65rQ==
+solidity-coverage@^0.8.10:
+ version "0.8.11"
+ resolved "https://registry.yarnpkg.com/solidity-coverage/-/solidity-coverage-0.8.11.tgz#c95798f2c3e885c49dcfc9c43ee570d112214785"
+ integrity sha512-yy0Yk+olovBbXn0Me8BWULmmv7A69ZKkP5aTOJGOO8u61Tu2zS989erfjtFlUjDnfWtxRAVkd8BsQD704yLWHw==
dependencies:
"@ethersproject/abi" "^5.0.9"
- "@solidity-parser/parser" "^0.14.1"
+ "@solidity-parser/parser" "^0.18.0"
chalk "^2.4.2"
death "^1.1.0"
- detect-port "^1.3.0"
difflib "^0.2.4"
fs-extra "^8.1.0"
ghost-testrpc "^0.0.2"
@@ -5572,7 +5378,7 @@ solidity-coverage@^0.8.2:
globby "^10.0.1"
jsonschema "^1.2.4"
lodash "^4.17.15"
- mocha "7.1.2"
+ mocha "^10.2.0"
node-emoji "^1.10.0"
pify "^4.0.1"
recursive-readdir "^2.2.2"
@@ -5638,11 +5444,6 @@ stealthy-require@^1.1.1:
resolved "https://registry.npmjs.org/stealthy-require/-/stealthy-require-1.1.1.tgz"
integrity sha512-ZnWpYnYugiOVEY5GkcuJK1io5V8QmNYChG62gSit9pQVGErXtrKuPC55ITaVSukmMta5qpMU7vqLt2Lnni4f/g==
-streamsearch@^1.1.0:
- version "1.1.0"
- resolved "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz"
- integrity sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==
-
string-argv@^0.3.1:
version "0.3.1"
resolved "https://registry.npmjs.org/string-argv/-/string-argv-0.3.1.tgz"
@@ -5670,7 +5471,7 @@ string-width@^3.0.0, string-width@^3.1.0:
is-fullwidth-code-point "^2.0.0"
strip-ansi "^5.1.0"
-string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3:
+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.npmjs.org/string-width/-/string-width-4.2.3.tgz"
integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==
@@ -6116,12 +5917,10 @@ underscore@>=1.12.1:
resolved "https://registry.yarnpkg.com/underscore/-/underscore-1.13.6.tgz#04786a1f589dc6c09f761fc5f45b89e935136441"
integrity sha512-+A5Sja4HP1M08MaXya7p5LvjuM7K6q/2EaC0+iovj/wOcMsTzMvDFbasi/oSapiwOlt252IqsKqPjCl7huKS0A==
-undici@>=5.8.2, undici@^5.4.0:
- version "5.20.0"
- resolved "https://registry.yarnpkg.com/undici/-/undici-5.20.0.tgz#6327462f5ce1d3646bcdac99da7317f455bcc263"
- integrity sha512-J3j60dYzuo6Eevbawwp1sdg16k5Tf768bxYK4TUJRH7cBM4kFCbf3mOnM/0E3vQYXvpxITbbWmBafaDbxLDz3g==
- dependencies:
- busboy "^1.6.0"
+undici@>=5.8.2, undici@^5.14.0, undici@^5.4.0:
+ version "6.9.0"
+ resolved "https://registry.yarnpkg.com/undici/-/undici-6.9.0.tgz#281b3c8bf29cafa957e743ab2a710b586b01e66e"
+ integrity sha512-XPWfXzJedevUziHwun70EKNvGnxv4CnfraFZ4f/JV01+fcvMYzHE26r/j8AY/9c/70nkN4B1zX7E2Oyuqwz4+Q==
universalify@^0.1.0:
version "0.1.2"
@@ -6239,10 +6038,17 @@ wide-align@1.1.3:
dependencies:
string-width "^1.0.2 || 2"
+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"
+
word-wrap@^1.2.3, word-wrap@~1.2.3:
- version "1.2.3"
- resolved "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz"
- integrity sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==
+ version "1.2.4"
+ resolved "https://registry.yarnpkg.com/word-wrap/-/word-wrap-1.2.4.tgz#cb4b50ec9aca570abd1f52f33cd45b6c61739a9f"
+ integrity sha512-2V81OA4ugVo5pRo46hAoD2ivUJx8jXmWXfUkY4KFNw0hEptvN0QfH3K4nHiwzGeKl5rFKedV48QVoqYavy4YpA==
wordwrap@^1.0.0:
version "1.0.0"
@@ -6321,11 +6127,6 @@ y18n@^5.0.5:
resolved "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz"
integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==
-yallist@^3.0.2:
- version "3.1.1"
- resolved "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz"
- integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==
-
yallist@^4.0.0:
version "4.0.0"
resolved "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz"