Compare commits
	
		
			32 Commits
		
	
	
		
			@0x/contra
			...
			pdowell/de
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 
						 | 
					ac563f5164 | ||
| 
						 | 
					ca7393641f | ||
| 
						 | 
					6e926af41c | ||
| 
						 | 
					172822044b | ||
| 
						 | 
					a0485ca3e0 | ||
| 
						 | 
					f32e834e11 | ||
| 
						 | 
					b5c18c2a9e | ||
| 
						 | 
					217348f31b | ||
| 
						 | 
					65a2024285 | ||
| 
						 | 
					b942551e33 | ||
| 
						 | 
					4c837110f2 | ||
| 
						 | 
					88c96659a1 | ||
| 
						 | 
					152accf9c1 | ||
| 
						 | 
					0f5d832daf | ||
| 
						 | 
					13dd95688d | ||
| 
						 | 
					15f79feb81 | ||
| 
						 | 
					3b55a88fc5 | ||
| 
						 | 
					cdb94d1780 | ||
| 
						 | 
					865c1f05db | ||
| 
						 | 
					2bbf3956f3 | ||
| 
						 | 
					5cf4cbe4b5 | ||
| 
						 | 
					f402c96053 | ||
| 
						 | 
					38665ffc86 | ||
| 
						 | 
					459fb3ee28 | ||
| 
						 | 
					dc8ff32d51 | ||
| 
						 | 
					9f30823d70 | ||
| 
						 | 
					f2f835591e | ||
| 
						 | 
					8c35931041 | ||
| 
						 | 
					a8539aa66e | ||
| 
						 | 
					4d7df00d5a | ||
| 
						 | 
					80193215e3 | ||
| 
						 | 
					c4b1f043c6 | 
							
								
								
									
										231
									
								
								.github/workflows/ci.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										231
									
								
								.github/workflows/ci.yml
									
									
									
									
										vendored
									
									
								
							@@ -1,108 +1,137 @@
 | 
			
		||||
name: Continuous Integration
 | 
			
		||||
on:
 | 
			
		||||
  push:
 | 
			
		||||
    branches:
 | 
			
		||||
      - main
 | 
			
		||||
      - development
 | 
			
		||||
  pull_request:
 | 
			
		||||
    push:
 | 
			
		||||
        branches:
 | 
			
		||||
            - main
 | 
			
		||||
            - development
 | 
			
		||||
    pull_request:
 | 
			
		||||
 | 
			
		||||
jobs:
 | 
			
		||||
  build:
 | 
			
		||||
    name: Build and test
 | 
			
		||||
    runs-on: ubuntu-latest
 | 
			
		||||
    steps:
 | 
			
		||||
      - uses: actions/checkout@v3
 | 
			
		||||
        with:
 | 
			
		||||
          submodules: recursive
 | 
			
		||||
 | 
			
		||||
      - name: Setup Node
 | 
			
		||||
        uses: actions/setup-node@v3
 | 
			
		||||
        with:
 | 
			
		||||
          node-version: "16"
 | 
			
		||||
 | 
			
		||||
      - name: Install dependencies
 | 
			
		||||
        run: yarn install --frozen-lockfile
 | 
			
		||||
 | 
			
		||||
      - name: Build solution
 | 
			
		||||
        run: yarn build
 | 
			
		||||
 | 
			
		||||
      - name: Lint typescript
 | 
			
		||||
        run: yarn lint:ts
 | 
			
		||||
 | 
			
		||||
      - name: Lint solidity
 | 
			
		||||
        run: yarn lint:contracts
 | 
			
		||||
 | 
			
		||||
      - name: Run prettier
 | 
			
		||||
        run: yarn prettier:ci
 | 
			
		||||
 | 
			
		||||
      - name: Check dependent packages have consistent versions
 | 
			
		||||
        run: yarn deps_versions:ci
 | 
			
		||||
 | 
			
		||||
      - name: Check diff in docs
 | 
			
		||||
        run: yarn diff_md_docs:ci
 | 
			
		||||
 | 
			
		||||
      - name: Check for broken links in markdown files
 | 
			
		||||
        run: yarn test:links
 | 
			
		||||
 | 
			
		||||
      - name: Test doc generation
 | 
			
		||||
        run: yarn test:generate_docs:ci
 | 
			
		||||
 | 
			
		||||
      - name: Test @0x/contracts-*
 | 
			
		||||
        run: |
 | 
			
		||||
                yarn wsrun \
 | 
			
		||||
                  -p @0x/contracts-multisig \
 | 
			
		||||
                  -p @0x/contracts-utils \
 | 
			
		||||
                  -p @0x/contracts-exchange-libs \
 | 
			
		||||
                  -p @0x/contracts-erc20 \
 | 
			
		||||
                  -p @0x/contracts-erc721 \
 | 
			
		||||
                  -p @0x/contracts-erc1155 \
 | 
			
		||||
                  -p @0x/contracts-asset-proxy \
 | 
			
		||||
                  -p @0x/contracts-broker \
 | 
			
		||||
                  -p @0x/contracts-zero-ex \
 | 
			
		||||
                  -m --serial -c test:ci
 | 
			
		||||
 | 
			
		||||
      - name: Test local @0x/contracts-*
 | 
			
		||||
        run: |
 | 
			
		||||
                yarn wsrun \
 | 
			
		||||
                  -p @0x/contracts-test-utils \
 | 
			
		||||
                  -p @0x/contract-addresses \
 | 
			
		||||
                  -p @0x/contract-artifacts \
 | 
			
		||||
                  -p @0x/contract-wrappers-test \
 | 
			
		||||
                  -p @0x/order-utils \
 | 
			
		||||
                  -m --serial -c test:ci
 | 
			
		||||
 | 
			
		||||
      - name: Add foundry
 | 
			
		||||
        uses: foundry-rs/foundry-toolchain@v1
 | 
			
		||||
        with:
 | 
			
		||||
          version: nightly
 | 
			
		||||
 | 
			
		||||
      - name: Run Forge build
 | 
			
		||||
        working-directory: contracts/zero-ex
 | 
			
		||||
        run: |
 | 
			
		||||
          forge --version
 | 
			
		||||
          forge build --sizes
 | 
			
		||||
 | 
			
		||||
      - name: Run Forge tests
 | 
			
		||||
        working-directory: contracts/zero-ex
 | 
			
		||||
    build:
 | 
			
		||||
        name: Build and test
 | 
			
		||||
        runs-on: ubuntu-latest
 | 
			
		||||
        env:
 | 
			
		||||
          ARBITRUM_RPC_URL: ${{ secrets.ARBITRUM_RPC_URL }}
 | 
			
		||||
          AVALANCHE_RPC_URL: ${{ secrets.AVALANCHE_RPC_URL }}
 | 
			
		||||
          BSC_RPC_URL: ${{ secrets.BSC_RPC_URL }}
 | 
			
		||||
          FANTOM_RPC_URL: ${{ secrets.FANTOM_RPC_URL }}
 | 
			
		||||
          MAINNET_RPC_URL: ${{ secrets.MAINNET_RPC_URL }}
 | 
			
		||||
          OPTIMISM_RPC_URL: ${{ secrets.OPTIMISM_RPC_URL }}
 | 
			
		||||
          POLYGON_RPC_URL: ${{ secrets.POLYGON_RPC_URL }}
 | 
			
		||||
        run: |
 | 
			
		||||
          forge test -vvv --gas-report
 | 
			
		||||
            ARBITRUM_RPC_URL: ${{ secrets.ARBITRUM_RPC_URL }}
 | 
			
		||||
            AVALANCHE_RPC_URL: ${{ secrets.AVALANCHE_RPC_URL }}
 | 
			
		||||
            BSC_RPC_URL: ${{ secrets.BSC_RPC_URL }}
 | 
			
		||||
            FANTOM_RPC_URL: ${{ secrets.FANTOM_RPC_URL }}
 | 
			
		||||
            MAINNET_RPC_URL: ${{ secrets.MAINNET_RPC_URL }}
 | 
			
		||||
            OPTIMISM_RPC_URL: ${{ secrets.OPTIMISM_RPC_URL }}
 | 
			
		||||
            POLYGON_RPC_URL: ${{ secrets.POLYGON_RPC_URL }}
 | 
			
		||||
        steps:
 | 
			
		||||
            - uses: actions/checkout@v3
 | 
			
		||||
              with:
 | 
			
		||||
                  submodules: recursive
 | 
			
		||||
 | 
			
		||||
      - name: Run Forge coverage
 | 
			
		||||
        working-directory: contracts/zero-ex
 | 
			
		||||
        run: |
 | 
			
		||||
          forge coverage --report lcov
 | 
			
		||||
            - name: Setup Node
 | 
			
		||||
              uses: actions/setup-node@v3
 | 
			
		||||
              with:
 | 
			
		||||
                  node-version: '16'
 | 
			
		||||
 | 
			
		||||
      - name: Upload the coverage report to Coveralls
 | 
			
		||||
        uses: coverallsapp/github-action@master
 | 
			
		||||
        with:
 | 
			
		||||
          github-token: ${{ secrets.GITHUB_TOKEN }}
 | 
			
		||||
          base-path: ./contracts/zero-ex/
 | 
			
		||||
          path-to-lcov: ./contracts/zero-ex/lcov.info
 | 
			
		||||
            - name: Install dependencies
 | 
			
		||||
              run: yarn install --frozen-lockfile
 | 
			
		||||
 | 
			
		||||
            - name: Build solution
 | 
			
		||||
              run: yarn build
 | 
			
		||||
 | 
			
		||||
            - name: Lint typescript
 | 
			
		||||
              run: yarn lint:ts
 | 
			
		||||
 | 
			
		||||
            - name: Lint solidity
 | 
			
		||||
              run: yarn lint:contracts
 | 
			
		||||
 | 
			
		||||
            - name: Run prettier
 | 
			
		||||
              run: yarn prettier:ci
 | 
			
		||||
 | 
			
		||||
            - name: Check dependent packages have consistent versions
 | 
			
		||||
              run: yarn deps_versions:ci
 | 
			
		||||
 | 
			
		||||
            - name: Check diff in docs
 | 
			
		||||
              run: yarn diff_md_docs:ci
 | 
			
		||||
 | 
			
		||||
            - name: Check for broken links in markdown files
 | 
			
		||||
              run: yarn test:links
 | 
			
		||||
 | 
			
		||||
            - name: Test doc generation
 | 
			
		||||
              run: yarn test:generate_docs:ci
 | 
			
		||||
 | 
			
		||||
            - name: Test @0x/contracts-*
 | 
			
		||||
              run: |
 | 
			
		||||
                  yarn wsrun \
 | 
			
		||||
                    -p @0x/contracts-multisig \
 | 
			
		||||
                    -p @0x/contracts-utils \
 | 
			
		||||
                    -p @0x/contracts-exchange-libs \
 | 
			
		||||
                    -p @0x/contracts-erc721 \
 | 
			
		||||
                    -p @0x/contracts-erc1155 \
 | 
			
		||||
                    -p @0x/contracts-asset-proxy \
 | 
			
		||||
                    -p @0x/contracts-broker \
 | 
			
		||||
                    -p @0x/contracts-zero-ex \
 | 
			
		||||
                    -m --serial -c test:ci
 | 
			
		||||
 | 
			
		||||
            - name: Test local @0x/contracts-*
 | 
			
		||||
              run: |
 | 
			
		||||
                  yarn wsrun \
 | 
			
		||||
                    -p @0x/contracts-test-utils \
 | 
			
		||||
                    -p @0x/contract-addresses \
 | 
			
		||||
                    -p @0x/contract-artifacts \
 | 
			
		||||
                    -p @0x/contract-wrappers-test \
 | 
			
		||||
                    -p @0x/order-utils \
 | 
			
		||||
                    -m --serial -c test:ci
 | 
			
		||||
 | 
			
		||||
            - name: Add foundry
 | 
			
		||||
              uses: foundry-rs/foundry-toolchain@v1
 | 
			
		||||
              with:
 | 
			
		||||
                  version: nightly
 | 
			
		||||
 | 
			
		||||
            - name: Run Forge build for erc20
 | 
			
		||||
              working-directory: contracts/erc20
 | 
			
		||||
              run: |
 | 
			
		||||
                  forge --version
 | 
			
		||||
                  forge build --sizes
 | 
			
		||||
 | 
			
		||||
            - name: Run Forge tests for erc20
 | 
			
		||||
              working-directory: contracts/erc20
 | 
			
		||||
              run: |
 | 
			
		||||
                  forge test -vvv --gas-report
 | 
			
		||||
 | 
			
		||||
            - name: Run Forge coverage for erc20
 | 
			
		||||
              working-directory: contracts/erc20
 | 
			
		||||
              run: |
 | 
			
		||||
                  forge coverage --report summary --report lcov
 | 
			
		||||
 | 
			
		||||
            - name: Upload the coverage report to Coveralls
 | 
			
		||||
              uses: coverallsapp/github-action@master
 | 
			
		||||
              with:
 | 
			
		||||
                  github-token: ${{ secrets.GITHUB_TOKEN }}
 | 
			
		||||
                  base-path: ./contracts/erc20/
 | 
			
		||||
                  path-to-lcov: ./contracts/erc20/lcov.info
 | 
			
		||||
 | 
			
		||||
            - name: Run Forge build for zero-ex
 | 
			
		||||
              working-directory: contracts/zero-ex
 | 
			
		||||
              run: |
 | 
			
		||||
                  forge --version
 | 
			
		||||
                  forge build --sizes
 | 
			
		||||
 | 
			
		||||
            - name: Run Forge tests for zero-ex
 | 
			
		||||
              working-directory: contracts/zero-ex
 | 
			
		||||
              run: |
 | 
			
		||||
                  forge test -vvv --gas-report
 | 
			
		||||
 | 
			
		||||
            - name: Run Forge coverage for zero-ex
 | 
			
		||||
              working-directory: contracts/zero-ex
 | 
			
		||||
              run: |
 | 
			
		||||
                  forge coverage --report summary --report lcov
 | 
			
		||||
 | 
			
		||||
            - name: Upload the coverage report to Coveralls
 | 
			
		||||
              uses: coverallsapp/github-action@master
 | 
			
		||||
              with:
 | 
			
		||||
                  github-token: ${{ secrets.GITHUB_TOKEN }}
 | 
			
		||||
                  base-path: ./contracts/zero-ex/
 | 
			
		||||
                  path-to-lcov: ./contracts/zero-ex/lcov.info
 | 
			
		||||
 | 
			
		||||
            - name: Check coverage threshold
 | 
			
		||||
              uses: VeryGoodOpenSource/very_good_coverage@v2
 | 
			
		||||
              with:
 | 
			
		||||
                  path: ./contracts/zero-ex/lcov.info
 | 
			
		||||
                  min_coverage: 6.98
 | 
			
		||||
                  exclude: '**/tests'
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										3
									
								
								.gitmodules
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										3
									
								
								.gitmodules
									
									
									
									
										vendored
									
									
								
							@@ -1,3 +1,6 @@
 | 
			
		||||
[submodule "contracts/zero-ex/contracts/deps/forge-std"]
 | 
			
		||||
	path = contracts/zero-ex/contracts/deps/forge-std
 | 
			
		||||
	url = https://github.com/foundry-rs/forge-std
 | 
			
		||||
[submodule "contracts/erc20/lib/forge-std"]
 | 
			
		||||
	path = contracts/erc20/lib/forge-std
 | 
			
		||||
	url = https://github.com/foundry-rs/forge-std
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
contracts/erc20/contracts/src/ZRXToken.sol
 | 
			
		||||
contracts/erc20/src/ZRXToken.sol
 | 
			
		||||
node_modules/
 | 
			
		||||
lib
 | 
			
		||||
deps
 | 
			
		||||
 
 | 
			
		||||
@@ -1,25 +0,0 @@
 | 
			
		||||
{
 | 
			
		||||
  "env": {
 | 
			
		||||
      "es2021": true,
 | 
			
		||||
      "node": true
 | 
			
		||||
  },
 | 
			
		||||
  "extends": ["eslint:recommended", "plugin:@typescript-eslint/recommended", "prettier"],
 | 
			
		||||
  "overrides": [],
 | 
			
		||||
  "parser": "@typescript-eslint/parser",
 | 
			
		||||
  "parserOptions": {
 | 
			
		||||
      "project": "./tsconfig.json",
 | 
			
		||||
      "ecmaVersion": "latest",
 | 
			
		||||
      "sourceType": "module"
 | 
			
		||||
  },
 | 
			
		||||
  "plugins": ["@typescript-eslint"],
 | 
			
		||||
  "ignorePatterns": [
 | 
			
		||||
      "lib/**/*",
 | 
			
		||||
      "contracts/**/*",
 | 
			
		||||
      "generated-wrappers/**/*",
 | 
			
		||||
      "generated-artifacts/**/*",
 | 
			
		||||
      "test/generated-wrappers/**/*",
 | 
			
		||||
      "test/generated-artifacts/**/*"
 | 
			
		||||
 | 
			
		||||
  ],
 | 
			
		||||
  "rules": {}
 | 
			
		||||
}
 | 
			
		||||
@@ -5,6 +5,10 @@ Edit the package's CHANGELOG.json file only.
 | 
			
		||||
 | 
			
		||||
CHANGELOG
 | 
			
		||||
 | 
			
		||||
## v4.0.0 - _February 16, 2023_
 | 
			
		||||
 | 
			
		||||
    * Migrated package to foundry
 | 
			
		||||
 | 
			
		||||
## v3.3.57 - _February 1, 2023_
 | 
			
		||||
 | 
			
		||||
    * Dependencies updated
 | 
			
		||||
 
 | 
			
		||||
@@ -1,28 +0,0 @@
 | 
			
		||||
{
 | 
			
		||||
    "artifactsDir": "./test/generated-artifacts",
 | 
			
		||||
    "contractsDir": "./contracts",
 | 
			
		||||
    "useDockerisedSolc": false,
 | 
			
		||||
    "isOfflineMode": false,
 | 
			
		||||
    "shouldSaveStandardInput": true,
 | 
			
		||||
    "compilerSettings": {
 | 
			
		||||
        "evmVersion": "istanbul",
 | 
			
		||||
        "optimizer": {
 | 
			
		||||
            "enabled": true,
 | 
			
		||||
            "runs": 1000000,
 | 
			
		||||
            "details": { "yul": true, "deduplicate": true, "cse": true, "constantOptimizer": true }
 | 
			
		||||
        },
 | 
			
		||||
        "outputSelection": {
 | 
			
		||||
            "*": {
 | 
			
		||||
                "*": [
 | 
			
		||||
                    "abi",
 | 
			
		||||
                    "devdoc",
 | 
			
		||||
                    "evm.bytecode.object",
 | 
			
		||||
                    "evm.bytecode.sourceMap",
 | 
			
		||||
                    "evm.deployedBytecode.object",
 | 
			
		||||
                    "evm.deployedBytecode.sourceMap",
 | 
			
		||||
                    "devdoc"
 | 
			
		||||
                ]
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,93 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  Copyright 2019 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.5.9;
 | 
			
		||||
 | 
			
		||||
import "./interfaces/IERC20Token.sol";
 | 
			
		||||
 | 
			
		||||
contract ERC20Token is IERC20Token {
 | 
			
		||||
    mapping(address => uint256) internal balances;
 | 
			
		||||
    mapping(address => mapping(address => uint256)) internal allowed;
 | 
			
		||||
 | 
			
		||||
    uint256 internal _totalSupply;
 | 
			
		||||
 | 
			
		||||
    /// @dev send `value` token to `to` from `msg.sender`
 | 
			
		||||
    /// @param _to The address of the recipient
 | 
			
		||||
    /// @param _value The amount of token to be transferred
 | 
			
		||||
    /// @return True if transfer was successful
 | 
			
		||||
    function transfer(address _to, uint256 _value) external returns (bool) {
 | 
			
		||||
        require(balances[msg.sender] >= _value, "ERC20_INSUFFICIENT_BALANCE");
 | 
			
		||||
        require(balances[_to] + _value >= balances[_to], "UINT256_OVERFLOW");
 | 
			
		||||
 | 
			
		||||
        balances[msg.sender] -= _value;
 | 
			
		||||
        balances[_to] += _value;
 | 
			
		||||
 | 
			
		||||
        emit Transfer(msg.sender, _to, _value);
 | 
			
		||||
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev send `value` token to `to` from `from` on the condition it is approved by `from`
 | 
			
		||||
    /// @param _from The address of the sender
 | 
			
		||||
    /// @param _to The address of the recipient
 | 
			
		||||
    /// @param _value The amount of token to be transferred
 | 
			
		||||
    /// @return True if transfer was successful
 | 
			
		||||
    function transferFrom(address _from, address _to, uint256 _value) external returns (bool) {
 | 
			
		||||
        require(balances[_from] >= _value, "ERC20_INSUFFICIENT_BALANCE");
 | 
			
		||||
        require(allowed[_from][msg.sender] >= _value, "ERC20_INSUFFICIENT_ALLOWANCE");
 | 
			
		||||
        require(balances[_to] + _value >= balances[_to], "UINT256_OVERFLOW");
 | 
			
		||||
 | 
			
		||||
        balances[_to] += _value;
 | 
			
		||||
        balances[_from] -= _value;
 | 
			
		||||
        allowed[_from][msg.sender] -= _value;
 | 
			
		||||
 | 
			
		||||
        emit Transfer(_from, _to, _value);
 | 
			
		||||
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev `msg.sender` approves `_spender` to spend `_value` tokens
 | 
			
		||||
    /// @param _spender The address of the account able to transfer the tokens
 | 
			
		||||
    /// @param _value The amount of wei to be approved for transfer
 | 
			
		||||
    /// @return Always true if the call has enough gas to complete execution
 | 
			
		||||
    function approve(address _spender, uint256 _value) external returns (bool) {
 | 
			
		||||
        allowed[msg.sender][_spender] = _value;
 | 
			
		||||
        emit Approval(msg.sender, _spender, _value);
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Query total supply of token
 | 
			
		||||
    /// @return Total supply of token
 | 
			
		||||
    function totalSupply() external view returns (uint256) {
 | 
			
		||||
        return _totalSupply;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Query the balance of owner
 | 
			
		||||
    /// @param _owner The address from which the balance will be retrieved
 | 
			
		||||
    /// @return Balance of owner
 | 
			
		||||
    function balanceOf(address _owner) external view returns (uint256) {
 | 
			
		||||
        return balances[_owner];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @param _owner The address of the account owning tokens
 | 
			
		||||
    /// @param _spender The address of the account able to transfer the tokens
 | 
			
		||||
    /// @return Amount of remaining tokens allowed to spent
 | 
			
		||||
    function allowance(address _owner, address _spender) external view returns (uint256) {
 | 
			
		||||
        return allowed[_owner][_spender];
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,136 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  Copyright 2019 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.5.9;
 | 
			
		||||
 | 
			
		||||
import "@0x/contracts-utils/contracts/src/LibRichErrors.sol";
 | 
			
		||||
import "@0x/contracts-utils/contracts/src/LibBytes.sol";
 | 
			
		||||
import "../src/interfaces/IERC20Token.sol";
 | 
			
		||||
 | 
			
		||||
library LibERC20Token {
 | 
			
		||||
    bytes private constant DECIMALS_CALL_DATA = hex"313ce567";
 | 
			
		||||
 | 
			
		||||
    /// @dev Calls `IERC20Token(token).approve()`.
 | 
			
		||||
    ///      Reverts if `false` is returned or if the return
 | 
			
		||||
    ///      data length is nonzero and not 32 bytes.
 | 
			
		||||
    /// @param token The address of the token contract.
 | 
			
		||||
    /// @param spender The address that receives an allowance.
 | 
			
		||||
    /// @param allowance The allowance to set.
 | 
			
		||||
    function approve(address token, address spender, uint256 allowance) internal {
 | 
			
		||||
        bytes memory callData = abi.encodeWithSelector(IERC20Token(0).approve.selector, spender, allowance);
 | 
			
		||||
        _callWithOptionalBooleanResult(token, callData);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Calls `IERC20Token(token).approve()` and sets the allowance to the
 | 
			
		||||
    ///      maximum if the current approval is not already >= an amount.
 | 
			
		||||
    ///      Reverts if `false` is returned or if the return
 | 
			
		||||
    ///      data length is nonzero and not 32 bytes.
 | 
			
		||||
    /// @param token The address of the token contract.
 | 
			
		||||
    /// @param spender The address that receives an allowance.
 | 
			
		||||
    /// @param amount The minimum allowance needed.
 | 
			
		||||
    function approveIfBelow(address token, address spender, uint256 amount) internal {
 | 
			
		||||
        if (IERC20Token(token).allowance(address(this), spender) < amount) {
 | 
			
		||||
            approve(token, spender, uint256(-1));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Calls `IERC20Token(token).transfer()`.
 | 
			
		||||
    ///      Reverts if `false` is returned or if the return
 | 
			
		||||
    ///      data length is nonzero and not 32 bytes.
 | 
			
		||||
    /// @param token The address of the token contract.
 | 
			
		||||
    /// @param to The address that receives the tokens
 | 
			
		||||
    /// @param amount Number of tokens to transfer.
 | 
			
		||||
    function transfer(address token, address to, uint256 amount) internal {
 | 
			
		||||
        bytes memory callData = abi.encodeWithSelector(IERC20Token(0).transfer.selector, to, amount);
 | 
			
		||||
        _callWithOptionalBooleanResult(token, callData);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Calls `IERC20Token(token).transferFrom()`.
 | 
			
		||||
    ///      Reverts if `false` is returned or if the return
 | 
			
		||||
    ///      data length is nonzero and not 32 bytes.
 | 
			
		||||
    /// @param token The address of the token contract.
 | 
			
		||||
    /// @param from The owner of the tokens.
 | 
			
		||||
    /// @param to The address that receives the tokens
 | 
			
		||||
    /// @param amount Number of tokens to transfer.
 | 
			
		||||
    function transferFrom(address token, address from, address to, uint256 amount) internal {
 | 
			
		||||
        bytes memory callData = abi.encodeWithSelector(IERC20Token(0).transferFrom.selector, from, to, amount);
 | 
			
		||||
        _callWithOptionalBooleanResult(token, callData);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Retrieves the number of decimals for a token.
 | 
			
		||||
    ///      Returns `18` if the call reverts.
 | 
			
		||||
    /// @param token The address of the token contract.
 | 
			
		||||
    /// @return tokenDecimals The number of decimals places for the token.
 | 
			
		||||
    function decimals(address token) internal view returns (uint8 tokenDecimals) {
 | 
			
		||||
        tokenDecimals = 18;
 | 
			
		||||
        (bool didSucceed, bytes memory resultData) = token.staticcall(DECIMALS_CALL_DATA);
 | 
			
		||||
        if (didSucceed && resultData.length == 32) {
 | 
			
		||||
            tokenDecimals = uint8(LibBytes.readUint256(resultData, 0));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Retrieves the allowance for a token, owner, and spender.
 | 
			
		||||
    ///      Returns `0` if the call reverts.
 | 
			
		||||
    /// @param token The address of the token contract.
 | 
			
		||||
    /// @param owner The owner of the tokens.
 | 
			
		||||
    /// @param spender The address the spender.
 | 
			
		||||
    /// @return allowance The allowance for a token, owner, and spender.
 | 
			
		||||
    function allowance(address token, address owner, address spender) internal view returns (uint256 allowance_) {
 | 
			
		||||
        (bool didSucceed, bytes memory resultData) = token.staticcall(
 | 
			
		||||
            abi.encodeWithSelector(IERC20Token(0).allowance.selector, owner, spender)
 | 
			
		||||
        );
 | 
			
		||||
        if (didSucceed && resultData.length == 32) {
 | 
			
		||||
            allowance_ = LibBytes.readUint256(resultData, 0);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Retrieves the balance for a token owner.
 | 
			
		||||
    ///      Returns `0` if the call reverts.
 | 
			
		||||
    /// @param token The address of the token contract.
 | 
			
		||||
    /// @param owner The owner of the tokens.
 | 
			
		||||
    /// @return balance The token balance of an owner.
 | 
			
		||||
    function balanceOf(address token, address owner) internal view returns (uint256 balance) {
 | 
			
		||||
        (bool didSucceed, bytes memory resultData) = token.staticcall(
 | 
			
		||||
            abi.encodeWithSelector(IERC20Token(0).balanceOf.selector, owner)
 | 
			
		||||
        );
 | 
			
		||||
        if (didSucceed && resultData.length == 32) {
 | 
			
		||||
            balance = LibBytes.readUint256(resultData, 0);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Executes a call on address `target` with calldata `callData`
 | 
			
		||||
    ///      and asserts that either nothing was returned or a single boolean
 | 
			
		||||
    ///      was returned equal to `true`.
 | 
			
		||||
    /// @param target The call target.
 | 
			
		||||
    /// @param callData The abi-encoded call data.
 | 
			
		||||
    function _callWithOptionalBooleanResult(address target, bytes memory callData) private {
 | 
			
		||||
        (bool didSucceed, bytes memory resultData) = target.call(callData);
 | 
			
		||||
        if (didSucceed) {
 | 
			
		||||
            if (resultData.length == 0) {
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            if (resultData.length == 32) {
 | 
			
		||||
                uint256 result = LibBytes.readUint256(resultData, 0);
 | 
			
		||||
                if (result == 1) {
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        LibRichErrors.rrevert(resultData);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,46 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  Copyright 2019 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.5.9;
 | 
			
		||||
 | 
			
		||||
import "@0x/contracts-utils/contracts/src/LibSafeMath.sol";
 | 
			
		||||
import "./UnlimitedAllowanceERC20Token.sol";
 | 
			
		||||
 | 
			
		||||
contract MintableERC20Token is UnlimitedAllowanceERC20Token {
 | 
			
		||||
    using LibSafeMath for uint256;
 | 
			
		||||
 | 
			
		||||
    /// @dev Mints new tokens
 | 
			
		||||
    /// @param _to Address of the beneficiary that will own the minted token
 | 
			
		||||
    /// @param _value Amount of tokens to mint
 | 
			
		||||
    function _mint(address _to, uint256 _value) internal {
 | 
			
		||||
        balances[_to] = _value.safeAdd(balances[_to]);
 | 
			
		||||
        _totalSupply = _totalSupply.safeAdd(_value);
 | 
			
		||||
 | 
			
		||||
        emit Transfer(address(0), _to, _value);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Mints new tokens
 | 
			
		||||
    /// @param _owner Owner of tokens that will be burned
 | 
			
		||||
    /// @param _value Amount of tokens to burn
 | 
			
		||||
    function _burn(address _owner, uint256 _value) internal {
 | 
			
		||||
        balances[_owner] = balances[_owner].safeSub(_value);
 | 
			
		||||
        _totalSupply = _totalSupply.safeSub(_value);
 | 
			
		||||
 | 
			
		||||
        emit Transfer(_owner, address(0), _value);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,48 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  Copyright 2019 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.5.9;
 | 
			
		||||
 | 
			
		||||
import "./ERC20Token.sol";
 | 
			
		||||
 | 
			
		||||
contract UnlimitedAllowanceERC20Token is ERC20Token {
 | 
			
		||||
    uint256 internal constant MAX_UINT = 2 ** 256 - 1;
 | 
			
		||||
 | 
			
		||||
    /// @dev ERC20 transferFrom, modified such that an allowance of MAX_UINT represents an unlimited allowance.
 | 
			
		||||
    // See https://github.com/ethereum/EIPs/issues/717
 | 
			
		||||
    /// @param _from Address to transfer from.
 | 
			
		||||
    /// @param _to Address to transfer to.
 | 
			
		||||
    /// @param _value Amount to transfer.
 | 
			
		||||
    /// @return Success of transfer.
 | 
			
		||||
    function transferFrom(address _from, address _to, uint256 _value) external returns (bool) {
 | 
			
		||||
        uint256 allowance = allowed[_from][msg.sender];
 | 
			
		||||
        require(balances[_from] >= _value, "ERC20_INSUFFICIENT_BALANCE");
 | 
			
		||||
        require(allowance >= _value, "ERC20_INSUFFICIENT_ALLOWANCE");
 | 
			
		||||
        require(balances[_to] + _value >= balances[_to], "UINT256_OVERFLOW");
 | 
			
		||||
 | 
			
		||||
        balances[_to] += _value;
 | 
			
		||||
        balances[_from] -= _value;
 | 
			
		||||
        if (allowance < MAX_UINT) {
 | 
			
		||||
            allowed[_from][msg.sender] -= _value;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        emit Transfer(_from, _to, _value);
 | 
			
		||||
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,57 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  Copyright 2019 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.5.9;
 | 
			
		||||
 | 
			
		||||
contract IERC20Token {
 | 
			
		||||
    event Transfer(address indexed _from, address indexed _to, uint256 _value);
 | 
			
		||||
 | 
			
		||||
    event Approval(address indexed _owner, address indexed _spender, uint256 _value);
 | 
			
		||||
 | 
			
		||||
    /// @dev send `value` token to `to` from `msg.sender`
 | 
			
		||||
    /// @param _to The address of the recipient
 | 
			
		||||
    /// @param _value The amount of token to be transferred
 | 
			
		||||
    /// @return True if transfer was successful
 | 
			
		||||
    function transfer(address _to, uint256 _value) external returns (bool);
 | 
			
		||||
 | 
			
		||||
    /// @dev send `value` token to `to` from `from` on the condition it is approved by `from`
 | 
			
		||||
    /// @param _from The address of the sender
 | 
			
		||||
    /// @param _to The address of the recipient
 | 
			
		||||
    /// @param _value The amount of token to be transferred
 | 
			
		||||
    /// @return True if transfer was successful
 | 
			
		||||
    function transferFrom(address _from, address _to, uint256 _value) external returns (bool);
 | 
			
		||||
 | 
			
		||||
    /// @dev `msg.sender` approves `_spender` to spend `_value` tokens
 | 
			
		||||
    /// @param _spender The address of the account able to transfer the tokens
 | 
			
		||||
    /// @param _value The amount of wei to be approved for transfer
 | 
			
		||||
    /// @return Always true if the call has enough gas to complete execution
 | 
			
		||||
    function approve(address _spender, uint256 _value) external returns (bool);
 | 
			
		||||
 | 
			
		||||
    /// @dev Query total supply of token
 | 
			
		||||
    /// @return Total supply of token
 | 
			
		||||
    function totalSupply() external view returns (uint256);
 | 
			
		||||
 | 
			
		||||
    /// @param _owner The address from which the balance will be retrieved
 | 
			
		||||
    /// @return Balance of owner
 | 
			
		||||
    function balanceOf(address _owner) external view returns (uint256);
 | 
			
		||||
 | 
			
		||||
    /// @param _owner The address of the account owning tokens
 | 
			
		||||
    /// @param _spender The address of the account able to transfer the tokens
 | 
			
		||||
    /// @return Amount of remaining tokens allowed to spent
 | 
			
		||||
    function allowance(address _owner, address _spender) external view returns (uint256);
 | 
			
		||||
}
 | 
			
		||||
@@ -1,27 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  Copyright 2019 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.5.9;
 | 
			
		||||
 | 
			
		||||
import "./IERC20Token.sol";
 | 
			
		||||
 | 
			
		||||
contract IEtherToken is IERC20Token {
 | 
			
		||||
    function deposit() public payable;
 | 
			
		||||
 | 
			
		||||
    function withdraw(uint256 amount) public;
 | 
			
		||||
}
 | 
			
		||||
@@ -1,63 +0,0 @@
 | 
			
		||||
// SPDX-License-Identifier: Apache-2.0
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  Copyright 2020 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.8.0;
 | 
			
		||||
 | 
			
		||||
interface IERC20TokenV08 {
 | 
			
		||||
    event Transfer(address indexed from, address indexed to, uint256 value);
 | 
			
		||||
 | 
			
		||||
    event Approval(address indexed owner, address indexed spender, uint256 value);
 | 
			
		||||
 | 
			
		||||
    /// @dev send `value` token to `to` from `msg.sender`
 | 
			
		||||
    /// @param to The address of the recipient
 | 
			
		||||
    /// @param value The amount of token to be transferred
 | 
			
		||||
    /// @return True if transfer was successful
 | 
			
		||||
    function transfer(address to, uint256 value) external returns (bool);
 | 
			
		||||
 | 
			
		||||
    /// @dev send `value` token to `to` from `from` on the condition it is approved by `from`
 | 
			
		||||
    /// @param from The address of the sender
 | 
			
		||||
    /// @param to The address of the recipient
 | 
			
		||||
    /// @param value The amount of token to be transferred
 | 
			
		||||
    /// @return True if transfer was successful
 | 
			
		||||
    function transferFrom(address from, address to, uint256 value) external returns (bool);
 | 
			
		||||
 | 
			
		||||
    /// @dev `msg.sender` approves `spender` to spend `value` tokens
 | 
			
		||||
    /// @param spender The address of the account able to transfer the tokens
 | 
			
		||||
    /// @param value The amount of wei to be approved for transfer
 | 
			
		||||
    /// @return Always true if the call has enough gas to complete execution
 | 
			
		||||
    function approve(address spender, uint256 value) external returns (bool);
 | 
			
		||||
 | 
			
		||||
    /// @dev Query total supply of token
 | 
			
		||||
    /// @return Total supply of token
 | 
			
		||||
    function totalSupply() external view returns (uint256);
 | 
			
		||||
 | 
			
		||||
    /// @dev Get the balance of `owner`.
 | 
			
		||||
    /// @param owner The address from which the balance will be retrieved
 | 
			
		||||
    /// @return Balance of owner
 | 
			
		||||
    function balanceOf(address owner) external view returns (uint256);
 | 
			
		||||
 | 
			
		||||
    /// @dev Get the allowance for `spender` to spend from `owner`.
 | 
			
		||||
    /// @param owner The address of the account owning tokens
 | 
			
		||||
    /// @param spender The address of the account able to transfer the tokens
 | 
			
		||||
    /// @return Amount of remaining tokens allowed to spent
 | 
			
		||||
    function allowance(address owner, address spender) external view returns (uint256);
 | 
			
		||||
 | 
			
		||||
    /// @dev Get the number of decimals this token has.
 | 
			
		||||
    function decimals() external view returns (uint8);
 | 
			
		||||
}
 | 
			
		||||
@@ -1,30 +0,0 @@
 | 
			
		||||
// SPDX-License-Identifier: Apache-2.0
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  Copyright 2020 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.8.0;
 | 
			
		||||
 | 
			
		||||
import "./IERC20TokenV08.sol";
 | 
			
		||||
 | 
			
		||||
interface IEtherTokenV08 is IERC20TokenV08 {
 | 
			
		||||
    /// @dev Wrap ether.
 | 
			
		||||
    function deposit() external payable;
 | 
			
		||||
 | 
			
		||||
    /// @dev Unwrap ether.
 | 
			
		||||
    function withdraw(uint256 amount) external;
 | 
			
		||||
}
 | 
			
		||||
@@ -1,61 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  Copyright 2019 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.5.5;
 | 
			
		||||
 | 
			
		||||
import "@0x/contracts-utils/contracts/src/LibSafeMath.sol";
 | 
			
		||||
import "@0x/contracts-utils/contracts/src/Ownable.sol";
 | 
			
		||||
import "../src/MintableERC20Token.sol";
 | 
			
		||||
 | 
			
		||||
contract DummyERC20Token is Ownable, MintableERC20Token {
 | 
			
		||||
    using LibSafeMath for uint256;
 | 
			
		||||
 | 
			
		||||
    string public name;
 | 
			
		||||
    string public symbol;
 | 
			
		||||
    uint256 public decimals;
 | 
			
		||||
    uint256 public constant MAX_MINT_AMOUNT = 10000000000000000000000;
 | 
			
		||||
 | 
			
		||||
    constructor(string memory _name, string memory _symbol, uint256 _decimals, uint256 _totalSupply) public {
 | 
			
		||||
        name = _name;
 | 
			
		||||
        symbol = _symbol;
 | 
			
		||||
        decimals = _decimals;
 | 
			
		||||
        _totalSupply = _totalSupply;
 | 
			
		||||
        balances[msg.sender] = _totalSupply;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Sets the balance of target address
 | 
			
		||||
    /// @param _target Address or which balance will be updated
 | 
			
		||||
    /// @param _value New balance of target address
 | 
			
		||||
    function setBalance(address _target, uint256 _value) external onlyOwner {
 | 
			
		||||
        uint256 currBalance = balances[_target];
 | 
			
		||||
        if (_value < currBalance) {
 | 
			
		||||
            _totalSupply = _totalSupply.safeSub(currBalance.safeSub(_value));
 | 
			
		||||
        } else {
 | 
			
		||||
            _totalSupply = _totalSupply.safeAdd(_value.safeSub(currBalance));
 | 
			
		||||
        }
 | 
			
		||||
        balances[_target] = _value;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Mints new tokens for sender
 | 
			
		||||
    /// @param _value Amount of tokens to mint
 | 
			
		||||
    function mint(uint256 _value) external {
 | 
			
		||||
        require(_value <= MAX_MINT_AMOUNT, "VALUE_TOO_LARGE");
 | 
			
		||||
 | 
			
		||||
        _mint(msg.sender, _value);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,46 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  Copyright 2019 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.5.5;
 | 
			
		||||
 | 
			
		||||
import "./DummyERC20Token.sol";
 | 
			
		||||
 | 
			
		||||
contract DummyMultipleReturnERC20Token is DummyERC20Token {
 | 
			
		||||
    constructor(
 | 
			
		||||
        string memory _name,
 | 
			
		||||
        string memory _symbol,
 | 
			
		||||
        uint256 _decimals,
 | 
			
		||||
        uint256 _totalSupply
 | 
			
		||||
    ) public DummyERC20Token(_name, _symbol, _decimals, _totalSupply) {}
 | 
			
		||||
 | 
			
		||||
    /// @dev send `value` token to `to` from `from` on the condition it is approved by `from`
 | 
			
		||||
    /// @param _from The address of the sender
 | 
			
		||||
    /// @param _to The address of the recipient
 | 
			
		||||
    /// @param _value The amount of token to be transferred
 | 
			
		||||
    function transferFrom(address _from, address _to, uint256 _value) external returns (bool) {
 | 
			
		||||
        emit Transfer(_from, _to, _value);
 | 
			
		||||
 | 
			
		||||
        // HACK: This contract will not compile if we remove `returns (bool)`, so we manually return 64 bytes
 | 
			
		||||
        // (equiavalent to true, true)
 | 
			
		||||
        assembly {
 | 
			
		||||
            mstore(0, 1)
 | 
			
		||||
            mstore(32, 1)
 | 
			
		||||
            return(0, 64)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,69 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  Copyright 2019 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.5.5;
 | 
			
		||||
 | 
			
		||||
import "./DummyERC20Token.sol";
 | 
			
		||||
 | 
			
		||||
contract DummyNoReturnERC20Token is DummyERC20Token {
 | 
			
		||||
    constructor(
 | 
			
		||||
        string memory _name,
 | 
			
		||||
        string memory _symbol,
 | 
			
		||||
        uint256 _decimals,
 | 
			
		||||
        uint256 _totalSupply
 | 
			
		||||
    ) public DummyERC20Token(_name, _symbol, _decimals, _totalSupply) {}
 | 
			
		||||
 | 
			
		||||
    /// @dev send `value` token to `to` from `msg.sender`
 | 
			
		||||
    /// @param _to The address of the recipient
 | 
			
		||||
    /// @param _value The amount of token to be transferred
 | 
			
		||||
    function transfer(address _to, uint256 _value) external returns (bool) {
 | 
			
		||||
        require(balances[msg.sender] >= _value, "ERC20_INSUFFICIENT_BALANCE");
 | 
			
		||||
        require(balances[_to] + _value >= balances[_to], "UINT256_OVERFLOW");
 | 
			
		||||
 | 
			
		||||
        balances[msg.sender] -= _value;
 | 
			
		||||
        balances[_to] += _value;
 | 
			
		||||
 | 
			
		||||
        emit Transfer(msg.sender, _to, _value);
 | 
			
		||||
 | 
			
		||||
        // HACK: This contract will not compile if we remove `returns (bool)`, so we manually return no data
 | 
			
		||||
        assembly {
 | 
			
		||||
            return(0, 0)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev send `value` token to `to` from `from` on the condition it is approved by `from`
 | 
			
		||||
    /// @param _from The address of the sender
 | 
			
		||||
    /// @param _to The address of the recipient
 | 
			
		||||
    /// @param _value The amount of token to be transferred
 | 
			
		||||
    function transferFrom(address _from, address _to, uint256 _value) external returns (bool) {
 | 
			
		||||
        require(balances[_from] >= _value, "ERC20_INSUFFICIENT_BALANCE");
 | 
			
		||||
        require(allowed[_from][msg.sender] >= _value, "ERC20_INSUFFICIENT_ALLOWANCE");
 | 
			
		||||
        require(balances[_to] + _value >= balances[_to], "UINT256_OVERFLOW");
 | 
			
		||||
 | 
			
		||||
        balances[_to] += _value;
 | 
			
		||||
        balances[_from] -= _value;
 | 
			
		||||
        allowed[_from][msg.sender] -= _value;
 | 
			
		||||
 | 
			
		||||
        emit Transfer(_from, _to, _value);
 | 
			
		||||
 | 
			
		||||
        // HACK: This contract will not compile if we remove `returns (bool)`, so we manually return no data
 | 
			
		||||
        assembly {
 | 
			
		||||
            return(0, 0)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,73 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  Copyright 2019 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.5.9;
 | 
			
		||||
 | 
			
		||||
import "../src/LibERC20Token.sol";
 | 
			
		||||
import "./TestLibERC20TokenTarget.sol";
 | 
			
		||||
 | 
			
		||||
contract TestLibERC20Token {
 | 
			
		||||
    TestLibERC20TokenTarget public target;
 | 
			
		||||
 | 
			
		||||
    constructor() public {
 | 
			
		||||
        target = new TestLibERC20TokenTarget();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function testApprove(
 | 
			
		||||
        bool shouldRevert,
 | 
			
		||||
        bytes calldata revertData,
 | 
			
		||||
        bytes calldata returnData,
 | 
			
		||||
        address spender,
 | 
			
		||||
        uint256 allowance
 | 
			
		||||
    ) external {
 | 
			
		||||
        target.setBehavior(shouldRevert, revertData, returnData);
 | 
			
		||||
        LibERC20Token.approve(address(target), spender, allowance);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function testTransfer(
 | 
			
		||||
        bool shouldRevert,
 | 
			
		||||
        bytes calldata revertData,
 | 
			
		||||
        bytes calldata returnData,
 | 
			
		||||
        address to,
 | 
			
		||||
        uint256 amount
 | 
			
		||||
    ) external {
 | 
			
		||||
        target.setBehavior(shouldRevert, revertData, returnData);
 | 
			
		||||
        LibERC20Token.transfer(address(target), to, amount);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function testTransferFrom(
 | 
			
		||||
        bool shouldRevert,
 | 
			
		||||
        bytes calldata revertData,
 | 
			
		||||
        bytes calldata returnData,
 | 
			
		||||
        address from,
 | 
			
		||||
        address to,
 | 
			
		||||
        uint256 amount
 | 
			
		||||
    ) external {
 | 
			
		||||
        target.setBehavior(shouldRevert, revertData, returnData);
 | 
			
		||||
        LibERC20Token.transferFrom(address(target), from, to, amount);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function testDecimals(
 | 
			
		||||
        bool shouldRevert,
 | 
			
		||||
        bytes calldata revertData,
 | 
			
		||||
        bytes calldata returnData
 | 
			
		||||
    ) external returns (uint8) {
 | 
			
		||||
        target.setBehavior(shouldRevert, revertData, returnData);
 | 
			
		||||
        return LibERC20Token.decimals(address(target));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,69 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  Copyright 2019 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.5.9;
 | 
			
		||||
 | 
			
		||||
contract TestLibERC20TokenTarget {
 | 
			
		||||
    event ApproveCalled(address spender, uint256 allowance);
 | 
			
		||||
 | 
			
		||||
    event TransferCalled(address to, uint256 amount);
 | 
			
		||||
 | 
			
		||||
    event TransferFromCalled(address from, address to, uint256 amount);
 | 
			
		||||
 | 
			
		||||
    bool private _shouldRevert;
 | 
			
		||||
    bytes private _revertData;
 | 
			
		||||
    bytes private _returnData;
 | 
			
		||||
 | 
			
		||||
    function setBehavior(bool shouldRevert, bytes calldata revertData, bytes calldata returnData) external {
 | 
			
		||||
        _shouldRevert = shouldRevert;
 | 
			
		||||
        _revertData = revertData;
 | 
			
		||||
        _returnData = returnData;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function approve(address spender, uint256 allowance) external returns (bool) {
 | 
			
		||||
        emit ApproveCalled(spender, allowance);
 | 
			
		||||
        _execute();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function transfer(address to, uint256 amount) external returns (bool) {
 | 
			
		||||
        emit TransferCalled(to, amount);
 | 
			
		||||
        _execute();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function transferFrom(address from, address to, uint256 amount) external returns (bool) {
 | 
			
		||||
        emit TransferFromCalled(from, to, amount);
 | 
			
		||||
        _execute();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function decimals() external view returns (uint8) {
 | 
			
		||||
        _execute();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function _execute() private view {
 | 
			
		||||
        if (_shouldRevert) {
 | 
			
		||||
            bytes memory revertData = _revertData;
 | 
			
		||||
            assembly {
 | 
			
		||||
                revert(add(revertData, 0x20), mload(revertData))
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        bytes memory returnData = _returnData;
 | 
			
		||||
        assembly {
 | 
			
		||||
            return(add(returnData, 0x20), mload(returnData))
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,38 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  Copyright 2019 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.5.5;
 | 
			
		||||
 | 
			
		||||
import "./DummyERC20Token.sol";
 | 
			
		||||
 | 
			
		||||
contract UntransferrableDummyERC20Token is DummyERC20Token {
 | 
			
		||||
    constructor(
 | 
			
		||||
        string memory _name,
 | 
			
		||||
        string memory _symbol,
 | 
			
		||||
        uint256 _decimals,
 | 
			
		||||
        uint256 _totalSupply
 | 
			
		||||
    ) public DummyERC20Token(_name, _symbol, _decimals, _totalSupply) {}
 | 
			
		||||
 | 
			
		||||
    /// @dev send `value` token to `to` from `from` on the condition it is approved by `from`
 | 
			
		||||
    /// @param _from The address of the sender
 | 
			
		||||
    /// @param _to The address of the recipient
 | 
			
		||||
    /// @param _value The amount of token to be transferred
 | 
			
		||||
    function transferFrom(address _from, address _to, uint256 _value) external returns (bool) {
 | 
			
		||||
        require(false, "TRANSFER_DISABLED");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										18
									
								
								contracts/erc20/foundry.toml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								contracts/erc20/foundry.toml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,18 @@
 | 
			
		||||
[profile.default]
 | 
			
		||||
src = 'src'
 | 
			
		||||
out = 'out'
 | 
			
		||||
libs = [
 | 
			
		||||
    'lib',
 | 
			
		||||
    'node_modules',
 | 
			
		||||
]
 | 
			
		||||
remappings = [
 | 
			
		||||
    '@0x/contracts-utils/=../utils/'
 | 
			
		||||
]
 | 
			
		||||
allow_paths = [
 | 
			
		||||
    '../utils/'
 | 
			
		||||
]
 | 
			
		||||
 | 
			
		||||
fs_permissions = [{ access = "read", path = "./out/ZRXToken.sol" }]
 | 
			
		||||
 | 
			
		||||
optimizer_runs = 1_000_000
 | 
			
		||||
# See more config options https://github.com/foundry-rs/foundry/tree/master/config
 | 
			
		||||
							
								
								
									
										1
									
								
								contracts/erc20/lib/forge-std
									
									
									
									
									
										Submodule
									
								
							
							
								
								
								
								
								
							
						
						
									
										1
									
								
								contracts/erc20/lib/forge-std
									
									
									
									
									
										Submodule
									
								
							 Submodule contracts/erc20/lib/forge-std added at a2edd39db9
									
								
							@@ -1,6 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
    "name": "@0x/contracts-erc20",
 | 
			
		||||
    "version": "3.3.57",
 | 
			
		||||
    "version": "4.0.0",
 | 
			
		||||
    "engines": {
 | 
			
		||||
        "node": ">=6.12"
 | 
			
		||||
    },
 | 
			
		||||
@@ -10,31 +10,10 @@
 | 
			
		||||
        "test": "test"
 | 
			
		||||
    },
 | 
			
		||||
    "scripts": {
 | 
			
		||||
        "build": "yarn pre_build && tsc -b",
 | 
			
		||||
        "build:ci": "yarn build",
 | 
			
		||||
        "pre_build": "run-s compile contracts:gen generate_contract_wrappers contracts:copy",
 | 
			
		||||
        "test": "yarn run_mocha",
 | 
			
		||||
        "rebuild_and_test": "run-s build test",
 | 
			
		||||
        "test:profiler": "SOLIDITY_PROFILER=true run-s build run_mocha profiler:report:html",
 | 
			
		||||
        "test:trace": "SOLIDITY_REVERT_TRACE=true run-s build run_mocha",
 | 
			
		||||
        "run_mocha": "mocha --require source-map-support/register --require make-promises-safe 'lib/test/**/*.js' --timeout 100000 --bail --exit",
 | 
			
		||||
        "compile": "sol-compiler",
 | 
			
		||||
        "watch": "sol-compiler -w",
 | 
			
		||||
        "clean": "shx rm -rf lib test/generated-artifacts test/generated-wrappers generated-artifacts generated-wrappers",
 | 
			
		||||
        "generate_contract_wrappers": "abi-gen --debug --abis  ${npm_package_config_abis} --output test/generated-wrappers --backend ethers",
 | 
			
		||||
        "lint": "eslint src test",
 | 
			
		||||
        "fix": "eslint --fix src test",
 | 
			
		||||
        "test:ci": "yarn test",
 | 
			
		||||
        "contracts:gen": "contracts-gen generate",
 | 
			
		||||
        "contracts:copy": "contracts-gen copy",
 | 
			
		||||
        "test:ci": "forge test",
 | 
			
		||||
        "docs:md": "ts-doc-gen --sourceDir='$PROJECT_FILES' --output=$MD_FILE_DIR --fileExtension=mdx --tsconfig=./typedoc-tsconfig.json",
 | 
			
		||||
        "docs:json": "typedoc --excludePrivate --excludeExternals --excludeProtected --ignoreCompilerErrors --target ES5 --tsconfig typedoc-tsconfig.json --json $JSON_FILE_PATH $PROJECT_FILES"
 | 
			
		||||
    },
 | 
			
		||||
    "config": {
 | 
			
		||||
        "publicInterfaceContracts": "DummyERC20Token,ERC20Token,WETH9,ZRXToken,DummyNoReturnERC20Token,DummyMultipleReturnERC20Token",
 | 
			
		||||
        "abis": "./test/generated-artifacts/@(DummyERC20Token|DummyMultipleReturnERC20Token|DummyNoReturnERC20Token|ERC20Token|IERC20Token|IERC20TokenV06|IERC20TokenV08|IEtherToken|IEtherTokenV06|IEtherTokenV08|LibERC20Token|LibERC20TokenV06|LibERC20TokenV08|MintableERC20Token|TestLibERC20Token|TestLibERC20TokenTarget|UnlimitedAllowanceERC20Token|UntransferrableDummyERC20Token|WETH9|WETH9V06|ZRXToken).json",
 | 
			
		||||
        "abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually."
 | 
			
		||||
    },
 | 
			
		||||
    "repository": {
 | 
			
		||||
        "type": "git",
 | 
			
		||||
        "url": "https://github.com/0xProject/protocol.git"
 | 
			
		||||
@@ -43,43 +22,13 @@
 | 
			
		||||
    "bugs": {
 | 
			
		||||
        "url": "https://github.com/0xProject/protocol/issues"
 | 
			
		||||
    },
 | 
			
		||||
    "homepage": "https://github.com/0xProject/protocol/tree/main/contracts/tokens",
 | 
			
		||||
    "homepage": "https://github.com/0xProject/protocol",
 | 
			
		||||
    "devDependencies": {
 | 
			
		||||
        "@0x/abi-gen": "^5.8.1",
 | 
			
		||||
        "@0x/contracts-gen": "^2.0.48",
 | 
			
		||||
        "@0x/contracts-test-utils": "^5.4.47",
 | 
			
		||||
        "@0x/contracts-utils": "^4.8.38",
 | 
			
		||||
        "@0x/dev-utils": "^5.0.0",
 | 
			
		||||
        "@0x/sol-compiler": "^4.8.2",
 | 
			
		||||
        "@0x/ts-doc-gen": "^0.0.28",
 | 
			
		||||
        "@0x/types": "^3.3.6",
 | 
			
		||||
        "@0x/typescript-typings": "^5.3.1",
 | 
			
		||||
        "@0x/utils": "^7.0.0",
 | 
			
		||||
        "@0x/web3-wrapper": "^8.0.0",
 | 
			
		||||
        "@types/lodash": "4.14.104",
 | 
			
		||||
        "@types/mocha": "^5.2.7",
 | 
			
		||||
        "@types/node": "12.12.54",
 | 
			
		||||
        "@typescript-eslint/eslint-plugin": "^5.38.0",
 | 
			
		||||
        "@typescript-eslint/parser": "^5.38.0",
 | 
			
		||||
        "chai": "^4.0.1",
 | 
			
		||||
        "chai-as-promised": "^7.1.0",
 | 
			
		||||
        "chai-bignumber": "^3.0.0",
 | 
			
		||||
        "dirty-chai": "^2.0.1",
 | 
			
		||||
        "eslint": "^8.23.1",
 | 
			
		||||
        "eslint-config-prettier": "^8.5.0",
 | 
			
		||||
        "ethereum-types": "^3.7.1",
 | 
			
		||||
        "lodash": "^4.17.11",
 | 
			
		||||
        "make-promises-safe": "^1.1.0",
 | 
			
		||||
        "mocha": "^6.2.0",
 | 
			
		||||
        "npm-run-all": "^4.1.2",
 | 
			
		||||
        "shx": "^0.2.2",
 | 
			
		||||
        "typedoc": "~0.16.11",
 | 
			
		||||
        "typescript": "4.6.3"
 | 
			
		||||
    },
 | 
			
		||||
    "dependencies": {
 | 
			
		||||
        "@0x/base-contract": "^7.0.0",
 | 
			
		||||
        "ethers": "~4.0.4"
 | 
			
		||||
        "typedoc": "~0.16.11"
 | 
			
		||||
    },
 | 
			
		||||
    "dependencies": {},
 | 
			
		||||
    "publishConfig": {
 | 
			
		||||
        "access": "public"
 | 
			
		||||
    },
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
// SPDX-License-Identifier: Apache-2.0
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  Copyright 2020 ZeroEx Intl.
 | 
			
		||||
  Copyright 2023 ZeroEx Intl.
 | 
			
		||||
 | 
			
		||||
  Licensed under the Apache License, Version 2.0 (the "License");
 | 
			
		||||
  you may not use this file except in compliance with the License.
 | 
			
		||||
@@ -17,9 +17,9 @@
 | 
			
		||||
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
pragma solidity ^0.6.5;
 | 
			
		||||
pragma solidity >=0.6.5 <0.9;
 | 
			
		||||
 | 
			
		||||
interface IERC20TokenV06 {
 | 
			
		||||
interface IERC20Token {
 | 
			
		||||
    event Transfer(address indexed from, address indexed to, uint256 value);
 | 
			
		||||
 | 
			
		||||
    event Approval(address indexed owner, address indexed spender, uint256 value);
 | 
			
		||||
@@ -19,9 +19,9 @@
 | 
			
		||||
 | 
			
		||||
pragma solidity ^0.6.5;
 | 
			
		||||
 | 
			
		||||
import "./IERC20TokenV06.sol";
 | 
			
		||||
import "./IERC20Token.sol";
 | 
			
		||||
 | 
			
		||||
interface IEtherTokenV06 is IERC20TokenV06 {
 | 
			
		||||
interface IEtherToken is IERC20Token {
 | 
			
		||||
    /// @dev Wrap ether.
 | 
			
		||||
    function deposit() external payable;
 | 
			
		||||
 | 
			
		||||
@@ -1,21 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * -----------------------------------------------------------------------------
 | 
			
		||||
 * Warning: This file is auto-generated by contracts-gen. Don't edit manually.
 | 
			
		||||
 * -----------------------------------------------------------------------------
 | 
			
		||||
 */
 | 
			
		||||
import { ContractArtifact } from 'ethereum-types';
 | 
			
		||||
 | 
			
		||||
import * as DummyERC20Token from '../generated-artifacts/DummyERC20Token.json';
 | 
			
		||||
import * as DummyMultipleReturnERC20Token from '../generated-artifacts/DummyMultipleReturnERC20Token.json';
 | 
			
		||||
import * as DummyNoReturnERC20Token from '../generated-artifacts/DummyNoReturnERC20Token.json';
 | 
			
		||||
import * as ERC20Token from '../generated-artifacts/ERC20Token.json';
 | 
			
		||||
import * as WETH9 from '../generated-artifacts/WETH9.json';
 | 
			
		||||
import * as ZRXToken from '../generated-artifacts/ZRXToken.json';
 | 
			
		||||
export const artifacts = {
 | 
			
		||||
    DummyERC20Token: DummyERC20Token as ContractArtifact,
 | 
			
		||||
    ERC20Token: ERC20Token as ContractArtifact,
 | 
			
		||||
    WETH9: WETH9 as ContractArtifact,
 | 
			
		||||
    ZRXToken: ZRXToken as any as ContractArtifact,
 | 
			
		||||
    DummyNoReturnERC20Token: DummyNoReturnERC20Token as ContractArtifact,
 | 
			
		||||
    DummyMultipleReturnERC20Token: DummyMultipleReturnERC20Token as ContractArtifact,
 | 
			
		||||
};
 | 
			
		||||
@@ -1,47 +0,0 @@
 | 
			
		||||
export {
 | 
			
		||||
    DummyERC20TokenContract,
 | 
			
		||||
    DummyMultipleReturnERC20TokenContract,
 | 
			
		||||
    DummyNoReturnERC20TokenContract,
 | 
			
		||||
    WETH9Contract,
 | 
			
		||||
    WETH9Events,
 | 
			
		||||
    WETH9DepositEventArgs,
 | 
			
		||||
    WETH9TransferEventArgs,
 | 
			
		||||
    WETH9WithdrawalEventArgs,
 | 
			
		||||
    ZRXTokenContract,
 | 
			
		||||
    DummyERC20TokenTransferEventArgs,
 | 
			
		||||
    ERC20TokenEventArgs,
 | 
			
		||||
    ERC20TokenEvents,
 | 
			
		||||
    ERC20TokenTransferEventArgs,
 | 
			
		||||
    ERC20TokenApprovalEventArgs,
 | 
			
		||||
    ERC20TokenContract,
 | 
			
		||||
} from './wrappers';
 | 
			
		||||
export { artifacts } from './artifacts';
 | 
			
		||||
export {
 | 
			
		||||
    ContractArtifact,
 | 
			
		||||
    ContractChains,
 | 
			
		||||
    CompilerOpts,
 | 
			
		||||
    StandardContractOutput,
 | 
			
		||||
    CompilerSettings,
 | 
			
		||||
    ContractChainData,
 | 
			
		||||
    ContractAbi,
 | 
			
		||||
    DevdocOutput,
 | 
			
		||||
    EvmOutput,
 | 
			
		||||
    CompilerSettingsMetadata,
 | 
			
		||||
    OptimizerSettings,
 | 
			
		||||
    OutputField,
 | 
			
		||||
    ParamDescription,
 | 
			
		||||
    EvmBytecodeOutput,
 | 
			
		||||
    EvmBytecodeOutputLinkReferences,
 | 
			
		||||
    AbiDefinition,
 | 
			
		||||
    FunctionAbi,
 | 
			
		||||
    EventAbi,
 | 
			
		||||
    RevertErrorAbi,
 | 
			
		||||
    EventParameter,
 | 
			
		||||
    DataItem,
 | 
			
		||||
    MethodAbi,
 | 
			
		||||
    ConstructorAbi,
 | 
			
		||||
    FallbackAbi,
 | 
			
		||||
    ConstructorStateMutability,
 | 
			
		||||
    TupleDataItem,
 | 
			
		||||
    StateMutability,
 | 
			
		||||
} from 'ethereum-types';
 | 
			
		||||
@@ -21,50 +21,50 @@ pragma solidity ^0.6.5;
 | 
			
		||||
 | 
			
		||||
import "@0x/contracts-utils/contracts/src/v06/errors/LibRichErrorsV06.sol";
 | 
			
		||||
import "@0x/contracts-utils/contracts/src/v06/LibBytesV06.sol";
 | 
			
		||||
import "./IERC20TokenV06.sol";
 | 
			
		||||
import "../IERC20Token.sol";
 | 
			
		||||
 | 
			
		||||
library LibERC20TokenV06 {
 | 
			
		||||
    bytes private constant DECIMALS_CALL_DATA = hex"313ce567";
 | 
			
		||||
 | 
			
		||||
    /// @dev Calls `IERC20TokenV06(token).approve()`.
 | 
			
		||||
    /// @dev Calls `IERC20Token(token).approve()`.
 | 
			
		||||
    ///      Reverts if the return data is invalid or the call reverts.
 | 
			
		||||
    /// @param token The address of the token contract.
 | 
			
		||||
    /// @param spender The address that receives an allowance.
 | 
			
		||||
    /// @param allowance The allowance to set.
 | 
			
		||||
    function compatApprove(IERC20TokenV06 token, address spender, uint256 allowance) internal {
 | 
			
		||||
    function compatApprove(IERC20Token token, address spender, uint256 allowance) internal {
 | 
			
		||||
        bytes memory callData = abi.encodeWithSelector(token.approve.selector, spender, allowance);
 | 
			
		||||
        _callWithOptionalBooleanResult(address(token), callData);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Calls `IERC20TokenV06(token).approve()` and sets the allowance to the
 | 
			
		||||
    /// @dev Calls `IERC20Token(token).approve()` and sets the allowance to the
 | 
			
		||||
    ///      maximum if the current approval is not already >= an amount.
 | 
			
		||||
    ///      Reverts if the return data is invalid or the call reverts.
 | 
			
		||||
    /// @param token The address of the token contract.
 | 
			
		||||
    /// @param spender The address that receives an allowance.
 | 
			
		||||
    /// @param amount The minimum allowance needed.
 | 
			
		||||
    function approveIfBelow(IERC20TokenV06 token, address spender, uint256 amount) internal {
 | 
			
		||||
    function approveIfBelow(IERC20Token token, address spender, uint256 amount) internal {
 | 
			
		||||
        if (token.allowance(address(this), spender) < amount) {
 | 
			
		||||
            compatApprove(token, spender, uint256(-1));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Calls `IERC20TokenV06(token).transfer()`.
 | 
			
		||||
    /// @dev Calls `IERC20Token(token).transfer()`.
 | 
			
		||||
    ///      Reverts if the return data is invalid or the call reverts.
 | 
			
		||||
    /// @param token The address of the token contract.
 | 
			
		||||
    /// @param to The address that receives the tokens
 | 
			
		||||
    /// @param amount Number of tokens to transfer.
 | 
			
		||||
    function compatTransfer(IERC20TokenV06 token, address to, uint256 amount) internal {
 | 
			
		||||
    function compatTransfer(IERC20Token token, address to, uint256 amount) internal {
 | 
			
		||||
        bytes memory callData = abi.encodeWithSelector(token.transfer.selector, to, amount);
 | 
			
		||||
        _callWithOptionalBooleanResult(address(token), callData);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Calls `IERC20TokenV06(token).transferFrom()`.
 | 
			
		||||
    /// @dev Calls `IERC20Token(token).transferFrom()`.
 | 
			
		||||
    ///      Reverts if the return data is invalid or the call reverts.
 | 
			
		||||
    /// @param token The address of the token contract.
 | 
			
		||||
    /// @param from The owner of the tokens.
 | 
			
		||||
    /// @param to The address that receives the tokens
 | 
			
		||||
    /// @param amount Number of tokens to transfer.
 | 
			
		||||
    function compatTransferFrom(IERC20TokenV06 token, address from, address to, uint256 amount) internal {
 | 
			
		||||
    function compatTransferFrom(IERC20Token token, address from, address to, uint256 amount) internal {
 | 
			
		||||
        bytes memory callData = abi.encodeWithSelector(token.transferFrom.selector, from, to, amount);
 | 
			
		||||
        _callWithOptionalBooleanResult(address(token), callData);
 | 
			
		||||
    }
 | 
			
		||||
@@ -73,7 +73,7 @@ library LibERC20TokenV06 {
 | 
			
		||||
    ///      Returns `18` if the call reverts.
 | 
			
		||||
    /// @param token The address of the token contract.
 | 
			
		||||
    /// @return tokenDecimals The number of decimals places for the token.
 | 
			
		||||
    function compatDecimals(IERC20TokenV06 token) internal view returns (uint8 tokenDecimals) {
 | 
			
		||||
    function compatDecimals(IERC20Token token) internal view returns (uint8 tokenDecimals) {
 | 
			
		||||
        tokenDecimals = 18;
 | 
			
		||||
        (bool didSucceed, bytes memory resultData) = address(token).staticcall(DECIMALS_CALL_DATA);
 | 
			
		||||
        if (didSucceed && resultData.length >= 32) {
 | 
			
		||||
@@ -88,7 +88,7 @@ library LibERC20TokenV06 {
 | 
			
		||||
    /// @param spender The address the spender.
 | 
			
		||||
    /// @return allowance_ The allowance for a token, owner, and spender.
 | 
			
		||||
    function compatAllowance(
 | 
			
		||||
        IERC20TokenV06 token,
 | 
			
		||||
        IERC20Token token,
 | 
			
		||||
        address owner,
 | 
			
		||||
        address spender
 | 
			
		||||
    ) internal view returns (uint256 allowance_) {
 | 
			
		||||
@@ -105,7 +105,7 @@ library LibERC20TokenV06 {
 | 
			
		||||
    /// @param token The address of the token contract.
 | 
			
		||||
    /// @param owner The owner of the tokens.
 | 
			
		||||
    /// @return balance The token balance of an owner.
 | 
			
		||||
    function compatBalanceOf(IERC20TokenV06 token, address owner) internal view returns (uint256 balance) {
 | 
			
		||||
    function compatBalanceOf(IERC20Token token, address owner) internal view returns (uint256 balance) {
 | 
			
		||||
        (bool didSucceed, bytes memory resultData) = address(token).staticcall(
 | 
			
		||||
            abi.encodeWithSelector(token.balanceOf.selector, owner)
 | 
			
		||||
        );
 | 
			
		||||
@@ -21,50 +21,50 @@ pragma solidity ^0.8.0;
 | 
			
		||||
 | 
			
		||||
import "@0x/contracts-utils/contracts/src/v08/errors/LibRichErrorsV08.sol";
 | 
			
		||||
import "@0x/contracts-utils/contracts/src/v08/LibBytesV08.sol";
 | 
			
		||||
import "./IERC20TokenV08.sol";
 | 
			
		||||
import "../IERC20Token.sol";
 | 
			
		||||
 | 
			
		||||
library LibERC20TokenV08 {
 | 
			
		||||
    bytes private constant DECIMALS_CALL_DATA = hex"313ce567";
 | 
			
		||||
 | 
			
		||||
    /// @dev Calls `IERC20TokenV08(token).approve()`.
 | 
			
		||||
    /// @dev Calls `IERC20Token(token).approve()`.
 | 
			
		||||
    ///      Reverts if the return data is invalid or the call reverts.
 | 
			
		||||
    /// @param token The address of the token contract.
 | 
			
		||||
    /// @param spender The address that receives an allowance.
 | 
			
		||||
    /// @param allowance The allowance to set.
 | 
			
		||||
    function compatApprove(IERC20TokenV08 token, address spender, uint256 allowance) internal {
 | 
			
		||||
    function compatApprove(IERC20Token token, address spender, uint256 allowance) internal {
 | 
			
		||||
        bytes memory callData = abi.encodeCall(token.approve, (spender, allowance));
 | 
			
		||||
        _callWithOptionalBooleanResult(address(token), callData);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Calls `IERC20TokenV08(token).approve()` and sets the allowance to the
 | 
			
		||||
    /// @dev Calls `IERC20Token(token).approve()` and sets the allowance to the
 | 
			
		||||
    ///      maximum if the current approval is not already >= an amount.
 | 
			
		||||
    ///      Reverts if the return data is invalid or the call reverts.
 | 
			
		||||
    /// @param token The address of the token contract.
 | 
			
		||||
    /// @param spender The address that receives an allowance.
 | 
			
		||||
    /// @param amount The minimum allowance needed.
 | 
			
		||||
    function approveIfBelow(IERC20TokenV08 token, address spender, uint256 amount) internal {
 | 
			
		||||
    function approveIfBelow(IERC20Token token, address spender, uint256 amount) internal {
 | 
			
		||||
        if (token.allowance(address(this), spender) < amount) {
 | 
			
		||||
            compatApprove(token, spender, type(uint256).max);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Calls `IERC20TokenV08(token).transfer()`.
 | 
			
		||||
    /// @dev Calls `IERC20Token(token).transfer()`.
 | 
			
		||||
    ///      Reverts if the return data is invalid or the call reverts.
 | 
			
		||||
    /// @param token The address of the token contract.
 | 
			
		||||
    /// @param to The address that receives the tokens
 | 
			
		||||
    /// @param amount Number of tokens to transfer.
 | 
			
		||||
    function compatTransfer(IERC20TokenV08 token, address to, uint256 amount) internal {
 | 
			
		||||
    function compatTransfer(IERC20Token token, address to, uint256 amount) internal {
 | 
			
		||||
        bytes memory callData = abi.encodeCall(token.transfer, (to, amount));
 | 
			
		||||
        _callWithOptionalBooleanResult(address(token), callData);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Calls `IERC20TokenV08(token).transferFrom()`.
 | 
			
		||||
    /// @dev Calls `IERC20Token(token).transferFrom()`.
 | 
			
		||||
    ///      Reverts if the return data is invalid or the call reverts.
 | 
			
		||||
    /// @param token The address of the token contract.
 | 
			
		||||
    /// @param from The owner of the tokens.
 | 
			
		||||
    /// @param to The address that receives the tokens
 | 
			
		||||
    /// @param amount Number of tokens to transfer.
 | 
			
		||||
    function compatTransferFrom(IERC20TokenV08 token, address from, address to, uint256 amount) internal {
 | 
			
		||||
    function compatTransferFrom(IERC20Token token, address from, address to, uint256 amount) internal {
 | 
			
		||||
        bytes memory callData = abi.encodeCall(token.transferFrom, (from, to, amount));
 | 
			
		||||
        _callWithOptionalBooleanResult(address(token), callData);
 | 
			
		||||
    }
 | 
			
		||||
@@ -73,7 +73,7 @@ library LibERC20TokenV08 {
 | 
			
		||||
    ///      Returns `18` if the call reverts.
 | 
			
		||||
    /// @param token The address of the token contract.
 | 
			
		||||
    /// @return tokenDecimals The number of decimals places for the token.
 | 
			
		||||
    function compatDecimals(IERC20TokenV08 token) internal view returns (uint8 tokenDecimals) {
 | 
			
		||||
    function compatDecimals(IERC20Token token) internal view returns (uint8 tokenDecimals) {
 | 
			
		||||
        tokenDecimals = 18;
 | 
			
		||||
        (bool didSucceed, bytes memory resultData) = address(token).staticcall(DECIMALS_CALL_DATA);
 | 
			
		||||
        if (didSucceed && resultData.length >= 32) {
 | 
			
		||||
@@ -88,7 +88,7 @@ library LibERC20TokenV08 {
 | 
			
		||||
    /// @param spender The address the spender.
 | 
			
		||||
    /// @return allowance_ The allowance for a token, owner, and spender.
 | 
			
		||||
    function compatAllowance(
 | 
			
		||||
        IERC20TokenV08 token,
 | 
			
		||||
        IERC20Token token,
 | 
			
		||||
        address owner,
 | 
			
		||||
        address spender
 | 
			
		||||
    ) internal view returns (uint256 allowance_) {
 | 
			
		||||
@@ -105,7 +105,7 @@ library LibERC20TokenV08 {
 | 
			
		||||
    /// @param token The address of the token contract.
 | 
			
		||||
    /// @param owner The owner of the tokens.
 | 
			
		||||
    /// @return balance The token balance of an owner.
 | 
			
		||||
    function compatBalanceOf(IERC20TokenV08 token, address owner) internal view returns (uint256 balance) {
 | 
			
		||||
    function compatBalanceOf(IERC20Token token, address owner) internal view returns (uint256 balance) {
 | 
			
		||||
        (bool didSucceed, bytes memory resultData) = address(token).staticcall(
 | 
			
		||||
            abi.encodeCall(token.balanceOf, (owner))
 | 
			
		||||
        );
 | 
			
		||||
@@ -1,11 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * -----------------------------------------------------------------------------
 | 
			
		||||
 * Warning: This file is auto-generated by contracts-gen. Don't edit manually.
 | 
			
		||||
 * -----------------------------------------------------------------------------
 | 
			
		||||
 */
 | 
			
		||||
export * from '../generated-wrappers/dummy_erc20_token';
 | 
			
		||||
export * from '../generated-wrappers/dummy_multiple_return_erc20_token';
 | 
			
		||||
export * from '../generated-wrappers/dummy_no_return_erc20_token';
 | 
			
		||||
export * from '../generated-wrappers/erc20_token';
 | 
			
		||||
export * from '../generated-wrappers/weth9';
 | 
			
		||||
export * from '../generated-wrappers/zrx_token';
 | 
			
		||||
							
								
								
									
										76
									
								
								contracts/erc20/test/WETH9V06Test.t.sol
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								contracts/erc20/test/WETH9V06Test.t.sol
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,76 @@
 | 
			
		||||
// SPDX-License-Identifier: Apache-2.0
 | 
			
		||||
/*
 | 
			
		||||
  Copyright 2023 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 "forge-std/Test.sol";
 | 
			
		||||
import "../src/v06/WETH9V06.sol";
 | 
			
		||||
 | 
			
		||||
contract WETH9V06Test is Test {
 | 
			
		||||
    address payable internal owner = payable(vm.addr(1));
 | 
			
		||||
    address payable internal user = payable(vm.addr(2));
 | 
			
		||||
    WETH9V06 internal etherToken;
 | 
			
		||||
 | 
			
		||||
    function setUp() public {
 | 
			
		||||
        vm.deal(owner, 1e20);
 | 
			
		||||
        vm.deal(user, 1e20);
 | 
			
		||||
 | 
			
		||||
        etherToken = new WETH9V06();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function testShouldRevertIfCallerAttemptsToDepositMoreThanTheirBalance() public {
 | 
			
		||||
        vm.prank(user);
 | 
			
		||||
        vm.expectRevert();
 | 
			
		||||
        etherToken.deposit{value: 1e20 + 1}();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function testShouldConvertDepositedETHToWrappedETH() public {
 | 
			
		||||
        vm.prank(user);
 | 
			
		||||
        etherToken.deposit{value: 1e20}();
 | 
			
		||||
        vm.stopPrank();
 | 
			
		||||
 | 
			
		||||
        assertEq(etherToken.balanceOf(user), 1e20);
 | 
			
		||||
        assertEq(address(etherToken).balance, 1e20);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function testShouldRevertIfCallerAttemptsToWithdrawMoreThanTheirBalance() public {
 | 
			
		||||
        vm.prank(user);
 | 
			
		||||
        etherToken.deposit{value: 1e20}();
 | 
			
		||||
 | 
			
		||||
        vm.expectRevert();
 | 
			
		||||
        etherToken.withdraw(1e20 + 1);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function testShouldConvertWithdrawWrappedETHToETH() public {
 | 
			
		||||
        vm.prank(user);
 | 
			
		||||
        etherToken.deposit{value: 1e20}();
 | 
			
		||||
        vm.prank(user);
 | 
			
		||||
        etherToken.withdraw(100);
 | 
			
		||||
        vm.stopPrank();
 | 
			
		||||
 | 
			
		||||
        assertEq(etherToken.balanceOf(user), 1e20 - 100);
 | 
			
		||||
        assertEq(address(etherToken).balance, 1e20 - 100);
 | 
			
		||||
        assertEq(user.balance, 100);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function testShouldConvertSentETHToWrappedETH() public {
 | 
			
		||||
        vm.prank(user);
 | 
			
		||||
        address(etherToken).call{value: 1e20}(new bytes(0));
 | 
			
		||||
        vm.stopPrank();
 | 
			
		||||
 | 
			
		||||
        assertEq(etherToken.balanceOf(user), 1e20);
 | 
			
		||||
        assertEq(address(etherToken).balance, 1e20);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										117
									
								
								contracts/erc20/test/ZRXTokenTest.t.sol
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										117
									
								
								contracts/erc20/test/ZRXTokenTest.t.sol
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,117 @@
 | 
			
		||||
// SPDX-License-Identifier: Apache-2.0
 | 
			
		||||
/*
 | 
			
		||||
  Copyright 2023 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.8.17;
 | 
			
		||||
 | 
			
		||||
import "forge-std/Test.sol";
 | 
			
		||||
import "../src/IERC20Token.sol";
 | 
			
		||||
 | 
			
		||||
contract ZRXTokenTest is Test {
 | 
			
		||||
    address payable internal owner = payable(vm.addr(1));
 | 
			
		||||
    address payable internal user = payable(vm.addr(2));
 | 
			
		||||
    address payable internal anotherUser = payable(vm.addr(3));
 | 
			
		||||
    uint256 internal totalSupply = 1_000_000_000 * 1e18;
 | 
			
		||||
    IERC20Token zrxToken;
 | 
			
		||||
 | 
			
		||||
    function setUp() public {
 | 
			
		||||
        vm.deal(owner, 1e20);
 | 
			
		||||
        vm.deal(user, 1e20);
 | 
			
		||||
 | 
			
		||||
        vm.prank(owner);
 | 
			
		||||
        bytes memory _bytecode = vm.getCode("./out/ZRXToken.sol/ZRXToken.json");
 | 
			
		||||
        address _address;
 | 
			
		||||
        assembly {
 | 
			
		||||
            _address := create(0, add(_bytecode, 0x20), mload(_bytecode))
 | 
			
		||||
        }
 | 
			
		||||
        vm.stopPrank();
 | 
			
		||||
        zrxToken = IERC20Token(address(_address));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function testShouldHave18Decimals() public {
 | 
			
		||||
        assertEq(zrxToken.decimals(), 18);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function testShouldHaveTotalSupplyOf1Billion() public {
 | 
			
		||||
        assertEq(zrxToken.totalSupply(), totalSupply);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function testShouldInitializeOwnerBalanceToTotalSupply() public {
 | 
			
		||||
        assertEq(zrxToken.balanceOf(owner), totalSupply);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function testShouldTransferBalanceCorrectly() public {
 | 
			
		||||
        vm.prank(owner);
 | 
			
		||||
        zrxToken.transfer(user, 100);
 | 
			
		||||
 | 
			
		||||
        assertEq(zrxToken.balanceOf(user), 100);
 | 
			
		||||
        assertEq(zrxToken.balanceOf(owner), totalSupply - 100);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function testShouldReturnTrueOnAZeroValueTransfer() public {
 | 
			
		||||
        vm.prank(owner);
 | 
			
		||||
        bool success = zrxToken.transfer(user, 0);
 | 
			
		||||
        assertTrue(success);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function testShouldReturnTrueOnAZeroValueTransferByUserWithZeroBalance() public {
 | 
			
		||||
        vm.prank(anotherUser);
 | 
			
		||||
        bool success = zrxToken.transfer(user, 0);
 | 
			
		||||
        assertTrue(success);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function testShouldReturnFalseIfSenderHasInsufficientBalance() public {
 | 
			
		||||
        vm.prank(owner);
 | 
			
		||||
        zrxToken.approve(user, totalSupply + 1);
 | 
			
		||||
        vm.stopPrank();
 | 
			
		||||
 | 
			
		||||
        bool success = zrxToken.transferFrom(owner, user, totalSupply + 1);
 | 
			
		||||
        assertEq(success, false);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function testShouldReturnFalseIfRecipientHasInsufficientAllowance() public {
 | 
			
		||||
        vm.prank(owner);
 | 
			
		||||
        zrxToken.approve(user, totalSupply - 1);
 | 
			
		||||
        vm.stopPrank();
 | 
			
		||||
 | 
			
		||||
        bool success = zrxToken.transferFrom(owner, user, totalSupply);
 | 
			
		||||
        assertEq(success, false);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function testShouldReturnTrueOnAZeroValueApprovedTransfer() public {
 | 
			
		||||
        vm.prank(user);
 | 
			
		||||
        bool success = zrxToken.transferFrom(owner, user, 0);
 | 
			
		||||
        assertEq(success, true);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function testShouldNotModifySenderAllowanceIfSetToUINT256Max() public {
 | 
			
		||||
        vm.prank(owner);
 | 
			
		||||
        zrxToken.approve(user, type(uint256).max);
 | 
			
		||||
        vm.stopPrank();
 | 
			
		||||
 | 
			
		||||
        zrxToken.transferFrom(owner, user, 100);
 | 
			
		||||
        assertEq(zrxToken.allowance(owner, user), type(uint256).max);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function testShouldTransferCorrectlyWhenSufficientAllowance() public {
 | 
			
		||||
        vm.prank(owner);
 | 
			
		||||
        zrxToken.approve(user, 1000 * 1e18);
 | 
			
		||||
        vm.stopPrank();
 | 
			
		||||
 | 
			
		||||
        vm.prank(user);
 | 
			
		||||
        zrxToken.transferFrom(owner, user, 100 * 1e18);
 | 
			
		||||
        assertEq(zrxToken.allowance(owner, user), 900 * 1e18);
 | 
			
		||||
        assertEq(zrxToken.balanceOf(user), 100 * 1e18);
 | 
			
		||||
        assertEq(zrxToken.balanceOf(owner), totalSupply - 100 * 1e18);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,51 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * -----------------------------------------------------------------------------
 | 
			
		||||
 * Warning: This file is auto-generated by contracts-gen. Don't edit manually.
 | 
			
		||||
 * -----------------------------------------------------------------------------
 | 
			
		||||
 */
 | 
			
		||||
import { ContractArtifact } from 'ethereum-types';
 | 
			
		||||
 | 
			
		||||
import * as DummyERC20Token from '../test/generated-artifacts/DummyERC20Token.json';
 | 
			
		||||
import * as DummyMultipleReturnERC20Token from '../test/generated-artifacts/DummyMultipleReturnERC20Token.json';
 | 
			
		||||
import * as DummyNoReturnERC20Token from '../test/generated-artifacts/DummyNoReturnERC20Token.json';
 | 
			
		||||
import * as ERC20Token from '../test/generated-artifacts/ERC20Token.json';
 | 
			
		||||
import * as IERC20Token from '../test/generated-artifacts/IERC20Token.json';
 | 
			
		||||
import * as IERC20TokenV06 from '../test/generated-artifacts/IERC20TokenV06.json';
 | 
			
		||||
import * as IERC20TokenV08 from '../test/generated-artifacts/IERC20TokenV08.json';
 | 
			
		||||
import * as IEtherToken from '../test/generated-artifacts/IEtherToken.json';
 | 
			
		||||
import * as IEtherTokenV06 from '../test/generated-artifacts/IEtherTokenV06.json';
 | 
			
		||||
import * as IEtherTokenV08 from '../test/generated-artifacts/IEtherTokenV08.json';
 | 
			
		||||
import * as LibERC20Token from '../test/generated-artifacts/LibERC20Token.json';
 | 
			
		||||
import * as LibERC20TokenV06 from '../test/generated-artifacts/LibERC20TokenV06.json';
 | 
			
		||||
import * as LibERC20TokenV08 from '../test/generated-artifacts/LibERC20TokenV08.json';
 | 
			
		||||
import * as MintableERC20Token from '../test/generated-artifacts/MintableERC20Token.json';
 | 
			
		||||
import * as TestLibERC20Token from '../test/generated-artifacts/TestLibERC20Token.json';
 | 
			
		||||
import * as TestLibERC20TokenTarget from '../test/generated-artifacts/TestLibERC20TokenTarget.json';
 | 
			
		||||
import * as UnlimitedAllowanceERC20Token from '../test/generated-artifacts/UnlimitedAllowanceERC20Token.json';
 | 
			
		||||
import * as UntransferrableDummyERC20Token from '../test/generated-artifacts/UntransferrableDummyERC20Token.json';
 | 
			
		||||
import * as WETH9 from '../test/generated-artifacts/WETH9.json';
 | 
			
		||||
import * as WETH9V06 from '../test/generated-artifacts/WETH9V06.json';
 | 
			
		||||
import * as ZRXToken from '../test/generated-artifacts/ZRXToken.json';
 | 
			
		||||
export const artifacts = {
 | 
			
		||||
    ERC20Token: ERC20Token as ContractArtifact,
 | 
			
		||||
    LibERC20Token: LibERC20Token as ContractArtifact,
 | 
			
		||||
    MintableERC20Token: MintableERC20Token as ContractArtifact,
 | 
			
		||||
    UnlimitedAllowanceERC20Token: UnlimitedAllowanceERC20Token as ContractArtifact,
 | 
			
		||||
    WETH9: WETH9 as ContractArtifact,
 | 
			
		||||
    ZRXToken: ZRXToken as any as ContractArtifact,
 | 
			
		||||
    IERC20Token: IERC20Token as ContractArtifact,
 | 
			
		||||
    IEtherToken: IEtherToken as ContractArtifact,
 | 
			
		||||
    IERC20TokenV06: IERC20TokenV06 as ContractArtifact,
 | 
			
		||||
    IEtherTokenV06: IEtherTokenV06 as ContractArtifact,
 | 
			
		||||
    LibERC20TokenV06: LibERC20TokenV06 as ContractArtifact,
 | 
			
		||||
    WETH9V06: WETH9V06 as ContractArtifact,
 | 
			
		||||
    IERC20TokenV08: IERC20TokenV08 as ContractArtifact,
 | 
			
		||||
    IEtherTokenV08: IEtherTokenV08 as ContractArtifact,
 | 
			
		||||
    LibERC20TokenV08: LibERC20TokenV08 as ContractArtifact,
 | 
			
		||||
    DummyERC20Token: DummyERC20Token as ContractArtifact,
 | 
			
		||||
    DummyMultipleReturnERC20Token: DummyMultipleReturnERC20Token as ContractArtifact,
 | 
			
		||||
    DummyNoReturnERC20Token: DummyNoReturnERC20Token as ContractArtifact,
 | 
			
		||||
    TestLibERC20Token: TestLibERC20Token as ContractArtifact,
 | 
			
		||||
    TestLibERC20TokenTarget: TestLibERC20TokenTarget as ContractArtifact,
 | 
			
		||||
    UntransferrableDummyERC20Token: UntransferrableDummyERC20Token as ContractArtifact,
 | 
			
		||||
};
 | 
			
		||||
@@ -1,335 +0,0 @@
 | 
			
		||||
import {
 | 
			
		||||
    blockchainTests,
 | 
			
		||||
    constants,
 | 
			
		||||
    expect,
 | 
			
		||||
    getRandomInteger,
 | 
			
		||||
    randomAddress,
 | 
			
		||||
    verifyEventsFromLogs,
 | 
			
		||||
} from '@0x/contracts-test-utils';
 | 
			
		||||
import { hexUtils, RawRevertError, StringRevertError } from '@0x/utils';
 | 
			
		||||
 | 
			
		||||
import { TestLibERC20TokenContract, TestLibERC20TokenTargetEvents } from './wrappers';
 | 
			
		||||
 | 
			
		||||
import { artifacts } from './artifacts';
 | 
			
		||||
 | 
			
		||||
blockchainTests('LibERC20Token', env => {
 | 
			
		||||
    let testContract: TestLibERC20TokenContract;
 | 
			
		||||
    const REVERT_STRING = 'WHOOPSIE';
 | 
			
		||||
    const ENCODED_REVERT = new StringRevertError(REVERT_STRING).encode();
 | 
			
		||||
    const ENCODED_TRUE = hexUtils.leftPad(1);
 | 
			
		||||
    const ENCODED_FALSE = hexUtils.leftPad(0);
 | 
			
		||||
    const ENCODED_TWO = hexUtils.leftPad(2);
 | 
			
		||||
    const ENCODED_SHORT_TRUE = hexUtils.leftPad(2, 31);
 | 
			
		||||
    const ENCODED_LONG_TRUE = hexUtils.leftPad(2, 33);
 | 
			
		||||
 | 
			
		||||
    before(async () => {
 | 
			
		||||
        testContract = await TestLibERC20TokenContract.deployFrom0xArtifactAsync(
 | 
			
		||||
            artifacts.TestLibERC20Token,
 | 
			
		||||
            env.provider,
 | 
			
		||||
            env.txDefaults,
 | 
			
		||||
            artifacts,
 | 
			
		||||
        );
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    describe('approve()', () => {
 | 
			
		||||
        it('calls the target with the correct arguments', async () => {
 | 
			
		||||
            const spender = randomAddress();
 | 
			
		||||
            const allowance = getRandomInteger(0, 100e18);
 | 
			
		||||
            const { logs } = await testContract
 | 
			
		||||
                .testApprove(false, ENCODED_REVERT, ENCODED_TRUE, spender, allowance)
 | 
			
		||||
                .awaitTransactionSuccessAsync();
 | 
			
		||||
            expect(logs).to.be.length(1);
 | 
			
		||||
            verifyEventsFromLogs(logs, [{ spender, allowance }], TestLibERC20TokenTargetEvents.ApproveCalled);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('succeeds if the target returns true', async () => {
 | 
			
		||||
            const spender = randomAddress();
 | 
			
		||||
            const allowance = getRandomInteger(0, 100e18);
 | 
			
		||||
            await testContract
 | 
			
		||||
                .testApprove(false, ENCODED_REVERT, ENCODED_TRUE, spender, allowance)
 | 
			
		||||
                .awaitTransactionSuccessAsync();
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('succeeds if the target returns nothing', async () => {
 | 
			
		||||
            const spender = randomAddress();
 | 
			
		||||
            const allowance = getRandomInteger(0, 100e18);
 | 
			
		||||
            await testContract
 | 
			
		||||
                .testApprove(false, ENCODED_REVERT, constants.NULL_BYTES, spender, allowance)
 | 
			
		||||
                .awaitTransactionSuccessAsync();
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('fails if the target returns false', async () => {
 | 
			
		||||
            const spender = randomAddress();
 | 
			
		||||
            const allowance = getRandomInteger(0, 100e18);
 | 
			
		||||
            const tx = testContract
 | 
			
		||||
                .testApprove(false, ENCODED_REVERT, ENCODED_FALSE, spender, allowance)
 | 
			
		||||
                .awaitTransactionSuccessAsync();
 | 
			
		||||
            const expectedError = new RawRevertError(ENCODED_FALSE);
 | 
			
		||||
            return expect(tx).to.revertWith(expectedError);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('fails if the target returns nonzero and not true', async () => {
 | 
			
		||||
            const spender = randomAddress();
 | 
			
		||||
            const allowance = getRandomInteger(0, 100e18);
 | 
			
		||||
            const tx = testContract
 | 
			
		||||
                .testApprove(false, ENCODED_REVERT, ENCODED_TWO, spender, allowance)
 | 
			
		||||
                .awaitTransactionSuccessAsync();
 | 
			
		||||
            const expectedError = new RawRevertError(ENCODED_TWO);
 | 
			
		||||
            return expect(tx).to.revertWith(expectedError);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('fails if the target returns less than 32 bytes', async () => {
 | 
			
		||||
            const spender = randomAddress();
 | 
			
		||||
            const allowance = getRandomInteger(0, 100e18);
 | 
			
		||||
            const tx = testContract
 | 
			
		||||
                .testApprove(false, ENCODED_REVERT, ENCODED_SHORT_TRUE, spender, allowance)
 | 
			
		||||
                .awaitTransactionSuccessAsync();
 | 
			
		||||
            const expectedError = new RawRevertError(ENCODED_SHORT_TRUE);
 | 
			
		||||
            return expect(tx).to.revertWith(expectedError);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('fails if the target returns greater than 32 bytes', async () => {
 | 
			
		||||
            const spender = randomAddress();
 | 
			
		||||
            const allowance = getRandomInteger(0, 100e18);
 | 
			
		||||
            const tx = testContract
 | 
			
		||||
                .testApprove(false, ENCODED_REVERT, ENCODED_LONG_TRUE, spender, allowance)
 | 
			
		||||
                .awaitTransactionSuccessAsync();
 | 
			
		||||
            const expectedError = new RawRevertError(ENCODED_LONG_TRUE);
 | 
			
		||||
            return expect(tx).to.revertWith(expectedError);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('fails if the target reverts', async () => {
 | 
			
		||||
            const spender = randomAddress();
 | 
			
		||||
            const allowance = getRandomInteger(0, 100e18);
 | 
			
		||||
            const tx = testContract
 | 
			
		||||
                .testApprove(true, ENCODED_REVERT, ENCODED_TRUE, spender, allowance)
 | 
			
		||||
                .awaitTransactionSuccessAsync();
 | 
			
		||||
            return expect(tx).to.revertWith(REVERT_STRING);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('fails if the target reverts with no data', async () => {
 | 
			
		||||
            const spender = randomAddress();
 | 
			
		||||
            const allowance = getRandomInteger(0, 100e18);
 | 
			
		||||
            const tx = testContract
 | 
			
		||||
                .testApprove(true, constants.NULL_BYTES, ENCODED_TRUE, spender, allowance)
 | 
			
		||||
                .awaitTransactionSuccessAsync();
 | 
			
		||||
            return expect(tx).to.be.rejectedWith('revert');
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    describe('transfer()', () => {
 | 
			
		||||
        it('calls the target with the correct arguments', async () => {
 | 
			
		||||
            const to = randomAddress();
 | 
			
		||||
            const amount = getRandomInteger(0, 100e18);
 | 
			
		||||
            const { logs } = await testContract
 | 
			
		||||
                .testTransfer(false, ENCODED_REVERT, ENCODED_TRUE, to, amount)
 | 
			
		||||
                .awaitTransactionSuccessAsync();
 | 
			
		||||
            expect(logs).to.be.length(1);
 | 
			
		||||
            verifyEventsFromLogs(logs, [{ to, amount }], TestLibERC20TokenTargetEvents.TransferCalled);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('succeeds if the target returns true', async () => {
 | 
			
		||||
            const to = randomAddress();
 | 
			
		||||
            const amount = getRandomInteger(0, 100e18);
 | 
			
		||||
            await testContract
 | 
			
		||||
                .testTransfer(false, ENCODED_REVERT, ENCODED_TRUE, to, amount)
 | 
			
		||||
                .awaitTransactionSuccessAsync();
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('succeeds if the target returns nothing', async () => {
 | 
			
		||||
            const to = randomAddress();
 | 
			
		||||
            const amount = getRandomInteger(0, 100e18);
 | 
			
		||||
            await testContract
 | 
			
		||||
                .testTransfer(false, ENCODED_REVERT, constants.NULL_BYTES, to, amount)
 | 
			
		||||
                .awaitTransactionSuccessAsync();
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('fails if the target returns false', async () => {
 | 
			
		||||
            const to = randomAddress();
 | 
			
		||||
            const amount = getRandomInteger(0, 100e18);
 | 
			
		||||
            const tx = testContract
 | 
			
		||||
                .testTransfer(false, ENCODED_REVERT, ENCODED_FALSE, to, amount)
 | 
			
		||||
                .awaitTransactionSuccessAsync();
 | 
			
		||||
            const expectedError = new RawRevertError(ENCODED_FALSE);
 | 
			
		||||
            return expect(tx).to.revertWith(expectedError);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('fails if the target returns nonzero and not true', async () => {
 | 
			
		||||
            const to = randomAddress();
 | 
			
		||||
            const amount = getRandomInteger(0, 100e18);
 | 
			
		||||
            const tx = testContract
 | 
			
		||||
                .testTransfer(false, ENCODED_REVERT, ENCODED_TWO, to, amount)
 | 
			
		||||
                .awaitTransactionSuccessAsync();
 | 
			
		||||
            const expectedError = new RawRevertError(ENCODED_TWO);
 | 
			
		||||
            return expect(tx).to.revertWith(expectedError);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('fails if the target returns less than 32 bytes', async () => {
 | 
			
		||||
            const to = randomAddress();
 | 
			
		||||
            const amount = getRandomInteger(0, 100e18);
 | 
			
		||||
            const tx = testContract
 | 
			
		||||
                .testTransfer(false, ENCODED_REVERT, ENCODED_SHORT_TRUE, to, amount)
 | 
			
		||||
                .awaitTransactionSuccessAsync();
 | 
			
		||||
            const expectedError = new RawRevertError(ENCODED_SHORT_TRUE);
 | 
			
		||||
            return expect(tx).to.revertWith(expectedError);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('fails if the target returns greater than 32 bytes', async () => {
 | 
			
		||||
            const to = randomAddress();
 | 
			
		||||
            const amount = getRandomInteger(0, 100e18);
 | 
			
		||||
            const tx = testContract
 | 
			
		||||
                .testTransfer(false, ENCODED_REVERT, ENCODED_LONG_TRUE, to, amount)
 | 
			
		||||
                .awaitTransactionSuccessAsync();
 | 
			
		||||
            const expectedError = new RawRevertError(ENCODED_LONG_TRUE);
 | 
			
		||||
            return expect(tx).to.revertWith(expectedError);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('fails if the target reverts', async () => {
 | 
			
		||||
            const to = randomAddress();
 | 
			
		||||
            const amount = getRandomInteger(0, 100e18);
 | 
			
		||||
            const tx = testContract
 | 
			
		||||
                .testTransfer(true, ENCODED_REVERT, ENCODED_TRUE, to, amount)
 | 
			
		||||
                .awaitTransactionSuccessAsync();
 | 
			
		||||
            return expect(tx).to.revertWith(REVERT_STRING);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('fails if the target reverts with no data', async () => {
 | 
			
		||||
            const to = randomAddress();
 | 
			
		||||
            const amount = getRandomInteger(0, 100e18);
 | 
			
		||||
            const tx = testContract
 | 
			
		||||
                .testTransfer(true, constants.NULL_BYTES, ENCODED_TRUE, to, amount)
 | 
			
		||||
                .awaitTransactionSuccessAsync();
 | 
			
		||||
            return expect(tx).to.be.rejectedWith('revert');
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    describe('transferFrom()', () => {
 | 
			
		||||
        it('calls the target with the correct arguments', async () => {
 | 
			
		||||
            const owner = randomAddress();
 | 
			
		||||
            const to = randomAddress();
 | 
			
		||||
            const amount = getRandomInteger(0, 100e18);
 | 
			
		||||
            const { logs } = await testContract
 | 
			
		||||
                .testTransferFrom(false, ENCODED_REVERT, ENCODED_TRUE, owner, to, amount)
 | 
			
		||||
                .awaitTransactionSuccessAsync();
 | 
			
		||||
            expect(logs).to.be.length(1);
 | 
			
		||||
            verifyEventsFromLogs(logs, [{ from: owner, to, amount }], TestLibERC20TokenTargetEvents.TransferFromCalled);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('succeeds if the target returns true', async () => {
 | 
			
		||||
            const owner = randomAddress();
 | 
			
		||||
            const to = randomAddress();
 | 
			
		||||
            const amount = getRandomInteger(0, 100e18);
 | 
			
		||||
            await testContract
 | 
			
		||||
                .testTransferFrom(false, ENCODED_REVERT, ENCODED_TRUE, owner, to, amount)
 | 
			
		||||
                .awaitTransactionSuccessAsync();
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('succeeds if the target returns nothing', async () => {
 | 
			
		||||
            const owner = randomAddress();
 | 
			
		||||
            const to = randomAddress();
 | 
			
		||||
            const amount = getRandomInteger(0, 100e18);
 | 
			
		||||
            await testContract
 | 
			
		||||
                .testTransferFrom(false, ENCODED_REVERT, constants.NULL_BYTES, owner, to, amount)
 | 
			
		||||
                .awaitTransactionSuccessAsync();
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('fails if the target returns false', async () => {
 | 
			
		||||
            const owner = randomAddress();
 | 
			
		||||
            const to = randomAddress();
 | 
			
		||||
            const amount = getRandomInteger(0, 100e18);
 | 
			
		||||
            const tx = testContract
 | 
			
		||||
                .testTransferFrom(false, ENCODED_REVERT, ENCODED_FALSE, owner, to, amount)
 | 
			
		||||
                .awaitTransactionSuccessAsync();
 | 
			
		||||
            const expectedError = new RawRevertError(ENCODED_FALSE);
 | 
			
		||||
            return expect(tx).to.revertWith(expectedError);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('fails if the target returns nonzero and not true', async () => {
 | 
			
		||||
            const owner = randomAddress();
 | 
			
		||||
            const to = randomAddress();
 | 
			
		||||
            const amount = getRandomInteger(0, 100e18);
 | 
			
		||||
            const tx = testContract
 | 
			
		||||
                .testTransferFrom(false, ENCODED_REVERT, ENCODED_TWO, owner, to, amount)
 | 
			
		||||
                .awaitTransactionSuccessAsync();
 | 
			
		||||
            const expectedError = new RawRevertError(ENCODED_TWO);
 | 
			
		||||
            return expect(tx).to.revertWith(expectedError);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('fails if the target returns less than 32 bytes', async () => {
 | 
			
		||||
            const owner = randomAddress();
 | 
			
		||||
            const to = randomAddress();
 | 
			
		||||
            const amount = getRandomInteger(0, 100e18);
 | 
			
		||||
            const tx = testContract
 | 
			
		||||
                .testTransferFrom(false, ENCODED_REVERT, ENCODED_SHORT_TRUE, owner, to, amount)
 | 
			
		||||
                .awaitTransactionSuccessAsync();
 | 
			
		||||
            const expectedError = new RawRevertError(ENCODED_SHORT_TRUE);
 | 
			
		||||
            return expect(tx).to.revertWith(expectedError);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('fails if the target returns greater than 32 bytes', async () => {
 | 
			
		||||
            const owner = randomAddress();
 | 
			
		||||
            const to = randomAddress();
 | 
			
		||||
            const amount = getRandomInteger(0, 100e18);
 | 
			
		||||
            const tx = testContract
 | 
			
		||||
                .testTransferFrom(false, ENCODED_REVERT, ENCODED_LONG_TRUE, owner, to, amount)
 | 
			
		||||
                .awaitTransactionSuccessAsync();
 | 
			
		||||
            const expectedError = new RawRevertError(ENCODED_LONG_TRUE);
 | 
			
		||||
            return expect(tx).to.revertWith(expectedError);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('fails if the target reverts', async () => {
 | 
			
		||||
            const owner = randomAddress();
 | 
			
		||||
            const to = randomAddress();
 | 
			
		||||
            const amount = getRandomInteger(0, 100e18);
 | 
			
		||||
            const tx = testContract
 | 
			
		||||
                .testTransferFrom(true, ENCODED_REVERT, ENCODED_TRUE, owner, to, amount)
 | 
			
		||||
                .awaitTransactionSuccessAsync();
 | 
			
		||||
            return expect(tx).to.revertWith(REVERT_STRING);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('fails if the target reverts with no data', async () => {
 | 
			
		||||
            const owner = randomAddress();
 | 
			
		||||
            const to = randomAddress();
 | 
			
		||||
            const amount = getRandomInteger(0, 100e18);
 | 
			
		||||
            const tx = testContract
 | 
			
		||||
                .testTransferFrom(true, constants.NULL_BYTES, ENCODED_TRUE, owner, to, amount)
 | 
			
		||||
                .awaitTransactionSuccessAsync();
 | 
			
		||||
            return expect(tx).to.be.rejectedWith('revert');
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    describe('decimals()', () => {
 | 
			
		||||
        const DEFAULT_DECIMALS = 18;
 | 
			
		||||
        const ENCODED_ZERO = hexUtils.leftPad(0);
 | 
			
		||||
        const ENCODED_SHORT_ZERO = hexUtils.leftPad(0, 31);
 | 
			
		||||
        const ENCODED_LONG_ZERO = hexUtils.leftPad(0, 33);
 | 
			
		||||
        const randomDecimals = () => Math.floor(Math.random() * 256) + 1;
 | 
			
		||||
 | 
			
		||||
        it('returns the number of decimals defined by the token', async () => {
 | 
			
		||||
            const decimals = randomDecimals();
 | 
			
		||||
            const encodedDecimals = hexUtils.leftPad(decimals);
 | 
			
		||||
            const result = await testContract.testDecimals(false, ENCODED_REVERT, encodedDecimals).callAsync();
 | 
			
		||||
            return expect(result).to.bignumber.eq(decimals);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('returns 0 if the token returns 0', async () => {
 | 
			
		||||
            const result = await testContract.testDecimals(false, ENCODED_REVERT, ENCODED_ZERO).callAsync();
 | 
			
		||||
            return expect(result).to.bignumber.eq(0);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('returns 18 if the token returns less than 32 bytes', async () => {
 | 
			
		||||
            const result = await testContract.testDecimals(false, ENCODED_REVERT, ENCODED_SHORT_ZERO).callAsync();
 | 
			
		||||
            return expect(result).to.bignumber.eq(DEFAULT_DECIMALS);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('returns 18 if the token returns greater than 32 bytes', async () => {
 | 
			
		||||
            const result = await testContract.testDecimals(false, ENCODED_REVERT, ENCODED_LONG_ZERO).callAsync();
 | 
			
		||||
            return expect(result).to.bignumber.eq(DEFAULT_DECIMALS);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('returns 18 if the token reverts', async () => {
 | 
			
		||||
            const result = await testContract.testDecimals(true, ENCODED_REVERT, ENCODED_ZERO).callAsync();
 | 
			
		||||
            return expect(result).to.bignumber.eq(DEFAULT_DECIMALS);
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
});
 | 
			
		||||
@@ -1,187 +0,0 @@
 | 
			
		||||
import { chaiSetup, constants, provider, txDefaults, web3Wrapper } from '@0x/contracts-test-utils';
 | 
			
		||||
import { BlockchainLifecycle } from '@0x/dev-utils';
 | 
			
		||||
import { RevertReason } from '@0x/types';
 | 
			
		||||
import { BigNumber } from '@0x/utils';
 | 
			
		||||
import * as chai from 'chai';
 | 
			
		||||
 | 
			
		||||
import { DummyERC20TokenContract } from './wrappers';
 | 
			
		||||
 | 
			
		||||
import { artifacts } from './artifacts';
 | 
			
		||||
 | 
			
		||||
chaiSetup.configure();
 | 
			
		||||
const expect = chai.expect;
 | 
			
		||||
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
 | 
			
		||||
 | 
			
		||||
describe('UnlimitedAllowanceToken', () => {
 | 
			
		||||
    let owner: string;
 | 
			
		||||
    let spender: string;
 | 
			
		||||
    const MAX_MINT_VALUE = new BigNumber(10000000000000000000000);
 | 
			
		||||
    let token: DummyERC20TokenContract;
 | 
			
		||||
 | 
			
		||||
    before(async () => {
 | 
			
		||||
        await blockchainLifecycle.startAsync();
 | 
			
		||||
    });
 | 
			
		||||
    after(async () => {
 | 
			
		||||
        await blockchainLifecycle.revertAsync();
 | 
			
		||||
    });
 | 
			
		||||
    before(async () => {
 | 
			
		||||
        const accounts = await web3Wrapper.getAvailableAddressesAsync();
 | 
			
		||||
        owner = accounts[0];
 | 
			
		||||
        spender = accounts[1];
 | 
			
		||||
        token = await DummyERC20TokenContract.deployFrom0xArtifactAsync(
 | 
			
		||||
            artifacts.DummyERC20Token,
 | 
			
		||||
            provider,
 | 
			
		||||
            txDefaults,
 | 
			
		||||
            artifacts,
 | 
			
		||||
            constants.DUMMY_TOKEN_NAME,
 | 
			
		||||
            constants.DUMMY_TOKEN_SYMBOL,
 | 
			
		||||
            constants.DUMMY_TOKEN_DECIMALS,
 | 
			
		||||
            constants.DUMMY_TOKEN_TOTAL_SUPPLY,
 | 
			
		||||
        );
 | 
			
		||||
        await web3Wrapper.awaitTransactionSuccessAsync(
 | 
			
		||||
            await token.mint(MAX_MINT_VALUE).sendTransactionAsync({ from: owner }),
 | 
			
		||||
            constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
        );
 | 
			
		||||
    });
 | 
			
		||||
    beforeEach(async () => {
 | 
			
		||||
        await blockchainLifecycle.startAsync();
 | 
			
		||||
    });
 | 
			
		||||
    afterEach(async () => {
 | 
			
		||||
        await blockchainLifecycle.revertAsync();
 | 
			
		||||
    });
 | 
			
		||||
    describe('transfer', () => {
 | 
			
		||||
        it('should revert if owner has insufficient balance', async () => {
 | 
			
		||||
            const ownerBalance = await token.balanceOf(owner).callAsync();
 | 
			
		||||
            const amountToTransfer = ownerBalance.plus(1);
 | 
			
		||||
            return expect(token.transfer(spender, amountToTransfer).callAsync({ from: owner })).to.revertWith(
 | 
			
		||||
                RevertReason.Erc20InsufficientBalance,
 | 
			
		||||
            );
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should transfer balance from sender to receiver', async () => {
 | 
			
		||||
            const receiver = spender;
 | 
			
		||||
            const initOwnerBalance = await token.balanceOf(owner).callAsync();
 | 
			
		||||
            const amountToTransfer = new BigNumber(1);
 | 
			
		||||
            await web3Wrapper.awaitTransactionSuccessAsync(
 | 
			
		||||
                await token.transfer(receiver, amountToTransfer).sendTransactionAsync({ from: owner }),
 | 
			
		||||
                constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
            );
 | 
			
		||||
            const finalOwnerBalance = await token.balanceOf(owner).callAsync();
 | 
			
		||||
            const finalReceiverBalance = await token.balanceOf(receiver).callAsync();
 | 
			
		||||
 | 
			
		||||
            const expectedFinalOwnerBalance = initOwnerBalance.minus(amountToTransfer);
 | 
			
		||||
            const expectedFinalReceiverBalance = amountToTransfer;
 | 
			
		||||
            expect(finalOwnerBalance).to.be.bignumber.equal(expectedFinalOwnerBalance);
 | 
			
		||||
            expect(finalReceiverBalance).to.be.bignumber.equal(expectedFinalReceiverBalance);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should return true on a 0 value transfer', async () => {
 | 
			
		||||
            const didReturnTrue = await token.transfer(spender, new BigNumber(0)).callAsync({
 | 
			
		||||
                from: owner,
 | 
			
		||||
            });
 | 
			
		||||
            expect(didReturnTrue).to.be.true();
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    describe('transferFrom', () => {
 | 
			
		||||
        it('should revert if owner has insufficient balance', async () => {
 | 
			
		||||
            const ownerBalance = await token.balanceOf(owner).callAsync();
 | 
			
		||||
            const amountToTransfer = ownerBalance.plus(1);
 | 
			
		||||
            await web3Wrapper.awaitTransactionSuccessAsync(
 | 
			
		||||
                await token.approve(spender, amountToTransfer).sendTransactionAsync({ from: owner }),
 | 
			
		||||
                constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
            );
 | 
			
		||||
            return expect(
 | 
			
		||||
                token.transferFrom(owner, spender, amountToTransfer).callAsync({
 | 
			
		||||
                    from: spender,
 | 
			
		||||
                }),
 | 
			
		||||
            ).to.revertWith(RevertReason.Erc20InsufficientBalance);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should revert if spender has insufficient allowance', async () => {
 | 
			
		||||
            const ownerBalance = await token.balanceOf(owner).callAsync();
 | 
			
		||||
            const amountToTransfer = ownerBalance;
 | 
			
		||||
 | 
			
		||||
            const spenderAllowance = await token.allowance(owner, spender).callAsync();
 | 
			
		||||
            const isSpenderAllowanceInsufficient = spenderAllowance.comparedTo(amountToTransfer) < 0;
 | 
			
		||||
            expect(isSpenderAllowanceInsufficient).to.be.true();
 | 
			
		||||
 | 
			
		||||
            return expect(
 | 
			
		||||
                token.transferFrom(owner, spender, amountToTransfer).callAsync({
 | 
			
		||||
                    from: spender,
 | 
			
		||||
                }),
 | 
			
		||||
            ).to.revertWith(RevertReason.Erc20InsufficientAllowance);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should return true on a 0 value transfer', async () => {
 | 
			
		||||
            const amountToTransfer = new BigNumber(0);
 | 
			
		||||
            const didReturnTrue = await token.transferFrom(owner, spender, amountToTransfer).callAsync({
 | 
			
		||||
                from: spender,
 | 
			
		||||
            });
 | 
			
		||||
            expect(didReturnTrue).to.be.true();
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should not modify spender allowance if spender allowance is 2^256 - 1', async () => {
 | 
			
		||||
            const initOwnerBalance = await token.balanceOf(owner).callAsync();
 | 
			
		||||
            const amountToTransfer = initOwnerBalance;
 | 
			
		||||
            const initSpenderAllowance = constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS;
 | 
			
		||||
            await web3Wrapper.awaitTransactionSuccessAsync(
 | 
			
		||||
                await token.approve(spender, initSpenderAllowance).sendTransactionAsync({ from: owner }),
 | 
			
		||||
                constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
            );
 | 
			
		||||
            await web3Wrapper.awaitTransactionSuccessAsync(
 | 
			
		||||
                await token.transferFrom(owner, spender, amountToTransfer).sendTransactionAsync({
 | 
			
		||||
                    from: spender,
 | 
			
		||||
                    gas: constants.MAX_TOKEN_TRANSFERFROM_GAS,
 | 
			
		||||
                }),
 | 
			
		||||
                constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
            const newSpenderAllowance = await token.allowance(owner, spender).callAsync();
 | 
			
		||||
            expect(initSpenderAllowance).to.be.bignumber.equal(newSpenderAllowance);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should transfer the correct balances if spender has sufficient allowance', async () => {
 | 
			
		||||
            const initOwnerBalance = await token.balanceOf(owner).callAsync();
 | 
			
		||||
            const amountToTransfer = initOwnerBalance;
 | 
			
		||||
            const initSpenderAllowance = initOwnerBalance;
 | 
			
		||||
            await web3Wrapper.awaitTransactionSuccessAsync(
 | 
			
		||||
                await token.approve(spender, initSpenderAllowance).sendTransactionAsync({ from: owner }),
 | 
			
		||||
                constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
            );
 | 
			
		||||
            await web3Wrapper.awaitTransactionSuccessAsync(
 | 
			
		||||
                await token.transferFrom(owner, spender, amountToTransfer).sendTransactionAsync({
 | 
			
		||||
                    from: spender,
 | 
			
		||||
                    gas: constants.MAX_TOKEN_TRANSFERFROM_GAS,
 | 
			
		||||
                }),
 | 
			
		||||
                constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
            const newOwnerBalance = await token.balanceOf(owner).callAsync();
 | 
			
		||||
            const newSpenderBalance = await token.balanceOf(spender).callAsync();
 | 
			
		||||
 | 
			
		||||
            expect(newOwnerBalance).to.be.bignumber.equal(0);
 | 
			
		||||
            expect(newSpenderBalance).to.be.bignumber.equal(initOwnerBalance);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should modify allowance if spender has sufficient allowance less than 2^256 - 1', async () => {
 | 
			
		||||
            const initOwnerBalance = await token.balanceOf(owner).callAsync();
 | 
			
		||||
            const amountToTransfer = initOwnerBalance;
 | 
			
		||||
            const initSpenderAllowance = initOwnerBalance;
 | 
			
		||||
            await web3Wrapper.awaitTransactionSuccessAsync(
 | 
			
		||||
                await token.approve(spender, initSpenderAllowance).sendTransactionAsync({ from: owner }),
 | 
			
		||||
                constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
            );
 | 
			
		||||
            await web3Wrapper.awaitTransactionSuccessAsync(
 | 
			
		||||
                await token.transferFrom(owner, spender, amountToTransfer).sendTransactionAsync({
 | 
			
		||||
                    from: spender,
 | 
			
		||||
                    gas: constants.MAX_TOKEN_TRANSFERFROM_GAS,
 | 
			
		||||
                }),
 | 
			
		||||
                constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
            const newSpenderAllowance = await token.allowance(owner, spender).callAsync();
 | 
			
		||||
            expect(newSpenderAllowance).to.be.bignumber.equal(0);
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
});
 | 
			
		||||
@@ -1,149 +0,0 @@
 | 
			
		||||
import {
 | 
			
		||||
    chaiSetup,
 | 
			
		||||
    constants,
 | 
			
		||||
    expectInsufficientFundsAsync,
 | 
			
		||||
    expectTransactionFailedWithoutReasonAsync,
 | 
			
		||||
    provider,
 | 
			
		||||
    txDefaults,
 | 
			
		||||
    web3Wrapper,
 | 
			
		||||
} from '@0x/contracts-test-utils';
 | 
			
		||||
import { BlockchainLifecycle } from '@0x/dev-utils';
 | 
			
		||||
import { BigNumber } from '@0x/utils';
 | 
			
		||||
import { Web3Wrapper } from '@0x/web3-wrapper';
 | 
			
		||||
import * as chai from 'chai';
 | 
			
		||||
 | 
			
		||||
import { WETH9Contract } from './wrappers';
 | 
			
		||||
 | 
			
		||||
import { artifacts } from './artifacts';
 | 
			
		||||
 | 
			
		||||
chaiSetup.configure();
 | 
			
		||||
const expect = chai.expect;
 | 
			
		||||
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
 | 
			
		||||
 | 
			
		||||
describe('EtherToken', () => {
 | 
			
		||||
    let account: string;
 | 
			
		||||
    const gasPrice = new BigNumber(constants.DEFAULT_GAS_PRICE);
 | 
			
		||||
    let etherToken: WETH9Contract;
 | 
			
		||||
 | 
			
		||||
    before(async () => {
 | 
			
		||||
        await blockchainLifecycle.startAsync();
 | 
			
		||||
    });
 | 
			
		||||
    after(async () => {
 | 
			
		||||
        await blockchainLifecycle.revertAsync();
 | 
			
		||||
    });
 | 
			
		||||
    before(async () => {
 | 
			
		||||
        const accounts = await web3Wrapper.getAvailableAddressesAsync();
 | 
			
		||||
        account = accounts[0];
 | 
			
		||||
 | 
			
		||||
        etherToken = await WETH9Contract.deployFrom0xArtifactAsync(
 | 
			
		||||
            artifacts.WETH9,
 | 
			
		||||
            provider,
 | 
			
		||||
            {
 | 
			
		||||
                ...txDefaults,
 | 
			
		||||
                gasPrice,
 | 
			
		||||
            },
 | 
			
		||||
            artifacts,
 | 
			
		||||
        );
 | 
			
		||||
    });
 | 
			
		||||
    beforeEach(async () => {
 | 
			
		||||
        await blockchainLifecycle.startAsync();
 | 
			
		||||
    });
 | 
			
		||||
    afterEach(async () => {
 | 
			
		||||
        await blockchainLifecycle.revertAsync();
 | 
			
		||||
    });
 | 
			
		||||
    describe('deposit', () => {
 | 
			
		||||
        it('should revert if caller attempts to deposit more Ether than caller balance', async () => {
 | 
			
		||||
            const initEthBalance = await web3Wrapper.getBalanceInWeiAsync(account);
 | 
			
		||||
            const ethToDeposit = initEthBalance.plus(1);
 | 
			
		||||
 | 
			
		||||
            return expectInsufficientFundsAsync(etherToken.deposit().sendTransactionAsync({ value: ethToDeposit }));
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should convert deposited Ether to wrapped Ether tokens', async () => {
 | 
			
		||||
            const initEthBalance = await web3Wrapper.getBalanceInWeiAsync(account);
 | 
			
		||||
            const initEthTokenBalance = await etherToken.balanceOf(account).callAsync();
 | 
			
		||||
 | 
			
		||||
            const ethToDeposit = new BigNumber(Web3Wrapper.toWei(new BigNumber(1)));
 | 
			
		||||
 | 
			
		||||
            const txHash = await etherToken.deposit().sendTransactionAsync({ value: ethToDeposit });
 | 
			
		||||
            const receipt = await web3Wrapper.awaitTransactionSuccessAsync(
 | 
			
		||||
                txHash,
 | 
			
		||||
                constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
            const ethSpentOnGas = gasPrice.times(receipt.gasUsed);
 | 
			
		||||
            const finalEthBalance = await web3Wrapper.getBalanceInWeiAsync(account);
 | 
			
		||||
            const finalEthTokenBalance = await etherToken.balanceOf(account).callAsync();
 | 
			
		||||
 | 
			
		||||
            expect(finalEthBalance).to.be.bignumber.equal(initEthBalance.minus(ethToDeposit.plus(ethSpentOnGas)));
 | 
			
		||||
            expect(finalEthTokenBalance).to.be.bignumber.equal(initEthTokenBalance.plus(ethToDeposit));
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    describe('withdraw', () => {
 | 
			
		||||
        it('should revert if caller attempts to withdraw greater than caller balance', async () => {
 | 
			
		||||
            const initEthTokenBalance = await etherToken.balanceOf(account).callAsync();
 | 
			
		||||
            const ethTokensToWithdraw = initEthTokenBalance.plus(1);
 | 
			
		||||
 | 
			
		||||
            return expectTransactionFailedWithoutReasonAsync(
 | 
			
		||||
                etherToken.withdraw(ethTokensToWithdraw).sendTransactionAsync(),
 | 
			
		||||
            );
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should convert ether tokens to ether with sufficient balance', async () => {
 | 
			
		||||
            const ethToDeposit = new BigNumber(Web3Wrapper.toWei(new BigNumber(1)));
 | 
			
		||||
            await web3Wrapper.awaitTransactionSuccessAsync(
 | 
			
		||||
                await etherToken.deposit().sendTransactionAsync({ value: ethToDeposit }),
 | 
			
		||||
                constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
            );
 | 
			
		||||
            const initEthTokenBalance = await etherToken.balanceOf(account).callAsync();
 | 
			
		||||
            const initEthBalance = await web3Wrapper.getBalanceInWeiAsync(account);
 | 
			
		||||
            const ethTokensToWithdraw = initEthTokenBalance;
 | 
			
		||||
            expect(ethTokensToWithdraw).to.not.be.bignumber.equal(0);
 | 
			
		||||
            const txHash = await etherToken.withdraw(ethTokensToWithdraw).sendTransactionAsync({
 | 
			
		||||
                gas: constants.MAX_ETHERTOKEN_WITHDRAW_GAS,
 | 
			
		||||
            });
 | 
			
		||||
            const receipt = await web3Wrapper.awaitTransactionSuccessAsync(
 | 
			
		||||
                txHash,
 | 
			
		||||
                constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
            const ethSpentOnGas = gasPrice.times(receipt.gasUsed);
 | 
			
		||||
            const finalEthBalance = await web3Wrapper.getBalanceInWeiAsync(account);
 | 
			
		||||
            const finalEthTokenBalance = await etherToken.balanceOf(account).callAsync();
 | 
			
		||||
 | 
			
		||||
            expect(finalEthBalance).to.be.bignumber.equal(
 | 
			
		||||
                initEthBalance.plus(ethTokensToWithdraw.minus(ethSpentOnGas)),
 | 
			
		||||
            );
 | 
			
		||||
            expect(finalEthTokenBalance).to.be.bignumber.equal(initEthTokenBalance.minus(ethTokensToWithdraw));
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    describe('fallback', () => {
 | 
			
		||||
        it('should convert sent ether to ether tokens', async () => {
 | 
			
		||||
            const initEthBalance = await web3Wrapper.getBalanceInWeiAsync(account);
 | 
			
		||||
            const initEthTokenBalance = await etherToken.balanceOf(account).callAsync();
 | 
			
		||||
 | 
			
		||||
            const ethToDeposit = Web3Wrapper.toBaseUnitAmount(new BigNumber(1), 18);
 | 
			
		||||
 | 
			
		||||
            const txHash = await web3Wrapper.sendTransactionAsync({
 | 
			
		||||
                from: account,
 | 
			
		||||
                to: etherToken.address,
 | 
			
		||||
                value: ethToDeposit,
 | 
			
		||||
                gasPrice,
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            const receipt = await web3Wrapper.awaitTransactionSuccessAsync(
 | 
			
		||||
                txHash,
 | 
			
		||||
                constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
            const ethSpentOnGas = gasPrice.times(receipt.gasUsed);
 | 
			
		||||
            const finalEthBalance = await web3Wrapper.getBalanceInWeiAsync(account);
 | 
			
		||||
            const finalEthTokenBalance = await etherToken.balanceOf(account).callAsync();
 | 
			
		||||
 | 
			
		||||
            expect(finalEthBalance).to.be.bignumber.equal(initEthBalance.minus(ethToDeposit.plus(ethSpentOnGas)));
 | 
			
		||||
            expect(finalEthTokenBalance).to.be.bignumber.equal(initEthTokenBalance.plus(ethToDeposit));
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
});
 | 
			
		||||
@@ -1,26 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 * -----------------------------------------------------------------------------
 | 
			
		||||
 * Warning: This file is auto-generated by contracts-gen. Don't edit manually.
 | 
			
		||||
 * -----------------------------------------------------------------------------
 | 
			
		||||
 */
 | 
			
		||||
export * from '../test/generated-wrappers/dummy_erc20_token';
 | 
			
		||||
export * from '../test/generated-wrappers/dummy_multiple_return_erc20_token';
 | 
			
		||||
export * from '../test/generated-wrappers/dummy_no_return_erc20_token';
 | 
			
		||||
export * from '../test/generated-wrappers/erc20_token';
 | 
			
		||||
export * from '../test/generated-wrappers/i_erc20_token';
 | 
			
		||||
export * from '../test/generated-wrappers/i_erc20_token_v06';
 | 
			
		||||
export * from '../test/generated-wrappers/i_erc20_token_v08';
 | 
			
		||||
export * from '../test/generated-wrappers/i_ether_token';
 | 
			
		||||
export * from '../test/generated-wrappers/i_ether_token_v06';
 | 
			
		||||
export * from '../test/generated-wrappers/i_ether_token_v08';
 | 
			
		||||
export * from '../test/generated-wrappers/lib_erc20_token';
 | 
			
		||||
export * from '../test/generated-wrappers/lib_erc20_token_v06';
 | 
			
		||||
export * from '../test/generated-wrappers/lib_erc20_token_v08';
 | 
			
		||||
export * from '../test/generated-wrappers/mintable_erc20_token';
 | 
			
		||||
export * from '../test/generated-wrappers/test_lib_erc20_token';
 | 
			
		||||
export * from '../test/generated-wrappers/test_lib_erc20_token_target';
 | 
			
		||||
export * from '../test/generated-wrappers/unlimited_allowance_erc20_token';
 | 
			
		||||
export * from '../test/generated-wrappers/untransferrable_dummy_erc20_token';
 | 
			
		||||
export * from '../test/generated-wrappers/weth9';
 | 
			
		||||
export * from '../test/generated-wrappers/weth9v06';
 | 
			
		||||
export * from '../test/generated-wrappers/zrx_token';
 | 
			
		||||
@@ -1,210 +0,0 @@
 | 
			
		||||
import { chaiSetup, constants, provider, txDefaults, web3Wrapper } from '@0x/contracts-test-utils';
 | 
			
		||||
import { BlockchainLifecycle } from '@0x/dev-utils';
 | 
			
		||||
import { BigNumber } from '@0x/utils';
 | 
			
		||||
import { Web3Wrapper } from '@0x/web3-wrapper';
 | 
			
		||||
import * as chai from 'chai';
 | 
			
		||||
 | 
			
		||||
import { ZRXTokenContract } from './wrappers';
 | 
			
		||||
 | 
			
		||||
import { artifacts } from './artifacts';
 | 
			
		||||
 | 
			
		||||
chaiSetup.configure();
 | 
			
		||||
const expect = chai.expect;
 | 
			
		||||
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
 | 
			
		||||
 | 
			
		||||
describe('ZRXToken', () => {
 | 
			
		||||
    let owner: string;
 | 
			
		||||
    let spender: string;
 | 
			
		||||
    let MAX_UINT: BigNumber;
 | 
			
		||||
    let zrxToken: ZRXTokenContract;
 | 
			
		||||
 | 
			
		||||
    before(async () => {
 | 
			
		||||
        await blockchainLifecycle.startAsync();
 | 
			
		||||
    });
 | 
			
		||||
    after(async () => {
 | 
			
		||||
        await blockchainLifecycle.revertAsync();
 | 
			
		||||
    });
 | 
			
		||||
    before(async () => {
 | 
			
		||||
        const accounts = await web3Wrapper.getAvailableAddressesAsync();
 | 
			
		||||
        owner = accounts[0];
 | 
			
		||||
        spender = accounts[1];
 | 
			
		||||
        zrxToken = await ZRXTokenContract.deployFrom0xArtifactAsync(
 | 
			
		||||
            artifacts.ZRXToken,
 | 
			
		||||
            provider,
 | 
			
		||||
            txDefaults,
 | 
			
		||||
            artifacts,
 | 
			
		||||
        );
 | 
			
		||||
        MAX_UINT = constants.UNLIMITED_ALLOWANCE_IN_BASE_UNITS;
 | 
			
		||||
    });
 | 
			
		||||
    beforeEach(async () => {
 | 
			
		||||
        await blockchainLifecycle.startAsync();
 | 
			
		||||
    });
 | 
			
		||||
    afterEach(async () => {
 | 
			
		||||
        await blockchainLifecycle.revertAsync();
 | 
			
		||||
    });
 | 
			
		||||
    describe('constants', () => {
 | 
			
		||||
        it('should have 18 decimals', async () => {
 | 
			
		||||
            const decimals = new BigNumber(await zrxToken.decimals().callAsync());
 | 
			
		||||
            const expectedDecimals = 18;
 | 
			
		||||
            expect(decimals).to.be.bignumber.equal(expectedDecimals);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should have a total supply of 1 billion tokens', async () => {
 | 
			
		||||
            const totalSupply = new BigNumber(await zrxToken.totalSupply().callAsync());
 | 
			
		||||
            const expectedTotalSupply = 1000000000;
 | 
			
		||||
            expect(Web3Wrapper.toUnitAmount(totalSupply, 18)).to.be.bignumber.equal(expectedTotalSupply);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should be named 0x Protocol Token', async () => {
 | 
			
		||||
            const name = await zrxToken.name().callAsync();
 | 
			
		||||
            const expectedName = '0x Protocol Token';
 | 
			
		||||
            expect(name).to.be.equal(expectedName);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should have the symbol ZRX', async () => {
 | 
			
		||||
            const symbol = await zrxToken.symbol().callAsync();
 | 
			
		||||
            const expectedSymbol = 'ZRX';
 | 
			
		||||
            expect(symbol).to.be.equal(expectedSymbol);
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    describe('constructor', () => {
 | 
			
		||||
        it('should initialize owner balance to totalSupply', async () => {
 | 
			
		||||
            const ownerBalance = await zrxToken.balanceOf(owner).callAsync();
 | 
			
		||||
            const totalSupply = new BigNumber(await zrxToken.totalSupply().callAsync());
 | 
			
		||||
            expect(totalSupply).to.be.bignumber.equal(ownerBalance);
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    describe('transfer', () => {
 | 
			
		||||
        it('should transfer balance from sender to receiver', async () => {
 | 
			
		||||
            const receiver = spender;
 | 
			
		||||
            const initOwnerBalance = await zrxToken.balanceOf(owner).callAsync();
 | 
			
		||||
            const amountToTransfer = new BigNumber(1);
 | 
			
		||||
            await web3Wrapper.awaitTransactionSuccessAsync(
 | 
			
		||||
                await zrxToken.transfer(receiver, amountToTransfer).sendTransactionAsync({ from: owner }),
 | 
			
		||||
                constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
            );
 | 
			
		||||
            const finalOwnerBalance = await zrxToken.balanceOf(owner).callAsync();
 | 
			
		||||
            const finalReceiverBalance = await zrxToken.balanceOf(receiver).callAsync();
 | 
			
		||||
 | 
			
		||||
            const expectedFinalOwnerBalance = initOwnerBalance.minus(amountToTransfer);
 | 
			
		||||
            const expectedFinalReceiverBalance = amountToTransfer;
 | 
			
		||||
            expect(finalOwnerBalance).to.be.bignumber.equal(expectedFinalOwnerBalance);
 | 
			
		||||
            expect(finalReceiverBalance).to.be.bignumber.equal(expectedFinalReceiverBalance);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should return true on a 0 value transfer', async () => {
 | 
			
		||||
            const didReturnTrue = await zrxToken.transfer(spender, new BigNumber(0)).callAsync({
 | 
			
		||||
                from: owner,
 | 
			
		||||
            });
 | 
			
		||||
            expect(didReturnTrue).to.be.true();
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    describe('transferFrom', () => {
 | 
			
		||||
        it('should return false if owner has insufficient balance', async () => {
 | 
			
		||||
            const ownerBalance = await zrxToken.balanceOf(owner).callAsync();
 | 
			
		||||
            const amountToTransfer = ownerBalance.plus(1);
 | 
			
		||||
            await web3Wrapper.awaitTransactionSuccessAsync(
 | 
			
		||||
                await zrxToken.approve(spender, amountToTransfer).sendTransactionAsync({
 | 
			
		||||
                    from: owner,
 | 
			
		||||
                    gas: constants.MAX_TOKEN_APPROVE_GAS,
 | 
			
		||||
                }),
 | 
			
		||||
                constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
            );
 | 
			
		||||
            const didReturnTrue = await zrxToken.transferFrom(owner, spender, amountToTransfer).callAsync({
 | 
			
		||||
                from: spender,
 | 
			
		||||
            });
 | 
			
		||||
            expect(didReturnTrue).to.be.false();
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should return false if spender has insufficient allowance', async () => {
 | 
			
		||||
            const ownerBalance = await zrxToken.balanceOf(owner).callAsync();
 | 
			
		||||
            const amountToTransfer = ownerBalance;
 | 
			
		||||
 | 
			
		||||
            const spenderAllowance = await zrxToken.allowance(owner, spender).callAsync();
 | 
			
		||||
            const isSpenderAllowanceInsufficient = spenderAllowance.comparedTo(amountToTransfer) < 0;
 | 
			
		||||
            expect(isSpenderAllowanceInsufficient).to.be.true();
 | 
			
		||||
 | 
			
		||||
            const didReturnTrue = await zrxToken.transferFrom(owner, spender, amountToTransfer).callAsync({
 | 
			
		||||
                from: spender,
 | 
			
		||||
            });
 | 
			
		||||
            expect(didReturnTrue).to.be.false();
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should return true on a 0 value transfer', async () => {
 | 
			
		||||
            const amountToTransfer = new BigNumber(0);
 | 
			
		||||
            const didReturnTrue = await zrxToken.transferFrom(owner, spender, amountToTransfer).callAsync({
 | 
			
		||||
                from: spender,
 | 
			
		||||
            });
 | 
			
		||||
            expect(didReturnTrue).to.be.true();
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should not modify spender allowance if spender allowance is 2^256 - 1', async () => {
 | 
			
		||||
            const initOwnerBalance = await zrxToken.balanceOf(owner).callAsync();
 | 
			
		||||
            const amountToTransfer = initOwnerBalance;
 | 
			
		||||
            const initSpenderAllowance = MAX_UINT;
 | 
			
		||||
            await web3Wrapper.awaitTransactionSuccessAsync(
 | 
			
		||||
                await zrxToken.approve(spender, initSpenderAllowance).sendTransactionAsync({
 | 
			
		||||
                    from: owner,
 | 
			
		||||
                    gas: constants.MAX_TOKEN_APPROVE_GAS,
 | 
			
		||||
                }),
 | 
			
		||||
                constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
            );
 | 
			
		||||
            await web3Wrapper.awaitTransactionSuccessAsync(
 | 
			
		||||
                await zrxToken.transferFrom(owner, spender, amountToTransfer).sendTransactionAsync({
 | 
			
		||||
                    from: spender,
 | 
			
		||||
                    gas: constants.MAX_TOKEN_TRANSFERFROM_GAS,
 | 
			
		||||
                }),
 | 
			
		||||
                constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
            const newSpenderAllowance = await zrxToken.allowance(owner, spender).callAsync();
 | 
			
		||||
            expect(initSpenderAllowance).to.be.bignumber.equal(newSpenderAllowance);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should transfer the correct balances if spender has sufficient allowance', async () => {
 | 
			
		||||
            const initOwnerBalance = await zrxToken.balanceOf(owner).callAsync();
 | 
			
		||||
            const initSpenderBalance = await zrxToken.balanceOf(spender).callAsync();
 | 
			
		||||
            const amountToTransfer = initOwnerBalance;
 | 
			
		||||
            const initSpenderAllowance = initOwnerBalance;
 | 
			
		||||
            await web3Wrapper.awaitTransactionSuccessAsync(
 | 
			
		||||
                await zrxToken.approve(spender, initSpenderAllowance).sendTransactionAsync(),
 | 
			
		||||
                constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
            );
 | 
			
		||||
            await web3Wrapper.awaitTransactionSuccessAsync(
 | 
			
		||||
                await zrxToken.transferFrom(owner, spender, amountToTransfer).sendTransactionAsync({
 | 
			
		||||
                    from: spender,
 | 
			
		||||
                    gas: constants.MAX_TOKEN_TRANSFERFROM_GAS,
 | 
			
		||||
                }),
 | 
			
		||||
                constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
            const newOwnerBalance = await zrxToken.balanceOf(owner).callAsync();
 | 
			
		||||
            const newSpenderBalance = await zrxToken.balanceOf(spender).callAsync();
 | 
			
		||||
 | 
			
		||||
            expect(newOwnerBalance).to.be.bignumber.equal(0);
 | 
			
		||||
            expect(newSpenderBalance).to.be.bignumber.equal(initSpenderBalance.plus(initOwnerBalance));
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should modify allowance if spender has sufficient allowance less than 2^256 - 1', async () => {
 | 
			
		||||
            const initOwnerBalance = await zrxToken.balanceOf(owner).callAsync();
 | 
			
		||||
            const amountToTransfer = initOwnerBalance;
 | 
			
		||||
            await web3Wrapper.awaitTransactionSuccessAsync(
 | 
			
		||||
                await zrxToken.approve(spender, amountToTransfer).sendTransactionAsync(),
 | 
			
		||||
                constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
            );
 | 
			
		||||
            await web3Wrapper.awaitTransactionSuccessAsync(
 | 
			
		||||
                await zrxToken.transferFrom(owner, spender, amountToTransfer).sendTransactionAsync({
 | 
			
		||||
                    from: spender,
 | 
			
		||||
                    gas: constants.MAX_TOKEN_TRANSFERFROM_GAS,
 | 
			
		||||
                }),
 | 
			
		||||
                constants.AWAIT_TRANSACTION_MINED_MS,
 | 
			
		||||
            );
 | 
			
		||||
 | 
			
		||||
            const newSpenderAllowance = await zrxToken.allowance(owner, spender).callAsync();
 | 
			
		||||
            expect(newSpenderAllowance).to.be.bignumber.equal(0);
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
});
 | 
			
		||||
@@ -1,35 +0,0 @@
 | 
			
		||||
{
 | 
			
		||||
    "extends": "../../tsconfig",
 | 
			
		||||
    "compilerOptions": { "outDir": "lib", "rootDir": ".", "resolveJsonModule": true },
 | 
			
		||||
    "include": ["./src/**/*", "./test/**/*", "./generated-wrappers/**/*"],
 | 
			
		||||
    "files": [
 | 
			
		||||
        "generated-artifacts/DummyERC20Token.json",
 | 
			
		||||
        "generated-artifacts/DummyMultipleReturnERC20Token.json",
 | 
			
		||||
        "generated-artifacts/DummyNoReturnERC20Token.json",
 | 
			
		||||
        "generated-artifacts/ERC20Token.json",
 | 
			
		||||
        "generated-artifacts/WETH9.json",
 | 
			
		||||
        "generated-artifacts/ZRXToken.json",
 | 
			
		||||
        "test/generated-artifacts/DummyERC20Token.json",
 | 
			
		||||
        "test/generated-artifacts/DummyMultipleReturnERC20Token.json",
 | 
			
		||||
        "test/generated-artifacts/DummyNoReturnERC20Token.json",
 | 
			
		||||
        "test/generated-artifacts/ERC20Token.json",
 | 
			
		||||
        "test/generated-artifacts/IERC20Token.json",
 | 
			
		||||
        "test/generated-artifacts/IERC20TokenV06.json",
 | 
			
		||||
        "test/generated-artifacts/IERC20TokenV08.json",
 | 
			
		||||
        "test/generated-artifacts/IEtherToken.json",
 | 
			
		||||
        "test/generated-artifacts/IEtherTokenV06.json",
 | 
			
		||||
        "test/generated-artifacts/IEtherTokenV08.json",
 | 
			
		||||
        "test/generated-artifacts/LibERC20Token.json",
 | 
			
		||||
        "test/generated-artifacts/LibERC20TokenV06.json",
 | 
			
		||||
        "test/generated-artifacts/LibERC20TokenV08.json",
 | 
			
		||||
        "test/generated-artifacts/MintableERC20Token.json",
 | 
			
		||||
        "test/generated-artifacts/TestLibERC20Token.json",
 | 
			
		||||
        "test/generated-artifacts/TestLibERC20TokenTarget.json",
 | 
			
		||||
        "test/generated-artifacts/UnlimitedAllowanceERC20Token.json",
 | 
			
		||||
        "test/generated-artifacts/UntransferrableDummyERC20Token.json",
 | 
			
		||||
        "test/generated-artifacts/WETH9.json",
 | 
			
		||||
        "test/generated-artifacts/WETH9V06.json",
 | 
			
		||||
        "test/generated-artifacts/ZRXToken.json"
 | 
			
		||||
    ],
 | 
			
		||||
    "exclude": ["./deploy/solc/solc_bin"]
 | 
			
		||||
}
 | 
			
		||||
@@ -1,7 +0,0 @@
 | 
			
		||||
{
 | 
			
		||||
    "extends": "../../typedoc-tsconfig",
 | 
			
		||||
    "compilerOptions": {
 | 
			
		||||
        "outDir": "lib"
 | 
			
		||||
    },
 | 
			
		||||
    "include": ["./src/**/*", "./test/**/*"]
 | 
			
		||||
}
 | 
			
		||||
@@ -90,7 +90,6 @@ export enum ContractName {
 | 
			
		||||
    DummyERC721Token = 'DummyERC721Token',
 | 
			
		||||
    TestLibBytes = 'TestLibBytes',
 | 
			
		||||
    TestWallet = 'TestWallet',
 | 
			
		||||
    Authorizable = 'Authorizable',
 | 
			
		||||
    Whitelist = 'Whitelist',
 | 
			
		||||
    Forwarder = 'Forwarder',
 | 
			
		||||
    BalanceThresholdFilter = 'BalanceThresholdFilter',
 | 
			
		||||
 
 | 
			
		||||
@@ -20,19 +20,19 @@
 | 
			
		||||
pragma solidity ^0.6.12;
 | 
			
		||||
pragma experimental ABIEncoderV2;
 | 
			
		||||
 | 
			
		||||
import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol";
 | 
			
		||||
import "@0x/contracts-erc20/src/IERC20Token.sol";
 | 
			
		||||
import "./IStaking.sol";
 | 
			
		||||
 | 
			
		||||
contract DefaultPoolOperator {
 | 
			
		||||
    // Immutables
 | 
			
		||||
    IStaking public immutable stakingProxy;
 | 
			
		||||
    IERC20TokenV06 public immutable weth;
 | 
			
		||||
    IERC20Token public immutable weth;
 | 
			
		||||
    bytes32 public immutable poolId;
 | 
			
		||||
 | 
			
		||||
    /// @dev Initializes this contract and creates a staking pool.
 | 
			
		||||
    /// @param stakingProxy_ The 0x staking proxy contract.
 | 
			
		||||
    /// @param weth_ The WETH token contract.
 | 
			
		||||
    constructor(IStaking stakingProxy_, IERC20TokenV06 weth_) public {
 | 
			
		||||
    constructor(IStaking stakingProxy_, IERC20Token weth_) public {
 | 
			
		||||
        stakingProxy = stakingProxy_;
 | 
			
		||||
        weth = weth_;
 | 
			
		||||
        // operator share = 100%
 | 
			
		||||
 
 | 
			
		||||
@@ -48,7 +48,7 @@
 | 
			
		||||
        "@0x/abi-gen": "^5.8.1",
 | 
			
		||||
        "@0x/contract-addresses": "^8.0.3",
 | 
			
		||||
        "@0x/contracts-asset-proxy": "^3.7.19",
 | 
			
		||||
        "@0x/contracts-erc20": "^3.3.57",
 | 
			
		||||
        "@0x/contracts-erc20": "3.3.57",
 | 
			
		||||
        "@0x/contracts-gen": "^2.0.48",
 | 
			
		||||
        "@0x/contracts-staking": "^2.0.45",
 | 
			
		||||
        "@0x/contracts-test-utils": "^5.4.47",
 | 
			
		||||
 
 | 
			
		||||
@@ -1,122 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  Copyright 2019 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.5.9;
 | 
			
		||||
 | 
			
		||||
import "./interfaces/IAuthorizable.sol";
 | 
			
		||||
import "./LibAuthorizableRichErrors.sol";
 | 
			
		||||
import "./LibRichErrors.sol";
 | 
			
		||||
import "./Ownable.sol";
 | 
			
		||||
 | 
			
		||||
contract Authorizable is Ownable, IAuthorizable {
 | 
			
		||||
    /// @dev Only authorized addresses can invoke functions with this modifier.
 | 
			
		||||
    modifier onlyAuthorized() {
 | 
			
		||||
        _assertSenderIsAuthorized();
 | 
			
		||||
        _;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Whether an adderss is authorized to call privileged functions.
 | 
			
		||||
    /// @param 0 Address to query.
 | 
			
		||||
    /// @return 0 Whether the address is authorized.
 | 
			
		||||
    mapping(address => bool) public authorized;
 | 
			
		||||
    /// @dev Whether an adderss is authorized to call privileged functions.
 | 
			
		||||
    /// @param 0 Index of authorized address.
 | 
			
		||||
    /// @return 0 Authorized address.
 | 
			
		||||
    address[] public authorities;
 | 
			
		||||
 | 
			
		||||
    /// @dev Initializes the `owner` address.
 | 
			
		||||
    constructor() public Ownable() {}
 | 
			
		||||
 | 
			
		||||
    /// @dev Authorizes an address.
 | 
			
		||||
    /// @param target Address to authorize.
 | 
			
		||||
    function addAuthorizedAddress(address target) external onlyOwner {
 | 
			
		||||
        _addAuthorizedAddress(target);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Removes authorizion of an address.
 | 
			
		||||
    /// @param target Address to remove authorization from.
 | 
			
		||||
    function removeAuthorizedAddress(address target) external onlyOwner {
 | 
			
		||||
        if (!authorized[target]) {
 | 
			
		||||
            LibRichErrors.rrevert(LibAuthorizableRichErrors.TargetNotAuthorizedError(target));
 | 
			
		||||
        }
 | 
			
		||||
        for (uint256 i = 0; i < authorities.length; i++) {
 | 
			
		||||
            if (authorities[i] == target) {
 | 
			
		||||
                _removeAuthorizedAddressAtIndex(target, i);
 | 
			
		||||
                break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Removes authorizion of an address.
 | 
			
		||||
    /// @param target Address to remove authorization from.
 | 
			
		||||
    /// @param index Index of target in authorities array.
 | 
			
		||||
    function removeAuthorizedAddressAtIndex(address target, uint256 index) external onlyOwner {
 | 
			
		||||
        _removeAuthorizedAddressAtIndex(target, index);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Gets all authorized addresses.
 | 
			
		||||
    /// @return Array of authorized addresses.
 | 
			
		||||
    function getAuthorizedAddresses() external view returns (address[] memory) {
 | 
			
		||||
        return authorities;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Reverts if msg.sender is not authorized.
 | 
			
		||||
    function _assertSenderIsAuthorized() internal view {
 | 
			
		||||
        if (!authorized[msg.sender]) {
 | 
			
		||||
            LibRichErrors.rrevert(LibAuthorizableRichErrors.SenderNotAuthorizedError(msg.sender));
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Authorizes an address.
 | 
			
		||||
    /// @param target Address to authorize.
 | 
			
		||||
    function _addAuthorizedAddress(address target) internal {
 | 
			
		||||
        // Ensure that the target is not the zero address.
 | 
			
		||||
        if (target == address(0)) {
 | 
			
		||||
            LibRichErrors.rrevert(LibAuthorizableRichErrors.ZeroCantBeAuthorizedError());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Ensure that the target is not already authorized.
 | 
			
		||||
        if (authorized[target]) {
 | 
			
		||||
            LibRichErrors.rrevert(LibAuthorizableRichErrors.TargetAlreadyAuthorizedError(target));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        authorized[target] = true;
 | 
			
		||||
        authorities.push(target);
 | 
			
		||||
        emit AuthorizedAddressAdded(target, msg.sender);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Removes authorizion of an address.
 | 
			
		||||
    /// @param target Address to remove authorization from.
 | 
			
		||||
    /// @param index Index of target in authorities array.
 | 
			
		||||
    function _removeAuthorizedAddressAtIndex(address target, uint256 index) internal {
 | 
			
		||||
        if (!authorized[target]) {
 | 
			
		||||
            LibRichErrors.rrevert(LibAuthorizableRichErrors.TargetNotAuthorizedError(target));
 | 
			
		||||
        }
 | 
			
		||||
        if (index >= authorities.length) {
 | 
			
		||||
            LibRichErrors.rrevert(LibAuthorizableRichErrors.IndexOutOfBoundsError(index, authorities.length));
 | 
			
		||||
        }
 | 
			
		||||
        if (authorities[index] != target) {
 | 
			
		||||
            LibRichErrors.rrevert(LibAuthorizableRichErrors.AuthorizedAddressMismatchError(authorities[index], target));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        delete authorized[target];
 | 
			
		||||
        authorities[index] = authorities[authorities.length - 1];
 | 
			
		||||
        authorities.length -= 1;
 | 
			
		||||
        emit AuthorizedAddressRemoved(target, msg.sender);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,159 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  Copyright 2019 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.5.16;
 | 
			
		||||
 | 
			
		||||
/// @dev A library for working with 18 digit, base 10 decimals.
 | 
			
		||||
library D18 {
 | 
			
		||||
    /// @dev Decimal places for dydx value quantities.
 | 
			
		||||
    uint256 private constant PRECISION = 18;
 | 
			
		||||
    /// @dev 1.0 in base-18 decimal.
 | 
			
		||||
    int256 private constant DECIMAL_ONE = int256(10 ** PRECISION);
 | 
			
		||||
    /// @dev Minimum signed integer value.
 | 
			
		||||
    int256 private constant MIN_INT256_VALUE =
 | 
			
		||||
        int256(0x8000000000000000000000000000000000000000000000000000000000000000);
 | 
			
		||||
 | 
			
		||||
    /// @dev Return `1.0`
 | 
			
		||||
    function one() internal pure returns (int256 r) {
 | 
			
		||||
        r = DECIMAL_ONE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Add two decimals.
 | 
			
		||||
    function add(int256 a, int256 b) internal pure returns (int256 r) {
 | 
			
		||||
        r = _add(a, b);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Add two decimals.
 | 
			
		||||
    function add(uint256 a, int256 b) internal pure returns (int256 r) {
 | 
			
		||||
        require(int256(a) >= 0, "D18/DECIMAL_VALUE_TOO_BIG");
 | 
			
		||||
        r = _add(int256(a), b);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Add two decimals.
 | 
			
		||||
    function add(int256 a, uint256 b) internal pure returns (int256 r) {
 | 
			
		||||
        require(int256(b) >= 0, "D18/DECIMAL_VALUE_TOO_BIG");
 | 
			
		||||
        r = _add(a, int256(b));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Add two decimals.
 | 
			
		||||
    function add(uint256 a, uint256 b) internal pure returns (int256 r) {
 | 
			
		||||
        require(int256(a) >= 0, "D18/DECIMAL_VALUE_TOO_BIG");
 | 
			
		||||
        require(int256(b) >= 0, "D18/DECIMAL_VALUE_TOO_BIG");
 | 
			
		||||
        r = _add(int256(a), int256(b));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Subract two decimals.
 | 
			
		||||
    function sub(int256 a, int256 b) internal pure returns (int256 r) {
 | 
			
		||||
        r = _add(a, -b);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Subract two decimals.
 | 
			
		||||
    function sub(uint256 a, int256 b) internal pure returns (int256 r) {
 | 
			
		||||
        require(int256(a) >= 0, "D18/DECIMAL_VALUE_TOO_BIG");
 | 
			
		||||
        r = _add(int256(a), -b);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Subract two decimals.
 | 
			
		||||
    function sub(uint256 a, uint256 b) internal pure returns (int256 r) {
 | 
			
		||||
        require(int256(a) >= 0, "D18/DECIMAL_VALUE_TOO_BIG");
 | 
			
		||||
        require(int256(b) >= 0, "D18/DECIMAL_VALUE_TOO_BIG");
 | 
			
		||||
        r = _add(int256(a), -int256(b));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Multiply two decimals.
 | 
			
		||||
    function mul(int256 a, int256 b) internal pure returns (int256 r) {
 | 
			
		||||
        r = _div(_mul(a, b), DECIMAL_ONE);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Multiply two decimals.
 | 
			
		||||
    function mul(uint256 a, int256 b) internal pure returns (int256 r) {
 | 
			
		||||
        require(int256(a) >= 0, "D18/DECIMAL_VALUE_TOO_BIG");
 | 
			
		||||
        r = _div(_mul(int256(a), b), DECIMAL_ONE);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Multiply two decimals.
 | 
			
		||||
    function mul(int256 a, uint256 b) internal pure returns (int256 r) {
 | 
			
		||||
        require(int256(b) >= 0, "D18/DECIMAL_VALUE_TOO_BIG");
 | 
			
		||||
        r = _div(_mul(a, int256(b)), DECIMAL_ONE);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Multiply two decimals.
 | 
			
		||||
    function mul(uint256 a, uint256 b) internal pure returns (int256 r) {
 | 
			
		||||
        require(int256(a) >= 0, "D18/DECIMAL_VALUE_TOO_BIG");
 | 
			
		||||
        require(int256(b) >= 0, "D18/DECIMAL_VALUE_TOO_BIG");
 | 
			
		||||
        r = _div(_mul(int256(a), int256(b)), DECIMAL_ONE);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Divide two decimals.
 | 
			
		||||
    function div(int256 a, int256 b) internal pure returns (int256 r) {
 | 
			
		||||
        r = _div(_mul(a, DECIMAL_ONE), b);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Divide two decimals.
 | 
			
		||||
    function div(uint256 a, int256 b) internal pure returns (int256 r) {
 | 
			
		||||
        require(int256(a) >= 0, "D18/DECIMAL_VALUE_TOO_BIG");
 | 
			
		||||
        r = _div(_mul(int256(a), DECIMAL_ONE), b);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Divide two decimals.
 | 
			
		||||
    function div(int256 a, uint256 b) internal pure returns (int256 r) {
 | 
			
		||||
        require(int256(b) >= 0, "D18/DECIMAL_VALUE_TOO_BIG");
 | 
			
		||||
        r = _div(_mul(a, DECIMAL_ONE), int256(b));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Divide two decimals.
 | 
			
		||||
    function div(uint256 a, uint256 b) internal pure returns (int256 r) {
 | 
			
		||||
        require(int256(a) >= 0, "D18/DECIMAL_VALUE_TOO_BIG");
 | 
			
		||||
        require(int256(b) >= 0, "D18/DECIMAL_VALUE_TOO_BIG");
 | 
			
		||||
        r = _div(_mul(int256(a), DECIMAL_ONE), int256(b));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Safely convert an unsigned integer into a signed integer.
 | 
			
		||||
    function toSigned(uint256 a) internal pure returns (int256 r) {
 | 
			
		||||
        require(int256(a) >= 0, "D18/DECIMAL_VALUE_TOO_BIG");
 | 
			
		||||
        r = int256(a);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Clip a signed value to be positive.
 | 
			
		||||
    function clip(int256 a) internal pure returns (int256 r) {
 | 
			
		||||
        r = a < 0 ? 0 : a;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Safely multiply two signed integers.
 | 
			
		||||
    function _mul(int256 a, int256 b) private pure returns (int256 r) {
 | 
			
		||||
        if (a == 0 || b == 0) {
 | 
			
		||||
            return 0;
 | 
			
		||||
        }
 | 
			
		||||
        r = a * b;
 | 
			
		||||
        require(r / a == b && r / b == a, "D18/DECIMAL_MUL_OVERFLOW");
 | 
			
		||||
        return r;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Safely divide two signed integers.
 | 
			
		||||
    function _div(int256 a, int256 b) private pure returns (int256 r) {
 | 
			
		||||
        require(b != 0, "D18/DECIMAL_DIV_BY_ZERO");
 | 
			
		||||
        require(a != MIN_INT256_VALUE || b != -1, "D18/DECIMAL_DIV_OVERFLOW");
 | 
			
		||||
        r = a / b;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Safely add two signed integers.
 | 
			
		||||
    function _add(int256 a, int256 b) private pure returns (int256 r) {
 | 
			
		||||
        r = a + b;
 | 
			
		||||
        require(!((a < 0 && b < 0 && r > a) || (a > 0 && b > 0 && r < a)), "D18/DECIMAL_ADD_OVERFLOW");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,251 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  Copyright 2020 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.5.9;
 | 
			
		||||
 | 
			
		||||
contract DeploymentConstants {
 | 
			
		||||
    // Mainnet addresses ///////////////////////////////////////////////////////
 | 
			
		||||
    /// @dev Mainnet address of the WETH contract.
 | 
			
		||||
    address private constant WETH_ADDRESS = 0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2;
 | 
			
		||||
    /// @dev Mainnet address of the KyberNetworkProxy contract.
 | 
			
		||||
    address private constant KYBER_NETWORK_PROXY_ADDRESS = 0x9AAb3f75489902f3a48495025729a0AF77d4b11e;
 | 
			
		||||
    /// @dev Mainnet address of the KyberHintHandler contract.
 | 
			
		||||
    address private constant KYBER_HINT_HANDLER_ADDRESS = 0xa1C0Fa73c39CFBcC11ec9Eb1Afc665aba9996E2C;
 | 
			
		||||
    /// @dev Mainnet address of the `UniswapExchangeFactory` contract.
 | 
			
		||||
    address private constant UNISWAP_EXCHANGE_FACTORY_ADDRESS = 0xc0a47dFe034B400B47bDaD5FecDa2621de6c4d95;
 | 
			
		||||
    /// @dev Mainnet address of the `UniswapV2Router01` contract.
 | 
			
		||||
    address private constant UNISWAP_V2_ROUTER_01_ADDRESS = 0xf164fC0Ec4E93095b804a4795bBe1e041497b92a;
 | 
			
		||||
    /// @dev Mainnet address of the Eth2Dai `MatchingMarket` contract.
 | 
			
		||||
    address private constant ETH2DAI_ADDRESS = 0x794e6e91555438aFc3ccF1c5076A74F42133d08D;
 | 
			
		||||
    /// @dev Mainnet address of the `ERC20BridgeProxy` contract
 | 
			
		||||
    address private constant ERC20_BRIDGE_PROXY_ADDRESS = 0x8ED95d1746bf1E4dAb58d8ED4724f1Ef95B20Db0;
 | 
			
		||||
    ///@dev Mainnet address of the `Dai` (multi-collateral) contract
 | 
			
		||||
    address private constant DAI_ADDRESS = 0x6B175474E89094C44Da98b954EedeAC495271d0F;
 | 
			
		||||
    /// @dev Mainnet address of the `Chai` contract
 | 
			
		||||
    address private constant CHAI_ADDRESS = 0x06AF07097C9Eeb7fD685c692751D5C66dB49c215;
 | 
			
		||||
    /// @dev Mainnet address of the 0x DevUtils contract.
 | 
			
		||||
    address private constant DEV_UTILS_ADDRESS = 0x74134CF88b21383713E096a5ecF59e297dc7f547;
 | 
			
		||||
    /// @dev Kyber ETH pseudo-address.
 | 
			
		||||
    address internal constant KYBER_ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
 | 
			
		||||
    /// @dev Mainnet address of the dYdX contract.
 | 
			
		||||
    address private constant DYDX_ADDRESS = 0x1E0447b19BB6EcFdAe1e4AE1694b0C3659614e4e;
 | 
			
		||||
    /// @dev Mainnet address of the GST2 contract
 | 
			
		||||
    address private constant GST_ADDRESS = 0x0000000000b3F879cb30FE243b4Dfee438691c04;
 | 
			
		||||
    /// @dev Mainnet address of the GST Collector
 | 
			
		||||
    address private constant GST_COLLECTOR_ADDRESS = 0x000000D3b08566BE75A6DB803C03C85C0c1c5B96;
 | 
			
		||||
    /// @dev Mainnet address of the mStable mUSD contract.
 | 
			
		||||
    address private constant MUSD_ADDRESS = 0xe2f2a5C287993345a840Db3B0845fbC70f5935a5;
 | 
			
		||||
    /// @dev Mainnet address of the Mooniswap Registry contract
 | 
			
		||||
    address private constant MOONISWAP_REGISTRY = 0x71CD6666064C3A1354a3B4dca5fA1E2D3ee7D303;
 | 
			
		||||
    /// @dev Mainnet address of the DODO Registry (ZOO) contract
 | 
			
		||||
    address private constant DODO_REGISTRY = 0x3A97247DF274a17C59A3bd12735ea3FcDFb49950;
 | 
			
		||||
    /// @dev Mainnet address of the DODO Helper contract
 | 
			
		||||
    address private constant DODO_HELPER = 0x533dA777aeDCE766CEAe696bf90f8541A4bA80Eb;
 | 
			
		||||
 | 
			
		||||
    // // Ropsten addresses ///////////////////////////////////////////////////////
 | 
			
		||||
    /// @dev Mainnet address of the WETH contract.
 | 
			
		||||
    // address constant private WETH_ADDRESS = 0xc778417E063141139Fce010982780140Aa0cD5Ab;
 | 
			
		||||
    /// @dev Mainnet address of the KyberNetworkProxy contract.
 | 
			
		||||
    // address constant private KYBER_NETWORK_PROXY_ADDRESS = 0xd719c34261e099Fdb33030ac8909d5788D3039C4;
 | 
			
		||||
    /// @dev Mainnet address of the `UniswapExchangeFactory` contract.
 | 
			
		||||
    // address constant private UNISWAP_EXCHANGE_FACTORY_ADDRESS = 0x9c83dCE8CA20E9aAF9D3efc003b2ea62aBC08351;
 | 
			
		||||
    /// @dev Mainnet address of the `UniswapV2Router01` contract.
 | 
			
		||||
    // address constant private UNISWAP_V2_ROUTER_01_ADDRESS = 0xf164fC0Ec4E93095b804a4795bBe1e041497b92a;
 | 
			
		||||
    /// @dev Mainnet address of the Eth2Dai `MatchingMarket` contract.
 | 
			
		||||
    // address constant private ETH2DAI_ADDRESS = address(0);
 | 
			
		||||
    /// @dev Mainnet address of the `ERC20BridgeProxy` contract
 | 
			
		||||
    // address constant private ERC20_BRIDGE_PROXY_ADDRESS = 0xb344afeD348de15eb4a9e180205A2B0739628339;
 | 
			
		||||
    // ///@dev Mainnet address of the `Dai` (multi-collateral) contract
 | 
			
		||||
    // address constant private DAI_ADDRESS = address(0);
 | 
			
		||||
    /// @dev Mainnet address of the `Chai` contract
 | 
			
		||||
    // address constant private CHAI_ADDRESS = address(0);
 | 
			
		||||
    /// @dev Mainnet address of the 0x DevUtils contract.
 | 
			
		||||
    // address constant private DEV_UTILS_ADDRESS = 0xC812AF3f3fBC62F76ea4262576EC0f49dB8B7f1c;
 | 
			
		||||
    /// @dev Kyber ETH pseudo-address.
 | 
			
		||||
    // address constant internal KYBER_ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
 | 
			
		||||
    /// @dev Mainnet address of the dYdX contract.
 | 
			
		||||
    // address constant private DYDX_ADDRESS = address(0);
 | 
			
		||||
    /// @dev Mainnet address of the GST2 contract
 | 
			
		||||
    // address constant private GST_ADDRESS = address(0);
 | 
			
		||||
    /// @dev Mainnet address of the GST Collector
 | 
			
		||||
    // address constant private GST_COLLECTOR_ADDRESS = address(0);
 | 
			
		||||
    /// @dev Mainnet address of the mStable mUSD contract.
 | 
			
		||||
    // address constant private MUSD_ADDRESS = 0x4E1000616990D83e56f4b5fC6CC8602DcfD20459;
 | 
			
		||||
 | 
			
		||||
    // // Rinkeby addresses ///////////////////////////////////////////////////////
 | 
			
		||||
    /// @dev Mainnet address of the WETH contract.
 | 
			
		||||
    // address constant private WETH_ADDRESS = 0xc778417E063141139Fce010982780140Aa0cD5Ab;
 | 
			
		||||
    /// @dev Mainnet address of the KyberNetworkProxy contract.
 | 
			
		||||
    // address constant private KYBER_NETWORK_PROXY_ADDRESS = 0x0d5371e5EE23dec7DF251A8957279629aa79E9C5;
 | 
			
		||||
    /// @dev Mainnet address of the `UniswapExchangeFactory` contract.
 | 
			
		||||
    // address constant private UNISWAP_EXCHANGE_FACTORY_ADDRESS = 0xf5D915570BC477f9B8D6C0E980aA81757A3AaC36;
 | 
			
		||||
    /// @dev Mainnet address of the `UniswapV2Router01` contract.
 | 
			
		||||
    // address constant private UNISWAP_V2_ROUTER_01_ADDRESS = 0xf164fC0Ec4E93095b804a4795bBe1e041497b92a;
 | 
			
		||||
    /// @dev Mainnet address of the Eth2Dai `MatchingMarket` contract.
 | 
			
		||||
    // address constant private ETH2DAI_ADDRESS = address(0);
 | 
			
		||||
    /// @dev Mainnet address of the `ERC20BridgeProxy` contract
 | 
			
		||||
    // address constant private ERC20_BRIDGE_PROXY_ADDRESS = 0xA2AA4bEFED748Fba27a3bE7Dfd2C4b2c6DB1F49B;
 | 
			
		||||
    // ///@dev Mainnet address of the `Dai` (multi-collateral) contract
 | 
			
		||||
    // address constant private DAI_ADDRESS = address(0);
 | 
			
		||||
    /// @dev Mainnet address of the `Chai` contract
 | 
			
		||||
    // address constant private CHAI_ADDRESS = address(0);
 | 
			
		||||
    /// @dev Mainnet address of the 0x DevUtils contract.
 | 
			
		||||
    // address constant private DEV_UTILS_ADDRESS = 0x46B5BC959e8A754c0256FFF73bF34A52Ad5CdfA9;
 | 
			
		||||
    /// @dev Kyber ETH pseudo-address.
 | 
			
		||||
    // address constant internal KYBER_ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
 | 
			
		||||
    /// @dev Mainnet address of the dYdX contract.
 | 
			
		||||
    // address constant private DYDX_ADDRESS = address(0);
 | 
			
		||||
    /// @dev Mainnet address of the GST2 contract
 | 
			
		||||
    // address constant private GST_ADDRESS = address(0);
 | 
			
		||||
    /// @dev Mainnet address of the GST Collector
 | 
			
		||||
    // address constant private GST_COLLECTOR_ADDRESS = address(0);
 | 
			
		||||
    /// @dev Mainnet address of the mStable mUSD contract.
 | 
			
		||||
    // address constant private MUSD_ADDRESS = address(0);
 | 
			
		||||
 | 
			
		||||
    // // Kovan addresses /////////////////////////////////////////////////////////
 | 
			
		||||
    /// @dev Kovan address of the WETH contract.
 | 
			
		||||
    // address constant private WETH_ADDRESS = 0xd0A1E359811322d97991E03f863a0C30C2cF029C;
 | 
			
		||||
    /// @dev Kovan address of the KyberNetworkProxy contract.
 | 
			
		||||
    // address constant private KYBER_NETWORK_PROXY_ADDRESS = 0x692f391bCc85cefCe8C237C01e1f636BbD70EA4D;
 | 
			
		||||
    /// @dev Kovan address of the `UniswapExchangeFactory` contract.
 | 
			
		||||
    // address constant private UNISWAP_EXCHANGE_FACTORY_ADDRESS = 0xD3E51Ef092B2845f10401a0159B2B96e8B6c3D30;
 | 
			
		||||
    /// @dev Kovan address of the `UniswapV2Router01` contract.
 | 
			
		||||
    // address constant private UNISWAP_V2_ROUTER_01_ADDRESS = 0xf164fC0Ec4E93095b804a4795bBe1e041497b92a;
 | 
			
		||||
    /// @dev Kovan address of the Eth2Dai `MatchingMarket` contract.
 | 
			
		||||
    // address constant private ETH2DAI_ADDRESS = 0xe325acB9765b02b8b418199bf9650972299235F4;
 | 
			
		||||
    /// @dev Kovan address of the `ERC20BridgeProxy` contract
 | 
			
		||||
    // address constant private ERC20_BRIDGE_PROXY_ADDRESS = 0x3577552C1Fb7A44aD76BeEB7aB53251668A21F8D;
 | 
			
		||||
    /// @dev Kovan address of the `Chai` contract
 | 
			
		||||
    // address constant private CHAI_ADDRESS = address(0);
 | 
			
		||||
    /// @dev Kovan address of the `Dai` (multi-collateral) contract
 | 
			
		||||
    // address constant private DAI_ADDRESS = 0x4F96Fe3b7A6Cf9725f59d353F723c1bDb64CA6Aa;
 | 
			
		||||
    /// @dev Kovan address of the 0x DevUtils contract.
 | 
			
		||||
    // address constant private DEV_UTILS_ADDRESS = 0x9402639A828BdF4E9e4103ac3B69E1a6E522eB59;
 | 
			
		||||
    /// @dev Kyber ETH pseudo-address.
 | 
			
		||||
    // address constant internal KYBER_ETH_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
 | 
			
		||||
    /// @dev Kovan address of the dYdX contract.
 | 
			
		||||
    // address constant private DYDX_ADDRESS = address(0);
 | 
			
		||||
    /// @dev Kovan address of the GST2 contract
 | 
			
		||||
    // address constant private GST_ADDRESS = address(0);
 | 
			
		||||
    /// @dev Kovan address of the GST Collector
 | 
			
		||||
    // address constant private GST_COLLECTOR_ADDRESS = address(0);
 | 
			
		||||
    /// @dev Mainnet address of the mStable mUSD contract.
 | 
			
		||||
    // address constant private MUSD_ADDRESS = address(0);
 | 
			
		||||
 | 
			
		||||
    /// @dev Overridable way to get the `KyberNetworkProxy` address.
 | 
			
		||||
    /// @return kyberAddress The `IKyberNetworkProxy` address.
 | 
			
		||||
    function _getKyberNetworkProxyAddress() internal view returns (address kyberAddress) {
 | 
			
		||||
        return KYBER_NETWORK_PROXY_ADDRESS;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Overridable way to get the `KyberHintHandler` address.
 | 
			
		||||
    /// @return kyberAddress The `IKyberHintHandler` address.
 | 
			
		||||
    function _getKyberHintHandlerAddress() internal view returns (address hintHandlerAddress) {
 | 
			
		||||
        return KYBER_HINT_HANDLER_ADDRESS;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Overridable way to get the WETH address.
 | 
			
		||||
    /// @return wethAddress The WETH address.
 | 
			
		||||
    function _getWethAddress() internal view returns (address wethAddress) {
 | 
			
		||||
        return WETH_ADDRESS;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Overridable way to get the `UniswapExchangeFactory` address.
 | 
			
		||||
    /// @return uniswapAddress The `UniswapExchangeFactory` address.
 | 
			
		||||
    function _getUniswapExchangeFactoryAddress() internal view returns (address uniswapAddress) {
 | 
			
		||||
        return UNISWAP_EXCHANGE_FACTORY_ADDRESS;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Overridable way to get the `UniswapV2Router01` address.
 | 
			
		||||
    /// @return uniswapRouterAddress The `UniswapV2Router01` address.
 | 
			
		||||
    function _getUniswapV2Router01Address() internal view returns (address uniswapRouterAddress) {
 | 
			
		||||
        return UNISWAP_V2_ROUTER_01_ADDRESS;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev An overridable way to retrieve the Eth2Dai `MatchingMarket` contract.
 | 
			
		||||
    /// @return eth2daiAddress The Eth2Dai `MatchingMarket` contract.
 | 
			
		||||
    function _getEth2DaiAddress() internal view returns (address eth2daiAddress) {
 | 
			
		||||
        return ETH2DAI_ADDRESS;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev An overridable way to retrieve the `ERC20BridgeProxy` contract.
 | 
			
		||||
    /// @return erc20BridgeProxyAddress The `ERC20BridgeProxy` contract.
 | 
			
		||||
    function _getERC20BridgeProxyAddress() internal view returns (address erc20BridgeProxyAddress) {
 | 
			
		||||
        return ERC20_BRIDGE_PROXY_ADDRESS;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev An overridable way to retrieve the `Dai` contract.
 | 
			
		||||
    /// @return daiAddress The `Dai` contract.
 | 
			
		||||
    function _getDaiAddress() internal view returns (address daiAddress) {
 | 
			
		||||
        return DAI_ADDRESS;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev An overridable way to retrieve the `Chai` contract.
 | 
			
		||||
    /// @return chaiAddress The `Chai` contract.
 | 
			
		||||
    function _getChaiAddress() internal view returns (address chaiAddress) {
 | 
			
		||||
        return CHAI_ADDRESS;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev An overridable way to retrieve the 0x `DevUtils` contract address.
 | 
			
		||||
    /// @return devUtils The 0x `DevUtils` contract address.
 | 
			
		||||
    function _getDevUtilsAddress() internal view returns (address devUtils) {
 | 
			
		||||
        return DEV_UTILS_ADDRESS;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Overridable way to get the DyDx contract.
 | 
			
		||||
    /// @return exchange The DyDx exchange contract.
 | 
			
		||||
    function _getDydxAddress() internal view returns (address dydxAddress) {
 | 
			
		||||
        return DYDX_ADDRESS;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev An overridable way to retrieve the GST2 contract address.
 | 
			
		||||
    /// @return gst The GST contract.
 | 
			
		||||
    function _getGstAddress() internal view returns (address gst) {
 | 
			
		||||
        return GST_ADDRESS;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev An overridable way to retrieve the GST Collector address.
 | 
			
		||||
    /// @return collector The GST collector address.
 | 
			
		||||
    function _getGstCollectorAddress() internal view returns (address collector) {
 | 
			
		||||
        return GST_COLLECTOR_ADDRESS;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev An overridable way to retrieve the mStable mUSD address.
 | 
			
		||||
    /// @return musd The mStable mUSD address.
 | 
			
		||||
    function _getMUsdAddress() internal view returns (address musd) {
 | 
			
		||||
        return MUSD_ADDRESS;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev An overridable way to retrieve the Mooniswap registry address.
 | 
			
		||||
    /// @return registry The Mooniswap registry address.
 | 
			
		||||
    function _getMooniswapAddress() internal view returns (address) {
 | 
			
		||||
        return MOONISWAP_REGISTRY;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev An overridable way to retrieve the DODO Registry contract address.
 | 
			
		||||
    /// @return registry The DODO Registry contract address.
 | 
			
		||||
    function _getDODORegistryAddress() internal view returns (address) {
 | 
			
		||||
        return DODO_REGISTRY;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev An overridable way to retrieve the DODO Helper contract address.
 | 
			
		||||
    /// @return registry The DODO Helper contract address.
 | 
			
		||||
    function _getDODOHelperAddress() internal view returns (address) {
 | 
			
		||||
        return DODO_HELPER;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,46 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  Copyright 2019 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.5.9;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Utility library of inline functions on addresses
 | 
			
		||||
 */
 | 
			
		||||
library LibAddress {
 | 
			
		||||
    /**
 | 
			
		||||
     * Returns whether the target address is a contract
 | 
			
		||||
     * @dev This function will return false if invoked during the constructor of a contract,
 | 
			
		||||
     * as the code is not actually created until after the constructor finishes.
 | 
			
		||||
     * @param account address of the account to check
 | 
			
		||||
     * @return whether the target address is a contract
 | 
			
		||||
     */
 | 
			
		||||
    function isContract(address account) internal view returns (bool) {
 | 
			
		||||
        uint256 size;
 | 
			
		||||
        // XXX Currently there is no better way to check if there is a contract in an address
 | 
			
		||||
        // than to check the size of the code at that address.
 | 
			
		||||
        // See https://ethereum.stackexchange.com/a/14016/36603
 | 
			
		||||
        // for more details about how this works.
 | 
			
		||||
        // TODO Check this again before the Serenity release, because all addresses will be
 | 
			
		||||
        // contracts then.
 | 
			
		||||
        // solium-disable-next-line security/no-inline-assembly
 | 
			
		||||
        assembly {
 | 
			
		||||
            size := extcodesize(account)
 | 
			
		||||
        }
 | 
			
		||||
        return size > 0;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,153 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  Copyright 2019 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.5.9;
 | 
			
		||||
 | 
			
		||||
import "./LibAddressArrayRichErrors.sol";
 | 
			
		||||
import "./LibBytes.sol";
 | 
			
		||||
import "./LibRichErrors.sol";
 | 
			
		||||
 | 
			
		||||
library LibAddressArray {
 | 
			
		||||
    /// @dev Append a new address to an array of addresses.
 | 
			
		||||
    ///      The `addressArray` may need to be reallocated to make space
 | 
			
		||||
    ///      for the new address. Because of this we return the resulting
 | 
			
		||||
    ///      memory location of `addressArray`.
 | 
			
		||||
    /// @param addressArray Array of addresses.
 | 
			
		||||
    /// @param addressToAppend  Address to append.
 | 
			
		||||
    /// @return Array of addresses: [... addressArray, addressToAppend]
 | 
			
		||||
    function append(address[] memory addressArray, address addressToAppend) internal pure returns (address[] memory) {
 | 
			
		||||
        // Get stats on address array and free memory
 | 
			
		||||
        uint256 freeMemPtr = 0;
 | 
			
		||||
        uint256 addressArrayBeginPtr = 0;
 | 
			
		||||
        uint256 addressArrayEndPtr = 0;
 | 
			
		||||
        uint256 addressArrayLength = addressArray.length;
 | 
			
		||||
        uint256 addressArrayMemSizeInBytes = 32 + (32 * addressArrayLength);
 | 
			
		||||
        assembly {
 | 
			
		||||
            freeMemPtr := mload(0x40)
 | 
			
		||||
            addressArrayBeginPtr := addressArray
 | 
			
		||||
            addressArrayEndPtr := add(addressArray, addressArrayMemSizeInBytes)
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Cases for `freeMemPtr`:
 | 
			
		||||
        //  `freeMemPtr` == `addressArrayEndPtr`: Nothing occupies memory after `addressArray`
 | 
			
		||||
        //  `freeMemPtr` > `addressArrayEndPtr`: Some value occupies memory after `addressArray`
 | 
			
		||||
        //  `freeMemPtr` < `addressArrayEndPtr`: Memory has not been managed properly.
 | 
			
		||||
        if (freeMemPtr < addressArrayEndPtr) {
 | 
			
		||||
            LibRichErrors.rrevert(LibAddressArrayRichErrors.MismanagedMemoryError(freeMemPtr, addressArrayEndPtr));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // If free memory begins at the end of `addressArray`
 | 
			
		||||
        // then we can append `addressToAppend` directly.
 | 
			
		||||
        // Otherwise, we must copy the array to free memory
 | 
			
		||||
        // before appending new values to it.
 | 
			
		||||
        if (freeMemPtr > addressArrayEndPtr) {
 | 
			
		||||
            LibBytes.memCopy(freeMemPtr, addressArrayBeginPtr, addressArrayMemSizeInBytes);
 | 
			
		||||
            assembly {
 | 
			
		||||
                addressArray := freeMemPtr
 | 
			
		||||
                addressArrayBeginPtr := addressArray
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Append `addressToAppend`
 | 
			
		||||
        addressArrayLength += 1;
 | 
			
		||||
        addressArrayMemSizeInBytes += 32;
 | 
			
		||||
        addressArrayEndPtr = addressArrayBeginPtr + addressArrayMemSizeInBytes;
 | 
			
		||||
        freeMemPtr = addressArrayEndPtr;
 | 
			
		||||
        assembly {
 | 
			
		||||
            // Store new array length
 | 
			
		||||
            mstore(addressArray, addressArrayLength)
 | 
			
		||||
 | 
			
		||||
            // Update `freeMemPtr`
 | 
			
		||||
            mstore(0x40, freeMemPtr)
 | 
			
		||||
        }
 | 
			
		||||
        addressArray[addressArrayLength - 1] = addressToAppend;
 | 
			
		||||
        return addressArray;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Checks if an address array contains the target address.
 | 
			
		||||
    /// @param addressArray Array of addresses.
 | 
			
		||||
    /// @param target Address to search for in array.
 | 
			
		||||
    /// @return True if the addressArray contains the target.
 | 
			
		||||
    function contains(address[] memory addressArray, address target) internal pure returns (bool success) {
 | 
			
		||||
        assembly {
 | 
			
		||||
            // Calculate byte length of array
 | 
			
		||||
            let arrayByteLen := mul(mload(addressArray), 32)
 | 
			
		||||
            // Calculate beginning of array contents
 | 
			
		||||
            let arrayContentsStart := add(addressArray, 32)
 | 
			
		||||
            // Calclulate end of array contents
 | 
			
		||||
            let arrayContentsEnd := add(arrayContentsStart, arrayByteLen)
 | 
			
		||||
 | 
			
		||||
            // Loop through array
 | 
			
		||||
            for {
 | 
			
		||||
                let i := arrayContentsStart
 | 
			
		||||
            } lt(i, arrayContentsEnd) {
 | 
			
		||||
                i := add(i, 32)
 | 
			
		||||
            } {
 | 
			
		||||
                // Load array element
 | 
			
		||||
                let arrayElement := mload(i)
 | 
			
		||||
 | 
			
		||||
                // Return true if array element equals target
 | 
			
		||||
                if eq(target, arrayElement) {
 | 
			
		||||
                    // Set success to true
 | 
			
		||||
                    success := 1
 | 
			
		||||
                    // Break loop
 | 
			
		||||
                    i := arrayContentsEnd
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return success;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Finds the index of an address within an array.
 | 
			
		||||
    /// @param addressArray Array of addresses.
 | 
			
		||||
    /// @param target Address to search for in array.
 | 
			
		||||
    /// @return Existence and index of the target in the array.
 | 
			
		||||
    function indexOf(
 | 
			
		||||
        address[] memory addressArray,
 | 
			
		||||
        address target
 | 
			
		||||
    ) internal pure returns (bool success, uint256 index) {
 | 
			
		||||
        assembly {
 | 
			
		||||
            // Calculate byte length of array
 | 
			
		||||
            let arrayByteLen := mul(mload(addressArray), 32)
 | 
			
		||||
            // Calculate beginning of array contents
 | 
			
		||||
            let arrayContentsStart := add(addressArray, 32)
 | 
			
		||||
            // Calclulate end of array contents
 | 
			
		||||
            let arrayContentsEnd := add(arrayContentsStart, arrayByteLen)
 | 
			
		||||
 | 
			
		||||
            // Loop through array
 | 
			
		||||
            for {
 | 
			
		||||
                let i := arrayContentsStart
 | 
			
		||||
            } lt(i, arrayContentsEnd) {
 | 
			
		||||
                i := add(i, 32)
 | 
			
		||||
            } {
 | 
			
		||||
                // Load array element
 | 
			
		||||
                let arrayElement := mload(i)
 | 
			
		||||
 | 
			
		||||
                // Return true if array element equals target
 | 
			
		||||
                if eq(target, arrayElement) {
 | 
			
		||||
                    // Set success and index
 | 
			
		||||
                    success := 1
 | 
			
		||||
                    index := div(sub(i, arrayContentsStart), 32)
 | 
			
		||||
                    // Break loop
 | 
			
		||||
                    i := arrayContentsEnd
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        return (success, index);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,31 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  Copyright 2019 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.5.9;
 | 
			
		||||
 | 
			
		||||
library LibAddressArrayRichErrors {
 | 
			
		||||
    // bytes4(keccak256("MismanagedMemoryError(uint256,uint256)"))
 | 
			
		||||
    bytes4 internal constant MISMANAGED_MEMORY_ERROR_SELECTOR = 0x5fc83722;
 | 
			
		||||
 | 
			
		||||
    function MismanagedMemoryError(
 | 
			
		||||
        uint256 freeMemPtr,
 | 
			
		||||
        uint256 addressArrayEndPtr
 | 
			
		||||
    ) internal pure returns (bytes memory) {
 | 
			
		||||
        return abi.encodeWithSelector(MISMANAGED_MEMORY_ERROR_SELECTOR, freeMemPtr, addressArrayEndPtr);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,63 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  Copyright 2019 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.5.9;
 | 
			
		||||
 | 
			
		||||
library LibAuthorizableRichErrors {
 | 
			
		||||
    // bytes4(keccak256("AuthorizedAddressMismatchError(address,address)"))
 | 
			
		||||
    bytes4 internal constant AUTHORIZED_ADDRESS_MISMATCH_ERROR_SELECTOR = 0x140a84db;
 | 
			
		||||
 | 
			
		||||
    // bytes4(keccak256("IndexOutOfBoundsError(uint256,uint256)"))
 | 
			
		||||
    bytes4 internal constant INDEX_OUT_OF_BOUNDS_ERROR_SELECTOR = 0xe9f83771;
 | 
			
		||||
 | 
			
		||||
    // bytes4(keccak256("SenderNotAuthorizedError(address)"))
 | 
			
		||||
    bytes4 internal constant SENDER_NOT_AUTHORIZED_ERROR_SELECTOR = 0xb65a25b9;
 | 
			
		||||
 | 
			
		||||
    // bytes4(keccak256("TargetAlreadyAuthorizedError(address)"))
 | 
			
		||||
    bytes4 internal constant TARGET_ALREADY_AUTHORIZED_ERROR_SELECTOR = 0xde16f1a0;
 | 
			
		||||
 | 
			
		||||
    // bytes4(keccak256("TargetNotAuthorizedError(address)"))
 | 
			
		||||
    bytes4 internal constant TARGET_NOT_AUTHORIZED_ERROR_SELECTOR = 0xeb5108a2;
 | 
			
		||||
 | 
			
		||||
    // bytes4(keccak256("ZeroCantBeAuthorizedError()"))
 | 
			
		||||
    bytes internal constant ZERO_CANT_BE_AUTHORIZED_ERROR_BYTES = hex"57654fe4";
 | 
			
		||||
 | 
			
		||||
    function AuthorizedAddressMismatchError(address authorized, address target) internal pure returns (bytes memory) {
 | 
			
		||||
        return abi.encodeWithSelector(AUTHORIZED_ADDRESS_MISMATCH_ERROR_SELECTOR, authorized, target);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function IndexOutOfBoundsError(uint256 index, uint256 length) internal pure returns (bytes memory) {
 | 
			
		||||
        return abi.encodeWithSelector(INDEX_OUT_OF_BOUNDS_ERROR_SELECTOR, index, length);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function SenderNotAuthorizedError(address sender) internal pure returns (bytes memory) {
 | 
			
		||||
        return abi.encodeWithSelector(SENDER_NOT_AUTHORIZED_ERROR_SELECTOR, sender);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function TargetAlreadyAuthorizedError(address target) internal pure returns (bytes memory) {
 | 
			
		||||
        return abi.encodeWithSelector(TARGET_ALREADY_AUTHORIZED_ERROR_SELECTOR, target);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function TargetNotAuthorizedError(address target) internal pure returns (bytes memory) {
 | 
			
		||||
        return abi.encodeWithSelector(TARGET_NOT_AUTHORIZED_ERROR_SELECTOR, target);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function ZeroCantBeAuthorizedError() internal pure returns (bytes memory) {
 | 
			
		||||
        return ZERO_CANT_BE_AUTHORIZED_ERROR_BYTES;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,25 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  Copyright 2019 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.5.9;
 | 
			
		||||
 | 
			
		||||
contract LibEIP1271 {
 | 
			
		||||
    /// @dev Magic bytes returned by EIP1271 wallets on success.
 | 
			
		||||
    /// @return 0 Magic bytes.
 | 
			
		||||
    bytes4 public constant EIP1271_MAGIC_VALUE = 0x20c13b0b;
 | 
			
		||||
}
 | 
			
		||||
@@ -1,103 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  Copyright 2019 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.5.9;
 | 
			
		||||
 | 
			
		||||
library LibEIP712 {
 | 
			
		||||
    // Hash of the EIP712 Domain Separator Schema
 | 
			
		||||
    // keccak256(abi.encodePacked(
 | 
			
		||||
    //     "EIP712Domain(",
 | 
			
		||||
    //     "string name,",
 | 
			
		||||
    //     "string version,",
 | 
			
		||||
    //     "uint256 chainId,",
 | 
			
		||||
    //     "address verifyingContract",
 | 
			
		||||
    //     ")"
 | 
			
		||||
    // ))
 | 
			
		||||
    bytes32 internal constant _EIP712_DOMAIN_SEPARATOR_SCHEMA_HASH =
 | 
			
		||||
        0x8b73c3c69bb8fe3d512ecc4cf759cc79239f7b179b0ffacaa9a75d522b39400f;
 | 
			
		||||
 | 
			
		||||
    /// @dev Calculates a EIP712 domain separator.
 | 
			
		||||
    /// @param name The EIP712 domain name.
 | 
			
		||||
    /// @param version The EIP712 domain version.
 | 
			
		||||
    /// @param verifyingContract The EIP712 verifying contract.
 | 
			
		||||
    /// @return EIP712 domain separator.
 | 
			
		||||
    function hashEIP712Domain(
 | 
			
		||||
        string memory name,
 | 
			
		||||
        string memory version,
 | 
			
		||||
        uint256 chainId,
 | 
			
		||||
        address verifyingContract
 | 
			
		||||
    ) internal pure returns (bytes32 result) {
 | 
			
		||||
        bytes32 schemaHash = _EIP712_DOMAIN_SEPARATOR_SCHEMA_HASH;
 | 
			
		||||
 | 
			
		||||
        // Assembly for more efficient computing:
 | 
			
		||||
        // keccak256(abi.encodePacked(
 | 
			
		||||
        //     _EIP712_DOMAIN_SEPARATOR_SCHEMA_HASH,
 | 
			
		||||
        //     keccak256(bytes(name)),
 | 
			
		||||
        //     keccak256(bytes(version)),
 | 
			
		||||
        //     chainId,
 | 
			
		||||
        //     uint256(verifyingContract)
 | 
			
		||||
        // ))
 | 
			
		||||
 | 
			
		||||
        assembly {
 | 
			
		||||
            // Calculate hashes of dynamic data
 | 
			
		||||
            let nameHash := keccak256(add(name, 32), mload(name))
 | 
			
		||||
            let versionHash := keccak256(add(version, 32), mload(version))
 | 
			
		||||
 | 
			
		||||
            // Load free memory pointer
 | 
			
		||||
            let memPtr := mload(64)
 | 
			
		||||
 | 
			
		||||
            // Store params in memory
 | 
			
		||||
            mstore(memPtr, schemaHash)
 | 
			
		||||
            mstore(add(memPtr, 32), nameHash)
 | 
			
		||||
            mstore(add(memPtr, 64), versionHash)
 | 
			
		||||
            mstore(add(memPtr, 96), chainId)
 | 
			
		||||
            mstore(add(memPtr, 128), verifyingContract)
 | 
			
		||||
 | 
			
		||||
            // Compute hash
 | 
			
		||||
            result := keccak256(memPtr, 160)
 | 
			
		||||
        }
 | 
			
		||||
        return result;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Calculates EIP712 encoding for a hash struct with a given domain hash.
 | 
			
		||||
    /// @param eip712DomainHash Hash of the domain domain separator data, computed
 | 
			
		||||
    ///                         with getDomainHash().
 | 
			
		||||
    /// @param hashStruct The EIP712 hash struct.
 | 
			
		||||
    /// @return EIP712 hash applied to the given EIP712 Domain.
 | 
			
		||||
    function hashEIP712Message(bytes32 eip712DomainHash, bytes32 hashStruct) internal pure returns (bytes32 result) {
 | 
			
		||||
        // Assembly for more efficient computing:
 | 
			
		||||
        // keccak256(abi.encodePacked(
 | 
			
		||||
        //     EIP191_HEADER,
 | 
			
		||||
        //     EIP712_DOMAIN_HASH,
 | 
			
		||||
        //     hashStruct
 | 
			
		||||
        // ));
 | 
			
		||||
 | 
			
		||||
        assembly {
 | 
			
		||||
            // Load free memory pointer
 | 
			
		||||
            let memPtr := mload(64)
 | 
			
		||||
 | 
			
		||||
            mstore(memPtr, 0x1901000000000000000000000000000000000000000000000000000000000000) // EIP191 header
 | 
			
		||||
            mstore(add(memPtr, 2), eip712DomainHash) // EIP712 domain hash
 | 
			
		||||
            mstore(add(memPtr, 34), hashStruct) // Hash of struct
 | 
			
		||||
 | 
			
		||||
            // Compute hash
 | 
			
		||||
            result := keccak256(memPtr, 66)
 | 
			
		||||
        }
 | 
			
		||||
        return result;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,96 +0,0 @@
 | 
			
		||||
pragma solidity ^0.5.9;
 | 
			
		||||
 | 
			
		||||
import "./LibSafeMath.sol";
 | 
			
		||||
 | 
			
		||||
library LibFractions {
 | 
			
		||||
    using LibSafeMath for uint256;
 | 
			
		||||
 | 
			
		||||
    /// @dev Safely adds two fractions `n1/d1 + n2/d2`
 | 
			
		||||
    /// @param n1 numerator of `1`
 | 
			
		||||
    /// @param d1 denominator of `1`
 | 
			
		||||
    /// @param n2 numerator of `2`
 | 
			
		||||
    /// @param d2 denominator of `2`
 | 
			
		||||
    /// @return numerator Numerator of sum
 | 
			
		||||
    /// @return denominator Denominator of sum
 | 
			
		||||
    function add(
 | 
			
		||||
        uint256 n1,
 | 
			
		||||
        uint256 d1,
 | 
			
		||||
        uint256 n2,
 | 
			
		||||
        uint256 d2
 | 
			
		||||
    ) internal pure returns (uint256 numerator, uint256 denominator) {
 | 
			
		||||
        if (n1 == 0) {
 | 
			
		||||
            return (numerator = n2, denominator = d2);
 | 
			
		||||
        }
 | 
			
		||||
        if (n2 == 0) {
 | 
			
		||||
            return (numerator = n1, denominator = d1);
 | 
			
		||||
        }
 | 
			
		||||
        numerator = n1.safeMul(d2).safeAdd(n2.safeMul(d1));
 | 
			
		||||
        denominator = d1.safeMul(d2);
 | 
			
		||||
        return (numerator, denominator);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Rescales a fraction to prevent overflows during addition if either
 | 
			
		||||
    ///      the numerator or the denominator are > `maxValue`.
 | 
			
		||||
    /// @param numerator The numerator.
 | 
			
		||||
    /// @param denominator The denominator.
 | 
			
		||||
    /// @param maxValue The maximum value allowed for both the numerator and
 | 
			
		||||
    ///        denominator.
 | 
			
		||||
    /// @return scaledNumerator The rescaled numerator.
 | 
			
		||||
    /// @return scaledDenominator The rescaled denominator.
 | 
			
		||||
    function normalize(
 | 
			
		||||
        uint256 numerator,
 | 
			
		||||
        uint256 denominator,
 | 
			
		||||
        uint256 maxValue
 | 
			
		||||
    ) internal pure returns (uint256 scaledNumerator, uint256 scaledDenominator) {
 | 
			
		||||
        // If either the numerator or the denominator are > `maxValue`,
 | 
			
		||||
        // re-scale them by `maxValue` to prevent overflows in future operations.
 | 
			
		||||
        if (numerator > maxValue || denominator > maxValue) {
 | 
			
		||||
            uint256 rescaleBase = numerator >= denominator ? numerator : denominator;
 | 
			
		||||
            rescaleBase = rescaleBase.safeDiv(maxValue);
 | 
			
		||||
            scaledNumerator = numerator.safeDiv(rescaleBase);
 | 
			
		||||
            scaledDenominator = denominator.safeDiv(rescaleBase);
 | 
			
		||||
        } else {
 | 
			
		||||
            scaledNumerator = numerator;
 | 
			
		||||
            scaledDenominator = denominator;
 | 
			
		||||
        }
 | 
			
		||||
        return (scaledNumerator, scaledDenominator);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Rescales a fraction to prevent overflows during addition if either
 | 
			
		||||
    ///      the numerator or the denominator are > 2 ** 127.
 | 
			
		||||
    /// @param numerator The numerator.
 | 
			
		||||
    /// @param denominator The denominator.
 | 
			
		||||
    /// @return scaledNumerator The rescaled numerator.
 | 
			
		||||
    /// @return scaledDenominator The rescaled denominator.
 | 
			
		||||
    function normalize(
 | 
			
		||||
        uint256 numerator,
 | 
			
		||||
        uint256 denominator
 | 
			
		||||
    ) internal pure returns (uint256 scaledNumerator, uint256 scaledDenominator) {
 | 
			
		||||
        return normalize(numerator, denominator, 2 ** 127);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Safely scales the difference between two fractions.
 | 
			
		||||
    /// @param n1 numerator of `1`
 | 
			
		||||
    /// @param d1 denominator of `1`
 | 
			
		||||
    /// @param n2 numerator of `2`
 | 
			
		||||
    /// @param d2 denominator of `2`
 | 
			
		||||
    /// @param s scalar to multiply by difference.
 | 
			
		||||
    /// @return result `s * (n1/d1 - n2/d2)`.
 | 
			
		||||
    function scaleDifference(
 | 
			
		||||
        uint256 n1,
 | 
			
		||||
        uint256 d1,
 | 
			
		||||
        uint256 n2,
 | 
			
		||||
        uint256 d2,
 | 
			
		||||
        uint256 s
 | 
			
		||||
    ) internal pure returns (uint256 result) {
 | 
			
		||||
        if (s == 0) {
 | 
			
		||||
            return 0;
 | 
			
		||||
        }
 | 
			
		||||
        if (n2 == 0) {
 | 
			
		||||
            return result = s.safeMul(n1).safeDiv(d1);
 | 
			
		||||
        }
 | 
			
		||||
        uint256 numerator = n1.safeMul(d2).safeSub(n2.safeMul(d1));
 | 
			
		||||
        uint256 tmp = numerator.safeDiv(d2);
 | 
			
		||||
        return s.safeMul(tmp).safeDiv(d1);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,174 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  Copyright 2019 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.5.9;
 | 
			
		||||
 | 
			
		||||
import "./LibSafeMath.sol";
 | 
			
		||||
import "./LibRichErrors.sol";
 | 
			
		||||
import "./LibMathRichErrors.sol";
 | 
			
		||||
 | 
			
		||||
library LibMath {
 | 
			
		||||
    using LibSafeMath for uint256;
 | 
			
		||||
 | 
			
		||||
    /// @dev Calculates partial value given a numerator and denominator rounded down.
 | 
			
		||||
    ///      Reverts if rounding error is >= 0.1%
 | 
			
		||||
    /// @param numerator Numerator.
 | 
			
		||||
    /// @param denominator Denominator.
 | 
			
		||||
    /// @param target Value to calculate partial of.
 | 
			
		||||
    /// @return Partial value of target rounded down.
 | 
			
		||||
    function safeGetPartialAmountFloor(
 | 
			
		||||
        uint256 numerator,
 | 
			
		||||
        uint256 denominator,
 | 
			
		||||
        uint256 target
 | 
			
		||||
    ) internal pure returns (uint256 partialAmount) {
 | 
			
		||||
        if (isRoundingErrorFloor(numerator, denominator, target)) {
 | 
			
		||||
            LibRichErrors.rrevert(LibMathRichErrors.RoundingError(numerator, denominator, target));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        partialAmount = numerator.safeMul(target).safeDiv(denominator);
 | 
			
		||||
        return partialAmount;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Calculates partial value given a numerator and denominator rounded down.
 | 
			
		||||
    ///      Reverts if rounding error is >= 0.1%
 | 
			
		||||
    /// @param numerator Numerator.
 | 
			
		||||
    /// @param denominator Denominator.
 | 
			
		||||
    /// @param target Value to calculate partial of.
 | 
			
		||||
    /// @return Partial value of target rounded up.
 | 
			
		||||
    function safeGetPartialAmountCeil(
 | 
			
		||||
        uint256 numerator,
 | 
			
		||||
        uint256 denominator,
 | 
			
		||||
        uint256 target
 | 
			
		||||
    ) internal pure returns (uint256 partialAmount) {
 | 
			
		||||
        if (isRoundingErrorCeil(numerator, denominator, target)) {
 | 
			
		||||
            LibRichErrors.rrevert(LibMathRichErrors.RoundingError(numerator, denominator, target));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // safeDiv computes `floor(a / b)`. We use the identity (a, b integer):
 | 
			
		||||
        //       ceil(a / b) = floor((a + b - 1) / b)
 | 
			
		||||
        // To implement `ceil(a / b)` using safeDiv.
 | 
			
		||||
        partialAmount = numerator.safeMul(target).safeAdd(denominator.safeSub(1)).safeDiv(denominator);
 | 
			
		||||
 | 
			
		||||
        return partialAmount;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Calculates partial value given a numerator and denominator rounded down.
 | 
			
		||||
    /// @param numerator Numerator.
 | 
			
		||||
    /// @param denominator Denominator.
 | 
			
		||||
    /// @param target Value to calculate partial of.
 | 
			
		||||
    /// @return Partial value of target rounded down.
 | 
			
		||||
    function getPartialAmountFloor(
 | 
			
		||||
        uint256 numerator,
 | 
			
		||||
        uint256 denominator,
 | 
			
		||||
        uint256 target
 | 
			
		||||
    ) internal pure returns (uint256 partialAmount) {
 | 
			
		||||
        partialAmount = numerator.safeMul(target).safeDiv(denominator);
 | 
			
		||||
        return partialAmount;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Calculates partial value given a numerator and denominator rounded down.
 | 
			
		||||
    /// @param numerator Numerator.
 | 
			
		||||
    /// @param denominator Denominator.
 | 
			
		||||
    /// @param target Value to calculate partial of.
 | 
			
		||||
    /// @return Partial value of target rounded up.
 | 
			
		||||
    function getPartialAmountCeil(
 | 
			
		||||
        uint256 numerator,
 | 
			
		||||
        uint256 denominator,
 | 
			
		||||
        uint256 target
 | 
			
		||||
    ) internal pure returns (uint256 partialAmount) {
 | 
			
		||||
        // safeDiv computes `floor(a / b)`. We use the identity (a, b integer):
 | 
			
		||||
        //       ceil(a / b) = floor((a + b - 1) / b)
 | 
			
		||||
        // To implement `ceil(a / b)` using safeDiv.
 | 
			
		||||
        partialAmount = numerator.safeMul(target).safeAdd(denominator.safeSub(1)).safeDiv(denominator);
 | 
			
		||||
 | 
			
		||||
        return partialAmount;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Checks if rounding error >= 0.1% when rounding down.
 | 
			
		||||
    /// @param numerator Numerator.
 | 
			
		||||
    /// @param denominator Denominator.
 | 
			
		||||
    /// @param target Value to multiply with numerator/denominator.
 | 
			
		||||
    /// @return Rounding error is present.
 | 
			
		||||
    function isRoundingErrorFloor(
 | 
			
		||||
        uint256 numerator,
 | 
			
		||||
        uint256 denominator,
 | 
			
		||||
        uint256 target
 | 
			
		||||
    ) internal pure returns (bool isError) {
 | 
			
		||||
        if (denominator == 0) {
 | 
			
		||||
            LibRichErrors.rrevert(LibMathRichErrors.DivisionByZeroError());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // The absolute rounding error is the difference between the rounded
 | 
			
		||||
        // value and the ideal value. The relative rounding error is the
 | 
			
		||||
        // absolute rounding error divided by the absolute value of the
 | 
			
		||||
        // ideal value. This is undefined when the ideal value is zero.
 | 
			
		||||
        //
 | 
			
		||||
        // The ideal value is `numerator * target / denominator`.
 | 
			
		||||
        // Let's call `numerator * target % denominator` the remainder.
 | 
			
		||||
        // The absolute error is `remainder / denominator`.
 | 
			
		||||
        //
 | 
			
		||||
        // When the ideal value is zero, we require the absolute error to
 | 
			
		||||
        // be zero. Fortunately, this is always the case. The ideal value is
 | 
			
		||||
        // zero iff `numerator == 0` and/or `target == 0`. In this case the
 | 
			
		||||
        // remainder and absolute error are also zero.
 | 
			
		||||
        if (target == 0 || numerator == 0) {
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Otherwise, we want the relative rounding error to be strictly
 | 
			
		||||
        // less than 0.1%.
 | 
			
		||||
        // The relative error is `remainder / (numerator * target)`.
 | 
			
		||||
        // We want the relative error less than 1 / 1000:
 | 
			
		||||
        //        remainder / (numerator * denominator)  <  1 / 1000
 | 
			
		||||
        // or equivalently:
 | 
			
		||||
        //        1000 * remainder  <  numerator * target
 | 
			
		||||
        // so we have a rounding error iff:
 | 
			
		||||
        //        1000 * remainder  >=  numerator * target
 | 
			
		||||
        uint256 remainder = mulmod(target, numerator, denominator);
 | 
			
		||||
        isError = remainder.safeMul(1000) >= numerator.safeMul(target);
 | 
			
		||||
        return isError;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Checks if rounding error >= 0.1% when rounding up.
 | 
			
		||||
    /// @param numerator Numerator.
 | 
			
		||||
    /// @param denominator Denominator.
 | 
			
		||||
    /// @param target Value to multiply with numerator/denominator.
 | 
			
		||||
    /// @return Rounding error is present.
 | 
			
		||||
    function isRoundingErrorCeil(
 | 
			
		||||
        uint256 numerator,
 | 
			
		||||
        uint256 denominator,
 | 
			
		||||
        uint256 target
 | 
			
		||||
    ) internal pure returns (bool isError) {
 | 
			
		||||
        if (denominator == 0) {
 | 
			
		||||
            LibRichErrors.rrevert(LibMathRichErrors.DivisionByZeroError());
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // See the comments in `isRoundingError`.
 | 
			
		||||
        if (target == 0 || numerator == 0) {
 | 
			
		||||
            // When either is zero, the ideal value and rounded value are zero
 | 
			
		||||
            // and there is no rounding error. (Although the relative error
 | 
			
		||||
            // is undefined.)
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
        // Compute remainder as before
 | 
			
		||||
        uint256 remainder = mulmod(target, numerator, denominator);
 | 
			
		||||
        remainder = denominator.safeSub(remainder) % denominator;
 | 
			
		||||
        isError = remainder.safeMul(1000) >= numerator.safeMul(target);
 | 
			
		||||
        return isError;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,21 +0,0 @@
 | 
			
		||||
pragma solidity ^0.5.9;
 | 
			
		||||
 | 
			
		||||
library LibMathRichErrors {
 | 
			
		||||
    // bytes4(keccak256("DivisionByZeroError()"))
 | 
			
		||||
    bytes internal constant DIVISION_BY_ZERO_ERROR = hex"a791837c";
 | 
			
		||||
 | 
			
		||||
    // bytes4(keccak256("RoundingError(uint256,uint256,uint256)"))
 | 
			
		||||
    bytes4 internal constant ROUNDING_ERROR_SELECTOR = 0x339f3de2;
 | 
			
		||||
 | 
			
		||||
    function DivisionByZeroError() internal pure returns (bytes memory) {
 | 
			
		||||
        return DIVISION_BY_ZERO_ERROR;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function RoundingError(
 | 
			
		||||
        uint256 numerator,
 | 
			
		||||
        uint256 denominator,
 | 
			
		||||
        uint256 target
 | 
			
		||||
    ) internal pure returns (bytes memory) {
 | 
			
		||||
        return abi.encodeWithSelector(ROUNDING_ERROR_SELECTOR, numerator, denominator, target);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,74 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  Copyright 2019 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.5.9;
 | 
			
		||||
 | 
			
		||||
import "./ReentrancyGuard.sol";
 | 
			
		||||
 | 
			
		||||
contract Refundable is ReentrancyGuard {
 | 
			
		||||
    // This bool is used by the refund modifier to allow for lazily evaluated refunds.
 | 
			
		||||
    bool internal _shouldNotRefund;
 | 
			
		||||
 | 
			
		||||
    modifier refundFinalBalance() {
 | 
			
		||||
        _;
 | 
			
		||||
        _refundNonZeroBalanceIfEnabled();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    modifier refundFinalBalanceNoReentry() {
 | 
			
		||||
        _lockMutexOrThrowIfAlreadyLocked();
 | 
			
		||||
        _;
 | 
			
		||||
        _refundNonZeroBalanceIfEnabled();
 | 
			
		||||
        _unlockMutex();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    modifier disableRefundUntilEnd() {
 | 
			
		||||
        if (_areRefundsDisabled()) {
 | 
			
		||||
            _;
 | 
			
		||||
        } else {
 | 
			
		||||
            _disableRefund();
 | 
			
		||||
            _;
 | 
			
		||||
            _enableAndRefundNonZeroBalance();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function _refundNonZeroBalanceIfEnabled() internal {
 | 
			
		||||
        if (!_areRefundsDisabled()) {
 | 
			
		||||
            _refundNonZeroBalance();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function _refundNonZeroBalance() internal {
 | 
			
		||||
        uint256 balance = address(this).balance;
 | 
			
		||||
        if (balance > 0) {
 | 
			
		||||
            msg.sender.transfer(balance);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function _disableRefund() internal {
 | 
			
		||||
        _shouldNotRefund = true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function _enableAndRefundNonZeroBalance() internal {
 | 
			
		||||
        _shouldNotRefund = false;
 | 
			
		||||
        _refundNonZeroBalance();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function _areRefundsDisabled() internal view returns (bool) {
 | 
			
		||||
        return _shouldNotRefund;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,46 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  Copyright 2019 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.5.9;
 | 
			
		||||
 | 
			
		||||
import "./IOwnable.sol";
 | 
			
		||||
 | 
			
		||||
contract IAuthorizable is IOwnable {
 | 
			
		||||
    // Event logged when a new address is authorized.
 | 
			
		||||
    event AuthorizedAddressAdded(address indexed target, address indexed caller);
 | 
			
		||||
 | 
			
		||||
    // Event logged when a currently authorized address is unauthorized.
 | 
			
		||||
    event AuthorizedAddressRemoved(address indexed target, address indexed caller);
 | 
			
		||||
 | 
			
		||||
    /// @dev Authorizes an address.
 | 
			
		||||
    /// @param target Address to authorize.
 | 
			
		||||
    function addAuthorizedAddress(address target) external;
 | 
			
		||||
 | 
			
		||||
    /// @dev Removes authorizion of an address.
 | 
			
		||||
    /// @param target Address to remove authorization from.
 | 
			
		||||
    function removeAuthorizedAddress(address target) external;
 | 
			
		||||
 | 
			
		||||
    /// @dev Removes authorizion of an address.
 | 
			
		||||
    /// @param target Address to remove authorization from.
 | 
			
		||||
    /// @param index Index of target in authorities array.
 | 
			
		||||
    function removeAuthorizedAddressAtIndex(address target, uint256 index) external;
 | 
			
		||||
 | 
			
		||||
    /// @dev Gets all authorized addresses.
 | 
			
		||||
    /// @return Array of authorized addresses.
 | 
			
		||||
    function getAuthorizedAddresses() external view returns (address[] memory);
 | 
			
		||||
}
 | 
			
		||||
@@ -1,50 +0,0 @@
 | 
			
		||||
// SPDX-License-Identifier: Apache-2.0
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  Copyright 2020 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;
 | 
			
		||||
 | 
			
		||||
import "./errors/LibReentrancyGuardRichErrorsV06.sol";
 | 
			
		||||
import "./errors/LibRichErrorsV06.sol";
 | 
			
		||||
 | 
			
		||||
contract ReentrancyGuardV06 {
 | 
			
		||||
    // Locked state of mutex.
 | 
			
		||||
    bool private _locked = false;
 | 
			
		||||
 | 
			
		||||
    /// @dev Functions with this modifer cannot be reentered. The mutex will be locked
 | 
			
		||||
    ///      before function execution and unlocked after.
 | 
			
		||||
    modifier nonReentrant() {
 | 
			
		||||
        _lockMutexOrThrowIfAlreadyLocked();
 | 
			
		||||
        _;
 | 
			
		||||
        _unlockMutex();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function _lockMutexOrThrowIfAlreadyLocked() internal {
 | 
			
		||||
        // Ensure mutex is unlocked.
 | 
			
		||||
        if (_locked) {
 | 
			
		||||
            LibRichErrorsV06.rrevert(LibReentrancyGuardRichErrorsV06.IllegalReentrancyError());
 | 
			
		||||
        }
 | 
			
		||||
        // Lock mutex.
 | 
			
		||||
        _locked = true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function _unlockMutex() internal {
 | 
			
		||||
        // Unlock mutex.
 | 
			
		||||
        _locked = false;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,25 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  Copyright 2019 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.5.9;
 | 
			
		||||
 | 
			
		||||
import "../src/Authorizable.sol";
 | 
			
		||||
 | 
			
		||||
contract TestAuthorizable is Authorizable {
 | 
			
		||||
    function onlyAuthorizedFn() external view onlyAuthorized {}
 | 
			
		||||
}
 | 
			
		||||
@@ -1,29 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  Copyright 2019 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.5.9;
 | 
			
		||||
 | 
			
		||||
import "../src/LibAddress.sol";
 | 
			
		||||
 | 
			
		||||
contract TestLibAddress {
 | 
			
		||||
    using LibAddress for address;
 | 
			
		||||
 | 
			
		||||
    function externalIsContract(address account) external view returns (bool) {
 | 
			
		||||
        return account.isContract();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,89 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  Copyright 2019 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.5.5;
 | 
			
		||||
 | 
			
		||||
import "../src/LibAddressArray.sol";
 | 
			
		||||
 | 
			
		||||
contract TestLibAddressArray {
 | 
			
		||||
    using LibAddressArray for address[];
 | 
			
		||||
 | 
			
		||||
    /// @dev Append a new address to an array of addresses.
 | 
			
		||||
    ///      The `addressArray` may need to be reallocated to make space
 | 
			
		||||
    ///      for the new address. Because of this we return the resulting
 | 
			
		||||
    ///      memory location of `addressArray`.
 | 
			
		||||
    /// @param addressArray Array of addresses.
 | 
			
		||||
    /// @param addressToAppend  Address to append.
 | 
			
		||||
    /// @return Array of addresses: [... addressArray, addressToAppend]
 | 
			
		||||
    function publicAppend(
 | 
			
		||||
        address[] memory addressArray,
 | 
			
		||||
        address addressToAppend
 | 
			
		||||
    ) public pure returns (address[] memory) {
 | 
			
		||||
        return addressArray.append(addressToAppend);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Moves the free memory pointer by `freeMemOffset` bytes,
 | 
			
		||||
    ///      then performs the append.
 | 
			
		||||
    ///      This tests the behavior of the address array being reallocated if
 | 
			
		||||
    ///      the memory immediately after the old array is claimed.
 | 
			
		||||
    /// @param addressArray Array of addresses.
 | 
			
		||||
    /// @param freeMemOffset Number of (signed) bytes to offset the free memory pointer (0x40).
 | 
			
		||||
    /// @param addressToAppend Address to append.
 | 
			
		||||
    /// @return The new address array.
 | 
			
		||||
    /// @return The memory address of the old address array.
 | 
			
		||||
    /// @return The memory address of the new address array.
 | 
			
		||||
    function testAppendRealloc(
 | 
			
		||||
        address[] memory addressArray,
 | 
			
		||||
        int256 freeMemOffset,
 | 
			
		||||
        address addressToAppend
 | 
			
		||||
    ) public pure returns (address[] memory result, uint256 oldArrayMemStart, uint256 newArrayMemStart) {
 | 
			
		||||
        assembly {
 | 
			
		||||
            // Remember the original memory address of the array.
 | 
			
		||||
            oldArrayMemStart := addressArray
 | 
			
		||||
            // Move the free memory pointer.
 | 
			
		||||
            mstore(0x40, add(mload(0x40), freeMemOffset))
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Call append.
 | 
			
		||||
        result = addressArray.append(addressToAppend);
 | 
			
		||||
 | 
			
		||||
        // Get the new array memory address.
 | 
			
		||||
        assembly {
 | 
			
		||||
            newArrayMemStart := result
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Checks if an address array contains the target address.
 | 
			
		||||
    /// @param addressArray Array of addresses.
 | 
			
		||||
    /// @param target Address to search for in array.
 | 
			
		||||
    /// @return True if the addressArray contains the target.
 | 
			
		||||
    function publicContains(address[] memory addressArray, address target) public pure returns (bool success) {
 | 
			
		||||
        return addressArray.contains(target);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Finds the index of an address within an array.
 | 
			
		||||
    /// @param addressArray Array of addresses.
 | 
			
		||||
    /// @param target Address to search for in array.
 | 
			
		||||
    /// @return Existence and index of the target in the array.
 | 
			
		||||
    function publicIndexOf(
 | 
			
		||||
        address[] memory addressArray,
 | 
			
		||||
        address target
 | 
			
		||||
    ) public pure returns (bool success, uint256 index) {
 | 
			
		||||
        (success, index) = addressArray.indexOf(target);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,36 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  Copyright 2019 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.5.9;
 | 
			
		||||
 | 
			
		||||
import "../src/LibEIP712.sol";
 | 
			
		||||
 | 
			
		||||
contract TestLibEIP712 {
 | 
			
		||||
    function externalHashEIP712DomainSeperator(
 | 
			
		||||
        string calldata name,
 | 
			
		||||
        string calldata version,
 | 
			
		||||
        uint256 chainid,
 | 
			
		||||
        address verifyingcontractaddress
 | 
			
		||||
    ) external pure returns (bytes32) {
 | 
			
		||||
        return LibEIP712.hashEIP712Domain(name, version, chainid, verifyingcontractaddress);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function externalHashEIP712Message(bytes32 eip712DomainHash, bytes32 hashStruct) external pure returns (bytes32) {
 | 
			
		||||
        return LibEIP712.hashEIP712Message(eip712DomainHash, hashStruct);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,104 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  Copyright 2019 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.5.9;
 | 
			
		||||
pragma experimental ABIEncoderV2;
 | 
			
		||||
 | 
			
		||||
import "../src/LibMath.sol";
 | 
			
		||||
 | 
			
		||||
contract TestLibMath {
 | 
			
		||||
    /// @dev Calculates partial value given a numerator and denominator.
 | 
			
		||||
    ///      Reverts if rounding error is >= 0.1%
 | 
			
		||||
    /// @param numerator Numerator.
 | 
			
		||||
    /// @param denominator Denominator.
 | 
			
		||||
    /// @param target Value to calculate partial of.
 | 
			
		||||
    /// @return Partial value of target.
 | 
			
		||||
    function safeGetPartialAmountFloor(
 | 
			
		||||
        uint256 numerator,
 | 
			
		||||
        uint256 denominator,
 | 
			
		||||
        uint256 target
 | 
			
		||||
    ) public pure returns (uint256 partialAmount) {
 | 
			
		||||
        return LibMath.safeGetPartialAmountFloor(numerator, denominator, target);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Calculates partial value given a numerator and denominator.
 | 
			
		||||
    ///      Reverts if rounding error is >= 0.1%
 | 
			
		||||
    /// @param numerator Numerator.
 | 
			
		||||
    /// @param denominator Denominator.
 | 
			
		||||
    /// @param target Value to calculate partial of.
 | 
			
		||||
    /// @return Partial value of target.
 | 
			
		||||
    function safeGetPartialAmountCeil(
 | 
			
		||||
        uint256 numerator,
 | 
			
		||||
        uint256 denominator,
 | 
			
		||||
        uint256 target
 | 
			
		||||
    ) public pure returns (uint256 partialAmount) {
 | 
			
		||||
        return LibMath.safeGetPartialAmountCeil(numerator, denominator, target);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Calculates partial value given a numerator and denominator.
 | 
			
		||||
    /// @param numerator Numerator.
 | 
			
		||||
    /// @param denominator Denominator.
 | 
			
		||||
    /// @param target Value to calculate partial of.
 | 
			
		||||
    /// @return Partial value of target.
 | 
			
		||||
    function getPartialAmountFloor(
 | 
			
		||||
        uint256 numerator,
 | 
			
		||||
        uint256 denominator,
 | 
			
		||||
        uint256 target
 | 
			
		||||
    ) public pure returns (uint256 partialAmount) {
 | 
			
		||||
        return LibMath.getPartialAmountFloor(numerator, denominator, target);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Calculates partial value given a numerator and denominator.
 | 
			
		||||
    /// @param numerator Numerator.
 | 
			
		||||
    /// @param denominator Denominator.
 | 
			
		||||
    /// @param target Value to calculate partial of.
 | 
			
		||||
    /// @return Partial value of target.
 | 
			
		||||
    function getPartialAmountCeil(
 | 
			
		||||
        uint256 numerator,
 | 
			
		||||
        uint256 denominator,
 | 
			
		||||
        uint256 target
 | 
			
		||||
    ) public pure returns (uint256 partialAmount) {
 | 
			
		||||
        return LibMath.getPartialAmountCeil(numerator, denominator, target);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Checks if rounding error >= 0.1%.
 | 
			
		||||
    /// @param numerator Numerator.
 | 
			
		||||
    /// @param denominator Denominator.
 | 
			
		||||
    /// @param target Value to multiply with numerator/denominator.
 | 
			
		||||
    /// @return Rounding error is present.
 | 
			
		||||
    function isRoundingErrorFloor(
 | 
			
		||||
        uint256 numerator,
 | 
			
		||||
        uint256 denominator,
 | 
			
		||||
        uint256 target
 | 
			
		||||
    ) public pure returns (bool isError) {
 | 
			
		||||
        return LibMath.isRoundingErrorFloor(numerator, denominator, target);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Checks if rounding error >= 0.1%.
 | 
			
		||||
    /// @param numerator Numerator.
 | 
			
		||||
    /// @param denominator Denominator.
 | 
			
		||||
    /// @param target Value to multiply with numerator/denominator.
 | 
			
		||||
    /// @return Rounding error is present.
 | 
			
		||||
    function isRoundingErrorCeil(
 | 
			
		||||
        uint256 numerator,
 | 
			
		||||
        uint256 denominator,
 | 
			
		||||
        uint256 target
 | 
			
		||||
    ) public pure returns (bool isError) {
 | 
			
		||||
        return LibMath.isRoundingErrorCeil(numerator, denominator, target);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,43 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  Copyright 2018 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.5.5;
 | 
			
		||||
 | 
			
		||||
import "./TestLogDecodingDownstream.sol";
 | 
			
		||||
 | 
			
		||||
contract TestLogDecoding {
 | 
			
		||||
    /// @dev arbitrary event; fields to not matter.
 | 
			
		||||
    event TestEvent(uint256 foo, bytes bar, string car);
 | 
			
		||||
 | 
			
		||||
    /// @dev Emits a local event
 | 
			
		||||
    function emitEvent() public {
 | 
			
		||||
        emit TestEvent(256, hex"1234", "4321");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Emits an event in a downstream contract
 | 
			
		||||
    function emitEventDownstream() public {
 | 
			
		||||
        TestLogDecodingDownstream testLogDecodingDownstream = new TestLogDecodingDownstream();
 | 
			
		||||
        ITestLogDecodingDownstream(testLogDecodingDownstream).emitEvent();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Emits a local event and a downstream event
 | 
			
		||||
    function emitEventsLocalAndDownstream() public {
 | 
			
		||||
        emitEvent();
 | 
			
		||||
        emitEventDownstream();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,37 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  Copyright 2018 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.5.5;
 | 
			
		||||
 | 
			
		||||
contract ITestLogDecodingDownstream {
 | 
			
		||||
    /// @dev Emits a local event
 | 
			
		||||
    function emitEvent() external;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
contract TestLogDecodingDownstream is ITestLogDecodingDownstream {
 | 
			
		||||
    /// @dev event with fields different than those in `TestLogDecoding.TestEvent`
 | 
			
		||||
    /// Note: do not include this in the interface
 | 
			
		||||
    /// For testing, we want to emit an event that is
 | 
			
		||||
    /// not known by the calling contract.
 | 
			
		||||
    event TestEvent2(uint256 lorem, string ipsum);
 | 
			
		||||
 | 
			
		||||
    /// @dev Emits a local event
 | 
			
		||||
    function emitEvent() external {
 | 
			
		||||
        emit TestEvent2(256, "4321");
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,49 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  Copyright 2019 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.5.9;
 | 
			
		||||
 | 
			
		||||
import "../src/Refundable.sol";
 | 
			
		||||
 | 
			
		||||
contract TestRefundable is Refundable {
 | 
			
		||||
    function refundNonZeroBalanceExternal() external payable {
 | 
			
		||||
        _refundNonZeroBalance();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function setShouldNotRefund(bool shouldNotRefundNew) external {
 | 
			
		||||
        _shouldNotRefund = shouldNotRefundNew;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function getShouldNotRefund() external view returns (bool) {
 | 
			
		||||
        return _shouldNotRefund;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function refundFinalBalanceFunction() public payable refundFinalBalance {}
 | 
			
		||||
 | 
			
		||||
    function disableRefundUntilEndFunction() public payable disableRefundUntilEnd {}
 | 
			
		||||
 | 
			
		||||
    function nestedDisableRefundUntilEndFunction() public payable disableRefundUntilEnd returns (uint256) {
 | 
			
		||||
        disableRefundUntilEndFunction();
 | 
			
		||||
        return address(this).balance;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function mixedRefundModifierFunction() public payable disableRefundUntilEnd returns (uint256) {
 | 
			
		||||
        refundFinalBalanceFunction();
 | 
			
		||||
        return address(this).balance;
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -1,154 +0,0 @@
 | 
			
		||||
/*
 | 
			
		||||
 | 
			
		||||
  Copyright 2019 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.5.9;
 | 
			
		||||
 | 
			
		||||
import "./TestRefundable.sol";
 | 
			
		||||
 | 
			
		||||
contract TestRefundableReceiver {
 | 
			
		||||
    /// @dev A payable fallback function is necessary to receive refunds from the `TestRefundable` contract.
 | 
			
		||||
    ///      This function ensures that zero value is not sent to the contract, which tests the feature of
 | 
			
		||||
    ///      of the `refundNonzeroBalance` that doesn't transfer if the balance is zero.
 | 
			
		||||
    function() external payable {
 | 
			
		||||
        // Ensure that a value of zero was not transferred to the contract.
 | 
			
		||||
        require(msg.value != 0, "Zero value should not be sent to this contract.");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev This function tests the behavior of the `refundNonzeroBalance` function by checking whether or
 | 
			
		||||
    ///      not the `callCounter` state variable changes after the `refundNonzeroBalance` is called.
 | 
			
		||||
    /// @param testRefundable The TestRefundable that should be tested against.
 | 
			
		||||
    function testRefundNonZeroBalance(TestRefundable testRefundable) external payable {
 | 
			
		||||
        // Call `refundNonzeroBalance()` and forward all of the eth sent to the contract.
 | 
			
		||||
        testRefundable.refundNonZeroBalanceExternal.value(msg.value)();
 | 
			
		||||
 | 
			
		||||
        // If the value sent was nonzero, a check that a refund was received will be executed. Otherwise, the fallback
 | 
			
		||||
        // function contains a check that will fail in the event that a value of zero was sent to the contract.
 | 
			
		||||
        if (msg.value > 0) {
 | 
			
		||||
            // Ensure that a full refund was provided to this contract.
 | 
			
		||||
            require(address(this).balance == msg.value, "A full refund was not provided by `refundNonzeroBalance`");
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev This function tests the behavior to a simple call to `refundFinalBalanceFunction`. This
 | 
			
		||||
    ///      test will verify that the correct refund was provided after the call (depending on whether
 | 
			
		||||
    ///      a refund should be provided), and it will ensure that the `shouldNotRefund` state variable
 | 
			
		||||
    ///      remains unaltered after the function call.
 | 
			
		||||
    /// @param testRefundable The TestRefundable that should be tested against.
 | 
			
		||||
    /// @param shouldNotRefund The value that shouldNotRefund should be set to before the call to TestRefundable.
 | 
			
		||||
    function testRefundFinalBalance(TestRefundable testRefundable, bool shouldNotRefund) external payable {
 | 
			
		||||
        // Set `shouldNotRefund` to the specified bool.
 | 
			
		||||
        testRefundable.setShouldNotRefund(shouldNotRefund);
 | 
			
		||||
 | 
			
		||||
        // Call `refundFinalBalanceFunction` and forward all value from the contract.
 | 
			
		||||
        testRefundable.refundFinalBalanceFunction.value(msg.value)();
 | 
			
		||||
 | 
			
		||||
        // Assert that the expected refunds happened and that the `shouldNotRefund` value was
 | 
			
		||||
        // set back to an unaltered state after the call.
 | 
			
		||||
        requireCorrectFinalBalancesAndState(testRefundable, shouldNotRefund);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev This function tests the behavior to a simple call to `disableRefundUntilEndFunction`. This
 | 
			
		||||
    ///      test will verify that the correct refund was provided after the call (depending on whether
 | 
			
		||||
    ///      a refund should be provided), and it will ensure that the `shouldNotRefund` state variable
 | 
			
		||||
    ///      remains unaltered after the function call.
 | 
			
		||||
    /// @param testRefundable The TestRefundable that should be tested against.
 | 
			
		||||
    /// @param shouldNotRefund The value that shouldNotRefund should be set to before the call to TestRefundable.
 | 
			
		||||
    function testDisableRefundUntilEnd(TestRefundable testRefundable, bool shouldNotRefund) external payable {
 | 
			
		||||
        // Set `shouldNotRefund` to the specified bool.
 | 
			
		||||
        testRefundable.setShouldNotRefund(shouldNotRefund);
 | 
			
		||||
 | 
			
		||||
        // Call `disableRefundUntilEndFunction` and forward all value from the contract.
 | 
			
		||||
        testRefundable.disableRefundUntilEndFunction.value(msg.value)();
 | 
			
		||||
 | 
			
		||||
        // Assert that the expected refunds happened and that the `shouldNotRefund` value was
 | 
			
		||||
        // set back to an unaltered state after the call.
 | 
			
		||||
        requireCorrectFinalBalancesAndState(testRefundable, shouldNotRefund);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev This function tests the behavior of a call to a function that has the `disableRefundUntilEndFunction`.
 | 
			
		||||
    ///      The function that is called also uses the `disableRefundUntilEndFunction`, so this function's role is
 | 
			
		||||
    ///      to verify that both the inner and outer modifiers worked correctly.
 | 
			
		||||
    /// @param testRefundable The TestRefundable that should be tested against.
 | 
			
		||||
    /// @param shouldNotRefund The value that shouldNotRefund should be set to before the call to TestRefundable.
 | 
			
		||||
    function testNestedDisableRefundUntilEnd(TestRefundable testRefundable, bool shouldNotRefund) external payable {
 | 
			
		||||
        // Set `shouldNotRefund` to the specified bool.
 | 
			
		||||
        testRefundable.setShouldNotRefund(shouldNotRefund);
 | 
			
		||||
 | 
			
		||||
        // Call `nestedDisableRefundUntilEndFunction` and forward all value from the contract.
 | 
			
		||||
        uint256 balanceWithinCall = testRefundable.nestedDisableRefundUntilEndFunction.value(msg.value)();
 | 
			
		||||
 | 
			
		||||
        // Ensure that the balance within the call was equal to `msg.value` since the inner refund should
 | 
			
		||||
        // not have been triggered regardless of the value of `shouldNotRefund`.
 | 
			
		||||
        require(balanceWithinCall == msg.value, "Incorrect inner balance");
 | 
			
		||||
 | 
			
		||||
        // Assert that the expected refunds happened and that the `shouldNotRefund` value was
 | 
			
		||||
        // set back to an unaltered state after the call.
 | 
			
		||||
        requireCorrectFinalBalancesAndState(testRefundable, shouldNotRefund);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev This function tests the behavior of a call to a function that has the `disableRefundUntilEndFunction`.
 | 
			
		||||
    ///      The function that is called uses the `refundFinalBalanceFunction`, so this function's role is
 | 
			
		||||
    ///      to verify that both the inner and outer modifiers worked correctly.
 | 
			
		||||
    /// @param testRefundable The TestRefundable that should be tested against.
 | 
			
		||||
    /// @param shouldNotRefund The value that shouldNotRefund should be set to before the call to TestRefundable.
 | 
			
		||||
    function testMixedRefunds(TestRefundable testRefundable, bool shouldNotRefund) external payable {
 | 
			
		||||
        // Set `shouldNotRefund` to the specified bool.
 | 
			
		||||
        testRefundable.setShouldNotRefund(shouldNotRefund);
 | 
			
		||||
 | 
			
		||||
        // Call `mixedRefundModifierFunction` and forward all value from the contract.
 | 
			
		||||
        uint256 balanceWithinCall = testRefundable.mixedRefundModifierFunction.value(msg.value)();
 | 
			
		||||
 | 
			
		||||
        // Ensure that the balance within the call was equal to `msg.value` since the inner refund should
 | 
			
		||||
        // not have been triggered regardless of the value of `shouldNotRefund`.
 | 
			
		||||
        require(balanceWithinCall == msg.value, "Incorrect inner balance");
 | 
			
		||||
 | 
			
		||||
        // Assert that the expected refunds happened and that the `shouldNotRefund` value was
 | 
			
		||||
        // set back to an unaltered state after the call.
 | 
			
		||||
        requireCorrectFinalBalancesAndState(testRefundable, shouldNotRefund);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev This helper function verifies the final balances of this receiver contract and a specified
 | 
			
		||||
    ///      refundable contract and verifies that the `shouldNotRefund` value remains unaltered.
 | 
			
		||||
    /// @param testRefundable The TestRefundable that should be tested against.
 | 
			
		||||
    /// @param shouldNotRefund The value that shouldNotRefund was set to before the call to TestRefundable.
 | 
			
		||||
    function requireCorrectFinalBalancesAndState(TestRefundable testRefundable, bool shouldNotRefund) internal {
 | 
			
		||||
        // If `shouldNotRefund` was true, then this contract should have a balance of zero,
 | 
			
		||||
        // and `testRefundable` should have a balance of `msg.value`. Otherwise, the opposite
 | 
			
		||||
        // should be true.
 | 
			
		||||
        if (shouldNotRefund) {
 | 
			
		||||
            // Ensure that this contract's balance is zero.
 | 
			
		||||
            require(address(this).balance == 0, "Incorrect balance for TestRefundableReceiver");
 | 
			
		||||
 | 
			
		||||
            // Ensure that the other contract's balance is equal to `msg.value`.
 | 
			
		||||
            require(address(testRefundable).balance == msg.value, "Incorrect balance for TestRefundable");
 | 
			
		||||
        } else {
 | 
			
		||||
            // Ensure that this contract's balance is `msg.value`.
 | 
			
		||||
            require(address(this).balance == msg.value, "Incorrect balance for TestRefundableReceiver");
 | 
			
		||||
 | 
			
		||||
            // Ensure that the other contract's balance is equal to zero.
 | 
			
		||||
            require(address(testRefundable).balance == 0, "Incorrect balance for TestRefundable");
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Ensure that `shouldNotRefund` in TestRefundable is set to the parameter `shouldNotRefund`
 | 
			
		||||
        // after the call (i.e. the value didn't change during the function call).
 | 
			
		||||
        require(testRefundable.getShouldNotRefund() == shouldNotRefund, "Incorrect shouldNotRefund value");
 | 
			
		||||
 | 
			
		||||
        // Drain the contract of funds so that subsequent tests don't have to account for leftover ether.
 | 
			
		||||
        msg.sender.transfer(address(this).balance);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -30,9 +30,9 @@
 | 
			
		||||
        "contracts:copy": "contracts-gen copy"
 | 
			
		||||
    },
 | 
			
		||||
    "config": {
 | 
			
		||||
        "publicInterfaceContracts": "Authorizable,IAuthorizable,IOwnable,LibAddress,LibAddressArray,LibAddressArrayRichErrors,LibAuthorizableRichErrors,LibBytes,LibBytesRichErrors,LibEIP1271,LibEIP712,LibFractions,LibOwnableRichErrors,LibReentrancyGuardRichErrors,LibRichErrors,LibMath,LibMathRichErrors,LibSafeMath,LibSafeMathRichErrors,Ownable,ReentrancyGuard,Refundable",
 | 
			
		||||
        "publicInterfaceContracts": "IOwnable,LibBytes,LibBytesRichErrors,LibOwnableRichErrors,LibReentrancyGuardRichErrors,LibRichErrors,LibSafeMath,LibSafeMathRichErrors,Ownable,ReentrancyGuard",
 | 
			
		||||
        "abis:comment": "This list is auto-generated by contracts-gen. Don't edit manually.",
 | 
			
		||||
        "abis": "./test/generated-artifacts/@(Authorizable|AuthorizableV06|AuthorizableV08|D18|DeploymentConstants|IAuthorizable|IAuthorizableV06|IAuthorizableV08|IOwnable|IOwnableV06|IOwnableV08|LibAddress|LibAddressArray|LibAddressArrayRichErrors|LibAuthorizableRichErrors|LibAuthorizableRichErrorsV06|LibAuthorizableRichErrorsV08|LibBytes|LibBytesRichErrors|LibBytesRichErrorsV06|LibBytesRichErrorsV08|LibBytesV06|LibBytesV08|LibEIP1271|LibEIP712|LibFractions|LibMath|LibMathRichErrors|LibMathRichErrorsV06|LibMathRichErrorsV08|LibMathV06|LibMathV08|LibOwnableRichErrors|LibOwnableRichErrorsV06|LibOwnableRichErrorsV08|LibReentrancyGuardRichErrors|LibReentrancyGuardRichErrorsV06|LibReentrancyGuardRichErrorsV08|LibRichErrors|LibRichErrorsV06|LibRichErrorsV08|LibSafeMath|LibSafeMathRichErrors|LibSafeMathRichErrorsV06|LibSafeMathRichErrorsV08|LibSafeMathV06|Ownable|OwnableV06|OwnableV08|ReentrancyGuard|ReentrancyGuardV06|ReentrancyGuardV08|Refundable|TestAuthorizable|TestLibAddress|TestLibAddressArray|TestLibBytes|TestLibEIP712|TestLibMath|TestLibRichErrors|TestLibSafeMath|TestLogDecoding|TestLogDecodingDownstream|TestOwnable|TestReentrancyGuard|TestRefundable|TestRefundableReceiver).json"
 | 
			
		||||
        "abis": "./test/generated-artifacts/@(AuthorizableV06|AuthorizableV08|IAuthorizableV06|IAuthorizableV08|IOwnable|IOwnableV06|IOwnableV08|LibAuthorizableRichErrorsV06|LibAuthorizableRichErrorsV08|LibBytes|LibBytesRichErrors|LibBytesRichErrorsV06|LibBytesRichErrorsV08|LibBytesV06|LibBytesV08|LibMathRichErrorsV06|LibMathRichErrorsV08|LibMathV06|LibMathV08|LibOwnableRichErrors|LibOwnableRichErrorsV06|LibOwnableRichErrorsV08|LibReentrancyGuardRichErrors|LibReentrancyGuardRichErrorsV06|LibReentrancyGuardRichErrorsV08|LibRichErrors|LibRichErrorsV06|LibRichErrorsV08|LibSafeMath|LibSafeMathRichErrors|LibSafeMathRichErrorsV06|LibSafeMathRichErrorsV08|LibSafeMathV06|Ownable|OwnableV06|OwnableV08|ReentrancyGuard|ReentrancyGuardV08|TestLibBytes|TestLibRichErrors|TestLibSafeMath|TestOwnable|TestReentrancyGuard).json"
 | 
			
		||||
    },
 | 
			
		||||
    "repository": {
 | 
			
		||||
        "type": "git",
 | 
			
		||||
 
 | 
			
		||||
@@ -5,20 +5,9 @@
 | 
			
		||||
 */
 | 
			
		||||
import { ContractArtifact } from 'ethereum-types';
 | 
			
		||||
 | 
			
		||||
import * as Authorizable from '../generated-artifacts/Authorizable.json';
 | 
			
		||||
import * as IAuthorizable from '../generated-artifacts/IAuthorizable.json';
 | 
			
		||||
import * as IOwnable from '../generated-artifacts/IOwnable.json';
 | 
			
		||||
import * as LibAddress from '../generated-artifacts/LibAddress.json';
 | 
			
		||||
import * as LibAddressArray from '../generated-artifacts/LibAddressArray.json';
 | 
			
		||||
import * as LibAddressArrayRichErrors from '../generated-artifacts/LibAddressArrayRichErrors.json';
 | 
			
		||||
import * as LibAuthorizableRichErrors from '../generated-artifacts/LibAuthorizableRichErrors.json';
 | 
			
		||||
import * as LibBytes from '../generated-artifacts/LibBytes.json';
 | 
			
		||||
import * as LibBytesRichErrors from '../generated-artifacts/LibBytesRichErrors.json';
 | 
			
		||||
import * as LibEIP1271 from '../generated-artifacts/LibEIP1271.json';
 | 
			
		||||
import * as LibEIP712 from '../generated-artifacts/LibEIP712.json';
 | 
			
		||||
import * as LibFractions from '../generated-artifacts/LibFractions.json';
 | 
			
		||||
import * as LibMath from '../generated-artifacts/LibMath.json';
 | 
			
		||||
import * as LibMathRichErrors from '../generated-artifacts/LibMathRichErrors.json';
 | 
			
		||||
import * as LibOwnableRichErrors from '../generated-artifacts/LibOwnableRichErrors.json';
 | 
			
		||||
import * as LibReentrancyGuardRichErrors from '../generated-artifacts/LibReentrancyGuardRichErrors.json';
 | 
			
		||||
import * as LibRichErrors from '../generated-artifacts/LibRichErrors.json';
 | 
			
		||||
@@ -26,28 +15,15 @@ import * as LibSafeMath from '../generated-artifacts/LibSafeMath.json';
 | 
			
		||||
import * as LibSafeMathRichErrors from '../generated-artifacts/LibSafeMathRichErrors.json';
 | 
			
		||||
import * as Ownable from '../generated-artifacts/Ownable.json';
 | 
			
		||||
import * as ReentrancyGuard from '../generated-artifacts/ReentrancyGuard.json';
 | 
			
		||||
import * as Refundable from '../generated-artifacts/Refundable.json';
 | 
			
		||||
export const artifacts = {
 | 
			
		||||
    Authorizable: Authorizable as ContractArtifact,
 | 
			
		||||
    IAuthorizable: IAuthorizable as ContractArtifact,
 | 
			
		||||
    IOwnable: IOwnable as ContractArtifact,
 | 
			
		||||
    LibAddress: LibAddress as ContractArtifact,
 | 
			
		||||
    LibAddressArray: LibAddressArray as ContractArtifact,
 | 
			
		||||
    LibAddressArrayRichErrors: LibAddressArrayRichErrors as ContractArtifact,
 | 
			
		||||
    LibAuthorizableRichErrors: LibAuthorizableRichErrors as ContractArtifact,
 | 
			
		||||
    LibBytes: LibBytes as ContractArtifact,
 | 
			
		||||
    LibBytesRichErrors: LibBytesRichErrors as ContractArtifact,
 | 
			
		||||
    LibEIP1271: LibEIP1271 as ContractArtifact,
 | 
			
		||||
    LibEIP712: LibEIP712 as ContractArtifact,
 | 
			
		||||
    LibFractions: LibFractions as ContractArtifact,
 | 
			
		||||
    LibOwnableRichErrors: LibOwnableRichErrors as ContractArtifact,
 | 
			
		||||
    LibReentrancyGuardRichErrors: LibReentrancyGuardRichErrors as ContractArtifact,
 | 
			
		||||
    LibRichErrors: LibRichErrors as ContractArtifact,
 | 
			
		||||
    LibMath: LibMath as ContractArtifact,
 | 
			
		||||
    LibMathRichErrors: LibMathRichErrors as ContractArtifact,
 | 
			
		||||
    LibSafeMath: LibSafeMath as ContractArtifact,
 | 
			
		||||
    LibSafeMathRichErrors: LibSafeMathRichErrors as ContractArtifact,
 | 
			
		||||
    Ownable: Ownable as ContractArtifact,
 | 
			
		||||
    ReentrancyGuard: ReentrancyGuard as ContractArtifact,
 | 
			
		||||
    Refundable: Refundable as ContractArtifact,
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -52,77 +52,3 @@ export function safeDiv(a: BigNumber, b: BigNumber): BigNumber {
 | 
			
		||||
    }
 | 
			
		||||
    return a.dividedToIntegerBy(b);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// LibMath
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Checks if rounding error >= 0.1% when rounding down.
 | 
			
		||||
 */
 | 
			
		||||
export function isRoundingErrorFloor(numerator: BigNumber, denominator: BigNumber, target: BigNumber): boolean {
 | 
			
		||||
    if (denominator.eq(0)) {
 | 
			
		||||
        throw new LibMathRevertErrors.DivisionByZeroError();
 | 
			
		||||
    }
 | 
			
		||||
    if (numerator.eq(0) || target.eq(0)) {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
    const remainder = numerator.times(target).mod(denominator);
 | 
			
		||||
    // Need to do this separately because solidity evaluates RHS of the comparison expression first.
 | 
			
		||||
    const rhs = safeMul(numerator, target);
 | 
			
		||||
    const lhs = safeMul(remainder, new BigNumber(1000));
 | 
			
		||||
    return lhs.gte(rhs);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Checks if rounding error >= 0.1% when rounding up.
 | 
			
		||||
 */
 | 
			
		||||
export function isRoundingErrorCeil(numerator: BigNumber, denominator: BigNumber, target: BigNumber): boolean {
 | 
			
		||||
    if (denominator.eq(0)) {
 | 
			
		||||
        throw new LibMathRevertErrors.DivisionByZeroError();
 | 
			
		||||
    }
 | 
			
		||||
    if (numerator.eq(0) || target.eq(0)) {
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
    let remainder = numerator.times(target).mod(denominator);
 | 
			
		||||
    remainder = safeSub(denominator, remainder).mod(denominator);
 | 
			
		||||
    // Need to do this separately because solidity evaluates RHS of the comparison expression first.
 | 
			
		||||
    const rhs = safeMul(numerator, target);
 | 
			
		||||
    const lhs = safeMul(remainder, new BigNumber(1000));
 | 
			
		||||
    return lhs.gte(rhs);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Calculates partial value given a numerator and denominator rounded down.
 | 
			
		||||
 *      Reverts if rounding error is >= 0.1%
 | 
			
		||||
 */
 | 
			
		||||
export function safeGetPartialAmountFloor(numerator: BigNumber, denominator: BigNumber, target: BigNumber): BigNumber {
 | 
			
		||||
    if (isRoundingErrorFloor(numerator, denominator, target)) {
 | 
			
		||||
        throw new LibMathRevertErrors.RoundingError(numerator, denominator, target);
 | 
			
		||||
    }
 | 
			
		||||
    return safeDiv(safeMul(numerator, target), denominator);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Calculates partial value given a numerator and denominator rounded down.
 | 
			
		||||
 *      Reverts if rounding error is >= 0.1%
 | 
			
		||||
 */
 | 
			
		||||
export function safeGetPartialAmountCeil(numerator: BigNumber, denominator: BigNumber, target: BigNumber): BigNumber {
 | 
			
		||||
    if (isRoundingErrorCeil(numerator, denominator, target)) {
 | 
			
		||||
        throw new LibMathRevertErrors.RoundingError(numerator, denominator, target);
 | 
			
		||||
    }
 | 
			
		||||
    return safeDiv(safeAdd(safeMul(numerator, target), safeSub(denominator, new BigNumber(1))), denominator);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Calculates partial value given a numerator and denominator rounded down.
 | 
			
		||||
 */
 | 
			
		||||
export function getPartialAmountFloor(numerator: BigNumber, denominator: BigNumber, target: BigNumber): BigNumber {
 | 
			
		||||
    return safeDiv(safeMul(numerator, target), denominator);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Calculates partial value given a numerator and denominator rounded down.
 | 
			
		||||
 */
 | 
			
		||||
export function getPartialAmountCeil(numerator: BigNumber, denominator: BigNumber, target: BigNumber): BigNumber {
 | 
			
		||||
    const sub = safeSub(denominator, new BigNumber(1)); // This is computed first to simulate Solidity's order of operations
 | 
			
		||||
    return safeDiv(safeAdd(safeMul(numerator, target), sub), denominator);
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -3,20 +3,9 @@
 | 
			
		||||
 * Warning: This file is auto-generated by contracts-gen. Don't edit manually.
 | 
			
		||||
 * -----------------------------------------------------------------------------
 | 
			
		||||
 */
 | 
			
		||||
export * from '../generated-wrappers/authorizable';
 | 
			
		||||
export * from '../generated-wrappers/i_authorizable';
 | 
			
		||||
export * from '../generated-wrappers/i_ownable';
 | 
			
		||||
export * from '../generated-wrappers/lib_address';
 | 
			
		||||
export * from '../generated-wrappers/lib_address_array';
 | 
			
		||||
export * from '../generated-wrappers/lib_address_array_rich_errors';
 | 
			
		||||
export * from '../generated-wrappers/lib_authorizable_rich_errors';
 | 
			
		||||
export * from '../generated-wrappers/lib_bytes';
 | 
			
		||||
export * from '../generated-wrappers/lib_bytes_rich_errors';
 | 
			
		||||
export * from '../generated-wrappers/lib_e_i_p1271';
 | 
			
		||||
export * from '../generated-wrappers/lib_e_i_p712';
 | 
			
		||||
export * from '../generated-wrappers/lib_fractions';
 | 
			
		||||
export * from '../generated-wrappers/lib_math';
 | 
			
		||||
export * from '../generated-wrappers/lib_math_rich_errors';
 | 
			
		||||
export * from '../generated-wrappers/lib_ownable_rich_errors';
 | 
			
		||||
export * from '../generated-wrappers/lib_reentrancy_guard_rich_errors';
 | 
			
		||||
export * from '../generated-wrappers/lib_rich_errors';
 | 
			
		||||
@@ -24,4 +13,3 @@ export * from '../generated-wrappers/lib_safe_math';
 | 
			
		||||
export * from '../generated-wrappers/lib_safe_math_rich_errors';
 | 
			
		||||
export * from '../generated-wrappers/ownable';
 | 
			
		||||
export * from '../generated-wrappers/reentrancy_guard';
 | 
			
		||||
export * from '../generated-wrappers/refundable';
 | 
			
		||||
 
 | 
			
		||||
@@ -5,21 +5,13 @@
 | 
			
		||||
 */
 | 
			
		||||
import { ContractArtifact } from 'ethereum-types';
 | 
			
		||||
 | 
			
		||||
import * as Authorizable from '../test/generated-artifacts/Authorizable.json';
 | 
			
		||||
import * as AuthorizableV06 from '../test/generated-artifacts/AuthorizableV06.json';
 | 
			
		||||
import * as AuthorizableV08 from '../test/generated-artifacts/AuthorizableV08.json';
 | 
			
		||||
import * as D18 from '../test/generated-artifacts/D18.json';
 | 
			
		||||
import * as DeploymentConstants from '../test/generated-artifacts/DeploymentConstants.json';
 | 
			
		||||
import * as IAuthorizable from '../test/generated-artifacts/IAuthorizable.json';
 | 
			
		||||
import * as IAuthorizableV06 from '../test/generated-artifacts/IAuthorizableV06.json';
 | 
			
		||||
import * as IAuthorizableV08 from '../test/generated-artifacts/IAuthorizableV08.json';
 | 
			
		||||
import * as IOwnable from '../test/generated-artifacts/IOwnable.json';
 | 
			
		||||
import * as IOwnableV06 from '../test/generated-artifacts/IOwnableV06.json';
 | 
			
		||||
import * as IOwnableV08 from '../test/generated-artifacts/IOwnableV08.json';
 | 
			
		||||
import * as LibAddress from '../test/generated-artifacts/LibAddress.json';
 | 
			
		||||
import * as LibAddressArray from '../test/generated-artifacts/LibAddressArray.json';
 | 
			
		||||
import * as LibAddressArrayRichErrors from '../test/generated-artifacts/LibAddressArrayRichErrors.json';
 | 
			
		||||
import * as LibAuthorizableRichErrors from '../test/generated-artifacts/LibAuthorizableRichErrors.json';
 | 
			
		||||
import * as LibAuthorizableRichErrorsV06 from '../test/generated-artifacts/LibAuthorizableRichErrorsV06.json';
 | 
			
		||||
import * as LibAuthorizableRichErrorsV08 from '../test/generated-artifacts/LibAuthorizableRichErrorsV08.json';
 | 
			
		||||
import * as LibBytes from '../test/generated-artifacts/LibBytes.json';
 | 
			
		||||
@@ -28,11 +20,6 @@ import * as LibBytesRichErrorsV06 from '../test/generated-artifacts/LibBytesRich
 | 
			
		||||
import * as LibBytesRichErrorsV08 from '../test/generated-artifacts/LibBytesRichErrorsV08.json';
 | 
			
		||||
import * as LibBytesV06 from '../test/generated-artifacts/LibBytesV06.json';
 | 
			
		||||
import * as LibBytesV08 from '../test/generated-artifacts/LibBytesV08.json';
 | 
			
		||||
import * as LibEIP1271 from '../test/generated-artifacts/LibEIP1271.json';
 | 
			
		||||
import * as LibEIP712 from '../test/generated-artifacts/LibEIP712.json';
 | 
			
		||||
import * as LibFractions from '../test/generated-artifacts/LibFractions.json';
 | 
			
		||||
import * as LibMath from '../test/generated-artifacts/LibMath.json';
 | 
			
		||||
import * as LibMathRichErrors from '../test/generated-artifacts/LibMathRichErrors.json';
 | 
			
		||||
import * as LibMathRichErrorsV06 from '../test/generated-artifacts/LibMathRichErrorsV06.json';
 | 
			
		||||
import * as LibMathRichErrorsV08 from '../test/generated-artifacts/LibMathRichErrorsV08.json';
 | 
			
		||||
import * as LibMathV06 from '../test/generated-artifacts/LibMathV06.json';
 | 
			
		||||
@@ -55,38 +42,15 @@ import * as Ownable from '../test/generated-artifacts/Ownable.json';
 | 
			
		||||
import * as OwnableV06 from '../test/generated-artifacts/OwnableV06.json';
 | 
			
		||||
import * as OwnableV08 from '../test/generated-artifacts/OwnableV08.json';
 | 
			
		||||
import * as ReentrancyGuard from '../test/generated-artifacts/ReentrancyGuard.json';
 | 
			
		||||
import * as ReentrancyGuardV06 from '../test/generated-artifacts/ReentrancyGuardV06.json';
 | 
			
		||||
import * as ReentrancyGuardV08 from '../test/generated-artifacts/ReentrancyGuardV08.json';
 | 
			
		||||
import * as Refundable from '../test/generated-artifacts/Refundable.json';
 | 
			
		||||
import * as TestAuthorizable from '../test/generated-artifacts/TestAuthorizable.json';
 | 
			
		||||
import * as TestLibAddress from '../test/generated-artifacts/TestLibAddress.json';
 | 
			
		||||
import * as TestLibAddressArray from '../test/generated-artifacts/TestLibAddressArray.json';
 | 
			
		||||
import * as TestLibBytes from '../test/generated-artifacts/TestLibBytes.json';
 | 
			
		||||
import * as TestLibEIP712 from '../test/generated-artifacts/TestLibEIP712.json';
 | 
			
		||||
import * as TestLibMath from '../test/generated-artifacts/TestLibMath.json';
 | 
			
		||||
import * as TestLibRichErrors from '../test/generated-artifacts/TestLibRichErrors.json';
 | 
			
		||||
import * as TestLibSafeMath from '../test/generated-artifacts/TestLibSafeMath.json';
 | 
			
		||||
import * as TestLogDecoding from '../test/generated-artifacts/TestLogDecoding.json';
 | 
			
		||||
import * as TestLogDecodingDownstream from '../test/generated-artifacts/TestLogDecodingDownstream.json';
 | 
			
		||||
import * as TestOwnable from '../test/generated-artifacts/TestOwnable.json';
 | 
			
		||||
import * as TestReentrancyGuard from '../test/generated-artifacts/TestReentrancyGuard.json';
 | 
			
		||||
import * as TestRefundable from '../test/generated-artifacts/TestRefundable.json';
 | 
			
		||||
import * as TestRefundableReceiver from '../test/generated-artifacts/TestRefundableReceiver.json';
 | 
			
		||||
export const artifacts = {
 | 
			
		||||
    Authorizable: Authorizable as ContractArtifact,
 | 
			
		||||
    D18: D18 as ContractArtifact,
 | 
			
		||||
    DeploymentConstants: DeploymentConstants as ContractArtifact,
 | 
			
		||||
    LibAddress: LibAddress as ContractArtifact,
 | 
			
		||||
    LibAddressArray: LibAddressArray as ContractArtifact,
 | 
			
		||||
    LibAddressArrayRichErrors: LibAddressArrayRichErrors as ContractArtifact,
 | 
			
		||||
    LibAuthorizableRichErrors: LibAuthorizableRichErrors as ContractArtifact,
 | 
			
		||||
    LibBytes: LibBytes as ContractArtifact,
 | 
			
		||||
    LibBytesRichErrors: LibBytesRichErrors as ContractArtifact,
 | 
			
		||||
    LibEIP1271: LibEIP1271 as ContractArtifact,
 | 
			
		||||
    LibEIP712: LibEIP712 as ContractArtifact,
 | 
			
		||||
    LibFractions: LibFractions as ContractArtifact,
 | 
			
		||||
    LibMath: LibMath as ContractArtifact,
 | 
			
		||||
    LibMathRichErrors: LibMathRichErrors as ContractArtifact,
 | 
			
		||||
    LibOwnableRichErrors: LibOwnableRichErrors as ContractArtifact,
 | 
			
		||||
    LibReentrancyGuardRichErrors: LibReentrancyGuardRichErrors as ContractArtifact,
 | 
			
		||||
    LibRichErrors: LibRichErrors as ContractArtifact,
 | 
			
		||||
@@ -94,15 +58,12 @@ export const artifacts = {
 | 
			
		||||
    LibSafeMathRichErrors: LibSafeMathRichErrors as ContractArtifact,
 | 
			
		||||
    Ownable: Ownable as ContractArtifact,
 | 
			
		||||
    ReentrancyGuard: ReentrancyGuard as ContractArtifact,
 | 
			
		||||
    Refundable: Refundable as ContractArtifact,
 | 
			
		||||
    IAuthorizable: IAuthorizable as ContractArtifact,
 | 
			
		||||
    IOwnable: IOwnable as ContractArtifact,
 | 
			
		||||
    AuthorizableV06: AuthorizableV06 as ContractArtifact,
 | 
			
		||||
    LibBytesV06: LibBytesV06 as ContractArtifact,
 | 
			
		||||
    LibMathV06: LibMathV06 as ContractArtifact,
 | 
			
		||||
    LibSafeMathV06: LibSafeMathV06 as ContractArtifact,
 | 
			
		||||
    OwnableV06: OwnableV06 as ContractArtifact,
 | 
			
		||||
    ReentrancyGuardV06: ReentrancyGuardV06 as ContractArtifact,
 | 
			
		||||
    LibAuthorizableRichErrorsV06: LibAuthorizableRichErrorsV06 as ContractArtifact,
 | 
			
		||||
    LibBytesRichErrorsV06: LibBytesRichErrorsV06 as ContractArtifact,
 | 
			
		||||
    LibMathRichErrorsV06: LibMathRichErrorsV06 as ContractArtifact,
 | 
			
		||||
@@ -126,18 +87,9 @@ export const artifacts = {
 | 
			
		||||
    LibSafeMathRichErrorsV08: LibSafeMathRichErrorsV08 as ContractArtifact,
 | 
			
		||||
    IAuthorizableV08: IAuthorizableV08 as ContractArtifact,
 | 
			
		||||
    IOwnableV08: IOwnableV08 as ContractArtifact,
 | 
			
		||||
    TestAuthorizable: TestAuthorizable as ContractArtifact,
 | 
			
		||||
    TestLibAddress: TestLibAddress as ContractArtifact,
 | 
			
		||||
    TestLibAddressArray: TestLibAddressArray as ContractArtifact,
 | 
			
		||||
    TestLibBytes: TestLibBytes as ContractArtifact,
 | 
			
		||||
    TestLibEIP712: TestLibEIP712 as ContractArtifact,
 | 
			
		||||
    TestLibMath: TestLibMath as ContractArtifact,
 | 
			
		||||
    TestLibRichErrors: TestLibRichErrors as ContractArtifact,
 | 
			
		||||
    TestLibSafeMath: TestLibSafeMath as ContractArtifact,
 | 
			
		||||
    TestLogDecoding: TestLogDecoding as ContractArtifact,
 | 
			
		||||
    TestLogDecodingDownstream: TestLogDecodingDownstream as ContractArtifact,
 | 
			
		||||
    TestOwnable: TestOwnable as ContractArtifact,
 | 
			
		||||
    TestReentrancyGuard: TestReentrancyGuard as ContractArtifact,
 | 
			
		||||
    TestRefundable: TestRefundable as ContractArtifact,
 | 
			
		||||
    TestRefundableReceiver: TestRefundableReceiver as ContractArtifact,
 | 
			
		||||
};
 | 
			
		||||
 
 | 
			
		||||
@@ -1,165 +0,0 @@
 | 
			
		||||
import { blockchainTests, constants, expect } from '@0x/contracts-test-utils';
 | 
			
		||||
import { AuthorizableRevertErrors, BigNumber, OwnableRevertErrors } from '@0x/utils';
 | 
			
		||||
import * as _ from 'lodash';
 | 
			
		||||
 | 
			
		||||
import { artifacts } from './artifacts';
 | 
			
		||||
import { TestAuthorizableContract } from './wrappers';
 | 
			
		||||
 | 
			
		||||
blockchainTests.resets('Authorizable', env => {
 | 
			
		||||
    let owner: string;
 | 
			
		||||
    let notOwner: string;
 | 
			
		||||
    let address: string;
 | 
			
		||||
    let authorizable: TestAuthorizableContract;
 | 
			
		||||
 | 
			
		||||
    before(async () => {
 | 
			
		||||
        const accounts = await env.getAccountAddressesAsync();
 | 
			
		||||
        [owner, address, notOwner] = _.slice(accounts, 0, 3);
 | 
			
		||||
        authorizable = await TestAuthorizableContract.deployFrom0xArtifactAsync(
 | 
			
		||||
            artifacts.TestAuthorizable,
 | 
			
		||||
            env.provider,
 | 
			
		||||
            env.txDefaults,
 | 
			
		||||
            artifacts,
 | 
			
		||||
        );
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    describe('addAuthorizedAddress', () => {
 | 
			
		||||
        it('should revert if not called by owner', async () => {
 | 
			
		||||
            const expectedError = new OwnableRevertErrors.OnlyOwnerError(notOwner, owner);
 | 
			
		||||
            const tx = authorizable.addAuthorizedAddress(notOwner).sendTransactionAsync({ from: notOwner });
 | 
			
		||||
            return expect(tx).to.revertWith(expectedError);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should allow owner to add an authorized address', async () => {
 | 
			
		||||
            await authorizable.addAuthorizedAddress(address).awaitTransactionSuccessAsync({ from: owner });
 | 
			
		||||
            const isAuthorized = await authorizable.authorized(address).callAsync();
 | 
			
		||||
            expect(isAuthorized).to.be.true();
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should revert if owner attempts to authorize the zero address', async () => {
 | 
			
		||||
            const expectedError = new AuthorizableRevertErrors.ZeroCantBeAuthorizedError();
 | 
			
		||||
            const tx = authorizable.addAuthorizedAddress(constants.NULL_ADDRESS).sendTransactionAsync({ from: owner });
 | 
			
		||||
            return expect(tx).to.revertWith(expectedError);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should revert if owner attempts to authorize a duplicate address', async () => {
 | 
			
		||||
            await authorizable.addAuthorizedAddress(address).awaitTransactionSuccessAsync({ from: owner });
 | 
			
		||||
            const expectedError = new AuthorizableRevertErrors.TargetAlreadyAuthorizedError(address);
 | 
			
		||||
            const tx = authorizable.addAuthorizedAddress(address).sendTransactionAsync({ from: owner });
 | 
			
		||||
            return expect(tx).to.revertWith(expectedError);
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    describe('onlyAuthorized', () => {
 | 
			
		||||
        before(async () => {
 | 
			
		||||
            await authorizable.addAuthorizedAddress(owner).awaitTransactionSuccessAsync({ from: owner });
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        after(async () => {
 | 
			
		||||
            await authorizable.removeAuthorizedAddress(owner).awaitTransactionSuccessAsync({ from: owner });
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should revert if sender is not authorized', async () => {
 | 
			
		||||
            const tx = authorizable.onlyAuthorizedFn().callAsync({ from: notOwner });
 | 
			
		||||
            const expectedError = new AuthorizableRevertErrors.SenderNotAuthorizedError(notOwner);
 | 
			
		||||
            return expect(tx).to.revertWith(expectedError);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should succeed if sender is authorized', async () => {
 | 
			
		||||
            await authorizable.onlyAuthorizedFn().callAsync({ from: owner });
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    describe('removeAuthorizedAddress', () => {
 | 
			
		||||
        it('should revert if not called by owner', async () => {
 | 
			
		||||
            await authorizable.addAuthorizedAddress(address).awaitTransactionSuccessAsync({ from: owner });
 | 
			
		||||
            const expectedError = new OwnableRevertErrors.OnlyOwnerError(notOwner, owner);
 | 
			
		||||
            const tx = authorizable.removeAuthorizedAddress(address).sendTransactionAsync({ from: notOwner });
 | 
			
		||||
            return expect(tx).to.revertWith(expectedError);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should allow owner to remove an authorized address', async () => {
 | 
			
		||||
            await authorizable.addAuthorizedAddress(address).awaitTransactionSuccessAsync({ from: owner });
 | 
			
		||||
            await authorizable.removeAuthorizedAddress(address).awaitTransactionSuccessAsync({ from: owner });
 | 
			
		||||
            const isAuthorized = await authorizable.authorized(address).callAsync();
 | 
			
		||||
            expect(isAuthorized).to.be.false();
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should revert if owner attempts to remove an address that is not authorized', async () => {
 | 
			
		||||
            const expectedError = new AuthorizableRevertErrors.TargetNotAuthorizedError(address);
 | 
			
		||||
            const tx = authorizable.removeAuthorizedAddress(address).sendTransactionAsync({ from: owner });
 | 
			
		||||
            return expect(tx).to.revertWith(expectedError);
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    describe('removeAuthorizedAddressAtIndex', () => {
 | 
			
		||||
        it('should revert if not called by owner', async () => {
 | 
			
		||||
            await authorizable.addAuthorizedAddress(address).awaitTransactionSuccessAsync({ from: owner });
 | 
			
		||||
            const index = new BigNumber(0);
 | 
			
		||||
            const expectedError = new OwnableRevertErrors.OnlyOwnerError(notOwner, owner);
 | 
			
		||||
            const tx = authorizable.removeAuthorizedAddressAtIndex(address, index).sendTransactionAsync({
 | 
			
		||||
                from: notOwner,
 | 
			
		||||
            });
 | 
			
		||||
            return expect(tx).to.revertWith(expectedError);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should revert if index is >= authorities.length', async () => {
 | 
			
		||||
            await authorizable.addAuthorizedAddress(address).awaitTransactionSuccessAsync({ from: owner });
 | 
			
		||||
            const index = new BigNumber(1);
 | 
			
		||||
            const expectedError = new AuthorizableRevertErrors.IndexOutOfBoundsError(index, index);
 | 
			
		||||
            const tx = authorizable.removeAuthorizedAddressAtIndex(address, index).sendTransactionAsync({
 | 
			
		||||
                from: owner,
 | 
			
		||||
            });
 | 
			
		||||
            return expect(tx).to.revertWith(expectedError);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should revert if owner attempts to remove an address that is not authorized', async () => {
 | 
			
		||||
            const index = new BigNumber(0);
 | 
			
		||||
            const expectedError = new AuthorizableRevertErrors.TargetNotAuthorizedError(address);
 | 
			
		||||
            const tx = authorizable.removeAuthorizedAddressAtIndex(address, index).sendTransactionAsync({
 | 
			
		||||
                from: owner,
 | 
			
		||||
            });
 | 
			
		||||
            return expect(tx).to.revertWith(expectedError);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should revert if address at index does not match target', async () => {
 | 
			
		||||
            const address1 = address;
 | 
			
		||||
            const address2 = notOwner;
 | 
			
		||||
            await authorizable.addAuthorizedAddress(address1).awaitTransactionSuccessAsync({ from: owner });
 | 
			
		||||
            await authorizable.addAuthorizedAddress(address2).awaitTransactionSuccessAsync({ from: owner });
 | 
			
		||||
            const address1Index = new BigNumber(0);
 | 
			
		||||
            const expectedError = new AuthorizableRevertErrors.AuthorizedAddressMismatchError(address1, address2);
 | 
			
		||||
            const tx = authorizable.removeAuthorizedAddressAtIndex(address2, address1Index).sendTransactionAsync({
 | 
			
		||||
                from: owner,
 | 
			
		||||
            });
 | 
			
		||||
            return expect(tx).to.revertWith(expectedError);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should allow owner to remove an authorized address', async () => {
 | 
			
		||||
            await authorizable.addAuthorizedAddress(address).awaitTransactionSuccessAsync({ from: owner });
 | 
			
		||||
            const index = new BigNumber(0);
 | 
			
		||||
            await authorizable.removeAuthorizedAddressAtIndex(address, index).awaitTransactionSuccessAsync({
 | 
			
		||||
                from: owner,
 | 
			
		||||
            });
 | 
			
		||||
            const isAuthorized = await authorizable.authorized(address).callAsync();
 | 
			
		||||
            expect(isAuthorized).to.be.false();
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    describe('getAuthorizedAddresses', () => {
 | 
			
		||||
        it('should return correct authorized addresses', async () => {
 | 
			
		||||
            // Initial Authorities
 | 
			
		||||
            let authorities = await authorizable.getAuthorizedAddresses().callAsync();
 | 
			
		||||
            expect(authorities).to.be.deep.eq([]);
 | 
			
		||||
 | 
			
		||||
            // Authorities after addition
 | 
			
		||||
            await authorizable.addAuthorizedAddress(address).awaitTransactionSuccessAsync({ from: owner });
 | 
			
		||||
            authorities = await authorizable.getAuthorizedAddresses().callAsync();
 | 
			
		||||
            expect(authorities).to.be.deep.eq([address]);
 | 
			
		||||
 | 
			
		||||
            // Authorities after removal
 | 
			
		||||
            await authorizable.removeAuthorizedAddress(address).awaitTransactionSuccessAsync({ from: owner });
 | 
			
		||||
            authorities = await authorizable.getAuthorizedAddresses().callAsync();
 | 
			
		||||
            expect(authorities).to.be.deep.eq([]);
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
});
 | 
			
		||||
@@ -1,43 +0,0 @@
 | 
			
		||||
import { chaiSetup, provider, txDefaults, web3Wrapper } from '@0x/contracts-test-utils';
 | 
			
		||||
import { BlockchainLifecycle } from '@0x/dev-utils';
 | 
			
		||||
import * as chai from 'chai';
 | 
			
		||||
 | 
			
		||||
import { artifacts } from './artifacts';
 | 
			
		||||
import { TestLibAddressContract } from './wrappers';
 | 
			
		||||
 | 
			
		||||
chaiSetup.configure();
 | 
			
		||||
const expect = chai.expect;
 | 
			
		||||
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
 | 
			
		||||
 | 
			
		||||
describe('LibAddress', () => {
 | 
			
		||||
    let lib: TestLibAddressContract;
 | 
			
		||||
    let nonContract: string;
 | 
			
		||||
 | 
			
		||||
    before(async () => {
 | 
			
		||||
        await blockchainLifecycle.startAsync();
 | 
			
		||||
        nonContract = (await web3Wrapper.getAvailableAddressesAsync())[0];
 | 
			
		||||
        // Deploy LibAddress
 | 
			
		||||
        lib = await TestLibAddressContract.deployFrom0xArtifactAsync(
 | 
			
		||||
            artifacts.TestLibAddress,
 | 
			
		||||
            provider,
 | 
			
		||||
            txDefaults,
 | 
			
		||||
            {},
 | 
			
		||||
        );
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    after(async () => {
 | 
			
		||||
        await blockchainLifecycle.revertAsync();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    describe('isContract', () => {
 | 
			
		||||
        it('should return false for a non-contract address', async () => {
 | 
			
		||||
            const isContract = await lib.externalIsContract(nonContract).callAsync();
 | 
			
		||||
            expect(isContract).to.be.false();
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should return true for a non-contract address', async () => {
 | 
			
		||||
            const isContract = await lib.externalIsContract(lib.address).callAsync();
 | 
			
		||||
            expect(isContract).to.be.true();
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
});
 | 
			
		||||
@@ -1,144 +0,0 @@
 | 
			
		||||
import { chaiSetup, provider, randomAddress, txDefaults, web3Wrapper } from '@0x/contracts-test-utils';
 | 
			
		||||
import { BlockchainLifecycle } from '@0x/dev-utils';
 | 
			
		||||
import { BigNumber, LibAddressArrayRevertErrors } from '@0x/utils';
 | 
			
		||||
import * as chai from 'chai';
 | 
			
		||||
import * as _ from 'lodash';
 | 
			
		||||
 | 
			
		||||
import { artifacts } from './artifacts';
 | 
			
		||||
import { TestLibAddressArrayContract } from './wrappers';
 | 
			
		||||
 | 
			
		||||
chaiSetup.configure();
 | 
			
		||||
const expect = chai.expect;
 | 
			
		||||
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
 | 
			
		||||
 | 
			
		||||
describe('LibAddressArray', () => {
 | 
			
		||||
    let lib: TestLibAddressArrayContract;
 | 
			
		||||
 | 
			
		||||
    before(async () => {
 | 
			
		||||
        await blockchainLifecycle.startAsync();
 | 
			
		||||
        // Deploy LibAddressArray
 | 
			
		||||
        lib = await TestLibAddressArrayContract.deployFrom0xArtifactAsync(
 | 
			
		||||
            artifacts.TestLibAddressArray,
 | 
			
		||||
            provider,
 | 
			
		||||
            txDefaults,
 | 
			
		||||
            artifacts,
 | 
			
		||||
        );
 | 
			
		||||
    });
 | 
			
		||||
    after(async () => {
 | 
			
		||||
        await blockchainLifecycle.revertAsync();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    describe('append', () => {
 | 
			
		||||
        it('should append to empty array', async () => {
 | 
			
		||||
            const addr = randomAddress();
 | 
			
		||||
            const result = await lib.publicAppend([], addr).callAsync();
 | 
			
		||||
            const expected = [addr];
 | 
			
		||||
            expect(result).to.deep.equal(expected);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should append to non-empty array', async () => {
 | 
			
		||||
            const arr = _.times(3, () => randomAddress());
 | 
			
		||||
            const addr = randomAddress();
 | 
			
		||||
            const expected = [...arr, addr];
 | 
			
		||||
            const result = await lib.publicAppend(arr, addr).callAsync();
 | 
			
		||||
            expect(result).to.deep.equal(expected);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should revert if the free memory pointer was moved to before the end of the array', async () => {
 | 
			
		||||
            const arr = _.times(3, () => randomAddress());
 | 
			
		||||
            const addr = randomAddress();
 | 
			
		||||
            const freeMemOffset = new BigNumber(-1);
 | 
			
		||||
            const addressArrayEndPtr = new BigNumber(256);
 | 
			
		||||
            const expectedError = new LibAddressArrayRevertErrors.MismanagedMemoryError(
 | 
			
		||||
                addressArrayEndPtr.plus(freeMemOffset),
 | 
			
		||||
                addressArrayEndPtr,
 | 
			
		||||
            );
 | 
			
		||||
            return expect(lib.testAppendRealloc(arr, freeMemOffset, addr).callAsync()).to.revertWith(expectedError);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should keep the same memory address if free memory pointer does not move', async () => {
 | 
			
		||||
            const arr = _.times(3, () => randomAddress());
 | 
			
		||||
            const addr = randomAddress();
 | 
			
		||||
            const freeMemOffset = new BigNumber(0);
 | 
			
		||||
            const expected = [...arr, addr];
 | 
			
		||||
            const [result, oldArrayMemStart, newArrayMemStart] = await lib
 | 
			
		||||
                .testAppendRealloc(arr, freeMemOffset, addr)
 | 
			
		||||
                .callAsync();
 | 
			
		||||
            expect(result).to.deep.equal(expected);
 | 
			
		||||
            expect(newArrayMemStart).bignumber.to.be.equal(oldArrayMemStart);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should change memory address if free memory pointer advances', async () => {
 | 
			
		||||
            const arr = _.times(3, () => randomAddress());
 | 
			
		||||
            const addr = randomAddress();
 | 
			
		||||
            const freeMemOffset = new BigNumber(1);
 | 
			
		||||
            const expectedArray = [...arr, addr];
 | 
			
		||||
            const [result, oldArrayMemStart, newArrayMemStart] = await lib
 | 
			
		||||
                .testAppendRealloc(arr, freeMemOffset, addr)
 | 
			
		||||
                .callAsync();
 | 
			
		||||
            // The new location should be the end of the old array + freeMemOffset.
 | 
			
		||||
            const expectedNewArrayMemStart = oldArrayMemStart.plus((arr.length + 1) * 32).plus(freeMemOffset);
 | 
			
		||||
            expect(result).to.deep.equal(expectedArray);
 | 
			
		||||
            expect(newArrayMemStart).bignumber.to.be.equal(expectedNewArrayMemStart);
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    describe('contains', () => {
 | 
			
		||||
        it('should return false on an empty array', async () => {
 | 
			
		||||
            const addr = randomAddress();
 | 
			
		||||
            const isFound = await lib.publicContains([], addr).callAsync();
 | 
			
		||||
            expect(isFound).to.equal(false);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should return false on a missing item', async () => {
 | 
			
		||||
            const arr = _.times(3, () => randomAddress());
 | 
			
		||||
            const addr = randomAddress();
 | 
			
		||||
            const isFound = await lib.publicContains(arr, addr).callAsync();
 | 
			
		||||
            expect(isFound).to.equal(false);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should return true on an included item', async () => {
 | 
			
		||||
            const arr = _.times(4, () => randomAddress());
 | 
			
		||||
            const addr = _.sample(arr) as string;
 | 
			
		||||
            const isFound = await lib.publicContains(arr, addr).callAsync();
 | 
			
		||||
            expect(isFound).to.equal(true);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should return true on the only item in the array', async () => {
 | 
			
		||||
            const arr = _.times(1, () => randomAddress());
 | 
			
		||||
            const isFound = await lib.publicContains(arr, arr[0]).callAsync();
 | 
			
		||||
            expect(isFound).to.equal(true);
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    describe('indexOf', () => {
 | 
			
		||||
        it('should fail on an empty array', async () => {
 | 
			
		||||
            const addr = randomAddress();
 | 
			
		||||
            const [isSuccess] = await lib.publicIndexOf([], addr).callAsync();
 | 
			
		||||
            expect(isSuccess).to.equal(false);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should fail on a missing item', async () => {
 | 
			
		||||
            const arr = _.times(3, () => randomAddress());
 | 
			
		||||
            const addr = randomAddress();
 | 
			
		||||
            const [isSuccess] = await lib.publicIndexOf(arr, addr).callAsync();
 | 
			
		||||
            expect(isSuccess).to.equal(false);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should succeed on an included item', async () => {
 | 
			
		||||
            const arr = _.times(4, () => randomAddress());
 | 
			
		||||
            const expectedIndexOf = _.random(0, arr.length - 1);
 | 
			
		||||
            const addr = arr[expectedIndexOf];
 | 
			
		||||
            const [isSuccess, index] = await lib.publicIndexOf(arr, addr).callAsync();
 | 
			
		||||
            expect(isSuccess).to.equal(true);
 | 
			
		||||
            expect(index).bignumber.to.equal(expectedIndexOf);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should succeed on the only item in the array', async () => {
 | 
			
		||||
            const arr = _.times(1, () => randomAddress());
 | 
			
		||||
            const [isSuccess, index] = await lib.publicIndexOf(arr, arr[0]).callAsync();
 | 
			
		||||
            expect(isSuccess).to.equal(true);
 | 
			
		||||
            expect(index).bignumber.to.equal(0);
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
});
 | 
			
		||||
@@ -1,108 +0,0 @@
 | 
			
		||||
import { chaiSetup, constants, provider, txDefaults, web3Wrapper } from '@0x/contracts-test-utils';
 | 
			
		||||
import { BlockchainLifecycle } from '@0x/dev-utils';
 | 
			
		||||
import { BigNumber, hexUtils, signTypedDataUtils } from '@0x/utils';
 | 
			
		||||
import * as chai from 'chai';
 | 
			
		||||
import * as _ from 'lodash';
 | 
			
		||||
 | 
			
		||||
import { artifacts } from './artifacts';
 | 
			
		||||
import { TestLibEIP712Contract } from './wrappers';
 | 
			
		||||
 | 
			
		||||
chaiSetup.configure();
 | 
			
		||||
const expect = chai.expect;
 | 
			
		||||
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
 | 
			
		||||
 | 
			
		||||
describe('LibEIP712', () => {
 | 
			
		||||
    let lib: TestLibEIP712Contract;
 | 
			
		||||
 | 
			
		||||
    before(async () => {
 | 
			
		||||
        await blockchainLifecycle.startAsync();
 | 
			
		||||
        // Deploy LibEIP712
 | 
			
		||||
        lib = await TestLibEIP712Contract.deployFrom0xArtifactAsync(artifacts.TestLibEIP712, provider, txDefaults, {});
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    after(async () => {
 | 
			
		||||
        await blockchainLifecycle.revertAsync();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Tests a specific instance of EIP712 domain hashing.
 | 
			
		||||
     * @param lib The LibEIP712 contract to call.
 | 
			
		||||
     * @param name The name of the domain.
 | 
			
		||||
     * @param version The version of the domain.
 | 
			
		||||
     * @param chainId The chain id of the domain.
 | 
			
		||||
     * @param verifyingContract The verifying contract address of the domain.
 | 
			
		||||
     */
 | 
			
		||||
    async function testHashEIP712DomainAsync(
 | 
			
		||||
        name: string,
 | 
			
		||||
        version: string,
 | 
			
		||||
        chainId: number,
 | 
			
		||||
        verifyingContract: string,
 | 
			
		||||
    ): Promise<void> {
 | 
			
		||||
        const expectedHash = signTypedDataUtils.generateDomainHash({
 | 
			
		||||
            name,
 | 
			
		||||
            version,
 | 
			
		||||
            chainId,
 | 
			
		||||
            verifyingContract,
 | 
			
		||||
        });
 | 
			
		||||
        const actualHash = await lib
 | 
			
		||||
            .externalHashEIP712DomainSeperator(name, version, new BigNumber(chainId), verifyingContract)
 | 
			
		||||
            .callAsync();
 | 
			
		||||
        expect(actualHash).to.be.eq(hexUtils.concat(expectedHash));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    describe('_hashEIP712Domain', async () => {
 | 
			
		||||
        it('should correctly hash empty input', async () => {
 | 
			
		||||
            await testHashEIP712DomainAsync('', '', 0, constants.NULL_ADDRESS);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should correctly hash non-empty input', async () => {
 | 
			
		||||
            await testHashEIP712DomainAsync('_hashEIP712Domain', '1.0', 62, lib.address);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should correctly hash non-empty input', async () => {
 | 
			
		||||
            await testHashEIP712DomainAsync('_hashEIP712Domain', '2.0', 0, lib.address);
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Tests a specific instance of EIP712 message hashing.
 | 
			
		||||
     * @param lib The LibEIP712 contract to call.
 | 
			
		||||
     * @param domainHash The hash of the EIP712 domain of this instance.
 | 
			
		||||
     * @param hashStruct The hash of the struct of this instance.
 | 
			
		||||
     */
 | 
			
		||||
    async function testHashEIP712MessageAsync(domainHash: string, hashStruct: string): Promise<void> {
 | 
			
		||||
        // Remove the hex prefix from the domain hash and the hash struct
 | 
			
		||||
        const unprefixedDomainHash = domainHash.slice(2, domainHash.length);
 | 
			
		||||
        const unprefixedHashStruct = hashStruct.slice(2, hashStruct.length);
 | 
			
		||||
 | 
			
		||||
        // Hash the provided input to get the expected hash
 | 
			
		||||
        const input = '0x1901'.concat(unprefixedDomainHash.concat(unprefixedHashStruct));
 | 
			
		||||
        const expectedHash = hexUtils.hash(input);
 | 
			
		||||
 | 
			
		||||
        // Get the actual hash by calling the smart contract
 | 
			
		||||
        const actualHash = await lib.externalHashEIP712Message(domainHash, hashStruct).callAsync();
 | 
			
		||||
 | 
			
		||||
        // Verify that the actual hash matches the expected hash
 | 
			
		||||
        expect(actualHash).to.be.eq(expectedHash);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    describe('_hashEIP712Message', () => {
 | 
			
		||||
        it('should correctly hash empty input', async () => {
 | 
			
		||||
            await testHashEIP712MessageAsync(constants.NULL_BYTES32, constants.NULL_BYTES32);
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should correctly hash non-empty input', async () => {
 | 
			
		||||
            await testHashEIP712MessageAsync(
 | 
			
		||||
                '0xb10e2d527612073b26eecdfd717e6a320cf44b4afac2b0732d9fcbe2b7fa0cf6', // keccak256(abi.encode(1))
 | 
			
		||||
                '0x405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace', // keccak256(abi.encode(2))
 | 
			
		||||
            );
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should correctly hash non-empty input', async () => {
 | 
			
		||||
            await testHashEIP712MessageAsync(
 | 
			
		||||
                '0x405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace', // keccak256(abi.encode(2))
 | 
			
		||||
                '0xc2575a0e9e593c00f959f8c92f12db2869c3395a3b0502d05e2516446f71f85b', // keccak256(abi.encode(3))
 | 
			
		||||
            );
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
});
 | 
			
		||||
@@ -1,421 +0,0 @@
 | 
			
		||||
import {
 | 
			
		||||
    blockchainTests,
 | 
			
		||||
    constants,
 | 
			
		||||
    describe,
 | 
			
		||||
    expect,
 | 
			
		||||
    testCombinatoriallyWithReferenceFunc,
 | 
			
		||||
    uint256Values,
 | 
			
		||||
} from '@0x/contracts-test-utils';
 | 
			
		||||
import { BigNumber, LibMathRevertErrors, SafeMathRevertErrors } from '@0x/utils';
 | 
			
		||||
 | 
			
		||||
import {
 | 
			
		||||
    getPartialAmountCeil,
 | 
			
		||||
    getPartialAmountFloor,
 | 
			
		||||
    isRoundingErrorCeil,
 | 
			
		||||
    isRoundingErrorFloor,
 | 
			
		||||
    safeGetPartialAmountCeil,
 | 
			
		||||
    safeGetPartialAmountFloor,
 | 
			
		||||
} from '../src/reference_functions';
 | 
			
		||||
 | 
			
		||||
import { artifacts } from './artifacts';
 | 
			
		||||
import { TestLibMathContract } from './wrappers';
 | 
			
		||||
 | 
			
		||||
blockchainTests('LibMath', env => {
 | 
			
		||||
    const { ONE_ETHER, MAX_UINT256, MAX_UINT256_ROOT, ZERO_AMOUNT } = constants;
 | 
			
		||||
    let libsContract: TestLibMathContract;
 | 
			
		||||
 | 
			
		||||
    before(async () => {
 | 
			
		||||
        libsContract = await TestLibMathContract.deployFrom0xArtifactAsync(
 | 
			
		||||
            artifacts.TestLibMath,
 | 
			
		||||
            env.provider,
 | 
			
		||||
            env.txDefaults,
 | 
			
		||||
            {},
 | 
			
		||||
        );
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    // Wrap a reference function with identical arguments in a promise.
 | 
			
		||||
    function createAsyncReferenceFunction<T>(ref: (...args: any[]) => T): (...args: any[]) => Promise<T> {
 | 
			
		||||
        return async (...args: any[]): Promise<T> => {
 | 
			
		||||
            return ref(...args);
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function createContractTestFunction<T>(name: string): (...args: any[]) => Promise<T> {
 | 
			
		||||
        return async (...args: any[]): Promise<T> => {
 | 
			
		||||
            return (libsContract as any)[name](...args).callAsync;
 | 
			
		||||
        };
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    describe('getPartialAmountFloor', () => {
 | 
			
		||||
        describe.optional('combinatorial tests', () => {
 | 
			
		||||
            testCombinatoriallyWithReferenceFunc(
 | 
			
		||||
                'getPartialAmountFloor',
 | 
			
		||||
                createAsyncReferenceFunction(getPartialAmountFloor),
 | 
			
		||||
                createContractTestFunction('getPartialAmountFloor'),
 | 
			
		||||
                [uint256Values, uint256Values, uint256Values],
 | 
			
		||||
            );
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        describe('explicit tests', () => {
 | 
			
		||||
            it('matches the reference function output', async () => {
 | 
			
		||||
                const numerator = ONE_ETHER;
 | 
			
		||||
                const denominator = ONE_ETHER.dividedToIntegerBy(2);
 | 
			
		||||
                const target = ONE_ETHER.times(0.01);
 | 
			
		||||
                const expected = getPartialAmountFloor(numerator, denominator, target);
 | 
			
		||||
                const actual = await libsContract.getPartialAmountFloor(numerator, denominator, target).callAsync();
 | 
			
		||||
                expect(actual).to.bignumber.eq(expected);
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            it('rounds down when computing the partial amount', async () => {
 | 
			
		||||
                const numerator = ONE_ETHER.times(0.6);
 | 
			
		||||
                const denominator = ONE_ETHER.times(1.8);
 | 
			
		||||
                const target = ONE_ETHER;
 | 
			
		||||
                const expected = ONE_ETHER.dividedToIntegerBy(3);
 | 
			
		||||
                const actual = await libsContract.getPartialAmountFloor(numerator, denominator, target).callAsync();
 | 
			
		||||
                expect(actual).to.bignumber.eq(expected);
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            it('reverts if `denominator` is zero', async () => {
 | 
			
		||||
                const numerator = ONE_ETHER;
 | 
			
		||||
                const denominator = ZERO_AMOUNT;
 | 
			
		||||
                const target = ONE_ETHER.times(0.01);
 | 
			
		||||
                const expectedError = new SafeMathRevertErrors.Uint256BinOpError(
 | 
			
		||||
                    SafeMathRevertErrors.BinOpErrorCodes.DivisionByZero,
 | 
			
		||||
                    numerator.times(target),
 | 
			
		||||
                    denominator,
 | 
			
		||||
                );
 | 
			
		||||
                return expect(
 | 
			
		||||
                    libsContract.getPartialAmountFloor(numerator, denominator, target).callAsync(),
 | 
			
		||||
                ).to.revertWith(expectedError);
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            it('reverts if `numerator * target` overflows', async () => {
 | 
			
		||||
                const numerator = MAX_UINT256;
 | 
			
		||||
                const denominator = ONE_ETHER.dividedToIntegerBy(2);
 | 
			
		||||
                const target = MAX_UINT256_ROOT.times(2);
 | 
			
		||||
                const expectedError = new SafeMathRevertErrors.Uint256BinOpError(
 | 
			
		||||
                    SafeMathRevertErrors.BinOpErrorCodes.MultiplicationOverflow,
 | 
			
		||||
                    numerator,
 | 
			
		||||
                    target,
 | 
			
		||||
                );
 | 
			
		||||
                return expect(
 | 
			
		||||
                    libsContract.getPartialAmountFloor(numerator, denominator, target).callAsync(),
 | 
			
		||||
                ).to.revertWith(expectedError);
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    describe('getPartialAmountCeil', () => {
 | 
			
		||||
        describe.optional('combinatorial tests', () => {
 | 
			
		||||
            testCombinatoriallyWithReferenceFunc(
 | 
			
		||||
                'getPartialAmountCeil',
 | 
			
		||||
                createAsyncReferenceFunction(getPartialAmountCeil),
 | 
			
		||||
                createContractTestFunction('getPartialAmountCeil'),
 | 
			
		||||
                [uint256Values, uint256Values, uint256Values],
 | 
			
		||||
            );
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        describe('explicit tests', () => {
 | 
			
		||||
            it('matches the reference function output', async () => {
 | 
			
		||||
                const numerator = ONE_ETHER;
 | 
			
		||||
                const denominator = ONE_ETHER.dividedToIntegerBy(2);
 | 
			
		||||
                const target = ONE_ETHER.times(0.01);
 | 
			
		||||
                const expected = getPartialAmountCeil(numerator, denominator, target);
 | 
			
		||||
                const actual = await libsContract.getPartialAmountCeil(numerator, denominator, target).callAsync();
 | 
			
		||||
                expect(actual).to.bignumber.eq(expected);
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            it('rounds up when computing the partial amount', async () => {
 | 
			
		||||
                const numerator = ONE_ETHER.times(0.6);
 | 
			
		||||
                const denominator = ONE_ETHER.times(1.8);
 | 
			
		||||
                const target = ONE_ETHER;
 | 
			
		||||
                const expected = ONE_ETHER.dividedToIntegerBy(3).plus(1);
 | 
			
		||||
                const actual = await libsContract.getPartialAmountCeil(numerator, denominator, target).callAsync();
 | 
			
		||||
                expect(actual).to.bignumber.eq(expected);
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            it('reverts if `denominator` is zero', async () => {
 | 
			
		||||
                const numerator = ONE_ETHER;
 | 
			
		||||
                const denominator = ZERO_AMOUNT;
 | 
			
		||||
                const target = ONE_ETHER.times(0.01);
 | 
			
		||||
                // This will actually manifest as a subtraction underflow.
 | 
			
		||||
                const expectedError = new SafeMathRevertErrors.Uint256BinOpError(
 | 
			
		||||
                    SafeMathRevertErrors.BinOpErrorCodes.SubtractionUnderflow,
 | 
			
		||||
                    denominator,
 | 
			
		||||
                    new BigNumber(1),
 | 
			
		||||
                );
 | 
			
		||||
                return expect(
 | 
			
		||||
                    libsContract.getPartialAmountCeil(numerator, denominator, target).callAsync(),
 | 
			
		||||
                ).to.revertWith(expectedError);
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            it('reverts if `numerator * target` overflows', async () => {
 | 
			
		||||
                const numerator = MAX_UINT256;
 | 
			
		||||
                const denominator = ONE_ETHER.dividedToIntegerBy(2);
 | 
			
		||||
                const target = MAX_UINT256_ROOT.times(2);
 | 
			
		||||
                const expectedError = new SafeMathRevertErrors.Uint256BinOpError(
 | 
			
		||||
                    SafeMathRevertErrors.BinOpErrorCodes.MultiplicationOverflow,
 | 
			
		||||
                    numerator,
 | 
			
		||||
                    target,
 | 
			
		||||
                );
 | 
			
		||||
                return expect(
 | 
			
		||||
                    libsContract.getPartialAmountCeil(numerator, denominator, target).callAsync(),
 | 
			
		||||
                ).to.revertWith(expectedError);
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    describe('safeGetPartialAmountFloor', () => {
 | 
			
		||||
        describe.optional('combinatorial tests', () => {
 | 
			
		||||
            testCombinatoriallyWithReferenceFunc(
 | 
			
		||||
                'safeGetPartialAmountFloor',
 | 
			
		||||
                createAsyncReferenceFunction(safeGetPartialAmountFloor),
 | 
			
		||||
                createContractTestFunction('safeGetPartialAmountFloor'),
 | 
			
		||||
                [uint256Values, uint256Values, uint256Values],
 | 
			
		||||
            );
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        describe('explicit tests', () => {
 | 
			
		||||
            it('matches the reference function output', async () => {
 | 
			
		||||
                const numerator = ONE_ETHER;
 | 
			
		||||
                const denominator = ONE_ETHER.dividedToIntegerBy(2);
 | 
			
		||||
                const target = ONE_ETHER.times(0.01);
 | 
			
		||||
                const expected = safeGetPartialAmountFloor(numerator, denominator, target);
 | 
			
		||||
                const actual = await libsContract.safeGetPartialAmountFloor(numerator, denominator, target).callAsync();
 | 
			
		||||
                expect(actual).to.bignumber.eq(expected);
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            it('rounds down when computing the partial amount', async () => {
 | 
			
		||||
                const numerator = ONE_ETHER.times(0.6);
 | 
			
		||||
                const denominator = ONE_ETHER.times(1.8);
 | 
			
		||||
                const target = ONE_ETHER;
 | 
			
		||||
                const expected = ONE_ETHER.dividedToIntegerBy(3);
 | 
			
		||||
                const actual = await libsContract.safeGetPartialAmountFloor(numerator, denominator, target).callAsync();
 | 
			
		||||
                expect(actual).to.bignumber.eq(expected);
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            it('reverts for a rounding error', async () => {
 | 
			
		||||
                const numerator = new BigNumber(1e3);
 | 
			
		||||
                const denominator = new BigNumber(1e4);
 | 
			
		||||
                const target = new BigNumber(333);
 | 
			
		||||
                const expectedError = new LibMathRevertErrors.RoundingError(numerator, denominator, target);
 | 
			
		||||
                return expect(
 | 
			
		||||
                    libsContract.safeGetPartialAmountFloor(numerator, denominator, target).callAsync(),
 | 
			
		||||
                ).to.revertWith(expectedError);
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            it('reverts if `denominator` is zero', async () => {
 | 
			
		||||
                const numerator = ONE_ETHER;
 | 
			
		||||
                const denominator = ZERO_AMOUNT;
 | 
			
		||||
                const target = ONE_ETHER.times(0.01);
 | 
			
		||||
                const expectedError = new LibMathRevertErrors.DivisionByZeroError();
 | 
			
		||||
                return expect(
 | 
			
		||||
                    libsContract.safeGetPartialAmountFloor(numerator, denominator, target).callAsync(),
 | 
			
		||||
                ).to.revertWith(expectedError);
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            it('reverts if `numerator * target` overflows', async () => {
 | 
			
		||||
                const numerator = MAX_UINT256;
 | 
			
		||||
                const denominator = ONE_ETHER.dividedToIntegerBy(2);
 | 
			
		||||
                const target = MAX_UINT256_ROOT.times(2);
 | 
			
		||||
                const expectedError = new SafeMathRevertErrors.Uint256BinOpError(
 | 
			
		||||
                    SafeMathRevertErrors.BinOpErrorCodes.MultiplicationOverflow,
 | 
			
		||||
                    numerator,
 | 
			
		||||
                    target,
 | 
			
		||||
                );
 | 
			
		||||
                return expect(
 | 
			
		||||
                    libsContract.safeGetPartialAmountFloor(numerator, denominator, target).callAsync(),
 | 
			
		||||
                ).to.revertWith(expectedError);
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    describe('safeGetPartialAmountCeil', () => {
 | 
			
		||||
        describe.optional('combinatorial tests', () => {
 | 
			
		||||
            testCombinatoriallyWithReferenceFunc(
 | 
			
		||||
                'safeGetPartialAmountCeil',
 | 
			
		||||
                createAsyncReferenceFunction(safeGetPartialAmountCeil),
 | 
			
		||||
                createContractTestFunction('safeGetPartialAmountCeil'),
 | 
			
		||||
                [uint256Values, uint256Values, uint256Values],
 | 
			
		||||
            );
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        describe('explicit tests', () => {
 | 
			
		||||
            it('matches the reference function output', async () => {
 | 
			
		||||
                const numerator = ONE_ETHER;
 | 
			
		||||
                const denominator = ONE_ETHER.dividedToIntegerBy(2);
 | 
			
		||||
                const target = ONE_ETHER.times(0.01);
 | 
			
		||||
                const expected = safeGetPartialAmountCeil(numerator, denominator, target);
 | 
			
		||||
                const actual = await libsContract.safeGetPartialAmountCeil(numerator, denominator, target).callAsync();
 | 
			
		||||
                expect(actual).to.bignumber.eq(expected);
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            it('rounds up when computing the partial amount', async () => {
 | 
			
		||||
                const numerator = ONE_ETHER.times(0.6);
 | 
			
		||||
                const denominator = ONE_ETHER.times(1.8);
 | 
			
		||||
                const target = ONE_ETHER;
 | 
			
		||||
                const expected = ONE_ETHER.dividedToIntegerBy(3).plus(1);
 | 
			
		||||
                const actual = await libsContract.safeGetPartialAmountCeil(numerator, denominator, target).callAsync();
 | 
			
		||||
                expect(actual).to.bignumber.eq(expected);
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            it('reverts for a rounding error', async () => {
 | 
			
		||||
                const numerator = new BigNumber(1e3);
 | 
			
		||||
                const denominator = new BigNumber(1e4);
 | 
			
		||||
                const target = new BigNumber(333);
 | 
			
		||||
                const expectedError = new LibMathRevertErrors.RoundingError(numerator, denominator, target);
 | 
			
		||||
                return expect(
 | 
			
		||||
                    libsContract.safeGetPartialAmountCeil(numerator, denominator, target).callAsync(),
 | 
			
		||||
                ).to.revertWith(expectedError);
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            it('reverts if `denominator` is zero', async () => {
 | 
			
		||||
                const numerator = ONE_ETHER;
 | 
			
		||||
                const denominator = ZERO_AMOUNT;
 | 
			
		||||
                const target = ONE_ETHER.times(0.01);
 | 
			
		||||
                const expectedError = new LibMathRevertErrors.DivisionByZeroError();
 | 
			
		||||
                return expect(
 | 
			
		||||
                    libsContract.safeGetPartialAmountCeil(numerator, denominator, target).callAsync(),
 | 
			
		||||
                ).to.revertWith(expectedError);
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            it('reverts if `numerator * target` overflows', async () => {
 | 
			
		||||
                const numerator = MAX_UINT256;
 | 
			
		||||
                const denominator = ONE_ETHER.dividedToIntegerBy(2);
 | 
			
		||||
                const target = MAX_UINT256_ROOT.times(2);
 | 
			
		||||
                const expectedError = new SafeMathRevertErrors.Uint256BinOpError(
 | 
			
		||||
                    SafeMathRevertErrors.BinOpErrorCodes.MultiplicationOverflow,
 | 
			
		||||
                    numerator,
 | 
			
		||||
                    target,
 | 
			
		||||
                );
 | 
			
		||||
                return expect(
 | 
			
		||||
                    libsContract.safeGetPartialAmountCeil(numerator, denominator, target).callAsync(),
 | 
			
		||||
                ).to.revertWith(expectedError);
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    describe('isRoundingErrorFloor', () => {
 | 
			
		||||
        describe.optional('combinatorial tests', () => {
 | 
			
		||||
            testCombinatoriallyWithReferenceFunc(
 | 
			
		||||
                'isRoundingErrorFloor',
 | 
			
		||||
                createAsyncReferenceFunction(isRoundingErrorFloor),
 | 
			
		||||
                createContractTestFunction('isRoundingErrorFloor'),
 | 
			
		||||
                [uint256Values, uint256Values, uint256Values],
 | 
			
		||||
            );
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        describe('explicit tests', () => {
 | 
			
		||||
            it('returns true when `numerator * target / denominator` produces an error >= 0.1%', async () => {
 | 
			
		||||
                const numerator = new BigNumber(100);
 | 
			
		||||
                const denominator = new BigNumber(102);
 | 
			
		||||
                const target = new BigNumber(52);
 | 
			
		||||
                const actual = await libsContract.isRoundingErrorFloor(numerator, denominator, target).callAsync();
 | 
			
		||||
                expect(actual).to.eq(true);
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            it('returns false when `numerator * target / denominator` produces an error < 0.1%', async () => {
 | 
			
		||||
                const numerator = new BigNumber(100);
 | 
			
		||||
                const denominator = new BigNumber(101);
 | 
			
		||||
                const target = new BigNumber(92);
 | 
			
		||||
                const actual = await libsContract.isRoundingErrorFloor(numerator, denominator, target).callAsync();
 | 
			
		||||
                expect(actual).to.eq(false);
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            it('matches the reference function output', async () => {
 | 
			
		||||
                const numerator = ONE_ETHER;
 | 
			
		||||
                const denominator = ONE_ETHER.dividedToIntegerBy(2);
 | 
			
		||||
                const target = ONE_ETHER.times(0.01);
 | 
			
		||||
                const expected = isRoundingErrorFloor(numerator, denominator, target);
 | 
			
		||||
                const actual = await libsContract.isRoundingErrorFloor(numerator, denominator, target).callAsync();
 | 
			
		||||
                expect(actual).to.eq(expected);
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            it('reverts if `denominator` is zero', async () => {
 | 
			
		||||
                const numerator = ONE_ETHER;
 | 
			
		||||
                const denominator = ZERO_AMOUNT;
 | 
			
		||||
                const target = ONE_ETHER.times(0.01);
 | 
			
		||||
                const expectedError = new LibMathRevertErrors.DivisionByZeroError();
 | 
			
		||||
                return expect(
 | 
			
		||||
                    libsContract.isRoundingErrorFloor(numerator, denominator, target).callAsync(),
 | 
			
		||||
                ).to.revertWith(expectedError);
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            it('reverts if `numerator * target` overflows', async () => {
 | 
			
		||||
                const numerator = MAX_UINT256;
 | 
			
		||||
                const denominator = ONE_ETHER.dividedToIntegerBy(2);
 | 
			
		||||
                const target = MAX_UINT256_ROOT.times(2);
 | 
			
		||||
                const expectedError = new SafeMathRevertErrors.Uint256BinOpError(
 | 
			
		||||
                    SafeMathRevertErrors.BinOpErrorCodes.MultiplicationOverflow,
 | 
			
		||||
                    numerator,
 | 
			
		||||
                    target,
 | 
			
		||||
                );
 | 
			
		||||
                return expect(
 | 
			
		||||
                    libsContract.isRoundingErrorFloor(numerator, denominator, target).callAsync(),
 | 
			
		||||
                ).to.revertWith(expectedError);
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    describe('isRoundingErrorCeil', () => {
 | 
			
		||||
        describe.optional('combinatorial tests', () => {
 | 
			
		||||
            testCombinatoriallyWithReferenceFunc(
 | 
			
		||||
                'isRoundingErrorCeil',
 | 
			
		||||
                createAsyncReferenceFunction(isRoundingErrorCeil),
 | 
			
		||||
                createContractTestFunction('isRoundingErrorCeil'),
 | 
			
		||||
                [uint256Values, uint256Values, uint256Values],
 | 
			
		||||
            );
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        describe('explicit tests', () => {
 | 
			
		||||
            it('returns true when `numerator * target / (denominator - 1)` produces an error >= 0.1%', async () => {
 | 
			
		||||
                const numerator = new BigNumber(100);
 | 
			
		||||
                const denominator = new BigNumber(101);
 | 
			
		||||
                const target = new BigNumber(92);
 | 
			
		||||
                const actual = await libsContract.isRoundingErrorCeil(numerator, denominator, target).callAsync();
 | 
			
		||||
                expect(actual).to.eq(true);
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            it('returns false when `numerator * target / (denominator - 1)` produces an error < 0.1%', async () => {
 | 
			
		||||
                const numerator = new BigNumber(100);
 | 
			
		||||
                const denominator = new BigNumber(102);
 | 
			
		||||
                const target = new BigNumber(52);
 | 
			
		||||
                const actual = await libsContract.isRoundingErrorCeil(numerator, denominator, target).callAsync();
 | 
			
		||||
                expect(actual).to.eq(false);
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            it('matches the reference function output', async () => {
 | 
			
		||||
                const numerator = ONE_ETHER;
 | 
			
		||||
                const denominator = ONE_ETHER.dividedToIntegerBy(2);
 | 
			
		||||
                const target = ONE_ETHER.times(0.01);
 | 
			
		||||
                const expected = isRoundingErrorCeil(numerator, denominator, target);
 | 
			
		||||
                const actual = await libsContract.isRoundingErrorCeil(numerator, denominator, target).callAsync();
 | 
			
		||||
                expect(actual).to.eq(expected);
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            it('reverts if `denominator` is zero', async () => {
 | 
			
		||||
                const numerator = ONE_ETHER;
 | 
			
		||||
                const denominator = ZERO_AMOUNT;
 | 
			
		||||
                const target = ONE_ETHER.times(0.01);
 | 
			
		||||
                const expectedError = new LibMathRevertErrors.DivisionByZeroError();
 | 
			
		||||
                return expect(
 | 
			
		||||
                    libsContract.isRoundingErrorCeil(numerator, denominator, target).callAsync(),
 | 
			
		||||
                ).to.revertWith(expectedError);
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            it('reverts if `numerator * target` overflows', async () => {
 | 
			
		||||
                const numerator = MAX_UINT256;
 | 
			
		||||
                const denominator = ONE_ETHER.dividedToIntegerBy(2);
 | 
			
		||||
                const target = MAX_UINT256_ROOT.times(2);
 | 
			
		||||
                const expectedError = new SafeMathRevertErrors.Uint256BinOpError(
 | 
			
		||||
                    SafeMathRevertErrors.BinOpErrorCodes.MultiplicationOverflow,
 | 
			
		||||
                    numerator,
 | 
			
		||||
                    target,
 | 
			
		||||
                );
 | 
			
		||||
                return expect(
 | 
			
		||||
                    libsContract.isRoundingErrorCeil(numerator, denominator, target).callAsync(),
 | 
			
		||||
                ).to.revertWith(expectedError);
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
});
 | 
			
		||||
@@ -1,98 +0,0 @@
 | 
			
		||||
import { chaiSetup, provider, txDefaults, web3Wrapper } from '@0x/contracts-test-utils';
 | 
			
		||||
import { BlockchainLifecycle } from '@0x/dev-utils';
 | 
			
		||||
import { BigNumber } from '@0x/utils';
 | 
			
		||||
import * as chai from 'chai';
 | 
			
		||||
import { DecodedLogArgs, LogWithDecodedArgs } from 'ethereum-types';
 | 
			
		||||
 | 
			
		||||
import { artifacts } from './artifacts';
 | 
			
		||||
import { TestLogDecodingContract } from './wrappers';
 | 
			
		||||
 | 
			
		||||
chaiSetup.configure();
 | 
			
		||||
const expect = chai.expect;
 | 
			
		||||
 | 
			
		||||
const blockchainLifecycle = new BlockchainLifecycle(web3Wrapper);
 | 
			
		||||
 | 
			
		||||
describe('TestLogDecoding', () => {
 | 
			
		||||
    let testLogDecodingWithDependencies: TestLogDecodingContract;
 | 
			
		||||
    let testLogDecodingDeployedWithoutDependencies: TestLogDecodingContract;
 | 
			
		||||
    const expectedEvent = {
 | 
			
		||||
        foo: new BigNumber(256),
 | 
			
		||||
        bar: '0x1234',
 | 
			
		||||
        car: '4321',
 | 
			
		||||
    };
 | 
			
		||||
    const expectedDownstreamEvent = {
 | 
			
		||||
        lorem: new BigNumber(256),
 | 
			
		||||
        ipsum: '4321',
 | 
			
		||||
    };
 | 
			
		||||
    const emptyDependencyList = {};
 | 
			
		||||
 | 
			
		||||
    before(async () => {
 | 
			
		||||
        testLogDecodingDeployedWithoutDependencies = await TestLogDecodingContract.deployFrom0xArtifactAsync(
 | 
			
		||||
            artifacts.TestLogDecoding,
 | 
			
		||||
            provider,
 | 
			
		||||
            txDefaults,
 | 
			
		||||
            emptyDependencyList,
 | 
			
		||||
        );
 | 
			
		||||
        testLogDecodingWithDependencies = await TestLogDecodingContract.deployFrom0xArtifactAsync(
 | 
			
		||||
            artifacts.TestLogDecoding,
 | 
			
		||||
            provider,
 | 
			
		||||
            txDefaults,
 | 
			
		||||
            artifacts,
 | 
			
		||||
        );
 | 
			
		||||
    });
 | 
			
		||||
    beforeEach(async () => {
 | 
			
		||||
        await blockchainLifecycle.startAsync();
 | 
			
		||||
    });
 | 
			
		||||
    afterEach(async () => {
 | 
			
		||||
        await blockchainLifecycle.revertAsync();
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    describe('Decoding Log Arguments', () => {
 | 
			
		||||
        it('should decode locally emitted event args when no dependencies are passed into wrapper', async () => {
 | 
			
		||||
            const txReceipt = await testLogDecodingDeployedWithoutDependencies
 | 
			
		||||
                .emitEvent()
 | 
			
		||||
                .awaitTransactionSuccessAsync();
 | 
			
		||||
            expect(txReceipt.logs.length).to.be.equal(1);
 | 
			
		||||
            expect((txReceipt.logs[0] as LogWithDecodedArgs<DecodedLogArgs>).args).to.be.deep.equal(expectedEvent);
 | 
			
		||||
        });
 | 
			
		||||
        it('should not decode event args when no dependencies are passed into wrapper', async () => {
 | 
			
		||||
            const txReceipt = await testLogDecodingDeployedWithoutDependencies
 | 
			
		||||
                .emitEventDownstream()
 | 
			
		||||
                .awaitTransactionSuccessAsync();
 | 
			
		||||
            expect(txReceipt.logs.length).to.be.equal(1);
 | 
			
		||||
            expect((txReceipt.logs[0] as LogWithDecodedArgs<DecodedLogArgs>).args).to.be.undefined();
 | 
			
		||||
        });
 | 
			
		||||
        it('should decode args for local but not downstream event when no dependencies are passed into wrapper', async () => {
 | 
			
		||||
            const txReceipt = await testLogDecodingDeployedWithoutDependencies
 | 
			
		||||
                .emitEventsLocalAndDownstream()
 | 
			
		||||
                .awaitTransactionSuccessAsync();
 | 
			
		||||
            expect(txReceipt.logs.length).to.be.equal(2);
 | 
			
		||||
            expect((txReceipt.logs[0] as LogWithDecodedArgs<DecodedLogArgs>).args).to.be.deep.equal(expectedEvent);
 | 
			
		||||
            expect((txReceipt.logs[1] as LogWithDecodedArgs<DecodedLogArgs>).args).to.be.undefined();
 | 
			
		||||
        });
 | 
			
		||||
        it('should decode locally emitted event args when dependencies are passed into wrapper', async () => {
 | 
			
		||||
            const txReceipt = await testLogDecodingWithDependencies.emitEvent().awaitTransactionSuccessAsync();
 | 
			
		||||
            expect(txReceipt.logs.length).to.be.equal(1);
 | 
			
		||||
            expect((txReceipt.logs[0] as LogWithDecodedArgs<DecodedLogArgs>).args).to.be.deep.equal(expectedEvent);
 | 
			
		||||
        });
 | 
			
		||||
        it('should decode downstream event args when dependencies are passed into wrapper', async () => {
 | 
			
		||||
            const txReceipt = await testLogDecodingWithDependencies
 | 
			
		||||
                .emitEventDownstream()
 | 
			
		||||
                .awaitTransactionSuccessAsync();
 | 
			
		||||
            expect(txReceipt.logs.length).to.be.equal(1);
 | 
			
		||||
            expect((txReceipt.logs[0] as LogWithDecodedArgs<DecodedLogArgs>).args).to.be.deep.equal(
 | 
			
		||||
                expectedDownstreamEvent,
 | 
			
		||||
            );
 | 
			
		||||
        });
 | 
			
		||||
        it('should decode args for both local and downstream events when dependencies are passed into wrapper', async () => {
 | 
			
		||||
            const txReceipt = await testLogDecodingWithDependencies
 | 
			
		||||
                .emitEventsLocalAndDownstream()
 | 
			
		||||
                .awaitTransactionSuccessAsync();
 | 
			
		||||
            expect(txReceipt.logs.length).to.be.equal(2);
 | 
			
		||||
            expect((txReceipt.logs[0] as LogWithDecodedArgs<DecodedLogArgs>).args).to.be.deep.equal(expectedEvent);
 | 
			
		||||
            expect((txReceipt.logs[1] as LogWithDecodedArgs<DecodedLogArgs>).args).to.be.deep.equal(
 | 
			
		||||
                expectedDownstreamEvent,
 | 
			
		||||
            );
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
});
 | 
			
		||||
@@ -1,141 +0,0 @@
 | 
			
		||||
import { blockchainTests, constants } from '@0x/contracts-test-utils';
 | 
			
		||||
import { BigNumber } from '@0x/utils';
 | 
			
		||||
import * as _ from 'lodash';
 | 
			
		||||
 | 
			
		||||
import { artifacts } from './artifacts';
 | 
			
		||||
import { TestRefundableContract, TestRefundableReceiverContract } from './wrappers';
 | 
			
		||||
 | 
			
		||||
blockchainTests('Refundable', env => {
 | 
			
		||||
    let refundable: TestRefundableContract;
 | 
			
		||||
    let receiver: TestRefundableReceiverContract;
 | 
			
		||||
 | 
			
		||||
    const ONE_HUNDRED = new BigNumber(100);
 | 
			
		||||
    const ONE_THOUSAND = new BigNumber(1000);
 | 
			
		||||
 | 
			
		||||
    before(async () => {
 | 
			
		||||
        // Create the refundable contract.
 | 
			
		||||
        refundable = await TestRefundableContract.deployFrom0xArtifactAsync(
 | 
			
		||||
            artifacts.TestRefundable,
 | 
			
		||||
            env.provider,
 | 
			
		||||
            env.txDefaults,
 | 
			
		||||
            {},
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        // Create the receiver contract.
 | 
			
		||||
        receiver = await TestRefundableReceiverContract.deployFrom0xArtifactAsync(
 | 
			
		||||
            artifacts.TestRefundableReceiver,
 | 
			
		||||
            env.provider,
 | 
			
		||||
            env.txDefaults,
 | 
			
		||||
            {},
 | 
			
		||||
        );
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    // The contents of these typescript tests is not adequate to understand the assertions that are made during
 | 
			
		||||
    // these calls. For a more accurate picture, checkout out "./contracts/test/TestRefundableReceiver.sol". Specifically,
 | 
			
		||||
    // the function `testRefundNonzeroBalance()` is used in this test suite.
 | 
			
		||||
    blockchainTests.resets('refundNonzeroBalance', () => {
 | 
			
		||||
        it('should not send a refund when no value is sent', async () => {
 | 
			
		||||
            // Send 100 wei to the refundable contract that should be refunded.
 | 
			
		||||
            await receiver.testRefundNonZeroBalance(refundable.address).awaitTransactionSuccessAsync({
 | 
			
		||||
                value: constants.ZERO_AMOUNT,
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should send a full refund when nonzero value is sent', async () => {
 | 
			
		||||
            // Send 100 wei to the refundable contract that should be refunded.
 | 
			
		||||
            await receiver.testRefundNonZeroBalance(refundable.address).awaitTransactionSuccessAsync({
 | 
			
		||||
                value: ONE_HUNDRED,
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    // The contents of these typescript tests is not adequate to understand the assertions that are made during
 | 
			
		||||
    // these calls. For a more accurate picture, checkout out "./contracts/test/TestRefundableReceiver.sol".
 | 
			
		||||
    blockchainTests.resets('refundFinalBalance', () => {
 | 
			
		||||
        it('should fully refund the sender when `shouldNotRefund` is false', async () => {
 | 
			
		||||
            // Send 100 wei to the refundable contract that should be refunded to the receiver contract.
 | 
			
		||||
            await receiver.testRefundFinalBalance(refundable.address, false).awaitTransactionSuccessAsync({
 | 
			
		||||
                value: ONE_HUNDRED,
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        // This test may not be necessary, but it is included here as a sanity check.
 | 
			
		||||
        it('should fully refund the sender when `shouldNotRefund` is false for two calls in a row', async () => {
 | 
			
		||||
            // Send 100 wei to the refundable contract that should be refunded to the receiver contract.
 | 
			
		||||
            await receiver.testRefundFinalBalance(refundable.address, false).awaitTransactionSuccessAsync({
 | 
			
		||||
                value: ONE_HUNDRED,
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            // Send 1000 wei to the refundable contract that should be refunded to the receiver contract.
 | 
			
		||||
            await receiver.testRefundFinalBalance(refundable.address, false).awaitTransactionSuccessAsync({
 | 
			
		||||
                value: new BigNumber(1000),
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should not refund the sender if `shouldNotRefund` is true', async () => {
 | 
			
		||||
            /// Send 100 wei to the refundable contract that should not be refunded.
 | 
			
		||||
            await receiver.testRefundFinalBalance(refundable.address, true).awaitTransactionSuccessAsync({
 | 
			
		||||
                value: new BigNumber(1000),
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
 | 
			
		||||
    // The contents of these typescript tests is not adequate to understand the assertions that are made during
 | 
			
		||||
    // these calls. For a more accurate picture, checkout out "./contracts/test/TestRefundableReceiver.sol".
 | 
			
		||||
    blockchainTests.resets('disableRefundUntilEnd', () => {
 | 
			
		||||
        it('should fully refund the sender when `shouldNotRefund` is false', async () => {
 | 
			
		||||
            // Send 100 wei to the refundable contract that should be refunded to the receiver contract.
 | 
			
		||||
            await receiver.testDisableRefundUntilEnd(refundable.address, false).awaitTransactionSuccessAsync({
 | 
			
		||||
                value: ONE_HUNDRED,
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        // This test may not be necessary, but it is included here as a sanity check.
 | 
			
		||||
        it('should fully refund the sender when `shouldNotRefund` is false for two calls in a row', async () => {
 | 
			
		||||
            // Send 100 wei to the refundable contract that should be refunded to the receiver contract.
 | 
			
		||||
            await receiver.testDisableRefundUntilEnd(refundable.address, false).awaitTransactionSuccessAsync({
 | 
			
		||||
                value: ONE_HUNDRED,
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            // Send 1000 wei to the refundable contract that should be refunded to the receiver contract.
 | 
			
		||||
            await receiver.testDisableRefundUntilEnd(refundable.address, false).awaitTransactionSuccessAsync({
 | 
			
		||||
                value: ONE_THOUSAND,
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should not refund the sender if `shouldNotRefund` is true', async () => {
 | 
			
		||||
            /// Send 100 wei to the refundable contract that should not be refunded.
 | 
			
		||||
            await receiver.testDisableRefundUntilEnd(refundable.address, false).awaitTransactionSuccessAsync({
 | 
			
		||||
                value: ONE_HUNDRED,
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should disable the `disableRefundUntilEnd` modifier and refund when `shouldNotRefund` is false', async () => {
 | 
			
		||||
            /// Send 100 wei to the refundable contract that should be refunded.
 | 
			
		||||
            await receiver.testNestedDisableRefundUntilEnd(refundable.address, false).awaitTransactionSuccessAsync({
 | 
			
		||||
                value: ONE_HUNDRED,
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should disable the `refundFinalBalance` modifier and send no refund when `shouldNotRefund` is true', async () => {
 | 
			
		||||
            /// Send 100 wei to the refundable contract that should not be refunded.
 | 
			
		||||
            await receiver.testNestedDisableRefundUntilEnd(refundable.address, true).awaitTransactionSuccessAsync({
 | 
			
		||||
                value: ONE_HUNDRED,
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should disable the `refundFinalBalance` modifier and refund when `shouldNotRefund` is false', async () => {
 | 
			
		||||
            /// Send 100 wei to the refundable contract that should be refunded.
 | 
			
		||||
            await receiver.testMixedRefunds(refundable.address, false).awaitTransactionSuccessAsync({
 | 
			
		||||
                value: ONE_HUNDRED,
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
 | 
			
		||||
        it('should disable the `refundFinalBalance` modifier and send no refund when `shouldNotRefund` is true', async () => {
 | 
			
		||||
            /// Send 100 wei to the refundable contract that should not be refunded.
 | 
			
		||||
            await receiver.testMixedRefunds(refundable.address, true).awaitTransactionSuccessAsync({
 | 
			
		||||
                value: ONE_HUNDRED,
 | 
			
		||||
            });
 | 
			
		||||
        });
 | 
			
		||||
    });
 | 
			
		||||
});
 | 
			
		||||
@@ -3,21 +3,13 @@
 | 
			
		||||
 * Warning: This file is auto-generated by contracts-gen. Don't edit manually.
 | 
			
		||||
 * -----------------------------------------------------------------------------
 | 
			
		||||
 */
 | 
			
		||||
export * from '../test/generated-wrappers/authorizable';
 | 
			
		||||
export * from '../test/generated-wrappers/authorizable_v06';
 | 
			
		||||
export * from '../test/generated-wrappers/authorizable_v08';
 | 
			
		||||
export * from '../test/generated-wrappers/d18';
 | 
			
		||||
export * from '../test/generated-wrappers/deployment_constants';
 | 
			
		||||
export * from '../test/generated-wrappers/i_authorizable';
 | 
			
		||||
export * from '../test/generated-wrappers/i_authorizable_v06';
 | 
			
		||||
export * from '../test/generated-wrappers/i_authorizable_v08';
 | 
			
		||||
export * from '../test/generated-wrappers/i_ownable';
 | 
			
		||||
export * from '../test/generated-wrappers/i_ownable_v06';
 | 
			
		||||
export * from '../test/generated-wrappers/i_ownable_v08';
 | 
			
		||||
export * from '../test/generated-wrappers/lib_address';
 | 
			
		||||
export * from '../test/generated-wrappers/lib_address_array';
 | 
			
		||||
export * from '../test/generated-wrappers/lib_address_array_rich_errors';
 | 
			
		||||
export * from '../test/generated-wrappers/lib_authorizable_rich_errors';
 | 
			
		||||
export * from '../test/generated-wrappers/lib_authorizable_rich_errors_v06';
 | 
			
		||||
export * from '../test/generated-wrappers/lib_authorizable_rich_errors_v08';
 | 
			
		||||
export * from '../test/generated-wrappers/lib_bytes';
 | 
			
		||||
@@ -26,11 +18,6 @@ export * from '../test/generated-wrappers/lib_bytes_rich_errors_v06';
 | 
			
		||||
export * from '../test/generated-wrappers/lib_bytes_rich_errors_v08';
 | 
			
		||||
export * from '../test/generated-wrappers/lib_bytes_v06';
 | 
			
		||||
export * from '../test/generated-wrappers/lib_bytes_v08';
 | 
			
		||||
export * from '../test/generated-wrappers/lib_e_i_p1271';
 | 
			
		||||
export * from '../test/generated-wrappers/lib_e_i_p712';
 | 
			
		||||
export * from '../test/generated-wrappers/lib_fractions';
 | 
			
		||||
export * from '../test/generated-wrappers/lib_math';
 | 
			
		||||
export * from '../test/generated-wrappers/lib_math_rich_errors';
 | 
			
		||||
export * from '../test/generated-wrappers/lib_math_rich_errors_v06';
 | 
			
		||||
export * from '../test/generated-wrappers/lib_math_rich_errors_v08';
 | 
			
		||||
export * from '../test/generated-wrappers/lib_math_v06';
 | 
			
		||||
@@ -53,20 +40,9 @@ export * from '../test/generated-wrappers/ownable';
 | 
			
		||||
export * from '../test/generated-wrappers/ownable_v06';
 | 
			
		||||
export * from '../test/generated-wrappers/ownable_v08';
 | 
			
		||||
export * from '../test/generated-wrappers/reentrancy_guard';
 | 
			
		||||
export * from '../test/generated-wrappers/reentrancy_guard_v06';
 | 
			
		||||
export * from '../test/generated-wrappers/reentrancy_guard_v08';
 | 
			
		||||
export * from '../test/generated-wrappers/refundable';
 | 
			
		||||
export * from '../test/generated-wrappers/test_authorizable';
 | 
			
		||||
export * from '../test/generated-wrappers/test_lib_address';
 | 
			
		||||
export * from '../test/generated-wrappers/test_lib_address_array';
 | 
			
		||||
export * from '../test/generated-wrappers/test_lib_bytes';
 | 
			
		||||
export * from '../test/generated-wrappers/test_lib_e_i_p712';
 | 
			
		||||
export * from '../test/generated-wrappers/test_lib_math';
 | 
			
		||||
export * from '../test/generated-wrappers/test_lib_rich_errors';
 | 
			
		||||
export * from '../test/generated-wrappers/test_lib_safe_math';
 | 
			
		||||
export * from '../test/generated-wrappers/test_log_decoding';
 | 
			
		||||
export * from '../test/generated-wrappers/test_log_decoding_downstream';
 | 
			
		||||
export * from '../test/generated-wrappers/test_ownable';
 | 
			
		||||
export * from '../test/generated-wrappers/test_reentrancy_guard';
 | 
			
		||||
export * from '../test/generated-wrappers/test_refundable';
 | 
			
		||||
export * from '../test/generated-wrappers/test_refundable_receiver';
 | 
			
		||||
 
 | 
			
		||||
@@ -3,20 +3,9 @@
 | 
			
		||||
    "compilerOptions": { "outDir": "lib", "rootDir": ".", "resolveJsonModule": true },
 | 
			
		||||
    "include": ["./src/**/*", "./test/**/*", "./generated-wrappers/**/*"],
 | 
			
		||||
    "files": [
 | 
			
		||||
        "generated-artifacts/Authorizable.json",
 | 
			
		||||
        "generated-artifacts/IAuthorizable.json",
 | 
			
		||||
        "generated-artifacts/IOwnable.json",
 | 
			
		||||
        "generated-artifacts/LibAddress.json",
 | 
			
		||||
        "generated-artifacts/LibAddressArray.json",
 | 
			
		||||
        "generated-artifacts/LibAddressArrayRichErrors.json",
 | 
			
		||||
        "generated-artifacts/LibAuthorizableRichErrors.json",
 | 
			
		||||
        "generated-artifacts/LibBytes.json",
 | 
			
		||||
        "generated-artifacts/LibBytesRichErrors.json",
 | 
			
		||||
        "generated-artifacts/LibEIP1271.json",
 | 
			
		||||
        "generated-artifacts/LibEIP712.json",
 | 
			
		||||
        "generated-artifacts/LibFractions.json",
 | 
			
		||||
        "generated-artifacts/LibMath.json",
 | 
			
		||||
        "generated-artifacts/LibMathRichErrors.json",
 | 
			
		||||
        "generated-artifacts/LibOwnableRichErrors.json",
 | 
			
		||||
        "generated-artifacts/LibReentrancyGuardRichErrors.json",
 | 
			
		||||
        "generated-artifacts/LibRichErrors.json",
 | 
			
		||||
@@ -24,22 +13,13 @@
 | 
			
		||||
        "generated-artifacts/LibSafeMathRichErrors.json",
 | 
			
		||||
        "generated-artifacts/Ownable.json",
 | 
			
		||||
        "generated-artifacts/ReentrancyGuard.json",
 | 
			
		||||
        "generated-artifacts/Refundable.json",
 | 
			
		||||
        "test/generated-artifacts/Authorizable.json",
 | 
			
		||||
        "test/generated-artifacts/AuthorizableV06.json",
 | 
			
		||||
        "test/generated-artifacts/AuthorizableV08.json",
 | 
			
		||||
        "test/generated-artifacts/D18.json",
 | 
			
		||||
        "test/generated-artifacts/DeploymentConstants.json",
 | 
			
		||||
        "test/generated-artifacts/IAuthorizable.json",
 | 
			
		||||
        "test/generated-artifacts/IAuthorizableV06.json",
 | 
			
		||||
        "test/generated-artifacts/IAuthorizableV08.json",
 | 
			
		||||
        "test/generated-artifacts/IOwnable.json",
 | 
			
		||||
        "test/generated-artifacts/IOwnableV06.json",
 | 
			
		||||
        "test/generated-artifacts/IOwnableV08.json",
 | 
			
		||||
        "test/generated-artifacts/LibAddress.json",
 | 
			
		||||
        "test/generated-artifacts/LibAddressArray.json",
 | 
			
		||||
        "test/generated-artifacts/LibAddressArrayRichErrors.json",
 | 
			
		||||
        "test/generated-artifacts/LibAuthorizableRichErrors.json",
 | 
			
		||||
        "test/generated-artifacts/LibAuthorizableRichErrorsV06.json",
 | 
			
		||||
        "test/generated-artifacts/LibAuthorizableRichErrorsV08.json",
 | 
			
		||||
        "test/generated-artifacts/LibBytes.json",
 | 
			
		||||
@@ -48,11 +28,6 @@
 | 
			
		||||
        "test/generated-artifacts/LibBytesRichErrorsV08.json",
 | 
			
		||||
        "test/generated-artifacts/LibBytesV06.json",
 | 
			
		||||
        "test/generated-artifacts/LibBytesV08.json",
 | 
			
		||||
        "test/generated-artifacts/LibEIP1271.json",
 | 
			
		||||
        "test/generated-artifacts/LibEIP712.json",
 | 
			
		||||
        "test/generated-artifacts/LibFractions.json",
 | 
			
		||||
        "test/generated-artifacts/LibMath.json",
 | 
			
		||||
        "test/generated-artifacts/LibMathRichErrors.json",
 | 
			
		||||
        "test/generated-artifacts/LibMathRichErrorsV06.json",
 | 
			
		||||
        "test/generated-artifacts/LibMathRichErrorsV08.json",
 | 
			
		||||
        "test/generated-artifacts/LibMathV06.json",
 | 
			
		||||
@@ -75,23 +50,12 @@
 | 
			
		||||
        "test/generated-artifacts/OwnableV06.json",
 | 
			
		||||
        "test/generated-artifacts/OwnableV08.json",
 | 
			
		||||
        "test/generated-artifacts/ReentrancyGuard.json",
 | 
			
		||||
        "test/generated-artifacts/ReentrancyGuardV06.json",
 | 
			
		||||
        "test/generated-artifacts/ReentrancyGuardV08.json",
 | 
			
		||||
        "test/generated-artifacts/Refundable.json",
 | 
			
		||||
        "test/generated-artifacts/TestAuthorizable.json",
 | 
			
		||||
        "test/generated-artifacts/TestLibAddress.json",
 | 
			
		||||
        "test/generated-artifacts/TestLibAddressArray.json",
 | 
			
		||||
        "test/generated-artifacts/TestLibBytes.json",
 | 
			
		||||
        "test/generated-artifacts/TestLibEIP712.json",
 | 
			
		||||
        "test/generated-artifacts/TestLibMath.json",
 | 
			
		||||
        "test/generated-artifacts/TestLibRichErrors.json",
 | 
			
		||||
        "test/generated-artifacts/TestLibSafeMath.json",
 | 
			
		||||
        "test/generated-artifacts/TestLogDecoding.json",
 | 
			
		||||
        "test/generated-artifacts/TestLogDecodingDownstream.json",
 | 
			
		||||
        "test/generated-artifacts/TestOwnable.json",
 | 
			
		||||
        "test/generated-artifacts/TestReentrancyGuard.json",
 | 
			
		||||
        "test/generated-artifacts/TestRefundable.json",
 | 
			
		||||
        "test/generated-artifacts/TestRefundableReceiver.json"
 | 
			
		||||
        "test/generated-artifacts/TestReentrancyGuard.json"
 | 
			
		||||
    ],
 | 
			
		||||
    "exclude": ["./deploy/solc/solc_bin"]
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,12 @@
 | 
			
		||||
[
 | 
			
		||||
    {
 | 
			
		||||
        "version": "0.39.0",
 | 
			
		||||
        "changes": [
 | 
			
		||||
            {
 | 
			
		||||
                "note": "Add KyberElastic mixin for Ethereum, Polygon, Arbitrum, Avalanche"
 | 
			
		||||
            }
 | 
			
		||||
        ]
 | 
			
		||||
    },
 | 
			
		||||
    {
 | 
			
		||||
        "timestamp": 1675210931,
 | 
			
		||||
        "version": "0.38.6",
 | 
			
		||||
 
 | 
			
		||||
@@ -20,6 +20,7 @@ import "./features/interfaces/ISimpleFunctionRegistryFeature.sol";
 | 
			
		||||
import "./features/interfaces/ITokenSpenderFeature.sol";
 | 
			
		||||
import "./features/interfaces/ITransformERC20Feature.sol";
 | 
			
		||||
import "./features/interfaces/IMetaTransactionsFeature.sol";
 | 
			
		||||
import "./features/interfaces/IMetaTransactionsFeatureV2.sol";
 | 
			
		||||
import "./features/interfaces/IUniswapFeature.sol";
 | 
			
		||||
import "./features/interfaces/IUniswapV3Feature.sol";
 | 
			
		||||
import "./features/interfaces/IPancakeSwapFeature.sol";
 | 
			
		||||
@@ -39,6 +40,7 @@ interface IZeroEx is
 | 
			
		||||
    ISimpleFunctionRegistryFeature,
 | 
			
		||||
    ITransformERC20Feature,
 | 
			
		||||
    IMetaTransactionsFeature,
 | 
			
		||||
    IMetaTransactionsFeatureV2,
 | 
			
		||||
    IUniswapFeature,
 | 
			
		||||
    IUniswapV3Feature,
 | 
			
		||||
    IPancakeSwapFeature,
 | 
			
		||||
 
 | 
			
		||||
@@ -15,7 +15,7 @@
 | 
			
		||||
pragma solidity ^0.6.5;
 | 
			
		||||
pragma experimental ABIEncoderV2;
 | 
			
		||||
 | 
			
		||||
import "@0x/contracts-erc20/contracts/src/v06/IEtherTokenV06.sol";
 | 
			
		||||
import "@0x/contracts-erc20/src/IEtherToken.sol";
 | 
			
		||||
import "@0x/contracts-utils/contracts/src/v06/AuthorizableV06.sol";
 | 
			
		||||
import "../vendor/v3/IStaking.sol";
 | 
			
		||||
 | 
			
		||||
@@ -33,14 +33,14 @@ contract FeeCollector is AuthorizableV06 {
 | 
			
		||||
    /// @param weth The WETH contract.
 | 
			
		||||
    /// @param staking The staking contract.
 | 
			
		||||
    /// @param poolId The pool ID this contract is collecting fees for.
 | 
			
		||||
    function initialize(IEtherTokenV06 weth, IStaking staking, bytes32 poolId) external onlyAuthorized {
 | 
			
		||||
    function initialize(IEtherToken weth, IStaking staking, bytes32 poolId) external onlyAuthorized {
 | 
			
		||||
        weth.approve(address(staking), type(uint256).max);
 | 
			
		||||
        staking.joinStakingPoolAsMaker(poolId);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Convert all held ether to WETH. Only an authority can call this.
 | 
			
		||||
    /// @param weth The WETH contract.
 | 
			
		||||
    function convertToWeth(IEtherTokenV06 weth) external onlyAuthorized {
 | 
			
		||||
    function convertToWeth(IEtherToken weth) external onlyAuthorized {
 | 
			
		||||
        if (address(this).balance > 0) {
 | 
			
		||||
            weth.deposit{value: address(this).balance}();
 | 
			
		||||
        }
 | 
			
		||||
 
 | 
			
		||||
@@ -15,7 +15,7 @@
 | 
			
		||||
pragma solidity ^0.6.5;
 | 
			
		||||
pragma experimental ABIEncoderV2;
 | 
			
		||||
 | 
			
		||||
import "@0x/contracts-erc20/contracts/src/v06/IEtherTokenV06.sol";
 | 
			
		||||
import "@0x/contracts-erc20/src/IEtherToken.sol";
 | 
			
		||||
import "../vendor/v3/IStaking.sol";
 | 
			
		||||
import "./FeeCollector.sol";
 | 
			
		||||
import "./LibFeeCollector.sol";
 | 
			
		||||
@@ -25,11 +25,11 @@ contract FeeCollectorController {
 | 
			
		||||
    /// @dev Hash of the fee collector init code.
 | 
			
		||||
    bytes32 public immutable FEE_COLLECTOR_INIT_CODE_HASH;
 | 
			
		||||
    /// @dev The WETH contract.
 | 
			
		||||
    IEtherTokenV06 private immutable WETH;
 | 
			
		||||
    IEtherToken private immutable WETH;
 | 
			
		||||
    /// @dev The staking contract.
 | 
			
		||||
    IStaking private immutable STAKING;
 | 
			
		||||
 | 
			
		||||
    constructor(IEtherTokenV06 weth, IStaking staking) public {
 | 
			
		||||
    constructor(IEtherToken weth, IStaking staking) public {
 | 
			
		||||
        FEE_COLLECTOR_INIT_CODE_HASH = keccak256(type(FeeCollector).creationCode);
 | 
			
		||||
        WETH = weth;
 | 
			
		||||
        STAKING = staking;
 | 
			
		||||
 
 | 
			
		||||
@@ -15,7 +15,7 @@
 | 
			
		||||
pragma solidity ^0.6.5;
 | 
			
		||||
pragma experimental ABIEncoderV2;
 | 
			
		||||
 | 
			
		||||
import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol";
 | 
			
		||||
import "@0x/contracts-erc20/src/IERC20Token.sol";
 | 
			
		||||
import "../vendor/ILiquidityProvider.sol";
 | 
			
		||||
 | 
			
		||||
interface ILiquidityProviderSandbox {
 | 
			
		||||
@@ -29,8 +29,8 @@ interface ILiquidityProviderSandbox {
 | 
			
		||||
    /// @param auxiliaryData Auxiliary data supplied to the `provider` contract.
 | 
			
		||||
    function executeSellTokenForToken(
 | 
			
		||||
        ILiquidityProvider provider,
 | 
			
		||||
        IERC20TokenV06 inputToken,
 | 
			
		||||
        IERC20TokenV06 outputToken,
 | 
			
		||||
        IERC20Token inputToken,
 | 
			
		||||
        IERC20Token outputToken,
 | 
			
		||||
        address recipient,
 | 
			
		||||
        uint256 minBuyAmount,
 | 
			
		||||
        bytes calldata auxiliaryData
 | 
			
		||||
@@ -45,7 +45,7 @@ interface ILiquidityProviderSandbox {
 | 
			
		||||
    /// @param auxiliaryData Auxiliary data supplied to the `provider` contract.
 | 
			
		||||
    function executeSellEthForToken(
 | 
			
		||||
        ILiquidityProvider provider,
 | 
			
		||||
        IERC20TokenV06 outputToken,
 | 
			
		||||
        IERC20Token outputToken,
 | 
			
		||||
        address recipient,
 | 
			
		||||
        uint256 minBuyAmount,
 | 
			
		||||
        bytes calldata auxiliaryData
 | 
			
		||||
@@ -60,7 +60,7 @@ interface ILiquidityProviderSandbox {
 | 
			
		||||
    /// @param auxiliaryData Auxiliary data supplied to the `provider` contract.
 | 
			
		||||
    function executeSellTokenForEth(
 | 
			
		||||
        ILiquidityProvider provider,
 | 
			
		||||
        IERC20TokenV06 inputToken,
 | 
			
		||||
        IERC20Token inputToken,
 | 
			
		||||
        address recipient,
 | 
			
		||||
        uint256 minBuyAmount,
 | 
			
		||||
        bytes calldata auxiliaryData
 | 
			
		||||
 
 | 
			
		||||
@@ -17,7 +17,7 @@ pragma experimental ABIEncoderV2;
 | 
			
		||||
 | 
			
		||||
import "@0x/contracts-utils/contracts/src/v06/errors/LibRichErrorsV06.sol";
 | 
			
		||||
import "@0x/contracts-utils/contracts/src/v06/errors/LibOwnableRichErrorsV06.sol";
 | 
			
		||||
import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol";
 | 
			
		||||
import "@0x/contracts-erc20/src/IERC20Token.sol";
 | 
			
		||||
import "../vendor/ILiquidityProvider.sol";
 | 
			
		||||
import "../vendor/v3/IERC20Bridge.sol";
 | 
			
		||||
import "./ILiquidityProviderSandbox.sol";
 | 
			
		||||
@@ -52,8 +52,8 @@ contract LiquidityProviderSandbox is ILiquidityProviderSandbox {
 | 
			
		||||
    /// @param auxiliaryData Auxiliary data supplied to the `provider` contract.
 | 
			
		||||
    function executeSellTokenForToken(
 | 
			
		||||
        ILiquidityProvider provider,
 | 
			
		||||
        IERC20TokenV06 inputToken,
 | 
			
		||||
        IERC20TokenV06 outputToken,
 | 
			
		||||
        IERC20Token inputToken,
 | 
			
		||||
        IERC20Token outputToken,
 | 
			
		||||
        address recipient,
 | 
			
		||||
        uint256 minBuyAmount,
 | 
			
		||||
        bytes calldata auxiliaryData
 | 
			
		||||
@@ -70,7 +70,7 @@ contract LiquidityProviderSandbox is ILiquidityProviderSandbox {
 | 
			
		||||
    /// @param auxiliaryData Auxiliary data supplied to the `provider` contract.
 | 
			
		||||
    function executeSellEthForToken(
 | 
			
		||||
        ILiquidityProvider provider,
 | 
			
		||||
        IERC20TokenV06 outputToken,
 | 
			
		||||
        IERC20Token outputToken,
 | 
			
		||||
        address recipient,
 | 
			
		||||
        uint256 minBuyAmount,
 | 
			
		||||
        bytes calldata auxiliaryData
 | 
			
		||||
@@ -87,7 +87,7 @@ contract LiquidityProviderSandbox is ILiquidityProviderSandbox {
 | 
			
		||||
    /// @param auxiliaryData Auxiliary data supplied to the `provider` contract.
 | 
			
		||||
    function executeSellTokenForEth(
 | 
			
		||||
        ILiquidityProvider provider,
 | 
			
		||||
        IERC20TokenV06 inputToken,
 | 
			
		||||
        IERC20Token inputToken,
 | 
			
		||||
        address recipient,
 | 
			
		||||
        uint256 minBuyAmount,
 | 
			
		||||
        bytes calldata auxiliaryData
 | 
			
		||||
 
 | 
			
		||||
@@ -15,7 +15,7 @@
 | 
			
		||||
pragma solidity ^0.6.5;
 | 
			
		||||
pragma experimental ABIEncoderV2;
 | 
			
		||||
 | 
			
		||||
import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol";
 | 
			
		||||
import "@0x/contracts-erc20/src/IERC20Token.sol";
 | 
			
		||||
import "../migrations/LibMigrate.sol";
 | 
			
		||||
import "../fixins/FixinCommon.sol";
 | 
			
		||||
import "./interfaces/IFeature.sol";
 | 
			
		||||
@@ -41,7 +41,7 @@ contract FundRecoveryFeature is IFeature, IFundRecoveryFeature, FixinCommon {
 | 
			
		||||
    /// @param amountOut Amount of tokens to withdraw.
 | 
			
		||||
    /// @param recipientWallet Recipient wallet address.
 | 
			
		||||
    function transferTrappedTokensTo(
 | 
			
		||||
        IERC20TokenV06 erc20,
 | 
			
		||||
        IERC20Token erc20,
 | 
			
		||||
        uint256 amountOut,
 | 
			
		||||
        address payable recipientWallet
 | 
			
		||||
    ) external override onlyOwner {
 | 
			
		||||
 
 | 
			
		||||
@@ -15,10 +15,9 @@
 | 
			
		||||
pragma solidity ^0.6.5;
 | 
			
		||||
pragma experimental ABIEncoderV2;
 | 
			
		||||
 | 
			
		||||
import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol";
 | 
			
		||||
import "@0x/contracts-erc20/src/IERC20Token.sol";
 | 
			
		||||
import "@0x/contracts-utils/contracts/src/v06/errors/LibRichErrorsV06.sol";
 | 
			
		||||
import "@0x/contracts-utils/contracts/src/v06/LibSafeMathV06.sol";
 | 
			
		||||
import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol";
 | 
			
		||||
import "../errors/LibLiquidityProviderRichErrors.sol";
 | 
			
		||||
import "../external/ILiquidityProviderSandbox.sol";
 | 
			
		||||
import "../external/LiquidityProviderSandbox.sol";
 | 
			
		||||
@@ -67,8 +66,8 @@ contract LiquidityProviderFeature is IFeature, ILiquidityProviderFeature, FixinC
 | 
			
		||||
    /// @param auxiliaryData Auxiliary data supplied to the `provider` contract.
 | 
			
		||||
    /// @return boughtAmount The amount of `outputToken` bought.
 | 
			
		||||
    function sellToLiquidityProvider(
 | 
			
		||||
        IERC20TokenV06 inputToken,
 | 
			
		||||
        IERC20TokenV06 outputToken,
 | 
			
		||||
        IERC20Token inputToken,
 | 
			
		||||
        IERC20Token outputToken,
 | 
			
		||||
        ILiquidityProvider provider,
 | 
			
		||||
        address recipient,
 | 
			
		||||
        uint256 sellAmount,
 | 
			
		||||
@@ -92,7 +91,7 @@ contract LiquidityProviderFeature is IFeature, ILiquidityProviderFeature, FixinC
 | 
			
		||||
        if (LibERC20Transformer.isTokenETH(inputToken)) {
 | 
			
		||||
            uint256 balanceBefore = outputToken.balanceOf(recipient);
 | 
			
		||||
            sandbox.executeSellEthForToken(provider, outputToken, recipient, minBuyAmount, auxiliaryData);
 | 
			
		||||
            boughtAmount = IERC20TokenV06(outputToken).balanceOf(recipient).safeSub(balanceBefore);
 | 
			
		||||
            boughtAmount = IERC20Token(outputToken).balanceOf(recipient).safeSub(balanceBefore);
 | 
			
		||||
        } else if (LibERC20Transformer.isTokenETH(outputToken)) {
 | 
			
		||||
            uint256 balanceBefore = recipient.balance;
 | 
			
		||||
            sandbox.executeSellTokenForEth(provider, inputToken, recipient, minBuyAmount, auxiliaryData);
 | 
			
		||||
 
 | 
			
		||||
@@ -63,8 +63,8 @@ contract MetaTransactionsFeature is
 | 
			
		||||
 | 
			
		||||
    /// @dev Arguments for a `TransformERC20.transformERC20()` call.
 | 
			
		||||
    struct ExternalTransformERC20Args {
 | 
			
		||||
        IERC20TokenV06 inputToken;
 | 
			
		||||
        IERC20TokenV06 outputToken;
 | 
			
		||||
        IERC20Token inputToken;
 | 
			
		||||
        IERC20Token outputToken;
 | 
			
		||||
        uint256 inputTokenAmount;
 | 
			
		||||
        uint256 minOutputTokenAmount;
 | 
			
		||||
        ITransformERC20Feature.Transformation[] transformations;
 | 
			
		||||
 
 | 
			
		||||
@@ -0,0 +1,616 @@
 | 
			
		||||
// SPDX-License-Identifier: Apache-2.0
 | 
			
		||||
/*
 | 
			
		||||
  Copyright 2023 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/src/IEtherToken.sol";
 | 
			
		||||
import "@0x/contracts-utils/contracts/src/v06/errors/LibRichErrorsV06.sol";
 | 
			
		||||
import "@0x/contracts-utils/contracts/src/v06/LibBytesV06.sol";
 | 
			
		||||
import "@0x/contracts-utils/contracts/src/v06/LibSafeMathV06.sol";
 | 
			
		||||
import "../errors/LibMetaTransactionsRichErrors.sol";
 | 
			
		||||
import "../fixins/FixinCommon.sol";
 | 
			
		||||
import "../fixins/FixinReentrancyGuard.sol";
 | 
			
		||||
import "../fixins/FixinTokenSpender.sol";
 | 
			
		||||
import "../fixins/FixinEIP712.sol";
 | 
			
		||||
import "../migrations/LibMigrate.sol";
 | 
			
		||||
import "../storage/LibMetaTransactionsV2Storage.sol";
 | 
			
		||||
import "./interfaces/IFeature.sol";
 | 
			
		||||
import "./interfaces/IMetaTransactionsFeatureV2.sol";
 | 
			
		||||
import "./interfaces/IMultiplexFeature.sol";
 | 
			
		||||
import "./interfaces/INativeOrdersFeature.sol";
 | 
			
		||||
import "./interfaces/ITransformERC20Feature.sol";
 | 
			
		||||
import "./libs/LibSignature.sol";
 | 
			
		||||
 | 
			
		||||
/// @dev MetaTransactions feature.
 | 
			
		||||
contract MetaTransactionsFeatureV2 is
 | 
			
		||||
    IFeature,
 | 
			
		||||
    IMetaTransactionsFeatureV2,
 | 
			
		||||
    FixinCommon,
 | 
			
		||||
    FixinReentrancyGuard,
 | 
			
		||||
    FixinEIP712,
 | 
			
		||||
    FixinTokenSpender
 | 
			
		||||
{
 | 
			
		||||
    using LibBytesV06 for bytes;
 | 
			
		||||
    using LibRichErrorsV06 for bytes;
 | 
			
		||||
 | 
			
		||||
    /// @dev Describes the state of a meta transaction.
 | 
			
		||||
    struct ExecuteState {
 | 
			
		||||
        // Sender of the meta-transaction.
 | 
			
		||||
        address sender;
 | 
			
		||||
        // Hash of the meta-transaction data.
 | 
			
		||||
        bytes32 hash;
 | 
			
		||||
        // The meta-transaction data.
 | 
			
		||||
        MetaTransactionDataV2 mtx;
 | 
			
		||||
        // The meta-transaction signature (by `mtx.signer`).
 | 
			
		||||
        LibSignature.Signature signature;
 | 
			
		||||
        // The selector of the function being called.
 | 
			
		||||
        bytes4 selector;
 | 
			
		||||
        // The ETH balance of this contract before performing the call.
 | 
			
		||||
        uint256 selfBalance;
 | 
			
		||||
        // The block number at which the meta-transaction was executed.
 | 
			
		||||
        uint256 executedBlockNumber;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Arguments for a `TransformERC20.transformERC20()` call.
 | 
			
		||||
    struct ExternalTransformERC20Args {
 | 
			
		||||
        IERC20Token inputToken;
 | 
			
		||||
        IERC20Token outputToken;
 | 
			
		||||
        uint256 inputTokenAmount;
 | 
			
		||||
        uint256 minOutputTokenAmount;
 | 
			
		||||
        ITransformERC20Feature.Transformation[] transformations;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Name of this feature.
 | 
			
		||||
    string public constant override FEATURE_NAME = "MetaTransactionsV2";
 | 
			
		||||
    /// @dev Version of this feature.
 | 
			
		||||
    uint256 public immutable override FEATURE_VERSION = _encodeVersion(1, 0, 0);
 | 
			
		||||
    /// @dev EIP712 typehash of the `MetaTransactionData` struct.
 | 
			
		||||
    bytes32 public immutable MTX_EIP712_TYPEHASH =
 | 
			
		||||
        keccak256(
 | 
			
		||||
            "MetaTransactionDataV2("
 | 
			
		||||
            "address signer,"
 | 
			
		||||
            "address sender,"
 | 
			
		||||
            "uint256 expirationTimeSeconds,"
 | 
			
		||||
            "uint256 salt,"
 | 
			
		||||
            "bytes callData,"
 | 
			
		||||
            "address feeToken,"
 | 
			
		||||
            "MetaTransactionFeeData[] fees"
 | 
			
		||||
            ")"
 | 
			
		||||
            "MetaTransactionFeeData("
 | 
			
		||||
            "address recipient,"
 | 
			
		||||
            "uint256 amount"
 | 
			
		||||
            ")"
 | 
			
		||||
        );
 | 
			
		||||
    bytes32 public immutable MTX_FEE_TYPEHASH =
 | 
			
		||||
        keccak256(
 | 
			
		||||
            "MetaTransactionFeeData("
 | 
			
		||||
            "address recipient,"
 | 
			
		||||
            "uint256 amount"
 | 
			
		||||
            ")"
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
    /// @dev The WETH token contract.
 | 
			
		||||
    IEtherToken private immutable WETH;
 | 
			
		||||
 | 
			
		||||
    /// @dev Ensures that the ETH balance of `this` does not go below the
 | 
			
		||||
    ///      initial ETH balance before the call (excluding ETH attached to the call).
 | 
			
		||||
    modifier doesNotReduceEthBalance() {
 | 
			
		||||
        uint256 initialBalance = address(this).balance;
 | 
			
		||||
        _;
 | 
			
		||||
        require(initialBalance <= address(this).balance, "MetaTransactionsFeatureV2/ETH_LEAK");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    constructor(address zeroExAddress, IEtherToken weth) public FixinCommon() FixinEIP712(zeroExAddress) {
 | 
			
		||||
        WETH = weth;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @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.executeMetaTransactionV2.selector);
 | 
			
		||||
        _registerFeatureFunction(this.batchExecuteMetaTransactionsV2.selector);
 | 
			
		||||
        _registerFeatureFunction(this.getMetaTransactionV2ExecutedBlock.selector);
 | 
			
		||||
        _registerFeatureFunction(this.getMetaTransactionV2HashExecutedBlock.selector);
 | 
			
		||||
        _registerFeatureFunction(this.getMetaTransactionV2Hash.selector);
 | 
			
		||||
        return LibMigrate.MIGRATE_SUCCESS;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Execute a single meta-transaction.
 | 
			
		||||
    /// @param mtx The meta-transaction.
 | 
			
		||||
    /// @param signature The signature by `mtx.signer`.
 | 
			
		||||
    /// @return returnResult The ABI-encoded result of the underlying call.
 | 
			
		||||
    function executeMetaTransactionV2(
 | 
			
		||||
        MetaTransactionDataV2 memory mtx,
 | 
			
		||||
        LibSignature.Signature memory signature
 | 
			
		||||
    ) public override nonReentrant(REENTRANCY_MTX) doesNotReduceEthBalance returns (bytes memory returnResult) {
 | 
			
		||||
        ExecuteState memory state;
 | 
			
		||||
        state.sender = msg.sender;
 | 
			
		||||
        state.mtx = mtx;
 | 
			
		||||
        state.hash = getMetaTransactionV2Hash(mtx);
 | 
			
		||||
        state.signature = signature;
 | 
			
		||||
 | 
			
		||||
        returnResult = _executeMetaTransactionPrivate(state);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Execute multiple meta-transactions.
 | 
			
		||||
    /// @param mtxs The meta-transactions.
 | 
			
		||||
    /// @param signatures The signature by each respective `mtx.signer`.
 | 
			
		||||
    /// @return returnResults The ABI-encoded results of the underlying calls.
 | 
			
		||||
    function batchExecuteMetaTransactionsV2(
 | 
			
		||||
        MetaTransactionDataV2[] memory mtxs,
 | 
			
		||||
        LibSignature.Signature[] memory signatures
 | 
			
		||||
    ) public override nonReentrant(REENTRANCY_MTX) doesNotReduceEthBalance returns (bytes[] memory returnResults) {
 | 
			
		||||
        if (mtxs.length != signatures.length) {
 | 
			
		||||
            LibMetaTransactionsRichErrors
 | 
			
		||||
                .InvalidMetaTransactionsArrayLengthsError(mtxs.length, signatures.length)
 | 
			
		||||
                .rrevert();
 | 
			
		||||
        }
 | 
			
		||||
        returnResults = new bytes[](mtxs.length);
 | 
			
		||||
        for (uint256 i = 0; i < mtxs.length; ++i) {
 | 
			
		||||
            ExecuteState memory state;
 | 
			
		||||
            state.sender = msg.sender;
 | 
			
		||||
            state.mtx = mtxs[i];
 | 
			
		||||
            state.hash = getMetaTransactionV2Hash(mtxs[i]);
 | 
			
		||||
            state.signature = signatures[i];
 | 
			
		||||
 | 
			
		||||
            returnResults[i] = _executeMetaTransactionPrivate(state);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Get the block at which a meta-transaction has been executed.
 | 
			
		||||
    /// @param mtx The meta-transaction.
 | 
			
		||||
    /// @return blockNumber The block height when the meta-transactioin was executed.
 | 
			
		||||
    function getMetaTransactionV2ExecutedBlock(
 | 
			
		||||
        MetaTransactionDataV2 memory mtx
 | 
			
		||||
    ) public view override returns (uint256 blockNumber) {
 | 
			
		||||
        return getMetaTransactionV2HashExecutedBlock(getMetaTransactionV2Hash(mtx));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Get the block at which a meta-transaction hash has been executed.
 | 
			
		||||
    /// @param mtxHash The meta-transaction hash.
 | 
			
		||||
    /// @return blockNumber The block height when the meta-transactioin was executed.
 | 
			
		||||
    function getMetaTransactionV2HashExecutedBlock(bytes32 mtxHash) public view override returns (uint256 blockNumber) {
 | 
			
		||||
        return LibMetaTransactionsV2Storage.getStorage().mtxHashToExecutedBlockNumber[mtxHash];
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Get the EIP712 hash of a meta-transaction.
 | 
			
		||||
    /// @param mtx The meta-transaction.
 | 
			
		||||
    /// @return mtxHash The EIP712 hash of `mtx`.
 | 
			
		||||
    function getMetaTransactionV2Hash(MetaTransactionDataV2 memory mtx) public view override returns (bytes32 mtxHash) {
 | 
			
		||||
        bytes32[] memory feeHashes = new bytes32[](mtx.fees.length);
 | 
			
		||||
        for (uint256 i = 0; i < mtx.fees.length; ++i) {
 | 
			
		||||
            feeHashes[i] = keccak256(abi.encode(MTX_FEE_TYPEHASH, mtx.fees[i]));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return
 | 
			
		||||
            _getEIP712Hash(
 | 
			
		||||
                keccak256(
 | 
			
		||||
                    abi.encode(
 | 
			
		||||
                        MTX_EIP712_TYPEHASH,
 | 
			
		||||
                        mtx.signer,
 | 
			
		||||
                        mtx.sender,
 | 
			
		||||
                        mtx.expirationTimeSeconds,
 | 
			
		||||
                        mtx.salt,
 | 
			
		||||
                        keccak256(mtx.callData),
 | 
			
		||||
                        mtx.feeToken,
 | 
			
		||||
                        keccak256(abi.encodePacked(feeHashes))
 | 
			
		||||
                    )
 | 
			
		||||
                )
 | 
			
		||||
            );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Execute a meta-transaction by `sender`. Low-level, hidden variant.
 | 
			
		||||
    /// @param state The `ExecuteState` for this metatransaction, with `sender`,
 | 
			
		||||
    ///              `hash`, `mtx`, and `signature` fields filled.
 | 
			
		||||
    /// @return returnResult The ABI-encoded result of the underlying call.
 | 
			
		||||
    function _executeMetaTransactionPrivate(ExecuteState memory state) private returns (bytes memory returnResult) {
 | 
			
		||||
        _validateMetaTransaction(state);
 | 
			
		||||
 | 
			
		||||
        // Mark the transaction executed by storing the block at which it was executed.
 | 
			
		||||
        // Currently the block number just indicates that the mtx was executed and
 | 
			
		||||
        // serves no other purpose from within this contract.
 | 
			
		||||
        LibMetaTransactionsV2Storage.getStorage().mtxHashToExecutedBlockNumber[state.hash] = block.number;
 | 
			
		||||
 | 
			
		||||
        // Pay the fees to the fee recipients.
 | 
			
		||||
        for (uint256 i = 0; i < state.mtx.fees.length; ++i) {
 | 
			
		||||
            _transferERC20TokensFrom(
 | 
			
		||||
                state.mtx.feeToken,
 | 
			
		||||
                state.mtx.signer,
 | 
			
		||||
                state.mtx.fees[i].recipient,
 | 
			
		||||
                state.mtx.fees[i].amount
 | 
			
		||||
            );
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Execute the call based on the selector.
 | 
			
		||||
        state.selector = state.mtx.callData.readBytes4(0);
 | 
			
		||||
        if (state.selector == ITransformERC20Feature.transformERC20.selector) {
 | 
			
		||||
            returnResult = _executeTransformERC20Call(state);
 | 
			
		||||
        } else if (state.selector == INativeOrdersFeature.fillLimitOrder.selector) {
 | 
			
		||||
            returnResult = _executeFillLimitOrderCall(state);
 | 
			
		||||
        } else if (state.selector == INativeOrdersFeature.fillRfqOrder.selector) {
 | 
			
		||||
            returnResult = _executeFillRfqOrderCall(state);
 | 
			
		||||
        } else if (state.selector == IMultiplexFeature.multiplexBatchSellTokenForToken.selector) {
 | 
			
		||||
            returnResult = _executeMultiplexBatchSellTokenForTokenCall(state);
 | 
			
		||||
        } else if (state.selector == IMultiplexFeature.multiplexBatchSellTokenForEth.selector) {
 | 
			
		||||
            returnResult = _executeMultiplexBatchSellTokenForEthCall(state);
 | 
			
		||||
        } else if (state.selector == IMultiplexFeature.multiplexMultiHopSellTokenForToken.selector) {
 | 
			
		||||
            returnResult = _executeMultiplexMultiHopSellTokenForTokenCall(state);
 | 
			
		||||
        } else if (state.selector == IMultiplexFeature.multiplexMultiHopSellTokenForEth.selector) {
 | 
			
		||||
            returnResult = _executeMultiplexMultiHopSellTokenForEthCall(state);
 | 
			
		||||
        } else {
 | 
			
		||||
            LibMetaTransactionsRichErrors.MetaTransactionUnsupportedFunctionError(state.hash, state.selector).rrevert();
 | 
			
		||||
        }
 | 
			
		||||
        emit MetaTransactionExecuted(state.hash, state.selector, state.mtx.signer, state.mtx.sender);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Validate that a meta-transaction is executable.
 | 
			
		||||
    function _validateMetaTransaction(ExecuteState memory state) private view {
 | 
			
		||||
        // Must be from the required sender, if set.
 | 
			
		||||
        if (state.mtx.sender != address(0) && state.mtx.sender != state.sender) {
 | 
			
		||||
            LibMetaTransactionsRichErrors
 | 
			
		||||
                .MetaTransactionWrongSenderError(state.hash, state.sender, state.mtx.sender)
 | 
			
		||||
                .rrevert();
 | 
			
		||||
        }
 | 
			
		||||
        // Must not be expired.
 | 
			
		||||
        if (state.mtx.expirationTimeSeconds <= block.timestamp) {
 | 
			
		||||
            LibMetaTransactionsRichErrors
 | 
			
		||||
                .MetaTransactionExpiredError(state.hash, block.timestamp, state.mtx.expirationTimeSeconds)
 | 
			
		||||
                .rrevert();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (LibSignature.getSignerOfHash(state.hash, state.signature) != state.mtx.signer) {
 | 
			
		||||
            LibSignatureRichErrors
 | 
			
		||||
                .SignatureValidationError(
 | 
			
		||||
                    LibSignatureRichErrors.SignatureValidationErrorCodes.WRONG_SIGNER,
 | 
			
		||||
                    state.hash,
 | 
			
		||||
                    state.mtx.signer,
 | 
			
		||||
                    // TODO: Remove this field from SignatureValidationError
 | 
			
		||||
                    //       when rich reverts are part of the protocol repo.
 | 
			
		||||
                    ""
 | 
			
		||||
                )
 | 
			
		||||
                .rrevert();
 | 
			
		||||
        }
 | 
			
		||||
        // Transaction must not have been already executed.
 | 
			
		||||
        state.executedBlockNumber = LibMetaTransactionsV2Storage.getStorage().mtxHashToExecutedBlockNumber[state.hash];
 | 
			
		||||
        if (state.executedBlockNumber != 0) {
 | 
			
		||||
            LibMetaTransactionsRichErrors
 | 
			
		||||
                .MetaTransactionAlreadyExecutedError(state.hash, state.executedBlockNumber)
 | 
			
		||||
                .rrevert();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Execute a `ITransformERC20Feature.transformERC20()` meta-transaction call
 | 
			
		||||
    ///      by decoding the call args and translating the call to the internal
 | 
			
		||||
    ///      `ITransformERC20Feature._transformERC20()` variant, where we can override
 | 
			
		||||
    ///      the taker address.
 | 
			
		||||
    function _executeTransformERC20Call(ExecuteState memory state) private returns (bytes memory returnResult) {
 | 
			
		||||
        // HACK(dorothy-zbornak): `abi.decode()` with the individual args
 | 
			
		||||
        // will cause a stack overflow. But we can prefix the call data with an
 | 
			
		||||
        // offset to transform it into the encoding for the equivalent single struct arg,
 | 
			
		||||
        // since decoding a single struct arg consumes far less stack space than
 | 
			
		||||
        // decoding multiple struct args.
 | 
			
		||||
 | 
			
		||||
        // Where the encoding for multiple args (with the selector ommitted)
 | 
			
		||||
        // would typically look like:
 | 
			
		||||
        // | argument                 |  offset |
 | 
			
		||||
        // |--------------------------|---------|
 | 
			
		||||
        // | inputToken               |       0 |
 | 
			
		||||
        // | outputToken              |      32 |
 | 
			
		||||
        // | inputTokenAmount         |      64 |
 | 
			
		||||
        // | minOutputTokenAmount     |      96 |
 | 
			
		||||
        // | transformations (offset) |     128 | = 32
 | 
			
		||||
        // | transformations (data)   |     160 |
 | 
			
		||||
 | 
			
		||||
        // We will ABI-decode a single struct arg copy with the layout:
 | 
			
		||||
        // | argument                 |  offset |
 | 
			
		||||
        // |--------------------------|---------|
 | 
			
		||||
        // | (arg 1 offset)           |       0 | = 32
 | 
			
		||||
        // | inputToken               |      32 |
 | 
			
		||||
        // | outputToken              |      64 |
 | 
			
		||||
        // | inputTokenAmount         |      96 |
 | 
			
		||||
        // | minOutputTokenAmount     |     128 |
 | 
			
		||||
        // | transformations (offset) |     160 | = 32
 | 
			
		||||
        // | transformations (data)   |     192 |
 | 
			
		||||
 | 
			
		||||
        ExternalTransformERC20Args memory args;
 | 
			
		||||
        {
 | 
			
		||||
            bytes memory encodedStructArgs = new bytes(state.mtx.callData.length - 4 + 32);
 | 
			
		||||
            // Copy the args data from the original, after the new struct offset prefix.
 | 
			
		||||
            bytes memory fromCallData = state.mtx.callData;
 | 
			
		||||
            assert(fromCallData.length >= 160);
 | 
			
		||||
            uint256 fromMem;
 | 
			
		||||
            uint256 toMem;
 | 
			
		||||
            assembly {
 | 
			
		||||
                // Prefix the calldata with a struct offset,
 | 
			
		||||
                // which points to just one word over.
 | 
			
		||||
                mstore(add(encodedStructArgs, 32), 32)
 | 
			
		||||
                // Copy everything after the selector.
 | 
			
		||||
                fromMem := add(fromCallData, 36)
 | 
			
		||||
                // Start copying after the struct offset.
 | 
			
		||||
                toMem := add(encodedStructArgs, 64)
 | 
			
		||||
            }
 | 
			
		||||
            LibBytesV06.memCopy(toMem, fromMem, fromCallData.length - 4);
 | 
			
		||||
            // Decode call args for `ITransformERC20Feature.transformERC20()` as a struct.
 | 
			
		||||
            args = abi.decode(encodedStructArgs, (ExternalTransformERC20Args));
 | 
			
		||||
        }
 | 
			
		||||
        // Call `ITransformERC20Feature._transformERC20()` (internal variant).
 | 
			
		||||
        return
 | 
			
		||||
            _callSelf(
 | 
			
		||||
                state.hash,
 | 
			
		||||
                abi.encodeWithSelector(
 | 
			
		||||
                    ITransformERC20Feature._transformERC20.selector,
 | 
			
		||||
                    ITransformERC20Feature.TransformERC20Args({
 | 
			
		||||
                        taker: state.mtx.signer, // taker is mtx signer
 | 
			
		||||
                        inputToken: args.inputToken,
 | 
			
		||||
                        outputToken: args.outputToken,
 | 
			
		||||
                        inputTokenAmount: args.inputTokenAmount,
 | 
			
		||||
                        minOutputTokenAmount: args.minOutputTokenAmount,
 | 
			
		||||
                        transformations: args.transformations,
 | 
			
		||||
                        useSelfBalance: false,
 | 
			
		||||
                        recipient: state.mtx.signer
 | 
			
		||||
                    })
 | 
			
		||||
                )
 | 
			
		||||
            );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Extract arguments from call data by copying everything after the
 | 
			
		||||
    ///      4-byte selector into a new byte array.
 | 
			
		||||
    /// @param callData The call data from which arguments are to be extracted.
 | 
			
		||||
    /// @return args The extracted arguments as a byte array.
 | 
			
		||||
    function _extractArgumentsFromCallData(bytes memory callData) private pure returns (bytes memory args) {
 | 
			
		||||
        args = new bytes(callData.length - 4);
 | 
			
		||||
        uint256 fromMem;
 | 
			
		||||
        uint256 toMem;
 | 
			
		||||
 | 
			
		||||
        assembly {
 | 
			
		||||
            fromMem := add(callData, 36) // skip length and 4-byte selector
 | 
			
		||||
            toMem := add(args, 32) // write after length prefix
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        LibBytesV06.memCopy(toMem, fromMem, args.length);
 | 
			
		||||
 | 
			
		||||
        return args;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Execute a `INativeOrdersFeature.fillLimitOrder()` meta-transaction call
 | 
			
		||||
    ///      by decoding the call args and translating the call to the internal
 | 
			
		||||
    ///      `INativeOrdersFeature._fillLimitOrder()` variant, where we can override
 | 
			
		||||
    ///      the taker address.
 | 
			
		||||
    function _executeFillLimitOrderCall(ExecuteState memory state) private returns (bytes memory returnResult) {
 | 
			
		||||
        LibNativeOrder.LimitOrder memory order;
 | 
			
		||||
        LibSignature.Signature memory signature;
 | 
			
		||||
        uint128 takerTokenFillAmount;
 | 
			
		||||
 | 
			
		||||
        bytes memory args = _extractArgumentsFromCallData(state.mtx.callData);
 | 
			
		||||
        (order, signature, takerTokenFillAmount) = abi.decode(
 | 
			
		||||
            args,
 | 
			
		||||
            (LibNativeOrder.LimitOrder, LibSignature.Signature, uint128)
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        return
 | 
			
		||||
            _callSelf(
 | 
			
		||||
                state.hash,
 | 
			
		||||
                abi.encodeWithSelector(
 | 
			
		||||
                    INativeOrdersFeature._fillLimitOrder.selector,
 | 
			
		||||
                    order,
 | 
			
		||||
                    signature,
 | 
			
		||||
                    takerTokenFillAmount,
 | 
			
		||||
                    state.mtx.signer, // taker is mtx signer
 | 
			
		||||
                    msg.sender
 | 
			
		||||
                )
 | 
			
		||||
            );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Execute a `INativeOrdersFeature.fillRfqOrder()` meta-transaction call
 | 
			
		||||
    ///      by decoding the call args and translating the call to the internal
 | 
			
		||||
    ///      `INativeOrdersFeature._fillRfqOrder()` variant, where we can override
 | 
			
		||||
    ///      the taker address.
 | 
			
		||||
    function _executeFillRfqOrderCall(ExecuteState memory state) private returns (bytes memory returnResult) {
 | 
			
		||||
        LibNativeOrder.RfqOrder memory order;
 | 
			
		||||
        LibSignature.Signature memory signature;
 | 
			
		||||
        uint128 takerTokenFillAmount;
 | 
			
		||||
 | 
			
		||||
        bytes memory args = _extractArgumentsFromCallData(state.mtx.callData);
 | 
			
		||||
        (order, signature, takerTokenFillAmount) = abi.decode(
 | 
			
		||||
            args,
 | 
			
		||||
            (LibNativeOrder.RfqOrder, LibSignature.Signature, uint128)
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        return
 | 
			
		||||
            _callSelf(
 | 
			
		||||
                state.hash,
 | 
			
		||||
                abi.encodeWithSelector(
 | 
			
		||||
                    INativeOrdersFeature._fillRfqOrder.selector,
 | 
			
		||||
                    order,
 | 
			
		||||
                    signature,
 | 
			
		||||
                    takerTokenFillAmount,
 | 
			
		||||
                    state.mtx.signer, // taker is mtx signer
 | 
			
		||||
                    false,
 | 
			
		||||
                    state.mtx.signer
 | 
			
		||||
                )
 | 
			
		||||
            );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Execute a `IMultiplexFeature.multiplexBatchSellTokenForToken()` meta-transaction
 | 
			
		||||
    ///      call by decoding the call args and translating the call to the internal
 | 
			
		||||
    ///      `IMultiplexFeature._multiplexBatchSell()` variant, where we can override the
 | 
			
		||||
    ///      payer address.
 | 
			
		||||
    function _executeMultiplexBatchSellTokenForTokenCall(
 | 
			
		||||
        ExecuteState memory state
 | 
			
		||||
    ) private returns (bytes memory returnResult) {
 | 
			
		||||
        IERC20Token inputToken;
 | 
			
		||||
        IERC20Token outputToken;
 | 
			
		||||
        IMultiplexFeature.BatchSellSubcall[] memory calls;
 | 
			
		||||
        uint256 sellAmount;
 | 
			
		||||
        uint256 minBuyAmount;
 | 
			
		||||
 | 
			
		||||
        bytes memory args = _extractArgumentsFromCallData(state.mtx.callData);
 | 
			
		||||
        (inputToken, outputToken, calls, sellAmount, minBuyAmount) = abi.decode(
 | 
			
		||||
            args,
 | 
			
		||||
            (IERC20Token, IERC20Token, IMultiplexFeature.BatchSellSubcall[], uint256, uint256)
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        return
 | 
			
		||||
            _callSelf(
 | 
			
		||||
                state.hash,
 | 
			
		||||
                abi.encodeWithSelector(
 | 
			
		||||
                    IMultiplexFeature._multiplexBatchSell.selector,
 | 
			
		||||
                    IMultiplexFeature.BatchSellParams({
 | 
			
		||||
                        inputToken: inputToken,
 | 
			
		||||
                        outputToken: outputToken,
 | 
			
		||||
                        sellAmount: sellAmount,
 | 
			
		||||
                        calls: calls,
 | 
			
		||||
                        useSelfBalance: false,
 | 
			
		||||
                        recipient: state.mtx.signer,
 | 
			
		||||
                        payer: state.mtx.signer
 | 
			
		||||
                    }),
 | 
			
		||||
                    minBuyAmount
 | 
			
		||||
                )
 | 
			
		||||
            );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Execute a `IMultiplexFeature.multiplexBatchSellTokenForEth()` meta-transaction
 | 
			
		||||
    ///      call by decoding the call args and translating the call to the internal
 | 
			
		||||
    ///      `IMultiplexFeature._multiplexBatchSellTokenForEth()` variant, where we can override the
 | 
			
		||||
    ///      payer address.
 | 
			
		||||
    function _executeMultiplexBatchSellTokenForEthCall(
 | 
			
		||||
        ExecuteState memory state
 | 
			
		||||
    ) private returns (bytes memory returnResult) {
 | 
			
		||||
        IERC20Token inputToken;
 | 
			
		||||
        IMultiplexFeature.BatchSellSubcall[] memory calls;
 | 
			
		||||
        uint256 sellAmount;
 | 
			
		||||
        uint256 minBuyAmount;
 | 
			
		||||
 | 
			
		||||
        bytes memory args = _extractArgumentsFromCallData(state.mtx.callData);
 | 
			
		||||
        (inputToken, calls, sellAmount, minBuyAmount) = abi.decode(
 | 
			
		||||
            args,
 | 
			
		||||
            (IERC20Token, IMultiplexFeature.BatchSellSubcall[], uint256, uint256)
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        returnResult = _callSelf(
 | 
			
		||||
            state.hash,
 | 
			
		||||
            abi.encodeWithSelector(
 | 
			
		||||
                IMultiplexFeature._multiplexBatchSell.selector,
 | 
			
		||||
                IMultiplexFeature.BatchSellParams({
 | 
			
		||||
                    inputToken: inputToken,
 | 
			
		||||
                    outputToken: IERC20Token(WETH),
 | 
			
		||||
                    sellAmount: sellAmount,
 | 
			
		||||
                    calls: calls,
 | 
			
		||||
                    useSelfBalance: false,
 | 
			
		||||
                    recipient: address(this),
 | 
			
		||||
                    payer: state.mtx.signer
 | 
			
		||||
                }),
 | 
			
		||||
                minBuyAmount
 | 
			
		||||
            )
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        // Unwrap and transfer WETH
 | 
			
		||||
        uint256 boughtAmount = abi.decode(returnResult, (uint256));
 | 
			
		||||
        WETH.withdraw(boughtAmount);
 | 
			
		||||
        _transferEth(state.mtx.signer, boughtAmount);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Execute a `IMultiplexFeature.multiplexMultiHopSellTokenForToken()` meta-transaction
 | 
			
		||||
    ///      call by decoding the call args and translating the call to the internal
 | 
			
		||||
    ///      `IMultiplexFeature._multiplexMultiHopSell()` variant, where we can override the
 | 
			
		||||
    ///      payer address.
 | 
			
		||||
    function _executeMultiplexMultiHopSellTokenForTokenCall(
 | 
			
		||||
        ExecuteState memory state
 | 
			
		||||
    ) private returns (bytes memory returnResult) {
 | 
			
		||||
        address[] memory tokens;
 | 
			
		||||
        IMultiplexFeature.MultiHopSellSubcall[] memory calls;
 | 
			
		||||
        uint256 sellAmount;
 | 
			
		||||
        uint256 minBuyAmount;
 | 
			
		||||
 | 
			
		||||
        bytes memory args = _extractArgumentsFromCallData(state.mtx.callData);
 | 
			
		||||
        (tokens, calls, sellAmount, minBuyAmount) = abi.decode(
 | 
			
		||||
            args,
 | 
			
		||||
            (address[], IMultiplexFeature.MultiHopSellSubcall[], uint256, uint256)
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        return
 | 
			
		||||
            _callSelf(
 | 
			
		||||
                state.hash,
 | 
			
		||||
                abi.encodeWithSelector(
 | 
			
		||||
                    IMultiplexFeature._multiplexMultiHopSell.selector,
 | 
			
		||||
                    IMultiplexFeature.MultiHopSellParams({
 | 
			
		||||
                        tokens: tokens,
 | 
			
		||||
                        sellAmount: sellAmount,
 | 
			
		||||
                        calls: calls,
 | 
			
		||||
                        useSelfBalance: false,
 | 
			
		||||
                        recipient: state.mtx.signer,
 | 
			
		||||
                        payer: state.mtx.signer
 | 
			
		||||
                    }),
 | 
			
		||||
                    minBuyAmount
 | 
			
		||||
                )
 | 
			
		||||
            );
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Execute a `IMultiplexFeature.multiplexMultiHopSellTokenForEth()` meta-transaction
 | 
			
		||||
    ///      call by decoding the call args and translating the call to the internal
 | 
			
		||||
    ///      `IMultiplexFeature._multiplexMultiHopSellTokenForEth()` variant, where we can override the
 | 
			
		||||
    ///      payer address.
 | 
			
		||||
    function _executeMultiplexMultiHopSellTokenForEthCall(
 | 
			
		||||
        ExecuteState memory state
 | 
			
		||||
    ) private returns (bytes memory returnResult) {
 | 
			
		||||
        address[] memory tokens;
 | 
			
		||||
        IMultiplexFeature.MultiHopSellSubcall[] memory calls;
 | 
			
		||||
        uint256 sellAmount;
 | 
			
		||||
        uint256 minBuyAmount;
 | 
			
		||||
 | 
			
		||||
        bytes memory args = _extractArgumentsFromCallData(state.mtx.callData);
 | 
			
		||||
        (tokens, calls, sellAmount, minBuyAmount) = abi.decode(
 | 
			
		||||
            args,
 | 
			
		||||
            (address[], IMultiplexFeature.MultiHopSellSubcall[], uint256, uint256)
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        require(
 | 
			
		||||
            tokens[tokens.length - 1] == address(WETH),
 | 
			
		||||
            "MetaTransactionsFeature::multiplexMultiHopSellTokenForEth/NOT_WETH"
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        returnResult = _callSelf(
 | 
			
		||||
            state.hash,
 | 
			
		||||
            abi.encodeWithSelector(
 | 
			
		||||
                IMultiplexFeature._multiplexMultiHopSell.selector,
 | 
			
		||||
                IMultiplexFeature.MultiHopSellParams({
 | 
			
		||||
                    tokens: tokens,
 | 
			
		||||
                    sellAmount: sellAmount,
 | 
			
		||||
                    calls: calls,
 | 
			
		||||
                    useSelfBalance: false,
 | 
			
		||||
                    recipient: address(this),
 | 
			
		||||
                    payer: state.mtx.signer
 | 
			
		||||
                }),
 | 
			
		||||
                minBuyAmount
 | 
			
		||||
            )
 | 
			
		||||
        );
 | 
			
		||||
 | 
			
		||||
        // Unwrap and transfer WETH
 | 
			
		||||
        uint256 boughtAmount = abi.decode(returnResult, (uint256));
 | 
			
		||||
        WETH.withdraw(boughtAmount);
 | 
			
		||||
        _transferEth(state.mtx.signer, boughtAmount);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Make an arbitrary internal, meta-transaction call.
 | 
			
		||||
    ///      Warning: Do not let unadulterated `callData` into this function.
 | 
			
		||||
    function _callSelf(bytes32 hash, bytes memory callData) private returns (bytes memory returnResult) {
 | 
			
		||||
        bool success;
 | 
			
		||||
        (success, returnResult) = address(this).call(callData);
 | 
			
		||||
        if (!success) {
 | 
			
		||||
            LibMetaTransactionsRichErrors.MetaTransactionCallFailedError(hash, callData, returnResult).rrevert();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -29,7 +29,7 @@ contract NativeOrdersFeature is IFeature, NativeOrdersSettlement {
 | 
			
		||||
 | 
			
		||||
    constructor(
 | 
			
		||||
        address zeroExAddress,
 | 
			
		||||
        IEtherTokenV06 weth,
 | 
			
		||||
        IEtherToken weth,
 | 
			
		||||
        IStaking staking,
 | 
			
		||||
        FeeCollectorController feeCollectorController,
 | 
			
		||||
        uint32 protocolFeeMultiplier
 | 
			
		||||
 
 | 
			
		||||
@@ -15,7 +15,7 @@
 | 
			
		||||
pragma solidity ^0.6.5;
 | 
			
		||||
pragma experimental ABIEncoderV2;
 | 
			
		||||
 | 
			
		||||
import "@0x/contracts-erc20/contracts/src/v06/IEtherTokenV06.sol";
 | 
			
		||||
import "@0x/contracts-erc20/src/IEtherToken.sol";
 | 
			
		||||
import "@0x/contracts-utils/contracts/src/v06/LibSafeMathV06.sol";
 | 
			
		||||
import "@0x/contracts-utils/contracts/src/v06/LibMathV06.sol";
 | 
			
		||||
import "../errors/LibNativeOrdersRichErrors.sol";
 | 
			
		||||
@@ -42,9 +42,9 @@ contract OtcOrdersFeature is IFeature, IOtcOrdersFeature, FixinCommon, FixinEIP7
 | 
			
		||||
    /// @dev ETH pseudo-token address.
 | 
			
		||||
    address private constant ETH_TOKEN_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
 | 
			
		||||
    /// @dev The WETH token contract.
 | 
			
		||||
    IEtherTokenV06 private immutable WETH;
 | 
			
		||||
    IEtherToken private immutable WETH;
 | 
			
		||||
 | 
			
		||||
    constructor(address zeroExAddress, IEtherTokenV06 weth) public FixinEIP712(zeroExAddress) {
 | 
			
		||||
    constructor(address zeroExAddress, IEtherToken weth) public FixinEIP712(zeroExAddress) {
 | 
			
		||||
        WETH = weth;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -15,8 +15,8 @@
 | 
			
		||||
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-erc20/src/IERC20Token.sol";
 | 
			
		||||
import "@0x/contracts-erc20/src/IEtherToken.sol";
 | 
			
		||||
import "../migrations/LibMigrate.sol";
 | 
			
		||||
import "../fixins/FixinCommon.sol";
 | 
			
		||||
import "./interfaces/IFeature.sol";
 | 
			
		||||
@@ -29,7 +29,7 @@ contract PancakeSwapFeature is IFeature, IPancakeSwapFeature, FixinCommon {
 | 
			
		||||
    /// @dev Version of this feature.
 | 
			
		||||
    uint256 public immutable override FEATURE_VERSION = _encodeVersion(1, 0, 2);
 | 
			
		||||
    /// @dev WBNB contract.
 | 
			
		||||
    IEtherTokenV06 private immutable WBNB;
 | 
			
		||||
    IEtherToken private immutable WBNB;
 | 
			
		||||
 | 
			
		||||
    // 0xFF + address of the PancakeSwap factory contract.
 | 
			
		||||
    uint256 private constant FF_PANCAKESWAP_FACTORY =
 | 
			
		||||
@@ -112,7 +112,7 @@ contract PancakeSwapFeature is IFeature, IPancakeSwapFeature, FixinCommon {
 | 
			
		||||
 | 
			
		||||
    /// @dev Construct this contract.
 | 
			
		||||
    /// @param wbnb The WBNB contract.
 | 
			
		||||
    constructor(IEtherTokenV06 wbnb) public {
 | 
			
		||||
    constructor(IEtherToken wbnb) public {
 | 
			
		||||
        WBNB = wbnb;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -131,7 +131,7 @@ contract PancakeSwapFeature is IFeature, IPancakeSwapFeature, FixinCommon {
 | 
			
		||||
    /// @param fork The protocol fork to use.
 | 
			
		||||
    /// @return buyAmount Amount of `tokens[-1]` bought.
 | 
			
		||||
    function sellToPancakeSwap(
 | 
			
		||||
        IERC20TokenV06[] calldata tokens,
 | 
			
		||||
        IERC20Token[] calldata tokens,
 | 
			
		||||
        uint256 sellAmount,
 | 
			
		||||
        uint256 minBuyAmount,
 | 
			
		||||
        ProtocolFork fork
 | 
			
		||||
@@ -139,7 +139,7 @@ contract PancakeSwapFeature is IFeature, IPancakeSwapFeature, FixinCommon {
 | 
			
		||||
        require(tokens.length > 1, "PancakeSwapFeature/InvalidTokensLength");
 | 
			
		||||
        {
 | 
			
		||||
            // Load immutables onto the stack.
 | 
			
		||||
            IEtherTokenV06 wbnb = WBNB;
 | 
			
		||||
            IEtherToken wbnb = WBNB;
 | 
			
		||||
 | 
			
		||||
            // Store some vars in memory to get around stack limits.
 | 
			
		||||
            assembly {
 | 
			
		||||
 
 | 
			
		||||
@@ -15,8 +15,8 @@
 | 
			
		||||
pragma solidity ^0.6.5;
 | 
			
		||||
pragma experimental ABIEncoderV2;
 | 
			
		||||
 | 
			
		||||
import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol";
 | 
			
		||||
import "@0x/contracts-erc20/contracts/src/v06/LibERC20TokenV06.sol";
 | 
			
		||||
import "@0x/contracts-erc20/src/IERC20Token.sol";
 | 
			
		||||
import "@0x/contracts-erc20/src/v06/LibERC20TokenV06.sol";
 | 
			
		||||
import "@0x/contracts-utils/contracts/src/v06/LibBytesV06.sol";
 | 
			
		||||
import "@0x/contracts-utils/contracts/src/v06/errors/LibRichErrorsV06.sol";
 | 
			
		||||
import "@0x/contracts-utils/contracts/src/v06/LibSafeMathV06.sol";
 | 
			
		||||
@@ -124,8 +124,8 @@ contract TransformERC20Feature is IFeature, ITransformERC20Feature, FixinCommon,
 | 
			
		||||
    ///        in sequence.
 | 
			
		||||
    /// @return outputTokenAmount The amount of `outputToken` received by the sender.
 | 
			
		||||
    function transformERC20(
 | 
			
		||||
        IERC20TokenV06 inputToken,
 | 
			
		||||
        IERC20TokenV06 outputToken,
 | 
			
		||||
        IERC20Token inputToken,
 | 
			
		||||
        IERC20Token outputToken,
 | 
			
		||||
        uint256 inputTokenAmount,
 | 
			
		||||
        uint256 minOutputTokenAmount,
 | 
			
		||||
        Transformation[] memory transformations
 | 
			
		||||
@@ -301,7 +301,7 @@ contract TransformERC20Feature is IFeature, ITransformERC20Feature, FixinCommon,
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    function _executeOutputTokenTransfer(
 | 
			
		||||
        IERC20TokenV06 outputToken,
 | 
			
		||||
        IERC20Token outputToken,
 | 
			
		||||
        IFlashWallet wallet,
 | 
			
		||||
        address payable recipient
 | 
			
		||||
    ) private returns (uint256 transferAmount) {
 | 
			
		||||
@@ -311,7 +311,7 @@ contract TransformERC20Feature is IFeature, ITransformERC20Feature, FixinCommon,
 | 
			
		||||
        } else {
 | 
			
		||||
            bytes memory resultData = wallet.executeCall(
 | 
			
		||||
                payable(address(outputToken)),
 | 
			
		||||
                abi.encodeWithSelector(IERC20TokenV06.transfer.selector, recipient, transferAmount),
 | 
			
		||||
                abi.encodeWithSelector(IERC20Token.transfer.selector, recipient, transferAmount),
 | 
			
		||||
                0
 | 
			
		||||
            );
 | 
			
		||||
            if (resultData.length == 0) {
 | 
			
		||||
 
 | 
			
		||||
@@ -15,8 +15,8 @@
 | 
			
		||||
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-erc20/src/IERC20Token.sol";
 | 
			
		||||
import "@0x/contracts-erc20/src/IEtherToken.sol";
 | 
			
		||||
import "../migrations/LibMigrate.sol";
 | 
			
		||||
import "../fixins/FixinCommon.sol";
 | 
			
		||||
import "./interfaces/IFeature.sol";
 | 
			
		||||
@@ -29,7 +29,7 @@ contract UniswapFeature is IFeature, IUniswapFeature, FixinCommon {
 | 
			
		||||
    /// @dev Version of this feature.
 | 
			
		||||
    uint256 public immutable override FEATURE_VERSION = _encodeVersion(1, 1, 2);
 | 
			
		||||
    /// @dev WETH contract.
 | 
			
		||||
    IEtherTokenV06 private immutable WETH;
 | 
			
		||||
    IEtherToken private immutable WETH;
 | 
			
		||||
 | 
			
		||||
    // 0xFF + address of the UniswapV2Factory contract.
 | 
			
		||||
    uint256 private constant FF_UNISWAP_FACTORY = 0xFF5C69bEe701ef814a2B6a3EDD4B1652CB9cc5aA6f0000000000000000000000;
 | 
			
		||||
@@ -75,7 +75,7 @@ contract UniswapFeature is IFeature, IUniswapFeature, FixinCommon {
 | 
			
		||||
 | 
			
		||||
    /// @dev Construct this contract.
 | 
			
		||||
    /// @param weth The WETH contract.
 | 
			
		||||
    constructor(IEtherTokenV06 weth) public {
 | 
			
		||||
    constructor(IEtherToken weth) public {
 | 
			
		||||
        WETH = weth;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
@@ -94,7 +94,7 @@ contract UniswapFeature is IFeature, IUniswapFeature, FixinCommon {
 | 
			
		||||
    /// @param isSushi Use sushiswap if true.
 | 
			
		||||
    /// @return buyAmount Amount of `tokens[-1]` bought.
 | 
			
		||||
    function sellToUniswap(
 | 
			
		||||
        IERC20TokenV06[] calldata tokens,
 | 
			
		||||
        IERC20Token[] calldata tokens,
 | 
			
		||||
        uint256 sellAmount,
 | 
			
		||||
        uint256 minBuyAmount,
 | 
			
		||||
        bool isSushi
 | 
			
		||||
@@ -102,7 +102,7 @@ contract UniswapFeature is IFeature, IUniswapFeature, FixinCommon {
 | 
			
		||||
        require(tokens.length > 1, "UniswapFeature/InvalidTokensLength");
 | 
			
		||||
        {
 | 
			
		||||
            // Load immutables onto the stack.
 | 
			
		||||
            IEtherTokenV06 weth = WETH;
 | 
			
		||||
            IEtherToken weth = WETH;
 | 
			
		||||
 | 
			
		||||
            // Store some vars in memory to get around stack limits.
 | 
			
		||||
            assembly {
 | 
			
		||||
 
 | 
			
		||||
@@ -15,8 +15,8 @@
 | 
			
		||||
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-erc20/src/IERC20Token.sol";
 | 
			
		||||
import "@0x/contracts-erc20/src/IEtherToken.sol";
 | 
			
		||||
import "../vendor/IUniswapV3Pool.sol";
 | 
			
		||||
import "../migrations/LibMigrate.sol";
 | 
			
		||||
import "../fixins/FixinCommon.sol";
 | 
			
		||||
@@ -31,7 +31,7 @@ contract UniswapV3Feature is IFeature, IUniswapV3Feature, FixinCommon, FixinToke
 | 
			
		||||
    /// @dev Version of this feature.
 | 
			
		||||
    uint256 public immutable override FEATURE_VERSION = _encodeVersion(1, 1, 0);
 | 
			
		||||
    /// @dev WETH contract.
 | 
			
		||||
    IEtherTokenV06 private immutable WETH;
 | 
			
		||||
    IEtherToken private immutable WETH;
 | 
			
		||||
    /// @dev UniswapV3 Factory contract address prepended with '0xff' and left-aligned.
 | 
			
		||||
    bytes32 private immutable UNI_FF_FACTORY_ADDRESS;
 | 
			
		||||
    /// @dev UniswapV3 pool init code hash.
 | 
			
		||||
@@ -57,7 +57,7 @@ contract UniswapV3Feature is IFeature, IUniswapV3Feature, FixinCommon, FixinToke
 | 
			
		||||
    /// @param weth The WETH contract.
 | 
			
		||||
    /// @param uniFactory The UniswapV3 factory contract.
 | 
			
		||||
    /// @param poolInitCodeHash The UniswapV3 pool init code hash.
 | 
			
		||||
    constructor(IEtherTokenV06 weth, address uniFactory, bytes32 poolInitCodeHash) public {
 | 
			
		||||
    constructor(IEtherToken weth, address uniFactory, bytes32 poolInitCodeHash) public {
 | 
			
		||||
        WETH = weth;
 | 
			
		||||
        UNI_FF_FACTORY_ADDRESS = bytes32((uint256(0xff) << 248) | (uint256(uniFactory) << 88));
 | 
			
		||||
        UNI_POOL_INIT_CODE_HASH = poolInitCodeHash;
 | 
			
		||||
@@ -70,6 +70,7 @@ contract UniswapV3Feature is IFeature, IUniswapV3Feature, FixinCommon, FixinToke
 | 
			
		||||
        _registerFeatureFunction(this.sellEthForTokenToUniswapV3.selector);
 | 
			
		||||
        _registerFeatureFunction(this.sellTokenForEthToUniswapV3.selector);
 | 
			
		||||
        _registerFeatureFunction(this.sellTokenForTokenToUniswapV3.selector);
 | 
			
		||||
        _registerFeatureFunction(this._sellTokenForTokenToUniswapV3.selector);
 | 
			
		||||
        _registerFeatureFunction(this._sellHeldTokenForTokenToUniswapV3.selector);
 | 
			
		||||
        _registerFeatureFunction(this.uniswapV3SwapCallback.selector);
 | 
			
		||||
        return LibMigrate.MIGRATE_SUCCESS;
 | 
			
		||||
@@ -139,6 +140,23 @@ contract UniswapV3Feature is IFeature, IUniswapV3Feature, FixinCommon, FixinToke
 | 
			
		||||
        buyAmount = _swap(encodedPath, sellAmount, minBuyAmount, msg.sender, _normalizeRecipient(recipient));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Sell a token for another token directly against uniswap v3. Internal variant.
 | 
			
		||||
    /// @param encodedPath Uniswap-encoded path.
 | 
			
		||||
    /// @param sellAmount amount of the first token in the path to sell.
 | 
			
		||||
    /// @param minBuyAmount Minimum amount of the last token in the path to buy.
 | 
			
		||||
    /// @param recipient The recipient of the bought tokens. Can be zero for payer.
 | 
			
		||||
    /// @param payer The address to pull the sold tokens from.
 | 
			
		||||
    /// @return buyAmount Amount of the last token in the path bought.
 | 
			
		||||
    function _sellTokenForTokenToUniswapV3(
 | 
			
		||||
        bytes memory encodedPath,
 | 
			
		||||
        uint256 sellAmount,
 | 
			
		||||
        uint256 minBuyAmount,
 | 
			
		||||
        address recipient,
 | 
			
		||||
        address payer
 | 
			
		||||
    ) public override onlySelf returns (uint256 buyAmount) {
 | 
			
		||||
        buyAmount = _swap(encodedPath, sellAmount, minBuyAmount, payer, _normalizeRecipient(recipient, payer));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /// @dev Sell a token for another token directly against uniswap v3.
 | 
			
		||||
    ///      Private variant, uses tokens held by `address(this)`.
 | 
			
		||||
    /// @param encodedPath Uniswap-encoded path.
 | 
			
		||||
@@ -163,8 +181,8 @@ contract UniswapV3Feature is IFeature, IUniswapV3Feature, FixinCommon, FixinToke
 | 
			
		||||
    /// @param data Arbitrary data forwarded from swap() caller. An ABI-encoded
 | 
			
		||||
    ///        struct of: inputToken, outputToken, fee, payer
 | 
			
		||||
    function uniswapV3SwapCallback(int256 amount0Delta, int256 amount1Delta, bytes calldata data) external override {
 | 
			
		||||
        IERC20TokenV06 token0;
 | 
			
		||||
        IERC20TokenV06 token1;
 | 
			
		||||
        IERC20Token token0;
 | 
			
		||||
        IERC20Token token1;
 | 
			
		||||
        address payer;
 | 
			
		||||
        {
 | 
			
		||||
            uint24 fee;
 | 
			
		||||
@@ -212,7 +230,7 @@ contract UniswapV3Feature is IFeature, IUniswapV3Feature, FixinCommon, FixinToke
 | 
			
		||||
                bool zeroForOne;
 | 
			
		||||
                IUniswapV3Pool pool;
 | 
			
		||||
                {
 | 
			
		||||
                    (IERC20TokenV06 inputToken, uint24 fee, IERC20TokenV06 outputToken) = _decodeFirstPoolInfoFromPath(
 | 
			
		||||
                    (IERC20Token inputToken, uint24 fee, IERC20Token outputToken) = _decodeFirstPoolInfoFromPath(
 | 
			
		||||
                        encodedPath
 | 
			
		||||
                    );
 | 
			
		||||
                    pool = _toPool(inputToken, fee, outputToken);
 | 
			
		||||
@@ -248,7 +266,7 @@ contract UniswapV3Feature is IFeature, IUniswapV3Feature, FixinCommon, FixinToke
 | 
			
		||||
 | 
			
		||||
    // Pay tokens from `payer` to `to`, using `transferFrom()` if
 | 
			
		||||
    // `payer` != this contract.
 | 
			
		||||
    function _pay(IERC20TokenV06 token, address payer, address to, uint256 amount) private {
 | 
			
		||||
    function _pay(IERC20Token token, address payer, address to, uint256 amount) private {
 | 
			
		||||
        if (payer != address(this)) {
 | 
			
		||||
            _transferERC20TokensFrom(token, payer, to, amount);
 | 
			
		||||
        } else {
 | 
			
		||||
@@ -259,8 +277,8 @@ contract UniswapV3Feature is IFeature, IUniswapV3Feature, FixinCommon, FixinToke
 | 
			
		||||
    // Update `swapCallbackData` in place with new values.
 | 
			
		||||
    function _updateSwapCallbackData(
 | 
			
		||||
        bytes memory swapCallbackData,
 | 
			
		||||
        IERC20TokenV06 inputToken,
 | 
			
		||||
        IERC20TokenV06 outputToken,
 | 
			
		||||
        IERC20Token inputToken,
 | 
			
		||||
        IERC20Token outputToken,
 | 
			
		||||
        uint24 fee,
 | 
			
		||||
        address payer
 | 
			
		||||
    ) private pure {
 | 
			
		||||
@@ -275,9 +293,9 @@ contract UniswapV3Feature is IFeature, IUniswapV3Feature, FixinCommon, FixinToke
 | 
			
		||||
 | 
			
		||||
    // Compute the pool address given two tokens and a fee.
 | 
			
		||||
    function _toPool(
 | 
			
		||||
        IERC20TokenV06 inputToken,
 | 
			
		||||
        IERC20Token inputToken,
 | 
			
		||||
        uint24 fee,
 | 
			
		||||
        IERC20TokenV06 outputToken
 | 
			
		||||
        IERC20Token outputToken
 | 
			
		||||
    ) private view returns (IUniswapV3Pool pool) {
 | 
			
		||||
        // address(keccak256(abi.encodePacked(
 | 
			
		||||
        //     hex"ff",
 | 
			
		||||
@@ -287,7 +305,7 @@ contract UniswapV3Feature is IFeature, IUniswapV3Feature, FixinCommon, FixinToke
 | 
			
		||||
        // )))
 | 
			
		||||
        bytes32 ffFactoryAddress = UNI_FF_FACTORY_ADDRESS;
 | 
			
		||||
        bytes32 poolInitCodeHash = UNI_POOL_INIT_CODE_HASH;
 | 
			
		||||
        (IERC20TokenV06 token0, IERC20TokenV06 token1) = inputToken < outputToken
 | 
			
		||||
        (IERC20Token token0, IERC20Token token1) = inputToken < outputToken
 | 
			
		||||
            ? (inputToken, outputToken)
 | 
			
		||||
            : (outputToken, inputToken);
 | 
			
		||||
        assembly {
 | 
			
		||||
@@ -314,7 +332,7 @@ contract UniswapV3Feature is IFeature, IUniswapV3Feature, FixinCommon, FixinToke
 | 
			
		||||
    // Return the first input token, output token, and fee of an encoded uniswap path.
 | 
			
		||||
    function _decodeFirstPoolInfoFromPath(
 | 
			
		||||
        bytes memory encodedPath
 | 
			
		||||
    ) private pure returns (IERC20TokenV06 inputToken, uint24 fee, IERC20TokenV06 outputToken) {
 | 
			
		||||
    ) private pure returns (IERC20Token inputToken, uint24 fee, IERC20Token outputToken) {
 | 
			
		||||
        require(encodedPath.length >= SINGLE_HOP_PATH_SIZE, "UniswapV3Feature/BAD_PATH_ENCODING");
 | 
			
		||||
        assembly {
 | 
			
		||||
            let p := add(encodedPath, 32)
 | 
			
		||||
@@ -337,8 +355,16 @@ contract UniswapV3Feature is IFeature, IUniswapV3Feature, FixinCommon, FixinToke
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Convert null address values to alternative address.
 | 
			
		||||
    function _normalizeRecipient(
 | 
			
		||||
        address recipient,
 | 
			
		||||
        address alternative
 | 
			
		||||
    ) private pure returns (address payable normalizedRecipient) {
 | 
			
		||||
        return recipient == address(0) ? payable(alternative) : payable(recipient);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Convert null address values to msg.sender.
 | 
			
		||||
    function _normalizeRecipient(address recipient) private view returns (address payable normalizedRecipient) {
 | 
			
		||||
        return recipient == address(0) ? msg.sender : payable(recipient);
 | 
			
		||||
        return _normalizeRecipient(recipient, msg.sender);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user