Migrate erc20-contracts to foundry (#664)

* Strip erc20 package of legacy nonsense and add foundry basics

* Make foundry build

* Remove obsoleted test/UntransferrableDummyERC20Token.sol contract

* Remove obsoleted ERC20 lib variant contracts

* Remove obsoleted DummyMultipleReturnERC20Token and DummyNoReturnERC20Token contracts

* Move test contract to dedicated folder
and remove obsoleted TypeScript contract wrappers

* Remove src/interfaces/IEtherToken.sol only used in
v3 staking which is being obsoleted [skip ci]

* Add foundry test for token

* Migrate ZRX token tests to foundry

* Fix paths to erc20 contracts

* Remove obsoleted references

* Pin erc20-contracts package on treasury

* Ignore foundry imports in link checker

* Run only forge tests for erc20 contracts

* Remove DummyERC20Token and its dependencies

* Merge IERC20TokenV06 and IERC20TokenV08
into range pragma to cover solidity 0.6.5 to 0.8.x

* Merge IEtherTokenV06 and IEtherTokenV08
into range pragma to cover solidity 0.6.5 to 0.8.x

* Migrate weth9 tests to foundry

* Upload code coverage for erc20 package

* Update changelog

* Fix review comments

Co-authored-by: duncancmt <1207590+duncancmt@users.noreply.github.com>

---------

Co-authored-by: duncancmt <1207590+duncancmt@users.noreply.github.com>
This commit is contained in:
Elena 2023-02-19 20:04:24 +02:00 committed by GitHub
parent f2f835591e
commit 9f30823d70
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
172 changed files with 945 additions and 2876 deletions

View File

@ -61,7 +61,6 @@ jobs:
-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 \
@ -84,18 +83,41 @@ jobs:
with:
version: nightly
- name: Run Forge build
- 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
- name: Run Forge tests for zero-ex
working-directory: contracts/zero-ex
run: |
forge test -vvv --gas-report
- name: Run Forge coverage
- name: Run Forge coverage for zero-ex
working-directory: contracts/zero-ex
run: |
forge coverage --report summary --report lcov

3
.gitmodules vendored
View File

@ -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

View File

@ -1,4 +1,4 @@
contracts/erc20/contracts/src/ZRXToken.sol
contracts/erc20/src/ZRXToken.sol
node_modules/
lib
deps

View File

@ -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": {}
}

View File

@ -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

View File

@ -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"
]
}
}
}
}

View File

@ -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];
}
}

View File

@ -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);
}
}

View File

@ -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);
}
}

View File

@ -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;
}
}

View File

@ -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);
}

View File

@ -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;
}

View File

@ -1,117 +0,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;
import "@0x/contracts-utils/contracts/src/v06/LibSafeMathV06.sol";
import "./IERC20TokenV06.sol";
contract MintableERC20TokenV06 is IERC20TokenV06 {
using LibSafeMathV06 for uint256;
uint8 public override decimals = 18;
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 override returns (bool) {
require(balances[msg.sender] >= _value, "ERC20_INSUFFICIENT_BALANCE");
require(balances[_to].safeAdd(_value) >= balances[_to], "UINT256_OVERFLOW");
balances[msg.sender] = balances[msg.sender].safeSub(_value);
balances[_to] = balances[_to].safeAdd(_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 override returns (bool) {
require(balances[_from] >= _value, "ERC20_INSUFFICIENT_BALANCE");
require(allowed[_from][msg.sender] >= _value, "ERC20_INSUFFICIENT_ALLOWANCE");
require(balances[_to].safeAdd(_value) >= balances[_to], "UINT256_OVERFLOW");
balances[_to] = balances[_to].safeAdd(_value);
balances[_from] = balances[_from].safeSub(_value);
allowed[_from][msg.sender] = allowed[_from][msg.sender].safeSub(_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 override 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 override 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 override 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 override returns (uint256) {
return allowed[_owner][_spender];
}
/// @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);
}
}

View File

@ -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);
}

View File

@ -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;
}

View File

@ -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);
}
}

View File

@ -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)
}
}
}

View File

@ -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)
}
}
}

View File

@ -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));
}
}

View File

@ -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))
}
}
}

View File

@ -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");
}
}

View 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

@ -0,0 +1 @@
Subproject commit a2edd39db95df7e9dd3f9ef9edc8c55fefddb6df

View File

@ -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"
},

View File

@ -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);

View File

@ -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;

View File

@ -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,
};

View File

@ -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';

View File

@ -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)
);

View File

@ -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))
);

View File

@ -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';

View 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);
}
}

View 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);
}
}

View File

@ -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,
};

View File

@ -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);
});
});
});

View File

@ -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);
});
});
});

View File

@ -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));
});
});
});

View File

@ -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';

View File

@ -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);
});
});
});

View File

@ -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"]
}

View File

@ -1,7 +0,0 @@
{
"extends": "../../typedoc-tsconfig",
"compilerOptions": {
"outDir": "lib"
},
"include": ["./src/**/*", "./test/**/*"]
}

View File

@ -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%

View File

@ -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 +1 @@
Subproject commit 058d2004ac10cc8f194625fb107fb7a87c4e702d
Subproject commit f8e700ed5d605f53f2194dc8df05a0bc3a7c1e43

View File

@ -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}();
}

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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 {

View File

@ -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);

View File

@ -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;

View File

@ -29,7 +29,7 @@ contract NativeOrdersFeature is IFeature, NativeOrdersSettlement {
constructor(
address zeroExAddress,
IEtherTokenV06 weth,
IEtherToken weth,
IStaking staking,
FeeCollectorController feeCollectorController,
uint32 protocolFeeMultiplier

View File

@ -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;
}

View File

@ -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 {

View File

@ -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) {

View File

@ -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 {

View File

@ -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;
@ -163,8 +163,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 +212,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 +248,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 +259,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 +275,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 +287,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 +314,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)

View File

@ -15,7 +15,7 @@
pragma solidity ^0.6;
pragma experimental ABIEncoderV2;
import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol";
import "@0x/contracts-erc20/src/IERC20Token.sol";
import "../libs/LibNFTOrder.sol";
import "../libs/LibSignature.sol";
import "../../vendor/IERC1155Token.sol";
@ -39,7 +39,7 @@ interface IERC1155OrdersFeature {
address maker,
address taker,
uint256 nonce,
IERC20TokenV06 erc20Token,
IERC20Token erc20Token,
uint256 erc20FillAmount,
IERC1155Token erc1155Token,
uint256 erc1155TokenId,
@ -60,7 +60,7 @@ interface IERC1155OrdersFeature {
address taker,
uint256 expiry,
uint256 nonce,
IERC20TokenV06 erc20Token,
IERC20Token erc20Token,
uint256 erc20TokenAmount,
LibNFTOrder.Fee[] fees,
IERC1155Token erc1155Token,

View File

@ -15,7 +15,7 @@
pragma solidity ^0.6;
pragma experimental ABIEncoderV2;
import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol";
import "@0x/contracts-erc20/src/IERC20Token.sol";
import "../libs/LibNFTOrder.sol";
import "../libs/LibSignature.sol";
import "../../vendor/IERC721Token.sol";
@ -40,7 +40,7 @@ interface IERC721OrdersFeature {
address maker,
address taker,
uint256 nonce,
IERC20TokenV06 erc20Token,
IERC20Token erc20Token,
uint256 erc20TokenAmount,
IERC721Token erc721Token,
uint256 erc721TokenId,
@ -60,7 +60,7 @@ interface IERC721OrdersFeature {
address taker,
uint256 expiry,
uint256 nonce,
IERC20TokenV06 erc20Token,
IERC20Token erc20Token,
uint256 erc20TokenAmount,
LibNFTOrder.Fee[] fees,
IERC721Token erc721Token,

View File

@ -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";
/// @dev Exchange Proxy Recovery Functions
interface IFundRecoveryFeature {
@ -24,5 +24,5 @@ interface IFundRecoveryFeature {
/// @param erc20 ERC20 Token Address.
/// @param amountOut Amount of tokens to withdraw.
/// @param recipientWallet Recipient wallet address.
function transferTrappedTokensTo(IERC20TokenV06 erc20, uint256 amountOut, address payable recipientWallet) external;
function transferTrappedTokensTo(IERC20Token erc20, uint256 amountOut, address payable recipientWallet) external;
}

View File

@ -15,15 +15,15 @@
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";
/// @dev Feature to swap directly with an on-chain liquidity provider.
interface ILiquidityProviderFeature {
/// @dev Event for data pipeline.
event LiquidityProviderSwap(
IERC20TokenV06 inputToken,
IERC20TokenV06 outputToken,
IERC20Token inputToken,
IERC20Token outputToken,
uint256 inputTokenAmount,
uint256 outputTokenAmount,
ILiquidityProvider provider,
@ -44,8 +44,8 @@ interface ILiquidityProviderFeature {
/// @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,

View File

@ -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 "../libs/LibSignature.sol";
/// @dev Meta-transactions feature.
@ -39,7 +39,7 @@ interface IMetaTransactionsFeature {
// Amount of ETH to attach to the call.
uint256 value;
// ERC20 fee `signer` pays `sender`.
IERC20TokenV06 feeToken;
IERC20Token feeToken;
// ERC20 fee amount.
uint256 feeAmount;
}

View File

@ -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";
interface IMultiplexFeature {
// Identifies the type of subcall.
@ -34,9 +34,9 @@ interface IMultiplexFeature {
// Parameters for a batch sell.
struct BatchSellParams {
// The token being sold.
IERC20TokenV06 inputToken;
IERC20Token inputToken;
// The token being bought.
IERC20TokenV06 outputToken;
IERC20Token outputToken;
// The amount of `inputToken` to sell.
uint256 sellAmount;
// The nested calls to perform.
@ -116,7 +116,7 @@ interface IMultiplexFeature {
/// must be bought for this function to not revert.
/// @return boughtAmount The amount of `outputToken` bought.
function multiplexBatchSellEthForToken(
IERC20TokenV06 outputToken,
IERC20Token outputToken,
BatchSellSubcall[] calldata calls,
uint256 minBuyAmount
) external payable returns (uint256 boughtAmount);
@ -130,7 +130,7 @@ interface IMultiplexFeature {
/// must be bought for this function to not revert.
/// @return boughtAmount The amount of ETH bought.
function multiplexBatchSellTokenForEth(
IERC20TokenV06 inputToken,
IERC20Token inputToken,
BatchSellSubcall[] calldata calls,
uint256 sellAmount,
uint256 minBuyAmount
@ -146,8 +146,8 @@ interface IMultiplexFeature {
/// that must be bought for this function to not revert.
/// @return boughtAmount The amount of `outputToken` bought.
function multiplexBatchSellTokenForToken(
IERC20TokenV06 inputToken,
IERC20TokenV06 outputToken,
IERC20Token inputToken,
IERC20Token outputToken,
BatchSellSubcall[] calldata calls,
uint256 sellAmount,
uint256 minBuyAmount

View File

@ -15,7 +15,6 @@
pragma solidity ^0.6.5;
pragma experimental ABIEncoderV2;
import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol";
import "../libs/LibSignature.sol";
import "../libs/LibNativeOrder.sol";

View File

@ -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 "../libs/LibSignature.sol";
import "../libs/LibNativeOrder.sol";
import "./INativeOrdersEvents.sol";
@ -150,7 +150,7 @@ interface INativeOrdersFeature is INativeOrdersEvents {
/// @param makerToken The maker token.
/// @param takerToken The taker token.
/// @param minValidSalt The new minimum valid salt.
function cancelPairLimitOrders(IERC20TokenV06 makerToken, IERC20TokenV06 takerToken, uint256 minValidSalt) external;
function cancelPairLimitOrders(IERC20Token makerToken, IERC20Token takerToken, uint256 minValidSalt) external;
/// @dev Cancel all limit orders for a given maker and pair with a salt less
/// than the value provided. The caller must be a signer registered to the maker.
@ -162,8 +162,8 @@ interface INativeOrdersFeature is INativeOrdersEvents {
/// @param minValidSalt The new minimum valid salt.
function cancelPairLimitOrdersWithSigner(
address maker,
IERC20TokenV06 makerToken,
IERC20TokenV06 takerToken,
IERC20Token makerToken,
IERC20Token takerToken,
uint256 minValidSalt
) external;
@ -175,8 +175,8 @@ interface INativeOrdersFeature is INativeOrdersEvents {
/// @param takerTokens The taker tokens.
/// @param minValidSalts The new minimum valid salts.
function batchCancelPairLimitOrders(
IERC20TokenV06[] calldata makerTokens,
IERC20TokenV06[] calldata takerTokens,
IERC20Token[] calldata makerTokens,
IERC20Token[] calldata takerTokens,
uint256[] calldata minValidSalts
) external;
@ -190,8 +190,8 @@ interface INativeOrdersFeature is INativeOrdersEvents {
/// @param minValidSalts The new minimum valid salts.
function batchCancelPairLimitOrdersWithSigner(
address maker,
IERC20TokenV06[] memory makerTokens,
IERC20TokenV06[] memory takerTokens,
IERC20Token[] memory makerTokens,
IERC20Token[] memory takerTokens,
uint256[] memory minValidSalts
) external;
@ -202,7 +202,7 @@ interface INativeOrdersFeature is INativeOrdersEvents {
/// @param makerToken The maker token.
/// @param takerToken The taker token.
/// @param minValidSalt The new minimum valid salt.
function cancelPairRfqOrders(IERC20TokenV06 makerToken, IERC20TokenV06 takerToken, uint256 minValidSalt) external;
function cancelPairRfqOrders(IERC20Token makerToken, IERC20Token takerToken, uint256 minValidSalt) external;
/// @dev Cancel all RFQ orders for a given maker and pair with a salt less
/// than the value provided. The caller must be a signer registered to the maker.
@ -214,8 +214,8 @@ interface INativeOrdersFeature is INativeOrdersEvents {
/// @param minValidSalt The new minimum valid salt.
function cancelPairRfqOrdersWithSigner(
address maker,
IERC20TokenV06 makerToken,
IERC20TokenV06 takerToken,
IERC20Token makerToken,
IERC20Token takerToken,
uint256 minValidSalt
) external;
@ -227,8 +227,8 @@ interface INativeOrdersFeature is INativeOrdersEvents {
/// @param takerTokens The taker tokens.
/// @param minValidSalts The new minimum valid salts.
function batchCancelPairRfqOrders(
IERC20TokenV06[] calldata makerTokens,
IERC20TokenV06[] calldata takerTokens,
IERC20Token[] calldata makerTokens,
IERC20Token[] calldata takerTokens,
uint256[] calldata minValidSalts
) external;
@ -242,8 +242,8 @@ interface INativeOrdersFeature is INativeOrdersEvents {
/// @param minValidSalts The new minimum valid salts.
function batchCancelPairRfqOrdersWithSigner(
address maker,
IERC20TokenV06[] memory makerTokens,
IERC20TokenV06[] memory takerTokens,
IERC20Token[] memory makerTokens,
IERC20Token[] memory takerTokens,
uint256[] memory minValidSalts
) external;

View File

@ -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";
/// @dev VIP PancakeSwap (and forks) fill functions.
interface IPancakeSwapFeature {
@ -37,7 +37,7 @@ interface IPancakeSwapFeature {
/// @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

View File

@ -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";
/// @dev Feature that allows spending token allowances.
interface ITokenSpenderFeature {
@ -25,14 +25,14 @@ interface ITokenSpenderFeature {
/// @param owner The owner of the tokens.
/// @param to The recipient of the tokens.
/// @param amount The amount of `token` to transfer.
function _spendERC20Tokens(IERC20TokenV06 token, address owner, address to, uint256 amount) external;
function _spendERC20Tokens(IERC20Token token, address owner, address to, uint256 amount) external;
/// @dev Gets the maximum amount of an ERC20 token `token` that can be
/// pulled from `owner`.
/// @param token The token to spend.
/// @param owner The owner of the tokens.
/// @return amount The amount of tokens that can be pulled.
function getSpendableERC20BalanceOf(IERC20TokenV06 token, address owner) external view returns (uint256 amount);
function getSpendableERC20BalanceOf(IERC20Token token, address owner) external view returns (uint256 amount);
/// @dev Get the address of the allowance target.
/// @return target The target of token allowances.

View File

@ -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 "../../transformers/IERC20Transformer.sol";
import "../../external/IFlashWallet.sol";
@ -37,10 +37,10 @@ interface ITransformERC20Feature {
address payable taker;
// The token being provided by the taker.
// If `0xeee...`, ETH is implied and should be provided with the call.`
IERC20TokenV06 inputToken;
IERC20Token inputToken;
// The token to be acquired by the taker.
// `0xeee...` implies ETH.
IERC20TokenV06 outputToken;
IERC20Token outputToken;
// The amount of `inputToken` to take from the taker.
// If set to `uint256(-1)`, the entire spendable balance of the taker
// will be solt.
@ -112,8 +112,8 @@ interface ITransformERC20Feature {
/// 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[] calldata transformations

View File

@ -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";
/// @dev VIP uniswap fill functions.
interface IUniswapFeature {
@ -26,7 +26,7 @@ interface IUniswapFeature {
/// @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

View File

@ -15,8 +15,6 @@
pragma solidity ^0.6.5;
pragma experimental ABIEncoderV2;
import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol";
/// @dev VIP uniswap v3 fill functions.
interface IUniswapV3Feature {
/// @dev Sell attached ETH directly against uniswap v3.

View File

@ -15,7 +15,7 @@
pragma solidity ^0.6;
pragma experimental ABIEncoderV2;
import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol";
import "@0x/contracts-erc20/src/IERC20Token.sol";
import "../../vendor/IERC1155Token.sol";
import "../../vendor/IERC721Token.sol";
import "../../vendor/IPropertyValidator.sol";
@ -53,7 +53,7 @@ library LibNFTOrder {
address taker;
uint256 expiry;
uint256 nonce;
IERC20TokenV06 erc20Token;
IERC20Token erc20Token;
uint256 erc20TokenAmount;
Fee[] fees;
address nft;
@ -68,7 +68,7 @@ library LibNFTOrder {
address taker;
uint256 expiry;
uint256 nonce;
IERC20TokenV06 erc20Token;
IERC20Token erc20Token;
uint256 erc20TokenAmount;
Fee[] fees;
IERC721Token erc721Token;
@ -84,7 +84,7 @@ library LibNFTOrder {
address taker;
uint256 expiry;
uint256 nonce;
IERC20TokenV06 erc20Token;
IERC20Token erc20Token;
uint256 erc20TokenAmount;
Fee[] fees;
IERC1155Token erc1155Token;

View File

@ -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 "@0x/contracts-utils/contracts/src/v06/errors/LibRichErrorsV06.sol";
import "@0x/contracts-utils/contracts/src/v06/LibSafeMathV06.sol";
import "../../errors/LibNativeOrdersRichErrors.sol";
@ -35,8 +35,8 @@ library LibNativeOrder {
/// @dev A standard OTC or OO limit order.
struct LimitOrder {
IERC20TokenV06 makerToken;
IERC20TokenV06 takerToken;
IERC20Token makerToken;
IERC20Token takerToken;
uint128 makerAmount;
uint128 takerAmount;
uint128 takerTokenFeeAmount;
@ -51,8 +51,8 @@ library LibNativeOrder {
/// @dev An RFQ limit order.
struct RfqOrder {
IERC20TokenV06 makerToken;
IERC20TokenV06 takerToken;
IERC20Token makerToken;
IERC20Token takerToken;
uint128 makerAmount;
uint128 takerAmount;
address maker;
@ -65,8 +65,8 @@ library LibNativeOrder {
/// @dev An OTC limit order.
struct OtcOrder {
IERC20TokenV06 makerToken;
IERC20TokenV06 takerToken;
IERC20Token makerToken;
IERC20Token takerToken;
uint128 makerAmount;
uint128 takerAmount;
address maker;

View File

@ -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 "@0x/contracts-utils/contracts/src/v06/LibSafeMathV06.sol";
import "../../external/ILiquidityProviderSandbox.sol";
import "../../fixins/FixinCommon.sol";
@ -54,11 +54,11 @@ contract MultiplexFeature is
uint256 private constant LOWER_255_BITS = HIGH_BIT - 1;
/// @dev The WETH token contract.
IEtherTokenV06 private immutable WETH;
IEtherToken private immutable WETH;
constructor(
address zeroExAddress,
IEtherTokenV06 weth,
IEtherToken weth,
ILiquidityProviderSandbox sandbox,
address uniswapFactory,
address sushiswapFactory,
@ -94,7 +94,7 @@ contract MultiplexFeature is
/// must be bought for this function to not revert.
/// @return boughtAmount The amount of `outputToken` bought.
function multiplexBatchSellEthForToken(
IERC20TokenV06 outputToken,
IERC20Token outputToken,
BatchSellSubcall[] memory calls,
uint256 minBuyAmount
) public payable override returns (uint256 boughtAmount) {
@ -125,7 +125,7 @@ contract MultiplexFeature is
/// must be bought for this function to not revert.
/// @return boughtAmount The amount of ETH bought.
function multiplexBatchSellTokenForEth(
IERC20TokenV06 inputToken,
IERC20Token inputToken,
BatchSellSubcall[] memory calls,
uint256 sellAmount,
uint256 minBuyAmount
@ -160,8 +160,8 @@ contract MultiplexFeature is
/// that must be bought for this function to not revert.
/// @return boughtAmount The amount of `outputToken` bought.
function multiplexBatchSellTokenForToken(
IERC20TokenV06 inputToken,
IERC20TokenV06 outputToken,
IERC20Token inputToken,
IERC20Token outputToken,
BatchSellSubcall[] memory calls,
uint256 sellAmount,
uint256 minBuyAmount
@ -327,7 +327,7 @@ contract MultiplexFeature is
"MultiplexFeature::_multiplexMultiHopSell/MISMATCHED_ARRAY_LENGTHS"
);
// The output token is the last token in the path.
IERC20TokenV06 outputToken = IERC20TokenV06(params.tokens[params.tokens.length - 1]);
IERC20Token outputToken = IERC20Token(params.tokens[params.tokens.length - 1]);
// Cache the recipient's balance of the output token.
uint256 balanceBefore = outputToken.balanceOf(params.recipient);
// Execute the multi-hop sell.
@ -394,12 +394,12 @@ contract MultiplexFeature is
// If the input tokens are currently held by `msg.sender` but
// the first hop expects them elsewhere, perform a `transferFrom`.
if (!params.useSelfBalance && state.from != msg.sender) {
_transferERC20TokensFrom(IERC20TokenV06(params.tokens[0]), msg.sender, state.from, params.sellAmount);
_transferERC20TokensFrom(IERC20Token(params.tokens[0]), msg.sender, state.from, params.sellAmount);
}
// If the input tokens are currently held by `address(this)` but
// the first hop expects them elsewhere, perform a `transfer`.
if (params.useSelfBalance && state.from != address(this)) {
_transferERC20Tokens(IERC20TokenV06(params.tokens[0]), state.from, params.sellAmount);
_transferERC20Tokens(IERC20Token(params.tokens[0]), state.from, params.sellAmount);
}
// Iterate through the calls and execute each one.
for (state.hopIndex = 0; state.hopIndex != params.calls.length; state.hopIndex++) {
@ -461,8 +461,8 @@ contract MultiplexFeature is
// The input and output tokens of the batch
// sell are the current and next tokens in
// `params.tokens`, respectively.
batchSellParams.inputToken = IERC20TokenV06(params.tokens[state.hopIndex]);
batchSellParams.outputToken = IERC20TokenV06(params.tokens[state.hopIndex + 1]);
batchSellParams.inputToken = IERC20Token(params.tokens[state.hopIndex]);
batchSellParams.outputToken = IERC20Token(params.tokens[state.hopIndex + 1]);
// The `sellAmount` for the batch sell is the
// `outputTokenAmount` from the previous hop.
batchSellParams.sellAmount = state.outputTokenAmount;

View File

@ -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/LibSafeMathV06.sol";
import "../../external/ILiquidityProviderSandbox.sol";
import "../../fixins/FixinCommon.sol";
@ -25,7 +25,7 @@ import "../../vendor/ILiquidityProvider.sol";
import "../interfaces/IMultiplexFeature.sol";
abstract contract MultiplexLiquidityProvider is FixinCommon, FixinTokenSpender {
using LibERC20TokenV06 for IERC20TokenV06;
using LibERC20TokenV06 for IERC20Token;
using LibSafeMathV06 for uint256;
// Same event fired by LiquidityProviderFeature
@ -125,8 +125,8 @@ abstract contract MultiplexLiquidityProvider is FixinCommon, FixinTokenSpender {
IMultiplexFeature.MultiHopSellParams memory params,
bytes memory wrappedCallData
) internal {
IERC20TokenV06 inputToken = IERC20TokenV06(params.tokens[state.hopIndex]);
IERC20TokenV06 outputToken = IERC20TokenV06(params.tokens[state.hopIndex + 1]);
IERC20Token inputToken = IERC20Token(params.tokens[state.hopIndex]);
IERC20Token outputToken = IERC20Token(params.tokens[state.hopIndex + 1]);
// Decode the provider address and auxiliary data.
(address provider, bytes memory auxiliaryData) = abi.decode(wrappedCallData, (address, bytes));
// Cache the recipient's balance of the output token.

View File

@ -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 "@0x/contracts-utils/contracts/src/v06/LibSafeMathV06.sol";
import "../../fixins/FixinCommon.sol";
import "../../fixins/FixinTokenSpender.sol";
@ -75,9 +75,9 @@ abstract contract MultiplexUniswapV2 is FixinCommon, FixinTokenSpender {
// so we transfer the tokens in now (either from `msg.sender`
// or using the Exchange Proxy's balance).
if (params.useSelfBalance) {
_transferERC20Tokens(IERC20TokenV06(tokens[0]), firstPairAddress, sellAmount);
_transferERC20Tokens(IERC20Token(tokens[0]), firstPairAddress, sellAmount);
} else {
_transferERC20TokensFrom(IERC20TokenV06(tokens[0]), msg.sender, firstPairAddress, sellAmount);
_transferERC20TokensFrom(IERC20Token(tokens[0]), msg.sender, firstPairAddress, sellAmount);
}
// Execute the Uniswap/Sushiswap trade.
return _sellToUniswapV2(tokens, sellAmount, isSushi, firstPairAddress, params.recipient);

View File

@ -15,7 +15,6 @@
pragma solidity ^0.6.5;
pragma experimental ABIEncoderV2;
import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol";
import "@0x/contracts-utils/contracts/src/v06/LibSafeMathV06.sol";
import "../../fixins/FixinTokenSpender.sol";
import "../interfaces/IMultiplexFeature.sol";

View File

@ -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 "@0x/contracts-utils/contracts/src/v06/errors/LibRichErrorsV06.sol";
import "../../errors/LibNativeOrdersRichErrors.sol";
import "../../storage/LibNativeOrdersStorage.sol";
@ -80,7 +80,7 @@ abstract contract NativeOrdersCancellation is INativeOrdersEvents, NativeOrdersI
/// @param makerToken The maker token.
/// @param takerToken The taker token.
/// @param minValidSalt The new minimum valid salt.
function cancelPairLimitOrders(IERC20TokenV06 makerToken, IERC20TokenV06 takerToken, uint256 minValidSalt) public {
function cancelPairLimitOrders(IERC20Token makerToken, IERC20Token takerToken, uint256 minValidSalt) public {
_cancelPairLimitOrders(msg.sender, makerToken, takerToken, minValidSalt);
}
@ -94,8 +94,8 @@ abstract contract NativeOrdersCancellation is INativeOrdersEvents, NativeOrdersI
/// @param minValidSalt The new minimum valid salt.
function cancelPairLimitOrdersWithSigner(
address maker,
IERC20TokenV06 makerToken,
IERC20TokenV06 takerToken,
IERC20Token makerToken,
IERC20Token takerToken,
uint256 minValidSalt
) public {
// verify that the signer is authorized for the maker
@ -114,8 +114,8 @@ abstract contract NativeOrdersCancellation is INativeOrdersEvents, NativeOrdersI
/// @param takerTokens The taker tokens.
/// @param minValidSalts The new minimum valid salts.
function batchCancelPairLimitOrders(
IERC20TokenV06[] memory makerTokens,
IERC20TokenV06[] memory takerTokens,
IERC20Token[] memory makerTokens,
IERC20Token[] memory takerTokens,
uint256[] memory minValidSalts
) public {
require(
@ -138,8 +138,8 @@ abstract contract NativeOrdersCancellation is INativeOrdersEvents, NativeOrdersI
/// @param minValidSalts The new minimum valid salts.
function batchCancelPairLimitOrdersWithSigner(
address maker,
IERC20TokenV06[] memory makerTokens,
IERC20TokenV06[] memory takerTokens,
IERC20Token[] memory makerTokens,
IERC20Token[] memory takerTokens,
uint256[] memory minValidSalts
) public {
require(
@ -163,7 +163,7 @@ abstract contract NativeOrdersCancellation is INativeOrdersEvents, NativeOrdersI
/// @param makerToken The maker token.
/// @param takerToken The taker token.
/// @param minValidSalt The new minimum valid salt.
function cancelPairRfqOrders(IERC20TokenV06 makerToken, IERC20TokenV06 takerToken, uint256 minValidSalt) public {
function cancelPairRfqOrders(IERC20Token makerToken, IERC20Token takerToken, uint256 minValidSalt) public {
_cancelPairRfqOrders(msg.sender, makerToken, takerToken, minValidSalt);
}
@ -177,8 +177,8 @@ abstract contract NativeOrdersCancellation is INativeOrdersEvents, NativeOrdersI
/// @param minValidSalt The new minimum valid salt.
function cancelPairRfqOrdersWithSigner(
address maker,
IERC20TokenV06 makerToken,
IERC20TokenV06 takerToken,
IERC20Token makerToken,
IERC20Token takerToken,
uint256 minValidSalt
) public {
if (!isValidOrderSigner(maker, msg.sender)) {
@ -196,8 +196,8 @@ abstract contract NativeOrdersCancellation is INativeOrdersEvents, NativeOrdersI
/// @param takerTokens The taker tokens.
/// @param minValidSalts The new minimum valid salts.
function batchCancelPairRfqOrders(
IERC20TokenV06[] memory makerTokens,
IERC20TokenV06[] memory takerTokens,
IERC20Token[] memory makerTokens,
IERC20Token[] memory takerTokens,
uint256[] memory minValidSalts
) public {
require(
@ -220,8 +220,8 @@ abstract contract NativeOrdersCancellation is INativeOrdersEvents, NativeOrdersI
/// @param minValidSalts The new minimum valid salts.
function batchCancelPairRfqOrdersWithSigner(
address maker,
IERC20TokenV06[] memory makerTokens,
IERC20TokenV06[] memory takerTokens,
IERC20Token[] memory makerTokens,
IERC20Token[] memory takerTokens,
uint256[] memory minValidSalts
) public {
require(
@ -258,8 +258,8 @@ abstract contract NativeOrdersCancellation is INativeOrdersEvents, NativeOrdersI
/// @param minValidSalt The new minimum valid salt.
function _cancelPairRfqOrders(
address maker,
IERC20TokenV06 makerToken,
IERC20TokenV06 takerToken,
IERC20Token makerToken,
IERC20Token takerToken,
uint256 minValidSalt
) private {
LibNativeOrdersStorage.Storage storage stor = LibNativeOrdersStorage.getStorage();
@ -288,8 +288,8 @@ abstract contract NativeOrdersCancellation is INativeOrdersEvents, NativeOrdersI
/// @param minValidSalt The new minimum valid salt.
function _cancelPairLimitOrders(
address maker,
IERC20TokenV06 makerToken,
IERC20TokenV06 takerToken,
IERC20Token makerToken,
IERC20Token takerToken,
uint256 minValidSalt
) private {
LibNativeOrdersStorage.Storage storage stor = LibNativeOrdersStorage.getStorage();

View File

@ -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 "@0x/contracts-utils/contracts/src/v06/LibSafeMathV06.sol";
import "@0x/contracts-utils/contracts/src/v06/LibMathV06.sol";
import "../../fixins/FixinEIP712.sol";
@ -32,7 +32,7 @@ abstract contract NativeOrdersInfo is FixinEIP712, FixinTokenSpender {
// @dev Params for `_getActualFillableTakerTokenAmount()`.
struct GetActualFillableTakerTokenAmountParams {
address maker;
IERC20TokenV06 makerToken;
IERC20Token makerToken;
uint128 orderMakerAmount;
uint128 orderTakerAmount;
LibNativeOrder.OrderInfo orderInfo;

View File

@ -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/errors/LibRichErrorsV06.sol";
import "@0x/contracts-utils/contracts/src/v06/LibSafeMathV06.sol";
import "../../fixins/FixinProtocolFees.sol";
@ -28,7 +28,7 @@ abstract contract NativeOrdersProtocolFees is FixinProtocolFees {
using LibRichErrorsV06 for bytes;
constructor(
IEtherTokenV06 weth,
IEtherToken weth,
IStaking staking,
FeeCollectorController feeCollectorController,
uint32 protocolFeeMultiplier

View File

@ -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 "@0x/contracts-utils/contracts/src/v06/errors/LibRichErrorsV06.sol";
import "@0x/contracts-utils/contracts/src/v06/LibSafeMathV06.sol";
import "@0x/contracts-utils/contracts/src/v06/LibMathV06.sol";
@ -51,9 +51,9 @@ abstract contract NativeOrdersSettlement is
// Recipient of the maker tokens.
address recipient;
// Maker token.
IERC20TokenV06 makerToken;
IERC20Token makerToken;
// Taker token.
IERC20TokenV06 takerToken;
IERC20Token takerToken;
// Maker token amount.
uint128 makerAmount;
// Taker token amount.
@ -105,7 +105,7 @@ abstract contract NativeOrdersSettlement is
constructor(
address zeroExAddress,
IEtherTokenV06 weth,
IEtherToken weth,
IStaking staking,
FeeCollectorController feeCollectorController,
uint32 protocolFeeMultiplier
@ -352,8 +352,8 @@ abstract contract NativeOrdersSettlement is
maker: params.order.maker,
payer: params.taker,
recipient: params.taker,
makerToken: IERC20TokenV06(params.order.makerToken),
takerToken: IERC20TokenV06(params.order.takerToken),
makerToken: IERC20Token(params.order.makerToken),
takerToken: IERC20Token(params.order.takerToken),
makerAmount: params.order.makerAmount,
takerAmount: params.order.takerAmount,
takerTokenFillAmount: params.takerTokenFillAmount,
@ -441,8 +441,8 @@ abstract contract NativeOrdersSettlement is
maker: params.order.maker,
payer: params.useSelfBalance ? address(this) : params.taker,
recipient: params.recipient,
makerToken: IERC20TokenV06(params.order.makerToken),
takerToken: IERC20TokenV06(params.order.takerToken),
makerToken: IERC20Token(params.order.makerToken),
takerToken: IERC20Token(params.order.takerToken),
makerAmount: params.order.makerAmount,
takerAmount: params.order.takerAmount,
takerTokenFillAmount: params.takerTokenFillAmount,

View File

@ -15,7 +15,7 @@
pragma solidity ^0.6;
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 "../../fixins/FixinERC1155Spender.sol";
import "../../migrations/LibMigrate.sol";
@ -41,7 +41,7 @@ contract ERC1155OrdersFeature is IFeature, IERC1155OrdersFeature, FixinERC1155Sp
/// @dev The magic return value indicating the success of a `onERC1155Received`.
bytes4 private constant ERC1155_RECEIVED_MAGIC_BYTES = this.onERC1155Received.selector;
constructor(address zeroExAddress, IEtherTokenV06 weth) public NFTOrders(zeroExAddress, weth) {}
constructor(address zeroExAddress, IEtherToken weth) public NFTOrders(zeroExAddress, weth) {}
/// @dev Initialize and register this feature.
/// Should be delegatecalled by `Migrate.migrate()`.

View File

@ -15,7 +15,7 @@
pragma solidity ^0.6;
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 "../../fixins/FixinERC721Spender.sol";
import "../../migrations/LibMigrate.sol";
@ -40,7 +40,7 @@ contract ERC721OrdersFeature is IFeature, IERC721OrdersFeature, FixinERC721Spend
/// @dev The magic return value indicating the success of a `onERC721Received`.
bytes4 private constant ERC721_RECEIVED_MAGIC_BYTES = this.onERC721Received.selector;
constructor(address zeroExAddress, IEtherTokenV06 weth) public NFTOrders(zeroExAddress, weth) {}
constructor(address zeroExAddress, IEtherToken weth) public NFTOrders(zeroExAddress, weth) {}
/// @dev Initialize and register this feature.
/// Should be delegatecalled by `Migrate.migrate()`.

View File

@ -15,8 +15,7 @@
pragma solidity ^0.6;
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/IEtherToken.sol";
import "@0x/contracts-utils/contracts/src/v06/LibMathV06.sol";
import "@0x/contracts-utils/contracts/src/v06/LibSafeMathV06.sol";
import "../../errors/LibNFTOrdersRichErrors.sol";
@ -36,14 +35,14 @@ abstract contract NFTOrders is FixinCommon, FixinEIP712, FixinTokenSpender {
/// @dev Native token pseudo-address.
address internal constant NATIVE_TOKEN_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
/// @dev The WETH token contract.
IEtherTokenV06 internal immutable WETH;
IEtherToken internal immutable WETH;
/// @dev The magic return value indicating the success of a `receiveZeroExFeeCallback`.
bytes4 private constant FEE_CALLBACK_MAGIC_BYTES = IFeeRecipient.receiveZeroExFeeCallback.selector;
/// @dev The magic return value indicating the success of a `zeroExTakerCallback`.
bytes4 private constant TAKER_CALLBACK_MAGIC_BYTES = ITakerCallback.zeroExTakerCallback.selector;
constructor(address zeroExAddress, IEtherTokenV06 weth) public FixinEIP712(zeroExAddress) {
constructor(address zeroExAddress, IEtherToken weth) public FixinEIP712(zeroExAddress) {
WETH = weth;
}

View File

@ -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 "../external/FeeCollector.sol";
import "../external/FeeCollectorController.sol";
import "../external/LibFeeCollector.sol";
@ -30,12 +30,12 @@ abstract contract FixinProtocolFees {
/// @dev Hash of the fee collector init code.
bytes32 private immutable FEE_COLLECTOR_INIT_CODE_HASH;
/// @dev The WETH token contract.
IEtherTokenV06 private immutable WETH;
IEtherToken private immutable WETH;
/// @dev The staking contract.
IStaking private immutable STAKING;
constructor(
IEtherTokenV06 weth,
IEtherToken weth,
IStaking staking,
FeeCollectorController feeCollectorController,
uint32 protocolFeeMultiplier

View File

@ -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 "@0x/contracts-utils/contracts/src/v06/LibSafeMathV06.sol";
/// @dev Helpers for moving tokens around.
@ -28,7 +28,7 @@ abstract contract FixinTokenSpender {
/// @param owner The owner of the tokens.
/// @param to The recipient of the tokens.
/// @param amount The amount of `token` to transfer.
function _transferERC20TokensFrom(IERC20TokenV06 token, address owner, address to, uint256 amount) internal {
function _transferERC20TokensFrom(IERC20Token token, address owner, address to, uint256 amount) internal {
require(address(token) != address(this), "FixinTokenSpender/CANNOT_INVOKE_SELF");
assembly {
@ -69,7 +69,7 @@ abstract contract FixinTokenSpender {
/// @param token The token to spend.
/// @param to The recipient of the tokens.
/// @param amount The amount of `token` to transfer.
function _transferERC20Tokens(IERC20TokenV06 token, address to, uint256 amount) internal {
function _transferERC20Tokens(IERC20Token token, address to, uint256 amount) internal {
require(address(token) != address(this), "FixinTokenSpender/CANNOT_INVOKE_SELF");
assembly {
@ -121,7 +121,7 @@ abstract contract FixinTokenSpender {
/// @param token The token to spend.
/// @param owner The owner of the tokens.
/// @return amount The amount of tokens that can be pulled.
function _getSpendableERC20BalanceOf(IERC20TokenV06 token, address owner) internal view returns (uint256) {
function _getSpendableERC20BalanceOf(IERC20Token token, address owner) internal view returns (uint256) {
return LibSafeMathV06.min256(token.allowance(owner, address(this)), token.balanceOf(owner));
}
}

View File

@ -16,14 +16,14 @@ pragma solidity ^0.6.5;
pragma experimental ABIEncoderV2;
import "@0x/contracts-utils/contracts/src/v06/errors/LibRichErrorsV06.sol";
import "@0x/contracts-erc20/contracts/src/v06/LibERC20TokenV06.sol";
import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol";
import "@0x/contracts-erc20/src/v06/LibERC20TokenV06.sol";
import "@0x/contracts-erc20/src/IERC20Token.sol";
import "@0x/contracts-utils/contracts/src/v06/LibSafeMathV06.sol";
import "../transformers/LibERC20Transformer.sol";
import "../vendor/ILiquidityProvider.sol";
contract CurveLiquidityProvider is ILiquidityProvider {
using LibERC20TokenV06 for IERC20TokenV06;
using LibERC20TokenV06 for IERC20Token;
using LibSafeMathV06 for uint256;
using LibRichErrorsV06 for bytes;
@ -48,8 +48,8 @@ contract CurveLiquidityProvider is ILiquidityProvider {
/// @param auxiliaryData Arbitrary auxiliary data supplied to the contract.
/// @return boughtAmount The amount of `outputToken` bought.
function sellTokenForToken(
IERC20TokenV06 inputToken,
IERC20TokenV06 outputToken,
IERC20Token inputToken,
IERC20Token outputToken,
address recipient,
uint256 minBuyAmount,
bytes calldata auxiliaryData
@ -79,7 +79,7 @@ contract CurveLiquidityProvider is ILiquidityProvider {
/// @param auxiliaryData Arbitrary auxiliary data supplied to the contract.
/// @return boughtAmount The amount of `outputToken` bought.
function sellEthForToken(
IERC20TokenV06 outputToken,
IERC20Token outputToken,
address recipient,
uint256 minBuyAmount,
bytes calldata auxiliaryData
@ -105,7 +105,7 @@ contract CurveLiquidityProvider is ILiquidityProvider {
/// @param auxiliaryData Arbitrary auxiliary data supplied to the contract.
/// @return boughtAmount The amount of ETH bought.
function sellTokenForEth(
IERC20TokenV06 inputToken,
IERC20Token inputToken,
address payable recipient,
uint256 minBuyAmount,
bytes calldata auxiliaryData
@ -126,8 +126,8 @@ contract CurveLiquidityProvider is ILiquidityProvider {
/// @dev Quotes the amount of `outputToken` that would be obtained by
/// selling `sellAmount` of `inputToken`.
function getSellQuote(
IERC20TokenV06 /* inputToken */,
IERC20TokenV06 /* outputToken */,
IERC20Token /* inputToken */,
IERC20Token /* outputToken */,
uint256 /* sellAmount */
) external view override returns (uint256) {
revert("CurveLiquidityProvider/NOT_IMPLEMENTED");
@ -136,8 +136,8 @@ contract CurveLiquidityProvider is ILiquidityProvider {
/// @dev Perform the swap against the curve pool. Handles any combination of
/// tokens
function _executeSwap(
IERC20TokenV06 inputToken,
IERC20TokenV06 outputToken,
IERC20Token inputToken,
IERC20Token outputToken,
uint256 minBuyAmount,
CurveData memory data,
address recipient // Only used to log event.

View File

@ -16,22 +16,22 @@ pragma solidity ^0.6.5;
pragma experimental ABIEncoderV2;
import "@0x/contracts-utils/contracts/src/v06/errors/LibRichErrorsV06.sol";
import "@0x/contracts-erc20/contracts/src/v06/LibERC20TokenV06.sol";
import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol";
import "@0x/contracts-erc20/contracts/src/v06/IEtherTokenV06.sol";
import "@0x/contracts-erc20/src/v06/LibERC20TokenV06.sol";
import "@0x/contracts-erc20/src/IERC20Token.sol";
import "@0x/contracts-erc20/src/IEtherToken.sol";
import "@0x/contracts-utils/contracts/src/v06/LibSafeMathV06.sol";
import "../transformers/LibERC20Transformer.sol";
import "../vendor/ILiquidityProvider.sol";
import "../vendor/IMooniswapPool.sol";
contract MooniswapLiquidityProvider is ILiquidityProvider {
using LibERC20TokenV06 for IERC20TokenV06;
using LibERC20TokenV06 for IERC20Token;
using LibSafeMathV06 for uint256;
using LibRichErrorsV06 for bytes;
IEtherTokenV06 private immutable WETH;
IEtherToken private immutable WETH;
constructor(IEtherTokenV06 weth) public {
constructor(IEtherToken weth) public {
WETH = weth;
}
@ -49,8 +49,8 @@ contract MooniswapLiquidityProvider is ILiquidityProvider {
/// @param auxiliaryData Arbitrary auxiliary data supplied to the contract.
/// @return boughtAmount The amount of `outputToken` bought.
function sellTokenForToken(
IERC20TokenV06 inputToken,
IERC20TokenV06 outputToken,
IERC20Token inputToken,
IERC20Token outputToken,
address recipient,
uint256 minBuyAmount,
bytes calldata auxiliaryData
@ -80,7 +80,7 @@ contract MooniswapLiquidityProvider is ILiquidityProvider {
/// @param auxiliaryData Arbitrary auxiliary data supplied to the contract.
/// @return boughtAmount The amount of `outputToken` bought.
function sellEthForToken(
IERC20TokenV06 outputToken,
IERC20Token outputToken,
address recipient,
uint256 minBuyAmount,
bytes calldata auxiliaryData
@ -104,7 +104,7 @@ contract MooniswapLiquidityProvider is ILiquidityProvider {
/// @param auxiliaryData Arbitrary auxiliary data supplied to the contract.
/// @return boughtAmount The amount of ETH bought.
function sellTokenForEth(
IERC20TokenV06 inputToken,
IERC20Token inputToken,
address payable recipient,
uint256 minBuyAmount,
bytes calldata auxiliaryData
@ -123,8 +123,8 @@ contract MooniswapLiquidityProvider is ILiquidityProvider {
/// @dev Quotes the amount of `outputToken` that would be obtained by
/// selling `sellAmount` of `inputToken`.
function getSellQuote(
IERC20TokenV06 /* inputToken */,
IERC20TokenV06 /* outputToken */,
IERC20Token /* inputToken */,
IERC20Token /* outputToken */,
uint256 /* sellAmount */
) external view override returns (uint256) {
revert("MooniswapLiquidityProvider/NOT_IMPLEMENTED");
@ -133,8 +133,8 @@ contract MooniswapLiquidityProvider is ILiquidityProvider {
/// @dev Perform the swap against the curve pool. Handles any combination of
/// tokens
function _executeSwap(
IERC20TokenV06 inputToken,
IERC20TokenV06 outputToken,
IERC20Token inputToken,
IERC20Token outputToken,
uint256 minBuyAmount,
IMooniswapPool pool,
address recipient // Only used to log event
@ -157,8 +157,8 @@ contract MooniswapLiquidityProvider is ILiquidityProvider {
}
boughtAmount = pool.swap{value: ethValue}(
_isTokenEthLike(inputToken) ? IERC20TokenV06(0) : inputToken,
_isTokenEthLike(outputToken) ? IERC20TokenV06(0) : outputToken,
_isTokenEthLike(inputToken) ? IERC20Token(0) : inputToken,
_isTokenEthLike(outputToken) ? IERC20Token(0) : outputToken,
sellAmount,
minBuyAmount,
address(0)
@ -181,7 +181,7 @@ contract MooniswapLiquidityProvider is ILiquidityProvider {
}
/// @dev Check if a token is ETH or WETH.
function _isTokenEthLike(IERC20TokenV06 token) private view returns (bool isEthOrWeth) {
function _isTokenEthLike(IERC20Token token) private view returns (bool isEthOrWeth) {
return LibERC20Transformer.isTokenETH(token) || token == WETH;
}
}

View File

@ -17,8 +17,8 @@ pragma experimental ABIEncoderV2;
import "@0x/contracts-utils/contracts/src/v06/errors/LibRichErrorsV06.sol";
import "@0x/contracts-utils/contracts/src/v06/LibSafeMathV06.sol";
import "@0x/contracts-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 "../errors/LibTransformERC20RichErrors.sol";
import "./Transformer.sol";
import "./LibERC20Transformer.sol";
@ -27,12 +27,12 @@ import "./LibERC20Transformer.sol";
contract AffiliateFeeTransformer is Transformer {
using LibRichErrorsV06 for bytes;
using LibSafeMathV06 for uint256;
using LibERC20Transformer for IERC20TokenV06;
using LibERC20Transformer for IERC20Token;
/// @dev Information for a single fee.
struct TokenFee {
// The token to transfer to `recipient`.
IERC20TokenV06 token;
IERC20Token token;
// Amount of each `token` to transfer to `recipient`.
// If `amount == uint256(-1)`, the entire balance of `token` will be
// transferred.

View File

@ -16,8 +16,8 @@ pragma solidity ^0.6.5;
pragma experimental ABIEncoderV2;
import "@0x/contracts-utils/contracts/src/v06/errors/LibRichErrorsV06.sol";
import "@0x/contracts-erc20/contracts/src/v06/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/LibSafeMathV06.sol";
import "@0x/contracts-utils/contracts/src/v06/LibMathV06.sol";
import "../errors/LibTransformERC20RichErrors.sol";
@ -31,8 +31,8 @@ import "../IZeroEx.sol";
/// @dev A transformer that fills an ERC20 market sell/buy quote.
/// This transformer shortcuts bridge orders and fills them directly
contract FillQuoteTransformer is Transformer {
using LibERC20TokenV06 for IERC20TokenV06;
using LibERC20Transformer for IERC20TokenV06;
using LibERC20TokenV06 for IERC20Token;
using LibERC20Transformer for IERC20Token;
using LibSafeMathV06 for uint256;
using LibSafeMathV06 for uint128;
using LibRichErrorsV06 for bytes;
@ -77,10 +77,10 @@ contract FillQuoteTransformer is Transformer {
Side side;
// The token being sold.
// This should be an actual token, not the ETH pseudo-token.
IERC20TokenV06 sellToken;
IERC20Token sellToken;
// The token being bought.
// This should be an actual token, not the ETH pseudo-token.
IERC20TokenV06 buyToken;
IERC20Token buyToken;
// External liquidity bridge orders. Sorted by fill sequence.
IBridgeAdapter.BridgeOrder[] bridgeOrders;
// Native limit orders. Sorted by fill sequence.

View File

@ -15,8 +15,6 @@
pragma solidity ^0.6.5;
pragma experimental ABIEncoderV2;
import "@0x/contracts-erc20/contracts/src/v06/IERC20TokenV06.sol";
/// @dev A transformation callback used in `TransformERC20.transformERC20()`.
interface IERC20Transformer {
/// @dev Context information to pass into `transform()` by `TransformERC20.transformERC20()`.

View File

@ -15,16 +15,16 @@
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";
library LibERC20Transformer {
using LibERC20TokenV06 for IERC20TokenV06;
using LibERC20TokenV06 for IERC20Token;
/// @dev ETH pseudo-token address.
address internal constant ETH_TOKEN_ADDRESS = 0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE;
/// @dev ETH pseudo-token.
IERC20TokenV06 internal constant ETH_TOKEN = IERC20TokenV06(ETH_TOKEN_ADDRESS);
IERC20Token internal constant ETH_TOKEN = IERC20Token(ETH_TOKEN_ADDRESS);
/// @dev Return value indicating success in `IERC20Transformer.transform()`.
/// This is just `keccak256('TRANSFORMER_SUCCESS')`.
bytes4 internal constant TRANSFORMER_SUCCESS = 0x13c9929e;
@ -35,7 +35,7 @@ library LibERC20Transformer {
/// @param token An ERC20 or the ETH pseudo-token address (`ETH_TOKEN_ADDRESS`).
/// @param to The recipient.
/// @param amount The transfer amount.
function transformerTransfer(IERC20TokenV06 token, address payable to, uint256 amount) internal {
function transformerTransfer(IERC20Token token, address payable to, uint256 amount) internal {
if (isTokenETH(token)) {
to.transfer(amount);
} else {
@ -48,7 +48,7 @@ library LibERC20Transformer {
/// @param token An ERC20 or the ETH pseudo-token address (`ETH_TOKEN_ADDRESS`).
/// @param to The recipient.
/// @param amount The transfer amount.
function unsafeTransformerTransfer(IERC20TokenV06 token, address payable to, uint256 amount) internal {
function unsafeTransformerTransfer(IERC20Token token, address payable to, uint256 amount) internal {
if (isTokenETH(token)) {
(bool sent, ) = to.call{value: amount}("");
require(sent, "LibERC20Transformer/FAILED_TO_SEND_ETHER");
@ -60,7 +60,7 @@ library LibERC20Transformer {
/// @dev Check if a token is the ETH pseudo-token.
/// @param token The token to check.
/// @return isETH `true` if the token is the ETH pseudo-token.
function isTokenETH(IERC20TokenV06 token) internal pure returns (bool isETH) {
function isTokenETH(IERC20Token token) internal pure returns (bool isETH) {
return address(token) == ETH_TOKEN_ADDRESS;
}
@ -68,7 +68,7 @@ library LibERC20Transformer {
/// @param token An ERC20 or the ETH pseudo-token address (`ETH_TOKEN_ADDRESS`).
/// @param owner Holder of the tokens.
/// @return tokenBalance The balance of `owner`.
function getTokenBalanceOf(IERC20TokenV06 token, address owner) internal view returns (uint256 tokenBalance) {
function getTokenBalanceOf(IERC20Token token, address owner) internal view returns (uint256 tokenBalance) {
if (isTokenETH(token)) {
return owner.balance;
}

View File

@ -17,8 +17,8 @@ pragma experimental ABIEncoderV2;
import "@0x/contracts-utils/contracts/src/v06/errors/LibRichErrorsV06.sol";
import "@0x/contracts-utils/contracts/src/v06/LibSafeMathV06.sol";
import "@0x/contracts-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 "../errors/LibTransformERC20RichErrors.sol";
import "./Transformer.sol";
import "./LibERC20Transformer.sol";
@ -27,12 +27,12 @@ import "./LibERC20Transformer.sol";
contract PayTakerTransformer is Transformer {
using LibRichErrorsV06 for bytes;
using LibSafeMathV06 for uint256;
using LibERC20Transformer for IERC20TokenV06;
using LibERC20Transformer for IERC20Token;
/// @dev Transform data to ABI-encode and pass into `transform()`.
struct TransformData {
// The tokens to transfer to the taker.
IERC20TokenV06[] tokens;
IERC20Token[] tokens;
// Amount of each token in `tokens` to transfer to the taker.
// `uint(-1)` will transfer the entire balance.
uint256[] amounts;

View File

@ -17,8 +17,8 @@ pragma experimental ABIEncoderV2;
import "@0x/contracts-utils/contracts/src/v06/errors/LibRichErrorsV06.sol";
import "@0x/contracts-utils/contracts/src/v06/LibSafeMathV06.sol";
import "@0x/contracts-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 "../errors/LibTransformERC20RichErrors.sol";
import "./Transformer.sol";
import "./LibERC20Transformer.sol";
@ -27,12 +27,12 @@ import "./LibERC20Transformer.sol";
contract PositiveSlippageFeeTransformer is Transformer {
using LibRichErrorsV06 for bytes;
using LibSafeMathV06 for uint256;
using LibERC20Transformer for IERC20TokenV06;
using LibERC20Transformer for IERC20Token;
/// @dev Information for a single fee.
struct TokenFee {
// The token to transfer to `recipient`.
IERC20TokenV06 token;
IERC20Token token;
// Amount of each `token` to transfer to `recipient`.
uint256 bestCaseAmount;
// Recipient of `token`.

View File

@ -17,7 +17,7 @@ pragma experimental ABIEncoderV2;
import "@0x/contracts-utils/contracts/src/v06/errors/LibRichErrorsV06.sol";
import "@0x/contracts-utils/contracts/src/v06/LibSafeMathV06.sol";
import "@0x/contracts-erc20/contracts/src/v06/IEtherTokenV06.sol";
import "@0x/contracts-erc20/src/IEtherToken.sol";
import "../errors/LibTransformERC20RichErrors.sol";
import "./Transformer.sol";
import "./LibERC20Transformer.sol";
@ -26,25 +26,25 @@ import "./LibERC20Transformer.sol";
contract WethTransformer is Transformer {
using LibRichErrorsV06 for bytes;
using LibSafeMathV06 for uint256;
using LibERC20Transformer for IERC20TokenV06;
using LibERC20Transformer for IERC20Token;
/// @dev Transform data to ABI-encode and pass into `transform()`.
struct TransformData {
// The token to wrap/unwrap. Must be either ETH or WETH.
IERC20TokenV06 token;
IERC20Token token;
// Amount of `token` to wrap or unwrap.
// `uint(-1)` will unwrap the entire balance.
uint256 amount;
}
/// @dev The WETH contract address.
IEtherTokenV06 public immutable weth;
IEtherToken public immutable weth;
/// @dev Maximum uint256 value.
uint256 private constant MAX_UINT256 = uint256(-1);
/// @dev Construct the transformer and store the WETH address in an immutable.
/// @param weth_ The weth token.
constructor(IEtherTokenV06 weth_) public Transformer() {
constructor(IEtherToken weth_) public Transformer() {
weth = weth_;
}

View File

@ -32,15 +32,15 @@ abstract contract AbstractBridgeAdapter is IBridgeAdapter {
function isSupportedSource(bytes32 source) external override returns (bool isSupported) {
BridgeOrder memory placeholderOrder;
placeholderOrder.source = source;
IERC20TokenV06 placeholderToken = IERC20TokenV06(address(0));
IERC20Token placeholderToken = IERC20Token(address(0));
(, isSupported) = _trade(placeholderOrder, placeholderToken, placeholderToken, 0, true);
}
function trade(
BridgeOrder memory order,
IERC20TokenV06 sellToken,
IERC20TokenV06 buyToken,
IERC20Token sellToken,
IERC20Token buyToken,
uint256 sellAmount
) public override returns (uint256 boughtAmount) {
(boughtAmount, ) = _trade(order, sellToken, buyToken, sellAmount, false);
@ -48,8 +48,8 @@ abstract contract AbstractBridgeAdapter is IBridgeAdapter {
function _trade(
BridgeOrder memory order,
IERC20TokenV06 sellToken,
IERC20TokenV06 buyToken,
IERC20Token sellToken,
IERC20Token buyToken,
uint256 sellAmount,
bool dryRun
) internal virtual returns (uint256 boughtAmount, bool supportedSource);

View File

@ -45,12 +45,12 @@ contract ArbitrumBridgeAdapter is
MixinWOOFi,
MixinZeroExBridge
{
constructor(IEtherTokenV06 weth) public MixinCurve(weth) MixinAaveV3(true) {}
constructor(IEtherToken weth) public MixinCurve(weth) MixinAaveV3(true) {}
function _trade(
BridgeOrder memory order,
IERC20TokenV06 sellToken,
IERC20TokenV06 buyToken,
IERC20Token sellToken,
IERC20Token buyToken,
uint256 sellAmount,
bool dryRun
) internal override returns (uint256 boughtAmount, bool supportedSource) {

View File

@ -43,12 +43,12 @@ contract AvalancheBridgeAdapter is
MixinWOOFi,
MixinZeroExBridge
{
constructor(IEtherTokenV06 weth) public MixinCurve(weth) MixinAaveV3(false) {}
constructor(IEtherToken weth) public MixinCurve(weth) MixinAaveV3(false) {}
function _trade(
BridgeOrder memory order,
IERC20TokenV06 sellToken,
IERC20TokenV06 buyToken,
IERC20Token sellToken,
IERC20Token buyToken,
uint256 sellAmount,
bool dryRun
) internal override returns (uint256 boughtAmount, bool supportedSource) {

Some files were not shown because too many files have changed in this diff Show More