Compare commits
	
		
			16 Commits
		
	
	
		
			@0x/contra
			...
			@0x/contra
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					2a6d66cc2a | ||
| 
						 | 
					b02992a373 | ||
| 
						 | 
					92ad924965 | ||
| 
						 | 
					138383e95c | ||
| 
						 | 
					0487cb7d39 | ||
| 
						 | 
					22e1ed35d3 | ||
| 
						 | 
					dabe6fd793 | ||
| 
						 | 
					3cc639c8d0 | ||
| 
						 | 
					22c8e0b6db | ||
| 
						 | 
					f3ca4293bc | ||
| 
						 | 
					db3e076d03 | ||
| 
						 | 
					1a6759820a | ||
| 
						 | 
					61c5e7b948 | ||
| 
						 | 
					5fd78ef32f | ||
| 
						 | 
					14ff9b827c | ||
| 
						 | 
					598dc2cd71 | 
							
								
								
									
										7
									
								
								.github/workflows/publish.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										7
									
								
								.github/workflows/publish.yml
									
									
									
									
										vendored
									
									
								
							@@ -7,6 +7,9 @@ on:
 | 
			
		||||
              description: 'required CI status'
 | 
			
		||||
              default: 'success'
 | 
			
		||||
              required: true
 | 
			
		||||
          prerelease:
 | 
			
		||||
              description: 'prerelease name'
 | 
			
		||||
              required: false
 | 
			
		||||
 | 
			
		||||
jobs:
 | 
			
		||||
    publish:
 | 
			
		||||
@@ -21,7 +24,7 @@ jobs:
 | 
			
		||||
                  (echo "::error ::${{ github.ref }} does not have a successful CI status" && false)
 | 
			
		||||
            - uses: actions/checkout@v2
 | 
			
		||||
              with:
 | 
			
		||||
                ref: 'development'
 | 
			
		||||
                ref: ${{ github.ref }}
 | 
			
		||||
                fetch-depth: 0
 | 
			
		||||
            - uses: actions/setup-node@v1
 | 
			
		||||
              with:
 | 
			
		||||
@@ -41,7 +44,9 @@ jobs:
 | 
			
		||||
              env:
 | 
			
		||||
                  NPM_TOKEN: ${{ secrets.NPM_PUBLISH_TOKEN }}
 | 
			
		||||
                  GITHUB_TOKEN: ${{ github.token }}
 | 
			
		||||
                  PUBLISH_PRERELEASE: ${{ github.event.inputs.prerelease }}
 | 
			
		||||
            - name: 'merge into main branch'
 | 
			
		||||
              if: github.event.inputs.prerelease == '' # unless it's a prerelease
 | 
			
		||||
              run: |
 | 
			
		||||
                  git checkout main && \
 | 
			
		||||
                  git merge ${{ github.ref }} && \
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,13 @@
 | 
			
		||||
[
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1615932869,
 | 
			
		||||
        "version": "3.7.8-multiplex.0",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1614141718,
 | 
			
		||||
        "version": "3.7.7",
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
 | 
			
		||||
 | 
			
		||||
CHANGELOG
 | 
			
		||||
 | 
			
		||||
## v3.7.8-multiplex.0 - _March 16, 2021_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v3.7.7 - _February 24, 2021_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
    "name": "@0x/contracts-asset-proxy",
 | 
			
		||||
    "version": "3.7.7",
 | 
			
		||||
    "version": "3.7.8-multiplex.0",
 | 
			
		||||
    "engines": {
 | 
			
		||||
        "node": ">=6.12"
 | 
			
		||||
    },
 | 
			
		||||
@@ -51,13 +51,13 @@
 | 
			
		||||
    },
 | 
			
		||||
    "homepage": "https://github.com/0xProject/protocol/tree/main/contracts/protocol",
 | 
			
		||||
    "devDependencies": {
 | 
			
		||||
        "@0x/abi-gen": "^5.4.19",
 | 
			
		||||
        "@0x/contract-wrappers": "^13.13.0",
 | 
			
		||||
        "@0x/contracts-gen": "^2.0.30",
 | 
			
		||||
        "@0x/contracts-test-utils": "^5.3.22",
 | 
			
		||||
        "@0x/contracts-utils": "^4.7.4",
 | 
			
		||||
        "@0x/abi-gen": "^5.4.21",
 | 
			
		||||
        "@0x/contract-wrappers": "^13.14.0-multiplex",
 | 
			
		||||
        "@0x/contracts-gen": "^2.0.32",
 | 
			
		||||
        "@0x/contracts-test-utils": "^5.3.23-multiplex.0",
 | 
			
		||||
        "@0x/contracts-utils": "^4.7.5-multiplex.0",
 | 
			
		||||
        "@0x/dev-utils": "^4.2.1",
 | 
			
		||||
        "@0x/sol-compiler": "^4.5.2",
 | 
			
		||||
        "@0x/sol-compiler": "^4.6.1",
 | 
			
		||||
        "@0x/ts-doc-gen": "^0.0.28",
 | 
			
		||||
        "@0x/tslint-config": "^4.1.3",
 | 
			
		||||
        "@types/lodash": "4.14.104",
 | 
			
		||||
@@ -80,11 +80,11 @@
 | 
			
		||||
    },
 | 
			
		||||
    "dependencies": {
 | 
			
		||||
        "@0x/base-contract": "^6.2.18",
 | 
			
		||||
        "@0x/contracts-erc1155": "^2.1.25",
 | 
			
		||||
        "@0x/contracts-erc20": "^3.3.4",
 | 
			
		||||
        "@0x/contracts-erc721": "^3.1.25",
 | 
			
		||||
        "@0x/contracts-exchange-libs": "^4.3.25",
 | 
			
		||||
        "@0x/order-utils": "^10.4.17",
 | 
			
		||||
        "@0x/contracts-erc1155": "^2.1.26-multiplex.0",
 | 
			
		||||
        "@0x/contracts-erc20": "^3.3.5-multiplex.0",
 | 
			
		||||
        "@0x/contracts-erc721": "^3.1.26-multiplex.0",
 | 
			
		||||
        "@0x/contracts-exchange-libs": "^4.3.26-multiplex.0",
 | 
			
		||||
        "@0x/order-utils": "^10.4.18-multiplex.0",
 | 
			
		||||
        "@0x/types": "^3.3.1",
 | 
			
		||||
        "@0x/typescript-typings": "^5.1.6",
 | 
			
		||||
        "@0x/utils": "^6.2.0",
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,13 @@
 | 
			
		||||
[
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1615932869,
 | 
			
		||||
        "version": "1.1.26-multiplex.0",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1614141718,
 | 
			
		||||
        "version": "1.1.25",
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
 | 
			
		||||
 | 
			
		||||
CHANGELOG
 | 
			
		||||
 | 
			
		||||
## v1.1.26-multiplex.0 - _March 16, 2021_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v1.1.25 - _February 24, 2021_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
    "name": "@0x/contracts-broker",
 | 
			
		||||
    "version": "1.1.25",
 | 
			
		||||
    "version": "1.1.26-multiplex.0",
 | 
			
		||||
    "engines": {
 | 
			
		||||
        "node": ">=6.12"
 | 
			
		||||
    },
 | 
			
		||||
@@ -51,16 +51,16 @@
 | 
			
		||||
    },
 | 
			
		||||
    "homepage": "https://github.com/0xProject/protocol/tree/main/contracts/extensions",
 | 
			
		||||
    "devDependencies": {
 | 
			
		||||
        "@0x/abi-gen": "^5.4.19",
 | 
			
		||||
        "@0x/contracts-asset-proxy": "^3.7.7",
 | 
			
		||||
        "@0x/contracts-erc20": "^3.3.4",
 | 
			
		||||
        "@0x/contracts-erc721": "^3.1.25",
 | 
			
		||||
        "@0x/contracts-exchange": "^3.2.26",
 | 
			
		||||
        "@0x/contracts-exchange-libs": "^4.3.25",
 | 
			
		||||
        "@0x/contracts-gen": "^2.0.30",
 | 
			
		||||
        "@0x/contracts-test-utils": "^5.3.22",
 | 
			
		||||
        "@0x/contracts-utils": "^4.7.4",
 | 
			
		||||
        "@0x/sol-compiler": "^4.5.2",
 | 
			
		||||
        "@0x/abi-gen": "^5.4.21",
 | 
			
		||||
        "@0x/contracts-asset-proxy": "^3.7.8-multiplex.0",
 | 
			
		||||
        "@0x/contracts-erc20": "^3.3.5-multiplex.0",
 | 
			
		||||
        "@0x/contracts-erc721": "^3.1.26-multiplex.0",
 | 
			
		||||
        "@0x/contracts-exchange": "^3.2.27-multiplex.0",
 | 
			
		||||
        "@0x/contracts-exchange-libs": "^4.3.26-multiplex.0",
 | 
			
		||||
        "@0x/contracts-gen": "^2.0.32",
 | 
			
		||||
        "@0x/contracts-test-utils": "^5.3.23-multiplex.0",
 | 
			
		||||
        "@0x/contracts-utils": "^4.7.5-multiplex.0",
 | 
			
		||||
        "@0x/sol-compiler": "^4.6.1",
 | 
			
		||||
        "@0x/ts-doc-gen": "^0.0.28",
 | 
			
		||||
        "@0x/tslint-config": "^4.1.3",
 | 
			
		||||
        "@0x/types": "^3.3.1",
 | 
			
		||||
@@ -85,7 +85,7 @@
 | 
			
		||||
    },
 | 
			
		||||
    "dependencies": {
 | 
			
		||||
        "@0x/base-contract": "^6.2.18",
 | 
			
		||||
        "@0x/order-utils": "^10.4.17",
 | 
			
		||||
        "@0x/order-utils": "^10.4.18-multiplex.0",
 | 
			
		||||
        "@0x/typescript-typings": "^5.1.6",
 | 
			
		||||
        "@0x/utils": "^6.2.0",
 | 
			
		||||
        "ethereum-types": "^3.4.0"
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,13 @@
 | 
			
		||||
[
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1615932869,
 | 
			
		||||
        "version": "3.1.27-multiplex.0",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1614141718,
 | 
			
		||||
        "version": "3.1.26",
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
 | 
			
		||||
 | 
			
		||||
CHANGELOG
 | 
			
		||||
 | 
			
		||||
## v3.1.27-multiplex.0 - _March 16, 2021_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v3.1.26 - _February 24, 2021_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
    "name": "@0x/contracts-coordinator",
 | 
			
		||||
    "version": "3.1.26",
 | 
			
		||||
    "version": "3.1.27-multiplex.0",
 | 
			
		||||
    "engines": {
 | 
			
		||||
        "node": ">=6.12"
 | 
			
		||||
    },
 | 
			
		||||
@@ -52,14 +52,14 @@
 | 
			
		||||
    },
 | 
			
		||||
    "homepage": "https://github.com/0xProject/protocol/tree/main/contracts/extensions",
 | 
			
		||||
    "devDependencies": {
 | 
			
		||||
        "@0x/abi-gen": "^5.4.19",
 | 
			
		||||
        "@0x/contracts-asset-proxy": "^3.7.7",
 | 
			
		||||
        "@0x/contracts-dev-utils": "^1.3.24",
 | 
			
		||||
        "@0x/contracts-erc20": "^3.3.4",
 | 
			
		||||
        "@0x/contracts-gen": "^2.0.30",
 | 
			
		||||
        "@0x/abi-gen": "^5.4.21",
 | 
			
		||||
        "@0x/contracts-asset-proxy": "^3.7.8-multiplex.0",
 | 
			
		||||
        "@0x/contracts-dev-utils": "^1.3.25-multiplex.0",
 | 
			
		||||
        "@0x/contracts-erc20": "^3.3.5-multiplex.0",
 | 
			
		||||
        "@0x/contracts-gen": "^2.0.32",
 | 
			
		||||
        "@0x/dev-utils": "^4.2.1",
 | 
			
		||||
        "@0x/order-utils": "^10.4.17",
 | 
			
		||||
        "@0x/sol-compiler": "^4.5.2",
 | 
			
		||||
        "@0x/order-utils": "^10.4.18-multiplex.0",
 | 
			
		||||
        "@0x/sol-compiler": "^4.6.1",
 | 
			
		||||
        "@0x/ts-doc-gen": "^0.0.28",
 | 
			
		||||
        "@0x/tslint-config": "^4.1.3",
 | 
			
		||||
        "@0x/web3-wrapper": "^7.4.1",
 | 
			
		||||
@@ -85,9 +85,9 @@
 | 
			
		||||
        "@0x/assert": "^3.0.21",
 | 
			
		||||
        "@0x/base-contract": "^6.2.18",
 | 
			
		||||
        "@0x/contract-addresses": "^5.11.0",
 | 
			
		||||
        "@0x/contracts-exchange": "^3.2.26",
 | 
			
		||||
        "@0x/contracts-test-utils": "^5.3.22",
 | 
			
		||||
        "@0x/contracts-utils": "^4.7.4",
 | 
			
		||||
        "@0x/contracts-exchange": "^3.2.27-multiplex.0",
 | 
			
		||||
        "@0x/contracts-test-utils": "^5.3.23-multiplex.0",
 | 
			
		||||
        "@0x/contracts-utils": "^4.7.5-multiplex.0",
 | 
			
		||||
        "@0x/json-schemas": "^5.4.1",
 | 
			
		||||
        "@0x/types": "^3.3.1",
 | 
			
		||||
        "@0x/typescript-typings": "^5.1.6",
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,13 @@
 | 
			
		||||
[
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1615932869,
 | 
			
		||||
        "version": "1.3.25-multiplex.0",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1614141718,
 | 
			
		||||
        "version": "1.3.24",
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
 | 
			
		||||
 | 
			
		||||
CHANGELOG
 | 
			
		||||
 | 
			
		||||
## v1.3.25-multiplex.0 - _March 16, 2021_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v1.3.24 - _February 24, 2021_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
    "name": "@0x/contracts-dev-utils",
 | 
			
		||||
    "version": "1.3.24",
 | 
			
		||||
    "version": "1.3.25-multiplex.0",
 | 
			
		||||
    "engines": {
 | 
			
		||||
        "node": ">=6.12"
 | 
			
		||||
    },
 | 
			
		||||
@@ -41,13 +41,13 @@
 | 
			
		||||
    },
 | 
			
		||||
    "homepage": "https://github.com/0xProject/protocol/tree/main/contracts/dev-utils",
 | 
			
		||||
    "devDependencies": {
 | 
			
		||||
        "@0x/abi-gen": "^5.4.19",
 | 
			
		||||
        "@0x/abi-gen": "^5.4.21",
 | 
			
		||||
        "@0x/assert": "^3.0.21",
 | 
			
		||||
        "@0x/contracts-asset-proxy": "^3.7.7",
 | 
			
		||||
        "@0x/contracts-erc20": "^3.3.4",
 | 
			
		||||
        "@0x/contracts-gen": "^2.0.30",
 | 
			
		||||
        "@0x/contracts-test-utils": "^5.3.22",
 | 
			
		||||
        "@0x/sol-compiler": "^4.5.2",
 | 
			
		||||
        "@0x/contracts-asset-proxy": "^3.7.8-multiplex.0",
 | 
			
		||||
        "@0x/contracts-erc20": "^3.3.5-multiplex.0",
 | 
			
		||||
        "@0x/contracts-gen": "^2.0.32",
 | 
			
		||||
        "@0x/contracts-test-utils": "^5.3.23-multiplex.0",
 | 
			
		||||
        "@0x/sol-compiler": "^4.6.1",
 | 
			
		||||
        "@0x/ts-doc-gen": "^0.0.28",
 | 
			
		||||
        "@0x/tslint-config": "^4.1.3",
 | 
			
		||||
        "@0x/types": "^3.3.1",
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,13 @@
 | 
			
		||||
[
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1615932869,
 | 
			
		||||
        "version": "2.1.26-multiplex.0",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1614141718,
 | 
			
		||||
        "version": "2.1.25",
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
 | 
			
		||||
 | 
			
		||||
CHANGELOG
 | 
			
		||||
 | 
			
		||||
## v2.1.26-multiplex.0 - _March 16, 2021_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v2.1.25 - _February 24, 2021_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
    "name": "@0x/contracts-erc1155",
 | 
			
		||||
    "version": "2.1.25",
 | 
			
		||||
    "version": "2.1.26-multiplex.0",
 | 
			
		||||
    "engines": {
 | 
			
		||||
        "node": ">=6.12"
 | 
			
		||||
    },
 | 
			
		||||
@@ -52,11 +52,11 @@
 | 
			
		||||
    },
 | 
			
		||||
    "homepage": "https://github.com/0xProject/protocol/tree/main/contracts/tokens",
 | 
			
		||||
    "devDependencies": {
 | 
			
		||||
        "@0x/abi-gen": "^5.4.19",
 | 
			
		||||
        "@0x/contracts-gen": "^2.0.30",
 | 
			
		||||
        "@0x/contracts-utils": "^4.7.4",
 | 
			
		||||
        "@0x/abi-gen": "^5.4.21",
 | 
			
		||||
        "@0x/contracts-gen": "^2.0.32",
 | 
			
		||||
        "@0x/contracts-utils": "^4.7.5-multiplex.0",
 | 
			
		||||
        "@0x/dev-utils": "^4.2.1",
 | 
			
		||||
        "@0x/sol-compiler": "^4.5.2",
 | 
			
		||||
        "@0x/sol-compiler": "^4.6.1",
 | 
			
		||||
        "@0x/ts-doc-gen": "^0.0.28",
 | 
			
		||||
        "@0x/tslint-config": "^4.1.3",
 | 
			
		||||
        "@0x/types": "^3.3.1",
 | 
			
		||||
@@ -81,7 +81,7 @@
 | 
			
		||||
    },
 | 
			
		||||
    "dependencies": {
 | 
			
		||||
        "@0x/base-contract": "^6.2.18",
 | 
			
		||||
        "@0x/contracts-test-utils": "^5.3.22",
 | 
			
		||||
        "@0x/contracts-test-utils": "^5.3.23-multiplex.0",
 | 
			
		||||
        "@0x/utils": "^6.2.0",
 | 
			
		||||
        "@0x/web3-wrapper": "^7.4.1",
 | 
			
		||||
        "lodash": "^4.17.11"
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,13 @@
 | 
			
		||||
[
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1615932869,
 | 
			
		||||
        "version": "3.3.5-multiplex.0",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1614141718,
 | 
			
		||||
        "version": "3.3.4",
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
 | 
			
		||||
 | 
			
		||||
CHANGELOG
 | 
			
		||||
 | 
			
		||||
## v3.3.5-multiplex.0 - _March 16, 2021_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v3.3.4 - _February 24, 2021_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
    "name": "@0x/contracts-erc20",
 | 
			
		||||
    "version": "3.3.4",
 | 
			
		||||
    "version": "3.3.5-multiplex.0",
 | 
			
		||||
    "engines": {
 | 
			
		||||
        "node": ">=6.12"
 | 
			
		||||
    },
 | 
			
		||||
@@ -51,12 +51,12 @@
 | 
			
		||||
    },
 | 
			
		||||
    "homepage": "https://github.com/0xProject/protocol/tree/main/contracts/tokens",
 | 
			
		||||
    "devDependencies": {
 | 
			
		||||
        "@0x/abi-gen": "^5.4.19",
 | 
			
		||||
        "@0x/contracts-gen": "^2.0.30",
 | 
			
		||||
        "@0x/contracts-test-utils": "^5.3.22",
 | 
			
		||||
        "@0x/contracts-utils": "^4.7.4",
 | 
			
		||||
        "@0x/abi-gen": "^5.4.21",
 | 
			
		||||
        "@0x/contracts-gen": "^2.0.32",
 | 
			
		||||
        "@0x/contracts-test-utils": "^5.3.23-multiplex.0",
 | 
			
		||||
        "@0x/contracts-utils": "^4.7.5-multiplex.0",
 | 
			
		||||
        "@0x/dev-utils": "^4.2.1",
 | 
			
		||||
        "@0x/sol-compiler": "^4.5.2",
 | 
			
		||||
        "@0x/sol-compiler": "^4.6.1",
 | 
			
		||||
        "@0x/ts-doc-gen": "^0.0.28",
 | 
			
		||||
        "@0x/tslint-config": "^4.1.3",
 | 
			
		||||
        "@0x/types": "^3.3.1",
 | 
			
		||||
 
 | 
			
		||||
@@ -6,6 +6,7 @@ export {
 | 
			
		||||
    WETH9Events,
 | 
			
		||||
    WETH9DepositEventArgs,
 | 
			
		||||
    WETH9TransferEventArgs,
 | 
			
		||||
    WETH9WithdrawalEventArgs,
 | 
			
		||||
    ZRXTokenContract,
 | 
			
		||||
    DummyERC20TokenTransferEventArgs,
 | 
			
		||||
    ERC20TokenEventArgs,
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,13 @@
 | 
			
		||||
[
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1615932869,
 | 
			
		||||
        "version": "3.1.26-multiplex.0",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1614141718,
 | 
			
		||||
        "version": "3.1.25",
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
 | 
			
		||||
 | 
			
		||||
CHANGELOG
 | 
			
		||||
 | 
			
		||||
## v3.1.26-multiplex.0 - _March 16, 2021_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v3.1.25 - _February 24, 2021_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
    "name": "@0x/contracts-erc721",
 | 
			
		||||
    "version": "3.1.25",
 | 
			
		||||
    "version": "3.1.26-multiplex.0",
 | 
			
		||||
    "engines": {
 | 
			
		||||
        "node": ">=6.12"
 | 
			
		||||
    },
 | 
			
		||||
@@ -52,12 +52,12 @@
 | 
			
		||||
    },
 | 
			
		||||
    "homepage": "https://github.com/0xProject/protocol/tree/main/contracts/tokens",
 | 
			
		||||
    "devDependencies": {
 | 
			
		||||
        "@0x/abi-gen": "^5.4.19",
 | 
			
		||||
        "@0x/contracts-gen": "^2.0.30",
 | 
			
		||||
        "@0x/contracts-test-utils": "^5.3.22",
 | 
			
		||||
        "@0x/contracts-utils": "^4.7.4",
 | 
			
		||||
        "@0x/abi-gen": "^5.4.21",
 | 
			
		||||
        "@0x/contracts-gen": "^2.0.32",
 | 
			
		||||
        "@0x/contracts-test-utils": "^5.3.23-multiplex.0",
 | 
			
		||||
        "@0x/contracts-utils": "^4.7.5-multiplex.0",
 | 
			
		||||
        "@0x/dev-utils": "^4.2.1",
 | 
			
		||||
        "@0x/sol-compiler": "^4.5.2",
 | 
			
		||||
        "@0x/sol-compiler": "^4.6.1",
 | 
			
		||||
        "@0x/ts-doc-gen": "^0.0.28",
 | 
			
		||||
        "@0x/tslint-config": "^4.1.3",
 | 
			
		||||
        "@0x/types": "^3.3.1",
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,13 @@
 | 
			
		||||
[
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1615932869,
 | 
			
		||||
        "version": "4.2.27-multiplex.0",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1614141718,
 | 
			
		||||
        "version": "4.2.26",
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
 | 
			
		||||
 | 
			
		||||
CHANGELOG
 | 
			
		||||
 | 
			
		||||
## v4.2.27-multiplex.0 - _March 16, 2021_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v4.2.26 - _February 24, 2021_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
    "name": "@0x/contracts-exchange-forwarder",
 | 
			
		||||
    "version": "4.2.26",
 | 
			
		||||
    "version": "4.2.27-multiplex.0",
 | 
			
		||||
    "engines": {
 | 
			
		||||
        "node": ">=6.12"
 | 
			
		||||
    },
 | 
			
		||||
@@ -52,20 +52,20 @@
 | 
			
		||||
    },
 | 
			
		||||
    "homepage": "https://github.com/0xProject/protocol/tree/main/contracts/extensions",
 | 
			
		||||
    "devDependencies": {
 | 
			
		||||
        "@0x/abi-gen": "^5.4.19",
 | 
			
		||||
        "@0x/contracts-asset-proxy": "^3.7.7",
 | 
			
		||||
        "@0x/contracts-dev-utils": "^1.3.24",
 | 
			
		||||
        "@0x/contracts-erc1155": "^2.1.25",
 | 
			
		||||
        "@0x/contracts-erc20": "^3.3.4",
 | 
			
		||||
        "@0x/contracts-erc721": "^3.1.25",
 | 
			
		||||
        "@0x/contracts-exchange": "^3.2.26",
 | 
			
		||||
        "@0x/contracts-exchange-libs": "^4.3.25",
 | 
			
		||||
        "@0x/contracts-gen": "^2.0.30",
 | 
			
		||||
        "@0x/contracts-test-utils": "^5.3.22",
 | 
			
		||||
        "@0x/contracts-utils": "^4.7.4",
 | 
			
		||||
        "@0x/abi-gen": "^5.4.21",
 | 
			
		||||
        "@0x/contracts-asset-proxy": "^3.7.8-multiplex.0",
 | 
			
		||||
        "@0x/contracts-dev-utils": "^1.3.25-multiplex.0",
 | 
			
		||||
        "@0x/contracts-erc1155": "^2.1.26-multiplex.0",
 | 
			
		||||
        "@0x/contracts-erc20": "^3.3.5-multiplex.0",
 | 
			
		||||
        "@0x/contracts-erc721": "^3.1.26-multiplex.0",
 | 
			
		||||
        "@0x/contracts-exchange": "^3.2.27-multiplex.0",
 | 
			
		||||
        "@0x/contracts-exchange-libs": "^4.3.26-multiplex.0",
 | 
			
		||||
        "@0x/contracts-gen": "^2.0.32",
 | 
			
		||||
        "@0x/contracts-test-utils": "^5.3.23-multiplex.0",
 | 
			
		||||
        "@0x/contracts-utils": "^4.7.5-multiplex.0",
 | 
			
		||||
        "@0x/dev-utils": "^4.2.1",
 | 
			
		||||
        "@0x/order-utils": "^10.4.17",
 | 
			
		||||
        "@0x/sol-compiler": "^4.5.2",
 | 
			
		||||
        "@0x/order-utils": "^10.4.18-multiplex.0",
 | 
			
		||||
        "@0x/sol-compiler": "^4.6.1",
 | 
			
		||||
        "@0x/ts-doc-gen": "^0.0.28",
 | 
			
		||||
        "@0x/tslint-config": "^4.1.3",
 | 
			
		||||
        "@0x/types": "^3.3.1",
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,13 @@
 | 
			
		||||
[
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1615932869,
 | 
			
		||||
        "version": "4.3.26-multiplex.0",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1614141718,
 | 
			
		||||
        "version": "4.3.25",
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
 | 
			
		||||
 | 
			
		||||
CHANGELOG
 | 
			
		||||
 | 
			
		||||
## v4.3.26-multiplex.0 - _March 16, 2021_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v4.3.25 - _February 24, 2021_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
    "name": "@0x/contracts-exchange-libs",
 | 
			
		||||
    "version": "4.3.25",
 | 
			
		||||
    "version": "4.3.26-multiplex.0",
 | 
			
		||||
    "engines": {
 | 
			
		||||
        "node": ">=6.12"
 | 
			
		||||
    },
 | 
			
		||||
@@ -52,10 +52,10 @@
 | 
			
		||||
    },
 | 
			
		||||
    "homepage": "https://github.com/0xProject/protocol/tree/main/contracts/libs",
 | 
			
		||||
    "devDependencies": {
 | 
			
		||||
        "@0x/abi-gen": "^5.4.19",
 | 
			
		||||
        "@0x/contracts-gen": "^2.0.30",
 | 
			
		||||
        "@0x/abi-gen": "^5.4.21",
 | 
			
		||||
        "@0x/contracts-gen": "^2.0.32",
 | 
			
		||||
        "@0x/dev-utils": "^4.2.1",
 | 
			
		||||
        "@0x/sol-compiler": "^4.5.2",
 | 
			
		||||
        "@0x/sol-compiler": "^4.6.1",
 | 
			
		||||
        "@0x/subproviders": "^6.4.1",
 | 
			
		||||
        "@0x/ts-doc-gen": "^0.0.28",
 | 
			
		||||
        "@0x/tslint-config": "^4.1.3",
 | 
			
		||||
@@ -81,9 +81,9 @@
 | 
			
		||||
    },
 | 
			
		||||
    "dependencies": {
 | 
			
		||||
        "@0x/base-contract": "^6.2.18",
 | 
			
		||||
        "@0x/contracts-test-utils": "^5.3.22",
 | 
			
		||||
        "@0x/contracts-utils": "^4.7.4",
 | 
			
		||||
        "@0x/order-utils": "^10.4.17",
 | 
			
		||||
        "@0x/contracts-test-utils": "^5.3.23-multiplex.0",
 | 
			
		||||
        "@0x/contracts-utils": "^4.7.5-multiplex.0",
 | 
			
		||||
        "@0x/order-utils": "^10.4.18-multiplex.0",
 | 
			
		||||
        "@0x/types": "^3.3.1",
 | 
			
		||||
        "@0x/typescript-typings": "^5.1.6",
 | 
			
		||||
        "@0x/utils": "^6.2.0",
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,13 @@
 | 
			
		||||
[
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1615932869,
 | 
			
		||||
        "version": "3.2.27-multiplex.0",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1614141718,
 | 
			
		||||
        "version": "3.2.26",
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
 | 
			
		||||
 | 
			
		||||
CHANGELOG
 | 
			
		||||
 | 
			
		||||
## v3.2.27-multiplex.0 - _March 16, 2021_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v3.2.26 - _February 24, 2021_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
    "name": "@0x/contracts-exchange",
 | 
			
		||||
    "version": "3.2.26",
 | 
			
		||||
    "version": "3.2.27-multiplex.0",
 | 
			
		||||
    "engines": {
 | 
			
		||||
        "node": ">=6.12"
 | 
			
		||||
    },
 | 
			
		||||
@@ -52,16 +52,16 @@
 | 
			
		||||
    },
 | 
			
		||||
    "homepage": "https://github.com/0xProject/protocol/tree/main/contracts/protocol",
 | 
			
		||||
    "devDependencies": {
 | 
			
		||||
        "@0x/abi-gen": "^5.4.19",
 | 
			
		||||
        "@0x/contracts-asset-proxy": "^3.7.7",
 | 
			
		||||
        "@0x/contracts-exchange-libs": "^4.3.25",
 | 
			
		||||
        "@0x/contracts-gen": "^2.0.30",
 | 
			
		||||
        "@0x/contracts-multisig": "^4.1.26",
 | 
			
		||||
        "@0x/contracts-staking": "^2.0.33",
 | 
			
		||||
        "@0x/contracts-test-utils": "^5.3.22",
 | 
			
		||||
        "@0x/contracts-utils": "^4.7.4",
 | 
			
		||||
        "@0x/abi-gen": "^5.4.21",
 | 
			
		||||
        "@0x/contracts-asset-proxy": "^3.7.8-multiplex.0",
 | 
			
		||||
        "@0x/contracts-exchange-libs": "^4.3.26-multiplex.0",
 | 
			
		||||
        "@0x/contracts-gen": "^2.0.32",
 | 
			
		||||
        "@0x/contracts-multisig": "^4.1.27-multiplex.0",
 | 
			
		||||
        "@0x/contracts-staking": "^2.0.34-multiplex.0",
 | 
			
		||||
        "@0x/contracts-test-utils": "^5.3.23-multiplex.0",
 | 
			
		||||
        "@0x/contracts-utils": "^4.7.5-multiplex.0",
 | 
			
		||||
        "@0x/dev-utils": "^4.2.1",
 | 
			
		||||
        "@0x/sol-compiler": "^4.5.2",
 | 
			
		||||
        "@0x/sol-compiler": "^4.6.1",
 | 
			
		||||
        "@0x/ts-doc-gen": "^0.0.28",
 | 
			
		||||
        "@0x/tslint-config": "^4.1.3",
 | 
			
		||||
        "@0x/types": "^3.3.1",
 | 
			
		||||
@@ -89,11 +89,11 @@
 | 
			
		||||
    },
 | 
			
		||||
    "dependencies": {
 | 
			
		||||
        "@0x/base-contract": "^6.2.18",
 | 
			
		||||
        "@0x/contracts-dev-utils": "^1.3.24",
 | 
			
		||||
        "@0x/contracts-erc1155": "^2.1.25",
 | 
			
		||||
        "@0x/contracts-erc20": "^3.3.4",
 | 
			
		||||
        "@0x/contracts-erc721": "^3.1.25",
 | 
			
		||||
        "@0x/order-utils": "^10.4.17",
 | 
			
		||||
        "@0x/contracts-dev-utils": "^1.3.25-multiplex.0",
 | 
			
		||||
        "@0x/contracts-erc1155": "^2.1.26-multiplex.0",
 | 
			
		||||
        "@0x/contracts-erc20": "^3.3.5-multiplex.0",
 | 
			
		||||
        "@0x/contracts-erc721": "^3.1.26-multiplex.0",
 | 
			
		||||
        "@0x/order-utils": "^10.4.18-multiplex.0",
 | 
			
		||||
        "@0x/utils": "^6.2.0",
 | 
			
		||||
        "lodash": "^4.17.11"
 | 
			
		||||
    },
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,13 @@
 | 
			
		||||
[
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1615932869,
 | 
			
		||||
        "version": "6.2.21-multiplex.0",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1614141718,
 | 
			
		||||
        "version": "6.2.20",
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
 | 
			
		||||
 | 
			
		||||
CHANGELOG
 | 
			
		||||
 | 
			
		||||
## v6.2.21-multiplex.0 - _March 16, 2021_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v6.2.20 - _February 24, 2021_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
    "name": "@0x/contracts-extensions",
 | 
			
		||||
    "version": "6.2.20",
 | 
			
		||||
    "version": "6.2.21-multiplex.0",
 | 
			
		||||
    "engines": {
 | 
			
		||||
        "node": ">=6.12"
 | 
			
		||||
    },
 | 
			
		||||
@@ -52,18 +52,18 @@
 | 
			
		||||
    },
 | 
			
		||||
    "homepage": "https://github.com/0xProject/protocol/tree/main/contracts/extensions",
 | 
			
		||||
    "devDependencies": {
 | 
			
		||||
        "@0x/abi-gen": "^5.4.19",
 | 
			
		||||
        "@0x/contracts-asset-proxy": "^3.7.7",
 | 
			
		||||
        "@0x/contracts-dev-utils": "^1.3.24",
 | 
			
		||||
        "@0x/contracts-erc20": "^3.3.4",
 | 
			
		||||
        "@0x/contracts-erc721": "^3.1.25",
 | 
			
		||||
        "@0x/contracts-exchange": "^3.2.26",
 | 
			
		||||
        "@0x/contracts-exchange-libs": "^4.3.25",
 | 
			
		||||
        "@0x/contracts-gen": "^2.0.30",
 | 
			
		||||
        "@0x/contracts-utils": "^4.7.4",
 | 
			
		||||
        "@0x/abi-gen": "^5.4.21",
 | 
			
		||||
        "@0x/contracts-asset-proxy": "^3.7.8-multiplex.0",
 | 
			
		||||
        "@0x/contracts-dev-utils": "^1.3.25-multiplex.0",
 | 
			
		||||
        "@0x/contracts-erc20": "^3.3.5-multiplex.0",
 | 
			
		||||
        "@0x/contracts-erc721": "^3.1.26-multiplex.0",
 | 
			
		||||
        "@0x/contracts-exchange": "^3.2.27-multiplex.0",
 | 
			
		||||
        "@0x/contracts-exchange-libs": "^4.3.26-multiplex.0",
 | 
			
		||||
        "@0x/contracts-gen": "^2.0.32",
 | 
			
		||||
        "@0x/contracts-utils": "^4.7.5-multiplex.0",
 | 
			
		||||
        "@0x/dev-utils": "^4.2.1",
 | 
			
		||||
        "@0x/order-utils": "^10.4.17",
 | 
			
		||||
        "@0x/sol-compiler": "^4.5.2",
 | 
			
		||||
        "@0x/order-utils": "^10.4.18-multiplex.0",
 | 
			
		||||
        "@0x/sol-compiler": "^4.6.1",
 | 
			
		||||
        "@0x/ts-doc-gen": "^0.0.28",
 | 
			
		||||
        "@0x/tslint-config": "^4.1.3",
 | 
			
		||||
        "@0x/types": "^3.3.1",
 | 
			
		||||
@@ -91,7 +91,7 @@
 | 
			
		||||
    },
 | 
			
		||||
    "dependencies": {
 | 
			
		||||
        "@0x/base-contract": "^6.2.18",
 | 
			
		||||
        "@0x/contracts-test-utils": "^5.3.22",
 | 
			
		||||
        "@0x/contracts-test-utils": "^5.3.23-multiplex.0",
 | 
			
		||||
        "@0x/typescript-typings": "^5.1.6",
 | 
			
		||||
        "ethereum-types": "^3.4.0"
 | 
			
		||||
    },
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
    "name": "@0x/contracts-integrations",
 | 
			
		||||
    "version": "2.7.27",
 | 
			
		||||
    "version": "2.7.29-multiplex.0",
 | 
			
		||||
    "private": true,
 | 
			
		||||
    "engines": {
 | 
			
		||||
        "node": ">=6.12"
 | 
			
		||||
@@ -52,23 +52,23 @@
 | 
			
		||||
    },
 | 
			
		||||
    "homepage": "https://github.com/0xProject/protocol/tree/main/contracts/extensions",
 | 
			
		||||
    "devDependencies": {
 | 
			
		||||
        "@0x/abi-gen": "^5.4.19",
 | 
			
		||||
        "@0x/abi-gen": "^5.4.21",
 | 
			
		||||
        "@0x/contract-addresses": "^5.11.0",
 | 
			
		||||
        "@0x/contract-wrappers": "^13.13.0",
 | 
			
		||||
        "@0x/contracts-broker": "^1.1.25",
 | 
			
		||||
        "@0x/contracts-coordinator": "^3.1.26",
 | 
			
		||||
        "@0x/contracts-dev-utils": "^1.3.24",
 | 
			
		||||
        "@0x/contracts-exchange-forwarder": "^4.2.26",
 | 
			
		||||
        "@0x/contracts-exchange-libs": "^4.3.25",
 | 
			
		||||
        "@0x/contracts-extensions": "^6.2.20",
 | 
			
		||||
        "@0x/contracts-gen": "^2.0.30",
 | 
			
		||||
        "@0x/contracts-utils": "^4.7.4",
 | 
			
		||||
        "@0x/contract-wrappers": "^13.14.0-multiplex",
 | 
			
		||||
        "@0x/contracts-broker": "^1.1.26-multiplex.0",
 | 
			
		||||
        "@0x/contracts-coordinator": "^3.1.27-multiplex.0",
 | 
			
		||||
        "@0x/contracts-dev-utils": "^1.3.25-multiplex.0",
 | 
			
		||||
        "@0x/contracts-exchange-forwarder": "^4.2.27-multiplex.0",
 | 
			
		||||
        "@0x/contracts-exchange-libs": "^4.3.26-multiplex.0",
 | 
			
		||||
        "@0x/contracts-extensions": "^6.2.21-multiplex.0",
 | 
			
		||||
        "@0x/contracts-gen": "^2.0.32",
 | 
			
		||||
        "@0x/contracts-utils": "^4.7.5-multiplex.0",
 | 
			
		||||
        "@0x/coordinator-server": "^1.0.5",
 | 
			
		||||
        "@0x/dev-utils": "^4.2.1",
 | 
			
		||||
        "@0x/migrations": "^7.0.0",
 | 
			
		||||
        "@0x/order-utils": "^10.4.17",
 | 
			
		||||
        "@0x/protocol-utils": "^1.3.0",
 | 
			
		||||
        "@0x/sol-compiler": "^4.5.2",
 | 
			
		||||
        "@0x/migrations": "^7.0.1-multiplex.0",
 | 
			
		||||
        "@0x/order-utils": "^10.4.18-multiplex.0",
 | 
			
		||||
        "@0x/protocol-utils": "^1.3.1-multiplex.0",
 | 
			
		||||
        "@0x/sol-compiler": "^4.6.1",
 | 
			
		||||
        "@0x/tslint-config": "^4.1.3",
 | 
			
		||||
        "@0x/web3-wrapper": "^7.4.1",
 | 
			
		||||
        "@azure/core-asynciterator-polyfill": "^1.0.0",
 | 
			
		||||
@@ -93,17 +93,17 @@
 | 
			
		||||
        "typescript": "3.0.1"
 | 
			
		||||
    },
 | 
			
		||||
    "dependencies": {
 | 
			
		||||
        "@0x/asset-swapper": "^6.1.0",
 | 
			
		||||
        "@0x/asset-swapper": "^6.3.0-multiplex",
 | 
			
		||||
        "@0x/base-contract": "^6.2.18",
 | 
			
		||||
        "@0x/contracts-asset-proxy": "^3.7.7",
 | 
			
		||||
        "@0x/contracts-erc1155": "^2.1.25",
 | 
			
		||||
        "@0x/contracts-erc20": "^3.3.4",
 | 
			
		||||
        "@0x/contracts-erc721": "^3.1.25",
 | 
			
		||||
        "@0x/contracts-exchange": "^3.2.26",
 | 
			
		||||
        "@0x/contracts-multisig": "^4.1.26",
 | 
			
		||||
        "@0x/contracts-staking": "^2.0.33",
 | 
			
		||||
        "@0x/contracts-test-utils": "^5.3.22",
 | 
			
		||||
        "@0x/contracts-zero-ex": "^0.19.0",
 | 
			
		||||
        "@0x/contracts-asset-proxy": "^3.7.8-multiplex.0",
 | 
			
		||||
        "@0x/contracts-erc1155": "^2.1.26-multiplex.0",
 | 
			
		||||
        "@0x/contracts-erc20": "^3.3.5-multiplex.0",
 | 
			
		||||
        "@0x/contracts-erc721": "^3.1.26-multiplex.0",
 | 
			
		||||
        "@0x/contracts-exchange": "^3.2.27-multiplex.0",
 | 
			
		||||
        "@0x/contracts-multisig": "^4.1.27-multiplex.0",
 | 
			
		||||
        "@0x/contracts-staking": "^2.0.34-multiplex.0",
 | 
			
		||||
        "@0x/contracts-test-utils": "^5.3.23-multiplex.0",
 | 
			
		||||
        "@0x/contracts-zero-ex": "^0.20.0-multiplex",
 | 
			
		||||
        "@0x/subproviders": "^6.4.1",
 | 
			
		||||
        "@0x/types": "^3.3.1",
 | 
			
		||||
        "@0x/typescript-typings": "^5.1.6",
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,13 @@
 | 
			
		||||
[
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1615932869,
 | 
			
		||||
        "version": "4.1.27-multiplex.0",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1614141718,
 | 
			
		||||
        "version": "4.1.26",
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
 | 
			
		||||
 | 
			
		||||
CHANGELOG
 | 
			
		||||
 | 
			
		||||
## v4.1.27-multiplex.0 - _March 16, 2021_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v4.1.26 - _February 24, 2021_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
    "name": "@0x/contracts-multisig",
 | 
			
		||||
    "version": "4.1.26",
 | 
			
		||||
    "version": "4.1.27-multiplex.0",
 | 
			
		||||
    "engines": {
 | 
			
		||||
        "node": ">=6.12"
 | 
			
		||||
    },
 | 
			
		||||
@@ -49,14 +49,14 @@
 | 
			
		||||
    },
 | 
			
		||||
    "homepage": "https://github.com/0xProject/protocol/tree/main/contracts/multisig",
 | 
			
		||||
    "devDependencies": {
 | 
			
		||||
        "@0x/abi-gen": "^5.4.19",
 | 
			
		||||
        "@0x/contracts-asset-proxy": "^3.7.7",
 | 
			
		||||
        "@0x/contracts-erc20": "^3.3.4",
 | 
			
		||||
        "@0x/contracts-gen": "^2.0.30",
 | 
			
		||||
        "@0x/contracts-test-utils": "^5.3.22",
 | 
			
		||||
        "@0x/contracts-utils": "^4.7.4",
 | 
			
		||||
        "@0x/abi-gen": "^5.4.21",
 | 
			
		||||
        "@0x/contracts-asset-proxy": "^3.7.8-multiplex.0",
 | 
			
		||||
        "@0x/contracts-erc20": "^3.3.5-multiplex.0",
 | 
			
		||||
        "@0x/contracts-gen": "^2.0.32",
 | 
			
		||||
        "@0x/contracts-test-utils": "^5.3.23-multiplex.0",
 | 
			
		||||
        "@0x/contracts-utils": "^4.7.5-multiplex.0",
 | 
			
		||||
        "@0x/dev-utils": "^4.2.1",
 | 
			
		||||
        "@0x/sol-compiler": "^4.5.2",
 | 
			
		||||
        "@0x/sol-compiler": "^4.6.1",
 | 
			
		||||
        "@0x/tslint-config": "^4.1.3",
 | 
			
		||||
        "@0x/types": "^3.3.1",
 | 
			
		||||
        "@0x/utils": "^6.2.0",
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,13 @@
 | 
			
		||||
[
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1615932869,
 | 
			
		||||
        "version": "2.0.34-multiplex.0",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1614141718,
 | 
			
		||||
        "version": "2.0.33",
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
 | 
			
		||||
 | 
			
		||||
CHANGELOG
 | 
			
		||||
 | 
			
		||||
## v2.0.34-multiplex.0 - _March 16, 2021_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v2.0.33 - _February 24, 2021_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
    "name": "@0x/contracts-staking",
 | 
			
		||||
    "version": "2.0.33",
 | 
			
		||||
    "version": "2.0.34-multiplex.0",
 | 
			
		||||
    "engines": {
 | 
			
		||||
        "node": ">=6.12"
 | 
			
		||||
    },
 | 
			
		||||
@@ -53,16 +53,16 @@
 | 
			
		||||
    },
 | 
			
		||||
    "homepage": "https://github.com/0xProject/protocol/tree/main/contracts/tokens",
 | 
			
		||||
    "devDependencies": {
 | 
			
		||||
        "@0x/abi-gen": "^5.4.19",
 | 
			
		||||
        "@0x/contracts-asset-proxy": "^3.7.7",
 | 
			
		||||
        "@0x/contracts-dev-utils": "^1.3.24",
 | 
			
		||||
        "@0x/contracts-erc20": "^3.3.4",
 | 
			
		||||
        "@0x/contracts-exchange-libs": "^4.3.25",
 | 
			
		||||
        "@0x/contracts-gen": "^2.0.30",
 | 
			
		||||
        "@0x/contracts-utils": "^4.7.4",
 | 
			
		||||
        "@0x/abi-gen": "^5.4.21",
 | 
			
		||||
        "@0x/contracts-asset-proxy": "^3.7.8-multiplex.0",
 | 
			
		||||
        "@0x/contracts-dev-utils": "^1.3.25-multiplex.0",
 | 
			
		||||
        "@0x/contracts-erc20": "^3.3.5-multiplex.0",
 | 
			
		||||
        "@0x/contracts-exchange-libs": "^4.3.26-multiplex.0",
 | 
			
		||||
        "@0x/contracts-gen": "^2.0.32",
 | 
			
		||||
        "@0x/contracts-utils": "^4.7.5-multiplex.0",
 | 
			
		||||
        "@0x/dev-utils": "^4.2.1",
 | 
			
		||||
        "@0x/order-utils": "^10.4.17",
 | 
			
		||||
        "@0x/sol-compiler": "^4.5.2",
 | 
			
		||||
        "@0x/order-utils": "^10.4.18-multiplex.0",
 | 
			
		||||
        "@0x/sol-compiler": "^4.6.1",
 | 
			
		||||
        "@0x/ts-doc-gen": "^0.0.28",
 | 
			
		||||
        "@0x/tslint-config": "^4.1.3",
 | 
			
		||||
        "@0x/types": "^3.3.1",
 | 
			
		||||
@@ -88,7 +88,7 @@
 | 
			
		||||
    },
 | 
			
		||||
    "dependencies": {
 | 
			
		||||
        "@0x/base-contract": "^6.2.18",
 | 
			
		||||
        "@0x/contracts-test-utils": "^5.3.22",
 | 
			
		||||
        "@0x/contracts-test-utils": "^5.3.23-multiplex.0",
 | 
			
		||||
        "@0x/typescript-typings": "^5.1.6",
 | 
			
		||||
        "@0x/utils": "^6.2.0",
 | 
			
		||||
        "ethereum-types": "^3.4.0",
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,13 @@
 | 
			
		||||
[
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1615932869,
 | 
			
		||||
        "version": "5.3.23-multiplex.0",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1614141718,
 | 
			
		||||
        "version": "5.3.22",
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
 | 
			
		||||
 | 
			
		||||
CHANGELOG
 | 
			
		||||
 | 
			
		||||
## v5.3.23-multiplex.0 - _March 16, 2021_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v5.3.22 - _February 24, 2021_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
    "name": "@0x/contracts-test-utils",
 | 
			
		||||
    "version": "5.3.22",
 | 
			
		||||
    "version": "5.3.23-multiplex.0",
 | 
			
		||||
    "engines": {
 | 
			
		||||
        "node": ">=6.12"
 | 
			
		||||
    },
 | 
			
		||||
@@ -34,7 +34,7 @@
 | 
			
		||||
    },
 | 
			
		||||
    "homepage": "https://github.com/0xProject/protocol/tree/main/contracts/test-utils",
 | 
			
		||||
    "devDependencies": {
 | 
			
		||||
        "@0x/sol-compiler": "^4.5.2",
 | 
			
		||||
        "@0x/sol-compiler": "^4.6.1",
 | 
			
		||||
        "@0x/tslint-config": "^4.1.3",
 | 
			
		||||
        "npm-run-all": "^4.1.2",
 | 
			
		||||
        "shx": "^0.2.2",
 | 
			
		||||
@@ -47,10 +47,10 @@
 | 
			
		||||
        "@0x/contract-addresses": "^5.11.0",
 | 
			
		||||
        "@0x/dev-utils": "^4.2.1",
 | 
			
		||||
        "@0x/json-schemas": "^5.4.1",
 | 
			
		||||
        "@0x/order-utils": "^10.4.17",
 | 
			
		||||
        "@0x/sol-coverage": "^4.0.29",
 | 
			
		||||
        "@0x/sol-profiler": "^4.1.19",
 | 
			
		||||
        "@0x/sol-trace": "^3.0.29",
 | 
			
		||||
        "@0x/order-utils": "^10.4.18-multiplex.0",
 | 
			
		||||
        "@0x/sol-coverage": "^4.0.31",
 | 
			
		||||
        "@0x/sol-profiler": "^4.1.21",
 | 
			
		||||
        "@0x/sol-trace": "^3.0.31",
 | 
			
		||||
        "@0x/subproviders": "^6.4.1",
 | 
			
		||||
        "@0x/types": "^3.3.1",
 | 
			
		||||
        "@0x/typescript-typings": "^5.1.6",
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,14 @@
 | 
			
		||||
[
 | 
			
		||||
    {
 | 
			
		||||
        "version": "1.1.0-multiplex",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Make the proposal/quorum thresholds updatable",
 | 
			
		||||
                "pr": 165
 | 
			
		||||
            }
 | 
			
		||||
        ],
 | 
			
		||||
        "timestamp": 1615932869
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1614141718,
 | 
			
		||||
        "version": "1.0.2",
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
 | 
			
		||||
 | 
			
		||||
CHANGELOG
 | 
			
		||||
 | 
			
		||||
## v1.1.0-multiplex - _March 16, 2021_
 | 
			
		||||
 | 
			
		||||
    * Make the proposal/quorum thresholds updatable (#165)
 | 
			
		||||
 | 
			
		||||
## v1.0.2 - _February 24, 2021_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 
 | 
			
		||||
@@ -96,6 +96,18 @@ interface IZrxTreasury {
 | 
			
		||||
        view
 | 
			
		||||
        returns (uint256);
 | 
			
		||||
 | 
			
		||||
    /// @dev Updates the proposal and quorum thresholds to the given
 | 
			
		||||
    ///      values. Note that this function is only callable by the
 | 
			
		||||
    ///      treasury contract itself, so the threshold can only be
 | 
			
		||||
    ///      updated via a successful treasury proposal.
 | 
			
		||||
    /// @param newProposalThreshold The new value for the proposal threshold.
 | 
			
		||||
    /// @param newQuorumThreshold The new value for the quorum threshold.
 | 
			
		||||
    function updateThresholds(
 | 
			
		||||
        uint256 newProposalThreshold,
 | 
			
		||||
        uint256 newQuorumThreshold
 | 
			
		||||
    )
 | 
			
		||||
        external;
 | 
			
		||||
 | 
			
		||||
    /// @dev Creates a proposal to send ZRX from this treasury on the
 | 
			
		||||
    ///      the given actions. Must have at least `proposalThreshold`
 | 
			
		||||
    ///      of voting power to call this function. See `getVotingPower`
 | 
			
		||||
 
 | 
			
		||||
@@ -42,8 +42,8 @@ contract ZrxTreasury is
 | 
			
		||||
    DefaultPoolOperator public immutable override defaultPoolOperator;
 | 
			
		||||
    bytes32 public immutable override defaultPoolId;
 | 
			
		||||
    uint256 public immutable override votingPeriod;
 | 
			
		||||
    uint256 public immutable override proposalThreshold;
 | 
			
		||||
    uint256 public immutable override quorumThreshold;
 | 
			
		||||
    uint256 public override proposalThreshold;
 | 
			
		||||
    uint256 public override quorumThreshold;
 | 
			
		||||
 | 
			
		||||
    // Storage
 | 
			
		||||
    Proposal[] public proposals;
 | 
			
		||||
@@ -82,6 +82,24 @@ contract ZrxTreasury is
 | 
			
		||||
    receive() external payable {}
 | 
			
		||||
    // solhint-enable
 | 
			
		||||
 | 
			
		||||
    /// @dev Updates the proposal and quorum thresholds to the given
 | 
			
		||||
    ///      values. Note that this function is only callable by the
 | 
			
		||||
    ///      treasury contract itself, so the threshold can only be
 | 
			
		||||
    ///      updated via a successful treasury proposal.
 | 
			
		||||
    /// @param newProposalThreshold The new value for the proposal threshold.
 | 
			
		||||
    /// @param newQuorumThreshold The new value for the quorum threshold.
 | 
			
		||||
    function updateThresholds(
 | 
			
		||||
        uint256 newProposalThreshold,
 | 
			
		||||
        uint256 newQuorumThreshold
 | 
			
		||||
    )
 | 
			
		||||
        external
 | 
			
		||||
        override
 | 
			
		||||
    {
 | 
			
		||||
        require(msg.sender == address(this), "updateThresholds/ONLY_SELF");
 | 
			
		||||
        proposalThreshold = newProposalThreshold;
 | 
			
		||||
        quorumThreshold = newQuorumThreshold;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Creates a proposal to send ZRX from this treasury on the
 | 
			
		||||
    ///      the given actions. Must have at least `proposalThreshold`
 | 
			
		||||
    ///      of voting power to call this function. See `getVotingPower`
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
    "name": "@0x/contracts-treasury",
 | 
			
		||||
    "version": "1.0.2",
 | 
			
		||||
    "version": "1.1.0-multiplex",
 | 
			
		||||
    "engines": {
 | 
			
		||||
        "node": ">=6.12"
 | 
			
		||||
    },
 | 
			
		||||
@@ -46,14 +46,14 @@
 | 
			
		||||
    },
 | 
			
		||||
    "homepage": "https://github.com/0xProject/protocol/tree/main/contracts/treasury",
 | 
			
		||||
    "devDependencies": {
 | 
			
		||||
        "@0x/abi-gen": "^5.4.13",
 | 
			
		||||
        "@0x/abi-gen": "^5.4.21",
 | 
			
		||||
        "@0x/contract-addresses": "^5.11.0",
 | 
			
		||||
        "@0x/contracts-asset-proxy": "^3.7.7",
 | 
			
		||||
        "@0x/contracts-erc20": "^3.3.4",
 | 
			
		||||
        "@0x/contracts-gen": "^2.0.24",
 | 
			
		||||
        "@0x/contracts-staking": "^2.0.33",
 | 
			
		||||
        "@0x/contracts-test-utils": "^5.3.22",
 | 
			
		||||
        "@0x/sol-compiler": "^4.4.1",
 | 
			
		||||
        "@0x/contracts-asset-proxy": "^3.7.8-multiplex.0",
 | 
			
		||||
        "@0x/contracts-erc20": "^3.3.5-multiplex.0",
 | 
			
		||||
        "@0x/contracts-gen": "^2.0.32",
 | 
			
		||||
        "@0x/contracts-staking": "^2.0.34-multiplex.0",
 | 
			
		||||
        "@0x/contracts-test-utils": "^5.3.23-multiplex.0",
 | 
			
		||||
        "@0x/sol-compiler": "^4.6.1",
 | 
			
		||||
        "@0x/ts-doc-gen": "^0.0.28",
 | 
			
		||||
        "@0x/tslint-config": "^4.1.3",
 | 
			
		||||
        "@types/isomorphic-fetch": "^0.0.35",
 | 
			
		||||
@@ -72,13 +72,13 @@
 | 
			
		||||
        "typescript": "3.0.1"
 | 
			
		||||
    },
 | 
			
		||||
    "dependencies": {
 | 
			
		||||
        "@0x/base-contract": "^6.2.14",
 | 
			
		||||
        "@0x/protocol-utils": "^1.3.0",
 | 
			
		||||
        "@0x/subproviders": "^6.2.3",
 | 
			
		||||
        "@0x/base-contract": "^6.2.18",
 | 
			
		||||
        "@0x/protocol-utils": "^1.3.1-multiplex.0",
 | 
			
		||||
        "@0x/subproviders": "^6.4.1",
 | 
			
		||||
        "@0x/types": "^3.3.1",
 | 
			
		||||
        "@0x/typescript-typings": "^5.1.6",
 | 
			
		||||
        "@0x/utils": "^6.1.1",
 | 
			
		||||
        "@0x/web3-wrapper": "^7.3.0",
 | 
			
		||||
        "@0x/utils": "^6.2.0",
 | 
			
		||||
        "@0x/web3-wrapper": "^7.4.1",
 | 
			
		||||
        "ethereum-types": "^3.4.0",
 | 
			
		||||
        "ethereumjs-util": "^5.1.1"
 | 
			
		||||
    },
 | 
			
		||||
 
 | 
			
		||||
@@ -580,4 +580,47 @@ blockchainTests.resets('Treasury governance', env => {
 | 
			
		||||
            expect(await weth.balanceOf(staking.address).callAsync()).to.bignumber.equal(wethAmount);
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
    describe('Can update thresholds via proposal', () => {
 | 
			
		||||
        it('Updates proposal and quorum thresholds', async () => {
 | 
			
		||||
            // Delegator has enough ZRX to create and pass a proposal
 | 
			
		||||
            await staking.stake(TREASURY_PARAMS.quorumThreshold).awaitTransactionSuccessAsync({ from: delegator });
 | 
			
		||||
            await staking
 | 
			
		||||
                .moveStake(
 | 
			
		||||
                    new StakeInfo(StakeStatus.Undelegated),
 | 
			
		||||
                    new StakeInfo(StakeStatus.Delegated, defaultPoolId),
 | 
			
		||||
                    TREASURY_PARAMS.quorumThreshold,
 | 
			
		||||
                )
 | 
			
		||||
                .awaitTransactionSuccessAsync({ from: delegator });
 | 
			
		||||
            await fastForwardToNextEpochAsync();
 | 
			
		||||
            const currentEpoch = await staking.currentEpoch().callAsync();
 | 
			
		||||
            const newProposalThreshold = new BigNumber(420);
 | 
			
		||||
            const newQuorumThreshold = new BigNumber(1337);
 | 
			
		||||
            const updateThresholdsAction = {
 | 
			
		||||
                target: treasury.address,
 | 
			
		||||
                data: treasury
 | 
			
		||||
                    .updateThresholds(newProposalThreshold, newQuorumThreshold)
 | 
			
		||||
                    .getABIEncodedTransactionData(),
 | 
			
		||||
                value: constants.ZERO_AMOUNT,
 | 
			
		||||
            };
 | 
			
		||||
            const tx = treasury.propose(
 | 
			
		||||
                [updateThresholdsAction],
 | 
			
		||||
                currentEpoch.plus(3),
 | 
			
		||||
                `Updates proposal threshold to ${newProposalThreshold} and quorum threshold to ${newQuorumThreshold}`,
 | 
			
		||||
                [],
 | 
			
		||||
            );
 | 
			
		||||
            const proposalId = await tx.callAsync({ from: delegator });
 | 
			
		||||
            await tx.awaitTransactionSuccessAsync({ from: delegator });
 | 
			
		||||
            await fastForwardToNextEpochAsync();
 | 
			
		||||
            await fastForwardToNextEpochAsync();
 | 
			
		||||
            await treasury.castVote(proposalId, true, []).awaitTransactionSuccessAsync({ from: delegator });
 | 
			
		||||
            await fastForwardToNextEpochAsync();
 | 
			
		||||
            await treasury
 | 
			
		||||
                .execute(proposalId, [updateThresholdsAction])
 | 
			
		||||
                .awaitTransactionSuccessAsync({ from: delegator });
 | 
			
		||||
            const proposalThreshold = await treasury.proposalThreshold().callAsync();
 | 
			
		||||
            const quorumThreshold = await treasury.quorumThreshold().callAsync();
 | 
			
		||||
            expect(proposalThreshold).to.bignumber.equal(newProposalThreshold);
 | 
			
		||||
            expect(quorumThreshold).to.bignumber.equal(newQuorumThreshold);
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
});
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,13 @@
 | 
			
		||||
[
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1615932869,
 | 
			
		||||
        "version": "4.7.5-multiplex.0",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Dependencies updated"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1614141718,
 | 
			
		||||
        "version": "4.7.4",
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
 | 
			
		||||
 | 
			
		||||
CHANGELOG
 | 
			
		||||
 | 
			
		||||
## v4.7.5-multiplex.0 - _March 16, 2021_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 | 
			
		||||
## v4.7.4 - _February 24, 2021_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
    "name": "@0x/contracts-utils",
 | 
			
		||||
    "version": "4.7.4",
 | 
			
		||||
    "version": "4.7.5-multiplex.0",
 | 
			
		||||
    "engines": {
 | 
			
		||||
        "node": ">=6.12"
 | 
			
		||||
    },
 | 
			
		||||
@@ -50,12 +50,12 @@
 | 
			
		||||
    },
 | 
			
		||||
    "homepage": "https://github.com/0xProject/protocol/tree/main/contracts/utils",
 | 
			
		||||
    "devDependencies": {
 | 
			
		||||
        "@0x/abi-gen": "^5.4.19",
 | 
			
		||||
        "@0x/contracts-gen": "^2.0.30",
 | 
			
		||||
        "@0x/contracts-test-utils": "^5.3.22",
 | 
			
		||||
        "@0x/abi-gen": "^5.4.21",
 | 
			
		||||
        "@0x/contracts-gen": "^2.0.32",
 | 
			
		||||
        "@0x/contracts-test-utils": "^5.3.23-multiplex.0",
 | 
			
		||||
        "@0x/dev-utils": "^4.2.1",
 | 
			
		||||
        "@0x/order-utils": "^10.4.17",
 | 
			
		||||
        "@0x/sol-compiler": "^4.5.2",
 | 
			
		||||
        "@0x/order-utils": "^10.4.18-multiplex.0",
 | 
			
		||||
        "@0x/sol-compiler": "^4.6.1",
 | 
			
		||||
        "@0x/tslint-config": "^4.1.3",
 | 
			
		||||
        "@0x/types": "^3.3.1",
 | 
			
		||||
        "@0x/web3-wrapper": "^7.4.1",
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,26 @@
 | 
			
		||||
[
 | 
			
		||||
    {
 | 
			
		||||
        "version": "0.20.0-multiplex",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Add `MooniswapLiquidityProvider`",
 | 
			
		||||
                "pr": 143
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Emit `LiquidityProviderFill` event in `CurveLiquidityProvider`",
 | 
			
		||||
                "pr": 143
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Add BatchFillNativeOrdersFeature and MultiplexFeature",
 | 
			
		||||
                "pr": 140
 | 
			
		||||
            },
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Export MultiplexFeatureContract",
 | 
			
		||||
                "pr": 168
 | 
			
		||||
            }
 | 
			
		||||
        ],
 | 
			
		||||
        "timestamp": 1615932869
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "version": "0.19.0",
 | 
			
		||||
        "changes": [
 | 
			
		||||
 
 | 
			
		||||
@@ -5,6 +5,13 @@ Edit the package's CHANGELOG.json file only.
 | 
			
		||||
 | 
			
		||||
CHANGELOG
 | 
			
		||||
 | 
			
		||||
## v0.20.0-multiplex - _March 16, 2021_
 | 
			
		||||
 | 
			
		||||
    * Add `MooniswapLiquidityProvider` (#143)
 | 
			
		||||
    * Emit `LiquidityProviderFill` event in `CurveLiquidityProvider` (#143)
 | 
			
		||||
    * Add BatchFillNativeOrdersFeature and MultiplexFeature (#140)
 | 
			
		||||
    * Export MultiplexFeatureContract (#168)
 | 
			
		||||
 | 
			
		||||
## v0.19.0 - _February 24, 2021_
 | 
			
		||||
 | 
			
		||||
    * Add `CurveLiquidityProvider` and misc refactors (#127)
 | 
			
		||||
 
 | 
			
		||||
@@ -20,14 +20,16 @@
 | 
			
		||||
pragma solidity ^0.6.5;
 | 
			
		||||
pragma experimental ABIEncoderV2;
 | 
			
		||||
 | 
			
		||||
import "./features/IOwnableFeature.sol";
 | 
			
		||||
import "./features/ISimpleFunctionRegistryFeature.sol";
 | 
			
		||||
import "./features/ITokenSpenderFeature.sol";
 | 
			
		||||
import "./features/ITransformERC20Feature.sol";
 | 
			
		||||
import "./features/IMetaTransactionsFeature.sol";
 | 
			
		||||
import "./features/IUniswapFeature.sol";
 | 
			
		||||
import "./features/ILiquidityProviderFeature.sol";
 | 
			
		||||
import "./features/INativeOrdersFeature.sol";
 | 
			
		||||
import "./features/interfaces/IOwnableFeature.sol";
 | 
			
		||||
import "./features/interfaces/ISimpleFunctionRegistryFeature.sol";
 | 
			
		||||
import "./features/interfaces/ITokenSpenderFeature.sol";
 | 
			
		||||
import "./features/interfaces/ITransformERC20Feature.sol";
 | 
			
		||||
import "./features/interfaces/IMetaTransactionsFeature.sol";
 | 
			
		||||
import "./features/interfaces/IUniswapFeature.sol";
 | 
			
		||||
import "./features/interfaces/ILiquidityProviderFeature.sol";
 | 
			
		||||
import "./features/interfaces/INativeOrdersFeature.sol";
 | 
			
		||||
import "./features/interfaces/IBatchFillNativeOrdersFeature.sol";
 | 
			
		||||
import "./features/interfaces/IMultiplexFeature.sol";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/// @dev Interface for a fully featured Exchange Proxy.
 | 
			
		||||
@@ -39,7 +41,9 @@ interface IZeroEx is
 | 
			
		||||
    IMetaTransactionsFeature,
 | 
			
		||||
    IUniswapFeature,
 | 
			
		||||
    ILiquidityProviderFeature,
 | 
			
		||||
    INativeOrdersFeature
 | 
			
		||||
    INativeOrdersFeature,
 | 
			
		||||
    IBatchFillNativeOrdersFeature,
 | 
			
		||||
    IMultiplexFeature
 | 
			
		||||
{
 | 
			
		||||
    // solhint-disable state-visibility
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -170,4 +170,21 @@ library LibNativeOrdersRichErrors {
 | 
			
		||||
            maker
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function BatchFillIncompleteError(
 | 
			
		||||
        bytes32 orderHash,
 | 
			
		||||
        uint256 takerTokenFilledAmount,
 | 
			
		||||
        uint256 takerTokenFillAmount
 | 
			
		||||
    )
 | 
			
		||||
        internal
 | 
			
		||||
        pure
 | 
			
		||||
        returns (bytes memory)
 | 
			
		||||
    {
 | 
			
		||||
        return abi.encodeWithSelector(
 | 
			
		||||
            bytes4(keccak256("BatchFillIncompleteError(bytes32,uint256,uint256)")),
 | 
			
		||||
            orderHash,
 | 
			
		||||
            takerTokenFilledAmount,
 | 
			
		||||
            takerTokenFillAmount
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,198 @@
 | 
			
		||||
// SPDX-License-Identifier: Apache-2.0
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  Copyright 2021 ZeroEx Intl.
 | 
			
		||||
 | 
			
		||||
  Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
  you may not use this file except in compliance with the License.
 | 
			
		||||
  You may obtain a copy of the License at
 | 
			
		||||
 | 
			
		||||
    http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 | 
			
		||||
  Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
  distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
  See the License for the specific language governing permissions and
 | 
			
		||||
  limitations under the License.
 | 
			
		||||
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
pragma solidity ^0.6.5;
 | 
			
		||||
pragma experimental ABIEncoderV2;
 | 
			
		||||
 | 
			
		||||
import "@0x/contracts-utils/contracts/src/v06/errors/LibRichErrorsV06.sol";
 | 
			
		||||
import "@0x/contracts-utils/contracts/src/v06/LibSafeMathV06.sol";
 | 
			
		||||
import "@0x/contracts-utils/contracts/src/v06/LibMathV06.sol";
 | 
			
		||||
import "../errors/LibNativeOrdersRichErrors.sol";
 | 
			
		||||
import "../fixins/FixinCommon.sol";
 | 
			
		||||
import "../fixins/FixinEIP712.sol";
 | 
			
		||||
import "../migrations/LibMigrate.sol";
 | 
			
		||||
import "./interfaces/IFeature.sol";
 | 
			
		||||
import "./interfaces/IBatchFillNativeOrdersFeature.sol";
 | 
			
		||||
import "./interfaces/INativeOrdersFeature.sol";
 | 
			
		||||
import "./libs/LibNativeOrder.sol";
 | 
			
		||||
import "./libs/LibSignature.sol";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/// @dev Feature for batch/market filling limit and RFQ orders.
 | 
			
		||||
contract BatchFillNativeOrdersFeature is
 | 
			
		||||
    IFeature,
 | 
			
		||||
    IBatchFillNativeOrdersFeature,
 | 
			
		||||
    FixinCommon,
 | 
			
		||||
    FixinEIP712
 | 
			
		||||
{
 | 
			
		||||
    using LibSafeMathV06 for uint128;
 | 
			
		||||
    using LibSafeMathV06 for uint256;
 | 
			
		||||
    using LibRichErrorsV06 for bytes;
 | 
			
		||||
 | 
			
		||||
    /// @dev Name of this feature.
 | 
			
		||||
    string public constant override FEATURE_NAME = "BatchFill";
 | 
			
		||||
    /// @dev Version of this feature.
 | 
			
		||||
    uint256 public immutable override FEATURE_VERSION = _encodeVersion(1, 0, 0);
 | 
			
		||||
 | 
			
		||||
    constructor(address zeroExAddress)
 | 
			
		||||
        public
 | 
			
		||||
        FixinEIP712(zeroExAddress)
 | 
			
		||||
    {
 | 
			
		||||
        // solhint-disable no-empty-blocks
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Initialize and register this feature.
 | 
			
		||||
    ///      Should be delegatecalled by `Migrate.migrate()`.
 | 
			
		||||
    /// @return success `LibMigrate.SUCCESS` on success.
 | 
			
		||||
    function migrate()
 | 
			
		||||
        external
 | 
			
		||||
        returns (bytes4 success)
 | 
			
		||||
    {
 | 
			
		||||
        _registerFeatureFunction(this.batchFillLimitOrders.selector);
 | 
			
		||||
        _registerFeatureFunction(this.batchFillRfqOrders.selector);
 | 
			
		||||
        return LibMigrate.MIGRATE_SUCCESS;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Fills multiple limit orders.
 | 
			
		||||
    /// @param orders Array of limit orders.
 | 
			
		||||
    /// @param signatures Array of signatures corresponding to each order.
 | 
			
		||||
    /// @param takerTokenFillAmounts Array of desired amounts to fill each order.
 | 
			
		||||
    /// @param revertIfIncomplete If true, reverts if this function fails to
 | 
			
		||||
    ///        fill the full fill amount for any individual order.
 | 
			
		||||
    /// @return takerTokenFilledAmounts Array of amounts filled, in taker token.
 | 
			
		||||
    /// @return makerTokenFilledAmounts Array of amounts filled, in maker token.
 | 
			
		||||
    function batchFillLimitOrders(
 | 
			
		||||
        LibNativeOrder.LimitOrder[] calldata orders,
 | 
			
		||||
        LibSignature.Signature[] calldata signatures,
 | 
			
		||||
        uint128[] calldata takerTokenFillAmounts,
 | 
			
		||||
        bool revertIfIncomplete
 | 
			
		||||
    )
 | 
			
		||||
        external
 | 
			
		||||
        payable
 | 
			
		||||
        override
 | 
			
		||||
        returns (
 | 
			
		||||
            uint128[] memory takerTokenFilledAmounts,
 | 
			
		||||
            uint128[] memory makerTokenFilledAmounts
 | 
			
		||||
        )
 | 
			
		||||
    {
 | 
			
		||||
        require(
 | 
			
		||||
            orders.length == signatures.length && orders.length == takerTokenFillAmounts.length,
 | 
			
		||||
            'BatchFillNativeOrdersFeature::batchFillLimitOrders/MISMATCHED_ARRAY_LENGTHS'
 | 
			
		||||
        );
 | 
			
		||||
        takerTokenFilledAmounts = new uint128[](orders.length);
 | 
			
		||||
        makerTokenFilledAmounts = new uint128[](orders.length);
 | 
			
		||||
        uint256 protocolFee = uint256(INativeOrdersFeature(address(this)).getProtocolFeeMultiplier())
 | 
			
		||||
            .safeMul(tx.gasprice);
 | 
			
		||||
        uint256 ethProtocolFeePaid;
 | 
			
		||||
        for (uint256 i = 0; i != orders.length; i++) {
 | 
			
		||||
            try
 | 
			
		||||
                INativeOrdersFeature(address(this))._fillLimitOrder
 | 
			
		||||
                    (
 | 
			
		||||
                        orders[i],
 | 
			
		||||
                        signatures[i],
 | 
			
		||||
                        takerTokenFillAmounts[i],
 | 
			
		||||
                        msg.sender,
 | 
			
		||||
                        msg.sender
 | 
			
		||||
                    )
 | 
			
		||||
                returns (uint128 takerTokenFilledAmount, uint128 makerTokenFilledAmount)
 | 
			
		||||
            {
 | 
			
		||||
                // Update amounts filled.
 | 
			
		||||
                (takerTokenFilledAmounts[i], makerTokenFilledAmounts[i]) =
 | 
			
		||||
                    (takerTokenFilledAmount, makerTokenFilledAmount);
 | 
			
		||||
                ethProtocolFeePaid = ethProtocolFeePaid.safeAdd(protocolFee);
 | 
			
		||||
            } catch {}
 | 
			
		||||
 | 
			
		||||
            if (
 | 
			
		||||
                revertIfIncomplete &&
 | 
			
		||||
                takerTokenFilledAmounts[i] < takerTokenFillAmounts[i]
 | 
			
		||||
            ) {
 | 
			
		||||
                bytes32 orderHash = _getEIP712Hash(
 | 
			
		||||
                    LibNativeOrder.getLimitOrderStructHash(orders[i])
 | 
			
		||||
                );
 | 
			
		||||
                // Did not fill the amount requested.
 | 
			
		||||
                LibNativeOrdersRichErrors.BatchFillIncompleteError(
 | 
			
		||||
                    orderHash,
 | 
			
		||||
                    takerTokenFilledAmounts[i],
 | 
			
		||||
                    takerTokenFillAmounts[i]
 | 
			
		||||
                ).rrevert();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        LibNativeOrder.refundExcessProtocolFeeToSender(ethProtocolFeePaid);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Fills multiple RFQ orders.
 | 
			
		||||
    /// @param orders Array of RFQ orders.
 | 
			
		||||
    /// @param signatures Array of signatures corresponding to each order.
 | 
			
		||||
    /// @param takerTokenFillAmounts Array of desired amounts to fill each order.
 | 
			
		||||
    /// @param revertIfIncomplete If true, reverts if this function fails to
 | 
			
		||||
    ///        fill the full fill amount for any individual order.
 | 
			
		||||
    /// @return takerTokenFilledAmounts Array of amounts filled, in taker token.
 | 
			
		||||
    /// @return makerTokenFilledAmounts Array of amounts filled, in maker token.
 | 
			
		||||
    function batchFillRfqOrders(
 | 
			
		||||
        LibNativeOrder.RfqOrder[] calldata orders,
 | 
			
		||||
        LibSignature.Signature[] calldata signatures,
 | 
			
		||||
        uint128[] calldata takerTokenFillAmounts,
 | 
			
		||||
        bool revertIfIncomplete
 | 
			
		||||
    )
 | 
			
		||||
        external
 | 
			
		||||
        override
 | 
			
		||||
        returns (
 | 
			
		||||
            uint128[] memory takerTokenFilledAmounts,
 | 
			
		||||
            uint128[] memory makerTokenFilledAmounts
 | 
			
		||||
        )
 | 
			
		||||
    {
 | 
			
		||||
        require(
 | 
			
		||||
            orders.length == signatures.length && orders.length == takerTokenFillAmounts.length,
 | 
			
		||||
            'BatchFillNativeOrdersFeature::batchFillRfqOrders/MISMATCHED_ARRAY_LENGTHS'
 | 
			
		||||
        );
 | 
			
		||||
        takerTokenFilledAmounts = new uint128[](orders.length);
 | 
			
		||||
        makerTokenFilledAmounts = new uint128[](orders.length);
 | 
			
		||||
        for (uint256 i = 0; i != orders.length; i++) {
 | 
			
		||||
            try
 | 
			
		||||
                INativeOrdersFeature(address(this))._fillRfqOrder
 | 
			
		||||
                    (
 | 
			
		||||
                        orders[i],
 | 
			
		||||
                        signatures[i],
 | 
			
		||||
                        takerTokenFillAmounts[i],
 | 
			
		||||
                        msg.sender
 | 
			
		||||
                    )
 | 
			
		||||
                returns (uint128 takerTokenFilledAmount, uint128 makerTokenFilledAmount)
 | 
			
		||||
            {
 | 
			
		||||
                // Update amounts filled.
 | 
			
		||||
                (takerTokenFilledAmounts[i], makerTokenFilledAmounts[i]) =
 | 
			
		||||
                    (takerTokenFilledAmount, makerTokenFilledAmount);
 | 
			
		||||
            } catch {}
 | 
			
		||||
 | 
			
		||||
            if (
 | 
			
		||||
                revertIfIncomplete &&
 | 
			
		||||
                takerTokenFilledAmounts[i] < takerTokenFillAmounts[i]
 | 
			
		||||
            ) {
 | 
			
		||||
                // Did not fill the amount requested.
 | 
			
		||||
                bytes32 orderHash = _getEIP712Hash(
 | 
			
		||||
                    LibNativeOrder.getRfqOrderStructHash(orders[i])
 | 
			
		||||
                );
 | 
			
		||||
                LibNativeOrdersRichErrors.BatchFillIncompleteError(
 | 
			
		||||
                    orderHash,
 | 
			
		||||
                    takerTokenFilledAmounts[i],
 | 
			
		||||
                    takerTokenFillAmounts[i]
 | 
			
		||||
                ).rrevert();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -23,7 +23,7 @@ pragma experimental ABIEncoderV2;
 | 
			
		||||
import "@0x/contracts-utils/contracts/src/v06/errors/LibRichErrorsV06.sol";
 | 
			
		||||
import "../migrations/LibBootstrap.sol";
 | 
			
		||||
import "../storage/LibProxyStorage.sol";
 | 
			
		||||
import "./IBootstrapFeature.sol";
 | 
			
		||||
import "./interfaces/IBootstrapFeature.sol";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/// @dev Detachable `bootstrap()` feature.
 | 
			
		||||
 
 | 
			
		||||
@@ -31,8 +31,8 @@ import "../fixins/FixinCommon.sol";
 | 
			
		||||
import "../fixins/FixinTokenSpender.sol";
 | 
			
		||||
import "../migrations/LibMigrate.sol";
 | 
			
		||||
import "../transformers/LibERC20Transformer.sol";
 | 
			
		||||
import "./IFeature.sol";
 | 
			
		||||
import "./ILiquidityProviderFeature.sol";
 | 
			
		||||
import "./interfaces/IFeature.sol";
 | 
			
		||||
import "./interfaces/ILiquidityProviderFeature.sol";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
contract LiquidityProviderFeature is
 | 
			
		||||
 
 | 
			
		||||
@@ -30,11 +30,11 @@ import "../fixins/FixinTokenSpender.sol";
 | 
			
		||||
import "../fixins/FixinEIP712.sol";
 | 
			
		||||
import "../migrations/LibMigrate.sol";
 | 
			
		||||
import "../storage/LibMetaTransactionsStorage.sol";
 | 
			
		||||
import "./IMetaTransactionsFeature.sol";
 | 
			
		||||
import "./ITransformERC20Feature.sol";
 | 
			
		||||
import "./interfaces/IFeature.sol";
 | 
			
		||||
import "./interfaces/IMetaTransactionsFeature.sol";
 | 
			
		||||
import "./interfaces/INativeOrdersFeature.sol";
 | 
			
		||||
import "./interfaces/ITransformERC20Feature.sol";
 | 
			
		||||
import "./libs/LibSignature.sol";
 | 
			
		||||
import "./IFeature.sol";
 | 
			
		||||
import "./INativeOrdersFeature.sol";
 | 
			
		||||
 | 
			
		||||
/// @dev MetaTransactions feature.
 | 
			
		||||
contract MetaTransactionsFeature is
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										805
									
								
								contracts/zero-ex/contracts/src/features/MultiplexFeature.sol
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										805
									
								
								contracts/zero-ex/contracts/src/features/MultiplexFeature.sol
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,805 @@
 | 
			
		||||
// SPDX-License-Identifier: Apache-2.0
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  Copyright 2021 ZeroEx Intl.
 | 
			
		||||
 | 
			
		||||
  Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
  you may not use this file except in compliance with the License.
 | 
			
		||||
  You may obtain a copy of the License at
 | 
			
		||||
 | 
			
		||||
    http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 | 
			
		||||
  Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
  distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
  See the License for the specific language governing permissions and
 | 
			
		||||
  limitations under the License.
 | 
			
		||||
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
pragma solidity ^0.6.5;
 | 
			
		||||
pragma experimental ABIEncoderV2;
 | 
			
		||||
 | 
			
		||||
import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol";
 | 
			
		||||
import "@0x/contracts-erc20/contracts/src/v06/IEtherTokenV06.sol";
 | 
			
		||||
import "@0x/contracts-utils/contracts/src/v06/LibMathV06.sol";
 | 
			
		||||
import "@0x/contracts-utils/contracts/src/v06/LibSafeMathV06.sol";
 | 
			
		||||
import "../external/ILiquidityProviderSandbox.sol";
 | 
			
		||||
import "../fixins/FixinCommon.sol";
 | 
			
		||||
import "../fixins/FixinEIP712.sol";
 | 
			
		||||
import "../fixins/FixinTokenSpender.sol";
 | 
			
		||||
import "../migrations/LibMigrate.sol";
 | 
			
		||||
import "../transformers/LibERC20Transformer.sol";
 | 
			
		||||
import "../vendor/ILiquidityProvider.sol";
 | 
			
		||||
import "../vendor/IUniswapV2Pair.sol";
 | 
			
		||||
import "./interfaces/IFeature.sol";
 | 
			
		||||
import "./interfaces/IMultiplexFeature.sol";
 | 
			
		||||
import "./interfaces/INativeOrdersFeature.sol";
 | 
			
		||||
import "./interfaces/ITransformERC20Feature.sol";
 | 
			
		||||
import "./libs/LibNativeOrder.sol";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/// @dev This feature enables efficient batch and multi-hop trades
 | 
			
		||||
///      using different liquidity sources.
 | 
			
		||||
contract MultiplexFeature is
 | 
			
		||||
    IFeature,
 | 
			
		||||
    IMultiplexFeature,
 | 
			
		||||
    FixinCommon,
 | 
			
		||||
    FixinEIP712,
 | 
			
		||||
    FixinTokenSpender
 | 
			
		||||
{
 | 
			
		||||
    using LibERC20Transformer for IERC20TokenV06;
 | 
			
		||||
    using LibSafeMathV06 for uint128;
 | 
			
		||||
    using LibSafeMathV06 for uint256;
 | 
			
		||||
 | 
			
		||||
    /// @dev Name of this feature.
 | 
			
		||||
    string public constant override FEATURE_NAME = "MultiplexFeature";
 | 
			
		||||
    /// @dev Version of this feature.
 | 
			
		||||
    uint256 public immutable override FEATURE_VERSION = _encodeVersion(1, 0, 0);
 | 
			
		||||
 | 
			
		||||
    /// @dev The WETH token contract.
 | 
			
		||||
    IEtherTokenV06 private immutable weth;
 | 
			
		||||
    /// @dev The sandbox contract address.
 | 
			
		||||
    ILiquidityProviderSandbox public immutable sandbox;
 | 
			
		||||
    // address of the UniswapV2Factory contract.
 | 
			
		||||
    address private constant UNISWAP_FACTORY = 0x5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f;
 | 
			
		||||
    // address of the (Sushiswap) UniswapV2Factory contract.
 | 
			
		||||
    address private constant SUSHISWAP_FACTORY = 0xC0AEe478e3658e2610c5F7A4A2E1777cE9e4f2Ac;
 | 
			
		||||
    // Init code hash of the UniswapV2Pair contract.
 | 
			
		||||
    uint256 private constant UNISWAP_PAIR_INIT_CODE_HASH = 0x96e8ac4277198ff8b6f785478aa9a39f403cb768dd02cbee326c3e7da348845f;
 | 
			
		||||
    // Init code hash of the (Sushiswap) UniswapV2Pair contract.
 | 
			
		||||
    uint256 private constant SUSHISWAP_PAIR_INIT_CODE_HASH = 0xe18a34eb0e04b04f7a0ac29a6e80748dca96319b42c54d679cb821dca90c6303;
 | 
			
		||||
 | 
			
		||||
    constructor(
 | 
			
		||||
        address zeroExAddress,
 | 
			
		||||
        IEtherTokenV06 weth_,
 | 
			
		||||
        ILiquidityProviderSandbox sandbox_,
 | 
			
		||||
        bytes32 greedyTokensBloomFilter
 | 
			
		||||
    )
 | 
			
		||||
        public
 | 
			
		||||
        FixinEIP712(zeroExAddress)
 | 
			
		||||
        FixinTokenSpender(greedyTokensBloomFilter)
 | 
			
		||||
    {
 | 
			
		||||
        weth = weth_;
 | 
			
		||||
        sandbox = sandbox_;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Initialize and register this feature.
 | 
			
		||||
    ///      Should be delegatecalled by `Migrate.migrate()`.
 | 
			
		||||
    /// @return success `LibMigrate.SUCCESS` on success.
 | 
			
		||||
    function migrate()
 | 
			
		||||
        external
 | 
			
		||||
        returns (bytes4 success)
 | 
			
		||||
    {
 | 
			
		||||
        _registerFeatureFunction(this.batchFill.selector);
 | 
			
		||||
        _registerFeatureFunction(this.multiHopFill.selector);
 | 
			
		||||
        return LibMigrate.MIGRATE_SUCCESS;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Executes a batch of fills selling `fillData.inputToken`
 | 
			
		||||
    ///      for `fillData.outputToken` in sequence. Refer to the
 | 
			
		||||
    ///      internal variant `_batchFill` for the allowed nested
 | 
			
		||||
    ///      operations.
 | 
			
		||||
    /// @param fillData Encodes the input/output tokens, the sell
 | 
			
		||||
    ///        amount, and the nested operations for this batch fill.
 | 
			
		||||
    /// @param minBuyAmount The minimum amount of `fillData.outputToken`
 | 
			
		||||
    ///        to buy. Reverts if this amount is not met.
 | 
			
		||||
    /// @return outputTokenAmount The amount of the output token bought.
 | 
			
		||||
    function batchFill(
 | 
			
		||||
        BatchFillData memory fillData,
 | 
			
		||||
        uint256 minBuyAmount
 | 
			
		||||
    )
 | 
			
		||||
        public
 | 
			
		||||
        payable
 | 
			
		||||
        override
 | 
			
		||||
        returns (uint256 outputTokenAmount)
 | 
			
		||||
    {
 | 
			
		||||
        // Cache the sender's balance of the output token.
 | 
			
		||||
        outputTokenAmount = fillData.outputToken.getTokenBalanceOf(msg.sender);
 | 
			
		||||
        // Cache the contract's ETH balance prior to this call.
 | 
			
		||||
        uint256 ethBalanceBefore = address(this).balance.safeSub(msg.value);
 | 
			
		||||
 | 
			
		||||
        // Perform the batch fill.
 | 
			
		||||
        _batchFill(fillData);
 | 
			
		||||
 | 
			
		||||
        // The `outputTokenAmount` returned by `_batchFill` may not
 | 
			
		||||
        // be fully accurate (e.g. due to some janky token).
 | 
			
		||||
        outputTokenAmount = fillData.outputToken.getTokenBalanceOf(msg.sender)
 | 
			
		||||
            .safeSub(outputTokenAmount);
 | 
			
		||||
        require(
 | 
			
		||||
            outputTokenAmount >= minBuyAmount,
 | 
			
		||||
            "MultiplexFeature::batchFill/UNDERBOUGHT"
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        uint256 ethBalanceAfter = address(this).balance;
 | 
			
		||||
        require(
 | 
			
		||||
            ethBalanceAfter >= ethBalanceBefore,
 | 
			
		||||
            "MultiplexFeature::batchFill/OVERSPENT_ETH"
 | 
			
		||||
        );
 | 
			
		||||
        // Refund ETH
 | 
			
		||||
        if (ethBalanceAfter > ethBalanceBefore) {
 | 
			
		||||
            _transferEth(msg.sender, ethBalanceAfter - ethBalanceBefore);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Executes a sequence of fills "hopping" through the
 | 
			
		||||
    ///      path of tokens given by `fillData.tokens`. Refer to the
 | 
			
		||||
    ///      internal variant `_multiHopFill` for the allowed nested
 | 
			
		||||
    ///      operations.
 | 
			
		||||
    /// @param fillData Encodes the path of tokens, the sell amount,
 | 
			
		||||
    ///        and the nested operations for this multi-hop fill.
 | 
			
		||||
    /// @param minBuyAmount The minimum amount of the output token
 | 
			
		||||
    ///        to buy. Reverts if this amount is not met.
 | 
			
		||||
    /// @return outputTokenAmount The amount of the output token bought.
 | 
			
		||||
    function multiHopFill(
 | 
			
		||||
        MultiHopFillData memory fillData,
 | 
			
		||||
        uint256 minBuyAmount
 | 
			
		||||
    )
 | 
			
		||||
        public
 | 
			
		||||
        payable
 | 
			
		||||
        override
 | 
			
		||||
        returns (uint256 outputTokenAmount)
 | 
			
		||||
    {
 | 
			
		||||
        IERC20TokenV06 outputToken = IERC20TokenV06(fillData.tokens[fillData.tokens.length - 1]);
 | 
			
		||||
        // Cache the sender's balance of the output token.
 | 
			
		||||
        outputTokenAmount = outputToken.getTokenBalanceOf(msg.sender);
 | 
			
		||||
        // Cache the contract's ETH balance prior to this call.
 | 
			
		||||
        uint256 ethBalanceBefore = address(this).balance.safeSub(msg.value);
 | 
			
		||||
 | 
			
		||||
        // Perform the multi-hop fill. Pass in `msg.value` as the maximum
 | 
			
		||||
        // allowable amount of ETH for the wrapped calls to consume.
 | 
			
		||||
        _multiHopFill(fillData, msg.value);
 | 
			
		||||
 | 
			
		||||
        // The `outputTokenAmount` returned by `_multiHopFill` may not
 | 
			
		||||
        // be fully accurate (e.g. due to some janky token).
 | 
			
		||||
        outputTokenAmount = outputToken.getTokenBalanceOf(msg.sender)
 | 
			
		||||
            .safeSub(outputTokenAmount);
 | 
			
		||||
        require(
 | 
			
		||||
            outputTokenAmount >= minBuyAmount,
 | 
			
		||||
            "MultiplexFeature::multiHopFill/UNDERBOUGHT"
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        uint256 ethBalanceAfter = address(this).balance;
 | 
			
		||||
        require(
 | 
			
		||||
            ethBalanceAfter >= ethBalanceBefore,
 | 
			
		||||
            "MultiplexFeature::multiHopFill/OVERSPENT_ETH"
 | 
			
		||||
        );
 | 
			
		||||
        // Refund ETH
 | 
			
		||||
        if (ethBalanceAfter > ethBalanceBefore) {
 | 
			
		||||
            _transferEth(msg.sender, ethBalanceAfter - ethBalanceBefore);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Similar to FQT. If `fillData.sellAmount` is set to `type(uint256).max`,
 | 
			
		||||
    // this is effectively a batch fill. Otherwise it can be set to perform a
 | 
			
		||||
    // market sell of some amount. Note that the `outputTokenAmount` returned
 | 
			
		||||
    // by this function could theoretically be inaccurate if `msg.sender` has
 | 
			
		||||
    // set a token allowance on an external contract that gets called during
 | 
			
		||||
    // the execution of this function.
 | 
			
		||||
    function _batchFill(BatchFillData memory fillData)
 | 
			
		||||
        internal
 | 
			
		||||
        returns (uint256 outputTokenAmount, uint256 remainingEth)
 | 
			
		||||
    {
 | 
			
		||||
        // Track the remaining ETH allocated to this call.
 | 
			
		||||
        remainingEth = msg.value;
 | 
			
		||||
        // Track the amount of input token sold.
 | 
			
		||||
        uint256 soldAmount;
 | 
			
		||||
        for (uint256 i = 0; i != fillData.calls.length; i++) {
 | 
			
		||||
            // Check if we've hit our target.
 | 
			
		||||
            if (soldAmount >= fillData.sellAmount) { break; }
 | 
			
		||||
            WrappedBatchCall memory wrappedCall = fillData.calls[i];
 | 
			
		||||
            // Compute the fill amount.
 | 
			
		||||
            uint256 inputTokenAmount = LibSafeMathV06.min256(
 | 
			
		||||
                wrappedCall.sellAmount,
 | 
			
		||||
                fillData.sellAmount.safeSub(soldAmount)
 | 
			
		||||
            );
 | 
			
		||||
            if (wrappedCall.selector == INativeOrdersFeature._fillRfqOrder.selector) {
 | 
			
		||||
                // Decode the RFQ order and signature.
 | 
			
		||||
                (
 | 
			
		||||
                    LibNativeOrder.RfqOrder memory order,
 | 
			
		||||
                    LibSignature.Signature memory signature
 | 
			
		||||
                ) = abi.decode(
 | 
			
		||||
                    wrappedCall.data,
 | 
			
		||||
                    (LibNativeOrder.RfqOrder, LibSignature.Signature)
 | 
			
		||||
                );
 | 
			
		||||
                if (order.expiry <= uint64(block.timestamp)) {
 | 
			
		||||
                    bytes32 orderHash = _getEIP712Hash(
 | 
			
		||||
                        LibNativeOrder.getRfqOrderStructHash(order)
 | 
			
		||||
                    );
 | 
			
		||||
                    emit ExpiredRfqOrder(
 | 
			
		||||
                        orderHash,
 | 
			
		||||
                        order.maker,
 | 
			
		||||
                        order.expiry
 | 
			
		||||
                    );
 | 
			
		||||
                    continue;
 | 
			
		||||
                }
 | 
			
		||||
                require(
 | 
			
		||||
                    order.takerToken == fillData.inputToken &&
 | 
			
		||||
                    order.makerToken == fillData.outputToken,
 | 
			
		||||
                    "MultiplexFeature::_batchFill/RFQ_ORDER_INVALID_TOKENS"
 | 
			
		||||
                );
 | 
			
		||||
                // Try filling the RFQ order. Swallows reverts.
 | 
			
		||||
                try
 | 
			
		||||
                    INativeOrdersFeature(address(this))._fillRfqOrder
 | 
			
		||||
                        (
 | 
			
		||||
                            order,
 | 
			
		||||
                            signature,
 | 
			
		||||
                            inputTokenAmount.safeDowncastToUint128(),
 | 
			
		||||
                            msg.sender
 | 
			
		||||
                        )
 | 
			
		||||
                    returns (uint128 takerTokenFilledAmount, uint128 makerTokenFilledAmount)
 | 
			
		||||
                {
 | 
			
		||||
                    // Increment the sold and bought amounts.
 | 
			
		||||
                    soldAmount = soldAmount.safeAdd(takerTokenFilledAmount);
 | 
			
		||||
                    outputTokenAmount = outputTokenAmount.safeAdd(makerTokenFilledAmount);
 | 
			
		||||
                } catch {}
 | 
			
		||||
            } else if (wrappedCall.selector == this._sellToUniswap.selector) {
 | 
			
		||||
                (address[] memory tokens, bool isSushi) = abi.decode(
 | 
			
		||||
                    wrappedCall.data,
 | 
			
		||||
                    (address[], bool)
 | 
			
		||||
                );
 | 
			
		||||
                require(
 | 
			
		||||
                    tokens.length >= 2 &&
 | 
			
		||||
                    tokens[0] == address(fillData.inputToken) &&
 | 
			
		||||
                    tokens[tokens.length - 1] == address(fillData.outputToken),
 | 
			
		||||
                    "MultiplexFeature::_batchFill/UNISWAP_INVALID_TOKENS"
 | 
			
		||||
                );
 | 
			
		||||
                // Perform the Uniswap/Sushiswap trade.
 | 
			
		||||
                uint256 outputTokenAmount_  = _sellToUniswap(
 | 
			
		||||
                    tokens,
 | 
			
		||||
                    inputTokenAmount,
 | 
			
		||||
                    isSushi,
 | 
			
		||||
                    address(0),
 | 
			
		||||
                    msg.sender
 | 
			
		||||
                );
 | 
			
		||||
                // Increment the sold and bought amounts.
 | 
			
		||||
                soldAmount = soldAmount.safeAdd(inputTokenAmount);
 | 
			
		||||
                outputTokenAmount = outputTokenAmount.safeAdd(outputTokenAmount_);
 | 
			
		||||
            } else if (wrappedCall.selector == this._sellToLiquidityProvider.selector) {
 | 
			
		||||
                (address provider, bytes memory auxiliaryData) = abi.decode(
 | 
			
		||||
                    wrappedCall.data,
 | 
			
		||||
                    (address, bytes)
 | 
			
		||||
                );
 | 
			
		||||
                if (fillData.inputToken.isTokenETH()) {
 | 
			
		||||
                    inputTokenAmount = LibSafeMathV06.min256(
 | 
			
		||||
                        inputTokenAmount,
 | 
			
		||||
                        remainingEth
 | 
			
		||||
                    );
 | 
			
		||||
                    // Transfer the input ETH to the provider.
 | 
			
		||||
                    _transferEth(payable(provider), inputTokenAmount);
 | 
			
		||||
                    // Count that ETH as spent.
 | 
			
		||||
                    remainingEth -= inputTokenAmount;
 | 
			
		||||
                } else {
 | 
			
		||||
                    // Transfer input ERC20 tokens to the provider.
 | 
			
		||||
                    _transferERC20Tokens(
 | 
			
		||||
                        fillData.inputToken,
 | 
			
		||||
                        msg.sender,
 | 
			
		||||
                        provider,
 | 
			
		||||
                        inputTokenAmount
 | 
			
		||||
                    );
 | 
			
		||||
                }
 | 
			
		||||
                // Perform the PLP trade.
 | 
			
		||||
                uint256 outputTokenAmount_ = _sellToLiquidityProvider(
 | 
			
		||||
                    fillData.inputToken,
 | 
			
		||||
                    fillData.outputToken,
 | 
			
		||||
                    inputTokenAmount,
 | 
			
		||||
                    ILiquidityProvider(provider),
 | 
			
		||||
                    msg.sender,
 | 
			
		||||
                    auxiliaryData
 | 
			
		||||
                );
 | 
			
		||||
                // Increment the sold and bought amounts.
 | 
			
		||||
                soldAmount = soldAmount.safeAdd(inputTokenAmount);
 | 
			
		||||
                outputTokenAmount = outputTokenAmount.safeAdd(outputTokenAmount_);
 | 
			
		||||
            } else if (wrappedCall.selector == ITransformERC20Feature._transformERC20.selector) {
 | 
			
		||||
                ITransformERC20Feature.TransformERC20Args memory args;
 | 
			
		||||
                args.taker = msg.sender;
 | 
			
		||||
                args.inputToken = fillData.inputToken;
 | 
			
		||||
                args.outputToken = fillData.outputToken;
 | 
			
		||||
                args.inputTokenAmount = inputTokenAmount;
 | 
			
		||||
                args.minOutputTokenAmount = 0;
 | 
			
		||||
                uint256 ethValue;
 | 
			
		||||
                (args.transformations, ethValue) = abi.decode(
 | 
			
		||||
                    wrappedCall.data,
 | 
			
		||||
                    (ITransformERC20Feature.Transformation[], uint256)
 | 
			
		||||
                );
 | 
			
		||||
                // Do not spend more than the remaining ETH.
 | 
			
		||||
                ethValue = LibSafeMathV06.min256(
 | 
			
		||||
                    ethValue,
 | 
			
		||||
                    remainingEth
 | 
			
		||||
                );
 | 
			
		||||
                if (ethValue > 0) {
 | 
			
		||||
                    require(
 | 
			
		||||
                        args.inputToken.isTokenETH(),
 | 
			
		||||
                        "MultiplexFeature::_batchFill/ETH_TRANSFORM_ONLY"
 | 
			
		||||
                    );
 | 
			
		||||
                }
 | 
			
		||||
                try ITransformERC20Feature(address(this))._transformERC20
 | 
			
		||||
                    {value: ethValue}
 | 
			
		||||
                    (args)
 | 
			
		||||
                    returns (uint256 outputTokenAmount_)
 | 
			
		||||
                {
 | 
			
		||||
                    remainingEth -= ethValue;
 | 
			
		||||
                    soldAmount = soldAmount.safeAdd(inputTokenAmount);
 | 
			
		||||
                    outputTokenAmount = outputTokenAmount.safeAdd(outputTokenAmount_);
 | 
			
		||||
                } catch {}
 | 
			
		||||
            } else if (wrappedCall.selector == this._multiHopFill.selector) {
 | 
			
		||||
                MultiHopFillData memory multiHopFillData;
 | 
			
		||||
                uint256 ethValue;
 | 
			
		||||
                (
 | 
			
		||||
                    multiHopFillData.tokens,
 | 
			
		||||
                    multiHopFillData.calls,
 | 
			
		||||
                    ethValue
 | 
			
		||||
                ) = abi.decode(
 | 
			
		||||
                    wrappedCall.data,
 | 
			
		||||
                    (address[], WrappedMultiHopCall[], uint256)
 | 
			
		||||
                );
 | 
			
		||||
                multiHopFillData.sellAmount = inputTokenAmount;
 | 
			
		||||
                // Do not spend more than the remaining ETH.
 | 
			
		||||
                ethValue = LibSafeMathV06.min256(
 | 
			
		||||
                    ethValue,
 | 
			
		||||
                    remainingEth
 | 
			
		||||
                );
 | 
			
		||||
                // Subtract the ethValue allocated to the nested multi-hop fill.
 | 
			
		||||
                remainingEth -= ethValue;
 | 
			
		||||
                (uint256 outputTokenAmount_, uint256 leftoverEth) =
 | 
			
		||||
                    _multiHopFill(multiHopFillData, ethValue);
 | 
			
		||||
                // Increment the sold and bought amounts.
 | 
			
		||||
                soldAmount = soldAmount.safeAdd(inputTokenAmount);
 | 
			
		||||
                outputTokenAmount = outputTokenAmount.safeAdd(outputTokenAmount_);
 | 
			
		||||
                // Add back any ETH that wasn't used by the nested multi-hop fill.
 | 
			
		||||
                remainingEth += leftoverEth;
 | 
			
		||||
            } else {
 | 
			
		||||
                revert("MultiplexFeature::_batchFill/UNRECOGNIZED_SELECTOR");
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Internal variant of `multiHopFill`. This function can be nested within
 | 
			
		||||
    // a `_batchFill`.
 | 
			
		||||
    // This function executes a sequence of fills "hopping" through the
 | 
			
		||||
    // path of tokens given by `fillData.tokens`. The nested operations that
 | 
			
		||||
    // can be used as "hops" are:
 | 
			
		||||
    // - WETH.deposit (wraps ETH)
 | 
			
		||||
    // - WETH.withdraw (unwraps WETH)
 | 
			
		||||
    // - _sellToUniswap (executes a Uniswap/Sushiswap swap)
 | 
			
		||||
    // - _sellToLiquidityProvider (executes a PLP swap)
 | 
			
		||||
    // - _transformERC20 (executes arbitrary ERC20 Transformations)
 | 
			
		||||
    // This function optimizes the number of ERC20 transfers performed
 | 
			
		||||
    // by having each hop transfer its output tokens directly to the
 | 
			
		||||
    // target address of the next hop. Note that the `outputTokenAmount` returned
 | 
			
		||||
    // by this function could theoretically be inaccurate if `msg.sender` has
 | 
			
		||||
    // set a token allowance on an external contract that gets called during
 | 
			
		||||
    // the execution of this function.
 | 
			
		||||
    function _multiHopFill(MultiHopFillData memory fillData, uint256 totalEth)
 | 
			
		||||
        public
 | 
			
		||||
        returns (uint256 outputTokenAmount, uint256 remainingEth)
 | 
			
		||||
    {
 | 
			
		||||
        // There should be one call/hop between every two tokens
 | 
			
		||||
        // in the path.
 | 
			
		||||
        // tokens[0]––calls[0]––>tokens[1]––...––calls[n-1]––>tokens[n]
 | 
			
		||||
        require(
 | 
			
		||||
            fillData.tokens.length == fillData.calls.length + 1,
 | 
			
		||||
            "MultiplexFeature::_multiHopFill/MISMATCHED_ARRAY_LENGTHS"
 | 
			
		||||
        );
 | 
			
		||||
        // Track the remaining ETH allocated to this call.
 | 
			
		||||
        remainingEth = totalEth;
 | 
			
		||||
        // This variable is used as the input and output amounts of
 | 
			
		||||
        // each hop. After the final hop, this will contain the output
 | 
			
		||||
        // amount of the multi-hop fill.
 | 
			
		||||
        outputTokenAmount = fillData.sellAmount;
 | 
			
		||||
        // This variable is used to cache the address to target in the
 | 
			
		||||
        // next hop. See `_computeHopRecipient` for details.
 | 
			
		||||
        address nextTarget;
 | 
			
		||||
        for (uint256 i = 0; i != fillData.calls.length; i++) {
 | 
			
		||||
            WrappedMultiHopCall memory wrappedCall = fillData.calls[i];
 | 
			
		||||
            if (wrappedCall.selector == this._sellToUniswap.selector) {
 | 
			
		||||
                // If the next hop supports a "transfer then execute" pattern,
 | 
			
		||||
                // the recipient will not be `msg.sender`. See `_computeHopRecipient`
 | 
			
		||||
                // for details.
 | 
			
		||||
                address recipient = _computeHopRecipient(fillData.calls, i);
 | 
			
		||||
                (address[] memory tokens, bool isSushi) = abi.decode(
 | 
			
		||||
                    wrappedCall.data,
 | 
			
		||||
                    (address[], bool)
 | 
			
		||||
                );
 | 
			
		||||
                // Perform the Uniswap/Sushiswap trade.
 | 
			
		||||
                outputTokenAmount = _sellToUniswap(
 | 
			
		||||
                    tokens,
 | 
			
		||||
                    outputTokenAmount,
 | 
			
		||||
                    isSushi,
 | 
			
		||||
                    nextTarget,
 | 
			
		||||
                    recipient
 | 
			
		||||
                );
 | 
			
		||||
                // If the recipient was not `msg.sender`, it must be the target
 | 
			
		||||
                // contract for the next hop.
 | 
			
		||||
                nextTarget = recipient == msg.sender ? address(0) : recipient;
 | 
			
		||||
            } else if (wrappedCall.selector == this._sellToLiquidityProvider.selector) {
 | 
			
		||||
                // If the next hop supports a "transfer then execute" pattern,
 | 
			
		||||
                // the recipient will not be `msg.sender`. See `_computeHopRecipient`
 | 
			
		||||
                // for details.
 | 
			
		||||
                address recipient = _computeHopRecipient(fillData.calls, i);
 | 
			
		||||
                // If `nextTarget` was not set in the previous hop, then we
 | 
			
		||||
                // need to send in the input ETH/tokens to the liquidity provider
 | 
			
		||||
                // contract before executing the trade.
 | 
			
		||||
                if (nextTarget == address(0)) {
 | 
			
		||||
                    (address provider, bytes memory auxiliaryData) = abi.decode(
 | 
			
		||||
                        wrappedCall.data,
 | 
			
		||||
                        (address, bytes)
 | 
			
		||||
                    );
 | 
			
		||||
                    // Transfer input ETH or ERC20 tokens to the liquidity
 | 
			
		||||
                    // provider contract.
 | 
			
		||||
                    if (IERC20TokenV06(fillData.tokens[i]).isTokenETH()) {
 | 
			
		||||
                        outputTokenAmount = LibSafeMathV06.min256(
 | 
			
		||||
                            outputTokenAmount,
 | 
			
		||||
                            remainingEth
 | 
			
		||||
                        );
 | 
			
		||||
                        _transferEth(payable(provider), outputTokenAmount);
 | 
			
		||||
                        remainingEth -= outputTokenAmount;
 | 
			
		||||
                    } else {
 | 
			
		||||
                        _transferERC20Tokens(
 | 
			
		||||
                            IERC20TokenV06(fillData.tokens[i]),
 | 
			
		||||
                            msg.sender,
 | 
			
		||||
                            provider,
 | 
			
		||||
                            outputTokenAmount
 | 
			
		||||
                        );
 | 
			
		||||
                    }
 | 
			
		||||
                    outputTokenAmount = _sellToLiquidityProvider(
 | 
			
		||||
                        IERC20TokenV06(fillData.tokens[i]),
 | 
			
		||||
                        IERC20TokenV06(fillData.tokens[i + 1]),
 | 
			
		||||
                        outputTokenAmount,
 | 
			
		||||
                        ILiquidityProvider(provider),
 | 
			
		||||
                        recipient,
 | 
			
		||||
                        auxiliaryData
 | 
			
		||||
                    );
 | 
			
		||||
                } else {
 | 
			
		||||
                    (, bytes memory auxiliaryData) = abi.decode(
 | 
			
		||||
                        wrappedCall.data,
 | 
			
		||||
                        (address, bytes)
 | 
			
		||||
                    );
 | 
			
		||||
                    // Tokens and ETH have already been transferred to
 | 
			
		||||
                    // the liquidity provider contract in the previous hop.
 | 
			
		||||
                    outputTokenAmount = _sellToLiquidityProvider(
 | 
			
		||||
                        IERC20TokenV06(fillData.tokens[i]),
 | 
			
		||||
                        IERC20TokenV06(fillData.tokens[i + 1]),
 | 
			
		||||
                        outputTokenAmount,
 | 
			
		||||
                        ILiquidityProvider(nextTarget),
 | 
			
		||||
                        recipient,
 | 
			
		||||
                        auxiliaryData
 | 
			
		||||
                    );
 | 
			
		||||
                }
 | 
			
		||||
                // If the recipient was not `msg.sender`, it must be the target
 | 
			
		||||
                // contract for the next hop.
 | 
			
		||||
                nextTarget = recipient == msg.sender ? address(0) : recipient;
 | 
			
		||||
            } else if (wrappedCall.selector == ITransformERC20Feature._transformERC20.selector) {
 | 
			
		||||
                ITransformERC20Feature.TransformERC20Args memory args;
 | 
			
		||||
                args.inputToken = IERC20TokenV06(fillData.tokens[i]);
 | 
			
		||||
                args.outputToken = IERC20TokenV06(fillData.tokens[i + 1]);
 | 
			
		||||
                args.minOutputTokenAmount = 0;
 | 
			
		||||
                args.taker = payable(_computeHopRecipient(fillData.calls, i));
 | 
			
		||||
                if (nextTarget != address(0)) {
 | 
			
		||||
                    // If `nextTarget` was set in the previous hop, then the input
 | 
			
		||||
                    // token was already sent to the FlashWallet. Setting
 | 
			
		||||
                    // `inputTokenAmount` to 0 indicates that no tokens need to
 | 
			
		||||
                    // be pulled into the FlashWallet before executing the
 | 
			
		||||
                    // transformations.
 | 
			
		||||
                    args.inputTokenAmount = 0;
 | 
			
		||||
                } else if (
 | 
			
		||||
                    args.taker != msg.sender &&
 | 
			
		||||
                    !args.inputToken.isTokenETH()
 | 
			
		||||
                ) {
 | 
			
		||||
                    address flashWallet = address(
 | 
			
		||||
                        ITransformERC20Feature(address(this)).getTransformWallet()
 | 
			
		||||
                    );
 | 
			
		||||
                    // The input token has _not_ already been sent to the
 | 
			
		||||
                    // FlashWallet. We also want PayTakerTransformer to
 | 
			
		||||
                    // send the output token to some address other than
 | 
			
		||||
                    // msg.sender, so we must transfer the input token
 | 
			
		||||
                    // to the FlashWallet here.
 | 
			
		||||
                    _transferERC20Tokens(
 | 
			
		||||
                        args.inputToken,
 | 
			
		||||
                        msg.sender,
 | 
			
		||||
                        flashWallet,
 | 
			
		||||
                        outputTokenAmount
 | 
			
		||||
                    );
 | 
			
		||||
                    args.inputTokenAmount = 0;
 | 
			
		||||
                } else {
 | 
			
		||||
                    // Otherwise, either:
 | 
			
		||||
                    // (1) args.taker == msg.sender, in which case
 | 
			
		||||
                    //     `_transformERC20` will pull the input token
 | 
			
		||||
                    //     into the FlashWallet, or
 | 
			
		||||
                    // (2) args.inputToken == ETH_TOKEN_ADDRESS, in which
 | 
			
		||||
                    //     case ETH is attached to the call and no token
 | 
			
		||||
                    //     transfer occurs.
 | 
			
		||||
                    args.inputTokenAmount = outputTokenAmount;
 | 
			
		||||
                }
 | 
			
		||||
                uint256 ethValue;
 | 
			
		||||
                (args.transformations, ethValue) = abi.decode(
 | 
			
		||||
                    wrappedCall.data,
 | 
			
		||||
                    (ITransformERC20Feature.Transformation[], uint256)
 | 
			
		||||
                );
 | 
			
		||||
                // Do not spend more than the remaining ETH.
 | 
			
		||||
                ethValue = LibSafeMathV06.min256(ethValue, remainingEth);
 | 
			
		||||
                if (ethValue > 0) {
 | 
			
		||||
                    require(
 | 
			
		||||
                        args.inputToken.isTokenETH(),
 | 
			
		||||
                        "MultiplexFeature::_multiHopFill/ETH_TRANSFORM_ONLY"
 | 
			
		||||
                    );
 | 
			
		||||
                }
 | 
			
		||||
                // Call `_transformERC20`.
 | 
			
		||||
                outputTokenAmount = ITransformERC20Feature(address(this))
 | 
			
		||||
                    ._transformERC20{value: ethValue}(args);
 | 
			
		||||
                // Decrement the remaining ETH.
 | 
			
		||||
                remainingEth -= ethValue;
 | 
			
		||||
                // If the recipient was not `msg.sender`, it must be the target
 | 
			
		||||
                // contract for the next hop.
 | 
			
		||||
                nextTarget = args.taker == msg.sender ? address(0) : args.taker;
 | 
			
		||||
            } else if (wrappedCall.selector == IEtherTokenV06.deposit.selector) {
 | 
			
		||||
                require(
 | 
			
		||||
                    i == 0,
 | 
			
		||||
                    "MultiplexFeature::_multiHopFill/DEPOSIT_FIRST_HOP_ONLY"
 | 
			
		||||
                );
 | 
			
		||||
                uint256 ethValue = LibSafeMathV06.min256(outputTokenAmount, remainingEth);
 | 
			
		||||
                // Wrap ETH.
 | 
			
		||||
                weth.deposit{value: ethValue}();
 | 
			
		||||
                nextTarget = _computeHopRecipient(fillData.calls, i);
 | 
			
		||||
                weth.transfer(nextTarget, ethValue);
 | 
			
		||||
                remainingEth -= ethValue;
 | 
			
		||||
            } else if (wrappedCall.selector == IEtherTokenV06.withdraw.selector) {
 | 
			
		||||
                require(
 | 
			
		||||
                    i == fillData.calls.length - 1,
 | 
			
		||||
                    "MultiplexFeature::_multiHopFill/WITHDRAW_LAST_HOP_ONLY"
 | 
			
		||||
                );
 | 
			
		||||
                // Unwrap WETH and send to `msg.sender`.
 | 
			
		||||
                weth.withdraw(outputTokenAmount);
 | 
			
		||||
                _transferEth(msg.sender, outputTokenAmount);
 | 
			
		||||
                nextTarget = address(0);
 | 
			
		||||
            } else {
 | 
			
		||||
                revert("MultiplexFeature::_multiHopFill/UNRECOGNIZED_SELECTOR");
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Similar to the UniswapFeature, but with a couple of differences:
 | 
			
		||||
    // - Does not perform the transfer in if `pairAddress` is given,
 | 
			
		||||
    //   which indicates that the transfer in was already performed
 | 
			
		||||
    //   in the previous hop of a multi-hop fill.
 | 
			
		||||
    // - Does not include a minBuyAmount check (which is performed in
 | 
			
		||||
    //   either `batchFill` or `multiHopFill`).
 | 
			
		||||
    // - Takes a `recipient` address parameter, so the output of the
 | 
			
		||||
    //   final `swap` call can be sent to an address other than `msg.sender`.
 | 
			
		||||
    function _sellToUniswap(
 | 
			
		||||
        address[] memory tokens,
 | 
			
		||||
        uint256 sellAmount,
 | 
			
		||||
        bool isSushi,
 | 
			
		||||
        address pairAddress,
 | 
			
		||||
        address recipient
 | 
			
		||||
    )
 | 
			
		||||
        public
 | 
			
		||||
        returns (uint256 outputTokenAmount)
 | 
			
		||||
    {
 | 
			
		||||
        require(tokens.length > 1, "MultiplexFeature::_sellToUniswap/InvalidTokensLength");
 | 
			
		||||
 | 
			
		||||
        if (pairAddress == address(0)) {
 | 
			
		||||
            pairAddress = _computeUniswapPairAddress(tokens[0], tokens[1], isSushi);
 | 
			
		||||
            _transferERC20Tokens(
 | 
			
		||||
                IERC20TokenV06(tokens[0]),
 | 
			
		||||
                msg.sender,
 | 
			
		||||
                pairAddress,
 | 
			
		||||
                sellAmount
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        for (uint256 i = 0; i < tokens.length - 1; i++) {
 | 
			
		||||
            (address inputToken, address outputToken) = (tokens[i], tokens[i + 1]);
 | 
			
		||||
            outputTokenAmount = _computeUniswapOutputAmount(
 | 
			
		||||
                pairAddress,
 | 
			
		||||
                inputToken,
 | 
			
		||||
                outputToken,
 | 
			
		||||
                sellAmount
 | 
			
		||||
            );
 | 
			
		||||
            (uint256 amount0Out, uint256 amount1Out) = inputToken < outputToken
 | 
			
		||||
                ? (uint256(0), outputTokenAmount)
 | 
			
		||||
                : (outputTokenAmount, uint256(0));
 | 
			
		||||
            address to = i < tokens.length - 2
 | 
			
		||||
                ? _computeUniswapPairAddress(outputToken, tokens[i + 2], isSushi)
 | 
			
		||||
                : recipient;
 | 
			
		||||
            IUniswapV2Pair(pairAddress).swap(
 | 
			
		||||
                amount0Out,
 | 
			
		||||
                amount1Out,
 | 
			
		||||
                to,
 | 
			
		||||
                new bytes(0)
 | 
			
		||||
            );
 | 
			
		||||
            pairAddress = to;
 | 
			
		||||
            sellAmount = outputTokenAmount;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Same as the LiquidityProviderFeature, but without the transfer in
 | 
			
		||||
    // (which is potentially done in the previous hop of a multi-hop fill)
 | 
			
		||||
    // and without the minBuyAmount check (which is performed at the top, i.e.
 | 
			
		||||
    // in either `batchFill` or `multiHopFill`).
 | 
			
		||||
    function _sellToLiquidityProvider(
 | 
			
		||||
        IERC20TokenV06 inputToken,
 | 
			
		||||
        IERC20TokenV06 outputToken,
 | 
			
		||||
        uint256 inputTokenAmount,
 | 
			
		||||
        ILiquidityProvider provider,
 | 
			
		||||
        address recipient,
 | 
			
		||||
        bytes memory auxiliaryData
 | 
			
		||||
    )
 | 
			
		||||
        public
 | 
			
		||||
        returns (uint256 outputTokenAmount)
 | 
			
		||||
    {
 | 
			
		||||
        uint256 balanceBefore = IERC20TokenV06(outputToken).getTokenBalanceOf(recipient);
 | 
			
		||||
        if (IERC20TokenV06(inputToken).isTokenETH()) {
 | 
			
		||||
            sandbox.executeSellEthForToken(
 | 
			
		||||
                provider,
 | 
			
		||||
                outputToken,
 | 
			
		||||
                recipient,
 | 
			
		||||
                0,
 | 
			
		||||
                auxiliaryData
 | 
			
		||||
            );
 | 
			
		||||
        } else if (IERC20TokenV06(outputToken).isTokenETH()) {
 | 
			
		||||
            sandbox.executeSellTokenForEth(
 | 
			
		||||
                provider,
 | 
			
		||||
                inputToken,
 | 
			
		||||
                recipient,
 | 
			
		||||
                0,
 | 
			
		||||
                auxiliaryData
 | 
			
		||||
            );
 | 
			
		||||
        } else {
 | 
			
		||||
            sandbox.executeSellTokenForToken(
 | 
			
		||||
                provider,
 | 
			
		||||
                inputToken,
 | 
			
		||||
                outputToken,
 | 
			
		||||
                recipient,
 | 
			
		||||
                0,
 | 
			
		||||
                auxiliaryData
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
        outputTokenAmount = IERC20TokenV06(outputToken).getTokenBalanceOf(recipient)
 | 
			
		||||
            .safeSub(balanceBefore);
 | 
			
		||||
        emit LiquidityProviderSwap(
 | 
			
		||||
            address(inputToken),
 | 
			
		||||
            address(outputToken),
 | 
			
		||||
            inputTokenAmount,
 | 
			
		||||
            outputTokenAmount,
 | 
			
		||||
            address(provider),
 | 
			
		||||
            recipient
 | 
			
		||||
        );
 | 
			
		||||
        return outputTokenAmount;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function _transferEth(address payable recipient, uint256 amount)
 | 
			
		||||
        private
 | 
			
		||||
    {
 | 
			
		||||
        (bool success,) = recipient.call{value: amount}("");
 | 
			
		||||
        require(success, "MultiplexFeature::_transferEth/TRANSFER_FALIED");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Some liquidity sources (e.g. Uniswap, Sushiswap, and PLP) can be passed
 | 
			
		||||
    // a `recipient` parameter so the boguht tokens are transferred to the
 | 
			
		||||
    // `recipient` address rather than `msg.sender`.
 | 
			
		||||
    // Some liquidity sources (also Uniswap, Sushiswap, and PLP incidentally)
 | 
			
		||||
    // support a "transfer then execute" pattern, where the token being sold
 | 
			
		||||
    // can be transferred into the contract before calling a swap function to
 | 
			
		||||
    // execute the trade.
 | 
			
		||||
    // If the current hop in a multi-hop fill satisfies the first condition,
 | 
			
		||||
    // and the next hop satisfies the second condition, the tokens bought
 | 
			
		||||
    // in the current hop can be directly sent to the target contract of
 | 
			
		||||
    // the next hop to save a transfer.
 | 
			
		||||
    function _computeHopRecipient(
 | 
			
		||||
        WrappedMultiHopCall[] memory calls,
 | 
			
		||||
        uint256 i
 | 
			
		||||
    )
 | 
			
		||||
        private
 | 
			
		||||
        view
 | 
			
		||||
        returns (address recipient)
 | 
			
		||||
    {
 | 
			
		||||
        recipient = msg.sender;
 | 
			
		||||
        if (i < calls.length - 1) {
 | 
			
		||||
            WrappedMultiHopCall memory nextCall = calls[i + 1];
 | 
			
		||||
            if (nextCall.selector == this._sellToUniswap.selector) {
 | 
			
		||||
                (address[] memory tokens, bool isSushi) = abi.decode(
 | 
			
		||||
                    nextCall.data,
 | 
			
		||||
                    (address[], bool)
 | 
			
		||||
                );
 | 
			
		||||
                recipient = _computeUniswapPairAddress(tokens[0], tokens[1], isSushi);
 | 
			
		||||
            } else if (nextCall.selector == this._sellToLiquidityProvider.selector) {
 | 
			
		||||
                (recipient,) = abi.decode(
 | 
			
		||||
                    nextCall.data,
 | 
			
		||||
                    (address, bytes)
 | 
			
		||||
                );
 | 
			
		||||
            } else if (nextCall.selector == IEtherTokenV06.withdraw.selector) {
 | 
			
		||||
                recipient = address(this);
 | 
			
		||||
            } else if (nextCall.selector == ITransformERC20Feature._transformERC20.selector) {
 | 
			
		||||
                recipient = address(
 | 
			
		||||
                    ITransformERC20Feature(address(this)).getTransformWallet()
 | 
			
		||||
                );
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        require(
 | 
			
		||||
            recipient != address(0),
 | 
			
		||||
            "MultiplexFeature::_computeHopRecipient/RECIPIENT_IS_NULL"
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Computes the the amount of output token that would be bought
 | 
			
		||||
    // from Uniswap/Sushiswap given the input amount.
 | 
			
		||||
    function _computeUniswapOutputAmount(
 | 
			
		||||
        address pairAddress,
 | 
			
		||||
        address inputToken,
 | 
			
		||||
        address outputToken,
 | 
			
		||||
        uint256 inputAmount
 | 
			
		||||
    )
 | 
			
		||||
        private
 | 
			
		||||
        view
 | 
			
		||||
        returns (uint256 outputAmount)
 | 
			
		||||
    {
 | 
			
		||||
        require(
 | 
			
		||||
            inputAmount > 0,
 | 
			
		||||
            "MultiplexFeature::_computeUniswapOutputAmount/INSUFFICIENT_INPUT_AMOUNT"
 | 
			
		||||
        );
 | 
			
		||||
        (uint256 reserve0, uint256 reserve1,) = IUniswapV2Pair(pairAddress).getReserves();
 | 
			
		||||
        require(
 | 
			
		||||
            reserve0 > 0 && reserve1 > 0,
 | 
			
		||||
            'MultiplexFeature::_computeUniswapOutputAmount/INSUFFICIENT_LIQUIDITY'
 | 
			
		||||
        );
 | 
			
		||||
        (uint256 inputReserve, uint256 outputReserve) = inputToken < outputToken
 | 
			
		||||
            ? (reserve0, reserve1)
 | 
			
		||||
            : (reserve1, reserve0);
 | 
			
		||||
        uint256 inputAmountWithFee = inputAmount.safeMul(997);
 | 
			
		||||
        uint256 numerator = inputAmountWithFee.safeMul(outputReserve);
 | 
			
		||||
        uint256 denominator = inputReserve.safeMul(1000).safeAdd(inputAmountWithFee);
 | 
			
		||||
        return numerator / denominator;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Computes the Uniswap/Sushiswap pair contract address for the
 | 
			
		||||
    // given tokens.
 | 
			
		||||
    function _computeUniswapPairAddress(
 | 
			
		||||
        address tokenA,
 | 
			
		||||
        address tokenB,
 | 
			
		||||
        bool isSushi
 | 
			
		||||
    )
 | 
			
		||||
        private
 | 
			
		||||
        pure
 | 
			
		||||
        returns (address pairAddress)
 | 
			
		||||
    {
 | 
			
		||||
        (address token0, address token1) = tokenA < tokenB
 | 
			
		||||
            ? (tokenA, tokenB)
 | 
			
		||||
            : (tokenB, tokenA);
 | 
			
		||||
        if (isSushi) {
 | 
			
		||||
            return address(uint256(keccak256(abi.encodePacked(
 | 
			
		||||
                hex'ff',
 | 
			
		||||
                SUSHISWAP_FACTORY,
 | 
			
		||||
                keccak256(abi.encodePacked(token0, token1)),
 | 
			
		||||
                SUSHISWAP_PAIR_INIT_CODE_HASH
 | 
			
		||||
            ))));
 | 
			
		||||
        } else {
 | 
			
		||||
            return address(uint256(keccak256(abi.encodePacked(
 | 
			
		||||
                hex'ff',
 | 
			
		||||
                UNISWAP_FACTORY,
 | 
			
		||||
                keccak256(abi.encodePacked(token0, token1)),
 | 
			
		||||
                UNISWAP_PAIR_INIT_CODE_HASH
 | 
			
		||||
            ))));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -26,8 +26,8 @@ import "../errors/LibOwnableRichErrors.sol";
 | 
			
		||||
import "../storage/LibOwnableStorage.sol";
 | 
			
		||||
import "../migrations/LibBootstrap.sol";
 | 
			
		||||
import "../migrations/LibMigrate.sol";
 | 
			
		||||
import "./IFeature.sol";
 | 
			
		||||
import "./IOwnableFeature.sol";
 | 
			
		||||
import "./interfaces/IFeature.sol";
 | 
			
		||||
import "./interfaces/IOwnableFeature.sol";
 | 
			
		||||
import "./SimpleFunctionRegistryFeature.sol";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -26,8 +26,8 @@ import "../storage/LibProxyStorage.sol";
 | 
			
		||||
import "../storage/LibSimpleFunctionRegistryStorage.sol";
 | 
			
		||||
import "../errors/LibSimpleFunctionRegistryRichErrors.sol";
 | 
			
		||||
import "../migrations/LibBootstrap.sol";
 | 
			
		||||
import "./IFeature.sol";
 | 
			
		||||
import "./ISimpleFunctionRegistryFeature.sol";
 | 
			
		||||
import "./interfaces/IFeature.sol";
 | 
			
		||||
import "./interfaces/ISimpleFunctionRegistryFeature.sol";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/// @dev Basic registry management features.
 | 
			
		||||
 
 | 
			
		||||
@@ -29,8 +29,8 @@ import "../fixins/FixinCommon.sol";
 | 
			
		||||
import "../migrations/LibMigrate.sol";
 | 
			
		||||
import "../external/IAllowanceTarget.sol";
 | 
			
		||||
import "../storage/LibTokenSpenderStorage.sol";
 | 
			
		||||
import "./ITokenSpenderFeature.sol";
 | 
			
		||||
import "./IFeature.sol";
 | 
			
		||||
import "./interfaces/IFeature.sol";
 | 
			
		||||
import "./interfaces/ITokenSpenderFeature.sol";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/// @dev Feature that allows spending token allowances.
 | 
			
		||||
 
 | 
			
		||||
@@ -33,8 +33,8 @@ import "../external/FlashWallet.sol";
 | 
			
		||||
import "../storage/LibTransformERC20Storage.sol";
 | 
			
		||||
import "../transformers/IERC20Transformer.sol";
 | 
			
		||||
import "../transformers/LibERC20Transformer.sol";
 | 
			
		||||
import "./ITransformERC20Feature.sol";
 | 
			
		||||
import "./IFeature.sol";
 | 
			
		||||
import "./interfaces/IFeature.sol";
 | 
			
		||||
import "./interfaces/ITransformERC20Feature.sol";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/// @dev Feature to composably transform between ERC20 tokens.
 | 
			
		||||
@@ -313,7 +313,7 @@ contract TransformERC20Feature is
 | 
			
		||||
            to.transfer(msg.value);
 | 
			
		||||
        }
 | 
			
		||||
        // Transfer input tokens.
 | 
			
		||||
        if (!LibERC20Transformer.isTokenETH(inputToken)) {
 | 
			
		||||
        if (!LibERC20Transformer.isTokenETH(inputToken) && amount != 0) {
 | 
			
		||||
            // Token is not ETH, so pull ERC20 tokens.
 | 
			
		||||
            _transferERC20Tokens(
 | 
			
		||||
                inputToken,
 | 
			
		||||
 
 | 
			
		||||
@@ -25,8 +25,8 @@ import "@0x/contracts-erc20/contracts/src/v06/IEtherTokenV06.sol";
 | 
			
		||||
import "../migrations/LibMigrate.sol";
 | 
			
		||||
import "../external/IAllowanceTarget.sol";
 | 
			
		||||
import "../fixins/FixinCommon.sol";
 | 
			
		||||
import "./IFeature.sol";
 | 
			
		||||
import "./IUniswapFeature.sol";
 | 
			
		||||
import "./interfaces/IFeature.sol";
 | 
			
		||||
import "./interfaces/IUniswapFeature.sol";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/// @dev VIP uniswap fill functions.
 | 
			
		||||
@@ -380,7 +380,7 @@ contract UniswapFeature is
 | 
			
		||||
                // will eat all our gas.
 | 
			
		||||
                if isTokenPossiblyGreedy(token) {
 | 
			
		||||
                    // Check if we have enough direct allowance by calling
 | 
			
		||||
                    // `token.allowance()``
 | 
			
		||||
                    // `token.allowance()`
 | 
			
		||||
                    mstore(0xB00, ALLOWANCE_CALL_SELECTOR_32)
 | 
			
		||||
                    mstore(0xB04, caller())
 | 
			
		||||
                    mstore(0xB24, address())
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,70 @@
 | 
			
		||||
// SPDX-License-Identifier: Apache-2.0
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  Copyright 2021 ZeroEx Intl.
 | 
			
		||||
 | 
			
		||||
  Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
  you may not use this file except in compliance with the License.
 | 
			
		||||
  You may obtain a copy of the License at
 | 
			
		||||
 | 
			
		||||
    http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 | 
			
		||||
  Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
  distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
  See the License for the specific language governing permissions and
 | 
			
		||||
  limitations under the License.
 | 
			
		||||
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
pragma solidity ^0.6.5;
 | 
			
		||||
pragma experimental ABIEncoderV2;
 | 
			
		||||
 | 
			
		||||
import "../libs/LibNativeOrder.sol";
 | 
			
		||||
import "../libs/LibSignature.sol";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/// @dev Feature for batch/market filling limit and RFQ orders.
 | 
			
		||||
interface IBatchFillNativeOrdersFeature {
 | 
			
		||||
 | 
			
		||||
    /// @dev Fills multiple limit orders.
 | 
			
		||||
    /// @param orders Array of limit orders.
 | 
			
		||||
    /// @param signatures Array of signatures corresponding to each order.
 | 
			
		||||
    /// @param takerTokenFillAmounts Array of desired amounts to fill each order.
 | 
			
		||||
    /// @param revertIfIncomplete If true, reverts if this function fails to
 | 
			
		||||
    ///        fill the full fill amount for any individual order.
 | 
			
		||||
    /// @return takerTokenFilledAmounts Array of amounts filled, in taker token.
 | 
			
		||||
    /// @return makerTokenFilledAmounts Array of amounts filled, in maker token.
 | 
			
		||||
    function batchFillLimitOrders(
 | 
			
		||||
        LibNativeOrder.LimitOrder[] calldata orders,
 | 
			
		||||
        LibSignature.Signature[] calldata signatures,
 | 
			
		||||
        uint128[] calldata takerTokenFillAmounts,
 | 
			
		||||
        bool revertIfIncomplete
 | 
			
		||||
    )
 | 
			
		||||
        external
 | 
			
		||||
        payable
 | 
			
		||||
        returns (
 | 
			
		||||
            uint128[] memory takerTokenFilledAmounts,
 | 
			
		||||
            uint128[] memory makerTokenFilledAmounts
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
    /// @dev Fills multiple RFQ orders.
 | 
			
		||||
    /// @param orders Array of RFQ orders.
 | 
			
		||||
    /// @param signatures Array of signatures corresponding to each order.
 | 
			
		||||
    /// @param takerTokenFillAmounts Array of desired amounts to fill each order.
 | 
			
		||||
    /// @param revertIfIncomplete If true, reverts if this function fails to
 | 
			
		||||
    ///        fill the full fill amount for any individual order.
 | 
			
		||||
    /// @return takerTokenFilledAmounts Array of amounts filled, in taker token.
 | 
			
		||||
    /// @return makerTokenFilledAmounts Array of amounts filled, in maker token.
 | 
			
		||||
    function batchFillRfqOrders(
 | 
			
		||||
        LibNativeOrder.RfqOrder[] calldata orders,
 | 
			
		||||
        LibSignature.Signature[] calldata signatures,
 | 
			
		||||
        uint128[] calldata takerTokenFillAmounts,
 | 
			
		||||
        bool revertIfIncomplete
 | 
			
		||||
    )
 | 
			
		||||
        external
 | 
			
		||||
        returns (
 | 
			
		||||
            uint128[] memory takerTokenFilledAmounts,
 | 
			
		||||
            uint128[] memory makerTokenFilledAmounts
 | 
			
		||||
        );
 | 
			
		||||
}
 | 
			
		||||
@@ -21,7 +21,7 @@ pragma solidity ^0.6.5;
 | 
			
		||||
pragma experimental ABIEncoderV2;
 | 
			
		||||
 | 
			
		||||
import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol";
 | 
			
		||||
import "../vendor/ILiquidityProvider.sol";
 | 
			
		||||
import "../../vendor/ILiquidityProvider.sol";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/// @dev Feature to swap directly with an on-chain liquidity provider.
 | 
			
		||||
@@ -21,7 +21,7 @@ pragma solidity ^0.6.5;
 | 
			
		||||
pragma experimental ABIEncoderV2;
 | 
			
		||||
 | 
			
		||||
import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol";
 | 
			
		||||
import "./libs/LibSignature.sol";
 | 
			
		||||
import "../libs/LibSignature.sol";
 | 
			
		||||
 | 
			
		||||
/// @dev Meta-transactions feature.
 | 
			
		||||
interface IMetaTransactionsFeature {
 | 
			
		||||
@@ -0,0 +1,117 @@
 | 
			
		||||
// SPDX-License-Identifier: Apache-2.0
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  Copyright 2021 ZeroEx Intl.
 | 
			
		||||
 | 
			
		||||
  Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
  you may not use this file except in compliance with the License.
 | 
			
		||||
  You may obtain a copy of the License at
 | 
			
		||||
 | 
			
		||||
    http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 | 
			
		||||
  Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
  distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
  See the License for the specific language governing permissions and
 | 
			
		||||
  limitations under the License.
 | 
			
		||||
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
pragma solidity ^0.6.5;
 | 
			
		||||
pragma experimental ABIEncoderV2;
 | 
			
		||||
 | 
			
		||||
import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
interface IMultiplexFeature {
 | 
			
		||||
 | 
			
		||||
    // Parameters for `batchFill`.
 | 
			
		||||
    struct BatchFillData {
 | 
			
		||||
        // The token being sold.
 | 
			
		||||
        IERC20TokenV06 inputToken;
 | 
			
		||||
        // The token being bought.
 | 
			
		||||
        IERC20TokenV06 outputToken;
 | 
			
		||||
        // The amount of `inputToken` to sell.
 | 
			
		||||
        uint256 sellAmount;
 | 
			
		||||
        // The nested calls to perform.
 | 
			
		||||
        WrappedBatchCall[] calls;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Represents a call nested within a `batchFill`.
 | 
			
		||||
    struct WrappedBatchCall {
 | 
			
		||||
        // The selector of the function to call.
 | 
			
		||||
        bytes4 selector;
 | 
			
		||||
        // Amount of `inputToken` to sell.
 | 
			
		||||
        uint256 sellAmount;
 | 
			
		||||
        // ABI-encoded parameters needed to perform the call.
 | 
			
		||||
        bytes data;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Parameters for `multiHopFill`.
 | 
			
		||||
    struct MultiHopFillData {
 | 
			
		||||
        // The sell path, i.e.
 | 
			
		||||
        // tokens = [inputToken, hopToken1, ..., hopTokenN, outputToken]
 | 
			
		||||
        address[] tokens;
 | 
			
		||||
        // The amount of `tokens[0]` to sell.
 | 
			
		||||
        uint256 sellAmount;
 | 
			
		||||
        // The nested calls to perform.
 | 
			
		||||
        WrappedMultiHopCall[] calls;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Represents a call nested within a `multiHopFill`.
 | 
			
		||||
    struct WrappedMultiHopCall {
 | 
			
		||||
        // The selector of the function to call.
 | 
			
		||||
        bytes4 selector;
 | 
			
		||||
        // ABI-encoded parameters needed to perform the call.
 | 
			
		||||
        bytes data;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    event LiquidityProviderSwap(
 | 
			
		||||
        address inputToken,
 | 
			
		||||
        address outputToken,
 | 
			
		||||
        uint256 inputTokenAmount,
 | 
			
		||||
        uint256 outputTokenAmount,
 | 
			
		||||
        address provider,
 | 
			
		||||
        address recipient
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    event ExpiredRfqOrder(
 | 
			
		||||
        bytes32 orderHash,
 | 
			
		||||
        address maker,
 | 
			
		||||
        uint64 expiry
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    /// @dev Executes a batch of fills selling `fillData.inputToken`
 | 
			
		||||
    ///      for `fillData.outputToken` in sequence. Refer to the
 | 
			
		||||
    ///      internal variant `_batchFill` for the allowed nested
 | 
			
		||||
    ///      operations.
 | 
			
		||||
    /// @param fillData Encodes the input/output tokens, the sell
 | 
			
		||||
    ///        amount, and the nested operations for this batch fill.
 | 
			
		||||
    /// @param minBuyAmount The minimum amount of `fillData.outputToken`
 | 
			
		||||
    ///        to buy. Reverts if this amount is not met.
 | 
			
		||||
    /// @return outputTokenAmount The amount of the output token bought.
 | 
			
		||||
    function batchFill(
 | 
			
		||||
        BatchFillData calldata fillData,
 | 
			
		||||
        uint256 minBuyAmount
 | 
			
		||||
    )
 | 
			
		||||
        external
 | 
			
		||||
        payable
 | 
			
		||||
        returns (uint256 outputTokenAmount);
 | 
			
		||||
 | 
			
		||||
    /// @dev Executes a sequence of fills "hopping" through the
 | 
			
		||||
    ///      path of tokens given by `fillData.tokens`. Refer to the
 | 
			
		||||
    ///      internal variant `_multiHopFill` for the allowed nested
 | 
			
		||||
    ///      operations.
 | 
			
		||||
    /// @param fillData Encodes the path of tokens, the sell amount,
 | 
			
		||||
    ///        and the nested operations for this multi-hop fill.
 | 
			
		||||
    /// @param minBuyAmount The minimum amount of the output token
 | 
			
		||||
    ///        to buy. Reverts if this amount is not met.
 | 
			
		||||
    /// @return outputTokenAmount The amount of the output token bought.
 | 
			
		||||
    function multiHopFill(
 | 
			
		||||
        MultiHopFillData calldata fillData,
 | 
			
		||||
        uint256 minBuyAmount
 | 
			
		||||
    )
 | 
			
		||||
        external
 | 
			
		||||
        payable
 | 
			
		||||
        returns (uint256 outputTokenAmount);
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,116 @@
 | 
			
		||||
// SPDX-License-Identifier: Apache-2.0
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  Copyright 2021 ZeroEx Intl.
 | 
			
		||||
 | 
			
		||||
  Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
  you may not use this file except in compliance with the License.
 | 
			
		||||
  You may obtain a copy of the License at
 | 
			
		||||
 | 
			
		||||
    http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 | 
			
		||||
  Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
  distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
  See the License for the specific language governing permissions and
 | 
			
		||||
  limitations under the License.
 | 
			
		||||
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
pragma solidity ^0.6.5;
 | 
			
		||||
pragma experimental ABIEncoderV2;
 | 
			
		||||
 | 
			
		||||
import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol";
 | 
			
		||||
import "../libs/LibSignature.sol";
 | 
			
		||||
import "../libs/LibNativeOrder.sol";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/// @dev Events emitted by NativeOrdersFeature.
 | 
			
		||||
interface INativeOrdersEvents {
 | 
			
		||||
 | 
			
		||||
    /// @dev Emitted whenever a `LimitOrder` is filled.
 | 
			
		||||
    /// @param orderHash The canonical hash of the order.
 | 
			
		||||
    /// @param maker The maker of the order.
 | 
			
		||||
    /// @param taker The taker of the order.
 | 
			
		||||
    /// @param feeRecipient Fee recipient of the order.
 | 
			
		||||
    /// @param takerTokenFilledAmount How much taker token was filled.
 | 
			
		||||
    /// @param makerTokenFilledAmount How much maker token was filled.
 | 
			
		||||
    /// @param protocolFeePaid How much protocol fee was paid.
 | 
			
		||||
    /// @param pool The fee pool associated with this order.
 | 
			
		||||
    event LimitOrderFilled(
 | 
			
		||||
        bytes32 orderHash,
 | 
			
		||||
        address maker,
 | 
			
		||||
        address taker,
 | 
			
		||||
        address feeRecipient,
 | 
			
		||||
        address makerToken,
 | 
			
		||||
        address takerToken,
 | 
			
		||||
        uint128 takerTokenFilledAmount,
 | 
			
		||||
        uint128 makerTokenFilledAmount,
 | 
			
		||||
        uint128 takerTokenFeeFilledAmount,
 | 
			
		||||
        uint256 protocolFeePaid,
 | 
			
		||||
        bytes32 pool
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    /// @dev Emitted whenever an `RfqOrder` is filled.
 | 
			
		||||
    /// @param orderHash The canonical hash of the order.
 | 
			
		||||
    /// @param maker The maker of the order.
 | 
			
		||||
    /// @param taker The taker of the order.
 | 
			
		||||
    /// @param takerTokenFilledAmount How much taker token was filled.
 | 
			
		||||
    /// @param makerTokenFilledAmount How much maker token was filled.
 | 
			
		||||
    /// @param pool The fee pool associated with this order.
 | 
			
		||||
    event RfqOrderFilled(
 | 
			
		||||
        bytes32 orderHash,
 | 
			
		||||
        address maker,
 | 
			
		||||
        address taker,
 | 
			
		||||
        address makerToken,
 | 
			
		||||
        address takerToken,
 | 
			
		||||
        uint128 takerTokenFilledAmount,
 | 
			
		||||
        uint128 makerTokenFilledAmount,
 | 
			
		||||
        bytes32 pool
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    /// @dev Emitted whenever a limit or RFQ order is cancelled.
 | 
			
		||||
    /// @param orderHash The canonical hash of the order.
 | 
			
		||||
    /// @param maker The order maker.
 | 
			
		||||
    event OrderCancelled(
 | 
			
		||||
        bytes32 orderHash,
 | 
			
		||||
        address maker
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    /// @dev Emitted whenever Limit orders are cancelled by pair by a maker.
 | 
			
		||||
    /// @param maker The maker of the order.
 | 
			
		||||
    /// @param makerToken The maker token in a pair for the orders cancelled.
 | 
			
		||||
    /// @param takerToken The taker token in a pair for the orders cancelled.
 | 
			
		||||
    /// @param minValidSalt The new minimum valid salt an order with this pair must
 | 
			
		||||
    ///        have.
 | 
			
		||||
    event PairCancelledLimitOrders(
 | 
			
		||||
        address maker,
 | 
			
		||||
        address makerToken,
 | 
			
		||||
        address takerToken,
 | 
			
		||||
        uint256 minValidSalt
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    /// @dev Emitted whenever RFQ orders are cancelled by pair by a maker.
 | 
			
		||||
    /// @param maker The maker of the order.
 | 
			
		||||
    /// @param makerToken The maker token in a pair for the orders cancelled.
 | 
			
		||||
    /// @param takerToken The taker token in a pair for the orders cancelled.
 | 
			
		||||
    /// @param minValidSalt The new minimum valid salt an order with this pair must
 | 
			
		||||
    ///        have.
 | 
			
		||||
    event PairCancelledRfqOrders(
 | 
			
		||||
        address maker,
 | 
			
		||||
        address makerToken,
 | 
			
		||||
        address takerToken,
 | 
			
		||||
        uint256 minValidSalt
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    /// @dev Emitted when new addresses are allowed or disallowed to fill
 | 
			
		||||
    ///      orders with a given txOrigin.
 | 
			
		||||
    /// @param origin The address doing the allowing.
 | 
			
		||||
    /// @param addrs The address being allowed/disallowed.
 | 
			
		||||
    /// @param allowed Indicates whether the address should be allowed.
 | 
			
		||||
    event RfqOrderOriginsAllowed(
 | 
			
		||||
        address origin,
 | 
			
		||||
        address[] addrs,
 | 
			
		||||
        bool allowed
 | 
			
		||||
    );
 | 
			
		||||
}
 | 
			
		||||
@@ -21,98 +21,15 @@ pragma solidity ^0.6.5;
 | 
			
		||||
pragma experimental ABIEncoderV2;
 | 
			
		||||
 | 
			
		||||
import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol";
 | 
			
		||||
import "./libs/LibSignature.sol";
 | 
			
		||||
import "./libs/LibNativeOrder.sol";
 | 
			
		||||
import "../libs/LibSignature.sol";
 | 
			
		||||
import "../libs/LibNativeOrder.sol";
 | 
			
		||||
import "./INativeOrdersEvents.sol";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/// @dev Feature for interacting with limit orders.
 | 
			
		||||
interface INativeOrdersFeature {
 | 
			
		||||
 | 
			
		||||
    /// @dev Emitted whenever a `LimitOrder` is filled.
 | 
			
		||||
    /// @param orderHash The canonical hash of the order.
 | 
			
		||||
    /// @param maker The maker of the order.
 | 
			
		||||
    /// @param taker The taker of the order.
 | 
			
		||||
    /// @param feeRecipient Fee recipient of the order.
 | 
			
		||||
    /// @param takerTokenFilledAmount How much taker token was filled.
 | 
			
		||||
    /// @param makerTokenFilledAmount How much maker token was filled.
 | 
			
		||||
    /// @param protocolFeePaid How much protocol fee was paid.
 | 
			
		||||
    /// @param pool The fee pool associated with this order.
 | 
			
		||||
    event LimitOrderFilled(
 | 
			
		||||
        bytes32 orderHash,
 | 
			
		||||
        address maker,
 | 
			
		||||
        address taker,
 | 
			
		||||
        address feeRecipient,
 | 
			
		||||
        address makerToken,
 | 
			
		||||
        address takerToken,
 | 
			
		||||
        uint128 takerTokenFilledAmount,
 | 
			
		||||
        uint128 makerTokenFilledAmount,
 | 
			
		||||
        uint128 takerTokenFeeFilledAmount,
 | 
			
		||||
        uint256 protocolFeePaid,
 | 
			
		||||
        bytes32 pool
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    /// @dev Emitted whenever an `RfqOrder` is filled.
 | 
			
		||||
    /// @param orderHash The canonical hash of the order.
 | 
			
		||||
    /// @param maker The maker of the order.
 | 
			
		||||
    /// @param taker The taker of the order.
 | 
			
		||||
    /// @param takerTokenFilledAmount How much taker token was filled.
 | 
			
		||||
    /// @param makerTokenFilledAmount How much maker token was filled.
 | 
			
		||||
    /// @param pool The fee pool associated with this order.
 | 
			
		||||
    event RfqOrderFilled(
 | 
			
		||||
        bytes32 orderHash,
 | 
			
		||||
        address maker,
 | 
			
		||||
        address taker,
 | 
			
		||||
        address makerToken,
 | 
			
		||||
        address takerToken,
 | 
			
		||||
        uint128 takerTokenFilledAmount,
 | 
			
		||||
        uint128 makerTokenFilledAmount,
 | 
			
		||||
        bytes32 pool
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    /// @dev Emitted whenever a limit or RFQ order is cancelled.
 | 
			
		||||
    /// @param orderHash The canonical hash of the order.
 | 
			
		||||
    /// @param maker The order maker.
 | 
			
		||||
    event OrderCancelled(
 | 
			
		||||
        bytes32 orderHash,
 | 
			
		||||
        address maker
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    /// @dev Emitted whenever Limit orders are cancelled by pair by a maker.
 | 
			
		||||
    /// @param maker The maker of the order.
 | 
			
		||||
    /// @param makerToken The maker token in a pair for the orders cancelled.
 | 
			
		||||
    /// @param takerToken The taker token in a pair for the orders cancelled.
 | 
			
		||||
    /// @param minValidSalt The new minimum valid salt an order with this pair must
 | 
			
		||||
    ///        have.
 | 
			
		||||
    event PairCancelledLimitOrders(
 | 
			
		||||
        address maker,
 | 
			
		||||
        address makerToken,
 | 
			
		||||
        address takerToken,
 | 
			
		||||
        uint256 minValidSalt
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    /// @dev Emitted whenever RFQ orders are cancelled by pair by a maker.
 | 
			
		||||
    /// @param maker The maker of the order.
 | 
			
		||||
    /// @param makerToken The maker token in a pair for the orders cancelled.
 | 
			
		||||
    /// @param takerToken The taker token in a pair for the orders cancelled.
 | 
			
		||||
    /// @param minValidSalt The new minimum valid salt an order with this pair must
 | 
			
		||||
    ///        have.
 | 
			
		||||
    event PairCancelledRfqOrders(
 | 
			
		||||
        address maker,
 | 
			
		||||
        address makerToken,
 | 
			
		||||
        address takerToken,
 | 
			
		||||
        uint256 minValidSalt
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    /// @dev Emitted when new addresses are allowed or disallowed to fill
 | 
			
		||||
    ///      orders with a given txOrigin.
 | 
			
		||||
    /// @param origin The address doing the allowing.
 | 
			
		||||
    /// @param addrs The address being allowed/disallowed.
 | 
			
		||||
    /// @param allowed Indicates whether the address should be allowed.
 | 
			
		||||
    event RfqOrderOriginsAllowed(
 | 
			
		||||
        address origin,
 | 
			
		||||
        address[] addrs,
 | 
			
		||||
        bool allowed
 | 
			
		||||
    );
 | 
			
		||||
interface INativeOrdersFeature is
 | 
			
		||||
    INativeOrdersEvents
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
    /// @dev Transfers protocol fees from the `FeeCollector` pools into
 | 
			
		||||
    ///      the staking contract.
 | 
			
		||||
@@ -21,8 +21,8 @@ pragma solidity ^0.6.5;
 | 
			
		||||
pragma experimental ABIEncoderV2;
 | 
			
		||||
 | 
			
		||||
import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol";
 | 
			
		||||
import "../transformers/IERC20Transformer.sol";
 | 
			
		||||
import "../external/IFlashWallet.sol";
 | 
			
		||||
import "../../transformers/IERC20Transformer.sol";
 | 
			
		||||
import "../../external/IFlashWallet.sol";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/// @dev Feature to composably transform between ERC20 tokens.
 | 
			
		||||
@@ -21,10 +21,15 @@ pragma solidity ^0.6.5;
 | 
			
		||||
pragma experimental ABIEncoderV2;
 | 
			
		||||
 | 
			
		||||
import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol";
 | 
			
		||||
import "@0x/contracts-utils/contracts/src/v06/errors/LibRichErrorsV06.sol";
 | 
			
		||||
import "@0x/contracts-utils/contracts/src/v06/LibSafeMathV06.sol";
 | 
			
		||||
import "../../errors/LibNativeOrdersRichErrors.sol";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/// @dev A library for common native order operations.
 | 
			
		||||
library LibNativeOrder {
 | 
			
		||||
    using LibSafeMathV06 for uint256;
 | 
			
		||||
    using LibRichErrorsV06 for bytes;
 | 
			
		||||
 | 
			
		||||
    enum OrderStatus {
 | 
			
		||||
        INVALID,
 | 
			
		||||
@@ -216,4 +221,23 @@ library LibNativeOrder {
 | 
			
		||||
            structHash := keccak256(mem, 0x160)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Refund any leftover protocol fees in `msg.value` to `msg.sender`.
 | 
			
		||||
    /// @param ethProtocolFeePaid How much ETH was paid in protocol fees.
 | 
			
		||||
    function refundExcessProtocolFeeToSender(uint256 ethProtocolFeePaid)
 | 
			
		||||
        internal
 | 
			
		||||
    {
 | 
			
		||||
        if (msg.value > ethProtocolFeePaid && msg.sender != address(this)) {
 | 
			
		||||
            uint256 refundAmount = msg.value.safeSub(ethProtocolFeePaid);
 | 
			
		||||
            (bool success,) = msg
 | 
			
		||||
                .sender
 | 
			
		||||
                .call{value: refundAmount}("");
 | 
			
		||||
            if (!success) {
 | 
			
		||||
                LibNativeOrdersRichErrors.ProtocolFeeRefundFailed(
 | 
			
		||||
                    msg.sender,
 | 
			
		||||
                    refundAmount
 | 
			
		||||
                ).rrevert();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,266 @@
 | 
			
		||||
// SPDX-License-Identifier: Apache-2.0
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  Copyright 2021 ZeroEx Intl.
 | 
			
		||||
 | 
			
		||||
  Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
  you may not use this file except in compliance with the License.
 | 
			
		||||
  You may obtain a copy of the License at
 | 
			
		||||
 | 
			
		||||
    http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 | 
			
		||||
  Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
  distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
  See the License for the specific language governing permissions and
 | 
			
		||||
  limitations under the License.
 | 
			
		||||
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
pragma solidity ^0.6.5;
 | 
			
		||||
pragma experimental ABIEncoderV2;
 | 
			
		||||
 | 
			
		||||
import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol";
 | 
			
		||||
import "@0x/contracts-utils/contracts/src/v06/errors/LibRichErrorsV06.sol";
 | 
			
		||||
import "../../errors/LibNativeOrdersRichErrors.sol";
 | 
			
		||||
import "../../storage/LibNativeOrdersStorage.sol";
 | 
			
		||||
import "../interfaces/INativeOrdersEvents.sol";
 | 
			
		||||
import "../libs/LibSignature.sol";
 | 
			
		||||
import "../libs/LibNativeOrder.sol";
 | 
			
		||||
import "./NativeOrdersInfo.sol";
 | 
			
		||||
 | 
			
		||||
/// @dev Feature for cancelling limit and RFQ orders.
 | 
			
		||||
abstract contract NativeOrdersCancellation is
 | 
			
		||||
    INativeOrdersEvents,
 | 
			
		||||
    NativeOrdersInfo
 | 
			
		||||
{
 | 
			
		||||
    using LibRichErrorsV06 for bytes;
 | 
			
		||||
 | 
			
		||||
    /// @dev Highest bit of a uint256, used to flag cancelled orders.
 | 
			
		||||
    uint256 private constant HIGH_BIT = 1 << 255;
 | 
			
		||||
 | 
			
		||||
    constructor(
 | 
			
		||||
        address zeroExAddress,
 | 
			
		||||
        bytes32 greedyTokensBloomFilter
 | 
			
		||||
    )
 | 
			
		||||
        internal
 | 
			
		||||
        NativeOrdersInfo(zeroExAddress, greedyTokensBloomFilter)
 | 
			
		||||
    {
 | 
			
		||||
        // solhint-disable no-empty-blocks
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Cancel a single limit order. The caller must be the maker.
 | 
			
		||||
    ///      Silently succeeds if the order has already been cancelled.
 | 
			
		||||
    /// @param order The limit order.
 | 
			
		||||
    function cancelLimitOrder(LibNativeOrder.LimitOrder memory order)
 | 
			
		||||
        public
 | 
			
		||||
    {
 | 
			
		||||
        bytes32 orderHash = getLimitOrderHash(order);
 | 
			
		||||
        if (msg.sender != order.maker) {
 | 
			
		||||
            LibNativeOrdersRichErrors.OnlyOrderMakerAllowed(
 | 
			
		||||
                orderHash,
 | 
			
		||||
                msg.sender,
 | 
			
		||||
                order.maker
 | 
			
		||||
            ).rrevert();
 | 
			
		||||
        }
 | 
			
		||||
        _cancelOrderHash(orderHash, order.maker);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Cancel a single RFQ order. The caller must be the maker.
 | 
			
		||||
    ///      Silently succeeds if the order has already been cancelled.
 | 
			
		||||
    /// @param order The RFQ order.
 | 
			
		||||
    function cancelRfqOrder(LibNativeOrder.RfqOrder memory order)
 | 
			
		||||
        public
 | 
			
		||||
    {
 | 
			
		||||
        bytes32 orderHash = getRfqOrderHash(order);
 | 
			
		||||
        if (msg.sender != order.maker) {
 | 
			
		||||
            LibNativeOrdersRichErrors.OnlyOrderMakerAllowed(
 | 
			
		||||
                orderHash,
 | 
			
		||||
                msg.sender,
 | 
			
		||||
                order.maker
 | 
			
		||||
            ).rrevert();
 | 
			
		||||
        }
 | 
			
		||||
        _cancelOrderHash(orderHash, order.maker);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Cancel multiple limit orders. The caller must be the maker.
 | 
			
		||||
    ///      Silently succeeds if the order has already been cancelled.
 | 
			
		||||
    /// @param orders The limit orders.
 | 
			
		||||
    function batchCancelLimitOrders(LibNativeOrder.LimitOrder[] memory orders)
 | 
			
		||||
        public
 | 
			
		||||
    {
 | 
			
		||||
        for (uint256 i = 0; i < orders.length; ++i) {
 | 
			
		||||
            cancelLimitOrder(orders[i]);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Cancel multiple RFQ orders. The caller must be the maker.
 | 
			
		||||
    ///      Silently succeeds if the order has already been cancelled.
 | 
			
		||||
    /// @param orders The RFQ orders.
 | 
			
		||||
    function batchCancelRfqOrders(LibNativeOrder.RfqOrder[] memory orders)
 | 
			
		||||
        public
 | 
			
		||||
    {
 | 
			
		||||
        for (uint256 i = 0; i < orders.length; ++i) {
 | 
			
		||||
            cancelRfqOrder(orders[i]);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Cancel all limit orders for a given maker and pair with a salt less
 | 
			
		||||
    ///      than the value provided. The caller must be the maker. Subsequent
 | 
			
		||||
    ///      calls to this function with the same caller and pair require the
 | 
			
		||||
    ///      new salt to be >= the old salt.
 | 
			
		||||
    /// @param makerToken The maker token.
 | 
			
		||||
    /// @param takerToken The taker token.
 | 
			
		||||
    /// @param minValidSalt The new minimum valid salt.
 | 
			
		||||
    function cancelPairLimitOrders(
 | 
			
		||||
        IERC20TokenV06 makerToken,
 | 
			
		||||
        IERC20TokenV06 takerToken,
 | 
			
		||||
        uint256 minValidSalt
 | 
			
		||||
    )
 | 
			
		||||
        public
 | 
			
		||||
    {
 | 
			
		||||
        LibNativeOrdersStorage.Storage storage stor =
 | 
			
		||||
            LibNativeOrdersStorage.getStorage();
 | 
			
		||||
 | 
			
		||||
        uint256 oldMinValidSalt =
 | 
			
		||||
            stor.limitOrdersMakerToMakerTokenToTakerTokenToMinValidOrderSalt
 | 
			
		||||
                [msg.sender]
 | 
			
		||||
                [address(makerToken)]
 | 
			
		||||
                [address(takerToken)];
 | 
			
		||||
 | 
			
		||||
        // New min salt must >= the old one.
 | 
			
		||||
        if (oldMinValidSalt > minValidSalt) {
 | 
			
		||||
            LibNativeOrdersRichErrors.
 | 
			
		||||
                CancelSaltTooLowError(minValidSalt, oldMinValidSalt)
 | 
			
		||||
                    .rrevert();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        stor.limitOrdersMakerToMakerTokenToTakerTokenToMinValidOrderSalt
 | 
			
		||||
            [msg.sender]
 | 
			
		||||
            [address(makerToken)]
 | 
			
		||||
            [address(takerToken)] = minValidSalt;
 | 
			
		||||
 | 
			
		||||
        emit PairCancelledLimitOrders(
 | 
			
		||||
            msg.sender,
 | 
			
		||||
            address(makerToken),
 | 
			
		||||
            address(takerToken),
 | 
			
		||||
            minValidSalt
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Cancel all limit orders for a given maker and pair with a salt less
 | 
			
		||||
    ///      than the value provided. The caller must be the maker. Subsequent
 | 
			
		||||
    ///      calls to this function with the same caller and pair require the
 | 
			
		||||
    ///      new salt to be >= the old salt.
 | 
			
		||||
    /// @param makerTokens The maker tokens.
 | 
			
		||||
    /// @param takerTokens The taker tokens.
 | 
			
		||||
    /// @param minValidSalts The new minimum valid salts.
 | 
			
		||||
    function batchCancelPairLimitOrders(
 | 
			
		||||
        IERC20TokenV06[] memory makerTokens,
 | 
			
		||||
        IERC20TokenV06[] memory takerTokens,
 | 
			
		||||
        uint256[] memory minValidSalts
 | 
			
		||||
    )
 | 
			
		||||
        public
 | 
			
		||||
    {
 | 
			
		||||
        require(
 | 
			
		||||
            makerTokens.length == takerTokens.length &&
 | 
			
		||||
            makerTokens.length == minValidSalts.length,
 | 
			
		||||
            "NativeOrdersFeature/MISMATCHED_PAIR_ORDERS_ARRAY_LENGTHS"
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        for (uint256 i = 0; i < makerTokens.length; ++i) {
 | 
			
		||||
            cancelPairLimitOrders(
 | 
			
		||||
                makerTokens[i],
 | 
			
		||||
                takerTokens[i],
 | 
			
		||||
                minValidSalts[i]
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Cancel all RFQ orders for a given maker and pair with a salt less
 | 
			
		||||
    ///      than the value provided. The caller must be the maker. Subsequent
 | 
			
		||||
    ///      calls to this function with the same caller and pair require the
 | 
			
		||||
    ///      new salt to be >= the old salt.
 | 
			
		||||
    /// @param makerToken The maker token.
 | 
			
		||||
    /// @param takerToken The taker token.
 | 
			
		||||
    /// @param minValidSalt The new minimum valid salt.
 | 
			
		||||
    function cancelPairRfqOrders(
 | 
			
		||||
        IERC20TokenV06 makerToken,
 | 
			
		||||
        IERC20TokenV06 takerToken,
 | 
			
		||||
        uint256 minValidSalt
 | 
			
		||||
    )
 | 
			
		||||
        public
 | 
			
		||||
    {
 | 
			
		||||
        LibNativeOrdersStorage.Storage storage stor =
 | 
			
		||||
            LibNativeOrdersStorage.getStorage();
 | 
			
		||||
 | 
			
		||||
        uint256 oldMinValidSalt =
 | 
			
		||||
            stor.rfqOrdersMakerToMakerTokenToTakerTokenToMinValidOrderSalt
 | 
			
		||||
                [msg.sender]
 | 
			
		||||
                [address(makerToken)]
 | 
			
		||||
                [address(takerToken)];
 | 
			
		||||
 | 
			
		||||
        // New min salt must >= the old one.
 | 
			
		||||
        if (oldMinValidSalt > minValidSalt) {
 | 
			
		||||
            LibNativeOrdersRichErrors.
 | 
			
		||||
                CancelSaltTooLowError(minValidSalt, oldMinValidSalt)
 | 
			
		||||
                    .rrevert();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        stor.rfqOrdersMakerToMakerTokenToTakerTokenToMinValidOrderSalt
 | 
			
		||||
            [msg.sender]
 | 
			
		||||
            [address(makerToken)]
 | 
			
		||||
            [address(takerToken)] = minValidSalt;
 | 
			
		||||
 | 
			
		||||
        emit PairCancelledRfqOrders(
 | 
			
		||||
            msg.sender,
 | 
			
		||||
            address(makerToken),
 | 
			
		||||
            address(takerToken),
 | 
			
		||||
            minValidSalt
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Cancel all RFQ orders for a given maker and pair with a salt less
 | 
			
		||||
    ///      than the value provided. The caller must be the maker. Subsequent
 | 
			
		||||
    ///      calls to this function with the same caller and pair require the
 | 
			
		||||
    ///      new salt to be >= the old salt.
 | 
			
		||||
    /// @param makerTokens The maker tokens.
 | 
			
		||||
    /// @param takerTokens The taker tokens.
 | 
			
		||||
    /// @param minValidSalts The new minimum valid salts.
 | 
			
		||||
    function batchCancelPairRfqOrders(
 | 
			
		||||
        IERC20TokenV06[] memory makerTokens,
 | 
			
		||||
        IERC20TokenV06[] memory takerTokens,
 | 
			
		||||
        uint256[] memory minValidSalts
 | 
			
		||||
    )
 | 
			
		||||
        public
 | 
			
		||||
    {
 | 
			
		||||
        require(
 | 
			
		||||
            makerTokens.length == takerTokens.length &&
 | 
			
		||||
            makerTokens.length == minValidSalts.length,
 | 
			
		||||
            "NativeOrdersFeature/MISMATCHED_PAIR_ORDERS_ARRAY_LENGTHS"
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        for (uint256 i = 0; i < makerTokens.length; ++i) {
 | 
			
		||||
            cancelPairRfqOrders(
 | 
			
		||||
                makerTokens[i],
 | 
			
		||||
                takerTokens[i],
 | 
			
		||||
                minValidSalts[i]
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Cancel a limit or RFQ order directly by its order hash.
 | 
			
		||||
    /// @param orderHash The order's order hash.
 | 
			
		||||
    /// @param maker The order's maker.
 | 
			
		||||
    function _cancelOrderHash(bytes32 orderHash, address maker)
 | 
			
		||||
        private
 | 
			
		||||
    {
 | 
			
		||||
        LibNativeOrdersStorage.Storage storage stor =
 | 
			
		||||
            LibNativeOrdersStorage.getStorage();
 | 
			
		||||
        // Set the high bit on the raw taker token fill amount to indicate
 | 
			
		||||
        // a cancel. It's OK to cancel twice.
 | 
			
		||||
        stor.orderHashToTakerTokenFilledAmount[orderHash] |= HIGH_BIT;
 | 
			
		||||
 | 
			
		||||
        emit OrderCancelled(orderHash, maker);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,394 @@
 | 
			
		||||
// SPDX-License-Identifier: Apache-2.0
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  Copyright 2021 ZeroEx Intl.
 | 
			
		||||
 | 
			
		||||
  Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
  you may not use this file except in compliance with the License.
 | 
			
		||||
  You may obtain a copy of the License at
 | 
			
		||||
 | 
			
		||||
    http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 | 
			
		||||
  Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
  distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
  See the License for the specific language governing permissions and
 | 
			
		||||
  limitations under the License.
 | 
			
		||||
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
pragma solidity ^0.6.5;
 | 
			
		||||
pragma experimental ABIEncoderV2;
 | 
			
		||||
 | 
			
		||||
import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol";
 | 
			
		||||
import "@0x/contracts-utils/contracts/src/v06/LibSafeMathV06.sol";
 | 
			
		||||
import "@0x/contracts-utils/contracts/src/v06/LibMathV06.sol";
 | 
			
		||||
import "../../fixins/FixinEIP712.sol";
 | 
			
		||||
import "../../fixins/FixinTokenSpender.sol";
 | 
			
		||||
import "../../storage/LibNativeOrdersStorage.sol";
 | 
			
		||||
import "../libs/LibSignature.sol";
 | 
			
		||||
import "../libs/LibNativeOrder.sol";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/// @dev Feature for getting info about limit and RFQ orders.
 | 
			
		||||
abstract contract NativeOrdersInfo is
 | 
			
		||||
    FixinEIP712,
 | 
			
		||||
    FixinTokenSpender
 | 
			
		||||
{
 | 
			
		||||
    using LibSafeMathV06 for uint256;
 | 
			
		||||
    using LibRichErrorsV06 for bytes;
 | 
			
		||||
 | 
			
		||||
    // @dev Params for `_getActualFillableTakerTokenAmount()`.
 | 
			
		||||
    struct GetActualFillableTakerTokenAmountParams {
 | 
			
		||||
        address maker;
 | 
			
		||||
        IERC20TokenV06 makerToken;
 | 
			
		||||
        uint128 orderMakerAmount;
 | 
			
		||||
        uint128 orderTakerAmount;
 | 
			
		||||
        LibNativeOrder.OrderInfo orderInfo;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Highest bit of a uint256, used to flag cancelled orders.
 | 
			
		||||
    uint256 private constant HIGH_BIT = 1 << 255;
 | 
			
		||||
 | 
			
		||||
    constructor(
 | 
			
		||||
        address zeroExAddress,
 | 
			
		||||
        bytes32 greedyTokensBloomFilter
 | 
			
		||||
    )
 | 
			
		||||
        internal
 | 
			
		||||
        FixinEIP712(zeroExAddress)
 | 
			
		||||
        FixinTokenSpender(greedyTokensBloomFilter)
 | 
			
		||||
    {
 | 
			
		||||
        // solhint-disable no-empty-blocks
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Get the order info for a limit order.
 | 
			
		||||
    /// @param order The limit order.
 | 
			
		||||
    /// @return orderInfo Info about the order.
 | 
			
		||||
    function getLimitOrderInfo(LibNativeOrder.LimitOrder memory order)
 | 
			
		||||
        public
 | 
			
		||||
        view
 | 
			
		||||
        returns (LibNativeOrder.OrderInfo memory orderInfo)
 | 
			
		||||
    {
 | 
			
		||||
        // Recover maker and compute order hash.
 | 
			
		||||
        orderInfo.orderHash = getLimitOrderHash(order);
 | 
			
		||||
        uint256 minValidSalt = LibNativeOrdersStorage.getStorage()
 | 
			
		||||
            .limitOrdersMakerToMakerTokenToTakerTokenToMinValidOrderSalt
 | 
			
		||||
                [order.maker]
 | 
			
		||||
                [address(order.makerToken)]
 | 
			
		||||
                [address(order.takerToken)];
 | 
			
		||||
        _populateCommonOrderInfoFields(
 | 
			
		||||
            orderInfo,
 | 
			
		||||
            order.takerAmount,
 | 
			
		||||
            order.expiry,
 | 
			
		||||
            order.salt,
 | 
			
		||||
            minValidSalt
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Get the order info for an RFQ order.
 | 
			
		||||
    /// @param order The RFQ order.
 | 
			
		||||
    /// @return orderInfo Info about the order.
 | 
			
		||||
    function getRfqOrderInfo(LibNativeOrder.RfqOrder memory order)
 | 
			
		||||
        public
 | 
			
		||||
        view
 | 
			
		||||
        returns (LibNativeOrder.OrderInfo memory orderInfo)
 | 
			
		||||
    {
 | 
			
		||||
        // Recover maker and compute order hash.
 | 
			
		||||
        orderInfo.orderHash = getRfqOrderHash(order);
 | 
			
		||||
        uint256 minValidSalt = LibNativeOrdersStorage.getStorage()
 | 
			
		||||
            .rfqOrdersMakerToMakerTokenToTakerTokenToMinValidOrderSalt
 | 
			
		||||
                [order.maker]
 | 
			
		||||
                [address(order.makerToken)]
 | 
			
		||||
                [address(order.takerToken)];
 | 
			
		||||
        _populateCommonOrderInfoFields(
 | 
			
		||||
            orderInfo,
 | 
			
		||||
            order.takerAmount,
 | 
			
		||||
            order.expiry,
 | 
			
		||||
            order.salt,
 | 
			
		||||
            minValidSalt
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        // Check for missing txOrigin.
 | 
			
		||||
        if (order.txOrigin == address(0)) {
 | 
			
		||||
            orderInfo.status = LibNativeOrder.OrderStatus.INVALID;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Get the canonical hash of a limit order.
 | 
			
		||||
    /// @param order The limit order.
 | 
			
		||||
    /// @return orderHash The order hash.
 | 
			
		||||
    function getLimitOrderHash(LibNativeOrder.LimitOrder memory order)
 | 
			
		||||
        public
 | 
			
		||||
        view
 | 
			
		||||
        returns (bytes32 orderHash)
 | 
			
		||||
    {
 | 
			
		||||
        return _getEIP712Hash(
 | 
			
		||||
            LibNativeOrder.getLimitOrderStructHash(order)
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Get the canonical hash of an RFQ order.
 | 
			
		||||
    /// @param order The RFQ order.
 | 
			
		||||
    /// @return orderHash The order hash.
 | 
			
		||||
    function getRfqOrderHash(LibNativeOrder.RfqOrder memory order)
 | 
			
		||||
        public
 | 
			
		||||
        view
 | 
			
		||||
        returns (bytes32 orderHash)
 | 
			
		||||
    {
 | 
			
		||||
        return _getEIP712Hash(
 | 
			
		||||
            LibNativeOrder.getRfqOrderStructHash(order)
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Get order info, fillable amount, and signature validity for a limit order.
 | 
			
		||||
    ///      Fillable amount is determined using balances and allowances of the maker.
 | 
			
		||||
    /// @param order The limit order.
 | 
			
		||||
    /// @param signature The order signature.
 | 
			
		||||
    /// @return orderInfo Info about the order.
 | 
			
		||||
    /// @return actualFillableTakerTokenAmount How much of the order is fillable
 | 
			
		||||
    ///         based on maker funds, in taker tokens.
 | 
			
		||||
    /// @return isSignatureValid Whether the signature is valid.
 | 
			
		||||
    function getLimitOrderRelevantState(
 | 
			
		||||
        LibNativeOrder.LimitOrder memory order,
 | 
			
		||||
        LibSignature.Signature calldata signature
 | 
			
		||||
    )
 | 
			
		||||
        public
 | 
			
		||||
        view
 | 
			
		||||
        returns (
 | 
			
		||||
            LibNativeOrder.OrderInfo memory orderInfo,
 | 
			
		||||
            uint128 actualFillableTakerTokenAmount,
 | 
			
		||||
            bool isSignatureValid
 | 
			
		||||
        )
 | 
			
		||||
    {
 | 
			
		||||
        orderInfo = getLimitOrderInfo(order);
 | 
			
		||||
        actualFillableTakerTokenAmount = _getActualFillableTakerTokenAmount(
 | 
			
		||||
            GetActualFillableTakerTokenAmountParams({
 | 
			
		||||
                maker: order.maker,
 | 
			
		||||
                makerToken: order.makerToken,
 | 
			
		||||
                orderMakerAmount: order.makerAmount,
 | 
			
		||||
                orderTakerAmount: order.takerAmount,
 | 
			
		||||
                orderInfo: orderInfo
 | 
			
		||||
            })
 | 
			
		||||
        );
 | 
			
		||||
        isSignatureValid = order.maker ==
 | 
			
		||||
            LibSignature.getSignerOfHash(orderInfo.orderHash, signature);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Get order info, fillable amount, and signature validity for an RFQ order.
 | 
			
		||||
    ///      Fillable amount is determined using balances and allowances of the maker.
 | 
			
		||||
    /// @param order The RFQ order.
 | 
			
		||||
    /// @param signature The order signature.
 | 
			
		||||
    /// @return orderInfo Info about the order.
 | 
			
		||||
    /// @return actualFillableTakerTokenAmount How much of the order is fillable
 | 
			
		||||
    ///         based on maker funds, in taker tokens.
 | 
			
		||||
    /// @return isSignatureValid Whether the signature is valid.
 | 
			
		||||
    function getRfqOrderRelevantState(
 | 
			
		||||
        LibNativeOrder.RfqOrder memory order,
 | 
			
		||||
        LibSignature.Signature memory signature
 | 
			
		||||
    )
 | 
			
		||||
        public
 | 
			
		||||
        view
 | 
			
		||||
        returns (
 | 
			
		||||
            LibNativeOrder.OrderInfo memory orderInfo,
 | 
			
		||||
            uint128 actualFillableTakerTokenAmount,
 | 
			
		||||
            bool isSignatureValid
 | 
			
		||||
        )
 | 
			
		||||
    {
 | 
			
		||||
        orderInfo = getRfqOrderInfo(order);
 | 
			
		||||
        actualFillableTakerTokenAmount = _getActualFillableTakerTokenAmount(
 | 
			
		||||
            GetActualFillableTakerTokenAmountParams({
 | 
			
		||||
                maker: order.maker,
 | 
			
		||||
                makerToken: order.makerToken,
 | 
			
		||||
                orderMakerAmount: order.makerAmount,
 | 
			
		||||
                orderTakerAmount: order.takerAmount,
 | 
			
		||||
                orderInfo: orderInfo
 | 
			
		||||
            })
 | 
			
		||||
        );
 | 
			
		||||
        isSignatureValid = order.maker ==
 | 
			
		||||
            LibSignature.getSignerOfHash(orderInfo.orderHash, signature);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Batch version of `getLimitOrderRelevantState()`, without reverting.
 | 
			
		||||
    ///      Orders that would normally cause `getLimitOrderRelevantState()`
 | 
			
		||||
    ///      to revert will have empty results.
 | 
			
		||||
    /// @param orders The limit orders.
 | 
			
		||||
    /// @param signatures The order signatures.
 | 
			
		||||
    /// @return orderInfos Info about the orders.
 | 
			
		||||
    /// @return actualFillableTakerTokenAmounts How much of each order is fillable
 | 
			
		||||
    ///         based on maker funds, in taker tokens.
 | 
			
		||||
    /// @return isSignatureValids Whether each signature is valid for the order.
 | 
			
		||||
    function batchGetLimitOrderRelevantStates(
 | 
			
		||||
        LibNativeOrder.LimitOrder[] calldata orders,
 | 
			
		||||
        LibSignature.Signature[] calldata signatures
 | 
			
		||||
    )
 | 
			
		||||
        external
 | 
			
		||||
        view
 | 
			
		||||
        returns (
 | 
			
		||||
            LibNativeOrder.OrderInfo[] memory orderInfos,
 | 
			
		||||
            uint128[] memory actualFillableTakerTokenAmounts,
 | 
			
		||||
            bool[] memory isSignatureValids
 | 
			
		||||
        )
 | 
			
		||||
    {
 | 
			
		||||
        require(
 | 
			
		||||
            orders.length == signatures.length,
 | 
			
		||||
            "NativeOrdersFeature/MISMATCHED_ARRAY_LENGTHS"
 | 
			
		||||
        );
 | 
			
		||||
        orderInfos = new LibNativeOrder.OrderInfo[](orders.length);
 | 
			
		||||
        actualFillableTakerTokenAmounts = new uint128[](orders.length);
 | 
			
		||||
        isSignatureValids = new bool[](orders.length);
 | 
			
		||||
        for (uint256 i = 0; i < orders.length; ++i) {
 | 
			
		||||
            try
 | 
			
		||||
                this.getLimitOrderRelevantState(orders[i], signatures[i])
 | 
			
		||||
                    returns (
 | 
			
		||||
                        LibNativeOrder.OrderInfo memory orderInfo,
 | 
			
		||||
                        uint128 actualFillableTakerTokenAmount,
 | 
			
		||||
                        bool isSignatureValid
 | 
			
		||||
                    )
 | 
			
		||||
            {
 | 
			
		||||
                orderInfos[i] = orderInfo;
 | 
			
		||||
                actualFillableTakerTokenAmounts[i] = actualFillableTakerTokenAmount;
 | 
			
		||||
                isSignatureValids[i] = isSignatureValid;
 | 
			
		||||
            }
 | 
			
		||||
            catch {}
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Batch version of `getRfqOrderRelevantState()`, without reverting.
 | 
			
		||||
    ///      Orders that would normally cause `getRfqOrderRelevantState()`
 | 
			
		||||
    ///      to revert will have empty results.
 | 
			
		||||
    /// @param orders The RFQ orders.
 | 
			
		||||
    /// @param signatures The order signatures.
 | 
			
		||||
    /// @return orderInfos Info about the orders.
 | 
			
		||||
    /// @return actualFillableTakerTokenAmounts How much of each order is fillable
 | 
			
		||||
    ///         based on maker funds, in taker tokens.
 | 
			
		||||
    /// @return isSignatureValids Whether each signature is valid for the order.
 | 
			
		||||
    function batchGetRfqOrderRelevantStates(
 | 
			
		||||
        LibNativeOrder.RfqOrder[] calldata orders,
 | 
			
		||||
        LibSignature.Signature[] calldata signatures
 | 
			
		||||
    )
 | 
			
		||||
        external
 | 
			
		||||
        view
 | 
			
		||||
        returns (
 | 
			
		||||
            LibNativeOrder.OrderInfo[] memory orderInfos,
 | 
			
		||||
            uint128[] memory actualFillableTakerTokenAmounts,
 | 
			
		||||
            bool[] memory isSignatureValids
 | 
			
		||||
        )
 | 
			
		||||
    {
 | 
			
		||||
        require(
 | 
			
		||||
            orders.length == signatures.length,
 | 
			
		||||
            "NativeOrdersFeature/MISMATCHED_ARRAY_LENGTHS"
 | 
			
		||||
        );
 | 
			
		||||
        orderInfos = new LibNativeOrder.OrderInfo[](orders.length);
 | 
			
		||||
        actualFillableTakerTokenAmounts = new uint128[](orders.length);
 | 
			
		||||
        isSignatureValids = new bool[](orders.length);
 | 
			
		||||
        for (uint256 i = 0; i < orders.length; ++i) {
 | 
			
		||||
            try
 | 
			
		||||
                this.getRfqOrderRelevantState(orders[i], signatures[i])
 | 
			
		||||
                    returns (
 | 
			
		||||
                        LibNativeOrder.OrderInfo memory orderInfo,
 | 
			
		||||
                        uint128 actualFillableTakerTokenAmount,
 | 
			
		||||
                        bool isSignatureValid
 | 
			
		||||
                    )
 | 
			
		||||
            {
 | 
			
		||||
                orderInfos[i] = orderInfo;
 | 
			
		||||
                actualFillableTakerTokenAmounts[i] = actualFillableTakerTokenAmount;
 | 
			
		||||
                isSignatureValids[i] = isSignatureValid;
 | 
			
		||||
            }
 | 
			
		||||
            catch {}
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Populate `status` and `takerTokenFilledAmount` fields in
 | 
			
		||||
    ///      `orderInfo`, which use the same code path for both limit and
 | 
			
		||||
    ///      RFQ orders.
 | 
			
		||||
    /// @param orderInfo `OrderInfo` with `orderHash` and `maker` filled.
 | 
			
		||||
    /// @param takerAmount The order's taker token amount..
 | 
			
		||||
    /// @param expiry The order's expiry.
 | 
			
		||||
    /// @param salt The order's salt.
 | 
			
		||||
    /// @param salt The minimum valid salt for the maker and pair combination.
 | 
			
		||||
    function _populateCommonOrderInfoFields(
 | 
			
		||||
        LibNativeOrder.OrderInfo memory orderInfo,
 | 
			
		||||
        uint128 takerAmount,
 | 
			
		||||
        uint64 expiry,
 | 
			
		||||
        uint256 salt,
 | 
			
		||||
        uint256 minValidSalt
 | 
			
		||||
    )
 | 
			
		||||
        private
 | 
			
		||||
        view
 | 
			
		||||
    {
 | 
			
		||||
        LibNativeOrdersStorage.Storage storage stor =
 | 
			
		||||
            LibNativeOrdersStorage.getStorage();
 | 
			
		||||
 | 
			
		||||
        // Get the filled and direct cancel state.
 | 
			
		||||
        {
 | 
			
		||||
            // The high bit of the raw taker token filled amount will be set
 | 
			
		||||
            // if the order was cancelled.
 | 
			
		||||
            uint256 rawTakerTokenFilledAmount =
 | 
			
		||||
                stor.orderHashToTakerTokenFilledAmount[orderInfo.orderHash];
 | 
			
		||||
            orderInfo.takerTokenFilledAmount = uint128(rawTakerTokenFilledAmount);
 | 
			
		||||
            if (orderInfo.takerTokenFilledAmount >= takerAmount) {
 | 
			
		||||
                orderInfo.status = LibNativeOrder.OrderStatus.FILLED;
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            if (rawTakerTokenFilledAmount & HIGH_BIT != 0) {
 | 
			
		||||
                orderInfo.status = LibNativeOrder.OrderStatus.CANCELLED;
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Check for expiration.
 | 
			
		||||
        if (expiry <= uint64(block.timestamp)) {
 | 
			
		||||
            orderInfo.status = LibNativeOrder.OrderStatus.EXPIRED;
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Check if the order was cancelled by salt.
 | 
			
		||||
        if (minValidSalt > salt) {
 | 
			
		||||
            orderInfo.status = LibNativeOrder.OrderStatus.CANCELLED;
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        orderInfo.status = LibNativeOrder.OrderStatus.FILLABLE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Calculate the actual fillable taker token amount of an order
 | 
			
		||||
    ///      based on maker allowance and balances.
 | 
			
		||||
    function _getActualFillableTakerTokenAmount(
 | 
			
		||||
        GetActualFillableTakerTokenAmountParams memory params
 | 
			
		||||
    )
 | 
			
		||||
        private
 | 
			
		||||
        view
 | 
			
		||||
        returns (uint128 actualFillableTakerTokenAmount)
 | 
			
		||||
    {
 | 
			
		||||
        if (params.orderMakerAmount == 0 || params.orderTakerAmount == 0) {
 | 
			
		||||
            // Empty order.
 | 
			
		||||
            return 0;
 | 
			
		||||
        }
 | 
			
		||||
        if (params.orderInfo.status != LibNativeOrder.OrderStatus.FILLABLE) {
 | 
			
		||||
            // Not fillable.
 | 
			
		||||
            return 0;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Get the fillable maker amount based on the order quantities and
 | 
			
		||||
        // previously filled amount
 | 
			
		||||
        uint256 fillableMakerTokenAmount = LibMathV06.getPartialAmountFloor(
 | 
			
		||||
            uint256(
 | 
			
		||||
                params.orderTakerAmount
 | 
			
		||||
                - params.orderInfo.takerTokenFilledAmount
 | 
			
		||||
            ),
 | 
			
		||||
            uint256(params.orderTakerAmount),
 | 
			
		||||
            uint256(params.orderMakerAmount)
 | 
			
		||||
        );
 | 
			
		||||
        // Clamp it to the amount of maker tokens we can spend on behalf of the
 | 
			
		||||
        // maker.
 | 
			
		||||
        fillableMakerTokenAmount = LibSafeMathV06.min256(
 | 
			
		||||
            fillableMakerTokenAmount,
 | 
			
		||||
            _getSpendableERC20BalanceOf(params.makerToken, params.maker)
 | 
			
		||||
        );
 | 
			
		||||
        // Convert to taker token amount.
 | 
			
		||||
        return LibMathV06.getPartialAmountCeil(
 | 
			
		||||
            fillableMakerTokenAmount,
 | 
			
		||||
            uint256(params.orderMakerAmount),
 | 
			
		||||
            uint256(params.orderTakerAmount)
 | 
			
		||||
        ).safeDowncastToUint128();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,71 @@
 | 
			
		||||
// SPDX-License-Identifier: Apache-2.0
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  Copyright 2021 ZeroEx Intl.
 | 
			
		||||
 | 
			
		||||
  Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
  you may not use this file except in compliance with the License.
 | 
			
		||||
  You may obtain a copy of the License at
 | 
			
		||||
 | 
			
		||||
    http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 | 
			
		||||
  Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
  distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
  See the License for the specific language governing permissions and
 | 
			
		||||
  limitations under the License.
 | 
			
		||||
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
pragma solidity ^0.6.5;
 | 
			
		||||
pragma experimental ABIEncoderV2;
 | 
			
		||||
 | 
			
		||||
import "@0x/contracts-erc20/contracts/src/v06/IEtherTokenV06.sol";
 | 
			
		||||
import "@0x/contracts-utils/contracts/src/v06/errors/LibRichErrorsV06.sol";
 | 
			
		||||
import "@0x/contracts-utils/contracts/src/v06/LibSafeMathV06.sol";
 | 
			
		||||
import "../../fixins/FixinProtocolFees.sol";
 | 
			
		||||
import "../../errors/LibNativeOrdersRichErrors.sol";
 | 
			
		||||
import "../../vendor/v3/IStaking.sol";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/// @dev Mixin for protocol fee utility functions.
 | 
			
		||||
abstract contract NativeOrdersProtocolFees is
 | 
			
		||||
    FixinProtocolFees
 | 
			
		||||
{
 | 
			
		||||
    using LibSafeMathV06 for uint256;
 | 
			
		||||
    using LibRichErrorsV06 for bytes;
 | 
			
		||||
 | 
			
		||||
    constructor(
 | 
			
		||||
        IEtherTokenV06 weth,
 | 
			
		||||
        IStaking staking,
 | 
			
		||||
        FeeCollectorController feeCollectorController,
 | 
			
		||||
        uint32 protocolFeeMultiplier
 | 
			
		||||
    )
 | 
			
		||||
        internal
 | 
			
		||||
        FixinProtocolFees(weth, staking, feeCollectorController, protocolFeeMultiplier)
 | 
			
		||||
    {
 | 
			
		||||
        // solhint-disable no-empty-blocks
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Transfers protocol fees from the `FeeCollector` pools into
 | 
			
		||||
    ///      the staking contract.
 | 
			
		||||
    /// @param poolIds Staking pool IDs
 | 
			
		||||
    function transferProtocolFeesForPools(bytes32[] calldata poolIds)
 | 
			
		||||
        external
 | 
			
		||||
    {
 | 
			
		||||
        for (uint256 i = 0; i < poolIds.length; ++i) {
 | 
			
		||||
            _transferFeesForPool(poolIds[i]);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Get the protocol fee multiplier. This should be multiplied by the
 | 
			
		||||
    ///      gas price to arrive at the required protocol fee to fill a native order.
 | 
			
		||||
    /// @return multiplier The protocol fee multiplier.
 | 
			
		||||
    function getProtocolFeeMultiplier()
 | 
			
		||||
        external
 | 
			
		||||
        view
 | 
			
		||||
        returns (uint32 multiplier)
 | 
			
		||||
    {
 | 
			
		||||
        return PROTOCOL_FEE_MULTIPLIER;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -0,0 +1,569 @@
 | 
			
		||||
// SPDX-License-Identifier: Apache-2.0
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  Copyright 2021 ZeroEx Intl.
 | 
			
		||||
 | 
			
		||||
  Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
  you may not use this file except in compliance with the License.
 | 
			
		||||
  You may obtain a copy of the License at
 | 
			
		||||
 | 
			
		||||
    http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 | 
			
		||||
  Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
  distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
  See the License for the specific language governing permissions and
 | 
			
		||||
  limitations under the License.
 | 
			
		||||
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
pragma solidity ^0.6.5;
 | 
			
		||||
pragma experimental ABIEncoderV2;
 | 
			
		||||
 | 
			
		||||
import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol";
 | 
			
		||||
import "@0x/contracts-erc20/contracts/src/v06/IEtherTokenV06.sol";
 | 
			
		||||
import "@0x/contracts-utils/contracts/src/v06/errors/LibRichErrorsV06.sol";
 | 
			
		||||
import "@0x/contracts-utils/contracts/src/v06/LibSafeMathV06.sol";
 | 
			
		||||
import "@0x/contracts-utils/contracts/src/v06/LibMathV06.sol";
 | 
			
		||||
import "../../errors/LibNativeOrdersRichErrors.sol";
 | 
			
		||||
import "../../fixins/FixinCommon.sol";
 | 
			
		||||
import "../../storage/LibNativeOrdersStorage.sol";
 | 
			
		||||
import "../../vendor/v3/IStaking.sol";
 | 
			
		||||
import "../interfaces/INativeOrdersEvents.sol";
 | 
			
		||||
import "../libs/LibSignature.sol";
 | 
			
		||||
import "../libs/LibNativeOrder.sol";
 | 
			
		||||
import "./NativeOrdersCancellation.sol";
 | 
			
		||||
import "./NativeOrdersProtocolFees.sol";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/// @dev Mixin for settling limit and RFQ orders.
 | 
			
		||||
abstract contract NativeOrdersSettlement is
 | 
			
		||||
    INativeOrdersEvents,
 | 
			
		||||
    NativeOrdersCancellation,
 | 
			
		||||
    NativeOrdersProtocolFees,
 | 
			
		||||
    FixinCommon
 | 
			
		||||
{
 | 
			
		||||
    using LibSafeMathV06 for uint128;
 | 
			
		||||
    using LibRichErrorsV06 for bytes;
 | 
			
		||||
 | 
			
		||||
    /// @dev Params for `_settleOrder()`.
 | 
			
		||||
    struct SettleOrderInfo {
 | 
			
		||||
        // Order hash.
 | 
			
		||||
        bytes32 orderHash;
 | 
			
		||||
        // Maker of the order.
 | 
			
		||||
        address maker;
 | 
			
		||||
        // Taker of the order.
 | 
			
		||||
        address taker;
 | 
			
		||||
        // Maker token.
 | 
			
		||||
        IERC20TokenV06 makerToken;
 | 
			
		||||
        // Taker token.
 | 
			
		||||
        IERC20TokenV06 takerToken;
 | 
			
		||||
        // Maker token amount.
 | 
			
		||||
        uint128 makerAmount;
 | 
			
		||||
        // Taker token amount.
 | 
			
		||||
        uint128 takerAmount;
 | 
			
		||||
        // Maximum taker token amount to fill.
 | 
			
		||||
        uint128 takerTokenFillAmount;
 | 
			
		||||
        // How much taker token amount has already been filled in this order.
 | 
			
		||||
        uint128 takerTokenFilledAmount;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Params for `_fillLimitOrderPrivate()`
 | 
			
		||||
    struct FillLimitOrderPrivateParams {
 | 
			
		||||
        // The limit order.
 | 
			
		||||
        LibNativeOrder.LimitOrder order;
 | 
			
		||||
        // The order signature.
 | 
			
		||||
        LibSignature.Signature signature;
 | 
			
		||||
        // Maximum taker token to fill this order with.
 | 
			
		||||
        uint128 takerTokenFillAmount;
 | 
			
		||||
        // The order taker.
 | 
			
		||||
        address taker;
 | 
			
		||||
        // The order sender.
 | 
			
		||||
        address sender;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // @dev Fill results returned by `_fillLimitOrderPrivate()` and
 | 
			
		||||
    ///     `_fillRfqOrderPrivate()`.
 | 
			
		||||
    struct FillNativeOrderResults {
 | 
			
		||||
        uint256 ethProtocolFeePaid;
 | 
			
		||||
        uint128 takerTokenFilledAmount;
 | 
			
		||||
        uint128 makerTokenFilledAmount;
 | 
			
		||||
        uint128 takerTokenFeeFilledAmount;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    constructor(
 | 
			
		||||
        address zeroExAddress,
 | 
			
		||||
        IEtherTokenV06 weth,
 | 
			
		||||
        IStaking staking,
 | 
			
		||||
        FeeCollectorController feeCollectorController,
 | 
			
		||||
        uint32 protocolFeeMultiplier,
 | 
			
		||||
        bytes32 greedyTokensBloomFilter
 | 
			
		||||
    )
 | 
			
		||||
        public
 | 
			
		||||
        NativeOrdersCancellation(zeroExAddress, greedyTokensBloomFilter)
 | 
			
		||||
        NativeOrdersProtocolFees(weth, staking, feeCollectorController, protocolFeeMultiplier)
 | 
			
		||||
    {
 | 
			
		||||
        // solhint-disable no-empty-blocks
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Fill a limit order. The taker and sender will be the caller.
 | 
			
		||||
    /// @param order The limit order. ETH protocol fees can be
 | 
			
		||||
    ///      attached to this call. Any unspent ETH will be refunded to
 | 
			
		||||
    ///      the caller.
 | 
			
		||||
    /// @param signature The order signature.
 | 
			
		||||
    /// @param takerTokenFillAmount Maximum taker token amount to fill this order with.
 | 
			
		||||
    /// @return takerTokenFilledAmount How much maker token was filled.
 | 
			
		||||
    /// @return makerTokenFilledAmount How much maker token was filled.
 | 
			
		||||
    function fillLimitOrder(
 | 
			
		||||
        LibNativeOrder.LimitOrder memory order,
 | 
			
		||||
        LibSignature.Signature memory signature,
 | 
			
		||||
        uint128 takerTokenFillAmount
 | 
			
		||||
    )
 | 
			
		||||
        public
 | 
			
		||||
        payable
 | 
			
		||||
        returns (uint128 takerTokenFilledAmount, uint128 makerTokenFilledAmount)
 | 
			
		||||
    {
 | 
			
		||||
        FillNativeOrderResults memory results =
 | 
			
		||||
            _fillLimitOrderPrivate(FillLimitOrderPrivateParams({
 | 
			
		||||
                order: order,
 | 
			
		||||
                signature: signature,
 | 
			
		||||
                takerTokenFillAmount: takerTokenFillAmount,
 | 
			
		||||
                taker: msg.sender,
 | 
			
		||||
                sender: msg.sender
 | 
			
		||||
            }));
 | 
			
		||||
        LibNativeOrder.refundExcessProtocolFeeToSender(results.ethProtocolFeePaid);
 | 
			
		||||
        (takerTokenFilledAmount, makerTokenFilledAmount) = (
 | 
			
		||||
            results.takerTokenFilledAmount,
 | 
			
		||||
            results.makerTokenFilledAmount
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Fill an RFQ order for up to `takerTokenFillAmount` taker tokens.
 | 
			
		||||
    ///      The taker will be the caller. ETH should be attached to pay the
 | 
			
		||||
    ///      protocol fee.
 | 
			
		||||
    /// @param order The RFQ order.
 | 
			
		||||
    /// @param signature The order signature.
 | 
			
		||||
    /// @param takerTokenFillAmount Maximum taker token amount to fill this order with.
 | 
			
		||||
    /// @return takerTokenFilledAmount How much maker token was filled.
 | 
			
		||||
    /// @return makerTokenFilledAmount How much maker token was filled.
 | 
			
		||||
    function fillRfqOrder(
 | 
			
		||||
        LibNativeOrder.RfqOrder memory order,
 | 
			
		||||
        LibSignature.Signature memory signature,
 | 
			
		||||
        uint128 takerTokenFillAmount
 | 
			
		||||
    )
 | 
			
		||||
        public
 | 
			
		||||
        returns (uint128 takerTokenFilledAmount, uint128 makerTokenFilledAmount)
 | 
			
		||||
    {
 | 
			
		||||
        FillNativeOrderResults memory results =
 | 
			
		||||
            _fillRfqOrderPrivate(
 | 
			
		||||
                order,
 | 
			
		||||
                signature,
 | 
			
		||||
                takerTokenFillAmount,
 | 
			
		||||
                msg.sender
 | 
			
		||||
            );
 | 
			
		||||
        (takerTokenFilledAmount, makerTokenFilledAmount) = (
 | 
			
		||||
            results.takerTokenFilledAmount,
 | 
			
		||||
            results.makerTokenFilledAmount
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Fill an RFQ order for exactly `takerTokenFillAmount` taker tokens.
 | 
			
		||||
    ///      The taker will be the caller. ETH protocol fees can be
 | 
			
		||||
    ///      attached to this call. Any unspent ETH will be refunded to
 | 
			
		||||
    ///      the caller.
 | 
			
		||||
    /// @param order The limit order.
 | 
			
		||||
    /// @param signature The order signature.
 | 
			
		||||
    /// @param takerTokenFillAmount How much taker token to fill this order with.
 | 
			
		||||
    /// @return makerTokenFilledAmount How much maker token was filled.
 | 
			
		||||
    function fillOrKillLimitOrder(
 | 
			
		||||
        LibNativeOrder.LimitOrder memory order,
 | 
			
		||||
        LibSignature.Signature memory signature,
 | 
			
		||||
        uint128 takerTokenFillAmount
 | 
			
		||||
    )
 | 
			
		||||
        public
 | 
			
		||||
        payable
 | 
			
		||||
        returns (uint128 makerTokenFilledAmount)
 | 
			
		||||
    {
 | 
			
		||||
        FillNativeOrderResults memory results =
 | 
			
		||||
            _fillLimitOrderPrivate(FillLimitOrderPrivateParams({
 | 
			
		||||
                order: order,
 | 
			
		||||
                signature: signature,
 | 
			
		||||
                takerTokenFillAmount: takerTokenFillAmount,
 | 
			
		||||
                taker: msg.sender,
 | 
			
		||||
                sender: msg.sender
 | 
			
		||||
            }));
 | 
			
		||||
        // Must have filled exactly the amount requested.
 | 
			
		||||
        if (results.takerTokenFilledAmount < takerTokenFillAmount) {
 | 
			
		||||
            LibNativeOrdersRichErrors.FillOrKillFailedError(
 | 
			
		||||
                getLimitOrderHash(order),
 | 
			
		||||
                results.takerTokenFilledAmount,
 | 
			
		||||
                takerTokenFillAmount
 | 
			
		||||
            ).rrevert();
 | 
			
		||||
        }
 | 
			
		||||
        LibNativeOrder.refundExcessProtocolFeeToSender(results.ethProtocolFeePaid);
 | 
			
		||||
        makerTokenFilledAmount = results.makerTokenFilledAmount;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Fill an RFQ order for exactly `takerTokenFillAmount` taker tokens.
 | 
			
		||||
    ///      The taker will be the caller. ETH protocol fees can be
 | 
			
		||||
    ///      attached to this call. Any unspent ETH will be refunded to
 | 
			
		||||
    ///      the caller.
 | 
			
		||||
    /// @param order The RFQ order.
 | 
			
		||||
    /// @param signature The order signature.
 | 
			
		||||
    /// @param takerTokenFillAmount How much taker token to fill this order with.
 | 
			
		||||
    /// @return makerTokenFilledAmount How much maker token was filled.
 | 
			
		||||
    function fillOrKillRfqOrder(
 | 
			
		||||
        LibNativeOrder.RfqOrder memory order,
 | 
			
		||||
        LibSignature.Signature memory signature,
 | 
			
		||||
        uint128 takerTokenFillAmount
 | 
			
		||||
    )
 | 
			
		||||
        public
 | 
			
		||||
        returns (uint128 makerTokenFilledAmount)
 | 
			
		||||
    {
 | 
			
		||||
        FillNativeOrderResults memory results =
 | 
			
		||||
            _fillRfqOrderPrivate(
 | 
			
		||||
                order,
 | 
			
		||||
                signature,
 | 
			
		||||
                takerTokenFillAmount,
 | 
			
		||||
                msg.sender
 | 
			
		||||
            );
 | 
			
		||||
        // Must have filled exactly the amount requested.
 | 
			
		||||
        if (results.takerTokenFilledAmount < takerTokenFillAmount) {
 | 
			
		||||
            LibNativeOrdersRichErrors.FillOrKillFailedError(
 | 
			
		||||
                getRfqOrderHash(order),
 | 
			
		||||
                results.takerTokenFilledAmount,
 | 
			
		||||
                takerTokenFillAmount
 | 
			
		||||
            ).rrevert();
 | 
			
		||||
        }
 | 
			
		||||
        makerTokenFilledAmount = results.makerTokenFilledAmount;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Fill a limit order. Internal variant. ETH protocol fees can be
 | 
			
		||||
    ///      attached to this call.
 | 
			
		||||
    /// @param order The limit order.
 | 
			
		||||
    /// @param signature The order signature.
 | 
			
		||||
    /// @param takerTokenFillAmount Maximum taker token to fill this order with.
 | 
			
		||||
    /// @param taker The order taker.
 | 
			
		||||
    /// @param sender The order sender.
 | 
			
		||||
    /// @return takerTokenFilledAmount How much maker token was filled.
 | 
			
		||||
    /// @return makerTokenFilledAmount How much maker token was filled.
 | 
			
		||||
    function _fillLimitOrder(
 | 
			
		||||
        LibNativeOrder.LimitOrder memory order,
 | 
			
		||||
        LibSignature.Signature memory signature,
 | 
			
		||||
        uint128 takerTokenFillAmount,
 | 
			
		||||
        address taker,
 | 
			
		||||
        address sender
 | 
			
		||||
    )
 | 
			
		||||
        public
 | 
			
		||||
        virtual
 | 
			
		||||
        payable
 | 
			
		||||
        onlySelf
 | 
			
		||||
        returns (uint128 takerTokenFilledAmount, uint128 makerTokenFilledAmount)
 | 
			
		||||
    {
 | 
			
		||||
        FillNativeOrderResults memory results =
 | 
			
		||||
            _fillLimitOrderPrivate(FillLimitOrderPrivateParams({
 | 
			
		||||
                order: order,
 | 
			
		||||
                signature: signature,
 | 
			
		||||
                takerTokenFillAmount: takerTokenFillAmount,
 | 
			
		||||
                taker: taker,
 | 
			
		||||
                sender: sender
 | 
			
		||||
            }));
 | 
			
		||||
        (takerTokenFilledAmount, makerTokenFilledAmount) = (
 | 
			
		||||
            results.takerTokenFilledAmount,
 | 
			
		||||
            results.makerTokenFilledAmount
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Fill an RFQ order. Internal variant. ETH protocol fees can be
 | 
			
		||||
    ///      attached to this call. Any unspent ETH will be refunded to
 | 
			
		||||
    ///      `msg.sender` (not `sender`).
 | 
			
		||||
    /// @param order The RFQ order.
 | 
			
		||||
    /// @param signature The order signature.
 | 
			
		||||
    /// @param takerTokenFillAmount Maximum taker token to fill this order with.
 | 
			
		||||
    /// @param taker The order taker.
 | 
			
		||||
    /// @return takerTokenFilledAmount How much maker token was filled.
 | 
			
		||||
    /// @return makerTokenFilledAmount How much maker token was filled.
 | 
			
		||||
    function _fillRfqOrder(
 | 
			
		||||
        LibNativeOrder.RfqOrder memory order,
 | 
			
		||||
        LibSignature.Signature memory signature,
 | 
			
		||||
        uint128 takerTokenFillAmount,
 | 
			
		||||
        address taker
 | 
			
		||||
    )
 | 
			
		||||
        public
 | 
			
		||||
        virtual
 | 
			
		||||
        onlySelf
 | 
			
		||||
        returns (uint128 takerTokenFilledAmount, uint128 makerTokenFilledAmount)
 | 
			
		||||
    {
 | 
			
		||||
        FillNativeOrderResults memory results =
 | 
			
		||||
            _fillRfqOrderPrivate(
 | 
			
		||||
                order,
 | 
			
		||||
                signature,
 | 
			
		||||
                takerTokenFillAmount,
 | 
			
		||||
                taker
 | 
			
		||||
            );
 | 
			
		||||
        (takerTokenFilledAmount, makerTokenFilledAmount) = (
 | 
			
		||||
            results.takerTokenFilledAmount,
 | 
			
		||||
            results.makerTokenFilledAmount
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Mark what tx.origin addresses are allowed to fill an order that
 | 
			
		||||
    ///      specifies the message sender as its txOrigin.
 | 
			
		||||
    /// @param origins An array of origin addresses to update.
 | 
			
		||||
    /// @param allowed True to register, false to unregister.
 | 
			
		||||
    function registerAllowedRfqOrigins(
 | 
			
		||||
        address[] memory origins,
 | 
			
		||||
        bool allowed
 | 
			
		||||
    )
 | 
			
		||||
        external
 | 
			
		||||
    {
 | 
			
		||||
        require(msg.sender == tx.origin,
 | 
			
		||||
            "NativeOrdersFeature/NO_CONTRACT_ORIGINS");
 | 
			
		||||
 | 
			
		||||
        LibNativeOrdersStorage.Storage storage stor =
 | 
			
		||||
            LibNativeOrdersStorage.getStorage();
 | 
			
		||||
 | 
			
		||||
        for (uint256 i = 0; i < origins.length; i++) {
 | 
			
		||||
            stor.originRegistry[msg.sender][origins[i]] = allowed;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        emit RfqOrderOriginsAllowed(msg.sender, origins, allowed);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Fill a limit order. Private variant. Does not refund protocol fees.
 | 
			
		||||
    /// @param params Function params.
 | 
			
		||||
    /// @return results Results of the fill.
 | 
			
		||||
    function _fillLimitOrderPrivate(FillLimitOrderPrivateParams memory params)
 | 
			
		||||
        private
 | 
			
		||||
        returns (FillNativeOrderResults memory results)
 | 
			
		||||
    {
 | 
			
		||||
        LibNativeOrder.OrderInfo memory orderInfo = getLimitOrderInfo(params.order);
 | 
			
		||||
 | 
			
		||||
        // Must be fillable.
 | 
			
		||||
        if (orderInfo.status != LibNativeOrder.OrderStatus.FILLABLE) {
 | 
			
		||||
            LibNativeOrdersRichErrors.OrderNotFillableError(
 | 
			
		||||
                orderInfo.orderHash,
 | 
			
		||||
                uint8(orderInfo.status)
 | 
			
		||||
            ).rrevert();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Must be fillable by the taker.
 | 
			
		||||
        if (params.order.taker != address(0) && params.order.taker != params.taker) {
 | 
			
		||||
            LibNativeOrdersRichErrors.OrderNotFillableByTakerError(
 | 
			
		||||
                orderInfo.orderHash,
 | 
			
		||||
                params.taker,
 | 
			
		||||
                params.order.taker
 | 
			
		||||
            ).rrevert();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Must be fillable by the sender.
 | 
			
		||||
        if (params.order.sender != address(0) && params.order.sender != params.sender) {
 | 
			
		||||
            LibNativeOrdersRichErrors.OrderNotFillableBySenderError(
 | 
			
		||||
                orderInfo.orderHash,
 | 
			
		||||
                params.sender,
 | 
			
		||||
                params.order.sender
 | 
			
		||||
            ).rrevert();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Signature must be valid for the order.
 | 
			
		||||
        {
 | 
			
		||||
            address signer = LibSignature.getSignerOfHash(
 | 
			
		||||
                orderInfo.orderHash,
 | 
			
		||||
                params.signature
 | 
			
		||||
            );
 | 
			
		||||
            if (signer != params.order.maker) {
 | 
			
		||||
                LibNativeOrdersRichErrors.OrderNotSignedByMakerError(
 | 
			
		||||
                    orderInfo.orderHash,
 | 
			
		||||
                    signer,
 | 
			
		||||
                    params.order.maker
 | 
			
		||||
                ).rrevert();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Pay the protocol fee.
 | 
			
		||||
        results.ethProtocolFeePaid = _collectProtocolFee(params.order.pool);
 | 
			
		||||
 | 
			
		||||
        // Settle between the maker and taker.
 | 
			
		||||
        (results.takerTokenFilledAmount, results.makerTokenFilledAmount) = _settleOrder(
 | 
			
		||||
            SettleOrderInfo({
 | 
			
		||||
                orderHash: orderInfo.orderHash,
 | 
			
		||||
                maker: params.order.maker,
 | 
			
		||||
                taker: params.taker,
 | 
			
		||||
                makerToken: IERC20TokenV06(params.order.makerToken),
 | 
			
		||||
                takerToken: IERC20TokenV06(params.order.takerToken),
 | 
			
		||||
                makerAmount: params.order.makerAmount,
 | 
			
		||||
                takerAmount: params.order.takerAmount,
 | 
			
		||||
                takerTokenFillAmount: params.takerTokenFillAmount,
 | 
			
		||||
                takerTokenFilledAmount: orderInfo.takerTokenFilledAmount
 | 
			
		||||
            })
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        // Pay the fee recipient.
 | 
			
		||||
        if (params.order.takerTokenFeeAmount > 0) {
 | 
			
		||||
            results.takerTokenFeeFilledAmount = uint128(LibMathV06.getPartialAmountFloor(
 | 
			
		||||
                results.takerTokenFilledAmount,
 | 
			
		||||
                params.order.takerAmount,
 | 
			
		||||
                params.order.takerTokenFeeAmount
 | 
			
		||||
            ));
 | 
			
		||||
            _transferERC20Tokens(
 | 
			
		||||
                params.order.takerToken,
 | 
			
		||||
                params.taker,
 | 
			
		||||
                params.order.feeRecipient,
 | 
			
		||||
                uint256(results.takerTokenFeeFilledAmount)
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        emit LimitOrderFilled(
 | 
			
		||||
            orderInfo.orderHash,
 | 
			
		||||
            params.order.maker,
 | 
			
		||||
            params.taker,
 | 
			
		||||
            params.order.feeRecipient,
 | 
			
		||||
            address(params.order.makerToken),
 | 
			
		||||
            address(params.order.takerToken),
 | 
			
		||||
            results.takerTokenFilledAmount,
 | 
			
		||||
            results.makerTokenFilledAmount,
 | 
			
		||||
            results.takerTokenFeeFilledAmount,
 | 
			
		||||
            results.ethProtocolFeePaid,
 | 
			
		||||
            params.order.pool
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Fill an RFQ order. Private variant. Does not refund protocol fees.
 | 
			
		||||
    /// @param order The RFQ order.
 | 
			
		||||
    /// @param signature The order signature.
 | 
			
		||||
    /// @param takerTokenFillAmount Maximum taker token to fill this order with.
 | 
			
		||||
    /// @param taker The order taker.
 | 
			
		||||
    /// @return results Results of the fill.
 | 
			
		||||
    function _fillRfqOrderPrivate(
 | 
			
		||||
        LibNativeOrder.RfqOrder memory order,
 | 
			
		||||
        LibSignature.Signature memory signature,
 | 
			
		||||
        uint128 takerTokenFillAmount,
 | 
			
		||||
        address taker
 | 
			
		||||
    )
 | 
			
		||||
        private
 | 
			
		||||
        returns (FillNativeOrderResults memory results)
 | 
			
		||||
    {
 | 
			
		||||
        LibNativeOrder.OrderInfo memory orderInfo = getRfqOrderInfo(order);
 | 
			
		||||
 | 
			
		||||
        // Must be fillable.
 | 
			
		||||
        if (orderInfo.status != LibNativeOrder.OrderStatus.FILLABLE) {
 | 
			
		||||
            LibNativeOrdersRichErrors.OrderNotFillableError(
 | 
			
		||||
                orderInfo.orderHash,
 | 
			
		||||
                uint8(orderInfo.status)
 | 
			
		||||
            ).rrevert();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        {
 | 
			
		||||
            LibNativeOrdersStorage.Storage storage stor =
 | 
			
		||||
                LibNativeOrdersStorage.getStorage();
 | 
			
		||||
 | 
			
		||||
            // Must be fillable by the tx.origin.
 | 
			
		||||
            if (order.txOrigin != tx.origin && !stor.originRegistry[order.txOrigin][tx.origin]) {
 | 
			
		||||
                LibNativeOrdersRichErrors.OrderNotFillableByOriginError(
 | 
			
		||||
                    orderInfo.orderHash,
 | 
			
		||||
                    tx.origin,
 | 
			
		||||
                    order.txOrigin
 | 
			
		||||
                ).rrevert();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Must be fillable by the taker.
 | 
			
		||||
        if (order.taker != address(0) && order.taker != taker) {
 | 
			
		||||
            LibNativeOrdersRichErrors.OrderNotFillableByTakerError(
 | 
			
		||||
                orderInfo.orderHash,
 | 
			
		||||
                taker,
 | 
			
		||||
                order.taker
 | 
			
		||||
            ).rrevert();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Signature must be valid for the order.
 | 
			
		||||
        {
 | 
			
		||||
            address signer = LibSignature.getSignerOfHash(orderInfo.orderHash, signature);
 | 
			
		||||
            if (signer != order.maker) {
 | 
			
		||||
                LibNativeOrdersRichErrors.OrderNotSignedByMakerError(
 | 
			
		||||
                    orderInfo.orderHash,
 | 
			
		||||
                    signer,
 | 
			
		||||
                    order.maker
 | 
			
		||||
                ).rrevert();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Settle between the maker and taker.
 | 
			
		||||
        (results.takerTokenFilledAmount, results.makerTokenFilledAmount) = _settleOrder(
 | 
			
		||||
            SettleOrderInfo({
 | 
			
		||||
                orderHash: orderInfo.orderHash,
 | 
			
		||||
                maker: order.maker,
 | 
			
		||||
                taker: taker,
 | 
			
		||||
                makerToken: IERC20TokenV06(order.makerToken),
 | 
			
		||||
                takerToken: IERC20TokenV06(order.takerToken),
 | 
			
		||||
                makerAmount: order.makerAmount,
 | 
			
		||||
                takerAmount: order.takerAmount,
 | 
			
		||||
                takerTokenFillAmount: takerTokenFillAmount,
 | 
			
		||||
                takerTokenFilledAmount: orderInfo.takerTokenFilledAmount
 | 
			
		||||
            })
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        emit RfqOrderFilled(
 | 
			
		||||
            orderInfo.orderHash,
 | 
			
		||||
            order.maker,
 | 
			
		||||
            taker,
 | 
			
		||||
            address(order.makerToken),
 | 
			
		||||
            address(order.takerToken),
 | 
			
		||||
            results.takerTokenFilledAmount,
 | 
			
		||||
            results.makerTokenFilledAmount,
 | 
			
		||||
            order.pool
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Settle the trade between an order's maker and taker.
 | 
			
		||||
    /// @param settleInfo Information needed to execute the settlement.
 | 
			
		||||
    /// @return takerTokenFilledAmount How much taker token was filled.
 | 
			
		||||
    /// @return makerTokenFilledAmount How much maker token was filled.
 | 
			
		||||
    function _settleOrder(SettleOrderInfo memory settleInfo)
 | 
			
		||||
        private
 | 
			
		||||
        returns (uint128 takerTokenFilledAmount, uint128 makerTokenFilledAmount)
 | 
			
		||||
    {
 | 
			
		||||
        // Clamp the taker token fill amount to the fillable amount.
 | 
			
		||||
        takerTokenFilledAmount = LibSafeMathV06.min128(
 | 
			
		||||
            settleInfo.takerTokenFillAmount,
 | 
			
		||||
            settleInfo.takerAmount.safeSub128(settleInfo.takerTokenFilledAmount)
 | 
			
		||||
        );
 | 
			
		||||
        // Compute the maker token amount.
 | 
			
		||||
        // This should never overflow because the values are all clamped to
 | 
			
		||||
        // (2^128-1).
 | 
			
		||||
        makerTokenFilledAmount = uint128(LibMathV06.getPartialAmountFloor(
 | 
			
		||||
            uint256(takerTokenFilledAmount),
 | 
			
		||||
            uint256(settleInfo.takerAmount),
 | 
			
		||||
            uint256(settleInfo.makerAmount)
 | 
			
		||||
        ));
 | 
			
		||||
 | 
			
		||||
        if (takerTokenFilledAmount == 0 || makerTokenFilledAmount == 0) {
 | 
			
		||||
            // Nothing to do.
 | 
			
		||||
            return (0, 0);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Update filled state for the order.
 | 
			
		||||
        LibNativeOrdersStorage
 | 
			
		||||
            .getStorage()
 | 
			
		||||
            .orderHashToTakerTokenFilledAmount[settleInfo.orderHash] =
 | 
			
		||||
            // OK to overwrite the whole word because we shouldn't get to this
 | 
			
		||||
            // function if the order is cancelled.
 | 
			
		||||
                settleInfo.takerTokenFilledAmount.safeAdd128(takerTokenFilledAmount);
 | 
			
		||||
 | 
			
		||||
        // Transfer taker -> maker.
 | 
			
		||||
        _transferERC20Tokens(
 | 
			
		||||
            settleInfo.takerToken,
 | 
			
		||||
            settleInfo.taker,
 | 
			
		||||
            settleInfo.maker,
 | 
			
		||||
            takerTokenFilledAmount
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        // Transfer maker -> taker.
 | 
			
		||||
        _transferERC20Tokens(
 | 
			
		||||
            settleInfo.makerToken,
 | 
			
		||||
            settleInfo.maker,
 | 
			
		||||
            settleInfo.taker,
 | 
			
		||||
            makerTokenFilledAmount
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -23,8 +23,8 @@ pragma experimental ABIEncoderV2;
 | 
			
		||||
import "@0x/contracts-utils/contracts/src/v06/errors/LibRichErrorsV06.sol";
 | 
			
		||||
import "../errors/LibCommonRichErrors.sol";
 | 
			
		||||
import "../errors/LibOwnableRichErrors.sol";
 | 
			
		||||
import "../features/IOwnableFeature.sol";
 | 
			
		||||
import "../features/ISimpleFunctionRegistryFeature.sol";
 | 
			
		||||
import "../features/interfaces/IOwnableFeature.sol";
 | 
			
		||||
import "../features/interfaces/ISimpleFunctionRegistryFeature.sol";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/// @dev Common feature utilities.
 | 
			
		||||
 
 | 
			
		||||
@@ -22,7 +22,7 @@ pragma experimental ABIEncoderV2;
 | 
			
		||||
 | 
			
		||||
import "@0x/contracts-erc20/contracts/src/v06/IEtherTokenV06.sol";
 | 
			
		||||
import "@0x/contracts-utils/contracts/src/v06/LibSafeMathV06.sol";
 | 
			
		||||
import "../features/ITokenSpenderFeature.sol";
 | 
			
		||||
import "../features/interfaces/ITokenSpenderFeature.sol";
 | 
			
		||||
import "../errors/LibSpenderRichErrors.sol";
 | 
			
		||||
import "../external/FeeCollector.sol";
 | 
			
		||||
import "../vendor/v3/IStaking.sol";
 | 
			
		||||
 
 | 
			
		||||
@@ -75,7 +75,8 @@ contract CurveLiquidityProvider is
 | 
			
		||||
            inputToken,
 | 
			
		||||
            outputToken,
 | 
			
		||||
            minBuyAmount,
 | 
			
		||||
            abi.decode(auxiliaryData, (CurveData))
 | 
			
		||||
            abi.decode(auxiliaryData, (CurveData)),
 | 
			
		||||
            recipient
 | 
			
		||||
        );
 | 
			
		||||
        // Every pool contract currently checks this but why not.
 | 
			
		||||
        require(boughtAmount >= minBuyAmount, "CurveLiquidityProvider/UNDERBOUGHT");
 | 
			
		||||
@@ -109,7 +110,8 @@ contract CurveLiquidityProvider is
 | 
			
		||||
            LibERC20Transformer.ETH_TOKEN,
 | 
			
		||||
            outputToken,
 | 
			
		||||
            minBuyAmount,
 | 
			
		||||
            abi.decode(auxiliaryData, (CurveData))
 | 
			
		||||
            abi.decode(auxiliaryData, (CurveData)),
 | 
			
		||||
            recipient
 | 
			
		||||
        );
 | 
			
		||||
        // Every pool contract currently checks this but why not.
 | 
			
		||||
        require(boughtAmount >= minBuyAmount, "CurveLiquidityProvider/UNDERBOUGHT");
 | 
			
		||||
@@ -141,7 +143,8 @@ contract CurveLiquidityProvider is
 | 
			
		||||
            inputToken,
 | 
			
		||||
            LibERC20Transformer.ETH_TOKEN,
 | 
			
		||||
            minBuyAmount,
 | 
			
		||||
            abi.decode(auxiliaryData, (CurveData))
 | 
			
		||||
            abi.decode(auxiliaryData, (CurveData)),
 | 
			
		||||
            recipient
 | 
			
		||||
        );
 | 
			
		||||
        // Every pool contract currently checks this but why not.
 | 
			
		||||
        require(boughtAmount >= minBuyAmount, "CurveLiquidityProvider/UNDERBOUGHT");
 | 
			
		||||
@@ -169,7 +172,8 @@ contract CurveLiquidityProvider is
 | 
			
		||||
        IERC20TokenV06 inputToken,
 | 
			
		||||
        IERC20TokenV06 outputToken,
 | 
			
		||||
        uint256 minBuyAmount,
 | 
			
		||||
        CurveData memory data
 | 
			
		||||
        CurveData memory data,
 | 
			
		||||
        address recipient // Only used to log event.
 | 
			
		||||
    )
 | 
			
		||||
        private
 | 
			
		||||
        returns (uint256 boughtAmount)
 | 
			
		||||
@@ -204,5 +208,16 @@ contract CurveLiquidityProvider is
 | 
			
		||||
            boughtAmount = LibERC20Transformer
 | 
			
		||||
                .getTokenBalanceOf(outputToken, address(this));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        emit LiquidityProviderFill(
 | 
			
		||||
            inputToken,
 | 
			
		||||
            outputToken,
 | 
			
		||||
            sellAmount,
 | 
			
		||||
            boughtAmount,
 | 
			
		||||
            bytes32("Curve"),
 | 
			
		||||
            address(data.curveAddress),
 | 
			
		||||
            msg.sender,
 | 
			
		||||
            recipient
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,227 @@
 | 
			
		||||
// SPDX-License-Identifier: Apache-2.0
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  Copyright 2021 ZeroEx Intl.
 | 
			
		||||
 | 
			
		||||
  Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
  you may not use this file except in compliance with the License.
 | 
			
		||||
  You may obtain a copy of the License at
 | 
			
		||||
 | 
			
		||||
    http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 | 
			
		||||
  Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
  distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
  See the License for the specific language governing permissions and
 | 
			
		||||
  limitations under the License.
 | 
			
		||||
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
pragma solidity ^0.6.5;
 | 
			
		||||
pragma experimental ABIEncoderV2;
 | 
			
		||||
 | 
			
		||||
import "@0x/contracts-utils/contracts/src/v06/errors/LibRichErrorsV06.sol";
 | 
			
		||||
import "@0x/contracts-erc20/contracts/src/v06/LibERC20TokenV06.sol";
 | 
			
		||||
import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol";
 | 
			
		||||
import "@0x/contracts-erc20/contracts/src/v06/IEtherTokenV06.sol";
 | 
			
		||||
import "@0x/contracts-utils/contracts/src/v06/LibSafeMathV06.sol";
 | 
			
		||||
import "../transformers/LibERC20Transformer.sol";
 | 
			
		||||
import "../vendor/ILiquidityProvider.sol";
 | 
			
		||||
import "../vendor/IMooniswapPool.sol";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
contract MooniswapLiquidityProvider is
 | 
			
		||||
    ILiquidityProvider
 | 
			
		||||
{
 | 
			
		||||
    using LibERC20TokenV06 for IERC20TokenV06;
 | 
			
		||||
    using LibSafeMathV06 for uint256;
 | 
			
		||||
    using LibRichErrorsV06 for bytes;
 | 
			
		||||
 | 
			
		||||
    IEtherTokenV06 private immutable WETH;
 | 
			
		||||
 | 
			
		||||
    constructor(IEtherTokenV06 weth) public {
 | 
			
		||||
        WETH = weth;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev This contract must be payable because takers can transfer funds
 | 
			
		||||
    ///      in prior to calling the swap function.
 | 
			
		||||
    receive() external payable {}
 | 
			
		||||
 | 
			
		||||
    /// @dev Trades `inputToken` for `outputToken`. The amount of `inputToken`
 | 
			
		||||
    ///      to sell must be transferred to the contract prior to calling this
 | 
			
		||||
    ///      function to trigger the trade.
 | 
			
		||||
    /// @param inputToken The token being sold.
 | 
			
		||||
    /// @param outputToken The token being bought.
 | 
			
		||||
    /// @param recipient The recipient of the bought tokens.
 | 
			
		||||
    /// @param minBuyAmount The minimum acceptable amount of `outputToken` to buy.
 | 
			
		||||
    /// @param auxiliaryData Arbitrary auxiliary data supplied to the contract.
 | 
			
		||||
    /// @return boughtAmount The amount of `outputToken` bought.
 | 
			
		||||
    function sellTokenForToken(
 | 
			
		||||
        IERC20TokenV06 inputToken,
 | 
			
		||||
        IERC20TokenV06 outputToken,
 | 
			
		||||
        address recipient,
 | 
			
		||||
        uint256 minBuyAmount,
 | 
			
		||||
        bytes calldata auxiliaryData
 | 
			
		||||
    )
 | 
			
		||||
        external
 | 
			
		||||
        override
 | 
			
		||||
        returns (uint256 boughtAmount)
 | 
			
		||||
    {
 | 
			
		||||
        require(
 | 
			
		||||
            !LibERC20Transformer.isTokenETH(inputToken)
 | 
			
		||||
                && !LibERC20Transformer.isTokenETH(outputToken)
 | 
			
		||||
                && inputToken != outputToken,
 | 
			
		||||
            "MooniswapLiquidityProvider/INVALID_ARGS"
 | 
			
		||||
        );
 | 
			
		||||
        boughtAmount = _executeSwap(
 | 
			
		||||
            inputToken,
 | 
			
		||||
            outputToken,
 | 
			
		||||
            minBuyAmount,
 | 
			
		||||
            abi.decode(auxiliaryData, (IMooniswapPool)),
 | 
			
		||||
            recipient
 | 
			
		||||
        );
 | 
			
		||||
        outputToken.compatTransfer(recipient, boughtAmount);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Trades ETH for token. ETH must either be attached to this function
 | 
			
		||||
    ///      call or sent to the contract prior to calling this function to
 | 
			
		||||
    ///      trigger the trade.
 | 
			
		||||
    /// @param outputToken The token being bought.
 | 
			
		||||
    /// @param recipient The recipient of the bought tokens.
 | 
			
		||||
    /// @param minBuyAmount The minimum acceptable amount of `outputToken` to buy.
 | 
			
		||||
    /// @param auxiliaryData Arbitrary auxiliary data supplied to the contract.
 | 
			
		||||
    /// @return boughtAmount The amount of `outputToken` bought.
 | 
			
		||||
    function sellEthForToken(
 | 
			
		||||
        IERC20TokenV06 outputToken,
 | 
			
		||||
        address recipient,
 | 
			
		||||
        uint256 minBuyAmount,
 | 
			
		||||
        bytes calldata auxiliaryData
 | 
			
		||||
    )
 | 
			
		||||
        external
 | 
			
		||||
        payable
 | 
			
		||||
        override
 | 
			
		||||
        returns (uint256 boughtAmount)
 | 
			
		||||
    {
 | 
			
		||||
        require(
 | 
			
		||||
            !LibERC20Transformer.isTokenETH(outputToken),
 | 
			
		||||
            "MooniswapLiquidityProvider/INVALID_ARGS"
 | 
			
		||||
        );
 | 
			
		||||
        boughtAmount = _executeSwap(
 | 
			
		||||
            LibERC20Transformer.ETH_TOKEN,
 | 
			
		||||
            outputToken,
 | 
			
		||||
            minBuyAmount,
 | 
			
		||||
            abi.decode(auxiliaryData, (IMooniswapPool)),
 | 
			
		||||
            recipient
 | 
			
		||||
        );
 | 
			
		||||
        outputToken.compatTransfer(recipient, boughtAmount);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Trades token for ETH. The token must be sent to the contract prior
 | 
			
		||||
    ///      to calling this function to trigger the trade.
 | 
			
		||||
    /// @param inputToken The token being sold.
 | 
			
		||||
    /// @param recipient The recipient of the bought tokens.
 | 
			
		||||
    /// @param minBuyAmount The minimum acceptable amount of ETH to buy.
 | 
			
		||||
    /// @param auxiliaryData Arbitrary auxiliary data supplied to the contract.
 | 
			
		||||
    /// @return boughtAmount The amount of ETH bought.
 | 
			
		||||
    function sellTokenForEth(
 | 
			
		||||
        IERC20TokenV06 inputToken,
 | 
			
		||||
        address payable recipient,
 | 
			
		||||
        uint256 minBuyAmount,
 | 
			
		||||
        bytes calldata auxiliaryData
 | 
			
		||||
    )
 | 
			
		||||
        external
 | 
			
		||||
        override
 | 
			
		||||
        returns (uint256 boughtAmount)
 | 
			
		||||
    {
 | 
			
		||||
        require(
 | 
			
		||||
            !LibERC20Transformer.isTokenETH(inputToken),
 | 
			
		||||
            "MooniswapLiquidityProvider/INVALID_ARGS"
 | 
			
		||||
        );
 | 
			
		||||
        boughtAmount = _executeSwap(
 | 
			
		||||
            inputToken,
 | 
			
		||||
            LibERC20Transformer.ETH_TOKEN,
 | 
			
		||||
            minBuyAmount,
 | 
			
		||||
            abi.decode(auxiliaryData, (IMooniswapPool)),
 | 
			
		||||
            recipient
 | 
			
		||||
        );
 | 
			
		||||
        recipient.call{value: boughtAmount}("");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Quotes the amount of `outputToken` that would be obtained by
 | 
			
		||||
    ///      selling `sellAmount` of `inputToken`.
 | 
			
		||||
    function getSellQuote(
 | 
			
		||||
        IERC20TokenV06 /* inputToken */,
 | 
			
		||||
        IERC20TokenV06 /* outputToken */,
 | 
			
		||||
        uint256 /* sellAmount */
 | 
			
		||||
    )
 | 
			
		||||
        external
 | 
			
		||||
        view
 | 
			
		||||
        override
 | 
			
		||||
        returns (uint256)
 | 
			
		||||
    {
 | 
			
		||||
        revert("MooniswapLiquidityProvider/NOT_IMPLEMENTED");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Perform the swap against the curve pool. Handles any combination of
 | 
			
		||||
    ///      tokens
 | 
			
		||||
    function _executeSwap(
 | 
			
		||||
        IERC20TokenV06 inputToken,
 | 
			
		||||
        IERC20TokenV06 outputToken,
 | 
			
		||||
        uint256 minBuyAmount,
 | 
			
		||||
        IMooniswapPool pool,
 | 
			
		||||
        address recipient // Only used to log event
 | 
			
		||||
    )
 | 
			
		||||
        private
 | 
			
		||||
        returns (uint256 boughtAmount)
 | 
			
		||||
    {
 | 
			
		||||
        uint256 sellAmount =
 | 
			
		||||
            LibERC20Transformer.getTokenBalanceOf(inputToken, address(this));
 | 
			
		||||
        uint256 ethValue = 0;
 | 
			
		||||
        if (inputToken == WETH) {
 | 
			
		||||
            // Selling WETH. Unwrap to ETH.
 | 
			
		||||
            require(!_isTokenEthLike(outputToken), 'MooniswapLiquidityProvider/ETH_TO_ETH');
 | 
			
		||||
            WETH.withdraw(sellAmount);
 | 
			
		||||
            ethValue = sellAmount;
 | 
			
		||||
        } else if (LibERC20Transformer.isTokenETH(inputToken)) {
 | 
			
		||||
            // Selling ETH directly.
 | 
			
		||||
            ethValue = sellAmount;
 | 
			
		||||
            require(!_isTokenEthLike(outputToken), 'MooniswapLiquidityProvider/ETH_TO_ETH');
 | 
			
		||||
        } else {
 | 
			
		||||
            // Selling a regular ERC20.
 | 
			
		||||
            require(inputToken != outputToken, 'MooniswapLiquidityProvider/SAME_TOKEN');
 | 
			
		||||
            inputToken.approveIfBelow(address(pool), sellAmount);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        boughtAmount = pool.swap{value: ethValue}(
 | 
			
		||||
            _isTokenEthLike(inputToken) ? IERC20TokenV06(0) : inputToken,
 | 
			
		||||
            _isTokenEthLike(outputToken) ? IERC20TokenV06(0) : outputToken,
 | 
			
		||||
            sellAmount,
 | 
			
		||||
            minBuyAmount,
 | 
			
		||||
            address(0)
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        if (outputToken == WETH) {
 | 
			
		||||
            WETH.deposit{value: boughtAmount}();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        emit LiquidityProviderFill(
 | 
			
		||||
            inputToken,
 | 
			
		||||
            outputToken,
 | 
			
		||||
            sellAmount,
 | 
			
		||||
            boughtAmount,
 | 
			
		||||
            bytes32("Mooniswap"),
 | 
			
		||||
            address(pool),
 | 
			
		||||
            msg.sender,
 | 
			
		||||
            recipient
 | 
			
		||||
        );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Check if a token is ETH or WETH.
 | 
			
		||||
    function _isTokenEthLike(IERC20TokenV06 token)
 | 
			
		||||
        private
 | 
			
		||||
        view
 | 
			
		||||
        returns (bool isEthOrWeth)
 | 
			
		||||
    {
 | 
			
		||||
        return LibERC20Transformer.isTokenETH(token) || token == WETH;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -21,7 +21,7 @@ pragma solidity ^0.6.5;
 | 
			
		||||
pragma experimental ABIEncoderV2;
 | 
			
		||||
 | 
			
		||||
import "../ZeroEx.sol";
 | 
			
		||||
import "../features/IOwnableFeature.sol";
 | 
			
		||||
import "../features/interfaces/IOwnableFeature.sol";
 | 
			
		||||
import "../features/TokenSpenderFeature.sol";
 | 
			
		||||
import "../features/TransformERC20Feature.sol";
 | 
			
		||||
import "../features/MetaTransactionsFeature.sol";
 | 
			
		||||
 
 | 
			
		||||
@@ -21,7 +21,7 @@ pragma solidity ^0.6.5;
 | 
			
		||||
pragma experimental ABIEncoderV2;
 | 
			
		||||
 | 
			
		||||
import "../ZeroEx.sol";
 | 
			
		||||
import "../features/IBootstrapFeature.sol";
 | 
			
		||||
import "../features/interfaces/IBootstrapFeature.sol";
 | 
			
		||||
import "../features/SimpleFunctionRegistryFeature.sol";
 | 
			
		||||
import "../features/OwnableFeature.sol";
 | 
			
		||||
import "./LibBootstrap.sol";
 | 
			
		||||
 
 | 
			
		||||
@@ -26,7 +26,7 @@ import "@0x/contracts-erc20/contracts/src/v06/LibERC20TokenV06.sol";
 | 
			
		||||
import "@0x/contracts-utils/contracts/src/v06/LibSafeMathV06.sol";
 | 
			
		||||
import "@0x/contracts-utils/contracts/src/v06/LibMathV06.sol";
 | 
			
		||||
import "../errors/LibTransformERC20RichErrors.sol";
 | 
			
		||||
import "../features/INativeOrdersFeature.sol";
 | 
			
		||||
import "../features/interfaces/INativeOrdersFeature.sol";
 | 
			
		||||
import "../features/libs/LibNativeOrder.sol";
 | 
			
		||||
import "./bridges/IBridgeAdapter.sol";
 | 
			
		||||
import "./Transformer.sol";
 | 
			
		||||
@@ -132,8 +132,6 @@ contract FillQuoteTransformer is
 | 
			
		||||
    /// @param orderHash The hash of the order that was skipped.
 | 
			
		||||
    event ProtocolFeeUnfunded(bytes32 orderHash);
 | 
			
		||||
 | 
			
		||||
    /// @dev Maximum uint256 value.
 | 
			
		||||
    uint256 private constant MAX_UINT256 = uint256(-1);
 | 
			
		||||
    /// @dev The highest bit of a uint256 value.
 | 
			
		||||
    uint256 private constant HIGH_BIT = 2 ** 255;
 | 
			
		||||
    /// @dev Mask of the lower 255 bits of a uint256 value.
 | 
			
		||||
 
 | 
			
		||||
@@ -24,6 +24,28 @@ import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol";
 | 
			
		||||
 | 
			
		||||
interface ILiquidityProvider {
 | 
			
		||||
 | 
			
		||||
    /// @dev An optional event an LP can emit for each fill against a source.
 | 
			
		||||
    /// @param inputToken The input token.
 | 
			
		||||
    /// @param outputToken The output token.
 | 
			
		||||
    /// @param inputTokenAmount How much input token was sold.
 | 
			
		||||
    /// @param outputTokenAmount How much output token was bought.
 | 
			
		||||
    /// @param sourceId A bytes32 encoded ascii source ID. E.g., `bytes32('Curve')`/
 | 
			
		||||
    /// @param sourceAddress An optional address associated with the source (e.g, a curve pool).
 | 
			
		||||
    /// @param sourceId A bytes32 encoded ascii source ID. E.g., `bytes32('Curve')`/
 | 
			
		||||
    /// @param sourceAddress An optional address associated with the source (e.g, a curve pool).
 | 
			
		||||
    /// @param sender The caller of the LP.
 | 
			
		||||
    /// @param recipient The recipient of the output tokens.
 | 
			
		||||
    event LiquidityProviderFill(
 | 
			
		||||
        IERC20TokenV06 inputToken,
 | 
			
		||||
        IERC20TokenV06 outputToken,
 | 
			
		||||
        uint256 inputTokenAmount,
 | 
			
		||||
        uint256 outputTokenAmount,
 | 
			
		||||
        bytes32 sourceId,
 | 
			
		||||
        address sourceAddress,
 | 
			
		||||
        address sender,
 | 
			
		||||
        address recipient
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    /// @dev Trades `inputToken` for `outputToken`. The amount of `inputToken`
 | 
			
		||||
    ///      to sell must be transferred to the contract prior to calling this
 | 
			
		||||
    ///      function to trigger the trade.
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										41
									
								
								contracts/zero-ex/contracts/src/vendor/IMooniswapPool.sol
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								contracts/zero-ex/contracts/src/vendor/IMooniswapPool.sol
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,41 @@
 | 
			
		||||
// SPDX-License-Identifier: Apache-2.0
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  Copyright 2021 ZeroEx Intl.
 | 
			
		||||
 | 
			
		||||
  Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
  you may not use this file except in compliance with the License.
 | 
			
		||||
  You may obtain a copy of the License at
 | 
			
		||||
 | 
			
		||||
    http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 | 
			
		||||
  Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
  distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
  See the License for the specific language governing permissions and
 | 
			
		||||
  limitations under the License.
 | 
			
		||||
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
pragma solidity ^0.6.5;
 | 
			
		||||
pragma experimental ABIEncoderV2;
 | 
			
		||||
 | 
			
		||||
import "@0x/contracts-erc20/contracts/src/v06/LibERC20TokenV06.sol";
 | 
			
		||||
import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol";
 | 
			
		||||
import "@0x/contracts-erc20/contracts/src/v06/IEtherTokenV06.sol";
 | 
			
		||||
 | 
			
		||||
/// @dev Moooniswap pool interface.
 | 
			
		||||
interface IMooniswapPool {
 | 
			
		||||
 | 
			
		||||
    function swap(
 | 
			
		||||
        IERC20TokenV06 sellToken,
 | 
			
		||||
        IERC20TokenV06 buyToken,
 | 
			
		||||
        uint256 sellAmount,
 | 
			
		||||
        uint256 minBoughtAmount,
 | 
			
		||||
        address referrer
 | 
			
		||||
    )
 | 
			
		||||
        external
 | 
			
		||||
        payable
 | 
			
		||||
        returns (uint256 boughtAmount);
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										48
									
								
								contracts/zero-ex/contracts/src/vendor/IUniswapV2Pair.sol
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										48
									
								
								contracts/zero-ex/contracts/src/vendor/IUniswapV2Pair.sol
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@@ -0,0 +1,48 @@
 | 
			
		||||
// SPDX-License-Identifier: Apache-2.0
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  Copyright 2021 ZeroEx Intl.
 | 
			
		||||
 | 
			
		||||
  Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
  you may not use this file except in compliance with the License.
 | 
			
		||||
  You may obtain a copy of the License at
 | 
			
		||||
 | 
			
		||||
    http://www.apache.org/licenses/LICENSE-2.0
 | 
			
		||||
 | 
			
		||||
  Unless required by applicable law or agreed to in writing, software
 | 
			
		||||
  distributed under the License is distributed on an "AS IS" BASIS,
 | 
			
		||||
  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
			
		||||
  See the License for the specific language governing permissions and
 | 
			
		||||
  limitations under the License.
 | 
			
		||||
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
pragma solidity ^0.6.12;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
interface IUniswapV2Pair {
 | 
			
		||||
    event Swap(
 | 
			
		||||
        address indexed sender,
 | 
			
		||||
        uint256 amount0In,
 | 
			
		||||
        uint256 amount1In,
 | 
			
		||||
        uint256 amount0Out,
 | 
			
		||||
        uint256 amount1Out,
 | 
			
		||||
        address indexed to
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    function swap(
 | 
			
		||||
        uint amount0Out,
 | 
			
		||||
        uint amount1Out,
 | 
			
		||||
        address to,
 | 
			
		||||
        bytes calldata data
 | 
			
		||||
    ) external;
 | 
			
		||||
 | 
			
		||||
    function getReserves()
 | 
			
		||||
        external
 | 
			
		||||
        view
 | 
			
		||||
        returns (
 | 
			
		||||
            uint112 reserve0,
 | 
			
		||||
            uint112 reserve1,
 | 
			
		||||
            uint32 blockTimestampLast
 | 
			
		||||
        );
 | 
			
		||||
}
 | 
			
		||||
@@ -21,7 +21,7 @@ pragma solidity ^0.6.5;
 | 
			
		||||
pragma experimental ABIEncoderV2;
 | 
			
		||||
 | 
			
		||||
import "../src/ZeroEx.sol";
 | 
			
		||||
import "../src/features/IBootstrapFeature.sol";
 | 
			
		||||
import "../src/features/interfaces/IBootstrapFeature.sol";
 | 
			
		||||
import "../src/migrations/InitialMigration.sol";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -20,8 +20,8 @@
 | 
			
		||||
pragma solidity ^0.6.5;
 | 
			
		||||
pragma experimental ABIEncoderV2;
 | 
			
		||||
 | 
			
		||||
import "../src/features/interfaces/IMetaTransactionsFeature.sol";
 | 
			
		||||
import "../src/features/NativeOrdersFeature.sol";
 | 
			
		||||
import "../src/features/IMetaTransactionsFeature.sol";
 | 
			
		||||
import "./TestFeeCollectorController.sol";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -20,8 +20,8 @@
 | 
			
		||||
pragma solidity ^0.6.5;
 | 
			
		||||
pragma experimental ABIEncoderV2;
 | 
			
		||||
 | 
			
		||||
import "../src/features/interfaces/IMetaTransactionsFeature.sol";
 | 
			
		||||
import "../src/features/TransformERC20Feature.sol";
 | 
			
		||||
import "../src/features/IMetaTransactionsFeature.sol";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
contract TestMetaTransactionsTransformERC20Feature is
 | 
			
		||||
 
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user